From 7a588b62679c51abd08171d31df6e44589f0097d Mon Sep 17 00:00:00 2001 From: Yixun Lan Date: Tue, 30 Jun 2026 12:52:45 +0000 Subject: [PATCH 1/6] clk: spacemit: k3: fix parent clock of UFS aclk According to SpacemiT updated clock docs, the previous UFS aclk parent clock was wrong, the correct one is illustrated below, so fix it. --> pll1_d5_491p52 --\ --> pll1_d6_409p6 --| --> pll2_d6 --|--> div --> gate --> ufs_aclk --> pll2_d5 --/ Fixes: e371a77255b8 ("clk: spacemit: k3: add the clock tree") Link: https://patch.msgid.link/20260630-06-clk-ufs-support-v1-1-cf7521d1d0fe@kernel.org Signed-off-by: Yixun Lan --- drivers/clk/spacemit/ccu-k3.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/clk/spacemit/ccu-k3.c b/drivers/clk/spacemit/ccu-k3.c index cb0c4277f72a..42293a38b098 100644 --- a/drivers/clk/spacemit/ccu-k3.c +++ b/drivers/clk/spacemit/ccu-k3.c @@ -926,11 +926,10 @@ CCU_MUX_DIV_GATE_FC_DEFINE(dpu_aclk, dpu_aclk_parents, APMU_LCD_CLK_RES_CTRL5, 1 20, 3, BIT(16), 0); static const struct clk_parent_data ufs_aclk_parents[] = { - CCU_PARENT_HW(pll1_d6_409p6), CCU_PARENT_HW(pll1_d5_491p52), - CCU_PARENT_HW(pll1_d4_614p4), - CCU_PARENT_HW(pll1_d8_307p2), - CCU_PARENT_HW(pll2_d4), + CCU_PARENT_HW(pll1_d6_409p6), + CCU_PARENT_HW(pll2_d6), + CCU_PARENT_HW(pll2_d5), }; CCU_MUX_DIV_GATE_FC_DEFINE(ufs_aclk, ufs_aclk_parents, APMU_UFS_CLK_RES_CTRL, 5, 3, BIT(8), 2, 3, BIT(1), 0); From 4fc567e1bacdb5da85628de8dd1d1e3328060798 Mon Sep 17 00:00:00 2001 From: Yixun Lan Date: Tue, 30 Jun 2026 12:52:46 +0000 Subject: [PATCH 2/6] dt-bindings: soc: spacemit: k3: Add clock ID for UFS refclk Add clock ID for the UFS refclk clock in SpacemiT K3 SoC. Acked-by: Conor Dooley Link: https://patch.msgid.link/20260630-06-clk-ufs-support-v1-2-cf7521d1d0fe@kernel.org Signed-off-by: Yixun Lan --- include/dt-bindings/clock/spacemit,k3-clocks.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/dt-bindings/clock/spacemit,k3-clocks.h b/include/dt-bindings/clock/spacemit,k3-clocks.h index dfae52547cda..69978ab0b29f 100644 --- a/include/dt-bindings/clock/spacemit,k3-clocks.h +++ b/include/dt-bindings/clock/spacemit,k3-clocks.h @@ -385,6 +385,7 @@ #define CLK_APMU_PCIE_PORTC_DBI 91 #define CLK_APMU_PCIE_PORTD_DBI 92 #define CLK_APMU_PCIE_PORTE_DBI 93 +#define CLK_APMU_UFS_REFCLK 94 /* DCIU clocks */ #define CLK_DCIU_HDMA 0 From 8abba78dc0ee4ffa7c4e0e05b93c58bd94ff11c0 Mon Sep 17 00:00:00 2001 From: Yixun Lan Date: Tue, 30 Jun 2026 12:52:47 +0000 Subject: [PATCH 3/6] clk: spacemit: k3: Add UFS refclk clock Add the UFS reference clock for SpacemiT K3 SoC. Link: https://patch.msgid.link/20260630-06-clk-ufs-support-v1-3-cf7521d1d0fe@kernel.org Signed-off-by: Yixun Lan --- drivers/clk/spacemit/ccu-k3.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/clk/spacemit/ccu-k3.c b/drivers/clk/spacemit/ccu-k3.c index 42293a38b098..f47d26e1d642 100644 --- a/drivers/clk/spacemit/ccu-k3.c +++ b/drivers/clk/spacemit/ccu-k3.c @@ -934,6 +934,8 @@ static const struct clk_parent_data ufs_aclk_parents[] = { CCU_MUX_DIV_GATE_FC_DEFINE(ufs_aclk, ufs_aclk_parents, APMU_UFS_CLK_RES_CTRL, 5, 3, BIT(8), 2, 3, BIT(1), 0); +CCU_FACTOR_DEFINE(ufs_refclk, CCU_PARENT_HW(pll1_d64_38p4), 2, 1); + static const struct clk_parent_data edp0_pclk_parents[] = { CCU_PARENT_HW(lcd_pxclk), CCU_PARENT_NAME(external_clk), @@ -1391,6 +1393,7 @@ static struct clk_hw *k3_ccu_apmu_hws[] = { [CLK_APMU_DSI4LN2_DPU_ACLK] = &dsi4ln2_dpu_aclk.common.hw, [CLK_APMU_DPU_ACLK] = &dpu_aclk.common.hw, [CLK_APMU_UFS_ACLK] = &ufs_aclk.common.hw, + [CLK_APMU_UFS_REFCLK] = &ufs_refclk.common.hw, [CLK_APMU_EDP0_PXCLK] = &edp0_pxclk.common.hw, [CLK_APMU_EDP1_PXCLK] = &edp1_pxclk.common.hw, [CLK_APMU_PCIE_PORTA_MSTE] = &pciea_mstr_clk.common.hw, From cf59a8742581aa4a026b20c7a413be06f4fc9831 Mon Sep 17 00:00:00 2001 From: Troy Mitchell Date: Fri, 17 Jul 2026 00:26:01 -0700 Subject: [PATCH 4/6] dt-bindings: soc: spacemit: k3: add i2s_sysclk, i2s_bclk_factor and i2s1_sysclk_src IDs Add three new clock IDs to expose clocks introduced by the topology fix: - CLK_MPMU_I2S_SYSCLK (51): the common i2s sysclk DDN at MPMU_ISCCR1 - CLK_MPMU_I2S_BCLK_FACTOR (52): the implicit /2 factor feeding i2s_bclk - CLK_MPMU_I2S1_SYSCLK_SRC (53): the dedicated i2s1 sysclk source mux CLK_MPMU_I2S1_SYSCLK keeps its existing ID (34) but will be repointed to the real per-instance i2s1 clock in a subsequent patch. No in-tree user references this ID so the semantic change is contained. Fixes: efe897b557e2 ("dt-bindings: soc: spacemit: k3: add clock support") Signed-off-by: Troy Mitchell Reviewed-by: Yixun Lan Link: https://patch.msgid.link/20260717-k3-clk-fix-i2s-v1-1-e95001a692ee@linux.spacemit.com Signed-off-by: Yixun Lan --- include/dt-bindings/clock/spacemit,k3-clocks.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/dt-bindings/clock/spacemit,k3-clocks.h b/include/dt-bindings/clock/spacemit,k3-clocks.h index 69978ab0b29f..4f1099f5da1c 100644 --- a/include/dt-bindings/clock/spacemit,k3-clocks.h +++ b/include/dt-bindings/clock/spacemit,k3-clocks.h @@ -145,6 +145,9 @@ #define CLK_MPMU_I2S3_SYSCLK 48 #define CLK_MPMU_I2S4_SYSCLK 49 #define CLK_MPMU_I2S5_SYSCLK 50 +#define CLK_MPMU_I2S_SYSCLK 51 +#define CLK_MPMU_I2S_BCLK_FACTOR 52 +#define CLK_MPMU_I2S1_SYSCLK_SRC 53 /* APBC clocks */ #define CLK_APBC_UART0 0 From e6b17a690c2f920963d6a9328642bb090f3be587 Mon Sep 17 00:00:00 2001 From: Troy Mitchell Date: Fri, 17 Jul 2026 00:26:02 -0700 Subject: [PATCH 5/6] clk: spacemit: k3: fix i2s clock topology The K3 i2s clocks were modelled as a single path behind one MPMU register: pll1_d96_25p6 / i2s_153p6_base `-- i2s_sysclk_src (mux+gate, MPMU_ISCCR) `-- i2s1_sysclk (DDN, MPMU_ISCCR) |-- i2s_bclk (div+gate, MPMU_ISCCR) `-- i2s2_sysclk (mux, parent 0) The hardware actually has two i2s clock control registers, ISCCR0 (0x0040) and ISCCR1 (0x0044): ISCCR1 drives the common sysclk shared by i2s0/2/3/4/5 and the common bclk, whose divider always implies a fixed 1/2 factor in front, while ISCCR0 drives a dedicated path for i2s1: pll1_d96_25p6 / i2s_153p6_base |-- i2s_sysclk_src (mux+gate, MPMU_ISCCR1) | `-- i2s_sysclk (DDN, MPMU_ISCCR1) | |-- i2s_bclk_factor (fixed factor, /2) | | `-- i2s_bclk (div+gate, MPMU_ISCCR1) | `-- i2s2_sysclk (mux, parent 0) `-- i2s1_sysclk_src (mux+gate, MPMU_ISCCR0) `-- i2s1_sysclk (DDN, MPMU_ISCCR0) Because of this mismatch, i2s_bclk reported twice the real rate, and the dedicated i2s1 clock path could not be described in DT at all. Model the tree as above: split the MPMU_ISCCR register macro into MPMU_ISCCR0 and MPMU_ISCCR1 to match the hardware register names, rename the common DDN to i2s_sysclk, insert the fixed 1/2 factor i2s_bclk_factor in front of i2s_bclk, and add the i2s1_sysclk_src mux and i2s1_sysclk DDN backed by MPMU_ISCCR0. CLK_MPMU_I2S1_SYSCLK now refers to the dedicated i2s1 clock; no in-tree user references this ID, so nothing is affected by the change of meaning. Fixes: e371a77255b8 ("clk: spacemit: k3: add the clock tree") Signed-off-by: Troy Mitchell Reviewed-by: Yixun Lan Link: https://patch.msgid.link/20260717-k3-clk-fix-i2s-v1-2-e95001a692ee@linux.spacemit.com Signed-off-by: Yixun Lan --- drivers/clk/spacemit/ccu-k3.c | 21 ++++++++++++++++----- include/soc/spacemit/k3-syscon.h | 3 ++- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/drivers/clk/spacemit/ccu-k3.c b/drivers/clk/spacemit/ccu-k3.c index f47d26e1d642..3133b5d5ec00 100644 --- a/drivers/clk/spacemit/ccu-k3.c +++ b/drivers/clk/spacemit/ccu-k3.c @@ -218,11 +218,19 @@ static const struct clk_parent_data i2s_sysclk_src_parents[] = { CCU_PARENT_HW(pll1_d96_25p6), CCU_PARENT_HW(i2s_153p6_base), }; -CCU_MUX_GATE_DEFINE(i2s_sysclk_src, i2s_sysclk_src_parents, MPMU_ISCCR, 30, 1, BIT(31), 0); +CCU_MUX_GATE_DEFINE(i2s_sysclk_src, i2s_sysclk_src_parents, MPMU_ISCCR1, 30, 1, BIT(31), 0); -CCU_DDN_DEFINE(i2s1_sysclk, i2s_sysclk_src, MPMU_ISCCR, 0, 15, 15, 12, 1, 0); +CCU_DDN_DEFINE(i2s_sysclk, i2s_sysclk_src, MPMU_ISCCR1, 0, 15, 15, 12, 1, 0); -CCU_DIV_GATE_DEFINE(i2s_bclk, CCU_PARENT_HW(i2s1_sysclk), MPMU_ISCCR, 27, 2, BIT(29), 0); +CCU_FACTOR_DEFINE(i2s_bclk_factor, CCU_PARENT_HW(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(i2s_bclk, CCU_PARENT_HW(i2s_bclk_factor), MPMU_ISCCR1, 27, 2, BIT(29), 0); + +CCU_MUX_GATE_DEFINE(i2s1_sysclk_src, i2s_sysclk_src_parents, MPMU_ISCCR0, 30, 1, BIT(31), 0); +CCU_DDN_DEFINE(i2s1_sysclk, i2s1_sysclk_src, MPMU_ISCCR0, 0, 15, 15, 12, 1, 0); static const struct clk_parent_data i2s_sysclk_parents[] = { CCU_PARENT_HW(pll1_d4_614p4), @@ -243,7 +251,7 @@ CCU_DDN_DEFINE(i2s4_sysclk_div, i2s4_sysclk_sel, MPMU_I2S4_SYSCLK, 0, 16, 16, 16 CCU_DDN_DEFINE(i2s5_sysclk_div, i2s5_sysclk_sel, MPMU_I2S5_SYSCLK, 0, 16, 16, 16, 1, 0); static const struct clk_parent_data i2s2_sysclk_parents[] = { - CCU_PARENT_HW(i2s1_sysclk), + CCU_PARENT_HW(i2s_sysclk), CCU_PARENT_HW(i2s2_sysclk_div), }; CCU_GATE_DEFINE(i2s0_sysclk, CCU_PARENT_HW(i2s0_sysclk_div), MPMU_I2S_SYSCLK_CTRL, BIT(2), 0); @@ -1162,8 +1170,11 @@ static struct clk_hw *k3_ccu_mpmu_hws[] = { [CLK_MPMU_I2S_153P6] = &i2s_153p6.common.hw, [CLK_MPMU_I2S_153P6_BASE] = &i2s_153p6_base.common.hw, [CLK_MPMU_I2S_SYSCLK_SRC] = &i2s_sysclk_src.common.hw, - [CLK_MPMU_I2S1_SYSCLK] = &i2s1_sysclk.common.hw, + [CLK_MPMU_I2S_SYSCLK] = &i2s_sysclk.common.hw, + [CLK_MPMU_I2S_BCLK_FACTOR] = &i2s_bclk_factor.common.hw, [CLK_MPMU_I2S_BCLK] = &i2s_bclk.common.hw, + [CLK_MPMU_I2S1_SYSCLK_SRC] = &i2s1_sysclk_src.common.hw, + [CLK_MPMU_I2S1_SYSCLK] = &i2s1_sysclk.common.hw, [CLK_MPMU_I2S0_SYSCLK_SEL] = &i2s0_sysclk_sel.common.hw, [CLK_MPMU_I2S2_SYSCLK_SEL] = &i2s2_sysclk_sel.common.hw, [CLK_MPMU_I2S3_SYSCLK_SEL] = &i2s3_sysclk_sel.common.hw, diff --git a/include/soc/spacemit/k3-syscon.h b/include/soc/spacemit/k3-syscon.h index a68255dd641f..959d8d0786fe 100644 --- a/include/soc/spacemit/k3-syscon.h +++ b/include/soc/spacemit/k3-syscon.h @@ -45,7 +45,8 @@ #define POSR_PLL7_LOCK BIT(30) #define POSR_PLL8_LOCK BIT(31) #define MPMU_SUCCR 0x0014 -#define MPMU_ISCCR 0x0044 +#define MPMU_ISCCR0 0x0040 +#define MPMU_ISCCR1 0x0044 #define MPMU_WDTPCR 0x0200 #define MPMU_RIPCCR 0x0210 #define MPMU_ACGR 0x1024 From 8a7d4b1924d2a424b1a6fe69de4f9464ee1fb485 Mon Sep 17 00:00:00 2001 From: Troy Mitchell Date: Fri, 17 Jul 2026 00:26:03 -0700 Subject: [PATCH 6/6] clk: spacemit: k3: fix missing /2 factor in i2s sysclk dividers The i2s{0,2,3,4,5}_sysclk_div DDNs have an additional fixed 1/2 divider in the hardware IP after the configurable divider, so the real output rate is: rate = parent_rate * den / (num * 2) Set pre_div to 2 to account for it. Fixes: e371a77255b8 ("clk: spacemit: k3: add the clock tree") Signed-off-by: Troy Mitchell Reviewed-by: Yixun Lan Link: https://patch.msgid.link/20260717-k3-clk-fix-i2s-v1-3-e95001a692ee@linux.spacemit.com Signed-off-by: Yixun Lan --- drivers/clk/spacemit/ccu-k3.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/clk/spacemit/ccu-k3.c b/drivers/clk/spacemit/ccu-k3.c index 3133b5d5ec00..a0622b80ac0a 100644 --- a/drivers/clk/spacemit/ccu-k3.c +++ b/drivers/clk/spacemit/ccu-k3.c @@ -244,11 +244,11 @@ CCU_MUX_DEFINE(i2s3_sysclk_sel, i2s_sysclk_parents, MPMU_I2S_SYSCLK_CTRL, 12, 2, CCU_MUX_DEFINE(i2s4_sysclk_sel, i2s_sysclk_parents, MPMU_I2S_SYSCLK_CTRL, 16, 2, 0); CCU_MUX_DEFINE(i2s5_sysclk_sel, i2s_sysclk_parents, MPMU_I2S_SYSCLK_CTRL, 20, 2, 0); -CCU_DDN_DEFINE(i2s0_sysclk_div, i2s0_sysclk_sel, MPMU_I2S0_SYSCLK, 0, 16, 16, 16, 1, 0); -CCU_DDN_DEFINE(i2s2_sysclk_div, i2s2_sysclk_sel, MPMU_I2S2_SYSCLK, 0, 16, 16, 16, 1, 0); -CCU_DDN_DEFINE(i2s3_sysclk_div, i2s3_sysclk_sel, MPMU_I2S3_SYSCLK, 0, 16, 16, 16, 1, 0); -CCU_DDN_DEFINE(i2s4_sysclk_div, i2s4_sysclk_sel, MPMU_I2S4_SYSCLK, 0, 16, 16, 16, 1, 0); -CCU_DDN_DEFINE(i2s5_sysclk_div, i2s5_sysclk_sel, MPMU_I2S5_SYSCLK, 0, 16, 16, 16, 1, 0); +CCU_DDN_DEFINE(i2s0_sysclk_div, i2s0_sysclk_sel, MPMU_I2S0_SYSCLK, 0, 16, 16, 16, 2, 0); +CCU_DDN_DEFINE(i2s2_sysclk_div, i2s2_sysclk_sel, MPMU_I2S2_SYSCLK, 0, 16, 16, 16, 2, 0); +CCU_DDN_DEFINE(i2s3_sysclk_div, i2s3_sysclk_sel, MPMU_I2S3_SYSCLK, 0, 16, 16, 16, 2, 0); +CCU_DDN_DEFINE(i2s4_sysclk_div, i2s4_sysclk_sel, MPMU_I2S4_SYSCLK, 0, 16, 16, 16, 2, 0); +CCU_DDN_DEFINE(i2s5_sysclk_div, i2s5_sysclk_sel, MPMU_I2S5_SYSCLK, 0, 16, 16, 16, 2, 0); static const struct clk_parent_data i2s2_sysclk_parents[] = { CCU_PARENT_HW(i2s_sysclk),