public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
* [PATCH v2 00/16] Add board support for Spacemit K1 SoC in SPL
@ 2026-02-10 15:14 Raymond Mao
  2026-02-10 15:14 ` [PATCH v2 01/16] spacemit: k1: support multi-board infrastructure Raymond Mao
                   ` (17 more replies)
  0 siblings, 18 replies; 24+ messages in thread
From: Raymond Mao @ 2026-02-10 15:14 UTC (permalink / raw)
  To: u-boot
  Cc: uboot, u-boot-spacemit, raymond.mao, rick, ycliang, trini, lukma,
	hs, jh80.chung, peng.fan, xypron.glpk, randolph, dlan, junhui.liu,
	neil.armstrong, quentin.schulz, samuel, raymondmaoca

From: Raymond Mao <raymond.mao@riscstar.com>

This patch series introduces full support for the k1 SoC in SPL for
multiple boards.

The series enables the board by:
1. Adding the base board definition with device tree.
2. Bringing up essential clock sources and tree.
3. Initializing I2C buses for peripheral communication.
4. Integrating the PMIC driver for power management.
5. Adding regulator drivers for voltage domain control.

Change in v2:
  - Use read_poll_timeout() in k1 i2c driver.
  - Abandon to parse offset and size from Kconfig & Makefile for binman.
  - Abandon to attach firmware image into the patch set.
  - Update the related document and some minor changes.

Junhui Liu (1):
  clk: spacemit: Add support for K1 SoC

Raymond Mao (15):
  spacemit: k1: support multi-board infrastructure
  spacemit: k1: enable SPL with debug UART
  configs: k1: enable early timer support
  reset: k1: add SPL support and enable TWSI8 reset
  dt-bindings: clock: import k1-syscon from upstream
  dts: k1: import dts file from upstream folder
  dts: k1: enable clocks in SPL
  board: k1: initialize clock and serial devices in SPL
  configs: k1: add default option for clock driver in SPL
  i2c: k1: add I2C driver support
  spacemit: k1: add TLV EEPROM support in SPL
  spacemit: k1: Add DDR firmware support to SPL
  power: pmic: add support for Spacemit P1 PMIC
  power: regulator: add support for Spacemit P1 SoC
  board: k1: enable pmic in spl

 arch/riscv/Kconfig                            |   10 +-
 arch/riscv/cpu/k1/Kconfig                     |    6 +
 arch/riscv/dts/Makefile                       |    1 +
 arch/riscv/dts/k1-spl.dts                     |  228 +++
 arch/riscv/dts/k1.dtsi                        |  666 +++++-
 board/spacemit/bananapi-f3/MAINTAINERS        |    6 -
 board/spacemit/bananapi-f3/Makefile           |    5 -
 board/spacemit/{bananapi-f3 => k1}/Kconfig    |   11 +-
 board/spacemit/k1/MAINTAINERS                 |   11 +
 board/spacemit/k1/Makefile                    |   27 +
 board/spacemit/{bananapi-f3 => k1}/board.c    |    0
 board/spacemit/k1/spl.c                       |  347 ++++
 board/spacemit/k1/tlv_codes.h                 |   22 +
 configs/bananapi-f3_defconfig                 |   24 -
 configs/spacemit_k1_defconfig                 |   76 +
 doc/board/spacemit/bananapi-f3.rst            |    2 +-
 drivers/clk/Kconfig                           |    5 +-
 drivers/clk/Makefile                          |    1 +
 drivers/clk/spacemit/Kconfig                  |   31 +
 drivers/clk/spacemit/Makefile                 |    7 +
 drivers/clk/spacemit/clk-k1.c                 | 1795 +++++++++++++++++
 drivers/clk/spacemit/clk_common.h             |   79 +
 drivers/clk/spacemit/clk_ddn.c                |   93 +
 drivers/clk/spacemit/clk_ddn.h                |   53 +
 drivers/clk/spacemit/clk_mix.c                |  403 ++++
 drivers/clk/spacemit/clk_mix.h                |  224 ++
 drivers/clk/spacemit/clk_pll.c                |  157 ++
 drivers/clk/spacemit/clk_pll.h                |   81 +
 drivers/i2c/Kconfig                           |    7 +
 drivers/i2c/Makefile                          |    1 +
 drivers/i2c/k1_i2c.c                          |  516 +++++
 drivers/i2c/k1_i2c.h                          |   69 +
 drivers/power/pmic/Kconfig                    |   17 +
 drivers/power/pmic/Makefile                   |    1 +
 drivers/power/pmic/pmic_spacemit_p1.c         |   94 +
 drivers/power/regulator/Kconfig               |   15 +
 drivers/power/regulator/Makefile              |    1 +
 .../power/regulator/spacemit_p1_regulator.c   |  460 +++++
 drivers/reset/Kconfig                         |    7 +
 drivers/reset/Makefile                        |    2 +-
 drivers/reset/reset-spacemit-k1.c             |    4 -
 include/configs/bananapi-f3.h                 |   13 -
 include/configs/k1.h                          |   19 +
 .../dt-bindings/clock/spacemit,k1-syscon.h    |  253 +++
 include/power/spacemit_p1.h                   |  163 ++
 include/soc/spacemit/k1-syscon.h              |  149 ++
 46 files changed, 5997 insertions(+), 165 deletions(-)
 create mode 100644 arch/riscv/dts/k1-spl.dts
 delete mode 100644 board/spacemit/bananapi-f3/MAINTAINERS
 delete mode 100644 board/spacemit/bananapi-f3/Makefile
 rename board/spacemit/{bananapi-f3 => k1}/Kconfig (63%)
 create mode 100644 board/spacemit/k1/MAINTAINERS
 create mode 100644 board/spacemit/k1/Makefile
 rename board/spacemit/{bananapi-f3 => k1}/board.c (100%)
 create mode 100644 board/spacemit/k1/spl.c
 create mode 100644 board/spacemit/k1/tlv_codes.h
 delete mode 100644 configs/bananapi-f3_defconfig
 create mode 100644 configs/spacemit_k1_defconfig
 create mode 100644 drivers/clk/spacemit/Kconfig
 create mode 100644 drivers/clk/spacemit/Makefile
 create mode 100644 drivers/clk/spacemit/clk-k1.c
 create mode 100644 drivers/clk/spacemit/clk_common.h
 create mode 100644 drivers/clk/spacemit/clk_ddn.c
 create mode 100644 drivers/clk/spacemit/clk_ddn.h
 create mode 100644 drivers/clk/spacemit/clk_mix.c
 create mode 100644 drivers/clk/spacemit/clk_mix.h
 create mode 100644 drivers/clk/spacemit/clk_pll.c
 create mode 100644 drivers/clk/spacemit/clk_pll.h
 create mode 100644 drivers/i2c/k1_i2c.c
 create mode 100644 drivers/i2c/k1_i2c.h
 create mode 100644 drivers/power/pmic/pmic_spacemit_p1.c
 create mode 100644 drivers/power/regulator/spacemit_p1_regulator.c
 delete mode 100644 include/configs/bananapi-f3.h
 create mode 100644 include/configs/k1.h
 create mode 100644 include/dt-bindings/clock/spacemit,k1-syscon.h
 create mode 100644 include/power/spacemit_p1.h
 create mode 100644 include/soc/spacemit/k1-syscon.h

-- 
2.25.1


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

* [PATCH v2 01/16] spacemit: k1: support multi-board infrastructure
  2026-02-10 15:14 [PATCH v2 00/16] Add board support for Spacemit K1 SoC in SPL Raymond Mao
@ 2026-02-10 15:14 ` Raymond Mao
  2026-03-19  6:44   ` Leo Liang
  2026-02-10 15:14 ` [PATCH v2 02/16] spacemit: k1: enable SPL with debug UART Raymond Mao
                   ` (16 subsequent siblings)
  17 siblings, 1 reply; 24+ messages in thread
From: Raymond Mao @ 2026-02-10 15:14 UTC (permalink / raw)
  To: u-boot
  Cc: uboot, u-boot-spacemit, raymond.mao, rick, ycliang, trini, lukma,
	hs, jh80.chung, peng.fan, xypron.glpk, randolph, dlan, junhui.liu,
	neil.armstrong, quentin.schulz, samuel, raymondmaoca

From: Raymond Mao <raymond.mao@riscstar.com>

Restructure K1 SoC support to handle multiple boards through a single
configuration:

1. Rename bananapi-f3_defconfig to k1_defconfig.
2. Move all K1 board files to k1 directory.

Eliminates the need for board-specific defconfigs while maintaining
hardware compatibility.

Signed-off-by: Raymond Mao <raymond.mao@riscstar.com>
---
 arch/riscv/Kconfig                                    | 10 ++++++----
 arch/riscv/cpu/k1/Kconfig                             |  4 ++++
 board/spacemit/{bananapi-f3 => k1}/Kconfig            | 11 ++++++++---
 board/spacemit/{bananapi-f3 => k1}/MAINTAINERS        |  4 ++--
 board/spacemit/{bananapi-f3 => k1}/Makefile           |  0
 board/spacemit/{bananapi-f3 => k1}/board.c            |  0
 .../{bananapi-f3_defconfig => spacemit_k1_defconfig}  |  3 ++-
 doc/board/spacemit/bananapi-f3.rst                    |  2 +-
 include/configs/{bananapi-f3.h => k1.h}               |  0
 9 files changed, 23 insertions(+), 11 deletions(-)
 rename board/spacemit/{bananapi-f3 => k1}/Kconfig (63%)
 rename board/spacemit/{bananapi-f3 => k1}/MAINTAINERS (61%)
 rename board/spacemit/{bananapi-f3 => k1}/Makefile (100%)
 rename board/spacemit/{bananapi-f3 => k1}/board.c (100%)
 rename configs/{bananapi-f3_defconfig => spacemit_k1_defconfig} (97%)
 rename include/configs/{bananapi-f3.h => k1.h} (100%)

diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index 79867656b15..ac50c1d7234 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -8,15 +8,17 @@ choice
 	prompt "Target select"
 	optional
 
+config ARCH_K1
+	bool "Spacemit K1 Architecture"
+	help
+	  This enables support for Spacemit K1 SoC family.
+
 config TARGET_ANDES_AE350
 	bool "Support Andes ae350"
 
 config TARGET_ANDES_VOYAGER
 	bool "Support Andes Voyager Board"
 
-config TARGET_BANANAPI_F3
-	bool "Support BananaPi F3 Board"
-
 config TARGET_K230_CANMV
 	bool "Support K230 CanMV Board"
 
@@ -115,7 +117,7 @@ source "board/sifive/unmatched/Kconfig"
 source "board/sipeed/maix/Kconfig"
 source "board/sophgo/milkv_duo/Kconfig"
 source "board/sophgo/licheerv_nano/Kconfig"
-source "board/spacemit/bananapi-f3/Kconfig"
+source "board/spacemit/k1/Kconfig"
 source "board/starfive/visionfive2/Kconfig"
 source "board/thead/th1520_lpi4a/Kconfig"
 source "board/xilinx/mbv/Kconfig"
diff --git a/arch/riscv/cpu/k1/Kconfig b/arch/riscv/cpu/k1/Kconfig
index 14201df80f2..4b621158334 100644
--- a/arch/riscv/cpu/k1/Kconfig
+++ b/arch/riscv/cpu/k1/Kconfig
@@ -2,6 +2,8 @@
 #
 # Copyright (C) 2024, Kongyang Liu <seashell11234455@gmail.com>
 
+if ARCH_K1
+
 config SPACEMIT_K1
 	bool
 	select BINMAN
@@ -17,3 +19,5 @@ config SPACEMIT_K1
 	imply SPL_CPU
 	imply SPL_OPENSBI
 	imply SPL_LOAD_FIT
+
+endif
diff --git a/board/spacemit/bananapi-f3/Kconfig b/board/spacemit/k1/Kconfig
similarity index 63%
rename from board/spacemit/bananapi-f3/Kconfig
rename to board/spacemit/k1/Kconfig
index f89fa9af2c7..9f9c806d00d 100644
--- a/board/spacemit/bananapi-f3/Kconfig
+++ b/board/spacemit/k1/Kconfig
@@ -1,7 +1,7 @@
-if TARGET_BANANAPI_F3
+if ARCH_K1
 
 config SYS_BOARD
-	default "bananapi-f3"
+	default "k1"
 
 config SYS_VENDOR
 	default "spacemit"
@@ -10,7 +10,7 @@ config SYS_CPU
 	default "k1"
 
 config SYS_CONFIG_NAME
-	default "bananapi-f3"
+	default "k1"
 
 config TEXT_BASE
 	default 0x00200000
@@ -22,4 +22,9 @@ config BOARD_SPECIFIC_OPTIONS
 	def_bool y
 	select SPACEMIT_K1
 
+config TARGET_BANANAPI_F3
+	bool "Support BananaPi F3 Board"
+	help
+	  BananaPi F3 board contains Spacemit K1 SoC.
+
 endif
diff --git a/board/spacemit/bananapi-f3/MAINTAINERS b/board/spacemit/k1/MAINTAINERS
similarity index 61%
rename from board/spacemit/bananapi-f3/MAINTAINERS
rename to board/spacemit/k1/MAINTAINERS
index 131bad03181..bd476c32719 100644
--- a/board/spacemit/bananapi-f3/MAINTAINERS
+++ b/board/spacemit/k1/MAINTAINERS
@@ -1,6 +1,6 @@
 BananaPi F3
 M:	Huan Zhou <pericycle.cc@@gmail.com>
 S:	Maintained
-F:	board/spacemit/bananapi-f3/
-F:	configs/bananapi-f3_defconfig
+F:	board/spacemit/k1/
+F:	configs/k1_defconfig
 F:	doc/board/spacemit/bananapi-f3.rst
diff --git a/board/spacemit/bananapi-f3/Makefile b/board/spacemit/k1/Makefile
similarity index 100%
rename from board/spacemit/bananapi-f3/Makefile
rename to board/spacemit/k1/Makefile
diff --git a/board/spacemit/bananapi-f3/board.c b/board/spacemit/k1/board.c
similarity index 100%
rename from board/spacemit/bananapi-f3/board.c
rename to board/spacemit/k1/board.c
diff --git a/configs/bananapi-f3_defconfig b/configs/spacemit_k1_defconfig
similarity index 97%
rename from configs/bananapi-f3_defconfig
rename to configs/spacemit_k1_defconfig
index a726ce84775..0bdc3c800f0 100644
--- a/configs/bananapi-f3_defconfig
+++ b/configs/spacemit_k1_defconfig
@@ -6,9 +6,10 @@ CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x1000000
 CONFIG_DEFAULT_DEVICE_TREE="k1-bananapi-f3"
 CONFIG_SYS_BOOTM_LEN=0xa000000
 CONFIG_SYS_LOAD_ADDR=0x200000
-CONFIG_TARGET_BANANAPI_F3=y
 CONFIG_ARCH_RV64I=y
 CONFIG_RISCV_SMODE=y
+CONFIG_ARCH_K1=y
+CONFIG_TARGET_BANANAPI_F3=y
 CONFIG_FIT=y
 CONFIG_SUPPORT_RAW_INITRD=y
 CONFIG_OF_BOARD_SETUP=y
diff --git a/doc/board/spacemit/bananapi-f3.rst b/doc/board/spacemit/bananapi-f3.rst
index f2220950a3a..1ece2ce9d02 100644
--- a/doc/board/spacemit/bananapi-f3.rst
+++ b/doc/board/spacemit/bananapi-f3.rst
@@ -29,7 +29,7 @@ built for SpacemiT K1 SoC as below:
 .. code-block:: console
 
    cd <U-Boot-dir>
-   make bananapi-f3_defconfig
+   make spacemit_k1_defconfig
    make OPENSBI=<OpenSBI-dir>/build/platform/generic/firmware/fw_dynamic.bin
 
 This will generate u-boot.itb
diff --git a/include/configs/bananapi-f3.h b/include/configs/k1.h
similarity index 100%
rename from include/configs/bananapi-f3.h
rename to include/configs/k1.h
-- 
2.25.1


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

* [PATCH v2 02/16] spacemit: k1: enable SPL with debug UART
  2026-02-10 15:14 [PATCH v2 00/16] Add board support for Spacemit K1 SoC in SPL Raymond Mao
  2026-02-10 15:14 ` [PATCH v2 01/16] spacemit: k1: support multi-board infrastructure Raymond Mao
@ 2026-02-10 15:14 ` Raymond Mao
  2026-02-10 15:14 ` [PATCH v2 03/16] configs: k1: enable early timer support Raymond Mao
                   ` (15 subsequent siblings)
  17 siblings, 0 replies; 24+ messages in thread
From: Raymond Mao @ 2026-02-10 15:14 UTC (permalink / raw)
  To: u-boot
  Cc: uboot, u-boot-spacemit, raymond.mao, rick, ycliang, trini, lukma,
	hs, jh80.chung, peng.fan, xypron.glpk, randolph, dlan, junhui.liu,
	neil.armstrong, quentin.schulz, samuel, raymondmaoca

From: Raymond Mao <raymond.mao@riscstar.com>

Add SPL support featuring debug UART output for early boot
diagnostics on K1 SoC.

Signed-off-by: Raymond Mao <raymond.mao@riscstar.com>
---
 arch/riscv/cpu/k1/Kconfig     |  2 ++
 arch/riscv/dts/Makefile       |  1 +
 arch/riscv/dts/k1-spl.dts     | 25 +++++++++++++++++++++++++
 arch/riscv/dts/k1.dtsi        |  2 +-
 board/spacemit/k1/Makefile    |  2 ++
 board/spacemit/k1/spl.c       | 24 ++++++++++++++++++++++++
 configs/spacemit_k1_defconfig | 21 ++++++++++++++++++++-
 include/configs/k1.h          |  7 +++++--
 8 files changed, 80 insertions(+), 4 deletions(-)
 create mode 100644 arch/riscv/dts/k1-spl.dts
 create mode 100644 board/spacemit/k1/spl.c

diff --git a/arch/riscv/cpu/k1/Kconfig b/arch/riscv/cpu/k1/Kconfig
index 4b621158334..011fc89557e 100644
--- a/arch/riscv/cpu/k1/Kconfig
+++ b/arch/riscv/cpu/k1/Kconfig
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0-or-later
 #
 # Copyright (C) 2024, Kongyang Liu <seashell11234455@gmail.com>
+# Copyright (C) 2025-2026, RISCstar Ltd.
 
 if ARCH_K1
 
@@ -9,6 +10,7 @@ config SPACEMIT_K1
 	select BINMAN
 	select ARCH_EARLY_INIT_R
 	select SYS_CACHE_SHIFT_6
+	select SUPPORT_SPL
 	imply CPU
 	imply CPU_RISCV
 	imply RISCV_TIMER if (RISCV_SMODE || SPL_RISCV_SMODE)
diff --git a/arch/riscv/dts/Makefile b/arch/riscv/dts/Makefile
index 9b347fc3b50..e942ef95142 100644
--- a/arch/riscv/dts/Makefile
+++ b/arch/riscv/dts/Makefile
@@ -1,5 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0+
 
+dtb-$(CONFIG_ARCH_K1) += k1-spl.dtb
 dtb-$(CONFIG_TARGET_ANDES_AE350) += ae350_32.dtb ae350_64.dtb
 dtb-$(CONFIG_TARGET_ANDES_VOYAGER) += qilai-voyager.dtb
 dtb-$(CONFIG_TARGET_BANANAPI_F3) += k1-bananapi-f3.dtb
diff --git a/arch/riscv/dts/k1-spl.dts b/arch/riscv/dts/k1-spl.dts
new file mode 100644
index 00000000000..c7196c2d722
--- /dev/null
+++ b/arch/riscv/dts/k1-spl.dts
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
+/*
+ * Copyright (C) 2023-2026 Spacemit, Inc
+ * Copyright (C) 2025-2026 RISCstar Ltd.
+ */
+
+/dts-v1/;
+#include "k1.dtsi"
+#include "binman.dtsi"
+
+/ {
+	model = "spacemit k1 spl";
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+};
+
+&soc {
+	bootph-all;
+	serial@d4017000 {
+		status = "okay";
+		bootph-pre-ram;
+	};
+};
diff --git a/arch/riscv/dts/k1.dtsi b/arch/riscv/dts/k1.dtsi
index a633e43da32..9c203eb4b79 100644
--- a/arch/riscv/dts/k1.dtsi
+++ b/arch/riscv/dts/k1.dtsi
@@ -318,7 +318,7 @@
 		};
 	};
 
-	soc {
+	soc: soc {
 		compatible = "simple-bus";
 		interrupt-parent = <&plic>;
 		#address-cells = <2>;
diff --git a/board/spacemit/k1/Makefile b/board/spacemit/k1/Makefile
index 2168698402b..f9cbf4b0e06 100644
--- a/board/spacemit/k1/Makefile
+++ b/board/spacemit/k1/Makefile
@@ -1,5 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0-or-later
 #
 # Copyright (c) 2024, Kongyang Liu <seashell11234455@gmail.com>
+# Copyright (c) 2025-2026, RISCstar Ltd.
 
 obj-y := board.o
+obj-$(CONFIG_SPL_BUILD) += spl.o
diff --git a/board/spacemit/k1/spl.c b/board/spacemit/k1/spl.c
new file mode 100644
index 00000000000..e15cf5f1abf
--- /dev/null
+++ b/board/spacemit/k1/spl.c
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2025-2026, RISCstar Ltd.
+ */
+
+#include <spl.h>
+
+void board_init_f(ulong dummy)
+{
+	int ret;
+
+	ret = spl_early_init();
+	if (ret)
+		panic("spl_early_init() failed:%d\n", ret);
+
+	riscv_cpu_setup();
+
+	preloader_console_init();
+}
+
+u32 spl_boot_device(void)
+{
+	return BOOT_DEVICE_NONE;
+}
diff --git a/configs/spacemit_k1_defconfig b/configs/spacemit_k1_defconfig
index 0bdc3c800f0..d794170bc5b 100644
--- a/configs/spacemit_k1_defconfig
+++ b/configs/spacemit_k1_defconfig
@@ -3,7 +3,19 @@ CONFIG_SYS_MALLOC_LEN=0x1000000
 CONFIG_NR_DRAM_BANKS=2
 CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y
 CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x1000000
-CONFIG_DEFAULT_DEVICE_TREE="k1-bananapi-f3"
+CONFIG_DEFAULT_DEVICE_TREE="k1-spl"
+CONFIG_SPL=y
+CONFIG_SPL_TEXT_BASE=0xc0801000
+CONFIG_SPL_MAX_SIZE=0x33000
+CONFIG_SPL_BSS_START_ADDR=0xc0837000
+CONFIG_SPL_BSS_MAX_SIZE=0x2000
+# CONFIG_SPL_SHARES_INIT_SP_ADDR is not set
+CONFIG_SPL_HAVE_INIT_STACK=y
+CONFIG_SPL_STACK=0xc0840000
+CONFIG_SPL_SIZE_LIMIT=0x31000
+CONFIG_SPL_FIT_SIGNATURE=y
+CONFIG_SPL_LOAD_FIT_ADDRESS=0x08000000
+CONFIG_STACK_SIZE=0x100000
 CONFIG_SYS_BOOTM_LEN=0xa000000
 CONFIG_SYS_LOAD_ADDR=0x200000
 CONFIG_ARCH_RV64I=y
@@ -23,3 +35,10 @@ CONFIG_PINCTRL_SINGLE=y
 CONFIG_RESET_SPACEMIT_K1=y
 CONFIG_SYS_NS16550=y
 CONFIG_SYS_NS16550_MEM32=y
+CONFIG_DEBUG_UART=y
+CONFIG_DEBUG_UART_BASE=0xd4017000
+CONFIG_DEBUG_UART_CLOCK=14700000
+CONFIG_DEBUG_UART_SHIFT=2
+CONFIG_DEBUG_UART_NS16550=y
+CONFIG_DEBUG_UART_ANNOUNCE=y
+# CONFIG_DEBUG_SBI_CONSOLE is not set
diff --git a/include/configs/k1.h b/include/configs/k1.h
index 97cf4d72df0..e0b05c50b70 100644
--- a/include/configs/k1.h
+++ b/include/configs/k1.h
@@ -1,13 +1,16 @@
 /* SPDX-License-Identifier: GPL-2.0-or-later */
 /*
  * Copyright (c) 2024, Kongyang Liu <seashell11234455@gmail.com>
+ * Copyright (C) 2025-2026, RISCstar Ltd.
  *
  */
 
 #ifndef __CONFIG_H
 #define __CONFIG_H
 
-#define CFG_SYS_SDRAM_BASE         0x0
-#define CFG_SYS_NS16550_IER        0x40 /* UART Unit Enable */
+#define CFG_SYS_SDRAM_BASE	    0x0
+
+#define CFG_SYS_NS16550_CLK	    14700000
+#define CFG_SYS_NS16550_IER	    0x40 /* UART Unit Enable */
 
 #endif /* __CONFIG_H */
-- 
2.25.1


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

* [PATCH v2 03/16] configs: k1: enable early timer support
  2026-02-10 15:14 [PATCH v2 00/16] Add board support for Spacemit K1 SoC in SPL Raymond Mao
  2026-02-10 15:14 ` [PATCH v2 01/16] spacemit: k1: support multi-board infrastructure Raymond Mao
  2026-02-10 15:14 ` [PATCH v2 02/16] spacemit: k1: enable SPL with debug UART Raymond Mao
@ 2026-02-10 15:14 ` Raymond Mao
  2026-02-10 15:14 ` [PATCH v2 04/16] reset: k1: add SPL support and enable TWSI8 reset Raymond Mao
                   ` (14 subsequent siblings)
  17 siblings, 0 replies; 24+ messages in thread
From: Raymond Mao @ 2026-02-10 15:14 UTC (permalink / raw)
  To: u-boot
  Cc: uboot, u-boot-spacemit, raymond.mao, rick, ycliang, trini, lukma,
	hs, jh80.chung, peng.fan, xypron.glpk, randolph, dlan, junhui.liu,
	neil.armstrong, quentin.schulz, samuel, raymondmaoca

From: Raymond Mao <raymond.mao@riscstar.com>

Enable CONFIG_TIMER_EARLY to allow udelay() calls during
early initialization phases. This is required for proper
timing operations before the full timer driver is available.

Signed-off-by: Raymond Mao <raymond.mao@riscstar.com>
---
 configs/spacemit_k1_defconfig | 2 ++
 include/configs/k1.h          | 3 +++
 2 files changed, 5 insertions(+)

diff --git a/configs/spacemit_k1_defconfig b/configs/spacemit_k1_defconfig
index d794170bc5b..617fe9d2aae 100644
--- a/configs/spacemit_k1_defconfig
+++ b/configs/spacemit_k1_defconfig
@@ -20,6 +20,7 @@ CONFIG_SYS_BOOTM_LEN=0xa000000
 CONFIG_SYS_LOAD_ADDR=0x200000
 CONFIG_ARCH_RV64I=y
 CONFIG_RISCV_SMODE=y
+CONFIG_SPL_RISCV_SMODE=y
 CONFIG_ARCH_K1=y
 CONFIG_TARGET_BANANAPI_F3=y
 CONFIG_FIT=y
@@ -42,3 +43,4 @@ CONFIG_DEBUG_UART_SHIFT=2
 CONFIG_DEBUG_UART_NS16550=y
 CONFIG_DEBUG_UART_ANNOUNCE=y
 # CONFIG_DEBUG_SBI_CONSOLE is not set
+CONFIG_TIMER_EARLY=y
diff --git a/include/configs/k1.h b/include/configs/k1.h
index e0b05c50b70..8e148803dea 100644
--- a/include/configs/k1.h
+++ b/include/configs/k1.h
@@ -13,4 +13,7 @@
 #define CFG_SYS_NS16550_CLK	    14700000
 #define CFG_SYS_NS16550_IER	    0x40 /* UART Unit Enable */
 
+#define RISCV_MMODE_TIMER_FREQ	    24000000
+#define RISCV_SMODE_TIMER_FREQ	    24000000
+
 #endif /* __CONFIG_H */
-- 
2.25.1


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

* [PATCH v2 04/16] reset: k1: add SPL support and enable TWSI8 reset
  2026-02-10 15:14 [PATCH v2 00/16] Add board support for Spacemit K1 SoC in SPL Raymond Mao
                   ` (2 preceding siblings ...)
  2026-02-10 15:14 ` [PATCH v2 03/16] configs: k1: enable early timer support Raymond Mao
@ 2026-02-10 15:14 ` Raymond Mao
  2026-02-10 15:14 ` [PATCH v2 05/16] dt-bindings: clock: import k1-syscon from upstream Raymond Mao
                   ` (13 subsequent siblings)
  17 siblings, 0 replies; 24+ messages in thread
From: Raymond Mao @ 2026-02-10 15:14 UTC (permalink / raw)
  To: u-boot
  Cc: uboot, u-boot-spacemit, raymond.mao, rick, ycliang, trini, lukma,
	hs, jh80.chung, peng.fan, xypron.glpk, randolph, dlan, junhui.liu,
	neil.armstrong, quentin.schulz, samuel, raymondmaoca

From: Raymond Mao <raymond.mao@riscstar.com>

This commit enhances the K1 reset controller driver:

1. Enable SPL support
   - Select CONFIG_SPL_RESET_SPACEMIT_K1 for SPL builds
   - Reset controller is required during early boot for
     proper hardware initialization sequence

2. Remove TWSI8 (I2C8) reset restriction
   - TWSI8 is now fully controllable by reset controller

Signed-off-by: Raymond Mao <raymond.mao@riscstar.com>
---
 drivers/reset/Kconfig             | 7 +++++++
 drivers/reset/Makefile            | 2 +-
 drivers/reset/reset-spacemit-k1.c | 4 ----
 3 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index 74c267dfc4e..1e69024ce74 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -252,5 +252,12 @@ config RESET_SPACEMIT_K1
 	  Support for SPACEMIT's K1 Reset system. Basic Assert/Deassert
 	  is supported.
 
+config SPL_RESET_SPACEMIT_K1
+	bool "SPL Reset driver for Spacemit K1 SoC"
+	depends on SPL && RESET_SPACEMIT_K1
+	default y
+	help
+	  Support for reset controller on Spacemit K1 SoCs in SPL.
+
 source "drivers/reset/stm32/Kconfig"
 endmenu
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index ee5b009d134..ec6893b1c45 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -33,8 +33,8 @@ obj-$(CONFIG_RESET_ZYNQMP) += reset-zynqmp.o
 obj-$(CONFIG_RESET_DRA7) += reset-dra7.o
 obj-$(CONFIG_RESET_AT91) += reset-at91.o
 obj-$(CONFIG_$(PHASE_)RESET_JH7110) += reset-jh7110.o
+obj-$(CONFIG_$(PHASE_)RESET_SPACEMIT_K1) += reset-spacemit-k1.o
 obj-$(CONFIG_RESET_RZG2L_USBPHY_CTRL) += reset-rzg2l-usbphy-ctrl.o
-obj-$(CONFIG_RESET_SPACEMIT_K1) += reset-spacemit-k1.o
 
 obj-$(CONFIG_ARCH_STM32) += stm32/
 obj-$(CONFIG_ARCH_STM32MP) += stm32/
diff --git a/drivers/reset/reset-spacemit-k1.c b/drivers/reset/reset-spacemit-k1.c
index 613e002fc4f..99dce90b4c4 100644
--- a/drivers/reset/reset-spacemit-k1.c
+++ b/drivers/reset/reset-spacemit-k1.c
@@ -452,10 +452,6 @@ static int spacemit_reset_update(struct reset_ctl *rst, bool assert)
 	if (rst->id < RESET_UART1 || rst->id >= RESET_NUMBER)
 		return 0;
 
-	/* can not write to twsi8 */
-	if (rst->id == RESET_TWSI8)
-		return 0;
-
 	spacemit_reset_set(rst, rst->id, assert);
 	return 0;
 }
-- 
2.25.1


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

* [PATCH v2 05/16] dt-bindings: clock: import k1-syscon from upstream
  2026-02-10 15:14 [PATCH v2 00/16] Add board support for Spacemit K1 SoC in SPL Raymond Mao
                   ` (3 preceding siblings ...)
  2026-02-10 15:14 ` [PATCH v2 04/16] reset: k1: add SPL support and enable TWSI8 reset Raymond Mao
@ 2026-02-10 15:14 ` Raymond Mao
  2026-02-10 15:14 ` [PATCH v2 06/16] dts: k1: import dts file from upstream folder Raymond Mao
                   ` (12 subsequent siblings)
  17 siblings, 0 replies; 24+ messages in thread
From: Raymond Mao @ 2026-02-10 15:14 UTC (permalink / raw)
  To: u-boot
  Cc: uboot, u-boot-spacemit, raymond.mao, rick, ycliang, trini, lukma,
	hs, jh80.chung, peng.fan, xypron.glpk, randolph, dlan, junhui.liu,
	neil.armstrong, quentin.schulz, samuel, raymondmaoca

From: Raymond Mao <raymond.mao@riscstar.com>

Import spacemit,k1-syscon.h from upstream folder. And remove
duplicated reset IDs in it.

Signed-off-by: Raymond Mao <raymond.mao@riscstar.com>
---
 .../dt-bindings/clock/spacemit,k1-syscon.h    | 253 ++++++++++++++++++
 1 file changed, 253 insertions(+)
 create mode 100644 include/dt-bindings/clock/spacemit,k1-syscon.h

diff --git a/include/dt-bindings/clock/spacemit,k1-syscon.h b/include/dt-bindings/clock/spacemit,k1-syscon.h
new file mode 100644
index 00000000000..c33da4ce73b
--- /dev/null
+++ b/include/dt-bindings/clock/spacemit,k1-syscon.h
@@ -0,0 +1,253 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+/*
+ * Copyright (C) 2024-2025 Haylen Chu <heylenay@outlook.com>
+ */
+
+#ifndef _DT_BINDINGS_SPACEMIT_CCU_H_
+#define _DT_BINDINGS_SPACEMIT_CCU_H_
+
+/* APBS (PLL) clocks */
+#define CLK_PLL1		0
+#define CLK_PLL2		1
+#define CLK_PLL3		2
+#define CLK_PLL1_D2		3
+#define CLK_PLL1_D3		4
+#define CLK_PLL1_D4		5
+#define CLK_PLL1_D5		6
+#define CLK_PLL1_D6		7
+#define CLK_PLL1_D7		8
+#define CLK_PLL1_D8		9
+#define CLK_PLL1_D11		10
+#define CLK_PLL1_D13		11
+#define CLK_PLL1_D23		12
+#define CLK_PLL1_D64		13
+#define CLK_PLL1_D10_AUD	14
+#define CLK_PLL1_D100_AUD	15
+#define CLK_PLL2_D1		16
+#define CLK_PLL2_D2		17
+#define CLK_PLL2_D3		18
+#define CLK_PLL2_D4		19
+#define CLK_PLL2_D5		20
+#define CLK_PLL2_D6		21
+#define CLK_PLL2_D7		22
+#define CLK_PLL2_D8		23
+#define CLK_PLL3_D1		24
+#define CLK_PLL3_D2		25
+#define CLK_PLL3_D3		26
+#define CLK_PLL3_D4		27
+#define CLK_PLL3_D5		28
+#define CLK_PLL3_D6		29
+#define CLK_PLL3_D7		30
+#define CLK_PLL3_D8		31
+#define CLK_PLL3_80		32
+#define CLK_PLL3_40		33
+#define CLK_PLL3_20		34
+
+/* MPMU clocks */
+#define CLK_PLL1_307P2		0
+#define CLK_PLL1_76P8		1
+#define CLK_PLL1_61P44		2
+#define CLK_PLL1_153P6		3
+#define CLK_PLL1_102P4		4
+#define CLK_PLL1_51P2		5
+#define CLK_PLL1_51P2_AP	6
+#define CLK_PLL1_57P6		7
+#define CLK_PLL1_25P6		8
+#define CLK_PLL1_12P8		9
+#define CLK_PLL1_12P8_WDT	10
+#define CLK_PLL1_6P4		11
+#define CLK_PLL1_3P2		12
+#define CLK_PLL1_1P6		13
+#define CLK_PLL1_0P8		14
+#define CLK_PLL1_409P6		15
+#define CLK_PLL1_204P8		16
+#define CLK_PLL1_491		17
+#define CLK_PLL1_245P76		18
+#define CLK_PLL1_614		19
+#define CLK_PLL1_47P26		20
+#define CLK_PLL1_31P5		21
+#define CLK_PLL1_819		22
+#define CLK_PLL1_1228		23
+#define CLK_SLOW_UART		24
+#define CLK_SLOW_UART1		25
+#define CLK_SLOW_UART2		26
+#define CLK_WDT			27
+#define CLK_RIPC		28
+#define CLK_I2S_SYSCLK		29
+#define CLK_I2S_BCLK		30
+#define CLK_APB			31
+#define CLK_WDT_BUS		32
+#define CLK_I2S_153P6		33
+#define CLK_I2S_153P6_BASE	34
+#define CLK_I2S_SYSCLK_SRC	35
+#define CLK_I2S_BCLK_FACTOR	36
+
+/* APBC clocks */
+#define CLK_UART0		0
+#define CLK_UART2		1
+#define CLK_UART3		2
+#define CLK_UART4		3
+#define CLK_UART5		4
+#define CLK_UART6		5
+#define CLK_UART7		6
+#define CLK_UART8		7
+#define CLK_UART9		8
+#define CLK_GPIO		9
+#define CLK_PWM0		10
+#define CLK_PWM1		11
+#define CLK_PWM2		12
+#define CLK_PWM3		13
+#define CLK_PWM4		14
+#define CLK_PWM5		15
+#define CLK_PWM6		16
+#define CLK_PWM7		17
+#define CLK_PWM8		18
+#define CLK_PWM9		19
+#define CLK_PWM10		20
+#define CLK_PWM11		21
+#define CLK_PWM12		22
+#define CLK_PWM13		23
+#define CLK_PWM14		24
+#define CLK_PWM15		25
+#define CLK_PWM16		26
+#define CLK_PWM17		27
+#define CLK_PWM18		28
+#define CLK_PWM19		29
+#define CLK_SSP3		30
+#define CLK_RTC			31
+#define CLK_TWSI0		32
+#define CLK_TWSI1		33
+#define CLK_TWSI2		34
+#define CLK_TWSI4		35
+#define CLK_TWSI5		36
+#define CLK_TWSI6		37
+#define CLK_TWSI7		38
+#define CLK_TWSI8		39
+#define CLK_TIMERS1		40
+#define CLK_TIMERS2		41
+#define CLK_AIB			42
+#define CLK_ONEWIRE		43
+#define CLK_SSPA0		44
+#define CLK_SSPA1		45
+#define CLK_DRO			46
+#define CLK_IR			47
+#define CLK_TSEN		48
+#define CLK_IPC_AP2AUD		49
+#define CLK_CAN0		50
+#define CLK_CAN0_BUS		51
+#define CLK_UART0_BUS		52
+#define CLK_UART2_BUS		53
+#define CLK_UART3_BUS		54
+#define CLK_UART4_BUS		55
+#define CLK_UART5_BUS		56
+#define CLK_UART6_BUS		57
+#define CLK_UART7_BUS		58
+#define CLK_UART8_BUS		59
+#define CLK_UART9_BUS		60
+#define CLK_GPIO_BUS		61
+#define CLK_PWM0_BUS		62
+#define CLK_PWM1_BUS		63
+#define CLK_PWM2_BUS		64
+#define CLK_PWM3_BUS		65
+#define CLK_PWM4_BUS		66
+#define CLK_PWM5_BUS		67
+#define CLK_PWM6_BUS		68
+#define CLK_PWM7_BUS		69
+#define CLK_PWM8_BUS		70
+#define CLK_PWM9_BUS		71
+#define CLK_PWM10_BUS		72
+#define CLK_PWM11_BUS		73
+#define CLK_PWM12_BUS		74
+#define CLK_PWM13_BUS		75
+#define CLK_PWM14_BUS		76
+#define CLK_PWM15_BUS		77
+#define CLK_PWM16_BUS		78
+#define CLK_PWM17_BUS		79
+#define CLK_PWM18_BUS		80
+#define CLK_PWM19_BUS		81
+#define CLK_SSP3_BUS		82
+#define CLK_RTC_BUS		83
+#define CLK_TWSI0_BUS		84
+#define CLK_TWSI1_BUS		85
+#define CLK_TWSI2_BUS		86
+#define CLK_TWSI4_BUS		87
+#define CLK_TWSI5_BUS		88
+#define CLK_TWSI6_BUS		89
+#define CLK_TWSI7_BUS		90
+#define CLK_TWSI8_BUS		91
+#define CLK_TIMERS1_BUS		92
+#define CLK_TIMERS2_BUS		93
+#define CLK_AIB_BUS		94
+#define CLK_ONEWIRE_BUS		95
+#define CLK_SSPA0_BUS		96
+#define CLK_SSPA1_BUS		97
+#define CLK_TSEN_BUS		98
+#define CLK_IPC_AP2AUD_BUS	99
+#define CLK_SSPA0_I2S_BCLK	100
+#define CLK_SSPA1_I2S_BCLK	101
+
+/* APMU clocks */
+#define CLK_CCI550		0
+#define CLK_CPU_C0_HI		1
+#define CLK_CPU_C0_CORE		2
+#define CLK_CPU_C0_ACE		3
+#define CLK_CPU_C0_TCM		4
+#define CLK_CPU_C1_HI		5
+#define CLK_CPU_C1_CORE		6
+#define CLK_CPU_C1_ACE		7
+#define CLK_CCIC_4X		8
+#define CLK_CCIC1PHY		9
+#define CLK_SDH_AXI		10
+#define CLK_SDH0		11
+#define CLK_SDH1		12
+#define CLK_SDH2		13
+#define CLK_USB_P1		14
+#define CLK_USB_AXI		15
+#define CLK_USB30		16
+#define CLK_QSPI		17
+#define CLK_QSPI_BUS		18
+#define CLK_DMA			19
+#define CLK_AES			20
+#define CLK_VPU			21
+#define CLK_GPU			22
+#define CLK_EMMC		23
+#define CLK_EMMC_X		24
+#define CLK_AUDIO		25
+#define CLK_HDMI		26
+#define CLK_PMUA_ACLK		27
+#define CLK_PCIE0_MASTER	28
+#define CLK_PCIE0_SLAVE		29
+#define CLK_PCIE0_DBI		30
+#define CLK_PCIE1_MASTER	31
+#define CLK_PCIE1_SLAVE		32
+#define CLK_PCIE1_DBI		33
+#define CLK_PCIE2_MASTER	34
+#define CLK_PCIE2_SLAVE		35
+#define CLK_PCIE2_DBI		36
+#define CLK_EMAC0_BUS		37
+#define CLK_EMAC0_PTP		38
+#define CLK_EMAC1_BUS		39
+#define CLK_EMAC1_PTP		40
+#define CLK_JPG			41
+#define CLK_CCIC2PHY		42
+#define CLK_CCIC3PHY		43
+#define CLK_CSI			44
+#define CLK_CAMM0		45
+#define CLK_CAMM1		46
+#define CLK_CAMM2		47
+#define CLK_ISP_CPP		48
+#define CLK_ISP_BUS		49
+#define CLK_ISP			50
+#define CLK_DPU_MCLK		51
+#define CLK_DPU_ESC		52
+#define CLK_DPU_BIT		53
+#define CLK_DPU_PXCLK		54
+#define CLK_DPU_HCLK		55
+#define CLK_DPU_SPI		56
+#define CLK_DPU_SPI_HBUS	57
+#define CLK_DPU_SPIBUS		58
+#define CLK_DPU_SPI_ACLK	59
+#define CLK_V2D			60
+#define CLK_EMMC_BUS		61
+
+#endif /* _DT_BINDINGS_SPACEMIT_CCU_H_ */
-- 
2.25.1


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

* [PATCH v2 06/16] dts: k1: import dts file from upstream folder
  2026-02-10 15:14 [PATCH v2 00/16] Add board support for Spacemit K1 SoC in SPL Raymond Mao
                   ` (4 preceding siblings ...)
  2026-02-10 15:14 ` [PATCH v2 05/16] dt-bindings: clock: import k1-syscon from upstream Raymond Mao
@ 2026-02-10 15:14 ` Raymond Mao
  2026-02-10 15:14 ` [PATCH v2 07/16] clk: spacemit: Add support for K1 SoC Raymond Mao
                   ` (11 subsequent siblings)
  17 siblings, 0 replies; 24+ messages in thread
From: Raymond Mao @ 2026-02-10 15:14 UTC (permalink / raw)
  To: u-boot
  Cc: uboot, u-boot-spacemit, raymond.mao, rick, ycliang, trini, lukma,
	hs, jh80.chung, peng.fan, xypron.glpk, randolph, dlan, junhui.liu,
	neil.armstrong, quentin.schulz, samuel, raymondmaoca

From: Raymond Mao <raymond.mao@riscstar.com>

Import K1.dtsi from upstream folder.

Signed-off-by: Raymond Mao <raymond.mao@riscstar.com>
---
 arch/riscv/dts/k1.dtsi | 562 +++++++++++++++++++++++++++++++++--------
 1 file changed, 460 insertions(+), 102 deletions(-)

diff --git a/arch/riscv/dts/k1.dtsi b/arch/riscv/dts/k1.dtsi
index 9c203eb4b79..20f1cb57462 100644
--- a/arch/riscv/dts/k1.dtsi
+++ b/arch/riscv/dts/k1.dtsi
@@ -1,8 +1,11 @@
-// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
+// SPDX-License-Identifier: GPL-2.0 OR MIT
 /*
  * Copyright (C) 2024 Yangyu Chen <cyy@cyyself.name>
  */
 
+#include <dt-bindings/clock/spacemit,k1-syscon.h>
+#include <dt-bindings/reset/spacemit-k1-reset.h>
+
 /dts-v1/;
 / {
 	#address-cells = <2>;
@@ -10,18 +13,6 @@
 	model = "SpacemiT K1";
 	compatible = "spacemit,k1";
 
-	aliases {
-		serial0 = &uart0;
-		serial1 = &uart2;
-		serial2 = &uart3;
-		serial3 = &uart4;
-		serial4 = &uart5;
-		serial5 = &uart6;
-		serial6 = &uart7;
-		serial7 = &uart8;
-		serial8 = &uart9;
-	};
-
 	cpus {
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -318,6 +309,36 @@
 		};
 	};
 
+	clocks {
+		vctcxo_1m: clock-1m {
+			compatible = "fixed-clock";
+			clock-frequency = <1000000>;
+			clock-output-names = "vctcxo_1m";
+			#clock-cells = <0>;
+		};
+
+		vctcxo_24m: clock-24m {
+			compatible = "fixed-clock";
+			clock-frequency = <24000000>;
+			clock-output-names = "vctcxo_24m";
+			#clock-cells = <0>;
+		};
+
+		vctcxo_3m: clock-3m {
+			compatible = "fixed-clock";
+			clock-frequency = <3000000>;
+			clock-output-names = "vctcxo_3m";
+			#clock-cells = <0>;
+		};
+
+		osc_32k: clock-32k {
+			compatible = "fixed-clock";
+			clock-frequency = <32000>;
+			clock-output-names = "osc_32k";
+			#clock-cells = <0>;
+		};
+	};
+
 	soc: soc {
 		compatible = "simple-bus";
 		interrupt-parent = <&plic>;
@@ -326,96 +347,267 @@
 		dma-noncoherent;
 		ranges;
 
-		uart0: serial@d4017000 {
-			compatible = "spacemit,k1-uart", "intel,xscale-uart";
-			reg = <0x0 0xd4017000 0x0 0x100>;
-			interrupts = <42>;
-			clock-frequency = <14857000>;
-			reg-shift = <2>;
-			reg-io-width = <4>;
+		syscon_rcpu: system-controller@c0880000 {
+			compatible = "spacemit,k1-syscon-rcpu";
+			reg = <0x0 0xc0880000 0x0 0x2048>;
+			#reset-cells = <1>;
+		};
+
+		syscon_rcpu2: system-controller@c0888000 {
+			compatible = "spacemit,k1-syscon-rcpu2";
+			reg = <0x0 0xc0888000 0x0 0x28>;
+			#reset-cells = <1>;
+		};
+
+		syscon_apbc: system-controller@d4015000 {
+			compatible = "spacemit,k1-syscon-apbc";
+			reg = <0x0 0xd4015000 0x0 0x1000>;
+			clocks = <&osc_32k>, <&vctcxo_1m>, <&vctcxo_3m>,
+				 <&vctcxo_24m>;
+			clock-names = "osc", "vctcxo_1m", "vctcxo_3m",
+				      "vctcxo_24m";
+			#clock-cells = <1>;
+			#reset-cells = <1>;
+		};
+
+		gpio: gpio@d4019000 {
+			compatible = "spacemit,k1-gpio";
+			reg = <0x0 0xd4019000 0x0 0x100>;
+			clocks = <&syscon_apbc CLK_GPIO>,
+				 <&syscon_apbc CLK_GPIO_BUS>;
+			clock-names = "core", "bus";
+			gpio-controller;
+			#gpio-cells = <3>;
+			interrupts = <58>;
+			interrupt-parent = <&plic>;
+			interrupt-controller;
+			#interrupt-cells = <3>;
+			gpio-ranges = <&pinctrl 0 0 0 32>,
+				      <&pinctrl 1 0 32 32>,
+				      <&pinctrl 2 0 64 32>,
+				      <&pinctrl 3 0 96 32>;
+		};
+
+		pwm0: pwm@d401a000 {
+			compatible = "spacemit,k1-pwm", "marvell,pxa910-pwm";
+			reg = <0x0 0xd401a000 0x0 0x10>;
+			#pwm-cells = <3>;
+			clocks = <&syscon_apbc CLK_PWM0>;
+			resets = <&syscon_apbc RESET_PWM0>;
+			status = "disabled";
+		};
+
+		pwm1: pwm@d401a400 {
+			compatible = "spacemit,k1-pwm", "marvell,pxa910-pwm";
+			reg = <0x0 0xd401a400 0x0 0x10>;
+			#pwm-cells = <3>;
+			clocks = <&syscon_apbc CLK_PWM1>;
+			resets = <&syscon_apbc RESET_PWM1>;
+			status = "disabled";
+		};
+
+		pwm2: pwm@d401a800 {
+			compatible = "spacemit,k1-pwm", "marvell,pxa910-pwm";
+			reg = <0x0 0xd401a800 0x0 0x10>;
+			#pwm-cells = <3>;
+			clocks = <&syscon_apbc CLK_PWM2>;
+			resets = <&syscon_apbc RESET_PWM2>;
+			status = "disabled";
+		};
+
+		pwm3: pwm@d401ac00 {
+			compatible = "spacemit,k1-pwm", "marvell,pxa910-pwm";
+			reg = <0x0 0xd401ac00 0x0 0x10>;
+			#pwm-cells = <3>;
+			clocks = <&syscon_apbc CLK_PWM3>;
+			resets = <&syscon_apbc RESET_PWM3>;
+			status = "disabled";
+		};
+
+		pwm4: pwm@d401b000 {
+			compatible = "spacemit,k1-pwm", "marvell,pxa910-pwm";
+			reg = <0x0 0xd401b000 0x0 0x10>;
+			#pwm-cells = <3>;
+			clocks = <&syscon_apbc CLK_PWM4>;
+			resets = <&syscon_apbc RESET_PWM4>;
+			status = "disabled";
+		};
+
+		pwm5: pwm@d401b400 {
+			compatible = "spacemit,k1-pwm", "marvell,pxa910-pwm";
+			reg = <0x0 0xd401b400 0x0 0x10>;
+			#pwm-cells = <3>;
+			clocks = <&syscon_apbc CLK_PWM5>;
+			resets = <&syscon_apbc RESET_PWM5>;
+			status = "disabled";
+		};
+
+		pwm6: pwm@d401b800 {
+			compatible = "spacemit,k1-pwm", "marvell,pxa910-pwm";
+			reg = <0x0 0xd401b800 0x0 0x10>;
+			#pwm-cells = <3>;
+			clocks = <&syscon_apbc CLK_PWM6>;
+			resets = <&syscon_apbc RESET_PWM6>;
+			status = "disabled";
+		};
+
+		pwm7: pwm@d401bc00 {
+			compatible = "spacemit,k1-pwm", "marvell,pxa910-pwm";
+			reg = <0x0 0xd401bc00 0x0 0x10>;
+			#pwm-cells = <3>;
+			clocks = <&syscon_apbc CLK_PWM7>;
+			resets = <&syscon_apbc RESET_PWM7>;
+			status = "disabled";
+		};
+
+		pinctrl: pinctrl@d401e000 {
+			compatible = "spacemit,k1-pinctrl";
+			reg = <0x0 0xd401e000 0x0 0x400>;
+			clocks = <&syscon_apbc CLK_AIB>,
+				 <&syscon_apbc CLK_AIB_BUS>;
+			clock-names = "func", "bus";
+		};
+
+		pwm8: pwm@d4020000 {
+			compatible = "spacemit,k1-pwm", "marvell,pxa910-pwm";
+			reg = <0x0 0xd4020000 0x0 0x10>;
+			#pwm-cells = <3>;
+			clocks = <&syscon_apbc CLK_PWM8>;
+			resets = <&syscon_apbc RESET_PWM8>;
+			status = "disabled";
+		};
+
+		pwm9: pwm@d4020400 {
+			compatible = "spacemit,k1-pwm", "marvell,pxa910-pwm";
+			reg = <0x0 0xd4020400 0x0 0x10>;
+			#pwm-cells = <3>;
+			clocks = <&syscon_apbc CLK_PWM9>;
+			resets = <&syscon_apbc RESET_PWM9>;
+			status = "disabled";
+		};
+
+		pwm10: pwm@d4020800 {
+			compatible = "spacemit,k1-pwm", "marvell,pxa910-pwm";
+			reg = <0x0 0xd4020800 0x0 0x10>;
+			#pwm-cells = <3>;
+			clocks = <&syscon_apbc CLK_PWM10>;
+			resets = <&syscon_apbc RESET_PWM10>;
 			status = "disabled";
 		};
 
-		uart2: serial@d4017100 {
-			compatible = "spacemit,k1-uart", "intel,xscale-uart";
-			reg = <0x0 0xd4017100 0x0 0x100>;
-			interrupts = <44>;
-			clock-frequency = <14857000>;
-			reg-shift = <2>;
-			reg-io-width = <4>;
+		pwm11: pwm@d4020c00 {
+			compatible = "spacemit,k1-pwm", "marvell,pxa910-pwm";
+			reg = <0x0 0xd4020c00 0x0 0x10>;
+			#pwm-cells = <3>;
+			clocks = <&syscon_apbc CLK_PWM11>;
+			resets = <&syscon_apbc RESET_PWM11>;
 			status = "disabled";
 		};
 
-		uart3: serial@d4017200 {
-			compatible = "spacemit,k1-uart", "intel,xscale-uart";
-			reg = <0x0 0xd4017200 0x0 0x100>;
-			interrupts = <45>;
-			clock-frequency = <14857000>;
-			reg-shift = <2>;
-			reg-io-width = <4>;
+		pwm12: pwm@d4021000 {
+			compatible = "spacemit,k1-pwm", "marvell,pxa910-pwm";
+			reg = <0x0 0xd4021000 0x0 0x10>;
+			#pwm-cells = <3>;
+			clocks = <&syscon_apbc CLK_PWM12>;
+			resets = <&syscon_apbc RESET_PWM12>;
 			status = "disabled";
 		};
 
-		uart4: serial@d4017300 {
-			compatible = "spacemit,k1-uart", "intel,xscale-uart";
-			reg = <0x0 0xd4017300 0x0 0x100>;
-			interrupts = <46>;
-			clock-frequency = <14857000>;
-			reg-shift = <2>;
-			reg-io-width = <4>;
+		pwm13: pwm@d4021400 {
+			compatible = "spacemit,k1-pwm", "marvell,pxa910-pwm";
+			reg = <0x0 0xd4021400 0x0 0x10>;
+			#pwm-cells = <3>;
+			clocks = <&syscon_apbc CLK_PWM13>;
+			resets = <&syscon_apbc RESET_PWM13>;
 			status = "disabled";
 		};
 
-		uart5: serial@d4017400 {
-			compatible = "spacemit,k1-uart", "intel,xscale-uart";
-			reg = <0x0 0xd4017400 0x0 0x100>;
-			interrupts = <47>;
-			clock-frequency = <14857000>;
-			reg-shift = <2>;
-			reg-io-width = <4>;
+		pwm14: pwm@d4021800 {
+			compatible = "spacemit,k1-pwm", "marvell,pxa910-pwm";
+			reg = <0x0 0xd4021800 0x0 0x10>;
+			#pwm-cells = <3>;
+			clocks = <&syscon_apbc CLK_PWM14>;
+			resets = <&syscon_apbc RESET_PWM14>;
 			status = "disabled";
 		};
 
-		uart6: serial@d4017500 {
-			compatible = "spacemit,k1-uart", "intel,xscale-uart";
-			reg = <0x0 0xd4017500 0x0 0x100>;
-			interrupts = <48>;
-			clock-frequency = <14857000>;
-			reg-shift = <2>;
-			reg-io-width = <4>;
+		pwm15: pwm@d4021c00 {
+			compatible = "spacemit,k1-pwm", "marvell,pxa910-pwm";
+			reg = <0x0 0xd4021c00 0x0 0x10>;
+			#pwm-cells = <3>;
+			clocks = <&syscon_apbc CLK_PWM15>;
+			resets = <&syscon_apbc RESET_PWM15>;
 			status = "disabled";
 		};
 
-		uart7: serial@d4017600 {
-			compatible = "spacemit,k1-uart", "intel,xscale-uart";
-			reg = <0x0 0xd4017600 0x0 0x100>;
-			interrupts = <49>;
-			clock-frequency = <14857000>;
-			reg-shift = <2>;
-			reg-io-width = <4>;
+		pwm16: pwm@d4022000 {
+			compatible = "spacemit,k1-pwm", "marvell,pxa910-pwm";
+			reg = <0x0 0xd4022000 0x0 0x10>;
+			#pwm-cells = <3>;
+			clocks = <&syscon_apbc CLK_PWM16>;
+			resets = <&syscon_apbc RESET_PWM16>;
 			status = "disabled";
 		};
 
-		uart8: serial@d4017700 {
-			compatible = "spacemit,k1-uart", "intel,xscale-uart";
-			reg = <0x0 0xd4017700 0x0 0x100>;
-			interrupts = <50>;
-			clock-frequency = <14857000>;
-			reg-shift = <2>;
-			reg-io-width = <4>;
+		pwm17: pwm@d4022400 {
+			compatible = "spacemit,k1-pwm", "marvell,pxa910-pwm";
+			reg = <0x0 0xd4022400 0x0 0x10>;
+			#pwm-cells = <3>;
+			clocks = <&syscon_apbc CLK_PWM17>;
+			resets = <&syscon_apbc RESET_PWM17>;
 			status = "disabled";
 		};
 
-		uart9: serial@d4017800 {
-			compatible = "spacemit,k1-uart", "intel,xscale-uart";
-			reg = <0x0 0xd4017800 0x0 0x100>;
-			interrupts = <51>;
-			clock-frequency = <14857000>;
-			reg-shift = <2>;
-			reg-io-width = <4>;
+		pwm18: pwm@d4022800 {
+			compatible = "spacemit,k1-pwm", "marvell,pxa910-pwm";
+			reg = <0x0 0xd4022800 0x0 0x10>;
+			#pwm-cells = <3>;
+			clocks = <&syscon_apbc CLK_PWM18>;
+			resets = <&syscon_apbc RESET_PWM18>;
 			status = "disabled";
 		};
 
+		pwm19: pwm@d4022c00 {
+			compatible = "spacemit,k1-pwm", "marvell,pxa910-pwm";
+			reg = <0x0 0xd4022c00 0x0 0x10>;
+			#pwm-cells = <3>;
+			clocks = <&syscon_apbc CLK_PWM19>;
+			resets = <&syscon_apbc RESET_PWM19>;
+			status = "disabled";
+		};
+
+		syscon_mpmu: system-controller@d4050000 {
+			compatible = "spacemit,k1-syscon-mpmu";
+			reg = <0x0 0xd4050000 0x0 0x209c>;
+			clocks = <&osc_32k>, <&vctcxo_1m>, <&vctcxo_3m>,
+				 <&vctcxo_24m>;
+			clock-names = "osc", "vctcxo_1m", "vctcxo_3m",
+				      "vctcxo_24m";
+			#clock-cells = <1>;
+			#power-domain-cells = <1>;
+			#reset-cells = <1>;
+		};
+
+		pll: clock-controller@d4090000 {
+			compatible = "spacemit,k1-pll";
+			reg = <0x0 0xd4090000 0x0 0x1000>;
+			clocks = <&vctcxo_24m>;
+			spacemit,mpmu = <&syscon_mpmu>;
+			#clock-cells = <1>;
+		};
+
+		syscon_apmu: system-controller@d4282800 {
+			compatible = "spacemit,k1-syscon-apmu";
+			reg = <0x0 0xd4282800 0x0 0x400>;
+			clocks = <&osc_32k>, <&vctcxo_1m>, <&vctcxo_3m>,
+				 <&vctcxo_24m>;
+			clock-names = "osc", "vctcxo_1m", "vctcxo_3m",
+				      "vctcxo_24m";
+			#clock-cells = <1>;
+			#power-domain-cells = <1>;
+			#reset-cells = <1>;
+		};
+
 		plic: interrupt-controller@e0000000 {
 			compatible = "spacemit,k1-plic", "sifive,plic-1.0.0";
 			reg = <0x0 0xe0000000 0x0 0x4000000>;
@@ -446,35 +638,201 @@
 					      <&cpu7_intc 3>, <&cpu7_intc 7>;
 		};
 
-		sec_uart1: serial@f0612000 {
-			compatible = "spacemit,k1-uart", "intel,xscale-uart";
-			reg = <0x0 0xf0612000 0x0 0x100>;
-			interrupts = <43>;
-			clock-frequency = <14857000>;
-			reg-shift = <2>;
-			reg-io-width = <4>;
-			status = "reserved"; /* for TEE usage */
-		};
-
-		reset: reset-controller@d4050000 {
-			compatible = "spacemit,k1-reset";
-			reg = <0x0 0xd4050000 0x0 0x209c>,
-				<0x0 0xd4282800 0x0 0x400>,
-				<0x0 0xd4015000 0x0 0x1000>,
-				<0x0 0xd4090000 0x0 0x1000>,
-				<0x0 0xd4282c00 0x0 0x400>,
-				<0x0 0xd8440000 0x0 0x98>,
-				<0x0 0xc0000000 0x0 0x4280>,
-				<0x0 0xf0610000 0x0 0x20>;
-			reg-names = "mpmu", "apmu", "apbc", "apbs", "ciu", "dciu", "ddrc", "apbc2";
+		syscon_apbc2: system-controller@f0610000 {
+			compatible = "spacemit,k1-syscon-apbc2";
+			reg = <0x0 0xf0610000 0x0 0x20>;
 			#reset-cells = <1>;
-			status = "disabled";
 		};
 
-		pinctrl: pinctrl@d401e000 {
-			compatible = "spacemit,k1-pinctrl", "pinctrl-single";
-			reg = <0x0 0xd401e000 0x0 0x400>;
-			pinctrl-single,register-width = <32>;
+		camera-bus {
+			compatible = "simple-bus";
+			ranges;
+			#address-cells = <2>;
+			#size-cells = <2>;
+			dma-ranges = <0x0 0x00000000 0x0 0x00000000 0x0 0x80000000>,
+				     <0x0 0x80000000 0x1 0x00000000 0x1 0x80000000>;
+		};
+
+		dma-bus {
+			compatible = "simple-bus";
+			ranges;
+			#address-cells = <2>;
+			#size-cells = <2>;
+			dma-ranges = <0x0 0x00000000 0x0 0x00000000 0x0 0x80000000>,
+				     <0x1 0x00000000 0x1 0x80000000 0x3 0x00000000>;
+
+			uart0: serial@d4017000 {
+				compatible = "spacemit,k1-uart",
+					     "intel,xscale-uart";
+				reg = <0x0 0xd4017000 0x0 0x100>;
+				clocks = <&syscon_apbc CLK_UART0>,
+					 <&syscon_apbc CLK_UART0_BUS>;
+				clock-names = "core", "bus";
+				interrupts = <42>;
+				reg-shift = <2>;
+				reg-io-width = <4>;
+				status = "disabled";
+			};
+
+			uart2: serial@d4017100 {
+				compatible = "spacemit,k1-uart",
+					     "intel,xscale-uart";
+				reg = <0x0 0xd4017100 0x0 0x100>;
+				clocks = <&syscon_apbc CLK_UART2>,
+					 <&syscon_apbc CLK_UART2_BUS>;
+				clock-names = "core", "bus";
+				interrupts = <44>;
+				reg-shift = <2>;
+				reg-io-width = <4>;
+				status = "disabled";
+			};
+
+			uart3: serial@d4017200 {
+				compatible = "spacemit,k1-uart",
+					     "intel,xscale-uart";
+				reg = <0x0 0xd4017200 0x0 0x100>;
+				clocks = <&syscon_apbc CLK_UART3>,
+					 <&syscon_apbc CLK_UART3_BUS>;
+				clock-names = "core", "bus";
+				interrupts = <45>;
+				reg-shift = <2>;
+				reg-io-width = <4>;
+				status = "disabled";
+			};
+
+			uart4: serial@d4017300 {
+				compatible = "spacemit,k1-uart",
+					     "intel,xscale-uart";
+				reg = <0x0 0xd4017300 0x0 0x100>;
+				clocks = <&syscon_apbc CLK_UART4>,
+					 <&syscon_apbc CLK_UART4_BUS>;
+				clock-names = "core", "bus";
+				interrupts = <46>;
+				reg-shift = <2>;
+				reg-io-width = <4>;
+				status = "disabled";
+			};
+
+			uart5: serial@d4017400 {
+				compatible = "spacemit,k1-uart",
+					     "intel,xscale-uart";
+				reg = <0x0 0xd4017400 0x0 0x100>;
+				clocks = <&syscon_apbc CLK_UART5>,
+					 <&syscon_apbc CLK_UART5_BUS>;
+				clock-names = "core", "bus";
+				interrupts = <47>;
+				reg-shift = <2>;
+				reg-io-width = <4>;
+				status = "disabled";
+			};
+
+			uart6: serial@d4017500 {
+				compatible = "spacemit,k1-uart",
+					     "intel,xscale-uart";
+				reg = <0x0 0xd4017500 0x0 0x100>;
+				clocks = <&syscon_apbc CLK_UART6>,
+					 <&syscon_apbc CLK_UART6_BUS>;
+				clock-names = "core", "bus";
+				interrupts = <48>;
+				reg-shift = <2>;
+				reg-io-width = <4>;
+				status = "disabled";
+			};
+
+			uart7: serial@d4017600 {
+				compatible = "spacemit,k1-uart",
+					     "intel,xscale-uart";
+				reg = <0x0 0xd4017600 0x0 0x100>;
+				clocks = <&syscon_apbc CLK_UART7>,
+					 <&syscon_apbc CLK_UART7_BUS>;
+				clock-names = "core", "bus";
+				interrupts = <49>;
+				reg-shift = <2>;
+				reg-io-width = <4>;
+				status = "disabled";
+			};
+
+			uart8: serial@d4017700 {
+				compatible = "spacemit,k1-uart",
+					     "intel,xscale-uart";
+				reg = <0x0 0xd4017700 0x0 0x100>;
+				clocks = <&syscon_apbc CLK_UART8>,
+					 <&syscon_apbc CLK_UART8_BUS>;
+				clock-names = "core", "bus";
+				interrupts = <50>;
+				reg-shift = <2>;
+				reg-io-width = <4>;
+				status = "disabled";
+			};
+
+			uart9: serial@d4017800 {
+				compatible = "spacemit,k1-uart",
+					     "intel,xscale-uart";
+				reg = <0x0 0xd4017800 0x0 0x100>;
+				clocks = <&syscon_apbc CLK_UART9>,
+					 <&syscon_apbc CLK_UART9_BUS>;
+				clock-names = "core", "bus";
+				interrupts = <51>;
+				reg-shift = <2>;
+				reg-io-width = <4>;
+				status = "disabled";
+			};
+
+			sec_uart1: serial@f0612000 {
+				compatible = "spacemit,k1-uart",
+					     "intel,xscale-uart";
+				reg = <0x0 0xf0612000 0x0 0x100>;
+				interrupts = <43>;
+				clock-frequency = <14857000>;
+				reg-shift = <2>;
+				reg-io-width = <4>;
+				status = "reserved"; /* for TEE usage */
+			};
+		};
+
+		multimedia-bus {
+			compatible = "simple-bus";
+			ranges;
+			#address-cells = <2>;
+			#size-cells = <2>;
+			dma-ranges = <0x0 0x00000000 0x0 0x00000000 0x0 0x80000000>,
+				     <0x0 0x80000000 0x1 0x00000000 0x3 0x80000000>;
+		};
+
+		network-bus {
+			compatible = "simple-bus";
+			ranges;
+			#address-cells = <2>;
+			#size-cells = <2>;
+			dma-ranges = <0x0 0x00000000 0x0 0x00000000 0x0 0x80000000>,
+				     <0x0 0x80000000 0x1 0x00000000 0x0 0x80000000>;
+		};
+
+		pcie-bus {
+			compatible = "simple-bus";
+			ranges;
+			#address-cells = <2>;
+			#size-cells = <2>;
+			dma-ranges = <0x0 0x00000000 0x0 0x00000000 0x0 0x80000000>,
+				     <0x0 0xb8000000 0x1 0x38000000 0x3 0x48000000>;
+		};
+
+		storage-bus {
+			compatible = "simple-bus";
+			ranges;
+			#address-cells = <2>;
+			#size-cells = <2>;
+			dma-ranges = <0x0 0x00000000 0x0 0x00000000 0x0 0x80000000>;
+
+			emmc: mmc@d4281000 {
+				compatible = "spacemit,k1-sdhci";
+				reg = <0x0 0xd4281000 0x0 0x200>;
+				clocks = <&syscon_apmu CLK_SDH_AXI>,
+					 <&syscon_apmu CLK_SDH2>;
+				clock-names = "core", "io";
+				interrupts = <101>;
+				status = "disabled";
+			};
 		};
 	};
 };
-- 
2.25.1


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

* [PATCH v2 07/16] clk: spacemit: Add support for K1 SoC
  2026-02-10 15:14 [PATCH v2 00/16] Add board support for Spacemit K1 SoC in SPL Raymond Mao
                   ` (5 preceding siblings ...)
  2026-02-10 15:14 ` [PATCH v2 06/16] dts: k1: import dts file from upstream folder Raymond Mao
@ 2026-02-10 15:14 ` Raymond Mao
  2026-02-10 15:14 ` [PATCH v2 08/16] dts: k1: enable clocks in SPL Raymond Mao
                   ` (10 subsequent siblings)
  17 siblings, 0 replies; 24+ messages in thread
From: Raymond Mao @ 2026-02-10 15:14 UTC (permalink / raw)
  To: u-boot
  Cc: uboot, u-boot-spacemit, raymond.mao, rick, ycliang, trini, lukma,
	hs, jh80.chung, peng.fan, xypron.glpk, randolph, dlan, junhui.liu,
	neil.armstrong, quentin.schulz, samuel, raymondmaoca, Raymond Mao

From: Junhui Liu <junhui.liu@pigmoral.tech>

Add clock support for Spacemit K1 SoC.

Signed-off-by: Junhui Liu <junhui.liu@pigmoral.tech>
Signed-off-by: Raymond Mao <raymond.mao@riststar.com>
---
 drivers/clk/Kconfig               |    5 +-
 drivers/clk/Makefile              |    1 +
 drivers/clk/spacemit/Kconfig      |   31 +
 drivers/clk/spacemit/Makefile     |    7 +
 drivers/clk/spacemit/clk-k1.c     | 1795 +++++++++++++++++++++++++++++
 drivers/clk/spacemit/clk_common.h |   79 ++
 drivers/clk/spacemit/clk_ddn.c    |   93 ++
 drivers/clk/spacemit/clk_ddn.h    |   53 +
 drivers/clk/spacemit/clk_mix.c    |  403 +++++++
 drivers/clk/spacemit/clk_mix.h    |  224 ++++
 drivers/clk/spacemit/clk_pll.c    |  157 +++
 drivers/clk/spacemit/clk_pll.h    |   81 ++
 include/soc/spacemit/k1-syscon.h  |  149 +++
 13 files changed, 3076 insertions(+), 2 deletions(-)
 create mode 100644 drivers/clk/spacemit/Kconfig
 create mode 100644 drivers/clk/spacemit/Makefile
 create mode 100644 drivers/clk/spacemit/clk-k1.c
 create mode 100644 drivers/clk/spacemit/clk_common.h
 create mode 100644 drivers/clk/spacemit/clk_ddn.c
 create mode 100644 drivers/clk/spacemit/clk_ddn.h
 create mode 100644 drivers/clk/spacemit/clk_mix.c
 create mode 100644 drivers/clk/spacemit/clk_mix.h
 create mode 100644 drivers/clk/spacemit/clk_pll.c
 create mode 100644 drivers/clk/spacemit/clk_pll.h
 create mode 100644 include/soc/spacemit/k1-syscon.h

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 85cc472b4cb..85da15bcaad 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -275,11 +275,12 @@ source "drivers/clk/mvebu/Kconfig"
 source "drivers/clk/owl/Kconfig"
 source "drivers/clk/qcom/Kconfig"
 source "drivers/clk/renesas/Kconfig"
-source "drivers/clk/sophgo/Kconfig"
-source "drivers/clk/sunxi/Kconfig"
 source "drivers/clk/sifive/Kconfig"
+source "drivers/clk/sophgo/Kconfig"
+source "drivers/clk/spacemit/Kconfig"
 source "drivers/clk/starfive/Kconfig"
 source "drivers/clk/stm32/Kconfig"
+source "drivers/clk/sunxi/Kconfig"
 source "drivers/clk/tegra/Kconfig"
 source "drivers/clk/ti/Kconfig"
 source "drivers/clk/thead/Kconfig"
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 5f0c0d8a5c2..dabbb3af4b6 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -48,6 +48,7 @@ obj-$(CONFIG_CLK_RENESAS) += renesas/
 obj-$(CONFIG_$(PHASE_)CLK_SCMI) += clk_scmi.o
 obj-$(CONFIG_CLK_SIFIVE) += sifive/
 obj-$(CONFIG_CLK_SOPHGO) += sophgo/
+obj-$(CONFIG_CLK_SPACEMIT) += spacemit/
 obj-$(CONFIG_CLK_SUNXI) += sunxi/
 obj-$(CONFIG_CLK_UNIPHIER) += uniphier/
 obj-$(CONFIG_CLK_VERSACLOCK) += clk_versaclock.o
diff --git a/drivers/clk/spacemit/Kconfig b/drivers/clk/spacemit/Kconfig
new file mode 100644
index 00000000000..fd96ec8fd2e
--- /dev/null
+++ b/drivers/clk/spacemit/Kconfig
@@ -0,0 +1,31 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# Copyright (c) 2025, Junhui Liu <junhui.liu@pigmoral.tech>
+
+config CLK_SPACEMIT
+	bool "Clock support for SpacemiT SoCs"
+	depends on CLK
+	select REGMAP
+	help
+	  This enables support clock driver for Spacemit SoC
+	  family.
+
+if CLK_SPACEMIT
+
+config CLK_SPACEMIT_K1
+	bool "SpacemiT K1 clock support"
+	select CLK_CCF
+	default SPACEMIT_K1
+	help
+	  This enables support clock driver for Spacemit K1 SoC.
+	  It's based on Common Clock Framework.
+
+config SPL_CLK_SPACEMIT_K1
+	bool "Enable Spacemit K1 SoC clock support in SPL"
+	select SPL_CLK_CCF
+	default SPACEMIT_K1
+	help
+	  It allows to use the Spacemit K1 SoC clock driver in
+	  SPL.
+
+endif
diff --git a/drivers/clk/spacemit/Makefile b/drivers/clk/spacemit/Makefile
new file mode 100644
index 00000000000..824e94d1f74
--- /dev/null
+++ b/drivers/clk/spacemit/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# Copyright (C) 2025 Junhui Liu <junhui.liu@pigmoral.tech>
+
+obj-$(CONFIG_CLK_SPACEMIT) += clk_ddn.o clk_mix.o clk_pll.o
+
+obj-$(CONFIG_CLK_SPACEMIT_K1)	+= clk-k1.o
diff --git a/drivers/clk/spacemit/clk-k1.c b/drivers/clk/spacemit/clk-k1.c
new file mode 100644
index 00000000000..063b6122e88
--- /dev/null
+++ b/drivers/clk/spacemit/clk-k1.c
@@ -0,0 +1,1795 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2024 SpacemiT Technology Co. Ltd
+ * Copyright (c) 2024-2025 Haylen Chu <heylenay@4d2.org>
+ * Copyright (c) 2025 Junhui Liu <junhui.liu@pigmoral.tech>
+ * Copyright (c) 2025-2026 RISCstar Ltd.
+ *
+ *  Authors: Haylen Chu <heylenay@4d2.org>
+ */
+
+#include <dm.h>
+#include <dm/device_compat.h>
+#include <dm/lists.h>
+#include <regmap.h>
+#include <linux/clk-provider.h>
+#include <soc/spacemit/k1-syscon.h>
+
+#include "clk_common.h"
+#include "clk_ddn.h"
+#include "clk_mix.h"
+#include "clk_pll.h"
+
+#include <dt-bindings/clock/spacemit,k1-syscon.h>
+
+#define K1_PLL_ID		100
+#define K1_MPMU_ID		200
+#define K1_APBC_ID		300
+#define K1_APMU_ID		400
+
+struct spacemit_ccu_data {
+	struct clk **clks;
+	size_t num;
+	unsigned long offset;
+};
+
+/* APBS clocks start, APBS region contains and only contains all PLL clocks */
+
+/*
+ * PLL{1,2} must run at fixed frequencies to provide clocks in correct rates for
+ * peripherals.
+ */
+static const struct ccu_pll_rate_tbl pll1_rate_tbl[] = {
+	CCU_PLL_RATE(2457600000UL, 0x0050dd64, 0x330ccccd),
+};
+
+static const struct ccu_pll_rate_tbl pll2_rate_tbl[] = {
+	CCU_PLL_RATE(3000000000UL, 0x0050dd66, 0x3fe00000),
+};
+
+static const struct ccu_pll_rate_tbl pll3_rate_tbl[] = {
+	CCU_PLL_RATE(1600000000UL, 0x0050cd61, 0x43eaaaab),
+	CCU_PLL_RATE(1800000000UL, 0x0050cd61, 0x4b000000),
+	CCU_PLL_RATE(2000000000UL, 0x0050dd62, 0x2aeaaaab),
+	CCU_PLL_RATE(2457600000UL, 0x0050dd64, 0x330ccccd),
+	CCU_PLL_RATE(3000000000UL, 0x0050dd66, 0x3fe00000),
+	CCU_PLL_RATE(3200000000UL, 0x0050dd67, 0x43eaaaab),
+};
+
+CCU_PLL_DEFINE(CLK_PLL1, pll1, pll1, "clock-24m", pll1_rate_tbl,
+	       APBS_PLL1_SWCR1, APBS_PLL1_SWCR3, MPMU_POSR, POSR_PLL1_LOCK,
+	       CLK_SET_RATE_GATE);
+CCU_PLL_DEFINE(CLK_PLL2, pll2, pll2, "clock-24m", pll2_rate_tbl,
+	       APBS_PLL2_SWCR1, APBS_PLL2_SWCR3, MPMU_POSR, POSR_PLL2_LOCK,
+	       CLK_SET_RATE_GATE);
+CCU_PLL_DEFINE(CLK_PLL3, pll3, pll3, "clock-24m", pll3_rate_tbl,
+	       APBS_PLL3_SWCR1, APBS_PLL3_SWCR3, MPMU_POSR, POSR_PLL3_LOCK,
+	       CLK_SET_RATE_GATE);
+
+CCU_FACTOR_GATE_DEFINE(CLK_PLL1_D2, pll1_d2, pll1_d2, "pll1", APBS_PLL1_SWCR2,
+		       BIT(1), 2, 1);
+CCU_FACTOR_GATE_DEFINE(CLK_PLL1_D3, pll1_d3, pll1_d3, "pll1", APBS_PLL1_SWCR2,
+		       BIT(2), 3, 1);
+CCU_FACTOR_GATE_DEFINE(CLK_PLL1_D4, pll1_d4, pll1_d4, "pll1", APBS_PLL1_SWCR2,
+		       BIT(3), 4, 1);
+CCU_FACTOR_GATE_DEFINE(CLK_PLL1_D5, pll1_d5, pll1_d5, "pll1", APBS_PLL1_SWCR2,
+		       BIT(4), 5, 1);
+CCU_FACTOR_GATE_DEFINE(CLK_PLL1_D6, pll1_d6, pll1_d6, "pll1", APBS_PLL1_SWCR2,
+		       BIT(5), 6, 1);
+CCU_FACTOR_GATE_DEFINE(CLK_PLL1_D7, pll1_d7, pll1_d7, "pll1", APBS_PLL1_SWCR2,
+		       BIT(6), 7, 1);
+CCU_FACTOR_GATE_FLAGS_DEFINE(CLK_PLL1_D8, pll1_d8, pll1_d8, "pll1",
+			     APBS_PLL1_SWCR2, BIT(7), 8, 1, CLK_IS_CRITICAL);
+CCU_FACTOR_GATE_DEFINE(CLK_PLL1_D11, pll1_d11_223p4, pll1_d11_223p4, "pll1",
+		       APBS_PLL1_SWCR2, BIT(15), 11, 1);
+CCU_FACTOR_GATE_DEFINE(CLK_PLL1_D13, pll1_d13_189, pll1_d13_189, "pll1",
+		       APBS_PLL1_SWCR2, BIT(16), 13, 1);
+CCU_FACTOR_GATE_DEFINE(CLK_PLL1_D23, pll1_d23_106p8, pll1_d23_106p8, "pll1",
+		       APBS_PLL1_SWCR2, BIT(20), 23, 1);
+CCU_FACTOR_GATE_DEFINE(CLK_PLL1_D64, pll1_d64_38p4, pll1_d64_38p4, "pll1",
+		       APBS_PLL1_SWCR2, BIT(0), 64, 1);
+CCU_FACTOR_GATE_DEFINE(CLK_PLL1_D10_AUD, pll1_aud_245p7, pll1_aud_245p7, "pll1",
+		       APBS_PLL1_SWCR2, BIT(10), 10, 1);
+CCU_FACTOR_GATE_DEFINE(CLK_PLL1_D100_AUD, pll1_aud_24p5, pll1_aud_24p5, "pll1",
+		       APBS_PLL1_SWCR2, BIT(11), 100, 1);
+
+CCU_FACTOR_GATE_DEFINE(CLK_PLL2_D1, pll2_d1, pll2_d1, "pll2", APBS_PLL2_SWCR2,
+		       BIT(0), 1, 1);
+CCU_FACTOR_GATE_DEFINE(CLK_PLL2_D2, pll2_d2, pll2_d2, "pll2", APBS_PLL2_SWCR2,
+		       BIT(1), 2, 1);
+CCU_FACTOR_GATE_DEFINE(CLK_PLL2_D3, pll2_d3, pll2_d3, "pll2", APBS_PLL2_SWCR2,
+		       BIT(2), 3, 1);
+CCU_FACTOR_GATE_DEFINE(CLK_PLL2_D4, pll2_d4, pll2_d4, "pll2", APBS_PLL2_SWCR2,
+		       BIT(3), 4, 1);
+CCU_FACTOR_GATE_DEFINE(CLK_PLL2_D5, pll2_d5, pll2_d5, "pll2", APBS_PLL2_SWCR2,
+		       BIT(4), 5, 1);
+CCU_FACTOR_GATE_DEFINE(CLK_PLL2_D6, pll2_d6, pll2_d6, "pll2", APBS_PLL2_SWCR2,
+		       BIT(5), 6, 1);
+CCU_FACTOR_GATE_DEFINE(CLK_PLL2_D7, pll2_d7, pll2_d7, "pll2", APBS_PLL2_SWCR2,
+		       BIT(6), 7, 1);
+CCU_FACTOR_GATE_DEFINE(CLK_PLL2_D8, pll2_d8, pll2_d8, "pll2", APBS_PLL2_SWCR2,
+		       BIT(7), 8, 1);
+
+CCU_FACTOR_GATE_DEFINE(CLK_PLL3_D1, pll3_d1, pll3_d1, "pll3", APBS_PLL3_SWCR2,
+		       BIT(0), 1, 1);
+CCU_FACTOR_GATE_DEFINE(CLK_PLL3_D2, pll3_d2, pll3_d2, "pll3", APBS_PLL3_SWCR2,
+		       BIT(1), 2, 1);
+CCU_FACTOR_GATE_DEFINE(CLK_PLL3_D3, pll3_d3, pll3_d3, "pll3", APBS_PLL3_SWCR2,
+		       BIT(2), 3, 1);
+CCU_FACTOR_GATE_DEFINE(CLK_PLL3_D4, pll3_d4, pll3_d4, "pll3", APBS_PLL3_SWCR2,
+		       BIT(3), 4, 1);
+CCU_FACTOR_GATE_DEFINE(CLK_PLL3_D5, pll3_d5, pll3_d5, "pll3", APBS_PLL3_SWCR2,
+		       BIT(4), 5, 1);
+CCU_FACTOR_GATE_DEFINE(CLK_PLL3_D6, pll3_d6, pll3_d6, "pll3", APBS_PLL3_SWCR2,
+		       BIT(5), 6, 1);
+CCU_FACTOR_GATE_DEFINE(CLK_PLL3_D7, pll3_d7, pll3_d7, "pll3", APBS_PLL3_SWCR2,
+		       BIT(6), 7, 1);
+CCU_FACTOR_GATE_DEFINE(CLK_PLL3_D8, pll3_d8, pll3_d8, "pll3", APBS_PLL3_SWCR2,
+		       BIT(7), 8, 1);
+
+CCU_FACTOR_DEFINE(CLK_PLL3_20, pll3_20, pll3_20, "pll3_d8", 20, 1);
+CCU_FACTOR_DEFINE(CLK_PLL3_40, pll3_40, pll3_40, "pll3_d8", 10, 1);
+CCU_FACTOR_DEFINE(CLK_PLL3_80, pll3_80, pll3_80, "pll3_d8", 5, 1);
+/* APBS clocks end */
+
+/* MPMU clocks start */
+CCU_GATE_DEFINE(CLK_PLL1_307P2, pll1_d8_307p2, pll1_d8_307p2, "pll1_d8",
+		MPMU_ACGR, BIT(13), 0);
+
+CCU_FACTOR_DEFINE(CLK_PLL1_76P8, pll1_d32_76p8, pll1_d32_76p8, "pll1_d8_307p2",
+		  4, 1);
+
+CCU_FACTOR_DEFINE(CLK_PLL1_61P44, pll1_d40_61p44, pll1_d40_61p44,
+		  "pll1_d8_307p2", 5, 1);
+
+CCU_FACTOR_DEFINE(CLK_PLL1_153P6, pll1_d16_153p6, pll1_d16_153p6,
+		  "pll1_d8", 2, 1);
+CCU_FACTOR_GATE_DEFINE(CLK_PLL1_102P4, pll1_d24_102p4, pll1_d24_102p4,
+		       "pll1_d8", MPMU_ACGR, BIT(12), 3, 1);
+CCU_FACTOR_GATE_DEFINE(CLK_PLL1_51P2, pll1_d48_51p2, pll1_d48_51p2,
+		       "pll1_d8", MPMU_ACGR, BIT(7), 6, 1);
+CCU_FACTOR_GATE_DEFINE(CLK_PLL1_51P2_AP, pll1_d48_51p2_ap, pll1_d48_51p2_ap,
+		       "pll1_d8", MPMU_ACGR, BIT(11), 6, 1);
+CCU_FACTOR_GATE_DEFINE(CLK_PLL1_57P6, pll1_m3d128_57p6, pll1_m3d128_57p6,
+		       "pll1_d8", MPMU_ACGR, BIT(8), 16, 3);
+CCU_FACTOR_GATE_DEFINE(CLK_PLL1_25P6, pll1_d96_25p6, pll1_d96_25p6,
+		       "pll1_d8", MPMU_ACGR, BIT(4), 12, 1);
+CCU_FACTOR_GATE_DEFINE(CLK_PLL1_12P8, pll1_d192_12p8, pll1_d192_12p8,
+		       "pll1_d8", MPMU_ACGR, BIT(3), 24, 1);
+CCU_FACTOR_GATE_DEFINE(CLK_PLL1_12P8_WDT, pll1_d192_12p8_wdt, pll1_d192_12p8_wdt,
+		       "pll1_d8", MPMU_ACGR, BIT(19), 24, 1);
+CCU_FACTOR_GATE_DEFINE(CLK_PLL1_6P4, pll1_d384_6p4, pll1_d384_6p4,
+		       "pll1_d8", MPMU_ACGR, BIT(2), 48, 1);
+
+CCU_FACTOR_DEFINE(CLK_PLL1_3P2, pll1_d768_3p2, pll1_d768_3p2,
+		  "pll1_d384_6p4", 2, 1);
+CCU_FACTOR_DEFINE(CLK_PLL1_1P6, pll1_d1536_1p6, pll1_d1536_1p6,
+		  "pll1_d384_6p4", 4, 1);
+CCU_FACTOR_DEFINE(CLK_PLL1_0P8, pll1_d3072_0p8, pll1_d3072_0p8,
+		  "pll1_d384_6p4", 8, 1);
+
+CCU_GATE_DEFINE(CLK_PLL1_409P6, pll1_d6_409p6, pll1_d6_409p6, "pll1_d6",
+		MPMU_ACGR, BIT(0), 0);
+CCU_FACTOR_GATE_DEFINE(CLK_PLL1_204P8, pll1_d12_204p8, pll1_d12_204p8,
+		       "pll1_d6", MPMU_ACGR, BIT(5), 2, 1);
+
+CCU_GATE_DEFINE(CLK_PLL1_491, pll1_d5_491p52, pll1_d5_491p52, "pll1_d5",
+		MPMU_ACGR, BIT(21), 0);
+CCU_FACTOR_GATE_DEFINE(CLK_PLL1_245P76, pll1_d10_245p76, pll1_d10_245p76,
+		       "pll1_d5", MPMU_ACGR, BIT(18), 2, 1);
+
+CCU_GATE_DEFINE(CLK_PLL1_614, pll1_d4_614p4, pll1_d4_614p4, "pll1_d4",
+		MPMU_ACGR, BIT(15), 0);
+CCU_FACTOR_GATE_DEFINE(CLK_PLL1_47P26, pll1_d52_47p26, pll1_d52_47p26,
+		       "pll1_d4", MPMU_ACGR, BIT(10), 13, 1);
+CCU_FACTOR_GATE_DEFINE(CLK_PLL1_31P5, pll1_d78_31p5, pll1_d78_31p5,
+		       "pll1_d4", MPMU_ACGR, BIT(6), 39, 2);
+
+CCU_GATE_DEFINE(CLK_PLL1_819, pll1_d3_819p2, pll1_d3_819p2, "pll1_d3",
+		MPMU_ACGR, BIT(14), 0);
+
+CCU_GATE_DEFINE(CLK_PLL1_1228, pll1_d2_1228p8, pll1_d2_1228p8, "pll1_d2",
+		MPMU_ACGR, BIT(16), 0);
+
+CCU_GATE_DEFINE(CLK_SLOW_UART, slow_uart, slow_uart, "clock-32k", MPMU_ACGR,
+		BIT(1), CLK_IGNORE_UNUSED);
+CCU_DDN_DEFINE(CLK_SLOW_UART1, slow_uart1_14p74, slow_uart1_14p74,
+	       "pll1_d16_153p6", MPMU_SUCCR,
+	       CCU_DDN_MASK(16, 13), 16, CCU_DDN_MASK(0, 13), 0, 2, 0);
+CCU_DDN_DEFINE(CLK_SLOW_UART2, slow_uart2_48, slow_uart2_48,
+	       "pll1_d4_614p4", MPMU_SUCCR_1,
+	       CCU_DDN_MASK(16, 13), 16, CCU_DDN_MASK(0, 13), 0, 2, 0);
+
+#if !IS_ENABLED(CONFIG_SPL_BUILD)
+CCU_GATE_DEFINE(CLK_WDT, wdt_clk, wdt_clk, "pll1_d96_25p6", MPMU_WDTPCR,
+		BIT(1), 0);
+
+CCU_FACTOR_DEFINE(CLK_I2S_153P6, i2s_153p6, i2s_153p6, "pll1_d8_307p2", 2, 1);
+
+static const char * const i2s_153p6_base_parents[] = {
+	"i2s_153p6",
+	"pll1_d8_307p2",
+};
+
+CCU_MUX_DEFINE(CLK_I2S_153P6_BASE, i2s_153p6_base, i2s_153p6_base,
+	       i2s_153p6_base_parents, ARRAY_SIZE(i2s_153p6_base_parents),
+	       MPMU_FCCR, 29, 1, 0);
+
+static const char * const i2s_sysclk_src_parents[] = {
+	"pll1_d96_25p6",
+	"i2s_153p6_base"
+};
+
+CCU_MUX_GATE_DEFINE(CLK_I2S_SYSCLK_SRC, i2s_sysclk_src, i2s_sysclk_src,
+		    i2s_sysclk_src_parents, ARRAY_SIZE(i2s_sysclk_src_parents),
+		    MPMU_ISCCR, 30, 1, BIT(31), 0);
+
+CCU_DDN_DEFINE(CLK_I2S_SYSCLK, i2s_sysclk, i2s_sysclk, "i2s_sysclk_src",
+	       MPMU_ISCCR, CCU_DDN_MASK(0, 15), 0, CCU_DDN_MASK(15, 12),
+	       15, 1, 0);
+
+CCU_FACTOR_DEFINE(CLK_I2S_BCLK_FACTOR, i2s_bclk_factor, i2s_bclk_factor,
+		  "i2s_sysclk", 2, 1);
+/*
+ * Divider of i2s_bclk always implies a 1/2 factor, which is
+ * described by i2s_bclk_factor.
+ */
+CCU_DIV_GATE_DEFINE(CLK_I2S_BCLK, i2s_bclk, i2s_bclk, "i2s_bclk_factor",
+		    MPMU_ISCCR, 27, 2, BIT(29), 0);
+
+static const char * const apb_parents[] = {
+	"pll1_d96_25p6",
+	"pll1_d48_51p2",
+	"pll1_d96_25p6",
+	"pll1_d24_102p4",
+};
+
+CCU_MUX_DEFINE(CLK_APB, apb_clk, apb_clk, apb_parents, ARRAY_SIZE(apb_parents),
+	       MPMU_APBCSCR, 0, 2, 0);
+
+CCU_GATE_DEFINE(CLK_WDT_BUS, wdt_bus_clk, wdt_bus_clk, "apb_clk", MPMU_WDTPCR,
+		BIT(0), 0);
+
+CCU_GATE_DEFINE(CLK_RIPC, ripc_clk, ripc_clk, "apb_clk", MPMU_RIPCCR, 0x1, 0);
+#endif
+/* MPMU clocks end */
+
+/* APBC clocks start */
+static const char * const uart_clk_parents[] = {
+	"pll1_m3d128_57p6",
+	"slow_uart1_14p74",
+	"slow_uart2_48",
+};
+
+CCU_MUX_GATE_DEFINE(CLK_UART0, uart0_clk, uart0_clk, uart_clk_parents,
+		    ARRAY_SIZE(uart_clk_parents), APBC_UART1_CLK_RST,
+		    4, 3, BIT(1) | BIT(0), 0);
+
+static const char * const twsi_parents[] = {
+	"pll1_d78_31p5",
+	"pll1_d48_51p2",
+	"pll1_d40_61p44",
+};
+
+CCU_MUX_GATE_DEFINE(CLK_TWSI2, twsi2_clk, twsi2_clk, twsi_parents,
+		    ARRAY_SIZE(twsi_parents), APBC_TWSI2_CLK_RST,
+		    4, 3, BIT(1) | BIT(0), 0);
+/*
+ * APBC_TWSI8_CLK_RST has a quirk that reading always results in zero.
+ * Combine functional and bus bits together as a gate to avoid sharing the
+ * write-only register between different clock hardwares.
+ */
+CCU_GATE_DEFINE(CLK_TWSI8, twsi8_clk, twsi8_clk, "pll1_d78_31p5",
+		APBC_TWSI8_CLK_RST, BIT(1) | BIT(0), 0);
+
+#if !IS_ENABLED(CONFIG_SPL_BUILD)
+CCU_MUX_GATE_DEFINE(CLK_UART2, uart2_clk, uart2_clk, uart_clk_parents,
+		    ARRAY_SIZE(uart_clk_parents), APBC_UART2_CLK_RST,
+		    4, 3, BIT(1) | BIT(0), 0);
+CCU_MUX_GATE_DEFINE(CLK_UART3, uart3_clk, uart3_clk, uart_clk_parents,
+		    ARRAY_SIZE(uart_clk_parents), APBC_UART3_CLK_RST,
+		    4, 3, BIT(1) | BIT(0), 0);
+CCU_MUX_GATE_DEFINE(CLK_UART4, uart4_clk, uart4_clk, uart_clk_parents,
+		    ARRAY_SIZE(uart_clk_parents), APBC_UART4_CLK_RST,
+		    4, 3, BIT(1) | BIT(0), 0);
+CCU_MUX_GATE_DEFINE(CLK_UART5, uart5_clk, uart5_clk, uart_clk_parents,
+		    ARRAY_SIZE(uart_clk_parents), APBC_UART5_CLK_RST,
+		    4, 3, BIT(1) | BIT(0), 0);
+CCU_MUX_GATE_DEFINE(CLK_UART6, uart6_clk, uart6_clk, uart_clk_parents,
+		    ARRAY_SIZE(uart_clk_parents), APBC_UART6_CLK_RST,
+		    4, 3, BIT(1) | BIT(0), 0);
+CCU_MUX_GATE_DEFINE(CLK_UART7, uart7_clk, uart7_clk, uart_clk_parents,
+		    ARRAY_SIZE(uart_clk_parents), APBC_UART7_CLK_RST,
+		    4, 3, BIT(1) | BIT(0), 0);
+CCU_MUX_GATE_DEFINE(CLK_UART8, uart8_clk, uart8_clk, uart_clk_parents,
+		    ARRAY_SIZE(uart_clk_parents), APBC_UART8_CLK_RST,
+		    4, 3, BIT(1) | BIT(0), 0);
+CCU_MUX_GATE_DEFINE(CLK_UART9, uart9_clk, uart9_clk, uart_clk_parents,
+		    ARRAY_SIZE(uart_clk_parents), APBC_UART9_CLK_RST,
+		    4, 3, BIT(1) | BIT(0), 0);
+
+CCU_GATE_DEFINE(CLK_GPIO, gpio_clk, gpio_clk, "clock-24m", APBC_GPIO_CLK_RST,
+		BIT(1) | BIT(0), 0);
+
+static const char * const pwm_parents[] = {
+	"pll1_d192_12p8",
+	"clock-32k",
+};
+
+CCU_MUX_GATE_DEFINE(CLK_PWM0, pwm0_clk, pwm0_clk, pwm_parents,
+		    ARRAY_SIZE(pwm_parents), APBC_PWM0_CLK_RST, 4, 3,
+		    BIT(1) | BIT(0), 0);
+CCU_MUX_GATE_DEFINE(CLK_PWM1, pwm1_clk, pwm1_clk, pwm_parents,
+		    ARRAY_SIZE(pwm_parents), APBC_PWM1_CLK_RST, 4, 3,
+		    BIT(1) | BIT(0), 0);
+CCU_MUX_GATE_DEFINE(CLK_PWM2, pwm2_clk, pwm2_clk, pwm_parents,
+		    ARRAY_SIZE(pwm_parents), APBC_PWM2_CLK_RST, 4, 3,
+		    BIT(1) | BIT(0), 0);
+CCU_MUX_GATE_DEFINE(CLK_PWM3, pwm3_clk, pwm3_clk, pwm_parents,
+		    ARRAY_SIZE(pwm_parents), APBC_PWM3_CLK_RST, 4, 3,
+		    BIT(1) | BIT(0), 0);
+CCU_MUX_GATE_DEFINE(CLK_PWM4, pwm4_clk, pwm4_clk, pwm_parents,
+		    ARRAY_SIZE(pwm_parents), APBC_PWM4_CLK_RST, 4, 3,
+		    BIT(1) | BIT(0), 0);
+CCU_MUX_GATE_DEFINE(CLK_PWM5, pwm5_clk, pwm5_clk, pwm_parents,
+		    ARRAY_SIZE(pwm_parents), APBC_PWM5_CLK_RST, 4, 3,
+		    BIT(1) | BIT(0), 0);
+CCU_MUX_GATE_DEFINE(CLK_PWM6, pwm6_clk, pwm6_clk, pwm_parents,
+		    ARRAY_SIZE(pwm_parents), APBC_PWM6_CLK_RST, 4, 3,
+		    BIT(1) | BIT(0), 0);
+CCU_MUX_GATE_DEFINE(CLK_PWM7, pwm7_clk, pwm7_clk, pwm_parents,
+		    ARRAY_SIZE(pwm_parents), APBC_PWM7_CLK_RST, 4, 3,
+		    BIT(1) | BIT(0), 0);
+CCU_MUX_GATE_DEFINE(CLK_PWM8, pwm8_clk, pwm8_clk, pwm_parents,
+		    ARRAY_SIZE(pwm_parents), APBC_PWM8_CLK_RST, 4, 3,
+		    BIT(1) | BIT(0), 0);
+CCU_MUX_GATE_DEFINE(CLK_PWM9, pwm9_clk, pwm9_clk, pwm_parents,
+		    ARRAY_SIZE(pwm_parents), APBC_PWM9_CLK_RST, 4, 3,
+		    BIT(1) | BIT(0), 0);
+CCU_MUX_GATE_DEFINE(CLK_PWM10, pwm10_clk, pwm10_clk, pwm_parents,
+		    ARRAY_SIZE(pwm_parents), APBC_PWM10_CLK_RST, 4, 3,
+		    BIT(1) | BIT(0), 0);
+CCU_MUX_GATE_DEFINE(CLK_PWM11, pwm11_clk, pwm11_clk, pwm_parents,
+		    ARRAY_SIZE(pwm_parents), APBC_PWM11_CLK_RST, 4, 3,
+		    BIT(1) | BIT(0), 0);
+CCU_MUX_GATE_DEFINE(CLK_PWM12, pwm12_clk, pwm12_clk, pwm_parents,
+		    ARRAY_SIZE(pwm_parents), APBC_PWM12_CLK_RST, 4, 3,
+		    BIT(1) | BIT(0), 0);
+CCU_MUX_GATE_DEFINE(CLK_PWM13, pwm13_clk, pwm13_clk, pwm_parents,
+		    ARRAY_SIZE(pwm_parents), APBC_PWM13_CLK_RST, 4, 3,
+		    BIT(1) | BIT(0), 0);
+CCU_MUX_GATE_DEFINE(CLK_PWM14, pwm14_clk, pwm14_clk, pwm_parents,
+		    ARRAY_SIZE(pwm_parents), APBC_PWM14_CLK_RST, 4, 3,
+		    BIT(1) | BIT(0), 0);
+CCU_MUX_GATE_DEFINE(CLK_PWM15, pwm15_clk, pwm15_clk, pwm_parents,
+		    ARRAY_SIZE(pwm_parents), APBC_PWM15_CLK_RST, 4, 3,
+		    BIT(1) | BIT(0), 0);
+CCU_MUX_GATE_DEFINE(CLK_PWM16, pwm16_clk, pwm16_clk, pwm_parents,
+		    ARRAY_SIZE(pwm_parents), APBC_PWM16_CLK_RST, 4, 3,
+		    BIT(1) | BIT(0), 0);
+CCU_MUX_GATE_DEFINE(CLK_PWM17, pwm17_clk, pwm17_clk, pwm_parents,
+		    ARRAY_SIZE(pwm_parents), APBC_PWM17_CLK_RST, 4, 3,
+		    BIT(1) | BIT(0), 0);
+CCU_MUX_GATE_DEFINE(CLK_PWM18, pwm18_clk, pwm18_clk, pwm_parents,
+		    ARRAY_SIZE(pwm_parents), APBC_PWM18_CLK_RST, 4, 3,
+		    BIT(1) | BIT(0), 0);
+CCU_MUX_GATE_DEFINE(CLK_PWM19, pwm19_clk, pwm19_clk, pwm_parents,
+		    ARRAY_SIZE(pwm_parents), APBC_PWM19_CLK_RST, 4, 3,
+		    BIT(1) | BIT(0), 0);
+
+static const char * const ssp_parents[] = {
+	"pll1_d384_6p4",
+	"pll1_d192_12p8",
+	"pll1_d96_25p6",
+	"pll1_d48_51p2",
+	"pll1_d768_3p2",
+	"pll1_d1536_1p6",
+	"pll1_d3072_0p8",
+};
+
+CCU_MUX_GATE_DEFINE(CLK_SSP3, ssp3_clk, ssp3_clk, ssp_parents,
+		    ARRAY_SIZE(ssp_parents), APBC_SSP3_CLK_RST, 4, 3,
+		    BIT(1), 0);
+
+CCU_GATE_DEFINE(CLK_RTC, rtc_clk, rtc_clk, "clock-32k", APBC_RTC_CLK_RST,
+		BIT(7) | BIT(1) | BIT(0), 0);
+
+CCU_MUX_GATE_DEFINE(CLK_TWSI0, twsi0_clk, twsi0_clk, twsi_parents,
+		    ARRAY_SIZE(twsi_parents), APBC_TWSI0_CLK_RST,
+		    4, 3, BIT(1) | BIT(0), 0);
+CCU_MUX_GATE_DEFINE(CLK_TWSI1, twsi1_clk, twsi1_clk, twsi_parents,
+		    ARRAY_SIZE(twsi_parents), APBC_TWSI1_CLK_RST,
+		    4, 3, BIT(1) | BIT(0), 0);
+CCU_MUX_GATE_DEFINE(CLK_TWSI4, twsi4_clk, twsi4_clk, twsi_parents,
+		    ARRAY_SIZE(twsi_parents), APBC_TWSI4_CLK_RST,
+		    4, 3, BIT(1) | BIT(0), 0);
+CCU_MUX_GATE_DEFINE(CLK_TWSI5, twsi5_clk, twsi5_clk, twsi_parents,
+		    ARRAY_SIZE(twsi_parents), APBC_TWSI5_CLK_RST,
+		    4, 3, BIT(1) | BIT(0), 0);
+CCU_MUX_GATE_DEFINE(CLK_TWSI6, twsi6_clk, twsi6_clk, twsi_parents,
+		    ARRAY_SIZE(twsi_parents), APBC_TWSI6_CLK_RST,
+		    4, 3, BIT(1) | BIT(0), 0);
+CCU_MUX_GATE_DEFINE(CLK_TWSI7, twsi7_clk, twsi7_clk, twsi_parents,
+		    ARRAY_SIZE(twsi_parents), APBC_TWSI7_CLK_RST,
+		    4, 3, BIT(1) | BIT(0), 0);
+
+static const char * const timer_parents[] = {
+	"pll1_d192_12p8",
+	"clock-32k",
+	"pll1_d384_6p4",
+	"clock-3m",
+	"clock-1m",
+};
+
+CCU_MUX_GATE_DEFINE(CLK_TIMERS1, timers1_clk, timers1_clk, timer_parents,
+		    ARRAY_SIZE(timer_parents), APBC_TIMERS1_CLK_RST, 4, 3,
+		    BIT(1) | BIT(0), 0);
+CCU_MUX_GATE_DEFINE(CLK_TIMERS2, timers2_clk, timers2_clk, timer_parents,
+		    ARRAY_SIZE(timer_parents), APBC_TIMERS2_CLK_RST, 4, 3,
+		    BIT(1) | BIT(0), 0);
+
+CCU_GATE_DEFINE(CLK_AIB, aib_clk, aib_clk, "clock-24m", APBC_AIB_CLK_RST,
+		BIT(1) | BIT(0), 0);
+
+CCU_GATE_DEFINE(CLK_ONEWIRE, onewire_clk, onewire_clk, "clock-24m",
+		APBC_ONEWIRE_CLK_RST, BIT(1) | BIT(0), 0);
+
+/*
+ * When i2s_bclk is selected as the parent clock of sspa,
+ * the hardware requires bit3 to be set
+ */
+CCU_GATE_DEFINE(CLK_SSPA0_I2S_BCLK, sspa0_i2s_bclk, sspa0_i2s_bclk, "i2s_bclk",
+		APBC_SSPA0_CLK_RST, BIT(3), 0);
+CCU_GATE_DEFINE(CLK_SSPA1_I2S_BCLK, sspa1_i2s_bclk, sspa1_i2s_bclk, "i2s_bclk",
+		APBC_SSPA1_CLK_RST, BIT(3), 0);
+
+static const char * const sspa0_parents[] = {
+	"pll1_d384_6p4",
+	"pll1_d192_12p8",
+	"pll1_d96_25p6",
+	"pll1_d48_51p2",
+	"pll1_d768_3p2",
+	"pll1_d1536_1p6",
+	"pll1_d3072_0p8",
+	"sspa0_i2s_bclk",
+};
+
+CCU_MUX_GATE_DEFINE(CLK_SSPA0, sspa0_clk, sspa0_clk, sspa0_parents,
+		    ARRAY_SIZE(sspa0_parents), APBC_SSPA0_CLK_RST, 4, 3,
+		    BIT(1), 0);
+
+static const char * const sspa1_parents[] = {
+	"pll1_d384_6p4",
+	"pll1_d192_12p8",
+	"pll1_d96_25p6",
+	"pll1_d48_51p2",
+	"pll1_d768_3p2",
+	"pll1_d1536_1p6",
+	"pll1_d3072_0p8",
+	"sspa1_i2s_bclk",
+};
+
+CCU_MUX_GATE_DEFINE(CLK_SSPA1, sspa1_clk, sspa1_clk, sspa1_parents,
+		    ARRAY_SIZE(sspa1_parents), APBC_SSPA1_CLK_RST, 4, 3,
+		    BIT(1), 0);
+
+CCU_GATE_DEFINE(CLK_DRO, dro_clk, dro_clk, "apb_clk", APBC_DRO_CLK_RST,
+		BIT(1) | BIT(0), 0);
+CCU_GATE_DEFINE(CLK_IR, ir_clk, ir_clk, "apb_clk", APBC_IR_CLK_RST,
+		BIT(1) | BIT(0), 0);
+CCU_GATE_DEFINE(CLK_TSEN, tsen_clk, tsen_clk, "apb_clk", APBC_TSEN_CLK_RST,
+		BIT(1) | BIT(0), 0);
+CCU_GATE_DEFINE(CLK_IPC_AP2AUD, ipc_ap2aud_clk, ipc_ap2aud_clk, "apb_clk",
+		APBC_IPC_AP2AUD_CLK_RST, BIT(1) | BIT(0), 0);
+
+static const char * const can_parents[] = {
+	"pll3_20",
+	"pll3_40",
+	"pll3_80",
+};
+
+CCU_MUX_GATE_DEFINE(CLK_CAN0, can0_clk, can0_clk, can_parents,
+		    ARRAY_SIZE(can_parents), APBC_CAN0_CLK_RST, 4, 3,
+		    BIT(1), 0);
+CCU_GATE_DEFINE(CLK_CAN0_BUS, can0_bus_clk, can0_bus_clk, "clock-24m",
+		APBC_CAN0_CLK_RST, BIT(0), 0);
+
+CCU_GATE_DEFINE(CLK_UART0_BUS, uart0_bus_clk, uart0_bus_clk, "apb_clk",
+		APBC_UART1_CLK_RST, BIT(0), 0);
+CCU_GATE_DEFINE(CLK_UART2_BUS, uart2_bus_clk, uart2_bus_clk, "apb_clk",
+		APBC_UART2_CLK_RST, BIT(0), 0);
+CCU_GATE_DEFINE(CLK_UART3_BUS, uart3_bus_clk, uart3_bus_clk, "apb_clk",
+		APBC_UART3_CLK_RST, BIT(0), 0);
+CCU_GATE_DEFINE(CLK_UART4_BUS, uart4_bus_clk, uart4_bus_clk, "apb_clk",
+		APBC_UART4_CLK_RST, BIT(0), 0);
+CCU_GATE_DEFINE(CLK_UART5_BUS, uart5_bus_clk, uart5_bus_clk, "apb_clk",
+		APBC_UART5_CLK_RST, BIT(0), 0);
+CCU_GATE_DEFINE(CLK_UART6_BUS, uart6_bus_clk, uart6_bus_clk, "apb_clk",
+		APBC_UART6_CLK_RST, BIT(0), 0);
+CCU_GATE_DEFINE(CLK_UART7_BUS, uart7_bus_clk, uart7_bus_clk, "apb_clk",
+		APBC_UART7_CLK_RST, BIT(0), 0);
+CCU_GATE_DEFINE(CLK_UART8_BUS, uart8_bus_clk, uart8_bus_clk, "apb_clk",
+		APBC_UART8_CLK_RST, BIT(0), 0);
+CCU_GATE_DEFINE(CLK_UART9_BUS, uart9_bus_clk, uart9_bus_clk, "apb_clk",
+		APBC_UART9_CLK_RST, BIT(0), 0);
+
+CCU_GATE_DEFINE(CLK_GPIO_BUS, gpio_bus_clk, gpio_bus_clk, "apb_clk",
+		APBC_GPIO_CLK_RST, BIT(0), 0);
+
+CCU_GATE_DEFINE(CLK_PWM0_BUS, pwm0_bus_clk, pwm0_bus_clk, "apb_clk",
+		APBC_PWM0_CLK_RST, BIT(0), 0);
+CCU_GATE_DEFINE(CLK_PWM1_BUS, pwm1_bus_clk, pwm1_bus_clk, "apb_clk",
+		APBC_PWM1_CLK_RST, BIT(0), 0);
+CCU_GATE_DEFINE(CLK_PWM2_BUS, pwm2_bus_clk, pwm2_bus_clk, "apb_clk",
+		APBC_PWM2_CLK_RST, BIT(0), 0);
+CCU_GATE_DEFINE(CLK_PWM3_BUS, pwm3_bus_clk, pwm3_bus_clk, "apb_clk",
+		APBC_PWM3_CLK_RST, BIT(0), 0);
+CCU_GATE_DEFINE(CLK_PWM4_BUS, pwm4_bus_clk, pwm4_bus_clk, "apb_clk",
+		APBC_PWM4_CLK_RST, BIT(0), 0);
+CCU_GATE_DEFINE(CLK_PWM5_BUS, pwm5_bus_clk, pwm5_bus_clk, "apb_clk",
+		APBC_PWM5_CLK_RST, BIT(0), 0);
+CCU_GATE_DEFINE(CLK_PWM6_BUS, pwm6_bus_clk, pwm6_bus_clk, "apb_clk",
+		APBC_PWM6_CLK_RST, BIT(0), 0);
+CCU_GATE_DEFINE(CLK_PWM7_BUS, pwm7_bus_clk, pwm7_bus_clk, "apb_clk",
+		APBC_PWM7_CLK_RST, BIT(0), 0);
+CCU_GATE_DEFINE(CLK_PWM8_BUS, pwm8_bus_clk, pwm8_bus_clk, "apb_clk",
+		APBC_PWM8_CLK_RST, BIT(0), 0);
+CCU_GATE_DEFINE(CLK_PWM9_BUS, pwm9_bus_clk, pwm9_bus_clk, "apb_clk",
+		APBC_PWM9_CLK_RST, BIT(0), 0);
+CCU_GATE_DEFINE(CLK_PWM10_BUS, pwm10_bus_clk, pwm10_bus_clk, "apb_clk",
+		APBC_PWM10_CLK_RST, BIT(0), 0);
+CCU_GATE_DEFINE(CLK_PWM11_BUS, pwm11_bus_clk, pwm11_bus_clk, "apb_clk",
+		APBC_PWM11_CLK_RST, BIT(0), 0);
+CCU_GATE_DEFINE(CLK_PWM12_BUS, pwm12_bus_clk, pwm12_bus_clk, "apb_clk",
+		APBC_PWM12_CLK_RST, BIT(0), 0);
+CCU_GATE_DEFINE(CLK_PWM13_BUS, pwm13_bus_clk, pwm13_bus_clk, "apb_clk",
+		APBC_PWM13_CLK_RST, BIT(0), 0);
+CCU_GATE_DEFINE(CLK_PWM14_BUS, pwm14_bus_clk, pwm14_bus_clk, "apb_clk",
+		APBC_PWM14_CLK_RST, BIT(0), 0);
+CCU_GATE_DEFINE(CLK_PWM15_BUS, pwm15_bus_clk, pwm15_bus_clk, "apb_clk",
+		APBC_PWM15_CLK_RST, BIT(0), 0);
+CCU_GATE_DEFINE(CLK_PWM16_BUS, pwm16_bus_clk, pwm16_bus_clk, "apb_clk",
+		APBC_PWM16_CLK_RST, BIT(0), 0);
+CCU_GATE_DEFINE(CLK_PWM17_BUS, pwm17_bus_clk, pwm17_bus_clk, "apb_clk",
+		APBC_PWM17_CLK_RST, BIT(0), 0);
+CCU_GATE_DEFINE(CLK_PWM18_BUS, pwm18_bus_clk, pwm18_bus_clk, "apb_clk",
+		APBC_PWM18_CLK_RST, BIT(0), 0);
+CCU_GATE_DEFINE(CLK_PWM19_BUS, pwm19_bus_clk, pwm19_bus_clk, "apb_clk",
+		APBC_PWM19_CLK_RST, BIT(0), 0);
+
+CCU_GATE_DEFINE(CLK_SSP3_BUS, ssp3_bus_clk, ssp3_bus_clk, "apb_clk",
+		APBC_SSP3_CLK_RST, BIT(0), 0);
+
+CCU_GATE_DEFINE(CLK_RTC_BUS, rtc_bus_clk, rtc_bus_clk, "apb_clk",
+		APBC_RTC_CLK_RST, BIT(0), 0);
+
+CCU_GATE_DEFINE(CLK_TWSI0_BUS, twsi0_bus_clk, twsi0_bus_clk, "apb_clk",
+		APBC_TWSI0_CLK_RST, BIT(0), 0);
+CCU_GATE_DEFINE(CLK_TWSI1_BUS, twsi1_bus_clk, twsi1_bus_clk, "apb_clk",
+		APBC_TWSI1_CLK_RST, BIT(0), 0);
+CCU_GATE_DEFINE(CLK_TWSI2_BUS, twsi2_bus_clk, twsi2_bus_clk, "apb_clk",
+		APBC_TWSI2_CLK_RST, BIT(0), 0);
+CCU_GATE_DEFINE(CLK_TWSI4_BUS, twsi4_bus_clk, twsi4_bus_clk, "apb_clk",
+		APBC_TWSI4_CLK_RST, BIT(0), 0);
+CCU_GATE_DEFINE(CLK_TWSI5_BUS, twsi5_bus_clk, twsi5_bus_clk, "apb_clk",
+		APBC_TWSI5_CLK_RST, BIT(0), 0);
+CCU_GATE_DEFINE(CLK_TWSI6_BUS, twsi6_bus_clk, twsi6_bus_clk, "apb_clk",
+		APBC_TWSI6_CLK_RST, BIT(0), 0);
+CCU_GATE_DEFINE(CLK_TWSI7_BUS, twsi7_bus_clk, twsi7_bus_clk, "apb_clk",
+		APBC_TWSI7_CLK_RST, BIT(0), 0);
+CCU_FACTOR_DEFINE(CLK_TWSI8_BUS, twsi8_bus_clk, twsi8_bus_clk, "apb_clk", 1, 1);
+
+CCU_GATE_DEFINE(CLK_TIMERS1_BUS, timers1_bus_clk, timers1_bus_clk, "apb_clk",
+		APBC_TIMERS1_CLK_RST, BIT(0), 0);
+CCU_GATE_DEFINE(CLK_TIMERS2_BUS, timers2_bus_clk, timers2_bus_clk, "apb_clk",
+		APBC_TIMERS2_CLK_RST, BIT(0), 0);
+
+CCU_GATE_DEFINE(CLK_AIB_BUS, aib_bus_clk, aib_bus_clk, "apb_clk",
+		APBC_AIB_CLK_RST, BIT(0), 0);
+
+CCU_GATE_DEFINE(CLK_ONEWIRE_BUS, onewire_bus_clk, onewire_bus_clk, "apb_clk",
+		APBC_ONEWIRE_CLK_RST, BIT(0), 0);
+
+CCU_GATE_DEFINE(CLK_SSPA0_BUS, sspa0_bus_clk, sspa0_bus_clk, "apb_clk",
+		APBC_SSPA0_CLK_RST, BIT(0), 0);
+CCU_GATE_DEFINE(CLK_SSPA1_BUS, sspa1_bus_clk, sspa1_bus_clk, "apb_clk",
+		APBC_SSPA1_CLK_RST, BIT(0), 0);
+
+CCU_GATE_DEFINE(CLK_TSEN_BUS, tsen_bus_clk, tsen_bus_clk, "apb_clk",
+		APBC_TSEN_CLK_RST, BIT(0), 0);
+
+CCU_GATE_DEFINE(CLK_IPC_AP2AUD_BUS, ipc_ap2aud_bus_clk, ipc_ap2aud_bus_clk,
+		"apb_clk", APBC_IPC_AP2AUD_CLK_RST, BIT(0), 0);
+#endif
+/* APBC clocks end */
+
+/* APMU clocks start */
+static const char * const pmua_aclk_parents[] = {
+	"pll1_d10_245p76",
+	"pll1_d8_307p2",
+};
+
+CCU_MUX_DIV_FC_DEFINE(CLK_PMUA_ACLK, pmua_aclk, pmua_aclk, pmua_aclk_parents,
+		      ARRAY_SIZE(pmua_aclk_parents),
+		      APMU_ACLK_CLK_CTRL, APMU_ACLK_CLK_CTRL, 1, 2, BIT(4),
+		      0, 1, 0);
+
+static const char * const emmc_parents[] = {
+	"pll1_d6_409p6",
+	"pll1_d4_614p4",
+	"pll1_d52_47p26",
+	"pll1_d3_819p2",
+};
+
+CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(CLK_EMMC, emmc_clk, emmc_clk, emmc_parents,
+				 ARRAY_SIZE(emmc_parents),
+				 APMU_PMUA_EM_CLK_RES_CTRL,
+				 APMU_PMUA_EM_CLK_RES_CTRL, 8, 3, BIT(11),
+				 6, 2, BIT(4), 0);
+CCU_DIV_GATE_DEFINE(CLK_EMMC_X, emmc_x_clk, emmc_x_clk, "pll1_d2_1228p8",
+		    APMU_PMUA_EM_CLK_RES_CTRL, 12,
+		    3, BIT(15), 0);
+
+CCU_GATE_DEFINE(CLK_EMMC_BUS, emmc_bus_clk, emmc_bus_clk, "pmua_aclk",
+		APMU_PMUA_EM_CLK_RES_CTRL, BIT(3), 0);
+
+#if !IS_ENABLED(CONFIG_SPL_BUILD)
+static const char * const cci550_clk_parents[] = {
+	"pll1_d5_491p52",
+	"pll1_d4_614p4",
+	"pll1_d3_819p2",
+	"pll2_d3",
+};
+
+CCU_MUX_DIV_FC_DEFINE(CLK_CCI550, cci550_clk, cci550_clk, cci550_clk_parents,
+		      ARRAY_SIZE(cci550_clk_parents),
+		      APMU_CCI550_CLK_CTRL, APMU_CCI550_CLK_CTRL, 8, 3,
+		      BIT(12), 0, 2, CLK_IS_CRITICAL);
+
+static const char * const cpu_c0_hi_clk_parents[] = {
+	"pll3_d2",
+	"pll3_d1",
+};
+
+CCU_MUX_DEFINE(CLK_CPU_C0_HI, cpu_c0_hi_clk, cpu_c0_hi_clk,
+	       cpu_c0_hi_clk_parents, ARRAY_SIZE(cpu_c0_hi_clk_parents),
+	       APMU_CPU_C0_CLK_CTRL, 13, 1, 0);
+static const char * const cpu_c0_clk_parents[] = {
+	"pll1_d4_614p4",
+	"pll1_d3_819p2",
+	"pll1_d6_409p6",
+	"pll1_d5_491p52",
+	"pll1_d2_1228p8",
+	"pll3_d3",
+	"pll2_d3",
+	"cpu_c0_hi_clk",
+};
+
+CCU_MUX_FC_DEFINE(CLK_CPU_C0_CORE, cpu_c0_core_clk, cpu_c0_core_clk,
+		  cpu_c0_clk_parents, ARRAY_SIZE(cpu_c0_clk_parents),
+		  APMU_CPU_C0_CLK_CTRL, APMU_CPU_C0_CLK_CTRL,
+		  BIT(12), 0, 3, CLK_IS_CRITICAL);
+CCU_DIV_DEFINE(CLK_CPU_C0_ACE, cpu_c0_ace_clk, cpu_c0_ace_clk,
+	       "cpu_c0_core_clk", APMU_CPU_C0_CLK_CTRL, 6, 3, CLK_IS_CRITICAL);
+CCU_DIV_DEFINE(CLK_CPU_C0_TCM, cpu_c0_tcm_clk, cpu_c0_tcm_clk,
+	       "cpu_c0_core_clk", APMU_CPU_C0_CLK_CTRL, 9, 3, CLK_IS_CRITICAL);
+
+static const char * const cpu_c1_hi_clk_parents[] = {
+	"pll3_d2",
+	"pll3_d1",
+};
+
+CCU_MUX_DEFINE(CLK_CPU_C1_HI, cpu_c1_hi_clk, cpu_c1_hi_clk,
+	       cpu_c1_hi_clk_parents, ARRAY_SIZE(cpu_c1_hi_clk_parents),
+	       APMU_CPU_C1_CLK_CTRL, 13, 1, 0);
+static const char * const cpu_c1_clk_parents[] = {
+	"pll1_d4_614p4",
+	"pll1_d3_819p2",
+	"pll1_d6_409p6",
+	"pll1_d5_491p52",
+	"pll1_d2_1228p8",
+	"pll3_d3",
+	"pll2_d3",
+	"cpu_c1_hi_clk",
+};
+
+CCU_MUX_FC_DEFINE(CLK_CPU_C1_CORE, cpu_c1_core_clk, cpu_c1_core_clk,
+		  cpu_c1_clk_parents, ARRAY_SIZE(cpu_c1_clk_parents),
+		  APMU_CPU_C1_CLK_CTRL, APMU_CPU_C1_CLK_CTRL,
+		  BIT(12), 0, 3, CLK_IS_CRITICAL);
+CCU_DIV_DEFINE(CLK_CPU_C1_ACE, cpu_c1_ace_clk, cpu_c1_ace_clk,
+	       "cpu_c1_core_clk", APMU_CPU_C1_CLK_CTRL, 6, 3, CLK_IS_CRITICAL);
+
+static const char * const jpg_parents[] = {
+	"pll1_d4_614p4",
+	"pll1_d6_409p6",
+	"pll1_d5_491p52",
+	"pll1_d3_819p2",
+	"pll1_d2_1228p8",
+	"pll2_d4",
+	"pll2_d3",
+};
+
+CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(CLK_JPG, jpg_clk, jpg_clk, jpg_parents,
+				 ARRAY_SIZE(jpg_parents),
+				 APMU_JPG_CLK_RES_CTRL,
+				 APMU_JPG_CLK_RES_CTRL,
+				 5, 3, BIT(15), 2, 3, BIT(1), 0);
+
+static const char * const ccic2phy_parents[] = {
+	"pll1_d24_102p4",
+	"pll1_d48_51p2_ap",
+};
+
+CCU_MUX_GATE_DEFINE(CLK_CCIC2PHY, ccic2phy_clk, ccic2phy_clk, ccic2phy_parents,
+		    ARRAY_SIZE(ccic2phy_parents), APMU_CSI_CCIC2_CLK_RES_CTRL,
+		    7, 1, BIT(5), 0);
+
+static const char * const ccic3phy_parents[] = {
+	"pll1_d24_102p4",
+	"pll1_d48_51p2_ap",
+};
+
+CCU_MUX_GATE_DEFINE(CLK_CCIC3PHY, ccic3phy_clk, ccic3phy_clk, ccic3phy_parents,
+		    ARRAY_SIZE(ccic3phy_parents), APMU_CSI_CCIC2_CLK_RES_CTRL,
+		    31, 1, BIT(30), 0);
+
+static const char * const csi_parents[] = {
+	"pll1_d5_491p52",
+	"pll1_d6_409p6",
+	"pll1_d4_614p4",
+	"pll1_d3_819p2",
+	"pll2_d2",
+	"pll2_d3",
+	"pll2_d4",
+	"pll1_d2_1228p8",
+};
+
+CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(CLK_CSI, csi_clk, csi_clk, csi_parents,
+				 ARRAY_SIZE(csi_parents),
+				 APMU_CSI_CCIC2_CLK_RES_CTRL,
+				 APMU_CSI_CCIC2_CLK_RES_CTRL, 20, 3, BIT(15),
+				 16, 3, BIT(4), 0);
+
+static const char * const camm_parents[] = {
+	"pll1_d8_307p2",
+	"pll2_d5",
+	"pll1_d6_409p6",
+	"clock-24m",
+};
+
+CCU_MUX_DIV_GATE_DEFINE(CLK_CAMM0, camm0_clk, camm0_clk, camm_parents,
+			ARRAY_SIZE(camm_parents),
+			APMU_CSI_CCIC2_CLK_RES_CTRL, 23, 4, 8, 2,
+			BIT(28), 0);
+CCU_MUX_DIV_GATE_DEFINE(CLK_CAMM1, camm1_clk, camm1_clk, camm_parents,
+			ARRAY_SIZE(camm_parents),
+			APMU_CSI_CCIC2_CLK_RES_CTRL, 23, 4, 8, 2,
+			BIT(6), 0);
+CCU_MUX_DIV_GATE_DEFINE(CLK_CAMM2, camm2_clk, camm2_clk, camm_parents,
+			ARRAY_SIZE(camm_parents),
+			APMU_CSI_CCIC2_CLK_RES_CTRL, 23, 4, 8, 2,
+			BIT(3), 0);
+
+static const char * const isp_cpp_parents[] = {
+	"pll1_d8_307p2",
+	"pll1_d6_409p6",
+};
+
+CCU_MUX_DIV_GATE_DEFINE(CLK_ISP_CPP, isp_cpp_clk, isp_cpp_clk, isp_cpp_parents,
+			ARRAY_SIZE(isp_cpp_parents),
+			APMU_ISP_CLK_RES_CTRL, 24, 2, 26, 1,
+			BIT(28), 0);
+static const char * const isp_bus_parents[] = {
+	"pll1_d6_409p6",
+	"pll1_d5_491p52",
+	"pll1_d8_307p2",
+	"pll1_d10_245p76",
+};
+
+CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(CLK_ISP_BUS, isp_bus_clk, isp_bus_clk,
+				 isp_bus_parents, ARRAY_SIZE(isp_cpp_parents),
+				 APMU_ISP_CLK_RES_CTRL,
+				 APMU_ISP_CLK_RES_CTRL, 18, 3, BIT(23),
+				 21, 2, BIT(17), 0);
+static const char * const isp_parents[] = {
+	"pll1_d6_409p6",
+	"pll1_d5_491p52",
+	"pll1_d4_614p4",
+	"pll1_d8_307p2",
+};
+
+CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(CLK_ISP, isp_clk, isp_clk, isp_parents,
+				 ARRAY_SIZE(isp_parents),
+				 APMU_ISP_CLK_RES_CTRL,
+				 APMU_ISP_CLK_RES_CTRL,
+				 4, 3, BIT(7), 8, 2, BIT(1), 0);
+
+static const char * const dpumclk_parents[] = {
+	"pll1_d6_409p6",
+	"pll1_d5_491p52",
+	"pll1_d4_614p4",
+	"pll1_d8_307p2",
+};
+
+CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(CLK_DPU_MCLK, dpu_mclk, dpu_mclk,
+				 dpumclk_parents, ARRAY_SIZE(dpumclk_parents),
+				 APMU_LCD_CLK_RES_CTRL2, APMU_LCD_CLK_RES_CTRL1,
+				 1, 4, BIT(29), 5, 3, BIT(0), 0);
+
+static const char * const dpuesc_parents[] = {
+	"pll1_d48_51p2_ap",
+	"pll1_d52_47p26",
+	"pll1_d96_25p6",
+	"pll1_d32_76p8",
+};
+
+CCU_MUX_GATE_DEFINE(CLK_DPU_ESC, dpu_esc_clk, dpu_esc_clk, dpuesc_parents,
+		    ARRAY_SIZE(dpuesc_parents), APMU_LCD_CLK_RES_CTRL1, 0, 2,
+		    BIT(2), 0);
+
+static const char * const dpubit_parents[] = {
+	"pll1_d3_819p2",
+	"pll2_d2",
+	"pll2_d3",
+	"pll1_d2_1228p8",
+	"pll2_d4",
+	"pll2_d5",
+	"pll2_d7",
+	"pll2_d8",
+};
+
+CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(CLK_DPU_BIT, dpu_bit_clk, dpu_bit_clk,
+				 dpubit_parents, ARRAY_SIZE(dpubit_parents),
+				 APMU_LCD_CLK_RES_CTRL1,
+				 APMU_LCD_CLK_RES_CTRL1, 17, 3, BIT(31),
+				 20, 3, BIT(16), 0);
+
+static const char * const dpupx_parents[] = {
+	"pll1_d6_409p6",
+	"pll1_d5_491p52",
+	"pll1_d4_614p4",
+	"pll1_d8_307p2",
+	"pll2_d7",
+	"pll2_d8",
+};
+
+CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(CLK_DPU_PXCLK, dpu_pxclk, dpu_pxclk,
+				 dpupx_parents, ARRAY_SIZE(dpupx_parents),
+				 APMU_LCD_CLK_RES_CTRL2, APMU_LCD_CLK_RES_CTRL1,
+				 17, 4, BIT(30), 21, 3, BIT(16), 0);
+
+CCU_GATE_DEFINE(CLK_DPU_HCLK, dpu_hclk, dpu_hclk, "pmua_aclk",
+		APMU_LCD_CLK_RES_CTRL1, BIT(5), 0);
+
+static const char * const dpu_spi_parents[] = {
+	"pll1_d8_307p2",
+	"pll1_d6_409p6",
+	"pll1_d10_245p76",
+	"pll1_d11_223p4",
+	"pll1_d13_189",
+	"pll1_d23_106p8",
+	"pll2_d3",
+	"pll2_d5",
+};
+
+CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(CLK_DPU_SPI, dpu_spi_clk, dpu_spi_clk,
+				 dpu_spi_parents, ARRAY_SIZE(dpu_spi_parents),
+				 APMU_LCD_SPI_CLK_RES_CTRL,
+				 APMU_LCD_SPI_CLK_RES_CTRL, 8, 3,
+				 BIT(7), 12, 3, BIT(1), 0);
+CCU_GATE_DEFINE(CLK_DPU_SPI_HBUS, dpu_spi_hbus_clk, dpu_spi_hbus_clk,
+		"pmua_aclk", APMU_LCD_SPI_CLK_RES_CTRL, BIT(3), 0);
+CCU_GATE_DEFINE(CLK_DPU_SPIBUS, dpu_spi_bus_clk, dpu_spi_bus_clk,
+		"pmua_aclk", APMU_LCD_SPI_CLK_RES_CTRL, BIT(5), 0);
+CCU_GATE_DEFINE(CLK_DPU_SPI_ACLK, dpu_spi_aclk, dpu_spi_aclk,
+		"pmua_aclk", APMU_LCD_SPI_CLK_RES_CTRL, BIT(6), 0);
+
+static const char * const v2d_parents[] = {
+	"pll1_d5_491p52",
+	"pll1_d6_409p6",
+	"pll1_d8_307p2",
+	"pll1_d4_614p4",
+};
+
+CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(CLK_V2D, v2d_clk, v2d_clk, v2d_parents,
+				 ARRAY_SIZE(v2d_parents),
+				 APMU_LCD_CLK_RES_CTRL1,
+				 APMU_LCD_CLK_RES_CTRL1, 9, 3, BIT(28), 12, 2,
+				 BIT(8), 0);
+
+static const char * const ccic_4x_parents[] = {
+	"pll1_d5_491p52",
+	"pll1_d6_409p6",
+	"pll1_d4_614p4",
+	"pll1_d3_819p2",
+	"pll2_d2",
+	"pll2_d3",
+	"pll2_d4",
+	"pll1_d2_1228p8",
+};
+
+CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(CLK_CCIC_4X, ccic_4x_clk, ccic_4x_clk,
+				 ccic_4x_parents, ARRAY_SIZE(ccic_4x_parents),
+				 APMU_CCIC_CLK_RES_CTRL,
+				 APMU_CCIC_CLK_RES_CTRL, 18, 3,
+				 BIT(15), 23, 2, BIT(4), 0);
+
+static const char * const ccic1phy_parents[] = {
+	"pll1_d24_102p4",
+	"pll1_d48_51p2_ap",
+};
+
+CCU_MUX_GATE_DEFINE(CLK_CCIC1PHY, ccic1phy_clk, ccic1phy_clk, ccic1phy_parents,
+		    ARRAY_SIZE(ccic1phy_parents), APMU_CCIC_CLK_RES_CTRL, 7, 1,
+		    BIT(5), 0);
+
+CCU_GATE_DEFINE(CLK_SDH_AXI, sdh_axi_aclk, sdh_axi_aclk, "pmua_aclk",
+		APMU_SDH0_CLK_RES_CTRL, BIT(3), 0);
+static const char * const sdh01_parents[] = {
+	"pll1_d6_409p6",
+	"pll1_d4_614p4",
+	"pll2_d8",
+	"pll2_d5",
+	"pll1_d11_223p4",
+	"pll1_d13_189",
+	"pll1_d23_106p8",
+};
+
+CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(CLK_SDH0, sdh0_clk, sdh0_clk, sdh01_parents,
+				 ARRAY_SIZE(sdh01_parents),
+				 APMU_SDH0_CLK_RES_CTRL,
+				 APMU_SDH0_CLK_RES_CTRL, 8, 3, BIT(11), 5, 3,
+				 BIT(4), 0);
+CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(CLK_SDH1, sdh1_clk, sdh1_clk, sdh01_parents,
+				 ARRAY_SIZE(sdh01_parents),
+				 APMU_SDH1_CLK_RES_CTRL,
+				 APMU_SDH1_CLK_RES_CTRL, 8, 3, BIT(11), 5, 3,
+				 BIT(4), 0);
+static const char * const sdh2_parents[] = {
+	"pll1_d6_409p6",
+	"pll1_d4_614p4",
+	"pll2_d8",
+	"pll1_d3_819p2",
+	"pll1_d11_223p4",
+	"pll1_d13_189",
+	"pll1_d23_106p8",
+};
+
+CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(CLK_SDH2, sdh2_clk, sdh2_clk, sdh2_parents,
+				 ARRAY_SIZE(sdh2_parents),
+				 APMU_SDH2_CLK_RES_CTRL,
+				 APMU_SDH2_CLK_RES_CTRL, 8, 3, BIT(11), 5, 3,
+				 BIT(4), 0);
+
+CCU_GATE_DEFINE(CLK_USB_AXI, usb_axi_clk, usb_axi_clk, "pmua_aclk",
+		APMU_USB_CLK_RES_CTRL, BIT(1), 0);
+CCU_GATE_DEFINE(CLK_USB_P1, usb_p1_aclk, usb_p1_aclk, "pmua_aclk",
+		APMU_USB_CLK_RES_CTRL, BIT(5), 0);
+CCU_GATE_DEFINE(CLK_USB30, usb30_clk, usb30_clk, "pmua_aclk",
+		APMU_USB_CLK_RES_CTRL, BIT(8), 0);
+
+static const char * const qspi_parents[] = {
+	"pll1_d6_409p6",
+	"pll2_d8",
+	"pll1_d8_307p2",
+	"pll1_d10_245p76",
+	"pll1_d11_223p4",
+	"pll1_d23_106p8",
+	"pll1_d5_491p52",
+	"pll1_d13_189",
+};
+
+CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(CLK_QSPI, qspi_clk, qspi_clk, qspi_parents,
+				 ARRAY_SIZE(qspi_parents),
+				 APMU_QSPI_CLK_RES_CTRL,
+				 APMU_QSPI_CLK_RES_CTRL, 9, 3, BIT(12), 6, 3,
+				 BIT(4), 0);
+CCU_GATE_DEFINE(CLK_QSPI_BUS, qspi_bus_clk, qspi_bus_clk, "pmua_aclk",
+		APMU_QSPI_CLK_RES_CTRL, BIT(3), 0);
+CCU_GATE_DEFINE(CLK_DMA, dma_clk, dma_clk, "pmua_aclk", APMU_DMA_CLK_RES_CTRL,
+		BIT(3), 0);
+
+static const char * const aes_parents[] = {
+	"pll1_d12_204p8",
+	"pll1_d24_102p4",
+};
+
+CCU_MUX_GATE_DEFINE(CLK_AES, aes_clk, aes_clk, aes_parents,
+		    ARRAY_SIZE(aes_parents), APMU_AES_CLK_RES_CTRL, 6, 1,
+		    BIT(5), 0);
+
+static const char * const vpu_parents[] = {
+	"pll1_d4_614p4",
+	"pll1_d5_491p52",
+	"pll1_d3_819p2",
+	"pll1_d6_409p6",
+	"pll3_d6",
+	"pll2_d3",
+	"pll2_d4",
+	"pll2_d5",
+};
+
+CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(CLK_VPU, vpu_clk, vpu_clk, vpu_parents,
+				 ARRAY_SIZE(vpu_parents), APMU_VPU_CLK_RES_CTRL,
+				 APMU_VPU_CLK_RES_CTRL, 13, 3, BIT(21), 10, 3,
+				 BIT(3), 0);
+
+static const char * const gpu_parents[] = {
+	"pll1_d4_614p4",
+	"pll1_d5_491p52",
+	"pll1_d3_819p2",
+	"pll1_d6_409p6",
+	"pll3_d6",
+	"pll2_d3",
+	"pll2_d4",
+	"pll2_d5",
+};
+
+CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(CLK_GPU, gpu_clk, gpu_clk, gpu_parents,
+				 ARRAY_SIZE(gpu_parents), APMU_GPU_CLK_RES_CTRL,
+				 APMU_GPU_CLK_RES_CTRL, 12, 3, BIT(15), 18, 3,
+				 BIT(4), 0);
+
+static const char * const audio_parents[] = {
+	"pll1_aud_245p7",
+	"pll1_d8_307p2",
+	"pll1_d6_409p6",
+};
+
+CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(CLK_AUDIO, audio_clk, audio_clk, audio_parents,
+				 ARRAY_SIZE(audio_parents),
+				 APMU_AUDIO_CLK_RES_CTRL,
+				 APMU_AUDIO_CLK_RES_CTRL, 4, 3, BIT(15),
+				 7, 3, BIT(12), 0);
+
+static const char * const hdmi_parents[] = {
+	"pll1_d6_409p6",
+	"pll1_d5_491p52",
+	"pll1_d4_614p4",
+	"pll1_d8_307p2",
+};
+
+CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(CLK_HDMI, hdmi_mclk, hdmi_mclk, hdmi_parents,
+				 ARRAY_SIZE(hdmi_parents),
+				 APMU_HDMI_CLK_RES_CTRL,
+				 APMU_HDMI_CLK_RES_CTRL, 1, 4, BIT(29), 5,
+				 3, BIT(0), 0);
+
+CCU_GATE_DEFINE(CLK_PCIE0_MASTER, pcie0_master_clk, pcie0_master_clk,
+		"pmua_aclk", APMU_PCIE_CLK_RES_CTRL_0, BIT(2), 0);
+CCU_GATE_DEFINE(CLK_PCIE0_SLAVE, pcie0_slave_clk, pcie0_slave_clk, "pmua_aclk",
+		APMU_PCIE_CLK_RES_CTRL_0, BIT(1), 0);
+CCU_GATE_DEFINE(CLK_PCIE0_DBI, pcie0_dbi_clk, pcie0_dbi_clk, "pmua_aclk",
+		APMU_PCIE_CLK_RES_CTRL_0, BIT(0), 0);
+
+CCU_GATE_DEFINE(CLK_PCIE1_MASTER, pcie1_master_clk, pcie1_master_clk,
+		"pmua_aclk", APMU_PCIE_CLK_RES_CTRL_1, BIT(2), 0);
+CCU_GATE_DEFINE(CLK_PCIE1_SLAVE, pcie1_slave_clk, pcie1_slave_clk, "pmua_aclk",
+		APMU_PCIE_CLK_RES_CTRL_1, BIT(1), 0);
+CCU_GATE_DEFINE(CLK_PCIE1_DBI, pcie1_dbi_clk, pcie1_dbi_clk, "pmua_aclk",
+		APMU_PCIE_CLK_RES_CTRL_1, BIT(0), 0);
+
+CCU_GATE_DEFINE(CLK_PCIE2_MASTER, pcie2_master_clk, pcie2_master_clk,
+		"pmua_aclk", APMU_PCIE_CLK_RES_CTRL_2, BIT(2), 0);
+CCU_GATE_DEFINE(CLK_PCIE2_SLAVE, pcie2_slave_clk, pcie2_slave_clk, "pmua_aclk",
+		APMU_PCIE_CLK_RES_CTRL_2, BIT(1), 0);
+CCU_GATE_DEFINE(CLK_PCIE2_DBI, pcie2_dbi_clk, pcie2_dbi_clk, "pmua_aclk",
+		APMU_PCIE_CLK_RES_CTRL_2, BIT(0), 0);
+
+CCU_GATE_DEFINE(CLK_EMAC0_BUS, emac0_bus_clk, emac0_bus_clk, "pmua_aclk",
+		APMU_EMAC0_CLK_RES_CTRL, BIT(0), 0);
+CCU_GATE_DEFINE(CLK_EMAC0_PTP, emac0_ptp_clk, emac0_ptp_clk, "pll2_d6",
+		APMU_EMAC0_CLK_RES_CTRL, BIT(15), 0);
+CCU_GATE_DEFINE(CLK_EMAC1_BUS, emac1_bus_clk, emac1_bus_clk, "pmua_aclk",
+		APMU_EMAC1_CLK_RES_CTRL, BIT(0), 0);
+CCU_GATE_DEFINE(CLK_EMAC1_PTP, emac1_ptp_clk, emac1_ptp_clk, "pll2_d6",
+		APMU_EMAC1_CLK_RES_CTRL, BIT(15), 0);
+
+#endif
+/* APMU clocks end */
+
+static struct clk *k1_ccu_pll_clks[] = {
+	&pll1.common.clk,
+	&pll2.common.clk,
+	&pll3.common.clk,
+	&pll1_d2.common.clk,
+	&pll1_d3.common.clk,
+	&pll1_d4.common.clk,
+	&pll1_d5.common.clk,
+	&pll1_d6.common.clk,
+	&pll1_d7.common.clk,
+	&pll1_d8.common.clk,
+	&pll1_d11_223p4.common.clk,
+	&pll1_d13_189.common.clk,
+	&pll1_d23_106p8.common.clk,
+	&pll1_d64_38p4.common.clk,
+	&pll1_aud_245p7.common.clk,
+	&pll1_aud_24p5.common.clk,
+	&pll2_d1.common.clk,
+	&pll2_d2.common.clk,
+	&pll2_d3.common.clk,
+	&pll2_d4.common.clk,
+	&pll2_d5.common.clk,
+	&pll2_d6.common.clk,
+	&pll2_d7.common.clk,
+	&pll2_d8.common.clk,
+	&pll3_d1.common.clk,
+	&pll3_d2.common.clk,
+	&pll3_d3.common.clk,
+	&pll3_d4.common.clk,
+	&pll3_d5.common.clk,
+	&pll3_d6.common.clk,
+	&pll3_d7.common.clk,
+	&pll3_d8.common.clk,
+	&pll3_80.common.clk,
+	&pll3_40.common.clk,
+	&pll3_20.common.clk,
+};
+
+static const struct spacemit_ccu_data k1_ccu_pll_data = {
+	.clks		= k1_ccu_pll_clks,
+	.num		= ARRAY_SIZE(k1_ccu_pll_clks),
+	.offset		= K1_PLL_ID,
+};
+
+#if IS_ENABLED(CONFIG_SPL_BUILD)
+static struct clk *k1_ccu_mpmu_clks[] = {
+	&pll1_d8_307p2.common.clk,
+	&pll1_d32_76p8.common.clk,
+	&pll1_d40_61p44.common.clk,
+	&pll1_d16_153p6.common.clk,
+	&pll1_d24_102p4.common.clk,
+	&pll1_d48_51p2.common.clk,
+	&pll1_d48_51p2_ap.common.clk,
+	&pll1_m3d128_57p6.common.clk,
+	&pll1_d96_25p6.common.clk,
+	&pll1_d192_12p8.common.clk,
+	&pll1_d192_12p8_wdt.common.clk,
+	&pll1_d384_6p4.common.clk,
+	&pll1_d768_3p2.common.clk,
+	&pll1_d1536_1p6.common.clk,
+	&pll1_d3072_0p8.common.clk,
+	&pll1_d6_409p6.common.clk,
+	&pll1_d12_204p8.common.clk,
+	&pll1_d5_491p52.common.clk,
+	&pll1_d10_245p76.common.clk,
+	&pll1_d4_614p4.common.clk,
+	&pll1_d52_47p26.common.clk,
+	&pll1_d78_31p5.common.clk,
+	&pll1_d3_819p2.common.clk,
+	&pll1_d2_1228p8.common.clk,
+	&slow_uart.common.clk,
+	&slow_uart1_14p74.common.clk,
+	&slow_uart2_48.common.clk,
+};
+#else
+static struct clk *k1_ccu_mpmu_clks[] = {
+	&pll1_d8_307p2.common.clk,
+	&pll1_d32_76p8.common.clk,
+	&pll1_d40_61p44.common.clk,
+	&pll1_d16_153p6.common.clk,
+	&pll1_d24_102p4.common.clk,
+	&pll1_d48_51p2.common.clk,
+	&pll1_d48_51p2_ap.common.clk,
+	&pll1_m3d128_57p6.common.clk,
+	&pll1_d96_25p6.common.clk,
+	&pll1_d192_12p8.common.clk,
+	&pll1_d192_12p8_wdt.common.clk,
+	&pll1_d384_6p4.common.clk,
+	&pll1_d768_3p2.common.clk,
+	&pll1_d1536_1p6.common.clk,
+	&pll1_d3072_0p8.common.clk,
+	&pll1_d6_409p6.common.clk,
+	&pll1_d12_204p8.common.clk,
+	&pll1_d5_491p52.common.clk,
+	&pll1_d10_245p76.common.clk,
+	&pll1_d4_614p4.common.clk,
+	&pll1_d52_47p26.common.clk,
+	&pll1_d78_31p5.common.clk,
+	&pll1_d3_819p2.common.clk,
+	&pll1_d2_1228p8.common.clk,
+	&slow_uart.common.clk,
+	&slow_uart1_14p74.common.clk,
+	&slow_uart2_48.common.clk,
+	&wdt_clk.common.clk,
+	&apb_clk.common.clk,
+	&ripc_clk.common.clk,
+	&i2s_153p6.common.clk,
+	&i2s_153p6_base.common.clk,
+	&i2s_sysclk_src.common.clk,
+	&i2s_sysclk.common.clk,
+	&i2s_bclk_factor.common.clk,
+	&i2s_bclk.common.clk,
+	&wdt_bus_clk.common.clk,
+};
+#endif
+
+static const struct spacemit_ccu_data k1_ccu_mpmu_data = {
+	.clks		= k1_ccu_mpmu_clks,
+	.num		= ARRAY_SIZE(k1_ccu_mpmu_clks),
+	.offset		= K1_MPMU_ID,
+};
+
+#if IS_ENABLED(CONFIG_SPL_BUILD)
+static struct clk *k1_ccu_apbc_clks[] = {
+	&uart0_clk.common.clk,
+	&twsi2_clk.common.clk,
+	&twsi8_clk.common.clk,
+};
+#else
+static struct clk *k1_ccu_apbc_clks[] = {
+	&uart0_clk.common.clk,
+	&uart2_clk.common.clk,
+	&uart3_clk.common.clk,
+	&uart4_clk.common.clk,
+	&uart5_clk.common.clk,
+	&uart6_clk.common.clk,
+	&uart7_clk.common.clk,
+	&uart8_clk.common.clk,
+	&uart9_clk.common.clk,
+	&gpio_clk.common.clk,
+	&pwm0_clk.common.clk,
+	&pwm1_clk.common.clk,
+	&pwm2_clk.common.clk,
+	&pwm3_clk.common.clk,
+	&pwm4_clk.common.clk,
+	&pwm5_clk.common.clk,
+	&pwm6_clk.common.clk,
+	&pwm7_clk.common.clk,
+	&pwm8_clk.common.clk,
+	&pwm9_clk.common.clk,
+	&pwm10_clk.common.clk,
+	&pwm11_clk.common.clk,
+	&pwm12_clk.common.clk,
+	&pwm13_clk.common.clk,
+	&pwm14_clk.common.clk,
+	&pwm15_clk.common.clk,
+	&pwm16_clk.common.clk,
+	&pwm17_clk.common.clk,
+	&pwm18_clk.common.clk,
+	&pwm19_clk.common.clk,
+	&ssp3_clk.common.clk,
+	&rtc_clk.common.clk,
+	&twsi0_clk.common.clk,
+	&twsi1_clk.common.clk,
+	&twsi2_clk.common.clk,
+	&twsi4_clk.common.clk,
+	&twsi5_clk.common.clk,
+	&twsi6_clk.common.clk,
+	&twsi7_clk.common.clk,
+	&twsi8_clk.common.clk,
+	&timers1_clk.common.clk,
+	&timers2_clk.common.clk,
+	&aib_clk.common.clk,
+	&onewire_clk.common.clk,
+	&sspa0_clk.common.clk,
+	&sspa1_clk.common.clk,
+	&dro_clk.common.clk,
+	&ir_clk.common.clk,
+	&tsen_clk.common.clk,
+	&ipc_ap2aud_clk.common.clk,
+	&can0_clk.common.clk,
+	&can0_bus_clk.common.clk,
+	&uart0_bus_clk.common.clk,
+	&uart2_bus_clk.common.clk,
+	&uart3_bus_clk.common.clk,
+	&uart4_bus_clk.common.clk,
+	&uart5_bus_clk.common.clk,
+	&uart6_bus_clk.common.clk,
+	&uart7_bus_clk.common.clk,
+	&uart8_bus_clk.common.clk,
+	&uart9_bus_clk.common.clk,
+	&gpio_bus_clk.common.clk,
+	&pwm0_bus_clk.common.clk,
+	&pwm1_bus_clk.common.clk,
+	&pwm2_bus_clk.common.clk,
+	&pwm3_bus_clk.common.clk,
+	&pwm4_bus_clk.common.clk,
+	&pwm5_bus_clk.common.clk,
+	&pwm6_bus_clk.common.clk,
+	&pwm7_bus_clk.common.clk,
+	&pwm8_bus_clk.common.clk,
+	&pwm9_bus_clk.common.clk,
+	&pwm10_bus_clk.common.clk,
+	&pwm11_bus_clk.common.clk,
+	&pwm12_bus_clk.common.clk,
+	&pwm13_bus_clk.common.clk,
+	&pwm14_bus_clk.common.clk,
+	&pwm15_bus_clk.common.clk,
+	&pwm16_bus_clk.common.clk,
+	&pwm17_bus_clk.common.clk,
+	&pwm18_bus_clk.common.clk,
+	&pwm19_bus_clk.common.clk,
+	&ssp3_bus_clk.common.clk,
+	&rtc_bus_clk.common.clk,
+	&twsi0_bus_clk.common.clk,
+	&twsi1_bus_clk.common.clk,
+	&twsi2_bus_clk.common.clk,
+	&twsi4_bus_clk.common.clk,
+	&twsi5_bus_clk.common.clk,
+	&twsi6_bus_clk.common.clk,
+	&twsi7_bus_clk.common.clk,
+	&twsi8_bus_clk.common.clk,
+	&timers1_bus_clk.common.clk,
+	&timers2_bus_clk.common.clk,
+	&aib_bus_clk.common.clk,
+	&onewire_bus_clk.common.clk,
+	&sspa0_bus_clk.common.clk,
+	&sspa1_bus_clk.common.clk,
+	&tsen_bus_clk.common.clk,
+	&ipc_ap2aud_bus_clk.common.clk,
+	&sspa0_i2s_bclk.common.clk,
+	&sspa1_i2s_bclk.common.clk,
+};
+#endif
+
+static const struct spacemit_ccu_data k1_ccu_apbc_data = {
+	.clks		= k1_ccu_apbc_clks,
+	.num		= ARRAY_SIZE(k1_ccu_apbc_clks),
+	.offset		= K1_APBC_ID,
+};
+
+#if IS_ENABLED(CONFIG_SPL_BUILD)
+static struct clk *k1_ccu_apmu_clks[] = {
+	&emmc_clk.common.clk,
+	&emmc_x_clk.common.clk,
+	&pmua_aclk.common.clk,
+	&emmc_bus_clk.common.clk,
+};
+#else
+static struct clk *k1_ccu_apmu_clks[] = {
+	&cci550_clk.common.clk,
+	&cpu_c0_hi_clk.common.clk,
+	&cpu_c0_core_clk.common.clk,
+	&cpu_c0_ace_clk.common.clk,
+	&cpu_c0_tcm_clk.common.clk,
+	&cpu_c1_hi_clk.common.clk,
+	&cpu_c1_core_clk.common.clk,
+	&cpu_c1_ace_clk.common.clk,
+	&ccic_4x_clk.common.clk,
+	&ccic1phy_clk.common.clk,
+	&sdh_axi_aclk.common.clk,
+	&sdh0_clk.common.clk,
+	&sdh1_clk.common.clk,
+	&sdh2_clk.common.clk,
+	&usb_p1_aclk.common.clk,
+	&usb_axi_clk.common.clk,
+	&usb30_clk.common.clk,
+	&qspi_clk.common.clk,
+	&qspi_bus_clk.common.clk,
+	&dma_clk.common.clk,
+	&aes_clk.common.clk,
+	&vpu_clk.common.clk,
+	&gpu_clk.common.clk,
+	&emmc_clk.common.clk,
+	&emmc_x_clk.common.clk,
+	&audio_clk.common.clk,
+	&hdmi_mclk.common.clk,
+	&pmua_aclk.common.clk,
+	&pcie0_master_clk.common.clk,
+	&pcie0_slave_clk.common.clk,
+	&pcie0_dbi_clk.common.clk,
+	&pcie1_master_clk.common.clk,
+	&pcie1_slave_clk.common.clk,
+	&pcie1_dbi_clk.common.clk,
+	&pcie2_master_clk.common.clk,
+	&pcie2_slave_clk.common.clk,
+	&pcie2_dbi_clk.common.clk,
+	&emac0_bus_clk.common.clk,
+	&emac0_ptp_clk.common.clk,
+	&emac1_bus_clk.common.clk,
+	&emac1_ptp_clk.common.clk,
+	&jpg_clk.common.clk,
+	&ccic2phy_clk.common.clk,
+	&ccic3phy_clk.common.clk,
+	&csi_clk.common.clk,
+	&camm0_clk.common.clk,
+	&camm1_clk.common.clk,
+	&camm2_clk.common.clk,
+	&isp_cpp_clk.common.clk,
+	&isp_bus_clk.common.clk,
+	&isp_clk.common.clk,
+	&dpu_mclk.common.clk,
+	&dpu_esc_clk.common.clk,
+	&dpu_bit_clk.common.clk,
+	&dpu_pxclk.common.clk,
+	&dpu_hclk.common.clk,
+	&dpu_spi_clk.common.clk,
+	&dpu_spi_hbus_clk.common.clk,
+	&dpu_spi_bus_clk.common.clk,
+	&dpu_spi_aclk.common.clk,
+	&v2d_clk.common.clk,
+	&emmc_bus_clk.common.clk,
+};
+#endif
+
+static int clk_k1_enable(struct clk *clk)
+{
+	const struct spacemit_ccu_data *data;
+	struct clk *c;
+	struct clk *pclk;
+	int ret, i;
+
+	data = (struct spacemit_ccu_data *)dev_get_driver_data(clk->dev);
+	for (i = 0; i < data->num; i++) {
+		if (clk->id == data->clks[i]->id) {
+			c = data->clks[i];
+			break;
+		}
+	}
+	if (i == data->num)
+		c = clk;
+
+	pclk = clk_get_parent(c);
+	if (!IS_ERR_OR_NULL(pclk)) {
+		ret = ccf_clk_enable(pclk);
+		if (ret)
+			return ret;
+	}
+	ret = ccu_gate_enable(c);
+	return ret;
+}
+
+static int clk_k1_disable(struct clk *clk)
+{
+	const struct spacemit_ccu_data *data;
+	struct clk *c;
+	struct clk *pclk;
+	int ret, i;
+
+	data = (struct spacemit_ccu_data *)dev_get_driver_data(clk->dev);
+	for (i = 0; i < data->num; i++) {
+		if (clk->id == data->clks[i]->id) {
+			c = data->clks[i];
+			break;
+		}
+	}
+	if (i == data->num)
+		c = clk;
+
+	pclk = clk_get_parent(c);
+	if (!IS_ERR_OR_NULL(pclk)) {
+		ret = ccf_clk_disable(pclk);
+		if (ret)
+			return ret;
+	}
+	ret = ccu_gate_disable(c);
+	return ret;
+}
+
+#define K1_CLK_OPS(name)				\
+static const struct clk_ops k1_##name##_clk_ops = {	\
+		.set_rate = ccf_clk_set_rate,		\
+		.get_rate = ccf_clk_get_rate,		\
+		.enable = clk_k1_enable,		\
+		.disable = clk_k1_disable,		\
+		.set_parent = ccf_clk_set_parent,	\
+		.of_xlate = k1_##name##_clk_of_xlate,	\
+}
+
+static const struct spacemit_ccu_data k1_ccu_apmu_data = {
+	.clks		= k1_ccu_apmu_clks,
+	.num		= ARRAY_SIZE(k1_ccu_apmu_clks),
+	.offset		= K1_APMU_ID,
+};
+
+struct clk_retry_item {
+	struct ccu_common *common;
+	struct list_head link;
+};
+
+static LIST_HEAD(retry_list);
+
+static int k1_clk_retry_register(void)
+{
+	struct clk_retry_item *item, *tmp;
+	int retries = 5;
+	int ret;
+
+	while (!list_empty(&retry_list) && retries) {
+		list_for_each_entry_safe(item, tmp, &retry_list, link) {
+			struct ccu_common *common = item->common;
+
+			ret = common->init(common);
+			if (ret)
+				return ret;
+
+			list_del(&item->link);
+			kfree(item);
+		}
+		retries--;
+	}
+
+	return 0;
+}
+
+static int k1_clk_register(struct udevice *dev, struct regmap *regmap,
+			   struct regmap *lock_regmap,
+			   const struct spacemit_ccu_data *data)
+{
+	int i, ret;
+
+	for (i = 0; i < data->num; i++) {
+		struct clk *clk = data->clks[i];
+		struct ccu_common *common;
+
+		if (!clk)
+			continue;
+
+		common = clk_to_ccu_common(clk);
+		common->regmap = regmap;
+		common->lock_regmap = lock_regmap;
+
+		clk->id = common->clk.id + data->offset;
+
+		ret = common->init(common);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int k1_clk_probe(struct udevice *dev)
+{
+	struct regmap *base_regmap, *lock_regmap = NULL;
+	const struct spacemit_ccu_data *data;
+	int ret;
+
+	clk_register_fixed_rate(NULL, "clock-1m", 1000000);
+	clk_register_fixed_rate(NULL, "clock-24m", 24000000);
+	clk_register_fixed_rate(NULL, "clock-3m", 3000000);
+	clk_register_fixed_rate(NULL, "clock-32k", 32000);
+
+	ret = regmap_init_mem(dev_ofnode(dev), &base_regmap);
+	if (ret)
+		return ret;
+
+	/*
+	 * The lock status of PLLs locate in MPMU region, while PLLs themselves
+	 * are in APBS region. Reference to MPMU syscon is required to check PLL
+	 * status.
+	 */
+	if (device_is_compatible(dev, "spacemit,k1-pll")) {
+		struct ofnode_phandle_args mpmu_args;
+
+		ret = dev_read_phandle_with_args(dev, "spacemit,mpmu", NULL, 0, 0,
+						 &mpmu_args);
+		if (ret)
+			return ret;
+
+		ret = regmap_init_mem(mpmu_args.node, &lock_regmap);
+		if (ret)
+			return ret;
+	}
+
+	data = (struct spacemit_ccu_data *)dev_get_driver_data(dev);
+
+	ret = k1_clk_register(dev, base_regmap, lock_regmap, data);
+	if (ret)
+		return -EPROBE_DEFER;
+
+	return k1_clk_retry_register();
+}
+
+static int k1_apbc_clk_probe(struct udevice *dev)
+{
+	struct regmap *base_regmap, *lock_regmap = NULL;
+	const struct spacemit_ccu_data *data;
+	int ret;
+	struct clk clk;
+
+	ret = regmap_init_mem(dev_ofnode(dev), &base_regmap);
+	if (ret)
+		return ret;
+
+	clk_register_fixed_rate(NULL, "clock-1m", 1000000);
+	clk_register_fixed_rate(NULL, "clock-24m", 24000000);
+	clk_register_fixed_rate(NULL, "clock-3m", 3000000);
+	clk_register_fixed_rate(NULL, "clock-32k", 32000);
+
+	/* probe PLL controller */
+	ret = clk_get_by_index(dev, 5, &clk);
+	if (ret)
+		return -EPROBE_DEFER;
+
+	/* probe MPMU controller */
+	ret = clk_get_by_index(dev, 4, &clk);
+	if (ret)
+		return -EPROBE_DEFER;
+
+	ret = regmap_init_mem(dev_ofnode(dev), &base_regmap);
+	if (ret)
+		return ret;
+
+	/*
+	 * The lock status of PLLs locate in MPMU region, while PLLs themselves
+	 * are in APBS region. Reference to MPMU syscon is required to check PLL
+	 * status.
+	 */
+	if (device_is_compatible(dev, "spacemit,k1-pll")) {
+		struct ofnode_phandle_args mpmu_args;
+
+		ret = dev_read_phandle_with_args(dev, "spacemit,mpmu", NULL, 0, 0,
+						 &mpmu_args);
+		if (ret)
+			return ret;
+
+		ret = regmap_init_mem(mpmu_args.node, &lock_regmap);
+		if (ret)
+			return ret;
+	}
+
+	data = (struct spacemit_ccu_data *)dev_get_driver_data(dev);
+
+	ret = k1_clk_register(dev, base_regmap, lock_regmap, data);
+	if (ret)
+		return -EPROBE_DEFER;
+
+	return k1_clk_retry_register();
+}
+
+static int k1_pll_clk_of_xlate(struct clk *clk, struct ofnode_phandle_args *args)
+{
+	if (args->args_count > 1) {
+		debug("Invalid args_count: %d\n", args->args_count);
+		return -EINVAL;
+	}
+
+	if (args->args_count)
+		clk->id = K1_PLL_ID + args->args[0];
+	else
+		clk->id = K1_PLL_ID;
+
+	return 0;
+}
+
+static int k1_mpmu_clk_of_xlate(struct clk *clk, struct ofnode_phandle_args *args)
+{
+	if (args->args_count > 1) {
+		debug("Invalid args_count: %d\n", args->args_count);
+		return -EINVAL;
+	}
+
+	if (args->args_count)
+		clk->id = K1_MPMU_ID + args->args[0];
+	else
+		clk->id = K1_MPMU_ID;
+
+	return 0;
+}
+
+static int k1_apbc_clk_of_xlate(struct clk *clk, struct ofnode_phandle_args *args)
+{
+	if (args->args_count > 1) {
+		debug("Invalid args_count: %d\n", args->args_count);
+		return -EINVAL;
+	}
+
+	if (args->args_count)
+		clk->id = K1_APBC_ID + args->args[0];
+	else
+		clk->id = K1_APBC_ID;
+
+	return 0;
+}
+
+static int k1_apmu_clk_of_xlate(struct clk *clk, struct ofnode_phandle_args *args)
+{
+	if (args->args_count > 1) {
+		debug("Invalid args_count: %d\n", args->args_count);
+		return -EINVAL;
+	}
+
+	if (args->args_count)
+		clk->id = K1_APMU_ID + args->args[0];
+	else
+		clk->id = K1_APMU_ID;
+
+	return 0;
+}
+
+static const struct udevice_id k1_pll_clk_match[] = {
+	{ .compatible = "spacemit,k1-pll",
+	      .data = (ulong)&k1_ccu_pll_data },
+	{ /* sentinel */ },
+};
+
+K1_CLK_OPS(pll);
+
+U_BOOT_DRIVER(k1_pll_clk) = {
+	.name		= "k1_pll_clk",
+	.id		= UCLASS_CLK,
+	.of_match	= k1_pll_clk_match,
+	.probe		= k1_clk_probe,
+	.ops		= &k1_pll_clk_ops,
+	.flags		= DM_FLAG_PRE_RELOC,
+};
+
+static const struct udevice_id k1_mpmu_clk_match[] = {
+	{ .compatible = "spacemit,k1-syscon-mpmu",
+	  .data = (ulong)&k1_ccu_mpmu_data },
+	{ /* sentinel */ },
+};
+
+K1_CLK_OPS(mpmu);
+
+U_BOOT_DRIVER(k1_mpmu_clk) = {
+	.name		= "k1_mpmu_clk",
+	.id		= UCLASS_CLK,
+	.of_match	= k1_mpmu_clk_match,
+	.probe		= k1_clk_probe,
+	.ops		= &k1_mpmu_clk_ops,
+	.flags		= DM_FLAG_PRE_RELOC,
+};
+
+static const struct udevice_id k1_apbc_clk_match[] = {
+	{ .compatible = "spacemit,k1-syscon-apbc",
+	  .data = (ulong)&k1_ccu_apbc_data },
+	{ /* sentinel */ },
+};
+
+K1_CLK_OPS(apbc);
+
+U_BOOT_DRIVER(k1_apbc_clk) = {
+	.name		= "k1_apbc_clk",
+	.id		= UCLASS_CLK,
+	.of_match	= k1_apbc_clk_match,
+	.probe		= k1_apbc_clk_probe,
+	.ops		= &k1_apbc_clk_ops,
+	.flags		= DM_FLAG_PRE_RELOC,
+};
+
+static const struct udevice_id k1_apmu_clk_match[] = {
+	{ .compatible = "spacemit,k1-syscon-apmu",
+	  .data = (ulong)&k1_ccu_apmu_data },
+	{ /* sentinel */ },
+};
+
+K1_CLK_OPS(apmu);
+
+U_BOOT_DRIVER(k1_apmu_clk) = {
+	.name		= "k1_apmu_clk",
+	.id		= UCLASS_CLK,
+	.of_match	= k1_apmu_clk_match,
+	.probe		= k1_clk_probe,
+	.ops		= &k1_apmu_clk_ops,
+	.flags		= DM_FLAG_PRE_RELOC,
+};
+
+static const struct udevice_id k1_rcpu_clk_match[] = {
+	{ .compatible = "spacemit,k1-syscon-rcpu" },
+	{ /* sentinel */ },
+};
+
+U_BOOT_DRIVER(k1_rcpu_clk) = {
+	.name		= "k1_rcpu_clk",
+	.id		= UCLASS_CLK,
+	.of_match	= k1_rcpu_clk_match,
+	.flags		= DM_FLAG_PRE_RELOC,
+};
+
+static const struct udevice_id k1_rcpu2_clk_match[] = {
+	{ .compatible = "spacemit,k1-syscon-rcpu2" },
+	{ /* sentinel */ },
+};
+
+U_BOOT_DRIVER(k1_rcpu2_clk) = {
+	.name		= "k1_rcpu2_clk",
+	.id		= UCLASS_CLK,
+	.of_match	= k1_rcpu2_clk_match,
+	.flags		= DM_FLAG_PRE_RELOC,
+};
+
+static const struct udevice_id k1_apbc2_clk_match[] = {
+	{ .compatible = "spacemit,k1-syscon-apbc2" },
+	{ /* sentinel */ },
+};
+
+U_BOOT_DRIVER(k1_apbc2_clk) = {
+	.name		= "k1_apbc2_clk",
+	.id		= UCLASS_CLK,
+	.of_match	= k1_apbc2_clk_match,
+	.flags		= DM_FLAG_PRE_RELOC,
+};
diff --git a/drivers/clk/spacemit/clk_common.h b/drivers/clk/spacemit/clk_common.h
new file mode 100644
index 00000000000..ea5ebf57784
--- /dev/null
+++ b/drivers/clk/spacemit/clk_common.h
@@ -0,0 +1,79 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2024 SpacemiT Technology Co. Ltd
+ * Copyright (c) 2024-2025 Haylen Chu <heylenay@4d2.org>
+ * Copyright (c) 2025 Junhui Liu <junhui.liu@pigmoral.tech>
+ * Copyright (c) 2025-2026 RISCstar Ltd.
+ *
+ *  Authors: Haylen Chu <heylenay@4d2.org>
+ */
+
+#ifndef _CLK_COMMON_H_
+#define _CLK_COMMON_H_
+
+#include <linux/clk-provider.h>
+
+struct ccu_common;
+
+typedef int (*ccu_init_fn)(struct ccu_common *common);
+
+struct ccu_common {
+	struct regmap *regmap;
+	struct regmap *lock_regmap;
+	const char *name;
+	const char * const *parents;
+	size_t num_parents;
+	ccu_init_fn init;
+
+	union {
+		/* For DDN and MIX */
+		struct {
+			u32 reg_ctrl;
+			u32 reg_fc;
+			u32 mask_fc;
+		};
+
+		/* For PLL */
+		struct {
+			u32 reg_swcr1;
+			u32 reg_swcr3;
+		};
+	};
+
+	struct clk clk;
+};
+
+#define CCU_COMMON(_id, _name, _parent, _init, _flags)			\
+	.name		= #_name,					\
+	.parents	= (const char *[]) { _parent },			\
+	.num_parents	= 1,						\
+	.init		= _init,					\
+	.clk		= { .flags = _flags, .id = _id, }		\
+
+#define CCU_COMMON_PARENTS(_id, _name, _parents, _num_p, _init, _flags)	\
+	.name		= #_name,					\
+	.parents	= _parents,					\
+	.num_parents	= _num_p,					\
+	.init		= _init,					\
+	.clk		= { .flags = _flags, .id = _id, }		\
+
+static inline struct ccu_common *clk_to_ccu_common(struct clk *clk)
+{
+	return container_of(clk, struct ccu_common, clk);
+}
+
+#define ccu_read(c, reg)						\
+	({								\
+		struct ccu_common * const __ccu = (c);			\
+		u32 tmp;						\
+		regmap_read(__ccu->regmap, __ccu->reg_##reg, &tmp);	\
+		tmp;							\
+	 })
+#define ccu_update(c, reg, mask, val) \
+	({								\
+		struct ccu_common * const __ccu = (c);			\
+		regmap_update_bits(__ccu->regmap, __ccu->reg_##reg,	\
+				   mask, val);				\
+	})
+
+#endif /* _CLK_COMMON_H_ */
diff --git a/drivers/clk/spacemit/clk_ddn.c b/drivers/clk/spacemit/clk_ddn.c
new file mode 100644
index 00000000000..7b93f30d5c3
--- /dev/null
+++ b/drivers/clk/spacemit/clk_ddn.c
@@ -0,0 +1,93 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2024 SpacemiT Technology Co. Ltd
+ * Copyright (c) 2024-2025 Haylen Chu <heylenay@4d2.org>
+ * Copyright (c) 2025 Junhui Liu <junhui.liu@pigmoral.tech>
+ *  Authors: Haylen Chu <heylenay@4d2.org>
+ *
+ * DDN stands for "Divider Denominator Numerator", it's M/N clock with a
+ * constant x2 factor. This clock hardware follows the equation below,
+ *
+ *	      numerator       Fin
+ *	2 * ------------- = -------
+ *	     denominator      Fout
+ *
+ * Thus, Fout could be calculated with,
+ *
+ *		Fin	denominator
+ *	Fout = ----- * -------------
+ *		 2	 numerator
+ */
+
+#include <dm/device.h>
+#include <regmap.h>
+#include <linux/clk-provider.h>
+#include <linux/rational.h>
+
+#include "clk_ddn.h"
+
+#define UBOOT_DM_SPACEMIT_CLK_DDN "spacemit_clk_ddn"
+
+static unsigned long ccu_ddn_calc_rate(unsigned long prate, unsigned long num,
+				       unsigned long den, unsigned int pre_div)
+{
+	return prate * den / pre_div / num;
+}
+
+static unsigned long ccu_ddn_calc_best_rate(struct ccu_ddn *ddn,
+					    unsigned long rate, unsigned long prate,
+					    unsigned long *num, unsigned long *den)
+{
+	rational_best_approximation(rate, prate / ddn->pre_div,
+				    ddn->den_mask >> ddn->den_shift,
+				    ddn->num_mask >> ddn->num_shift,
+				    den, num);
+	return ccu_ddn_calc_rate(prate, *num, *den, ddn->pre_div);
+}
+
+static unsigned long ccu_ddn_recalc_rate(struct clk *clk)
+{
+	struct ccu_ddn *ddn = clk_to_ccu_ddn(clk);
+	unsigned int val, num, den;
+
+	val = ccu_read(&ddn->common, ctrl);
+
+	num = (val & ddn->num_mask) >> ddn->num_shift;
+	den = (val & ddn->den_mask) >> ddn->den_shift;
+
+	return ccu_ddn_calc_rate(clk_get_parent_rate(clk), num, den, ddn->pre_div);
+}
+
+static unsigned long ccu_ddn_set_rate(struct clk *clk, unsigned long rate)
+{
+	struct ccu_ddn *ddn = clk_to_ccu_ddn(clk);
+	unsigned long num, den;
+
+	ccu_ddn_calc_best_rate(ddn, rate, clk_get_parent_rate(clk), &num, &den);
+
+	ccu_update(&ddn->common, ctrl,
+		   ddn->num_mask | ddn->den_mask,
+		   (num << ddn->num_shift) | (den << ddn->den_shift));
+
+	return 0;
+}
+
+static const struct clk_ops spacemit_clk_ddn_ops = {
+	.get_rate = ccu_ddn_recalc_rate,
+	.set_rate = ccu_ddn_set_rate,
+};
+
+int spacemit_ddn_init(struct ccu_common *common)
+{
+	struct clk *clk = &common->clk;
+
+	return clk_register(clk, UBOOT_DM_SPACEMIT_CLK_DDN,
+			    common->name, common->parents[0]);
+}
+
+U_BOOT_DRIVER(spacemit_clk_ddn) = {
+	.name	= UBOOT_DM_SPACEMIT_CLK_DDN,
+	.id	= UCLASS_CLK,
+	.ops	= &spacemit_clk_ddn_ops,
+	.flags	= DM_FLAG_PRE_RELOC,
+};
diff --git a/drivers/clk/spacemit/clk_ddn.h b/drivers/clk/spacemit/clk_ddn.h
new file mode 100644
index 00000000000..1330ced23b1
--- /dev/null
+++ b/drivers/clk/spacemit/clk_ddn.h
@@ -0,0 +1,53 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2024 SpacemiT Technology Co. Ltd
+ * Copyright (c) 2024-2025 Haylen Chu <heylenay@4d2.org>
+ * Copyright (c) 2025 Junhui Liu <junhui.liu@pigmoral.tech>
+ * Copyright (c) 2025-2026 RISCstar Ltd.
+ *
+ *  Authors: Haylen Chu <heylenay@4d2.org>
+ */
+
+#ifndef _CLK_DDN_H_
+#define _CLK_DDN_H_
+
+#include <linux/clk-provider.h>
+
+#include "clk_common.h"
+
+struct ccu_ddn {
+	struct ccu_common common;
+	unsigned int num_mask;
+	unsigned int num_shift;
+	unsigned int den_mask;
+	unsigned int den_shift;
+	unsigned int pre_div;
+};
+
+#define CCU_DDN_MASK(_num_shift, _num_width)					\
+	GENMASK((_num_shift) + (_num_width) - 1, _num_shift)
+
+#define CCU_DDN_DEFINE(_id, _var, _name, _parent, _reg_ctrl, _num_mask,		\
+		       _num_shift, _den_mask, _den_shift, _pre_div, _flags)	\
+static struct ccu_ddn _var = {							\
+	.common = {								\
+		.reg_ctrl	= _reg_ctrl,					\
+		CCU_COMMON(_id, _name, _parent, spacemit_ddn_init, _flags)	\
+	},									\
+	.num_mask	= _num_mask,						\
+	.num_shift	= _num_shift,						\
+	.den_mask	= _den_mask,						\
+	.den_shift	= _den_shift,						\
+	.pre_div	= _pre_div,						\
+}
+
+static inline struct ccu_ddn *clk_to_ccu_ddn(struct clk *clk)
+{
+	struct ccu_common *common = clk_to_ccu_common(clk);
+
+	return container_of(common, struct ccu_ddn, common);
+}
+
+int spacemit_ddn_init(struct ccu_common *common);
+
+#endif /* _CLK_DDN_H_ */
diff --git a/drivers/clk/spacemit/clk_mix.c b/drivers/clk/spacemit/clk_mix.c
new file mode 100644
index 00000000000..a1158512a92
--- /dev/null
+++ b/drivers/clk/spacemit/clk_mix.c
@@ -0,0 +1,403 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2024 SpacemiT Technology Co. Ltd
+ * Copyright (c) 2024-2025 Haylen Chu <heylenay@4d2.org>
+ * Copyright (c) 2025 Junhui Liu <junhui.liu@pigmoral.tech>
+ *  Authors: Haylen Chu <heylenay@4d2.org>
+ *
+ * MIX clock type is the combination of mux, factor or divider, and gate
+ */
+
+#include <dm/device.h>
+#include <dm/uclass.h>
+#include <div64.h>
+#include <regmap.h>
+#include <linux/clk-provider.h>
+#include <linux/kernel.h>
+
+#include "clk_mix.h"
+
+#define UBOOT_DM_SPACEMIT_CLK_GATE		"spacemit_clk_gate"
+#define UBOOT_DM_SPACEMIT_CLK_FACTOR		"spacemit_clk_factor"
+#define UBOOT_DM_SPACEMIT_CLK_MUX		"spacemit_clk_mux"
+#define UBOOT_DM_SPACEMIT_CLK_DIV		"spacemit_clk_div"
+#define UBOOT_DM_SPACEMIT_CLK_FACTOR_GATE	"spacemit_clk_factor_gate"
+#define UBOOT_DM_SPACEMIT_CLK_MUX_GATE		"spacemit_clk_mux_gate"
+#define UBOOT_DM_SPACEMIT_CLK_DIV_GATE		"spacemit_clk_div_gate"
+#define UBOOT_DM_SPACEMIT_CLK_MUX_DIV		"spacemit_clk_mux_div"
+#define UBOOT_DM_SPACEMIT_CLK_MUX_DIV_GATE	"spacemit_clk_mux_div_gate"
+
+#define MIX_FC_TIMEOUT_US	10000
+#define MIX_FC_DELAY_US		5
+
+int ccu_gate_disable(struct clk *clk)
+{
+	struct ccu_mix *mix = clk_to_ccu_mix(clk);
+
+	ccu_update(&mix->common, ctrl, mix->gate.mask, 0);
+
+	return 0;
+}
+
+int ccu_gate_enable(struct clk *clk)
+{
+	struct ccu_mix *mix = clk_to_ccu_mix(clk);
+	struct ccu_gate_config *gate = &mix->gate;
+
+	ccu_update(&mix->common, ctrl, gate->mask, gate->mask);
+
+	return 0;
+}
+
+static unsigned long ccu_factor_recalc_rate(struct clk *clk)
+{
+	struct ccu_mix *mix = clk_to_ccu_mix(clk);
+
+	return clk_get_parent_rate(clk) * mix->factor.mul / mix->factor.div;
+}
+
+static unsigned long ccu_div_recalc_rate(struct clk *clk)
+{
+	struct ccu_mix *mix = clk_to_ccu_mix(clk);
+	struct ccu_div_config *div = &mix->div;
+	unsigned long val;
+
+	val = ccu_read(&mix->common, ctrl) >> div->shift;
+	val &= (1 << div->width) - 1;
+
+	return divider_recalc_rate(clk, clk_get_parent_rate(clk), val, NULL, 0, div->width);
+}
+
+/*
+ * Some clocks require a "FC" (frequency change) bit to be set after changing
+ * their rates or reparenting. This bit will be automatically cleared by
+ * hardware in MIX_FC_TIMEOUT_US, which indicates the operation is completed.
+ */
+static int ccu_mix_trigger_fc(struct clk *clk)
+{
+	struct ccu_common *common = clk_to_ccu_common(clk);
+	unsigned int val;
+
+	if (common->reg_fc)
+		return 0;
+
+	ccu_update(common, fc, common->mask_fc, common->mask_fc);
+
+	return regmap_read_poll_timeout(common->regmap, common->reg_fc,
+					val, !(val & common->mask_fc),
+					MIX_FC_DELAY_US,
+					MIX_FC_TIMEOUT_US);
+}
+
+static unsigned long
+ccu_mix_calc_best_rate(struct clk *clk, unsigned long rate,
+		       struct clk **best_parent,
+		       unsigned long *best_parent_rate,
+		       u32 *div_val)
+{
+	struct ccu_common *common = clk_to_ccu_common(clk);
+	struct ccu_mix *mix = clk_to_ccu_mix(clk);
+	unsigned int parent_num = common->num_parents;
+	struct ccu_div_config *div = &mix->div;
+	u32 div_max = 1 << div->width;
+	unsigned long best_rate = 0;
+
+	for (int i = 0; i < parent_num; i++) {
+		struct udevice *parent_dev;
+		unsigned long parent_rate;
+		struct clk *parent;
+
+		if (uclass_get_device_by_name(UCLASS_CLK, common->parents[i],
+					      &parent_dev))
+			continue;
+		parent = dev_get_clk_ptr(parent_dev);
+		if (!parent)
+			continue;
+
+		parent_rate = clk_get_rate(parent);
+
+		for (int j = 1; j <= div_max; j++) {
+			unsigned long tmp = DIV_ROUND_CLOSEST_ULL(parent_rate, j);
+
+			if (abs(tmp - rate) < abs(best_rate - rate)) {
+				best_rate = tmp;
+
+				if (div_val)
+					*div_val = j - 1;
+
+				if (best_parent) {
+					*best_parent      = parent;
+					*best_parent_rate = parent_rate;
+				}
+			}
+		}
+	}
+
+	return best_rate;
+}
+
+static unsigned long ccu_mix_set_rate(struct clk *clk, unsigned long rate)
+{
+	struct ccu_mix *mix = clk_to_ccu_mix(clk);
+	struct ccu_common *common = &mix->common;
+	struct ccu_div_config *div = &mix->div;
+	u32 current_div, target_div, mask;
+
+	ccu_mix_calc_best_rate(clk, rate, NULL, NULL, &target_div);
+
+	current_div = ccu_read(common, ctrl) >> div->shift;
+	current_div &= (1 << div->width) - 1;
+
+	if (current_div == target_div)
+		return 0;
+
+	mask = GENMASK(div->width + div->shift - 1, div->shift);
+
+	ccu_update(common, ctrl, mask, target_div << div->shift);
+
+	return ccu_mix_trigger_fc(clk);
+}
+
+static u8 ccu_mux_get_parent(struct clk *clk)
+{
+	struct ccu_mix *mix = clk_to_ccu_mix(clk);
+	struct ccu_mux_config *mux = &mix->mux;
+	u8 parent;
+
+	parent = ccu_read(&mix->common, ctrl) >> mux->shift;
+	parent &= (1 << mux->width) - 1;
+
+	return parent;
+}
+
+static int ccu_mux_set_parent(struct clk *clk, struct clk *parent)
+{
+	struct ccu_common *common = clk_to_ccu_common(clk);
+	struct ccu_mix *mix = clk_to_ccu_mix(clk);
+	struct ccu_mux_config *mux = &mix->mux;
+	u32 mask;
+	int i = 0;
+
+	mask = GENMASK(mux->width + mux->shift - 1, mux->shift);
+
+	for (i = 0; i < common->num_parents; i++) {
+		if (!strcmp(parent->dev->name, common->parents[i]))
+			break;
+	}
+
+	if (i == common->num_parents)
+		return -EINVAL;
+
+	ccu_update(&mix->common, ctrl, mask, i << mux->shift);
+
+	return ccu_mix_trigger_fc(clk);
+}
+
+int spacemit_gate_init(struct ccu_common *common)
+{
+	struct clk *clk = &common->clk;
+
+	return clk_register(clk, UBOOT_DM_SPACEMIT_CLK_GATE,
+			    common->name, common->parents[0]);
+}
+
+static const struct clk_ops spacemit_clk_gate_ops = {
+	.disable	= ccu_gate_disable,
+	.enable		= ccu_gate_enable,
+	.get_rate	= clk_generic_get_rate,
+};
+
+U_BOOT_DRIVER(spacemit_clk_gate) = {
+	.name	= UBOOT_DM_SPACEMIT_CLK_GATE,
+	.id	= UCLASS_CLK,
+	.ops	= &spacemit_clk_gate_ops,
+	.flags	= DM_FLAG_PRE_RELOC,
+};
+
+int spacemit_factor_init(struct ccu_common *common)
+{
+	struct clk *clk = &common->clk;
+
+	return clk_register(clk, UBOOT_DM_SPACEMIT_CLK_FACTOR,
+			    common->name, common->parents[0]);
+}
+
+static const struct clk_ops spacemit_clk_factor_ops = {
+	.get_rate	= ccu_factor_recalc_rate,
+};
+
+U_BOOT_DRIVER(spacemit_clk_factor) = {
+	.name	= UBOOT_DM_SPACEMIT_CLK_FACTOR,
+	.id	= UCLASS_CLK,
+	.ops	= &spacemit_clk_factor_ops,
+	.flags	= DM_FLAG_PRE_RELOC,
+};
+
+int spacemit_mux_init(struct ccu_common *common)
+{
+	struct clk *clk = &common->clk;
+	u8 index;
+
+	index = ccu_mux_get_parent(clk);
+	if (index >= common->num_parents)
+		index = 0;
+
+	return clk_register(clk, UBOOT_DM_SPACEMIT_CLK_MUX,
+			    common->name, common->parents[index]);
+}
+
+static const struct clk_ops spacemit_clk_mux_ops = {
+	.set_parent	= ccu_mux_set_parent,
+	.get_rate	= clk_generic_get_rate,
+};
+
+U_BOOT_DRIVER(spacemit_clk_mux) = {
+	.name	= UBOOT_DM_SPACEMIT_CLK_MUX,
+	.id	= UCLASS_CLK,
+	.ops	= &spacemit_clk_mux_ops,
+	.flags	= DM_FLAG_PRE_RELOC,
+};
+
+int spacemit_div_init(struct ccu_common *common)
+{
+	struct clk *clk = &common->clk;
+
+	return clk_register(clk, UBOOT_DM_SPACEMIT_CLK_DIV,
+			    common->name, common->parents[0]);
+}
+
+static const struct clk_ops spacemit_clk_div_ops = {
+	.get_rate	= ccu_div_recalc_rate,
+	.set_rate	= ccu_mix_set_rate,
+};
+
+U_BOOT_DRIVER(spacemit_clk_div) = {
+	.name	= UBOOT_DM_SPACEMIT_CLK_DIV,
+	.id	= UCLASS_CLK,
+	.ops	= &spacemit_clk_div_ops,
+	.flags	= DM_FLAG_PRE_RELOC,
+};
+
+int spacemit_factor_gate_init(struct ccu_common *common)
+{
+	struct clk *clk = &common->clk;
+
+	return clk_register(clk, UBOOT_DM_SPACEMIT_CLK_FACTOR_GATE,
+			    common->name, common->parents[0]);
+}
+
+static const struct clk_ops spacemit_clk_factor_gate_ops = {
+	.disable	= ccu_gate_disable,
+	.enable		= ccu_gate_enable,
+	.get_rate	= ccu_factor_recalc_rate,
+};
+
+U_BOOT_DRIVER(spacemit_clk_factor_gate) = {
+	.name	= UBOOT_DM_SPACEMIT_CLK_FACTOR_GATE,
+	.id	= UCLASS_CLK,
+	.ops	= &spacemit_clk_factor_gate_ops,
+	.flags	= DM_FLAG_PRE_RELOC,
+};
+
+int spacemit_mux_gate_init(struct ccu_common *common)
+{
+	struct clk *clk = &common->clk;
+	u8 index;
+
+	index = ccu_mux_get_parent(clk);
+	if (index >= common->num_parents)
+		index = 0;
+
+	return clk_register(clk, UBOOT_DM_SPACEMIT_CLK_MUX_GATE,
+			    common->name, common->parents[index]);
+}
+
+static const struct clk_ops spacemit_clk_mux_gate_ops = {
+	.disable	= ccu_gate_disable,
+	.enable		= ccu_gate_enable,
+	.set_parent	= ccu_mux_set_parent,
+	.get_rate	= clk_generic_get_rate,
+};
+
+U_BOOT_DRIVER(spacemit_clk_mux_gate) = {
+	.name	= UBOOT_DM_SPACEMIT_CLK_MUX_GATE,
+	.id	= UCLASS_CLK,
+	.ops	= &spacemit_clk_mux_gate_ops,
+	.flags	= DM_FLAG_PRE_RELOC,
+};
+
+int spacemit_div_gate_init(struct ccu_common *common)
+{
+	struct clk *clk = &common->clk;
+
+	return clk_register(clk, UBOOT_DM_SPACEMIT_CLK_DIV_GATE,
+			    common->name, common->parents[0]);
+}
+
+static const struct clk_ops spacemit_clk_div_gate_ops = {
+	.disable	= ccu_gate_disable,
+	.enable		= ccu_gate_enable,
+	.get_rate	= ccu_div_recalc_rate,
+	.set_rate	= ccu_mix_set_rate,
+};
+
+U_BOOT_DRIVER(spacemit_clk_div_gate) = {
+	.name	= UBOOT_DM_SPACEMIT_CLK_DIV_GATE,
+	.id	= UCLASS_CLK,
+	.ops	= &spacemit_clk_div_gate_ops,
+	.flags	= DM_FLAG_PRE_RELOC,
+};
+
+int spacemit_mux_div_init(struct ccu_common *common)
+{
+	struct clk *clk = &common->clk;
+	u8 index;
+
+	index = ccu_mux_get_parent(clk);
+	if (index >= common->num_parents)
+		index = 0;
+
+	return clk_register(clk, UBOOT_DM_SPACEMIT_CLK_MUX_DIV,
+			    common->name, common->parents[index]);
+}
+
+static const struct clk_ops spacemit_clk_mux_div_ops = {
+	.set_parent	= ccu_mux_set_parent,
+	.get_rate	= ccu_div_recalc_rate,
+	.set_rate	= ccu_mix_set_rate,
+};
+
+U_BOOT_DRIVER(spacemit_clk_mux_div) = {
+	.name	= UBOOT_DM_SPACEMIT_CLK_MUX_DIV,
+	.id	= UCLASS_CLK,
+	.ops	= &spacemit_clk_mux_div_ops,
+	.flags	= DM_FLAG_PRE_RELOC,
+};
+
+int spacemit_mux_div_gate_init(struct ccu_common *common)
+{
+	struct clk *clk = &common->clk;
+	u8 index;
+
+	index = ccu_mux_get_parent(clk);
+	if (index >= common->num_parents)
+		index = 0;
+
+	return clk_register(clk, UBOOT_DM_SPACEMIT_CLK_MUX_DIV_GATE,
+			    common->name, common->parents[index]);
+}
+
+static const struct clk_ops spacemit_clk_mux_div_gate_ops = {
+	.disable	= ccu_gate_disable,
+	.enable		= ccu_gate_enable,
+	.set_parent	= ccu_mux_set_parent,
+	.get_rate	= ccu_div_recalc_rate,
+	.set_rate	= ccu_mix_set_rate,
+};
+
+U_BOOT_DRIVER(spacemit_clk_mux_div_gate) = {
+	.name	= UBOOT_DM_SPACEMIT_CLK_MUX_DIV_GATE,
+	.id	= UCLASS_CLK,
+	.ops	= &spacemit_clk_mux_div_gate_ops,
+	.flags	= DM_FLAG_PRE_RELOC,
+};
diff --git a/drivers/clk/spacemit/clk_mix.h b/drivers/clk/spacemit/clk_mix.h
new file mode 100644
index 00000000000..26a12cedd0d
--- /dev/null
+++ b/drivers/clk/spacemit/clk_mix.h
@@ -0,0 +1,224 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2024 SpacemiT Technology Co. Ltd
+ * Copyright (c) 2024-2025 Haylen Chu <heylenay@4d2.org>
+ * Copyright (c) 2025 Junhui Liu <junhui.liu@pigmoral.tech>
+ * Copyright (c) 2025-2026 RISCstar Ltd.
+ *
+ *  Authors: Haylen Chu <heylenay@4d2.org>
+ */
+
+#ifndef _CLK_MIX_H_
+#define _CLK_MIX_H_
+
+#include <linux/clk-provider.h>
+
+#include "clk_common.h"
+
+/**
+ * struct ccu_gate_config - Gate configuration
+ *
+ * @mask:	Mask to enable the gate. Some clocks may have more than one bit
+ *		set in this field.
+ */
+struct ccu_gate_config {
+	u32 mask;
+};
+
+struct ccu_factor_config {
+	u32 div;
+	u32 mul;
+};
+
+struct ccu_mux_config {
+	u8 shift;
+	u8 width;
+};
+
+struct ccu_div_config {
+	u8 shift;
+	u8 width;
+};
+
+struct ccu_mix {
+	struct ccu_factor_config factor;
+	struct ccu_gate_config gate;
+	struct ccu_div_config div;
+	struct ccu_mux_config mux;
+	struct ccu_common common;
+};
+
+#define CCU_GATE_INIT(_mask)		{ .mask = _mask }
+#define CCU_FACTOR_INIT(_div, _mul)	{ .div = _div, .mul = _mul }
+#define CCU_MUX_INIT(_shift, _width)	{ .shift = _shift, .width = _width }
+#define CCU_DIV_INIT(_shift, _width)	{ .shift = _shift, .width = _width }
+
+#define CCU_GATE_DEFINE(_id, _var, _name, _parent, _reg_ctrl,		\
+			_mask_gate, _flags)				\
+static struct ccu_mix _var = {						\
+	.gate	= CCU_GATE_INIT(_mask_gate),				\
+	.common	= {							\
+		.reg_ctrl	= _reg_ctrl,				\
+		CCU_COMMON(_id, _name, _parent, spacemit_gate_init,	\
+			   _flags)					\
+	}								\
+}
+
+#define CCU_FACTOR_DEFINE(_id, _var, _name, _parent, _div, _mul)	\
+static struct ccu_mix _var = {						\
+	.factor	= CCU_FACTOR_INIT(_div, _mul),				\
+	.common = {							\
+		CCU_COMMON(_id, _name, _parent, spacemit_factor_init,	\
+			   0)						\
+	}								\
+}
+
+#define CCU_MUX_DEFINE(_id, _var, _name, _parents, _num_p, _reg_ctrl,	\
+		       _shift, _width, _flags)				\
+static struct ccu_mix _var = {						\
+	.mux	= CCU_MUX_INIT(_shift, _width),				\
+	.common	= {							\
+		.reg_ctrl	= _reg_ctrl,				\
+		CCU_COMMON_PARENTS(_id, _name, _parents, _num_p,	\
+				   spacemit_mux_init, _flags)		\
+	}								\
+}
+
+#define CCU_DIV_DEFINE(_id, _var, _name, _parent, _reg_ctrl, _shift,	\
+		       _width, _flags)					\
+static struct ccu_mix _var = {						\
+	.div	= CCU_DIV_INIT(_shift, _width),				\
+	.common = {							\
+		.reg_ctrl	= _reg_ctrl,				\
+		CCU_COMMON(_id, _name, _parent, spacemit_div_init,	\
+			   _flags)					\
+	}								\
+}
+
+#define CCU_FACTOR_GATE_FLAGS_DEFINE(_id, _var, _name, _parent,		\
+				     _reg_ctrl,	_mask_gate, _div, _mul,	\
+				     _flags)				\
+static struct ccu_mix _var = {						\
+	.gate	= CCU_GATE_INIT(_mask_gate),				\
+	.factor	= CCU_FACTOR_INIT(_div, _mul),				\
+	.common = {							\
+		.reg_ctrl	= _reg_ctrl,				\
+		CCU_COMMON(_id, _name, _parent,				\
+			   spacemit_factor_gate_init, _flags)		\
+	}								\
+}
+
+#define CCU_FACTOR_GATE_DEFINE(_id, _var, _name, _parent, _reg_ctrl,	\
+			       _mask_gate, _div, _mul)			\
+	CCU_FACTOR_GATE_FLAGS_DEFINE(_id, _var, _name, _parent,		\
+				     _reg_ctrl,	_mask_gate, _div, _mul,	\
+				     0)
+
+#define CCU_MUX_GATE_DEFINE(_id, _var, _name, _parents, _num_p,		\
+			    _reg_ctrl, _shift, _width, _mask_gate,	\
+			    _flags)					\
+static struct ccu_mix _var = {						\
+	.gate	= CCU_GATE_INIT(_mask_gate),				\
+	.mux	= CCU_MUX_INIT(_shift, _width),				\
+	.common	= {							\
+		.reg_ctrl	= _reg_ctrl,				\
+		CCU_COMMON_PARENTS(_id, _name, _parents, _num_p,	\
+				   spacemit_mux_gate_init, _flags)	\
+	}								\
+}
+
+#define CCU_DIV_GATE_DEFINE(_id, _var, _name, _parent, _reg_ctrl,	\
+			    _shift, _width, _mask_gate,	_flags)		\
+static struct ccu_mix _var = {						\
+	.gate	= CCU_GATE_INIT(_mask_gate),				\
+	.div	= CCU_DIV_INIT(_shift, _width),				\
+	.common = {							\
+		.reg_ctrl	= _reg_ctrl,				\
+		CCU_COMMON(_id, _name, _parent,				\
+			   spacemit_div_gate_init, _flags)		\
+	}								\
+}
+
+#define CCU_MUX_DIV_GATE_DEFINE(_id, _var, _name, _parents, _num_p,	\
+				_reg_ctrl, _mshift, _mwidth, _muxshift,	\
+				_muxwidth, _mask_gate, _flags)		\
+static struct ccu_mix _var = {						\
+	.gate	= CCU_GATE_INIT(_mask_gate),				\
+	.div	= CCU_DIV_INIT(_mshift, _mwidth),			\
+	.mux	= CCU_MUX_INIT(_muxshift, _muxwidth),			\
+	.common	= {							\
+		.reg_ctrl	= _reg_ctrl,				\
+		CCU_COMMON_PARENTS(_id, _name, _parents, _num_p,	\
+				   spacemit_mux_div_gate_init, _flags)	\
+	},								\
+}
+
+#define CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(_id, _var, _name, _parents,	\
+					 _num_p, _reg_ctrl, _reg_fc,	\
+					 _mshift, _mwidth, _mask_fc,	\
+					 _muxshift, _muxwidth,		\
+					 _mask_gate, _flags)		\
+static struct ccu_mix _var = {						\
+	.gate	= CCU_GATE_INIT(_mask_gate),				\
+	.div	= CCU_DIV_INIT(_mshift, _mwidth),			\
+	.mux	= CCU_MUX_INIT(_muxshift, _muxwidth),			\
+	.common = {							\
+		.reg_ctrl	= _reg_ctrl,				\
+		.reg_fc		= _reg_fc,				\
+		.mask_fc	= _mask_fc,				\
+		CCU_COMMON_PARENTS(_id, _name, _parents, _num_p,	\
+				   spacemit_mux_div_gate_init, _flags)	\
+	},								\
+}
+
+#define CCU_MUX_DIV_FC_DEFINE(_id, _var, _name, _parents, _num_p,	\
+			      _reg_ctrl, _reg_fc, _mshift, _mwidth,	\
+			      _mask_fc,	_muxshift, _muxwidth, _flags)	\
+static struct ccu_mix _var = {						\
+	.div	= CCU_DIV_INIT(_mshift, _mwidth),			\
+	.mux	= CCU_MUX_INIT(_muxshift, _muxwidth),			\
+	.common = {							\
+		.reg_ctrl	= _reg_ctrl,				\
+		.reg_fc		= _reg_fc,				\
+		.mask_fc	= _mask_fc,				\
+		CCU_COMMON_PARENTS(_id, _name, _parents, _num_p,	\
+				   spacemit_mux_div_init, _flags)	\
+	},								\
+}
+
+#define CCU_MUX_FC_DEFINE(_id, _var, _name, _parents, _num_p,		\
+			  _reg_ctrl, _reg_fc, _mask_fc, _muxshift,	\
+			  _muxwidth, _flags)				\
+static struct ccu_mix _var = {						\
+	.mux	= CCU_MUX_INIT(_muxshift, _muxwidth),			\
+	.common = {							\
+		.reg_ctrl	= _reg_ctrl,				\
+		.reg_fc		= _reg_fc,				\
+		.mask_fc	= _mask_fc,				\
+		CCU_COMMON_PARENTS(_id, _name, _parents, _num_p,	\
+				   spacemit_mux_init,			\
+				   _flags)				\
+	},								\
+}
+
+static inline struct ccu_mix *clk_to_ccu_mix(struct clk *clk)
+{
+	struct ccu_common *common = clk_to_ccu_common(clk);
+
+	return container_of(common, struct ccu_mix, common);
+}
+
+int ccu_gate_enable(struct clk *clk);
+int ccu_gate_disable(struct clk *clk);
+
+int spacemit_gate_init(struct ccu_common *common);
+int spacemit_factor_init(struct ccu_common *common);
+int spacemit_mux_init(struct ccu_common *common);
+int spacemit_div_init(struct ccu_common *common);
+int spacemit_factor_gate_init(struct ccu_common *common);
+int spacemit_div_gate_init(struct ccu_common *common);
+int spacemit_mux_gate_init(struct ccu_common *common);
+int spacemit_mux_div_init(struct ccu_common *common);
+int spacemit_mux_div_gate_init(struct ccu_common *common);
+
+#endif /* _CLK_MIX_H_ */
diff --git a/drivers/clk/spacemit/clk_pll.c b/drivers/clk/spacemit/clk_pll.c
new file mode 100644
index 00000000000..56da70af58a
--- /dev/null
+++ b/drivers/clk/spacemit/clk_pll.c
@@ -0,0 +1,157 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2024 SpacemiT Technology Co. Ltd
+ * Copyright (c) 2024-2025 Haylen Chu <heylenay@4d2.org>
+ * Copyright (c) 2025 Junhui Liu <junhui.liu@pigmoral.tech>
+ *  Authors: Haylen Chu <heylenay@4d2.org>
+ */
+
+#include <dm/device.h>
+#include <regmap.h>
+#include <linux/bug.h>
+#include <linux/clk-provider.h>
+
+#include "clk_pll.h"
+
+#define UBOOT_DM_SPACEMIT_CLK_PLL "spacemit_clk_pll"
+
+#define PLL_TIMEOUT_US		3000
+#define PLL_DELAY_US		5
+
+#define PLL_SWCR3_EN		((u32)BIT(31))
+#define PLL_SWCR3_MASK		GENMASK(30, 0)
+
+static const struct ccu_pll_rate_tbl *ccu_pll_lookup_best_rate(struct ccu_pll *pll,
+							       unsigned long rate)
+{
+	struct ccu_pll_config *config = &pll->config;
+	const struct ccu_pll_rate_tbl *best_entry;
+	unsigned long best_delta = ULONG_MAX;
+	int i;
+
+	for (i = 0; i < config->tbl_num; i++) {
+		const struct ccu_pll_rate_tbl *entry = &config->rate_tbl[i];
+		unsigned long delta = abs(entry->rate - rate);
+
+		if (delta < best_delta) {
+			best_delta = delta;
+			best_entry = entry;
+		}
+	}
+
+	return best_entry;
+}
+
+static const struct ccu_pll_rate_tbl *ccu_pll_lookup_matched_entry(struct ccu_pll *pll)
+{
+	struct ccu_pll_config *config = &pll->config;
+	u32 swcr1, swcr3;
+	int i;
+
+	swcr1 = ccu_read(&pll->common, swcr1);
+	swcr3 = ccu_read(&pll->common, swcr3);
+	swcr3 &= PLL_SWCR3_MASK;
+
+	for (i = 0; i < config->tbl_num; i++) {
+		const struct ccu_pll_rate_tbl *entry = &config->rate_tbl[i];
+
+		if (swcr1 == entry->swcr1 && swcr3 == entry->swcr3)
+			return entry;
+	}
+
+	return NULL;
+}
+
+static void ccu_pll_update_param(struct ccu_pll *pll, const struct ccu_pll_rate_tbl *entry)
+{
+	struct ccu_common *common = &pll->common;
+
+	regmap_write(common->regmap, common->reg_swcr1, entry->swcr1);
+	ccu_update(common, swcr3, PLL_SWCR3_MASK, entry->swcr3);
+}
+
+static int ccu_pll_enable(struct clk *clk)
+{
+	struct ccu_pll *pll = clk_to_ccu_pll(clk);
+	struct ccu_common *common = &pll->common;
+	unsigned int tmp;
+
+	ccu_update(common, swcr3, PLL_SWCR3_EN, PLL_SWCR3_EN);
+
+	/* check lock status */
+	return regmap_read_poll_timeout(common->lock_regmap,
+					pll->config.reg_lock,
+					tmp,
+					tmp & pll->config.mask_lock,
+					PLL_DELAY_US, PLL_TIMEOUT_US);
+}
+
+static int ccu_pll_disable(struct clk *clk)
+{
+	struct ccu_common *common = clk_to_ccu_common(clk);
+
+	ccu_update(common, swcr3, PLL_SWCR3_EN, 0);
+
+	return 0;
+}
+
+/*
+ * PLLs must be gated before changing rate, which is ensured by
+ * flag CLK_SET_RATE_GATE.
+ */
+static unsigned long ccu_pll_set_rate(struct clk *clk, unsigned long rate)
+{
+	struct ccu_pll *pll = clk_to_ccu_pll(clk);
+	const struct ccu_pll_rate_tbl *entry;
+
+	entry = ccu_pll_lookup_best_rate(pll, rate);
+	ccu_pll_update_param(pll, entry);
+
+	return 0;
+}
+
+static unsigned long ccu_pll_recalc_rate(struct clk *clk)
+{
+	struct ccu_pll *pll = clk_to_ccu_pll(clk);
+	const struct ccu_pll_rate_tbl *entry;
+
+	entry = ccu_pll_lookup_matched_entry(pll);
+
+	WARN_ON_ONCE(!entry);
+
+	return entry ? entry->rate : 0;
+}
+
+static const struct clk_ops spacemit_clk_pll_ops = {
+	.enable = ccu_pll_enable,
+	.disable = ccu_pll_disable,
+	.set_rate = ccu_pll_set_rate,
+	.get_rate = ccu_pll_recalc_rate,
+};
+
+int spacemit_pll_init(struct ccu_common *common)
+{
+	struct clk *clk = &common->clk;
+	struct ccu_pll *pll = clk_to_ccu_pll(clk);
+	int ret;
+
+	ret = clk_register(clk, UBOOT_DM_SPACEMIT_CLK_PLL,
+			   common->name, common->parents[0]);
+	if (ret)
+		return ret;
+
+	if (ccu_pll_lookup_matched_entry(pll))
+		return 0;
+
+	ccu_pll_disable(clk);
+	ccu_pll_update_param(pll, &pll->config.rate_tbl[0]);
+
+	return 0;
+}
+
+U_BOOT_DRIVER(spacemit_clk_pll) = {
+	.name	= UBOOT_DM_SPACEMIT_CLK_PLL,
+	.id	= UCLASS_CLK,
+	.ops	= &spacemit_clk_pll_ops,
+	.flags	= DM_FLAG_PRE_RELOC,
+};
diff --git a/drivers/clk/spacemit/clk_pll.h b/drivers/clk/spacemit/clk_pll.h
new file mode 100644
index 00000000000..3987cc1141b
--- /dev/null
+++ b/drivers/clk/spacemit/clk_pll.h
@@ -0,0 +1,81 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2024 SpacemiT Technology Co. Ltd
+ * Copyright (c) 2024-2025 Haylen Chu <heylenay@4d2.org>
+ * Copyright (c) 2025 Junhui Liu <junhui.liu@pigmoral.tech>
+ * Copyright (c) 2025-2026 RISCstar Ltd.
+ *
+ *  Authors: Haylen Chu <heylenay@4d2.org>
+ */
+
+#ifndef _CLK_PLL_H_
+#define _CLK_PLL_H_
+
+#include <linux/clk-provider.h>
+
+#include "clk_common.h"
+
+/**
+ * struct ccu_pll_rate_tbl - Structure mapping between PLL rate and register
+ * configuration.
+ *
+ * @rate:	PLL rate
+ * @swcr1:	Register value of PLLX_SW1_CTRL (PLLx_SWCR1).
+ * @swcr3:	Register value of the PLLx_SW3_CTRL's lowest 31 bits of
+ *		PLLx_SW3_CTRL (PLLx_SWCR3). This highest bit is for enabling
+ *		the PLL and not contained in this field.
+ */
+struct ccu_pll_rate_tbl {
+	unsigned long rate;
+	u32 swcr1;
+	u32 swcr3;
+};
+
+#define CCU_PLL_RATE(_rate, _swcr1, _swcr3)	\
+	{					\
+		.rate	= _rate,		\
+		.swcr1	= _swcr1,		\
+		.swcr3	= _swcr3,		\
+	}
+
+struct ccu_pll_config {
+	const struct ccu_pll_rate_tbl *rate_tbl;
+	u32 tbl_num;
+	u32 reg_lock;
+	u32 mask_lock;
+};
+
+struct ccu_pll {
+	struct ccu_common	common;
+	struct ccu_pll_config	config;
+};
+
+#define CCU_PLL_CONFIG(_table, _reg_lock, _mask_lock) \
+	{									\
+		.rate_tbl	= (_table),					\
+		.tbl_num	= sizeof(_table) / sizeof((_table)[0]),		\
+		.reg_lock	= (_reg_lock),					\
+		.mask_lock	= (_mask_lock),					\
+	}
+
+#define CCU_PLL_DEFINE(_id, _var, _name, _parent, _table, _reg_swcr1,		\
+		       _reg_swcr3, _reg_lock, _mask_lock, _flags)		\
+static struct ccu_pll _var = {							\
+	.config	= CCU_PLL_CONFIG(_table, _reg_lock, _mask_lock),		\
+	.common = {								\
+		.reg_swcr1	= _reg_swcr1,					\
+		.reg_swcr3	= _reg_swcr3,					\
+		CCU_COMMON(_id, _name, _parent, spacemit_pll_init, _flags)	\
+	}									\
+}
+
+static inline struct ccu_pll *clk_to_ccu_pll(struct clk *clk)
+{
+	struct ccu_common *common = clk_to_ccu_common(clk);
+
+	return container_of(common, struct ccu_pll, common);
+}
+
+int spacemit_pll_init(struct ccu_common *common);
+
+#endif /* _CLK_PLL_H_ */
diff --git a/include/soc/spacemit/k1-syscon.h b/include/soc/spacemit/k1-syscon.h
new file mode 100644
index 00000000000..331cc1d35bb
--- /dev/null
+++ b/include/soc/spacemit/k1-syscon.h
@@ -0,0 +1,149 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+/* SpacemiT clock and reset driver definitions for the K1 SoC */
+
+#ifndef __SOC_K1_SYSCON_H__
+#define __SOC_K1_SYSCON_H__
+
+/* APBS register offset */
+#define APBS_PLL1_SWCR1			0x100
+#define APBS_PLL1_SWCR2			0x104
+#define APBS_PLL1_SWCR3			0x108
+#define APBS_PLL2_SWCR1			0x118
+#define APBS_PLL2_SWCR2			0x11c
+#define APBS_PLL2_SWCR3			0x120
+#define APBS_PLL3_SWCR1			0x124
+#define APBS_PLL3_SWCR2			0x128
+#define APBS_PLL3_SWCR3			0x12c
+
+/* MPMU register offset */
+#define MPMU_POSR			0x0010
+#define MPMU_FCCR			0x0008
+#define  POSR_PLL1_LOCK			BIT(27)
+#define  POSR_PLL2_LOCK			BIT(28)
+#define  POSR_PLL3_LOCK			BIT(29)
+#define MPMU_SUCCR			0x0014
+#define MPMU_ISCCR			0x0044
+#define MPMU_WDTPCR			0x0200
+#define MPMU_RIPCCR			0x0210
+#define MPMU_ACGR			0x1024
+#define MPMU_APBCSCR			0x1050
+#define MPMU_SUCCR_1			0x10b0
+
+/* APBC register offset */
+#define APBC_UART1_CLK_RST		0x00
+#define APBC_UART2_CLK_RST		0x04
+#define APBC_GPIO_CLK_RST		0x08
+#define APBC_PWM0_CLK_RST		0x0c
+#define APBC_PWM1_CLK_RST		0x10
+#define APBC_PWM2_CLK_RST		0x14
+#define APBC_PWM3_CLK_RST		0x18
+#define APBC_TWSI8_CLK_RST		0x20
+#define APBC_UART3_CLK_RST		0x24
+#define APBC_RTC_CLK_RST		0x28
+#define APBC_TWSI0_CLK_RST		0x2c
+#define APBC_TWSI1_CLK_RST		0x30
+#define APBC_TIMERS1_CLK_RST		0x34
+#define APBC_TWSI2_CLK_RST		0x38
+#define APBC_AIB_CLK_RST		0x3c
+#define APBC_TWSI4_CLK_RST		0x40
+#define APBC_TIMERS2_CLK_RST		0x44
+#define APBC_ONEWIRE_CLK_RST		0x48
+#define APBC_TWSI5_CLK_RST		0x4c
+#define APBC_DRO_CLK_RST		0x58
+#define APBC_IR_CLK_RST			0x5c
+#define APBC_TWSI6_CLK_RST		0x60
+#define APBC_COUNTER_CLK_SEL		0x64
+#define APBC_TWSI7_CLK_RST		0x68
+#define APBC_TSEN_CLK_RST		0x6c
+#define APBC_UART4_CLK_RST		0x70
+#define APBC_UART5_CLK_RST		0x74
+#define APBC_UART6_CLK_RST		0x78
+#define APBC_SSP3_CLK_RST		0x7c
+#define APBC_SSPA0_CLK_RST		0x80
+#define APBC_SSPA1_CLK_RST		0x84
+#define APBC_IPC_AP2AUD_CLK_RST		0x90
+#define APBC_UART7_CLK_RST		0x94
+#define APBC_UART8_CLK_RST		0x98
+#define APBC_UART9_CLK_RST		0x9c
+#define APBC_CAN0_CLK_RST		0xa0
+#define APBC_PWM4_CLK_RST		0xa8
+#define APBC_PWM5_CLK_RST		0xac
+#define APBC_PWM6_CLK_RST		0xb0
+#define APBC_PWM7_CLK_RST		0xb4
+#define APBC_PWM8_CLK_RST		0xb8
+#define APBC_PWM9_CLK_RST		0xbc
+#define APBC_PWM10_CLK_RST		0xc0
+#define APBC_PWM11_CLK_RST		0xc4
+#define APBC_PWM12_CLK_RST		0xc8
+#define APBC_PWM13_CLK_RST		0xcc
+#define APBC_PWM14_CLK_RST		0xd0
+#define APBC_PWM15_CLK_RST		0xd4
+#define APBC_PWM16_CLK_RST		0xd8
+#define APBC_PWM17_CLK_RST		0xdc
+#define APBC_PWM18_CLK_RST		0xe0
+#define APBC_PWM19_CLK_RST		0xe4
+
+/* APMU register offset */
+#define APMU_JPG_CLK_RES_CTRL		0x020
+#define APMU_CSI_CCIC2_CLK_RES_CTRL	0x024
+#define APMU_ISP_CLK_RES_CTRL		0x038
+#define APMU_LCD_CLK_RES_CTRL1		0x044
+#define APMU_LCD_SPI_CLK_RES_CTRL	0x048
+#define APMU_LCD_CLK_RES_CTRL2		0x04c
+#define APMU_CCIC_CLK_RES_CTRL		0x050
+#define APMU_SDH0_CLK_RES_CTRL		0x054
+#define APMU_SDH1_CLK_RES_CTRL		0x058
+#define APMU_USB_CLK_RES_CTRL		0x05c
+#define APMU_QSPI_CLK_RES_CTRL		0x060
+#define APMU_DMA_CLK_RES_CTRL		0x064
+#define APMU_AES_CLK_RES_CTRL		0x068
+#define APMU_VPU_CLK_RES_CTRL		0x0a4
+#define APMU_GPU_CLK_RES_CTRL		0x0cc
+#define APMU_SDH2_CLK_RES_CTRL		0x0e0
+#define APMU_PMUA_MC_CTRL		0x0e8
+#define APMU_PMU_CC2_AP			0x100
+#define APMU_PMUA_EM_CLK_RES_CTRL	0x104
+#define APMU_AUDIO_CLK_RES_CTRL		0x14c
+#define APMU_HDMI_CLK_RES_CTRL		0x1b8
+#define APMU_CCI550_CLK_CTRL		0x300
+#define APMU_ACLK_CLK_CTRL		0x388
+#define APMU_CPU_C0_CLK_CTRL		0x38C
+#define APMU_CPU_C1_CLK_CTRL		0x390
+#define APMU_PCIE_CLK_RES_CTRL_0	0x3cc
+#define APMU_PCIE_CLK_RES_CTRL_1	0x3d4
+#define APMU_PCIE_CLK_RES_CTRL_2	0x3dc
+#define APMU_EMAC0_CLK_RES_CTRL		0x3e4
+#define APMU_EMAC1_CLK_RES_CTRL		0x3ec
+
+/* RCPU register offsets */
+#define RCPU_SSP0_CLK_RST		0x0028
+#define RCPU_I2C0_CLK_RST		0x0030
+#define RCPU_UART1_CLK_RST		0x003c
+#define RCPU_CAN_CLK_RST		0x0048
+#define RCPU_IR_CLK_RST			0x004c
+#define RCPU_UART0_CLK_RST		0x00d8
+#define AUDIO_HDMI_CLK_CTRL		0x2044
+
+/* RCPU2 register offsets */
+#define RCPU2_PWM0_CLK_RST		0x0000
+#define RCPU2_PWM1_CLK_RST		0x0004
+#define RCPU2_PWM2_CLK_RST		0x0008
+#define RCPU2_PWM3_CLK_RST		0x000c
+#define RCPU2_PWM4_CLK_RST		0x0010
+#define RCPU2_PWM5_CLK_RST		0x0014
+#define RCPU2_PWM6_CLK_RST		0x0018
+#define RCPU2_PWM7_CLK_RST		0x001c
+#define RCPU2_PWM8_CLK_RST		0x0020
+#define RCPU2_PWM9_CLK_RST		0x0024
+
+/* APBC2 register offsets */
+#define APBC2_UART1_CLK_RST		0x0000
+#define APBC2_SSP2_CLK_RST		0x0004
+#define APBC2_TWSI3_CLK_RST		0x0008
+#define APBC2_RTC_CLK_RST		0x000c
+#define APBC2_TIMERS0_CLK_RST		0x0010
+#define APBC2_KPC_CLK_RST		0x0014
+#define APBC2_GPIO_CLK_RST		0x001c
+
+#endif /* __SOC_K1_SYSCON_H__ */
-- 
2.25.1


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

* [PATCH v2 08/16] dts: k1: enable clocks in SPL
  2026-02-10 15:14 [PATCH v2 00/16] Add board support for Spacemit K1 SoC in SPL Raymond Mao
                   ` (6 preceding siblings ...)
  2026-02-10 15:14 ` [PATCH v2 07/16] clk: spacemit: Add support for K1 SoC Raymond Mao
@ 2026-02-10 15:14 ` Raymond Mao
  2026-02-10 15:14 ` [PATCH v2 09/16] board: k1: initialize clock and serial devices " Raymond Mao
                   ` (9 subsequent siblings)
  17 siblings, 0 replies; 24+ messages in thread
From: Raymond Mao @ 2026-02-10 15:14 UTC (permalink / raw)
  To: u-boot
  Cc: uboot, u-boot-spacemit, raymond.mao, rick, ycliang, trini, lukma,
	hs, jh80.chung, peng.fan, xypron.glpk, randolph, dlan, junhui.liu,
	neil.armstrong, quentin.schulz, samuel, raymondmaoca

From: Raymond Mao <raymond.mao@riscstar.com>

Enable clock nodes for K1 SoC in SPL.

Signed-off-by: Raymond Mao <raymond.mao@riscstar.com>
---
 arch/riscv/dts/k1-spl.dts | 49 ++++++++++++++++++++++++++++++++++++++-
 1 file changed, 48 insertions(+), 1 deletion(-)

diff --git a/arch/riscv/dts/k1-spl.dts b/arch/riscv/dts/k1-spl.dts
index c7196c2d722..a74eaaf6a8f 100644
--- a/arch/riscv/dts/k1-spl.dts
+++ b/arch/riscv/dts/k1-spl.dts
@@ -11,15 +11,62 @@
 / {
 	model = "spacemit k1 spl";
 
+	aliases {
+		console = &uart0;
+		serial0 = &uart0;
+	};
+
 	chosen {
 		stdout-path = "serial0:115200n8";
 	};
 };
 
+&vctcxo_1m {
+	status = "okay";
+	bootph-pre-ram;
+};
+
+&vctcxo_24m {
+	status = "okay";
+	bootph-pre-ram;
+};
+
+&vctcxo_3m {
+	status = "okay";
+	bootph-pre-ram;
+};
+
+&osc_32k {
+	status = "okay";
+	bootph-pre-ram;
+};
+
 &soc {
 	bootph-all;
-	serial@d4017000 {
+	system-controller@d4050000 {
 		status = "okay";
 		bootph-pre-ram;
 	};
+	clock-controller@d4090000 {
+		status = "okay";
+		bootph-pre-ram;
+	};
+	system-controller@d4282800 {
+		status = "okay";
+		bootph-pre-ram;
+	};
+	system-controller@d4015000 {
+		clocks = <&osc_32k>, <&vctcxo_1m>, <&vctcxo_3m>,
+			 <&vctcxo_24m>, <&syscon_mpmu CLK_PLL1_31P5>,
+			 <&pll CLK_PLL1_D4>;
+		clock-names = "osc", "vctcxo_1m", "vctcxo_3m",
+			      "vctcxo_24m", "pll1_d78_31p5", "pll1_d4";
+		status = "okay";
+		bootph-pre-ram;
+	};
+};
+
+&uart0 {
+	status = "okay";
+	bootph-pre-ram;
 };
-- 
2.25.1


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

* [PATCH v2 09/16] board: k1: initialize clock and serial devices in SPL
  2026-02-10 15:14 [PATCH v2 00/16] Add board support for Spacemit K1 SoC in SPL Raymond Mao
                   ` (7 preceding siblings ...)
  2026-02-10 15:14 ` [PATCH v2 08/16] dts: k1: enable clocks in SPL Raymond Mao
@ 2026-02-10 15:14 ` Raymond Mao
  2026-02-10 15:14 ` [PATCH v2 10/16] configs: k1: add default option for clock driver " Raymond Mao
                   ` (8 subsequent siblings)
  17 siblings, 0 replies; 24+ messages in thread
From: Raymond Mao @ 2026-02-10 15:14 UTC (permalink / raw)
  To: u-boot
  Cc: uboot, u-boot-spacemit, raymond.mao, rick, ycliang, trini, lukma,
	hs, jh80.chung, peng.fan, xypron.glpk, randolph, dlan, junhui.liu,
	neil.armstrong, quentin.schulz, samuel, raymondmaoca

From: Raymond Mao <raymond.mao@riscstar.com>

Initialize clock and serial devices in SPL. Otherwise, the device
driver won't be loaded in SPL.

Signed-off-by: Raymond Mao <raymond.mao@riscstar.com>
---
 board/spacemit/k1/spl.c | 39 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/board/spacemit/k1/spl.c b/board/spacemit/k1/spl.c
index e15cf5f1abf..78f26616347 100644
--- a/board/spacemit/k1/spl.c
+++ b/board/spacemit/k1/spl.c
@@ -3,8 +3,45 @@
  * Copyright (c) 2025-2026, RISCstar Ltd.
  */
 
+#include <dm/device.h>
+#include <dm/uclass.h>
+#include <log.h>
 #include <spl.h>
 
+static void clk_early_init(void)
+{
+	struct udevice *dev;
+	int ret;
+
+	ret = uclass_get_device_by_name(UCLASS_CLK, "clock-controller@d4090000", &dev);
+	if (ret)
+		panic("Fail to detect clock-controller@d4090000\n");
+	ret = uclass_get_device_by_name(UCLASS_CLK, "system-controller@d4050000", &dev);
+	if (ret)
+		panic("Fail to detect system-controller@d4050000\n");
+	ret = uclass_get_device_by_name(UCLASS_CLK, "system-controller@d4282800", &dev);
+	if (ret)
+		panic("Fail to detect system-controller@d4282800\n");
+	ret = uclass_get_device_by_name(UCLASS_CLK, "system-controller@d4015000", &dev);
+	if (ret)
+		panic("Fail to detect system-controller@d4015000\n");
+
+	if (device_active(dev))
+		log_debug("clk: device is active\n");
+	else
+		log_debug("clk: device not active, probing...\n");
+}
+
+void serial_early_init(void)
+{
+	struct udevice *dev;
+	int ret;
+
+	ret = uclass_get_device(UCLASS_SERIAL, 0, &dev);
+	if (ret)
+		panic("Serial uclass init failed: %d\n", ret);
+}
+
 void board_init_f(ulong dummy)
 {
 	int ret;
@@ -15,6 +52,8 @@ void board_init_f(ulong dummy)
 
 	riscv_cpu_setup();
 
+	clk_early_init();
+	serial_early_init();
 	preloader_console_init();
 }
 
-- 
2.25.1


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

* [PATCH v2 10/16] configs: k1: add default option for clock driver in SPL
  2026-02-10 15:14 [PATCH v2 00/16] Add board support for Spacemit K1 SoC in SPL Raymond Mao
                   ` (8 preceding siblings ...)
  2026-02-10 15:14 ` [PATCH v2 09/16] board: k1: initialize clock and serial devices " Raymond Mao
@ 2026-02-10 15:14 ` Raymond Mao
  2026-02-10 15:14 ` [PATCH v2 11/16] i2c: k1: add I2C driver support Raymond Mao
                   ` (7 subsequent siblings)
  17 siblings, 0 replies; 24+ messages in thread
From: Raymond Mao @ 2026-02-10 15:14 UTC (permalink / raw)
  To: u-boot
  Cc: uboot, u-boot-spacemit, raymond.mao, rick, ycliang, trini, lukma,
	hs, jh80.chung, peng.fan, xypron.glpk, randolph, dlan, junhui.liu,
	neil.armstrong, quentin.schulz, samuel, raymondmaoca

From: Raymond Mao <raymond.mao@riscstar.com>

Add default option for enabling clock driver in SPL.

Signed-off-by: Raymond Mao <raymond.mao@riscstar.com>
---
 configs/spacemit_k1_defconfig | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/configs/spacemit_k1_defconfig b/configs/spacemit_k1_defconfig
index 617fe9d2aae..e64687e95ce 100644
--- a/configs/spacemit_k1_defconfig
+++ b/configs/spacemit_k1_defconfig
@@ -44,3 +44,11 @@ CONFIG_DEBUG_UART_NS16550=y
 CONFIG_DEBUG_UART_ANNOUNCE=y
 # CONFIG_DEBUG_SBI_CONSOLE is not set
 CONFIG_TIMER_EARLY=y
+CONFIG_REGMAP=y
+CONFIG_SPL_REGMAP=y
+CONFIG_LIB_RATIONAL=y
+CONFIG_SPL_LIB_RATIONAL=y
+CONFIG_CLK=y
+CONFIG_CLK_SPACEMIT=y
+CONFIG_SPL_CLK=y
+CONFIG_SYS_MALLOC_F_LEN=0x5000
-- 
2.25.1


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

* [PATCH v2 11/16] i2c: k1: add I2C driver support
  2026-02-10 15:14 [PATCH v2 00/16] Add board support for Spacemit K1 SoC in SPL Raymond Mao
                   ` (9 preceding siblings ...)
  2026-02-10 15:14 ` [PATCH v2 10/16] configs: k1: add default option for clock driver " Raymond Mao
@ 2026-02-10 15:14 ` Raymond Mao
  2026-02-11  4:57   ` Heiko Schocher
  2026-02-10 15:14 ` [PATCH v2 12/16] spacemit: k1: add TLV EEPROM support in SPL Raymond Mao
                   ` (6 subsequent siblings)
  17 siblings, 1 reply; 24+ messages in thread
From: Raymond Mao @ 2026-02-10 15:14 UTC (permalink / raw)
  To: u-boot
  Cc: uboot, u-boot-spacemit, raymond.mao, rick, ycliang, trini, lukma,
	hs, jh80.chung, peng.fan, xypron.glpk, randolph, dlan, junhui.liu,
	neil.armstrong, quentin.schulz, samuel, raymondmaoca, Guodong Xu

From: Raymond Mao <raymond.mao@riscstar.com>

Add I2C driver support on Spacemit K1 SoC using driver model.

Signed-off-by: Raymond Mao <raymond.mao@riscstar.com>
Signed-off-by: Guodong Xu <guodong.xu@riscstar.com>
---
 drivers/i2c/Kconfig  |   7 +
 drivers/i2c/Makefile |   1 +
 drivers/i2c/k1_i2c.c | 516 +++++++++++++++++++++++++++++++++++++++++++
 drivers/i2c/k1_i2c.h |  69 ++++++
 4 files changed, 593 insertions(+)
 create mode 100644 drivers/i2c/k1_i2c.c
 create mode 100644 drivers/i2c/k1_i2c.h

diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig
index 55465dc1d46..eb7219f15a6 100644
--- a/drivers/i2c/Kconfig
+++ b/drivers/i2c/Kconfig
@@ -817,6 +817,13 @@ config SYS_I2C_IHS
         help
           Support for gdsys IHS I2C driver on FPGA bus.
 
+config SYS_I2C_SPACEMIT_K1
+	bool "Spacemit K1 I2C driver"
+	depends on DM_I2C
+	help
+	  Support for Spacemit I2C controller. It's based on
+	  Driver Model.
+
 source "drivers/i2c/muxes/Kconfig"
 
 endif
diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
index 5fe30d0df4f..d57daaba70b 100644
--- a/drivers/i2c/Makefile
+++ b/drivers/i2c/Makefile
@@ -48,6 +48,7 @@ obj-$(CONFIG_SYS_I2C_S3C24X0) += s3c24x0_i2c.o exynos_hs_i2c.o
 obj-$(CONFIG_SYS_I2C_SANDBOX) += sandbox_i2c.o i2c-emul-uclass.o
 obj-$(CONFIG_SYS_I2C_SH) += sh_i2c.o
 obj-$(CONFIG_SYS_I2C_SOFT) += soft_i2c.o
+obj-$(CONFIG_SYS_I2C_SPACEMIT_K1) += k1_i2c.o
 obj-$(CONFIG_SYS_I2C_STM32F7) += stm32f7_i2c.o
 obj-$(CONFIG_SYS_I2C_SUN6I_P2WI) += sun6i_p2wi.o
 obj-$(CONFIG_SYS_I2C_SUN8I_RSB) += sun8i_rsb.o
diff --git a/drivers/i2c/k1_i2c.c b/drivers/i2c/k1_i2c.c
new file mode 100644
index 00000000000..0be2debc828
--- /dev/null
+++ b/drivers/i2c/k1_i2c.c
@@ -0,0 +1,516 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2023-2026 Spacemit, Inc
+ * Copyright (C) 2025-2026 RISCstar Ltd.
+ */
+
+#include <asm/io.h>
+#include <clk.h>
+#include <dm.h>
+#include <dm/device_compat.h>
+#include <i2c.h>
+#include <linux/delay.h>
+#include <linux/iopoll.h>
+#include <reset.h>
+#include "k1_i2c.h"
+
+#define ICR_OFFSET		0x00
+#define ISR_OFFSET		0x04
+#define ISAR_OFFSET		0x08
+#define IDBR_OFFSET		0x0c
+#define ILCR_OFFSET		0x10
+#define IWCR_OFFSET		0x14
+#define IRCR_OFFSET		0x18
+#define IBMR_OFFSET		0x1c
+#define WFIFO_OFFSET		0x20
+#define WFIFO_WPTR_OFFSET	0x24
+#define WFIFO_RPTR_OFFSET	0x28
+#define RFIFO_OFFSET		0x2c
+#define RFIFO_WPTR_OFFSET	0x30
+#define RFIFO_RPTR_OFFSET	0x34
+
+/* All transfers are described by this data structure */
+struct k1_i2c_msg {
+	u8 condition;
+	u8 acknack;
+	u8 direction;
+	u8 data;
+};
+
+struct k1_i2c {
+	u32 icr;
+	u32 isr;
+	u32 isar;
+	u32 idbr;
+	u32 ilcr;
+	u32 iwcr;
+	u32 irst_cyc;
+	u32 ibmr;
+};
+
+struct k1_i2c_priv {
+	int id;
+	void __iomem *base;
+	struct reset_ctl_bulk resets;
+	struct clk clk;
+	u32 clk_rate;
+};
+
+/*
+ * i2c_reset: - reset the host controller
+ *
+ */
+static void i2c_reset(void __iomem *base)
+{
+	u32 icr_mode;
+	u32 val;
+
+	/* Save bus mode (standard or fast speed) for later use */
+	icr_mode = readl(base + ICR_OFFSET) & ICR_MODE_MASK;
+	/* disable unit */
+	val = readl(base + ICR_OFFSET);
+	writel(val & ~ICR_IUE, base + ICR_OFFSET);
+	udelay(10);
+	/* reset the unit */
+	val = readl(base + ICR_OFFSET);
+	val |= ICR_UR;
+	writel(val, base + ICR_OFFSET);
+	udelay(100);
+	/* disable unit */
+	val = readl(base + ICR_OFFSET);
+	writel(val & ~ICR_IUE, base + ICR_OFFSET);
+
+	/* set slave address */
+	writel(0x00, base + ISR_OFFSET);
+	/* set control reg values */
+	writel(I2C_ICR_INIT | icr_mode, base + ICR_OFFSET);
+	writel(I2C_ISR_INIT, base + ISR_OFFSET); /* set clear interrupt bits */
+	val = readl(base + ICR_OFFSET);
+	val |= ICR_IUE;
+	writel(val, base + ICR_OFFSET); /* enable unit */
+	udelay(100);
+}
+
+static inline bool is_isr_set_or_clr(unsigned long isr, unsigned long set_mask,
+				     unsigned long clr_mask)
+{
+	return ((isr & set_mask) == set_mask) && ((isr & clr_mask) == 0);
+}
+
+/*
+ * i2c_isr_set_cleared: - wait until certain bits of the I2C status register
+ *	                  are set and cleared
+ *
+ * @return: 0 on success or -ETIMEDOUT.
+ */
+static int i2c_isr_set_cleared(void __iomem *base, unsigned long set_mask,
+			       unsigned long clr_mask)
+{
+	int cnt = 1000, delay = 10, isr, ret;
+
+	ret = read_poll_timeout(readl, isr,
+				is_isr_set_or_clr(isr, set_mask, clr_mask),
+				delay, delay * cnt, base + ISR_OFFSET);
+	return ret;
+}
+
+/*
+ * i2c_transfer: - Transfer one byte over the i2c bus
+ *
+ * This function can transfer a byte over the i2c bus in both directions.
+ * It is used by the public API functions.
+ *
+ * @return:  0: transfer successful or error code
+ */
+static int i2c_transfer(void __iomem *base, struct k1_i2c_msg *msg)
+{
+	int ret;
+	u32 val;
+
+	if (!msg)
+		goto transfer_error_msg_empty;
+
+	switch (msg->direction) {
+	case I2C_WRITE:
+		/* check if bus is not busy */
+		if (i2c_isr_set_cleared(base, 0, ISR_IBB))
+			goto transfer_error_bus_busy;
+
+		/* start transmission */
+		val = readl(base + ICR_OFFSET);
+		val &= ~ICR_START;
+		writel(val, base + ICR_OFFSET);
+		val = readl(base + ICR_OFFSET);
+		val &= ~ICR_STOP;
+		writel(val, base + ICR_OFFSET);
+		writel(msg->data, base + IDBR_OFFSET);
+		if (msg->condition == I2C_COND_START) {
+			val = readl(base + ICR_OFFSET);
+			val |= ICR_START;
+			writel(val, base + ICR_OFFSET);
+		}
+		if (msg->condition == I2C_COND_STOP) {
+			val = readl(base + ICR_OFFSET);
+			val |= ICR_STOP;
+			writel(val, base + ICR_OFFSET);
+		}
+		if (msg->acknack == I2C_ACKNAK_SENDNAK) {
+			val = readl(base + ICR_OFFSET);
+			val |= ICR_ACKNAK;
+			writel(val, base + ICR_OFFSET);
+		}
+		if (msg->acknack == I2C_ACKNAK_SENDACK) {
+			val = readl(base + ICR_OFFSET);
+			val &= ~ICR_ACKNAK;
+			writel(val, base + ICR_OFFSET);
+		}
+		val = readl(base + ICR_OFFSET);
+		val &= ~ICR_ALDIE;
+		writel(val, base + ICR_OFFSET);
+		val = readl(base + ICR_OFFSET);
+		val |= ICR_TB;
+		writel(val, base + ICR_OFFSET);
+
+		/* transmit register empty? */
+		if (i2c_isr_set_cleared(base, ISR_ITE, 0))
+			goto transfer_error_transmit_timeout;
+
+		/* clear 'transmit empty' state */
+		val = readl(base + ISR_OFFSET);
+		val |= ISR_ITE;
+		writel(val, base + ISR_OFFSET);
+
+		/* wait for ACK from slave */
+		if (msg->acknack == I2C_ACKNAK_WAITACK)
+			if (i2c_isr_set_cleared(base, 0, ISR_ACKNAK))
+				goto transfer_error_ack_missing;
+		break;
+
+	case I2C_READ:
+		/* check if bus is not busy */
+		if (i2c_isr_set_cleared(base, 0, ISR_IBB))
+			goto transfer_error_bus_busy;
+
+		/* start receive */
+		val = readl(base + ICR_OFFSET);
+		val &= ~ICR_START;
+		writel(val, base + ICR_OFFSET);
+		val = readl(base + ICR_OFFSET);
+		val &= ~ICR_STOP;
+		writel(val, base + ICR_OFFSET);
+		if (msg->condition == I2C_COND_START) {
+			val = readl(base + ICR_OFFSET);
+			val |= ICR_START;
+			writel(val, base + ICR_OFFSET);
+		}
+		if (msg->condition == I2C_COND_STOP) {
+			val = readl(base + ICR_OFFSET);
+			val |= ICR_STOP;
+			writel(val, base + ICR_OFFSET);
+		}
+		if (msg->acknack == I2C_ACKNAK_SENDNAK) {
+			val = readl(base + ICR_OFFSET);
+			val |= ICR_ACKNAK;
+			writel(val, base + ICR_OFFSET);
+		}
+		if (msg->acknack == I2C_ACKNAK_SENDACK) {
+			val = readl(base + ICR_OFFSET);
+			val &= ~ICR_ACKNAK;
+			writel(val, base + ICR_OFFSET);
+		}
+		val = readl(base + ICR_OFFSET);
+		val &= ~ICR_ALDIE;
+		writel(val, base + ICR_OFFSET);
+		val = readl(base + ICR_OFFSET);
+		val |= ICR_TB;
+		writel(val, base + ICR_OFFSET);
+
+		/* receive register full? */
+		if (i2c_isr_set_cleared(base, ISR_IRF, 0))
+			goto transfer_error_receive_timeout;
+
+		msg->data = readl(base + IDBR_OFFSET);
+
+		/* clear 'receive empty' state */
+		val = readl(base + ISR_OFFSET);
+		val |= ISR_IRF;
+		writel(val, base + ISR_OFFSET);
+		break;
+	default:
+		goto transfer_error_illegal_param;
+	}
+
+	return 0;
+
+transfer_error_msg_empty:
+	debug("%s: error: 'msg' is empty\n", __func__);
+	ret = -EINVAL;
+	goto i2c_transfer_finish;
+
+transfer_error_transmit_timeout:
+	debug("%s: error: transmit timeout\n", __func__);
+	ret = -ETIMEDOUT;
+	goto i2c_transfer_finish;
+
+transfer_error_ack_missing:
+	debug("%s: error: ACK missing\n", __func__);
+	ret = -EREMOTEIO;
+	goto i2c_transfer_finish;
+
+transfer_error_receive_timeout:
+	debug("%s: error: receive timeout\n", __func__);
+	ret = -ETIMEDOUT;
+	goto i2c_transfer_finish;
+
+transfer_error_illegal_param:
+	debug("%s: error: illegal parameters\n", __func__);
+	ret = -EINVAL;
+	goto i2c_transfer_finish;
+
+transfer_error_bus_busy:
+	debug("%s: error: bus is busy\n", __func__);
+	ret = -EIO;
+	goto i2c_transfer_finish;
+
+i2c_transfer_finish:
+	debug("%s: ISR: 0x%04x\n", __func__, readl(base + ISR_OFFSET));
+	i2c_reset(base);
+	return ret;
+}
+
+static int __i2c_read(void __iomem *base, uchar chip, u8 *addr, int alen,
+		      uchar *buffer, int len)
+{
+	struct k1_i2c_msg msg;
+	int ret;
+
+	debug("%s(chip=0x%02x, addr=0x%02x, alen=0x%02x, len=0x%02x)\n",
+	      __func__, chip, *addr, alen, len);
+
+	if (len == 0) {
+		pr_err("reading zero byte is invalid\n");
+		return -EINVAL;
+	}
+
+	i2c_reset(base);
+
+	/* dummy chip address write */
+	debug("%s: dummy chip address write\n", __func__);
+	msg.condition = I2C_COND_START;
+	msg.acknack   = I2C_ACKNAK_WAITACK;
+	msg.direction = I2C_WRITE;
+	msg.data = (chip << 1);
+	msg.data &= 0xFE;
+	ret = i2c_transfer(base, &msg);
+	if (ret)
+		return ret;
+
+	/*
+	 * send memory address bytes;
+	 * alen defines how much bytes we have to send.
+	 */
+	while (--alen >= 0) {
+		debug("%s: send address byte %02x (alen=%d)\n",
+		      __func__, *addr, alen);
+		msg.condition = I2C_COND_NORMAL;
+		msg.acknack   = I2C_ACKNAK_WAITACK;
+		msg.direction = I2C_WRITE;
+		msg.data      = addr[alen];
+		ret = i2c_transfer(base, &msg);
+		if (ret)
+			return ret;
+	}
+
+	/* start read sequence */
+	debug("%s: start read sequence\n", __func__);
+	msg.condition = I2C_COND_START;
+	msg.acknack   = I2C_ACKNAK_WAITACK;
+	msg.direction = I2C_WRITE;
+	msg.data      = (chip << 1);
+	msg.data     |= 0x01;
+	ret = i2c_transfer(base, &msg);
+	if (ret)
+		return ret;
+
+	/* read bytes; send NACK at last byte */
+	while (len--) {
+		if (len == 0) {
+			msg.condition = I2C_COND_STOP;
+			msg.acknack   = I2C_ACKNAK_SENDNAK;
+		} else {
+			msg.condition = I2C_COND_NORMAL;
+			msg.acknack   = I2C_ACKNAK_SENDACK;
+		}
+
+		msg.direction = I2C_READ;
+		msg.data      = 0x00;
+		ret = i2c_transfer(base, &msg);
+		if (ret)
+			return ret;
+
+		*buffer = msg.data;
+		debug("%s: reading byte (%p)=0x%02x\n",
+		      __func__, buffer, *buffer);
+		buffer++;
+	}
+
+	i2c_reset(base);
+
+	return 0;
+}
+
+static int __i2c_write(struct k1_i2c *base, uchar chip, u8 *addr, int alen,
+		       uchar *buffer, int len)
+{
+	struct k1_i2c_msg msg;
+	int ret;
+
+	debug("%s(chip=0x%02x, addr=0x%02x, alen=0x%02x, len=0x%02x)\n",
+	      __func__, chip, *addr, alen, len);
+
+	i2c_reset(base);
+
+	/* chip address write */
+	debug("%s: chip address write\n", __func__);
+	msg.condition = I2C_COND_START;
+	msg.acknack   = I2C_ACKNAK_WAITACK;
+	msg.direction = I2C_WRITE;
+	msg.data = (chip << 1);
+	msg.data &= 0xFE;
+	ret = i2c_transfer(base, &msg);
+	if (ret)
+		return ret;
+
+	/*
+	 * send memory address bytes;
+	 * alen defines how much bytes we have to send.
+	 */
+	while (--alen >= 0) {
+		debug("%s: send address byte %02x (alen=%d)\n",
+		      __func__, *addr, alen);
+		msg.condition = I2C_COND_NORMAL;
+		msg.acknack   = I2C_ACKNAK_WAITACK;
+		msg.direction = I2C_WRITE;
+		msg.data      = addr[alen];
+		ret = i2c_transfer(base, &msg);
+		if (ret)
+			return ret;
+	}
+
+	/* write bytes; send NACK at last byte */
+	while (len--) {
+		debug("%s: writing byte (%p)=0x%02x\n",
+		      __func__, buffer, *buffer);
+
+		if (len == 0)
+			msg.condition = I2C_COND_STOP;
+		else
+			msg.condition = I2C_COND_NORMAL;
+
+		msg.acknack   = I2C_ACKNAK_WAITACK;
+		msg.direction = I2C_WRITE;
+		msg.data      = *(buffer++);
+
+		ret = i2c_transfer(base, &msg);
+		if (ret)
+			return ret;
+	}
+
+	i2c_reset(base);
+
+	return 0;
+}
+
+static int k1_i2c_xfer(struct udevice *bus, struct i2c_msg *msg, int nmsgs)
+{
+	struct k1_i2c_priv *i2c = dev_get_priv(bus);
+	struct i2c_msg *dmsg, *omsg, dummy;
+
+	memset(&dummy, 0, sizeof(struct i2c_msg));
+
+	/*
+	 * We expect either two messages (one with an offset and one with the
+	 * actual data) or one message (just data or offset/data combined)
+	 */
+	if (nmsgs > 2 || nmsgs == 0) {
+		debug("%s: Only one or two messages are supported.", __func__);
+		return -EINVAL;
+	}
+
+	omsg = nmsgs == 1 ? &dummy : msg;
+	dmsg = nmsgs == 1 ? msg : msg + 1;
+
+	if (dmsg->flags & I2C_M_RD)
+		return __i2c_read(i2c->base, dmsg->addr, omsg->buf,
+				  omsg->len, dmsg->buf, dmsg->len);
+	else
+		return __i2c_write(i2c->base, dmsg->addr, omsg->buf,
+				   omsg->len, dmsg->buf, dmsg->len);
+}
+
+static int k1_i2c_set_bus_speed(struct udevice *bus, unsigned int speed)
+{
+	struct k1_i2c_priv *priv = dev_get_priv(bus);
+	void __iomem *base = priv->base;
+	u32 val;
+
+	if (speed > I2C_SPEED_STANDARD_RATE)
+		val = ICR_FM;
+	else
+		val = ICR_SM;
+	clrsetbits_le32(base + ICR_OFFSET, ICR_MODE_MASK, val);
+
+	return 0;
+}
+
+static int k1_i2c_probe(struct udevice *bus)
+{
+	struct k1_i2c_priv *priv = dev_get_priv(bus);
+	struct reset_ctl reset;
+	int ret;
+
+	priv->id = dev_seq(bus);
+	ret = reset_get_by_index(bus, 0, &reset);
+	if (ret) {
+		dev_err(bus, "%s: can not get reset\n", __func__);
+		return ret;
+	}
+	reset_assert(&reset);
+	udelay(10);
+	reset_deassert(&reset);
+	udelay(10);
+
+	ret = clk_get_by_index(bus, 0, &priv->clk);
+	if (ret)
+		return ret;
+
+	ret = clk_enable(&priv->clk);
+	if (ret && ret != -ENOSYS && ret != -EOPNOTSUPP) {
+		debug("%s: failed to enable clock\n", __func__);
+		return ret;
+	}
+	priv->clk_rate = clk_get_rate(&priv->clk);
+
+	priv->base = (void *)devfdt_get_addr_ptr(bus);
+	k1_i2c_set_bus_speed(bus, priv->clk_rate);
+	return 0;
+}
+
+static const struct dm_i2c_ops k1_i2c_ops = {
+	.xfer		= k1_i2c_xfer,
+	.set_bus_speed	= k1_i2c_set_bus_speed,
+};
+
+static const struct udevice_id k1_i2c_ids[] = {
+	{ .compatible = "spacemit,k1-i2c" },
+	{ }
+};
+
+U_BOOT_DRIVER(i2c_spacemit) = {
+	.name	= "i2c_spacemit",
+	.id	= UCLASS_I2C,
+	.of_match = k1_i2c_ids,
+	.probe	= k1_i2c_probe,
+	.priv_auto = sizeof(struct k1_i2c_priv),
+	.ops	= &k1_i2c_ops,
+};
diff --git a/drivers/i2c/k1_i2c.h b/drivers/i2c/k1_i2c.h
new file mode 100644
index 00000000000..856947aa43b
--- /dev/null
+++ b/drivers/i2c/k1_i2c.h
@@ -0,0 +1,69 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2023-2026 Spacemit Ltd.
+ * Copyright (C) 2025-2026 RISCstar Ltd.
+ */
+
+#ifndef __SPACEMIT_I2C_H
+#define __SPACEMIT_I2C_H
+
+/* Shall the current transfer have a start/stop condition? */
+#define I2C_COND_NORMAL		0
+#define I2C_COND_START		1
+#define I2C_COND_STOP		2
+
+/* Shall the current transfer be ack/nacked or being waited for it? */
+#define I2C_ACKNAK_WAITACK	1
+#define I2C_ACKNAK_SENDACK	2
+#define I2C_ACKNAK_SENDNAK	4
+
+/* Specify who shall transfer the data (master or slave) */
+#define I2C_READ		0
+#define I2C_WRITE		1
+
+#if (CONFIG_SYS_I2C_SPEED == 400000)
+#define I2C_ICR_INIT	(ICR_FM | ICR_BEIE | ICR_IRFIE | ICR_ITEIE |	\
+			 ICR_GCD | ICR_SCLE)
+#else
+#define I2C_ICR_INIT	(ICR_BEIE | ICR_IRFIE | ICR_ITEIE | ICR_GCD |	\
+			 ICR_SCLE)
+#endif
+
+/* ----- Control register bits ---------------------------------------- */
+
+#define ICR_START	0x1		/* start bit */
+#define ICR_STOP	0x2		/* stop bit */
+#define ICR_ACKNAK	0x4		/* send ACK(0) or NAK(1) */
+#define ICR_TB		0x8		/* transfer byte bit */
+#define ICR_MA		BIT(12)		/* master abort */
+#define ICR_SCLE	BIT(13)		/* master clock enable, mona SCLEA */
+#define ICR_IUE		BIT(14)		/* unit enable */
+#define ICR_GCD		BIT(21)		/* general call disable */
+#define ICR_ITEIE	BIT(19)		/* enable tx interrupts */
+#define ICR_IRFIE	BIT(20)		/* enable rx interrupts, mona: DRFIE */
+#define ICR_BEIE	BIT(22)		/* enable bus error ints */
+#define ICR_SSDIE	BIT(24)		/* slave STOP detected int enable */
+#define ICR_ALDIE	BIT(18)		/* enable arbitration interrupt */
+#define ICR_SADIE	BIT(23)		/* slave address detected int enable */
+#define ICR_UR		BIT(10)		/* unit reset */
+#define ICR_SM		(0x0)		/* Standard Mode */
+#define ICR_FM		BIT(8)		/* Fast Mode */
+#define ICR_MODE_MASK	(0x300)		/* Mode mask */
+
+/* ----- Status register bits ----------------------------------------- */
+
+#define ISR_RWM		BIT(13)		/* read/write mode */
+#define ISR_ACKNAK	BIT(14)		/* ack/nak status */
+#define ISR_UB		BIT(15)		/* unit busy */
+#define ISR_IBB		BIT(16)		/* bus busy */
+#define ISR_SSD		BIT(24)		/* slave stop detected */
+#define ISR_ALD		BIT(18)		/* arbitration loss detected */
+#define ISR_ITE		BIT(19)		/* tx buffer empty */
+#define ISR_IRF		BIT(20)		/* rx buffer full */
+#define ISR_GCAD	BIT(21)		/* general call address detected */
+#define ISR_SAD		BIT(23)		/* slave address detected */
+#define ISR_BED		BIT(22)		/* bus error no ACK/NAK */
+
+#define I2C_ISR_INIT	0x1FDE000
+
+#endif
-- 
2.25.1


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

* [PATCH v2 12/16] spacemit: k1: add TLV EEPROM support in SPL
  2026-02-10 15:14 [PATCH v2 00/16] Add board support for Spacemit K1 SoC in SPL Raymond Mao
                   ` (10 preceding siblings ...)
  2026-02-10 15:14 ` [PATCH v2 11/16] i2c: k1: add I2C driver support Raymond Mao
@ 2026-02-10 15:14 ` Raymond Mao
  2026-02-10 15:14 ` [PATCH v2 13/16] spacemit: k1: Add DDR firmware support to SPL Raymond Mao
                   ` (5 subsequent siblings)
  17 siblings, 0 replies; 24+ messages in thread
From: Raymond Mao @ 2026-02-10 15:14 UTC (permalink / raw)
  To: u-boot
  Cc: uboot, u-boot-spacemit, raymond.mao, rick, ycliang, trini, lukma,
	hs, jh80.chung, peng.fan, xypron.glpk, randolph, dlan, junhui.liu,
	neil.armstrong, quentin.schulz, samuel, raymondmaoca, Guodong Xu

From: Raymond Mao <raymond.mao@riscstar.com>

And support for required components including clock, I2C controller,
and I2C EEPROM.

Signed-off-by: Raymond Mao <raymond.mao@riscstar.com>
Signed-off-by: Guodong Xu <guodong.xu@riscstar.com>
---
 arch/riscv/dts/k1-spl.dts     |  28 +++++++++
 arch/riscv/dts/k1.dtsi        | 104 ++++++++++++++++++++++++++++++++++
 board/spacemit/k1/spl.c       | 104 +++++++++++++++++++++++++++++++++-
 board/spacemit/k1/tlv_codes.h |  22 +++++++
 configs/spacemit_k1_defconfig |  13 +++++
 5 files changed, 270 insertions(+), 1 deletion(-)
 create mode 100644 board/spacemit/k1/tlv_codes.h

diff --git a/arch/riscv/dts/k1-spl.dts b/arch/riscv/dts/k1-spl.dts
index a74eaaf6a8f..74e9957b83a 100644
--- a/arch/riscv/dts/k1-spl.dts
+++ b/arch/riscv/dts/k1-spl.dts
@@ -5,6 +5,7 @@
  */
 
 /dts-v1/;
+
 #include "k1.dtsi"
 #include "binman.dtsi"
 
@@ -64,6 +65,33 @@
 		status = "okay";
 		bootph-pre-ram;
 	};
+
+	i2c@d4012000 {		/* i2c2 */
+		status = "okay";
+		bootph-pre-ram;
+		eeprom: eeprom {
+			compatible = "atmel,24c02";
+			reg = <0x50>;
+			status = "okay";
+			bootph-pre-ram;
+		};
+	};
+
+	i2c@d401d800 {		/* i2c8 */
+		status = "okay";
+		bootph-pre-ram;
+		pmic@41 {
+			compatible = "pmic";
+			reg = <0x41>;
+			status = "okay";
+			bootph-pre-ram;
+		};
+	};
+
+	reset-controller@d4050000 {
+		status = "okay";
+		bootph-pre-ram;
+	};
 };
 
 &uart0 {
diff --git a/arch/riscv/dts/k1.dtsi b/arch/riscv/dts/k1.dtsi
index 20f1cb57462..682d2fb88e2 100644
--- a/arch/riscv/dts/k1.dtsi
+++ b/arch/riscv/dts/k1.dtsi
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0 OR MIT
 /*
  * Copyright (C) 2024 Yangyu Chen <cyy@cyyself.name>
+ * Copyright (C) 2025-2026 RISCstar Ltd.
  */
 
 #include <dt-bindings/clock/spacemit,k1-syscon.h>
@@ -576,6 +577,21 @@
 			status = "disabled";
 		};
 
+		reset: reset-controller@d4050000 {
+			compatible = "spacemit,k1-reset";
+			reg = <0x0 0xd4050000 0x0 0x209c>,
+			    <0x0 0xd4282800 0x0 0x400>,
+			    <0x0 0xd4015000 0x0 0x1000>,
+			    <0x0 0xd4090000 0x0 0x1000>,
+			    <0x0 0xd4282c00 0x0 0x400>,
+			    <0x0 0xd8440000 0x0 0x98>,
+			    <0x0 0xc0000000 0x0 0x4280>,
+			    <0x0 0xf0610000 0x0 0x20>;
+			reg-names = "mpmu", "apmu", "apbc", "apbs", "ciu", "dciu", "ddrc", "apbc2";
+			#reset-cells = <1>;
+			status = "disabled";
+		};
+
 		syscon_mpmu: system-controller@d4050000 {
 			compatible = "spacemit,k1-syscon-mpmu";
 			reg = <0x0 0xd4050000 0x0 0x209c>;
@@ -608,6 +624,94 @@
 			#reset-cells = <1>;
 		};
 
+		i2c0: i2c@d4010800 {
+			compatible = "spacemit,k1-i2c";
+			reg = <0x0 0xd4010800 0x0 0x38>;
+			clocks = <&syscon_apbc CLK_TWSI0>;
+			resets = <&reset RESET_TWSI0>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		i2c1: i2c@d4011000 {
+			compatible = "spacemit,k1-i2c";
+			reg = <0x0 0xd4011000 0x0 0x38>;
+			clocks = <&syscon_apbc CLK_TWSI1>;
+			resets = <&reset RESET_TWSI1>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		i2c2: i2c@d4012000 {
+			compatible = "spacemit,k1-i2c";
+			reg = <0x0 0xd4012000 0x0 0x38>;
+			clocks = <&syscon_apbc CLK_TWSI2>;
+			resets = <&reset RESET_TWSI2>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		i2c3: i2c@d4014000 {
+			compatible = "spacemit,k1-i2c";
+			reg = <0x0 0xd4014000 0x0 0x38>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		i2c4: i2c@d4012800 {
+			compatible = "spacemit,k1-i2c";
+			reg = <0x0 0xd4012800 0x0 0x38>;
+			clocks = <&syscon_apbc CLK_TWSI4>;
+			resets = <&reset RESET_TWSI4>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		i2c5: i2c@d4013800 {
+			compatible = "spacemit,k1-i2c";
+			reg = <0x0 0xd4013800 0x0 0x38>;
+			clocks = <&syscon_apbc CLK_TWSI5>;
+			resets = <&reset RESET_TWSI5>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		i2c6: i2c@d4018800 {
+			compatible = "spacemit,k1-i2c";
+			reg = <0x0 0xd4018800 0x0 0x38>;
+			clocks = <&syscon_apbc CLK_TWSI6>;
+			resets = <&reset RESET_TWSI6>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		i2c7: i2c@d401d000 {
+			compatible = "spacemit,k1-i2c";
+			reg = <0x0 0xd401d000 0x0 0x38>;
+			clocks = <&syscon_apbc CLK_TWSI7>;
+			resets = <&reset RESET_TWSI7>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		i2c8: i2c@d401d800 {
+			compatible = "spacemit,k1-i2c";
+			reg = <0x0 0xd401d800 0x0 0x38>;
+			clocks = <&syscon_apbc CLK_TWSI8>;
+			resets = <&reset RESET_TWSI8>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
 		plic: interrupt-controller@e0000000 {
 			compatible = "spacemit,k1-plic", "sifive,plic-1.0.0";
 			reg = <0x0 0xe0000000 0x0 0x4000000>;
diff --git a/board/spacemit/k1/spl.c b/board/spacemit/k1/spl.c
index 78f26616347..182e833849d 100644
--- a/board/spacemit/k1/spl.c
+++ b/board/spacemit/k1/spl.c
@@ -3,10 +3,87 @@
  * Copyright (c) 2025-2026, RISCstar Ltd.
  */
 
+#include <asm/io.h>
+#include <clk.h>
+#include <clk-uclass.h>
+#include <configs/k1.h>
 #include <dm/device.h>
 #include <dm/uclass.h>
+#include <i2c.h>
+#include <linux/delay.h>
 #include <log.h>
 #include <spl.h>
+#include <tlv_eeprom.h>
+
+#define MUX_MODE4		4
+#define EDGE_NONE		BIT(6)
+#define PULL_UP			(6 << 13)       /* bit[15:13] 110 */
+#define PAD_DS_MEDIUM		BIT(12)
+#define PAD_1V8_DS2		PAD_DS_MEDIUM
+#define I2C_PIN_CONFIG(x)       ((x) | EDGE_NONE | PULL_UP | PAD_1V8_DS2)
+#define I2C_BUF_SIZE		64
+
+#define MFP_GPIO_84		0xd401e154
+#define MFP_GPIO_85		0xd401e158
+
+static void reset_early_init(void)
+{
+	struct udevice *dev;
+	int ret;
+
+	ret = uclass_get_device(UCLASS_RESET, 0, &dev);
+	if (ret)
+		panic("Fail to detect reset controller.\n");
+}
+
+static void i2c_early_init(void)
+{
+	struct udevice *bus;
+
+	// eeprom: I2C2, pin group(GPIO_84, GPIO_85)
+	writel(I2C_PIN_CONFIG(MUX_MODE4), (void __iomem *)MFP_GPIO_84);
+	writel(I2C_PIN_CONFIG(MUX_MODE4), (void __iomem *)MFP_GPIO_85);
+	udelay(100);
+	uclass_first_device(UCLASS_I2C, &bus);
+	while (bus) {
+		uclass_next_device(&bus);
+		if (!bus)
+			break;
+	}
+}
+
+int read_product_name(char *name, int size)
+{
+	u8 eeprom_data[TLV_TOTAL_LEN_MAX], *p;
+	struct tlvinfo_header *tlv_hdr;
+	struct tlvinfo_tlv *tlv_entry;
+	int ret, i = 0;
+	u32 entry_size;
+
+	if (!name || size <= 0)
+		return -EINVAL;
+	ret = read_tlvinfo_tlv_eeprom(eeprom_data, &tlv_hdr,
+				      &tlv_entry, i);
+	if (ret)
+		return ret;
+	p = (u8 *)tlv_entry;
+	for (i = 0; i < tlv_hdr->totallen; ) {
+		if (tlv_entry->type == TLV_CODE_PRODUCT_NAME) {
+			if (tlv_entry->length < size)
+				size = tlv_entry->length;
+			memset(name, 0, size);
+			memcpy(name, &tlv_entry->value[0], size);
+			return 0;
+		}
+		if (tlv_entry->type == TLV_CODE_CRC_32)
+			return -ENOENT;
+		entry_size = tlv_entry->length + sizeof(struct tlvinfo_tlv);
+		i += entry_size;
+		p += entry_size;
+		tlv_entry = (struct tlvinfo_tlv *)p;
+	}
+	return -ENOENT;
+}
 
 static void clk_early_init(void)
 {
@@ -44,6 +121,7 @@ void serial_early_init(void)
 
 void board_init_f(ulong dummy)
 {
+	u8 i2c_buf[I2C_BUF_SIZE];
 	int ret;
 
 	ret = spl_early_init();
@@ -52,12 +130,36 @@ void board_init_f(ulong dummy)
 
 	riscv_cpu_setup();
 
+	reset_early_init();
 	clk_early_init();
 	serial_early_init();
+
 	preloader_console_init();
+
+	i2c_early_init();
+	ret = read_product_name(i2c_buf, I2C_BUF_SIZE);
+	if (ret)
+		log_info("Fail to detect board:%d\n", ret);
+	else
+		log_info("Get board name:%s\n", (char *)i2c_buf);
 }
 
 u32 spl_boot_device(void)
 {
-	return BOOT_DEVICE_NONE;
+	return BOOT_DEVICE_NOR;
+}
+
+void pmic_init(void)
+{
+	struct udevice *pmic_dev = NULL;
+	int ret;
+
+	ret = uclass_get_device(UCLASS_PMIC, 0, &pmic_dev);
+	if (ret)
+		panic("Fail to detect PMIC:%d\n", ret);
+}
+
+void spl_board_init(void)
+{
+	pmic_init();
 }
diff --git a/board/spacemit/k1/tlv_codes.h b/board/spacemit/k1/tlv_codes.h
new file mode 100644
index 00000000000..e40fbdcee6d
--- /dev/null
+++ b/board/spacemit/k1/tlv_codes.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2025-2026 RISCstar Ltd.
+ */
+
+#ifndef __TLV_CODES_H
+#define __TLV_CODES_H
+
+#define TLV_CODE_SDK_VERSION		0x40
+#define TLV_CODE_DDR_CSNUM		0x41
+#define TLV_CODE_DDR_TYPE		0x42
+#define TLV_CODE_DDR_DATARATE		0x43
+#define TLV_CODE_DDR_TX_ODT		0x44
+
+#define TLV_CODE_WIFI_MAC_ADDR		0x60
+#define TLV_CODE_BLUETOOTH_ADDR		0x61
+
+#define TLV_CODE_PMIC_TYPE		0x80
+#define TLV_CODE_EEPROM_I2C_INDEX	0x81
+#define TLV_CODE_EEPROM_PIN_GROUP	0x82
+
+#endif /* __TLV_CODES_H */
diff --git a/configs/spacemit_k1_defconfig b/configs/spacemit_k1_defconfig
index e64687e95ce..65e8143a0bd 100644
--- a/configs/spacemit_k1_defconfig
+++ b/configs/spacemit_k1_defconfig
@@ -34,6 +34,7 @@ CONFIG_ENV_OVERWRITE=y
 CONFIG_PINCTRL=y
 CONFIG_PINCTRL_SINGLE=y
 CONFIG_RESET_SPACEMIT_K1=y
+CONFIG_SPL_RESET_SPACEMIT_K1=y
 CONFIG_SYS_NS16550=y
 CONFIG_SYS_NS16550_MEM32=y
 CONFIG_DEBUG_UART=y
@@ -52,3 +53,15 @@ CONFIG_CLK=y
 CONFIG_CLK_SPACEMIT=y
 CONFIG_SPL_CLK=y
 CONFIG_SYS_MALLOC_F_LEN=0x5000
+CONFIG_SPL_DM_RESET=y
+CONFIG_DM_I2C=y
+CONFIG_SPL_I2C=y
+CONFIG_SYS_I2C_SPACEMIT_K1=y
+CONFIG_MISC=y
+CONFIG_SPL_MISC=y
+CONFIG_SPL_DRIVERS_MISC=y
+CONFIG_I2C_EEPROM=y
+CONFIG_SPL_I2C_EEPROM=y
+CONFIG_CMD_TLV_EEPROM=y
+CONFIG_SPL_CMD_TLV_EEPROM=y
+CONFIG_LOG=y
-- 
2.25.1


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

* [PATCH v2 13/16] spacemit: k1: Add DDR firmware support to SPL
  2026-02-10 15:14 [PATCH v2 00/16] Add board support for Spacemit K1 SoC in SPL Raymond Mao
                   ` (11 preceding siblings ...)
  2026-02-10 15:14 ` [PATCH v2 12/16] spacemit: k1: add TLV EEPROM support in SPL Raymond Mao
@ 2026-02-10 15:14 ` Raymond Mao
  2026-02-10 15:14 ` [PATCH v2 14/16] power: pmic: add support for Spacemit P1 PMIC Raymond Mao
                   ` (4 subsequent siblings)
  17 siblings, 0 replies; 24+ messages in thread
From: Raymond Mao @ 2026-02-10 15:14 UTC (permalink / raw)
  To: u-boot
  Cc: uboot, u-boot-spacemit, raymond.mao, rick, ycliang, trini, lukma,
	hs, jh80.chung, peng.fan, xypron.glpk, randolph, dlan, junhui.liu,
	neil.armstrong, quentin.schulz, samuel, raymondmaoca, Guodong Xu

From: Raymond Mao <raymond.mao@riscstar.com>

Include DDR initialization firmware in the SPL image. The firmware
path can be specified via the DDR_FW_FILE environment variable. If
the firmware is not found, an empty placeholder file is created to
allow the build to proceed without DDR initialization support.

Signed-off-by: Raymond Mao <raymond.mao@riscstar.com>
Signed-off-by: Guodong Xu <guodong.xu@riscstar.com>
---
 arch/riscv/dts/k1-spl.dts  |  24 +++++++-
 board/spacemit/k1/Makefile |  20 ++++++
 board/spacemit/k1/spl.c    | 122 +++++++++++++++++++++++++++++++++++++
 3 files changed, 165 insertions(+), 1 deletion(-)

diff --git a/arch/riscv/dts/k1-spl.dts b/arch/riscv/dts/k1-spl.dts
index 74e9957b83a..e118767e6db 100644
--- a/arch/riscv/dts/k1-spl.dts
+++ b/arch/riscv/dts/k1-spl.dts
@@ -7,7 +7,6 @@
 /dts-v1/;
 
 #include "k1.dtsi"
-#include "binman.dtsi"
 
 / {
 	model = "spacemit k1 spl";
@@ -20,6 +19,29 @@
 	chosen {
 		stdout-path = "serial0:115200n8";
 	};
+
+	binman {
+		u-boot-spl-ddr {
+			type = "section";
+			filename = "u-boot-spl-ddr.bin";
+			pad-byte = <0xff>;
+
+			u-boot-spl {
+			};
+
+			ddr-fw {
+				type = "blob";
+				filename = "ddr_fw.bin";
+				align = <64>;
+			};
+
+			u-boot-any {
+				type = "section";
+				size = <0>;
+				offset = <0>;
+			};
+		};
+	};
 };
 
 &vctcxo_1m {
diff --git a/board/spacemit/k1/Makefile b/board/spacemit/k1/Makefile
index f9cbf4b0e06..827b1e507c7 100644
--- a/board/spacemit/k1/Makefile
+++ b/board/spacemit/k1/Makefile
@@ -5,3 +5,23 @@
 
 obj-y := board.o
 obj-$(CONFIG_SPL_BUILD) += spl.o
+
+DDR_FW_SRC ?= $(DDR_FW_FILE)
+FW_TARGET = $(objtree)/ddr_fw.bin
+
+$(obj)/spl.o: $(FW_TARGET)
+
+$(FW_TARGET):
+	@echo "Preparing DDR firmware..."
+	@if [ -n "$(DDR_FW_SRC)" ] && [ -f "$(DDR_FW_SRC)" ]; then \
+		echo "  Copying from: $(DDR_FW_SRC)"; \
+		cp "$(DDR_FW_SRC)" $@; \
+	elif [ -f $@ ]; then \
+		echo "  Using existing $@"; \
+	else \
+		echo "  Note: No firmware found, creating empty file"; \
+		echo "  (Set DDR_FW_FILE to specify firmware location)"; \
+		touch $@; \
+	fi
+
+clean-files += $(FW_TARGET)
diff --git a/board/spacemit/k1/spl.c b/board/spacemit/k1/spl.c
index 182e833849d..95b61f5aa90 100644
--- a/board/spacemit/k1/spl.c
+++ b/board/spacemit/k1/spl.c
@@ -4,8 +4,11 @@
  */
 
 #include <asm/io.h>
+#include <binman.h>
+#include <binman_sym.h>
 #include <clk.h>
 #include <clk-uclass.h>
+#include <cpu_func.h>
 #include <configs/k1.h>
 #include <dm/device.h>
 #include <dm/uclass.h>
@@ -14,6 +17,7 @@
 #include <log.h>
 #include <spl.h>
 #include <tlv_eeprom.h>
+#include "tlv_codes.h"
 
 #define MUX_MODE4		4
 #define EDGE_NONE		BIT(6)
@@ -26,6 +30,29 @@
 #define MFP_GPIO_84		0xd401e154
 #define MFP_GPIO_85		0xd401e158
 
+#define DDR_FIRMWARE_BASE	0xc082d000
+
+#define DDR_DEFAULT_CS_NUM      2
+#define DDR_DEFAULT_TYPE        "LPDDR4X"
+#define DDR_DEFAULT_TX_ODT      80
+#define DDR_DEFAULT_DATA_RATE   2400
+
+#define MAGIC_NUM		0xaa55aa55
+
+typedef void (*puts_func_t)(const char *s);
+typedef int (*ddr_init_func_t)(u64 ddr_base, u32 cs_num, u32 data_rate,
+			       puts_func_t puts);
+
+struct ddr_cfg {
+	u32     data_rate;
+	u32     cs_num;
+	u32     tx_odt;
+	u8      type[I2C_BUF_SIZE];
+};
+
+binman_sym_declare(ulong, ddr_fw, image_pos);
+binman_sym_declare(ulong, ddr_fw, size);
+
 static void reset_early_init(void)
 {
 	struct udevice *dev;
@@ -119,6 +146,100 @@ void serial_early_init(void)
 		panic("Serial uclass init failed: %d\n", ret);
 }
 
+/* Set default value for DDR chips */
+static void ddr_cfg_init(struct ddr_cfg *cfg)
+{
+	memset(cfg, 0, sizeof(struct ddr_cfg));
+	cfg->data_rate = DDR_DEFAULT_DATA_RATE;
+	cfg->cs_num = DDR_DEFAULT_CS_NUM;
+	cfg->tx_odt = DDR_DEFAULT_TX_ODT;
+	strcpy(cfg->type, DDR_DEFAULT_TYPE);
+}
+
+int read_ddr_info(struct ddr_cfg *cfg)
+{
+	u8 eeprom_data[TLV_TOTAL_LEN_MAX], *p;
+	struct tlvinfo_header *tlv_hdr;
+	struct tlvinfo_tlv *tlv_entry;
+	u32 size, entry_size;
+	int ret, i;
+	bool found = false;
+
+	if (!cfg)
+		return -EINVAL;
+	ddr_cfg_init(cfg);
+	ret = read_tlvinfo_tlv_eeprom(eeprom_data, &tlv_hdr,
+				      &tlv_entry, i);
+	if (ret)
+		return ret;
+	p = (u8 *)tlv_entry;
+	for (i = 0; i < tlv_hdr->totallen; ) {
+		switch (tlv_entry->type) {
+		case TLV_CODE_DDR_CSNUM:
+			memcpy(&cfg->cs_num, &tlv_entry->value[0], 1);
+			found = true;
+			break;
+		case TLV_CODE_DDR_TYPE:
+			size = min((u32)tlv_entry->length, (u32)I2C_BUF_SIZE);
+			memcpy(&cfg->type[0], &tlv_entry->value[0], size);
+			found = true;
+			break;
+		case TLV_CODE_DDR_DATARATE:
+			memcpy(&cfg->data_rate, &tlv_entry->value[0], 2);
+			found = true;
+			break;
+		case TLV_CODE_DDR_TX_ODT:
+			memcpy(&cfg->tx_odt, &tlv_entry->value[0], 1);
+			found = true;
+			break;
+		case TLV_CODE_CRC_32:
+			if (!found)
+				return -ENOENT;
+			return 0;
+		}
+		entry_size = tlv_entry->length + sizeof(struct tlvinfo_tlv);
+		i += entry_size;
+		p += entry_size;
+		tlv_entry = (struct tlvinfo_tlv *)p;
+	}
+	if (!found)
+		return -ENOENT;
+	return 0;
+}
+
+/* Load DDR firmware */
+void ddr_early_init(void)
+{
+	void __iomem *src, *dst;
+	ulong pos, size;
+	struct ddr_cfg cfg;
+	ddr_init_func_t ddr_init;
+
+	pos = binman_sym(ulong, ddr_fw, image_pos);
+	size = binman_sym(ulong, ddr_fw, size);
+	src = (void __iomem *)pos;
+	dst = (void __iomem *)(DDR_FIRMWARE_BASE);
+	log_info("DDR firmware: [0x%lx]:0x%x, size:0x%lx\n", pos, readl(src), size);
+	memcpy((u8 *)dst, (u8 *)src, size);
+	size = round_up(size, 64);
+	flush_dcache_range((u32)(u64)dst, (u32)(u64)dst + size);
+
+	read_ddr_info(&cfg);
+	ddr_init = (ddr_init_func_t)DDR_FIRMWARE_BASE;
+#ifdef DEBUG
+	ddr_init(0xc0000000, cfg.cs_num, cfg.data_rate, puts);
+#else
+	ddr_init(0xc0000000, cfg.cs_num, cfg.data_rate, NULL);
+#endif
+	writel(MAGIC_NUM, (void __iomem *)0x00000000);
+	flush_dcache_range(0, 64);
+	invalidate_dcache_range(0, 64);
+	if (readl((void __iomem *)0x00000000) == MAGIC_NUM)
+		log_info("DDR is ready\n");
+	else
+		log_info("DDR isn't invalid\n");
+}
+
 void board_init_f(ulong dummy)
 {
 	u8 i2c_buf[I2C_BUF_SIZE];
@@ -142,6 +263,7 @@ void board_init_f(ulong dummy)
 		log_info("Fail to detect board:%d\n", ret);
 	else
 		log_info("Get board name:%s\n", (char *)i2c_buf);
+	ddr_early_init();
 }
 
 u32 spl_boot_device(void)
-- 
2.25.1


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

* [PATCH v2 14/16] power: pmic: add support for Spacemit P1 PMIC
  2026-02-10 15:14 [PATCH v2 00/16] Add board support for Spacemit K1 SoC in SPL Raymond Mao
                   ` (12 preceding siblings ...)
  2026-02-10 15:14 ` [PATCH v2 13/16] spacemit: k1: Add DDR firmware support to SPL Raymond Mao
@ 2026-02-10 15:14 ` Raymond Mao
  2026-03-03  3:37   ` Peng Fan
  2026-02-10 15:14 ` [PATCH v2 15/16] power: regulator: add support for Spacemit P1 SoC Raymond Mao
                   ` (3 subsequent siblings)
  17 siblings, 1 reply; 24+ messages in thread
From: Raymond Mao @ 2026-02-10 15:14 UTC (permalink / raw)
  To: u-boot
  Cc: uboot, u-boot-spacemit, raymond.mao, rick, ycliang, trini, lukma,
	hs, jh80.chung, peng.fan, xypron.glpk, randolph, dlan, junhui.liu,
	neil.armstrong, quentin.schulz, samuel, raymondmaoca, Guodong Xu

From: Raymond Mao <raymond.mao@riscstar.com>

Spacemit's PMIC is used by Spacemit K1 SoC. It contains voltage
regulators, GPIOs and Watchdog.

Signed-off-by: Raymond Mao <raymond.mao@riscstar.com>
Signed-off-by: Guodong Xu <guodong.xu@riscstar.com>
---
 drivers/power/pmic/Kconfig            |  17 +++
 drivers/power/pmic/Makefile           |   1 +
 drivers/power/pmic/pmic_spacemit_p1.c |  94 +++++++++++++++
 include/power/spacemit_p1.h           | 163 ++++++++++++++++++++++++++
 4 files changed, 275 insertions(+)
 create mode 100644 drivers/power/pmic/pmic_spacemit_p1.c
 create mode 100644 include/power/spacemit_p1.h

diff --git a/drivers/power/pmic/Kconfig b/drivers/power/pmic/Kconfig
index b1a5b1c2a1f..19a0c4a77dd 100644
--- a/drivers/power/pmic/Kconfig
+++ b/drivers/power/pmic/Kconfig
@@ -433,6 +433,23 @@ config PMIC_RAA215300
 	  support and several voltage regulators. For now, this driver simply
 	  allows register access and will bind the sysreset driver
 	  (CONFIG_SYSRESET_RAA215300) if it is enabled.
+
+config PMIC_SPACEMIT_P1
+	bool "Enable driver for Spacemit P1 power management chip"
+	depends on DM_PMIC
+	help
+	  The P1 PMIC integrates multiple functions including
+	  voltage regulators, a watchdog timer, GPIO interfaces, and a
+	  real-time clock.
+
+config SPL_PMIC_SPACEMIT_P1
+	bool "Enable driver for Spacemit P1 power management chip in SPL"
+	depends on SPL_DM_PMIC
+	help
+	  The P1 PMIC integrates multiple functions including
+	  voltage regulators, a watchdog timer, GPIO interfaces, and a
+	  real-time clock.
+
 endif
 
 config PMIC_TPS65217
diff --git a/drivers/power/pmic/Makefile b/drivers/power/pmic/Makefile
index 6bebffb05a6..dfe60223f00 100644
--- a/drivers/power/pmic/Makefile
+++ b/drivers/power/pmic/Makefile
@@ -39,6 +39,7 @@ obj-$(CONFIG_PMIC_TPS65941) += tps65941.o
 obj-$(CONFIG_PMIC_RAA215300) += raa215300.o
 obj-$(CONFIG_POWER_TPS65218) += pmic_tps65218.o
 obj-$(CONFIG_$(PHASE_)DM_PMIC_CPCAP) += cpcap.o
+obj-$(CONFIG_$(PHASE_)PMIC_SPACEMIT_P1) += pmic_spacemit_p1.o
 
 ifeq ($(CONFIG_$(PHASE_)POWER_LEGACY),y)
 obj-$(CONFIG_POWER_LTC3676) += pmic_ltc3676.o
diff --git a/drivers/power/pmic/pmic_spacemit_p1.c b/drivers/power/pmic/pmic_spacemit_p1.c
new file mode 100644
index 00000000000..46c5926874c
--- /dev/null
+++ b/drivers/power/pmic/pmic_spacemit_p1.c
@@ -0,0 +1,94 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2025-2026 RISCstar Ltd.
+ */
+
+#include <dm.h>
+#include <power/pmic.h>
+#include <power/spacemit_p1.h>
+
+static int pmic_p1_reg_count(struct udevice *dev)
+{
+	return P1_MAX_REGS;
+}
+
+static int pmic_p1_write(struct udevice *dev, uint reg, const u8 *buffer,
+			 int len)
+{
+	int ret;
+
+	ret = dm_i2c_write(dev, reg, buffer, len);
+	if (ret)
+		pr_err("%s write error on register %02x\n", dev->name, reg);
+
+	return ret;
+}
+
+static int pmic_p1_read(struct udevice *dev, uint reg, u8 *buffer,
+			int len)
+{
+	int ret;
+
+	ret = dm_i2c_read(dev, reg, buffer, len);
+	if (ret)
+		pr_err("%s read error on register %02x\n", dev->name, reg);
+
+	return ret;
+}
+
+static const struct pmic_child_info p1_children_info[] = {
+	{ .prefix = "buck",		.driver = P1_BUCK_DRIVER },
+	{ .prefix = "aldo",		.driver = P1_ALDO_DRIVER },
+	{ .prefix = "dldo",		.driver = P1_DLDO_DRIVER },
+	{ },
+};
+
+static int pmic_p1_bind(struct udevice *dev)
+{
+	const struct pmic_child_info *p1_children_info =
+			(struct pmic_child_info *)dev_get_driver_data(dev);
+	ofnode regulators_node;
+	int children;
+
+	regulators_node = dev_read_subnode(dev, "regulators");
+	if (!ofnode_valid(regulators_node)) {
+		debug("%s regulators subnode not found\n", dev->name);
+		return -EINVAL;
+	}
+
+	children = pmic_bind_children(dev, regulators_node,
+				      p1_children_info);
+	if (!children)
+		debug("%s has no children (regulators)\n", dev->name);
+
+	return 0;
+}
+
+static int pmic_p1_probe(struct udevice *dev)
+{
+	return 0;
+}
+
+static struct dm_pmic_ops pmic_p1_ops = {
+	.reg_count	= pmic_p1_reg_count,
+	.read		= pmic_p1_read,
+	.write		= pmic_p1_write,
+};
+
+static const struct udevice_id pmic_p1_match[] = {
+	{
+		.compatible = "spacemit,p1",
+		.data = (ulong)&p1_children_info,
+	}, {
+		/* sentinel */
+	}
+};
+
+U_BOOT_DRIVER(pmic_p1) = {
+	.name		= "pmic_p1",
+	.id		= UCLASS_PMIC,
+	.of_match	= pmic_p1_match,
+	.bind		= pmic_p1_bind,
+	.probe		= pmic_p1_probe,
+	.ops		= &pmic_p1_ops,
+};
diff --git a/include/power/spacemit_p1.h b/include/power/spacemit_p1.h
new file mode 100644
index 00000000000..ef5a45e8cec
--- /dev/null
+++ b/include/power/spacemit_p1.h
@@ -0,0 +1,163 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2025-2026 RISCstar Ltd.
+ */
+
+#ifndef __SPACEMIT_P1_H_
+#define __SPACEMIT_P1_H_
+
+#define P1_MAX_REGS			0xA8
+
+#define P1_REG_ID			0x0
+
+#define P1_ID				0x2
+
+#define P1_REG_BUCK1_CTRL		0x47
+#define P1_REG_BUCK2_CTRL		0x4a
+#define P1_REG_BUCK3_CTRL		0x4d
+#define P1_REG_BUCK4_CTRL		0x50
+#define P1_REG_BUCK5_CTRL		0x53
+#define P1_REG_BUCK6_CTRL		0x56
+
+#define P1_REG_BUCK1_VSEL		0x48
+#define P1_REG_BUCK2_VSEL		0x4b
+#define P1_REG_BUCK3_VSEL		0x4e
+#define P1_REG_BUCK4_VSEL		0x51
+#define P1_REG_BUCK5_VSEL		0x54
+#define P1_REG_BUCK6_VSEL		0x57
+
+#define P1_REG_BUCK1_SVSEL		0x49
+#define P1_REG_BUCK2_SVSEL		0x4c
+#define P1_REG_BUCK3_SVSEL		0x4f
+#define P1_REG_BUCK4_SVSEL		0x52
+#define P1_REG_BUCK5_SVSEL		0x55
+#define P1_REG_BUCK6_SVSEL		0x58
+
+#define P1_BUCK_CTRL(x)			(0x47 + ((x) - 1) * 3)
+#define P1_BUCK_VSEL(x)			(0x48 + ((x) - 1) * 3)
+#define P1_BUCK_SVSEL(x)		(0x49 + ((x) - 1) * 3)
+
+#define BUCK_VSEL_MASK			0xff
+#define BUCK_EN_MASK			0x1
+#define BUCK_SVSEL_MASK			0xff
+
+#define P1_REG_ALDO1_CTRL		0x5b
+#define P1_REG_ALDO2_CTRL		0x5e
+#define P1_REG_ALDO3_CTRL		0x61
+#define P1_REG_ALDO4_CTRL		0x64
+
+#define P1_REG_ALDO1_VOLT		0x5c
+#define P1_REG_ALDO2_VOLT		0x5f
+#define P1_REG_ALDO3_VOLT		0x62
+#define P1_REG_ALDO4_VOLT		0x65
+
+#define P1_REG_ALDO1_SVOLT		0x5d
+#define P1_REG_ALDO2_SVOLT		0x60
+#define P1_REG_ALDO3_SVOLT		0x63
+#define P1_REG_ALDO4_SVOLT		0x66
+
+#define P1_ALDO_CTRL(x)			(0x5b + ((x) - 1) * 3)
+#define P1_ALDO_VOLT(x)			(0x5c + ((x) - 1) * 3)
+#define P1_ALDO_SVOLT(x)		(0x5d + ((x) - 1) * 3)
+
+#define ALDO_SVSEL_MASK			0x7f
+#define ALDO_EN_MASK			0x1
+#define ALDO_VSEL_MASK			0x7f
+
+#define P1_REG_DLDO1_CTRL		0x67
+#define P1_REG_DLDO2_CTRL		0x6a
+#define P1_REG_DLDO3_CTRL		0x6d
+#define P1_REG_DLDO4_CTRL		0x70
+#define P1_REG_DLDO5_CTRL		0x73
+#define P1_REG_DLDO6_CTRL		0x76
+#define P1_REG_DLDO7_CTRL		0x79
+
+#define P1_REG_DLDO1_VOLT		0x68
+#define P1_REG_DLDO2_VOLT		0x6b
+#define P1_REG_DLDO3_VOLT		0x6e
+#define P1_REG_DLDO4_VOLT		0x71
+#define P1_REG_DLDO5_VOLT		0x74
+#define P1_REG_DLDO6_VOLT		0x77
+#define P1_REG_DLDO7_VOLT		0x7a
+
+#define P1_REG_DLDO1_SVOLT		0x69
+#define P1_REG_DLDO2_SVOLT		0x6c
+#define P1_REG_DLDO3_SVOLT		0x6f
+#define P1_REG_DLDO4_SVOLT		0x72
+#define P1_REG_DLDO5_SVOLT		0x75
+#define P1_REG_DLDO6_SVOLT		0x78
+#define P1_REG_DLDO7_SVOLT		0x7b
+
+#define P1_DLDO_CTRL(x)			(0x67 + ((x) - 1) * 3)
+#define P1_DLDO_VOLT(x)			(0x68 + ((x) - 1) * 3)
+#define P1_DLDO_SVOLT(x)		(0x69 + ((x) - 1) * 3)
+
+#define DLDO_SVSEL_MASK			0x7f
+#define DLDO_EN_MASK			0x1
+#define DLDO_VSEL_MASK			0x7f
+
+#define P1_REG_SWITCH_CTRL		0x59
+#define P1_SWTICH_EN_MASK		0x1
+
+#define P1_REG_SWITCH_PWRKEY_EVENT_CTRL	0x97
+#define P1_SWITCH_PWRKEY_EVENT_EN_MSK	0xf
+
+#define P1_REG_SWITCH_PWRKEY_INIT_CTRL	0x9e
+#define P1_SWITCH_PWRKEY_INT_EN_MSK	0xf
+
+/* Watchdog Timer Registers */
+#define P1_WDT_CTRL			0x44
+#define P1_PWR_CTRL0			0x7C
+#define P1_PWR_CTRL2			0x7E
+#define P1_PWR_CTRL2_MSK		0xff
+
+/* Watchdog Timer Control Bits */
+#define P1_WDT_CLEAR_STATUS		0x1
+#define P1_SW_RST			0x2
+#define P1_WDT_RESET_ENABLE		0x80
+#define P1_WDT_ENABLE			0x8
+#define P1_WDT_TIMEOUT_1S		0x0
+#define P1_WDT_TIMEOUT_4S		0x1
+#define P1_WDT_TIMEOUT_8S		0x2
+#define P1_WDT_TIMEOUT_16S		0x3
+
+#define P1_RTC_TICK_CTRL		0x1d
+#define P1_RTC_TICK_CTRL_MSK		0x7f
+
+#define P1_RTC_TICK_EVENT		0x92
+#define P1_RTC_TICK_EVENT_MSK		0x3f
+
+#define P1_RTC_TICK_IRQ			0x99
+#define P1_RTC_TICK_IRQ_MSK		0x3f
+
+#define P1_REG_ALIVE			0xab
+#define P1_ALIVE_MSK			0x7
+#define SYS_REBOOT_FLAG_BIT		0x2
+
+/* SWITCH ID */
+enum {
+	P1_ID_SWITCH1,
+	P1_ID_SWITCH1_PWRKEY_EVENT,
+	P1_ID_SWITCH1_PWRKEY_INT,
+	P1_ID_SWITCH_RTC_TICK_CTRL,
+	P1_ID_SWITCH_RTC_TICK_EVENT,
+	P1_ID_SWITCH_RTC_TCK_IRQ,
+	P1_ID_SWITCH_POWER_DOWN,
+	P1_ID_SWITCH_CHARGING_FLAG,
+};
+
+/* POWERKEY events */
+enum {
+	PWRKEY_RISING_EVENT = 1,
+	PWRKEY_FAILING_EVENT = 2,
+	PWRKEY_SHORT_PRESS_EVENT = 4,
+	PWRKEY_LONG_PRESS_EVENT = 8,
+};
+
+#define P1_BUCK_DRIVER			"p1_buck"
+#define P1_ALDO_DRIVER			"p1_aldo"
+#define P1_DLDO_DRIVER			"p1_dldo"
+#define P1_SWITCH_DRIVER		"p1_switch"
+#define P1_WDT_DRIVER			"p1_wdt"
+
+#endif /* __SPACEMIT_P1_H_ */
-- 
2.25.1


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

* [PATCH v2 15/16] power: regulator: add support for Spacemit P1 SoC
  2026-02-10 15:14 [PATCH v2 00/16] Add board support for Spacemit K1 SoC in SPL Raymond Mao
                   ` (13 preceding siblings ...)
  2026-02-10 15:14 ` [PATCH v2 14/16] power: pmic: add support for Spacemit P1 PMIC Raymond Mao
@ 2026-02-10 15:14 ` Raymond Mao
  2026-03-03  3:37   ` Peng Fan
  2026-02-10 15:14 ` [PATCH v2 16/16] board: k1: enable pmic in spl Raymond Mao
                   ` (2 subsequent siblings)
  17 siblings, 1 reply; 24+ messages in thread
From: Raymond Mao @ 2026-02-10 15:14 UTC (permalink / raw)
  To: u-boot
  Cc: uboot, u-boot-spacemit, raymond.mao, rick, ycliang, trini, lukma,
	hs, jh80.chung, peng.fan, xypron.glpk, randolph, dlan, junhui.liu,
	neil.armstrong, quentin.schulz, samuel, raymondmaoca

From: Raymond Mao <raymond.mao@riscstar.com>

Support voltage regulator for Spacemit P1 SoC. It contains 6 BUCKs
and 11 LDOs.

Signed-off-by: Raymond Mao <raymond.mao@riscstar.com>
---
 drivers/power/regulator/Kconfig               |  15 +
 drivers/power/regulator/Makefile              |   1 +
 .../power/regulator/spacemit_p1_regulator.c   | 460 ++++++++++++++++++
 3 files changed, 476 insertions(+)
 create mode 100644 drivers/power/regulator/spacemit_p1_regulator.c

diff --git a/drivers/power/regulator/Kconfig b/drivers/power/regulator/Kconfig
index c6da459a212..182510581c0 100644
--- a/drivers/power/regulator/Kconfig
+++ b/drivers/power/regulator/Kconfig
@@ -520,3 +520,18 @@ config DM_REGULATOR_CPCAP
 	REGULATOR CPCAP. The driver supports both DC-to-DC Step-Down Switching
 	(SW) Regulators and Low-Dropout Linear (LDO) Regulators	found in CPCAP
 	PMIC and implements get/set api for voltage and state.
+
+config DM_REGULATOR_SPACEMIT_P1
+	bool "Enable driver for Spacemit P1 PMIC regulators"
+	depends on DM_REGULATOR && PMIC_SPACEMIT_P1
+	help
+	  Enable implementation of driver-model regulator uclass features
+	  for regulator P1. The driver supports BUCKs, LDOs and SWITCHes.
+
+config SPL_DM_REGULATOR_SPACEMIT_P1
+	bool "Enable driver for Spacemit P1 PMIC regulators in SPL"
+	depends on SPL_DM_REGULATOR && SPL_PMIC_SPACEMIT_P1
+	help
+	  Enable implementation of driver-model regulator uclass features
+	  for regulator P1 in SPL. The driver supports BUCKs, LDOs and
+	  SWITCHes.
diff --git a/drivers/power/regulator/Makefile b/drivers/power/regulator/Makefile
index ee8f56ea3b9..2a586e42f5c 100644
--- a/drivers/power/regulator/Makefile
+++ b/drivers/power/regulator/Makefile
@@ -47,3 +47,4 @@ obj-$(CONFIG_$(PHASE_)DM_REGULATOR_ANATOP) += anatop_regulator.o
 obj-$(CONFIG_DM_REGULATOR_TPS65219) += tps65219_regulator.o
 obj-$(CONFIG_REGULATOR_RZG2L_USBPHY) += rzg2l-usbphy-regulator.o
 obj-$(CONFIG_$(PHASE_)DM_REGULATOR_CPCAP) += cpcap_regulator.o
+obj-$(CONFIG_$(PHASE_)DM_REGULATOR_SPACEMIT_P1) += spacemit_p1_regulator.o
diff --git a/drivers/power/regulator/spacemit_p1_regulator.c b/drivers/power/regulator/spacemit_p1_regulator.c
new file mode 100644
index 00000000000..ab3ca489f0b
--- /dev/null
+++ b/drivers/power/regulator/spacemit_p1_regulator.c
@@ -0,0 +1,460 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2025-2026 RISCstar Ltd.
+ */
+
+#include <dm.h>
+#include <dm/lists.h>
+#include <errno.h>
+#include <log.h>
+#include <power/pmic.h>
+#include <power/regulator.h>
+#include <power/spacemit_p1.h>
+
+struct p1_reg_info {
+	uint min_uv;
+	uint step_uv;
+	u8 vsel_reg;
+	u8 vsel_sleep_reg;
+	u8 config_reg;
+	u8 vsel_mask;
+	u8 min_sel;
+	u8 max_sel;
+};
+
+static const struct p1_reg_info p1_bucks[] = {
+	/* BUCK 1 */
+	{ 500000,  5000, P1_BUCK_VSEL(1), P1_BUCK_SVSEL(1), P1_BUCK_CTRL(1),
+	  BUCK_VSEL_MASK, 0x00, 0xaa },
+	{ 1375000, 25000, P1_BUCK_VSEL(1), P1_BUCK_SVSEL(1), P1_BUCK_CTRL(1),
+	  BUCK_VSEL_MASK, 0xab, 0xfe },
+	/* BUCK 2 */
+	{ 500000,  5000, P1_BUCK_VSEL(2), P1_BUCK_SVSEL(2), P1_BUCK_CTRL(2),
+	  BUCK_VSEL_MASK, 0x00, 0xaa },
+	{ 1375000, 25000, P1_BUCK_VSEL(2), P1_BUCK_SVSEL(2), P1_BUCK_CTRL(2),
+	  BUCK_VSEL_MASK, 0xab, 0xfe },
+	/* BUCK 3 */
+	{ 500000,  5000, P1_BUCK_VSEL(3), P1_BUCK_SVSEL(3), P1_BUCK_CTRL(3),
+	  BUCK_VSEL_MASK, 0x00, 0xaa },
+	{ 1375000, 25000, P1_BUCK_VSEL(3), P1_BUCK_SVSEL(3), P1_BUCK_CTRL(3),
+	  BUCK_VSEL_MASK, 0xab, 0xfe },
+	/* BUCK 4 */
+	{ 500000,  5000, P1_BUCK_VSEL(4), P1_BUCK_SVSEL(4), P1_BUCK_CTRL(4),
+	  BUCK_VSEL_MASK, 0x00, 0xaa },
+	{ 1375000, 25000, P1_BUCK_VSEL(4), P1_BUCK_SVSEL(4), P1_BUCK_CTRL(4),
+	  BUCK_VSEL_MASK, 0xab, 0xfe },
+	/* BUCK 5 */
+	{ 500000,  5000, P1_BUCK_VSEL(5), P1_BUCK_SVSEL(5), P1_BUCK_CTRL(5),
+	  BUCK_VSEL_MASK, 0x00, 0xaa },
+	{ 1375000, 25000, P1_BUCK_VSEL(5), P1_BUCK_SVSEL(5), P1_BUCK_CTRL(5),
+	  BUCK_VSEL_MASK, 0xab, 0xfe },
+	/* BUCK 6 */
+	{ 500000,  5000, P1_BUCK_VSEL(6), P1_BUCK_SVSEL(6), P1_BUCK_CTRL(6),
+	  BUCK_VSEL_MASK, 0x00, 0xaa },
+	{ 1375000, 25000, P1_BUCK_VSEL(6), P1_BUCK_SVSEL(6), P1_BUCK_CTRL(6),
+	  BUCK_VSEL_MASK, 0xab, 0xfe },
+};
+
+static const struct p1_reg_info p1_aldos[] = {
+	/* ALDO 1 */
+	{ 500000, 25000, P1_ALDO_VOLT(1), P1_ALDO_SVOLT(1), P1_ALDO_CTRL(1),
+	  ALDO_VSEL_MASK, 0x0b, 0x7f },
+	/* ALDO 2 */
+	{ 500000, 25000, P1_ALDO_VOLT(2), P1_ALDO_SVOLT(2), P1_ALDO_CTRL(2),
+	  ALDO_VSEL_MASK, 0x0b, 0x7f },
+	/* ALDO 3 */
+	{ 500000, 25000, P1_ALDO_VOLT(3), P1_ALDO_SVOLT(3), P1_ALDO_CTRL(3),
+	  ALDO_VSEL_MASK, 0x0b, 0x7f },
+	/* ALDO 4 */
+	{ 500000, 25000, P1_ALDO_VOLT(4), P1_ALDO_SVOLT(4), P1_ALDO_CTRL(4),
+	  ALDO_VSEL_MASK, 0x0b, 0x7f },
+};
+
+static const struct p1_reg_info p1_dldos[] = {
+	/* DLDO 1 */
+	{ 500000, 25000, P1_DLDO_VOLT(1), P1_DLDO_SVOLT(1), P1_DLDO_CTRL(1),
+	  ALDO_VSEL_MASK, 0x0b, 0x7f },
+	/* DLDO 2 */
+	{ 500000, 25000, P1_DLDO_VOLT(2), P1_DLDO_SVOLT(2), P1_DLDO_CTRL(2),
+	  ALDO_VSEL_MASK, 0x0b, 0x7f },
+	/* DLDO 3 */
+	{ 500000, 25000, P1_DLDO_VOLT(3), P1_DLDO_SVOLT(3), P1_DLDO_CTRL(3),
+	  ALDO_VSEL_MASK, 0x0b, 0x7f },
+	/* DLDO 4 */
+	{ 500000, 25000, P1_DLDO_VOLT(4), P1_DLDO_SVOLT(4), P1_DLDO_CTRL(4),
+	  ALDO_VSEL_MASK, 0x0b, 0x7f },
+	/* DLDO 5 */
+	{ 500000, 25000, P1_DLDO_VOLT(5), P1_DLDO_SVOLT(5), P1_DLDO_CTRL(5),
+	  ALDO_VSEL_MASK, 0x0b, 0x7f },
+	/* DLDO 6 */
+	{ 500000, 25000, P1_DLDO_VOLT(6), P1_DLDO_SVOLT(6), P1_DLDO_CTRL(6),
+	  ALDO_VSEL_MASK, 0x0b, 0x7f },
+	/* DLDO 7 */
+	{ 500000, 25000, P1_DLDO_VOLT(7), P1_DLDO_SVOLT(7), P1_DLDO_CTRL(7),
+	  ALDO_VSEL_MASK, 0x0b, 0x7f },
+};
+
+static const struct p1_reg_info *get_buck_reg(struct udevice *pmic,
+					      int idx, int uvolt)
+{
+	if (idx < 0)
+		return NULL;
+	if (uvolt < 1375000)
+		return &p1_bucks[(idx - 1) * 2 + 0];
+	return &p1_bucks[(idx - 1) * 2 + 1];
+}
+
+static const struct p1_reg_info *get_aldo_reg(struct udevice *pmic,
+					      int idx, int uvolt)
+{
+	return &p1_aldos[idx];
+}
+
+static const struct p1_reg_info *get_dldo_reg(struct udevice *pmic,
+					      int idx, int uvolt)
+{
+	return &p1_dldos[idx];
+}
+
+static int buck_get_value(struct udevice *dev)
+{
+	const struct dm_pmic_ops *ops = device_get_ops(dev->parent);
+	const struct p1_reg_info *info;
+	uint val;
+	int ret;
+
+	if (!ops || !ops->read)
+		return -ENOSYS;
+
+	info = get_buck_reg(dev->parent, dev->driver_data, 0);
+	if (!info)
+		return -ENOENT;
+	ret = pmic_reg_read(dev->parent, info->vsel_reg);
+	if (ret < 0)
+		return ret;
+	val = ret & info->vsel_mask;
+	while (val > info->max_sel)
+		info++;
+
+	return info->min_uv + (val - info->min_sel) * info->step_uv;
+}
+
+static int buck_set_value(struct udevice *dev, int uvolt)
+{
+	const struct dm_pmic_ops *ops = device_get_ops(dev->parent);
+	const struct p1_reg_info *info;
+	uint val;
+	int ret;
+
+	if (!ops || !ops->write)
+		return -ENOSYS;
+
+	info = get_buck_reg(dev->parent, dev->driver_data, uvolt);
+	if (!info)
+		return -ENOENT;
+	val = (uvolt - info->min_uv);
+	val = val / info->step_uv;
+	val += info->min_sel;
+	ret = pmic_reg_write(dev->parent, info->vsel_reg, val);
+	if (ret < 0)
+		return ret;
+	return 0;
+}
+
+static int buck_get_enable(struct udevice *dev)
+{
+	const struct p1_reg_info *info;
+	int ret;
+
+	info = get_buck_reg(dev->parent, dev->driver_data, 0);
+	if (!info)
+		return -ENOENT;
+
+	ret = pmic_reg_read(dev->parent, info->config_reg);
+	if (ret < 0)
+		return ret;
+	return ret & BUCK_EN_MASK;
+}
+
+static int buck_set_enable(struct udevice *dev, bool enable)
+{
+	const struct p1_reg_info *info;
+	uint val;
+	int ret;
+
+	info = get_buck_reg(dev->parent, dev->driver_data, 0);
+	if (!info)
+		return -ENOENT;
+
+	ret = pmic_reg_read(dev->parent, info->config_reg);
+	if (ret < 0)
+		return ret;
+	val = (unsigned int)ret;
+	val &= BUCK_EN_MASK;
+
+	if (enable == val)
+		return 0;
+
+	val = enable;
+	ret = pmic_clrsetbits(dev->parent, info->config_reg, BUCK_EN_MASK, val);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static const struct dm_regulator_ops p1_buck_ops = {
+	.get_value  = buck_get_value,
+	.set_value  = buck_set_value,
+	.get_enable = buck_get_enable,
+	.set_enable = buck_set_enable,
+};
+
+static int p1_buck_probe(struct udevice *dev)
+{
+	struct dm_regulator_uclass_plat *uc_pdata;
+
+	uc_pdata = dev_get_uclass_plat(dev);
+
+	uc_pdata->type = REGULATOR_TYPE_BUCK;
+	uc_pdata->mode_count = 0;
+
+	return 0;
+}
+
+U_BOOT_DRIVER(p1_buck) = {
+	.name		= P1_BUCK_DRIVER,
+	.id		= UCLASS_REGULATOR,
+	.ops		= &p1_buck_ops,
+	.probe		= p1_buck_probe,
+};
+
+static int aldo_get_value(struct udevice *dev)
+{
+	const struct dm_pmic_ops *ops = device_get_ops(dev->parent);
+	const struct p1_reg_info *info;
+	uint val;
+	int ret;
+
+	if (!ops || !ops->read)
+		return -ENOSYS;
+
+	info = get_aldo_reg(dev->parent, dev->driver_data, 0);
+	if (!info)
+		return -ENOENT;
+
+	ret = pmic_reg_read(dev->parent, info->vsel_reg);
+	if (ret < 0)
+		return ret;
+
+	val = ret & info->vsel_mask;
+	while (val > info->max_sel)
+		info++;
+
+	return info->min_uv + (val - info->min_sel) * info->step_uv;
+}
+
+static int aldo_set_value(struct udevice *dev, int uvolt)
+{
+	const struct dm_pmic_ops *ops = device_get_ops(dev->parent);
+	const struct p1_reg_info *info;
+	uint val;
+	int ret;
+
+	if (!ops || !ops->write)
+		return -ENOSYS;
+
+	info = get_aldo_reg(dev->parent, dev->driver_data, uvolt);
+	if (!info)
+		return -ENOENT;
+	val = (uvolt - info->min_uv);
+	val = val / info->step_uv;
+	val += info->min_sel;
+	ret = pmic_reg_write(dev->parent, info->vsel_reg, val);
+	if (ret < 0)
+		return ret;
+	return 0;
+}
+
+static int aldo_get_enable(struct udevice *dev)
+{
+	const struct p1_reg_info *info;
+	int ret;
+
+	info = get_aldo_reg(dev->parent, dev->driver_data, 0);
+	if (!info)
+		return -ENOENT;
+
+	ret = pmic_reg_read(dev->parent, info->config_reg);
+	if (ret < 0)
+		return ret;
+	return ret & ALDO_EN_MASK;
+}
+
+static int aldo_set_enable(struct udevice *dev, bool enable)
+{
+	const struct p1_reg_info *info;
+	uint val;
+	int ret;
+
+	info = get_aldo_reg(dev->parent, dev->driver_data, 0);
+	if (!info)
+		return -ENOENT;
+
+	ret = pmic_reg_read(dev->parent, info->config_reg);
+	if (ret < 0)
+		return ret;
+	val = (unsigned int)ret;
+	val &= ALDO_EN_MASK;
+
+	if (enable == val)
+		return 0;
+
+	val = enable;
+	ret = pmic_clrsetbits(dev->parent, info->config_reg, ALDO_EN_MASK, val);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static const struct dm_regulator_ops p1_aldo_ops = {
+	.get_value	= aldo_get_value,
+	.set_value	= aldo_set_value,
+	.get_enable	= aldo_get_enable,
+	.set_enable	= aldo_set_enable,
+};
+
+static int p1_aldo_probe(struct udevice *dev)
+{
+	struct dm_regulator_uclass_plat *uc_pdata;
+
+	uc_pdata = dev_get_uclass_plat(dev);
+
+	uc_pdata->type = REGULATOR_TYPE_LDO;
+	uc_pdata->mode_count = 0;
+
+	return 0;
+}
+
+U_BOOT_DRIVER(p1_aldo) = {
+	.name		= P1_ALDO_DRIVER,
+	.id		= UCLASS_REGULATOR,
+	.ops		= &p1_aldo_ops,
+	.probe		= p1_aldo_probe,
+};
+
+static int dldo_get_value(struct udevice *dev)
+{
+	const struct dm_pmic_ops *ops = device_get_ops(dev->parent);
+	const struct p1_reg_info *info;
+	uint val;
+	int ret;
+
+	if (!ops || !ops->read)
+		return -ENOSYS;
+
+	info = get_dldo_reg(dev->parent, dev->driver_data, 0);
+	if (!info)
+		return -ENOENT;
+
+	ret = pmic_reg_read(dev->parent, info->vsel_reg);
+	if (ret < 0)
+		return ret;
+
+	val = ret & info->vsel_mask;
+	while (val > info->max_sel)
+		info++;
+
+	return info->min_uv + (val - info->min_sel) * info->step_uv;
+}
+
+static int dldo_set_value(struct udevice *dev, int uvolt)
+{
+	const struct dm_pmic_ops *ops = device_get_ops(dev->parent);
+	const struct p1_reg_info *info;
+	uint val;
+	int ret;
+
+	if (!ops || !ops->write)
+		return -ENOSYS;
+
+	info = get_dldo_reg(dev->parent, dev->driver_data, uvolt);
+	if (!info)
+		return -ENOENT;
+	val = (uvolt - info->min_uv);
+	val = val / info->step_uv;
+	val += info->min_sel;
+	ret = pmic_reg_write(dev->parent, info->vsel_reg, val);
+	if (ret < 0)
+		return ret;
+	return 0;
+}
+
+static int dldo_get_enable(struct udevice *dev)
+{
+	const struct p1_reg_info *info;
+	int ret;
+
+	info = get_dldo_reg(dev->parent, dev->driver_data, 0);
+	if (!info)
+		return -ENOENT;
+
+	ret = pmic_reg_read(dev->parent, info->config_reg);
+	if (ret < 0)
+		return ret;
+	return ret & DLDO_EN_MASK;
+}
+
+static int dldo_set_enable(struct udevice *dev, bool enable)
+{
+	const struct p1_reg_info *info;
+	uint val;
+	int ret;
+
+	info = get_dldo_reg(dev->parent, dev->driver_data, 0);
+	if (!info)
+		return -ENOENT;
+
+	ret = pmic_reg_read(dev->parent, info->config_reg);
+	if (ret < 0)
+		return ret;
+	val = (unsigned int)ret;
+	val &= DLDO_EN_MASK;
+
+	if (enable == val)
+		return 0;
+
+	val = enable;
+	ret = pmic_clrsetbits(dev->parent, info->config_reg, DLDO_EN_MASK, val);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static const struct dm_regulator_ops p1_dldo_ops = {
+	.get_value	= dldo_get_value,
+	.set_value	= dldo_set_value,
+	.get_enable	= dldo_get_enable,
+	.set_enable	= dldo_set_enable,
+};
+
+static int p1_dldo_probe(struct udevice *dev)
+{
+	struct dm_regulator_uclass_plat *uc_pdata;
+
+	uc_pdata = dev_get_uclass_plat(dev);
+
+	uc_pdata->type = REGULATOR_TYPE_LDO;
+	uc_pdata->mode_count = 0;
+
+	return 0;
+}
+
+U_BOOT_DRIVER(p1_dldo) = {
+	.name		= P1_DLDO_DRIVER,
+	.id		= UCLASS_REGULATOR,
+	.ops		= &p1_dldo_ops,
+	.probe		= p1_dldo_probe,
+};
-- 
2.25.1


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

* [PATCH v2 16/16] board: k1: enable pmic in spl
  2026-02-10 15:14 [PATCH v2 00/16] Add board support for Spacemit K1 SoC in SPL Raymond Mao
                   ` (14 preceding siblings ...)
  2026-02-10 15:14 ` [PATCH v2 15/16] power: regulator: add support for Spacemit P1 SoC Raymond Mao
@ 2026-02-10 15:14 ` Raymond Mao
  2026-02-25 14:53 ` [PATCH v2 00/16] Add board support for Spacemit K1 SoC in SPL Raymond Mao
  2026-03-11  7:37 ` [PATCH] doc: spacemit: add K1 SPL build and test guide Guodong Xu
  17 siblings, 0 replies; 24+ messages in thread
From: Raymond Mao @ 2026-02-10 15:14 UTC (permalink / raw)
  To: u-boot
  Cc: uboot, u-boot-spacemit, raymond.mao, rick, ycliang, trini, lukma,
	hs, jh80.chung, peng.fan, xypron.glpk, randolph, dlan, junhui.liu,
	neil.armstrong, quentin.schulz, samuel, raymondmaoca, Guodong Xu

From: Raymond Mao <raymond.mao@riscstar.com>

Add Spacemit P1 SoC support in SPL. And set the default voltage
for BUCKs and LDOs.

Signed-off-by: Raymond Mao <raymond.mao@riscstar.com>
Signed-off-by: Guodong Xu <guodong.xu@riscstar.com>
---
 arch/riscv/dts/k1-spl.dts     | 128 +++++++++++++++++++++++++++++++---
 board/spacemit/k1/MAINTAINERS |   7 +-
 board/spacemit/k1/spl.c       |  82 +++++++++++++++++++---
 configs/spacemit_k1_defconfig |   9 +++
 4 files changed, 203 insertions(+), 23 deletions(-)

diff --git a/arch/riscv/dts/k1-spl.dts b/arch/riscv/dts/k1-spl.dts
index e118767e6db..6f9407aada6 100644
--- a/arch/riscv/dts/k1-spl.dts
+++ b/arch/riscv/dts/k1-spl.dts
@@ -99,17 +99,6 @@
 		};
 	};
 
-	i2c@d401d800 {		/* i2c8 */
-		status = "okay";
-		bootph-pre-ram;
-		pmic@41 {
-			compatible = "pmic";
-			reg = <0x41>;
-			status = "okay";
-			bootph-pre-ram;
-		};
-	};
-
 	reset-controller@d4050000 {
 		status = "okay";
 		bootph-pre-ram;
@@ -120,3 +109,120 @@
 	status = "okay";
 	bootph-pre-ram;
 };
+
+&i2c8 {
+	status = "okay";
+	bootph-pre-ram;
+	pmic@41 {
+		compatible = "spacemit,p1";
+		reg = <0x41>;
+		status = "okay";
+		bootph-pre-ram;
+
+		regulators {
+			buck1 {
+				regulator-name = "vdd_core";
+				regulator-min-microvolt = <500000>;
+				regulator-max-microvolt = <3450000>;
+				regulator-ramp-delay = <5000>;
+				regulator-always-on;
+				bootph-pre-ram;
+			};
+
+			buck2 {
+				regulator-min-microvolt = <500000>;
+				regulator-max-microvolt = <3450000>;
+				regulator-ramp-delay = <5000>;
+				regulator-always-on;
+			};
+
+			buck3_1v8: buck3 {
+				regulator-name = "vdd_1v8";
+				regulator-min-microvolt = <500000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-ramp-delay = <5000>;
+				regulator-always-on;
+				bootph-pre-ram;
+			};
+
+			buck4 {
+				regulator-min-microvolt = <500000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-ramp-delay = <5000>;
+				regulator-always-on;
+			};
+
+			buck5 {
+				regulator-min-microvolt = <500000>;
+				regulator-max-microvolt = <3450000>;
+				regulator-ramp-delay = <5000>;
+				regulator-always-on;
+			};
+
+			buck6 {
+				regulator-min-microvolt = <500000>;
+				regulator-max-microvolt = <3450000>;
+				regulator-ramp-delay = <5000>;
+				regulator-always-on;
+			};
+
+			aldo1 {
+				regulator-name = "vdd_1v8_mmc";
+				regulator-min-microvolt = <500000>;
+				regulator-max-microvolt = <3400000>;
+				regulator-boot-on;
+				bootph-pre-ram;
+			};
+
+			aldo2 {
+				regulator-min-microvolt = <500000>;
+				regulator-max-microvolt = <3400000>;
+			};
+
+			aldo3 {
+				regulator-min-microvolt = <500000>;
+				regulator-max-microvolt = <3400000>;
+			};
+
+			aldo4 {
+				regulator-min-microvolt = <500000>;
+				regulator-max-microvolt = <3400000>;
+			};
+
+			dldo1 {
+				regulator-min-microvolt = <500000>;
+				regulator-max-microvolt = <3400000>;
+			};
+
+			dldo2 {
+				regulator-min-microvolt = <500000>;
+				regulator-max-microvolt = <3400000>;
+			};
+
+			dldo3 {
+				regulator-min-microvolt = <500000>;
+				regulator-max-microvolt = <3400000>;
+			};
+
+			dldo4 {
+				regulator-min-microvolt = <500000>;
+				regulator-max-microvolt = <3400000>;
+			};
+
+			dldo5 {
+				regulator-min-microvolt = <500000>;
+				regulator-max-microvolt = <3400000>;
+			};
+
+			dldo6 {
+				regulator-min-microvolt = <500000>;
+				regulator-max-microvolt = <3400000>;
+			};
+
+			dldo7 {
+				regulator-min-microvolt = <500000>;
+				regulator-max-microvolt = <3400000>;
+			};
+		};
+	};
+};
diff --git a/board/spacemit/k1/MAINTAINERS b/board/spacemit/k1/MAINTAINERS
index bd476c32719..f550745afea 100644
--- a/board/spacemit/k1/MAINTAINERS
+++ b/board/spacemit/k1/MAINTAINERS
@@ -1,6 +1,11 @@
 BananaPi F3
 M:	Huan Zhou <pericycle.cc@@gmail.com>
+M:	Guodong Xu <guodong.xu@riscstar.com>
+L:      u-boot-spacemit@groups.io
 S:	Maintained
 F:	board/spacemit/k1/
-F:	configs/k1_defconfig
+F:	configs/spacemit_k1_defconfig
 F:	doc/board/spacemit/bananapi-f3.rst
+F:	drivers/i2c/k1_i2c.c
+F:	drivers/power/pmic/pmic_spacemit_p1.c
+F:	drivers/power/regulator/spacemit_p1_regulator.c
diff --git a/board/spacemit/k1/spl.c b/board/spacemit/k1/spl.c
index 95b61f5aa90..5af804f0409 100644
--- a/board/spacemit/k1/spl.c
+++ b/board/spacemit/k1/spl.c
@@ -10,11 +10,13 @@
 #include <clk-uclass.h>
 #include <cpu_func.h>
 #include <configs/k1.h>
+#include <cpu_func.h>
 #include <dm/device.h>
 #include <dm/uclass.h>
 #include <i2c.h>
 #include <linux/delay.h>
 #include <log.h>
+#include <power/regulator.h>
 #include <spl.h>
 #include <tlv_eeprom.h>
 #include "tlv_codes.h"
@@ -146,6 +148,73 @@ void serial_early_init(void)
 		panic("Serial uclass init failed: %d\n", ret);
 }
 
+static void set_vdd_core(void)
+{
+	struct udevice *dev;
+	int ret;
+
+	ret = regulator_get_by_platname("vdd_core", &dev);
+	if (ret)
+		panic("Fail to detect vdd_core (%d)\n", ret);
+	ret = regulator_set_enable(dev, true);
+	if (ret)
+		log_warning("Fail to enable vdd_core (%d)\n", ret);
+	ret = regulator_get_value(dev);
+	if (ret < 0)
+		log_warning("Fail to read vdd_core (%d)\n", ret);
+	log_info("vdd_core, value:%d\n", ret);
+}
+
+static void set_vdd_1v8(void)
+{
+	struct udevice *dev;
+	int ret;
+
+	ret = regulator_get_by_platname("vdd_1v8", &dev);
+	if (ret)
+		panic("Fail to detect vdd_1v8 (%d)\n", ret);
+	ret = regulator_set_value(dev, 1800000);
+	if (ret)
+		log_warning("Fail to set vdd_1v8 as 1800000 (%d)\n", ret);
+	ret = regulator_set_enable(dev, true);
+	if (ret)
+		log_warning("Fail to enable vdd_1v8 (%d)\n", ret);
+	ret = regulator_get_value(dev);
+	if (ret < 0)
+		log_warning("Fail to read vdd_1v8 (%d)\n", ret);
+	log_info("vdd_1v8, value:%d\n", ret);
+}
+
+static void set_vdd_mmc(void)
+{
+	struct udevice *dev;
+	int ret;
+
+	ret = regulator_get_by_platname("vdd_1v8_mmc", &dev);
+	if (ret)
+		panic("Fail to detect vdd_1v8_mmc (%d)\n", ret);
+	ret = regulator_set_enable(dev, true);
+	if (ret)
+		log_warning("Fail to enable vdd_1v8_mmc (%d)\n", ret);
+	ret = regulator_get_value(dev);
+	if (ret < 0)
+		log_warning("Fail to read vdd_1v8_mmc (%d)\n", ret);
+	log_info("vdd_1v8_mmc, value:%d\n", ret);
+}
+
+void pmic_init(void)
+{
+	struct udevice *pmic_dev;
+	int ret;
+
+	ret = uclass_get_device(UCLASS_PMIC, 0, &pmic_dev);
+	if (ret)
+		panic("Fail to detect PMIC (%d)\n", ret);
+	set_vdd_core();
+	set_vdd_1v8();
+	set_vdd_mmc();
+}
+
 /* Set default value for DDR chips */
 static void ddr_cfg_init(struct ddr_cfg *cfg)
 {
@@ -263,6 +332,8 @@ void board_init_f(ulong dummy)
 		log_info("Fail to detect board:%d\n", ret);
 	else
 		log_info("Get board name:%s\n", (char *)i2c_buf);
+	pmic_init();
+
 	ddr_early_init();
 }
 
@@ -271,17 +342,6 @@ u32 spl_boot_device(void)
 	return BOOT_DEVICE_NOR;
 }
 
-void pmic_init(void)
-{
-	struct udevice *pmic_dev = NULL;
-	int ret;
-
-	ret = uclass_get_device(UCLASS_PMIC, 0, &pmic_dev);
-	if (ret)
-		panic("Fail to detect PMIC:%d\n", ret);
-}
-
 void spl_board_init(void)
 {
-	pmic_init();
 }
diff --git a/configs/spacemit_k1_defconfig b/configs/spacemit_k1_defconfig
index 65e8143a0bd..33efd204e3a 100644
--- a/configs/spacemit_k1_defconfig
+++ b/configs/spacemit_k1_defconfig
@@ -65,3 +65,12 @@ CONFIG_SPL_I2C_EEPROM=y
 CONFIG_CMD_TLV_EEPROM=y
 CONFIG_SPL_CMD_TLV_EEPROM=y
 CONFIG_LOG=y
+CONFIG_SPL_POWER=y
+CONFIG_DM_PMIC=y
+CONFIG_SPL_DM_PMIC=y
+CONFIG_PMIC_SPACEMIT_P1=y
+CONFIG_SPL_PMIC_SPACEMIT_P1=y
+CONFIG_DM_REGULATOR=y
+CONFIG_SPL_DM_REGULATOR=y
+CONFIG_DM_REGULATOR_SPACEMIT_P1=y
+CONFIG_SPL_DM_REGULATOR_SPACEMIT_P1=y
-- 
2.25.1


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

* Re: [PATCH v2 11/16] i2c: k1: add I2C driver support
  2026-02-10 15:14 ` [PATCH v2 11/16] i2c: k1: add I2C driver support Raymond Mao
@ 2026-02-11  4:57   ` Heiko Schocher
  0 siblings, 0 replies; 24+ messages in thread
From: Heiko Schocher @ 2026-02-11  4:57 UTC (permalink / raw)
  To: Raymond Mao, u-boot
  Cc: uboot, u-boot-spacemit, raymond.mao, rick, ycliang, trini, lukma,
	jh80.chung, peng.fan, xypron.glpk, randolph, dlan, junhui.liu,
	neil.armstrong, quentin.schulz, samuel, Guodong Xu

Hello Raymond,

On 10.02.26 16:14, Raymond Mao wrote:
> From: Raymond Mao <raymond.mao@riscstar.com>
> 
> Add I2C driver support on Spacemit K1 SoC using driver model.
> 
> Signed-off-by: Raymond Mao <raymond.mao@riscstar.com>
> Signed-off-by: Guodong Xu <guodong.xu@riscstar.com>
> ---
>   drivers/i2c/Kconfig  |   7 +
>   drivers/i2c/Makefile |   1 +
>   drivers/i2c/k1_i2c.c | 516 +++++++++++++++++++++++++++++++++++++++++++
>   drivers/i2c/k1_i2c.h |  69 ++++++
>   4 files changed, 593 insertions(+)
>   create mode 100644 drivers/i2c/k1_i2c.c
>   create mode 100644 drivers/i2c/k1_i2c.h

No changelog? (You may take a look at patman tool in
tools/patman)

But it seems, you have addressed my comments to v1, so

Reviewed-by: Heiko Schocher <hs@nabladev.com>

Thanks!

bye,
Heiko

[...]
-- 
Nabla Software Engineering
HRB 40522 Augsburg
Phone: +49 821 45592596
E-Mail: office@nabladev.com
Geschäftsführer : Stefano Babic

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

* Re: [PATCH v2 00/16] Add board support for Spacemit K1 SoC in SPL
  2026-02-10 15:14 [PATCH v2 00/16] Add board support for Spacemit K1 SoC in SPL Raymond Mao
                   ` (15 preceding siblings ...)
  2026-02-10 15:14 ` [PATCH v2 16/16] board: k1: enable pmic in spl Raymond Mao
@ 2026-02-25 14:53 ` Raymond Mao
  2026-03-02 14:36   ` Raymond Mao
  2026-03-11  7:37 ` [PATCH] doc: spacemit: add K1 SPL build and test guide Guodong Xu
  17 siblings, 1 reply; 24+ messages in thread
From: Raymond Mao @ 2026-02-25 14:53 UTC (permalink / raw)
  To: u-boot
  Cc: uboot, u-boot-spacemit, raymond.mao, rick, ycliang, trini, lukma,
	hs, jh80.chung, peng.fan, xypron.glpk, randolph, dlan, junhui.liu,
	neil.armstrong, quentin.schulz, samuel

Hi all,

Any further comments on this series?

Raymond

On Tue, Feb 10, 2026 at 10:15 AM Raymond Mao <raymondmaoca@gmail.com> wrote:
>
> From: Raymond Mao <raymond.mao@riscstar.com>
>
> This patch series introduces full support for the k1 SoC in SPL for
> multiple boards.
>
> The series enables the board by:
> 1. Adding the base board definition with device tree.
> 2. Bringing up essential clock sources and tree.
> 3. Initializing I2C buses for peripheral communication.
> 4. Integrating the PMIC driver for power management.
> 5. Adding regulator drivers for voltage domain control.
>
> Change in v2:
>   - Use read_poll_timeout() in k1 i2c driver.
>   - Abandon to parse offset and size from Kconfig & Makefile for binman.
>   - Abandon to attach firmware image into the patch set.
>   - Update the related document and some minor changes.
>
> Junhui Liu (1):
>   clk: spacemit: Add support for K1 SoC
>
> Raymond Mao (15):
>   spacemit: k1: support multi-board infrastructure
>   spacemit: k1: enable SPL with debug UART
>   configs: k1: enable early timer support
>   reset: k1: add SPL support and enable TWSI8 reset
>   dt-bindings: clock: import k1-syscon from upstream
>   dts: k1: import dts file from upstream folder
>   dts: k1: enable clocks in SPL
>   board: k1: initialize clock and serial devices in SPL
>   configs: k1: add default option for clock driver in SPL
>   i2c: k1: add I2C driver support
>   spacemit: k1: add TLV EEPROM support in SPL
>   spacemit: k1: Add DDR firmware support to SPL
>   power: pmic: add support for Spacemit P1 PMIC
>   power: regulator: add support for Spacemit P1 SoC
>   board: k1: enable pmic in spl
>
>  arch/riscv/Kconfig                            |   10 +-
>  arch/riscv/cpu/k1/Kconfig                     |    6 +
>  arch/riscv/dts/Makefile                       |    1 +
>  arch/riscv/dts/k1-spl.dts                     |  228 +++
>  arch/riscv/dts/k1.dtsi                        |  666 +++++-
>  board/spacemit/bananapi-f3/MAINTAINERS        |    6 -
>  board/spacemit/bananapi-f3/Makefile           |    5 -
>  board/spacemit/{bananapi-f3 => k1}/Kconfig    |   11 +-
>  board/spacemit/k1/MAINTAINERS                 |   11 +
>  board/spacemit/k1/Makefile                    |   27 +
>  board/spacemit/{bananapi-f3 => k1}/board.c    |    0
>  board/spacemit/k1/spl.c                       |  347 ++++
>  board/spacemit/k1/tlv_codes.h                 |   22 +
>  configs/bananapi-f3_defconfig                 |   24 -
>  configs/spacemit_k1_defconfig                 |   76 +
>  doc/board/spacemit/bananapi-f3.rst            |    2 +-
>  drivers/clk/Kconfig                           |    5 +-
>  drivers/clk/Makefile                          |    1 +
>  drivers/clk/spacemit/Kconfig                  |   31 +
>  drivers/clk/spacemit/Makefile                 |    7 +
>  drivers/clk/spacemit/clk-k1.c                 | 1795 +++++++++++++++++
>  drivers/clk/spacemit/clk_common.h             |   79 +
>  drivers/clk/spacemit/clk_ddn.c                |   93 +
>  drivers/clk/spacemit/clk_ddn.h                |   53 +
>  drivers/clk/spacemit/clk_mix.c                |  403 ++++
>  drivers/clk/spacemit/clk_mix.h                |  224 ++
>  drivers/clk/spacemit/clk_pll.c                |  157 ++
>  drivers/clk/spacemit/clk_pll.h                |   81 +
>  drivers/i2c/Kconfig                           |    7 +
>  drivers/i2c/Makefile                          |    1 +
>  drivers/i2c/k1_i2c.c                          |  516 +++++
>  drivers/i2c/k1_i2c.h                          |   69 +
>  drivers/power/pmic/Kconfig                    |   17 +
>  drivers/power/pmic/Makefile                   |    1 +
>  drivers/power/pmic/pmic_spacemit_p1.c         |   94 +
>  drivers/power/regulator/Kconfig               |   15 +
>  drivers/power/regulator/Makefile              |    1 +
>  .../power/regulator/spacemit_p1_regulator.c   |  460 +++++
>  drivers/reset/Kconfig                         |    7 +
>  drivers/reset/Makefile                        |    2 +-
>  drivers/reset/reset-spacemit-k1.c             |    4 -
>  include/configs/bananapi-f3.h                 |   13 -
>  include/configs/k1.h                          |   19 +
>  .../dt-bindings/clock/spacemit,k1-syscon.h    |  253 +++
>  include/power/spacemit_p1.h                   |  163 ++
>  include/soc/spacemit/k1-syscon.h              |  149 ++
>  46 files changed, 5997 insertions(+), 165 deletions(-)
>  create mode 100644 arch/riscv/dts/k1-spl.dts
>  delete mode 100644 board/spacemit/bananapi-f3/MAINTAINERS
>  delete mode 100644 board/spacemit/bananapi-f3/Makefile
>  rename board/spacemit/{bananapi-f3 => k1}/Kconfig (63%)
>  create mode 100644 board/spacemit/k1/MAINTAINERS
>  create mode 100644 board/spacemit/k1/Makefile
>  rename board/spacemit/{bananapi-f3 => k1}/board.c (100%)
>  create mode 100644 board/spacemit/k1/spl.c
>  create mode 100644 board/spacemit/k1/tlv_codes.h
>  delete mode 100644 configs/bananapi-f3_defconfig
>  create mode 100644 configs/spacemit_k1_defconfig
>  create mode 100644 drivers/clk/spacemit/Kconfig
>  create mode 100644 drivers/clk/spacemit/Makefile
>  create mode 100644 drivers/clk/spacemit/clk-k1.c
>  create mode 100644 drivers/clk/spacemit/clk_common.h
>  create mode 100644 drivers/clk/spacemit/clk_ddn.c
>  create mode 100644 drivers/clk/spacemit/clk_ddn.h
>  create mode 100644 drivers/clk/spacemit/clk_mix.c
>  create mode 100644 drivers/clk/spacemit/clk_mix.h
>  create mode 100644 drivers/clk/spacemit/clk_pll.c
>  create mode 100644 drivers/clk/spacemit/clk_pll.h
>  create mode 100644 drivers/i2c/k1_i2c.c
>  create mode 100644 drivers/i2c/k1_i2c.h
>  create mode 100644 drivers/power/pmic/pmic_spacemit_p1.c
>  create mode 100644 drivers/power/regulator/spacemit_p1_regulator.c
>  delete mode 100644 include/configs/bananapi-f3.h
>  create mode 100644 include/configs/k1.h
>  create mode 100644 include/dt-bindings/clock/spacemit,k1-syscon.h
>  create mode 100644 include/power/spacemit_p1.h
>  create mode 100644 include/soc/spacemit/k1-syscon.h
>
> --
> 2.25.1
>

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

* Re: [PATCH v2 00/16] Add board support for Spacemit K1 SoC in SPL
  2026-02-25 14:53 ` [PATCH v2 00/16] Add board support for Spacemit K1 SoC in SPL Raymond Mao
@ 2026-03-02 14:36   ` Raymond Mao
  0 siblings, 0 replies; 24+ messages in thread
From: Raymond Mao @ 2026-03-02 14:36 UTC (permalink / raw)
  To: u-boot
  Cc: uboot, u-boot-spacemit, raymond.mao, rick, ycliang, trini, lukma,
	hs, jh80.chung, peng.fan, xypron.glpk, randolph, dlan, junhui.liu,
	neil.armstrong, quentin.schulz, samuel

Hi Tom, Leo and Rick,

Can I get help from you to get this series merged?

Thanks and regards,
Raymond

On Wed, Feb 25, 2026 at 9:53 AM Raymond Mao <raymondmaoca@gmail.com> wrote:
>
> Hi all,
>
> Any further comments on this series?
>
> Raymond
>
> On Tue, Feb 10, 2026 at 10:15 AM Raymond Mao <raymondmaoca@gmail.com> wrote:
> >
> > From: Raymond Mao <raymond.mao@riscstar.com>
> >
> > This patch series introduces full support for the k1 SoC in SPL for
> > multiple boards.
> >
> > The series enables the board by:
> > 1. Adding the base board definition with device tree.
> > 2. Bringing up essential clock sources and tree.
> > 3. Initializing I2C buses for peripheral communication.
> > 4. Integrating the PMIC driver for power management.
> > 5. Adding regulator drivers for voltage domain control.
> >
> > Change in v2:
> >   - Use read_poll_timeout() in k1 i2c driver.
> >   - Abandon to parse offset and size from Kconfig & Makefile for binman.
> >   - Abandon to attach firmware image into the patch set.
> >   - Update the related document and some minor changes.
> >
> > Junhui Liu (1):
> >   clk: spacemit: Add support for K1 SoC
> >
> > Raymond Mao (15):
> >   spacemit: k1: support multi-board infrastructure
> >   spacemit: k1: enable SPL with debug UART
> >   configs: k1: enable early timer support
> >   reset: k1: add SPL support and enable TWSI8 reset
> >   dt-bindings: clock: import k1-syscon from upstream
> >   dts: k1: import dts file from upstream folder
> >   dts: k1: enable clocks in SPL
> >   board: k1: initialize clock and serial devices in SPL
> >   configs: k1: add default option for clock driver in SPL
> >   i2c: k1: add I2C driver support
> >   spacemit: k1: add TLV EEPROM support in SPL
> >   spacemit: k1: Add DDR firmware support to SPL
> >   power: pmic: add support for Spacemit P1 PMIC
> >   power: regulator: add support for Spacemit P1 SoC
> >   board: k1: enable pmic in spl
> >
> >  arch/riscv/Kconfig                            |   10 +-
> >  arch/riscv/cpu/k1/Kconfig                     |    6 +
> >  arch/riscv/dts/Makefile                       |    1 +
> >  arch/riscv/dts/k1-spl.dts                     |  228 +++
> >  arch/riscv/dts/k1.dtsi                        |  666 +++++-
> >  board/spacemit/bananapi-f3/MAINTAINERS        |    6 -
> >  board/spacemit/bananapi-f3/Makefile           |    5 -
> >  board/spacemit/{bananapi-f3 => k1}/Kconfig    |   11 +-
> >  board/spacemit/k1/MAINTAINERS                 |   11 +
> >  board/spacemit/k1/Makefile                    |   27 +
> >  board/spacemit/{bananapi-f3 => k1}/board.c    |    0
> >  board/spacemit/k1/spl.c                       |  347 ++++
> >  board/spacemit/k1/tlv_codes.h                 |   22 +
> >  configs/bananapi-f3_defconfig                 |   24 -
> >  configs/spacemit_k1_defconfig                 |   76 +
> >  doc/board/spacemit/bananapi-f3.rst            |    2 +-
> >  drivers/clk/Kconfig                           |    5 +-
> >  drivers/clk/Makefile                          |    1 +
> >  drivers/clk/spacemit/Kconfig                  |   31 +
> >  drivers/clk/spacemit/Makefile                 |    7 +
> >  drivers/clk/spacemit/clk-k1.c                 | 1795 +++++++++++++++++
> >  drivers/clk/spacemit/clk_common.h             |   79 +
> >  drivers/clk/spacemit/clk_ddn.c                |   93 +
> >  drivers/clk/spacemit/clk_ddn.h                |   53 +
> >  drivers/clk/spacemit/clk_mix.c                |  403 ++++
> >  drivers/clk/spacemit/clk_mix.h                |  224 ++
> >  drivers/clk/spacemit/clk_pll.c                |  157 ++
> >  drivers/clk/spacemit/clk_pll.h                |   81 +
> >  drivers/i2c/Kconfig                           |    7 +
> >  drivers/i2c/Makefile                          |    1 +
> >  drivers/i2c/k1_i2c.c                          |  516 +++++
> >  drivers/i2c/k1_i2c.h                          |   69 +
> >  drivers/power/pmic/Kconfig                    |   17 +
> >  drivers/power/pmic/Makefile                   |    1 +
> >  drivers/power/pmic/pmic_spacemit_p1.c         |   94 +
> >  drivers/power/regulator/Kconfig               |   15 +
> >  drivers/power/regulator/Makefile              |    1 +
> >  .../power/regulator/spacemit_p1_regulator.c   |  460 +++++
> >  drivers/reset/Kconfig                         |    7 +
> >  drivers/reset/Makefile                        |    2 +-
> >  drivers/reset/reset-spacemit-k1.c             |    4 -
> >  include/configs/bananapi-f3.h                 |   13 -
> >  include/configs/k1.h                          |   19 +
> >  .../dt-bindings/clock/spacemit,k1-syscon.h    |  253 +++
> >  include/power/spacemit_p1.h                   |  163 ++
> >  include/soc/spacemit/k1-syscon.h              |  149 ++
> >  46 files changed, 5997 insertions(+), 165 deletions(-)
> >  create mode 100644 arch/riscv/dts/k1-spl.dts
> >  delete mode 100644 board/spacemit/bananapi-f3/MAINTAINERS
> >  delete mode 100644 board/spacemit/bananapi-f3/Makefile
> >  rename board/spacemit/{bananapi-f3 => k1}/Kconfig (63%)
> >  create mode 100644 board/spacemit/k1/MAINTAINERS
> >  create mode 100644 board/spacemit/k1/Makefile
> >  rename board/spacemit/{bananapi-f3 => k1}/board.c (100%)
> >  create mode 100644 board/spacemit/k1/spl.c
> >  create mode 100644 board/spacemit/k1/tlv_codes.h
> >  delete mode 100644 configs/bananapi-f3_defconfig
> >  create mode 100644 configs/spacemit_k1_defconfig
> >  create mode 100644 drivers/clk/spacemit/Kconfig
> >  create mode 100644 drivers/clk/spacemit/Makefile
> >  create mode 100644 drivers/clk/spacemit/clk-k1.c
> >  create mode 100644 drivers/clk/spacemit/clk_common.h
> >  create mode 100644 drivers/clk/spacemit/clk_ddn.c
> >  create mode 100644 drivers/clk/spacemit/clk_ddn.h
> >  create mode 100644 drivers/clk/spacemit/clk_mix.c
> >  create mode 100644 drivers/clk/spacemit/clk_mix.h
> >  create mode 100644 drivers/clk/spacemit/clk_pll.c
> >  create mode 100644 drivers/clk/spacemit/clk_pll.h
> >  create mode 100644 drivers/i2c/k1_i2c.c
> >  create mode 100644 drivers/i2c/k1_i2c.h
> >  create mode 100644 drivers/power/pmic/pmic_spacemit_p1.c
> >  create mode 100644 drivers/power/regulator/spacemit_p1_regulator.c
> >  delete mode 100644 include/configs/bananapi-f3.h
> >  create mode 100644 include/configs/k1.h
> >  create mode 100644 include/dt-bindings/clock/spacemit,k1-syscon.h
> >  create mode 100644 include/power/spacemit_p1.h
> >  create mode 100644 include/soc/spacemit/k1-syscon.h
> >
> > --
> > 2.25.1
> >

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

* Re: [PATCH v2 14/16] power: pmic: add support for Spacemit P1 PMIC
  2026-02-10 15:14 ` [PATCH v2 14/16] power: pmic: add support for Spacemit P1 PMIC Raymond Mao
@ 2026-03-03  3:37   ` Peng Fan
  0 siblings, 0 replies; 24+ messages in thread
From: Peng Fan @ 2026-03-03  3:37 UTC (permalink / raw)
  To: Raymond Mao
  Cc: u-boot, uboot, u-boot-spacemit, raymond.mao, rick, ycliang, trini,
	lukma, hs, jh80.chung, peng.fan, xypron.glpk, randolph, dlan,
	junhui.liu, neil.armstrong, quentin.schulz, samuel, Guodong Xu

On Tue, Feb 10, 2026 at 10:14:57AM -0500, Raymond Mao wrote:
>From: Raymond Mao <raymond.mao@riscstar.com>
>
>Spacemit's PMIC is used by Spacemit K1 SoC. It contains voltage
>regulators, GPIOs and Watchdog.
>
>Signed-off-by: Raymond Mao <raymond.mao@riscstar.com>
>Signed-off-by: Guodong Xu <guodong.xu@riscstar.com>

Acked-by: Peng Fan <peng.fan@nxp.com>

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

* Re: [PATCH v2 15/16] power: regulator: add support for Spacemit P1 SoC
  2026-02-10 15:14 ` [PATCH v2 15/16] power: regulator: add support for Spacemit P1 SoC Raymond Mao
@ 2026-03-03  3:37   ` Peng Fan
  0 siblings, 0 replies; 24+ messages in thread
From: Peng Fan @ 2026-03-03  3:37 UTC (permalink / raw)
  To: Raymond Mao
  Cc: u-boot, uboot, u-boot-spacemit, raymond.mao, rick, ycliang, trini,
	lukma, hs, jh80.chung, peng.fan, xypron.glpk, randolph, dlan,
	junhui.liu, neil.armstrong, quentin.schulz, samuel

On Tue, Feb 10, 2026 at 10:14:58AM -0500, Raymond Mao wrote:
>From: Raymond Mao <raymond.mao@riscstar.com>
>
>Support voltage regulator for Spacemit P1 SoC. It contains 6 BUCKs
>and 11 LDOs.
>
>Signed-off-by: Raymond Mao <raymond.mao@riscstar.com>

Acked-by: Peng Fan <peng.fan@nxp.com>

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

* [PATCH] doc: spacemit: add K1 SPL build and test guide
  2026-02-10 15:14 [PATCH v2 00/16] Add board support for Spacemit K1 SoC in SPL Raymond Mao
                   ` (16 preceding siblings ...)
  2026-02-25 14:53 ` [PATCH v2 00/16] Add board support for Spacemit K1 SoC in SPL Raymond Mao
@ 2026-03-11  7:37 ` Guodong Xu
  17 siblings, 0 replies; 24+ messages in thread
From: Guodong Xu @ 2026-03-11  7:37 UTC (permalink / raw)
  To: u-boot
  Cc: trini, heinrich.schuchardt, rick, ycliang, raymond.mao,
	u-boot-spacemit, Guodong Xu

The K1 SPL patchset requires DDR firmware integration and FSBL signing
steps that are not covered by existing documentation. Add a SoC-level
guide so reviewers and developers can build and test on hardware.

Signed-off-by: Guodong Xu <guodong@riscstar.com>
---
Following up on the discussion at yesterday's community meeting, this
patch adds build and test instructions for the K1 SPL patchset [1].

This is placed as a SoC-level guide since the SPL build and flashing
procedure is shared across all K1 boards. The existing bananapi-f3.rst
will be updated to reference this in a future patch as more of the boot
chain is upstreamed.

Link: https://lore.kernel.org/u-boot/20260210151459.2348758-1-raymondmaoca@gmail.com/ [1]

 doc/board/spacemit/index.rst  |   1 +
 doc/board/spacemit/k1-spl.rst | 214 ++++++++++++++++++++++++++++++++++
 2 files changed, 215 insertions(+)
 create mode 100644 doc/board/spacemit/k1-spl.rst

diff --git a/doc/board/spacemit/index.rst b/doc/board/spacemit/index.rst
index e7d3d94e459..a5e35ee12ab 100644
--- a/doc/board/spacemit/index.rst
+++ b/doc/board/spacemit/index.rst
@@ -6,4 +6,5 @@ SpacemiT
    :maxdepth: 1
 
    bananapi-f3
+   k1-spl
 
diff --git a/doc/board/spacemit/k1-spl.rst b/doc/board/spacemit/k1-spl.rst
new file mode 100644
index 00000000000..3e22f6dec70
--- /dev/null
+++ b/doc/board/spacemit/k1-spl.rst
@@ -0,0 +1,214 @@
+.. SPDX-License-Identifier: GPL-2.0-or-later
+
+SpacemiT K1 SPL Build and Test Guide
+=====================================
+
+This guide explains how to build and test U-Boot SPL on SpacemiT K1 based
+boards. It covers building SPL with DDR initialization, generating the signed
+FSBL image, and deploying via USB fastboot.
+
+Tested boards: Banana Pi BPI-F3, MusePi Pro.
+
+Prerequisites
+~~~~~~~~~~~~~
+
+- A SpacemiT K1 board with USB Type-C and UART access
+- USB-to-UART adapter (3.3V TTL)
+- ``minicom`` or equivalent serial terminal, configured at 115200 8N1
+- ``fastboot`` tool on the host
+
+Hardware Setup
+~~~~~~~~~~~~~~
+
+**1. UART Connection**
+
+Connect a 3.3V USB-to-UART cable to the **J25** header on the BPI-F3.
+Remove all other cables first, then attach UART::
+
+    BPI-F3 top view
+    +--------------------------------------------------+
+    |                                                  |
+    |   J15: USB-C [====]     [FDL] [PWR] [RST]       |
+    |                                                  |
+    |                                                  |
+    |                              J25 (UART header)   |
+    |                              [TXD] [RXD] [GND]  |
+    +--------------------------------------------------+
+
+After UART is connected, attach the USB Type-C cable to J15 to power on.
+
+**2. Serial Console**
+
+.. code-block:: console
+
+   $ minicom -D /dev/ttyUSB0
+
+Default baudrate: 115200.
+
+Building U-Boot SPL
+~~~~~~~~~~~~~~~~~~~~
+
+**1. Obtain the DDR training firmware**
+
+The DDR training firmware is a proprietary binary provided by SpacemiT. It is
+not included in U-Boot and must be downloaded separately from:
+
+https://github.com/spacemit-com/spacemit-firmware/tree/master/k1/v0.2
+
+Download ``ddr_fw.bin`` from that directory.
+
+This binary is integrated into the SPL image at build time via the binman
+framework. When the SPL image is loaded to SRAM (e.g., via USB fastboot),
+the SPL executes the DDR firmware from SRAM to perform DDR initialization.
+
+**2. Build SPL**
+
+.. code-block:: console
+
+   $ export CROSS_COMPILE=riscv64-linux-gnu-
+   $ export ARCH=riscv
+   $ export DDR_FW_FILE=$(pwd)/ddr_fw.bin
+   $ make spacemit_k1_defconfig
+   $ make
+
+Output: ``u-boot-spl-ddr.bin`` in the build directory. This image contains the
+SPL code and the DDR firmware blob packaged together via binman.
+
+.. note::
+
+   If ``DDR_FW_FILE`` is not set, the build completes with an empty
+   placeholder. The resulting SPL will boot but cannot initialize DDR.
+
+**3. Generate signed FSBL image**
+
+The K1 BootROM requires a signed first-stage bootloader (FSBL). The signing
+tool (``tools/build_binary_file.py``) is in SpacemiT's vendor U-Boot repository:
+
+.. code-block:: console
+
+   $ git clone https://gitee.com/bianbu-linux/uboot-2022.10
+
+The script uses ``fsbl_ddr.json`` which may not exist by default. If
+``fsbl_ddr.json`` does not exist in ``uboot-2022.10/spl_bin/configs/``,
+create it by copying ``fsbl.json`` and replacing the reference to
+``u-boot-spl.bin`` with ``u-boot-spl-ddr.bin``:
+
+.. code-block:: console
+
+   $ cd uboot-2022.10/spl_bin/configs
+   $ cp fsbl.json fsbl_ddr.json
+   $ sed -i 's/u-boot-spl\.bin/u-boot-spl-ddr.bin/g' fsbl_ddr.json
+
+Create the ``fsbl.sh`` script below in the ``uboot-2022.10`` directory.
+Update the path variables to match your local setup:
+
+.. code-block:: bash
+
+   #!/bin/sh
+   MAINLINE_UBOOT_IMG_PATH="{your path}/u-boot"
+   MAINLINE_SPL_IMG_PATH="{your path}/u-boot/spl"
+   FSBL_PATH="{your path}/uboot-2022.10/spl_bin"
+   KEY_TOOL_PATH="{your path}/uboot-2022.10/tools"
+   CONFIG_PATH="{your path}/uboot-2022.10/spl_bin/configs"
+
+   echo "Clean binaries in ${FSBL_PATH}"
+   rm -f ${FSBL_PATH}/u-boot-spl-ddr.bin
+   rm -f ${FSBL_PATH}/u-boot-spl.bin
+
+   if [ ! -d ${MAINLINE_SPL_IMG_PATH} ]; then
+           MAINLINE_UBOOT_IMG_PATH="{your path}/build"
+           MAINLINE_SPL_IMG_PATH="{your path}/build/spl"
+   fi
+
+   cp ${MAINLINE_UBOOT_IMG_PATH}/u-boot-spl-ddr.bin ${FSBL_PATH}/
+   python3 ${KEY_TOOL_PATH}/build_binary_file.py \
+       -c ${CONFIG_PATH}/fsbl_ddr.json \
+       -o ${FSBL_PATH}/FSBL.bin
+
+Then run:
+
+.. code-block:: console
+
+   $ chmod +x fsbl.sh
+   $ ./fsbl.sh
+
+Output: ``FSBL.bin`` in the ``spl_bin`` directory, ready for deployment.
+
+Deploying via USB Fastboot
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+To enter BootROM fastboot mode:
+
+1. Disconnect USB Type-C cable from J15 (power off)
+2. **Press and hold** the FDL button (see board layout above)
+3. Reconnect USB Type-C cable while holding the FDL button
+4. Release the FDL button
+
+The serial console should show a BootROM prompt indicating it is ready to
+accept an image via USB.
+
+On the host:
+
+.. code-block:: console
+
+   $ sudo fastboot stage FSBL.bin
+   $ sudo fastboot continue
+
+Expected Output
+~~~~~~~~~~~~~~~~
+
+After successful SPL boot with DDR initialization, the serial console displays
+messages confirming:
+
+- I2C and PMIC initialization
+- DDR training firmware loaded and executed
+- DDR initialization complete
+
+Sample DDR training success log::
+
+    Read Training.....
+    each RX Vref corresponding min margin = 9 10 10 11 11 12 11 11 11 10 10 9 8 4 4 0
+     optimize Rx Vref adjust=5 ,corresponding best margin=12
+    Again!!! training optimize Fine Rx vref step = 5
+    Write Training.....
+    each TX Vref corresponding min margin = 9 9 9 10 9 10 10 10 10 10 10 10 10 10 10 10
+     optimize Tx Vref adjust=24 ,corresponding best margin=10
+    Again!!! training optimize Fine Tx vref step = 24
+    Training status[0xFFFFFFFC0058000]=0x00000000
+    DDR DQ rx margin:
+    0xc083feb0: 0d 0d 0d 0c 0d 0d 0d 0d 0d 0d 0d 0d 0d 0d 0d 0c
+    0xc083fec0: 0d 0d 0d 0d 0c 0d 0c 0d 0c 0c 0c 0d 0d 0d 0d 0d
+    DDR DQ tx margin:
+    0xc083fed0: 0b 0b 0b 0a 0b 0b 0b 0b 0a 0b 0a 0b 0b 0b 0b 0a
+    0xc083fee0: 0c 0b 0b 0a 0b 0b 0b 0b 0a 0a 0a 0b 0a 0b 0a 0a
+    change to 2400MTPS
+    !!!!!ADDR[0xffffffffd4282bb4]=0x00033b40 !!!!
+    frequency change done!!!!
+    ADDR[0xffffffffd4282bb4]=0x00033b40 !!!!
+    150000 KHZ: 1; 150000 KHZ: 1; 200000 KHZ: 1; 266000 KHZ: 1; 300000 KHZ: 1; 400000 KHZ: 1; 600000 KHZ: 2; 666000 KHZ: 3;
+    Change DDR data rate to 2400MT/s
+    ddr_early_init: ret:2400
+
+Key success indicators:
+
+- ``Read Training`` / ``Write Training`` - DDR read/write training completed
+- ``Training status[...]=0x00000000`` - training completed with no errors
+- ``change to 2400MTPS`` and ``frequency change done`` - DDR frequency switch succeeded
+- ``Change DDR data rate to 2400MT/s`` - DDR running at target speed
+- ``ddr_early_init: ret:2400`` - DDR init function returned successfully
+
+.. note::
+
+   After DDR init succeeds, SPL proceeds to load U-Boot proper. If U-Boot
+   proper is not yet available (as in SPL-only testing), you will see
+   ``SPL: failed to boot from all boot devices`` - this is expected and
+   confirms that SPL with DDR init is working correctly.
+
+If SPL hangs before printing DDR messages, verify that ``DDR_FW_FILE`` was set
+during build and that ``ddr_fw.bin`` is not empty.
+
+References
+~~~~~~~~~~~
+
+- `DDR firmware repository <https://github.com/spacemit-com/spacemit-firmware>`_
+- `SpacemiT vendor U-Boot (signing tool) <https://gitee.com/bianbu-linux/uboot-2022.10>`_
-- 
2.43.0


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

* Re: [PATCH v2 01/16] spacemit: k1: support multi-board infrastructure
  2026-02-10 15:14 ` [PATCH v2 01/16] spacemit: k1: support multi-board infrastructure Raymond Mao
@ 2026-03-19  6:44   ` Leo Liang
  0 siblings, 0 replies; 24+ messages in thread
From: Leo Liang @ 2026-03-19  6:44 UTC (permalink / raw)
  To: Raymond Mao
  Cc: u-boot, uboot, u-boot-spacemit, raymond.mao, rick, trini, lukma,
	hs, jh80.chung, peng.fan, xypron.glpk, randolph, dlan, junhui.liu,
	neil.armstrong, quentin.schulz, samuel

Hi Raymond,

On Tue, Feb 10, 2026 at 10:14:44AM -0500, Raymond Mao wrote:
> From: Raymond Mao <raymond.mao@riscstar.com>
> 
> Restructure K1 SoC support to handle multiple boards through a single
> configuration:
> 
> 1. Rename bananapi-f3_defconfig to k1_defconfig.
> 2. Move all K1 board files to k1 directory.
> 
> Eliminates the need for board-specific defconfigs while maintaining
> hardware compatibility.
> 
> Signed-off-by: Raymond Mao <raymond.mao@riscstar.com>
> ---
>  arch/riscv/Kconfig                                    | 10 ++++++----
>  arch/riscv/cpu/k1/Kconfig                             |  4 ++++
>  board/spacemit/{bananapi-f3 => k1}/Kconfig            | 11 ++++++++---
>  board/spacemit/{bananapi-f3 => k1}/MAINTAINERS        |  4 ++--
>  board/spacemit/{bananapi-f3 => k1}/Makefile           |  0
>  board/spacemit/{bananapi-f3 => k1}/board.c            |  0
>  .../{bananapi-f3_defconfig => spacemit_k1_defconfig}  |  3 ++-
>  doc/board/spacemit/bananapi-f3.rst                    |  2 +-
>  include/configs/{bananapi-f3.h => k1.h}               |  0
>  9 files changed, 23 insertions(+), 11 deletions(-)
>  rename board/spacemit/{bananapi-f3 => k1}/Kconfig (63%)
>  rename board/spacemit/{bananapi-f3 => k1}/MAINTAINERS (61%)
>  rename board/spacemit/{bananapi-f3 => k1}/Makefile (100%)
>  rename board/spacemit/{bananapi-f3 => k1}/board.c (100%)
>  rename configs/{bananapi-f3_defconfig => spacemit_k1_defconfig} (97%)
>  rename include/configs/{bananapi-f3.h => k1.h} (100%)

This patch seems to cause recursive dependency error.
https://source.denx.de/u-boot/custodians/u-boot-riscv/-/jobs/1405503
Could you fix this and respin the patchset again?

Best regards,
Leo

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

end of thread, other threads:[~2026-03-19  6:45 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-02-10 15:14 [PATCH v2 00/16] Add board support for Spacemit K1 SoC in SPL Raymond Mao
2026-02-10 15:14 ` [PATCH v2 01/16] spacemit: k1: support multi-board infrastructure Raymond Mao
2026-03-19  6:44   ` Leo Liang
2026-02-10 15:14 ` [PATCH v2 02/16] spacemit: k1: enable SPL with debug UART Raymond Mao
2026-02-10 15:14 ` [PATCH v2 03/16] configs: k1: enable early timer support Raymond Mao
2026-02-10 15:14 ` [PATCH v2 04/16] reset: k1: add SPL support and enable TWSI8 reset Raymond Mao
2026-02-10 15:14 ` [PATCH v2 05/16] dt-bindings: clock: import k1-syscon from upstream Raymond Mao
2026-02-10 15:14 ` [PATCH v2 06/16] dts: k1: import dts file from upstream folder Raymond Mao
2026-02-10 15:14 ` [PATCH v2 07/16] clk: spacemit: Add support for K1 SoC Raymond Mao
2026-02-10 15:14 ` [PATCH v2 08/16] dts: k1: enable clocks in SPL Raymond Mao
2026-02-10 15:14 ` [PATCH v2 09/16] board: k1: initialize clock and serial devices " Raymond Mao
2026-02-10 15:14 ` [PATCH v2 10/16] configs: k1: add default option for clock driver " Raymond Mao
2026-02-10 15:14 ` [PATCH v2 11/16] i2c: k1: add I2C driver support Raymond Mao
2026-02-11  4:57   ` Heiko Schocher
2026-02-10 15:14 ` [PATCH v2 12/16] spacemit: k1: add TLV EEPROM support in SPL Raymond Mao
2026-02-10 15:14 ` [PATCH v2 13/16] spacemit: k1: Add DDR firmware support to SPL Raymond Mao
2026-02-10 15:14 ` [PATCH v2 14/16] power: pmic: add support for Spacemit P1 PMIC Raymond Mao
2026-03-03  3:37   ` Peng Fan
2026-02-10 15:14 ` [PATCH v2 15/16] power: regulator: add support for Spacemit P1 SoC Raymond Mao
2026-03-03  3:37   ` Peng Fan
2026-02-10 15:14 ` [PATCH v2 16/16] board: k1: enable pmic in spl Raymond Mao
2026-02-25 14:53 ` [PATCH v2 00/16] Add board support for Spacemit K1 SoC in SPL Raymond Mao
2026-03-02 14:36   ` Raymond Mao
2026-03-11  7:37 ` [PATCH] doc: spacemit: add K1 SPL build and test guide Guodong Xu

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