U-Boot Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 00/15] rockchip: Add support for the RV1103B, RV1103 and RV1106
@ 2026-07-07 15:30 Simon Glass
  2026-07-07 15:30 ` [PATCH v3 01/15] ARM: dts: Add the RV1103B devicetree files Simon Glass
                   ` (15 more replies)
  0 siblings, 16 replies; 21+ messages in thread
From: Simon Glass @ 2026-07-07 15:30 UTC (permalink / raw)
  To: u-boot
  Cc: Fabio Estevam, Jonas Karlman, Simon Glass, Albert Aribaud,
	Alexander Feilke, Alexey Charkov, Alexey Charkov, Andrew Davis,
	Anshul Dalal, Bastien Curutchet, Chris Morgan, Chris Packham,
	Elaine Zhang, FUKAUMI Naoki, Finley Xiao, Heinrich Schuchardt,
	Hrushikesh Salunke, Ilias Apalodimas, Jeffy Chen, Johan Jonker,
	João Marcos Costa, Kever Yang, Lukasz Majewski,
	Mattijs Korpershoek, Neil Armstrong, Niu Zhihong, Peng Fan,
	Peter Robinson, Philipp Tomsich, Quentin Schulz, Richard Genoud,
	Svyatoslav Ryhel, Tianling Shen, Tom Rini, Xuhui Lin, Ye Zhang,
	huang lin

This series adds support for three small Rockchip camera SoCs and two
boards which use them.

The first eight patches are Fabio Estevam's series adding the RV1103B
and the Onion Omega4 board, updated here to address the review
comments on v2: the board patch is split into SoC and board patches,
the devicetree files move into the patches where they belong and the
pinctrl driver uses regmap_update_bits() throughout. All credit for
this work goes to Fabio. The devicetree concern raised in the v2
review is also resolved now: the devicetree files carried here are the
versions merged in Linux v7.1, verbatim, and can be dropped once the
next dts/upstream sync brings them in.

The remaining patches add the RV1106 and its RV1103 package variant,
following the same structure as the RV1103B patches, together with
the Luckfox Pico Mini B board. These SoCs have no mainline Linux
support yet, so their devicetrees are local for now. The clock and
pinctrl drivers are ported from the Rockchip vendor tree and are the
work of Elaine Zhang and Ye Zhang. The final patch makes the
maskrom-mode RAM-boot images work on 32-bit boards without OP-TEE,
which both of these boards rely on.

Tested on the Luckfox Pico Mini B: U-Boot runs from RAM over the USB
maskrom path and both the SPI NAND and a microSD card are usable. THe
board is running in my lab.

Changes in v3:
- Move the board devicetrees to the board patch and the SoC u-boot.dtsi
  to the SoC patch (Jonas)
- Use the devicetree files as merged in Linux v7.1
- Use regmap_update_bits() in all the remaining places (Jonas)
- Align continuation lines with the open parenthesis (checkpatch)
- Use CONFIG_IS_ENABLED() to guard the set_parent operation, matching
  clk_rk3588.c, since plain IS_ENABLED() needs the CONFIG_ prefix
- Guard the spi-nand checks with SPI_NAND_LOAD so that boards without
  SPI NAND support do not grow in size
- New patch, split out from the board patch (Jonas)
- Include the SoC u-boot.dtsi here (Jonas)
- Match the pmu-grf compatible used by the devicetree merged in Linux
  v7.1
- Split out the SoC support into its own patch (Jonas)
- Move the board devicetree files into this patch (Jonas)
- Add the board to the list in the Rockchip documentation
- Extend the MAINTAINERS entry to cover all the RV1103B files
- Use the board devicetree files as merged in Linux v7.1 and switch
  the default devicetree to rv1103b-omega4-evb

Changes in v2:
- Use the devicetrees submitted to upstream Linux
- Use the original author from Rockchip's vendor U-Boot tree
- Use regmap_update_bits()
- Remove unneeded blank lines
- Remove unneeded logging functions
- Use the original author from Rockchip's vendor U-Boot tree
- Use RV1103B rather than RV1103, which is the correct SoC name

Elaine Zhang (1):
  clk: rockchip: Add RV1103B clock driver

Fabio Estevam (5):
  ARM: dts: Add the RV1103B devicetree files
  rockchip: spl-boot-order: Add SPI NAND support
  spl: Add SPI NAND support via MTD in SPL
  rockchip: rv1103b: Add SoC support
  omega4-rv1103b: Add the initial support

Simon Glass (7):
  tools: rkcommon: Add RV1106 support
  pinctrl: rockchip: Add RV1106 support
  ARM: dts: Add the RV1103/RV1106 devicetree files
  clk: rockchip: Add RV1106 clock driver
  rockchip: rv1106: Add SoC support
  luckfox-pico: Add the initial support
  rockchip: Support legacy images when booting from RAM

Xuhui Lin (1):
  tools: rkcommon: Add RV1103B support

Ye Zhang (1):
  pinctrl: rockchip: Add RV1103B support

 .../rv1103-luckfox-pico-mini-b-u-boot.dtsi    |   10 +
 arch/arm/dts/rv1103-luckfox-pico-mini-b.dts   |   85 ++
 arch/arm/dts/rv1103.dtsi                      |   16 +
 arch/arm/dts/rv1103b-omega4-evb-u-boot.dtsi   |   10 +
 arch/arm/dts/rv1103b-omega4-evb.dts           |   63 +
 arch/arm/dts/rv1103b-omega4.dtsi              |  147 ++
 arch/arm/dts/rv1103b-pinctrl.dtsi             |  816 ++++++++++
 arch/arm/dts/rv1103b-u-boot.dtsi              |    4 +
 arch/arm/dts/rv1103b.dtsi                     |  239 +++
 arch/arm/dts/rv1106-pinctrl.dtsi              | 1102 ++++++++++++++
 arch/arm/dts/rv1106-u-boot.dtsi               |    4 +
 arch/arm/dts/rv1106.dtsi                      |  328 ++++
 .../include/asm/arch-rockchip/cru_rv1103b.h   |  266 ++++
 .../include/asm/arch-rockchip/cru_rv1106.h    |  305 ++++
 .../include/asm/arch-rockchip/grf_rv1103b.h   |   31 +
 arch/arm/include/asm/arch-rv1103b/boot0.h     |   11 +
 arch/arm/include/asm/arch-rv1106/boot0.h      |   11 +
 arch/arm/mach-rockchip/Kconfig                |   28 +
 arch/arm/mach-rockchip/Makefile               |    2 +
 arch/arm/mach-rockchip/rv1103b/Kconfig        |   22 +
 arch/arm/mach-rockchip/rv1103b/Makefile       |   12 +
 arch/arm/mach-rockchip/rv1103b/boot0.h        |    5 +
 arch/arm/mach-rockchip/rv1103b/clk_rv1103b.c  |   32 +
 arch/arm/mach-rockchip/rv1103b/rv1103b.c      |  133 ++
 .../mach-rockchip/rv1103b/syscon_rv1103b.c    |   19 +
 arch/arm/mach-rockchip/rv1106/Kconfig         |   28 +
 arch/arm/mach-rockchip/rv1106/Makefile        |   12 +
 arch/arm/mach-rockchip/rv1106/clk_rv1106.c    |   31 +
 arch/arm/mach-rockchip/rv1106/rv1106.c        |  118 ++
 arch/arm/mach-rockchip/rv1106/syscon_rv1106.c |   19 +
 arch/arm/mach-rockchip/spl-boot-order.c       |   12 +-
 arch/arm/mach-rockchip/spl.c                  |   53 +-
 board/luckfox/pico/Kconfig                    |   12 +
 board/luckfox/pico/MAINTAINERS                |    6 +
 board/luckfox/pico/Makefile                   |    7 +
 board/luckfox/pico/pico.c                     |   19 +
 board/luckfox/pico/pico.env                   |    4 +
 board/onion/omega4_rv1103b/Kconfig            |   12 +
 board/onion/omega4_rv1103b/MAINTAINERS        |   15 +
 board/onion/omega4_rv1103b/Makefile           |    7 +
 board/onion/omega4_rv1103b/omega4_rv1103b.c   |   19 +
 board/onion/omega4_rv1103b/omega4_rv1103b.env |    5 +
 common/spl/Kconfig                            |   10 +-
 common/spl/Makefile                           |    1 +
 common/spl/spl_spi_nand.c                     |   82 +
 configs/luckfox-pico-mini-b-rv1103_defconfig  |   79 +
 configs/omega4-rv1103b_defconfig              |   82 +
 doc/board/index.rst                           |    2 +
 doc/board/luckfox/index.rst                   |    9 +
 doc/board/luckfox/luckfox-pico.rst            |   71 +
 doc/board/onion/index.rst                     |    9 +
 doc/board/onion/omega4-rv1103b.rst            |   56 +
 doc/board/rockchip/rockchip.rst               |    7 +
 drivers/clk/rockchip/Makefile                 |    2 +
 drivers/clk/rockchip/clk_rv1103b.c            | 1068 +++++++++++++
 drivers/clk/rockchip/clk_rv1106.c             | 1319 +++++++++++++++++
 drivers/mtd/Makefile                          |    1 +
 drivers/mtd/nand/Makefile                     |   13 +-
 drivers/pinctrl/rockchip/Makefile             |    2 +
 drivers/pinctrl/rockchip/pinctrl-rv1103b.c    |  402 +++++
 drivers/pinctrl/rockchip/pinctrl-rv1106.c     |  320 ++++
 include/configs/luckfox_pico.h                |   11 +
 include/configs/omega4_rv1103b.h              |   11 +
 include/configs/rv1103b_common.h              |   14 +
 include/configs/rv1106_common.h               |   13 +
 .../dt-bindings/clock/rockchip,rv1103b-cru.h  |  220 +++
 include/dt-bindings/clock/rv1106-cru.h        |  572 +++++++
 tools/rkcommon.c                              |    2 +
 68 files changed, 8436 insertions(+), 22 deletions(-)
 create mode 100644 arch/arm/dts/rv1103-luckfox-pico-mini-b-u-boot.dtsi
 create mode 100644 arch/arm/dts/rv1103-luckfox-pico-mini-b.dts
 create mode 100644 arch/arm/dts/rv1103.dtsi
 create mode 100644 arch/arm/dts/rv1103b-omega4-evb-u-boot.dtsi
 create mode 100644 arch/arm/dts/rv1103b-omega4-evb.dts
 create mode 100644 arch/arm/dts/rv1103b-omega4.dtsi
 create mode 100644 arch/arm/dts/rv1103b-pinctrl.dtsi
 create mode 100644 arch/arm/dts/rv1103b-u-boot.dtsi
 create mode 100644 arch/arm/dts/rv1103b.dtsi
 create mode 100644 arch/arm/dts/rv1106-pinctrl.dtsi
 create mode 100644 arch/arm/dts/rv1106-u-boot.dtsi
 create mode 100644 arch/arm/dts/rv1106.dtsi
 create mode 100644 arch/arm/include/asm/arch-rockchip/cru_rv1103b.h
 create mode 100644 arch/arm/include/asm/arch-rockchip/cru_rv1106.h
 create mode 100644 arch/arm/include/asm/arch-rockchip/grf_rv1103b.h
 create mode 100644 arch/arm/include/asm/arch-rv1103b/boot0.h
 create mode 100644 arch/arm/include/asm/arch-rv1106/boot0.h
 create mode 100644 arch/arm/mach-rockchip/rv1103b/Kconfig
 create mode 100644 arch/arm/mach-rockchip/rv1103b/Makefile
 create mode 100644 arch/arm/mach-rockchip/rv1103b/boot0.h
 create mode 100644 arch/arm/mach-rockchip/rv1103b/clk_rv1103b.c
 create mode 100644 arch/arm/mach-rockchip/rv1103b/rv1103b.c
 create mode 100644 arch/arm/mach-rockchip/rv1103b/syscon_rv1103b.c
 create mode 100644 arch/arm/mach-rockchip/rv1106/Kconfig
 create mode 100644 arch/arm/mach-rockchip/rv1106/Makefile
 create mode 100644 arch/arm/mach-rockchip/rv1106/clk_rv1106.c
 create mode 100644 arch/arm/mach-rockchip/rv1106/rv1106.c
 create mode 100644 arch/arm/mach-rockchip/rv1106/syscon_rv1106.c
 create mode 100644 board/luckfox/pico/Kconfig
 create mode 100644 board/luckfox/pico/MAINTAINERS
 create mode 100644 board/luckfox/pico/Makefile
 create mode 100644 board/luckfox/pico/pico.c
 create mode 100644 board/luckfox/pico/pico.env
 create mode 100644 board/onion/omega4_rv1103b/Kconfig
 create mode 100644 board/onion/omega4_rv1103b/MAINTAINERS
 create mode 100644 board/onion/omega4_rv1103b/Makefile
 create mode 100644 board/onion/omega4_rv1103b/omega4_rv1103b.c
 create mode 100644 board/onion/omega4_rv1103b/omega4_rv1103b.env
 create mode 100644 common/spl/spl_spi_nand.c
 create mode 100644 configs/luckfox-pico-mini-b-rv1103_defconfig
 create mode 100644 configs/omega4-rv1103b_defconfig
 create mode 100644 doc/board/luckfox/index.rst
 create mode 100644 doc/board/luckfox/luckfox-pico.rst
 create mode 100644 doc/board/onion/index.rst
 create mode 100644 doc/board/onion/omega4-rv1103b.rst
 create mode 100644 drivers/clk/rockchip/clk_rv1103b.c
 create mode 100644 drivers/clk/rockchip/clk_rv1106.c
 create mode 100644 drivers/pinctrl/rockchip/pinctrl-rv1103b.c
 create mode 100644 drivers/pinctrl/rockchip/pinctrl-rv1106.c
 create mode 100644 include/configs/luckfox_pico.h
 create mode 100644 include/configs/omega4_rv1103b.h
 create mode 100644 include/configs/rv1103b_common.h
 create mode 100644 include/configs/rv1106_common.h
 create mode 100644 include/dt-bindings/clock/rockchip,rv1103b-cru.h
 create mode 100644 include/dt-bindings/clock/rv1106-cru.h

---
base-commit: ee5d46b45ec0c63f8f9dd1e816e0dac3452ccc3d
branch: rocka-us3

-- 
2.43.0


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

* [PATCH v3 01/15] ARM: dts: Add the RV1103B devicetree files
  2026-07-07 15:30 [PATCH v3 00/15] rockchip: Add support for the RV1103B, RV1103 and RV1106 Simon Glass
@ 2026-07-07 15:30 ` Simon Glass
  2026-07-07 15:31 ` [PATCH v3 02/15] pinctrl: rockchip: Add RV1103B support Simon Glass
                   ` (14 subsequent siblings)
  15 siblings, 0 replies; 21+ messages in thread
From: Simon Glass @ 2026-07-07 15:30 UTC (permalink / raw)
  To: u-boot
  Cc: Fabio Estevam, Jonas Karlman, Simon Glass, Albert Aribaud,
	Ilias Apalodimas, Kever Yang, Philipp Tomsich, Tom Rini

From: Fabio Estevam <festevam@nabladev.com>

Add the RV1103B SoC devicetree files, taken verbatim from Linux v7.1,
where the RV1103B support is merged.

Once U-Boot's dts/upstream subtree is updated to v7.1-dts, the
OF_UPSTREAM mechanism can be enabled and these files dropped.

Signed-off-by: Fabio Estevam <festevam@nabladev.com>
Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3:
- Move the board devicetrees to the board patch and the SoC u-boot.dtsi
  to the SoC patch (Jonas)
- Use the devicetree files as merged in Linux v7.1

Changes in v2:
- Use the devicetrees submitted to upstream Linux

 arch/arm/dts/rv1103b-pinctrl.dtsi             | 816 ++++++++++++++++++
 arch/arm/dts/rv1103b.dtsi                     | 239 +++++
 .../dt-bindings/clock/rockchip,rv1103b-cru.h  | 220 +++++
 3 files changed, 1275 insertions(+)
 create mode 100644 arch/arm/dts/rv1103b-pinctrl.dtsi
 create mode 100644 arch/arm/dts/rv1103b.dtsi
 create mode 100644 include/dt-bindings/clock/rockchip,rv1103b-cru.h

diff --git a/arch/arm/dts/rv1103b-pinctrl.dtsi b/arch/arm/dts/rv1103b-pinctrl.dtsi
new file mode 100644
index 00000000000..15516c38413
--- /dev/null
+++ b/arch/arm/dts/rv1103b-pinctrl.dtsi
@@ -0,0 +1,816 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2026 Rockchip Electronics Co., Ltd.
+ */
+
+#include <dt-bindings/pinctrl/rockchip.h>
+#include <arm64/rockchip/rockchip-pinconf.dtsi>
+
+&pinctrl {
+	cam-clk0 {
+		/omit-if-no-ref/
+		cam_clk0: cam-clk0 {
+			rockchip,pins =
+				/* cam_clk0_out */
+				<1 RK_PB5 1 &pcfg_pull_none>;
+		};
+	};
+
+	cam-clk1 {
+		/omit-if-no-ref/
+		cam_clk1: cam-clk1 {
+			rockchip,pins =
+				/* cam_clk1_out */
+				<1 RK_PB6 1 &pcfg_pull_none>;
+		};
+	};
+
+	cam-spi {
+		/omit-if-no-ref/
+		cam_spi_bus4: cam-spi-bus4 {
+			rockchip,pins =
+				/* cam_spi_d0 */
+				<0 RK_PB5 4 &pcfg_pull_up_drv_level_2>,
+				/* cam_spi_d1 */
+				<0 RK_PB2 4 &pcfg_pull_up_drv_level_2>,
+				/* cam_spi_d2 */
+				<0 RK_PB1 4 &pcfg_pull_up_drv_level_2>,
+				/* cam_spi_d3 */
+				<0 RK_PB0 4 &pcfg_pull_up_drv_level_2>;
+		};
+
+		/omit-if-no-ref/
+		cam_spi_clk: cam-spi-clk {
+			rockchip,pins =
+				/* cam_spi_clk */
+				<0 RK_PB4 4 &pcfg_pull_none>;
+		};
+		/omit-if-no-ref/
+		cam_spi_cs0n: cam-spi-cs0n {
+			rockchip,pins =
+				/* cam_spi_cs0n */
+				<0 RK_PB3 4 &pcfg_pull_none>;
+		};
+	};
+
+	clk {
+		/omit-if-no-ref/
+		clk_32k: clk-32k {
+			rockchip,pins =
+				/* clk_32k */
+				<0 RK_PA0 2 &pcfg_pull_none>;
+		};
+	};
+
+	clk-24m {
+		/omit-if-no-ref/
+		clk_24m_out: clk-24m-out {
+			rockchip,pins =
+				/* clk_24m_out */
+				<0 RK_PA0 3 &pcfg_pull_none>;
+		};
+	};
+
+	cpu {
+		/omit-if-no-ref/
+		cpu: cpu {
+			rockchip,pins =
+				/* cpu_avs */
+				<0 RK_PA1 2 &pcfg_pull_none>;
+		};
+	};
+
+	emmc {
+		/omit-if-no-ref/
+		emmc_bus4: emmc-bus4 {
+			rockchip,pins =
+				/* emmc_d0 */
+				<1 RK_PA1 1 &pcfg_pull_up_drv_level_2>,
+				/* emmc_d1 */
+				<1 RK_PA2 1 &pcfg_pull_up_drv_level_2>,
+				/* emmc_d2 */
+				<1 RK_PA3 1 &pcfg_pull_up_drv_level_2>,
+				/* emmc_d3 */
+				<1 RK_PA0 1 &pcfg_pull_up_drv_level_2>;
+		};
+
+		/omit-if-no-ref/
+		emmc_clk: emmc-clk {
+			rockchip,pins =
+				/* emmc_clk */
+				<1 RK_PA4 1 &pcfg_pull_up_drv_level_2>;
+		};
+
+		/omit-if-no-ref/
+		emmc_cmd: emmc-cmd {
+			rockchip,pins =
+				/* emmc_cmd */
+				<1 RK_PA5 1 &pcfg_pull_up_drv_level_2>;
+		};
+	};
+
+	fspi {
+		/omit-if-no-ref/
+		fspi_bus4: fspi-bus4 {
+			rockchip,pins =
+				/* fspi_d0 */
+				<1 RK_PA1 2 &pcfg_pull_none>,
+				/* fspi_d1 */
+				<1 RK_PA2 2 &pcfg_pull_none>,
+				/* fspi_d2 */
+				<1 RK_PA3 2 &pcfg_pull_none>,
+				/* fspi_d3 */
+				<1 RK_PA0 2 &pcfg_pull_none>;
+		};
+
+		/omit-if-no-ref/
+		fspi_cs0: fspi-cs0 {
+			rockchip,pins =
+				/* fspi_cs0n */
+				<1 RK_PA5 2 &pcfg_pull_up>;
+		};
+
+		/omit-if-no-ref/
+		fspi_clk: fspi-clk {
+			rockchip,pins =
+				/* fspi_clk */
+				<1 RK_PA4 2 &pcfg_pull_none>;
+		};
+	};
+
+	i2c0 {
+		/omit-if-no-ref/
+		i2c0m0_xfer: i2c0m0-xfer {
+			rockchip,pins =
+				/* i2c0_scl_m0 */
+				<0 RK_PA5 3 &pcfg_pull_none_smt>,
+				/* i2c0_sda_m0 */
+				<0 RK_PA6 3 &pcfg_pull_none_smt>;
+		};
+
+		/omit-if-no-ref/
+		i2c0m1_xfer: i2c0m1-xfer {
+			rockchip,pins =
+				/* i2c0_scl_m1 */
+				<1 RK_PB4 5 &pcfg_pull_none_smt>,
+				/* i2c0_sda_m1 */
+				<1 RK_PB3 5 &pcfg_pull_none_smt>;
+		};
+
+		/omit-if-no-ref/
+		i2c0m2_xfer: i2c0m2-xfer {
+			rockchip,pins =
+				/* i2c0_scl_m2 */
+				<1 RK_PB5 2 &pcfg_pull_none_smt>,
+				/* i2c0_sda_m2 */
+				<1 RK_PB6 2 &pcfg_pull_none_smt>;
+		};
+	};
+
+	i2c1 {
+		/omit-if-no-ref/
+		i2c1m0_xfer: i2c1m0-xfer {
+			rockchip,pins =
+				/* i2c1_scl_m0 */
+				<0 RK_PB0 1 &pcfg_pull_none_smt>,
+				/* i2c1_sda_m0 */
+				<0 RK_PB1 1 &pcfg_pull_none_smt>;
+		};
+
+		/omit-if-no-ref/
+		i2c1m1_xfer: i2c1m1-xfer {
+			rockchip,pins =
+				/* i2c1_scl_m1 */
+				<2 RK_PA4 4 &pcfg_pull_none_smt>,
+				/* i2c1_sda_m1 */
+				<2 RK_PA5 4 &pcfg_pull_none_smt>;
+		};
+	};
+
+	i2c2 {
+		/omit-if-no-ref/
+		i2c2m0_xfer: i2c2m0-xfer {
+			rockchip,pins =
+				/* i2c2_scl_m0 */
+				<0 RK_PB2 1 &pcfg_pull_none_smt>,
+				/* i2c2_sda_m0 */
+				<0 RK_PB3 1 &pcfg_pull_none_smt>;
+		};
+
+		/omit-if-no-ref/
+		i2c2m1_xfer: i2c2m1-xfer {
+			rockchip,pins =
+				/* i2c2_scl_m1 */
+				<2 RK_PA6 4 &pcfg_pull_none_smt>,
+				/* i2c2_sda_m1 */
+				<2 RK_PA7 4 &pcfg_pull_none_smt>;
+		};
+	};
+
+	i2c3 {
+		/omit-if-no-ref/
+		i2c3m0_xfer: i2c3m0-xfer {
+			rockchip,pins =
+				/* i2c3_scl_m0 */
+				<0 RK_PB4 1 &pcfg_pull_none_smt>,
+				/* i2c3_sda_m0 */
+				<0 RK_PB5 1 &pcfg_pull_none_smt>;
+		};
+
+		/omit-if-no-ref/
+		i2c3m1_xfer: i2c3m1-xfer {
+			rockchip,pins =
+				/* i2c3_scl_m1 */
+				<2 RK_PB3 4 &pcfg_pull_none_smt>,
+				/* i2c3_sda_m1 */
+				<2 RK_PB2 4 &pcfg_pull_none_smt>;
+		};
+	};
+
+	i2c4 {
+		/omit-if-no-ref/
+		i2c4m0_xfer: i2c4m0-xfer {
+			rockchip,pins =
+				/* i2c4_scl_m0 */
+				<2 RK_PB0 4 &pcfg_pull_none_smt>,
+				/* i2c4_sda_m0 */
+				<2 RK_PB1 4 &pcfg_pull_none_smt>;
+		};
+
+		/omit-if-no-ref/
+		i2c4m1_xfer: i2c4m1-xfer {
+			rockchip,pins =
+				/* i2c4_scl_m1 */
+				<1 RK_PB7 2 &pcfg_pull_none_smt>,
+				/* i2c4_sda_m1 */
+				<1 RK_PC0 2 &pcfg_pull_none_smt>;
+		};
+	};
+
+	jtag {
+		/omit-if-no-ref/
+		jtagm0: jtagm0 {
+			rockchip,pins =
+				/* jtag_tck_m0 */
+				<0 RK_PA5 5 &pcfg_pull_none>,
+				/* jtag_tms_m0 */
+				<0 RK_PA6 5 &pcfg_pull_none>;
+		};
+
+		/omit-if-no-ref/
+		jtagm1: jtagm1 {
+			rockchip,pins =
+				/* jtag_tck_m1 */
+				<0 RK_PB4 3 &pcfg_pull_none>,
+				/* jtag_tms_m1 */
+				<0 RK_PB5 3 &pcfg_pull_none>;
+		};
+
+		/omit-if-no-ref/
+		jtagm2: jtagm2 {
+			rockchip,pins =
+				/* jtag_tck_m2 */
+				<1 RK_PB4 3 &pcfg_pull_none>,
+				/* jtag_tms_m2 */
+				<1 RK_PB3 3 &pcfg_pull_none>;
+		};
+	};
+
+	psram-spi {
+		/omit-if-no-ref/
+		psram_spi_bus4: psram-spi-bus4 {
+			rockchip,pins =
+				/* psram_spi_d0 */
+				<0 RK_PA2 4 &pcfg_pull_none>,
+				/* psram_spi_d1 */
+				<0 RK_PA1 4 &pcfg_pull_none>,
+				/* psram_spi_d2 */
+				<0 RK_PA5 4 &pcfg_pull_none>,
+				/* psram_spi_d3 */
+				<0 RK_PA6 4 &pcfg_pull_none>;
+		};
+
+		/omit-if-no-ref/
+		psram_spi_clk: psram-spi-clk {
+			rockchip,pins =
+				/* psram_spi_clk */
+				<0 RK_PA0 4 &pcfg_pull_none>;
+		};
+		/omit-if-no-ref/
+		psram_spi_cs0n: psram-spi-cs0n {
+			rockchip,pins =
+				/* psram_spi_cs0n */
+				<0 RK_PA4 4 &pcfg_pull_none>;
+		};
+	};
+
+	pwm0 {
+		/omit-if-no-ref/
+		pwm0m0_ch0: pwm0m0-ch0 {
+			rockchip,pins =
+				/* pwm0m0_ch0 */
+				<0 RK_PA1 1 &pcfg_pull_none_drv_level_0>;
+		};
+		/omit-if-no-ref/
+		pwm0m0_ch1: pwm0m0-ch1 {
+			rockchip,pins =
+				/* pwm0m0_ch1 */
+				<0 RK_PA5 2 &pcfg_pull_none_drv_level_0>;
+		};
+		/omit-if-no-ref/
+		pwm0m0_ch2: pwm0m0-ch2 {
+			rockchip,pins =
+				/* pwm0m0_ch2 */
+				<0 RK_PA6 2 &pcfg_pull_none_drv_level_0>;
+		};
+		/omit-if-no-ref/
+		pwm0m0_ch3: pwm0m0-ch3 {
+			rockchip,pins =
+				/* pwm0m0_ch3 */
+				<0 RK_PA2 1 &pcfg_pull_none_drv_level_0>;
+		};
+
+		/omit-if-no-ref/
+		pwm0m1_ch0: pwm0m1-ch0 {
+			rockchip,pins =
+				/* pwm0m1_ch0 */
+				<2 RK_PA0 3 &pcfg_pull_none_drv_level_0>;
+		};
+		/omit-if-no-ref/
+		pwm0m1_ch1: pwm0m1-ch1 {
+			rockchip,pins =
+				/* pwm0m1_ch1 */
+				<2 RK_PA1 3 &pcfg_pull_none_drv_level_0>;
+		};
+		/omit-if-no-ref/
+		pwm0m1_ch2: pwm0m1-ch2 {
+			rockchip,pins =
+				/* pwm0m1_ch2 */
+				<2 RK_PA2 3 &pcfg_pull_none_drv_level_0>;
+		};
+		/omit-if-no-ref/
+		pwm0m1_ch3: pwm0m1-ch3 {
+			rockchip,pins =
+				/* pwm0m1_ch3 */
+				<2 RK_PB0 3 &pcfg_pull_none_drv_level_0>;
+		};
+
+		/omit-if-no-ref/
+		pwm0m2_ch1: pwm0m2-ch1 {
+			rockchip,pins =
+				/* pwm0m2_ch1 */
+				<1 RK_PB7 1 &pcfg_pull_none_drv_level_0>;
+		};
+		/omit-if-no-ref/
+		pwm0m2_ch2: pwm0m2-ch2 {
+			rockchip,pins =
+				/* pwm0m2_ch2 */
+				<1 RK_PC0 1 &pcfg_pull_none_drv_level_0>;
+		};
+	};
+
+	pwm1 {
+		/omit-if-no-ref/
+		pwm1m0_ch0: pwm1m0-ch0 {
+			rockchip,pins =
+				/* pwm1m0_ch0 */
+				<0 RK_PB0 3 &pcfg_pull_none_drv_level_0>;
+		};
+		/omit-if-no-ref/
+		pwm1m0_ch1: pwm1m0-ch1 {
+			rockchip,pins =
+				/* pwm1m0_ch1 */
+				<0 RK_PB1 3 &pcfg_pull_none_drv_level_0>;
+		};
+		/omit-if-no-ref/
+		pwm1m0_ch2: pwm1m0-ch2 {
+			rockchip,pins =
+				/* pwm1m0_ch2 */
+				<0 RK_PB2 3 &pcfg_pull_none_drv_level_0>;
+		};
+		/omit-if-no-ref/
+		pwm1m0_ch3: pwm1m0-ch3 {
+			rockchip,pins =
+				/* pwm1m0_ch3 */
+				<0 RK_PB3 3 &pcfg_pull_none_drv_level_0>;
+		};
+
+		/omit-if-no-ref/
+		pwm1m1_ch0: pwm1m1-ch0 {
+			rockchip,pins =
+				/* pwm1m1_ch0 */
+				<2 RK_PA3 3 &pcfg_pull_none_drv_level_0>;
+		};
+		/omit-if-no-ref/
+		pwm1m1_ch1: pwm1m1-ch1 {
+			rockchip,pins =
+				/* pwm1m1_ch1 */
+				<2 RK_PA4 3 &pcfg_pull_none_drv_level_0>;
+		};
+		/omit-if-no-ref/
+		pwm1m1_ch2: pwm1m1-ch2 {
+			rockchip,pins =
+				/* pwm1m1_ch2 */
+				<2 RK_PA5 3 &pcfg_pull_none_drv_level_0>;
+		};
+		/omit-if-no-ref/
+		pwm1m1_ch3: pwm1m1-ch3 {
+			rockchip,pins =
+				/* pwm1m1_ch3 */
+				<2 RK_PB1 3 &pcfg_pull_none_drv_level_0>;
+		};
+	};
+
+	pwm2 {
+		/omit-if-no-ref/
+		pwm2m0_ch0: pwm2m0-ch0 {
+			rockchip,pins =
+				/* pwm2m0_ch0 */
+				<1 RK_PB0 4 &pcfg_pull_none_drv_level_0>;
+		};
+		/omit-if-no-ref/
+		pwm2m0_ch1: pwm2m0-ch1 {
+			rockchip,pins =
+				/* pwm2m0_ch1 */
+				<1 RK_PA7 4 &pcfg_pull_none_drv_level_0>;
+		};
+		/omit-if-no-ref/
+		pwm2m0_ch2: pwm2m0-ch2 {
+			rockchip,pins =
+				/* pwm2m0_ch2 */
+				<1 RK_PB4 4 &pcfg_pull_none_drv_level_0>;
+		};
+		/omit-if-no-ref/
+		pwm2m0_ch3: pwm2m0-ch3 {
+			rockchip,pins =
+				/* pwm2m0_ch3 */
+				<1 RK_PB3 4 &pcfg_pull_none_drv_level_0>;
+		};
+
+		/omit-if-no-ref/
+		pwm2m1_ch0: pwm2m1-ch0 {
+			rockchip,pins =
+				/* pwm2m1_ch0 */
+				<2 RK_PA6 3 &pcfg_pull_none_drv_level_0>;
+		};
+		/omit-if-no-ref/
+		pwm2m1_ch1: pwm2m1-ch1 {
+			rockchip,pins =
+				/* pwm2m1_ch1 */
+				<2 RK_PA7 3 &pcfg_pull_none_drv_level_0>;
+		};
+		/omit-if-no-ref/
+		pwm2m1_ch2: pwm2m1-ch2 {
+			rockchip,pins =
+				/* pwm2m1_ch2 */
+				<2 RK_PB2 3 &pcfg_pull_none_drv_level_0>;
+		};
+		/omit-if-no-ref/
+		pwm2m1_ch3: pwm2m1-ch3 {
+			rockchip,pins =
+				/* pwm2m1_ch3 */
+				<2 RK_PB3 3 &pcfg_pull_none_drv_level_0>;
+		};
+	};
+
+	pwr {
+		/omit-if-no-ref/
+		pwr: pwr {
+			rockchip,pins =
+				/* pwr_ctrl0 */
+				<0 RK_PA3 1 &pcfg_pull_none>,
+				/* pwr_ctrl1 */
+				<0 RK_PA4 1 &pcfg_pull_none>;
+		};
+	};
+
+	rtc_32k {
+		/omit-if-no-ref/
+		rtc_32k: rtc-32k {
+			rockchip,pins =
+				/* rtc_32k_out */
+				<0 RK_PA0 1 &pcfg_pull_none>;
+		};
+	};
+
+	sai {
+		/omit-if-no-ref/
+		sai: sai {
+			rockchip,pins =
+				/* sai_lrck */
+				<2 RK_PB1 5 &pcfg_pull_none>,
+				/* sai_mclk */
+				<2 RK_PB0 5 &pcfg_pull_none>,
+				/* sai_sclk */
+				<2 RK_PA7 5 &pcfg_pull_none>,
+				/* sai_sdi */
+				<2 RK_PA6 5 &pcfg_pull_none>,
+				/* sai_sdo */
+				<2 RK_PB2 5 &pcfg_pull_none>;
+		};
+	};
+
+	sdmmc0 {
+		/omit-if-no-ref/
+		sdmmc0_bus4: sdmmc0-bus4 {
+			rockchip,pins =
+				/* sdmmc0_d0 */
+				<1 RK_PB0 1 &pcfg_pull_up_drv_level_2>,
+				/* sdmmc0_d1 */
+				<1 RK_PA7 1 &pcfg_pull_up_drv_level_2>,
+				/* sdmmc0_d2 */
+				<1 RK_PB4 1 &pcfg_pull_up_drv_level_2>,
+				/* sdmmc0_d3 */
+				<1 RK_PB3 1 &pcfg_pull_up_drv_level_2>;
+		};
+
+		/omit-if-no-ref/
+		sdmmc0_clk: sdmmc0-clk {
+			rockchip,pins =
+				/* sdmmc0_clk */
+				<1 RK_PB1 1 &pcfg_pull_up_drv_level_2>;
+		};
+
+		/omit-if-no-ref/
+		sdmmc0_cmd: sdmmc0-cmd {
+			rockchip,pins =
+				/* sdmmc0_cmd */
+				<1 RK_PB2 1 &pcfg_pull_up_drv_level_2>;
+		};
+
+		/omit-if-no-ref/
+		sdmmc0_det: sdmmc0-det {
+			rockchip,pins =
+				/* sdmmc0_det */
+				<1 RK_PA6 1 &pcfg_pull_up>;
+		};
+	};
+
+	sdmmc1 {
+		/omit-if-no-ref/
+		sdmmc1_bus4: sdmmc1-bus4 {
+			rockchip,pins =
+				/* sdmmc1_d0 */
+				<2 RK_PA1 1 &pcfg_pull_up_drv_level_2>,
+				/* sdmmc1_d1 */
+				<2 RK_PA0 1 &pcfg_pull_up_drv_level_2>,
+				/* sdmmc1_d2 */
+				<2 RK_PA5 1 &pcfg_pull_up_drv_level_2>,
+				/* sdmmc1_d3 */
+				<2 RK_PA4 1 &pcfg_pull_up_drv_level_2>;
+		};
+
+		/omit-if-no-ref/
+		sdmmc1_clk: sdmmc1-clk {
+			rockchip,pins =
+				/* sdmmc1_clk */
+				<2 RK_PA2 1 &pcfg_pull_up_drv_level_2>;
+		};
+
+		/omit-if-no-ref/
+		sdmmc1_cmd: sdmmc1-cmd {
+			rockchip,pins =
+				/* sdmmc1_cmd */
+				<2 RK_PA3 1 &pcfg_pull_up_drv_level_2>;
+		};
+	};
+
+	spi0 {
+		/omit-if-no-ref/
+		spi0m0_clk: spi0m0-clk {
+			rockchip,pins =
+				/* spi0_clk_m0 */
+				<2 RK_PB0 2 &pcfg_pull_none>,
+				/* spi0_miso_m0 */
+				<2 RK_PB3 2 &pcfg_pull_none>,
+				/* spi0_mosi_m0 */
+				<2 RK_PB1 2 &pcfg_pull_none>;
+		};
+
+		/omit-if-no-ref/
+		spi0m0_cs0: spi0m0-cs0 {
+			rockchip,pins =
+				/* spi0_cs0n_m0 */
+				<2 RK_PB2 2 &pcfg_pull_none>;
+		};
+
+		/omit-if-no-ref/
+		spi0m0_cs1: spi0m0-cs1 {
+			rockchip,pins =
+				/* spi0_cs1n_m0 */
+				<2 RK_PA7 2 &pcfg_pull_none>;
+		};
+
+		/omit-if-no-ref/
+		spi0m1_clk: spi0m1-clk {
+			rockchip,pins =
+				/* spi0_clk_m1 */
+				<2 RK_PA2 5 &pcfg_pull_none>,
+				/* spi0_miso_m1 */
+				<2 RK_PA4 5 &pcfg_pull_none>,
+				/* spi0_mosi_m1 */
+				<2 RK_PA1 5 &pcfg_pull_none>;
+		};
+
+		/omit-if-no-ref/
+		spi0m1_cs0: spi0m1-cs0 {
+			rockchip,pins =
+				/* spi0_cs0n_m1 */
+				<2 RK_PA3 5 &pcfg_pull_none>;
+		};
+
+		/omit-if-no-ref/
+		spi0m1_cs1: spi0m1-cs1 {
+			rockchip,pins =
+				/* spi0_cs1n_m1 */
+				<2 RK_PA0 5 &pcfg_pull_none>;
+		};
+	};
+
+	uart0 {
+		/omit-if-no-ref/
+		uart0m0_xfer: uart0m0-xfer {
+			rockchip,pins =
+				/* uart0_rx_m0 */
+				<0 RK_PA6 1 &pcfg_pull_up>,
+				/* uart0_tx_m0 */
+				<0 RK_PA5 1 &pcfg_pull_up>;
+		};
+
+		/omit-if-no-ref/
+		uart0m1_xfer: uart0m1-xfer {
+			rockchip,pins =
+				/* uart0_rx_m1 */
+				<0 RK_PB5 2 &pcfg_pull_up>,
+				/* uart0_tx_m1 */
+				<0 RK_PB4 2 &pcfg_pull_up>;
+		};
+
+		/omit-if-no-ref/
+		uart0m2_xfer: uart0m2-xfer {
+			rockchip,pins =
+				/* uart0_rx_m2 */
+				<1 RK_PB3 2 &pcfg_pull_up>,
+				/* uart0_tx_m2 */
+				<1 RK_PB4 2 &pcfg_pull_up>;
+		};
+	};
+
+	uart1 {
+		/omit-if-no-ref/
+		uart1m0_xfer: uart1m0-xfer {
+			rockchip,pins =
+				/* uart1_rx_m0 */
+				<0 RK_PB2 2 &pcfg_pull_up>,
+				/* uart1_tx_m0 */
+				<0 RK_PB3 2 &pcfg_pull_up>;
+		};
+
+		/omit-if-no-ref/
+		uart1m0_ctsn: uart1m0-ctsn {
+			rockchip,pins =
+				/* uart1m0_ctsn */
+				<0 RK_PB5 5 &pcfg_pull_none>;
+		};
+		/omit-if-no-ref/
+		uart1m0_rtsn: uart1m0-rtsn {
+			rockchip,pins =
+				/* uart1m0_rtsn */
+				<0 RK_PB4 5 &pcfg_pull_none>;
+		};
+
+		/omit-if-no-ref/
+		uart1m1_xfer: uart1m1-xfer {
+			rockchip,pins =
+				/* uart1_rx_m1 */
+				<1 RK_PA7 2 &pcfg_pull_up>,
+				/* uart1_tx_m1 */
+				<1 RK_PB0 2 &pcfg_pull_up>;
+		};
+
+		/omit-if-no-ref/
+		uart1m1_ctsn: uart1m1-ctsn {
+			rockchip,pins =
+				/* uart1m1_ctsn */
+				<1 RK_PB2 2 &pcfg_pull_none>;
+		};
+		/omit-if-no-ref/
+		uart1m1_rtsn: uart1m1-rtsn {
+			rockchip,pins =
+				/* uart1m1_rtsn */
+				<1 RK_PB1 2 &pcfg_pull_none>;
+		};
+
+		/omit-if-no-ref/
+		uart1m2_xfer: uart1m2-xfer {
+			rockchip,pins =
+				/* uart1_rx_m2 */
+				<2 RK_PA7 1 &pcfg_pull_up>,
+				/* uart1_tx_m2 */
+				<2 RK_PA6 1 &pcfg_pull_up>;
+		};
+
+		/omit-if-no-ref/
+		uart1m2_ctsn: uart1m2-ctsn {
+			rockchip,pins =
+				/* uart1m2_ctsn */
+				<2 RK_PA5 2 &pcfg_pull_none>;
+		};
+		/omit-if-no-ref/
+		uart1m2_rtsn: uart1m2-rtsn {
+			rockchip,pins =
+				/* uart1m2_rtsn */
+				<2 RK_PA4 2 &pcfg_pull_none>;
+		};
+
+		/omit-if-no-ref/
+		uart1m3_xfer: uart1m3-xfer {
+			rockchip,pins =
+				/* uart1_rx_m3 */
+				<2 RK_PA3 2 &pcfg_pull_up>,
+				/* uart1_tx_m3 */
+				<2 RK_PA2 2 &pcfg_pull_up>;
+		};
+
+		/omit-if-no-ref/
+		uart1m3_ctsn: uart1m3-ctsn {
+			rockchip,pins =
+				/* uart1m3_ctsn */
+				<2 RK_PA1 2 &pcfg_pull_none>;
+		};
+		/omit-if-no-ref/
+		uart1m3_rtsn: uart1m3-rtsn {
+			rockchip,pins =
+				/* uart1m3_rtsn */
+				<2 RK_PA0 2 &pcfg_pull_none>;
+		};
+	};
+
+	uart2 {
+		/omit-if-no-ref/
+		uart2m0_xfer: uart2m0-xfer {
+			rockchip,pins =
+				/* uart2_rx_m0 */
+				<0 RK_PB1 2 &pcfg_pull_up>,
+				/* uart2_tx_m0 */
+				<0 RK_PB0 2 &pcfg_pull_up>;
+		};
+
+		/omit-if-no-ref/
+		uart2m0_ctsn: uart2m0-ctsn {
+			rockchip,pins =
+				/* uart2m0_ctsn */
+				<0 RK_PB3 5 &pcfg_pull_none>;
+		};
+		/omit-if-no-ref/
+		uart2m0_rtsn: uart2m0-rtsn {
+			rockchip,pins =
+				/* uart2m0_rtsn */
+				<0 RK_PB2 5 &pcfg_pull_none>;
+		};
+
+		/omit-if-no-ref/
+		uart2m1_xfer: uart2m1-xfer {
+			rockchip,pins =
+				/* uart2_rx_m1 */
+				<2 RK_PB1 1 &pcfg_pull_up>,
+				/* uart2_tx_m1 */
+				<2 RK_PB0 1 &pcfg_pull_up>;
+		};
+
+		/omit-if-no-ref/
+		uart2m1_ctsn: uart2m1-ctsn {
+			rockchip,pins =
+				/* uart2m1_ctsn */
+				<2 RK_PB3 1 &pcfg_pull_none>;
+		};
+		/omit-if-no-ref/
+		uart2m1_rtsn: uart2m1-rtsn {
+			rockchip,pins =
+				/* uart2m1_rtsn */
+				<2 RK_PB2 1 &pcfg_pull_none>;
+		};
+
+		/omit-if-no-ref/
+		uart2m2_xfer: uart2m2-xfer {
+			rockchip,pins =
+				/* uart2_rx_m2 */
+				<1 RK_PB6 3 &pcfg_pull_up>,
+				/* uart2_tx_m2 */
+				<1 RK_PB5 3 &pcfg_pull_up>;
+		};
+
+		/omit-if-no-ref/
+		uart2m2_ctsn: uart2m2-ctsn {
+			rockchip,pins =
+				/* uart2m2_ctsn */
+				<1 RK_PC0 3 &pcfg_pull_none>;
+		};
+		/omit-if-no-ref/
+		uart2m2_rtsn: uart2m2-rtsn {
+			rockchip,pins =
+				/* uart2m2_rtsn */
+				<1 RK_PB7 3 &pcfg_pull_none>;
+		};
+	};
+};
diff --git a/arch/arm/dts/rv1103b.dtsi b/arch/arm/dts/rv1103b.dtsi
new file mode 100644
index 00000000000..39f78e0733c
--- /dev/null
+++ b/arch/arm/dts/rv1103b.dtsi
@@ -0,0 +1,239 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2026 Rockchip Electronics Co., Ltd.
+ */
+
+#include <dt-bindings/clock/rockchip,rv1103b-cru.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/pinctrl/rockchip.h>
+#include <dt-bindings/soc/rockchip,boot-mode.h>
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	compatible = "rockchip,rv1103b";
+
+	interrupt-parent = <&gic>;
+
+	arm-pmu {
+		compatible = "arm,cortex-a7-pmu";
+		interrupts = <GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-affinity = <&cpu0>;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu0: cpu@0 {
+			compatible = "arm,cortex-a7";
+			reg = <0x0>;
+			clocks = <&cru ARMCLK>;
+			device_type = "cpu";
+		};
+	};
+
+	timer {
+		compatible = "arm,armv7-timer";
+		clock-frequency = <24000000>;
+		interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_HIGH)>,
+			     <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_HIGH)>;
+	};
+
+	xin24m: oscillator-24m {
+		compatible = "fixed-clock";
+		clock-frequency = <24000000>;
+		clock-output-names = "xin24m";
+		#clock-cells = <0>;
+	};
+
+	pinctrl: pinctrl {
+		compatible = "rockchip,rv1103b-pinctrl";
+		rockchip,grf = <&ioc>;
+		ranges;
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		gpio0: gpio@20520000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0x20520000 0x200>;
+			clocks = <&cru PCLK_PMU_GPIO0>, <&cru DBCLK_PMU_GPIO0>;
+			gpio-controller;
+			interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-controller;
+			#gpio-cells = <2>;
+			#interrupt-cells = <2>;
+		};
+
+		gpio1: gpio@20d80000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0x20d80000 0x200>;
+			clocks = <&cru PCLK_GPIO1>, <&cru DBCLK_GPIO1>;
+			gpio-controller;
+			interrupts = <GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-controller;
+			#gpio-cells = <2>;
+			#interrupt-cells = <2>;
+		};
+
+		gpio2: gpio@20840000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0x20840000 0x200>;
+			clocks = <&cru PCLK_GPIO2>, <&cru DBCLK_GPIO2>;
+			gpio-controller;
+			interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-controller;
+			#gpio-cells = <2>;
+			#interrupt-cells = <2>;
+		};
+	};
+
+	soc {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		cru: clock-controller@20000000 {
+			compatible = "rockchip,rv1103b-cru";
+			reg = <0x20000000 0x81000>;
+			#clock-cells = <1>;
+			#reset-cells = <1>;
+		};
+
+		pmu_grf: syscon@20160000 {
+			compatible = "rockchip,rv1103b-pmu-grf", "syscon", "simple-mfd";
+			reg = <0x20160000 0x1000>;
+
+			reboot_mode: reboot-mode {
+				compatible = "syscon-reboot-mode";
+				offset = <0x200>;
+				mode-normal = <BOOT_NORMAL>;
+				mode-recovery = <BOOT_RECOVERY>;
+				mode-bootloader = <BOOT_FASTBOOT>;
+				mode-loader = <BOOT_BL_DOWNLOAD>;
+			};
+		};
+
+		ioc: syscon@20170000 {
+			compatible = "rockchip,rv1103b-ioc", "syscon";
+			reg = <0x20170000 0x60000>;
+		};
+
+		gic: interrupt-controller@20411000 {
+			compatible = "arm,gic-400";
+			reg = <0x20411000 0x1000>,
+			      <0x20412000 0x2000>,
+			      <0x20414000 0x2000>,
+			      <0x20416000 0x2000>;
+			interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_HIGH)>;
+			interrupt-controller;
+			#interrupt-cells = <3>;
+			#address-cells = <0>;
+		};
+
+		uart0: serial@20540000 {
+			compatible = "rockchip,rv1103b-uart", "snps,dw-apb-uart";
+			reg = <0x20540000 0x100>;
+			clocks = <&cru SCLK_UART0>, <&cru PCLK_UART0>;
+			clock-names = "baudclk", "apb_pclk";
+			interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&uart0m0_xfer>;
+			reg-shift = <2>;
+			reg-io-width = <4>;
+			status = "disabled";
+		};
+
+		sdmmc1: mmc@20650000 {
+			compatible = "rockchip,rv1103b-dw-mshc", "rockchip,rk3576-dw-mshc";
+			reg = <0x20650000 0x4000>;
+			clocks = <&cru HCLK_SDMMC1>, <&cru CCLK_SDMMC1>;
+			clock-names = "biu", "ciu";
+			fifo-depth = <0x100>;
+			interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
+			max-frequency = <150000000>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&sdmmc1_clk &sdmmc1_cmd &sdmmc1_bus4>;
+			status = "disabled";
+		};
+
+		uart1: serial@20870000 {
+			compatible = "rockchip,rv1103b-uart", "snps,dw-apb-uart";
+			reg = <0x20870000 0x100>;
+			clocks = <&cru SCLK_UART1>, <&cru PCLK_UART1>;
+			clock-names = "baudclk", "apb_pclk";
+			interrupts = <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&uart1m0_xfer>;
+			reg-shift = <2>;
+			reg-io-width = <4>;
+			status = "disabled";
+		};
+
+		uart2: serial@20880000 {
+			compatible = "rockchip,rv1103b-uart", "snps,dw-apb-uart";
+			reg = <0x20880000 0x100>;
+			clocks = <&cru SCLK_UART2>, <&cru PCLK_UART2>;
+			clock-names = "baudclk", "apb_pclk";
+			interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&uart2m0_xfer>;
+			reg-shift = <2>;
+			reg-io-width = <4>;
+			status = "disabled";
+		};
+
+		sdmmc0: mmc@20d20000 {
+			compatible = "rockchip,rv1103b-dw-mshc", "rockchip,rk3576-dw-mshc";
+			reg = <0x20d20000 0x4000>;
+			clocks = <&cru HCLK_SDMMC0>, <&cru CCLK_SDMMC0>;
+			clock-names = "biu", "ciu";
+			fifo-depth = <0x100>;
+			interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
+			max-frequency = <150000000>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&sdmmc0_det &sdmmc0_clk &sdmmc0_cmd &sdmmc0_bus4>;
+			status = "disabled";
+		};
+
+		emmc: mmc@20d30000 {
+			compatible = "rockchip,rv1103b-dw-mshc", "rockchip,rk3576-dw-mshc";
+			reg = <0x20d30000 0x4000>;
+			clocks = <&cru HCLK_EMMC>, <&cru CCLK_EMMC>;
+			clock-names = "biu", "ciu";
+			fifo-depth = <0x100>;
+			interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>;
+			max-frequency = <150000000>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_bus4>;
+			status = "disabled";
+		};
+
+		fspi0: spi@20d40000 {
+			compatible = "rockchip,sfc";
+			reg = <0x20d40000 0x4000>;
+			clocks = <&cru SCLK_SFC_2X>, <&cru HCLK_SFC>;
+			clock-names = "clk_sfc", "hclk_sfc";
+			interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&fspi_bus4 &fspi_cs0 &fspi_clk>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		system_sram: sram@210f6000 {
+			compatible = "mmio-sram";
+			reg = <0x210f6000 0x8000>;
+			ranges = <0 0x210f6000 0x8000>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+		};
+	};
+};
+
+#include "rv1103b-pinctrl.dtsi"
diff --git a/include/dt-bindings/clock/rockchip,rv1103b-cru.h b/include/dt-bindings/clock/rockchip,rv1103b-cru.h
new file mode 100644
index 00000000000..35afdee7e96
--- /dev/null
+++ b/include/dt-bindings/clock/rockchip,rv1103b-cru.h
@@ -0,0 +1,220 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */
+/*
+ * Copyright (c) 2024 Rockchip Electronics Co. Ltd.
+ * Author: Elaine Zhang <zhangqing@rock-chips.com>
+ */
+
+#ifndef _DT_BINDINGS_CLK_ROCKCHIP_RV1103B_H
+#define _DT_BINDINGS_CLK_ROCKCHIP_RV1103B_H
+
+#define PLL_GPLL		0
+#define ARMCLK			1
+#define PLL_DPLL		2
+#define XIN_OSC0_HALF		3
+#define CLK_GPLL_DIV24		4
+#define CLK_GPLL_DIV12		5
+#define CLK_GPLL_DIV6		6
+#define CLK_GPLL_DIV4		7
+#define CLK_GPLL_DIV3		8
+#define CLK_GPLL_DIV2P5		9
+#define CLK_GPLL_DIV2		10
+#define CLK_UART0_SRC		11
+#define CLK_UART1_SRC		12
+#define CLK_UART2_SRC		13
+#define CLK_UART0_FRAC		14
+#define CLK_UART1_FRAC		15
+#define CLK_UART2_FRAC		16
+#define CLK_SAI_SRC		17
+#define CLK_SAI_FRAC		18
+#define LSCLK_NPU_SRC		19
+#define CLK_NPU_SRC		20
+#define ACLK_VEPU_SRC		21
+#define CLK_VEPU_SRC		22
+#define ACLK_VI_SRC		23
+#define CLK_ISP_SRC		24
+#define DCLK_VICAP		25
+#define CCLK_EMMC		26
+#define CCLK_SDMMC0		27
+#define SCLK_SFC_2X		28
+#define LSCLK_PERI_SRC		29
+#define ACLK_PERI_SRC		30
+#define HCLK_HPMCU		31
+#define SCLK_UART0		32
+#define SCLK_UART1		33
+#define SCLK_UART2		34
+#define CLK_I2C_PMU		35
+#define CLK_I2C_PERI		36
+#define CLK_SPI0		37
+#define CLK_PWM0_SRC		38
+#define CLK_PWM1		39
+#define CLK_PWM2		40
+#define DCLK_DECOM_SRC		41
+#define CCLK_SDMMC1		42
+#define CLK_CORE_CRYPTO		43
+#define CLK_PKA_CRYPTO		44
+#define CLK_CORE_RGA		45
+#define MCLK_SAI_SRC		46
+#define CLK_FREQ_PWM0_SRC	47
+#define CLK_COUNTER_PWM0_SRC	48
+#define PCLK_TOP_ROOT		49
+#define CLK_REF_MIPI0		50
+#define CLK_MIPI0_OUT2IO	51
+#define CLK_REF_MIPI1		52
+#define CLK_MIPI1_OUT2IO	53
+#define MCLK_SAI_OUT2IO		54
+#define ACLK_NPU_ROOT		55
+#define HCLK_RKNN		56
+#define ACLK_RKNN		57
+#define LSCLK_VEPU_ROOT		58
+#define HCLK_VEPU		59
+#define ACLK_VEPU		60
+#define CLK_CORE_VEPU		61
+#define PCLK_IOC_VCCIO3		62
+#define PCLK_ACODEC		63
+#define PCLK_USBPHY		64
+#define LSCLK_VI_100M		65
+#define LSCLK_VI_ROOT		66
+#define HCLK_ISP		67
+#define ACLK_ISP		68
+#define CLK_CORE_ISP		69
+#define ACLK_VICAP		70
+#define HCLK_VICAP		71
+#define ISP0CLK_VICAP		72
+#define PCLK_CSI2HOST0		73
+#define PCLK_CSI2HOST1		74
+#define HCLK_EMMC		75
+#define HCLK_SFC		76
+#define HCLK_SFC_XIP		77
+#define HCLK_SDMMC0		78
+#define PCLK_CSIPHY		79
+#define PCLK_GPIO1		80
+#define DBCLK_GPIO1		81
+#define PCLK_IOC_VCCIO47	82
+#define LSCLK_DDR_ROOT		83
+#define CLK_TIMER_DDRMON	84
+#define LSCLK_PMU_ROOT		85
+#define PCLK_PMU		86
+#define XIN_RC_DIV		87
+#define CLK_32K			88
+#define PCLK_PMU_GPIO0		89
+#define DBCLK_PMU_GPIO0		90
+#define CLK_DDR_FAIL_SAFE	91
+#define PCLK_PMU_HP_TIMER	92
+#define CLK_PMU_32K_HP_TIMER	93
+#define PCLK_PWM0		94
+#define CLK_PWM0		95
+#define CLK_OSC_PWM0		96
+#define CLK_RC_PWM0		97
+#define CLK_FREQ_PWM0		98
+#define CLK_COUNTER_PWM0	99
+#define PCLK_I2C0		100
+#define CLK_I2C0		101
+#define PCLK_UART0		102
+#define PCLK_IOC_PMUIO0		103
+#define CLK_REFOUT		104
+#define CLK_PREROLL		105
+#define CLK_PREROLL_32K		106
+#define CLK_LPMCU_PMU		107
+#define PCLK_SPI2AHB		108
+#define HCLK_SPI2AHB		109
+#define SCLK_SPI2AHB		110
+#define PCLK_WDT_LPMCU		111
+#define TCLK_WDT_LPMCU		112
+#define HCLK_SFC_PMU1		113
+#define HCLK_SFC_XIP_PMU1	114
+#define SCLK_SFC_2X_PMU1	115
+#define CLK_LPMCU		116
+#define CLK_LPMCU_RTC		117
+#define PCLK_LPMCU_MAILBOX	118
+#define PCLK_IOC_PMUIO1		119
+#define PCLK_CRU_PMU1		120
+#define PCLK_PERI_ROOT		121
+#define PCLK_RTC_ROOT		122
+#define CLK_TIMER_ROOT		123
+#define PCLK_TIMER		124
+#define CLK_TIMER0		125
+#define CLK_TIMER1		126
+#define CLK_TIMER2		127
+#define CLK_TIMER3		128
+#define CLK_TIMER4		129
+#define CLK_TIMER5		130
+#define PCLK_STIMER		131
+#define CLK_STIMER0		132
+#define CLK_STIMER1		133
+#define PCLK_WDT_NS		134
+#define TCLK_WDT_NS		135
+#define PCLK_WDT_S		136
+#define TCLK_WDT_S		137
+#define PCLK_WDT_HPMCU		138
+#define TCLK_WDT_HPMCU		139
+#define PCLK_I2C1		140
+#define CLK_I2C1		141
+#define PCLK_I2C2		142
+#define CLK_I2C2		143
+#define PCLK_I2C3		144
+#define CLK_I2C3		145
+#define PCLK_I2C4		146
+#define CLK_I2C4		147
+#define PCLK_SPI0		148
+#define PCLK_PWM1		149
+#define CLK_OSC_PWM1		150
+#define PCLK_PWM2		151
+#define CLK_OSC_PWM2		152
+#define PCLK_UART2		153
+#define PCLK_UART1		154
+#define ACLK_RKDMA		155
+#define PCLK_TSADC		156
+#define CLK_TSADC		157
+#define CLK_TSADC_TSEN		158
+#define PCLK_SARADC		159
+#define CLK_SARADC		160
+#define PCLK_GPIO2		161
+#define DBCLK_GPIO2		162
+#define PCLK_IOC_VCCIO6		163
+#define ACLK_USBOTG		164
+#define CLK_REF_USBOTG		165
+#define HCLK_SDMMC1		166
+#define HCLK_SAI		167
+#define MCLK_SAI		168
+#define ACLK_CRYPTO		169
+#define HCLK_CRYPTO		170
+#define HCLK_RK_RNG_NS		171
+#define HCLK_RK_RNG_S		172
+#define PCLK_OTPC_NS		173
+#define CLK_OTPC_ROOT_NS	174
+#define CLK_SBPI_OTPC_NS	175
+#define CLK_USER_OTPC_NS	176
+#define PCLK_OTPC_S		177
+#define CLK_OTPC_ROOT_S		178
+#define CLK_SBPI_OTPC_S		179
+#define CLK_USER_OTPC_S		180
+#define CLK_OTPC_ARB		181
+#define PCLK_OTP_MASK		182
+#define HCLK_RGA		183
+#define ACLK_RGA		184
+#define ACLK_MAC		185
+#define PCLK_MAC		186
+#define CLK_MACPHY		187
+#define ACLK_SPINLOCK		188
+#define HCLK_CACHE		189
+#define PCLK_HPMCU_MAILBOX	190
+#define PCLK_HPMCU_INTMUX	191
+#define CLK_HPMCU		192
+#define CLK_HPMCU_RTC		193
+#define DCLK_DECOM		194
+#define ACLK_DECOM		195
+#define PCLK_DECOM		196
+#define ACLK_SYS_SRAM		197
+#define PCLK_DMA2DDR		198
+#define ACLK_DMA2DDR		199
+#define PCLK_DCF		200
+#define ACLK_DCF		201
+#define MCLK_ACODEC_TX		202
+#define SCLK_UART0_SRC		203
+#define SCLK_UART1_SRC		204
+#define SCLK_UART2_SRC		205
+#define XIN_RC_SRC		206
+#define CLK_UTMI_USBOTG		207
+#define CLK_REF_USBPHY		208
+
+#endif // _DT_BINDINGS_CLK_ROCKCHIP_RV1103B_H
-- 
2.43.0


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

* [PATCH v3 02/15] pinctrl: rockchip: Add RV1103B support
  2026-07-07 15:30 [PATCH v3 00/15] rockchip: Add support for the RV1103B, RV1103 and RV1106 Simon Glass
  2026-07-07 15:30 ` [PATCH v3 01/15] ARM: dts: Add the RV1103B devicetree files Simon Glass
@ 2026-07-07 15:31 ` Simon Glass
  2026-07-07 15:31 ` [PATCH v3 03/15] clk: rockchip: Add RV1103B clock driver Simon Glass
                   ` (13 subsequent siblings)
  15 siblings, 0 replies; 21+ messages in thread
From: Simon Glass @ 2026-07-07 15:31 UTC (permalink / raw)
  To: u-boot
  Cc: Fabio Estevam, Jonas Karlman, Ye Zhang, Simon Glass, Jeffy Chen,
	Kever Yang, Philipp Tomsich, Tom Rini, huang lin

From: Ye Zhang <ye.zhang@rock-chips.com>

Add the pinctrl driver for the RV1103B.

Signed-off-by: Ye Zhang <ye.zhang@rock-chips.com>
Signed-off-by: Fabio Estevam <festevam@nabladev.com>
Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3:
- Use regmap_update_bits() in all the remaining places (Jonas)
- Align continuation lines with the open parenthesis (checkpatch)

Changes in v2:
- Use the original author from Rockchip's vendor U-Boot tree
- Use regmap_update_bits()
- Remove unneeded blank lines
- Remove unneeded logging functions

 drivers/pinctrl/rockchip/Makefile          |   1 +
 drivers/pinctrl/rockchip/pinctrl-rv1103b.c | 402 +++++++++++++++++++++
 2 files changed, 403 insertions(+)
 create mode 100644 drivers/pinctrl/rockchip/pinctrl-rv1103b.c

diff --git a/drivers/pinctrl/rockchip/Makefile b/drivers/pinctrl/rockchip/Makefile
index 0405df128df..b7ce6402ea3 100644
--- a/drivers/pinctrl/rockchip/Makefile
+++ b/drivers/pinctrl/rockchip/Makefile
@@ -19,5 +19,6 @@ obj-$(CONFIG_ROCKCHIP_RK3528) += pinctrl-rk3528.o
 obj-$(CONFIG_ROCKCHIP_RK3568) += pinctrl-rk3568.o
 obj-$(CONFIG_ROCKCHIP_RK3576) += pinctrl-rk3576.o
 obj-$(CONFIG_ROCKCHIP_RK3588) += pinctrl-rk3588.o
+obj-$(CONFIG_ROCKCHIP_RV1103B) += pinctrl-rv1103b.o
 obj-$(CONFIG_ROCKCHIP_RV1108) += pinctrl-rv1108.o
 obj-$(CONFIG_ROCKCHIP_RV1126) += pinctrl-rv1126.o
diff --git a/drivers/pinctrl/rockchip/pinctrl-rv1103b.c b/drivers/pinctrl/rockchip/pinctrl-rv1103b.c
new file mode 100644
index 00000000000..4bd74312c8c
--- /dev/null
+++ b/drivers/pinctrl/rockchip/pinctrl-rv1103b.c
@@ -0,0 +1,402 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2024 Rockchip Electronics Co., Ltd
+ */
+
+#include <dm.h>
+#include <log.h>
+#include <dm/pinctrl.h>
+#include <regmap.h>
+#include <syscon.h>
+#include <linux/bitops.h>
+
+#include "pinctrl-rockchip.h"
+
+static int rv1103b_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
+{
+	struct rockchip_pinctrl_priv *priv = bank->priv;
+	int iomux_num = (pin / 8);
+	struct regmap *regmap;
+	u32 data, rmask;
+	int reg, mask;
+	u8 bit;
+
+	if (bank->bank_num == 2 && pin >= 12)
+		return 0;
+
+	regmap = priv->regmap_base;
+	reg = bank->iomux[iomux_num].offset;
+	if ((pin % 8) >= 4)
+		reg += 0x4;
+	bit = (pin % 4) * 4;
+	mask = 0xf;
+
+	if (bank->recalced_mask & BIT(pin))
+		rockchip_get_recalced_mux(bank, pin, &reg, &bit, &mask);
+	data = (mask << (bit + 16));
+	rmask = data | (data >> 16);
+	data |= (mux & mask) << bit;
+
+	return regmap_update_bits(regmap, reg, rmask, data);
+}
+
+#define RV1103_DRV_BITS_PER_PIN		8
+#define RV1103_DRV_PINS_PER_REG		2
+#define RV1103_DRV_GPIO0_A_OFFSET		0x40100
+#define RV1103_DRV_GPIO0_B_OFFSET		0x50110
+#define RV1103_DRV_GPIO1_A01_OFFSET		0x140
+#define RV1103_DRV_GPIO1_A67_OFFSET		0x1014C
+#define RV1103_DRV_GPIO2_OFFSET		0x30180
+#define RV1103_DRV_GPIO2_SARADC_OFFSET		0x3080C
+
+static int rv1103b_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
+					int pin_num, struct regmap **regmap,
+					int *reg, u8 *bit)
+{
+	struct rockchip_pinctrl_priv *priv = bank->priv;
+	int ret = 0;
+
+	*regmap = priv->regmap_base;
+	switch (bank->bank_num) {
+	case 0:
+		if (pin_num < 7)
+			*reg = RV1103_DRV_GPIO0_A_OFFSET;
+		else if (pin_num > 7 && pin_num < 14)
+			*reg = RV1103_DRV_GPIO0_B_OFFSET - 0x10;
+		else
+			ret = -EINVAL;
+		break;
+
+	case 1:
+		if (pin_num < 6)
+			*reg = RV1103_DRV_GPIO1_A01_OFFSET;
+		else if (pin_num >= 6 && pin_num < 23)
+			*reg = RV1103_DRV_GPIO1_A67_OFFSET - 0xc;
+		else if (pin_num >= 24 && pin_num < 30)
+			*reg = RV1103_DRV_GPIO1_A67_OFFSET - 0xc;
+		else
+			ret = -EINVAL;
+		break;
+
+	case 2:
+		if (pin_num < 12) {
+			*reg = RV1103_DRV_GPIO2_OFFSET;
+		} else if (pin_num >= 16) {
+			ret = -EINVAL;
+		} else {
+			*reg = RV1103_DRV_GPIO2_SARADC_OFFSET;
+			*bit = 10;
+
+			return 0;
+		}
+		break;
+
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	if (ret) {
+		printf("unsupported bank_num %d pin_num %d\n", bank->bank_num, pin_num);
+		return ret;
+	}
+
+	*reg += ((pin_num / RV1103_DRV_PINS_PER_REG) * 4);
+	*bit = pin_num % RV1103_DRV_PINS_PER_REG;
+	*bit *= RV1103_DRV_BITS_PER_PIN;
+
+	return 0;
+}
+
+static int rv1103b_set_drive(struct rockchip_pin_bank *bank,
+			     int pin_num, int strength)
+{
+	struct regmap *regmap;
+	int reg, ret, i;
+	u32 data, rmask;
+	u8 bit;
+	int rmask_bits = RV1103_DRV_BITS_PER_PIN;
+
+	ret = rv1103b_calc_drv_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
+	if (ret)
+		return ret;
+
+	for (i = 0, ret = 1; i < strength; i++)
+		ret = (ret << 1) | 1;
+
+	if (bank->bank_num == 2 && pin_num >= 12) {
+		rmask_bits = 2;
+		ret = strength;
+	}
+
+	/* Enable the write to the equivalent lower bits */
+	data = ((1 << rmask_bits) - 1) << (bit + 16);
+	rmask = data | (data >> 16);
+	data |= (ret << bit);
+
+	return regmap_update_bits(regmap, reg, rmask, data);
+}
+
+#define RV1103_PULL_BITS_PER_PIN		2
+#define RV1103_PULL_PINS_PER_REG		8
+#define RV1103_PULL_GPIO0_A_OFFSET		0x40200
+#define RV1103_PULL_GPIO0_B_OFFSET		0x50204
+#define RV1103_PULL_GPIO1_A01_OFFSET		0x210
+#define RV1103_PULL_GPIO1_A67_OFFSET		0x10210
+#define RV1103_PULL_GPIO2_OFFSET		0x30220
+#define RV1103_PULL_GPIO2_SARADC_OFFSET	0x3080C
+
+static int rv1103b_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
+					 int pin_num, struct regmap **regmap,
+					 int *reg, u8 *bit)
+{
+	struct rockchip_pinctrl_priv *priv = bank->priv;
+	int ret = 0;
+
+	*regmap = priv->regmap_base;
+	switch (bank->bank_num) {
+	case 0:
+		if (pin_num < 7)
+			*reg = RV1103_PULL_GPIO0_A_OFFSET;
+		else if (pin_num > 7 && pin_num < 14)
+			*reg = RV1103_PULL_GPIO0_B_OFFSET - 0x4;
+		else
+			ret = -EINVAL;
+		break;
+
+	case 1:
+		if (pin_num < 6)
+			*reg = RV1103_PULL_GPIO1_A01_OFFSET;
+		else if (pin_num >= 6 && pin_num < 23)
+			*reg = RV1103_PULL_GPIO1_A67_OFFSET;
+		else if (pin_num >= 24 && pin_num < 30)
+			*reg = RV1103_PULL_GPIO1_A67_OFFSET;
+		else
+			ret = -EINVAL;
+		break;
+
+	case 2:
+		if (pin_num < 12) {
+			*reg = RV1103_PULL_GPIO2_OFFSET;
+		} else if (pin_num >= 16) {
+			ret = -EINVAL;
+		} else {
+			*reg = RV1103_PULL_GPIO2_SARADC_OFFSET;
+			*bit = 13;
+
+			return 0;
+		}
+		break;
+
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	if (ret) {
+		printf("unsupported bank_num %d pin_num %d\n", bank->bank_num, pin_num);
+		return ret;
+	}
+
+	*reg += ((pin_num / RV1103_PULL_PINS_PER_REG) * 4);
+	*bit = pin_num % RV1103_PULL_PINS_PER_REG;
+	*bit *= RV1103_PULL_BITS_PER_PIN;
+
+	return 0;
+}
+
+static int rv1103b_set_pull(struct rockchip_pin_bank *bank,
+			    int pin_num, int pull)
+{
+	struct regmap *regmap;
+	int reg, ret;
+	u8 bit, type;
+	u32 data, rmask;
+
+	if (pull == PIN_CONFIG_BIAS_PULL_PIN_DEFAULT)
+		return -EINVAL;
+
+	ret = rv1103b_calc_pull_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
+	if (ret)
+		return ret;
+	type = bank->pull_type[pin_num / 8];
+
+	if (bank->bank_num == 2 && pin_num >= 12)
+		type = 1;
+
+	ret = rockchip_translate_pull_value(type, pull);
+	if (ret < 0) {
+		debug("unsupported pull setting %d\n", pull);
+		return ret;
+	}
+
+	/* Enable the write to the equivalent lower bits */
+	data = ((1 << RV1103_PULL_BITS_PER_PIN) - 1) << (bit + 16);
+	rmask = data | (data >> 16);
+	data |= (ret << bit);
+
+	return regmap_update_bits(regmap, reg, rmask, data);
+}
+
+#define RV1103_SMT_BITS_PER_PIN		1
+#define RV1103_SMT_PINS_PER_REG		8
+#define RV1103_SMT_GPIO0_A_OFFSET		0x40400
+#define RV1103_SMT_GPIO0_B_OFFSET		0x50404
+#define RV1103_SMT_GPIO1_A01_OFFSET		0x410
+#define RV1103_SMT_GPIO1_A67_OFFSET		0x10410
+#define RV1103_SMT_GPIO2_OFFSET		0x30420
+#define RV1103_SMT_GPIO2_SARADC_OFFSET		0x3080C
+
+static int rv1103b_calc_schmitt_reg_and_bit(struct rockchip_pin_bank *bank,
+					    int pin_num,
+					    struct regmap **regmap,
+					    int *reg, u8 *bit)
+{
+	struct rockchip_pinctrl_priv *priv = bank->priv;
+	int ret = 0;
+
+	*regmap = priv->regmap_base;
+	switch (bank->bank_num) {
+	case 0:
+		if (pin_num < 7)
+			*reg = RV1103_SMT_GPIO0_A_OFFSET;
+		else if (pin_num > 7 && pin_num < 14)
+			*reg = RV1103_SMT_GPIO0_B_OFFSET - 0x4;
+		else
+			ret = -EINVAL;
+		break;
+
+	case 1:
+		if (pin_num < 6)
+			*reg = RV1103_SMT_GPIO1_A01_OFFSET;
+		else if (pin_num >= 6 && pin_num < 23)
+			*reg = RV1103_SMT_GPIO1_A67_OFFSET;
+		else if (pin_num >= 24 && pin_num < 30)
+			*reg = RV1103_SMT_GPIO1_A67_OFFSET;
+		else
+			ret = -EINVAL;
+		break;
+
+	case 2:
+		if (pin_num < 12) {
+			*reg = RV1103_SMT_GPIO2_OFFSET;
+		} else if (pin_num >= 16) {
+			ret = -EINVAL;
+		} else {
+			*reg = RV1103_SMT_GPIO2_SARADC_OFFSET;
+			*bit = 8;
+
+			return 0;
+		}
+		break;
+
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	if (ret) {
+		printf("unsupported bank_num %d pin_num %d\n", bank->bank_num, pin_num);
+		return ret;
+	}
+
+	*reg += ((pin_num / RV1103_SMT_PINS_PER_REG) * 4);
+	*bit = pin_num % RV1103_SMT_PINS_PER_REG;
+	*bit *= RV1103_SMT_BITS_PER_PIN;
+
+	return 0;
+}
+
+static int rv1103b_set_schmitt(struct rockchip_pin_bank *bank,
+			       int pin_num, int enable)
+{
+	struct regmap *regmap;
+	int reg, ret;
+	u32 data, rmask, mask;
+	u8 bit;
+
+	ret = rv1103b_calc_schmitt_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
+	if (ret)
+		return ret;
+
+	mask = (1 << RV1103_SMT_BITS_PER_PIN) - 1;
+	if (bank->bank_num == 2 && pin_num >= 12) {
+		mask = 0x3;
+		enable = enable ? 0x3 : 0;
+	}
+
+	/* enable the write to the equivalent lower bits */
+	data = mask << (bit + 16);
+	rmask = data | (data >> 16);
+	data |= (enable << bit);
+
+	return regmap_update_bits(regmap, reg, rmask, data);
+}
+
+static struct rockchip_mux_recalced_data rv1103b_mux_recalced_data[] = {
+	{
+		.num = 1,
+		.pin = 6,
+		.reg = 0x10024,
+		.bit = 8,
+		.mask = 0xf
+	}, {
+		.num = 1,
+		.pin = 7,
+		.reg = 0x10024,
+		.bit = 12,
+		.mask = 0xf
+	},
+};
+
+static struct rockchip_pin_bank rv1103b_pin_banks[] = {
+	PIN_BANK_IOMUX_FLAGS_OFFSET(0, 32, "gpio0",
+				    IOMUX_WIDTH_4BIT,
+				    IOMUX_WIDTH_4BIT,
+				    IOMUX_WIDTH_4BIT,
+				    IOMUX_WIDTH_4BIT,
+				    0x40000, 0x50008, 0x50010, 0x50018),
+	PIN_BANK_IOMUX_FLAGS_OFFSET(1, 32, "gpio1",
+				    IOMUX_WIDTH_4BIT,
+				    IOMUX_WIDTH_4BIT,
+				    IOMUX_WIDTH_4BIT,
+				    IOMUX_WIDTH_4BIT,
+				    0x20, 0x10028, 0x10030, 0x10038),
+	PIN_BANK_IOMUX_FLAGS_OFFSET(2, 32, "gpio2",
+				    IOMUX_WIDTH_4BIT,
+				    IOMUX_WIDTH_4BIT,
+				    IOMUX_WIDTH_4BIT,
+				    IOMUX_WIDTH_4BIT,
+				    0x30040, 0x30048, 0x30050, 0x30058),
+};
+
+static const struct rockchip_pin_ctrl rv1103b_pin_ctrl = {
+	.pin_banks		= rv1103b_pin_banks,
+	.nr_banks		= ARRAY_SIZE(rv1103b_pin_banks),
+	.iomux_recalced		= rv1103b_mux_recalced_data,
+	.niomux_recalced	= ARRAY_SIZE(rv1103b_mux_recalced_data),
+	.set_mux		= rv1103b_set_mux,
+	.set_pull		= rv1103b_set_pull,
+	.set_drive		= rv1103b_set_drive,
+	.set_schmitt		= rv1103b_set_schmitt,
+};
+
+static const struct udevice_id rv1103b_pinctrl_ids[] = {
+	{
+		.compatible = "rockchip,rv1103b-pinctrl",
+		.data = (ulong)&rv1103b_pin_ctrl
+	},
+	{ }
+};
+
+U_BOOT_DRIVER(pinctrl_rv1103b) = {
+	.name		= "rockchip_rv1103b_pinctrl",
+	.id		= UCLASS_PINCTRL,
+	.of_match	= rv1103b_pinctrl_ids,
+	.priv_auto	= sizeof(struct rockchip_pinctrl_priv),
+	.ops		= &rockchip_pinctrl_ops,
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
+	.bind		= dm_scan_fdt_dev,
+#endif
+	.probe		= rockchip_pinctrl_probe,
+};
-- 
2.43.0


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

* [PATCH v3 03/15] clk: rockchip: Add RV1103B clock driver
  2026-07-07 15:30 [PATCH v3 00/15] rockchip: Add support for the RV1103B, RV1103 and RV1106 Simon Glass
  2026-07-07 15:30 ` [PATCH v3 01/15] ARM: dts: Add the RV1103B devicetree files Simon Glass
  2026-07-07 15:31 ` [PATCH v3 02/15] pinctrl: rockchip: Add RV1103B support Simon Glass
@ 2026-07-07 15:31 ` Simon Glass
  2026-07-07 15:31 ` [PATCH v3 04/15] tools: rkcommon: Add RV1103B support Simon Glass
                   ` (12 subsequent siblings)
  15 siblings, 0 replies; 21+ messages in thread
From: Simon Glass @ 2026-07-07 15:31 UTC (permalink / raw)
  To: u-boot
  Cc: Fabio Estevam, Jonas Karlman, Elaine Zhang, Simon Glass,
	Finley Xiao, Ilias Apalodimas, Jeffy Chen, Kever Yang,
	Lukasz Majewski, Philipp Tomsich, Tom Rini, huang lin

From: Elaine Zhang <zhangqing@rock-chips.com>

Add the basic clock driver for the RV1103B.

Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com>
Signed-off-by: Fabio Estevam <festevam@nabladev.com>
Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3:
- Use CONFIG_IS_ENABLED() to guard the set_parent operation, matching
  clk_rk3588.c, since plain IS_ENABLED() needs the CONFIG_ prefix

Changes in v2:
- Use the original author from Rockchip's vendor U-Boot tree

 .../include/asm/arch-rockchip/cru_rv1103b.h   |  266 ++++
 .../include/asm/arch-rockchip/grf_rv1103b.h   |   31 +
 drivers/clk/rockchip/Makefile                 |    1 +
 drivers/clk/rockchip/clk_rv1103b.c            | 1068 +++++++++++++++++
 4 files changed, 1366 insertions(+)
 create mode 100644 arch/arm/include/asm/arch-rockchip/cru_rv1103b.h
 create mode 100644 arch/arm/include/asm/arch-rockchip/grf_rv1103b.h
 create mode 100644 drivers/clk/rockchip/clk_rv1103b.c

diff --git a/arch/arm/include/asm/arch-rockchip/cru_rv1103b.h b/arch/arm/include/asm/arch-rockchip/cru_rv1103b.h
new file mode 100644
index 00000000000..fc7aa4dfc0d
--- /dev/null
+++ b/arch/arm/include/asm/arch-rockchip/cru_rv1103b.h
@@ -0,0 +1,266 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2024 Rockchip Electronics Co. Ltd.
+ * Author: Elaine Zhang <zhangqing@rock-chips.com>
+ */
+
+#ifndef _ASM_ARCH_CRU_RV1103B_H
+#define _ASM_ARCH_CRU_RV1103B_H
+
+#define MHz		1000000
+#define KHz		1000
+#define OSC_HZ		(24 * MHz)
+#define RC_OSC_HZ	(125 * MHz)
+
+#define GPLL_HZ		(1188 * MHz)
+
+/* RV1103B pll id */
+enum rv1103b_pll_id {
+	GPLL,
+	PLL_COUNT,
+};
+
+struct rv1103b_clk_info {
+	unsigned long id;
+	char *name;
+	bool is_cru;
+};
+
+struct rv1103b_clk_priv {
+	struct rv1103b_cru *cru;
+	struct rv1103b_grf *grf;
+	ulong gpll_hz;
+	ulong armclk_hz;
+	ulong armclk_enter_hz;
+	ulong armclk_init_hz;
+	bool sync_kernel;
+	bool set_armclk_rate;
+};
+
+struct rv1103b_grf_clk_priv {
+	struct rv1103b_grf *grf;
+};
+
+struct rv1103b_pll {
+	unsigned int con0;
+	unsigned int con1;
+	unsigned int con2;
+	unsigned int con3;
+	unsigned int con4;
+	unsigned int reserved0[3];
+};
+
+struct rv1103b_cru {
+	unsigned int reserved0[192];
+	unsigned int peri_clksel_con[4];
+	unsigned int reserved1[316];
+	unsigned int peri_clkgate_con[12];
+	unsigned int reserved2[116];
+	unsigned int peri_softrst_con[12];
+	unsigned int reserved3[15924];
+	unsigned int vepu_clksel_con[3];
+	unsigned int reserved4[317];
+	unsigned int vepu_clkgate_con[1];
+	unsigned int reserved5[127];
+	unsigned int vepu_softrst_con[1];
+	unsigned int reserved6[15935];
+	unsigned int npu_clksel_con[3];
+	unsigned int reserved7[317];
+	unsigned int npu_clkgate_con[1];
+	unsigned int reserved8[127];
+	unsigned int npu_softrst_con[1];
+	unsigned int reserved9[15935];
+	unsigned int vi_clksel_con[1];
+	unsigned int reserved10[319];
+	unsigned int vi_clkgate_con[3];
+	unsigned int reserved11[125];
+	unsigned int vi_softrst_con[3];
+	unsigned int reserved12[15933];
+	unsigned int core_clksel_con[3];
+	unsigned int reserved13[16381];
+	unsigned int ddr_clksel_con[1];
+	unsigned int reserved14[16207];
+	struct rv1103b_pll pll[2];
+	unsigned int reserved15[128];
+	unsigned int mode;
+	unsigned int reserved16[31];
+	unsigned int clksel_con[42];
+	unsigned int reserved17[278];
+	unsigned int clkgate_con[7];
+	unsigned int reserved18[121];
+	unsigned int softrst_con[1];
+	unsigned int reserved19[127];
+	unsigned int glb_cnt_th;
+	unsigned int glb_rst_st;
+	unsigned int glb_srst_fst;
+	unsigned int glb_srst_snd;
+	unsigned int glb_rst_con;
+	unsigned int reserved20[15803];
+	unsigned int pmu_clksel_con[3];
+	unsigned int reserved21[317];
+	unsigned int pmu_clkgate_con[3];
+	unsigned int reserved22[125];
+	unsigned int pmu_softrst_con[3];
+	unsigned int reserved23[15933];
+	unsigned int pmu1_clksel_con[1];
+	unsigned int reserved24[319];
+	unsigned int pmu1_clkgate_con[2];
+	unsigned int reserved25[126];
+	unsigned int pmu1_softrst_con[2];
+};
+
+check_member(rv1103b_cru, pmu1_softrst_con[1], 0x80a04);
+
+struct pll_rate_table {
+	unsigned long rate;
+	unsigned int fbdiv;
+	unsigned int postdiv1;
+	unsigned int refdiv;
+	unsigned int postdiv2;
+	unsigned int dsmpd;
+	unsigned int frac;
+};
+
+#define RV1103B_TOPCRU_BASE		0x60000
+#define RV1103B_PERICRU_BASE		0x0
+#define RV1103B_VICRU_BASE		0x30000
+#define RV1103B_NPUCRU_BASE		0x20000
+#define RV1103B_CORECRU_BASE		0x40000
+#define RV1103B_VEPUCRU_BASE		0x10000
+#define RV1103B_DDRCRU_BASE		0x50000
+#define RV1103B_SUBDDRCRU_BASE		0x58000
+#define RV1103B_PMUCRU_BASE		0x70000
+#define RV1103B_PMU1CRU_BASE		0x80000
+
+#define RV1103B_CRU_BASE		0x20000000
+
+#define RV1103B_PLL_CON(x)		((x) * 0x4 + RV1103B_TOPCRU_BASE)
+#define RV1103B_MODE_CON		(0x280 + RV1103B_TOPCRU_BASE)
+#define RV1103B_CLKSEL_CON(x)		((x) * 0x4 + 0x300 + RV1103B_TOPCRU_BASE)
+#define RV1103B_SUBDDRMODE_CON		(0x280 + RV1103B_SUBDDRCRU_BASE)
+
+enum {
+	/* CORECRU_CLK_SEL0_CON */
+	CLK_CORE_SRC_SEL_SHIFT		= 1,
+	CLK_CORE_SRC_SEL_MASK		= 0x1 << CLK_CORE_SRC_SEL_SHIFT,
+	CLK_CORE_SRC_SEL_GPLL		= 0,
+	CLK_CORE_SRC_SEL_PVTPLL,
+
+	/* CRU_PERI_CLK_SEL0_CON */
+	CLK_TSADC_TSEN_DIV_SHIFT	= 10,
+	CLK_TSADC_TSEN_DIV_MASK		= 0x1f << CLK_TSADC_TSEN_DIV_SHIFT,
+	CLK_TSADC_DIV_SHIFT		= 4,
+	CLK_TSADC_DIV_MASK		= 0x1f << CLK_TSADC_DIV_SHIFT,
+	PCLK_PERI_DIV_SHIFT		= 0,
+	PCLK_PERI_DIV_MASK		= 0x3 << PCLK_PERI_DIV_SHIFT,
+
+	/* CRU_PERI_CLK_SEL1_CON */
+	CLK_SARADC_DIV_SHIFT		= 0,
+	CLK_SARADC_DIV_MASK		= 0x7 << CLK_SARADC_DIV_SHIFT,
+
+	/* CRU_CLK_SEL5_CON */
+	CLK_UART2_SRC_DIV_SHIFT		= 10,
+	CLK_UART2_SRC_DIV_MASK		= 0x1f << CLK_UART2_SRC_DIV_SHIFT,
+	CLK_UART1_SRC_DIV_SHIFT		= 5,
+	CLK_UART1_SRC_DIV_MASK		= 0x1f << CLK_UART1_SRC_DIV_SHIFT,
+	CLK_UART0_SRC_DIV_SHIFT		= 0,
+	CLK_UART0_SRC_DIV_MASK		= 0x1f << CLK_UART0_SRC_DIV_SHIFT,
+
+	/* CRU_CLK_SEL10_CON */
+	CLK_UART_FRAC_NUMERATOR_SHIFT	= 16,
+	CLK_UART_FRAC_NUMERATOR_MASK	= 0xffff << 16,
+	CLK_UART_FRAC_DENOMINATOR_SHIFT	= 0,
+	CLK_UART_FRAC_DENOMINATOR_MASK	= 0xffff,
+
+	/* CRU_CLK_SEL31_CON */
+	CLK_EMMC_SEL_SHIFT		= 15,
+	CLK_EMMC_SEL_MASK		= 0x1 << CLK_EMMC_SEL_SHIFT,
+	ACLK_PERI_SEL_SHIFT		= 10,
+	ACLK_PERI_SEL_MASK		= 0x3 << ACLK_PERI_SEL_SHIFT,
+	ACLK_PERI_SEL_600M		= 0,
+	ACLK_PERI_SEL_480M,
+	ACLK_PERI_SEL_400M,
+	LSCLK_PERI_SEL_SHIFT		= 9,
+	LSCLK_PERI_SEL_MASK		= 0x1 << LSCLK_PERI_SEL_SHIFT,
+	LSCLK_PERI_SEL_300M		= 0,
+	LSCLK_PERI_SEL_200M,
+	CLK_EMMC_DIV_SHIFT		= 0,
+	CLK_EMMC_DIV_MASK		= 0xff << CLK_EMMC_DIV_SHIFT,
+
+	/* CRU_CLK_SEL32_CON */
+	CLK_SDMMC_SEL_SHIFT		= 15,
+	CLK_SDMMC_SEL_MASK		= 0x1 << CLK_SDMMC_SEL_SHIFT,
+	CLK_MMC_SEL_GPLL		= 0,
+	CLK_MMC_SEL_OSC,
+	CLK_UART2_SEL_SHIFT		= 12,
+	CLK_UART2_SEL_MASK		= 3 << CLK_UART2_SEL_SHIFT,
+	CLK_UART1_SEL_SHIFT		= 10,
+	CLK_UART1_SEL_MASK		= 3 << CLK_UART1_SEL_SHIFT,
+	CLK_UART0_SEL_SHIFT		= 8,
+	CLK_UART0_SEL_MASK		= 3 << CLK_UART0_SEL_SHIFT,
+	CLK_UART_SEL_SRC		= 0,
+	CLK_UART_SEL_FRAC,
+	CLK_UART_SEL_OSC,
+	CLK_SDMMC_DIV_SHIFT		= 0,
+	CLK_SDMMC_DIV_MASK		= 0xff << CLK_SDMMC_DIV_SHIFT,
+
+	/* CRU_CLK_SEL33_CON */
+	CLK_SFC_SEL_SHIFT		= 15,
+	CLK_SFC_SEL_MASK		= 0x1 << CLK_SFC_SEL_SHIFT,
+	CLK_SFC_DIV_SHIFT		= 0,
+	CLK_SFC_DIV_MASK		= 0xff << CLK_SFC_DIV_SHIFT,
+
+	/* CRU_CLK_SEL34_CON */
+	CLK_PWM2_SEL_SHIFT		= 14,
+	CLK_PWM2_SEL_MASK		= 1 << CLK_PWM2_SEL_SHIFT,
+	CLK_PWM1_SEL_SHIFT		= 13,
+	CLK_PWM1_SEL_MASK		= 1 << CLK_PWM1_SEL_SHIFT,
+	CLK_PWM0_SEL_SHIFT		= 12,
+	CLK_PWM0_SEL_MASK		= 1 << CLK_PWM0_SEL_SHIFT,
+	CLK_PWM_SEL_100M		= 0,
+	CLK_PWM_SEL_24M,
+	CLK_SPI0_SEL_SHIFT		= 2,
+	CLK_SPI0_SEL_MASK		= 3 << CLK_SPI0_SEL_SHIFT,
+	CLK_SPI0_SEL_200M		= 0,
+	CLK_SPI0_SEL_100M,
+	CLK_SPI0_SEL_50M,
+	CLK_SPI0_SEL_24M,
+	CLK_I2C1_SEL_SHIFT		= 1,
+	CLK_I2C1_SEL_MASK		= 0x1 << CLK_I2C1_SEL_SHIFT,
+	CLK_I2C0_SEL_SHIFT		= 0,
+	CLK_I2C0_SEL_MASK		= 0x1 << CLK_I2C0_SEL_SHIFT,
+	CLK_I2C_SEL_100M		= 0,
+	CLK_I2C_SEL_24M,
+
+	/* CRU_CLK_SEL35_CON */
+	CLK_PKA_CRYPTO_SEL_SHIFT	= 4,
+	CLK_PKA_CRYPTO_SEL_MASK		= 0x3 << CLK_PKA_CRYPTO_SEL_SHIFT,
+	CLK_CORE_CRYPTO_SEL_SHIFT	= 2,
+	CLK_CORE_CRYPTO_SEL_MASK	= 0x3 << CLK_CORE_CRYPTO_SEL_SHIFT,
+	CLK_CORE_CRYPTO_SEL_300M	= 0,
+	CLK_CORE_CRYPTO_SEL_200M,
+	CLK_CORE_CRYPTO_SEL_100M,
+	DCLK_DECOM_SEL_SHIFT		= 0,
+	DCLK_DECOM_SEL_MASK		= 0x3 << DCLK_DECOM_SEL_SHIFT,
+	DCLK_DECOM_SEL_480M		= 0,
+	DCLK_DECOM_SEL_400M,
+	DCLK_DECOM_SEL_300M,
+
+	/* CRU_CLK_SEL37_CON */
+	CLK_CORE_GPLL_DIV_SHIFT		= 13,
+	CLK_CORE_GPLL_DIV_MASK		= 0x7 << CLK_CORE_GPLL_DIV_SHIFT,
+	CLK_CORE_GPLL_SEL_SHIFT		= 12,
+	CLK_CORE_GPLL_SEL_MASK		= 0x1 << CLK_CORE_GPLL_SEL_SHIFT,
+	CLK_CORE_GPLL_SEL_GPLL		= 0,
+	CLK_CORE_GPLL_SEL_OSC,
+
+	/* CRU_PMU_CLK_SEL2_CON */
+	LSCLK_PMU_SEL_SHIFT		= 4,
+	LSCLK_PMU_SEL_MASK		= 0x1 << LSCLK_PMU_SEL_SHIFT,
+	LSCLK_PMU_SEL_24M		= 0,
+	LSCLK_PMU_SEL_RC_OSC,
+	LSCLK_PMU_DIV_SHIFT		= 0,
+	LSCLK_PMU_DIV_MASK		= 0x3 << LSCLK_PMU_DIV_SHIFT,
+
+};
+#endif
diff --git a/arch/arm/include/asm/arch-rockchip/grf_rv1103b.h b/arch/arm/include/asm/arch-rockchip/grf_rv1103b.h
new file mode 100644
index 00000000000..6bb382a8e07
--- /dev/null
+++ b/arch/arm/include/asm/arch-rockchip/grf_rv1103b.h
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier:     GPL-2.0+ */
+
+/*
+ * (C) Copyright 2024 Rockchip Electronics Co., Ltd.
+ */
+
+#ifndef _ASM_ARCH_GRF_RV1103B_H
+#define _ASM_ARCH_GRF_RV1103B_H
+
+#define VEPU_GRF	0x20100000
+#define NPU_GRF		0x20110000
+#define VI_GRF		0x20120000
+#define CPU_GRF		0x20130000
+#define DDR_GRF		0x20140000
+#define SYS_GRF		0x20150000
+#define PMU_GRF		0x20160000
+
+struct rv1103b_grf {
+	u32 reserved0[(SYS_GRF + 0xA0 - VEPU_GRF) / 4];
+	u32 gmac_con0;				/* address offset: 0x00a0 */
+	u32 gmac_clk_con;			/* address offset: 0x00a4 */
+	u32 gmac_st;				/* address offset: 0x00a8 */
+	u32 reserved00ac;			/* address offset: 0x00ac */
+	u32 macphy_con0;			/* address offset: 0x00b0 */
+	u32 macphy_con1;			/* address offset: 0x00b4 */
+	u32 reserved1[(PMU_GRF + 0x10000 - (SYS_GRF + 0xB4)) / 4];
+};
+
+check_member(rv1103b_grf, macphy_con1, SYS_GRF + 0xB4 - VEPU_GRF);
+
+#endif /*  _ASM_ARCH_GRF_RV1103B_H  */
diff --git a/drivers/clk/rockchip/Makefile b/drivers/clk/rockchip/Makefile
index 07525c36432..de2635b7475 100644
--- a/drivers/clk/rockchip/Makefile
+++ b/drivers/clk/rockchip/Makefile
@@ -20,5 +20,6 @@ obj-$(CONFIG_ROCKCHIP_RK3528) += clk_rk3528.o
 obj-$(CONFIG_ROCKCHIP_RK3568) += clk_rk3568.o
 obj-$(CONFIG_ROCKCHIP_RK3576) += clk_rk3576.o
 obj-$(CONFIG_ROCKCHIP_RK3588) += clk_rk3588.o
+obj-$(CONFIG_ROCKCHIP_RV1103B) += clk_rv1103b.o
 obj-$(CONFIG_ROCKCHIP_RV1108) += clk_rv1108.o
 obj-$(CONFIG_ROCKCHIP_RV1126) += clk_rv1126.o
diff --git a/drivers/clk/rockchip/clk_rv1103b.c b/drivers/clk/rockchip/clk_rv1103b.c
new file mode 100644
index 00000000000..c94a6ebb3dd
--- /dev/null
+++ b/drivers/clk/rockchip/clk_rv1103b.c
@@ -0,0 +1,1068 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2024 Rockchip Electronics Co., Ltd
+ * Author: Elaine Zhang <zhangqing@rock-chips.com>
+ */
+
+#include <bitfield.h>
+#include <clk-uclass.h>
+#include <dm.h>
+#include <asm/arch-rockchip/hardware.h>
+#include <asm/io.h>
+#include <dm/lists.h>
+#include <dt-bindings/clock/rockchip,rv1103b-cru.h>
+
+#include <clk.h>
+#include <log.h>
+#include <malloc.h>
+#include <asm/global_data.h>
+#include <asm/arch-rockchip/clock.h>
+#include <asm/arch-rockchip/cru_rv1103b.h>
+#include <asm/arch-rockchip/hardware.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
+#include <linux/delay.h>
+#include <linux/stringify.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define DIV_TO_RATE(input_rate, div)	((input_rate) / ((div) + 1))
+
+#ifndef BITS_WITH_WMASK
+#define BITS_WITH_WMASK(bits, msk, shift) \
+	((bits) << (shift)) | ((msk) << ((shift) + 16))
+#endif
+
+static struct rockchip_pll_rate_table rv1103b_pll_rates[] = {
+	/* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */
+	RK3036_PLL_RATE(1188000000, 1, 99, 2, 1, 1, 0),
+	RK3036_PLL_RATE(594000000, 1, 99, 4, 1, 1, 0),
+	{ /* sentinel */ },
+};
+
+static struct rockchip_pll_clock rv1103b_pll_clks[] = {
+	[GPLL] = PLL(pll_rk3328, PLL_GPLL, RV1103B_PLL_CON(24),
+		     RV1103B_MODE_CON, 0, 10, 0, rv1103b_pll_rates),
+};
+
+static ulong rv1103b_peri_get_clk(struct rv1103b_clk_priv *priv, ulong clk_id)
+{
+	struct rv1103b_cru *cru = priv->cru;
+	u32 con, sel, div, rate, prate;
+
+	switch (clk_id) {
+	case ACLK_PERI_SRC:
+		con = readl(&cru->clksel_con[31]);
+		sel = (con & ACLK_PERI_SEL_MASK) >> ACLK_PERI_SEL_SHIFT;
+		if (sel == ACLK_PERI_SEL_600M)
+			rate = 600 * MHz;
+		else if (sel == ACLK_PERI_SEL_480M)
+			rate = 480 * MHz;
+		else
+			rate = 400 * MHz;
+		break;
+	case LSCLK_PERI_SRC:
+		con = readl(&cru->clksel_con[31]);
+		sel = (con & LSCLK_PERI_SEL_MASK) >> LSCLK_PERI_SEL_SHIFT;
+		if (sel == LSCLK_PERI_SEL_300M)
+			rate = 300 * MHz;
+		else
+			rate = 200 * MHz;
+		break;
+	case PCLK_PERI_ROOT:
+		con = readl(&cru->peri_clksel_con[0]);
+		div = (con & PCLK_PERI_DIV_MASK) >> PCLK_PERI_DIV_SHIFT;
+		rate = DIV_TO_RATE(rv1103b_peri_get_clk(priv, LSCLK_PERI_SRC),
+				   div);
+		break;
+	case PCLK_TOP_ROOT:
+		rate = DIV_TO_RATE(priv->gpll_hz, 11);
+		break;
+	case LSCLK_PMU_ROOT:
+	case PCLK_PMU:
+		con = readl(&cru->pmu_clksel_con[2]);
+		sel = (con & LSCLK_PMU_SEL_MASK) >> LSCLK_PMU_SEL_SHIFT;
+		div = (con & LSCLK_PMU_DIV_MASK) >> LSCLK_PMU_DIV_SHIFT;
+		if (sel == LSCLK_PMU_SEL_24M)
+			prate = OSC_HZ;
+		else
+			prate = RC_OSC_HZ;
+		rate = DIV_TO_RATE(prate, div);
+		break;
+	default:
+		return -ENOENT;
+	}
+
+	return rate;
+}
+
+static ulong rv1103b_peri_set_clk(struct rv1103b_clk_priv *priv,
+				  ulong clk_id, ulong rate)
+{
+	struct rv1103b_cru *cru = priv->cru;
+	int src_clk, div;
+
+	switch (clk_id) {
+	case ACLK_PERI_SRC:
+		if (rate >= 594 * MHz)
+			src_clk = ACLK_PERI_SEL_600M;
+		else if (rate >= 480 * MHz)
+			src_clk = ACLK_PERI_SEL_480M;
+		else
+			src_clk = ACLK_PERI_SEL_400M;
+		rk_clrsetreg(&cru->clksel_con[31],
+			     ACLK_PERI_SEL_MASK,
+			     src_clk << ACLK_PERI_SEL_SHIFT);
+		break;
+	case LSCLK_PERI_SRC:
+		if (rate >= 297 * MHz)
+			src_clk = LSCLK_PERI_SEL_300M;
+		else
+			src_clk = LSCLK_PERI_SEL_200M;
+		rk_clrsetreg(&cru->clksel_con[31],
+			     LSCLK_PERI_SEL_MASK,
+			     src_clk << LSCLK_PERI_SEL_SHIFT);
+		break;
+	case PCLK_PERI_ROOT:
+		div = DIV_ROUND_UP(rv1103b_peri_get_clk(priv, LSCLK_PERI_SRC),
+				   rate);
+		rk_clrsetreg(&cru->peri_clksel_con[0],
+			     PCLK_PERI_DIV_MASK,
+			     (div - 1) << PCLK_PERI_DIV_SHIFT);
+		break;
+	case PCLK_TOP_ROOT:
+		break;
+	case LSCLK_PMU_ROOT:
+	case PCLK_PMU:
+		if (!(OSC_HZ % rate)) {
+			src_clk = LSCLK_PMU_SEL_24M;
+			div = DIV_ROUND_UP(OSC_HZ, rate);
+		} else {
+			src_clk = LSCLK_PMU_SEL_RC_OSC;
+			div = DIV_ROUND_UP(RC_OSC_HZ, rate);
+		}
+		rk_clrsetreg(&cru->pmu_clksel_con[2],
+			     LSCLK_PMU_SEL_MASK | LSCLK_PMU_DIV_MASK,
+			     (src_clk << LSCLK_PMU_SEL_SHIFT) |
+			     ((div - 1) << LSCLK_PMU_DIV_SHIFT));
+		break;
+	default:
+		printf("do not support this permid freq\n");
+		return -EINVAL;
+	}
+
+	return rv1103b_peri_get_clk(priv, clk_id);
+}
+
+static ulong rv1103b_i2c_get_clk(struct rv1103b_clk_priv *priv, ulong clk_id)
+{
+	struct rv1103b_cru *cru = priv->cru;
+	u32 sel, con;
+	ulong rate;
+
+	switch (clk_id) {
+	case CLK_I2C1:
+	case CLK_I2C2:
+	case CLK_I2C3:
+	case CLK_I2C4:
+	case CLK_I2C_PERI:
+		con = readl(&cru->clksel_con[34]);
+		sel = (con & CLK_I2C1_SEL_MASK) >> CLK_I2C1_SEL_SHIFT;
+		break;
+	case CLK_I2C0:
+	case CLK_I2C_PMU:
+		con = readl(&cru->clksel_con[34]);
+		sel = (con & CLK_I2C0_SEL_MASK) >> CLK_I2C0_SEL_SHIFT;
+		break;
+	default:
+		return -ENOENT;
+	}
+
+	if (sel == CLK_I2C_SEL_100M)
+		rate = 100 * MHz;
+	else
+		rate = OSC_HZ;
+
+	return rate;
+}
+
+static ulong rv1103b_crypto_get_clk(struct rv1103b_clk_priv *priv, ulong clk_id)
+{
+	struct rv1103b_cru *cru = priv->cru;
+	u32 sel, con, rate;
+
+	switch (clk_id) {
+	case ACLK_CRYPTO:
+	case HCLK_CRYPTO:
+	case HCLK_RK_RNG_NS:
+	case HCLK_RK_RNG_S:
+		return rv1103b_peri_get_clk(priv, LSCLK_PERI_SRC);
+	case CLK_CORE_CRYPTO:
+		con = readl(&cru->clksel_con[35]);
+		sel = (con & CLK_CORE_CRYPTO_SEL_MASK) >>
+		      CLK_CORE_CRYPTO_SEL_SHIFT;
+		break;
+	case CLK_PKA_CRYPTO:
+		con = readl(&cru->clksel_con[35]);
+		sel = (con & CLK_PKA_CRYPTO_SEL_MASK) >>
+		      CLK_PKA_CRYPTO_SEL_SHIFT;
+		break;
+	default:
+		return -ENOENT;
+	}
+	if (sel == CLK_CORE_CRYPTO_SEL_300M)
+		rate = 300 * MHz;
+	else if (sel == CLK_CORE_CRYPTO_SEL_200M)
+		rate = 200 * MHz;
+	else
+		rate = 100 * MHz;
+
+	return rate;
+}
+
+static ulong rv1103b_crypto_set_clk(struct rv1103b_clk_priv *priv,
+				    ulong clk_id, ulong rate)
+{
+	struct rv1103b_cru *cru = priv->cru;
+	u32 sel;
+
+	if (rate >= 297 * MHz)
+		sel = CLK_CORE_CRYPTO_SEL_300M;
+	else if (rate >= 198 * MHz)
+		sel = CLK_CORE_CRYPTO_SEL_200M;
+	else
+		sel = CLK_CORE_CRYPTO_SEL_100M;
+
+	switch (clk_id) {
+	case ACLK_CRYPTO:
+	case HCLK_CRYPTO:
+	case HCLK_RK_RNG_NS:
+	case HCLK_RK_RNG_S:
+		rv1103b_peri_set_clk(priv, LSCLK_PERI_SRC, rate);
+	case CLK_CORE_CRYPTO:
+		rk_clrsetreg(&cru->clksel_con[35],
+			     CLK_CORE_CRYPTO_SEL_MASK,
+			     (sel << CLK_CORE_CRYPTO_SEL_SHIFT));
+		break;
+	case CLK_PKA_CRYPTO:
+		rk_clrsetreg(&cru->clksel_con[35],
+			     CLK_PKA_CRYPTO_SEL_MASK,
+			     (sel << CLK_PKA_CRYPTO_SEL_SHIFT));
+		break;
+	default:
+		return -ENOENT;
+	}
+	return rv1103b_crypto_get_clk(priv, clk_id);
+}
+
+static ulong rv1103b_mmc_get_clk(struct rv1103b_clk_priv *priv, ulong clk_id)
+{
+	struct rv1103b_cru *cru = priv->cru;
+	u32 div, sel, con, prate;
+
+	switch (clk_id) {
+	case CCLK_SDMMC1:
+	case HCLK_SDMMC1:
+		con = readl(&cru->clksel_con[36]);
+		sel = (con & CLK_SDMMC_SEL_MASK) >>
+		      CLK_SDMMC_SEL_SHIFT;
+		div = (con & CLK_SDMMC_DIV_MASK) >>
+		      CLK_SDMMC_DIV_SHIFT;
+		if (sel == CLK_MMC_SEL_GPLL)
+			prate = priv->gpll_hz;
+		else
+			prate = OSC_HZ;
+		return DIV_TO_RATE(prate, div);
+	case CCLK_SDMMC0:
+	case HCLK_SDMMC0:
+		con = readl(&cru->clksel_con[32]);
+		sel = (con & CLK_SDMMC_SEL_MASK) >>
+		      CLK_SDMMC_SEL_SHIFT;
+		div = (con & CLK_SDMMC_DIV_MASK) >>
+		      CLK_SDMMC_DIV_SHIFT;
+		if (sel == CLK_MMC_SEL_GPLL)
+			prate = priv->gpll_hz;
+		else
+			prate = OSC_HZ;
+		return DIV_TO_RATE(prate, div);
+	case CCLK_EMMC:
+	case HCLK_EMMC:
+		con = readl(&cru->clksel_con[31]);
+		sel = (con & CLK_EMMC_SEL_MASK) >>
+		      CLK_EMMC_SEL_SHIFT;
+		div = (con & CLK_EMMC_DIV_MASK) >>
+		      CLK_EMMC_DIV_SHIFT;
+		if (sel == CLK_MMC_SEL_GPLL)
+			prate = priv->gpll_hz;
+		else
+			prate = OSC_HZ;
+		return DIV_TO_RATE(prate, div);
+	case SCLK_SFC_2X:
+	case HCLK_SFC:
+		con = readl(&cru->clksel_con[33]);
+		sel = (con & CLK_SFC_SEL_MASK) >>
+		      CLK_SFC_SEL_SHIFT;
+		div = (con & CLK_SFC_DIV_MASK) >>
+		      CLK_SFC_DIV_SHIFT;
+		if (sel == CLK_MMC_SEL_GPLL)
+			prate = priv->gpll_hz;
+		else
+			prate = OSC_HZ;
+		return DIV_TO_RATE(prate, div);
+	default:
+		return -ENOENT;
+	}
+}
+
+static ulong rv1103b_mmc_set_clk(struct rv1103b_clk_priv *priv,
+				 ulong clk_id, ulong rate)
+{
+	struct rv1103b_cru *cru = priv->cru;
+	u32 sel, src_clk_div;
+	ulong prate = 0;
+
+	if ((OSC_HZ % rate) == 0) {
+		sel = CLK_MMC_SEL_OSC;
+		prate = OSC_HZ;
+	} else {
+		sel = CLK_MMC_SEL_GPLL;
+		prate = priv->gpll_hz;
+	}
+	src_clk_div = DIV_ROUND_UP(prate, rate);
+
+	switch (clk_id) {
+	case CCLK_SDMMC1:
+	case HCLK_SDMMC1:
+		src_clk_div = DIV_ROUND_UP(prate, rate);
+		rk_clrsetreg(&cru->clksel_con[36],
+			     CLK_SDMMC_SEL_MASK |
+			     CLK_SDMMC_DIV_MASK,
+			     (sel << CLK_SDMMC_SEL_SHIFT) |
+			     ((src_clk_div - 1) <<
+			      CLK_SDMMC_DIV_SHIFT));
+		break;
+	case CCLK_SDMMC0:
+	case HCLK_SDMMC0:
+		src_clk_div = DIV_ROUND_UP(prate, rate);
+		rk_clrsetreg(&cru->clksel_con[32],
+			     CLK_SDMMC_SEL_MASK |
+			     CLK_SDMMC_DIV_MASK,
+			     (sel << CLK_SDMMC_SEL_SHIFT) |
+			     ((src_clk_div - 1) <<
+			      CLK_SDMMC_DIV_SHIFT));
+		break;
+	case CCLK_EMMC:
+	case HCLK_EMMC:
+		src_clk_div = DIV_ROUND_UP(prate, rate);
+		rk_clrsetreg(&cru->clksel_con[31],
+			     CLK_EMMC_SEL_MASK |
+			     CLK_EMMC_DIV_MASK,
+			     (sel << CLK_EMMC_SEL_SHIFT) |
+			     ((src_clk_div - 1) <<
+			      CLK_EMMC_DIV_SHIFT));
+		break;
+	case SCLK_SFC_2X:
+	case HCLK_SFC:
+		src_clk_div = DIV_ROUND_UP(prate, rate);
+		rk_clrsetreg(&cru->clksel_con[33],
+			     CLK_SFC_SEL_MASK |
+			     CLK_SFC_DIV_MASK,
+			     (sel << CLK_SFC_SEL_SHIFT) |
+			     ((src_clk_div - 1) <<
+			      CLK_SFC_DIV_SHIFT));
+		break;
+	default:
+		return -ENOENT;
+	}
+	return rv1103b_mmc_get_clk(priv, clk_id);
+}
+
+static ulong rv1103b_i2c_set_clk(struct rv1103b_clk_priv *priv, ulong clk_id,
+				 ulong rate)
+{
+	struct rv1103b_cru *cru = priv->cru;
+	int src_clk;
+
+	if (rate == OSC_HZ)
+		src_clk = CLK_I2C_SEL_24M;
+	else
+		src_clk = CLK_I2C_SEL_100M;
+
+	switch (clk_id) {
+	case CLK_I2C1:
+	case CLK_I2C2:
+	case CLK_I2C3:
+	case CLK_I2C4:
+	case CLK_I2C_PERI:
+		rk_clrsetreg(&cru->clksel_con[34], CLK_I2C1_SEL_MASK,
+			     src_clk << CLK_I2C1_SEL_SHIFT);
+		break;
+	case CLK_I2C0:
+	case CLK_I2C_PMU:
+		rk_clrsetreg(&cru->clksel_con[34], CLK_I2C0_SEL_MASK,
+			     src_clk << CLK_I2C0_SEL_SHIFT);
+		break;
+	default:
+		return -ENOENT;
+	}
+	return rv1103b_i2c_get_clk(priv, clk_id);
+}
+
+static ulong rv1103b_spi_get_clk(struct rv1103b_clk_priv *priv, ulong clk_id)
+{
+	struct rv1103b_cru *cru = priv->cru;
+	u32 sel, con, rate;
+
+	switch (clk_id) {
+	case CLK_SPI0:
+		con = readl(&cru->clksel_con[34]);
+		sel = (con & CLK_SPI0_SEL_MASK) >> CLK_SPI0_SEL_SHIFT;
+		break;
+	default:
+		return -ENOENT;
+	}
+	if (sel == CLK_SPI0_SEL_200M)
+		rate = 200 * MHz;
+	else if (sel == CLK_SPI0_SEL_100M)
+		rate = 100 * MHz;
+	else if (sel == CLK_SPI0_SEL_50M)
+		rate = 50 * MHz;
+	else
+		rate = OSC_HZ;
+
+	return rate;
+}
+
+static ulong rv1103b_spi_set_clk(struct rv1103b_clk_priv *priv,
+				 ulong clk_id, ulong rate)
+{
+	struct rv1103b_cru *cru = priv->cru;
+	int src_clk;
+
+	if (rate >= 198 * MHz)
+		src_clk = CLK_SPI0_SEL_200M;
+	else if (rate >= 99 * MHz)
+		src_clk = CLK_SPI0_SEL_100M;
+	else if (rate >= 48 * MHz)
+		src_clk = CLK_SPI0_SEL_50M;
+	else
+		src_clk = CLK_SPI0_SEL_24M;
+
+	switch (clk_id) {
+	case CLK_SPI0:
+		rk_clrsetreg(&cru->clksel_con[34], CLK_SPI0_SEL_MASK,
+			     src_clk << CLK_SPI0_SEL_SHIFT);
+		break;
+	default:
+		return -ENOENT;
+	}
+
+	return rv1103b_spi_get_clk(priv, clk_id);
+}
+
+static ulong rv1103b_pwm_get_clk(struct rv1103b_clk_priv *priv, ulong clk_id)
+{
+	struct rv1103b_cru *cru = priv->cru;
+	u32 sel, con;
+
+	switch (clk_id) {
+	case CLK_PWM0:
+	case CLK_PWM0_SRC:
+		con = readl(&cru->clksel_con[34]);
+		sel = (con & CLK_PWM0_SEL_MASK) >> CLK_PWM0_SEL_SHIFT;
+		break;
+	case CLK_PWM1:
+		con = readl(&cru->clksel_con[34]);
+		sel = (con & CLK_PWM1_SEL_MASK) >> CLK_PWM1_SEL_SHIFT;
+		break;
+	case CLK_PWM2:
+		con = readl(&cru->clksel_con[34]);
+		sel = (con & CLK_PWM2_SEL_MASK) >> CLK_PWM2_SEL_SHIFT;
+		break;
+	default:
+		return -ENOENT;
+	}
+
+	switch (sel) {
+	case CLK_PWM_SEL_100M:
+		return 100 * MHz;
+	case CLK_PWM_SEL_24M:
+		return OSC_HZ;
+	default:
+		return -ENOENT;
+	}
+}
+
+static ulong rv1103b_pwm_set_clk(struct rv1103b_clk_priv *priv,
+				 ulong clk_id, ulong rate)
+{
+	struct rv1103b_cru *cru = priv->cru;
+	int src_clk;
+
+	if (rate >= 99 * MHz)
+		src_clk = CLK_PWM_SEL_100M;
+	else
+		src_clk = CLK_PWM_SEL_24M;
+
+	switch (clk_id) {
+	case CLK_PWM0:
+	case CLK_PWM0_SRC:
+		rk_clrsetreg(&cru->clksel_con[34],
+			     CLK_PWM0_SEL_MASK,
+			     src_clk << CLK_PWM0_SEL_SHIFT);
+		break;
+	case CLK_PWM1:
+		rk_clrsetreg(&cru->clksel_con[34],
+			     CLK_PWM1_SEL_MASK,
+			     src_clk << CLK_PWM1_SEL_SHIFT);
+		break;
+	case CLK_PWM2:
+		rk_clrsetreg(&cru->clksel_con[34],
+			     CLK_PWM2_SEL_MASK,
+			     src_clk << CLK_PWM2_SEL_SHIFT);
+		break;
+	default:
+		return -ENOENT;
+	}
+
+	return rv1103b_pwm_get_clk(priv, clk_id);
+}
+
+static ulong rv1103b_adc_get_clk(struct rv1103b_clk_priv *priv, ulong clk_id)
+{
+	struct rv1103b_cru *cru = priv->cru;
+	u32 div, con;
+
+	switch (clk_id) {
+	case CLK_SARADC:
+		con = readl(&cru->peri_clksel_con[1]);
+		div = (con & CLK_SARADC_DIV_MASK) >>
+		      CLK_SARADC_DIV_SHIFT;
+		return DIV_TO_RATE(OSC_HZ, div);
+	case CLK_TSADC_TSEN:
+		con = readl(&cru->peri_clksel_con[0]);
+		div = (con & CLK_TSADC_TSEN_DIV_MASK) >>
+		      CLK_TSADC_TSEN_DIV_SHIFT;
+		return DIV_TO_RATE(OSC_HZ, div);
+	case CLK_TSADC:
+		con = readl(&cru->peri_clksel_con[0]);
+		div = (con & CLK_TSADC_DIV_MASK) >> CLK_TSADC_DIV_SHIFT;
+		return DIV_TO_RATE(OSC_HZ, div);
+	default:
+		return -ENOENT;
+	}
+}
+
+static ulong rv1103b_adc_set_clk(struct rv1103b_clk_priv *priv,
+				 ulong clk_id, ulong rate)
+{
+	struct rv1103b_cru *cru = priv->cru;
+	int src_clk_div;
+
+	src_clk_div = DIV_ROUND_UP(OSC_HZ, rate);
+
+	switch (clk_id) {
+	case CLK_SARADC:
+		assert(src_clk_div - 1 <= 7);
+		rk_clrsetreg(&cru->peri_clksel_con[1],
+			     CLK_SARADC_DIV_MASK,
+			     (src_clk_div - 1) <<
+			     CLK_SARADC_DIV_SHIFT);
+		break;
+	case CLK_TSADC_TSEN:
+		assert(src_clk_div - 1 <= 32);
+		rk_clrsetreg(&cru->peri_clksel_con[0],
+			     CLK_TSADC_TSEN_DIV_MASK,
+			     (src_clk_div - 1) <<
+			     CLK_TSADC_TSEN_DIV_SHIFT);
+		break;
+	case CLK_TSADC:
+		assert(src_clk_div - 1 <= 32);
+		rk_clrsetreg(&cru->peri_clksel_con[0],
+			     CLK_TSADC_DIV_MASK,
+			     (src_clk_div - 1) <<
+			     CLK_TSADC_DIV_SHIFT);
+		break;
+	default:
+		return -ENOENT;
+	}
+	return rv1103b_adc_get_clk(priv, clk_id);
+}
+
+/*
+ *
+ * rational_best_approximation(31415, 10000,
+ *		(1 << 8) - 1, (1 << 5) - 1, &n, &d);
+ *
+ * you may look at given_numerator as a fixed point number,
+ * with the fractional part size described in given_denominator.
+ *
+ * for theoretical background, see:
+ * http://en.wikipedia.org/wiki/Continued_fraction
+ */
+static void rational_best_approximation(unsigned long given_numerator,
+					unsigned long given_denominator,
+					unsigned long max_numerator,
+					unsigned long max_denominator,
+					unsigned long *best_numerator,
+					unsigned long *best_denominator)
+{
+	unsigned long n, d, n0, d0, n1, d1;
+
+	n = given_numerator;
+	d = given_denominator;
+	n0 = 0;
+	d1 = 0;
+	n1 = 1;
+	d0 = 1;
+	for (;;) {
+		unsigned long t, a;
+
+		if (n1 > max_numerator || d1 > max_denominator) {
+			n1 = n0;
+			d1 = d0;
+			break;
+		}
+		if (d == 0)
+			break;
+		t = d;
+		a = n / d;
+		d = n % d;
+		n = t;
+		t = n0 + a * n1;
+		n0 = n1;
+		n1 = t;
+		t = d0 + a * d1;
+		d0 = d1;
+		d1 = t;
+	}
+	*best_numerator = n1;
+	*best_denominator = d1;
+}
+
+static ulong rv1103b_uart_get_rate(struct rv1103b_clk_priv *priv, ulong clk_id)
+{
+	struct rv1103b_cru *cru = priv->cru;
+	u32 reg, con, fracdiv, div, src, p_rate;
+	unsigned long m, n;
+
+	switch (clk_id) {
+	case SCLK_UART0:
+		reg = 10;
+		con = readl(&cru->clksel_con[32]);
+		src = (con & CLK_UART0_SEL_MASK) >> CLK_UART0_SEL_SHIFT;
+		con = readl(&cru->clksel_con[5]);
+		div = (con & CLK_UART0_SRC_DIV_MASK) >> CLK_UART0_SRC_DIV_SHIFT;
+		break;
+	case SCLK_UART1:
+		reg = 11;
+		con = readl(&cru->clksel_con[32]);
+		src = (con & CLK_UART1_SEL_MASK) >> CLK_UART1_SEL_SHIFT;
+		con = readl(&cru->clksel_con[5]);
+		div = (con & CLK_UART1_SRC_DIV_MASK) >> CLK_UART1_SRC_DIV_SHIFT;
+		break;
+	case SCLK_UART2:
+		reg = 12;
+		con = readl(&cru->clksel_con[32]);
+		src = (con & CLK_UART2_SEL_MASK) >> CLK_UART2_SEL_SHIFT;
+		con = readl(&cru->clksel_con[5]);
+		div = (con & CLK_UART2_SRC_DIV_MASK) >> CLK_UART2_SRC_DIV_SHIFT;
+		break;
+	default:
+		return -ENOENT;
+	}
+
+	p_rate = priv->gpll_hz;
+	if (src == CLK_UART_SEL_SRC) {
+		return DIV_TO_RATE(p_rate, div);
+	} else if (src == CLK_UART_SEL_FRAC) {
+		fracdiv = readl(&cru->clksel_con[reg]);
+		n = fracdiv & CLK_UART_FRAC_NUMERATOR_MASK;
+		n >>= CLK_UART_FRAC_NUMERATOR_SHIFT;
+		m = fracdiv & CLK_UART_FRAC_DENOMINATOR_MASK;
+		m >>= CLK_UART_FRAC_DENOMINATOR_SHIFT;
+		return DIV_TO_RATE(p_rate, div) * n / m;
+	} else {
+		return OSC_HZ;
+	}
+}
+
+static ulong rv1103b_uart_set_rate(struct rv1103b_clk_priv *priv,
+				   ulong clk_id, ulong rate)
+{
+	struct rv1103b_cru *cru = priv->cru;
+	u32 reg, uart_src, div;
+	unsigned long m = 0, n = 0, val;
+
+	if (priv->gpll_hz % rate == 0) {
+		uart_src = CLK_UART_SEL_SRC;
+		div = DIV_ROUND_UP(priv->gpll_hz, rate);
+	} else if (rate == OSC_HZ) {
+		uart_src = CLK_UART_SEL_OSC;
+		div = 2;
+	} else {
+		uart_src = CLK_UART_SEL_FRAC;
+		div = 2;
+		rational_best_approximation(rate, priv->gpll_hz / div,
+					    GENMASK(16 - 1, 0),
+					    GENMASK(16 - 1, 0),
+					    &m, &n);
+	}
+
+	switch (clk_id) {
+	case SCLK_UART0:
+		reg = 10;
+		rk_clrsetreg(&cru->clksel_con[5],
+			     CLK_UART0_SRC_DIV_MASK,
+			     div << CLK_UART0_SRC_DIV_SHIFT);
+		rk_clrsetreg(&cru->clksel_con[32],
+			     CLK_UART0_SEL_MASK,
+			     uart_src << CLK_UART0_SEL_SHIFT);
+		break;
+	case SCLK_UART1:
+		reg = 11;
+		rk_clrsetreg(&cru->clksel_con[5],
+			     CLK_UART1_SRC_DIV_MASK,
+			     div << CLK_UART1_SRC_DIV_SHIFT);
+		rk_clrsetreg(&cru->clksel_con[32],
+			     CLK_UART1_SEL_MASK,
+			     uart_src << CLK_UART1_SEL_SHIFT);
+		break;
+	case SCLK_UART2:
+		reg = 12;
+		rk_clrsetreg(&cru->clksel_con[5],
+			     CLK_UART2_SRC_DIV_MASK,
+			     div << CLK_UART2_SRC_DIV_SHIFT);
+		rk_clrsetreg(&cru->clksel_con[32],
+			     CLK_UART2_SEL_MASK,
+			     uart_src << CLK_UART2_SEL_SHIFT);
+		break;
+	default:
+		return -ENOENT;
+	}
+	if (m && n) {
+		val = m << CLK_UART_FRAC_NUMERATOR_SHIFT | n;
+		writel(val, &cru->clksel_con[reg]);
+	}
+
+	return rv1103b_uart_get_rate(priv, clk_id);
+}
+
+static ulong rv1103b_decom_get_clk(struct rv1103b_clk_priv *priv)
+{
+	struct rv1103b_cru *cru = priv->cru;
+	u32 sel, con, prate;
+
+	con = readl(&cru->clksel_con[35]);
+	sel = (con & DCLK_DECOM_SEL_MASK) >>
+	      DCLK_DECOM_SEL_SHIFT;
+	if (sel == DCLK_DECOM_SEL_480M)
+		prate = 480 * MHz;
+	else if (sel == DCLK_DECOM_SEL_400M)
+		prate = 400 * MHz;
+	else
+		prate = 300 * MHz;
+	return prate;
+}
+
+static ulong rv1103b_decom_set_clk(struct rv1103b_clk_priv *priv, ulong rate)
+{
+	struct rv1103b_cru *cru = priv->cru;
+	u32 sel;
+
+	if (rate >= 480 * MHz)
+		sel = DCLK_DECOM_SEL_480M;
+	else if (rate >= 396 * MHz)
+		sel = DCLK_DECOM_SEL_400M;
+	else
+		sel = DCLK_DECOM_SEL_300M;
+	rk_clrsetreg(&cru->clksel_con[35], DCLK_DECOM_SEL_MASK,
+		     (sel << DCLK_DECOM_SEL_SHIFT));
+
+	return rv1103b_decom_get_clk(priv);
+}
+
+static ulong rv1103b_clk_get_rate(struct clk *clk)
+{
+	struct rv1103b_clk_priv *priv = dev_get_priv(clk->dev);
+	ulong rate = 0;
+
+	if (!priv->gpll_hz) {
+		printf("%s gpll=%lu\n", __func__, priv->gpll_hz);
+		return -ENOENT;
+	}
+
+	switch (clk->id) {
+	case PLL_GPLL:
+		rate = rockchip_pll_get_rate(&rv1103b_pll_clks[GPLL], priv->cru,
+					     GPLL);
+		break;
+	case ACLK_PERI_SRC:
+	case LSCLK_PERI_SRC:
+	case PCLK_PERI_ROOT:
+	case PCLK_TOP_ROOT:
+	case LSCLK_PMU_ROOT:
+	case PCLK_PMU:
+		rate = rv1103b_peri_get_clk(priv, clk->id);
+		break;
+	case ACLK_CRYPTO:
+	case HCLK_CRYPTO:
+	case HCLK_RK_RNG_NS:
+	case HCLK_RK_RNG_S:
+	case CLK_CORE_CRYPTO:
+	case CLK_PKA_CRYPTO:
+		rate = rv1103b_crypto_get_clk(priv, clk->id);
+		break;
+	case CCLK_SDMMC1:
+	case HCLK_SDMMC1:
+	case CCLK_SDMMC0:
+	case HCLK_SDMMC0:
+	case CCLK_EMMC:
+	case HCLK_EMMC:
+	case SCLK_SFC_2X:
+	case HCLK_SFC:
+		rate = rv1103b_mmc_get_clk(priv, clk->id);
+		break;
+	case CLK_I2C1:
+	case CLK_I2C2:
+	case CLK_I2C3:
+	case CLK_I2C4:
+	case CLK_I2C_PERI:
+	case CLK_I2C0:
+	case CLK_I2C_PMU:
+		rate = rv1103b_i2c_get_clk(priv, clk->id);
+		break;
+	case CLK_SPI0:
+		rate = rv1103b_spi_get_clk(priv, clk->id);
+		break;
+	case CLK_PWM0:
+	case CLK_PWM0_SRC:
+	case CLK_PWM1:
+	case CLK_PWM2:
+		rate = rv1103b_pwm_get_clk(priv, clk->id);
+		break;
+	case CLK_SARADC:
+	case CLK_TSADC_TSEN:
+	case CLK_TSADC:
+		rate = rv1103b_adc_get_clk(priv, clk->id);
+		break;
+	case SCLK_UART0:
+	case SCLK_UART1:
+	case SCLK_UART2:
+		rate = rv1103b_uart_get_rate(priv, clk->id);
+		break;
+	case DCLK_DECOM_SRC:
+	case DCLK_DECOM:
+		rate = rv1103b_decom_get_clk(priv);
+		break;
+	case TCLK_WDT_LPMCU:
+	case TCLK_WDT_HPMCU:
+	case TCLK_WDT_NS:
+	case TCLK_WDT_S:
+		rate = OSC_HZ;
+		break;
+	default:
+		return -ENOENT;
+	}
+
+	return rate;
+};
+
+static ulong rv1103b_clk_set_rate(struct clk *clk, ulong rate)
+{
+	struct rv1103b_clk_priv *priv = dev_get_priv(clk->dev);
+	ulong ret = 0;
+
+	if (!priv->gpll_hz) {
+		printf("%s gpll=%lu\n", __func__, priv->gpll_hz);
+		return -ENOENT;
+	}
+
+	switch (clk->id) {
+	case PLL_GPLL:
+		ret = rockchip_pll_set_rate(&rv1103b_pll_clks[GPLL], priv->cru,
+					    GPLL, rate);
+		break;
+	case ACLK_PERI_SRC:
+	case LSCLK_PERI_SRC:
+	case PCLK_PERI_ROOT:
+	case PCLK_TOP_ROOT:
+	case LSCLK_PMU_ROOT:
+	case PCLK_PMU:
+		ret = rv1103b_peri_set_clk(priv, clk->id, rate);
+		break;
+	case ACLK_CRYPTO:
+	case HCLK_CRYPTO:
+	case HCLK_RK_RNG_NS:
+	case HCLK_RK_RNG_S:
+	case CLK_CORE_CRYPTO:
+	case CLK_PKA_CRYPTO:
+		ret = rv1103b_crypto_set_clk(priv, clk->id, rate);
+		break;
+	case CCLK_SDMMC1:
+	case HCLK_SDMMC1:
+	case CCLK_SDMMC0:
+	case HCLK_SDMMC0:
+	case CCLK_EMMC:
+	case HCLK_EMMC:
+	case SCLK_SFC_2X:
+	case HCLK_SFC:
+		ret = rv1103b_mmc_set_clk(priv, clk->id, rate);
+		break;
+	case CLK_I2C1:
+	case CLK_I2C2:
+	case CLK_I2C3:
+	case CLK_I2C4:
+	case CLK_I2C_PERI:
+	case CLK_I2C0:
+	case CLK_I2C_PMU:
+		ret = rv1103b_i2c_set_clk(priv, clk->id, rate);
+		break;
+	case CLK_SPI0:
+		ret = rv1103b_spi_set_clk(priv, clk->id, rate);
+		break;
+	case CLK_PWM0:
+	case CLK_PWM0_SRC:
+	case CLK_PWM1:
+	case CLK_PWM2:
+		ret = rv1103b_pwm_set_clk(priv, clk->id, rate);
+		break;
+	case CLK_SARADC:
+	case CLK_TSADC_TSEN:
+	case CLK_TSADC:
+		ret = rv1103b_adc_set_clk(priv, clk->id, rate);
+		break;
+	case SCLK_UART0:
+	case SCLK_UART1:
+	case SCLK_UART2:
+		ret = rv1103b_uart_set_rate(priv, clk->id, rate);
+		break;
+	case DCLK_DECOM_SRC:
+	case DCLK_DECOM:
+		rate = rv1103b_decom_set_clk(priv, rate);
+		break;
+	default:
+		return -ENOENT;
+	}
+
+	return ret;
+};
+
+static int rv1103b_clk_set_parent(struct clk *clk, struct clk *parent)
+{
+	switch (clk->id) {
+	default:
+		return -ENOENT;
+	}
+
+	return 0;
+}
+
+static struct clk_ops rv1103b_clk_ops = {
+	.get_rate = rv1103b_clk_get_rate,
+	.set_rate = rv1103b_clk_set_rate,
+#if (CONFIG_IS_ENABLED(OF_CONTROL)) || (!CONFIG_IS_ENABLED(OF_PLATDATA))
+	.set_parent = rv1103b_clk_set_parent,
+#endif
+};
+
+static void rv1103b_clk_init(struct rv1103b_clk_priv *priv)
+{
+	int ret;
+	u32 div;
+
+	priv->sync_kernel = false;
+	priv->gpll_hz = rockchip_pll_get_rate(&rv1103b_pll_clks[GPLL],
+					      priv->cru, GPLL);
+	if (priv->gpll_hz != GPLL_HZ) {
+		ret = rockchip_pll_set_rate(&rv1103b_pll_clks[GPLL], priv->cru,
+					    GPLL, GPLL_HZ);
+		if (!ret)
+			priv->gpll_hz = GPLL_HZ;
+	}
+
+	if (!priv->armclk_enter_hz) {
+		div = (readl(&priv->cru->clksel_con[37]) &
+		       CLK_CORE_GPLL_DIV_MASK) >>
+		      CLK_CORE_GPLL_DIV_SHIFT;
+		priv->armclk_enter_hz = DIV_TO_RATE(priv->gpll_hz, div);
+		priv->armclk_init_hz = priv->armclk_enter_hz;
+	}
+}
+
+static int rv1103b_clk_probe(struct udevice *dev)
+{
+	struct rv1103b_clk_priv *priv = dev_get_priv(dev);
+	int ret;
+
+#ifdef CONFIG_SPL_BUILD
+	/* fix lsclk_prei div */
+	writel(BITS_WITH_WMASK(1, 0x1U, 9), RV1103B_CRU_BASE + RV1103B_CLKSEL_CON(31));
+	/* fix cpu div */
+	writel(BITS_WITH_WMASK(1, 0x7U, 13), RV1103B_CRU_BASE + RV1103B_CLKSEL_CON(37));
+	/* fix gpll postdiv1 */
+	writel(BITS_WITH_WMASK(1, 0x7U, 12), RV1103B_CRU_BASE + RV1103B_PLL_CON(24));
+#endif
+
+	rv1103b_clk_init(priv);
+
+	/* Process 'assigned-{clocks/clock-parents/clock-rates}' properties */
+	ret = clk_set_defaults(dev, 1);
+	if (ret)
+		debug("%s clk_set_defaults failed %d\n", __func__, ret);
+	else
+		priv->sync_kernel = true;
+	return 0;
+}
+
+static int rv1103b_clk_of_to_plat(struct udevice *dev)
+{
+	struct rv1103b_clk_priv *priv = dev_get_priv(dev);
+
+	priv->cru = dev_read_addr_ptr(dev);
+
+	return 0;
+}
+
+static int rv1103b_clk_bind(struct udevice *dev)
+{
+	struct udevice *sys_child;
+	struct sysreset_reg *priv;
+	int ret;
+
+	/* The sysreset driver does not have a device node, so bind it here */
+	ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset", &sys_child);
+	if (ret) {
+		debug("Warning: No sysreset driver: ret=%d\n", ret);
+	} else {
+		priv = malloc(sizeof(struct sysreset_reg));
+		priv->glb_srst_fst_value = offsetof(struct rv1103b_cru, glb_srst_fst);
+		priv->glb_srst_snd_value = offsetof(struct rv1103b_cru, glb_srst_snd);
+		dev_set_priv(sys_child, priv);
+	}
+
+#if CONFIG_IS_ENABLED(RESET_ROCKCHIP)
+	ret = offsetof(struct rv1103b_cru, peri_softrst_con[0]);
+	ret = rockchip_reset_bind(dev, ret, 12); /* number of reset registers */
+	if (ret)
+		debug("Warning: software reset driver bind failed\n");
+#endif
+
+	return 0;
+}
+
+static const struct udevice_id rv1103b_clk_ids[] = {
+	{ .compatible = "rockchip,rv1103b-cru" },
+	{ }
+};
+
+U_BOOT_DRIVER(clk_rv1103b) = {
+	.name		= "clk_rv1103b",
+	.id		= UCLASS_CLK,
+	.of_match	= rv1103b_clk_ids,
+	.priv_auto	= sizeof(struct rv1103b_clk_priv),
+	.of_to_plat	= rv1103b_clk_of_to_plat,
+	.ops		= &rv1103b_clk_ops,
+	.bind		= rv1103b_clk_bind,
+	.probe		= rv1103b_clk_probe,
+};
-- 
2.43.0


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

* [PATCH v3 04/15] tools: rkcommon: Add RV1103B support
  2026-07-07 15:30 [PATCH v3 00/15] rockchip: Add support for the RV1103B, RV1103 and RV1106 Simon Glass
                   ` (2 preceding siblings ...)
  2026-07-07 15:31 ` [PATCH v3 03/15] clk: rockchip: Add RV1103B clock driver Simon Glass
@ 2026-07-07 15:31 ` Simon Glass
  2026-07-07 15:31 ` [PATCH v3 05/15] rockchip: spl-boot-order: Add SPI NAND support Simon Glass
                   ` (11 subsequent siblings)
  15 siblings, 0 replies; 21+ messages in thread
From: Simon Glass @ 2026-07-07 15:31 UTC (permalink / raw)
  To: u-boot
  Cc: Fabio Estevam, Jonas Karlman, Xuhui Lin, Simon Glass,
	Ilias Apalodimas, Kever Yang, Neil Armstrong, Philipp Tomsich,
	Quentin Schulz, Tom Rini

From: Xuhui Lin <xuhui.lin@rock-chips.com>

Allow rkcommon to generate an image for the RV1103B.

Signed-off-by: Xuhui Lin <xuhui.lin@rock-chips.com>
Signed-off-by: Fabio Estevam <festevam@nabladev.com>
Signed-off-by: Simon Glass <sjg@chromium.org>
---

(no changes since v1)

 tools/rkcommon.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/tools/rkcommon.c b/tools/rkcommon.c
index b39777fc060..6f25a1cda31 100644
--- a/tools/rkcommon.c
+++ b/tools/rkcommon.c
@@ -153,6 +153,7 @@ static struct spl_info spl_infos[] = {
 	{ "rk3568", "RK35", 0x10000 - 0x1000, false, RK_HEADER_V2 },
 	{ "rk3576", "RK35", 0x80000 - 0x1000, false, RK_HEADER_V2 },
 	{ "rk3588", "RK35", 0x100000 - 0x1000, false, RK_HEADER_V2 },
+	{ "rv1103b", "110E", 0x40000 - 0x1000, false, RK_HEADER_V2 },
 	{ "rv1108", "RK11", 0x1800, false, RK_HEADER_V1 },
 	{ "rv1126", "110B", 0x10000 - 0x1000, false, RK_HEADER_V1 },
 };
-- 
2.43.0


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

* [PATCH v3 05/15] rockchip: spl-boot-order: Add SPI NAND support
  2026-07-07 15:30 [PATCH v3 00/15] rockchip: Add support for the RV1103B, RV1103 and RV1106 Simon Glass
                   ` (3 preceding siblings ...)
  2026-07-07 15:31 ` [PATCH v3 04/15] tools: rkcommon: Add RV1103B support Simon Glass
@ 2026-07-07 15:31 ` Simon Glass
  2026-07-07 15:31 ` [PATCH v3 06/15] spl: Add SPI NAND support via MTD in SPL Simon Glass
                   ` (10 subsequent siblings)
  15 siblings, 0 replies; 21+ messages in thread
From: Simon Glass @ 2026-07-07 15:31 UTC (permalink / raw)
  To: u-boot
  Cc: Fabio Estevam, Jonas Karlman, Simon Glass, Alexey Charkov,
	Anshul Dalal, Ilias Apalodimas, Jeffy Chen, Kever Yang,
	Philipp Tomsich, Quentin Schulz, Tom Rini, huang lin

From: Fabio Estevam <festevam@nabladev.com>

Make spl-boot-order accept booting from SPI NAND as well.

With this change, it is possible to specify spi_nand as the boot medium
like this:

u-boot,spl-boot-order = &spi_nand;

Signed-off-by: Fabio Estevam <festevam@nabladev.com>
Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3:
- Guard the spi-nand checks with SPI_NAND_LOAD so that boards without
  SPI NAND support do not grow in size

 arch/arm/mach-rockchip/spl-boot-order.c | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-rockchip/spl-boot-order.c b/arch/arm/mach-rockchip/spl-boot-order.c
index d2dd5e10935..3942dfe6f5c 100644
--- a/arch/arm/mach-rockchip/spl-boot-order.c
+++ b/arch/arm/mach-rockchip/spl-boot-order.c
@@ -4,6 +4,7 @@
  */
 
 #include <dm.h>
+#include <dm/device_compat.h>
 #include <fdt_support.h>
 #include <log.h>
 #include <mmc.h>
@@ -75,6 +76,9 @@ static int spl_node_to_boot_device(int node)
 	 */
 	if (!uclass_find_device_by_of_offset(UCLASS_SPI_FLASH, node, &parent))
 		return BOOT_DEVICE_SPI;
+	if (CONFIG_IS_ENABLED(SPI_NAND_LOAD) &&
+	    !fdt_node_check_compatible(gd->fdt_blob, node, "spi-nand"))
+		return BOOT_DEVICE_SPI;
 
 	if (!uclass_find_device_by_of_offset(UCLASS_UFS, node, &parent))
 		return BOOT_DEVICE_UFS;
@@ -223,8 +227,14 @@ int spl_decode_boot_device(u32 boot_device, char *buf, size_t buflen)
 			}
 
 			ret = uclass_find_device_by_of_offset(UCLASS_SPI_FLASH, node, &dev);
+			if (ret && CONFIG_IS_ENABLED(SPI_NAND_LOAD)) {
+				ret = uclass_find_device_by_of_offset(UCLASS_MTD, node, &dev);
+				if (!ret && !device_is_compatible(dev, "spi-nand"))
+					ret = -ENODEV;
+			}
 			if (ret) {
-				debug("%s: could not find udevice for %s\n", __func__, conf);
+				debug("%s: could not find udevice for %s\n",
+				      __func__, conf);
 				continue;
 			}
 
-- 
2.43.0


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

* [PATCH v3 06/15] spl: Add SPI NAND support via MTD in SPL
  2026-07-07 15:30 [PATCH v3 00/15] rockchip: Add support for the RV1103B, RV1103 and RV1106 Simon Glass
                   ` (4 preceding siblings ...)
  2026-07-07 15:31 ` [PATCH v3 05/15] rockchip: spl-boot-order: Add SPI NAND support Simon Glass
@ 2026-07-07 15:31 ` Simon Glass
  2026-07-07 15:31 ` [PATCH v3 07/15] rockchip: rv1103b: Add SoC support Simon Glass
                   ` (9 subsequent siblings)
  15 siblings, 0 replies; 21+ messages in thread
From: Simon Glass @ 2026-07-07 15:31 UTC (permalink / raw)
  To: u-boot
  Cc: Fabio Estevam, Jonas Karlman, Simon Glass, Alexey Charkov,
	Andrew Davis, Anshul Dalal, Bastien Curutchet, Hrushikesh Salunke,
	Johan Jonker, João Marcos Costa, Mattijs Korpershoek,
	Neil Armstrong, Peng Fan, Quentin Schulz, Richard Genoud,
	Tom Rini

From: Fabio Estevam <festevam@nabladev.com>

Add support for booting U-Boot SPL from SPI NAND devices using the MTD
subsystem:

- Introduce CONFIG_SPL_SPI_NAND_LOAD to enable SPL loading from SPI
  NAND flash.
- Implement spl_spi_nand.c as a dedicated SPL loader that reads the
  FIT image from SPI NAND via MTD.
- Update common/spl/Kconfig and the Makefiles to include the new
  loader in SPL builds.
- Adjust drivers/mtd/Makefile and drivers/mtd/nand/Makefile to build
  the necessary SPI NAND MTD objects only when SPL_SPI_NAND_LOAD is
  enabled, avoiding a size impact on other boards.

This allows boards like the Omega4 RV1103B to boot SPL directly from
SPI NAND, keeping the SPL small and avoiding unnecessary inclusion of
SPI NOR code.

Signed-off-by: Fabio Estevam <festevam@nabladev.com>
Signed-off-by: Simon Glass <sjg@chromium.org>
---

(no changes since v1)

 common/spl/Kconfig        | 10 ++++-
 common/spl/Makefile       |  1 +
 common/spl/spl_spi_nand.c | 82 +++++++++++++++++++++++++++++++++++++++
 drivers/mtd/Makefile      |  1 +
 drivers/mtd/nand/Makefile | 13 ++++++-
 5 files changed, 105 insertions(+), 2 deletions(-)
 create mode 100644 common/spl/spl_spi_nand.c

diff --git a/common/spl/Kconfig b/common/spl/Kconfig
index 0618f42c941..0a3b53d0e66 100644
--- a/common/spl/Kconfig
+++ b/common/spl/Kconfig
@@ -1576,13 +1576,21 @@ config SPL_SPI_LOAD
 	  Enable support for loading next stage, U-Boot or otherwise, from
 	  SPI NOR in U-Boot SPL.
 
+config SPL_SPI_NAND_LOAD
+	bool "Support loading from SPI NAND flash"
+	depends on SPL
+	depends on MTD && DM_MTD
+	help
+	  Enable support for loading next stage, U-Boot or otherwise, from
+	  SPI NAND in U-Boot SPL.
+
 endif # SPL_SPI_FLASH_SUPPORT
 
 config SYS_SPI_U_BOOT_OFFS
 	hex "address of u-boot payload in SPI flash"
 	default 0x8000 if ARCH_SUNXI
 	default 0x0
-	depends on SPL_SPI_LOAD || SPL_SPI_SUNXI
+	depends on SPL_SPI_LOAD || SPL_SPI_NAND_LOAD || SPL_SPI_SUNXI
 	help
 	  Address within SPI-Flash from where the u-boot payload is fetched
 	  from.
diff --git a/common/spl/Makefile b/common/spl/Makefile
index 9c94e8f143e..e8365b69825 100644
--- a/common/spl/Makefile
+++ b/common/spl/Makefile
@@ -36,6 +36,7 @@ obj-$(CONFIG_$(PHASE_)NVME) += spl_nvme.o
 obj-$(CONFIG_$(PHASE_)SEMIHOSTING) += spl_semihosting.o
 obj-$(CONFIG_$(PHASE_)DFU) += spl_dfu.o
 obj-$(CONFIG_$(PHASE_)SPI_LOAD) += spl_spi.o
+obj-$(CONFIG_$(PHASE_)SPI_NAND_LOAD) += spl_spi_nand.o
 obj-$(CONFIG_$(PHASE_)RAM_SUPPORT) += spl_ram.o
 obj-$(CONFIG_$(PHASE_)USB_SDP_SUPPORT) += spl_sdp.o
 obj-$(CONFIG_$(PHASE_)UFS_SUPPORT) += spl_ufs.o
diff --git a/common/spl/spl_spi_nand.c b/common/spl/spl_spi_nand.c
new file mode 100644
index 00000000000..20b877f75a0
--- /dev/null
+++ b/common/spl/spl_spi_nand.c
@@ -0,0 +1,82 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/*
+ * SPL loader for SPI NAND devices using the MTD subsystem.
+ *
+ * Based on spl_spi.c, which is:
+ *
+ * Copyright (C) 2011 OMICRON electronics GmbH
+ *
+ * based on drivers/mtd/nand/raw/nand_spl_load.c
+ *
+ * Copyright (C) 2011
+ * Heiko Schocher, DENX Software Engineering, hs@denx.de.
+ */
+
+#include <config.h>
+#include <image.h>
+#include <log.h>
+#include <errno.h>
+#include <spl.h>
+#include <spl_load.h>
+#include <asm/io.h>
+#include <dm/device_compat.h>
+#include <dm/ofnode.h>
+#include <dm/uclass.h>
+#include <mtd.h>
+
+static struct mtd_info *spl_spi_nand_get_mtd(void)
+{
+	struct udevice *dev;
+	int ret;
+
+	for (ret = uclass_first_device_err(UCLASS_MTD, &dev);
+	     dev;
+	     ret = uclass_next_device_err(&dev)) {
+		if (ret)
+			continue;
+		if (device_is_compatible(dev, "spi-nand"))
+			return dev_get_uclass_priv(dev);
+	}
+
+	return NULL;
+}
+
+static ulong spl_spinand_fit_read(struct spl_load_info *load, ulong offs,
+				  ulong size, void *buf)
+{
+	struct mtd_info *mtd = load->priv;
+	size_t retlen = 0;
+	int ret;
+
+	ret = mtd_read(mtd, offs, size, &retlen, buf);
+	if (ret && ret != -EUCLEAN) {
+		printf("SPI NAND read failed offs=0x%lx size=0x%lx ret=%d\n",
+		       offs, size, ret);
+		return 0;
+	}
+	if (retlen != size)
+		return 0;
+
+	return retlen;
+}
+
+static int spl_spinand_load_image(struct spl_image_info *spl_image,
+				  struct spl_boot_device *bootdev)
+{
+	struct spl_load_info load;
+	struct mtd_info *mtd;
+
+	mtd = spl_spi_nand_get_mtd();
+	if (!mtd) {
+		puts("SPI NAND probe failed.\n");
+		return -ENODEV;
+	}
+
+	spl_load_init(&load, spl_spinand_fit_read, mtd, 1);
+
+	return spl_load(spl_image, bootdev, &load, 0, CONFIG_SYS_SPI_U_BOOT_OFFS);
+}
+
+/* Use priority 1 so that boards can override this */
+SPL_LOAD_IMAGE_METHOD("SPI NAND", 1, BOOT_DEVICE_SPI, spl_spinand_load_image);
diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile
index ce05e206073..a12d880a9e9 100644
--- a/drivers/mtd/Makefile
+++ b/drivers/mtd/Makefile
@@ -34,6 +34,7 @@ else
 ifneq ($(mtd-y),)
 obj-$(CONFIG_SPL_MTD) += mtd.o
 endif
+obj-$(CONFIG_SPL_SPI_NAND_LOAD) += nand/
 obj-$(CONFIG_$(PHASE_)NAND_SUPPORT) += nand/
 obj-$(CONFIG_SPL_ONENAND_SUPPORT) += onenand/
 obj-$(CONFIG_$(PHASE_)SPI_FLASH_SUPPORT) += spi/
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index c8169cf7390..7cd2a5f1af9 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -1,10 +1,21 @@
 # SPDX-License-Identifier: GPL-2.0+
 
-ifeq ($(CONFIG_XPL_BUILD)$(CONFIG_TPL_BUILD),)
 nandcore-objs := core.o bbt.o
+
+ifeq ($(CONFIG_XPL_BUILD)$(CONFIG_TPL_BUILD),)
+
+# U-Boot proper
 obj-$(CONFIG_MTD_NAND_CORE) += nandcore.o
 obj-$(CONFIG_MTD_RAW_NAND) += raw/
 obj-$(CONFIG_MTD_SPI_NAND) += spi/
+
 else
+
+# SPL / XPL / TPL
+# SPL has no MTD_NAND_CORE symbol, so we must key off SPI NAND usage
+obj-$(CONFIG_SPL_SPI_NAND_LOAD) += nandcore.o
+obj-$(CONFIG_SPL_SPI_NAND_LOAD) += spi/
+
+# raw NAND still follows the normal SPL rule
 obj-$(CONFIG_$(PHASE_)NAND_SUPPORT) += raw/
 endif
-- 
2.43.0


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

* [PATCH v3 07/15] rockchip: rv1103b: Add SoC support
  2026-07-07 15:30 [PATCH v3 00/15] rockchip: Add support for the RV1103B, RV1103 and RV1106 Simon Glass
                   ` (5 preceding siblings ...)
  2026-07-07 15:31 ` [PATCH v3 06/15] spl: Add SPI NAND support via MTD in SPL Simon Glass
@ 2026-07-07 15:31 ` Simon Glass
  2026-07-07 15:31 ` [PATCH v3 08/15] omega4-rv1103b: Add the initial support Simon Glass
                   ` (8 subsequent siblings)
  15 siblings, 0 replies; 21+ messages in thread
From: Simon Glass @ 2026-07-07 15:31 UTC (permalink / raw)
  To: u-boot
  Cc: Fabio Estevam, Jonas Karlman, Simon Glass, Heinrich Schuchardt,
	Ilias Apalodimas, Jeffy Chen, Johan Jonker, Kever Yang,
	Mattijs Korpershoek, Philipp Tomsich, Quentin Schulz, Tom Rini,
	huang lin

From: Fabio Estevam <festevam@nabladev.com>

The RV1103B is an ARM-based SoC with a single Cortex-A7 32-bit core
which integrates NEON and FPU. It contains a built-in NPU for AI
related applications.

Add the core SoC support for it: the Kconfig and Makefile entries,
the boot0 hook, the SoC init code, the syscon driver and the SPL
clock setup.

Signed-off-by: Fabio Estevam <festevam@nabladev.com>
Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3:
- New patch, split out from the board patch (Jonas)
- Include the SoC u-boot.dtsi here (Jonas)
- Match the pmu-grf compatible used by the devicetree merged in Linux
  v7.1

 arch/arm/dts/rv1103b-u-boot.dtsi              |   4 +
 arch/arm/include/asm/arch-rv1103b/boot0.h     |  11 ++
 arch/arm/mach-rockchip/Kconfig                |  13 ++
 arch/arm/mach-rockchip/Makefile               |   1 +
 arch/arm/mach-rockchip/rv1103b/Kconfig        |  15 ++
 arch/arm/mach-rockchip/rv1103b/Makefile       |  12 ++
 arch/arm/mach-rockchip/rv1103b/boot0.h        |   5 +
 arch/arm/mach-rockchip/rv1103b/clk_rv1103b.c  |  32 +++++
 arch/arm/mach-rockchip/rv1103b/rv1103b.c      | 133 ++++++++++++++++++
 .../mach-rockchip/rv1103b/syscon_rv1103b.c    |  19 +++
 include/configs/rv1103b_common.h              |  14 ++
 11 files changed, 259 insertions(+)
 create mode 100644 arch/arm/dts/rv1103b-u-boot.dtsi
 create mode 100644 arch/arm/include/asm/arch-rv1103b/boot0.h
 create mode 100644 arch/arm/mach-rockchip/rv1103b/Kconfig
 create mode 100644 arch/arm/mach-rockchip/rv1103b/Makefile
 create mode 100644 arch/arm/mach-rockchip/rv1103b/boot0.h
 create mode 100644 arch/arm/mach-rockchip/rv1103b/clk_rv1103b.c
 create mode 100644 arch/arm/mach-rockchip/rv1103b/rv1103b.c
 create mode 100644 arch/arm/mach-rockchip/rv1103b/syscon_rv1103b.c
 create mode 100644 include/configs/rv1103b_common.h

diff --git a/arch/arm/dts/rv1103b-u-boot.dtsi b/arch/arm/dts/rv1103b-u-boot.dtsi
new file mode 100644
index 00000000000..3b77dd31152
--- /dev/null
+++ b/arch/arm/dts/rv1103b-u-boot.dtsi
@@ -0,0 +1,4 @@
+// SPDX-License-Identifier:     GPL-2.0+
+// (C) Copyright 2024 Rockchip Electronics Co., Ltd
+
+#include "rockchip-u-boot.dtsi"
diff --git a/arch/arm/include/asm/arch-rv1103b/boot0.h b/arch/arm/include/asm/arch-rv1103b/boot0.h
new file mode 100644
index 00000000000..2e78b074ade
--- /dev/null
+++ b/arch/arm/include/asm/arch-rv1103b/boot0.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2019 Rockchip Electronics Co., Ltd
+ */
+
+#ifndef __ASM_ARCH_BOOT0_H__
+#define __ASM_ARCH_BOOT0_H__
+
+#include <asm/arch-rockchip/boot0.h>
+
+#endif
diff --git a/arch/arm/mach-rockchip/Kconfig b/arch/arm/mach-rockchip/Kconfig
index 1a2e7847c9e..1969c313f47 100644
--- a/arch/arm/mach-rockchip/Kconfig
+++ b/arch/arm/mach-rockchip/Kconfig
@@ -532,6 +532,18 @@ config ROCKCHIP_RK3588
 	  SD3.0/MMC4.5, USB OTG 3.0, Type-C, USB 2.0, PCIe 3.0, SATA 3, Ethernet,
 	  SDIO3.0 I2C, UART, SPI, GPIO and PWM.
 
+config ROCKCHIP_RV1103B
+	bool "Support Rockchip RV1103B"
+	select CPU_V7A
+	select SPL_ARMV7_SET_CORTEX_SMPEN
+	select SUPPORT_SPL
+	select SPL
+	imply ROCKCHIP_COMMON_BOARD
+	help
+	  The Rockchip RV1103B is an ARM-based SoC with a single Cortex-A7
+	  32-bit core which integrates NEON and FPU.
+	  It contains a built-in NPU for AI related applications.
+
 config ROCKCHIP_RV1108
 	bool "Support Rockchip RV1108"
 	select CPU_V7A
@@ -795,6 +807,7 @@ source "arch/arm/mach-rockchip/rk3528/Kconfig"
 source "arch/arm/mach-rockchip/rk3568/Kconfig"
 source "arch/arm/mach-rockchip/rk3576/Kconfig"
 source "arch/arm/mach-rockchip/rk3588/Kconfig"
+source "arch/arm/mach-rockchip/rv1103b/Kconfig"
 source "arch/arm/mach-rockchip/rv1108/Kconfig"
 source "arch/arm/mach-rockchip/rv1126/Kconfig"
 
diff --git a/arch/arm/mach-rockchip/Makefile b/arch/arm/mach-rockchip/Makefile
index d3bc0689f89..e09dc44a7ad 100644
--- a/arch/arm/mach-rockchip/Makefile
+++ b/arch/arm/mach-rockchip/Makefile
@@ -47,6 +47,7 @@ obj-$(CONFIG_ROCKCHIP_RK3528) += rk3528/
 obj-$(CONFIG_ROCKCHIP_RK3568) += rk3568/
 obj-$(CONFIG_ROCKCHIP_RK3576) += rk3576/
 obj-$(CONFIG_ROCKCHIP_RK3588) += rk3588/
+obj-$(CONFIG_ROCKCHIP_RV1103B) += rv1103b/
 obj-$(CONFIG_ROCKCHIP_RV1108) += rv1108/
 obj-$(CONFIG_ROCKCHIP_RV1126) += rv1126/
 
diff --git a/arch/arm/mach-rockchip/rv1103b/Kconfig b/arch/arm/mach-rockchip/rv1103b/Kconfig
new file mode 100644
index 00000000000..710a86aeb33
--- /dev/null
+++ b/arch/arm/mach-rockchip/rv1103b/Kconfig
@@ -0,0 +1,15 @@
+if ROCKCHIP_RV1103B
+
+config ROCKCHIP_BOOT_MODE_REG
+	default 0x20160200
+
+config ROCKCHIP_STIMER_BASE
+	default 0x20500000
+
+config SYS_SOC
+	default "rv1103b"
+
+config SYS_MALLOC_F_LEN
+	default 0x400
+
+endif
diff --git a/arch/arm/mach-rockchip/rv1103b/Makefile b/arch/arm/mach-rockchip/rv1103b/Makefile
new file mode 100644
index 00000000000..2f34853adac
--- /dev/null
+++ b/arch/arm/mach-rockchip/rv1103b/Makefile
@@ -0,0 +1,12 @@
+#
+# (C) Copyright 2016 Rockchip Electronics Co., Ltd
+#
+# SPDX-License-Identifier:     GPL-2.0+
+#
+
+obj-y += rv1103b.o
+obj-y += clk_rv1103b.o
+
+ifndef CONFIG_XPL_BUILD
+obj-y += syscon_rv1103b.o
+endif
diff --git a/arch/arm/mach-rockchip/rv1103b/boot0.h b/arch/arm/mach-rockchip/rv1103b/boot0.h
new file mode 100644
index 00000000000..466ab0e8077
--- /dev/null
+++ b/arch/arm/mach-rockchip/rv1103b/boot0.h
@@ -0,0 +1,5 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/* Dummy boot0.h for RV1103B — SoC does not require special boot0 setup. */
+#ifndef __ASM_ARCH_BOOT0_H__
+#define __ASM_ARCH_BOOT0_H__
+#endif
diff --git a/arch/arm/mach-rockchip/rv1103b/clk_rv1103b.c b/arch/arm/mach-rockchip/rv1103b/clk_rv1103b.c
new file mode 100644
index 00000000000..2bcbb08537e
--- /dev/null
+++ b/arch/arm/mach-rockchip/rv1103b/clk_rv1103b.c
@@ -0,0 +1,32 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * (C) Copyright 2016 Rockchip Electronics Co., Ltd
+ * Author: Andy Yan <andy.yan@rock-chips.com>
+ */
+
+#include <dm.h>
+#include <syscon.h>
+#include <asm/arch-rockchip/clock.h>
+#include <asm/arch-rockchip/cru_rv1103b.h>
+#include <linux/err.h>
+
+int rockchip_get_clk(struct udevice **devp)
+{
+	return uclass_get_device_by_driver(UCLASS_CLK,
+			DM_DRIVER_GET(clk_rv1103b), devp);
+}
+
+void *rockchip_get_cru(void)
+{
+	struct rv1103b_clk_priv *priv;
+	struct udevice *dev;
+	int ret;
+
+	ret = rockchip_get_clk(&dev);
+	if (ret)
+		return ERR_PTR(ret);
+
+	priv = dev_get_priv(dev);
+
+	return priv->cru;
+}
diff --git a/arch/arm/mach-rockchip/rv1103b/rv1103b.c b/arch/arm/mach-rockchip/rv1103b/rv1103b.c
new file mode 100644
index 00000000000..a7ff1934f7d
--- /dev/null
+++ b/arch/arm/mach-rockchip/rv1103b/rv1103b.c
@@ -0,0 +1,133 @@
+// SPDX-License-Identifier:     GPL-2.0+
+// Copyright (c) 2024 Rockchip Electronics Co., Ltd
+
+#include <dm.h>
+#include <spl.h>
+#include <asm/io.h>
+#include <image.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define PERI_CRU_BASE			0x20000000
+#define PERICRU_PERISOFTRST_CON10	0x0a28
+
+#define PMU0_CRU_BASE			0x20070000
+#define PMUCRU_PMUSOFTRST_CON02		0x0a08
+
+#define GRF_SYS_BASE			0x20150000
+#define GRF_SYS_HPMCU_CACHE_MISC	0x0214
+
+#define GPIO0_IOC_BASE			0x201B0000
+#define GPIO0A_IOMUX_SEL_H		0x04
+#define GPIO0_BASE			0x20520000
+#define GPIO_SWPORT_DR_L		0x00
+#define GPIO_SWPORT_DDR_L		0x08
+
+#define GPIO1_IOC_BASE			0x20170000
+#define GPIO1A_IOMUX_SEL_0		0x20
+#define GPIO1A_IOMUX_SEL_1_0		0x24
+#define GPIO1A_IOMUX_SEL_1_1		0x10024
+#define GPIO1B_IOMUX_SEL_0		0x10028
+#define GPIO1B_IOMUX_SEL_1		0x1002c
+#define GPIO1_IOC_GPIO1A_PULL_0		0x210
+#define GPIO1_IOC_GPIO1A_PULL_1		0x10210
+#define GPIO1_IOC_GPIO1B_PULL		0x10214
+#define GPIO1_IOC_JTAG_M2_CON		0x10810
+
+#define GPIO2_IOC_BASE			0x20840000
+#define GPIO2A_IOMUX_SEL_1_1		0x44
+
+#define SGRF_SYS_BASE			0x20250000
+#define SGRF_SYS_SOC_CON2		0x0008
+#define SGRF_SYS_SOC_CON3		0x000c
+#define SGRF_SYS_OTP_CON		0x0018
+#define FIREWALL_CON0			0x0020
+#define FIREWALL_CON1			0x0024
+#define FIREWALL_CON2			0x0028
+#define FIREWALL_CON3			0x002c
+#define FIREWALL_CON4			0x0030
+#define FIREWALL_CON5			0x0034
+#define FIREWALL_CON7			0x003c
+#define SGRF_SYS_HPMCU_BOOT_DDR		0x0080
+
+#define SGRF_PMU_BASE			0x20260000
+#define SGRF_PMU_SOC_CON0		0x0000
+#define SGRF_PMU_PMUMCU_BOOT_ADDR	0x0020
+
+#define SYS_GRF_BASE			0x20150000
+#define GRF_SYS_PERI_CON2		0x08
+#define GRF_SYS_USBPHY_CON0		0x50
+
+#define TOP_CRU_BASE			0x20060000
+#define TOPCRU_CRU_GLB_RST_CON		0xc10
+
+#define USBPHY_APB_BASE			0x20e10000
+#define USBPHY_FSLS_DIFF_RECEIVER	0x0100
+
+#define RV1103B_WDT_BASE			0x208d0000
+#define RV1103B_WDT_CR			0x00
+
+void board_debug_uart_init(void)
+{
+	/* No need to change uart */
+}
+
+#ifdef CONFIG_SPL_BUILD
+void rockchip_stimer_init(void)
+{
+	/* If Timer already enabled, don't re-init it */
+	u32 reg = readl(CONFIG_ROCKCHIP_STIMER_BASE + 0x4);
+
+	if (reg & 0x1)
+		return;
+	writel(0x00010000, CONFIG_ROCKCHIP_STIMER_BASE + 0x4);
+
+	asm volatile("mcr p15, 0, %0, c14, c0, 0" : : "r"(CONFIG_COUNTER_FREQUENCY));
+	writel(0xffffffff, CONFIG_ROCKCHIP_STIMER_BASE + 0x14);
+	writel(0xffffffff, CONFIG_ROCKCHIP_STIMER_BASE + 0x18);
+	writel(0x00010001, CONFIG_ROCKCHIP_STIMER_BASE + 0x4);
+}
+#endif
+
+#ifndef CONFIG_TPL_BUILD
+int arch_cpu_init(void)
+{
+	/* Stop any watchdog left running by BootROM/Boot1. */
+	writel(0, RV1103B_WDT_BASE + RV1103B_WDT_CR);
+
+#if defined(CONFIG_SPL_BUILD)
+	/* Set all devices to Non-secure */
+	writel(0xffff0000, SGRF_SYS_BASE + FIREWALL_CON0);
+	writel(0xffff0000, SGRF_SYS_BASE + FIREWALL_CON1);
+	writel(0xffff0000, SGRF_SYS_BASE + FIREWALL_CON2);
+	writel(0xffff0000, SGRF_SYS_BASE + FIREWALL_CON3);
+	writel(0xffff0000, SGRF_SYS_BASE + FIREWALL_CON4);
+	writel(0xffff0000, SGRF_SYS_BASE + FIREWALL_CON5);
+	writel(0x01f00000, SGRF_SYS_BASE + FIREWALL_CON7);
+	/* Set OTP to none secure mode */
+	writel(0x00020000, SGRF_SYS_BASE + SGRF_SYS_OTP_CON);
+
+	/* no-secure WDT reset output will reset SoC system. */
+	writel(0x00010001, SYS_GRF_BASE + GRF_SYS_PERI_CON2);
+	/* secure WDT reset output will reset SoC system. */
+	writel(0x00010001, SGRF_SYS_BASE + SGRF_SYS_SOC_CON2);
+	/*
+	 * enable tsadc trigger global reset and select first reset.
+	 * enable global reset and wdt trigger pmu reset.
+	 * select first reset trigger pmu reset.
+	 */
+	writel(0x0000ffdf, TOP_CRU_BASE + TOPCRU_CRU_GLB_RST_CON);
+
+	/*
+	 * Set the USB2 PHY in suspend mode and turn off the
+	 * USB2 PHY FS/LS differential receiver to save power:
+	 * VCC1V8_USB : reduce 3.8 mA
+	 * VDD_0V9 : reduce 4.4 mA
+	 */
+	writel(0x01ff01d1, SYS_GRF_BASE + GRF_SYS_USBPHY_CON0);
+	writel(0x00000000, USBPHY_APB_BASE + USBPHY_FSLS_DIFF_RECEIVER);
+#endif
+
+	return 0;
+}
+#endif
diff --git a/arch/arm/mach-rockchip/rv1103b/syscon_rv1103b.c b/arch/arm/mach-rockchip/rv1103b/syscon_rv1103b.c
new file mode 100644
index 00000000000..7c71b1092f3
--- /dev/null
+++ b/arch/arm/mach-rockchip/rv1103b/syscon_rv1103b.c
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2016 Rockchip Electronics Co., Ltd
+ */
+
+#include <dm.h>
+#include <syscon.h>
+#include <asm/arch-rockchip/clock.h>
+
+static const struct udevice_id rv1103b_syscon_ids[] = {
+	{ .compatible = "rockchip,rv1103b-pmu-grf", .data = ROCKCHIP_SYSCON_PMUGRF },
+	{ }
+};
+
+U_BOOT_DRIVER(syscon_rv1103b) = {
+	.name = "rv1103b_syscon",
+	.id = UCLASS_SYSCON,
+	.of_match = rv1103b_syscon_ids,
+};
diff --git a/include/configs/rv1103b_common.h b/include/configs/rv1103b_common.h
new file mode 100644
index 00000000000..8e970d71051
--- /dev/null
+++ b/include/configs/rv1103b_common.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2016 Rockchip Electronics Co., Ltd
+ */
+#ifndef __CONFIG_RV1103B_COMMON_H
+#define __CONFIG_RV1103B_COMMON_H
+
+#include "rockchip-common.h"
+#include <config_distro_bootcmd.h>
+
+#define CFG_IRAM_BASE			0x210f6000
+#define CFG_SYS_SDRAM_BASE		0x00000000
+
+#endif
-- 
2.43.0


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

* [PATCH v3 08/15] omega4-rv1103b: Add the initial support
  2026-07-07 15:30 [PATCH v3 00/15] rockchip: Add support for the RV1103B, RV1103 and RV1106 Simon Glass
                   ` (6 preceding siblings ...)
  2026-07-07 15:31 ` [PATCH v3 07/15] rockchip: rv1103b: Add SoC support Simon Glass
@ 2026-07-07 15:31 ` Simon Glass
  2026-07-07 15:31 ` [PATCH v3 09/15] tools: rkcommon: Add RV1106 support Simon Glass
                   ` (7 subsequent siblings)
  15 siblings, 0 replies; 21+ messages in thread
From: Simon Glass @ 2026-07-07 15:31 UTC (permalink / raw)
  To: u-boot
  Cc: Fabio Estevam, Jonas Karlman, Simon Glass, Alexander Feilke,
	Chris Morgan, Chris Packham, FUKAUMI Naoki, Ilias Apalodimas,
	Johan Jonker, Kever Yang, Niu Zhihong, Peng Fan, Peter Robinson,
	Philipp Tomsich, Quentin Schulz, Svyatoslav Ryhel, Tom Rini

From: Fabio Estevam <festevam@nabladev.com>

Add the initial support for Onion's Omega4 RV1103B board, using the
board devicetree files as merged in Linux v7.1, which split the board
into rv1103b-omega4.dtsi and rv1103b-omega4-evb.dts

It boots from the SPI NAND.

Tested the boot of a 6.6 OpenWRT kernel and also a 6.19-rc8 mainline
kernel.

Signed-off-by: Fabio Estevam <festevam@nabladev.com>
Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3:
- Split out the SoC support into its own patch (Jonas)
- Move the board devicetree files into this patch (Jonas)
- Add the board to the list in the Rockchip documentation
- Extend the MAINTAINERS entry to cover all the RV1103B files
- Use the board devicetree files as merged in Linux v7.1 and switch
  the default devicetree to rv1103b-omega4-evb

Changes in v2:
- Use RV1103B rather than RV1103, which is the correct SoC name

 arch/arm/dts/rv1103b-omega4-evb-u-boot.dtsi   |  10 ++
 arch/arm/dts/rv1103b-omega4-evb.dts           |  63 ++++++++
 arch/arm/dts/rv1103b-omega4.dtsi              | 147 ++++++++++++++++++
 arch/arm/mach-rockchip/rv1103b/Kconfig        |   7 +
 board/onion/omega4_rv1103b/Kconfig            |  12 ++
 board/onion/omega4_rv1103b/MAINTAINERS        |  15 ++
 board/onion/omega4_rv1103b/Makefile           |   7 +
 board/onion/omega4_rv1103b/omega4_rv1103b.c   |  19 +++
 board/onion/omega4_rv1103b/omega4_rv1103b.env |   5 +
 configs/omega4-rv1103b_defconfig              |  82 ++++++++++
 doc/board/index.rst                           |   1 +
 doc/board/onion/index.rst                     |   9 ++
 doc/board/onion/omega4-rv1103b.rst            |  56 +++++++
 doc/board/rockchip/rockchip.rst               |   3 +
 include/configs/omega4_rv1103b.h              |  11 ++
 15 files changed, 447 insertions(+)
 create mode 100644 arch/arm/dts/rv1103b-omega4-evb-u-boot.dtsi
 create mode 100644 arch/arm/dts/rv1103b-omega4-evb.dts
 create mode 100644 arch/arm/dts/rv1103b-omega4.dtsi
 create mode 100644 board/onion/omega4_rv1103b/Kconfig
 create mode 100644 board/onion/omega4_rv1103b/MAINTAINERS
 create mode 100644 board/onion/omega4_rv1103b/Makefile
 create mode 100644 board/onion/omega4_rv1103b/omega4_rv1103b.c
 create mode 100644 board/onion/omega4_rv1103b/omega4_rv1103b.env
 create mode 100644 configs/omega4-rv1103b_defconfig
 create mode 100644 doc/board/onion/index.rst
 create mode 100644 doc/board/onion/omega4-rv1103b.rst
 create mode 100644 include/configs/omega4_rv1103b.h

diff --git a/arch/arm/dts/rv1103b-omega4-evb-u-boot.dtsi b/arch/arm/dts/rv1103b-omega4-evb-u-boot.dtsi
new file mode 100644
index 00000000000..c7616de1715
--- /dev/null
+++ b/arch/arm/dts/rv1103b-omega4-evb-u-boot.dtsi
@@ -0,0 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
+// (C) Copyright 2024 Rockchip Electronics Co., Ltd
+
+#include "rockchip-u-boot.dtsi"
+
+/ {
+	chosen {
+		u-boot,spl-boot-order = &spi_nand;
+	};
+};
diff --git a/arch/arm/dts/rv1103b-omega4-evb.dts b/arch/arm/dts/rv1103b-omega4-evb.dts
new file mode 100644
index 00000000000..c6472f933aa
--- /dev/null
+++ b/arch/arm/dts/rv1103b-omega4-evb.dts
@@ -0,0 +1,63 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2022 Rockchip Electronics Co., Ltd.
+ * Copyright (c) 2025 plan44.ch/luz
+ * Copyright (c) 2026 Onion Corporation
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/leds/common.h>
+#include "rv1103b-omega4.dtsi"
+
+/ {
+	model = "Onion Omega4 Evaluation Board";
+	compatible = "onion,omega4-evb", "onion,omega4", "rockchip,rv1103b";
+
+	aliases {
+		serial0 = &uart0;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		led-0	{
+			color = <LED_COLOR_ID_BLUE>;
+			default-state = "on";
+			function = LED_FUNCTION_STATUS;
+			gpios = <&gpio0 RK_PA2 GPIO_ACTIVE_HIGH>;
+			label = "sys";
+			pinctrl-names = "default";
+			pinctrl-0 = <&led>;
+		};
+	};
+};
+
+&fspi0 {
+	status = "okay";
+};
+
+&pinctrl {
+	leds {
+		led: led {
+			rockchip,pins = <0 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+};
+
+&sdmmc0 {
+	status = "okay";
+};
+
+&sdmmc1 {
+	status = "okay";
+};
+
+&uart0 {
+	status = "okay";
+};
diff --git a/arch/arm/dts/rv1103b-omega4.dtsi b/arch/arm/dts/rv1103b-omega4.dtsi
new file mode 100644
index 00000000000..6a8e8e0f80c
--- /dev/null
+++ b/arch/arm/dts/rv1103b-omega4.dtsi
@@ -0,0 +1,147 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2022 Rockchip Electronics Co., Ltd.
+ * Copyright (c) 2025 plan44.ch/luz
+ * Copyright (c) 2026 Onion Corporation
+ */
+
+/dts-v1/;
+
+#include "rv1103b.dtsi"
+
+/ {
+	sdio_pwrseq: sdio-pwrseq {
+		compatible = "mmc-pwrseq-simple";
+		pinctrl-names = "default";
+		pinctrl-0 = <&wifi_enable_h>;
+		post-power-on-delay-ms = <300>;
+		reset-gpios = <&gpio2 RK_PB2 GPIO_ACTIVE_LOW>;
+	};
+
+	vcc3v3_sd: vcc3v3-sd {
+		compatible = "regulator-fixed";
+		gpio = <&gpio0 RK_PA4 GPIO_ACTIVE_LOW>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&sdmmc_pwren>;
+		regulator-name = "vcc3v3_sd";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+	};
+
+	vccio_sd: vccio-sd {
+		compatible = "regulator-gpio";
+		gpios = <&gpio0 RK_PA3 GPIO_ACTIVE_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&sdmmc_volt>;
+		regulator-name = "vccio_sd";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <3300000>;
+		states = <3300000 1 1800000 0>;
+	};
+};
+
+&uart0 {
+	bootph-all;
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0m0_xfer>;
+};
+
+&fspi0 {
+	spi_nand: flash@0 {
+		compatible = "spi-nand";
+		reg = <0>;
+		bootph-pre-ram;
+		bootph-some-ram;
+		spi-max-frequency = <75000000>;
+		spi-rx-bus-width = <4>;
+		spi-tx-bus-width = <1>;
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			partition@0 {
+				reg = <0x00000000 0x00040000>;
+				label = "env";
+			};
+
+			partition@40000 {
+				reg = <0x00040000 0x00100000>;
+				label = "idblock";
+				read-only;
+			};
+
+			partition@140000 {
+				reg = <0x00140000 0x00100000>;
+				label = "uboot";
+				read-only;
+			};
+
+			partition@240000 {
+				reg = <0x00240000 0x00800000>;
+				label = "boot";
+			};
+
+			partition@a40000 {
+				reg = <0x00a40000 0x0f5c0000>;
+				label = "ubi";
+			};
+		};
+	};
+};
+
+&sdmmc0 {
+	bus-width = <4>;
+	cap-mmc-highspeed;
+	cap-sd-highspeed;
+	disable-wp;
+	no-sdio;
+	no-mmc;
+	sd-uhs-sdr104;
+	vmmc-supply = <&vcc3v3_sd>;
+	vqmmc-supply = <&vccio_sd>;
+	status = "disabled";
+};
+
+&sdmmc1 {
+	bus-width = <4>;
+	cap-sd-highspeed;
+	cap-sdio-irq;
+	keep-power-in-suspend;
+	mmc-pwrseq = <&sdio_pwrseq>;
+	no-sd;
+	no-mmc;
+	non-removable;
+	pinctrl-names = "default";
+	pinctrl-0 = <&sdmmc1_cmd &sdmmc1_clk &sdmmc1_bus4>;
+	status = "disabled";
+};
+
+&pinctrl {
+	sdio-pwrseq {
+		/omit-if-no-ref/
+		wifi_enable_h: wifi-enable-h {
+			rockchip,pins = <2 RK_PB2 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+
+	sdmmc {
+		/omit-if-no-ref/
+		sdmmc_pwren: sdmmc-pwren {
+			rockchip,pins = <0 RK_PA4 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+
+		/omit-if-no-ref/
+		sdmmc_volt: sdmmc-volt {
+			rockchip,pins = <0 RK_PA3 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+
+	wireless-wlan {
+		/omit-if-no-ref/
+		wifi_host_wake_irq: wifi-host-wake-irq {
+			rockchip,pins = <2 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+};
diff --git a/arch/arm/mach-rockchip/rv1103b/Kconfig b/arch/arm/mach-rockchip/rv1103b/Kconfig
index 710a86aeb33..77699a5180e 100644
--- a/arch/arm/mach-rockchip/rv1103b/Kconfig
+++ b/arch/arm/mach-rockchip/rv1103b/Kconfig
@@ -1,5 +1,10 @@
 if ROCKCHIP_RV1103B
 
+config TARGET_OMEGA4_RV1103B
+	bool "OMEGA4_RV1103B"
+	help
+	  Support Onion's Omega4 RV1103B board.
+
 config ROCKCHIP_BOOT_MODE_REG
 	default 0x20160200
 
@@ -12,4 +17,6 @@ config SYS_SOC
 config SYS_MALLOC_F_LEN
 	default 0x400
 
+source "board/onion/omega4_rv1103b/Kconfig"
+
 endif
diff --git a/board/onion/omega4_rv1103b/Kconfig b/board/onion/omega4_rv1103b/Kconfig
new file mode 100644
index 00000000000..43b126c20e9
--- /dev/null
+++ b/board/onion/omega4_rv1103b/Kconfig
@@ -0,0 +1,12 @@
+if TARGET_OMEGA4_RV1103B
+
+config SYS_BOARD
+	default "omega4_rv1103b"
+
+config SYS_VENDOR
+	default "onion"
+
+config SYS_CONFIG_NAME
+	default "omega4_rv1103b"
+
+endif
diff --git a/board/onion/omega4_rv1103b/MAINTAINERS b/board/onion/omega4_rv1103b/MAINTAINERS
new file mode 100644
index 00000000000..5ad58118989
--- /dev/null
+++ b/board/onion/omega4_rv1103b/MAINTAINERS
@@ -0,0 +1,15 @@
+OMEGA4 RV1103B
+M:	Fabio Estevam <festevam@nabladev.com>
+S:	Maintained
+F:	arch/arm/dts/rv1103b*
+F:	arch/arm/include/asm/arch-rv1103b/
+F:	arch/arm/include/asm/arch-rockchip/cru_rv1103b.h
+F:	arch/arm/mach-rockchip/rv1103b/
+F:	board/onion/omega4_rv1103b/
+F:	configs/omega4-rv1103b_defconfig
+F:	doc/board/onion/
+F:	drivers/clk/rockchip/clk_rv1103b.c
+F:	drivers/pinctrl/rockchip/pinctrl-rv1103b.c
+F:	include/configs/omega4_rv1103b.h
+F:	include/configs/rv1103b_common.h
+F:	include/dt-bindings/clock/rockchip,rv1103b-cru.h
diff --git a/board/onion/omega4_rv1103b/Makefile b/board/onion/omega4_rv1103b/Makefile
new file mode 100644
index 00000000000..afa0a7f7a93
--- /dev/null
+++ b/board/onion/omega4_rv1103b/Makefile
@@ -0,0 +1,7 @@
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+# Copyright 2026 Fabio Estevam <festevam@nabladev.com>
+#
+
+obj-y	+= omega4_rv1103b.o
diff --git a/board/onion/omega4_rv1103b/omega4_rv1103b.c b/board/onion/omega4_rv1103b/omega4_rv1103b.c
new file mode 100644
index 00000000000..9bdec3c396a
--- /dev/null
+++ b/board/onion/omega4_rv1103b/omega4_rv1103b.c
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: GPL-2.0+
+//
+// Copyright 2026 Fabio Estevam <festevam@nabladev.com>
+
+#include <asm/global_data.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int dram_init(void)
+{
+	gd->ram_size = SZ_256M;
+
+	return 0;
+}
+
+phys_addr_t board_get_usable_ram_top(phys_size_t total_size)
+{
+	return gd->ram_top;
+}
diff --git a/board/onion/omega4_rv1103b/omega4_rv1103b.env b/board/onion/omega4_rv1103b/omega4_rv1103b.env
new file mode 100644
index 00000000000..7ed232cab91
--- /dev/null
+++ b/board/onion/omega4_rv1103b/omega4_rv1103b.env
@@ -0,0 +1,5 @@
+kernel_addr_r=0x00800000
+fdt_addr_r=0x02000000
+ramdisk_addr_r=0x04000000
+bootargs=console=ttyS0,115200 mtdparts=spi1.0:256K(env),1M@256K(idblock),1M(uboot),8M(boot),-(ubi) ro rootwait ubi.mtd=ubi ubi.block=0,rootfs root=/dev/ubiblock0_0 rootfstype=squashfs
+bootcmd=mtd read spi-nand0 0x04000000 0x240000 0x800000;imxtract 0x04000000 kernel 0x00800000; imxtract 0x04000000 fdt 0x02000000; bootz 0x00800000 - 0x02000000
diff --git a/configs/omega4-rv1103b_defconfig b/configs/omega4-rv1103b_defconfig
new file mode 100644
index 00000000000..04e51af605c
--- /dev/null
+++ b/configs/omega4-rv1103b_defconfig
@@ -0,0 +1,82 @@
+CONFIG_ARM=y
+CONFIG_SKIP_LOWLEVEL_INIT=y
+CONFIG_COUNTER_FREQUENCY=24000000
+CONFIG_SYS_ARCH_TIMER=y
+CONFIG_ARCH_ROCKCHIP=y
+CONFIG_TEXT_BASE=0x00200000
+CONFIG_SYS_MALLOC_F_LEN=0x80000
+CONFIG_SPL_LIBCOMMON_SUPPORT=y
+CONFIG_SPL_LIBGENERIC_SUPPORT=y
+CONFIG_NR_DRAM_BANKS=1
+CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y
+CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x00400000
+CONFIG_SF_DEFAULT_SPEED=24000000
+CONFIG_DEFAULT_DEVICE_TREE="rv1103b-omega4-evb"
+CONFIG_SPL_SYS_MALLOC_F_LEN=0x100000
+CONFIG_ROCKCHIP_RV1103B=y
+CONFIG_SPL_ROCKCHIP_COMMON_BOARD=y
+CONFIG_ROCKCHIP_EXTERNAL_TPL=y
+CONFIG_SPL_SERIAL=y
+CONFIG_TARGET_OMEGA4_RV1103B=y
+CONFIG_SYS_BOOTM_LEN=0x04000000
+CONFIG_SYS_LOAD_ADDR=0x00008000
+CONFIG_SF_DEFAULT_BUS=1
+CONFIG_DEBUG_UART_BASE=0x20540000
+CONFIG_DEBUG_UART_CLOCK=24000000
+# CONFIG_DEBUG_UART_BOARD_INIT is not set
+CONFIG_SPL_SPI_FLASH_SUPPORT=y
+CONFIG_SPL_SPI=y
+CONFIG_DEBUG_UART=y
+CONFIG_FIT=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_FIT_CIPHER=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_FIT_BEST_MATCH=y
+CONFIG_LEGACY_IMAGE_FORMAT=y
+CONFIG_BOOTDELAY=1
+# CONFIG_DISPLAY_CPUINFO is not set
+CONFIG_SPL_NO_BSS_LIMIT=y
+CONFIG_SPL_MTD=y
+CONFIG_SPL_SPI_NAND_LOAD=y
+CONFIG_SYS_SPI_U_BOOT_OFFS=0x140000
+CONFIG_CMD_BOOTZ=y
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_MTD=y
+CONFIG_CMD_SPI=y
+# CONFIG_CMD_SETEXPR is not set
+CONFIG_CMD_CACHE=y
+CONFIG_CMD_TIME=y
+CONFIG_SPL_OF_CONTROL=y
+CONFIG_ENV_RELOC_GD_ENV_ADDR=y
+CONFIG_NO_NET=y
+CONFIG_SPL_DM_SEQ_ALIAS=y
+CONFIG_REGMAP=y
+CONFIG_SPL_REGMAP=y
+CONFIG_SYSCON=y
+CONFIG_SPL_SYSCON=y
+CONFIG_CLK=y
+CONFIG_SPL_CLK=y
+CONFIG_ROCKCHIP_GPIO=y
+CONFIG_SYS_I2C_ROCKCHIP=y
+# CONFIG_MMC is not set
+CONFIG_DM_MTD=y
+CONFIG_MTD_SPI_NAND=y
+CONFIG_SPI_FLASH_SFDP_SUPPORT=y
+CONFIG_SPI_FLASH_GIGADEVICE=y
+CONFIG_SPI_FLASH_WINBOND=y
+CONFIG_SPI_FLASH_XTX=y
+CONFIG_SPI_FLASH_MTD=y
+CONFIG_PINCTRL=y
+CONFIG_SPL_PINCTRL=y
+CONFIG_PINCTRL_ROCKCHIP_RV1103B=y
+CONFIG_DM_REGULATOR_FIXED=y
+CONFIG_DEBUG_UART_SHIFT=2
+CONFIG_SYS_NS16550_MEM32=y
+CONFIG_ROCKCHIP_SFC=y
+CONFIG_SYSRESET=y
+# CONFIG_RSA is not set
+# CONFIG_SPL_SHA1 is not set
+# CONFIG_SPL_SHA256 is not set
+CONFIG_LZMA=y
+CONFIG_SPL_LZMA=y
+CONFIG_ERRNO_STR=y
diff --git a/doc/board/index.rst b/doc/board/index.rst
index 4103fef8d8f..2454c3598fb 100644
--- a/doc/board/index.rst
+++ b/doc/board/index.rst
@@ -46,6 +46,7 @@ Board-specific doc
    motorola/index
    nvidia/index
    nxp/index
+   onion/index
    openpiton/index
    ouya/index
    pegatron/index
diff --git a/doc/board/onion/index.rst b/doc/board/onion/index.rst
new file mode 100644
index 00000000000..2e106c8b773
--- /dev/null
+++ b/doc/board/onion/index.rst
@@ -0,0 +1,9 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+Onion
+=====
+
+.. toctree::
+   :maxdepth: 2
+
+   omega4-rv1103b
diff --git a/doc/board/onion/omega4-rv1103b.rst b/doc/board/onion/omega4-rv1103b.rst
new file mode 100644
index 00000000000..41c64f40d6c
--- /dev/null
+++ b/doc/board/onion/omega4-rv1103b.rst
@@ -0,0 +1,56 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+Onion Omega4 RV1103B board
+==========================
+
+U-Boot for the Onion Omega4 RV1103B board
+
+Quick Start
+-----------
+
+- Get the DDR initialization binary
+- Build U-Boot
+- Flash U-Boot into the SPI NAND
+
+Get the DDR initialization binary
+---------------------------------
+
+.. code-block:: bash
+
+   $ git clone https://github.com/rockchip-linux/rkbin.git
+
+The RV1103B DDR initialization is located at rkbin/bin/rv11/rv1103bb_ddr_924MHz_v1.05.bin
+
+Build U-Boot
+------------
+
+.. code-block:: bash
+
+   $ export CROSS_COMPILE=arm-linux-gnueabihf-
+   $ export ROCKCHIP_TPL=<path-to-rkbin>/bin/rv11/rv1103bb_ddr_924MHz_v1.05.bin
+   $ make omega4-rv1103b_defconfig
+   $ make
+
+The idbloader-spi.img and u-boot.img are the binaries that need to be flashed
+into the SPI NAND.
+
+Flash U-Boot into the SPI NAND
+------------------------------
+
+Connect the USB OTG and UART console cables from the Omega4 board to
+the host PC.
+
+Press the BOOT button while applying power to the board.
+
+The string "RKUART" should appear on the console (115200,8N1).
+
+Install the rkdeveloptool from https://github.com/rockchip-linux/rkdeveloptool
+by following the instruction in the README file.
+
+.. code-block:: bash
+
+   $ sudo ./rkdeveloptool db download.bin
+   $ sudo ./rkdeveloptool wl 0x200 idbloader.img
+   $ sudo ./rkdeveloptool wl 0xa00 u-boot.img
+
+Power cycle the board and U-Boot output is seen on the console.
diff --git a/doc/board/rockchip/rockchip.rst b/doc/board/rockchip/rockchip.rst
index a31ee7100b9..2574a1da52c 100644
--- a/doc/board/rockchip/rockchip.rst
+++ b/doc/board/rockchip/rockchip.rst
@@ -180,6 +180,9 @@ List of mainline supported Rockchip boards:
      - Yanyi Tech CoolPi CM5 EVB (coolpi-cm5-evb-rk3588)
      - Yanyi Tech CoolPi CM5 GenBook (coolpi-cm5-genbook-rk3588)
 
+* rv1103b
+     - Onion Omega4 (omega4-rv1103b), see :doc:`../onion/omega4-rv1103b`
+
 * rv1108
      - Rockchip Evb-rv1108 (evb-rv1108)
      - Elgin-R1 (elgin-rv1108)
diff --git a/include/configs/omega4_rv1103b.h b/include/configs/omega4_rv1103b.h
new file mode 100644
index 00000000000..8430b0b4d09
--- /dev/null
+++ b/include/configs/omega4_rv1103b.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2016 Rockchip Electronics Co., Ltd
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#include <configs/rv1103b_common.h>
+
+#endif
-- 
2.43.0


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

* [PATCH v3 09/15] tools: rkcommon: Add RV1106 support
  2026-07-07 15:30 [PATCH v3 00/15] rockchip: Add support for the RV1103B, RV1103 and RV1106 Simon Glass
                   ` (7 preceding siblings ...)
  2026-07-07 15:31 ` [PATCH v3 08/15] omega4-rv1103b: Add the initial support Simon Glass
@ 2026-07-07 15:31 ` Simon Glass
  2026-07-07 15:31 ` [PATCH v3 10/15] pinctrl: rockchip: " Simon Glass
                   ` (6 subsequent siblings)
  15 siblings, 0 replies; 21+ messages in thread
From: Simon Glass @ 2026-07-07 15:31 UTC (permalink / raw)
  To: u-boot
  Cc: Fabio Estevam, Jonas Karlman, Simon Glass, Ilias Apalodimas,
	Kever Yang, Neil Armstrong, Philipp Tomsich, Quentin Schulz,
	Tom Rini, Xuhui Lin

Add rv1106 to the list of supported SoCs. Like the RV1103B, it uses
the version-2 image header, for which the 4-byte header tag is unused.

The RV1103 is a package variant of the RV1106 and uses the same boot
image format, so this entry covers both

Signed-off-by: Simon Glass <sjg@chromium.org>
---

(no changes since v1)

 tools/rkcommon.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/tools/rkcommon.c b/tools/rkcommon.c
index 6f25a1cda31..06df57ec72d 100644
--- a/tools/rkcommon.c
+++ b/tools/rkcommon.c
@@ -154,6 +154,7 @@ static struct spl_info spl_infos[] = {
 	{ "rk3576", "RK35", 0x80000 - 0x1000, false, RK_HEADER_V2 },
 	{ "rk3588", "RK35", 0x100000 - 0x1000, false, RK_HEADER_V2 },
 	{ "rv1103b", "110E", 0x40000 - 0x1000, false, RK_HEADER_V2 },
+	{ "rv1106", "110C", 0x40000 - 0x1000, false, RK_HEADER_V2 },
 	{ "rv1108", "RK11", 0x1800, false, RK_HEADER_V1 },
 	{ "rv1126", "110B", 0x10000 - 0x1000, false, RK_HEADER_V1 },
 };
-- 
2.43.0


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

* [PATCH v3 10/15] pinctrl: rockchip: Add RV1106 support
  2026-07-07 15:30 [PATCH v3 00/15] rockchip: Add support for the RV1103B, RV1103 and RV1106 Simon Glass
                   ` (8 preceding siblings ...)
  2026-07-07 15:31 ` [PATCH v3 09/15] tools: rkcommon: Add RV1106 support Simon Glass
@ 2026-07-07 15:31 ` Simon Glass
  2026-07-07 15:31 ` [PATCH v3 11/15] ARM: dts: Add the RV1103/RV1106 devicetree files Simon Glass
                   ` (5 subsequent siblings)
  15 siblings, 0 replies; 21+ messages in thread
From: Simon Glass @ 2026-07-07 15:31 UTC (permalink / raw)
  To: u-boot
  Cc: Fabio Estevam, Jonas Karlman, Simon Glass, Jeffy Chen, Kever Yang,
	Philipp Tomsich, Tom Rini, Ye Zhang, huang lin

Add the pinctrl driver for the RV1106, based on the driver in the
Rockchip vendor tree, converted to use regmap_update_bits() so that
the pin configuration in the devicetree cannot overflow the register
fields.

The RV1103 is a package variant of the RV1106 and shares this driver.
Unlike most Rockchip SoCs, the GPIO0 IOC block lives in the PMU, so
the driver selects the PMU regmap for bank 0

Signed-off-by: Simon Glass <sjg@chromium.org>
---

(no changes since v1)

 drivers/pinctrl/rockchip/Makefile         |   1 +
 drivers/pinctrl/rockchip/pinctrl-rv1106.c | 320 ++++++++++++++++++++++
 2 files changed, 321 insertions(+)
 create mode 100644 drivers/pinctrl/rockchip/pinctrl-rv1106.c

diff --git a/drivers/pinctrl/rockchip/Makefile b/drivers/pinctrl/rockchip/Makefile
index b7ce6402ea3..6d7a2548af5 100644
--- a/drivers/pinctrl/rockchip/Makefile
+++ b/drivers/pinctrl/rockchip/Makefile
@@ -20,5 +20,6 @@ obj-$(CONFIG_ROCKCHIP_RK3568) += pinctrl-rk3568.o
 obj-$(CONFIG_ROCKCHIP_RK3576) += pinctrl-rk3576.o
 obj-$(CONFIG_ROCKCHIP_RK3588) += pinctrl-rk3588.o
 obj-$(CONFIG_ROCKCHIP_RV1103B) += pinctrl-rv1103b.o
+obj-$(CONFIG_ROCKCHIP_RV1106) += pinctrl-rv1106.o
 obj-$(CONFIG_ROCKCHIP_RV1108) += pinctrl-rv1108.o
 obj-$(CONFIG_ROCKCHIP_RV1126) += pinctrl-rv1126.o
diff --git a/drivers/pinctrl/rockchip/pinctrl-rv1106.c b/drivers/pinctrl/rockchip/pinctrl-rv1106.c
new file mode 100644
index 00000000000..5c3ad3ed09d
--- /dev/null
+++ b/drivers/pinctrl/rockchip/pinctrl-rv1106.c
@@ -0,0 +1,320 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2022 Rockchip Electronics Co., Ltd
+ */
+
+#include <dm.h>
+#include <log.h>
+#include <dm/pinctrl.h>
+#include <regmap.h>
+#include <syscon.h>
+#include <linux/bitops.h>
+
+#include "pinctrl-rockchip.h"
+
+static int rv1106_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
+{
+	struct rockchip_pinctrl_priv *priv = bank->priv;
+	int iomux_num = (pin / 8);
+	struct regmap *regmap;
+	u32 data, rmask;
+	int reg, mask;
+	u8 bit;
+
+	if (bank->iomux[iomux_num].type & IOMUX_SOURCE_PMU)
+		regmap = priv->regmap_pmu;
+	else
+		regmap = priv->regmap_base;
+
+	reg = bank->iomux[iomux_num].offset;
+	if ((pin % 8) >= 4)
+		reg += 0x4;
+	bit = (pin % 4) * 4;
+	mask = 0xf;
+
+	data = (mask << (bit + 16));
+	rmask = data | (data >> 16);
+	data |= (mux & mask) << bit;
+
+	return regmap_update_bits(regmap, reg, rmask, data);
+}
+
+#define RV1106_DRV_BITS_PER_PIN		8
+#define RV1106_DRV_PINS_PER_REG		2
+#define RV1106_DRV_GPIO0_OFFSET		0x10
+#define RV1106_DRV_GPIO1_OFFSET		0x80
+#define RV1106_DRV_GPIO2_OFFSET		0x100c0
+#define RV1106_DRV_GPIO3_OFFSET		0x20100
+#define RV1106_DRV_GPIO4_OFFSET		0x30020
+
+static int rv1106_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
+				       int pin_num, struct regmap **regmap,
+				       int *reg, u8 *bit)
+{
+	struct rockchip_pinctrl_priv *priv = bank->priv;
+
+	/* GPIO0_IOC is located in the PMU */
+	switch (bank->bank_num) {
+	case 0:
+		*regmap = priv->regmap_pmu;
+		*reg = RV1106_DRV_GPIO0_OFFSET;
+		break;
+	case 1:
+		*regmap = priv->regmap_base;
+		*reg = RV1106_DRV_GPIO1_OFFSET;
+		break;
+	case 2:
+		*regmap = priv->regmap_base;
+		*reg = RV1106_DRV_GPIO2_OFFSET;
+		break;
+	case 3:
+		*regmap = priv->regmap_base;
+		*reg = RV1106_DRV_GPIO3_OFFSET;
+		break;
+	case 4:
+		*regmap = priv->regmap_base;
+		*reg = RV1106_DRV_GPIO4_OFFSET;
+		break;
+	default:
+		printf("unsupported bank_num %d\n", bank->bank_num);
+		return -EINVAL;
+	}
+
+	*reg += ((pin_num / RV1106_DRV_PINS_PER_REG) * 4);
+	*bit = pin_num % RV1106_DRV_PINS_PER_REG;
+	*bit *= RV1106_DRV_BITS_PER_PIN;
+
+	return 0;
+}
+
+static int rv1106_set_drive(struct rockchip_pin_bank *bank,
+			    int pin_num, int strength)
+{
+	struct regmap *regmap;
+	int reg, ret;
+	u32 data, rmask;
+	u8 bit;
+	int drv = (1 << (strength + 1)) - 1;
+
+	ret = rv1106_calc_drv_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
+	if (ret)
+		return ret;
+
+	/* enable the write to the equivalent lower bits */
+	data = ((1 << RV1106_DRV_BITS_PER_PIN) - 1) << (bit + 16);
+	rmask = data | (data >> 16);
+	data |= (drv << bit);
+
+	return regmap_update_bits(regmap, reg, rmask, data);
+}
+
+#define RV1106_PULL_BITS_PER_PIN	2
+#define RV1106_PULL_PINS_PER_REG	8
+#define RV1106_PULL_GPIO0_OFFSET	0x38
+#define RV1106_PULL_GPIO1_OFFSET	0x1c0
+#define RV1106_PULL_GPIO2_OFFSET	0x101d0
+#define RV1106_PULL_GPIO3_OFFSET	0x201e0
+#define RV1106_PULL_GPIO4_OFFSET	0x30070
+
+static int rv1106_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
+					int pin_num, struct regmap **regmap,
+					int *reg, u8 *bit)
+{
+	struct rockchip_pinctrl_priv *priv = bank->priv;
+
+	/* GPIO0_IOC is located in the PMU */
+	switch (bank->bank_num) {
+	case 0:
+		*regmap = priv->regmap_pmu;
+		*reg = RV1106_PULL_GPIO0_OFFSET;
+		break;
+	case 1:
+		*regmap = priv->regmap_base;
+		*reg = RV1106_PULL_GPIO1_OFFSET;
+		break;
+	case 2:
+		*regmap = priv->regmap_base;
+		*reg = RV1106_PULL_GPIO2_OFFSET;
+		break;
+	case 3:
+		*regmap = priv->regmap_base;
+		*reg = RV1106_PULL_GPIO3_OFFSET;
+		break;
+	case 4:
+		*regmap = priv->regmap_base;
+		*reg = RV1106_PULL_GPIO4_OFFSET;
+		break;
+	default:
+		printf("unsupported bank_num %d\n", bank->bank_num);
+		return -EINVAL;
+	}
+
+	*reg += ((pin_num / RV1106_PULL_PINS_PER_REG) * 4);
+	*bit = pin_num % RV1106_PULL_PINS_PER_REG;
+	*bit *= RV1106_PULL_BITS_PER_PIN;
+
+	return 0;
+}
+
+static int rv1106_set_pull(struct rockchip_pin_bank *bank,
+			   int pin_num, int pull)
+{
+	struct regmap *regmap;
+	int reg, ret;
+	u8 bit, type;
+	u32 data, rmask;
+
+	if (pull == PIN_CONFIG_BIAS_PULL_PIN_DEFAULT)
+		return -ENOTSUPP;
+
+	ret = rv1106_calc_pull_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
+	if (ret)
+		return ret;
+
+	type = bank->pull_type[pin_num / 8];
+	ret = rockchip_translate_pull_value(type, pull);
+	if (ret < 0) {
+		debug("unsupported pull setting %d\n", pull);
+		return ret;
+	}
+
+	/* enable the write to the equivalent lower bits */
+	data = ((1 << RV1106_PULL_BITS_PER_PIN) - 1) << (bit + 16);
+	rmask = data | (data >> 16);
+	data |= (ret << bit);
+
+	return regmap_update_bits(regmap, reg, rmask, data);
+}
+
+#define RV1106_SMT_BITS_PER_PIN		1
+#define RV1106_SMT_PINS_PER_REG		8
+#define RV1106_SMT_GPIO0_OFFSET		0x40
+#define RV1106_SMT_GPIO1_OFFSET		0x280
+#define RV1106_SMT_GPIO2_OFFSET		0x10290
+#define RV1106_SMT_GPIO3_OFFSET		0x202a0
+#define RV1106_SMT_GPIO4_OFFSET		0x300a0
+
+static int rv1106_calc_schmitt_reg_and_bit(struct rockchip_pin_bank *bank,
+					   int pin_num,
+					   struct regmap **regmap,
+					   int *reg, u8 *bit)
+{
+	struct rockchip_pinctrl_priv *priv = bank->priv;
+
+	/* GPIO0_IOC is located in the PMU */
+	switch (bank->bank_num) {
+	case 0:
+		*regmap = priv->regmap_pmu;
+		*reg = RV1106_SMT_GPIO0_OFFSET;
+		break;
+	case 1:
+		*regmap = priv->regmap_base;
+		*reg = RV1106_SMT_GPIO1_OFFSET;
+		break;
+	case 2:
+		*regmap = priv->regmap_base;
+		*reg = RV1106_SMT_GPIO2_OFFSET;
+		break;
+	case 3:
+		*regmap = priv->regmap_base;
+		*reg = RV1106_SMT_GPIO3_OFFSET;
+		break;
+	case 4:
+		*regmap = priv->regmap_base;
+		*reg = RV1106_SMT_GPIO4_OFFSET;
+		break;
+	default:
+		printf("unsupported bank_num %d\n", bank->bank_num);
+		return -EINVAL;
+	}
+
+	*reg += ((pin_num / RV1106_SMT_PINS_PER_REG) * 4);
+	*bit = pin_num % RV1106_SMT_PINS_PER_REG;
+	*bit *= RV1106_SMT_BITS_PER_PIN;
+
+	return 0;
+}
+
+static int rv1106_set_schmitt(struct rockchip_pin_bank *bank,
+			      int pin_num, int enable)
+{
+	struct regmap *regmap;
+	int reg, ret;
+	u32 data, rmask;
+	u8 bit;
+
+	ret = rv1106_calc_schmitt_reg_and_bit(bank, pin_num, &regmap, &reg,
+					      &bit);
+	if (ret)
+		return ret;
+
+	/* enable the write to the equivalent lower bits */
+	data = ((1 << RV1106_SMT_BITS_PER_PIN) - 1) << (bit + 16);
+	rmask = data | (data >> 16);
+	data |= (enable << bit);
+
+	return regmap_update_bits(regmap, reg, rmask, data);
+}
+
+static struct rockchip_pin_bank rv1106_pin_banks[] = {
+	PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0",
+			     IOMUX_WIDTH_4BIT | IOMUX_SOURCE_PMU,
+			     IOMUX_WIDTH_4BIT | IOMUX_SOURCE_PMU,
+			     IOMUX_WIDTH_4BIT | IOMUX_SOURCE_PMU,
+			     IOMUX_WIDTH_4BIT | IOMUX_SOURCE_PMU),
+	PIN_BANK_IOMUX_FLAGS_OFFSET(1, 32, "gpio1",
+				    IOMUX_WIDTH_4BIT,
+				    IOMUX_WIDTH_4BIT,
+				    IOMUX_WIDTH_4BIT,
+				    IOMUX_WIDTH_4BIT,
+				    0, 0x08, 0x10, 0x18),
+	PIN_BANK_IOMUX_FLAGS_OFFSET(2, 32, "gpio2",
+				    IOMUX_WIDTH_4BIT,
+				    IOMUX_WIDTH_4BIT,
+				    IOMUX_WIDTH_4BIT,
+				    IOMUX_WIDTH_4BIT,
+				    0x10020, 0x10028, 0, 0),
+	PIN_BANK_IOMUX_FLAGS_OFFSET(3, 32, "gpio3",
+				    IOMUX_WIDTH_4BIT,
+				    IOMUX_WIDTH_4BIT,
+				    IOMUX_WIDTH_4BIT,
+				    IOMUX_WIDTH_4BIT,
+				    0x20040, 0x20048, 0x20050, 0x20058),
+	PIN_BANK_IOMUX_FLAGS_OFFSET(4, 24, "gpio4",
+				    IOMUX_WIDTH_4BIT,
+				    IOMUX_WIDTH_4BIT,
+				    IOMUX_WIDTH_4BIT,
+				    0,
+				    0x30000, 0x30008, 0x30010, 0),
+};
+
+static const struct rockchip_pin_ctrl rv1106_pin_ctrl = {
+	.pin_banks		= rv1106_pin_banks,
+	.nr_banks		= ARRAY_SIZE(rv1106_pin_banks),
+	.grf_mux_offset		= 0x0,
+	.pmu_mux_offset		= 0x0,
+	.set_mux		= rv1106_set_mux,
+	.set_pull		= rv1106_set_pull,
+	.set_drive		= rv1106_set_drive,
+	.set_schmitt		= rv1106_set_schmitt,
+};
+
+static const struct udevice_id rv1106_pinctrl_ids[] = {
+	{
+		.compatible = "rockchip,rv1106-pinctrl",
+		.data = (ulong)&rv1106_pin_ctrl
+	},
+	{ }
+};
+
+U_BOOT_DRIVER(pinctrl_rv1106) = {
+	.name		= "rockchip_rv1106_pinctrl",
+	.id		= UCLASS_PINCTRL,
+	.of_match	= rv1106_pinctrl_ids,
+	.priv_auto	= sizeof(struct rockchip_pinctrl_priv),
+	.ops		= &rockchip_pinctrl_ops,
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
+	.bind		= dm_scan_fdt_dev,
+#endif
+	.probe		= rockchip_pinctrl_probe,
+};
-- 
2.43.0


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

* [PATCH v3 11/15] ARM: dts: Add the RV1103/RV1106 devicetree files
  2026-07-07 15:30 [PATCH v3 00/15] rockchip: Add support for the RV1103B, RV1103 and RV1106 Simon Glass
                   ` (9 preceding siblings ...)
  2026-07-07 15:31 ` [PATCH v3 10/15] pinctrl: rockchip: " Simon Glass
@ 2026-07-07 15:31 ` Simon Glass
  2026-07-07 15:31 ` [PATCH v3 12/15] clk: rockchip: Add RV1106 clock driver Simon Glass
                   ` (4 subsequent siblings)
  15 siblings, 0 replies; 21+ messages in thread
From: Simon Glass @ 2026-07-07 15:31 UTC (permalink / raw)
  To: u-boot
  Cc: Fabio Estevam, Jonas Karlman, Simon Glass, Albert Aribaud,
	Ilias Apalodimas, Kever Yang, Philipp Tomsich, Tom Rini

Add the SoC devicetree files for the Rockchip RV1106 and its RV1103
package variant, based on the devicetrees in the Rockchip vendor tree,
trimmed to the devices that U-Boot supports.

The files come from the Luckfox Pico SDK [1] at commit 824b817f8:
rv1106-pinctrl.dtsi and the rv1106-cru.h binding header are verbatim
copies from its U-Boot tree (2017.09-based, with only the pinconf
include path adjusted), rv1106.dtsi is a trimmed version of the same
tree's file with the camera, codec and other vendor-only nodes
removed, and rv1103.dtsi follows the pattern of the corresponding
file in its kernel tree (Linux 5.10.160).

Neither SoC is supported in mainline Linux and no support is in
review, so there are no upstream devicetrees to inherit. Once Linux
gains RV1106 devicetrees, the OF_UPSTREAM mechanism can be enabled and
these files dropped.

[1] https://github.com/LuckfoxTECH/luckfox-pico

Signed-off-by: Simon Glass <sjg@chromium.org>
---

(no changes since v1)

 arch/arm/dts/rv1103.dtsi               |   16 +
 arch/arm/dts/rv1106-pinctrl.dtsi       | 1102 ++++++++++++++++++++++++
 arch/arm/dts/rv1106.dtsi               |  328 +++++++
 include/dt-bindings/clock/rv1106-cru.h |  572 ++++++++++++
 4 files changed, 2018 insertions(+)
 create mode 100644 arch/arm/dts/rv1103.dtsi
 create mode 100644 arch/arm/dts/rv1106-pinctrl.dtsi
 create mode 100644 arch/arm/dts/rv1106.dtsi
 create mode 100644 include/dt-bindings/clock/rv1106-cru.h

diff --git a/arch/arm/dts/rv1103.dtsi b/arch/arm/dts/rv1103.dtsi
new file mode 100644
index 00000000000..025fde5bf09
--- /dev/null
+++ b/arch/arm/dts/rv1103.dtsi
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2022 Rockchip Electronics Co., Ltd.
+ */
+
+#include "rv1106.dtsi"
+
+/ {
+	compatible = "rockchip,rv1103";
+
+	aliases {
+		/delete-property/ gpio2;
+	};
+};
+
+/delete-node/ &gpio2;
diff --git a/arch/arm/dts/rv1106-pinctrl.dtsi b/arch/arm/dts/rv1106-pinctrl.dtsi
new file mode 100644
index 00000000000..8338556dafd
--- /dev/null
+++ b/arch/arm/dts/rv1106-pinctrl.dtsi
@@ -0,0 +1,1102 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2022 Rockchip Electronics Co., Ltd.
+ */
+
+#include <dt-bindings/pinctrl/rockchip.h>
+#include <arm64/rockchip/rockchip-pinconf.dtsi>
+
+/*
+ * This file is auto generated by pin2dts tool, please keep these code
+ * by adding changes at end of this file.
+ */
+&pinctrl {
+	adc {
+		adc_pins: adc-pins {
+			rockchip,pins =
+				/* adc_in0 */
+				<4 RK_PC0 1 &pcfg_pull_none>,
+				/* adc_in1 */
+				<4 RK_PC1 1 &pcfg_pull_none>;
+		};
+	};
+
+	avs {
+		avs_pins: avs-pins {
+			rockchip,pins =
+				/* avs_arm */
+				<1 RK_PA2 2 &pcfg_pull_none>;
+		};
+	};
+
+	clk {
+		clk_32k: clk-32k {
+			rockchip,pins =
+				/* clk_32k */
+				<0 RK_PA0 2 &pcfg_pull_none>;
+		};
+		clk_refout: clk-refout {
+			rockchip,pins =
+				/* clk_refout */
+				<0 RK_PA0 3 &pcfg_pull_none>;
+		};
+	};
+
+	dsmaudio {
+		dsmaudio_pins: dsmaudio-pins {
+			rockchip,pins =
+				/* dsmaudio_n */
+				<1 RK_PD3 7 &pcfg_pull_none>,
+				/* dsmaudio_p */
+				<1 RK_PD2 7 &pcfg_pull_none>;
+		};
+	};
+
+	emmc {
+		emmc_bus8: emmc-bus8 {
+			rockchip,pins =
+				/* emmc_d0 */
+				<4 RK_PA4 1 &pcfg_pull_up_drv_level_2>,
+				/* emmc_d1 */
+				<4 RK_PA3 1 &pcfg_pull_up_drv_level_2>,
+				/* emmc_d2 */
+				<4 RK_PA2 1 &pcfg_pull_up_drv_level_2>,
+				/* emmc_d3 */
+				<4 RK_PA6 1 &pcfg_pull_up_drv_level_2>,
+				/* emmc_d4 */
+				<4 RK_PA5 1 &pcfg_pull_up_drv_level_2>,
+				/* emmc_d5 */
+				<4 RK_PA7 1 &pcfg_pull_up_drv_level_2>,
+				/* emmc_d6 */
+				<4 RK_PA1 1 &pcfg_pull_up_drv_level_2>,
+				/* emmc_d7 */
+				<4 RK_PA0 1 &pcfg_pull_up_drv_level_2>;
+		};
+
+		emmc_clk: emmc-clk {
+			rockchip,pins =
+				/* emmc_clk */
+				<4 RK_PB1 1 &pcfg_pull_up_drv_level_2>;
+		};
+
+		emmc_cmd: emmc-cmd {
+			rockchip,pins =
+				/* emmc_cmd */
+				<4 RK_PB0 1 &pcfg_pull_up_drv_level_2>;
+		};
+	};
+
+	flash {
+		flash_pins: flash-pins {
+			rockchip,pins =
+				/* flash_trig_out */
+				<2 RK_PA6 6 &pcfg_pull_none>;
+		};
+	};
+
+	fspi {
+		fspi_pins: fspi-pins {
+			rockchip,pins =
+				/* fspi_clk */
+				<4 RK_PB1 2 &pcfg_pull_up_drv_level_2>,
+				/* fspi_d0 */
+				<4 RK_PA4 2 &pcfg_pull_none>,
+				/* fspi_d1 */
+				<4 RK_PA3 2 &pcfg_pull_none>,
+				/* fspi_d2 */
+				<4 RK_PA2 2 &pcfg_pull_none>,
+				/* fspi_d3 */
+				<4 RK_PA6 2 &pcfg_pull_none>;
+		};
+
+		fspi_cs0: fspi-cs0 {
+			rockchip,pins =
+				/* fspi_cs0n */
+				<4 RK_PB0 2 &pcfg_pull_up>;
+		};
+	};
+
+	hpmcu {
+		hpmcum0_pins: hpmcum0-pins {
+			rockchip,pins =
+				/* hpmcu_jtag_tck_m0 */
+				<1 RK_PB2 3 &pcfg_pull_none>,
+				/* hpmcu_jtag_tms_m0 */
+				<1 RK_PB3 3 &pcfg_pull_none>;
+		};
+
+		hpmcum1_pins: hpmcum1-pins {
+			rockchip,pins =
+				/* hpmcu_jtag_tck_m1 */
+				<3 RK_PA7 4 &pcfg_pull_none>,
+				/* hpmcu_jtag_tms_m1 */
+				<3 RK_PA6 4 &pcfg_pull_none>;
+		};
+	};
+
+	i2c0 {
+		i2c0m0_xfer: i2c0m0-xfer {
+			rockchip,pins =
+				/* i2c0_scl_m0 */
+				<1 RK_PA3 2 &pcfg_pull_none_smt>,
+				/* i2c0_sda_m0 */
+				<1 RK_PA4 2 &pcfg_pull_none_smt>;
+		};
+
+		i2c0m1_xfer: i2c0m1-xfer {
+			rockchip,pins =
+				/* i2c0_scl_m1 */
+				<4 RK_PA1 4 &pcfg_pull_none_smt>,
+				/* i2c0_sda_m1 */
+				<4 RK_PA0 4 &pcfg_pull_none_smt>;
+		};
+
+		i2c0m2_xfer: i2c0m2-xfer {
+			rockchip,pins =
+				/* i2c0_scl_m2 */
+				<3 RK_PA4 3 &pcfg_pull_none_smt>,
+				/* i2c0_sda_m2 */
+				<3 RK_PA5 3 &pcfg_pull_none_smt>;
+		};
+	};
+
+	i2c1 {
+		i2c1m0_xfer: i2c1m0-xfer {
+			rockchip,pins =
+				/* i2c1_scl_m0 */
+				<0 RK_PA5 1 &pcfg_pull_none_smt>,
+				/* i2c1_sda_m0 */
+				<0 RK_PA6 1 &pcfg_pull_none_smt>;
+		};
+
+		i2c1m1_xfer: i2c1m1-xfer {
+			rockchip,pins =
+				/* i2c1_scl_m1 */
+				<2 RK_PB0 2 &pcfg_pull_none_smt>,
+				/* i2c1_sda_m1 */
+				<2 RK_PB1 2 &pcfg_pull_none_smt>;
+		};
+	};
+
+	i2c2 {
+		i2c2m0_xfer: i2c2m0-xfer {
+			rockchip,pins =
+				/* i2c2_scl_m0 */
+				<1 RK_PA0 2 &pcfg_pull_none_smt>,
+				/* i2c2_sda_m0 */
+				<1 RK_PA1 2 &pcfg_pull_none_smt>;
+		};
+
+		i2c2m1_xfer: i2c2m1-xfer {
+			rockchip,pins =
+				/* i2c2_scl_m1 */
+				<4 RK_PA7 4 &pcfg_pull_none_smt>,
+				/* i2c2_sda_m1 */
+				<4 RK_PA5 4 &pcfg_pull_none_smt>;
+		};
+	};
+
+	i2c3 {
+		i2c3m0_xfer: i2c3m0-xfer {
+			rockchip,pins =
+				/* i2c3_scl_m0 */
+				<2 RK_PA6 5 &pcfg_pull_none_smt>,
+				/* i2c3_sda_m0 */
+				<2 RK_PA7 5 &pcfg_pull_none_smt>;
+		};
+
+		i2c3m1_xfer: i2c3m1-xfer {
+			rockchip,pins =
+				/* i2c3_scl_m1 */
+				<1 RK_PD3 3 &pcfg_pull_none_smt>,
+				/* i2c3_sda_m1 */
+				<1 RK_PD2 3 &pcfg_pull_none_smt>;
+		};
+
+		i2c3m2_xfer: i2c3m2-xfer {
+			rockchip,pins =
+				/* i2c3_scl_m2 */
+				<3 RK_PD1 3 &pcfg_pull_none_smt>,
+				/* i2c3_sda_m2 */
+				<3 RK_PD2 3 &pcfg_pull_none_smt>;
+		};
+	};
+
+	i2c4 {
+		i2c4m0_xfer: i2c4m0-xfer {
+			rockchip,pins =
+				/* i2c4_scl_m0 */
+				<2 RK_PA1 5 &pcfg_pull_none_smt>,
+				/* i2c4_sda_m0 */
+				<2 RK_PA0 5 &pcfg_pull_none_smt>;
+		};
+
+		i2c4m1_xfer: i2c4m1-xfer {
+			rockchip,pins =
+				/* i2c4_scl_m1 */
+				<1 RK_PC2 4 &pcfg_pull_none_smt>,
+				/* i2c4_sda_m1 */
+				<1 RK_PC3 4 &pcfg_pull_none_smt>;
+		};
+
+		i2c4m2_xfer: i2c4m2-xfer {
+			rockchip,pins =
+				/* i2c4_scl_m2 */
+				<3 RK_PC7 3 &pcfg_pull_none_smt>,
+				/* i2c4_sda_m2 */
+				<3 RK_PD0 3 &pcfg_pull_none_smt>;
+		};
+	};
+
+	i2s0 {
+		i2s0_pins: i2s0-pins {
+			rockchip,pins =
+				/* i2s0_lrck */
+				<2 RK_PA1 2 &pcfg_pull_none>,
+				/* i2s0_mclk */
+				<2 RK_PA2 2 &pcfg_pull_none>,
+				/* i2s0_sclk */
+				<2 RK_PA0 2 &pcfg_pull_none>,
+				/* i2s0_sdi0 */
+				<2 RK_PA5 2 &pcfg_pull_none>,
+				/* i2s0_sdo0 */
+				<2 RK_PA4 2 &pcfg_pull_none>,
+				/* i2s0_sdo1_sdi3 */
+				<2 RK_PA7 2 &pcfg_pull_none>,
+				/* i2s0_sdo2_sdi2 */
+				<2 RK_PA6 2 &pcfg_pull_none>,
+				/* i2s0_sdo3_sdi1 */
+				<2 RK_PA3 2 &pcfg_pull_none>;
+		};
+	};
+
+	lcd {
+		lcd_pins: lcd-pins {
+			rockchip,pins =
+				/* lcd_clk */
+				<1 RK_PD3 1 &pcfg_pull_none>,
+				/* lcd_d0 */
+				<1 RK_PC7 1 &pcfg_pull_none>,
+				/* lcd_d1 */
+				<1 RK_PC6 1 &pcfg_pull_none>,
+				/* lcd_d2 */
+				<1 RK_PC5 1 &pcfg_pull_none>,
+				/* lcd_d3 */
+				<1 RK_PC4 1 &pcfg_pull_none>,
+				/* lcd_d4 */
+				<1 RK_PC3 1 &pcfg_pull_none>,
+				/* lcd_d5 */
+				<1 RK_PC2 1 &pcfg_pull_none>,
+				/* lcd_d6 */
+				<1 RK_PC1 1 &pcfg_pull_none>,
+				/* lcd_d7 */
+				<1 RK_PC0 1 &pcfg_pull_none>,
+				/* lcd_d8 */
+				<2 RK_PA0 3 &pcfg_pull_none>,
+				/* lcd_d9 */
+				<2 RK_PA1 3 &pcfg_pull_none>,
+				/* lcd_d10 */
+				<2 RK_PA2 3 &pcfg_pull_none>,
+				/* lcd_d11 */
+				<2 RK_PA3 3 &pcfg_pull_none>,
+				/* lcd_d12 */
+				<2 RK_PA4 3 &pcfg_pull_none>,
+				/* lcd_d13 */
+				<2 RK_PA5 3 &pcfg_pull_none>,
+				/* lcd_d14 */
+				<2 RK_PA6 3 &pcfg_pull_none>,
+				/* lcd_d15 */
+				<2 RK_PA7 3 &pcfg_pull_none>,
+				/* lcd_d16 */
+				<2 RK_PB0 3 &pcfg_pull_none>,
+				/* lcd_d17 */
+				<2 RK_PB1 3 &pcfg_pull_none>,
+				/* lcd_den */
+				<1 RK_PD0 1 &pcfg_pull_none>,
+				/* lcd_hsync */
+				<1 RK_PD1 1 &pcfg_pull_none>,
+				/* lcd_vsync */
+				<1 RK_PD2 1 &pcfg_pull_none>;
+		};
+	};
+
+	lpmcu {
+		lpmcum0_pins: lpmcum0-pins {
+			rockchip,pins =
+				/* lpmcu_jtag_tck_m0 */
+				<1 RK_PB2 4 &pcfg_pull_none>,
+				/* lpmcu_jtag_tms_m0 */
+				<1 RK_PB3 4 &pcfg_pull_none>;
+		};
+
+		lpmcum1_pins: lpmcum1-pins {
+			rockchip,pins =
+				/* lpmcu_jtag_tck_m1 */
+				<3 RK_PA4 4 &pcfg_pull_none>,
+				/* lpmcu_jtag_tms_m1 */
+				<3 RK_PA5 4 &pcfg_pull_none>;
+		};
+	};
+
+	mipi {
+		mipi_pins: mipi-pins {
+			rockchip,pins =
+				/* mipi_lvds_ck0n */
+				<3 RK_PC0 2 &pcfg_pull_none>,
+				/* mipi_lvds_ck0p */
+				<3 RK_PC1 2 &pcfg_pull_none>,
+				/* mipi_lvds_ck1n */
+				<3 RK_PB2 2 &pcfg_pull_none>,
+				/* mipi_lvds_ck1p */
+				<3 RK_PB3 2 &pcfg_pull_none>,
+				/* mipi_lvds_d0n */
+				<3 RK_PC2 2 &pcfg_pull_none>,
+				/* mipi_lvds_d0p */
+				<3 RK_PC3 2 &pcfg_pull_none>,
+				/* mipi_lvds_d1n */
+				<3 RK_PB6 2 &pcfg_pull_none>,
+				/* mipi_lvds_d1p */
+				<3 RK_PB7 2 &pcfg_pull_none>,
+				/* mipi_lvds_d2n */
+				<3 RK_PB4 2 &pcfg_pull_none>,
+				/* mipi_lvds_d2p */
+				<3 RK_PB5 2 &pcfg_pull_none>,
+				/* mipi_lvds_d3n */
+				<3 RK_PB0 2 &pcfg_pull_none>,
+				/* mipi_lvds_d3p */
+				<3 RK_PB1 2 &pcfg_pull_none>,
+				/* mipi_refclk_out0 */
+				<3 RK_PC4 2 &pcfg_pull_none>,
+				/* mipi_refclk_out1 */
+				<3 RK_PC6 3 &pcfg_pull_none>;
+		};
+	};
+
+	pmic {
+		pmicm0_pins: pmicm0-pins {
+			rockchip,pins =
+				/* pmic_sleep_m0 */
+				<0 RK_PA4 1 &pcfg_pull_none>;
+		};
+
+		pmicm1_pins: pmicm1-pins {
+			rockchip,pins =
+				/* pmic_sleep_m1 */
+				<0 RK_PA3 1 &pcfg_pull_none>;
+		};
+	};
+
+	pmu {
+		pmu_pins: pmu-pins {
+			rockchip,pins =
+				/* pmu_debug */
+				<1 RK_PA1 3 &pcfg_pull_none>;
+		};
+	};
+
+	prelight {
+		prelight_pins: prelight-pins {
+			rockchip,pins =
+				/* prelight_trig_out */
+				<2 RK_PA7 6 &pcfg_pull_none>;
+		};
+	};
+
+	pwm0 {
+		pwm0m0_pins: pwm0m0-pins {
+			rockchip,pins =
+				/* pwm0_m0 */
+				<1 RK_PA2 1 &pcfg_pull_none>;
+		};
+
+		pwm0m1_pins: pwm0m1-pins {
+			rockchip,pins =
+				/* pwm0_m1 */
+				<1 RK_PD2 6 &pcfg_pull_none>;
+		};
+	};
+
+	pwm1 {
+		pwm1m0_pins: pwm1m0-pins {
+			rockchip,pins =
+				/* pwm1_m0 */
+				<0 RK_PA4 2 &pcfg_pull_none>;
+		};
+
+		pwm1m1_pins: pwm1m1-pins {
+			rockchip,pins =
+				/* pwm1_m1 */
+				<4 RK_PC1 2 &pcfg_pull_none>;
+		};
+
+		pwm1m2_pins: pwm1m2-pins {
+			rockchip,pins =
+				/* pwm1_m2 */
+				<3 RK_PD3 2 &pcfg_pull_none>;
+		};
+	};
+
+	pwm2 {
+		pwm2m0_pins: pwm2m0-pins {
+			rockchip,pins =
+				/* pwm2_m0 */
+				<0 RK_PA1 2 &pcfg_pull_none>;
+		};
+
+		pwm2m1_pins: pwm2m1-pins {
+			rockchip,pins =
+				/* pwm2_m1 */
+				<2 RK_PA6 4 &pcfg_pull_none>;
+		};
+
+		pwm2m2_pins: pwm2m2-pins {
+			rockchip,pins =
+				/* pwm2_m2 */
+				<1 RK_PC0 3 &pcfg_pull_none>;
+		};
+	};
+
+	pwm3 {
+		pwm3m0_pins: pwm3m0-pins {
+			rockchip,pins =
+				/* pwm3_ir_m0 */
+				<0 RK_PA2 1 &pcfg_pull_none>;
+		};
+
+		pwm3m1_pins: pwm3m1-pins {
+			rockchip,pins =
+				/* pwm3_ir_m1 */
+				<1 RK_PB0 2 &pcfg_pull_none>;
+		};
+
+		pwm3m2_pins: pwm3m2-pins {
+			rockchip,pins =
+				/* pwm3_ir_m2 */
+				<1 RK_PD0 3 &pcfg_pull_none>;
+		};
+	};
+
+	pwm4 {
+		pwm4m0_pins: pwm4m0-pins {
+			rockchip,pins =
+				/* pwm4_m0 */
+				<1 RK_PA1 4 &pcfg_pull_none>;
+		};
+
+		pwm4m1_pins: pwm4m1-pins {
+			rockchip,pins =
+				/* pwm4_m1 */
+				<2 RK_PA7 4 &pcfg_pull_none>;
+		};
+
+		pwm4m2_pins: pwm4m2-pins {
+			rockchip,pins =
+				/* pwm4_m2 */
+				<1 RK_PC1 3 &pcfg_pull_none>;
+		};
+	};
+
+	pwm5 {
+		pwm5m0_pins: pwm5m0-pins {
+			rockchip,pins =
+				/* pwm5_m0 */
+				<0 RK_PA5 3 &pcfg_pull_none>;
+		};
+
+		pwm5m1_pins: pwm5m1-pins {
+			rockchip,pins =
+				/* pwm5_m1 */
+				<2 RK_PB0 4 &pcfg_pull_none>;
+		};
+
+		pwm5m2_pins: pwm5m2-pins {
+			rockchip,pins =
+				/* pwm5_m2 */
+				<1 RK_PC2 3 &pcfg_pull_none>;
+		};
+	};
+
+	pwm6 {
+		pwm6m0_pins: pwm6m0-pins {
+			rockchip,pins =
+				/* pwm6_m0 */
+				<0 RK_PA6 3 &pcfg_pull_none>;
+		};
+
+		pwm6m1_pins: pwm6m1-pins {
+			rockchip,pins =
+				/* pwm6_m1 */
+				<2 RK_PB1 4 &pcfg_pull_none>;
+		};
+
+		pwm6m2_pins: pwm6m2-pins {
+			rockchip,pins =
+				/* pwm6_m2 */
+				<1 RK_PC3 3 &pcfg_pull_none>;
+		};
+	};
+
+	pwm7 {
+		pwm7m0_pins: pwm7m0-pins {
+			rockchip,pins =
+				/* pwm7_ir_m0 */
+				<1 RK_PA0 3 &pcfg_pull_none>;
+		};
+
+		pwm7m1_pins: pwm7m1-pins {
+			rockchip,pins =
+				/* pwm7_ir_m1 */
+				<1 RK_PB1 2 &pcfg_pull_none>;
+		};
+
+		pwm7m2_pins: pwm7m2-pins {
+			rockchip,pins =
+				/* pwm7_ir_m2 */
+				<3 RK_PC6 2 &pcfg_pull_none>;
+		};
+	};
+
+	pwm8 {
+		pwm8m0_pins: pwm8m0-pins {
+			rockchip,pins =
+				/* pwm8_m0 */
+				<3 RK_PA3 4 &pcfg_pull_none>;
+		};
+
+		pwm8m1_pins: pwm8m1-pins {
+			rockchip,pins =
+				/* pwm8_m1 */
+				<1 RK_PC4 3 &pcfg_pull_none>;
+		};
+	};
+
+	pwm9 {
+		pwm9m0_pins: pwm9m0-pins {
+			rockchip,pins =
+				/* pwm9_m0 */
+				<3 RK_PA2 4 &pcfg_pull_none>;
+		};
+
+		pwm9m1_pins: pwm9m1-pins {
+			rockchip,pins =
+				/* pwm9_m1 */
+				<1 RK_PC5 3 &pcfg_pull_none>;
+		};
+	};
+
+	pwm10 {
+		pwm10m0_pins: pwm10m0-pins {
+			rockchip,pins =
+				/* pwm10_m0 */
+				<3 RK_PA4 5 &pcfg_pull_none>;
+		};
+
+		pwm10m1_pins: pwm10m1-pins {
+			rockchip,pins =
+				/* pwm10_m1 */
+				<1 RK_PC6 3 &pcfg_pull_none>;
+		};
+
+		pwm10m2_pins: pwm10m2-pins {
+			rockchip,pins =
+				/* pwm10_m2 */
+				<1 RK_PD1 3 &pcfg_pull_none>;
+		};
+	};
+
+	pwm11 {
+		pwm11m0_pins: pwm11m0-pins {
+			rockchip,pins =
+				/* pwm11_ir_m0 */
+				<3 RK_PA5 5 &pcfg_pull_none>;
+		};
+
+		pwm11m1_pins: pwm11m1-pins {
+			rockchip,pins =
+				/* pwm11_ir_m1 */
+				<1 RK_PC7 3 &pcfg_pull_none>;
+		};
+
+		pwm11m2_pins: pwm11m2-pins {
+			rockchip,pins =
+				/* pwm11_ir_m2 */
+				<1 RK_PD3 5 &pcfg_pull_none>;
+		};
+	};
+
+	rtc {
+		rtc_pins: rtc-pins {
+			rockchip,pins =
+				/* rtc_clko */
+				<0 RK_PA0 4 &pcfg_pull_none>;
+		};
+	};
+
+	sdmmc0: sdmmc0 {
+		sdmmc0_bus4: sdmmc0-bus4 {
+			rockchip,pins =
+				/* sdmmc0_d0 */
+				<3 RK_PA3 1 &pcfg_pull_up_drv_level_2>,
+				/* sdmmc0_d1 */
+				<3 RK_PA2 1 &pcfg_pull_up_drv_level_2>,
+				/* sdmmc0_d2 */
+				<3 RK_PA7 1 &pcfg_pull_up_drv_level_2>,
+				/* sdmmc0_d3 */
+				<3 RK_PA6 1 &pcfg_pull_up_drv_level_2>;
+		};
+
+		sdmmc0_clk: sdmmc0-clk {
+			rockchip,pins =
+				/* sdmmc0_clk */
+				<3 RK_PA4 1 &pcfg_pull_up_drv_level_2>;
+		};
+
+		sdmmc0_cmd: sdmmc0-cmd {
+			rockchip,pins =
+				/* sdmmc0_cmd */
+				<3 RK_PA5 1 &pcfg_pull_up_drv_level_2>;
+		};
+
+		sdmmc0_det: sdmmc0-det {
+			rockchip,pins =
+				/* sdmmc0_det */
+				<3 RK_PA1 1 &pcfg_pull_up>;
+		};
+
+		sdmmc0_idle_pins: sdmmc0-idle-pins {
+			rockchip,pins =
+				/* sdmmc0_d0 */
+				<3 RK_PA3 1 &pcfg_pull_down>,
+				/* sdmmc0_d1 */
+				<3 RK_PA2 1 &pcfg_pull_down>,
+				/* sdmmc0_d2 */
+				<3 RK_PA7 1 &pcfg_pull_down>,
+				/* sdmmc0_d3 */
+				<3 RK_PA6 1 &pcfg_pull_down>,
+				/* sdmmc0_clk */
+				<3 RK_PA4 1 &pcfg_pull_down>,
+				/* sdmmc0_cmd */
+				<3 RK_PA5 1 &pcfg_pull_down>;
+		};
+	};
+
+	sdmmc1 {
+		sdmmc1m0_bus4: sdmmc1m0-bus4 {
+			rockchip,pins =
+				/* sdmmc1_d0_m0 */
+				<2 RK_PA1 1 &pcfg_pull_up_drv_level_2>,
+				/* sdmmc1_d1_m0 */
+				<2 RK_PA0 1 &pcfg_pull_up_drv_level_2>,
+				/* sdmmc1_d2_m0 */
+				<2 RK_PA5 1 &pcfg_pull_up_drv_level_2>,
+				/* sdmmc1_d3_m0 */
+				<2 RK_PA4 1 &pcfg_pull_up_drv_level_2>;
+		};
+
+		sdmmc1m0_clk: sdmmc1m0-clk {
+			rockchip,pins =
+				/* sdmmc1_clk_m0 */
+				<2 RK_PA2 1 &pcfg_pull_up_drv_level_2>;
+		};
+
+		sdmmc1m0_cmd: sdmmc1m0-cmd {
+			rockchip,pins =
+				/* sdmmc1_cmd_m0 */
+				<2 RK_PA3 1 &pcfg_pull_up_drv_level_2>;
+		};
+
+		sdmmc1m1_bus4: sdmmc1m1-bus4 {
+			rockchip,pins =
+				/* sdmmc1_d0_m1 */
+				<1 RK_PC1 5 &pcfg_pull_up_drv_level_2>,
+				/* sdmmc1_d1_m1 */
+				<1 RK_PC0 5 &pcfg_pull_up_drv_level_2>,
+				/* sdmmc1_d2_m1 */
+				<1 RK_PC5 5 &pcfg_pull_up_drv_level_2>,
+				/* sdmmc1_d3_m1 */
+				<1 RK_PC4 5 &pcfg_pull_up_drv_level_2>;
+		};
+
+		sdmmc1m1_clk: sdmmc1m1-clk {
+			rockchip,pins =
+				/* sdmmc1_clk_m1 */
+				<1 RK_PC2 5 &pcfg_pull_up_drv_level_2>;
+		};
+
+		sdmmc1m1_cmd: sdmmc1m1-cmd {
+			rockchip,pins =
+				/* sdmmc1_cmd_m1 */
+				<1 RK_PC3 5 &pcfg_pull_up_drv_level_2>;
+		};
+
+		sdmmc1m1_idle_pins: sdmmc1m1-idle-pins {
+			rockchip,pins =
+				/* sdmmc1_d0_m1 */
+				<1 RK_PC1 5 &pcfg_pull_down>,
+				/* sdmmc1_d1_m1 */
+				<1 RK_PC0 5 &pcfg_pull_down>,
+				/* sdmmc1_d2_m1 */
+				<1 RK_PC5 5 &pcfg_pull_down>,
+				/* sdmmc1_d3_m1 */
+				<1 RK_PC4 5 &pcfg_pull_down>,
+				/* sdmmc1_clk_m1 */
+				<1 RK_PC2 5 &pcfg_pull_down>,
+				/* sdmmc1_cmd_m1 */
+				<1 RK_PC3 5 &pcfg_pull_down>;
+		};
+	};
+
+	spi0 {
+		spi0m0_pins: spi0m0-pins {
+			rockchip,pins =
+				/* spi0_clk_m0 */
+				<1 RK_PC1 4 &pcfg_pull_none>,
+				/* spi0_miso_m0 */
+				<1 RK_PC3 6 &pcfg_pull_none>,
+				/* spi0_mosi_m0 */
+				<1 RK_PC2 6 &pcfg_pull_none>;
+		};
+
+		spi0m0_cs0: spi0m0-cs0 {
+			rockchip,pins =
+				/* spi0_cs0n_m0 */
+				<1 RK_PC0 4 &pcfg_pull_none>;
+		};
+
+		spi0m0_cs1: spi0m0-cs1 {
+			rockchip,pins =
+				/* spi0_cs1n_m0 */
+				<1 RK_PD2 5 &pcfg_pull_none>;
+		};
+	};
+
+	spi1 {
+		spi1m0_pins: spi1m0-pins {
+			rockchip,pins =
+				/* spi1_clk_m0 */
+				<4 RK_PA7 2 &pcfg_pull_none>,
+				/* spi1_miso_m0 */
+				<4 RK_PA0 2 &pcfg_pull_none>,
+				/* spi1_mosi_m0 */
+				<4 RK_PA1 2 &pcfg_pull_none>;
+		};
+
+		spi1m0_cs0: spi1m0-cs0 {
+			rockchip,pins =
+				/* spi1_cs0n_m0 */
+				<4 RK_PA5 2 &pcfg_pull_none>;
+		};
+
+		spi1m0_cs1: spi1m0-cs1 {
+			rockchip,pins =
+				/* spi1_cs1n_m0 */
+				<1 RK_PB1 3 &pcfg_pull_none>;
+		};
+	};
+
+	uart0 {
+		uart0m0_xfer: uart0m0-xfer {
+			rockchip,pins =
+				/* uart0_rx_m0 */
+				<0 RK_PA0 1 &pcfg_pull_up>,
+				/* uart0_tx_m0 */
+				<0 RK_PA1 1 &pcfg_pull_up>;
+		};
+
+		uart0m1_xfer: uart0m1-xfer {
+			rockchip,pins =
+				/* uart0_rx_m1 */
+				<2 RK_PB0 1 &pcfg_pull_up>,
+				/* uart0_tx_m1 */
+				<2 RK_PB1 1 &pcfg_pull_up>;
+		};
+
+		uart0m1_ctsn: uart0m1-ctsn {
+			rockchip,pins =
+				/* uart0m1_ctsn */
+				<2 RK_PA7 1 &pcfg_pull_none>;
+		};
+		uart0m1_rtsn: uart0m1-rtsn {
+			rockchip,pins =
+				/* uart0m1_rtsn */
+				<2 RK_PA6 1 &pcfg_pull_none>;
+		};
+
+		uart0m2_xfer: uart0m2-xfer {
+			rockchip,pins =
+				/* uart0_rx_m2 */
+				<4 RK_PA0 3 &pcfg_pull_up>,
+				/* uart0_tx_m2 */
+				<4 RK_PA1 3 &pcfg_pull_up>;
+		};
+	};
+
+	uart1 {
+		uart1m0_xfer: uart1m0-xfer {
+			rockchip,pins =
+				/* uart1_rx_m0 */
+				<1 RK_PA4 1 &pcfg_pull_up>,
+				/* uart1_tx_m0 */
+				<1 RK_PA3 1 &pcfg_pull_up>;
+		};
+
+		uart1m0_ctsn: uart1m0-ctsn {
+			rockchip,pins =
+				/* uart1m0_ctsn */
+				<0 RK_PA6 2 &pcfg_pull_none>;
+		};
+		uart1m0_rtsn: uart1m0-rtsn {
+			rockchip,pins =
+				/* uart1m0_rtsn */
+				<0 RK_PA5 2 &pcfg_pull_none>;
+		};
+
+		uart1m1_xfer: uart1m1-xfer {
+			rockchip,pins =
+				/* uart1_rx_m1 */
+				<2 RK_PA5 4 &pcfg_pull_up>,
+				/* uart1_tx_m1 */
+				<2 RK_PA4 4 &pcfg_pull_up>;
+		};
+
+		uart1m1_ctsn: uart1m1-ctsn {
+			rockchip,pins =
+				/* uart1m1_ctsn */
+				<2 RK_PA0 4 &pcfg_pull_none>;
+		};
+		uart1m1_rtsn: uart1m1-rtsn {
+			rockchip,pins =
+				/* uart1m1_rtsn */
+				<2 RK_PA1 4 &pcfg_pull_none>;
+		};
+
+		uart1m2_xfer: uart1m2-xfer {
+			rockchip,pins =
+				/* uart1_rx_m2 */
+				<4 RK_PA7 3 &pcfg_pull_up>,
+				/* uart1_tx_m2 */
+				<4 RK_PA5 3 &pcfg_pull_up>;
+		};
+	};
+
+	uart2 {
+		uart2m0_xfer: uart2m0-xfer {
+			rockchip,pins =
+				/* uart2_rx_m0 */
+				<3 RK_PA3 2 &pcfg_pull_up>,
+				/* uart2_tx_m0 */
+				<3 RK_PA2 2 &pcfg_pull_up>;
+		};
+
+		uart2m1_xfer: uart2m1-xfer {
+			rockchip,pins =
+				/* uart2_rx_m1 */
+				<1 RK_PB3 2 &pcfg_pull_up>,
+				/* uart2_tx_m1 */
+				<1 RK_PB2 2 &pcfg_pull_up>;
+		};
+	};
+
+	uart3 {
+		uart3m0_xfer: uart3m0-xfer {
+			rockchip,pins =
+				/* uart3_rx_m0 */
+				<1 RK_PA1 1 &pcfg_pull_up>,
+				/* uart3_tx_m0 */
+				<1 RK_PA0 1 &pcfg_pull_up>;
+		};
+
+		uart3m1_xfer: uart3m1-xfer {
+			rockchip,pins =
+				/* uart3_rx_m1 */
+				<1 RK_PD1 5 &pcfg_pull_up>,
+				/* uart3_tx_m1 */
+				<1 RK_PD0 5 &pcfg_pull_up>;
+		};
+	};
+
+	uart4 {
+		uart4m0_xfer: uart4m0-xfer {
+			rockchip,pins =
+				/* uart4_rx_m0 */
+				<1 RK_PB0 1 &pcfg_pull_up>,
+				/* uart4_tx_m0 */
+				<1 RK_PB1 1 &pcfg_pull_up>;
+		};
+
+		uart4m1_xfer: uart4m1-xfer {
+			rockchip,pins =
+				/* uart4_rx_m1 */
+				<1 RK_PC4 4 &pcfg_pull_up>,
+				/* uart4_tx_m1 */
+				<1 RK_PC5 4 &pcfg_pull_up>;
+		};
+
+		uart4m1_ctsn: uart4m1-ctsn {
+			rockchip,pins =
+				/* uart4m1_ctsn */
+				<1 RK_PC7 4 &pcfg_pull_none>;
+		};
+		uart4m1_rtsn: uart4m1-rtsn {
+			rockchip,pins =
+				/* uart4m1_rtsn */
+				<1 RK_PC6 4 &pcfg_pull_none>;
+		};
+	};
+
+	uart5 {
+		uart5m0_xfer: uart5m0-xfer {
+			rockchip,pins =
+				/* uart5_rx_m0 */
+				<3 RK_PA7 2 &pcfg_pull_up>,
+				/* uart5_tx_m0 */
+				<3 RK_PA6 2 &pcfg_pull_up>;
+		};
+
+		uart5m0_ctsn: uart5m0-ctsn {
+			rockchip,pins =
+				/* uart5m0_ctsn */
+				<3 RK_PA5 2 &pcfg_pull_none>;
+		};
+		uart5m0_rtsn: uart5m0-rtsn {
+			rockchip,pins =
+				/* uart5m0_rtsn */
+				<3 RK_PA4 2 &pcfg_pull_none>;
+		};
+
+		uart5m1_xfer: uart5m1-xfer {
+			rockchip,pins =
+				/* uart5_rx_m1 */
+				<1 RK_PD2 4 &pcfg_pull_up>,
+				/* uart5_tx_m1 */
+				<1 RK_PD3 4 &pcfg_pull_up>;
+		};
+
+		uart5m1_ctsn: uart5m1-ctsn {
+			rockchip,pins =
+				/* uart5m1_ctsn */
+				<1 RK_PD1 4 &pcfg_pull_none>;
+		};
+		uart5m1_rtsn: uart5m1-rtsn {
+			rockchip,pins =
+				/* uart5m1_rtsn */
+				<1 RK_PD0 4 &pcfg_pull_none>;
+		};
+
+		uart5m2_xfer: uart5m2-xfer {
+			rockchip,pins =
+				/* uart5_rx_m2 */
+				<3 RK_PD0 2 &pcfg_pull_up>,
+				/* uart5_tx_m2 */
+				<3 RK_PC7 2 &pcfg_pull_up>;
+		};
+
+		uart5m2_ctsn: uart5m2-ctsn {
+			rockchip,pins =
+				/* uart5m2_ctsn */
+				<3 RK_PD2 2 &pcfg_pull_none>;
+		};
+		uart5m2_rtsn: uart5m2-rtsn {
+			rockchip,pins =
+				/* uart5m2_rtsn */
+				<3 RK_PD1 2 &pcfg_pull_none>;
+		};
+	};
+
+	vicap {
+		vicapm0_pins: vicapm0-pins {
+			rockchip,pins =
+				/* vicap_clkin_m0 */
+				<3 RK_PC2 1 &pcfg_pull_none>,
+				/* vicap_clkout_m0 */
+				<3 RK_PC4 1 &pcfg_pull_none>,
+				/* vicap_d0_m0 */
+				<3 RK_PB0 1 &pcfg_pull_none>,
+				/* vicap_d1_m0 */
+				<3 RK_PB1 1 &pcfg_pull_none>,
+				/* vicap_d2_m0 */
+				<3 RK_PB2 1 &pcfg_pull_none>,
+				/* vicap_d3_m0 */
+				<3 RK_PB3 1 &pcfg_pull_none>,
+				/* vicap_d4_m0 */
+				<3 RK_PB4 1 &pcfg_pull_none>,
+				/* vicap_d5_m0 */
+				<3 RK_PB5 1 &pcfg_pull_none>,
+				/* vicap_d6_m0 */
+				<3 RK_PB6 1 &pcfg_pull_none>,
+				/* vicap_d7_m0 */
+				<3 RK_PB7 1 &pcfg_pull_none>,
+				/* vicap_d8_m0 */
+				<3 RK_PC0 1 &pcfg_pull_none>,
+				/* vicap_d9_m0 */
+				<3 RK_PC1 1 &pcfg_pull_none>,
+				/* vicap_hsync_m0 */
+				<3 RK_PC3 1 &pcfg_pull_none>,
+				/* vicap_vsync_m0 */
+				<3 RK_PC5 1 &pcfg_pull_none>;
+		};
+
+		vicapm1_pins: vicapm1-pins {
+			rockchip,pins =
+				/* vicap_clkin_m1 */
+				<1 RK_PD0 2 &pcfg_pull_none>,
+				/* vicap_clkout_m1 */
+				<1 RK_PD3 2 &pcfg_pull_none>,
+				/* vicap_d0_m1 */
+				<1 RK_PA2 3 &pcfg_pull_none>,
+				/* vicap_d1_m1 */
+				<1 RK_PB1 4 &pcfg_pull_none>,
+				/* vicap_d2_m1 */
+				<1 RK_PC0 2 &pcfg_pull_none>,
+				/* vicap_d3_m1 */
+				<1 RK_PC1 2 &pcfg_pull_none>,
+				/* vicap_d4_m1 */
+				<1 RK_PC2 2 &pcfg_pull_none>,
+				/* vicap_d5_m1 */
+				<1 RK_PC3 2 &pcfg_pull_none>,
+				/* vicap_d6_m1 */
+				<1 RK_PC4 2 &pcfg_pull_none>,
+				/* vicap_d7_m1 */
+				<1 RK_PC5 2 &pcfg_pull_none>,
+				/* vicap_d8_m1 */
+				<1 RK_PC6 2 &pcfg_pull_none>,
+				/* vicap_d9_m1 */
+				<1 RK_PC7 2 &pcfg_pull_none>,
+				/* vicap_hsync_m1 */
+				<1 RK_PD1 2 &pcfg_pull_none>,
+				/* vicap_vsync_m1 */
+				<1 RK_PD2 2 &pcfg_pull_none>;
+		};
+
+		vicap_d10: vicap-d10 {
+			rockchip,pins =
+				/* vicap_d10 */
+				<3 RK_PC6 1 &pcfg_pull_none>;
+		};
+		vicap_d11: vicap-d11 {
+			rockchip,pins =
+				/* vicap_d11 */
+				<3 RK_PC7 1 &pcfg_pull_none>;
+		};
+		vicap_d12: vicap-d12 {
+			rockchip,pins =
+				/* vicap_d12 */
+				<3 RK_PD0 1 &pcfg_pull_none>;
+		};
+		vicap_d13: vicap-d13 {
+			rockchip,pins =
+				/* vicap_d13 */
+				<3 RK_PD1 1 &pcfg_pull_none>;
+		};
+		vicap_d14: vicap-d14 {
+			rockchip,pins =
+				/* vicap_d14 */
+				<3 RK_PD2 1 &pcfg_pull_none>;
+		};
+		vicap_d15: vicap-d15 {
+			rockchip,pins =
+				/* vicap_d15 */
+				<3 RK_PD3 1 &pcfg_pull_none>;
+		};
+	};
+};
diff --git a/arch/arm/dts/rv1106.dtsi b/arch/arm/dts/rv1106.dtsi
new file mode 100644
index 00000000000..df2386eb31e
--- /dev/null
+++ b/arch/arm/dts/rv1106.dtsi
@@ -0,0 +1,328 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2022 Rockchip Electronics Co., Ltd.
+ */
+
+#include <dt-bindings/clock/rv1106-cru.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/pinctrl/rockchip.h>
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	compatible = "rockchip,rv1106";
+
+	interrupt-parent = <&gic>;
+
+	aliases {
+		gpio0 = &gpio0;
+		gpio1 = &gpio1;
+		gpio2 = &gpio2;
+		gpio3 = &gpio3;
+		gpio4 = &gpio4;
+		serial0 = &uart0;
+		serial1 = &uart1;
+		serial2 = &uart2;
+		serial3 = &uart3;
+		serial4 = &uart4;
+		serial5 = &uart5;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu0: cpu@f00 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a7";
+			reg = <0xf00>;
+		};
+	};
+
+	timer {
+		compatible = "arm,armv7-timer";
+		interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_HIGH)>;
+		clock-frequency = <24000000>;
+	};
+
+	xin24m: oscillator {
+		compatible = "fixed-clock";
+		clock-frequency = <24000000>;
+		clock-output-names = "xin24m";
+		#clock-cells = <0>;
+	};
+
+	grf: syscon@ff000000 {
+		compatible = "rockchip,rv1106-grf", "syscon", "simple-mfd";
+		reg = <0xff000000 0x68000>;
+
+		grf_cru: grf-clock-controller {
+			compatible = "rockchip,rv1106-grf-cru";
+			#clock-cells = <1>;
+		};
+	};
+
+	gic: interrupt-controller@ff1f0000 {
+		compatible = "arm,gic-400";
+		interrupt-controller;
+		#interrupt-cells = <3>;
+		#address-cells = <0>;
+
+		reg = <0xff1f1000 0x1000>,
+		      <0xff1f2000 0x2000>,
+		      <0xff1f4000 0x2000>,
+		      <0xff1f6000 0x2000>;
+		interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_HIGH)>;
+	};
+
+	pmuioc: syscon@ff388000 {
+		compatible = "rockchip,rv1106-pmuioc", "syscon";
+		reg = <0xff388000 0x1000>;
+	};
+
+	cru: clock-controller@ff3a0000 {
+		compatible = "rockchip,rv1106-cru";
+		reg = <0xff3a0000 0x20000>;
+		rockchip,grf = <&grf>;
+		#clock-cells = <1>;
+		#reset-cells = <1>;
+
+		assigned-clocks =
+			<&cru PLL_GPLL>, <&cru PLL_CPLL>,
+			<&cru ARMCLK>,
+			<&cru ACLK_PERI_ROOT>, <&cru HCLK_PERI_ROOT>,
+			<&cru PCLK_PERI_ROOT>, <&cru ACLK_BUS_ROOT>,
+			<&cru PCLK_TOP_ROOT>, <&cru PCLK_PMU_ROOT>,
+			<&cru HCLK_PMU_ROOT>;
+		assigned-clock-rates =
+			<1188000000>, <1000000000>,
+			<816000000>,
+			<400000000>, <200000000>,
+			<100000000>, <300000000>,
+			<100000000>, <100000000>,
+			<200000000>;
+	};
+
+	saradc: saradc@ff3c0000 {
+		compatible = "rockchip,rv1106-saradc";
+		reg = <0xff3c0000 0x100>;
+		interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
+		#io-channel-cells = <1>;
+		clocks = <&cru CLK_SARADC>, <&cru PCLK_SARADC>;
+		clock-names = "saradc", "apb_pclk";
+		resets = <&cru SRST_P_SARADC>;
+		reset-names = "saradc-apb";
+		status = "disabled";
+	};
+
+	uart0: serial@ff4a0000 {
+		compatible = "rockchip,rv1106-uart", "snps,dw-apb-uart";
+		reg = <0xff4a0000 0x100>;
+		interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
+		reg-shift = <2>;
+		reg-io-width = <4>;
+		clock-frequency = <24000000>;
+		clocks = <&cru SCLK_UART0>, <&cru PCLK_UART0>;
+		clock-names = "baudclk", "apb_pclk";
+		status = "disabled";
+	};
+
+	uart1: serial@ff4b0000 {
+		compatible = "rockchip,rv1106-uart", "snps,dw-apb-uart";
+		reg = <0xff4b0000 0x100>;
+		interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
+		reg-shift = <2>;
+		reg-io-width = <4>;
+		clock-frequency = <24000000>;
+		clocks = <&cru SCLK_UART1>, <&cru PCLK_UART1>;
+		clock-names = "baudclk", "apb_pclk";
+		status = "disabled";
+	};
+
+	uart2: serial@ff4c0000 {
+		compatible = "rockchip,rv1106-uart", "snps,dw-apb-uart";
+		reg = <0xff4c0000 0x100>;
+		interrupts = <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>;
+		reg-shift = <2>;
+		reg-io-width = <4>;
+		clock-frequency = <24000000>;
+		clocks = <&cru SCLK_UART2>, <&cru PCLK_UART2>;
+		clock-names = "baudclk", "apb_pclk";
+		pinctrl-names = "default";
+		pinctrl-0 = <&uart2m1_xfer>;
+		status = "disabled";
+	};
+
+	uart3: serial@ff4d0000 {
+		compatible = "rockchip,rv1106-uart", "snps,dw-apb-uart";
+		reg = <0xff4d0000 0x100>;
+		interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>;
+		reg-shift = <2>;
+		reg-io-width = <4>;
+		clock-frequency = <24000000>;
+		clocks = <&cru SCLK_UART3>, <&cru PCLK_UART3>;
+		clock-names = "baudclk", "apb_pclk";
+		status = "disabled";
+	};
+
+	uart4: serial@ff4e0000 {
+		compatible = "rockchip,rv1106-uart", "snps,dw-apb-uart";
+		reg = <0xff4e0000 0x100>;
+		interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
+		reg-shift = <2>;
+		reg-io-width = <4>;
+		clock-frequency = <24000000>;
+		clocks = <&cru SCLK_UART4>, <&cru PCLK_UART4>;
+		clock-names = "baudclk", "apb_pclk";
+		status = "disabled";
+	};
+
+	uart5: serial@ff4f0000 {
+		compatible = "rockchip,rv1106-uart", "snps,dw-apb-uart";
+		reg = <0xff4f0000 0x100>;
+		interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
+		reg-shift = <2>;
+		reg-io-width = <4>;
+		clock-frequency = <24000000>;
+		clocks = <&cru SCLK_UART5>, <&cru PCLK_UART5>;
+		clock-names = "baudclk", "apb_pclk";
+		status = "disabled";
+	};
+
+	ioc: syscon@ff538000 {
+		compatible = "rockchip,rv1106-ioc", "syscon";
+		reg = <0xff538000 0x40000>;
+	};
+
+	wdt: watchdog@ff5a0000 {
+		compatible = "rockchip,rv1106-wdt", "snps,dw-wdt";
+		reg = <0xff5a0000 0x100>;
+		clocks = <&cru TCLK_WDT_NS>, <&cru PCLK_WDT_NS>;
+		clock-names = "tclk", "pclk";
+		interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
+		resets = <&cru SRST_P_WDT_NS>;
+		reset-names = "reset";
+		status = "disabled";
+	};
+
+	emmc: mmc@ffa90000 {
+		compatible = "rockchip,rv1106-dw-mshc", "rockchip,rk3288-dw-mshc";
+		reg = <0xffa90000 0x4000>;
+		interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru HCLK_EMMC>, <&cru CCLK_SRC_EMMC>,
+			 <&grf_cru SCLK_EMMC_DRV>, <&grf_cru SCLK_EMMC_SAMPLE>;
+		clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
+		fifo-depth = <0x100>;
+		max-frequency = <200000000>;
+		status = "disabled";
+	};
+
+	sdmmc: mmc@ffaa0000 {
+		compatible = "rockchip,rv1106-dw-mshc", "rockchip,rk3288-dw-mshc";
+		reg = <0xffaa0000 0x4000>;
+		interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru HCLK_SDMMC>, <&cru CCLK_SRC_SDMMC>,
+			 <&grf_cru SCLK_SDMMC_DRV>, <&grf_cru SCLK_SDMMC_SAMPLE>;
+		clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
+		cd-gpios = <&gpio3 RK_PA1 GPIO_ACTIVE_HIGH>;
+		fifo-depth = <0x100>;
+		max-frequency = <200000000>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&sdmmc0_clk &sdmmc0_cmd &sdmmc0_det &sdmmc0_bus4>;
+		status = "disabled";
+	};
+
+	sfc: spi@ffac0000 {
+		compatible = "rockchip,sfc";
+		reg = <0xffac0000 0x4000>;
+		interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru SCLK_SFC>, <&cru HCLK_SFC>;
+		clock-names = "clk_sfc", "hclk_sfc";
+		assigned-clocks = <&cru SCLK_SFC>;
+		assigned-clock-rates = <75000000>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&fspi_pins &fspi_cs0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	pinctrl: pinctrl {
+		compatible = "rockchip,rv1106-pinctrl";
+		rockchip,grf = <&ioc>;
+		rockchip,pmu = <&pmuioc>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		gpio0: gpio@ff380000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0xff380000 0x100>;
+			interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cru PCLK_PMU_GPIO0>, <&cru DBCLK_PMU_GPIO0>;
+
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <&pinctrl 0 0 32>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpio1: gpio@ff530000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0xff530000 0x100>;
+			interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cru PCLK_GPIO1>, <&cru DBCLK_GPIO1>;
+
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <&pinctrl 0 32 32>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpio2: gpio@ff540000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0xff540000 0x100>;
+			interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cru PCLK_GPIO2>, <&cru DBCLK_GPIO2>;
+
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <&pinctrl 0 64 32>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpio3: gpio@ff550000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0xff550000 0x100>;
+			interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cru PCLK_GPIO3>, <&cru DBCLK_GPIO3>;
+
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <&pinctrl 0 96 32>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpio4: gpio@ff560000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0xff560000 0x100>;
+			interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cru PCLK_GPIO4>, <&cru DBCLK_GPIO4>;
+
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <&pinctrl 0 128 32>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+	};
+};
+
+#include "rv1106-pinctrl.dtsi"
diff --git a/include/dt-bindings/clock/rv1106-cru.h b/include/dt-bindings/clock/rv1106-cru.h
new file mode 100644
index 00000000000..8febd5d8a66
--- /dev/null
+++ b/include/dt-bindings/clock/rv1106-cru.h
@@ -0,0 +1,572 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2022 Rockchip Electronics Co. Ltd.
+ * Author: Elaine Zhang <zhangqing@rock-chips.com>
+ */
+
+#ifndef _DT_BINDINGS_CLK_ROCKCHIP_RV1106_H
+#define _DT_BINDINGS_CLK_ROCKCHIP_RV1106_H
+
+/* pll clocks */
+#define PLL_APLL		1
+#define PLL_DPLL		2
+#define PLL_CPLL		3
+#define PLL_GPLL		4
+#define ARMCLK			5
+
+/* clk (clocks) */
+#define PCLK_DDRPHY		11
+#define PCLK_DDR_ROOT		12
+#define PCLK_DDRMON		13
+#define CLK_TIMER_DDRMON	14
+#define PCLK_DDRC		15
+#define PCLK_DFICTRL		16
+#define ACLK_DDR_ROOT		17
+#define ACLK_SYS_SHRM		18
+#define HCLK_NPU_ROOT		19
+#define ACLK_NPU_ROOT		20
+#define PCLK_NPU_ROOT		21
+#define HCLK_RKNN		22
+#define ACLK_RKNN		23
+#define PCLK_ACODEC		24
+#define MCLK_ACODEC_TX		25
+#define MCLK_ACODEC_RX		26
+#define CLK_CORE_CRYPTO		27
+#define CLK_PKA_CRYPTO		28
+#define ACLK_CRYPTO		29
+#define HCLK_CRYPTO		30
+#define ACLK_DECOM		31
+#define PCLK_DECOM		32
+#define DCLK_DECOM		33
+#define ACLK_DMAC		34
+#define PCLK_DSM		35
+#define MCLK_DSM		36
+#define CCLK_SRC_EMMC		37
+#define HCLK_EMMC		38
+#define PCLK_GPIO4		39
+#define DBCLK_GPIO4		40
+#define PCLK_I2C0		41
+#define CLK_I2C0		42
+#define PCLK_I2C2		43
+#define CLK_I2C2		44
+#define PCLK_I2C3		45
+#define CLK_I2C3		46
+#define PCLK_I2C4		47
+#define CLK_I2C4		48
+#define HCLK_I2S0		49
+#define PCLK_DFT2APB		50
+#define HCLK_IVE		51
+#define ACLK_IVE		52
+#define PCLK_PWM0_PERI		53
+#define CLK_PWM0_PERI		54
+#define CLK_CAPTURE_PWM0_PERI	55
+#define PCLK_PERI_ROOT		56
+#define ACLK_PERI_ROOT		57
+#define HCLK_PERI_ROOT		58
+#define CLK_TIMER_ROOT		59
+#define ACLK_BUS_ROOT		60
+#define HCLK_SFC		61
+#define SCLK_SFC		62
+#define PCLK_UART0		63
+#define CLK_PVTM_CORE		64
+#define PCLK_UART1		65
+#define CLK_CORE_MCU_RTC	66
+#define PCLK_PWM1_PERI		67
+#define CLK_PWM1_PERI		68
+#define CLK_CAPTURE_PWM1_PERI	69
+#define PCLK_PWM2_PERI		70
+#define CLK_PWM2_PERI		71
+#define CLK_CAPTURE_PWM2_PERI	72
+#define HCLK_BOOTROM		73
+#define HCLK_SAI		74
+#define MCLK_SAI		75
+#define PCLK_SARADC		76
+#define CLK_SARADC		77
+#define PCLK_SPI1		78
+#define CLK_SPI1		79
+#define PCLK_STIMER		80
+#define CLK_STIMER0		81
+#define CLK_STIMER1		82
+#define PCLK_TIMER		83
+#define CLK_TIMER0		84
+#define CLK_TIMER1		85
+#define CLK_TIMER2		86
+#define CLK_TIMER3		87
+#define CLK_TIMER4		88
+#define CLK_TIMER5		89
+#define HCLK_TRNG_NS		90
+#define HCLK_TRNG_S		91
+#define PCLK_UART2		92
+#define HCLK_CPU		93
+#define PCLK_UART3		94
+#define CLK_CORE_MCU		95
+#define PCLK_UART4		96
+#define PCLK_DDR_HWLP		97
+#define PCLK_UART5		98
+#define ACLK_USBOTG		100
+#define CLK_REF_USBOTG		101
+#define CLK_UTMI_USBOTG		102
+#define PCLK_USBPHY		103
+#define CLK_REF_USBPHY		104
+#define PCLK_WDT_NS		105
+#define TCLK_WDT_NS		106
+#define PCLK_WDT_S		107
+#define TCLK_WDT_S		108
+#define CLK_DDR_FAIL_SAFE	109
+#define XIN_OSC0_DIV		110
+#define CLK_DEEPSLOW		111
+#define PCLK_PMU_GPIO0		112
+#define DBCLK_PMU_GPIO0		113
+#define CLK_PMU			114
+#define PCLK_PMU		115
+#define PCLK_PMU_HP_TIMER	116
+#define CLK_PMU_HP_TIMER	117
+#define CLK_PMU_32K_HP_TIMER	118
+#define PCLK_I2C1		119
+#define CLK_I2C1		120
+#define PCLK_PMU_IOC		121
+#define PCLK_PMU_MAILBOX	122
+#define CLK_PMU_MCU		123
+#define CLK_PMU_MCU_RTC		124
+#define CLK_PMU_MCU_JTAG	125
+#define CLK_PVTM_PMU		126
+#define PCLK_PVTM_PMU		127
+#define CLK_REFOUT		128
+#define CLK_100M_PMU		129
+#define PCLK_PMU_ROOT		130
+#define HCLK_PMU_ROOT		131
+#define HCLK_PMU_SRAM		132
+#define PCLK_PMU_WDT		133
+#define TCLK_PMU_WDT		134
+#define CLK_DFICTRL		135
+#define CLK_DDRMON		136
+#define CLK_DDR_PHY		137
+#define ACLK_DDRC		138
+#define CLK_CORE_DDRC_SRC	139
+#define CLK_CORE_DDRC		140
+#define CLK_50M_SRC		141
+#define CLK_100M_SRC		142
+#define CLK_150M_SRC		143
+#define CLK_200M_SRC		144
+#define CLK_250M_SRC		145
+#define CLK_300M_SRC		146
+#define CLK_339M_SRC		147
+#define CLK_400M_SRC		148
+#define CLK_450M_SRC		149
+#define CLK_500M_SRC		150
+#define CLK_I2S0_8CH_TX_SRC	151
+#define CLK_I2S0_8CH_TX_FRAC	152
+#define CLK_I2S0_8CH_TX		153
+#define CLK_I2S0_8CH_RX_SRC	154
+#define CLK_I2S0_8CH_RX_FRAC	155
+#define CLK_I2S0_8CH_RX		156
+#define I2S0_8CH_MCLKOUT	157
+#define MCLK_I2S0_8CH_RX	158
+#define MCLK_I2S0_8CH_TX	159
+#define CLK_REF_MIPI0_SRC	160
+#define CLK_REF_MIPI0_FRAC	161
+#define CLK_REF_MIPI0_OUT	162
+#define CLK_REF_MIPI1_SRC	163
+#define CLK_REF_MIPI1_FRAC	164
+#define MCLK_REF_MIPI0		165
+#define MCLK_REF_MIPI1		166
+#define CLK_REF_MIPI0		167
+#define CLK_REF_MIPI1		168
+#define CLK_UART0_SRC		169
+#define CLK_UART0_FRAC		170
+#define CLK_UART0		171
+#define SCLK_UART0		172
+#define CLK_UART1_SRC		173
+#define CLK_UART1_FRAC		174
+#define CLK_UART1		175
+#define SCLK_UART1		176
+#define CLK_UART2_SRC		177
+#define CLK_UART2_FRAC		178
+#define CLK_UART2		179
+#define SCLK_UART2		180
+#define CLK_UART3_SRC		181
+#define CLK_UART3_FRAC		182
+#define CLK_UART3		183
+#define SCLK_UART3		184
+#define CLK_UART4_SRC		185
+#define CLK_UART4_FRAC		186
+#define CLK_UART4		187
+#define SCLK_UART4		188
+#define CLK_UART5_SRC		189
+#define CLK_UART5_FRAC		190
+#define CLK_UART5		191
+#define SCLK_UART5		192
+#define CLK_VICAP_M0_SRC	193
+#define CLK_VICAP_M0_FRAC	194
+#define CLK_VICAP_M0		195
+#define SCLK_VICAP_M0		196
+#define CLK_VICAP_M1_SRC	197
+#define CLK_VICAP_M1_FRAC	198
+#define CLK_VICAP_M1		199
+#define SCLK_VICAP_M1		200
+#define DCLK_VOP_SRC		201
+#define PCLK_CRU		202
+#define PCLK_TOP_ROOT		203
+#define PCLK_SPI0		204
+#define CLK_SPI0		205
+#define SCLK_IN_SPI0		206
+#define CLK_UART_DETN_FLT	207
+#define HCLK_VEPU		208
+#define ACLK_VEPU		209
+#define CLK_CORE_VEPU		210
+#define CLK_CORE_VEPU_DVBM	211
+#define PCLK_GPIO1		212
+#define DBCLK_GPIO1		213
+#define HCLK_VEPU_PP		214
+#define ACLK_VEPU_PP		215
+#define HCLK_VEPU_ROOT		216
+#define ACLK_VEPU_COM_ROOT	217
+#define ACLK_VEPU_ROOT		218
+#define PCLK_VEPU_ROOT		219
+#define PCLK_VICAP_VEPU		220
+#define PCLK_CSIHOST0		221
+#define CLK_RXBYTECLKHS_0	222
+#define PCLK_CSIHOST1		223
+#define CLK_RXBYTECLKHS_1	224
+#define PCLK_GPIO3		225
+#define DBCLK_GPIO3		226
+#define HCLK_ISP3P2		227
+#define ACLK_ISP3P2		228
+#define CLK_CORE_ISP3P2		229
+#define PCLK_MIPICSIPHY		230
+#define CCLK_SRC_SDMMC		231
+#define HCLK_SDMMC		232
+#define CLK_SDMMC_DETN_FLT	233
+#define HCLK_VI_ROOT		234
+#define ACLK_VI_ROOT		235
+#define PCLK_VI_ROOT		236
+#define PCLK_VI_RTC_ROOT	237
+#define PCLK_VI_RTC_TEST	238
+#define PCLK_VI_RTC_PHY		239
+#define DCLK_VICAP		240
+#define PCLK_VICAP		241
+#define ACLK_VICAP		242
+#define HCLK_VICAP		243
+#define I0CLK_VICAP		244
+#define I1CLK_VICAP		245
+#define RX0PCLK_VICAP		246
+#define RX1PCLK_VICAP		247
+#define ISP0CLK_VICAP		248
+#define PCLK_GPIO2		249
+#define DBCLK_GPIO2		250
+#define ACLK_MAC		251
+#define PCLK_MAC		252
+#define CLK_GMAC0_50M_O		253
+#define CLK_GMAC0_TX_50M_O	254
+#define CLK_GMAC0_REF_50M	255
+#define CLK_GMAC0_TX_50M	256
+#define CLK_GMAC0_RX_50M	257
+#define ACLK_MAC_ROOT		258
+#define CLK_MACPHY		259
+#define CLK_OTPC_ARB		260
+#define PCLK_OTPC_NS		261
+#define CLK_SBPI_OTPC_NS	262
+#define CLK_USER_OTPC_NS	263
+#define PCLK_OTPC_S		264
+#define CLK_SBPI_OTPC_S		265
+#define CLK_USER_OTPC_S		266
+#define PCLK_OTP_MASK		267
+#define CLK_PMC_OTP		268
+#define HCLK_RGA2E		269
+#define ACLK_RGA2E		270
+#define CLK_CORE_RGA2E		271
+#define CCLK_SRC_SDIO		272
+#define HCLK_SDIO		273
+#define PCLK_TSADC		274
+#define CLK_TSADC		275
+#define CLK_TSADC_TSEN		276
+#define ACLK_VO_ROOT		277
+#define HCLK_VO_ROOT		278
+#define PCLK_VO_ROOT		279
+#define ACLK_VOP_ROOT		280
+#define HCLK_VOP		281
+#define DCLK_VOP		282
+#define ACLK_VOP		283
+#define CLK_RTC_32K		284
+#define PCLK_MAILBOX		291
+
+#define CLK_NR_CLKS		(PCLK_MAILBOX + 1)
+
+#define SCLK_EMMC_DRV		1
+#define SCLK_EMMC_SAMPLE	2
+#define SCLK_SDMMC_DRV		3
+#define SCLK_SDMMC_SAMPLE	4
+#define SCLK_SDIO_DRV		5
+#define SCLK_SDIO_SAMPLE	6
+
+#define CLK_NR_GRF_CLKS		(SCLK_SDIO_SAMPLE + 1)
+
+/********Name=PMUSOFTRST_CON00,Offset=0xA00********/
+#define SRST_P_I2C1		3
+#define SRST_I2C1		4
+#define SRST_H_PMU_BIU		6
+#define SRST_P_PMU_BIU		7
+#define SRST_H_PMU_SRAM		8
+#define SRST_PMU_MCU		9
+#define SRST_PMU_MCU_PWRUP	10
+#define SRST_PMU_MCU_CPU	11
+#define SRST_T_PMU_MCU_CPU	12
+/********Name=PMUSOFTRST_CON01,Offset=0xA04********/
+#define SRST_P_PMU_GPIO0	18
+#define SRST_PMU_GPIO0		19
+#define SRST_PVTM_PMU		20
+#define SRST_P_PVTM_PMU		21
+#define SRST_DDR_FAIL_SAFE	31
+/********Name=PMUSOFTRST_CON02,Offset=0xA08********/
+#define SRST_P_PMU_HP_TIMER	32
+#define SRST_PMU_HP_TIMER	33
+#define SRST_PMU_32K_HP_TIMER	34
+#define SRST_P_PMU_IOC		35
+#define SRST_P_PMU_CRU		36
+#define SRST_P_PMU_GRF		37
+#define SRST_P_PMU_SGRF		38
+#define SRST_P_PMU_SGRF_REMAP	39
+#define SRST_P_PMU_WDT		40
+#define SRST_T_PMU_WDT		41
+#define SRST_P_PMU_MAILBOX	42
+#define SRST_WRITE_ENABLE	48
+/********Name=SOFTRST_CON02,Offset=0x10A08********/
+#define SRST_REF_PVTPLL_0	262183
+#define SRST_REF_PVTPLL_1	262184
+#define SRST_P_CRU		262186
+#define SRST_P_CRU_BIU		262187
+/********Name=PERISOFTRST_CON00,Offset=0x12A00********/
+#define SRST_P_PERI_BIU		294916
+#define SRST_A_PERI_BIU		294917
+#define SRST_H_PERI_BIU		294918
+#define SRST_H_BOOTROM		294919
+#define SRST_P_TIMER		294920
+#define SRST_TIMER0		294921
+#define SRST_TIMER1		294922
+#define SRST_TIMER2		294923
+#define SRST_TIMER3		294924
+#define SRST_TIMER4		294925
+#define SRST_TIMER5		294926
+#define SRST_P_STIMER		294927
+/********Name=PERISOFTRST_CON01,Offset=0x12A04********/
+#define SRST_STIMER0		294928
+#define SRST_STIMER1		294929
+#define SRST_P_WDT_NS		294930
+#define SRST_T_WDT_NS		294931
+#define SRST_P_WDT_S		294932
+#define SRST_T_WDT_S		294933
+#define SRST_P_I2C0		294934
+#define SRST_I2C0		294935
+#define SRST_P_I2C2		294938
+#define SRST_I2C2		294939
+#define SRST_P_I2C3		294940
+#define SRST_I2C3		294941
+#define SRST_P_I2C4		294942
+#define SRST_I2C4		294943
+/********Name=PERISOFTRST_CON02,Offset=0x12A08********/
+#define SRST_P_GPIO4		294944
+#define SRST_GPIO4		294945
+#define SRST_P_PERI_IOC		294946
+#define SRST_P_UART2		294947
+#define SRST_S_UART2		294950
+#define SRST_P_UART3		294951
+#define SRST_S_UART3		294954
+#define SRST_P_UART4		294955
+#define SRST_S_UART4		294958
+#define SRST_P_UART5		294959
+/********Name=PERISOFTRST_CON03,Offset=0x12A0C********/
+#define SRST_S_UART5		294962
+#define SRST_P_SARADC		294963
+#define SRST_SARADC		294964
+#define SRST_SARADC_PHY		294965
+#define SRST_P_SPI1		294966
+#define SRST_SPI1		294967
+#define SRST_H_TRNG_NS		294969
+#define SRST_H_TRNG_S		294970
+#define SRST_CORE_CRYPTO	294971
+#define SRST_PKA_CRYPTO		294972
+#define SRST_A_CRYPTO		294973
+#define SRST_H_CRYPTO		294974
+#define SRST_P_PWM1_PERI	294975
+/********Name=PERISOFTRST_CON04,Offset=0x12A10********/
+#define SRST_PWM1_PERI		294976
+#define SRST_P_PWM2_PERI	294978
+#define SRST_PWM2_PERI		294979
+#define SRST_P_PERI_GRF		294981
+#define SRST_P_PERI_CRU		294982
+#define SRST_A_USBOTG		294983
+#define SRST_A_BUS_BIU		294986
+#define SRST_H_EMMC		294989
+#define SRST_H_SFC		294990
+/********Name=PERISOFTRST_CON05,Offset=0x12A14********/
+#define SRST_S_SFC		294992
+#define SRST_P_USBPHY		294993
+#define SRST_USBPHY_POR		294994
+#define SRST_USBPHY_OTG		294995
+#define SRST_A_DMAC		295000
+#define SRST_A_DECOM		295001
+#define SRST_P_DECOM		295002
+#define SRST_D_DECOM		295003
+#define SRST_P_PERI_SGRF	295004
+#define SRST_H_SAI		295005
+#define SRST_M_SAI		295006
+#define SRST_M_I2S0_8CH_TX	295007
+/********Name=PERISOFTRST_CON06,Offset=0x12A18********/
+#define SRST_H_I2S0		295008
+#define SRST_M_DSM		295009
+#define SRST_P_DSM		295010
+#define SRST_P_ACODEC		295011
+#define SRST_M_I2S0_8CH_RX	295014
+#define SRST_P_DFT2APB		295015
+#define SRST_H_IVE		295017
+#define SRST_A_IVE		295018
+#define SRST_P_UART0		295019
+#define SRST_S_UART0		295022
+#define SRST_P_UART1		295023
+/********Name=PERISOFTRST_CON07,Offset=0x12A1C********/
+#define SRST_S_UART1		295026
+#define SRST_P_PWM0_PERI	295027
+#define SRST_PWM0_PERI		295028
+/********Name=VISOFTRST_CON00,Offset=0x14A00********/
+#define SRST_H_VI_BIU		327684
+#define SRST_A_VI_BIU		327685
+#define SRST_P_VI_BIU		327686
+#define SRST_CORE_ISP3P2	327689
+#define SRST_D_VICAP		327690
+#define SRST_P_VICAP		327691
+#define SRST_A_VICAP		327692
+#define SRST_H_VICAP		327693
+#define SRST_VICAP_I0		327694
+#define SRST_VICAP_I1		327695
+/********Name=VISOFTRST_CON01,Offset=0x14A04********/
+#define SRST_VICAP_RX0		327696
+#define SRST_VICAP_RX1		327697
+#define SRST_VICAP_ISP0		327698
+#define SRST_P_CSIHOST0		327700
+#define SRST_P_CSIHOST1		327702
+#define SRST_H_SDMMC		327708
+#define SRST_SDMMC_DETN_FLT	327709
+#define SRST_P_MIPICSIPHY	327710
+#define SRST_P_GPIO3		327711
+/********Name=VISOFTRST_CON02,Offset=0x14A08********/
+#define SRST_GPIO3		327712
+#define SRST_P_VI_IOC		327713
+#define SRST_P_VI_GRF		327714
+#define SRST_P_VI_SGRF		327715
+#define SRST_P_VI_CRU		327716
+#define SRST_P_VI_RTC_TEST	327717
+#define SRST_P_VI_RTC_NIU	327719
+/********Name=NPUSOFTRST_CON00,Offset=0x16A00********/
+#define SRST_H_NPU_BIU		360451
+#define SRST_A_NPU_BIU		360452
+#define SRST_P_NPU_BIU		360453
+#define SRST_P_NPU_CRU		360454
+#define SRST_P_NPU_SGRF		360455
+#define SRST_P_NPU_GRF		360456
+#define SRST_H_RKNN		360457
+#define SRST_A_RKNN		360458
+/********Name=CORESOFTRST_CON00,Offset=0x18A00********/
+#define SRST_NCOREPORESET	393217
+#define SRST_NCORESET		393218
+#define SRST_NDBGRESET		393219
+#define SRST_NL2RESET		393220
+#define SRST_A_M_CORE_BIU	393221
+#define SRST_P_DBG		393222
+#define SRST_POT_DBG		393223
+#define SRST_NT_DBG		393224
+#define SRST_P_CORE_GRF		393227
+#define SRST_H_CPU_BIU		393228
+#define SRST_P_CPU_BIU		393229
+#define SRST_PVTM_CORE		393230
+#define SRST_P_PVTM_CORE	393231
+/********Name=CORESOFTRST_CON01,Offset=0x18A04********/
+#define SRST_REF_PVTPLL_CORE	393232
+#define SRST_CORE_MCU		393233
+#define SRST_CORE_MCU_PWRUP	393234
+#define SRST_CORE_MCU_CPU	393235
+#define SRST_T_CORE_MCU_CPU	393236
+#define SRST_MCU_BIU		393237
+#define SRST_P_MAILBOX		393240
+#define SRST_P_INTMUX		393241
+#define SRST_P_CORE_CRU		393242
+#define SRST_P_CORE_SGRF	393243
+#define SRST_H_CACHE		393244
+/********Name=VEPUSOFTRST_CON00,Offset=0x1AA00********/
+#define SRST_H_VEPU_BIU		425988
+#define SRST_A_VEPU_BIU		425989
+#define SRST_A_VEPU_COM_BIU	425990
+#define SRST_P_VEPU_BIU		425991
+#define SRST_H_VEPU		425992
+#define SRST_A_VEPU		425993
+#define SRST_CORE_VEPU		425994
+#define SRST_H_VEPU_PP		425995
+#define SRST_A_VEPU_PP		425996
+#define SRST_CORE_VEPU_DVBM	425997
+#define SRST_P_VICAP_VEPU	425998
+#define SRST_P_GPIO1		425999
+/********Name=VEPUSOFTRST_CON01,Offset=0x1AA04********/
+#define SRST_GPIO1		426000
+#define SRST_P_VEPU_IOC		426001
+#define SRST_P_SPI0		426002
+#define SRST_SPI0		426003
+#define SRST_P_VEPU_CRU		426005
+#define SRST_P_VEPU_SGRF	426006
+#define SRST_P_VEPU_GRF		426007
+#define SRST_UART_DETN_FLT	426008
+/********Name=VOSOFTRST_CON00,Offset=0x1CA00********/
+#define SRST_A_VO_BIU		458755
+#define SRST_H_VO_BIU		458756
+#define SRST_H_RGA2E		458759
+#define SRST_A_RGA2E		458760
+#define SRST_CORE_RGA2E		458761
+#define SRST_P_VO_GRF		458762
+#define SRST_A_VOP_BIU		458764
+#define SRST_H_VOP		458765
+#define SRST_D_VOP		458766
+#define SRST_A_VOP		458767
+/********Name=VOSOFTRST_CON01,Offset=0x1CA04********/
+#define SRST_P_MAC_BIU		458774
+#define SRST_A_MAC_BIU		458775
+#define SRST_A_MAC		458776
+#define SRST_P_VO_SGRF		458780
+#define SRST_P_VO_CRU		458781
+#define SRST_H_SDIO		458783
+/********Name=VOSOFTRST_CON02,Offset=0x1CA08********/
+#define SRST_P_TSADC		458784
+#define SRST_TSADC		458785
+#define SRST_P_OTPC_NS		458787
+#define SRST_SBPI_OTPC_NS	458789
+#define SRST_USER_OTPC_NS	458790
+#define SRST_P_OTPC_S		458791
+#define SRST_SBPI_OTPC_S	458793
+#define SRST_USER_OTPC_S	458794
+#define SRST_OTPC_ARB		458795
+#define SRST_MACPHY		458797
+#define SRST_P_OTP_MASK		458798
+#define SRST_PMC_OTP		458799
+/********Name=VOSOFTRST_CON03,Offset=0x1CA0C********/
+#define SRST_P_GPIO2		458800
+#define SRST_GPIO2		458801
+#define SRST_P_VO_IOC		458802
+/********Name=DDRSOFTRST_CON00,Offset=0x1EA00********/
+#define SRST_P_DDR_BIU		491522
+#define SRST_P_DDRC		491525
+#define SRST_P_DDRMON		491527
+#define SRST_TIMER_DDRMON	491528
+#define SRST_P_DFICTRL		491531
+#define SRST_A_SYS_SHRM		491533
+#define SRST_A_SHRM_NIU		491534
+#define SRST_P_DDR_GRF		491535
+/********Name=DDRSOFTRST_CON01,Offset=0x1EA04********/
+#define SRST_P_DDR_CRU		491536
+#define SRST_P_DDR_HWLP		491538
+#define SRST_P_DDRPHY		491539
+/********Name=SUBDDRSOFTRST_CON00,Offset=0x1FA00********/
+#define SRST_MSCH_BIU		507904
+#define SRST_A_DDRC		507905
+#define SRST_CORE_DDRC		507907
+#define SRST_DDRMON		507908
+#define SRST_DFICTRL		507909
+#define SRST_DDR_PHY		507910
+
+#endif
-- 
2.43.0


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

* [PATCH v3 12/15] clk: rockchip: Add RV1106 clock driver
  2026-07-07 15:30 [PATCH v3 00/15] rockchip: Add support for the RV1103B, RV1103 and RV1106 Simon Glass
                   ` (10 preceding siblings ...)
  2026-07-07 15:31 ` [PATCH v3 11/15] ARM: dts: Add the RV1103/RV1106 devicetree files Simon Glass
@ 2026-07-07 15:31 ` Simon Glass
  2026-07-07 15:31 ` [PATCH v3 13/15] rockchip: rv1106: Add SoC support Simon Glass
                   ` (3 subsequent siblings)
  15 siblings, 0 replies; 21+ messages in thread
From: Simon Glass @ 2026-07-07 15:31 UTC (permalink / raw)
  To: u-boot
  Cc: Fabio Estevam, Jonas Karlman, Simon Glass, Elaine Zhang,
	Finley Xiao, Ilias Apalodimas, Jeffy Chen, Kever Yang,
	Lukasz Majewski, Philipp Tomsich, Tom Rini, huang lin

Add the clock driver for the RV1106, based on the driver in the
Rockchip vendor tree, with the vendor-specific clk-dump and MMC
phase-tuning code removed and the driver-model API usage brought up to
date.

The RV1103 is a package variant of the RV1106 and shares this driver

Signed-off-by: Simon Glass <sjg@chromium.org>
---

(no changes since v1)

 .../include/asm/arch-rockchip/cru_rv1106.h    |  305 ++++
 drivers/clk/rockchip/Makefile                 |    1 +
 drivers/clk/rockchip/clk_rv1106.c             | 1319 +++++++++++++++++
 3 files changed, 1625 insertions(+)
 create mode 100644 arch/arm/include/asm/arch-rockchip/cru_rv1106.h
 create mode 100644 drivers/clk/rockchip/clk_rv1106.c

diff --git a/arch/arm/include/asm/arch-rockchip/cru_rv1106.h b/arch/arm/include/asm/arch-rockchip/cru_rv1106.h
new file mode 100644
index 00000000000..8e3ac228c2b
--- /dev/null
+++ b/arch/arm/include/asm/arch-rockchip/cru_rv1106.h
@@ -0,0 +1,305 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2022 Rockchip Electronics Co. Ltd.
+ * Author: Elaine Zhang <zhangqing@rock-chips.com>
+ */
+
+#ifndef _ASM_ARCH_CRU_RV1106_H
+#define _ASM_ARCH_CRU_RV1106_H
+
+
+#define MHz		1000000
+#define KHz		1000
+#define OSC_HZ		(24 * MHz)
+
+#define APLL_HZ		(816 * MHz)
+#define GPLL_HZ		(1188 * MHz)
+#define CPLL_HZ		(1000 * MHz)
+
+/* RV1106 pll id */
+enum rv1106_pll_id {
+	APLL,
+	DPLL,
+	CPLL,
+	GPLL,
+	PLL_COUNT,
+};
+
+struct rv1106_clk_info {
+	unsigned long id;
+	char *name;
+	bool is_cru;
+};
+
+struct rv1106_clk_priv {
+	struct rv1106_cru *cru;
+	struct rv1106_grf *grf;
+	ulong gpll_hz;
+	ulong cpll_hz;
+	ulong armclk_hz;
+	ulong armclk_enter_hz;
+	ulong armclk_init_hz;
+	bool sync_kernel;
+	bool set_armclk_rate;
+};
+
+struct rv1106_grf_clk_priv {
+	struct rv1106_grf *grf;
+};
+
+struct rv1106_pll {
+	unsigned int con0;
+	unsigned int con1;
+	unsigned int con2;
+	unsigned int con3;
+	unsigned int con4;
+	unsigned int reserved0[3];
+};
+
+struct rv1106_cru {
+	unsigned int reserved0[192];
+	unsigned int pmu_clksel_con[8];
+	unsigned int reserved1[312];
+	unsigned int pmu_clkgate_con[3];
+	unsigned int reserved2[125];
+	unsigned int pmu_softrst_con[3];
+	unsigned int reserved3[15741];
+	struct rv1106_pll pll[4];
+	unsigned int reserved4[128];
+	unsigned int mode;
+	unsigned int reserved5[31];
+	unsigned int clksel_con[34];
+	unsigned int reserved6[286];
+	unsigned int clkgate_con[4];
+	unsigned int reserved7[124];
+	unsigned int softrst_con[3];
+	unsigned int reserved8[125];
+	unsigned int glb_cnt_th;
+	unsigned int glb_rst_st;
+	unsigned int glb_srst_fst;
+	unsigned int glb_srst_snd;
+	unsigned int glb_rst_con;
+	unsigned int con[2];
+	unsigned int sdmmc_con[2];
+	unsigned int emmc_con[2];
+	unsigned int reserved9[1461];
+	unsigned int peri_clksel_con[12];
+	unsigned int reserved10[308];
+	unsigned int peri_clkgate_con[8];
+	unsigned int reserved11[120];
+	unsigned int peri_softrst_con[8];
+	unsigned int reserved12[1592];
+	unsigned int vi_clksel_con[4];
+	unsigned int reserved13[316];
+	unsigned int vi_clkgate_con[3];
+	unsigned int reserved14[125];
+	unsigned int vi_softrst_con[3];
+	unsigned int reserved15[3645];
+	unsigned int core_clksel_con[5];
+	unsigned int reserved16[2043];
+	unsigned int vepu_clksel_con[2];
+	unsigned int reserved17[318];
+	unsigned int vepu_clkgate_con[3];
+	unsigned int reserved18[125];
+	unsigned int vepu_softrst_con[2];
+	unsigned int reserved19[1598];
+	unsigned int vo_clksel_con[4];
+	unsigned int reserved20[316];
+	unsigned int vo_clkgate_con[3];
+	unsigned int reserved21[125];
+	unsigned int vo_softrst_con[4];
+};
+check_member(rv1106_cru, vo_softrst_con[0], 0x1ca00);
+
+struct pll_rate_table {
+	unsigned long rate;
+	unsigned int fbdiv;
+	unsigned int postdiv1;
+	unsigned int refdiv;
+	unsigned int postdiv2;
+	unsigned int dsmpd;
+	unsigned int frac;
+};
+
+#define RV1106_TOPCRU_BASE		0x10000
+#define RV1106_SUBDDRCRU_BASE		0x1F000
+
+#define RV1106_PLL_CON(x)		((x) * 0x4 + RV1106_TOPCRU_BASE)
+#define RV1106_MODE_CON			(0x280 + RV1106_TOPCRU_BASE)
+#define RV1106_SUBDDRMODE_CON		(0x280 + RV1106_SUBDDRCRU_BASE)
+
+enum {
+	/* CRU_PMU_CLK_SEL0_CON */
+	CLK_I2C1_SEL_SHIFT		= 6,
+	CLK_I2C1_SEL_MASK		= 0x3 << CLK_I2C1_SEL_SHIFT,
+	CLK_I2C1_SEL_200M		= 0,
+	CLK_I2C1_SEL_100M,
+	CLK_I2C1_SEL_24M,
+	CLK_I2C1_SEL_32K,
+	HCLK_PMU_SEL_SHIFT		= 4,
+	HCLK_PMU_SEL_MASK		= 0x3 << HCLK_PMU_SEL_SHIFT,
+	HCLK_PMU_SEL_200M		= 0,
+	HCLK_PMU_SEL_100M,
+	HCLK_PMU_SEL_24M,
+	PCLK_PMU_SEL_SHIFT		= 3,
+	PCLK_PMU_SEL_MASK		= 0x1 << PCLK_PMU_SEL_SHIFT,
+	PCLK_PMU_SEL_100M		= 0,
+	PCLK_PMU_SEL_24M,
+
+	/* CRU_CLK_SEL5_CON */
+	CLK_UART_SRC_SEL_SHIFT		= 5,
+	CLK_UART_SRC_SEL_MASK		= 0x1 << CLK_UART_SRC_SEL_SHIFT,
+	CLK_UART_SRC_SEL_GPLL		= 0,
+	CLK_UART_SRC_SEL_CPLL,
+	CLK_UART_SRC_DIV_SHIFT		= 0,
+	CLK_UART_SRC_DIV_MASK		= 0x1f << CLK_UART_SRC_DIV_SHIFT,
+
+	/* CRU_CLK_SEL6_CON */
+	CLK_UART_FRAC_NUMERATOR_SHIFT	= 16,
+	CLK_UART_FRAC_NUMERATOR_MASK	= 0xffff << 16,
+	CLK_UART_FRAC_DENOMINATOR_SHIFT	= 0,
+	CLK_UART_FRAC_DENOMINATOR_MASK	= 0xffff,
+
+	/* CRU_CLK_SEL7_CON */
+	CLK_UART_SEL_SHIFT		= 0,
+	CLK_UART_SEL_MASK		= 0x3 << CLK_UART_SEL_SHIFT,
+	CLK_UART_SEL_SRC		= 0,
+	CLK_UART_SEL_FRAC,
+	CLK_UART_SEL_XIN24M,
+
+	/* CRU_CLK_SEL23_CON */
+	DCLK_VOP_SEL_SHIFT		= 8,
+	DCLK_VOP_SEL_MASK		= 0x1 << DCLK_VOP_SEL_SHIFT,
+	DCLK_VOP_SEL_GPLL		= 0,
+	DCLK_VOP_SEL_CPLL,
+	DCLK_VOP_DIV_SHIFT		= 3,
+	DCLK_VOP_DIV_MASK		= 0x1f << DCLK_VOP_DIV_SHIFT,
+
+	/* CRU_CLK_SEL24_CON */
+	PCLK_TOP_SEL_SHIFT		= 5,
+	PCLK_TOP_SEL_MASK		= 0x3 << PCLK_TOP_SEL_SHIFT,
+	PCLK_TOP_SEL_100M		= 0,
+	PCLK_TOP_SEL_50M,
+	PCLK_TOP_SEL_24M,
+
+	/* CRU_PERI_CLK_SEL1_CON */
+	CLK_I2C3_SEL_SHIFT		= 14,
+	CLK_I2C3_SEL_MASK		= 0x3 << CLK_I2C3_SEL_SHIFT,
+	CLK_I2C2_SEL_SHIFT		= 12,
+	CLK_I2C2_SEL_MASK		= 0x3 << CLK_I2C2_SEL_SHIFT,
+	CLK_I2C0_SEL_SHIFT		= 8,
+	CLK_I2C0_SEL_MASK		= 0x3 << CLK_I2C0_SEL_SHIFT,
+	CLK_I2C0_SEL_200M		= 0,
+	CLK_I2C0_SEL_100M,
+	CLK_I2C0_SEL_50M,
+	CLK_I2C0_SEL_24M,
+	HCLK_PERI_SEL_SHIFT		= 4,
+	HCLK_PERI_SEL_MASK		= 0x3 << HCLK_PERI_SEL_SHIFT,
+	HCLK_PERI_SEL_200M		= 0,
+	HCLK_PERI_SEL_100M,
+	HCLK_PERI_SEL_50M,
+	HCLK_PERI_SEL_24M,
+	ACLK_PERI_SEL_SHIFT		= 2,
+	ACLK_PERI_SEL_MASK		= 0x3 << ACLK_PERI_SEL_SHIFT,
+	ACLK_PERI_SEL_400M		= 0,
+	ACLK_PERI_SEL_200M,
+	ACLK_PERI_SEL_100M,
+	ACLK_PERI_SEL_24M,
+	PCLK_PERI_SEL_SHIFT		= 0,
+	PCLK_PERI_SEL_MASK		= 0x3 << PCLK_PERI_SEL_SHIFT,
+	PCLK_PERI_SEL_100M		= 0,
+	PCLK_PERI_SEL_50M,
+	PCLK_PERI_SEL_24M,
+
+	/* CRU_PERI_CLK_SEL2_CON */
+	CLK_I2C4_SEL_SHIFT		= 0,
+	CLK_I2C4_SEL_MASK		= 0x3 << CLK_I2C4_SEL_SHIFT,
+
+	/* CRU_PERI_CLK_SEL6_CON */
+	CLK_PWM2_SEL_SHIFT		= 11,
+	CLK_PWM2_SEL_MASK		= 0x3 << CLK_PWM2_SEL_SHIFT,
+	CLK_PWM1_SEL_SHIFT		= 9,
+	CLK_PWM1_SEL_MASK		= 0x3 << CLK_PWM1_SEL_SHIFT,
+	CLK_PWM_SEL_100M		= 0,
+	CLK_PWM_SEL_50M,
+	CLK_PWM_SEL_24M,
+	CLK_PKA_CRYPTO_SEL_SHIFT	= 7,
+	CLK_PKA_CRYPTO_SEL_MASK		= 0x3 << CLK_PKA_CRYPTO_SEL_SHIFT,
+	CLK_CORE_CRYPTO_SEL_SHIFT	= 5,
+	CLK_CORE_CRYPTO_SEL_MASK	= 0x3 << CLK_CORE_CRYPTO_SEL_SHIFT,
+	CLK_CRYPTO_SEL_300M		= 0,
+	CLK_CRYPTO_SEL_200M,
+	CLK_CRYPTO_SEL_100M,
+	CLK_CRYPTO_SEL_24M,
+	CLK_SARADC_DIV_SHIFT		= 0,
+	CLK_SARADC_DIV_MASK		= 0x7 << CLK_SARADC_DIV_SHIFT,
+	CLK_SPI1_SEL_SHIFT		= 3,
+	CLK_SPI1_SEL_MASK		= 0x3 << CLK_SPI1_SEL_SHIFT,
+
+	/* CRU_PERI_CLK_SEL7_CON */
+	DCLK_DECOM_SEL_SHIFT		= 14,
+	DCLK_DECOM_SEL_MASK		= 0x3 << DCLK_DECOM_SEL_SHIFT,
+	DCLK_DECOM_SEL_400M		= 0,
+	DCLK_DECOM_SEL_200M,
+	DCLK_DECOM_SEL_100M,
+	DCLK_DECOM_SEL_24M,
+	CLK_SFC_SEL_SHIFT		= 12,
+	CLK_SFC_SEL_MASK		= 0x3 << CLK_SFC_SEL_SHIFT,
+	CLK_SFC_SEL_500M		= 0,
+	CLK_SFC_SEL_300M,
+	CLK_SFC_SEL_200M,
+	CLK_SFC_SEL_24M,
+	CLK_SFC_DIV_SHIFT		= 7,
+	CLK_SFC_DIV_MASK		= 0x1f << CLK_SFC_DIV_SHIFT,
+	CLK_EMMC_SEL_SHIFT		= 6,
+	CLK_EMMC_SEL_MASK		= 0x1 << CLK_EMMC_SEL_SHIFT,
+	CLK_MMC_SEL_400M		= 0,
+	CLK_MMC_SEL_24M,
+	CLK_EMMC_DIV_SHIFT		= 0,
+	CLK_EMMC_DIV_MASK		= 0x3f << CLK_EMMC_DIV_SHIFT,
+
+	/* CRU_PERI_CLK_SEL9_CON */
+	ACLK_BUS_SEL_SHIFT		= 0,
+	ACLK_BUS_SEL_MASK		= 0x3 << ACLK_BUS_SEL_SHIFT,
+	ACLK_BUS_SEL_300M		= 0,
+	ACLK_BUS_SEL_200M,
+	ACLK_BUS_SEL_100M,
+	ACLK_BUS_SEL_24M,
+
+	/* CRU_PERI_CLK_SEL11_CON */
+	CLK_PWM0_SEL_SHIFT		= 0,
+	CLK_PWM0_SEL_MASK		= 0x3 << CLK_PWM0_SEL_SHIFT,
+
+	/* CRU_VEPU_CLK_SEL0_CON */
+	CLK_SPI0_SEL_SHIFT		= 12,
+	CLK_SPI0_SEL_MASK		= 0x3 << CLK_SPI0_SEL_SHIFT,
+	CLK_SPI0_SEL_200M		= 0,
+	CLK_SPI0_SEL_100M,
+	CLK_SPI0_SEL_50M,
+	CLK_SPI0_SEL_24M,
+
+	/* CRU_CORE_CLK_SEL0_CON */
+	CLK_CORE_DIV_SHIFT		= 0,
+	CLK_CORE_DIV_MASK		= 0x1f << CLK_CORE_DIV_SHIFT,
+
+	/* CRU_VI_CLK_SEL1_CON */
+	CLK_SDMMC_SEL_SHIFT		= 14,
+	CLK_SDMMC_SEL_MASK		= 0x1 << CLK_SDMMC_SEL_SHIFT,
+	CLK_SDMMC_DIV_SHIFT		= 8,
+	CLK_SDMMC_DIV_MASK		= 0x3f << CLK_SDMMC_DIV_SHIFT,
+
+	/* CRU_VO_CLK_SEL1_CON */
+	ACLK_VOP_SEL_SHIFT		= 10,
+	ACLK_VOP_SEL_MASK		= 0x3 << ACLK_VOP_SEL_SHIFT,
+	ACLK_VOP_SEL_300M		= 0,
+	ACLK_VOP_SEL_200M,
+	ACLK_VOP_SEL_100M,
+	ACLK_VOP_SEL_24M,
+
+	/* CRU_VO_CLK_SEL3_CON */
+	CLK_TSADC_TSEN_DIV_SHIFT	= 5,
+	CLK_TSADC_TSEN_DIV_MASK		= 0x1F << CLK_TSADC_TSEN_DIV_SHIFT,
+	CLK_TSADC_DIV_SHIFT		= 0,
+	CLK_TSADC_DIV_MASK		= 0x1F << CLK_TSADC_DIV_SHIFT,
+};
+#endif
diff --git a/drivers/clk/rockchip/Makefile b/drivers/clk/rockchip/Makefile
index de2635b7475..d76f7d02634 100644
--- a/drivers/clk/rockchip/Makefile
+++ b/drivers/clk/rockchip/Makefile
@@ -21,5 +21,6 @@ obj-$(CONFIG_ROCKCHIP_RK3568) += clk_rk3568.o
 obj-$(CONFIG_ROCKCHIP_RK3576) += clk_rk3576.o
 obj-$(CONFIG_ROCKCHIP_RK3588) += clk_rk3588.o
 obj-$(CONFIG_ROCKCHIP_RV1103B) += clk_rv1103b.o
+obj-$(CONFIG_ROCKCHIP_RV1106) += clk_rv1106.o
 obj-$(CONFIG_ROCKCHIP_RV1108) += clk_rv1108.o
 obj-$(CONFIG_ROCKCHIP_RV1126) += clk_rv1126.o
diff --git a/drivers/clk/rockchip/clk_rv1106.c b/drivers/clk/rockchip/clk_rv1106.c
new file mode 100644
index 00000000000..7c23c9633df
--- /dev/null
+++ b/drivers/clk/rockchip/clk_rv1106.c
@@ -0,0 +1,1319 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2021 Rockchip Electronics Co., Ltd
+ * Author: Elaine Zhang <zhangqing@rock-chips.com>
+ */
+
+#include <bitfield.h>
+#include <clk.h>
+#include <clk-uclass.h>
+#include <dm.h>
+#include <errno.h>
+#include <log.h>
+#include <malloc.h>
+#include <syscon.h>
+#include <asm/arch-rockchip/clock.h>
+#include <asm/arch-rockchip/cru_rv1106.h>
+#include <asm/arch-rockchip/hardware.h>
+#include <asm/global_data.h>
+#include <asm/io.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
+#include <dt-bindings/clock/rv1106-cru.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define DIV_TO_RATE(input_rate, div)	((input_rate) / ((div) + 1))
+
+static struct rockchip_pll_rate_table rv1106_pll_rates[] = {
+	/* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */
+	RK3036_PLL_RATE(1188000000, 1, 99, 2, 1, 1, 0),
+	RK3036_PLL_RATE(1104000000, 1, 92, 2, 1, 1, 0),
+	RK3036_PLL_RATE(1008000000, 1, 84, 2, 1, 1, 0),
+	RK3036_PLL_RATE(1000000000, 3, 250, 2, 1, 1, 0),
+	RK3036_PLL_RATE(816000000, 1, 68, 2, 1, 1, 0),
+	RK3036_PLL_RATE(600000000, 1, 100, 4, 1, 1, 0),
+	RK3036_PLL_RATE(594000000, 1, 99, 4, 1, 1, 0),
+	{ /* sentinel */ },
+};
+
+static struct rockchip_pll_clock rv1106_pll_clks[] = {
+	[APLL] = PLL(pll_rk3328, PLL_APLL, RV1106_PLL_CON(0),
+		     RV1106_MODE_CON, 0, 10, 0, rv1106_pll_rates),
+	[DPLL] = PLL(pll_rk3328, PLL_DPLL, RV1106_PLL_CON(16),
+		     RV1106_SUBDDRMODE_CON, 0, 10, 0, NULL),
+	[CPLL] = PLL(pll_rk3328, PLL_CPLL, RV1106_PLL_CON(8),
+		     RV1106_MODE_CON, 2, 10, 0, rv1106_pll_rates),
+	[GPLL] = PLL(pll_rk3328, PLL_GPLL, RV1106_PLL_CON(24),
+		     RV1106_MODE_CON, 4, 10, 0, rv1106_pll_rates),
+};
+
+static ulong rv1106_peri_get_clk(struct rv1106_clk_priv *priv, ulong clk_id)
+{
+	struct rv1106_cru *cru = priv->cru;
+	u32 con, sel, rate;
+
+	switch (clk_id) {
+	case ACLK_PERI_ROOT:
+		con = readl(&cru->peri_clksel_con[1]);
+		sel = (con & ACLK_PERI_SEL_MASK) >> ACLK_PERI_SEL_SHIFT;
+		if (sel == ACLK_PERI_SEL_400M)
+			rate = 400 * MHz;
+		else if (sel == ACLK_PERI_SEL_200M)
+			rate = 200 * MHz;
+		else if (sel == ACLK_PERI_SEL_100M)
+			rate = 100 * MHz;
+		else
+			rate = OSC_HZ;
+		break;
+	case HCLK_PERI_ROOT:
+		con = readl(&cru->peri_clksel_con[1]);
+		sel = (con & HCLK_PERI_SEL_MASK) >> HCLK_PERI_SEL_SHIFT;
+		if (sel == HCLK_PERI_SEL_200M)
+			rate = 200 * MHz;
+		else if (sel == HCLK_PERI_SEL_100M)
+			rate = 100 * MHz;
+		else if (sel == HCLK_PERI_SEL_50M)
+			rate = 50 * MHz;
+		else
+			rate = OSC_HZ;
+		break;
+	case PCLK_PERI_ROOT:
+		con = readl(&cru->peri_clksel_con[1]);
+		sel = (con & PCLK_PERI_SEL_MASK) >> PCLK_PERI_SEL_SHIFT;
+		if (sel == PCLK_PERI_SEL_100M)
+			rate = 100 * MHz;
+		else if (sel == PCLK_PERI_SEL_50M)
+			rate = 50 * MHz;
+		else
+			rate = OSC_HZ;
+		break;
+	case ACLK_BUS_ROOT:
+		con = readl(&cru->peri_clksel_con[9]);
+		sel = (con & ACLK_BUS_SEL_MASK) >> ACLK_BUS_SEL_SHIFT;
+		if (sel == ACLK_BUS_SEL_300M)
+			rate = 300 * MHz;
+		else if (sel == ACLK_BUS_SEL_200M)
+			rate = 200 * MHz;
+		else if (sel == ACLK_BUS_SEL_100M)
+			rate = 100 * MHz;
+		else
+			rate = OSC_HZ;
+		break;
+	case PCLK_TOP_ROOT:
+		con = readl(&cru->clksel_con[24]);
+		sel = (con & PCLK_TOP_SEL_MASK) >> PCLK_TOP_SEL_SHIFT;
+		if (sel == PCLK_TOP_SEL_100M)
+			rate = 100 * MHz;
+		else if (sel == PCLK_TOP_SEL_50M)
+			rate = 50 * MHz;
+		else
+			rate = OSC_HZ;
+		break;
+	case PCLK_PMU_ROOT:
+		con = readl(&cru->pmu_clksel_con[0]);
+		sel = (con & PCLK_PMU_SEL_MASK) >> PCLK_PMU_SEL_SHIFT;
+		if (sel == PCLK_PMU_SEL_100M)
+			rate = 100 * MHz;
+		else
+			rate = OSC_HZ;
+		break;
+	case HCLK_PMU_ROOT:
+		con = readl(&cru->pmu_clksel_con[0]);
+		sel = (con & HCLK_PMU_SEL_MASK) >> HCLK_PMU_SEL_SHIFT;
+		if (sel == HCLK_PMU_SEL_200M)
+			rate = 200 * MHz;
+		else if (sel == HCLK_PMU_SEL_100M)
+			rate = 100 * MHz;
+		else
+			rate = OSC_HZ;
+		break;
+	default:
+		return -ENOENT;
+	}
+
+	return rate;
+}
+
+static ulong rv1106_peri_set_clk(struct rv1106_clk_priv *priv,
+				 ulong clk_id, ulong rate)
+{
+	struct rv1106_cru *cru = priv->cru;
+	int src_clk;
+
+	switch (clk_id) {
+	case ACLK_PERI_ROOT:
+		if (rate >= 396 * MHz)
+			src_clk = ACLK_PERI_SEL_400M;
+		else if (rate >= 198 * MHz)
+			src_clk = ACLK_PERI_SEL_200M;
+		else if (rate >= 99 * MHz)
+			src_clk = ACLK_PERI_SEL_100M;
+		else
+			src_clk = ACLK_PERI_SEL_24M;
+		rk_clrsetreg(&cru->peri_clksel_con[1],
+			     ACLK_PERI_SEL_MASK,
+			     src_clk << ACLK_PERI_SEL_SHIFT);
+		break;
+	case HCLK_PERI_ROOT:
+		if (rate >= 198 * MHz)
+			src_clk = HCLK_PERI_SEL_200M;
+		else if (rate >= 99 * MHz)
+			src_clk = HCLK_PERI_SEL_100M;
+		else if (rate >= 48 * MHz)
+			src_clk = HCLK_PERI_SEL_50M;
+		else
+			src_clk = HCLK_PERI_SEL_24M;
+		rk_clrsetreg(&cru->peri_clksel_con[1],
+			     HCLK_PERI_SEL_MASK,
+			     src_clk << HCLK_PERI_SEL_SHIFT);
+		break;
+	case PCLK_PERI_ROOT:
+		if (rate >= 99 * MHz)
+			src_clk = PCLK_PERI_SEL_100M;
+		else if (rate >= 48 * MHz)
+			src_clk = PCLK_PERI_SEL_50M;
+		else
+			src_clk = PCLK_PERI_SEL_24M;
+		rk_clrsetreg(&cru->peri_clksel_con[1],
+			     PCLK_PERI_SEL_MASK,
+			     src_clk << PCLK_PERI_SEL_SHIFT);
+		break;
+	case ACLK_BUS_ROOT:
+		if (rate >= 297 * MHz)
+			src_clk = ACLK_BUS_SEL_300M;
+		else if (rate >= 198 * MHz)
+			src_clk = ACLK_BUS_SEL_200M;
+		else if (rate >= 99 * MHz)
+			src_clk = ACLK_BUS_SEL_100M;
+		else
+			src_clk = ACLK_BUS_SEL_24M;
+		rk_clrsetreg(&cru->peri_clksel_con[9],
+			     ACLK_BUS_SEL_MASK,
+			     src_clk << ACLK_BUS_SEL_SHIFT);
+		break;
+	case PCLK_TOP_ROOT:
+		if (rate >= 99 * MHz)
+			src_clk = PCLK_TOP_SEL_100M;
+		else if (rate >= 48 * MHz)
+			src_clk = PCLK_TOP_SEL_50M;
+		else
+			src_clk = PCLK_TOP_SEL_24M;
+		rk_clrsetreg(&cru->clksel_con[24],
+			     PCLK_TOP_SEL_MASK,
+			     src_clk << PCLK_TOP_SEL_SHIFT);
+		break;
+	case PCLK_PMU_ROOT:
+		if (rate >= 99 * MHz)
+			src_clk = PCLK_PMU_SEL_100M;
+		else
+			src_clk = PCLK_PMU_SEL_24M;
+		rk_clrsetreg(&cru->pmu_clksel_con[0],
+			     PCLK_PMU_SEL_MASK,
+			     src_clk << PCLK_PMU_SEL_SHIFT);
+		break;
+	case HCLK_PMU_ROOT:
+		if (rate >= 198 * MHz)
+			src_clk = HCLK_PMU_SEL_200M;
+		else if (rate >= 99 * MHz)
+			src_clk = HCLK_PMU_SEL_100M;
+		else
+			src_clk = HCLK_PMU_SEL_24M;
+		rk_clrsetreg(&cru->pmu_clksel_con[0],
+			     HCLK_PMU_SEL_MASK,
+			     src_clk << HCLK_PMU_SEL_SHIFT);
+		break;
+	default:
+		printf("do not support this permid freq\n");
+		return -EINVAL;
+	}
+
+	return rv1106_peri_get_clk(priv, clk_id);
+}
+
+static ulong rv1106_i2c_get_clk(struct rv1106_clk_priv *priv, ulong clk_id)
+{
+	struct rv1106_cru *cru = priv->cru;
+	u32 sel, con;
+	ulong rate;
+
+	switch (clk_id) {
+	case CLK_I2C1:
+		con = readl(&cru->pmu_clksel_con[0]);
+		sel = (con & CLK_I2C1_SEL_MASK) >> CLK_I2C1_SEL_SHIFT;
+		if (sel == CLK_I2C1_SEL_200M)
+			rate = 200 * MHz;
+		else if (sel == CLK_I2C1_SEL_100M)
+			rate = 100 * MHz;
+		else if (sel == CLK_I2C1_SEL_24M)
+			rate = OSC_HZ;
+		else
+			rate = 32768;
+		return rate;
+	case CLK_I2C0:
+		con = readl(&cru->peri_clksel_con[1]);
+		sel = (con & CLK_I2C0_SEL_MASK) >> CLK_I2C0_SEL_SHIFT;
+		break;
+	case CLK_I2C2:
+		con = readl(&cru->peri_clksel_con[1]);
+		sel = (con & CLK_I2C2_SEL_MASK) >> CLK_I2C2_SEL_SHIFT;
+		break;
+	case CLK_I2C3:
+		con = readl(&cru->peri_clksel_con[1]);
+		sel = (con & CLK_I2C3_SEL_MASK) >> CLK_I2C3_SEL_SHIFT;
+		break;
+	case CLK_I2C4:
+		con = readl(&cru->peri_clksel_con[2]);
+		sel = (con & CLK_I2C4_SEL_MASK) >> CLK_I2C4_SEL_SHIFT;
+		break;
+	default:
+		return -ENOENT;
+	}
+
+	if (sel == CLK_I2C0_SEL_200M)
+		rate = 200 * MHz;
+	else if (sel == CLK_I2C0_SEL_100M)
+		rate = 100 * MHz;
+	else if (sel == CLK_I2C0_SEL_50M)
+		rate = 50 * MHz;
+	else
+		rate = OSC_HZ;
+
+	return rate;
+}
+
+static ulong rv1106_crypto_get_clk(struct rv1106_clk_priv *priv, ulong clk_id)
+{
+	struct rv1106_cru *cru = priv->cru;
+	u32 sel, con;
+
+	switch (clk_id) {
+	case CLK_CORE_CRYPTO:
+		con = readl(&cru->peri_clksel_con[6]);
+		sel = (con & CLK_CORE_CRYPTO_SEL_MASK) >>
+		      CLK_CORE_CRYPTO_SEL_SHIFT;
+		break;
+	case CLK_PKA_CRYPTO:
+		con = readl(&cru->peri_clksel_con[6]);
+		sel = (con & CLK_PKA_CRYPTO_SEL_MASK) >>
+		      CLK_PKA_CRYPTO_SEL_SHIFT;
+		break;
+	default:
+		return -ENOENT;
+	}
+	switch (sel) {
+	case CLK_CRYPTO_SEL_300M:
+		return 300 * MHz;
+	case CLK_CRYPTO_SEL_200M:
+		return 200 * MHz;
+	case CLK_CRYPTO_SEL_100M:
+		return 100 * MHz;
+	case CLK_CRYPTO_SEL_24M:
+		return OSC_HZ;
+	default:
+		return -ENOENT;
+	}
+}
+
+static ulong rv1106_crypto_set_clk(struct rv1106_clk_priv *priv,
+				   ulong clk_id, ulong rate)
+{
+	struct rv1106_cru *cru = priv->cru;
+	u32 sel;
+
+	if (rate >= 297 * MHz)
+		sel = CLK_CRYPTO_SEL_300M;
+	else if (rate >= 198 * MHz)
+		sel = CLK_CRYPTO_SEL_200M;
+	else if (rate >= 99 * MHz)
+		sel = CLK_CRYPTO_SEL_100M;
+	else
+		sel = CLK_CRYPTO_SEL_24M;
+
+	switch (clk_id) {
+	case CLK_CORE_CRYPTO:
+		rk_clrsetreg(&cru->peri_clksel_con[6],
+			     CLK_CORE_CRYPTO_SEL_MASK,
+			     sel << CLK_CORE_CRYPTO_SEL_SHIFT);
+		break;
+	case CLK_PKA_CRYPTO:
+		rk_clrsetreg(&cru->peri_clksel_con[6],
+			     CLK_PKA_CRYPTO_SEL_MASK,
+			     sel << CLK_PKA_CRYPTO_SEL_SHIFT);
+		break;
+	default:
+		return -ENOENT;
+	}
+	return rv1106_crypto_get_clk(priv, clk_id);
+}
+
+static ulong rv1106_mmc_get_clk(struct rv1106_clk_priv *priv, ulong clk_id)
+{
+	struct rv1106_cru *cru = priv->cru;
+	u32 div, sel, con, prate;
+
+	switch (clk_id) {
+	case CCLK_SRC_SDMMC:
+	case HCLK_SDMMC:
+		con = readl(&cru->vi_clksel_con[1]);
+		sel = (con & CLK_SDMMC_SEL_MASK) >>
+		      CLK_SDMMC_SEL_SHIFT;
+		div = (con & CLK_SDMMC_DIV_MASK) >>
+		      CLK_SDMMC_DIV_SHIFT;
+		if (sel == CLK_MMC_SEL_400M)
+			prate = 400 * MHz;
+		else
+			prate = OSC_HZ;
+		return DIV_TO_RATE(prate, div);
+	case CCLK_SRC_EMMC:
+	case HCLK_EMMC:
+		con = readl(&cru->peri_clksel_con[7]);
+		sel = (con & CLK_EMMC_SEL_MASK) >>
+		      CLK_EMMC_SEL_SHIFT;
+		div = (con & CLK_EMMC_DIV_MASK) >>
+		      CLK_EMMC_DIV_SHIFT;
+		if (sel)
+			prate = OSC_HZ;
+		else
+			prate = 400 * MHz;
+		return DIV_TO_RATE(prate, div);
+	case SCLK_SFC:
+	case HCLK_SFC:
+		con = readl(&cru->peri_clksel_con[7]);
+		sel = (con & CLK_SFC_SEL_MASK) >>
+		      CLK_SFC_SEL_SHIFT;
+		div = (con & CLK_SFC_DIV_MASK) >>
+		      CLK_SFC_DIV_SHIFT;
+		if (sel == CLK_SFC_SEL_500M)
+			prate = 500 * MHz;
+		else if (sel == CLK_SFC_SEL_300M)
+			prate = 300 * MHz;
+		else if (sel == CLK_SFC_SEL_200M)
+			prate = 200 * MHz;
+		else
+			prate = OSC_HZ;
+		return DIV_TO_RATE(prate, div);
+	default:
+		return -ENOENT;
+	}
+}
+
+static ulong rv1106_mmc_set_clk(struct rv1106_clk_priv *priv,
+				ulong clk_id, ulong rate)
+{
+	struct rv1106_cru *cru = priv->cru;
+	u32 sel, src_clk_div;
+	ulong prate = 0;
+
+	if ((OSC_HZ % rate) == 0) {
+		sel = CLK_MMC_SEL_24M;
+		prate = OSC_HZ;
+	} else {
+		sel = CLK_MMC_SEL_400M;
+		prate = 400 * MHz;
+	}
+	src_clk_div = DIV_ROUND_UP(prate, rate);
+
+	switch (clk_id) {
+	case CCLK_SRC_SDMMC:
+	case HCLK_SDMMC:
+		if ((OSC_HZ % rate) == 0) {
+			sel = CLK_MMC_SEL_24M;
+			prate = OSC_HZ;
+		} else {
+			sel = CLK_MMC_SEL_400M;
+			prate = 400 * MHz;
+		}
+		src_clk_div = DIV_ROUND_UP(prate, rate);
+		rk_clrsetreg(&cru->vi_clksel_con[1],
+			     CLK_SDMMC_SEL_MASK |
+			     CLK_SDMMC_DIV_MASK,
+			     (sel << CLK_SDMMC_SEL_SHIFT) |
+			     ((src_clk_div - 1) <<
+			      CLK_SDMMC_DIV_SHIFT));
+		break;
+	case CCLK_SRC_EMMC:
+	case HCLK_EMMC:
+		if ((OSC_HZ % rate) == 0) {
+			sel = CLK_MMC_SEL_24M;
+			prate = OSC_HZ;
+		} else {
+			sel = CLK_MMC_SEL_400M;
+			prate = 400 * MHz;
+		}
+		src_clk_div = DIV_ROUND_UP(prate, rate);
+		rk_clrsetreg(&cru->peri_clksel_con[7],
+			     CLK_EMMC_SEL_MASK |
+			     CLK_EMMC_DIV_MASK,
+			     (sel << CLK_EMMC_SEL_SHIFT) |
+			     ((src_clk_div - 1) <<
+			      CLK_EMMC_DIV_SHIFT));
+		break;
+	case SCLK_SFC:
+	case HCLK_SFC:
+		if ((OSC_HZ % rate) == 0) {
+			sel = CLK_SFC_SEL_24M;
+			prate = OSC_HZ;
+		} else if ((500 * MHz % rate) == 0) {
+			sel = CLK_SFC_SEL_500M;
+			prate = 500 * MHz;
+		} else if ((300 * MHz % rate) == 0) {
+			sel = CLK_SFC_SEL_300M;
+			prate = 300 * MHz;
+		} else {
+			sel = CLK_SFC_SEL_200M;
+			prate = 200 * MHz;
+		}
+		src_clk_div = DIV_ROUND_UP(prate, rate);
+		rk_clrsetreg(&cru->peri_clksel_con[7],
+			     CLK_SFC_SEL_MASK |
+			     CLK_SFC_DIV_MASK,
+			     (sel << CLK_SFC_SEL_SHIFT) |
+			     ((src_clk_div - 1) <<
+			      CLK_SFC_DIV_SHIFT));
+		break;
+	default:
+		return -ENOENT;
+	}
+	return rv1106_mmc_get_clk(priv, clk_id);
+}
+
+static ulong rv1106_i2c_set_clk(struct rv1106_clk_priv *priv, ulong clk_id,
+				ulong rate)
+{
+	struct rv1106_cru *cru = priv->cru;
+	int src_clk;
+
+	if (rate >= 198 * MHz)
+		src_clk = CLK_I2C0_SEL_200M;
+	else if (rate >= 99 * MHz)
+		src_clk = CLK_I2C0_SEL_100M;
+	else if (rate >= 48 * MHz)
+		src_clk = CLK_I2C0_SEL_50M;
+	else
+		src_clk = CLK_I2C0_SEL_24M;
+
+	switch (clk_id) {
+	case CLK_I2C1:
+		if (rate >= 198 * MHz)
+			src_clk = CLK_I2C1_SEL_200M;
+		else if (rate >= 99 * MHz)
+			src_clk = CLK_I2C1_SEL_100M;
+		else if (rate >= 24 * MHz)
+			src_clk = CLK_I2C1_SEL_24M;
+		else
+			src_clk = CLK_I2C1_SEL_32K;
+		rk_clrsetreg(&cru->clksel_con[71], CLK_I2C1_SEL_MASK,
+			     src_clk << CLK_I2C1_SEL_SHIFT);
+		return rv1106_i2c_get_clk(priv, clk_id);
+	case CLK_I2C0:
+		rk_clrsetreg(&cru->peri_clksel_con[1], CLK_I2C0_SEL_MASK,
+			     src_clk << CLK_I2C0_SEL_SHIFT);
+		break;
+	case CLK_I2C2:
+		rk_clrsetreg(&cru->peri_clksel_con[1], CLK_I2C2_SEL_MASK,
+			     src_clk << CLK_I2C2_SEL_SHIFT);
+		break;
+	case CLK_I2C3:
+		rk_clrsetreg(&cru->peri_clksel_con[1], CLK_I2C3_SEL_MASK,
+			     src_clk << CLK_I2C3_SEL_SHIFT);
+		break;
+	case CLK_I2C4:
+		rk_clrsetreg(&cru->peri_clksel_con[2], CLK_I2C4_SEL_MASK,
+			     src_clk << CLK_I2C4_SEL_SHIFT);
+		break;
+	default:
+		return -ENOENT;
+	}
+
+	return rv1106_i2c_get_clk(priv, clk_id);
+}
+
+static ulong rv1106_spi_get_clk(struct rv1106_clk_priv *priv, ulong clk_id)
+{
+	struct rv1106_cru *cru = priv->cru;
+	u32 sel, con, rate;
+
+	switch (clk_id) {
+	case CLK_SPI0:
+		con = readl(&cru->vepu_clksel_con[0]);
+		sel = (con & CLK_SPI0_SEL_MASK) >> CLK_SPI0_SEL_SHIFT;
+		break;
+	case CLK_SPI1:
+		con = readl(&cru->peri_clksel_con[6]);
+		sel = (con & CLK_SPI1_SEL_MASK) >> CLK_SPI1_SEL_SHIFT;
+		break;
+	default:
+		return -ENOENT;
+	}
+	if (sel == CLK_SPI0_SEL_200M)
+		rate = 200 * MHz;
+	else if (sel == CLK_SPI0_SEL_100M)
+		rate = 100 * MHz;
+	else if (sel == CLK_SPI0_SEL_50M)
+		rate = 50 * MHz;
+	else
+		rate = OSC_HZ;
+
+	return rate;
+}
+
+static ulong rv1106_spi_set_clk(struct rv1106_clk_priv *priv,
+				ulong clk_id, ulong rate)
+{
+	struct rv1106_cru *cru = priv->cru;
+	int src_clk;
+
+	if (rate >= 198 * MHz)
+		src_clk = CLK_SPI0_SEL_200M;
+	else if (rate >= 99 * MHz)
+		src_clk = CLK_SPI0_SEL_100M;
+	else if (rate >= 48 * MHz)
+		src_clk = CLK_SPI0_SEL_50M;
+	else
+		src_clk = CLK_SPI0_SEL_24M;
+
+	switch (clk_id) {
+	case CLK_SPI0:
+		rk_clrsetreg(&cru->vepu_clksel_con[0], CLK_SPI0_SEL_MASK,
+			     src_clk << CLK_SPI0_SEL_SHIFT);
+		break;
+	case CLK_SPI1:
+		rk_clrsetreg(&cru->peri_clksel_con[6], CLK_SPI1_SEL_MASK,
+			     src_clk << CLK_SPI1_SEL_SHIFT);
+		break;
+	default:
+		return -ENOENT;
+	}
+
+	return rv1106_spi_get_clk(priv, clk_id);
+}
+
+static ulong rv1106_pwm_get_clk(struct rv1106_clk_priv *priv, ulong clk_id)
+{
+	struct rv1106_cru *cru = priv->cru;
+	u32 sel, con;
+
+	switch (clk_id) {
+	case CLK_PWM0_PERI:
+		con = readl(&cru->peri_clksel_con[11]);
+		sel = (con & CLK_PWM0_SEL_MASK) >> CLK_PWM0_SEL_SHIFT;
+		break;
+	case CLK_PWM1_PERI:
+		con = readl(&cru->peri_clksel_con[6]);
+		sel = (con & CLK_PWM1_SEL_MASK) >> CLK_PWM1_SEL_SHIFT;
+		break;
+	case CLK_PWM2_PERI:
+		con = readl(&cru->peri_clksel_con[6]);
+		sel = (con & CLK_PWM2_SEL_MASK) >> CLK_PWM2_SEL_SHIFT;
+		break;
+	default:
+		return -ENOENT;
+	}
+
+	switch (sel) {
+	case CLK_PWM_SEL_100M:
+		return 100 * MHz;
+	case CLK_PWM_SEL_50M:
+		return 100 * MHz;
+	case CLK_PWM_SEL_24M:
+		return OSC_HZ;
+	default:
+		return -ENOENT;
+	}
+}
+
+static ulong rv1106_pwm_set_clk(struct rv1106_clk_priv *priv,
+				ulong clk_id, ulong rate)
+{
+	struct rv1106_cru *cru = priv->cru;
+	int src_clk;
+
+	if (rate >= 99 * MHz)
+		src_clk = CLK_PWM_SEL_100M;
+	else if (rate >= 48 * MHz)
+		src_clk = CLK_PWM_SEL_50M;
+	else
+		src_clk = CLK_PWM_SEL_24M;
+
+	switch (clk_id) {
+	case CLK_PWM0_PERI:
+		rk_clrsetreg(&cru->peri_clksel_con[11],
+			     CLK_PWM0_SEL_MASK,
+			     src_clk << CLK_PWM0_SEL_SHIFT);
+		break;
+	case CLK_PWM1_PERI:
+		rk_clrsetreg(&cru->peri_clksel_con[6],
+			     CLK_PWM1_SEL_MASK,
+			     src_clk << CLK_PWM1_SEL_SHIFT);
+		break;
+	case CLK_PWM2_PERI:
+		rk_clrsetreg(&cru->peri_clksel_con[6],
+			     CLK_PWM2_SEL_MASK,
+			     src_clk << CLK_PWM2_SEL_SHIFT);
+		break;
+	default:
+		return -ENOENT;
+	}
+
+	return rv1106_pwm_get_clk(priv, clk_id);
+}
+
+static ulong rv1106_adc_get_clk(struct rv1106_clk_priv *priv, ulong clk_id)
+{
+	struct rv1106_cru *cru = priv->cru;
+	u32 div, con;
+
+	switch (clk_id) {
+	case CLK_SARADC:
+		con = readl(&cru->peri_clksel_con[6]);
+		div = (con & CLK_SARADC_DIV_MASK) >>
+		      CLK_SARADC_DIV_SHIFT;
+		return DIV_TO_RATE(OSC_HZ, div);
+	case CLK_TSADC_TSEN:
+		con = readl(&cru->vo_clksel_con[3]);
+		div = (con & CLK_TSADC_TSEN_DIV_MASK) >>
+		      CLK_TSADC_TSEN_DIV_SHIFT;
+		return DIV_TO_RATE(OSC_HZ, div);
+	case CLK_TSADC:
+		con = readl(&cru->vo_clksel_con[3]);
+		div = (con & CLK_TSADC_DIV_MASK) >> CLK_TSADC_DIV_SHIFT;
+		return DIV_TO_RATE(OSC_HZ, div);
+	default:
+		return -ENOENT;
+	}
+}
+
+static ulong rv1106_adc_set_clk(struct rv1106_clk_priv *priv,
+				ulong clk_id, ulong rate)
+{
+	struct rv1106_cru *cru = priv->cru;
+	int src_clk_div;
+
+	src_clk_div = DIV_ROUND_UP(OSC_HZ, rate);
+
+	switch (clk_id) {
+	case CLK_SARADC:
+		assert(src_clk_div - 1 <= 7);
+		rk_clrsetreg(&cru->peri_clksel_con[6],
+			     CLK_SARADC_DIV_MASK,
+			     (src_clk_div - 1) <<
+			     CLK_SARADC_DIV_SHIFT);
+		break;
+	case CLK_TSADC_TSEN:
+		assert(src_clk_div - 1 <= 128);
+		rk_clrsetreg(&cru->vo_clksel_con[3],
+			     CLK_TSADC_TSEN_DIV_MASK,
+			     (src_clk_div - 1) <<
+			     CLK_TSADC_TSEN_DIV_SHIFT);
+		break;
+	case CLK_TSADC:
+		assert(src_clk_div - 1 <= 128);
+		rk_clrsetreg(&cru->vo_clksel_con[3],
+			     CLK_TSADC_DIV_MASK,
+			     (src_clk_div - 1) <<
+			     CLK_TSADC_DIV_SHIFT);
+		break;
+	default:
+		return -ENOENT;
+	}
+	return rv1106_adc_get_clk(priv, clk_id);
+}
+
+/*
+ *
+ * rational_best_approximation(31415, 10000,
+ *		(1 << 8) - 1, (1 << 5) - 1, &n, &d);
+ *
+ * you may look at given_numerator as a fixed point number,
+ * with the fractional part size described in given_denominator.
+ *
+ * for theoretical background, see:
+ * http://en.wikipedia.org/wiki/Continued_fraction
+ */
+static void rational_best_approximation(unsigned long given_numerator,
+					unsigned long given_denominator,
+					unsigned long max_numerator,
+					unsigned long max_denominator,
+					unsigned long *best_numerator,
+					unsigned long *best_denominator)
+{
+	unsigned long n, d, n0, d0, n1, d1;
+
+	n = given_numerator;
+	d = given_denominator;
+	n0 = 0;
+	d1 = 0;
+	n1 = 1;
+	d0 = 1;
+	for (;;) {
+		unsigned long t, a;
+
+		if (n1 > max_numerator || d1 > max_denominator) {
+			n1 = n0;
+			d1 = d0;
+			break;
+		}
+		if (d == 0)
+			break;
+		t = d;
+		a = n / d;
+		d = n % d;
+		n = t;
+		t = n0 + a * n1;
+		n0 = n1;
+		n1 = t;
+		t = d0 + a * d1;
+		d0 = d1;
+		d1 = t;
+	}
+	*best_numerator = n1;
+	*best_denominator = d1;
+}
+
+static ulong rv1106_uart_get_rate(struct rv1106_clk_priv *priv, ulong clk_id)
+{
+	struct rv1106_cru *cru = priv->cru;
+	u32 reg, con, fracdiv, div, src, p_src, p_rate;
+	unsigned long m, n;
+
+	switch (clk_id) {
+	case SCLK_UART0:
+		reg = 5;
+		break;
+	case SCLK_UART1:
+		reg = 7;
+		break;
+	case SCLK_UART2:
+		reg = 9;
+		break;
+	case SCLK_UART3:
+		reg = 11;
+		break;
+	case SCLK_UART4:
+		reg = 13;
+		break;
+	case SCLK_UART5:
+		reg = 15;
+		break;
+	default:
+		return -ENOENT;
+	}
+	con = readl(&cru->clksel_con[reg + 2]);
+	src = (con & CLK_UART_SEL_MASK) >> CLK_UART_SEL_SHIFT;
+	con = readl(&cru->clksel_con[reg]);
+	div = (con & CLK_UART_SRC_DIV_MASK) >> CLK_UART_SRC_DIV_SHIFT;
+	p_src = (con & CLK_UART_SRC_SEL_MASK) >> CLK_UART_SRC_SEL_SHIFT;
+	if (p_src == CLK_UART_SRC_SEL_GPLL)
+		p_rate = priv->gpll_hz;
+	else if (p_src == CLK_UART_SRC_SEL_CPLL)
+		p_rate = priv->cpll_hz;
+	else
+		p_rate = 480000000;
+	if (src == CLK_UART_SEL_SRC) {
+		return DIV_TO_RATE(p_rate, div);
+	} else if (src == CLK_UART_SEL_FRAC) {
+		fracdiv = readl(&cru->clksel_con[reg + 1]);
+		n = fracdiv & CLK_UART_FRAC_NUMERATOR_MASK;
+		n >>= CLK_UART_FRAC_NUMERATOR_SHIFT;
+		m = fracdiv & CLK_UART_FRAC_DENOMINATOR_MASK;
+		m >>= CLK_UART_FRAC_DENOMINATOR_SHIFT;
+		return DIV_TO_RATE(p_rate, div) * n / m;
+	} else {
+		return OSC_HZ;
+	}
+}
+
+static ulong rv1106_uart_set_rate(struct rv1106_clk_priv *priv,
+				  ulong clk_id, ulong rate)
+{
+	struct rv1106_cru *cru = priv->cru;
+	u32 reg, clk_src, uart_src, div;
+	unsigned long m = 0, n = 0, val;
+
+	if (priv->gpll_hz % rate == 0) {
+		clk_src = CLK_UART_SRC_SEL_GPLL;
+		uart_src = CLK_UART_SEL_SRC;
+		div = DIV_ROUND_UP(priv->gpll_hz, rate);
+	} else if (priv->cpll_hz % rate == 0) {
+		clk_src = CLK_UART_SRC_SEL_CPLL;
+		uart_src = CLK_UART_SEL_SRC;
+		div = DIV_ROUND_UP(priv->gpll_hz, rate);
+	} else if (rate == OSC_HZ) {
+		clk_src = CLK_UART_SRC_SEL_GPLL;
+		uart_src = CLK_UART_SEL_XIN24M;
+		div = 2;
+	} else {
+		clk_src = CLK_UART_SRC_SEL_GPLL;
+		uart_src = CLK_UART_SEL_FRAC;
+		div = 2;
+		rational_best_approximation(rate, priv->gpll_hz / div,
+					    GENMASK(16 - 1, 0),
+					    GENMASK(16 - 1, 0),
+					    &m, &n);
+	}
+
+	switch (clk_id) {
+	case SCLK_UART0:
+		reg = 5;
+		break;
+	case SCLK_UART1:
+		reg = 7;
+		break;
+	case SCLK_UART2:
+		reg = 9;
+		break;
+	case SCLK_UART3:
+		reg = 11;
+		break;
+	case SCLK_UART4:
+		reg = 13;
+		break;
+	case SCLK_UART5:
+		reg = 15;
+		break;
+	default:
+		return -ENOENT;
+	}
+	rk_clrsetreg(&cru->clksel_con[reg],
+		     CLK_UART_SRC_SEL_MASK |
+		     CLK_UART_SRC_DIV_MASK,
+		     (clk_src << CLK_UART_SRC_SEL_SHIFT) |
+		     ((div - 1) << CLK_UART_SRC_DIV_SHIFT));
+	rk_clrsetreg(&cru->clksel_con[reg + 2],
+		     CLK_UART_SEL_MASK,
+		     uart_src << CLK_UART_SEL_SHIFT);
+	if (m && n) {
+		val = m << CLK_UART_FRAC_NUMERATOR_SHIFT | n;
+		writel(val, &cru->clksel_con[reg + 1]);
+	}
+
+	return rv1106_uart_get_rate(priv, clk_id);
+}
+
+static ulong rv1106_vop_get_clk(struct rv1106_clk_priv *priv, ulong clk_id)
+{
+	struct rv1106_cru *cru = priv->cru;
+	u32 div, sel, con;
+
+	switch (clk_id) {
+	case ACLK_VOP_ROOT:
+	case ACLK_VOP:
+		con = readl(&cru->vo_clksel_con[1]);
+		sel = (con & ACLK_VOP_SEL_MASK) >> ACLK_VOP_SEL_SHIFT;
+		if (sel == ACLK_VOP_SEL_300M)
+			return 300 * MHz;
+		else if (sel == ACLK_VOP_SEL_200M)
+			return 200 * MHz;
+		else if (sel == ACLK_VOP_SEL_100M)
+			return 100 * MHz;
+		else
+			return  OSC_HZ;
+	case DCLK_VOP_SRC:
+	case DCLK_VOP:
+		con = readl(&cru->clksel_con[23]);
+		sel = (con & DCLK_VOP_SEL_MASK) >> DCLK_VOP_SEL_SHIFT;
+		div = (con & DCLK_VOP_DIV_MASK) >> DCLK_VOP_DIV_SHIFT;
+		if (sel == DCLK_VOP_SEL_GPLL)
+			return DIV_TO_RATE(priv->gpll_hz, div);
+		else
+			return DIV_TO_RATE(priv->cpll_hz, div);
+	default:
+		return -ENOENT;
+	}
+}
+
+static ulong rv1106_vop_set_clk(struct rv1106_clk_priv *priv,
+				ulong clk_id, ulong rate)
+{
+	struct rv1106_cru *cru = priv->cru;
+	int div, sel;
+
+	switch (clk_id) {
+	case ACLK_VOP_ROOT:
+	case ACLK_VOP:
+		if (rate >= 297 * MHz)
+			sel = ACLK_VOP_SEL_300M;
+		else if (rate >= 198 * MHz)
+			sel = ACLK_VOP_SEL_200M;
+		else if (rate >= 99 * MHz)
+			sel = ACLK_VOP_SEL_100M;
+		else
+			sel = ACLK_VOP_SEL_24M;
+		rk_clrsetreg(&cru->vo_clksel_con[1],
+			     ACLK_VOP_SEL_MASK,
+			     sel << ACLK_VOP_SEL_SHIFT);
+		break;
+	case DCLK_VOP_SRC:
+	case DCLK_VOP:
+		if ((priv->cpll_hz % rate) == 0) {
+			sel = DCLK_VOP_SEL_CPLL;
+			div = DIV_ROUND_UP(priv->cpll_hz, rate);
+		} else {
+			sel = DCLK_VOP_SEL_GPLL;
+			div = DIV_ROUND_UP(priv->gpll_hz, rate);
+		}
+		rk_clrsetreg(&cru->clksel_con[23],
+			     DCLK_VOP_SEL_MASK |
+			     DCLK_VOP_DIV_MASK,
+			     sel << DCLK_VOP_SEL_SHIFT |
+			     (div - 1) << DCLK_VOP_DIV_SHIFT);
+		break;
+	default:
+		return -ENOENT;
+	}
+
+	return rv1106_vop_get_clk(priv, clk_id);
+}
+
+static ulong rv1106_decom_get_clk(struct rv1106_clk_priv *priv)
+{
+	struct rv1106_cru *cru = priv->cru;
+	u32 sel, con, prate;
+
+	con = readl(&cru->peri_clksel_con[7]);
+	sel = (con & DCLK_DECOM_SEL_MASK) >>
+	      DCLK_DECOM_SEL_SHIFT;
+	if (sel == DCLK_DECOM_SEL_400M)
+		prate = 400 * MHz;
+	else if (sel == DCLK_DECOM_SEL_200M)
+		prate = 200 * MHz;
+	else if (sel == DCLK_DECOM_SEL_100M)
+		prate = 100 * MHz;
+	else
+		prate = OSC_HZ;
+	return prate;
+}
+
+static ulong rv1106_decom_set_clk(struct rv1106_clk_priv *priv, ulong rate)
+{
+	struct rv1106_cru *cru = priv->cru;
+	u32 sel;
+
+	if (rate >= 396 * MHz)
+		sel = DCLK_DECOM_SEL_400M;
+	else if (rate >= 198 * MHz)
+		sel = DCLK_DECOM_SEL_200M;
+	else if (rate >= 99 * MHz)
+		sel = DCLK_DECOM_SEL_100M;
+	else
+		sel = DCLK_DECOM_SEL_24M;
+	rk_clrsetreg(&cru->peri_clksel_con[7], DCLK_DECOM_SEL_MASK,
+		     (sel << DCLK_DECOM_SEL_SHIFT));
+
+	return rv1106_decom_get_clk(priv);
+}
+
+static ulong rv1106_clk_get_rate(struct clk *clk)
+{
+	struct rv1106_clk_priv *priv = dev_get_priv(clk->dev);
+	ulong rate = 0;
+
+	if (!priv->gpll_hz) {
+		printf("%s gpll=%lu\n", __func__, priv->gpll_hz);
+		return -ENOENT;
+	}
+
+	switch (clk->id) {
+	case PLL_APLL:
+		rate = rockchip_pll_get_rate(&rv1106_pll_clks[APLL], priv->cru,
+					     APLL);
+		break;
+	case PLL_DPLL:
+		rate = rockchip_pll_get_rate(&rv1106_pll_clks[DPLL], priv->cru,
+					     DPLL);
+		break;
+	case PLL_CPLL:
+		rate = rockchip_pll_get_rate(&rv1106_pll_clks[CPLL], priv->cru,
+					     CPLL);
+		break;
+	case PLL_GPLL:
+		rate = rockchip_pll_get_rate(&rv1106_pll_clks[GPLL], priv->cru,
+					     GPLL);
+		break;
+	case ACLK_PERI_ROOT:
+	case HCLK_PERI_ROOT:
+	case PCLK_PERI_ROOT:
+	case ACLK_BUS_ROOT:
+	case PCLK_TOP_ROOT:
+	case PCLK_PMU_ROOT:
+	case HCLK_PMU_ROOT:
+		rate = rv1106_peri_get_clk(priv, clk->id);
+		break;
+	case CLK_CORE_CRYPTO:
+	case CLK_PKA_CRYPTO:
+	case ACLK_CRYPTO:
+		rate = rv1106_crypto_get_clk(priv, clk->id);
+		break;
+	case CCLK_SRC_SDMMC:
+	case CCLK_SRC_EMMC:
+	case SCLK_SFC:
+	case HCLK_SDMMC:
+	case HCLK_EMMC:
+	case HCLK_SFC:
+		rate = rv1106_mmc_get_clk(priv, clk->id);
+		break;
+	case CLK_I2C0:
+	case CLK_I2C1:
+	case CLK_I2C2:
+	case CLK_I2C3:
+	case CLK_I2C4:
+		rate = rv1106_i2c_get_clk(priv, clk->id);
+		break;
+	case CLK_SPI0:
+	case CLK_SPI1:
+		rate = rv1106_spi_get_clk(priv, clk->id);
+		break;
+	case CLK_PWM0_PERI:
+	case CLK_PWM1_PERI:
+	case CLK_PWM2_PERI:
+		rate = rv1106_pwm_get_clk(priv, clk->id);
+		break;
+	case CLK_SARADC:
+	case CLK_TSADC_TSEN:
+	case CLK_TSADC:
+		rate = rv1106_adc_get_clk(priv, clk->id);
+		break;
+	case SCLK_UART0:
+	case SCLK_UART1:
+	case SCLK_UART2:
+	case SCLK_UART3:
+	case SCLK_UART4:
+	case SCLK_UART5:
+		rate = rv1106_uart_get_rate(priv, clk->id);
+		break;
+	case DCLK_VOP_SRC:
+	case DCLK_VOP:
+	case ACLK_VOP_ROOT:
+	case ACLK_VOP:
+		rate = rv1106_vop_get_clk(priv, clk->id);
+		break;
+	case DCLK_DECOM:
+		rate = rv1106_decom_get_clk(priv);
+		break;
+	case TCLK_WDT_NS:
+		rate = OSC_HZ;
+		break;
+	default:
+		return -ENOENT;
+	}
+
+	return rate;
+};
+
+static ulong rv1106_clk_set_rate(struct clk *clk, ulong rate)
+{
+	struct rv1106_clk_priv *priv = dev_get_priv(clk->dev);
+	ulong ret = 0;
+
+	if (!priv->gpll_hz) {
+		printf("%s gpll=%lu\n", __func__, priv->gpll_hz);
+		return -ENOENT;
+	}
+
+	switch (clk->id) {
+	case PLL_APLL:
+		ret = rockchip_pll_set_rate(&rv1106_pll_clks[APLL], priv->cru,
+					    APLL, rate);
+		break;
+	case PLL_CPLL:
+		ret = rockchip_pll_set_rate(&rv1106_pll_clks[CPLL], priv->cru,
+					    CPLL, rate);
+		break;
+	case PLL_GPLL:
+		ret = rockchip_pll_set_rate(&rv1106_pll_clks[GPLL], priv->cru,
+					    GPLL, rate);
+		break;
+	case ACLK_PERI_ROOT:
+	case HCLK_PERI_ROOT:
+	case PCLK_PERI_ROOT:
+	case ACLK_BUS_ROOT:
+	case PCLK_TOP_ROOT:
+	case PCLK_PMU_ROOT:
+	case HCLK_PMU_ROOT:
+		ret = rv1106_peri_set_clk(priv, clk->id, rate);
+		break;
+	case CLK_CORE_CRYPTO:
+	case CLK_PKA_CRYPTO:
+	case ACLK_CRYPTO:
+		ret = rv1106_crypto_set_clk(priv, clk->id, rate);
+		break;
+	case CCLK_SRC_SDMMC:
+	case CCLK_SRC_EMMC:
+	case SCLK_SFC:
+	case HCLK_SDMMC:
+	case HCLK_EMMC:
+	case HCLK_SFC:
+		ret = rv1106_mmc_set_clk(priv, clk->id, rate);
+		break;
+	case CLK_I2C0:
+	case CLK_I2C1:
+	case CLK_I2C2:
+	case CLK_I2C3:
+	case CLK_I2C4:
+		ret = rv1106_i2c_set_clk(priv, clk->id, rate);
+		break;
+	case CLK_SPI0:
+	case CLK_SPI1:
+		ret = rv1106_spi_set_clk(priv, clk->id, rate);
+		break;
+	case CLK_PWM0_PERI:
+	case CLK_PWM1_PERI:
+	case CLK_PWM2_PERI:
+		ret = rv1106_pwm_set_clk(priv, clk->id, rate);
+		break;
+	case CLK_SARADC:
+	case CLK_TSADC_TSEN:
+	case CLK_TSADC:
+		ret = rv1106_adc_set_clk(priv, clk->id, rate);
+		break;
+	case SCLK_UART0:
+	case SCLK_UART1:
+	case SCLK_UART2:
+	case SCLK_UART3:
+	case SCLK_UART4:
+	case SCLK_UART5:
+		ret = rv1106_uart_set_rate(priv, clk->id, rate);
+		break;
+	case DCLK_VOP_SRC:
+	case DCLK_VOP:
+	case ACLK_VOP_ROOT:
+	case ACLK_VOP:
+		rate = rv1106_vop_set_clk(priv, clk->id, rate);
+		break;
+	case DCLK_DECOM:
+		rate = rv1106_decom_set_clk(priv, rate);
+		break;
+	default:
+		return -ENOENT;
+	}
+
+	return ret;
+};
+
+static int rv1106_clk_set_parent(struct clk *clk, struct clk *parent)
+{
+	switch (clk->id) {
+	default:
+		return -ENOENT;
+	}
+
+	return 0;
+}
+
+static struct clk_ops rv1106_clk_ops = {
+	.get_rate = rv1106_clk_get_rate,
+	.set_rate = rv1106_clk_set_rate,
+#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
+	.set_parent = rv1106_clk_set_parent,
+#endif
+};
+
+static void rv1106_clk_init(struct rv1106_clk_priv *priv)
+{
+	int ret;
+
+	priv->sync_kernel = false;
+	if (!priv->armclk_enter_hz) {
+		priv->armclk_enter_hz =
+			rockchip_pll_get_rate(&rv1106_pll_clks[APLL],
+					      priv->cru, APLL);
+		priv->armclk_init_hz = priv->armclk_enter_hz;
+	}
+
+	if (priv->armclk_init_hz != APLL_HZ) {
+			ret = rockchip_pll_set_rate(&rv1106_pll_clks[APLL], priv->cru,
+						    APLL, APLL_HZ);
+		if (!ret)
+			priv->armclk_init_hz = APLL_HZ;
+	}
+
+	if (priv->cpll_hz != CPLL_HZ) {
+		ret = rockchip_pll_set_rate(&rv1106_pll_clks[CPLL], priv->cru,
+					    CPLL, CPLL_HZ);
+		if (!ret)
+			priv->cpll_hz = CPLL_HZ;
+	}
+
+	if (priv->gpll_hz != GPLL_HZ) {
+		ret = rockchip_pll_set_rate(&rv1106_pll_clks[GPLL], priv->cru,
+					    GPLL, GPLL_HZ);
+		if (!ret)
+			priv->gpll_hz = GPLL_HZ;
+	}
+}
+
+static int rv1106_clk_probe(struct udevice *dev)
+{
+	struct rv1106_clk_priv *priv = dev_get_priv(dev);
+	int ret;
+
+	rv1106_clk_init(priv);
+
+	/* Process 'assigned-{clocks/clock-parents/clock-rates}' properties */
+	ret = clk_set_defaults(dev, 1);
+	if (ret)
+		debug("%s clk_set_defaults failed %d\n", __func__, ret);
+	else
+		priv->sync_kernel = true;
+	rk_clrsetreg(&priv->cru->core_clksel_con[0],
+		     CLK_CORE_DIV_MASK,
+		     0 << CLK_CORE_DIV_SHIFT);
+
+	return 0;
+}
+
+static int rv1106_clk_of_to_plat(struct udevice *dev)
+{
+	struct rv1106_clk_priv *priv = dev_get_priv(dev);
+
+	priv->cru = dev_read_addr_ptr(dev);
+
+	return 0;
+}
+
+static int rv1106_clk_bind(struct udevice *dev)
+{
+	struct udevice *sys_child;
+	struct sysreset_reg *priv;
+	int ret;
+
+	/* The sysreset driver does not have a device node, so bind it here */
+	ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset",
+				 &sys_child);
+	if (ret) {
+		debug("Warning: No sysreset driver: ret=%d\n", ret);
+	} else {
+		priv = malloc(sizeof(struct sysreset_reg));
+		priv->glb_srst_fst_value = offsetof(struct rv1106_cru,
+						    glb_srst_fst);
+		priv->glb_srst_snd_value = offsetof(struct rv1106_cru,
+						    glb_srst_snd);
+		dev_set_priv(sys_child, priv);
+	}
+
+#if CONFIG_IS_ENABLED(RESET_ROCKCHIP)
+	ret = offsetof(struct rv1106_cru, pmu_softrst_con[0]);
+	ret = rockchip_reset_bind(dev, ret, 15);
+	if (ret)
+		debug("Warning: software reset driver bind failed\n");
+#endif
+
+	return 0;
+}
+
+static const struct udevice_id rv1106_clk_ids[] = {
+	{ .compatible = "rockchip,rv1106-cru" },
+	{ }
+};
+
+U_BOOT_DRIVER(rockchip_rv1106_cru) = {
+	.name		= "rockchip_rv1106_cru",
+	.id		= UCLASS_CLK,
+	.of_match	= rv1106_clk_ids,
+	.priv_auto	= sizeof(struct rv1106_clk_priv),
+	.of_to_plat	= rv1106_clk_of_to_plat,
+	.ops		= &rv1106_clk_ops,
+	.bind		= rv1106_clk_bind,
+	.probe		= rv1106_clk_probe,
+};
-- 
2.43.0


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

* [PATCH v3 13/15] rockchip: rv1106: Add SoC support
  2026-07-07 15:30 [PATCH v3 00/15] rockchip: Add support for the RV1103B, RV1103 and RV1106 Simon Glass
                   ` (11 preceding siblings ...)
  2026-07-07 15:31 ` [PATCH v3 12/15] clk: rockchip: Add RV1106 clock driver Simon Glass
@ 2026-07-07 15:31 ` Simon Glass
  2026-07-07 15:31 ` [PATCH v3 14/15] luckfox-pico: Add the initial support Simon Glass
                   ` (2 subsequent siblings)
  15 siblings, 0 replies; 21+ messages in thread
From: Simon Glass @ 2026-07-07 15:31 UTC (permalink / raw)
  To: u-boot
  Cc: Fabio Estevam, Jonas Karlman, Simon Glass, Heinrich Schuchardt,
	Ilias Apalodimas, Jeffy Chen, Johan Jonker, Kever Yang,
	Mattijs Korpershoek, Philipp Tomsich, Quentin Schulz, Tom Rini,
	huang lin

The RV1106 is an ARM-based SoC with a single Cortex-A7 32-bit core
which integrates NEON and FPU. It contains a built-in NPU for AI
related applications. The RV1103 is a package variant of the RV1106
with fewer pins.

Add the core SoC support for it: the Kconfig and Makefile entries, the
boot0 hook, the SoC init code (firewall setup, watchdog release and
the pvtpll reboot workaround from the vendor tree), the syscon driver
and the SoC u-boot.dtsi

Signed-off-by: Simon Glass <sjg@chromium.org>
---

(no changes since v1)

 arch/arm/dts/rv1106-u-boot.dtsi               |   4 +
 arch/arm/include/asm/arch-rv1106/boot0.h      |  11 ++
 arch/arm/mach-rockchip/Kconfig                |  15 +++
 arch/arm/mach-rockchip/Makefile               |   1 +
 arch/arm/mach-rockchip/rv1106/Kconfig         |  28 +++++
 arch/arm/mach-rockchip/rv1106/Makefile        |  12 ++
 arch/arm/mach-rockchip/rv1106/clk_rv1106.c    |  31 +++++
 arch/arm/mach-rockchip/rv1106/rv1106.c        | 118 ++++++++++++++++++
 arch/arm/mach-rockchip/rv1106/syscon_rv1106.c |  19 +++
 board/luckfox/pico/Kconfig                    |  12 ++
 include/configs/rv1106_common.h               |  13 ++
 11 files changed, 264 insertions(+)
 create mode 100644 arch/arm/dts/rv1106-u-boot.dtsi
 create mode 100644 arch/arm/include/asm/arch-rv1106/boot0.h
 create mode 100644 arch/arm/mach-rockchip/rv1106/Kconfig
 create mode 100644 arch/arm/mach-rockchip/rv1106/Makefile
 create mode 100644 arch/arm/mach-rockchip/rv1106/clk_rv1106.c
 create mode 100644 arch/arm/mach-rockchip/rv1106/rv1106.c
 create mode 100644 arch/arm/mach-rockchip/rv1106/syscon_rv1106.c
 create mode 100644 board/luckfox/pico/Kconfig
 create mode 100644 include/configs/rv1106_common.h

diff --git a/arch/arm/dts/rv1106-u-boot.dtsi b/arch/arm/dts/rv1106-u-boot.dtsi
new file mode 100644
index 00000000000..fa062c8ee84
--- /dev/null
+++ b/arch/arm/dts/rv1106-u-boot.dtsi
@@ -0,0 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
+// (C) Copyright 2022 Rockchip Electronics Co., Ltd
+
+#include "rockchip-u-boot.dtsi"
diff --git a/arch/arm/include/asm/arch-rv1106/boot0.h b/arch/arm/include/asm/arch-rv1106/boot0.h
new file mode 100644
index 00000000000..e132eb98116
--- /dev/null
+++ b/arch/arm/include/asm/arch-rv1106/boot0.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2022 Rockchip Electronics Co., Ltd
+ */
+
+#ifndef __ASM_ARCH_BOOT0_H__
+#define __ASM_ARCH_BOOT0_H__
+
+#include <asm/arch-rockchip/boot0.h>
+
+#endif
diff --git a/arch/arm/mach-rockchip/Kconfig b/arch/arm/mach-rockchip/Kconfig
index 1969c313f47..5b1032f258b 100644
--- a/arch/arm/mach-rockchip/Kconfig
+++ b/arch/arm/mach-rockchip/Kconfig
@@ -544,6 +544,20 @@ config ROCKCHIP_RV1103B
 	  32-bit core which integrates NEON and FPU.
 	  It contains a built-in NPU for AI related applications.
 
+config ROCKCHIP_RV1106
+	bool "Support Rockchip RV1106"
+	select CPU_V7A
+	select SPL_ARMV7_SET_CORTEX_SMPEN
+	select SUPPORT_SPL
+	select SPL
+	imply ROCKCHIP_COMMON_BOARD
+	help
+	  The Rockchip RV1106 is an ARM-based SoC with a single Cortex-A7
+	  32-bit core which integrates NEON and FPU. It contains a built-in
+	  NPU for AI related applications. The RV1103 is a package variant
+	  of the RV1106 with fewer pins and is also supported by this
+	  option.
+
 config ROCKCHIP_RV1108
 	bool "Support Rockchip RV1108"
 	select CPU_V7A
@@ -808,6 +822,7 @@ source "arch/arm/mach-rockchip/rk3568/Kconfig"
 source "arch/arm/mach-rockchip/rk3576/Kconfig"
 source "arch/arm/mach-rockchip/rk3588/Kconfig"
 source "arch/arm/mach-rockchip/rv1103b/Kconfig"
+source "arch/arm/mach-rockchip/rv1106/Kconfig"
 source "arch/arm/mach-rockchip/rv1108/Kconfig"
 source "arch/arm/mach-rockchip/rv1126/Kconfig"
 
diff --git a/arch/arm/mach-rockchip/Makefile b/arch/arm/mach-rockchip/Makefile
index e09dc44a7ad..0d42ddbe678 100644
--- a/arch/arm/mach-rockchip/Makefile
+++ b/arch/arm/mach-rockchip/Makefile
@@ -48,6 +48,7 @@ obj-$(CONFIG_ROCKCHIP_RK3568) += rk3568/
 obj-$(CONFIG_ROCKCHIP_RK3576) += rk3576/
 obj-$(CONFIG_ROCKCHIP_RK3588) += rk3588/
 obj-$(CONFIG_ROCKCHIP_RV1103B) += rv1103b/
+obj-$(CONFIG_ROCKCHIP_RV1106) += rv1106/
 obj-$(CONFIG_ROCKCHIP_RV1108) += rv1108/
 obj-$(CONFIG_ROCKCHIP_RV1126) += rv1126/
 
diff --git a/arch/arm/mach-rockchip/rv1106/Kconfig b/arch/arm/mach-rockchip/rv1106/Kconfig
new file mode 100644
index 00000000000..05eafd96833
--- /dev/null
+++ b/arch/arm/mach-rockchip/rv1106/Kconfig
@@ -0,0 +1,28 @@
+if ROCKCHIP_RV1106
+
+config TARGET_LUCKFOX_PICO_RV1103
+	bool "LUCKFOX_PICO_RV1103"
+	help
+	  Support Luckfox's Pico series of RV1103 boards, such as the Pico
+	  Mini B. These are small, low-cost boards with 64MB of in-package
+	  DDR2, a microSD slot and a USB-C port used for both power and
+	  maskrom-mode USB download; most I/O is on castellated edge pins.
+	  The Mini B adds a 128MB Winbond SPI NAND, from which it boots.
+	  U-Boot can also run entirely from RAM over USB, with nothing
+	  written to the flash.
+
+config ROCKCHIP_BOOT_MODE_REG
+	default 0xff020200
+
+config ROCKCHIP_STIMER_BASE
+	default 0xff590020
+
+config SYS_SOC
+	default "rv1106"
+
+config SYS_MALLOC_F_LEN
+	default 0x400
+
+source "board/luckfox/pico/Kconfig"
+
+endif
diff --git a/arch/arm/mach-rockchip/rv1106/Makefile b/arch/arm/mach-rockchip/rv1106/Makefile
new file mode 100644
index 00000000000..66aba9fbfe2
--- /dev/null
+++ b/arch/arm/mach-rockchip/rv1106/Makefile
@@ -0,0 +1,12 @@
+#
+# (C) Copyright 2022 Rockchip Electronics Co., Ltd
+#
+# SPDX-License-Identifier:     GPL-2.0+
+#
+
+obj-y += rv1106.o
+obj-y += clk_rv1106.o
+
+ifndef CONFIG_XPL_BUILD
+obj-y += syscon_rv1106.o
+endif
diff --git a/arch/arm/mach-rockchip/rv1106/clk_rv1106.c b/arch/arm/mach-rockchip/rv1106/clk_rv1106.c
new file mode 100644
index 00000000000..86020c45c22
--- /dev/null
+++ b/arch/arm/mach-rockchip/rv1106/clk_rv1106.c
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * (C) Copyright 2022 Rockchip Electronics Co., Ltd
+ */
+
+#include <dm.h>
+#include <syscon.h>
+#include <asm/arch-rockchip/clock.h>
+#include <asm/arch-rockchip/cru_rv1106.h>
+#include <linux/err.h>
+
+int rockchip_get_clk(struct udevice **devp)
+{
+	return uclass_get_device_by_driver(UCLASS_CLK,
+			DM_DRIVER_GET(rockchip_rv1106_cru), devp);
+}
+
+void *rockchip_get_cru(void)
+{
+	struct rv1106_clk_priv *priv;
+	struct udevice *dev;
+	int ret;
+
+	ret = rockchip_get_clk(&dev);
+	if (ret)
+		return ERR_PTR(ret);
+
+	priv = dev_get_priv(dev);
+
+	return priv->cru;
+}
diff --git a/arch/arm/mach-rockchip/rv1106/rv1106.c b/arch/arm/mach-rockchip/rv1106/rv1106.c
new file mode 100644
index 00000000000..a93c3e5f2fe
--- /dev/null
+++ b/arch/arm/mach-rockchip/rv1106/rv1106.c
@@ -0,0 +1,118 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2022 Rockchip Electronics Co., Ltd
+ */
+
+#include <dm.h>
+#include <spl.h>
+#include <asm/io.h>
+#include <linux/delay.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define PERI_GRF_BASE			0xff000000
+#define PERI_GRF_PERI_CON1		0x0004
+
+#define PERI_SGRF_BASE			0xff070000
+#define PERI_SGRF_FIREWALL_CON0		0x0020
+#define PERI_SGRF_FIREWALL_CON1		0x0024
+#define PERI_SGRF_FIREWALL_CON2		0x0028
+#define PERI_SGRF_FIREWALL_CON3		0x002c
+#define PERI_SGRF_FIREWALL_CON4		0x0030
+#define PERI_SGRF_SOC_CON3		0x00bc
+
+#define CORE_SGRF_BASE			0xff076000
+#define CORE_SGRF_FIREWALL_CON0		0x0020
+#define CORE_SGRF_FIREWALL_CON1		0x0024
+#define CORE_SGRF_FIREWALL_CON2		0x0028
+#define CORE_SGRF_FIREWALL_CON3		0x002c
+#define CORE_SGRF_FIREWALL_CON4		0x0030
+#define CORE_SGRF_CPU_CTRL_CON		0x0040
+
+#define PMU_SGRF_BASE			0xff080000
+
+#define FW_DDR_BASE			0xff900000
+#define FW_DDR_MST3_REG			0x4c
+#define FW_SHRM_BASE			0xff910000
+#define FW_SHRM_MST1_REG		0x44
+
+#define CRU_BASE			0xff3b0000
+#define CRU_GLB_RST_CON			0x0c10
+#define CRU_PVTPLL0_CON0_L		0x1000
+#define CRU_PVTPLL0_CON1_L		0x1008
+#define CRU_PVTPLL1_CON0_L		0x1030
+#define CRU_PVTPLL1_CON1_L		0x1038
+
+#define VICRU_BASE			0xff3b4000
+#define VICRU_VISOFTRST_CON01		0x0a04
+
+#define CHIP_VER_REG			0xff020204
+#define CHIP_VER_MSK			0x7
+#define V(x)				((x) - 1)
+#define ROM_VER_REG			0xffff4ffc
+#define ROM_V2				0x30303256
+
+void board_debug_uart_init(void)
+{
+	/* The BootROM leaves the debug UART configured */
+}
+
+static void rv1106_xpl_init(void)
+{
+	/* Save the chip version to OS_REG1[2:0] */
+	if (readl(ROM_VER_REG) == ROM_V2)
+		writel((readl(CHIP_VER_REG) & ~CHIP_VER_MSK) | V(2),
+		       CHIP_VER_REG);
+	else
+		writel((readl(CHIP_VER_REG) & ~CHIP_VER_MSK) | V(1),
+		       CHIP_VER_REG);
+
+	/* Set all devices to non-secure */
+	writel(0xffff0000, PERI_SGRF_BASE + PERI_SGRF_FIREWALL_CON0);
+	writel(0xffff0000, PERI_SGRF_BASE + PERI_SGRF_FIREWALL_CON1);
+	writel(0xffff0000, PERI_SGRF_BASE + PERI_SGRF_FIREWALL_CON2);
+	writel(0xffff0000, PERI_SGRF_BASE + PERI_SGRF_FIREWALL_CON3);
+	writel(0xffff0000, PERI_SGRF_BASE + PERI_SGRF_FIREWALL_CON4);
+	writel(0x000f0000, PERI_SGRF_BASE + PERI_SGRF_SOC_CON3);
+	writel(0xffff0000, CORE_SGRF_BASE + CORE_SGRF_FIREWALL_CON0);
+	writel(0xffff0000, CORE_SGRF_BASE + CORE_SGRF_FIREWALL_CON1);
+	writel(0xffff0000, CORE_SGRF_BASE + CORE_SGRF_FIREWALL_CON2);
+	writel(0xffff0000, CORE_SGRF_BASE + CORE_SGRF_FIREWALL_CON3);
+	writel(0xffff0000, CORE_SGRF_BASE + CORE_SGRF_FIREWALL_CON4);
+	writel(0x00030002, CORE_SGRF_BASE + CORE_SGRF_CPU_CTRL_CON);
+	writel(0x20000000, PMU_SGRF_BASE);
+
+	/* Allow the eMMC and FSPI to access the secure area */
+	writel(0x00000000, FW_DDR_BASE + FW_DDR_MST3_REG);
+	writel(0xff00ffff, FW_SHRM_BASE + FW_SHRM_MST1_REG);
+
+	/* Release the watchdog */
+	writel(0x2000200, PERI_GRF_BASE + PERI_GRF_PERI_CON1);
+	writel(0x400040, CRU_BASE + CRU_GLB_RST_CON);
+
+	/*
+	 * When the venc/npu use the pvtpll, a reboot fails because the
+	 * pvtpll is reset before the venc/npu reset, so the venc/npu is
+	 * not completely reset and the system blocks when accessing the
+	 * NoC in SPL. Enable the pvtpll so that the venc/npu reset can
+	 * complete.
+	 */
+	writel(0xffff0018, CRU_BASE + CRU_PVTPLL0_CON1_L);
+	writel(0x00030003, CRU_BASE + CRU_PVTPLL0_CON0_L);
+	writel(0xffff0018, CRU_BASE + CRU_PVTPLL1_CON1_L);
+	writel(0x00030003, CRU_BASE + CRU_PVTPLL1_CON0_L);
+	udelay(2);
+}
+
+int arch_cpu_init(void)
+{
+	if (is_xpl())
+		rv1106_xpl_init();
+
+	/* Reset the sdmmc0 to prevent a power leak */
+	writel(0x30003000, VICRU_BASE + VICRU_VISOFTRST_CON01);
+	udelay(1);
+	writel(0x30000000, VICRU_BASE + VICRU_VISOFTRST_CON01);
+
+	return 0;
+}
diff --git a/arch/arm/mach-rockchip/rv1106/syscon_rv1106.c b/arch/arm/mach-rockchip/rv1106/syscon_rv1106.c
new file mode 100644
index 00000000000..d669991fbc5
--- /dev/null
+++ b/arch/arm/mach-rockchip/rv1106/syscon_rv1106.c
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2022 Rockchip Electronics Co., Ltd
+ */
+
+#include <dm.h>
+#include <syscon.h>
+#include <asm/arch-rockchip/clock.h>
+
+static const struct udevice_id rv1106_syscon_ids[] = {
+	{ .compatible = "rockchip,rv1106-grf", .data = ROCKCHIP_SYSCON_GRF },
+	{ }
+};
+
+U_BOOT_DRIVER(syscon_rv1106) = {
+	.name = "rv1106_syscon",
+	.id = UCLASS_SYSCON,
+	.of_match = rv1106_syscon_ids,
+};
diff --git a/board/luckfox/pico/Kconfig b/board/luckfox/pico/Kconfig
new file mode 100644
index 00000000000..62176b3779f
--- /dev/null
+++ b/board/luckfox/pico/Kconfig
@@ -0,0 +1,12 @@
+if TARGET_LUCKFOX_PICO_RV1103
+
+config SYS_BOARD
+	default "pico"
+
+config SYS_VENDOR
+	default "luckfox"
+
+config SYS_CONFIG_NAME
+	default "luckfox_pico"
+
+endif
diff --git a/include/configs/rv1106_common.h b/include/configs/rv1106_common.h
new file mode 100644
index 00000000000..1678fe54676
--- /dev/null
+++ b/include/configs/rv1106_common.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2022 Rockchip Electronics Co., Ltd
+ */
+#ifndef __CONFIG_RV1106_COMMON_H
+#define __CONFIG_RV1106_COMMON_H
+
+#include "rockchip-common.h"
+
+#define CFG_IRAM_BASE			0xff6c0000
+#define CFG_SYS_SDRAM_BASE		0x00000000
+
+#endif
-- 
2.43.0


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

* [PATCH v3 14/15] luckfox-pico: Add the initial support
  2026-07-07 15:30 [PATCH v3 00/15] rockchip: Add support for the RV1103B, RV1103 and RV1106 Simon Glass
                   ` (12 preceding siblings ...)
  2026-07-07 15:31 ` [PATCH v3 13/15] rockchip: rv1106: Add SoC support Simon Glass
@ 2026-07-07 15:31 ` Simon Glass
  2026-07-07 15:31 ` [PATCH v3 15/15] rockchip: Support legacy images when booting from RAM Simon Glass
  2026-07-07 15:35 ` [PATCH v3 00/15] rockchip: Add support for the RV1103B, RV1103 and RV1106 Tom Rini
  15 siblings, 0 replies; 21+ messages in thread
From: Simon Glass @ 2026-07-07 15:31 UTC (permalink / raw)
  To: u-boot
  Cc: Fabio Estevam, Jonas Karlman, Simon Glass, Alexander Feilke,
	Chris Packham, FUKAUMI Naoki, Ilias Apalodimas, Johan Jonker,
	Kever Yang, Niu Zhihong, Peng Fan, Peter Robinson,
	Philipp Tomsich, Quentin Schulz, Svyatoslav Ryhel, Tianling Shen,
	Tom Rini

Add the initial support for the Luckfox Pico Mini B board, which uses
the RV1103 with 64MB of in-package DDR2 and a 128MB Winbond SPI NAND.

The board boots from the SPI NAND, or over USB in maskrom mode using
the u-boot-rockchip-usb471/usb472 images, in which case U-Boot runs
entirely from RAM. The console is on UART2 at 115200 baud

Signed-off-by: Simon Glass <sjg@chromium.org>
---

(no changes since v1)

 .../rv1103-luckfox-pico-mini-b-u-boot.dtsi    | 10 +++
 arch/arm/dts/rv1103-luckfox-pico-mini-b.dts   | 85 +++++++++++++++++++
 board/luckfox/pico/MAINTAINERS                |  6 ++
 board/luckfox/pico/Makefile                   |  7 ++
 board/luckfox/pico/pico.c                     | 19 +++++
 board/luckfox/pico/pico.env                   |  4 +
 configs/luckfox-pico-mini-b-rv1103_defconfig  | 79 +++++++++++++++++
 doc/board/index.rst                           |  1 +
 doc/board/luckfox/index.rst                   |  9 ++
 doc/board/luckfox/luckfox-pico.rst            | 71 ++++++++++++++++
 doc/board/rockchip/rockchip.rst               |  4 +
 include/configs/luckfox_pico.h                | 11 +++
 12 files changed, 306 insertions(+)
 create mode 100644 arch/arm/dts/rv1103-luckfox-pico-mini-b-u-boot.dtsi
 create mode 100644 arch/arm/dts/rv1103-luckfox-pico-mini-b.dts
 create mode 100644 board/luckfox/pico/MAINTAINERS
 create mode 100644 board/luckfox/pico/Makefile
 create mode 100644 board/luckfox/pico/pico.c
 create mode 100644 board/luckfox/pico/pico.env
 create mode 100644 configs/luckfox-pico-mini-b-rv1103_defconfig
 create mode 100644 doc/board/luckfox/index.rst
 create mode 100644 doc/board/luckfox/luckfox-pico.rst
 create mode 100644 include/configs/luckfox_pico.h

diff --git a/arch/arm/dts/rv1103-luckfox-pico-mini-b-u-boot.dtsi b/arch/arm/dts/rv1103-luckfox-pico-mini-b-u-boot.dtsi
new file mode 100644
index 00000000000..968bf1dfa66
--- /dev/null
+++ b/arch/arm/dts/rv1103-luckfox-pico-mini-b-u-boot.dtsi
@@ -0,0 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
+// (C) Copyright 2026 Simon Glass <sjg@chromium.org>
+
+#include "rockchip-u-boot.dtsi"
+
+/ {
+	chosen {
+		u-boot,spl-boot-order = &spi_nand;
+	};
+};
diff --git a/arch/arm/dts/rv1103-luckfox-pico-mini-b.dts b/arch/arm/dts/rv1103-luckfox-pico-mini-b.dts
new file mode 100644
index 00000000000..b0eac7d13c1
--- /dev/null
+++ b/arch/arm/dts/rv1103-luckfox-pico-mini-b.dts
@@ -0,0 +1,85 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2023 Luckfox Electronics Co., Ltd
+ */
+
+/dts-v1/;
+
+#include "rv1103.dtsi"
+
+/ {
+	model = "Luckfox Pico Mini B";
+	compatible = "luckfox,pico-mini-b", "rockchip,rv1103";
+
+	aliases {
+		mmc0 = &sdmmc;
+		spi0 = &sfc;
+	};
+
+	chosen {
+		stdout-path = "serial2:115200n8";
+	};
+};
+
+&sdmmc {
+	bus-width = <4>;
+	cap-sd-highspeed;
+	disable-wp;
+	status = "okay";
+};
+
+&sfc {
+	status = "okay";
+
+	spi_nand: flash@0 {
+		compatible = "spi-nand";
+		reg = <0>;
+		bootph-pre-ram;
+		bootph-some-ram;
+		spi-max-frequency = <75000000>;
+		spi-rx-bus-width = <4>;
+		spi-tx-bus-width = <1>;
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			partition@0 {
+				label = "env";
+				reg = <0x00000000 0x00040000>;
+			};
+
+			partition@40000 {
+				label = "idblock";
+				reg = <0x00040000 0x00100000>;
+				read-only;
+			};
+
+			partition@140000 {
+				label = "uboot";
+				reg = <0x00140000 0x00100000>;
+				read-only;
+			};
+
+			partition@240000 {
+				label = "boot";
+				reg = <0x00240000 0x00800000>;
+			};
+
+			partition@a40000 {
+				label = "ubi";
+				reg = <0x00a40000 0x075c0000>;
+			};
+		};
+	};
+};
+
+&uart2 {
+	bootph-all;
+	status = "okay";
+};
+
+&wdt {
+	status = "okay";
+};
diff --git a/board/luckfox/pico/MAINTAINERS b/board/luckfox/pico/MAINTAINERS
new file mode 100644
index 00000000000..debf7059cf9
--- /dev/null
+++ b/board/luckfox/pico/MAINTAINERS
@@ -0,0 +1,6 @@
+LUCKFOX PICO
+M:	Simon Glass <sjg@chromium.org>
+S:	Maintained
+F:	board/luckfox/pico
+F:	include/configs/luckfox_pico.h
+F:	configs/luckfox-pico-mini-b-rv1103_defconfig
diff --git a/board/luckfox/pico/Makefile b/board/luckfox/pico/Makefile
new file mode 100644
index 00000000000..4d2f5caff96
--- /dev/null
+++ b/board/luckfox/pico/Makefile
@@ -0,0 +1,7 @@
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+# Copyright 2026 Simon Glass <sjg@chromium.org>
+#
+
+obj-y	+= pico.o
diff --git a/board/luckfox/pico/pico.c b/board/luckfox/pico/pico.c
new file mode 100644
index 00000000000..a8a471c20f3
--- /dev/null
+++ b/board/luckfox/pico/pico.c
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: GPL-2.0+
+//
+// Copyright 2026 Simon Glass <sjg@chromium.org>
+
+#include <asm/global_data.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int dram_init(void)
+{
+	gd->ram_size = SZ_64M;
+
+	return 0;
+}
+
+phys_addr_t board_get_usable_ram_top(phys_size_t total_size)
+{
+	return gd->ram_top;
+}
diff --git a/board/luckfox/pico/pico.env b/board/luckfox/pico/pico.env
new file mode 100644
index 00000000000..0d954ee4f98
--- /dev/null
+++ b/board/luckfox/pico/pico.env
@@ -0,0 +1,4 @@
+kernel_addr_r=0x00800000
+fdt_addr_r=0x02000000
+ramdisk_addr_r=0x03000000
+bootargs=console=ttyS2,115200 mtdparts=spi0.0:256K(env),1M@256K(idblock),1M(uboot),8M(boot),-(ubi) ro rootwait ubi.mtd=ubi ubi.block=0,rootfs root=/dev/ubiblock0_0 rootfstype=squashfs
diff --git a/configs/luckfox-pico-mini-b-rv1103_defconfig b/configs/luckfox-pico-mini-b-rv1103_defconfig
new file mode 100644
index 00000000000..f857f0a42c0
--- /dev/null
+++ b/configs/luckfox-pico-mini-b-rv1103_defconfig
@@ -0,0 +1,79 @@
+CONFIG_ARM=y
+CONFIG_SKIP_LOWLEVEL_INIT=y
+CONFIG_COUNTER_FREQUENCY=24000000
+CONFIG_SYS_ARCH_TIMER=y
+CONFIG_ARCH_ROCKCHIP=y
+CONFIG_TEXT_BASE=0x00200000
+CONFIG_SYS_MALLOC_F_LEN=0x80000
+CONFIG_SPL_LIBCOMMON_SUPPORT=y
+CONFIG_SPL_LIBGENERIC_SUPPORT=y
+CONFIG_NR_DRAM_BANKS=1
+CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y
+CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x00400000
+CONFIG_SF_DEFAULT_SPEED=24000000
+CONFIG_DEFAULT_DEVICE_TREE="rv1103-luckfox-pico-mini-b"
+CONFIG_ROCKCHIP_RV1106=y
+CONFIG_SPL_ROCKCHIP_COMMON_BOARD=y
+CONFIG_ROCKCHIP_EXTERNAL_TPL=y
+CONFIG_ROCKCHIP_MASKROM_IMAGE=y
+CONFIG_SPL_SERIAL=y
+CONFIG_TARGET_LUCKFOX_PICO_RV1103=y
+CONFIG_SPL_SYS_MALLOC_F_LEN=0x100000
+CONFIG_SYS_BOOTM_LEN=0x04000000
+CONFIG_SYS_LOAD_ADDR=0x00008000
+CONFIG_DEBUG_UART_BASE=0xff4c0000
+CONFIG_DEBUG_UART_CLOCK=24000000
+# CONFIG_DEBUG_UART_BOARD_INIT is not set
+CONFIG_SPL_SPI_FLASH_SUPPORT=y
+CONFIG_SPL_SPI=y
+CONFIG_DEBUG_UART=y
+CONFIG_FIT=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_FIT_CIPHER=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_FIT_BEST_MATCH=y
+CONFIG_LEGACY_IMAGE_FORMAT=y
+CONFIG_BOOTDELAY=1
+# CONFIG_DISPLAY_CPUINFO is not set
+CONFIG_SPL_NO_BSS_LIMIT=y
+CONFIG_SPL_MTD=y
+CONFIG_SPL_SPI_NAND_LOAD=y
+CONFIG_SYS_SPI_U_BOOT_OFFS=0x140000
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_MMC=y
+CONFIG_CMD_MTD=y
+CONFIG_CMD_SPI=y
+# CONFIG_CMD_SETEXPR is not set
+CONFIG_CMD_CACHE=y
+CONFIG_CMD_TIME=y
+CONFIG_SPL_OF_CONTROL=y
+CONFIG_ENV_RELOC_GD_ENV_ADDR=y
+CONFIG_NO_NET=y
+CONFIG_SPL_DM_SEQ_ALIAS=y
+CONFIG_SYSCON=y
+CONFIG_SPL_SYSCON=y
+CONFIG_CLK=y
+CONFIG_SPL_CLK=y
+CONFIG_ROCKCHIP_GPIO=y
+CONFIG_SYS_I2C_ROCKCHIP=y
+CONFIG_MMC_DW=y
+CONFIG_MMC_DW_ROCKCHIP=y
+CONFIG_DM_MTD=y
+CONFIG_MTD_SPI_NAND=y
+CONFIG_SPI_FLASH_SFDP_SUPPORT=y
+CONFIG_SPI_FLASH_GIGADEVICE=y
+CONFIG_SPI_FLASH_WINBOND=y
+CONFIG_SPI_FLASH_XTX=y
+CONFIG_SPI_FLASH_MTD=y
+CONFIG_PINCTRL=y
+CONFIG_SPL_PINCTRL=y
+CONFIG_DM_REGULATOR_FIXED=y
+CONFIG_DEBUG_UART_SHIFT=2
+CONFIG_SYS_NS16550_MEM32=y
+CONFIG_ROCKCHIP_SFC=y
+CONFIG_SYSRESET=y
+# CONFIG_RSA is not set
+# CONFIG_SPL_SHA1 is not set
+# CONFIG_SPL_SHA256 is not set
+CONFIG_LZMA=y
+CONFIG_ERRNO_STR=y
diff --git a/doc/board/index.rst b/doc/board/index.rst
index 2454c3598fb..11ec39cf915 100644
--- a/doc/board/index.rst
+++ b/doc/board/index.rst
@@ -39,6 +39,7 @@ Board-specific doc
    kontron/index
    lenovo/index
    lg/index
+   luckfox/index
    liebherr/index
    mediatek/index
    microchip/index
diff --git a/doc/board/luckfox/index.rst b/doc/board/luckfox/index.rst
new file mode 100644
index 00000000000..66feee84257
--- /dev/null
+++ b/doc/board/luckfox/index.rst
@@ -0,0 +1,9 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+Luckfox
+=======
+
+.. toctree::
+   :maxdepth: 2
+
+   luckfox-pico
diff --git a/doc/board/luckfox/luckfox-pico.rst b/doc/board/luckfox/luckfox-pico.rst
new file mode 100644
index 00000000000..a971ee67e0b
--- /dev/null
+++ b/doc/board/luckfox/luckfox-pico.rst
@@ -0,0 +1,71 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+Luckfox Pico boards
+===================
+
+U-Boot for the Luckfox Pico series of RV1103/RV1106 boards. Only the
+Pico Mini B (RV1103, 64MB DDR2, 128MB SPI NAND) is supported so far.
+
+Quick Start
+-----------
+
+- Get the DDR initialization binary
+- Build U-Boot
+- Boot the board over USB, or flash U-Boot into the SPI NAND
+
+Get the DDR initialization binary
+---------------------------------
+
+.. code-block:: bash
+
+   $ git clone https://github.com/rockchip-linux/rkbin.git
+
+The DDR initialization binary is at rkbin/bin/rv11/rv1106_ddr_924MHz_v1.15.bin
+and covers both the RV1103 and the RV1106.
+
+Build U-Boot
+------------
+
+.. code-block:: bash
+
+   $ export CROSS_COMPILE=arm-linux-gnueabihf-
+   $ export ROCKCHIP_TPL=<path-to-rkbin>/bin/rv11/rv1106_ddr_924MHz_v1.15.bin
+   $ make luckfox-pico-mini-b-rv1103_defconfig
+   $ make
+
+This produces idbloader.img and u-boot.img for flashing to the SPI
+NAND, plus u-boot-rockchip-usb471.bin and u-boot-rockchip-usb472.bin
+for booting over USB.
+
+Boot over USB (maskrom mode)
+----------------------------
+
+Hold the BOOT button while applying power (or leave the boot media
+blank) and the BootROM enters maskrom mode on the USB OTG port,
+appearing as USB ID 2207:110c. U-Boot then runs entirely from RAM;
+nothing is written to the flash.
+
+Send the two images with a maskrom download tool such as rockusb or
+rkdeveloptool (note that the loader format parser in older
+rkdeveloptool versions is not needed here, since these are raw
+images):
+
+.. code-block:: bash
+
+   $ rockusb download-boot u-boot-rockchip-usb471.bin u-boot-rockchip-usb472.bin
+
+Flash U-Boot into the SPI NAND
+------------------------------
+
+Enter maskrom mode as above, then use a loader from rkbin to run the
+Rockchip usbplug and write the images:
+
+.. code-block:: bash
+
+   $ cd <path-to-rkbin>
+   $ ./tools/boot_merger RKBOOT/RV1106MINIALL.ini
+   $ ./tools/upgrade_tool db rv1106_download_*.bin
+   $ ./tools/upgrade_tool wl 0x200 idbloader.img
+   $ ./tools/upgrade_tool wl 0xa00 u-boot.img
+
+Power cycle the board and U-Boot output appears on UART2 (115200,8N1).
diff --git a/doc/board/rockchip/rockchip.rst b/doc/board/rockchip/rockchip.rst
index 2574a1da52c..532a13594fc 100644
--- a/doc/board/rockchip/rockchip.rst
+++ b/doc/board/rockchip/rockchip.rst
@@ -180,6 +180,10 @@ List of mainline supported Rockchip boards:
      - Yanyi Tech CoolPi CM5 EVB (coolpi-cm5-evb-rk3588)
      - Yanyi Tech CoolPi CM5 GenBook (coolpi-cm5-genbook-rk3588)
 
+* rv1103
+     - Luckfox Pico Mini B (luckfox-pico-mini-b-rv1103), see
+       :doc:`../luckfox/luckfox-pico`
+
 * rv1103b
      - Onion Omega4 (omega4-rv1103b), see :doc:`../onion/omega4-rv1103b`
 
diff --git a/include/configs/luckfox_pico.h b/include/configs/luckfox_pico.h
new file mode 100644
index 00000000000..107ab622dd5
--- /dev/null
+++ b/include/configs/luckfox_pico.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2026 Simon Glass <sjg@chromium.org>
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#include <configs/rv1106_common.h>
+
+#endif
-- 
2.43.0


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

* [PATCH v3 15/15] rockchip: Support legacy images when booting from RAM
  2026-07-07 15:30 [PATCH v3 00/15] rockchip: Add support for the RV1103B, RV1103 and RV1106 Simon Glass
                   ` (13 preceding siblings ...)
  2026-07-07 15:31 ` [PATCH v3 14/15] luckfox-pico: Add the initial support Simon Glass
@ 2026-07-07 15:31 ` Simon Glass
  2026-07-07 15:35 ` [PATCH v3 00/15] rockchip: Add support for the RV1103B, RV1103 and RV1106 Tom Rini
  15 siblings, 0 replies; 21+ messages in thread
From: Simon Glass @ 2026-07-07 15:31 UTC (permalink / raw)
  To: u-boot
  Cc: Fabio Estevam, Jonas Karlman, Simon Glass, Ilias Apalodimas,
	Jeffy Chen, Kever Yang, Philipp Tomsich, Tom Rini, huang lin

The ramboot loader used for maskrom-mode USB boot only handles FIT
payloads, but the maskrom usb472 image contains a legacy image on
32-bit boards without OP-TEE, since the FIT template requires either
TF-A or OP-TEE. Such boards print 'Trying to boot from RAM' and then
hang.

Use the binman payload symbols to locate a legacy image placed
directly after SPL and load it with spl_load(). This allows boards
like the Luckfox Pico Mini and the Omega4 to run U-Boot entirely from
RAM in maskrom mode

Signed-off-by: Simon Glass <sjg@chromium.org>
---

(no changes since v1)

 arch/arm/mach-rockchip/spl.c | 53 +++++++++++++++++++++++-------------
 1 file changed, 34 insertions(+), 19 deletions(-)

diff --git a/arch/arm/mach-rockchip/spl.c b/arch/arm/mach-rockchip/spl.c
index e989c148079..1322fc000b0 100644
--- a/arch/arm/mach-rockchip/spl.c
+++ b/arch/arm/mach-rockchip/spl.c
@@ -14,6 +14,7 @@
 #include <mapmem.h>
 #include <ram.h>
 #include <spl.h>
+#include <spl_load.h>
 #include <asm/arch-rockchip/bootrom.h>
 #include <asm/arch-rockchip/timer.h>
 #include <asm/global_data.h>
@@ -153,15 +154,14 @@ void spl_board_prepare_for_boot(void)
 	cleanup_before_linux();
 }
 
-#if CONFIG_IS_ENABLED(RAM_DEVICE) && IS_ENABLED(CONFIG_SPL_LOAD_FIT)
+#if CONFIG_IS_ENABLED(RAM_DEVICE)
 binman_sym_declare_optional(ulong, payload, image_pos);
 binman_sym_declare_optional(ulong, payload, size);
 
 static ulong ramboot_load_read(struct spl_load_info *load, ulong sector,
 			       ulong count, void *buf)
 {
-	ulong addr = IF_ENABLED_INT(CONFIG_SPL_LOAD_FIT,
-				    CONFIG_SPL_LOAD_FIT_ADDRESS);
+	ulong addr = (ulong)load->priv;
 
 	memcpy(buf, map_sysmem(addr + sector, 0), count);
 	return count;
@@ -170,29 +170,44 @@ static ulong ramboot_load_read(struct spl_load_info *load, ulong sector,
 static int ramboot_load_image(struct spl_image_info *spl_image,
 			      struct spl_boot_device *bootdev)
 {
-	struct legacy_img_hdr *header;
-	ulong addr = IF_ENABLED_INT(CONFIG_SPL_LOAD_FIT,
-				    CONFIG_SPL_LOAD_FIT_ADDRESS);
 	ulong image_pos = binman_sym(ulong, payload, image_pos);
 	ulong size = binman_sym(ulong, payload, size);
+	struct legacy_img_hdr *header;
+	struct spl_load_info load;
+
+	if (IS_ENABLED(CONFIG_SPL_LOAD_FIT)) {
+		ulong addr = IF_ENABLED_INT(CONFIG_SPL_LOAD_FIT,
+					    CONFIG_SPL_LOAD_FIT_ADDRESS);
+
+		if (addr == CFG_SYS_SDRAM_BASE || addr == CONFIG_SPL_TEXT_BASE)
+			return -ENODEV;
+
+		if (image_pos != BINMAN_SYM_MISSING &&
+		    size != BINMAN_SYM_MISSING) {
+			header = map_sysmem(image_pos, 0);
+			if (image_get_magic(header) == FDT_MAGIC) {
+				memmove(map_sysmem(addr, 0), header, size);
+				memset(header, 0, sizeof(*header));
+			}
+		}
 
-	if (addr == CFG_SYS_SDRAM_BASE || addr == CONFIG_SPL_TEXT_BASE)
-		return -ENODEV;
-
-	if (image_pos != BINMAN_SYM_MISSING && size != BINMAN_SYM_MISSING) {
-		header = map_sysmem(image_pos, 0);
+		header = map_sysmem(addr, 0);
 		if (image_get_magic(header) == FDT_MAGIC) {
-			memmove(map_sysmem(addr, 0), header, size);
-			memset(header, 0, sizeof(*header));
+			spl_load_init(&load, ramboot_load_read,
+				      map_sysmem(addr, 0), 1);
+			return spl_load_simple_fit(spl_image, &load, 0,
+						   header);
 		}
 	}
 
-	header = map_sysmem(addr, 0);
-	if (image_get_magic(header) == FDT_MAGIC) {
-		struct spl_load_info load;
-
-		spl_load_init(&load, ramboot_load_read, NULL, 1);
-		return spl_load_simple_fit(spl_image, &load, 0, header);
+	/* Fall back to a legacy image placed directly after SPL */
+	if (image_pos != BINMAN_SYM_MISSING && size != BINMAN_SYM_MISSING) {
+		header = map_sysmem(image_pos, 0);
+		if (image_get_magic(header) == IH_MAGIC) {
+			spl_load_init(&load, ramboot_load_read,
+				      map_sysmem(image_pos, 0), 1);
+			return spl_load(spl_image, bootdev, &load, size, 0);
+		}
 	}
 
 	return -ENODEV;
-- 
2.43.0


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

* Re: [PATCH v3 00/15] rockchip: Add support for the RV1103B, RV1103 and RV1106
  2026-07-07 15:30 [PATCH v3 00/15] rockchip: Add support for the RV1103B, RV1103 and RV1106 Simon Glass
                   ` (14 preceding siblings ...)
  2026-07-07 15:31 ` [PATCH v3 15/15] rockchip: Support legacy images when booting from RAM Simon Glass
@ 2026-07-07 15:35 ` Tom Rini
  2026-07-08 22:36   ` Simon Glass
  15 siblings, 1 reply; 21+ messages in thread
From: Tom Rini @ 2026-07-07 15:35 UTC (permalink / raw)
  To: Simon Glass
  Cc: u-boot, Fabio Estevam, Jonas Karlman, Albert Aribaud,
	Alexander Feilke, Alexey Charkov, Alexey Charkov, Andrew Davis,
	Anshul Dalal, Bastien Curutchet, Chris Morgan, Chris Packham,
	Elaine Zhang, FUKAUMI Naoki, Finley Xiao, Heinrich Schuchardt,
	Hrushikesh Salunke, Ilias Apalodimas, Jeffy Chen, Johan Jonker,
	João Marcos Costa, Kever Yang, Lukasz Majewski,
	Mattijs Korpershoek, Neil Armstrong, Niu Zhihong, Peng Fan,
	Peter Robinson, Philipp Tomsich, Quentin Schulz, Richard Genoud,
	Svyatoslav Ryhel, Tianling Shen, Xuhui Lin, Ye Zhang, huang lin

[-- Attachment #1: Type: text/plain, Size: 1625 bytes --]

On Tue, Jul 07, 2026 at 09:30:58AM -0600, Simon Glass wrote:

> This series adds support for three small Rockchip camera SoCs and two
> boards which use them.
> 
> The first eight patches are Fabio Estevam's series adding the RV1103B
> and the Onion Omega4 board, updated here to address the review
> comments on v2: the board patch is split into SoC and board patches,
> the devicetree files move into the patches where they belong and the
> pinctrl driver uses regmap_update_bits() throughout. All credit for
> this work goes to Fabio. The devicetree concern raised in the v2
> review is also resolved now: the devicetree files carried here are the
> versions merged in Linux v7.1, verbatim, and can be dropped once the
> next dts/upstream sync brings them in.
> 
> The remaining patches add the RV1106 and its RV1103 package variant,
> following the same structure as the RV1103B patches, together with
> the Luckfox Pico Mini B board. These SoCs have no mainline Linux
> support yet, so their devicetrees are local for now. The clock and
> pinctrl drivers are ported from the Rockchip vendor tree and are the
> work of Elaine Zhang and Ye Zhang. The final patch makes the
> maskrom-mode RAM-boot images work on 32-bit boards without OP-TEE,
> which both of these boards rely on.
> 
> Tested on the Luckfox Pico Mini B: U-Boot runs from RAM over the USB
> maskrom path and both the SPI NAND and a microSD card are usable. THe
> board is running in my lab.

I did ask you not to do this, Simon, as your patches aren't being picked
up until we've resolved the status of u-boot.org.

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

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

* Re: [PATCH v3 00/15] rockchip: Add support for the RV1103B, RV1103 and RV1106
  2026-07-07 15:35 ` [PATCH v3 00/15] rockchip: Add support for the RV1103B, RV1103 and RV1106 Tom Rini
@ 2026-07-08 22:36   ` Simon Glass
  2026-07-09  0:38     ` Tom Rini
  0 siblings, 1 reply; 21+ messages in thread
From: Simon Glass @ 2026-07-08 22:36 UTC (permalink / raw)
  To: Tom Rini
  Cc: U-Boot Mailing List, Fabio Estevam, Jonas Karlman, Albert Aribaud,
	Alexander Feilke, Alexey Charkov, Alexey Charkov, Andrew Davis,
	Anshul Dalal, Bastien Curutchet, Chris Morgan, Chris Packham,
	Elaine Zhang, FUKAUMI Naoki, Finley Xiao, Heinrich Schuchardt,
	Hrushikesh Salunke, Ilias Apalodimas, Jeffy Chen, Johan Jonker,
	João Marcos Costa, Kever Yang, Lukasz Majewski,
	Mattijs Korpershoek, Neil Armstrong, Niu Zhihong, Peng Fan,
	Peter Robinson, Philipp Tomsich, Quentin Schulz, Richard Genoud,
	Svyatoslav Ryhel, Tianling Shen, Xuhui Lin, Ye Zhang, huang lin

Hi Tom,

On Tue, 7 Jul 2026 at 09:35, Tom Rini <trini@konsulko.com> wrote:
>
> On Tue, Jul 07, 2026 at 09:30:58AM -0600, Simon Glass wrote:
>
> > This series adds support for three small Rockchip camera SoCs and two
> > boards which use them.
> >
> > The first eight patches are Fabio Estevam's series adding the RV1103B
> > and the Onion Omega4 board, updated here to address the review
> > comments on v2: the board patch is split into SoC and board patches,
> > the devicetree files move into the patches where they belong and the
> > pinctrl driver uses regmap_update_bits() throughout. All credit for
> > this work goes to Fabio. The devicetree concern raised in the v2
> > review is also resolved now: the devicetree files carried here are the
> > versions merged in Linux v7.1, verbatim, and can be dropped once the
> > next dts/upstream sync brings them in.
> >
> > The remaining patches add the RV1106 and its RV1103 package variant,
> > following the same structure as the RV1103B patches, together with
> > the Luckfox Pico Mini B board. These SoCs have no mainline Linux
> > support yet, so their devicetrees are local for now. The clock and
> > pinctrl drivers are ported from the Rockchip vendor tree and are the
> > work of Elaine Zhang and Ye Zhang. The final patch makes the
> > maskrom-mode RAM-boot images work on 32-bit boards without OP-TEE,
> > which both of these boards rely on.
> >
> > Tested on the Luckfox Pico Mini B: U-Boot runs from RAM over the USB
> > maskrom path and both the SPI NAND and a microSD card are usable. THe
> > board is running in my lab.
>
> I did ask you not to do this, Simon, as your patches aren't being picked
> up until we've resolved the status of u-boot.org.

I just saw that email Tom...OK, so I should not send any patches at all?

Regards,
Simon

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

* Re: [PATCH v3 00/15] rockchip: Add support for the RV1103B, RV1103 and RV1106
  2026-07-08 22:36   ` Simon Glass
@ 2026-07-09  0:38     ` Tom Rini
  2026-07-09  1:27       ` Simon Glass
  0 siblings, 1 reply; 21+ messages in thread
From: Tom Rini @ 2026-07-09  0:38 UTC (permalink / raw)
  To: Simon Glass
  Cc: U-Boot Mailing List, Fabio Estevam, Jonas Karlman, Albert Aribaud,
	Alexander Feilke, Alexey Charkov, Alexey Charkov, Andrew Davis,
	Anshul Dalal, Bastien Curutchet, Chris Morgan, Chris Packham,
	Elaine Zhang, FUKAUMI Naoki, Finley Xiao, Heinrich Schuchardt,
	Hrushikesh Salunke, Ilias Apalodimas, Jeffy Chen, Johan Jonker,
	João Marcos Costa, Kever Yang, Lukasz Majewski,
	Mattijs Korpershoek, Neil Armstrong, Niu Zhihong, Peng Fan,
	Peter Robinson, Philipp Tomsich, Quentin Schulz, Richard Genoud,
	Svyatoslav Ryhel, Tianling Shen, Xuhui Lin, Ye Zhang, huang lin

[-- Attachment #1: Type: text/plain, Size: 2173 bytes --]

On Wed, Jul 08, 2026 at 04:36:57PM -0600, Simon Glass wrote:
> Hi Tom,
> 
> On Tue, 7 Jul 2026 at 09:35, Tom Rini <trini@konsulko.com> wrote:
> >
> > On Tue, Jul 07, 2026 at 09:30:58AM -0600, Simon Glass wrote:
> >
> > > This series adds support for three small Rockchip camera SoCs and two
> > > boards which use them.
> > >
> > > The first eight patches are Fabio Estevam's series adding the RV1103B
> > > and the Onion Omega4 board, updated here to address the review
> > > comments on v2: the board patch is split into SoC and board patches,
> > > the devicetree files move into the patches where they belong and the
> > > pinctrl driver uses regmap_update_bits() throughout. All credit for
> > > this work goes to Fabio. The devicetree concern raised in the v2
> > > review is also resolved now: the devicetree files carried here are the
> > > versions merged in Linux v7.1, verbatim, and can be dropped once the
> > > next dts/upstream sync brings them in.
> > >
> > > The remaining patches add the RV1106 and its RV1103 package variant,
> > > following the same structure as the RV1103B patches, together with
> > > the Luckfox Pico Mini B board. These SoCs have no mainline Linux
> > > support yet, so their devicetrees are local for now. The clock and
> > > pinctrl drivers are ported from the Rockchip vendor tree and are the
> > > work of Elaine Zhang and Ye Zhang. The final patch makes the
> > > maskrom-mode RAM-boot images work on 32-bit boards without OP-TEE,
> > > which both of these boards rely on.
> > >
> > > Tested on the Luckfox Pico Mini B: U-Boot runs from RAM over the USB
> > > maskrom path and both the SPI NAND and a microSD card are usable. THe
> > > board is running in my lab.
> >
> > I did ask you not to do this, Simon, as your patches aren't being picked
> > up until we've resolved the status of u-boot.org.
> 
> I just saw that email Tom...OK, so I should not send any patches at all?

As I told you on the community call over two weeks ago now, I'm not
comfortable taking your patches until we have resolved the u-boot.org
domain transfer. So no, your patches are not being merged.

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

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

* Re: [PATCH v3 00/15] rockchip: Add support for the RV1103B, RV1103 and RV1106
  2026-07-09  0:38     ` Tom Rini
@ 2026-07-09  1:27       ` Simon Glass
  2026-07-09  1:40         ` Tom Rini
  0 siblings, 1 reply; 21+ messages in thread
From: Simon Glass @ 2026-07-09  1:27 UTC (permalink / raw)
  To: Tom Rini
  Cc: U-Boot Mailing List, Fabio Estevam, Jonas Karlman, Albert Aribaud,
	Alexander Feilke, Alexey Charkov, Alexey Charkov, Andrew Davis,
	Anshul Dalal, Bastien Curutchet, Chris Morgan, Chris Packham,
	Elaine Zhang, FUKAUMI Naoki, Finley Xiao, Heinrich Schuchardt,
	Hrushikesh Salunke, Ilias Apalodimas, Jeffy Chen, Johan Jonker,
	João Marcos Costa, Kever Yang, Lukasz Majewski,
	Mattijs Korpershoek, Neil Armstrong, Niu Zhihong, Peng Fan,
	Peter Robinson, Philipp Tomsich, Quentin Schulz, Richard Genoud,
	Svyatoslav Ryhel, Tianling Shen, Xuhui Lin, Ye Zhang, huang lin

Hi Tom,

On Wed, 8 Jul 2026 at 18:38, Tom Rini <trini@konsulko.com> wrote:
>
> On Wed, Jul 08, 2026 at 04:36:57PM -0600, Simon Glass wrote:
> > Hi Tom,
> >
> > On Tue, 7 Jul 2026 at 09:35, Tom Rini <trini@konsulko.com> wrote:
> > >
> > > On Tue, Jul 07, 2026 at 09:30:58AM -0600, Simon Glass wrote:
> > >
> > > > This series adds support for three small Rockchip camera SoCs and two
> > > > boards which use them.
> > > >
> > > > The first eight patches are Fabio Estevam's series adding the RV1103B
> > > > and the Onion Omega4 board, updated here to address the review
> > > > comments on v2: the board patch is split into SoC and board patches,
> > > > the devicetree files move into the patches where they belong and the
> > > > pinctrl driver uses regmap_update_bits() throughout. All credit for
> > > > this work goes to Fabio. The devicetree concern raised in the v2
> > > > review is also resolved now: the devicetree files carried here are the
> > > > versions merged in Linux v7.1, verbatim, and can be dropped once the
> > > > next dts/upstream sync brings them in.
> > > >
> > > > The remaining patches add the RV1106 and its RV1103 package variant,
> > > > following the same structure as the RV1103B patches, together with
> > > > the Luckfox Pico Mini B board. These SoCs have no mainline Linux
> > > > support yet, so their devicetrees are local for now. The clock and
> > > > pinctrl drivers are ported from the Rockchip vendor tree and are the
> > > > work of Elaine Zhang and Ye Zhang. The final patch makes the
> > > > maskrom-mode RAM-boot images work on 32-bit boards without OP-TEE,
> > > > which both of these boards rely on.
> > > >
> > > > Tested on the Luckfox Pico Mini B: U-Boot runs from RAM over the USB
> > > > maskrom path and both the SPI NAND and a microSD card are usable. THe
> > > > board is running in my lab.
> > >
> > > I did ask you not to do this, Simon, as your patches aren't being picked
> > > up until we've resolved the status of u-boot.org.
> >
> > I just saw that email Tom...OK, so I should not send any patches at all?
>
> As I told you on the community call over two weeks ago now, I'm not
> comfortable taking your patches until we have resolved the u-boot.org
> domain transfer. So no, your patches are not being merged.

Do you mean:

- still send patches, they might be reviewed but will not be merged
until we resolve the Concept tree / domain
- stop sending patches completely

Regards,
Simon

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

* Re: [PATCH v3 00/15] rockchip: Add support for the RV1103B, RV1103 and RV1106
  2026-07-09  1:27       ` Simon Glass
@ 2026-07-09  1:40         ` Tom Rini
  0 siblings, 0 replies; 21+ messages in thread
From: Tom Rini @ 2026-07-09  1:40 UTC (permalink / raw)
  To: Simon Glass; +Cc: U-Boot Mailing List

[-- Attachment #1: Type: text/plain, Size: 2979 bytes --]

Dropping everyone else except for the list itself.

On Wed, Jul 08, 2026 at 07:27:52PM -0600, Simon Glass wrote:
> Hi Tom,
> 
> On Wed, 8 Jul 2026 at 18:38, Tom Rini <trini@konsulko.com> wrote:
> >
> > On Wed, Jul 08, 2026 at 04:36:57PM -0600, Simon Glass wrote:
> > > Hi Tom,
> > >
> > > On Tue, 7 Jul 2026 at 09:35, Tom Rini <trini@konsulko.com> wrote:
> > > >
> > > > On Tue, Jul 07, 2026 at 09:30:58AM -0600, Simon Glass wrote:
> > > >
> > > > > This series adds support for three small Rockchip camera SoCs and two
> > > > > boards which use them.
> > > > >
> > > > > The first eight patches are Fabio Estevam's series adding the RV1103B
> > > > > and the Onion Omega4 board, updated here to address the review
> > > > > comments on v2: the board patch is split into SoC and board patches,
> > > > > the devicetree files move into the patches where they belong and the
> > > > > pinctrl driver uses regmap_update_bits() throughout. All credit for
> > > > > this work goes to Fabio. The devicetree concern raised in the v2
> > > > > review is also resolved now: the devicetree files carried here are the
> > > > > versions merged in Linux v7.1, verbatim, and can be dropped once the
> > > > > next dts/upstream sync brings them in.
> > > > >
> > > > > The remaining patches add the RV1106 and its RV1103 package variant,
> > > > > following the same structure as the RV1103B patches, together with
> > > > > the Luckfox Pico Mini B board. These SoCs have no mainline Linux
> > > > > support yet, so their devicetrees are local for now. The clock and
> > > > > pinctrl drivers are ported from the Rockchip vendor tree and are the
> > > > > work of Elaine Zhang and Ye Zhang. The final patch makes the
> > > > > maskrom-mode RAM-boot images work on 32-bit boards without OP-TEE,
> > > > > which both of these boards rely on.
> > > > >
> > > > > Tested on the Luckfox Pico Mini B: U-Boot runs from RAM over the USB
> > > > > maskrom path and both the SPI NAND and a microSD card are usable. THe
> > > > > board is running in my lab.
> > > >
> > > > I did ask you not to do this, Simon, as your patches aren't being picked
> > > > up until we've resolved the status of u-boot.org.
> > >
> > > I just saw that email Tom...OK, so I should not send any patches at all?
> >
> > As I told you on the community call over two weeks ago now, I'm not
> > comfortable taking your patches until we have resolved the u-boot.org
> > domain transfer. So no, your patches are not being merged.
> 
> Do you mean:
> 
> - still send patches, they might be reviewed but will not be merged
> until we resolve the Concept tree / domain
> - stop sending patches completely

I don't want to start another mega-thread.

I'm unsure what is unclear about "I'm not comfortable taking your
patches until we have resolved the u-boot.org domain transfer".

I'm unsure what else I can add here that won't result in another
mega-thread.

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

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

end of thread, other threads:[~2026-07-09  1:55 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-07 15:30 [PATCH v3 00/15] rockchip: Add support for the RV1103B, RV1103 and RV1106 Simon Glass
2026-07-07 15:30 ` [PATCH v3 01/15] ARM: dts: Add the RV1103B devicetree files Simon Glass
2026-07-07 15:31 ` [PATCH v3 02/15] pinctrl: rockchip: Add RV1103B support Simon Glass
2026-07-07 15:31 ` [PATCH v3 03/15] clk: rockchip: Add RV1103B clock driver Simon Glass
2026-07-07 15:31 ` [PATCH v3 04/15] tools: rkcommon: Add RV1103B support Simon Glass
2026-07-07 15:31 ` [PATCH v3 05/15] rockchip: spl-boot-order: Add SPI NAND support Simon Glass
2026-07-07 15:31 ` [PATCH v3 06/15] spl: Add SPI NAND support via MTD in SPL Simon Glass
2026-07-07 15:31 ` [PATCH v3 07/15] rockchip: rv1103b: Add SoC support Simon Glass
2026-07-07 15:31 ` [PATCH v3 08/15] omega4-rv1103b: Add the initial support Simon Glass
2026-07-07 15:31 ` [PATCH v3 09/15] tools: rkcommon: Add RV1106 support Simon Glass
2026-07-07 15:31 ` [PATCH v3 10/15] pinctrl: rockchip: " Simon Glass
2026-07-07 15:31 ` [PATCH v3 11/15] ARM: dts: Add the RV1103/RV1106 devicetree files Simon Glass
2026-07-07 15:31 ` [PATCH v3 12/15] clk: rockchip: Add RV1106 clock driver Simon Glass
2026-07-07 15:31 ` [PATCH v3 13/15] rockchip: rv1106: Add SoC support Simon Glass
2026-07-07 15:31 ` [PATCH v3 14/15] luckfox-pico: Add the initial support Simon Glass
2026-07-07 15:31 ` [PATCH v3 15/15] rockchip: Support legacy images when booting from RAM Simon Glass
2026-07-07 15:35 ` [PATCH v3 00/15] rockchip: Add support for the RV1103B, RV1103 and RV1106 Tom Rini
2026-07-08 22:36   ` Simon Glass
2026-07-09  0:38     ` Tom Rini
2026-07-09  1:27       ` Simon Glass
2026-07-09  1:40         ` Tom Rini

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