* [PATCH 00/10] Add support for A9 family clock controller
@ 2026-05-11 12:47 Jian Hu via B4 Relay
2026-05-11 12:47 ` [PATCH 01/10] dt-bindings: clock: Add Amlogic A9 SCMI " Jian Hu via B4 Relay
` (9 more replies)
0 siblings, 10 replies; 17+ messages in thread
From: Jian Hu via B4 Relay @ 2026-05-11 12:47 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Neil Armstrong, Jerome Brunet, Xianwei Zhao,
Kevin Hilman, Martin Blumenstingl
Cc: linux-kernel, linux-clk, devicetree, linux-amlogic,
linux-arm-kernel, Jian Hu
There are 4 clock controllers in A9 SoC:
- SCMI clock controller: these clocks are managed by the
Trusted Firmware-A(TF-A) and handled through SCMI.
- PLL clock controller.
- peripheral clock controller.
- AO clock controller.
There are reserved register regions placed between individual PLLs, so a
separate driver is implemented for each PLL, similar to T7.
Compared to previous SoCs PLLs, the A9 PLL controller introduces 4 new features:
1.PLL l_detect signal supports active-high configuration.
Previous A7 and T7 l_detect signals are active-low.
2.PLL reset signal supports active-low configuration.
Previous reset signals are active-high.
3.Support POWER_OF_TWO for the PLL pre-divider N;
the N pre-divider follows the same calculation rule as OD.
4.The PLL input path includes an inherent divide-by-2 divider.
Implement the first three features in clk-pll.c (verified on A9 and T7),
with no impact to PLL logic on existing SoCs. Add a fixed divide-by-2 to
A9 PLL driver for the fourth feature.
A9 PLL is composed as follows:
PLL
+---------------------------------+
| |
| +--+ |
in/2 >>---[ /2^N ]-->| | +-----+ |
| | |------| DCO |----->> out
| +--------->| | +--v--+ |
| | +--+ | |
| | | |
| +--[ *(M + (F/Fmax) ]<--+ |
| |
+---------------------------------+
out = in / 2 * (m + frac / frac_max) / 2^n
Signed-off-by: Jian Hu <jian.hu@amlogic.com>
---
Jian Hu (10):
dt-bindings: clock: Add Amlogic A9 SCMI clock controller
dt-bindings: clock: Add Amlogic A9 PLL clock controller
dt-bindings: clock: Add Amlogic A9 peripherals clock controller
dt-bindings: clock: Add Amlogic A9 AO clock controller
clk: amlogic: PLL l_detect signal supports active-high configuration
clk: amlogic: PLL reset signal supports active-low configuration
clk: amlogic: Support POWER_OF_TWO for PLL pre-divider
clk: amlogic: Add A9 PLL clock controller driver
clk: amlogic: Add A9 peripherals clock controller driver
clk: amlogic: Add A9 AO clock controller driver
.../bindings/clock/amlogic,a9-aoclkc.yaml | 76 +
.../clock/amlogic,a9-peripherals-clkc.yaml | 150 ++
.../bindings/clock/amlogic,a9-pll-clkc.yaml | 110 +
drivers/clk/meson/Kconfig | 28 +
drivers/clk/meson/Makefile | 2 +
drivers/clk/meson/a9-aoclk.c | 494 +++++
drivers/clk/meson/a9-peripherals.c | 2317 ++++++++++++++++++++
drivers/clk/meson/a9-pll.c | 831 +++++++
drivers/clk/meson/clk-pll.c | 79 +-
drivers/clk/meson/clk-pll.h | 6 +
include/dt-bindings/clock/amlogic,a9-aoclkc.h | 76 +
.../clock/amlogic,a9-peripherals-clkc.h | 352 +++
include/dt-bindings/clock/amlogic,a9-pll-clkc.h | 55 +
include/dt-bindings/clock/amlogic,a9-scmi-clkc.h | 51 +
14 files changed, 4609 insertions(+), 18 deletions(-)
---
base-commit: ca89c88bcf69daca829044c638a8163d5ce47af0
change-id: 20260511-b4-a9_clk-67652c1ae56e
Best regards,
--
Jian Hu <jian.hu@amlogic.com>
^ permalink raw reply [flat|nested] 17+ messages in thread* [PATCH 01/10] dt-bindings: clock: Add Amlogic A9 SCMI clock controller 2026-05-11 12:47 [PATCH 00/10] Add support for A9 family clock controller Jian Hu via B4 Relay @ 2026-05-11 12:47 ` Jian Hu via B4 Relay 2026-05-11 12:47 ` [PATCH 02/10] dt-bindings: clock: Add Amlogic A9 PLL " Jian Hu via B4 Relay ` (8 subsequent siblings) 9 siblings, 0 replies; 17+ messages in thread From: Jian Hu via B4 Relay @ 2026-05-11 12:47 UTC (permalink / raw) To: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Neil Armstrong, Jerome Brunet, Xianwei Zhao, Kevin Hilman, Martin Blumenstingl Cc: linux-kernel, linux-clk, devicetree, linux-amlogic, linux-arm-kernel, Jian Hu From: Jian Hu <jian.hu@amlogic.com> Add the SCMI clock controller dt-bindings for the Amlogic A9 SoC family. Signed-off-by: Jian Hu <jian.hu@amlogic.com> --- include/dt-bindings/clock/amlogic,a9-scmi-clkc.h | 51 ++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/include/dt-bindings/clock/amlogic,a9-scmi-clkc.h b/include/dt-bindings/clock/amlogic,a9-scmi-clkc.h new file mode 100644 index 000000000000..d543db9fe035 --- /dev/null +++ b/include/dt-bindings/clock/amlogic,a9-scmi-clkc.h @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * Copyright (C) 2026 Amlogic, Inc. All rights reserved. + */ + +#ifndef __AMLOGIC_A9_SCMI_CLKC_H +#define __AMLOGIC_A9_SCMI_CLKC_H + +#define CLKID_GP0_PLL_OSC 0 +#define CLKID_GP1_PLL_OSC 1 +#define CLKID_HIFI_PLL_OSC 2 +#define CLKID_GP2_PLL_OSC 3 +#define CLKID_MCLK_PLL_OSC 4 +#define CLKID_FIXED_PLL 5 +#define CLKID_FCLK_50M_PREDIV 6 +#define CLKID_FCLK_50M_DIV 7 +#define CLKID_FCLK_50M 8 +#define CLKID_FCLK_DIV2_DIV 9 +#define CLKID_FCLK_DIV2 10 +#define CLKID_FCLK_DIV2P5_DIV 11 +#define CLKID_FCLK_DIV2P5 12 +#define CLKID_FCLK_DIV3_DIV 13 +#define CLKID_FCLK_DIV3 14 +#define CLKID_FCLK_DIV4_DIV 15 +#define CLKID_FCLK_DIV4 16 +#define CLKID_FCLK_DIV5_DIV 17 +#define CLKID_FCLK_DIV5 18 +#define CLKID_FCLK_DIV7_DIV 19 +#define CLKID_FCLK_DIV7 20 +#define CLKID_SYS_CLK 21 +#define CLKID_SYS_AO_SYS 22 +#define CLKID_SYS_MMC_APB 23 +#define CLKID_SYS_CPU_APB 24 +#define CLKID_SYS_GIC 25 +#define CLKID_AXI_CLK 26 +#define CLKID_AXI_SYS_NIC 27 +#define CLKID_AXI_RAMA 28 +#define CLKID_CPU_CLK 29 +#define CLKID_A78_CLK 30 +#define CLKID_DSU_CLK 31 +#define CLKID_ACLKM 32 +#define CLKID_GP1_PLL 33 +#define CLKID_GP2_PLL 34 +#define CLKID_SYS_PLL_DIV16 35 +#define CLKID_CPU_CLK_DIV16 36 +#define CLKID_A78_CLK_DIV16 37 +#define CLKID_DSU_CLK_DIV16 38 +#define CLKID_GIC_CLK 39 +#define CLKID_RTC 40 + +#endif /* __AMLOGIC_A9_SCMI_CLKC_H */ -- 2.47.1 ^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 02/10] dt-bindings: clock: Add Amlogic A9 PLL clock controller 2026-05-11 12:47 [PATCH 00/10] Add support for A9 family clock controller Jian Hu via B4 Relay 2026-05-11 12:47 ` [PATCH 01/10] dt-bindings: clock: Add Amlogic A9 SCMI " Jian Hu via B4 Relay @ 2026-05-11 12:47 ` Jian Hu via B4 Relay 2026-05-11 12:47 ` [PATCH 03/10] dt-bindings: clock: Add Amlogic A9 peripherals " Jian Hu via B4 Relay ` (7 subsequent siblings) 9 siblings, 0 replies; 17+ messages in thread From: Jian Hu via B4 Relay @ 2026-05-11 12:47 UTC (permalink / raw) To: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Neil Armstrong, Jerome Brunet, Xianwei Zhao, Kevin Hilman, Martin Blumenstingl Cc: linux-kernel, linux-clk, devicetree, linux-amlogic, linux-arm-kernel, Jian Hu From: Jian Hu <jian.hu@amlogic.com> Add the PLL clock controller dt-bindings for the Amlogic A9 SoC family. Signed-off-by: Jian Hu <jian.hu@amlogic.com> --- .../bindings/clock/amlogic,a9-pll-clkc.yaml | 110 +++++++++++++++++++++ include/dt-bindings/clock/amlogic,a9-pll-clkc.h | 55 +++++++++++ 2 files changed, 165 insertions(+) diff --git a/Documentation/devicetree/bindings/clock/amlogic,a9-pll-clkc.yaml b/Documentation/devicetree/bindings/clock/amlogic,a9-pll-clkc.yaml new file mode 100644 index 000000000000..4ee6013ba1a1 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/amlogic,a9-pll-clkc.yaml @@ -0,0 +1,110 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +# Copyright (C) 2026 Amlogic, Inc. All rights reserved +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/amlogic,a9-pll-clkc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Amlogic A9 Series PLL Clock Controller + +maintainers: + - Neil Armstrong <neil.armstrong@linaro.org> + - Jerome Brunet <jbrunet@baylibre.com> + - Jian Hu <jian.hu@amlogic.com> + - Xianwei Zhao <xianwei.zhao@amlogic.com> + +properties: + compatible: + enum: + - amlogic,a9-gp0-pll + - amlogic,a9-hifi0-pll + - amlogic,a9-hifi1-pll + - amlogic,a9-mclk0-pll + - amlogic,a9-mclk1-pll + + reg: + maxItems: 1 + + '#clock-cells': + const: 1 + + clocks: + items: + - description: pll input oscillator gate + - description: fixed input clock source for mclk_sel_0 + - description: u3p2pll input clock source for mclk_sel_0 (optional) + minItems: 1 + + clock-names: + items: + - const: in0 + - const: in1 + - const: in2 + minItems: 1 + +required: + - compatible + - '#clock-cells' + - reg + - clocks + - clock-names + +allOf: + - if: + properties: + compatible: + contains: + enum: + - amlogic,a9-mclk0-pll + - amlogic,a9-mclk1-pll + + then: + properties: + clocks: + maxItems: 3 + + clock-names: + maxItems: 3 + + - if: + properties: + compatible: + contains: + enum: + - amlogic,a9-gp0-pll + - amlogic,a9-hifi0-pll + - amlogic,a9-hifi1-pll + + then: + properties: + clocks: + maxItems: 1 + + clock-names: + maxItems: 1 + +additionalProperties: false + +examples: + - | + apb4 { + #address-cells = <2>; + #size-cells = <2>; + + clock-controller@8200 { + compatible = "amlogic,a9-gp0-pll"; + reg = <0x0 0x8200 0x0 0x20>; + #clock-cells = <1>; + clocks = <&scmi_clk 0>; + clock-names = "in0"; + }; + + clock-controller@8330 { + compatible = "amlogic,a9-mclk0-pll"; + reg = <0x0 0x8330 0x0 0x14>; + #clock-cells = <1>; + clocks = <&scmi_clk 4>, + <&scmi_clk 8>; + clock-names = "in0", "in1"; + }; + }; diff --git a/include/dt-bindings/clock/amlogic,a9-pll-clkc.h b/include/dt-bindings/clock/amlogic,a9-pll-clkc.h new file mode 100644 index 000000000000..31edb0bc95e7 --- /dev/null +++ b/include/dt-bindings/clock/amlogic,a9-pll-clkc.h @@ -0,0 +1,55 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * Copyright (C) 2026 Amlogic, Inc. All rights reserved. + */ + +#ifndef __AMLOGIC_A9_PLL_CLKC_H +#define __AMLOGIC_A9_PLL_CLKC_H + +/* GP0 */ +#define CLKID_GP0_IN_DIV2_DIV 0 +#define CLKID_GP0_IN_DIV2 1 +#define CLKID_GP0_PLL_DCO 2 +#define CLKID_GP0_PLL 3 + +/* HIFI0 */ +#define CLKID_HIFI0_IN_DIV2_DIV 0 +#define CLKID_HIFI0_IN_DIV2 1 +#define CLKID_HIFI0_PLL_DCO 2 +#define CLKID_HIFI0_PLL 3 + +/* HIFI1 */ +#define CLKID_HIFI1_IN_DIV2_DIV 0 +#define CLKID_HIFI1_IN_DIV2 1 +#define CLKID_HIFI1_PLL_DCO 2 +#define CLKID_HIFI1_PLL 3 + +/* MCLK0 */ +#define CLKID_MCLK0_IN_DIV2 0 +#define CLKID_MCLK0_PLL_DCO 1 +#define CLKID_MCLK0_0_PLL 2 +#define CLKID_MCLK0_0_PRE 3 +#define CLKID_MCLK0_0_SEL 4 +#define CLKID_MCLK0_0_DIV 5 +#define CLKID_MCLK0_0 6 +#define CLKID_MCLK0_1_PLL 7 +#define CLKID_MCLK0_1_PRE 8 +#define CLKID_MCLK0_1_SEL 9 +#define CLKID_MCLK0_1_DIV 10 +#define CLKID_MCLK0_1 11 + +/* MCLK1 */ +#define CLKID_MCLK1_IN_DIV2 0 +#define CLKID_MCLK1_PLL_DCO 1 +#define CLKID_MCLK1_0_PLL 2 +#define CLKID_MCLK1_0_PRE 3 +#define CLKID_MCLK1_0_SEL 4 +#define CLKID_MCLK1_0_DIV 5 +#define CLKID_MCLK1_0 6 +#define CLKID_MCLK1_1_PLL 7 +#define CLKID_MCLK1_1_PRE 8 +#define CLKID_MCLK1_1_SEL 9 +#define CLKID_MCLK1_1_DIV 10 +#define CLKID_MCLK1_1 11 + +#endif /* __AMLOGIC_A9_PLL_CLKC_H */ -- 2.47.1 ^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 03/10] dt-bindings: clock: Add Amlogic A9 peripherals clock controller 2026-05-11 12:47 [PATCH 00/10] Add support for A9 family clock controller Jian Hu via B4 Relay 2026-05-11 12:47 ` [PATCH 01/10] dt-bindings: clock: Add Amlogic A9 SCMI " Jian Hu via B4 Relay 2026-05-11 12:47 ` [PATCH 02/10] dt-bindings: clock: Add Amlogic A9 PLL " Jian Hu via B4 Relay @ 2026-05-11 12:47 ` Jian Hu via B4 Relay 2026-05-11 12:47 ` [PATCH 04/10] dt-bindings: clock: Add Amlogic A9 AO " Jian Hu via B4 Relay ` (6 subsequent siblings) 9 siblings, 0 replies; 17+ messages in thread From: Jian Hu via B4 Relay @ 2026-05-11 12:47 UTC (permalink / raw) To: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Neil Armstrong, Jerome Brunet, Xianwei Zhao, Kevin Hilman, Martin Blumenstingl Cc: linux-kernel, linux-clk, devicetree, linux-amlogic, linux-arm-kernel, Jian Hu From: Jian Hu <jian.hu@amlogic.com> Add the peripherals clock controller dt-bindings for the Amlogic A9 SoC family. Signed-off-by: Jian Hu <jian.hu@amlogic.com> --- .../clock/amlogic,a9-peripherals-clkc.yaml | 150 +++++++++ .../clock/amlogic,a9-peripherals-clkc.h | 352 +++++++++++++++++++++ 2 files changed, 502 insertions(+) diff --git a/Documentation/devicetree/bindings/clock/amlogic,a9-peripherals-clkc.yaml b/Documentation/devicetree/bindings/clock/amlogic,a9-peripherals-clkc.yaml new file mode 100644 index 000000000000..97e2c44d8630 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/amlogic,a9-peripherals-clkc.yaml @@ -0,0 +1,150 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +# Copyright (C) 2026 Amlogic, Inc. All rights reserved +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/amlogic,a9-peripherals-clkc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Amlogic A9 Series Peripherals Clock Controller + +maintainers: + - Neil Armstrong <neil.armstrong@linaro.org> + - Jerome Brunet <jbrunet@baylibre.com> + - Jian Hu <jian.hu@amlogic.com> + - Xianwei Zhao <xianwei.zhao@amlogic.com> + +properties: + compatible: + const: amlogic,a9-peripherals-clkc + + reg: + maxItems: 1 + + '#clock-cells': + const: 1 + + clocks: + minItems: 20 + items: + - description: input oscillator + - description: input fclk div 2 + - description: input fclk div 3 + - description: input fclk div 4 + - description: input fclk div 5 + - description: input fclk div 7 + - description: input fclk div 2p5 + - description: input sys clk + - description: input gp1 pll + - description: input gp2 pll + - description: input sys pll div 16 + - description: input cpu clk div 16 + - description: input a78 clk div 16 + - description: input dsu clk div 16 + - description: input rtc clk + - description: input gp0 pll + - description: input hifi0 pll + - description: input hifi1 pll + - description: input mclk0 pll + - description: input mclk1 pll + - description: input video1 pll (optional) + - description: input video2 pll (optional) + - description: input hdmi out2 clk (optional) + - description: input hdmi pixel clk (optional) + - description: input pixel0 pll (optional) + - description: input pixel1 pll (optional) + - description: input usb2 drd clk (optional) + - description: external input rmii oscillator (optional) + + clock-names: + minItems: 20 + items: + - const: xtal + - const: fdiv2 + - const: fdiv3 + - const: fdiv4 + - const: fdiv5 + - const: fdiv7 + - const: fdiv2p5 + - const: sys + - const: gp1 + - const: gp2 + - const: sysplldiv16 + - const: cpudiv16 + - const: a78div16 + - const: dsudiv16 + - const: rtc + - const: gp0 + - const: hifi0 + - const: hifi1 + - const: mclk0 + - const: mclk1 + - const: vid1 + - const: vid2 + - const: hdmiout2 + - const: hdmipix + - const: pix0 + - const: pix1 + - const: u2drd + - const: ext_rmii + +required: + - compatible + - reg + - '#clock-cells' + - clocks + - clock-names + +additionalProperties: false + +examples: + - | + apb4 { + #address-cells = <2>; + #size-cells = <2>; + + clock-controller@200 { + compatible = "amlogic,a9-peripherals-clkc"; + reg = <0x0 0x200 0x0 0x2f8>; + #clock-cells = <1>; + clocks = <&xtal>, + <&scmi_clk 10>, + <&scmi_clk 12>, + <&scmi_clk 14>, + <&scmi_clk 16>, + <&scmi_clk 18>, + <&scmi_clk 20>, + <&scmi_clk 21>, + <&scmi_clk 33>, + <&scmi_clk 34>, + <&scmi_clk 35>, + <&scmi_clk 36>, + <&scmi_clk 37>, + <&scmi_clk 38>, + <&scmi_clk 40>, + <&gp0 3>, + <&hifi0 3>, + <&hifi1 3>, + <&mclk0 3>, + <&mclk1 3>; + clock-names = "xtal", + "fdiv2", + "fdiv3", + "fdiv4", + "fdiv5", + "fdiv7", + "fdiv2p5", + "sys", + "gp1", + "gp2", + "sysplldiv16", + "cpudiv16", + "a78div16", + "dsudiv16", + "rtc", + "gp0", + "hifi0", + "hifi1", + "mclk0", + "mclk1"; + }; + }; diff --git a/include/dt-bindings/clock/amlogic,a9-peripherals-clkc.h b/include/dt-bindings/clock/amlogic,a9-peripherals-clkc.h new file mode 100644 index 000000000000..bca69771d728 --- /dev/null +++ b/include/dt-bindings/clock/amlogic,a9-peripherals-clkc.h @@ -0,0 +1,352 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * Copyright (C) 2026 Amlogic, Inc. All rights reserved. + */ + +#ifndef __AMLOGIC_A9_PERIPHERALS_CLKC_H +#define __AMLOGIC_A9_PERIPHERALS_CLKC_H + +#define CLKID_SYS_AM_AXI 0 +#define CLKID_SYS_DOS 1 +#define CLKID_SYS_MIPI_DSI 2 +#define CLKID_SYS_ETH_PHY 3 +#define CLKID_SYS_AMFC 4 +#define CLKID_SYS_MALI 5 +#define CLKID_SYS_NNA 6 +#define CLKID_SYS_ETH_AXI 7 +#define CLKID_SYS_DP_APB 8 +#define CLKID_SYS_EDPTX_APB 9 +#define CLKID_SYS_U3HSG 10 +#define CLKID_SYS_AUCPU 11 +#define CLKID_SYS_GLB 12 +#define CLKID_SYS_COMBO_DPHY_APB 13 +#define CLKID_SYS_HDMIRX_APB 14 +#define CLKID_SYS_HDMIRX_PCLK 15 +#define CLKID_SYS_MIPI_DSI_PHY 16 +#define CLKID_SYS_CAN0 17 +#define CLKID_SYS_CAN1 18 +#define CLKID_SYS_SD_EMMC_A 19 +#define CLKID_SYS_SD_EMMC_B 20 +#define CLKID_SYS_SD_EMMC_C 21 +#define CLKID_SYS_SC 22 +#define CLKID_SYS_ACODEC 23 +#define CLKID_SYS_MIPI_ISP 24 +#define CLKID_SYS_MSR 25 +#define CLKID_SYS_AUDIO 26 +#define CLKID_SYS_MIPI_DSI_B 27 +#define CLKID_SYS_MIPI_DSI1_PHY 28 +#define CLKID_SYS_ETH 29 +#define CLKID_SYS_ETH_1G_MAC 30 +#define CLKID_SYS_UART_A 31 +#define CLKID_SYS_UART_F 32 +#define CLKID_SYS_TS_A55 33 +#define CLKID_SYS_ETH_1G_AXI 34 +#define CLKID_SYS_TS_DOS 35 +#define CLKID_SYS_U3DRD_B 36 +#define CLKID_SYS_TS_CORE 37 +#define CLKID_SYS_TS_PLL 38 +#define CLKID_SYS_CSI_DIG_CLKIN 39 +#define CLKID_SYS_CVE 40 +#define CLKID_SYS_GE2D 41 +#define CLKID_SYS_SPISG 42 +#define CLKID_SYS_U3DRD_1 43 +#define CLKID_SYS_U2H 44 +#define CLKID_SYS_PCIE_MAC_A 45 +#define CLKID_SYS_U3DRD_A 46 +#define CLKID_SYS_U2DRD 47 +#define CLKID_SYS_PCIE_PHY 48 +#define CLKID_SYS_PCIE_MAC_B 49 +#define CLKID_SYS_PERIPH 50 +#define CLKID_SYS_PIO 51 +#define CLKID_SYS_I3C 52 +#define CLKID_SYS_I2C_M_E 53 +#define CLKID_SYS_I2C_M_F 54 +#define CLKID_SYS_HDMITX_APB 55 +#define CLKID_SYS_I2C_M_I 56 +#define CLKID_SYS_I2C_M_G 57 +#define CLKID_SYS_I2C_M_H 58 +#define CLKID_SYS_HDMI20_AES 59 +#define CLKID_SYS_CSI2_HOST 60 +#define CLKID_SYS_CSI2_ADAPT 61 +#define CLKID_SYS_DSPA 62 +#define CLKID_SYS_PP_DMA 63 +#define CLKID_SYS_PP_WRAPPER 64 +#define CLKID_SYS_VPU_INTR 65 +#define CLKID_SYS_CSI2_PHY 66 +#define CLKID_SYS_SARADC 67 +#define CLKID_SYS_PWM_J 68 +#define CLKID_SYS_PWM_I 69 +#define CLKID_SYS_PWM_H 70 +#define CLKID_SYS_PWM_N 71 +#define CLKID_SYS_PWM_M 72 +#define CLKID_SYS_PWM_L 73 +#define CLKID_SYS_PWM_K 74 +#define CLKID_SD_EMMC_A_SEL 75 +#define CLKID_SD_EMMC_A_DIV 76 +#define CLKID_SD_EMMC_A 77 +#define CLKID_SD_EMMC_B_SEL 78 +#define CLKID_SD_EMMC_B_DIV 79 +#define CLKID_SD_EMMC_B 80 +#define CLKID_SD_EMMC_C_SEL 81 +#define CLKID_SD_EMMC_C_DIV 82 +#define CLKID_SD_EMMC_C 83 +#define CLKID_PWM_H_SEL 84 +#define CLKID_PWM_H_DIV 85 +#define CLKID_PWM_H 86 +#define CLKID_PWM_I_SEL 87 +#define CLKID_PWM_I_DIV 88 +#define CLKID_PWM_I 89 +#define CLKID_PWM_J_SEL 90 +#define CLKID_PWM_J_DIV 91 +#define CLKID_PWM_J 92 +#define CLKID_PWM_K_SEL 93 +#define CLKID_PWM_K_DIV 94 +#define CLKID_PWM_K 95 +#define CLKID_PWM_L_SEL 96 +#define CLKID_PWM_L_DIV 97 +#define CLKID_PWM_L 98 +#define CLKID_PWM_M_SEL 99 +#define CLKID_PWM_M_DIV 100 +#define CLKID_PWM_M 101 +#define CLKID_PWM_N_SEL 102 +#define CLKID_PWM_N_DIV 103 +#define CLKID_PWM_N 104 +#define CLKID_SPISG_SEL 105 +#define CLKID_SPISG_DIV 106 +#define CLKID_SPISG 107 +#define CLKID_SPISG1_SEL 108 +#define CLKID_SPISG1_DIV 109 +#define CLKID_SPISG1 110 +#define CLKID_SPISG2_SEL 111 +#define CLKID_SPISG2_DIV 112 +#define CLKID_SPISG2 113 +#define CLKID_SARADC_SEL 114 +#define CLKID_SARADC_DIV 115 +#define CLKID_SARADC 116 +#define CLKID_AMFC_SEL 117 +#define CLKID_AMFC_DIV 118 +#define CLKID_AMFC 119 +#define CLKID_NNA_SEL 120 +#define CLKID_NNA_DIV 121 +#define CLKID_NNA 122 +#define CLKID_USB_250M_SEL 123 +#define CLKID_USB_250M_DIV 124 +#define CLKID_USB_250M 125 +#define CLKID_USB_48M_PRE_SEL 126 +#define CLKID_USB_48M_PRE_DIV 127 +#define CLKID_USB_48M_PRE 128 +#define CLKID_PCIE_TL_SEL 129 +#define CLKID_PCIE_TL_DIV 130 +#define CLKID_PCIE_TL 131 +#define CLKID_PCIE1_TL_SEL 132 +#define CLKID_PCIE1_TL_DIV 133 +#define CLKID_PCIE1_TL 134 +#define CLKID_CMPR_SEL 135 +#define CLKID_CMPR_DIV 136 +#define CLKID_CMPR 137 +#define CLKID_DEWARPA_SEL 138 +#define CLKID_DEWARPA_DIV 139 +#define CLKID_DEWARPA 140 +#define CLKID_SC_PRE_SEL 141 +#define CLKID_SC_PRE_DIV 142 +#define CLKID_SC_PRE 143 +#define CLKID_SC 144 +#define CLKID_DPTX_APB2_SEL 145 +#define CLKID_DPTX_APB2_DIV 146 +#define CLKID_DPTX_APB2 147 +#define CLKID_DPTX_AUD_SEL 148 +#define CLKID_DPTX_AUD_DIV 149 +#define CLKID_DPTX_AUD 150 +#define CLKID_ISP_SEL 151 +#define CLKID_ISP_DIV 152 +#define CLKID_ISP 153 +#define CLKID_CVE_SEL 154 +#define CLKID_CVE_DIV 155 +#define CLKID_CVE 156 +#define CLKID_VGE_SEL 157 +#define CLKID_VGE_DIV 158 +#define CLKID_VGE 159 +#define CLKID_PP_SEL 160 +#define CLKID_PP_DIV 161 +#define CLKID_PP 162 +#define CLKID_GLB_SEL 163 +#define CLKID_GLB_DIV 164 +#define CLKID_GLB 165 +#define CLKID_USB_48M_DUALDIV_IN 166 +#define CLKID_USB_48M_DUALDIV_DIV 167 +#define CLKID_USB_48M_DUALDIV_SEL 168 +#define CLKID_USB_48M_DUALDIV 169 +#define CLKID_USB_48M 170 +#define CLKID_CAN_PE_SEL 171 +#define CLKID_CAN_PE_DIV 172 +#define CLKID_CAN_PE 173 +#define CLKID_CAN1_PE_SEL 174 +#define CLKID_CAN1_PE_DIV 175 +#define CLKID_CAN1_PE 176 +#define CLKID_CAN_FILTER_SEL 177 +#define CLKID_CAN_FILTER_DIV 178 +#define CLKID_CAN_FILTER 179 +#define CLKID_CAN1_FILTER_SEL 180 +#define CLKID_CAN1_FILTER_DIV 181 +#define CLKID_CAN1_FILTER 182 +#define CLKID_I3C_SEL 183 +#define CLKID_I3C_DIV 184 +#define CLKID_I3C 185 +#define CLKID_TS_DIV 186 +#define CLKID_TS 187 +#define CLKID_ETH_125M_DIV 188 +#define CLKID_ETH_125M 189 +#define CLKID_ETH_RMII_SEL 190 +#define CLKID_ETH_RMII_DIV 191 +#define CLKID_ETH_RMII 192 +#define CLKID_GEN_SEL 193 +#define CLKID_GEN_DIV 194 +#define CLKID_GEN 195 +#define CLKID_CLK24M_IN 196 +#define CLKID_CLK12_24M 197 +#define CLKID_MALI_0_SEL 198 +#define CLKID_MALI_0_DIV 199 +#define CLKID_MALI_0 200 +#define CLKID_MALI_1_SEL 201 +#define CLKID_MALI_1_DIV 202 +#define CLKID_MALI_1 203 +#define CLKID_MALI 204 +#define CLKID_MALI_STACK_0_SEL 205 +#define CLKID_MALI_STACK_0_DIV 206 +#define CLKID_MALI_STACK_0 207 +#define CLKID_MALI_STACK_1_SEL 208 +#define CLKID_MALI_STACK_1_DIV 209 +#define CLKID_MALI_STACK_1 210 +#define CLKID_MALI_STACK 211 +#define CLKID_DSPA_0_SEL 212 +#define CLKID_DSPA_0_DIV 213 +#define CLKID_DSPA_0 214 +#define CLKID_DSPA_1_SEL 215 +#define CLKID_DSPA_1_DIV 216 +#define CLKID_DSPA_1 217 +#define CLKID_DSPA 218 +#define CLKID_HEVCF_0_SEL 219 +#define CLKID_HEVCF_0_DIV 220 +#define CLKID_HEVCF_0 221 +#define CLKID_HEVCF_1_SEL 222 +#define CLKID_HEVCF_1_DIV 223 +#define CLKID_HEVCF_1 224 +#define CLKID_HEVCF 225 +#define CLKID_HCODEC_0_SEL 226 +#define CLKID_HCODEC_0_DIV 227 +#define CLKID_HCODEC_0 228 +#define CLKID_HCODEC_1_SEL 229 +#define CLKID_HCODEC_1_DIV 230 +#define CLKID_HCODEC_1 231 +#define CLKID_HCODEC 232 +#define CLKID_VPU_0_SEL 233 +#define CLKID_VPU_0_DIV 234 +#define CLKID_VPU_0 235 +#define CLKID_VPU_1_SEL 236 +#define CLKID_VPU_1_DIV 237 +#define CLKID_VPU_1 238 +#define CLKID_VPU 239 +#define CLKID_VAPB_0_SEL 240 +#define CLKID_VAPB_0_DIV 241 +#define CLKID_VAPB_0 242 +#define CLKID_VAPB_1_SEL 243 +#define CLKID_VAPB_1_DIV 244 +#define CLKID_VAPB_1 245 +#define CLKID_VAPB 246 +#define CLKID_GE2D 247 +#define CLKID_VPU_CLKB_TMP_SEL 248 +#define CLKID_VPU_CLKB_TMP_DIV 249 +#define CLKID_VPU_CLKB_TMP 250 +#define CLKID_VPU_CLKB_DIV 251 +#define CLKID_VPU_CLKB 252 +#define CLKID_HDMITX_SYS_SEL 253 +#define CLKID_HDMITX_SYS_DIV 254 +#define CLKID_HDMITX_SYS 255 +#define CLKID_HDMITX_PRIF_SEL 256 +#define CLKID_HDMITX_PRIF_DIV 257 +#define CLKID_HDMITX_PRIF 258 +#define CLKID_HDMITX_200M_SEL 259 +#define CLKID_HDMITX_200M_DIV 260 +#define CLKID_HDMITX_200M 261 +#define CLKID_HDMITX_AUD_SEL 262 +#define CLKID_HDMITX_AUD_DIV 263 +#define CLKID_HDMITX_AUD 264 +#define CLKID_HDMIRX_5M_SEL 265 +#define CLKID_HDMIRX_5M_DIV 266 +#define CLKID_HDMIRX_5M 267 +#define CLKID_HDMIRX_2M_SEL 268 +#define CLKID_HDMIRX_2M_DIV 269 +#define CLKID_HDMIRX_2M 270 +#define CLKID_HDMIRX_CFG_SEL 271 +#define CLKID_HDMIRX_CFG_DIV 272 +#define CLKID_HDMIRX_CFG 273 +#define CLKID_HDMIRX_HDCP2X_SEL 274 +#define CLKID_HDMIRX_HDCP2X_DIV 275 +#define CLKID_HDMIRX_HDCP2X 276 +#define CLKID_HDMIRX_ACR_REF_SEL 277 +#define CLKID_HDMIRX_ACR_REF_DIV 278 +#define CLKID_HDMIRX_ACR_REF 279 +#define CLKID_HDMIRX_METER_SEL 280 +#define CLKID_HDMIRX_METER_DIV 281 +#define CLKID_HDMIRX_METER 282 +#define CLKID_VID_LOCK_SEL 283 +#define CLKID_VID_LOCK_DIV 284 +#define CLKID_VID_LOCK 285 +#define CLKID_VDIN_MEAS_SEL 286 +#define CLKID_VDIN_MEAS_DIV 287 +#define CLKID_VDIN_MEAS 288 +#define CLKID_VID_PLL_DIV 289 +#define CLKID_VID_PLL_SEL 290 +#define CLKID_VID_PLL 291 +#define CLKID_VID_PLL_VCLK 292 +#define CLKID_VCLK_SEL 293 +#define CLKID_VCLK_IN 294 +#define CLKID_VCLK_DIV 295 +#define CLKID_VCLK 296 +#define CLKID_VCLK_DIV1_EN 297 +#define CLKID_VCLK_DIV2_EN 298 +#define CLKID_VCLK_DIV2 299 +#define CLKID_VCLK_DIV4_EN 300 +#define CLKID_VCLK_DIV4 301 +#define CLKID_VCLK_DIV6_EN 302 +#define CLKID_VCLK_DIV6 303 +#define CLKID_VCLK_DIV12_EN 304 +#define CLKID_VCLK_DIV12 305 +#define CLKID_VCLK2_SEL 306 +#define CLKID_VCLK2_IN 307 +#define CLKID_VCLK2_DIV 308 +#define CLKID_VCLK2 309 +#define CLKID_VCLK2_DIV1_EN 310 +#define CLKID_VCLK2_DIV2_EN 311 +#define CLKID_VCLK2_DIV2 312 +#define CLKID_VCLK2_DIV4_EN 313 +#define CLKID_VCLK2_DIV4 314 +#define CLKID_VCLK2_DIV6_EN 315 +#define CLKID_VCLK2_DIV6 316 +#define CLKID_VCLK2_DIV12_EN 317 +#define CLKID_VCLK2_DIV12 318 +#define CLKID_VDAC_SEL 319 +#define CLKID_VDAC 320 +#define CLKID_ENC_SEL 321 +#define CLKID_ENC 322 +#define CLKID_ENC1_SEL 323 +#define CLKID_ENC1 324 +#define CLKID_HDMITX_PIXEL_SEL 325 +#define CLKID_HDMITX_PIXEL 326 +#define CLKID_HDMITX_FE_SEL 327 +#define CLKID_HDMITX_FE 328 +#define CLKID_HDMITX1_PIXEL_SEL 329 +#define CLKID_HDMITX1_PIXEL 330 +#define CLKID_HDMITX1_FE_SEL 331 +#define CLKID_HDMITX1_FE 332 +#define CLKID_CSI_PHY_SEL 333 +#define CLKID_CSI_PHY_DIV 334 +#define CLKID_CSI_PHY 335 +#define CLKID_DSI_MEAS_SEL 336 +#define CLKID_DSI_MEAS_DIV 337 +#define CLKID_DSI_MEAS 338 +#define CLKID_DSI_B_MEAS_SEL 339 +#define CLKID_DSI_B_MEAS_DIV 340 +#define CLKID_DSI_B_MEAS 341 + +#endif /* __AMLOGIC_A9_PERIPHERALS_CLKC_H */ -- 2.47.1 ^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 04/10] dt-bindings: clock: Add Amlogic A9 AO clock controller 2026-05-11 12:47 [PATCH 00/10] Add support for A9 family clock controller Jian Hu via B4 Relay ` (2 preceding siblings ...) 2026-05-11 12:47 ` [PATCH 03/10] dt-bindings: clock: Add Amlogic A9 peripherals " Jian Hu via B4 Relay @ 2026-05-11 12:47 ` Jian Hu via B4 Relay 2026-05-11 12:47 ` [PATCH 05/10] clk: amlogic: PLL l_detect signal supports active-high configuration Jian Hu via B4 Relay ` (5 subsequent siblings) 9 siblings, 0 replies; 17+ messages in thread From: Jian Hu via B4 Relay @ 2026-05-11 12:47 UTC (permalink / raw) To: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Neil Armstrong, Jerome Brunet, Xianwei Zhao, Kevin Hilman, Martin Blumenstingl Cc: linux-kernel, linux-clk, devicetree, linux-amlogic, linux-arm-kernel, Jian Hu From: Jian Hu <jian.hu@amlogic.com> Add the Always-On clock controller dt-bindings for the Amlogic A9 SoC family. Signed-off-by: Jian Hu <jian.hu@amlogic.com> --- .../bindings/clock/amlogic,a9-aoclkc.yaml | 76 ++++++++++++++++++++++ include/dt-bindings/clock/amlogic,a9-aoclkc.h | 76 ++++++++++++++++++++++ 2 files changed, 152 insertions(+) diff --git a/Documentation/devicetree/bindings/clock/amlogic,a9-aoclkc.yaml b/Documentation/devicetree/bindings/clock/amlogic,a9-aoclkc.yaml new file mode 100644 index 000000000000..973cac3c6988 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/amlogic,a9-aoclkc.yaml @@ -0,0 +1,76 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +# Copyright (C) 2026 Amlogic, Inc. All rights reserved +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/amlogic,a9-aoclkc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Amlogic A9 Series Always-On Clock Controller + +maintainers: + - Neil Armstrong <neil.armstrong@linaro.org> + - Jerome Brunet <jbrunet@baylibre.com> + - Jian Hu <jian.hu@amlogic.com> + - Xianwei Zhao <xianwei.zhao@amlogic.com> + +properties: + compatible: + const: amlogic,a9-aoclkc + + reg: + maxItems: 1 + + '#clock-cells': + const: 1 + + clocks: + minItems: 5 + items: + - description: input oscillator + - description: input fclk div 3 + - description: input fclk div 4 + - description: input fclk div 5 + - description: input sys clk + - description: external fixed 32k (optional) + + clock-names: + minItems: 5 + items: + - const: xtal + - const: fdiv3 + - const: fdiv4 + - const: fdiv5 + - const: sys + - const: ext_32k + +required: + - compatible + - reg + - '#clock-cells' + - clocks + - clock-names + +additionalProperties: false + +examples: + - | + aobus { + #address-cells = <2>; + #size-cells = <2>; + + clock-controller@0 { + compatible = "amlogic,a9-aoclkc"; + reg = <0x0 0x0 0x0 0x58>; + #clock-cells = <1>; + clocks = <&xtal>, + <&scmi_clk 14>, + <&scmi_clk 16>, + <&scmi_clk 18>, + <&scmi_clk 21>; + clock-names = "xtal", + "fdiv3", + "fdiv4", + "fdiv5", + "sys"; + }; + }; diff --git a/include/dt-bindings/clock/amlogic,a9-aoclkc.h b/include/dt-bindings/clock/amlogic,a9-aoclkc.h new file mode 100644 index 000000000000..a7d704d4b58e --- /dev/null +++ b/include/dt-bindings/clock/amlogic,a9-aoclkc.h @@ -0,0 +1,76 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * Copyright (C) 2026 Amlogic, Inc. All rights reserved. + */ + +#ifndef __AMLOGIC_A9_AO_CLKC_H +#define __AMLOGIC_A9_AO_CLKC_H + +#define CLKID_AO_XTAL_IN 0 +#define CLKID_AO_XTAL 1 +#define CLKID_AO_SYS 2 +#define CLKID_AO_SYS_I3C 3 +#define CLKID_AO_SYS_RTC_REG 4 +#define CLKID_AO_SYS_CLKTREE 5 +#define CLKID_AO_SYS_RST_CTRL 6 +#define CLKID_AO_SYS_PAD 7 +#define CLKID_AO_SYS_RTC_DIG 8 +#define CLKID_AO_SYS_IRQ 9 +#define CLKID_AO_SYS_PWRCTRL 10 +#define CLKID_AO_SYS_PWM_A 11 +#define CLKID_AO_SYS_PWM_B 12 +#define CLKID_AO_SYS_PWM_C 13 +#define CLKID_AO_SYS_PWM_D 14 +#define CLKID_AO_SYS_PWM_E 15 +#define CLKID_AO_SYS_PWM_F 16 +#define CLKID_AO_SYS_PWM_G 17 +#define CLKID_AO_SYS_I2C_A 18 +#define CLKID_AO_SYS_I2C_B 19 +#define CLKID_AO_SYS_I2C_C 20 +#define CLKID_AO_SYS_I2C_D 21 +#define CLKID_AO_SYS_SED 22 +#define CLKID_AO_SYS_IR_CTRL 23 +#define CLKID_AO_SYS_UART_B 24 +#define CLKID_AO_SYS_UART_C 25 +#define CLKID_AO_SYS_UART_D 26 +#define CLKID_AO_SYS_UART_E 27 +#define CLKID_AO_SYS_SPISG_0 28 +#define CLKID_AO_SYS_RTC_SECURE 29 +#define CLKID_AO_SYS_CEC 30 +#define CLKID_AO_SYS_AOCPU 31 +#define CLKID_AO_SYS_SRAM 32 +#define CLKID_AO_SYS_SPISG_1 33 +#define CLKID_AO_SYS_SPISG_2 34 +#define CLKID_AO_PWM_A_SEL 35 +#define CLKID_AO_PWM_A_DIV 36 +#define CLKID_AO_PWM_A 37 +#define CLKID_AO_PWM_B_SEL 38 +#define CLKID_AO_PWM_B_DIV 39 +#define CLKID_AO_PWM_B 40 +#define CLKID_AO_PWM_C_SEL 41 +#define CLKID_AO_PWM_C_DIV 42 +#define CLKID_AO_PWM_C 43 +#define CLKID_AO_PWM_D_SEL 44 +#define CLKID_AO_PWM_D_DIV 45 +#define CLKID_AO_PWM_D 46 +#define CLKID_AO_PWM_E_SEL 47 +#define CLKID_AO_PWM_E_DIV 48 +#define CLKID_AO_PWM_E 49 +#define CLKID_AO_PWM_F_SEL 50 +#define CLKID_AO_PWM_F_DIV 51 +#define CLKID_AO_PWM_F 52 +#define CLKID_AO_PWM_G_SEL 53 +#define CLKID_AO_PWM_G_DIV 54 +#define CLKID_AO_PWM_G 55 +#define CLKID_AO_RTC_DUALDIV_IN 56 +#define CLKID_AO_RTC_DUALDIV_DIV 57 +#define CLKID_AO_RTC_DUALDIV_SEL 58 +#define CLKID_AO_RTC_DUALDIV 59 +#define CLKID_AO_RTC 60 +#define CLKID_AO_CEC_DUALDIV_IN 61 +#define CLKID_AO_CEC_DUALDIV_DIV 62 +#define CLKID_AO_CEC_DUALDIV_SEL 63 +#define CLKID_AO_CEC_DUALDIV 64 +#define CLKID_AO_CEC 65 + +#endif /* __AMLOGIC_A9_AO_CLKC_H */ -- 2.47.1 ^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 05/10] clk: amlogic: PLL l_detect signal supports active-high configuration 2026-05-11 12:47 [PATCH 00/10] Add support for A9 family clock controller Jian Hu via B4 Relay ` (3 preceding siblings ...) 2026-05-11 12:47 ` [PATCH 04/10] dt-bindings: clock: Add Amlogic A9 AO " Jian Hu via B4 Relay @ 2026-05-11 12:47 ` Jian Hu via B4 Relay 2026-05-11 15:47 ` Brian Masney 2026-05-11 12:47 ` [PATCH 06/10] clk: amlogic: PLL reset signal supports active-low configuration Jian Hu via B4 Relay ` (4 subsequent siblings) 9 siblings, 1 reply; 17+ messages in thread From: Jian Hu via B4 Relay @ 2026-05-11 12:47 UTC (permalink / raw) To: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Neil Armstrong, Jerome Brunet, Xianwei Zhao, Kevin Hilman, Martin Blumenstingl Cc: linux-kernel, linux-clk, devicetree, linux-amlogic, linux-arm-kernel, Jian Hu From: Jian Hu <jian.hu@amlogic.com> l_detect controls the enable/disable of the PLL lock-detect module. For A9, the l_detect signal is active-high: 0 -> Disable lock-detect module; 1 -> Enable lock-detect module. Here, a flag CLK_MESON_PLL_L_DETECT_ACTIVE_HIGH is added to handle cases like A9, where the signal is active-high. Signed-off-by: Jian Hu <jian.hu@amlogic.com> --- drivers/clk/meson/clk-pll.c | 9 +++++++-- drivers/clk/meson/clk-pll.h | 2 ++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c index 1ea6579a760f..5a0bd75f85a9 100644 --- a/drivers/clk/meson/clk-pll.c +++ b/drivers/clk/meson/clk-pll.c @@ -388,8 +388,13 @@ static int meson_clk_pll_enable(struct clk_hw *hw) } if (MESON_PARM_APPLICABLE(&pll->l_detect)) { - meson_parm_write(clk->map, &pll->l_detect, 1); - meson_parm_write(clk->map, &pll->l_detect, 0); + if (pll->flags & CLK_MESON_PLL_L_DETECT_ACTIVE_HIGH) { + meson_parm_write(clk->map, &pll->l_detect, 0); + meson_parm_write(clk->map, &pll->l_detect, 1); + } else { + meson_parm_write(clk->map, &pll->l_detect, 1); + meson_parm_write(clk->map, &pll->l_detect, 0); + } } if (meson_clk_pll_wait_lock(hw)) diff --git a/drivers/clk/meson/clk-pll.h b/drivers/clk/meson/clk-pll.h index 949157fb7bf5..97b7c70376a3 100644 --- a/drivers/clk/meson/clk-pll.h +++ b/drivers/clk/meson/clk-pll.h @@ -29,6 +29,8 @@ struct pll_mult_range { #define CLK_MESON_PLL_ROUND_CLOSEST BIT(0) #define CLK_MESON_PLL_NOINIT_ENABLED BIT(1) +/* l_detect signal is active-high */ +#define CLK_MESON_PLL_L_DETECT_ACTIVE_HIGH BIT(2) struct meson_clk_pll_data { struct parm en; -- 2.47.1 ^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [PATCH 05/10] clk: amlogic: PLL l_detect signal supports active-high configuration 2026-05-11 12:47 ` [PATCH 05/10] clk: amlogic: PLL l_detect signal supports active-high configuration Jian Hu via B4 Relay @ 2026-05-11 15:47 ` Brian Masney 0 siblings, 0 replies; 17+ messages in thread From: Brian Masney @ 2026-05-11 15:47 UTC (permalink / raw) To: jian.hu Cc: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Neil Armstrong, Jerome Brunet, Xianwei Zhao, Kevin Hilman, Martin Blumenstingl, linux-kernel, linux-clk, devicetree, linux-amlogic, linux-arm-kernel On Mon, May 11, 2026 at 08:47:27PM +0800, Jian Hu via B4 Relay wrote: > From: Jian Hu <jian.hu@amlogic.com> > > l_detect controls the enable/disable of the PLL lock-detect module. > > For A9, the l_detect signal is active-high: > 0 -> Disable lock-detect module; > 1 -> Enable lock-detect module. > > Here, a flag CLK_MESON_PLL_L_DETECT_ACTIVE_HIGH is added to handle cases > like A9, where the signal is active-high. > > Signed-off-by: Jian Hu <jian.hu@amlogic.com> Reviewed-by: Brian Masney <bmasney@redhat.com> ^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 06/10] clk: amlogic: PLL reset signal supports active-low configuration 2026-05-11 12:47 [PATCH 00/10] Add support for A9 family clock controller Jian Hu via B4 Relay ` (4 preceding siblings ...) 2026-05-11 12:47 ` [PATCH 05/10] clk: amlogic: PLL l_detect signal supports active-high configuration Jian Hu via B4 Relay @ 2026-05-11 12:47 ` Jian Hu via B4 Relay 2026-05-11 15:21 ` Brian Masney 2026-05-11 12:47 ` [PATCH 07/10] clk: amlogic: Support POWER_OF_TWO for PLL pre-divider Jian Hu via B4 Relay ` (3 subsequent siblings) 9 siblings, 1 reply; 17+ messages in thread From: Jian Hu via B4 Relay @ 2026-05-11 12:47 UTC (permalink / raw) To: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Neil Armstrong, Jerome Brunet, Xianwei Zhao, Kevin Hilman, Martin Blumenstingl Cc: linux-kernel, linux-clk, devicetree, linux-amlogic, linux-arm-kernel, Jian Hu From: Jian Hu <jian.hu@amlogic.com> In the A9 design, the PLL reset signal is configured as active-low. Add the flag 'CLK_MESON_PLL_RST_N' to indicate that the PLL reset signal is active-low. Signed-off-by: Jian Hu <jian.hu@amlogic.com> --- drivers/clk/meson/clk-pll.c | 42 +++++++++++++++++++++++++++++++----------- drivers/clk/meson/clk-pll.h | 2 ++ 2 files changed, 33 insertions(+), 11 deletions(-) diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c index 5a0bd75f85a9..8568ad6ba7b6 100644 --- a/drivers/clk/meson/clk-pll.c +++ b/drivers/clk/meson/clk-pll.c @@ -295,10 +295,14 @@ static int meson_clk_pll_is_enabled(struct clk_hw *hw) { struct clk_regmap *clk = to_clk_regmap(hw); struct meson_clk_pll_data *pll = meson_clk_pll_data(clk); + unsigned int rst; - if (MESON_PARM_APPLICABLE(&pll->rst) && - meson_parm_read(clk->map, &pll->rst)) - return 0; + if (MESON_PARM_APPLICABLE(&pll->rst)) { + rst = meson_parm_read(clk->map, &pll->rst); + if ((rst && !(pll->flags & CLK_MESON_PLL_RST_ACTIVE_LOW)) || + (!rst && (pll->flags & CLK_MESON_PLL_RST_ACTIVE_LOW))) + return 0; + } if (!meson_parm_read(clk->map, &pll->en) || !meson_parm_read(clk->map, &pll->l)) @@ -326,14 +330,22 @@ static int meson_clk_pll_init(struct clk_hw *hw) return 0; if (pll->init_count) { - if (MESON_PARM_APPLICABLE(&pll->rst)) - meson_parm_write(clk->map, &pll->rst, 1); + if (MESON_PARM_APPLICABLE(&pll->rst)) { + if (pll->flags & CLK_MESON_PLL_RST_ACTIVE_LOW) + meson_parm_write(clk->map, &pll->rst, 0); + else + meson_parm_write(clk->map, &pll->rst, 1); + } regmap_multi_reg_write(clk->map, pll->init_regs, pll->init_count); - if (MESON_PARM_APPLICABLE(&pll->rst)) - meson_parm_write(clk->map, &pll->rst, 0); + if (MESON_PARM_APPLICABLE(&pll->rst)) { + if (pll->flags & CLK_MESON_PLL_RST_ACTIVE_LOW) + meson_parm_write(clk->map, &pll->rst, 1); + else + meson_parm_write(clk->map, &pll->rst, 0); + } } return 0; @@ -363,15 +375,23 @@ static int meson_clk_pll_enable(struct clk_hw *hw) return 0; /* Make sure the pll is in reset */ - if (MESON_PARM_APPLICABLE(&pll->rst)) - meson_parm_write(clk->map, &pll->rst, 1); + if (MESON_PARM_APPLICABLE(&pll->rst)) { + if (pll->flags & CLK_MESON_PLL_RST_ACTIVE_LOW) + meson_parm_write(clk->map, &pll->rst, 0); + else + meson_parm_write(clk->map, &pll->rst, 1); + } /* Enable the pll */ meson_parm_write(clk->map, &pll->en, 1); /* Take the pll out reset */ - if (MESON_PARM_APPLICABLE(&pll->rst)) - meson_parm_write(clk->map, &pll->rst, 0); + if (MESON_PARM_APPLICABLE(&pll->rst)) { + if (pll->flags & CLK_MESON_PLL_RST_ACTIVE_LOW) + meson_parm_write(clk->map, &pll->rst, 1); + else + meson_parm_write(clk->map, &pll->rst, 0); + } /* * Compared with the previous SoCs, self-adaption current module diff --git a/drivers/clk/meson/clk-pll.h b/drivers/clk/meson/clk-pll.h index 97b7c70376a3..1be7e6e77631 100644 --- a/drivers/clk/meson/clk-pll.h +++ b/drivers/clk/meson/clk-pll.h @@ -31,6 +31,8 @@ struct pll_mult_range { #define CLK_MESON_PLL_NOINIT_ENABLED BIT(1) /* l_detect signal is active-high */ #define CLK_MESON_PLL_L_DETECT_ACTIVE_HIGH BIT(2) +/* rst signal is active-low (Power-on reset) */ +#define CLK_MESON_PLL_RST_ACTIVE_LOW BIT(3) struct meson_clk_pll_data { struct parm en; -- 2.47.1 ^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [PATCH 06/10] clk: amlogic: PLL reset signal supports active-low configuration 2026-05-11 12:47 ` [PATCH 06/10] clk: amlogic: PLL reset signal supports active-low configuration Jian Hu via B4 Relay @ 2026-05-11 15:21 ` Brian Masney 0 siblings, 0 replies; 17+ messages in thread From: Brian Masney @ 2026-05-11 15:21 UTC (permalink / raw) To: jian.hu Cc: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Neil Armstrong, Jerome Brunet, Xianwei Zhao, Kevin Hilman, Martin Blumenstingl, linux-kernel, linux-clk, devicetree, linux-amlogic, linux-arm-kernel On Mon, May 11, 2026 at 08:47:28PM +0800, Jian Hu via B4 Relay wrote: > From: Jian Hu <jian.hu@amlogic.com> > > In the A9 design, the PLL reset signal is configured as active-low. > > Add the flag 'CLK_MESON_PLL_RST_N' to indicate that the PLL reset signal > is active-low. This flag isn't in the patch. I assume that you mean CLK_MESON_PLL_RST_ACTIVE_LOW? Brian > > Signed-off-by: Jian Hu <jian.hu@amlogic.com> > --- > drivers/clk/meson/clk-pll.c | 42 +++++++++++++++++++++++++++++++----------- > drivers/clk/meson/clk-pll.h | 2 ++ > 2 files changed, 33 insertions(+), 11 deletions(-) > > diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c > index 5a0bd75f85a9..8568ad6ba7b6 100644 > --- a/drivers/clk/meson/clk-pll.c > +++ b/drivers/clk/meson/clk-pll.c > @@ -295,10 +295,14 @@ static int meson_clk_pll_is_enabled(struct clk_hw *hw) > { > struct clk_regmap *clk = to_clk_regmap(hw); > struct meson_clk_pll_data *pll = meson_clk_pll_data(clk); > + unsigned int rst; > > - if (MESON_PARM_APPLICABLE(&pll->rst) && > - meson_parm_read(clk->map, &pll->rst)) > - return 0; > + if (MESON_PARM_APPLICABLE(&pll->rst)) { > + rst = meson_parm_read(clk->map, &pll->rst); > + if ((rst && !(pll->flags & CLK_MESON_PLL_RST_ACTIVE_LOW)) || > + (!rst && (pll->flags & CLK_MESON_PLL_RST_ACTIVE_LOW))) > + return 0; > + } > > if (!meson_parm_read(clk->map, &pll->en) || > !meson_parm_read(clk->map, &pll->l)) > @@ -326,14 +330,22 @@ static int meson_clk_pll_init(struct clk_hw *hw) > return 0; > > if (pll->init_count) { > - if (MESON_PARM_APPLICABLE(&pll->rst)) > - meson_parm_write(clk->map, &pll->rst, 1); > + if (MESON_PARM_APPLICABLE(&pll->rst)) { > + if (pll->flags & CLK_MESON_PLL_RST_ACTIVE_LOW) > + meson_parm_write(clk->map, &pll->rst, 0); > + else > + meson_parm_write(clk->map, &pll->rst, 1); > + } > > regmap_multi_reg_write(clk->map, pll->init_regs, > pll->init_count); > > - if (MESON_PARM_APPLICABLE(&pll->rst)) > - meson_parm_write(clk->map, &pll->rst, 0); > + if (MESON_PARM_APPLICABLE(&pll->rst)) { > + if (pll->flags & CLK_MESON_PLL_RST_ACTIVE_LOW) > + meson_parm_write(clk->map, &pll->rst, 1); > + else > + meson_parm_write(clk->map, &pll->rst, 0); > + } > } > > return 0; > @@ -363,15 +375,23 @@ static int meson_clk_pll_enable(struct clk_hw *hw) > return 0; > > /* Make sure the pll is in reset */ > - if (MESON_PARM_APPLICABLE(&pll->rst)) > - meson_parm_write(clk->map, &pll->rst, 1); > + if (MESON_PARM_APPLICABLE(&pll->rst)) { > + if (pll->flags & CLK_MESON_PLL_RST_ACTIVE_LOW) > + meson_parm_write(clk->map, &pll->rst, 0); > + else > + meson_parm_write(clk->map, &pll->rst, 1); > + } > > /* Enable the pll */ > meson_parm_write(clk->map, &pll->en, 1); > > /* Take the pll out reset */ > - if (MESON_PARM_APPLICABLE(&pll->rst)) > - meson_parm_write(clk->map, &pll->rst, 0); > + if (MESON_PARM_APPLICABLE(&pll->rst)) { > + if (pll->flags & CLK_MESON_PLL_RST_ACTIVE_LOW) > + meson_parm_write(clk->map, &pll->rst, 1); > + else > + meson_parm_write(clk->map, &pll->rst, 0); > + } > > /* > * Compared with the previous SoCs, self-adaption current module > diff --git a/drivers/clk/meson/clk-pll.h b/drivers/clk/meson/clk-pll.h > index 97b7c70376a3..1be7e6e77631 100644 > --- a/drivers/clk/meson/clk-pll.h > +++ b/drivers/clk/meson/clk-pll.h > @@ -31,6 +31,8 @@ struct pll_mult_range { > #define CLK_MESON_PLL_NOINIT_ENABLED BIT(1) > /* l_detect signal is active-high */ > #define CLK_MESON_PLL_L_DETECT_ACTIVE_HIGH BIT(2) > +/* rst signal is active-low (Power-on reset) */ > +#define CLK_MESON_PLL_RST_ACTIVE_LOW BIT(3) > > struct meson_clk_pll_data { > struct parm en; > > -- > 2.47.1 > > ^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 07/10] clk: amlogic: Support POWER_OF_TWO for PLL pre-divider 2026-05-11 12:47 [PATCH 00/10] Add support for A9 family clock controller Jian Hu via B4 Relay ` (5 preceding siblings ...) 2026-05-11 12:47 ` [PATCH 06/10] clk: amlogic: PLL reset signal supports active-low configuration Jian Hu via B4 Relay @ 2026-05-11 12:47 ` Jian Hu via B4 Relay 2026-05-11 15:23 ` Brian Masney 2026-05-11 12:47 ` [PATCH 08/10] clk: amlogic: Add A9 PLL clock controller driver Jian Hu via B4 Relay ` (2 subsequent siblings) 9 siblings, 1 reply; 17+ messages in thread From: Jian Hu via B4 Relay @ 2026-05-11 12:47 UTC (permalink / raw) To: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Neil Armstrong, Jerome Brunet, Xianwei Zhao, Kevin Hilman, Martin Blumenstingl Cc: linux-kernel, linux-clk, devicetree, linux-amlogic, linux-arm-kernel, Jian Hu From: Jian Hu <jian.hu@amlogic.com> The A9 PLL pre-divider uses a division factor of 2^n to ensure a clock duty cycle of 50% after predivision. Add flag 'CLK_MESON_PLL_N_POWER_OF_TWO' to indicate that the PLL pre-divider division factor is 2^n. Signed-off-by: Jian Hu <jian.hu@amlogic.com> --- drivers/clk/meson/clk-pll.c | 28 +++++++++++++++++++++++----- drivers/clk/meson/clk-pll.h | 2 ++ 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c index 8568ad6ba7b6..49483e431d44 100644 --- a/drivers/clk/meson/clk-pll.c +++ b/drivers/clk/meson/clk-pll.c @@ -66,6 +66,9 @@ static unsigned long __pll_params_to_rate(unsigned long parent_rate, rate += DIV_ROUND_UP_ULL(frac_rate, frac_max); } + if (pll->flags & CLK_MESON_PLL_N_POWER_OF_TWO) + n = 1 << n; + return DIV_ROUND_UP_ULL(rate, n); } @@ -83,7 +86,7 @@ static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw, * it would result in a division by zero. The rate can't be * calculated in this case */ - if (n == 0) + if (n == 0 && !(pll->flags & CLK_MESON_PLL_N_POWER_OF_TWO)) return 0; m = meson_parm_read(clk->map, &pll->m); @@ -103,7 +106,12 @@ static unsigned int __pll_params_with_frac(unsigned long rate, { unsigned int frac_max = pll->frac_max ? pll->frac_max : (1 << pll->frac.width); - u64 val = (u64)rate * n; + u64 val; + + if (pll->flags & CLK_MESON_PLL_N_POWER_OF_TWO) + n = 1 << n; + + val = (u64)rate * n; /* Bail out if we are already over the requested rate */ if (rate < parent_rate * m / n) @@ -142,7 +150,8 @@ static int meson_clk_get_pll_table_index(unsigned int index, unsigned int *n, struct meson_clk_pll_data *pll) { - if (!pll->table[index].n) + if (!pll->table[index].n && + !(pll->flags & CLK_MESON_PLL_N_POWER_OF_TWO)) return -EINVAL; *m = pll->table[index].m; @@ -156,7 +165,12 @@ static unsigned int meson_clk_get_pll_range_m(unsigned long rate, unsigned int n, struct meson_clk_pll_data *pll) { - u64 val = (u64)rate * n; + u64 val; + + if (pll->flags & CLK_MESON_PLL_N_POWER_OF_TWO) + n = 1 << n; + + val = (u64)rate * n; if (__pll_round_closest_mult(pll)) return DIV_ROUND_CLOSEST_ULL(val, parent_rate); @@ -173,11 +187,15 @@ static int meson_clk_get_pll_range_index(unsigned long rate, { *n = index + 1; + if ((pll->flags & CLK_MESON_PLL_N_POWER_OF_TWO)) + *n = index; + /* Check the predivider range */ if (*n >= (1 << pll->n.width)) return -EINVAL; - if (*n == 1) { + if ((*n == 1 && !(pll->flags & CLK_MESON_PLL_N_POWER_OF_TWO)) || + (*n == 0 && (pll->flags & CLK_MESON_PLL_N_POWER_OF_TWO))) { /* Get the boundaries out the way */ if (rate <= pll->range->min * parent_rate) { *m = pll->range->min; diff --git a/drivers/clk/meson/clk-pll.h b/drivers/clk/meson/clk-pll.h index 1be7e6e77631..60b2772a54c8 100644 --- a/drivers/clk/meson/clk-pll.h +++ b/drivers/clk/meson/clk-pll.h @@ -33,6 +33,8 @@ struct pll_mult_range { #define CLK_MESON_PLL_L_DETECT_ACTIVE_HIGH BIT(2) /* rst signal is active-low (Power-on reset) */ #define CLK_MESON_PLL_RST_ACTIVE_LOW BIT(3) +/* The division factor of the PLL pre-divider is 2^n */ +#define CLK_MESON_PLL_N_POWER_OF_TWO BIT(4) struct meson_clk_pll_data { struct parm en; -- 2.47.1 ^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [PATCH 07/10] clk: amlogic: Support POWER_OF_TWO for PLL pre-divider 2026-05-11 12:47 ` [PATCH 07/10] clk: amlogic: Support POWER_OF_TWO for PLL pre-divider Jian Hu via B4 Relay @ 2026-05-11 15:23 ` Brian Masney 0 siblings, 0 replies; 17+ messages in thread From: Brian Masney @ 2026-05-11 15:23 UTC (permalink / raw) To: jian.hu Cc: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Neil Armstrong, Jerome Brunet, Xianwei Zhao, Kevin Hilman, Martin Blumenstingl, linux-kernel, linux-clk, devicetree, linux-amlogic, linux-arm-kernel On Mon, May 11, 2026 at 08:47:29PM +0800, Jian Hu via B4 Relay wrote: > From: Jian Hu <jian.hu@amlogic.com> > > The A9 PLL pre-divider uses a division factor of 2^n to ensure a clock > duty cycle of 50% after predivision. > > Add flag 'CLK_MESON_PLL_N_POWER_OF_TWO' to indicate that the PLL > pre-divider division factor is 2^n. > > Signed-off-by: Jian Hu <jian.hu@amlogic.com> Reviewed-by: Brian Masney <bmasney@redhat.com> ^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 08/10] clk: amlogic: Add A9 PLL clock controller driver 2026-05-11 12:47 [PATCH 00/10] Add support for A9 family clock controller Jian Hu via B4 Relay ` (6 preceding siblings ...) 2026-05-11 12:47 ` [PATCH 07/10] clk: amlogic: Support POWER_OF_TWO for PLL pre-divider Jian Hu via B4 Relay @ 2026-05-11 12:47 ` Jian Hu via B4 Relay 2026-05-11 15:36 ` Brian Masney 2026-05-11 12:47 ` [PATCH 09/10] clk: amlogic: Add A9 peripherals " Jian Hu via B4 Relay 2026-05-11 12:47 ` [PATCH 10/10] clk: amlogic: Add A9 AO " Jian Hu via B4 Relay 9 siblings, 1 reply; 17+ messages in thread From: Jian Hu via B4 Relay @ 2026-05-11 12:47 UTC (permalink / raw) To: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Neil Armstrong, Jerome Brunet, Xianwei Zhao, Kevin Hilman, Martin Blumenstingl Cc: linux-kernel, linux-clk, devicetree, linux-amlogic, linux-arm-kernel, Jian Hu From: Jian Hu <jian.hu@amlogic.com> Add the PLL clock controller driver for the Amlogic A9 SoC family. Signed-off-by: Jian Hu <jian.hu@amlogic.com> --- drivers/clk/meson/Kconfig | 13 + drivers/clk/meson/Makefile | 1 + drivers/clk/meson/a9-pll.c | 831 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 845 insertions(+) diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig index cf8cf3f9e4ee..3549e67d6988 100644 --- a/drivers/clk/meson/Kconfig +++ b/drivers/clk/meson/Kconfig @@ -132,6 +132,19 @@ config COMMON_CLK_A1_PERIPHERALS device, A1 SoC Family. Say Y if you want A1 Peripherals clock controller to work. +config COMMON_CLK_A9_PLL + tristate "Amlogic A9 SoC PLL controller support" + depends on ARM64 + default ARCH_MESON + select COMMON_CLK_MESON_REGMAP + select COMMON_CLK_MESON_CLKC_UTILS + select COMMON_CLK_MESON_PLL + imply COMMON_CLK_SCMI + help + Support for the PLL clock controller on Amlogic A311Y3 based + device, AKA A9. PLLs are required by most peripheral to operate. + Say Y if you want A9 PLL clock controller to work. + config COMMON_CLK_C3_PLL tristate "Amlogic C3 PLL clock controller" depends on ARM64 diff --git a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile index c6719694a242..77636033061f 100644 --- a/drivers/clk/meson/Makefile +++ b/drivers/clk/meson/Makefile @@ -19,6 +19,7 @@ obj-$(CONFIG_COMMON_CLK_AXG) += axg.o axg-aoclk.o obj-$(CONFIG_COMMON_CLK_AXG_AUDIO) += axg-audio.o obj-$(CONFIG_COMMON_CLK_A1_PLL) += a1-pll.o obj-$(CONFIG_COMMON_CLK_A1_PERIPHERALS) += a1-peripherals.o +obj-$(CONFIG_COMMON_CLK_A9_PLL) += a9-pll.o obj-$(CONFIG_COMMON_CLK_C3_PLL) += c3-pll.o obj-$(CONFIG_COMMON_CLK_C3_PERIPHERALS) += c3-peripherals.o obj-$(CONFIG_COMMON_CLK_GXBB) += gxbb.o gxbb-aoclk.o diff --git a/drivers/clk/meson/a9-pll.c b/drivers/clk/meson/a9-pll.c new file mode 100644 index 000000000000..84b591c3afff --- /dev/null +++ b/drivers/clk/meson/a9-pll.c @@ -0,0 +1,831 @@ +// SPDX-License-Identifier: (GPL-2.0-only OR MIT) +/* + * Copyright (C) 2026 Amlogic, Inc. All rights reserved + */ + +#include <linux/clk-provider.h> +#include <linux/platform_device.h> +#include <dt-bindings/clock/amlogic,a9-pll-clkc.h> +#include "clk-regmap.h" +#include "clk-pll.h" +#include "meson-clkc-utils.h" + +#define GP0PLL_CTRL0 0x00 +#define GP0PLL_CTRL1 0x04 +#define GP0PLL_CTRL2 0x08 +#define GP0PLL_CTRL3 0x0c +#define GP0PLL_CTRL4 0x10 + +/* HIFI0 and HIFI1 share the same IP and register offset layout. */ +#define HIFIPLL_CTRL0 0x00 +#define HIFIPLL_CTRL1 0x04 +#define HIFIPLL_CTRL2 0x08 +#define HIFIPLL_CTRL3 0x0c +#define HIFIPLL_CTRL4 0x10 + +/* MCLK0 and MCLK1 share the same IP and register offset layout. */ +#define MCLKPLL_CTRL0 0x00 +#define MCLKPLL_CTRL1 0x04 +#define MCLKPLL_CTRL2 0x08 +#define MCLKPLL_CTRL3 0x0c +#define MCLKPLL_CTRL4 0x10 + +#define A9_COMP_SEL(_name, _reg, _shift, _mask, _pdata) \ + MESON_COMP_SEL(a9_, _name, _reg, _shift, _mask, _pdata, NULL, 0, 0) + +#define A9_COMP_DIV(_name, _reg, _shift, _width) \ + MESON_COMP_DIV(a9_, _name, _reg, _shift, _width, 0, CLK_SET_RATE_PARENT) + +#define A9_COMP_GATE(_name, _reg, _bit) \ + MESON_COMP_GATE(a9_, _name, _reg, _bit, CLK_SET_RATE_PARENT) + +/* + * Compared with previous SoC PLLs, the A9 PLL input path has an inherent + * 2-divider. The N pre-divider follows the same calculation rule as OD, + * where the pre-divider ratio equals 2^N. + * + * A9 PLL is composed as follows: + * + * PLL + * +---------------------------------+ + * | | + * | +--+ | + * in/2 >>---[ /2^N ]-->| | +-----+ | + * | | |------| DCO |----->> out + * | +--------->| | +--v--+ | + * | | +--+ | | + * | | | | + * | +--[ *(M + (F/Fmax) ]<--+ | + * | | + * +---------------------------------+ + * + * out = in / 2 * (m + frac / frac_max) / 2^n + */ + +static struct clk_fixed_factor a9_gp0_in_div2_div = { + .mult = 1, + .div = 2, + .hw.init = &(struct clk_init_data){ + .name = "gp0_in_div2_div", + .ops = &clk_fixed_factor_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "in0", + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap a9_gp0_in_div2 = { + .data = &(struct clk_regmap_gate_data) { + .offset = GP0PLL_CTRL0, + .bit_idx = 27, + }, + .hw.init = &(struct clk_init_data) { + .name = "gp0_in_div2", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &a9_gp0_in_div2_div.hw + }, + .num_parents = 1, + }, +}; + +/* The output frequency range of the A9 PLL_DCO is 1.4 GHz to 2.8 GHz. */ +static const struct pll_mult_range a9_pll_mult_range = { + .min = 117, + .max = 233, +}; + +static const struct reg_sequence a9_gp0_pll_init_regs[] = { + { .reg = GP0PLL_CTRL0, .def = 0x00010000 }, + { .reg = GP0PLL_CTRL1, .def = 0x11480000 }, + { .reg = GP0PLL_CTRL2, .def = 0x1219b010 }, + { .reg = GP0PLL_CTRL3, .def = 0x00008010 } +}; + +static struct clk_regmap a9_gp0_pll_dco = { + .data = &(struct meson_clk_pll_data) { + .en = { + .reg_off = GP0PLL_CTRL0, + .shift = 28, + .width = 1, + }, + .m = { + .reg_off = GP0PLL_CTRL0, + .shift = 0, + .width = 9, + }, + .n = { + .reg_off = GP0PLL_CTRL0, + .shift = 12, + .width = 3, + }, + .frac = { + .reg_off = GP0PLL_CTRL1, + .shift = 0, + .width = 17, + }, + .l = { + .reg_off = GP0PLL_CTRL0, + .shift = 31, + .width = 1, + }, + .rst = { + .reg_off = GP0PLL_CTRL0, + .shift = 29, + .width = 1, + }, + .l_detect = { + .reg_off = GP0PLL_CTRL0, + .shift = 30, + .width = 1, + }, + .range = &a9_pll_mult_range, + .init_regs = a9_gp0_pll_init_regs, + .init_count = ARRAY_SIZE(a9_gp0_pll_init_regs), + .flags = CLK_MESON_PLL_RST_ACTIVE_LOW | + CLK_MESON_PLL_N_POWER_OF_TWO | + CLK_MESON_PLL_L_DETECT_ACTIVE_HIGH, + }, + .hw.init = &(struct clk_init_data) { + .name = "gp0_pll_dco", + .ops = &meson_clk_pll_ops, + .parent_hws = (const struct clk_hw *[]) { + &a9_gp0_in_div2.hw + }, + .num_parents = 1, + }, +}; + +/* For gp0, hifi and mclk pll, the maximum value of od is 4. */ +static const struct clk_div_table a9_pll_od_table[] = { + { 0, 1 }, + { 1, 2 }, + { 2, 4 }, + { 3, 8 }, + { 4, 16 }, + { /* sentinel */ } +}; + +static struct clk_regmap a9_gp0_pll = { + .data = &(struct clk_regmap_div_data) { + .offset = GP0PLL_CTRL0, + .shift = 20, + .width = 3, + .table = a9_pll_od_table, + }, + .hw.init = &(struct clk_init_data) { + .name = "gp0_pll", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &a9_gp0_pll_dco.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_fixed_factor a9_hifi0_in_div2_div = { + .mult = 1, + .div = 2, + .hw.init = &(struct clk_init_data){ + .name = "hifi0_in_div2_div", + .ops = &clk_fixed_factor_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "in0", + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap a9_hifi0_in_div2 = { + .data = &(struct clk_regmap_gate_data) { + .offset = HIFIPLL_CTRL0, + .bit_idx = 27, + }, + .hw.init = &(struct clk_init_data) { + .name = "hifi0_in_div2", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &a9_hifi0_in_div2_div.hw + }, + .num_parents = 1, + }, +}; + +static const struct reg_sequence a9_hifi0_pll_init_regs[] = { + { .reg = HIFIPLL_CTRL0, .def = 0x00010000 }, + { .reg = HIFIPLL_CTRL1, .def = 0x11480000 }, + { .reg = HIFIPLL_CTRL2, .def = 0x1219b010 }, + { .reg = HIFIPLL_CTRL3, .def = 0x00008010 } +}; + +static struct clk_regmap a9_hifi0_pll_dco = { + .data = &(struct meson_clk_pll_data) { + .en = { + .reg_off = HIFIPLL_CTRL0, + .shift = 28, + .width = 1, + }, + .m = { + .reg_off = HIFIPLL_CTRL0, + .shift = 0, + .width = 9, + }, + .n = { + .reg_off = HIFIPLL_CTRL0, + .shift = 12, + .width = 3, + }, + .frac = { + .reg_off = HIFIPLL_CTRL1, + .shift = 0, + .width = 17, + }, + .l = { + .reg_off = HIFIPLL_CTRL0, + .shift = 31, + .width = 1, + }, + .rst = { + .reg_off = HIFIPLL_CTRL0, + .shift = 29, + .width = 1, + }, + .l_detect = { + .reg_off = HIFIPLL_CTRL0, + .shift = 30, + .width = 1, + }, + .range = &a9_pll_mult_range, + .init_regs = a9_hifi0_pll_init_regs, + .init_count = ARRAY_SIZE(a9_hifi0_pll_init_regs), + .frac_max = 100000, + .flags = CLK_MESON_PLL_RST_ACTIVE_LOW | + CLK_MESON_PLL_N_POWER_OF_TWO | + CLK_MESON_PLL_L_DETECT_ACTIVE_HIGH, + }, + .hw.init = &(struct clk_init_data) { + .name = "hifi0_pll_dco", + .ops = &meson_clk_pll_ops, + .parent_hws = (const struct clk_hw *[]) { + &a9_hifi0_in_div2.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap a9_hifi0_pll = { + .data = &(struct clk_regmap_div_data) { + .offset = HIFIPLL_CTRL0, + .shift = 20, + .width = 3, + .table = a9_pll_od_table, + }, + .hw.init = &(struct clk_init_data) { + .name = "hifi0_pll", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &a9_hifi0_pll_dco.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_fixed_factor a9_hifi1_in_div2_div = { + .mult = 1, + .div = 2, + .hw.init = &(struct clk_init_data){ + .name = "hifi1_in_div2_div", + .ops = &clk_fixed_factor_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "in0", + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap a9_hifi1_in_div2 = { + .data = &(struct clk_regmap_gate_data) { + .offset = HIFIPLL_CTRL0, + .bit_idx = 27, + }, + .hw.init = &(struct clk_init_data) { + .name = "hifi1_in_div2", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &a9_hifi1_in_div2_div.hw + }, + .num_parents = 1, + }, +}; + +static const struct reg_sequence a9_hifi1_pll_init_regs[] = { + { .reg = HIFIPLL_CTRL0, .def = 0x00010000 }, + { .reg = HIFIPLL_CTRL1, .def = 0x11480000 }, + { .reg = HIFIPLL_CTRL2, .def = 0x1219b011 }, + { .reg = HIFIPLL_CTRL3, .def = 0x00008010 } +}; + +static struct clk_regmap a9_hifi1_pll_dco = { + .data = &(struct meson_clk_pll_data) { + .en = { + .reg_off = HIFIPLL_CTRL0, + .shift = 28, + .width = 1, + }, + .m = { + .reg_off = HIFIPLL_CTRL0, + .shift = 0, + .width = 9, + }, + .n = { + .reg_off = HIFIPLL_CTRL0, + .shift = 12, + .width = 3, + }, + .frac = { + .reg_off = HIFIPLL_CTRL1, + .shift = 0, + .width = 17, + }, + .l = { + .reg_off = HIFIPLL_CTRL0, + .shift = 31, + .width = 1, + }, + .rst = { + .reg_off = HIFIPLL_CTRL0, + .shift = 29, + .width = 1, + }, + .l_detect = { + .reg_off = HIFIPLL_CTRL0, + .shift = 30, + .width = 1, + }, + .range = &a9_pll_mult_range, + .init_regs = a9_hifi1_pll_init_regs, + .init_count = ARRAY_SIZE(a9_hifi1_pll_init_regs), + .frac_max = 100000, + .flags = CLK_MESON_PLL_RST_ACTIVE_LOW | + CLK_MESON_PLL_N_POWER_OF_TWO | + CLK_MESON_PLL_L_DETECT_ACTIVE_HIGH, + }, + .hw.init = &(struct clk_init_data) { + .name = "hifi1_pll_dco", + .ops = &meson_clk_pll_ops, + .parent_hws = (const struct clk_hw *[]) { + &a9_hifi1_in_div2.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap a9_hifi1_pll = { + .data = &(struct clk_regmap_div_data) { + .offset = HIFIPLL_CTRL0, + .shift = 20, + .width = 3, + .table = a9_pll_od_table, + }, + .hw.init = &(struct clk_init_data) { + .name = "hifi1_pll", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &a9_hifi1_pll_dco.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +/* + * Unlike GP0 and HIFI PLLs, the input divider 2 of MCLK PLL is + * enabled by default and has no enable control bit. + */ +static struct clk_fixed_factor a9_mclk0_in_div2 = { + .mult = 1, + .div = 2, + .hw.init = &(struct clk_init_data){ + .name = "mclk0_in_div2_div", + .ops = &clk_fixed_factor_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "in0", + }, + .num_parents = 1, + }, +}; + +static const struct reg_sequence a9_mclk0_pll_init_regs[] = { + { .reg = MCLKPLL_CTRL1, .def = 0x00422000 }, + { .reg = MCLKPLL_CTRL2, .def = 0x60000100 }, + { .reg = MCLKPLL_CTRL3, .def = 0x02000200 }, + { .reg = MCLKPLL_CTRL4, .def = 0xd616d616 } +}; + +static struct clk_regmap a9_mclk0_pll_dco = { + .data = &(struct meson_clk_pll_data) { + .en = { + .reg_off = MCLKPLL_CTRL0, + .shift = 28, + .width = 1, + }, + .m = { + .reg_off = MCLKPLL_CTRL0, + .shift = 0, + .width = 9, + }, + .n = { + .reg_off = MCLKPLL_CTRL0, + .shift = 12, + .width = 3, + }, + .l = { + .reg_off = MCLKPLL_CTRL0, + .shift = 31, + .width = 1, + }, + .rst = { + .reg_off = MCLKPLL_CTRL0, + .shift = 29, + .width = 1, + }, + .l_detect = { + .reg_off = MCLKPLL_CTRL0, + .shift = 30, + .width = 1, + }, + .range = &a9_pll_mult_range, + .init_regs = a9_mclk0_pll_init_regs, + .init_count = ARRAY_SIZE(a9_mclk0_pll_init_regs), + .flags = CLK_MESON_PLL_RST_ACTIVE_LOW | + CLK_MESON_PLL_N_POWER_OF_TWO | + CLK_MESON_PLL_L_DETECT_ACTIVE_HIGH, + }, + .hw.init = &(struct clk_init_data) { + .name = "mclk0_pll_dco", + .ops = &meson_clk_pll_ops, + .parent_hws = (const struct clk_hw *[]) { + &a9_mclk0_in_div2.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap a9_mclk0_0_pll = { + .data = &(struct clk_regmap_div_data) { + .offset = MCLKPLL_CTRL3, + .shift = 0, + .width = 3, + .table = a9_pll_od_table, + }, + .hw.init = &(struct clk_init_data) { + .name = "mclk0_0_pll", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &a9_mclk0_pll_dco.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap a9_mclk0_0_pre = { + .data = &(struct clk_regmap_div_data) { + .offset = MCLKPLL_CTRL3, + .shift = 3, + .width = 5, + .flags = CLK_DIVIDER_MAX_AT_ZERO, + }, + .hw.init = &(struct clk_init_data) { + .name = "mclk0_0_pre", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &a9_mclk0_0_pll.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static const struct clk_parent_data a9_mclk0_0_parents[] = { + { .hw = &a9_mclk0_0_pre.hw }, + { .fw_name = "in0" }, + { .fw_name = "in1" }, + { .fw_name = "in2" } +}; + +static A9_COMP_SEL(mclk0_0, MCLKPLL_CTRL3, 12, 0x3, a9_mclk0_0_parents); +static A9_COMP_DIV(mclk0_0, MCLKPLL_CTRL3, 10, 1); +static A9_COMP_GATE(mclk0_0, MCLKPLL_CTRL3, 8); + +static struct clk_regmap a9_mclk0_1_pll = { + .data = &(struct clk_regmap_div_data) { + .offset = MCLKPLL_CTRL3, + .shift = 16, + .width = 3, + .table = a9_pll_od_table, + }, + .hw.init = &(struct clk_init_data) { + .name = "mclk0_1_pll", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &a9_mclk0_pll_dco.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap a9_mclk0_1_pre = { + .data = &(struct clk_regmap_div_data) { + .offset = MCLKPLL_CTRL3, + .shift = 19, + .width = 5, + .flags = CLK_DIVIDER_MAX_AT_ZERO, + }, + .hw.init = &(struct clk_init_data) { + .name = "mclk0_1_pre", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &a9_mclk0_1_pll.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static const struct clk_parent_data a9_mclk0_1_parents[] = { + { .hw = &a9_mclk0_1_pre.hw }, + { .fw_name = "in0" }, + { .fw_name = "in1" }, + { .fw_name = "in2" } +}; + +static A9_COMP_SEL(mclk0_1, MCLKPLL_CTRL3, 28, 0x3, a9_mclk0_1_parents); +static A9_COMP_DIV(mclk0_1, MCLKPLL_CTRL3, 26, 1); +static A9_COMP_GATE(mclk0_1, MCLKPLL_CTRL3, 24); + +static struct clk_fixed_factor a9_mclk1_in_div2 = { + .mult = 1, + .div = 2, + .hw.init = &(struct clk_init_data){ + .name = "mclk1_in_div2", + .ops = &clk_fixed_factor_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "in0", + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap a9_mclk1_pll_dco = { + .data = &(struct meson_clk_pll_data) { + .en = { + .reg_off = MCLKPLL_CTRL0, + .shift = 28, + .width = 1, + }, + .m = { + .reg_off = MCLKPLL_CTRL0, + .shift = 0, + .width = 9, + }, + .n = { + .reg_off = MCLKPLL_CTRL0, + .shift = 12, + .width = 3, + }, + .l = { + .reg_off = MCLKPLL_CTRL0, + .shift = 31, + .width = 1, + }, + .rst = { + .reg_off = MCLKPLL_CTRL0, + .shift = 29, + .width = 1, + }, + .l_detect = { + .reg_off = MCLKPLL_CTRL0, + .shift = 30, + .width = 1, + }, + .range = &a9_pll_mult_range, + .init_regs = a9_mclk0_pll_init_regs, + .init_count = ARRAY_SIZE(a9_mclk0_pll_init_regs), + .flags = CLK_MESON_PLL_RST_ACTIVE_LOW | + CLK_MESON_PLL_N_POWER_OF_TWO | + CLK_MESON_PLL_L_DETECT_ACTIVE_HIGH, + }, + .hw.init = &(struct clk_init_data) { + .name = "mclk1_pll_dco", + .ops = &meson_clk_pll_ops, + .parent_hws = (const struct clk_hw *[]) { + &a9_mclk1_in_div2.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap a9_mclk1_0_pll = { + .data = &(struct clk_regmap_div_data) { + .offset = MCLKPLL_CTRL3, + .shift = 0, + .width = 3, + .table = a9_pll_od_table, + }, + .hw.init = &(struct clk_init_data) { + .name = "mclk1_0_pll", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &a9_mclk1_pll_dco.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap a9_mclk1_0_pre = { + .data = &(struct clk_regmap_div_data) { + .offset = MCLKPLL_CTRL3, + .shift = 3, + .width = 5, + .flags = CLK_DIVIDER_MAX_AT_ZERO, + }, + .hw.init = &(struct clk_init_data) { + .name = "mclk1_0_pre", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &a9_mclk1_0_pll.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static const struct clk_parent_data a9_mclk1_0_parents[] = { + { .hw = &a9_mclk1_0_pre.hw }, + { .fw_name = "in0" }, + { .fw_name = "in1" }, + { .fw_name = "in2" } +}; + +static A9_COMP_SEL(mclk1_0, MCLKPLL_CTRL3, 12, 0x3, a9_mclk1_0_parents); +static A9_COMP_DIV(mclk1_0, MCLKPLL_CTRL3, 10, 1); +static A9_COMP_GATE(mclk1_0, MCLKPLL_CTRL3, 8); + +static struct clk_regmap a9_mclk1_1_pll = { + .data = &(struct clk_regmap_div_data) { + .offset = MCLKPLL_CTRL3, + .shift = 16, + .width = 3, + .table = a9_pll_od_table, + }, + .hw.init = &(struct clk_init_data) { + .name = "mclk1_1_pll", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &a9_mclk1_pll_dco.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap a9_mclk1_1_pre = { + .data = &(struct clk_regmap_div_data) { + .offset = MCLKPLL_CTRL3, + .shift = 19, + .width = 5, + .flags = CLK_DIVIDER_MAX_AT_ZERO, + }, + .hw.init = &(struct clk_init_data) { + .name = "mclk1_1_pre", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &a9_mclk1_1_pll.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static const struct clk_parent_data a9_mclk1_1_parents[] = { + { .hw = &a9_mclk1_1_pre.hw }, + { .fw_name = "in0" }, + { .fw_name = "in1" }, + { .fw_name = "in2" } +}; + +static A9_COMP_SEL(mclk1_1, MCLKPLL_CTRL3, 28, 0x3, a9_mclk1_1_parents); +static A9_COMP_DIV(mclk1_1, MCLKPLL_CTRL3, 26, 1); +static A9_COMP_GATE(mclk1_1, MCLKPLL_CTRL3, 24); + +static struct clk_hw *a9_gp0_hw_clks[] = { + [CLKID_GP0_IN_DIV2_DIV] = &a9_gp0_in_div2_div.hw, + [CLKID_GP0_IN_DIV2] = &a9_gp0_in_div2.hw, + [CLKID_GP0_PLL_DCO] = &a9_gp0_pll_dco.hw, + [CLKID_GP0_PLL] = &a9_gp0_pll.hw, +}; + +static struct clk_hw *a9_hifi0_hw_clks[] = { + [CLKID_HIFI0_IN_DIV2_DIV] = &a9_hifi0_in_div2_div.hw, + [CLKID_HIFI0_IN_DIV2] = &a9_hifi0_in_div2.hw, + [CLKID_HIFI0_PLL_DCO] = &a9_hifi0_pll_dco.hw, + [CLKID_HIFI0_PLL] = &a9_hifi0_pll.hw, +}; + +static struct clk_hw *a9_hifi1_hw_clks[] = { + [CLKID_HIFI1_IN_DIV2_DIV] = &a9_hifi1_in_div2_div.hw, + [CLKID_HIFI1_IN_DIV2] = &a9_hifi1_in_div2.hw, + [CLKID_HIFI1_PLL_DCO] = &a9_hifi1_pll_dco.hw, + [CLKID_HIFI1_PLL] = &a9_hifi1_pll.hw, +}; + +static struct clk_hw *a9_mclk0_hw_clks[] = { + [CLKID_MCLK0_IN_DIV2] = &a9_mclk0_in_div2.hw, + [CLKID_MCLK0_PLL_DCO] = &a9_mclk0_pll_dco.hw, + [CLKID_MCLK0_0_PLL] = &a9_mclk0_0_pll.hw, + [CLKID_MCLK0_0_PRE] = &a9_mclk0_0_pre.hw, + [CLKID_MCLK0_0_SEL] = &a9_mclk0_0_sel.hw, + [CLKID_MCLK0_0_DIV] = &a9_mclk0_0_div.hw, + [CLKID_MCLK0_0] = &a9_mclk0_0.hw, + [CLKID_MCLK0_1_PLL] = &a9_mclk0_1_pll.hw, + [CLKID_MCLK0_1_PRE] = &a9_mclk0_1_pre.hw, + [CLKID_MCLK0_1_SEL] = &a9_mclk0_1_sel.hw, + [CLKID_MCLK0_1_DIV] = &a9_mclk0_1_div.hw, + [CLKID_MCLK0_1] = &a9_mclk0_1.hw, +}; + +static struct clk_hw *a9_mclk1_hw_clks[] = { + [CLKID_MCLK1_IN_DIV2] = &a9_mclk1_in_div2.hw, + [CLKID_MCLK1_PLL_DCO] = &a9_mclk1_pll_dco.hw, + [CLKID_MCLK1_0_PLL] = &a9_mclk1_0_pll.hw, + [CLKID_MCLK1_0_PRE] = &a9_mclk1_0_pre.hw, + [CLKID_MCLK1_0_SEL] = &a9_mclk1_0_sel.hw, + [CLKID_MCLK1_0_DIV] = &a9_mclk1_0_div.hw, + [CLKID_MCLK1_0] = &a9_mclk1_0.hw, + [CLKID_MCLK1_1_PLL] = &a9_mclk1_1_pll.hw, + [CLKID_MCLK1_1_PRE] = &a9_mclk1_1_pre.hw, + [CLKID_MCLK1_1_SEL] = &a9_mclk1_1_sel.hw, + [CLKID_MCLK1_1_DIV] = &a9_mclk1_1_div.hw, + [CLKID_MCLK1_1] = &a9_mclk1_1.hw, +}; + +static const struct meson_clkc_data a9_gp0_data = { + .hw_clks = { + .hws = a9_gp0_hw_clks, + .num = ARRAY_SIZE(a9_gp0_hw_clks), + }, +}; + +static const struct meson_clkc_data a9_hifi0_data = { + .hw_clks = { + .hws = a9_hifi0_hw_clks, + .num = ARRAY_SIZE(a9_hifi0_hw_clks), + }, +}; + +static const struct meson_clkc_data a9_hifi1_data = { + .hw_clks = { + .hws = a9_hifi1_hw_clks, + .num = ARRAY_SIZE(a9_hifi1_hw_clks), + }, +}; + +static const struct meson_clkc_data a9_mclk0_data = { + .hw_clks = { + .hws = a9_mclk0_hw_clks, + .num = ARRAY_SIZE(a9_mclk0_hw_clks), + }, +}; + +static const struct meson_clkc_data a9_mclk1_data = { + .hw_clks = { + .hws = a9_mclk1_hw_clks, + .num = ARRAY_SIZE(a9_mclk1_hw_clks), + }, +}; + +static const struct of_device_id a9_pll_clkc_match_table[] = { + { .compatible = "amlogic,a9-gp0-pll", .data = &a9_gp0_data, }, + { .compatible = "amlogic,a9-hifi0-pll", .data = &a9_hifi0_data, }, + { .compatible = "amlogic,a9-hifi1-pll", .data = &a9_hifi1_data, }, + { .compatible = "amlogic,a9-mclk0-pll", .data = &a9_mclk0_data, }, + { .compatible = "amlogic,a9-mclk1-pll", .data = &a9_mclk1_data, }, + {} +}; +MODULE_DEVICE_TABLE(of, a9_pll_clkc_match_table); + +static struct platform_driver a9_pll_clkc_driver = { + .probe = meson_clkc_mmio_probe, + .driver = { + .name = "a9-pll-clkc", + .of_match_table = a9_pll_clkc_match_table, + }, +}; +module_platform_driver(a9_pll_clkc_driver); + +MODULE_DESCRIPTION("Amlogic A9 PLL Clock Controller Driver"); +MODULE_AUTHOR("Jian Hu <jian.hu@amlogic.com>"); +MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS("CLK_MESON"); -- 2.47.1 ^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [PATCH 08/10] clk: amlogic: Add A9 PLL clock controller driver 2026-05-11 12:47 ` [PATCH 08/10] clk: amlogic: Add A9 PLL clock controller driver Jian Hu via B4 Relay @ 2026-05-11 15:36 ` Brian Masney 0 siblings, 0 replies; 17+ messages in thread From: Brian Masney @ 2026-05-11 15:36 UTC (permalink / raw) To: jian.hu Cc: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Neil Armstrong, Jerome Brunet, Xianwei Zhao, Kevin Hilman, Martin Blumenstingl, linux-kernel, linux-clk, devicetree, linux-amlogic, linux-arm-kernel Hi Jian, On Mon, May 11, 2026 at 08:47:30PM +0800, Jian Hu via B4 Relay wrote: > From: Jian Hu <jian.hu@amlogic.com> > > Add the PLL clock controller driver for the Amlogic A9 SoC family. > > Signed-off-by: Jian Hu <jian.hu@amlogic.com> > --- > drivers/clk/meson/Kconfig | 13 + > drivers/clk/meson/Makefile | 1 + > drivers/clk/meson/a9-pll.c | 831 +++++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 845 insertions(+) > > diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig > index cf8cf3f9e4ee..3549e67d6988 100644 > --- a/drivers/clk/meson/Kconfig > +++ b/drivers/clk/meson/Kconfig > @@ -132,6 +132,19 @@ config COMMON_CLK_A1_PERIPHERALS > device, A1 SoC Family. Say Y if you want A1 Peripherals clock > controller to work. > > +config COMMON_CLK_A9_PLL > + tristate "Amlogic A9 SoC PLL controller support" > + depends on ARM64 depends on ARM64 || COMPILE_TEST > + default ARCH_MESON > + select COMMON_CLK_MESON_REGMAP > + select COMMON_CLK_MESON_CLKC_UTILS > + select COMMON_CLK_MESON_PLL > + imply COMMON_CLK_SCMI > + help > + Support for the PLL clock controller on Amlogic A311Y3 based > + device, AKA A9. PLLs are required by most peripheral to operate. > + Say Y if you want A9 PLL clock controller to work. > + > config COMMON_CLK_C3_PLL > tristate "Amlogic C3 PLL clock controller" > depends on ARM64 > diff --git a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile > index c6719694a242..77636033061f 100644 > --- a/drivers/clk/meson/Makefile > +++ b/drivers/clk/meson/Makefile > @@ -19,6 +19,7 @@ obj-$(CONFIG_COMMON_CLK_AXG) += axg.o axg-aoclk.o > obj-$(CONFIG_COMMON_CLK_AXG_AUDIO) += axg-audio.o > obj-$(CONFIG_COMMON_CLK_A1_PLL) += a1-pll.o > obj-$(CONFIG_COMMON_CLK_A1_PERIPHERALS) += a1-peripherals.o > +obj-$(CONFIG_COMMON_CLK_A9_PLL) += a9-pll.o > obj-$(CONFIG_COMMON_CLK_C3_PLL) += c3-pll.o > obj-$(CONFIG_COMMON_CLK_C3_PERIPHERALS) += c3-peripherals.o > obj-$(CONFIG_COMMON_CLK_GXBB) += gxbb.o gxbb-aoclk.o > diff --git a/drivers/clk/meson/a9-pll.c b/drivers/clk/meson/a9-pll.c > new file mode 100644 > index 000000000000..84b591c3afff > --- /dev/null > +++ b/drivers/clk/meson/a9-pll.c > @@ -0,0 +1,831 @@ > +// SPDX-License-Identifier: (GPL-2.0-only OR MIT) > +/* > + * Copyright (C) 2026 Amlogic, Inc. All rights reserved > + */ > + > +#include <linux/clk-provider.h> > +#include <linux/platform_device.h> > +#include <dt-bindings/clock/amlogic,a9-pll-clkc.h> > +#include "clk-regmap.h" > +#include "clk-pll.h" > +#include "meson-clkc-utils.h" Sort the headers > + > +#define GP0PLL_CTRL0 0x00 > +#define GP0PLL_CTRL1 0x04 > +#define GP0PLL_CTRL2 0x08 > +#define GP0PLL_CTRL3 0x0c > +#define GP0PLL_CTRL4 0x10 > + > +/* HIFI0 and HIFI1 share the same IP and register offset layout. */ > +#define HIFIPLL_CTRL0 0x00 > +#define HIFIPLL_CTRL1 0x04 > +#define HIFIPLL_CTRL2 0x08 > +#define HIFIPLL_CTRL3 0x0c > +#define HIFIPLL_CTRL4 0x10 > + > +/* MCLK0 and MCLK1 share the same IP and register offset layout. */ > +#define MCLKPLL_CTRL0 0x00 > +#define MCLKPLL_CTRL1 0x04 > +#define MCLKPLL_CTRL2 0x08 > +#define MCLKPLL_CTRL3 0x0c > +#define MCLKPLL_CTRL4 0x10 > + > +#define A9_COMP_SEL(_name, _reg, _shift, _mask, _pdata) \ > + MESON_COMP_SEL(a9_, _name, _reg, _shift, _mask, _pdata, NULL, 0, 0) > + > +#define A9_COMP_DIV(_name, _reg, _shift, _width) \ > + MESON_COMP_DIV(a9_, _name, _reg, _shift, _width, 0, CLK_SET_RATE_PARENT) > + > +#define A9_COMP_GATE(_name, _reg, _bit) \ > + MESON_COMP_GATE(a9_, _name, _reg, _bit, CLK_SET_RATE_PARENT) > + > +/* > + * Compared with previous SoC PLLs, the A9 PLL input path has an inherent > + * 2-divider. The N pre-divider follows the same calculation rule as OD, > + * where the pre-divider ratio equals 2^N. > + * > + * A9 PLL is composed as follows: > + * > + * PLL > + * +---------------------------------+ > + * | | > + * | +--+ | > + * in/2 >>---[ /2^N ]-->| | +-----+ | > + * | | |------| DCO |----->> out > + * | +--------->| | +--v--+ | > + * | | +--+ | | > + * | | | | > + * | +--[ *(M + (F/Fmax) ]<--+ | > + * | | > + * +---------------------------------+ > + * > + * out = in / 2 * (m + frac / frac_max) / 2^n > + */ > + > +static struct clk_fixed_factor a9_gp0_in_div2_div = { > + .mult = 1, > + .div = 2, > + .hw.init = &(struct clk_init_data){ > + .name = "gp0_in_div2_div", > + .ops = &clk_fixed_factor_ops, > + .parent_data = &(const struct clk_parent_data) { > + .fw_name = "in0", > + }, > + .num_parents = 1, > + }, You can use CLK_HW_INIT_FW_NAME() for the hw.init here and other places below. > +}; > + > +static struct clk_regmap a9_gp0_in_div2 = { > + .data = &(struct clk_regmap_gate_data) { > + .offset = GP0PLL_CTRL0, > + .bit_idx = 27, > + }, > + .hw.init = &(struct clk_init_data) { > + .name = "gp0_in_div2", > + .ops = &clk_regmap_gate_ops, > + .parent_hws = (const struct clk_hw *[]) { > + &a9_gp0_in_div2_div.hw > + }, > + .num_parents = 1, > + }, > +}; > + > +/* The output frequency range of the A9 PLL_DCO is 1.4 GHz to 2.8 GHz. */ > +static const struct pll_mult_range a9_pll_mult_range = { > + .min = 117, > + .max = 233, > +}; > + > +static const struct reg_sequence a9_gp0_pll_init_regs[] = { > + { .reg = GP0PLL_CTRL0, .def = 0x00010000 }, > + { .reg = GP0PLL_CTRL1, .def = 0x11480000 }, > + { .reg = GP0PLL_CTRL2, .def = 0x1219b010 }, > + { .reg = GP0PLL_CTRL3, .def = 0x00008010 } > +}; > + > +static struct clk_regmap a9_gp0_pll_dco = { > + .data = &(struct meson_clk_pll_data) { > + .en = { > + .reg_off = GP0PLL_CTRL0, > + .shift = 28, > + .width = 1, > + }, > + .m = { > + .reg_off = GP0PLL_CTRL0, > + .shift = 0, > + .width = 9, > + }, > + .n = { > + .reg_off = GP0PLL_CTRL0, > + .shift = 12, > + .width = 3, > + }, > + .frac = { > + .reg_off = GP0PLL_CTRL1, > + .shift = 0, > + .width = 17, > + }, > + .l = { > + .reg_off = GP0PLL_CTRL0, > + .shift = 31, > + .width = 1, > + }, > + .rst = { > + .reg_off = GP0PLL_CTRL0, > + .shift = 29, > + .width = 1, > + }, > + .l_detect = { > + .reg_off = GP0PLL_CTRL0, > + .shift = 30, > + .width = 1, > + }, > + .range = &a9_pll_mult_range, > + .init_regs = a9_gp0_pll_init_regs, > + .init_count = ARRAY_SIZE(a9_gp0_pll_init_regs), > + .flags = CLK_MESON_PLL_RST_ACTIVE_LOW | > + CLK_MESON_PLL_N_POWER_OF_TWO | > + CLK_MESON_PLL_L_DETECT_ACTIVE_HIGH, > + }, > + .hw.init = &(struct clk_init_data) { > + .name = "gp0_pll_dco", > + .ops = &meson_clk_pll_ops, > + .parent_hws = (const struct clk_hw *[]) { > + &a9_gp0_in_div2.hw > + }, > + .num_parents = 1, > + }, You can use CLK_HW_INIT_HWS() here and other places below. Brian > +}; > + > +/* For gp0, hifi and mclk pll, the maximum value of od is 4. */ > +static const struct clk_div_table a9_pll_od_table[] = { > + { 0, 1 }, > + { 1, 2 }, > + { 2, 4 }, > + { 3, 8 }, > + { 4, 16 }, > + { /* sentinel */ } > +}; > + > +static struct clk_regmap a9_gp0_pll = { > + .data = &(struct clk_regmap_div_data) { > + .offset = GP0PLL_CTRL0, > + .shift = 20, > + .width = 3, > + .table = a9_pll_od_table, > + }, > + .hw.init = &(struct clk_init_data) { > + .name = "gp0_pll", > + .ops = &clk_regmap_divider_ops, > + .parent_hws = (const struct clk_hw *[]) { > + &a9_gp0_pll_dco.hw > + }, > + .num_parents = 1, > + .flags = CLK_SET_RATE_PARENT, > + }, > +}; > + > +static struct clk_fixed_factor a9_hifi0_in_div2_div = { > + .mult = 1, > + .div = 2, > + .hw.init = &(struct clk_init_data){ > + .name = "hifi0_in_div2_div", > + .ops = &clk_fixed_factor_ops, > + .parent_data = &(const struct clk_parent_data) { > + .fw_name = "in0", > + }, > + .num_parents = 1, > + }, > +}; > + > +static struct clk_regmap a9_hifi0_in_div2 = { > + .data = &(struct clk_regmap_gate_data) { > + .offset = HIFIPLL_CTRL0, > + .bit_idx = 27, > + }, > + .hw.init = &(struct clk_init_data) { > + .name = "hifi0_in_div2", > + .ops = &clk_regmap_gate_ops, > + .parent_hws = (const struct clk_hw *[]) { > + &a9_hifi0_in_div2_div.hw > + }, > + .num_parents = 1, > + }, > +}; > + > +static const struct reg_sequence a9_hifi0_pll_init_regs[] = { > + { .reg = HIFIPLL_CTRL0, .def = 0x00010000 }, > + { .reg = HIFIPLL_CTRL1, .def = 0x11480000 }, > + { .reg = HIFIPLL_CTRL2, .def = 0x1219b010 }, > + { .reg = HIFIPLL_CTRL3, .def = 0x00008010 } > +}; > + > +static struct clk_regmap a9_hifi0_pll_dco = { > + .data = &(struct meson_clk_pll_data) { > + .en = { > + .reg_off = HIFIPLL_CTRL0, > + .shift = 28, > + .width = 1, > + }, > + .m = { > + .reg_off = HIFIPLL_CTRL0, > + .shift = 0, > + .width = 9, > + }, > + .n = { > + .reg_off = HIFIPLL_CTRL0, > + .shift = 12, > + .width = 3, > + }, > + .frac = { > + .reg_off = HIFIPLL_CTRL1, > + .shift = 0, > + .width = 17, > + }, > + .l = { > + .reg_off = HIFIPLL_CTRL0, > + .shift = 31, > + .width = 1, > + }, > + .rst = { > + .reg_off = HIFIPLL_CTRL0, > + .shift = 29, > + .width = 1, > + }, > + .l_detect = { > + .reg_off = HIFIPLL_CTRL0, > + .shift = 30, > + .width = 1, > + }, > + .range = &a9_pll_mult_range, > + .init_regs = a9_hifi0_pll_init_regs, > + .init_count = ARRAY_SIZE(a9_hifi0_pll_init_regs), > + .frac_max = 100000, > + .flags = CLK_MESON_PLL_RST_ACTIVE_LOW | > + CLK_MESON_PLL_N_POWER_OF_TWO | > + CLK_MESON_PLL_L_DETECT_ACTIVE_HIGH, > + }, > + .hw.init = &(struct clk_init_data) { > + .name = "hifi0_pll_dco", > + .ops = &meson_clk_pll_ops, > + .parent_hws = (const struct clk_hw *[]) { > + &a9_hifi0_in_div2.hw > + }, > + .num_parents = 1, > + }, > +}; > + > +static struct clk_regmap a9_hifi0_pll = { > + .data = &(struct clk_regmap_div_data) { > + .offset = HIFIPLL_CTRL0, > + .shift = 20, > + .width = 3, > + .table = a9_pll_od_table, > + }, > + .hw.init = &(struct clk_init_data) { > + .name = "hifi0_pll", > + .ops = &clk_regmap_divider_ops, > + .parent_hws = (const struct clk_hw *[]) { > + &a9_hifi0_pll_dco.hw > + }, > + .num_parents = 1, > + .flags = CLK_SET_RATE_PARENT, > + }, > +}; > + > +static struct clk_fixed_factor a9_hifi1_in_div2_div = { > + .mult = 1, > + .div = 2, > + .hw.init = &(struct clk_init_data){ > + .name = "hifi1_in_div2_div", > + .ops = &clk_fixed_factor_ops, > + .parent_data = &(const struct clk_parent_data) { > + .fw_name = "in0", > + }, > + .num_parents = 1, > + }, > +}; > + > +static struct clk_regmap a9_hifi1_in_div2 = { > + .data = &(struct clk_regmap_gate_data) { > + .offset = HIFIPLL_CTRL0, > + .bit_idx = 27, > + }, > + .hw.init = &(struct clk_init_data) { > + .name = "hifi1_in_div2", > + .ops = &clk_regmap_gate_ops, > + .parent_hws = (const struct clk_hw *[]) { > + &a9_hifi1_in_div2_div.hw > + }, > + .num_parents = 1, > + }, > +}; > + > +static const struct reg_sequence a9_hifi1_pll_init_regs[] = { > + { .reg = HIFIPLL_CTRL0, .def = 0x00010000 }, > + { .reg = HIFIPLL_CTRL1, .def = 0x11480000 }, > + { .reg = HIFIPLL_CTRL2, .def = 0x1219b011 }, > + { .reg = HIFIPLL_CTRL3, .def = 0x00008010 } > +}; > + > +static struct clk_regmap a9_hifi1_pll_dco = { > + .data = &(struct meson_clk_pll_data) { > + .en = { > + .reg_off = HIFIPLL_CTRL0, > + .shift = 28, > + .width = 1, > + }, > + .m = { > + .reg_off = HIFIPLL_CTRL0, > + .shift = 0, > + .width = 9, > + }, > + .n = { > + .reg_off = HIFIPLL_CTRL0, > + .shift = 12, > + .width = 3, > + }, > + .frac = { > + .reg_off = HIFIPLL_CTRL1, > + .shift = 0, > + .width = 17, > + }, > + .l = { > + .reg_off = HIFIPLL_CTRL0, > + .shift = 31, > + .width = 1, > + }, > + .rst = { > + .reg_off = HIFIPLL_CTRL0, > + .shift = 29, > + .width = 1, > + }, > + .l_detect = { > + .reg_off = HIFIPLL_CTRL0, > + .shift = 30, > + .width = 1, > + }, > + .range = &a9_pll_mult_range, > + .init_regs = a9_hifi1_pll_init_regs, > + .init_count = ARRAY_SIZE(a9_hifi1_pll_init_regs), > + .frac_max = 100000, > + .flags = CLK_MESON_PLL_RST_ACTIVE_LOW | > + CLK_MESON_PLL_N_POWER_OF_TWO | > + CLK_MESON_PLL_L_DETECT_ACTIVE_HIGH, > + }, > + .hw.init = &(struct clk_init_data) { > + .name = "hifi1_pll_dco", > + .ops = &meson_clk_pll_ops, > + .parent_hws = (const struct clk_hw *[]) { > + &a9_hifi1_in_div2.hw > + }, > + .num_parents = 1, > + }, > +}; > + > +static struct clk_regmap a9_hifi1_pll = { > + .data = &(struct clk_regmap_div_data) { > + .offset = HIFIPLL_CTRL0, > + .shift = 20, > + .width = 3, > + .table = a9_pll_od_table, > + }, > + .hw.init = &(struct clk_init_data) { > + .name = "hifi1_pll", > + .ops = &clk_regmap_divider_ops, > + .parent_hws = (const struct clk_hw *[]) { > + &a9_hifi1_pll_dco.hw > + }, > + .num_parents = 1, > + .flags = CLK_SET_RATE_PARENT, > + }, > +}; > + > +/* > + * Unlike GP0 and HIFI PLLs, the input divider 2 of MCLK PLL is > + * enabled by default and has no enable control bit. > + */ > +static struct clk_fixed_factor a9_mclk0_in_div2 = { > + .mult = 1, > + .div = 2, > + .hw.init = &(struct clk_init_data){ > + .name = "mclk0_in_div2_div", > + .ops = &clk_fixed_factor_ops, > + .parent_data = &(const struct clk_parent_data) { > + .fw_name = "in0", > + }, > + .num_parents = 1, > + }, > +}; > + > +static const struct reg_sequence a9_mclk0_pll_init_regs[] = { > + { .reg = MCLKPLL_CTRL1, .def = 0x00422000 }, > + { .reg = MCLKPLL_CTRL2, .def = 0x60000100 }, > + { .reg = MCLKPLL_CTRL3, .def = 0x02000200 }, > + { .reg = MCLKPLL_CTRL4, .def = 0xd616d616 } > +}; > + > +static struct clk_regmap a9_mclk0_pll_dco = { > + .data = &(struct meson_clk_pll_data) { > + .en = { > + .reg_off = MCLKPLL_CTRL0, > + .shift = 28, > + .width = 1, > + }, > + .m = { > + .reg_off = MCLKPLL_CTRL0, > + .shift = 0, > + .width = 9, > + }, > + .n = { > + .reg_off = MCLKPLL_CTRL0, > + .shift = 12, > + .width = 3, > + }, > + .l = { > + .reg_off = MCLKPLL_CTRL0, > + .shift = 31, > + .width = 1, > + }, > + .rst = { > + .reg_off = MCLKPLL_CTRL0, > + .shift = 29, > + .width = 1, > + }, > + .l_detect = { > + .reg_off = MCLKPLL_CTRL0, > + .shift = 30, > + .width = 1, > + }, > + .range = &a9_pll_mult_range, > + .init_regs = a9_mclk0_pll_init_regs, > + .init_count = ARRAY_SIZE(a9_mclk0_pll_init_regs), > + .flags = CLK_MESON_PLL_RST_ACTIVE_LOW | > + CLK_MESON_PLL_N_POWER_OF_TWO | > + CLK_MESON_PLL_L_DETECT_ACTIVE_HIGH, > + }, > + .hw.init = &(struct clk_init_data) { > + .name = "mclk0_pll_dco", > + .ops = &meson_clk_pll_ops, > + .parent_hws = (const struct clk_hw *[]) { > + &a9_mclk0_in_div2.hw > + }, > + .num_parents = 1, > + }, > +}; > + > +static struct clk_regmap a9_mclk0_0_pll = { > + .data = &(struct clk_regmap_div_data) { > + .offset = MCLKPLL_CTRL3, > + .shift = 0, > + .width = 3, > + .table = a9_pll_od_table, > + }, > + .hw.init = &(struct clk_init_data) { > + .name = "mclk0_0_pll", > + .ops = &clk_regmap_divider_ops, > + .parent_hws = (const struct clk_hw *[]) { > + &a9_mclk0_pll_dco.hw > + }, > + .num_parents = 1, > + }, > +}; > + > +static struct clk_regmap a9_mclk0_0_pre = { > + .data = &(struct clk_regmap_div_data) { > + .offset = MCLKPLL_CTRL3, > + .shift = 3, > + .width = 5, > + .flags = CLK_DIVIDER_MAX_AT_ZERO, > + }, > + .hw.init = &(struct clk_init_data) { > + .name = "mclk0_0_pre", > + .ops = &clk_regmap_divider_ops, > + .parent_hws = (const struct clk_hw *[]) { > + &a9_mclk0_0_pll.hw > + }, > + .num_parents = 1, > + .flags = CLK_SET_RATE_PARENT, > + }, > +}; > + > +static const struct clk_parent_data a9_mclk0_0_parents[] = { > + { .hw = &a9_mclk0_0_pre.hw }, > + { .fw_name = "in0" }, > + { .fw_name = "in1" }, > + { .fw_name = "in2" } > +}; > + > +static A9_COMP_SEL(mclk0_0, MCLKPLL_CTRL3, 12, 0x3, a9_mclk0_0_parents); > +static A9_COMP_DIV(mclk0_0, MCLKPLL_CTRL3, 10, 1); > +static A9_COMP_GATE(mclk0_0, MCLKPLL_CTRL3, 8); > + > +static struct clk_regmap a9_mclk0_1_pll = { > + .data = &(struct clk_regmap_div_data) { > + .offset = MCLKPLL_CTRL3, > + .shift = 16, > + .width = 3, > + .table = a9_pll_od_table, > + }, > + .hw.init = &(struct clk_init_data) { > + .name = "mclk0_1_pll", > + .ops = &clk_regmap_divider_ops, > + .parent_hws = (const struct clk_hw *[]) { > + &a9_mclk0_pll_dco.hw > + }, > + .num_parents = 1, > + }, > +}; > + > +static struct clk_regmap a9_mclk0_1_pre = { > + .data = &(struct clk_regmap_div_data) { > + .offset = MCLKPLL_CTRL3, > + .shift = 19, > + .width = 5, > + .flags = CLK_DIVIDER_MAX_AT_ZERO, > + }, > + .hw.init = &(struct clk_init_data) { > + .name = "mclk0_1_pre", > + .ops = &clk_regmap_divider_ops, > + .parent_hws = (const struct clk_hw *[]) { > + &a9_mclk0_1_pll.hw > + }, > + .num_parents = 1, > + .flags = CLK_SET_RATE_PARENT, > + }, > +}; > + > +static const struct clk_parent_data a9_mclk0_1_parents[] = { > + { .hw = &a9_mclk0_1_pre.hw }, > + { .fw_name = "in0" }, > + { .fw_name = "in1" }, > + { .fw_name = "in2" } > +}; > + > +static A9_COMP_SEL(mclk0_1, MCLKPLL_CTRL3, 28, 0x3, a9_mclk0_1_parents); > +static A9_COMP_DIV(mclk0_1, MCLKPLL_CTRL3, 26, 1); > +static A9_COMP_GATE(mclk0_1, MCLKPLL_CTRL3, 24); > + > +static struct clk_fixed_factor a9_mclk1_in_div2 = { > + .mult = 1, > + .div = 2, > + .hw.init = &(struct clk_init_data){ > + .name = "mclk1_in_div2", > + .ops = &clk_fixed_factor_ops, > + .parent_data = &(const struct clk_parent_data) { > + .fw_name = "in0", > + }, > + .num_parents = 1, > + }, > +}; > + > +static struct clk_regmap a9_mclk1_pll_dco = { > + .data = &(struct meson_clk_pll_data) { > + .en = { > + .reg_off = MCLKPLL_CTRL0, > + .shift = 28, > + .width = 1, > + }, > + .m = { > + .reg_off = MCLKPLL_CTRL0, > + .shift = 0, > + .width = 9, > + }, > + .n = { > + .reg_off = MCLKPLL_CTRL0, > + .shift = 12, > + .width = 3, > + }, > + .l = { > + .reg_off = MCLKPLL_CTRL0, > + .shift = 31, > + .width = 1, > + }, > + .rst = { > + .reg_off = MCLKPLL_CTRL0, > + .shift = 29, > + .width = 1, > + }, > + .l_detect = { > + .reg_off = MCLKPLL_CTRL0, > + .shift = 30, > + .width = 1, > + }, > + .range = &a9_pll_mult_range, > + .init_regs = a9_mclk0_pll_init_regs, > + .init_count = ARRAY_SIZE(a9_mclk0_pll_init_regs), > + .flags = CLK_MESON_PLL_RST_ACTIVE_LOW | > + CLK_MESON_PLL_N_POWER_OF_TWO | > + CLK_MESON_PLL_L_DETECT_ACTIVE_HIGH, > + }, > + .hw.init = &(struct clk_init_data) { > + .name = "mclk1_pll_dco", > + .ops = &meson_clk_pll_ops, > + .parent_hws = (const struct clk_hw *[]) { > + &a9_mclk1_in_div2.hw > + }, > + .num_parents = 1, > + }, > +}; > + > +static struct clk_regmap a9_mclk1_0_pll = { > + .data = &(struct clk_regmap_div_data) { > + .offset = MCLKPLL_CTRL3, > + .shift = 0, > + .width = 3, > + .table = a9_pll_od_table, > + }, > + .hw.init = &(struct clk_init_data) { > + .name = "mclk1_0_pll", > + .ops = &clk_regmap_divider_ops, > + .parent_hws = (const struct clk_hw *[]) { > + &a9_mclk1_pll_dco.hw > + }, > + .num_parents = 1, > + }, > +}; > + > +static struct clk_regmap a9_mclk1_0_pre = { > + .data = &(struct clk_regmap_div_data) { > + .offset = MCLKPLL_CTRL3, > + .shift = 3, > + .width = 5, > + .flags = CLK_DIVIDER_MAX_AT_ZERO, > + }, > + .hw.init = &(struct clk_init_data) { > + .name = "mclk1_0_pre", > + .ops = &clk_regmap_divider_ops, > + .parent_hws = (const struct clk_hw *[]) { > + &a9_mclk1_0_pll.hw > + }, > + .num_parents = 1, > + .flags = CLK_SET_RATE_PARENT, > + }, > +}; > + > +static const struct clk_parent_data a9_mclk1_0_parents[] = { > + { .hw = &a9_mclk1_0_pre.hw }, > + { .fw_name = "in0" }, > + { .fw_name = "in1" }, > + { .fw_name = "in2" } > +}; > + > +static A9_COMP_SEL(mclk1_0, MCLKPLL_CTRL3, 12, 0x3, a9_mclk1_0_parents); > +static A9_COMP_DIV(mclk1_0, MCLKPLL_CTRL3, 10, 1); > +static A9_COMP_GATE(mclk1_0, MCLKPLL_CTRL3, 8); > + > +static struct clk_regmap a9_mclk1_1_pll = { > + .data = &(struct clk_regmap_div_data) { > + .offset = MCLKPLL_CTRL3, > + .shift = 16, > + .width = 3, > + .table = a9_pll_od_table, > + }, > + .hw.init = &(struct clk_init_data) { > + .name = "mclk1_1_pll", > + .ops = &clk_regmap_divider_ops, > + .parent_hws = (const struct clk_hw *[]) { > + &a9_mclk1_pll_dco.hw > + }, > + .num_parents = 1, > + }, > +}; > + > +static struct clk_regmap a9_mclk1_1_pre = { > + .data = &(struct clk_regmap_div_data) { > + .offset = MCLKPLL_CTRL3, > + .shift = 19, > + .width = 5, > + .flags = CLK_DIVIDER_MAX_AT_ZERO, > + }, > + .hw.init = &(struct clk_init_data) { > + .name = "mclk1_1_pre", > + .ops = &clk_regmap_divider_ops, > + .parent_hws = (const struct clk_hw *[]) { > + &a9_mclk1_1_pll.hw > + }, > + .num_parents = 1, > + .flags = CLK_SET_RATE_PARENT, > + }, > +}; > + > +static const struct clk_parent_data a9_mclk1_1_parents[] = { > + { .hw = &a9_mclk1_1_pre.hw }, > + { .fw_name = "in0" }, > + { .fw_name = "in1" }, > + { .fw_name = "in2" } > +}; > + > +static A9_COMP_SEL(mclk1_1, MCLKPLL_CTRL3, 28, 0x3, a9_mclk1_1_parents); > +static A9_COMP_DIV(mclk1_1, MCLKPLL_CTRL3, 26, 1); > +static A9_COMP_GATE(mclk1_1, MCLKPLL_CTRL3, 24); > + > +static struct clk_hw *a9_gp0_hw_clks[] = { > + [CLKID_GP0_IN_DIV2_DIV] = &a9_gp0_in_div2_div.hw, > + [CLKID_GP0_IN_DIV2] = &a9_gp0_in_div2.hw, > + [CLKID_GP0_PLL_DCO] = &a9_gp0_pll_dco.hw, > + [CLKID_GP0_PLL] = &a9_gp0_pll.hw, > +}; > + > +static struct clk_hw *a9_hifi0_hw_clks[] = { > + [CLKID_HIFI0_IN_DIV2_DIV] = &a9_hifi0_in_div2_div.hw, > + [CLKID_HIFI0_IN_DIV2] = &a9_hifi0_in_div2.hw, > + [CLKID_HIFI0_PLL_DCO] = &a9_hifi0_pll_dco.hw, > + [CLKID_HIFI0_PLL] = &a9_hifi0_pll.hw, > +}; > + > +static struct clk_hw *a9_hifi1_hw_clks[] = { > + [CLKID_HIFI1_IN_DIV2_DIV] = &a9_hifi1_in_div2_div.hw, > + [CLKID_HIFI1_IN_DIV2] = &a9_hifi1_in_div2.hw, > + [CLKID_HIFI1_PLL_DCO] = &a9_hifi1_pll_dco.hw, > + [CLKID_HIFI1_PLL] = &a9_hifi1_pll.hw, > +}; > + > +static struct clk_hw *a9_mclk0_hw_clks[] = { > + [CLKID_MCLK0_IN_DIV2] = &a9_mclk0_in_div2.hw, > + [CLKID_MCLK0_PLL_DCO] = &a9_mclk0_pll_dco.hw, > + [CLKID_MCLK0_0_PLL] = &a9_mclk0_0_pll.hw, > + [CLKID_MCLK0_0_PRE] = &a9_mclk0_0_pre.hw, > + [CLKID_MCLK0_0_SEL] = &a9_mclk0_0_sel.hw, > + [CLKID_MCLK0_0_DIV] = &a9_mclk0_0_div.hw, > + [CLKID_MCLK0_0] = &a9_mclk0_0.hw, > + [CLKID_MCLK0_1_PLL] = &a9_mclk0_1_pll.hw, > + [CLKID_MCLK0_1_PRE] = &a9_mclk0_1_pre.hw, > + [CLKID_MCLK0_1_SEL] = &a9_mclk0_1_sel.hw, > + [CLKID_MCLK0_1_DIV] = &a9_mclk0_1_div.hw, > + [CLKID_MCLK0_1] = &a9_mclk0_1.hw, > +}; > + > +static struct clk_hw *a9_mclk1_hw_clks[] = { > + [CLKID_MCLK1_IN_DIV2] = &a9_mclk1_in_div2.hw, > + [CLKID_MCLK1_PLL_DCO] = &a9_mclk1_pll_dco.hw, > + [CLKID_MCLK1_0_PLL] = &a9_mclk1_0_pll.hw, > + [CLKID_MCLK1_0_PRE] = &a9_mclk1_0_pre.hw, > + [CLKID_MCLK1_0_SEL] = &a9_mclk1_0_sel.hw, > + [CLKID_MCLK1_0_DIV] = &a9_mclk1_0_div.hw, > + [CLKID_MCLK1_0] = &a9_mclk1_0.hw, > + [CLKID_MCLK1_1_PLL] = &a9_mclk1_1_pll.hw, > + [CLKID_MCLK1_1_PRE] = &a9_mclk1_1_pre.hw, > + [CLKID_MCLK1_1_SEL] = &a9_mclk1_1_sel.hw, > + [CLKID_MCLK1_1_DIV] = &a9_mclk1_1_div.hw, > + [CLKID_MCLK1_1] = &a9_mclk1_1.hw, > +}; > + > +static const struct meson_clkc_data a9_gp0_data = { > + .hw_clks = { > + .hws = a9_gp0_hw_clks, > + .num = ARRAY_SIZE(a9_gp0_hw_clks), > + }, > +}; > + > +static const struct meson_clkc_data a9_hifi0_data = { > + .hw_clks = { > + .hws = a9_hifi0_hw_clks, > + .num = ARRAY_SIZE(a9_hifi0_hw_clks), > + }, > +}; > + > +static const struct meson_clkc_data a9_hifi1_data = { > + .hw_clks = { > + .hws = a9_hifi1_hw_clks, > + .num = ARRAY_SIZE(a9_hifi1_hw_clks), > + }, > +}; > + > +static const struct meson_clkc_data a9_mclk0_data = { > + .hw_clks = { > + .hws = a9_mclk0_hw_clks, > + .num = ARRAY_SIZE(a9_mclk0_hw_clks), > + }, > +}; > + > +static const struct meson_clkc_data a9_mclk1_data = { > + .hw_clks = { > + .hws = a9_mclk1_hw_clks, > + .num = ARRAY_SIZE(a9_mclk1_hw_clks), > + }, > +}; > + > +static const struct of_device_id a9_pll_clkc_match_table[] = { > + { .compatible = "amlogic,a9-gp0-pll", .data = &a9_gp0_data, }, > + { .compatible = "amlogic,a9-hifi0-pll", .data = &a9_hifi0_data, }, > + { .compatible = "amlogic,a9-hifi1-pll", .data = &a9_hifi1_data, }, > + { .compatible = "amlogic,a9-mclk0-pll", .data = &a9_mclk0_data, }, > + { .compatible = "amlogic,a9-mclk1-pll", .data = &a9_mclk1_data, }, > + {} > +}; > +MODULE_DEVICE_TABLE(of, a9_pll_clkc_match_table); > + > +static struct platform_driver a9_pll_clkc_driver = { > + .probe = meson_clkc_mmio_probe, > + .driver = { > + .name = "a9-pll-clkc", > + .of_match_table = a9_pll_clkc_match_table, > + }, > +}; > +module_platform_driver(a9_pll_clkc_driver); > + > +MODULE_DESCRIPTION("Amlogic A9 PLL Clock Controller Driver"); > +MODULE_AUTHOR("Jian Hu <jian.hu@amlogic.com>"); > +MODULE_LICENSE("GPL"); > +MODULE_IMPORT_NS("CLK_MESON"); > > -- > 2.47.1 > > ^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 09/10] clk: amlogic: Add A9 peripherals clock controller driver 2026-05-11 12:47 [PATCH 00/10] Add support for A9 family clock controller Jian Hu via B4 Relay ` (7 preceding siblings ...) 2026-05-11 12:47 ` [PATCH 08/10] clk: amlogic: Add A9 PLL clock controller driver Jian Hu via B4 Relay @ 2026-05-11 12:47 ` Jian Hu via B4 Relay 2026-05-11 15:42 ` Brian Masney 2026-05-11 12:47 ` [PATCH 10/10] clk: amlogic: Add A9 AO " Jian Hu via B4 Relay 9 siblings, 1 reply; 17+ messages in thread From: Jian Hu via B4 Relay @ 2026-05-11 12:47 UTC (permalink / raw) To: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Neil Armstrong, Jerome Brunet, Xianwei Zhao, Kevin Hilman, Martin Blumenstingl Cc: linux-kernel, linux-clk, devicetree, linux-amlogic, linux-arm-kernel, Jian Hu From: Jian Hu <jian.hu@amlogic.com> Add the peripherals clock controller driver for the Amlogic A9 SoC family. Signed-off-by: Jian Hu <jian.hu@amlogic.com> --- drivers/clk/meson/Kconfig | 15 + drivers/clk/meson/Makefile | 1 + drivers/clk/meson/a9-peripherals.c | 2317 ++++++++++++++++++++++++++++++++++++ 3 files changed, 2333 insertions(+) diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig index 3549e67d6988..48a15a5e1323 100644 --- a/drivers/clk/meson/Kconfig +++ b/drivers/clk/meson/Kconfig @@ -145,6 +145,21 @@ config COMMON_CLK_A9_PLL device, AKA A9. PLLs are required by most peripheral to operate. Say Y if you want A9 PLL clock controller to work. +config COMMON_CLK_A9_PERIPHERALS + tristate "Amlogic A9 SoC peripherals clock controller support" + depends on ARM64 + default ARCH_MESON + select COMMON_CLK_MESON_REGMAP + select COMMON_CLK_MESON_CLKC_UTILS + select COMMON_CLK_MESON_DUALDIV + select COMMON_CLK_MESON_VID_PLL_DIV + imply COMMON_CLK_SCMI + imply COMMON_CLK_A9_PLL + help + Support for the peripherals clock controller on Amlogic A311Y3 based + device, AKA A9. Peripherals are required by most peripheral to operate. + Say Y if you want A9 peripherals clock controller to work. + config COMMON_CLK_C3_PLL tristate "Amlogic C3 PLL clock controller" depends on ARM64 diff --git a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile index 77636033061f..2b5b67b14efc 100644 --- a/drivers/clk/meson/Makefile +++ b/drivers/clk/meson/Makefile @@ -20,6 +20,7 @@ obj-$(CONFIG_COMMON_CLK_AXG_AUDIO) += axg-audio.o obj-$(CONFIG_COMMON_CLK_A1_PLL) += a1-pll.o obj-$(CONFIG_COMMON_CLK_A1_PERIPHERALS) += a1-peripherals.o obj-$(CONFIG_COMMON_CLK_A9_PLL) += a9-pll.o +obj-$(CONFIG_COMMON_CLK_A9_PERIPHERALS) += a9-peripherals.o obj-$(CONFIG_COMMON_CLK_C3_PLL) += c3-pll.o obj-$(CONFIG_COMMON_CLK_C3_PERIPHERALS) += c3-peripherals.o obj-$(CONFIG_COMMON_CLK_GXBB) += gxbb.o gxbb-aoclk.o diff --git a/drivers/clk/meson/a9-peripherals.c b/drivers/clk/meson/a9-peripherals.c new file mode 100644 index 000000000000..338a91c473ea --- /dev/null +++ b/drivers/clk/meson/a9-peripherals.c @@ -0,0 +1,2317 @@ +// SPDX-License-Identifier: (GPL-2.0-only OR MIT) +/* + * Copyright (C) 2026 Amlogic, Inc. All rights reserved + */ + +#include <linux/clk-provider.h> +#include <linux/platform_device.h> +#include <dt-bindings/clock/amlogic,a9-peripherals-clkc.h> +#include "clk-regmap.h" +#include "clk-dualdiv.h" +#include "vid-pll-div.h" +#include "meson-clkc-utils.h" + +#define SYS_CLK_EN0_REG0 0x30 +#define SYS_CLK_EN0_REG1 0x34 +#define SYS_CLK_EN0_REG2 0x38 +#define SYS_CLK_EN0_REG3 0x3c +#define SD_EMMC_CLK_CTRL0 0x90 +#define SD_EMMC_CLK_CTRL1 0x94 +#define PWM_CLK_H_CTRL 0xbc +#define PWM_CLK_I_CTRL 0xc0 +#define PWM_CLK_J_CTRL 0xc4 +#define PWM_CLK_K_CTRL 0xc8 +#define PWM_CLK_L_CTRL 0xcc +#define PWM_CLK_M_CTRL 0xd0 +#define PWM_CLK_N_CTRL 0xd4 +#define SPISG_CLK_CTRL 0x100 +#define SPISG_CLK_CTRL1 0x104 +#define SAR_CLK_CTRL 0x150 +#define AMFC_CLK_CTRL 0x154 +#define NNA_CLK_CTRL 0x15c +#define USB_CLK_CTRL 0x160 +#define PCIE_TL_CLK_CTRL 0x164 +#define CMPR_CLK_CTRL 0x168 +#define DEWARP_CLK_CTRL 0x16c +#define SC_CLK_CTRL 0x170 +#define DPTX_CLK_CTRL 0x178 +#define ISP_CLK_CTRL 0x17c +#define CVE_CLK_CTRL 0x180 +#define PP_CLK_CTRL 0x184 +#define GLB_CLK_CTRL 0x188 +#define USB_CLK_CTRL0 0x18c +#define USB_CLK_CTRL1 0x190 +#define CAN_CLK_CTRL 0x194 +#define CAN_CLK_CTRL1 0x198 +#define I3C_CLK_CTRL 0x19c +#define TS_CLK_CTRL 0x1a0 +#define ETH_CLK_CTRL 0x1a4 +#define GEN_CLK_CTRL 0x1a8 +#define CLK12_24_CTRL 0x1ac +#define MALI_CLK_CTRL 0x200 +#define MALI_STACK_CLK_CTRL 0x204 +#define DSPA_CLK_CTRL 0x220 +#define HEVCF_CLK_CTRL 0x240 +#define HCODEC_CLK_CTRL 0x244 +#define VPU_CLK_CTRL 0x260 +#define VAPB_CLK_CTRL 0x268 +#define VPU_CLKB_CTRL 0x280 +#define HDMI_CLK_CTRL 0x284 +#define HTX_CLK_CTRL 0x28c +#define HTX_CLK_CTRL1 0x290 +#define HRX_CLK_CTRL 0x294 +#define HRX_CLK_CTRL1 0x298 +#define HRX_CLK_CTRL2 0x29c +#define HRX_CLK_CTRL3 0x2a0 +#define VID_LOCK_CLK_CTRL 0x2a4 +#define VDIN_MEAS_CLK_CTRL 0x2a8 +#define VID_PLL_CLK_DIV 0x2b0 +#define VID_CLK_CTRL 0x2c0 +#define VID_CLK_CTRL2 0x2c4 +#define VID_CLK_DIV 0x2c8 +#define VIID_CLK_DIV 0x2cc +#define VIID_CLK_CTRL 0x2d0 +#define MIPI_CSI_PHY_CLK_CTRL 0x2e0 +#define DSI_MEAS_CLK_CTRL 0x2f4 + +#define A9_COMP_SEL(_name, _reg, _shift, _mask, _pdata, _table) \ + MESON_COMP_SEL(a9_, _name, _reg, _shift, _mask, _pdata, _table, 0, 0) + +#define A9_COMP_DIV(_name, _reg, _shift, _width) \ + MESON_COMP_DIV(a9_, _name, _reg, _shift, _width, 0, CLK_SET_RATE_PARENT) + +#define A9_COMP_GATE(_name, _reg, _bit, _iflags) \ + MESON_COMP_GATE(a9_, _name, _reg, _bit, CLK_SET_RATE_PARENT | (_iflags)) + +static const struct clk_parent_data a9_sys_pclk_parents = { .fw_name = "sys" }; + +#define A9_SYS_PCLK(_name, _reg, _bit) \ + MESON_PCLK(a9_##_name, _reg, _bit, &a9_sys_pclk_parents, 0) + +static A9_SYS_PCLK(sys_am_axi, SYS_CLK_EN0_REG0, 0); +static A9_SYS_PCLK(sys_dos, SYS_CLK_EN0_REG0, 1); +static A9_SYS_PCLK(sys_mipi_dsi, SYS_CLK_EN0_REG0, 3); +static A9_SYS_PCLK(sys_eth_phy, SYS_CLK_EN0_REG0, 4); +static A9_SYS_PCLK(sys_amfc, SYS_CLK_EN0_REG0, 5); +static A9_SYS_PCLK(sys_mali, SYS_CLK_EN0_REG0, 6); +static A9_SYS_PCLK(sys_nna, SYS_CLK_EN0_REG0, 7); +static A9_SYS_PCLK(sys_eth_axi, SYS_CLK_EN0_REG0, 8); +static A9_SYS_PCLK(sys_dp_apb, SYS_CLK_EN0_REG0, 9); +static A9_SYS_PCLK(sys_edptx_apb, SYS_CLK_EN0_REG0, 10); +static A9_SYS_PCLK(sys_u3hsg, SYS_CLK_EN0_REG0, 11); +static A9_SYS_PCLK(sys_aucpu, SYS_CLK_EN0_REG0, 14); +static A9_SYS_PCLK(sys_glb, SYS_CLK_EN0_REG0, 15); +static A9_SYS_PCLK(sys_combo_dphy_apb, SYS_CLK_EN0_REG0, 17); +static A9_SYS_PCLK(sys_hdmirx_apb, SYS_CLK_EN0_REG0, 18); +static A9_SYS_PCLK(sys_hdmirx_pclk, SYS_CLK_EN0_REG0, 19); +static A9_SYS_PCLK(sys_mipi_dsi_phy, SYS_CLK_EN0_REG0, 20); +static A9_SYS_PCLK(sys_can0, SYS_CLK_EN0_REG0, 21); +static A9_SYS_PCLK(sys_can1, SYS_CLK_EN0_REG0, 22); +static A9_SYS_PCLK(sys_sd_emmc_a, SYS_CLK_EN0_REG0, 24); +static A9_SYS_PCLK(sys_sd_emmc_b, SYS_CLK_EN0_REG0, 25); +static A9_SYS_PCLK(sys_sd_emmc_c, SYS_CLK_EN0_REG0, 26); +static A9_SYS_PCLK(sys_sc, SYS_CLK_EN0_REG0, 27); +static A9_SYS_PCLK(sys_acodec, SYS_CLK_EN0_REG0, 28); +static A9_SYS_PCLK(sys_mipi_isp, SYS_CLK_EN0_REG0, 29); +static A9_SYS_PCLK(sys_msr, SYS_CLK_EN0_REG0, 30); +static A9_SYS_PCLK(sys_audio, SYS_CLK_EN0_REG1, 0); +static A9_SYS_PCLK(sys_mipi_dsi_b, SYS_CLK_EN0_REG1, 1); +static A9_SYS_PCLK(sys_mipi_dsi1_phy, SYS_CLK_EN0_REG1, 2); +static A9_SYS_PCLK(sys_eth, SYS_CLK_EN0_REG1, 3); +static A9_SYS_PCLK(sys_eth_1g_mac, SYS_CLK_EN0_REG1, 4); +static A9_SYS_PCLK(sys_uart_a, SYS_CLK_EN0_REG1, 5); +static A9_SYS_PCLK(sys_uart_f, SYS_CLK_EN0_REG1, 10); +static A9_SYS_PCLK(sys_ts_a55, SYS_CLK_EN0_REG1, 11); +static A9_SYS_PCLK(sys_eth_1g_axi, SYS_CLK_EN0_REG1, 12); +static A9_SYS_PCLK(sys_ts_dos, SYS_CLK_EN0_REG1, 13); +static A9_SYS_PCLK(sys_u3drd_b, SYS_CLK_EN0_REG1, 14); +static A9_SYS_PCLK(sys_ts_core, SYS_CLK_EN0_REG1, 15); +static A9_SYS_PCLK(sys_ts_pll, SYS_CLK_EN0_REG1, 16); +static A9_SYS_PCLK(sys_csi_dig_clkin, SYS_CLK_EN0_REG1, 18); +static A9_SYS_PCLK(sys_cve, SYS_CLK_EN0_REG1, 19); +static A9_SYS_PCLK(sys_ge2d, SYS_CLK_EN0_REG1, 20); +static A9_SYS_PCLK(sys_spisg, SYS_CLK_EN0_REG1, 21); +static A9_SYS_PCLK(sys_u3drd_1, SYS_CLK_EN0_REG1, 22); +static A9_SYS_PCLK(sys_u2h, SYS_CLK_EN0_REG1, 23); +static A9_SYS_PCLK(sys_pcie_mac_a, SYS_CLK_EN0_REG1, 24); +static A9_SYS_PCLK(sys_u3drd_a, SYS_CLK_EN0_REG1, 25); +static A9_SYS_PCLK(sys_u2drd, SYS_CLK_EN0_REG1, 26); +static A9_SYS_PCLK(sys_pcie_phy, SYS_CLK_EN0_REG1, 27); +static A9_SYS_PCLK(sys_pcie_mac_b, SYS_CLK_EN0_REG1, 28); +static A9_SYS_PCLK(sys_periph, SYS_CLK_EN0_REG1, 29); +static A9_SYS_PCLK(sys_pio, SYS_CLK_EN0_REG2, 0); +static A9_SYS_PCLK(sys_i3c, SYS_CLK_EN0_REG2, 1); +static A9_SYS_PCLK(sys_i2c_m_e, SYS_CLK_EN0_REG2, 2); +static A9_SYS_PCLK(sys_i2c_m_f, SYS_CLK_EN0_REG2, 3); +static A9_SYS_PCLK(sys_hdmitx_apb, SYS_CLK_EN0_REG2, 4); +static A9_SYS_PCLK(sys_i2c_m_i, SYS_CLK_EN0_REG2, 5); +static A9_SYS_PCLK(sys_i2c_m_g, SYS_CLK_EN0_REG2, 6); +static A9_SYS_PCLK(sys_i2c_m_h, SYS_CLK_EN0_REG2, 7); +static A9_SYS_PCLK(sys_hdmi20_aes, SYS_CLK_EN0_REG2, 9); +static A9_SYS_PCLK(sys_csi2_host, SYS_CLK_EN0_REG2, 16); +static A9_SYS_PCLK(sys_csi2_adapt, SYS_CLK_EN0_REG2, 17); +static A9_SYS_PCLK(sys_dspa, SYS_CLK_EN0_REG2, 21); +static A9_SYS_PCLK(sys_pp_dma, SYS_CLK_EN0_REG2, 22); +static A9_SYS_PCLK(sys_pp_wrapper, SYS_CLK_EN0_REG2, 23); +static A9_SYS_PCLK(sys_vpu_intr, SYS_CLK_EN0_REG2, 25); +static A9_SYS_PCLK(sys_csi2_phy, SYS_CLK_EN0_REG2, 27); +static A9_SYS_PCLK(sys_saradc, SYS_CLK_EN0_REG2, 28); +static A9_SYS_PCLK(sys_pwm_j, SYS_CLK_EN0_REG2, 30); +static A9_SYS_PCLK(sys_pwm_i, SYS_CLK_EN0_REG2, 31); +static A9_SYS_PCLK(sys_pwm_h, SYS_CLK_EN0_REG3, 0); +static A9_SYS_PCLK(sys_pwm_n, SYS_CLK_EN0_REG3, 8); +static A9_SYS_PCLK(sys_pwm_m, SYS_CLK_EN0_REG3, 9); +static A9_SYS_PCLK(sys_pwm_l, SYS_CLK_EN0_REG3, 10); +static A9_SYS_PCLK(sys_pwm_k, SYS_CLK_EN0_REG3, 11); + +/* Channel 5 is unconnected. */ +static u32 a9_sd_emmc_parents_val_table[] = { 0, 1, 2, 3, 4, 6, 7 }; +static const struct clk_parent_data a9_sd_emmc_parents[] = { + { .fw_name = "xtal", }, + { .fw_name = "fdiv2", }, + { .fw_name = "fdiv3", }, + { .fw_name = "hifi0", }, + { .fw_name = "fdiv2p5", }, + { .fw_name = "gp1", }, + { .fw_name = "gp0", } +}; + +static A9_COMP_SEL(sd_emmc_a, SD_EMMC_CLK_CTRL0, 9, 0x7, a9_sd_emmc_parents, + a9_sd_emmc_parents_val_table); +static A9_COMP_DIV(sd_emmc_a, SD_EMMC_CLK_CTRL0, 0, 7); +static A9_COMP_GATE(sd_emmc_a, SD_EMMC_CLK_CTRL0, 8, 0); + +static A9_COMP_SEL(sd_emmc_b, SD_EMMC_CLK_CTRL0, 25, 0x7, a9_sd_emmc_parents, + a9_sd_emmc_parents_val_table); +static A9_COMP_DIV(sd_emmc_b, SD_EMMC_CLK_CTRL0, 16, 7); +static A9_COMP_GATE(sd_emmc_b, SD_EMMC_CLK_CTRL0, 24, 0); + +static A9_COMP_SEL(sd_emmc_c, SD_EMMC_CLK_CTRL1, 9, 0x7, a9_sd_emmc_parents, + a9_sd_emmc_parents_val_table); +static A9_COMP_DIV(sd_emmc_c, SD_EMMC_CLK_CTRL1, 0, 7); +static A9_COMP_GATE(sd_emmc_c, SD_EMMC_CLK_CTRL1, 8, 0); + +static const struct clk_parent_data a9_pwm_parents[] = { + { .fw_name = "xtal", }, + { .fw_name = "fdiv5", }, + { .fw_name = "fdiv4", }, + { .fw_name = "fdiv3", } +}; + +static A9_COMP_SEL(pwm_h, PWM_CLK_H_CTRL, 9, 0x7, a9_pwm_parents, NULL); +static A9_COMP_DIV(pwm_h, PWM_CLK_H_CTRL, 0, 8); +static A9_COMP_GATE(pwm_h, PWM_CLK_H_CTRL, 8, 0); + +static A9_COMP_SEL(pwm_i, PWM_CLK_I_CTRL, 9, 0x7, a9_pwm_parents, NULL); +static A9_COMP_DIV(pwm_i, PWM_CLK_I_CTRL, 0, 8); +static A9_COMP_GATE(pwm_i, PWM_CLK_I_CTRL, 8, 0); + +static A9_COMP_SEL(pwm_j, PWM_CLK_J_CTRL, 9, 0x7, a9_pwm_parents, NULL); +static A9_COMP_DIV(pwm_j, PWM_CLK_J_CTRL, 0, 8); +static A9_COMP_GATE(pwm_j, PWM_CLK_J_CTRL, 8, 0); + +static A9_COMP_SEL(pwm_k, PWM_CLK_K_CTRL, 9, 0x7, a9_pwm_parents, NULL); +static A9_COMP_DIV(pwm_k, PWM_CLK_K_CTRL, 0, 8); +static A9_COMP_GATE(pwm_k, PWM_CLK_K_CTRL, 8, 0); + +static A9_COMP_SEL(pwm_l, PWM_CLK_L_CTRL, 9, 0x7, a9_pwm_parents, NULL); +static A9_COMP_DIV(pwm_l, PWM_CLK_L_CTRL, 0, 8); +static A9_COMP_GATE(pwm_l, PWM_CLK_L_CTRL, 8, 0); + +static A9_COMP_SEL(pwm_m, PWM_CLK_M_CTRL, 9, 0x7, a9_pwm_parents, NULL); +static A9_COMP_DIV(pwm_m, PWM_CLK_M_CTRL, 0, 8); +static A9_COMP_GATE(pwm_m, PWM_CLK_M_CTRL, 8, 0); + +static A9_COMP_SEL(pwm_n, PWM_CLK_N_CTRL, 9, 0x7, a9_pwm_parents, NULL); +static A9_COMP_DIV(pwm_n, PWM_CLK_N_CTRL, 0, 8); +static A9_COMP_GATE(pwm_n, PWM_CLK_N_CTRL, 8, 0); + +static const struct clk_parent_data a9_spisg_parents[] = { + { .fw_name = "xtal", }, + { .fw_name = "sys", }, + { .fw_name = "fdiv4", }, + { .fw_name = "fdiv3", }, + { .fw_name = "fdiv2", }, + { .fw_name = "fdiv5", }, + { .fw_name = "fdiv7", }, + { .fw_name = "gp0", } +}; + +static A9_COMP_SEL(spisg, SPISG_CLK_CTRL, 9, 0x7, a9_spisg_parents, NULL); +static A9_COMP_DIV(spisg, SPISG_CLK_CTRL, 0, 6); +static A9_COMP_GATE(spisg, SPISG_CLK_CTRL, 8, 0); + +static A9_COMP_SEL(spisg1, SPISG_CLK_CTRL, 25, 0x7, a9_spisg_parents, NULL); +static A9_COMP_DIV(spisg1, SPISG_CLK_CTRL, 16, 6); +static A9_COMP_GATE(spisg1, SPISG_CLK_CTRL, 24, 0); + +static A9_COMP_SEL(spisg2, SPISG_CLK_CTRL1, 9, 0x7, a9_spisg_parents, NULL); +static A9_COMP_DIV(spisg2, SPISG_CLK_CTRL1, 0, 6); +static A9_COMP_GATE(spisg2, SPISG_CLK_CTRL1, 8, 0); + +static const struct clk_parent_data a9_saradc_parents[] = { + { .fw_name = "xtal", }, + { .fw_name = "sys", } +}; + +static A9_COMP_SEL(saradc, SAR_CLK_CTRL, 9, 0x7, a9_saradc_parents, NULL); +static A9_COMP_DIV(saradc, SAR_CLK_CTRL, 0, 8); +static A9_COMP_GATE(saradc, SAR_CLK_CTRL, 8, 0); + +static const struct clk_parent_data a9_amfc_parents[] = { + { .fw_name = "xtal", }, + { .fw_name = "sys", }, + { .fw_name = "fdiv2", }, + { .fw_name = "fdiv2p5", }, + { .fw_name = "fdiv3", }, + { .fw_name = "fdiv4", }, + { .fw_name = "fdiv5", }, + { .fw_name = "fdiv7", } +}; + +static A9_COMP_SEL(amfc, AMFC_CLK_CTRL, 9, 0x7, a9_amfc_parents, NULL); +static A9_COMP_DIV(amfc, AMFC_CLK_CTRL, 0, 6); +static A9_COMP_GATE(amfc, AMFC_CLK_CTRL, 8, 0); + +static const struct clk_parent_data a9_nna_parents[] = { + { .fw_name = "xtal", }, + { .fw_name = "fdiv2p5", }, + { .fw_name = "fdiv4", }, + { .fw_name = "fdiv3", }, + { .fw_name = "fdiv5", }, + { .fw_name = "fdiv2", }, + { .fw_name = "gp2", }, + { .fw_name = "hifi", } +}; + +static A9_COMP_SEL(nna, NNA_CLK_CTRL, 9, 0x7, a9_nna_parents, NULL); +static A9_COMP_DIV(nna, NNA_CLK_CTRL, 0, 7); +static A9_COMP_GATE(nna, NNA_CLK_CTRL, 8, 0); + +/* Channel 5 and 6 are unconnected. */ +static u32 a9_usb_250m_parents_val_table[] = { 0, 1, 2, 3, 4, 7 }; +static const struct clk_parent_data a9_usb_250m_parents[] = { + { .fw_name = "fdiv4", }, + { .fw_name = "fdiv3", }, + { .fw_name = "fdiv5", }, + { .fw_name = "fdiv2", }, + { .fw_name = "fdiv7", }, + { .fw_name = "fdiv2p5", } +}; + +static A9_COMP_SEL(usb_250m, USB_CLK_CTRL, 9, 0x7, a9_usb_250m_parents, + a9_usb_250m_parents_val_table); +static A9_COMP_DIV(usb_250m, USB_CLK_CTRL, 0, 7); +static A9_COMP_GATE(usb_250m, USB_CLK_CTRL, 8, 0); + +static const struct clk_parent_data a9_usb_48m_pre_parents[] = { + { .fw_name = "fdiv4", }, + { .fw_name = "fdiv3", }, + { .fw_name = "fdiv5", }, + { .fw_name = "fdiv2", }, + { .fw_name = "fdiv7", }, + { .fw_name = "fdiv2p5", } +}; + +static A9_COMP_SEL(usb_48m_pre, USB_CLK_CTRL, 25, 0x7, a9_usb_48m_pre_parents, + NULL); +static A9_COMP_DIV(usb_48m_pre, USB_CLK_CTRL, 16, 7); +static A9_COMP_GATE(usb_48m_pre, USB_CLK_CTRL, 24, 0); + +static const struct clk_parent_data a9_pcie_tl_parents[] = { + { .fw_name = "fdiv4", }, + { .fw_name = "fdiv3", }, + { .fw_name = "fdiv5", }, + { .fw_name = "fdiv2", }, + { .fw_name = "fdiv2p5", }, + { .fw_name = "gp0", }, + { .fw_name = "sys", }, + { .fw_name = "xtal", } +}; + +static A9_COMP_SEL(pcie_tl, PCIE_TL_CLK_CTRL, 9, 0x7, a9_pcie_tl_parents, + NULL); +static A9_COMP_DIV(pcie_tl, PCIE_TL_CLK_CTRL, 0, 7); +static A9_COMP_GATE(pcie_tl, PCIE_TL_CLK_CTRL, 8, 0); + +static A9_COMP_SEL(pcie1_tl, PCIE_TL_CLK_CTRL, 25, 0x7, a9_pcie_tl_parents, + NULL); +static A9_COMP_DIV(pcie1_tl, PCIE_TL_CLK_CTRL, 16, 7); +static A9_COMP_GATE(pcie1_tl, PCIE_TL_CLK_CTRL, 24, 0); + +static const struct clk_parent_data a9_cmpr_parents[] = { + { .fw_name = "xtal", }, + { .fw_name = "fdiv2p5", }, + { .fw_name = "fdiv3", }, + { .fw_name = "fdiv4", }, + { .fw_name = "fdiv5", }, + { .fw_name = "fdiv7", }, + { .fw_name = "hifi0", }, + { .fw_name = "gp1", } +}; + +static A9_COMP_SEL(cmpr, CMPR_CLK_CTRL, 25, 0x7, a9_cmpr_parents, NULL); +static A9_COMP_DIV(cmpr, CMPR_CLK_CTRL, 16, 7); +static A9_COMP_GATE(cmpr, CMPR_CLK_CTRL, 24, 0); + +static const struct clk_parent_data a9_dewarpa_parents[] = { + { .fw_name = "fdiv2p5", }, + { .fw_name = "fdiv3", }, + { .fw_name = "fdiv4", }, + { .fw_name = "fdiv5", }, + { .fw_name = "fdiv7", }, + { .fw_name = "gp0", }, + { .fw_name = "hifi0", }, + { .fw_name = "gp1", } +}; + +static A9_COMP_SEL(dewarpa, DEWARP_CLK_CTRL, 9, 0x7, a9_dewarpa_parents, NULL); +static A9_COMP_DIV(dewarpa, DEWARP_CLK_CTRL, 0, 7); +static A9_COMP_GATE(dewarpa, DEWARP_CLK_CTRL, 8, 0); + +static const struct clk_parent_data a9_sc_parents[] = { + { .fw_name = "fdiv2", }, + { .fw_name = "fdiv3", }, + { .fw_name = "fdiv5", }, + { .fw_name = "xtal", } +}; + +static A9_COMP_SEL(sc_pre, SC_CLK_CTRL, 9, 0x7, a9_sc_parents, NULL); +static A9_COMP_DIV(sc_pre, SC_CLK_CTRL, 0, 8); +static A9_COMP_GATE(sc_pre, SC_CLK_CTRL, 8, 0); + +static struct clk_regmap a9_sc = { + .data = &(struct clk_regmap_div_data) { + .offset = SC_CLK_CTRL, + .shift = 16, + .width = 4, + }, + .hw.init = &(struct clk_init_data) { + .name = "sc", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &a9_sc_pre.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static const struct clk_parent_data a9_dptx_apb2_parents[] = { + { .fw_name = "xtal", }, + { .fw_name = "sys", }, + { .fw_name = "fdiv4", }, + { .fw_name = "fdiv5", } +}; + +static A9_COMP_SEL(dptx_apb2, DPTX_CLK_CTRL, 9, 0x7, a9_dptx_apb2_parents, NULL); +static A9_COMP_DIV(dptx_apb2, DPTX_CLK_CTRL, 0, 7); +static A9_COMP_GATE(dptx_apb2, DPTX_CLK_CTRL, 8, 0); + +static const struct clk_parent_data a9_dptx_aud_parents[] = { + { .fw_name = "xtal", }, + { .fw_name = "sys", }, + { .fw_name = "fdiv3", }, + { .fw_name = "fdiv4", } +}; + +static A9_COMP_SEL(dptx_aud, DPTX_CLK_CTRL, 25, 0x7, a9_dptx_aud_parents, NULL); +static A9_COMP_DIV(dptx_aud, DPTX_CLK_CTRL, 16, 7); +static A9_COMP_GATE(dptx_aud, DPTX_CLK_CTRL, 24, 0); + +static const struct clk_parent_data a9_isp_parents[] = { + { .fw_name = "fdiv2p5", }, + { .fw_name = "fdiv3", }, + { .fw_name = "fdiv4", }, + { .fw_name = "fdiv5", }, + { .fw_name = "gp0", }, + { .fw_name = "hifi0", }, + { .fw_name = "fdiv2", }, + { .fw_name = "xtal", } +}; + +static A9_COMP_SEL(isp, ISP_CLK_CTRL, 9, 0x7, a9_isp_parents, NULL); +static A9_COMP_DIV(isp, ISP_CLK_CTRL, 0, 7); +static A9_COMP_GATE(isp, ISP_CLK_CTRL, 8, 0); + +static const struct clk_parent_data a9_cve_vge_parents[] = { + { .fw_name = "xtal", }, + { .fw_name = "fdiv2p5", }, + { .fw_name = "fdiv3", }, + { .fw_name = "fdiv4", }, + { .fw_name = "hifi0", }, + { .fw_name = "fdiv5", }, + { .fw_name = "gp0", }, + { .fw_name = "rtc", } +}; + +static A9_COMP_SEL(cve, CVE_CLK_CTRL, 9, 0x7, a9_cve_vge_parents, NULL); +static A9_COMP_DIV(cve, CVE_CLK_CTRL, 0, 7); +static A9_COMP_GATE(cve, CVE_CLK_CTRL, 8, 0); + +static A9_COMP_SEL(vge, CVE_CLK_CTRL, 25, 0x7, a9_cve_vge_parents, NULL); +static A9_COMP_DIV(vge, CVE_CLK_CTRL, 16, 7); +static A9_COMP_GATE(vge, CVE_CLK_CTRL, 24, 0); + +static const struct clk_parent_data a9_pp_parents[] = { + { .fw_name = "fdiv4", }, + { .fw_name = "fdiv3", }, + { .fw_name = "fdiv5", }, + { .fw_name = "fdiv2", }, + { .fw_name = "fdiv2p5", }, + { .fw_name = "gp0", }, + { .fw_name = "sys", }, + { .fw_name = "xtal", } +}; + +static A9_COMP_SEL(pp, PP_CLK_CTRL, 9, 0x7, a9_pp_parents, NULL); +static A9_COMP_DIV(pp, PP_CLK_CTRL, 0, 6); +static A9_COMP_GATE(pp, PP_CLK_CTRL, 8, 0); + +/* Channel 6 is unconnected. */ +static u32 a9_glb_parents_val_table[] = { 0, 1, 2, 3, 4, 5, 7 }; +static struct clk_regmap a9_dspa; + +static const struct clk_parent_data a9_glb_parents[] = { + { .fw_name = "xtal", }, + { .hw = &a9_dspa.hw }, + { .fw_name = "fdiv3", }, + { .fw_name = "fdiv4", }, + { .fw_name = "fdiv5", }, + { .hw = &a9_isp.hw }, + { .fw_name = "rtc", } +}; + +static A9_COMP_SEL(glb, GLB_CLK_CTRL, 9, 0x7, a9_glb_parents, + a9_glb_parents_val_table); +static A9_COMP_DIV(glb, GLB_CLK_CTRL, 0, 7); +static A9_COMP_GATE(glb, GLB_CLK_CTRL, 8, 0); + +static struct clk_regmap a9_usb_48m_dualdiv_in = { + .data = &(struct clk_regmap_gate_data) { + .offset = USB_CLK_CTRL, + .bit_idx = 31, + }, + .hw.init = &(struct clk_init_data) { + .name = "usb_48m_dualdiv_in", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &a9_usb_48m_pre.hw + }, + .num_parents = 1, + }, +}; + +static const struct meson_clk_dualdiv_param a9_usb_48m_dualdiv_div_table[] = { + { 733, 732, 8, 11, 1 }, + { /* sentinel */ } +}; + +static struct clk_regmap a9_usb_48m_dualdiv_div = { + .data = &(struct meson_clk_dualdiv_data) { + .n1 = { + .reg_off = USB_CLK_CTRL0, + .shift = 0, + .width = 12, + }, + .n2 = { + .reg_off = USB_CLK_CTRL0, + .shift = 12, + .width = 12, + }, + .m1 = { + .reg_off = USB_CLK_CTRL1, + .shift = 0, + .width = 12, + }, + .m2 = { + .reg_off = USB_CLK_CTRL1, + .shift = 12, + .width = 12, + }, + .dual = { + .reg_off = USB_CLK_CTRL0, + .shift = 28, + .width = 1, + }, + .table = a9_usb_48m_dualdiv_div_table, + }, + .hw.init = &(struct clk_init_data) { + .name = "usb_48m_dualdiv_div", + .ops = &meson_clk_dualdiv_ops, + .parent_hws = (const struct clk_hw *[]) { + &a9_usb_48m_dualdiv_in.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap a9_usb_48m_dualdiv_sel = { + .data = &(struct clk_regmap_mux_data) { + .offset = USB_CLK_CTRL1, + .mask = 0x1, + .shift = 24, + }, + .hw.init = &(struct clk_init_data) { + .name = "usb_48m_dualdiv_sel", + .ops = &clk_regmap_mux_ops, + .parent_hws = (const struct clk_hw *[]) { + &a9_usb_48m_dualdiv_in.hw, + &a9_usb_48m_dualdiv_div.hw, + }, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap a9_usb_48m_dualdiv = { + .data = &(struct clk_regmap_gate_data) { + .offset = USB_CLK_CTRL0, + .bit_idx = 30, + }, + .hw.init = &(struct clk_init_data) { + .name = "usb_48m_dualdiv", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &a9_usb_48m_dualdiv_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap a9_usb_48m = { + .data = &(struct clk_regmap_mux_data) { + .offset = USB_CLK_CTRL1, + .mask = 0x3, + .shift = 30, + }, + .hw.init = &(struct clk_init_data) { + .name = "usb_48m", + .ops = &clk_regmap_mux_ops, + .parent_hws = (const struct clk_hw *[]) { + &a9_usb_48m_pre.hw, + &a9_usb_48m_dualdiv.hw, + }, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static const struct clk_parent_data a9_can_pe_parents[] = { + { .fw_name = "sys", }, + { .fw_name = "xtal", }, + { .fw_name = "usb2drd", }, + { .fw_name = "fdiv5", } +}; + +static A9_COMP_SEL(can_pe, CAN_CLK_CTRL, 9, 0x7, a9_can_pe_parents, NULL); +static A9_COMP_DIV(can_pe, CAN_CLK_CTRL, 0, 7); +static A9_COMP_GATE(can_pe, CAN_CLK_CTRL, 8, 0); + +static A9_COMP_SEL(can1_pe, CAN_CLK_CTRL, 25, 0x7, a9_can_pe_parents, NULL); +static A9_COMP_DIV(can1_pe, CAN_CLK_CTRL, 16, 7); +static A9_COMP_GATE(can1_pe, CAN_CLK_CTRL, 24, 0); + +static const struct clk_parent_data a9_can_filter_parents[] = { + { .fw_name = "sys", }, + { .fw_name = "xtal", }, + { .fw_name = "fdiv4", }, + { .fw_name = "fdiv5", } +}; + +static A9_COMP_SEL(can_filter, CAN_CLK_CTRL1, 9, 0x7, a9_can_filter_parents, + NULL); +static A9_COMP_DIV(can_filter, CAN_CLK_CTRL1, 0, 7); +static A9_COMP_GATE(can_filter, CAN_CLK_CTRL1, 8, 0); + +static A9_COMP_SEL(can1_filter, CAN_CLK_CTRL1, 25, 0x7, a9_can_filter_parents, + NULL); +static A9_COMP_DIV(can1_filter, CAN_CLK_CTRL1, 16, 7); +static A9_COMP_GATE(can1_filter, CAN_CLK_CTRL1, 24, 0); + +static const struct clk_parent_data a9_i3c_parents[] = { + { .fw_name = "sys", }, + { .fw_name = "xtal", }, + { .fw_name = "fdiv5", } +}; + +static A9_COMP_SEL(i3c, I3C_CLK_CTRL, 9, 0x7, a9_i3c_parents, NULL); +static A9_COMP_DIV(i3c, I3C_CLK_CTRL, 0, 8); +static A9_COMP_GATE(i3c, I3C_CLK_CTRL, 8, 0); + +static struct clk_regmap a9_ts_div = { + .data = &(struct clk_regmap_div_data) { + .offset = TS_CLK_CTRL, + .shift = 0, + .width = 8, + }, + .hw.init = &(struct clk_init_data) { + .name = "ts_div", + .ops = &clk_regmap_divider_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap a9_ts = { + .data = &(struct clk_regmap_gate_data) { + .offset = TS_CLK_CTRL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data) { + .name = "ts", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &a9_ts_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_fixed_factor a9_eth_125m_div = { + .mult = 1, + .div = 8, + .hw.init = &(struct clk_init_data) { + .name = "eth_125m_div", + .ops = &clk_fixed_factor_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "fdiv2", + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap a9_eth_125m = { + .data = &(struct clk_regmap_gate_data) { + .offset = ETH_CLK_CTRL, + .bit_idx = 7, + }, + .hw.init = &(struct clk_init_data) { + .name = "eth_125m", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &a9_eth_125m_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +/* + * Channel 1, 2, 3, 4, 5 and 6 are unconnected, + * ext_rmii connects external PAD. + */ +static u32 a9_eth_rmii_parents_val_table[] = { 0, 7 }; +static const struct clk_parent_data a9_eth_rmii_parents[] = { + { .fw_name = "fdiv2", }, + { .fw_name = "ext_rmii", } +}; + +static struct clk_regmap a9_eth_rmii_sel = { + .data = &(struct clk_regmap_mux_data) { + .offset = ETH_CLK_CTRL, + .mask = 0x7, + .shift = 9, + .table = a9_eth_rmii_parents_val_table, + }, + .hw.init = &(struct clk_init_data){ + .name = "eth_rmii_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = a9_eth_rmii_parents, + .num_parents = ARRAY_SIZE(a9_eth_rmii_parents), + .flags = CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_regmap a9_eth_rmii_div = { + .data = &(struct clk_regmap_div_data) { + .offset = ETH_CLK_CTRL, + .shift = 0, + .width = 7, + }, + .hw.init = &(struct clk_init_data){ + .name = "eth_rmii_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &a9_eth_rmii_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap a9_eth_rmii = { + .data = &(struct clk_regmap_gate_data) { + .offset = ETH_CLK_CTRL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "eth_rmii", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &a9_eth_rmii_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +/* + * Channel 3(ddr_dpll_pt_clk) is manged by the DDR module; + * channel 12(msr_clk) is manged by clock measures module. + * channel 16(audio_dac1_clk) is manged by audio module. + * Channel 10, 11, 13, 14 are not connected. + */ +static u32 a9_gen_parents_val_table[] = { 0, 1, 2, 4, 5, 6, 7, 8, 9, 15, 17, 18, + 19, 20, 21, 22, 23, 24, 25, 26}; +static struct clk_regmap a9_vid_pll; + +static const struct clk_parent_data a9_gen_parents[] = { + { .fw_name = "xtal" }, + { .fw_name = "rtc" }, + { .fw_name = "sysplldiv16" }, + { .hw = &a9_vid_pll.hw }, + { .fw_name = "gp0" }, + { .fw_name = "hifi1" }, + { .fw_name = "hifi0" }, + { .fw_name = "gp1" }, + { .fw_name = "gp2" }, + { .fw_name = "dsudiv16" }, + { .fw_name = "cpudiv16" }, + { .fw_name = "a78div16" }, + { .fw_name = "fdiv2" }, + { .fw_name = "fdiv2p5" }, + { .fw_name = "fdiv3" }, + { .fw_name = "fdiv4" }, + { .fw_name = "fdiv5" }, + { .fw_name = "fdiv7" }, + { .fw_name = "mclk0" }, + { .fw_name = "mclk1" } +}; + +static A9_COMP_SEL(gen, GEN_CLK_CTRL, 12, 0x1f, a9_gen_parents, + a9_gen_parents_val_table); +static A9_COMP_DIV(gen, GEN_CLK_CTRL, 0, 12); +static A9_COMP_GATE(gen, GEN_CLK_CTRL, 11, 0); + +static struct clk_regmap a9_24m_in = { + .data = &(struct clk_regmap_gate_data) { + .offset = CLK12_24_CTRL, + .bit_idx = 11, + }, + .hw.init = &(struct clk_init_data) { + .name = "24m_in", + .ops = &clk_regmap_gate_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap a9_12_24m = { + .data = &(struct clk_regmap_div_data) { + .offset = CLK12_24_CTRL, + .shift = 10, + .width = 1, + }, + .hw.init = &(struct clk_init_data) { + .name = "12_24m", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &a9_24m_in.hw + }, + .num_parents = 1, + }, +}; + +static const struct clk_parent_data a9_mali_parents[] = { + { .fw_name = "xtal", }, + { .fw_name = "gp1", }, + { .fw_name = "fdiv2", }, + { .fw_name = "fdiv2p5", }, + { .fw_name = "fdiv3", }, + { .fw_name = "fdiv4", }, + { .fw_name = "fdiv5", }, + { .fw_name = "fdiv7", } +}; + +static A9_COMP_SEL(mali_0, MALI_CLK_CTRL, 9, 0x7, a9_mali_parents, NULL); +static A9_COMP_DIV(mali_0, MALI_CLK_CTRL, 0, 7); +static A9_COMP_GATE(mali_0, MALI_CLK_CTRL, 8, CLK_SET_RATE_GATE); + +static A9_COMP_SEL(mali_1, MALI_CLK_CTRL, 25, 0x7, a9_mali_parents, NULL); +static A9_COMP_DIV(mali_1, MALI_CLK_CTRL, 16, 7); +static A9_COMP_GATE(mali_1, MALI_CLK_CTRL, 24, CLK_SET_RATE_GATE); + +static struct clk_regmap a9_mali = { + .data = &(struct clk_regmap_mux_data){ + .offset = MALI_CLK_CTRL, + .mask = 0x1, + .shift = 31, + }, + .hw.init = &(struct clk_init_data){ + .name = "mali", + .ops = &clk_regmap_mux_ops, + .parent_hws = (const struct clk_hw *[]) { + &a9_mali_0.hw, + &a9_mali_1.hw + }, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static A9_COMP_SEL(mali_stack_0, MALI_STACK_CLK_CTRL, 9, 0x7, a9_mali_parents, + NULL); +static A9_COMP_DIV(mali_stack_0, MALI_STACK_CLK_CTRL, 0, 7); +static A9_COMP_GATE(mali_stack_0, MALI_STACK_CLK_CTRL, 8, CLK_SET_RATE_GATE); + +static A9_COMP_SEL(mali_stack_1, MALI_STACK_CLK_CTRL, 25, 0x7, a9_mali_parents, + NULL); +static A9_COMP_DIV(mali_stack_1, MALI_STACK_CLK_CTRL, 16, 7); +static A9_COMP_GATE(mali_stack_1, MALI_STACK_CLK_CTRL, 24, CLK_SET_RATE_GATE); + +static struct clk_regmap a9_mali_stack = { + .data = &(struct clk_regmap_mux_data){ + .offset = MALI_STACK_CLK_CTRL, + .mask = 0x1, + .shift = 31, + }, + .hw.init = &(struct clk_init_data){ + .name = "mali_stack", + .ops = &clk_regmap_mux_ops, + .parent_hws = (const struct clk_hw *[]) { + &a9_mali_stack_0.hw, + &a9_mali_stack_1.hw + }, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static const struct clk_parent_data a9_dspa_parents[] = { + { .fw_name = "xtal", }, + { .fw_name = "fdiv2p5", }, + { .fw_name = "fdiv3", }, + { .fw_name = "fdiv5", }, + { .fw_name = "gp2", }, + { .fw_name = "fdiv4", }, + { .fw_name = "hifi0", }, + { .fw_name = "rtc", } +}; + +static A9_COMP_SEL(dspa_0, DSPA_CLK_CTRL, 9, 0x7, a9_dspa_parents, NULL); +static A9_COMP_DIV(dspa_0, DSPA_CLK_CTRL, 0, 7); +static A9_COMP_GATE(dspa_0, DSPA_CLK_CTRL, 8, CLK_SET_RATE_GATE); + +static A9_COMP_SEL(dspa_1, DSPA_CLK_CTRL, 25, 0x7, a9_dspa_parents, NULL); +static A9_COMP_DIV(dspa_1, DSPA_CLK_CTRL, 16, 7); +static A9_COMP_GATE(dspa_1, DSPA_CLK_CTRL, 24, CLK_SET_RATE_GATE); + +static struct clk_regmap a9_dspa = { + .data = &(struct clk_regmap_mux_data){ + .offset = DSPA_CLK_CTRL, + .mask = 0x1, + .shift = 31, + }, + .hw.init = &(struct clk_init_data){ + .name = "dspa", + .ops = &clk_regmap_mux_ops, + .parent_hws = (const struct clk_hw *[]) { + &a9_dspa_0.hw, + &a9_dspa_1.hw + }, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static const struct clk_parent_data a9_hevcf_parents[] = { + { .fw_name = "fdiv2p5", }, + { .fw_name = "fdiv3", }, + { .fw_name = "fdiv4", }, + { .fw_name = "fdiv5", }, + { .fw_name = "fdiv7", }, + { .fw_name = "hifi0", }, + { .fw_name = "gp1", }, + { .fw_name = "xtal", } +}; + +static A9_COMP_SEL(hevcf_0, HEVCF_CLK_CTRL, 9, 0x7, a9_hevcf_parents, NULL); +static A9_COMP_DIV(hevcf_0, HEVCF_CLK_CTRL, 0, 7); +static A9_COMP_GATE(hevcf_0, HEVCF_CLK_CTRL, 8, CLK_SET_RATE_GATE); + +static A9_COMP_SEL(hevcf_1, HEVCF_CLK_CTRL, 25, 0x7, a9_hevcf_parents, NULL); +static A9_COMP_DIV(hevcf_1, HEVCF_CLK_CTRL, 16, 7); +static A9_COMP_GATE(hevcf_1, HEVCF_CLK_CTRL, 24, CLK_SET_RATE_GATE); + +static struct clk_regmap a9_hevcf = { + .data = &(struct clk_regmap_mux_data){ + .offset = HEVCF_CLK_CTRL, + .mask = 0x1, + .shift = 31, + }, + .hw.init = &(struct clk_init_data){ + .name = "hevcf", + .ops = &clk_regmap_mux_ops, + .parent_hws = (const struct clk_hw *[]) { + &a9_hevcf_0.hw, + &a9_hevcf_1.hw + }, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static const struct clk_parent_data a9_hcodec_parents[] = { + { .fw_name = "fdiv2p5", }, + { .fw_name = "fdiv3", }, + { .fw_name = "fdiv4", }, + { .fw_name = "fdiv5", }, + { .fw_name = "fdiv7", }, + { .fw_name = "hifi0", }, + { .fw_name = "gp0", }, + { .fw_name = "xtal", } +}; + +static A9_COMP_SEL(hcodec_0, HCODEC_CLK_CTRL, 9, 0x7, a9_hcodec_parents, NULL); +static A9_COMP_DIV(hcodec_0, HCODEC_CLK_CTRL, 0, 7); +static A9_COMP_GATE(hcodec_0, HCODEC_CLK_CTRL, 8, CLK_SET_RATE_GATE); + +static A9_COMP_SEL(hcodec_1, HCODEC_CLK_CTRL, 25, 0x7, a9_hcodec_parents, NULL); +static A9_COMP_DIV(hcodec_1, HCODEC_CLK_CTRL, 16, 7); +static A9_COMP_GATE(hcodec_1, HCODEC_CLK_CTRL, 24, CLK_SET_RATE_GATE); + +static struct clk_regmap a9_hcodec = { + .data = &(struct clk_regmap_mux_data){ + .offset = HCODEC_CLK_CTRL, + .mask = 0x1, + .shift = 31, + }, + .hw.init = &(struct clk_init_data){ + .name = "hcodec", + .ops = &clk_regmap_mux_ops, + .parent_hws = (const struct clk_hw *[]) { + &a9_hcodec_0.hw, + &a9_hcodec_1.hw + }, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static const struct clk_parent_data a9_vpu_parents[] = { + { .fw_name = "fdiv3", }, + { .fw_name = "fdiv4", }, + { .fw_name = "fdiv5", }, + { .fw_name = "vid1", }, + { .fw_name = "fdiv2", }, + { .hw = &a9_vid_pll.hw }, + { .fw_name = "vid2", }, + { .fw_name = "gp1", } +}; + +static A9_COMP_SEL(vpu_0, VPU_CLK_CTRL, 9, 0x7, a9_vpu_parents, NULL); +static A9_COMP_DIV(vpu_0, VPU_CLK_CTRL, 0, 7); +static A9_COMP_GATE(vpu_0, VPU_CLK_CTRL, 8, CLK_SET_RATE_GATE); + +static A9_COMP_SEL(vpu_1, VPU_CLK_CTRL, 25, 0x7, a9_vpu_parents, NULL); +static A9_COMP_DIV(vpu_1, VPU_CLK_CTRL, 16, 7); +static A9_COMP_GATE(vpu_1, VPU_CLK_CTRL, 24, CLK_SET_RATE_GATE); + +static struct clk_regmap a9_vpu = { + .data = &(struct clk_regmap_mux_data){ + .offset = VPU_CLK_CTRL, + .mask = 0x1, + .shift = 31, + }, + .hw.init = &(struct clk_init_data){ + .name = "vpu", + .ops = &clk_regmap_mux_ops, + .parent_hws = (const struct clk_hw *[]) { + &a9_vpu_0.hw, + &a9_vpu_1.hw + }, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static const struct clk_parent_data a9_vapb_parents[] = { + { .fw_name = "fdiv4", }, + { .fw_name = "fdiv3", }, + { .fw_name = "fdiv5", }, + { .fw_name = "fdiv7", }, + { .fw_name = "fdiv2", }, + { .hw = &a9_vid_pll.hw }, + { .fw_name = "hifi0", }, + { .fw_name = "fdiv2p5", } +}; + +static A9_COMP_SEL(vapb_0, VAPB_CLK_CTRL, 9, 0x7, a9_vapb_parents, NULL); +static A9_COMP_DIV(vapb_0, VAPB_CLK_CTRL, 0, 7); +static A9_COMP_GATE(vapb_0, VAPB_CLK_CTRL, 8, CLK_SET_RATE_GATE); + +static A9_COMP_SEL(vapb_1, VAPB_CLK_CTRL, 25, 0x7, a9_vapb_parents, NULL); +static A9_COMP_DIV(vapb_1, VAPB_CLK_CTRL, 16, 7); +static A9_COMP_GATE(vapb_1, VAPB_CLK_CTRL, 24, CLK_SET_RATE_GATE); + +static struct clk_regmap a9_vapb = { + .data = &(struct clk_regmap_mux_data){ + .offset = VAPB_CLK_CTRL, + .mask = 0x1, + .shift = 31, + }, + .hw.init = &(struct clk_init_data){ + .name = "vapb", + .ops = &clk_regmap_mux_ops, + .parent_hws = (const struct clk_hw *[]) { + &a9_vapb_0.hw, + &a9_vapb_1.hw + }, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap a9_ge2d = { + .data = &(struct clk_regmap_gate_data) { + .offset = VAPB_CLK_CTRL, + .bit_idx = 30, + }, + .hw.init = &(struct clk_init_data) { + .name = "ge2d", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &a9_vapb.hw, + }, + .num_parents = 1, + }, +}; + +static const struct clk_parent_data a9_vpu_clkb_tmp_parents[] = { + { .hw = &a9_vpu.hw }, + { .fw_name = "fdiv4", }, + { .fw_name = "fdiv5", }, + { .fw_name = "fdiv7", } +}; + +static A9_COMP_SEL(vpu_clkb_tmp, VPU_CLKB_CTRL, 25, 0x7, a9_vpu_clkb_tmp_parents, + NULL); +static A9_COMP_DIV(vpu_clkb_tmp, VPU_CLKB_CTRL, 16, 4); +static A9_COMP_GATE(vpu_clkb_tmp, VPU_CLKB_CTRL, 24, 0); + +static struct clk_regmap a9_vpu_clkb_div = { + .data = &(struct clk_regmap_div_data) { + .offset = VPU_CLKB_CTRL, + .shift = 0, + .width = 8, + }, + .hw.init = &(struct clk_init_data) { + .name = "vpu_clkb_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &a9_vpu_clkb_tmp.hw, + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap a9_vpu_clkb = { + .data = &(struct clk_regmap_gate_data) { + .offset = VPU_CLKB_CTRL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data) { + .name = "vpu_clkb", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &a9_vpu_clkb_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static const struct clk_parent_data a9_hdmi_parents[] = { + { .fw_name = "xtal", }, + { .fw_name = "fdiv4", }, + { .fw_name = "fdiv3", }, + { .fw_name = "fdiv5", } +}; + +static A9_COMP_SEL(hdmitx_sys, HDMI_CLK_CTRL, 9, 0x7, a9_hdmi_parents, NULL); +static A9_COMP_DIV(hdmitx_sys, HDMI_CLK_CTRL, 0, 7); +static A9_COMP_GATE(hdmitx_sys, HDMI_CLK_CTRL, 8, 0); + +static A9_COMP_SEL(hdmitx_prif, HTX_CLK_CTRL, 9, 0x7, a9_hdmi_parents, NULL); +static A9_COMP_DIV(hdmitx_prif, HTX_CLK_CTRL, 0, 7); +static A9_COMP_GATE(hdmitx_prif, HTX_CLK_CTRL, 8, 0); + +static A9_COMP_SEL(hdmitx_200m, HTX_CLK_CTRL, 25, 0x7, a9_hdmi_parents, NULL); +static A9_COMP_DIV(hdmitx_200m, HTX_CLK_CTRL, 16, 7); +static A9_COMP_GATE(hdmitx_200m, HTX_CLK_CTRL, 24, 0); + +static A9_COMP_SEL(hdmitx_aud, HTX_CLK_CTRL1, 9, 0x7, a9_hdmi_parents, NULL); +static A9_COMP_DIV(hdmitx_aud, HTX_CLK_CTRL1, 0, 7); +static A9_COMP_GATE(hdmitx_aud, HTX_CLK_CTRL1, 8, 0); + +static A9_COMP_SEL(hdmirx_5m, HRX_CLK_CTRL, 9, 0x7, a9_hdmi_parents, + NULL); +static A9_COMP_DIV(hdmirx_5m, HRX_CLK_CTRL, 0, 7); +static A9_COMP_GATE(hdmirx_5m, HRX_CLK_CTRL, 8, 0); + +static A9_COMP_SEL(hdmirx_2m, HRX_CLK_CTRL, 25, 0x7, a9_hdmi_parents, + NULL); +static A9_COMP_DIV(hdmirx_2m, HRX_CLK_CTRL, 16, 7); +static A9_COMP_GATE(hdmirx_2m, HRX_CLK_CTRL, 24, 0); + +static A9_COMP_SEL(hdmirx_cfg, HRX_CLK_CTRL1, 9, 0x7, a9_hdmi_parents, + NULL); +static A9_COMP_DIV(hdmirx_cfg, HRX_CLK_CTRL1, 0, 7); +static A9_COMP_GATE(hdmirx_cfg, HRX_CLK_CTRL1, 8, 0); + +static A9_COMP_SEL(hdmirx_hdcp2x, HRX_CLK_CTRL1, 25, 0x7, a9_hdmi_parents, + NULL); +static A9_COMP_DIV(hdmirx_hdcp2x, HRX_CLK_CTRL1, 16, 7); +static A9_COMP_GATE(hdmirx_hdcp2x, HRX_CLK_CTRL1, 24, 0); + +static A9_COMP_SEL(hdmirx_acr_ref, HRX_CLK_CTRL2, 25, 0x7, a9_hdmi_parents, + NULL); +static A9_COMP_DIV(hdmirx_acr_ref, HRX_CLK_CTRL2, 16, 7); +static A9_COMP_GATE(hdmirx_acr_ref, HRX_CLK_CTRL2, 24, 0); + +static A9_COMP_SEL(hdmirx_meter, HRX_CLK_CTRL3, 9, 0x7, a9_hdmi_parents, + NULL); +static A9_COMP_DIV(hdmirx_meter, HRX_CLK_CTRL3, 0, 7); +static A9_COMP_GATE(hdmirx_meter, HRX_CLK_CTRL3, 8, 0); + +static struct clk_regmap a9_enc, a9_enc1; + +static const struct clk_parent_data a9_vid_lock_parents[] = { + { .fw_name = "xtal", }, + { .hw = &a9_enc.hw }, + { .hw = &a9_enc1.hw } +}; + +static A9_COMP_SEL(vid_lock, VID_LOCK_CLK_CTRL, 9, 0x7, a9_vid_lock_parents, + NULL); +static A9_COMP_DIV(vid_lock, VID_LOCK_CLK_CTRL, 0, 7); +static A9_COMP_GATE(vid_lock, VID_LOCK_CLK_CTRL, 8, 0); + +static const struct clk_parent_data a9_vdin_meas_parents[] = { + { .fw_name = "xtal", }, + { .fw_name = "fdiv4", }, + { .fw_name = "fdiv3", }, + { .fw_name = "fdiv5", } +}; + +static A9_COMP_SEL(vdin_meas, VDIN_MEAS_CLK_CTRL, 9, 0x7, a9_vdin_meas_parents, + NULL); +static A9_COMP_DIV(vdin_meas, VDIN_MEAS_CLK_CTRL, 0, 7); +static A9_COMP_GATE(vdin_meas, VDIN_MEAS_CLK_CTRL, 8, 0); + +static struct clk_regmap a9_vid_pll_div = { + .data = &(struct meson_vid_pll_div_data){ + .val = { + .reg_off = VID_PLL_CLK_DIV, + .shift = 0, + .width = 15, + }, + .sel = { + .reg_off = VID_PLL_CLK_DIV, + .shift = 16, + .width = 2, + }, + }, + .hw.init = &(struct clk_init_data) { + .name = "vid_pll_div", + .ops = &meson_vid_pll_div_ro_ops, + .parent_data = (const struct clk_parent_data []) { + { .fw_name = "hdmiout2", } + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap a9_vid_pll_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = VID_PLL_CLK_DIV, + .mask = 0x1, + .shift = 18, + }, + .hw.init = &(struct clk_init_data){ + .name = "vid_pll_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = (const struct clk_parent_data []) { + { .hw = &a9_vid_pll_div.hw }, + { .fw_name = "hdmiout2", } + }, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap a9_vid_pll = { + .data = &(struct clk_regmap_gate_data){ + .offset = VID_PLL_CLK_DIV, + .bit_idx = 19, + }, + .hw.init = &(struct clk_init_data) { + .name = "vid_pll", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &a9_vid_pll_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap a9_vid_pll_vclk = { + .data = &(struct clk_regmap_mux_data){ + .offset = HDMI_CLK_CTRL, + .mask = 0x1, + .shift = 15, + }, + .hw.init = &(struct clk_init_data){ + .name = "vid_pll_vclk", + .ops = &clk_regmap_mux_ops, + .parent_data = (const struct clk_parent_data []) { + { .hw = &a9_vid_pll.hw }, + { .fw_name = "hdmipix", } + }, + .num_parents = 2, + }, +}; + +static const struct clk_parent_data a9_vclk_parents[] = { + { .hw = &a9_vid_pll_vclk.hw }, + { .fw_name = "pix0", }, + { .fw_name = "vid1", }, + { .fw_name = "pix1", }, + { .fw_name = "fdiv3", }, + { .fw_name = "fdiv4", }, + { .fw_name = "fdiv5", }, + { .fw_name = "vid2", } +}; + +static struct clk_regmap a9_vclk_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = VID_CLK_CTRL, + .mask = 0x7, + .shift = 16, + }, + .hw.init = &(struct clk_init_data){ + .name = "vclk_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = a9_vclk_parents, + .num_parents = ARRAY_SIZE(a9_vclk_parents), + }, +}; + +static struct clk_regmap a9_vclk_in = { + .data = &(struct clk_regmap_gate_data){ + .offset = VID_CLK_DIV, + .bit_idx = 16, + }, + .hw.init = &(struct clk_init_data) { + .name = "vclk_in", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { &a9_vclk_sel.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap a9_vclk_div = { + .data = &(struct clk_regmap_div_data){ + .offset = VID_CLK_DIV, + .shift = 0, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "vclk_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &a9_vclk_in.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap a9_vclk = { + .data = &(struct clk_regmap_gate_data){ + .offset = VID_CLK_CTRL, + .bit_idx = 19, + }, + .hw.init = &(struct clk_init_data) { + .name = "vclk", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { &a9_vclk_div.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap a9_vclk_div1_en = { + .data = &(struct clk_regmap_gate_data){ + .offset = VID_CLK_CTRL, + .bit_idx = 0, + }, + .hw.init = &(struct clk_init_data) { + .name = "vclk_div1_en", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { &a9_vclk.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap a9_vclk_div2_en = { + .data = &(struct clk_regmap_gate_data){ + .offset = VID_CLK_CTRL, + .bit_idx = 1, + }, + .hw.init = &(struct clk_init_data) { + .name = "vclk_div2_en", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { &a9_vclk.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_fixed_factor a9_vclk_div2 = { + .mult = 1, + .div = 2, + .hw.init = &(struct clk_init_data){ + .name = "vclk_div2", + .ops = &clk_fixed_factor_ops, + .parent_hws = (const struct clk_hw *[]) { + &a9_vclk_div2_en.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap a9_vclk_div4_en = { + .data = &(struct clk_regmap_gate_data){ + .offset = VID_CLK_CTRL, + .bit_idx = 2, + }, + .hw.init = &(struct clk_init_data) { + .name = "vclk_div4_en", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { &a9_vclk.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_fixed_factor a9_vclk_div4 = { + .mult = 1, + .div = 4, + .hw.init = &(struct clk_init_data){ + .name = "vclk_div4", + .ops = &clk_fixed_factor_ops, + .parent_hws = (const struct clk_hw *[]) { + &a9_vclk_div4_en.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap a9_vclk_div6_en = { + .data = &(struct clk_regmap_gate_data){ + .offset = VID_CLK_CTRL, + .bit_idx = 3, + }, + .hw.init = &(struct clk_init_data) { + .name = "vclk_div6_en", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { &a9_vclk.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_fixed_factor a9_vclk_div6 = { + .mult = 1, + .div = 6, + .hw.init = &(struct clk_init_data){ + .name = "vclk_div6", + .ops = &clk_fixed_factor_ops, + .parent_hws = (const struct clk_hw *[]) { + &a9_vclk_div6_en.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap a9_vclk_div12_en = { + .data = &(struct clk_regmap_gate_data){ + .offset = VID_CLK_CTRL, + .bit_idx = 4, + }, + .hw.init = &(struct clk_init_data) { + .name = "vclk_div12_en", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { &a9_vclk.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_fixed_factor a9_vclk_div12 = { + .mult = 1, + .div = 12, + .hw.init = &(struct clk_init_data){ + .name = "vclk_div12", + .ops = &clk_fixed_factor_ops, + .parent_hws = (const struct clk_hw *[]) { + &a9_vclk_div12_en.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap a9_vclk2_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = VIID_CLK_CTRL, + .mask = 0x7, + .shift = 16, + }, + .hw.init = &(struct clk_init_data){ + .name = "vclk2_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = a9_vclk_parents, + .num_parents = ARRAY_SIZE(a9_vclk_parents), + }, +}; + +static struct clk_regmap a9_vclk2_in = { + .data = &(struct clk_regmap_gate_data){ + .offset = VIID_CLK_DIV, + .bit_idx = 16, + }, + .hw.init = &(struct clk_init_data) { + .name = "vclk2_in", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { &a9_vclk2_sel.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap a9_vclk2_div = { + .data = &(struct clk_regmap_div_data){ + .offset = VIID_CLK_DIV, + .shift = 0, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "vclk2_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &a9_vclk2_in.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap a9_vclk2 = { + .data = &(struct clk_regmap_gate_data){ + .offset = VIID_CLK_CTRL, + .bit_idx = 19, + }, + .hw.init = &(struct clk_init_data) { + .name = "vclk2", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { &a9_vclk2_div.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap a9_vclk2_div1_en = { + .data = &(struct clk_regmap_gate_data){ + .offset = VIID_CLK_CTRL, + .bit_idx = 0, + }, + .hw.init = &(struct clk_init_data) { + .name = "vclk2_div1_en", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { &a9_vclk2.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap a9_vclk2_div2_en = { + .data = &(struct clk_regmap_gate_data){ + .offset = VIID_CLK_CTRL, + .bit_idx = 1, + }, + .hw.init = &(struct clk_init_data) { + .name = "vclk2_div2_en", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { &a9_vclk2.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_fixed_factor a9_vclk2_div2 = { + .mult = 1, + .div = 2, + .hw.init = &(struct clk_init_data){ + .name = "vclk2_div2", + .ops = &clk_fixed_factor_ops, + .parent_hws = (const struct clk_hw *[]) { + &a9_vclk2_div2_en.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap a9_vclk2_div4_en = { + .data = &(struct clk_regmap_gate_data){ + .offset = VIID_CLK_CTRL, + .bit_idx = 2, + }, + .hw.init = &(struct clk_init_data) { + .name = "vclk2_div4_en", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { &a9_vclk2.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_fixed_factor a9_vclk2_div4 = { + .mult = 1, + .div = 4, + .hw.init = &(struct clk_init_data){ + .name = "vclk2_div4", + .ops = &clk_fixed_factor_ops, + .parent_hws = (const struct clk_hw *[]) { + &a9_vclk2_div4_en.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap a9_vclk2_div6_en = { + .data = &(struct clk_regmap_gate_data){ + .offset = VIID_CLK_CTRL, + .bit_idx = 3, + }, + .hw.init = &(struct clk_init_data) { + .name = "vclk2_div6_en", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { &a9_vclk2.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_fixed_factor a9_vclk2_div6 = { + .mult = 1, + .div = 6, + .hw.init = &(struct clk_init_data){ + .name = "vclk2_div6", + .ops = &clk_fixed_factor_ops, + .parent_hws = (const struct clk_hw *[]) { + &a9_vclk2_div6_en.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap a9_vclk2_div12_en = { + .data = &(struct clk_regmap_gate_data){ + .offset = VIID_CLK_CTRL, + .bit_idx = 4, + }, + .hw.init = &(struct clk_init_data) { + .name = "vclk2_div12_en", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { &a9_vclk2.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_fixed_factor a9_vclk2_div12 = { + .mult = 1, + .div = 12, + .hw.init = &(struct clk_init_data){ + .name = "vclk2_div12", + .ops = &clk_fixed_factor_ops, + .parent_hws = (const struct clk_hw *[]) { + &a9_vclk2_div12_en.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +/* Channel 5, 6 and 7 are unconnected */ +static u32 a9_vid_parents_val_table[] = { 0, 1, 2, 3, 4, 8, 9, 10, 11, 12 }; +static const struct clk_hw *a9_vid_parents[] = { + &a9_vclk_div1_en.hw, + &a9_vclk_div2.hw, + &a9_vclk_div4.hw, + &a9_vclk_div6.hw, + &a9_vclk_div12.hw, + &a9_vclk2_div1_en.hw, + &a9_vclk2_div2.hw, + &a9_vclk2_div4.hw, + &a9_vclk2_div6.hw, + &a9_vclk2_div12.hw +}; + +static struct clk_regmap a9_vdac_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = VIID_CLK_DIV, + .mask = 0xf, + .shift = 28, + .table = a9_vid_parents_val_table, + }, + .hw.init = &(struct clk_init_data){ + .name = "vdac_sel", + .ops = &clk_regmap_mux_ops, + .parent_hws = a9_vid_parents, + .num_parents = ARRAY_SIZE(a9_vid_parents), + }, +}; + +static struct clk_regmap a9_vdac = { + .data = &(struct clk_regmap_gate_data){ + .offset = VID_CLK_CTRL2, + .bit_idx = 4, + }, + .hw.init = &(struct clk_init_data) { + .name = "vdac", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &a9_vdac_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap a9_enc_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = VIID_CLK_DIV, + .mask = 0xf, + .shift = 12, + .table = a9_vid_parents_val_table, + }, + .hw.init = &(struct clk_init_data){ + .name = "enc_sel", + .ops = &clk_regmap_mux_ops, + .parent_hws = a9_vid_parents, + .num_parents = ARRAY_SIZE(a9_vid_parents), + }, +}; + +static struct clk_regmap a9_enc = { + .data = &(struct clk_regmap_gate_data){ + .offset = VID_CLK_CTRL2, + .bit_idx = 10, + }, + .hw.init = &(struct clk_init_data) { + .name = "enc", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &a9_enc_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap a9_enc1_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = VIID_CLK_DIV, + .mask = 0xf, + .shift = 8, + .table = a9_vid_parents_val_table, + }, + .hw.init = &(struct clk_init_data){ + .name = "enc1_sel", + .ops = &clk_regmap_mux_ops, + .parent_hws = a9_vid_parents, + .num_parents = ARRAY_SIZE(a9_vid_parents), + }, +}; + +static struct clk_regmap a9_enc1 = { + .data = &(struct clk_regmap_gate_data){ + .offset = VID_CLK_CTRL2, + .bit_idx = 11, + }, + .hw.init = &(struct clk_init_data) { + .name = "enc1", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &a9_enc1_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap a9_hdmitx_pixel_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = HDMI_CLK_CTRL, + .mask = 0xf, + .shift = 16, + .table = a9_vid_parents_val_table, + }, + .hw.init = &(struct clk_init_data){ + .name = "hdmitx_pixel_sel", + .ops = &clk_regmap_mux_ops, + .parent_hws = a9_vid_parents, + .num_parents = ARRAY_SIZE(a9_vid_parents), + }, +}; + +static struct clk_regmap a9_hdmitx_pixel = { + .data = &(struct clk_regmap_gate_data){ + .offset = VID_CLK_CTRL2, + .bit_idx = 5, + }, + .hw.init = &(struct clk_init_data) { + .name = "hdmitx_pixel", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &a9_hdmitx_pixel_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap a9_hdmitx_fe_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = HDMI_CLK_CTRL, + .mask = 0xf, + .shift = 20, + .table = a9_vid_parents_val_table, + }, + .hw.init = &(struct clk_init_data){ + .name = "hdmitx_fe_sel", + .ops = &clk_regmap_mux_ops, + .parent_hws = a9_vid_parents, + .num_parents = ARRAY_SIZE(a9_vid_parents), + }, +}; + +static struct clk_regmap a9_hdmitx_fe = { + .data = &(struct clk_regmap_gate_data){ + .offset = VID_CLK_CTRL2, + .bit_idx = 9, + }, + .hw.init = &(struct clk_init_data) { + .name = "hdmitx_fe", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &a9_hdmitx_fe_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap a9_hdmitx1_pixel_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = HDMI_CLK_CTRL, + .mask = 0xf, + .shift = 24, + .table = a9_vid_parents_val_table, + }, + .hw.init = &(struct clk_init_data){ + .name = "hdmitx1_pixel_sel", + .ops = &clk_regmap_mux_ops, + .parent_hws = a9_vid_parents, + .num_parents = ARRAY_SIZE(a9_vid_parents), + }, +}; + +static struct clk_regmap a9_hdmitx1_pixel = { + .data = &(struct clk_regmap_gate_data){ + .offset = VID_CLK_CTRL2, + .bit_idx = 12, + }, + .hw.init = &(struct clk_init_data) { + .name = "hdmitx1_pixel", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &a9_hdmitx_pixel_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap a9_hdmitx1_fe_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = HDMI_CLK_CTRL, + .mask = 0xf, + .shift = 28, + .table = a9_vid_parents_val_table, + }, + .hw.init = &(struct clk_init_data){ + .name = "hdmitx1_fe_sel", + .ops = &clk_regmap_mux_ops, + .parent_hws = a9_vid_parents, + .num_parents = ARRAY_SIZE(a9_vid_parents), + }, +}; + +static struct clk_regmap a9_hdmitx1_fe = { + .data = &(struct clk_regmap_gate_data){ + .offset = VID_CLK_CTRL2, + .bit_idx = 13, + }, + .hw.init = &(struct clk_init_data) { + .name = "hdmitx1_fe", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &a9_hdmitx1_fe_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static const struct clk_parent_data a9_csi_phy_parents[] = { + { .fw_name = "fdiv2p5", }, + { .fw_name = "fdiv3", }, + { .fw_name = "fdiv4", }, + { .fw_name = "fdiv5", }, + { .fw_name = "gp0", }, + { .fw_name = "hifi0", }, + { .fw_name = "fdiv2", }, + { .fw_name = "xtal", } +}; + +static A9_COMP_SEL(csi_phy, MIPI_CSI_PHY_CLK_CTRL, 9, 0x7, + a9_csi_phy_parents, NULL); +static A9_COMP_DIV(csi_phy, MIPI_CSI_PHY_CLK_CTRL, 0, 7); +static A9_COMP_GATE(csi_phy, MIPI_CSI_PHY_CLK_CTRL, 8, 0); + +static const struct clk_parent_data a9_dsi_meas_parents[] = { + { .fw_name = "xtal", }, + { .fw_name = "fdiv4", }, + { .fw_name = "fdiv3", }, + { .fw_name = "fdiv5", }, + { .hw = &a9_vid_pll.hw }, + { .fw_name = "gp0", }, + { .fw_name = "vid1", }, + { .fw_name = "vid2", } +}; + +static A9_COMP_SEL(dsi_meas, DSI_MEAS_CLK_CTRL, 9, 0x7, + a9_dsi_meas_parents, NULL); +static A9_COMP_DIV(dsi_meas, DSI_MEAS_CLK_CTRL, 0, 7); +static A9_COMP_GATE(dsi_meas, DSI_MEAS_CLK_CTRL, 8, 0); + +static A9_COMP_SEL(dsi_b_meas, DSI_MEAS_CLK_CTRL, 25, 0x7, + a9_dsi_meas_parents, NULL); +static A9_COMP_DIV(dsi_b_meas, DSI_MEAS_CLK_CTRL, 16, 7); +static A9_COMP_GATE(dsi_b_meas, DSI_MEAS_CLK_CTRL, 24, 0); + +static struct clk_hw *a9_peripherals_hw_clks[] = { + [CLKID_SYS_AM_AXI] = &a9_sys_am_axi.hw, + [CLKID_SYS_DOS] = &a9_sys_dos.hw, + [CLKID_SYS_MIPI_DSI] = &a9_sys_mipi_dsi.hw, + [CLKID_SYS_ETH_PHY] = &a9_sys_eth_phy.hw, + [CLKID_SYS_AMFC] = &a9_sys_amfc.hw, + [CLKID_SYS_MALI] = &a9_sys_mali.hw, + [CLKID_SYS_NNA] = &a9_sys_nna.hw, + [CLKID_SYS_ETH_AXI] = &a9_sys_eth_axi.hw, + [CLKID_SYS_DP_APB] = &a9_sys_dp_apb.hw, + [CLKID_SYS_EDPTX_APB] = &a9_sys_edptx_apb.hw, + [CLKID_SYS_U3HSG] = &a9_sys_u3hsg.hw, + [CLKID_SYS_AUCPU] = &a9_sys_aucpu.hw, + [CLKID_SYS_GLB] = &a9_sys_glb.hw, + [CLKID_SYS_COMBO_DPHY_APB] = &a9_sys_combo_dphy_apb.hw, + [CLKID_SYS_HDMIRX_APB] = &a9_sys_hdmirx_apb.hw, + [CLKID_SYS_HDMIRX_PCLK] = &a9_sys_hdmirx_pclk.hw, + [CLKID_SYS_MIPI_DSI_PHY] = &a9_sys_mipi_dsi_phy.hw, + [CLKID_SYS_CAN0] = &a9_sys_can0.hw, + [CLKID_SYS_CAN1] = &a9_sys_can1.hw, + [CLKID_SYS_SD_EMMC_A] = &a9_sys_sd_emmc_a.hw, + [CLKID_SYS_SD_EMMC_B] = &a9_sys_sd_emmc_b.hw, + [CLKID_SYS_SD_EMMC_C] = &a9_sys_sd_emmc_c.hw, + [CLKID_SYS_SC] = &a9_sys_sc.hw, + [CLKID_SYS_ACODEC] = &a9_sys_acodec.hw, + [CLKID_SYS_MIPI_ISP] = &a9_sys_mipi_isp.hw, + [CLKID_SYS_MSR] = &a9_sys_msr.hw, + [CLKID_SYS_AUDIO] = &a9_sys_audio.hw, + [CLKID_SYS_MIPI_DSI_B] = &a9_sys_mipi_dsi_b.hw, + [CLKID_SYS_MIPI_DSI1_PHY] = &a9_sys_mipi_dsi1_phy.hw, + [CLKID_SYS_ETH] = &a9_sys_eth.hw, + [CLKID_SYS_ETH_1G_MAC] = &a9_sys_eth_1g_mac.hw, + [CLKID_SYS_UART_A] = &a9_sys_uart_a.hw, + [CLKID_SYS_UART_F] = &a9_sys_uart_f.hw, + [CLKID_SYS_TS_A55] = &a9_sys_ts_a55.hw, + [CLKID_SYS_ETH_1G_AXI] = &a9_sys_eth_1g_axi.hw, + [CLKID_SYS_TS_DOS] = &a9_sys_ts_dos.hw, + [CLKID_SYS_U3DRD_B] = &a9_sys_u3drd_b.hw, + [CLKID_SYS_TS_CORE] = &a9_sys_ts_core.hw, + [CLKID_SYS_TS_PLL] = &a9_sys_ts_pll.hw, + [CLKID_SYS_CSI_DIG_CLKIN] = &a9_sys_csi_dig_clkin.hw, + [CLKID_SYS_CVE] = &a9_sys_cve.hw, + [CLKID_SYS_GE2D] = &a9_sys_ge2d.hw, + [CLKID_SYS_SPISG] = &a9_sys_spisg.hw, + [CLKID_SYS_U3DRD_1] = &a9_sys_u3drd_1.hw, + [CLKID_SYS_U2H] = &a9_sys_u2h.hw, + [CLKID_SYS_PCIE_MAC_A] = &a9_sys_pcie_mac_a.hw, + [CLKID_SYS_U3DRD_A] = &a9_sys_u3drd_a.hw, + [CLKID_SYS_U2DRD] = &a9_sys_u2drd.hw, + [CLKID_SYS_PCIE_PHY] = &a9_sys_pcie_phy.hw, + [CLKID_SYS_PCIE_MAC_B] = &a9_sys_pcie_mac_b.hw, + [CLKID_SYS_PERIPH] = &a9_sys_periph.hw, + [CLKID_SYS_PIO] = &a9_sys_pio.hw, + [CLKID_SYS_I3C] = &a9_sys_i3c.hw, + [CLKID_SYS_I2C_M_E] = &a9_sys_i2c_m_e.hw, + [CLKID_SYS_I2C_M_F] = &a9_sys_i2c_m_f.hw, + [CLKID_SYS_HDMITX_APB] = &a9_sys_hdmitx_apb.hw, + [CLKID_SYS_I2C_M_I] = &a9_sys_i2c_m_i.hw, + [CLKID_SYS_I2C_M_G] = &a9_sys_i2c_m_g.hw, + [CLKID_SYS_I2C_M_H] = &a9_sys_i2c_m_h.hw, + [CLKID_SYS_HDMI20_AES] = &a9_sys_hdmi20_aes.hw, + [CLKID_SYS_CSI2_HOST] = &a9_sys_csi2_host.hw, + [CLKID_SYS_CSI2_ADAPT] = &a9_sys_csi2_adapt.hw, + [CLKID_SYS_DSPA] = &a9_sys_dspa.hw, + [CLKID_SYS_PP_DMA] = &a9_sys_pp_dma.hw, + [CLKID_SYS_PP_WRAPPER] = &a9_sys_pp_wrapper.hw, + [CLKID_SYS_VPU_INTR] = &a9_sys_vpu_intr.hw, + [CLKID_SYS_CSI2_PHY] = &a9_sys_csi2_phy.hw, + [CLKID_SYS_SARADC] = &a9_sys_saradc.hw, + [CLKID_SYS_PWM_J] = &a9_sys_pwm_j.hw, + [CLKID_SYS_PWM_I] = &a9_sys_pwm_i.hw, + [CLKID_SYS_PWM_H] = &a9_sys_pwm_h.hw, + [CLKID_SYS_PWM_N] = &a9_sys_pwm_n.hw, + [CLKID_SYS_PWM_M] = &a9_sys_pwm_m.hw, + [CLKID_SYS_PWM_L] = &a9_sys_pwm_l.hw, + [CLKID_SYS_PWM_K] = &a9_sys_pwm_k.hw, + [CLKID_SD_EMMC_A_SEL] = &a9_sd_emmc_a_sel.hw, + [CLKID_SD_EMMC_A_DIV] = &a9_sd_emmc_a_div.hw, + [CLKID_SD_EMMC_A] = &a9_sd_emmc_a.hw, + [CLKID_SD_EMMC_B_SEL] = &a9_sd_emmc_b_sel.hw, + [CLKID_SD_EMMC_B_DIV] = &a9_sd_emmc_b_div.hw, + [CLKID_SD_EMMC_B] = &a9_sd_emmc_b.hw, + [CLKID_SD_EMMC_C_SEL] = &a9_sd_emmc_c_sel.hw, + [CLKID_SD_EMMC_C_DIV] = &a9_sd_emmc_c_div.hw, + [CLKID_SD_EMMC_C] = &a9_sd_emmc_c.hw, + [CLKID_PWM_H_SEL] = &a9_pwm_h_sel.hw, + [CLKID_PWM_H_DIV] = &a9_pwm_h_div.hw, + [CLKID_PWM_H] = &a9_pwm_h.hw, + [CLKID_PWM_I_SEL] = &a9_pwm_i_sel.hw, + [CLKID_PWM_I_DIV] = &a9_pwm_i_div.hw, + [CLKID_PWM_I] = &a9_pwm_i.hw, + [CLKID_PWM_J_SEL] = &a9_pwm_j_sel.hw, + [CLKID_PWM_J_DIV] = &a9_pwm_j_div.hw, + [CLKID_PWM_J] = &a9_pwm_j.hw, + [CLKID_PWM_K_SEL] = &a9_pwm_k_sel.hw, + [CLKID_PWM_K_DIV] = &a9_pwm_k_div.hw, + [CLKID_PWM_K] = &a9_pwm_k.hw, + [CLKID_PWM_L_SEL] = &a9_pwm_l_sel.hw, + [CLKID_PWM_L_DIV] = &a9_pwm_l_div.hw, + [CLKID_PWM_L] = &a9_pwm_l.hw, + [CLKID_PWM_M_SEL] = &a9_pwm_m_sel.hw, + [CLKID_PWM_M_DIV] = &a9_pwm_m_div.hw, + [CLKID_PWM_M] = &a9_pwm_m.hw, + [CLKID_PWM_N_SEL] = &a9_pwm_n_sel.hw, + [CLKID_PWM_N_DIV] = &a9_pwm_n_div.hw, + [CLKID_PWM_N] = &a9_pwm_n.hw, + [CLKID_SPISG_SEL] = &a9_spisg_sel.hw, + [CLKID_SPISG_DIV] = &a9_spisg_div.hw, + [CLKID_SPISG] = &a9_spisg.hw, + [CLKID_SPISG1_SEL] = &a9_spisg1_sel.hw, + [CLKID_SPISG1_DIV] = &a9_spisg1_div.hw, + [CLKID_SPISG1] = &a9_spisg1.hw, + [CLKID_SPISG2_SEL] = &a9_spisg2_sel.hw, + [CLKID_SPISG2_DIV] = &a9_spisg2_div.hw, + [CLKID_SPISG2] = &a9_spisg2.hw, + [CLKID_SARADC_SEL] = &a9_saradc_sel.hw, + [CLKID_SARADC_DIV] = &a9_saradc_div.hw, + [CLKID_SARADC] = &a9_saradc.hw, + [CLKID_AMFC_SEL] = &a9_amfc_sel.hw, + [CLKID_AMFC_DIV] = &a9_amfc_div.hw, + [CLKID_AMFC] = &a9_amfc.hw, + [CLKID_NNA_SEL] = &a9_nna_sel.hw, + [CLKID_NNA_DIV] = &a9_nna_div.hw, + [CLKID_NNA] = &a9_nna.hw, + [CLKID_USB_250M_SEL] = &a9_usb_250m_sel.hw, + [CLKID_USB_250M_DIV] = &a9_usb_250m_div.hw, + [CLKID_USB_250M] = &a9_usb_250m.hw, + [CLKID_USB_48M_PRE_SEL] = &a9_usb_48m_pre_sel.hw, + [CLKID_USB_48M_PRE_DIV] = &a9_usb_48m_pre_div.hw, + [CLKID_USB_48M_PRE] = &a9_usb_48m_pre.hw, + [CLKID_PCIE_TL_SEL] = &a9_pcie_tl_sel.hw, + [CLKID_PCIE_TL_DIV] = &a9_pcie_tl_div.hw, + [CLKID_PCIE_TL] = &a9_pcie_tl.hw, + [CLKID_PCIE1_TL_SEL] = &a9_pcie1_tl_sel.hw, + [CLKID_PCIE1_TL_DIV] = &a9_pcie1_tl_div.hw, + [CLKID_PCIE1_TL] = &a9_pcie1_tl.hw, + [CLKID_CMPR_SEL] = &a9_cmpr_sel.hw, + [CLKID_CMPR_DIV] = &a9_cmpr_div.hw, + [CLKID_CMPR] = &a9_cmpr.hw, + [CLKID_DEWARPA_SEL] = &a9_dewarpa_sel.hw, + [CLKID_DEWARPA_DIV] = &a9_dewarpa_div.hw, + [CLKID_DEWARPA] = &a9_dewarpa.hw, + [CLKID_SC_PRE_SEL] = &a9_sc_pre_sel.hw, + [CLKID_SC_PRE_DIV] = &a9_sc_pre_div.hw, + [CLKID_SC_PRE] = &a9_sc_pre.hw, + [CLKID_SC] = &a9_sc.hw, + [CLKID_DPTX_APB2_SEL] = &a9_dptx_apb2_sel.hw, + [CLKID_DPTX_APB2_DIV] = &a9_dptx_apb2_div.hw, + [CLKID_DPTX_APB2] = &a9_dptx_apb2.hw, + [CLKID_DPTX_AUD_SEL] = &a9_dptx_aud_sel.hw, + [CLKID_DPTX_AUD_DIV] = &a9_dptx_aud_div.hw, + [CLKID_DPTX_AUD] = &a9_dptx_aud.hw, + [CLKID_ISP_SEL] = &a9_isp_sel.hw, + [CLKID_ISP_DIV] = &a9_isp_div.hw, + [CLKID_ISP] = &a9_isp.hw, + [CLKID_CVE_SEL] = &a9_cve_sel.hw, + [CLKID_CVE_DIV] = &a9_cve_div.hw, + [CLKID_CVE] = &a9_cve.hw, + [CLKID_VGE_SEL] = &a9_vge_sel.hw, + [CLKID_VGE_DIV] = &a9_vge_div.hw, + [CLKID_VGE] = &a9_vge.hw, + [CLKID_PP_SEL] = &a9_pp_sel.hw, + [CLKID_PP_DIV] = &a9_pp_div.hw, + [CLKID_PP] = &a9_pp.hw, + [CLKID_GLB_SEL] = &a9_glb_sel.hw, + [CLKID_GLB_DIV] = &a9_glb_div.hw, + [CLKID_GLB] = &a9_glb.hw, + [CLKID_USB_48M_DUALDIV_IN] = &a9_usb_48m_dualdiv_in.hw, + [CLKID_USB_48M_DUALDIV_DIV] = &a9_usb_48m_dualdiv_div.hw, + [CLKID_USB_48M_DUALDIV_SEL] = &a9_usb_48m_dualdiv_sel.hw, + [CLKID_USB_48M_DUALDIV] = &a9_usb_48m_dualdiv.hw, + [CLKID_USB_48M] = &a9_usb_48m.hw, + [CLKID_CAN_PE_SEL] = &a9_can_pe_sel.hw, + [CLKID_CAN_PE_DIV] = &a9_can_pe_div.hw, + [CLKID_CAN_PE] = &a9_can_pe.hw, + [CLKID_CAN1_PE_SEL] = &a9_can1_pe_sel.hw, + [CLKID_CAN1_PE_DIV] = &a9_can1_pe_div.hw, + [CLKID_CAN1_PE] = &a9_can1_pe.hw, + [CLKID_CAN_FILTER_SEL] = &a9_can_filter_sel.hw, + [CLKID_CAN_FILTER_DIV] = &a9_can_filter_div.hw, + [CLKID_CAN_FILTER] = &a9_can_filter.hw, + [CLKID_CAN1_FILTER_SEL] = &a9_can1_filter_sel.hw, + [CLKID_CAN1_FILTER_DIV] = &a9_can1_filter_div.hw, + [CLKID_CAN1_FILTER] = &a9_can1_filter.hw, + [CLKID_I3C_SEL] = &a9_i3c_sel.hw, + [CLKID_I3C_DIV] = &a9_i3c_div.hw, + [CLKID_I3C] = &a9_i3c.hw, + [CLKID_TS_DIV] = &a9_ts_div.hw, + [CLKID_TS] = &a9_ts.hw, + [CLKID_ETH_125M_DIV] = &a9_eth_125m_div.hw, + [CLKID_ETH_125M] = &a9_eth_125m.hw, + [CLKID_ETH_RMII_SEL] = &a9_eth_rmii_sel.hw, + [CLKID_ETH_RMII_DIV] = &a9_eth_rmii_div.hw, + [CLKID_ETH_RMII] = &a9_eth_rmii.hw, + [CLKID_GEN_SEL] = &a9_gen_sel.hw, + [CLKID_GEN_DIV] = &a9_gen_div.hw, + [CLKID_GEN] = &a9_gen.hw, + [CLKID_CLK24M_IN] = &a9_24m_in.hw, + [CLKID_CLK12_24M] = &a9_12_24m.hw, + [CLKID_MALI_0_SEL] = &a9_mali_0_sel.hw, + [CLKID_MALI_0_DIV] = &a9_mali_0_div.hw, + [CLKID_MALI_0] = &a9_mali_0.hw, + [CLKID_MALI_1_SEL] = &a9_mali_1_sel.hw, + [CLKID_MALI_1_DIV] = &a9_mali_1_div.hw, + [CLKID_MALI_1] = &a9_mali_1.hw, + [CLKID_MALI] = &a9_mali.hw, + [CLKID_MALI_STACK_0_SEL] = &a9_mali_stack_0_sel.hw, + [CLKID_MALI_STACK_0_DIV] = &a9_mali_stack_0_div.hw, + [CLKID_MALI_STACK_0] = &a9_mali_stack_0.hw, + [CLKID_MALI_STACK_1_SEL] = &a9_mali_stack_1_sel.hw, + [CLKID_MALI_STACK_1_DIV] = &a9_mali_stack_1_div.hw, + [CLKID_MALI_STACK_1] = &a9_mali_stack_1.hw, + [CLKID_MALI_STACK] = &a9_mali_stack.hw, + [CLKID_DSPA_0_SEL] = &a9_dspa_0_sel.hw, + [CLKID_DSPA_0_DIV] = &a9_dspa_0_div.hw, + [CLKID_DSPA_0] = &a9_dspa_0.hw, + [CLKID_DSPA_1_SEL] = &a9_dspa_1_sel.hw, + [CLKID_DSPA_1_DIV] = &a9_dspa_1_div.hw, + [CLKID_DSPA_1] = &a9_dspa_1.hw, + [CLKID_DSPA] = &a9_dspa.hw, + [CLKID_HEVCF_0_SEL] = &a9_hevcf_0_sel.hw, + [CLKID_HEVCF_0_DIV] = &a9_hevcf_0_div.hw, + [CLKID_HEVCF_0] = &a9_hevcf_0.hw, + [CLKID_HEVCF_1_SEL] = &a9_hevcf_1_sel.hw, + [CLKID_HEVCF_1_DIV] = &a9_hevcf_1_div.hw, + [CLKID_HEVCF_1] = &a9_hevcf_1.hw, + [CLKID_HEVCF] = &a9_hevcf.hw, + [CLKID_HCODEC_0_SEL] = &a9_hcodec_0_sel.hw, + [CLKID_HCODEC_0_DIV] = &a9_hcodec_0_div.hw, + [CLKID_HCODEC_0] = &a9_hcodec_0.hw, + [CLKID_HCODEC_1_SEL] = &a9_hcodec_1_sel.hw, + [CLKID_HCODEC_1_DIV] = &a9_hcodec_1_div.hw, + [CLKID_HCODEC_1] = &a9_hcodec_1.hw, + [CLKID_HCODEC] = &a9_hcodec.hw, + [CLKID_VPU_0_SEL] = &a9_vpu_0_sel.hw, + [CLKID_VPU_0_DIV] = &a9_vpu_0_div.hw, + [CLKID_VPU_0] = &a9_vpu_0.hw, + [CLKID_VPU_1_SEL] = &a9_vpu_1_sel.hw, + [CLKID_VPU_1_DIV] = &a9_vpu_1_div.hw, + [CLKID_VPU_1] = &a9_vpu_1.hw, + [CLKID_VPU] = &a9_vpu.hw, + [CLKID_VAPB_0_SEL] = &a9_vapb_0_sel.hw, + [CLKID_VAPB_0_DIV] = &a9_vapb_0_div.hw, + [CLKID_VAPB_0] = &a9_vapb_0.hw, + [CLKID_VAPB_1_SEL] = &a9_vapb_1_sel.hw, + [CLKID_VAPB_1_DIV] = &a9_vapb_1_div.hw, + [CLKID_VAPB_1] = &a9_vapb_1.hw, + [CLKID_VAPB] = &a9_vapb.hw, + [CLKID_GE2D] = &a9_ge2d.hw, + [CLKID_VPU_CLKB_TMP_SEL] = &a9_vpu_clkb_tmp_sel.hw, + [CLKID_VPU_CLKB_TMP_DIV] = &a9_vpu_clkb_tmp_div.hw, + [CLKID_VPU_CLKB_TMP] = &a9_vpu_clkb_tmp.hw, + [CLKID_VPU_CLKB_DIV] = &a9_vpu_clkb_div.hw, + [CLKID_VPU_CLKB] = &a9_vpu_clkb.hw, + [CLKID_HDMITX_SYS_SEL] = &a9_hdmitx_sys_sel.hw, + [CLKID_HDMITX_SYS_DIV] = &a9_hdmitx_sys_div.hw, + [CLKID_HDMITX_SYS] = &a9_hdmitx_sys.hw, + [CLKID_HDMITX_PRIF_SEL] = &a9_hdmitx_prif_sel.hw, + [CLKID_HDMITX_PRIF_DIV] = &a9_hdmitx_prif_div.hw, + [CLKID_HDMITX_PRIF] = &a9_hdmitx_prif.hw, + [CLKID_HDMITX_200M_SEL] = &a9_hdmitx_200m_sel.hw, + [CLKID_HDMITX_200M_DIV] = &a9_hdmitx_200m_div.hw, + [CLKID_HDMITX_200M] = &a9_hdmitx_200m.hw, + [CLKID_HDMITX_AUD_SEL] = &a9_hdmitx_aud_sel.hw, + [CLKID_HDMITX_AUD_DIV] = &a9_hdmitx_aud_div.hw, + [CLKID_HDMITX_AUD] = &a9_hdmitx_aud.hw, + [CLKID_HDMIRX_5M_SEL] = &a9_hdmirx_5m_sel.hw, + [CLKID_HDMIRX_5M_DIV] = &a9_hdmirx_5m_div.hw, + [CLKID_HDMIRX_5M] = &a9_hdmirx_5m.hw, + [CLKID_HDMIRX_2M_SEL] = &a9_hdmirx_2m_sel.hw, + [CLKID_HDMIRX_2M_DIV] = &a9_hdmirx_2m_div.hw, + [CLKID_HDMIRX_2M] = &a9_hdmirx_2m.hw, + [CLKID_HDMIRX_CFG_SEL] = &a9_hdmirx_cfg_sel.hw, + [CLKID_HDMIRX_CFG_DIV] = &a9_hdmirx_cfg_div.hw, + [CLKID_HDMIRX_CFG] = &a9_hdmirx_cfg.hw, + [CLKID_HDMIRX_HDCP2X_SEL] = &a9_hdmirx_hdcp2x_sel.hw, + [CLKID_HDMIRX_HDCP2X_DIV] = &a9_hdmirx_hdcp2x_div.hw, + [CLKID_HDMIRX_HDCP2X] = &a9_hdmirx_hdcp2x.hw, + [CLKID_HDMIRX_ACR_REF_SEL] = &a9_hdmirx_acr_ref_sel.hw, + [CLKID_HDMIRX_ACR_REF_DIV] = &a9_hdmirx_acr_ref_div.hw, + [CLKID_HDMIRX_ACR_REF] = &a9_hdmirx_acr_ref.hw, + [CLKID_HDMIRX_METER_SEL] = &a9_hdmirx_meter_sel.hw, + [CLKID_HDMIRX_METER_DIV] = &a9_hdmirx_meter_div.hw, + [CLKID_HDMIRX_METER] = &a9_hdmirx_meter.hw, + [CLKID_VID_LOCK_SEL] = &a9_vid_lock_sel.hw, + [CLKID_VID_LOCK_DIV] = &a9_vid_lock_div.hw, + [CLKID_VID_LOCK] = &a9_vid_lock.hw, + [CLKID_VDIN_MEAS_SEL] = &a9_vdin_meas_sel.hw, + [CLKID_VDIN_MEAS_DIV] = &a9_vdin_meas_div.hw, + [CLKID_VDIN_MEAS] = &a9_vdin_meas.hw, + [CLKID_VID_PLL_DIV] = &a9_vid_pll_div.hw, + [CLKID_VID_PLL_SEL] = &a9_vid_pll_sel.hw, + [CLKID_VID_PLL] = &a9_vid_pll.hw, + [CLKID_VID_PLL_VCLK] = &a9_vid_pll_vclk.hw, + [CLKID_VCLK_SEL] = &a9_vclk_sel.hw, + [CLKID_VCLK_IN] = &a9_vclk_in.hw, + [CLKID_VCLK_DIV] = &a9_vclk_div.hw, + [CLKID_VCLK] = &a9_vclk.hw, + [CLKID_VCLK_DIV1_EN] = &a9_vclk_div1_en.hw, + [CLKID_VCLK_DIV2_EN] = &a9_vclk_div2_en.hw, + [CLKID_VCLK_DIV2] = &a9_vclk_div2.hw, + [CLKID_VCLK_DIV4_EN] = &a9_vclk_div4_en.hw, + [CLKID_VCLK_DIV4] = &a9_vclk_div4.hw, + [CLKID_VCLK_DIV6_EN] = &a9_vclk_div6_en.hw, + [CLKID_VCLK_DIV6] = &a9_vclk_div6.hw, + [CLKID_VCLK_DIV12_EN] = &a9_vclk_div12_en.hw, + [CLKID_VCLK_DIV12] = &a9_vclk_div12.hw, + [CLKID_VCLK2_SEL] = &a9_vclk2_sel.hw, + [CLKID_VCLK2_IN] = &a9_vclk2_in.hw, + [CLKID_VCLK2_DIV] = &a9_vclk2_div.hw, + [CLKID_VCLK2] = &a9_vclk2.hw, + [CLKID_VCLK2_DIV1_EN] = &a9_vclk2_div1_en.hw, + [CLKID_VCLK2_DIV2_EN] = &a9_vclk2_div2_en.hw, + [CLKID_VCLK2_DIV2] = &a9_vclk2_div2.hw, + [CLKID_VCLK2_DIV4_EN] = &a9_vclk2_div4_en.hw, + [CLKID_VCLK2_DIV4] = &a9_vclk2_div4.hw, + [CLKID_VCLK2_DIV6_EN] = &a9_vclk2_div6_en.hw, + [CLKID_VCLK2_DIV6] = &a9_vclk2_div6.hw, + [CLKID_VCLK2_DIV12_EN] = &a9_vclk2_div12_en.hw, + [CLKID_VCLK2_DIV12] = &a9_vclk2_div12.hw, + [CLKID_VDAC_SEL] = &a9_vdac_sel.hw, + [CLKID_VDAC] = &a9_vdac.hw, + [CLKID_ENC_SEL] = &a9_enc_sel.hw, + [CLKID_ENC] = &a9_enc.hw, + [CLKID_ENC1_SEL] = &a9_enc1_sel.hw, + [CLKID_ENC1] = &a9_enc1.hw, + [CLKID_HDMITX_PIXEL_SEL] = &a9_hdmitx_pixel_sel.hw, + [CLKID_HDMITX_PIXEL] = &a9_hdmitx_pixel.hw, + [CLKID_HDMITX_FE_SEL] = &a9_hdmitx_fe_sel.hw, + [CLKID_HDMITX_FE] = &a9_hdmitx_fe.hw, + [CLKID_HDMITX1_PIXEL_SEL] = &a9_hdmitx1_pixel_sel.hw, + [CLKID_HDMITX1_PIXEL] = &a9_hdmitx1_pixel.hw, + [CLKID_HDMITX1_FE_SEL] = &a9_hdmitx1_fe_sel.hw, + [CLKID_HDMITX1_FE] = &a9_hdmitx1_fe.hw, + [CLKID_CSI_PHY_SEL] = &a9_csi_phy_sel.hw, + [CLKID_CSI_PHY_DIV] = &a9_csi_phy_div.hw, + [CLKID_CSI_PHY] = &a9_csi_phy.hw, + [CLKID_DSI_MEAS_SEL] = &a9_dsi_meas_sel.hw, + [CLKID_DSI_MEAS_DIV] = &a9_dsi_meas_div.hw, + [CLKID_DSI_MEAS] = &a9_dsi_meas.hw, + [CLKID_DSI_B_MEAS_SEL] = &a9_dsi_b_meas_sel.hw, + [CLKID_DSI_B_MEAS_DIV] = &a9_dsi_b_meas_div.hw, + [CLKID_DSI_B_MEAS] = &a9_dsi_b_meas.hw, +}; + +static const struct meson_clkc_data a9_peripherals_clkc_data = { + .hw_clks = { + .hws = a9_peripherals_hw_clks, + .num = ARRAY_SIZE(a9_peripherals_hw_clks), + }, +}; + +static const struct of_device_id a9_peripherals_clkc_match_table[] = { + { + .compatible = "amlogic,a9-peripherals-clkc", + .data = &a9_peripherals_clkc_data, + }, + { /* sentinel */ } +}; + +MODULE_DEVICE_TABLE(of, a9_peripherals_clkc_match_table); + +static struct platform_driver a9_peripherals_clkc_driver = { + .probe = meson_clkc_mmio_probe, + .driver = { + .name = "a9-peripherals-clkc", + .of_match_table = a9_peripherals_clkc_match_table, + }, +}; +module_platform_driver(a9_peripherals_clkc_driver); + +MODULE_DESCRIPTION("Amlogic A9 Peripherals Clock Controller driver"); +MODULE_AUTHOR("Jian Hu <jian.hu@amlogic.com>"); +MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS("CLK_MESON"); -- 2.47.1 ^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [PATCH 09/10] clk: amlogic: Add A9 peripherals clock controller driver 2026-05-11 12:47 ` [PATCH 09/10] clk: amlogic: Add A9 peripherals " Jian Hu via B4 Relay @ 2026-05-11 15:42 ` Brian Masney 0 siblings, 0 replies; 17+ messages in thread From: Brian Masney @ 2026-05-11 15:42 UTC (permalink / raw) To: jian.hu Cc: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Neil Armstrong, Jerome Brunet, Xianwei Zhao, Kevin Hilman, Martin Blumenstingl, linux-kernel, linux-clk, devicetree, linux-amlogic, linux-arm-kernel Hi Jian, On Mon, May 11, 2026 at 08:47:31PM +0800, Jian Hu via B4 Relay wrote: > From: Jian Hu <jian.hu@amlogic.com> > > Add the peripherals clock controller driver for the Amlogic A9 SoC family. > > Signed-off-by: Jian Hu <jian.hu@amlogic.com> > --- > drivers/clk/meson/Kconfig | 15 + > drivers/clk/meson/Makefile | 1 + > drivers/clk/meson/a9-peripherals.c | 2317 ++++++++++++++++++++++++++++++++++++ > 3 files changed, 2333 insertions(+) > > diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig > index 3549e67d6988..48a15a5e1323 100644 > --- a/drivers/clk/meson/Kconfig > +++ b/drivers/clk/meson/Kconfig > @@ -145,6 +145,21 @@ config COMMON_CLK_A9_PLL > device, AKA A9. PLLs are required by most peripheral to operate. > Say Y if you want A9 PLL clock controller to work. > > +config COMMON_CLK_A9_PERIPHERALS > + tristate "Amlogic A9 SoC peripherals clock controller support" > + depends on ARM64 depends on ARM64 || COMPILE_TEST > + default ARCH_MESON > + select COMMON_CLK_MESON_REGMAP > + select COMMON_CLK_MESON_CLKC_UTILS > + select COMMON_CLK_MESON_DUALDIV > + select COMMON_CLK_MESON_VID_PLL_DIV > + imply COMMON_CLK_SCMI > + imply COMMON_CLK_A9_PLL > + help > + Support for the peripherals clock controller on Amlogic A311Y3 based > + device, AKA A9. Peripherals are required by most peripheral to operate. > + Say Y if you want A9 peripherals clock controller to work. > + > config COMMON_CLK_C3_PLL > tristate "Amlogic C3 PLL clock controller" > depends on ARM64 > diff --git a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile > index 77636033061f..2b5b67b14efc 100644 > --- a/drivers/clk/meson/Makefile > +++ b/drivers/clk/meson/Makefile > @@ -20,6 +20,7 @@ obj-$(CONFIG_COMMON_CLK_AXG_AUDIO) += axg-audio.o > obj-$(CONFIG_COMMON_CLK_A1_PLL) += a1-pll.o > obj-$(CONFIG_COMMON_CLK_A1_PERIPHERALS) += a1-peripherals.o > obj-$(CONFIG_COMMON_CLK_A9_PLL) += a9-pll.o > +obj-$(CONFIG_COMMON_CLK_A9_PERIPHERALS) += a9-peripherals.o > obj-$(CONFIG_COMMON_CLK_C3_PLL) += c3-pll.o > obj-$(CONFIG_COMMON_CLK_C3_PERIPHERALS) += c3-peripherals.o > obj-$(CONFIG_COMMON_CLK_GXBB) += gxbb.o gxbb-aoclk.o > diff --git a/drivers/clk/meson/a9-peripherals.c b/drivers/clk/meson/a9-peripherals.c > new file mode 100644 > index 000000000000..338a91c473ea > --- /dev/null > +++ b/drivers/clk/meson/a9-peripherals.c > @@ -0,0 +1,2317 @@ > +// SPDX-License-Identifier: (GPL-2.0-only OR MIT) > +/* > + * Copyright (C) 2026 Amlogic, Inc. All rights reserved > + */ > + > +#include <linux/clk-provider.h> > +#include <linux/platform_device.h> > +#include <dt-bindings/clock/amlogic,a9-peripherals-clkc.h> > +#include "clk-regmap.h" > +#include "clk-dualdiv.h" > +#include "vid-pll-div.h" > +#include "meson-clkc-utils.h" Sort the headers. > + > +#define SYS_CLK_EN0_REG0 0x30 > +#define SYS_CLK_EN0_REG1 0x34 > +#define SYS_CLK_EN0_REG2 0x38 > +#define SYS_CLK_EN0_REG3 0x3c > +#define SD_EMMC_CLK_CTRL0 0x90 > +#define SD_EMMC_CLK_CTRL1 0x94 > +#define PWM_CLK_H_CTRL 0xbc > +#define PWM_CLK_I_CTRL 0xc0 > +#define PWM_CLK_J_CTRL 0xc4 > +#define PWM_CLK_K_CTRL 0xc8 > +#define PWM_CLK_L_CTRL 0xcc > +#define PWM_CLK_M_CTRL 0xd0 > +#define PWM_CLK_N_CTRL 0xd4 > +#define SPISG_CLK_CTRL 0x100 > +#define SPISG_CLK_CTRL1 0x104 > +#define SAR_CLK_CTRL 0x150 > +#define AMFC_CLK_CTRL 0x154 > +#define NNA_CLK_CTRL 0x15c > +#define USB_CLK_CTRL 0x160 > +#define PCIE_TL_CLK_CTRL 0x164 > +#define CMPR_CLK_CTRL 0x168 > +#define DEWARP_CLK_CTRL 0x16c > +#define SC_CLK_CTRL 0x170 > +#define DPTX_CLK_CTRL 0x178 > +#define ISP_CLK_CTRL 0x17c > +#define CVE_CLK_CTRL 0x180 > +#define PP_CLK_CTRL 0x184 > +#define GLB_CLK_CTRL 0x188 > +#define USB_CLK_CTRL0 0x18c > +#define USB_CLK_CTRL1 0x190 > +#define CAN_CLK_CTRL 0x194 > +#define CAN_CLK_CTRL1 0x198 > +#define I3C_CLK_CTRL 0x19c > +#define TS_CLK_CTRL 0x1a0 > +#define ETH_CLK_CTRL 0x1a4 > +#define GEN_CLK_CTRL 0x1a8 > +#define CLK12_24_CTRL 0x1ac > +#define MALI_CLK_CTRL 0x200 > +#define MALI_STACK_CLK_CTRL 0x204 > +#define DSPA_CLK_CTRL 0x220 > +#define HEVCF_CLK_CTRL 0x240 > +#define HCODEC_CLK_CTRL 0x244 > +#define VPU_CLK_CTRL 0x260 > +#define VAPB_CLK_CTRL 0x268 > +#define VPU_CLKB_CTRL 0x280 > +#define HDMI_CLK_CTRL 0x284 > +#define HTX_CLK_CTRL 0x28c > +#define HTX_CLK_CTRL1 0x290 > +#define HRX_CLK_CTRL 0x294 > +#define HRX_CLK_CTRL1 0x298 > +#define HRX_CLK_CTRL2 0x29c > +#define HRX_CLK_CTRL3 0x2a0 > +#define VID_LOCK_CLK_CTRL 0x2a4 > +#define VDIN_MEAS_CLK_CTRL 0x2a8 > +#define VID_PLL_CLK_DIV 0x2b0 > +#define VID_CLK_CTRL 0x2c0 > +#define VID_CLK_CTRL2 0x2c4 > +#define VID_CLK_DIV 0x2c8 > +#define VIID_CLK_DIV 0x2cc > +#define VIID_CLK_CTRL 0x2d0 > +#define MIPI_CSI_PHY_CLK_CTRL 0x2e0 > +#define DSI_MEAS_CLK_CTRL 0x2f4 > + > +#define A9_COMP_SEL(_name, _reg, _shift, _mask, _pdata, _table) \ > + MESON_COMP_SEL(a9_, _name, _reg, _shift, _mask, _pdata, _table, 0, 0) > + > +#define A9_COMP_DIV(_name, _reg, _shift, _width) \ > + MESON_COMP_DIV(a9_, _name, _reg, _shift, _width, 0, CLK_SET_RATE_PARENT) > + > +#define A9_COMP_GATE(_name, _reg, _bit, _iflags) \ > + MESON_COMP_GATE(a9_, _name, _reg, _bit, CLK_SET_RATE_PARENT | (_iflags)) > + > +static const struct clk_parent_data a9_sys_pclk_parents = { .fw_name = "sys" }; > + > +#define A9_SYS_PCLK(_name, _reg, _bit) \ > + MESON_PCLK(a9_##_name, _reg, _bit, &a9_sys_pclk_parents, 0) > + > +static A9_SYS_PCLK(sys_am_axi, SYS_CLK_EN0_REG0, 0); > +static A9_SYS_PCLK(sys_dos, SYS_CLK_EN0_REG0, 1); > +static A9_SYS_PCLK(sys_mipi_dsi, SYS_CLK_EN0_REG0, 3); > +static A9_SYS_PCLK(sys_eth_phy, SYS_CLK_EN0_REG0, 4); > +static A9_SYS_PCLK(sys_amfc, SYS_CLK_EN0_REG0, 5); > +static A9_SYS_PCLK(sys_mali, SYS_CLK_EN0_REG0, 6); > +static A9_SYS_PCLK(sys_nna, SYS_CLK_EN0_REG0, 7); > +static A9_SYS_PCLK(sys_eth_axi, SYS_CLK_EN0_REG0, 8); > +static A9_SYS_PCLK(sys_dp_apb, SYS_CLK_EN0_REG0, 9); > +static A9_SYS_PCLK(sys_edptx_apb, SYS_CLK_EN0_REG0, 10); > +static A9_SYS_PCLK(sys_u3hsg, SYS_CLK_EN0_REG0, 11); > +static A9_SYS_PCLK(sys_aucpu, SYS_CLK_EN0_REG0, 14); > +static A9_SYS_PCLK(sys_glb, SYS_CLK_EN0_REG0, 15); > +static A9_SYS_PCLK(sys_combo_dphy_apb, SYS_CLK_EN0_REG0, 17); > +static A9_SYS_PCLK(sys_hdmirx_apb, SYS_CLK_EN0_REG0, 18); > +static A9_SYS_PCLK(sys_hdmirx_pclk, SYS_CLK_EN0_REG0, 19); > +static A9_SYS_PCLK(sys_mipi_dsi_phy, SYS_CLK_EN0_REG0, 20); > +static A9_SYS_PCLK(sys_can0, SYS_CLK_EN0_REG0, 21); > +static A9_SYS_PCLK(sys_can1, SYS_CLK_EN0_REG0, 22); > +static A9_SYS_PCLK(sys_sd_emmc_a, SYS_CLK_EN0_REG0, 24); > +static A9_SYS_PCLK(sys_sd_emmc_b, SYS_CLK_EN0_REG0, 25); > +static A9_SYS_PCLK(sys_sd_emmc_c, SYS_CLK_EN0_REG0, 26); > +static A9_SYS_PCLK(sys_sc, SYS_CLK_EN0_REG0, 27); > +static A9_SYS_PCLK(sys_acodec, SYS_CLK_EN0_REG0, 28); > +static A9_SYS_PCLK(sys_mipi_isp, SYS_CLK_EN0_REG0, 29); > +static A9_SYS_PCLK(sys_msr, SYS_CLK_EN0_REG0, 30); > +static A9_SYS_PCLK(sys_audio, SYS_CLK_EN0_REG1, 0); > +static A9_SYS_PCLK(sys_mipi_dsi_b, SYS_CLK_EN0_REG1, 1); > +static A9_SYS_PCLK(sys_mipi_dsi1_phy, SYS_CLK_EN0_REG1, 2); > +static A9_SYS_PCLK(sys_eth, SYS_CLK_EN0_REG1, 3); > +static A9_SYS_PCLK(sys_eth_1g_mac, SYS_CLK_EN0_REG1, 4); > +static A9_SYS_PCLK(sys_uart_a, SYS_CLK_EN0_REG1, 5); > +static A9_SYS_PCLK(sys_uart_f, SYS_CLK_EN0_REG1, 10); > +static A9_SYS_PCLK(sys_ts_a55, SYS_CLK_EN0_REG1, 11); > +static A9_SYS_PCLK(sys_eth_1g_axi, SYS_CLK_EN0_REG1, 12); > +static A9_SYS_PCLK(sys_ts_dos, SYS_CLK_EN0_REG1, 13); > +static A9_SYS_PCLK(sys_u3drd_b, SYS_CLK_EN0_REG1, 14); > +static A9_SYS_PCLK(sys_ts_core, SYS_CLK_EN0_REG1, 15); > +static A9_SYS_PCLK(sys_ts_pll, SYS_CLK_EN0_REG1, 16); > +static A9_SYS_PCLK(sys_csi_dig_clkin, SYS_CLK_EN0_REG1, 18); > +static A9_SYS_PCLK(sys_cve, SYS_CLK_EN0_REG1, 19); > +static A9_SYS_PCLK(sys_ge2d, SYS_CLK_EN0_REG1, 20); > +static A9_SYS_PCLK(sys_spisg, SYS_CLK_EN0_REG1, 21); > +static A9_SYS_PCLK(sys_u3drd_1, SYS_CLK_EN0_REG1, 22); > +static A9_SYS_PCLK(sys_u2h, SYS_CLK_EN0_REG1, 23); > +static A9_SYS_PCLK(sys_pcie_mac_a, SYS_CLK_EN0_REG1, 24); > +static A9_SYS_PCLK(sys_u3drd_a, SYS_CLK_EN0_REG1, 25); > +static A9_SYS_PCLK(sys_u2drd, SYS_CLK_EN0_REG1, 26); > +static A9_SYS_PCLK(sys_pcie_phy, SYS_CLK_EN0_REG1, 27); > +static A9_SYS_PCLK(sys_pcie_mac_b, SYS_CLK_EN0_REG1, 28); > +static A9_SYS_PCLK(sys_periph, SYS_CLK_EN0_REG1, 29); > +static A9_SYS_PCLK(sys_pio, SYS_CLK_EN0_REG2, 0); > +static A9_SYS_PCLK(sys_i3c, SYS_CLK_EN0_REG2, 1); > +static A9_SYS_PCLK(sys_i2c_m_e, SYS_CLK_EN0_REG2, 2); > +static A9_SYS_PCLK(sys_i2c_m_f, SYS_CLK_EN0_REG2, 3); > +static A9_SYS_PCLK(sys_hdmitx_apb, SYS_CLK_EN0_REG2, 4); > +static A9_SYS_PCLK(sys_i2c_m_i, SYS_CLK_EN0_REG2, 5); > +static A9_SYS_PCLK(sys_i2c_m_g, SYS_CLK_EN0_REG2, 6); > +static A9_SYS_PCLK(sys_i2c_m_h, SYS_CLK_EN0_REG2, 7); > +static A9_SYS_PCLK(sys_hdmi20_aes, SYS_CLK_EN0_REG2, 9); > +static A9_SYS_PCLK(sys_csi2_host, SYS_CLK_EN0_REG2, 16); > +static A9_SYS_PCLK(sys_csi2_adapt, SYS_CLK_EN0_REG2, 17); > +static A9_SYS_PCLK(sys_dspa, SYS_CLK_EN0_REG2, 21); > +static A9_SYS_PCLK(sys_pp_dma, SYS_CLK_EN0_REG2, 22); > +static A9_SYS_PCLK(sys_pp_wrapper, SYS_CLK_EN0_REG2, 23); > +static A9_SYS_PCLK(sys_vpu_intr, SYS_CLK_EN0_REG2, 25); > +static A9_SYS_PCLK(sys_csi2_phy, SYS_CLK_EN0_REG2, 27); > +static A9_SYS_PCLK(sys_saradc, SYS_CLK_EN0_REG2, 28); > +static A9_SYS_PCLK(sys_pwm_j, SYS_CLK_EN0_REG2, 30); > +static A9_SYS_PCLK(sys_pwm_i, SYS_CLK_EN0_REG2, 31); > +static A9_SYS_PCLK(sys_pwm_h, SYS_CLK_EN0_REG3, 0); > +static A9_SYS_PCLK(sys_pwm_n, SYS_CLK_EN0_REG3, 8); > +static A9_SYS_PCLK(sys_pwm_m, SYS_CLK_EN0_REG3, 9); > +static A9_SYS_PCLK(sys_pwm_l, SYS_CLK_EN0_REG3, 10); > +static A9_SYS_PCLK(sys_pwm_k, SYS_CLK_EN0_REG3, 11); > + > +/* Channel 5 is unconnected. */ > +static u32 a9_sd_emmc_parents_val_table[] = { 0, 1, 2, 3, 4, 6, 7 }; > +static const struct clk_parent_data a9_sd_emmc_parents[] = { > + { .fw_name = "xtal", }, > + { .fw_name = "fdiv2", }, > + { .fw_name = "fdiv3", }, > + { .fw_name = "hifi0", }, > + { .fw_name = "fdiv2p5", }, > + { .fw_name = "gp1", }, > + { .fw_name = "gp0", } > +}; > + > +static A9_COMP_SEL(sd_emmc_a, SD_EMMC_CLK_CTRL0, 9, 0x7, a9_sd_emmc_parents, > + a9_sd_emmc_parents_val_table); > +static A9_COMP_DIV(sd_emmc_a, SD_EMMC_CLK_CTRL0, 0, 7); > +static A9_COMP_GATE(sd_emmc_a, SD_EMMC_CLK_CTRL0, 8, 0); > + > +static A9_COMP_SEL(sd_emmc_b, SD_EMMC_CLK_CTRL0, 25, 0x7, a9_sd_emmc_parents, > + a9_sd_emmc_parents_val_table); > +static A9_COMP_DIV(sd_emmc_b, SD_EMMC_CLK_CTRL0, 16, 7); > +static A9_COMP_GATE(sd_emmc_b, SD_EMMC_CLK_CTRL0, 24, 0); > + > +static A9_COMP_SEL(sd_emmc_c, SD_EMMC_CLK_CTRL1, 9, 0x7, a9_sd_emmc_parents, > + a9_sd_emmc_parents_val_table); > +static A9_COMP_DIV(sd_emmc_c, SD_EMMC_CLK_CTRL1, 0, 7); > +static A9_COMP_GATE(sd_emmc_c, SD_EMMC_CLK_CTRL1, 8, 0); > + > +static const struct clk_parent_data a9_pwm_parents[] = { > + { .fw_name = "xtal", }, > + { .fw_name = "fdiv5", }, > + { .fw_name = "fdiv4", }, > + { .fw_name = "fdiv3", } > +}; > + > +static A9_COMP_SEL(pwm_h, PWM_CLK_H_CTRL, 9, 0x7, a9_pwm_parents, NULL); > +static A9_COMP_DIV(pwm_h, PWM_CLK_H_CTRL, 0, 8); > +static A9_COMP_GATE(pwm_h, PWM_CLK_H_CTRL, 8, 0); > + > +static A9_COMP_SEL(pwm_i, PWM_CLK_I_CTRL, 9, 0x7, a9_pwm_parents, NULL); > +static A9_COMP_DIV(pwm_i, PWM_CLK_I_CTRL, 0, 8); > +static A9_COMP_GATE(pwm_i, PWM_CLK_I_CTRL, 8, 0); > + > +static A9_COMP_SEL(pwm_j, PWM_CLK_J_CTRL, 9, 0x7, a9_pwm_parents, NULL); > +static A9_COMP_DIV(pwm_j, PWM_CLK_J_CTRL, 0, 8); > +static A9_COMP_GATE(pwm_j, PWM_CLK_J_CTRL, 8, 0); > + > +static A9_COMP_SEL(pwm_k, PWM_CLK_K_CTRL, 9, 0x7, a9_pwm_parents, NULL); > +static A9_COMP_DIV(pwm_k, PWM_CLK_K_CTRL, 0, 8); > +static A9_COMP_GATE(pwm_k, PWM_CLK_K_CTRL, 8, 0); > + > +static A9_COMP_SEL(pwm_l, PWM_CLK_L_CTRL, 9, 0x7, a9_pwm_parents, NULL); > +static A9_COMP_DIV(pwm_l, PWM_CLK_L_CTRL, 0, 8); > +static A9_COMP_GATE(pwm_l, PWM_CLK_L_CTRL, 8, 0); > + > +static A9_COMP_SEL(pwm_m, PWM_CLK_M_CTRL, 9, 0x7, a9_pwm_parents, NULL); > +static A9_COMP_DIV(pwm_m, PWM_CLK_M_CTRL, 0, 8); > +static A9_COMP_GATE(pwm_m, PWM_CLK_M_CTRL, 8, 0); > + > +static A9_COMP_SEL(pwm_n, PWM_CLK_N_CTRL, 9, 0x7, a9_pwm_parents, NULL); > +static A9_COMP_DIV(pwm_n, PWM_CLK_N_CTRL, 0, 8); > +static A9_COMP_GATE(pwm_n, PWM_CLK_N_CTRL, 8, 0); > + > +static const struct clk_parent_data a9_spisg_parents[] = { > + { .fw_name = "xtal", }, > + { .fw_name = "sys", }, > + { .fw_name = "fdiv4", }, > + { .fw_name = "fdiv3", }, > + { .fw_name = "fdiv2", }, > + { .fw_name = "fdiv5", }, > + { .fw_name = "fdiv7", }, > + { .fw_name = "gp0", } > +}; > + > +static A9_COMP_SEL(spisg, SPISG_CLK_CTRL, 9, 0x7, a9_spisg_parents, NULL); > +static A9_COMP_DIV(spisg, SPISG_CLK_CTRL, 0, 6); > +static A9_COMP_GATE(spisg, SPISG_CLK_CTRL, 8, 0); > + > +static A9_COMP_SEL(spisg1, SPISG_CLK_CTRL, 25, 0x7, a9_spisg_parents, NULL); > +static A9_COMP_DIV(spisg1, SPISG_CLK_CTRL, 16, 6); > +static A9_COMP_GATE(spisg1, SPISG_CLK_CTRL, 24, 0); > + > +static A9_COMP_SEL(spisg2, SPISG_CLK_CTRL1, 9, 0x7, a9_spisg_parents, NULL); > +static A9_COMP_DIV(spisg2, SPISG_CLK_CTRL1, 0, 6); > +static A9_COMP_GATE(spisg2, SPISG_CLK_CTRL1, 8, 0); > + > +static const struct clk_parent_data a9_saradc_parents[] = { > + { .fw_name = "xtal", }, > + { .fw_name = "sys", } > +}; > + > +static A9_COMP_SEL(saradc, SAR_CLK_CTRL, 9, 0x7, a9_saradc_parents, NULL); > +static A9_COMP_DIV(saradc, SAR_CLK_CTRL, 0, 8); > +static A9_COMP_GATE(saradc, SAR_CLK_CTRL, 8, 0); > + > +static const struct clk_parent_data a9_amfc_parents[] = { > + { .fw_name = "xtal", }, > + { .fw_name = "sys", }, > + { .fw_name = "fdiv2", }, > + { .fw_name = "fdiv2p5", }, > + { .fw_name = "fdiv3", }, > + { .fw_name = "fdiv4", }, > + { .fw_name = "fdiv5", }, > + { .fw_name = "fdiv7", } > +}; > + > +static A9_COMP_SEL(amfc, AMFC_CLK_CTRL, 9, 0x7, a9_amfc_parents, NULL); > +static A9_COMP_DIV(amfc, AMFC_CLK_CTRL, 0, 6); > +static A9_COMP_GATE(amfc, AMFC_CLK_CTRL, 8, 0); > + > +static const struct clk_parent_data a9_nna_parents[] = { > + { .fw_name = "xtal", }, > + { .fw_name = "fdiv2p5", }, > + { .fw_name = "fdiv4", }, > + { .fw_name = "fdiv3", }, > + { .fw_name = "fdiv5", }, > + { .fw_name = "fdiv2", }, > + { .fw_name = "gp2", }, > + { .fw_name = "hifi", } hifi isn't in the dt bindings. Should this be hifi0 and/or hifi1? > +}; > + > +static A9_COMP_SEL(nna, NNA_CLK_CTRL, 9, 0x7, a9_nna_parents, NULL); > +static A9_COMP_DIV(nna, NNA_CLK_CTRL, 0, 7); > +static A9_COMP_GATE(nna, NNA_CLK_CTRL, 8, 0); > + > +/* Channel 5 and 6 are unconnected. */ > +static u32 a9_usb_250m_parents_val_table[] = { 0, 1, 2, 3, 4, 7 }; > +static const struct clk_parent_data a9_usb_250m_parents[] = { > + { .fw_name = "fdiv4", }, > + { .fw_name = "fdiv3", }, > + { .fw_name = "fdiv5", }, > + { .fw_name = "fdiv2", }, > + { .fw_name = "fdiv7", }, > + { .fw_name = "fdiv2p5", } > +}; > + > +static A9_COMP_SEL(usb_250m, USB_CLK_CTRL, 9, 0x7, a9_usb_250m_parents, > + a9_usb_250m_parents_val_table); > +static A9_COMP_DIV(usb_250m, USB_CLK_CTRL, 0, 7); > +static A9_COMP_GATE(usb_250m, USB_CLK_CTRL, 8, 0); > + > +static const struct clk_parent_data a9_usb_48m_pre_parents[] = { > + { .fw_name = "fdiv4", }, > + { .fw_name = "fdiv3", }, > + { .fw_name = "fdiv5", }, > + { .fw_name = "fdiv2", }, > + { .fw_name = "fdiv7", }, > + { .fw_name = "fdiv2p5", } > +}; > + > +static A9_COMP_SEL(usb_48m_pre, USB_CLK_CTRL, 25, 0x7, a9_usb_48m_pre_parents, > + NULL); > +static A9_COMP_DIV(usb_48m_pre, USB_CLK_CTRL, 16, 7); > +static A9_COMP_GATE(usb_48m_pre, USB_CLK_CTRL, 24, 0); > + > +static const struct clk_parent_data a9_pcie_tl_parents[] = { > + { .fw_name = "fdiv4", }, > + { .fw_name = "fdiv3", }, > + { .fw_name = "fdiv5", }, > + { .fw_name = "fdiv2", }, > + { .fw_name = "fdiv2p5", }, > + { .fw_name = "gp0", }, > + { .fw_name = "sys", }, > + { .fw_name = "xtal", } > +}; > + > +static A9_COMP_SEL(pcie_tl, PCIE_TL_CLK_CTRL, 9, 0x7, a9_pcie_tl_parents, > + NULL); > +static A9_COMP_DIV(pcie_tl, PCIE_TL_CLK_CTRL, 0, 7); > +static A9_COMP_GATE(pcie_tl, PCIE_TL_CLK_CTRL, 8, 0); > + > +static A9_COMP_SEL(pcie1_tl, PCIE_TL_CLK_CTRL, 25, 0x7, a9_pcie_tl_parents, > + NULL); > +static A9_COMP_DIV(pcie1_tl, PCIE_TL_CLK_CTRL, 16, 7); > +static A9_COMP_GATE(pcie1_tl, PCIE_TL_CLK_CTRL, 24, 0); > + > +static const struct clk_parent_data a9_cmpr_parents[] = { > + { .fw_name = "xtal", }, > + { .fw_name = "fdiv2p5", }, > + { .fw_name = "fdiv3", }, > + { .fw_name = "fdiv4", }, > + { .fw_name = "fdiv5", }, > + { .fw_name = "fdiv7", }, > + { .fw_name = "hifi0", }, > + { .fw_name = "gp1", } > +}; > + > +static A9_COMP_SEL(cmpr, CMPR_CLK_CTRL, 25, 0x7, a9_cmpr_parents, NULL); > +static A9_COMP_DIV(cmpr, CMPR_CLK_CTRL, 16, 7); > +static A9_COMP_GATE(cmpr, CMPR_CLK_CTRL, 24, 0); > + > +static const struct clk_parent_data a9_dewarpa_parents[] = { > + { .fw_name = "fdiv2p5", }, > + { .fw_name = "fdiv3", }, > + { .fw_name = "fdiv4", }, > + { .fw_name = "fdiv5", }, > + { .fw_name = "fdiv7", }, > + { .fw_name = "gp0", }, > + { .fw_name = "hifi0", }, > + { .fw_name = "gp1", } > +}; > + > +static A9_COMP_SEL(dewarpa, DEWARP_CLK_CTRL, 9, 0x7, a9_dewarpa_parents, NULL); > +static A9_COMP_DIV(dewarpa, DEWARP_CLK_CTRL, 0, 7); > +static A9_COMP_GATE(dewarpa, DEWARP_CLK_CTRL, 8, 0); > + > +static const struct clk_parent_data a9_sc_parents[] = { > + { .fw_name = "fdiv2", }, > + { .fw_name = "fdiv3", }, > + { .fw_name = "fdiv5", }, > + { .fw_name = "xtal", } > +}; > + > +static A9_COMP_SEL(sc_pre, SC_CLK_CTRL, 9, 0x7, a9_sc_parents, NULL); > +static A9_COMP_DIV(sc_pre, SC_CLK_CTRL, 0, 8); > +static A9_COMP_GATE(sc_pre, SC_CLK_CTRL, 8, 0); > + > +static struct clk_regmap a9_sc = { > + .data = &(struct clk_regmap_div_data) { > + .offset = SC_CLK_CTRL, > + .shift = 16, > + .width = 4, > + }, > + .hw.init = &(struct clk_init_data) { > + .name = "sc", > + .ops = &clk_regmap_divider_ops, > + .parent_hws = (const struct clk_hw *[]) { > + &a9_sc_pre.hw > + }, > + .num_parents = 1, > + .flags = CLK_SET_RATE_PARENT, > + }, You can use CLK_HW_INIT_HWS() here. Brian ^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 10/10] clk: amlogic: Add A9 AO clock controller driver 2026-05-11 12:47 [PATCH 00/10] Add support for A9 family clock controller Jian Hu via B4 Relay ` (8 preceding siblings ...) 2026-05-11 12:47 ` [PATCH 09/10] clk: amlogic: Add A9 peripherals " Jian Hu via B4 Relay @ 2026-05-11 12:47 ` Jian Hu via B4 Relay 2026-05-11 15:45 ` Brian Masney 9 siblings, 1 reply; 17+ messages in thread From: Jian Hu via B4 Relay @ 2026-05-11 12:47 UTC (permalink / raw) To: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Neil Armstrong, Jerome Brunet, Xianwei Zhao, Kevin Hilman, Martin Blumenstingl Cc: linux-kernel, linux-clk, devicetree, linux-amlogic, linux-arm-kernel, Jian Hu From: Jian Hu <jian.hu@amlogic.com> Add the Always-on clock controller driver for the Amlogic A9 SoC family. Signed-off-by: Jian Hu <jian.hu@amlogic.com> --- drivers/clk/meson/Makefile | 2 +- drivers/clk/meson/a9-aoclk.c | 494 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 495 insertions(+), 1 deletion(-) diff --git a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile index 2b5b67b14efc..91af609ce815 100644 --- a/drivers/clk/meson/Makefile +++ b/drivers/clk/meson/Makefile @@ -20,7 +20,7 @@ obj-$(CONFIG_COMMON_CLK_AXG_AUDIO) += axg-audio.o obj-$(CONFIG_COMMON_CLK_A1_PLL) += a1-pll.o obj-$(CONFIG_COMMON_CLK_A1_PERIPHERALS) += a1-peripherals.o obj-$(CONFIG_COMMON_CLK_A9_PLL) += a9-pll.o -obj-$(CONFIG_COMMON_CLK_A9_PERIPHERALS) += a9-peripherals.o +obj-$(CONFIG_COMMON_CLK_A9_PERIPHERALS) += a9-peripherals.o a9-aoclk.o obj-$(CONFIG_COMMON_CLK_C3_PLL) += c3-pll.o obj-$(CONFIG_COMMON_CLK_C3_PERIPHERALS) += c3-peripherals.o obj-$(CONFIG_COMMON_CLK_GXBB) += gxbb.o gxbb-aoclk.o diff --git a/drivers/clk/meson/a9-aoclk.c b/drivers/clk/meson/a9-aoclk.c new file mode 100644 index 000000000000..3c42eaf585d2 --- /dev/null +++ b/drivers/clk/meson/a9-aoclk.c @@ -0,0 +1,494 @@ +// SPDX-License-Identifier: (GPL-2.0-only OR MIT) +/* + * Copyright (C) 2026 Amlogic, Inc. All rights reserved + */ + +#include <linux/clk-provider.h> +#include <linux/platform_device.h> +#include <dt-bindings/clock/amlogic,a9-aoclkc.h> +#include "clk-regmap.h" +#include "clk-dualdiv.h" +#include "meson-clkc-utils.h" + +#define AO_OSCIN_CTRL 0x00 +#define AO_SYS_CLK0 0x04 +#define AO_PWM_CLK_A_CTRL 0x1c +#define AO_PWM_CLK_B_CTRL 0x20 +#define AO_PWM_CLK_C_CTRL 0x24 +#define AO_PWM_CLK_D_CTRL 0x28 +#define AO_PWM_CLK_E_CTRL 0x2c +#define AO_PWM_CLK_F_CTRL 0x30 +#define AO_PWM_CLK_G_CTRL 0x34 +#define AO_CEC_CTRL0 0x38 +#define AO_CEC_CTRL1 0x3c +#define AO_RTC_BY_OSCIN_CTRL0 0x50 +#define AO_RTC_BY_OSCIN_CTRL1 0x54 + +#define A9_COMP_SEL(_name, _reg, _shift, _mask, _pdata) \ + MESON_COMP_SEL(a9_, _name, _reg, _shift, _mask, _pdata, NULL, 0, 0) + +#define A9_COMP_DIV(_name, _reg, _shift, _width) \ + MESON_COMP_DIV(a9_, _name, _reg, _shift, _width, 0, CLK_SET_RATE_PARENT) + +#define A9_COMP_GATE(_name, _reg, _bit) \ + MESON_COMP_GATE(a9_, _name, _reg, _bit, CLK_SET_RATE_PARENT) + +static struct clk_regmap a9_ao_xtal_in = { + .data = &(struct clk_regmap_gate_data){ + .offset = AO_OSCIN_CTRL, + .bit_idx = 3, + }, + .hw.init = &(struct clk_init_data) { + .name = "ao_xtal_in", + .ops = &clk_regmap_gate_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, + .num_parents = 1, + /* + * It may be ao_sys's parent clock, its child clocks mark + * CLK_IS_CRITICAL, So mark CLK_IS_CRITICAL for it. + */ + .flags = CLK_IS_CRITICAL, + }, +}; + +static struct clk_regmap a9_ao_xtal = { + .data = &(struct clk_regmap_mux_data) { + .offset = AO_OSCIN_CTRL, + .mask = 0x1, + .shift = 0, + }, + .hw.init = &(struct clk_init_data){ + .name = "ao_xtal", + .ops = &clk_regmap_mux_ops, + /* ext_32k is from external PAD, do not automatically reparent */ + .parent_data = (const struct clk_parent_data []) { + { .hw = &a9_ao_xtal_in.hw }, + { .fw_name = "ext_32k", }, + }, + .num_parents = 2, + .flags = CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_regmap a9_ao_sys = { + .data = &(struct clk_regmap_mux_data) { + .offset = AO_OSCIN_CTRL, + .mask = 0x1, + .shift = 1, + }, + .hw.init = &(struct clk_init_data){ + .name = "ao_sys", + .ops = &clk_regmap_mux_ops, + .parent_data = (const struct clk_parent_data []) { + { .hw = &a9_ao_xtal.hw }, + { .fw_name = "sys", }, + }, + .num_parents = 2, + .flags = CLK_SET_PARENT_GATE, + }, +}; + +static const struct clk_parent_data a9_ao_pclk_parents = { .hw = &a9_ao_sys.hw }; + +#define A9_AO_PCLK(_name, _bit, _flags) \ + MESON_PCLK(a9_ao_sys_##_name, AO_SYS_CLK0, _bit, \ + &a9_ao_pclk_parents, _flags) + +/* + * A9 integrates a low-power microprocessor (Always-on CPU: AOCPU). Some AO sys + * clocks control the AOCPU modules. Mark the AOCPU-related clocks with + * CLK_IS_CRITICAL to avoid them being disabled and impacting AOCPU functionality. + * AOCPU-related clocks list: + * - clktree + * - rst_ctrl + * - pad + * - irq + * - pwrctrl + * - aocpu + * - sram + */ +static A9_AO_PCLK(i2c3, 0, 0); +static A9_AO_PCLK(rtc_reg, 1, 0); +static A9_AO_PCLK(clktree, 2, CLK_IS_CRITICAL); +static A9_AO_PCLK(rst_ctrl, 3, CLK_IS_CRITICAL); +static A9_AO_PCLK(pad, 4, CLK_IS_CRITICAL); +static A9_AO_PCLK(rtc_dig, 5, 0); +static A9_AO_PCLK(irq, 6, CLK_IS_CRITICAL); +static A9_AO_PCLK(pwrctrl, 7, CLK_IS_CRITICAL); +static A9_AO_PCLK(pwm_a, 8, 0); +static A9_AO_PCLK(pwm_b, 9, 0); +static A9_AO_PCLK(pwm_c, 10, 0); +static A9_AO_PCLK(pwm_d, 11, 0); +static A9_AO_PCLK(pwm_e, 12, 0); +static A9_AO_PCLK(pwm_f, 13, 0); +static A9_AO_PCLK(pwm_g, 14, 0); +static A9_AO_PCLK(i2c_a, 15, 0); +static A9_AO_PCLK(i2c_b, 16, 0); +static A9_AO_PCLK(i2c_c, 17, 0); +static A9_AO_PCLK(i2c_d, 18, 0); +static A9_AO_PCLK(sed, 19, 0); +static A9_AO_PCLK(ir_ctrl, 20, 0); +static A9_AO_PCLK(uart_b, 21, 0); +static A9_AO_PCLK(uart_c, 22, 0); +static A9_AO_PCLK(uart_d, 23, 0); +static A9_AO_PCLK(uart_e, 24, 0); +static A9_AO_PCLK(spisg_0, 25, 0); +static A9_AO_PCLK(rtc_secure, 26, 0); +static A9_AO_PCLK(cec, 27, 0); +static A9_AO_PCLK(aocpu, 28, CLK_IS_CRITICAL); +static A9_AO_PCLK(sram, 29, CLK_IS_CRITICAL); +static A9_AO_PCLK(spisg_1, 30, 0); +static A9_AO_PCLK(spisg_2, 31, 0); + +static const struct clk_parent_data a9_ao_pwm_parents[] = { + { .hw = &a9_ao_xtal.hw }, + { .fw_name = "fdiv5", }, + { .fw_name = "fdiv4", }, + { .fw_name = "fdiv3", } +}; + +static A9_COMP_SEL(ao_pwm_a, AO_PWM_CLK_A_CTRL, 9, 0x7, a9_ao_pwm_parents); +static A9_COMP_DIV(ao_pwm_a, AO_PWM_CLK_A_CTRL, 0, 8); +static A9_COMP_GATE(ao_pwm_a, AO_PWM_CLK_A_CTRL, 8); + +static A9_COMP_SEL(ao_pwm_b, AO_PWM_CLK_B_CTRL, 9, 0x7, a9_ao_pwm_parents); +static A9_COMP_DIV(ao_pwm_b, AO_PWM_CLK_B_CTRL, 0, 8); +static A9_COMP_GATE(ao_pwm_b, AO_PWM_CLK_A_CTRL, 8); + +static A9_COMP_SEL(ao_pwm_c, AO_PWM_CLK_C_CTRL, 9, 0x7, a9_ao_pwm_parents); +static A9_COMP_DIV(ao_pwm_c, AO_PWM_CLK_C_CTRL, 0, 8); +static A9_COMP_GATE(ao_pwm_c, AO_PWM_CLK_C_CTRL, 8); + +static A9_COMP_SEL(ao_pwm_d, AO_PWM_CLK_D_CTRL, 9, 0x7, a9_ao_pwm_parents); +static A9_COMP_DIV(ao_pwm_d, AO_PWM_CLK_D_CTRL, 0, 8); +static A9_COMP_GATE(ao_pwm_d, AO_PWM_CLK_D_CTRL, 8); + +static A9_COMP_SEL(ao_pwm_e, AO_PWM_CLK_E_CTRL, 9, 0x7, a9_ao_pwm_parents); +static A9_COMP_DIV(ao_pwm_e, AO_PWM_CLK_E_CTRL, 0, 8); +static A9_COMP_GATE(ao_pwm_e, AO_PWM_CLK_E_CTRL, 8); + +static A9_COMP_SEL(ao_pwm_f, AO_PWM_CLK_F_CTRL, 9, 0x7, a9_ao_pwm_parents); +static A9_COMP_DIV(ao_pwm_f, AO_PWM_CLK_F_CTRL, 0, 8); +static A9_COMP_GATE(ao_pwm_f, AO_PWM_CLK_F_CTRL, 8); + +static A9_COMP_SEL(ao_pwm_g, AO_PWM_CLK_G_CTRL, 9, 0x7, a9_ao_pwm_parents); +static A9_COMP_DIV(ao_pwm_g, AO_PWM_CLK_G_CTRL, 0, 8); +static A9_COMP_GATE(ao_pwm_g, AO_PWM_CLK_G_CTRL, 8); + +static struct clk_regmap a9_ao_rtc_dualdiv_in = { + .data = &(struct clk_regmap_gate_data){ + .offset = AO_RTC_BY_OSCIN_CTRL0, + .bit_idx = 31, + }, + .hw.init = &(struct clk_init_data) { + .name = "ao_rtc_duandiv_in", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &a9_ao_xtal.hw + }, + .num_parents = 1, + }, +}; + +static const struct meson_clk_dualdiv_param a9_ao_dualdiv_table[] = { + { 733, 732, 8, 11, 1 }, + { /* sentinel */ } +}; + +static struct clk_regmap a9_ao_rtc_dualdiv_div = { + .data = &(struct meson_clk_dualdiv_data){ + .n1 = { + .reg_off = AO_RTC_BY_OSCIN_CTRL0, + .shift = 0, + .width = 12, + }, + .n2 = { + .reg_off = AO_RTC_BY_OSCIN_CTRL0, + .shift = 12, + .width = 12, + }, + .m1 = { + .reg_off = AO_RTC_BY_OSCIN_CTRL1, + .shift = 0, + .width = 12, + }, + .m2 = { + .reg_off = AO_RTC_BY_OSCIN_CTRL1, + .shift = 12, + .width = 12, + }, + .dual = { + .reg_off = AO_RTC_BY_OSCIN_CTRL0, + .shift = 28, + .width = 1, + }, + .table = a9_ao_dualdiv_table, + }, + .hw.init = &(struct clk_init_data){ + .name = "a9_ao_rtc_dualdiv_div", + .ops = &meson_clk_dualdiv_ops, + .parent_hws = (const struct clk_hw *[]) { + &a9_ao_rtc_dualdiv_in.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap a9_ao_rtc_dualdiv_sel = { + .data = &(struct clk_regmap_mux_data) { + .offset = AO_RTC_BY_OSCIN_CTRL1, + .mask = 0x1, + .shift = 24, + }, + .hw.init = &(struct clk_init_data){ + .name = "ao_rtc_dualdiv_sel", + .ops = &clk_regmap_mux_ops, + .parent_hws = (const struct clk_hw *[]) { + &a9_ao_rtc_dualdiv_div.hw, + &a9_ao_rtc_dualdiv_in.hw, + }, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap a9_ao_rtc_dualdiv = { + .data = &(struct clk_regmap_gate_data){ + .offset = AO_RTC_BY_OSCIN_CTRL0, + .bit_idx = 30, + }, + .hw.init = &(struct clk_init_data) { + .name = "ao_rtc_dualdiv", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &a9_ao_rtc_dualdiv_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap a9_ao_rtc = { + .data = &(struct clk_regmap_mux_data) { + .offset = AO_RTC_BY_OSCIN_CTRL1, + .mask = 0x1, + .shift = 30, + }, + .hw.init = &(struct clk_init_data){ + .name = "ao_rtc", + .ops = &clk_regmap_mux_ops, + .parent_hws = (const struct clk_hw *[]) { + &a9_ao_xtal.hw, + &a9_ao_rtc_dualdiv.hw, + }, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap a9_ao_cec_dualdiv_in = { + .data = &(struct clk_regmap_gate_data){ + .offset = AO_CEC_CTRL0, + .bit_idx = 31, + }, + .hw.init = &(struct clk_init_data) { + .name = "ao_cec_dualdiv_in", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &a9_ao_xtal.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap a9_ao_cec_dualdiv_div = { + .data = &(struct meson_clk_dualdiv_data){ + .n1 = { + .reg_off = AO_CEC_CTRL0, + .shift = 0, + .width = 12, + }, + .n2 = { + .reg_off = AO_CEC_CTRL0, + .shift = 12, + .width = 12, + }, + .m1 = { + .reg_off = AO_CEC_CTRL1, + .shift = 0, + .width = 12, + }, + .m2 = { + .reg_off = AO_CEC_CTRL1, + .shift = 12, + .width = 12, + }, + .dual = { + .reg_off = AO_CEC_CTRL0, + .shift = 28, + .width = 1, + }, + .table = a9_ao_dualdiv_table, + }, + .hw.init = &(struct clk_init_data){ + .name = "ao_cec_dualdiv_div", + .ops = &meson_clk_dualdiv_ops, + .parent_hws = (const struct clk_hw *[]) { + &a9_ao_cec_dualdiv_in.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap a9_ao_cec_dualdiv_sel = { + .data = &(struct clk_regmap_mux_data) { + .offset = AO_CEC_CTRL1, + .mask = 0x1, + .shift = 24, + }, + .hw.init = &(struct clk_init_data){ + .name = "ao_cec_dualdiv_sel", + .ops = &clk_regmap_mux_ops, + .parent_hws = (const struct clk_hw *[]) { + &a9_ao_cec_dualdiv_div.hw, + &a9_ao_cec_dualdiv_in.hw, + }, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap a9_ao_cec_dualdiv = { + .data = &(struct clk_regmap_gate_data){ + .offset = AO_CEC_CTRL0, + .bit_idx = 30, + }, + .hw.init = &(struct clk_init_data){ + .name = "ao_cec_dualdiv", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &a9_ao_cec_dualdiv_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap a9_ao_cec = { + .data = &(struct clk_regmap_mux_data) { + .offset = AO_CEC_CTRL1, + .mask = 0x1, + .shift = 30, + }, + .hw.init = &(struct clk_init_data){ + .name = "ao_cec", + .ops = &clk_regmap_mux_ops, + .parent_hws = (const struct clk_hw *[]) { + &a9_ao_cec_dualdiv.hw, + &a9_ao_rtc.hw, + }, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_hw *a9_ao_hw_clks[] = { + [CLKID_AO_XTAL_IN] = &a9_ao_xtal_in.hw, + [CLKID_AO_XTAL] = &a9_ao_xtal.hw, + [CLKID_AO_SYS] = &a9_ao_sys.hw, + [CLKID_AO_SYS_I3C] = &a9_ao_sys_i2c3.hw, + [CLKID_AO_SYS_RTC_REG] = &a9_ao_sys_rtc_reg.hw, + [CLKID_AO_SYS_CLKTREE] = &a9_ao_sys_clktree.hw, + [CLKID_AO_SYS_RST_CTRL] = &a9_ao_sys_rst_ctrl.hw, + [CLKID_AO_SYS_PAD] = &a9_ao_sys_pad.hw, + [CLKID_AO_SYS_RTC_DIG] = &a9_ao_sys_rtc_dig.hw, + [CLKID_AO_SYS_IRQ] = &a9_ao_sys_irq.hw, + [CLKID_AO_SYS_PWRCTRL] = &a9_ao_sys_pwrctrl.hw, + [CLKID_AO_SYS_PWM_A] = &a9_ao_sys_pwm_a.hw, + [CLKID_AO_SYS_PWM_B] = &a9_ao_sys_pwm_b.hw, + [CLKID_AO_SYS_PWM_C] = &a9_ao_sys_pwm_c.hw, + [CLKID_AO_SYS_PWM_D] = &a9_ao_sys_pwm_d.hw, + [CLKID_AO_SYS_PWM_E] = &a9_ao_sys_pwm_e.hw, + [CLKID_AO_SYS_PWM_F] = &a9_ao_sys_pwm_f.hw, + [CLKID_AO_SYS_PWM_G] = &a9_ao_sys_pwm_g.hw, + [CLKID_AO_SYS_I2C_A] = &a9_ao_sys_i2c_a.hw, + [CLKID_AO_SYS_I2C_B] = &a9_ao_sys_i2c_b.hw, + [CLKID_AO_SYS_I2C_C] = &a9_ao_sys_i2c_c.hw, + [CLKID_AO_SYS_I2C_D] = &a9_ao_sys_i2c_d.hw, + [CLKID_AO_SYS_SED] = &a9_ao_sys_sed.hw, + [CLKID_AO_SYS_IR_CTRL] = &a9_ao_sys_ir_ctrl.hw, + [CLKID_AO_SYS_UART_B] = &a9_ao_sys_uart_b.hw, + [CLKID_AO_SYS_UART_C] = &a9_ao_sys_uart_c.hw, + [CLKID_AO_SYS_UART_D] = &a9_ao_sys_uart_d.hw, + [CLKID_AO_SYS_UART_E] = &a9_ao_sys_uart_e.hw, + [CLKID_AO_SYS_SPISG_0] = &a9_ao_sys_spisg_0.hw, + [CLKID_AO_SYS_RTC_SECURE] = &a9_ao_sys_rtc_secure.hw, + [CLKID_AO_SYS_CEC] = &a9_ao_sys_cec.hw, + [CLKID_AO_SYS_AOCPU] = &a9_ao_sys_aocpu.hw, + [CLKID_AO_SYS_SRAM] = &a9_ao_sys_sram.hw, + [CLKID_AO_SYS_SPISG_1] = &a9_ao_sys_spisg_1.hw, + [CLKID_AO_SYS_SPISG_2] = &a9_ao_sys_spisg_2.hw, + [CLKID_AO_PWM_A_SEL] = &a9_ao_pwm_a_sel.hw, + [CLKID_AO_PWM_A_DIV] = &a9_ao_pwm_a_div.hw, + [CLKID_AO_PWM_A] = &a9_ao_pwm_a.hw, + [CLKID_AO_PWM_B_SEL] = &a9_ao_pwm_b_sel.hw, + [CLKID_AO_PWM_B_DIV] = &a9_ao_pwm_b_div.hw, + [CLKID_AO_PWM_B] = &a9_ao_pwm_b.hw, + [CLKID_AO_PWM_C_SEL] = &a9_ao_pwm_c_sel.hw, + [CLKID_AO_PWM_C_DIV] = &a9_ao_pwm_c_div.hw, + [CLKID_AO_PWM_C] = &a9_ao_pwm_c.hw, + [CLKID_AO_PWM_D_SEL] = &a9_ao_pwm_d_sel.hw, + [CLKID_AO_PWM_D_DIV] = &a9_ao_pwm_d_div.hw, + [CLKID_AO_PWM_D] = &a9_ao_pwm_d.hw, + [CLKID_AO_PWM_E_SEL] = &a9_ao_pwm_e_sel.hw, + [CLKID_AO_PWM_E_DIV] = &a9_ao_pwm_e_div.hw, + [CLKID_AO_PWM_E] = &a9_ao_pwm_e.hw, + [CLKID_AO_PWM_F_SEL] = &a9_ao_pwm_f_sel.hw, + [CLKID_AO_PWM_F_DIV] = &a9_ao_pwm_f_div.hw, + [CLKID_AO_PWM_F] = &a9_ao_pwm_f.hw, + [CLKID_AO_PWM_G_SEL] = &a9_ao_pwm_g_sel.hw, + [CLKID_AO_PWM_G_DIV] = &a9_ao_pwm_g_div.hw, + [CLKID_AO_PWM_G] = &a9_ao_pwm_g.hw, + [CLKID_AO_RTC_DUALDIV_IN] = &a9_ao_rtc_dualdiv_in.hw, + [CLKID_AO_RTC_DUALDIV_DIV] = &a9_ao_rtc_dualdiv_div.hw, + [CLKID_AO_RTC_DUALDIV_SEL] = &a9_ao_rtc_dualdiv_sel.hw, + [CLKID_AO_RTC_DUALDIV] = &a9_ao_rtc_dualdiv.hw, + [CLKID_AO_RTC] = &a9_ao_rtc.hw, + [CLKID_AO_CEC_DUALDIV_IN] = &a9_ao_cec_dualdiv_in.hw, + [CLKID_AO_CEC_DUALDIV_DIV] = &a9_ao_cec_dualdiv_div.hw, + [CLKID_AO_CEC_DUALDIV_SEL] = &a9_ao_cec_dualdiv_sel.hw, + [CLKID_AO_CEC_DUALDIV] = &a9_ao_cec_dualdiv.hw, + [CLKID_AO_CEC] = &a9_ao_cec.hw, +}; + +static const struct meson_clkc_data a9_ao_clkc_data = { + .hw_clks = { + .hws = a9_ao_hw_clks, + .num = ARRAY_SIZE(a9_ao_hw_clks), + }, +}; + +static const struct of_device_id a9_ao_clkc_match_table[] = { + { + .compatible = "amlogic,a9-aoclkc", + .data = &a9_ao_clkc_data, + }, + { } +}; +MODULE_DEVICE_TABLE(of, a9_ao_clkc_match_table); + +static struct platform_driver a9_ao_clkc_driver = { + .probe = meson_clkc_mmio_probe, + .driver = { + .name = "a9-aoclkc", + .of_match_table = a9_ao_clkc_match_table, + }, +}; +module_platform_driver(a9_ao_clkc_driver); + +MODULE_DESCRIPTION("Amlogic A9 Always-ON Clock Controller driver"); +MODULE_AUTHOR("Jian Hu <jian.hu@amlogic.com>"); +MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS("CLK_MESON"); -- 2.47.1 ^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [PATCH 10/10] clk: amlogic: Add A9 AO clock controller driver 2026-05-11 12:47 ` [PATCH 10/10] clk: amlogic: Add A9 AO " Jian Hu via B4 Relay @ 2026-05-11 15:45 ` Brian Masney 0 siblings, 0 replies; 17+ messages in thread From: Brian Masney @ 2026-05-11 15:45 UTC (permalink / raw) To: jian.hu Cc: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Neil Armstrong, Jerome Brunet, Xianwei Zhao, Kevin Hilman, Martin Blumenstingl, linux-kernel, linux-clk, devicetree, linux-amlogic, linux-arm-kernel Hi Jian, On Mon, May 11, 2026 at 08:47:32PM +0800, Jian Hu via B4 Relay wrote: > From: Jian Hu <jian.hu@amlogic.com> > > Add the Always-on clock controller driver for the Amlogic A9 SoC family. > > Signed-off-by: Jian Hu <jian.hu@amlogic.com> I'll only flag new things that I spot here that weren't mentioned in the other patches I reviewed in this series. > --- > drivers/clk/meson/Makefile | 2 +- > drivers/clk/meson/a9-aoclk.c | 494 +++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 495 insertions(+), 1 deletion(-) > > diff --git a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile > index 2b5b67b14efc..91af609ce815 100644 > --- a/drivers/clk/meson/Makefile > +++ b/drivers/clk/meson/Makefile > @@ -20,7 +20,7 @@ obj-$(CONFIG_COMMON_CLK_AXG_AUDIO) += axg-audio.o > obj-$(CONFIG_COMMON_CLK_A1_PLL) += a1-pll.o > obj-$(CONFIG_COMMON_CLK_A1_PERIPHERALS) += a1-peripherals.o > obj-$(CONFIG_COMMON_CLK_A9_PLL) += a9-pll.o > -obj-$(CONFIG_COMMON_CLK_A9_PERIPHERALS) += a9-peripherals.o > +obj-$(CONFIG_COMMON_CLK_A9_PERIPHERALS) += a9-peripherals.o a9-aoclk.o > obj-$(CONFIG_COMMON_CLK_C3_PLL) += c3-pll.o > obj-$(CONFIG_COMMON_CLK_C3_PERIPHERALS) += c3-peripherals.o > obj-$(CONFIG_COMMON_CLK_GXBB) += gxbb.o gxbb-aoclk.o > diff --git a/drivers/clk/meson/a9-aoclk.c b/drivers/clk/meson/a9-aoclk.c > new file mode 100644 > index 000000000000..3c42eaf585d2 > --- /dev/null > +++ b/drivers/clk/meson/a9-aoclk.c > @@ -0,0 +1,494 @@ > +// SPDX-License-Identifier: (GPL-2.0-only OR MIT) > +/* > + * Copyright (C) 2026 Amlogic, Inc. All rights reserved > + */ > + > +#include <linux/clk-provider.h> > +#include <linux/platform_device.h> > +#include <dt-bindings/clock/amlogic,a9-aoclkc.h> > +#include "clk-regmap.h" > +#include "clk-dualdiv.h" > +#include "meson-clkc-utils.h" > + > +#define AO_OSCIN_CTRL 0x00 > +#define AO_SYS_CLK0 0x04 > +#define AO_PWM_CLK_A_CTRL 0x1c > +#define AO_PWM_CLK_B_CTRL 0x20 > +#define AO_PWM_CLK_C_CTRL 0x24 > +#define AO_PWM_CLK_D_CTRL 0x28 > +#define AO_PWM_CLK_E_CTRL 0x2c > +#define AO_PWM_CLK_F_CTRL 0x30 > +#define AO_PWM_CLK_G_CTRL 0x34 > +#define AO_CEC_CTRL0 0x38 > +#define AO_CEC_CTRL1 0x3c > +#define AO_RTC_BY_OSCIN_CTRL0 0x50 > +#define AO_RTC_BY_OSCIN_CTRL1 0x54 > + > +#define A9_COMP_SEL(_name, _reg, _shift, _mask, _pdata) \ > + MESON_COMP_SEL(a9_, _name, _reg, _shift, _mask, _pdata, NULL, 0, 0) > + > +#define A9_COMP_DIV(_name, _reg, _shift, _width) \ > + MESON_COMP_DIV(a9_, _name, _reg, _shift, _width, 0, CLK_SET_RATE_PARENT) > + > +#define A9_COMP_GATE(_name, _reg, _bit) \ > + MESON_COMP_GATE(a9_, _name, _reg, _bit, CLK_SET_RATE_PARENT) > + > +static struct clk_regmap a9_ao_xtal_in = { > + .data = &(struct clk_regmap_gate_data){ > + .offset = AO_OSCIN_CTRL, > + .bit_idx = 3, > + }, > + .hw.init = &(struct clk_init_data) { > + .name = "ao_xtal_in", > + .ops = &clk_regmap_gate_ops, > + .parent_data = &(const struct clk_parent_data) { > + .fw_name = "xtal", > + }, > + .num_parents = 1, > + /* > + * It may be ao_sys's parent clock, its child clocks mark > + * CLK_IS_CRITICAL, So mark CLK_IS_CRITICAL for it. > + */ > + .flags = CLK_IS_CRITICAL, > + }, > +}; > + > +static struct clk_regmap a9_ao_xtal = { > + .data = &(struct clk_regmap_mux_data) { > + .offset = AO_OSCIN_CTRL, > + .mask = 0x1, > + .shift = 0, > + }, > + .hw.init = &(struct clk_init_data){ > + .name = "ao_xtal", > + .ops = &clk_regmap_mux_ops, > + /* ext_32k is from external PAD, do not automatically reparent */ > + .parent_data = (const struct clk_parent_data []) { > + { .hw = &a9_ao_xtal_in.hw }, > + { .fw_name = "ext_32k", }, > + }, > + .num_parents = 2, > + .flags = CLK_SET_RATE_NO_REPARENT, > + }, > +}; > + > +static struct clk_regmap a9_ao_sys = { > + .data = &(struct clk_regmap_mux_data) { > + .offset = AO_OSCIN_CTRL, > + .mask = 0x1, > + .shift = 1, > + }, > + .hw.init = &(struct clk_init_data){ > + .name = "ao_sys", > + .ops = &clk_regmap_mux_ops, > + .parent_data = (const struct clk_parent_data []) { > + { .hw = &a9_ao_xtal.hw }, > + { .fw_name = "sys", }, > + }, > + .num_parents = 2, > + .flags = CLK_SET_PARENT_GATE, > + }, > +}; > + > +static const struct clk_parent_data a9_ao_pclk_parents = { .hw = &a9_ao_sys.hw }; > + > +#define A9_AO_PCLK(_name, _bit, _flags) \ > + MESON_PCLK(a9_ao_sys_##_name, AO_SYS_CLK0, _bit, \ > + &a9_ao_pclk_parents, _flags) > + > +/* > + * A9 integrates a low-power microprocessor (Always-on CPU: AOCPU). Some AO sys > + * clocks control the AOCPU modules. Mark the AOCPU-related clocks with > + * CLK_IS_CRITICAL to avoid them being disabled and impacting AOCPU functionality. > + * AOCPU-related clocks list: > + * - clktree > + * - rst_ctrl > + * - pad > + * - irq > + * - pwrctrl > + * - aocpu > + * - sram > + */ > +static A9_AO_PCLK(i2c3, 0, 0); > +static A9_AO_PCLK(rtc_reg, 1, 0); > +static A9_AO_PCLK(clktree, 2, CLK_IS_CRITICAL); > +static A9_AO_PCLK(rst_ctrl, 3, CLK_IS_CRITICAL); > +static A9_AO_PCLK(pad, 4, CLK_IS_CRITICAL); > +static A9_AO_PCLK(rtc_dig, 5, 0); > +static A9_AO_PCLK(irq, 6, CLK_IS_CRITICAL); > +static A9_AO_PCLK(pwrctrl, 7, CLK_IS_CRITICAL); > +static A9_AO_PCLK(pwm_a, 8, 0); > +static A9_AO_PCLK(pwm_b, 9, 0); > +static A9_AO_PCLK(pwm_c, 10, 0); > +static A9_AO_PCLK(pwm_d, 11, 0); > +static A9_AO_PCLK(pwm_e, 12, 0); > +static A9_AO_PCLK(pwm_f, 13, 0); > +static A9_AO_PCLK(pwm_g, 14, 0); > +static A9_AO_PCLK(i2c_a, 15, 0); > +static A9_AO_PCLK(i2c_b, 16, 0); > +static A9_AO_PCLK(i2c_c, 17, 0); > +static A9_AO_PCLK(i2c_d, 18, 0); > +static A9_AO_PCLK(sed, 19, 0); > +static A9_AO_PCLK(ir_ctrl, 20, 0); > +static A9_AO_PCLK(uart_b, 21, 0); > +static A9_AO_PCLK(uart_c, 22, 0); > +static A9_AO_PCLK(uart_d, 23, 0); > +static A9_AO_PCLK(uart_e, 24, 0); > +static A9_AO_PCLK(spisg_0, 25, 0); > +static A9_AO_PCLK(rtc_secure, 26, 0); > +static A9_AO_PCLK(cec, 27, 0); > +static A9_AO_PCLK(aocpu, 28, CLK_IS_CRITICAL); > +static A9_AO_PCLK(sram, 29, CLK_IS_CRITICAL); > +static A9_AO_PCLK(spisg_1, 30, 0); > +static A9_AO_PCLK(spisg_2, 31, 0); > + > +static const struct clk_parent_data a9_ao_pwm_parents[] = { > + { .hw = &a9_ao_xtal.hw }, > + { .fw_name = "fdiv5", }, > + { .fw_name = "fdiv4", }, > + { .fw_name = "fdiv3", } > +}; > + > +static A9_COMP_SEL(ao_pwm_a, AO_PWM_CLK_A_CTRL, 9, 0x7, a9_ao_pwm_parents); > +static A9_COMP_DIV(ao_pwm_a, AO_PWM_CLK_A_CTRL, 0, 8); > +static A9_COMP_GATE(ao_pwm_a, AO_PWM_CLK_A_CTRL, 8); > + > +static A9_COMP_SEL(ao_pwm_b, AO_PWM_CLK_B_CTRL, 9, 0x7, a9_ao_pwm_parents); > +static A9_COMP_DIV(ao_pwm_b, AO_PWM_CLK_B_CTRL, 0, 8); > +static A9_COMP_GATE(ao_pwm_b, AO_PWM_CLK_A_CTRL, 8); Should this be AO_PWM_CLK_B_CTRL ? > + > +static A9_COMP_SEL(ao_pwm_c, AO_PWM_CLK_C_CTRL, 9, 0x7, a9_ao_pwm_parents); > +static A9_COMP_DIV(ao_pwm_c, AO_PWM_CLK_C_CTRL, 0, 8); > +static A9_COMP_GATE(ao_pwm_c, AO_PWM_CLK_C_CTRL, 8); > + > +static A9_COMP_SEL(ao_pwm_d, AO_PWM_CLK_D_CTRL, 9, 0x7, a9_ao_pwm_parents); > +static A9_COMP_DIV(ao_pwm_d, AO_PWM_CLK_D_CTRL, 0, 8); > +static A9_COMP_GATE(ao_pwm_d, AO_PWM_CLK_D_CTRL, 8); > + > +static A9_COMP_SEL(ao_pwm_e, AO_PWM_CLK_E_CTRL, 9, 0x7, a9_ao_pwm_parents); > +static A9_COMP_DIV(ao_pwm_e, AO_PWM_CLK_E_CTRL, 0, 8); > +static A9_COMP_GATE(ao_pwm_e, AO_PWM_CLK_E_CTRL, 8); > + > +static A9_COMP_SEL(ao_pwm_f, AO_PWM_CLK_F_CTRL, 9, 0x7, a9_ao_pwm_parents); > +static A9_COMP_DIV(ao_pwm_f, AO_PWM_CLK_F_CTRL, 0, 8); > +static A9_COMP_GATE(ao_pwm_f, AO_PWM_CLK_F_CTRL, 8); > + > +static A9_COMP_SEL(ao_pwm_g, AO_PWM_CLK_G_CTRL, 9, 0x7, a9_ao_pwm_parents); > +static A9_COMP_DIV(ao_pwm_g, AO_PWM_CLK_G_CTRL, 0, 8); > +static A9_COMP_GATE(ao_pwm_g, AO_PWM_CLK_G_CTRL, 8); > + > +static struct clk_regmap a9_ao_rtc_dualdiv_in = { > + .data = &(struct clk_regmap_gate_data){ > + .offset = AO_RTC_BY_OSCIN_CTRL0, > + .bit_idx = 31, > + }, > + .hw.init = &(struct clk_init_data) { > + .name = "ao_rtc_duandiv_in", s/duandiv/dualdiv/ ? Brian ^ permalink raw reply [flat|nested] 17+ messages in thread
end of thread, other threads:[~2026-05-11 15:47 UTC | newest] Thread overview: 17+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-05-11 12:47 [PATCH 00/10] Add support for A9 family clock controller Jian Hu via B4 Relay 2026-05-11 12:47 ` [PATCH 01/10] dt-bindings: clock: Add Amlogic A9 SCMI " Jian Hu via B4 Relay 2026-05-11 12:47 ` [PATCH 02/10] dt-bindings: clock: Add Amlogic A9 PLL " Jian Hu via B4 Relay 2026-05-11 12:47 ` [PATCH 03/10] dt-bindings: clock: Add Amlogic A9 peripherals " Jian Hu via B4 Relay 2026-05-11 12:47 ` [PATCH 04/10] dt-bindings: clock: Add Amlogic A9 AO " Jian Hu via B4 Relay 2026-05-11 12:47 ` [PATCH 05/10] clk: amlogic: PLL l_detect signal supports active-high configuration Jian Hu via B4 Relay 2026-05-11 15:47 ` Brian Masney 2026-05-11 12:47 ` [PATCH 06/10] clk: amlogic: PLL reset signal supports active-low configuration Jian Hu via B4 Relay 2026-05-11 15:21 ` Brian Masney 2026-05-11 12:47 ` [PATCH 07/10] clk: amlogic: Support POWER_OF_TWO for PLL pre-divider Jian Hu via B4 Relay 2026-05-11 15:23 ` Brian Masney 2026-05-11 12:47 ` [PATCH 08/10] clk: amlogic: Add A9 PLL clock controller driver Jian Hu via B4 Relay 2026-05-11 15:36 ` Brian Masney 2026-05-11 12:47 ` [PATCH 09/10] clk: amlogic: Add A9 peripherals " Jian Hu via B4 Relay 2026-05-11 15:42 ` Brian Masney 2026-05-11 12:47 ` [PATCH 10/10] clk: amlogic: Add A9 AO " Jian Hu via B4 Relay 2026-05-11 15:45 ` Brian Masney
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox