* [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; 21+ 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] 21+ 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; 21+ 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] 21+ 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-12 4:18 ` sashiko-bot
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, 1 reply; 21+ 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] 21+ 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; 21+ 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] 21+ 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; 21+ 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] 21+ 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; 21+ 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] 21+ 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-12 4:48 ` sashiko-bot
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, 2 replies; 21+ 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] 21+ 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; 21+ 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] 21+ 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-12 5:56 ` sashiko-bot
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, 2 replies; 21+ 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] 21+ 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-12 6:18 ` sashiko-bot
2026-05-11 12:47 ` [PATCH 10/10] clk: amlogic: Add A9 AO " Jian Hu via B4 Relay
9 siblings, 2 replies; 21+ 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] 21+ 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; 21+ 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] 21+ 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
2026-05-12 4:48 ` sashiko-bot
1 sibling, 0 replies; 21+ 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] 21+ 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; 21+ 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] 21+ 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
2026-05-12 5:56 ` sashiko-bot
1 sibling, 0 replies; 21+ 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] 21+ 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
2026-05-12 6:18 ` sashiko-bot
1 sibling, 0 replies; 21+ 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] 21+ 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; 21+ 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] 21+ 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; 21+ 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] 21+ messages in thread
* Re: [PATCH 02/10] dt-bindings: clock: Add Amlogic A9 PLL clock controller
2026-05-11 12:47 ` [PATCH 02/10] dt-bindings: clock: Add Amlogic A9 PLL " Jian Hu via B4 Relay
@ 2026-05-12 4:18 ` sashiko-bot
0 siblings, 0 replies; 21+ messages in thread
From: sashiko-bot @ 2026-05-12 4:18 UTC (permalink / raw)
To: Jian Hu via B4 Relay; +Cc: robh, devicetree, krzk+dt, conor+dt
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] The schema conditional block for MCLK PLLs fails to enforce the required second clock input, allowing incomplete device tree nodes to pass validation.
--
commit 5fa007b81417dc37662d2d766cd8ecfc23758d15
Author: Jian Hu <jian.hu@amlogic.com>
dt-bindings: clock: Add Amlogic A9 PLL clock controller
This commit adds the PLL clock controller device tree bindings for the
Amlogic A9 SoC family.
> 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
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/amlogic,a9-pll-clkc.yaml
[ ... ]
> + 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
[ ... ]
> +allOf:
> + - if:
> + properties:
> + compatible:
> + contains:
> + enum:
> + - amlogic,a9-mclk0-pll
> + - amlogic,a9-mclk1-pll
> +
> + then:
> + properties:
> + clocks:
> + maxItems: 3
> +
> + clock-names:
> + maxItems: 3
Does this conditional block also need to specify minItems: 2 for the clocks
and clock-names properties?
The global property definition describes the second clock as a fixed input
clock source without the (optional) designation given to the third clock.
Since the global minItems is 1, omitting a stricter minItems constraint
here causes a schema validation regression where an incomplete device tree
node specifying only a single clock for an MCLK PLL will silently pass,
even though it is missing the mandatory second input.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260511-b4-a9_clk-v1-0-41cb4071b7c9@amlogic.com?part=2
^ permalink raw reply [flat|nested] 21+ 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
@ 2026-05-12 4:48 ` sashiko-bot
1 sibling, 0 replies; 21+ messages in thread
From: sashiko-bot @ 2026-05-12 4:48 UTC (permalink / raw)
To: Jian Hu via B4 Relay; +Cc: robh, conor+dt, devicetree, krzk+dt
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] The `meson_clk_pll_disable` function was not updated to handle the new `CLK_MESON_PLL_RST_ACTIVE_LOW` flag, causing it to incorrectly de-assert the reset signal instead of asserting it.
- [Medium] The flag name documented in the commit message does not match the actual code implementation.
--
commit c5af3b10e7a77c9b06f4a72f2dacfc47fec10acf
Author: Jian Hu <jian.hu@amlogic.com>
clk: amlogic: PLL reset signal supports active-low configuration
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.
> Add the flag 'CLK_MESON_PLL_RST_N' to indicate that the PLL reset signal
> is active-low.
This isn't a bug, but the commit message says 'CLK_MESON_PLL_RST_N' while
the code defines CLK_MESON_PLL_RST_ACTIVE_LOW. Could the commit message
be updated to match the code?
> diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c
> index 5a0bd75f85a92..8568ad6ba7b6e 100644
> --- a/drivers/clk/meson/clk-pll.c
> +++ b/drivers/clk/meson/clk-pll.c
[ ... ]
> @@ -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);
> + }
Since active-low PLLs use 0 to assert the reset here, does
meson_clk_pll_disable() also need to be updated to respect the
CLK_MESON_PLL_RST_ACTIVE_LOW flag?
Currently it unconditionally writes 1 to assert reset:
drivers/clk/meson/clk-pll.c:meson_clk_pll_disable() {
...
/* Put the pll is in reset */
if (MESON_PARM_APPLICABLE(&pll->rst))
meson_parm_write(clk->map, &pll->rst, 1);
...
}
If this is an active-low PLL, wouldn't writing 1 de-assert the reset when
the clock is disabled, potentially causing hardware state inconsistencies?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260511-b4-a9_clk-v1-0-41cb4071b7c9@amlogic.com?part=6
^ permalink raw reply [flat|nested] 21+ 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
@ 2026-05-12 5:56 ` sashiko-bot
1 sibling, 0 replies; 21+ messages in thread
From: sashiko-bot @ 2026-05-12 5:56 UTC (permalink / raw)
To: Jian Hu via B4 Relay; +Cc: robh, krzk+dt, conor+dt, devicetree
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] The new driver file `drivers/clk/meson/a9-pll.c` uses module-specific macros but fails to include `<linux/module.h>`.
--
commit 497c46fd6ed69111b1539ecfa46cd63980fab5e1
Author: Jian Hu <jian.hu@amlogic.com>
clk: amlogic: Add A9 PLL clock controller driver
This commit adds the PLL clock controller driver for the Amlogic A9 SoC
family.
> diff --git a/drivers/clk/meson/a9-pll.c b/drivers/clk/meson/a9-pll.c
> new file mode 100644
> index 0000000000000..84b591c3afff5
> --- /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"
[ ... ]
> +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");
Should linux/module.h be included in this file since it uses several
module-specific macros?
Relying on implicit inclusion via other headers like linux/platform_device.h
can sometimes lead to build failures on different architectures or in future
kernel versions if header dependencies change.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260511-b4-a9_clk-v1-0-41cb4071b7c9@amlogic.com?part=8
^ permalink raw reply [flat|nested] 21+ 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
@ 2026-05-12 6:18 ` sashiko-bot
1 sibling, 0 replies; 21+ messages in thread
From: sashiko-bot @ 2026-05-12 6:18 UTC (permalink / raw)
To: Jian Hu via B4 Relay; +Cc: krzk+dt, conor+dt, devicetree, robh
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [High] Missing multiplexer value table for `usb_48m_pre` clock
- [High] Register bit overlap between `gen` clock divider and gate
- [High] Incorrect parent clock selector referenced by `hdmitx1_pixel`
--
commit 4a10654bfda3abb70d26d386a44e76675278fccb
Author: Jian Hu <jian.hu@amlogic.com>
clk: amlogic: Add A9 peripherals clock controller driver
Add the peripherals clock controller driver for the Amlogic A9 SoC family.
> diff --git a/drivers/clk/meson/a9-peripherals.c b/drivers/clk/meson/a9-peripherals.c
> new file mode 100644
> --- /dev/null
> +++ b/drivers/clk/meson/a9-peripherals.c
[ ... ]
> /* 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 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);
^^^^
Since channels 5 and 6 are unconnected, should this macro use a value table
similar to a9_usb_250m_parents_val_table?
Passing NULL might cause the framework to write the unconnected index 5 for
the fdiv2p5 clock, potentially silencing the clock output instead of
selecting index 7.
[ ... ]
> 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);
^^
Could this cause a register bit overlap?
The divider is configured to be 12 bits wide starting at bit 0, which means
it occupies bits 0 through 11. However, the clock gate is also defined at
bit 11 in the same register.
Writing to the divider might inadvertently toggle the clock gate, and
toggling the gate could corrupt the most significant bit of the divider.
[ ... ]
> 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
^^^^^^^^^^^^^^^^^^^^^^^
Is this the intended parent selector?
This references a9_hdmitx_pixel_sel instead of a9_hdmitx1_pixel_sel. This
hierarchy mismatch might cause parent and rate adjustments for hdmitx1_pixel
to mutate the wrong clock selector, leaving its own hardware unconfigured.
[ ... ]
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260511-b4-a9_clk-v1-0-41cb4071b7c9@amlogic.com?part=9
^ permalink raw reply [flat|nested] 21+ messages in thread
end of thread, other threads:[~2026-05-12 6:18 UTC | newest]
Thread overview: 21+ 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-12 4:18 ` sashiko-bot
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-12 4:48 ` sashiko-bot
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-12 5:56 ` sashiko-bot
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-12 6:18 ` sashiko-bot
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