mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-09-18 23:09:29 +02:00
Merge branches 'clk-pile' and 'clk-microchip' into clk-next
* clk-pile: (111 commits) clk: microchip: mpfs: fix regmap_update_bits() mask/val order clk: visconti: Make sure clk_init_data is fully initialized clk: ti: Make sure clk_init_data is fully initialized MAINTAINERS: Add Brian Masney and Jerome Brunet as co-maintainers for clk subsystem Drop Michael Turquette's clk maintainer entry clk: ti: composite: resolve parent clocks by DT index, not by name clk: ti: mux: resolve parent clocks by DT index, not by name clk: devres: fix cleanup in devm_clk_get_optional_enabled_with_rate() dt-bindings: clock: ti,keystone-gate: Convert to DT schema dt-bindings: clock: ti: Convert APLL clock to DT schema clk: zynq: pll: Fix kernel-doc after determine_rate() conversion dt-bindings: clock: ti,clockdomain: Convert to DT schema dt-bindings: clock: Correct white-space style clk: tegra: set up proper EMC clock implementation for Tegra114 clk: clocking-wizard: remove 20kHz restriction clk: clocking-wizard: optimize clock search clk: clocking-wizard: fix clock difference detection clk: mediatek: mt8135: Fix inverted gate control for devapc_ck clk: clocking-wizard: Program PLL CP/RES and lock parameters on reconfig clk: tegra: support 48MHz clock for pll_p_out1 ... * clk-microchip: clk: at91: Read "reg" with helper
This commit is contained in:
@@ -4085,6 +4085,10 @@ S: 4226 Landgreen Street
|
||||
S: Rockville, Maryland 20853
|
||||
S: USA
|
||||
|
||||
N: Michael Turquette
|
||||
E: mturquette@baylibre.com
|
||||
D: common clk maintenance
|
||||
|
||||
N: Stephen Tweedie
|
||||
E: sct@redhat.com
|
||||
P: 1024/E7A417AD E2 FE A4 20 34 EC ED FC 7D 7E 67 8D E0 31 D1 69
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/clock/eswin,eic7700-hspcrg.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: ESWIN EIC7700 HSP Clock and Reset Generator
|
||||
|
||||
maintainers:
|
||||
- Xuyang Dong <dongxuyang@eswincomputing.com>
|
||||
|
||||
description:
|
||||
Clock and reset generator for the ESWIN EIC7700 HSP (high-speed peripherals).
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: eswin,eic7700-hspcrg
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: HSP configuration top clock
|
||||
- description: MMC top clock
|
||||
- description: SATA top clock
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: cfg
|
||||
- const: mmc
|
||||
- const: sata
|
||||
|
||||
'#clock-cells':
|
||||
const: 1
|
||||
description:
|
||||
See <dt-bindings/clock/eswin,eic7700-hspcrg.h> for valid indices.
|
||||
|
||||
'#reset-cells':
|
||||
const: 1
|
||||
description:
|
||||
See <dt-bindings/reset/eswin,eic7700-hspcrg.h> for valid indices.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- clock-names
|
||||
- '#clock-cells'
|
||||
- '#reset-cells'
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
clock-controller@50440000 {
|
||||
compatible = "eswin,eic7700-hspcrg";
|
||||
reg = <0x50440000 0x2000>;
|
||||
clocks = <&clock 171>, <&clock 254>, <&clock 187>;
|
||||
clock-names = "cfg", "mmc", "sata";
|
||||
#clock-cells = <1>;
|
||||
#reset-cells = <1>;
|
||||
};
|
||||
@@ -1,27 +0,0 @@
|
||||
Binding for Keystone gate control driver which uses PSC controller IP.
|
||||
|
||||
This binding uses the common clock binding[1].
|
||||
|
||||
[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
|
||||
|
||||
Required properties:
|
||||
- compatible : shall be "ti,keystone,psc-clock".
|
||||
- #clock-cells : from common clock binding; shall be set to 0.
|
||||
- clocks : parent clock phandle
|
||||
- reg : psc control and domain address address space
|
||||
- reg-names : psc control and domain registers
|
||||
- domain-id : psc domain id needed to check the transition state register
|
||||
|
||||
Optional properties:
|
||||
- clock-output-names : From common clock binding to override the
|
||||
default output clock name
|
||||
Example:
|
||||
clkusb: clkusb {
|
||||
#clock-cells = <0>;
|
||||
compatible = "ti,keystone,psc-clock";
|
||||
clocks = <&chipclk16>;
|
||||
clock-output-names = "usb";
|
||||
reg = <0x02350008 0xb00>, <0x02350000 0x400>;
|
||||
reg-names = "control", "domain";
|
||||
domain-id = <0>;
|
||||
};
|
||||
@@ -0,0 +1,70 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
|
||||
$id: http://devicetree.org/schemas/clock/mediatek,mt8173-mfgtop.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: MediaTek MT8173 MFG TOP controller
|
||||
|
||||
maintainers:
|
||||
- AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
|
||||
description:
|
||||
The MFG TOP glue layer controls various signals going to the MFG (GPU)
|
||||
block on the MT8173.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: mediatek,mt8173-mfgtop
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 4
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: sys
|
||||
- const: mem
|
||||
- const: core
|
||||
- const: clk26m
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
'#clock-cells':
|
||||
const: 1
|
||||
|
||||
'#power-domain-cells':
|
||||
const: 0
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- clock-names
|
||||
- power-domains
|
||||
- '#clock-cells'
|
||||
- '#power-domain-cells'
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/mt8173-clk.h>
|
||||
#include <dt-bindings/power/mt8173-power.h>
|
||||
|
||||
clock-controller@13fff000 {
|
||||
compatible = "mediatek,mt8173-mfgtop";
|
||||
reg = <0x13fff000 0x1000>;
|
||||
clocks = <&topckgen CLK_TOP_AXI_MFG_IN_SEL>,
|
||||
<&topckgen CLK_TOP_MEM_MFG_IN_SEL>,
|
||||
<&topckgen CLK_TOP_MFG_SEL>,
|
||||
<&clk26m>;
|
||||
clock-names = "sys", "mem", "core", "clk26m";
|
||||
power-domains = <&spm MT8173_POWER_DOMAIN_MFG>;
|
||||
#clock-cells = <1>;
|
||||
#power-domain-cells = <0>;
|
||||
};
|
||||
@@ -65,7 +65,7 @@ examples:
|
||||
|
||||
- |
|
||||
pericfg@10003000 {
|
||||
compatible = "mediatek,mt7623-pericfg", "mediatek,mt2701-pericfg", "syscon";
|
||||
compatible = "mediatek,mt7623-pericfg", "mediatek,mt2701-pericfg", "syscon";
|
||||
reg = <0x10003000 0x1000>;
|
||||
#clock-cells = <1>;
|
||||
#reset-cells = <1>;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
$id: http://devicetree.org/schemas/clock/silabs,si544.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Silicon Labs SI514/SI544 clock generator
|
||||
title: Silicon Labs SI514/SI544/SI549 clock generator
|
||||
|
||||
maintainers:
|
||||
- Mike Looijmans <mike.looijmans@topic.nl>
|
||||
@@ -13,8 +13,9 @@ description: >
|
||||
Silicon Labs 514/544 programmable I2C clock generator. Details about the device
|
||||
can be found in the datasheet:
|
||||
|
||||
https://www.silabs.com/Support%20Documents/TechnicalDocs/si514.pdf
|
||||
https://www.silabs.com/documents/public/data-sheets/si544-datasheet.pdf
|
||||
https://www.skyworksinc.com/-/media/Skyworks/SL/documents/public/data-sheets/Si514.pdf
|
||||
https://www.skyworksinc.com/-/media/Skyworks/SL/documents/public/data-sheets/si544-datasheet.pdf
|
||||
https://www.skyworksinc.com/-/media/Skyworks/SL/documents/public/data-sheets/si549-datasheet.pdf
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
@@ -23,6 +24,9 @@ properties:
|
||||
- silabs,si544a
|
||||
- silabs,si544b
|
||||
- silabs,si544c
|
||||
- silabs,si549a
|
||||
- silabs,si549b
|
||||
- silabs,si549c
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
@@ -125,75 +125,75 @@ examples:
|
||||
reg = <0x44200000 0x10000>;
|
||||
#clock-cells = <1>;
|
||||
#reset-cells = <1>;
|
||||
clocks = <&scmi_clk CK_SCMI_HSE>,
|
||||
<&scmi_clk CK_SCMI_HSI>,
|
||||
<&scmi_clk CK_SCMI_MSI>,
|
||||
<&scmi_clk CK_SCMI_LSE>,
|
||||
<&scmi_clk CK_SCMI_LSI>,
|
||||
<&scmi_clk CK_SCMI_HSE_DIV2>,
|
||||
<&scmi_clk CK_SCMI_ICN_HS_MCU>,
|
||||
<&scmi_clk CK_SCMI_ICN_LS_MCU>,
|
||||
<&scmi_clk CK_SCMI_ICN_SDMMC>,
|
||||
<&scmi_clk CK_SCMI_ICN_DDR>,
|
||||
<&scmi_clk CK_SCMI_ICN_DISPLAY>,
|
||||
<&scmi_clk CK_SCMI_ICN_HSL>,
|
||||
<&scmi_clk CK_SCMI_ICN_NIC>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_07>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_08>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_09>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_10>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_11>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_12>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_13>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_14>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_16>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_17>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_18>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_19>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_20>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_21>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_22>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_23>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_24>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_25>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_26>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_27>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_29>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_30>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_31>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_33>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_36>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_37>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_38>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_39>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_40>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_41>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_42>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_43>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_44>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_45>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_46>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_47>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_48>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_50>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_51>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_52>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_53>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_54>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_55>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_56>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_57>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_58>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_61>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_62>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_63>,
|
||||
<&scmi_clk CK_SCMI_ICN_APB1>,
|
||||
<&scmi_clk CK_SCMI_ICN_APB2>,
|
||||
<&scmi_clk CK_SCMI_ICN_APB3>,
|
||||
<&scmi_clk CK_SCMI_ICN_APB4>,
|
||||
<&scmi_clk CK_SCMI_ICN_APB5>,
|
||||
<&scmi_clk CK_SCMI_ICN_APBDBG>,
|
||||
<&scmi_clk CK_SCMI_TIMG1>,
|
||||
<&scmi_clk CK_SCMI_TIMG2>;
|
||||
clocks = <&scmi_clk CK_SCMI_HSE>,
|
||||
<&scmi_clk CK_SCMI_HSI>,
|
||||
<&scmi_clk CK_SCMI_MSI>,
|
||||
<&scmi_clk CK_SCMI_LSE>,
|
||||
<&scmi_clk CK_SCMI_LSI>,
|
||||
<&scmi_clk CK_SCMI_HSE_DIV2>,
|
||||
<&scmi_clk CK_SCMI_ICN_HS_MCU>,
|
||||
<&scmi_clk CK_SCMI_ICN_LS_MCU>,
|
||||
<&scmi_clk CK_SCMI_ICN_SDMMC>,
|
||||
<&scmi_clk CK_SCMI_ICN_DDR>,
|
||||
<&scmi_clk CK_SCMI_ICN_DISPLAY>,
|
||||
<&scmi_clk CK_SCMI_ICN_HSL>,
|
||||
<&scmi_clk CK_SCMI_ICN_NIC>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_07>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_08>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_09>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_10>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_11>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_12>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_13>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_14>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_16>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_17>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_18>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_19>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_20>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_21>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_22>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_23>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_24>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_25>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_26>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_27>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_29>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_30>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_31>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_33>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_36>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_37>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_38>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_39>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_40>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_41>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_42>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_43>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_44>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_45>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_46>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_47>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_48>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_50>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_51>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_52>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_53>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_54>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_55>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_56>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_57>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_58>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_61>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_62>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_63>,
|
||||
<&scmi_clk CK_SCMI_ICN_APB1>,
|
||||
<&scmi_clk CK_SCMI_ICN_APB2>,
|
||||
<&scmi_clk CK_SCMI_ICN_APB3>,
|
||||
<&scmi_clk CK_SCMI_ICN_APB4>,
|
||||
<&scmi_clk CK_SCMI_ICN_APB5>,
|
||||
<&scmi_clk CK_SCMI_ICN_APBDBG>,
|
||||
<&scmi_clk CK_SCMI_TIMG1>,
|
||||
<&scmi_clk CK_SCMI_TIMG2>;
|
||||
};
|
||||
...
|
||||
|
||||
@@ -135,85 +135,85 @@ examples:
|
||||
reg = <0x44200000 0x10000>;
|
||||
#clock-cells = <1>;
|
||||
#reset-cells = <1>;
|
||||
clocks = <&scmi_clk CK_SCMI_HSE>,
|
||||
<&scmi_clk CK_SCMI_HSI>,
|
||||
<&scmi_clk CK_SCMI_MSI>,
|
||||
<&scmi_clk CK_SCMI_LSE>,
|
||||
<&scmi_clk CK_SCMI_LSI>,
|
||||
<&scmi_clk CK_SCMI_HSE_DIV2>,
|
||||
<&scmi_clk CK_SCMI_ICN_HS_MCU>,
|
||||
<&scmi_clk CK_SCMI_ICN_LS_MCU>,
|
||||
<&scmi_clk CK_SCMI_ICN_SDMMC>,
|
||||
<&scmi_clk CK_SCMI_ICN_DDR>,
|
||||
<&scmi_clk CK_SCMI_ICN_DISPLAY>,
|
||||
<&scmi_clk CK_SCMI_ICN_HSL>,
|
||||
<&scmi_clk CK_SCMI_ICN_NIC>,
|
||||
<&scmi_clk CK_SCMI_ICN_VID>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_07>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_08>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_09>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_10>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_11>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_12>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_13>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_14>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_15>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_16>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_17>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_18>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_19>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_20>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_21>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_22>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_23>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_24>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_25>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_26>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_27>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_28>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_29>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_30>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_31>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_32>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_33>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_34>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_35>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_36>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_37>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_38>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_39>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_40>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_41>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_42>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_43>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_44>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_45>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_46>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_47>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_48>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_49>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_50>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_51>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_52>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_53>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_54>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_55>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_56>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_57>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_58>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_59>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_60>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_61>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_62>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_63>,
|
||||
<&scmi_clk CK_SCMI_ICN_APB1>,
|
||||
<&scmi_clk CK_SCMI_ICN_APB2>,
|
||||
<&scmi_clk CK_SCMI_ICN_APB3>,
|
||||
<&scmi_clk CK_SCMI_ICN_APB4>,
|
||||
<&scmi_clk CK_SCMI_ICN_APBDBG>,
|
||||
<&scmi_clk CK_SCMI_TIMG1>,
|
||||
<&scmi_clk CK_SCMI_TIMG2>,
|
||||
<&scmi_clk CK_SCMI_PLL3>,
|
||||
<&clk_dsi_txbyte>;
|
||||
clocks = <&scmi_clk CK_SCMI_HSE>,
|
||||
<&scmi_clk CK_SCMI_HSI>,
|
||||
<&scmi_clk CK_SCMI_MSI>,
|
||||
<&scmi_clk CK_SCMI_LSE>,
|
||||
<&scmi_clk CK_SCMI_LSI>,
|
||||
<&scmi_clk CK_SCMI_HSE_DIV2>,
|
||||
<&scmi_clk CK_SCMI_ICN_HS_MCU>,
|
||||
<&scmi_clk CK_SCMI_ICN_LS_MCU>,
|
||||
<&scmi_clk CK_SCMI_ICN_SDMMC>,
|
||||
<&scmi_clk CK_SCMI_ICN_DDR>,
|
||||
<&scmi_clk CK_SCMI_ICN_DISPLAY>,
|
||||
<&scmi_clk CK_SCMI_ICN_HSL>,
|
||||
<&scmi_clk CK_SCMI_ICN_NIC>,
|
||||
<&scmi_clk CK_SCMI_ICN_VID>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_07>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_08>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_09>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_10>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_11>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_12>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_13>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_14>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_15>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_16>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_17>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_18>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_19>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_20>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_21>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_22>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_23>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_24>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_25>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_26>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_27>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_28>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_29>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_30>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_31>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_32>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_33>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_34>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_35>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_36>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_37>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_38>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_39>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_40>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_41>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_42>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_43>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_44>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_45>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_46>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_47>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_48>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_49>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_50>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_51>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_52>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_53>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_54>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_55>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_56>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_57>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_58>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_59>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_60>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_61>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_62>,
|
||||
<&scmi_clk CK_SCMI_FLEXGEN_63>,
|
||||
<&scmi_clk CK_SCMI_ICN_APB1>,
|
||||
<&scmi_clk CK_SCMI_ICN_APB2>,
|
||||
<&scmi_clk CK_SCMI_ICN_APB3>,
|
||||
<&scmi_clk CK_SCMI_ICN_APB4>,
|
||||
<&scmi_clk CK_SCMI_ICN_APBDBG>,
|
||||
<&scmi_clk CK_SCMI_TIMG1>,
|
||||
<&scmi_clk CK_SCMI_TIMG2>,
|
||||
<&scmi_clk CK_SCMI_PLL3>,
|
||||
<&clk_dsi_txbyte>;
|
||||
};
|
||||
...
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/clock/ti,keystone,psc-clock.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: TI Keystone PSC clock
|
||||
|
||||
maintainers:
|
||||
- Santosh Shilimkar <santosh.shilimkar@ti.com>
|
||||
- Murali Karicheri <m-karicheri2@ti.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: ti,keystone,psc-clock
|
||||
|
||||
reg:
|
||||
items:
|
||||
- description: PSC control
|
||||
- description: Domain
|
||||
|
||||
reg-names:
|
||||
items:
|
||||
- const: control
|
||||
- const: domain
|
||||
|
||||
domain-id:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description: PSC domain id needed to check the transition state register
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
clock-output-names:
|
||||
maxItems: 1
|
||||
|
||||
"#clock-cells":
|
||||
const: 0
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- reg-names
|
||||
- domain-id
|
||||
- clocks
|
||||
- "#clock-cells"
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
clkusb@2350008 {
|
||||
compatible = "ti,keystone,psc-clock";
|
||||
reg = <0x02350008 0xb00>, <0x02350000 0x400>;
|
||||
reg-names = "control", "domain";
|
||||
domain-id = <0>;
|
||||
clocks = <&chipclk16>;
|
||||
clock-output-names = "usb";
|
||||
#clock-cells = <0>;
|
||||
};
|
||||
@@ -1,43 +0,0 @@
|
||||
Binding for Texas Instruments APLL clock.
|
||||
|
||||
This binding uses the common clock binding[1]. It assumes a
|
||||
register-mapped APLL with usually two selectable input clocks
|
||||
(reference clock and bypass clock), with analog phase locked
|
||||
loop logic for multiplying the input clock to a desired output
|
||||
clock. This clock also typically supports different operation
|
||||
modes (locked, low power stop etc.) APLL mostly behaves like
|
||||
a subtype of a DPLL [2], although a simplified one at that.
|
||||
|
||||
[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
|
||||
[2] Documentation/devicetree/bindings/clock/ti/dpll.txt
|
||||
|
||||
Required properties:
|
||||
- compatible : shall be "ti,dra7-apll-clock" or "ti,omap2-apll-clock"
|
||||
- #clock-cells : from common clock binding; shall be set to 0.
|
||||
- clocks : link phandles of parent clocks (clk-ref and clk-bypass)
|
||||
- reg : address and length of the register set for controlling the APLL.
|
||||
It contains the information of registers in the following order:
|
||||
"control" - contains the control register offset
|
||||
"idlest" - contains the idlest register offset
|
||||
"autoidle" - contains the autoidle register offset (OMAP2 only)
|
||||
- ti,clock-frequency : static clock frequency for the clock (OMAP2 only)
|
||||
- ti,idlest-shift : bit-shift for the idlest field (OMAP2 only)
|
||||
- ti,bit-shift : bit-shift for enable and autoidle fields (OMAP2 only)
|
||||
|
||||
Examples:
|
||||
apll_pcie_ck: apll_pcie_ck {
|
||||
#clock-cells = <0>;
|
||||
clocks = <&apll_pcie_in_clk_mux>, <&dpll_pcie_ref_ck>;
|
||||
reg = <0x021c>, <0x0220>;
|
||||
compatible = "ti,dra7-apll-clock";
|
||||
};
|
||||
|
||||
apll96_ck: apll96_ck {
|
||||
#clock-cells = <0>;
|
||||
compatible = "ti,omap2-apll-clock";
|
||||
clocks = <&sys_ck>;
|
||||
ti,bit-shift = <2>;
|
||||
ti,idlest-shift = <8>;
|
||||
ti,clock-frequency = <96000000>;
|
||||
reg = <0x0500>, <0x0530>, <0x0520>;
|
||||
};
|
||||
@@ -1,25 +0,0 @@
|
||||
Binding for Texas Instruments clockdomain.
|
||||
|
||||
This binding uses the common clock binding[1] in consumer role.
|
||||
Every clock on TI SoC belongs to one clockdomain, but software
|
||||
only needs this information for specific clocks which require
|
||||
their parent clockdomain to be controlled when the clock is
|
||||
enabled/disabled. This binding doesn't define a new clock
|
||||
binding type, it is used to group existing clock nodes under
|
||||
hardware hierarchy.
|
||||
|
||||
[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
|
||||
|
||||
Required properties:
|
||||
- compatible : shall be "ti,clockdomain"
|
||||
- #clock-cells : from common clock binding; shall be set to 0.
|
||||
- clocks : link phandles of clocks within this domain
|
||||
|
||||
Optional properties:
|
||||
- clock-output-names : from common clock binding.
|
||||
|
||||
Examples:
|
||||
dss_clkdm: dss_clkdm {
|
||||
compatible = "ti,clockdomain";
|
||||
clocks = <&dss1_alwon_fck_3430es2>, <&dss_ick_3430es2>;
|
||||
};
|
||||
@@ -0,0 +1,89 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/clock/ti/ti,apll-clock.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Texas Instruments APLL clock
|
||||
|
||||
maintainers:
|
||||
- Eduard Bostina <egbostina@gmail.com>
|
||||
|
||||
allOf:
|
||||
- $ref: /schemas/clock/clock.yaml#
|
||||
|
||||
description:
|
||||
This binding assumes a register-mapped APLL with usually two selectable
|
||||
input clocks (reference clock and bypass clock), with analog phase locked
|
||||
loop logic for multiplying the input clock to a desired output clock.
|
||||
This clock also typically supports different operation modes (locked, low
|
||||
power stop etc.) APLL mostly behaves like a subtype of a DPLL, although
|
||||
a simplified one at that.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- ti,dra7-apll-clock
|
||||
- ti,omap2-apll-clock
|
||||
|
||||
"#clock-cells":
|
||||
const: 0
|
||||
|
||||
clocks:
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
description: Link phandles of parent clocks (clk-ref and clk-bypass)
|
||||
|
||||
reg:
|
||||
minItems: 2
|
||||
maxItems: 3
|
||||
description: |
|
||||
Address and length of the register set for controlling the APLL.
|
||||
It contains the information of registers in the following order:
|
||||
"control" - contains the control register offset
|
||||
"idlest" - contains the idlest register offset
|
||||
"autoidle" - contains the autoidle register offset (OMAP2 only)
|
||||
|
||||
ti,clock-frequency:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description: static clock frequency for the clock (OMAP2 only)
|
||||
|
||||
ti,idlest-shift:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description: bit-shift for the idlest field (OMAP2 only)
|
||||
|
||||
ti,bit-shift:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description: bit-shift for enable and autoidle fields (OMAP2 only)
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- "#clock-cells"
|
||||
- clocks
|
||||
- reg
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
bus {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
clock@21c {
|
||||
#clock-cells = <0>;
|
||||
compatible = "ti,dra7-apll-clock";
|
||||
clocks = <&apll_pcie_in_clk_mux>, <&dpll_pcie_ref_ck>;
|
||||
reg = <0x021c>, <0x0220>;
|
||||
};
|
||||
|
||||
clock@500 {
|
||||
#clock-cells = <0>;
|
||||
compatible = "ti,omap2-apll-clock";
|
||||
clocks = <&sys_ck>;
|
||||
ti,bit-shift = <2>;
|
||||
ti,idlest-shift = <8>;
|
||||
ti,clock-frequency = <96000000>;
|
||||
reg = <0x0500>, <0x0530>, <0x0520>;
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,44 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/clock/ti/ti,clockdomain.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Texas Instruments clockdomain
|
||||
|
||||
maintainers:
|
||||
- Tero Kristo <kristo@kernel.org>
|
||||
|
||||
description:
|
||||
This binding uses the common clock binding in consumer role. Every clock on TI
|
||||
SoC belongs to one clockdomain, but software only needs this information for
|
||||
specific clocks which require their parent clockdomain to be controlled when
|
||||
the clock is enabled/disabled. This binding doesn't define a new clock binding
|
||||
type, it is used to group existing clock nodes under hardware hierarchy.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: ti,clockdomain
|
||||
|
||||
"#clock-cells":
|
||||
const: 0
|
||||
|
||||
clocks:
|
||||
minItems: 1
|
||||
maxItems: 64
|
||||
|
||||
clock-output-names:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- clocks
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
dss_clkdm {
|
||||
compatible = "ti,clockdomain";
|
||||
clocks = <&dss1_alwon_fck_3430es2>, <&dss_ick_3430es2>;
|
||||
};
|
||||
@@ -19,7 +19,7 @@ description: |
|
||||
that is used.
|
||||
|
||||
[1] Documentation/devicetree/bindings/clock/gpio-gate-clock.yaml
|
||||
[2] Documentation/devicetree/bindings/clock/ti/clockdomain.txt
|
||||
[2] Documentation/devicetree/bindings/clock/ti/ti,clockdomain.yaml
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/clock/ultrarisc,dp1000-clk.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: UltraRISC DP1000 Clock Controller
|
||||
|
||||
maintainers:
|
||||
- Jia Wang <wangjia@ultrarisc.com>
|
||||
|
||||
description: |
|
||||
The UltraRISC DP1000 clock controller is driven from a single external
|
||||
oscillator input. It provides a system PLL with fractional multiplier
|
||||
and post-divider stages, several fixed-ratio derived clocks for
|
||||
the on-chip subsystem, Clock Configuration Register (CCR) divider
|
||||
outputs for GMAC and the UART, I2C, and SPI root clocks, and
|
||||
per-instance gate clocks for UART0-3, I2C0-3, and SPI0-1.
|
||||
|
||||
All available clocks are defined as preprocessor macros in
|
||||
include/dt-bindings/clock/ultrarisc,dp1000-clk.h
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: ultrarisc,dp1000-clk
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
description:
|
||||
External oscillator input clock used as the parent of the PLLs.
|
||||
|
||||
"#clock-cells":
|
||||
const: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- "#clock-cells"
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/ultrarisc,dp1000-clk.h>
|
||||
|
||||
soc {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
|
||||
clock-controller@11080000 {
|
||||
compatible = "ultrarisc,dp1000-clk";
|
||||
reg = <0x0 0x11080000 0x0 0x1000>;
|
||||
clocks = <&osc>;
|
||||
#clock-cells = <1>;
|
||||
};
|
||||
};
|
||||
@@ -70,7 +70,7 @@ additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
clock-controller@b0000000 {
|
||||
clock-controller@b0000000 {
|
||||
compatible = "xlnx,clocking-wizard";
|
||||
reg = <0xb0000000 0x10000>;
|
||||
#clock-cells = <1>;
|
||||
|
||||
@@ -75,7 +75,7 @@ SoCs only:
|
||||
|
||||
- clocks: Should contain the device's input clock, and should be
|
||||
defined as per the bindings in,
|
||||
Documentation/devicetree/bindings/clock/keystone-gate.txt
|
||||
Documentation/devicetree/bindings/clock/ti,keystone,psc-clock.yaml
|
||||
|
||||
The following are mandatory properties for Keystone 2 66AK2G SoCs only:
|
||||
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/soc/cix/cix,sky1-audss-cru.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Cix Sky1 audio subsystem clock and reset unit
|
||||
|
||||
maintainers:
|
||||
- Joakim Zhang <joakim.zhang@cixtech.com>
|
||||
|
||||
description: |
|
||||
The Cix Sky1 Audio Subsystem (AUDSS) Clock and Reset Unit (CRU) groups
|
||||
audio-related clock muxing, gating and block-level software reset control
|
||||
in a single register block.
|
||||
|
||||
A single device node exposes both the clock controller and software reset
|
||||
lines. The clock driver registers as a platform driver; the reset controller
|
||||
is registered by an auxiliary driver bound from the clock driver.
|
||||
|
||||
Four SoC-level reference clocks listed in clocks/clock-names feed the AUDSS
|
||||
clock tree. Internal AUDSS clocks are exposed via #clock-cells; indices are
|
||||
defined in include/dt-bindings/clock/cix,sky1-audss-cru.h.
|
||||
|
||||
Block-level software reset indices are exposed via #reset-cells; indices
|
||||
are defined in include/dt-bindings/reset/cix,sky1-audss-cru.h.
|
||||
|
||||
The SoC syscon NoC (or bus) reset is described via resets. The audio
|
||||
subsystem power domain is described via power-domains.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: cix,sky1-audss-cru
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
'#clock-cells':
|
||||
const: 1
|
||||
description:
|
||||
Clock indices are defined in include/dt-bindings/clock/cix,sky1-audss-cru.h.
|
||||
|
||||
'#reset-cells':
|
||||
const: 1
|
||||
description:
|
||||
Reset indices are defined in include/dt-bindings/reset/cix,sky1-audss-cru.h.
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: I2S parent clock for sampling rates multiple of 8kHz.
|
||||
- description: I2S parent clock for sampling rates multiple of 11.025kHz.
|
||||
- description: Clock feeding most devices in AUDSS (NOC, DSP, SRAM, HDA, DMAC, I2S, and mailbox).
|
||||
- description: Clock feeding HDA, timer and watchdog, which is a dedicated 48 MHz clock.
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: x8k
|
||||
- const: x11k
|
||||
- const: sys
|
||||
- const: 48m
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
resets:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- '#clock-cells'
|
||||
- '#reset-cells'
|
||||
- clocks
|
||||
- clock-names
|
||||
- power-domains
|
||||
- resets
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
audss_cru: clock-controller@7110000 {
|
||||
compatible = "cix,sky1-audss-cru";
|
||||
reg = <0x7110000 0x10000>;
|
||||
#clock-cells = <1>;
|
||||
#reset-cells = <1>;
|
||||
clocks = <&scmi_clk 76>, <&scmi_clk 78>,
|
||||
<&scmi_clk 70>, <&scmi_clk 71>;
|
||||
clock-names = "x8k", "x11k", "sys", "48m";
|
||||
power-domains = <&smc_devpd 0>;
|
||||
resets = <&s5_syscon 31>;
|
||||
};
|
||||
@@ -42,21 +42,8 @@ clock interface.
|
||||
Common data structures and api
|
||||
==============================
|
||||
|
||||
Below is the common struct clk_core definition from
|
||||
drivers/clk/clk.c, modified for brevity::
|
||||
|
||||
struct clk_core {
|
||||
const char *name;
|
||||
const struct clk_ops *ops;
|
||||
struct clk_hw *hw;
|
||||
struct module *owner;
|
||||
struct clk_core *parent;
|
||||
const char **parent_names;
|
||||
struct clk_core **parents;
|
||||
u8 num_parents;
|
||||
u8 new_parent_index;
|
||||
...
|
||||
};
|
||||
.. kernel-doc:: drivers/clk/clk.c
|
||||
:identifiers: struct clk_core
|
||||
|
||||
The members above make up the core of the clk tree topology. The clk
|
||||
api itself defines several driver-facing functions which operate on
|
||||
@@ -64,38 +51,17 @@ struct clk. That api is documented in include/linux/clk.h.
|
||||
|
||||
Platforms and devices utilizing the common struct clk_core use the struct
|
||||
clk_ops pointer in struct clk_core to perform the hardware-specific parts of
|
||||
the operations defined in clk-provider.h::
|
||||
the operations defined in clk-provider.h, and can set one or more
|
||||
framework-level flags documented below.
|
||||
|
||||
struct clk_ops {
|
||||
int (*prepare)(struct clk_hw *hw);
|
||||
void (*unprepare)(struct clk_hw *hw);
|
||||
int (*is_prepared)(struct clk_hw *hw);
|
||||
void (*unprepare_unused)(struct clk_hw *hw);
|
||||
int (*enable)(struct clk_hw *hw);
|
||||
void (*disable)(struct clk_hw *hw);
|
||||
int (*is_enabled)(struct clk_hw *hw);
|
||||
void (*disable_unused)(struct clk_hw *hw);
|
||||
unsigned long (*recalc_rate)(struct clk_hw *hw,
|
||||
unsigned long parent_rate);
|
||||
int (*determine_rate)(struct clk_hw *hw,
|
||||
struct clk_rate_request *req);
|
||||
int (*set_parent)(struct clk_hw *hw, u8 index);
|
||||
u8 (*get_parent)(struct clk_hw *hw);
|
||||
int (*set_rate)(struct clk_hw *hw,
|
||||
unsigned long rate,
|
||||
unsigned long parent_rate);
|
||||
int (*set_rate_and_parent)(struct clk_hw *hw,
|
||||
unsigned long rate,
|
||||
unsigned long parent_rate,
|
||||
u8 index);
|
||||
unsigned long (*recalc_accuracy)(struct clk_hw *hw,
|
||||
unsigned long parent_accuracy);
|
||||
int (*get_phase)(struct clk_hw *hw);
|
||||
int (*set_phase)(struct clk_hw *hw, int degrees);
|
||||
void (*init)(struct clk_hw *hw);
|
||||
void (*debug_init)(struct clk_hw *hw,
|
||||
struct dentry *dentry);
|
||||
};
|
||||
.. kernel-doc:: include/linux/clk-provider.h
|
||||
:identifiers: struct clk_ops
|
||||
|
||||
Core flags
|
||||
==========
|
||||
|
||||
.. kernel-doc:: include/linux/clk-provider.h
|
||||
:doc: clk framework flags
|
||||
|
||||
Hardware clk implementations
|
||||
============================
|
||||
|
||||
@@ -248,6 +248,7 @@ CLOCK
|
||||
devm_clk_put()
|
||||
devm_clk_bulk_get()
|
||||
devm_clk_bulk_get_all()
|
||||
devm_clk_bulk_get_enable()
|
||||
devm_clk_bulk_get_optional()
|
||||
devm_get_clk_from_child()
|
||||
devm_clk_hw_register()
|
||||
|
||||
+13
-4
@@ -6447,9 +6447,9 @@ F: include/linux/comedi/
|
||||
F: include/uapi/linux/comedi.h
|
||||
|
||||
COMMON CLK FRAMEWORK
|
||||
M: Michael Turquette <mturquette@baylibre.com>
|
||||
M: Stephen Boyd <sboyd@kernel.org>
|
||||
R: Brian Masney <bmasney@redhat.com>
|
||||
M: Brian Masney <bmasney+clk@redhat.com>
|
||||
M: Jerome Brunet <jbrunet+clk@baylibre.com>
|
||||
L: linux-clk@vger.kernel.org
|
||||
S: Maintained
|
||||
Q: http://patchwork.kernel.org/project/linux-clk/list/
|
||||
@@ -9660,9 +9660,10 @@ ESWIN EIC7700 CLOCK DRIVER
|
||||
M: Yifeng Huang <huangyifeng@eswincomputing.com>
|
||||
M: Xuyang Dong <dongxuyang@eswincomputing.com>
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/clock/eswin,eic7700-clock.yaml
|
||||
F: Documentation/devicetree/bindings/clock/eswin,eic7700*
|
||||
F: drivers/clk/eswin/
|
||||
F: include/dt-bindings/clock/eswin,eic7700-clock.h
|
||||
F: include/dt-bindings/clock/eswin,eic7700*
|
||||
F: include/dt-bindings/reset/eswin,eic7700-hspcrg.h
|
||||
|
||||
ET131X NETWORK DRIVER
|
||||
M: Mark Einon <mark.einon@gmail.com>
|
||||
@@ -27672,6 +27673,14 @@ S: Maintained
|
||||
F: drivers/usb/common/ulpi.c
|
||||
F: include/linux/ulpi/
|
||||
|
||||
ULTRARISC DP1000 CLOCK DRIVER
|
||||
M: Jia Wang <wangjia@ultrarisc.com>
|
||||
L: linux-clk@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/clock/ultrarisc,dp1000-clk.yaml
|
||||
F: drivers/clk/ultrarisc/*
|
||||
F: include/dt-bindings/clock/ultrarisc,dp1000-clk.h
|
||||
|
||||
ULTRARISC DP1000 PINCTRL DRIVER
|
||||
M: Jia Wang <wangjia@ultrarisc.com>
|
||||
L: linux-gpio@vger.kernel.org
|
||||
|
||||
@@ -6,6 +6,10 @@
|
||||
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/clock/cix,sky1.h>
|
||||
#include <dt-bindings/clock/cix,sky1-audss-cru.h>
|
||||
#include <dt-bindings/reset/cix,sky1-system-control.h>
|
||||
#include <dt-bindings/reset/cix,sky1-s5-system-control.h>
|
||||
#include <dt-bindings/reset/cix,sky1-audss-cru.h>
|
||||
#include "sky1-power.h"
|
||||
|
||||
/ {
|
||||
@@ -558,6 +562,20 @@
|
||||
cix,mbox-dir = "rx";
|
||||
};
|
||||
|
||||
audss_cru: clock-controller@7110000 {
|
||||
compatible = "cix,sky1-audss-cru";
|
||||
reg = <0x0 0x07110000 0x0 0x10000>;
|
||||
#clock-cells = <1>;
|
||||
#reset-cells = <1>;
|
||||
clocks = <&scmi_clk CLK_TREE_AUDIO_CLK0>,
|
||||
<&scmi_clk CLK_TREE_AUDIO_CLK2>,
|
||||
<&scmi_clk CLK_TREE_AUDIO_CLK4>,
|
||||
<&scmi_clk CLK_TREE_AUDIO_CLK5>;
|
||||
clock-names = "x8k", "x11k", "sys", "48m";
|
||||
power-domains = <&smc_devpd SKY1_PD_AUDIO>;
|
||||
resets = <&s5_syscon SKY1_AUDIO_HIFI5_NOC_RESET_N>;
|
||||
};
|
||||
|
||||
mbox_sfh2ap: mailbox@8090000 {
|
||||
compatible = "cix,sky1-mbox";
|
||||
reg = <0x0 0x08090000 0x0 0x10000>;
|
||||
|
||||
@@ -4,6 +4,7 @@ CONFIG_OF=y
|
||||
CONFIG_OF_OVERLAY=y
|
||||
CONFIG_COMMON_CLK=y
|
||||
CONFIG_CLK_KUNIT_TEST=y
|
||||
CONFIG_CLK_DIVIDER_KUNIT_TEST=y
|
||||
CONFIG_CLK_FIXED_RATE_KUNIT_TEST=y
|
||||
CONFIG_CLK_GATE_KUNIT_TEST=y
|
||||
CONFIG_CLK_FD_KUNIT_TEST=y
|
||||
|
||||
+14
-4
@@ -155,12 +155,12 @@ config COMMON_CLK_SI514
|
||||
generator.
|
||||
|
||||
config COMMON_CLK_SI544
|
||||
tristate "Clock driver for SiLabs 544 devices"
|
||||
tristate "Clock driver for SiLabs 544 and compatible devices"
|
||||
depends on I2C
|
||||
select REGMAP_I2C
|
||||
help
|
||||
This driver supports the Silicon Labs 544 programmable clock
|
||||
generator.
|
||||
This driver supports the Silicon Labs 544/549 programmable clock
|
||||
generators.
|
||||
|
||||
config COMMON_CLK_SI570
|
||||
tristate "Clock driver for SiLabs 570 and compatible devices"
|
||||
@@ -278,7 +278,7 @@ config COMMON_CLK_LAN966X
|
||||
tristate "Generic Clock Controller driver for LAN966X SoC"
|
||||
depends on HAS_IOMEM
|
||||
depends on OF
|
||||
depends on SOC_LAN966 || ARCH_LAN969X || COMPILE_TEST
|
||||
depends on SOC_LAN966 || ARCH_LAN969X || MCHP_LAN966X_PCI || COMPILE_TEST
|
||||
help
|
||||
This driver provides support for Generic Clock Controller(GCK) on
|
||||
LAN966X SoC. GCK generates and supplies clock to various peripherals
|
||||
@@ -509,6 +509,7 @@ source "drivers/clk/actions/Kconfig"
|
||||
source "drivers/clk/analogbits/Kconfig"
|
||||
source "drivers/clk/aspeed/Kconfig"
|
||||
source "drivers/clk/bcm/Kconfig"
|
||||
source "drivers/clk/cix/Kconfig"
|
||||
source "drivers/clk/eswin/Kconfig"
|
||||
source "drivers/clk/hisilicon/Kconfig"
|
||||
source "drivers/clk/imgtec/Kconfig"
|
||||
@@ -541,6 +542,7 @@ source "drivers/clk/tenstorrent/Kconfig"
|
||||
source "drivers/clk/thead/Kconfig"
|
||||
source "drivers/clk/stm32/Kconfig"
|
||||
source "drivers/clk/ti/Kconfig"
|
||||
source "drivers/clk/ultrarisc/Kconfig"
|
||||
source "drivers/clk/uniphier/Kconfig"
|
||||
source "drivers/clk/visconti/Kconfig"
|
||||
source "drivers/clk/x86/Kconfig"
|
||||
@@ -579,4 +581,12 @@ config CLK_FD_KUNIT_TEST
|
||||
help
|
||||
Kunit test for the clk-fractional-divider type.
|
||||
|
||||
config CLK_DIVIDER_KUNIT_TEST
|
||||
tristate "KUnit tests for clk divider bestdiv" if !KUNIT_ALL_TESTS
|
||||
depends on KUNIT
|
||||
depends on !S390
|
||||
default KUNIT_ALL_TESTS
|
||||
help
|
||||
Kunit test for the clk-divider type.
|
||||
|
||||
endif
|
||||
|
||||
+17
-3
@@ -18,9 +18,20 @@ clk-test-y := clk_test.o \
|
||||
kunit_clk_assigned_rates_without_consumer.dtbo.o \
|
||||
kunit_clk_assigned_rates_zero.dtbo.o \
|
||||
kunit_clk_assigned_rates_zero_consumer.dtbo.o \
|
||||
kunit_clk_assigned_sscs_one.dtbo.o \
|
||||
kunit_clk_assigned_sscs_one_consumer.dtbo.o \
|
||||
kunit_clk_assigned_sscs_multiple.dtbo.o \
|
||||
kunit_clk_assigned_sscs_multiple_consumer.dtbo.o \
|
||||
kunit_clk_assigned_sscs_null.dtbo.o \
|
||||
kunit_clk_assigned_sscs_null_consumer.dtbo.o \
|
||||
kunit_clk_assigned_sscs_without.dtbo.o \
|
||||
kunit_clk_assigned_sscs_without_consumer.dtbo.o \
|
||||
kunit_clk_assigned_sscs_zero.dtbo.o \
|
||||
kunit_clk_assigned_sscs_zero_consumer.dtbo.o \
|
||||
kunit_clk_hw_get_dev_of_node.dtbo.o \
|
||||
kunit_clk_parent_data_test.dtbo.o
|
||||
obj-$(CONFIG_COMMON_CLK) += clk-divider.o
|
||||
obj-$(CONFIG_CLK_DIVIDER_KUNIT_TEST) += clk-divider_test.o
|
||||
obj-$(CONFIG_COMMON_CLK) += clk-fixed-factor.o
|
||||
obj-$(CONFIG_COMMON_CLK) += clk-fixed-rate.o
|
||||
obj-$(CONFIG_CLK_FIXED_RATE_KUNIT_TEST) += clk-fixed-rate-test.o
|
||||
@@ -88,7 +99,8 @@ obj-$(CONFIG_COMMON_CLK_RP1) += clk-rp1.o
|
||||
obj-$(CONFIG_COMMON_CLK_RPMI) += clk-rpmi.o
|
||||
obj-$(CONFIG_COMMON_CLK_HI655X) += clk-hi655x.o
|
||||
obj-$(CONFIG_COMMON_CLK_S2MPS11) += clk-s2mps11.o
|
||||
obj-$(CONFIG_COMMON_CLK_SCMI) += clk-scmi.o
|
||||
scmi-clk-y := clk-scmi.o clk-scmi-oem.o
|
||||
obj-$(CONFIG_COMMON_CLK_SCMI) += scmi-clk.o
|
||||
obj-$(CONFIG_COMMON_CLK_SCPI) += clk-scpi.o
|
||||
obj-$(CONFIG_COMMON_CLK_SI5341) += clk-si5341.o
|
||||
obj-$(CONFIG_COMMON_CLK_SI5351) += clk-si5351.o
|
||||
@@ -119,9 +131,10 @@ obj-$(CONFIG_ARCH_ARTPEC) += axis/
|
||||
obj-$(CONFIG_ARC_PLAT_AXS10X) += axs10x/
|
||||
obj-y += bcm/
|
||||
obj-$(CONFIG_ARCH_BERLIN) += berlin/
|
||||
obj-y += cix/
|
||||
obj-$(CONFIG_ARCH_DAVINCI) += davinci/
|
||||
obj-$(CONFIG_COMMON_CLK_ESWIN) += eswin/
|
||||
obj-$(CONFIG_ARCH_HISI) += hisilicon/
|
||||
obj-$(CONFIG_COMMON_CLK_HISI) += hisilicon/
|
||||
obj-y += imgtec/
|
||||
obj-y += imx/
|
||||
obj-y += ingenic/
|
||||
@@ -151,7 +164,7 @@ obj-y += spacemit/
|
||||
obj-$(CONFIG_PLAT_SPEAR) += spear/
|
||||
obj-y += sprd/
|
||||
obj-$(CONFIG_ARCH_STI) += st/
|
||||
obj-$(CONFIG_ARCH_STM32) += stm32/
|
||||
obj-$(CONFIG_COMMON_CLK_STM32MP) += stm32/
|
||||
obj-y += starfive/
|
||||
obj-$(CONFIG_ARCH_SUNXI) += sunxi/
|
||||
obj-y += sunxi-ng/
|
||||
@@ -159,6 +172,7 @@ obj-$(CONFIG_ARCH_TEGRA) += tegra/
|
||||
obj-y += tenstorrent/
|
||||
obj-y += thead/
|
||||
obj-y += ti/
|
||||
obj-y += ultrarisc/
|
||||
obj-$(CONFIG_CLK_UNIPHIER) += uniphier/
|
||||
obj-$(CONFIG_ARCH_U8500) += ux500/
|
||||
obj-y += versatile/
|
||||
|
||||
@@ -272,6 +272,13 @@ static const unsigned int sdclk_parent_ids[] = {
|
||||
|
||||
static const struct clk_hw *sdclk_parent_hws[ARRAY_SIZE(sdclk_parent_ids)];
|
||||
|
||||
static const unsigned int peciclk_parent_ids[] = {
|
||||
SCU1_CLKIN,
|
||||
SCU1_CLK_HPLL_DIV4
|
||||
};
|
||||
|
||||
static const struct clk_hw *peciclk_parent_hws[ARRAY_SIZE(peciclk_parent_ids)];
|
||||
|
||||
#define FIXED_CLK(_id, _name, _rate) \
|
||||
{ \
|
||||
.id = _id, \
|
||||
@@ -457,6 +464,7 @@ static const struct ast2700_clk_info ast2700_scu1_clk_info[] __initconst = {
|
||||
PLL_CLK(SCU1_CLK_HPLL, CLK_PLL, "soc1-hpll", SCU1_CLKIN, SCU1_HPLL_PARAM),
|
||||
PLL_CLK(SCU1_CLK_APLL, CLK_PLL, "soc1-apll", SCU1_CLKIN, SCU1_APLL_PARAM),
|
||||
PLL_CLK(SCU1_CLK_DPLL, CLK_PLL, "soc1-dpll", SCU1_CLKIN, SCU1_DPLL_PARAM),
|
||||
FIXED_FACTOR_CLK(SCU1_CLK_HPLL_DIV4, "soc1-hpll_div4", SCU1_CLK_HPLL, 1, 4),
|
||||
FIXED_FACTOR_CLK(SCU1_CLK_APLL_DIV2, "soc1-apll_div2", SCU1_CLK_APLL, 1, 2),
|
||||
FIXED_FACTOR_CLK(SCU1_CLK_APLL_DIV4, "soc1-apll_div4", SCU1_CLK_APLL, 1, 4),
|
||||
FIXED_FACTOR_CLK(SCU1_CLK_CAN, "canclk", SCU1_CLK_APLL, 1, 10),
|
||||
@@ -480,6 +488,8 @@ static const struct ast2700_clk_info ast2700_scu1_clk_info[] __initconst = {
|
||||
uxclk_parent_hws, SCU1_CLK_SEL2, 0, 2),
|
||||
MUX_CLK(SCU1_CLK_HUXCLK, "huxclk", uxclk_parent_ids, ARRAY_SIZE(uxclk_parent_ids),
|
||||
uxclk_parent_hws, SCU1_CLK_SEL2, 3, 2),
|
||||
MUX_CLK(SCU1_CLK_PECI, "peciclk", peciclk_parent_ids, ARRAY_SIZE(peciclk_parent_ids),
|
||||
peciclk_parent_hws, SCU1_CLK_SEL2, 16, 1),
|
||||
DIVIDER_CLK(SCU1_CLK_SDCLK, "sdclk", SCU1_CLK_SDMUX,
|
||||
SCU1_CLK_SEL1, 14, 3, ast2700_clk_div_table),
|
||||
PLL_CLK(SCU1_CLK_UARTX, CLK_UART_PLL, "uartxclk", SCU1_CLK_UXCLK, SCU1_UXCLK_CTRL),
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/clk/at91_pmc.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/slab.h>
|
||||
@@ -217,7 +218,7 @@ CLK_OF_DECLARE(of_sama5d4_clk_h32mx_setup, "atmel,sama5d4-clk-h32mx",
|
||||
static void __init of_sama5d2_clk_i2s_mux_setup(struct device_node *np)
|
||||
{
|
||||
struct regmap *regmap_sfr;
|
||||
u8 bus_id;
|
||||
u64 bus_id;
|
||||
const char *parent_names[2];
|
||||
struct device_node *i2s_mux_np;
|
||||
struct clk_hw *hw;
|
||||
@@ -228,7 +229,7 @@ static void __init of_sama5d2_clk_i2s_mux_setup(struct device_node *np)
|
||||
return;
|
||||
|
||||
for_each_child_of_node(np, i2s_mux_np) {
|
||||
if (of_property_read_u8(i2s_mux_np, "reg", &bus_id))
|
||||
if (of_property_read_reg(i2s_mux_np, 0, &bus_id, NULL))
|
||||
continue;
|
||||
|
||||
if (bus_id > I2S_BUS_NR)
|
||||
|
||||
@@ -1098,8 +1098,7 @@ static u8 kona_peri_clk_get_parent(struct clk_hw *hw)
|
||||
|
||||
index = selector_read_index(bcm_clk->ccu, &data->sel);
|
||||
|
||||
/* Not all callers would handle an out-of-range value gracefully */
|
||||
return index == BAD_CLK_INDEX ? 0 : index;
|
||||
return index;
|
||||
}
|
||||
|
||||
static int kona_peri_clk_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
# Audio subsystem clock support for Cixtech SoC family
|
||||
menu "Cixtech Audio Subsystem Clock Driver"
|
||||
|
||||
config CLK_SKY1_AUDSS
|
||||
tristate "Cixtech Sky1 Audio Subsystem Clock Driver"
|
||||
depends on ARCH_CIX || COMPILE_TEST
|
||||
select AUXILIARY_BUS
|
||||
select REGMAP_MMIO
|
||||
select RESET_CONTROLLER
|
||||
help
|
||||
Support for the Audio Subsystem clock controller present on
|
||||
Cixtech Sky1 SoC. This driver provides mux, divider and gate
|
||||
clocks for DSP, I2S, HDA and related blocks in the audio
|
||||
subsystem. Say M or Y here if you want to build this driver.
|
||||
endmenu
|
||||
@@ -0,0 +1,3 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
obj-$(CONFIG_CLK_SKY1_AUDSS) += clk-sky1-audss.o
|
||||
File diff suppressed because it is too large
Load Diff
@@ -147,12 +147,12 @@ static int bd71837_clk_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
static const struct platform_device_id bd718x7_clk_id[] = {
|
||||
{ "bd71837-clk", ROHM_CHIP_TYPE_BD71837 },
|
||||
{ "bd71847-clk", ROHM_CHIP_TYPE_BD71847 },
|
||||
{ "bd71828-clk", ROHM_CHIP_TYPE_BD71828 },
|
||||
{ "bd71815-clk", ROHM_CHIP_TYPE_BD71815 },
|
||||
{ "bd72720-clk", ROHM_CHIP_TYPE_BD72720 },
|
||||
{ },
|
||||
{ .name = "bd71837-clk", .driver_data = ROHM_CHIP_TYPE_BD71837 },
|
||||
{ .name = "bd71847-clk", .driver_data = ROHM_CHIP_TYPE_BD71847 },
|
||||
{ .name = "bd71828-clk", .driver_data = ROHM_CHIP_TYPE_BD71828 },
|
||||
{ .name = "bd71815-clk", .driver_data = ROHM_CHIP_TYPE_BD71815 },
|
||||
{ .name = "bd72720-clk", .driver_data = ROHM_CHIP_TYPE_BD72720 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(platform, bd718x7_clk_id);
|
||||
|
||||
|
||||
@@ -679,7 +679,7 @@ MODULE_DEVICE_TABLE(of, cdce706_dt_match);
|
||||
#endif
|
||||
|
||||
static const struct i2c_device_id cdce706_id[] = {
|
||||
{ "cdce706" },
|
||||
{ .name = "cdce706" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, cdce706_id);
|
||||
|
||||
@@ -826,10 +826,10 @@ static const struct clk_cdce925_chip_info clk_cdce949_info = {
|
||||
};
|
||||
|
||||
static const struct i2c_device_id cdce925_id[] = {
|
||||
{ "cdce913", (kernel_ulong_t)&clk_cdce913_info },
|
||||
{ "cdce925", (kernel_ulong_t)&clk_cdce925_info },
|
||||
{ "cdce937", (kernel_ulong_t)&clk_cdce937_info },
|
||||
{ "cdce949", (kernel_ulong_t)&clk_cdce949_info },
|
||||
{ .name = "cdce913", .driver_data = (kernel_ulong_t)&clk_cdce913_info },
|
||||
{ .name = "cdce925", .driver_data = (kernel_ulong_t)&clk_cdce925_info },
|
||||
{ .name = "cdce937", .driver_data = (kernel_ulong_t)&clk_cdce937_info },
|
||||
{ .name = "cdce949", .driver_data = (kernel_ulong_t)&clk_cdce949_info },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, cdce925_id);
|
||||
|
||||
@@ -462,3 +462,4 @@ struct clk_hw *devm_clk_hw_register_composite_pdata(struct device *dev,
|
||||
rate_hw, rate_ops, gate_hw,
|
||||
gate_ops, flags);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_clk_hw_register_composite_pdata);
|
||||
|
||||
@@ -155,6 +155,78 @@ static int __set_clk_rates(struct device_node *node, bool clk_supplier)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __set_clk_spread_spectrum(struct device_node *node, bool clk_supplier)
|
||||
{
|
||||
u32 elem_size = sizeof(struct clk_spread_spectrum);
|
||||
struct clk_spread_spectrum *sscs;
|
||||
struct of_phandle_args clkspec;
|
||||
int rc, count, index;
|
||||
struct clk *clk;
|
||||
|
||||
/* modfreq, spreadPercent, modmethod */
|
||||
count = of_property_count_elems_of_size(node, "assigned-clock-sscs", elem_size);
|
||||
if (count <= 0)
|
||||
return 0;
|
||||
|
||||
sscs = kcalloc(count, elem_size, GFP_KERNEL);
|
||||
if (!sscs)
|
||||
return -ENOMEM;
|
||||
|
||||
rc = of_property_read_u32_array(node, "assigned-clock-sscs", (u32 *)sscs,
|
||||
count * 3);
|
||||
if (rc)
|
||||
goto free_sscs;
|
||||
|
||||
for (index = 0; index < count; index++) {
|
||||
struct clk_spread_spectrum *conf = &sscs[index];
|
||||
struct clk_hw *hw;
|
||||
|
||||
if (!conf->modfreq_hz && !conf->spread_bp && !conf->method)
|
||||
continue;
|
||||
|
||||
rc = of_parse_phandle_with_args(node, "assigned-clocks", "#clock-cells",
|
||||
index, &clkspec);
|
||||
if (rc < 0) {
|
||||
/* skip empty (null) phandles */
|
||||
if (rc == -ENOENT) {
|
||||
rc = 0;
|
||||
continue;
|
||||
} else
|
||||
goto free_sscs;
|
||||
}
|
||||
|
||||
if (clkspec.np == node && !clk_supplier) {
|
||||
of_node_put(clkspec.np);
|
||||
goto free_sscs;
|
||||
}
|
||||
|
||||
clk = of_clk_get_from_provider(&clkspec);
|
||||
of_node_put(clkspec.np);
|
||||
if (IS_ERR(clk)) {
|
||||
if (PTR_ERR(clk) != -EPROBE_DEFER)
|
||||
pr_warn("clk: couldn't get clock %d for %pOF\n",
|
||||
index, node);
|
||||
rc = PTR_ERR(clk);
|
||||
goto free_sscs;
|
||||
}
|
||||
|
||||
hw = __clk_get_hw(clk);
|
||||
rc = clk_hw_set_spread_spectrum(hw, conf);
|
||||
if (rc < 0) {
|
||||
pr_err("clk: couldn't set %s clk spread spectrum %u %u %u: %d\n",
|
||||
__clk_get_name(clk), conf->modfreq_hz, conf->spread_bp,
|
||||
conf->method, rc);
|
||||
/* Do not fail */
|
||||
rc = 0;
|
||||
}
|
||||
clk_put(clk);
|
||||
}
|
||||
|
||||
free_sscs:
|
||||
kfree(sscs);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* of_clk_set_defaults() - parse and set assigned clocks configuration
|
||||
* @node: device node to apply clock settings for
|
||||
@@ -174,6 +246,10 @@ int of_clk_set_defaults(struct device_node *node, bool clk_supplier)
|
||||
if (!node)
|
||||
return 0;
|
||||
|
||||
rc = __set_clk_spread_spectrum(node, clk_supplier);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
rc = __set_clk_parents(node, clk_supplier);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
@@ -122,8 +122,8 @@ static const struct of_device_id cs2000_of_match[] = {
|
||||
MODULE_DEVICE_TABLE(of, cs2000_of_match);
|
||||
|
||||
static const struct i2c_device_id cs2000_id[] = {
|
||||
{ "cs2000-cp", },
|
||||
{}
|
||||
{ .name = "cs2000-cp" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, cs2000_id);
|
||||
|
||||
@@ -404,11 +404,7 @@ static int cs2000_enable(struct clk_hw *hw)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = cs2000_wait_pll_lock(priv);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return ret;
|
||||
return cs2000_wait_pll_lock(priv);
|
||||
}
|
||||
|
||||
static void cs2000_disable(struct clk_hw *hw)
|
||||
|
||||
@@ -99,6 +99,11 @@ struct clk *devm_clk_get_optional_enabled(struct device *dev, const char *id)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_clk_get_optional_enabled);
|
||||
|
||||
static void devm_clk_disable_unprepare(void *data)
|
||||
{
|
||||
clk_disable_unprepare(data);
|
||||
}
|
||||
|
||||
struct clk *devm_clk_get_optional_enabled_with_rate(struct device *dev,
|
||||
const char *id,
|
||||
unsigned long rate)
|
||||
@@ -106,8 +111,7 @@ struct clk *devm_clk_get_optional_enabled_with_rate(struct device *dev,
|
||||
struct clk *clk;
|
||||
int ret;
|
||||
|
||||
clk = __devm_clk_get(dev, id, clk_get_optional, NULL,
|
||||
clk_disable_unprepare);
|
||||
clk = devm_clk_get_optional(dev, id);
|
||||
if (IS_ERR(clk))
|
||||
return ERR_CAST(clk);
|
||||
|
||||
@@ -119,6 +123,10 @@ struct clk *devm_clk_get_optional_enabled_with_rate(struct device *dev,
|
||||
if (ret)
|
||||
goto out_put_clk;
|
||||
|
||||
ret = devm_add_action_or_reset(dev, devm_clk_disable_unprepare, clk);
|
||||
if (ret)
|
||||
goto out_put_clk;
|
||||
|
||||
return clk;
|
||||
|
||||
out_put_clk:
|
||||
@@ -222,6 +230,13 @@ err_clk_get:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int __must_check devm_clk_bulk_get_enable(struct device *dev, int num_clks,
|
||||
struct clk_bulk_data *clks)
|
||||
{
|
||||
return __devm_clk_bulk_get_enable(dev, num_clks, clks, false);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_clk_bulk_get_enable);
|
||||
|
||||
int __must_check devm_clk_bulk_get_optional_enable(struct device *dev, int num_clks,
|
||||
struct clk_bulk_data *clks)
|
||||
{
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <linux/err.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/log2.h>
|
||||
#include <linux/overflow.h>
|
||||
|
||||
/*
|
||||
* DOC: basic adjustable divider clock that cannot gate
|
||||
@@ -301,6 +302,7 @@ static int clk_divider_bestdiv(struct clk_hw *hw, struct clk_hw *parent,
|
||||
int i, bestdiv = 0;
|
||||
unsigned long parent_rate, best = 0, now, maxdiv;
|
||||
unsigned long parent_rate_saved = *best_parent_rate;
|
||||
unsigned long target_parent_rate;
|
||||
|
||||
if (!rate)
|
||||
rate = 1;
|
||||
@@ -315,15 +317,11 @@ static int clk_divider_bestdiv(struct clk_hw *hw, struct clk_hw *parent,
|
||||
return bestdiv;
|
||||
}
|
||||
|
||||
/*
|
||||
* The maximum divider we can use without overflowing
|
||||
* unsigned long in rate * i below
|
||||
*/
|
||||
maxdiv = min(ULONG_MAX / rate, maxdiv);
|
||||
|
||||
for (i = _next_div(table, 0, flags); i <= maxdiv;
|
||||
i = _next_div(table, i, flags)) {
|
||||
if (rate * i == parent_rate_saved) {
|
||||
bool overflow = check_mul_overflow(rate, (unsigned long)i, &target_parent_rate);
|
||||
|
||||
if (!overflow && target_parent_rate == parent_rate_saved) {
|
||||
/*
|
||||
* It's the most ideal case if the requested rate can be
|
||||
* divided from parent clock without needing to change
|
||||
@@ -332,13 +330,24 @@ static int clk_divider_bestdiv(struct clk_hw *hw, struct clk_hw *parent,
|
||||
*best_parent_rate = parent_rate_saved;
|
||||
return i;
|
||||
}
|
||||
parent_rate = clk_hw_round_rate(parent, rate * i);
|
||||
/*
|
||||
* Clamp target_parent_rate to ULONG_MAX on overflow. The true
|
||||
* required parent rate exceeds what can be represented, so ask
|
||||
* the parent for the highest rate it can produce. There is no
|
||||
* point continuing the loop past this since larger dividers
|
||||
* only move further from the requested rate.
|
||||
*/
|
||||
if (overflow)
|
||||
target_parent_rate = ULONG_MAX;
|
||||
parent_rate = clk_hw_round_rate(parent, target_parent_rate);
|
||||
now = DIV_ROUND_UP_ULL((u64)parent_rate, i);
|
||||
if (_is_best_div(rate, now, best, flags)) {
|
||||
bestdiv = i;
|
||||
best = now;
|
||||
*best_parent_rate = parent_rate;
|
||||
}
|
||||
if (overflow)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!bestdiv) {
|
||||
|
||||
@@ -0,0 +1,153 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* KUnit tests for clk_divider_bestdiv()
|
||||
*/
|
||||
#include <kunit/test.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/limits.h>
|
||||
#include <linux/units.h>
|
||||
|
||||
#define PARENT_RATE_1GHZ GIGA
|
||||
#define PARENT_RATE_2GHZ (2 * GIGA)
|
||||
#define PARENT_RATE_4GHZ (4 * GIGA)
|
||||
|
||||
KUNIT_DEFINE_ACTION_WRAPPER(clk_hw_unregister_fixed_rate_wrapper,
|
||||
clk_hw_unregister_fixed_rate, struct clk_hw *);
|
||||
KUNIT_DEFINE_ACTION_WRAPPER(clk_hw_unregister_divider_wrapper,
|
||||
clk_hw_unregister_divider, struct clk_hw *);
|
||||
KUNIT_DEFINE_ACTION_WRAPPER(clk_hw_unregister_mux_wrapper,
|
||||
clk_hw_unregister_mux, struct clk_hw *);
|
||||
|
||||
static const struct clk_div_table bestdiv_table[] = {
|
||||
{ .val = 0, .div = 2 },
|
||||
{ .val = 1, .div = 4 },
|
||||
{ .val = 2, .div = 8 },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
/*
|
||||
* Test that clk_round_rate(clk, ULONG_MAX) returns the maximum achievable
|
||||
* rate for a divider clock.
|
||||
*/
|
||||
static void clk_divider_bestdiv_ulong_max_returns_max_rate(struct kunit *test)
|
||||
{
|
||||
struct clk_hw *parent_hw, *div_hw;
|
||||
unsigned long rate;
|
||||
u32 *fake_reg;
|
||||
|
||||
fake_reg = kunit_kzalloc(test, sizeof(*fake_reg), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, fake_reg);
|
||||
|
||||
parent_hw = clk_hw_register_fixed_rate(NULL, "bestdiv-parent",
|
||||
NULL, 0, PARENT_RATE_1GHZ);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, parent_hw);
|
||||
KUNIT_ASSERT_EQ(test, 0,
|
||||
kunit_add_action_or_reset(test, clk_hw_unregister_fixed_rate_wrapper,
|
||||
parent_hw));
|
||||
|
||||
div_hw = clk_hw_register_divider_table(NULL, "bestdiv-div",
|
||||
"bestdiv-parent",
|
||||
CLK_SET_RATE_PARENT,
|
||||
(void __iomem __force *)fake_reg,
|
||||
0, 2, 0, bestdiv_table, NULL);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, div_hw);
|
||||
KUNIT_ASSERT_EQ(test, 0,
|
||||
kunit_add_action_or_reset(test, clk_hw_unregister_divider_wrapper,
|
||||
div_hw));
|
||||
|
||||
/*
|
||||
* ULONG_MAX is the canonical way to probe the maximum rate a clock
|
||||
* can produce.
|
||||
*/
|
||||
rate = clk_hw_round_rate(div_hw, ULONG_MAX);
|
||||
KUNIT_EXPECT_EQ(test, rate, PARENT_RATE_1GHZ / 2);
|
||||
}
|
||||
|
||||
/*
|
||||
* Test that clk_round_rate(clk, ULONG_MAX) returns the correct maximum rate
|
||||
* when a mux clock sits between a divider and its parent candidates.
|
||||
*
|
||||
* Topology:
|
||||
*
|
||||
* [fixed 4 GHz] --\
|
||||
* +--> [mux CLK_SET_RATE_PARENT] --> [div {2,4,8} CLK_SET_RATE_PARENT]
|
||||
* [fixed 2 GHz] --/
|
||||
*
|
||||
*/
|
||||
static void clk_divider_bestdiv_mux_ulong_max_returns_max_rate(struct kunit *test)
|
||||
{
|
||||
static const char * const mux_parents[] = {
|
||||
"bestdiv-mux-parent-a",
|
||||
"bestdiv-mux-parent-b",
|
||||
};
|
||||
struct clk_hw *parent_a_hw, *parent_b_hw, *mux_hw, *div_hw;
|
||||
u32 *fake_reg_mux, *fake_reg_div;
|
||||
unsigned long rate;
|
||||
|
||||
fake_reg_mux = kunit_kzalloc(test, sizeof(*fake_reg_mux), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, fake_reg_mux);
|
||||
|
||||
fake_reg_div = kunit_kzalloc(test, sizeof(*fake_reg_div), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, fake_reg_div);
|
||||
|
||||
/* Higher-rate parent: the mux should select this for ULONG_MAX. */
|
||||
parent_a_hw = clk_hw_register_fixed_rate(NULL, "bestdiv-mux-parent-a",
|
||||
NULL, 0, PARENT_RATE_4GHZ);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, parent_a_hw);
|
||||
KUNIT_ASSERT_EQ(test, 0,
|
||||
kunit_add_action_or_reset(test, clk_hw_unregister_fixed_rate_wrapper,
|
||||
parent_a_hw));
|
||||
|
||||
/* Lower-rate parent: should not be selected. */
|
||||
parent_b_hw = clk_hw_register_fixed_rate(NULL, "bestdiv-mux-parent-b",
|
||||
NULL, 0, PARENT_RATE_2GHZ);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, parent_b_hw);
|
||||
KUNIT_ASSERT_EQ(test, 0,
|
||||
kunit_add_action_or_reset(test, clk_hw_unregister_fixed_rate_wrapper,
|
||||
parent_b_hw));
|
||||
|
||||
/*
|
||||
* 1-bit mux register selects between the two parents.
|
||||
* CLK_SET_RATE_PARENT allows the divider's rate request to
|
||||
* propagate into clk_mux_determine_rate().
|
||||
*/
|
||||
mux_hw = clk_hw_register_mux(NULL, "bestdiv-mux",
|
||||
mux_parents, ARRAY_SIZE(mux_parents),
|
||||
CLK_SET_RATE_PARENT,
|
||||
(void __iomem __force *)fake_reg_mux,
|
||||
0, 1, 0, NULL);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, mux_hw);
|
||||
KUNIT_ASSERT_EQ(test, 0,
|
||||
kunit_add_action_or_reset(test, clk_hw_unregister_mux_wrapper,
|
||||
mux_hw));
|
||||
|
||||
div_hw = clk_hw_register_divider_table(NULL, "bestdiv-mux-div",
|
||||
"bestdiv-mux",
|
||||
CLK_SET_RATE_PARENT,
|
||||
(void __iomem __force *)fake_reg_div,
|
||||
0, 2, 0, bestdiv_table, NULL);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, div_hw);
|
||||
KUNIT_ASSERT_EQ(test, 0,
|
||||
kunit_add_action_or_reset(test, clk_hw_unregister_divider_wrapper,
|
||||
div_hw));
|
||||
|
||||
rate = clk_hw_round_rate(div_hw, ULONG_MAX);
|
||||
KUNIT_EXPECT_EQ(test, rate, PARENT_RATE_4GHZ / 2);
|
||||
}
|
||||
|
||||
static struct kunit_case clk_divider_bestdiv_test_cases[] = {
|
||||
KUNIT_CASE(clk_divider_bestdiv_ulong_max_returns_max_rate),
|
||||
KUNIT_CASE(clk_divider_bestdiv_mux_ulong_max_returns_max_rate),
|
||||
{}
|
||||
};
|
||||
|
||||
static struct kunit_suite clk_divider_bestdiv_test_suite = {
|
||||
.name = "clk_divider_bestdiv",
|
||||
.test_cases = clk_divider_bestdiv_test_cases,
|
||||
};
|
||||
|
||||
kunit_test_suite(clk_divider_bestdiv_test_suite);
|
||||
|
||||
MODULE_DESCRIPTION("KUnit tests for clk divider");
|
||||
MODULE_LICENSE("GPL");
|
||||
+33
-10
@@ -57,6 +57,7 @@
|
||||
|
||||
#define REG_RST_CTRL2 0x830
|
||||
#define REG_RST_CTRL1 0x834
|
||||
#define REG_PCIE_HB_RST BIT(29)
|
||||
#define EN751221_REG_RST_DMT 0x84
|
||||
#define EN751221_REG_RST_USB 0xec
|
||||
|
||||
@@ -338,6 +339,7 @@ static const struct en_clk_desc en7581_base_clks[] = {
|
||||
static const u16 en7581_rst_ofs[] = {
|
||||
REG_RST_CTRL2,
|
||||
REG_RST_CTRL1,
|
||||
REG_NP_SCU_PCIC,
|
||||
};
|
||||
|
||||
static const u16 en751221_rst_ofs[] = {
|
||||
@@ -450,6 +452,11 @@ static const u16 en7581_rst_map[] = {
|
||||
[EN7581_CPU_TIMER_RST] = RST_NR_PER_BANK + 28,
|
||||
[EN7581_PCIE_HB_RST] = RST_NR_PER_BANK + 29,
|
||||
[EN7581_XPON_MAC_RST] = RST_NR_PER_BANK + 31,
|
||||
|
||||
/* RST_PCIC */
|
||||
[EN7581_PCIC_PERSTOUT0_RST] = 2 * RST_NR_PER_BANK + 29,
|
||||
[EN7581_PCIC_PERSTOUT1_RST] = 2 * RST_NR_PER_BANK + 26,
|
||||
[EN7581_PCIC_PERSTOUT2_RST] = 2 * RST_NR_PER_BANK + 16,
|
||||
};
|
||||
|
||||
static const u16 en751221_rst_map[] = {
|
||||
@@ -635,9 +642,7 @@ static int en7581_pci_enable(struct clk_hw *hw)
|
||||
void __iomem *np_base = cg->base;
|
||||
u32 val, mask;
|
||||
|
||||
mask = REG_PCI_CONTROL_REFCLK_EN0 | REG_PCI_CONTROL_REFCLK_EN1 |
|
||||
REG_PCI_CONTROL_PERSTOUT1 | REG_PCI_CONTROL_PERSTOUT2 |
|
||||
REG_PCI_CONTROL_PERSTOUT;
|
||||
mask = REG_PCI_CONTROL_REFCLK_EN0 | REG_PCI_CONTROL_REFCLK_EN1;
|
||||
val = readl(np_base + REG_PCI_CONTROL);
|
||||
writel(val | mask, np_base + REG_PCI_CONTROL);
|
||||
|
||||
@@ -650,9 +655,7 @@ static void en7581_pci_disable(struct clk_hw *hw)
|
||||
void __iomem *np_base = cg->base;
|
||||
u32 val, mask;
|
||||
|
||||
mask = REG_PCI_CONTROL_REFCLK_EN0 | REG_PCI_CONTROL_REFCLK_EN1 |
|
||||
REG_PCI_CONTROL_PERSTOUT1 | REG_PCI_CONTROL_PERSTOUT2 |
|
||||
REG_PCI_CONTROL_PERSTOUT;
|
||||
mask = REG_PCI_CONTROL_REFCLK_EN0 | REG_PCI_CONTROL_REFCLK_EN1;
|
||||
val = readl(np_base + REG_PCI_CONTROL);
|
||||
writel(val & ~mask, np_base + REG_PCI_CONTROL);
|
||||
usleep_range(1000, 2000);
|
||||
@@ -754,11 +757,17 @@ static int en7523_reset_update(struct reset_controller_dev *rcdev,
|
||||
unsigned long id, bool assert)
|
||||
{
|
||||
struct en_rst_data *rst_data = container_of(rcdev, struct en_rst_data, rcdev);
|
||||
void __iomem *addr = rst_data->base + rst_data->bank_ofs[id / RST_NR_PER_BANK];
|
||||
u32 offset = rst_data->bank_ofs[id / RST_NR_PER_BANK];
|
||||
void __iomem *addr = rst_data->base + offset;
|
||||
bool inverted = false;
|
||||
u32 val;
|
||||
|
||||
/* For PCIC reset logic is inverted, 0:assert 1:deassert */
|
||||
if (offset == REG_NP_SCU_PCIC)
|
||||
inverted = true;
|
||||
|
||||
val = readl(addr);
|
||||
if (assert)
|
||||
if (assert ^ inverted)
|
||||
val |= BIT(id % RST_NR_PER_BANK);
|
||||
else
|
||||
val &= ~BIT(id % RST_NR_PER_BANK);
|
||||
@@ -783,9 +792,17 @@ static int en7523_reset_status(struct reset_controller_dev *rcdev,
|
||||
unsigned long id)
|
||||
{
|
||||
struct en_rst_data *rst_data = container_of(rcdev, struct en_rst_data, rcdev);
|
||||
void __iomem *addr = rst_data->base + rst_data->bank_ofs[id / RST_NR_PER_BANK];
|
||||
u32 offset = rst_data->bank_ofs[id / RST_NR_PER_BANK];
|
||||
void __iomem *addr = rst_data->base + offset;
|
||||
bool inverted = false;
|
||||
u32 val;
|
||||
|
||||
return !!(readl(addr) & BIT(id % RST_NR_PER_BANK));
|
||||
/* For PCIC reset logic is inverted, 0:assert 1:deassert */
|
||||
if (offset == REG_NP_SCU_PCIC)
|
||||
inverted = true;
|
||||
|
||||
val = readl(addr) & BIT(id % RST_NR_PER_BANK);
|
||||
return inverted ? !val : !!val;
|
||||
}
|
||||
|
||||
static int en7523_reset_xlate(struct reset_controller_dev *rcdev,
|
||||
@@ -853,6 +870,12 @@ static int en7581_clk_hw_init(struct platform_device *pdev,
|
||||
val = readl(base + REG_NP_SCU_PCIC);
|
||||
writel(val | 3, base + REG_NP_SCU_PCIC);
|
||||
|
||||
val = readl(base + REG_RST_CTRL1);
|
||||
val |= REG_PCIE_HB_RST;
|
||||
writel(val, base + REG_RST_CTRL1);
|
||||
val &= ~REG_PCIE_HB_RST;
|
||||
writel(val, base + REG_RST_CTRL1);
|
||||
|
||||
return en7581_reset_register(&pdev->dev, base, en7581_rst_map,
|
||||
ARRAY_SIZE(en7581_rst_map),
|
||||
en7581_rst_ofs);
|
||||
|
||||
@@ -2227,6 +2227,7 @@ static int k230_clk_set_rate_mul(struct clk_hw *hw, unsigned long rate,
|
||||
guard(spinlock)(rate_self->lock);
|
||||
|
||||
mul_reg = readl(rate_self->reg + clk->mul_reg_off);
|
||||
mul_reg &= ~(rate_self->mul_mask << rate_self->mul_shift);
|
||||
mul_reg |= ((mul - 1) & rate_self->mul_mask) << (rate_self->mul_shift);
|
||||
mul_reg |= BIT(rate_self->write_enable_bit);
|
||||
writel(mul_reg, rate_self->reg + clk->mul_reg_off);
|
||||
@@ -2257,6 +2258,7 @@ static int k230_clk_set_rate_div(struct clk_hw *hw, unsigned long rate,
|
||||
guard(spinlock)(rate_self->lock);
|
||||
|
||||
div_reg = readl(rate_self->reg + clk->div_reg_off);
|
||||
div_reg &= ~(rate_self->div_mask << rate_self->div_shift);
|
||||
div_reg |= ((div - 1) & rate_self->div_mask) << (rate_self->div_shift);
|
||||
div_reg |= BIT(rate_self->write_enable_bit);
|
||||
writel(div_reg, rate_self->reg + clk->div_reg_off);
|
||||
@@ -2287,11 +2289,13 @@ static int k230_clk_set_rate_mul_div(struct clk_hw *hw, unsigned long rate,
|
||||
guard(spinlock)(rate_self->lock);
|
||||
|
||||
div_reg = readl(rate_self->reg + clk->div_reg_off);
|
||||
div_reg &= ~(rate_self->div_mask << rate_self->div_shift);
|
||||
div_reg |= ((div - 1) & rate_self->div_mask) << (rate_self->div_shift);
|
||||
div_reg |= BIT(rate_self->write_enable_bit);
|
||||
writel(div_reg, rate_self->reg + clk->div_reg_off);
|
||||
|
||||
mul_reg = readl(rate_self->reg + clk->mul_reg_off);
|
||||
mul_reg &= ~(rate_self->mul_mask << rate_self->mul_shift);
|
||||
mul_reg |= ((mul - 1) & rate_self->mul_mask) << (rate_self->mul_shift);
|
||||
mul_reg |= BIT(rate_self->write_enable_bit);
|
||||
writel(mul_reg, rate_self->reg + clk->mul_reg_off);
|
||||
|
||||
+14
-25
@@ -175,10 +175,6 @@
|
||||
#define LMK04832_REG_RB_HOLDOVER 0x188
|
||||
#define LMK04832_REG_SPI_LOCK 0x555
|
||||
|
||||
enum lmk04832_device_types {
|
||||
LMK04832,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct lmk04832_device_info - Holds static device information that is
|
||||
* specific to the chip revision
|
||||
@@ -197,14 +193,12 @@ struct lmk04832_device_info {
|
||||
unsigned int vco1_range[2];
|
||||
};
|
||||
|
||||
static const struct lmk04832_device_info lmk04832_device_info[] = {
|
||||
[LMK04832] = {
|
||||
.pid = 0x63d1, /* WARNING PROD_ID is inverted in the datasheet */
|
||||
.maskrev = 0x70,
|
||||
.num_channels = 14,
|
||||
.vco0_range = { 2440, 2580 },
|
||||
.vco1_range = { 2945, 3255 },
|
||||
},
|
||||
static const struct lmk04832_device_info lmk04832_device_info = {
|
||||
.pid = 0x63d1, /* WARNING PROD_ID is inverted in the datasheet */
|
||||
.maskrev = 0x70,
|
||||
.num_channels = 14,
|
||||
.vco0_range = { 2440, 2580 },
|
||||
.vco1_range = { 2945, 3255 },
|
||||
};
|
||||
|
||||
enum lmk04832_rdbk_type {
|
||||
@@ -422,11 +416,10 @@ static unsigned long lmk04832_vco_recalc_rate(struct clk_hw *hw,
|
||||
*/
|
||||
static int lmk04832_check_vco_ranges(struct lmk04832 *lmk, unsigned long rate)
|
||||
{
|
||||
struct spi_device *spi = to_spi_device(lmk->dev);
|
||||
const struct lmk04832_device_info *info;
|
||||
unsigned long mhz = rate / 1000000;
|
||||
|
||||
info = &lmk04832_device_info[spi_get_device_id(spi)->driver_data];
|
||||
info = &lmk04832_device_info;
|
||||
|
||||
if (mhz >= info->vco0_range[0] && mhz <= info->vco0_range[1])
|
||||
return LMK04832_VAL_VCO_MUX_VCO0;
|
||||
@@ -822,13 +815,6 @@ static int lmk04832_sclk_sync_sequence(struct lmk04832 *lmk)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = regmap_update_bits(lmk->regmap, LMK04832_REG_SYNC,
|
||||
LMK04832_BIT_SYNC_MODE,
|
||||
FIELD_PREP(LMK04832_BIT_SYNC_MODE,
|
||||
lmk->sync_mode));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* 9. (optional) if SCLKx_y_DIS_MODE was used to mute SYSREF outputs
|
||||
* during the SYNC event, restore SCLKx_y_DIS_MODE=0 for active state,
|
||||
@@ -843,7 +829,10 @@ static int lmk04832_sclk_sync_sequence(struct lmk04832 *lmk)
|
||||
* SYNC pulse to delay the output by some number of VCO counts).
|
||||
*/
|
||||
|
||||
return ret;
|
||||
return regmap_update_bits(lmk->regmap, LMK04832_REG_SYNC,
|
||||
LMK04832_BIT_SYNC_MODE,
|
||||
FIELD_PREP(LMK04832_BIT_SYNC_MODE,
|
||||
lmk->sync_mode));
|
||||
}
|
||||
|
||||
static int lmk04832_sclk_is_enabled(struct clk_hw *hw)
|
||||
@@ -1405,7 +1394,7 @@ static int lmk04832_probe(struct spi_device *spi)
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
info = &lmk04832_device_info[spi_get_device_id(spi)->driver_data];
|
||||
info = &lmk04832_device_info;
|
||||
|
||||
lmk = devm_kzalloc(&spi->dev, sizeof(struct lmk04832), GFP_KERNEL);
|
||||
if (!lmk)
|
||||
@@ -1553,8 +1542,8 @@ static int lmk04832_probe(struct spi_device *spi)
|
||||
}
|
||||
|
||||
static const struct spi_device_id lmk04832_id[] = {
|
||||
{ "lmk04832", LMK04832 },
|
||||
{}
|
||||
{ .name = "lmk04832" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(spi, lmk04832_id);
|
||||
|
||||
|
||||
@@ -264,10 +264,10 @@ static int max77686_clk_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
static const struct platform_device_id max77686_clk_id[] = {
|
||||
{ "max77686-clk", .driver_data = CHIP_MAX77686, },
|
||||
{ "max77802-clk", .driver_data = CHIP_MAX77802, },
|
||||
{ "max77620-clock", .driver_data = CHIP_MAX77620, },
|
||||
{},
|
||||
{ .name = "max77686-clk", .driver_data = CHIP_MAX77686 },
|
||||
{ .name = "max77802-clk", .driver_data = CHIP_MAX77802 },
|
||||
{ .name = "max77620-clock", .driver_data = CHIP_MAX77620 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(platform, max77686_clk_id);
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@ static void __init moxart_of_pll_clk_init(struct device_node *node)
|
||||
{
|
||||
void __iomem *base;
|
||||
struct clk_hw *hw;
|
||||
struct clk *ref_clk;
|
||||
unsigned int mul;
|
||||
const char *name = node->name;
|
||||
const char *parent_name;
|
||||
@@ -34,12 +33,6 @@ static void __init moxart_of_pll_clk_init(struct device_node *node)
|
||||
mul = readl(base + 0x30) >> 3 & 0x3f;
|
||||
iounmap(base);
|
||||
|
||||
ref_clk = of_clk_get(node, 0);
|
||||
if (IS_ERR(ref_clk)) {
|
||||
pr_err("%pOF: of_clk_get failed\n", node);
|
||||
return;
|
||||
}
|
||||
|
||||
hw = clk_hw_register_fixed_factor(NULL, name, parent_name, 0, mul, 1);
|
||||
if (IS_ERR(hw)) {
|
||||
pr_err("%pOF: failed to register clock\n", node);
|
||||
@@ -56,7 +49,6 @@ static void __init moxart_of_apb_clk_init(struct device_node *node)
|
||||
{
|
||||
void __iomem *base;
|
||||
struct clk_hw *hw;
|
||||
struct clk *pll_clk;
|
||||
unsigned int div, val;
|
||||
unsigned int div_idx[] = { 2, 3, 4, 6, 8};
|
||||
const char *name = node->name;
|
||||
@@ -78,12 +70,6 @@ static void __init moxart_of_apb_clk_init(struct device_node *node)
|
||||
val = 0;
|
||||
div = div_idx[val] * 2;
|
||||
|
||||
pll_clk = of_clk_get(node, 0);
|
||||
if (IS_ERR(pll_clk)) {
|
||||
pr_err("%pOF: of_clk_get failed\n", node);
|
||||
return;
|
||||
}
|
||||
|
||||
hw = clk_hw_register_fixed_factor(NULL, name, parent_name, 0, 1, div);
|
||||
if (IS_ERR(hw)) {
|
||||
pr_err("%pOF: failed to register clock\n", node);
|
||||
|
||||
@@ -194,6 +194,13 @@ static void palmas_clks_get_clk_data(struct platform_device *pdev,
|
||||
cinfo->ext_control_pin = prop;
|
||||
}
|
||||
|
||||
static void palmas_clks_unprepare_ext_control(void *data)
|
||||
{
|
||||
struct palmas_clock_info *cinfo = data;
|
||||
|
||||
clk_unprepare(cinfo->hw.clk);
|
||||
}
|
||||
|
||||
static int palmas_clks_init_configure(struct palmas_clock_info *cinfo)
|
||||
{
|
||||
int ret;
|
||||
@@ -214,13 +221,18 @@ static int palmas_clks_init_configure(struct palmas_clock_info *cinfo)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = devm_add_action_or_reset(cinfo->dev,
|
||||
palmas_clks_unprepare_ext_control,
|
||||
cinfo);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = palmas_ext_control_req_config(cinfo->palmas,
|
||||
cinfo->clk_desc->sleep_reqstr_id,
|
||||
cinfo->ext_control_pin, true);
|
||||
if (ret < 0) {
|
||||
dev_err(cinfo->dev, "Ext config for %s failed, %d\n",
|
||||
cinfo->clk_desc->clk_name, ret);
|
||||
clk_unprepare(cinfo->hw.clk);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@@ -230,7 +242,6 @@ static int palmas_clks_init_configure(struct palmas_clock_info *cinfo)
|
||||
static int palmas_clks_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct palmas *palmas = dev_get_drvdata(pdev->dev.parent);
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
const struct palmas_clks_of_match_data *match_data;
|
||||
struct palmas_clock_info *cinfo;
|
||||
int ret;
|
||||
@@ -264,24 +275,19 @@ static int palmas_clks_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = of_clk_add_hw_provider(node, of_clk_hw_simple_get, &cinfo->hw);
|
||||
ret = devm_of_clk_add_hw_provider(&pdev->dev, of_clk_hw_simple_get,
|
||||
&cinfo->hw);
|
||||
if (ret < 0)
|
||||
dev_err(&pdev->dev, "Fail to add clock driver, %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void palmas_clks_remove(struct platform_device *pdev)
|
||||
{
|
||||
of_clk_del_provider(pdev->dev.of_node);
|
||||
}
|
||||
|
||||
static struct platform_driver palmas_clks_driver = {
|
||||
.driver = {
|
||||
.name = "palmas-clk",
|
||||
.of_match_table = palmas_clks_of_match,
|
||||
},
|
||||
.probe = palmas_clks_probe,
|
||||
.remove = palmas_clks_remove,
|
||||
};
|
||||
|
||||
module_platform_driver(palmas_clks_driver);
|
||||
|
||||
@@ -394,9 +394,9 @@ static const struct rs9_chip_info renesas_9fgv0841_info = {
|
||||
};
|
||||
|
||||
static const struct i2c_device_id rs9_id[] = {
|
||||
{ "9fgv0241", .driver_data = (kernel_ulong_t)&renesas_9fgv0241_info },
|
||||
{ "9fgv0441", .driver_data = (kernel_ulong_t)&renesas_9fgv0441_info },
|
||||
{ "9fgv0841", .driver_data = (kernel_ulong_t)&renesas_9fgv0841_info },
|
||||
{ .name = "9fgv0241", .driver_data = (kernel_ulong_t)&renesas_9fgv0241_info },
|
||||
{ .name = "9fgv0441", .driver_data = (kernel_ulong_t)&renesas_9fgv0441_info },
|
||||
{ .name = "9fgv0841", .driver_data = (kernel_ulong_t)&renesas_9fgv0841_info },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, rs9_id);
|
||||
|
||||
@@ -1174,12 +1174,6 @@ static unsigned long rp1_varsrc_recalc_rate(struct clk_hw *hw,
|
||||
return clock->cached_rate;
|
||||
}
|
||||
|
||||
static int rp1_varsrc_determine_rate(struct clk_hw *hw,
|
||||
struct clk_rate_request *req)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct clk_ops rp1_pll_core_ops = {
|
||||
.is_prepared = rp1_pll_core_is_on,
|
||||
.prepare = rp1_pll_core_on,
|
||||
@@ -1227,7 +1221,7 @@ static const struct clk_ops rp1_clk_ops = {
|
||||
static const struct clk_ops rp1_varsrc_ops = {
|
||||
.set_rate = rp1_varsrc_set_rate,
|
||||
.recalc_rate = rp1_varsrc_recalc_rate,
|
||||
.determine_rate = rp1_varsrc_determine_rate,
|
||||
.determine_rate = clk_determine_rate_noop,
|
||||
};
|
||||
|
||||
static struct clk_hw *rp1_register_pll(struct rp1_clockman *clockman,
|
||||
|
||||
@@ -225,12 +225,12 @@ static void s2mps11_clk_remove(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
static const struct platform_device_id s2mps11_clk_id[] = {
|
||||
{ "s2mpg10-clk", S2MPG10},
|
||||
{ "s2mps11-clk", S2MPS11X},
|
||||
{ "s2mps13-clk", S2MPS13X},
|
||||
{ "s2mps14-clk", S2MPS14X},
|
||||
{ "s5m8767-clk", S5M8767X},
|
||||
{ },
|
||||
{ .name = "s2mpg10-clk", .driver_data = S2MPG10 },
|
||||
{ .name = "s2mps11-clk", .driver_data = S2MPS11X },
|
||||
{ .name = "s2mps13-clk", .driver_data = S2MPS13X },
|
||||
{ .name = "s2mps14-clk", .driver_data = S2MPS14X },
|
||||
{ .name = "s5m8767-clk", .driver_data = S5M8767X },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(platform, s2mps11_clk_id);
|
||||
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* The Vendor OEM extension for System Control and Power Interface (SCMI)
|
||||
* Protocol based clock driver
|
||||
*
|
||||
* Copyright 2025 NXP
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/scmi_imx_protocol.h>
|
||||
#include <linux/scmi_protocol.h>
|
||||
|
||||
#include "clk-scmi.h"
|
||||
|
||||
#define SCMI_CLOCK_CFG_IMX_SSC 0x80
|
||||
#define SCMI_CLOCK_IMX_SS_PERCENTAGE_MASK GENMASK(7, 0)
|
||||
#define SCMI_CLOCK_IMX_SS_MOD_FREQ_MASK GENMASK(23, 8)
|
||||
#define SCMI_CLOCK_IMX_SS_ENABLE_MASK BIT(24)
|
||||
|
||||
/*
|
||||
* Selection is based on SCMI vendor_id/sub_vendor_id and optional machine
|
||||
* compatible string, without involving impl_ver. impl_ver‑specific behavior
|
||||
* should be considered a bug and handled via SCMI Quirk framework.
|
||||
*/
|
||||
struct scmi_clk_oem_info {
|
||||
char *vendor_id;
|
||||
char *sub_vendor_id;
|
||||
char *compatible;
|
||||
const void *data;
|
||||
};
|
||||
|
||||
static int
|
||||
scmi_clk_imx_set_spread_spectrum(struct clk_hw *hw,
|
||||
const struct clk_spread_spectrum *ss_conf)
|
||||
{
|
||||
struct scmi_clk *clk = to_scmi_clk(hw);
|
||||
int ret;
|
||||
u32 val;
|
||||
|
||||
/*
|
||||
* extConfigValue[7:0] - spread percentage (%)
|
||||
* extConfigValue[23:8] - Modulation Frequency
|
||||
* extConfigValue[24] - Enable/Disable
|
||||
* extConfigValue[31:25] - Reserved
|
||||
*/
|
||||
val = FIELD_PREP(SCMI_CLOCK_IMX_SS_PERCENTAGE_MASK, ss_conf->spread_bp / 10000);
|
||||
val |= FIELD_PREP(SCMI_CLOCK_IMX_SS_MOD_FREQ_MASK, ss_conf->modfreq_hz);
|
||||
if (ss_conf->method != CLK_SPREAD_NO)
|
||||
val |= SCMI_CLOCK_IMX_SS_ENABLE_MASK;
|
||||
ret = scmi_proto_clk_ops->config_oem_set(clk->ph, clk->id,
|
||||
SCMI_CLOCK_CFG_IMX_SSC,
|
||||
val, false);
|
||||
if (ret)
|
||||
dev_warn(clk->dev,
|
||||
"Failed to set spread spectrum(%u,%u,%u) for clock ID %d\n",
|
||||
ss_conf->modfreq_hz, ss_conf->spread_bp, ss_conf->method,
|
||||
clk->id);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
scmi_clk_imx_query_oem_feats(const struct scmi_protocol_handle *ph, u32 id,
|
||||
unsigned int *feats_key)
|
||||
{
|
||||
int ret;
|
||||
u32 val;
|
||||
|
||||
ret = scmi_proto_clk_ops->config_oem_get(ph, id,
|
||||
SCMI_CLOCK_CFG_IMX_SSC,
|
||||
&val, NULL, false);
|
||||
if (!ret)
|
||||
*feats_key |= BIT(SCMI_CLK_EXT_OEM_SSC_SUPPORTED);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct scmi_clk_oem scmi_clk_oem_imx = {
|
||||
.query_ext_oem_feats = scmi_clk_imx_query_oem_feats,
|
||||
.set_spread_spectrum = scmi_clk_imx_set_spread_spectrum,
|
||||
};
|
||||
|
||||
static const struct scmi_clk_oem_info info[] = {
|
||||
{ SCMI_IMX_VENDOR, SCMI_IMX_SUBVENDOR, NULL, &scmi_clk_oem_imx },
|
||||
};
|
||||
|
||||
int scmi_clk_oem_init(struct scmi_device *sdev)
|
||||
{
|
||||
const struct scmi_handle *handle = sdev->handle;
|
||||
int i, size = ARRAY_SIZE(info);
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
if (strcmp(handle->version->vendor_id, info[i].vendor_id) ||
|
||||
strcmp(handle->version->sub_vendor_id, info[i].sub_vendor_id))
|
||||
continue;
|
||||
if (info[i].compatible &&
|
||||
!of_machine_is_compatible(info[i].compatible))
|
||||
continue;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (i < size)
|
||||
dev_set_drvdata(&sdev->dev, (void *)info[i].data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
+16
-28
@@ -13,32 +13,9 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/scmi_protocol.h>
|
||||
|
||||
#define NOT_ATOMIC false
|
||||
#define ATOMIC true
|
||||
#include "clk-scmi.h"
|
||||
|
||||
enum scmi_clk_feats {
|
||||
SCMI_CLK_ATOMIC_SUPPORTED,
|
||||
SCMI_CLK_STATE_CTRL_SUPPORTED,
|
||||
SCMI_CLK_RATE_CTRL_SUPPORTED,
|
||||
SCMI_CLK_PARENT_CTRL_SUPPORTED,
|
||||
SCMI_CLK_DUTY_CYCLE_SUPPORTED,
|
||||
SCMI_CLK_FEATS_COUNT
|
||||
};
|
||||
|
||||
#define SCMI_MAX_CLK_OPS BIT(SCMI_CLK_FEATS_COUNT)
|
||||
|
||||
static const struct scmi_clk_proto_ops *scmi_proto_clk_ops;
|
||||
|
||||
struct scmi_clk {
|
||||
u32 id;
|
||||
struct device *dev;
|
||||
struct clk_hw hw;
|
||||
const struct scmi_clock_info *info;
|
||||
const struct scmi_protocol_handle *ph;
|
||||
struct clk_parent_data *parent_data;
|
||||
};
|
||||
|
||||
#define to_scmi_clk(clk) container_of(clk, struct scmi_clk, hw)
|
||||
const struct scmi_clk_proto_ops *scmi_proto_clk_ops;
|
||||
|
||||
static unsigned long scmi_clk_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
@@ -235,6 +212,7 @@ static int scmi_clk_ops_init(struct device *dev, struct scmi_clk *sclk,
|
||||
static const struct clk_ops *
|
||||
scmi_clk_ops_alloc(struct device *dev, unsigned long feats_key)
|
||||
{
|
||||
struct scmi_clk_oem *oem_data = dev_get_drvdata(dev);
|
||||
struct clk_ops *ops;
|
||||
|
||||
ops = devm_kzalloc(dev, sizeof(*ops), GFP_KERNEL);
|
||||
@@ -281,11 +259,15 @@ scmi_clk_ops_alloc(struct device *dev, unsigned long feats_key)
|
||||
ops->set_duty_cycle = scmi_clk_set_duty_cycle;
|
||||
}
|
||||
|
||||
if (oem_data && (feats_key & BIT(SCMI_CLK_EXT_OEM_SSC_SUPPORTED)))
|
||||
ops->set_spread_spectrum = oem_data->set_spread_spectrum;
|
||||
|
||||
return ops;
|
||||
}
|
||||
|
||||
/**
|
||||
* scmi_clk_ops_select() - Select a proper set of clock operations
|
||||
* @sdev: pointer to the SCMI device
|
||||
* @sclk: A reference to an SCMI clock descriptor
|
||||
* @atomic_capable: A flag to indicate if atomic mode is supported by the
|
||||
* transport
|
||||
@@ -310,8 +292,8 @@ scmi_clk_ops_alloc(struct device *dev, unsigned long feats_key)
|
||||
* NULL otherwise.
|
||||
*/
|
||||
static const struct clk_ops *
|
||||
scmi_clk_ops_select(struct scmi_clk *sclk, bool atomic_capable,
|
||||
unsigned int atomic_threshold_us,
|
||||
scmi_clk_ops_select(struct scmi_device *sdev, struct scmi_clk *sclk,
|
||||
bool atomic_capable, unsigned int atomic_threshold_us,
|
||||
const struct clk_ops **clk_ops_db, size_t db_size)
|
||||
{
|
||||
int ret;
|
||||
@@ -319,6 +301,7 @@ scmi_clk_ops_select(struct scmi_clk *sclk, bool atomic_capable,
|
||||
const struct scmi_clock_info *ci = sclk->info;
|
||||
unsigned int feats_key = 0;
|
||||
const struct clk_ops *ops;
|
||||
struct scmi_clk_oem *oem_data = dev_get_drvdata(&sdev->dev);
|
||||
|
||||
/*
|
||||
* Note that when transport is atomic but SCMI protocol did not
|
||||
@@ -343,6 +326,9 @@ scmi_clk_ops_select(struct scmi_clk *sclk, bool atomic_capable,
|
||||
&val, NULL, false);
|
||||
if (!ret)
|
||||
feats_key |= BIT(SCMI_CLK_DUTY_CYCLE_SUPPORTED);
|
||||
|
||||
if (oem_data && oem_data->query_ext_oem_feats)
|
||||
oem_data->query_ext_oem_feats(sclk->ph, sclk->id, &feats_key);
|
||||
}
|
||||
|
||||
if (WARN_ON(feats_key >= db_size))
|
||||
@@ -400,6 +386,8 @@ static int scmi_clocks_probe(struct scmi_device *sdev)
|
||||
clk_data->num = count;
|
||||
hws = clk_data->hws;
|
||||
|
||||
scmi_clk_oem_init(sdev);
|
||||
|
||||
transport_is_atomic = handle->is_transport_atomic(handle,
|
||||
&atomic_threshold_us);
|
||||
|
||||
@@ -431,7 +419,7 @@ static int scmi_clocks_probe(struct scmi_device *sdev)
|
||||
* to avoid sharing the devm_ allocated clk_ops between multiple
|
||||
* SCMI clk driver instances.
|
||||
*/
|
||||
scmi_ops = scmi_clk_ops_select(sclk, transport_is_atomic,
|
||||
scmi_ops = scmi_clk_ops_select(sdev, sclk, transport_is_atomic,
|
||||
atomic_threshold_us,
|
||||
scmi_clk_ops_db,
|
||||
ARRAY_SIZE(scmi_clk_ops_db));
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright 2025 NXP
|
||||
*/
|
||||
|
||||
#ifndef __SCMI_CLK_H
|
||||
#define __SCMI_CLK_H
|
||||
|
||||
#include <linux/bits.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/scmi_protocol.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#define NOT_ATOMIC false
|
||||
#define ATOMIC true
|
||||
|
||||
enum scmi_clk_feats {
|
||||
SCMI_CLK_ATOMIC_SUPPORTED,
|
||||
SCMI_CLK_STATE_CTRL_SUPPORTED,
|
||||
SCMI_CLK_RATE_CTRL_SUPPORTED,
|
||||
SCMI_CLK_PARENT_CTRL_SUPPORTED,
|
||||
SCMI_CLK_DUTY_CYCLE_SUPPORTED,
|
||||
SCMI_CLK_EXT_OEM_SSC_SUPPORTED,
|
||||
SCMI_CLK_FEATS_COUNT
|
||||
};
|
||||
|
||||
#define SCMI_MAX_CLK_OPS BIT(SCMI_CLK_FEATS_COUNT)
|
||||
|
||||
struct scmi_clk {
|
||||
u32 id;
|
||||
struct device *dev;
|
||||
struct clk_hw hw;
|
||||
const struct scmi_clock_info *info;
|
||||
const struct scmi_protocol_handle *ph;
|
||||
struct clk_parent_data *parent_data;
|
||||
};
|
||||
|
||||
#define to_scmi_clk(clk) container_of(clk, struct scmi_clk, hw)
|
||||
|
||||
extern const struct scmi_clk_proto_ops *scmi_proto_clk_ops;
|
||||
|
||||
struct scmi_clk_oem {
|
||||
int (*query_ext_oem_feats)(const struct scmi_protocol_handle *ph,
|
||||
u32 id, unsigned int *feats_key);
|
||||
int (*set_spread_spectrum)(struct clk_hw *hw,
|
||||
const struct clk_spread_spectrum *ss_conf);
|
||||
};
|
||||
|
||||
int scmi_clk_oem_init(struct scmi_device *dev);
|
||||
|
||||
#endif
|
||||
+1
-13
@@ -32,18 +32,6 @@ static unsigned long scpi_clk_recalc_rate(struct clk_hw *hw,
|
||||
return clk->scpi_ops->clk_get_val(clk->id);
|
||||
}
|
||||
|
||||
static int scpi_clk_determine_rate(struct clk_hw *hw,
|
||||
struct clk_rate_request *req)
|
||||
{
|
||||
/*
|
||||
* We can't figure out what rate it will be, so just return the
|
||||
* rate back to the caller. scpi_clk_recalc_rate() will be called
|
||||
* after the rate is set and we'll know what rate the clock is
|
||||
* running at then.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int scpi_clk_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
@@ -54,7 +42,7 @@ static int scpi_clk_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
|
||||
static const struct clk_ops scpi_clk_ops = {
|
||||
.recalc_rate = scpi_clk_recalc_rate,
|
||||
.determine_rate = scpi_clk_determine_rate,
|
||||
.determine_rate = clk_determine_rate_noop,
|
||||
.set_rate = scpi_clk_set_rate,
|
||||
};
|
||||
|
||||
|
||||
@@ -379,7 +379,7 @@ static int si514_probe(struct i2c_client *client)
|
||||
}
|
||||
|
||||
static const struct i2c_device_id si514_id[] = {
|
||||
{ "si514" },
|
||||
{ .name = "si514" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, si514_id);
|
||||
|
||||
@@ -364,9 +364,9 @@ static int __maybe_unused si521xx_resume(struct device *dev)
|
||||
}
|
||||
|
||||
static const struct i2c_device_id si521xx_id[] = {
|
||||
{ "si52144", .driver_data = SI521XX_OE_MAP(0x5, 0xc0) },
|
||||
{ "si52146", .driver_data = SI521XX_OE_MAP(0x15, 0xe0) },
|
||||
{ "si52147", .driver_data = SI521XX_OE_MAP(0x17, 0xf8) },
|
||||
{ .name = "si52144", .driver_data = SI521XX_OE_MAP(0x5, 0xc0) },
|
||||
{ .name = "si52146", .driver_data = SI521XX_OE_MAP(0x15, 0xe0) },
|
||||
{ .name = "si52147", .driver_data = SI521XX_OE_MAP(0x17, 0xf8) },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, si521xx_id);
|
||||
|
||||
@@ -1825,11 +1825,11 @@ static void si5341_remove(struct i2c_client *client)
|
||||
}
|
||||
|
||||
static const struct i2c_device_id si5341_id[] = {
|
||||
{ "si5340", 0 },
|
||||
{ "si5341", 1 },
|
||||
{ "si5342", 2 },
|
||||
{ "si5344", 4 },
|
||||
{ "si5345", 5 },
|
||||
{ .name = "si5340" },
|
||||
{ .name = "si5341" },
|
||||
{ .name = "si5342" },
|
||||
{ .name = "si5344" },
|
||||
{ .name = "si5345" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, si5341_id);
|
||||
|
||||
@@ -1425,10 +1425,10 @@ si53351_of_clk_get(struct of_phandle_args *clkspec, void *data)
|
||||
#endif /* CONFIG_OF */
|
||||
|
||||
static const struct i2c_device_id si5351_i2c_ids[] = {
|
||||
{ "si5351a", SI5351_VARIANT_A },
|
||||
{ "si5351a-msop", SI5351_VARIANT_A3 },
|
||||
{ "si5351b", SI5351_VARIANT_B },
|
||||
{ "si5351c", SI5351_VARIANT_C },
|
||||
{ .name = "si5351a", .driver_data = SI5351_VARIANT_A },
|
||||
{ .name = "si5351a-msop", .driver_data = SI5351_VARIANT_A3 },
|
||||
{ .name = "si5351b", .driver_data = SI5351_VARIANT_B },
|
||||
{ .name = "si5351c", .driver_data = SI5351_VARIANT_C },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, si5351_i2c_ids);
|
||||
|
||||
+65
-17
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Driver for Silicon Labs Si544 Programmable Oscillator
|
||||
* Driver for Silicon Labs Si544/Si549 Programmable Oscillator
|
||||
* Copyright (C) 2018 Topic Embedded Products
|
||||
* Author: Mike Looijmans <mike.looijmans@topic.nl>
|
||||
*/
|
||||
@@ -40,7 +40,9 @@
|
||||
#define SI544_MIN_FREQ 200000U
|
||||
|
||||
/* Si544 Internal oscillator runs at 55.05 MHz */
|
||||
#define FXO 55050000U
|
||||
#define SI544_XO_FREQ 55050000U
|
||||
/* Si549 Internal oscilator runs at 152.60 MHz */
|
||||
#define SI549_XO_FREQ 152600000U
|
||||
|
||||
/* VCO range is 10.8 .. 12.1 GHz, max depends on speed grade */
|
||||
#define FVCO_MIN 10800000000ULL
|
||||
@@ -56,11 +58,16 @@
|
||||
#define DELTA_M_FRAC_NUM 19
|
||||
#define DELTA_M_FRAC_DEN 20000
|
||||
|
||||
struct si544_clk_desc {
|
||||
unsigned long max_freq;
|
||||
unsigned long xo_freq;
|
||||
};
|
||||
|
||||
struct clk_si544 {
|
||||
struct clk_hw hw;
|
||||
struct regmap *regmap;
|
||||
struct i2c_client *i2c_client;
|
||||
unsigned long max_freq;
|
||||
const struct si544_clk_desc *chip_info;
|
||||
};
|
||||
#define to_clk_si544(_hw) container_of(_hw, struct clk_si544, hw)
|
||||
|
||||
@@ -79,6 +86,7 @@ struct clk_si544_muldiv {
|
||||
u16 hs_div;
|
||||
u8 ls_div_bits;
|
||||
s32 delta_m;
|
||||
u32 xo_freq;
|
||||
};
|
||||
|
||||
/* Enables or disables the output driver */
|
||||
@@ -145,6 +153,8 @@ static int si544_get_muldiv(struct clk_si544 *data,
|
||||
settings->delta_m = reg[0] << 8 | reg[1] << 16 | reg[2] << 24;
|
||||
settings->delta_m >>= 8;
|
||||
|
||||
settings->xo_freq = data->chip_info->xo_freq;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -193,7 +203,7 @@ static bool is_valid_frequency(const struct clk_si544 *data,
|
||||
if (frequency < SI544_MIN_FREQ)
|
||||
return false;
|
||||
|
||||
return frequency <= data->max_freq;
|
||||
return frequency <= data->chip_info->max_freq;
|
||||
}
|
||||
|
||||
/* Calculate divider settings for a given frequency */
|
||||
@@ -201,6 +211,7 @@ static int si544_calc_muldiv(struct clk_si544_muldiv *settings,
|
||||
unsigned long frequency)
|
||||
{
|
||||
u64 vco;
|
||||
u32 fxo = settings->xo_freq;
|
||||
u32 ls_freq;
|
||||
u32 tmp;
|
||||
u8 res;
|
||||
@@ -238,13 +249,13 @@ static int si544_calc_muldiv(struct clk_si544_muldiv *settings,
|
||||
vco = (u64)ls_freq * settings->hs_div;
|
||||
|
||||
/* Calculate the integer part of the feedback divider */
|
||||
tmp = do_div(vco, FXO);
|
||||
tmp = do_div(vco, fxo);
|
||||
settings->fb_div_int = vco;
|
||||
|
||||
/* And the fractional bits using the remainder */
|
||||
vco = (u64)tmp << 32;
|
||||
vco += FXO / 2; /* Round to nearest multiple */
|
||||
do_div(vco, FXO);
|
||||
vco += fxo / 2; /* Round to nearest multiple */
|
||||
do_div(vco, fxo);
|
||||
settings->fb_div_frac = vco;
|
||||
|
||||
/* Reset the frequency adjustment */
|
||||
@@ -258,15 +269,16 @@ static unsigned long si544_calc_center_rate(
|
||||
const struct clk_si544_muldiv *settings)
|
||||
{
|
||||
u32 d = settings->hs_div * BIT(settings->ls_div_bits);
|
||||
u32 fxo = settings->xo_freq;
|
||||
u64 vco;
|
||||
|
||||
/* Calculate VCO from the fractional part */
|
||||
vco = (u64)settings->fb_div_frac * FXO;
|
||||
vco += (FXO / 2);
|
||||
vco = (u64)settings->fb_div_frac * fxo;
|
||||
vco += (fxo / 2);
|
||||
vco >>= 32;
|
||||
|
||||
/* Add the integer part of the VCO frequency */
|
||||
vco += (u64)settings->fb_div_int * FXO;
|
||||
vco += (u64)settings->fb_div_int * fxo;
|
||||
|
||||
/* Apply divider to obtain the generated frequency */
|
||||
do_div(vco, d);
|
||||
@@ -446,7 +458,7 @@ static int si544_probe(struct i2c_client *client)
|
||||
init.num_parents = 0;
|
||||
data->hw.init = &init;
|
||||
data->i2c_client = client;
|
||||
data->max_freq = (uintptr_t)i2c_get_match_data(client);
|
||||
data->chip_info = i2c_get_match_data(client);
|
||||
|
||||
if (of_property_read_string(client->dev.of_node, "clock-output-names",
|
||||
&init.name))
|
||||
@@ -478,18 +490,54 @@ static int si544_probe(struct i2c_client *client)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct si544_clk_desc clk_si544a_info = {
|
||||
.xo_freq = SI544_XO_FREQ,
|
||||
.max_freq = 1500000000,
|
||||
};
|
||||
|
||||
static const struct si544_clk_desc clk_si544b_info = {
|
||||
.xo_freq = SI544_XO_FREQ,
|
||||
.max_freq = 800000000,
|
||||
};
|
||||
|
||||
static const struct si544_clk_desc clk_si544c_info = {
|
||||
.xo_freq = SI544_XO_FREQ,
|
||||
.max_freq = 325000000,
|
||||
};
|
||||
|
||||
static const struct si544_clk_desc clk_si549a_info = {
|
||||
.xo_freq = SI549_XO_FREQ,
|
||||
.max_freq = 1500000000,
|
||||
};
|
||||
|
||||
static const struct si544_clk_desc clk_si549b_info = {
|
||||
.xo_freq = SI549_XO_FREQ,
|
||||
.max_freq = 800000000,
|
||||
};
|
||||
|
||||
static const struct si544_clk_desc clk_si549c_info = {
|
||||
.xo_freq = SI549_XO_FREQ,
|
||||
.max_freq = 325000000,
|
||||
};
|
||||
|
||||
static const struct i2c_device_id si544_id[] = {
|
||||
{ "si544a", 1500000000 },
|
||||
{ "si544b", 800000000 },
|
||||
{ "si544c", 350000000 },
|
||||
{ .name = "si544a", .driver_data = (kernel_ulong_t)&clk_si544a_info },
|
||||
{ .name = "si544b", .driver_data = (kernel_ulong_t)&clk_si544b_info },
|
||||
{ .name = "si544c", .driver_data = (kernel_ulong_t)&clk_si544c_info },
|
||||
{ .name = "si549a", .driver_data = (kernel_ulong_t)&clk_si549a_info },
|
||||
{ .name = "si549b", .driver_data = (kernel_ulong_t)&clk_si549b_info },
|
||||
{ .name = "si549c", .driver_data = (kernel_ulong_t)&clk_si549c_info },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, si544_id);
|
||||
|
||||
static const struct of_device_id clk_si544_of_match[] = {
|
||||
{ .compatible = "silabs,si544a", .data = (void *)1500000000 },
|
||||
{ .compatible = "silabs,si544b", .data = (void *)800000000 },
|
||||
{ .compatible = "silabs,si544c", .data = (void *)350000000 },
|
||||
{ .compatible = "silabs,si544a", .data = &clk_si544a_info },
|
||||
{ .compatible = "silabs,si544b", .data = &clk_si544b_info },
|
||||
{ .compatible = "silabs,si544c", .data = &clk_si544c_info },
|
||||
{ .compatible = "silabs,si549a", .data = &clk_si549a_info },
|
||||
{ .compatible = "silabs,si549b", .data = &clk_si549b_info },
|
||||
{ .compatible = "silabs,si549c", .data = &clk_si549c_info },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, clk_si544_of_match);
|
||||
|
||||
@@ -503,10 +503,10 @@ static const struct clk_si570_info clk_si590_info = {
|
||||
};
|
||||
|
||||
static const struct i2c_device_id si570_id[] = {
|
||||
{ "si570", (kernel_ulong_t)&clk_si570_info },
|
||||
{ "si571", (kernel_ulong_t)&clk_si570_info },
|
||||
{ "si598", (kernel_ulong_t)&clk_si590_info },
|
||||
{ "si599", (kernel_ulong_t)&clk_si590_info },
|
||||
{ .name = "si570", .driver_data = (kernel_ulong_t)&clk_si570_info },
|
||||
{ .name = "si571", .driver_data = (kernel_ulong_t)&clk_si570_info },
|
||||
{ .name = "si598", .driver_data = (kernel_ulong_t)&clk_si590_info },
|
||||
{ .name = "si599", .driver_data = (kernel_ulong_t)&clk_si590_info },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, si570_id);
|
||||
|
||||
@@ -1310,14 +1310,14 @@ static const struct vc5_chip_info idt_5p49v6975_info = {
|
||||
};
|
||||
|
||||
static const struct i2c_device_id vc5_id[] = {
|
||||
{ "5p49v5923", .driver_data = (kernel_ulong_t)&idt_5p49v5923_info },
|
||||
{ "5p49v5925", .driver_data = (kernel_ulong_t)&idt_5p49v5925_info },
|
||||
{ "5p49v5933", .driver_data = (kernel_ulong_t)&idt_5p49v5933_info },
|
||||
{ "5p49v5935", .driver_data = (kernel_ulong_t)&idt_5p49v5935_info },
|
||||
{ "5p49v60", .driver_data = (kernel_ulong_t)&idt_5p49v60_info },
|
||||
{ "5p49v6901", .driver_data = (kernel_ulong_t)&idt_5p49v6901_info },
|
||||
{ "5p49v6965", .driver_data = (kernel_ulong_t)&idt_5p49v6965_info },
|
||||
{ "5p49v6975", .driver_data = (kernel_ulong_t)&idt_5p49v6975_info },
|
||||
{ .name = "5p49v5923", .driver_data = (kernel_ulong_t)&idt_5p49v5923_info },
|
||||
{ .name = "5p49v5925", .driver_data = (kernel_ulong_t)&idt_5p49v5925_info },
|
||||
{ .name = "5p49v5933", .driver_data = (kernel_ulong_t)&idt_5p49v5933_info },
|
||||
{ .name = "5p49v5935", .driver_data = (kernel_ulong_t)&idt_5p49v5935_info },
|
||||
{ .name = "5p49v60", .driver_data = (kernel_ulong_t)&idt_5p49v60_info },
|
||||
{ .name = "5p49v6901", .driver_data = (kernel_ulong_t)&idt_5p49v6901_info },
|
||||
{ .name = "5p49v6965", .driver_data = (kernel_ulong_t)&idt_5p49v6965_info },
|
||||
{ .name = "5p49v6975", .driver_data = (kernel_ulong_t)&idt_5p49v6975_info },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, vc5_id);
|
||||
|
||||
@@ -1197,7 +1197,7 @@ static int vc7_probe(struct i2c_client *client)
|
||||
if (ret) {
|
||||
dev_err_probe(&client->dev, ret,
|
||||
"unable to register output %d\n", i);
|
||||
return ret;
|
||||
goto err_clk;
|
||||
}
|
||||
|
||||
switch (bank_src_map.type) {
|
||||
@@ -1288,8 +1288,8 @@ static const struct regmap_config vc7_regmap_config = {
|
||||
};
|
||||
|
||||
static const struct i2c_device_id vc7_i2c_id[] = {
|
||||
{ "rc21008a", .driver_data = (kernel_ulong_t)&vc7_rc21008a_info },
|
||||
{}
|
||||
{ .name = "rc21008a", .driver_data = (kernel_ulong_t)&vc7_rc21008a_info },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, vc7_i2c_id);
|
||||
|
||||
|
||||
+104
-8
@@ -63,6 +63,57 @@ struct clk_parent_map {
|
||||
int index;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct clk_core - The internal state of a clk in the clk tree.
|
||||
* @name: Unique name of the clk for identification.
|
||||
* @ops: Pointer to hardware-specific operations for this clk.
|
||||
* @hw: Pointer for traversing from a struct clk to its
|
||||
* corresponding hardware-specific structure.
|
||||
* @owner: Kernel module owning this clk (for reference counting).
|
||||
* @dev: Device associated with this clk (optional)
|
||||
* @rpm_node: Node for runtime power management list management.
|
||||
* @of_node: Device tree node associated with this clk (if applicable)
|
||||
* @parent: Pointer to the current parent in the clock tree.
|
||||
* @parents: Array of possible parents (for muxes/selectable parents).
|
||||
* @num_parents: Number of possible parents.
|
||||
* @new_parent_index: Index of the new parent during parent change operations.
|
||||
* @rate: Current cached clock rate (Hz).
|
||||
* @req_rate: The last rate requested by a call to clk_set_rate(). It's
|
||||
* initialized to clk_core->rate. It's also updated to
|
||||
* clk_core->rate every time the clock is reparented, and
|
||||
* when we're doing the orphan -> !orphan transition.
|
||||
* @new_rate: New rate to be set during a rate change operation.
|
||||
* @new_parent: Pointer to new parent during parent change. This is also
|
||||
* used when a clk's rate is changed.
|
||||
* @new_child: Pointer to new child during reparenting. This is also
|
||||
* used when a clk's rate is changed.
|
||||
* @flags: Clock property and capability flags. See
|
||||
* `clk framework flags`.
|
||||
* @orphan: True if this clk is currently orphaned.
|
||||
* @rpm_enabled: True if runtime power management is enabled for this clk.
|
||||
* @enable_count: Reference count of enables.
|
||||
* @prepare_count: Reference count of prepares.
|
||||
* @protect_count: Protection reference count against disable.
|
||||
* @min_rate: Minimum supported clock rate (Hz).
|
||||
* @max_rate: Maximum supported clock rate (Hz).
|
||||
* @accuracy: Accuracy of the clock rate (parts per billion).
|
||||
* @phase: Current phase (degrees).
|
||||
* @duty: Current duty cycle configuration (as ratio: num/den).
|
||||
* @children: All of the children of this clk.
|
||||
* @child_node: Node for linking as a child in the parent's list.
|
||||
* @hashtable_node: Node for hash table that allows fast clk lookup by name.
|
||||
* @clks: All of the clk consumers registered.
|
||||
* @notifier_count: Number of notifiers registered for this clk.
|
||||
* @dentry: DebugFS entry for this clk.
|
||||
* @debug_node: DebugFS node for this clk.
|
||||
* @ref: Reference count for structure lifetime management.
|
||||
*
|
||||
* Managed by the clk framework. Clk providers and consumers do not interact
|
||||
* with this structure directly. Instead, clk operations flow through the
|
||||
* framework and the framework manipulates this structure to keep track of
|
||||
* parent/child relationships, rate, enable state, etc.
|
||||
*
|
||||
*/
|
||||
struct clk_core {
|
||||
const char *name;
|
||||
const struct clk_ops *ops;
|
||||
@@ -882,6 +933,24 @@ int clk_hw_determine_rate_no_reparent(struct clk_hw *hw,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_hw_determine_rate_no_reparent);
|
||||
|
||||
/**
|
||||
* clk_determine_rate_noop - clk_ops::determine_rate noop implementation
|
||||
* @hw: clk to determine rate on
|
||||
* @req: rate request
|
||||
*
|
||||
* Noop determine rate for clocks where the rate rounding is handled by the
|
||||
* firmware/hardware, or the clock is capable of any rate. The requested rate is
|
||||
* passed through unchanged, and the actual rate will be learned via
|
||||
* recalc_rate() after the rate is set.
|
||||
*
|
||||
* Returns: 0 always
|
||||
*/
|
||||
int clk_determine_rate_noop(struct clk_hw *hw, struct clk_rate_request *req)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_determine_rate_noop);
|
||||
|
||||
/*** clk api ***/
|
||||
|
||||
static void clk_core_rate_unprotect(struct clk_core *core)
|
||||
@@ -1846,10 +1915,10 @@ static int __clk_notify(struct clk_core *core, unsigned long msg,
|
||||
}
|
||||
|
||||
/**
|
||||
* __clk_recalc_accuracies
|
||||
* __clk_recalc_accuracies - recalculate all accuracies in the clk subtree
|
||||
* @core: first clk in the subtree
|
||||
*
|
||||
* Walks the subtree of clks starting with clk and recalculates accuracies as
|
||||
* Walks the subtree of clks starting with @core and recalculates accuracies as
|
||||
* it goes. Note that if a clk does not implement the .recalc_accuracy
|
||||
* callback then it is assumed that the clock will take on the accuracy of its
|
||||
* parent.
|
||||
@@ -1919,16 +1988,16 @@ static unsigned long clk_recalc(struct clk_core *core,
|
||||
}
|
||||
|
||||
/**
|
||||
* __clk_recalc_rates
|
||||
* __clk_recalc_rates - recalculate all rates in the clk subtree
|
||||
* @core: first clk in the subtree
|
||||
* @update_req: Whether req_rate should be updated with the new rate
|
||||
* @msg: notification type (see include/linux/clk.h)
|
||||
*
|
||||
* Walks the subtree of clks starting with clk and recalculates rates as it
|
||||
* Walks the subtree of clks starting with @core and recalculates rates as it
|
||||
* goes. Note that if a clk does not implement the .recalc_rate callback then
|
||||
* it is assumed that the clock will take on the rate of its parent.
|
||||
*
|
||||
* clk_recalc_rates also propagates the POST_RATE_CHANGE notification,
|
||||
* __clk_recalc_rates also propagates the POST_RATE_CHANGE notification,
|
||||
* if necessary.
|
||||
*/
|
||||
static void __clk_recalc_rates(struct clk_core *core, bool update_req,
|
||||
@@ -2191,14 +2260,14 @@ static int __clk_set_parent(struct clk_core *core, struct clk_core *parent,
|
||||
}
|
||||
|
||||
/**
|
||||
* __clk_speculate_rates
|
||||
* __clk_speculate_rates - speculate all rates in the clk subtree
|
||||
* @core: first clk in the subtree
|
||||
* @parent_rate: the "future" rate of clk's parent
|
||||
*
|
||||
* Walks the subtree of clks starting with clk, speculating rates as it
|
||||
* Walks the subtree of clks starting with @core, speculating rates as it
|
||||
* goes and firing off PRE_RATE_CHANGE notifications as necessary.
|
||||
*
|
||||
* Unlike clk_recalc_rates, clk_speculate_rates exists only for sending
|
||||
* Unlike __clk_recalc_rates, __clk_speculate_rates exists only for sending
|
||||
* pre-rate change notifications and returns early if no clks in the
|
||||
* subtree have subscribed to the notifications. Note that if a clk does not
|
||||
* implement the .recalc_rate callback then it is assumed that the clock will
|
||||
@@ -2774,6 +2843,33 @@ int clk_set_max_rate(struct clk *clk, unsigned long rate)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_set_max_rate);
|
||||
|
||||
int clk_hw_set_spread_spectrum(struct clk_hw *hw, const struct clk_spread_spectrum *ss_conf)
|
||||
{
|
||||
struct clk_core *core;
|
||||
int ret;
|
||||
|
||||
if (!hw)
|
||||
return 0;
|
||||
|
||||
core = hw->core;
|
||||
|
||||
clk_prepare_lock();
|
||||
|
||||
ret = clk_pm_runtime_get(core);
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
if (core->ops->set_spread_spectrum)
|
||||
ret = core->ops->set_spread_spectrum(hw, ss_conf);
|
||||
|
||||
clk_pm_runtime_put(core);
|
||||
|
||||
fail:
|
||||
clk_prepare_unlock();
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_hw_set_spread_spectrum);
|
||||
|
||||
/**
|
||||
* clk_get_parent - return the parent of a clk
|
||||
* @clk: the clk whose parent gets returned
|
||||
|
||||
+206
-8
@@ -7,6 +7,7 @@
|
||||
#include <linux/clk/clk-conf.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/units.h>
|
||||
|
||||
/* Needed for clk_hw_get_clk() */
|
||||
#include "clk.h"
|
||||
@@ -21,13 +22,14 @@
|
||||
|
||||
static const struct clk_ops empty_clk_ops = { };
|
||||
|
||||
#define DUMMY_CLOCK_INIT_RATE (42 * 1000 * 1000)
|
||||
#define DUMMY_CLOCK_RATE_1 (142 * 1000 * 1000)
|
||||
#define DUMMY_CLOCK_RATE_2 (242 * 1000 * 1000)
|
||||
#define DUMMY_CLOCK_INIT_RATE (42 * HZ_PER_MHZ)
|
||||
#define DUMMY_CLOCK_RATE_1 (142 * HZ_PER_MHZ)
|
||||
#define DUMMY_CLOCK_RATE_2 (242 * HZ_PER_MHZ)
|
||||
|
||||
struct clk_dummy_context {
|
||||
struct clk_hw hw;
|
||||
unsigned long rate;
|
||||
struct clk_spread_spectrum sscs;
|
||||
};
|
||||
|
||||
static unsigned long clk_dummy_recalc_rate(struct clk_hw *hw,
|
||||
@@ -83,6 +85,17 @@ static int clk_dummy_set_rate(struct clk_hw *hw,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int clk_dummy_set_spread_spectrum(struct clk_hw *hw,
|
||||
const struct clk_spread_spectrum *ss_conf)
|
||||
{
|
||||
struct clk_dummy_context *ctx =
|
||||
container_of(hw, struct clk_dummy_context, hw);
|
||||
|
||||
ctx->sscs = *ss_conf;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int clk_dummy_single_set_parent(struct clk_hw *hw, u8 index)
|
||||
{
|
||||
if (index >= clk_hw_get_num_parents(hw))
|
||||
@@ -100,18 +113,21 @@ static const struct clk_ops clk_dummy_rate_ops = {
|
||||
.recalc_rate = clk_dummy_recalc_rate,
|
||||
.determine_rate = clk_dummy_determine_rate,
|
||||
.set_rate = clk_dummy_set_rate,
|
||||
.set_spread_spectrum = clk_dummy_set_spread_spectrum,
|
||||
};
|
||||
|
||||
static const struct clk_ops clk_dummy_maximize_rate_ops = {
|
||||
.recalc_rate = clk_dummy_recalc_rate,
|
||||
.determine_rate = clk_dummy_maximize_rate,
|
||||
.set_rate = clk_dummy_set_rate,
|
||||
.set_spread_spectrum = clk_dummy_set_spread_spectrum,
|
||||
};
|
||||
|
||||
static const struct clk_ops clk_dummy_minimize_rate_ops = {
|
||||
.recalc_rate = clk_dummy_recalc_rate,
|
||||
.determine_rate = clk_dummy_minimize_rate,
|
||||
.set_rate = clk_dummy_set_rate,
|
||||
.set_spread_spectrum = clk_dummy_set_spread_spectrum,
|
||||
};
|
||||
|
||||
static const struct clk_ops clk_dummy_single_parent_ops = {
|
||||
@@ -2232,7 +2248,7 @@ static void
|
||||
clk_leaf_mux_set_rate_parent_determine_rate_test_case_to_desc(
|
||||
const struct clk_leaf_mux_set_rate_parent_determine_rate_test_case *t, char *desc)
|
||||
{
|
||||
strcpy(desc, t->desc);
|
||||
strscpy(desc, t->desc, KUNIT_PARAM_DESC_SIZE);
|
||||
}
|
||||
|
||||
static const struct clk_leaf_mux_set_rate_parent_determine_rate_test_case
|
||||
@@ -2644,7 +2660,7 @@ static void
|
||||
clk_register_clk_parent_data_test_case_to_desc(
|
||||
const struct clk_register_clk_parent_data_test_case *t, char *desc)
|
||||
{
|
||||
strcpy(desc, t->desc);
|
||||
strscpy(desc, t->desc, KUNIT_PARAM_DESC_SIZE);
|
||||
}
|
||||
|
||||
static const struct clk_register_clk_parent_data_test_case
|
||||
@@ -3097,6 +3113,7 @@ struct clk_assigned_rates_context {
|
||||
* @overlay_end: Pointer to end of DT overlay to apply for test
|
||||
* @rate0: Initial rate of first clk
|
||||
* @rate1: Initial rate of second clk
|
||||
* @sscs: Initial spread spectrum settings
|
||||
* @consumer_test: true if a consumer is being tested
|
||||
*/
|
||||
struct clk_assigned_rates_test_param {
|
||||
@@ -3105,6 +3122,7 @@ struct clk_assigned_rates_test_param {
|
||||
u8 *overlay_end;
|
||||
unsigned long rate0;
|
||||
unsigned long rate1;
|
||||
struct clk_spread_spectrum sscs;
|
||||
bool consumer_test;
|
||||
};
|
||||
|
||||
@@ -3116,7 +3134,7 @@ static void
|
||||
clk_assigned_rates_register_clk(struct kunit *test,
|
||||
struct clk_dummy_context *ctx,
|
||||
struct device_node *np, const char *name,
|
||||
unsigned long rate)
|
||||
unsigned long rate, const struct clk_spread_spectrum *sscs)
|
||||
{
|
||||
struct clk_init_data init = { };
|
||||
|
||||
@@ -3124,6 +3142,7 @@ clk_assigned_rates_register_clk(struct kunit *test,
|
||||
init.ops = &clk_dummy_rate_ops;
|
||||
ctx->hw.init = &init;
|
||||
ctx->rate = rate;
|
||||
ctx->sscs = *sscs;
|
||||
|
||||
KUNIT_ASSERT_EQ(test, 0, of_clk_hw_register_kunit(test, np, &ctx->hw));
|
||||
KUNIT_ASSERT_EQ(test, ctx->rate, rate);
|
||||
@@ -3167,14 +3186,16 @@ static int clk_assigned_rates_test_init(struct kunit *test)
|
||||
KUNIT_ASSERT_LT(test, clk_cells, 2);
|
||||
|
||||
clk_assigned_rates_register_clk(test, &ctx->clk0, np,
|
||||
"test_assigned_rate0", test_param->rate0);
|
||||
"test_assigned_rate0", test_param->rate0,
|
||||
&test_param->sscs);
|
||||
if (clk_cells == 0) {
|
||||
KUNIT_ASSERT_EQ(test, 0,
|
||||
of_clk_add_hw_provider_kunit(test, np, of_clk_hw_simple_get,
|
||||
&ctx->clk0.hw));
|
||||
} else if (clk_cells == 1) {
|
||||
clk_assigned_rates_register_clk(test, &ctx->clk1, np,
|
||||
"test_assigned_rate1", test_param->rate1);
|
||||
"test_assigned_rate1", test_param->rate1,
|
||||
&test_param->sscs);
|
||||
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test,
|
||||
data = kunit_kzalloc(test, struct_size(data, hws, 2), GFP_KERNEL));
|
||||
@@ -3403,6 +3424,182 @@ static struct kunit_suite clk_assigned_rates_suite = {
|
||||
.init = clk_assigned_rates_test_init,
|
||||
};
|
||||
|
||||
OF_OVERLAY_DECLARE(kunit_clk_assigned_sscs_one);
|
||||
OF_OVERLAY_DECLARE(kunit_clk_assigned_sscs_one_consumer);
|
||||
OF_OVERLAY_DECLARE(kunit_clk_assigned_sscs_multiple);
|
||||
OF_OVERLAY_DECLARE(kunit_clk_assigned_sscs_multiple_consumer);
|
||||
OF_OVERLAY_DECLARE(kunit_clk_assigned_sscs_without);
|
||||
OF_OVERLAY_DECLARE(kunit_clk_assigned_sscs_without_consumer);
|
||||
OF_OVERLAY_DECLARE(kunit_clk_assigned_sscs_zero);
|
||||
OF_OVERLAY_DECLARE(kunit_clk_assigned_sscs_zero_consumer);
|
||||
OF_OVERLAY_DECLARE(kunit_clk_assigned_sscs_null);
|
||||
OF_OVERLAY_DECLARE(kunit_clk_assigned_sscs_null_consumer);
|
||||
|
||||
static void clk_assigned_sscs_assigns_one(struct kunit *test)
|
||||
{
|
||||
struct clk_assigned_rates_context *ctx = test->priv;
|
||||
|
||||
KUNIT_EXPECT_EQ(test, ctx->clk0.sscs.modfreq_hz, ASSIGNED_SSCS_0_MODFREQ);
|
||||
KUNIT_EXPECT_EQ(test, ctx->clk0.sscs.spread_bp, ASSIGNED_SSCS_0_SPREAD);
|
||||
KUNIT_EXPECT_EQ(test, ctx->clk0.sscs.method, ASSIGNED_SSCS_0_METHOD);
|
||||
}
|
||||
|
||||
/* Test cases that assign sscs for one clk */
|
||||
static const struct clk_assigned_rates_test_param clk_assigned_sscs_assigns_one_test_params[] = {
|
||||
{
|
||||
/*
|
||||
* Test that a single cell assigned-clock-sscs property
|
||||
* assigns the sscs when the property is in the provider.
|
||||
*/
|
||||
.desc = "provider assigns",
|
||||
TEST_PARAM_OVERLAY(kunit_clk_assigned_sscs_one),
|
||||
},
|
||||
{
|
||||
/*
|
||||
* Test that a single cell assigned-clock-sscs property
|
||||
* assigns the sscs when the property is in the consumer.
|
||||
*/
|
||||
.desc = "consumer assigns",
|
||||
TEST_PARAM_OVERLAY(kunit_clk_assigned_sscs_one_consumer),
|
||||
.consumer_test = true,
|
||||
},
|
||||
};
|
||||
KUNIT_ARRAY_PARAM_DESC(clk_assigned_sscs_assigns_one,
|
||||
clk_assigned_sscs_assigns_one_test_params, desc)
|
||||
|
||||
static void clk_assigned_sscs_assigns_multiple(struct kunit *test)
|
||||
{
|
||||
struct clk_assigned_rates_context *ctx = test->priv;
|
||||
|
||||
KUNIT_EXPECT_EQ(test, ctx->clk0.sscs.modfreq_hz, ASSIGNED_SSCS_0_MODFREQ);
|
||||
KUNIT_EXPECT_EQ(test, ctx->clk0.sscs.spread_bp, ASSIGNED_SSCS_0_SPREAD);
|
||||
KUNIT_EXPECT_EQ(test, ctx->clk0.sscs.method, ASSIGNED_SSCS_0_METHOD);
|
||||
KUNIT_EXPECT_EQ(test, ctx->clk1.sscs.modfreq_hz, ASSIGNED_SSCS_1_MODFREQ);
|
||||
KUNIT_EXPECT_EQ(test, ctx->clk1.sscs.spread_bp, ASSIGNED_SSCS_1_SPREAD);
|
||||
KUNIT_EXPECT_EQ(test, ctx->clk1.sscs.method, ASSIGNED_SSCS_1_METHOD);
|
||||
}
|
||||
|
||||
/* Test cases that assign sscs for multiple clks */
|
||||
static const
|
||||
struct clk_assigned_rates_test_param clk_assigned_sscs_assigns_multiple_test_params[] = {
|
||||
{
|
||||
/*
|
||||
* Test that a multiple cell assigned-clock-sscs property
|
||||
* assigns the sscs when the property is in the provider.
|
||||
*/
|
||||
.desc = "provider assigns",
|
||||
TEST_PARAM_OVERLAY(kunit_clk_assigned_sscs_multiple),
|
||||
},
|
||||
{
|
||||
/*
|
||||
* Test that a multiple cell assigned-clock-sscs property
|
||||
* assigns the sscs when the property is in the consumer.
|
||||
*/
|
||||
.desc = "consumer assigns",
|
||||
TEST_PARAM_OVERLAY(kunit_clk_assigned_sscs_multiple_consumer),
|
||||
.consumer_test = true,
|
||||
},
|
||||
};
|
||||
KUNIT_ARRAY_PARAM_DESC(clk_assigned_sscs_assigns_multiple,
|
||||
clk_assigned_sscs_assigns_multiple_test_params,
|
||||
desc)
|
||||
|
||||
static void clk_assigned_sscs_skips(struct kunit *test)
|
||||
{
|
||||
struct clk_assigned_rates_context *ctx = test->priv;
|
||||
const struct clk_assigned_rates_test_param *test_param = test->param_value;
|
||||
|
||||
KUNIT_EXPECT_NE(test, ctx->clk0.sscs.modfreq_hz, ASSIGNED_SSCS_0_MODFREQ);
|
||||
KUNIT_EXPECT_NE(test, ctx->clk0.sscs.spread_bp, ASSIGNED_SSCS_0_SPREAD);
|
||||
KUNIT_EXPECT_NE(test, ctx->clk0.sscs.method, ASSIGNED_SSCS_0_METHOD);
|
||||
KUNIT_EXPECT_EQ(test, ctx->clk0.sscs.modfreq_hz, test_param->sscs.modfreq_hz);
|
||||
KUNIT_EXPECT_EQ(test, ctx->clk0.sscs.spread_bp, test_param->sscs.spread_bp);
|
||||
KUNIT_EXPECT_EQ(test, ctx->clk0.sscs.method, test_param->sscs.method);
|
||||
}
|
||||
|
||||
/* Test cases that skip changing the sscs due to malformed DT */
|
||||
static const struct clk_assigned_rates_test_param clk_assigned_sscs_skips_test_params[] = {
|
||||
{
|
||||
/*
|
||||
* Test that an assigned-clock-sscs property without an assigned-clocks
|
||||
* property fails when the property is in the provider.
|
||||
*/
|
||||
.desc = "provider missing assigned-clocks",
|
||||
TEST_PARAM_OVERLAY(kunit_clk_assigned_sscs_without),
|
||||
.sscs = {50000, 60000, 3},
|
||||
},
|
||||
{
|
||||
/*
|
||||
* Test that an assigned-clock-sscs property without an assigned-clocks
|
||||
* property fails when the property is in the consumer.
|
||||
*/
|
||||
.desc = "consumer missing assigned-clocks",
|
||||
TEST_PARAM_OVERLAY(kunit_clk_assigned_sscs_without_consumer),
|
||||
.sscs = {50000, 60000, 3},
|
||||
.consumer_test = true,
|
||||
},
|
||||
{
|
||||
/*
|
||||
* Test that an assigned-clock-sscs property of zero doesn't
|
||||
* set sscs when the property is in the provider.
|
||||
*/
|
||||
.desc = "provider assigned-clock-sscs of zero",
|
||||
TEST_PARAM_OVERLAY(kunit_clk_assigned_sscs_zero),
|
||||
.sscs = {50000, 60000, 3},
|
||||
},
|
||||
{
|
||||
/*
|
||||
* Test that an assigned-clock-sscs property of zero doesn't
|
||||
* set sscs when the property is in the consumer.
|
||||
*/
|
||||
.desc = "consumer assigned-clock-sscs of zero",
|
||||
TEST_PARAM_OVERLAY(kunit_clk_assigned_sscs_zero_consumer),
|
||||
.sscs = {50000, 60000, 3},
|
||||
.consumer_test = true,
|
||||
},
|
||||
{
|
||||
/*
|
||||
* Test that an assigned-clocks property with a null phandle
|
||||
* doesn't set sscs when the property is in the provider.
|
||||
*/
|
||||
.desc = "provider assigned-clocks null phandle",
|
||||
TEST_PARAM_OVERLAY(kunit_clk_assigned_sscs_null),
|
||||
.sscs = {50000, 60000, 3},
|
||||
},
|
||||
{
|
||||
/*
|
||||
* Test that an assigned-clocks property with a null phandle
|
||||
* doesn't set sscs when the property is in the consumer.
|
||||
*/
|
||||
.desc = "consumer assigned-clocks null phandle",
|
||||
TEST_PARAM_OVERLAY(kunit_clk_assigned_sscs_null_consumer),
|
||||
.sscs = {50000, 60000, 3},
|
||||
.consumer_test = true,
|
||||
},
|
||||
};
|
||||
KUNIT_ARRAY_PARAM_DESC(clk_assigned_sscs_skips,
|
||||
clk_assigned_sscs_skips_test_params,
|
||||
desc)
|
||||
|
||||
static struct kunit_case clk_assigned_sscs_test_cases[] = {
|
||||
KUNIT_CASE_PARAM(clk_assigned_sscs_assigns_one,
|
||||
clk_assigned_sscs_assigns_one_gen_params),
|
||||
KUNIT_CASE_PARAM(clk_assigned_sscs_assigns_multiple,
|
||||
clk_assigned_sscs_assigns_multiple_gen_params),
|
||||
KUNIT_CASE_PARAM(clk_assigned_sscs_skips,
|
||||
clk_assigned_sscs_skips_gen_params),
|
||||
{}
|
||||
};
|
||||
|
||||
/*
|
||||
* Test suite for assigned-clock-sscs DT property.
|
||||
*/
|
||||
static struct kunit_suite clk_assigned_sscs_suite = {
|
||||
.name = "clk_assigned_sscs",
|
||||
.test_cases = clk_assigned_sscs_test_cases,
|
||||
.init = clk_assigned_rates_test_init,
|
||||
};
|
||||
|
||||
static const struct clk_init_data clk_hw_get_dev_of_node_init_data = {
|
||||
.name = "clk_hw_get_dev_of_node",
|
||||
.ops = &empty_clk_ops,
|
||||
@@ -3544,6 +3741,7 @@ static struct kunit_suite clk_hw_get_dev_of_node_test_suite = {
|
||||
|
||||
kunit_test_suites(
|
||||
&clk_assigned_rates_suite,
|
||||
&clk_assigned_sscs_suite,
|
||||
&clk_hw_get_dev_of_node_test_suite,
|
||||
&clk_leaf_mux_set_rate_parent_test_suite,
|
||||
&clk_test_suite,
|
||||
|
||||
@@ -13,3 +13,16 @@ config COMMON_CLK_EIC7700
|
||||
SoC. The clock controller generates and supplies clocks to various
|
||||
peripherals within the SoC.
|
||||
Say yes here to support the clock controller on the EIC7700 SoC.
|
||||
|
||||
config COMMON_CLK_EIC7700_HSP
|
||||
tristate "EIC7700 HSP Clock Driver"
|
||||
depends on ARCH_ESWIN || COMPILE_TEST
|
||||
select AUXILIARY_BUS
|
||||
select COMMON_CLK_EIC7700
|
||||
select RESET_EIC7700_HSP if RESET_CONTROLLER
|
||||
select REGMAP_MMIO
|
||||
help
|
||||
This driver provides support for clock controller on ESWIN EIC7700
|
||||
HSP. The clock controller generates and supplies clocks to high
|
||||
speed peripherals within the SoC.
|
||||
Say yes here to support the clock controller on the EIC7700 HSP.
|
||||
|
||||
@@ -6,3 +6,4 @@
|
||||
obj-$(CONFIG_COMMON_CLK_ESWIN) += clk.o
|
||||
|
||||
obj-$(CONFIG_COMMON_CLK_EIC7700) += clk-eic7700.o
|
||||
obj-$(CONFIG_COMMON_CLK_EIC7700_HSP) += clk-eic7700-hsp.o
|
||||
|
||||
@@ -0,0 +1,345 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright 2026, Beijing ESWIN Computing Technology Co., Ltd..
|
||||
* All rights reserved.
|
||||
*
|
||||
* ESWIN EIC7700 HSP Clock Driver
|
||||
*
|
||||
* Authors: Xuyang Dong <dongxuyang@eswincomputing.com>
|
||||
*/
|
||||
|
||||
#include <linux/auxiliary_bus.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#include <dt-bindings/clock/eswin,eic7700-hspcrg.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#define EIC7700_HSP_SATA_REG 0x300
|
||||
#define EIC7700_HSP_MSHC0_REG 0x510
|
||||
#define EIC7700_HSP_MSHC1_REG 0x610
|
||||
#define EIC7700_HSP_MSHC2_REG 0x710
|
||||
#define EIC7700_HSP_USB0_REG 0x800
|
||||
#define EIC7700_HSP_USB0_REF_REG 0x83c
|
||||
#define EIC7700_HSP_USB1_REG 0x900
|
||||
#define EIC7700_HSP_USB1_REF_REG 0x93c
|
||||
|
||||
#define USB_REF_XTAL24M 0x2a
|
||||
#define EIC7700_HSP_NR_CLKS (EIC7700_HSP_CLK_GATE_SATA + 1)
|
||||
|
||||
struct eic7700_hsp_clk_gate {
|
||||
struct clk_hw hw;
|
||||
unsigned int id;
|
||||
struct regmap *regmap;
|
||||
unsigned int reg;
|
||||
unsigned int ref_reg;
|
||||
const char *name;
|
||||
const struct clk_parent_data *parent_data;
|
||||
unsigned long flags;
|
||||
unsigned int offset;
|
||||
unsigned int ref_offset;
|
||||
u8 bit_idx;
|
||||
};
|
||||
|
||||
static const struct regmap_config eic7700_hsp_regmap_config = {
|
||||
.reg_bits = 32,
|
||||
.val_bits = 32,
|
||||
.max_register = 0x1ffc,
|
||||
.reg_stride = 4,
|
||||
.fast_io = true,
|
||||
.use_raw_spinlock = true,
|
||||
};
|
||||
|
||||
static inline struct eic7700_hsp_clk_gate *to_gate_clk(struct clk_hw *hw)
|
||||
{
|
||||
return container_of(hw, struct eic7700_hsp_clk_gate, hw);
|
||||
}
|
||||
|
||||
#define EIC7700_HSP_GATE(_id, _name, _pdata, _flags, _offset, _idx, \
|
||||
_ref_offset) \
|
||||
{ \
|
||||
.id = _id, \
|
||||
.name = _name, \
|
||||
.parent_data = _pdata, \
|
||||
.flags = _flags, \
|
||||
.offset = _offset, \
|
||||
.ref_offset = _ref_offset, \
|
||||
.bit_idx = _idx, \
|
||||
}
|
||||
|
||||
static void hsp_clk_gate_endisable(struct clk_hw *hw, bool enable)
|
||||
{
|
||||
struct eic7700_hsp_clk_gate *gate = to_gate_clk(hw);
|
||||
|
||||
if (enable) {
|
||||
/*
|
||||
* Hardware bug: The USB reference clock must be 24MHz.
|
||||
* The default register value after reset is invalid.
|
||||
* Workaround: Rewrite the correct value before enabling
|
||||
* the USB gate clock.
|
||||
*/
|
||||
regmap_update_bits(gate->regmap, gate->ref_reg, 0x3f,
|
||||
USB_REF_XTAL24M);
|
||||
}
|
||||
regmap_assign_bits(gate->regmap, gate->reg, BIT(gate->bit_idx), enable);
|
||||
}
|
||||
|
||||
static int hsp_clk_gate_enable(struct clk_hw *hw)
|
||||
{
|
||||
hsp_clk_gate_endisable(hw, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void hsp_clk_gate_disable(struct clk_hw *hw)
|
||||
{
|
||||
hsp_clk_gate_endisable(hw, false);
|
||||
}
|
||||
|
||||
static int hsp_clk_gate_is_enabled(struct clk_hw *hw)
|
||||
{
|
||||
struct eic7700_hsp_clk_gate *gate = to_gate_clk(hw);
|
||||
unsigned int val;
|
||||
int ret;
|
||||
|
||||
ret = regmap_read(gate->regmap, gate->reg, &val);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
return !!(val & BIT(gate->bit_idx));
|
||||
}
|
||||
|
||||
static const struct clk_ops hsp_clk_gate_ops = {
|
||||
.enable = hsp_clk_gate_enable,
|
||||
.disable = hsp_clk_gate_disable,
|
||||
.is_enabled = hsp_clk_gate_is_enabled,
|
||||
};
|
||||
|
||||
static struct clk_hw *
|
||||
hsp_clk_register_gate(struct device *dev, unsigned int id, const char *name,
|
||||
const struct clk_parent_data *parent_data,
|
||||
unsigned long flags, struct regmap *regmap,
|
||||
unsigned int reg, unsigned int ref_reg, u8 bit_idx)
|
||||
{
|
||||
struct eic7700_hsp_clk_gate *gate;
|
||||
struct clk_init_data init = {};
|
||||
struct clk_hw *hw;
|
||||
int ret;
|
||||
|
||||
gate = devm_kzalloc(dev, sizeof(*gate), GFP_KERNEL);
|
||||
if (!gate)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
init.name = name;
|
||||
init.ops = &hsp_clk_gate_ops;
|
||||
init.flags = flags;
|
||||
init.parent_data = parent_data;
|
||||
init.num_parents = 1;
|
||||
|
||||
gate->id = id;
|
||||
gate->regmap = regmap;
|
||||
gate->reg = reg;
|
||||
gate->ref_reg = ref_reg;
|
||||
gate->bit_idx = bit_idx;
|
||||
gate->hw.init = &init;
|
||||
|
||||
hw = &gate->hw;
|
||||
ret = devm_clk_hw_register(dev, hw);
|
||||
if (ret)
|
||||
hw = ERR_PTR(ret);
|
||||
|
||||
return hw;
|
||||
}
|
||||
|
||||
static const struct clk_parent_data hsp_cfg[] = {
|
||||
{ .index = 0 }
|
||||
};
|
||||
|
||||
static const struct clk_parent_data hsp_mmc[] = {
|
||||
{ .index = 1 }
|
||||
};
|
||||
|
||||
static const struct clk_parent_data hsp_usb_sata[] = {
|
||||
{ .index = 2 }
|
||||
};
|
||||
|
||||
static struct eswin_fixed_factor_clock eic7700_hsp_factor_clks[] = {
|
||||
ESWIN_FACTOR(EIC7700_HSP_CLK_FAC_CFG_DIV2, "factor_hsp_cfg_div2",
|
||||
hsp_cfg, 1, 2, 0),
|
||||
ESWIN_FACTOR(EIC7700_HSP_CLK_FAC_CFG_DIV4, "factor_hsp_cfg_div4",
|
||||
hsp_cfg, 1, 4, 0),
|
||||
ESWIN_FACTOR(EIC7700_HSP_CLK_FAC_MMC_DIV10, "factor_hsp_mmc_div10",
|
||||
hsp_mmc, 1, 10, 0),
|
||||
};
|
||||
|
||||
static struct eswin_gate_clock eic7700_hsp_gate_clks[] = {
|
||||
ESWIN_GATE(EIC7700_HSP_CLK_GATE_SATA, "gate_clk_hsp_sata", hsp_usb_sata,
|
||||
CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
|
||||
EIC7700_HSP_SATA_REG, 28, 0),
|
||||
ESWIN_GATE(EIC7700_HSP_CLK_GATE_MSHC0_TMR, "gate_clk_hsp_mshc0_tmr",
|
||||
hsp_mmc, CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
|
||||
EIC7700_HSP_MSHC0_REG, 8, 0),
|
||||
ESWIN_GATE(EIC7700_HSP_CLK_GATE_MSHC1_TMR, "gate_clk_hsp_mshc1_tmr",
|
||||
hsp_mmc, CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
|
||||
EIC7700_HSP_MSHC1_REG, 8, 0),
|
||||
ESWIN_GATE(EIC7700_HSP_CLK_GATE_MSHC2_TMR, "gate_clk_hsp_mshc2_tmr",
|
||||
hsp_mmc, CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
|
||||
EIC7700_HSP_MSHC2_REG, 8, 0),
|
||||
};
|
||||
|
||||
static struct eic7700_hsp_clk_gate eic7700_hsp_spec_gate_clks[] = {
|
||||
EIC7700_HSP_GATE(EIC7700_HSP_CLK_GATE_USB0, "gate_clk_hsp_usb0",
|
||||
hsp_usb_sata, CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
|
||||
EIC7700_HSP_USB0_REG, 28, EIC7700_HSP_USB0_REF_REG),
|
||||
EIC7700_HSP_GATE(EIC7700_HSP_CLK_GATE_USB1, "gate_clk_hsp_usb1",
|
||||
hsp_usb_sata, CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
|
||||
EIC7700_HSP_USB1_REG, 28, EIC7700_HSP_USB1_REF_REG),
|
||||
};
|
||||
|
||||
static const struct clk_parent_data mux_mmc_3mux1_p[] = {
|
||||
{ .fw_name = "cfg" },
|
||||
{ .hw = &eic7700_hsp_factor_clks[0].hw },
|
||||
{ .hw = &eic7700_hsp_factor_clks[1].hw },
|
||||
};
|
||||
|
||||
static const struct clk_parent_data mux_mmc_2mux1_p[] = {
|
||||
{ .fw_name = "mmc" },
|
||||
{ .hw = &eic7700_hsp_factor_clks[2].hw },
|
||||
};
|
||||
|
||||
static u32 mux_mmc_3mux1_tbl[] = { 0x0, 0x1, 0x3 };
|
||||
|
||||
static struct eswin_mux_clock eic7700_hsp_mux_clks[] = {
|
||||
ESWIN_MUX_TBL(EIC7700_HSP_CLK_MUX_EMMC_3MUX1, "mux_hsp_emmc_3mux1",
|
||||
mux_mmc_3mux1_p, ARRAY_SIZE(mux_mmc_3mux1_p),
|
||||
CLK_SET_RATE_PARENT, EIC7700_HSP_MSHC0_REG, 16, 2, 0,
|
||||
mux_mmc_3mux1_tbl),
|
||||
ESWIN_MUX_TBL(EIC7700_HSP_CLK_MUX_SD0_3MUX1, "mux_hsp_sd0_3mux1",
|
||||
mux_mmc_3mux1_p, ARRAY_SIZE(mux_mmc_3mux1_p),
|
||||
CLK_SET_RATE_PARENT, EIC7700_HSP_MSHC1_REG, 16, 2, 0,
|
||||
mux_mmc_3mux1_tbl),
|
||||
ESWIN_MUX_TBL(EIC7700_HSP_CLK_MUX_SD1_3MUX1, "mux_hsp_sd1_3mux1",
|
||||
mux_mmc_3mux1_p, ARRAY_SIZE(mux_mmc_3mux1_p),
|
||||
CLK_SET_RATE_PARENT, EIC7700_HSP_MSHC2_REG, 16, 2, 0,
|
||||
mux_mmc_3mux1_tbl),
|
||||
ESWIN_MUX(EIC7700_HSP_CLK_MUX_EMMC_CQE_2MUX1, "mux_hsp_emmc_cqe_2mux1",
|
||||
mux_mmc_2mux1_p, ARRAY_SIZE(mux_mmc_2mux1_p),
|
||||
CLK_SET_RATE_PARENT, EIC7700_HSP_MSHC0_REG, 0, 1, 0),
|
||||
ESWIN_MUX(EIC7700_HSP_CLK_MUX_SD0_CQE_2MUX1, "mux_hsp_sd0_cqe_2mux1",
|
||||
mux_mmc_2mux1_p, ARRAY_SIZE(mux_mmc_2mux1_p),
|
||||
CLK_SET_RATE_PARENT, EIC7700_HSP_MSHC1_REG, 0, 1, 0),
|
||||
ESWIN_MUX(EIC7700_HSP_CLK_MUX_SD1_CQE_2MUX1, "mux_hsp_sd1_cqe_2mux1",
|
||||
mux_mmc_2mux1_p, ARRAY_SIZE(mux_mmc_2mux1_p),
|
||||
CLK_SET_RATE_PARENT, EIC7700_HSP_MSHC2_REG, 0, 1, 0),
|
||||
};
|
||||
|
||||
static struct eswin_clk_info eic7700_hsp_clks[] = {
|
||||
ESWIN_GATE_TYPE(EIC7700_HSP_CLK_GATE_EMMC, "gate_clk_hsp_emmc",
|
||||
EIC7700_HSP_CLK_MUX_EMMC_3MUX1,
|
||||
CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
|
||||
EIC7700_HSP_MSHC0_REG, 24, 0),
|
||||
ESWIN_GATE_TYPE(EIC7700_HSP_CLK_GATE_SD0, "gate_clk_hsp_sd0",
|
||||
EIC7700_HSP_CLK_MUX_SD0_3MUX1,
|
||||
CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
|
||||
EIC7700_HSP_MSHC1_REG, 24, 0),
|
||||
ESWIN_GATE_TYPE(EIC7700_HSP_CLK_GATE_SD1, "gate_clk_hsp_sd1",
|
||||
EIC7700_HSP_CLK_MUX_SD1_3MUX1,
|
||||
CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
|
||||
EIC7700_HSP_MSHC2_REG, 24, 0),
|
||||
};
|
||||
|
||||
static int eic7700_hsp_clk_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct auxiliary_device *adev;
|
||||
struct eswin_clock_data *data;
|
||||
struct regmap *regmap;
|
||||
struct clk_hw *hw;
|
||||
int i, ret;
|
||||
|
||||
data = eswin_clk_init(pdev, EIC7700_HSP_NR_CLKS);
|
||||
if (IS_ERR(data))
|
||||
return dev_err_probe(dev, PTR_ERR(data),
|
||||
"failed to get clk data!\n");
|
||||
|
||||
regmap = devm_regmap_init_mmio(dev, data->base,
|
||||
&eic7700_hsp_regmap_config);
|
||||
if (IS_ERR(regmap))
|
||||
return dev_err_probe(dev, PTR_ERR(regmap),
|
||||
"failed to get regmap!\n");
|
||||
|
||||
ret = eswin_clk_register_fixed_factor(dev, eic7700_hsp_factor_clks,
|
||||
ARRAY_SIZE(eic7700_hsp_factor_clks),
|
||||
data);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret,
|
||||
"failed to register fixed factor clock\n");
|
||||
|
||||
ret = eswin_clk_register_gate(dev, eic7700_hsp_gate_clks,
|
||||
ARRAY_SIZE(eic7700_hsp_gate_clks), data);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret,
|
||||
"failed to register gate clock\n");
|
||||
|
||||
ret = eswin_clk_register_mux(dev, eic7700_hsp_mux_clks,
|
||||
ARRAY_SIZE(eic7700_hsp_mux_clks),
|
||||
data);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret,
|
||||
"failed to register mux clock\n");
|
||||
|
||||
ret = eswin_clk_register_clks(dev, eic7700_hsp_clks,
|
||||
ARRAY_SIZE(eic7700_hsp_clks), data);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret,
|
||||
"failed to register clock\n");
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(eic7700_hsp_spec_gate_clks); i++) {
|
||||
struct eic7700_hsp_clk_gate *gate;
|
||||
|
||||
gate = &eic7700_hsp_spec_gate_clks[i];
|
||||
hw = hsp_clk_register_gate(dev, gate->id, gate->name,
|
||||
gate->parent_data, gate->flags,
|
||||
regmap, gate->offset,
|
||||
gate->ref_offset, gate->bit_idx);
|
||||
if (IS_ERR(hw))
|
||||
return dev_err_probe(dev, PTR_ERR(hw),
|
||||
"failed to register gate clock\n");
|
||||
|
||||
data->clk_data.hws[gate->id] = hw;
|
||||
}
|
||||
|
||||
ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
|
||||
&data->clk_data);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "add clk provider failed\n");
|
||||
|
||||
adev = devm_auxiliary_device_create(dev, "hsp-reset", NULL);
|
||||
if (!adev)
|
||||
return dev_err_probe(dev, -ENODEV,
|
||||
"register hsp-reset device failed\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id eic7700_hsp_clock_dt_ids[] = {
|
||||
{ .compatible = "eswin,eic7700-hspcrg", },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, eic7700_hsp_clock_dt_ids);
|
||||
|
||||
static struct platform_driver eic7700_hsp_clock_driver = {
|
||||
.probe = eic7700_hsp_clk_probe,
|
||||
.driver = {
|
||||
.name = "eic7700-hsp-clock",
|
||||
.of_match_table = eic7700_hsp_clock_dt_ids,
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver(eic7700_hsp_clock_driver);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Xuyang Dong <dongxuyang@eswincomputing.com>");
|
||||
MODULE_DESCRIPTION("ESWIN EIC7700 HSP clock controller driver");
|
||||
@@ -791,7 +791,8 @@ static struct eswin_clk_info eic7700_clks[] = {
|
||||
EIC7700_CLK_MUX_CPU_ROOT_3MUX1_GFREE,
|
||||
CLK_SET_RATE_PARENT, EIC7700_REG_OFFSET_U84, 27, 0),
|
||||
ESWIN_GATE_TYPE(EIC7700_CLK_GATE_NOC_NSP_CLK, "gate_noc_nsp_clk",
|
||||
EIC7700_CLK_DIV_NOC_NSP_DYNM, CLK_SET_RATE_PARENT,
|
||||
EIC7700_CLK_DIV_NOC_NSP_DYNM,
|
||||
CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
|
||||
EIC7700_REG_OFFSET_NOC, 31, 0),
|
||||
ESWIN_GATE_TYPE(EIC7700_CLK_GATE_BOOTSPI, "gate_clk_bootspi",
|
||||
EIC7700_CLK_MUX_BOOTSPI_CLK_2MUX1_GFREE,
|
||||
|
||||
@@ -204,7 +204,7 @@ int eswin_clk_register_pll(struct device *dev, struct eswin_pll_clock *clks,
|
||||
int nums, struct eswin_clock_data *data)
|
||||
{
|
||||
struct eswin_clk_pll *p_clk = NULL;
|
||||
struct clk_init_data init;
|
||||
struct clk_init_data init = {};
|
||||
struct clk_hw *clk_hw;
|
||||
int i, ret;
|
||||
|
||||
@@ -419,7 +419,7 @@ struct clk_hw *eswin_register_clkdiv(struct device *dev, unsigned int id,
|
||||
unsigned long priv_flag, spinlock_t *lock)
|
||||
{
|
||||
struct eswin_divider_clock *dclk;
|
||||
struct clk_init_data init;
|
||||
struct clk_init_data init = {};
|
||||
struct clk_hw *clk_hw;
|
||||
int ret;
|
||||
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
config COMMON_CLK_HISI
|
||||
bool
|
||||
default ARCH_HISI
|
||||
|
||||
config COMMON_CLK_HI3516CV300
|
||||
tristate "HI3516CV300 Clock Driver"
|
||||
depends on ARCH_HISI || COMPILE_TEST
|
||||
select RESET_HISI
|
||||
select COMMON_CLK_HISI
|
||||
default ARCH_HISI
|
||||
help
|
||||
Build the clock driver for hi3516cv300.
|
||||
@@ -11,6 +16,7 @@ config COMMON_CLK_HI3519
|
||||
tristate "Hi3519 Clock Driver"
|
||||
depends on ARCH_HISI || COMPILE_TEST
|
||||
select RESET_HISI
|
||||
select COMMON_CLK_HISI
|
||||
default ARCH_HISI
|
||||
help
|
||||
Build the clock driver for hi3519.
|
||||
@@ -19,6 +25,7 @@ config COMMON_CLK_HI3559A
|
||||
bool "Hi3559A Clock Driver"
|
||||
depends on ARCH_HISI || COMPILE_TEST
|
||||
select RESET_HISI
|
||||
select COMMON_CLK_HISI
|
||||
default ARCH_HISI
|
||||
help
|
||||
Build the clock driver for hi3559a.
|
||||
@@ -26,6 +33,7 @@ config COMMON_CLK_HI3559A
|
||||
config COMMON_CLK_HI3660
|
||||
bool "Hi3660 Clock Driver"
|
||||
depends on ARCH_HISI || COMPILE_TEST
|
||||
select COMMON_CLK_HISI
|
||||
default ARCH_HISI
|
||||
help
|
||||
Build the clock driver for hi3660.
|
||||
@@ -33,6 +41,7 @@ config COMMON_CLK_HI3660
|
||||
config COMMON_CLK_HI3670
|
||||
bool "Hi3670 Clock Driver"
|
||||
depends on ARCH_HISI || COMPILE_TEST
|
||||
select COMMON_CLK_HISI
|
||||
default ARCH_HISI
|
||||
help
|
||||
Build the clock driver for hi3670.
|
||||
@@ -41,6 +50,7 @@ config COMMON_CLK_HI3798CV200
|
||||
tristate "Hi3798CV200 Clock Driver"
|
||||
depends on ARCH_HISI || COMPILE_TEST
|
||||
select RESET_HISI
|
||||
select COMMON_CLK_HISI
|
||||
default ARCH_HISI
|
||||
help
|
||||
Build the clock driver for hi3798cv200.
|
||||
@@ -48,6 +58,7 @@ config COMMON_CLK_HI3798CV200
|
||||
config COMMON_CLK_HI6220
|
||||
bool "Hi6220 Clock Driver"
|
||||
depends on ARCH_HISI || COMPILE_TEST
|
||||
select COMMON_CLK_HISI
|
||||
default ARCH_HISI
|
||||
help
|
||||
Build the Hisilicon Hi6220 clock driver based on the common clock framework.
|
||||
@@ -55,6 +66,7 @@ config COMMON_CLK_HI6220
|
||||
config RESET_HISI
|
||||
bool "HiSilicon Reset Controller Driver"
|
||||
depends on ARCH_HISI || COMPILE_TEST
|
||||
select COMMON_CLK_HISI
|
||||
select RESET_CONTROLLER
|
||||
help
|
||||
Build reset controller driver for HiSilicon device chipsets.
|
||||
@@ -63,6 +75,7 @@ config STUB_CLK_HI6220
|
||||
bool "Hi6220 Stub Clock Driver" if EXPERT
|
||||
depends on (COMMON_CLK_HI6220 || COMPILE_TEST)
|
||||
depends on MAILBOX
|
||||
select COMMON_CLK_HISI
|
||||
default COMMON_CLK_HI6220
|
||||
help
|
||||
Build the Hisilicon Hi6220 stub clock driver.
|
||||
@@ -71,6 +84,7 @@ config STUB_CLK_HI3660
|
||||
bool "Hi3660 Stub Clock Driver" if EXPERT
|
||||
depends on (COMMON_CLK_HI3660 || COMPILE_TEST)
|
||||
depends on MAILBOX
|
||||
select COMMON_CLK_HISI
|
||||
default COMMON_CLK_HI3660
|
||||
help
|
||||
Build the Hisilicon Hi3660 stub clock driver.
|
||||
|
||||
@@ -67,16 +67,6 @@ static unsigned long hi3660_stub_clk_recalc_rate(struct clk_hw *hw,
|
||||
return stub_clk->rate;
|
||||
}
|
||||
|
||||
static int hi3660_stub_clk_determine_rate(struct clk_hw *hw,
|
||||
struct clk_rate_request *req)
|
||||
{
|
||||
/*
|
||||
* LPM3 handles rate rounding so just return whatever
|
||||
* rate is requested.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hi3660_stub_clk_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
@@ -97,7 +87,7 @@ static int hi3660_stub_clk_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
|
||||
static const struct clk_ops hi3660_stub_clk_ops = {
|
||||
.recalc_rate = hi3660_stub_clk_recalc_rate,
|
||||
.determine_rate = hi3660_stub_clk_determine_rate,
|
||||
.determine_rate = clk_determine_rate_noop,
|
||||
.set_rate = hi3660_stub_clk_set_rate,
|
||||
};
|
||||
|
||||
@@ -124,7 +114,6 @@ static struct clk_hw *hi3660_stub_clk_hw_get(struct of_phandle_args *clkspec,
|
||||
static int hi3660_stub_clk_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct resource *res;
|
||||
unsigned int i;
|
||||
int ret;
|
||||
|
||||
@@ -139,12 +128,9 @@ static int hi3660_stub_clk_probe(struct platform_device *pdev)
|
||||
if (IS_ERR(stub_clk_chan.mbox))
|
||||
return PTR_ERR(stub_clk_chan.mbox);
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res)
|
||||
return -EINVAL;
|
||||
freq_reg = devm_ioremap(dev, res->start, resource_size(res));
|
||||
if (!freq_reg)
|
||||
return -ENOMEM;
|
||||
freq_reg = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(freq_reg))
|
||||
return PTR_ERR(freq_reg);
|
||||
|
||||
freq_reg += HI3660_STUB_CLOCK_DATA;
|
||||
|
||||
|
||||
@@ -91,7 +91,7 @@ struct hisi_reset_controller *hisi_reset_init(struct platform_device *pdev)
|
||||
{
|
||||
struct hisi_reset_controller *rstc;
|
||||
|
||||
rstc = devm_kmalloc(&pdev->dev, sizeof(*rstc), GFP_KERNEL);
|
||||
rstc = devm_kzalloc(&pdev->dev, sizeof(*rstc), GFP_KERNEL);
|
||||
if (!rstc)
|
||||
return NULL;
|
||||
|
||||
|
||||
@@ -262,23 +262,6 @@ static unsigned long clk_scu_recalc_rate(struct clk_hw *hw,
|
||||
return le32_to_cpu(msg.data.resp.rate);
|
||||
}
|
||||
|
||||
/*
|
||||
* clk_scu_determine_rate - Returns the closest rate for a SCU clock
|
||||
* @hw: clock to round rate for
|
||||
* @req: clock rate request
|
||||
*
|
||||
* Returns 0 on success, a negative error on failure
|
||||
*/
|
||||
static int clk_scu_determine_rate(struct clk_hw *hw,
|
||||
struct clk_rate_request *req)
|
||||
{
|
||||
/*
|
||||
* Assume we support all the requested rate and let the SCU firmware
|
||||
* to handle the left work
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int clk_scu_atf_set_cpu_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
@@ -436,7 +419,7 @@ static void clk_scu_unprepare(struct clk_hw *hw)
|
||||
|
||||
static const struct clk_ops clk_scu_ops = {
|
||||
.recalc_rate = clk_scu_recalc_rate,
|
||||
.determine_rate = clk_scu_determine_rate,
|
||||
.determine_rate = clk_determine_rate_noop,
|
||||
.set_rate = clk_scu_set_rate,
|
||||
.get_parent = clk_scu_get_parent,
|
||||
.set_parent = clk_scu_set_parent,
|
||||
@@ -446,7 +429,7 @@ static const struct clk_ops clk_scu_ops = {
|
||||
|
||||
static const struct clk_ops clk_scu_cpu_ops = {
|
||||
.recalc_rate = clk_scu_recalc_rate,
|
||||
.determine_rate = clk_scu_determine_rate,
|
||||
.determine_rate = clk_determine_rate_noop,
|
||||
.set_rate = clk_scu_atf_set_cpu_rate,
|
||||
.prepare = clk_scu_prepare,
|
||||
.unprepare = clk_scu_unprepare,
|
||||
@@ -454,7 +437,7 @@ static const struct clk_ops clk_scu_cpu_ops = {
|
||||
|
||||
static const struct clk_ops clk_scu_pi_ops = {
|
||||
.recalc_rate = clk_scu_recalc_rate,
|
||||
.determine_rate = clk_scu_determine_rate,
|
||||
.determine_rate = clk_determine_rate_noop,
|
||||
.set_rate = clk_scu_set_rate,
|
||||
};
|
||||
|
||||
@@ -475,7 +458,6 @@ struct clk_hw *__imx_clk_scu(struct device *dev, const char *name,
|
||||
clk->clk_type = clk_type;
|
||||
|
||||
init.name = name;
|
||||
init.ops = &clk_scu_ops;
|
||||
if (rsrc_id == IMX_SC_R_A35 || rsrc_id == IMX_SC_R_A53 || rsrc_id == IMX_SC_R_A72)
|
||||
init.ops = &clk_scu_cpu_ops;
|
||||
else if (rsrc_id == IMX_SC_R_PI_0_PLL)
|
||||
|
||||
@@ -1,8 +1,18 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
|
||||
#include <dt-bindings/clock/clock.h>
|
||||
|
||||
#ifndef _KUNIT_CLK_ASSIGNED_RATES_H
|
||||
#define _KUNIT_CLK_ASSIGNED_RATES_H
|
||||
|
||||
#define ASSIGNED_RATES_0_RATE 1600000
|
||||
#define ASSIGNED_RATES_1_RATE 9700000
|
||||
|
||||
#define ASSIGNED_SSCS_0_MODFREQ 10000
|
||||
#define ASSIGNED_SSCS_0_SPREAD 30000
|
||||
#define ASSIGNED_SSCS_0_METHOD CLK_SSC_CENTER_SPREAD
|
||||
#define ASSIGNED_SSCS_1_MODFREQ 20000
|
||||
#define ASSIGNED_SSCS_1_SPREAD 40000
|
||||
#define ASSIGNED_SSCS_1_METHOD CLK_SSC_UP_SPREAD
|
||||
|
||||
#endif
|
||||
|
||||
@@ -12,5 +12,11 @@
|
||||
<&clk 1>;
|
||||
assigned-clock-rates-u64 = /bits/ 64 <ASSIGNED_RATES_0_RATE>,
|
||||
/bits/ 64 <ASSIGNED_RATES_1_RATE>;
|
||||
assigned-clock-sscs = <ASSIGNED_SSCS_0_MODFREQ
|
||||
ASSIGNED_SSCS_0_SPREAD
|
||||
ASSIGNED_SSCS_0_METHOD>,
|
||||
<ASSIGNED_SSCS_1_MODFREQ
|
||||
ASSIGNED_SSCS_1_SPREAD
|
||||
ASSIGNED_SSCS_1_METHOD>;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -16,5 +16,11 @@
|
||||
<&clk 1>;
|
||||
assigned-clock-rates-u64 = /bits/ 64 <ASSIGNED_RATES_0_RATE>,
|
||||
/bits/ 64 <ASSIGNED_RATES_1_RATE>;
|
||||
assigned-clock-sscs = <ASSIGNED_SSCS_0_MODFREQ
|
||||
ASSIGNED_SSCS_0_SPREAD
|
||||
ASSIGNED_SSCS_0_METHOD>,
|
||||
<ASSIGNED_SSCS_1_MODFREQ
|
||||
ASSIGNED_SSCS_1_SPREAD
|
||||
ASSIGNED_SSCS_1_METHOD>;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -10,5 +10,8 @@
|
||||
#clock-cells = <0>;
|
||||
assigned-clocks = <&clk>;
|
||||
assigned-clock-rates-u64 = /bits/ 64 <ASSIGNED_RATES_0_RATE>;
|
||||
assigned-clock-sscs = <ASSIGNED_SSCS_0_MODFREQ
|
||||
ASSIGNED_SSCS_0_SPREAD
|
||||
ASSIGNED_SSCS_0_METHOD>;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -14,5 +14,8 @@
|
||||
compatible = "test,clk-consumer";
|
||||
assigned-clocks = <&clk>;
|
||||
assigned-clock-rates-u64 = /bits/ 64 <ASSIGNED_RATES_0_RATE>;
|
||||
assigned-clock-sscs = <ASSIGNED_SSCS_0_MODFREQ
|
||||
ASSIGNED_SSCS_0_SPREAD
|
||||
ASSIGNED_SSCS_0_METHOD>;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/dts-v1/;
|
||||
/plugin/;
|
||||
|
||||
#include "kunit_clk_assigned_rates.h"
|
||||
|
||||
&{/} {
|
||||
clk: kunit-clock {
|
||||
compatible = "test,clk-assigned-rates";
|
||||
#clock-cells = <1>;
|
||||
assigned-clocks = <&clk 0>,
|
||||
<&clk 1>;
|
||||
assigned-clock-sscs = <ASSIGNED_SSCS_0_MODFREQ
|
||||
ASSIGNED_SSCS_0_SPREAD
|
||||
ASSIGNED_SSCS_0_METHOD>,
|
||||
<ASSIGNED_SSCS_1_MODFREQ
|
||||
ASSIGNED_SSCS_1_SPREAD
|
||||
ASSIGNED_SSCS_1_METHOD>;
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,24 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/dts-v1/;
|
||||
/plugin/;
|
||||
|
||||
#include "kunit_clk_assigned_rates.h"
|
||||
|
||||
&{/} {
|
||||
clk: kunit-clock {
|
||||
compatible = "test,clk-assigned-rates";
|
||||
#clock-cells = <1>;
|
||||
};
|
||||
|
||||
kunit-clock-consumer {
|
||||
compatible = "test,clk-consumer";
|
||||
assigned-clocks = <&clk 0>,
|
||||
<&clk 1>;
|
||||
assigned-clock-sscs = <ASSIGNED_SSCS_0_MODFREQ
|
||||
ASSIGNED_SSCS_0_SPREAD
|
||||
ASSIGNED_SSCS_0_METHOD>,
|
||||
<ASSIGNED_SSCS_1_MODFREQ
|
||||
ASSIGNED_SSCS_1_SPREAD
|
||||
ASSIGNED_SSCS_1_METHOD>;
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,16 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/dts-v1/;
|
||||
/plugin/;
|
||||
|
||||
#include "kunit_clk_assigned_rates.h"
|
||||
|
||||
&{/} {
|
||||
clk: kunit-clock {
|
||||
compatible = "test,clk-assigned-rates";
|
||||
#clock-cells = <0>;
|
||||
assigned-clocks = <0>;
|
||||
assigned-clock-sscs = <ASSIGNED_SSCS_0_MODFREQ
|
||||
ASSIGNED_SSCS_0_SPREAD
|
||||
ASSIGNED_SSCS_0_METHOD>;
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,20 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/dts-v1/;
|
||||
/plugin/;
|
||||
|
||||
#include "kunit_clk_assigned_rates.h"
|
||||
|
||||
&{/} {
|
||||
clk: kunit-clock {
|
||||
compatible = "test,clk-assigned-rates";
|
||||
#clock-cells = <0>;
|
||||
};
|
||||
|
||||
kunit-clock-consumer {
|
||||
compatible = "test,clk-consumer";
|
||||
assigned-clocks = <0>;
|
||||
assigned-clock-sscs = <ASSIGNED_SSCS_0_MODFREQ
|
||||
ASSIGNED_SSCS_0_SPREAD
|
||||
ASSIGNED_SSCS_0_METHOD>;
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,16 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/dts-v1/;
|
||||
/plugin/;
|
||||
|
||||
#include "kunit_clk_assigned_rates.h"
|
||||
|
||||
&{/} {
|
||||
clk: kunit-clock {
|
||||
compatible = "test,clk-assigned-rates";
|
||||
#clock-cells = <0>;
|
||||
assigned-clocks = <&clk>;
|
||||
assigned-clock-sscs = <ASSIGNED_SSCS_0_MODFREQ
|
||||
ASSIGNED_SSCS_0_SPREAD
|
||||
ASSIGNED_SSCS_0_METHOD>;
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,20 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/dts-v1/;
|
||||
/plugin/;
|
||||
|
||||
#include "kunit_clk_assigned_rates.h"
|
||||
|
||||
&{/} {
|
||||
clk: kunit-clock {
|
||||
compatible = "test,clk-assigned-rates";
|
||||
#clock-cells = <0>;
|
||||
};
|
||||
|
||||
kunit-clock-consumer {
|
||||
compatible = "test,clk-consumer";
|
||||
assigned-clocks = <&clk>;
|
||||
assigned-clock-sscs = <ASSIGNED_SSCS_0_MODFREQ
|
||||
ASSIGNED_SSCS_0_SPREAD
|
||||
ASSIGNED_SSCS_0_METHOD>;
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,15 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/dts-v1/;
|
||||
/plugin/;
|
||||
|
||||
#include "kunit_clk_assigned_rates.h"
|
||||
|
||||
&{/} {
|
||||
clk: kunit-clock {
|
||||
compatible = "test,clk-assigned-rates";
|
||||
#clock-cells = <0>;
|
||||
assigned-clock-sscs = <ASSIGNED_SSCS_0_MODFREQ
|
||||
ASSIGNED_SSCS_0_SPREAD
|
||||
ASSIGNED_SSCS_0_METHOD>;
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,19 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/dts-v1/;
|
||||
/plugin/;
|
||||
|
||||
#include "kunit_clk_assigned_rates.h"
|
||||
|
||||
&{/} {
|
||||
clk: kunit-clock {
|
||||
compatible = "test,clk-assigned-rates";
|
||||
#clock-cells = <0>;
|
||||
};
|
||||
|
||||
kunit-clock-consumer {
|
||||
compatible = "test,clk-consumer";
|
||||
assigned-clock-sscs = <ASSIGNED_SSCS_0_MODFREQ
|
||||
ASSIGNED_SSCS_0_SPREAD
|
||||
ASSIGNED_SSCS_0_METHOD>;
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,12 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/dts-v1/;
|
||||
/plugin/;
|
||||
|
||||
&{/} {
|
||||
clk: kunit-clock {
|
||||
compatible = "test,clk-assigned-rates";
|
||||
#clock-cells = <0>;
|
||||
assigned-clocks = <&clk>;
|
||||
assigned-clock-sscs = <0 0 0>;
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,16 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/dts-v1/;
|
||||
/plugin/;
|
||||
|
||||
&{/} {
|
||||
clk: kunit-clock {
|
||||
compatible = "test,clk-assigned-rates";
|
||||
#clock-cells = <0>;
|
||||
};
|
||||
|
||||
kunit-clock-consumer {
|
||||
compatible = "test,clk-consumer";
|
||||
assigned-clocks = <&clk>;
|
||||
assigned-clock-sscs = <0 0 0>;
|
||||
};
|
||||
};
|
||||
@@ -537,6 +537,16 @@ config COMMON_CLK_MT8173_IMGSYS
|
||||
help
|
||||
This driver supports MediaTek MT8173 imgsys clocks.
|
||||
|
||||
config COMMON_CLK_MT8173_MFGTOP
|
||||
tristate "Clock and power driver for MediaTek MT8173 mfgtop"
|
||||
depends on COMMON_CLK_MT8173
|
||||
depends on PM
|
||||
default COMMON_CLK_MT8173
|
||||
select PM_GENERIC_DOMAINS
|
||||
select PM_GENERIC_DOMAINS_OF
|
||||
help
|
||||
This driver supports MediaTek MT8173 mfgtop clocks and power domain.
|
||||
|
||||
config COMMON_CLK_MT8173_MMSYS
|
||||
tristate "Clock driver for MediaTek MT8173 mmsys"
|
||||
depends on COMMON_CLK_MT8173
|
||||
@@ -1006,6 +1016,7 @@ config COMMON_CLK_MT8196
|
||||
tristate "Clock driver for MediaTek MT8196"
|
||||
depends on ARM64 || COMPILE_TEST
|
||||
select COMMON_CLK_MEDIATEK
|
||||
select REGMAP_MMIO
|
||||
default ARCH_MEDIATEK
|
||||
help
|
||||
This driver supports MediaTek MT8196 basic clocks.
|
||||
|
||||
@@ -82,6 +82,7 @@ obj-$(CONFIG_COMMON_CLK_MT8167_VDECSYS) += clk-mt8167-vdec.o
|
||||
obj-$(CONFIG_COMMON_CLK_MT8173) += clk-mt8173-apmixedsys.o clk-mt8173-infracfg.o \
|
||||
clk-mt8173-pericfg.o clk-mt8173-topckgen.o
|
||||
obj-$(CONFIG_COMMON_CLK_MT8173_IMGSYS) += clk-mt8173-img.o
|
||||
obj-$(CONFIG_COMMON_CLK_MT8173_MFGTOP) += clk-mt8173-mfgtop.o
|
||||
obj-$(CONFIG_COMMON_CLK_MT8173_MMSYS) += clk-mt8173-mm.o
|
||||
obj-$(CONFIG_COMMON_CLK_MT8173_VDECSYS) += clk-mt8173-vdecsys.o
|
||||
obj-$(CONFIG_COMMON_CLK_MT8173_VENCSYS) += clk-mt8173-vencsys.o
|
||||
|
||||
@@ -102,9 +102,12 @@ static int clk_mt6735_apmixed_probe(struct platform_device *pdev)
|
||||
|
||||
ret = devm_of_clk_add_hw_provider(&pdev->dev, of_clk_hw_onecell_get,
|
||||
clk_data);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev,
|
||||
"Failed to register clock provider: %d\n", ret);
|
||||
mtk_clk_unregister_plls(apmixedsys_plls, ARRAY_SIZE(apmixedsys_plls),
|
||||
clk_data);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -63,6 +63,7 @@ static const struct of_device_id of_match_mt6735_vdecsys[] = {
|
||||
{ .compatible = "mediatek,mt6735-vdecsys", .data = &vdecsys_clks },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, of_match_mt6735_vdecsys);
|
||||
|
||||
static struct platform_driver clk_mt6735_vdecsys = {
|
||||
.probe = mtk_clk_simple_probe,
|
||||
|
||||
@@ -37,6 +37,7 @@ static const struct of_device_id of_match_mt6735_vencsys[] = {
|
||||
{ .compatible = "mediatek,mt6735-vencsys", .data = &vencsys_clks },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, of_match_mt6735_vencsys);
|
||||
|
||||
static struct platform_driver clk_mt6735_vencsys = {
|
||||
.probe = mtk_clk_simple_probe,
|
||||
|
||||
@@ -409,6 +409,9 @@ static const struct mtk_gate_regs infra_cg_regs = {
|
||||
GATE_MTK_FLAGS(_id, _name, _parent, &infra_cg_regs, _shift, \
|
||||
&mtk_clk_gate_ops_setclr, CLK_IS_CRITICAL)
|
||||
|
||||
#define GATE_ICG_INV(_id, _name, _parent, _shift) \
|
||||
GATE_MTK(_id, _name, _parent, &infra_cg_regs, _shift, &mtk_clk_gate_ops_setclr_inv)
|
||||
|
||||
static const struct mtk_gate infra_clks[] = {
|
||||
GATE_DUMMY(CLK_DUMMY, "infra_dummy"),
|
||||
GATE_ICG(CLK_INFRA_PMIC_WRAP, "pmic_wrap_ck", "axi_sel", 23),
|
||||
@@ -419,7 +422,7 @@ static const struct mtk_gate infra_clks[] = {
|
||||
GATE_ICG(CLK_INFRA_CPUM, "cpum_ck", "cpum_tck_in", 15),
|
||||
GATE_ICG_AO(CLK_INFRA_M4U, "m4u_ck", "mem_sel", 8),
|
||||
GATE_ICG(CLK_INFRA_MFGAXI, "mfgaxi_ck", "axi_sel", 7),
|
||||
GATE_ICG(CLK_INFRA_DEVAPC, "devapc_ck", "axi_sel", 6),
|
||||
GATE_ICG_INV(CLK_INFRA_DEVAPC, "devapc_ck", "axi_sel", 6),
|
||||
GATE_ICG(CLK_INFRA_AUDIO, "audio_ck", "aud_intbus_sel", 5),
|
||||
GATE_ICG(CLK_INFRA_MFG_BUS, "mfg_bus_ck", "axi_sel", 2),
|
||||
GATE_ICG(CLK_INFRA_SMI, "smi_ck", "smi_sel", 1),
|
||||
|
||||
@@ -0,0 +1,242 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2024 Google LLC
|
||||
* Author: Chen-Yu Tsai <wenst@chromium.org>
|
||||
*
|
||||
* Based on driver in downstream ChromeOS v5.15 kernel.
|
||||
*
|
||||
* Copyright (c) 2014 MediaTek Inc.
|
||||
* Author: Chiawen Lee <chiawen.lee@mediatek.com>
|
||||
*/
|
||||
|
||||
#include <dt-bindings/clock/mt8173-clk.h>
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_domain.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#include "clk-gate.h"
|
||||
#include "clk-mtk.h"
|
||||
|
||||
static const struct mtk_gate_regs mfg_cg_regs = {
|
||||
.sta_ofs = 0x0000,
|
||||
.clr_ofs = 0x0008,
|
||||
.set_ofs = 0x0004,
|
||||
};
|
||||
|
||||
#define GATE_MFG(_id, _name, _parent, _shift, _flags) \
|
||||
GATE_MTK_FLAGS(_id, _name, _parent, &mfg_cg_regs, _shift, &mtk_clk_gate_ops_setclr, _flags)
|
||||
|
||||
/* TODO: The block actually has dividers for the core and mem clocks. */
|
||||
static const struct mtk_gate mfg_clks[] = {
|
||||
GATE_MFG(CLK_MFG_AXI, "mfg_axi", "axi_mfg_in_sel", 0, CLK_SET_RATE_PARENT),
|
||||
GATE_MFG(CLK_MFG_MEM, "mfg_mem", "mem_mfg_in_sel", 1, CLK_SET_RATE_PARENT),
|
||||
GATE_MFG(CLK_MFG_G3D, "mfg_g3d", "mfg_sel", 2, CLK_SET_RATE_PARENT),
|
||||
GATE_MFG(CLK_MFG_26M, "mfg_26m", "clk26m", 3, 0),
|
||||
};
|
||||
|
||||
struct mt8173_mfgtop_data {
|
||||
struct clk_hw_onecell_data *clk_data;
|
||||
struct regmap *regmap;
|
||||
struct generic_pm_domain genpd;
|
||||
struct of_phandle_args parent_pd, child_pd;
|
||||
struct clk *clk_26m;
|
||||
};
|
||||
|
||||
/* Delay count in clock cycles */
|
||||
#define MFG_ACTIVE_POWER_CON0 0x24
|
||||
#define RST_B_DELAY_CNT GENMASK(7, 0) /* pwr_rst_b de-assert delay during power-up */
|
||||
#define CLK_EN_DELAY_CNT GENMASK(15, 8) /* CLK_DIS deassert delay during power-up */
|
||||
#define CLK_DIS_DELAY_CNT GENMASK(23, 16) /* CLK_DIS assert delay during power-down */
|
||||
#define FORCE_ABORT BIT(30) /* write 1 to force abort a power event */
|
||||
#define ACTIVE_PWRCTL_EN BIT(31) /* enable ACTIVE_POWER */
|
||||
|
||||
#define MFG_ACTIVE_POWER_CON1 0x28
|
||||
#define PWR_ON_S_DELAY_CNT GENMASK(7, 0) /* pwr_on_s assert delay during power-up */
|
||||
#define ISO_DELAY_CNT GENMASK(15, 8) /* ISO assert delay during power-down */
|
||||
#define ISOOFF_DELAY_CNT GENMASK(23, 16) /* ISO de-assert delay during power-up */
|
||||
#define RST_DELAY_CNT GENMASK(31, 24) /* pwr_rsb_b assert delay during power-down */
|
||||
|
||||
static int clk_mt8173_mfgtop_power_on(struct generic_pm_domain *domain)
|
||||
{
|
||||
struct mt8173_mfgtop_data *data = container_of(domain, struct mt8173_mfgtop_data, genpd);
|
||||
int ret;
|
||||
|
||||
/* drives internal power management */
|
||||
ret = clk_prepare_enable(data->clk_26m);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Power on/off delays for various signals */
|
||||
regmap_write(data->regmap, MFG_ACTIVE_POWER_CON0,
|
||||
FIELD_PREP(RST_B_DELAY_CNT, 77) |
|
||||
FIELD_PREP(CLK_EN_DELAY_CNT, 61) |
|
||||
FIELD_PREP(CLK_DIS_DELAY_CNT, 60) |
|
||||
FIELD_PREP(ACTIVE_PWRCTL_EN, 0));
|
||||
regmap_write(data->regmap, MFG_ACTIVE_POWER_CON1,
|
||||
FIELD_PREP(PWR_ON_S_DELAY_CNT, 11) |
|
||||
FIELD_PREP(ISO_DELAY_CNT, 68) |
|
||||
FIELD_PREP(ISOOFF_DELAY_CNT, 69) |
|
||||
FIELD_PREP(RST_DELAY_CNT, 77));
|
||||
|
||||
/* Magic numbers related to core switch sequence and delays */
|
||||
regmap_write(data->regmap, 0xe0, 0x7a710184);
|
||||
regmap_write(data->regmap, 0xe4, 0x835f6856);
|
||||
regmap_write(data->regmap, 0xe8, 0x002b0234);
|
||||
regmap_write(data->regmap, 0xec, 0x80000000);
|
||||
regmap_write(data->regmap, 0xa0, 0x08000000);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int clk_mt8173_mfgtop_power_off(struct generic_pm_domain *domain)
|
||||
{
|
||||
struct mt8173_mfgtop_data *data = container_of(domain, struct mt8173_mfgtop_data, genpd);
|
||||
|
||||
/* Magic numbers related to core switch sequence and delays */
|
||||
regmap_write(data->regmap, 0xec, 0);
|
||||
|
||||
/* drives internal power management */
|
||||
clk_disable_unprepare(data->clk_26m);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int clk_mt8173_mfgtop_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct device_node *node = dev->of_node;
|
||||
struct mt8173_mfgtop_data *data;
|
||||
int ret;
|
||||
|
||||
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
platform_set_drvdata(pdev, data);
|
||||
|
||||
data->clk_data = mtk_devm_alloc_clk_data(dev, ARRAY_SIZE(mfg_clks));
|
||||
if (!data->clk_data)
|
||||
return -ENOMEM;
|
||||
|
||||
/* MTK clock gates also uses regmap */
|
||||
data->regmap = device_node_to_regmap(node);
|
||||
if (IS_ERR(data->regmap))
|
||||
return dev_err_probe(dev, PTR_ERR(data->regmap), "Failed to get regmap\n");
|
||||
|
||||
data->child_pd.np = node;
|
||||
data->child_pd.args_count = 0;
|
||||
ret = of_parse_phandle_with_args(node, "power-domains", "#power-domain-cells", 0,
|
||||
&data->parent_pd);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "Failed to parse power domain\n");
|
||||
|
||||
devm_pm_runtime_enable(dev);
|
||||
/*
|
||||
* Do a pm_runtime_resume_and_get() to workaround a possible
|
||||
* deadlock between clk_register() and the genpd framework.
|
||||
*/
|
||||
ret = pm_runtime_resume_and_get(dev);
|
||||
if (ret) {
|
||||
dev_err_probe(dev, ret, "Failed to runtime resume device\n");
|
||||
goto put_of_node;
|
||||
}
|
||||
|
||||
ret = mtk_clk_register_gates(dev, node, mfg_clks, ARRAY_SIZE(mfg_clks),
|
||||
data->clk_data);
|
||||
if (ret) {
|
||||
dev_err_probe(dev, ret, "Failed to register clock gates\n");
|
||||
goto put_pm_runtime;
|
||||
}
|
||||
|
||||
data->clk_26m = clk_hw_get_clk(data->clk_data->hws[CLK_MFG_26M], "26m");
|
||||
if (IS_ERR(data->clk_26m)) {
|
||||
ret = dev_err_probe(dev, PTR_ERR(data->clk_26m), "Failed to get 26 MHz clock\n");
|
||||
goto unregister_clks;
|
||||
}
|
||||
|
||||
ret = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, data->clk_data);
|
||||
if (ret) {
|
||||
dev_err_probe(dev, ret, "Failed to add clk OF provider\n");
|
||||
goto put_26m_clk;
|
||||
}
|
||||
|
||||
data->genpd.name = "mfg-top";
|
||||
data->genpd.power_on = clk_mt8173_mfgtop_power_on;
|
||||
data->genpd.power_off = clk_mt8173_mfgtop_power_off;
|
||||
ret = pm_genpd_init(&data->genpd, NULL, true);
|
||||
if (ret) {
|
||||
dev_err_probe(dev, ret, "Failed to add power domain\n");
|
||||
goto del_clk_provider;
|
||||
}
|
||||
|
||||
ret = of_genpd_add_provider_simple(node, &data->genpd);
|
||||
if (ret) {
|
||||
dev_err_probe(dev, ret, "Failed to add power domain OF provider\n");
|
||||
goto remove_pd;
|
||||
}
|
||||
|
||||
ret = of_genpd_add_subdomain(&data->parent_pd, &data->child_pd);
|
||||
if (ret) {
|
||||
dev_err_probe(dev, ret, "Failed to link PM domains\n");
|
||||
goto del_pd_provider;
|
||||
}
|
||||
|
||||
pm_runtime_put(dev);
|
||||
return 0;
|
||||
|
||||
del_pd_provider:
|
||||
of_genpd_del_provider(node);
|
||||
remove_pd:
|
||||
pm_genpd_remove(&data->genpd);
|
||||
del_clk_provider:
|
||||
of_clk_del_provider(node);
|
||||
put_26m_clk:
|
||||
clk_put(data->clk_26m);
|
||||
unregister_clks:
|
||||
mtk_clk_unregister_gates(mfg_clks, ARRAY_SIZE(mfg_clks), data->clk_data);
|
||||
put_pm_runtime:
|
||||
pm_runtime_put_sync(dev);
|
||||
put_of_node:
|
||||
of_node_put(data->parent_pd.np);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void clk_mt8173_mfgtop_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct mt8173_mfgtop_data *data = platform_get_drvdata(pdev);
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
|
||||
of_genpd_remove_subdomain(&data->parent_pd, &data->child_pd);
|
||||
of_genpd_del_provider(node);
|
||||
pm_genpd_remove(&data->genpd);
|
||||
of_clk_del_provider(node);
|
||||
clk_put(data->clk_26m);
|
||||
mtk_clk_unregister_gates(mfg_clks, ARRAY_SIZE(mfg_clks), data->clk_data);
|
||||
of_node_put(data->parent_pd.np);
|
||||
}
|
||||
|
||||
static const struct of_device_id of_match_clk_mt8173_mfgtop[] = {
|
||||
{ .compatible = "mediatek,mt8173-mfgtop" },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, of_match_clk_mt8173_mfgtop);
|
||||
|
||||
static struct platform_driver clk_mt8173_mfgtop_drv = {
|
||||
.probe = clk_mt8173_mfgtop_probe,
|
||||
.remove = clk_mt8173_mfgtop_remove,
|
||||
.driver = {
|
||||
.name = "clk-mt8173-mfgtop",
|
||||
.of_match_table = of_match_clk_mt8173_mfgtop,
|
||||
},
|
||||
};
|
||||
module_platform_driver(clk_mt8173_mfgtop_drv);
|
||||
|
||||
MODULE_DESCRIPTION("MediaTek MT8173 mfgtop clock driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
@@ -629,7 +629,6 @@ static const struct regmap_config vlpckgen_regmap_config = {
|
||||
.val_bits = 32,
|
||||
.reg_stride = 4,
|
||||
.max_register = 0x1000,
|
||||
.fast_io = true,
|
||||
};
|
||||
|
||||
static int clk_mt8196_vlp_probe(struct platform_device *pdev)
|
||||
|
||||
@@ -197,12 +197,56 @@ static void mtk_clk_unregister_pllfh(struct clk_hw *hw)
|
||||
kfree(fh);
|
||||
}
|
||||
|
||||
static void mtk_clk_cleanup_pllfhs(void __iomem *iomem_base,
|
||||
const struct mtk_pll_data *plls, int num_plls,
|
||||
void __iomem *iomem_fhctl_base,
|
||||
struct mtk_pllfh_data *pllfhs, int num_fhs,
|
||||
struct clk_hw_onecell_data *clk_data)
|
||||
{
|
||||
void __iomem *base = iomem_base;
|
||||
void __iomem *fhctl_base = iomem_fhctl_base;
|
||||
int i;
|
||||
|
||||
for (i = num_plls - 1; i >= 0; i--) {
|
||||
const struct mtk_pll_data *pll = &plls[i];
|
||||
struct mtk_pllfh_data *pllfh;
|
||||
bool use_fhctl;
|
||||
|
||||
if (IS_ERR_OR_NULL(clk_data->hws[pll->id]))
|
||||
continue;
|
||||
|
||||
pllfh = get_pllfh_by_id(pllfhs, num_fhs, pll->id);
|
||||
use_fhctl = fhctl_is_supported_and_enabled(pllfh);
|
||||
|
||||
if (!base)
|
||||
base = mtk_clk_pll_get_base(clk_data->hws[pll->id],
|
||||
pll);
|
||||
|
||||
if (use_fhctl) {
|
||||
if (!fhctl_base)
|
||||
fhctl_base = pllfh->state.base;
|
||||
mtk_clk_unregister_pllfh(clk_data->hws[pll->id]);
|
||||
} else {
|
||||
mtk_clk_unregister_pll(clk_data->hws[pll->id]);
|
||||
}
|
||||
|
||||
clk_data->hws[pll->id] = ERR_PTR(-ENOENT);
|
||||
}
|
||||
|
||||
if (fhctl_base)
|
||||
iounmap(fhctl_base);
|
||||
|
||||
if (base)
|
||||
iounmap(base);
|
||||
}
|
||||
|
||||
|
||||
int mtk_clk_register_pllfhs(struct device *dev,
|
||||
const struct mtk_pll_data *plls, int num_plls,
|
||||
struct mtk_pllfh_data *pllfhs, int num_fhs,
|
||||
struct clk_hw_onecell_data *clk_data)
|
||||
{
|
||||
void __iomem *base;
|
||||
void __iomem *base, *fhctl_base = NULL;
|
||||
int i;
|
||||
struct clk_hw *hw;
|
||||
|
||||
@@ -238,24 +282,8 @@ int mtk_clk_register_pllfhs(struct device *dev,
|
||||
return 0;
|
||||
|
||||
err:
|
||||
while (--i >= 0) {
|
||||
const struct mtk_pll_data *pll = &plls[i];
|
||||
struct mtk_pllfh_data *pllfh;
|
||||
bool use_fhctl;
|
||||
|
||||
pllfh = get_pllfh_by_id(pllfhs, num_fhs, pll->id);
|
||||
use_fhctl = fhctl_is_supported_and_enabled(pllfh);
|
||||
|
||||
if (use_fhctl)
|
||||
mtk_clk_unregister_pllfh(clk_data->hws[pll->id]);
|
||||
else
|
||||
mtk_clk_unregister_pll(clk_data->hws[pll->id]);
|
||||
|
||||
clk_data->hws[pll->id] = ERR_PTR(-ENOENT);
|
||||
}
|
||||
|
||||
iounmap(base);
|
||||
|
||||
mtk_clk_cleanup_pllfhs(base, plls, i, fhctl_base, pllfhs, num_fhs,
|
||||
clk_data);
|
||||
return PTR_ERR(hw);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mtk_clk_register_pllfhs);
|
||||
@@ -264,38 +292,10 @@ void mtk_clk_unregister_pllfhs(const struct mtk_pll_data *plls, int num_plls,
|
||||
struct mtk_pllfh_data *pllfhs, int num_fhs,
|
||||
struct clk_hw_onecell_data *clk_data)
|
||||
{
|
||||
void __iomem *base = NULL, *fhctl_base = NULL;
|
||||
int i;
|
||||
|
||||
if (!clk_data)
|
||||
return;
|
||||
|
||||
for (i = num_plls; i > 0; i--) {
|
||||
const struct mtk_pll_data *pll = &plls[i - 1];
|
||||
struct mtk_pllfh_data *pllfh;
|
||||
bool use_fhctl;
|
||||
|
||||
if (IS_ERR_OR_NULL(clk_data->hws[pll->id]))
|
||||
continue;
|
||||
|
||||
pllfh = get_pllfh_by_id(pllfhs, num_fhs, pll->id);
|
||||
use_fhctl = fhctl_is_supported_and_enabled(pllfh);
|
||||
|
||||
if (use_fhctl) {
|
||||
fhctl_base = pllfh->state.base;
|
||||
mtk_clk_unregister_pllfh(clk_data->hws[pll->id]);
|
||||
} else {
|
||||
base = mtk_clk_pll_get_base(clk_data->hws[pll->id],
|
||||
pll);
|
||||
mtk_clk_unregister_pll(clk_data->hws[pll->id]);
|
||||
}
|
||||
|
||||
clk_data->hws[pll->id] = ERR_PTR(-ENOENT);
|
||||
}
|
||||
|
||||
if (fhctl_base)
|
||||
iounmap(fhctl_base);
|
||||
|
||||
iounmap(base);
|
||||
mtk_clk_cleanup_pllfhs(NULL, plls, num_plls, NULL, pllfhs,
|
||||
num_fhs, clk_data);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mtk_clk_unregister_pllfhs);
|
||||
|
||||
@@ -285,7 +285,7 @@ static int mpfs_cfg_clk_set_rate(struct clk_hw *hw, unsigned long rate, unsigned
|
||||
|
||||
mask = clk_div_mask(cfg->width) << cfg->shift;
|
||||
val = divider_setting << cfg->shift;
|
||||
regmap_update_bits(cfg->map, cfg->map_offset, val, mask);
|
||||
regmap_update_bits(cfg->map, cfg->map_offset, mask, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@ static void pxa1908_clk_reset_init(struct device_node *np,
|
||||
cells[i].bits = BIT(2);
|
||||
cells[i].flags = 0;
|
||||
cells[i].lock = apbc_gate_clks[i].lock;
|
||||
};
|
||||
}
|
||||
|
||||
mmp_clk_reset_register(np, cells, nr_cells);
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ static void pxa1908_clk_reset_init(struct device_node *np,
|
||||
cells[i].bits = BIT(2);
|
||||
cells[i].flags = 0;
|
||||
cells[i].lock = apbcp_gate_clks[i].lock;
|
||||
};
|
||||
}
|
||||
|
||||
mmp_clk_reset_register(np, cells, nr_cells);
|
||||
}
|
||||
|
||||
@@ -153,7 +153,7 @@ static int clk_cpu_on_set_rate(struct clk_hw *hwclk, unsigned long rate,
|
||||
static int clk_cpu_set_rate(struct clk_hw *hwclk, unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
if (__clk_is_enabled(hwclk->clk))
|
||||
if (clk_hw_is_enabled(hwclk))
|
||||
return clk_cpu_on_set_rate(hwclk, rate, parent_rate);
|
||||
else
|
||||
return clk_cpu_off_set_rate(hwclk, rate, parent_rate);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user