public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
* [PATCH v2 0/7] ARM: Add RV1103B Omega4 board support
@ 2026-02-08 21:26 Fabio Estevam
  2026-02-08 21:26 ` [PATCH v2 1/7] ARM: dts: Add RV1103B Omega4 support Fabio Estevam
                   ` (6 more replies)
  0 siblings, 7 replies; 12+ messages in thread
From: Fabio Estevam @ 2026-02-08 21:26 UTC (permalink / raw)
  To: kever.yang; +Cc: trini, jonas, u-boot, Fabio Estevam

From: Fabio Estevam <festevam@nabladev.com>

Hi,

This patch series adds support for the Onion RV1103B Omega4 board.

It covers SPL, SPI NAND boot, and the minimal board devicetree required to
boot the board.

Upstreaming the RV1103B devicetree in Linux is ongoing, but to avoid blocking
U-Boot support, this series introduces board-specific devicetrees for now.

Once the Linux RV1103B devicetrees are upstreamed, the OF_UPSTREAM mechanism
can be enabled.

In v2, the correct SoC name was used: RV1103B instead of RV1103 (Thanks Jonas!),
the RV1103B dt-bindings, devicetrees, clock and pinctrl drivers have been
submitted upstream.

The dt-bindings have already been reviewed by the Linux DT maintainer:

https://lore.kernel.org/linux-devicetree/cadee46d-589b-4833-8650-691f7a0f8321@kernel.org/

https://lore.kernel.org/linux-devicetree/a2be67b7-a33a-4d72-b5b7-fa900063b599@kernel.org/

https://lore.kernel.org/linux-devicetree/47561412-cbaa-42c7-b8ab-9cafb7e0f9be@kernel.org/

https://lore.kernel.org/linux-devicetree/20260207-hulking-elegant-ferret-8efcea@quoll/

https://lore.kernel.org/linux-devicetree/20260208-analytic-fine-grouse-e17baa@quoll/

https://lore.kernel.org/linux-devicetree/20260208-pearl-ammonite-of-warranty-2c9212@quoll/

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

This series has successfully passed through CI.

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

Fabio Estevam (4):
  ARM: dts: Add RV1103B Omega4 support
  rockchip: spl-boot-order: Add SPI NAND support
  spl: add SPI NAND support via MTD in SPL
  omega4-rv1103b: Add the initial support

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

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

 arch/arm/dts/rv1103b-omega4-u-boot.dtsi       |   10 +
 arch/arm/dts/rv1103b-omega4.dts               |  105 ++
 arch/arm/dts/rv1103b-pinctrl.dtsi             |  831 +++++++++++++
 arch/arm/dts/rv1103b-u-boot.dtsi              |    4 +
 arch/arm/dts/rv1103b.dtsi                     |  266 ++++
 .../include/asm/arch-rockchip/cru_rv1103b.h   |  266 ++++
 .../include/asm/arch-rockchip/grf_rv1103b.h   |   31 +
 arch/arm/include/asm/arch-rv1103b/boot0.h     |   11 +
 arch/arm/mach-rockchip/Kconfig                |   14 +
 arch/arm/mach-rockchip/Makefile               |    1 +
 arch/arm/mach-rockchip/rv1103b/Kconfig        |   23 +
 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/spl-boot-order.c       |   11 +-
 board/onion/omega4_rv1103b/Kconfig            |   12 +
 board/onion/omega4_rv1103b/MAINTAINERS        |    6 +
 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/omega4-rv1103b_defconfig              |   82 ++
 doc/board/index.rst                           |    1 +
 doc/board/onion/index.rst                     |    9 +
 doc/board/onion/omega4-rv1103b.rst            |   56 +
 drivers/clk/rockchip/Makefile                 |    1 +
 drivers/clk/rockchip/clk_rv1103b.c            | 1068 +++++++++++++++++
 drivers/mtd/Makefile                          |    1 +
 drivers/mtd/nand/Makefile                     |   13 +-
 drivers/pinctrl/rockchip/Makefile             |    1 +
 drivers/pinctrl/rockchip/pinctrl-rv1103b.c    |  398 ++++++
 include/configs/omega4_rv1103b.h              |   11 +
 include/configs/rv1103b_common.h              |   14 +
 .../dt-bindings/clock/rockchip,rv1103b-cru.h  |  220 ++++
 tools/rkcommon.c                              |    1 +
 39 files changed, 3788 insertions(+), 4 deletions(-)
 create mode 100644 arch/arm/dts/rv1103b-omega4-u-boot.dtsi
 create mode 100644 arch/arm/dts/rv1103b-omega4.dts
 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/include/asm/arch-rockchip/cru_rv1103b.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/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 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/omega4-rv1103b_defconfig
 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/pinctrl/rockchip/pinctrl-rv1103b.c
 create mode 100644 include/configs/omega4_rv1103b.h
 create mode 100644 include/configs/rv1103b_common.h
 create mode 100644 include/dt-bindings/clock/rockchip,rv1103b-cru.h

-- 
2.34.1


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

* [PATCH v2 1/7] ARM: dts: Add RV1103B Omega4 support
  2026-02-08 21:26 [PATCH v2 0/7] ARM: Add RV1103B Omega4 board support Fabio Estevam
