Linux clock framework development
 help / color / mirror / Atom feed
* [PATCH RFC v3 00/17] riscv: add initial Zhihe A210 support using SCMI clocks and resets
@ 2026-11-02 19:45 Han Gao via B4 Relay
  2026-11-02 19:45 ` [PATCH RFC v3 01/17] firmware: arm_scmi: Drop the ARM architecture dependency Han Gao via B4 Relay
                   ` (16 more replies)
  0 siblings, 17 replies; 19+ messages in thread
From: Han Gao via B4 Relay @ 2026-11-02 19:45 UTC (permalink / raw)
  To: Sudeep Holla, Cristian Marussi, Michal Simek, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Paul Walmsley, Palmer Dabbelt,
	Albert Ou, Alexandre Ghiti, Zhiguo Zhu, Jassi Brar, Linus Walleij,
	Uwe Kleine-König, Bartosz Golaszewski, Philipp Zabel,
	Thomas Gleixner, Radu Rendec, Samuel Holland, Daniel Lezcano,
	Anup Patel, Stephen Boyd, Brian Masney, Jerome Brunet,
	Greg Kroah-Hartman, Jiri Slaby, Drew Fustini, Icenowy Zheng,
	Inochi Amaoto, Vivian Wang, Yao Zi, Jiaxun Yang
  Cc: arm-scmi, linux-arm-kernel, linux-kernel, devicetree, linux-riscv,
	linux-gpio, Paul Walmsley, linux-clk, linux-serial, Han Gao,
	Han Gao, Conor Dooley

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

The A210 has four C908V and four C920V2 cores, plus an E902 management
core. The E902 firmware handles clocks, resets, power, the PMIC and
CPU DVFS, so Linux uses SCMI for clocks and resets. The only new SCMI
piece is the mailbox to the E902. [2] explains why I picked SCMI over
RPMI.

The series adds the mailbox, the pin controller, the UARTs and their
bindings and DTs. On v7.4-rc1 with the riscv defconfig, a Melon Pi V2
boots to a shell on the serial console with all eight CPUs online.

The numbering follows [1], as Bartosz asked, so the RFC [2] is v2 and
this is v3.

Conor asked about vendor firmware. We are talking to Zhihe about SCMI
support in their firmware. Until that is settled, mainline needs the
firmware below, so this is still an RFC.

The E902 runs a Zephyr based SCMI server [3]. The rest of the boot
chain is coreboot [4], OpenSBI [5] and EDK2 [6][7]. The full Linux tree
with the other peripherals is at [8].

[1] https://lore.kernel.org/r/20261022-a210-init-v1-0-5e438f972d24@iscas.ac.cn
[2] https://lore.kernel.org/r/20261027-a210-scmi-v1-0-74d58ce85bd8@iscas.ac.cn
[3] https://github.com/RevySR/zephyr/tree/xuantie/scmi-v3
[4] https://github.com/revyos/coreboot/tree/a210/scmi-v3
[5] https://github.com/revyos/opensbi/tree/a210/scmi-v3
[6] https://github.com/revyos/edk2/tree/a210/scmi-v3
[7] https://github.com/revyos/ruyiedk2/tree/a210/scmi-v3
[8] https://github.com/RevySR/linux/tree/a210/scmi-v3

Signed-off-by: Han Gao <gaohan@iscas.ac.cn>
---
Changes in v3:
- Rebase on v7.4-rc1, and add zhihe,a210-uart to the list of DW APB
  UARTs with two resets.
- arm_scmi: drop the ARM dependency instead of adding RISCV (Michal).
  Build tested on x86_64 without OF, i386, loongarch64, ppc64le and
  riscv64 (Sudeep).
- Move the SCMI clock and reset IDs from dt-bindings to headers next
  to the DTS, as the firmware assigns them (Conor).
- mailbox binding: use fixed "local" and "remote" regions and add blank
  lines between properties (Conor). Drop the clocks, as the firmware
  keeps the mailboxes running, and call it a mailbox, not a doorbell.
- mailbox driver: don't request a shared interrupt.
- pinctrl: rename to pinctrl-zhihe-a210.c and PINCTRL_ZHIHE_A210, drop
  the 64BIT dependency and a forward declaration, comment the register
  layout and the ____ placeholder, and round drive strength up (Linus).
  Don't include mod_devicetable.h (Uwe).
- pinctrl: drop PERI3. It comes back with the SDIO controller, as pins
  and function, with the shared mux handled in the driver (Conor).
- pinctrl: use one function name per kind, like gpio, spi or pwm, and
  number them only where a pad can pick an instance, as for the UARTs
  (Conor).
- pinctrl: use pm_sleep_ptr() instead of #ifdef CONFIG_PM_SLEEP, and
  don't use dev_err_probe() in resume.
- defconfig: drop SRAM, the SCMI mailbox transport and the SCMI reset
  driver. SCMI maps its shared memory itself, and the other two are
  enabled by default with SCMI. Shorten the NR_UARTS explanation.
- dts: use 0x1000 regions for uart0 and uart4, like the other UARTs.
- dts: describe the PLIC M-mode contexts with 11 instead of -1.
- Spell the vendor name Zhihe everywhere.
- Add Conor's acks.
- Link to v2 (sent as RFC): https://patch.msgid.link/20261027-a210-scmi-v1-0-74d58ce85bd8@iscas.ac.cn

Changes in v2 (sent as RFC):
- Replace the native clock and reset drivers with SCMI. Conor pointed
  out that the clock blocks were not modelled right, and the E902
  firmware uses those registers too.
- Add the AP to E902 mailbox driver as the SCMI transport, and allow
  arm_scmi transports on RISC-V.
- Add dt-bindings headers for the SCMI clock and reset IDs.
- Add zhihe,a210-uart with separate APB and serial resets (Philipp).
- pinctrl: take the pad resets from SCMI, explain the SDIO pad names
  and the shared SDIO mux bit, and order pin nodes as pins, function,
  then config (Conor).
- defconfig: explain why SERIAL_8250_NR_UARTS is 10 (Conor).
- Link to v1: https://patch.msgid.link/20261022-a210-init-v1-0-5e438f972d24@iscas.ac.cn

---
Han Gao (9):
      firmware: arm_scmi: Drop the ARM architecture dependency
      dt-bindings: mailbox: add Zhihe A210 AP to E902 mailbox
      mailbox: add Zhihe A210 AP to E902 mailbox driver
      dt-bindings: timer: add Zhihe A210 CLINT
      dt-bindings: serial: snps-dw-apb-uart: add Zhihe A210 UART
      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 (8):
      dt-bindings: vendor-prefixes: add Zhihe
      riscv: add Zhihe 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

 .../interrupt-controller/sifive,plic-1.0.0.yaml    |   1 +
 .../bindings/mailbox/zhihe,a210-ap-mailbox.yaml    |  67 ++
 .../bindings/pinctrl/zhihe,a210-pinctrl.yaml       | 146 +++
 Documentation/devicetree/bindings/riscv/zhihe.yaml |  27 +
 .../bindings/serial/snps-dw-apb-uart.yaml          |   6 +-
 .../devicetree/bindings/timer/sifive,clint.yaml    |   1 +
 .../devicetree/bindings/vendor-prefixes.yaml       |   2 +
 MAINTAINERS                                        |  12 +
 arch/riscv/Kconfig.socs                            |  10 +
 arch/riscv/boot/dts/Makefile                       |   1 +
 arch/riscv/boot/dts/zhihe/Makefile                 |   2 +
 arch/riscv/boot/dts/zhihe/a210-clock.h             |  15 +
 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-reset.h             |  13 +
 arch/riscv/boot/dts/zhihe/a210-som.dtsi            |  11 +
 arch/riscv/boot/dts/zhihe/a210.dtsi                | 593 ++++++++++++
 arch/riscv/configs/defconfig                       |   7 +
 drivers/firmware/arm_scmi/Kconfig                  |   1 -
 drivers/mailbox/Kconfig                            |   9 +
 drivers/mailbox/Makefile                           |   2 +
 drivers/mailbox/mailbox-a210.c                     | 176 ++++
 drivers/pinctrl/Kconfig                            |  13 +
 drivers/pinctrl/Makefile                           |   1 +
 drivers/pinctrl/pinctrl-zhihe-a210.c               | 996 +++++++++++++++++++++
 26 files changed, 2183 insertions(+), 2 deletions(-)
---
base-commit: 6628e7d4c6b25c8d18f1345e3a20d21829aae7e4
change-id: 20261027-a210-scmi-ec32fdc246a6

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



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

* [PATCH RFC v3 01/17] firmware: arm_scmi: Drop the ARM architecture dependency
  2026-11-02 19:45 [PATCH RFC v3 00/17] riscv: add initial Zhihe A210 support using SCMI clocks and resets Han Gao via B4 Relay
@ 2026-11-02 19:45 ` Han Gao via B4 Relay
  2026-11-02 19:55   ` sashiko-bot
  2026-11-02 19:45 ` [PATCH RFC v3 02/17] dt-bindings: vendor-prefixes: add Zhihe Han Gao via B4 Relay
                   ` (15 subsequent siblings)
  16 siblings, 1 reply; 19+ messages in thread
From: Han Gao via B4 Relay @ 2026-11-02 19:45 UTC (permalink / raw)
  To: Sudeep Holla, Cristian Marussi, Michal Simek, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Paul Walmsley, Palmer Dabbelt,
	Albert Ou, Alexandre Ghiti, Zhiguo Zhu, Jassi Brar, Linus Walleij,
	Uwe Kleine-König, Bartosz Golaszewski, Philipp Zabel,
	Thomas Gleixner, Radu Rendec, Samuel Holland, Daniel Lezcano,
	Anup Patel, Stephen Boyd, Brian Masney, Jerome Brunet,
	Greg Kroah-Hartman, Jiri Slaby, Drew Fustini, Icenowy Zheng,
	Inochi Amaoto, Vivian Wang, Yao Zi, Jiaxun Yang
  Cc: arm-scmi, linux-arm-kernel, linux-kernel, devicetree, linux-riscv,
	linux-gpio, Paul Walmsley, linux-clk, linux-serial, Han Gao,
	Han Gao

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

The SCMI core and the mailbox and shared memory transports only use
generic kernel interfaces. Transports that need architecture support,
such as SMC, already carry their own dependencies.

Drop the ARM and ARM64 dependency so that other architectures can use
SCMI.

Suggested-by: Michal Simek <michal.simek@amd.com>
Signed-off-by: Han Gao <gaohan@iscas.ac.cn>
---
 drivers/firmware/arm_scmi/Kconfig | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/firmware/arm_scmi/Kconfig b/drivers/firmware/arm_scmi/Kconfig
index 783c24a20e29..b56aed46a387 100644
--- a/drivers/firmware/arm_scmi/Kconfig
+++ b/drivers/firmware/arm_scmi/Kconfig
@@ -3,7 +3,6 @@ menu "ARM System Control and Management Interface Protocol"
 
 config ARM_SCMI_PROTOCOL
 	tristate "ARM System Control and Management Interface (SCMI) Message Protocol"
-	depends on ARM || ARM64 || COMPILE_TEST
 	help
 	  ARM System Control and Management Interface (SCMI) protocol is a
 	  set of operating system-independent software interfaces that are

-- 
2.55.0



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

* [PATCH RFC v3 02/17] dt-bindings: vendor-prefixes: add Zhihe
  2026-11-02 19:45 [PATCH RFC v3 00/17] riscv: add initial Zhihe A210 support using SCMI clocks and resets Han Gao via B4 Relay
  2026-11-02 19:45 ` [PATCH RFC v3 01/17] firmware: arm_scmi: Drop the ARM architecture dependency Han Gao via B4 Relay
@ 2026-11-02 19:45 ` Han Gao via B4 Relay
  2026-11-02 19:45 ` [PATCH RFC v3 03/17] riscv: add Zhihe A210 support Han Gao via B4 Relay
                   ` (14 subsequent siblings)
  16 siblings, 0 replies; 19+ messages in thread
From: Han Gao via B4 Relay @ 2026-11-02 19:45 UTC (permalink / raw)
  To: Sudeep Holla, Cristian Marussi, Michal Simek, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Paul Walmsley, Palmer Dabbelt,
	Albert Ou, Alexandre Ghiti, Zhiguo Zhu, Jassi Brar, Linus Walleij,
	Uwe Kleine-König, Bartosz Golaszewski, Philipp Zabel,
	Thomas Gleixner, Radu Rendec, Samuel Holland, Daniel Lezcano,
	Anup Patel, Stephen Boyd, Brian Masney, Jerome Brunet,
	Greg Kroah-Hartman, Jiri Slaby, Drew Fustini, Icenowy Zheng,
	Inochi Amaoto, Vivian Wang, Yao Zi, Jiaxun Yang
  Cc: arm-scmi, linux-arm-kernel, linux-kernel, devicetree, linux-riscv,
	linux-gpio, Paul Walmsley, linux-clk, linux-serial, Han Gao,
	Han Gao, Conor Dooley

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>
Acked-by: Conor Dooley <conor.dooley@microchip.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 5471a06f93f1..e6db332510bc 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.yaml
+++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml
@@ -1995,6 +1995,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 related	[flat|nested] 19+ messages in thread

* [PATCH RFC v3 03/17] riscv: add Zhihe A210 support
  2026-11-02 19:45 [PATCH RFC v3 00/17] riscv: add initial Zhihe A210 support using SCMI clocks and resets Han Gao via B4 Relay
  2026-11-02 19:45 ` [PATCH RFC v3 01/17] firmware: arm_scmi: Drop the ARM architecture dependency Han Gao via B4 Relay
  2026-11-02 19:45 ` [PATCH RFC v3 02/17] dt-bindings: vendor-prefixes: add Zhihe Han Gao via B4 Relay
