[PATCH v4 04/14] clk: spacemit: k1: prune SPL clock tree
Guodong Xu
guodong at riscstar.com
Tue May 19 12:26:22 CEST 2026
K1 SPL runs from on-chip SRAM with a small pre-relocation malloc heap.
Registering the full K1 clock tree would not fit, so split the tree on
CONFIG_SPL_BUILD: the SPL build registers only the subset SPL needs
(currently UART, SDHCI, I2C (TWSI), and their PLL/MPMU/APMU/APBC
ancestors); the non-SPL build keeps the full tree.
Where surviving SPL CCU definitions reference parent clocks outside
that subset, use "clock-dummy", so framework parent lookups still resolve.
Signed-off-by: Guodong Xu <guodong at riscstar.com>
---
v4:
- New patch. Prune SPL clock tree to the UART/SDHCI/I2C subset.
---
drivers/clk/spacemit/clk-k1.c | 128 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 128 insertions(+)
diff --git a/drivers/clk/spacemit/clk-k1.c b/drivers/clk/spacemit/clk-k1.c
index 80eede251b8..6695c4379e1 100644
--- a/drivers/clk/spacemit/clk-k1.c
+++ b/drivers/clk/spacemit/clk-k1.c
@@ -44,6 +44,18 @@ static const struct ccu_pll_rate_tbl pll1_rate_tbl[] = {
CCU_PLL_RATE(2457600000UL, 0x0050dd64, 0x330ccccd),
};
+#if IS_ENABLED(CONFIG_SPL_BUILD)
+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_FACTOR_GATE_DEFINE(CLK_PLL1_D4, pll1_d4, pll1_d4, "pll1", APBS_PLL1_SWCR2,
+ BIT(3), 4, 1);
+CCU_FACTOR_GATE_DEFINE(CLK_PLL1_D6, pll1_d6, pll1_d6, "pll1", APBS_PLL1_SWCR2,
+ BIT(5), 6, 1);
+CCU_FACTOR_GATE_FLAGS_DEFINE(CLK_PLL1_D8, pll1_d8, pll1_d8, "pll1",
+ APBS_PLL1_SWCR2, BIT(7), 8, 1, CLK_IS_CRITICAL);
+#else
static const struct ccu_pll_rate_tbl pll2_rate_tbl[] = {
CCU_PLL_RATE(3000000000UL, 0x0050dd66, 0x3fe00000),
};
@@ -131,9 +143,23 @@ CCU_FACTOR_GATE_DEFINE(CLK_PLL3_D8, pll3_d8, pll3_d8, "pll3", APBS_PLL3_SWCR2,
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);
+#endif
/* APBS clocks end */
/* MPMU clocks start */
+#if IS_ENABLED(CONFIG_SPL_BUILD)
+CCU_GATE_DEFINE(CLK_PLL1_614, pll1_d4_614p4, pll1_d4_614p4, "pll1_d4",
+ MPMU_ACGR, BIT(15), 0);
+CCU_GATE_DEFINE(CLK_PLL1_409P6, pll1_d6_409p6, pll1_d6_409p6, "pll1_d6",
+ MPMU_ACGR, BIT(0), 0);
+CCU_GATE_DEFINE(CLK_PLL1_307P2, pll1_d8_307p2, pll1_d8_307p2, "pll1_d8",
+ MPMU_ACGR, BIT(13), 0);
+CCU_FACTOR_GATE_DEFINE(CLK_PLL1_31P5, pll1_d78_31p5, pll1_d78_31p5,
+ "pll1_d4", MPMU_ACGR, BIT(6), 39, 2);
+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);
+#else
CCU_GATE_DEFINE(CLK_PLL1_307P2, pll1_d8_307p2, pll1_d8_307p2, "pll1_d8",
MPMU_ACGR, BIT(13), 0);
@@ -251,9 +277,37 @@ CCU_GATE_DEFINE(CLK_WDT_BUS, wdt_bus_clk, wdt_bus_clk, "apb_clk", MPMU_WDTPCR,
BIT(0), 0);
CCU_GATE_DEFINE(CLK_RIPC, ripc_clk, ripc_clk, "apb_clk", MPMU_RIPCCR, 0x1, 0);
+#endif
/* MPMU clocks end */
/* APBC clocks start */
+#if IS_ENABLED(CONFIG_SPL_BUILD)
+static const char * const uart_clk_parents[] = {
+ "clock-dummy",
+ "clock-dummy",
+ "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",
+};
+
+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);
+
+#else
static const char * const uart_clk_parents[] = {
"pll1_m3d128_57p6",
"slow_uart1_14p74",
@@ -598,9 +652,44 @@ CCU_GATE_DEFINE(CLK_TSEN_BUS, tsen_bus_clk, tsen_bus_clk, "apb_clk",
CCU_GATE_DEFINE(CLK_IPC_AP2AUD_BUS, ipc_ap2aud_bus_clk, ipc_ap2aud_bus_clk,
"apb_clk", APBC_IPC_AP2AUD_CLK_RST, BIT(0), 0);
+#endif
/* APBC clocks end */
/* APMU clocks start */
+#if IS_ENABLED(CONFIG_SPL_BUILD)
+static const char * const pmua_aclk_parents[] = {
+ "clock-dummy",
+ "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);
+
+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",
+};
+
+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);
+
+static const char * const sdh2_parents[] = {
+ "pll1_d6_409p6",
+};
+
+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);
+#else
static const char * const pmua_aclk_parents[] = {
"pll1_d10_245p76",
"pll1_d8_307p2",
@@ -1082,8 +1171,17 @@ CCU_GATE_DEFINE(CLK_EMAC1_BUS, emac1_bus_clk, emac1_bus_clk, "pmua_aclk",
CCU_GATE_DEFINE(CLK_EMAC1_PTP, emac1_ptp_clk, emac1_ptp_clk, "pll2_d6",
APMU_EMAC1_CLK_RES_CTRL, BIT(15), 0);
+#endif
/* APMU clocks end */
+#if IS_ENABLED(CONFIG_SPL_BUILD)
+static struct clk *k1_ccu_pll_clks[] = {
+ &pll1.common.clk,
+ &pll1_d4.common.clk,
+ &pll1_d6.common.clk,
+ &pll1_d8.common.clk,
+};
+#else
static struct clk *k1_ccu_pll_clks[] = {
&pll1.common.clk,
&pll2.common.clk,
@@ -1121,6 +1219,7 @@ static struct clk *k1_ccu_pll_clks[] = {
&pll3_40.common.clk,
&pll3_20.common.clk,
};
+#endif
static const struct spacemit_ccu_data k1_ccu_pll_data = {
.clks = k1_ccu_pll_clks,
@@ -1128,6 +1227,15 @@ static const struct spacemit_ccu_data k1_ccu_pll_data = {
.offset = K1_PLL_ID,
};
+#if IS_ENABLED(CONFIG_SPL_BUILD)
+static struct clk *k1_ccu_mpmu_clks[] = {
+ &pll1_d4_614p4.common.clk,
+ &pll1_d6_409p6.common.clk,
+ &pll1_d8_307p2.common.clk,
+ &pll1_d78_31p5.common.clk,
+ &slow_uart2_48.common.clk,
+};
+#else
static struct clk *k1_ccu_mpmu_clks[] = {
&pll1_d8_307p2.common.clk,
&pll1_d32_76p8.common.clk,
@@ -1167,6 +1275,7 @@ static struct clk *k1_ccu_mpmu_clks[] = {
&i2s_bclk.common.clk,
&wdt_bus_clk.common.clk,
};
+#endif
static const struct spacemit_ccu_data k1_ccu_mpmu_data = {
.clks = k1_ccu_mpmu_clks,
@@ -1174,6 +1283,13 @@ static const struct spacemit_ccu_data k1_ccu_mpmu_data = {
.offset = K1_MPMU_ID,
};
+#if IS_ENABLED(CONFIG_SPL_BUILD)
+static struct clk *k1_ccu_apbc_clks[] = {
+ &uart0_clk.common.clk,
+ &twsi2_clk.common.clk,
+ &twsi8_clk.common.clk,
+};
+#else
static struct clk *k1_ccu_apbc_clks[] = {
&uart0_clk.common.clk,
&uart2_clk.common.clk,
@@ -1278,6 +1394,7 @@ static struct clk *k1_ccu_apbc_clks[] = {
&sspa0_i2s_bclk.common.clk,
&sspa1_i2s_bclk.common.clk,
};
+#endif
static const struct spacemit_ccu_data k1_ccu_apbc_data = {
.clks = k1_ccu_apbc_clks,
@@ -1285,6 +1402,14 @@ static const struct spacemit_ccu_data k1_ccu_apbc_data = {
.offset = K1_APBC_ID,
};
+#if IS_ENABLED(CONFIG_SPL_BUILD)
+static struct clk *k1_ccu_apmu_clks[] = {
+ &pmua_aclk.common.clk,
+ &sdh_axi_aclk.common.clk,
+ &sdh0_clk.common.clk,
+ &sdh2_clk.common.clk,
+};
+#else
static struct clk *k1_ccu_apmu_clks[] = {
&cci550_clk.common.clk,
&cpu_c0_hi_clk.common.clk,
@@ -1349,6 +1474,7 @@ static struct clk *k1_ccu_apmu_clks[] = {
&v2d_clk.common.clk,
&emmc_bus_clk.common.clk,
};
+#endif
static int clk_k1_enable(struct clk *clk)
{
@@ -1486,6 +1612,8 @@ static int k1_pll_clk_probe(struct udevice *dev)
const struct spacemit_ccu_data *data;
int ret;
+ clk_register_fixed_rate(NULL, "clock-dummy", 0);
+
ret = regmap_init_mem(dev_ofnode(dev), &base_regmap);
if (ret)
return ret;
--
2.43.0
More information about the U-Boot
mailing list