@ 2026-02-08 21:26 ` Fabio Estevam
  2026-02-09 10:45   ` Jonas Karlman
  2026-02-08 21:26 ` [PATCH v2 2/7] pinctrl: rockchip: Add RV1103B support Fabio Estevam
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 12+ messages in thread
From: Fabio Estevam @ 2026-02-08 21:26 UTC (permalink / raw)
  To: kever.yang; +Cc: trini, jonas, u-boot, Fabio Estevam

From: Fabio Estevam <festevam@nabladev.com>

Add the necessary devicetrees to support the RV1103B Omega4 board.

The RV1103B is a Rockchip SoC that is still not supported in Linux
mainline.

The initial RV1103B support has already been submitted to Linux kernel
and it is under review.

Once the Linux RV1103 devicetrees are upstreamed, the OF_UPSTREAM mechanism
can be enabled.

Signed-off-by: Fabio Estevam <festevam@nabladev.com>
---
Changes since v1:
- Used the devicetrees submitted to upstream Linux.

 arch/arm/dts/rv1103b-omega4-u-boot.dtsi       |  10 +
 arch/arm/dts/rv1103b-omega4.dts               | 105 +++
 arch/arm/dts/rv1103b-pinctrl.dtsi             | 831 ++++++++++++++++++
 arch/arm/dts/rv1103b-u-boot.dtsi              |   4 +
 arch/arm/dts/rv1103b.dtsi                     | 266 ++++++
 .../dt-bindings/clock/rockchip,rv1103b-cru.h  | 220 +++++
 6 files changed, 1436 insertions(+)
 create mode 100644 arch/arm/dts/rv1103b-omega4-u-boot.dtsi
 create mode 100644 arch/arm/dts/rv1103b-omega4.dts
 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 include/dt-bindings/clock/rockchip,rv1103b-cru.h

diff --git a/arch/arm/dts/rv1103b-omega4-u-boot.dtsi b/arch/arm/dts/rv1103b-omega4-u-boot.dtsi
new file mode 100644
index 000000000000..c7616de1715c
--- /dev/null
+++ b/arch/arm/dts/rv1103b-omega4-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.dts b/arch/arm/dts/rv1103b-omega4.dts
new file mode 100644
index 000000000000..3d58954d5e4a
--- /dev/null
+++ b/arch/arm/dts/rv1103b-omega4.dts
@@ -0,0 +1,105 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2022 Rockchip Electronics Co., Ltd.
+ * Copyright (c) 2025 plan44.ch/luz
+ * Copyright (c) 2025 Onion Corporation
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/leds/common.h>
+#include "rv1103b.dtsi"
+
+/ {
+	model = "Onion RV1103 Omega4 Board";
+	compatible = "onion,rv1103b-omega4", "rockchip,rv1103b";
+
+	aliases {
+		serial0 = &uart0;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		led-0	{
+			pinctrl-names = "default";
+			pinctrl-0 = <&led_pin>;
+			gpios = <&gpio0 RK_PA2 GPIO_ACTIVE_HIGH>;
+			function = LED_FUNCTION_STATUS;
+			color = <LED_COLOR_ID_BLUE>;
+			label = "sys";
+			default-state = "on";
+		};
+	};
+};
+
+&fspi0 {
+	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 0x0f5c0000>;
+			};
+		};
+	};
+};
+
+&uart0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0m0_xfer_pins>;
+	bootph-all;
+	status = "okay";
+};
+
+&wdt {
+	status = "okay";
+};
+
+&pinctrl {
+	leds {
+		led_pin: led-pin {
+			rockchip,pins = <0 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+};
diff --git a/arch/arm/dts/rv1103b-pinctrl.dtsi b/arch/arm/dts/rv1103b-pinctrl.dtsi
new file mode 100644
index 000000000000..bc4d8fcdfaf7
--- /dev/null
+++ b/arch/arm/dts/rv1103b-pinctrl.dtsi
@@ -0,0 +1,831 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2024 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 {
+	cam_clk0 {
+		cam_clk0_pins: cam-clk0-pins {
+			rockchip,pins =
+				/* cam_clk0_out */
+				<1 RK_PB5 1 &pcfg_pull_none>;
+		};
+	};
+
+	cam_clk1 {
+		cam_clk1_pins: cam-clk1-pins {
+			rockchip,pins =
+				/* cam_clk1_out */
+				<1 RK_PB6 1 &pcfg_pull_none>;
+		};
+	};
+
+	cam_spi {
+		cam_spi_bus4_pins: cam-spi-bus4-pins {
+			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>;
+		};
+		cam_spi_clk_pins: cam-spi-clk-pins {
+			rockchip,pins =
+				/* cam_spi_clk */
+				<0 RK_PB4 4 &pcfg_pull_none>;
+		};
+		cam_spi_cs0n_pins: cam-spi-cs0n-pins {
+			rockchip,pins =
+				/* cam_spi_cs0n */
+				<0 RK_PB3 4 &pcfg_pull_none>;
+		};
+	};
+
+	clk {
+		clk_32k_pins: clk-32k-pins {
+			rockchip,pins =
+				/* clk_32k */
+				<0 RK_PA0 2 &pcfg_pull_none>;
+		};
+	};
+
+	clk_24m {
+		clk_24m_out_pins: clk-24m-out-pins {
+			rockchip,pins =
+				/* clk_24m_out */
+				<0 RK_PA0 3 &pcfg_pull_none>;
+		};
+	};
+
+	cpu {
+		cpu_pins: cpu-pins {
+			rockchip,pins =
+				/* cpu_avs */
+				<0 RK_PA1 2 &pcfg_pull_none>;
+		};
+	};
+
+	emmc {
+		emmc_bus4_pins: emmc-bus4-pins {
+			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>;
+		};
+		emmc_clk_pins: emmc-clk-pins {
+			rockchip,pins =
+				/* emmc_clk */
+				<1 RK_PA4 1 &pcfg_pull_up_drv_level_2>;
+		};
+		emmc_cmd_pins: emmc-cmd-pins {
+			rockchip,pins =
+				/* emmc_cmd */
+				<1 RK_PA5 1 &pcfg_pull_up_drv_level_2>;
+		};
+	};
+
+	emmc_testclk {
+		emmc_testclk_clk_pins: emmc-testclk-clk-pins {
+			rockchip,pins =
+				/* emmc_testclk_out */
+				<1 RK_PA7 3 &pcfg_pull_up_drv_level_2>;
+		};
+	};
+
+	emmc_testdata {
+		emmc_testdata_out_pins: emmc-testdata-out-pins {
+			rockchip,pins =
+				/* emmc_testdata_out */
+				<1 RK_PB0 3 &pcfg_pull_none>;
+		};
+	};
+
+	eth_led {
+		eth_led_dpx_pins: eth-led-dpx-pins {
+			rockchip,pins =
+				/* eth_led_dpx */
+				<2 RK_PA4 6 &pcfg_pull_none>;
+		};
+		eth_led_link_pins: eth-led-link-pins {
+			rockchip,pins =
+				/* eth_led_link */
+				<2 RK_PA6 6 &pcfg_pull_none>;
+		};
+		eth_led_spd_pins: eth-led-spd-pins {
+			rockchip,pins =
+				/* eth_led_spd */
+				<2 RK_PA7 6 &pcfg_pull_none>;
+		};
+	};
+
+	flash_trig {
+		flash_trig_pins: flash-trig-pins {
+			rockchip,pins =
+				/* flash_trig_out */
+				<2 RK_PB0 6 &pcfg_pull_none>;
+		};
+	};
+
+	fspi {
+		fspi_bus4_pins: fspi-bus4-pins {
+			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>;
+		};
+		fspi_cs0_pins: fspi-cs0-pins {
+			rockchip,pins =
+				/* fspi_cs0n */
+				<1 RK_PA5 2 &pcfg_pull_up>;
+		};
+		fspi_clk_pins: fspi-clk-pins {
+			rockchip,pins =
+				/* fspi_clk */
+				<1 RK_PA4 2 &pcfg_pull_none>;
+		};
+	};
+
+	fspi_testclk {
+		fspi_testclk_out_pins: fspi-testclk-out-pins {
+			rockchip,pins =
+				/* fspi_testclk_out */
+				<1 RK_PA7 5 &pcfg_pull_none>;
+		};
+	};
+
+	fspi_testdata {
+		fspi_testdata_out_pins: fspi-testdata-out-pins {
+			rockchip,pins =
+				/* fspi_testdata_out */
+				<1 RK_PB0 5 &pcfg_pull_none>;
+		};
+	};
+
+	i2c0 {
+		i2c0m0_xfer_pins: i2c0m0-xfer-pins {
+			rockchip,pins =
+				/* i2c0_scl_m0 */
+				<0 RK_PA5 3 &pcfg_pull_none_smt>,
+				/* i2c0_sda_m0 */
+				<0 RK_PA6 3 &pcfg_pull_none_smt>;
+		};
+		i2c0m1_xfer_pins: i2c0m1-xfer-pins {
+			rockchip,pins =
+				/* i2c0_scl_m1 */
+				<1 RK_PB4 5 &pcfg_pull_none_smt>,
+				/* i2c0_sda_m1 */
+				<1 RK_PB3 5 &pcfg_pull_none_smt>;
+		};
+		i2c0m2_xfer_pins: i2c0m2-xfer-pins {
+			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 {
+		i2c1m0_xfer_pins: i2c1m0-xfer-pins {
+			rockchip,pins =
+				/* i2c1_scl_m0 */
+				<0 RK_PB0 1 &pcfg_pull_none_smt>,
+				/* i2c1_sda_m0 */
+				<0 RK_PB1 1 &pcfg_pull_none_smt>;
+		};
+		i2c1m1_xfer_pins: i2c1m1-xfer-pins {
+			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 {
+		i2c2m0_xfer_pins: i2c2m0-xfer-pins {
+			rockchip,pins =
+				/* i2c2_scl_m0 */
+				<0 RK_PB2 1 &pcfg_pull_none_smt>,
+				/* i2c2_sda_m0 */
+				<0 RK_PB3 1 &pcfg_pull_none_smt>;
+		};
+		i2c2m1_xfer_pins: i2c2m1-xfer-pins {
+			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 {
+		i2c3m0_xfer_pins: i2c3m0-xfer-pins {
+			rockchip,pins =
+				/* i2c3_scl_m0 */
+				<0 RK_PB4 1 &pcfg_pull_none_smt>,
+				/* i2c3_sda_m0 */
+				<0 RK_PB5 1 &pcfg_pull_none_smt>;
+		};
+		i2c3m1_xfer_pins: i2c3m1-xfer-pins {
+			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 {
+		i2c4m0_xfer_pins: i2c4m0-xfer-pins {
+			rockchip,pins =
+				/* i2c4_scl_m0 */
+				<2 RK_PB0 4 &pcfg_pull_none_smt>,
+				/* i2c4_sda_m0 */
+				<2 RK_PB1 4 &pcfg_pull_none_smt>;
+		};
+		i2c4m1_xfer_pins: i2c4m1-xfer-pins {
+			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 {
+		jtagm0_pins: jtagm0-pins {
+			rockchip,pins =
+				/* jtag_tck_m0 */
+				<0 RK_PA5 5 &pcfg_pull_none>,
+				/* jtag_tms_m0 */
+				<0 RK_PA6 5 &pcfg_pull_none>;
+		};
+		jtagm1_pins: jtagm1-pins {
+			rockchip,pins =
+				/* jtag_tck_m1 */
+				<0 RK_PB4 3 &pcfg_pull_none>,
+				/* jtag_tms_m1 */
+				<0 RK_PB5 3 &pcfg_pull_none>;
+		};
+		jtagm2_pins: jtagm2-pins {
+			rockchip,pins =
+				/* jtag_tck_m2 */
+				<1 RK_PB4 3 &pcfg_pull_none>,
+				/* jtag_tms_m2 */
+				<1 RK_PB3 3 &pcfg_pull_none>;
+		};
+	};
+
+	pmu_debug_test {
+		pmu_debug_test_pins: pmu-debug-test-pins {
+			rockchip,pins =
+				/* pmu_debug_test_out */
+				<0 RK_PB1 5 &pcfg_pull_none>;
+		};
+	};
+
+	prelight_trig {
+		prelight_trig_pins: prelight-trig-pins {
+			rockchip,pins =
+				/* prelight_trig_out */
+				<2 RK_PB1 6 &pcfg_pull_none>;
+		};
+	};
+
+	psram_spi {
+		psram_spi_bus4_pins: psram-spi-bus4-pins {
+			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>;
+		};
+		psram_spi_clk_pins: psram-spi-clk-pins {
+			rockchip,pins =
+				/* psram_spi_clk */
+				<0 RK_PA0 4 &pcfg_pull_none>;
+		};
+		psram_spi_cs0n_pins: psram-spi-cs0n-pins {
+			rockchip,pins =
+				/* psram_spi_cs0n */
+				<0 RK_PA4 4 &pcfg_pull_none>;
+		};
+	};
+
+	pwm0 {
+		pwm0m0_ch0_pins: pwm0m0-ch0-pins {
+			rockchip,pins =
+				/* pwm0m0_ch0 */
+				<0 RK_PA1 1 &pcfg_pull_none_drv_level_0>;
+		};
+		pwm0m0_ch1_pins: pwm0m0-ch1-pins {
+			rockchip,pins =
+				/* pwm0m0_ch1 */
+				<0 RK_PA5 2 &pcfg_pull_none_drv_level_0>;
+		};
+		pwm0m0_ch2_pins: pwm0m0-ch2-pins {
+			rockchip,pins =
+				/* pwm0m0_ch2 */
+				<0 RK_PA6 2 &pcfg_pull_none_drv_level_0>;
+		};
+		pwm0m0_ch3_pins: pwm0m0-ch3-pins {
+			rockchip,pins =
+				/* pwm0m0_ch3 */
+				<0 RK_PA2 1 &pcfg_pull_none_drv_level_0>;
+		};
+		pwm0m1_ch0_pins: pwm0m1-ch0-pins {
+			rockchip,pins =
+				/* pwm0m1_ch0 */
+				<2 RK_PA0 3 &pcfg_pull_none_drv_level_0>;
+		};
+		pwm0m1_ch1_pins: pwm0m1-ch1-pins {
+			rockchip,pins =
+				/* pwm0m1_ch1 */
+				<2 RK_PA1 3 &pcfg_pull_none_drv_level_0>;
+		};
+		pwm0m1_ch2_pins: pwm0m1-ch2-pins {
+			rockchip,pins =
+				/* pwm0m1_ch2 */
+				<2 RK_PA2 3 &pcfg_pull_none_drv_level_0>;
+		};
+		pwm0m1_ch3_pins: pwm0m1-ch3-pins {
+			rockchip,pins =
+				/* pwm0m1_ch3 */
+				<2 RK_PB0 3 &pcfg_pull_none_drv_level_0>;
+		};
+		pwm0m2_ch1_pins: pwm0m2-ch1-pins {
+			rockchip,pins =
+				/* pwm0m2_ch1 */
+				<1 RK_PB7 1 &pcfg_pull_none_drv_level_0>;
+		};
+		pwm0m2_ch2_pins: pwm0m2-ch2-pins {
+			rockchip,pins =
+				/* pwm0m2_ch2 */
+				<1 RK_PC0 1 &pcfg_pull_none_drv_level_0>;
+		};
+	};
+
+	pwm1 {
+		pwm1m0_ch0_pins: pwm1m0-ch0-pins {
+			rockchip,pins =
+				/* pwm1m0_ch0 */
+				<0 RK_PB0 3 &pcfg_pull_none_drv_level_0>;
+		};
+		pwm1m0_ch1_pins: pwm1m0-ch1-pins {
+			rockchip,pins =
+				/* pwm1m0_ch1 */
+				<0 RK_PB1 3 &pcfg_pull_none_drv_level_0>;
+		};
+		pwm1m0_ch2_pins: pwm1m0-ch2-pins {
+			rockchip,pins =
+				/* pwm1m0_ch2 */
+				<0 RK_PB2 3 &pcfg_pull_none_drv_level_0>;
+		};
+		pwm1m0_ch3_pins: pwm1m0-ch3-pins {
+			rockchip,pins =
+				/* pwm1m0_ch3 */
+				<0 RK_PB3 3 &pcfg_pull_none_drv_level_0>;
+		};
+		pwm1m1_ch0_pins: pwm1m1-ch0-pins {
+			rockchip,pins =
+				/* pwm1m1_ch0 */
+				<2 RK_PA3 3 &pcfg_pull_none_drv_level_0>;
+		};
+		pwm1m1_ch1_pins: pwm1m1-ch1-pins {
+			rockchip,pins =
+				/* pwm1m1_ch1 */
+				<2 RK_PA4 3 &pcfg_pull_none_drv_level_0>;
+		};
+		pwm1m1_ch2_pins: pwm1m1-ch2-pins {
+			rockchip,pins =
+				/* pwm1m1_ch2 */
+				<2 RK_PA5 3 &pcfg_pull_none_drv_level_0>;
+		};
+		pwm1m1_ch3_pins: pwm1m1-ch3-pins {
+			rockchip,pins =
+				/* pwm1m1_ch3 */
+				<2 RK_PB1 3 &pcfg_pull_none_drv_level_0>;
+		};
+	};
+
+	pwm2 {
+		pwm2m0_ch0_pins: pwm2m0-ch0-pins {
+			rockchip,pins =
+				/* pwm2m0_ch0 */
+				<1 RK_PB0 4 &pcfg_pull_none_drv_level_0>;
+		};
+		pwm2m0_ch1_pins: pwm2m0-ch1-pins {
+			rockchip,pins =
+				/* pwm2m0_ch1 */
+				<1 RK_PA7 4 &pcfg_pull_none_drv_level_0>;
+		};
+		pwm2m0_ch2_pins: pwm2m0-ch2-pins {
+			rockchip,pins =
+				/* pwm2m0_ch2 */
+				<1 RK_PB4 4 &pcfg_pull_none_drv_level_0>;
+		};
+		pwm2m0_ch3_pins: pwm2m0-ch3-pins {
+			rockchip,pins =
+				/* pwm2m0_ch3 */
+				<1 RK_PB3 4 &pcfg_pull_none_drv_level_0>;
+		};
+		pwm2m1_ch0_pins: pwm2m1-ch0-pins {
+			rockchip,pins =
+				/* pwm2m1_ch0 */
+				<2 RK_PA6 3 &pcfg_pull_none_drv_level_0>;
+		};
+		pwm2m1_ch1_pins: pwm2m1-ch1-pins {
+			rockchip,pins =
+				/* pwm2m1_ch1 */
+				<2 RK_PA7 3 &pcfg_pull_none_drv_level_0>;
+		};
+		pwm2m1_ch2_pins: pwm2m1-ch2-pins {
+			rockchip,pins =
+				/* pwm2m1_ch2 */
+				<2 RK_PB2 3 &pcfg_pull_none_drv_level_0>;
+		};
+		pwm2m1_ch3_pins: pwm2m1-ch3-pins {
+			rockchip,pins =
+				/* pwm2m1_ch3 */
+				<2 RK_PB3 3 &pcfg_pull_none_drv_level_0>;
+		};
+	};
+
+	pwr {
+		pwr_pins: pwr-pins {
+			rockchip,pins =
+				/* pwr_ctrl0 */
+				<0 RK_PA3 1 &pcfg_pull_none>,
+				/* pwr_ctrl1 */
+				<0 RK_PA4 1 &pcfg_pull_none>;
+		};
+	};
+
+	rtc_32k {
+		rtc_32k_pins: rtc-32k-pins {
+			rockchip,pins =
+				/* rtc_32k_out */
+				<0 RK_PA0 1 &pcfg_pull_none>;
+		};
+	};
+
+	sai {
+		sai_pins: sai-pins {
+			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 {
+		sdmmc0_bus4_pins: sdmmc0-bus4-pins {
+			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>;
+		};
+		sdmmc0_clk_pins: sdmmc0-clk-pins {
+			rockchip,pins =
+				/* sdmmc0_clk */
+				<1 RK_PB1 1 &pcfg_pull_up_drv_level_2>;
+		};
+		sdmmc0_cmd_pins: sdmmc0-cmd-pins {
+			rockchip,pins =
+				/* sdmmc0_cmd */
+				<1 RK_PB2 1 &pcfg_pull_up_drv_level_2>;
+		};
+		sdmmc0_det_pins: sdmmc0-det-pins {
+			rockchip,pins =
+				/* sdmmc0_det */
+				<1 RK_PA6 1 &pcfg_pull_up>;
+		};
+	};
+
+	sdmmc1 {
+		sdmmc1_bus4_pins: sdmmc1-bus4-pins {
+			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>;
+		};
+		sdmmc1_clk_pins: sdmmc1-clk-pins {
+			rockchip,pins =
+				/* sdmmc1_clk */
+				<2 RK_PA2 1 &pcfg_pull_up_drv_level_2>;
+		};
+		sdmmc1_cmd_pins: sdmmc1-cmd-pins {
+			rockchip,pins =
+				/* sdmmc1_cmd */
+				<2 RK_PA3 1 &pcfg_pull_up_drv_level_2>;
+		};
+	};
+
+	sdmmc0_testclk {
+		sdmmc0_testclk_clk_pins: sdmmc0-testclk-clk-pins {
+			rockchip,pins =
+				/* sdmmc0_testclk_out */
+				<1 RK_PA0 3 &pcfg_pull_up_drv_level_2>;
+		};
+	};
+
+	sdmmc0_testdata {
+		sdmmc0_testdata_out_pins: sdmmc0-testdata-out-pins {
+			rockchip,pins =
+				/* sdmmc0_testdata_out */
+				<1 RK_PA3 3 &pcfg_pull_none>;
+		};
+	};
+
+	sdmmc1_testclk {
+		sdmmc1_testclk_clk_pins: sdmmc1-testclk-clk-pins {
+			rockchip,pins =
+				/* sdmmc1_testclk_out */
+				<2 RK_PA6 7 &pcfg_pull_up_drv_level_2>;
+		};
+	};
+
+	sdmmc1_testdata {
+		sdmmc1_testdata_out_pins: sdmmc1-testdata-out-pins {
+			rockchip,pins =
+				/* sdmmc1_testdata_out */
+				<2 RK_PA7 7 &pcfg_pull_none>;
+		};
+	};
+
+	spi0 {
+		spi0m0_clk_pins: spi0m0-clk-pins {
+			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>;
+		};
+		spi0m0_cs0_pins: spi0m0-cs0-pins {
+			rockchip,pins =
+				/* spi0_cs0n_m0 */
+				<2 RK_PB2 2 &pcfg_pull_none>;
+		};
+		spi0m0_cs1_pins: spi0m0-cs1-pins {
+			rockchip,pins =
+				/* spi0_cs1n_m0 */
+				<2 RK_PA7 2 &pcfg_pull_none>;
+		};
+		spi0m1_clk_pins: spi0m1-clk-pins {
+			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>;
+		};
+		spi0m1_cs0_pins: spi0m1-cs0-pins {
+			rockchip,pins =
+				/* spi0_cs0n_m1 */
+				<2 RK_PA3 5 &pcfg_pull_none>;
+		};
+		spi0m1_cs1_pins: spi0m1-cs1-pins {
+			rockchip,pins =
+				/* spi0_cs1n_m1 */
+				<2 RK_PA0 5 &pcfg_pull_none>;
+		};
+	};
+
+	uart0 {
+		uart0m0_xfer_pins: uart0m0-xfer-pins {
+			rockchip,pins =
+				/* uart0_rx_m0 */
+				<0 RK_PA6 1 &pcfg_pull_up>,
+				/* uart0_tx_m0 */
+				<0 RK_PA5 1 &pcfg_pull_up>;
+		};
+		uart0m1_xfer_pins: uart0m1-xfer-pins {
+			rockchip,pins =
+				/* uart0_rx_m1 */
+				<0 RK_PB5 2 &pcfg_pull_up>,
+				/* uart0_tx_m1 */
+				<0 RK_PB4 2 &pcfg_pull_up>;
+		};
+		uart0m2_xfer_pins: uart0m2-xfer-pins {
+			rockchip,pins =
+				/* uart0_rx_m2 */
+				<1 RK_PB3 2 &pcfg_pull_up>,
+				/* uart0_tx_m2 */
+				<1 RK_PB4 2 &pcfg_pull_up>;
+		};
+	};
+
+	uart1 {
+		uart1m0_xfer_pins: uart1m0-xfer-pins {
+			rockchip,pins =
+				/* uart1_rx_m0 */
+				<0 RK_PB2 2 &pcfg_pull_up>,
+				/* uart1_tx_m0 */
+				<0 RK_PB3 2 &pcfg_pull_up>;
+		};
+		uart1m0_ctsn_pins: uart1m0-ctsn-pins {
+			rockchip,pins =
+				/* uart1m0_ctsn */
+				<0 RK_PB5 5 &pcfg_pull_none>;
+		};
+		uart1m0_rtsn_pins: uart1m0-rtsn-pins {
+			rockchip,pins =
+				/* uart1m0_rtsn */
+				<0 RK_PB4 5 &pcfg_pull_none>;
+		};
+		uart1m1_xfer_pins: uart1m1-xfer-pins {
+			rockchip,pins =
+				/* uart1_rx_m1 */
+				<1 RK_PA7 2 &pcfg_pull_up>,
+				/* uart1_tx_m1 */
+				<1 RK_PB0 2 &pcfg_pull_up>;
+		};
+		uart1m1_ctsn_pins: uart1m1-ctsn-pins {
+			rockchip,pins =
+				/* uart1m1_ctsn */
+				<1 RK_PB2 2 &pcfg_pull_none>;
+		};
+		uart1m1_rtsn_pins: uart1m1-rtsn-pins {
+			rockchip,pins =
+				/* uart1m1_rtsn */
+				<1 RK_PB1 2 &pcfg_pull_none>;
+		};
+		uart1m2_xfer_pins: uart1m2-xfer-pins {
+			rockchip,pins =
+				/* uart1_rx_m2 */
+				<2 RK_PA7 1 &pcfg_pull_up>,
+				/* uart1_tx_m2 */
+				<2 RK_PA6 1 &pcfg_pull_up>;
+		};
+		uart1m2_ctsn_pins: uart1m2-ctsn-pins {
+			rockchip,pins =
+				/* uart1m2_ctsn */
+				<2 RK_PA5 2 &pcfg_pull_none>;
+		};
+		uart1m2_rtsn_pins: uart1m2-rtsn-pins {
+			rockchip,pins =
+				/* uart1m2_rtsn */
+				<2 RK_PA4 2 &pcfg_pull_none>;
+		};
+		uart1m3_xfer_pins: uart1m3-xfer-pins {
+			rockchip,pins =
+				/* uart1_rx_m3 */
+				<2 RK_PA3 2 &pcfg_pull_up>,
+				/* uart1_tx_m3 */
+				<2 RK_PA2 2 &pcfg_pull_up>;
+		};
+		uart1m3_ctsn_pins: uart1m3-ctsn-pins {
+			rockchip,pins =
+				/* uart1m3_ctsn */
+				<2 RK_PA1 2 &pcfg_pull_none>;
+		};
+		uart1m3_rtsn_pins: uart1m3-rtsn-pins {
+			rockchip,pins =
+				/* uart1m3_rtsn */
+				<2 RK_PA0 2 &pcfg_pull_none>;
+		};
+	};
+
+	uart2 {
+		uart2m0_xfer_pins: uart2m0-xfer-pins {
+			rockchip,pins =
+				/* uart2_rx_m0 */
+				<0 RK_PB1 2 &pcfg_pull_up>,
+				/* uart2_tx_m0 */
+				<0 RK_PB0 2 &pcfg_pull_up>;
+		};
+		uart2m0_ctsn_pins: uart2m0-ctsn-pins {
+			rockchip,pins =
+				/* uart2m0_ctsn */
+				<0 RK_PB3 5 &pcfg_pull_none>;
+		};
+		uart2m0_rtsn_pins: uart2m0-rtsn-pins {
+			rockchip,pins =
+				/* uart2m0_rtsn */
+				<0 RK_PB2 5 &pcfg_pull_none>;
+		};
+		uart2m1_xfer_pins: uart2m1-xfer-pins {
+			rockchip,pins =
+				/* uart2_rx_m1 */
+				<2 RK_PB1 1 &pcfg_pull_up>,
+				/* uart2_tx_m1 */
+				<2 RK_PB0 1 &pcfg_pull_up>;
+		};
+		uart2m1_ctsn_pins: uart2m1-ctsn-pins {
+			rockchip,pins =
+				/* uart2m1_ctsn */
+				<2 RK_PB3 1 &pcfg_pull_none>;
+		};
+		uart2m1_rtsn_pins: uart2m1-rtsn-pins {
+			rockchip,pins =
+				/* uart2m1_rtsn */
+				<2 RK_PB2 1 &pcfg_pull_none>;
+		};
+		uart2m2_xfer_pins: uart2m2-xfer-pins {
+			rockchip,pins =
+				/* uart2_rx_m2 */
+				<1 RK_PB6 3 &pcfg_pull_up>,
+				/* uart2_tx_m2 */
+				<1 RK_PB5 3 &pcfg_pull_up>;
+		};
+		uart2m2_ctsn_pins: uart2m2-ctsn-pins {
+			rockchip,pins =
+				/* uart2m2_ctsn */
+				<1 RK_PC0 3 &pcfg_pull_none>;
+		};
+		uart2m2_rtsn_pins: uart2m2-rtsn-pins {
+			rockchip,pins =
+				/* uart2m2_rtsn */
+				<1 RK_PB7 3 &pcfg_pull_none>;
+		};
+	};
+};
+
+&pinctrl {
+	sdmmc0 {
+		sdmmc0_clk_idle_pins: sdmmc0-clk-idle-pins {
+			rockchip,pins =
+				/* sdmmc0_clk */
+				<1 RK_PB1 RK_FUNC_GPIO &pcfg_pull_down>;
+		};
+		sdmmc0_cmd_idle_pins: sdmmc0-cmd-idle-pins {
+			rockchip,pins =
+				/* sdmmc0_cmd */
+				<1 RK_PB2 RK_FUNC_GPIO &pcfg_pull_down>;
+		};
+		sdmmc0_bus1_pins: sdmmc0-bus1-pins {
+			rockchip,pins =
+				/* sdmmc0_d0 */
+				<1 RK_PB0 1 &pcfg_pull_up_drv_level_2>;
+		};
+		sdmmc0_bus1_idle_pins: sdmmc0-bus1-idle-pins {
+			rockchip,pins =
+				/* sdmmc0_d0 */
+				<1 RK_PB0 RK_FUNC_GPIO &pcfg_pull_down>;
+		};
+		sdmmc0_bus4_idle_pins: sdmmc0-bus4-idle-pins {
+			rockchip,pins =
+				/* sdmmc0_d0 */
+				<1 RK_PB0 RK_FUNC_GPIO &pcfg_pull_down>,
+				/* sdmmc0_d1 */
+				<1 RK_PA7 RK_FUNC_GPIO &pcfg_pull_down>,
+				/* sdmmc0_d2 */
+				<1 RK_PB4 RK_FUNC_GPIO &pcfg_pull_down>,
+				/* sdmmc0_d3 */
+				<1 RK_PB3 RK_FUNC_GPIO &pcfg_pull_down>;
+		};
+	};
+
+	sdmmc1 {
+		sdmmc1_bus1_pins: sdmmc1-bus1-pins {
+			rockchip,pins =
+				/* sdmmc1_d0 */
+				<2 RK_PA1 1 &pcfg_pull_up_drv_level_2>;
+		};
+	};
+};
diff --git a/arch/arm/dts/rv1103b-u-boot.dtsi b/arch/arm/dts/rv1103b-u-boot.dtsi
new file mode 100644
index 000000000000..3b77dd31152f
--- /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/dts/rv1103b.dtsi b/arch/arm/dts/rv1103b.dtsi
new file mode 100644
index 000000000000..5c850aa56de7
--- /dev/null
+++ b/arch/arm/dts/rv1103b.dtsi
@@ -0,0 +1,266 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2024 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>
+
+/ {
+	#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>;
+	};
+
+	xin32k: oscillator-32k {
+		compatible = "fixed-clock";
+		clock-frequency = <32768>;
+		clock-output-names = "xin32k";
+		#clock-cells = <0>;
+	};
+
+	xin24m: oscillator-24m {
+		compatible = "fixed-clock";
+		clock-frequency = <24000000>;
+		clock-output-names = "xin24m";
+		#clock-cells = <0>;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu0: cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a7";
+			reg = <0x0>;
+			clocks = <&cru ARMCLK>;
+		};
+	};
+
+	timer {
+		compatible = "arm,armv7-timer";
+		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)>;
+		clock-frequency = <24000000>;
+	};
+
+	cru: clock-controller@20000000 {
+		compatible = "rockchip,rv1103b-cru";
+		reg = <0x20000000 0x81000>;
+		#clock-cells = <1>;
+		#reset-cells = <1>;
+		bootph-all;
+		assigned-clocks = <&cru PLL_GPLL>, <&cru CLK_GPLL_DIV12>;
+		assigned-clock-rates = <1188000000>, <100000000>;
+	};
+
+	/*
+	 * Merge all GRF, each independent GRF offset is shown as bellow:
+	 * VEPU_GRF:		0x20100000
+	 * NPU_GRF:		0x20110000
+	 * VI_GRF:		0x20120000
+	 * CPU_GRF:		0x20130000
+	 * DDR_GRF:		0x20140000
+	 * SYS_GRF:		0x20150000
+	 * PMU_GRF:		0x20160000
+	 */
+	grf: syscon@20100000 {
+		compatible = "rockchip,rv1103b-grf", "syscon", "simple-mfd";
+		reg = <0x20100000 0x61000>;
+
+		reboot_mode: reboot-mode {
+			compatible = "syscon-reboot-mode";
+			offset = <0x60200>;
+		};
+	};
+
+	ioc: syscon@20170000 {
+		compatible = "rockchip,rv1103b-ioc", "syscon";
+		reg = <0x20170000 0x60000>;
+	};
+
+	gic: interrupt-controller@20411000 {
+		compatible = "arm,gic-400";
+		interrupt-controller;
+		#interrupt-cells = <3>;
+		#address-cells = <0>;
+
+		reg = <0x20411000 0x1000>,
+		      <0x20412000 0x2000>,
+		      <0x20414000 0x2000>,
+		      <0x20416000 0x2000>;
+		interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_HIGH)>;
+	};
+
+	uart0: serial@20540000 {
+		compatible = "rockchip,rv1103b-uart", "snps,dw-apb-uart";
+		reg = <0x20540000 0x100>;
+		interrupts = <GIC_SPI 69 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";
+		pinctrl-names = "default";
+		pinctrl-0 = <&uart0m0_xfer_pins>;
+		status = "disabled";
+	};
+
+	sdmmc1: mmc@20650000 {
+		compatible = "rockchip,rv1103b-dw-mshc", "rockchip,rk3288-dw-mshc";
+		reg = <0x20650000 0x4000>;
+		interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru HCLK_SDMMC1>, <&cru CCLK_SDMMC1>;
+		clock-names = "biu", "ciu";
+		fifo-depth = <0x100>;
+		max-frequency = <150000000>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&sdmmc1_clk_pins &sdmmc1_cmd_pins &sdmmc1_bus4_pins>;
+		status = "disabled";
+	};
+
+	uart1: serial@20870000 {
+		compatible = "rockchip,rv1103b-uart", "snps,dw-apb-uart";
+		reg = <0x20870000 0x100>;
+		interrupts = <GIC_SPI 70 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";
+		pinctrl-names = "default";
+		pinctrl-0 = <&uart1m0_xfer_pins>;
+		status = "disabled";
+	};
+
+	uart2: serial@20880000 {
+		compatible = "rockchip,rv1103b-uart", "snps,dw-apb-uart";
+		reg = <0x20880000 0x100>;
+		interrupts = <GIC_SPI 71 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 = <&uart2m0_xfer_pins>;
+		status = "disabled";
+	};
+
+	wdt: watchdog@208d0000 {
+		compatible = "snps,dw-wdt";
+		reg = <0x208d0000 0x100>;
+		clocks = <&cru TCLK_WDT_NS>, <&cru PCLK_WDT_NS>;
+		clock-names = "tclk", "pclk";
+		interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
+		status = "disabled";
+	};
+
+	sdmmc0: mmc@20d20000 {
+		compatible = "rockchip,rv1103b-dw-mshc", "rockchip,rk3288-dw-mshc";
+		reg = <0x20d20000 0x4000>;
+		interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru HCLK_SDMMC0>, <&cru CCLK_SDMMC0>;
+		clock-names = "biu", "ciu";
+		fifo-depth = <0x100>;
+		max-frequency = <150000000>;
+		pinctrl-names = "normal", "idle";
+		pinctrl-0 = <&sdmmc0_det_pins
+			     &sdmmc0_clk_pins
+			     &sdmmc0_cmd_pins
+			     &sdmmc0_bus4_pins>;
+		pinctrl-1 = <&sdmmc0_det_pins
+			     &sdmmc0_clk_idle_pins
+			     &sdmmc0_cmd_idle_pins
+			     &sdmmc0_bus4_idle_pins>;
+		status = "disabled";
+	};
+
+	emmc: mmc@20d30000 {
+		compatible = "rockchip,rv1103b-dw-mshc", "rockchip,rk3288-dw-mshc";
+		reg = <0x20d30000 0x4000>;
+		interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru HCLK_EMMC>, <&cru CCLK_EMMC>;
+		clock-names = "biu", "ciu";
+		fifo-depth = <0x100>;
+		max-frequency = <150000000>;
+		status = "disabled";
+	};
+
+	fspi0: spi@20d40000 {
+		compatible = "rockchip,sfc";
+		reg = <0x20d40000 0x4000>;
+		interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru SCLK_SFC_2X>, <&cru HCLK_SFC>;
+		clock-names = "clk_sfc", "hclk_sfc";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	system_sram: sram@210f6000 {
+		compatible = "mmio-sram";
+		reg = <0x210f6000 0x8000>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0 0x210f6000 0x8000>;
+	};
+
+	pinctrl: pinctrl {
+		compatible = "rockchip,rv1103b-pinctrl";
+		rockchip,grf = <&ioc>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		gpio0: gpio@20520000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0x20520000 0x200>;
+			interrupts = <GIC_SPI 75 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@20d80000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0x20d80000 0x200>;
+			interrupts = <GIC_SPI 79 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@20840000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0x20840000 0x200>;
+			interrupts = <GIC_SPI 83 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>;
+		};
+	};
+};
+
+#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 000000000000..35afdee7e961
--- /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.34.1


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

* [PATCH v2 2/7] pinctrl: rockchip: Add RV1103B support
  2026-02-08 21:26 [PATCH v2 0/7] ARM: Add RV1103B Omega4 board support Fabio Estevam
  2026-02-08 21:26 ` [PATCH v2 1/7] ARM: dts: Add RV1103B Omega4 support Fabio Estevam