@ 2026-11-02 19:45 ` Han Gao via B4 Relay
  2026-11-02 19:45 ` [PATCH RFC v3 04/17] dt-bindings: mailbox: add Zhihe A210 AP to E902 mailbox Han Gao via B4 Relay
                   ` (13 subsequent siblings)
  16 siblings, 0 replies; 19+ messages in thread
From: Han Gao via B4 Relay @ 2026-11-02 19:45 UTC (permalink / raw)
  To: Sudeep Holla, Cristian Marussi, Michal Simek, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Paul Walmsley, Palmer Dabbelt,
	Albert Ou, Alexandre Ghiti, Zhiguo Zhu, Jassi Brar, Linus Walleij,
	Uwe Kleine-König, Bartosz Golaszewski, Philipp Zabel,
	Thomas Gleixner, Radu Rendec, Samuel Holland, Daniel Lezcano,
	Anup Patel, Stephen Boyd, Brian Masney, Jerome Brunet,
	Greg Kroah-Hartman, Jiri Slaby, Drew Fustini, Icenowy Zheng,
	Inochi Amaoto, Vivian Wang, Yao Zi, Jiaxun Yang
  Cc: arm-scmi, linux-arm-kernel, linux-kernel, devicetree, linux-riscv,
	linux-gpio, Paul Walmsley, linux-clk, linux-serial, Han Gao,
	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..9e096feb79b9 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 C908V and four C920V2 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 related	[flat|nested] 19+ messages in thread

* [PATCH RFC v3 04/17] dt-bindings: mailbox: add Zhihe A210 AP to E902 mailbox
  2026-11-02 19:45 [PATCH RFC v3 00/17] riscv: add initial Zhihe A210 support using SCMI clocks and resets Han Gao via B4 Relay
                   ` (2 preceding siblings ...)
  2026-11-02 19:45 ` [PATCH RFC v3 03/17] riscv: add Zhihe A210 support Han Gao via B4 Relay
@ 2026-11-02 19:45 ` Han Gao via B4 Relay
  2026-11-02 19:45 ` [PATCH RFC v3 05/17] mailbox: add Zhihe A210 AP to E902 mailbox driver Han Gao via B4 Relay
                   ` (12 subsequent siblings)
  16 siblings, 0 replies; 19+ messages in thread
From: Han Gao via B4 Relay @ 2026-11-02 19:45 UTC (permalink / raw)
  To: Sudeep Holla, Cristian Marussi, Michal Simek, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Paul Walmsley, Palmer Dabbelt,
	Albert Ou, Alexandre Ghiti, Zhiguo Zhu, Jassi Brar, Linus Walleij,
	Uwe Kleine-König, Bartosz Golaszewski, Philipp Zabel,
	Thomas Gleixner, Radu Rendec, Samuel Holland, Daniel Lezcano,
	Anup Patel, Stephen Boyd, Brian Masney, Jerome Brunet,
	Greg Kroah-Hartman, Jiri Slaby, Drew Fustini, Icenowy Zheng,
	Inochi Amaoto, Vivian Wang, Yao Zi, Jiaxun Yang
  Cc: arm-scmi, linux-arm-kernel, linux-kernel, devicetree, linux-riscv,
	linux-gpio, Paul Walmsley, linux-clk, linux-serial, Han Gao,
	Han Gao

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

The Zhihe A210 has an E902 management core next to its application
processors. Each side owns a mailbox block and rings the other side by
writing to its slice of the other side's mailbox.

The application processors ring E902 through their slice of the E902
mailbox. E902 rings back through the application processor mailbox and
writes INFO0 or INFO1 there to say which of its two doorbells it rang.
The doorbells carry no data, and clients such as SCMI keep their
messages in shared memory.

Signed-off-by: Han Gao <gaohan@iscas.ac.cn>
---
 .../bindings/mailbox/zhihe,a210-ap-mailbox.yaml    | 67 ++++++++++++++++++++++
 1 file changed, 67 insertions(+)

diff --git a/Documentation/devicetree/bindings/mailbox/zhihe,a210-ap-mailbox.yaml b/Documentation/devicetree/bindings/mailbox/zhihe,a210-ap-mailbox.yaml
new file mode 100644
index 000000000000..7d7ab1c550a0
--- /dev/null
+++ b/Documentation/devicetree/bindings/mailbox/zhihe,a210-ap-mailbox.yaml
@@ -0,0 +1,67 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mailbox/zhihe,a210-ap-mailbox.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Zhihe A210 application processor to E902 mailbox
+
+maintainers:
+  - Han Gao <gaohan@iscas.ac.cn>
+
+description: |
+  The A210 application processors and the E902 always-on core each own a
+  mailbox. A core raises an interrupt on the other side by writing the
+  generate register of the other core's mailbox, and can leave a value in one
+  of the INFO registers there to identify the request. The application
+  processor side therefore needs its own mailbox, which holds the INFO
+  registers written by E902 and the interrupt status, clear and mask
+  registers, and the slice of the E902 mailbox assigned to it.
+
+  The E902 firmware keeps both mailboxes clocked and out of reset. Their
+  clocks and resets are not controlled from the application processors.
+
+properties:
+  compatible:
+    const: zhihe,a210-ap-mailbox
+
+  reg:
+    items:
+      - description: Application processor mailbox
+      - description: Application processor slice of the E902 mailbox
+
+  reg-names:
+    items:
+      - const: local
+      - const: remote
+
+  interrupts:
+    maxItems: 1
+
+  '#mbox-cells':
+    const: 1
+    description:
+      Doorbell index, 0 or 1. E902 writes INFO0 or INFO1 of the application
+      processor mailbox to tell which doorbell it rings. Only doorbell 0 can
+      also be rung by the application processor.
+
+required:
+  - compatible
+  - reg
+  - reg-names
+  - interrupts
+  - '#mbox-cells'
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/irq.h>
+
+    mailbox@320000 {
+        compatible = "zhihe,a210-ap-mailbox";
+        reg = <0x320000 0x2000>, <0x311000 0x1000>;
+        reg-names = "local", "remote";
+        interrupts = <336 IRQ_TYPE_LEVEL_HIGH>;
+        #mbox-cells = <1>;
+    };

-- 
2.55.0



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

* [PATCH RFC v3 05/17] mailbox: add Zhihe A210 AP to E902 mailbox driver
  2026-11-02 19:45 [PATCH RFC v3 00/17] riscv: add initial Zhihe A210 support using SCMI clocks and resets Han Gao via B4 Relay
                   ` (3 preceding siblings ...)
  2026-11-02 19:45 ` [PATCH RFC v3 04/17] dt-bindings: mailbox: add Zhihe A210 AP to E902 mailbox Han Gao via B4 Relay
@ 2026-11-02 19:45 ` Han Gao via B4 Relay
  2026-11-02 19:45 ` [PATCH RFC v3 06/17] dt-bindings: pinctrl: add Zhihe A210 pin controller Han Gao via B4 Relay
                   ` (11 subsequent siblings)
  16 siblings, 0 replies; 19+ messages in thread
From: Han Gao via B4 Relay @ 2026-11-02 19:45 UTC (permalink / raw)
  To: Sudeep Holla, Cristian Marussi, Michal Simek, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Paul Walmsley, Palmer Dabbelt,
	Albert Ou, Alexandre Ghiti, Zhiguo Zhu, Jassi Brar, Linus Walleij,
	Uwe Kleine-König, Bartosz Golaszewski, Philipp Zabel,
	Thomas Gleixner, Radu Rendec, Samuel Holland, Daniel Lezcano,
	Anup Patel, Stephen Boyd, Brian Masney, Jerome Brunet,
	Greg Kroah-Hartman, Jiri Slaby, Drew Fustini, Icenowy Zheng,
	Inochi Amaoto, Vivian Wang, Yao Zi, Jiaxun Yang
  Cc: arm-scmi, linux-arm-kernel, linux-kernel, devicetree, linux-riscv,
	linux-gpio, Paul Walmsley, linux-clk, linux-serial, Han Gao,
	Han Gao

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

Add a mailbox controller for the doorbells between the A210 application
processors and the E902 management core. It serves as the SCMI
transport to the E902 firmware.

Channel 0 rings E902 and receives its completions. Channel 1 is receive
only and carries E902 notifications. Both share one interrupt, and E902
writes INFO0 or INFO1 to tell them apart.

The E902 firmware keeps both mailboxes clocked and out of reset, so the
driver does not manage clocks or resets.

Signed-off-by: Han Gao <gaohan@iscas.ac.cn>
---
 drivers/mailbox/Kconfig        |   9 +++
 drivers/mailbox/Makefile       |   2 +
 drivers/mailbox/mailbox-a210.c | 176 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 187 insertions(+)

diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig
index ab869769e278..6d620b0dde6f 100644
--- a/drivers/mailbox/Kconfig
+++ b/drivers/mailbox/Kconfig
@@ -409,4 +409,13 @@ config AXIADO_MAILBOX
 	  Axiado SoCs.
 	  If unsure, say N.
 
+config ZHIHE_A210_MBOX
+	bool "Zhihe A210 AP to E902 mailbox"
+	depends on OF && (ARCH_ZHIHE || COMPILE_TEST)
+	help
+	  Mailbox driver for the doorbells between the application
+	  processors and the E902 management core of the Zhihe A210. The
+	  doorbells carry no data, so clients pass their messages through
+	  shared memory. Say Y to use the SCMI firmware on the E902.
+
 endif
diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile
index 45dc59bb3e7f..f537ebb8aaff 100644
--- a/drivers/mailbox/Makefile
+++ b/drivers/mailbox/Makefile
@@ -86,3 +86,5 @@ obj-$(CONFIG_BCM74110_MAILBOX)	+= bcm74110-mailbox.o
 obj-$(CONFIG_RISCV_SBI_MPXY_MBOX)	+= riscv-sbi-mpxy-mbox.o
 
 obj-$(CONFIG_AXIADO_MAILBOX)	+= axiado-mailbox.o
+
+obj-$(CONFIG_ZHIHE_A210_MBOX) += mailbox-a210.o
diff --git a/drivers/mailbox/mailbox-a210.c b/drivers/mailbox/mailbox-a210.c
new file mode 100644
index 000000000000..0b66fded6b09
--- /dev/null
+++ b/drivers/mailbox/mailbox-a210.c
@@ -0,0 +1,176 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Zhihe A210 application processor to E902 mailbox */
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/mailbox_controller.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+
+/* The local mailbox holds the INFO bank and, one page up, the AP interrupt. */
+#define A210_MBOX_STATUS		0x1000
+#define A210_MBOX_CLEAR		0x1004
+#define A210_MBOX_MASK		0x100c
+#define A210_MBOX_GENERATE	0x10
+#define A210_MBOX_INFO(n)	(0x14 + 4 * (n))
+#define A210_MBOX_E902_PENDING	BIT(0)
+#define A210_MBOX_NOTIFY		BIT(6)
+
+/* Channel 0 carries AP requests and completions, channel 1 E902 notifications. */
+#define A210_MBOX_CHANS		2
+
+struct a210_mbox {
+	struct mbox_controller controller;
+	struct mbox_chan channels[A210_MBOX_CHANS];
+	void __iomem *local;
+	void __iomem *remote;
+	/* Protects the shared interrupt mask and the set of started channels. */
+	spinlock_t lock;
+	unsigned long started;
+	int irq;
+};
+
+static void a210_mbox_mask(struct a210_mbox *mbox, unsigned int index, bool enable)
+{
+	unsigned long flags;
+	u32 value;
+
+	spin_lock_irqsave(&mbox->lock, flags);
+	if (enable)
+		__set_bit(index, &mbox->started);
+	else
+		__clear_bit(index, &mbox->started);
+	value = readl(mbox->local + A210_MBOX_MASK);
+	if (mbox->started)
+		value |= A210_MBOX_E902_PENDING;
+	else
+		value &= ~A210_MBOX_E902_PENDING;
+	writel(value, mbox->local + A210_MBOX_MASK);
+	spin_unlock_irqrestore(&mbox->lock, flags);
+}
+
+static irqreturn_t a210_mbox_irq(int irq, void *data)
+{
+	struct a210_mbox *mbox = data;
+
+	if (!(readl(mbox->local + A210_MBOX_MASK) & A210_MBOX_E902_PENDING))
+		return IRQ_NONE;
+	if (!(readl(mbox->local + A210_MBOX_STATUS) & A210_MBOX_E902_PENDING))
+		return IRQ_NONE;
+
+	writel(A210_MBOX_E902_PENDING, mbox->local + A210_MBOX_CLEAR);
+
+	/* E902 sets INFO<n> before ringing the shared doorbell for channel n. */
+	for (unsigned int i = 0; i < A210_MBOX_CHANS; i++) {
+		if (!readl(mbox->local + A210_MBOX_INFO(i)))
+			continue;
+		writel(0, mbox->local + A210_MBOX_INFO(i));
+		if (test_bit(i, &mbox->started))
+			mbox_chan_received_data(&mbox->channels[i], NULL);
+	}
+	return IRQ_HANDLED;
+}
+
+static unsigned int a210_mbox_index(struct a210_mbox *mbox, struct mbox_chan *channel)
+{
+	return channel - mbox->channels;
+}
+
+static int a210_mbox_send(struct mbox_chan *channel, void *data)
+{
+	struct a210_mbox *mbox = channel->con_priv;
+
+	/* E902 notifications are receive-only. */
+	if (a210_mbox_index(mbox, channel))
+		return -EINVAL;
+
+	/* Payload and completion ownership belong to the shared-memory client. */
+	writel(A210_MBOX_NOTIFY, mbox->remote + A210_MBOX_GENERATE);
+	return 0;
+}
+
+static int a210_mbox_startup(struct mbox_chan *channel)
+{
+	struct a210_mbox *mbox = channel->con_priv;
+	unsigned int index = a210_mbox_index(mbox, channel);
+
+	writel(0, mbox->local + A210_MBOX_INFO(index));
+	a210_mbox_mask(mbox, index, true);
+	return 0;
+}
+
+static void a210_mbox_shutdown(struct mbox_chan *channel)
+{
+	struct a210_mbox *mbox = channel->con_priv;
+
+	a210_mbox_mask(mbox, a210_mbox_index(mbox, channel), false);
+	synchronize_irq(mbox->irq);
+}
+
+static const struct mbox_chan_ops a210_mbox_ops = {
+	.send_data = a210_mbox_send,
+	.startup = a210_mbox_startup,
+	.shutdown = a210_mbox_shutdown,
+};
+
+static int a210_mbox_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct a210_mbox *mbox;
+	int ret;
+
+	mbox = devm_kzalloc(dev, sizeof(*mbox), GFP_KERNEL);
+	if (!mbox)
+		return -ENOMEM;
+
+	mbox->local = devm_platform_ioremap_resource_byname(pdev, "local");
+	if (IS_ERR(mbox->local))
+		return PTR_ERR(mbox->local);
+	mbox->remote = devm_platform_ioremap_resource_byname(pdev, "remote");
+	if (IS_ERR(mbox->remote))
+		return PTR_ERR(mbox->remote);
+	mbox->irq = platform_get_irq(pdev, 0);
+	if (mbox->irq < 0)
+		return mbox->irq;
+
+	spin_lock_init(&mbox->lock);
+	a210_mbox_mask(mbox, 0, false);
+	for (unsigned int i = 0; i < A210_MBOX_CHANS; i++)
+		mbox->channels[i].con_priv = mbox;
+	/*
+	 * Neither txdone_irq nor txdone_poll is set: the client acknowledges
+	 * completion after consuming shared memory.
+	 */
+	mbox->controller.dev = dev;
+	mbox->controller.chans = mbox->channels;
+	mbox->controller.num_chans = A210_MBOX_CHANS;
+	mbox->controller.ops = &a210_mbox_ops;
+
+	ret = devm_request_irq(dev, mbox->irq, a210_mbox_irq, 0, dev_name(dev),
+			       mbox);
+	if (ret)
+		return ret;
+
+	return devm_mbox_controller_register(dev, &mbox->controller);
+}
+
+static const struct of_device_id a210_mbox_match[] = {
+	{ .compatible = "zhihe,a210-ap-mailbox" },
+	{}
+};
+MODULE_DEVICE_TABLE(of, a210_mbox_match);
+
+static struct platform_driver a210_mbox_driver = {
+	.probe = a210_mbox_probe,
+	.driver = {
+		.name = "a210-mailbox",
+		.of_match_table = a210_mbox_match,
+		/* Running E902 firmware continuously accesses the remote bank. */
+		.suppress_bind_attrs = true,
+	},
+};
+module_platform_driver(a210_mbox_driver);
+
+MODULE_AUTHOR("Han Gao <gaohan@iscas.ac.cn>");
+MODULE_DESCRIPTION("Zhihe A210 AP to E902 mailbox");
+MODULE_LICENSE("GPL");

-- 
2.55.0



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

* [PATCH RFC v3 06/17] dt-bindings: pinctrl: add Zhihe A210 pin controller
  2026-11-02 19:45 [PATCH RFC v3 00/17] riscv: add initial Zhihe A210 support using SCMI clocks and resets Han Gao via B4 Relay
                   ` (4 preceding siblings ...)
  2026-11-02 19:45 ` [PATCH RFC v3 05/17] mailbox: add Zhihe A210 AP to E902 mailbox driver Han Gao via B4 Relay
@ 2026-11-02 19:45 ` Han Gao via B4 Relay
  2026-11-02 19:45 ` [PATCH RFC v3 07/17] pinctrl: zhihe: add A210 support Han Gao via B4 Relay
                   ` (10 subsequent siblings)
  16 siblings, 0 replies; 19+ messages in thread
