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 <dkl@rock-chips.com>
This commit is contained in:
dkl
2015-01-08 11:37:44 +08:00
committed by Huang, Tao
parent be11cff0b0
commit 61ed90154e
5 changed files with 122 additions and 3 deletions

View File

@@ -234,7 +234,7 @@
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>;
};

View 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)

View File

@@ -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;

View File

@@ -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, \

View 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 */