@ 2026-02-08 21:26 ` Fabio Estevam
  2026-02-09 10:50   ` Jonas Karlman
  2026-02-08 21:26 ` [PATCH v2 3/7] clk: rockchip: Add RV1103B clock driver Fabio Estevam
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 12+ messages in thread
From: Fabio Estevam @ 2026-02-08 21:26 UTC (permalink / raw)
  To: kever.yang; +Cc: trini, jonas, u-boot, Ye Zhang, Fabio Estevam

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

Add pinctrl driver for RV1103.

Signed-off-by: Ye Zhang <ye.zhang@rock-chips.com>
Signed-off-by: Fabio Estevam <festevam@nabladev.com>
---
Changes since v1:
- Use the original author from Rockchip's vendor U-Boot tree.
- Use regmap_update_bits()
- Removed unneeded blank lines.
- Removed unneeded logging functions.

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

diff --git a/drivers/pinctrl/rockchip/Makefile b/drivers/pinctrl/rockchip/Makefile
index e17415e1ca68..2bbee66bd3ca 100644
--- a/drivers/pinctrl/rockchip/Makefile
+++ b/drivers/pinctrl/rockchip/Makefile
@@ -18,5 +18,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 000000000000..fb946b036661
--- /dev/null
+++ b/drivers/pinctrl/rockchip/pinctrl-rv1103b.c
@@ -0,0 +1,398 @@
+// 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;
+	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);
+	data |= (ret << bit);
+	return regmap_write(regmap, reg, 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;
+
+	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);
+
+	data |= (ret << bit);
+	ret = regmap_write(regmap, reg, data);
+
+	return ret;
+}
+
+#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;
+	u8 bit;
+
+	ret = rv1103b_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 << RV1103_SMT_BITS_PER_PIN) - 1) << (bit + 16);
+	data |= (enable << bit);
+
+	if (bank->bank_num == 2 && pin_num >= 12) {
+		data = 0x3 << (bit + 16);
+		data |= ((enable ? 0x3 : 0) << bit);
+	}
+	return regmap_write(regmap, reg, 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.34.1


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

* [PATCH v2 3/7] clk: rockchip: Add RV1103B clock driver
  2026-02-08 21:26 [PATCH v2 0/7] ARM: Add RV1103B Omega4 board support Fabio Estevam
  2026-02-08 21:26 ` [PATCH v2 1/7] ARM: dts: Add RV1103B Omega4 support Fabio Estevam
  2026-02-08 21:26 ` [PATCH v2 2/7] pinctrl: rockchip: Add RV1103B support Fabio Estevam
@ 2026-02-08 21:26 ` Fabio Estevam
  2026-02-08 21:26 ` [PATCH v2 4/7] tools: rkcommon: Add RV1103B support Fabio Estevam
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 12+ messages in thread
From: Fabio Estevam @ 2026-02-08 21:26 UTC (permalink / raw)
  To: kever.yang; +Cc: trini, jonas, u-boot, Elaine Zhang, Fabio Estevam

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

Add basic clock for the RV1103B clock driver.

Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com>
Signed-off-by: Fabio Estevam <festevam@nabladev.com>
---
Changes since v1:
- 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 000000000000..fc7aa4dfc0db
--- /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 000000000000..6bb382a8e079
--- /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 34b63d4df34a..7bb0df6748cc 100644
--- a/drivers/clk/rockchip/Makefile
+++ b/drivers/clk/rockchip/Makefile
@@ -19,5 +19,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 000000000000..81d892bf43c6
--- /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 (IS_ENABLED(OF_CONTROL)) || (!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.34.1


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

* [PATCH v2 4/7] tools: rkcommon: Add RV1103B support
  2026-02-08 21:26 [PATCH v2 0/7] ARM: Add RV1103B Omega4 board support Fabio Estevam
                   ` (2 preceding siblings ...)
  2026-02-08 21:26 ` [PATCH v2 3/7] clk: rockchip: Add RV1103B clock driver Fabio Estevam
@ 2026-02-08 21:26 ` Fabio Estevam
  2026-02-08 21:26 ` [PATCH v2 5/7] rockchip: spl-boot-order: Add SPI NAND support Fabio Estevam
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 12+ messages in thread
From: Fabio Estevam @ 2026-02-08 21:26 UTC (permalink / raw)
  To: kever.yang; +Cc: trini, jonas, u-boot, Xuhui Lin, Fabio Estevam

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>
---
Changes since v1:
- Use the original author from Rockchip's vendor U-Boot tre

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

diff --git a/tools/rkcommon.c b/tools/rkcommon.c
index e7e78ef7e5b7..15aaf8f890aa 100644
--- a/tools/rkcommon.c
+++ b/tools/rkcommon.c
@@ -148,6 +148,7 @@ static struct spl_info spl_infos[] = {
 	{ "rk3328", "RK32", 0x8000 - 0x800, false, RK_HEADER_V1 },
 	{ "rk3368", "RK33", 0x8000 - 0x1000, false, RK_HEADER_V1 },
 	{ "rk3399", "RK33", 0x30000 - 0x2000, false, RK_HEADER_V1 },
+	{ "rv1103b", "110E", 0x40000 - 0x1000, false, RK_HEADER_V2 },
 	{ "rv1108", "RK11", 0x1800, false, RK_HEADER_V1 },
 	{ "rv1126", "110B", 0x10000 - 0x1000, false, RK_HEADER_V1 },
 	{ "rk3528", "RK35", 0x10000 - 0x1000, false, RK_HEADER_V2 },
-- 
2.34.1


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

* [PATCH v2 5/7] rockchip: spl-boot-order: Add SPI NAND support
  2026-02-08 21:26 [PATCH v2 0/7] ARM: Add RV1103B Omega4 board support Fabio Estevam
                   ` (3 preceding siblings ...)
  2026-02-08 21:26 ` [PATCH v2 4/7] tools: rkcommon: Add RV1103B support Fabio Estevam
@ 2026-02-08 21:26 ` Fabio Estevam
  2026-02-09  9:56   ` Jonas Karlman
  2026-02-08 21:26 ` [PATCH v2 6/7] spl: add SPI NAND support via MTD in SPL Fabio Estevam
  2026-02-08 21:26 ` [PATCH v2 7/7] omega4-rv1103b: Add the initial support Fabio Estevam
  6 siblings, 1 reply; 12+ messages in thread
From: Fabio Estevam @ 2026-02-08 21:26 UTC (permalink / raw)
  To: kever.yang; +Cc: trini, jonas, u-boot, Fabio Estevam

From: Fabio Estevam <festevam@nabladev.com>

Make spl-boot-order to accept boot 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>
---
Changes since v1:
- None.

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

diff --git a/arch/arm/mach-rockchip/spl-boot-order.c b/arch/arm/mach-rockchip/spl-boot-order.c
index 6572dde29f65..e5897536934a 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,8 @@ 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 (fdt_node_check_compatible(gd->fdt_blob, node, "spi-nand") == 0)
+		return BOOT_DEVICE_SPI;
 
 	return -1;
 }
@@ -221,8 +224,12 @@ 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) {
-				debug("%s: could not find udevice for %s\n", __func__, conf);
-				continue;
+				ret = uclass_find_device_by_of_offset(UCLASS_MTD, node, &dev);
+				if (ret || !device_is_compatible(dev, "spi-nand")) {
+					debug("%s: could not find udevice for %s\n",
+					      __func__, conf);
+					continue;
+				}
 			}
 
 			return ofnode_get_path(dev_ofnode(dev), buf, buflen);
-- 
2.34.1


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

* [PATCH v2 6/7] spl: add SPI NAND support via MTD in SPL
  2026-02-08 21:26 [PATCH v2 0/7] ARM: Add RV1103B Omega4 board support Fabio Estevam
                   ` (4 preceding siblings ...)
  2026-02-08 21:26 ` [PATCH v2 5/7] rockchip: spl-boot-order: Add SPI NAND support Fabio Estevam
@ 2026-02-08 21:26 ` Fabio Estevam
  2026-02-08 23:47   ` Jonas Karlman
  2026-02-08 21:26 ` [PATCH v2 7/7] omega4-rv1103b: Add the initial support Fabio Estevam
  6 siblings, 1 reply; 12+ messages in thread