From: Han Gao via B4 Relay @ 2026-11-02 19:45 UTC (permalink / raw)
  To: Sudeep Holla, Cristian Marussi, Michal Simek, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Paul Walmsley, Palmer Dabbelt,
	Albert Ou, Alexandre Ghiti, Zhiguo Zhu, Jassi Brar, Linus Walleij,
	Uwe Kleine-König, Bartosz Golaszewski, Philipp Zabel,
	Thomas Gleixner, Radu Rendec, Samuel Holland, Daniel Lezcano,
	Anup Patel, Stephen Boyd, Brian Masney, Jerome Brunet,
	Greg Kroah-Hartman, Jiri Slaby, Drew Fustini, Icenowy Zheng,
	Inochi Amaoto, Vivian Wang, Yao Zi, Jiaxun Yang
  Cc: arm-scmi, linux-arm-kernel, linux-kernel, devicetree, linux-riscv,
	linux-gpio, Paul Walmsley, linux-clk, linux-serial, Han Gao,
	Han Gao

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

Add a binding for the AON, PERI1 and PERI2 pad controllers of the Zhihe
A210. Every pad is muxed and configured on its own. Functions of the same
kind share one name unless a pad can select more than one instance of
them, as with the UARTs.

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       | 146 +++++++++++++++++++++
 1 file changed, 146 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..96c46b59d147
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/zhihe,a210-pinctrl.yaml
@@ -0,0 +1,146 @@
+# 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.
+
+  Most pads of the A210 are split into three groups, each managed by its
+  own pad controller with a separate register range:
+
+    AON pad controller   -> zhihe,a210-aon-pinctrl
+    Peripheral 1 pads    -> zhihe,a210-peri1-pinctrl
+    Peripheral 2 pads    -> zhihe,a210-peri2-pinctrl
+
+  Each pad can be muxed individually to up to 8 different functions,
+  though for most pads only a few of those settings are valid. A few pads
+  in the AON group do not support muxing or configuration at all.
+
+  The pads support configurable drive strength, bias, input enable,
+  Schmitt trigger and slew rate.
+
+properties:
+  compatible:
+    enum:
+      - zhihe,a210-aon-pinctrl
+      - zhihe,a210-peri1-pinctrl
+      - zhihe,a210-peri2-pinctrl
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+
+  clock-names:
+    const: pclk
+
+  resets:
+    maxItems: 1
+
+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.
+
+          function:
+            $ref: /schemas/pinctrl/pinmux-node.yaml#/properties/function
+            enum: [ aouart, aouart_ir, aogpio, aoi2c, aospi, jtag, reset,
+                    por, pmic, dvs, uart0, uart1, uart2, uart3, uart4,
+                    uart5, uart6, uart7, uart8, uart9, uart_ir, gpio,
+                    gmac0, gmac1, spi, qspi, pwm, can, i2s0, i2s1, i2s2,
+                    i2s3, i2c0, i2c1, i2c2, i2c3, i2c4, i2c5, i2c6, i2c7,
+                    i2c7_smb, sdio, isp0, dptx, usb31, sata, hdmi, zmac,
+                    bsel, dbgm, cdbg, pdm, tdm, pcie, sen_vclk ]
+            description: |
+              The mux function to select for the given pins. Functions of
+              the same kind share one name, such as spi or pwm, unless a
+              pad can select more than one instance. For example GPIO0_16
+              selects UART0 or UART1, so the UARTs are named uart0 to
+              uart9.
+
+          bias-disable: true
+
+          bias-pull-up: true
+
+          bias-pull-down: true
+
+          drive-strength:
+            minimum: 1
+            maximum: 25
+            description:
+              Drive strength in mA. The pads support 1, 2, 3, 5, 7, 8, 10,
+              12, 13, 15, 16, 18, 20, 21, 23 and 25 mA. Other values select
+              the next higher strength.
+
+          input-enable: true
+
+          input-disable: true
+
+          input-schmitt-enable: true
+
+          input-schmitt-disable: true
+
+          slew-rate:
+            maximum: 1
+
+        required:
+          - pins
+
+        additionalProperties: 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 {
+                pins = "GPIO0_0", "GPIO0_12";
+                function = "gmac0";
+                bias-disable;
+                drive-strength = <13>;
+                input-disable;
+                input-schmitt-disable;
+                slew-rate = <0>;
+            };
+        };
+    };

-- 
2.55.0



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

* [PATCH RFC v3 07/17] pinctrl: zhihe: add A210 support
  2026-11-02 19:45 [PATCH RFC v3 00/17] riscv: add initial Zhihe A210 support using SCMI clocks and resets Han Gao via B4 Relay
                   ` (5 preceding siblings ...)
  2026-11-02 19:45 ` [PATCH RFC v3 06/17] dt-bindings: pinctrl: add Zhihe A210 pin controller Han Gao via B4 Relay
