Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

clk: spacemit: fix i2s clock

Defining i2s_bclk and i2s_sysclk as fixed-rate clocks is insufficient
for real I2S use cases.

Moreover, the current I2S clock configuration does not work as expected
due to missing parent clocks.

This patch adds the missing parent clocks, defines i2s_sysclk as
a DDN clock, and i2s_bclk as a DIV clock.

A special note for i2s_bclk:

From the register definition, the i2s_bclk divider always implies
an additional 1/2 factor.

The following table shows the correspondence between index
and frequency division coefficients:

| index | div |
|-------|-------|
| 0 | 2 |
| 1 | 4 |
| 2 | 6 |
| 3 | 8 |

From a software perspective, introducing i2s_bclk_factor as the
parent of i2s_bclk is sufficient to address the issue.

The I2S-related clock registers can be found here [1].

Link:
https://developer.spacemit.com/documentation?token=LCrKwWDasiJuROkVNusc2pWTnEb
[1]

Fixes: 1b72c59db0add ("clk: spacemit: Add clock support for SpacemiT K1 SoC")
Co-developer: Jinmei Wei <weijinmei@linux.spacemit.com>
Suggested-by: Haylen Chu <heylenay@4d2.org>
Signed-off-by: Jinmei Wei <weijinmei@linux.spacemit.com>
Signed-off-by: Troy Mitchell <troy.mitchell@linux.spacemit.com>
Signed-off-by: Stephen Boyd <sboyd@kernel.org>

authored by

Troy Mitchell and committed by
Stephen Boyd
519cff1d 74246a82

+27 -2
+26 -2
drivers/clk/spacemit/ccu-k1.c
··· 141 141 142 142 CCU_GATE_DEFINE(wdt_clk, CCU_PARENT_HW(pll1_d96_25p6), MPMU_WDTPCR, BIT(1), 0); 143 143 144 - CCU_FACTOR_GATE_DEFINE(i2s_sysclk, CCU_PARENT_HW(pll1_d16_153p6), MPMU_ISCCR, BIT(31), 50, 1); 145 - CCU_FACTOR_GATE_DEFINE(i2s_bclk, CCU_PARENT_HW(i2s_sysclk), MPMU_ISCCR, BIT(29), 1, 1); 144 + CCU_FACTOR_DEFINE(i2s_153p6, CCU_PARENT_HW(pll1_d8_307p2), 2, 1); 145 + 146 + static const struct clk_parent_data i2s_153p6_base_parents[] = { 147 + CCU_PARENT_HW(i2s_153p6), 148 + CCU_PARENT_HW(pll1_d8_307p2), 149 + }; 150 + CCU_MUX_DEFINE(i2s_153p6_base, i2s_153p6_base_parents, MPMU_FCCR, 29, 1, 0); 151 + 152 + static const struct clk_parent_data i2s_sysclk_src_parents[] = { 153 + CCU_PARENT_HW(pll1_d96_25p6), 154 + CCU_PARENT_HW(i2s_153p6_base) 155 + }; 156 + CCU_MUX_GATE_DEFINE(i2s_sysclk_src, i2s_sysclk_src_parents, MPMU_ISCCR, 30, 1, BIT(31), 0); 157 + 158 + CCU_DDN_DEFINE(i2s_sysclk, i2s_sysclk_src, MPMU_ISCCR, 0, 15, 15, 12, 1, 0); 159 + 160 + CCU_FACTOR_DEFINE(i2s_bclk_factor, CCU_PARENT_HW(i2s_sysclk), 2, 1); 161 + /* 162 + * Divider of i2s_bclk always implies a 1/2 factor, which is 163 + * described by i2s_bclk_factor. 164 + */ 165 + CCU_DIV_GATE_DEFINE(i2s_bclk, CCU_PARENT_HW(i2s_bclk_factor), MPMU_ISCCR, 27, 2, BIT(29), 0); 146 166 147 167 static const struct clk_parent_data apb_parents[] = { 148 168 CCU_PARENT_HW(pll1_d96_25p6), ··· 795 775 [CLK_I2S_BCLK] = &i2s_bclk.common.hw, 796 776 [CLK_APB] = &apb_clk.common.hw, 797 777 [CLK_WDT_BUS] = &wdt_bus_clk.common.hw, 778 + [CLK_I2S_153P6] = &i2s_153p6.common.hw, 779 + [CLK_I2S_153P6_BASE] = &i2s_153p6_base.common.hw, 780 + [CLK_I2S_SYSCLK_SRC] = &i2s_sysclk_src.common.hw, 781 + [CLK_I2S_BCLK_FACTOR] = &i2s_bclk_factor.common.hw, 798 782 }; 799 783 800 784 static const struct spacemit_ccu_data k1_ccu_mpmu_data = {
+1
include/soc/spacemit/k1-syscon.h
··· 30 30 31 31 /* MPMU register offset */ 32 32 #define MPMU_POSR 0x0010 33 + #define MPMU_FCCR 0x0008 33 34 #define POSR_PLL1_LOCK BIT(27) 34 35 #define POSR_PLL2_LOCK BIT(28) 35 36 #define POSR_PLL3_LOCK BIT(29)