mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH 00/18] riscv: add initial support for Zhihe A210 and Melon Pi
@ 2026-10-21 19:53 Han Gao via B4 Relay
  2026-10-21 19:53 ` [PATCH 01/18] dt-bindings: vendor-prefixes: add Zhihe Han Gao via B4 Relay
                   ` (17 more replies)
  0 siblings, 18 replies; 22+ messages in thread
From: Han Gao via B4 Relay @ 2026-10-21 19:53 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Zhiguo Zhu,
	Stephen Boyd, Brian Masney, Jerome Brunet, Philipp Zabel,
	Linus Walleij, Bartosz Golaszewski, Thomas Gleixner, Radu Rendec,
	Samuel Holland, Daniel Lezcano, Anup Patel, Icenowy Zheng,
	Drew Fustini
  Cc: devicetree, linux-kernel, linux-riscv, linux-clk, linux-gpio,
	Paul Walmsley, Han Gao

This series adds initial support for the Zhihe A210 SoC and the Melon Pi
V1 and V2 boards.

The A210 features eight RISC-V cores in two clusters: four C908 cores
and four C920 cores.

This series provides UART, clock, reset and pinctrl support, together
with the required bindings and device trees.

It is based on Linux v7.3 and has been boot-tested on a Melon Pi V2
with all eight CPUs online.

Signed-off-by: Han Gao <gaohan@iscas.ac.cn>
---
Han Gao (6):
      dt-bindings: clock: add Zhihe A210 AON clock controller
      dt-bindings: timer: add Zhihe A210 CLINT
      riscv: dts: zhihe: add A210 module memory
      riscv: dts: zhihe: add Melon Pi V1 and V2
      riscv: defconfig: enable A210 support
      MAINTAINERS: add Zhihe A210

Zhiguo Zhu (12):
      dt-bindings: vendor-prefixes: add Zhihe
      riscv: add Zhihe A210 support
      dt-bindings: clock: add Zhihe A210 clock controllers
      clk: zhihe: add A210 support
      dt-bindings: reset: add Zhihe A210 reset controllers
      reset: zhihe: add A210 support
      dt-bindings: pinctrl: add Zhihe A210 pin controller
      pinctrl: zhihe: add A210 support
      dt-bindings: interrupt-controller: add Zhihe A210 PLIC
      dt-bindings: riscv: add Melon Pi V1 and V2
      riscv: dts: zhihe: add A210 core support
      riscv: dts: zhihe: add A210 UARTs

 .../bindings/clock/zhihe,a210-aon-clk.yaml         |   58 +
 .../devicetree/bindings/clock/zhihe,a210-clk.yaml  |  231 ++
 .../interrupt-controller/sifive,plic-1.0.0.yaml    |    1 +
 .../bindings/pinctrl/zhihe,a210-pinctrl.yaml       |  206 ++
 .../bindings/reset/zhihe,a210-reset.yaml           |   56 +
 Documentation/devicetree/bindings/riscv/zhihe.yaml |   27 +
 .../devicetree/bindings/timer/sifive,clint.yaml    |    1 +
 .../devicetree/bindings/vendor-prefixes.yaml       |    2 +
 MAINTAINERS                                        |   16 +
 arch/riscv/Kconfig.socs                            |   10 +
 arch/riscv/boot/dts/Makefile                       |    1 +
 arch/riscv/boot/dts/zhihe/Makefile                 |    2 +
 arch/riscv/boot/dts/zhihe/a210-melonpi-common.dtsi |   55 +
 arch/riscv/boot/dts/zhihe/a210-melonpi-v1.dts      |    9 +
 arch/riscv/boot/dts/zhihe/a210-melonpi-v2.dts      |    9 +
 arch/riscv/boot/dts/zhihe/a210-som.dtsi            |   11 +
 arch/riscv/boot/dts/zhihe/a210.dtsi                |  645 ++++++
 arch/riscv/configs/defconfig                       |    4 +
 drivers/clk/Kconfig                                |    1 +
 drivers/clk/Makefile                               |    1 +
 drivers/clk/zhihe/Kconfig                          |   12 +
 drivers/clk/zhihe/Makefile                         |    2 +
 drivers/clk/zhihe/clk-a210-aon.c                   |   94 +
 drivers/clk/zhihe/clk-a210-ap.c                    | 2283 ++++++++++++++++++++
 drivers/pinctrl/Kconfig                            |   14 +
 drivers/pinctrl/Makefile                           |    1 +
 drivers/pinctrl/pinctrl-a210.c                     | 1206 +++++++++++
 drivers/reset/Kconfig                              |   11 +
 drivers/reset/Makefile                             |    1 +
 drivers/reset/reset-a210.c                         |  589 +++++
 include/dt-bindings/clock/zhihe,a210-aon-clk.h     |    9 +
 include/dt-bindings/clock/zhihe,a210-clk.h         |  649 ++++++
 include/dt-bindings/reset/zhihe,a210-resets.h      |  351 +++
 33 files changed, 6568 insertions(+)
---
base-commit: c03c1a14507dfaf8b856c2608f9ac216021fc222
change-id: 20261022-a210-init-d38cb9e6456a

Best regards,
--  
Han Gao <gaohan@iscas.ac.cn>



^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 01/18] dt-bindings: vendor-prefixes: add Zhihe
  2026-10-21 19:53 [PATCH 00/18] riscv: add initial support for Zhihe A210 and Melon Pi Han Gao via B4 Relay
@ 2026-10-21 19:53 ` Han Gao via B4 Relay
  2026-10-21 19:53 ` [PATCH 02/18] riscv: add Zhihe A210 support Han Gao via B4 Relay
                   ` (16 subsequent siblings)
  17 siblings, 0 replies; 22+ messages in thread
From: Han Gao via B4 Relay @ 2026-10-21 19:53 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Zhiguo Zhu,
	Stephen Boyd, Brian Masney, Jerome Brunet, Philipp Zabel,
	Linus Walleij, Bartosz Golaszewski, Thomas Gleixner, Radu Rendec,
	Samuel Holland, Daniel Lezcano, Anup Patel, Icenowy Zheng,
	Drew Fustini
  Cc: devicetree, linux-kernel, linux-riscv, linux-clk, linux-gpio,
	Paul Walmsley, Han Gao

From: Zhiguo Zhu <zhiguo.zhu@linux.alibaba.com>

Add the vendor prefix for Zhihe Computing.

Signed-off-by: Zhiguo Zhu <zhiguo.zhu@linux.alibaba.com>
Signed-off-by: Han Gao <gaohan@iscas.ac.cn>
---
 Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml
index ba2002969373..21142578837b 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.yaml
+++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml
@@ -1973,6 +1973,8 @@ patternProperties:
     description: Zealz
   "^zeitec,.*":
     description: ZEITEC Semiconductor Co., LTD.
+  "^zhihe,.*":
+    description: Zhihe Computing Limited
   "^zidoo,.*":
     description: Shenzhen Zidoo Technology Co., Ltd.
   "^zii,.*":

-- 
2.55.0



^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 02/18] riscv: add Zhihe A210 support
  2026-10-21 19:53 [PATCH 00/18] riscv: add initial support for Zhihe A210 and Melon Pi Han Gao via B4 Relay
  2026-10-21 19:53 ` [PATCH 01/18] dt-bindings: vendor-prefixes: add Zhihe Han Gao via B4 Relay
@ 2026-10-21 19:53 ` Han Gao via B4 Relay
  2026-10-21 19:53 ` [PATCH 03/18] dt-bindings: clock: add Zhihe A210 clock controllers Han Gao via B4 Relay
                   ` (15 subsequent siblings)
  17 siblings, 0 replies; 22+ messages in thread
From: Han Gao via B4 Relay @ 2026-10-21 19:53 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Zhiguo Zhu,
	Stephen Boyd, Brian Masney, Jerome Brunet, Philipp Zabel,
	Linus Walleij, Bartosz Golaszewski, Thomas Gleixner, Radu Rendec,
	Samuel Holland, Daniel Lezcano, Anup Patel, Icenowy Zheng,
	Drew Fustini
  Cc: devicetree, linux-kernel, linux-riscv, linux-clk, linux-gpio,
	Paul Walmsley, Han Gao

From: Zhiguo Zhu <zhiguo.zhu@linux.alibaba.com>

Add the ARCH_ZHIHE option for the Zhihe A210 SoC.

Signed-off-by: Zhiguo Zhu <zhiguo.zhu@linux.alibaba.com>
Co-developed-by: Han Gao <gaohan@iscas.ac.cn>
Signed-off-by: Han Gao <gaohan@iscas.ac.cn>
---
 arch/riscv/Kconfig.socs | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs
index cecbce0c4983..b9863ebd88c7 100644
--- a/arch/riscv/Kconfig.socs
+++ b/arch/riscv/Kconfig.socs
@@ -91,6 +91,16 @@ config ARCH_ULTRARISC
 	  This enables support for UltraRISC SoC platform hardware,
 	  including boards based on the UR-DP1000.
 
+config ARCH_ZHIHE
+	bool "ZhiHe SoCs"
+	depends on 64BIT && MMU
+	select ARCH_HAS_RESET_CONTROLLER
+	help
+	  Enable support for the Zhihe A210 SoC.
+	  A210 has four C908 and four C920 RISC-V CPU cores.
+	  Supported boards include the Melon Pi V1 and V2.
+	  Say Y here to build a kernel for these boards.
+
 config ARCH_VIRT
 	bool "QEMU Virt Machine"
 	select POWER_RESET

-- 
2.55.0



^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 03/18] dt-bindings: clock: add Zhihe A210 clock controllers
  2026-10-21 19:53 [PATCH 00/18] riscv: add initial support for Zhihe A210 and Melon Pi Han Gao via B4 Relay
  2026-10-21 19:53 ` [PATCH 01/18] dt-bindings: vendor-prefixes: add Zhihe Han Gao via B4 Relay
  2026-10-21 19:53 ` [PATCH 02/18] riscv: add Zhihe A210 support Han Gao via B4 Relay
@ 2026-10-21 19:53 ` Han Gao via B4 Relay
  2026-10-21 19:53 ` [PATCH 04/18] dt-bindings: clock: add Zhihe A210 AON clock controller Han Gao via B4 Relay
                   ` (14 subsequent siblings)
  17 siblings, 0 replies; 22+ messages in thread
From: Han Gao via B4 Relay @ 2026-10-21 19:53 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Zhiguo Zhu,
	Stephen Boyd, Brian Masney, Jerome Brunet, Philipp Zabel,
	Linus Walleij, Bartosz Golaszewski, Thomas Gleixner, Radu Rendec,
	Samuel Holland, Daniel Lezcano, Anup Patel, Icenowy Zheng,
	Drew Fustini
  Cc: devicetree, linux-kernel, linux-riscv, linux-clk, linux-gpio,
	Paul Walmsley, Han Gao

From: Zhiguo Zhu <zhiguo.zhu@linux.alibaba.com>

Add bindings for the A210 clock controllers, including register ranges,
input clocks and clock IDs.

Signed-off-by: Zhiguo Zhu <zhiguo.zhu@linux.alibaba.com>
Signed-off-by: Han Gao <gaohan@iscas.ac.cn>
---
 .../devicetree/bindings/clock/zhihe,a210-clk.yaml  | 231 ++++++++
 include/dt-bindings/clock/zhihe,a210-clk.h         | 649 +++++++++++++++++++++
 2 files changed, 880 insertions(+)

diff --git a/Documentation/devicetree/bindings/clock/zhihe,a210-clk.yaml b/Documentation/devicetree/bindings/clock/zhihe,a210-clk.yaml
new file mode 100644
index 000000000000..a3546d2f5977
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/zhihe,a210-clk.yaml
@@ -0,0 +1,231 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/zhihe,a210-clk.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: ZhiHe A210 Clock Controller
+
+maintainers:
+  - Zhiguo Zhu <zhiguo.zhu@linux.alibaba.com>
+
+description:
+  The ZhiHe A210 SoC contains several clock controllers spread across
+  different subsystems. Each controller manages PLLs, dividers, gates and
+  muxes for its subsystem. The register regions consumed by a controller
+  depend on the specific compatible string.
+
+properties:
+  compatible:
+    enum:
+      - zhihe,a210-clk
+      - zhihe,a210-peri-clk
+      - zhihe,a210-gpu-clk
+      - zhihe,a210-pcie-clk
+      - zhihe,a210-usb-clk
+      - zhihe,a210-vi-clk
+      - zhihe,a210-vp-clk
+      - zhihe,a210-vo-clk
+      - zhihe,a210-npu-clk
+
+  reg:
+    minItems: 1
+    maxItems: 9
+
+  reg-names:
+    minItems: 1
+    maxItems: 9
+
+  clocks:
+    description: Input reference oscillators.
+    minItems: 1
+    maxItems: 3
+
+  clock-names:
+    minItems: 1
+    maxItems: 3
+    items:
+      enum:
+        - osc-32k
+        - osc-24m
+        - rc-24m
+
+  power-domains:
+    maxItems: 1
+
+  "#clock-cells":
+    const: 1
+    description:
+      The single cell is the clock ID defined in
+      include/dt-bindings/clock/zhihe,a210-clk.h.
+
+required:
+  - compatible
+  - reg
+  - reg-names
+  - "#clock-cells"
+
+allOf:
+  - if:
+      properties:
+        compatible:
+          const: zhihe,a210-clk
+    then:
+      properties:
+        reg:
+          minItems: 9
+        reg-names:
+          items:
+            - const: pll-wrap
+            - const: top-crg
+            - const: cpu-ss-clk-sysreg
+            - const: cpu-ss-cpu-pll
+            - const: ddr0-sysreg
+            - const: ddr1-sysreg
+            - const: slc-dual-sysreg
+            - const: top-crg-t
+            - const: cpu-ss-ccu
+        clocks:
+          minItems: 3
+        clock-names:
+          items:
+            - const: osc-32k
+            - const: osc-24m
+            - const: rc-24m
+      required:
+        - clocks
+        - clock-names
+
+  - if:
+      properties:
+        compatible:
+          const: zhihe,a210-peri-clk
+    then:
+      properties:
+        reg:
+          minItems: 5
+          maxItems: 5
+        reg-names:
+          items:
+            - const: peri0-sysreg
+            - const: peri1-sysreg
+            - const: peri2-sysreg
+            - const: peri3-sysreg
+            - const: tee-crg
+
+  - if:
+      properties:
+        compatible:
+          const: zhihe,a210-gpu-clk
+    then:
+      properties:
+        reg:
+          minItems: 2
+          maxItems: 2
+        reg-names:
+          items:
+            - const: gpu-ss-pwrap-clk-en
+            - const: gpu-ss-top-clk-en
+
+  - if:
+      properties:
+        compatible:
+          const: zhihe,a210-pcie-clk
+    then:
+      properties:
+        reg:
+          maxItems: 1
+        reg-names:
+          items:
+            - const: pcie-clk-en
+
+  - if:
+      properties:
+        compatible:
+          const: zhihe,a210-usb-clk
+    then:
+      properties:
+        reg:
+          maxItems: 1
+        reg-names:
+          items:
+            - const: usb-clk-en
+
+  - if:
+      properties:
+        compatible:
+          const: zhihe,a210-vi-clk
+    then:
+      properties:
+        reg:
+          minItems: 2
+          maxItems: 2
+        reg-names:
+          items:
+            - const: vi-clk
+            - const: vi-misc-ctrl
+
+  - if:
+      properties:
+        compatible:
+          const: zhihe,a210-vp-clk
+    then:
+      properties:
+        reg:
+          maxItems: 1
+        reg-names:
+          items:
+            - const: vp-clk
+
+  - if:
+      properties:
+        compatible:
+          const: zhihe,a210-vo-clk
+    then:
+      properties:
+        reg:
+          minItems: 2
+          maxItems: 2
+        reg-names:
+          items:
+            - const: vo-clk
+            - const: vo-path-ctrl
+
+  - if:
+      properties:
+        compatible:
+          const: zhihe,a210-npu-clk
+    then:
+      properties:
+        reg:
+          minItems: 2
+          maxItems: 2
+        reg-names:
+          items:
+            - const: npu-clk
+            - const: npu-top-clk
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/zhihe,a210-clk.h>
+
+    clock-controller@260000 {
+        compatible = "zhihe,a210-clk";
+        reg = <0x00260000 0x1000>,
+              <0x00250000 0x1000>,
+              <0x10141600 0x100>,
+              <0x10141400 0x100>,
+              <0x04810000 0x1000>,
+              <0x05810000 0x1000>,
+              <0x04900000 0x1000>,
+              <0x20250000 0x1000>,
+              <0x10140000 0xe00>;
+        reg-names = "pll-wrap", "top-crg", "cpu-ss-clk-sysreg", "cpu-ss-cpu-pll",
+                    "ddr0-sysreg", "ddr1-sysreg", "slc-dual-sysreg", "top-crg-t",
+                    "cpu-ss-ccu";
+        #clock-cells = <1>;
+        clocks = <&osc_32k>, <&osc_24m>, <&rc_24m>;
+        clock-names = "osc-32k", "osc-24m", "rc-24m";
+    };
diff --git a/include/dt-bindings/clock/zhihe,a210-clk.h b/include/dt-bindings/clock/zhihe,a210-clk.h
new file mode 100644
index 000000000000..aa59d91a9ad0
--- /dev/null
+++ b/include/dt-bindings/clock/zhihe,a210-clk.h
@@ -0,0 +1,649 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+#ifndef _DT_BINDINGS_CLOCK_ZHIHE_A210_CLK_H
+#define _DT_BINDINGS_CLOCK_ZHIHE_A210_CLK_H
+
+// PLL_WRAP
+#define AUDIO0_PLL_FOUTVCO                                 0
+#define AUDIO0_PLL_FOUTPOSTDIV                             1
+#define AUDIO0_PLL_FOUT2                                   2
+#define AUDIO1_PLL_FOUTVCO                                 3
+#define AUDIO1_PLL_FOUTPOSTDIV                             4
+#define AUDIO1_PLL_FOUT2                                   5
+#define GMAC_PLL_FOUTVCO                                   6
+#define GMAC_PLL_FOUTPOSTDIV                               7
+#define GMAC_PLL_FOUT1PH0                                  8
+#define DVFS_PLL_FOUTVCO                                   9
+#define DPU0_PLL_FOUTPOSTDIV                               10
+#define DPU1_PLL_FOUTVCO                                   11
+#define DPU1_PLL_FOUTPOSTDIV                               12
+#define DPU2_PLL_FOUTVCO                                   13
+#define DPU2_PLL_FOUTPOSTDIV                               14
+#define VIDEO_PLL_FOUTVCO                                  15
+#define VIDEO_PLL_FOUTPOSTDIV                              16
+#define VIDEO_PLL_FOUT1PH0                                 17
+#define VIDEO_PLL_FOUT3                                    18
+#define TEE_PLL_FOUTVCO                                    19
+
+// TOP_CRG
+#define IOMMU_PTW_ACLK_DIV                                 20
+#define NOC_CCLK_DIV                                       21
+#define NOC_CCLK_MUX                                       22
+#define TOP_CFG_ACLK_DIV                                   23
+#define TOP_PCLK_DIV                                       24
+#define TOP_CPU_BAK_PLL0_CLK_DIV4                          25
+#define TOP_CPUSYS_PIC_CLK_DIV                             26
+#define TOP_CPU_DDR1_ACLK_MUX                              27
+#define TOP_CPU_DDR0_ACLK_MUX                              28
+#define TOP_CPU_BAK_PLL0_CLK_MUX0                          29
+#define TOP_CPU_BAK_PLL0_CLK_DIV0                          30
+#define TOP_CPU_BAK_PLL0_CLK_DIV1                          31
+#define TOP_CPU_BAK_PLL0_CLK_DIV3                          32
+#define TOP_CPUSYS_PIC_CLK_MUX                             33
+#define TOP_CPU_BAK_PLL0_CLK_MUX                           34
+#define TOP_CPU_BAK_PLL1_CLK_DIV1                          35
+#define TOP_CPUSYS_BUS_CLK_DIV                             36
+#define TOP_CPUSYS_BUS_CLK_MUX                             37
+#define TOP_CPU_BAK_PLL1_CLK_DIV0                          38
+#define TOP_CPU_BAK_PLL1_CLK_MUX0                          39
+#define TOP_CPU_BAK_PLL1_CLK_DIV3                          40
+#define TOP_CPU_BAK_PLL1_CLK_MUX                           41
+#define TOP_D2D_REF_CLK_MUX                                42
+#define TOP_D2D_SCAN_CLK0_DIV                              43
+#define TOP_D2D_SCAN_CLK1_DIV                              44
+#define TOP_D2D_ACLK_DIV                                   45
+#define TOP_D2D_ACLK_MUX                                   46
+#define AMUX_CLK_DIV                                       47
+#define TOP_GPU_CORE_CLK_DIV                               48
+#define TOP_GPU_CORE_CLK_MUX                               49
+#define TOP_PCIE_SCAN_REF_CLK1_DIV                         50
+#define TOP_PCIE_SCAN_REF_CLK0_DIV                         51
+#define TOP_PCIE_AXI_M_ACLK_DIV                            52
+#define TOP_PCIE_AXI_M_ACLK_MUX                            53
+#define TOP_PERI_SPI_SSI_CLK0_DIV                          54
+#define TOP_PERI_MST_ACLK0_DIV                             55
+#define TOP_PERI_TIMER_CLK_MUX                             56
+#define TOP_PERI_I2S_8CH0_SRC_CLK_MUX                      57
+#define TOP_PERI_I2S_2CH0_SRC_CLK_MUX                      58
+#define TOP_PERI_QSPI_SSI_CLK_MUX0                         59
+#define TOP_PERI_QSPI0_SSI_CLK_DIV0                        60
+#define TOP_PERI_QSPI0_SSI_CLK_DIV1                        61
+#define TOP_PERI_SPI_SSI_CLK1_DIV                          62
+#define TOP_PERI_HIRES_CLK0_DIV                            63
+#define TOP_PERI_HIRES_CLK1_DIV                            64
+#define TOP_PERI_TDM_SRC_CLK_MUX                           65
+#define TOP_UART_SCLK_MUX                                  66
+#define TOP_PERI_I2S_2CH1_SRC_CLK_MUX                      67
+#define TOP_PERI_PDM_MCLK_MUX                              68
+#define TOP_PERI_I2S_2CH2_SRC_CLK_MUX                      69
+#define TOP_PERI_QSPI_SSI_CLK_MUX1                         70
+#define TOP_PERI_QSPI1_SSI_CLK_DIV0                        71
+#define TOP_PERI_QSPI1_SSI_CLK_DIV1                        72
+#define TOP_PERI_MST_CLK1_DIV                              73
+#define TOP_PERI_EMMC_REF_CLK_DIV                          74
+#define TOP_PERI_PDM_MCLK_DIV                              75
+#define TOP_PERI_EMMC_REF_CLK_MUX                          76
+#define TOP_PAD_SENSOR_VCLK_MUX1                           77
+#define TOP_PAD_SENSOR_VCLK_MUX0                           78
+#define TOP_PAD_SENSOR_VCLK1_DIV                           79
+#define TOP_PAD_SENSOR_VCLK0_DIV                           80
+#define TOP_TEE_CLK_DIV                                    81
+#define TOP_TEE_CLK_MUX                                    82
+#define TOP_USB_BUS_ACLK_DIV                               83
+#define TOP_USB_DP_AUX_CLK_DIV                             84
+#define TOP_VP_ACLK_MUX                                    85
+#define TOP_VP_ACLK_DIV                                    86
+#define TOP_VP_G2D_CCLK_DIV                                87
+#define TOP_VP_G2D_CCLK_MUX                                88
+#define TOP_VP_VDEC_CCLK_DIV                               89
+#define TOP_VP_VDEC_CCLK_MUX                               90
+#define TOP_VP_VENC_CCLK_DIV                               91
+#define TOP_VP_VENC_CCLK_MUX                               92
+#define TOP_NPU_ACLK_DIV                                   93
+#define TOP_NPU_ACLK_MUX                                   94
+#define TOP_NPU_CCLK_DIV                                   95
+#define TOP_NPU_CCLK_MUX                                   96
+#define TOP_USB_USB20_SCAN_REF_CLK_DIV                     97
+#define TOP_USB_SCAN_REF_CLK3_DIV                          98
+#define TOP_USB_SCAN_REF_CLK2_DIV                          99
+#define TOP_USB_SCAN_REF_CLK1_DIV                          100
+#define TOP_USB_SCAN_REF_CLK0_DIV                          101
+#define TOP_CPU_BAK_PLL1_CLK_DIV4                          102
+#define SW_TOP_PAD_SENSOR_VCLK1_EN                         103
+#define SW_TOP_PAD_SENSOR_VCLK0_EN                         104
+#define SW_NOC_CCLK_EN                                     105
+#define SW_TOP_OSC_CLK_LOGIC_EN                            106
+#define SW_IOMMU_PTW_330_ACLK_EN                           107
+#define SW_AMUX_660_CLK_EN                                 108
+#define SW_NPU_SS_CLK_EN                                   109
+#define SW_CPU_SS_CLK_EN                                   110
+#define SW_DDR_SS_CLK_EN                                   111
+#define SW_D2D_SS_CLK_EN                                   112
+#define SW_VP_SS_CLK_EN                                    113
+#define SW_VO_SS_CLK_EN                                    114
+#define SW_VI_SS_CLK_EN                                    115
+#define SW_PCIE_SS_CLK_EN                                  116
+#define SW_USB_SS_CLK_EN                                   117
+#define SW_PERI1_SS_CLK_EN                                 118
+#define SW_PERI3_SS_CLK_EN                                 119
+#define SW_GPU_SS_CLK_EN                                   120
+
+// CPU_SS_CLK_SYSREG
+#define C908_CPU_TO_CDE_CLK_MUX                            121
+#define C920_CPU_TO_CDE_CLK_MUX                            122
+
+// CPU_SS_CPU_PLL
+#define C908_PLL_FOUTVCO                                   123
+#define C920_PLL_FOUTVCO                                   124
+
+// GPU_SS_SYSREG
+#define SW_PWR_WRAP_X2P_PCLK_EN                            125
+#define SW_PWR_WRAP_SYSREG_PCLK_EN                         126
+#define SW_PWR_WRAP_DFMU_PCLK_EN                           127
+#define SW_PWR_WRAP_X2P_ACLK_EN                            128
+#define SW_PWR_WRAP_CFG_ACLK_EN                            129
+#define SW_PWR_WRAP_CFG_AAB_MST_ACLK_EN                    130
+#define SW_PWR_WRAP_GPU_SYS_CLK_EN                         131
+#define SW_PWR_WRAP_MEMIF_AAB_SLV_CORE_CLK_EN              132
+#define SW_PWR_WRAP_DFMU_CORE_CLK_EN                       133
+#define SW_PWR_WRAP_GPU_CORE_CLK_EN                        134
+
+// GPU_SS_TOP_SYSREG
+#define SW_TOP_CFG_AAB_SLV_ACLK_EN                         135
+#define SW_TOP_X2P_PCLK_EN                                 136
+#define SW_TOP_SYSREG_PCLK_EN                              137
+#define SW_TOP_X2P_ACLK_EN                                 138
+#define SW_TOP_CFG_ACLK_EN                                 139
+#define SW_TOP_AFENCE_ACLK_EN                              140
+#define SW_MEMIF_AAB_MST_BUS_CLK_EN                        141
+
+// NPU_CRG
+#define NPU_CCLK_BUF_CDE_RATIO                             142
+#define NPU_CCLK_BUF_CDE_MUX                               143
+#define NPU_ACLK_BUF_CDE_RATIO                             144
+#define NPU_ACLK_BUF_CDE_MUX                               145
+#define SW_DROOP_PCLK_EN                                   146
+#define SW_DROOP_CLK_EN                                    147
+#define SW_DROOP_CCTRL_PCLK_EN                             148
+#define SW_DROOP_CCTRL_CLK_EN                              149
+#define SW_SEMA_PCLK_EN                                    150
+#define SW_SEMA_ACLK_EN                                    151
+#define SW_NPU_X2P_ACLK_EN                                 152
+#define SW_NPU_X2H_ACLK_EN                                 153
+#define SW_NPU_PTW_CCU_PCLK_EN                             154
+#define SW_NPU_PTW_CCU_CLK_EN                              155
+#define SW_NPU_PCTRL_PCLK_EN                               156
+#define SW_NPU_PCTRL_EN                                    157
+#define SW_NPU_LPE_C_PCLK_EN                               158
+#define SW_NPU_LPE_C_CLK_EN                                159
+#define SW_NPU_LPC_C_CLK_EN                                160
+#define SW_NPU_IP_HCLK_EN                                  161
+#define SW_NPU_IP_CCLK_EN                                  162
+#define SW_NPU_IP_ACLK_EN                                  163
+#define SW_NPU_DFMU_PTWCLK_EN                              164
+#define SW_NPU_DFMU_PCLK_EN                                165
+#define SW_NPU_CLK_CALC_EN                                 166
+#define SW_NPU_AXI_M2S1_ACLK_EN                            167
+#define SW_NPU_AXI_CCU_PCLK_EN                             168
+#define SW_NPU_AXI_CCU_CLK_EN                              169
+#define SW_NPU_AXI_ACLK_EN                                 170
+#define SW_NPU_AFENCE_EN                                   171
+#define SW_NPU_AAB_MST_ACLK_EN                             172
+#define SW_DFMU_ACLK_EN                                    173
+
+// NPU_TOP_CRG
+#define SW_NPUSS_AAB_SLV_CLK_EN                            174
+#define SW_NPUSS_FENCE_CLK_EN                              175
+
+// DDR0_SYSREG
+#define DDR0_PHY_DFICLK_EN                                 176
+#define DDR0_DDRC_ACLK_EN                                  177
+#define DDR0_DDRC_CCLK_EN                                  178
+#define DDR0_SBR_CLK_EN                                    179
+
+// DDR1_SYSREG
+#define DDR1_PHY_DFICLK_EN                                 180
+#define DDR1_DDRC_ACLK_EN                                  181
+#define DDR1_DDRC_CCLK_EN                                  182
+#define DDR1_SBR_CLK_EN                                    183
+
+// SLC_DUAL_SYSREG
+#define DDR_PLL_FOUTVCO                                    184
+#define DDR_PLL_FOUTPOSTDIV                                185
+#define DDR_PLL_FOUT1PH0                                   186
+#define DDR_PLL_FOUT2                                      187
+#define DDR_PLL_FOUT4                                      188
+#define DDR_PLL_CLK_SEL                                    189
+#define DDR_PLL_CLK_EN                                     190
+#define DDR_CBUS2DDR_ACLK0                                 191
+#define DDR_CBUS2DDR_ACLK1                                 192
+
+// D2D_CRG_REG_T
+#define D2D_SS_CTRL0_CLK_EN                                193
+#define D2D_SS_CTRL1_CLK_EN                                194
+
+// PCIE_CPR
+#define AXI4_PCIE_MST_PCLK_EN                              195
+#define AXI4_PCIE_MST_ACLK_EN                              196
+#define X2X_PERI3_MST_ACLK_EN                              197
+#define X2X_PERI3_SLV_ACLK_EN                              198
+#define PCIE_SS_DFMU_ACLK_EN                               199
+#define PCIE_SS_DFMU_IOMMU_PTW_ACLK_EN                     200
+#define PCIE_SS_DFMU_PCLK_EN                               201
+#define E16PHY_PCLK_EN                                     202
+#define SATA_MST_AFENCE_ACLK_EN                            203
+#define SATA_SLV_AFENCE_ACLK_EN                            204
+#define SATA_GEN3X2_ACLK_EN                                205
+#define X2X_SATA_SLV_ACLK_EN                               206
+#define X2X_SATA_MST_ACLK_EN                               207
+#define SATA_RXOOB1_CLK_EN                                 208
+#define SATA_RXOOB0_CLK_EN                                 209
+#define SATA_PMALIVE_CLK_EN                                210
+#define PCIE_DM_MST_AFENCE_ACLK_EN                         211
+#define PCIE_DM_SLV_AFENCE_ACLK_EN                         212
+#define PCIE_DM_GEN3X4_AUX_CLK_EN                          213
+#define PCIE_DM_GEN3X4_MST_ACLK_EN                         214
+#define PCIE_DM_GEN3X4_PCLK_EN                             215
+#define PCIE_DM_GEN3X4_SLV_ACLK_EN                         216
+#define PCIE_RP_MST_AFENCE_ACLK_EN                         217
+#define PCIE_RP_SLV_AFENCE_ACLK_EN                         218
+#define PCIE_RP_GEN3X1_AUX_CLK_EN                          219
+#define PCIE_RP_GEN3X1_MST_ACLK_EN                         220
+#define PCIE_RP_GEN3X1_PCLK_EN                             221
+#define PCIE_RP_GEN3X1_SLV_ACLK_EN                         222
+
+// USB_CPR
+#define USB_SS_AXI_MST_PCLK_EN                             223
+#define USB_SS_AXI_MST_ACLK_EN                             224
+#define USB_SS_DFMU_IOMMU_PTW_ACLK_EN                      225
+#define USB_SS_DFMU_ACLK_EN                                226
+#define USB_SS_DFMU_PCLK_EN                                227
+#define DPTX_I2S_CLK_EN                                    228
+#define DPTX_IPI_CLK_EN                                    229
+#define DPTX_AUX_CLK_EN                                    230
+#define DPTX_GTC_CLK_EN                                    231
+#define DPTX_PCLK_EN                                       232
+#define USB31_SLV_AFENCE_ACLK_EN                           233
+#define USB31_REF_CLK_EN                                   234
+#define USB31_SUSPEND_CLK_EN                               235
+#define USB31_BUS_CLK_EN                                   236
+#define USB31_PCLK_EN                                      237
+#define C10PHY_SUSPEND_CLK_EN                              238
+#define C10PHY_PCLK_EN                                     239
+#define USB2_SYSREG_PCLK_EN                                240
+#define USB2_AXI_MST_ACLK_EN                               241
+#define USB2_AHB_SLV_HCLK_EN                               242
+#define USB2_H2P_HCLK_EN                                   243
+#define USB2_SLV_AFENCE_ACLK_EN                            244
+#define USB2_X2H_ACLK_EN                                   245
+#define USB2_X2H_HCLK_EN                                   246
+#define USB2_WRAP_A2X1_ACLK_EN                             247
+#define USB2_WRAP_A2X1_HCLK_EN                             248
+#define USB2_WRAP_A2X0_ACLK_EN                             249
+#define USB2_WRAP_A2X0_HCLK_EN                             250
+#define USB2_WRAP1_HCLK_EN                                 251
+#define USB2_WRAP0_HCLK_EN                                 252
+#define USB_SS_PERI2_SLV_AFENCE_ACLK_EN                    253
+#define USB_SS_PERI2_CFG_ACLK_EN                           254
+
+// VI_SYSREG
+#define VI_DW_SCLK_EN                                      255
+#define VI_VSE_CLK_EN                                      256
+#define VI_DWE_CLK_EN                                      257
+#define VI_DW200_ACLK_EN                                   258
+#define VI_DW200_HCLK_EN                                   259
+#define VI_DECOMP_CLK_EN                                   260
+#define VI_COMP1_CLK_EN                                    261
+#define VI_COMP0_CLK_EN                                    262
+#define VI_VSEOUT_CLK_EN                                   263
+#define VI_DECOUT_CLK_EN                                   264
+#define VI_ISPOUT_CLK_EN                                   265
+#define VI_COMP_ACLK_EN                                    266
+#define VI_COMP_PCLK_EN                                    267
+#define VI_ISP_CLK_EN                                      268
+#define VI_VIPRE_ACLK_EN                                   269
+#define VI_VIPRE_SCLK_EN                                   270
+#define VI_VIPRE_I1_PIXCLK_EN                              271
+#define VI_VIPRE_I0_PIXCLK_EN                              272
+#define VI_VIPRE_PCLK_EN                                   273
+#define VI_MIPI1_CSI1_PIXCLK_EN                            274
+#define VI_MIPI1_CSI0_PIXCLK_EN                            275
+#define VI_MIPI1B_CFGCLK_EN                                276
+#define VI_MIPI1A_CFGCLK_EN                                277
+#define VI_MIPI1CSI1_PCLK_EN                               278
+#define VI_MIPI1CSI0_PCLK_EN                               279
+#define VI_MIPI0_CSI1_PIXCLK_EN                            280
+#define VI_MIPI0_CSI0_PIXCLK_EN                            281
+#define VI_MIPI0B_CFGCLK_EN                                282
+#define VI_MIPI0A_CFGCLK_EN                                283
+#define VI_MIPI0CSI1_PCLK_EN                               284
+#define VI_MIPI0CSI0_PCLK_EN                               285
+#define VI_REC_ACLK_EN                                     286
+#define VI_REC_PCLK_EN                                     287
+#define VI_FENCE_ACLK_EN                                   288
+#define VI_MIPI1CSI1_FPCLK_EN                              289
+#define VI_MIPI1CSI0_FPCLK_EN                              290
+#define VI_MIPI0CSI1_FPCLK_EN                              291
+#define VI_MIPI0CSI0_FPCLK_EN                              292
+#define VI_X2H2_CLK_EN                                     293
+#define VI_X2H1_CLK_EN                                     294
+#define VI_X2H0_CLK_EN                                     295
+#define VI_ARB_ACLK_EN                                     296
+#define VI_ARB_PCLK_EN                                     297
+#define VI_PTW_ACLK_EN                                     298
+#define VI_DFMU_ACLK_EN                                    299
+#define VI_DFMU_PCLK_EN                                    300
+#define VI_PRE_ISP_CORE_CLK_DIV_EN                         301
+#define VI_PRE_ISP_IF_CLK_DIV_EN                           302
+#define VI_PRE_MIPI1_PIXCLK_DIV_EN                         303
+#define VI_PRE_MIPI0_PIXCLK_DIV_EN                         304
+#define VI_ISP_IF_REF_SWITCH_SEL                           305
+#define VI_MIPI1_PIX_REF_SWITCH_SEL                        306
+#define VI_MIPI0_PIX_REF_SWITCH_SEL                        307
+#define VI_PRE_ISP_CORE_CLK_DIV_NUM                        308
+#define VI_PRE_ISP_IF_CLK_DIV_NUM                          309
+#define VI_PRE_MIPI1_PIXCLK_DIV_NUM                        310
+#define VI_PRE_MIPI0_PIXCLK_DIV_NUM                        311
+#define VI_PRE_DECOMP_CLK_DIV_EN                           312
+#define VI_PRE_COMP_CLK_DIV_EN                             313
+#define VI_PRE_DWE_CLK_DIV_EN                              314
+#define VI_PRE_VSE_CLK_DIV_EN                              315
+#define VI_PRE_AXI_CLK_DIV_EN                              316
+#define VI_PRE_DECOMP_CLK_DIV_NUM                          317
+#define VI_PRE_COMP_CLK_DIV_NUM                            318
+#define VI_PRE_DWE_CLK_DIV_NUM                             319
+#define VI_PRE_VSE_CLK_DIV_NUM                             320
+#define VI_PRE_AXI_CLK_DIV_NUM                             321
+
+// VO_SYSREG
+#define VO_X2H1_CLK_EN                                     322
+#define VO_X2H0_CLK_EN                                     323
+#define VO_PTW_ACLK_EN                                     324
+#define VO_DFMU_ACLK_EN                                    325
+#define VO_DFMU_PCLK_EN                                    326
+#define VO_ARB_ACLK_EN                                     327
+#define VO_ARB_PCLK_EN                                     328
+#define VO_DECOMP_ACLK_EN                                  329
+#define VO_DECOMP1_CLK_EN                                  330
+#define VO_DECOMP0_CLK_EN                                  331
+#define VO_DECOMP_PCLK_EN                                  332
+#define VO_MIPI_CFGCLK_EN                                  333
+#define VO_MIPI_PCLK_EN                                    334
+#define VO_HDMI_SFRCLK_EN                                  335
+#define VO_CEC_CLK_EN                                      336
+#define VO_I2S_CLK_EN                                      337
+#define VO_HDMI_PCLK_EN                                    338
+#define VO_AUXDISP_ACLK_EN                                 339
+#define VO_AUXDISP_PCLK_EN                                 340
+#define VO_CH2_PIXCLK_EN                                   341
+#define VO_DPU_ACLK_EN                                     342
+#define VO_DPUC_CLK_EN                                     343
+#define VO_DPU_HCLK_EN                                     344
+#define VO_CH1_PIXCLK_EN                                   345
+#define VO_CH0_PIXCLK_EN                                   346
+#define VO_PLL2_DIV_EN                                     347
+#define VO_PLL2_DIV_NUM                                    348
+#define VO_PLL1_DIV_EN                                     349
+#define VO_PLL1_DIV_NUM                                    350
+#define VO_PLL0_DIV_EN                                     351
+#define VO_PLL0_DIV_NUM                                    352
+#define VO_DECOMP_DIV_EN                                   353
+#define VO_DECOMP_DIV_NUM                                  354
+#define VO_DPUC_DIV_EN                                     355
+#define VO_DPUC_DIV_NUM                                    356
+#define VO_ACLK_DIV_EN                                     357
+#define VO_ACLK_DIV_NUM                                    358
+
+// VP_SYSREG
+#define VP_DECOMP_EXTPCLK_EN                               359
+#define VP_COMP_EXTPCLK_EN                                 360
+#define VP_VENC_RS_ACLK_EN                                 361
+#define VP_VDEC_RS_ACLK_EN                                 362
+#define VP_ARB_ACLK_EN                                     363
+#define VP_ARB_PCLK_EN                                     364
+#define VP_PTW_ACLK_EN                                     365
+#define VP_DFMU_ACLK_EN                                    366
+#define VP_DFMU_PCLK_EN                                    367
+#define VP_DECOMP_ACLK_EN                                  368
+#define VP_DECOMP_CCLK_EN                                  369
+#define VP_DECOMP_PCLK_EN                                  370
+#define VP_COMP_ACLK_EN                                    371
+#define VP_COMP_CCLK_EN                                    372
+#define VP_COMP_PCLK_EN                                    373
+#define VP_G2D_ACLK_EN                                     374
+#define VP_G2D_CCLK_EN                                     375
+#define VP_G2D_PCLK_EN                                     376
+#define VP_VENC_ACLK_EN                                    377
+#define VP_VENC_CCLK_EN                                    378
+#define VP_VENC_PCLK_EN                                    379
+#define VP_VDEC_ACLK_EN                                    380
+#define VP_VDEC_CCLK_EN                                    381
+#define VP_VDEC_PCLK_EN                                    382
+#define VP_DECOMP_DIV_EN                                   383
+#define VP_DECOMP_DIV_NUM                                  384
+#define VP_COMP_DIV_EN                                     385
+#define VP_COMP_DIV_NUM                                    386
+
+// PERI0_SYSREG
+#define PERI0_MBOX1_PCLK_EN                                387
+#define PERI0_MBOX0_PCLK_EN                                388
+#define PERI0_WDT0_PCLK_EN                                 389
+#define PERI0_TIMER1_PCLK_EN                               390
+#define PERI0_TIMER1_CCLK_EN                               391
+#define PERI0_TIMER0_PCLK_EN                               392
+#define PERI0_TIMER0_CCLK_EN                               393
+
+// PERI1_SYSREG
+#define PERI1_UART3_SCLK_EN                                394
+#define PERI1_UART3_PCLK_EN                                395
+#define PERI1_UART2_SCLK_EN                                396
+#define PERI1_UART2_PCLK_EN                                397
+#define PERI1_UART1_SCLK_EN                                398
+#define PERI1_UART1_PCLK_EN                                399
+#define PERI1_UART0_SCLK_EN                                400
+#define PERI1_UART0_PCLK_EN                                401
+#define PERI1_SPI0_SSI_CLK_EN                              402
+#define PERI1_SPI0_PCLK_EN                                 403
+#define PERI1_QSPI0_SSI_CLK_EN                             404
+#define PERI1_QSPI0_PCLK_EN                                405
+#define PERI1_PWM0_PCLK_EN                                 406
+#define PERI1_PWM0_CCLK_EN                                 407
+#define PERI1_MST_BUS_PCLK_EN                              408
+#define PERI1_MST_BUS_ACLK_EN                              409
+#define PERI1_I2S0_SRC_CLK_EN                              410
+#define PERI1_I2S0_PCLK_EN                                 411
+#define PERI1_I2C2_PCLK_EN                                 412
+#define PERI1_I2C2_IC_CLK_EN                               413
+#define PERI1_I2C1_PCLK_EN                                 414
+#define PERI1_I2C1_IC_CLK_EN                               415
+#define PERI1_I2C0_PCLK_EN                                 416
+#define PERI1_I2C0_IC_CLK_EN                               417
+#define PERI1_GPIO1_PCLK_EN                                418
+#define PERI1_GPIO1_DBCLK_EN                               419
+#define PERI1_GPIO0_PCLK_EN                                420
+#define PERI1_GPIO0_DBCLK_EN                               421
+#define PERI1_GMAC1_HCLK_EN                                422
+#define PERI1_GMAC1_ACLK_EN                                423
+#define PERI1_GMAC0_HCLK_EN                                424
+#define PERI1_GMAC0_ACLK_EN                                425
+
+// PERI2_SYSREG
+#define PERI2_I2S3_PCLK_EN                                 426
+#define PERI2_I2S3_SRC_CLK_EN                              427
+#define PERI2_I2S2_PCLK_EN                                 428
+#define PERI2_I2S2_SRC_CLK_EN                              429
+#define PERI2_I2S1_PCLK_EN                                 430
+#define PERI2_I2S1_SRC_CLK_EN                              431
+#define PERI2_I2C7_IC_CLK_EN                               432
+#define PERI2_I2C7_PCLK_EN                                 433
+#define PERI2_I2C6_IC_CLK_EN                               434
+#define PERI2_I2C6_PCLK_EN                                 435
+#define PERI2_I2C5_IC_CLK_EN                               436
+#define PERI2_I2C5_PCLK_EN                                 437
+#define PERI2_I2C4_IC_CLK_EN                               438
+#define PERI2_I2C4_PCLK_EN                                 439
+#define PERI2_I2C3_IC_CLK_EN                               440
+#define PERI2_I2C3_PCLK_EN                                 441
+#define PERI2_GPIO3_DBCLK_EN                               442
+#define PERI2_GPIO3_PCLK_EN                                443
+#define PERI2_PAD_CTRL_PCLK_EN                             444
+#define PERI2_UART6_PCLK_EN                                445
+#define PERI2_UART5_PCLK_EN                                446
+#define PERI2_UART4_PCLK_EN                                447
+#define PERI2_SPI1_PCLK_EN                                 448
+#define PERI2_GPIO2_PCLK_EN                                449
+#define PERI2_CAN2_PCLK_EN                                 450
+#define PERI2_UART6_SCLK_EN                                451
+#define PERI2_UART5_SCLK_EN                                452
+#define PERI2_UART4_SCLK_EN                                453
+#define PERI2_SPI1_SSI_CLK_EN                              454
+#define PERI2_GPIO2_DBCLK_EN                               455
+#define PERI2_CAN2_OSC_CLK_EN                              456
+#define PERI2_CAN2_HIRES_CLK_EN                            457
+#define PERI2_QSPI1_PCLK_EN                                458
+#define PERI2_QSPI1_SSI_CLK_EN                             459
+#define PERI2_UART9_PCLK_EN                                460
+#define PERI2_UART9_SCLK_EN                                461
+#define PERI2_UART8_PCLK_EN                                462
+#define PERI2_UART8_SCLK_EN                                463
+#define PERI2_UART7_PCLK_EN                                464
+#define PERI2_UART7_SCLK_EN                                465
+#define PERI2_PWM2_PCLK_EN                                 466
+#define PERI2_PWM2_CCLK_EN                                 467
+#define PERI2_PWM1_PCLK_EN                                 468
+#define PERI2_PWM1_CCLK_EN                                 469
+
+// PERI3_SYSREG
+#define PERI3_PAD_CTRL_PCLK_EN                             470
+#define PERI3_GPIO4_PCLK_EN                                471
+#define PERI3_GPIO4_DBCLK_EN                               472
+#define CLKCTRL_PERI3_TEE_H2H_SHCLKEN                      473
+#define CLKCTRL_PERI3_TEE_H2H_MHCLKEN                      474
+#define PERI3_TEE_X2X_ACLK_S_EN                            475
+#define PERI3_ADC_PCLK_EN                                  476
+#define AXI_PERI3_MST_PCLK_EN                              477
+#define AXI_PERI3_MST_ACLK_EN                              478
+#define PERI3_SDIO_X2X_ACLK_S_EN                           479
+#define PERI3_SDIO_X2X_ACLK_M_EN                           480
+#define PERI3_SDIO_OSC_CLK_EN                              481
+#define PERI3_SDIO_HCLK_EN                                 482
+#define PERI3_EMMC_X2X_ACLK_S_EN                           483
+#define PERI3_EMMC_X2X_ACLK_M_EN                           484
+#define PERI3_EMMC_OSC_CLK_EN                              485
+#define PERI3_EMMC_HCLK_EN                                 486
+#define PERI3_EMMC_ACLK_EN                                 487
+#define PERI3_EMMC_SDIO_REF_CLK_CG_EN                      488
+#define PERI3_DMAC_HCLK_EN                                 489
+#define PERI3_DMAC_ACLK_EN                                 490
+
+// TEE_CRG
+#define TEE_PCLK_CDE_RATIO                                 491
+#define TEE_AHB2_TEESYS_CLKEN                              492
+#define TEE_APB3_TEESYS_CLKEN                              493
+#define TEE_AXI4_TEESYS_CLKEN                              494
+#define TEE_X2P_TEESYS_CLKEN                               495
+#define TEE_EIP120SI_CLKEN                                 496
+#define TEE_EIP120SII_CLKEN                                497
+#define TEE_EIP120SIII_CLKEN                               498
+#define TEE_EIP150B_CLKEN                                  499
+#define TEE_DMAC_CLKEN                                     500
+#define TEE_DS_CLKEN                                       501
+#define TEE_OCRAM_CLKEN                                    502
+#define TEE_EFUSE_CLKEN                                    503
+#define TEE_KEYRAM_CLKEN                                   504
+
+#define CLK_DUMMY                                          505
+#define OSC_32K                                            506
+#define OSC_24M                                            507
+#define RC_24M                                             508
+
+#define TOP_PLL_REF_CLK                                    509
+#define AON_OSC_CLK_PHY                                    510
+#define AON_OSC_CLK_LOGIC                                  511
+#define PLL_OSC_CLK                                        512
+#define D2D_PHY_REF_CLK_100M                               513
+#define D2D_PHY_SCAN_CLK2                                  514
+#define TOP_PERI_TIMER_CLK_100M                            515
+#define PERI1_UART_SCLK                                    516
+#define PERI2_UART_SCLK                                    517
+#define UART_SCLK_100M                                     518
+#define GPU_TOP_SYS_CLK                                    519
+#define GPU_PCLK_CDT                                       520
+#define PCIE_SS_APB_CLK                                    521
+#define USB_SS_GTC_CLK                                     522
+#define USB_SS_PAD_OSC_CLK_1M                              523
+#define USB20_BUS_CLK                                      524
+#define USB20_CORE_CLK                                     525
+#define VI_PCLK                                            526
+#define VO_PCLK                                            527
+#define AON_RTC_CLK                                        528
+#define PERI1_PWM_CLK                                      529
+#define PERI2_PWM_CLK                                      530
+#define I2C_IC_CLK                                         531
+#define PERI3_SDIO_ACLK_EN                                 532
+
+#define PERI1_ZGMAC_X2X_ACLK_EN                            533
+#define PERI1_GMAC2_HCLK_EN                                534
+#define PERI1_GMAC2_ACLK_EN                                535
+#define PERI1_X2H_GMAC2_HCLK_EN                            536
+#define PERI1_X2H_GMAC2_ACLK_EN                            537
+#define PERI1_CHIP_DBG_PCLK_EN                             538
+#define PERI1_CHIP_DBG_CCLK_EN                             539
+#define PERI1_CHIP_DBG_ACLK_EN                             540
+#define PERI1_TDM0_SCLK_EN                                 541
+#define PERI1_TDM0_PCLK_EN                                 542
+#define PERI1_PDM0_PCLK_EN                                 543
+#define PERI1_PDM0_MCLK_EN                                 544
+#define PERI1_CAN1_PCLK_EN                                 545
+#define PERI1_CAN1_OSC_CLK_EN                              546
+#define PERI1_CAN1_HIRES_CLK_EN                            547
+#define PERI1_CAN0_PCLK_EN                                 548
+#define PERI1_CAN0_OSC_CLK_EN                              549
+#define PERI1_CAN0_HIRES_CLK_EN                            550
+#define PERI1_PAD_CTRL_PCLK_EN                             551
+#define PERI1_DFMU_PTW_ACLK_EN                             552
+#define PERI1_DFMU_PCLK_EN                                 553
+#define PERI1_DFMU_ACLK_EN                                 554
+#define PERI1_X2H_GMAC1_HCLK_EN                            555
+#define PERI1_X2H_GMAC1_ACLK_EN                            556
+#define PERI1_X2H_GMAC0_HCLK_EN                            557
+#define PERI1_X2H_GMAC0_ACLK_EN                            558
+#define DPU0_PLL_FOUTVCO                                   559
+
+#define PERI3_EMMC_SDIO_REF_CLK                            560
+
+#define VO_MIPI_PIXCLK                                     561
+#define VO_HDMI_PIXCLK                                     562
+#define VO_DPTX_PIXCLK                                     563
+
+#define TOP_CPUSYS_CFG_ACLK_DIV                            564
+#define TOP_CPUSYS_COM_APB_CLK_DIV                         565
+#define TOP_CPUSYS_APB_CLK_DIV                             566
+
+#define VI_MISC_CTRL_H0CLK_CLK_EN                          567
+#define VI_MISC_CTRL_H1CLK_CLK_EN                          568
+#define VI_MISC_CTRL_ISP_ACLK_CLK_EN                       569
+#define VI_MISC_CTRL_ISP_SCLK_CLK0_EN                      570
+#define VI_MISC_CTRL_ISP_SCLK_CLK1_EN                      571
+#define VI_MISC_CTRL_ISP_SCLK_CLK2_EN                      572
+#define VI_MISC_CTRL_ISP_SCLK_CLK3_EN                      573
+#define VI_MISC_CTRL_ISP_CORE_CLK_EN                       574
+#define VI_MISC_CTRL_ISP_FLEXA_CLK_EN                      575
+#define VI_MISC_CTRL_ISP_MCM_CLK_EN                        576
+#define VI_MISC_CTRL_BUS_CLK_GT_DISABLE                    577
+
+#define USB20_X2H_HCLK                                    578
+#define USB20_X2H_ACLK                                    579
+#define USB20_SLV_AFENCE_ACLK                             580
+#define USB20_H2P_HCLK                                    581
+#define USB20_AHB_SLV_HCLK                                582
+#define USB20_SYSREG_PCLK                                 583
+#define USB20_WRAP0_HCLK                                  584
+#define USB20_WRAP1_HCLK                                  585
+#define USB20_A2X0_HCLK                                   586
+#define USB20_A2X0_ACLK                                   587
+#define USB20_A2X1_HCLK                                   588
+#define USB20_A2X1_ACLK                                   589
+
+#define CLK_END 590
+
+#endif

-- 
2.55.0



^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 04/18] dt-bindings: clock: add Zhihe A210 AON clock controller
  2026-10-21 19:53 [PATCH 00/18] riscv: add initial support for Zhihe A210 and Melon Pi Han Gao via B4 Relay
                   ` (2 preceding siblings ...)
  2026-10-21 19:53 ` [PATCH 03/18] dt-bindings: clock: add Zhihe A210 clock controllers Han Gao via B4 Relay
@ 2026-10-21 19:53 ` Han Gao via B4 Relay
  2026-10-21 19:53 ` [PATCH 05/18] clk: zhihe: add A210 support Han Gao via B4 Relay
                   ` (13 subsequent siblings)
  17 siblings, 0 replies; 22+ messages in thread
From: Han Gao via B4 Relay @ 2026-10-21 19:53 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Zhiguo Zhu,
	Stephen Boyd, Brian Masney, Jerome Brunet, Philipp Zabel,
	Linus Walleij, Bartosz Golaszewski, Thomas Gleixner, Radu Rendec,
	Samuel Holland, Daniel Lezcano, Anup Patel, Icenowy Zheng,
	Drew Fustini
  Cc: devicetree, linux-kernel, linux-riscv, linux-clk, linux-gpio,
	Paul Walmsley, Han Gao

From: Han Gao <gaohan@iscas.ac.cn>

Add bindings for the A210 AON clock controller, including input clocks,
the system clock and I2C1 gates.

Signed-off-by: Han Gao <gaohan@iscas.ac.cn>
---
 .../bindings/clock/zhihe,a210-aon-clk.yaml         | 58 ++++++++++++++++++++++
 include/dt-bindings/clock/zhihe,a210-aon-clk.h     |  9 ++++
 2 files changed, 67 insertions(+)

diff --git a/Documentation/devicetree/bindings/clock/zhihe,a210-aon-clk.yaml b/Documentation/devicetree/bindings/clock/zhihe,a210-aon-clk.yaml
new file mode 100644
index 000000000000..bc1587e3fa81
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/zhihe,a210-aon-clk.yaml
@@ -0,0 +1,58 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/zhihe,a210-aon-clk.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Zhihe A210 always-on peripheral clock controller
+
+maintainers:
+  - Han Gao <gaohan@iscas.ac.cn>
+
+description: |
+  The AON clock controller provides a system clock multiplexer and
+  divider, along with peripheral clock gates.
+
+properties:
+  compatible:
+    const: zhihe,a210-aon-clk
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    items:
+      - description: High-speed AON reference
+      - description: External oscillator
+      - description: Internal RC oscillator
+      - description: RTC oscillator
+
+  clock-names:
+    items:
+      - const: high
+      - const: osc
+      - const: rc
+      - const: rtc
+
+  '#clock-cells':
+    const: 1
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - clock-names
+  - '#clock-cells'
+
+additionalProperties: false
+
+examples:
+  - |
+    clock-controller@30844000 {
+        compatible = "zhihe,a210-aon-clk";
+        reg = <0x30844000 0x1c>;
+        #clock-cells = <1>;
+        clocks = <&aon_high>, <&osc24m>, <&rc26m>, <&rtc32k>;
+        clock-names = "high", "osc", "rc", "rtc";
+    };
+...
diff --git a/include/dt-bindings/clock/zhihe,a210-aon-clk.h b/include/dt-bindings/clock/zhihe,a210-aon-clk.h
new file mode 100644
index 000000000000..29d7e9183adf
--- /dev/null
+++ b/include/dt-bindings/clock/zhihe,a210-aon-clk.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+#ifndef _DT_BINDINGS_CLOCK_ZHIHE_A210_AON_H
+#define _DT_BINDINGS_CLOCK_ZHIHE_A210_AON_H
+
+#define A210_AON_SYS_CLK		0
+#define A210_AON_I2C1_IC_CLK	1
+#define A210_AON_I2C1_PCLK	2
+
+#endif

-- 
2.55.0



^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 05/18] clk: zhihe: add A210 support
  2026-10-21 19:53 [PATCH 00/18] riscv: add initial support for Zhihe A210 and Melon Pi Han Gao via B4 Relay
                   ` (3 preceding siblings ...)
  2026-10-21 19:53 ` [PATCH 04/18] dt-bindings: clock: add Zhihe A210 AON clock controller Han Gao via B4 Relay
@ 2026-10-21 19:53 ` Han Gao via B4 Relay
  2026-10-21 19:53 ` [PATCH 06/18] dt-bindings: reset: add Zhihe A210 reset controllers Han Gao via B4 Relay
                   ` (12 subsequent siblings)
  17 siblings, 0 replies; 22+ messages in thread
From: Han Gao via B4 Relay @ 2026-10-21 19:53 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Zhiguo Zhu,
	Stephen Boyd, Brian Masney, Jerome Brunet, Philipp Zabel,
	Linus Walleij, Bartosz Golaszewski, Thomas Gleixner, Radu Rendec,
	Samuel Holland, Daniel Lezcano, Anup Patel, Icenowy Zheng,
	Drew Fustini
  Cc: devicetree, linux-kernel, linux-riscv, linux-clk, linux-gpio,
	Paul Walmsley, Han Gao

From: Zhiguo Zhu <zhiguo.zhu@linux.alibaba.com>

Add AP and AON clock providers for A210. Preserve the PLL settings at
probe and keep the AON system clock read-only.

Signed-off-by: Zhiguo Zhu <zhiguo.zhu@linux.alibaba.com>
Co-developed-by: Han Gao <gaohan@iscas.ac.cn>
Signed-off-by: Han Gao <gaohan@iscas.ac.cn>
---
 drivers/clk/Kconfig              |    1 +
 drivers/clk/Makefile             |    1 +
 drivers/clk/zhihe/Kconfig        |   12 +
 drivers/clk/zhihe/Makefile       |    2 +
 drivers/clk/zhihe/clk-a210-aon.c |   94 ++
 drivers/clk/zhihe/clk-a210-ap.c  | 2283 ++++++++++++++++++++++++++++++++++++++
 6 files changed, 2393 insertions(+)

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index f9592fd9ec2b..6f4d7a829a89 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -547,6 +547,7 @@ source "drivers/clk/uniphier/Kconfig"
 source "drivers/clk/visconti/Kconfig"
 source "drivers/clk/x86/Kconfig"
 source "drivers/clk/xilinx/Kconfig"
+source "drivers/clk/zhihe/Kconfig"
 source "drivers/clk/zynqmp/Kconfig"
 
 # Kunit test cases
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index b18af485d7f0..63b9f69803fd 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -181,5 +181,6 @@ ifeq ($(CONFIG_COMMON_CLK), y)
 obj-$(CONFIG_X86)			+= x86/
 endif
 obj-y					+= xilinx/
+obj-$(CONFIG_CLK_ZHIHE_A210)		+= zhihe/
 obj-$(CONFIG_ARCH_ZYNQ)			+= zynq/
 obj-$(CONFIG_COMMON_CLK_ZYNQMP)         += zynqmp/
diff --git a/drivers/clk/zhihe/Kconfig b/drivers/clk/zhihe/Kconfig
new file mode 100644
index 000000000000..3319817709e6
--- /dev/null
+++ b/drivers/clk/zhihe/Kconfig
@@ -0,0 +1,12 @@
+# SPDX-License-Identifier: GPL-2.0
+
+config CLK_ZHIHE_A210
+	tristate "ZhiHe A210 clock driver"
+	depends on OF && (ARCH_ZHIHE || COMPILE_TEST)
+	default ARCH_ZHIHE
+	help
+	  Build the clock controller driver for the ZhiHe A210 SoC.
+
+	  This driver provides clock tree management including PLLs,
+	  dividers, gates, and muxes for the A210 platform. Say Y if
+	  you are building a kernel for the ZhiHe A210.
diff --git a/drivers/clk/zhihe/Makefile b/drivers/clk/zhihe/Makefile
new file mode 100644
index 000000000000..90f7075f9eab
--- /dev/null
+++ b/drivers/clk/zhihe/Makefile
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_CLK_ZHIHE_A210) += clk-a210-ap.o clk-a210-aon.o
diff --git a/drivers/clk/zhihe/clk-a210-aon.c b/drivers/clk/zhihe/clk-a210-aon.c
new file mode 100644
index 000000000000..5e311b1008c8
--- /dev/null
+++ b/drivers/clk/zhihe/clk-a210-aon.c
@@ -0,0 +1,94 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Read the firmware-selected AON clock and gate the AP-owned I2C bus. */
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+
+#include <dt-bindings/clock/zhihe,a210-aon-clk.h>
+
+#define AON_CLOCK_CONFIG 0x00
+#define AON_CLOCK_GATE 0x04
+#define AON_SOURCE_SHIFT 4
+#define AON_SOURCE_WIDTH 2
+#define AON_DIVIDER_WIDTH 3
+#define AON_I2C1_IC_ENABLE 20
+#define AON_I2C1_APB_ENABLE 21
+
+struct a210_aon_clock {
+	/* Protects the AP-owned AON gate register bits. */
+	spinlock_t lock;
+	struct clk_hw_onecell_data data;
+};
+
+static int a210_aon_clock_probe(struct platform_device *pdev)
+{
+	static const struct clk_parent_data parents[] = {
+		{ .fw_name = "high" },
+		{ .fw_name = "osc" },
+		{ .fw_name = "rc" },
+		{ .fw_name = "rtc" },
+	};
+	struct device *dev = &pdev->dev;
+	struct a210_aon_clock *priv;
+	struct clk_hw *mux, *sys, *hw;
+	void __iomem *base;
+	int i;
+
+	priv = devm_kzalloc(dev, struct_size(priv, data.hws, 3), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+	spin_lock_init(&priv->lock);
+	priv->data.num = 3;
+	base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+
+	/* E902 firmware owns source selection and the synchronized divider. */
+	mux = devm_clk_hw_register_mux_parent_data_table(dev, "aon_mux", parents,
+							 ARRAY_SIZE(parents), CLK_GET_RATE_NOCACHE,
+							 base + AON_CLOCK_CONFIG, AON_SOURCE_SHIFT,
+							 AON_SOURCE_WIDTH, CLK_MUX_READ_ONLY, NULL,
+							 &priv->lock);
+	if (IS_ERR(mux))
+		return PTR_ERR(mux);
+	sys = devm_clk_hw_register_divider_parent_hw(dev, "aon_sys", mux,
+						     CLK_IS_CRITICAL | CLK_GET_RATE_NOCACHE,
+						     base + AON_CLOCK_CONFIG, 0, AON_DIVIDER_WIDTH,
+						     CLK_DIVIDER_READ_ONLY, &priv->lock);
+	if (IS_ERR(sys))
+		return PTR_ERR(sys);
+	priv->data.hws[A210_AON_SYS_CLK] = sys;
+
+	for (i = 0; i < 2; i++) {
+		const char *name = i ? "aon_i2c1_pclk" : "aon_i2c1_ic_clk";
+		unsigned int bit = i ? AON_I2C1_APB_ENABLE : AON_I2C1_IC_ENABLE;
+
+		hw = devm_clk_hw_register_gate_parent_hw(dev, name, sys, 0,
+							 base + AON_CLOCK_GATE, bit, 0,
+							 &priv->lock);
+		if (IS_ERR(hw))
+			return PTR_ERR(hw);
+		priv->data.hws[A210_AON_I2C1_IC_CLK + i] = hw;
+	}
+
+	return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, &priv->data);
+}
+
+static const struct of_device_id a210_aon_clock_match[] = {
+	{ .compatible = "zhihe,a210-aon-clk" },
+	{}
+};
+MODULE_DEVICE_TABLE(of, a210_aon_clock_match);
+
+static struct platform_driver a210_aon_clock_driver = {
+	.probe = a210_aon_clock_probe,
+	.driver = {
+		.name = "a210-aon-clock",
+		.of_match_table = a210_aon_clock_match,
+	},
+};
+module_platform_driver(a210_aon_clock_driver);
+
+MODULE_DESCRIPTION("Zhihe A210 AON peripheral clocks");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/zhihe/clk-a210-ap.c b/drivers/clk/zhihe/clk-a210-ap.c
new file mode 100644
index 000000000000..6f47388684bf
--- /dev/null
+++ b/drivers/clk/zhihe/clk-a210-ap.c
@@ -0,0 +1,2283 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2025 Zhihe Computing Limited.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/math.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/property.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+#include <dt-bindings/clock/zhihe,a210-clk.h>
+
+/* Serializes updates to registers shared by clocks in each controller. */
+static DEFINE_SPINLOCK(a210_clk_lock);
+
+#define div_mask(d) GENMASK((d)->width - 1, 0)
+
+#define PLL_RATE(_vco, _rate, _r, _b, _f, _p, _k)				\
+	{									\
+		.vco_rate = (_vco),						\
+		.rate = (_rate),						\
+		.refdiv = (_r),							\
+		.fbdiv = (_b),							\
+		.frac = (_f),							\
+		.postdiv1 = (_p),						\
+		.postdiv2 = (_k),						\
+	}
+
+#define REG_NAMED(n, _name)							\
+	[(n)] = { .name = (_name) }
+
+#define CLK(_type, _id, _name, _parent)						\
+	.type = (_type),							\
+	.id = (_id),								\
+	.name = (_name),							\
+	.parent = (_parent)
+
+#define PLL(_id, _name, _parent, _reg, _shift, _pll) {				\
+	CLK(A210_CLK_PLL, (_id), (_name), (_parent)),				\
+	.reg = (_reg),								\
+	.shift = (_shift),							\
+	.pll = (_pll),								\
+}
+
+#define PLL_POSTDIV(_id, _name, _parent, _reg, _pll) { \
+	CLK(A210_CLK_PLL_POSTDIV, (_id), (_name), (_parent)), \
+	.reg = (_reg), \
+	.pll = (_pll), \
+}
+
+#define FIXED_FACTOR(_id, _name, _parent, _mult, _div) {			\
+	CLK(A210_CLK_FIXED_FACTOR, (_id), (_name), (_parent)),			\
+	.fixed_factor = { .mult = (_mult), .div = (_div) },			\
+}
+
+#define DIV(_id, _name, _parent, _reg, _shift, _bit_idx, _width, _sync,		\
+	    _div_type, _min, _max) {						\
+	CLK(A210_CLK_DIVIDER, (_id), (_name), (_parent)),			\
+	.reg = (_reg),								\
+	.shift = (_shift),							\
+	.bit_idx = (_bit_idx),							\
+	.width = (_width),							\
+	.divider = {								\
+		.sync = (_sync),						\
+		.div_type = (_div_type),					\
+		.min = (_min),							\
+		.max = (_max)							\
+	}									\
+}
+
+#define DIV_CLOSEST(_id, _name, _parent, _reg, _shift, _bit_idx,		\
+		    _width, _sync, _div_type, _min, _max) {			\
+	CLK(A210_CLK_DIVIDER_CLOSEST, (_id), (_name), (_parent)),		\
+	.reg = (_reg),								\
+	.shift = (_shift),							\
+	.bit_idx = (_bit_idx),							\
+	.width = (_width),							\
+	.divider = {								\
+		.sync = (_sync),						\
+		.div_type = (_div_type),					\
+		.min = (_min),							\
+		.max = (_max)							\
+	}									\
+}
+
+#define GATE(_id, _name, _parent, _reg, _shift, _bit_idx) {			\
+	CLK(A210_CLK_GATE, (_id), (_name), (_parent)),				\
+	.reg = (_reg),								\
+	.shift = (_shift),							\
+	.bit_idx = (_bit_idx),							\
+}
+
+#define GATE_FLAGS(_id, _name, _parent, _reg, _shift, _bit_idx, _flags) {	\
+	CLK(A210_CLK_GATE, (_id), (_name), (_parent)),				\
+	.reg = (_reg),								\
+	.shift = (_shift),							\
+	.bit_idx = (_bit_idx),							\
+	.flags = (_flags),							\
+}
+
+#define GATE_SHARED(_id, _name, _parent, _reg, _shift, _bit_idx,		\
+		    _count, _flags) {						\
+	CLK(A210_CLK_GATE_SHARED, (_id), (_name), (_parent)),			\
+	.flags = (_flags),							\
+	.reg = (_reg),								\
+	.shift = (_shift),							\
+	.bit_idx = (_bit_idx),							\
+	.gate_shared = {							\
+		.share_count = (_count)						\
+	},									\
+}
+
+#define MUX(_id, _name, _reg, _shift, _bit_idx, _width, _parents, _flags) {	\
+	CLK(A210_CLK_MUX, (_id), (_name), ""),					\
+	.reg = (_reg),								\
+	.shift = (_shift),							\
+	.bit_idx = (_bit_idx),							\
+	.width = (_width),							\
+	.mux = {								\
+		.parents = (_parents),						\
+		.num_parents = ARRAY_SIZE(_parents),				\
+		.flags = (_flags)						\
+	},									\
+}
+
+#define PLL_PARAM(_pll, _out, _table, _cfg0, _sts, _lock,			\
+		  _bypass, _rst, _mode, _name)					\
+	[(_pll)] = {								\
+		.out_type = (_out),						\
+		.rate_table = (_table),						\
+		.rate_count = ARRAY_SIZE(_table),				\
+		.cfg0_reg_off = (_cfg0),					\
+		.pll_sts_off = (_sts),						\
+		.pll_lock_bit = (_lock),					\
+		.pll_bypass_bit = (_bypass),					\
+		.pll_rst_bit = (_rst),						\
+		.pll_mode = (_mode),						\
+		.name = (_name),						\
+	}
+
+#define CLK_SUBSYS(_name, _regs, _info) {					\
+	.name = (_name),							\
+	.regs = (_regs),							\
+	.num_regs = ARRAY_SIZE(_regs),						\
+	.info = (_info),							\
+	.num_info = ARRAY_SIZE(_info),						\
+}
+
+enum a210_pll_outtype {
+	A210_PLL_VCO,
+	A210_PLL_DIV,
+};
+
+enum a210_div_type {
+	MUX_TYPE_DIV,
+	MUX_TYPE_CDE,
+};
+
+enum a210_div_sync_type {
+	NO_DIV_EN = 255,
+};
+
+enum a210_clk_type {
+	A210_CLK_PLL,
+	A210_CLK_PLL_POSTDIV,
+	A210_CLK_FIXED_FACTOR,
+	A210_CLK_DIVIDER,
+	A210_CLK_DIVIDER_CLOSEST,
+	A210_CLK_GATE,
+	A210_CLK_GATE_SHARED,
+	A210_CLK_MUX,
+};
+
+enum a210_pll_mode {
+	PLL_MODE_FRAC,
+	PLL_MODE_INT,
+};
+
+struct a210_clk_reg {
+	void __iomem *base;
+	const char *name;
+};
+
+/* clk summary info at subsys level */
+struct a210_ccu {
+	const char *name;
+	struct a210_clk_reg *regs;
+	u32 num_regs;
+	const struct a210_clk_desc *info;
+	u32 num_info;
+	struct clk_hw_onecell_data *clk_data;
+	struct clk_bulk_data *inputs;
+	int num_inputs;
+};
+
+struct a210_pll {
+	struct clk_hw hw;
+	void __iomem *base;
+	enum a210_pll_outtype out_type;
+	enum a210_pll_mode pll_mode;
+	const struct a210_pll_rate *rate_table;
+	int rate_count;
+
+	u32 cfg0_reg_off;
+	u32 pll_sts_off;
+	int pll_lock_bit;
+	int pll_rst_bit;
+	int pll_bypass_bit;
+};
+
+struct a210_div {
+	struct clk_divider divider;
+	enum a210_div_type div_type;
+	u8 sync_en;
+	struct clk_div_table table[];
+};
+
+struct a210_shared_gate {
+	struct clk_gate gate;
+	unsigned int *share_count;
+	const struct clk_ops *ops;
+};
+
+struct a210_pll_rate {
+	unsigned long vco_rate;
+	unsigned long rate;
+	unsigned int refdiv;
+	unsigned int fbdiv;
+	unsigned int frac;
+	unsigned int postdiv1;
+	unsigned int postdiv2;
+};
+
+/* detailed clk info for each clk */
+
+struct a210_pll_desc {
+	enum a210_pll_outtype out_type;
+	const struct a210_pll_rate *rate_table;
+	int rate_count;
+	int flags;
+	const char *name;
+	u32 cfg0_reg_off;
+	u32 pll_sts_off;
+	int pll_lock_bit;
+	int pll_rst_bit;
+	int pll_bypass_bit;
+	enum a210_pll_mode pll_mode;
+};
+
+struct a210_factor_desc {
+	unsigned int mult;
+	unsigned int div;
+};
+
+struct a210_div_desc {
+	u8 sync;
+	enum a210_div_type div_type;
+	u16 min;
+	u16 max;
+};
+
+struct a210_shared_gate_desc {
+	unsigned int *share_count;
+};
+
+struct a210_mux_desc {
+	const char *const *parents;
+	int num_parents;
+	unsigned long flags;
+};
+
+struct a210_clk_desc {
+	enum a210_clk_type type;
+	u32 id;
+	const char *name;
+	const char *parent;
+	u8 reg;
+	u32 shift;
+	u8 width;
+	u8 bit_idx;
+	unsigned long flags;
+	union {
+		struct a210_factor_desc fixed_factor;
+		const struct a210_pll_desc *pll;
+		struct a210_div_desc divider;
+		struct a210_shared_gate_desc gate_shared;
+		struct a210_mux_desc mux;
+	};
+};
+
+#define A210_PLL_CFG0 0x0
+#define A210_PLL_CFG1 0x04
+#define A210_PLL_CFG2 0x8
+#define A210_POSTDIV2_SHIFT 24
+#define A210_POSTDIV2_MASK GENMASK(26, 24)
+#define A210_POSTDIV1_SHIFT 20
+#define A210_POSTDIV1_MASK GENMASK(22, 20)
+#define A210_FBDIV_SHIFT 8
+#define A210_FBDIV_MASK GENMASK(19, 8)
+#define A210_REFDIV_SHIFT 0
+#define A210_REFDIV_MASK GENMASK(5, 0)
+#define A210_BYPASS_MASK BIT(30)
+#define A210_RST_MASK BIT(29)
+#define A210_DSMPD_MASK BIT(24)
+#define A210_DACPD_MASK BIT(25)
+#define A210_FRAC_MASK GENMASK(23, 0)
+#define A210_FRAC_SHIFT 0
+#define A210_FRAC_DIV BIT(24)
+
+#define LOCK_TIMEOUT_US 10000
+
+#define to_a210_pll(_hw) container_of(_hw, struct a210_pll, hw)
+
+static int a210_pll_wait_lock(struct a210_pll *pll)
+{
+	u32 val;
+
+	return readl_poll_timeout(pll->base + pll->pll_sts_off, val, val & pll->pll_lock_bit, 0,
+				  LOCK_TIMEOUT_US);
+}
+
+static int a210_pll_prepare(struct clk_hw *hw)
+{
+	struct a210_pll *pll = to_a210_pll(hw);
+	void __iomem *cfg1_off;
+	u32 val;
+	int ret;
+
+	cfg1_off = pll->base + pll->cfg0_reg_off + A210_PLL_CFG1;
+	val = readl_relaxed(cfg1_off);
+	if (!(val & pll->pll_rst_bit))
+		return 0;
+
+	/* Enable RST */
+	val |= pll->pll_rst_bit;
+	writel_relaxed(val, cfg1_off);
+
+	udelay(3);
+
+	/* Disable RST */
+	val &= ~pll->pll_rst_bit;
+	writel_relaxed(val, cfg1_off);
+
+	ret = a210_pll_wait_lock(pll);
+	if (ret)
+		writel_relaxed(val | pll->pll_rst_bit, cfg1_off);
+
+	return ret;
+}
+
+static int a210_pll_is_prepared(struct clk_hw *hw)
+{
+	struct a210_pll *pll = to_a210_pll(hw);
+	u32 val;
+
+	val = readl_relaxed(pll->base + pll->cfg0_reg_off + A210_PLL_CFG1);
+
+	return (val & pll->pll_rst_bit) ? 0 : 1;
+}
+
+static void a210_pll_unprepare(struct clk_hw *hw)
+{
+	struct a210_pll *pll = to_a210_pll(hw);
+	u32 val;
+
+	val = readl_relaxed(pll->base + pll->cfg0_reg_off + A210_PLL_CFG1);
+	val |= pll->pll_rst_bit;
+	writel_relaxed(val, pll->base + pll->cfg0_reg_off + A210_PLL_CFG1);
+}
+
+static unsigned long a210_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
+{
+	struct a210_pll *pll = to_a210_pll(hw);
+	u32 refdiv, fbdiv, postdiv1, postdiv2, frac;
+	u32 pll_cfg0, pll_cfg1;
+	u64 fvco = 0;
+
+	pll_cfg0 = readl_relaxed(pll->base + pll->cfg0_reg_off);
+	pll_cfg1 = readl_relaxed(pll->base + pll->cfg0_reg_off + A210_PLL_CFG1);
+	if (pll->out_type == A210_PLL_DIV && (pll_cfg1 & pll->pll_bypass_bit))
+		return parent_rate;
+
+	refdiv = (pll_cfg0 & A210_REFDIV_MASK) >> A210_REFDIV_SHIFT;
+	fbdiv = (pll_cfg0 & A210_FBDIV_MASK) >> A210_FBDIV_SHIFT;
+	postdiv1 = (pll_cfg0 & A210_POSTDIV1_MASK) >> A210_POSTDIV1_SHIFT;
+	postdiv2 = (pll_cfg0 & A210_POSTDIV2_MASK) >> A210_POSTDIV2_SHIFT;
+	frac = (pll_cfg1 & A210_FRAC_MASK) >> A210_FRAC_SHIFT;
+
+	if (!refdiv || (pll->out_type == A210_PLL_DIV && (!postdiv1 || !postdiv2)))
+		return 0;
+
+	/* Read the mode selected by firmware until a rate change requests it. */
+	if (!(pll_cfg1 & A210_DSMPD_MASK))
+		fvco = ((u64)parent_rate * frac) / A210_FRAC_DIV;
+
+	fvco += (u64)parent_rate * fbdiv;
+	do_div(fvco, refdiv);
+
+	if (pll->out_type == A210_PLL_DIV)
+		do_div(fvco, postdiv1 * postdiv2);
+
+	return fvco;
+}
+
+static const struct a210_pll_rate *a210_get_pll_div_settings(struct a210_pll *pll,
+							     unsigned long rate)
+{
+	const struct a210_pll_rate *rate_table = pll->rate_table;
+	int i;
+
+	for (i = 0; i < pll->rate_count; i++)
+		if (rate == rate_table[i].rate)
+			return &rate_table[i];
+
+	return NULL;
+}
+
+static const struct a210_pll_rate *a210_get_pll_vco_settings(struct a210_pll *pll,
+							     unsigned long rate)
+{
+	const struct a210_pll_rate *rate_table = pll->rate_table;
+	int i;
+
+	for (i = 0; i < pll->rate_count; i++)
+		if (rate == rate_table[i].vco_rate)
+			return &rate_table[i];
+
+	return NULL;
+}
+
+static inline bool a210_pll_change(struct a210_pll *pll, const struct a210_pll_rate *rate)
+{
+	u32 refdiv_old, fbdiv_old, postdiv1_old, postdiv2_old, frac_old;
+	u32 cfg0, cfg1;
+	bool pll_changed;
+
+	cfg0 = readl_relaxed(pll->base + pll->cfg0_reg_off);
+	cfg1 = readl_relaxed(pll->base + pll->cfg0_reg_off + A210_PLL_CFG1);
+
+	refdiv_old = (cfg0 & A210_REFDIV_MASK) >> A210_REFDIV_SHIFT;
+	fbdiv_old = (cfg0 & A210_FBDIV_MASK) >> A210_FBDIV_SHIFT;
+	postdiv1_old = (cfg0 & A210_POSTDIV1_MASK) >> A210_POSTDIV1_SHIFT;
+	postdiv2_old = (cfg0 & A210_POSTDIV2_MASK) >> A210_POSTDIV2_SHIFT;
+	frac_old = (cfg1 & A210_FRAC_MASK) >> A210_FRAC_SHIFT;
+
+	pll_changed = (pll->out_type == A210_PLL_DIV && (cfg1 & pll->pll_bypass_bit)) ||
+		      (!!(cfg1 & A210_DSMPD_MASK) != (pll->pll_mode == PLL_MODE_INT)) ||
+		      rate->refdiv != refdiv_old || rate->fbdiv != fbdiv_old ||
+		      rate->postdiv1 != postdiv1_old || rate->postdiv2 != postdiv2_old;
+	if (pll->pll_mode == PLL_MODE_FRAC)
+		pll_changed |= (rate->frac != frac_old);
+
+	return pll_changed;
+}
+
+static int a210_pll_set_rate(struct clk_hw *hw, unsigned long drate, unsigned long prate)
+{
+	struct a210_pll *pll = to_a210_pll(hw);
+	const struct a210_pll_rate *rate;
+	void __iomem *cfg1_off;
+	u32 tmp, div_val, old_cfg0, old_cfg1;
+	int ret;
+
+	if (pll->out_type == A210_PLL_VCO) {
+		rate = a210_get_pll_vco_settings(pll, drate);
+		if (!rate) {
+			pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__, drate,
+			       clk_hw_get_name(hw));
+			return -EINVAL;
+		}
+	} else {
+		rate = a210_get_pll_div_settings(pll, drate);
+		if (!rate) {
+			pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__, drate,
+			       clk_hw_get_name(hw));
+			return -EINVAL;
+		}
+	}
+
+	if (!a210_pll_change(pll, rate))
+		return 0;
+
+	/* Enable RST */
+	cfg1_off = pll->base + pll->cfg0_reg_off + A210_PLL_CFG1;
+	old_cfg0 = readl_relaxed(pll->base + pll->cfg0_reg_off);
+	old_cfg1 = readl_relaxed(cfg1_off);
+	tmp = old_cfg1 | pll->pll_rst_bit;
+	writel_relaxed(tmp, cfg1_off);
+
+	div_val = (rate->refdiv << A210_REFDIV_SHIFT) | (rate->fbdiv << A210_FBDIV_SHIFT) |
+		  (rate->postdiv1 << A210_POSTDIV1_SHIFT) | (rate->postdiv2 << A210_POSTDIV2_SHIFT);
+	div_val |= old_cfg0 &
+		   ~(A210_REFDIV_MASK | A210_FBDIV_MASK | A210_POSTDIV1_MASK | A210_POSTDIV2_MASK);
+	writel_relaxed(div_val, pll->base + pll->cfg0_reg_off);
+
+	tmp &= ~(A210_FRAC_MASK | A210_DSMPD_MASK | A210_DACPD_MASK);
+	if (pll->pll_mode == PLL_MODE_FRAC)
+		tmp |= rate->frac;
+	else
+		tmp |= A210_DSMPD_MASK | A210_DACPD_MASK;
+	writel_relaxed(tmp, cfg1_off);
+
+	udelay(3);
+
+	/* Disable RST */
+	tmp &= ~pll->pll_rst_bit;
+	writel_relaxed(tmp, cfg1_off);
+
+	ret = a210_pll_wait_lock(pll);
+	if (ret) {
+		/* Restore the previous configuration on a failed transition. */
+		writel_relaxed(tmp | pll->pll_rst_bit, cfg1_off);
+		writel_relaxed(old_cfg0, pll->base + pll->cfg0_reg_off);
+		writel_relaxed(old_cfg1, cfg1_off);
+		return ret;
+	}
+
+	/* Retain the reference settling time before selecting the PLL output. */
+	usleep_range(30, 40);
+	if (pll->out_type == A210_PLL_DIV)
+		tmp &= ~pll->pll_bypass_bit;
+	tmp |= old_cfg1 & pll->pll_rst_bit;
+	writel_relaxed(tmp, cfg1_off);
+
+	return 0;
+}
+
+static int a210_pllvco_determine_rate(struct clk_hw *hw, struct clk_rate_request *req)
+{
+	struct a210_pll *pll = to_a210_pll(hw);
+	const struct a210_pll_rate *rate_table = pll->rate_table;
+	unsigned long best_diff;
+	unsigned int best_i = 0;
+	unsigned int i;
+
+	if (!pll->rate_count)
+		return -EINVAL;
+
+	best_diff = abs_diff(rate_table[0].vco_rate, req->rate);
+
+	for (i = 1; i < pll->rate_count; i++) {
+		unsigned long diff = abs_diff(rate_table[i].vco_rate, req->rate);
+
+		if (diff < best_diff) {
+			best_diff = diff;
+			best_i = i;
+		}
+	}
+
+	req->rate = rate_table[best_i].vco_rate;
+
+	return 0;
+}
+
+static int a210_plldiv_determine_rate(struct clk_hw *hw, struct clk_rate_request *req)
+{
+	struct a210_pll *pll = to_a210_pll(hw);
+	const struct a210_pll_rate *rate_table = pll->rate_table;
+	unsigned long best_diff;
+	unsigned int best_i = 0;
+	unsigned int i;
+
+	if (!pll->rate_count)
+		return -EINVAL;
+
+	best_diff = abs_diff(rate_table[0].rate, req->rate);
+
+	for (i = 1; i < pll->rate_count; i++) {
+		unsigned long diff = abs_diff(rate_table[i].rate, req->rate);
+
+		if (diff < best_diff) {
+			best_diff = diff;
+			best_i = i;
+		}
+	}
+
+	req->rate = rate_table[best_i].rate;
+
+	return 0;
+}
+
+static const struct clk_ops a210_pll_def_ops = {
+	.recalc_rate = a210_pll_recalc_rate,
+};
+
+static const struct clk_ops a210_pllvco_ops = {
+	.prepare = a210_pll_prepare,
+	.unprepare = a210_pll_unprepare,
+	.is_prepared = a210_pll_is_prepared,
+	.recalc_rate = a210_pll_recalc_rate,
+	.determine_rate = a210_pllvco_determine_rate,
+	.set_rate = a210_pll_set_rate,
+};
+
+static const struct clk_ops a210_plldiv_ops = {
+	.prepare = a210_pll_prepare,
+	.unprepare = a210_pll_unprepare,
+	.is_prepared = a210_pll_is_prepared,
+	.recalc_rate = a210_pll_recalc_rate,
+	.determine_rate = a210_plldiv_determine_rate,
+	.set_rate = a210_pll_set_rate,
+};
+
+static struct clk_hw *a210_register_pll(struct device *dev, const char *name,
+					const char *parent_name, void __iomem *base,
+					const struct a210_pll_desc *pll_clk)
+{
+	struct a210_pll *pll;
+	int ret;
+	struct clk_init_data init = {};
+
+	pll = devm_kzalloc(dev, sizeof(*pll), GFP_KERNEL);
+	if (!pll)
+		return ERR_PTR(-ENOMEM);
+
+	init.name = name;
+	init.flags = pll_clk->flags | CLK_SET_RATE_GATE;
+	init.parent_names = &parent_name;
+	init.num_parents = 1;
+
+	switch (pll_clk->out_type) {
+	case A210_PLL_VCO:
+		if (pll_clk->rate_table)
+			init.ops = &a210_pllvco_ops;
+		break;
+	case A210_PLL_DIV:
+		if (pll_clk->rate_table)
+			init.ops = &a210_plldiv_ops;
+		break;
+	default:
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (!pll_clk->rate_table)
+		init.ops = &a210_pll_def_ops;
+
+	pll->base = base;
+	pll->hw.init = &init;
+	pll->out_type = pll_clk->out_type;
+	pll->rate_table = pll_clk->rate_table;
+	pll->rate_count = pll_clk->rate_count;
+	pll->cfg0_reg_off = pll_clk->cfg0_reg_off;
+	pll->pll_sts_off = pll_clk->pll_sts_off;
+	pll->pll_lock_bit = pll_clk->pll_lock_bit;
+	pll->pll_bypass_bit = pll_clk->pll_bypass_bit;
+	pll->pll_rst_bit = pll_clk->pll_rst_bit;
+	pll->pll_mode = pll_clk->pll_mode;
+
+	/* Registration must preserve the firmware-selected PLL state. */
+	ret = devm_clk_hw_register(dev, &pll->hw);
+	if (ret)
+		return ERR_PTR(ret);
+
+	return &pll->hw;
+}
+
+static u8 a210_postdiv_get_parent(struct clk_hw *hw)
+{
+	struct a210_pll *pll = to_a210_pll(hw);
+	u32 value = readl_relaxed(pll->base + pll->cfg0_reg_off + A210_PLL_CFG1);
+
+	return !!(value & pll->pll_bypass_bit);
+}
+
+static unsigned long a210_postdiv_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
+{
+	struct a210_pll *pll = to_a210_pll(hw);
+	u32 value, div1, div2;
+
+	if (a210_postdiv_get_parent(hw))
+		return parent_rate;
+
+	value = readl_relaxed(pll->base + pll->cfg0_reg_off);
+	div1 = (value & A210_POSTDIV1_MASK) >> A210_POSTDIV1_SHIFT;
+	div2 = (value & A210_POSTDIV2_MASK) >> A210_POSTDIV2_SHIFT;
+	if (!div1 || !div2)
+		return 0;
+
+	return parent_rate / (div1 * div2);
+}
+
+static const struct clk_ops a210_postdiv_ops = {
+	.get_parent = a210_postdiv_get_parent,
+	.recalc_rate = a210_postdiv_recalc_rate,
+};
+
+static struct clk_hw *a210_register_postdiv(struct device *dev, const char *name,
+					    const char *parent_name, void __iomem *base,
+					    const struct a210_pll_desc *pll_clk)
+{
+	const char *const parents[] = { parent_name, "pll_osc_clk" };
+	struct clk_init_data init = {
+		.name = name,
+		.ops = &a210_postdiv_ops,
+		.parent_names = parents,
+		.num_parents = ARRAY_SIZE(parents),
+	};
+	struct a210_pll *pll;
+	int ret;
+
+	pll = devm_kzalloc(dev, sizeof(*pll), GFP_KERNEL);
+	if (!pll)
+		return ERR_PTR(-ENOMEM);
+
+	pll->base = base;
+	pll->cfg0_reg_off = pll_clk->cfg0_reg_off;
+	pll->pll_bypass_bit = pll_clk->pll_bypass_bit;
+	pll->hw.init = &init;
+	ret = devm_clk_hw_register(dev, &pll->hw);
+	if (ret)
+		return ERR_PTR(ret);
+
+	return &pll->hw;
+}
+
+static inline struct a210_div *to_a210_div(struct clk_hw *hw)
+{
+	struct clk_divider *divider = to_clk_divider(hw);
+
+	return container_of(divider, struct a210_div, divider);
+}
+
+static unsigned long a210_div_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
+{
+	struct a210_div *cd = to_a210_div(hw);
+	struct clk_divider *div = &cd->divider;
+	u32 value = (readl(div->reg) >> div->shift) & div_mask(div);
+	unsigned long flags = cd->div_type == MUX_TYPE_DIV ? CLK_DIVIDER_ONE_BASED : 0;
+
+	/* Report the actual firmware setting even outside the writable range. */
+	return divider_recalc_rate(hw, parent_rate, value, NULL, flags, div->width);
+}
+
+static int a210_div_determine_rate(struct clk_hw *hw, struct clk_rate_request *req)
+{
+	struct a210_div *cd = to_a210_div(hw);
+	struct clk_divider *div = &cd->divider;
+
+	return divider_determine_rate(hw, req, div->table, div->width, div->flags);
+}
+
+static int a210_div_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate)
+{
+	struct a210_div *cd = to_a210_div(hw);
+	struct clk_divider *div = to_clk_divider(hw);
+	int value;
+	unsigned long flags = 0;
+	u32 val;
+
+	if (!rate)
+		return -EINVAL;
+
+	value = divider_get_val(rate, parent_rate, div->table, div->width, div->flags);
+	if (value < 0)
+		return value;
+
+	spin_lock_irqsave(div->lock, flags);
+
+	val = readl(div->reg);
+
+	if (cd->sync_en != NO_DIV_EN) {
+		val &= ~BIT(cd->sync_en);
+		writel(val, div->reg);
+		udelay(1);
+	}
+
+	val &= ~(div_mask(div) << div->shift);
+	val |= value << div->shift;
+	writel(val, div->reg);
+
+	if (cd->sync_en != NO_DIV_EN) {
+		udelay(1);
+		val |= BIT(cd->sync_en);
+		writel(val, div->reg);
+	}
+
+	spin_unlock_irqrestore(div->lock, flags);
+
+	return 0;
+}
+
+static const struct clk_ops a210_div_ops = {
+	.recalc_rate = a210_div_recalc_rate,
+	.determine_rate = a210_div_determine_rate,
+	.set_rate = a210_div_set_rate,
+};
+
+static struct clk_hw *a210_register_divider(struct device *dev, const char *name,
+					    const char *parent, void __iomem *reg, u8 shift,
+					    u8 width, u8 sync, enum a210_div_type div_type, u16 min,
+					    u16 max, bool closest)
+{
+	struct a210_div *div;
+	struct clk_hw *hw;
+	struct clk_init_data init;
+	unsigned int i, count;
+	int ret;
+
+	if (!width || width > 16 || min > max || max >= BIT(width) ||
+	    (div_type == MUX_TYPE_DIV && !min))
+		return ERR_PTR(-EINVAL);
+
+	count = max - min + 1;
+	div = devm_kzalloc(dev, struct_size(div, table, count + 1), GFP_KERNEL);
+	if (!div)
+		return ERR_PTR(-ENOMEM);
+
+	init.name = name;
+	init.ops = &a210_div_ops;
+	init.flags = CLK_SET_RATE_PARENT;
+	init.parent_names = parent ? &parent : NULL;
+	init.num_parents = parent ? 1 : 0;
+
+	div->divider.reg = reg;
+	div->divider.shift = shift;
+	div->divider.width = width;
+	div->divider.lock = &a210_clk_lock;
+	div->divider.hw.init = &init;
+	div->sync_en = sync;
+	div->div_type = div_type;
+	if (closest)
+		div->divider.flags = CLK_DIVIDER_ROUND_CLOSEST;
+
+	for (i = 0; i < count; i++) {
+		div->table[i].val = min + i;
+		div->table[i].div = min + i + (div_type == MUX_TYPE_CDE);
+	}
+	div->divider.table = div->table;
+
+	hw = &div->divider.hw;
+
+	ret = devm_clk_hw_register(dev, hw);
+	if (ret)
+		return ERR_PTR(ret);
+
+	return hw;
+}
+
+static inline struct a210_shared_gate *to_a210_shared_gate(struct clk_hw *hw)
+{
+	struct clk_gate *gate = to_clk_gate(hw);
+
+	return container_of(gate, struct a210_shared_gate, gate);
+}
+
+static int a210_shared_gate_is_enabled(struct clk_hw *hw)
+{
+	struct a210_shared_gate *gate = to_a210_shared_gate(hw);
+
+	return gate->ops->is_enabled(hw);
+}
+
+static int a210_shared_gate_enable(struct clk_hw *hw)
+{
+	struct a210_shared_gate *gate = to_a210_shared_gate(hw);
+
+	if (gate->share_count && (*gate->share_count)++ > 0)
+		return 0;
+
+	return gate->ops->enable(hw);
+}
+
+static void a210_shared_gate_disable(struct clk_hw *hw)
+{
+	struct a210_shared_gate *gate = to_a210_shared_gate(hw);
+
+	if (gate->share_count) {
+		if (WARN_ON(*gate->share_count == 0))
+			return;
+		else if (--(*gate->share_count) > 0)
+			return;
+	}
+
+	gate->ops->disable(hw);
+}
+
+static void a210_shared_gate_disable_unused(struct clk_hw *hw)
+{
+	struct a210_shared_gate *gate = to_a210_shared_gate(hw);
+
+	if (!gate->share_count || *gate->share_count == 0)
+		return gate->ops->disable(hw);
+}
+
+static const struct clk_ops a210_shared_gate_ops = {
+	.enable = a210_shared_gate_enable,
+	.disable = a210_shared_gate_disable,
+	.disable_unused = a210_shared_gate_disable_unused,
+	.is_enabled = a210_shared_gate_is_enabled,
+};
+
+static struct clk_hw *a210_register_shared_gate(struct device *dev, const char *name,
+						const char *parent, unsigned long flags,
+						void __iomem *reg, u8 shift, spinlock_t *lock,
+						unsigned int *share_count)
+{
+	struct a210_shared_gate *gate;
+	struct clk_hw *hw;
+	struct clk_init_data init;
+	int ret;
+
+	gate = devm_kzalloc(dev, sizeof(*gate), GFP_KERNEL);
+	if (!gate)
+		return ERR_PTR(-ENOMEM);
+
+	gate->gate.reg = reg;
+	gate->gate.bit_idx = shift;
+	gate->gate.flags = 0;
+	gate->gate.lock = lock;
+	gate->gate.hw.init = &init;
+	gate->ops = &clk_gate_ops;
+	gate->share_count = share_count;
+
+	init.name = name;
+	init.ops = &a210_shared_gate_ops;
+	init.flags = flags;
+	init.parent_names = parent ? &parent : NULL;
+	init.num_parents = parent ? 1 : 0;
+
+	hw = &gate->gate.hw;
+
+	ret = devm_clk_hw_register(dev, hw);
+	if (ret)
+		return ERR_PTR(ret);
+
+	return hw;
+}
+
+static int a210_map_registers(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct a210_ccu *priv = dev_get_drvdata(dev);
+	int ret = 0;
+
+	for (int i = 0; i < priv->num_regs; i++) {
+		priv->regs[i].base =
+			devm_platform_ioremap_resource_byname(pdev, priv->regs[i].name);
+		if (IS_ERR(priv->regs[i].base)) {
+			ret = PTR_ERR(priv->regs[i].base);
+			return ret;
+		}
+	}
+
+	return ret;
+}
+
+static int a210_register_clocks(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct a210_ccu *priv = dev_get_drvdata(dev);
+	struct clk_hw **hws = priv->clk_data->hws;
+	int i;
+
+	for (i = 0; i < priv->num_info; i++) {
+		const struct a210_clk_desc *info = &priv->info[i];
+		const char *name = info->name;
+		const char *parent = info->parent;
+		struct clk_hw *hw;
+		void __iomem *base;
+		u32 id = info->id;
+		int j;
+
+		for (j = 0; j < priv->num_inputs; j++)
+			if (priv->inputs[j].id && !strcmp(parent, priv->inputs[j].id)) {
+				parent = __clk_get_name(priv->inputs[j].clk);
+				break;
+			}
+
+		if (id >= priv->clk_data->num)
+			return dev_err_probe(dev, -EINVAL, "invalid clock id %u for %s\n", id,
+					     info->name);
+		if (info->reg >= priv->num_regs)
+			return dev_err_probe(dev, -EINVAL, "invalid register index %u for %s\n",
+					     info->reg, info->name);
+
+		base = priv->regs[info->reg].base + info->shift;
+
+		switch (info->type) {
+		case A210_CLK_FIXED_FACTOR:
+			hw = devm_clk_hw_register_fixed_factor(dev, name, parent,
+							       CLK_SET_RATE_PARENT,
+							       info->fixed_factor.mult,
+							       info->fixed_factor.div);
+			break;
+		case A210_CLK_PLL:
+			hw = a210_register_pll(dev, name, parent, base, info->pll);
+			break;
+		case A210_CLK_PLL_POSTDIV:
+			hw = a210_register_postdiv(dev, name, parent, base, info->pll);
+			break;
+		case A210_CLK_DIVIDER:
+		case A210_CLK_DIVIDER_CLOSEST:
+			hw = a210_register_divider(dev, name, parent, base, info->bit_idx,
+						   info->width, info->divider.sync,
+						   info->divider.div_type, info->divider.min,
+						   info->divider.max,
+						   info->type == A210_CLK_DIVIDER_CLOSEST);
+			break;
+		case A210_CLK_GATE:
+			hw = devm_clk_hw_register_gate(dev, name, parent,
+						       CLK_SET_RATE_PARENT | info->flags, base,
+						       info->bit_idx, 0, &a210_clk_lock);
+			break;
+		case A210_CLK_GATE_SHARED:
+			hw = a210_register_shared_gate(dev, name, parent,
+						       CLK_SET_RATE_PARENT | info->flags, base,
+						       info->bit_idx, &a210_clk_lock,
+						       info->gate_shared.share_count);
+			break;
+		case A210_CLK_MUX:
+			hw = devm_clk_hw_register_mux(dev, name, info->mux.parents,
+						      info->mux.num_parents, info->mux.flags, base,
+						      info->bit_idx, info->width, 0,
+						      &a210_clk_lock);
+			break;
+		default:
+			return dev_err_probe(dev, -EINVAL, "invalid clock type %u for %s\n",
+					     info->type, name);
+		}
+
+		if (IS_ERR(hw))
+			return dev_err_probe(dev, PTR_ERR(hw), "failed to register clock %s\n",
+					     name);
+		hws[id] = hw;
+	}
+
+	return 0;
+}
+
+/* top reg idx */
+#define PLL_WRAP 0
+#define TOP_CRG 1
+#define CPU_SS_CLK_SYSREG 2
+#define CPU_SS_CPU_PLL 3
+#define DDR0_SYSREG 4
+#define DDR1_SYSREG 5
+#define SLC_DUAL_SYSREG 6
+#define TOP_CRG_T 7
+#define CPU_SS_CCU 8
+/* gpu reg idx */
+#define GPU_SS_PWRAP_CLK_EN 0
+#define GPU_SS_TOP_CLK_EN 1
+/* pcie reg idx */
+#define PCIE_CLK_EN 0
+/* usb reg idx */
+#define USB_CLK_EN 0
+/* vi reg idx */
+#define VI_CLK 0
+#define VI_MISC_CTRL 1
+/* vp reg idx */
+#define VP_CLK 0
+/* vo reg idx */
+#define VO_CLK 0
+#define VO_PATH_CTRL 1
+/* npu reg idx */
+#define NPU_CLK 0
+#define NPU_TOP_CLK 1
+/* peri reg idx */
+#define PERI0_SYSREG 0
+#define PERI1_SYSREG 1
+#define PERI2_SYSREG 2
+#define PERI3_SYSREG 3
+#define TEE_CRG 4
+
+static u32 share_cnt_ddr_pll_clk_en;
+
+enum a210_pll_clktype {
+	AUDIO0_PLL,
+	AUDIO1_PLL,
+	VIDEO_PLL,
+	GMAC_PLL,
+	DVFS_PLL,
+	DPU0_PLL,
+	DPU1_PLL,
+	DPU2_PLL,
+	TEE_PLL,
+	DDR_PLL,
+	C920_PLL,
+	C908_PLL,
+};
+
+static const char *const uart_sclk_parents[] = {
+	"uart_sclk_100m",
+	"aon_osc_clk_logic",
+};
+
+static const char *const noc_cclk_mux_parents[] = {
+	"dpu1_pll_foutvco",
+	"video_pll_foutvco",
+	"gmac_pll_foutvco",
+};
+
+static const char *const top_cpu_ddr1_aclk_parents[] = {
+	"cbus2ddr_aclk1",
+	"gmac_pll_foutpostdiv",
+};
+
+static const char *const top_cpu_ddr0_aclk_parents[] = {
+	"cbus2ddr_aclk0",
+	"gmac_pll_foutpostdiv",
+};
+
+static const char *const ddr_pll_clkout_parents[] = {
+	"ddr_pll_foutpostdiv",
+	"ddr_pll_fout1ph0",
+	"ddr_pll_fout2",
+};
+
+static const char *const top_cpu_bak_pll0_clk_mux0_parents[] = {
+	"audio0_pll_foutvco",
+	"dvfs_pll_foutvco",
+	"top_cpu_bak_pll0_clk_div0",
+	"top_cpu_bak_pll0_clk_div1",
+};
+
+static const char *const top_cpu_bak_pll0_clk_mux_parents[] = {
+	"dpu1_pll_foutvco",	     "top_cpu_bak_pll0_clk_mux0", "dvfs_pll_foutvco",
+	"audio0_pll_foutvco",	     "top_cpu_bak_pll0_clk_div0", "top_cpu_bak_pll0_clk_div4",
+	"top_cpu_bak_pll0_clk_div3", "top_cpu_bak_pll0_clk_div1",
+};
+
+static const char *const top_cpu_bak_pll1_clk_mux0_parents[] = {
+	"audio0_pll_foutvco",
+	"dvfs_pll_foutvco",
+	"top_cpu_bak_pll1_clk_div0",
+	"top_cpu_bak_pll1_clk_div1",
+};
+
+static const char *const top_cpu_bak_pll1_clk_mux_parents[] = {
+	"dpu1_pll_foutvco",	     "top_cpu_bak_pll1_clk_mux0", "dvfs_pll_foutvco",
+	"audio0_pll_foutvco",	     "top_cpu_bak_pll1_clk_div0", "top_cpu_bak_pll1_clk_div4",
+	"top_cpu_bak_pll1_clk_div3", "top_cpu_bak_pll1_clk_div1",
+};
+
+static const char *const top_cpusys_pic_clk_mux_parents[] = {
+	"gmac_pll_foutvco",
+	"video_pll_foutvco",
+};
+
+static const char *const top_cpusys_bus_clk_mux_parents[] = {
+	"video_pll_foutvco",
+	"gmac_pll_foutvco",
+	"audio0_pll_foutvco",
+	"dpu2_pll_foutvco",
+};
+
+static const char *const d2d_phy_ref_clk_parents[] = {
+	"d2d_phy_ref_clk_100M",
+	"aon_osc_clk_logic",
+};
+
+static const char *const top_d2d_aclk_mux_parents[] = {
+	"dpu1_pll_foutvco",
+	"gmac_pll_foutvco",
+	"audio1_pll_foutvco",
+	"audio0_pll_foutvco",
+};
+
+static const char *const top_gpu_core_clk_mux_parents[] = {
+	"dpu2_pll_foutvco",
+	"video_pll_foutvco",
+	"dvfs_pll_foutvco",
+	"audio0_pll_foutvco",
+};
+
+static const char *const pcie_ss_axi_m_aclk_mux_parents[] = {
+	"audio0_pll_foutvco",
+	"video_pll_foutvco",
+};
+
+static const char *const peri0_timer_clk_parents[] = {
+	"peri0_timer_clk_100M",
+	"aon_osc_clk_logic",
+};
+
+static const char *const peri2_i2s3_src_clk_parents[] = {
+	"audio1_pll_fout2",
+	"audio0_pll_fout2",
+};
+
+static const char *const peri1_i2s0_src_clk_parents[] = {
+	"audio1_pll_fout2",
+	"audio0_pll_fout2",
+};
+
+static const char *const peri2_i2s1_src_clk_parents[] = {
+	"audio1_pll_fout2",
+	"audio0_pll_fout2",
+};
+
+static const char *const peri2_i2s2_src_clk_parents[] = {
+	"audio1_pll_fout2",
+	"audio0_pll_fout2",
+};
+
+static const char *const peri1_qspi_ssi_clk_parents[] = {
+	"peri1_qspi_ssi_clk_div1",
+	"peri1_qspi_ssi_clk_div0",
+};
+
+static const char *const peri2_qspi_ssi_clk_parents[] = {
+	"peri2_qspi_ssi_clk_div1",
+	"peri2_qspi_ssi_clk_div0",
+};
+
+static const char *const peri1_tdm_src_clk_parents[] = {
+	"audio1_pll_fout2",
+	"audio0_pll_fout2",
+};
+
+static const char *const pdm_clk_mux_parents[] = {
+	"audio1_pll_fout2",
+	"audio0_pll_fout2",
+};
+
+static const char *const emmc_ref_clk_mux_parents[] = {
+	"audio0_pll_foutvco",
+	"video_pll_foutvco",
+};
+
+static const char *const pad_sensor_vclk0_mux_parents[] = {
+	"dpu0_pll_foutpostdiv",
+	"dpu1_pll_foutpostdiv",
+	"dpu2_pll_foutpostdiv",
+	"aon_osc_clk_logic",
+};
+
+static const char *const pad_sensor_vclk1_mux_parents[] = {
+	"dpu0_pll_foutpostdiv",
+	"dpu1_pll_foutpostdiv",
+	"dpu2_pll_foutpostdiv",
+	"aon_osc_clk_logic",
+};
+
+static const char *const vp_aclk_mux_parents[] = {
+	"video_pll_foutvco",
+	"audio0_pll_foutvco",
+};
+
+static const char *const g2d_cclk_mux_parents[] = {
+	"audio0_pll_foutvco",
+	"gmac_pll_foutvco",
+	"video_pll_foutvco",
+};
+
+static const char *const vdec_cclk_mux_parents[] = {
+	"audio0_pll_foutvco",
+	"video_pll_foutvco",
+	"gmac_pll_foutvco",
+	"audio1_pll_foutvco",
+};
+
+static const char *const venc_cclk_mux_parents[] = {
+	"gmac_pll_foutvco",
+	"video_pll_foutvco",
+	"audio0_pll_foutvco",
+	"audio1_pll_foutvco",
+};
+
+static const char *const npu_aclk_mux_parents[] = {
+	"gmac_pll_foutvco",
+	"video_pll_foutvco",
+	"audio0_pll_foutvco",
+	"audio1_pll_foutvco",
+};
+
+static const char *const npu_cclk_mux_parents[] = {
+	"gmac_pll_foutvco",
+	"video_pll_foutvco",
+	"audio0_pll_foutvco",
+	"audio1_pll_foutvco",
+};
+
+static const char *const c908_cpu_clk_parents[] = {
+	"c908_pll_foutvco",
+	"top_cpu_bak_pll0_clk",
+};
+
+static const char *const c920_cpu_clk_parents[] = {
+	"c920_pll_foutvco",
+	"top_cpu_bak_pll1_clk",
+};
+
+static const char *const tee_clk_mux_parents[] = {
+	"video_pll_foutvco",
+	"tee_pll_foutvco",
+};
+
+static const char *const isp_if_ref_mux_parents[] = {
+	"audio0_pll_foutvco",
+	"video_pll_foutvco",
+};
+
+static const char *const vi_preocc_mipi0_ifclk_mux_parents[] = {
+	"audio0_pll_foutvco",
+	"video_pll_foutvco",
+};
+
+static const char *const vi_preocc_mipi1_ifclk_mux_parents[] = {
+	"audio0_pll_foutvco",
+	"video_pll_foutvco",
+};
+
+static const char *const vo_mipi_pixclk_mux_parents[] = {
+	"dpu0_pixclk",
+	"dpu1_pixclk",
+	"dpu2_pixclk",
+};
+
+static const char *const vo_hdmi_pixclk_mux_parents[] = {
+	"dpu0_pixclk",
+	"dpu1_pixclk",
+	"dpu2_pixclk",
+};
+
+static const char *const vo_dptx_pixclk_mux_parents[] = {
+	"dpu0_pixclk",
+	"dpu1_pixclk",
+	"dpu2_pixclk",
+};
+
+static const struct a210_pll_rate a210_teepll_tbl[] = {
+	PLL_RATE(2400000000, 800000000U, 1, 100, 0, 3, 1),
+};
+
+static const struct a210_pll_rate a210_dpu2pll_tbl[] = {
+	PLL_RATE(2376000000, 1188000000U, 1, 99, 0, 2, 1),
+};
+
+static const struct a210_pll_rate a210_dpu1pll_tbl[] = {
+	PLL_RATE(2376000000, 1188000000U, 1, 99, 0, 2, 1),
+};
+
+static const struct a210_pll_rate a210_dpu0pll_tbl[] = {
+	PLL_RATE(2376000000, 1188000000U, 1, 99, 0, 2, 1),
+};
+
+static const struct a210_pll_rate a210_dvfspll_tbl[] = {
+	PLL_RATE(1920000000, 960000000U, 1, 80, 0, 2, 1),
+};
+
+static const struct a210_pll_rate a210_gmacpll_tbl[] = {
+	PLL_RATE(3000000000, 1000000000U, 1, 125, 0, 3, 1),
+};
+
+static const struct a210_pll_rate a210_videopll_tbl[] = {
+	PLL_RATE(2640000000U, 1320000000U, 1, 110, 0, 2, 1),
+};
+
+static const struct a210_pll_rate a210_audio0pll_tbl[] = {
+	PLL_RATE(2359296000U, 1179648000U, 1, 98, 5100274, 2, 1),
+};
+
+static const struct a210_pll_rate a210_audio1pll_tbl[] = {
+	PLL_RATE(2528870400U, 1264435200U, 1, 105, 6200859, 2, 1),
+};
+
+static const struct a210_pll_rate a210_c908pll_tbl[] = {
+	PLL_RATE(1200000000U, 1200000000U, 1, 50, 0, 1, 1),
+	PLL_RATE(1500000000U, 1500000000U, 2, 125, 0, 1, 1),
+	PLL_RATE(1698000000U, 1698000000U, 4, 283, 0, 1, 1),
+	PLL_RATE(1896000000U, 1896000000U, 1, 79, 0, 1, 1),
+};
+
+static const struct a210_pll_rate a210_c920pll_tbl[] = {
+	PLL_RATE(1500000000U, 1500000000U, 2, 125, 0, 1, 1),
+	PLL_RATE(1698000000U, 1698000000U, 4, 283, 0, 1, 1),
+	PLL_RATE(1896000000U, 1896000000U, 1, 79, 0, 1, 1),
+	PLL_RATE(2298000000U, 2298000000U, 4, 383, 0, 1, 1),
+};
+
+static const struct a210_pll_desc plls_top[] = {
+	PLL_PARAM(TEE_PLL, A210_PLL_VCO, a210_teepll_tbl, 0x160, 0x170, BIT(0), BIT(31), BIT(30),
+		  PLL_MODE_INT, "tee_pll_foutvco_frequency"),
+	PLL_PARAM(DPU2_PLL, A210_PLL_VCO, a210_dpu2pll_tbl, 0x120, 0x130, BIT(0), BIT(31), BIT(30),
+		  PLL_MODE_INT, "dpu2_pll_foutvco_frequency"),
+	PLL_PARAM(DPU1_PLL, A210_PLL_VCO, a210_dpu1pll_tbl, 0x100, 0x110, BIT(0), BIT(31), BIT(30),
+		  PLL_MODE_INT, "dpu1_pll_foutvco_frequency"),
+	PLL_PARAM(DPU0_PLL, A210_PLL_VCO, a210_dpu0pll_tbl, 0x80, 0x90, BIT(0), BIT(31), BIT(30),
+		  PLL_MODE_INT, "dpu0_pll_foutvco_frequency"),
+	PLL_PARAM(DVFS_PLL, A210_PLL_VCO, a210_dvfspll_tbl, 0x60, 0x70, BIT(0), BIT(31), BIT(30),
+		  PLL_MODE_INT, "dvfs_pll_foutvco_frequency"),
+	PLL_PARAM(AUDIO0_PLL, A210_PLL_VCO, a210_audio0pll_tbl, 0x0, 0x10, BIT(0), BIT(31),
+		  BIT(30), PLL_MODE_FRAC, "audio0_pll_foutvco_frequency"),
+	PLL_PARAM(AUDIO1_PLL, A210_PLL_VCO, a210_audio1pll_tbl, 0x20, 0x30, BIT(0), BIT(31),
+		  BIT(30), PLL_MODE_FRAC, "audio1_pll_foutvco_frequency"),
+	PLL_PARAM(GMAC_PLL, A210_PLL_VCO, a210_gmacpll_tbl, 0x40, 0x50, BIT(0), BIT(31), BIT(30),
+		  PLL_MODE_INT, "gmac_pll_foutvco_frequency"),
+	PLL_PARAM(VIDEO_PLL, A210_PLL_VCO, a210_videopll_tbl, 0x140, 0x150, BIT(0), BIT(31),
+		  BIT(30), PLL_MODE_INT, "video_pll_foutvco_frequency"),
+	PLL_PARAM(C908_PLL, A210_PLL_VCO, a210_c908pll_tbl, 0x0, 0x10, BIT(0), BIT(31), BIT(30),
+		  PLL_MODE_INT, ""),
+	PLL_PARAM(C920_PLL, A210_PLL_VCO, a210_c920pll_tbl, 0x40, 0x50, BIT(0), BIT(31), BIT(30),
+		  PLL_MODE_INT, ""),
+};
+
+/* DDR PLL programming belongs to the firmware that trains the memory. */
+static const struct a210_pll_desc ddr_pll = {
+	.out_type = A210_PLL_VCO,
+	.cfg0_reg_off = 0x8,
+	.pll_bypass_bit = BIT(31),
+};
+
+static struct a210_clk_reg regs_top[] = {
+	REG_NAMED(PLL_WRAP, "pll-wrap"),
+	REG_NAMED(TOP_CRG, "top-crg"),
+	REG_NAMED(CPU_SS_CLK_SYSREG, "cpu-ss-clk-sysreg"),
+	REG_NAMED(CPU_SS_CPU_PLL, "cpu-ss-cpu-pll"),
+	REG_NAMED(DDR0_SYSREG, "ddr0-sysreg"),
+	REG_NAMED(DDR1_SYSREG, "ddr1-sysreg"),
+	REG_NAMED(SLC_DUAL_SYSREG, "slc-dual-sysreg"),
+	REG_NAMED(TOP_CRG_T, "top-crg-t"),
+	REG_NAMED(CPU_SS_CCU, "cpu-ss-ccu"),
+};
+
+static struct a210_clk_reg regs_gpu[] = {
+	REG_NAMED(GPU_SS_PWRAP_CLK_EN, "gpu-ss-pwrap-clk-en"),
+	REG_NAMED(GPU_SS_TOP_CLK_EN, "gpu-ss-top-clk-en"),
+};
+
+static struct a210_clk_reg regs_pcie[] = {
+	REG_NAMED(PCIE_CLK_EN, "pcie-clk-en"),
+};
+
+static struct a210_clk_reg regs_usb[] = {
+	REG_NAMED(USB_CLK_EN, "usb-clk-en"),
+};
+
+static struct a210_clk_reg regs_vi[] = {
+	REG_NAMED(VI_CLK, "vi-clk"),
+	REG_NAMED(VI_MISC_CTRL, "vi-misc-ctrl"),
+};
+
+static struct a210_clk_reg regs_vp[] = {
+	REG_NAMED(VP_CLK, "vp-clk"),
+};
+
+static struct a210_clk_reg regs_vo[] = {
+	REG_NAMED(VO_CLK, "vo-clk"),
+	REG_NAMED(VO_PATH_CTRL, "vo-path-ctrl"),
+};
+
+static struct a210_clk_reg regs_npu[] = {
+	REG_NAMED(NPU_CLK, "npu-clk"),
+	REG_NAMED(NPU_TOP_CLK, "npu-top-clk"),
+};
+
+static struct a210_clk_reg regs_peri[] = {
+	REG_NAMED(PERI0_SYSREG, "peri0-sysreg"),
+	REG_NAMED(PERI1_SYSREG, "peri1-sysreg"),
+	REG_NAMED(PERI2_SYSREG, "peri2-sysreg"),
+	REG_NAMED(PERI3_SYSREG, "peri3-sysreg"),
+	REG_NAMED(TEE_CRG, "tee-crg"),
+};
+
+static const struct a210_clk_desc info_top[] = {
+	/* Reference oscillator aliases. */
+	FIXED_FACTOR(AON_OSC_CLK_PHY, "aon_osc_clk_phy", "osc-24m", 1, 1),
+	FIXED_FACTOR(AON_OSC_CLK_LOGIC, "aon_osc_clk_logic", "osc-24m", 1, 1),
+	FIXED_FACTOR(TOP_PLL_REF_CLK, "top_pll_ref_clk", "osc-24m", 1, 1),
+	FIXED_FACTOR(PLL_OSC_CLK, "pll_osc_clk", "osc-24m", 1, 1),
+	FIXED_FACTOR(AON_RTC_CLK, "aon_rtc_clk", "osc-32k", 1, 1),
+	/* PLL */
+	PLL(AUDIO0_PLL_FOUTVCO, "audio0_pll_foutvco", "osc-24m", PLL_WRAP, 0,
+	    &plls_top[AUDIO0_PLL]),
+	PLL_POSTDIV(AUDIO0_PLL_FOUTPOSTDIV, "audio0_pll_foutpostdiv",
+		    "audio0_pll_foutvco", PLL_WRAP, &plls_top[AUDIO0_PLL]),
+	FIXED_FACTOR(AUDIO0_PLL_FOUT2, "audio0_pll_fout2", "audio0_pll_foutpostdiv", 1, 4),
+	PLL(AUDIO1_PLL_FOUTVCO, "audio1_pll_foutvco", "osc-24m", PLL_WRAP, 0,
+	    &plls_top[AUDIO1_PLL]),
+	PLL_POSTDIV(AUDIO1_PLL_FOUTPOSTDIV, "audio1_pll_foutpostdiv",
+		    "audio1_pll_foutvco", PLL_WRAP, &plls_top[AUDIO1_PLL]),
+	FIXED_FACTOR(AUDIO1_PLL_FOUT2, "audio1_pll_fout2", "audio1_pll_foutpostdiv", 1, 4),
+	PLL(C908_PLL_FOUTVCO, "c908_pll_foutvco", "osc-24m", CPU_SS_CPU_PLL, 0,
+	    &plls_top[C908_PLL]),
+	PLL(C920_PLL_FOUTVCO, "c920_pll_foutvco", "osc-24m", CPU_SS_CPU_PLL, 0,
+	    &plls_top[C920_PLL]),
+	PLL(VIDEO_PLL_FOUTVCO, "video_pll_foutvco", "top_pll_ref_clk", PLL_WRAP, 0,
+	    &plls_top[VIDEO_PLL]),
+	PLL_POSTDIV(VIDEO_PLL_FOUTPOSTDIV, "video_pll_foutpostdiv",
+		    "video_pll_foutvco", PLL_WRAP, &plls_top[VIDEO_PLL]),
+	FIXED_FACTOR(VIDEO_PLL_FOUT1PH0, "video_pll_fout1ph0", "video_pll_foutpostdiv", 1, 2),
+	FIXED_FACTOR(VIDEO_PLL_FOUT3, "video_pll_fout3", "video_pll_foutpostdiv", 1, 6),
+	PLL(GMAC_PLL_FOUTVCO, "gmac_pll_foutvco", "top_pll_ref_clk", PLL_WRAP, 0,
+	    &plls_top[GMAC_PLL]),
+	PLL_POSTDIV(GMAC_PLL_FOUTPOSTDIV, "gmac_pll_foutpostdiv",
+		    "gmac_pll_foutvco", PLL_WRAP, &plls_top[GMAC_PLL]),
+	FIXED_FACTOR(GMAC_PLL_FOUT1PH0, "gmac_pll_fout1ph0", "gmac_pll_foutpostdiv", 1, 2),
+	PLL(DVFS_PLL_FOUTVCO, "dvfs_pll_foutvco", "top_pll_ref_clk", PLL_WRAP, 0,
+	    &plls_top[DVFS_PLL]),
+	PLL(DPU0_PLL_FOUTVCO, "dpu0_pll_foutvco", "top_pll_ref_clk", PLL_WRAP, 0,
+	    &plls_top[DPU0_PLL]),
+	PLL_POSTDIV(DPU0_PLL_FOUTPOSTDIV, "dpu0_pll_foutpostdiv",
+		    "dpu0_pll_foutvco", PLL_WRAP, &plls_top[DPU0_PLL]),
+	PLL(DPU1_PLL_FOUTVCO, "dpu1_pll_foutvco", "top_pll_ref_clk", PLL_WRAP, 0,
+	    &plls_top[DPU1_PLL]),
+	PLL_POSTDIV(DPU1_PLL_FOUTPOSTDIV, "dpu1_pll_foutpostdiv",
+		    "dpu1_pll_foutvco", PLL_WRAP, &plls_top[DPU1_PLL]),
+	PLL(DPU2_PLL_FOUTVCO, "dpu2_pll_foutvco", "top_pll_ref_clk", PLL_WRAP, 0,
+	    &plls_top[DPU2_PLL]),
+	PLL_POSTDIV(DPU2_PLL_FOUTPOSTDIV, "dpu2_pll_foutpostdiv",
+		    "dpu2_pll_foutvco", PLL_WRAP, &plls_top[DPU2_PLL]),
+	PLL(TEE_PLL_FOUTVCO, "tee_pll_foutvco", "top_pll_ref_clk", PLL_WRAP, 0, &plls_top[TEE_PLL]),
+	/* TOP SS */
+	DIV(TOP_CFG_ACLK_DIV, "top_cfg_aclk", "video_pll_fout1ph0", TOP_CRG, 0, 8, 8, NO_DIV_EN,
+	    MUX_TYPE_DIV, 2, 255),
+	DIV(TOP_PCLK_DIV, "top_pclk", "video_pll_fout1ph0", TOP_CRG, 0, 0, 8, NO_DIV_EN,
+	    MUX_TYPE_DIV, 4, 255),
+	DIV(AMUX_CLK_DIV, "top_amux_clk_div", "video_pll_foutvco", TOP_CRG, 0x18, 8, 4, NO_DIV_EN,
+	    MUX_TYPE_DIV, 4, 15),
+	GATE_FLAGS(SW_TOP_OSC_CLK_LOGIC_EN, "top_osc_clk_logic", "aon_osc_clk_logic", TOP_CRG,
+		   0x200, 2, CLK_IS_CRITICAL),
+	GATE_FLAGS(SW_AMUX_660_CLK_EN, "top_amux_clk", "top_amux_clk_div", TOP_CRG, 0x200, 0,
+		   CLK_IS_CRITICAL),
+	/* TOP SS - IOMMU_PTW_ACLK */
+	GATE(SW_IOMMU_PTW_330_ACLK_EN, "iommu_ptw_aclk", "iommu_ptw_aclk_div", TOP_CRG, 0x200, 1),
+	DIV(IOMMU_PTW_ACLK_DIV, "iommu_ptw_aclk_div", "video_pll_fout1ph0", TOP_CRG, 0, 24, 3,
+	    NO_DIV_EN, MUX_TYPE_DIV, 2, 7),
+	/* TOP SS - CPU SS */
+	DIV(TOP_CPUSYS_BUS_CLK_DIV, "top_cpusys_bus_clk", "top_cpusys_bus_clk_mux", TOP_CRG, 0x8,
+	    20, 4, NO_DIV_EN, MUX_TYPE_DIV, 2, 15),
+	MUX(TOP_CPUSYS_BUS_CLK_MUX, "top_cpusys_bus_clk_mux", TOP_CRG, 0x8, 16, 2,
+	    top_cpusys_bus_clk_mux_parents, CLK_SET_RATE_PARENT | CLK_IS_CRITICAL),
+	DIV(TOP_CPUSYS_PIC_CLK_DIV, "top_cpusys_pic_clk", "top_cpusys_pic_clk_mux", TOP_CRG, 0x4,
+	    20, 4, NO_DIV_EN, MUX_TYPE_DIV, 3, 15),
+	MUX(TOP_CPUSYS_PIC_CLK_MUX, "top_cpusys_pic_clk_mux", TOP_CRG, 0x4, 3, 1,
+	    top_cpusys_pic_clk_mux_parents, CLK_SET_RATE_PARENT | CLK_IS_CRITICAL),
+	MUX(TOP_CPU_BAK_PLL0_CLK_MUX, "top_cpu_bak_pll0_clk", TOP_CRG, 0x4, 0, 3,
+	    top_cpu_bak_pll0_clk_mux_parents, CLK_SET_RATE_PARENT),
+	MUX(TOP_CPU_BAK_PLL0_CLK_MUX0, "top_cpu_bak_pll0_clk_mux0", TOP_CRG, 0x4, 16, 2,
+	    top_cpu_bak_pll0_clk_mux0_parents, CLK_SET_RATE_PARENT),
+	DIV(TOP_CPU_BAK_PLL0_CLK_DIV0, "top_cpu_bak_pll0_clk_div0", "gmac_pll_foutvco", TOP_CRG,
+	    0x4, 12, 4, NO_DIV_EN, MUX_TYPE_DIV, 2, 15),
+	DIV(TOP_CPU_BAK_PLL0_CLK_DIV1, "top_cpu_bak_pll0_clk_div1", "gmac_pll_foutvco", TOP_CRG,
+	    0x4, 8, 4, NO_DIV_EN, MUX_TYPE_DIV, 3, 15),
+	DIV(TOP_CPU_BAK_PLL0_CLK_DIV3, "top_cpu_bak_pll0_clk_div3", "audio1_pll_foutvco", TOP_CRG,
+	    0x4, 4, 4, NO_DIV_EN, MUX_TYPE_DIV, 2, 15),
+	DIV(TOP_CPU_BAK_PLL0_CLK_DIV4, "top_cpu_bak_pll0_clk_div4", "video_pll_foutvco", TOP_CRG,
+	    0x4, 24, 8, NO_DIV_EN, MUX_TYPE_DIV, 2, 255),
+	MUX(TOP_CPU_BAK_PLL1_CLK_MUX, "top_cpu_bak_pll1_clk", TOP_CRG, 0x8, 0, 3,
+	    top_cpu_bak_pll1_clk_mux_parents, CLK_SET_RATE_PARENT),
+	MUX(TOP_CPU_BAK_PLL1_CLK_MUX0, "top_cpu_bak_pll1_clk_mux0", TOP_CRG, 0x8, 8, 2,
+	    top_cpu_bak_pll1_clk_mux0_parents, CLK_SET_RATE_PARENT),
+	DIV(TOP_CPU_BAK_PLL1_CLK_DIV0, "top_cpu_bak_pll1_clk_div0", "gmac_pll_foutvco", TOP_CRG,
+	    0x8, 12, 4, NO_DIV_EN, MUX_TYPE_DIV, 2, 15),
+	DIV(TOP_CPU_BAK_PLL1_CLK_DIV1, "top_cpu_bak_pll1_clk_div1", "gmac_pll_foutvco", TOP_CRG,
+	    0x8, 24, 4, NO_DIV_EN, MUX_TYPE_DIV, 3, 15),
+	DIV(TOP_CPU_BAK_PLL1_CLK_DIV3, "top_cpu_bak_pll1_clk_div3", "audio1_pll_foutvco", TOP_CRG,
+	    0x8, 4, 4, NO_DIV_EN, MUX_TYPE_DIV, 2, 15),
+	DIV(TOP_CPU_BAK_PLL1_CLK_DIV4, "top_cpu_bak_pll1_clk_div4", "video_pll_foutvco", TOP_CRG,
+	    0x44, 0, 8, NO_DIV_EN, MUX_TYPE_DIV, 2, 255),
+	DIV(TOP_CPUSYS_CFG_ACLK_DIV, "top_cpusys_sys_cfg_axi_clk", "video_pll_fout1ph0", CPU_SS_CCU,
+	    0x1c, 0, 16, NO_DIV_EN, MUX_TYPE_CDE, 1, 5),
+	DIV(TOP_CPUSYS_COM_APB_CLK_DIV, "top_cpusys_sys_com_apb_clk", "video_pll_fout1ph0",
+	    CPU_SS_CCU, 0x21c, 0, 16, NO_DIV_EN, MUX_TYPE_CDE, 3, 7),
+	DIV(TOP_CPUSYS_APB_CLK_DIV, "top_cpusys_cpu_apb_clk", "video_pll_fout1ph0", CPU_SS_CCU,
+	    0x41c, 0, 16, NO_DIV_EN, MUX_TYPE_CDE, 3, 7),
+	/* TOP SS - NOC_CCLK */
+	GATE_FLAGS(SW_NOC_CCLK_EN, "noc_cclk", "noc_cclk_div", TOP_CRG, 0x200, 3, CLK_IS_CRITICAL),
+	DIV(NOC_CCLK_DIV, "noc_cclk_div", "noc_cclk_mux", TOP_CRG, 0, 20, 4, NO_DIV_EN,
+	    MUX_TYPE_DIV, 3, 15),
+	MUX(NOC_CCLK_MUX, "noc_cclk_mux", TOP_CRG, 0, 16, 2, noc_cclk_mux_parents,
+	    CLK_SET_RATE_PARENT),
+	/* TOP SS - DDR SS */
+	MUX(TOP_CPU_DDR1_ACLK_MUX, "top_ddr1_aclk", TOP_CRG, 0x4, 19, 1, top_cpu_ddr1_aclk_parents,
+	    CLK_SET_RATE_PARENT | CLK_IS_CRITICAL),
+	MUX(TOP_CPU_DDR0_ACLK_MUX, "top_ddr0_aclk", TOP_CRG, 0x4, 18, 1, top_cpu_ddr0_aclk_parents,
+	    CLK_SET_RATE_PARENT | CLK_IS_CRITICAL),
+	FIXED_FACTOR(DDR_CBUS2DDR_ACLK0, "cbus2ddr_aclk0", "ddr_pll_clk_en", 1, 1),
+	FIXED_FACTOR(DDR_CBUS2DDR_ACLK1, "cbus2ddr_aclk1", "ddr_pll_clk_en", 1, 1),
+	PLL(DDR_PLL_FOUTVCO, "ddr_pll_foutvco", "pll_osc_clk", SLC_DUAL_SYSREG, 0, &ddr_pll),
+	PLL_POSTDIV(DDR_PLL_FOUTPOSTDIV, "ddr_pll_foutpostdiv",
+		    "ddr_pll_foutvco", SLC_DUAL_SYSREG, &ddr_pll),
+	FIXED_FACTOR(DDR_PLL_FOUT1PH0, "ddr_pll_fout1ph0", "ddr_pll_foutpostdiv", 1, 2),
+	FIXED_FACTOR(DDR_PLL_FOUT2, "ddr_pll_fout2", "ddr_pll_foutpostdiv", 1, 4),
+	FIXED_FACTOR(DDR_PLL_FOUT4, "ddr_pll_fout4", "ddr_pll_foutpostdiv", 1, 8),
+	/* TOP SS - D2D SS */
+	FIXED_FACTOR(D2D_PHY_REF_CLK_100M, "d2d_phy_ref_clk_100M", "gmac_pll_foutpostdiv", 1, 10),
+	MUX(TOP_D2D_REF_CLK_MUX, "d2d_phy_ref_clk", TOP_CRG, 0x14, 15, 1, d2d_phy_ref_clk_parents,
+	    CLK_SET_RATE_PARENT),
+	DIV(TOP_D2D_SCAN_CLK0_DIV, "d2d_phy_scan_clk0", "dpu1_pll_foutvco", TOP_CRG, 0x14, 12, 3,
+	    NO_DIV_EN, MUX_TYPE_DIV, 3, 7),
+	DIV(TOP_D2D_SCAN_CLK1_DIV, "d2d_phy_scan_clk1", "dpu1_pll_foutvco", TOP_CRG, 0x14, 8, 4,
+	    NO_DIV_EN, MUX_TYPE_DIV, 3, 15),
+	FIXED_FACTOR(D2D_PHY_SCAN_CLK2, "d2d_phy_scan_clk2", "dpu2_pll_foutpostdiv", 1, 1),
+	DIV(TOP_D2D_ACLK_DIV, "top_d2d_aclk", "top_d2d_aclk_mux", TOP_CRG, 0x14, 4, 4, NO_DIV_EN,
+	    MUX_TYPE_DIV, 3, 15),
+	MUX(TOP_D2D_ACLK_MUX, "top_d2d_aclk_mux", TOP_CRG, 0x14, 0, 2, top_d2d_aclk_mux_parents,
+	    CLK_SET_RATE_PARENT),
+	/* TOP SS - GPU SS */
+	DIV(TOP_GPU_CORE_CLK_DIV, "top_gpu_core_clk", "top_gpu_core_clk_mux", TOP_CRG, 0x18, 4, 4,
+	    NO_DIV_EN, MUX_TYPE_DIV, 3, 15),
+	MUX(TOP_GPU_CORE_CLK_MUX, "top_gpu_core_clk_mux", TOP_CRG, 0x18, 0, 2,
+	    top_gpu_core_clk_mux_parents, CLK_SET_RATE_PARENT),
+	/* TOP SS - PCIE SS */
+	DIV(TOP_PCIE_SCAN_REF_CLK0_DIV, "scan_ref_clk0", "dpu1_pll_foutvco", TOP_CRG, 0x1c, 8, 4,
+	    NO_DIV_EN, MUX_TYPE_DIV, 6, 15),
+	DIV(TOP_PCIE_SCAN_REF_CLK1_DIV, "scan_ref_clk1", "gmac_pll_foutvco", TOP_CRG, 0x1c, 12, 4,
+	    NO_DIV_EN, MUX_TYPE_DIV, 3, 15),
+	DIV(TOP_PCIE_AXI_M_ACLK_DIV, "pcie_ss_axi_m_aclk", "pcie_ss_axi_m_aclk_mux", TOP_CRG, 0x1c,
+	    4, 4, NO_DIV_EN, MUX_TYPE_DIV, 3, 15),
+	MUX(TOP_PCIE_AXI_M_ACLK_MUX, "pcie_ss_axi_m_aclk_mux", TOP_CRG, 0x1c, 0, 1,
+	    pcie_ss_axi_m_aclk_mux_parents, CLK_SET_RATE_PARENT),
+	/* TOP SS - PERI SS */
+	DIV(TOP_PERI_SPI_SSI_CLK0_DIV, "peri1_spi_ssi_clk", "audio1_pll_foutvco", TOP_CRG, 0x20, 20,
+	    8, NO_DIV_EN, MUX_TYPE_DIV, 6, 255),
+	DIV(TOP_PERI_MST_ACLK0_DIV, "peri1_mst_aclk", "video_pll_fout1ph0", TOP_CRG, 0x20, 16, 3,
+	    NO_DIV_EN, MUX_TYPE_DIV, 2, 7),
+	FIXED_FACTOR(TOP_PERI_TIMER_CLK_100M, "peri0_timer_clk_100M", "gmac_pll_foutpostdiv", 1,
+		     10),
+	MUX(TOP_PERI_TIMER_CLK_MUX, "peri0_timer_clk", TOP_CRG, 0x20, 15, 1,
+	    peri0_timer_clk_parents, CLK_SET_RATE_PARENT),
+	MUX(TOP_PERI_I2S_8CH0_SRC_CLK_MUX, "peri2_i2s3_src_clk", TOP_CRG, 0x28, 21, 1,
+	    peri2_i2s3_src_clk_parents, CLK_SET_RATE_PARENT),
+	MUX(TOP_PERI_I2S_2CH0_SRC_CLK_MUX, "peri1_i2s0_src_clk", TOP_CRG, 0x20, 13, 1,
+	    peri1_i2s0_src_clk_parents, CLK_SET_RATE_PARENT),
+	MUX(TOP_PERI_I2S_2CH1_SRC_CLK_MUX, "peri2_i2s1_src_clk", TOP_CRG, 0x20, 14, 1,
+	    peri2_i2s1_src_clk_parents, CLK_SET_RATE_PARENT),
+	MUX(TOP_PERI_I2S_2CH2_SRC_CLK_MUX, "peri2_i2s2_src_clk", TOP_CRG, 0x28, 23, 1,
+	    peri2_i2s2_src_clk_parents, CLK_SET_RATE_PARENT),
+	DIV(TOP_PERI_QSPI0_SSI_CLK_DIV0, "peri1_qspi_ssi_clk_div0", "video_pll_foutvco", TOP_CRG,
+	    0x20, 8, 4, NO_DIV_EN, MUX_TYPE_DIV, 2, 15),
+	DIV(TOP_PERI_QSPI0_SSI_CLK_DIV1, "peri1_qspi_ssi_clk_div1", "audio1_pll_foutvco", TOP_CRG,
+	    0x20, 0, 8, NO_DIV_EN, MUX_TYPE_DIV, 6, 255),
+	MUX(TOP_PERI_QSPI_SSI_CLK_MUX0, "peri1_qspi_ssi_clk", TOP_CRG, 0x20, 12, 1,
+	    peri1_qspi_ssi_clk_parents, CLK_SET_RATE_PARENT),
+	DIV(TOP_PERI_SPI_SSI_CLK1_DIV, "peri2_spi_ssi_clk", "audio1_pll_foutvco", TOP_CRG, 0x24, 24,
+	    8, NO_DIV_EN, MUX_TYPE_DIV, 6, 255),
+	DIV(TOP_PERI_HIRES_CLK0_DIV, "peri1_hires_clk", "video_pll_foutvco", TOP_CRG, 0x24, 16, 6,
+	    NO_DIV_EN, MUX_TYPE_DIV, 33, 63),
+	DIV(TOP_PERI_HIRES_CLK1_DIV, "peri2_hires_clk", "video_pll_foutvco", TOP_CRG, 0x24, 0, 6,
+	    NO_DIV_EN, MUX_TYPE_DIV, 33, 63),
+	MUX(TOP_PERI_TDM_SRC_CLK_MUX, "peri1_tdm_src_clk", TOP_CRG, 0x28, 25, 1,
+	    peri1_tdm_src_clk_parents, CLK_SET_RATE_PARENT),
+	FIXED_FACTOR(UART_SCLK_100M, "uart_sclk_100m", "gmac_pll_foutpostdiv", 1, 10),
+	MUX(TOP_UART_SCLK_MUX, "uart_sclk", TOP_CRG, 0x28, 24, 1, uart_sclk_parents, 0),
+	FIXED_FACTOR(PERI1_UART_SCLK, "peri1_uart_sclk", "uart_sclk", 1, 1),
+	FIXED_FACTOR(PERI2_UART_SCLK, "peri2_uart_sclk", "uart_sclk", 1, 1),
+	DIV(TOP_PERI_PDM_MCLK_DIV, "peri1_pdm_mclk", "pdm_clk_mux", TOP_CRG, 0x2c, 24, 8, NO_DIV_EN,
+	    MUX_TYPE_DIV, 10, 255),
+	MUX(TOP_PERI_PDM_MCLK_MUX, "pdm_clk_mux", TOP_CRG, 0x28, 22, 1, pdm_clk_mux_parents,
+	    CLK_SET_RATE_PARENT),
+	DIV(TOP_PERI_QSPI1_SSI_CLK_DIV0, "peri2_qspi_ssi_clk_div0", "video_pll_foutvco", TOP_CRG,
+	    0x28, 16, 4, NO_DIV_EN, MUX_TYPE_DIV, 2, 15),
+	DIV(TOP_PERI_QSPI1_SSI_CLK_DIV1, "peri2_qspi_ssi_clk_div1", "audio1_pll_foutvco", TOP_CRG,
+	    0x28, 8, 8, NO_DIV_EN, MUX_TYPE_DIV, 6, 255),
+	MUX(TOP_PERI_QSPI_SSI_CLK_MUX1, "peri2_qspi_ssi_clk", TOP_CRG, 0x28, 20, 1,
+	    peri2_qspi_ssi_clk_parents, CLK_SET_RATE_PARENT),
+	DIV(TOP_PERI_MST_CLK1_DIV, "peri3_mst_aclk", "video_pll_foutvco", TOP_CRG, 0x28, 4, 4,
+	    NO_DIV_EN, MUX_TYPE_DIV, 6, 15),
+	DIV(TOP_PERI_EMMC_REF_CLK_DIV, "emmc_ref_clk", "emmc_ref_clk_mux", TOP_CRG, 0x28, 0, 4,
+	    NO_DIV_EN, MUX_TYPE_DIV, 3, 15),
+	MUX(TOP_PERI_EMMC_REF_CLK_MUX, "emmc_ref_clk_mux", TOP_CRG, 0x2c, 20, 1,
+	    emmc_ref_clk_mux_parents, CLK_SET_RATE_PARENT),
+	FIXED_FACTOR(PERI1_PWM_CLK, "peri1_pwm_clk", "gmac_pll_fout1ph0", 1, 10),
+	FIXED_FACTOR(PERI2_PWM_CLK, "peri2_pwm_clk", "gmac_pll_fout1ph0", 1, 10),
+	FIXED_FACTOR(I2C_IC_CLK, "i2c_ic_clk", "gmac_pll_foutpostdiv", 1, 10),
+	MUX(TOP_PAD_SENSOR_VCLK_MUX0, "pad_sensor_vclk0_mux", TOP_CRG, 0x2c, 16, 2,
+	    pad_sensor_vclk0_mux_parents, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT),
+	DIV(TOP_PAD_SENSOR_VCLK0_DIV, "top_pad_sensor_vclk0_div", "pad_sensor_vclk0_mux", TOP_CRG,
+	    0x2c, 0, 8, NO_DIV_EN, MUX_TYPE_DIV, 16, 255),
+	MUX(TOP_PAD_SENSOR_VCLK_MUX1, "pad_sensor_vclk1_mux", TOP_CRG, 0x2c, 18, 2,
+	    pad_sensor_vclk1_mux_parents, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT),
+	DIV(TOP_PAD_SENSOR_VCLK1_DIV, "top_pad_sensor_vclk1_div", "pad_sensor_vclk1_mux", TOP_CRG,
+	    0x2c, 8, 8, NO_DIV_EN, MUX_TYPE_DIV, 16, 255),
+	MUX(TOP_TEE_CLK_MUX, "tee_clk_mux", TOP_CRG, 0x30, 0, 1, tee_clk_mux_parents,
+	    CLK_SET_RATE_PARENT),
+	DIV_CLOSEST(TOP_TEE_CLK_DIV, "tee_clk", "tee_clk_mux", TOP_CRG, 0x30, 4, 8, NO_DIV_EN,
+		    MUX_TYPE_DIV, 7, 255),
+	DIV(TOP_USB_BUS_ACLK_DIV, "clkgen_usb_ss_bus_clk", "video_pll_fout1ph0", TOP_CRG, 0x34, 8,
+	    3, NO_DIV_EN, MUX_TYPE_DIV, 2, 7),
+	DIV(TOP_USB_DP_AUX_CLK_DIV, "clkgen_usb_ss_aux_clk", "video_pll_foutvco", TOP_CRG, 0x34, 0,
+	    8, NO_DIV_EN, MUX_TYPE_DIV, 165, 255),
+	DIV(TOP_VP_ACLK_DIV, "vp_aclk", "vp_aclk_mux", TOP_CRG, 0x38, 24, 4, NO_DIV_EN,
+	    MUX_TYPE_DIV, 3, 15),
+	MUX(TOP_VP_ACLK_MUX, "vp_aclk_mux", TOP_CRG, 0x38, 28, 1, vp_aclk_mux_parents,
+	    CLK_SET_RATE_PARENT),
+	DIV(TOP_VP_G2D_CCLK_DIV, "g2d_cclk", "g2d_cclk_mux", TOP_CRG, 0x38, 20, 4, NO_DIV_EN,
+	    MUX_TYPE_DIV, 3, 15),
+	MUX(TOP_VP_G2D_CCLK_MUX, "g2d_cclk_mux", TOP_CRG, 0x38, 16, 2, g2d_cclk_mux_parents,
+	    CLK_SET_RATE_PARENT),
+	DIV(TOP_VP_VDEC_CCLK_DIV, "vdec_cclk", "vdec_cclk_mux", TOP_CRG, 0x38, 12, 4, NO_DIV_EN,
+	    MUX_TYPE_DIV, 3, 15),
+	MUX(TOP_VP_VDEC_CCLK_MUX, "vdec_cclk_mux", TOP_CRG, 0x38, 8, 2, vdec_cclk_mux_parents,
+	    CLK_SET_RATE_PARENT),
+	DIV(TOP_VP_VENC_CCLK_DIV, "venc_cclk", "venc_cclk_mux", TOP_CRG, 0x38, 4, 4, NO_DIV_EN,
+	    MUX_TYPE_DIV, 5, 15),
+	MUX(TOP_VP_VENC_CCLK_MUX, "venc_cclk_mux", TOP_CRG, 0x38, 0, 2, venc_cclk_mux_parents,
+	    CLK_SET_RATE_PARENT),
+	DIV(TOP_NPU_ACLK_DIV, "npu_aclk", "npu_aclk_mux", TOP_CRG, 0x3c, 12, 4, NO_DIV_EN,
+	    MUX_TYPE_DIV, 3, 15),
+	MUX(TOP_NPU_ACLK_MUX, "npu_aclk_mux", TOP_CRG, 0x3c, 8, 2, npu_aclk_mux_parents,
+	    CLK_SET_RATE_PARENT),
+	DIV(TOP_NPU_CCLK_DIV, "npu_cclk", "npu_cclk_mux", TOP_CRG, 0x3c, 4, 4, NO_DIV_EN,
+	    MUX_TYPE_DIV, 3, 15),
+	MUX(TOP_NPU_CCLK_MUX, "npu_cclk_mux", TOP_CRG, 0x3c, 0, 2, npu_cclk_mux_parents,
+	    CLK_SET_RATE_PARENT),
+	DIV(TOP_USB_USB20_SCAN_REF_CLK_DIV, "clkgen_usb20phy_scan_ref_clk", "dpu1_pll_foutvco",
+	    TOP_CRG, 0x40, 16, 4, NO_DIV_EN, MUX_TYPE_DIV, 5, 15),
+	DIV(TOP_USB_SCAN_REF_CLK3_DIV, "clkgen_c10phy_scan_ref_clk3", "dpu1_pll_foutvco", TOP_CRG,
+	    0x40, 12, 4, NO_DIV_EN, MUX_TYPE_DIV, 3, 15),
+	DIV(TOP_USB_SCAN_REF_CLK2_DIV, "clkgen_c10phy_scan_ref_clk2", "gmac_pll_foutvco", TOP_CRG,
+	    0x40, 8, 4, NO_DIV_EN, MUX_TYPE_DIV, 5, 15),
+	DIV(TOP_USB_SCAN_REF_CLK1_DIV, "clkgen_c10phy_scan_ref_clk1", "gmac_pll_foutvco", TOP_CRG,
+	    0x40, 4, 4, NO_DIV_EN, MUX_TYPE_DIV, 6, 15),
+	DIV(TOP_USB_SCAN_REF_CLK0_DIV, "clkgen_c10phy_scan_ref_clk0", "dpu1_pll_foutvco", TOP_CRG,
+	    0x40, 0, 4, NO_DIV_EN, MUX_TYPE_DIV, 6, 15),
+	GATE(SW_TOP_PAD_SENSOR_VCLK0_EN, "top_pad_sensor_vclk0", "top_pad_sensor_vclk0_div",
+	     TOP_CRG, 0x200, 4),
+	GATE(SW_TOP_PAD_SENSOR_VCLK1_EN, "top_pad_sensor_vclk1", "top_pad_sensor_vclk1_div",
+	     TOP_CRG, 0x200, 5),
+	/* CPU SS */
+	MUX(C908_CPU_TO_CDE_CLK_MUX, "c908_cpu_clk", CPU_SS_CLK_SYSREG, 0x0, 0, 1,
+	    c908_cpu_clk_parents, CLK_SET_RATE_PARENT | CLK_IS_CRITICAL),
+	MUX(C920_CPU_TO_CDE_CLK_MUX, "c920_cpu_clk", CPU_SS_CLK_SYSREG, 0x4, 0, 1,
+	    c920_cpu_clk_parents, CLK_SET_RATE_PARENT | CLK_IS_CRITICAL),
+	/* DDR SS */
+	GATE_FLAGS(DDR0_PHY_DFICLK_EN, "ddr0_phy_dficlk", "ddr_pll_foutpostdiv", DDR0_SYSREG, 0x8,
+		   3, CLK_IS_CRITICAL),
+	GATE_FLAGS(DDR0_DDRC_ACLK_EN, "ddr0_aclk", "ddr_pll_foutpostdiv", DDR0_SYSREG, 0x8, 2,
+		   CLK_IS_CRITICAL),
+	GATE_FLAGS(DDR0_DDRC_CCLK_EN, "ddr0_cclk", "ddr_pll_foutpostdiv", DDR0_SYSREG, 0x8, 1,
+		   CLK_IS_CRITICAL),
+	GATE(DDR0_SBR_CLK_EN, "ddr0_sbr_clk", "ddr_pll_foutpostdiv", DDR0_SYSREG, 0x8, 0),
+	GATE_FLAGS(DDR1_PHY_DFICLK_EN, "ddr1_phy_dficlk", "ddr_pll_foutpostdiv", DDR1_SYSREG, 0x8,
+		   3, CLK_IS_CRITICAL),
+	GATE_FLAGS(DDR1_DDRC_ACLK_EN, "ddr1_aclk", "ddr_pll_foutpostdiv", DDR1_SYSREG, 0x8, 2,
+		   CLK_IS_CRITICAL),
+	GATE_FLAGS(DDR1_DDRC_CCLK_EN, "ddr1_cclk", "ddr_pll_foutpostdiv", DDR1_SYSREG, 0x8, 1,
+		   CLK_IS_CRITICAL),
+	GATE(DDR1_SBR_CLK_EN, "ddr1_sbr_clk", "ddr_pll_foutpostdiv", DDR1_SYSREG, 0x8, 0),
+	GATE_SHARED(DDR_PLL_CLK_EN, "ddr_pll_clk_en", "ddr_pll_clkout", SLC_DUAL_SYSREG, 0x18, 16,
+		    &share_cnt_ddr_pll_clk_en, CLK_IS_CRITICAL),
+	MUX(DDR_PLL_CLK_SEL, "ddr_pll_clkout", SLC_DUAL_SYSREG, 0x18, 17, 2, ddr_pll_clkout_parents,
+	    CLK_SET_RATE_PARENT),
+};
+
+static const struct a210_clk_desc info_gpu[] = {
+	FIXED_FACTOR(GPU_TOP_SYS_CLK, "gpu_top_sys_clk", "top_cfg_aclk", 1, 1),
+	FIXED_FACTOR(GPU_PCLK_CDT, "gpu_pclk_cdt", "gpu_top_sys_clk", 1, 2),
+	GATE(SW_PWR_WRAP_DFMU_PCLK_EN, "gpu_top_pclk", "gpu_pclk_cdt", GPU_SS_PWRAP_CLK_EN, 0, 7),
+	GATE(SW_PWR_WRAP_GPU_SYS_CLK_EN, "gpu_top_aclk", "gpu_top_sys_clk", GPU_SS_PWRAP_CLK_EN, 0,
+	     3),
+	GATE(SW_PWR_WRAP_DFMU_CORE_CLK_EN, "gpu_dfmu_core_clk", "top_cfg_aclk", GPU_SS_PWRAP_CLK_EN,
+	     0, 1),
+	GATE(SW_PWR_WRAP_GPU_CORE_CLK_EN, "gpu_core_clk", "top_gpu_core_clk", GPU_SS_PWRAP_CLK_EN,
+	     0, 0),
+};
+
+static const struct a210_clk_desc info_pcie[] = {
+	FIXED_FACTOR(PCIE_SS_APB_CLK, "pcie_ss_apb_clk", "gmac_pll_foutpostdiv", 1, 10),
+	GATE(E16PHY_PCLK_EN, "e16phy_apbs_pclk", "pcie_ss_apb_clk", PCIE_CLK_EN, 0x8, 0),
+	GATE(SATA_MST_AFENCE_ACLK_EN, "sata_mst_afence_aclk", "pcie_ss_axi_m_aclk", PCIE_CLK_EN,
+	     0x10, 20),
+	GATE(SATA_SLV_AFENCE_ACLK_EN, "sata_slv_afence_aclk", "top_cfg_aclk", PCIE_CLK_EN, 0x10,
+	     16),
+	GATE(X2X_SATA_SLV_ACLK_EN, "x2x_sata_slv_aclk", "pcie_ss_axi_m_aclk", PCIE_CLK_EN, 0x10, 4),
+	GATE(X2X_SATA_MST_ACLK_EN, "x2x_sata_mst_aclk", "top_cfg_aclk", PCIE_CLK_EN, 0x10, 0),
+	GATE(SATA_PMALIVE_CLK_EN, "sata_pmalive_clk", "aon_osc_clk_logic", PCIE_CLK_EN, 0x14, 0),
+	GATE(SATA_RXOOB0_CLK_EN, "sata_rxoob0_clk", "pcie_ss_apb_clk", PCIE_CLK_EN, 0x14, 16),
+	GATE(SATA_RXOOB1_CLK_EN, "sata_rxoob1_clk", "pcie_ss_apb_clk", PCIE_CLK_EN, 0x14, 20),
+	GATE(SATA_GEN3X2_ACLK_EN, "sata_gen3x2_aclk", "pcie_ss_axi_m_aclk", PCIE_CLK_EN, 0x10, 8),
+	GATE(PCIE_DM_GEN3X4_AUX_CLK_EN, "pcie_dm_gen3x4_aux_clk", "aon_osc_clk_logic", PCIE_CLK_EN,
+	     0x20, 12),
+	GATE(PCIE_DM_GEN3X4_SLV_ACLK_EN, "pcie_dm_gen3x4_slv_aclk", "top_cfg_aclk", PCIE_CLK_EN,
+	     0x20, 0),
+	GATE(PCIE_DM_GEN3X4_MST_ACLK_EN, "pcie_dm_gen3x4_mst_aclk", "pcie_ss_axi_m_aclk",
+	     PCIE_CLK_EN, 0x20, 8),
+	GATE(PCIE_DM_GEN3X4_PCLK_EN, "pcie_dm_gen3x4_pclk", "pcie_ss_apb_clk", PCIE_CLK_EN, 0x20,
+	     4),
+	GATE(PCIE_RP_GEN3X1_AUX_CLK_EN, "pcie_rp_gen3x1_aux_clk", "aon_osc_clk_logic", PCIE_CLK_EN,
+	     0x24, 12),
+	GATE(PCIE_RP_GEN3X1_SLV_ACLK_EN, "pcie_rp_gen3x1_slv_aclk", "top_cfg_aclk", PCIE_CLK_EN,
+	     0x24, 0),
+	GATE(PCIE_RP_GEN3X1_MST_ACLK_EN, "pcie_rp_gen3x1_mst_aclk", "pcie_ss_axi_m_aclk",
+	     PCIE_CLK_EN, 0x24, 8),
+	GATE(PCIE_RP_GEN3X1_PCLK_EN, "pcie_rp_gen3x1_pclk", "pcie_ss_apb_clk", PCIE_CLK_EN, 0x24,
+	     4),
+};
+
+static const struct a210_clk_desc info_usb[] = {
+	GATE(USB_SS_AXI_MST_PCLK_EN, "usb_axi_mst_pclk", "usb_ss_gtc_clk", USB_CLK_EN, 0, 16),
+	GATE(USB_SS_AXI_MST_ACLK_EN, "usb_axi_mst_aclk", "clkgen_usb_ss_bus_clk", USB_CLK_EN, 0,
+	     12),
+	GATE(USB_SS_DFMU_IOMMU_PTW_ACLK_EN, "usb_dfmu_ptw_aclk", "clkgen_usb_ss_bus_clk",
+	     USB_CLK_EN, 0, 8),
+	GATE(USB_SS_DFMU_ACLK_EN, "usb_dfmu_aclk", "clkgen_usb_ss_bus_clk", USB_CLK_EN, 0, 4),
+	GATE(USB_SS_DFMU_PCLK_EN, "usb_dfmu_pclk", "usb_ss_gtc_clk", USB_CLK_EN, 0, 0),
+	GATE(DPTX_I2S_CLK_EN, "usb_dptx_i2s_clk", "audio0_pll_foutvco", USB_CLK_EN, 0x4, 16),
+	GATE(DPTX_IPI_CLK_EN, "usb_dptx_ipi_clk", "usb_ss_gtc_clk", USB_CLK_EN, 0x4, 12),
+	GATE(DPTX_AUX_CLK_EN, "usb_dptx_aux_clk", "clkgen_usb_ss_aux_clk", USB_CLK_EN, 0x4, 8),
+	FIXED_FACTOR(USB_SS_GTC_CLK, "usb_ss_gtc_clk", "gmac_pll_foutpostdiv", 1, 10),
+	GATE(DPTX_GTC_CLK_EN, "usb_dptx_gtc_clk", "usb_ss_gtc_clk", USB_CLK_EN, 0x4, 4),
+	GATE(DPTX_PCLK_EN, "usb_dptx_pclk", "usb_ss_gtc_clk", USB_CLK_EN, 0x4, 0),
+	GATE(USB31_REF_CLK_EN, "usb31_ref_clk", "aon_osc_clk_logic", USB_CLK_EN, 0x8, 16),
+	GATE(USB31_SLV_AFENCE_ACLK_EN, "usb31_slv_afence_aclk", "clkgen_usb_ss_bus_clk", USB_CLK_EN,
+	     0x8, 20),
+	FIXED_FACTOR(USB_SS_PAD_OSC_CLK_1M, "usb_ss_pad_osc_clk_1m", "aon_osc_clk_logic", 1, 24),
+	GATE(USB31_SUSPEND_CLK_EN, "usb31_suspend_clk", "usb_ss_pad_osc_clk_1m", USB_CLK_EN, 0x8,
+	     8),
+	GATE(USB31_BUS_CLK_EN, "usb31_bus_clk", "clkgen_usb_ss_bus_clk", USB_CLK_EN, 0x8, 4),
+	GATE(USB31_PCLK_EN, "usb31_pclk", "usb_ss_gtc_clk", USB_CLK_EN, 0x8, 0),
+	GATE(C10PHY_SUSPEND_CLK_EN, "usb_c10phy_suspend_clk", "usb_ss_pad_osc_clk_1m", USB_CLK_EN,
+	     0xc, 4),
+	GATE(C10PHY_PCLK_EN, "usb_c10phy_pclk", "usb_ss_gtc_clk", USB_CLK_EN, 0xc, 0),
+	FIXED_FACTOR(USB20_CORE_CLK, "usb20_core_clk", "aon_osc_clk_logic", 1, 1),
+	GATE(USB_SS_PERI2_CFG_ACLK_EN, "usb_peri2_cfg_aclk", "aon_osc_clk_logic", USB_CLK_EN, 0x20,
+	     4),
+	GATE(USB20_BUS_CLK, "usb20_bus_clk", "clkgen_usb_ss_bus_clk", USB_CLK_EN, 0x10, 24),
+	GATE(USB20_X2H_HCLK, "usb20_x2h_hclk", "clkgen_usb_ss_bus_clk", USB_CLK_EN, 0x10, 0),
+	GATE(USB20_X2H_ACLK, "usb20_x2h_aclk", "clkgen_usb_ss_bus_clk", USB_CLK_EN, 0x10, 4),
+	GATE(USB20_SLV_AFENCE_ACLK, "usb20_slv_afence_aclk", "clkgen_usb_ss_bus_clk", USB_CLK_EN,
+	     0x10, 8),
+	GATE(USB20_H2P_HCLK, "usb20_h2p_hclk", "clkgen_usb_ss_bus_clk", USB_CLK_EN, 0x10, 16),
+	GATE(USB20_AHB_SLV_HCLK, "usb20_ahb_slv_hclk", "clkgen_usb_ss_bus_clk", USB_CLK_EN, 0x10,
+	     20),
+	GATE(USB20_SYSREG_PCLK, "usb20_sysreg_pclk", "clkgen_usb_ss_bus_clk", USB_CLK_EN, 0x10, 28),
+	GATE(USB20_WRAP0_HCLK, "usb20_wrap0_hclk", "clkgen_usb_ss_bus_clk", USB_CLK_EN, 0x14, 0),
+	GATE(USB20_WRAP1_HCLK, "usb20_wrap1_hclk", "clkgen_usb_ss_bus_clk", USB_CLK_EN, 0x14, 4),
+	GATE(USB20_A2X0_HCLK, "usb20_a2x0_hclk", "clkgen_usb_ss_bus_clk", USB_CLK_EN, 0x14, 16),
+	GATE(USB20_A2X0_ACLK, "usb20_a2x0_aclk", "clkgen_usb_ss_bus_clk", USB_CLK_EN, 0x14, 20),
+	GATE(USB20_A2X1_HCLK, "usb20_a2x1_hclk", "clkgen_usb_ss_bus_clk", USB_CLK_EN, 0x14, 24),
+	GATE(USB20_A2X1_ACLK, "usb20_a2x1_aclk", "clkgen_usb_ss_bus_clk", USB_CLK_EN, 0x14, 28),
+
+};
+
+static const struct a210_clk_desc info_vi[] = {
+	GATE(VI_VSE_CLK_EN, "dw200_vseclk", "vi_pre_vse_clk_div", VI_CLK, 0, 29),
+	GATE(VI_VSEOUT_CLK_EN, "dw200_vseout_clk", "vi_pre_vse_clk_div", VI_CLK, 0, 22),
+	DIV(VI_PRE_VSE_CLK_DIV_NUM, "vi_pre_vse_clk_div", "gmac_pll_foutpostdiv", VI_CLK, 0xc, 4, 4,
+	    25, MUX_TYPE_DIV, 1, 15),
+	GATE(VI_DWE_CLK_EN, "dw200_dweclk", "vi_pre_dwe_clk_div", VI_CLK, 0, 28),
+	GATE(VI_DW_SCLK_EN, "dw_sclk", "vi_pre_dwe_clk_div", VI_CLK, 0, 30),
+	DIV(VI_PRE_DWE_CLK_DIV_NUM, "vi_pre_dwe_clk_div", "video_pll_foutvco", VI_CLK, 0xc, 8, 4,
+	    26, MUX_TYPE_DIV, 3, 15),
+	DIV(VI_PRE_AXI_CLK_DIV_NUM, "vi_preocc_aclk", "video_pll_foutvco", VI_CLK, 0xc, 0, 4, 24,
+	    MUX_TYPE_DIV, 3, 15),
+	GATE(VI_DW200_ACLK_EN, "dw200_aclk", "vi_preocc_aclk", VI_CLK, 0, 27),
+	GATE(VI_DW200_HCLK_EN, "dw200_hclk", "top_cfg_aclk", VI_CLK, 0, 26),
+	DIV(VI_PRE_DECOMP_CLK_DIV_NUM, "vi_pre_decomp_clk", "audio0_pll_foutvco", VI_CLK, 0xc, 20,
+	    4, 29, MUX_TYPE_DIV, 4, 15),
+	GATE(VI_DECOMP_CLK_EN, "decomp_clk", "vi_pre_decomp_clk", VI_CLK, 0, 25),
+	GATE(VI_DECOUT_CLK_EN, "decout_clk", "vi_pre_decomp_clk", VI_CLK, 0, 21),
+	DIV(VI_PRE_COMP_CLK_DIV_NUM, "vi_pre_comp_clk", "audio0_pll_foutvco", VI_CLK, 0xc, 16, 4,
+	    28, MUX_TYPE_DIV, 4, 15),
+	GATE(VI_COMP0_CLK_EN, "comp0_clk", "vi_pre_comp_clk", VI_CLK, 0, 23),
+	GATE(VI_COMP1_CLK_EN, "comp1_clk", "vi_pre_comp_clk", VI_CLK, 0, 24),
+	GATE(VI_COMP_ACLK_EN, "comp_aclk", "vi_preocc_aclk", VI_CLK, 0, 19),
+	GATE(VI_COMP_PCLK_EN, "comp_pclk", "vi_pclk", VI_CLK, 0, 18),
+	GATE(VI_MIPI0CSI0_PCLK_EN, "mipi0_csi0_pclk", "vi_pclk", VI_CLK, 0, 0),
+	GATE(VI_MIPI0CSI1_PCLK_EN, "mipi0_csi1_pclk", "vi_pclk", VI_CLK, 0, 1),
+	GATE(VI_MIPI1CSI0_PCLK_EN, "mipi1_csi0_pclk", "vi_pclk", VI_CLK, 0, 6),
+	GATE(VI_MIPI1CSI1_PCLK_EN, "mipi1_csi1_pclk", "vi_pclk", VI_CLK, 0, 7),
+	GATE(VI_VIPRE_PCLK_EN, "vipre_pclk", "vi_pclk", VI_CLK, 0, 12),
+	GATE(VI_MIPI0CSI0_FPCLK_EN, "mipi0_csi0_fpclk", "vi_pclk", VI_CLK, 0x4, 8),
+	GATE(VI_MIPI0CSI1_FPCLK_EN, "mipi0_csi1_fpclk", "vi_pclk", VI_CLK, 0x4, 9),
+	GATE(VI_MIPI1CSI0_FPCLK_EN, "mipi1_csi0_fpclk", "vi_pclk", VI_CLK, 0x4, 10),
+	GATE(VI_MIPI1CSI1_FPCLK_EN, "mipi1_csi1_fpclk", "vi_pclk", VI_CLK, 0x4, 11),
+	FIXED_FACTOR(VI_PCLK, "vi_pclk", "top_cfg_aclk", 1, 2),
+	MUX(VI_ISP_IF_REF_SWITCH_SEL, "isp_if_ref_mux", VI_CLK, 0x8, 22, 2, isp_if_ref_mux_parents,
+	    CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT),
+	GATE(VI_VIPRE_SCLK_EN, "vipre_sclk", "isp_if_ref_clk_div", VI_CLK, 0, 15),
+	DIV_CLOSEST(VI_PRE_ISP_IF_CLK_DIV_NUM, "isp_if_ref_clk_div", "isp_if_ref_mux", VI_CLK, 0x8,
+		    11, 4, 26, MUX_TYPE_DIV, 3, 15),
+	GATE(VI_ISP_CLK_EN, "isp_entire_clk", "video_pll_foutvco", VI_CLK, 0, 17),
+	DIV(VI_PRE_ISP_CORE_CLK_DIV_NUM, "isp_core_clk", "video_pll_foutvco", VI_CLK, 0x8, 16, 4,
+	    27, MUX_TYPE_DIV, 4, 15),
+	GATE(VI_ISPOUT_CLK_EN, "ispout_clk", "isp_core_clk", VI_CLK, 0, 20),
+	GATE(VI_VIPRE_ACLK_EN, "vipre_aclk", "vi_preocc_aclk", VI_CLK, 0, 16),
+	GATE(VI_VIPRE_I0_PIXCLK_EN, "vipre_m0if_clk", "vi_preocc_mipi0_ifclk", VI_CLK, 0, 13),
+	GATE(VI_MIPI0_CSI0_PIXCLK_EN, "mipi0_csi0if_clk", "vi_preocc_mipi0_ifclk", VI_CLK, 0, 4),
+	GATE(VI_MIPI0_CSI1_PIXCLK_EN, "mipi0_csi1if_clk", "vi_preocc_mipi0_ifclk", VI_CLK, 0, 5),
+	DIV_CLOSEST(VI_PRE_MIPI0_PIXCLK_DIV_NUM, "vi_preocc_mipi0_ifclk",
+		    "vi_preocc_mipi0_ifclk_mux", VI_CLK, 0x8, 0, 4, 24, MUX_TYPE_DIV, 3, 15),
+	MUX(VI_MIPI0_PIX_REF_SWITCH_SEL, "vi_preocc_mipi0_ifclk_mux", VI_CLK, 0x8, 20, 1,
+	    vi_preocc_mipi0_ifclk_mux_parents, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT),
+	GATE(VI_VIPRE_I1_PIXCLK_EN, "vipre_m1if_clk", "vi_preocc_mipi1_ifclk", VI_CLK, 0, 14),
+	GATE(VI_MIPI1_CSI0_PIXCLK_EN, "mipi1_csi0if_clk", "vi_preocc_mipi1_ifclk", VI_CLK, 0, 10),
+	GATE(VI_MIPI1_CSI1_PIXCLK_EN, "mipi1_csi1if_clk", "vi_preocc_mipi1_ifclk", VI_CLK, 0, 11),
+	DIV_CLOSEST(VI_PRE_MIPI1_PIXCLK_DIV_NUM, "vi_preocc_mipi1_ifclk",
+		    "vi_preocc_mipi1_ifclk_mux", VI_CLK, 0x8, 4, 4, 25, MUX_TYPE_DIV, 3, 15),
+	MUX(VI_MIPI1_PIX_REF_SWITCH_SEL, "vi_preocc_mipi1_ifclk_mux", VI_CLK, 0x8, 21, 1,
+	    vi_preocc_mipi1_ifclk_mux_parents, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT),
+	GATE(VI_MIPI1B_CFGCLK_EN, "mipi1_csi0_cfgclk", "aon_osc_clk_logic", VI_CLK, 0, 9),
+	GATE(VI_MIPI1A_CFGCLK_EN, "mipi1_csi1_cfgclk", "aon_osc_clk_logic", VI_CLK, 0, 8),
+	GATE(VI_MIPI0B_CFGCLK_EN, "mipi0_csi0_cfgclk", "aon_osc_clk_logic", VI_CLK, 0, 3),
+	GATE(VI_MIPI0A_CFGCLK_EN, "mipi0_csi1_cfgclk", "aon_osc_clk_logic", VI_CLK, 0, 2),
+	GATE(VI_X2H0_CLK_EN, "vi_x2h0_clk", "top_cfg_aclk", VI_CLK, 0x4, 5),
+	GATE(VI_X2H1_CLK_EN, "vi_x2h1_clk", "top_cfg_aclk", VI_CLK, 0x4, 6),
+	GATE(VI_X2H2_CLK_EN, "vi_x2h2_clk", "top_cfg_aclk", VI_CLK, 0x4, 7),
+	GATE(VI_REC_PCLK_EN, "vi_rec_pclk", "top_cfg_aclk", VI_CLK, 0x4, 13),
+	GATE(VI_REC_ACLK_EN, "vi_rec_aclk", "top_cfg_aclk", VI_CLK, 0x4, 14),
+	GATE(VI_MISC_CTRL_H0CLK_CLK_EN, "vi_misc_ctrl_h0clk", "top_cfg_aclk", VI_MISC_CTRL, 0x0, 1),
+	GATE(VI_MISC_CTRL_H1CLK_CLK_EN, "vi_misc_ctrl_h1clk", "top_cfg_aclk", VI_MISC_CTRL, 0x0, 2),
+	GATE(VI_MISC_CTRL_ISP_ACLK_CLK_EN, "vi_misc_ctrl_isp_aclk", "top_cfg_aclk", VI_MISC_CTRL,
+	     0x0, 3),
+	GATE(VI_MISC_CTRL_ISP_SCLK_CLK0_EN, "vi_misc_ctrl_isp_sclk0", "top_cfg_aclk", VI_MISC_CTRL,
+	     0x0, 4),
+	GATE(VI_MISC_CTRL_ISP_SCLK_CLK1_EN, "vi_misc_ctrl_isp_sclk1", "top_cfg_aclk", VI_MISC_CTRL,
+	     0x0, 5),
+	GATE(VI_MISC_CTRL_ISP_SCLK_CLK2_EN, "vi_misc_ctrl_isp_sclk2", "top_cfg_aclk", VI_MISC_CTRL,
+	     0x0, 6),
+	GATE(VI_MISC_CTRL_ISP_SCLK_CLK3_EN, "vi_misc_ctrl_isp_sclk3", "top_cfg_aclk", VI_MISC_CTRL,
+	     0x0, 7),
+	GATE(VI_MISC_CTRL_ISP_CORE_CLK_EN, "vi_misc_ctrl_isp_core_clk", "isp_core_clk",
+	     VI_MISC_CTRL, 0x0, 8),
+	GATE(VI_MISC_CTRL_ISP_FLEXA_CLK_EN, "vi_misc_ctrl_isp_flexa_clk", "isp_core_clk",
+	     VI_MISC_CTRL, 0x0, 9),
+	GATE(VI_MISC_CTRL_ISP_MCM_CLK_EN, "vi_misc_ctrl_isp_mcm_clk", "isp_core_clk", VI_MISC_CTRL,
+	     0x0, 10),
+	GATE(VI_MISC_CTRL_BUS_CLK_GT_DISABLE, "vi_misc_ctrl_bus_clk", "isp_core_clk", VI_MISC_CTRL,
+	     0x0, 11),
+};
+
+static const struct a210_clk_desc info_vp[] = {
+	GATE(VP_DECOMP_EXTPCLK_EN, "vp_decomp_extpclk", "top_cfg_aclk", VP_CLK, 0, 23),
+	GATE(VP_COMP_EXTPCLK_EN, "vp_comp_extpclk", "top_cfg_aclk", VP_CLK, 0, 22),
+	GATE(VP_DECOMP_ACLK_EN, "vp_decomp_aclk", "vp_aclk", VP_CLK, 0, 14),
+	GATE(VP_DECOMP_CCLK_EN, "vp_decomp_cclk", "vp_decomp_clk_div", VP_CLK, 0, 13),
+	GATE(VP_DECOMP_PCLK_EN, "vp_decomp_pclk", "top_cfg_aclk", VP_CLK, 0, 12),
+	GATE(VP_COMP_ACLK_EN, "vp_comp_aclk", "vp_aclk", VP_CLK, 0, 11),
+	GATE(VP_COMP_CCLK_EN, "vp_comp_cclk", "vp_comp_clk_div", VP_CLK, 0, 10),
+	GATE(VP_COMP_PCLK_EN, "vp_comp_pclk", "top_cfg_aclk", VP_CLK, 0, 9),
+	GATE(VP_G2D_ACLK_EN, "vp_g2d_aclk", "vp_aclk", VP_CLK, 0, 8),
+	GATE(VP_G2D_CCLK_EN, "vp_g2d_cclk", "g2d_cclk", VP_CLK, 0, 7),
+	GATE(VP_G2D_PCLK_EN, "vp_g2d_pclk", "top_cfg_aclk", VP_CLK, 0, 6),
+	GATE(VP_VENC_ACLK_EN, "vp_venc_aclk", "vp_aclk", VP_CLK, 0, 5),
+	GATE(VP_VENC_CCLK_EN, "vp_venc_cclk", "venc_cclk", VP_CLK, 0, 4),
+	GATE(VP_VENC_PCLK_EN, "vp_venc_pclk", "top_cfg_aclk", VP_CLK, 0, 3),
+	GATE(VP_VDEC_ACLK_EN, "vp_vdec_aclk", "vp_aclk", VP_CLK, 0, 2),
+	GATE(VP_VDEC_CCLK_EN, "vp_vdec_cclk", "vdec_cclk", VP_CLK, 0, 1),
+	GATE(VP_VDEC_PCLK_EN, "vp_vdec_pclk", "top_cfg_aclk", VP_CLK, 0, 0),
+	DIV(VP_DECOMP_DIV_NUM, "vp_decomp_clk_div", "vp_aclk", VP_CLK, 0x4, 16, 4, 20, MUX_TYPE_DIV,
+	    2, 15),
+	DIV(VP_COMP_DIV_NUM, "vp_comp_clk_div", "vp_aclk", VP_CLK, 0x4, 8, 4, 12, MUX_TYPE_DIV, 2,
+	    15),
+};
+
+#define VO_PIXCLK_MUX_FLAGS (CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT)
+
+static const struct a210_clk_desc info_vo[] = {
+	GATE(VO_DFMU_PCLK_EN, "vo_dfmu_pclk", "vo_pclk", VO_CLK, 0, 20),
+	GATE(VO_DFMU_ACLK_EN, "vo_dfmu_aclk", "vo_preocc_aclk", VO_CLK, 0, 21),
+	GATE(VO_PTW_ACLK_EN, "vo_ptw_aclk", "vo_preocc_aclk", VO_CLK, 0, 22),
+	GATE(VO_X2H1_CLK_EN, "vo_x2h1_clk", "top_cfg_aclk", VO_CLK, 0, 24),
+	GATE(VO_X2H0_CLK_EN, "vo_x2h0_clk", "top_cfg_aclk", VO_CLK, 0, 23),
+	GATE(VO_ARB_ACLK_EN, "vo_arb_aclk", "vo_preocc_aclk", VO_CLK, 0, 19),
+	GATE(VO_DPU_ACLK_EN, "vo_dpu_aclk", "vo_preocc_aclk", VO_CLK, 0, 4),
+	GATE(VO_AUXDISP_ACLK_EN, "vo_disp_aclk", "vo_preocc_aclk", VO_CLK, 0, 7),
+	GATE(VO_DECOMP_ACLK_EN, "vo_decomp_aclk", "vo_preocc_aclk", VO_CLK, 0, 17),
+	DIV(VO_ACLK_DIV_NUM, "vo_preocc_aclk", "video_pll_foutvco", VO_CLK, 0x8, 0, 4, 4,
+	    MUX_TYPE_DIV, 3, 15),
+	GATE(VO_DECOMP_PCLK_EN, "vo_decomp_pclk", "vo_pclk", VO_CLK, 0, 14),
+	GATE(VO_HDMI_PCLK_EN, "vo_hdmi_pclk", "vo_pclk", VO_CLK, 0, 8),
+	GATE(VO_MIPI_PCLK_EN, "vo_mipi_pclk", "vo_pclk", VO_CLK, 0, 12),
+	GATE(VO_AUXDISP_PCLK_EN, "vo_auxdisp_pclk", "vo_pclk", VO_CLK, 0, 6),
+	GATE(VO_ARB_PCLK_EN, "vo_arb_pclk", "vo_pclk", VO_CLK, 0, 18),
+	FIXED_FACTOR(VO_PCLK, "vo_pclk", "top_cfg_aclk", 1, 2),
+	GATE(VO_DECOMP0_CLK_EN, "vo_decomp0_clk", "vo_decomp_div", VO_CLK, 0, 15),
+	GATE(VO_DECOMP1_CLK_EN, "vo_decomp1_clk", "vo_decomp_div", VO_CLK, 0, 16),
+	DIV(VO_DECOMP_DIV_NUM, "vo_decomp_div", "video_pll_foutvco", VO_CLK, 0x8, 16, 4, 20,
+	    MUX_TYPE_DIV, 12, 15),
+	GATE(VO_MIPI_CFGCLK_EN, "vo_mipi_cfgclk", "aon_osc_clk_logic", VO_CLK, 0, 13),
+	GATE(VO_HDMI_SFRCLK_EN, "vo_hdmi_sfrclk", "aon_osc_clk_logic", VO_CLK, 0, 11),
+	GATE(VO_CEC_CLK_EN, "vo_hdmi_cecclk", "aon_rtc_clk", VO_CLK, 0, 10),
+	GATE(VO_I2S_CLK_EN, "vo_hdmi_i2sclk", "audio0_pll_foutvco", VO_CLK, 0, 9),
+	GATE(VO_CH0_PIXCLK_EN, "dpu0_pixclk", "vo_pll0_div", VO_CLK, 0, 0),
+	DIV(VO_PLL0_DIV_NUM, "vo_pll0_div", "dpu0_pll_foutpostdiv", VO_CLK, 0x4, 0, 8, 8,
+	    MUX_TYPE_DIV, 2, 255),
+	GATE(VO_CH1_PIXCLK_EN, "dpu1_pixclk", "vo_pll1_div", VO_CLK, 0, 1),
+	DIV(VO_PLL1_DIV_NUM, "vo_pll1_div", "dpu1_pll_foutpostdiv", VO_CLK, 0x4, 10, 8, 18,
+	    MUX_TYPE_DIV, 2, 255),
+	GATE(VO_CH2_PIXCLK_EN, "dpu2_pixclk", "vo_pll2_div", VO_CLK, 0, 5),
+	DIV(VO_PLL2_DIV_NUM, "vo_pll2_div", "dpu2_pll_foutpostdiv", VO_CLK, 0x4, 20, 8, 28,
+	    MUX_TYPE_DIV, 2, 255),
+	GATE(VO_DPU_HCLK_EN, "vo_dpuc_hclk", "top_cfg_aclk", VO_CLK, 0, 2),
+	GATE(VO_DPUC_CLK_EN, "vo_dpuc_clk", "vo_dpuc_div", VO_CLK, 0, 3),
+	DIV(VO_DPUC_DIV_NUM, "vo_dpuc_div", "video_pll_foutvco", VO_CLK, 0x8, 8, 4, 12,
+	    MUX_TYPE_DIV, 3, 15),
+	MUX(VO_MIPI_PIXCLK, "vo_mipi_pixclk", VO_PATH_CTRL, 0x0, 0, 2, vo_mipi_pixclk_mux_parents,
+	    VO_PIXCLK_MUX_FLAGS),
+	MUX(VO_HDMI_PIXCLK, "vo_hdmi_pixclk", VO_PATH_CTRL, 0x0, 2, 2, vo_hdmi_pixclk_mux_parents,
+	    VO_PIXCLK_MUX_FLAGS),
+	MUX(VO_DPTX_PIXCLK, "vo_dptx_pixclk", VO_PATH_CTRL, 0x0, 4, 2, vo_dptx_pixclk_mux_parents,
+	    VO_PIXCLK_MUX_FLAGS),
+};
+
+static const struct a210_clk_desc info_npu[] = {
+	GATE(SW_SEMA_PCLK_EN, "npu_clkgen_sema_pclk", "top_cfg_aclk", NPU_CLK, 0, 23),
+	GATE(SW_SEMA_ACLK_EN, "npu_clkgen_sema_aclk", "npu_aclk", NPU_CLK, 0, 22),
+	GATE(SW_NPU_X2P_ACLK_EN, "npu_x2p_aclk", "top_cfg_aclk", NPU_CLK, 0, 21),
+	GATE(SW_NPU_X2H_ACLK_EN, "npu_x2h_aclk", "top_cfg_aclk", NPU_CLK, 0, 20),
+	GATE(SW_NPU_IP_HCLK_EN, "npu_ip_hclk", "top_cfg_aclk", NPU_CLK, 0, 12),
+	GATE(SW_NPU_IP_CCLK_EN, "npu_ip_cclk", "npu_cclk", NPU_CLK, 0, 11),
+	GATE(SW_NPU_IP_ACLK_EN, "npu_ip_aclk", "npu_aclk", NPU_CLK, 0, 10),
+};
+
+static const struct a210_clk_desc info_peri[] = {
+	/* PERI0 SS */
+	GATE(PERI0_MBOX1_PCLK_EN, "peri0_mbox1_pclk", "top_cfg_aclk", PERI0_SYSREG, 0, 6),
+	GATE(PERI0_MBOX0_PCLK_EN, "peri0_mbox0_pclk", "top_cfg_aclk", PERI0_SYSREG, 0, 5),
+	GATE(PERI0_WDT0_PCLK_EN, "peri0_wdt0_pclk", "top_cfg_aclk", PERI0_SYSREG, 0, 4),
+	GATE(PERI0_TIMER1_PCLK_EN, "peri0_timer1_pclk", "top_cfg_aclk", PERI0_SYSREG, 0, 3),
+	GATE(PERI0_TIMER1_CCLK_EN, "peri0_timer1_cclk", "top_cfg_aclk", PERI0_SYSREG, 0, 2),
+	GATE(PERI0_TIMER0_PCLK_EN, "peri0_timer0_pclk", "top_cfg_aclk", PERI0_SYSREG, 0, 1),
+	GATE(PERI0_TIMER0_CCLK_EN, "peri0_timer0_cclk", "top_cfg_aclk", PERI0_SYSREG, 0, 0),
+	/* PERI1 SS */
+	GATE(PERI1_UART3_SCLK_EN, "peri1_clkgen_uart3_sclk", "uart_sclk", PERI1_SYSREG, 0, 31),
+	GATE(PERI1_UART3_PCLK_EN, "peri1_clkgen_uart3_pclk", "top_cfg_aclk", PERI1_SYSREG, 0, 30),
+	GATE(PERI1_UART2_SCLK_EN, "peri1_clkgen_uart2_sclk", "uart_sclk", PERI1_SYSREG, 0, 29),
+	GATE(PERI1_UART2_PCLK_EN, "peri1_clkgen_uart2_pclk", "top_cfg_aclk", PERI1_SYSREG, 0, 28),
+	GATE(PERI1_UART1_SCLK_EN, "peri1_clkgen_uart1_sclk", "uart_sclk", PERI1_SYSREG, 0, 27),
+	GATE(PERI1_UART1_PCLK_EN, "peri1_clkgen_uart1_pclk", "top_cfg_aclk", PERI1_SYSREG, 0, 26),
+	GATE(PERI1_UART0_SCLK_EN, "peri1_clkgen_uart0_sclk", "uart_sclk", PERI1_SYSREG, 0, 25),
+	GATE(PERI1_UART0_PCLK_EN, "peri1_clkgen_uart0_pclk", "top_cfg_aclk", PERI1_SYSREG, 0, 24),
+	GATE(PERI1_SPI0_SSI_CLK_EN, "peri1_clkgen_spi0_ssi_clk", "peri1_spi_ssi_clk", PERI1_SYSREG,
+	     0, 23),
+	GATE(PERI1_SPI0_PCLK_EN, "peri1_clkgen_spi0_pclk", "top_cfg_aclk", PERI1_SYSREG, 0, 22),
+	GATE(PERI1_QSPI0_SSI_CLK_EN, "peri1_clkgen_qspi0_ssi_clk", "peri1_qspi_ssi_clk",
+	     PERI1_SYSREG, 0, 21),
+	GATE(PERI1_QSPI0_PCLK_EN, "peri1_clkgen_qspi0_pclk", "top_cfg_aclk", PERI1_SYSREG, 0, 20),
+	GATE(PERI1_PWM0_PCLK_EN, "peri1_clkgen_pwm0_pclk", "peri1_pwm_clk", PERI1_SYSREG, 0, 19),
+	GATE(PERI1_PWM0_CCLK_EN, "peri1_clkgen_pwm0_cclk", "peri1_clkgen_pwm0_pclk", PERI1_SYSREG,
+	     0, 18),
+	/* E902 firmware accesses AP peripherals through this shared bus. */
+	GATE_FLAGS(PERI1_MST_BUS_PCLK_EN, "peri1_clkgen_mst_bus_pclk", "top_cfg_aclk", PERI1_SYSREG,
+		   0, 17, CLK_IS_CRITICAL),
+	GATE_FLAGS(PERI1_MST_BUS_ACLK_EN, "peri1_clkgen_mst_bus_aclk", "peri1_mst_aclk",
+		   PERI1_SYSREG, 0, 16, CLK_IS_CRITICAL),
+	GATE(PERI1_I2S0_SRC_CLK_EN, "peri1_clkgen_i2s0_src_clk", "peri1_i2s0_src_clk", PERI1_SYSREG,
+	     0, 15),
+	GATE(PERI1_I2S0_PCLK_EN, "peri1_clkgen_i2s0_pclk", "top_cfg_aclk", PERI1_SYSREG, 0, 14),
+	GATE(PERI1_I2C2_PCLK_EN, "peri1_clkgen_i2c2_pclk", "top_cfg_aclk", PERI1_SYSREG, 0, 13),
+	GATE(PERI1_I2C2_IC_CLK_EN, "peri1_clkgen_i2c2_ic_clk", "i2c_ic_clk", PERI1_SYSREG, 0, 12),
+	GATE(PERI1_I2C1_PCLK_EN, "peri1_clkgen_i2c1_pclk", "top_cfg_aclk", PERI1_SYSREG, 0, 11),
+	GATE(PERI1_I2C1_IC_CLK_EN, "peri1_clkgen_i2c1_ic_clk", "i2c_ic_clk", PERI1_SYSREG, 0, 10),
+	GATE(PERI1_I2C0_PCLK_EN, "peri1_clkgen_i2c0_pclk", "top_cfg_aclk", PERI1_SYSREG, 0, 9),
+	GATE(PERI1_I2C0_IC_CLK_EN, "peri1_clkgen_i2c0_ic_clk", "i2c_ic_clk", PERI1_SYSREG, 0, 8),
+	GATE(PERI1_GPIO1_PCLK_EN, "peri1_clkgen_gpio1_pclk", "top_cfg_aclk", PERI1_SYSREG, 0, 7),
+	GATE(PERI1_GPIO1_DBCLK_EN, "peri1_clkgen_gpio1_dbclk", "aon_rtc_clk", PERI1_SYSREG, 0, 6),
+	GATE(PERI1_GPIO0_PCLK_EN, "peri1_clkgen_gpio0_pclk", "top_cfg_aclk", PERI1_SYSREG, 0, 5),
+	GATE(PERI1_GPIO0_DBCLK_EN, "peri1_clkgen_gpio0_dbclk", "aon_rtc_clk", PERI1_SYSREG, 0, 4),
+	GATE(PERI1_GMAC1_HCLK_EN, "peri1_gmac1_hclk", "top_cfg_aclk", PERI1_SYSREG, 0, 3),
+	GATE(PERI1_GMAC1_ACLK_EN, "peri1_gmac1_aclk", "peri1_mst_aclk", PERI1_SYSREG, 0, 2),
+	GATE(PERI1_GMAC0_HCLK_EN, "peri1_gmac0_hclk", "top_cfg_aclk", PERI1_SYSREG, 0, 1),
+	GATE(PERI1_GMAC0_ACLK_EN, "peri1_gmac0_aclk", "peri1_mst_aclk", PERI1_SYSREG, 0, 0),
+	GATE(PERI1_ZGMAC_X2X_ACLK_EN, "peri1_zgmac0_x2x_aclk", "peri1_mst_aclk", PERI1_SYSREG, 0x4,
+	     25),
+	GATE(PERI1_GMAC2_HCLK_EN, "peri1_gmac2_hclk", "top_cfg_aclk", PERI1_SYSREG, 0x4, 24),
+	GATE(PERI1_GMAC2_ACLK_EN, "peri1_gmac2_aclk", "top_cfg_aclk", PERI1_SYSREG, 0x4, 23),
+	GATE(PERI1_X2H_GMAC2_HCLK_EN, "peri1_x2h_gmac2_hclk", "top_cfg_aclk", PERI1_SYSREG, 0x4,
+	     22),
+	GATE(PERI1_X2H_GMAC2_ACLK_EN, "peri1_x2h_gmac2_aclk", "top_cfg_aclk", PERI1_SYSREG, 0x4,
+	     21),
+	GATE(PERI1_CHIP_DBG_PCLK_EN, "peri1_chip_dbg_pclk", "top_cfg_aclk", PERI1_SYSREG, 0x4, 20),
+	GATE(PERI1_CHIP_DBG_CCLK_EN, "peri1_chip_dbg_cclk", "aon_osc_clk_logic", PERI1_SYSREG, 0x4,
+	     19),
+	GATE(PERI1_CHIP_DBG_ACLK_EN, "peri1_chip_dbg_aclk", "peri1_mst_aclk", PERI1_SYSREG, 0x4,
+	     18),
+	GATE(PERI1_TDM0_SCLK_EN, "peri1_tdm0_sclk", "peri1_tdm_src_clk", PERI1_SYSREG, 0x4, 17),
+	GATE(PERI1_TDM0_PCLK_EN, "peri1_tdm0_pclk", "top_cfg_aclk", PERI1_SYSREG, 0x4, 16),
+	GATE(PERI1_PDM0_PCLK_EN, "peri1_pdm0_pclk", "top_cfg_aclk", PERI1_SYSREG, 0x4, 15),
+	GATE(PERI1_PDM0_MCLK_EN, "peri1_pdm0_mclk", "peri1_pdm_mclk", PERI1_SYSREG, 0x4, 14),
+	GATE(PERI1_CAN1_PCLK_EN, "peri1_can1_pclk", "top_cfg_aclk", PERI1_SYSREG, 0x4, 13),
+	GATE(PERI1_CAN1_OSC_CLK_EN, "peri1_can1_osc_clk", "peri1_hires_clk", PERI1_SYSREG, 0x4, 12),
+	GATE(PERI1_CAN1_HIRES_CLK_EN, "peri1_can1_hires_clk", "peri1_can1_osc_clk", PERI1_SYSREG,
+	     0x4, 11),
+	GATE(PERI1_CAN0_PCLK_EN, "peri1_can0_pclk", "top_cfg_aclk", PERI1_SYSREG, 0x4, 10),
+	GATE(PERI1_CAN0_OSC_CLK_EN, "peri1_can0_osc_clk", "peri1_hires_clk", PERI1_SYSREG, 0x4, 9),
+	GATE(PERI1_CAN0_HIRES_CLK_EN, "peri1_can0_hires_clk", "peri1_can0_osc_clk", PERI1_SYSREG,
+	     0x4, 8),
+	GATE(PERI1_PAD_CTRL_PCLK_EN, "peri1_pad_ctrl_pclk", "top_cfg_aclk", PERI1_SYSREG, 0x4, 7),
+	GATE(PERI1_X2H_GMAC1_HCLK_EN, "peri1_x2h_gmac1_hclk", "top_cfg_aclk", PERI1_SYSREG, 0x4, 3),
+	GATE(PERI1_X2H_GMAC1_ACLK_EN, "peri1_x2h_gmac1_aclk", "top_cfg_aclk", PERI1_SYSREG, 0x4, 2),
+	GATE(PERI1_X2H_GMAC0_HCLK_EN, "peri1_x2h_gmac0_hclk", "top_cfg_aclk", PERI1_SYSREG, 0x4, 1),
+	GATE(PERI1_X2H_GMAC0_ACLK_EN, "peri1_x2h_gmac0_aclk", "top_cfg_aclk", PERI1_SYSREG, 0x4, 0),
+	/* PERI2 SS */
+	GATE(PERI2_I2S3_PCLK_EN, "peri2_clkgen_i2s3_pclk", "top_cfg_aclk", PERI2_SYSREG, 0, 31),
+	GATE(PERI2_I2S3_SRC_CLK_EN, "peri2_clkgen_i2s3_src_clk", "peri2_i2s3_src_clk", PERI2_SYSREG,
+	     0, 30),
+	GATE(PERI2_I2S2_PCLK_EN, "peri2_clkgen_i2s2_pclk", "top_cfg_aclk", PERI2_SYSREG, 0, 29),
+	GATE(PERI2_I2S2_SRC_CLK_EN, "peri2_clkgen_i2s2_src_clk", "peri2_i2s2_src_clk", PERI2_SYSREG,
+	     0, 28),
+	GATE(PERI2_I2S1_PCLK_EN, "peri2_clkgen_i2s1_pclk", "top_cfg_aclk", PERI2_SYSREG, 0, 27),
+	GATE_FLAGS(PERI2_I2S1_SRC_CLK_EN, "peri2_clkgen_i2s1_src_clk", "peri2_i2s1_src_clk",
+		   PERI2_SYSREG, 0, 26, CLK_SET_RATE_PARENT),
+	GATE(PERI2_I2C7_IC_CLK_EN, "peri2_clkgen_i2c7_ic_clk", "i2c_ic_clk", PERI2_SYSREG, 0, 25),
+	GATE(PERI2_I2C7_PCLK_EN, "peri2_clkgen_i2c7_pclk", "top_cfg_aclk", PERI2_SYSREG, 0, 24),
+	GATE(PERI2_I2C6_IC_CLK_EN, "peri2_clkgen_i2c6_ic_clk", "i2c_ic_clk", PERI2_SYSREG, 0, 23),
+	GATE(PERI2_I2C6_PCLK_EN, "peri2_clkgen_i2c6_pclk", "top_cfg_aclk", PERI2_SYSREG, 0, 22),
+	GATE(PERI2_I2C5_IC_CLK_EN, "peri2_clkgen_i2c5_ic_clk", "i2c_ic_clk", PERI2_SYSREG, 0, 21),
+	GATE(PERI2_I2C5_PCLK_EN, "peri2_clkgen_i2c5_pclk", "top_cfg_aclk", PERI2_SYSREG, 0, 20),
+	GATE(PERI2_I2C4_IC_CLK_EN, "peri2_clkgen_i2c4_ic_clk", "i2c_ic_clk", PERI2_SYSREG, 0, 19),
+	GATE(PERI2_I2C4_PCLK_EN, "peri2_clkgen_i2c4_pclk", "top_cfg_aclk", PERI2_SYSREG, 0, 18),
+	GATE(PERI2_I2C3_IC_CLK_EN, "peri2_clkgen_i2c3_ic_clk", "i2c_ic_clk", PERI2_SYSREG, 0, 17),
+	GATE(PERI2_I2C3_PCLK_EN, "peri2_clkgen_i2c3_pclk", "top_cfg_aclk", PERI2_SYSREG, 0, 16),
+	GATE(PERI2_GPIO3_DBCLK_EN, "peri2_clkgen_gpio3_dbclk", "aon_rtc_clk", PERI2_SYSREG, 0, 15),
+	GATE(PERI2_GPIO3_PCLK_EN, "peri2_clkgen_gpio3_pclk", "top_cfg_aclk", PERI2_SYSREG, 0, 14),
+	GATE(PERI2_PAD_CTRL_PCLK_EN, "peri2_clkgen_pad_ctrl_pclk", "top_cfg_aclk", PERI2_SYSREG, 0,
+	     13),
+	GATE(PERI2_UART6_PCLK_EN, "peri2_clkgen_uart6_pclk", "top_cfg_aclk", PERI2_SYSREG, 0, 12),
+	GATE(PERI2_UART5_PCLK_EN, "peri2_clkgen_uart5_pclk", "top_cfg_aclk", PERI2_SYSREG, 0, 11),
+	GATE_FLAGS(PERI2_UART4_PCLK_EN, "peri2_clkgen_uart4_pclk", "top_cfg_aclk", PERI2_SYSREG, 0,
+		   10, CLK_IS_CRITICAL),
+	GATE(PERI2_SPI1_PCLK_EN, "peri2_clkgen_spi1_pclk", "top_cfg_aclk", PERI2_SYSREG, 0, 9),
+	GATE(PERI2_GPIO2_PCLK_EN, "peri2_clkgen_gpio2_pclk", "top_cfg_aclk", PERI2_SYSREG, 0, 8),
+	GATE(PERI2_CAN2_PCLK_EN, "peri2_clkgen_can2_pclk", "top_cfg_aclk", PERI2_SYSREG, 0, 7),
+	GATE(PERI2_UART6_SCLK_EN, "peri2_clkgen_uart6_sclk", "uart_sclk", PERI2_SYSREG, 0, 6),
+	GATE(PERI2_UART5_SCLK_EN, "peri2_clkgen_uart5_sclk", "uart_sclk", PERI2_SYSREG, 0, 5),
+	GATE_FLAGS(PERI2_UART4_SCLK_EN, "peri2_clkgen_uart4_sclk", "uart_sclk", PERI2_SYSREG, 0, 4,
+		   CLK_IS_CRITICAL),
+	GATE(PERI2_SPI1_SSI_CLK_EN, "peri2_clkgen_spi1_ssi_clk", "peri2_spi_ssi_clk", PERI2_SYSREG,
+	     0, 3),
+	GATE(PERI2_GPIO2_DBCLK_EN, "peri2_clkgen_gpio2_dbclk", "aon_rtc_clk", PERI2_SYSREG, 0, 2),
+	GATE(PERI2_CAN2_OSC_CLK_EN, "peri2_clkgen_can2_osc_clk", "peri2_hires_clk", PERI2_SYSREG, 0,
+	     1),
+	GATE(PERI2_CAN2_HIRES_CLK_EN, "peri2_clkgen_can2_hires_clk", "peri2_clkgen_can2_osc_clk",
+	     PERI2_SYSREG, 0, 0),
+	GATE(PERI2_QSPI1_PCLK_EN, "peri2_clkgen_qspi1_pclk", "top_cfg_aclk", PERI2_SYSREG, 0x4, 11),
+	GATE(PERI2_QSPI1_SSI_CLK_EN, "peri2_clkgen_qspi1_ssi_clk", "peri2_qspi_ssi_clk",
+	     PERI2_SYSREG, 0x4, 10),
+	GATE(PERI2_UART9_PCLK_EN, "peri2_clkgen_uart9_pclk", "top_cfg_aclk", PERI2_SYSREG, 0x4, 9),
+	GATE(PERI2_UART9_SCLK_EN, "peri2_clkgen_uart9_sclk", "uart_sclk", PERI2_SYSREG, 0x4, 8),
+	GATE(PERI2_UART8_PCLK_EN, "peri2_clkgen_uart8_pclk", "top_cfg_aclk", PERI2_SYSREG, 0x4, 7),
+	GATE(PERI2_UART8_SCLK_EN, "peri2_clkgen_uart8_sclk", "uart_sclk", PERI2_SYSREG, 0x4, 6),
+	GATE(PERI2_UART7_PCLK_EN, "peri2_clkgen_uart7_pclk", "top_cfg_aclk", PERI2_SYSREG, 0x4, 5),
+	GATE(PERI2_UART7_SCLK_EN, "peri2_clkgen_uart7_sclk", "uart_sclk", PERI2_SYSREG, 0x4, 4),
+	GATE(PERI2_PWM2_PCLK_EN, "peri2_clkgen_pwm2_pclk", "peri2_pwm_clk", PERI2_SYSREG, 0x4, 3),
+	GATE(PERI2_PWM2_CCLK_EN, "peri2_clkgen_pwm2_cclk", "peri2_clkgen_pwm2_pclk", PERI2_SYSREG,
+	     0x4, 2),
+	GATE(PERI2_PWM1_PCLK_EN, "peri2_clkgen_pwm1_pclk", "peri2_pwm_clk", PERI2_SYSREG, 0x4, 1),
+	GATE(PERI2_PWM1_CCLK_EN, "peri2_clkgen_pwm1_cclk", "peri2_clkgen_pwm1_pclk", PERI2_SYSREG,
+	     0x4, 0),
+	/* PERI3 SS */
+	GATE(PERI3_PAD_CTRL_PCLK_EN, "peri3_clkgen_pad_ctrl_pclk", "top_cfg_aclk", PERI3_SYSREG, 0,
+	     21),
+	GATE(PERI3_GPIO4_PCLK_EN, "peri3_clkgen_gpio4_pclk", "top_cfg_aclk", PERI3_SYSREG, 0, 20),
+	GATE(PERI3_GPIO4_DBCLK_EN, "peri3_clkgen_gpio4_dbclk", "aon_rtc_clk", PERI3_SYSREG, 0, 19),
+	GATE(CLKCTRL_PERI3_TEE_H2H_SHCLKEN, "peri3_clkgen_tee_h2h_shclk", "top_cfg_aclk",
+	     PERI3_SYSREG, 0, 18),
+	GATE(CLKCTRL_PERI3_TEE_H2H_MHCLKEN, "peri3_clkgen_tee_h2h_mhclk", "top_cfg_aclk",
+	     PERI3_SYSREG, 0, 17),
+	GATE(PERI3_TEE_X2X_ACLK_S_EN, "peri3_clkgen_tee_x2x_aclk", "top_cfg_aclk", PERI3_SYSREG, 0,
+	     16),
+	GATE(PERI3_ADC_PCLK_EN, "peri3_clkgen_adc_pclk", "top_cfg_aclk", PERI3_SYSREG, 0, 15),
+	GATE(AXI_PERI3_MST_PCLK_EN, "peri3_clkgen_axi_mst_pclk", "top_cfg_aclk", PERI3_SYSREG, 0,
+	     14),
+	GATE(AXI_PERI3_MST_ACLK_EN, "peri3_clkgen_axi_mst_aclk", "peri3_mst_aclk", PERI3_SYSREG, 0,
+	     13),
+	GATE(PERI3_SDIO_X2X_ACLK_S_EN, "peri3_clkgen_sdio_x2x_aclk_s", "peri3_mst_aclk",
+	     PERI3_SYSREG, 0, 12),
+	GATE(PERI3_SDIO_X2X_ACLK_M_EN, "peri3_clkgen_sdio_x2x_aclk_m", "top_cfg_aclk", PERI3_SYSREG,
+	     0, 11),
+	GATE(PERI3_SDIO_OSC_CLK_EN, "peri3_clkgen_sdio_osc_clk", "aon_osc_clk_logic", PERI3_SYSREG,
+	     0, 10),
+	GATE(PERI3_SDIO_HCLK_EN, "peri3_clkgen_sdio_hclk", "top_cfg_aclk", PERI3_SYSREG, 0, 9),
+	GATE(PERI3_SDIO_ACLK_EN, "peri3_clkgen_sdio_aclk", "top_cfg_aclk", PERI3_SYSREG, 0, 8),
+	GATE(PERI3_EMMC_X2X_ACLK_S_EN, "peri3_clkgen_emmc_x2x_aclk_s", "peri3_mst_aclk",
+	     PERI3_SYSREG, 0, 7),
+	GATE(PERI3_EMMC_X2X_ACLK_M_EN, "peri3_clkgen_emmc_x2x_aclk_m", "top_cfg_aclk", PERI3_SYSREG,
+	     0, 6),
+	GATE(PERI3_EMMC_OSC_CLK_EN, "peri3_clkgen_emmc_osc_clk", "aon_osc_clk_logic", PERI3_SYSREG,
+	     0, 5),
+	GATE(PERI3_EMMC_HCLK_EN, "peri3_clkgen_emmc_hclk", "top_cfg_aclk", PERI3_SYSREG, 0, 4),
+	GATE(PERI3_EMMC_ACLK_EN, "peri3_clkgen_emmc_aclk", "top_cfg_aclk", PERI3_SYSREG, 0, 3),
+	FIXED_FACTOR(PERI3_EMMC_SDIO_REF_CLK, "peri3_emmc_sdio_ref_clk", "emmc_ref_clk", 1, 4),
+	GATE(PERI3_EMMC_SDIO_REF_CLK_CG_EN, "peri3_clkgen_sdio_ref_clk", "peri3_emmc_sdio_ref_clk",
+	     PERI3_SYSREG, 0, 2),
+	GATE(PERI3_DMAC_HCLK_EN, "peri3_clkgen_dmac_hclk", "top_cfg_aclk", PERI3_SYSREG, 0, 1),
+	GATE(PERI3_DMAC_ACLK_EN, "peri3_clkgen_dmac_aclk", "peri3_mst_aclk", PERI3_SYSREG, 0, 0),
+	/* TEE SS */
+	GATE(TEE_AHB2_TEESYS_CLKEN, "tee_ahb2_teesys_clk", "tee_clk", TEE_CRG, 0, 19),
+	GATE(TEE_APB3_TEESYS_CLKEN, "tee_apb3_teesys_clk", "tee_clk", TEE_CRG, 0, 18),
+	GATE(TEE_AXI4_TEESYS_CLKEN, "tee_axi4_teesys_clk", "tee_clk", TEE_CRG, 0, 17),
+	GATE(TEE_X2P_TEESYS_CLKEN, "tee_x2p_teesys_clk", "tee_clk", TEE_CRG, 0, 16),
+	GATE(TEE_EIP120SI_CLKEN, "tee_eip120si_clk", "tee_clk", TEE_CRG, 0, 12),
+	GATE(TEE_EIP120SII_CLKEN, "tee_eip120sii_clk", "tee_clk", TEE_CRG, 0, 11),
+	GATE(TEE_EIP120SIII_CLKEN, "tee_eip120siii_clk", "tee_clk", TEE_CRG, 0, 10),
+	GATE(TEE_EIP150B_CLKEN, "tee_eip150b_clk", "tee_clk", TEE_CRG, 0, 9),
+	GATE(TEE_DMAC_CLKEN, "tee_dmac_clk", "tee_clk", TEE_CRG, 0, 8),
+	FIXED_FACTOR(TEE_PCLK_CDE_RATIO, "tee_pclk", "tee_clk", 1, 4),
+	GATE(TEE_DS_CLKEN, "tee_ds_clk", "tee_pclk", TEE_CRG, 0, 3),
+	GATE(TEE_OCRAM_CLKEN, "tee_ocram_clk", "tee_clk", TEE_CRG, 0, 2),
+	GATE(TEE_EFUSE_CLKEN, "tee_efuse_clk", "tee_pclk", TEE_CRG, 0, 1),
+	GATE(TEE_KEYRAM_CLKEN, "tee_keyram_clk", "tee_pclk", TEE_CRG, 0, 0),
+};
+
+static const struct a210_ccu top_clk = CLK_SUBSYS("top clk", regs_top, info_top);
+static const struct a210_ccu gpu_clk = CLK_SUBSYS("gpu clk", regs_gpu, info_gpu);
+static const struct a210_ccu pcie_clk = CLK_SUBSYS("pcie clk", regs_pcie, info_pcie);
+static const struct a210_ccu usb_clk = CLK_SUBSYS("usb clk", regs_usb, info_usb);
+static const struct a210_ccu vi_clk = CLK_SUBSYS("vi clk", regs_vi, info_vi);
+static const struct a210_ccu vp_clk = CLK_SUBSYS("vp clk", regs_vp, info_vp);
+static const struct a210_ccu vo_clk = CLK_SUBSYS("vo clk", regs_vo, info_vo);
+static const struct a210_ccu npu_clk = CLK_SUBSYS("npu clk", regs_npu, info_npu);
+static const struct a210_ccu peri_clk = CLK_SUBSYS("peri clk", regs_peri, info_peri);
+
+static int a210_clocks_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct clk_hw_onecell_data *clk_data;
+	const struct a210_ccu *data;
+	struct a210_ccu *priv;
+	int i, ret;
+
+	ret = devm_pm_runtime_enable(dev);
+	if (ret)
+		return ret;
+
+	clk_data = devm_kzalloc(dev, struct_size(clk_data, hws, CLK_END), GFP_KERNEL);
+	if (!clk_data)
+		return -ENOMEM;
+
+	clk_data->num = CLK_END;
+	for (i = 0; i < CLK_END; i++)
+		clk_data->hws[i] = ERR_PTR(-ENOENT);
+
+	data = device_get_match_data(dev);
+	if (!data)
+		return -EINVAL;
+
+	priv = devm_kmemdup(dev, data, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+	priv->regs =
+		devm_kmemdup(dev, data->regs, sizeof(*data->regs) * data->num_regs, GFP_KERNEL);
+	if (!priv->regs)
+		return -ENOMEM;
+	priv->num_inputs = devm_clk_bulk_get_all(dev, &priv->inputs);
+	if (priv->num_inputs < 0)
+		return dev_err_probe(dev, priv->num_inputs, "failed to get input clocks\n");
+
+	priv->clk_data = clk_data;
+	dev_set_drvdata(dev, priv);
+
+	ret = a210_map_registers(pdev);
+	if (ret)
+		return dev_err_probe(dev, ret, "failed to parse register base\n");
+
+	ret = a210_register_clocks(pdev);
+	if (ret)
+		return ret;
+
+	return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, clk_data);
+}
+
+static const struct of_device_id a210_clk_of_match[] = {
+	{ .compatible = "zhihe,a210-clk", .data = &top_clk },
+	{ .compatible = "zhihe,a210-gpu-clk", .data = &gpu_clk },
+	{ .compatible = "zhihe,a210-pcie-clk", .data = &pcie_clk },
+	{ .compatible = "zhihe,a210-usb-clk", .data = &usb_clk },
+	{ .compatible = "zhihe,a210-vi-clk", .data = &vi_clk },
+	{ .compatible = "zhihe,a210-vp-clk", .data = &vp_clk },
+	{ .compatible = "zhihe,a210-vo-clk", .data = &vo_clk },
+	{ .compatible = "zhihe,a210-npu-clk", .data = &npu_clk },
+	{ .compatible = "zhihe,a210-peri-clk", .data = &peri_clk },
+	{ /* Sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, a210_clk_of_match);
+
+static struct platform_driver a210_clk_driver = {
+	.probe = a210_clocks_probe,
+	.driver = {
+		.name = "a210-clk",
+		.of_match_table = a210_clk_of_match,
+	},
+};
+
+module_platform_driver(a210_clk_driver);
+
+MODULE_AUTHOR("dong.yan <yand@zhihecomputing.com>");
+MODULE_DESCRIPTION("Zhihe A210 clock driver");
+MODULE_LICENSE("GPL");

-- 
2.55.0



^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 06/18] dt-bindings: reset: add Zhihe A210 reset controllers
  2026-10-21 19:53 [PATCH 00/18] riscv: add initial support for Zhihe A210 and Melon Pi Han Gao via B4 Relay
                   ` (4 preceding siblings ...)
  2026-10-21 19:53 ` [PATCH 05/18] clk: zhihe: add A210 support Han Gao via B4 Relay
@ 2026-10-21 19:53 ` Han Gao via B4 Relay
  2026-10-21 19:53 ` [PATCH 07/18] reset: zhihe: add A210 support Han Gao via B4 Relay
                   ` (11 subsequent siblings)
  17 siblings, 0 replies; 22+ messages in thread
From: Han Gao via B4 Relay @ 2026-10-21 19:53 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Zhiguo Zhu,
	Stephen Boyd, Brian Masney, Jerome Brunet, Philipp Zabel,
	Linus Walleij, Bartosz Golaszewski, Thomas Gleixner, Radu Rendec,
	Samuel Holland, Daniel Lezcano, Anup Patel, Icenowy Zheng,
	Drew Fustini
  Cc: devicetree, linux-kernel, linux-riscv, linux-clk, linux-gpio,
	Paul Walmsley, Han Gao

From: Zhiguo Zhu <zhiguo.zhu@linux.alibaba.com>

Add bindings for the A210 reset controllers and their reset IDs.

Signed-off-by: Zhiguo Zhu <zhiguo.zhu@linux.alibaba.com>
Signed-off-by: Han Gao <gaohan@iscas.ac.cn>
---
 .../bindings/reset/zhihe,a210-reset.yaml           |  56 ++++
 include/dt-bindings/reset/zhihe,a210-resets.h      | 351 +++++++++++++++++++++
 2 files changed, 407 insertions(+)

diff --git a/Documentation/devicetree/bindings/reset/zhihe,a210-reset.yaml b/Documentation/devicetree/bindings/reset/zhihe,a210-reset.yaml
new file mode 100644
index 000000000000..708cb49444eb
--- /dev/null
+++ b/Documentation/devicetree/bindings/reset/zhihe,a210-reset.yaml
@@ -0,0 +1,56 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/reset/zhihe,a210-reset.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Zhihe A210 Reset Controller
+
+maintainers:
+  - Zhiguo Zhu <zhiguo.zhu@linux.alibaba.com>
+
+description:
+  Reset controllers for the Zhihe A210 SoC. Each subsystem exposes a
+  separate reset controller register block and has its own compatible.
+
+properties:
+  compatible:
+    enum:
+      - zhihe,a210-vp-reset
+      - zhihe,a210-vi-reset
+      - zhihe,a210-npu-reset
+      - zhihe,a210-vo-reset
+      - zhihe,a210-peri0-reset
+      - zhihe,a210-peri1-reset
+      - zhihe,a210-peri2-reset
+      - zhihe,a210-peri3-reset
+      - zhihe,a210-pcie-reset
+      - zhihe,a210-usb-reset
+      - zhihe,a210-tee-reset
+      - zhihe,a210-gpu-reset
+
+  reg:
+    maxItems: 1
+
+  "#reset-cells":
+    const: 1
+    description:
+      The single cell is the reset ID defined in
+      include/dt-bindings/reset/zhihe,a210-resets.h.
+
+required:
+  - compatible
+  - reg
+  - "#reset-cells"
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/reset/zhihe,a210-resets.h>
+
+    reset-controller@6b20400 {
+        compatible = "zhihe,a210-vp-reset";
+        reg = <0x06b20400 0x200>;
+        #reset-cells = <1>;
+    };
diff --git a/include/dt-bindings/reset/zhihe,a210-resets.h b/include/dt-bindings/reset/zhihe,a210-resets.h
new file mode 100644
index 000000000000..2845c0e9e5ed
--- /dev/null
+++ b/include/dt-bindings/reset/zhihe,a210-resets.h
@@ -0,0 +1,351 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+/*
+ * Copyright (C) 2025 Zhihe Computing Limited.
+ */
+
+#ifndef _DT_BINDINGS_RESET_ZHIHE_A210_RESETS_H
+#define _DT_BINDINGS_RESET_ZHIHE_A210_RESETS_H
+
+#define VP_VDEC_PRST		0
+#define VP_VDEC_CRST		1
+#define VP_VDEC_ARST		2
+#define VP_VENC_PRST		3
+#define VP_VENC_CRST		4
+#define VP_VENC_ARST		5
+#define VP_G2D_PRST		6
+#define VP_G2D_CRST		7
+#define VP_G2D_ARST		8
+#define VP_COMP_PRST		9
+#define VP_COMP_CRST		10
+#define VP_COMP_ARST		11
+#define VP_DECOMP_PRST		12
+#define VP_DECOMP_CRST		13
+#define VP_DECOMP_ARST		14
+#define VP_DFMU_PRST		15
+#define VP_DFMU_ARST		16
+#define VP_ARB_PRST		17
+#define VP_ARB_ARST		18
+#define VP_VDEC_RS_ARST		19
+#define VP_VENC_RS_ARST		20
+#define VP_COMP_EXTPRST		21
+#define VP_DECOMP_EXTPRST	22
+
+#define VI_MIPI0_CSI0_PRST	0
+#define VI_MIPI0_CSI1_PRST	1
+#define VI_MIPI0_FIFO_RST	2
+#define VI_MIPI1_CSI0_PRST	3
+#define VI_MIPI1_CSI1_PRST	4
+#define VI_MIPI1_FIFO_RST	5
+#define VI_VIPRE_PRST		6
+#define VI_VIPRE_I0_PIX_RST	7
+#define VI_VIPRE_I1_PIX_RST	8
+#define VI_VIPRE_ISPIF_RST	9
+#define VI_VIPRE_ARST		10
+#define VI_ISP_RST		11
+#define VI_COMP_PRST		12
+#define VI_COMP_ARST		13
+#define VI_COMP_ISPOUT_RST	14
+#define VI_COMP_DECOUT_RST	15
+#define VI_COMP_VSEOUT_RST	16
+#define VI_COMP0_RST		17
+#define VI_COMP1_RST		18
+#define VI_DECOMP_RST		19
+#define VI_DW200_RST		20
+#define VI_DFMU_PRST		21
+#define VI_DFMU_ARST		22
+#define VI_ARB_PRST		23
+#define VI_ARB_ARST		24
+#define VI_X2H0_HRST		25
+#define VI_X2H1_HRST		26
+#define VI_X2H2_HRST		27
+#define VI_REC_PRST		28
+#define VI_REC_ARST		29
+
+#define NPU_AAB_MST_RST		0
+#define NPU_AFENCE_RST		1
+#define NPU_AXI_CCU_PRST	2
+#define NPU_AXI_CCU_RST		3
+#define NPU_AXI_M2S1_RST	4
+#define NPU_AXI_RST		5
+#define NPU_CLK_CALC_RST	6
+#define NPU_DFMU_ARST		7
+#define NPU_DFMU_PRST		8
+#define NPU_LPC_C_RST		9
+#define NPU_LPE_C_PRST		10
+#define NPU_LPE_C_RST		11
+#define NPU_ARST		12
+#define NPU_CRST		13
+#define NPU_HRST		14
+#define NPU_PCTRL_PB_RST	15
+#define NPU_PCTRL_PRST		16
+#define NPU_PCTRL_RST		17
+#define NPU_PTW_CCU_PRST	18
+#define NPU_PTW_CCU_RST		19
+#define NPU_SEMA_ARST		20
+#define NPU_SEMA_PRST		21
+#define NPU_DROOP_CCTRL_PRST	22
+#define NPU_DROOP_CCTRL_RST	23
+#define NPU_X2H_RST		24
+#define NPU_X2P_RST		25
+#define NPU_LDIP_RST		26
+#define NPU_SRAM_RST		27
+
+#define VO_X2H0_RST		0
+#define VO_X2H1_RST		1
+#define VO_DPU_HRST		2
+#define VO_DPU_CRST		3
+#define VO_DPU_ARST		4
+#define VO_AUXDISP_PRST		5
+#define VO_AUXDISP_PIX_RST	6
+#define VO_AUXDISP_ARST		7
+#define VO_HDMI_PRST		8
+#define VO_HDMI_MAIN_RST	9
+#define VO_MIPI_PRST		10
+#define VO_DECOMP_PRST		11
+#define VO_DECOMP0_CRST		12
+#define VO_DECOMP1_CRST		13
+#define VO_DECOMP_ARST		14
+#define VO_ARB_PRST		15
+#define VO_ARB_ARST		16
+#define VO_DFMU_PRST		17
+#define VO_DFMU_ARST		18
+
+#define PERI0_TIMER0_CRST	0
+#define PERI0_TIMER0_PRST	1
+#define PERI0_TIMER1_CRST	2
+#define PERI0_TIMER1_PRST	3
+#define PERI0_WDT0_PRST		4
+#define PERI0_MBOX0_PRST	5
+#define PERI0_MBOX1_PRST	6
+#define PERI0_TIMER0_RST	7
+#define PERI0_TIMER1_RST	8
+
+#define PERI1_GMAC0_ARST	0
+#define PERI1_GMAC0_HRST	1
+#define PERI1_GMAC1_ARST	2
+#define PERI1_GMAC1_HRST	3
+#define PERI1_GPIO0_DBRST	4
+#define PERI1_GPIO0_PRST	5
+#define PERI1_GPIO1_DBRST	6
+#define PERI1_GPIO1_PRST	7
+#define PERI1_I2C0_IC_RST	8
+#define PERI1_I2C0_PRST		9
+#define PERI1_I2C1_IC_RST	10
+#define PERI1_I2C1_PRST		11
+#define PERI1_I2C2_IC_RST	12
+#define PERI1_I2C2_PRST		13
+#define PERI1_I2S0_PRST		14
+#define PERI1_MST_BUS_ARST	15
+#define PERI1_MST_BUS_PRST	16
+#define PERI1_PWM0_CRST		17
+#define PERI1_PWM0_PRST		18
+#define PERI1_QSPI0_PRST	19
+#define PERI1_QSPI0_SSI_RST	20
+#define PERI1_SPI0_PRST		21
+#define PERI1_SPI0_SSI_RST	22
+#define PERI1_UART0_PRST	23
+#define PERI1_UART0_S_RST	24
+#define PERI1_UART1_PRST	25
+#define PERI1_UART1_S_RST	26
+#define PERI1_UART2_PRST	27
+#define PERI1_UART2_S_RST	28
+#define PERI1_UART3_PRST	29
+#define PERI1_UART3_S_RST	30
+#define PERI1_X2H_GMAC0_ARST	31
+#define PERI1_X2H_GMAC0_HRST	32
+#define PERI1_X2H_GMAC1_ARST	33
+#define PERI1_X2H_GMAC1_HRST	34
+#define PERI1_DFMU_ARESET	35
+#define PERI1_DFMU_PRESET	36
+#define PERI1_PAD_CTRL_PRST	37
+#define PERI1_PDM0_MRST		38
+#define PERI1_PDM0_PRST		39
+#define PERI1_TDM0_RST		40
+#define PERI1_CAN0_IPG_PE_RST	41
+#define PERI1_CAN0_IPG_RST	42
+#define PERI1_CAN0_IPG_SOFT_RST	43
+#define PERI1_CAN0_IPG_TS_RST	44
+#define PERI1_CAN0_PRST		45
+#define PERI1_CAN1_IPG_PE_RST	46
+#define PERI1_CAN1_IPG_RST	47
+#define PERI1_CAN1_IPG_SOFT_RST	48
+#define PERI1_CAN1_IPG_TS_RST	49
+#define PERI1_CAN1_PRST		50
+#define PERI1_CHIP_DBG_ARST	51
+#define PERI1_CHIP_DBG_CRST	52
+#define PERI1_CHIP_DBG_PRST	53
+#define PERI1_GMAC_CRST		54
+#define PERI1_X2H_GMAC2_ARST	55
+#define PERI1_X2H_GMAC2_HRST	56
+#define PERI1_ZGMAC_X2X_ARST	57
+#define PERI1_SPI0_RST		58
+#define PERI1_I2C0_RST		59
+#define PERI1_I2C1_RST		60
+#define PERI1_I2C2_RST		61
+#define PERI1_GMAC0_RST		62
+#define PERI1_GMAC0_X2H_RST	63
+#define PERI1_GMAC1_RST		64
+#define PERI1_GMAC1_X2H_RST	65
+
+#define PERI2_CAN2_IPG_PE_RST	0
+#define PERI2_CAN2_IPG_RST	1
+#define PERI2_CAN2_IPG_SOFT_RST	2
+#define PERI2_CAN2_IPG_TS_RST	3
+#define PERI2_CAN2_PRST		4
+#define PERI2_GPIO2_DBRST	5
+#define PERI2_GPIO2_PRST	6
+#define PERI2_I2C4_IC_RST	7
+#define PERI2_I2C4_PRST		8
+#define PERI2_I2S2_PRST		9
+#define PERI2_SPI1_PRST		10
+#define PERI2_SPI1_SSI_RST	11
+#define PERI2_UART4_PRST	12
+#define PERI2_UART4_S_RST	13
+#define PERI2_UART5_PRST	14
+#define PERI2_UART5_S_RST	15
+#define PERI2_UART6_PRST	16
+#define PERI2_UART6_S_RST	17
+#define PERI2_PAD_CTRL_PRST	18
+#define PERI2_GPIO3_DBRST	19
+#define PERI2_GPIO3_PRST	20
+#define PERI2_I2C3_IC_RST	21
+#define PERI2_I2C3_PRST		22
+#define PERI2_I2C5_IC_RST	23
+#define PERI2_I2C5_PRST		24
+#define PERI2_I2C6_IC_RST	25
+#define PERI2_I2C6_PRST		26
+#define PERI2_I2C7_IC_RST	27
+#define PERI2_I2C7_PRST		28
+#define PERI2_I2S1_PRST		29
+#define PERI2_I2S3_PRST		30
+#define PERI2_UART7_PRST	31
+#define PERI2_UART7_S_RST	32
+#define PERI2_UART8_PRST	33
+#define PERI2_UART8_S_RST	34
+#define PERI2_UART9_PRST	35
+#define PERI2_UART9_S_RST	36
+#define PERI2_QSPI1_PRST	37
+#define PERI2_QSPI1_SSI_RST	38
+#define PERI2_PWM1_CRST		39
+#define PERI2_PWM1_PRST		40
+#define PERI2_PWM2_CRST		41
+#define PERI2_PWM2_PRST		42
+#define PERI2_I2C3_RST		43
+#define PERI2_I2C4_RST		44
+#define PERI2_I2C5_RST		45
+#define PERI2_I2C6_RST		46
+#define PERI2_I2C7_RST		47
+#define PERI2_SPI1_RST		48
+
+#define PERI3_DMAC_ARST				0
+#define PERI3_DMAC_HRST				1
+#define PERI3_EMMC_SDIO_CLKGEN_RST		2
+#define PERI3_EMMC_RST				3
+#define PERI3_EMMC_X2X_ARST_M			4
+#define PERI3_EMMC_X2X_ARST_S			5
+#define PERI3_SDIO_RST				6
+#define PERI3_SDIO_X2X_ARST_M			7
+#define PERI3_SDIO_X2X_ARST_S			8
+#define PERI3_AXI_MST_ARST			9
+#define PERI3_AXI_MST_PRST			10
+#define PERI3_ADC_PRST				11
+#define PERI3_TEE_X2X_ARST_M			12
+#define PERI3_TEE_X2X_ARST_S			13
+#define PERI3_TEE_H2H_HRST			14
+#define PERI3_GPIO4_DBRST			15
+#define PERI3_GPIO4_PRST			16
+#define PERI3_PAD_CTRL_PRST			17
+
+/* pcie common */
+#define PCIE_X2X_PERI_SLV_ARST			0
+#define PCIE_X2X_PERI_MST_ARST			1
+#define PCIE_AXI4_PCIE_MST_ARST			2
+#define PCIE_AXI4_PCIE_MST_PRST			3
+#define PCIE_DFMU_PRST				4
+#define PCIE_DFMU_ARST				5
+#define PCIE_E16PHY_PHY_RST			6
+#define PCIE_E16PHY_APBS_PRST			7
+#define PCIE_X2X_SATA_MST_ARST			8
+#define PCIE_X2X_SATA_SLV_ARST			9
+
+/* sata */
+#define PCIE_SATA_ARESET			10
+#define PCIE_SATA_RST_PMALIVE			11
+#define PCIE_SATA_SLV_AFENCE_ARST		12
+#define PCIE_SATA_MST_AFENCE_ARST		13
+#define PCIE_SATA_RST_ASIC0			14
+#define PCIE_SATA_RST_ASIC1			15
+#define PCIE_SATA_RST_RXOOB0			16
+#define PCIE_SATA_RST_RXOOB1			17
+
+/* pcie0 */
+#define PCIE_DM_GEN3X4_APBS_PRST		18
+#define PCIE_DM_GEN3X4_POWER_UP_RST		19
+#define PCIE_DM_SLV_AFENCE_ARST			20
+#define PCIE_DM_MST_AFENCE_ARST			21
+
+/* pcie1 */
+#define PCIE_RP_GEN3X1_APBS_PRST		22
+#define PCIE_RP_GEN3X1_POWER_UP_RST		23
+#define PCIE_RP_SLV_AFENCE_ARST			24
+#define PCIE_RP_MST_AFENCE_ARST			25
+
+#define USB_DFMU_PRST				0
+#define USB_DFMU_ARST				1
+#define USB_AXI4_MST_ARST			2
+#define USB_AXI4_MST_PRST			3
+#define USB_DPTX_APBS_PRST			4
+#define USB_DPTX_VCC_RST			5
+#define USB_USB31_APBS_PRST			6
+#define USB_USB31_VCC_RST			7
+#define USB_USB31_PHY_RST			8
+#define USB_USB31_SLV_AFENCE_ARST		9
+#define USB_C10PHY_PHY_RST			10
+#define USB_C10PHY_APBS_PRST			11
+#define USB_USB20_BLK_X2H_HRST			12
+#define USB_USB20_BLK_X2H_ARST			13
+#define USB_USB20_SLV_AFENCE_ARST		14
+#define USB_USB20_BLK_H2P_HRST			15
+#define USB_USB20_BLK_AHB_SLV_HRST		16
+#define USB_USB20_BLK_AXI_MST_ARST		17
+#define USB_USB20_BLK_USB2_SYSREG_PRST		18
+#define USB_USB20_BLK_USB2_WRAP0_PRST		19
+#define USB_USB20_BLK_USB2_WRAP0_HRST		20
+#define USB_USB20_BLK_USB2_WRAP1_PRST		21
+#define USB_USB20_BLK_USB2_WRAP1_HRST		22
+#define USB_USB20_BLK_A2X0_HRST			23
+#define USB_USB20_BLK_A2X0_ARST			24
+#define USB_USB20_BLK_A2X1_HRST			25
+#define USB_USB20_BLK_A2X1_ARST			26
+#define USB_USB20_BLK_USB0_PHY_PON_RESET	27
+#define USB_USB20_BLK_USB1_PHY_PON_RESET	28
+#define USB_PERI2_SS_RST			29
+#define USB_PERI2_SLV_AFENCE_ARST		30
+
+#define TEE_KEYRAM_PRST				0
+#define TEE_DS_PRST				1
+#define TEE_EFUSE_PRST				2
+#define TEE_OCRAM_HRST				3
+#define TEE_SYSREG_PRST				4
+#define TEE_CCU_PRST				5
+#define TEE_CCU_CRST				6
+#define TEE_EIP150B_HRST			7
+#define TEE_EIP120SIII_HRST			8
+#define TEE_EIP120SIII_ARST			9
+#define TEE_EIP120SII_HRST			10
+#define TEE_EIP120SII_ARST			11
+#define TEE_EIP120SI_HRST			12
+#define TEE_EIP120SI_ARST			13
+#define TEE_DMAC_HRST				14
+#define TEE_DMAC_ARST				15
+#define TEE_X2P_TEESYS_PRST			16
+#define TEE_X2P_TEESYS_ARST			17
+#define TEE_AXI4_TEESYS_ARST			18
+#define TEE_APB3_TEESYS_PRST			19
+#define TEE_APB3_TEESYS_HRST			20
+#define TEE_AHB2_TEESYS_HRST			21
+
+#define GPU_PWR_WRAP_RGX_HOOD_RST		0
+#define GPU_PWR_WRAP_DFMU_RST			1
+
+#endif

-- 
2.55.0



^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 07/18] reset: zhihe: add A210 support
  2026-10-21 19:53 [PATCH 00/18] riscv: add initial support for Zhihe A210 and Melon Pi Han Gao via B4 Relay
                   ` (5 preceding siblings ...)
  2026-10-21 19:53 ` [PATCH 06/18] dt-bindings: reset: add Zhihe A210 reset controllers Han Gao via B4 Relay
@ 2026-10-21 19:53 ` Han Gao via B4 Relay
  2026-10-22  9:22   ` Philipp Zabel
  2026-10-21 19:53 ` [PATCH 08/18] dt-bindings: pinctrl: add Zhihe A210 pin controller Han Gao via B4 Relay
                   ` (10 subsequent siblings)
  17 siblings, 1 reply; 22+ messages in thread
From: Han Gao via B4 Relay @ 2026-10-21 19:53 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Zhiguo Zhu,
	Stephen Boyd, Brian Masney, Jerome Brunet, Philipp Zabel,
	Linus Walleij, Bartosz Golaszewski, Thomas Gleixner, Radu Rendec,
	Samuel Holland, Daniel Lezcano, Anup Patel, Icenowy Zheng,
	Drew Fustini
  Cc: devicetree, linux-kernel, linux-riscv, linux-clk, linux-gpio,
	Paul Walmsley, Han Gao

From: Zhiguo Zhu <zhiguo.zhu@linux.alibaba.com>

Add support for A210 reset banks and linked reset signals. Check
register readback to detect rejected writes.

Signed-off-by: Zhiguo Zhu <zhiguo.zhu@linux.alibaba.com>
Co-developed-by: Han Gao <gaohan@iscas.ac.cn>
Signed-off-by: Han Gao <gaohan@iscas.ac.cn>
---
 drivers/reset/Kconfig      |  11 +
 drivers/reset/Makefile     |   1 +
 drivers/reset/reset-a210.c | 589 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 601 insertions(+)

diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index 3168ab1eea88..039e8a4046dc 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -428,6 +428,17 @@ config RESET_UNIPHIER_GLUE
 	  on UniPhier SoCs. Say Y if you want to control reset signals
 	  provided by the glue layer.
 
+config RESET_ZHIHE_A210
+	tristate "ZhiHe A210 reset controller"
+	depends on OF && (ARCH_ZHIHE || COMPILE_TEST)
+	default ARCH_ZHIHE
+	help
+	  Build the reset controller driver for the ZhiHe A210 SoC.
+
+	  This driver provides reset control for the various hardware
+	  blocks in the A210 SoC. Say Y if you are building a kernel
+	  for the ZhiHe A210 platform.
+
 config RESET_ZYNQ
 	bool "ZYNQ Reset Driver" if COMPILE_TEST
 	default ARCH_ZYNQ
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index 45ad17062462..3620e94e4539 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -52,5 +52,6 @@ obj-$(CONFIG_RESET_TI_TPS380X) += reset-tps380x.o
 obj-$(CONFIG_RESET_TN48M_CPLD) += reset-tn48m.o
 obj-$(CONFIG_RESET_UNIPHIER) += reset-uniphier.o
 obj-$(CONFIG_RESET_UNIPHIER_GLUE) += reset-uniphier-glue.o
+obj-$(CONFIG_RESET_ZHIHE_A210) += reset-a210.o
 obj-$(CONFIG_RESET_ZYNQ) += reset-zynq.o
 obj-$(CONFIG_RESET_ZYNQMP) += reset-zynqmp.o
diff --git a/drivers/reset/reset-a210.c b/drivers/reset/reset-a210.c
new file mode 100644
index 000000000000..38bad400d6b8
--- /dev/null
+++ b/drivers/reset/reset-a210.c
@@ -0,0 +1,589 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2025 Zhihe Computing Limited.
+ */
+
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/property.h>
+#include <linux/reset-controller.h>
+#include <linux/spinlock.h>
+
+#include <dt-bindings/reset/zhihe,a210-resets.h>
+
+struct a210_rst_signal {
+	u16 offset;
+	u32 mask;
+	/* Zero terminates a chain of signals that share one reset ID. */
+	u16 nextid;
+};
+
+struct a210_reset_data {
+	const struct a210_rst_signal *signals;
+	unsigned int num_signals;
+};
+
+struct a210_reset {
+	struct reset_controller_dev rcdev;
+	void __iomem *base;
+	const struct a210_reset_data *data;
+	/* Protects register updates and snapshots of linked reset signals. */
+	spinlock_t lock;
+};
+
+static const struct a210_rst_signal vp_rst_signals[] = {
+	[VP_VDEC_PRST] = { 0, BIT(0), 0 },
+	[VP_VDEC_CRST] = { 0, BIT(1), 0 },
+	[VP_VDEC_ARST] = { 0, BIT(2), 0 },
+	[VP_VENC_PRST] = { 0, BIT(3), 0 },
+	[VP_VENC_CRST] = { 0, BIT(4), 0 },
+	[VP_VENC_ARST] = { 0, BIT(5), 0 },
+	[VP_G2D_PRST] = { 0, BIT(6), 0 },
+	[VP_G2D_CRST] = { 0, BIT(7), 0 },
+	[VP_G2D_ARST] = { 0, BIT(8), 0 },
+	[VP_COMP_PRST] = { 0, BIT(9), 0 },
+	[VP_COMP_CRST] = { 0, BIT(10), 0 },
+	[VP_COMP_ARST] = { 0, BIT(11), 0 },
+	[VP_DECOMP_PRST] = { 0, BIT(12), 0 },
+	[VP_DECOMP_CRST] = { 0, BIT(13), 0 },
+	[VP_DECOMP_ARST] = { 0, BIT(14), 0 },
+	[VP_DFMU_PRST] = { 0, BIT(15), 0 },
+	[VP_DFMU_ARST] = { 0, BIT(16), 0 },
+	[VP_ARB_PRST] = { 0, BIT(18), 0 },
+	[VP_ARB_ARST] = { 0, BIT(19), 0 },
+	[VP_VDEC_RS_ARST] = { 0, BIT(20), 0 },
+	[VP_VENC_RS_ARST] = { 0, BIT(21), 0 },
+	[VP_COMP_EXTPRST] = { 0, BIT(22), 0 },
+	[VP_DECOMP_EXTPRST] = { 0, BIT(23), 0 },
+};
+
+static const struct a210_rst_signal vi_rst_signals[] = {
+	[VI_MIPI0_CSI0_PRST] = { 0, BIT(0), 0 },
+	[VI_MIPI0_CSI1_PRST] = { 0, BIT(1), 0 },
+	[VI_MIPI0_FIFO_RST] = { 0, BIT(2), 0 },
+	[VI_MIPI1_CSI0_PRST] = { 0, BIT(3), 0 },
+	[VI_MIPI1_CSI1_PRST] = { 0, BIT(4), 0 },
+	[VI_MIPI1_FIFO_RST] = { 0, BIT(5), 0 },
+	[VI_VIPRE_PRST] = { 0, BIT(6), 0 },
+	[VI_VIPRE_I0_PIX_RST] = { 0, BIT(7), 0 },
+	[VI_VIPRE_I1_PIX_RST] = { 0, BIT(8), 0 },
+	[VI_VIPRE_ISPIF_RST] = { 0, BIT(9), 0 },
+	[VI_VIPRE_ARST] = { 0, BIT(10), 0 },
+	[VI_ISP_RST] = { 0, BIT(11), 0 },
+	[VI_COMP_PRST] = { 0, BIT(12), 0 },
+	[VI_COMP_ARST] = { 0, BIT(13), 0 },
+	[VI_COMP_ISPOUT_RST] = { 0, BIT(14), 0 },
+	[VI_COMP_DECOUT_RST] = { 0, BIT(15), 0 },
+	[VI_COMP_VSEOUT_RST] = { 0, BIT(16), 0 },
+	[VI_COMP0_RST] = { 0, BIT(17), 0 },
+	[VI_COMP1_RST] = { 0, BIT(18), 0 },
+	[VI_DECOMP_RST] = { 0, BIT(19), 0 },
+	[VI_DW200_RST] = { 0, BIT(20), 0 },
+	[VI_DFMU_PRST] = { 0, BIT(21), 0 },
+	[VI_DFMU_ARST] = { 0, BIT(22), 0 },
+	[VI_ARB_PRST] = { 0, BIT(23), 0 },
+	[VI_ARB_ARST] = { 0, BIT(24), 0 },
+	[VI_X2H0_HRST] = { 0, BIT(26), 0 },
+	[VI_X2H1_HRST] = { 0, BIT(27), 0 },
+	[VI_X2H2_HRST] = { 0, BIT(28), 0 },
+	[VI_REC_PRST] = { 0, BIT(29), 0 },
+	[VI_REC_ARST] = { 0, BIT(30), 0 },
+};
+
+static const struct a210_rst_signal npu_rst_signals[] = {
+	[NPU_AAB_MST_RST] = { 0, BIT(0), 0 },
+	[NPU_AFENCE_RST] = { 0, BIT(1), 0 },
+	[NPU_AXI_CCU_PRST] = { 0, BIT(2), 0 },
+	[NPU_AXI_CCU_RST] = { 0, BIT(3), 0 },
+	[NPU_AXI_M2S1_RST] = { 0, BIT(4), 0 },
+	[NPU_AXI_RST] = { 0, BIT(5), 0 },
+	[NPU_CLK_CALC_RST] = { 0, BIT(6), 0 },
+	[NPU_DFMU_ARST] = { 0, BIT(7), 0 },
+	[NPU_DFMU_PRST] = { 0, BIT(8), 0 },
+	[NPU_LPC_C_RST] = { 0, BIT(9), 0 },
+	[NPU_LPE_C_PRST] = { 0, BIT(10), 0 },
+	[NPU_LPE_C_RST] = { 0, BIT(11), 0 },
+	[NPU_ARST] = { 0, BIT(12), 0 },
+	[NPU_CRST] = { 0, BIT(13), 0 },
+	[NPU_HRST] = { 0, BIT(14), 0 },
+	[NPU_PCTRL_PB_RST] = { 0, BIT(15), 0 },
+	[NPU_PCTRL_PRST] = { 0, BIT(16), 0 },
+	[NPU_PCTRL_RST] = { 0, BIT(17), 0 },
+	[NPU_PTW_CCU_PRST] = { 0, BIT(18), 0 },
+	[NPU_PTW_CCU_RST] = { 0, BIT(19), 0 },
+	[NPU_SEMA_ARST] = { 0, BIT(20), 0 },
+	[NPU_SEMA_PRST] = { 0, BIT(21), 0 },
+	[NPU_DROOP_CCTRL_PRST] = { 0, BIT(22), 0 },
+	[NPU_DROOP_CCTRL_RST] = { 0, BIT(23), 0 },
+	[NPU_X2H_RST] = { 0, BIT(24), 0 },
+	[NPU_X2P_RST] = { 0, BIT(25), 0 },
+	[NPU_LDIP_RST] = { 0, BIT(26), 0 },
+	[NPU_SRAM_RST] = { 0, BIT(27), 0 },
+};
+
+static const struct a210_rst_signal vo_rst_signals[] = {
+	[VO_X2H0_RST] = { 0, BIT(0), 0 },
+	[VO_X2H1_RST] = { 0, BIT(1), 0 },
+	[VO_DPU_HRST] = { 0, BIT(2), 0 },
+	[VO_DPU_CRST] = { 0, BIT(3), 0 },
+	[VO_DPU_ARST] = { 0, BIT(4), 0 },
+	[VO_AUXDISP_PRST] = { 0, BIT(5), 0 },
+	[VO_AUXDISP_PIX_RST] = { 0, BIT(6), 0 },
+	[VO_AUXDISP_ARST] = { 0, BIT(7), 0 },
+	[VO_HDMI_PRST] = { 0, BIT(8), 0 },
+	[VO_HDMI_MAIN_RST] = { 0, BIT(9), 0 },
+	[VO_MIPI_PRST] = { 0, BIT(10), 0 },
+	[VO_DECOMP_PRST] = { 0, BIT(11), 0 },
+	[VO_DECOMP0_CRST] = { 0, BIT(12), 0 },
+	[VO_DECOMP1_CRST] = { 0, BIT(13), 0 },
+	[VO_DECOMP_ARST] = { 0, BIT(14), 0 },
+	[VO_ARB_PRST] = { 0, BIT(15), 0 },
+	[VO_ARB_ARST] = { 0, BIT(16), 0 },
+	[VO_DFMU_PRST] = { 0, BIT(17), 0 },
+	[VO_DFMU_ARST] = { 0, BIT(18), 0 },
+};
+
+static const struct a210_rst_signal peri0_rst_signals[] = {
+	[PERI0_TIMER0_CRST] = { 0, BIT(0), 0 },
+	[PERI0_TIMER0_PRST] = { 0, BIT(1), 0 },
+	[PERI0_TIMER1_CRST] = { 0, BIT(2), 0 },
+	[PERI0_TIMER1_PRST] = { 0, BIT(3), 0 },
+	[PERI0_WDT0_PRST] = { 0, BIT(4), 0 },
+	[PERI0_MBOX0_PRST] = { 0, BIT(5), 0 },
+	[PERI0_MBOX1_PRST] = { 0, BIT(6), 0 },
+	[PERI0_TIMER0_RST] = { 0, BIT(0) | BIT(1), 0 },
+	[PERI0_TIMER1_RST] = { 0, BIT(2) | BIT(3), 0 },
+};
+
+static const struct a210_rst_signal peri1_rst_signals[] = {
+	[PERI1_GMAC0_ARST] = { 0, BIT(0), 0 },
+	[PERI1_GMAC0_HRST] = { 0, BIT(1), 0 },
+	[PERI1_GMAC1_ARST] = { 0, BIT(2), 0 },
+	[PERI1_GMAC1_HRST] = { 0, BIT(3), 0 },
+	[PERI1_GPIO0_DBRST] = { 0, BIT(4), 0 },
+	[PERI1_GPIO0_PRST] = { 0, BIT(5), 0 },
+	[PERI1_GPIO1_DBRST] = { 0, BIT(6), 0 },
+	[PERI1_GPIO1_PRST] = { 0, BIT(7), 0 },
+	[PERI1_I2C0_IC_RST] = { 0, BIT(8), 0 },
+	[PERI1_I2C0_PRST] = { 0, BIT(9), 0 },
+	[PERI1_I2C1_IC_RST] = { 0, BIT(10), 0 },
+	[PERI1_I2C1_PRST] = { 0, BIT(11), 0 },
+	[PERI1_I2C2_IC_RST] = { 0, BIT(12), 0 },
+	[PERI1_I2C2_PRST] = { 0, BIT(13), 0 },
+	[PERI1_I2S0_PRST] = { 0, BIT(14), 0 },
+	[PERI1_MST_BUS_ARST] = { 0, BIT(15), 0 },
+	[PERI1_MST_BUS_PRST] = { 0, BIT(16), 0 },
+	[PERI1_PWM0_CRST] = { 0, BIT(17), 0 },
+	[PERI1_PWM0_PRST] = { 0, BIT(18), 0 },
+	[PERI1_QSPI0_PRST] = { 0, BIT(19), 0 },
+	[PERI1_QSPI0_SSI_RST] = { 0, BIT(20), 0 },
+	[PERI1_SPI0_PRST] = { 0, BIT(21), 0 },
+	[PERI1_SPI0_SSI_RST] = { 0, BIT(22), 0 },
+	[PERI1_UART0_PRST] = { 0, BIT(23), PERI1_UART0_S_RST },
+	[PERI1_UART0_S_RST] = { 0, BIT(24), 0 },
+	[PERI1_UART1_PRST] = { 0, BIT(25), PERI1_UART1_S_RST },
+	[PERI1_UART1_S_RST] = { 0, BIT(26), 0 },
+	[PERI1_UART2_PRST] = { 0, BIT(27), PERI1_UART2_S_RST },
+	[PERI1_UART2_S_RST] = { 0, BIT(28), 0 },
+	[PERI1_UART3_PRST] = { 0, BIT(29), PERI1_UART3_S_RST },
+	[PERI1_UART3_S_RST] = { 0, BIT(30), 0 },
+	[PERI1_X2H_GMAC0_ARST] = { 0, BIT(31), 0 },
+	[PERI1_X2H_GMAC0_HRST] = { 0x4, BIT(0), 0 },
+	[PERI1_X2H_GMAC1_ARST] = { 0x4, BIT(1), 0 },
+	[PERI1_X2H_GMAC1_HRST] = { 0x4, BIT(2), 0 },
+	[PERI1_DFMU_ARESET] = { 0x4, BIT(3), 0 },
+	[PERI1_DFMU_PRESET] = { 0x4, BIT(4), 0 },
+	[PERI1_PAD_CTRL_PRST] = { 0x4, BIT(5), 0 },
+	[PERI1_PDM0_MRST] = { 0x4, BIT(6), 0 },
+	[PERI1_PDM0_PRST] = { 0x4, BIT(7), 0 },
+	[PERI1_TDM0_RST] = { 0x4, BIT(8), 0 },
+	[PERI1_CAN0_IPG_PE_RST] = { 0x4, BIT(9), 0 },
+	[PERI1_CAN0_IPG_RST] = { 0x4, BIT(10), 0 },
+	[PERI1_CAN0_IPG_SOFT_RST] = { 0x4, BIT(11), 0 },
+	[PERI1_CAN0_IPG_TS_RST] = { 0x4, BIT(12), 0 },
+	[PERI1_CAN0_PRST] = { 0x4, BIT(13), 0 },
+	[PERI1_CAN1_IPG_PE_RST] = { 0x4, BIT(14), 0 },
+	[PERI1_CAN1_IPG_RST] = { 0x4, BIT(15), 0 },
+	[PERI1_CAN1_IPG_SOFT_RST] = { 0x4, BIT(16), 0 },
+	[PERI1_CAN1_IPG_TS_RST] = { 0x4, BIT(17), 0 },
+	[PERI1_CAN1_PRST] = { 0x4, BIT(18), 0 },
+	[PERI1_CHIP_DBG_ARST] = { 0x4, BIT(19), 0 },
+	[PERI1_CHIP_DBG_CRST] = { 0x4, BIT(20), 0 },
+	[PERI1_CHIP_DBG_PRST] = { 0x4, BIT(21), 0 },
+	[PERI1_GMAC_CRST] = { 0x4, BIT(22), 0 },
+	[PERI1_X2H_GMAC2_ARST] = { 0x4, BIT(23), 0 },
+	[PERI1_X2H_GMAC2_HRST] = { 0x4, BIT(24), 0 },
+	[PERI1_ZGMAC_X2X_ARST] = { 0x4, BIT(25), 0 },
+	[PERI1_SPI0_RST] = { 0, BIT(21) | BIT(22), 0 },
+	[PERI1_I2C0_RST] = { 0, BIT(8) | BIT(9), 0 },
+	[PERI1_I2C1_RST] = { 0, BIT(10) | BIT(11), 0 },
+	[PERI1_I2C2_RST] = { 0, BIT(12) | BIT(13), 0 },
+	[PERI1_GMAC0_RST] = { 0, BIT(0) | BIT(1) | BIT(31), 0 },
+	[PERI1_GMAC0_X2H_RST] = { 0x4, BIT(0), 0 },
+	[PERI1_GMAC1_RST] = { 0, BIT(2) | BIT(3), 0 },
+	[PERI1_GMAC1_X2H_RST] = { 0x4, BIT(1) | BIT(2), 0 },
+};
+
+static const struct a210_rst_signal peri2_rst_signals[] = {
+	[PERI2_CAN2_IPG_PE_RST] = { 0, BIT(0), 0 },
+	[PERI2_CAN2_IPG_RST] = { 0, BIT(1), 0 },
+	[PERI2_CAN2_IPG_SOFT_RST] = { 0, BIT(2), 0 },
+	[PERI2_CAN2_IPG_TS_RST] = { 0, BIT(3), 0 },
+	[PERI2_CAN2_PRST] = { 0, BIT(4), 0 },
+	[PERI2_GPIO2_DBRST] = { 0, BIT(5), 0 },
+	[PERI2_GPIO2_PRST] = { 0, BIT(6), 0 },
+	[PERI2_I2C4_IC_RST] = { 0, BIT(7), 0 },
+	[PERI2_I2C4_PRST] = { 0, BIT(8), 0 },
+	[PERI2_I2S2_PRST] = { 0, BIT(9), 0 },
+	[PERI2_SPI1_PRST] = { 0, BIT(10), 0 },
+	[PERI2_SPI1_SSI_RST] = { 0, BIT(11), 0 },
+	[PERI2_UART4_PRST] = { 0, BIT(12), PERI2_UART4_S_RST },
+	[PERI2_UART4_S_RST] = { 0, BIT(13), 0 },
+	[PERI2_UART5_PRST] = { 0, BIT(14), PERI2_UART5_S_RST },
+	[PERI2_UART5_S_RST] = { 0, BIT(15), 0 },
+	[PERI2_UART6_PRST] = { 0, BIT(16), PERI2_UART6_S_RST },
+	[PERI2_UART6_S_RST] = { 0, BIT(17), 0 },
+	[PERI2_PAD_CTRL_PRST] = { 0, BIT(18), 0 },
+	[PERI2_GPIO3_DBRST] = { 0, BIT(19), 0 },
+	[PERI2_GPIO3_PRST] = { 0, BIT(20), 0 },
+	[PERI2_I2C3_IC_RST] = { 0, BIT(21), 0 },
+	[PERI2_I2C3_PRST] = { 0, BIT(22), 0 },
+	[PERI2_I2C5_IC_RST] = { 0, BIT(23), 0 },
+	[PERI2_I2C5_PRST] = { 0, BIT(24), 0 },
+	[PERI2_I2C6_IC_RST] = { 0, BIT(25), 0 },
+	[PERI2_I2C6_PRST] = { 0, BIT(26), 0 },
+	[PERI2_I2C7_IC_RST] = { 0, BIT(27), 0 },
+	[PERI2_I2C7_PRST] = { 0, BIT(28), 0 },
+	[PERI2_I2S1_PRST] = { 0, BIT(29), 0 },
+	[PERI2_I2S3_PRST] = { 0, BIT(30), 0 },
+	[PERI2_UART7_PRST] = { 0, BIT(31), PERI2_UART7_S_RST },
+	[PERI2_UART7_S_RST] = { 0x4, BIT(0), 0 },
+	[PERI2_UART8_PRST] = { 0x4, BIT(1), PERI2_UART8_S_RST },
+	[PERI2_UART8_S_RST] = { 0x4, BIT(2), 0 },
+	[PERI2_UART9_PRST] = { 0x4, BIT(3), PERI2_UART9_S_RST },
+	[PERI2_UART9_S_RST] = { 0x4, BIT(4), 0 },
+	[PERI2_QSPI1_PRST] = { 0x4, BIT(5), 0 },
+	[PERI2_QSPI1_SSI_RST] = { 0x4, BIT(6), 0 },
+	[PERI2_PWM1_CRST] = { 0x4, BIT(7), 0 },
+	[PERI2_PWM1_PRST] = { 0x4, BIT(8), 0 },
+	[PERI2_PWM2_CRST] = { 0x4, BIT(9), 0 },
+	[PERI2_PWM2_PRST] = { 0x4, BIT(10), 0 },
+	[PERI2_I2C3_RST] = { 0, BIT(21) | BIT(22), 0 },
+	[PERI2_I2C4_RST] = { 0, BIT(7) | BIT(8), 0 },
+	[PERI2_I2C5_RST] = { 0, BIT(23) | BIT(24), 0 },
+	[PERI2_I2C6_RST] = { 0, BIT(25) | BIT(26), 0 },
+	[PERI2_I2C7_RST] = { 0, BIT(27) | BIT(28), 0 },
+	[PERI2_SPI1_RST] = { 0, BIT(10) | BIT(11), 0 },
+};
+
+static const struct a210_rst_signal peri3_rst_signals[] = {
+	[PERI3_DMAC_ARST] = { 0, BIT(0), 0 },
+	[PERI3_DMAC_HRST] = { 0, BIT(1), 0 },
+	[PERI3_EMMC_SDIO_CLKGEN_RST] = { 0, BIT(2), 0 },
+	[PERI3_EMMC_RST] = { 0, BIT(3), 0 },
+	[PERI3_EMMC_X2X_ARST_M] = { 0, BIT(4), 0 },
+	[PERI3_EMMC_X2X_ARST_S] = { 0, BIT(5), 0 },
+	[PERI3_SDIO_RST] = { 0, BIT(6), 0 },
+	[PERI3_SDIO_X2X_ARST_M] = { 0, BIT(7), 0 },
+	[PERI3_SDIO_X2X_ARST_S] = { 0, BIT(8), 0 },
+	[PERI3_AXI_MST_ARST] = { 0, BIT(9), 0 },
+	[PERI3_AXI_MST_PRST] = { 0, BIT(10), 0 },
+	[PERI3_ADC_PRST] = { 0, BIT(11), 0 },
+	[PERI3_TEE_X2X_ARST_M] = { 0, BIT(12), 0 },
+	[PERI3_TEE_X2X_ARST_S] = { 0, BIT(13), 0 },
+	[PERI3_TEE_H2H_HRST] = { 0, BIT(14), 0 },
+	[PERI3_GPIO4_DBRST] = { 0, BIT(15), 0 },
+	[PERI3_GPIO4_PRST] = { 0, BIT(16), 0 },
+	[PERI3_PAD_CTRL_PRST] = { 0, BIT(17), 0 },
+};
+
+static const struct a210_rst_signal pcie_rst_signals[] = {
+	[PCIE_X2X_PERI_SLV_ARST] = { 0, BIT(0), 0 },
+	[PCIE_X2X_PERI_MST_ARST] = { 0, BIT(4), 0 },
+	[PCIE_AXI4_PCIE_MST_ARST] = { 0, BIT(8), 0 },
+	[PCIE_AXI4_PCIE_MST_PRST] = { 0, BIT(12), 0 },
+	[PCIE_DFMU_PRST] = { 0x4, BIT(0), 0 },
+	[PCIE_DFMU_ARST] = { 0x4, BIT(4), 0 },
+	[PCIE_E16PHY_PHY_RST] = { 0x8, BIT(0), 0 },
+	[PCIE_E16PHY_APBS_PRST] = { 0x8, BIT(4), 0 },
+	[PCIE_X2X_SATA_MST_ARST] = { 0x10, BIT(0), 0 },
+	[PCIE_X2X_SATA_SLV_ARST] = { 0x10, BIT(4), 0 },
+	[PCIE_SATA_ARESET] = { 0x10, BIT(8), 0 },
+	[PCIE_SATA_RST_PMALIVE] = { 0x10, BIT(12), 0 },
+	[PCIE_SATA_SLV_AFENCE_ARST] = { 0x10, BIT(16), 0 },
+	[PCIE_SATA_MST_AFENCE_ARST] = { 0x10, BIT(20), 0 },
+	[PCIE_SATA_RST_ASIC0] = { 0x14, BIT(0), 0 },
+	[PCIE_SATA_RST_ASIC1] = { 0x14, BIT(4), 0 },
+	[PCIE_SATA_RST_RXOOB0] = { 0x14, BIT(8), 0 },
+	[PCIE_SATA_RST_RXOOB1] = { 0x14, BIT(12), 0 },
+	[PCIE_DM_GEN3X4_APBS_PRST] = { 0x20, BIT(0), 0 },
+	[PCIE_DM_GEN3X4_POWER_UP_RST] = { 0x20, BIT(4), 0 },
+	[PCIE_DM_SLV_AFENCE_ARST] = { 0x20, BIT(16), 0 },
+	[PCIE_DM_MST_AFENCE_ARST] = { 0x20, BIT(20), 0 },
+	[PCIE_RP_GEN3X1_APBS_PRST] = { 0x24, BIT(0), 0 },
+	[PCIE_RP_GEN3X1_POWER_UP_RST] = { 0x24, BIT(4), 0 },
+	[PCIE_RP_SLV_AFENCE_ARST] = { 0x24, BIT(16), 0 },
+	[PCIE_RP_MST_AFENCE_ARST] = { 0x24, BIT(20), 0 },
+};
+
+static const struct a210_rst_signal usb_rst_signals[] = {
+	[USB_DFMU_PRST] = { 0, BIT(0), 0 },
+	[USB_DFMU_ARST] = { 0, BIT(4), 0 },
+	[USB_AXI4_MST_ARST] = { 0, BIT(8), 0 },
+	[USB_AXI4_MST_PRST] = { 0, BIT(12), 0 },
+	[USB_DPTX_APBS_PRST] = { 0x4, BIT(0), 0 },
+	[USB_DPTX_VCC_RST] = { 0x4, BIT(4), 0 },
+	[USB_USB31_APBS_PRST] = { 0x8, BIT(0), 0 },
+	[USB_USB31_VCC_RST] = { 0x8, BIT(4), 0 },
+	[USB_USB31_PHY_RST] = { 0x8, BIT(8), 0 },
+	[USB_USB31_SLV_AFENCE_ARST] = { 0x8, BIT(12), 0 },
+	[USB_C10PHY_PHY_RST] = { 0xc, BIT(0), 0 },
+	[USB_C10PHY_APBS_PRST] = { 0xc, BIT(4), 0 },
+	[USB_USB20_BLK_X2H_HRST] = { 0x10, BIT(0), 0 },
+	[USB_USB20_BLK_X2H_ARST] = { 0x10, BIT(4), 0 },
+	[USB_USB20_SLV_AFENCE_ARST] = { 0x10, BIT(8), 0 },
+	[USB_USB20_BLK_H2P_HRST] = { 0x10, BIT(16), 0 },
+	[USB_USB20_BLK_AHB_SLV_HRST] = { 0x10, BIT(20), 0 },
+	[USB_USB20_BLK_AXI_MST_ARST] = { 0x10, BIT(24), 0 },
+	[USB_USB20_BLK_USB2_SYSREG_PRST] = { 0x10, BIT(28), 0 },
+	[USB_USB20_BLK_USB2_WRAP0_PRST] = { 0x14, BIT(0), 0 },
+	[USB_USB20_BLK_USB2_WRAP0_HRST] = { 0x14, BIT(4), 0 },
+	[USB_USB20_BLK_USB2_WRAP1_PRST] = { 0x14, BIT(8), 0 },
+	[USB_USB20_BLK_USB2_WRAP1_HRST] = { 0x14, BIT(12), 0 },
+	[USB_USB20_BLK_A2X0_HRST] = { 0x14, BIT(16), 0 },
+	[USB_USB20_BLK_A2X0_ARST] = { 0x14, BIT(20), 0 },
+	[USB_USB20_BLK_A2X1_HRST] = { 0x14, BIT(24), 0 },
+	[USB_USB20_BLK_A2X1_ARST] = { 0x14, BIT(28), 0 },
+	[USB_USB20_BLK_USB0_PHY_PON_RESET] = { 0x18, BIT(0), 0 },
+	[USB_USB20_BLK_USB1_PHY_PON_RESET] = { 0x18, BIT(4), 0 },
+	[USB_PERI2_SS_RST] = { 0x20, BIT(0), 0 },
+	[USB_PERI2_SLV_AFENCE_ARST] = { 0x20, BIT(4), 0 },
+};
+
+static const struct a210_rst_signal tee_rst_signals[] = {
+	[TEE_KEYRAM_PRST] = { 0, BIT(0), 0 },
+	[TEE_DS_PRST] = { 0, BIT(1), 0 },
+	[TEE_EFUSE_PRST] = { 0, BIT(2), 0 },
+	[TEE_OCRAM_HRST] = { 0, BIT(3), 0 },
+	[TEE_SYSREG_PRST] = { 0, BIT(4), 0 },
+	[TEE_CCU_PRST] = { 0, BIT(5), 0 },
+	[TEE_CCU_CRST] = { 0, BIT(6), 0 },
+	[TEE_EIP150B_HRST] = { 0, BIT(8), 0 },
+	[TEE_EIP120SIII_HRST] = { 0, BIT(9), 0 },
+	[TEE_EIP120SIII_ARST] = { 0, BIT(10), 0 },
+	[TEE_EIP120SII_HRST] = { 0, BIT(11), 0 },
+	[TEE_EIP120SII_ARST] = { 0, BIT(12), 0 },
+	[TEE_EIP120SI_HRST] = { 0, BIT(13), 0 },
+	[TEE_EIP120SI_ARST] = { 0, BIT(14), 0 },
+	[TEE_DMAC_HRST] = { 0, BIT(15), 0 },
+	[TEE_DMAC_ARST] = { 0, BIT(16), 0 },
+	[TEE_X2P_TEESYS_PRST] = { 0, BIT(24), 0 },
+	[TEE_X2P_TEESYS_ARST] = { 0, BIT(25), 0 },
+	[TEE_AXI4_TEESYS_ARST] = { 0, BIT(26), 0 },
+	[TEE_APB3_TEESYS_PRST] = { 0, BIT(27), 0 },
+	[TEE_APB3_TEESYS_HRST] = { 0, BIT(28), 0 },
+	[TEE_AHB2_TEESYS_HRST] = { 0, BIT(29), 0 },
+};
+
+static const struct a210_rst_signal gpu_rst_signals[] = {
+	[GPU_PWR_WRAP_RGX_HOOD_RST] = { 0, BIT(0), 0 },
+	[GPU_PWR_WRAP_DFMU_RST] = { 0, BIT(1), 0 },
+};
+
+static inline struct a210_reset *to_a210_reset(struct reset_controller_dev *rcdev)
+{
+	return container_of(rcdev, struct a210_reset, rcdev);
+}
+
+static int a210_reset_update(struct reset_controller_dev *rcdev,
+			     unsigned long id, bool assert)
+{
+	struct a210_reset *rst = to_a210_reset(rcdev);
+	const struct a210_rst_signal *signal;
+	unsigned long flags;
+	u32 value;
+	int ret = 0;
+
+	if (id >= rst->data->num_signals)
+		return -EINVAL;
+
+	spin_lock_irqsave(&rst->lock, flags);
+	do {
+		signal = &rst->data->signals[id];
+		value = readl(rst->base + signal->offset);
+		if (assert)
+			value &= ~signal->mask;
+		else
+			value |= signal->mask;
+		writel(value, rst->base + signal->offset);
+		/* Firmware can lock individual reset controls against AP writes. */
+		if ((readl(rst->base + signal->offset) & signal->mask) !=
+		    (value & signal->mask)) {
+			ret = -EIO;
+			break;
+		}
+		id = signal->nextid;
+	} while (id);
+	spin_unlock_irqrestore(&rst->lock, flags);
+
+	return ret;
+}
+
+static int a210_reset_assert(struct reset_controller_dev *rcdev, unsigned long id)
+{
+	return a210_reset_update(rcdev, id, true);
+}
+
+static int a210_reset_deassert(struct reset_controller_dev *rcdev, unsigned long id)
+{
+	return a210_reset_update(rcdev, id, false);
+}
+
+static int a210_reset_status(struct reset_controller_dev *rcdev, unsigned long id)
+{
+	struct a210_reset *rst = to_a210_reset(rcdev);
+	const struct a210_rst_signal *signal;
+	unsigned long flags;
+	bool asserted;
+
+	if (id >= rst->data->num_signals)
+		return -EINVAL;
+
+	/* The logical reset is asserted if any linked signal is asserted. */
+	spin_lock_irqsave(&rst->lock, flags);
+	do {
+		signal = &rst->data->signals[id];
+		asserted = (readl(rst->base + signal->offset) & signal->mask) !=
+			   signal->mask;
+		if (asserted)
+			break;
+		id = signal->nextid;
+	} while (id);
+	spin_unlock_irqrestore(&rst->lock, flags);
+
+	return asserted;
+}
+
+static const struct reset_control_ops a210_reset_ops = {
+	.assert = a210_reset_assert,
+	.deassert = a210_reset_deassert,
+	.status = a210_reset_status,
+};
+
+static int a210_reset_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct a210_reset *rst;
+
+	rst = devm_kzalloc(dev, sizeof(*rst), GFP_KERNEL);
+	if (!rst)
+		return -ENOMEM;
+
+	rst->data = device_get_match_data(dev);
+	if (!rst->data)
+		return -EINVAL;
+
+	rst->base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(rst->base))
+		return PTR_ERR(rst->base);
+
+	spin_lock_init(&rst->lock);
+	rst->rcdev.ops = &a210_reset_ops;
+	rst->rcdev.owner = THIS_MODULE;
+	rst->rcdev.dev = dev;
+	rst->rcdev.of_node = dev->of_node;
+	rst->rcdev.nr_resets = rst->data->num_signals;
+
+	return devm_reset_controller_register(dev, &rst->rcdev);
+}
+
+static const struct a210_reset_data vp_reset_data = {
+	.signals = vp_rst_signals,
+	.num_signals = ARRAY_SIZE(vp_rst_signals),
+};
+
+static const struct a210_reset_data vi_reset_data = {
+	.signals = vi_rst_signals,
+	.num_signals = ARRAY_SIZE(vi_rst_signals),
+};
+
+static const struct a210_reset_data npu_reset_data = {
+	.signals = npu_rst_signals,
+	.num_signals = ARRAY_SIZE(npu_rst_signals),
+};
+
+static const struct a210_reset_data vo_reset_data = {
+	.signals = vo_rst_signals,
+	.num_signals = ARRAY_SIZE(vo_rst_signals),
+};
+
+static const struct a210_reset_data peri0_reset_data = {
+	.signals = peri0_rst_signals,
+	.num_signals = ARRAY_SIZE(peri0_rst_signals),
+};
+
+static const struct a210_reset_data peri1_reset_data = {
+	.signals = peri1_rst_signals,
+	.num_signals = ARRAY_SIZE(peri1_rst_signals),
+};
+
+static const struct a210_reset_data peri2_reset_data = {
+	.signals = peri2_rst_signals,
+	.num_signals = ARRAY_SIZE(peri2_rst_signals),
+};
+
+static const struct a210_reset_data peri3_reset_data = {
+	.signals = peri3_rst_signals,
+	.num_signals = ARRAY_SIZE(peri3_rst_signals),
+};
+
+static const struct a210_reset_data pcie_reset_data = {
+	.signals = pcie_rst_signals,
+	.num_signals = ARRAY_SIZE(pcie_rst_signals),
+};
+
+static const struct a210_reset_data usb_reset_data = {
+	.signals = usb_rst_signals,
+	.num_signals = ARRAY_SIZE(usb_rst_signals),
+};
+
+static const struct a210_reset_data tee_reset_data = {
+	.signals = tee_rst_signals,
+	.num_signals = ARRAY_SIZE(tee_rst_signals),
+};
+
+static const struct a210_reset_data gpu_reset_data = {
+	.signals = gpu_rst_signals,
+	.num_signals = ARRAY_SIZE(gpu_rst_signals),
+};
+
+static const struct of_device_id a210_reset_of_match[] = {
+	{ .compatible = "zhihe,a210-vp-reset", .data = &vp_reset_data },
+	{ .compatible = "zhihe,a210-vi-reset", .data = &vi_reset_data },
+	{ .compatible = "zhihe,a210-npu-reset", .data = &npu_reset_data },
+	{ .compatible = "zhihe,a210-vo-reset", .data = &vo_reset_data },
+	{ .compatible = "zhihe,a210-peri0-reset", .data = &peri0_reset_data },
+	{ .compatible = "zhihe,a210-peri1-reset", .data = &peri1_reset_data },
+	{ .compatible = "zhihe,a210-peri2-reset", .data = &peri2_reset_data },
+	{ .compatible = "zhihe,a210-peri3-reset", .data = &peri3_reset_data },
+	{ .compatible = "zhihe,a210-pcie-reset", .data = &pcie_reset_data },
+	{ .compatible = "zhihe,a210-usb-reset", .data = &usb_reset_data },
+	{ .compatible = "zhihe,a210-tee-reset", .data = &tee_reset_data },
+	{ .compatible = "zhihe,a210-gpu-reset", .data = &gpu_reset_data },
+	{}
+};
+MODULE_DEVICE_TABLE(of, a210_reset_of_match);
+
+static struct platform_driver a210_reset_driver = {
+	.probe = a210_reset_probe,
+	.driver = {
+		.name = "a210-reset",
+		.of_match_table = a210_reset_of_match,
+	},
+};
+module_platform_driver(a210_reset_driver);
+
+MODULE_AUTHOR("Zhiguo Zhu <zhiguo.zhu@linux.alibaba.com>");
+MODULE_DESCRIPTION("Zhihe A210 reset controller driver");
+MODULE_LICENSE("GPL");

-- 
2.55.0



^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 08/18] dt-bindings: pinctrl: add Zhihe A210 pin controller
  2026-10-21 19:53 [PATCH 00/18] riscv: add initial support for Zhihe A210 and Melon Pi Han Gao via B4 Relay
                   ` (6 preceding siblings ...)
  2026-10-21 19:53 ` [PATCH 07/18] reset: zhihe: add A210 support Han Gao via B4 Relay
@ 2026-10-21 19:53 ` Han Gao via B4 Relay
  2026-10-21 19:53 ` [PATCH 09/18] pinctrl: zhihe: add A210 support Han Gao via B4 Relay
                   ` (9 subsequent siblings)
  17 siblings, 0 replies; 22+ messages in thread
From: Han Gao via B4 Relay @ 2026-10-21 19:53 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Zhiguo Zhu,
	Stephen Boyd, Brian Masney, Jerome Brunet, Philipp Zabel,
	Linus Walleij, Bartosz Golaszewski, Thomas Gleixner, Radu Rendec,
	Samuel Holland, Daniel Lezcano, Anup Patel, Icenowy Zheng,
	Drew Fustini
  Cc: devicetree, linux-kernel, linux-riscv, linux-clk, linux-gpio,
	Paul Walmsley, Han Gao

From: Zhiguo Zhu <zhiguo.zhu@linux.alibaba.com>

Add bindings for the four A210 pad controllers. Describe the shared
PERI3 SDIO mux and per-pad bias controls.

Signed-off-by: Zhiguo Zhu <zhiguo.zhu@linux.alibaba.com>
Signed-off-by: Han Gao <gaohan@iscas.ac.cn>
---
 .../bindings/pinctrl/zhihe,a210-pinctrl.yaml       | 206 +++++++++++++++++++++
 1 file changed, 206 insertions(+)

diff --git a/Documentation/devicetree/bindings/pinctrl/zhihe,a210-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/zhihe,a210-pinctrl.yaml
new file mode 100644
index 000000000000..51cbb0189f47
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/zhihe,a210-pinctrl.yaml
@@ -0,0 +1,206 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/zhihe,a210-pinctrl.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: ZhiHe A210 pin controller
+
+maintainers:
+  - Zhiguo Zhu <zhiguo.zhu@linux.alibaba.com>
+
+description: |
+  Pinmux and pinconf controller of the ZhiHe A210 RISC-V SoC.
+
+  The pads of the A210 are split into four groups, each managed by its
+  own pad controller with a separate register range:
+
+    AON pad controller     -> zhihe,a210-aon-pinctrl
+    PADCTRL0 (peripheral1) -> zhihe,a210-peri1-pinctrl
+    PADCTRL1 (peripheral2) -> zhihe,a210-peri2-pinctrl
+    PADCTRL2 (peripheral3) -> zhihe,a210-peri3-pinctrl
+
+  Each pad can be muxed individually to up to 8 different functions,
+  though for most pads only a few of those configurations are valid.
+  A few pads in the AON group do not support muxing or configuration
+  at all.
+
+  AON, PERI1 and PERI2 pads support configurable drive strength, bias,
+  input enable, Schmitt trigger and slew rate. PERI3 has a separate pad
+  layout: its six SDIO pads share one mux bit. Select their function with
+  the "sdio" group. Per-pad bias can be configured independently.
+
+properties:
+  compatible:
+    enum:
+      - zhihe,a210-aon-pinctrl
+      - zhihe,a210-peri1-pinctrl
+      - zhihe,a210-peri2-pinctrl
+      - zhihe,a210-peri3-pinctrl
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+
+  clock-names:
+    const: pclk
+
+patternProperties:
+  '-[0-9]+$':
+    type: object
+
+    description:
+      A pinmux group referenced by a consumer's pinctrl phandle. It
+      contains one subnode per set of pads sharing the same pinmux and
+      pinconf settings.
+
+    additionalProperties: false
+
+    patternProperties:
+      '-pins$':
+        type: object
+        $ref: /schemas/pinctrl/pincfg-node.yaml#
+
+        description:
+          A pinctrl node describing the pinmux and pinconf settings of
+          one or more pads.
+
+        properties:
+          pins:
+            $ref: /schemas/pinctrl/pinmux-node.yaml#/properties/pins
+            description: List of pads that properties in the node apply to.
+
+          groups:
+            items:
+              - const: sdio
+
+          function:
+            $ref: /schemas/pinctrl/pinmux-node.yaml#/properties/function
+            enum: [ aouart, aouart_ir, aogpio0, aogpio1, aoi2c0, aoi2c1,
+                    aospi, jtag, reset, por, pmic, dvs, uart0, uart1,
+                    uart2, uart3, uart4, uart5, uart6, uart7, uart8,
+                    uart9, uart0_ir, uart1_ir, uart2_ir, uart3_ir,
+                    uart4_ir, uart5_ir, uart6_ir, uart7_ir, uart8_ir,
+                    uart9_ir, gpio0, gpio1, gpio2, gpio3, gpio4, gmac0,
+                    gmac1, spi0, spi1, qspi0, qspi1, pwm0, pwm1, pwm2,
+                    can0, can1, can2, i2s0, i2s1, i2s2, i2s3, i2c0, i2c1,
+                    i2c2, i2c3, i2c4, i2c5, i2c6, i2c7, i2c7_smb, sdio,
+                    isp0, dptx, usb31, sata_p0, sata_p1, hdmi, zmac,
+                    bsel, dbgm, cdbg, pdm, tdm, pcie_x1, pcie_x4,
+                    sen_vclk ]
+            description: The mux function to select for the given pins.
+
+          bias-disable: true
+
+          bias-pull-up: true
+
+          bias-pull-down: true
+
+          drive-strength:
+            enum: [ 1, 2, 3, 5, 7, 8, 10, 12, 13, 15, 16, 18, 20, 21, 23,
+                    25 ]
+            description: Drive strength in mA.
+
+          input-enable: true
+
+          input-disable: true
+
+          input-schmitt-enable: true
+
+          input-schmitt-disable: true
+
+          slew-rate:
+            maximum: 1
+
+        oneOf:
+          - required: [pins]
+          - required: [groups]
+
+        additionalProperties: false
+
+allOf:
+  - if:
+      properties:
+        compatible:
+          const: zhihe,a210-peri3-pinctrl
+    then:
+      patternProperties:
+        '-[0-9]+$':
+          patternProperties:
+            '-pins$':
+              properties:
+                pins:
+                  items:
+                    enum: [SDIO_CLK, SDIO_CMD, SDIO_DAT0, SDIO_DAT1,
+                           SDIO_DAT2, SDIO_DAT3]
+                function:
+                  enum: [sdio, gpio4]
+                drive-strength: false
+                input-enable: false
+                input-disable: false
+                input-schmitt-enable: false
+                input-schmitt-disable: false
+                slew-rate: false
+              if:
+                required: [function]
+              then:
+                required: [groups]
+    else:
+      patternProperties:
+        '-[0-9]+$':
+          patternProperties:
+            '-pins$':
+              properties:
+                groups: false
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - clock-names
+
+additionalProperties: false
+
+examples:
+  - |
+    pinctrl@2026000 {
+        compatible = "zhihe,a210-peri1-pinctrl";
+        reg = <0x2026000 0x1000>;
+        clocks = <&clk 0>;
+        clock-names = "pclk";
+
+        gmac0-0 {
+            gmac0-pins {
+                bias-disable;
+                drive-strength = <13>;
+                function = "gmac0";
+                input-disable;
+                input-schmitt-disable;
+                pins = "GPIO0_0", "GPIO0_12";
+                slew-rate = <0>;
+            };
+        };
+    };
+
+  - |
+    pinctrl@542000 {
+        compatible = "zhihe,a210-peri3-pinctrl";
+        reg = <0x542000 0x1000>;
+        clocks = <&clk 0>;
+        clock-names = "pclk";
+
+        sdio-0 {
+            cmd-data-pins {
+                bias-pull-up;
+                pins = "SDIO_CMD", "SDIO_DAT0", "SDIO_DAT1",
+                       "SDIO_DAT2", "SDIO_DAT3";
+            };
+
+            sdio-pins {
+                function = "sdio";
+                groups = "sdio";
+            };
+        };
+    };

-- 
2.55.0



^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 09/18] pinctrl: zhihe: add A210 support
  2026-10-21 19:53 [PATCH 00/18] riscv: add initial support for Zhihe A210 and Melon Pi Han Gao via B4 Relay
                   ` (7 preceding siblings ...)
  2026-10-21 19:53 ` [PATCH 08/18] dt-bindings: pinctrl: add Zhihe A210 pin controller Han Gao via B4 Relay
@ 2026-10-21 19:53 ` Han Gao via B4 Relay
  2026-10-21 19:53 ` [PATCH 10/18] dt-bindings: interrupt-controller: add Zhihe A210 PLIC Han Gao via B4 Relay
                   ` (8 subsequent siblings)
  17 siblings, 0 replies; 22+ messages in thread
From: Han Gao via B4 Relay @ 2026-10-21 19:53 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Zhiguo Zhu,
	Stephen Boyd, Brian Masney, Jerome Brunet, Philipp Zabel,
	Linus Walleij, Bartosz Golaszewski, Thomas Gleixner, Radu Rendec,
	Samuel Holland, Daniel Lezcano, Anup Patel, Icenowy Zheng,
	Drew Fustini
  Cc: devicetree, linux-kernel, linux-riscv, linux-clk, linux-gpio,
	Paul Walmsley, Han Gao

From: Zhiguo Zhu <zhiguo.zhu@linux.alibaba.com>

Add mux and pin configuration support for the four A210 pad controllers,
including the shared PERI3 SDIO mux and suspend-state restoration.

Signed-off-by: Zhiguo Zhu <zhiguo.zhu@linux.alibaba.com>
Co-developed-by: Han Gao <gaohan@iscas.ac.cn>
Signed-off-by: Han Gao <gaohan@iscas.ac.cn>
---
 drivers/pinctrl/Kconfig        |   14 +
 drivers/pinctrl/Makefile       |    1 +
 drivers/pinctrl/pinctrl-a210.c | 1206 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 1221 insertions(+)

diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index e1ab3a916086..50fd2732b9b8 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -37,6 +37,20 @@ config DEBUG_PINCTRL
 	help
 	  Say Y here to add some extra checks and diagnostics to PINCTRL calls.
 
+config PINCTRL_A210
+	tristate "Pinctrl driver for the ZhiHe A210 SoC"
+	depends on 64BIT
+	depends on OF && (ARCH_ZHIHE || COMPILE_TEST)
+	select GENERIC_PINMUX_FUNCTIONS
+	select GENERIC_PINCONF
+	select PINMUX
+	help
+	  This selects the pinctrl driver for the ZhiHe A210 RISC-V SoC.
+
+	  It provides pin multiplexing and configuration support for
+	  the A210 pad controllers (AON, PADCTRL0-2). Say Y if you
+	  are building a kernel for the ZhiHe A210 platform.
+
 config PINCTRL_AMD
 	bool "AMD GPIO pin control"
 	depends on HAS_IOMEM
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index a35d71135abf..c79ec78229ae 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_GENERIC_PINCONF)	+= pinconf-generic.o
 obj-$(CONFIG_GENERIC_PINCTRL)	+= pinctrl-generic.o
 obj-$(CONFIG_OF)		+= devicetree.o
 
+obj-$(CONFIG_PINCTRL_A210)	+= pinctrl-a210.o
 obj-$(CONFIG_PINCTRL_AMD)	+= pinctrl-amd.o
 obj-$(CONFIG_PINCTRL_AMDISP)	+= pinctrl-amdisp.o
 obj-$(CONFIG_PINCTRL_APPLE_GPIO) += pinctrl-apple-gpio.o
diff --git a/drivers/pinctrl/pinctrl-a210.c b/drivers/pinctrl/pinctrl-a210.c
new file mode 100644
index 000000000000..753253e35c05
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-a210.c
@@ -0,0 +1,1206 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2025 Zhihe Computing Limited.
+ */
+
+#include <linux/bitops.h>
+#include <linux/cleanup.h>
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/seq_file.h>
+#include <linux/spinlock.h>
+
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+
+#include "core.h"
+#include "pinmux.h"
+#include "pinconf.h"
+
+#define A210_PADCFG_IE BIT(9)
+#define A210_PADCFG_SL BIT(8)
+#define A210_PADCFG_ST BIT(7)
+#define A210_PADCFG_SPU BIT(6)
+#define A210_PADCFG_PS BIT(5)
+#define A210_PADCFG_PE BIT(4)
+#define A210_PADCFG_BIAS (A210_PADCFG_SPU | A210_PADCFG_PS | A210_PADCFG_PE)
+#define A210_PADCFG_DS GENMASK(3, 0)
+
+/* PERI3 has one 32-bit configuration register per SDIO pad. */
+#define A210_SDIO_PULL_UP BIT(1)
+#define A210_SDIO_PULL_DOWN BIT(0)
+#define A210_SDIO_BIAS (A210_SDIO_PULL_UP | A210_SDIO_PULL_DOWN)
+
+#define A210_PULL_DOWN_OHM 44000 /* typ. 44kOhm */
+#define A210_PULL_UP_OHM 48000 /* typ. 48kOhm */
+#define A210_PULL_STRONG_OHM 2100 /* typ. 2.1kOhm */
+
+#define A210_PAD_NO_PADCFG BIT(63)
+#define A210_PAD_MUXDATA GENMASK(55, 0)
+
+#ifdef CONFIG_PM_SLEEP
+#define A210_MAX_CFG_REGS 25
+#define A210_MAX_MUX_REGS 7
+
+struct a210_register_state {
+	u32 mask;
+	u32 value;
+};
+#endif
+
+struct a210_pinctrl;
+
+enum a210_pinctrl_type {
+	A210_PADCTRL_AON,
+	A210_PADCTRL_0,
+	A210_PADCTRL_1,
+	A210_PADCTRL_2,
+};
+
+struct a210_pad_group {
+	const char *name;
+	const struct pinctrl_pin_desc *pins;
+	unsigned int npins;
+	unsigned int offset_mux;
+	unsigned int mask_mux;
+	unsigned int offset_cfg;
+	unsigned int mask_cfg;
+	enum a210_pinctrl_type type;
+};
+
+struct a210_pinctrl {
+	struct pinctrl_desc desc;
+	raw_spinlock_t lock; /* serialize register access */
+	void __iomem *base;
+	struct clk *clk;
+	bool clk_enabled;
+	unsigned int offset_mux;
+	unsigned int mask_mux;
+	unsigned int offset_cfg;
+	unsigned int mask_cfg;
+	enum a210_pinctrl_type type;
+	struct pinctrl_dev *pctl;
+#ifdef CONFIG_PM_SLEEP
+	struct a210_register_state cfg_state[A210_MAX_CFG_REGS];
+	struct a210_register_state mux_state[A210_MAX_MUX_REGS];
+#endif
+};
+
+static void __iomem *a210_padcfg(struct a210_pinctrl *pp, unsigned int pin)
+{
+	int width = hweight32(pp->mask_cfg);
+
+	return pp->base + pp->offset_cfg + 4 * (pin * width / 32);
+}
+
+static unsigned int a210_padcfg_shift(struct a210_pinctrl *pp, unsigned int pin)
+{
+	int width = hweight32(pp->mask_cfg);
+
+	return width * (pin & (32 / width - 1));
+}
+
+static void __iomem *a210_muxcfg(struct a210_pinctrl *pp, unsigned int pin)
+{
+	int width = hweight32(pp->mask_mux);
+
+	return pp->base + pp->offset_mux + 4 * (pin * width / 32);
+}
+
+static unsigned int a210_muxcfg_shift(struct a210_pinctrl *pp, unsigned int pin)
+{
+	int width = hweight32(pp->mask_mux);
+
+	if (pp->type == A210_PADCTRL_2)
+		return 0;
+
+	return width * (pin & (32 / width - 1));
+}
+
+enum a210_muxtype {
+	A210_MUX_____,
+	A210_MUX_AOUART,
+	A210_MUX_AOUART_IR,
+	A210_MUX_AOGPIO0,
+	A210_MUX_AOGPIO1,
+	A210_MUX_AOI2C0,
+	A210_MUX_AOI2C1,
+	A210_MUX_AOSPI,
+	A210_MUX_JTAG,
+	A210_MUX_RST,
+	A210_MUX_POR,
+	A210_MUX_PMIC,
+	A210_MUX_DVS,
+	A210_MUX_UART0,
+	A210_MUX_UART1,
+	A210_MUX_UART2,
+	A210_MUX_UART3,
+	A210_MUX_UART4,
+	A210_MUX_UART5,
+	A210_MUX_UART6,
+	A210_MUX_UART7,
+	A210_MUX_UART8,
+	A210_MUX_UART9,
+	A210_MUX_UART0_IR,
+	A210_MUX_UART1_IR,
+	A210_MUX_UART2_IR,
+	A210_MUX_UART3_IR,
+	A210_MUX_UART4_IR,
+	A210_MUX_UART5_IR,
+	A210_MUX_UART6_IR,
+	A210_MUX_UART7_IR,
+	A210_MUX_UART8_IR,
+	A210_MUX_UART9_IR,
+	A210_MUX_GPIO0,
+	A210_MUX_GPIO1,
+	A210_MUX_GPIO2,
+	A210_MUX_GPIO3,
+	A210_MUX_GPIO4,
+	A210_MUX_GMAC0,
+	A210_MUX_GMAC1,
+	A210_MUX_SPI0,
+	A210_MUX_SPI1,
+	A210_MUX_QSPI0,
+	A210_MUX_QSPI1,
+	A210_MUX_PWM0,
+	A210_MUX_PWM1,
+	A210_MUX_PWM2,
+	A210_MUX_CAN0,
+	A210_MUX_CAN1,
+	A210_MUX_CAN2,
+	A210_MUX_I2S0,
+	A210_MUX_I2S1,
+	A210_MUX_I2S2,
+	A210_MUX_I2S3,
+	A210_MUX_I2C0,
+	A210_MUX_I2C1,
+	A210_MUX_I2C2,
+	A210_MUX_I2C3,
+	A210_MUX_I2C4,
+	A210_MUX_I2C5,
+	A210_MUX_I2C6,
+	A210_MUX_I2C7,
+	A210_MUX_I2C7_SMB,
+	A210_MUX_SDIO,
+	A210_MUX_ISP0,
+	A210_MUX_DPTX,
+	A210_MUX_USB31,
+	A210_MUX_SATA_P0,
+	A210_MUX_SATA_P1,
+	A210_MUX_HDMI,
+	A210_MUX_ZMAC,
+	A210_MUX_BSEL,
+	A210_MUX_DBGM,
+	A210_MUX_CDBG,
+	A210_MUX_PDM,
+	A210_MUX_TDM,
+	A210_MUX_PCIE_X1,
+	A210_MUX_PCIE_X4,
+	A210_MUX_SEN_VCLK,
+	A210_MUX_MAX = 127,
+};
+
+static const char *const a210_muxtype_string[] = {
+	[A210_MUX_AOUART] = "aouart",
+	[A210_MUX_AOUART_IR] = "aouart_ir",
+	[A210_MUX_AOGPIO0] = "aogpio0",
+	[A210_MUX_AOGPIO1] = "aogpio1",
+	[A210_MUX_AOI2C0] = "aoi2c0",
+	[A210_MUX_AOI2C1] = "aoi2c1",
+	[A210_MUX_AOSPI] = "aospi",
+	[A210_MUX_JTAG] = "jtag",
+	[A210_MUX_RST] = "reset",
+	[A210_MUX_POR] = "por",
+	[A210_MUX_PMIC] = "pmic",
+	[A210_MUX_DVS] = "dvs",
+	[A210_MUX_UART0] = "uart0",
+	[A210_MUX_UART1] = "uart1",
+	[A210_MUX_UART2] = "uart2",
+	[A210_MUX_UART3] = "uart3",
+	[A210_MUX_UART4] = "uart4",
+	[A210_MUX_UART5] = "uart5",
+	[A210_MUX_UART6] = "uart6",
+	[A210_MUX_UART7] = "uart7",
+	[A210_MUX_UART8] = "uart8",
+	[A210_MUX_UART9] = "uart9",
+	[A210_MUX_UART0_IR] = "uart0_ir",
+	[A210_MUX_UART1_IR] = "uart1_ir",
+	[A210_MUX_UART2_IR] = "uart2_ir",
+	[A210_MUX_UART3_IR] = "uart3_ir",
+	[A210_MUX_UART4_IR] = "uart4_ir",
+	[A210_MUX_UART5_IR] = "uart5_ir",
+	[A210_MUX_UART6_IR] = "uart6_ir",
+	[A210_MUX_UART7_IR] = "uart7_ir",
+	[A210_MUX_UART8_IR] = "uart8_ir",
+	[A210_MUX_UART9_IR] = "uart9_ir",
+	[A210_MUX_GPIO0] = "gpio0",
+	[A210_MUX_GPIO1] = "gpio1",
+	[A210_MUX_GPIO2] = "gpio2",
+	[A210_MUX_GPIO3] = "gpio3",
+	[A210_MUX_GPIO4] = "gpio4",
+	[A210_MUX_GMAC0] = "gmac0",
+	[A210_MUX_GMAC1] = "gmac1",
+	[A210_MUX_SPI0] = "spi0",
+	[A210_MUX_SPI1] = "spi1",
+	[A210_MUX_QSPI0] = "qspi0",
+	[A210_MUX_QSPI1] = "qspi1",
+	[A210_MUX_PWM0] = "pwm0",
+	[A210_MUX_PWM1] = "pwm1",
+	[A210_MUX_PWM2] = "pwm2",
+	[A210_MUX_CAN0] = "can0",
+	[A210_MUX_CAN1] = "can1",
+	[A210_MUX_CAN2] = "can2",
+	[A210_MUX_I2S0] = "i2s0",
+	[A210_MUX_I2S1] = "i2s1",
+	[A210_MUX_I2S2] = "i2s2",
+	[A210_MUX_I2S3] = "i2s3",
+	[A210_MUX_I2C0] = "i2c0",
+	[A210_MUX_I2C1] = "i2c1",
+	[A210_MUX_I2C2] = "i2c2",
+	[A210_MUX_I2C3] = "i2c3",
+	[A210_MUX_I2C4] = "i2c4",
+	[A210_MUX_I2C5] = "i2c5",
+	[A210_MUX_I2C6] = "i2c6",
+	[A210_MUX_I2C7] = "i2c7",
+	[A210_MUX_I2C7_SMB] = "i2c7_smb",
+	[A210_MUX_SDIO] = "sdio",
+	[A210_MUX_ISP0] = "isp0",
+	[A210_MUX_DPTX] = "dptx",
+	[A210_MUX_USB31] = "usb31",
+	[A210_MUX_SATA_P0] = "sata_p0",
+	[A210_MUX_SATA_P1] = "sata_p1",
+	[A210_MUX_HDMI] = "hdmi",
+	[A210_MUX_ZMAC] = "zmac",
+	[A210_MUX_BSEL] = "bsel",
+	[A210_MUX_DBGM] = "dbgm",
+	[A210_MUX_CDBG] = "cdbg",
+	[A210_MUX_PDM] = "pdm",
+	[A210_MUX_TDM] = "tdm",
+	[A210_MUX_PCIE_X1] = "pcie_x1",
+	[A210_MUX_PCIE_X4] = "pcie_x4",
+	[A210_MUX_SEN_VCLK] = "sen_vclk",
+};
+
+#define A210_PAD(_nr, _name, m0, m1, m2, m3, m4, m5, m6, m7, _flags)                             \
+	{ .number = _nr,                                                                         \
+	  .name = #_name,                                                                        \
+	  .drv_data =                                                                            \
+		  (void *)((_flags) | (A210_MUX_##m0 << 0) | (A210_MUX_##m1 << 7) |              \
+			   (A210_MUX_##m2 << 14) | (A210_MUX_##m3 << 21) |                       \
+			   ((uintptr_t)A210_MUX_##m4 << 28) | ((uintptr_t)A210_MUX_##m5 << 35) | \
+			   ((uintptr_t)A210_MUX_##m6 << 42) | ((uintptr_t)A210_MUX_##m7 << 49)) }
+
+static const struct pinctrl_pin_desc a210_group0_pins[] = {
+	A210_PAD(0, OSC_CLK_IN, ____, ____, ____, ____, ____, ____, ____, ____, A210_PAD_NO_PADCFG),
+	A210_PAD(1, OSC_CLK_OUT, ____, ____, ____, ____, ____, ____, ____, ____,
+		 A210_PAD_NO_PADCFG),
+	A210_PAD(2, RST_N_IN, ____, ____, ____, ____, ____, ____, ____, ____, A210_PAD_NO_PADCFG),
+	A210_PAD(3, RTC_CLK_IN, ____, ____, ____, ____, ____, ____, ____, ____, A210_PAD_NO_PADCFG),
+	A210_PAD(4, RTC_CLK_OUT, ____, ____, ____, ____, ____, ____, ____, ____,
+		 A210_PAD_NO_PADCFG),
+	A210_PAD(5, TEST_MODE, ____, ____, ____, ____, ____, ____, ____, ____, A210_PAD_NO_PADCFG),
+	A210_PAD(6, POR_SEL, ____, ____, ____, ____, ____, ____, ____, ____, A210_PAD_NO_PADCFG),
+	A210_PAD(7, RST_N_OUT, RST, ____, ____, AOGPIO0, ____, ____, ____, ____, 0),
+	A210_PAD(8, BOOT_SEL0, BSEL, ____, ____, AOGPIO0, ____, ____, ____, ____, 0),
+	A210_PAD(9, BOOT_SEL1, BSEL, AOUART, ____, AOGPIO0, ____, ____, ____, ____, 0),
+	A210_PAD(10, DEBUG_MODE, DBGM, ____, ____, AOGPIO0, ____, ____, ____, ____, 0),
+	A210_PAD(11, AOUART_TXD, AOUART, AOUART_IR, ____, AOGPIO0, ____, ____, ____, ____, 0),
+	A210_PAD(12, AOUART_RXD, AOUART, AOUART_IR, ____, AOGPIO0, ____, ____, ____, ____, 0),
+	A210_PAD(13, AOI2C0_SCL, AOI2C0, AOSPI, ____, AOGPIO0, ____, ____, ____, ____, 0),
+	A210_PAD(14, AOI2C0_SDA, AOI2C0, AOSPI, ____, AOGPIO0, ____, ____, ____, ____, 0),
+	A210_PAD(15, AOI2C1_SCL, AOI2C1, AOSPI, ____, AOGPIO0, ____, ____, ____, ____, 0),
+	A210_PAD(16, AOI2C1_SDA, AOI2C1, AOSPI, ____, AOGPIO0, ____, ____, ____, ____, 0),
+	A210_PAD(17, CPU_JTG_TCLK, JTAG, ____, ____, AOGPIO0, ____, ____, ____, ____, 0),
+	A210_PAD(18, CPU_JTG_TMS, JTAG, ____, ____, AOGPIO0, ____, ____, ____, ____, 0),
+	A210_PAD(19, CPU_JTG_TDI, JTAG, ____, ____, AOGPIO0, ____, ____, ____, ____, 0),
+	A210_PAD(20, CPU_JTG_TDO, JTAG, POR, ____, AOGPIO0, ____, ____, ____, ____, 0),
+	A210_PAD(21, CPU_JTG_TRST, JTAG, ____, ____, AOGPIO0, ____, ____, ____, ____, 0),
+	A210_PAD(22, AOGPIO0_21, AOGPIO0, AOSPI, PMIC, ____, ____, ____, ____, ____, 0),
+	A210_PAD(23, AOGPIO0_22, AOGPIO0, AOSPI, PMIC, ____, ____, ____, ____, ____, 0),
+	A210_PAD(24, AOGPIO0_23, BSEL, AOSPI, PMIC, AOGPIO0, ____, ____, ____, ____, 0),
+	A210_PAD(25, AOGPIO0_24, AOGPIO0, AOSPI, PMIC, ____, ____, ____, ____, ____, 0),
+	A210_PAD(26, AOGPIO0_25, AOGPIO0, AOSPI, PMIC, ____, ____, ____, ____, ____, 0),
+	A210_PAD(27, AOGPIO0_26, AOGPIO0, AOI2C1, PMIC, ____, ____, ____, ____, ____, 0),
+	A210_PAD(28, AOGPIO0_27, AOGPIO0, AOI2C1, PMIC, ____, ____, ____, ____, ____, 0),
+	A210_PAD(29, AOGPIO0_28, AOGPIO0, AOI2C1, PMIC, ____, ____, ____, ____, ____, 0),
+	A210_PAD(30, AOGPIO0_29, AOGPIO0, AOI2C1, PMIC, ____, ____, ____, ____, ____, 0),
+	A210_PAD(31, AOGPIO0_30, AOGPIO0, AOI2C1, PMIC, DVS, ____, ____, ____, ____, 0),
+	A210_PAD(32, AOGPIO0_31, AOGPIO0, AOUART, PMIC, DVS, ____, ____, ____, ____, 0),
+	A210_PAD(33, AOGPIO1_0, AOGPIO1, AOUART, PMIC, ____, ____, ____, ____, ____, 0),
+	A210_PAD(34, AOGPIO1_1, AOGPIO1, ____, PMIC, ____, ____, ____, ____, ____, 0),
+	A210_PAD(35, AOGPIO1_2, AOGPIO1, ____, PMIC, DVS, ____, ____, ____, ____, 0),
+	A210_PAD(36, AOGPIO1_3, AOGPIO1, ____, PMIC, DVS, ____, ____, ____, ____, 0),
+	A210_PAD(37, AOGPIO1_4, AOGPIO1, ____, PMIC, DVS, ____, ____, ____, ____, 0),
+	A210_PAD(38, AOGPIO1_5, AOGPIO1, ____, PMIC, DVS, ____, ____, ____, ____, 0),
+	A210_PAD(39, AOGPIO1_6, AOGPIO1, ____, PMIC, DVS, ____, ____, ____, ____, 0),
+	A210_PAD(40, AOGPIO1_7, AOGPIO1, ____, PMIC, DVS, ____, ____, ____, ____, 0),
+	A210_PAD(41, AOGPIO1_8, PCIE_X4, ____, PMIC, AOGPIO1, ____, ____, ____, ____, 0),
+	A210_PAD(42, AOGPIO1_9, AOGPIO1, ____, PMIC, ____, ____, ____, ____, ____, 0),
+};
+
+static const struct pinctrl_pin_desc a210_group1_pins[] = {
+	A210_PAD(0, GPIO0_0, GPIO0, GMAC0, ____, ____, ____, ____, ZMAC, ____, 0),
+	A210_PAD(1, GPIO0_1, GPIO0, GMAC0, ____, ____, ____, ____, ZMAC, ____, 0),
+	A210_PAD(2, GPIO0_2, GPIO0, GMAC0, ____, ____, ____, ____, ZMAC, ____, 0),
+	A210_PAD(3, GPIO0_3, GPIO0, GMAC0, UART3, UART3_IR, ____, SATA_P0, ZMAC, ____, 0),
+	A210_PAD(4, GPIO0_4, GPIO0, GMAC0, UART3, UART3_IR, ____, SATA_P1, ZMAC, ____, 0),
+	A210_PAD(5, GPIO0_5, GPIO0, GMAC0, UART3, ____, ____, SATA_P1, ZMAC, ____, 0),
+	A210_PAD(6, GPIO0_6, GPIO0, GMAC0, UART3, ____, ____, SATA_P1, ZMAC, ____, 0),
+	A210_PAD(7, GPIO0_7, GPIO0, GMAC0, ____, ____, ____, SATA_P1, ZMAC, ____, 0),
+	A210_PAD(8, GPIO0_8, GPIO0, GMAC0, I2C0, ____, ____, SATA_P1, ZMAC, ____, 0),
+	A210_PAD(9, GPIO0_9, GPIO0, GMAC0, I2C0, ____, ____, PCIE_X4, ZMAC, ____, 0),
+	A210_PAD(10, GPIO0_10, GPIO0, GMAC0, I2C1, ____, ____, PCIE_X4, ZMAC, ____, 0),
+	A210_PAD(11, GPIO0_11, GPIO0, GMAC0, I2C1, ____, ____, PCIE_X4, ZMAC, ____, 0),
+	A210_PAD(12, GPIO0_12, GPIO0, GMAC0, ____, ____, ____, PCIE_X4, ZMAC, ____, 0),
+	A210_PAD(13, GPIO0_13, GPIO0, GMAC0, ____, ____, ____, PWM0, ZMAC, ____, 0),
+	A210_PAD(14, GPIO0_14, GPIO0, UART0, UART0_IR, ____, SATA_P1, I2S0, ____, ____, 0),
+	A210_PAD(15, GPIO0_15, GPIO0, UART0, UART0_IR, QSPI0, SATA_P1, I2S0, ____, ____, 0),
+	A210_PAD(16, GPIO0_16, GPIO0, UART0, UART1, UART1_IR, SATA_P1, I2S0, ZMAC, ____, 0),
+	A210_PAD(17, GPIO0_17, GPIO0, UART0, UART1, UART1_IR, SATA_P1, I2S0, ZMAC, ____, 0),
+	A210_PAD(18, GPIO0_18, GPIO0, QSPI0, GMAC0, SDIO, SATA_P1, I2S0, ____, PCIE_X1, 0),
+	A210_PAD(19, GPIO0_19, GPIO0, QSPI0, GMAC1, ____, TDM, SATA_P0, ____, PCIE_X1, 0),
+	A210_PAD(20, GPIO0_20, GPIO0, QSPI0, UART3, UART3_IR, TDM, SATA_P0, ZMAC, PCIE_X1, 0),
+	A210_PAD(21, GPIO0_21, GPIO0, QSPI0, UART3, UART3_IR, TDM, SATA_P0, ZMAC, PCIE_X1, 0),
+	A210_PAD(22, GPIO0_22, GPIO0, QSPI0, I2C2, ____, TDM, SATA_P0, ZMAC, PWM0, 0),
+	A210_PAD(23, GPIO0_23, GPIO0, QSPI0, I2C2, ____, ____, SATA_P0, ZMAC, PWM0, 0),
+	A210_PAD(24, GPIO0_24, GPIO0, QSPI0, I2C0, CAN0, CDBG, PCIE_X1, UART0, PWM0, 0),
+	A210_PAD(25, GPIO0_25, GPIO0, QSPI0, I2C0, CAN0, CDBG, PCIE_X1, UART0, PWM0, 0),
+	A210_PAD(26, GPIO0_26, GPIO0, QSPI0, I2C1, CAN1, CDBG, PCIE_X1, UART0, UART0_IR, 0),
+	A210_PAD(27, GPIO0_27, GPIO0, QSPI0, I2C1, CAN1, CDBG, PCIE_X1, UART0, UART0_IR, 0),
+	A210_PAD(28, GPIO0_28, GPIO0, PWM0, SPI0, UART1_IR, I2S0, PCIE_X4, UART1, ____, 0),
+	A210_PAD(29, GPIO0_29, GPIO0, PWM0, SPI0, UART1_IR, I2S0, PCIE_X4, UART1, ____, 0),
+	A210_PAD(30, GPIO0_30, GPIO0, PWM0, SPI0, ____, I2S0, PCIE_X4, UART1, ____, 0),
+	A210_PAD(31, GPIO0_31, GPIO0, PWM0, SPI0, QSPI0, I2S0, PCIE_X4, UART1, ____, 0),
+	A210_PAD(32, GPIO1_0, GPIO1, PWM0, UART2, UART2_IR, I2S0, SDIO, GMAC1, SATA_P0, 0),
+	A210_PAD(33, GPIO1_1, GPIO1, PWM0, UART2, UART2_IR, I2C2, SATA_P1, SPI0, SDIO, 0),
+	A210_PAD(34, GPIO1_2, GPIO1, GMAC1, TDM, PWM0, I2C2, SATA_P1, ____, ____, 0),
+	A210_PAD(35, GPIO1_3, GPIO1, GMAC1, TDM, PWM0, ____, SATA_P1, ____, ____, 0),
+	A210_PAD(36, GPIO1_4, GPIO1, GMAC1, TDM, UART2, ____, SATA_P1, ____, ____, 0),
+	A210_PAD(37, GPIO1_5, GPIO1, GMAC1, ____, UART2, ____, SATA_P1, ____, ____, 0),
+	A210_PAD(38, GPIO1_6, GPIO1, GMAC1, SPI0, PWM0, CDBG, SATA_P0, ____, ____, 0),
+	A210_PAD(39, GPIO1_7, GPIO1, GMAC1, SPI0, PWM0, CDBG, SATA_P0, ____, ____, 0),
+	A210_PAD(40, GPIO1_8, GPIO1, GMAC1, SPI0, PDM, CDBG, SATA_P0, ____, ____, 0),
+	A210_PAD(41, GPIO1_9, GPIO1, GMAC1, SPI0, PWM0, ____, SATA_P0, GMAC0, ____, 0),
+	A210_PAD(42, GPIO1_10, GPIO1, GMAC1, SPI0, PWM0, ____, SATA_P0, ____, ____, 0),
+	A210_PAD(43, GPIO1_11, GPIO1, GMAC1, QSPI0, PDM, I2S0, ISP0, PWM0, ____, 0),
+	A210_PAD(44, GPIO1_12, GPIO1, GMAC1, QSPI0, PDM, I2S0, ISP0, ____, ____, 0),
+	A210_PAD(45, GPIO1_13, GPIO1, GMAC1, QSPI0, PDM, I2S0, ISP0, ____, ____, 0),
+	A210_PAD(46, GPIO1_14, GPIO1, GMAC1, ____, PDM, I2S0, ISP0, ____, ____, 0),
+	A210_PAD(47, GPIO1_15, GPIO1, GMAC1, SDIO, PDM, I2S0, ISP0, ____, ____, 0),
+	A210_PAD(48, GPIO1_16, GPIO1, GMAC0, ____, ____, ____, SDIO, ____, ____, 0),
+};
+
+static const struct pinctrl_pin_desc a210_group2_pins[] = {
+	A210_PAD(0, GPIO2_0, GPIO2, UART4, UART4_IR, PWM2, ____, I2C3, ____, ____, 0),
+	A210_PAD(1, GPIO2_1, GPIO2, UART4, UART4_IR, PWM2, ____, I2C3, ____, ____, 0),
+	A210_PAD(2, GPIO2_2, GPIO2, UART5, UART5_IR, PWM2, ____, I2C5, I2S1, ____, 0),
+	A210_PAD(3, GPIO2_3, GPIO2, UART5, UART5_IR, PWM2, ____, I2C5, I2S1, ____, 0),
+	A210_PAD(4, GPIO2_4, GPIO2, UART6, UART6_IR, PWM2, ____, I2C6, I2S1, ____, 0),
+	A210_PAD(5, GPIO2_5, GPIO2, UART6, UART6_IR, PWM2, ____, I2C6, I2S1, ____, 0),
+	A210_PAD(6, GPIO2_6, GPIO2, UART7, UART7_IR, PWM2, SEN_VCLK, I2C4, I2S1, ____, 0),
+	A210_PAD(7, GPIO2_7, GPIO2, UART7, UART7_IR, PWM2, SEN_VCLK, I2C4, ____, ____, 0),
+	A210_PAD(8, GPIO2_8, GPIO2, I2S2, ____, SPI1, UART6, I2C6, PWM2, ____, 0),
+	A210_PAD(9, GPIO2_9, GPIO2, I2S2, ____, SPI1, UART6, I2C6, PWM2, ____, 0),
+	A210_PAD(10, GPIO2_10, GPIO2, I2S2, PWM1, SPI1, UART9, I2C7, ____, ____, 0),
+	A210_PAD(11, GPIO2_11, GPIO2, I2S2, PWM1, SPI1, UART9, I2C7, ____, ____, 0),
+	A210_PAD(12, GPIO2_12, GPIO2, I2S2, PWM1, SPI1, UART8, I2C7, ____, ____, 0),
+	A210_PAD(13, GPIO2_13, GPIO2, I2S3, PWM1, ____, ____, ____, ____, ____, 0),
+	A210_PAD(14, GPIO2_14, GPIO2, I2S3, PWM1, ____, ____, ____, ____, ____, 0),
+	A210_PAD(15, GPIO2_15, GPIO2, I2S3, ____, ____, ____, ____, ____, ____, 0),
+	A210_PAD(16, GPIO2_16, GPIO2, I2S3, ____, ____, ____, ____, ____, ____, 0),
+	A210_PAD(17, GPIO2_17, GPIO2, I2S3, SPI1, I2C4, UART8, I2C7, ____, ____, 0),
+	A210_PAD(18, GPIO2_18, GPIO2, I2S3, SPI1, I2C4, PWM2, UART5, UART5_IR, ____, 0),
+	A210_PAD(19, GPIO2_19, GPIO2, I2S3, SPI1, ____, PWM1, UART5, UART5_IR, ____, 0),
+	A210_PAD(20, GPIO2_20, GPIO2, I2S3, ____, ____, ____, ____, ____, ____, 0),
+	A210_PAD(21, GPIO2_21, GPIO2, I2S3, SPI1, I2C3, PWM1, UART8, ____, ____, 0),
+	A210_PAD(22, GPIO2_22, GPIO2, I2S3, SPI1, I2C3, PWM1, UART8, ____, ____, 0),
+	A210_PAD(23, GPIO2_23, GPIO2, I2S3, PWM1, ____, ____, ____, ____, ____, 0),
+	A210_PAD(24, GPIO2_24, GPIO2, I2C3, UART5, ____, ____, ____, ____, ____, 0),
+	A210_PAD(25, GPIO2_25, GPIO2, I2C3, UART5, ____, HDMI, QSPI1, PWM2, ____, 0),
+	A210_PAD(26, GPIO2_26, GPIO2, I2C4, UART6, ____, ____, ____, ____, ____, 0),
+	A210_PAD(27, GPIO2_27, GPIO2, I2C4, UART6, ____, ____, ____, ____, ____, 0),
+	A210_PAD(28, GPIO2_28, GPIO2, I2C5, UART7, PWM1, ____, QSPI1, ____, ____, 0),
+	A210_PAD(29, GPIO2_29, GPIO2, I2C5, UART7, PWM1, ____, QSPI1, ____, ____, 0),
+	A210_PAD(30, GPIO2_30, GPIO2, I2C6, UART8, PWM1, HDMI, QSPI1, I2S3, ____, 0),
+	A210_PAD(31, GPIO2_31, GPIO2, I2C6, UART8, PWM1, HDMI, QSPI1, I2S3, ____, 0),
+	A210_PAD(32, GPIO3_0, GPIO3, I2C7, UART9, PWM1, CAN2, QSPI1, I2S3, SEN_VCLK, 0),
+	A210_PAD(33, GPIO3_1, GPIO3, I2C7, UART9, PWM1, CAN2, QSPI1, I2S3, SEN_VCLK, 0),
+	A210_PAD(34, GPIO3_2, GPIO3, QSPI1, UART8, UART8_IR, ____, ____, I2S3, PWM1, 0),
+	A210_PAD(35, GPIO3_3, GPIO3, QSPI1, UART8, UART8_IR, ____, ____, I2S3, PWM1, 0),
+	A210_PAD(36, GPIO3_4, GPIO3, QSPI1, UART9, UART9_IR, ____, ____, I2S3, PWM2, 0),
+	A210_PAD(37, GPIO3_5, GPIO3, QSPI1, UART9, UART9_IR, ____, ____, I2S3, PWM2, 0),
+	A210_PAD(38, GPIO3_6, GPIO3, QSPI1, I2S1, I2C7_SMB, ____, DPTX, I2S3, PWM2, 0),
+	A210_PAD(39, GPIO3_7, GPIO3, QSPI1, I2S1, I2C7_SMB, UART7, I2C5, I2S3, PWM2, 0),
+	A210_PAD(40, GPIO3_8, GPIO3, QSPI1, I2S1, I2C7_SMB, UART7, I2C5, I2S3, PWM2, 0),
+	A210_PAD(41, GPIO3_9, GPIO3, UART4, I2S1, I2C7_SMB, UART5, DPTX, ____, PWM2, 0),
+	A210_PAD(42, GPIO3_10, GPIO3, UART4, I2S1, I2C7_SMB, UART5, USB31, ____, ____, 0),
+};
+
+static const struct pinctrl_pin_desc a210_group3_pins[] = {
+	A210_PAD(0, SDIO_CLK, SDIO, GPIO4, ____, ____, ____, ____, ____, ____, 0),
+	A210_PAD(1, SDIO_CMD, SDIO, GPIO4, ____, ____, ____, ____, ____, ____, 0),
+	A210_PAD(2, SDIO_DAT0, SDIO, GPIO4, ____, ____, ____, ____, ____, ____, 0),
+	A210_PAD(3, SDIO_DAT1, SDIO, GPIO4, ____, ____, ____, ____, ____, ____, 0),
+	A210_PAD(4, SDIO_DAT2, SDIO, GPIO4, ____, ____, ____, ____, ____, ____, 0),
+	A210_PAD(5, SDIO_DAT3, SDIO, GPIO4, ____, ____, ____, ____, ____, ____, 0),
+};
+
+static const struct a210_pad_group a210_group0 = {
+	/* aon */
+	.name = "a210-group0",
+	.pins = a210_group0_pins,
+	.npins = ARRAY_SIZE(a210_group0_pins),
+	.offset_mux = 0x400,
+	.mask_mux = 0xf,
+	.offset_cfg = 0x0,
+	.mask_cfg = 0xffff,
+	.type = A210_PADCTRL_AON,
+};
+
+static const struct a210_pad_group a210_group1 = {
+	/* peri1 */
+	.name = "a210-group1",
+	.pins = a210_group1_pins,
+	.npins = ARRAY_SIZE(a210_group1_pins),
+	.offset_mux = 0x400,
+	.mask_mux = 0xf,
+	.offset_cfg = 0x0,
+	.mask_cfg = 0xffff,
+	.type = A210_PADCTRL_0,
+};
+
+static const struct a210_pad_group a210_group2 = {
+	/* peri2 */
+	.name = "a210-group2",
+	.pins = a210_group2_pins,
+	.npins = ARRAY_SIZE(a210_group2_pins),
+	.offset_mux = 0x400,
+	.mask_mux = 0xf,
+	.offset_cfg = 0x0,
+	.mask_cfg = 0xffff,
+	.type = A210_PADCTRL_1,
+};
+
+static const struct a210_pad_group a210_group3 = {
+	/* PERI3 has one shared mux bit for all six SDIO pads. */
+	.name = "a210-group3",
+	.pins = a210_group3_pins,
+	.npins = ARRAY_SIZE(a210_group3_pins),
+	.offset_mux = 0x200,
+	.mask_mux = 0x1,
+	.offset_cfg = 0x0,
+	.mask_cfg = U32_MAX,
+	.type = A210_PADCTRL_2,
+};
+
+static int a210_pinctrl_get_groups_count(struct pinctrl_dev *pctldev)
+{
+	struct a210_pinctrl *pp = pinctrl_dev_get_drvdata(pctldev);
+
+	return pp->type == A210_PADCTRL_2 ? 1 : pp->desc.npins;
+}
+
+static const char *a210_pinctrl_get_group_name(struct pinctrl_dev *pctldev, unsigned int gsel)
+{
+	struct a210_pinctrl *pp = pinctrl_dev_get_drvdata(pctldev);
+
+	return pp->type == A210_PADCTRL_2 ? "sdio" : pp->desc.pins[gsel].name;
+}
+
+static const unsigned int a210_sdio_pins[] = { 0, 1, 2, 3, 4, 5 };
+
+static int a210_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
+				       unsigned int gsel,
+				       const unsigned int **pins,
+				       unsigned int *npins)
+{
+	struct a210_pinctrl *pp = pinctrl_dev_get_drvdata(pctldev);
+
+	if (pp->type == A210_PADCTRL_2) {
+		*pins = a210_sdio_pins;
+		*npins = ARRAY_SIZE(a210_sdio_pins);
+	} else {
+		*pins = &pp->desc.pins[gsel].number;
+		*npins = 1;
+	}
+	return 0;
+}
+
+#ifdef CONFIG_DEBUG_FS
+static void a210_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s, unsigned int pin)
+{
+	struct a210_pinctrl *pp = pinctrl_dev_get_drvdata(pctldev);
+	void __iomem *padcfg = a210_padcfg(pp, pin);
+	void __iomem *muxcfg = a210_muxcfg(pp, pin);
+	u32 pad;
+	u32 mux;
+
+	if ((uintptr_t)pin_desc_get(pctldev, pin)->drv_data & A210_PAD_NO_PADCFG)
+		return;
+
+	scoped_guard(raw_spinlock_irqsave, &pp->lock) {
+		pad = readl_relaxed(padcfg);
+		mux = readl_relaxed(muxcfg);
+	}
+
+	seq_printf(s, "[padcfg=0x%08x muxcfg=0x%08x]", pad, mux);
+}
+#else
+#define a210_pin_dbg_show NULL
+#endif
+
+static const struct pinctrl_ops a210_pinctrl_ops = {
+	.get_groups_count = a210_pinctrl_get_groups_count,
+	.get_group_name = a210_pinctrl_get_group_name,
+	.get_group_pins = a210_pinctrl_get_group_pins,
+	.pin_dbg_show = a210_pin_dbg_show,
+	.dt_node_to_map = pinconf_generic_dt_node_to_map_all,
+	.dt_free_map = pinconf_generic_dt_free_map,
+};
+
+static const u8 a210_drive_strength_in_ma[16] = {
+	1, 2, 3, 5, 7, 8, 10, 12, 13, 15, 16, 18, 20, 21, 23, 25,
+};
+
+static int a210_drive_strength_from_ma(u32 arg)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(a210_drive_strength_in_ma); i++)
+		if (arg == a210_drive_strength_in_ma[i])
+			return i;
+	return -EINVAL;
+}
+
+static int a210_padcfg_rmw(struct a210_pinctrl *pp, unsigned int pin, u32 mask, u32 value)
+{
+	void __iomem *padcfg = a210_padcfg(pp, pin);
+	unsigned int shift = a210_padcfg_shift(pp, pin);
+	u32 tmp;
+
+	mask <<= shift;
+	value <<= shift;
+
+	scoped_guard(raw_spinlock_irqsave, &pp->lock) {
+		tmp = readl_relaxed(padcfg);
+		tmp = (tmp & ~mask) | value;
+		writel_relaxed(tmp, padcfg);
+#ifdef CONFIG_PM_SLEEP
+		pp->cfg_state[pin * hweight32(pp->mask_cfg) / 32].mask |= mask;
+#endif
+	}
+	return 0;
+}
+
+static int a210_sdio_pinconf_get(struct a210_pinctrl *pp, unsigned int pin,
+				 unsigned long *config)
+{
+	enum pin_config_param param = pinconf_to_config_param(*config);
+	u32 value = readl_relaxed(a210_padcfg(pp, pin)) & A210_SDIO_BIAS;
+
+	switch (param) {
+	case PIN_CONFIG_BIAS_DISABLE:
+		if (value)
+			return -EINVAL;
+		break;
+	case PIN_CONFIG_BIAS_PULL_UP:
+		if (value != A210_SDIO_PULL_UP)
+			return -EINVAL;
+		break;
+	case PIN_CONFIG_BIAS_PULL_DOWN:
+		if (value != A210_SDIO_PULL_DOWN)
+			return -EINVAL;
+		break;
+	default:
+		return -ENOTSUPP;
+	}
+
+	*config = pinconf_to_config_packed(param, param != PIN_CONFIG_BIAS_DISABLE);
+	return 0;
+}
+
+static int a210_sdio_pinconf_set(struct a210_pinctrl *pp, unsigned int pin,
+				 unsigned long *configs, unsigned int num_configs)
+{
+	u32 value = 0;
+	unsigned int i;
+
+	for (i = 0; i < num_configs; i++) {
+		enum pin_config_param param = pinconf_to_config_param(configs[i]);
+		u32 arg = pinconf_to_config_argument(configs[i]);
+
+		switch (param) {
+		case PIN_CONFIG_BIAS_DISABLE:
+			value = 0;
+			break;
+		case PIN_CONFIG_BIAS_PULL_UP:
+		case PIN_CONFIG_BIAS_PULL_DOWN:
+			if (arg != 1)
+				return -EINVAL;
+			value = param == PIN_CONFIG_BIAS_PULL_UP ?
+				A210_SDIO_PULL_UP : A210_SDIO_PULL_DOWN;
+			break;
+		default:
+			return -ENOTSUPP;
+		}
+	}
+
+	if (!num_configs)
+		return 0;
+
+	return a210_padcfg_rmw(pp, pin, A210_SDIO_BIAS, value);
+}
+
+static int a210_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin, unsigned long *config)
+{
+	struct a210_pinctrl *pp = pinctrl_dev_get_drvdata(pctldev);
+	const struct pin_desc *desc = pin_desc_get(pctldev, pin);
+	bool enabled;
+	int param;
+	u32 value;
+	u32 arg;
+
+	if ((uintptr_t)desc->drv_data & A210_PAD_NO_PADCFG)
+		return -ENOTSUPP;
+	if (pp->type == A210_PADCTRL_2)
+		return a210_sdio_pinconf_get(pp, pin, config);
+
+	value = readl_relaxed(a210_padcfg(pp, pin));
+	value = (value >> a210_padcfg_shift(pp, pin)) & GENMASK(9, 0);
+
+	param = pinconf_to_config_param(*config);
+	switch (param) {
+	case PIN_CONFIG_BIAS_DISABLE:
+		enabled = !(value & (A210_PADCFG_SPU | A210_PADCFG_PE));
+		arg = 0;
+		break;
+	case PIN_CONFIG_BIAS_PULL_DOWN:
+		enabled = (value & A210_PADCFG_BIAS) == A210_PADCFG_PE;
+		arg = enabled ? A210_PULL_DOWN_OHM : 0;
+		break;
+	case PIN_CONFIG_BIAS_PULL_UP:
+		if (value & A210_PADCFG_SPU) {
+			enabled = true;
+			arg = A210_PULL_STRONG_OHM;
+		} else if ((value & (A210_PADCFG_PE | A210_PADCFG_PS)) ==
+			   (A210_PADCFG_PE | A210_PADCFG_PS)) {
+			enabled = true;
+			arg = A210_PULL_UP_OHM;
+		} else {
+			enabled = false;
+			arg = 0;
+		}
+		break;
+	case PIN_CONFIG_DRIVE_STRENGTH:
+		enabled = true;
+		arg = a210_drive_strength_in_ma[value & A210_PADCFG_DS];
+		break;
+	case PIN_CONFIG_INPUT_ENABLE:
+		enabled = value & A210_PADCFG_IE;
+		arg = enabled ? 1 : 0;
+		break;
+	case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+		enabled = value & A210_PADCFG_ST;
+		arg = enabled ? 1 : 0;
+		break;
+	case PIN_CONFIG_SLEW_RATE:
+		enabled = true;
+		arg = !!(value & A210_PADCFG_SL);
+		break;
+	default:
+		return -ENOTSUPP;
+	}
+
+	*config = pinconf_to_config_packed(param, arg);
+	return enabled ? 0 : -EINVAL;
+}
+
+static int a210_pinconf_group_get(struct pinctrl_dev *pctldev, unsigned int gsel,
+				  unsigned long *config)
+{
+	const unsigned int *pins;
+	unsigned int npins, i;
+	unsigned long first = *config;
+	int ret;
+
+	a210_pinctrl_get_group_pins(pctldev, gsel, &pins, &npins);
+	for (i = 0; i < npins; i++) {
+		unsigned long value = *config;
+
+		ret = a210_pinconf_get(pctldev, pins[i], &value);
+		if (ret)
+			return ret;
+		if (i && value != first)
+			return -ENOTSUPP;
+		first = value;
+	}
+	*config = first;
+	return 0;
+}
+
+static int a210_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, unsigned long *configs,
+			    unsigned int num_configs)
+{
+	struct a210_pinctrl *pp = pinctrl_dev_get_drvdata(pctldev);
+	const struct pin_desc *desc = pin_desc_get(pctldev, pin);
+	unsigned int i;
+	u16 mask, value;
+
+	if ((uintptr_t)desc->drv_data & A210_PAD_NO_PADCFG)
+		return -ENOTSUPP;
+	if (pp->type == A210_PADCTRL_2)
+		return a210_sdio_pinconf_set(pp, pin, configs, num_configs);
+
+	mask = 0;
+	value = 0;
+	for (i = 0; i < num_configs; i++) {
+		int param = pinconf_to_config_param(configs[i]);
+		u32 arg = pinconf_to_config_argument(configs[i]);
+
+		switch (param) {
+		case PIN_CONFIG_BIAS_DISABLE:
+			mask |= A210_PADCFG_BIAS;
+			value &= ~A210_PADCFG_BIAS;
+			break;
+		case PIN_CONFIG_BIAS_PULL_DOWN:
+			if (arg != 1 && arg != A210_PULL_DOWN_OHM)
+				return -EINVAL;
+			mask |= A210_PADCFG_BIAS;
+			value &= ~A210_PADCFG_BIAS;
+			value |= A210_PADCFG_PE;
+			break;
+		case PIN_CONFIG_BIAS_PULL_UP:
+			if (arg != 1 && arg != A210_PULL_UP_OHM && arg != A210_PULL_STRONG_OHM)
+				return -EINVAL;
+			mask |= A210_PADCFG_BIAS;
+			value &= ~A210_PADCFG_BIAS;
+			if (arg == A210_PULL_STRONG_OHM)
+				value |= A210_PADCFG_SPU;
+			else
+				value |= A210_PADCFG_PE | A210_PADCFG_PS;
+			break;
+		case PIN_CONFIG_DRIVE_STRENGTH: {
+			int strength = a210_drive_strength_from_ma(arg);
+
+			if (strength < 0)
+				return strength;
+			mask |= A210_PADCFG_DS;
+			value &= ~A210_PADCFG_DS;
+			value |= strength;
+			break;
+		}
+		case PIN_CONFIG_INPUT_ENABLE:
+			mask |= A210_PADCFG_IE;
+			if (arg)
+				value |= A210_PADCFG_IE;
+			else
+				value &= ~A210_PADCFG_IE;
+			break;
+		case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+			mask |= A210_PADCFG_ST;
+			if (arg)
+				value |= A210_PADCFG_ST;
+			else
+				value &= ~A210_PADCFG_ST;
+			break;
+		case PIN_CONFIG_SLEW_RATE:
+			if (arg > 1)
+				return -EINVAL;
+			mask |= A210_PADCFG_SL;
+			if (arg)
+				value |= A210_PADCFG_SL;
+			else
+				value &= ~A210_PADCFG_SL;
+			break;
+		default:
+			return -ENOTSUPP;
+		}
+	}
+
+	return a210_padcfg_rmw(pp, pin, mask, value);
+}
+
+static int a210_pinconf_group_set(struct pinctrl_dev *pctldev, unsigned int gsel,
+				  unsigned long *configs, unsigned int num_configs)
+{
+	const unsigned int *pins;
+	unsigned int npins, i;
+	int ret;
+
+	a210_pinctrl_get_group_pins(pctldev, gsel, &pins, &npins);
+	for (i = 0; i < npins; i++) {
+		ret = a210_pinconf_set(pctldev, pins[i], configs, num_configs);
+		if (ret)
+			return ret;
+	}
+	return 0;
+}
+
+#ifdef CONFIG_DEBUG_FS
+static void a210_pinconf_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s, unsigned int pin)
+{
+	struct a210_pinctrl *pp = pinctrl_dev_get_drvdata(pctldev);
+	u32 value;
+
+	if ((uintptr_t)pin_desc_get(pctldev, pin)->drv_data & A210_PAD_NO_PADCFG)
+		return;
+
+	value = readl_relaxed(a210_padcfg(pp, pin));
+
+	if (pp->type != A210_PADCTRL_2)
+		value = (value >> a210_padcfg_shift(pp, pin)) & GENMASK(9, 0);
+
+	seq_printf(s, " [0x%03x]", value);
+}
+#else
+#define a210_pinconf_dbg_show NULL
+#endif
+
+static const struct pinconf_ops a210_pinconf_ops = {
+	.pin_config_get = a210_pinconf_get,
+	.pin_config_group_get = a210_pinconf_group_get,
+	.pin_config_set = a210_pinconf_set,
+	.pin_config_group_set = a210_pinconf_group_set,
+	.pin_config_dbg_show = a210_pinconf_dbg_show,
+	.is_generic = true,
+};
+
+static int a210_pinmux_set(struct a210_pinctrl *pp, unsigned int pin, unsigned long muxdata,
+			   enum a210_muxtype muxtype)
+{
+	void __iomem *muxcfg = a210_muxcfg(pp, pin);
+	unsigned int shift = a210_muxcfg_shift(pp, pin);
+	u32 mask, value, tmp;
+
+	for (value = 0; muxdata; muxdata >>= 7, value++) {
+		if ((muxdata & GENMASK(6, 0)) == muxtype)
+			break;
+	}
+	if (!muxdata) {
+		dev_err(pp->pctl->dev, "invalid mux %s for pin %s\n", a210_muxtype_string[muxtype],
+			pin_get_name(pp->pctl, pin));
+		return -EINVAL;
+	}
+
+	mask = pp->mask_mux << shift;
+	value = value << shift;
+
+	scoped_guard(raw_spinlock_irqsave, &pp->lock) {
+		tmp = readl_relaxed(muxcfg);
+		tmp = (tmp & ~mask) | value;
+		writel_relaxed(tmp, muxcfg);
+#ifdef CONFIG_PM_SLEEP
+		pp->mux_state[pin * hweight32(pp->mask_mux) / 32].mask |= mask;
+#endif
+	}
+
+	return 0;
+}
+
+static int a210_pinmux_set_mux(struct pinctrl_dev *pctldev, unsigned int fsel, unsigned int gsel)
+{
+	struct a210_pinctrl *pp = pinctrl_dev_get_drvdata(pctldev);
+	const struct function_desc *func = pinmux_generic_get_function(pctldev, fsel);
+
+	return a210_pinmux_set(pp, pp->desc.pins[gsel].number,
+			       (uintptr_t)pp->desc.pins[gsel].drv_data & A210_PAD_MUXDATA,
+			       *(enum a210_muxtype *)func->data);
+}
+
+static bool a210_mux_is_gpio(enum a210_muxtype muxtype)
+{
+	switch (muxtype) {
+	case A210_MUX_AOGPIO0:
+	case A210_MUX_AOGPIO1:
+	case A210_MUX_GPIO0:
+	case A210_MUX_GPIO1:
+	case A210_MUX_GPIO2:
+	case A210_MUX_GPIO3:
+	case A210_MUX_GPIO4:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static int a210_gpio_request_enable(struct pinctrl_dev *pctldev, struct pinctrl_gpio_range *range,
+				    unsigned int offset)
+{
+	struct a210_pinctrl *pp = pinctrl_dev_get_drvdata(pctldev);
+	const struct pin_desc *desc = pin_desc_get(pctldev, offset);
+	unsigned long muxdata = (uintptr_t)desc->drv_data & A210_PAD_MUXDATA;
+
+	if (pp->type == A210_PADCTRL_2)
+		return -EOPNOTSUPP;
+
+	for (; muxdata; muxdata >>= 7) {
+		enum a210_muxtype muxtype = muxdata & GENMASK(6, 0);
+
+		if (a210_mux_is_gpio(muxtype))
+			return a210_pinmux_set(pp, offset,
+					       (uintptr_t)desc->drv_data & A210_PAD_MUXDATA,
+					       muxtype);
+	}
+
+	dev_err(pp->pctl->dev, "no GPIO mux for pin %s\n", desc->name);
+
+	return -EINVAL;
+}
+
+static int a210_gpio_set_direction(struct pinctrl_dev *pctldev, struct pinctrl_gpio_range *range,
+				   unsigned int offset, bool input)
+{
+	struct a210_pinctrl *pp = pinctrl_dev_get_drvdata(pctldev);
+
+	if (pp->type == A210_PADCTRL_2)
+		return -EOPNOTSUPP;
+
+	return a210_padcfg_rmw(pp, offset, A210_PADCFG_IE, input ? A210_PADCFG_IE : 0);
+}
+
+static const struct pinmux_ops a210_pinmux_ops = {
+	.get_functions_count = pinmux_generic_get_function_count,
+	.get_function_name = pinmux_generic_get_function_name,
+	.get_function_groups = pinmux_generic_get_function_groups,
+	.function_is_gpio = pinmux_generic_function_is_gpio,
+	.set_mux = a210_pinmux_set_mux,
+	.gpio_request_enable = a210_gpio_request_enable,
+	.gpio_set_direction = a210_gpio_set_direction,
+	.strict = true,
+};
+
+struct a210_function {
+	struct pinfunction function;
+	enum a210_muxtype type;
+};
+
+static bool a210_pin_has_function(const struct pinctrl_pin_desc *pin,
+				  enum a210_muxtype type)
+{
+	unsigned long muxdata = (uintptr_t)pin->drv_data & A210_PAD_MUXDATA;
+
+	for (; muxdata; muxdata >>= 7)
+		if ((muxdata & GENMASK(6, 0)) == type)
+			return true;
+	return false;
+}
+
+static int a210_register_functions(struct a210_pinctrl *pp)
+{
+	struct device *dev = pp->pctl->dev;
+	unsigned int ngroups = a210_pinctrl_get_groups_count(pp->pctl);
+	enum a210_muxtype type;
+
+	for (type = A210_MUX_AOUART; type < ARRAY_SIZE(a210_muxtype_string); type++) {
+		struct a210_function *function;
+		const char **groups;
+		unsigned int i, count = 0;
+		int ret;
+
+		for (i = 0; i < ngroups; i++)
+			count += a210_pin_has_function(&pp->desc.pins[i], type);
+		if (!count)
+			continue;
+
+		function = devm_kzalloc(dev, sizeof(*function), GFP_KERNEL);
+		if (!function)
+			return -ENOMEM;
+		groups = devm_kcalloc(dev, count, sizeof(*groups), GFP_KERNEL);
+		if (!groups)
+			return -ENOMEM;
+		function->type = type;
+		function->function.name = a210_muxtype_string[type];
+		function->function.groups = groups;
+		function->function.ngroups = count;
+		if (a210_mux_is_gpio(type))
+			function->function.flags = PINFUNCTION_FLAG_GPIO;
+		count = 0;
+		for (i = 0; i < ngroups; i++)
+			if (a210_pin_has_function(&pp->desc.pins[i], type))
+				groups[count++] = a210_pinctrl_get_group_name(pp->pctl, i);
+		ret = pinmux_generic_add_pinfunction(pp->pctl, &function->function,
+						     &function->type);
+		if (ret < 0)
+			return ret;
+	}
+	return 0;
+}
+
+static int a210_pinctrl_enable_clock(struct a210_pinctrl *pp)
+{
+	int ret;
+
+	if (pp->clk_enabled)
+		return 0;
+
+	ret = clk_prepare_enable(pp->clk);
+	if (!ret)
+		pp->clk_enabled = true;
+	return ret;
+}
+
+static void a210_pinctrl_disable_clock(void *data)
+{
+	struct a210_pinctrl *pp = data;
+
+	if (pp->clk_enabled) {
+		clk_disable_unprepare(pp->clk);
+		pp->clk_enabled = false;
+	}
+}
+
+static int a210_pinctrl_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	const struct a210_pad_group *group;
+	struct a210_pinctrl *pp;
+	int ret;
+
+	group = device_get_match_data(dev);
+	if (!group)
+		return dev_err_probe(dev, -EINVAL, "missing pad group data\n");
+
+	pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL);
+	if (!pp)
+		return -ENOMEM;
+
+	pp->base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(pp->base))
+		return PTR_ERR(pp->base);
+
+	pp->desc.name = group->name;
+	pp->desc.pins = group->pins;
+	pp->desc.npins = group->npins;
+	pp->offset_mux = group->offset_mux;
+	pp->mask_mux = group->mask_mux;
+	pp->offset_cfg = group->offset_cfg;
+	pp->mask_cfg = group->mask_cfg;
+	pp->type = group->type;
+	pp->desc.pctlops = &a210_pinctrl_ops;
+	pp->desc.pmxops = &a210_pinmux_ops;
+	pp->desc.confops = &a210_pinconf_ops;
+	pp->desc.owner = THIS_MODULE;
+	raw_spin_lock_init(&pp->lock);
+
+	pp->clk = devm_clk_get(dev, "pclk");
+	if (IS_ERR(pp->clk))
+		return dev_err_probe(dev, PTR_ERR(pp->clk), "error getting clock\n");
+
+	ret = a210_pinctrl_enable_clock(pp);
+	if (ret)
+		return dev_err_probe(dev, ret, "could not enable padctrl clock\n");
+	ret = devm_add_action_or_reset(dev, a210_pinctrl_disable_clock, pp);
+	if (ret)
+		return ret;
+
+	platform_set_drvdata(pdev, pp);
+	ret = devm_pinctrl_register_and_init(dev, &pp->desc, pp, &pp->pctl);
+	if (ret)
+		return dev_err_probe(dev, ret, "could not register pinctrl driver\n");
+
+	ret = a210_register_functions(pp);
+	if (ret)
+		return ret;
+
+	return pinctrl_enable(pp->pctl);
+}
+
+#ifdef CONFIG_PM_SLEEP
+static void a210_pinctrl_save_regs(struct a210_register_state *state,
+				   unsigned int count, void __iomem *base)
+{
+	unsigned int i;
+
+	for (i = 0; i < count; i++)
+		if (state[i].mask)
+			state[i].value = readl(base + i * sizeof(u32)) & state[i].mask;
+}
+
+static void a210_pinctrl_restore_regs(const struct a210_register_state *state,
+				      unsigned int count, void __iomem *base)
+{
+	unsigned int i;
+
+	for (i = 0; i < count; i++) {
+		u32 value;
+
+		if (!state[i].mask)
+			continue;
+		value = readl(base + i * sizeof(u32));
+		value = (value & ~state[i].mask) | state[i].value;
+		writel(value, base + i * sizeof(u32));
+	}
+}
+
+static int a210_pinctrl_suspend(struct device *dev)
+{
+	struct a210_pinctrl *pp = dev_get_drvdata(dev);
+
+	if (!pp->clk_enabled)
+		return 0;
+
+	scoped_guard(raw_spinlock_irqsave, &pp->lock) {
+		a210_pinctrl_save_regs(pp->cfg_state, ARRAY_SIZE(pp->cfg_state),
+				       pp->base + pp->offset_cfg);
+		a210_pinctrl_save_regs(pp->mux_state, ARRAY_SIZE(pp->mux_state),
+				       pp->base + pp->offset_mux);
+	}
+	if (pp->type != A210_PADCTRL_AON)
+		a210_pinctrl_disable_clock(pp);
+
+	return 0;
+}
+
+static int a210_pinctrl_resume(struct device *dev)
+{
+	struct a210_pinctrl *pp = dev_get_drvdata(dev);
+	int ret;
+
+	ret = a210_pinctrl_enable_clock(pp);
+	if (ret)
+		return dev_err_probe(dev, ret, "could not enable padctrl clock\n");
+
+	/* Leave firmware-owned and reserved fields at their current values. */
+	scoped_guard(raw_spinlock_irqsave, &pp->lock) {
+		a210_pinctrl_restore_regs(pp->cfg_state, ARRAY_SIZE(pp->cfg_state),
+					  pp->base + pp->offset_cfg);
+		a210_pinctrl_restore_regs(pp->mux_state, ARRAY_SIZE(pp->mux_state),
+					  pp->base + pp->offset_mux);
+	}
+	return 0;
+}
+#endif /* CONFIG_PM_SLEEP */
+
+static const struct dev_pm_ops a210_pinctrl_dev_pm_ops = {
+	SET_LATE_SYSTEM_SLEEP_PM_OPS(a210_pinctrl_suspend, a210_pinctrl_resume)
+};
+
+static const struct of_device_id a210_pinctrl_of_match[] = {
+	{ .compatible = "zhihe,a210-aon-pinctrl", .data = &a210_group0 },
+	{ .compatible = "zhihe,a210-peri1-pinctrl", .data = &a210_group1 },
+	{ .compatible = "zhihe,a210-peri2-pinctrl", .data = &a210_group2 },
+	{ .compatible = "zhihe,a210-peri3-pinctrl", .data = &a210_group3 },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, a210_pinctrl_of_match);
+
+static struct platform_driver a210_pinctrl_driver = {
+	.probe = a210_pinctrl_probe,
+	.driver = {
+		.name = "pinctrl-a210",
+		.of_match_table = a210_pinctrl_of_match,
+		.pm = &a210_pinctrl_dev_pm_ops,
+	},
+};
+module_platform_driver(a210_pinctrl_driver);
+
+MODULE_DESCRIPTION("Pinctrl driver for the ZhiHe A210 SoC");
+MODULE_AUTHOR("Zhiguo Zhu <zhiguo.zhu@linux.alibaba.com>");
+MODULE_LICENSE("GPL");

-- 
2.55.0



^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 10/18] dt-bindings: interrupt-controller: add Zhihe A210 PLIC
  2026-10-21 19:53 [PATCH 00/18] riscv: add initial support for Zhihe A210 and Melon Pi Han Gao via B4 Relay
                   ` (8 preceding siblings ...)
  2026-10-21 19:53 ` [PATCH 09/18] pinctrl: zhihe: add A210 support Han Gao via B4 Relay
@ 2026-10-21 19:53 ` Han Gao via B4 Relay
  2026-10-21 19:53 ` [PATCH 11/18] dt-bindings: riscv: add Melon Pi V1 and V2 Han Gao via B4 Relay
                   ` (7 subsequent siblings)
  17 siblings, 0 replies; 22+ messages in thread
From: Han Gao via B4 Relay @ 2026-10-21 19:53 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Zhiguo Zhu,
	Stephen Boyd, Brian Masney, Jerome Brunet, Philipp Zabel,
	Linus Walleij, Bartosz Golaszewski, Thomas Gleixner, Radu Rendec,
	Samuel Holland, Daniel Lezcano, Anup Patel, Icenowy Zheng,
	Drew Fustini
  Cc: devicetree, linux-kernel, linux-riscv, linux-clk, linux-gpio,
	Paul Walmsley, Han Gao

From: Zhiguo Zhu <zhiguo.zhu@linux.alibaba.com>

Add the A210 PLIC compatible with the thead,c900-plic fallback.

Signed-off-by: Zhiguo Zhu <zhiguo.zhu@linux.alibaba.com>
Signed-off-by: Han Gao <gaohan@iscas.ac.cn>
---
 .../devicetree/bindings/interrupt-controller/sifive,plic-1.0.0.yaml      | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/interrupt-controller/sifive,plic-1.0.0.yaml b/Documentation/devicetree/bindings/interrupt-controller/sifive,plic-1.0.0.yaml
index cde4bb691897..fd5b61db3f5f 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/sifive,plic-1.0.0.yaml
+++ b/Documentation/devicetree/bindings/interrupt-controller/sifive,plic-1.0.0.yaml
@@ -80,6 +80,7 @@ properties:
               - sophgo,sg2042-plic
               - sophgo,sg2044-plic
               - thead,th1520-plic
+              - zhihe,a210-plic
           - const: thead,c900-plic
       - items:
           - const: ultrarisc,dp1000-plic

-- 
2.55.0



^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 11/18] dt-bindings: riscv: add Melon Pi V1 and V2
  2026-10-21 19:53 [PATCH 00/18] riscv: add initial support for Zhihe A210 and Melon Pi Han Gao via B4 Relay
                   ` (9 preceding siblings ...)
  2026-10-21 19:53 ` [PATCH 10/18] dt-bindings: interrupt-controller: add Zhihe A210 PLIC Han Gao via B4 Relay
@ 2026-10-21 19:53 ` Han Gao via B4 Relay
  2026-10-21 19:53 ` [PATCH 12/18] dt-bindings: timer: add Zhihe A210 CLINT Han Gao via B4 Relay
                   ` (6 subsequent siblings)
  17 siblings, 0 replies; 22+ messages in thread
From: Han Gao via B4 Relay @ 2026-10-21 19:53 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Zhiguo Zhu,
	Stephen Boyd, Brian Masney, Jerome Brunet, Philipp Zabel,
	Linus Walleij, Bartosz Golaszewski, Thomas Gleixner, Radu Rendec,
	Samuel Holland, Daniel Lezcano, Anup Patel, Icenowy Zheng,
	Drew Fustini
  Cc: devicetree, linux-kernel, linux-riscv, linux-clk, linux-gpio,
	Paul Walmsley, Han Gao

From: Zhiguo Zhu <zhiguo.zhu@linux.alibaba.com>

Add bindings for Melon Pi V1 and V2 with the A210 module. V3 uses the
same board compatible as V2.

Signed-off-by: Zhiguo Zhu <zhiguo.zhu@linux.alibaba.com>
Co-developed-by: Han Gao <gaohan@iscas.ac.cn>
Signed-off-by: Han Gao <gaohan@iscas.ac.cn>
---
 Documentation/devicetree/bindings/riscv/zhihe.yaml | 27 ++++++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/Documentation/devicetree/bindings/riscv/zhihe.yaml b/Documentation/devicetree/bindings/riscv/zhihe.yaml
new file mode 100644
index 000000000000..92ac0a99a687
--- /dev/null
+++ b/Documentation/devicetree/bindings/riscv/zhihe.yaml
@@ -0,0 +1,27 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/riscv/zhihe.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: ZhiHe SoC-based boards
+
+maintainers:
+  - Zhiguo Zhu <zhiguo.zhu@linux.alibaba.com>
+
+properties:
+  $nodename:
+    const: '/'
+  compatible:
+    oneOf:
+      - description: Melon Pi V1 and V2 with the A210 SODIMM module
+        items:
+          - enum:
+              - zhihe,a210-melonpi-v1
+              - zhihe,a210-melonpi-v2
+          - const: zhihe,a210-som
+          - const: zhihe,a210
+
+additionalProperties: true
+
+...

-- 
2.55.0



^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 12/18] dt-bindings: timer: add Zhihe A210 CLINT
  2026-10-21 19:53 [PATCH 00/18] riscv: add initial support for Zhihe A210 and Melon Pi Han Gao via B4 Relay
                   ` (10 preceding siblings ...)
  2026-10-21 19:53 ` [PATCH 11/18] dt-bindings: riscv: add Melon Pi V1 and V2 Han Gao via B4 Relay
@ 2026-10-21 19:53 ` Han Gao via B4 Relay
  2026-10-21 19:53 ` [PATCH 13/18] riscv: dts: zhihe: add A210 core support Han Gao via B4 Relay
                   ` (5 subsequent siblings)
  17 siblings, 0 replies; 22+ messages in thread
From: Han Gao via B4 Relay @ 2026-10-21 19:53 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Zhiguo Zhu,
	Stephen Boyd, Brian Masney, Jerome Brunet, Philipp Zabel,
	Linus Walleij, Bartosz Golaszewski, Thomas Gleixner, Radu Rendec,
	Samuel Holland, Daniel Lezcano, Anup Patel, Icenowy Zheng,
	Drew Fustini
  Cc: devicetree, linux-kernel, linux-riscv, linux-clk, linux-gpio,
	Paul Walmsley, Han Gao

From: Han Gao <gaohan@iscas.ac.cn>

Add the A210 CLINT compatible with the thead,c900-clint fallback.

Signed-off-by: Han Gao <gaohan@iscas.ac.cn>
---
 Documentation/devicetree/bindings/timer/sifive,clint.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/timer/sifive,clint.yaml b/Documentation/devicetree/bindings/timer/sifive,clint.yaml
index 3673836e14de..805262bb6cd3 100644
--- a/Documentation/devicetree/bindings/timer/sifive,clint.yaml
+++ b/Documentation/devicetree/bindings/timer/sifive,clint.yaml
@@ -56,6 +56,7 @@ properties:
               - sophgo,sg2000-clint
               - sophgo,sg2002-clint
               - thead,th1520-clint
+              - zhihe,a210-clint
           - const: thead,c900-clint
       - items:
           - const: sifive,clint0

-- 
2.55.0



^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 13/18] riscv: dts: zhihe: add A210 core support
  2026-10-21 19:53 [PATCH 00/18] riscv: add initial support for Zhihe A210 and Melon Pi Han Gao via B4 Relay
                   ` (11 preceding siblings ...)
  2026-10-21 19:53 ` [PATCH 12/18] dt-bindings: timer: add Zhihe A210 CLINT Han Gao via B4 Relay
@ 2026-10-21 19:53 ` Han Gao via B4 Relay
  2026-10-21 19:53 ` [PATCH 14/18] riscv: dts: zhihe: add A210 UARTs Han Gao via B4 Relay
                   ` (4 subsequent siblings)
  17 siblings, 0 replies; 22+ messages in thread
From: Han Gao via B4 Relay @ 2026-10-21 19:53 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Zhiguo Zhu,
	Stephen Boyd, Brian Masney, Jerome Brunet, Philipp Zabel,
	Linus Walleij, Bartosz Golaszewski, Thomas Gleixner, Radu Rendec,
	Samuel Holland, Daniel Lezcano, Anup Patel, Icenowy Zheng,
	Drew Fustini
  Cc: devicetree, linux-kernel, linux-riscv, linux-clk, linux-gpio,
	Paul Walmsley, Han Gao

From: Zhiguo Zhu <zhiguo.zhu@linux.alibaba.com>

Add the A210 CPU clusters, caches, interrupt controllers and control
blocks.

Signed-off-by: Zhiguo Zhu <zhiguo.zhu@linux.alibaba.com>
Co-developed-by: Han Gao <gaohan@iscas.ac.cn>
Signed-off-by: Han Gao <gaohan@iscas.ac.cn>
---
 arch/riscv/boot/dts/zhihe/a210.dtsi | 495 ++++++++++++++++++++++++++++++++++++
 1 file changed, 495 insertions(+)

diff --git a/arch/riscv/boot/dts/zhihe/a210.dtsi b/arch/riscv/boot/dts/zhihe/a210.dtsi
new file mode 100644
index 000000000000..bbad51a3edb0
--- /dev/null
+++ b/arch/riscv/boot/dts/zhihe/a210.dtsi
@@ -0,0 +1,495 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+/*
+ * Copyright (C) 2021 Alibaba Group Holding Limited.
+ */
+
+#include <dt-bindings/clock/zhihe,a210-clk.h>
+#include <dt-bindings/clock/zhihe,a210-aon-clk.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/reset/zhihe,a210-resets.h>
+
+/ {
+	compatible = "zhihe,a210";
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	aon_rc: clock-aon-rc {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <26000000>;
+	};
+
+	osc_24m: clock-osc-24m {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <24000000>;
+		clock-output-names = "osc-24m";
+	};
+
+	osc_32k: clock-osc-32k {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <32768>;
+		clock-output-names = "osc-32k";
+	};
+
+	aon_110m: clock-osc-110m {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <110000000>;
+		clock-output-names = "aon-110m";
+	};
+
+	rc_24m: clock-rc-24m {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <24000000>;
+		clock-output-names = "rc-24m";
+	};
+
+	cpus: cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		timebase-frequency = <24000000>;
+
+		cpu-map {
+			cluster0 {
+				core0 {
+					cpu = <&c908_0>;
+				};
+
+				core1 {
+					cpu = <&c908_1>;
+				};
+
+				core2 {
+					cpu = <&c908_2>;
+				};
+
+				core3 {
+					cpu = <&c908_3>;
+				};
+			};
+
+			cluster1 {
+				core0 {
+					cpu = <&c920_4>;
+				};
+
+				core1 {
+					cpu = <&c920_5>;
+				};
+
+				core2 {
+					cpu = <&c920_6>;
+				};
+
+				core3 {
+					cpu = <&c920_7>;
+				};
+			};
+		};
+
+		c0_l2_cache: l2-cache0 {
+			compatible = "cache";
+			cache-block-size = <64>;
+			cache-level = <2>;
+			cache-sets = <512>;
+			cache-size = <524288>;
+			cache-unified;
+		};
+
+		c1_l2_cache: l2-cache1 {
+			compatible = "cache";
+			cache-block-size = <64>;
+			cache-level = <2>;
+			cache-sets = <1024>;
+			cache-size = <1048576>;
+			cache-unified;
+		};
+
+		c908_0: cpu@0 {
+			device_type = "cpu";
+			compatible = "thead,c908", "riscv";
+			reg = <0>;
+			clocks = <&clk C908_CPU_TO_CDE_CLK_MUX>;
+			d-cache-block-size = <64>;
+			d-cache-sets = <256>;
+			d-cache-size = <32768>;
+			i-cache-block-size = <64>;
+			i-cache-sets = <256>;
+			i-cache-size = <32768>;
+			mmu-type = "riscv,sv39";
+			next-level-cache = <&c0_l2_cache>;
+			riscv,cbom-block-size = <64>;
+			riscv,cbop-block-size = <64>;
+			riscv,cboz-block-size = <64>;
+			riscv,isa-base = "rv64i";
+			riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+					       "b", "v", "sscofpmf", "sstc",
+					       "svpbmt", "zba", "zbb", "zbc",
+					       "zbs", "zicbom", "zicbop",
+					       "zicboz", "zicntr", "zicsr",
+					       "zifencei", "zihpm";
+
+			cpu0_intc: interrupt-controller {
+				compatible = "riscv,cpu-intc";
+				#interrupt-cells = <1>;
+				interrupt-controller;
+			};
+		};
+
+		c908_1: cpu@1 {
+			device_type = "cpu";
+			compatible = "thead,c908", "riscv";
+			reg = <1>;
+			d-cache-block-size = <64>;
+			d-cache-sets = <256>;
+			d-cache-size = <32768>;
+			i-cache-block-size = <64>;
+			i-cache-sets = <256>;
+			i-cache-size = <32768>;
+			mmu-type = "riscv,sv39";
+			next-level-cache = <&c0_l2_cache>;
+			riscv,cbom-block-size = <64>;
+			riscv,cbop-block-size = <64>;
+			riscv,cboz-block-size = <64>;
+			riscv,isa-base = "rv64i";
+			riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+					       "b", "v", "sscofpmf", "sstc",
+					       "svpbmt", "zba", "zbb", "zbc",
+					       "zbs", "zicbom", "zicbop",
+					       "zicboz", "zicntr", "zicsr",
+					       "zifencei", "zihpm";
+
+			cpu1_intc: interrupt-controller {
+				compatible = "riscv,cpu-intc";
+				#interrupt-cells = <1>;
+				interrupt-controller;
+			};
+		};
+
+		c908_2: cpu@2 {
+			device_type = "cpu";
+			compatible = "thead,c908", "riscv";
+			reg = <2>;
+			d-cache-block-size = <64>;
+			d-cache-sets = <256>;
+			d-cache-size = <32768>;
+			i-cache-block-size = <64>;
+			i-cache-sets = <256>;
+			i-cache-size = <32768>;
+			mmu-type = "riscv,sv39";
+			next-level-cache = <&c0_l2_cache>;
+			riscv,cbom-block-size = <64>;
+			riscv,cbop-block-size = <64>;
+			riscv,cboz-block-size = <64>;
+			riscv,isa-base = "rv64i";
+			riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+					       "b", "v", "sscofpmf", "sstc",
+					       "svpbmt", "zba", "zbb", "zbc",
+					       "zbs", "zicbom", "zicbop",
+					       "zicboz", "zicntr", "zicsr",
+					       "zifencei", "zihpm";
+
+			cpu2_intc: interrupt-controller {
+				compatible = "riscv,cpu-intc";
+				#interrupt-cells = <1>;
+				interrupt-controller;
+			};
+		};
+
+		c908_3: cpu@3 {
+			device_type = "cpu";
+			compatible = "thead,c908", "riscv";
+			reg = <3>;
+			d-cache-block-size = <64>;
+			d-cache-sets = <256>;
+			d-cache-size = <32768>;
+			i-cache-block-size = <64>;
+			i-cache-sets = <256>;
+			i-cache-size = <32768>;
+			mmu-type = "riscv,sv39";
+			next-level-cache = <&c0_l2_cache>;
+			riscv,cbom-block-size = <64>;
+			riscv,cbop-block-size = <64>;
+			riscv,cboz-block-size = <64>;
+			riscv,isa-base = "rv64i";
+			riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+					       "b", "v", "sscofpmf", "sstc",
+					       "svpbmt", "zba", "zbb", "zbc",
+					       "zbs", "zicbom", "zicbop",
+					       "zicboz", "zicntr", "zicsr",
+					       "zifencei", "zihpm";
+
+			cpu3_intc: interrupt-controller {
+				compatible = "riscv,cpu-intc";
+				#interrupt-cells = <1>;
+				interrupt-controller;
+			};
+		};
+
+		c920_4: cpu@4 {
+			device_type = "cpu";
+			compatible = "thead,c920", "riscv";
+			reg = <4>;
+			clocks = <&clk C920_CPU_TO_CDE_CLK_MUX>;
+			d-cache-block-size = <64>;
+			d-cache-sets = <512>;
+			d-cache-size = <65536>;
+			i-cache-block-size = <64>;
+			i-cache-sets = <512>;
+			i-cache-size = <65536>;
+			mmu-type = "riscv,sv39";
+			next-level-cache = <&c1_l2_cache>;
+			riscv,cbom-block-size = <64>;
+			riscv,cbop-block-size = <64>;
+			riscv,cboz-block-size = <64>;
+			riscv,isa-base = "rv64i";
+			riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+					       "b", "v", "sscofpmf", "sstc",
+					       "svpbmt", "zba", "zbb", "zbc",
+					       "zbs", "zicbom", "zicbop",
+					       "zicboz", "zicntr", "zicsr",
+					       "zifencei", "zihpm";
+
+			cpu4_intc: interrupt-controller {
+				compatible = "riscv,cpu-intc";
+				#interrupt-cells = <1>;
+				interrupt-controller;
+			};
+		};
+
+		c920_5: cpu@5 {
+			device_type = "cpu";
+			compatible = "thead,c920", "riscv";
+			reg = <5>;
+			d-cache-block-size = <64>;
+			d-cache-sets = <512>;
+			d-cache-size = <65536>;
+			i-cache-block-size = <64>;
+			i-cache-sets = <512>;
+			i-cache-size = <65536>;
+			mmu-type = "riscv,sv39";
+			next-level-cache = <&c1_l2_cache>;
+			riscv,cbom-block-size = <64>;
+			riscv,cbop-block-size = <64>;
+			riscv,cboz-block-size = <64>;
+			riscv,isa-base = "rv64i";
+			riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+					       "b", "v", "sscofpmf", "sstc",
+					       "svpbmt", "zba", "zbb", "zbc",
+					       "zbs", "zicbom", "zicbop",
+					       "zicboz", "zicntr", "zicsr",
+					       "zifencei", "zihpm";
+
+			cpu5_intc: interrupt-controller {
+				compatible = "riscv,cpu-intc";
+				#interrupt-cells = <1>;
+				interrupt-controller;
+			};
+		};
+
+		c920_6: cpu@6 {
+			device_type = "cpu";
+			compatible = "thead,c920", "riscv";
+			reg = <6>;
+			d-cache-block-size = <64>;
+			d-cache-sets = <512>;
+			d-cache-size = <65536>;
+			i-cache-block-size = <64>;
+			i-cache-sets = <512>;
+			i-cache-size = <65536>;
+			mmu-type = "riscv,sv39";
+			next-level-cache = <&c1_l2_cache>;
+			riscv,cbom-block-size = <64>;
+			riscv,cbop-block-size = <64>;
+			riscv,cboz-block-size = <64>;
+			riscv,isa-base = "rv64i";
+			riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+					       "b", "v", "sscofpmf", "sstc",
+					       "svpbmt", "zba", "zbb", "zbc",
+					       "zbs", "zicbom", "zicbop",
+					       "zicboz", "zicntr", "zicsr",
+					       "zifencei", "zihpm";
+
+			cpu6_intc: interrupt-controller {
+				compatible = "riscv,cpu-intc";
+				#interrupt-cells = <1>;
+				interrupt-controller;
+			};
+		};
+
+		c920_7: cpu@7 {
+			device_type = "cpu";
+			compatible = "thead,c920", "riscv";
+			reg = <7>;
+			d-cache-block-size = <64>;
+			d-cache-sets = <512>;
+			d-cache-size = <65536>;
+			i-cache-block-size = <64>;
+			i-cache-sets = <512>;
+			i-cache-size = <65536>;
+			mmu-type = "riscv,sv39";
+			next-level-cache = <&c1_l2_cache>;
+			riscv,cbom-block-size = <64>;
+			riscv,cbop-block-size = <64>;
+			riscv,cboz-block-size = <64>;
+			riscv,isa-base = "rv64i";
+			riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
+					       "b", "v", "sscofpmf", "sstc",
+					       "svpbmt", "zba", "zbb", "zbc",
+					       "zbs", "zicbom", "zicbop",
+					       "zicboz", "zicntr", "zicsr",
+					       "zifencei", "zihpm";
+
+			cpu7_intc: interrupt-controller {
+				compatible = "riscv,cpu-intc";
+				#interrupt-cells = <1>;
+				interrupt-controller;
+			};
+		};
+	};
+
+	soc {
+		compatible = "simple-bus";
+		ranges;
+		#address-cells = <2>;
+		dma-noncoherent;
+		#size-cells = <2>;
+
+		clk: clock-controller@260000 {
+			compatible = "zhihe,a210-clk";
+			reg = <0x0 0x00260000 0x0 0x1000>,
+			      <0x0 0x00250000 0x0 0x1000>,
+			      <0x0 0x10141600 0x0 0x100>,
+			      <0x0 0x10141400 0x0 0x100>,
+			      <0x0 0x04810000 0x0 0x1000>,
+			      <0x0 0x05810000 0x0 0x1000>,
+			      <0x0 0x04900000 0x0 0x1000>,
+			      <0x0 0x20250000 0x0 0x1000>,
+			      <0x0 0x10140000 0x0 0xe00>;
+			reg-names = "pll-wrap", "top-crg", "cpu-ss-clk-sysreg",
+				    "cpu-ss-cpu-pll", "ddr0-sysreg",
+				    "ddr1-sysreg", "slc-dual-sysreg",
+				    "top-crg-t", "cpu-ss-ccu";
+			#clock-cells = <1>;
+			clocks = <&osc_32k>, <&osc_24m>, <&rc_24m>;
+			clock-names = "osc-32k", "osc-24m", "rc-24m";
+		};
+
+		clk_peri: clock-controller@300200 {
+			compatible = "zhihe,a210-peri-clk";
+			reg = <0x0 0x00300200 0x0 0x4>,
+			      <0x0 0x02010200 0x0 0x8>,
+			      <0x0 0x08400200 0x0 0x8>,
+			      <0x0 0x00540200 0x0 0x4>,
+			      <0x0 0x27420200 0x0 0x200>;
+			reg-names = "peri0-sysreg", "peri1-sysreg",
+				    "peri2-sysreg", "peri3-sysreg", "tee-crg";
+			#clock-cells = <1>;
+		};
+
+		peri3_padctrl: pinctrl@542000 {
+			compatible = "zhihe,a210-peri3-pinctrl";
+			reg = <0x0 0x00542000 0x0 0x1000>;
+			clocks = <&clk_peri PERI3_PAD_CTRL_PCLK_EN>;
+			clock-names = "pclk";
+
+			status = "disabled";
+		};
+
+		rst_peri1: reset-controller@2010400 {
+			compatible = "zhihe,a210-peri1-reset";
+			reg = <0x0 0x02010400 0x0 0x200>;
+			#reset-cells = <1>;
+		};
+
+		peri1_padctrl: pinctrl@2026000 {
+			compatible = "zhihe,a210-peri1-pinctrl";
+			reg = <0x0 0x02026000 0x0 0x1000>;
+			clocks = <&clk_peri PERI1_PAD_CTRL_PCLK_EN>;
+			clock-names = "pclk";
+
+			status = "disabled";
+		};
+
+		rst_peri2: reset-controller@8400400 {
+			compatible = "zhihe,a210-peri2-reset";
+			reg = <0x0 0x08400400 0x0 0x200>;
+			#reset-cells = <1>;
+		};
+
+		peri2_padctrl: pinctrl@8411000 {
+			compatible = "zhihe,a210-peri2-pinctrl";
+			reg = <0x0 0x08411000 0x0 0x1000>;
+			clocks = <&clk_peri PERI2_PAD_CTRL_PCLK_EN>;
+			clock-names = "pclk";
+
+			status = "disabled";
+		};
+
+		intc: interrupt-controller@18000000 {
+			compatible = "zhihe,a210-plic", "thead,c900-plic";
+			reg = <0x0 0x18000000 0x0 0x04000000>;
+			#address-cells = <0>;
+			#interrupt-cells = <2>;
+			interrupt-controller;
+			interrupts-extended = <&cpu0_intc 0xffffffff>,
+					      <&cpu0_intc 9>,
+					      <&cpu1_intc 0xffffffff>,
+					      <&cpu1_intc 9>,
+					      <&cpu2_intc 0xffffffff>,
+					      <&cpu2_intc 9>,
+					      <&cpu3_intc 0xffffffff>,
+					      <&cpu3_intc 9>,
+					      <&cpu4_intc 0xffffffff>,
+					      <&cpu4_intc 9>,
+					      <&cpu5_intc 0xffffffff>,
+					      <&cpu5_intc 9>,
+					      <&cpu6_intc 0xffffffff>,
+					      <&cpu6_intc 9>,
+					      <&cpu7_intc 0xffffffff>,
+					      <&cpu7_intc 9>;
+			riscv,ndev = <351>;
+		};
+
+		clint0: clint@1c000000 {
+			compatible = "zhihe,a210-clint", "thead,c900-clint";
+			reg = <0x0 0x1c000000 0x0 0x0000d800>;
+			interrupts-extended = <&cpu0_intc 3>,
+					      <&cpu0_intc 7>,
+					      <&cpu1_intc 3>,
+					      <&cpu1_intc 7>,
+					      <&cpu2_intc 3>,
+					      <&cpu2_intc 7>,
+					      <&cpu3_intc 3>,
+					      <&cpu3_intc 7>,
+					      <&cpu4_intc 3>,
+					      <&cpu4_intc 7>,
+					      <&cpu5_intc 3>,
+					      <&cpu5_intc 7>,
+					      <&cpu6_intc 3>,
+					      <&cpu6_intc 7>,
+					      <&cpu7_intc 3>,
+					      <&cpu7_intc 7>;
+		};
+
+		clk_aon: clock-controller@30844000 {
+			compatible = "zhihe,a210-aon-clk";
+			reg = <0 0x30844000 0 0x1c>;
+			#clock-cells = <1>;
+			clocks = <&aon_110m>, <&osc_24m>, <&aon_rc>, <&osc_32k>;
+			clock-names = "high", "osc", "rc", "rtc";
+		};
+
+		aon_padctrl: pinctrl@30848000 {
+			compatible = "zhihe,a210-aon-pinctrl";
+			reg = <0x0 0x30848000 0x0 0x2000>;
+			clocks = <&clk_aon A210_AON_SYS_CLK>;
+			clock-names = "pclk";
+
+			status = "disabled";
+		};
+	};
+};

-- 
2.55.0



^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 14/18] riscv: dts: zhihe: add A210 UARTs
  2026-10-21 19:53 [PATCH 00/18] riscv: add initial support for Zhihe A210 and Melon Pi Han Gao via B4 Relay
                   ` (12 preceding siblings ...)
  2026-10-21 19:53 ` [PATCH 13/18] riscv: dts: zhihe: add A210 core support Han Gao via B4 Relay
@ 2026-10-21 19:53 ` Han Gao via B4 Relay
  2026-10-22  9:22   ` Philipp Zabel
  2026-10-21 19:53 ` [PATCH 15/18] riscv: dts: zhihe: add A210 module memory Han Gao via B4 Relay
                   ` (3 subsequent siblings)
  17 siblings, 1 reply; 22+ messages in thread
From: Han Gao via B4 Relay @ 2026-10-21 19:53 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Zhiguo Zhu,
	Stephen Boyd, Brian Masney, Jerome Brunet, Philipp Zabel,
	Linus Walleij, Bartosz Golaszewski, Thomas Gleixner, Radu Rendec,
	Samuel Holland, Daniel Lezcano, Anup Patel, Icenowy Zheng,
	Drew Fustini
  Cc: devicetree, linux-kernel, linux-riscv, linux-clk, linux-gpio,
	Paul Walmsley, Han Gao

From: Zhiguo Zhu <zhiguo.zhu@linux.alibaba.com>

Add the ten A210 UARTs with their clocks, resets and interrupts, using
the snps,dw-apb-uart compatible.

Signed-off-by: Zhiguo Zhu <zhiguo.zhu@linux.alibaba.com>
Co-developed-by: Han Gao <gaohan@iscas.ac.cn>
Signed-off-by: Han Gao <gaohan@iscas.ac.cn>
---
 arch/riscv/boot/dts/zhihe/a210.dtsi | 150 ++++++++++++++++++++++++++++++++++++
 1 file changed, 150 insertions(+)

diff --git a/arch/riscv/boot/dts/zhihe/a210.dtsi b/arch/riscv/boot/dts/zhihe/a210.dtsi
index bbad51a3edb0..a07b67d10633 100644
--- a/arch/riscv/boot/dts/zhihe/a210.dtsi
+++ b/arch/riscv/boot/dts/zhihe/a210.dtsi
@@ -405,6 +405,66 @@ rst_peri1: reset-controller@2010400 {
 			#reset-cells = <1>;
 		};
 
+		uart0: serial@2014000 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0x0 0x02014000 0x0 0x400>;
+			clocks = <&clk_peri PERI1_UART0_SCLK_EN>,
+				 <&clk_peri PERI1_UART0_PCLK_EN>;
+			clock-names = "baudclk", "apb_pclk";
+			interrupt-parent = <&intc>;
+			interrupts = <321 IRQ_TYPE_LEVEL_HIGH>;
+			reg-io-width = <4>;
+			reg-shift = <2>;
+			resets = <&rst_peri1 PERI1_UART0_PRST>;
+
+			status = "disabled";
+		};
+
+		uart1: serial@2015000 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0x0 0x02015000 0x0 0x1000>;
+			clocks = <&clk_peri PERI1_UART1_SCLK_EN>,
+				 <&clk_peri PERI1_UART1_PCLK_EN>;
+			clock-names = "baudclk", "apb_pclk";
+			interrupt-parent = <&intc>;
+			interrupts = <322 IRQ_TYPE_LEVEL_HIGH>;
+			reg-io-width = <4>;
+			reg-shift = <2>;
+			resets = <&rst_peri1 PERI1_UART1_PRST>;
+
+			status = "disabled";
+		};
+
+		uart2: serial@2016000 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0x0 0x02016000 0x0 0x1000>;
+			clocks = <&clk_peri PERI1_UART2_SCLK_EN>,
+				 <&clk_peri PERI1_UART2_PCLK_EN>;
+			clock-names = "baudclk", "apb_pclk";
+			interrupt-parent = <&intc>;
+			interrupts = <323 IRQ_TYPE_LEVEL_HIGH>;
+			reg-io-width = <4>;
+			reg-shift = <2>;
+			resets = <&rst_peri1 PERI1_UART2_PRST>;
+
+			status = "disabled";
+		};
+
+		uart3: serial@2017000 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0x0 0x02017000 0x0 0x1000>;
+			clocks = <&clk_peri PERI1_UART3_SCLK_EN>,
+				 <&clk_peri PERI1_UART3_PCLK_EN>;
+			clock-names = "baudclk", "apb_pclk";
+			interrupt-parent = <&intc>;
+			interrupts = <324 IRQ_TYPE_LEVEL_HIGH>;
+			reg-io-width = <4>;
+			reg-shift = <2>;
+			resets = <&rst_peri1 PERI1_UART3_PRST>;
+
+			status = "disabled";
+		};
+
 		peri1_padctrl: pinctrl@2026000 {
 			compatible = "zhihe,a210-peri1-pinctrl";
 			reg = <0x0 0x02026000 0x0 0x1000>;
@@ -420,6 +480,96 @@ rst_peri2: reset-controller@8400400 {
 			#reset-cells = <1>;
 		};
 
+		uart4: serial@8401000 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0x0 0x08401000 0x0 0x400>;
+			clocks = <&clk_peri PERI2_UART4_SCLK_EN>,
+				 <&clk_peri PERI2_UART4_PCLK_EN>;
+			clock-names = "baudclk", "apb_pclk";
+			interrupt-parent = <&intc>;
+			interrupts = <325 IRQ_TYPE_LEVEL_HIGH>;
+			reg-io-width = <4>;
+			reg-shift = <2>;
+			resets = <&rst_peri2 PERI2_UART4_PRST>;
+
+			status = "disabled";
+		};
+
+		uart5: serial@8402000 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0x0 0x08402000 0x0 0x1000>;
+			clocks = <&clk_peri PERI2_UART5_SCLK_EN>,
+				 <&clk_peri PERI2_UART5_PCLK_EN>;
+			clock-names = "baudclk", "apb_pclk";
+			interrupt-parent = <&intc>;
+			interrupts = <326 IRQ_TYPE_LEVEL_HIGH>;
+			reg-io-width = <4>;
+			reg-shift = <2>;
+			resets = <&rst_peri2 PERI2_UART5_PRST>;
+
+			status = "disabled";
+		};
+
+		uart6: serial@8403000 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0x0 0x08403000 0x0 0x1000>;
+			clocks = <&clk_peri PERI2_UART6_SCLK_EN>,
+				 <&clk_peri PERI2_UART6_PCLK_EN>;
+			clock-names = "baudclk", "apb_pclk";
+			interrupt-parent = <&intc>;
+			interrupts = <327 IRQ_TYPE_LEVEL_HIGH>;
+			reg-io-width = <4>;
+			reg-shift = <2>;
+			resets = <&rst_peri2 PERI2_UART6_PRST>;
+
+			status = "disabled";
+		};
+
+		uart7: serial@8404000 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0x0 0x08404000 0x0 0x1000>;
+			clocks = <&clk_peri PERI2_UART7_SCLK_EN>,
+				 <&clk_peri PERI2_UART7_PCLK_EN>;
+			clock-names = "baudclk", "apb_pclk";
+			interrupt-parent = <&intc>;
+			interrupts = <328 IRQ_TYPE_LEVEL_HIGH>;
+			reg-io-width = <4>;
+			reg-shift = <2>;
+			resets = <&rst_peri2 PERI2_UART7_PRST>;
+
+			status = "disabled";
+		};
+
+		uart8: serial@8405000 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0x0 0x08405000 0x0 0x1000>;
+			clocks = <&clk_peri PERI2_UART8_SCLK_EN>,
+				 <&clk_peri PERI2_UART8_PCLK_EN>;
+			clock-names = "baudclk", "apb_pclk";
+			interrupt-parent = <&intc>;
+			interrupts = <329 IRQ_TYPE_LEVEL_HIGH>;
+			reg-io-width = <4>;
+			reg-shift = <2>;
+			resets = <&rst_peri2 PERI2_UART8_PRST>;
+
+			status = "disabled";
+		};
+
+		uart9: serial@8406000 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0x0 0x08406000 0x0 0x1000>;
+			clocks = <&clk_peri PERI2_UART9_SCLK_EN>,
+				 <&clk_peri PERI2_UART9_PCLK_EN>;
+			clock-names = "baudclk", "apb_pclk";
+			interrupt-parent = <&intc>;
+			interrupts = <330 IRQ_TYPE_LEVEL_HIGH>;
+			reg-io-width = <4>;
+			reg-shift = <2>;
+			resets = <&rst_peri2 PERI2_UART9_PRST>;
+
+			status = "disabled";
+		};
+
 		peri2_padctrl: pinctrl@8411000 {
 			compatible = "zhihe,a210-peri2-pinctrl";
 			reg = <0x0 0x08411000 0x0 0x1000>;

-- 
2.55.0



^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 15/18] riscv: dts: zhihe: add A210 module memory
  2026-10-21 19:53 [PATCH 00/18] riscv: add initial support for Zhihe A210 and Melon Pi Han Gao via B4 Relay
                   ` (13 preceding siblings ...)
  2026-10-21 19:53 ` [PATCH 14/18] riscv: dts: zhihe: add A210 UARTs Han Gao via B4 Relay
@ 2026-10-21 19:53 ` Han Gao via B4 Relay
  2026-10-21 19:53 ` [PATCH 16/18] riscv: dts: zhihe: add Melon Pi V1 and V2 Han Gao via B4 Relay
                   ` (2 subsequent siblings)
  17 siblings, 0 replies; 22+ messages in thread
From: Han Gao via B4 Relay @ 2026-10-21 19:53 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Zhiguo Zhu,
	Stephen Boyd, Brian Masney, Jerome Brunet, Philipp Zabel,
	Linus Walleij, Bartosz Golaszewski, Thomas Gleixner, Radu Rendec,
	Samuel Holland, Daniel Lezcano, Anup Patel, Icenowy Zheng,
	Drew Fustini
  Cc: devicetree, linux-kernel, linux-riscv, linux-clk, linux-gpio,
	Paul Walmsley, Han Gao

From: Han Gao <gaohan@iscas.ac.cn>

Add the A210 module memory node with a default 4 GiB range for boot
firmware to update with the detected capacity.

Signed-off-by: Han Gao <gaohan@iscas.ac.cn>
---
 arch/riscv/boot/dts/zhihe/a210-som.dtsi | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/arch/riscv/boot/dts/zhihe/a210-som.dtsi b/arch/riscv/boot/dts/zhihe/a210-som.dtsi
new file mode 100644
index 000000000000..a77447e402d7
--- /dev/null
+++ b/arch/riscv/boot/dts/zhihe/a210-som.dtsi
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+
+#include "a210.dtsi"
+
+/ {
+	/* The loader replaces this reference capacity after DDR training. */
+	memory@80000000 {
+		device_type = "memory";
+		reg = <0x0 0x80000000 0x1 0x0>;
+	};
+};

-- 
2.55.0



^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 16/18] riscv: dts: zhihe: add Melon Pi V1 and V2
  2026-10-21 19:53 [PATCH 00/18] riscv: add initial support for Zhihe A210 and Melon Pi Han Gao via B4 Relay
                   ` (14 preceding siblings ...)
  2026-10-21 19:53 ` [PATCH 15/18] riscv: dts: zhihe: add A210 module memory Han Gao via B4 Relay
@ 2026-10-21 19:53 ` Han Gao via B4 Relay
  2026-10-21 19:53 ` [PATCH 17/18] riscv: defconfig: enable A210 support Han Gao via B4 Relay
  2026-10-21 19:53 ` [PATCH 18/18] MAINTAINERS: add Zhihe A210 Han Gao via B4 Relay
  17 siblings, 0 replies; 22+ messages in thread
From: Han Gao via B4 Relay @ 2026-10-21 19:53 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Zhiguo Zhu,
	Stephen Boyd, Brian Masney, Jerome Brunet, Philipp Zabel,
	Linus Walleij, Bartosz Golaszewski, Thomas Gleixner, Radu Rendec,
	Samuel Holland, Daniel Lezcano, Anup Patel, Icenowy Zheng,
	Drew Fustini
  Cc: devicetree, linux-kernel, linux-riscv, linux-clk, linux-gpio,
	Paul Walmsley, Han Gao

From: Han Gao <gaohan@iscas.ac.cn>

Add Melon Pi V1 and V2 with the UART4 console on GPIO2_0 and GPIO2_1.
Use serial aliases to preserve physical UART numbering.

Signed-off-by: Han Gao <gaohan@iscas.ac.cn>
---
 arch/riscv/boot/dts/Makefile                       |  1 +
 arch/riscv/boot/dts/zhihe/Makefile                 |  2 +
 arch/riscv/boot/dts/zhihe/a210-melonpi-common.dtsi | 55 ++++++++++++++++++++++
 arch/riscv/boot/dts/zhihe/a210-melonpi-v1.dts      |  9 ++++
 arch/riscv/boot/dts/zhihe/a210-melonpi-v2.dts      |  9 ++++
 5 files changed, 76 insertions(+)

diff --git a/arch/riscv/boot/dts/Makefile b/arch/riscv/boot/dts/Makefile
index 69d8751fb17c..445edde8f107 100644
--- a/arch/riscv/boot/dts/Makefile
+++ b/arch/riscv/boot/dts/Makefile
@@ -12,3 +12,4 @@ subdir-y += spacemit
 subdir-y += starfive
 subdir-y += tenstorrent
 subdir-y += thead
+subdir-y += zhihe
diff --git a/arch/riscv/boot/dts/zhihe/Makefile b/arch/riscv/boot/dts/zhihe/Makefile
new file mode 100644
index 000000000000..553102091d4f
--- /dev/null
+++ b/arch/riscv/boot/dts/zhihe/Makefile
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0
+dtb-$(CONFIG_ARCH_ZHIHE) += a210-melonpi-v1.dtb a210-melonpi-v2.dtb
diff --git a/arch/riscv/boot/dts/zhihe/a210-melonpi-common.dtsi b/arch/riscv/boot/dts/zhihe/a210-melonpi-common.dtsi
new file mode 100644
index 000000000000..7a6e6af0aa1f
--- /dev/null
+++ b/arch/riscv/boot/dts/zhihe/a210-melonpi-common.dtsi
@@ -0,0 +1,55 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+
+#include "a210-som.dtsi"
+
+/ {
+	aliases {
+		serial0 = &uart0;
+		serial1 = &uart1;
+		serial2 = &uart2;
+		serial3 = &uart3;
+		serial4 = &uart4;
+		serial5 = &uart5;
+		serial6 = &uart6;
+		serial7 = &uart7;
+		serial8 = &uart8;
+		serial9 = &uart9;
+	};
+
+	chosen {
+		stdout-path = "serial4:115200n8";
+	};
+};
+
+&peri2_padctrl {
+	status = "okay";
+
+	uart4_pins: uart4-0 {
+		rx-pins {
+			bias-disable;
+			drive-strength = <1>;
+			function = "uart4";
+			input-enable;
+			input-schmitt-enable;
+			pins = "GPIO2_1";
+			slew-rate = <0>;
+		};
+
+		tx-pins {
+			bias-disable;
+			drive-strength = <3>;
+			function = "uart4";
+			input-disable;
+			input-schmitt-disable;
+			pins = "GPIO2_0";
+			slew-rate = <0>;
+		};
+	};
+};
+
+&uart4 {
+	pinctrl-0 = <&uart4_pins>;
+	pinctrl-names = "default";
+
+	status = "okay";
+};
diff --git a/arch/riscv/boot/dts/zhihe/a210-melonpi-v1.dts b/arch/riscv/boot/dts/zhihe/a210-melonpi-v1.dts
new file mode 100644
index 000000000000..a88e9b949c4a
--- /dev/null
+++ b/arch/riscv/boot/dts/zhihe/a210-melonpi-v1.dts
@@ -0,0 +1,9 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+/dts-v1/;
+
+#include "a210-melonpi-common.dtsi"
+
+/ {
+	compatible = "zhihe,a210-melonpi-v1", "zhihe,a210-som", "zhihe,a210";
+	model = "Melon Pi V1";
+};
diff --git a/arch/riscv/boot/dts/zhihe/a210-melonpi-v2.dts b/arch/riscv/boot/dts/zhihe/a210-melonpi-v2.dts
new file mode 100644
index 000000000000..71752471c5fb
--- /dev/null
+++ b/arch/riscv/boot/dts/zhihe/a210-melonpi-v2.dts
@@ -0,0 +1,9 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+/dts-v1/;
+
+#include "a210-melonpi-common.dtsi"
+
+/ {
+	compatible = "zhihe,a210-melonpi-v2", "zhihe,a210-som", "zhihe,a210";
+	model = "Melon Pi V2";
+};

-- 
2.55.0



^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 17/18] riscv: defconfig: enable A210 support
  2026-10-21 19:53 [PATCH 00/18] riscv: add initial support for Zhihe A210 and Melon Pi Han Gao via B4 Relay
                   ` (15 preceding siblings ...)
  2026-10-21 19:53 ` [PATCH 16/18] riscv: dts: zhihe: add Melon Pi V1 and V2 Han Gao via B4 Relay
@ 2026-10-21 19:53 ` Han Gao via B4 Relay
  2026-10-21 19:53 ` [PATCH 18/18] MAINTAINERS: add Zhihe A210 Han Gao via B4 Relay
  17 siblings, 0 replies; 22+ messages in thread
From: Han Gao via B4 Relay @ 2026-10-21 19:53 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Zhiguo Zhu,
	Stephen Boyd, Brian Masney, Jerome Brunet, Philipp Zabel,
	Linus Walleij, Bartosz Golaszewski, Thomas Gleixner, Radu Rendec,
	Samuel Holland, Daniel Lezcano, Anup Patel, Icenowy Zheng,
	Drew Fustini
  Cc: devicetree, linux-kernel, linux-riscv, linux-clk, linux-gpio,
	Paul Walmsley, Han Gao

From: Han Gao <gaohan@iscas.ac.cn>

Enable A210 platform drivers and reserve ten 8250 UART ports.

Signed-off-by: Han Gao <gaohan@iscas.ac.cn>
---
 arch/riscv/configs/defconfig | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/riscv/configs/defconfig b/arch/riscv/configs/defconfig
index 04ae305d5511..b9b3bca12089 100644
--- a/arch/riscv/configs/defconfig
+++ b/arch/riscv/configs/defconfig
@@ -33,6 +33,7 @@ CONFIG_SOC_STARFIVE=y
 CONFIG_ARCH_SUNXI=y
 CONFIG_ARCH_TENSTORRENT=y
 CONFIG_ARCH_THEAD=y
+CONFIG_ARCH_ZHIHE=y
 CONFIG_ARCH_ULTRARISC=y
 CONFIG_ARCH_VIRT=y
 CONFIG_ARCH_CANAAN=y
@@ -149,6 +150,8 @@ CONFIG_KEYBOARD_GPIO=y
 CONFIG_KEYBOARD_SUN4I_LRADC=m
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=10
+CONFIG_SERIAL_8250_RUNTIME_UARTS=10
 CONFIG_SERIAL_8250_DW=y
 CONFIG_SERIAL_OF_PLATFORM=y
 CONFIG_SERIAL_EARLYCON_RISCV_SBI=y
@@ -167,6 +170,7 @@ CONFIG_SPI_PL022=m
 CONFIG_SPI_SIFIVE=y
 CONFIG_SPI_SUN6I=y
 # CONFIG_PTP_1588_CLOCK is not set
+CONFIG_PINCTRL_A210=y
 CONFIG_PINCTRL_TH1520=y
 CONFIG_PINCTRL_SOPHGO_CV1800B=y
 CONFIG_PINCTRL_SOPHGO_CV1812H=y

-- 
2.55.0



^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 18/18] MAINTAINERS: add Zhihe A210
  2026-10-21 19:53 [PATCH 00/18] riscv: add initial support for Zhihe A210 and Melon Pi Han Gao via B4 Relay
                   ` (16 preceding siblings ...)
  2026-10-21 19:53 ` [PATCH 17/18] riscv: defconfig: enable A210 support Han Gao via B4 Relay
@ 2026-10-21 19:53 ` Han Gao via B4 Relay
  17 siblings, 0 replies; 22+ messages in thread
From: Han Gao via B4 Relay @ 2026-10-21 19:53 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Zhiguo Zhu,
	Stephen Boyd, Brian Masney, Jerome Brunet, Philipp Zabel,
	Linus Walleij, Bartosz Golaszewski, Thomas Gleixner, Radu Rendec,
	Samuel Holland, Daniel Lezcano, Anup Patel, Icenowy Zheng,
	Drew Fustini
  Cc: devicetree, linux-kernel, linux-riscv, linux-clk, linux-gpio,
	Paul Walmsley, Han Gao

From: Han Gao <gaohan@iscas.ac.cn>

Add Zhiguo Zhu and Han Gao as A210 maintainers.

Signed-off-by: Han Gao <gaohan@iscas.ac.cn>
---
 MAINTAINERS | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 782389bd5cd3..97cf956fd632 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -30115,6 +30115,22 @@ L:	linux-kernel@vger.kernel.org
 S:	Maintained
 F:	arch/x86/kernel/cpu/zhaoxin.c
 
+ZHIHE A210 SOC SUPPORT
+M:	Zhiguo Zhu <zhiguo.zhu@linux.alibaba.com>
+M:	Han Gao <gaohan@iscas.ac.cn>
+L:	linux-riscv@lists.infradead.org
+S:	Maintained
+F:	Documentation/devicetree/bindings/clock/zhihe,a210-*.yaml
+F:	Documentation/devicetree/bindings/pinctrl/zhihe,a210-pinctrl.yaml
+F:	Documentation/devicetree/bindings/reset/zhihe,a210-reset.yaml
+F:	Documentation/devicetree/bindings/riscv/zhihe.yaml
+F:	arch/riscv/boot/dts/zhihe/
+F:	drivers/clk/zhihe/
+F:	drivers/pinctrl/pinctrl-a210.c
+F:	drivers/reset/reset-a210.c
+F:	include/dt-bindings/clock/zhihe,a210-*.h
+F:	include/dt-bindings/reset/zhihe,a210-resets.h
+
 ZONED BLOCK DEVICE (BLOCK LAYER)
 M:	Damien Le Moal <dlemoal@kernel.org>
 L:	linux-block@vger.kernel.org

-- 
2.55.0



^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 07/18] reset: zhihe: add A210 support
  2026-10-21 19:53 ` [PATCH 07/18] reset: zhihe: add A210 support Han Gao via B4 Relay
@ 2026-10-22  9:22   ` Philipp Zabel
  0 siblings, 0 replies; 22+ messages in thread
From: Philipp Zabel @ 2026-10-22  9:22 UTC (permalink / raw)
  To: gaohan, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
	Zhiguo Zhu, Stephen Boyd, Brian Masney, Jerome Brunet,
	Linus Walleij, Bartosz Golaszewski, Thomas Gleixner, Radu Rendec,
	Samuel Holland, Daniel Lezcano, Anup Patel, Icenowy Zheng,
	Drew Fustini
  Cc: devicetree, linux-kernel, linux-riscv, linux-clk, linux-gpio,
	Paul Walmsley

On Do, 2026-10-22 at 03:53 +0800, Han Gao via B4 Relay wrote:
> From: Zhiguo Zhu <zhiguo.zhu@linux.alibaba.com>
> 
> Add support for A210 reset banks and linked reset signals. Check
> register readback to detect rejected writes.

Please explain why the linked reset mechanism is required. To me it
looks like these should be separate resets.

> Signed-off-by: Zhiguo Zhu <zhiguo.zhu@linux.alibaba.com>
> Co-developed-by: Han Gao <gaohan@iscas.ac.cn>
> Signed-off-by: Han Gao <gaohan@iscas.ac.cn>
> ---
>  drivers/reset/Kconfig      |  11 +
>  drivers/reset/Makefile     |   1 +
>  drivers/reset/reset-a210.c | 589 +++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 601 insertions(+)
> 
> diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
> index 3168ab1eea88..039e8a4046dc 100644
> --- a/drivers/reset/Kconfig
> +++ b/drivers/reset/Kconfig
> @@ -428,6 +428,17 @@ config RESET_UNIPHIER_GLUE
>  	  on UniPhier SoCs. Say Y if you want to control reset signals
>  	  provided by the glue layer.
>  
> +config RESET_ZHIHE_A210
> +	tristate "ZhiHe A210 reset controller"
> +	depends on OF && (ARCH_ZHIHE || COMPILE_TEST)
> +	default ARCH_ZHIHE
> +	help
> +	  Build the reset controller driver for the ZhiHe A210 SoC.
> +
> +	  This driver provides reset control for the various hardware
> +	  blocks in the A210 SoC. Say Y if you are building a kernel
> +	  for the ZhiHe A210 platform.
> +
>  config RESET_ZYNQ
>  	bool "ZYNQ Reset Driver" if COMPILE_TEST
>  	default ARCH_ZYNQ
> diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
> index 45ad17062462..3620e94e4539 100644
> --- a/drivers/reset/Makefile
> +++ b/drivers/reset/Makefile
> @@ -52,5 +52,6 @@ obj-$(CONFIG_RESET_TI_TPS380X) += reset-tps380x.o
>  obj-$(CONFIG_RESET_TN48M_CPLD) += reset-tn48m.o
>  obj-$(CONFIG_RESET_UNIPHIER) += reset-uniphier.o
>  obj-$(CONFIG_RESET_UNIPHIER_GLUE) += reset-uniphier-glue.o
> +obj-$(CONFIG_RESET_ZHIHE_A210) += reset-a210.o
>  obj-$(CONFIG_RESET_ZYNQ) += reset-zynq.o
>  obj-$(CONFIG_RESET_ZYNQMP) += reset-zynqmp.o
> diff --git a/drivers/reset/reset-a210.c b/drivers/reset/reset-a210.c
> new file mode 100644
> index 000000000000..38bad400d6b8
> --- /dev/null
> +++ b/drivers/reset/reset-a210.c
> @@ -0,0 +1,589 @@
[...]
> +static int a210_reset_update(struct reset_controller_dev *rcdev,
> +			     unsigned long id, bool assert)
> +{
> +	struct a210_reset *rst = to_a210_reset(rcdev);
> +	const struct a210_rst_signal *signal;
> +	unsigned long flags;
> +	u32 value;
> +	int ret = 0;
> +
> +	if (id >= rst->data->num_signals)
> +		return -EINVAL;

Unnecessary, the core already checks id < rcdev->num_resets before
creating the reset control.

> +
> +	spin_lock_irqsave(&rst->lock, flags);

If you use guard() here ...

> +	do {
> +		signal = &rst->data->signals[id];
> +		value = readl(rst->base + signal->offset);
> +		if (assert)
> +			value &= ~signal->mask;
> +		else
> +			value |= signal->mask;
> +		writel(value, rst->base + signal->offset);
> +		/* Firmware can lock individual reset controls against AP writes. */
> +		if ((readl(rst->base + signal->offset) & signal->mask) !=
> +		    (value & signal->mask)) {
> +			ret = -EIO;
> +			break;

... this could just return -EIO;

> +		}
> +		id = signal->nextid;
> +	} while (id);

Is this loop a workaround for the UART driver not handling two resets?

Or do the two linked reset bits really have to be asserted, one
directly after the other, without any other write to the same register
in-between and without setting them at the same time? If so, why?

> +	spin_unlock_irqrestore(&rst->lock, flags);
> +
> +	return ret;
> +}
> +
> +static int a210_reset_assert(struct reset_controller_dev *rcdev, unsigned long id)
> +{
> +	return a210_reset_update(rcdev, id, true);
> +}
> +
> +static int a210_reset_deassert(struct reset_controller_dev *rcdev, unsigned long id)
> +{
> +	return a210_reset_update(rcdev, id, false);
> +}
> +
> +static int a210_reset_status(struct reset_controller_dev *rcdev, unsigned long id)

Do you actually need this for any consumer?

> +{
> +	struct a210_reset *rst = to_a210_reset(rcdev);
> +	const struct a210_rst_signal *signal;
> +	unsigned long flags;
> +	bool asserted;
> +
> +	if (id >= rst->data->num_signals)
> +		return -EINVAL;
> +
> +	/* The logical reset is asserted if any linked signal is asserted. */

What is the "logical reset" in this context?

When there are multiple reset lines that can be in different states,
I'd expect this to return an error.

> +	spin_lock_irqsave(&rst->lock, flags);
> +	do {
> +		signal = &rst->data->signals[id];
> +		asserted = (readl(rst->base + signal->offset) & signal->mask) !=
> +			   signal->mask;
> +		if (asserted)
> +			break;
> +		id = signal->nextid;
> +	} while (id);
> +	spin_unlock_irqrestore(&rst->lock, flags);
> +
> +	return asserted;
> +}

regards
Philipp

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 14/18] riscv: dts: zhihe: add A210 UARTs
  2026-10-21 19:53 ` [PATCH 14/18] riscv: dts: zhihe: add A210 UARTs Han Gao via B4 Relay
@ 2026-10-22  9:22   ` Philipp Zabel
  0 siblings, 0 replies; 22+ messages in thread
From: Philipp Zabel @ 2026-10-22  9:22 UTC (permalink / raw)
  To: gaohan, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
	Zhiguo Zhu, Stephen Boyd, Brian Masney, Jerome Brunet,
	Linus Walleij, Bartosz Golaszewski, Thomas Gleixner, Radu Rendec,
	Samuel Holland, Daniel Lezcano, Anup Patel, Icenowy Zheng,
	Drew Fustini
  Cc: devicetree, linux-kernel, linux-riscv, linux-clk, linux-gpio,
	Paul Walmsley

On Do, 2026-10-22 at 03:53 +0800, Han Gao via B4 Relay wrote:
> From: Zhiguo Zhu <zhiguo.zhu@linux.alibaba.com>
> 
> Add the ten A210 UARTs with their clocks, resets and interrupts, using
> the snps,dw-apb-uart compatible.
> 
> Signed-off-by: Zhiguo Zhu <zhiguo.zhu@linux.alibaba.com>
> Co-developed-by: Han Gao <gaohan@iscas.ac.cn>
> Signed-off-by: Han Gao <gaohan@iscas.ac.cn>
> ---
>  arch/riscv/boot/dts/zhihe/a210.dtsi | 150 ++++++++++++++++++++++++++++++++++++
>  1 file changed, 150 insertions(+)
> 
> diff --git a/arch/riscv/boot/dts/zhihe/a210.dtsi b/arch/riscv/boot/dts/zhihe/a210.dtsi
> index bbad51a3edb0..a07b67d10633 100644
> --- a/arch/riscv/boot/dts/zhihe/a210.dtsi
> +++ b/arch/riscv/boot/dts/zhihe/a210.dtsi
> @@ -405,6 +405,66 @@ rst_peri1: reset-controller@2010400 {
>  			#reset-cells = <1>;
>  		};
>  
> +		uart0: serial@2014000 {
> +			compatible = "snps,dw-apb-uart";

Prepend a vendor compatible if you need two resets, similar to
"starfive,jh7100-uart"?

> +			reg = <0x0 0x02014000 0x0 0x400>;
> +			clocks = <&clk_peri PERI1_UART0_SCLK_EN>,
> +				 <&clk_peri PERI1_UART0_PCLK_EN>;
> +			clock-names = "baudclk", "apb_pclk";
> +			interrupt-parent = <&intc>;
> +			interrupts = <321 IRQ_TYPE_LEVEL_HIGH>;
> +			reg-io-width = <4>;
> +			reg-shift = <2>;
> +			resets = <&rst_peri1 PERI1_UART0_PRST>;

This looks to me like it should be

			resets = <&rst_peri1 PERI1_UART0_PRST>,
				 <&rst_peri1 PERI1_UART0_S_RST>;

instead.

regards
Philipp

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 07/18] reset: zhihe: add A210 support
  2026-10-21 19:48 [PATCH 00/18] riscv: add initial support for Zhihe A210 and Melon Pi Han Gao
@ 2026-10-21 19:48 ` Han Gao
  0 siblings, 0 replies; 22+ messages in thread
From: Han Gao @ 2026-10-21 19:48 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Zhiguo Zhu,
	Stephen Boyd, Brian Masney, Jerome Brunet, Philipp Zabel,
	Linus Walleij, Bartosz Golaszewski, Thomas Gleixner, Radu Rendec,
	Samuel Holland, Daniel Lezcano, Anup Patel, Icenowy Zheng,
	Drew Fustini
  Cc: devicetree, linux-kernel, linux-riscv, linux-clk, linux-gpio,
	Paul Walmsley, Han Gao

From: Zhiguo Zhu <zhiguo.zhu@linux.alibaba.com>

Add support for A210 reset banks and linked reset signals. Check
register readback to detect rejected writes.

Signed-off-by: Zhiguo Zhu <zhiguo.zhu@linux.alibaba.com>
Co-developed-by: Han Gao <gaohan@iscas.ac.cn>
Signed-off-by: Han Gao <gaohan@iscas.ac.cn>
---
 drivers/reset/Kconfig      |  11 +
 drivers/reset/Makefile     |   1 +
 drivers/reset/reset-a210.c | 589 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 601 insertions(+)

diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index 3168ab1eea88..039e8a4046dc 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -428,6 +428,17 @@ config RESET_UNIPHIER_GLUE
 	  on UniPhier SoCs. Say Y if you want to control reset signals
 	  provided by the glue layer.
 
+config RESET_ZHIHE_A210
+	tristate "ZhiHe A210 reset controller"
+	depends on OF && (ARCH_ZHIHE || COMPILE_TEST)
+	default ARCH_ZHIHE
+	help
+	  Build the reset controller driver for the ZhiHe A210 SoC.
+
+	  This driver provides reset control for the various hardware
+	  blocks in the A210 SoC. Say Y if you are building a kernel
+	  for the ZhiHe A210 platform.
+
 config RESET_ZYNQ
 	bool "ZYNQ Reset Driver" if COMPILE_TEST
 	default ARCH_ZYNQ
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index 45ad17062462..3620e94e4539 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -52,5 +52,6 @@ obj-$(CONFIG_RESET_TI_TPS380X) += reset-tps380x.o
 obj-$(CONFIG_RESET_TN48M_CPLD) += reset-tn48m.o
 obj-$(CONFIG_RESET_UNIPHIER) += reset-uniphier.o
 obj-$(CONFIG_RESET_UNIPHIER_GLUE) += reset-uniphier-glue.o
+obj-$(CONFIG_RESET_ZHIHE_A210) += reset-a210.o
 obj-$(CONFIG_RESET_ZYNQ) += reset-zynq.o
 obj-$(CONFIG_RESET_ZYNQMP) += reset-zynqmp.o
diff --git a/drivers/reset/reset-a210.c b/drivers/reset/reset-a210.c
new file mode 100644
index 000000000000..38bad400d6b8
--- /dev/null
+++ b/drivers/reset/reset-a210.c
@@ -0,0 +1,589 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2025 Zhihe Computing Limited.
+ */
+
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/property.h>
+#include <linux/reset-controller.h>
+#include <linux/spinlock.h>
+
+#include <dt-bindings/reset/zhihe,a210-resets.h>
+
+struct a210_rst_signal {
+	u16 offset;
+	u32 mask;
+	/* Zero terminates a chain of signals that share one reset ID. */
+	u16 nextid;
+};
+
+struct a210_reset_data {
+	const struct a210_rst_signal *signals;
+	unsigned int num_signals;
+};
+
+struct a210_reset {
+	struct reset_controller_dev rcdev;
+	void __iomem *base;
+	const struct a210_reset_data *data;
+	/* Protects register updates and snapshots of linked reset signals. */
+	spinlock_t lock;
+};
+
+static const struct a210_rst_signal vp_rst_signals[] = {
+	[VP_VDEC_PRST] = { 0, BIT(0), 0 },
+	[VP_VDEC_CRST] = { 0, BIT(1), 0 },
+	[VP_VDEC_ARST] = { 0, BIT(2), 0 },
+	[VP_VENC_PRST] = { 0, BIT(3), 0 },
+	[VP_VENC_CRST] = { 0, BIT(4), 0 },
+	[VP_VENC_ARST] = { 0, BIT(5), 0 },
+	[VP_G2D_PRST] = { 0, BIT(6), 0 },
+	[VP_G2D_CRST] = { 0, BIT(7), 0 },
+	[VP_G2D_ARST] = { 0, BIT(8), 0 },
+	[VP_COMP_PRST] = { 0, BIT(9), 0 },
+	[VP_COMP_CRST] = { 0, BIT(10), 0 },
+	[VP_COMP_ARST] = { 0, BIT(11), 0 },
+	[VP_DECOMP_PRST] = { 0, BIT(12), 0 },
+	[VP_DECOMP_CRST] = { 0, BIT(13), 0 },
+	[VP_DECOMP_ARST] = { 0, BIT(14), 0 },
+	[VP_DFMU_PRST] = { 0, BIT(15), 0 },
+	[VP_DFMU_ARST] = { 0, BIT(16), 0 },
+	[VP_ARB_PRST] = { 0, BIT(18), 0 },
+	[VP_ARB_ARST] = { 0, BIT(19), 0 },
+	[VP_VDEC_RS_ARST] = { 0, BIT(20), 0 },
+	[VP_VENC_RS_ARST] = { 0, BIT(21), 0 },
+	[VP_COMP_EXTPRST] = { 0, BIT(22), 0 },
+	[VP_DECOMP_EXTPRST] = { 0, BIT(23), 0 },
+};
+
+static const struct a210_rst_signal vi_rst_signals[] = {
+	[VI_MIPI0_CSI0_PRST] = { 0, BIT(0), 0 },
+	[VI_MIPI0_CSI1_PRST] = { 0, BIT(1), 0 },
+	[VI_MIPI0_FIFO_RST] = { 0, BIT(2), 0 },
+	[VI_MIPI1_CSI0_PRST] = { 0, BIT(3), 0 },
+	[VI_MIPI1_CSI1_PRST] = { 0, BIT(4), 0 },
+	[VI_MIPI1_FIFO_RST] = { 0, BIT(5), 0 },
+	[VI_VIPRE_PRST] = { 0, BIT(6), 0 },
+	[VI_VIPRE_I0_PIX_RST] = { 0, BIT(7), 0 },
+	[VI_VIPRE_I1_PIX_RST] = { 0, BIT(8), 0 },
+	[VI_VIPRE_ISPIF_RST] = { 0, BIT(9), 0 },
+	[VI_VIPRE_ARST] = { 0, BIT(10), 0 },
+	[VI_ISP_RST] = { 0, BIT(11), 0 },
+	[VI_COMP_PRST] = { 0, BIT(12), 0 },
+	[VI_COMP_ARST] = { 0, BIT(13), 0 },
+	[VI_COMP_ISPOUT_RST] = { 0, BIT(14), 0 },
+	[VI_COMP_DECOUT_RST] = { 0, BIT(15), 0 },
+	[VI_COMP_VSEOUT_RST] = { 0, BIT(16), 0 },
+	[VI_COMP0_RST] = { 0, BIT(17), 0 },
+	[VI_COMP1_RST] = { 0, BIT(18), 0 },
+	[VI_DECOMP_RST] = { 0, BIT(19), 0 },
+	[VI_DW200_RST] = { 0, BIT(20), 0 },
+	[VI_DFMU_PRST] = { 0, BIT(21), 0 },
+	[VI_DFMU_ARST] = { 0, BIT(22), 0 },
+	[VI_ARB_PRST] = { 0, BIT(23), 0 },
+	[VI_ARB_ARST] = { 0, BIT(24), 0 },
+	[VI_X2H0_HRST] = { 0, BIT(26), 0 },
+	[VI_X2H1_HRST] = { 0, BIT(27), 0 },
+	[VI_X2H2_HRST] = { 0, BIT(28), 0 },
+	[VI_REC_PRST] = { 0, BIT(29), 0 },
+	[VI_REC_ARST] = { 0, BIT(30), 0 },
+};
+
+static const struct a210_rst_signal npu_rst_signals[] = {
+	[NPU_AAB_MST_RST] = { 0, BIT(0), 0 },
+	[NPU_AFENCE_RST] = { 0, BIT(1), 0 },
+	[NPU_AXI_CCU_PRST] = { 0, BIT(2), 0 },
+	[NPU_AXI_CCU_RST] = { 0, BIT(3), 0 },
+	[NPU_AXI_M2S1_RST] = { 0, BIT(4), 0 },
+	[NPU_AXI_RST] = { 0, BIT(5), 0 },
+	[NPU_CLK_CALC_RST] = { 0, BIT(6), 0 },
+	[NPU_DFMU_ARST] = { 0, BIT(7), 0 },
+	[NPU_DFMU_PRST] = { 0, BIT(8), 0 },
+	[NPU_LPC_C_RST] = { 0, BIT(9), 0 },
+	[NPU_LPE_C_PRST] = { 0, BIT(10), 0 },
+	[NPU_LPE_C_RST] = { 0, BIT(11), 0 },
+	[NPU_ARST] = { 0, BIT(12), 0 },
+	[NPU_CRST] = { 0, BIT(13), 0 },
+	[NPU_HRST] = { 0, BIT(14), 0 },
+	[NPU_PCTRL_PB_RST] = { 0, BIT(15), 0 },
+	[NPU_PCTRL_PRST] = { 0, BIT(16), 0 },
+	[NPU_PCTRL_RST] = { 0, BIT(17), 0 },
+	[NPU_PTW_CCU_PRST] = { 0, BIT(18), 0 },
+	[NPU_PTW_CCU_RST] = { 0, BIT(19), 0 },
+	[NPU_SEMA_ARST] = { 0, BIT(20), 0 },
+	[NPU_SEMA_PRST] = { 0, BIT(21), 0 },
+	[NPU_DROOP_CCTRL_PRST] = { 0, BIT(22), 0 },
+	[NPU_DROOP_CCTRL_RST] = { 0, BIT(23), 0 },
+	[NPU_X2H_RST] = { 0, BIT(24), 0 },
+	[NPU_X2P_RST] = { 0, BIT(25), 0 },
+	[NPU_LDIP_RST] = { 0, BIT(26), 0 },
+	[NPU_SRAM_RST] = { 0, BIT(27), 0 },
+};
+
+static const struct a210_rst_signal vo_rst_signals[] = {
+	[VO_X2H0_RST] = { 0, BIT(0), 0 },
+	[VO_X2H1_RST] = { 0, BIT(1), 0 },
+	[VO_DPU_HRST] = { 0, BIT(2), 0 },
+	[VO_DPU_CRST] = { 0, BIT(3), 0 },
+	[VO_DPU_ARST] = { 0, BIT(4), 0 },
+	[VO_AUXDISP_PRST] = { 0, BIT(5), 0 },
+	[VO_AUXDISP_PIX_RST] = { 0, BIT(6), 0 },
+	[VO_AUXDISP_ARST] = { 0, BIT(7), 0 },
+	[VO_HDMI_PRST] = { 0, BIT(8), 0 },
+	[VO_HDMI_MAIN_RST] = { 0, BIT(9), 0 },
+	[VO_MIPI_PRST] = { 0, BIT(10), 0 },
+	[VO_DECOMP_PRST] = { 0, BIT(11), 0 },
+	[VO_DECOMP0_CRST] = { 0, BIT(12), 0 },
+	[VO_DECOMP1_CRST] = { 0, BIT(13), 0 },
+	[VO_DECOMP_ARST] = { 0, BIT(14), 0 },
+	[VO_ARB_PRST] = { 0, BIT(15), 0 },
+	[VO_ARB_ARST] = { 0, BIT(16), 0 },
+	[VO_DFMU_PRST] = { 0, BIT(17), 0 },
+	[VO_DFMU_ARST] = { 0, BIT(18), 0 },
+};
+
+static const struct a210_rst_signal peri0_rst_signals[] = {
+	[PERI0_TIMER0_CRST] = { 0, BIT(0), 0 },
+	[PERI0_TIMER0_PRST] = { 0, BIT(1), 0 },
+	[PERI0_TIMER1_CRST] = { 0, BIT(2), 0 },
+	[PERI0_TIMER1_PRST] = { 0, BIT(3), 0 },
+	[PERI0_WDT0_PRST] = { 0, BIT(4), 0 },
+	[PERI0_MBOX0_PRST] = { 0, BIT(5), 0 },
+	[PERI0_MBOX1_PRST] = { 0, BIT(6), 0 },
+	[PERI0_TIMER0_RST] = { 0, BIT(0) | BIT(1), 0 },
+	[PERI0_TIMER1_RST] = { 0, BIT(2) | BIT(3), 0 },
+};
+
+static const struct a210_rst_signal peri1_rst_signals[] = {
+	[PERI1_GMAC0_ARST] = { 0, BIT(0), 0 },
+	[PERI1_GMAC0_HRST] = { 0, BIT(1), 0 },
+	[PERI1_GMAC1_ARST] = { 0, BIT(2), 0 },
+	[PERI1_GMAC1_HRST] = { 0, BIT(3), 0 },
+	[PERI1_GPIO0_DBRST] = { 0, BIT(4), 0 },
+	[PERI1_GPIO0_PRST] = { 0, BIT(5), 0 },
+	[PERI1_GPIO1_DBRST] = { 0, BIT(6), 0 },
+	[PERI1_GPIO1_PRST] = { 0, BIT(7), 0 },
+	[PERI1_I2C0_IC_RST] = { 0, BIT(8), 0 },
+	[PERI1_I2C0_PRST] = { 0, BIT(9), 0 },
+	[PERI1_I2C1_IC_RST] = { 0, BIT(10), 0 },
+	[PERI1_I2C1_PRST] = { 0, BIT(11), 0 },
+	[PERI1_I2C2_IC_RST] = { 0, BIT(12), 0 },
+	[PERI1_I2C2_PRST] = { 0, BIT(13), 0 },
+	[PERI1_I2S0_PRST] = { 0, BIT(14), 0 },
+	[PERI1_MST_BUS_ARST] = { 0, BIT(15), 0 },
+	[PERI1_MST_BUS_PRST] = { 0, BIT(16), 0 },
+	[PERI1_PWM0_CRST] = { 0, BIT(17), 0 },
+	[PERI1_PWM0_PRST] = { 0, BIT(18), 0 },
+	[PERI1_QSPI0_PRST] = { 0, BIT(19), 0 },
+	[PERI1_QSPI0_SSI_RST] = { 0, BIT(20), 0 },
+	[PERI1_SPI0_PRST] = { 0, BIT(21), 0 },
+	[PERI1_SPI0_SSI_RST] = { 0, BIT(22), 0 },
+	[PERI1_UART0_PRST] = { 0, BIT(23), PERI1_UART0_S_RST },
+	[PERI1_UART0_S_RST] = { 0, BIT(24), 0 },
+	[PERI1_UART1_PRST] = { 0, BIT(25), PERI1_UART1_S_RST },
+	[PERI1_UART1_S_RST] = { 0, BIT(26), 0 },
+	[PERI1_UART2_PRST] = { 0, BIT(27), PERI1_UART2_S_RST },
+	[PERI1_UART2_S_RST] = { 0, BIT(28), 0 },
+	[PERI1_UART3_PRST] = { 0, BIT(29), PERI1_UART3_S_RST },
+	[PERI1_UART3_S_RST] = { 0, BIT(30), 0 },
+	[PERI1_X2H_GMAC0_ARST] = { 0, BIT(31), 0 },
+	[PERI1_X2H_GMAC0_HRST] = { 0x4, BIT(0), 0 },
+	[PERI1_X2H_GMAC1_ARST] = { 0x4, BIT(1), 0 },
+	[PERI1_X2H_GMAC1_HRST] = { 0x4, BIT(2), 0 },
+	[PERI1_DFMU_ARESET] = { 0x4, BIT(3), 0 },
+	[PERI1_DFMU_PRESET] = { 0x4, BIT(4), 0 },
+	[PERI1_PAD_CTRL_PRST] = { 0x4, BIT(5), 0 },
+	[PERI1_PDM0_MRST] = { 0x4, BIT(6), 0 },
+	[PERI1_PDM0_PRST] = { 0x4, BIT(7), 0 },
+	[PERI1_TDM0_RST] = { 0x4, BIT(8), 0 },
+	[PERI1_CAN0_IPG_PE_RST] = { 0x4, BIT(9), 0 },
+	[PERI1_CAN0_IPG_RST] = { 0x4, BIT(10), 0 },
+	[PERI1_CAN0_IPG_SOFT_RST] = { 0x4, BIT(11), 0 },
+	[PERI1_CAN0_IPG_TS_RST] = { 0x4, BIT(12), 0 },
+	[PERI1_CAN0_PRST] = { 0x4, BIT(13), 0 },
+	[PERI1_CAN1_IPG_PE_RST] = { 0x4, BIT(14), 0 },
+	[PERI1_CAN1_IPG_RST] = { 0x4, BIT(15), 0 },
+	[PERI1_CAN1_IPG_SOFT_RST] = { 0x4, BIT(16), 0 },
+	[PERI1_CAN1_IPG_TS_RST] = { 0x4, BIT(17), 0 },
+	[PERI1_CAN1_PRST] = { 0x4, BIT(18), 0 },
+	[PERI1_CHIP_DBG_ARST] = { 0x4, BIT(19), 0 },
+	[PERI1_CHIP_DBG_CRST] = { 0x4, BIT(20), 0 },
+	[PERI1_CHIP_DBG_PRST] = { 0x4, BIT(21), 0 },
+	[PERI1_GMAC_CRST] = { 0x4, BIT(22), 0 },
+	[PERI1_X2H_GMAC2_ARST] = { 0x4, BIT(23), 0 },
+	[PERI1_X2H_GMAC2_HRST] = { 0x4, BIT(24), 0 },
+	[PERI1_ZGMAC_X2X_ARST] = { 0x4, BIT(25), 0 },
+	[PERI1_SPI0_RST] = { 0, BIT(21) | BIT(22), 0 },
+	[PERI1_I2C0_RST] = { 0, BIT(8) | BIT(9), 0 },
+	[PERI1_I2C1_RST] = { 0, BIT(10) | BIT(11), 0 },
+	[PERI1_I2C2_RST] = { 0, BIT(12) | BIT(13), 0 },
+	[PERI1_GMAC0_RST] = { 0, BIT(0) | BIT(1) | BIT(31), 0 },
+	[PERI1_GMAC0_X2H_RST] = { 0x4, BIT(0), 0 },
+	[PERI1_GMAC1_RST] = { 0, BIT(2) | BIT(3), 0 },
+	[PERI1_GMAC1_X2H_RST] = { 0x4, BIT(1) | BIT(2), 0 },
+};
+
+static const struct a210_rst_signal peri2_rst_signals[] = {
+	[PERI2_CAN2_IPG_PE_RST] = { 0, BIT(0), 0 },
+	[PERI2_CAN2_IPG_RST] = { 0, BIT(1), 0 },
+	[PERI2_CAN2_IPG_SOFT_RST] = { 0, BIT(2), 0 },
+	[PERI2_CAN2_IPG_TS_RST] = { 0, BIT(3), 0 },
+	[PERI2_CAN2_PRST] = { 0, BIT(4), 0 },
+	[PERI2_GPIO2_DBRST] = { 0, BIT(5), 0 },
+	[PERI2_GPIO2_PRST] = { 0, BIT(6), 0 },
+	[PERI2_I2C4_IC_RST] = { 0, BIT(7), 0 },
+	[PERI2_I2C4_PRST] = { 0, BIT(8), 0 },
+	[PERI2_I2S2_PRST] = { 0, BIT(9), 0 },
+	[PERI2_SPI1_PRST] = { 0, BIT(10), 0 },
+	[PERI2_SPI1_SSI_RST] = { 0, BIT(11), 0 },
+	[PERI2_UART4_PRST] = { 0, BIT(12), PERI2_UART4_S_RST },
+	[PERI2_UART4_S_RST] = { 0, BIT(13), 0 },
+	[PERI2_UART5_PRST] = { 0, BIT(14), PERI2_UART5_S_RST },
+	[PERI2_UART5_S_RST] = { 0, BIT(15), 0 },
+	[PERI2_UART6_PRST] = { 0, BIT(16), PERI2_UART6_S_RST },
+	[PERI2_UART6_S_RST] = { 0, BIT(17), 0 },
+	[PERI2_PAD_CTRL_PRST] = { 0, BIT(18), 0 },
+	[PERI2_GPIO3_DBRST] = { 0, BIT(19), 0 },
+	[PERI2_GPIO3_PRST] = { 0, BIT(20), 0 },
+	[PERI2_I2C3_IC_RST] = { 0, BIT(21), 0 },
+	[PERI2_I2C3_PRST] = { 0, BIT(22), 0 },
+	[PERI2_I2C5_IC_RST] = { 0, BIT(23), 0 },
+	[PERI2_I2C5_PRST] = { 0, BIT(24), 0 },
+	[PERI2_I2C6_IC_RST] = { 0, BIT(25), 0 },
+	[PERI2_I2C6_PRST] = { 0, BIT(26), 0 },
+	[PERI2_I2C7_IC_RST] = { 0, BIT(27), 0 },
+	[PERI2_I2C7_PRST] = { 0, BIT(28), 0 },
+	[PERI2_I2S1_PRST] = { 0, BIT(29), 0 },
+	[PERI2_I2S3_PRST] = { 0, BIT(30), 0 },
+	[PERI2_UART7_PRST] = { 0, BIT(31), PERI2_UART7_S_RST },
+	[PERI2_UART7_S_RST] = { 0x4, BIT(0), 0 },
+	[PERI2_UART8_PRST] = { 0x4, BIT(1), PERI2_UART8_S_RST },
+	[PERI2_UART8_S_RST] = { 0x4, BIT(2), 0 },
+	[PERI2_UART9_PRST] = { 0x4, BIT(3), PERI2_UART9_S_RST },
+	[PERI2_UART9_S_RST] = { 0x4, BIT(4), 0 },
+	[PERI2_QSPI1_PRST] = { 0x4, BIT(5), 0 },
+	[PERI2_QSPI1_SSI_RST] = { 0x4, BIT(6), 0 },
+	[PERI2_PWM1_CRST] = { 0x4, BIT(7), 0 },
+	[PERI2_PWM1_PRST] = { 0x4, BIT(8), 0 },
+	[PERI2_PWM2_CRST] = { 0x4, BIT(9), 0 },
+	[PERI2_PWM2_PRST] = { 0x4, BIT(10), 0 },
+	[PERI2_I2C3_RST] = { 0, BIT(21) | BIT(22), 0 },
+	[PERI2_I2C4_RST] = { 0, BIT(7) | BIT(8), 0 },
+	[PERI2_I2C5_RST] = { 0, BIT(23) | BIT(24), 0 },
+	[PERI2_I2C6_RST] = { 0, BIT(25) | BIT(26), 0 },
+	[PERI2_I2C7_RST] = { 0, BIT(27) | BIT(28), 0 },
+	[PERI2_SPI1_RST] = { 0, BIT(10) | BIT(11), 0 },
+};
+
+static const struct a210_rst_signal peri3_rst_signals[] = {
+	[PERI3_DMAC_ARST] = { 0, BIT(0), 0 },
+	[PERI3_DMAC_HRST] = { 0, BIT(1), 0 },
+	[PERI3_EMMC_SDIO_CLKGEN_RST] = { 0, BIT(2), 0 },
+	[PERI3_EMMC_RST] = { 0, BIT(3), 0 },
+	[PERI3_EMMC_X2X_ARST_M] = { 0, BIT(4), 0 },
+	[PERI3_EMMC_X2X_ARST_S] = { 0, BIT(5), 0 },
+	[PERI3_SDIO_RST] = { 0, BIT(6), 0 },
+	[PERI3_SDIO_X2X_ARST_M] = { 0, BIT(7), 0 },
+	[PERI3_SDIO_X2X_ARST_S] = { 0, BIT(8), 0 },
+	[PERI3_AXI_MST_ARST] = { 0, BIT(9), 0 },
+	[PERI3_AXI_MST_PRST] = { 0, BIT(10), 0 },
+	[PERI3_ADC_PRST] = { 0, BIT(11), 0 },
+	[PERI3_TEE_X2X_ARST_M] = { 0, BIT(12), 0 },
+	[PERI3_TEE_X2X_ARST_S] = { 0, BIT(13), 0 },
+	[PERI3_TEE_H2H_HRST] = { 0, BIT(14), 0 },
+	[PERI3_GPIO4_DBRST] = { 0, BIT(15), 0 },
+	[PERI3_GPIO4_PRST] = { 0, BIT(16), 0 },
+	[PERI3_PAD_CTRL_PRST] = { 0, BIT(17), 0 },
+};
+
+static const struct a210_rst_signal pcie_rst_signals[] = {
+	[PCIE_X2X_PERI_SLV_ARST] = { 0, BIT(0), 0 },
+	[PCIE_X2X_PERI_MST_ARST] = { 0, BIT(4), 0 },
+	[PCIE_AXI4_PCIE_MST_ARST] = { 0, BIT(8), 0 },
+	[PCIE_AXI4_PCIE_MST_PRST] = { 0, BIT(12), 0 },
+	[PCIE_DFMU_PRST] = { 0x4, BIT(0), 0 },
+	[PCIE_DFMU_ARST] = { 0x4, BIT(4), 0 },
+	[PCIE_E16PHY_PHY_RST] = { 0x8, BIT(0), 0 },
+	[PCIE_E16PHY_APBS_PRST] = { 0x8, BIT(4), 0 },
+	[PCIE_X2X_SATA_MST_ARST] = { 0x10, BIT(0), 0 },
+	[PCIE_X2X_SATA_SLV_ARST] = { 0x10, BIT(4), 0 },
+	[PCIE_SATA_ARESET] = { 0x10, BIT(8), 0 },
+	[PCIE_SATA_RST_PMALIVE] = { 0x10, BIT(12), 0 },
+	[PCIE_SATA_SLV_AFENCE_ARST] = { 0x10, BIT(16), 0 },
+	[PCIE_SATA_MST_AFENCE_ARST] = { 0x10, BIT(20), 0 },
+	[PCIE_SATA_RST_ASIC0] = { 0x14, BIT(0), 0 },
+	[PCIE_SATA_RST_ASIC1] = { 0x14, BIT(4), 0 },
+	[PCIE_SATA_RST_RXOOB0] = { 0x14, BIT(8), 0 },
+	[PCIE_SATA_RST_RXOOB1] = { 0x14, BIT(12), 0 },
+	[PCIE_DM_GEN3X4_APBS_PRST] = { 0x20, BIT(0), 0 },
+	[PCIE_DM_GEN3X4_POWER_UP_RST] = { 0x20, BIT(4), 0 },
+	[PCIE_DM_SLV_AFENCE_ARST] = { 0x20, BIT(16), 0 },
+	[PCIE_DM_MST_AFENCE_ARST] = { 0x20, BIT(20), 0 },
+	[PCIE_RP_GEN3X1_APBS_PRST] = { 0x24, BIT(0), 0 },
+	[PCIE_RP_GEN3X1_POWER_UP_RST] = { 0x24, BIT(4), 0 },
+	[PCIE_RP_SLV_AFENCE_ARST] = { 0x24, BIT(16), 0 },
+	[PCIE_RP_MST_AFENCE_ARST] = { 0x24, BIT(20), 0 },
+};
+
+static const struct a210_rst_signal usb_rst_signals[] = {
+	[USB_DFMU_PRST] = { 0, BIT(0), 0 },
+	[USB_DFMU_ARST] = { 0, BIT(4), 0 },
+	[USB_AXI4_MST_ARST] = { 0, BIT(8), 0 },
+	[USB_AXI4_MST_PRST] = { 0, BIT(12), 0 },
+	[USB_DPTX_APBS_PRST] = { 0x4, BIT(0), 0 },
+	[USB_DPTX_VCC_RST] = { 0x4, BIT(4), 0 },
+	[USB_USB31_APBS_PRST] = { 0x8, BIT(0), 0 },
+	[USB_USB31_VCC_RST] = { 0x8, BIT(4), 0 },
+	[USB_USB31_PHY_RST] = { 0x8, BIT(8), 0 },
+	[USB_USB31_SLV_AFENCE_ARST] = { 0x8, BIT(12), 0 },
+	[USB_C10PHY_PHY_RST] = { 0xc, BIT(0), 0 },
+	[USB_C10PHY_APBS_PRST] = { 0xc, BIT(4), 0 },
+	[USB_USB20_BLK_X2H_HRST] = { 0x10, BIT(0), 0 },
+	[USB_USB20_BLK_X2H_ARST] = { 0x10, BIT(4), 0 },
+	[USB_USB20_SLV_AFENCE_ARST] = { 0x10, BIT(8), 0 },
+	[USB_USB20_BLK_H2P_HRST] = { 0x10, BIT(16), 0 },
+	[USB_USB20_BLK_AHB_SLV_HRST] = { 0x10, BIT(20), 0 },
+	[USB_USB20_BLK_AXI_MST_ARST] = { 0x10, BIT(24), 0 },
+	[USB_USB20_BLK_USB2_SYSREG_PRST] = { 0x10, BIT(28), 0 },
+	[USB_USB20_BLK_USB2_WRAP0_PRST] = { 0x14, BIT(0), 0 },
+	[USB_USB20_BLK_USB2_WRAP0_HRST] = { 0x14, BIT(4), 0 },
+	[USB_USB20_BLK_USB2_WRAP1_PRST] = { 0x14, BIT(8), 0 },
+	[USB_USB20_BLK_USB2_WRAP1_HRST] = { 0x14, BIT(12), 0 },
+	[USB_USB20_BLK_A2X0_HRST] = { 0x14, BIT(16), 0 },
+	[USB_USB20_BLK_A2X0_ARST] = { 0x14, BIT(20), 0 },
+	[USB_USB20_BLK_A2X1_HRST] = { 0x14, BIT(24), 0 },
+	[USB_USB20_BLK_A2X1_ARST] = { 0x14, BIT(28), 0 },
+	[USB_USB20_BLK_USB0_PHY_PON_RESET] = { 0x18, BIT(0), 0 },
+	[USB_USB20_BLK_USB1_PHY_PON_RESET] = { 0x18, BIT(4), 0 },
+	[USB_PERI2_SS_RST] = { 0x20, BIT(0), 0 },
+	[USB_PERI2_SLV_AFENCE_ARST] = { 0x20, BIT(4), 0 },
+};
+
+static const struct a210_rst_signal tee_rst_signals[] = {
+	[TEE_KEYRAM_PRST] = { 0, BIT(0), 0 },
+	[TEE_DS_PRST] = { 0, BIT(1), 0 },
+	[TEE_EFUSE_PRST] = { 0, BIT(2), 0 },
+	[TEE_OCRAM_HRST] = { 0, BIT(3), 0 },
+	[TEE_SYSREG_PRST] = { 0, BIT(4), 0 },
+	[TEE_CCU_PRST] = { 0, BIT(5), 0 },
+	[TEE_CCU_CRST] = { 0, BIT(6), 0 },
+	[TEE_EIP150B_HRST] = { 0, BIT(8), 0 },
+	[TEE_EIP120SIII_HRST] = { 0, BIT(9), 0 },
+	[TEE_EIP120SIII_ARST] = { 0, BIT(10), 0 },
+	[TEE_EIP120SII_HRST] = { 0, BIT(11), 0 },
+	[TEE_EIP120SII_ARST] = { 0, BIT(12), 0 },
+	[TEE_EIP120SI_HRST] = { 0, BIT(13), 0 },
+	[TEE_EIP120SI_ARST] = { 0, BIT(14), 0 },
+	[TEE_DMAC_HRST] = { 0, BIT(15), 0 },
+	[TEE_DMAC_ARST] = { 0, BIT(16), 0 },
+	[TEE_X2P_TEESYS_PRST] = { 0, BIT(24), 0 },
+	[TEE_X2P_TEESYS_ARST] = { 0, BIT(25), 0 },
+	[TEE_AXI4_TEESYS_ARST] = { 0, BIT(26), 0 },
+	[TEE_APB3_TEESYS_PRST] = { 0, BIT(27), 0 },
+	[TEE_APB3_TEESYS_HRST] = { 0, BIT(28), 0 },
+	[TEE_AHB2_TEESYS_HRST] = { 0, BIT(29), 0 },
+};
+
+static const struct a210_rst_signal gpu_rst_signals[] = {
+	[GPU_PWR_WRAP_RGX_HOOD_RST] = { 0, BIT(0), 0 },
+	[GPU_PWR_WRAP_DFMU_RST] = { 0, BIT(1), 0 },
+};
+
+static inline struct a210_reset *to_a210_reset(struct reset_controller_dev *rcdev)
+{
+	return container_of(rcdev, struct a210_reset, rcdev);
+}
+
+static int a210_reset_update(struct reset_controller_dev *rcdev,
+			     unsigned long id, bool assert)
+{
+	struct a210_reset *rst = to_a210_reset(rcdev);
+	const struct a210_rst_signal *signal;
+	unsigned long flags;
+	u32 value;
+	int ret = 0;
+
+	if (id >= rst->data->num_signals)
+		return -EINVAL;
+
+	spin_lock_irqsave(&rst->lock, flags);
+	do {
+		signal = &rst->data->signals[id];
+		value = readl(rst->base + signal->offset);
+		if (assert)
+			value &= ~signal->mask;
+		else
+			value |= signal->mask;
+		writel(value, rst->base + signal->offset);
+		/* Firmware can lock individual reset controls against AP writes. */
+		if ((readl(rst->base + signal->offset) & signal->mask) !=
+		    (value & signal->mask)) {
+			ret = -EIO;
+			break;
+		}
+		id = signal->nextid;
+	} while (id);
+	spin_unlock_irqrestore(&rst->lock, flags);
+
+	return ret;
+}
+
+static int a210_reset_assert(struct reset_controller_dev *rcdev, unsigned long id)
+{
+	return a210_reset_update(rcdev, id, true);
+}
+
+static int a210_reset_deassert(struct reset_controller_dev *rcdev, unsigned long id)
+{
+	return a210_reset_update(rcdev, id, false);
+}
+
+static int a210_reset_status(struct reset_controller_dev *rcdev, unsigned long id)
+{
+	struct a210_reset *rst = to_a210_reset(rcdev);
+	const struct a210_rst_signal *signal;
+	unsigned long flags;
+	bool asserted;
+
+	if (id >= rst->data->num_signals)
+		return -EINVAL;
+
+	/* The logical reset is asserted if any linked signal is asserted. */
+	spin_lock_irqsave(&rst->lock, flags);
+	do {
+		signal = &rst->data->signals[id];
+		asserted = (readl(rst->base + signal->offset) & signal->mask) !=
+			   signal->mask;
+		if (asserted)
+			break;
+		id = signal->nextid;
+	} while (id);
+	spin_unlock_irqrestore(&rst->lock, flags);
+
+	return asserted;
+}
+
+static const struct reset_control_ops a210_reset_ops = {
+	.assert = a210_reset_assert,
+	.deassert = a210_reset_deassert,
+	.status = a210_reset_status,
+};
+
+static int a210_reset_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct a210_reset *rst;
+
+	rst = devm_kzalloc(dev, sizeof(*rst), GFP_KERNEL);
+	if (!rst)
+		return -ENOMEM;
+
+	rst->data = device_get_match_data(dev);
+	if (!rst->data)
+		return -EINVAL;
+
+	rst->base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(rst->base))
+		return PTR_ERR(rst->base);
+
+	spin_lock_init(&rst->lock);
+	rst->rcdev.ops = &a210_reset_ops;
+	rst->rcdev.owner = THIS_MODULE;
+	rst->rcdev.dev = dev;
+	rst->rcdev.of_node = dev->of_node;
+	rst->rcdev.nr_resets = rst->data->num_signals;
+
+	return devm_reset_controller_register(dev, &rst->rcdev);
+}
+
+static const struct a210_reset_data vp_reset_data = {
+	.signals = vp_rst_signals,
+	.num_signals = ARRAY_SIZE(vp_rst_signals),
+};
+
+static const struct a210_reset_data vi_reset_data = {
+	.signals = vi_rst_signals,
+	.num_signals = ARRAY_SIZE(vi_rst_signals),
+};
+
+static const struct a210_reset_data npu_reset_data = {
+	.signals = npu_rst_signals,
+	.num_signals = ARRAY_SIZE(npu_rst_signals),
+};
+
+static const struct a210_reset_data vo_reset_data = {
+	.signals = vo_rst_signals,
+	.num_signals = ARRAY_SIZE(vo_rst_signals),
+};
+
+static const struct a210_reset_data peri0_reset_data = {
+	.signals = peri0_rst_signals,
+	.num_signals = ARRAY_SIZE(peri0_rst_signals),
+};
+
+static const struct a210_reset_data peri1_reset_data = {
+	.signals = peri1_rst_signals,
+	.num_signals = ARRAY_SIZE(peri1_rst_signals),
+};
+
+static const struct a210_reset_data peri2_reset_data = {
+	.signals = peri2_rst_signals,
+	.num_signals = ARRAY_SIZE(peri2_rst_signals),
+};
+
+static const struct a210_reset_data peri3_reset_data = {
+	.signals = peri3_rst_signals,
+	.num_signals = ARRAY_SIZE(peri3_rst_signals),
+};
+
+static const struct a210_reset_data pcie_reset_data = {
+	.signals = pcie_rst_signals,
+	.num_signals = ARRAY_SIZE(pcie_rst_signals),
+};
+
+static const struct a210_reset_data usb_reset_data = {
+	.signals = usb_rst_signals,
+	.num_signals = ARRAY_SIZE(usb_rst_signals),
+};
+
+static const struct a210_reset_data tee_reset_data = {
+	.signals = tee_rst_signals,
+	.num_signals = ARRAY_SIZE(tee_rst_signals),
+};
+
+static const struct a210_reset_data gpu_reset_data = {
+	.signals = gpu_rst_signals,
+	.num_signals = ARRAY_SIZE(gpu_rst_signals),
+};
+
+static const struct of_device_id a210_reset_of_match[] = {
+	{ .compatible = "zhihe,a210-vp-reset", .data = &vp_reset_data },
+	{ .compatible = "zhihe,a210-vi-reset", .data = &vi_reset_data },
+	{ .compatible = "zhihe,a210-npu-reset", .data = &npu_reset_data },
+	{ .compatible = "zhihe,a210-vo-reset", .data = &vo_reset_data },
+	{ .compatible = "zhihe,a210-peri0-reset", .data = &peri0_reset_data },
+	{ .compatible = "zhihe,a210-peri1-reset", .data = &peri1_reset_data },
+	{ .compatible = "zhihe,a210-peri2-reset", .data = &peri2_reset_data },
+	{ .compatible = "zhihe,a210-peri3-reset", .data = &peri3_reset_data },
+	{ .compatible = "zhihe,a210-pcie-reset", .data = &pcie_reset_data },
+	{ .compatible = "zhihe,a210-usb-reset", .data = &usb_reset_data },
+	{ .compatible = "zhihe,a210-tee-reset", .data = &tee_reset_data },
+	{ .compatible = "zhihe,a210-gpu-reset", .data = &gpu_reset_data },
+	{}
+};
+MODULE_DEVICE_TABLE(of, a210_reset_of_match);
+
+static struct platform_driver a210_reset_driver = {
+	.probe = a210_reset_probe,
+	.driver = {
+		.name = "a210-reset",
+		.of_match_table = a210_reset_of_match,
+	},
+};
+module_platform_driver(a210_reset_driver);
+
+MODULE_AUTHOR("Zhiguo Zhu <zhiguo.zhu@linux.alibaba.com>");
+MODULE_DESCRIPTION("Zhihe A210 reset controller driver");
+MODULE_LICENSE("GPL");

-- 
2.55.0


^ permalink raw reply	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2026-10-22  9:22 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-21 19:53 [PATCH 00/18] riscv: add initial support for Zhihe A210 and Melon Pi Han Gao via B4 Relay
2026-10-21 19:53 ` [PATCH 01/18] dt-bindings: vendor-prefixes: add Zhihe Han Gao via B4 Relay
2026-10-21 19:53 ` [PATCH 02/18] riscv: add Zhihe A210 support Han Gao via B4 Relay
2026-10-21 19:53 ` [PATCH 03/18] dt-bindings: clock: add Zhihe A210 clock controllers Han Gao via B4 Relay
2026-10-21 19:53 ` [PATCH 04/18] dt-bindings: clock: add Zhihe A210 AON clock controller Han Gao via B4 Relay
2026-10-21 19:53 ` [PATCH 05/18] clk: zhihe: add A210 support Han Gao via B4 Relay
2026-10-21 19:53 ` [PATCH 06/18] dt-bindings: reset: add Zhihe A210 reset controllers Han Gao via B4 Relay
2026-10-21 19:53 ` [PATCH 07/18] reset: zhihe: add A210 support Han Gao via B4 Relay
2026-10-22  9:22   ` Philipp Zabel
2026-10-21 19:53 ` [PATCH 08/18] dt-bindings: pinctrl: add Zhihe A210 pin controller Han Gao via B4 Relay
2026-10-21 19:53 ` [PATCH 09/18] pinctrl: zhihe: add A210 support Han Gao via B4 Relay
2026-10-21 19:53 ` [PATCH 10/18] dt-bindings: interrupt-controller: add Zhihe A210 PLIC Han Gao via B4 Relay
2026-10-21 19:53 ` [PATCH 11/18] dt-bindings: riscv: add Melon Pi V1 and V2 Han Gao via B4 Relay
2026-10-21 19:53 ` [PATCH 12/18] dt-bindings: timer: add Zhihe A210 CLINT Han Gao via B4 Relay
2026-10-21 19:53 ` [PATCH 13/18] riscv: dts: zhihe: add A210 core support Han Gao via B4 Relay
2026-10-21 19:53 ` [PATCH 14/18] riscv: dts: zhihe: add A210 UARTs Han Gao via B4 Relay
2026-10-22  9:22   ` Philipp Zabel
2026-10-21 19:53 ` [PATCH 15/18] riscv: dts: zhihe: add A210 module memory Han Gao via B4 Relay
2026-10-21 19:53 ` [PATCH 16/18] riscv: dts: zhihe: add Melon Pi V1 and V2 Han Gao via B4 Relay
2026-10-21 19:53 ` [PATCH 17/18] riscv: defconfig: enable A210 support Han Gao via B4 Relay
2026-10-21 19:53 ` [PATCH 18/18] MAINTAINERS: add Zhihe A210 Han Gao via B4 Relay
  -- strict thread matches above, loose matches on Subject: below --
2026-10-21 19:48 [PATCH 00/18] riscv: add initial support for Zhihe A210 and Melon Pi Han Gao
2026-10-21 19:48 ` [PATCH 07/18] reset: zhihe: add A210 support Han Gao

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®