@ 2026-11-02 19:45 ` Han Gao via B4 Relay
  2026-11-02 19:45 ` [PATCH RFC v3 08/17] dt-bindings: interrupt-controller: add Zhihe A210 PLIC Han Gao via B4 Relay
                   ` (9 subsequent siblings)
  16 siblings, 0 replies; 19+ messages in thread
From: Han Gao via B4 Relay @ 2026-11-02 19:45 UTC (permalink / raw)
  To: Sudeep Holla, Cristian Marussi, Michal Simek, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Paul Walmsley, Palmer Dabbelt,
	Albert Ou, Alexandre Ghiti, Zhiguo Zhu, Jassi Brar, Linus Walleij,
	Uwe Kleine-König, Bartosz Golaszewski, Philipp Zabel,
	Thomas Gleixner, Radu Rendec, Samuel Holland, Daniel Lezcano,
	Anup Patel, Stephen Boyd, Brian Masney, Jerome Brunet,
	Greg Kroah-Hartman, Jiri Slaby, Drew Fustini, Icenowy Zheng,
	Inochi Amaoto, Vivian Wang, Yao Zi, Jiaxun Yang
  Cc: arm-scmi, linux-arm-kernel, linux-kernel, devicetree, linux-riscv,
	linux-gpio, Paul Walmsley, linux-clk, linux-serial, Han Gao,
	Han Gao

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

Add pin mux and pin configuration support for the AON, PERI1 and PERI2
pad controllers of the Zhihe A210. Each pad forms its own group. Drive
strength requests are rounded up to the next supported value.

Across system suspend, restore only the register fields Linux has
programmed and leave the ones set up by firmware alone. Release the
optional pad controller reset at probe.

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              |  13 +
 drivers/pinctrl/Makefile             |   1 +
 drivers/pinctrl/pinctrl-zhihe-a210.c | 996 +++++++++++++++++++++++++++++++++++
 3 files changed, 1010 insertions(+)

diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index dc7138302c55..b59da0c11e2e 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -665,6 +665,19 @@ config PINCTRL_UPBOARD
 	  To compile this driver as a module, choose M here: the module
 	  will be called pinctrl-upboard.
 
+config PINCTRL_ZHIHE_A210
+	tristate "Pinctrl driver for the Zhihe A210 SoC"
+	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 AON, PERI1 and PERI2 pad controllers. Say Y if you
+	  are building a kernel for the Zhihe A210 platform.
+
 config PINCTRL_ZYNQ
 	bool "Pinctrl driver for Xilinx Zynq"
 	depends on ARCH_ZYNQ || COMPILE_TEST
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index ce0825f4fc1b..f90b29c7ab06 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -65,6 +65,7 @@ obj-$(CONFIG_PINCTRL_TB10X)	+= pinctrl-tb10x.o
 obj-$(CONFIG_PINCTRL_TPS6594)	+= pinctrl-tps6594.o
 obj-$(CONFIG_PINCTRL_TH1520)	+= pinctrl-th1520.o
 obj-$(CONFIG_PINCTRL_UPBOARD)	+= pinctrl-upboard.o
+obj-$(CONFIG_PINCTRL_ZHIHE_A210)	+= pinctrl-zhihe-a210.o
 obj-$(CONFIG_PINCTRL_ZYNQMP)	+= pinctrl-zynqmp.o
 obj-$(CONFIG_PINCTRL_ZYNQ)	+= pinctrl-zynq.o
 
diff --git a/drivers/pinctrl/pinctrl-zhihe-a210.c b/drivers/pinctrl/pinctrl-zhihe-a210.c
new file mode 100644
index 000000000000..8f771179cb4c
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-zhihe-a210.c
@@ -0,0 +1,996 @@
+// 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/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/property.h>
+#include <linux/reset.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"
+
+/*
+ * The pad configuration registers start at offset 0. Each 32-bit register
+ * holds the 16-bit fields of two consecutive pads, the lower pad number in
+ * the low half. The mux registers start at A210_MUX_BASE and hold the
+ * 4-bit fields of eight consecutive pads in the same way. So pad n is
+ * configured in register n / 2 at bit (n % 2) * 16 and muxed in register
+ * n / 8 at bit (n % 8) * 4.
+ */
+#define A210_CFG_WIDTH 16
+#define A210_CFG_PER_REG (32 / A210_CFG_WIDTH)
+#define A210_MUX_BASE 0x400
+#define A210_MUX_WIDTH 4
+#define A210_MUX_PER_REG (32 / A210_MUX_WIDTH)
+
+#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)
+#define A210_PADCFG_MASK GENMASK(9, 0)
+
+#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_MAX_PINS 49
+
+struct a210_register_state {
+	u32 mask;
+	u32 value;
+};
+
+struct a210_pad_group {
+	const char *name;
+	const struct pinctrl_pin_desc *pins;
+	unsigned int npins;
+	bool aon;
+};
+
+struct a210_pinctrl {
+	struct pinctrl_desc desc;
+	raw_spinlock_t lock; /* serialize register access */
+	void __iomem *base;
+	struct clk *clk;
+	bool clk_enabled;
+	bool aon;
+	struct pinctrl_dev *pctl;
+	struct a210_register_state cfg_state[DIV_ROUND_UP(A210_MAX_PINS, A210_CFG_PER_REG)];
+	struct a210_register_state mux_state[DIV_ROUND_UP(A210_MAX_PINS, A210_MUX_PER_REG)];
+};
+
+static void __iomem *a210_padcfg(struct a210_pinctrl *pp, unsigned int pin)
+{
+	return pp->base + pin / A210_CFG_PER_REG * sizeof(u32);
+}
+
+static unsigned int a210_padcfg_shift(unsigned int pin)
+{
+	return pin % A210_CFG_PER_REG * A210_CFG_WIDTH;
+}
+
+static void __iomem *a210_muxcfg(struct a210_pinctrl *pp, unsigned int pin)
+{
+	return pp->base + A210_MUX_BASE + pin / A210_MUX_PER_REG * sizeof(u32);
+}
+
+static unsigned int a210_muxcfg_shift(unsigned int pin)
+{
+	return pin % A210_MUX_PER_REG * A210_MUX_WIDTH;
+}
+
+enum a210_muxtype {
+	/*
+	 * A mux setting with no function behind it. The pad tables below
+	 * spell it ____ so that their eight mux columns line up.
+	 */
+	A210_MUX_____,
+	A210_MUX_AOUART,
+	A210_MUX_AOUART_IR,
+	A210_MUX_AOGPIO,
+	A210_MUX_AOI2C,
+	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_UART_IR,
+	A210_MUX_GPIO,
+	A210_MUX_GMAC0,
+	A210_MUX_GMAC1,
+	A210_MUX_SPI,
+	A210_MUX_QSPI,
+	A210_MUX_PWM,
+	A210_MUX_CAN,
+	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,
+	A210_MUX_HDMI,
+	A210_MUX_ZMAC,
+	A210_MUX_BSEL,
+	A210_MUX_DBGM,
+	A210_MUX_CDBG,
+	A210_MUX_PDM,
+	A210_MUX_TDM,
+	A210_MUX_PCIE,
+	A210_MUX_SEN_VCLK,
+};
+
+static const char *const a210_muxtype_string[] = {
+	[A210_MUX_AOUART] = "aouart",
+	[A210_MUX_AOUART_IR] = "aouart_ir",
+	[A210_MUX_AOGPIO] = "aogpio",
+	[A210_MUX_AOI2C] = "aoi2c",
+	[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_UART_IR] = "uart_ir",
+	[A210_MUX_GPIO] = "gpio",
+	[A210_MUX_GMAC0] = "gmac0",
+	[A210_MUX_GMAC1] = "gmac1",
+	[A210_MUX_SPI] = "spi",
+	[A210_MUX_QSPI] = "qspi",
+	[A210_MUX_PWM] = "pwm",
+	[A210_MUX_CAN] = "can",
+	[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] = "sata",
+	[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] = "pcie",
+	[A210_MUX_SEN_VCLK] = "sen_vclk",
+};
+
+/* The functions selected by mux settings 0 to 7 of a pad. */
+struct a210_pad {
+	u8 mux[8];
+	bool fixed;
+};
+
+#define A210_PAD(_nr, _name, m0, m1, m2, m3, m4, m5, m6, m7)			\
+	{									\
+		.number = _nr,							\
+		.name = #_name,							\
+		.drv_data = (void *)&(const struct a210_pad) {			\
+			.mux = { A210_MUX_##m0, A210_MUX_##m1, A210_MUX_##m2,	\
+				 A210_MUX_##m3, A210_MUX_##m4, A210_MUX_##m5,	\
+				 A210_MUX_##m6, A210_MUX_##m7 },		\
+		},								\
+	}
+
+/* A dedicated pad without mux or configuration register fields. */
+#define A210_FIXED_PAD(_nr, _name)						\
+	{									\
+		.number = _nr,							\
+		.name = #_name,							\
+		.drv_data = (void *)&(const struct a210_pad) { .fixed = true },	\
+	}
+
+static const struct pinctrl_pin_desc a210_group0_pins[] = {
+	A210_FIXED_PAD(0, OSC_CLK_IN),
+	A210_FIXED_PAD(1, OSC_CLK_OUT),
+	A210_FIXED_PAD(2, RST_N_IN),
+	A210_FIXED_PAD(3, RTC_CLK_IN),
+	A210_FIXED_PAD(4, RTC_CLK_OUT),
+	A210_FIXED_PAD(5, TEST_MODE),
+	A210_FIXED_PAD(6, POR_SEL),
+	A210_PAD(7, RST_N_OUT, RST, ____, ____, AOGPIO, ____, ____, ____, ____),
+	A210_PAD(8, BOOT_SEL0, BSEL, ____, ____, AOGPIO, ____, ____, ____, ____),
+	A210_PAD(9, BOOT_SEL1, BSEL, AOUART, ____, AOGPIO, ____, ____, ____, ____),
+	A210_PAD(10, DEBUG_MODE, DBGM, ____, ____, AOGPIO, ____, ____, ____, ____),
+	A210_PAD(11, AOUART_TXD, AOUART, AOUART_IR, ____, AOGPIO, ____, ____, ____, ____),
+	A210_PAD(12, AOUART_RXD, AOUART, AOUART_IR, ____, AOGPIO, ____, ____, ____, ____),
+	A210_PAD(13, AOI2C0_SCL, AOI2C, AOSPI, ____, AOGPIO, ____, ____, ____, ____),
+	A210_PAD(14, AOI2C0_SDA, AOI2C, AOSPI, ____, AOGPIO, ____, ____, ____, ____),
+	A210_PAD(15, AOI2C1_SCL, AOI2C, AOSPI, ____, AOGPIO, ____, ____, ____, ____),
+	A210_PAD(16, AOI2C1_SDA, AOI2C, AOSPI, ____, AOGPIO, ____, ____, ____, ____),
+	A210_PAD(17, CPU_JTG_TCLK, JTAG, ____, ____, AOGPIO, ____, ____, ____, ____),
+	A210_PAD(18, CPU_JTG_TMS, JTAG, ____, ____, AOGPIO, ____, ____, ____, ____),
+	A210_PAD(19, CPU_JTG_TDI, JTAG, ____, ____, AOGPIO, ____, ____, ____, ____),
+	A210_PAD(20, CPU_JTG_TDO, JTAG, POR, ____, AOGPIO, ____, ____, ____, ____),
+	A210_PAD(21, CPU_JTG_TRST, JTAG, ____, ____, AOGPIO, ____, ____, ____, ____),
+	A210_PAD(22, AOGPIO0_21, AOGPIO, AOSPI, PMIC, ____, ____, ____, ____, ____),
+	A210_PAD(23, AOGPIO0_22, AOGPIO, AOSPI, PMIC, ____, ____, ____, ____, ____),
+	A210_PAD(24, AOGPIO0_23, BSEL, AOSPI, PMIC, AOGPIO, ____, ____, ____, ____),
+	A210_PAD(25, AOGPIO0_24, AOGPIO, AOSPI, PMIC, ____, ____, ____, ____, ____),
+	A210_PAD(26, AOGPIO0_25, AOGPIO, AOSPI, PMIC, ____, ____, ____, ____, ____),
+	A210_PAD(27, AOGPIO0_26, AOGPIO, AOI2C, PMIC, ____, ____, ____, ____, ____),
+	A210_PAD(28, AOGPIO0_27, AOGPIO, AOI2C, PMIC, ____, ____, ____, ____, ____),
+	A210_PAD(29, AOGPIO0_28, AOGPIO, AOI2C, PMIC, ____, ____, ____, ____, ____),
+	A210_PAD(30, AOGPIO0_29, AOGPIO, AOI2C, PMIC, ____, ____, ____, ____, ____),
+	A210_PAD(31, AOGPIO0_30, AOGPIO, AOI2C, PMIC, DVS, ____, ____, ____, ____),
+	A210_PAD(32, AOGPIO0_31, AOGPIO, AOUART, PMIC, DVS, ____, ____, ____, ____),
+	A210_PAD(33, AOGPIO1_0, AOGPIO, AOUART, PMIC, ____, ____, ____, ____, ____),
+	A210_PAD(34, AOGPIO1_1, AOGPIO, ____, PMIC, ____, ____, ____, ____, ____),
+	A210_PAD(35, AOGPIO1_2, AOGPIO, ____, PMIC, DVS, ____, ____, ____, ____),
+	A210_PAD(36, AOGPIO1_3, AOGPIO, ____, PMIC, DVS, ____, ____, ____, ____),
+	A210_PAD(37, AOGPIO1_4, AOGPIO, ____, PMIC, DVS, ____, ____, ____, ____),
+	A210_PAD(38, AOGPIO1_5, AOGPIO, ____, PMIC, DVS, ____, ____, ____, ____),
+	A210_PAD(39, AOGPIO1_6, AOGPIO, ____, PMIC, DVS, ____, ____, ____, ____),
+	A210_PAD(40, AOGPIO1_7, AOGPIO, ____, PMIC, DVS, ____, ____, ____, ____),
+	A210_PAD(41, AOGPIO1_8, PCIE, ____, PMIC, AOGPIO, ____, ____, ____, ____),
+	A210_PAD(42, AOGPIO1_9, AOGPIO, ____, PMIC, ____, ____, ____, ____, ____),
+};
+
+static const struct pinctrl_pin_desc a210_group1_pins[] = {
+	A210_PAD(0, GPIO0_0, GPIO, GMAC0, ____, ____, ____, ____, ZMAC, ____),
+	A210_PAD(1, GPIO0_1, GPIO, GMAC0, ____, ____, ____, ____, ZMAC, ____),
+	A210_PAD(2, GPIO0_2, GPIO, GMAC0, ____, ____, ____, ____, ZMAC, ____),
+	A210_PAD(3, GPIO0_3, GPIO, GMAC0, UART3, UART_IR, ____, SATA, ZMAC, ____),
+	A210_PAD(4, GPIO0_4, GPIO, GMAC0, UART3, UART_IR, ____, SATA, ZMAC, ____),
+	A210_PAD(5, GPIO0_5, GPIO, GMAC0, UART3, ____, ____, SATA, ZMAC, ____),
+	A210_PAD(6, GPIO0_6, GPIO, GMAC0, UART3, ____, ____, SATA, ZMAC, ____),
+	A210_PAD(7, GPIO0_7, GPIO, GMAC0, ____, ____, ____, SATA, ZMAC, ____),
+	A210_PAD(8, GPIO0_8, GPIO, GMAC0, I2C0, ____, ____, SATA, ZMAC, ____),
+	A210_PAD(9, GPIO0_9, GPIO, GMAC0, I2C0, ____, ____, PCIE, ZMAC, ____),
+	A210_PAD(10, GPIO0_10, GPIO, GMAC0, I2C1, ____, ____, PCIE, ZMAC, ____),
+	A210_PAD(11, GPIO0_11, GPIO, GMAC0, I2C1, ____, ____, PCIE, ZMAC, ____),
+	A210_PAD(12, GPIO0_12, GPIO, GMAC0, ____, ____, ____, PCIE, ZMAC, ____),
+	A210_PAD(13, GPIO0_13, GPIO, GMAC0, ____, ____, ____, PWM, ZMAC, ____),
+	A210_PAD(14, GPIO0_14, GPIO, UART0, UART_IR, ____, SATA, I2S0, ____, ____),
+	A210_PAD(15, GPIO0_15, GPIO, UART0, UART_IR, QSPI, SATA, I2S0, ____, ____),
+	A210_PAD(16, GPIO0_16, GPIO, UART0, UART1, UART_IR, SATA, I2S0, ZMAC, ____),
+	A210_PAD(17, GPIO0_17, GPIO, UART0, UART1, UART_IR, SATA, I2S0, ZMAC, ____),
+	A210_PAD(18, GPIO0_18, GPIO, QSPI, GMAC0, SDIO, SATA, I2S0, ____, PCIE),
+	A210_PAD(19, GPIO0_19, GPIO, QSPI, GMAC1, ____, TDM, SATA, ____, PCIE),
+	A210_PAD(20, GPIO0_20, GPIO, QSPI, UART3, UART_IR, TDM, SATA, ZMAC, PCIE),
+	A210_PAD(21, GPIO0_21, GPIO, QSPI, UART3, UART_IR, TDM, SATA, ZMAC, PCIE),
+	A210_PAD(22, GPIO0_22, GPIO, QSPI, I2C2, ____, TDM, SATA, ZMAC, PWM),
+	A210_PAD(23, GPIO0_23, GPIO, QSPI, I2C2, ____, ____, SATA, ZMAC, PWM),
+	A210_PAD(24, GPIO0_24, GPIO, QSPI, I2C0, CAN, CDBG, PCIE, UART0, PWM),
+	A210_PAD(25, GPIO0_25, GPIO, QSPI, I2C0, CAN, CDBG, PCIE, UART0, PWM),
+	A210_PAD(26, GPIO0_26, GPIO, QSPI, I2C1, CAN, CDBG, PCIE, UART0, UART_IR),
+	A210_PAD(27, GPIO0_27, GPIO, QSPI, I2C1, CAN, CDBG, PCIE, UART0, UART_IR),
+	A210_PAD(28, GPIO0_28, GPIO, PWM, SPI, UART_IR, I2S0, PCIE, UART1, ____),
+	A210_PAD(29, GPIO0_29, GPIO, PWM, SPI, UART_IR, I2S0, PCIE, UART1, ____),
+	A210_PAD(30, GPIO0_30, GPIO, PWM, SPI, ____, I2S0, PCIE, UART1, ____),
+	A210_PAD(31, GPIO0_31, GPIO, PWM, SPI, QSPI, I2S0, PCIE, UART1, ____),
+	A210_PAD(32, GPIO1_0, GPIO, PWM, UART2, UART_IR, I2S0, SDIO, GMAC1, SATA),
+	A210_PAD(33, GPIO1_1, GPIO, PWM, UART2, UART_IR, I2C2, SATA, SPI, SDIO),
+	A210_PAD(34, GPIO1_2, GPIO, GMAC1, TDM, PWM, I2C2, SATA, ____, ____),
+	A210_PAD(35, GPIO1_3, GPIO, GMAC1, TDM, PWM, ____, SATA, ____, ____),
+	A210_PAD(36, GPIO1_4, GPIO, GMAC1, TDM, UART2, ____, SATA, ____, ____),
+	A210_PAD(37, GPIO1_5, GPIO, GMAC1, ____, UART2, ____, SATA, ____, ____),
+	A210_PAD(38, GPIO1_6, GPIO, GMAC1, SPI, PWM, CDBG, SATA, ____, ____),
+	A210_PAD(39, GPIO1_7, GPIO, GMAC1, SPI, PWM, CDBG, SATA, ____, ____),
+	A210_PAD(40, GPIO1_8, GPIO, GMAC1, SPI, PDM, CDBG, SATA, ____, ____),
+	A210_PAD(41, GPIO1_9, GPIO, GMAC1, SPI, PWM, ____, SATA, GMAC0, ____),
+	A210_PAD(42, GPIO1_10, GPIO, GMAC1, SPI, PWM, ____, SATA, ____, ____),
+	A210_PAD(43, GPIO1_11, GPIO, GMAC1, QSPI, PDM, I2S0, ISP0, PWM, ____),
+	A210_PAD(44, GPIO1_12, GPIO, GMAC1, QSPI, PDM, I2S0, ISP0, ____, ____),
+	A210_PAD(45, GPIO1_13, GPIO, GMAC1, QSPI, PDM, I2S0, ISP0, ____, ____),
+	A210_PAD(46, GPIO1_14, GPIO, GMAC1, ____, PDM, I2S0, ISP0, ____, ____),
+	A210_PAD(47, GPIO1_15, GPIO, GMAC1, SDIO, PDM, I2S0, ISP0, ____, ____),
+	A210_PAD(48, GPIO1_16, GPIO, GMAC0, ____, ____, ____, SDIO, ____, ____),
+};
+
+static const struct pinctrl_pin_desc a210_group2_pins[] = {
+	A210_PAD(0, GPIO2_0, GPIO, UART4, UART_IR, PWM, ____, I2C3, ____, ____),
+	A210_PAD(1, GPIO2_1, GPIO, UART4, UART_IR, PWM, ____, I2C3, ____, ____),
+	A210_PAD(2, GPIO2_2, GPIO, UART5, UART_IR, PWM, ____, I2C5, I2S1, ____),
+	A210_PAD(3, GPIO2_3, GPIO, UART5, UART_IR, PWM, ____, I2C5, I2S1, ____),
+	A210_PAD(4, GPIO2_4, GPIO, UART6, UART_IR, PWM, ____, I2C6, I2S1, ____),
+	A210_PAD(5, GPIO2_5, GPIO, UART6, UART_IR, PWM, ____, I2C6, I2S1, ____),
+	A210_PAD(6, GPIO2_6, GPIO, UART7, UART_IR, PWM, SEN_VCLK, I2C4, I2S1, ____),
+	A210_PAD(7, GPIO2_7, GPIO, UART7, UART_IR, PWM, SEN_VCLK, I2C4, ____, ____),
+	A210_PAD(8, GPIO2_8, GPIO, I2S2, ____, SPI, UART6, I2C6, PWM, ____),
+	A210_PAD(9, GPIO2_9, GPIO, I2S2, ____, SPI, UART6, I2C6, PWM, ____),
+	A210_PAD(10, GPIO2_10, GPIO, I2S2, PWM, SPI, UART9, I2C7, ____, ____),
+	A210_PAD(11, GPIO2_11, GPIO, I2S2, PWM, SPI, UART9, I2C7, ____, ____),
+	A210_PAD(12, GPIO2_12, GPIO, I2S2, PWM, SPI, UART8, I2C7, ____, ____),
+	A210_PAD(13, GPIO2_13, GPIO, I2S3, PWM, ____, ____, ____, ____, ____),
+	A210_PAD(14, GPIO2_14, GPIO, I2S3, PWM, ____, ____, ____, ____, ____),
+	A210_PAD(15, GPIO2_15, GPIO, I2S3, ____, ____, ____, ____, ____, ____),
+	A210_PAD(16, GPIO2_16, GPIO, I2S3, ____, ____, ____, ____, ____, ____),
+	A210_PAD(17, GPIO2_17, GPIO, I2S3, SPI, I2C4, UART8, I2C7, ____, ____),
+	A210_PAD(18, GPIO2_18, GPIO, I2S3, SPI, I2C4, PWM, UART5, UART_IR, ____),
+	A210_PAD(19, GPIO2_19, GPIO, I2S3, SPI, ____, PWM, UART5, UART_IR, ____),
+	A210_PAD(20, GPIO2_20, GPIO, I2S3, ____, ____, ____, ____, ____, ____),
+	A210_PAD(21, GPIO2_21, GPIO, I2S3, SPI, I2C3, PWM, UART8, ____, ____),
+	A210_PAD(22, GPIO2_22, GPIO, I2S3, SPI, I2C3, PWM, UART8, ____, ____),
+	A210_PAD(23, GPIO2_23, GPIO, I2S3, PWM, ____, ____, ____, ____, ____),
+	A210_PAD(24, GPIO2_24, GPIO, I2C3, UART5, ____, ____, ____, ____, ____),
+	A210_PAD(25, GPIO2_25, GPIO, I2C3, UART5, ____, HDMI, QSPI, PWM, ____),
+	A210_PAD(26, GPIO2_26, GPIO, I2C4, UART6, ____, ____, ____, ____, ____),
+	A210_PAD(27, GPIO2_27, GPIO, I2C4, UART6, ____, ____, ____, ____, ____),
+	A210_PAD(28, GPIO2_28, GPIO, I2C5, UART7, PWM, ____, QSPI, ____, ____),
+	A210_PAD(29, GPIO2_29, GPIO, I2C5, UART7, PWM, ____, QSPI, ____, ____),
+	A210_PAD(30, GPIO2_30, GPIO, I2C6, UART8, PWM, HDMI, QSPI, I2S3, ____),
+	A210_PAD(31, GPIO2_31, GPIO, I2C6, UART8, PWM, HDMI, QSPI, I2S3, ____),
+	A210_PAD(32, GPIO3_0, GPIO, I2C7, UART9, PWM, CAN, QSPI, I2S3, SEN_VCLK),
+	A210_PAD(33, GPIO3_1, GPIO, I2C7, UART9, PWM, CAN, QSPI, I2S3, SEN_VCLK),
+	A210_PAD(34, GPIO3_2, GPIO, QSPI, UART8, UART_IR, ____, ____, I2S3, PWM),
+	A210_PAD(35, GPIO3_3, GPIO, QSPI, UART8, UART_IR, ____, ____, I2S3, PWM),
+	A210_PAD(36, GPIO3_4, GPIO, QSPI, UART9, UART_IR, ____, ____, I2S3, PWM),
+	A210_PAD(37, GPIO3_5, GPIO, QSPI, UART9, UART_IR, ____, ____, I2S3, PWM),
+	A210_PAD(38, GPIO3_6, GPIO, QSPI, I2S1, I2C7_SMB, ____, DPTX, I2S3, PWM),
+	A210_PAD(39, GPIO3_7, GPIO, QSPI, I2S1, I2C7_SMB, UART7, I2C5, I2S3, PWM),
+	A210_PAD(40, GPIO3_8, GPIO, QSPI, I2S1, I2C7_SMB, UART7, I2C5, I2S3, PWM),
+	A210_PAD(41, GPIO3_9, GPIO, UART4, I2S1, I2C7_SMB, UART5, DPTX, ____, PWM),
+	A210_PAD(42, GPIO3_10, GPIO, UART4, I2S1, I2C7_SMB, UART5, USB31, ____, ____),
+};
+
+static const struct a210_pad_group a210_group0 = {
+	.name = "a210-aon",
+	.pins = a210_group0_pins,
+	.npins = ARRAY_SIZE(a210_group0_pins),
+	.aon = true,
+};
+
+static const struct a210_pad_group a210_group1 = {
+	.name = "a210-peri1",
+	.pins = a210_group1_pins,
+	.npins = ARRAY_SIZE(a210_group1_pins),
+};
+
+static const struct a210_pad_group a210_group2 = {
+	.name = "a210-peri2",
+	.pins = a210_group2_pins,
+	.npins = ARRAY_SIZE(a210_group2_pins),
+};
+
+static const struct a210_pad *a210_pad_get(struct pinctrl_dev *pctldev, unsigned int pin)
+{
+	return pin_desc_get(pctldev, pin)->drv_data;
+}
+
+static int a210_pinctrl_get_groups_count(struct pinctrl_dev *pctldev)
+{
+	struct a210_pinctrl *pp = pinctrl_dev_get_drvdata(pctldev);
+
+	return 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->desc.pins[gsel].name;
+}
+
+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);
+
+	*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);
+	u32 pad;
+	u32 mux;
+
+	if (a210_pad_get(pctldev, pin)->fixed)
+		return;
+
+	scoped_guard(raw_spinlock_irqsave, &pp->lock) {
+		pad = readl_relaxed(a210_padcfg(pp, pin));
+		mux = readl_relaxed(a210_muxcfg(pp, pin));
+	}
+
+	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,
+};
+
+/* Use the weakest setting that provides at least the requested current. */
+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(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);
+		/*
+		 * Track the fields Linux has written. Suspend saves and resume
+		 * restores only those, leaving fields set up by firmware alone.
+		 */
+		pp->cfg_state[pin / A210_CFG_PER_REG].mask |= mask;
+	}
+	return 0;
+}
+
+static int a210_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin, unsigned long *config)
+{
+	struct a210_pinctrl *pp = pinctrl_dev_get_drvdata(pctldev);
+	bool enabled;
+	int param;
+	u32 value;
+	u32 arg;
+
+	if (a210_pad_get(pctldev, pin)->fixed)
+		return -ENOTSUPP;
+
+	value = readl_relaxed(a210_padcfg(pp, pin));
+	value = (value >> a210_padcfg_shift(pin)) & A210_PADCFG_MASK;
+
+	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_set(struct pinctrl_dev *pctldev, unsigned int pin, unsigned long *configs,
+			    unsigned int num_configs)
+{
+	struct a210_pinctrl *pp = pinctrl_dev_get_drvdata(pctldev);
+	unsigned int i;
+	u16 mask, value;
+
+	if (a210_pad_get(pctldev, pin)->fixed)
+		return -ENOTSUPP;
+
+	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_get(struct pinctrl_dev *pctldev, unsigned int gsel,
+				  unsigned long *config)
+{
+	struct a210_pinctrl *pp = pinctrl_dev_get_drvdata(pctldev);
+
+	return a210_pinconf_get(pctldev, pp->desc.pins[gsel].number, config);
+}
+
+static int a210_pinconf_group_set(struct pinctrl_dev *pctldev, unsigned int gsel,
+				  unsigned long *configs, unsigned int num_configs)
+{
+	struct a210_pinctrl *pp = pinctrl_dev_get_drvdata(pctldev);
+
+	return a210_pinconf_set(pctldev, pp->desc.pins[gsel].number, configs, num_configs);
+}
+
+#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 (a210_pad_get(pctldev, pin)->fixed)
+		return;
+
+	value = readl_relaxed(a210_padcfg(pp, pin));
+	value = (value >> a210_padcfg_shift(pin)) & A210_PADCFG_MASK;
+
+	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,
+			   enum a210_muxtype muxtype)
+{
+	const struct a210_pad *pad = a210_pad_get(pp->pctl, pin);
+	void __iomem *muxcfg = a210_muxcfg(pp, pin);
+	unsigned int shift = a210_muxcfg_shift(pin);
+	u32 mask, value, tmp;
+
+	for (value = 0; value < ARRAY_SIZE(pad->mux); value++)
+		if (pad->mux[value] == muxtype)
+			break;
+	if (pad->fixed || value == ARRAY_SIZE(pad->mux)) {
+		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 = GENMASK(A210_MUX_WIDTH - 1, 0) << shift;
+	value <<= shift;
+
+	scoped_guard(raw_spinlock_irqsave, &pp->lock) {
+		tmp = readl_relaxed(muxcfg);
+		tmp = (tmp & ~mask) | value;
+		writel_relaxed(tmp, muxcfg);
+		/* See a210_padcfg_rmw(). */
+		pp->mux_state[pin / A210_MUX_PER_REG].mask |= mask;
+	}
+
+	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,
+			       *(enum a210_muxtype *)func->data);
+}
+
+static bool a210_mux_is_gpio(enum a210_muxtype muxtype)
+{
+	return muxtype == A210_MUX_AOGPIO || muxtype == A210_MUX_GPIO;
+}
+
+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 a210_pad *pad = a210_pad_get(pctldev, offset);
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(pad->mux); i++)
+		if (a210_mux_is_gpio(pad->mux[i]))
+			return a210_pinmux_set(pp, offset, pad->mux[i]);
+
+	dev_err(pp->pctl->dev, "no GPIO mux for pin %s\n", pin_get_name(pctldev, offset));
+
+	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);
+
+	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)
+{
+	const struct a210_pad *pad = pin->drv_data;
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(pad->mux); i++)
+		if (pad->mux[i] == type)
+			return true;
+	return false;
+}
+
+static int a210_register_functions(struct a210_pinctrl *pp)
+{
+	struct device *dev = pp->pctl->dev;
+	unsigned int npins = pp->desc.npins;
+	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 < npins; 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 < npins; i++)
+			if (a210_pin_has_function(&pp->desc.pins[i], type))
+				groups[count++] = pp->desc.pins[i].name;
+		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;
+	struct reset_control *rst;
+	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->aon = group->aon;
+	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;
+
+	rst = devm_reset_control_get_optional_exclusive_deasserted(dev, NULL);
+	if (IS_ERR(rst))
+		return dev_err_probe(dev, PTR_ERR(rst), "could not release padctrl reset\n");
+
+	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);
+}
+
+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);
+		a210_pinctrl_save_regs(pp->mux_state, ARRAY_SIZE(pp->mux_state),
+				       pp->base + A210_MUX_BASE);
+	}
+	if (!pp->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) {
+		dev_err(dev, "could not enable padctrl clock: %d\n", ret);
+		return ret;
+	}
+
+	scoped_guard(raw_spinlock_irqsave, &pp->lock) {
+		a210_pinctrl_restore_regs(pp->cfg_state, ARRAY_SIZE(pp->cfg_state), pp->base);
+		a210_pinctrl_restore_regs(pp->mux_state, ARRAY_SIZE(pp->mux_state),
+					  pp->base + A210_MUX_BASE);
+	}
+	return 0;
+}
+
+static const struct dev_pm_ops a210_pinctrl_dev_pm_ops = {
+	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 },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, a210_pinctrl_of_match);
+
+static struct platform_driver a210_pinctrl_driver = {
+	.probe = a210_pinctrl_probe,
+	.driver = {
+		.name = "pinctrl-zhihe-a210",
+		.of_match_table = a210_pinctrl_of_match,
+		.pm = pm_sleep_ptr(&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 related	[flat|nested] 19+ messages in thread

* [PATCH RFC v3 08/17] dt-bindings: interrupt-controller: add Zhihe A210 PLIC
  2026-11-02 19:45 [PATCH RFC v3 00/17] riscv: add initial Zhihe A210 support using SCMI clocks and resets Han Gao via B4 Relay
                   ` (6 preceding siblings ...)
  2026-11-02 19:45 ` [PATCH RFC v3 07/17] pinctrl: zhihe: add A210 support Han Gao via B4 Relay
@ 2026-11-02 19:45 ` Han Gao via B4 Relay
  2026-11-02 19:45 ` [PATCH RFC v3 09/17] dt-bindings: riscv: add Melon Pi V1 and V2 Han Gao via B4 Relay
                   ` (8 subsequent siblings)
  16 siblings, 0 replies; 19+ messages in thread