From: Fabio Estevam @ 2026-02-08 21:26 UTC (permalink / raw)
  To: kever.yang; +Cc: trini, jonas, u-boot, Fabio Estevam

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 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
  CONFIG_SPL_SPI_NAND_LOAD is enabled, avoiding size impact
  on other boards.

This allows boards like the Omega4 RV1103 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>
---
Changes since v1:
- None.

 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 2998b7acb75f..126855b804ce 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 4c9482bd3096..4628902e7e31 100644
--- a/common/spl/Makefile
+++ b/common/spl/Makefile
@@ -35,6 +35,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
 endif
diff --git a/common/spl/spl_spi_nand.c b/common/spl/spl_spi_nand.c
new file mode 100644
index 000000000000..20b877f75a05
--- /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 ce05e206073d..a12d880a9e90 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 c8169cf73902..7cd2a5f1af9b 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.34.1


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

* [PATCH v2 7/7] omega4-rv1103b: Add the initial support
  2026-02-08 21:26 [PATCH v2 0/7] ARM: Add RV1103B Omega4 board support Fabio Estevam
                   ` (5 preceding siblings ...)
  2026-02-08 21:26 ` [PATCH v2 6/7] spl: add SPI NAND support via MTD in SPL Fabio Estevam
@ 2026-02-08 21:26 ` Fabio Estevam
  6 siblings, 0 replies; 12+ messages in thread
From: Fabio Estevam @ 2026-02-08 21:26 UTC (permalink / raw)
  To: kever.yang; +Cc: trini, jonas, u-boot, Fabio Estevam

From: Fabio Estevam <festevam@nabladev.com>

Add the initial support for Onion's Omega4 RV1103B board.

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>
---
Changes since v1:
- Only adapted to the correct SoC name: RV1103B instead of RV1103.

 arch/arm/include/asm/arch-rv1103b/boot0.h     |  11 ++
 arch/arm/mach-rockchip/Kconfig                |  14 ++
 arch/arm/mach-rockchip/Makefile               |   1 +
 arch/arm/mach-rockchip/rv1103b/Kconfig        |  23 +++
 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 +++
 board/onion/omega4_rv1103b/Kconfig            |  12 ++
 board/onion/omega4_rv1103b/MAINTAINERS        |   6 +
 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 ++++++++
 include/configs/omega4_rv1103b.h              |  11 ++
 include/configs/rv1103b_common.h              |  14 ++
 20 files changed, 472 insertions(+)
 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 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
 create mode 100644 include/configs/rv1103b_common.h

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 000000000000..2e78b074ade8
--- /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 92bb4aa62f11..c1faeb974328 100644
--- a/arch/arm/mach-rockchip/Kconfig
+++ b/arch/arm/mach-rockchip/Kconfig
@@ -487,6 +487,19 @@ 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
@@ -749,6 +762,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 06fb527b21a0..7bbb1697836c 100644
--- a/arch/arm/mach-rockchip/Makefile
+++ b/arch/arm/mach-rockchip/Makefile
@@ -46,6 +46,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 000000000000..6b5f5b0b9e14
--- /dev/null
+++ b/arch/arm/mach-rockchip/rv1103b/Kconfig
@@ -0,0 +1,23 @@
+if ROCKCHIP_RV1103B
+
+
+config TARGET_OMEGA4_RV1103B
+	bool "OMEGA4_RV1103B"
+	help
+	  Support Onion's Omega4 RV1103B board.
+
+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
+
+source "board/onion/omega4_rv1103b/Kconfig"
+
+endif
diff --git a/arch/arm/mach-rockchip/rv1103b/Makefile b/arch/arm/mach-rockchip/rv1103b/Makefile
new file mode 100644
index 000000000000..2f34853adac5
--- /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 000000000000..466ab0e80770
--- /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 000000000000..2bcbb08537e8
--- /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 000000000000..a7ff1934f7db
--- /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 000000000000..545b4d8ebe12
--- /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-grf", .data = ROCKCHIP_SYSCON_GRF },
+	{ }
+};
+
+U_BOOT_DRIVER(syscon_rv1103b) = {
+	.name = "rv1103b_syscon",
+	.id = UCLASS_SYSCON,
+	.of_match = rv1103b_syscon_ids,
+};
diff --git a/board/onion/omega4_rv1103b/Kconfig b/board/onion/omega4_rv1103b/Kconfig
new file mode 100644
index 000000000000..43b126c20e9c
--- /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 000000000000..53d774535bdd
--- /dev/null
+++ b/board/onion/omega4_rv1103b/MAINTAINERS
@@ -0,0 +1,6 @@
+OMEGA4 RV1103B
+M:      Fabio Estevam <festevam@nabladev.com>
+S:      Maintained
+F:      board/onion/omega4_rv1103b
+F:      include/configs/omega4_rv1103b.h
+F:      configs/omega4-rv1103b_defconfig
diff --git a/board/onion/omega4_rv1103b/Makefile b/board/onion/omega4_rv1103b/Makefile
new file mode 100644
index 000000000000..afa0a7f7a932
--- /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 000000000000..9bdec3c396a8
--- /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 000000000000..7ed232cab916
--- /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 000000000000..b1e8ede1cf6e
--- /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"
+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 7870f1bc2461..d859f8a22bfe 100644
--- a/doc/board/index.rst
+++ b/doc/board/index.rst
@@ -45,6 +45,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 000000000000..2e106c8b7734
--- /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 000000000000..41c64f40d6c4
--- /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/include/configs/omega4_rv1103b.h b/include/configs/omega4_rv1103b.h
new file mode 100644
index 000000000000..8430b0b4d091
--- /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
diff --git a/include/configs/rv1103b_common.h b/include/configs/rv1103b_common.h
new file mode 100644
index 000000000000..8e970d710514
--- /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.34.1


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

* Re: [PATCH v2 6/7] spl: add SPI NAND support via MTD in SPL
  2026-02-08 21:26 ` [PATCH v2 6/7] spl: add SPI NAND support via MTD in SPL Fabio Estevam
