linux-clk.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v1 0/6] clk: rockchip: Support for some new features
@ 2019-04-03  9:42 Elaine Zhang
  2019-04-03  9:42 ` [PATCH v1 1/6] clk: rockchip: Add supprot to limit input rate for fractional divider Elaine Zhang
                   ` (5 more replies)
  0 siblings, 6 replies; 16+ messages in thread
From: Elaine Zhang @ 2019-04-03  9:42 UTC (permalink / raw)
  To: heiko
  Cc: mturquette, sboyd, linux-clk, linux-arm-kernel, linux-rockchip,
	linux-kernel, xxx, xf, huangtao, Elaine Zhang

1. Support for some new features
2. fix up some error

Elaine Zhang (4):
  clk: rockchip: fix up the frac clk get rate error
  clk: rockchip: add a clock-type for muxes based in the pmugrf
  clk: rockchip: add pll up and down when change pll freq
  clk: rockchip: support pll setting by auto

Finley Xiao (2):
  clk: rockchip: Add supprot to limit input rate for fractional divider
  clk: rockchip: add a COMPOSITE_DIV_OFFSET clock-type

 drivers/clk/rockchip/clk-pll.c    | 234 +++++++++++++++++++++++++++++++++++---
 drivers/clk/rockchip/clk-px30.c   |  29 ++---
 drivers/clk/rockchip/clk-rk3036.c |  13 ++-
 drivers/clk/rockchip/clk-rk3128.c |  15 ++-
 drivers/clk/rockchip/clk-rk3188.c |  24 ++--
 drivers/clk/rockchip/clk-rk3228.c |  18 +--
 drivers/clk/rockchip/clk-rk3288.c |  19 ++--
 drivers/clk/rockchip/clk-rk3328.c |  17 +--
 drivers/clk/rockchip/clk-rk3368.c |  17 +--
 drivers/clk/rockchip/clk-rk3399.c |  32 +++---
 drivers/clk/rockchip/clk-rv1108.c |  14 ++-
 drivers/clk/rockchip/clk.c        |  48 ++++++--
 drivers/clk/rockchip/clk.h        |  50 +++++++-
 include/linux/clk-provider.h      |   2 +
 14 files changed, 423 insertions(+), 109 deletions(-)

-- 
1.9.1




^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH v1 1/6] clk: rockchip: Add supprot to limit input rate for fractional divider
  2019-04-03  9:42 [PATCH v1 0/6] clk: rockchip: Support for some new features Elaine Zhang