From: Han Gao via B4 Relay @ 2026-11-02 19:45 UTC (permalink / raw)
  To: Sudeep Holla, Cristian Marussi, Michal Simek, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Paul Walmsley, Palmer Dabbelt,
	Albert Ou, Alexandre Ghiti, Zhiguo Zhu, Jassi Brar, Linus Walleij,
	Uwe Kleine-König, Bartosz Golaszewski, Philipp Zabel,
	Thomas Gleixner, Radu Rendec, Samuel Holland, Daniel Lezcano,
	Anup Patel, Stephen Boyd, Brian Masney, Jerome Brunet,
	Greg Kroah-Hartman, Jiri Slaby, Drew Fustini, Icenowy Zheng,
	Inochi Amaoto, Vivian Wang, Yao Zi, Jiaxun Yang
  Cc: arm-scmi, linux-arm-kernel, linux-kernel, devicetree, linux-riscv,
	linux-gpio, Paul Walmsley, linux-clk, linux-serial, Han Gao,
	Han Gao, Conor Dooley

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>
Acked-by: Conor Dooley <conor.dooley@microchip.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 related	[flat|nested] 19+ messages in thread

* [PATCH RFC v3 09/17] dt-bindings: riscv: add Melon Pi V1 and V2
  2026-11-02 19:45 [PATCH RFC v3 00/17] riscv: add initial Zhihe A210 support using SCMI clocks and resets Han Gao via B4 Relay
                   ` (7 preceding siblings ...)
  2026-11-02 19:45 ` [PATCH RFC v3 08/17] dt-bindings: interrupt-controller: add Zhihe A210 PLIC Han Gao via B4 Relay
