Skip to content

Commit 67c1518

Browse files
Sam Protsenkokrzk
authored andcommitted
clk: samsung: exynos850: Propagate SPI IPCLK rate change
When SPI transfer is being prepared, the spi-s3c64xx driver will call clk_set_rate() to change the rate of SPI source clock (IPCLK). But IPCLK is a gate (leaf) clock, so it must propagate the rate change up the clock tree, so that corresponding DIV clocks can actually change their divider values. Add CLK_SET_RATE_PARENT flag to corresponding clocks for all SPI instances in Exynos850 (spi_0, spi_1 and spi_2) to make it possible. This change involves next clocks: usi_spi_0: Clock Block Div range -------------------------------------------- gout_spi0_ipclk CMU_PERI - dout_peri_spi0 CMU_PERI /1..32 mout_peri_spi_user CMU_PERI - dout_peri_ip CMU_TOP /1..16 usi_cmgp0: Clock Block Div range -------------------------------------------- gout_cmgp_usi0_ipclk CMU_CMGP - dout_cmgp_usi0 CMU_CMGP /1..32 mout_cmgp_usi0 CMU_CMGP - gout_clkcmu_cmgp_bus CMU_APM - dout_apm_bus CMU_APM /1..8 usi_cmgp1: Clock Block Div range -------------------------------------------- gout_cmgp_usi1_ipclk CMU_CMGP - dout_cmgp_usi1 CMU_CMGP /1..32 mout_cmgp_usi1 CMU_CMGP - gout_clkcmu_cmgp_bus CMU_APM - dout_apm_bus CMU_APM /1..8 With input clock of 400 MHz, this scheme provides next IPCLK rate range, for each SPI block: SPI0: 781 kHz ... 400 MHz SPI1/2: 1.6 MHz ... 400 MHz Accounting for internal /4 divider in SPI blocks, and because the max SPI frequency is limited at 50 MHz, it gives us next SPI SCK rates: SPI0: 200 kHz ... 49.9 MHz SPI1/2: 400 kHz ... 49.9 MHz Which should cover all possible applications of SPI bus. Of course, setting SPI frequency to values as low as 500 kHz will also affect the common bus dividers (dout_apm_bus or dout_peri_ip), which in turn effectively lowers the rates for all leaf bus clocks derived from those dividers, like HSI2C and I3C clocks. But at least it gives the board designer a choice, whether to keep all clocks (SPI/HSI2C/I3C) at high frequencies, or make all those clocks have lower frequencies. Not propagating the rate change to those common dividers would limit this choice to "only high frequencies are allowed for SPI/HSI2C/I3C" option, making the common dividers useless. This decision follows the "Worse is better" approach, relying on the users/engineers to know the system internals when working with such low-level features, instead of trying to account for all possible use-cases. Fixes: 7dd0557 ("clk: samsung: Introduce Exynos850 clock driver") Signed-off-by: Sam Protsenko <[email protected]> Reviewed-by: Tudor Ambarus <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Krzysztof Kozlowski <[email protected]>
1 parent 8a96d27 commit 67c1518

File tree

1 file changed

+17
-16
lines changed

1 file changed

+17
-16
lines changed

