From 61ed90154ecc89ad61d35dab2e16006e5b6f39ee Mon Sep 17 00:00:00 2001 From: dkl Date: Thu, 8 Jan 2015 11:37:44 +0800 Subject: [PATCH] clk: rk3368: add clk_pll_ops_3368_low_jitter and modify dclk_lcdc ops In order to provide low jitter dclk_lcdc for dislay(especially HDMI), we neeed to set dclk_lcdc's src pll with max VCO. Thus we add clk_pll_ops_3368_low_jitter type pll to get pll low jitter setting from a table. Also dclk_lcdc ops in rk3368 is modifided to get best parent rate from a table firstly, or caculate a parent rate if not found in the table. Signed-off-by: dkl --- arch/arm64/boot/dts/rk3368-clocks.dtsi | 2 +- drivers/clk/rockchip/clk-ops.c | 20 +++++- drivers/clk/rockchip/clk-pll.c | 93 ++++++++++++++++++++++++++ drivers/clk/rockchip/clk-pll.h | 9 +++ include/dt-bindings/clock/rockchip.h | 1 + 5 files changed, 122 insertions(+), 3 deletions(-) diff --git a/arch/arm64/boot/dts/rk3368-clocks.dtsi b/arch/arm64/boot/dts/rk3368-clocks.dtsi index ced1d1b320fb..b2eb9e45c97c 100644 --- a/arch/arm64/boot/dts/rk3368-clocks.dtsi +++ b/arch/arm64/boot/dts/rk3368-clocks.dtsi @@ -234,7 +234,7 @@ status-reg = <0x0480 5>; clocks = <&xin24m>; clock-output-names = "clk_npll"; - rockchip,pll-type = ; + rockchip,pll-type = ; #clock-cells = <0>; #clock-init-cells = <1>; }; diff --git a/drivers/clk/rockchip/clk-ops.c b/drivers/clk/rockchip/clk-ops.c index 8a13320bc50a..c303239c3f1c 100644 --- a/drivers/clk/rockchip/clk-ops.c +++ b/drivers/clk/rockchip/clk-ops.c @@ -791,10 +791,26 @@ static long clk_3368_dclk_lcdc_determine_rate(struct clk_hw *hw, struct clk **best_parent_p) { struct clk *npll = clk_get(NULL, "clk_npll"); - unsigned long div, prate, best; + unsigned long div, prate, best, *p_prate; + static unsigned long rk3368_pll_rates[] = {1188*MHZ, 0}; - *best_parent_p = npll; + if (best_parent_p) + *best_parent_p = npll; + /* first get parent_rate from table */ + p_prate = rk3368_pll_rates; + + while (*p_prate) { + if (!(*p_prate % (rate*2)) || (*p_prate == rate)) { + clk_debug("%s: get rate from table\n", __func__); + *best_parent_rate = *p_prate; + best = rate; + return best; + } + p_prate++; + } + + /* if not suitable parent_rate found in table, then auto calc rate */ div = RK3368_LIMIT_NPLL/rate; /* div should be even */ if (div % 2) diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c index 193a79fb1088..9bc8347a8568 100755 --- a/drivers/clk/rockchip/clk-pll.c +++ b/drivers/clk/rockchip/clk-pll.c @@ -329,6 +329,12 @@ static const struct apll_clk_set rk3368_aplll_table[] = { _RK3368_APLL_SET_CLKS(0, 1, 32, 16, 2, 1, 1), }; +static const struct pll_clk_set rk3368_pll_table_low_jitter[] = { + /* _khz, nr, nf, no, nb */ + _RK3188PLUS_PLL_SET_CLKS_NB(1188000, 1, 99, 2, 1), + _RK3188PLUS_PLL_SET_CLKS( 0, 0, 0, 0), +}; + static void pll_wait_lock(struct clk_hw *hw) { struct clk_pll *pll = to_clk_pll(hw); @@ -1189,6 +1195,90 @@ static const struct clk_ops clk_pll_ops_3188plus_auto = { .is_enabled = clk_pll_is_enabled_3188plus, }; +static long clk_pll_round_rate_3368_low_jitter(struct clk_hw *hw, + unsigned long rate, + unsigned long *prate) +{ + unsigned long best; + struct pll_clk_set *p_clk_set; + + p_clk_set = (struct pll_clk_set *)(rk3368_pll_table_low_jitter); + + while (p_clk_set->rate) { + if (p_clk_set->rate == rate) + break; + p_clk_set++; + } + + if (p_clk_set->rate == rate) { + clk_debug("get rate from table\n"); + return rate; + } + + for (best = rate; best > 0; best--) { + if (!pll_clk_get_best_set(*prate, best, NULL, NULL, NULL)) + return best; + } + + clk_err("%s: can't round rate %lu\n", __func__, rate); + return 0; +} + + +static int clk_pll_set_rate_3368_low_jitter(struct clk_hw *hw, + unsigned long rate, + unsigned long parent_rate) +{ + unsigned long best; + u32 nr, nf, no; + struct pll_clk_set clk_set, *p_clk_set; + int ret; + + p_clk_set = (struct pll_clk_set *)(rk3368_pll_table_low_jitter); + + while (p_clk_set->rate) { + if (p_clk_set->rate == rate) + break; + p_clk_set++; + } + + if (p_clk_set->rate == rate) { + clk_debug("get rate from table\n"); + goto set_rate; + } + + best = clk_pll_round_rate_3188plus_auto(hw, rate, &parent_rate); + + if (!best) + return -EINVAL; + + pll_clk_get_best_set(parent_rate, best, &nr, &nf, &no); + + /* prepare clk_set */ + clk_set.rate = best; + clk_set.pllcon0 = RK3188PLUS_PLL_CLKR_SET(nr)|RK3188PLUS_PLL_CLKOD_SET(no); + clk_set.pllcon1 = RK3188PLUS_PLL_CLKF_SET(nf); + clk_set.pllcon2 = RK3188PLUS_PLL_CLK_BWADJ_SET(nf >> 1); + clk_set.rst_dly = ((nr*500)/24+1); + + p_clk_set = &clk_set; + +set_rate: + ret = _pll_clk_set_rate_3188plus(p_clk_set, hw); + clk_debug("pll %s set rate=%lu OK!\n", __clk_get_name(hw->clk), + p_clk_set->rate); + + return ret; +} + +static const struct clk_ops clk_pll_ops_3368_low_jitter = { + .recalc_rate = clk_pll_recalc_rate_3188plus_auto, + .round_rate = clk_pll_round_rate_3368_low_jitter, + .set_rate = clk_pll_set_rate_3368_low_jitter, + .enable = clk_pll_enable_3188plus, + .disable = clk_pll_disable_3188plus, + .is_enabled = clk_pll_is_enabled_3188plus, +}; /* CLK_PLL_3188PLUS_APLL type ops */ static unsigned long clk_pll_recalc_rate_3188plus_apll(struct clk_hw *hw, @@ -2428,6 +2518,9 @@ const struct clk_ops *rk_get_pll_ops(u32 pll_flags) case CLK_PLL_3368_APLLL: return &clk_pll_ops_3368_aplll; + case CLK_PLL_3368_LOW_JITTER: + return &clk_pll_ops_3368_low_jitter; + default: clk_err("%s: unknown pll_flags!\n", __func__); return NULL; diff --git a/drivers/clk/rockchip/clk-pll.h b/drivers/clk/rockchip/clk-pll.h index 3ecc178a5903..f4e917df75eb 100755 --- a/drivers/clk/rockchip/clk-pll.h +++ b/drivers/clk/rockchip/clk-pll.h @@ -194,6 +194,15 @@ .rst_dly = ((nr*500)/24+1),\ } +#define _RK3188PLUS_PLL_SET_CLKS_NB(_mhz, nr, nf, no, nb) \ +{ \ + .rate = (_mhz) * KHZ, \ + .pllcon0 = RK3188PLUS_PLL_CLKR_SET(nr)|RK3188PLUS_PLL_CLKOD_SET(no), \ + .pllcon1 = RK3188PLUS_PLL_CLKF_SET(nf),\ + .pllcon2 = RK3188PLUS_PLL_CLK_BWADJ_SET(nb-1),\ + .rst_dly = ((nr*500)/24+1),\ +} + #define _RK3188_APLL_SET_CLKS(_mhz, nr, nf, no, _periph_div, _aclk_div) \ { \ .rate = _mhz * MHZ, \ diff --git a/include/dt-bindings/clock/rockchip.h b/include/dt-bindings/clock/rockchip.h index 82e1f6b4b4b2..dacc17a610ea 100644 --- a/include/dt-bindings/clock/rockchip.h +++ b/include/dt-bindings/clock/rockchip.h @@ -45,6 +45,7 @@ #define CLK_PLL_312XPLUS BIT(8) #define CLK_PLL_3368_APLLB BIT(9) #define CLK_PLL_3368_APLLL BIT(10) +#define CLK_PLL_3368_LOW_JITTER BIT(11) /* rate_ops index */ -- 2.34.1