@ 2026-11-02 19:45 ` Han Gao via B4 Relay
  2026-11-02 19:45 ` [PATCH RFC v3 10/17] dt-bindings: timer: add Zhihe A210 CLINT Han Gao via B4 Relay
                   ` (7 subsequent siblings)
  16 siblings, 0 replies; 19+ messages in thread
From: Han Gao via B4 Relay @ 2026-11-02 19:45 UTC (permalink / raw)
  To: Sudeep Holla, Cristian Marussi, Michal Simek, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Paul Walmsley, Palmer Dabbelt,
	Albert Ou, Alexandre Ghiti, Zhiguo Zhu, Jassi Brar, Linus Walleij,
	Uwe Kleine-König, Bartosz Golaszewski, Philipp Zabel,
	Thomas Gleixner, Radu Rendec, Samuel Holland, Daniel Lezcano,
	Anup Patel, Stephen Boyd, Brian Masney, Jerome Brunet,
	Greg Kroah-Hartman, Jiri Slaby, Drew Fustini, Icenowy Zheng,
	Inochi Amaoto, Vivian Wang, Yao Zi, Jiaxun Yang
  Cc: arm-scmi, linux-arm-kernel, linux-kernel, devicetree, linux-riscv,
	linux-gpio, Paul Walmsley, linux-clk, linux-serial, Han Gao,
	Han Gao, Conor Dooley

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>
Acked-by: Conor Dooley <conor.dooley@microchip.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..aa778275ab5d
--- /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 related	[flat|nested] 19+ messages in thread

* [PATCH RFC v3 10/17] dt-bindings: timer: add Zhihe A210 CLINT
  2026-11-02 19:45 [PATCH RFC v3 00/17] riscv: add initial Zhihe A210 support using SCMI clocks and resets Han Gao via B4 Relay
                   ` (8 preceding siblings ...)
  2026-11-02 19:45 ` [PATCH RFC v3 09/17] dt-bindings: riscv: add Melon Pi V1 and V2 Han Gao via B4 Relay
@ 2026-11-02 19:45 ` Han Gao via B4 Relay
  2026-11-02 19:45 ` [PATCH RFC v3 11/17] dt-bindings: serial: snps-dw-apb-uart: add Zhihe A210 UART Han Gao via B4 Relay
                   ` (6 subsequent siblings)
  16 siblings, 0 replies; 19+ messages in thread
From: Han Gao via B4 Relay @ 2026-11-02 19:45 UTC (permalink / raw)
  To: Sudeep Holla, Cristian Marussi, Michal Simek, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Paul Walmsley, Palmer Dabbelt,
	Albert Ou, Alexandre Ghiti, Zhiguo Zhu, Jassi Brar, Linus Walleij,
	Uwe Kleine-König, Bartosz Golaszewski, Philipp Zabel,
	Thomas Gleixner, Radu Rendec, Samuel Holland, Daniel Lezcano,
	Anup Patel, Stephen Boyd, Brian Masney, Jerome Brunet,
	Greg Kroah-Hartman, Jiri Slaby, Drew Fustini, Icenowy Zheng,
	Inochi Amaoto, Vivian Wang, Yao Zi, Jiaxun Yang
  Cc: arm-scmi, linux-arm-kernel, linux-kernel, devicetree, linux-riscv,
	linux-gpio, Paul Walmsley, linux-clk, linux-serial, Han Gao,
	Han Gao, Conor Dooley

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

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

Acked-by: Conor Dooley <conor.dooley@microchip.com>
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 d53f52e80d88..6480c8dacf6b 100644
--- a/Documentation/devicetree/bindings/timer/sifive,clint.yaml
+++ b/Documentation/devicetree/bindings/timer/sifive,clint.yaml
@@ -55,6 +55,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 related	[flat|nested] 19+ messages in thread

* [PATCH RFC v3 11/17] dt-bindings: serial: snps-dw-apb-uart: add Zhihe A210 UART
  2026-11-02 19:45 [PATCH RFC v3 00/17] riscv: add initial Zhihe A210 support using SCMI clocks and resets Han Gao via B4 Relay
                   ` (9 preceding siblings ...)
  2026-11-02 19:45 ` [PATCH RFC v3 10/17] dt-bindings: timer: add Zhihe A210 CLINT Han Gao via B4 Relay
@ 2026-11-02 19:45 ` Han Gao via B4 Relay
  2026-11-02 19:45 ` [PATCH RFC v3 12/17] riscv: dts: zhihe: add A210 core support Han Gao via B4 Relay
                   ` (5 subsequent siblings)
  16 siblings, 0 replies; 19+ messages in thread
From: Han Gao via B4 Relay @ 2026-11-02 19:45 UTC (permalink / raw)
  To: Sudeep Holla, Cristian Marussi, Michal Simek, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Paul Walmsley, Palmer Dabbelt,
	Albert Ou, Alexandre Ghiti, Zhiguo Zhu, Jassi Brar, Linus Walleij,
	Uwe Kleine-König, Bartosz Golaszewski, Philipp Zabel,
	Thomas Gleixner, Radu Rendec, Samuel Holland, Daniel Lezcano,
	Anup Patel, Stephen Boyd, Brian Masney, Jerome Brunet,
	Greg Kroah-Hartman, Jiri Slaby, Drew Fustini, Icenowy Zheng,
	Inochi Amaoto, Vivian Wang, Yao Zi, Jiaxun Yang
  Cc: arm-scmi, linux-arm-kernel, linux-kernel, devicetree, linux-riscv,
	linux-gpio, Paul Walmsley, linux-clk, linux-serial, Han Gao,
	Han Gao, Conor Dooley

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

The Zhihe A210 UARTs have separate APB and serial clock domain resets.
Add an SoC-specific compatible that, like the StarFive JH7110 one,
allows both resets.

Acked-by: Conor Dooley <conor.dooley@microchip.com>
Signed-off-by: Han Gao <gaohan@iscas.ac.cn>
---
 Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml b/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml
index e2ca126d58ba..a46a87e100bf 100644
--- a/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml
+++ b/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml
@@ -29,7 +29,9 @@ allOf:
       properties:
         compatible:
           contains:
-            const: starfive,jh7110-uart
+            enum:
+              - starfive,jh7110-uart
+              - zhihe,a210-uart
     then:
       properties:
         resets:
@@ -43,6 +45,7 @@ allOf:
               enum:
                 - starfive,jh7110-uart
                 - syna,sl2610-uart
+                - zhihe,a210-uart
     then:
       properties:
         resets:
@@ -92,6 +95,7 @@ properties:
               - syna,sl2610-uart
               - ti,tda54-uart
               - ultrarisc,dp1000-uart
+              - zhihe,a210-uart
           - const: snps,dw-apb-uart
       - const: snps,dw-apb-uart
 

-- 
2.55.0



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

* [PATCH RFC v3 12/17] riscv: dts: zhihe: add A210 core support
  2026-11-02 19:45 [PATCH RFC v3 00/17] riscv: add initial Zhihe A210 support using SCMI clocks and resets Han Gao via B4 Relay
                   ` (10 preceding siblings ...)
  2026-11-02 19:45 ` [PATCH RFC v3 11/17] dt-bindings: serial: snps-dw-apb-uart: add Zhihe A210 UART Han Gao via B4 Relay
@ 2026-11-02 19:45 ` Han Gao via B4 Relay
  2026-11-02 19:45 ` [PATCH RFC v3 13/17] riscv: dts: zhihe: add A210 UARTs Han Gao via B4 Relay
                   ` (4 subsequent siblings)
  16 siblings, 0 replies; 19+ messages in thread
From: Han Gao via B4 Relay @ 2026-11-02 19:45 UTC (permalink / raw)
  To: Sudeep Holla, Cristian Marussi, Michal Simek, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Paul Walmsley, Palmer Dabbelt,
	Albert Ou, Alexandre Ghiti, Zhiguo Zhu, Jassi Brar, Linus Walleij,
	Uwe Kleine-König, Bartosz Golaszewski, Philipp Zabel,
	Thomas Gleixner, Radu Rendec, Samuel Holland, Daniel Lezcano,
	Anup Patel, Stephen Boyd, Brian Masney, Jerome Brunet,
	Greg Kroah-Hartman, Jiri Slaby, Drew Fustini, Icenowy Zheng,
	Inochi Amaoto, Vivian Wang, Yao Zi, Jiaxun Yang
  Cc: arm-scmi, linux-arm-kernel, linux-kernel, devicetree, linux-riscv,
	linux-gpio, Paul Walmsley, linux-clk, linux-serial, Han Gao,
	Han Gao

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

Describe the CPU clusters, interrupt controllers and pad controllers.
Use SCMI clock and reset services through the E902 mailbox, with a
second mailbox channel for firmware notifications.

The SCMI clock and reset IDs are assigned by the E902 firmware, so they
live in headers next to the DTS rather than in dt-bindings.

Signed-off-by: Zhiguo Zhu <zhiguo.zhu@linux.alibaba.com>
Signed-off-by: Han Gao <gaohan@iscas.ac.cn>
---
 arch/riscv/boot/dts/zhihe/a210-clock.h |  15 ++
 arch/riscv/boot/dts/zhihe/a210-reset.h |  13 +
 arch/riscv/boot/dts/zhihe/a210.dtsi    | 433 +++++++++++++++++++++++++++++++++
 3 files changed, 461 insertions(+)

diff --git a/arch/riscv/boot/dts/zhihe/a210-clock.h b/arch/riscv/boot/dts/zhihe/a210-clock.h
new file mode 100644
index 000000000000..d57e99dfd3e3
--- /dev/null
+++ b/arch/riscv/boot/dts/zhihe/a210-clock.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+#ifndef __A210_CLOCK_H
+#define __A210_CLOCK_H
+
+/* SCMI clock IDs as numbered by the E902 firmware */
+#define A210_CLK_UART_SCLK(n) (n)
+#define A210_CLK_UART_PCLK(n) (10 + (n))
+#define A210_CLK_PERI1_PAD 20
+#define A210_CLK_PERI2_PAD 21
+#define A210_CLK_PERI3_PAD 22
+#define A210_CLK_AON_SYS 23
+#define A210_CLK_AON_I2C1_IC 24
+#define A210_CLK_AON_I2C1_PCLK 25
+
+#endif
diff --git a/arch/riscv/boot/dts/zhihe/a210-reset.h b/arch/riscv/boot/dts/zhihe/a210-reset.h
new file mode 100644
index 000000000000..3f8eaf0fc17b
--- /dev/null
+++ b/arch/riscv/boot/dts/zhihe/a210-reset.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+#ifndef __A210_RESET_H
+#define __A210_RESET_H
+
+/* SCMI reset IDs as numbered by the E902 firmware */
+#define A210_RESET_UART_SRST(n) (n)
+#define A210_RESET_UART_PRST(n) (10 + (n))
+#define A210_RESET_PERI1_PAD 20
+#define A210_RESET_PERI2_PAD 21
+#define A210_RESET_PERI3_PAD 22
+#define A210_RESET_AON_I2C1 23
+
+#endif
diff --git a/arch/riscv/boot/dts/zhihe/a210.dtsi b/arch/riscv/boot/dts/zhihe/a210.dtsi
new file mode 100644
index 000000000000..6d85d94f0af1
--- /dev/null
+++ b/arch/riscv/boot/dts/zhihe/a210.dtsi
@@ -0,0 +1,433 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+/*
+ * Copyright (C) 2021 Alibaba Group Holding Limited.
+ */
+
+#include <dt-bindings/interrupt-controller/irq.h>
+
+#include "a210-clock.h"
+#include "a210-reset.h"
+
+/ {
+	compatible = "zhihe,a210";
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	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>;
+			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>;
+			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;
+			};
+		};
+	};
+
+	firmware {
+		scmi {
+			compatible = "arm,scmi";
+			mboxes = <&mbox_e902 0>, <&mbox_e902 1>;
+			mbox-names = "tx", "rx";
+			shmem = <&scmi_shmem>, <&scmi_notification_shmem>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			scmi_clk: protocol@14 {
+				reg = <0x14>;
+				#clock-cells = <1>;
+			};
+
+			scmi_reset: protocol@16 {
+				reg = <0x16>;
+				#reset-cells = <1>;
+			};
+		};
+	};
+
+	soc {
+		compatible = "simple-bus";
+		ranges;
+		#address-cells = <2>;
+		dma-noncoherent;
+		#size-cells = <2>;
+
+		mbox_e902: mailbox@320000 {
+			compatible = "zhihe,a210-ap-mailbox";
+			reg = <0 0x00320000 0 0x2000>,
+			      <0 0x00311000 0 0x1000>;
+			reg-names = "local", "remote";
+			interrupt-parent = <&intc>;
+			interrupts = <336 IRQ_TYPE_LEVEL_HIGH>;
+			#mbox-cells = <1>;
+		};
+
+		peri1_padctrl: pinctrl@2026000 {
+			compatible = "zhihe,a210-peri1-pinctrl";
+			reg = <0x0 0x02026000 0x0 0x1000>;
+			clocks = <&scmi_clk A210_CLK_PERI1_PAD>;
+			clock-names = "pclk";
+			resets = <&scmi_reset A210_RESET_PERI1_PAD>;
+
+			status = "disabled";
+		};
+
+		peri2_padctrl: pinctrl@8411000 {
+			compatible = "zhihe,a210-peri2-pinctrl";
+			reg = <0x0 0x08411000 0x0 0x1000>;
+			clocks = <&scmi_clk A210_CLK_PERI2_PAD>;
+			clock-names = "pclk";
+			resets = <&scmi_reset A210_RESET_PERI2_PAD>;
+
+			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 11>, <&cpu0_intc 9>,
+					      <&cpu1_intc 11>, <&cpu1_intc 9>,
+					      <&cpu2_intc 11>, <&cpu2_intc 9>,
+					      <&cpu3_intc 11>, <&cpu3_intc 9>,
+					      <&cpu4_intc 11>, <&cpu4_intc 9>,
+					      <&cpu5_intc 11>, <&cpu5_intc 9>,
+					      <&cpu6_intc 11>, <&cpu6_intc 9>,
+					      <&cpu7_intc 11>, <&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>;
+		};
+
+		aon_padctrl: pinctrl@30848000 {
+			compatible = "zhihe,a210-aon-pinctrl";
+			reg = <0x0 0x30848000 0x0 0x2000>;
+			clocks = <&scmi_clk A210_CLK_AON_SYS>;
+			clock-names = "pclk";
+
+			status = "disabled";
+		};
+
+		sram@30907c00 {
+			compatible = "mmio-sram";
+			reg = <0 0x30907c00 0 0x200>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0 0 0x30907c00 0x200>;
+
+			scmi_shmem: scp-sram@0 {
+				compatible = "arm,scmi-shmem";
+				reg = <0 0x100>;
+			};
+
+			scmi_notification_shmem: scp-sram@100 {
+				compatible = "arm,scmi-shmem";
+				reg = <0x100 0x100>;
+			};
+		};
+	};
+};