@ 2019-04-03  9:42 ` Elaine Zhang
  2019-04-12 11:52   ` Heiko Stübner
  2019-04-03  9:42 ` [PATCH v1 2/6] clk: rockchip: fix up the frac clk get rate error Elaine Zhang
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 16+ messages in thread
From: Elaine Zhang @ 2019-04-03  9:42 UTC (permalink / raw)
  To: heiko
  Cc: mturquette, sboyd, linux-clk, linux-arm-kernel, linux-rockchip,
	linux-kernel, xxx, xf, huangtao, Finley Xiao, Elaine Zhang

From: Finley Xiao <finley.xiao@rock-chips.com>

From Rockchips fractional divider usage, some clocks can be generated
by fractional divider, but the input clock frequency of fractional
divider should be less than a specified value.

Signed-off-by: Finley Xiao <finley.xiao@rock-chips.com>
Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com>
---
 drivers/clk/rockchip/clk-px30.c   | 29 +++++++++++++++--------------
 drivers/clk/rockchip/clk-rk3036.c | 13 ++++++++-----
 drivers/clk/rockchip/clk-rk3128.c | 15 +++++++++------
 drivers/clk/rockchip/clk-rk3188.c | 24 ++++++++++++++----------
 drivers/clk/rockchip/clk-rk3228.c | 18 +++++++++++-------
 drivers/clk/rockchip/clk-rk3288.c | 19 +++++++++++--------
 drivers/clk/rockchip/clk-rk3328.c | 17 ++++++++++-------
 drivers/clk/rockchip/clk-rk3368.c | 17 ++++++++++-------
 drivers/clk/rockchip/clk-rk3399.c | 32 +++++++++++++++++++-------------
 drivers/clk/rockchip/clk-rv1108.c | 14 ++++++++------
 drivers/clk/rockchip/clk.c        | 21 ++++++++++++++++++---
 drivers/clk/rockchip/clk.h        | 10 +++++++---
 include/linux/clk-provider.h      |  2 ++
 13 files changed, 142 insertions(+), 89 deletions(-)

diff --git a/drivers/clk/rockchip/clk-px30.c b/drivers/clk/rockchip/clk-px30.c
index 601a77f1af78..ccabce35580b 100644
--- a/drivers/clk/rockchip/clk-px30.c
+++ b/drivers/clk/rockchip/clk-px30.c
@@ -21,6 +21,7 @@
 #include "clk.h"
 
 #define PX30_GRF_SOC_STATUS0		0x480
+#define PX30_FRAC_MAX_PRATE		600000000
 
 enum px30_plls {
 	apll, dpll, cpll, npll, apll_b_h, apll_b_l,
@@ -428,7 +429,7 @@ enum px30_pmu_plls {
 	COMPOSITE_FRACMUX(0, "dclk_vopb_frac", "dclk_vopb_src", CLK_SET_RATE_PARENT,
 			PX30_CLKSEL_CON(6), 0,
 			PX30_CLKGATE_CON(2), 3, GFLAGS,
-			&px30_dclk_vopb_fracmux),
+			&px30_dclk_vopb_fracmux, 0),
 	GATE(DCLK_VOPB, "dclk_vopb", "dclk_vopb_mux", CLK_SET_RATE_PARENT,
 			PX30_CLKGATE_CON(2), 4, GFLAGS),
 	COMPOSITE(0, "dclk_vopl_src", mux_npll_cpll_p, 0,
@@ -437,7 +438,7 @@ enum px30_pmu_plls {
 	COMPOSITE_FRACMUX(0, "dclk_vopl_frac", "dclk_vopl_src", CLK_SET_RATE_PARENT,
 			PX30_CLKSEL_CON(9), 0,
 			PX30_CLKGATE_CON(2), 7, GFLAGS,
-			&px30_dclk_vopl_fracmux),
+			&px30_dclk_vopl_fracmux, 0),
 	GATE(DCLK_VOPL, "dclk_vopl", "dclk_vopl_mux", CLK_SET_RATE_PARENT,
 			PX30_CLKGATE_CON(2), 8, GFLAGS),
 
@@ -563,7 +564,7 @@ enum px30_pmu_plls {
 	COMPOSITE_FRACMUX(0, "clk_pdm_frac", "clk_pdm_src", CLK_SET_RATE_PARENT,
 			PX30_CLKSEL_CON(27), 0,
 			PX30_CLKGATE_CON(9), 10, GFLAGS,
-			&px30_pdm_fracmux),
+			&px30_pdm_fracmux, PX30_FRAC_MAX_PRATE),
 	GATE(SCLK_PDM, "clk_pdm", "clk_pdm_mux", CLK_SET_RATE_PARENT,
 			PX30_CLKGATE_CON(9), 11, GFLAGS),
 
@@ -573,7 +574,7 @@ enum px30_pmu_plls {
 	COMPOSITE_FRACMUX(0, "clk_i2s0_tx_frac", "clk_i2s0_tx_src", CLK_SET_RATE_PARENT,
 			PX30_CLKSEL_CON(29), 0,
 			PX30_CLKGATE_CON(9), 13, GFLAGS,
-			&px30_i2s0_tx_fracmux),
+			&px30_i2s0_tx_fracmux, PX30_FRAC_MAX_PRATE),
 	COMPOSITE_NODIV(SCLK_I2S0_TX, "clk_i2s0_tx", mux_i2s0_tx_rx_p, CLK_SET_RATE_PARENT,
 			PX30_CLKSEL_CON(28), 12, 1, MFLAGS,
 			PX30_CLKGATE_CON(9), 14, GFLAGS),
@@ -589,7 +590,7 @@ enum px30_pmu_plls {
 	COMPOSITE_FRACMUX(0, "clk_i2s0_rx_frac", "clk_i2s0_rx_src", CLK_SET_RATE_PARENT,
 			PX30_CLKSEL_CON(59), 0,
 			PX30_CLKGATE_CON(17), 1, GFLAGS,
-			&px30_i2s0_rx_fracmux),
+			&px30_i2s0_rx_fracmux, PX30_FRAC_MAX_PRATE),
 	COMPOSITE_NODIV(SCLK_I2S0_RX, "clk_i2s0_rx", mux_i2s0_rx_tx_p, CLK_SET_RATE_PARENT,
 			PX30_CLKSEL_CON(58), 12, 1, MFLAGS,
 			PX30_CLKGATE_CON(17), 2, GFLAGS),
@@ -605,7 +606,7 @@ enum px30_pmu_plls {
 	COMPOSITE_FRACMUX(0, "clk_i2s1_frac", "clk_i2s1_src", CLK_SET_RATE_PARENT,
 			PX30_CLKSEL_CON(31), 0,
 			PX30_CLKGATE_CON(10), 1, GFLAGS,
-			&px30_i2s1_fracmux),
+			&px30_i2s1_fracmux, PX30_FRAC_MAX_PRATE),
 	GATE(SCLK_I2S1, "clk_i2s1", "clk_i2s1_mux", CLK_SET_RATE_PARENT,
 			PX30_CLKGATE_CON(10), 2, GFLAGS),
 	COMPOSITE_NODIV(0, "clk_i2s1_out_pre", mux_i2s1_out_p, 0,
@@ -620,7 +621,7 @@ enum px30_pmu_plls {
 	COMPOSITE_FRACMUX(0, "clk_i2s2_frac", "clk_i2s2_src", CLK_SET_RATE_PARENT,
 			PX30_CLKSEL_CON(33), 0,
 			PX30_CLKGATE_CON(10), 5, GFLAGS,
-			&px30_i2s2_fracmux),
+			&px30_i2s2_fracmux, PX30_FRAC_MAX_PRATE),
 	GATE(SCLK_I2S2, "clk_i2s2", "clk_i2s2_mux", CLK_SET_RATE_PARENT,
 			PX30_CLKGATE_CON(10), 6, GFLAGS),
 	COMPOSITE_NODIV(0, "clk_i2s2_out_pre", mux_i2s2_out_p, 0,
@@ -638,7 +639,7 @@ enum px30_pmu_plls {
 	COMPOSITE_FRACMUX(0, "clk_uart1_frac", "clk_uart1_src", CLK_SET_RATE_PARENT,
 			PX30_CLKSEL_CON(36), 0,
 			PX30_CLKGATE_CON(10), 14, GFLAGS,
-			&px30_uart1_fracmux),
+			&px30_uart1_fracmux, PX30_FRAC_MAX_PRATE),
 	GATE(SCLK_UART1, "clk_uart1", "clk_uart1_mux", CLK_SET_RATE_PARENT,
 			PX30_CLKGATE_CON(10), 15, GFLAGS),
 
@@ -651,7 +652,7 @@ enum px30_pmu_plls {
 	COMPOSITE_FRACMUX(0, "clk_uart2_frac", "clk_uart2_src", CLK_SET_RATE_PARENT,
 			PX30_CLKSEL_CON(39), 0,
 			PX30_CLKGATE_CON(11), 2, GFLAGS,
-			&px30_uart2_fracmux),
+			&px30_uart2_fracmux, PX30_FRAC_MAX_PRATE),
 	GATE(SCLK_UART2, "clk_uart2", "clk_uart2_mux", CLK_SET_RATE_PARENT,
 			PX30_CLKGATE_CON(11), 3, GFLAGS),
 
@@ -664,7 +665,7 @@ enum px30_pmu_plls {
 	COMPOSITE_FRACMUX(0, "clk_uart3_frac", "clk_uart3_src", CLK_SET_RATE_PARENT,
 			PX30_CLKSEL_CON(42), 0,
 			PX30_CLKGATE_CON(11), 6, GFLAGS,
-			&px30_uart3_fracmux),
+			&px30_uart3_fracmux, PX30_FRAC_MAX_PRATE),
 	GATE(SCLK_UART3, "clk_uart3", "clk_uart3_mux", CLK_SET_RATE_PARENT,
 			PX30_CLKGATE_CON(11), 7, GFLAGS),
 
@@ -677,7 +678,7 @@ enum px30_pmu_plls {
 	COMPOSITE_FRACMUX(0, "clk_uart4_frac", "clk_uart4_src", CLK_SET_RATE_PARENT,
 			PX30_CLKSEL_CON(45), 0,
 			PX30_CLKGATE_CON(11), 10, GFLAGS,
-			&px30_uart4_fracmux),
+			&px30_uart4_fracmux, PX30_FRAC_MAX_PRATE),
 	GATE(SCLK_UART4, "clk_uart4", "clk_uart4_mux", CLK_SET_RATE_PARENT,
 			PX30_CLKGATE_CON(11), 11, GFLAGS),
 
@@ -690,7 +691,7 @@ enum px30_pmu_plls {
 	COMPOSITE_FRACMUX(0, "clk_uart5_frac", "clk_uart5_src", CLK_SET_RATE_PARENT,
 			PX30_CLKSEL_CON(48), 0,
 			PX30_CLKGATE_CON(11), 14, GFLAGS,
-			&px30_uart5_fracmux),
+			&px30_uart5_fracmux, PX30_FRAC_MAX_PRATE),
 	GATE(SCLK_UART5, "clk_uart5", "clk_uart5_mux", CLK_SET_RATE_PARENT,
 			PX30_CLKGATE_CON(11), 15, GFLAGS),
 
@@ -887,7 +888,7 @@ enum px30_pmu_plls {
 	COMPOSITE_FRACMUX(0, "clk_rtc32k_frac", "xin24m", CLK_IGNORE_UNUSED,
 			PX30_PMU_CLKSEL_CON(1), 0,
 			PX30_PMU_CLKGATE_CON(0), 13, GFLAGS,
-			&px30_rtc32k_pmu_fracmux),
+			&px30_rtc32k_pmu_fracmux, 0),
 
 	COMPOSITE_NOMUX(XIN24M_DIV, "xin24m_div", "xin24m", CLK_IGNORE_UNUSED,
 			PX30_PMU_CLKSEL_CON(0), 8, 5, DFLAGS,
@@ -909,7 +910,7 @@ enum px30_pmu_plls {
 	COMPOSITE_FRACMUX(0, "clk_uart0_frac", "clk_uart0_pmu_src", CLK_SET_RATE_PARENT,
 			PX30_PMU_CLKSEL_CON(5), 0,
 			PX30_PMU_CLKGATE_CON(1), 2, GFLAGS,
-			&px30_uart0_pmu_fracmux),
+			&px30_uart0_pmu_fracmux, PX30_FRAC_MAX_PRATE),
 	GATE(SCLK_UART0_PMU, "clk_uart0_pmu", "clk_uart0_pmu_mux", CLK_SET_RATE_PARENT,
 			PX30_PMU_CLKGATE_CON(1), 3, GFLAGS),
 
diff --git a/drivers/clk/rockchip/clk-rk3036.c b/drivers/clk/rockchip/clk-rk3036.c
index c3001980dbdc..622f47ab3e25 100644
--- a/drivers/clk/rockchip/clk-rk3036.c
+++ b/drivers/clk/rockchip/clk-rk3036.c
@@ -24,6 +24,9 @@
 #include "clk.h"
 
 #define RK3036_GRF_SOC_STATUS0	0x14c
+#define RK3036_UART_FRAC_MAX_PRATE	600000000
+#define RK3036_I2S_FRAC_MAX_PRATE	600000000
+#define RK3036_SPDIF_FRAC_MAX_PRATE	600000000
 
 enum rk3036_plls {
 	apll, dpll, gpll,
@@ -256,15 +259,15 @@ enum rk3036_plls {
 	COMPOSITE_FRACMUX(0, "uart0_frac", "uart0_src", CLK_SET_RATE_PARENT,
 			RK2928_CLKSEL_CON(17), 0,
 			RK2928_CLKGATE_CON(1), 9, GFLAGS,
-			&rk3036_uart0_fracmux),
+			&rk3036_uart0_fracmux, RK3036_UART_FRAC_MAX_PRATE),
 	COMPOSITE_FRACMUX(0, "uart1_frac", "uart1_src", CLK_SET_RATE_PARENT,
 			RK2928_CLKSEL_CON(18), 0,
 			RK2928_CLKGATE_CON(1), 11, GFLAGS,
-			&rk3036_uart1_fracmux),
+			&rk3036_uart1_fracmux, RK3036_UART_FRAC_MAX_PRATE),
 	COMPOSITE_FRACMUX(0, "uart2_frac", "uart2_src", CLK_SET_RATE_PARENT,
 			RK2928_CLKSEL_CON(19), 0,
 			RK2928_CLKGATE_CON(1), 13, GFLAGS,
-			&rk3036_uart2_fracmux),
+			&rk3036_uart2_fracmux, RK3036_UART_FRAC_MAX_PRATE),
 
 	COMPOSITE(0, "aclk_vcodec", mux_pll_src_3plls_p, 0,
 			RK2928_CLKSEL_CON(32), 14, 2, MFLAGS, 8, 5, DFLAGS,
@@ -317,7 +320,7 @@ enum rk3036_plls {
 	COMPOSITE_FRACMUX(0, "i2s_frac", "i2s_src", CLK_SET_RATE_PARENT,
 			RK2928_CLKSEL_CON(7), 0,
 			RK2928_CLKGATE_CON(0), 10, GFLAGS,
-			&rk3036_i2s_fracmux),
+			&rk3036_i2s_fracmux, RK3036_I2S_FRAC_MAX_PRATE),
 	COMPOSITE_NODIV(SCLK_I2S_OUT, "i2s_clkout", mux_i2s_clkout_p, 0,
 			RK2928_CLKSEL_CON(3), 12, 1, MFLAGS,
 			RK2928_CLKGATE_CON(0), 13, GFLAGS),
@@ -330,7 +333,7 @@ enum rk3036_plls {
 	COMPOSITE_FRACMUX(0, "spdif_frac", "spdif_src", 0,
 			RK2928_CLKSEL_CON(9), 0,
 			RK2928_CLKGATE_CON(2), 12, GFLAGS,
-			&rk3036_spdif_fracmux),
+			&rk3036_spdif_fracmux, RK3036_SPDIF_FRAC_MAX_PRATE),
 
 	GATE(SCLK_OTGPHY0, "sclk_otgphy0", "xin12m", CLK_IGNORE_UNUSED,
 			RK2928_CLKGATE_CON(1), 5, GFLAGS),
diff --git a/drivers/clk/rockchip/clk-rk3128.c b/drivers/clk/rockchip/clk-rk3128.c
index 5970a50671b9..35387252ad68 100644
--- a/drivers/clk/rockchip/clk-rk3128.c
+++ b/drivers/clk/rockchip/clk-rk3128.c
@@ -21,6 +21,9 @@
 #include "clk.h"
 
 #define RK3128_GRF_SOC_STATUS0	0x14c
+#define RK3128_UART_FRAC_MAX_PRATE	600000000
+#define RK3128_I2S_FRAC_MAX_PRATE	600000000
+#define RK3128_SPDIF_FRAC_MAX_PRATE	600000000
 
 enum rk3128_plls {
 	apll, dpll, cpll, gpll,
@@ -367,7 +370,7 @@ enum rk3128_plls {
 	COMPOSITE_FRACMUX(0, "i2s0_frac", "i2s0_src", CLK_SET_RATE_PARENT,
 			RK2928_CLKSEL_CON(8), 0,
 			RK2928_CLKGATE_CON(4), 5, GFLAGS,
-			&rk3128_i2s0_fracmux),
+			&rk3128_i2s0_fracmux, RK3128_I2S_FRAC_MAX_PRATE),
 	GATE(SCLK_I2S0, "sclk_i2s0", "i2s0_pre", CLK_SET_RATE_PARENT,
 			RK2928_CLKGATE_CON(4), 6, GFLAGS),
 
@@ -377,7 +380,7 @@ enum rk3128_plls {
 	COMPOSITE_FRACMUX(0, "i2s1_frac", "i2s1_src", CLK_SET_RATE_PARENT,
 			RK2928_CLKSEL_CON(7), 0,
 			RK2928_CLKGATE_CON(0), 10, GFLAGS,
-			&rk3128_i2s1_fracmux),
+			&rk3128_i2s1_fracmux, RK3128_I2S_FRAC_MAX_PRATE),
 	GATE(SCLK_I2S1, "sclk_i2s1", "i2s1_pre", CLK_SET_RATE_PARENT,
 			RK2928_CLKGATE_CON(0), 14, GFLAGS),
 	COMPOSITE_NODIV(SCLK_I2S_OUT, "i2s_out", mux_i2s_out_p, 0,
@@ -390,7 +393,7 @@ enum rk3128_plls {
 	COMPOSITE_FRACMUX(0, "spdif_frac", "sclk_spdif_src", CLK_SET_RATE_PARENT,
 			RK2928_CLKSEL_CON(20), 0,
 			RK2928_CLKGATE_CON(2), 12, GFLAGS,
-			&rk3128_spdif_fracmux),
+			&rk3128_spdif_fracmux, RK3128_SPDIF_FRAC_MAX_PRATE),
 
 	GATE(0, "jtag", "ext_jtag", CLK_IGNORE_UNUSED,
 			RK2928_CLKGATE_CON(1), 3, GFLAGS),
@@ -427,15 +430,15 @@ enum rk3128_plls {
 	COMPOSITE_FRACMUX(0, "uart0_frac", "uart0_src", CLK_SET_RATE_PARENT,
 			RK2928_CLKSEL_CON(17), 0,
 			RK2928_CLKGATE_CON(1), 9, GFLAGS,
-			&rk3128_uart0_fracmux),
+			&rk3128_uart0_fracmux, RK3128_UART_FRAC_MAX_PRATE),
 	COMPOSITE_FRACMUX(0, "uart1_frac", "uart1_src", CLK_SET_RATE_PARENT,
 			RK2928_CLKSEL_CON(18), 0,
 			RK2928_CLKGATE_CON(1), 11, GFLAGS,
-			&rk3128_uart1_fracmux),
+			&rk3128_uart1_fracmux, RK3128_UART_FRAC_MAX_PRATE),
 	COMPOSITE_FRACMUX(0, "uart2_frac", "uart2_src", CLK_SET_RATE_PARENT,
 			RK2928_CLKSEL_CON(19), 0,
 			RK2928_CLKGATE_CON(1), 13, GFLAGS,
-			&rk3128_uart2_fracmux),
+			&rk3128_uart2_fracmux, RK3128_UART_FRAC_MAX_PRATE),
 
 	COMPOSITE(SCLK_MAC_SRC, "sclk_gmac_src", mux_pll_src_3plls_p, 0,
 			RK2928_CLKSEL_CON(5), 6, 2, MFLAGS, 0, 5, DFLAGS,
diff --git a/drivers/clk/rockchip/clk-rk3188.c b/drivers/clk/rockchip/clk-rk3188.c
index 5ecf28854876..985d3a0153d7 100644
--- a/drivers/clk/rockchip/clk-rk3188.c
+++ b/drivers/clk/rockchip/clk-rk3188.c
@@ -22,6 +22,10 @@
 
 #define RK3066_GRF_SOC_STATUS	0x15c
 #define RK3188_GRF_SOC_STATUS	0xac
+#define RK3188_UART_FRAC_MAX_PRATE	600000000
+#define RK3188_I2S_FRAC_MAX_PRATE	600000000
+#define RK3188_SPDIF_FRAC_MAX_PRATE	600000000
+#define RK3188_HSADC_FRAC_MAX_PRATE	300000000
 
 enum rk3188_plls {
 	apll, cpll, dpll, gpll,
@@ -371,7 +375,7 @@ enum rk3188_plls {
 	COMPOSITE_FRACMUX(0, "hsadc_frac", "hsadc_src", 0,
 			RK2928_CLKSEL_CON(23), 0,
 			RK2928_CLKGATE_CON(2), 7, GFLAGS,
-			&common_hsadc_out_fracmux),
+			&common_hsadc_out_fracmux, RK3188_HSADC_FRAC_MAX_PRATE),
 	INVERTER(SCLK_HSADC, "sclk_hsadc", "sclk_hsadc_out",
 			RK2928_CLKSEL_CON(22), 7, IFLAGS),
 
@@ -385,7 +389,7 @@ enum rk3188_plls {
 	COMPOSITE_FRACMUX(0, "spdif_frac", "spdif_pre", CLK_SET_RATE_PARENT,
 			RK2928_CLKSEL_CON(9), 0,
 			RK2928_CLKGATE_CON(0), 14, GFLAGS,
-			&common_spdif_fracmux),
+			&common_spdif_fracmux, RK3188_SPDIF_FRAC_MAX_PRATE),
 
 	/*
 	 * Clock-Architecture Diagram 4
@@ -419,28 +423,28 @@ enum rk3188_plls {
 	COMPOSITE_FRACMUX(0, "uart0_frac", "uart0_pre", 0,
 			RK2928_CLKSEL_CON(17), 0,
 			RK2928_CLKGATE_CON(1), 9, GFLAGS,
-			&common_uart0_fracmux),
+			&common_uart0_fracmux, RK3188_UART_FRAC_MAX_PRATE),
 	COMPOSITE_NOMUX(0, "uart1_pre", "uart_src", 0,
 			RK2928_CLKSEL_CON(14), 0, 7, DFLAGS,
 			RK2928_CLKGATE_CON(1), 10, GFLAGS),
 	COMPOSITE_FRACMUX(0, "uart1_frac", "uart1_pre", 0,
 			RK2928_CLKSEL_CON(18), 0,
 			RK2928_CLKGATE_CON(1), 11, GFLAGS,
-			&common_uart1_fracmux),
+			&common_uart1_fracmux, RK3188_UART_FRAC_MAX_PRATE),
 	COMPOSITE_NOMUX(0, "uart2_pre", "uart_src", 0,
 			RK2928_CLKSEL_CON(15), 0, 7, DFLAGS,
 			RK2928_CLKGATE_CON(1), 12, GFLAGS),
 	COMPOSITE_FRACMUX(0, "uart2_frac", "uart2_pre", 0,
 			RK2928_CLKSEL_CON(19), 0,
 			RK2928_CLKGATE_CON(1), 13, GFLAGS,
-			&common_uart2_fracmux),
+			&common_uart2_fracmux, RK3188_UART_FRAC_MAX_PRATE),
 	COMPOSITE_NOMUX(0, "uart3_pre", "uart_src", 0,
 			RK2928_CLKSEL_CON(16), 0, 7, DFLAGS,
 			RK2928_CLKGATE_CON(1), 14, GFLAGS),
 	COMPOSITE_FRACMUX(0, "uart3_frac", "uart3_pre", 0,
 			RK2928_CLKSEL_CON(20), 0,
 			RK2928_CLKGATE_CON(1), 15, GFLAGS,
-			&common_uart3_fracmux),
+			&common_uart3_fracmux, RK3188_UART_FRAC_MAX_PRATE),
 
 	GATE(SCLK_JTAG, "jtag", "ext_jtag", 0, RK2928_CLKGATE_CON(1), 3, GFLAGS),
 
@@ -626,21 +630,21 @@ enum rk3188_plls {
 	COMPOSITE_FRACMUX(0, "i2s0_frac", "i2s0_pre", 0,
 			RK2928_CLKSEL_CON(6), 0,
 			RK2928_CLKGATE_CON(0), 8, GFLAGS,
-			&rk3066a_i2s0_fracmux),
+			&rk3066a_i2s0_fracmux, RK3188_I2S_FRAC_MAX_PRATE),
 	COMPOSITE_NOMUX(0, "i2s1_pre", "i2s_src", 0,
 			RK2928_CLKSEL_CON(3), 0, 7, DFLAGS,
 			RK2928_CLKGATE_CON(0), 9, GFLAGS),
 	COMPOSITE_FRACMUX(0, "i2s1_frac", "i2s1_pre", 0,
 			RK2928_CLKSEL_CON(7), 0,
 			RK2928_CLKGATE_CON(0), 10, GFLAGS,
-			&rk3066a_i2s1_fracmux),
+			&rk3066a_i2s1_fracmux, RK3188_I2S_FRAC_MAX_PRATE),
 	COMPOSITE_NOMUX(0, "i2s2_pre", "i2s_src", 0,
 			RK2928_CLKSEL_CON(4), 0, 7, DFLAGS,
 			RK2928_CLKGATE_CON(0), 11, GFLAGS),
 	COMPOSITE_FRACMUX(0, "i2s2_frac", "i2s2_pre", 0,
 			RK2928_CLKSEL_CON(8), 0,
 			RK2928_CLKGATE_CON(0), 12, GFLAGS,
-			&rk3066a_i2s2_fracmux),
+			&rk3066a_i2s2_fracmux, RK3188_I2S_FRAC_MAX_PRATE),
 
 	GATE(HCLK_I2S1, "hclk_i2s1", "hclk_cpu", 0, RK2928_CLKGATE_CON(7), 3, GFLAGS),
 	GATE(HCLK_I2S2, "hclk_i2s2", "hclk_cpu", 0, RK2928_CLKGATE_CON(7), 4, GFLAGS),
@@ -734,7 +738,7 @@ enum rk3188_plls {
 	COMPOSITE_FRACMUX(0, "i2s0_frac", "i2s0_pre", CLK_SET_RATE_PARENT,
 			RK2928_CLKSEL_CON(7), 0,
 			RK2928_CLKGATE_CON(0), 10, GFLAGS,
-			&rk3188_i2s0_fracmux),
+			&rk3188_i2s0_fracmux, RK3188_I2S_FRAC_MAX_PRATE),
 
 	GATE(0, "hclk_imem0", "hclk_cpu", 0, RK2928_CLKGATE_CON(4), 14, GFLAGS),
 	GATE(0, "hclk_imem1", "hclk_cpu", 0, RK2928_CLKGATE_CON(4), 15, GFLAGS),
diff --git a/drivers/clk/rockchip/clk-rk3228.c b/drivers/clk/rockchip/clk-rk3228.c
index 7af48184b022..35e3be34f2f8 100644
--- a/drivers/clk/rockchip/clk-rk3228.c
+++ b/drivers/clk/rockchip/clk-rk3228.c
@@ -23,6 +23,10 @@
 
 #define RK3228_GRF_SOC_STATUS0	0x480
 
+#define RK3228_UART_FRAC_MAX_PRATE	600000000
+#define RK3228_SPDIF_FRAC_MAX_PRATE	600000000
+#define RK3228_I2S_FRAC_MAX_PRATE	600000000
+
 enum rk3228_plls {
 	apll, dpll, cpll, gpll,
 };
@@ -428,7 +432,7 @@ enum rk3228_plls {
 	COMPOSITE_FRACMUX(0, "i2s0_frac", "i2s0_src", CLK_SET_RATE_PARENT,
 			RK2928_CLKSEL_CON(8), 0,
 			RK2928_CLKGATE_CON(0), 4, GFLAGS,
-			&rk3228_i2s0_fracmux),
+			&rk3228_i2s0_fracmux, RK3228_I2S_FRAC_MAX_PRATE),
 	GATE(SCLK_I2S0, "sclk_i2s0", "i2s0_pre", CLK_SET_RATE_PARENT,
 			RK2928_CLKGATE_CON(0), 5, GFLAGS),
 
@@ -438,7 +442,7 @@ enum rk3228_plls {
 	COMPOSITE_FRACMUX(0, "i2s1_frac", "i2s1_src", CLK_SET_RATE_PARENT,
 			RK2928_CLKSEL_CON(7), 0,
 			RK2928_CLKGATE_CON(0), 11, GFLAGS,
-			&rk3228_i2s1_fracmux),
+			&rk3228_i2s1_fracmux, RK3228_I2S_FRAC_MAX_PRATE),
 	GATE(SCLK_I2S1, "sclk_i2s1", "i2s1_pre", CLK_SET_RATE_PARENT,
 			RK2928_CLKGATE_CON(0), 14, GFLAGS),
 	COMPOSITE_NODIV(SCLK_I2S_OUT, "i2s_out", mux_i2s_out_p, 0,
@@ -451,7 +455,7 @@ enum rk3228_plls {
 	COMPOSITE_FRACMUX(0, "i2s2_frac", "i2s2_src", CLK_SET_RATE_PARENT,
 			RK2928_CLKSEL_CON(30), 0,
 			RK2928_CLKGATE_CON(0), 8, GFLAGS,
-			&rk3228_i2s2_fracmux),
+			&rk3228_i2s2_fracmux, RK3228_I2S_FRAC_MAX_PRATE),
 	GATE(SCLK_I2S2, "sclk_i2s2", "i2s2_pre", CLK_SET_RATE_PARENT,
 			RK2928_CLKGATE_CON(0), 9, GFLAGS),
 
@@ -461,7 +465,7 @@ enum rk3228_plls {
 	COMPOSITE_FRACMUX(0, "spdif_frac", "sclk_spdif_src", CLK_SET_RATE_PARENT,
 			RK2928_CLKSEL_CON(20), 0,
 			RK2928_CLKGATE_CON(2), 12, GFLAGS,
-			&rk3228_spdif_fracmux),
+			&rk3228_spdif_fracmux, RK3228_SPDIF_FRAC_MAX_PRATE),
 
 	GATE(0, "jtag", "ext_jtag", CLK_IGNORE_UNUSED,
 			RK2928_CLKGATE_CON(1), 3, GFLAGS),
@@ -503,15 +507,15 @@ enum rk3228_plls {
 	COMPOSITE_FRACMUX(0, "uart0_frac", "uart0_src", CLK_SET_RATE_PARENT,
 			RK2928_CLKSEL_CON(17), 0,
 			RK2928_CLKGATE_CON(1), 9, GFLAGS,
-			&rk3228_uart0_fracmux),
+			&rk3228_uart0_fracmux, RK3228_UART_FRAC_MAX_PRATE),
 	COMPOSITE_FRACMUX(0, "uart1_frac", "uart1_src", CLK_SET_RATE_PARENT,
 			RK2928_CLKSEL_CON(18), 0,
 			RK2928_CLKGATE_CON(1), 11, GFLAGS,
-			&rk3228_uart1_fracmux),
+			&rk3228_uart1_fracmux, RK3228_UART_FRAC_MAX_PRATE),
 	COMPOSITE_FRACMUX(0, "uart2_frac", "uart2_src", CLK_SET_RATE_PARENT,
 			RK2928_CLKSEL_CON(19), 0,
 			RK2928_CLKGATE_CON(1), 13, GFLAGS,
-			&rk3228_uart2_fracmux),
+			&rk3228_uart2_fracmux, RK3228_UART_FRAC_MAX_PRATE),
 
 	COMPOSITE(SCLK_NANDC, "sclk_nandc", mux_pll_src_2plls_p, 0,
 			RK2928_CLKSEL_CON(2), 14, 1, MFLAGS, 8, 5, DFLAGS,
diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c
index 5a67b7869960..8bee8ee51354 100644
--- a/drivers/clk/rockchip/clk-rk3288.c
+++ b/drivers/clk/rockchip/clk-rk3288.c
@@ -22,6 +22,9 @@
 
 #define RK3288_GRF_SOC_CON(x)	(0x244 + x * 4)
 #define RK3288_GRF_SOC_STATUS1	0x284
+#define RK3288_UART_FRAC_MAX_PRATE	600000000
+#define RK3288_I2S_FRAC_MAX_PRATE	600000000
+#define RK3288_SPDIF_FRAC_MAX_PRATE	600000000
 
 enum rk3288_plls {
 	apll, dpll, cpll, gpll, npll,
@@ -366,7 +369,7 @@ enum rk3288_plls {
 	COMPOSITE_FRACMUX(0, "i2s_frac", "i2s_src", CLK_SET_RATE_PARENT,
 			RK3288_CLKSEL_CON(8), 0,
 			RK3288_CLKGATE_CON(4), 2, GFLAGS,
-			&rk3288_i2s_fracmux),
+			&rk3288_i2s_fracmux, RK3288_I2S_FRAC_MAX_PRATE),
 	COMPOSITE_NODIV(SCLK_I2S0_OUT, "i2s0_clkout", mux_i2s_clkout_p, 0,
 			RK3288_CLKSEL_CON(4), 12, 1, MFLAGS,
 			RK3288_CLKGATE_CON(4), 0, GFLAGS),
@@ -381,7 +384,7 @@ enum rk3288_plls {
 	COMPOSITE_FRACMUX(0, "spdif_frac", "spdif_src", CLK_SET_RATE_PARENT,
 			RK3288_CLKSEL_CON(9), 0,
 			RK3288_CLKGATE_CON(4), 5, GFLAGS,
-			&rk3288_spdif_fracmux),
+			&rk3288_spdif_fracmux, RK3288_SPDIF_FRAC_MAX_PRATE),
 	GATE(SCLK_SPDIF, "sclk_spdif", "spdif_mux", CLK_SET_RATE_PARENT,
 			RK3288_CLKGATE_CON(4), 6, GFLAGS),
 	COMPOSITE_NOMUX(0, "spdif_8ch_pre", "spdif_src", CLK_SET_RATE_PARENT,
@@ -390,7 +393,7 @@ enum rk3288_plls {
 	COMPOSITE_FRACMUX(0, "spdif_8ch_frac", "spdif_8ch_pre", CLK_SET_RATE_PARENT,
 			RK3288_CLKSEL_CON(41), 0,
 			RK3288_CLKGATE_CON(4), 8, GFLAGS,
-			&rk3288_spdif_8ch_fracmux),
+			&rk3288_spdif_8ch_fracmux, RK3288_SPDIF_FRAC_MAX_PRATE),
 	GATE(SCLK_SPDIF8CH, "sclk_spdif_8ch", "spdif_8ch_mux", CLK_SET_RATE_PARENT,
 			RK3288_CLKGATE_CON(4), 9, GFLAGS),
 
@@ -593,7 +596,7 @@ enum rk3288_plls {
 	COMPOSITE_FRACMUX(0, "uart0_frac", "uart0_src", CLK_SET_RATE_PARENT,
 			RK3288_CLKSEL_CON(17), 0,
 			RK3288_CLKGATE_CON(1), 9, GFLAGS,
-			&rk3288_uart0_fracmux),
+			&rk3288_uart0_fracmux, RK3288_UART_FRAC_MAX_PRATE),
 	MUX(0, "uart_src", mux_pll_src_cpll_gpll_p, 0,
 			RK3288_CLKSEL_CON(13), 15, 1, MFLAGS),
 	COMPOSITE_NOMUX(0, "uart1_src", "uart_src", 0,
@@ -602,28 +605,28 @@ enum rk3288_plls {
 	COMPOSITE_FRACMUX(0, "uart1_frac", "uart1_src", CLK_SET_RATE_PARENT,
 			RK3288_CLKSEL_CON(18), 0,
 			RK3288_CLKGATE_CON(1), 11, GFLAGS,
-			&rk3288_uart1_fracmux),
+			&rk3288_uart1_fracmux, RK3288_UART_FRAC_MAX_PRATE),
 	COMPOSITE_NOMUX(0, "uart2_src", "uart_src", 0,
 			RK3288_CLKSEL_CON(15), 0, 7, DFLAGS,
 			RK3288_CLKGATE_CON(1), 12, GFLAGS),
 	COMPOSITE_FRACMUX(0, "uart2_frac", "uart2_src", CLK_SET_RATE_PARENT,
 			RK3288_CLKSEL_CON(19), 0,
 			RK3288_CLKGATE_CON(1), 13, GFLAGS,
-			&rk3288_uart2_fracmux),
+			&rk3288_uart2_fracmux, RK3288_UART_FRAC_MAX_PRATE),
 	COMPOSITE_NOMUX(0, "uart3_src", "uart_src", 0,
 			RK3288_CLKSEL_CON(16), 0, 7, DFLAGS,
 			RK3288_CLKGATE_CON(1), 14, GFLAGS),
 	COMPOSITE_FRACMUX(0, "uart3_frac", "uart3_src", CLK_SET_RATE_PARENT,
 			RK3288_CLKSEL_CON(20), 0,
 			RK3288_CLKGATE_CON(1), 15, GFLAGS,
-			&rk3288_uart3_fracmux),
+			&rk3288_uart3_fracmux, RK3288_UART_FRAC_MAX_PRATE),
 	COMPOSITE_NOMUX(0, "uart4_src", "uart_src", 0,
 			RK3288_CLKSEL_CON(3), 0, 7, DFLAGS,
 			RK3288_CLKGATE_CON(2), 12, GFLAGS),
 	COMPOSITE_FRACMUX(0, "uart4_frac", "uart4_src", CLK_SET_RATE_PARENT,
 			RK3288_CLKSEL_CON(7), 0,
 			RK3288_CLKGATE_CON(2), 13, GFLAGS,
-			&rk3288_uart4_fracmux),
+			&rk3288_uart4_fracmux, RK3288_UART_FRAC_MAX_PRATE),
 
 	COMPOSITE(0, "mac_pll_src", mux_pll_src_npll_cpll_gpll_p, 0,
 			RK3288_CLKSEL_CON(21), 0, 2, MFLAGS, 8, 5, DFLAGS,
diff --git a/drivers/clk/rockchip/clk-rk3328.c b/drivers/clk/rockchip/clk-rk3328.c
index 65ab5c2f48b0..8ebf0c46e17a 100644
--- a/drivers/clk/rockchip/clk-rk3328.c
+++ b/drivers/clk/rockchip/clk-rk3328.c
@@ -24,6 +24,9 @@
 #define RK3328_GRF_SOC_STATUS0		0x480
 #define RK3328_GRF_MAC_CON1		0x904
 #define RK3328_GRF_MAC_CON2		0x908
+#define RK3328_I2S_FRAC_MAX_PRATE       600000000
+#define RK3328_UART_FRAC_MAX_PRATE	600000000
+#define RK3328_SPDIF_FRAC_MAX_PRATE	600000000
 
 enum rk3328_plls {
 	apll, dpll, cpll, gpll, npll,
@@ -380,7 +383,7 @@ enum rk3328_plls {
 	COMPOSITE_FRACMUX(0, "clk_i2s0_frac", "clk_i2s0_div", CLK_SET_RATE_PARENT,
 			RK3328_CLKSEL_CON(7), 0,
 			RK3328_CLKGATE_CON(1), 2, GFLAGS,
-			&rk3328_i2s0_fracmux),
+			&rk3328_i2s0_fracmux, RK3328_I2S_FRAC_MAX_PRATE),
 	GATE(SCLK_I2S0, "clk_i2s0", "i2s0_pre", CLK_SET_RATE_PARENT,
 			RK3328_CLKGATE_CON(1), 3, GFLAGS),
 
@@ -390,7 +393,7 @@ enum rk3328_plls {
 	COMPOSITE_FRACMUX(0, "clk_i2s1_frac", "clk_i2s1_div", CLK_SET_RATE_PARENT,
 			RK3328_CLKSEL_CON(9), 0,
 			RK3328_CLKGATE_CON(1), 5, GFLAGS,
-			&rk3328_i2s1_fracmux),
+			&rk3328_i2s1_fracmux, RK3328_I2S_FRAC_MAX_PRATE),
 	GATE(SCLK_I2S1, "clk_i2s1", "i2s1_pre", CLK_SET_RATE_PARENT,
 			RK3328_CLKGATE_CON(1), 6, GFLAGS),
 	COMPOSITE_NODIV(SCLK_I2S1_OUT, "i2s1_out", mux_i2s1out_p, 0,
@@ -403,7 +406,7 @@ enum rk3328_plls {
 	COMPOSITE_FRACMUX(0, "clk_i2s2_frac", "clk_i2s2_div", CLK_SET_RATE_PARENT,
 			RK3328_CLKSEL_CON(11), 0,
 			RK3328_CLKGATE_CON(1), 9, GFLAGS,
-			&rk3328_i2s2_fracmux),
+			&rk3328_i2s2_fracmux, RK3328_I2S_FRAC_MAX_PRATE),
 	GATE(SCLK_I2S2, "clk_i2s2", "i2s2_pre", CLK_SET_RATE_PARENT,
 			RK3328_CLKGATE_CON(1), 10, GFLAGS),
 	COMPOSITE_NODIV(SCLK_I2S2_OUT, "i2s2_out", mux_i2s2out_p, 0,
@@ -416,7 +419,7 @@ enum rk3328_plls {
 	COMPOSITE_FRACMUX(0, "clk_spdif_frac", "clk_spdif_div", CLK_SET_RATE_PARENT,
 			RK3328_CLKSEL_CON(13), 0,
 			RK3328_CLKGATE_CON(1), 13, GFLAGS,
-			&rk3328_spdif_fracmux),
+			&rk3328_spdif_fracmux, RK3328_SPDIF_FRAC_MAX_PRATE),
 
 	/* PD_UART */
 	COMPOSITE(0, "clk_uart0_div", mux_2plls_u480m_p, 0,
@@ -431,15 +434,15 @@ enum rk3328_plls {
 	COMPOSITE_FRACMUX(0, "clk_uart0_frac", "clk_uart0_div", CLK_SET_RATE_PARENT,
 			RK3328_CLKSEL_CON(15), 0,
 			RK3328_CLKGATE_CON(1), 15, GFLAGS,
-			&rk3328_uart0_fracmux),
+			&rk3328_uart0_fracmux, RK3328_UART_FRAC_MAX_PRATE),
 	COMPOSITE_FRACMUX(0, "clk_uart1_frac", "clk_uart1_div", CLK_SET_RATE_PARENT,
 			RK3328_CLKSEL_CON(17), 0,
 			RK3328_CLKGATE_CON(2), 1, GFLAGS,
-			&rk3328_uart1_fracmux),
+			&rk3328_uart1_fracmux, RK3328_UART_FRAC_MAX_PRATE),
 	COMPOSITE_FRACMUX(0, "clk_uart2_frac", "clk_uart2_div", CLK_SET_RATE_PARENT,
 			RK3328_CLKSEL_CON(19), 0,
 			RK3328_CLKGATE_CON(2), 3, GFLAGS,
-			&rk3328_uart2_fracmux),
+			&rk3328_uart2_fracmux, RK3328_UART_FRAC_MAX_PRATE),
 
 	/*
 	 * Clock-Architecture Diagram 4
diff --git a/drivers/clk/rockchip/clk-rk3368.c b/drivers/clk/rockchip/clk-rk3368.c
index 7c4d242f19c1..67c2da5e7d61 100644
--- a/drivers/clk/rockchip/clk-rk3368.c
+++ b/drivers/clk/rockchip/clk-rk3368.c
@@ -20,6 +20,9 @@
 #include "clk.h"
 
 #define RK3368_GRF_SOC_STATUS0	0x480
+#define RK3368_I2S_FRAC_MAX_PRATE       600000000
+#define RK3368_UART_FRAC_MAX_PRATE	600000000
+#define RK3368_SPDIF_FRAC_MAX_PRATE	600000000
 
 enum rk3368_plls {
 	apllb, aplll, dpll, cpll, gpll, npll,
@@ -376,7 +379,7 @@ enum rk3368_plls {
 	COMPOSITE_FRACMUX(0, "i2s_8ch_frac", "i2s_8ch_src", CLK_SET_RATE_PARENT,
 			  RK3368_CLKSEL_CON(28), 0,
 			  RK3368_CLKGATE_CON(6), 2, GFLAGS,
-			  &rk3368_i2s_8ch_fracmux),
+			  &rk3368_i2s_8ch_fracmux, RK3368_I2S_FRAC_MAX_PRATE),
 	COMPOSITE_NODIV(SCLK_I2S_8CH_OUT, "i2s_8ch_clkout", mux_i2s_8ch_clkout_p, 0,
 			RK3368_CLKSEL_CON(27), 15, 1, MFLAGS,
 			RK3368_CLKGATE_CON(6), 0, GFLAGS),
@@ -388,7 +391,7 @@ enum rk3368_plls {
 	COMPOSITE_FRACMUX(0, "spdif_8ch_frac", "spdif_8ch_src", CLK_SET_RATE_PARENT,
 			  RK3368_CLKSEL_CON(32), 0,
 			  RK3368_CLKGATE_CON(6), 5, GFLAGS,
-			  &rk3368_spdif_8ch_fracmux),
+			  &rk3368_spdif_8ch_fracmux, RK3368_SPDIF_FRAC_MAX_PRATE),
 	GATE(SCLK_SPDIF_8CH, "sclk_spdif_8ch", "spdif_8ch_pre", CLK_SET_RATE_PARENT,
 	     RK3368_CLKGATE_CON(6), 6, GFLAGS),
 	COMPOSITE(0, "i2s_2ch_src", mux_pll_src_cpll_gpll_p, 0,
@@ -397,7 +400,7 @@ enum rk3368_plls {
 	COMPOSITE_FRACMUX(0, "i2s_2ch_frac", "i2s_2ch_src", CLK_SET_RATE_PARENT,
 			  RK3368_CLKSEL_CON(54), 0,
 			  RK3368_CLKGATE_CON(5), 14, GFLAGS,
-			  &rk3368_i2s_2ch_fracmux),
+			  &rk3368_i2s_2ch_fracmux, RK3368_I2S_FRAC_MAX_PRATE),
 	GATE(SCLK_I2S_2CH, "sclk_i2s_2ch", "i2s_2ch_pre", CLK_SET_RATE_PARENT,
 	     RK3368_CLKGATE_CON(5), 15, GFLAGS),
 
@@ -598,7 +601,7 @@ enum rk3368_plls {
 	COMPOSITE_FRACMUX(0, "uart0_frac", "uart0_src", CLK_SET_RATE_PARENT,
 			  RK3368_CLKSEL_CON(34), 0,
 			  RK3368_CLKGATE_CON(2), 1, GFLAGS,
-			  &rk3368_uart0_fracmux),
+			  &rk3368_uart0_fracmux, RK3368_UART_FRAC_MAX_PRATE),
 
 	COMPOSITE_NOMUX(0, "uart1_src", "uart_src", 0,
 			RK3368_CLKSEL_CON(35), 0, 7, DFLAGS,
@@ -606,7 +609,7 @@ enum rk3368_plls {
 	COMPOSITE_FRACMUX(0, "uart1_frac", "uart1_src", CLK_SET_RATE_PARENT,
 			  RK3368_CLKSEL_CON(36), 0,
 			  RK3368_CLKGATE_CON(2), 3, GFLAGS,
-			  &rk3368_uart1_fracmux),
+			  &rk3368_uart1_fracmux, RK3368_UART_FRAC_MAX_PRATE),
 
 	COMPOSITE_NOMUX(0, "uart3_src", "uart_src", 0,
 			RK3368_CLKSEL_CON(39), 0, 7, DFLAGS,
@@ -614,7 +617,7 @@ enum rk3368_plls {
 	COMPOSITE_FRACMUX(0, "uart3_frac", "uart3_src", CLK_SET_RATE_PARENT,
 			  RK3368_CLKSEL_CON(40), 0,
 			  RK3368_CLKGATE_CON(2), 7, GFLAGS,
-			  &rk3368_uart3_fracmux),
+			  &rk3368_uart3_fracmux, RK3368_UART_FRAC_MAX_PRATE),
 
 	COMPOSITE_NOMUX(0, "uart4_src", "uart_src", 0,
 			RK3368_CLKSEL_CON(41), 0, 7, DFLAGS,
@@ -622,7 +625,7 @@ enum rk3368_plls {
 	COMPOSITE_FRACMUX(0, "uart4_frac", "uart4_src", CLK_SET_RATE_PARENT,
 			  RK3368_CLKSEL_CON(42), 0,
 			  RK3368_CLKGATE_CON(2), 9, GFLAGS,
-			  &rk3368_uart4_fracmux),
+			  &rk3368_uart4_fracmux, RK3368_UART_FRAC_MAX_PRATE),
 
 	COMPOSITE(0, "mac_pll_src", mux_pll_src_npll_cpll_gpll_p, 0,
 			RK3368_CLKSEL_CON(43), 6, 2, MFLAGS, 0, 5, DFLAGS,
diff --git a/drivers/clk/rockchip/clk-rk3399.c b/drivers/clk/rockchip/clk-rk3399.c
index 5a628148f3f0..1d81382bd3e0 100644
--- a/drivers/clk/rockchip/clk-rk3399.c
+++ b/drivers/clk/rockchip/clk-rk3399.c
@@ -21,6 +21,12 @@
 #include <dt-bindings/clock/rk3399-cru.h>
 #include "clk.h"
 
+#define RK3399_I2S_FRAC_MAX_PRATE       600000000
+#define RK3399_UART_FRAC_MAX_PRATE	600000000
+#define RK3399_SPDIF_FRAC_MAX_PRATE	600000000
+#define RK3399_VOP_FRAC_MAX_PRATE	600000000
+#define RK3399_WIFI_FRAC_MAX_PRATE	600000000
+
 enum rk3399_plls {
 	lpll, bpll, dpll, cpll, gpll, npll, vpll,
 };
@@ -590,7 +596,7 @@ enum rk3399_pmu_plls {
 	COMPOSITE_FRACMUX(0, "clk_spdif_frac", "clk_spdif_div", 0,
 			RK3399_CLKSEL_CON(99), 0,
 			RK3399_CLKGATE_CON(8), 14, GFLAGS,
-			&rk3399_spdif_fracmux),
+			&rk3399_spdif_fracmux, RK3399_SPDIF_FRAC_MAX_PRATE),
 	GATE(SCLK_SPDIF_8CH, "clk_spdif", "clk_spdif_mux", CLK_SET_RATE_PARENT,
 			RK3399_CLKGATE_CON(8), 15, GFLAGS),
 
@@ -604,7 +610,7 @@ enum rk3399_pmu_plls {
 	COMPOSITE_FRACMUX(0, "clk_i2s0_frac", "clk_i2s0_div", 0,
 			RK3399_CLKSEL_CON(96), 0,
 			RK3399_CLKGATE_CON(8), 4, GFLAGS,
-			&rk3399_i2s0_fracmux),
+			&rk3399_i2s0_fracmux, RK3399_I2S_FRAC_MAX_PRATE),
 	GATE(SCLK_I2S0_8CH, "clk_i2s0", "clk_i2s0_mux", CLK_SET_RATE_PARENT,
 			RK3399_CLKGATE_CON(8), 5, GFLAGS),
 
@@ -614,7 +620,7 @@ enum rk3399_pmu_plls {
 	COMPOSITE_FRACMUX(0, "clk_i2s1_frac", "clk_i2s1_div", 0,
 			RK3399_CLKSEL_CON(97), 0,
 			RK3399_CLKGATE_CON(8), 7, GFLAGS,
-			&rk3399_i2s1_fracmux),
+			&rk3399_i2s1_fracmux, RK3399_I2S_FRAC_MAX_PRATE),
 	GATE(SCLK_I2S1_8CH, "clk_i2s1", "clk_i2s1_mux", CLK_SET_RATE_PARENT,
 			RK3399_CLKGATE_CON(8), 8, GFLAGS),
 
@@ -624,7 +630,7 @@ enum rk3399_pmu_plls {
 	COMPOSITE_FRACMUX(0, "clk_i2s2_frac", "clk_i2s2_div", 0,
 			RK3399_CLKSEL_CON(98), 0,
 			RK3399_CLKGATE_CON(8), 10, GFLAGS,
-			&rk3399_i2s2_fracmux),
+			&rk3399_i2s2_fracmux, RK3399_I2S_FRAC_MAX_PRATE),
 	GATE(SCLK_I2S2_8CH, "clk_i2s2", "clk_i2s2_mux", CLK_SET_RATE_PARENT,
 			RK3399_CLKGATE_CON(8), 11, GFLAGS),
 
@@ -643,7 +649,7 @@ enum rk3399_pmu_plls {
 	COMPOSITE_FRACMUX(0, "clk_uart0_frac", "clk_uart0_div", 0,
 			RK3399_CLKSEL_CON(100), 0,
 			RK3399_CLKGATE_CON(9), 1, GFLAGS,
-			&rk3399_uart0_fracmux),
+			&rk3399_uart0_fracmux, RK3399_UART_FRAC_MAX_PRATE),
 
 	MUX(0, "clk_uart_src", mux_pll_src_cpll_gpll_p, 0,
 			RK3399_CLKSEL_CON(33), 15, 1, MFLAGS),
@@ -653,7 +659,7 @@ enum rk3399_pmu_plls {
 	COMPOSITE_FRACMUX(0, "clk_uart1_frac", "clk_uart1_div", 0,
 			RK3399_CLKSEL_CON(101), 0,
 			RK3399_CLKGATE_CON(9), 3, GFLAGS,
-			&rk3399_uart1_fracmux),
+			&rk3399_uart1_fracmux, RK3399_UART_FRAC_MAX_PRATE),
 
 	COMPOSITE_NOMUX(0, "clk_uart2_div", "clk_uart_src", 0,
 			RK3399_CLKSEL_CON(35), 0, 7, DFLAGS,
@@ -661,7 +667,7 @@ enum rk3399_pmu_plls {
 	COMPOSITE_FRACMUX(0, "clk_uart2_frac", "clk_uart2_div", 0,
 			RK3399_CLKSEL_CON(102), 0,
 			RK3399_CLKGATE_CON(9), 5, GFLAGS,
-			&rk3399_uart2_fracmux),
+			&rk3399_uart2_fracmux, RK3399_UART_FRAC_MAX_PRATE),
 
 	COMPOSITE_NOMUX(0, "clk_uart3_div", "clk_uart_src", 0,
 			RK3399_CLKSEL_CON(36), 0, 7, DFLAGS,
@@ -669,7 +675,7 @@ enum rk3399_pmu_plls {
 	COMPOSITE_FRACMUX(0, "clk_uart3_frac", "clk_uart3_div", 0,
 			RK3399_CLKSEL_CON(103), 0,
 			RK3399_CLKGATE_CON(9), 7, GFLAGS,
-			&rk3399_uart3_fracmux),
+			&rk3399_uart3_fracmux, RK3399_UART_FRAC_MAX_PRATE),
 
 	COMPOSITE(PCLK_DDR, "pclk_ddr", mux_pll_src_cpll_gpll_p, CLK_IGNORE_UNUSED,
 			RK3399_CLKSEL_CON(6), 15, 1, MFLAGS, 8, 5, DFLAGS,
@@ -1172,7 +1178,7 @@ enum rk3399_pmu_plls {
 
 	COMPOSITE_FRACMUX_NOGATE(DCLK_VOP0_FRAC, "dclk_vop0_frac", "dclk_vop0_div", 0,
 			RK3399_CLKSEL_CON(106), 0,
-			&rk3399_dclk_vop0_fracmux),
+			&rk3399_dclk_vop0_fracmux, RK3399_VOP_FRAC_MAX_PRATE),
 
 	COMPOSITE(SCLK_VOP0_PWM, "clk_vop0_pwm", mux_pll_src_vpll_cpll_gpll_24m_p, 0,
 			RK3399_CLKSEL_CON(51), 6, 2, MFLAGS, 0, 5, DFLAGS,
@@ -1202,7 +1208,7 @@ enum rk3399_pmu_plls {
 
 	COMPOSITE_FRACMUX_NOGATE(DCLK_VOP1_FRAC, "dclk_vop1_frac", "dclk_vop1_div", 0,
 			RK3399_CLKSEL_CON(107), 0,
-			&rk3399_dclk_vop1_fracmux),
+			&rk3399_dclk_vop1_fracmux, RK3399_VOP_FRAC_MAX_PRATE),
 
 	COMPOSITE(SCLK_VOP1_PWM, "clk_vop1_pwm", mux_pll_src_vpll_cpll_gpll_24m_p, CLK_IGNORE_UNUSED,
 			RK3399_CLKSEL_CON(52), 6, 2, MFLAGS, 0, 5, DFLAGS,
@@ -1316,7 +1322,7 @@ enum rk3399_pmu_plls {
 			RK3399_CLKSEL_CON(58), 7, 1, MFLAGS),
 	COMPOSITE_FRAC(0, "clk_test_frac", "clk_test_pre", 0,
 			RK3399_CLKSEL_CON(105), 0,
-			RK3399_CLKGATE_CON(13), 9, GFLAGS),
+			RK3399_CLKGATE_CON(13), 9, GFLAGS, 0),
 
 	DIV(0, "clk_test_24m", "xin24m", 0,
 			RK3399_CLKSEL_CON(57), 6, 10, DFLAGS),
@@ -1421,7 +1427,7 @@ enum rk3399_pmu_plls {
 
 	COMPOSITE_FRACMUX_NOGATE(0, "clk_wifi_frac", "clk_wifi_div", 0,
 			RK3399_PMU_CLKSEL_CON(7), 0,
-			&rk3399_pmuclk_wifi_fracmux),
+			&rk3399_pmuclk_wifi_fracmux, RK3399_WIFI_FRAC_MAX_PRATE),
 
 	MUX(0, "clk_timer_src_pmu", mux_pll_p, CLK_IGNORE_UNUSED,
 			RK3399_PMU_CLKSEL_CON(1), 15, 1, MFLAGS),
@@ -1450,7 +1456,7 @@ enum rk3399_pmu_plls {
 	COMPOSITE_FRACMUX(0, "clk_uart4_frac", "clk_uart4_div", 0,
 			RK3399_PMU_CLKSEL_CON(6), 0,
 			RK3399_PMU_CLKGATE_CON(0), 6, GFLAGS,
-			&rk3399_uart4_pmu_fracmux),
+			&rk3399_uart4_pmu_fracmux, RK3399_UART_FRAC_MAX_PRATE),
 
 	DIV(PCLK_SRC_PMU, "pclk_pmu_src", "ppll", CLK_IGNORE_UNUSED,
 			RK3399_PMU_CLKSEL_CON(0), 0, 5, DFLAGS),
diff --git a/drivers/clk/rockchip/clk-rv1108.c b/drivers/clk/rockchip/clk-rv1108.c
index 089cb17925e5..17f78c9afb50 100644
--- a/drivers/clk/rockchip/clk-rv1108.c
+++ b/drivers/clk/rockchip/clk-rv1108.c
@@ -22,6 +22,8 @@
 #include "clk.h"
 
 #define RV1108_GRF_SOC_STATUS0	0x480
+#define RV1108_I2S_FRAC_MAX_RATE	600000000
+#define RV1108_UART_FRAC_MAX_RATE	600000000
 
 enum rv1108_plls {
 	apll, dpll, gpll,
@@ -512,7 +514,7 @@ enum rv1108_plls {
 	COMPOSITE_FRACMUX(0, "i2s0_frac", "i2s0_src", CLK_SET_RATE_PARENT,
 			RV1108_CLKSEL_CON(8), 0,
 			RV1108_CLKGATE_CON(2), 1, GFLAGS,
-			&rv1108_i2s0_fracmux),
+			&rv1108_i2s0_fracmux, RV1108_I2S_FRAC_MAX_RATE),
 	GATE(SCLK_I2S0, "sclk_i2s0", "i2s0_pre", CLK_SET_RATE_PARENT,
 			RV1108_CLKGATE_CON(2), 2, GFLAGS),
 	COMPOSITE_NODIV(0, "i2s_out", mux_i2s_out_p, 0,
@@ -525,7 +527,7 @@ enum rv1108_plls {
 	COMPOSITE_FRACMUX(0, "i2s1_frac", "i2s1_src", CLK_SET_RATE_PARENT,
 			RK2928_CLKSEL_CON(9), 0,
 			RK2928_CLKGATE_CON(2), 5, GFLAGS,
-			&rv1108_i2s1_fracmux),
+			&rv1108_i2s1_fracmux, RV1108_I2S_FRAC_MAX_RATE),
 	GATE(SCLK_I2S1, "sclk_i2s1", "i2s1_pre", CLK_SET_RATE_PARENT,
 			RV1108_CLKGATE_CON(2), 6, GFLAGS),
 
@@ -535,7 +537,7 @@ enum rv1108_plls {
 	COMPOSITE_FRACMUX(0, "i2s2_frac", "i2s2_src", CLK_SET_RATE_PARENT,
 			RV1108_CLKSEL_CON(10), 0,
 			RV1108_CLKGATE_CON(2), 9, GFLAGS,
-			&rv1108_i2s2_fracmux),
+			&rv1108_i2s2_fracmux, RV1108_I2S_FRAC_MAX_RATE),
 	GATE(SCLK_I2S2, "sclk_i2s2", "i2s2_pre", CLK_SET_RATE_PARENT,
 			RV1108_CLKGATE_CON(2), 10, GFLAGS),
 
@@ -601,15 +603,15 @@ enum rv1108_plls {
 	COMPOSITE_FRACMUX(0, "uart0_frac", "uart0_src", CLK_SET_RATE_PARENT,
 			RV1108_CLKSEL_CON(16), 0,
 			RV1108_CLKGATE_CON(3), 2, GFLAGS,
-			&rv1108_uart0_fracmux),
+			&rv1108_uart0_fracmux, RV1108_UART_FRAC_MAX_RATE),
 	COMPOSITE_FRACMUX(0, "uart1_frac", "uart1_src", CLK_SET_RATE_PARENT,
 			RV1108_CLKSEL_CON(17), 0,
 			RV1108_CLKGATE_CON(3), 4, GFLAGS,
-			&rv1108_uart1_fracmux),
+			&rv1108_uart1_fracmux, RV1108_UART_FRAC_MAX_RATE),
 	COMPOSITE_FRACMUX(0, "uart2_frac", "uart2_src", CLK_SET_RATE_PARENT,
 			RV1108_CLKSEL_CON(18), 0,
 			RV1108_CLKGATE_CON(3), 6, GFLAGS,
-			&rv1108_uart2_fracmux),
+			&rv1108_uart2_fracmux, RV1108_UART_FRAC_MAX_RATE),
 	GATE(PCLK_UART0, "pclk_uart0", "pclk_bus_pre", 0,
 			RV1108_CLKGATE_CON(13), 10, GFLAGS),
 	GATE(PCLK_UART1, "pclk_uart1", "pclk_bus_pre", 0,
diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c
index c3ad92965823..e04bf300ea0a 100644
--- a/drivers/clk/rockchip/clk.c
+++ b/drivers/clk/rockchip/clk.c
@@ -189,12 +189,26 @@ static void rockchip_fractional_approximation(struct clk_hw *hw,
 	unsigned long p_rate, p_parent_rate;
 	struct clk_hw *p_parent;
 	unsigned long scale;
+	u32 div;
 
 	p_rate = clk_hw_get_rate(clk_hw_get_parent(hw));
-	if ((rate * 20 > p_rate) && (p_rate % rate != 0)) {
+	if (((rate * 20 > p_rate) && (p_rate % rate != 0)) ||
+	    (fd->max_prate && fd->max_prate < p_rate)) {
 		p_parent = clk_hw_get_parent(clk_hw_get_parent(hw));
 		p_parent_rate = clk_hw_get_rate(p_parent);
 		*parent_rate = p_parent_rate;
+		if (fd->max_prate && p_parent_rate > fd->max_prate) {
+			div = DIV_ROUND_UP(p_parent_rate, fd->max_prate);
+			*parent_rate = p_parent_rate / div;
+		}
+
+		if (*parent_rate < rate * 20) {
+			pr_err("%s parent_rate(%ld) is low than rate(%ld)*20, fractional div is not allowed\n",
+			       clk_hw_get_name(hw), *parent_rate, rate);
+			*m = 0;
+			*n = 1;
+			return;
+		}
 	}
 
 	/*
@@ -217,7 +231,7 @@ static struct clk *rockchip_clk_register_frac_branch(
 		void __iomem *base, int muxdiv_offset, u8 div_flags,
 		int gate_offset, u8 gate_shift, u8 gate_flags,
 		unsigned long flags, struct rockchip_clk_branch *child,
-		spinlock_t *lock)
+		unsigned long max_prate, spinlock_t *lock)
 {
 	struct rockchip_clk_frac *frac;
 	struct clk *clk;
@@ -258,6 +272,7 @@ static struct clk *rockchip_clk_register_frac_branch(
 	div->nmask = GENMASK(div->nwidth - 1, 0) << div->nshift;
 	div->lock = lock;
 	div->approximation = rockchip_fractional_approximation;
+	div->max_prate = max_prate;
 	div_ops = &clk_fractional_divider_ops;
 
 	clk = clk_register_composite(NULL, name, parent_names, num_parents,
@@ -490,7 +505,7 @@ void __init rockchip_clk_register_branches(
 				list->div_flags,
 				list->gate_offset, list->gate_shift,
 				list->gate_flags, flags, list->child,
-				&ctx->lock);
+				list->max_prate, &ctx->lock);
 			break;
 		case branch_half_divider:
 			clk = rockchip_clk_register_halfdiv(list->name,
diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h
index 6b53fff4cc96..3c827ec0965c 100644
--- a/drivers/clk/rockchip/clk.h
+++ b/drivers/clk/rockchip/clk.h
@@ -415,6 +415,7 @@ struct rockchip_clk_branch {
 	u8				gate_shift;
 	u8				gate_flags;
 	struct rockchip_clk_branch	*child;
+	unsigned long			max_prate;
 };
 
 #define COMPOSITE(_id, cname, pnames, f, mo, ms, mw, mf, ds, dw,\
@@ -532,7 +533,7 @@ struct rockchip_clk_branch {
 		.gate_offset	= -1,				\
 	}
 
-#define COMPOSITE_FRAC(_id, cname, pname, f, mo, df, go, gs, gf)\
+#define COMPOSITE_FRAC(_id, cname, pname, f, mo, df, go, gs, gf, prate)\
 	{							\
 		.id		= _id,				\
 		.branch_type	= branch_fraction_divider,	\
@@ -547,9 +548,10 @@ struct rockchip_clk_branch {
 		.gate_offset	= go,				\
 		.gate_shift	= gs,				\
 		.gate_flags	= gf,				\
+		.max_prate	= prate,			\
 	}
 
-#define COMPOSITE_FRACMUX(_id, cname, pname, f, mo, df, go, gs, gf, ch) \
+#define COMPOSITE_FRACMUX(_id, cname, pname, f, mo, df, go, gs, gf, ch, prate) \
 	{							\
 		.id		= _id,				\
 		.branch_type	= branch_fraction_divider,	\
@@ -565,9 +567,10 @@ struct rockchip_clk_branch {
 		.gate_shift	= gs,				\
 		.gate_flags	= gf,				\
 		.child		= ch,				\
+		.max_prate	= prate,			\
 	}
 
-#define COMPOSITE_FRACMUX_NOGATE(_id, cname, pname, f, mo, df, ch) \
+#define COMPOSITE_FRACMUX_NOGATE(_id, cname, pname, f, mo, df, ch, prate) \
 	{							\
 		.id		= _id,				\
 		.branch_type	= branch_fraction_divider,	\
@@ -581,6 +584,7 @@ struct rockchip_clk_branch {
 		.div_flags	= df,				\
 		.gate_offset	= -1,				\
 		.child		= ch,				\
+		.max_prate	= prate,			\
 	}
 
 #define COMPOSITE_DDRCLK(_id, cname, pnames, f, mo, ms, mw,	\
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index b7cf80a71293..b0a65fac1779 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -593,6 +593,7 @@ struct clk_hw *clk_hw_register_fixed_factor(struct device *dev,
  * @mwidth:	width of the numerator bit field
  * @nshift:	shift to the denominator bit field
  * @nwidth:	width of the denominator bit field
+ * @max_parent:	the maximum frequency of fractional divider parent clock
  * @lock:	register lock
  *
  * Clock with adjustable fractional divider affecting its output frequency.
@@ -613,6 +614,7 @@ struct clk_fractional_divider {
 	u8		nwidth;
 	u32		nmask;
 	u8		flags;
+	unsigned long	max_prate;
 	void		(*approximation)(struct clk_hw *hw,
 				unsigned long rate, unsigned long *parent_rate,
 				unsigned long *m, unsigned long *n);
-- 
1.9.1




^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v1 2/6] clk: rockchip: fix up the frac clk get rate error
  2019-04-03  9:42 [PATCH v1 0/6] clk: rockchip: Support for some new features Elaine Zhang
  2019-04-03  9:42 ` [PATCH v1 1/6] clk: rockchip: Add supprot to limit input rate for fractional divider Elaine Zhang
