* [PATCH 0/8] riscv: spacemit: k1: add clock reset drivers, switch to upstream DT
@ 2026-05-10 12:06 Guodong Xu
2026-05-10 12:06 ` [PATCH 1/8] clk: spacemit: Add support for K1 SoC Guodong Xu
` (8 more replies)
0 siblings, 9 replies; 14+ messages in thread
From: Guodong Xu @ 2026-05-10 12:06 UTC (permalink / raw)
To: u-boot
Cc: Tom Rini, Lukasz Majewski, Patrice Chotard, Patrick Delaunay,
Michal Simek, Quentin Schulz, Yao Zi, Junhui Liu, Peter Korsgaard,
Leo Yu-Chi Liang, Raymond Mao, Gabriel Fernandez, Kever Yang,
Finley Xiao, Rick Chen, Conor Dooley, u-boot-spacemit,
Vincent Legoll, Guodong Xu, Heinrich Schuchardt
Currently U-Boot's SpacemiT K1 ships its own arch/riscv/dts/k1.dtsi and a
spacemit,k1-reset binding that has no node in the upstream
(kernel-mainline) K1 dts. After list discussion [1], this series
moves U-Boot to the upstream DT before further K1 work lands.
In the upstream DT, each K1 syscon provides both clocks and resets.
The kernel's clock driver spawns the reset child via the auxiliary
bus. This patchset does the same in U-Boot: each clock driver
spawns a UCLASS_RESET sibling on the same ofnode.
Patch 1/8 adds the K1 clock driver.
Patch 2/8 adds a new syscon-bound reset driver with no DT of_match. At this
point, the legacy reset driver and local dts are still there.
Patch 3/8 has each per-syscon clock driver spawn the reset child on the
same ofnode, the way the kernel uses auxiliary devices.
Patch 4/8 enables the clock driver.
Patch 5/8 switches BPI-F3 to dts/upstream/.
Patch 6/8, 7/8 and 8/8 clean up the legacy reset driver and local dts files.
Old and new reset drivers coexist from 2/8 through 6/8 so the series
is bisectable.
The K1 SPL bring-up [2] and PIN/SPI [3] series will be rebased on
this and resent once it lands.
Link: https://lore.kernel.org/u-boot/20260507140558.GU1614990@bill-the-cat/ [1]
Link: https://lore.kernel.org/u-boot/20260325223232.1553212-1-raymondmaoca@gmail.com/ [2]
Link: https://lore.kernel.org/u-boot/20260422143112.1329478-1-raymondmaoca@gmail.com/ [3]
Signed-off-by: Guodong Xu <guodong@riscstar.com>
---
Guodong Xu (7):
reset: spacemit: k1: introduce syscon-bound reset driver
clk: spacemit: k1: spawn reset device from per-syscon clock drivers
configs: bananapi-f3: enable Spacemit K1 clock driver
dts: k1: switch BPI-F3 build to upstream DT
dts: k1: drop legacy local DT files
reset: spacemit: k1: drop legacy spacemit,k1-reset driver
dt-bindings: reset: drop spacemit-k1-reset.h
Junhui Liu (1):
clk: spacemit: Add support for K1 SoC
arch/riscv/dts/Makefile | 1 -
arch/riscv/dts/k1-bananapi-f3-u-boot.dtsi | 30 +
arch/riscv/dts/k1-bananapi-f3.dts | 28 -
arch/riscv/dts/k1-pinctrl.dtsi | 19 -
arch/riscv/dts/k1.dtsi | 480 -------
configs/bananapi-f3_defconfig | 6 +-
drivers/clk/Kconfig | 5 +-
drivers/clk/Makefile | 1 +
drivers/clk/spacemit/Kconfig | 23 +
drivers/clk/spacemit/Makefile | 7 +
drivers/clk/spacemit/clk-k1.c | 1759 +++++++++++++++++++++++++
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/reset/Kconfig | 7 -
drivers/reset/Makefile | 2 +-
drivers/reset/reset-spacemit-k1.c | 548 --------
drivers/reset/spacemit/Makefile | 5 +
drivers/reset/spacemit/reset-spacemit-k1.c | 289 ++++
include/dt-bindings/reset/spacemit-k1-reset.h | 118 --
include/soc/spacemit/k1-reset.h | 23 +
include/soc/spacemit/k1-syscon.h | 149 +++
26 files changed, 3384 insertions(+), 1206 deletions(-)
---
base-commit: 24db98cdf911b6ca362209e674bf9412441c1095
change-id: 20260510-b4-k1-clk-reset-upstream-dts-cbf1f3a79cfb
Best regards,
--
Guodong Xu <guodong@riscstar.com>
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 1/8] clk: spacemit: Add support for K1 SoC
2026-05-10 12:06 [PATCH 0/8] riscv: spacemit: k1: add clock reset drivers, switch to upstream DT Guodong Xu
@ 2026-05-10 12:06 ` Guodong Xu
2026-05-22 16:09 ` Yao Zi
2026-05-10 12:06 ` [PATCH 2/8] reset: spacemit: k1: introduce syscon-bound reset driver Guodong Xu
` (7 subsequent siblings)
8 siblings, 1 reply; 14+ messages in thread
From: Guodong Xu @ 2026-05-10 12:06 UTC (permalink / raw)
To: u-boot
Cc: Tom Rini, Lukasz Majewski, Patrice Chotard, Patrick Delaunay,
Michal Simek, Quentin Schulz, Yao Zi, Junhui Liu, Peter Korsgaard,
Leo Yu-Chi Liang, Raymond Mao, Gabriel Fernandez, Kever Yang,
Finley Xiao, Rick Chen, Conor Dooley, u-boot-spacemit,
Vincent Legoll, Guodong Xu, Heinrich Schuchardt
From: Junhui Liu <junhui.liu@pigmoral.tech>
The K1 SoC exposes four clock providers in the kernel mainline DT: one
PLL controller ("spacemit,k1-pll") and three syscon clock nodes
("spacemit,k1-syscon-{mpmu,apbc,apmu}"). Register a separate
U_BOOT_DRIVER for each.
Inter-controller ordering is enforced where the registers actually
depend on each other.
Signed-off-by: Junhui Liu <junhui.liu@pigmoral.tech>
Signed-off-by: Raymond Mao <raymond.mao@riscstar.com>
Signed-off-by: Guodong Xu <guodong@riscstar.com>
---
drivers/clk/Kconfig | 5 +-
drivers/clk/Makefile | 1 +
drivers/clk/spacemit/Kconfig | 23 +
drivers/clk/spacemit/Makefile | 7 +
drivers/clk/spacemit/clk-k1.c | 1722 +++++++++++++++++++++++++++++++++++++
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, 2995 insertions(+), 2 deletions(-)
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index c88931c8ec4..913550698f8 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -276,11 +276,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..03aecefddc4
--- /dev/null
+++ b/drivers/clk/spacemit/Kconfig
@@ -0,0 +1,23 @@
+# 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
+ select LIB_RATIONAL
+ help
+ This enables support clock driver for Spacemit K1 SoC.
+ It's based on Common Clock Framework.
+
+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..4c0972d952e
--- /dev/null
+++ b/drivers/clk/spacemit/clk-k1.c
@@ -0,0 +1,1722 @@
+// 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);
+
+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);
+/* 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);
+
+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);
+/* 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);
+
+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);
+
+/* 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,
+};
+
+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,
+};
+
+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,
+};
+
+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,
+};
+
+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,
+};
+
+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,
+ &pmua_aclk.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,
+ &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,
+};
+
+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;
+
+ if (common->clk.id < K1_PLL_ID)
+ clk->id = common->clk.id + data->offset;
+ else
+ clk->id = common->clk.id;
+
+ ret = common->init(common);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int k1_pll_clk_probe(struct udevice *dev)
+{
+ struct regmap *base_regmap, *lock_regmap = NULL;
+ const struct spacemit_ccu_data *data;
+ int ret;
+
+ 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_mpmu_clk_probe(struct udevice *dev)
+{
+ struct regmap *base_regmap, *lock_regmap = NULL;
+ const struct spacemit_ccu_data *data;
+ struct clk clk;
+ int ret;
+
+ /* probe PLL 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;
+
+ 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_apmu_clk_probe(struct udevice *dev)
+{
+ struct regmap *base_regmap, *lock_regmap = NULL;
+ const struct spacemit_ccu_data *data;
+ int ret;
+
+ ret = regmap_init_mem(dev_ofnode(dev), &base_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;
+ struct clk clk;
+ int ret;
+
+ /* probe PLL controller */
+ ret = clk_get_by_index(dev, 4, &clk);
+ if (ret)
+ return -EPROBE_DEFER;
+ /* probe MPMU controller */
+ ret = clk_get_by_index(dev, 5, &clk);
+ if (ret)
+ return -EPROBE_DEFER;
+ /* probe APMU controller */
+ ret = clk_get_by_index(dev, 6, &clk);
+ if (ret)
+ return -EPROBE_DEFER;
+
+ ret = regmap_init_mem(dev_ofnode(dev), &base_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_pll_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_mpmu_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_apmu_clk_probe,
+ .ops = &k1_apmu_clk_ops,
+ .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.43.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 2/8] reset: spacemit: k1: introduce syscon-bound reset driver
2026-05-10 12:06 [PATCH 0/8] riscv: spacemit: k1: add clock reset drivers, switch to upstream DT Guodong Xu
2026-05-10 12:06 ` [PATCH 1/8] clk: spacemit: Add support for K1 SoC Guodong Xu
@ 2026-05-10 12:06 ` Guodong Xu
2026-05-10 12:06 ` [PATCH 3/8] clk: spacemit: k1: spawn reset device from per-syscon clock drivers Guodong Xu
` (6 subsequent siblings)
8 siblings, 0 replies; 14+ messages in thread
From: Guodong Xu @ 2026-05-10 12:06 UTC (permalink / raw)
To: u-boot
Cc: Tom Rini, Lukasz Majewski, Patrice Chotard, Patrick Delaunay,
Michal Simek, Quentin Schulz, Yao Zi, Junhui Liu, Peter Korsgaard,
Leo Yu-Chi Liang, Raymond Mao, Gabriel Fernandez, Kever Yang,
Finley Xiao, Rick Chen, Conor Dooley, u-boot-spacemit,
Vincent Legoll, Guodong Xu, Heinrich Schuchardt
The existing K1 reset driver (drivers/reset/reset-spacemit-k1.c) binds
via DT of_match against a top-level reset-controller node, but kernel
mainline DT for K1 has no such node: the mpmu, apbc, apmu and apbc2
syscons each spawn their own reset device as an auxiliary of the
clock controller. The legacy driver therefore cannot consume it.
Add a new reset driver at drivers/reset/spacemit/reset-spacemit-k1.c
bound by name from each per-syscon clock driver via
device_bind_driver_to_node(), without DT of_match, mirroring the
kernel's auxiliary-device pattern.
To keep the series bisectable, this driver coexists link-cleanly with
the legacy spacemit,k1-reset driver during the transition. A
follow-up patch that switches the K1 build to
dts/upstream/src/riscv/spacemit/ will drop the legacy driver.
Signed-off-by: Guodong Xu <guodong@riscstar.com>
---
drivers/reset/Makefile | 1 +
drivers/reset/spacemit/Makefile | 5 +
drivers/reset/spacemit/reset-spacemit-k1.c | 289 +++++++++++++++++++++++++++++
include/soc/spacemit/k1-reset.h | 23 +++
4 files changed, 318 insertions(+)
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index 088545c6473..10e1460ee34 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -35,6 +35,7 @@ obj-$(CONFIG_RESET_AT91) += reset-at91.o
obj-$(CONFIG_$(PHASE_)RESET_JH7110) += reset-jh7110.o
obj-$(CONFIG_RESET_RZG2L_USBPHY_CTRL) += reset-rzg2l-usbphy-ctrl.o
obj-$(CONFIG_RESET_SPACEMIT_K1) += reset-spacemit-k1.o
+obj-$(CONFIG_RESET_SPACEMIT_K1) += spacemit/
obj-$(CONFIG_ARCH_STM32) += stm32/
obj-$(CONFIG_ARCH_STM32MP) += stm32/
diff --git a/drivers/reset/spacemit/Makefile b/drivers/reset/spacemit/Makefile
new file mode 100644
index 00000000000..16722c68954
--- /dev/null
+++ b/drivers/reset/spacemit/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# SpacemiT reset drivers
+
+obj-y += reset-spacemit-k1.o
diff --git a/drivers/reset/spacemit/reset-spacemit-k1.c b/drivers/reset/spacemit/reset-spacemit-k1.c
new file mode 100644
index 00000000000..129e1cc96f1
--- /dev/null
+++ b/drivers/reset/spacemit/reset-spacemit-k1.c
@@ -0,0 +1,289 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * SpacemiT K1 reset driver (syscon-bound).
+ *
+ * Copyright (C) 2022 Spacemit Inc.
+ * Copyright (C) 2025 Huan Zhou <pericycle.cc@gmail.com>
+ * Copyright (C) 2026 RISCstar Ltd.
+ */
+
+#include <asm/io.h>
+#include <dm.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
+#include <dt-bindings/clock/spacemit,k1-syscon.h>
+#include <linux/bitops.h>
+#include <malloc.h>
+#include <reset-uclass.h>
+#include <soc/spacemit/k1-reset.h>
+#include <soc/spacemit/k1-syscon.h>
+
+/* ===================================================================
+ * Per-syscon reset signal tables.
+ *
+ * Indexed by the kernel-side per-syscon-local IDs from
+ * <dt-bindings/clock/spacemit,k1-syscon.h>. Each entry is
+ * (offset, assert_mask, deassert_mask): bits in assert_mask are set
+ * when the reset line is asserted; bits in deassert_mask are set when
+ * deasserted; the union (assert_mask | deassert_mask) is the set of
+ * bits the controller will overwrite on each transition.
+ *
+ * Layout mirrors the kernel-side K1 reset driver.
+ * ===================================================================
+ */
+
+struct spacemit_k1_reset_data {
+ u32 offset;
+ u32 assert_mask;
+ u32 deassert_mask;
+};
+
+#define RESET_DATA(o, a, d) { \
+ .offset = (o), .assert_mask = (a), .deassert_mask = (d) \
+}
+
+static const struct spacemit_k1_reset_data k1_mpmu_resets[] = {
+ [RESET_WDT] = RESET_DATA(MPMU_WDTPCR, BIT(2), 0),
+};
+
+static const struct spacemit_k1_reset_data k1_apbc_resets[] = {
+ [RESET_UART0] = RESET_DATA(APBC_UART1_CLK_RST, BIT(2), 0),
+ [RESET_UART2] = RESET_DATA(APBC_UART2_CLK_RST, BIT(2), 0),
+ [RESET_UART3] = RESET_DATA(APBC_UART3_CLK_RST, BIT(2), 0),
+ [RESET_UART4] = RESET_DATA(APBC_UART4_CLK_RST, BIT(2), 0),
+ [RESET_UART5] = RESET_DATA(APBC_UART5_CLK_RST, BIT(2), 0),
+ [RESET_UART6] = RESET_DATA(APBC_UART6_CLK_RST, BIT(2), 0),
+ [RESET_UART7] = RESET_DATA(APBC_UART7_CLK_RST, BIT(2), 0),
+ [RESET_UART8] = RESET_DATA(APBC_UART8_CLK_RST, BIT(2), 0),
+ [RESET_UART9] = RESET_DATA(APBC_UART9_CLK_RST, BIT(2), 0),
+ [RESET_GPIO] = RESET_DATA(APBC_GPIO_CLK_RST, BIT(2), 0),
+ [RESET_PWM0] = RESET_DATA(APBC_PWM0_CLK_RST, BIT(2), BIT(0)),
+ [RESET_PWM1] = RESET_DATA(APBC_PWM1_CLK_RST, BIT(2), BIT(0)),
+ [RESET_PWM2] = RESET_DATA(APBC_PWM2_CLK_RST, BIT(2), BIT(0)),
+ [RESET_PWM3] = RESET_DATA(APBC_PWM3_CLK_RST, BIT(2), BIT(0)),
+ [RESET_PWM4] = RESET_DATA(APBC_PWM4_CLK_RST, BIT(2), BIT(0)),
+ [RESET_PWM5] = RESET_DATA(APBC_PWM5_CLK_RST, BIT(2), BIT(0)),
+ [RESET_PWM6] = RESET_DATA(APBC_PWM6_CLK_RST, BIT(2), BIT(0)),
+ [RESET_PWM7] = RESET_DATA(APBC_PWM7_CLK_RST, BIT(2), BIT(0)),
+ [RESET_PWM8] = RESET_DATA(APBC_PWM8_CLK_RST, BIT(2), BIT(0)),
+ [RESET_PWM9] = RESET_DATA(APBC_PWM9_CLK_RST, BIT(2), BIT(0)),
+ [RESET_PWM10] = RESET_DATA(APBC_PWM10_CLK_RST, BIT(2), BIT(0)),
+ [RESET_PWM11] = RESET_DATA(APBC_PWM11_CLK_RST, BIT(2), BIT(0)),
+ [RESET_PWM12] = RESET_DATA(APBC_PWM12_CLK_RST, BIT(2), BIT(0)),
+ [RESET_PWM13] = RESET_DATA(APBC_PWM13_CLK_RST, BIT(2), BIT(0)),
+ [RESET_PWM14] = RESET_DATA(APBC_PWM14_CLK_RST, BIT(2), BIT(0)),
+ [RESET_PWM15] = RESET_DATA(APBC_PWM15_CLK_RST, BIT(2), BIT(0)),
+ [RESET_PWM16] = RESET_DATA(APBC_PWM16_CLK_RST, BIT(2), BIT(0)),
+ [RESET_PWM17] = RESET_DATA(APBC_PWM17_CLK_RST, BIT(2), BIT(0)),
+ [RESET_PWM18] = RESET_DATA(APBC_PWM18_CLK_RST, BIT(2), BIT(0)),
+ [RESET_PWM19] = RESET_DATA(APBC_PWM19_CLK_RST, BIT(2), BIT(0)),
+ [RESET_SSP3] = RESET_DATA(APBC_SSP3_CLK_RST, BIT(2), 0),
+ [RESET_RTC] = RESET_DATA(APBC_RTC_CLK_RST, BIT(2), 0),
+ [RESET_TWSI0] = RESET_DATA(APBC_TWSI0_CLK_RST, BIT(2), 0),
+ [RESET_TWSI1] = RESET_DATA(APBC_TWSI1_CLK_RST, BIT(2), 0),
+ [RESET_TWSI2] = RESET_DATA(APBC_TWSI2_CLK_RST, BIT(2), 0),
+ [RESET_TWSI4] = RESET_DATA(APBC_TWSI4_CLK_RST, BIT(2), 0),
+ [RESET_TWSI5] = RESET_DATA(APBC_TWSI5_CLK_RST, BIT(2), 0),
+ [RESET_TWSI6] = RESET_DATA(APBC_TWSI6_CLK_RST, BIT(2), 0),
+ [RESET_TWSI7] = RESET_DATA(APBC_TWSI7_CLK_RST, BIT(2), 0),
+ [RESET_TWSI8] = RESET_DATA(APBC_TWSI8_CLK_RST, BIT(2), 0),
+ [RESET_TIMERS1] = RESET_DATA(APBC_TIMERS1_CLK_RST, BIT(2), 0),
+ [RESET_TIMERS2] = RESET_DATA(APBC_TIMERS2_CLK_RST, BIT(2), 0),
+ [RESET_AIB] = RESET_DATA(APBC_AIB_CLK_RST, BIT(2), 0),
+ [RESET_ONEWIRE] = RESET_DATA(APBC_ONEWIRE_CLK_RST, BIT(2), 0),
+ [RESET_SSPA0] = RESET_DATA(APBC_SSPA0_CLK_RST, BIT(2), 0),
+ [RESET_SSPA1] = RESET_DATA(APBC_SSPA1_CLK_RST, BIT(2), 0),
+ [RESET_DRO] = RESET_DATA(APBC_DRO_CLK_RST, BIT(2), 0),
+ [RESET_IR] = RESET_DATA(APBC_IR_CLK_RST, BIT(2), 0),
+ [RESET_TSEN] = RESET_DATA(APBC_TSEN_CLK_RST, BIT(2), 0),
+ [RESET_IPC_AP2AUD] = RESET_DATA(APBC_IPC_AP2AUD_CLK_RST, BIT(2), 0),
+ [RESET_CAN0] = RESET_DATA(APBC_CAN0_CLK_RST, BIT(2), 0),
+};
+
+static const struct spacemit_k1_reset_data k1_apmu_resets[] = {
+ [RESET_CCIC_4X] = RESET_DATA(APMU_CCIC_CLK_RES_CTRL, 0, BIT(1)),
+ [RESET_CCIC1_PHY] = RESET_DATA(APMU_CCIC_CLK_RES_CTRL, 0, BIT(2)),
+ [RESET_SDH_AXI] = RESET_DATA(APMU_SDH0_CLK_RES_CTRL, 0, BIT(0)),
+ [RESET_SDH0] = RESET_DATA(APMU_SDH0_CLK_RES_CTRL, 0, BIT(1)),
+ [RESET_SDH1] = RESET_DATA(APMU_SDH1_CLK_RES_CTRL, 0, BIT(1)),
+ [RESET_SDH2] = RESET_DATA(APMU_SDH2_CLK_RES_CTRL, 0, BIT(1)),
+ [RESET_USBP1_AXI] = RESET_DATA(APMU_USB_CLK_RES_CTRL, 0, BIT(4)),
+ [RESET_USB_AXI] = RESET_DATA(APMU_USB_CLK_RES_CTRL, 0, BIT(0)),
+ [RESET_USB30_AHB] = RESET_DATA(APMU_USB_CLK_RES_CTRL, 0, BIT(9)),
+ [RESET_USB30_VCC] = RESET_DATA(APMU_USB_CLK_RES_CTRL, 0, BIT(10)),
+ [RESET_USB30_PHY] = RESET_DATA(APMU_USB_CLK_RES_CTRL, 0, BIT(11)),
+ [RESET_QSPI] = RESET_DATA(APMU_QSPI_CLK_RES_CTRL, 0, BIT(1)),
+ [RESET_QSPI_BUS] = RESET_DATA(APMU_QSPI_CLK_RES_CTRL, 0, BIT(0)),
+ [RESET_DMA] = RESET_DATA(APMU_DMA_CLK_RES_CTRL, 0, BIT(0)),
+ [RESET_AES] = RESET_DATA(APMU_AES_CLK_RES_CTRL, 0, BIT(4)),
+ [RESET_VPU] = RESET_DATA(APMU_VPU_CLK_RES_CTRL, 0, BIT(0)),
+ [RESET_GPU] = RESET_DATA(APMU_GPU_CLK_RES_CTRL, 0, BIT(1)),
+ [RESET_EMMC] = RESET_DATA(APMU_PMUA_EM_CLK_RES_CTRL, 0, BIT(1)),
+ [RESET_EMMC_X] = RESET_DATA(APMU_PMUA_EM_CLK_RES_CTRL, 0, BIT(0)),
+ [RESET_AUDIO_SYS] = RESET_DATA(APMU_AUDIO_CLK_RES_CTRL, 0, BIT(0)),
+ [RESET_AUDIO_MCU] = RESET_DATA(APMU_AUDIO_CLK_RES_CTRL, 0, BIT(2)),
+ [RESET_AUDIO_APMU] = RESET_DATA(APMU_AUDIO_CLK_RES_CTRL, 0, BIT(3)),
+ [RESET_HDMI] = RESET_DATA(APMU_HDMI_CLK_RES_CTRL, 0, BIT(9)),
+ [RESET_PCIE0_DBI] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_0, 0, BIT(3)),
+ [RESET_PCIE0_SLAVE] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_0, 0, BIT(4)),
+ [RESET_PCIE0_MASTER] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_0, 0, BIT(5)),
+ [RESET_PCIE0_GLOBAL] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_0, BIT(8), 0),
+ [RESET_PCIE1_DBI] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_1, 0, BIT(3)),
+ [RESET_PCIE1_SLAVE] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_1, 0, BIT(4)),
+ [RESET_PCIE1_MASTER] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_1, 0, BIT(5)),
+ [RESET_PCIE1_GLOBAL] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_1, BIT(8), 0),
+ [RESET_PCIE2_DBI] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_2, 0, BIT(3)),
+ [RESET_PCIE2_SLAVE] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_2, 0, BIT(4)),
+ [RESET_PCIE2_MASTER] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_2, 0, BIT(5)),
+ [RESET_PCIE2_GLOBAL] = RESET_DATA(APMU_PCIE_CLK_RES_CTRL_2, BIT(8), 0),
+ [RESET_EMAC0] = RESET_DATA(APMU_EMAC0_CLK_RES_CTRL, 0, BIT(1)),
+ [RESET_EMAC1] = RESET_DATA(APMU_EMAC1_CLK_RES_CTRL, 0, BIT(1)),
+ [RESET_JPG] = RESET_DATA(APMU_JPG_CLK_RES_CTRL, 0, BIT(0)),
+ [RESET_CCIC2PHY] = RESET_DATA(APMU_CSI_CCIC2_CLK_RES_CTRL, 0, BIT(2)),
+ [RESET_CCIC3PHY] = RESET_DATA(APMU_CSI_CCIC2_CLK_RES_CTRL, 0, BIT(29)),
+ [RESET_CSI] = RESET_DATA(APMU_CSI_CCIC2_CLK_RES_CTRL, 0, BIT(1)),
+ [RESET_ISP] = RESET_DATA(APMU_ISP_CLK_RES_CTRL, 0, BIT(0)),
+ [RESET_ISP_CPP] = RESET_DATA(APMU_ISP_CLK_RES_CTRL, 0, BIT(27)),
+ [RESET_ISP_BUS] = RESET_DATA(APMU_ISP_CLK_RES_CTRL, 0, BIT(3)),
+ [RESET_ISP_CI] = RESET_DATA(APMU_ISP_CLK_RES_CTRL, 0, BIT(16)),
+ [RESET_DPU_MCLK] = RESET_DATA(APMU_LCD_CLK_RES_CTRL2, 0, BIT(9)),
+ [RESET_DPU_ESC] = RESET_DATA(APMU_LCD_CLK_RES_CTRL1, 0, BIT(3)),
+ [RESET_DPU_HCLK] = RESET_DATA(APMU_LCD_CLK_RES_CTRL1, 0, BIT(4)),
+ [RESET_DPU_SPIBUS] = RESET_DATA(APMU_LCD_SPI_CLK_RES_CTRL, 0, BIT(4)),
+ [RESET_DPU_SPI_HBUS] = RESET_DATA(APMU_LCD_SPI_CLK_RES_CTRL, 0, BIT(2)),
+ [RESET_V2D] = RESET_DATA(APMU_LCD_CLK_RES_CTRL1, 0, BIT(27)),
+ [RESET_MIPI] = RESET_DATA(APMU_LCD_CLK_RES_CTRL1, 0, BIT(15)),
+ [RESET_MC] = RESET_DATA(APMU_PMUA_MC_CTRL, 0, BIT(0)),
+};
+
+static const struct spacemit_k1_reset_data k1_apbc2_resets[] = {
+ [RESET_APBC2_UART1] = RESET_DATA(APBC2_UART1_CLK_RST, BIT(2), 0),
+ [RESET_APBC2_SSP2] = RESET_DATA(APBC2_SSP2_CLK_RST, BIT(2), 0),
+ [RESET_APBC2_TWSI3] = RESET_DATA(APBC2_TWSI3_CLK_RST, BIT(2), 0),
+ [RESET_APBC2_RTC] = RESET_DATA(APBC2_RTC_CLK_RST, BIT(2), 0),
+ [RESET_APBC2_TIMERS0] = RESET_DATA(APBC2_TIMERS0_CLK_RST, BIT(2), 0),
+ [RESET_APBC2_KPC] = RESET_DATA(APBC2_KPC_CLK_RST, BIT(2), 0),
+ [RESET_APBC2_GPIO] = RESET_DATA(APBC2_GPIO_CLK_RST, BIT(2), 0),
+};
+
+/* ===================================================================
+ * Driver
+ * ===================================================================
+ */
+
+struct spacemit_k1_reset_priv {
+ void __iomem *base;
+ const struct spacemit_k1_reset_data *table;
+ size_t table_size;
+};
+
+static int spacemit_k1_reset_xfer(struct reset_ctl *rst, bool assert)
+{
+ struct spacemit_k1_reset_priv *priv = dev_get_priv(rst->dev);
+ const struct spacemit_k1_reset_data *e;
+ u32 v;
+
+ if (rst->id >= priv->table_size)
+ return -EINVAL;
+
+ e = &priv->table[rst->id];
+ if (e->assert_mask == 0 && e->deassert_mask == 0)
+ return -EINVAL; /* not owned by this syscon */
+
+ v = readl(priv->base + e->offset);
+ v &= ~(e->assert_mask | e->deassert_mask);
+ v |= assert ? e->assert_mask : e->deassert_mask;
+ writel(v, priv->base + e->offset);
+
+ return 0;
+}
+
+static int spacemit_k1_reset_assert(struct reset_ctl *rst)
+{
+ return spacemit_k1_reset_xfer(rst, true);
+}
+
+static int spacemit_k1_reset_deassert(struct reset_ctl *rst)
+{
+ return spacemit_k1_reset_xfer(rst, false);
+}
+
+static int spacemit_k1_reset_request(struct reset_ctl *rst)
+{
+ struct spacemit_k1_reset_priv *priv = dev_get_priv(rst->dev);
+
+ return rst->id < priv->table_size ? 0 : -EINVAL;
+}
+
+static const struct reset_ops spacemit_k1_reset_ops = {
+ .request = spacemit_k1_reset_request,
+ .rst_assert = spacemit_k1_reset_assert,
+ .rst_deassert = spacemit_k1_reset_deassert,
+};
+
+static int spacemit_k1_reset_probe(struct udevice *dev)
+{
+ struct spacemit_k1_reset_priv *priv = dev_get_priv(dev);
+
+ priv->base = (void __iomem *)dev_remap_addr(dev);
+ if (!priv->base)
+ return -ENODEV;
+
+ return 0;
+}
+
+U_BOOT_DRIVER(spacemit_k1_reset) = {
+ .name = "spacemit_k1_reset",
+ .id = UCLASS_RESET,
+ .ops = &spacemit_k1_reset_ops,
+ .probe = spacemit_k1_reset_probe,
+ .priv_auto = sizeof(struct spacemit_k1_reset_priv),
+ .flags = DM_FLAG_PRE_RELOC,
+};
+
+int spacemit_k1_reset_bind(struct udevice *parent,
+ enum spacemit_k1_reset_syscon syscon)
+{
+ struct spacemit_k1_reset_priv *priv;
+ struct udevice *rst_dev;
+ const struct spacemit_k1_reset_data *table;
+ size_t table_size;
+ int ret;
+
+ switch (syscon) {
+ case SPACEMIT_K1_RESET_MPMU:
+ table = k1_mpmu_resets;
+ table_size = ARRAY_SIZE(k1_mpmu_resets);
+ break;
+ case SPACEMIT_K1_RESET_APMU:
+ table = k1_apmu_resets;
+ table_size = ARRAY_SIZE(k1_apmu_resets);
+ break;
+ case SPACEMIT_K1_RESET_APBC:
+ table = k1_apbc_resets;
+ table_size = ARRAY_SIZE(k1_apbc_resets);
+ break;
+ case SPACEMIT_K1_RESET_APBC2:
+ table = k1_apbc2_resets;
+ table_size = ARRAY_SIZE(k1_apbc2_resets);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ret = device_bind_driver_to_node(parent, "spacemit_k1_reset", "reset",
+ dev_ofnode(parent), &rst_dev);
+ if (ret)
+ return ret;
+
+ priv = malloc(sizeof(*priv));
+ if (!priv) {
+ device_unbind(rst_dev);
+ return -ENOMEM;
+ }
+ priv->table = table;
+ priv->table_size = table_size;
+ dev_set_priv(rst_dev, priv);
+
+ return 0;
+}
diff --git a/include/soc/spacemit/k1-reset.h b/include/soc/spacemit/k1-reset.h
new file mode 100644
index 00000000000..1dbfd6b1cb0
--- /dev/null
+++ b/include/soc/spacemit/k1-reset.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * SpacemiT K1 reset driver — header interface.
+ *
+ * Copyright (C) 2026 RISCstar Ltd.
+ */
+
+#ifndef _SOC_SPACEMIT_K1_RESET_H
+#define _SOC_SPACEMIT_K1_RESET_H
+
+struct udevice;
+
+enum spacemit_k1_reset_syscon {
+ SPACEMIT_K1_RESET_MPMU,
+ SPACEMIT_K1_RESET_APMU,
+ SPACEMIT_K1_RESET_APBC,
+ SPACEMIT_K1_RESET_APBC2,
+};
+
+int spacemit_k1_reset_bind(struct udevice *parent,
+ enum spacemit_k1_reset_syscon syscon);
+
+#endif /* _SOC_SPACEMIT_K1_RESET_H */
--
2.43.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 3/8] clk: spacemit: k1: spawn reset device from per-syscon clock drivers
2026-05-10 12:06 [PATCH 0/8] riscv: spacemit: k1: add clock reset drivers, switch to upstream DT Guodong Xu
2026-05-10 12:06 ` [PATCH 1/8] clk: spacemit: Add support for K1 SoC Guodong Xu
2026-05-10 12:06 ` [PATCH 2/8] reset: spacemit: k1: introduce syscon-bound reset driver Guodong Xu
@ 2026-05-10 12:06 ` Guodong Xu
2026-05-10 12:06 ` [PATCH 4/8] configs: bananapi-f3: enable Spacemit K1 clock driver Guodong Xu
` (5 subsequent siblings)
8 siblings, 0 replies; 14+ messages in thread
From: Guodong Xu @ 2026-05-10 12:06 UTC (permalink / raw)
To: u-boot
Cc: Tom Rini, Lukasz Majewski, Patrice Chotard, Patrick Delaunay,
Michal Simek, Quentin Schulz, Yao Zi, Junhui Liu, Peter Korsgaard,
Leo Yu-Chi Liang, Raymond Mao, Gabriel Fernandez, Kever Yang,
Finley Xiao, Rick Chen, Conor Dooley, u-boot-spacemit,
Vincent Legoll, Guodong Xu, Heinrich Schuchardt
The K1 reset driver in drivers/reset/spacemit/ binds by name (no DT
of_match), so the per-syscon clock drivers must spawn it.
Add a .bind hook to k1_mpmu_clk, k1_apbc_clk and k1_apmu_clk that
calls spacemit_k1_reset_bind() to instantiate a UCLASS_RESET sibling
on the same ofnode.
Also introduce k1_apbc2_clk here. Its kernel DT node has #reset-cells
but no #clock-cells, so the driver exists only as the binding hook
for the apbc2 reset spawn.
With this in place, references such as
resets = <&syscon_apbc RESET_TWSI0>;
in the kernel-mainline DT resolve correctly.
Signed-off-by: Guodong Xu <guodong@riscstar.com>
---
drivers/clk/spacemit/clk-k1.c | 37 +++++++++++++++++++++++++++++++++++++
1 file changed, 37 insertions(+)
diff --git a/drivers/clk/spacemit/clk-k1.c b/drivers/clk/spacemit/clk-k1.c
index 4c0972d952e..80eede251b8 100644
--- a/drivers/clk/spacemit/clk-k1.c
+++ b/drivers/clk/spacemit/clk-k1.c
@@ -13,6 +13,7 @@
#include <dm/lists.h>
#include <regmap.h>
#include <linux/clk-provider.h>
+#include <soc/spacemit/k1-reset.h>
#include <soc/spacemit/k1-syscon.h>
#include "clk_common.h"
@@ -1670,6 +1671,26 @@ U_BOOT_DRIVER(k1_pll_clk) = {
.flags = DM_FLAG_PRE_RELOC,
};
+static int k1_mpmu_clk_bind(struct udevice *dev)
+{
+ return spacemit_k1_reset_bind(dev, SPACEMIT_K1_RESET_MPMU);
+}
+
+static int k1_apbc_clk_bind(struct udevice *dev)
+{
+ return spacemit_k1_reset_bind(dev, SPACEMIT_K1_RESET_APBC);
+}
+
+static int k1_apmu_clk_bind(struct udevice *dev)
+{
+ return spacemit_k1_reset_bind(dev, SPACEMIT_K1_RESET_APMU);
+}
+
+static int k1_apbc2_clk_bind(struct udevice *dev)
+{
+ return spacemit_k1_reset_bind(dev, SPACEMIT_K1_RESET_APBC2);
+}
+
static const struct udevice_id k1_mpmu_clk_match[] = {
{ .compatible = "spacemit,k1-syscon-mpmu",
.data = (ulong)&k1_ccu_mpmu_data },
@@ -1682,6 +1703,7 @@ U_BOOT_DRIVER(k1_mpmu_clk) = {
.name = "k1_mpmu_clk",
.id = UCLASS_CLK,
.of_match = k1_mpmu_clk_match,
+ .bind = k1_mpmu_clk_bind,
.probe = k1_mpmu_clk_probe,
.ops = &k1_mpmu_clk_ops,
.flags = DM_FLAG_PRE_RELOC,
@@ -1699,6 +1721,7 @@ U_BOOT_DRIVER(k1_apbc_clk) = {
.name = "k1_apbc_clk",
.id = UCLASS_CLK,
.of_match = k1_apbc_clk_match,
+ .bind = k1_apbc_clk_bind,
.probe = k1_apbc_clk_probe,
.ops = &k1_apbc_clk_ops,
.flags = DM_FLAG_PRE_RELOC,
@@ -1716,7 +1739,21 @@ U_BOOT_DRIVER(k1_apmu_clk) = {
.name = "k1_apmu_clk",
.id = UCLASS_CLK,
.of_match = k1_apmu_clk_match,
+ .bind = k1_apmu_clk_bind,
.probe = k1_apmu_clk_probe,
.ops = &k1_apmu_clk_ops,
.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,
+ .bind = k1_apbc2_clk_bind,
+ .flags = DM_FLAG_PRE_RELOC,
+};
--
2.43.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 4/8] configs: bananapi-f3: enable Spacemit K1 clock driver
2026-05-10 12:06 [PATCH 0/8] riscv: spacemit: k1: add clock reset drivers, switch to upstream DT Guodong Xu
` (2 preceding siblings ...)
2026-05-10 12:06 ` [PATCH 3/8] clk: spacemit: k1: spawn reset device from per-syscon clock drivers Guodong Xu
@ 2026-05-10 12:06 ` Guodong Xu
2026-05-10 12:06 ` [PATCH 5/8] dts: k1: switch BPI-F3 build to upstream DT Guodong Xu
` (4 subsequent siblings)
8 siblings, 0 replies; 14+ messages in thread
From: Guodong Xu @ 2026-05-10 12:06 UTC (permalink / raw)
To: u-boot
Cc: Tom Rini, Lukasz Majewski, Patrice Chotard, Patrick Delaunay,
Michal Simek, Quentin Schulz, Yao Zi, Junhui Liu, Peter Korsgaard,
Leo Yu-Chi Liang, Raymond Mao, Gabriel Fernandez, Kever Yang,
Finley Xiao, Rick Chen, Conor Dooley, u-boot-spacemit,
Vincent Legoll, Guodong Xu, Heinrich Schuchardt
Enable CLK_SPACEMIT and CLK_SPACEMIT_K1 to compile in the K1
per-syscon clock drivers.
Signed-off-by: Guodong Xu <guodong@riscstar.com>
---
configs/bananapi-f3_defconfig | 2 ++
1 file changed, 2 insertions(+)
diff --git a/configs/bananapi-f3_defconfig b/configs/bananapi-f3_defconfig
index a726ce84775..9f9424adc9f 100644
--- a/configs/bananapi-f3_defconfig
+++ b/configs/bananapi-f3_defconfig
@@ -17,6 +17,8 @@ CONFIG_SYS_PBSIZE=276
# CONFIG_BOARD_INIT is not set
CONFIG_HUSH_PARSER=y
CONFIG_ENV_OVERWRITE=y
+CONFIG_CLK_SPACEMIT=y
+CONFIG_CLK_SPACEMIT_K1=y
CONFIG_PINCTRL=y
CONFIG_PINCTRL_SINGLE=y
CONFIG_RESET_SPACEMIT_K1=y
--
2.43.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 5/8] dts: k1: switch BPI-F3 build to upstream DT
2026-05-10 12:06 [PATCH 0/8] riscv: spacemit: k1: add clock reset drivers, switch to upstream DT Guodong Xu
` (3 preceding siblings ...)
2026-05-10 12:06 ` [PATCH 4/8] configs: bananapi-f3: enable Spacemit K1 clock driver Guodong Xu
@ 2026-05-10 12:06 ` Guodong Xu
2026-05-10 12:06 ` [PATCH 6/8] dts: k1: drop legacy local DT files Guodong Xu
` (3 subsequent siblings)
8 siblings, 0 replies; 14+ messages in thread
From: Guodong Xu @ 2026-05-10 12:06 UTC (permalink / raw)
To: u-boot
Cc: Tom Rini, Lukasz Majewski, Patrice Chotard, Patrick Delaunay,
Michal Simek, Quentin Schulz, Yao Zi, Junhui Liu, Peter Korsgaard,
Leo Yu-Chi Liang, Raymond Mao, Gabriel Fernandez, Kever Yang,
Finley Xiao, Rick Chen, Conor Dooley, u-boot-spacemit,
Vincent Legoll, Guodong Xu, Heinrich Schuchardt
Adopt the kernel device tree directly from
dts/upstream/src/riscv/spacemit/k1-bananapi-f3.dts instead of carrying
a forked copy under arch/riscv/dts/.
Carry U-Boot-only deltas in k1-bananapi-f3-u-boot.dtsi, in particular
extra parent clocks on &syscon_mpmu and &syscon_apbc. The kernel CCF
registers these parents programmatically inside the syscon driver,
but U-Boot's per-syscon probes look them up by clk_get_by_index() for
inter-controller ordering, so they must appear in DT.
Signed-off-by: Guodong Xu <guodong@riscstar.com>
---
arch/riscv/dts/Makefile | 1 -
arch/riscv/dts/k1-bananapi-f3-u-boot.dtsi | 30 ++++++++++++++++++++++++++++++
configs/bananapi-f3_defconfig | 3 ++-
3 files changed, 32 insertions(+), 2 deletions(-)
diff --git a/arch/riscv/dts/Makefile b/arch/riscv/dts/Makefile
index 8e591cb7aa9..71c5c13d221 100644
--- a/arch/riscv/dts/Makefile
+++ b/arch/riscv/dts/Makefile
@@ -2,7 +2,6 @@
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
dtb-$(CONFIG_TARGET_K230_CANMV) += k230-canmv.dtb
dtb-$(CONFIG_TARGET_MICROCHIP_ICICLE) += mpfs-icicle-kit.dtb
dtb-$(CONFIG_TARGET_MILKV_DUO) += cv1800b-milkv-duo.dtb
diff --git a/arch/riscv/dts/k1-bananapi-f3-u-boot.dtsi b/arch/riscv/dts/k1-bananapi-f3-u-boot.dtsi
new file mode 100644
index 00000000000..9e1925eb68e
--- /dev/null
+++ b/arch/riscv/dts/k1-bananapi-f3-u-boot.dtsi
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Copyright (C) 2026 RISCstar Ltd.
+ */
+
+#include <dt-bindings/clock/spacemit,k1-syscon.h>
+#include "binman.dtsi"
+
+/ {
+ memory@0 {
+ device_type = "memory";
+ reg = <0x00000000 0x00000000 0x00000000 0x80000000>;
+ };
+};
+
+&syscon_mpmu {
+ clocks = <&osc_32k>, <&vctcxo_1m>, <&vctcxo_3m>, <&vctcxo_24m>,
+ <&pll CLK_PLL1_D4>;
+ clock-names = "osc", "vctcxo_1m", "vctcxo_3m", "vctcxo_24m",
+ "pll1_d4";
+};
+
+&syscon_apbc {
+ clocks = <&osc_32k>, <&vctcxo_1m>, <&vctcxo_3m>, <&vctcxo_24m>,
+ <&pll CLK_PLL1_D4>,
+ <&syscon_mpmu CLK_PLL1_31P5>,
+ <&syscon_apmu CLK_PMUA_ACLK>;
+ clock-names = "osc", "vctcxo_1m", "vctcxo_3m", "vctcxo_24m",
+ "pll1_d4", "pll1_d78_31p5", "pmua_aclk";
+};
diff --git a/configs/bananapi-f3_defconfig b/configs/bananapi-f3_defconfig
index 9f9424adc9f..b9a2ee19f53 100644
--- a/configs/bananapi-f3_defconfig
+++ b/configs/bananapi-f3_defconfig
@@ -3,7 +3,7 @@ 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="spacemit/k1-bananapi-f3"
CONFIG_SYS_BOOTM_LEN=0xa000000
CONFIG_SYS_LOAD_ADDR=0x200000
CONFIG_TARGET_BANANAPI_F3=y
@@ -16,6 +16,7 @@ CONFIG_SYS_CBSIZE=256
CONFIG_SYS_PBSIZE=276
# CONFIG_BOARD_INIT is not set
CONFIG_HUSH_PARSER=y
+CONFIG_OF_UPSTREAM=y
CONFIG_ENV_OVERWRITE=y
CONFIG_CLK_SPACEMIT=y
CONFIG_CLK_SPACEMIT_K1=y
--
2.43.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 6/8] dts: k1: drop legacy local DT files
2026-05-10 12:06 [PATCH 0/8] riscv: spacemit: k1: add clock reset drivers, switch to upstream DT Guodong Xu
` (4 preceding siblings ...)
2026-05-10 12:06 ` [PATCH 5/8] dts: k1: switch BPI-F3 build to upstream DT Guodong Xu
@ 2026-05-10 12:06 ` Guodong Xu
2026-05-10 12:06 ` [PATCH 7/8] reset: spacemit: k1: drop legacy spacemit,k1-reset driver Guodong Xu
` (2 subsequent siblings)
8 siblings, 0 replies; 14+ messages in thread
From: Guodong Xu @ 2026-05-10 12:06 UTC (permalink / raw)
To: u-boot
Cc: Tom Rini, Lukasz Majewski, Patrice Chotard, Patrick Delaunay,
Michal Simek, Quentin Schulz, Yao Zi, Junhui Liu, Peter Korsgaard,
Leo Yu-Chi Liang, Raymond Mao, Gabriel Fernandez, Kever Yang,
Finley Xiao, Rick Chen, Conor Dooley, u-boot-spacemit,
Vincent Legoll, Guodong Xu, Heinrich Schuchardt
The K1 build now consumes the kernel device tree via OF_UPSTREAM. The
local copies under arch/riscv/dts/ (k1.dtsi, k1-pinctrl.dtsi,
k1-bananapi-f3.dts) are unreachable; remove them.
Signed-off-by: Guodong Xu <guodong@riscstar.com>
---
arch/riscv/dts/k1-bananapi-f3.dts | 28 ---
arch/riscv/dts/k1-pinctrl.dtsi | 19 --
arch/riscv/dts/k1.dtsi | 480 --------------------------------------
3 files changed, 527 deletions(-)
diff --git a/arch/riscv/dts/k1-bananapi-f3.dts b/arch/riscv/dts/k1-bananapi-f3.dts
deleted file mode 100644
index 6b5b83bcdb9..00000000000
--- a/arch/riscv/dts/k1-bananapi-f3.dts
+++ /dev/null
@@ -1,28 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
-/*
- * Copyright (C) 2024 Yangyu Chen <cyy@cyyself.name>
- */
-
-#include "k1.dtsi"
-#include "binman.dtsi"
-#include "k1-pinctrl.dtsi"
-
-/ {
- model = "Banana Pi BPI-F3";
- compatible = "bananapi,bpi-f3", "spacemit,k1";
-
- chosen {
- stdout-path = "serial0";
- };
-
- memory@0 {
- device_type = "memory";
- reg = <0x00000000 0x00000000 0x00000000 0x80000000>;
- };
-};
-
-&uart0 {
- pinctrl-names = "default";
- pinctrl-0 = <&uart0_2_cfg>;
- status = "okay";
-};
diff --git a/arch/riscv/dts/k1-pinctrl.dtsi b/arch/riscv/dts/k1-pinctrl.dtsi
deleted file mode 100644
index 14e7096fbcf..00000000000
--- a/arch/riscv/dts/k1-pinctrl.dtsi
+++ /dev/null
@@ -1,19 +0,0 @@
-// SPDX-License-Identifier: (GPL-2.0 OR MIT)
-/*
- * Copyright (C) 2022 Spacemit Inc.
- * Copyright (C) 2025 Yixun Lan <dlan@gentoo.org>
- */
-
-#define K1_PADCONF(pin, func) (((pin) << 16) | (func))
-
-&pinctrl {
- uart0_2_cfg: uart0-2-cfg {
- uart0-2-pins {
- pinmux = <K1_PADCONF(68, 2)>,
- <K1_PADCONF(69, 2)>;
-
- bias-pull-up = <0>;
- drive-strength = <32>;
- };
- };
-};
diff --git a/arch/riscv/dts/k1.dtsi b/arch/riscv/dts/k1.dtsi
deleted file mode 100644
index a633e43da32..00000000000
--- a/arch/riscv/dts/k1.dtsi
+++ /dev/null
@@ -1,480 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
-/*
- * Copyright (C) 2024 Yangyu Chen <cyy@cyyself.name>
- */
-
-/dts-v1/;
-/ {
- #address-cells = <2>;
- #size-cells = <2>;
- 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>;
- timebase-frequency = <24000000>;
-
- cpu-map {
- cluster0 {
- core0 {
- cpu = <&cpu_0>;
- };
- core1 {
- cpu = <&cpu_1>;
- };
- core2 {
- cpu = <&cpu_2>;
- };
- core3 {
- cpu = <&cpu_3>;
- };
- };
-
- cluster1 {
- core0 {
- cpu = <&cpu_4>;
- };
- core1 {
- cpu = <&cpu_5>;
- };
- core2 {
- cpu = <&cpu_6>;
- };
- core3 {
- cpu = <&cpu_7>;
- };
- };
- };
-
- cpu_0: cpu@0 {
- compatible = "spacemit,x60", "riscv";
- device_type = "cpu";
- reg = <0>;
- riscv,isa = "rv64imafdcv_zicbom_zicbop_zicboz_zicntr_zicond_zicsr_zifencei_zihintpause_zihpm_zfh_zba_zbb_zbc_zbs_zkt_zvfh_zvkt_sscofpmf_sstc_svinval_svnapot_svpbmt";
- riscv,isa-base = "rv64i";
- riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "v", "zicbom",
- "zicbop", "zicboz", "zicntr", "zicond", "zicsr",
- "zifencei", "zihintpause", "zihpm", "zfh", "zba",
- "zbb", "zbc", "zbs", "zkt", "zvfh", "zvkt",
- "sscofpmf", "sstc", "svinval", "svnapot", "svpbmt";
- riscv,cbom-block-size = <64>;
- riscv,cbop-block-size = <64>;
- riscv,cboz-block-size = <64>;
- i-cache-block-size = <64>;
- i-cache-size = <32768>;
- i-cache-sets = <128>;
- d-cache-block-size = <64>;
- d-cache-size = <32768>;
- d-cache-sets = <128>;
- next-level-cache = <&cluster0_l2_cache>;
- mmu-type = "riscv,sv39";
-
- cpu0_intc: interrupt-controller {
- compatible = "riscv,cpu-intc";
- interrupt-controller;
- #interrupt-cells = <1>;
- };
- };
-
- cpu_1: cpu@1 {
- compatible = "spacemit,x60", "riscv";
- device_type = "cpu";
- reg = <1>;
- riscv,isa = "rv64imafdcv_zicbom_zicbop_zicboz_zicntr_zicond_zicsr_zifencei_zihintpause_zihpm_zfh_zba_zbb_zbc_zbs_zkt_zvfh_zvkt_sscofpmf_sstc_svinval_svnapot_svpbmt";
- riscv,isa-base = "rv64i";
- riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "v", "zicbom",
- "zicbop", "zicboz", "zicntr", "zicond", "zicsr",
- "zifencei", "zihintpause", "zihpm", "zfh", "zba",
- "zbb", "zbc", "zbs", "zkt", "zvfh", "zvkt",
- "sscofpmf", "sstc", "svinval", "svnapot", "svpbmt";
- riscv,cbom-block-size = <64>;
- riscv,cbop-block-size = <64>;
- riscv,cboz-block-size = <64>;
- i-cache-block-size = <64>;
- i-cache-size = <32768>;
- i-cache-sets = <128>;
- d-cache-block-size = <64>;
- d-cache-size = <32768>;
- d-cache-sets = <128>;
- next-level-cache = <&cluster0_l2_cache>;
- mmu-type = "riscv,sv39";
-
- cpu1_intc: interrupt-controller {
- compatible = "riscv,cpu-intc";
- interrupt-controller;
- #interrupt-cells = <1>;
- };
- };
-
- cpu_2: cpu@2 {
- compatible = "spacemit,x60", "riscv";
- device_type = "cpu";
- reg = <2>;
- riscv,isa = "rv64imafdcv_zicbom_zicbop_zicboz_zicntr_zicond_zicsr_zifencei_zihintpause_zihpm_zfh_zba_zbb_zbc_zbs_zkt_zvfh_zvkt_sscofpmf_sstc_svinval_svnapot_svpbmt";
- riscv,isa-base = "rv64i";
- riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "v", "zicbom",
- "zicbop", "zicboz", "zicntr", "zicond", "zicsr",
- "zifencei", "zihintpause", "zihpm", "zfh", "zba",
- "zbb", "zbc", "zbs", "zkt", "zvfh", "zvkt",
- "sscofpmf", "sstc", "svinval", "svnapot", "svpbmt";
- riscv,cbom-block-size = <64>;
- riscv,cbop-block-size = <64>;
- riscv,cboz-block-size = <64>;
- i-cache-block-size = <64>;
- i-cache-size = <32768>;
- i-cache-sets = <128>;
- d-cache-block-size = <64>;
- d-cache-size = <32768>;
- d-cache-sets = <128>;
- next-level-cache = <&cluster0_l2_cache>;
- mmu-type = "riscv,sv39";
-
- cpu2_intc: interrupt-controller {
- compatible = "riscv,cpu-intc";
- interrupt-controller;
- #interrupt-cells = <1>;
- };
- };
-
- cpu_3: cpu@3 {
- compatible = "spacemit,x60", "riscv";
- device_type = "cpu";
- reg = <3>;
- riscv,isa = "rv64imafdcv_zicbom_zicbop_zicboz_zicntr_zicond_zicsr_zifencei_zihintpause_zihpm_zfh_zba_zbb_zbc_zbs_zkt_zvfh_zvkt_sscofpmf_sstc_svinval_svnapot_svpbmt";
- riscv,isa-base = "rv64i";
- riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "v", "zicbom",
- "zicbop", "zicboz", "zicntr", "zicond", "zicsr",
- "zifencei", "zihintpause", "zihpm", "zfh", "zba",
- "zbb", "zbc", "zbs", "zkt", "zvfh", "zvkt",
- "sscofpmf", "sstc", "svinval", "svnapot", "svpbmt";
- riscv,cbom-block-size = <64>;
- riscv,cbop-block-size = <64>;
- riscv,cboz-block-size = <64>;
- i-cache-block-size = <64>;
- i-cache-size = <32768>;
- i-cache-sets = <128>;
- d-cache-block-size = <64>;
- d-cache-size = <32768>;
- d-cache-sets = <128>;
- next-level-cache = <&cluster0_l2_cache>;
- mmu-type = "riscv,sv39";
-
- cpu3_intc: interrupt-controller {
- compatible = "riscv,cpu-intc";
- interrupt-controller;
- #interrupt-cells = <1>;
- };
- };
-
- cpu_4: cpu@4 {
- compatible = "spacemit,x60", "riscv";
- device_type = "cpu";
- reg = <4>;
- riscv,isa = "rv64imafdcv_zicbom_zicbop_zicboz_zicntr_zicond_zicsr_zifencei_zihintpause_zihpm_zfh_zba_zbb_zbc_zbs_zkt_zvfh_zvkt_sscofpmf_sstc_svinval_svnapot_svpbmt";
- riscv,isa-base = "rv64i";
- riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "v", "zicbom",
- "zicbop", "zicboz", "zicntr", "zicond", "zicsr",
- "zifencei", "zihintpause", "zihpm", "zfh", "zba",
- "zbb", "zbc", "zbs", "zkt", "zvfh", "zvkt",
- "sscofpmf", "sstc", "svinval", "svnapot", "svpbmt";
- riscv,cbom-block-size = <64>;
- riscv,cbop-block-size = <64>;
- riscv,cboz-block-size = <64>;
- i-cache-block-size = <64>;
- i-cache-size = <32768>;
- i-cache-sets = <128>;
- d-cache-block-size = <64>;
- d-cache-size = <32768>;
- d-cache-sets = <128>;
- next-level-cache = <&cluster1_l2_cache>;
- mmu-type = "riscv,sv39";
-
- cpu4_intc: interrupt-controller {
- compatible = "riscv,cpu-intc";
- interrupt-controller;
- #interrupt-cells = <1>;
- };
- };
-
- cpu_5: cpu@5 {
- compatible = "spacemit,x60", "riscv";
- device_type = "cpu";
- reg = <5>;
- riscv,isa = "rv64imafdcv_zicbom_zicbop_zicboz_zicntr_zicond_zicsr_zifencei_zihintpause_zihpm_zfh_zba_zbb_zbc_zbs_zkt_zvfh_zvkt_sscofpmf_sstc_svinval_svnapot_svpbmt";
- riscv,isa-base = "rv64i";
- riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "v", "zicbom",
- "zicbop", "zicboz", "zicntr", "zicond", "zicsr",
- "zifencei", "zihintpause", "zihpm", "zfh", "zba",
- "zbb", "zbc", "zbs", "zkt", "zvfh", "zvkt",
- "sscofpmf", "sstc", "svinval", "svnapot", "svpbmt";
- riscv,cbom-block-size = <64>;
- riscv,cbop-block-size = <64>;
- riscv,cboz-block-size = <64>;
- i-cache-block-size = <64>;
- i-cache-size = <32768>;
- i-cache-sets = <128>;
- d-cache-block-size = <64>;
- d-cache-size = <32768>;
- d-cache-sets = <128>;
- next-level-cache = <&cluster1_l2_cache>;
- mmu-type = "riscv,sv39";
-
- cpu5_intc: interrupt-controller {
- compatible = "riscv,cpu-intc";
- interrupt-controller;
- #interrupt-cells = <1>;
- };
- };
-
- cpu_6: cpu@6 {
- compatible = "spacemit,x60", "riscv";
- device_type = "cpu";
- reg = <6>;
- riscv,isa = "rv64imafdcv_zicbom_zicbop_zicboz_zicntr_zicond_zicsr_zifencei_zihintpause_zihpm_zfh_zba_zbb_zbc_zbs_zkt_zvfh_zvkt_sscofpmf_sstc_svinval_svnapot_svpbmt";
- riscv,isa-base = "rv64i";
- riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "v", "zicbom",
- "zicbop", "zicboz", "zicntr", "zicond", "zicsr",
- "zifencei", "zihintpause", "zihpm", "zfh", "zba",
- "zbb", "zbc", "zbs", "zkt", "zvfh", "zvkt",
- "sscofpmf", "sstc", "svinval", "svnapot", "svpbmt";
- riscv,cbom-block-size = <64>;
- riscv,cbop-block-size = <64>;
- riscv,cboz-block-size = <64>;
- i-cache-block-size = <64>;
- i-cache-size = <32768>;
- i-cache-sets = <128>;
- d-cache-block-size = <64>;
- d-cache-size = <32768>;
- d-cache-sets = <128>;
- next-level-cache = <&cluster1_l2_cache>;
- mmu-type = "riscv,sv39";
-
- cpu6_intc: interrupt-controller {
- compatible = "riscv,cpu-intc";
- interrupt-controller;
- #interrupt-cells = <1>;
- };
- };
-
- cpu_7: cpu@7 {
- compatible = "spacemit,x60", "riscv";
- device_type = "cpu";
- reg = <7>;
- riscv,isa = "rv64imafdcv_zicbom_zicbop_zicboz_zicntr_zicond_zicsr_zifencei_zihintpause_zihpm_zfh_zba_zbb_zbc_zbs_zkt_zvfh_zvkt_sscofpmf_sstc_svinval_svnapot_svpbmt";
- riscv,isa-base = "rv64i";
- riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "v", "zicbom",
- "zicbop", "zicboz", "zicntr", "zicond", "zicsr",
- "zifencei", "zihintpause", "zihpm", "zfh", "zba",
- "zbb", "zbc", "zbs", "zkt", "zvfh", "zvkt",
- "sscofpmf", "sstc", "svinval", "svnapot", "svpbmt";
- riscv,cbom-block-size = <64>;
- riscv,cbop-block-size = <64>;
- riscv,cboz-block-size = <64>;
- i-cache-block-size = <64>;
- i-cache-size = <32768>;
- i-cache-sets = <128>;
- d-cache-block-size = <64>;
- d-cache-size = <32768>;
- d-cache-sets = <128>;
- next-level-cache = <&cluster1_l2_cache>;
- mmu-type = "riscv,sv39";
-
- cpu7_intc: interrupt-controller {
- compatible = "riscv,cpu-intc";
- interrupt-controller;
- #interrupt-cells = <1>;
- };
- };
-
- cluster0_l2_cache: l2-cache0 {
- compatible = "cache";
- cache-block-size = <64>;
- cache-level = <2>;
- cache-size = <524288>;
- cache-sets = <512>;
- cache-unified;
- };
-
- cluster1_l2_cache: l2-cache1 {
- compatible = "cache";
- cache-block-size = <64>;
- cache-level = <2>;
- cache-size = <524288>;
- cache-sets = <512>;
- cache-unified;
- };
- };
-
- soc {
- compatible = "simple-bus";
- interrupt-parent = <&plic>;
- #address-cells = <2>;
- #size-cells = <2>;
- 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>;
- 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>;
- 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>;
- 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>;
- 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>;
- 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>;
- 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>;
- 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>;
- 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>;
- status = "disabled";
- };
-
- plic: interrupt-controller@e0000000 {
- compatible = "spacemit,k1-plic", "sifive,plic-1.0.0";
- reg = <0x0 0xe0000000 0x0 0x4000000>;
- interrupts-extended = <&cpu0_intc 11>, <&cpu0_intc 9>,
- <&cpu1_intc 11>, <&cpu1_intc 9>,
- <&cpu2_intc 11>, <&cpu2_intc 9>,
- <&cpu3_intc 11>, <&cpu3_intc 9>,
- <&cpu4_intc 11>, <&cpu4_intc 9>,
- <&cpu5_intc 11>, <&cpu5_intc 9>,
- <&cpu6_intc 11>, <&cpu6_intc 9>,
- <&cpu7_intc 11>, <&cpu7_intc 9>;
- interrupt-controller;
- #address-cells = <0>;
- #interrupt-cells = <1>;
- riscv,ndev = <159>;
- };
-
- clint: timer@e4000000 {
- compatible = "spacemit,k1-clint", "sifive,clint0";
- reg = <0x0 0xe4000000 0x0 0x10000>;
- interrupts-extended = <&cpu0_intc 3>, <&cpu0_intc 7>,
- <&cpu1_intc 3>, <&cpu1_intc 7>,
- <&cpu2_intc 3>, <&cpu2_intc 7>,
- <&cpu3_intc 3>, <&cpu3_intc 7>,
- <&cpu4_intc 3>, <&cpu4_intc 7>,
- <&cpu5_intc 3>, <&cpu5_intc 7>,
- <&cpu6_intc 3>, <&cpu6_intc 7>,
- <&cpu7_intc 3>, <&cpu7_intc 7>;
- };
-
- 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";
- #reset-cells = <1>;
- status = "disabled";
- };
-
- pinctrl: pinctrl@d401e000 {
- compatible = "spacemit,k1-pinctrl", "pinctrl-single";
- reg = <0x0 0xd401e000 0x0 0x400>;
- pinctrl-single,register-width = <32>;
- };
- };
-};
--
2.43.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 7/8] reset: spacemit: k1: drop legacy spacemit,k1-reset driver
2026-05-10 12:06 [PATCH 0/8] riscv: spacemit: k1: add clock reset drivers, switch to upstream DT Guodong Xu
` (5 preceding siblings ...)
2026-05-10 12:06 ` [PATCH 6/8] dts: k1: drop legacy local DT files Guodong Xu
@ 2026-05-10 12:06 ` Guodong Xu
2026-05-10 12:06 ` [PATCH 8/8] dt-bindings: reset: drop spacemit-k1-reset.h Guodong Xu
2026-05-10 19:44 ` [PATCH 0/8] riscv: spacemit: k1: add clock reset drivers, switch to upstream DT Vincent Legoll
8 siblings, 0 replies; 14+ messages in thread
From: Guodong Xu @ 2026-05-10 12:06 UTC (permalink / raw)
To: u-boot
Cc: Tom Rini, Lukasz Majewski, Patrice Chotard, Patrick Delaunay,
Michal Simek, Quentin Schulz, Yao Zi, Junhui Liu, Peter Korsgaard,
Leo Yu-Chi Liang, Raymond Mao, Gabriel Fernandez, Kever Yang,
Finley Xiao, Rick Chen, Conor Dooley, u-boot-spacemit,
Vincent Legoll, Guodong Xu, Heinrich Schuchardt
After the K1 build switched to dts/upstream/src/riscv/spacemit/ and the
local arch/riscv/dts/k1.dtsi was deleted, the legacy
reset-controller@d4050000 DT node no longer exists. The of_match driver
in drivers/reset/reset-spacemit-k1.c (compatible "spacemit,k1-reset")
matches nothing and only sits in the binary as dead code.
Remove the legacy driver file, its Makefile entry, the RESET_SPACEMIT_K1
Kconfig symbol, and its bananapi-f3_defconfig selection. The new
syscon-bound reset driver under drivers/reset/spacemit/ has no
DT of_match of its own and is spawned by the K1 clock drivers, so gate
the subdirectory on CONFIG_CLK_SPACEMIT_K1 instead.
Signed-off-by: Guodong Xu <guodong@riscstar.com>
---
configs/bananapi-f3_defconfig | 1 -
drivers/reset/Kconfig | 7 -
drivers/reset/Makefile | 3 +-
drivers/reset/reset-spacemit-k1.c | 548 --------------------------------------
4 files changed, 1 insertion(+), 558 deletions(-)
diff --git a/configs/bananapi-f3_defconfig b/configs/bananapi-f3_defconfig
index b9a2ee19f53..adecbee10f2 100644
--- a/configs/bananapi-f3_defconfig
+++ b/configs/bananapi-f3_defconfig
@@ -22,6 +22,5 @@ CONFIG_CLK_SPACEMIT=y
CONFIG_CLK_SPACEMIT_K1=y
CONFIG_PINCTRL=y
CONFIG_PINCTRL_SINGLE=y
-CONFIG_RESET_SPACEMIT_K1=y
CONFIG_SYS_NS16550=y
CONFIG_SYS_NS16550_MEM32=y
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index 2fd91d6299c..7af309945fe 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -246,12 +246,5 @@ config RESET_RZG2L_USBPHY_CTRL
RZ/G2L SoC. This is required for USB 2.0 functionality to work on this
SoC.
-config RESET_SPACEMIT_K1
- bool "Support for SPACEMIT's K1 Reset driver"
- depends on DM_RESET
- help
- Support for SPACEMIT's K1 Reset system. Basic Assert/Deassert
- is supported.
-
source "drivers/reset/stm32/Kconfig"
endmenu
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index 10e1460ee34..170446f9a7e 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -34,8 +34,7 @@ obj-$(CONFIG_RESET_DRA7) += reset-dra7.o
obj-$(CONFIG_RESET_AT91) += reset-at91.o
obj-$(CONFIG_$(PHASE_)RESET_JH7110) += reset-jh7110.o
obj-$(CONFIG_RESET_RZG2L_USBPHY_CTRL) += reset-rzg2l-usbphy-ctrl.o
-obj-$(CONFIG_RESET_SPACEMIT_K1) += reset-spacemit-k1.o
-obj-$(CONFIG_RESET_SPACEMIT_K1) += spacemit/
+obj-$(CONFIG_CLK_SPACEMIT_K1) += spacemit/
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
deleted file mode 100644
index 613e002fc4f..00000000000
--- a/drivers/reset/reset-spacemit-k1.c
+++ /dev/null
@@ -1,548 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (C) 2022 Spacemit Inc.
- * Copyright (C) 2025 Huan Zhou <pericycle.cc@gmail.com>
- */
-
-#include <asm/io.h>
-#include <config.h>
-#include <dm.h>
-#include <dm/device_compat.h>
-#include <dm/device-internal.h>
-#include <dm/lists.h>
-#include <dt-bindings/reset/spacemit-k1-reset.h>
-#include <linux/bitops.h>
-#include <reset-uclass.h>
-
-/* APBC register offset */
-#define APBC_UART1_CLK_RST 0x0
-#define APBC_UART2_CLK_RST 0x4
-#define APBC_GPIO_CLK_RST 0x8
-#define APBC_PWM0_CLK_RST 0xc
-#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_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
-/* end of APBC register offset */
-
-/* MPMU register offset */
-#define MPMU_WDTPCR 0x200
-/* end of MPMU register offset */
-
-/* APMU register offset */
-#define APMU_JPG_CLK_RES_CTRL 0x20
-#define APMU_CSI_CCIC2_CLK_RES_CTRL 0x24
-#define APMU_ISP_CLK_RES_CTRL 0x38
-#define APMU_LCD_CLK_RES_CTRL1 0x44
-#define APMU_LCD_SPI_CLK_RES_CTRL 0x48
-#define APMU_LCD_CLK_RES_CTRL2 0x4c
-#define APMU_CCIC_CLK_RES_CTRL 0x50
-#define APMU_SDH0_CLK_RES_CTRL 0x54
-#define APMU_SDH1_CLK_RES_CTRL 0x58
-#define APMU_USB_CLK_RES_CTRL 0x5c
-#define APMU_QSPI_CLK_RES_CTRL 0x60
-#define APMU_USB_CLK_RES_CTRL 0x5c
-#define APMU_DMA_CLK_RES_CTRL 0x64
-#define APMU_AES_CLK_RES_CTRL 0x68
-#define APMU_VPU_CLK_RES_CTRL 0xa4
-#define APMU_GPU_CLK_RES_CTRL 0xcc
-#define APMU_SDH2_CLK_RES_CTRL 0xe0
-#define APMU_PMUA_MC_CTRL 0xe8
-#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_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
-/* end of APMU register offset */
-
-/* APBC2 register offset */
-#define APBC2_UART1_CLK_RST 0x00
-#define APBC2_SSP2_CLK_RST 0x04
-#define APBC2_TWSI3_CLK_RST 0x08
-#define APBC2_RTC_CLK_RST 0x0c
-#define APBC2_TIMERS0_CLK_RST 0x10
-#define APBC2_KPC_CLK_RST 0x14
-#define APBC2_GPIO_CLK_RST 0x1c
-/* end of APBC2 register offset */
-
-enum spacemit_reset_base_type {
- RST_BASE_TYPE_MPMU = 0,
- RST_BASE_TYPE_APMU = 1,
- RST_BASE_TYPE_APBC = 2,
- RST_BASE_TYPE_APBS = 3,
- RST_BASE_TYPE_CIU = 4,
- RST_BASE_TYPE_DCIU = 5,
- RST_BASE_TYPE_DDRC = 6,
- RST_BASE_TYPE_AUDC = 7,
- RST_BASE_TYPE_APBC2 = 8,
-};
-
-struct spacemit_reset_signal {
- u32 offset;
- u32 mask;
- u32 deassert_val;
- u32 assert_val;
- enum spacemit_reset_base_type type;
-};
-
-struct spacemit_reset_base {
- void __iomem *mpmu_base;
- void __iomem *apmu_base;
- void __iomem *apbc_base;
- void __iomem *apbs_base;
- void __iomem *ciu_base;
- void __iomem *dciu_base;
- void __iomem *ddrc_base;
- void __iomem *audio_ctrl_base;
- void __iomem *apbc2_base;
-};
-
-struct spacemit_reset {
- struct spacemit_reset_base io_base;
- const struct spacemit_reset_signal *signals;
-};
-
-enum {
- RESET_TWSI6_SPL = 0,
- RESET_TWSI8_SPL,
- RESET_SDH_AXI_SPL,
- RESET_SDH0_SPL,
- RESET_USB_AXI_SPL,
- RESET_USBP1_AXI_SPL,
- RESET_USB3_0_SPL,
- RESET_QSPI_SPL,
- RESET_QSPI_BUS_SPL,
- RESET_AES_SPL,
- RESET_SDH2_SPL,
- RESET_NUMBER_SPL
-};
-
-static const struct spacemit_reset_signal
- k1_reset_signals[RESET_NUMBER] = {
- [RESET_UART1] = { APBC_UART1_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_UART2] = { APBC_UART2_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_GPIO] = { APBC_GPIO_CLK_RST, BIT(2), 0,
- BIT(2),
- RST_BASE_TYPE_APBC },
- [RESET_PWM0] = { APBC_PWM0_CLK_RST,
- BIT(2) | BIT(0),
- BIT(0),
- BIT(2),
- RST_BASE_TYPE_APBC },
- [RESET_PWM1] = { APBC_PWM1_CLK_RST,
- BIT(2) | BIT(0),
- BIT(0),
- BIT(2),
- RST_BASE_TYPE_APBC },
- [RESET_PWM2] = { APBC_PWM2_CLK_RST,
- BIT(2) | BIT(0),
- BIT(0),
- BIT(2),
- RST_BASE_TYPE_APBC },
- [RESET_PWM3] = { APBC_PWM3_CLK_RST,
- BIT(2) | BIT(0),
- BIT(0),
- BIT(2),
- RST_BASE_TYPE_APBC },
- [RESET_PWM4] = { APBC_PWM4_CLK_RST,
- BIT(2) | BIT(0),
- BIT(0),
- BIT(2),
- RST_BASE_TYPE_APBC },
- [RESET_PWM5] = { APBC_PWM5_CLK_RST,
- BIT(2) | BIT(0),
- BIT(0),
- BIT(2),
- RST_BASE_TYPE_APBC },
- [RESET_PWM6] = { APBC_PWM6_CLK_RST,
- BIT(2) | BIT(0),
- BIT(0),
- BIT(2),
- RST_BASE_TYPE_APBC },
- [RESET_PWM7] = { APBC_PWM7_CLK_RST,
- BIT(2) | BIT(0),
- BIT(0),
- BIT(2),
- RST_BASE_TYPE_APBC },
- [RESET_PWM8] = { APBC_PWM8_CLK_RST,
- BIT(2) | BIT(0),
- BIT(0),
- BIT(2),
- RST_BASE_TYPE_APBC },
- [RESET_PWM9] = { APBC_PWM9_CLK_RST,
- BIT(2) | BIT(0),
- BIT(0),
- BIT(2),
- RST_BASE_TYPE_APBC },
- [RESET_PWM10] = { APBC_PWM10_CLK_RST,
- BIT(2) | BIT(0),
- BIT(0),
- BIT(2),
- RST_BASE_TYPE_APBC },
- [RESET_PWM11] = { APBC_PWM11_CLK_RST,
- BIT(2) | BIT(0),
- BIT(0),
- BIT(2),
- RST_BASE_TYPE_APBC },
- [RESET_PWM12] = { APBC_PWM12_CLK_RST,
- BIT(2) | BIT(0),
- BIT(0),
- BIT(2),
- RST_BASE_TYPE_APBC },
- [RESET_PWM13] = { APBC_PWM13_CLK_RST,
- BIT(2) | BIT(0),
- BIT(0),
- BIT(2),
- RST_BASE_TYPE_APBC },
- [RESET_PWM14] = { APBC_PWM14_CLK_RST,
- BIT(2) | BIT(0),
- BIT(0),
- BIT(2),
- RST_BASE_TYPE_APBC },
- [RESET_PWM15] = { APBC_PWM15_CLK_RST,
- BIT(2) | BIT(0),
- BIT(0),
- BIT(2),
- RST_BASE_TYPE_APBC },
- [RESET_PWM16] = { APBC_PWM16_CLK_RST,
- BIT(2) | BIT(0),
- BIT(0),
- BIT(2),
- RST_BASE_TYPE_APBC },
- [RESET_PWM17] = { APBC_PWM17_CLK_RST,
- BIT(2) | BIT(0),
- BIT(0),
- BIT(2),
- RST_BASE_TYPE_APBC },
- [RESET_PWM18] = { APBC_PWM18_CLK_RST,
- BIT(2) | BIT(0),
- BIT(0),
- BIT(2),
- RST_BASE_TYPE_APBC },
- [RESET_PWM19] = { APBC_PWM19_CLK_RST,
- BIT(2) | BIT(0),
- BIT(0),
- BIT(2),
- RST_BASE_TYPE_APBC },
- [RESET_SSP3] = { APBC_SSP3_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_UART3] = { APBC_UART3_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_RTC] = { APBC_RTC_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_TWSI0] = { APBC_TWSI0_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_TIMERS1] = { APBC_TIMERS1_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_AIB] = { APBC_AIB_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_TIMERS2] = { APBC_TIMERS2_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_ONEWIRE] = { APBC_ONEWIRE_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_SSPA0] = { APBC_SSPA0_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_SSPA1] = { APBC_SSPA1_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_DRO] = { APBC_DRO_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_IR] = { APBC_IR_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_TWSI1] = { APBC_TWSI1_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_TSEN] = { APBC_TSEN_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_TWSI2] = { APBC_TWSI2_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_TWSI4] = { APBC_TWSI4_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_TWSI5] = { APBC_TWSI5_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_TWSI6] = { APBC_TWSI6_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_TWSI7] = { APBC_TWSI7_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_TWSI8] = { APBC_TWSI8_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_IPC_AP2AUD] = { APBC_IPC_AP2AUD_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_UART4] = { APBC_UART4_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_UART5] = { APBC_UART5_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_UART6] = { APBC_UART6_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_UART7] = { APBC_UART7_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_UART8] = { APBC_UART8_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_UART9] = { APBC_UART9_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- [RESET_CAN0] = { APBC_CAN0_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
- /* MPMU */
- [RESET_WDT] = { MPMU_WDTPCR, BIT(2), 0, BIT(2), RST_BASE_TYPE_MPMU },
- /* APMU */
- [RESET_JPG] = { APMU_JPG_CLK_RES_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU },
- [RESET_CSI] = { APMU_CSI_CCIC2_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU },
- [RESET_CCIC2_PHY] = { APMU_CSI_CCIC2_CLK_RES_CTRL,
- BIT(2),
- BIT(2),
- 0,
- RST_BASE_TYPE_APMU },
- [RESET_CCIC3_PHY] = { APMU_CSI_CCIC2_CLK_RES_CTRL,
- BIT(29),
- BIT(29),
- 0,
- RST_BASE_TYPE_APMU },
- [RESET_ISP] = { APMU_ISP_CLK_RES_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU },
- [RESET_ISP_AHB] = { APMU_ISP_CLK_RES_CTRL, BIT(3), BIT(3), 0, RST_BASE_TYPE_APMU },
- [RESET_ISP_CI] = { APMU_ISP_CLK_RES_CTRL, BIT(16), BIT(16), 0, RST_BASE_TYPE_APMU },
- [RESET_ISP_CPP] = { APMU_ISP_CLK_RES_CTRL, BIT(27), BIT(27), 0, RST_BASE_TYPE_APMU },
- [RESET_LCD] = { APMU_LCD_CLK_RES_CTRL1, BIT(4), BIT(4), 0, RST_BASE_TYPE_APMU },
- [RESET_DSI_ESC] = { APMU_LCD_CLK_RES_CTRL1, BIT(3), BIT(3), 0, RST_BASE_TYPE_APMU },
- [RESET_V2D] = { APMU_LCD_CLK_RES_CTRL1, BIT(27), BIT(27), 0, RST_BASE_TYPE_APMU },
- [RESET_MIPI] = { APMU_LCD_CLK_RES_CTRL1, BIT(15), BIT(15), 0, RST_BASE_TYPE_APMU },
- [RESET_LCD_SPI] = { APMU_LCD_SPI_CLK_RES_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU },
- [RESET_LCD_SPI_BUS] = { APMU_LCD_SPI_CLK_RES_CTRL,
- BIT(4),
- BIT(4),
- 0,
- RST_BASE_TYPE_APMU },
- [RESET_LCD_SPI_HBUS] = { APMU_LCD_SPI_CLK_RES_CTRL,
- BIT(2),
- BIT(2),
- 0,
- RST_BASE_TYPE_APMU },
- [RESET_LCD_MCLK] = { APMU_LCD_CLK_RES_CTRL2, BIT(9), BIT(9), 0, RST_BASE_TYPE_APMU },
- [RESET_CCIC_4X] = { APMU_CCIC_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU },
- [RESET_CCIC1_PHY] = { APMU_CCIC_CLK_RES_CTRL, BIT(2), BIT(2), 0, RST_BASE_TYPE_APMU },
- [RESET_SDH_AXI] = { APMU_SDH0_CLK_RES_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU },
- [RESET_SDH0] = { APMU_SDH0_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU },
- [RESET_SDH1] = { APMU_SDH1_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU },
- [RESET_USB_AXI] = { APMU_USB_CLK_RES_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU },
- [RESET_USBP1_AXI] = { APMU_USB_CLK_RES_CTRL, BIT(4), BIT(4), 0, RST_BASE_TYPE_APMU },
- [RESET_USB3_0] = { APMU_USB_CLK_RES_CTRL,
- BIT(9) | BIT(10) | BIT(11),
- BIT(9) | BIT(10) | BIT(11),
- 0,
- RST_BASE_TYPE_APMU },
- [RESET_QSPI] = { APMU_QSPI_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU },
- [RESET_QSPI_BUS] = { APMU_QSPI_CLK_RES_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU },
- [RESET_DMA] = { APMU_DMA_CLK_RES_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU },
- [RESET_AES] = { APMU_AES_CLK_RES_CTRL, BIT(4), BIT(4), 0, RST_BASE_TYPE_APMU },
- [RESET_VPU] = { APMU_VPU_CLK_RES_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU },
- [RESET_GPU] = { APMU_GPU_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU },
- [RESET_SDH2] = { APMU_SDH2_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU },
- [RESET_MC] = { APMU_PMUA_MC_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU },
- [RESET_EM_AXI] = { APMU_PMUA_EM_CLK_RES_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU },
- [RESET_EM] = { APMU_PMUA_EM_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU },
- [RESET_AUDIO_SYS] = { APMU_AUDIO_CLK_RES_CTRL,
- BIT(0) | BIT(2) | BIT(3),
- BIT(0) | BIT(2) | BIT(3),
- 0,
- RST_BASE_TYPE_APMU },
- [RESET_HDMI] = { APMU_HDMI_CLK_RES_CTRL, BIT(9), BIT(9), 0, RST_BASE_TYPE_APMU },
- [RESET_PCIE0] = { APMU_PCIE_CLK_RES_CTRL_0,
- BIT(3) | BIT(4) | BIT(5) | BIT(8),
- BIT(3) | BIT(4) | BIT(5),
- BIT(8),
- RST_BASE_TYPE_APMU },
- [RESET_PCIE1] = { APMU_PCIE_CLK_RES_CTRL_1,
- BIT(3) | BIT(4) | BIT(5) | BIT(8),
- BIT(3) | BIT(4) | BIT(5),
- BIT(8),
- RST_BASE_TYPE_APMU },
- [RESET_PCIE2] = { APMU_PCIE_CLK_RES_CTRL_2, 0x138, 0x38, 0x100, RST_BASE_TYPE_APMU },
- [RESET_EMAC0] = { APMU_EMAC0_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU },
- [RESET_EMAC1] = { APMU_EMAC1_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU },
- [RESET_SEC_UART1] = { APBC2_UART1_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC2 },
- [RESET_SEC_SSP2] = { APBC2_SSP2_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC2 },
- [RESET_SEC_TWSI3] = { APBC2_TWSI3_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC2 },
- [RESET_SEC_RTC] = { APBC2_RTC_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC2 },
- [RESET_SEC_TIMERS0] = { APBC2_TIMERS0_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC2 },
- [RESET_SEC_KPC] = { APBC2_KPC_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC2 },
- [RESET_SEC_GPIO] = { APBC2_GPIO_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC2 },
- };
-
-static u32 spacemit_reset_read(struct spacemit_reset *reset, u32 id)
-{
- void __iomem *base;
-
- switch (reset->signals[id].type) {
- case RST_BASE_TYPE_APMU:
- base = reset->io_base.apmu_base;
- break;
- case RST_BASE_TYPE_APBC:
- base = reset->io_base.apbc_base;
- break;
- default:
- base = reset->io_base.apbc_base;
- break;
- }
-
- return readl(base + reset->signals[id].offset);
-}
-
-static void spacemit_reset_write(struct spacemit_reset *reset, u32 value, u32 id)
-{
- void __iomem *base;
-
- switch (reset->signals[id].type) {
- case RST_BASE_TYPE_APMU:
- base = reset->io_base.apmu_base;
- break;
- case RST_BASE_TYPE_APBC:
- base = reset->io_base.apbc_base;
- break;
- default:
- base = reset->io_base.apbc_base;
- break;
- }
-
- writel(value, base + reset->signals[id].offset);
-}
-
-static void spacemit_reset_set(struct reset_ctl *rst, u32 id, bool assert)
-{
- u32 value;
- struct spacemit_reset *reset = dev_get_priv(rst->dev);
-
- value = spacemit_reset_read(reset, id);
-
- if (assert) {
- value &= ~reset->signals[id].mask;
- value |= reset->signals[id].assert_val;
- } else {
- value &= ~reset->signals[id].mask;
- value |= reset->signals[id].deassert_val;
- }
-
- spacemit_reset_write(reset, value, id);
-}
-
-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;
-}
-
-static int spacemit_reset_assert(struct reset_ctl *rst)
-{
- return spacemit_reset_update(rst, true);
-}
-
-static int spacemit_reset_deassert(struct reset_ctl *rst)
-{
- return spacemit_reset_update(rst, false);
-}
-
-static int spacemit_k1_reset_probe(struct udevice *dev)
-{
- struct spacemit_reset *reset = dev_get_priv(dev);
-
- reset->io_base.mpmu_base = (void *)dev_remap_addr_index(dev, 0);
- if (!reset->io_base.mpmu_base) {
- pr_err("failed to map mpmu registers\n");
- goto out;
- }
-
- reset->io_base.apmu_base = (void *)dev_remap_addr_index(dev, 1);
- if (!reset->io_base.apmu_base) {
- pr_err("failed to map apmu registers\n");
- goto out;
- }
-
- reset->io_base.apbc_base = (void *)dev_remap_addr_index(dev, 2);
- if (!reset->io_base.apbc_base) {
- pr_err("failed to map apbc registers\n");
- goto out;
- }
-
- reset->io_base.apbs_base = (void *)dev_remap_addr_index(dev, 3);
- if (!reset->io_base.apbs_base) {
- pr_err("failed to map apbs registers\n");
- goto out;
- }
-
- reset->io_base.ciu_base = (void *)dev_remap_addr_index(dev, 4);
- if (!reset->io_base.ciu_base) {
- pr_err("failed to map ciu registers\n");
- goto out;
- }
-
- reset->io_base.dciu_base = (void *)dev_remap_addr_index(dev, 5);
- if (!reset->io_base.dciu_base) {
- pr_err("failed to map dragon ciu registers\n");
- goto out;
- }
-
- reset->io_base.ddrc_base = (void *)dev_remap_addr_index(dev, 6);
- if (!reset->io_base.ddrc_base) {
- pr_err("failed to map ddrc registers\n");
- goto out;
- }
-
- reset->io_base.apbc2_base = (void *)dev_remap_addr_index(dev, 7);
- if (!reset->io_base.apbc2_base) {
- pr_err("failed to map apbc2 registers\n");
- goto out;
- }
-
- reset->signals = k1_reset_signals;
-
-out:
- return 0;
-}
-
-const struct reset_ops k1_reset_ops = {
- .rst_assert = spacemit_reset_assert,
- .rst_deassert = spacemit_reset_deassert,
-};
-
-static const struct udevice_id k1_reset_ids[] = {
- { .compatible = "spacemit,k1-reset", },
- {},
-};
-
-U_BOOT_DRIVER(k1_reset) = {
- .name = "spacemit,k1-reset",
- .id = UCLASS_RESET,
- .ops = &k1_reset_ops,
- .of_match = k1_reset_ids,
- .probe = spacemit_k1_reset_probe,
- .priv_auto = sizeof(struct spacemit_reset),
-};
--
2.43.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 8/8] dt-bindings: reset: drop spacemit-k1-reset.h
2026-05-10 12:06 [PATCH 0/8] riscv: spacemit: k1: add clock reset drivers, switch to upstream DT Guodong Xu
` (6 preceding siblings ...)
2026-05-10 12:06 ` [PATCH 7/8] reset: spacemit: k1: drop legacy spacemit,k1-reset driver Guodong Xu
@ 2026-05-10 12:06 ` Guodong Xu
2026-05-10 19:44 ` [PATCH 0/8] riscv: spacemit: k1: add clock reset drivers, switch to upstream DT Vincent Legoll
8 siblings, 0 replies; 14+ messages in thread
From: Guodong Xu @ 2026-05-10 12:06 UTC (permalink / raw)
To: u-boot
Cc: Tom Rini, Lukasz Majewski, Patrice Chotard, Patrick Delaunay,
Michal Simek, Quentin Schulz, Yao Zi, Junhui Liu, Peter Korsgaard,
Leo Yu-Chi Liang, Raymond Mao, Gabriel Fernandez, Kever Yang,
Finley Xiao, Rick Chen, Conor Dooley, u-boot-spacemit,
Vincent Legoll, Guodong Xu, Heinrich Schuchardt
After the K1 build switched to dts/upstream/, all reset IDs come from
the kernel's per-syscon namespace in
<dt-bindings/clock/spacemit,k1-syscon.h>. Remove the legacy U-Boot-only
reset binding header.
Signed-off-by: Guodong Xu <guodong@riscstar.com>
---
include/dt-bindings/reset/spacemit-k1-reset.h | 118 --------------------------
1 file changed, 118 deletions(-)
diff --git a/include/dt-bindings/reset/spacemit-k1-reset.h b/include/dt-bindings/reset/spacemit-k1-reset.h
deleted file mode 100644
index 74db58b27ef..00000000000
--- a/include/dt-bindings/reset/spacemit-k1-reset.h
+++ /dev/null
@@ -1,118 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (C) 2022 Spacemit Inc.
- * Copyright (C) 2025 Huan Zhou <pericycle.cc@gmail.com>
- */
-
-#ifndef __DT_BINDINGS_RESET_SAPCEMIT_K1_H__
-#define __DT_BINDINGS_RESET_SAPCEMIT_K1_H__
-/* APBC */
-#define RESET_UART1 1
-#define RESET_UART2 2
-#define RESET_GPIO 3
-#define RESET_PWM0 4
-#define RESET_PWM1 5
-#define RESET_PWM2 6
-#define RESET_PWM3 7
-#define RESET_PWM4 8
-#define RESET_PWM5 9
-#define RESET_PWM6 10
-#define RESET_PWM7 11
-#define RESET_PWM8 12
-#define RESET_PWM9 13
-#define RESET_PWM10 14
-#define RESET_PWM11 15
-#define RESET_PWM12 16
-#define RESET_PWM13 17
-#define RESET_PWM14 18
-#define RESET_PWM15 19
-#define RESET_PWM16 20
-#define RESET_PWM17 21
-#define RESET_PWM18 22
-#define RESET_PWM19 23
-#define RESET_SSP3 24
-#define RESET_UART3 25
-#define RESET_RTC 26
-#define RESET_TWSI0 27
-#define RESET_TIMERS1 28
-#define RESET_AIB 29
-#define RESET_TIMERS2 30
-#define RESET_ONEWIRE 31
-#define RESET_SSPA0 32
-#define RESET_SSPA1 33
-#define RESET_DRO 34
-#define RESET_IR 35
-#define RESET_TWSI1 36
-#define RESET_TSEN 37
-#define RESET_TWSI2 38
-#define RESET_TWSI4 39
-#define RESET_TWSI5 40
-#define RESET_TWSI6 41
-#define RESET_TWSI7 42
-#define RESET_TWSI8 43
-#define RESET_IPC_AP2AUD 44
-#define RESET_UART4 45
-#define RESET_UART5 46
-#define RESET_UART6 47
-#define RESET_UART7 48
-#define RESET_UART8 49
-#define RESET_UART9 50
-#define RESET_CAN0 51
-
-/* MPMU */
-#define RESET_WDT 52
-
-/* APMU */
-#define RESET_JPG 53
-#define RESET_CSI 54
-#define RESET_CCIC2_PHY 55
-#define RESET_CCIC3_PHY 56
-#define RESET_ISP 57
-#define RESET_ISP_AHB 58
-#define RESET_ISP_CI 59
-#define RESET_ISP_CPP 60
-#define RESET_LCD 61
-#define RESET_DSI_ESC 62
-#define RESET_V2D 63
-#define RESET_MIPI 64
-#define RESET_LCD_SPI 65
-#define RESET_LCD_SPI_BUS 66
-#define RESET_LCD_SPI_HBUS 67
-#define RESET_LCD_MCLK 68
-#define RESET_CCIC_4X 69
-#define RESET_CCIC1_PHY 70
-#define RESET_SDH_AXI 71
-#define RESET_SDH0 72
-#define RESET_SDH1 73
-#define RESET_USB_AXI 74
-#define RESET_USBP1_AXI 75
-#define RESET_USB3_0 76
-#define RESET_QSPI 77
-#define RESET_QSPI_BUS 78
-#define RESET_DMA 79
-#define RESET_AES 80
-#define RESET_VPU 81
-#define RESET_GPU 82
-#define RESET_SDH2 83
-#define RESET_MC 84
-#define RESET_EM_AXI 85
-#define RESET_EM 86
-#define RESET_AUDIO_SYS 87
-#define RESET_HDMI 88
-#define RESET_PCIE0 89
-#define RESET_PCIE1 90
-#define RESET_PCIE2 91
-#define RESET_EMAC0 92
-#define RESET_EMAC1 93
-
-/* APBC2 */
-#define RESET_SEC_UART1 94
-#define RESET_SEC_SSP2 95
-#define RESET_SEC_TWSI3 96
-#define RESET_SEC_RTC 97
-#define RESET_SEC_TIMERS0 98
-#define RESET_SEC_KPC 99
-#define RESET_SEC_GPIO 100
-#define RESET_NUMBER 101
-
-#endif
--
2.43.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH 0/8] riscv: spacemit: k1: add clock reset drivers, switch to upstream DT
2026-05-10 12:06 [PATCH 0/8] riscv: spacemit: k1: add clock reset drivers, switch to upstream DT Guodong Xu
` (7 preceding siblings ...)
2026-05-10 12:06 ` [PATCH 8/8] dt-bindings: reset: drop spacemit-k1-reset.h Guodong Xu
@ 2026-05-10 19:44 ` Vincent Legoll
2026-05-11 4:52 ` Yao Zi
8 siblings, 1 reply; 14+ messages in thread
From: Vincent Legoll @ 2026-05-10 19:44 UTC (permalink / raw)
To: Guodong Xu, u-boot
Cc: Tom Rini, Lukasz Majewski, Patrice Chotard, Patrick Delaunay,
Michal Simek, Quentin Schulz, Yao Zi, Junhui Liu, Peter Korsgaard,
Leo Yu-Chi Liang, Raymond Mao, Gabriel Fernandez, Kever Yang,
Finley Xiao, Rick Chen, Conor Dooley, u-boot-spacemit,
Heinrich Schuchardt
Hello Guodong Xu,
On 5/10/26 14:06, Guodong Xu wrote:
> Currently U-Boot's SpacemiT K1 ships its own arch/riscv/dts/k1.dtsi and a
> spacemit,k1-reset binding that has no node in the upstream
> (kernel-mainline) K1 dts. After list discussion [1], this series
> moves U-Boot to the upstream DT before further K1 work lands.
>
> In the upstream DT, each K1 syscon provides both clocks and resets.
> The kernel's clock driver spawns the reset child via the auxiliary
> bus. This patchset does the same in U-Boot: each clock driver
> spawns a UCLASS_RESET sibling on the same ofnode.
>
> Patch 1/8 adds the K1 clock driver.
> Patch 2/8 adds a new syscon-bound reset driver with no DT of_match. At this
> point, the legacy reset driver and local dts are still there.
> Patch 3/8 has each per-syscon clock driver spawn the reset child on the
> same ofnode, the way the kernel uses auxiliary devices.
> Patch 4/8 enables the clock driver.
> Patch 5/8 switches BPI-F3 to dts/upstream/.
> Patch 6/8, 7/8 and 8/8 clean up the legacy reset driver and local dts files.
>
> Old and new reset drivers coexist from 2/8 through 6/8 so the series
> is bisectable.
>
> The K1 SPL bring-up [2] and PIN/SPI [3] series will be rebased on
> this and resent once it lands.
>
> Link: https://lore.kernel.org/u-boot/20260507140558.GU1614990@bill-the-cat/ [1]
> Link: https://lore.kernel.org/u-boot/20260325223232.1553212-1-raymondmaoca@gmail.com/ [2]
> Link: https://lore.kernel.org/u-boot/20260422143112.1329478-1-raymondmaoca@gmail.com/ [3]
>
> [...]
>
> ---
> base-commit: 24db98cdf911b6ca362209e674bf9412441c1095
> change-id: 20260510-b4-k1-clk-reset-upstream-dts-cbf1f3a79cfb
I tried to apply this locally but failed:
$ git log --oneline -1
24db98cdf91 (HEAD -> test) Merge tag 'u-boot-imx-next-20260318' of
https://gitlab.denx.de/u-boot/custodians/u-boot-imx into next
$ git status
On branch test
nothing to commit, working tree clean
$ wget
https://lore.kernel.org/u-boot/20260510-b4-k1-clk-reset-upstream-dts-v1-0-db0b0503ee44@riscstar.com/t.mbox.gz
\
-O ~/Downloads/PATCH-0-8-riscv-spacemit-k1-add-clock-reset-drivers-switch-to-upstream-DT.mbox.gz
$ gzip -dc
~/Downloads/PATCH-0-8-riscv-spacemit-k1-add-clock-reset-drivers-switch-to-upstream-DT.mbox.gz
| git am
Applying: riscv: spacemit: k1: add clock reset drivers, switch to
upstream DT
error: No valid patches in input (allow with "--allow-empty")
Patch failed at 0001 riscv: spacemit: k1: add clock reset drivers,
switch to upstream DT
hint: Use 'git am --show-current-patch=diff' to see the failed patch
hint: When you have resolved this problem, run "git am --continue".
hint: If you prefer to skip this patch, run "git am --skip" instead.
hint: To restore the original branch and stop patching, run "git am
--abort".
hint: Disable this message with "git config set advice.mergeConflict false"
I had a similar failure with the mbox downloaded with:
$ b4 mbox
https://lore.kernel.org/u-boot/20260510-b4-k1-clk-reset-upstream-dts-v1-0-db0b0503ee44@riscstar.com/T/#t
I also tried to apply to master branch without success
Is there something I'm doing wrong ?
Regards
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 0/8] riscv: spacemit: k1: add clock reset drivers, switch to upstream DT
2026-05-10 19:44 ` [PATCH 0/8] riscv: spacemit: k1: add clock reset drivers, switch to upstream DT Vincent Legoll
@ 2026-05-11 4:52 ` Yao Zi
2026-05-11 6:51 ` Vincent Legoll
0 siblings, 1 reply; 14+ messages in thread
From: Yao Zi @ 2026-05-11 4:52 UTC (permalink / raw)
To: Vincent Legoll, Guodong Xu, u-boot
Cc: Tom Rini, Lukasz Majewski, Patrice Chotard, Patrick Delaunay,
Michal Simek, Quentin Schulz, Junhui Liu, Peter Korsgaard,
Leo Yu-Chi Liang, Raymond Mao, Gabriel Fernandez, Kever Yang,
Finley Xiao, Rick Chen, Conor Dooley, u-boot-spacemit,
Heinrich Schuchardt
On Sun, May 10, 2026 at 09:44:14PM +0200, Vincent Legoll wrote:
> Hello Guodong Xu,
>
> On 5/10/26 14:06, Guodong Xu wrote:
> > Currently U-Boot's SpacemiT K1 ships its own arch/riscv/dts/k1.dtsi and a
> > spacemit,k1-reset binding that has no node in the upstream
> > (kernel-mainline) K1 dts. After list discussion [1], this series
> > moves U-Boot to the upstream DT before further K1 work lands.
> >
> > In the upstream DT, each K1 syscon provides both clocks and resets.
> > The kernel's clock driver spawns the reset child via the auxiliary
> > bus. This patchset does the same in U-Boot: each clock driver
> > spawns a UCLASS_RESET sibling on the same ofnode.
> >
> > Patch 1/8 adds the K1 clock driver.
> > Patch 2/8 adds a new syscon-bound reset driver with no DT of_match. At this
> > point, the legacy reset driver and local dts are still there.
> > Patch 3/8 has each per-syscon clock driver spawn the reset child on the
> > same ofnode, the way the kernel uses auxiliary devices.
> > Patch 4/8 enables the clock driver.
> > Patch 5/8 switches BPI-F3 to dts/upstream/.
> > Patch 6/8, 7/8 and 8/8 clean up the legacy reset driver and local dts files.
> >
> > Old and new reset drivers coexist from 2/8 through 6/8 so the series
> > is bisectable.
> >
> > The K1 SPL bring-up [2] and PIN/SPI [3] series will be rebased on
> > this and resent once it lands.
> >
> > Link: https://lore.kernel.org/u-boot/20260507140558.GU1614990@bill-the-cat/ [1]
> > Link: https://lore.kernel.org/u-boot/20260325223232.1553212-1-raymondmaoca@gmail.com/ [2]
> > Link: https://lore.kernel.org/u-boot/20260422143112.1329478-1-raymondmaoca@gmail.com/ [3]
> >
> > [...]
> >
> > ---
> > base-commit: 24db98cdf911b6ca362209e674bf9412441c1095
> > change-id: 20260510-b4-k1-clk-reset-upstream-dts-cbf1f3a79cfb
>
>
> I tried to apply this locally but failed:
>
> $ git log --oneline -1
> 24db98cdf91 (HEAD -> test) Merge tag 'u-boot-imx-next-20260318' of
> https://gitlab.denx.de/u-boot/custodians/u-boot-imx into next
>
> $ git status
> On branch test
> nothing to commit, working tree clean
>
> $ wget https://lore.kernel.org/u-boot/20260510-b4-k1-clk-reset-upstream-dts-v1-0-db0b0503ee44@riscstar.com/t.mbox.gz
> \
>
> -O ~/Downloads/PATCH-0-8-riscv-spacemit-k1-add-clock-reset-drivers-switch-to-upstream-DT.mbox.gz
>
>
> $ gzip -dc ~/Downloads/PATCH-0-8-riscv-spacemit-k1-add-clock-reset-drivers-switch-to-upstream-DT.mbox.gz
> | git am
> Applying: riscv: spacemit: k1: add clock reset drivers, switch to upstream
> DT
> error: No valid patches in input (allow with "--allow-empty")
> Patch failed at 0001 riscv: spacemit: k1: add clock reset drivers, switch to
> upstream DT
> hint: Use 'git am --show-current-patch=diff' to see the failed patch
> hint: When you have resolved this problem, run "git am --continue".
> hint: If you prefer to skip this patch, run "git am --skip" instead.
> hint: To restore the original branch and stop patching, run "git am
> --abort".
> hint: Disable this message with "git config set advice.mergeConflict false"
>
> I had a similar failure with the mbox downloaded with:
Because the first mail in the mbox file is the cover letter, not a real
patch, thus contains no code changes and couldn't be applied by default.
Try
b4 shazam 20260510-b4-k1-clk-reset-upstream-dts-v1-0-db0b0503ee44@riscstar.com
instead, which applies the series cleanly at least on my side. With
git am you might skip application of the first mail manually by
git am --skip
and continue with rest of the series.
> $ b4 mbox https://lore.kernel.org/u-boot/20260510-b4-k1-clk-reset-upstream-dts-v1-0-db0b0503ee44@riscstar.com/T/#t
>
>
> I also tried to apply to master branch without success
>
> Is there something I'm doing wrong ?
>
> Regards
>
Regards,
Yao Zi
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 0/8] riscv: spacemit: k1: add clock reset drivers, switch to upstream DT
2026-05-11 4:52 ` Yao Zi
@ 2026-05-11 6:51 ` Vincent Legoll
0 siblings, 0 replies; 14+ messages in thread
From: Vincent Legoll @ 2026-05-11 6:51 UTC (permalink / raw)
To: Yao Zi, Guodong Xu, u-boot
Cc: Tom Rini, Lukasz Majewski, Patrice Chotard, Patrick Delaunay,
Michal Simek, Quentin Schulz, Junhui Liu, Peter Korsgaard,
Leo Yu-Chi Liang, Raymond Mao, Gabriel Fernandez, Kever Yang,
Finley Xiao, Rick Chen, Conor Dooley, u-boot-spacemit,
Heinrich Schuchardt
Hello,
I was sure it was something silly...
On 5/11/26 06:52, Yao Zi wrote:
> b4 shazam20260510-b4-k1-clk-reset-upstream-dts-v1-0-db0b0503ee44@riscstar.com
That's my first use of b4 tool, so not really up to speed with it,
thanks for the right incantation, this works.
I'll report my testing, this evening (CET).
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 1/8] clk: spacemit: Add support for K1 SoC
2026-05-10 12:06 ` [PATCH 1/8] clk: spacemit: Add support for K1 SoC Guodong Xu
@ 2026-05-22 16:09 ` Yao Zi
2026-05-23 13:11 ` Guodong Xu
0 siblings, 1 reply; 14+ messages in thread
From: Yao Zi @ 2026-05-22 16:09 UTC (permalink / raw)
To: Guodong Xu, u-boot
Cc: Tom Rini, Lukasz Majewski, Patrice Chotard, Patrick Delaunay,
Michal Simek, Quentin Schulz, Junhui Liu, Peter Korsgaard,
Leo Yu-Chi Liang, Raymond Mao, Gabriel Fernandez, Kever Yang,
Finley Xiao, Rick Chen, Conor Dooley, u-boot-spacemit,
Vincent Legoll, Heinrich Schuchardt
On Sun, May 10, 2026 at 08:06:23AM -0400, Guodong Xu wrote:
> From: Junhui Liu <junhui.liu@pigmoral.tech>
>
> The K1 SoC exposes four clock providers in the kernel mainline DT: one
> PLL controller ("spacemit,k1-pll") and three syscon clock nodes
> ("spacemit,k1-syscon-{mpmu,apbc,apmu}"). Register a separate
> U_BOOT_DRIVER for each.
>
> Inter-controller ordering is enforced where the registers actually
> depend on each other.
What do you mean by "registers actually depend on each other"? Do you
refer to the fact that some APBC clocks are derived from APMU/PLL
controllers thus must be registered after them? If so, would this
series[1] help which allows arbitrary clock registration order and
handles dependencies in CCF instead?
> Signed-off-by: Junhui Liu <junhui.liu@pigmoral.tech>
> Signed-off-by: Raymond Mao <raymond.mao@riscstar.com>
> Signed-off-by: Guodong Xu <guodong@riscstar.com>
> ---
> drivers/clk/Kconfig | 5 +-
> drivers/clk/Makefile | 1 +
> drivers/clk/spacemit/Kconfig | 23 +
> drivers/clk/spacemit/Makefile | 7 +
> drivers/clk/spacemit/clk-k1.c | 1722 +++++++++++++++++++++++++++++++++++++
> 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, 2995 insertions(+), 2 deletions(-)
...
> diff --git a/drivers/clk/spacemit/Kconfig b/drivers/clk/spacemit/Kconfig
> new file mode 100644
> index 00000000000..03aecefddc4
> --- /dev/null
> +++ b/drivers/clk/spacemit/Kconfig
> @@ -0,0 +1,23 @@
> +# 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
What about
depends on CLK || COMPILE_TEST
to allow building-only tests?
> + 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
> + select LIB_RATIONAL
CLK_SPACEMIT instead of CLK_SPACEMIT_K1 should selects LIB_RATIONAL...
> + help
> + This enables support clock driver for Spacemit K1 SoC.
> + It's based on Common Clock Framework.
> +
> +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
... since the driver actually makes use of rational routines, clk_ddn.o,
is guarded by CONFIG_CLK_SPACEMIT, not CONFIG_CLK_SPACEMIT_K1.
> +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..4c0972d952e
> --- /dev/null
> +++ b/drivers/clk/spacemit/clk-k1.c
...
> +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;
> +}
Is retrying for handling dependencies between clocks? Could the series
I mentioned above help? This version looks very hacking...
Another solution might be carefully specify the order in which clocks
are registered to ensure parents are always registered before children.
...
> 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
...
> +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);
Rational routines are used here.
> + return ccu_ddn_calc_rate(prate, *num, *den, ddn->pre_div);
> +}
Best regards,
Yao Zi
[1]: https://lore.kernel.org/u-boot/20260120-clk-reparent-v3-0-0d43d4b362ac@outlook.com/
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 1/8] clk: spacemit: Add support for K1 SoC
2026-05-22 16:09 ` Yao Zi
@ 2026-05-23 13:11 ` Guodong Xu
0 siblings, 0 replies; 14+ messages in thread
From: Guodong Xu @ 2026-05-23 13:11 UTC (permalink / raw)
To: Yao Zi
Cc: u-boot, Tom Rini, Lukasz Majewski, Patrice Chotard,
Patrick Delaunay, Michal Simek, Quentin Schulz, Junhui Liu,
Peter Korsgaard, Leo Yu-Chi Liang, Raymond Mao, Gabriel Fernandez,
Kever Yang, Finley Xiao, Rick Chen, Conor Dooley, u-boot-spacemit,
Vincent Legoll, Heinrich Schuchardt
Hi, Yao Zi
On Sat, May 23, 2026 at 12:10 AM Yao Zi <me@ziyao.cc> wrote:
>
> On Sun, May 10, 2026 at 08:06:23AM -0400, Guodong Xu wrote:
> > From: Junhui Liu <junhui.liu@pigmoral.tech>
> >
> > The K1 SoC exposes four clock providers in the kernel mainline DT: one
> > PLL controller ("spacemit,k1-pll") and three syscon clock nodes
> > ("spacemit,k1-syscon-{mpmu,apbc,apmu}"). Register a separate
> > U_BOOT_DRIVER for each.
> >
> > Inter-controller ordering is enforced where the registers actually
> > depend on each other.
>
> What do you mean by "registers actually depend on each other"? Do you
> refer to the fact that some APBC clocks are derived from APMU/PLL
> controllers thus must be registered after them? If so, would this
Yes, exactly. I can change the wording in next version. But yes,
I mean that dependency in K1's PLL controller and syscon nodes:
MPMU <- PLL
APMU <- PLL + MPMU
APBC <- PLL + MPMU + APMU
> series[1] help which allows arbitrary clock registration order and
> handles dependencies in CCF instead?
I have concerns. This series [1] doesn't allow xPL useage. As the author
stated in his cover letter "This feature is disabled for xPLs by default..
no clean way to enable it for xPL". And SPL registration is exactly what
K1 needs. Also, Tom Rini reported a boot failure on TI board in that
thread, still unresolved.
I will keep an eye on it, but at this moment, I don't think it is the right
solution for my case.
>
> > Signed-off-by: Junhui Liu <junhui.liu@pigmoral.tech>
> > Signed-off-by: Raymond Mao <raymond.mao@riscstar.com>
> > Signed-off-by: Guodong Xu <guodong@riscstar.com>
> > ---
> > drivers/clk/Kconfig | 5 +-
> > drivers/clk/Makefile | 1 +
> > drivers/clk/spacemit/Kconfig | 23 +
> > drivers/clk/spacemit/Makefile | 7 +
> > drivers/clk/spacemit/clk-k1.c | 1722 +++++++++++++++++++++++++++++++++++++
> > 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, 2995 insertions(+), 2 deletions(-)
>
> ...
>
> > diff --git a/drivers/clk/spacemit/Kconfig b/drivers/clk/spacemit/Kconfig
> > new file mode 100644
> > index 00000000000..03aecefddc4
> > --- /dev/null
> > +++ b/drivers/clk/spacemit/Kconfig
> > @@ -0,0 +1,23 @@
> > +# 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
>
> What about
>
> depends on CLK || COMPILE_TEST
>
> to allow building-only tests?
Yes, agree. Will add that.
>
> > + 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
> > + select LIB_RATIONAL
>
> CLK_SPACEMIT instead of CLK_SPACEMIT_K1 should selects LIB_RATIONAL...
>
Agree. I will fix that.
> > + help
> > + This enables support clock driver for Spacemit K1 SoC.
> > + It's based on Common Clock Framework.
> > +
> > +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
>
> ... since the driver actually makes use of rational routines, clk_ddn.o,
> is guarded by CONFIG_CLK_SPACEMIT, not CONFIG_CLK_SPACEMIT_K1.
>
> > +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..4c0972d952e
> > --- /dev/null
> > +++ b/drivers/clk/spacemit/clk-k1.c
>
> ...
>
> > +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;
> > +}
>
> Is retrying for handling dependencies between clocks? Could the series
> I mentioned above help? This version looks very hacking...
>
> Another solution might be carefully specify the order in which clocks
> are registered to ensure parents are always registered before children.
>
Agreed that explicit ordering is the right idea.
To keep the order, I will do it at controller side via force-probe, letting
the dependent controller (eg. APBC)'s own .probe function forces its parent
controller (eg. PLL) to probe, by calling
uclass_get_device_by_driver(..,DM_DRIVER_GET(k1_pll_clk),..).
This way also removes the clk_get_by_index(4/5/6) magic-index.
BR,
Guodong Xu
> ...
>
> > 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
>
> ...
>
> > +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);
>
> Rational routines are used here.
>
> > + return ccu_ddn_calc_rate(prate, *num, *den, ddn->pre_div);
> > +}
>
> Best regards,
> Yao Zi
>
> [1]: https://lore.kernel.org/u-boot/20260120-clk-reparent-v3-0-0d43d4b362ac@outlook.com/
^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2026-05-23 13:12 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-10 12:06 [PATCH 0/8] riscv: spacemit: k1: add clock reset drivers, switch to upstream DT Guodong Xu
2026-05-10 12:06 ` [PATCH 1/8] clk: spacemit: Add support for K1 SoC Guodong Xu
2026-05-22 16:09 ` Yao Zi
2026-05-23 13:11 ` Guodong Xu
2026-05-10 12:06 ` [PATCH 2/8] reset: spacemit: k1: introduce syscon-bound reset driver Guodong Xu
2026-05-10 12:06 ` [PATCH 3/8] clk: spacemit: k1: spawn reset device from per-syscon clock drivers Guodong Xu
2026-05-10 12:06 ` [PATCH 4/8] configs: bananapi-f3: enable Spacemit K1 clock driver Guodong Xu
2026-05-10 12:06 ` [PATCH 5/8] dts: k1: switch BPI-F3 build to upstream DT Guodong Xu
2026-05-10 12:06 ` [PATCH 6/8] dts: k1: drop legacy local DT files Guodong Xu
2026-05-10 12:06 ` [PATCH 7/8] reset: spacemit: k1: drop legacy spacemit,k1-reset driver Guodong Xu
2026-05-10 12:06 ` [PATCH 8/8] dt-bindings: reset: drop spacemit-k1-reset.h Guodong Xu
2026-05-10 19:44 ` [PATCH 0/8] riscv: spacemit: k1: add clock reset drivers, switch to upstream DT Vincent Legoll
2026-05-11 4:52 ` Yao Zi
2026-05-11 6:51 ` Vincent Legoll
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.