-- 
2.55.0



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

* [PATCH RFC v3 13/17] riscv: dts: zhihe: add A210 UARTs
  2026-11-02 19:45 [PATCH RFC v3 00/17] riscv: add initial Zhihe A210 support using SCMI clocks and resets Han Gao via B4 Relay
                   ` (11 preceding siblings ...)
  2026-11-02 19:45 ` [PATCH RFC v3 12/17] riscv: dts: zhihe: add A210 core support Han Gao via B4 Relay
@ 2026-11-02 19:45 ` Han Gao via B4 Relay
  2026-11-02 19:45 ` [PATCH RFC v3 14/17] riscv: dts: zhihe: add A210 module memory Han Gao via B4 Relay
                   ` (3 subsequent siblings)
  16 siblings, 0 replies; 19+ messages in thread
From: Han Gao via B4 Relay @ 2026-11-02 19:45 UTC (permalink / raw)
  To: Sudeep Holla, Cristian Marussi, Michal Simek, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Paul Walmsley, Palmer Dabbelt,
	Albert Ou, Alexandre Ghiti, Zhiguo Zhu, Jassi Brar, Linus Walleij,
	Uwe Kleine-König, Bartosz Golaszewski, Philipp Zabel,
	Thomas Gleixner, Radu Rendec, Samuel Holland, Daniel Lezcano,
	Anup Patel, Stephen Boyd, Brian Masney, Jerome Brunet,
	Greg Kroah-Hartman, Jiri Slaby, Drew Fustini, Icenowy Zheng,
	Inochi Amaoto, Vivian Wang, Yao Zi, Jiaxun Yang
  Cc: arm-scmi, linux-arm-kernel, linux-kernel, devicetree, linux-riscv,
	linux-gpio, Paul Walmsley, linux-clk, linux-serial, Han Gao,
	Han Gao

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

Describe the ten DW APB UARTs with SCMI clocks and their separate APB
and serial resets.

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

diff --git a/arch/riscv/boot/dts/zhihe/a210.dtsi b/arch/riscv/boot/dts/zhihe/a210.dtsi
index 6d85d94f0af1..caa3005830ca 100644
--- a/arch/riscv/boot/dts/zhihe/a210.dtsi
+++ b/arch/riscv/boot/dts/zhihe/a210.dtsi
@@ -353,6 +353,70 @@ mbox_e902: mailbox@320000 {
 			#mbox-cells = <1>;
 		};
 
+		uart0: serial@2014000 {
+			compatible = "zhihe,a210-uart", "snps,dw-apb-uart";
+			reg = <0x0 0x02014000 0x0 0x1000>;
+			clocks = <&scmi_clk A210_CLK_UART_SCLK(0)>,
+				 <&scmi_clk A210_CLK_UART_PCLK(0)>;
+			clock-names = "baudclk", "apb_pclk";
+			interrupt-parent = <&intc>;
+			interrupts = <321 IRQ_TYPE_LEVEL_HIGH>;
+			reg-io-width = <4>;
+			reg-shift = <2>;
+			resets = <&scmi_reset A210_RESET_UART_PRST(0)>,
+				 <&scmi_reset A210_RESET_UART_SRST(0)>;
+
+			status = "disabled";
+		};
+
+		uart1: serial@2015000 {
+			compatible = "zhihe,a210-uart", "snps,dw-apb-uart";
+			reg = <0x0 0x02015000 0x0 0x1000>;
+			clocks = <&scmi_clk A210_CLK_UART_SCLK(1)>,
+				 <&scmi_clk A210_CLK_UART_PCLK(1)>;
+			clock-names = "baudclk", "apb_pclk";
+			interrupt-parent = <&intc>;
+			interrupts = <322 IRQ_TYPE_LEVEL_HIGH>;
+			reg-io-width = <4>;
+			reg-shift = <2>;
+			resets = <&scmi_reset A210_RESET_UART_PRST(1)>,
+				 <&scmi_reset A210_RESET_UART_SRST(1)>;
+
+			status = "disabled";
+		};
+
+		uart2: serial@2016000 {
+			compatible = "zhihe,a210-uart", "snps,dw-apb-uart";
+			reg = <0x0 0x02016000 0x0 0x1000>;
+			clocks = <&scmi_clk A210_CLK_UART_SCLK(2)>,
+				 <&scmi_clk A210_CLK_UART_PCLK(2)>;
+			clock-names = "baudclk", "apb_pclk";
+			interrupt-parent = <&intc>;
+			interrupts = <323 IRQ_TYPE_LEVEL_HIGH>;
+			reg-io-width = <4>;
+			reg-shift = <2>;
+			resets = <&scmi_reset A210_RESET_UART_PRST(2)>,
+				 <&scmi_reset A210_RESET_UART_SRST(2)>;
+
+			status = "disabled";
+		};
+
+		uart3: serial@2017000 {
+			compatible = "zhihe,a210-uart", "snps,dw-apb-uart";
+			reg = <0x0 0x02017000 0x0 0x1000>;
+			clocks = <&scmi_clk A210_CLK_UART_SCLK(3)>,
+				 <&scmi_clk A210_CLK_UART_PCLK(3)>;
+			clock-names = "baudclk", "apb_pclk";
+			interrupt-parent = <&intc>;
+			interrupts = <324 IRQ_TYPE_LEVEL_HIGH>;
+			reg-io-width = <4>;
+			reg-shift = <2>;
+			resets = <&scmi_reset A210_RESET_UART_PRST(3)>,
+				 <&scmi_reset A210_RESET_UART_SRST(3)>;
+
+			status = "disabled";
+		};
+
 		peri1_padctrl: pinctrl@2026000 {
 			compatible = "zhihe,a210-peri1-pinctrl";
 			reg = <0x0 0x02026000 0x0 0x1000>;
@@ -363,6 +427,102 @@ peri1_padctrl: pinctrl@2026000 {
 			status = "disabled";
 		};
 
+		uart4: serial@8401000 {
+			compatible = "zhihe,a210-uart", "snps,dw-apb-uart";
+			reg = <0x0 0x08401000 0x0 0x1000>;
+			clocks = <&scmi_clk A210_CLK_UART_SCLK(4)>,
+				 <&scmi_clk A210_CLK_UART_PCLK(4)>;
+			clock-names = "baudclk", "apb_pclk";
+			interrupt-parent = <&intc>;
+			interrupts = <325 IRQ_TYPE_LEVEL_HIGH>;
+			reg-io-width = <4>;
+			reg-shift = <2>;
+			resets = <&scmi_reset A210_RESET_UART_PRST(4)>,
+				 <&scmi_reset A210_RESET_UART_SRST(4)>;
+
+			status = "disabled";
+		};
+
+		uart5: serial@8402000 {
+			compatible = "zhihe,a210-uart", "snps,dw-apb-uart";
+			reg = <0x0 0x08402000 0x0 0x1000>;
+			clocks = <&scmi_clk A210_CLK_UART_SCLK(5)>,
+				 <&scmi_clk A210_CLK_UART_PCLK(5)>;
+			clock-names = "baudclk", "apb_pclk";
+			interrupt-parent = <&intc>;
+			interrupts = <326 IRQ_TYPE_LEVEL_HIGH>;
+			reg-io-width = <4>;
+			reg-shift = <2>;
+			resets = <&scmi_reset A210_RESET_UART_PRST(5)>,
+				 <&scmi_reset A210_RESET_UART_SRST(5)>;
+
+			status = "disabled";
+		};
+
+		uart6: serial@8403000 {
+			compatible = "zhihe,a210-uart", "snps,dw-apb-uart";
+			reg = <0x0 0x08403000 0x0 0x1000>;
+			clocks = <&scmi_clk A210_CLK_UART_SCLK(6)>,
+				 <&scmi_clk A210_CLK_UART_PCLK(6)>;
+			clock-names = "baudclk", "apb_pclk";
+			interrupt-parent = <&intc>;
+			interrupts = <327 IRQ_TYPE_LEVEL_HIGH>;
+			reg-io-width = <4>;
+			reg-shift = <2>;
+			resets = <&scmi_reset A210_RESET_UART_PRST(6)>,
+				 <&scmi_reset A210_RESET_UART_SRST(6)>;
+
+			status = "disabled";
+		};
+
+		uart7: serial@8404000 {
+			compatible = "zhihe,a210-uart", "snps,dw-apb-uart";
+			reg = <0x0 0x08404000 0x0 0x1000>;
+			clocks = <&scmi_clk A210_CLK_UART_SCLK(7)>,
+				 <&scmi_clk A210_CLK_UART_PCLK(7)>;
+			clock-names = "baudclk", "apb_pclk";
+			interrupt-parent = <&intc>;
+			interrupts = <328 IRQ_TYPE_LEVEL_HIGH>;
+			reg-io-width = <4>;
+			reg-shift = <2>;
+			resets = <&scmi_reset A210_RESET_UART_PRST(7)>,
+				 <&scmi_reset A210_RESET_UART_SRST(7)>;
+
+			status = "disabled";
+		};
+
+		uart8: serial@8405000 {
+			compatible = "zhihe,a210-uart", "snps,dw-apb-uart";
+			reg = <0x0 0x08405000 0x0 0x1000>;
+			clocks = <&scmi_clk A210_CLK_UART_SCLK(8)>,
+				 <&scmi_clk A210_CLK_UART_PCLK(8)>;
+			clock-names = "baudclk", "apb_pclk";
+			interrupt-parent = <&intc>;
+			interrupts = <329 IRQ_TYPE_LEVEL_HIGH>;
+			reg-io-width = <4>;
+			reg-shift = <2>;
+			resets = <&scmi_reset A210_RESET_UART_PRST(8)>,
+				 <&scmi_reset A210_RESET_UART_SRST(8)>;
+
+			status = "disabled";
+		};
+
+		uart9: serial@8406000 {
+			compatible = "zhihe,a210-uart", "snps,dw-apb-uart";
+			reg = <0x0 0x08406000 0x0 0x1000>;
+			clocks = <&scmi_clk A210_CLK_UART_SCLK(9)>,
+				 <&scmi_clk A210_CLK_UART_PCLK(9)>;
+			clock-names = "baudclk", "apb_pclk";
+			interrupt-parent = <&intc>;
+			interrupts = <330 IRQ_TYPE_LEVEL_HIGH>;
+			reg-io-width = <4>;
+			reg-shift = <2>;
+			resets = <&scmi_reset A210_RESET_UART_PRST(9)>,
+				 <&scmi_reset A210_RESET_UART_SRST(9)>;
+
+			status = "disabled";
+		};
+
 		peri2_padctrl: pinctrl@8411000 {
 			compatible = "zhihe,a210-peri2-pinctrl";
 			reg = <0x0 0x08411000 0x0 0x1000>;

-- 
2.55.0



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

* [PATCH RFC v3 14/17] riscv: dts: zhihe: add A210 module memory
  2026-11-02 19:45 [PATCH RFC v3 00/17] riscv: add initial Zhihe A210 support using SCMI clocks and resets Han Gao via B4 Relay
                   ` (12 preceding siblings ...)
  2026-11-02 19:45 ` [PATCH RFC v3 13/17] riscv: dts: zhihe: add A210 UARTs Han Gao via B4 Relay
@ 2026-11-02 19:45 ` Han Gao via B4 Relay
  2026-11-02 19:45 ` [PATCH RFC v3 15/17] riscv: dts: zhihe: add Melon Pi V1 and V2 Han Gao via B4 Relay
                   ` (2 subsequent siblings)
  16 siblings, 0 replies; 19+ messages in thread
From: Han Gao via B4 Relay @ 2026-11-02 19:45 UTC (permalink / raw)
  To: Sudeep Holla, Cristian Marussi, Michal Simek, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Paul Walmsley, Palmer Dabbelt,
	Albert Ou, Alexandre Ghiti, Zhiguo Zhu, Jassi Brar, Linus Walleij,
	Uwe Kleine-König, Bartosz Golaszewski, Philipp Zabel,
	Thomas Gleixner, Radu Rendec, Samuel Holland, Daniel Lezcano,
	Anup Patel, Stephen Boyd, Brian Masney, Jerome Brunet,
	Greg Kroah-Hartman, Jiri Slaby, Drew Fustini, Icenowy Zheng,
	Inochi Amaoto, Vivian Wang, Yao Zi, Jiaxun Yang
  Cc: arm-scmi, linux-arm-kernel, linux-kernel, devicetree, linux-riscv,
	linux-gpio, Paul Walmsley, linux-clk, linux-serial, Han Gao,
	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 related	[flat|nested] 19+ messages in thread

* [PATCH RFC v3 15/17] riscv: dts: zhihe: add Melon Pi V1 and V2
  2026-11-02 19:45 [PATCH RFC v3 00/17] riscv: add initial Zhihe A210 support using SCMI clocks and resets Han Gao via B4 Relay
                   ` (13 preceding siblings ...)
  2026-11-02 19:45 ` [PATCH RFC v3 14/17] riscv: dts: zhihe: add A210 module memory Han Gao via B4 Relay