@ 2019-04-03  9:42 ` Elaine Zhang
  2019-04-03  9:42 ` [PATCH v1 3/6] clk: rockchip: add a COMPOSITE_DIV_OFFSET clock-type Elaine Zhang
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 16+ messages in thread
From: Elaine Zhang @ 2019-04-03  9:42 UTC (permalink / raw)
  To: heiko
  Cc: mturquette, sboyd, linux-clk, linux-arm-kernel, linux-rockchip,
	linux-kernel, xxx, xf, huangtao, Elaine Zhang

support fractional divider with only one level parent clock

Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com>
---
 drivers/clk/rockchip/clk.c | 19 ++++++++++++-------
 1 file changed, 12 insertions(+), 7 deletions(-)

diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c
index e04bf300ea0a..0256a99f06f3 100644
--- a/drivers/clk/rockchip/clk.c
+++ b/drivers/clk/rockchip/clk.c
@@ -195,16 +195,21 @@ static void rockchip_fractional_approximation(struct clk_hw *hw,
 	if (((rate * 20 > p_rate) && (p_rate % rate != 0)) ||
 	    (fd->max_prate && fd->max_prate < p_rate)) {
 		p_parent = clk_hw_get_parent(clk_hw_get_parent(hw));
-		p_parent_rate = clk_hw_get_rate(p_parent);
-		*parent_rate = p_parent_rate;
-		if (fd->max_prate && p_parent_rate > fd->max_prate) {
-			div = DIV_ROUND_UP(p_parent_rate, fd->max_prate);
-			*parent_rate = p_parent_rate / div;
+		if (!p_parent) {
+			*parent_rate = p_rate;
+		} else {
+			p_parent_rate = clk_hw_get_rate(p_parent);
+			*parent_rate = p_parent_rate;
+			if (fd->max_prate && p_parent_rate > fd->max_prate) {
+				div = DIV_ROUND_UP(p_parent_rate,
+						   fd->max_prate);
+				*parent_rate = p_parent_rate / div;
+			}
 		}
 
 		if (*parent_rate < rate * 20) {
-			pr_err("%s parent_rate(%ld) is low than rate(%ld)*20, fractional div is not allowed\n",
-			       clk_hw_get_name(hw), *parent_rate, rate);
+			pr_warn("%s p_rate(%ld) is low than rate(%ld)*20, use integer or half-div\n",
+				clk_hw_get_name(hw), *parent_rate, rate);
 			*m = 0;
 			*n = 1;
 			return;
-- 
1.9.1




^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v1 3/6] clk: rockchip: add a COMPOSITE_DIV_OFFSET clock-type
  2019-04-03  9:42 [PATCH v1 0/6] clk: rockchip: Support for some new features Elaine Zhang
  2019-04-03  9:42 ` [PATCH v1 1/6] clk: rockchip: Add supprot to limit input rate for fractional divider Elaine Zhang
  2019-04-03  9:42 ` [PATCH v1 2/6] clk: rockchip: fix up the frac clk get rate error Elaine Zhang
@ 2019-04-03  9:42 ` Elaine Zhang
  2019-04-12 11:35   ` Heiko Stübner
  2019-04-03  9:42 ` [PATCH v1 4/6] clk: rockchip: add a clock-type for muxes based in the pmugrf Elaine Zhang
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 16+ messages in thread
From: Elaine Zhang @ 2019-04-03  9:42 UTC (permalink / raw)
  To: heiko
  Cc: mturquette, sboyd, linux-clk, linux-arm-kernel, linux-rockchip,
	linux-kernel, xxx, xf, huangtao, Finley Xiao, Elaine Zhang

From: Finley Xiao <finley.xiao@rock-chips.com>

The div offset of some clocks are different from their mux offset
and the COMPOSITE clock-type require that div and mux offset are
the same, so add a new COMPOSITE_DIV_OFFSET clock-type to handle that.

Signed-off-by: Finley Xiao <finley.xiao@rock-chips.com>
Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com>
---
 drivers/clk/rockchip/clk.c |  9 ++++++---
 drivers/clk/rockchip/clk.h | 23 +++++++++++++++++++++++
 2 files changed, 29 insertions(+), 3 deletions(-)

diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c
index 0256a99f06f3..0a8a694a41ab 100644
--- a/drivers/clk/rockchip/clk.c
+++ b/drivers/clk/rockchip/clk.c
@@ -46,7 +46,7 @@ static struct clk *rockchip_clk_register_branch(const char *name,
 		const char *const *parent_names, u8 num_parents,
 		void __iomem *base,
 		int muxdiv_offset, u8 mux_shift, u8 mux_width, u8 mux_flags,
-		u8 div_shift, u8 div_width, u8 div_flags,
+		int div_offset, u8 div_shift, u8 div_width, u8 div_flags,
 		struct clk_div_table *div_table, int gate_offset,
 		u8 gate_shift, u8 gate_flags, unsigned long flags,
 		spinlock_t *lock)
@@ -95,7 +95,10 @@ static struct clk *rockchip_clk_register_branch(const char *name,
 		}
 
 		div->flags = div_flags;
-		div->reg = base + muxdiv_offset;
+		if (div_offset)
+			div->reg = base + div_offset;
+		else
+			div->reg = base + muxdiv_offset;
 		div->shift = div_shift;
 		div->width = div_width;
 		div->lock = lock;
@@ -536,7 +539,7 @@ void __init rockchip_clk_register_branches(
 				ctx->reg_base, list->muxdiv_offset,
 				list->mux_shift,
 				list->mux_width, list->mux_flags,
-				list->div_shift, list->div_width,
+				list->div_offset, list->div_shift, list->div_width,
 				list->div_flags, list->div_table,
 				list->gate_offset, list->gate_shift,
 				list->gate_flags, flags, &ctx->lock);
diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h
index 3c827ec0965c..20200a707611 100644
--- a/drivers/clk/rockchip/clk.h
+++ b/drivers/clk/rockchip/clk.h
@@ -407,6 +407,7 @@ struct rockchip_clk_branch {
 	u8				mux_shift;
 	u8				mux_width;
 	u8				mux_flags;
+	int				div_offset;
 	u8				div_shift;
 	u8				div_width;
 	u8				div_flags;
@@ -439,6 +440,28 @@ struct rockchip_clk_branch {
 		.gate_flags	= gf,				\
 	}
 
+#define COMPOSITE_DIV_OFFSET(_id, cname, pnames, f, mo, ms, mw,	\
+			     mf, do, ds, dw, df, go, gs, gf)	\
+	{							\
+		.id		= _id,				\
+		.branch_type	= branch_composite,		\
+		.name		= cname,			\
+		.parent_names	= pnames,			\
+		.num_parents	= ARRAY_SIZE(pnames),		\
+		.flags		= f,				\
+		.muxdiv_offset	= mo,				\
+		.mux_shift	= ms,				\
+		.mux_width	= mw,				\
+		.mux_flags	= mf,				\
+		.div_offset	= do,				\
+		.div_shift	= ds,				\
+		.div_width	= dw,				\
+		.div_flags	= df,				\
+		.gate_offset	= go,				\
+		.gate_shift	= gs,				\
+		.gate_flags	= gf,				\
+	}
+
 #define COMPOSITE_NOMUX(_id, cname, pname, f, mo, ds, dw, df,	\
 			go, gs, gf)				\
 	{							\
-- 
1.9.1




^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v1 4/6] clk: rockchip: add a clock-type for muxes based in the pmugrf
  2019-04-03  9:42 [PATCH v1 0/6] clk: rockchip: Support for some new features Elaine Zhang
                   ` (2 preceding siblings ...)
  2019-04-03  9:42 ` [PATCH v1 3/6] clk: rockchip: add a COMPOSITE_DIV_OFFSET clock-type Elaine Zhang
@ 2019-04-03  9:42 ` Elaine Zhang
  2019-04-12 11:45   ` Heiko Stübner
  2019-04-03  9:44 ` [PATCH v1 5/6] clk: rockchip: add pll up and down when change pll freq Elaine Zhang
  2019-04-03  9:44 ` [PATCH v1 6/6] clk: rockchip: support pll setting by auto Elaine Zhang
  5 siblings, 1 reply; 16+ messages in thread
From: Elaine Zhang @ 2019-04-03  9:42 UTC (permalink / raw)
  To: heiko
  Cc: mturquette, sboyd, linux-clk, linux-arm-kernel, linux-rockchip,
	linux-kernel, xxx, xf, huangtao, Elaine Zhang

Rockchip socs often have some tiny number of muxes not controlled from
the core clock controller but through bits set in the pmugrf.
Use MUXPMUGRF() to cover this special clock-type.

Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com>
---
 drivers/clk/rockchip/clk.c |  9 +++++++++
 drivers/clk/rockchip/clk.h | 17 +++++++++++++++++
 2 files changed, 26 insertions(+)

diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c
index 0a8a694a41ab..875412043dd7 100644
--- a/drivers/clk/rockchip/clk.c
+++ b/drivers/clk/rockchip/clk.c
@@ -415,6 +415,8 @@ struct rockchip_clk_provider * __init rockchip_clk_init(struct device_node *np,
 
 	ctx->grf = syscon_regmap_lookup_by_phandle(ctx->cru_node,
 						   "rockchip,grf");
+	ctx->pmugrf = syscon_regmap_lookup_by_phandle(ctx->cru_node,
+						   "rockchip,pmugrf");
 
 	return ctx;
 
@@ -490,6 +492,13 @@ void __init rockchip_clk_register_branches(
 				list->mux_shift, list->mux_width,
 				list->mux_flags);
 			break;
+		case branch_muxpmugrf:
+			clk = rockchip_clk_register_muxgrf(list->name,
+				list->parent_names, list->num_parents,
+				flags, ctx->pmugrf, list->muxdiv_offset,
+				list->mux_shift, list->mux_width,
+				list->mux_flags);
+			break;
 		case branch_divider:
 			if (list->div_table)
 				clk = clk_register_divider_table(NULL,
diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h
index 20200a707611..1b30346f11e1 100644
--- a/drivers/clk/rockchip/clk.h
+++ b/drivers/clk/rockchip/clk.h
@@ -234,6 +234,7 @@ struct rockchip_clk_provider {
 	struct clk_onecell_data clk_data;
 	struct device_node *cru_node;
 	struct regmap *grf;
+	struct regmap *pmugrf;
 	spinlock_t lock;
 };
 
@@ -386,6 +387,7 @@ enum rockchip_clk_branch_type {
 	branch_composite,
 	branch_mux,
 	branch_muxgrf,
+	branch_muxpmugrf,
 	branch_divider,
 	branch_fraction_divider,
 	branch_gate,
@@ -658,6 +660,21 @@ struct rockchip_clk_branch {
 		.gate_offset	= -1,				\
 	}
 
+#define MUXPMUGRF(_id, cname, pnames, f, o, s, w, mf)		\
+	{							\
+		.id		= _id,				\
+		.branch_type	= branch_muxpmugrf,		\
+		.name		= cname,			\
+		.parent_names	= pnames,			\
+		.num_parents	= ARRAY_SIZE(pnames),		\
+		.flags		= f,				\
+		.muxdiv_offset	= o,				\
+		.mux_shift	= s,				\
+		.mux_width	= w,				\
+		.mux_flags	= mf,				\
+		.gate_offset	= -1,				\
+	}
+
 #define DIV(_id, cname, pname, f, o, s, w, df)			\
 	{							\
 		.id		= _id,				\
-- 
1.9.1




^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v1 5/6] clk: rockchip: add pll up and down when change pll freq
  2019-04-03  9:42 [PATCH v1 0/6] clk: rockchip: Support for some new features Elaine Zhang
                   ` (3 preceding siblings ...)
  2019-04-03  9:42 ` [PATCH v1 4/6] clk: rockchip: add a clock-type for muxes based in the pmugrf Elaine Zhang
@ 2019-04-03  9:44 ` Elaine Zhang
  2019-04-12 12:15   ` Heiko Stübner
  2019-04-03  9:44 ` [PATCH v1 6/6] clk: rockchip: support pll setting by auto Elaine Zhang
  5 siblings, 1 reply; 16+ messages in thread
From: Elaine Zhang @ 2019-04-03  9:44 UTC (permalink / raw)
  To: heiko
  Cc: mturquette, sboyd, linux-clk, linux-arm-kernel, linux-rockchip,
	linux-kernel, xxx, xf, huangtao, Elaine Zhang

set pll sequence:
	->set pll to slow mode or other plls
	->set pll down
	->set pll params
	->set pll up
	->wait pll lock status
	->set pll to normal mode

To slove the system error:
wait_pll_lock: timeout waiting for pll to lock
pll_set_params: pll update unsucessful,
		trying to restore old params

Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com>
---
 drivers/clk/rockchip/clk-pll.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c
index dd0433d4753e..9fe1227e77e9 100644
--- a/drivers/clk/rockchip/clk-pll.c
+++ b/drivers/clk/rockchip/clk-pll.c
@@ -208,6 +208,11 @@ static int rockchip_rk3036_pll_set_params(struct rockchip_clk_pll *pll,
 		rate_change_remuxed = 1;
 	}
 
+	/* set pll power down */
+	writel(HIWORD_UPDATE(1,
+			     RK3036_PLLCON1_PWRDOWN, 13),
+	       pll->reg_base + RK3036_PLLCON(1));
+
 	/* update pll values */
 	writel_relaxed(HIWORD_UPDATE(rate->fbdiv, RK3036_PLLCON0_FBDIV_MASK,
 					  RK3036_PLLCON0_FBDIV_SHIFT) |
@@ -229,6 +234,10 @@ static int rockchip_rk3036_pll_set_params(struct rockchip_clk_pll *pll,
 	pllcon |= rate->frac << RK3036_PLLCON2_FRAC_SHIFT;
 	writel_relaxed(pllcon, pll->reg_base + RK3036_PLLCON(2));
 
+	/* set pll power up */
+	writel(HIWORD_UPDATE(0, RK3036_PLLCON1_PWRDOWN, 13),
+	       pll->reg_base + RK3036_PLLCON(1));
+
 	/* wait for the pll to lock */
 	ret = rockchip_pll_wait_lock(pll);
 	if (ret) {
@@ -685,6 +694,11 @@ static int rockchip_rk3399_pll_set_params(struct rockchip_clk_pll *pll,
 		rate_change_remuxed = 1;
 	}
 
+	/* set pll power down */
+	writel(HIWORD_UPDATE(RK3399_PLLCON3_PWRDOWN,
+			     RK3399_PLLCON3_PWRDOWN, 0),
+	       pll->reg_base + RK3399_PLLCON(3));
+
 	/* update pll values */
 	writel_relaxed(HIWORD_UPDATE(rate->fbdiv, RK3399_PLLCON0_FBDIV_MASK,
 						  RK3399_PLLCON0_FBDIV_SHIFT),
@@ -708,6 +722,11 @@ static int rockchip_rk3399_pll_set_params(struct rockchip_clk_pll *pll,
 					    RK3399_PLLCON3_DSMPD_SHIFT),
 		       pll->reg_base + RK3399_PLLCON(3));
 
+	/* set pll power up */
+	writel(HIWORD_UPDATE(0,
+			     RK3399_PLLCON3_PWRDOWN, 0),
+	       pll->reg_base + RK3399_PLLCON(3));
+
 	/* wait for the pll to lock */
 	ret = rockchip_rk3399_pll_wait_lock(pll);
 	if (ret) {
-- 
1.9.1




^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v1 6/6] clk: rockchip: support pll setting by auto
  2019-04-03  9:42 [PATCH v1 0/6] clk: rockchip: Support for some new features Elaine Zhang
                   ` (4 preceding siblings ...)
  2019-04-03  9:44 ` [PATCH v1 5/6] clk: rockchip: add pll up and down when change pll freq Elaine Zhang
@ 2019-04-03  9:44 ` Elaine Zhang
  5 siblings, 0 replies; 16+ messages in thread
From: Elaine Zhang @ 2019-04-03  9:44 UTC (permalink / raw)
  To: heiko
  Cc: mturquette, sboyd, linux-clk, linux-arm-kernel, linux-rockchip,
	linux-kernel, xxx, xf, huangtao, Elaine Zhang

If setting freq is not support in rockchip_pll_rate_table,
It can calculate and set pll params by auto.

Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com>
---
 drivers/clk/rockchip/clk-pll.c | 215 ++++++++++++++++++++++++++++++++++++++---
 1 file changed, 200 insertions(+), 15 deletions(-)

diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c
index 9fe1227e77e9..e718a791b8c2 100644
--- a/drivers/clk/rockchip/clk-pll.c
+++ b/drivers/clk/rockchip/clk-pll.c
@@ -23,6 +23,7 @@
 #include <linux/clk-provider.h>
 #include <linux/regmap.h>
 #include <linux/clk.h>
+#include <linux/gcd.h>
 #include "clk.h"
 
 #define PLL_MODE_MASK		0x3
@@ -55,6 +56,198 @@ struct rockchip_clk_pll {
 #define to_rockchip_clk_pll_nb(nb) \
 			container_of(nb, struct rockchip_clk_pll, clk_nb)
 
+#define MHZ			(1000UL * 1000UL)
+#define KHZ			(1000UL)
+
+/* CLK_PLL_TYPE_RK3066_AUTO type ops */
+#define PLL_FREF_MIN		(269 * KHZ)
+#define PLL_FREF_MAX		(2200 * MHZ)
+
+#define PLL_FVCO_MIN		(440 * MHZ)
+#define PLL_FVCO_MAX		(2200 * MHZ)
+
+#define PLL_FOUT_MIN		(27500 * KHZ)
+#define PLL_FOUT_MAX		(2200 * MHZ)
+
+#define PLL_NF_MAX		(4096)
+#define PLL_NR_MAX		(64)
+#define PLL_NO_MAX		(16)
+
+/* CLK_PLL_TYPE_RK3036/3366/3399_AUTO type ops */
+#define MIN_FOUTVCO_FREQ	(800 * MHZ)
+#define MAX_FOUTVCO_FREQ	(2000 * MHZ)
+
+static struct rockchip_pll_rate_table auto_table;
+
+static struct rockchip_pll_rate_table *rk_pll_rate_table_get(void)
+{
+	return &auto_table;
+}
+
+static int rockchip_pll_clk_set_postdiv(unsigned long fout_hz,
+					u32 *postdiv1,
+					u32 *postdiv2,
+					u32 *foutvco)
+{
+	unsigned long freq;
+
+	if (fout_hz < MIN_FOUTVCO_FREQ) {
+		for (*postdiv1 = 1; *postdiv1 <= 7; (*postdiv1)++) {
+			for (*postdiv2 = 1; *postdiv2 <= 7; (*postdiv2)++) {
+				freq = fout_hz * (*postdiv1) * (*postdiv2);
+				if (freq >= MIN_FOUTVCO_FREQ &&
+				    freq <= MAX_FOUTVCO_FREQ) {
+					*foutvco = freq;
+					return 0;
+				}
+			}
+		}
+		pr_err("CANNOT FIND postdiv1/2 to make fout in range from 800M to 2000M,fout = %lu\n",
+		       fout_hz);
+	} else {
+		*postdiv1 = 1;
+		*postdiv2 = 1;
+	}
+	return 0;
+}
+
+static struct rockchip_pll_rate_table *
+rockchip_pll_clk_set_by_auto(struct rockchip_clk_pll *pll,
+			     unsigned long fin_hz,
+			     unsigned long fout_hz)
+{
+	struct rockchip_pll_rate_table *rate_table = rk_pll_rate_table_get();
+	/* FIXME set postdiv1/2 always 1*/
+	u32 foutvco = fout_hz;
+	u64 fin_64, frac_64;
+	u32 f_frac, postdiv1, postdiv2;
+	unsigned long clk_gcd = 0;
+
+	if (fin_hz == 0 || fout_hz == 0 || fout_hz == fin_hz)
+		return NULL;
+
+	rockchip_pll_clk_set_postdiv(fout_hz, &postdiv1, &postdiv2, &foutvco);
+	rate_table->postdiv1 = postdiv1;
+	rate_table->postdiv2 = postdiv2;
+	rate_table->dsmpd = 1;
+
+	if (fin_hz / MHZ * MHZ == fin_hz && fout_hz / MHZ * MHZ == fout_hz) {
+		fin_hz /= MHZ;
+		foutvco /= MHZ;
+		clk_gcd = gcd(fin_hz, foutvco);
+		rate_table->refdiv = fin_hz / clk_gcd;
+		rate_table->fbdiv = foutvco / clk_gcd;
+
+		rate_table->frac = 0;
+
+		pr_debug("fin = %lu, fout = %lu, clk_gcd = %lu, refdiv = %u, fbdiv = %u, postdiv1 = %u, postdiv2 = %u, frac = %u\n",
+			 fin_hz, fout_hz, clk_gcd, rate_table->refdiv,
+			 rate_table->fbdiv, rate_table->postdiv1,
+			 rate_table->postdiv2, rate_table->frac);
+	} else {
+		pr_debug("frac div running, fin_hz = %lu, fout_hz = %lu, fin_INT_mhz = %lu, fout_INT_mhz = %lu\n",
+			 fin_hz, fout_hz,
+			 fin_hz / MHZ * MHZ,
+			 fout_hz / MHZ * MHZ);
+		pr_debug("frac get postdiv1 = %u,  postdiv2 = %u, foutvco = %u\n",
+			 rate_table->postdiv1, rate_table->postdiv2, foutvco);
+		clk_gcd = gcd(fin_hz / MHZ, foutvco / MHZ);
+		rate_table->refdiv = fin_hz / MHZ / clk_gcd;
+		rate_table->fbdiv = foutvco / MHZ / clk_gcd;
+		pr_debug("frac get refdiv = %u,  fbdiv = %u\n",
+			 rate_table->refdiv, rate_table->fbdiv);
+
+		rate_table->frac = 0;
+
+		f_frac = (foutvco % MHZ);
+		fin_64 = fin_hz;
+		do_div(fin_64, (u64)rate_table->refdiv);
+		frac_64 = (u64)f_frac << 24;
+		do_div(frac_64, fin_64);
+		rate_table->frac = (u32)frac_64;
+		if (rate_table->frac > 0)
+			rate_table->dsmpd = 0;
+		pr_debug("frac = %x\n", rate_table->frac);
+	}
+	return rate_table;
+}
+
+static struct rockchip_pll_rate_table *
+rockchip_rk3066_pll_clk_set_by_auto(struct rockchip_clk_pll *pll,
+				    unsigned long fin_hz,
+				    unsigned long fout_hz)
+{
+	struct rockchip_pll_rate_table *rate_table = rk_pll_rate_table_get();
+	u32 nr, nf, no, nonr;
+	u32 nr_out, nf_out, no_out;
+	u32 n;
+	u32 numerator, denominator;
+	u64 fref, fvco, fout;
+	unsigned long clk_gcd = 0;
+
+	nr_out = PLL_NR_MAX + 1;
+	no_out = 0;
+	nf_out = 0;
+
+	if (fin_hz == 0 || fout_hz == 0 || fout_hz == fin_hz)
+		return NULL;
+
+	clk_gcd = gcd(fin_hz, fout_hz);
+
+	numerator = fout_hz / clk_gcd;
+	denominator = fin_hz / clk_gcd;
+
+	for (n = 1;; n++) {
+		nf = numerator * n;
+		nonr = denominator * n;
+		if (nf > PLL_NF_MAX || nonr > (PLL_NO_MAX * PLL_NR_MAX))
+			break;
+
+		for (no = 1; no <= PLL_NO_MAX; no++) {
+			if (!(no == 1 || !(no % 2)))
+				continue;
+
+			if (nonr % no)
+				continue;
+			nr = nonr / no;
+
+			if (nr > PLL_NR_MAX)
+				continue;
+
+			fref = fin_hz / nr;
+			if (fref < PLL_FREF_MIN || fref > PLL_FREF_MAX)
+				continue;
+
+			fvco = fref * nf;
+			if (fvco < PLL_FVCO_MIN || fvco > PLL_FVCO_MAX)
+				continue;
+
+			fout = fvco / no;
+			if (fout < PLL_FOUT_MIN || fout > PLL_FOUT_MAX)
+				continue;
+
+			/* select the best from all available PLL settings */
+			if ((no > no_out) ||
+			    ((no == no_out) && (nr < nr_out))) {
+				nr_out = nr;
+				nf_out = nf;
+				no_out = no;
+			}
+		}
+	}
+
+	/* output the best PLL setting */
+	if ((nr_out <= PLL_NR_MAX) && (no_out > 0)) {
+		rate_table->nr = nr_out;
+		rate_table->nf = nf_out;
+		rate_table->no = no_out;
+	} else {
+		return NULL;
+	}
+
+	return rate_table;
+}
+
 static const struct rockchip_pll_rate_table *rockchip_get_pll_settings(
 			    struct rockchip_clk_pll *pll, unsigned long rate)
 {
@@ -66,24 +259,16 @@ static const struct rockchip_pll_rate_table *rockchip_get_pll_settings(
 			return &rate_table[i];
 	}
 
-	return NULL;
+	if (pll->type == pll_rk3066)
+		return rockchip_rk3066_pll_clk_set_by_auto(pll, 24 * MHZ, rate);
+	else
+		return rockchip_pll_clk_set_by_auto(pll, 24 * MHZ, rate);
 }
 
 static long rockchip_pll_round_rate(struct clk_hw *hw,
 			    unsigned long drate, unsigned long *prate)
 {
-	struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
-	const struct rockchip_pll_rate_table *rate_table = pll->rate_table;
-	int i;
-
-	/* Assumming rate_table is in descending order */
-	for (i = 0; i < pll->rate_count; i++) {
-		if (drate >= rate_table[i].rate)
-			return rate_table[i].rate;
-	}
-
-	/* return minimum supported value */
-	return rate_table[i - 1].rate;
+	return drate;
 }
 
 /*
@@ -163,7 +348,7 @@ static unsigned long rockchip_rk3036_pll_recalc_rate(struct clk_hw *hw,
 {
 	struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
 	struct rockchip_pll_rate_table cur;
-	u64 rate64 = prate;
+	u64 rate64 = prate, frac_rate64 = prate;
 
 	rockchip_rk3036_pll_get_params(pll, &cur);
 
@@ -172,7 +357,7 @@ static unsigned long rockchip_rk3036_pll_recalc_rate(struct clk_hw *hw,
 
 	if (cur.dsmpd == 0) {
 		/* fractional mode */
-		u64 frac_rate64 = prate * cur.frac;
+		frac_rate64 *= cur.frac;
 
 		do_div(frac_rate64, cur.refdiv);
 		rate64 += frac_rate64 >> 24;
-- 
1.9.1




^ permalink raw reply related	[flat|nested] 16+ messages in thread

* Re: [PATCH v1 3/6] clk: rockchip: add a COMPOSITE_DIV_OFFSET clock-type
  2019-04-03  9:42 ` [PATCH v1 3/6] clk: rockchip: add a COMPOSITE_DIV_OFFSET clock-type Elaine Zhang
@ 2019-04-12 11:35   ` Heiko Stübner
  0 siblings, 0 replies; 16+ messages in thread
From: Heiko Stübner @ 2019-04-12 11:35 UTC (permalink / raw)
  To: Elaine Zhang
  Cc: mturquette, sboyd, linux-clk, linux-arm-kernel, linux-rockchip,
	linux-kernel, xxx, xf, huangtao, Finley Xiao

Am Mittwoch, 3. April 2019, 11:42:26 CEST schrieb Elaine Zhang:
> From: Finley Xiao <finley.xiao@rock-chips.com>
> 
> The div offset of some clocks are different from their mux offset
> and the COMPOSITE clock-type require that div and mux offset are
> the same, so add a new COMPOSITE_DIV_OFFSET clock-type to handle that.
> 
> Signed-off-by: Finley Xiao <finley.xiao@rock-chips.com>
> Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com>

applied for 5.2

Thanks
Heiko



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v1 4/6] clk: rockchip: add a clock-type for muxes based in the pmugrf
  2019-04-03  9:42 ` [PATCH v1 4/6] clk: rockchip: add a clock-type for muxes based in the pmugrf Elaine Zhang
@ 2019-04-12 11:45   ` Heiko Stübner
  0 siblings, 0 replies; 16+ messages in thread
From: Heiko Stübner @ 2019-04-12 11:45 UTC (permalink / raw)
  To: Elaine Zhang
  Cc: mturquette, sboyd, linux-clk, linux-arm-kernel, linux-rockchip,
	linux-kernel, xxx, xf, huangtao

Hi Elaine,

Am Mittwoch, 3. April 2019, 11:42:27 CEST schrieb Elaine Zhang:
> Rockchip socs often have some tiny number of muxes not controlled from
> the core clock controller but through bits set in the pmugrf.
> Use MUXPMUGRF() to cover this special clock-type.
> 
> Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com>

Do you have an example for such a clock?

I.e. on rk3399 we have the pmucru which already links
to the pmugrf as its "regular" rockchip,grf.
Similarly the main-cru links to the main grf.

So I don't really see where a clock needs to be defined
in the main-grf and use a bit from the pmugrf.

Similarly I wasn't really able to find anything that looks like
a clock-mux in the PX30's (rk3326) pmugrf.

So I'd really like an example beforehand :-D

Thanks
Heiko

> ---
>  drivers/clk/rockchip/clk.c |  9 +++++++++
>  drivers/clk/rockchip/clk.h | 17 +++++++++++++++++
>  2 files changed, 26 insertions(+)
> 
> diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c
> index 0a8a694a41ab..875412043dd7 100644
> --- a/drivers/clk/rockchip/clk.c
> +++ b/drivers/clk/rockchip/clk.c
> @@ -415,6 +415,8 @@ struct rockchip_clk_provider * __init rockchip_clk_init(struct device_node *np,
>  
>  	ctx->grf = syscon_regmap_lookup_by_phandle(ctx->cru_node,
>  						   "rockchip,grf");
> +	ctx->pmugrf = syscon_regmap_lookup_by_phandle(ctx->cru_node,
> +						   "rockchip,pmugrf");
>  
>  	return ctx;
>  
> @@ -490,6 +492,13 @@ void __init rockchip_clk_register_branches(
>  				list->mux_shift, list->mux_width,
>  				list->mux_flags);
>  			break;
> +		case branch_muxpmugrf:
> +			clk = rockchip_clk_register_muxgrf(list->name,
> +				list->parent_names, list->num_parents,
> +				flags, ctx->pmugrf, list->muxdiv_offset,
> +				list->mux_shift, list->mux_width,
> +				list->mux_flags);
> +			break;
>  		case branch_divider:
>  			if (list->div_table)
>  				clk = clk_register_divider_table(NULL,
> diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h
> index 20200a707611..1b30346f11e1 100644
> --- a/drivers/clk/rockchip/clk.h
> +++ b/drivers/clk/rockchip/clk.h
> @@ -234,6 +234,7 @@ struct rockchip_clk_provider {
>  	struct clk_onecell_data clk_data;
>  	struct device_node *cru_node;
>  	struct regmap *grf;
> +	struct regmap *pmugrf;
>  	spinlock_t lock;
>  };
>  
> @@ -386,6 +387,7 @@ enum rockchip_clk_branch_type {
>  	branch_composite,
>  	branch_mux,
>  	branch_muxgrf,
> +	branch_muxpmugrf,
>  	branch_divider,
>  	branch_fraction_divider,
>  	branch_gate,
> @@ -658,6 +660,21 @@ struct rockchip_clk_branch {
>  		.gate_offset	= -1,				\
>  	}
>  
> +#define MUXPMUGRF(_id, cname, pnames, f, o, s, w, mf)		\
> +	{							\
> +		.id		= _id,				\
> +		.branch_type	= branch_muxpmugrf,		\
> +		.name		= cname,			\
> +		.parent_names	= pnames,			\
> +		.num_parents	= ARRAY_SIZE(pnames),		\
> +		.flags		= f,				\
> +		.muxdiv_offset	= o,				\
> +		.mux_shift	= s,				\
> +		.mux_width	= w,				\
> +		.mux_flags	= mf,				\
> +		.gate_offset	= -1,				\
> +	}
> +
>  #define DIV(_id, cname, pname, f, o, s, w, df)			\
>  	{							\
>  		.id		= _id,				\
> 





^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v1 1/6] clk: rockchip: Add supprot to limit input rate for fractional divider
  2019-04-03  9:42 ` [PATCH v1 1/6] clk: rockchip: Add supprot to limit input rate for fractional divider Elaine Zhang
@ 2019-04-12 11:52   ` Heiko Stübner
  2019-04-12 12:12     ` Christoph Müllner
  0 siblings, 1 reply; 16+ messages in thread
From: Heiko Stübner @ 2019-04-12 11:52 UTC (permalink / raw)
  To: Elaine Zhang
  Cc: mturquette, sboyd, linux-clk, linux-arm-kernel, linux-rockchip,
	linux-kernel, xxx, xf, huangtao, Finley Xiao, christoph.muellner

Hi Elaine,

Am Mittwoch, 3. April 2019, 11:42:24 CEST schrieb Elaine Zhang:
> From: Finley Xiao <finley.xiao@rock-chips.com>
> 
> From Rockchips fractional divider usage, some clocks can be generated
> by fractional divider, but the input clock frequency of fractional
> divider should be less than a specified value.
> 
> Signed-off-by: Finley Xiao <finley.xiao@rock-chips.com>
> Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com>

can you tell me where these maximum input values come from?

I talked to Christoph from Theobroma (Cc'ed) last week and he mentioned
that they're using the fractional divider with a higher input frequency
to create a very specific frequency [some details are gone from my memory
though] they can't get otherwise.

So I really don't want to break their working setup by introducing barriers
that are not strictly necessary.

@Christoph: can you describe the bits from your fractional setup that
I've forgotten please?


Thanks
Heiko


> diff --git a/drivers/clk/rockchip/clk-px30.c b/drivers/clk/rockchip/clk-px30.c
> index 601a77f1af78..ccabce35580b 100644
> --- a/drivers/clk/rockchip/clk-px30.c
> +++ b/drivers/clk/rockchip/clk-px30.c
> @@ -21,6 +21,7 @@
>  #include "clk.h"
>  
>  #define PX30_GRF_SOC_STATUS0		0x480
> +#define PX30_FRAC_MAX_PRATE		600000000


> diff --git a/drivers/clk/rockchip/clk-rk3368.c b/drivers/clk/rockchip/clk-rk3368.c
> index 7c4d242f19c1..67c2da5e7d61 100644
> --- a/drivers/clk/rockchip/clk-rk3368.c
> +++ b/drivers/clk/rockchip/clk-rk3368.c
> @@ -20,6 +20,9 @@
>  #include "clk.h"
>  
>  #define RK3368_GRF_SOC_STATUS0	0x480
> +#define RK3368_I2S_FRAC_MAX_PRATE       600000000
> +#define RK3368_UART_FRAC_MAX_PRATE	600000000
> +#define RK3368_SPDIF_FRAC_MAX_PRATE	600000000

> diff --git a/drivers/clk/rockchip/clk-rk3399.c b/drivers/clk/rockchip/clk-rk3399.c
> index 5a628148f3f0..1d81382bd3e0 100644
> --- a/drivers/clk/rockchip/clk-rk3399.c
> +++ b/drivers/clk/rockchip/clk-rk3399.c
> @@ -21,6 +21,12 @@
>  #include <dt-bindings/clock/rk3399-cru.h>
>  #include "clk.h"
>  
> +#define RK3399_I2S_FRAC_MAX_PRATE       600000000
> +#define RK3399_UART_FRAC_MAX_PRATE	600000000
> +#define RK3399_SPDIF_FRAC_MAX_PRATE	600000000
> +#define RK3399_VOP_FRAC_MAX_PRATE	600000000
> +#define RK3399_WIFI_FRAC_MAX_PRATE	600000000
> +




^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v1 1/6] clk: rockchip: Add supprot to limit input rate for fractional divider
  2019-04-12 11:52   ` Heiko Stübner
@ 2019-04-12 12:12     ` Christoph Müllner
  2019-04-12 12:21       ` Heiko Stübner
  0 siblings, 1 reply; 16+ messages in thread
From: Christoph Müllner @ 2019-04-12 12:12 UTC (permalink / raw)
  To: Heiko Stübner, Elaine Zhang
  Cc: mturquette, sboyd, linux-clk, linux-arm-kernel, linux-rockchip,
	linux-kernel, xxx, xf, huangtao, Finley Xiao

Hi Heiko,

On 12.04.19 13:52, Heiko Stübner wrote:
> Hi Elaine,
> 
> Am Mittwoch, 3. April 2019, 11:42:24 CEST schrieb Elaine Zhang:
>> From: Finley Xiao <finley.xiao@rock-chips.com>
>>
>> From Rockchips fractional divider usage, some clocks can be generated
>> by fractional divider, but the input clock frequency of fractional
>> divider should be less than a specified value.
>>
>> Signed-off-by: Finley Xiao <finley.xiao@rock-chips.com>
>> Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com>
> 
> can you tell me where these maximum input values come from?
> 
> I talked to Christoph from Theobroma (Cc'ed) last week and he mentioned
> that they're using the fractional divider with a higher input frequency
> to create a very specific frequency [some details are gone from my memory
> though] they can't get otherwise.
> 
> So I really don't want to break their working setup by introducing barriers
> that are not strictly necessary.
> 
> @Christoph: can you describe the bits from your fractional setup that
> I've forgotten please?

We need to set the I2S0 clock to 24.56 MHz.

When restricting the input frequency to a maximum of 600 Mhz,
we could use the integer divider to get 400 Mhz (dividing by 2).
However, with the 400 Mhz as input to the frac divider,
we run into the problem, that the maximum possible output frequency
is 20 MHz (there is another restriction which states that the
fraction input : output frequency must be >= 20).

Thanks,
Christoph

> 
>> diff --git a/drivers/clk/rockchip/clk-px30.c b/drivers/clk/rockchip/clk-px30.c
>> index 601a77f1af78..ccabce35580b 100644
>> --- a/drivers/clk/rockchip/clk-px30.c
>> +++ b/drivers/clk/rockchip/clk-px30.c
>> @@ -21,6 +21,7 @@
>>  #include "clk.h"
>>  
>>  #define PX30_GRF_SOC_STATUS0		0x480
>> +#define PX30_FRAC_MAX_PRATE		600000000
> 
> 
>> diff --git a/drivers/clk/rockchip/clk-rk3368.c b/drivers/clk/rockchip/clk-rk3368.c
>> index 7c4d242f19c1..67c2da5e7d61 100644
>> --- a/drivers/clk/rockchip/clk-rk3368.c
>> +++ b/drivers/clk/rockchip/clk-rk3368.c
>> @@ -20,6 +20,9 @@
>>  #include "clk.h"
>>  
>>  #define RK3368_GRF_SOC_STATUS0	0x480
>> +#define RK3368_I2S_FRAC_MAX_PRATE       600000000
>> +#define RK3368_UART_FRAC_MAX_PRATE	600000000
>> +#define RK3368_SPDIF_FRAC_MAX_PRATE	600000000
> 
>> diff --git a/drivers/clk/rockchip/clk-rk3399.c b/drivers/clk/rockchip/clk-rk3399.c
>> index 5a628148f3f0..1d81382bd3e0 100644
>> --- a/drivers/clk/rockchip/clk-rk3399.c
>> +++ b/drivers/clk/rockchip/clk-rk3399.c
>> @@ -21,6 +21,12 @@
>>  #include <dt-bindings/clock/rk3399-cru.h>
>>  #include "clk.h"
>>  
>> +#define RK3399_I2S_FRAC_MAX_PRATE       600000000
>> +#define RK3399_UART_FRAC_MAX_PRATE	600000000
>> +#define RK3399_SPDIF_FRAC_MAX_PRATE	600000000
>> +#define RK3399_VOP_FRAC_MAX_PRATE	600000000
>> +#define RK3399_WIFI_FRAC_MAX_PRATE	600000000
>> +
> 
> 
> 


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v1 5/6] clk: rockchip: add pll up and down when change pll freq
  2019-04-03  9:44 ` [PATCH v1 5/6] clk: rockchip: add pll up and down when change pll freq Elaine Zhang
@ 2019-04-12 12:15   ` Heiko Stübner
  2019-04-12 17:28     ` Doug Anderson
  0 siblings, 1 reply; 16+ messages in thread
From: Heiko Stübner @ 2019-04-12 12:15 UTC (permalink / raw)
  To: Elaine Zhang
  Cc: mturquette, sboyd, linux-clk, linux-arm-kernel, linux-rockchip,
	linux-kernel, xxx, xf, huangtao, dianders, briannorris

Hi Elaine,

Am Mittwoch, 3. April 2019, 11:44:09 CEST schrieb Elaine Zhang:
> set pll sequence:
> 	->set pll to slow mode or other plls
> 	->set pll down
> 	->set pll params
> 	->set pll up
> 	->wait pll lock status
> 	->set pll to normal mode
> 
> To slove the system error:
> wait_pll_lock: timeout waiting for pll to lock
> pll_set_params: pll update unsucessful,
> 		trying to restore old params

Can you tell me on what soc this was experienced?

The patch includes rk3399, but I don't think the CrOS kernel
does powerdown the pll when changing the cpu-frequency
[added Doug and Brian for clarification and possible testing :-) ]

But I did find that the M0 code in ATF does actually power-down the
PLL and follow your outline from above. So essentially I'd just like
a thumbs up from chromeos people if they have the time.


Heiko


> Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com>
> ---
>  drivers/clk/rockchip/clk-pll.c | 19 +++++++++++++++++++
>  1 file changed, 19 insertions(+)
> 
> diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c
> index dd0433d4753e..9fe1227e77e9 100644
> --- a/drivers/clk/rockchip/clk-pll.c
> +++ b/drivers/clk/rockchip/clk-pll.c
> @@ -208,6 +208,11 @@ static int rockchip_rk3036_pll_set_params(struct rockchip_clk_pll *pll,
>  		rate_change_remuxed = 1;
>  	}
>  
> +	/* set pll power down */
> +	writel(HIWORD_UPDATE(1,
> +			     RK3036_PLLCON1_PWRDOWN, 13),
> +	       pll->reg_base + RK3036_PLLCON(1));
> +
>  	/* update pll values */
>  	writel_relaxed(HIWORD_UPDATE(rate->fbdiv, RK3036_PLLCON0_FBDIV_MASK,
>  					  RK3036_PLLCON0_FBDIV_SHIFT) |
> @@ -229,6 +234,10 @@ static int rockchip_rk3036_pll_set_params(struct rockchip_clk_pll *pll,
>  	pllcon |= rate->frac << RK3036_PLLCON2_FRAC_SHIFT;
>  	writel_relaxed(pllcon, pll->reg_base + RK3036_PLLCON(2));
>  
> +	/* set pll power up */
> +	writel(HIWORD_UPDATE(0, RK3036_PLLCON1_PWRDOWN, 13),
> +	       pll->reg_base + RK3036_PLLCON(1));
> +
>  	/* wait for the pll to lock */
>  	ret = rockchip_pll_wait_lock(pll);
>  	if (ret) {
> @@ -685,6 +694,11 @@ static int rockchip_rk3399_pll_set_params(struct rockchip_clk_pll *pll,
>  		rate_change_remuxed = 1;
>  	}
>  
> +	/* set pll power down */
> +	writel(HIWORD_UPDATE(RK3399_PLLCON3_PWRDOWN,
> +			     RK3399_PLLCON3_PWRDOWN, 0),
> +	       pll->reg_base + RK3399_PLLCON(3));
> +
>  	/* update pll values */
>  	writel_relaxed(HIWORD_UPDATE(rate->fbdiv, RK3399_PLLCON0_FBDIV_MASK,
>  						  RK3399_PLLCON0_FBDIV_SHIFT),
> @@ -708,6 +722,11 @@ static int rockchip_rk3399_pll_set_params(struct rockchip_clk_pll *pll,
>  					    RK3399_PLLCON3_DSMPD_SHIFT),
>  		       pll->reg_base + RK3399_PLLCON(3));
>  
> +	/* set pll power up */
> +	writel(HIWORD_UPDATE(0,
> +			     RK3399_PLLCON3_PWRDOWN, 0),
> +	       pll->reg_base + RK3399_PLLCON(3));
> +
>  	/* wait for the pll to lock */
>  	ret = rockchip_rk3399_pll_wait_lock(pll);
>  	if (ret) {
> 





^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v1 1/6] clk: rockchip: Add supprot to limit input rate for fractional divider
  2019-04-12 12:12     ` Christoph Müllner
@ 2019-04-12 12:21       ` Heiko Stübner
  2019-04-12 12:32         ` Christoph Müllner
  0 siblings, 1 reply; 16+ messages in thread
From: Heiko Stübner @ 2019-04-12 12:21 UTC (permalink / raw)
  To: Christoph Müllner
  Cc: Elaine Zhang, mturquette, sboyd, linux-clk, linux-arm-kernel,
	linux-rockchip, linux-kernel, xxx, xf, huangtao, Finley Xiao

Hi Christoph,

Am Freitag, 12. April 2019, 14:12:52 CEST schrieb Christoph Müllner:
> On 12.04.19 13:52, Heiko Stübner wrote:
> > Am Mittwoch, 3. April 2019, 11:42:24 CEST schrieb Elaine Zhang:
> >> From: Finley Xiao <finley.xiao@rock-chips.com>
> >>
> >> From Rockchips fractional divider usage, some clocks can be generated
> >> by fractional divider, but the input clock frequency of fractional
> >> divider should be less than a specified value.
> >>
> >> Signed-off-by: Finley Xiao <finley.xiao@rock-chips.com>
> >> Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com>
> > 
> > can you tell me where these maximum input values come from?
> > 
> > I talked to Christoph from Theobroma (Cc'ed) last week and he mentioned
> > that they're using the fractional divider with a higher input frequency
> > to create a very specific frequency [some details are gone from my memory
> > though] they can't get otherwise.
> > 
> > So I really don't want to break their working setup by introducing barriers
> > that are not strictly necessary.
> > 
> > @Christoph: can you describe the bits from your fractional setup that
> > I've forgotten please?
> 
> We need to set the I2S0 clock to 24.56 MHz.
> 
> When restricting the input frequency to a maximum of 600 Mhz,
> we could use the integer divider to get 400 Mhz (dividing by 2).
> However, with the 400 Mhz as input to the frac divider,
> we run into the problem, that the maximum possible output frequency
> is 20 MHz (there is another restriction which states that the
> fraction input : output frequency must be >= 20).

just for clarification, what is the current input frequency you
already use sucessfully?


Heiko

> > 
> >> diff --git a/drivers/clk/rockchip/clk-px30.c b/drivers/clk/rockchip/clk-px30.c
> >> index 601a77f1af78..ccabce35580b 100644
> >> --- a/drivers/clk/rockchip/clk-px30.c
> >> +++ b/drivers/clk/rockchip/clk-px30.c
> >> @@ -21,6 +21,7 @@
> >>  #include "clk.h"
> >>  
> >>  #define PX30_GRF_SOC_STATUS0		0x480
> >> +#define PX30_FRAC_MAX_PRATE		600000000
> > 
> > 
> >> diff --git a/drivers/clk/rockchip/clk-rk3368.c b/drivers/clk/rockchip/clk-rk3368.c
> >> index 7c4d242f19c1..67c2da5e7d61 100644
> >> --- a/drivers/clk/rockchip/clk-rk3368.c
> >> +++ b/drivers/clk/rockchip/clk-rk3368.c
> >> @@ -20,6 +20,9 @@
> >>  #include "clk.h"
> >>  
> >>  #define RK3368_GRF_SOC_STATUS0	0x480
> >> +#define RK3368_I2S_FRAC_MAX_PRATE       600000000
> >> +#define RK3368_UART_FRAC_MAX_PRATE	600000000
> >> +#define RK3368_SPDIF_FRAC_MAX_PRATE	600000000
> > 
> >> diff --git a/drivers/clk/rockchip/clk-rk3399.c b/drivers/clk/rockchip/clk-rk3399.c
> >> index 5a628148f3f0..1d81382bd3e0 100644
> >> --- a/drivers/clk/rockchip/clk-rk3399.c
> >> +++ b/drivers/clk/rockchip/clk-rk3399.c
> >> @@ -21,6 +21,12 @@
> >>  #include <dt-bindings/clock/rk3399-cru.h>
> >>  #include "clk.h"
> >>  
> >> +#define RK3399_I2S_FRAC_MAX_PRATE       600000000
> >> +#define RK3399_UART_FRAC_MAX_PRATE	600000000
> >> +#define RK3399_SPDIF_FRAC_MAX_PRATE	600000000
> >> +#define RK3399_VOP_FRAC_MAX_PRATE	600000000
> >> +#define RK3399_WIFI_FRAC_MAX_PRATE	600000000
> >> +
> > 
> > 
> > 
> 





^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v1 1/6] clk: rockchip: Add supprot to limit input rate for fractional divider
  2019-04-12 12:21       ` Heiko Stübner
@ 2019-04-12 12:32         ` Christoph Müllner
  2019-04-12 12:39           ` Heiko Stübner
  0 siblings, 1 reply; 16+ messages in thread
From: Christoph Müllner @ 2019-04-12 12:32 UTC (permalink / raw)
  To: Heiko Stübner
  Cc: Elaine Zhang, mturquette, sboyd, linux-clk, linux-arm-kernel,
	linux-rockchip, linux-kernel, xxx, xf, huangtao, Finley Xiao



On 12.04.19 14:21, Heiko Stübner wrote:
> Hi Christoph,
> 
> Am Freitag, 12. April 2019, 14:12:52 CEST schrieb Christoph Müllner:
>> On 12.04.19 13:52, Heiko Stübner wrote:
>>> Am Mittwoch, 3. April 2019, 11:42:24 CEST schrieb Elaine Zhang:
>>>> From: Finley Xiao <finley.xiao@rock-chips.com>
>>>>
>>>> From Rockchips fractional divider usage, some clocks can be generated
>>>> by fractional divider, but the input clock frequency of fractional
>>>> divider should be less than a specified value.
>>>>
>>>> Signed-off-by: Finley Xiao <finley.xiao@rock-chips.com>
>>>> Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com>
>>>
>>> can you tell me where these maximum input values come from?
>>>
>>> I talked to Christoph from Theobroma (Cc'ed) last week and he mentioned
>>> that they're using the fractional divider with a higher input frequency
>>> to create a very specific frequency [some details are gone from my memory
>>> though] they can't get otherwise.
>>>
>>> So I really don't want to break their working setup by introducing barriers
>>> that are not strictly necessary.
>>>
>>> @Christoph: can you describe the bits from your fractional setup that
>>> I've forgotten please?
>>
>> We need to set the I2S0 clock to 24.56 MHz.
>>
>> When restricting the input frequency to a maximum of 600 Mhz,
>> we could use the integer divider to get 400 Mhz (dividing by 2).
>> However, with the 400 Mhz as input to the frac divider,
>> we run into the problem, that the maximum possible output frequency
>> is 20 MHz (there is another restriction which states that the
>> fraction input : output frequency must be >= 20).
> 
> just for clarification, what is the current input frequency you
> already use sucessfully?

Our working setup uses the integer divider to reduce to 400 MHz
and uses the frac divider to get something near 24.56 MHz.
I have to admit I have never measured what's on the clock line.

>>>
>>>> diff --git a/drivers/clk/rockchip/clk-px30.c b/drivers/clk/rockchip/clk-px30.c
>>>> index 601a77f1af78..ccabce35580b 100644
>>>> --- a/drivers/clk/rockchip/clk-px30.c
>>>> +++ b/drivers/clk/rockchip/clk-px30.c
>>>> @@ -21,6 +21,7 @@
>>>>  #include "clk.h"
>>>>  
>>>>  #define PX30_GRF_SOC_STATUS0		0x480
>>>> +#define PX30_FRAC_MAX_PRATE		600000000
>>>
>>>
>>>> diff --git a/drivers/clk/rockchip/clk-rk3368.c b/drivers/clk/rockchip/clk-rk3368.c
>>>> index 7c4d242f19c1..67c2da5e7d61 100644
>>>> --- a/drivers/clk/rockchip/clk-rk3368.c
>>>> +++ b/drivers/clk/rockchip/clk-rk3368.c
>>>> @@ -20,6 +20,9 @@
>>>>  #include "clk.h"
>>>>  
>>>>  #define RK3368_GRF_SOC_STATUS0	0x480
>>>> +#define RK3368_I2S_FRAC_MAX_PRATE       600000000
>>>> +#define RK3368_UART_FRAC_MAX_PRATE	600000000
>>>> +#define RK3368_SPDIF_FRAC_MAX_PRATE	600000000
>>>
>>>> diff --git a/drivers/clk/rockchip/clk-rk3399.c b/drivers/clk/rockchip/clk-rk3399.c
>>>> index 5a628148f3f0..1d81382bd3e0 100644
>>>> --- a/drivers/clk/rockchip/clk-rk3399.c
>>>> +++ b/drivers/clk/rockchip/clk-rk3399.c
>>>> @@ -21,6 +21,12 @@
>>>>  #include <dt-bindings/clock/rk3399-cru.h>
>>>>  #include "clk.h"
>>>>  
>>>> +#define RK3399_I2S_FRAC_MAX_PRATE       600000000
>>>> +#define RK3399_UART_FRAC_MAX_PRATE	600000000
>>>> +#define RK3399_SPDIF_FRAC_MAX_PRATE	600000000
>>>> +#define RK3399_VOP_FRAC_MAX_PRATE	600000000
>>>> +#define RK3399_WIFI_FRAC_MAX_PRATE	600000000
>>>> +
>>>
>>>
>>>
>>
> 
> 
> 
> 


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v1 1/6] clk: rockchip: Add supprot to limit input rate for fractional divider
  2019-04-12 12:32         ` Christoph Müllner
@ 2019-04-12 12:39           ` Heiko Stübner
  0 siblings, 0 replies; 16+ messages in thread
From: Heiko Stübner @ 2019-04-12 12:39 UTC (permalink / raw)
  To: Christoph Müllner
  Cc: Elaine Zhang, mturquette, sboyd, linux-clk, linux-arm-kernel,
	linux-rockchip, linux-kernel, xxx, xf, huangtao, Finley Xiao

Am Freitag, 12. April 2019, 14:32:08 CEST schrieb Christoph Müllner:
> 
> On 12.04.19 14:21, Heiko Stübner wrote:
> > Hi Christoph,
> > 
> > Am Freitag, 12. April 2019, 14:12:52 CEST schrieb Christoph Müllner:
> >> On 12.04.19 13:52, Heiko Stübner wrote:
> >>> Am Mittwoch, 3. April 2019, 11:42:24 CEST schrieb Elaine Zhang:
> >>>> From: Finley Xiao <finley.xiao@rock-chips.com>
> >>>>
> >>>> From Rockchips fractional divider usage, some clocks can be generated
> >>>> by fractional divider, but the input clock frequency of fractional
> >>>> divider should be less than a specified value.
> >>>>
> >>>> Signed-off-by: Finley Xiao <finley.xiao@rock-chips.com>
> >>>> Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com>
> >>>
> >>> can you tell me where these maximum input values come from?
> >>>
> >>> I talked to Christoph from Theobroma (Cc'ed) last week and he mentioned
> >>> that they're using the fractional divider with a higher input frequency
> >>> to create a very specific frequency [some details are gone from my memory
> >>> though] they can't get otherwise.
> >>>
> >>> So I really don't want to break their working setup by introducing barriers
> >>> that are not strictly necessary.
> >>>
> >>> @Christoph: can you describe the bits from your fractional setup that
> >>> I've forgotten please?
> >>
> >> We need to set the I2S0 clock to 24.56 MHz.
> >>
> >> When restricting the input frequency to a maximum of 600 Mhz,
> >> we could use the integer divider to get 400 Mhz (dividing by 2).
> >> However, with the 400 Mhz as input to the frac divider,
> >> we run into the problem, that the maximum possible output frequency
> >> is 20 MHz (there is another restriction which states that the
> >> fraction input : output frequency must be >= 20).
> > 
> > just for clarification, what is the current input frequency you
> > already use sucessfully?
> 
> Our working setup uses the integer divider to reduce to 400 MHz
> and uses the frac divider to get something near 24.56 MHz.
> I have to admit I have never measured what's on the clock line.

Ah ok, so the 600MHz input maximum is ok for your setup and the "< 20"
ratio is the question. I thought I remembered you using a higher than
600MHz input rate. [bad memory on my side]




^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v1 5/6] clk: rockchip: add pll up and down when change pll freq
  2019-04-12 12:15   ` Heiko Stübner
@ 2019-04-12 17:28     ` Doug Anderson
  0 siblings, 0 replies; 16+ messages in thread
From: Doug Anderson @ 2019-04-12 17:28 UTC (permalink / raw)
  To: Heiko Stübner
  Cc: Elaine Zhang, Michael Turquette, Stephen Boyd, linux-clk,
	Linux ARM, open list:ARM/Rockchip SoC...,
	LKML, xxx, xf, 黄涛,
	Brian Norris

Hi,

On Fri, Apr 12, 2019 at 5:16 AM Heiko Stübner <heiko@sntech.de> wrote:
>
> Hi Elaine,
>
> Am Mittwoch, 3. April 2019, 11:44:09 CEST schrieb Elaine Zhang:
> > set pll sequence:
> >       ->set pll to slow mode or other plls
> >       ->set pll down
> >       ->set pll params
> >       ->set pll up
> >       ->wait pll lock status
> >       ->set pll to normal mode
> >
> > To slove the system error:
> > wait_pll_lock: timeout waiting for pll to lock
> > pll_set_params: pll update unsucessful,
> >               trying to restore old params
>
> Can you tell me on what soc this was experienced?
>
> The patch includes rk3399, but I don't think the CrOS kernel
> does powerdown the pll when changing the cpu-frequency
> [added Doug and Brian for clarification and possible testing :-) ]

As far as I can tell you're right.  We don't seem to have it and I'm
not aware of problems.


> But I did find that the M0 code in ATF does actually power-down the
> PLL and follow your outline from above. So essentially I'd just like
> a thumbs up from chromeos people if they have the time.

It does seem like it should be fine in general to do it.  It's one
extra step but presumably it should be fine.

In general the Rockchip PLL programming guidelines have always been a
bit funny.  Looking at the version of the doc I have, I see phrases
like "The PLL programming support changed on-the-fly and the PLL will
simply slew to the new frequency" which makes me feel like you're
supposed to be able to change the PLL frequency without powering down.
This is repeated in another part of the manual which talks about the
glitches that can happen when changing the PLL on the fly: it doesn't
say not to do it, it just says to expect glitches (which can be
avoided by changing the parent first).

...but then in another section of the doc it talks about asserting PD
before doing a frequency change!  :-P

Though in that same section it says: "Release PD after no less than
1us from the time it was asserted."  Even though probably 1 us has
passed, I'd still expect a udelay(1) to be explicit here.


One other thing that concerns me a little about this patch is that I
wonder if it is legal to call rockchip_rk3399_pll_set_params() while
the PLL is off.  AKA is it OK to change the rate of a PLL while it is
not enabled?  I'm not saying that this would have worked before
(actually, you might end up hitting the exact error "timeout waiting
for pll to lock"), but now it seems even worse because we'll
implicitly turning on the PLL.  ...a part of me wonders if this is the
root cause of the problem Elaine's patch is trying to solve: that some
code was trying to set the rate of a PLL before enabling it.


So, tl; dr:
* I doubt this patch is needed on rk3399, but it probably won't hurt.
* If you're going to do the power down, you should add the udelay()
* There's a bug on 3036.  See below.
* You should change your patch so it doesn't enable the PLL if it
wasn't already enabled.


> > Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com>
> > ---
> >  drivers/clk/rockchip/clk-pll.c | 19 +++++++++++++++++++
> >  1 file changed, 19 insertions(+)
> >
> > diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c
> > index dd0433d4753e..9fe1227e77e9 100644
> > --- a/drivers/clk/rockchip/clk-pll.c
> > +++ b/drivers/clk/rockchip/clk-pll.c
> > @@ -208,6 +208,11 @@ static int rockchip_rk3036_pll_set_params(struct rockchip_clk_pll *pll,
> >               rate_change_remuxed = 1;
> >       }
> >
> > +     /* set pll power down */
> > +     writel(HIWORD_UPDATE(1,
> > +                          RK3036_PLLCON1_PWRDOWN, 13),

This does not do what you think it does.  It should be:

HIWORD_UPDATE(RK3036_PLLCON1_PWRDOWN,
     RK3036_PLLCON1_PWRDOWN, 0)

...without that my compiler yells at me:

signed shift result (0x40000000000) requires 44 bits to represent

...and the compiler is, indeed, correct.


> > +            pll->reg_base + RK3036_PLLCON(1));
> > +
> >       /* update pll values */
> >       writel_relaxed(HIWORD_UPDATE(rate->fbdiv, RK3036_PLLCON0_FBDIV_MASK,
> >                                         RK3036_PLLCON0_FBDIV_SHIFT) |
> > @@ -229,6 +234,10 @@ static int rockchip_rk3036_pll_set_params(struct rockchip_clk_pll *pll,
> >       pllcon |= rate->frac << RK3036_PLLCON2_FRAC_SHIFT;
> >       writel_relaxed(pllcon, pll->reg_base + RK3036_PLLCON(2));
> >
> > +     /* set pll power up */
> > +     writel(HIWORD_UPDATE(0, RK3036_PLLCON1_PWRDOWN, 13),
> > +            pll->reg_base + RK3036_PLLCON(1));

In a similar vein, the above should be:

writel(HIWORD_UPDATE(0, RK3036_PLLCON1_PWRDOWN, 0),

...since RK3036_PLLCON1_PWRDOWN already has the shift.

^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2019-04-12 17:29 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-04-03  9:42 [PATCH v1 0/6] clk: rockchip: Support for some new features Elaine Zhang
2019-04-03  9:42 ` [PATCH v1 1/6] clk: rockchip: Add supprot to limit input rate for fractional divider Elaine Zhang
2019-04-12 11:52   ` Heiko Stübner
2019-04-12 12:12     ` Christoph Müllner
2019-04-12 12:21       ` Heiko Stübner
2019-04-12 12:32         ` Christoph Müllner
2019-04-12 12:39           ` Heiko Stübner
2019-04-03  9:42 ` [PATCH v1 2/6] clk: rockchip: fix up the frac clk get rate error Elaine Zhang
2019-04-03  9:42 ` [PATCH v1 3/6] clk: rockchip: add a COMPOSITE_DIV_OFFSET clock-type Elaine Zhang
2019-04-12 11:35   ` Heiko Stübner
2019-04-03  9:42 ` [PATCH v1 4/6] clk: rockchip: add a clock-type for muxes based in the pmugrf Elaine Zhang
2019-04-12 11:45   ` Heiko Stübner
2019-04-03  9:44 ` [PATCH v1 5/6] clk: rockchip: add pll up and down when change pll freq Elaine Zhang
2019-04-12 12:15   ` Heiko Stübner
2019-04-12 17:28     ` Doug Anderson
2019-04-03  9:44 ` [PATCH v1 6/6] clk: rockchip: support pll setting by auto Elaine Zhang

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).