@ 2026-02-08 23:47   ` Jonas Karlman
  0 siblings, 0 replies; 12+ messages in thread
From: Jonas Karlman @ 2026-02-08 23:47 UTC (permalink / raw)
  To: Fabio Estevam; +Cc: kever.yang, trini, u-boot, Fabio Estevam

Hi Fabio,

On 2/8/2026 10:26 PM, Fabio Estevam wrote:
> 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 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
>   CONFIG_SPL_SPI_NAND_LOAD is enabled, avoiding size impact
>   on other boards.
> 
> This allows boards like the Omega4 RV1103 to boot SPL directly
> from SPI NAND, keeping the SPL small and avoiding unnecessary
> inclusion of SPI NOR code.

The content in this patch seem very generic and could possible be sent
as a separate series that adds a generic SPL MTD loader.

There also seem to be another SPL NAND loader part of the series at [1]
that may be related.

[1] https://lore.kernel.org/all/20260129050446.8858-1-dinesh.maniyam@altera.com/

> 
> Signed-off-by: Fabio Estevam <festevam@nabladev.com>
> ---
> Changes since v1:
> - None.
> 
>  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 2998b7acb75f..126855b804ce 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 4c9482bd3096..4628902e7e31 100644
> --- a/common/spl/Makefile
> +++ b/common/spl/Makefile
> @@ -35,6 +35,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
>  endif
> diff --git a/common/spl/spl_spi_nand.c b/common/spl/spl_spi_nand.c
> new file mode 100644
> index 000000000000..20b877f75a05
> --- /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);

Is there a reason why you limit this to only spi-nand?

I think it would be better to pivot this into a more generic SPL MTD
loader.

> +	}
> +
> +	return NULL;
> +}
> +
> +static ulong spl_spinand_fit_read(struct spl_load_info *load, ulong offs,
> +				  ulong size, void *buf)

The _fit_ part can probably be dropped.

> +{
> +	struct mtd_info *mtd = load->priv;
> +	size_t retlen = 0;
> +	int ret;
> +
> +	ret = mtd_read(mtd, offs, size, &retlen, buf);
> +	if (ret && ret != -EUCLEAN) {

Maybe use mtd_is_bitflip(ret)

> +		printf("SPI NAND read failed offs=0x%lx size=0x%lx ret=%d\n",
> +		       offs, size, ret);
> +		return 0;
> +	}
> +	if (retlen != size)

Why do we need an error message above and not here?

> +		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);

Should probably use mtd->writesize as bl_len.

	spl_load_init(&load, spl_mtd_read, mtd, mtd->writesize);

> +
> +	return spl_load(spl_image, bootdev, &load, 0, CONFIG_SYS_SPI_U_BOOT_OFFS);

Suggest you could use something like following to closer match SPL flash.

	offset = CONFIG_SYS_SPI_U_BOOT_OFFS;
	if (CONFIG_IS_ENABLED(OF_REAL))
		offset = ofnode_conf_read_int("u-boot,spl-payload-offset",
					      offset);

	return spl_load(spl_image, bootdev, &load, 0, offset);

> +}
> +
> +/* 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 ce05e206073d..a12d880a9e90 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 c8169cf73902..7cd2a5f1af9b 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),)

Having both XPL and TPL is redundant and could be cleaned up to just
have ($(CONFIG_XPL_BUILD),).

Regards,
Jonas

> +
> +# 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


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

* Re: [PATCH v2 5/7] rockchip: spl-boot-order: Add SPI NAND support
  2026-02-08 21:26 ` [PATCH v2 5/7] rockchip: spl-boot-order: Add SPI NAND support Fabio Estevam