@ 2026-11-02 19:45 ` Han Gao via B4 Relay
  2026-11-02 19:45 ` [PATCH RFC v3 16/17] riscv: defconfig: enable A210 support Han Gao via B4 Relay
  2026-11-02 19:45 ` [PATCH RFC v3 17/17] MAINTAINERS: add Zhihe A210 Han Gao via B4 Relay
  16 siblings, 0 replies; 19+ messages in thread
From: Han Gao via B4 Relay @ 2026-11-02 19:45 UTC (permalink / raw)
  To: Sudeep Holla, Cristian Marussi, Michal Simek, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Paul Walmsley, Palmer Dabbelt,
	Albert Ou, Alexandre Ghiti, Zhiguo Zhu, Jassi Brar, Linus Walleij,
	Uwe Kleine-König, Bartosz Golaszewski, Philipp Zabel,
	Thomas Gleixner, Radu Rendec, Samuel Holland, Daniel Lezcano,
	Anup Patel, Stephen Boyd, Brian Masney, Jerome Brunet,
	Greg Kroah-Hartman, Jiri Slaby, Drew Fustini, Icenowy Zheng,
	Inochi Amaoto, Vivian Wang, Yao Zi, Jiaxun Yang
  Cc: arm-scmi, linux-arm-kernel, linux-kernel, devicetree, linux-riscv,
	linux-gpio, Paul Walmsley, linux-clk, linux-serial, Han Gao,
	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..52015f6de5f8
--- /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 {
+			pins = "GPIO2_1";
+			function = "uart4";
+			bias-disable;
+			drive-strength = <1>;
+			input-enable;
+			input-schmitt-enable;
+			slew-rate = <0>;
+		};
+
+		tx-pins {
+			pins = "GPIO2_0";
+			function = "uart4";
+			bias-disable;
+			drive-strength = <3>;
+			input-disable;
+			input-schmitt-disable;
+			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 related	[flat|nested] 19+ messages in thread

* [PATCH RFC v3 16/17] riscv: defconfig: enable A210 support
  2026-11-02 19:45 [PATCH RFC v3 00/17] riscv: add initial Zhihe A210 support using SCMI clocks and resets Han Gao via B4 Relay
                   ` (14 preceding siblings ...)
  2026-11-02 19:45 ` [PATCH RFC v3 15/17] riscv: dts: zhihe: add Melon Pi V1 and V2 Han Gao via B4 Relay
@ 2026-11-02 19:45 ` Han Gao via B4 Relay
  2026-11-02 19:45 ` [PATCH RFC v3 17/17] MAINTAINERS: add Zhihe A210 Han Gao via B4 Relay
  16 siblings, 0 replies; 19+ messages in thread
From: Han Gao via B4 Relay @ 2026-11-02 19:45 UTC (permalink / raw)
  To: Sudeep Holla, Cristian Marussi, Michal Simek, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Paul Walmsley, Palmer Dabbelt,
	Albert Ou, Alexandre Ghiti, Zhiguo Zhu, Jassi Brar, Linus Walleij,
	Uwe Kleine-König, Bartosz Golaszewski, Philipp Zabel,
	Thomas Gleixner, Radu Rendec, Samuel Holland, Daniel Lezcano,
	Anup Patel, Stephen Boyd, Brian Masney, Jerome Brunet,
	Greg Kroah-Hartman, Jiri Slaby, Drew Fustini, Icenowy Zheng,
	Inochi Amaoto, Vivian Wang, Yao Zi, Jiaxun Yang
  Cc: arm-scmi, linux-arm-kernel, linux-kernel, devicetree, linux-riscv,
	linux-gpio, Paul Walmsley, linux-clk, linux-serial, Han Gao,
	Han Gao

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

Enable the A210 pinctrl and mailbox drivers, SCMI and the SCMI clock
driver. The SCMI mailbox transport and reset driver follow SCMI by
default.

The A210 has 10 UARTs. With the default of 4, UARTs beyond the 4th
don't get a fixed ttyS index and end up in whatever slot is free. Set
SERIAL_8250_NR_UARTS and SERIAL_8250_RUNTIME_UARTS to 10 to keep the
index stable.

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

diff --git a/arch/riscv/configs/defconfig b/arch/riscv/configs/defconfig
index 04ae305d5511..e9275be22e8c 100644
--- a/arch/riscv/configs/defconfig
+++ b/arch/riscv/configs/defconfig
@@ -34,6 +34,7 @@ CONFIG_ARCH_SUNXI=y
 CONFIG_ARCH_TENSTORRENT=y
 CONFIG_ARCH_THEAD=y
 CONFIG_ARCH_ULTRARISC=y
+CONFIG_ARCH_ZHIHE=y
 CONFIG_ARCH_VIRT=y
 CONFIG_ARCH_CANAAN=y
 CONFIG_SMP=y
@@ -111,6 +112,7 @@ CONFIG_PCIE_STARFIVE_HOST=m
 CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
 CONFIG_SIFIVE_CCACHE=y
+CONFIG_ARM_SCMI_PROTOCOL=y
 CONFIG_MTD=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_CFI=y
@@ -149,6 +151,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
@@ -168,6 +172,7 @@ CONFIG_SPI_SIFIVE=y
 CONFIG_SPI_SUN6I=y
 # CONFIG_PTP_1588_CLOCK is not set
 CONFIG_PINCTRL_TH1520=y
+CONFIG_PINCTRL_ZHIHE_A210=y
 CONFIG_PINCTRL_SOPHGO_CV1800B=y
 CONFIG_PINCTRL_SOPHGO_CV1812H=y
 CONFIG_PINCTRL_SOPHGO_SG2000=y
@@ -255,6 +260,7 @@ CONFIG_VIRTIO_PCI=y
 CONFIG_VIRTIO_BALLOON=y
 CONFIG_VIRTIO_INPUT=y
 CONFIG_VIRTIO_MMIO=y
+CONFIG_COMMON_CLK_SCMI=y
 CONFIG_CLK_SOPHGO_CV1800=y
 CONFIG_CLK_SOPHGO_SG2042_PLL=y
 CONFIG_CLK_SOPHGO_SG2042_CLKGEN=y
@@ -262,6 +268,7 @@ CONFIG_CLK_SOPHGO_SG2042_RPGATE=y
 CONFIG_SPACEMIT_K1_CCU=y
 CONFIG_SPACEMIT_K3_CCU=y
 CONFIG_SUN8I_DE2_CCU=m
+CONFIG_ZHIHE_A210_MBOX=y
 CONFIG_SUN50I_IOMMU=y
 CONFIG_RPMSG_CHAR=y
 CONFIG_RPMSG_CTRL=y

-- 
2.55.0



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

* [PATCH RFC v3 17/17] MAINTAINERS: add Zhihe A210
  2026-11-02 19:45 [PATCH RFC v3 00/17] riscv: add initial Zhihe A210 support using SCMI clocks and resets Han Gao via B4 Relay
                   ` (15 preceding siblings ...)
  2026-11-02 19:45 ` [PATCH RFC v3 16/17] riscv: defconfig: enable A210 support Han Gao via B4 Relay
@ 2026-11-02 19:45 ` Han Gao via B4 Relay
  16 siblings, 0 replies; 19+ messages in thread
From: Han Gao via B4 Relay @ 2026-11-02 19:45 UTC (permalink / raw)
  To: Sudeep Holla, Cristian Marussi, Michal Simek, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Paul Walmsley, Palmer Dabbelt,
	Albert Ou, Alexandre Ghiti, Zhiguo Zhu, Jassi Brar, Linus Walleij,
	Uwe Kleine-König, Bartosz Golaszewski, Philipp Zabel,
	Thomas Gleixner, Radu Rendec, Samuel Holland, Daniel Lezcano,
	Anup Patel, Stephen Boyd, Brian Masney, Jerome Brunet,
	Greg Kroah-Hartman, Jiri Slaby, Drew Fustini, Icenowy Zheng,
	Inochi Amaoto, Vivian Wang, Yao Zi, Jiaxun Yang
  Cc: arm-scmi, linux-arm-kernel, linux-kernel, devicetree, linux-riscv,
	linux-gpio, Paul Walmsley, linux-clk, linux-serial, Han Gao,
	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 | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 93abbb315065..64ed305d9bce 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -30860,6 +30860,18 @@ 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/mailbox/zhihe,a210-ap-mailbox.yaml
+F:	Documentation/devicetree/bindings/pinctrl/zhihe,a210-pinctrl.yaml
+F:	Documentation/devicetree/bindings/riscv/zhihe.yaml
+F:	arch/riscv/boot/dts/zhihe/
+F:	drivers/mailbox/mailbox-a210.c
+F:	drivers/pinctrl/pinctrl-zhihe-a210.c
+
 ZONED BLOCK DEVICE (BLOCK LAYER)
 M:	Damien Le Moal <dlemoal@kernel.org>
 L:	linux-block@vger.kernel.org

-- 
2.55.0



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

* Re: [PATCH RFC v3 01/17] firmware: arm_scmi: Drop the ARM architecture dependency
  2026-11-02 19:45 ` [PATCH RFC v3 01/17] firmware: arm_scmi: Drop the ARM architecture dependency Han Gao via B4 Relay
@ 2026-11-02 19:55   ` sashiko-bot
  0 siblings, 0 replies; 19+ messages in thread
From: sashiko-bot @ 2026-11-02 19:55 UTC (permalink / raw)
  To: Han Gao; +Cc: devicetree, linux-gpio, linux-clk, linux-serial, robh, conor+dt

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] firmware: arm_scmi: missing HAS_IOMEM dependency on ARM_SCMI_PROTOCOL
--

commit 2b45f4669350cda60b185c5a0c439cbdd7f35cc9
Author: Han Gao <gaohan@iscas.ac.cn>

firmware: arm_scmi: Drop the ARM architecture dependency

This commit removes the ARM, ARM64, and COMPILE_TEST dependency from
ARM_SCMI_PROTOCOL in Kconfig so that other architectures can build and use
the SCMI protocol driver.

> diff --git a/drivers/firmware/arm_scmi/Kconfig b/drivers/firmware/arm_scmi/Kconfig
> index 783c24a20e291..b56aed46a3870 100644
> --- a/drivers/firmware/arm_scmi/Kconfig
> +++ b/drivers/firmware/arm_scmi/Kconfig
> @@ -3,7 +3,6 @@ menu "ARM System Control and Management Interface Protocol"
>  
>  config ARM_SCMI_PROTOCOL
>  	tristate "ARM System Control and Management Interface (SCMI) Message Protocol"
> -	depends on ARM || ARM64 || COMPILE_TEST

[Severity: Low]
Should ARM_SCMI_PROTOCOL retain a dependency on HAS_IOMEM?

Previously, ARM and ARM64 selected HAS_IOMEM, and COMPILE_TEST in
init/Kconfig depends on HAS_IOMEM, which guaranteed that CONFIG_HAS_IOMEM
was enabled whenever ARM_SCMI_PROTOCOL was selectable. Dropping this line
leaves ARM_SCMI_PROTOCOL with no dependencies, allowing it to be enabled on
targets where CONFIG_HAS_IOMEM is disabled (such as ARCH=um).

When CONFIG_ARM_SCMI_PROTOCOL is enabled, the core driver in
drivers/firmware/arm_scmi/driver.c unconditionally compiles
scmi_common_fastchannel_init(), which calls devm_ioremap():

    addr = devm_ioremap(ph->dev, phys_addr, size);

In addition, when CONFIG_MAILBOX or CONFIG_OPTEE is enabled,
ARM_SCMI_TRANSPORT_MAILBOX or ARM_SCMI_TRANSPORT_OPTEE selects
ARM_SCMI_HAVE_SHMEM, which compiles drivers/firmware/arm_scmi/shmem.c
(calling __ioread32_copy() in shmem_memcpy_fromio32(), __iowrite32_copy()
in shmem_memcpy_toio32(), and devm_ioremap() in shmem_setup_iomap()) and
drivers/firmware/arm_scmi/transports/mailbox.c (calling devm_iounmap() in
mailbox_chan_setup()).

Because lib/Makefile only builds iomap_copy.o and devres.o when
CONFIG_HAS_IOMEM is enabled:

    obj-$(CONFIG_HAS_IOMEM) += iomap_copy.o devres.o

won't building ARM_SCMI_PROTOCOL with CONFIG_HAS_IOMEM disabled fail at link
time with undefined references to devm_ioremap(), devm_iounmap(),
__ioread32_copy(), and __iowrite32_copy()?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261103-a210-scmi-v3-0-ee6b31580808@iscas.ac.cn?part=1

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

end of thread, other threads:[~2026-11-02 19:55 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-02 19:45 [PATCH RFC v3 00/17] riscv: add initial Zhihe A210 support using SCMI clocks and resets Han Gao via B4 Relay
2026-11-02 19:45 ` [PATCH RFC v3 01/17] firmware: arm_scmi: Drop the ARM architecture dependency Han Gao via B4 Relay
2026-11-02 19:55   ` sashiko-bot
2026-11-02 19:45 ` [PATCH RFC v3 02/17] dt-bindings: vendor-prefixes: add Zhihe Han Gao via B4 Relay
2026-11-02 19:45 ` [PATCH RFC v3 03/17] riscv: add Zhihe A210 support Han Gao via B4 Relay
2026-11-02 19:45 ` [PATCH RFC v3 04/17] dt-bindings: mailbox: add Zhihe A210 AP to E902 mailbox Han Gao via B4 Relay
2026-11-02 19:45 ` [PATCH RFC v3 05/17] mailbox: add Zhihe A210 AP to E902 mailbox driver Han Gao via B4 Relay
2026-11-02 19:45 ` [PATCH RFC v3 06/17] dt-bindings: pinctrl: add Zhihe A210 pin controller Han Gao via B4 Relay
2026-11-02 19:45 ` [PATCH RFC v3 07/17] pinctrl: zhihe: add A210 support Han Gao via B4 Relay
2026-11-02 19:45 ` [PATCH RFC v3 08/17] dt-bindings: interrupt-controller: add Zhihe A210 PLIC Han Gao via B4 Relay
2026-11-02 19:45 ` [PATCH RFC v3 09/17] dt-bindings: riscv: add Melon Pi V1 and V2 Han Gao via B4 Relay
2026-11-02 19:45 ` [PATCH RFC v3 10/17] dt-bindings: timer: add Zhihe A210 CLINT Han Gao via B4 Relay
2026-11-02 19:45 ` [PATCH RFC v3 11/17] dt-bindings: serial: snps-dw-apb-uart: add Zhihe A210 UART Han Gao via B4 Relay
2026-11-02 19:45 ` [PATCH RFC v3 12/17] riscv: dts: zhihe: add A210 core support Han Gao via B4 Relay
2026-11-02 19:45 ` [PATCH RFC v3 13/17] riscv: dts: zhihe: add A210 UARTs Han Gao via B4 Relay
2026-11-02 19:45 ` [PATCH RFC v3 14/17] riscv: dts: zhihe: add A210 module memory Han Gao via B4 Relay
2026-11-02 19:45 ` [PATCH RFC v3 15/17] riscv: dts: zhihe: add Melon Pi V1 and V2 Han Gao via B4 Relay
2026-11-02 19:45 ` [PATCH RFC v3 16/17] riscv: defconfig: enable A210 support Han Gao via B4 Relay
2026-11-02 19:45 ` [PATCH RFC v3 17/17] MAINTAINERS: add Zhihe A210 Han Gao via B4 Relay

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