clk: rk3368: add clk_pll_ops_3368_low_jitter and modify dclk_lcdc ops
authordkl <dkl@rock-chips.com>
Thu, 8 Jan 2015 03:37:44 +0000 (11:37 +0800)
committerHuang, Tao <huangtao@rock-chips.com>
Mon, 12 Jan 2015 07:31:16 +0000 (15:31 +0800)
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 <dkl@rock-chips.com>
arch/arm64/boot/dts/rk3368-clocks.dtsi
drivers/clk/rockchip/clk-ops.c
drivers/clk/rockchip/clk-pll.c
drivers/clk/rockchip/clk-pll.h
include/dt-bindings/clock/rockchip.h

index ced1d1b320fb9dd7c4769c5928713ed24ecb5657..b2eb9e45c97ca5c65a53b507cab9df8423e807fa 100644 (file)
                                        status-reg = <0x0480 5>;
                                        clocks = <&xin24m>;
                                        clock-output-names = "clk_npll";
-                                       rockchip,pll-type = <CLK_PLL_3188PLUS_AUTO>;
+                                       rockchip,pll-type = <CLK_PLL_3368_LOW_JITTER>;
                                        #clock-cells = <0>;
                                        #clock-init-cells = <1>;
                                };
index 8a13320bc50a4cdf977356117ba7d3fb6c559973..c303239c3f1c78993c636f59003ccb4e28e81bb1 100644 (file)
@@ -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)
index 193a79fb10880ffc86e99892a61e537426eb681f..9bc8347a85689dea390fc63a753dfc3d41883b84 100755 (executable)
@@ -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;
index 3ecc178a5903d993efac14fe363f693bfb977f51..f4e917df75eb377f5b4da4006fbaced73fdf764a 100755 (executable)
        .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, \
index 82e1f6b4b4b2d48def540f579a357696ebfda77f..dacc17a610ea113e80ddaa32946013b350f46e07 100644 (file)
@@ -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 */