@ 2026-02-09  9:56   ` Jonas Karlman
  0 siblings, 0 replies; 12+ messages in thread
From: Jonas Karlman @ 2026-02-09  9:56 UTC (permalink / raw)
  To: Fabio Estevam
  Cc: kever.yang@rock-chips.com, trini@konsulko.com,
	u-boot@lists.denx.de, Fabio Estevam

Hi Fabio,

On 2/8/2026 10:26 PM, Fabio Estevam wrote:
> From: Fabio Estevam <festevam@nabladev.com>
> 
> Make spl-boot-order to accept boot 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;

You should probably include something like following (after DT has been
updated as per DT review) in rv1103b.c to also allow "same-as-spl" to
work.

const char * const boot_devices[BROM_LAST_BOOTSOURCE + 1] = {
	[BROM_BOOTSOURCE_EMMC] = "/soc/mmc@20d30000",
	[BROM_BOOTSOURCE_SPINOR] = "/soc/spi@20d40000/flash@0",
	[BROM_BOOTSOURCE_SD] = "/soc/mmc@20d20000",
};

> Signed-off-by: Fabio Estevam <festevam@nabladev.com>
> ---
> Changes since v1:
> - None.
> 
>  arch/arm/mach-rockchip/spl-boot-order.c | 11 +++++++++--
>  1 file changed, 9 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm/mach-rockchip/spl-boot-order.c b/arch/arm/mach-rockchip/spl-boot-order.c
> index 6572dde29f65..e5897536934a 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,8 @@ 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 (fdt_node_check_compatible(gd->fdt_blob, node, "spi-nand") == 0)
> +		return BOOT_DEVICE_SPI;

I think something like following will be better:

	if (!uclass_find_device_by_of_offset(UCLASS_MTD, node, &parent))
		return BOOT_DEVICE_MTD;

And possible also with a protect check (should probably be fixed for
MMC/SPI_FLASH in a separate future patch/series).

	if (CONFIG_IS_ENABLED(MTD_LOAD_SUPPORT) &&
	    !uclass_find_device_by_of_offset(UCLASS_MTD, node, &parent))
		return BOOT_DEVICE_MTD;

Or whatever Kconfig option is used to ensure both UCLASS and SPL loader
is supported in the build. To avoid error messages about missing UCLASS
like following (from a different rk soc/board):

  board_spl_was_booted_from: brom_bootdevice_id 3 maps to '/soc/spi@ffac0000/flash@0'
  Cannot find uclass for id 119: please add the UCLASS_DRIVER() declaration for this UCLASS_... id
  board_boot_order: could not map node /soc/spi@ffac0000/flash@0 to a boot-device
  Cannot find uclass for id 119: please add the UCLASS_DRIVER() declaration for this UCLASS_... id

>  
>  	return -1;
>  }
> @@ -221,8 +224,12 @@ 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) {
> -				debug("%s: could not find udevice for %s\n", __func__, conf);
> -				continue;
> +				ret = uclass_find_device_by_of_offset(UCLASS_MTD, node, &dev);
> +				if (ret || !device_is_compatible(dev, "spi-nand")) {

I do not think we need to check for spi-nand compatible here, make it
generic and only check for UCLASS_MTD. If the node binds to a UCLASS_MTD
driver it is likely we could use a generic SPL MTD loader that used mtd
read ops to load next stage.

With that we could possible also support SPI_FLASH_MTD and consolidate
and/or simplify SPL code, something that can be looked at in future once
we have a more generic SPL MTD loader in place.

Regards,
Jonas

> +					debug("%s: could not find udevice for %s\n",
> +					      __func__, conf);
> +					continue;
> +				}
>  			}
>  
>  			return ofnode_get_path(dev_ofnode(dev), buf, buflen);


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

* Re: [PATCH v2 1/7] ARM: dts: Add RV1103B Omega4 support
  2026-02-08 21:26 ` [PATCH v2 1/7] ARM: dts: Add RV1103B Omega4 support Fabio Estevam