drivers/clk/samsung/clk-exynos850.c

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -605,7 +605,7 @@ static const struct samsung_div_clock apm_div_clks[] __initconst = {
605605

606606
static const struct samsung_gate_clock apm_gate_clks[] __initconst = {
607607
GATE(CLK_GOUT_CLKCMU_CMGP_BUS, "gout_clkcmu_cmgp_bus", "dout_apm_bus",
608-
CLK_CON_GAT_CLKCMU_CMGP_BUS, 21, 0, 0),
608+
CLK_CON_GAT_CLKCMU_CMGP_BUS, 21, CLK_SET_RATE_PARENT, 0),
609609
GATE(CLK_GOUT_CLKCMU_CHUB_BUS, "gout_clkcmu_chub_bus",
610610
"mout_clkcmu_chub_bus",
611611
CLK_CON_GAT_GATE_CLKCMU_CHUB_BUS, 21, 0, 0),
@@ -974,19 +974,19 @@ static const struct samsung_fixed_rate_clock cmgp_fixed_clks[] __initconst = {
974974
static const struct samsung_mux_clock cmgp_mux_clks[] __initconst = {
975975
MUX(CLK_MOUT_CMGP_ADC, "mout_cmgp_adc", mout_cmgp_adc_p,
976976
CLK_CON_MUX_CLK_CMGP_ADC, 0, 1),
977-
MUX(CLK_MOUT_CMGP_USI0, "mout_cmgp_usi0", mout_cmgp_usi0_p,
978-
CLK_CON_MUX_MUX_CLK_CMGP_USI_CMGP0, 0, 1),
979-
MUX(CLK_MOUT_CMGP_USI1, "mout_cmgp_usi1", mout_cmgp_usi1_p,
980-
CLK_CON_MUX_MUX_CLK_CMGP_USI_CMGP1, 0, 1),
977+
MUX_F(CLK_MOUT_CMGP_USI0, "mout_cmgp_usi0", mout_cmgp_usi0_p,
978+
CLK_CON_MUX_MUX_CLK_CMGP_USI_CMGP0, 0, 1, CLK_SET_RATE_PARENT, 0),
979+
MUX_F(CLK_MOUT_CMGP_USI1, "mout_cmgp_usi1", mout_cmgp_usi1_p,
980+
CLK_CON_MUX_MUX_CLK_CMGP_USI_CMGP1, 0, 1, CLK_SET_RATE_PARENT, 0),
981981
};
982982

983983
static const struct samsung_div_clock cmgp_div_clks[] __initconst = {
984984
DIV(CLK_DOUT_CMGP_ADC, "dout_cmgp_adc", "gout_clkcmu_cmgp_bus",
985985
CLK_CON_DIV_DIV_CLK_CMGP_ADC, 0, 4),
986-
DIV(CLK_DOUT_CMGP_USI0, "dout_cmgp_usi0", "mout_cmgp_usi0",
987-
CLK_CON_DIV_DIV_CLK_CMGP_USI_CMGP0, 0, 5),
988-
DIV(CLK_DOUT_CMGP_USI1, "dout_cmgp_usi1", "mout_cmgp_usi1",
989-
CLK_CON_DIV_DIV_CLK_CMGP_USI_CMGP1, 0, 5),
986+
DIV_F(CLK_DOUT_CMGP_USI0, "dout_cmgp_usi0", "mout_cmgp_usi0",
987+
CLK_CON_DIV_DIV_CLK_CMGP_USI_CMGP0, 0, 5, CLK_SET_RATE_PARENT, 0),
988+
DIV_F(CLK_DOUT_CMGP_USI1, "dout_cmgp_usi1", "mout_cmgp_usi1",
989+
CLK_CON_DIV_DIV_CLK_CMGP_USI_CMGP1, 0, 5, CLK_SET_RATE_PARENT, 0),
990990
};
991991

992992
static const struct samsung_gate_clock cmgp_gate_clks[] __initconst = {
@@ -1001,12 +1001,12 @@ static const struct samsung_gate_clock cmgp_gate_clks[] __initconst = {
10011001
"gout_clkcmu_cmgp_bus",
10021002
CLK_CON_GAT_GOUT_CMGP_GPIO_PCLK, 21, CLK_IGNORE_UNUSED, 0),
10031003
GATE(CLK_GOUT_CMGP_USI0_IPCLK, "gout_cmgp_usi0_ipclk", "dout_cmgp_usi0",
1004-
CLK_CON_GAT_GOUT_CMGP_USI_CMGP0_IPCLK, 21, 0, 0),
1004+
CLK_CON_GAT_GOUT_CMGP_USI_CMGP0_IPCLK, 21, CLK_SET_RATE_PARENT, 0),
10051005
GATE(CLK_GOUT_CMGP_USI0_PCLK, "gout_cmgp_usi0_pclk",
10061006
"gout_clkcmu_cmgp_bus",
10071007
CLK_CON_GAT_GOUT_CMGP_USI_CMGP0_PCLK, 21, 0, 0),
10081008
GATE(CLK_GOUT_CMGP_USI1_IPCLK, "gout_cmgp_usi1_ipclk", "dout_cmgp_usi1",
1009-
CLK_CON_GAT_GOUT_CMGP_USI_CMGP1_IPCLK, 21, 0, 0),
1009+
CLK_CON_GAT_GOUT_CMGP_USI_CMGP1_IPCLK, 21, CLK_SET_RATE_PARENT, 0),
10101010
GATE(CLK_GOUT_CMGP_USI1_PCLK, "gout_cmgp_usi1_pclk",
10111011
"gout_clkcmu_cmgp_bus",
10121012
CLK_CON_GAT_GOUT_CMGP_USI_CMGP1_PCLK, 21, 0, 0),
@@ -1557,8 +1557,9 @@ static const struct samsung_mux_clock peri_mux_clks[] __initconst = {
15571557
mout_peri_uart_user_p, PLL_CON0_MUX_CLKCMU_PERI_UART_USER, 4, 1),
15581558
MUX(CLK_MOUT_PERI_HSI2C_USER, "mout_peri_hsi2c_user",
15591559
mout_peri_hsi2c_user_p, PLL_CON0_MUX_CLKCMU_PERI_HSI2C_USER, 4, 1),
1560-
MUX(CLK_MOUT_PERI_SPI_USER, "mout_peri_spi_user", mout_peri_spi_user_p,
1561-
PLL_CON0_MUX_CLKCMU_PERI_SPI_USER, 4, 1),
1560+
MUX_F(CLK_MOUT_PERI_SPI_USER, "mout_peri_spi_user",
1561+
mout_peri_spi_user_p, PLL_CON0_MUX_CLKCMU_PERI_SPI_USER, 4, 1,
1562+
CLK_SET_RATE_PARENT, 0),
15621563
};
15631564