@ 2026-02-09 10:45   ` Jonas Karlman
  0 siblings, 0 replies; 12+ messages in thread
From: Jonas Karlman @ 2026-02-09 10:45 UTC (permalink / raw)
  To: Fabio Estevam; +Cc: kever.yang, trini, u-boot, Fabio Estevam

Hi Fabio,

On 2/8/2026 10:26 PM, Fabio Estevam wrote:
> From: Fabio Estevam <festevam@nabladev.com>
> 
> Add the necessary devicetrees to support the RV1103B Omega4 board.
> 
> The RV1103B is a Rockchip SoC that is still not supported in Linux
> mainline.
> 
> The initial RV1103B support has already been submitted to Linux kernel
> and it is under review.
> 
> Once the Linux RV1103 devicetrees are upstreamed, the OF_UPSTREAM mechanism
> can be enabled.

Please address my upstream DT review and give it some more time before
adding DTs that cannot be picked to dts/upstream in U-Boot.

For the past two years the Rockchip platform has only allowed adding
arch and boards using DTs that come from dts/upstream. So please give a
good explanation why your arch/board cannot wait until that is the case
and need exception from this.

> Signed-off-by: Fabio Estevam <festevam@nabladev.com>
> ---
> Changes since v1:
> - Used the devicetrees submitted to upstream Linux.
> 
>  arch/arm/dts/rv1103b-omega4-u-boot.dtsi       |  10 +
>  arch/arm/dts/rv1103b-omega4.dts               | 105 +++
>  arch/arm/dts/rv1103b-pinctrl.dtsi             | 831 ++++++++++++++++++
>  arch/arm/dts/rv1103b-u-boot.dtsi              |   4 +
>  arch/arm/dts/rv1103b.dtsi                     | 266 ++++++
>  .../dt-bindings/clock/rockchip,rv1103b-cru.h  | 220 +++++
>  6 files changed, 1436 insertions(+)
>  create mode 100644 arch/arm/dts/rv1103b-omega4-u-boot.dtsi
>  create mode 100644 arch/arm/dts/rv1103b-omega4.dts

Please split patch 7/7 in two, one that add rv1103b arch support and a
second that add the omega4 board. Then please move the board DTs to the
patch that adds support for the omega4 board.

>  create mode 100644 arch/arm/dts/rv1103b-pinctrl.dtsi
>  create mode 100644 arch/arm/dts/rv1103b-u-boot.dtsi

The soc u-boot.dtsi is better to add in the patch that add rv1103b arch
support, i.e. this patch should only include DTs and headers that is a
drop in replacement for future files that are expected to land in
dts/upstream.

Regards,
Jonas

>  create mode 100644 arch/arm/dts/rv1103b.dtsi
>  create mode 100644 include/dt-bindings/clock/rockchip,rv1103b-cru.h

[snip]

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

* Re: [PATCH v2 2/7] pinctrl: rockchip: Add RV1103B support
  2026-02-08 21:26 ` [PATCH v2 2/7] pinctrl: rockchip: Add RV1103B support Fabio Estevam