15641565
static const struct samsung_div_clock peri_div_clks[] __initconst = {
@@ -1568,8 +1569,8 @@ static const struct samsung_div_clock peri_div_clks[] __initconst = {
15681569
CLK_CON_DIV_DIV_CLK_PERI_HSI2C_1, 0, 5),
15691570
DIV(CLK_DOUT_PERI_HSI2C2, "dout_peri_hsi2c2", "gout_peri_hsi2c2",
15701571
CLK_CON_DIV_DIV_CLK_PERI_HSI2C_2, 0, 5),
1571-
DIV(CLK_DOUT_PERI_SPI0, "dout_peri_spi0", "mout_peri_spi_user",
1572-
CLK_CON_DIV_DIV_CLK_PERI_SPI_0, 0, 5),
1572+
DIV_F(CLK_DOUT_PERI_SPI0, "dout_peri_spi0", "mout_peri_spi_user",
1573+
CLK_CON_DIV_DIV_CLK_PERI_SPI_0, 0, 5, CLK_SET_RATE_PARENT, 0),
15731574
};
15741575

15751576
static const struct samsung_gate_clock peri_gate_clks[] __initconst = {
@@ -1611,7 +1612,7 @@ static const struct samsung_gate_clock peri_gate_clks[] __initconst = {
16111612
"mout_peri_bus_user",
16121613
CLK_CON_GAT_GOUT_PERI_PWM_MOTOR_PCLK, 21, 0, 0),
16131614
GATE(CLK_GOUT_SPI0_IPCLK, "gout_spi0_ipclk", "dout_peri_spi0",
1614-
CLK_CON_GAT_GOUT_PERI_SPI_0_IPCLK, 21, 0, 0),
1615+
CLK_CON_GAT_GOUT_PERI_SPI_0_IPCLK, 21, CLK_SET_RATE_PARENT, 0),
16151616
GATE(CLK_GOUT_SPI0_PCLK, "gout_spi0_pclk", "mout_peri_bus_user",
16161617
CLK_CON_GAT_GOUT_PERI_SPI_0_PCLK, 21, 0, 0),
16171618
GATE(CLK_GOUT_SYSREG_PERI_PCLK, "gout_sysreg_peri_pclk",

0 commit comments

Comments
 (0)