@ 2026-02-09 10:50   ` Jonas Karlman
  0 siblings, 0 replies; 12+ messages in thread
From: Jonas Karlman @ 2026-02-09 10:50 UTC (permalink / raw)
  To: Fabio Estevam; +Cc: kever.yang, trini, u-boot, Ye Zhang, Fabio Estevam

Hi Fabio,

On 2/8/2026 10:26 PM, Fabio Estevam wrote:
> From: Ye Zhang <ye.zhang@rock-chips.com>
> 
> Add pinctrl driver for RV1103.
> 
> Signed-off-by: Ye Zhang <ye.zhang@rock-chips.com>
> Signed-off-by: Fabio Estevam <festevam@nabladev.com>
> ---
> Changes since v1:
> - Use the original author from Rockchip's vendor U-Boot tree.
> - Use regmap_update_bits()
> - Removed unneeded blank lines.
> - Removed unneeded logging functions.
> 
>  drivers/pinctrl/rockchip/Makefile          |   1 +
>  drivers/pinctrl/rockchip/pinctrl-rv1103b.c | 398 +++++++++++++++++++++
>  2 files changed, 399 insertions(+)
>  create mode 100644 drivers/pinctrl/rockchip/pinctrl-rv1103b.c
> 
> diff --git a/drivers/pinctrl/rockchip/Makefile b/drivers/pinctrl/rockchip/Makefile
> index e17415e1ca68..2bbee66bd3ca 100644
> --- a/drivers/pinctrl/rockchip/Makefile
> +++ b/drivers/pinctrl/rockchip/Makefile
> @@ -18,5 +18,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 000000000000..fb946b036661
> --- /dev/null
> +++ b/drivers/pinctrl/rockchip/pinctrl-rv1103b.c
> @@ -0,0 +1,398 @@
> +// 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);

This seem to have been updated to use regmap_update_bits(), thanks.

> +}
> +
> +#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;
> +	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);
> +	data |= (ret << bit);
> +	return regmap_write(regmap, reg, data);

However, this and all remaining places still use regmap_write, please
change all instances of regmap_write to use regmap_update_bits.

This ensure the pins configuration in DT cannot overflow the fields,
that is something that has happened in the past and is why I ensure all
new rk pinctrl drivers matches Linux kernel and use regmap_update_bits
instead of regmap_write.

Regards,
Jonas

> +}

[snip]

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

end of thread, other threads:[~2026-02-09 10:50 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-02-08 21:26 [PATCH v2 0/7] ARM: Add RV1103B Omega4 board support Fabio Estevam
2026-02-08 21:26 ` [PATCH v2 1/7] ARM: dts: Add RV1103B Omega4 support Fabio Estevam
2026-02-09 10:45   ` Jonas Karlman
2026-02-08 21:26 ` [PATCH v2 2/7] pinctrl: rockchip: Add RV1103B support Fabio Estevam
2026-02-09 10:50   ` Jonas Karlman
2026-02-08 21:26 ` [PATCH v2 3/7] clk: rockchip: Add RV1103B clock driver Fabio Estevam
2026-02-08 21:26 ` [PATCH v2 4/7] tools: rkcommon: Add RV1103B support Fabio Estevam
2026-02-08 21:26 ` [PATCH v2 5/7] rockchip: spl-boot-order: Add SPI NAND support Fabio Estevam
2026-02-09  9:56   ` Jonas Karlman
2026-02-08 21:26 ` [PATCH v2 6/7] spl: add SPI NAND support via MTD in SPL Fabio Estevam
2026-02-08 23:47   ` Jonas Karlman
2026-02-08 21:26 ` [PATCH v2 7/7] omega4-rv1103b: Add the initial support Fabio Estevam

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