clk: tegra: move some PLLC and PLLXC init to clk-pll.c
VCO min clipping, dynamic ramp setup and IDDQ init can be done in the respective PLL clk_register functions if the parent is already registered. This is done for other some PLLs already. Signed-off-by: Peter De Schrijver <pdeschrijver@nvidia.com>
This commit is contained in:
parent
5bb9d26700
commit
04edb099a4
|
@ -773,6 +773,48 @@ static int _pll_fixed_mdiv(struct tegra_clk_pll_params *pll_params,
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static unsigned long _clip_vco_min(unsigned long vco_min,
|
||||||
|
unsigned long parent_rate)
|
||||||
|
{
|
||||||
|
return DIV_ROUND_UP(vco_min, parent_rate) * parent_rate;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _setup_dynamic_ramp(struct tegra_clk_pll_params *pll_params,
|
||||||
|
void __iomem *clk_base,
|
||||||
|
unsigned long parent_rate)
|
||||||
|
{
|
||||||
|
u32 val;
|
||||||
|
u32 step_a, step_b;
|
||||||
|
|
||||||
|
switch (parent_rate) {
|
||||||
|
case 12000000:
|
||||||
|
case 13000000:
|
||||||
|
case 26000000:
|
||||||
|
step_a = 0x2B;
|
||||||
|
step_b = 0x0B;
|
||||||
|
break;
|
||||||
|
case 16800000:
|
||||||
|
step_a = 0x1A;
|
||||||
|
step_b = 0x09;
|
||||||
|
break;
|
||||||
|
case 19200000:
|
||||||
|
step_a = 0x12;
|
||||||
|
step_b = 0x08;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
pr_err("%s: Unexpected reference rate %lu\n",
|
||||||
|
__func__, parent_rate);
|
||||||
|
WARN_ON(1);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
val = step_a << pll_params->stepa_shift;
|
||||||
|
val |= step_b << pll_params->stepb_shift;
|
||||||
|
writel_relaxed(val, clk_base + pll_params->dyn_ramp_reg);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int clk_pll_iddq_enable(struct clk_hw *hw)
|
static int clk_pll_iddq_enable(struct clk_hw *hw)
|
||||||
{
|
{
|
||||||
struct tegra_clk_pll *pll = to_clk_pll(hw);
|
struct tegra_clk_pll *pll = to_clk_pll(hw);
|
||||||
|
@ -1423,11 +1465,39 @@ struct clk *tegra_clk_register_pllxc(const char *name, const char *parent_name,
|
||||||
spinlock_t *lock)
|
spinlock_t *lock)
|
||||||
{
|
{
|
||||||
struct tegra_clk_pll *pll;
|
struct tegra_clk_pll *pll;
|
||||||
struct clk *clk;
|
struct clk *clk, *parent;
|
||||||
|
unsigned long parent_rate;
|
||||||
|
int err;
|
||||||
|
u32 val, val_iddq;
|
||||||
|
|
||||||
|
parent = __clk_lookup(parent_name);
|
||||||
|
if (IS_ERR(parent)) {
|
||||||
|
WARN(1, "parent clk %s of %s must be registered first\n",
|
||||||
|
name, parent_name);
|
||||||
|
return ERR_PTR(-EINVAL);
|
||||||
|
}
|
||||||
|
|
||||||
if (!pll_params->pdiv_tohw)
|
if (!pll_params->pdiv_tohw)
|
||||||
return ERR_PTR(-EINVAL);
|
return ERR_PTR(-EINVAL);
|
||||||
|
|
||||||
|
parent_rate = __clk_get_rate(parent);
|
||||||
|
|
||||||
|
pll_params->vco_min = _clip_vco_min(pll_params->vco_min, parent_rate);
|
||||||
|
|
||||||
|
err = _setup_dynamic_ramp(pll_params, clk_base, parent_rate);
|
||||||
|
if (err)
|
||||||
|
return ERR_PTR(err);
|
||||||
|
|
||||||
|
val = readl_relaxed(clk_base + pll_params->base_reg);
|
||||||
|
val_iddq = readl_relaxed(clk_base + pll_params->iddq_reg);
|
||||||
|
|
||||||
|
if (val & PLL_BASE_ENABLE)
|
||||||
|
WARN_ON(val_iddq & BIT(pll_params->iddq_bit_idx));
|
||||||
|
else {
|
||||||
|
val_iddq |= BIT(pll_params->iddq_bit_idx);
|
||||||
|
writel_relaxed(val_iddq, clk_base + pll_params->iddq_reg);
|
||||||
|
}
|
||||||
|
|
||||||
pll_flags |= TEGRA_PLL_HAS_LOCK_ENABLE;
|
pll_flags |= TEGRA_PLL_HAS_LOCK_ENABLE;
|
||||||
pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags,
|
pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags,
|
||||||
freq_table, lock);
|
freq_table, lock);
|
||||||
|
@ -1455,6 +1525,9 @@ struct clk *tegra_clk_register_pllre(const char *name, const char *parent_name,
|
||||||
struct clk *clk;
|
struct clk *clk;
|
||||||
|
|
||||||
pll_flags |= TEGRA_PLL_HAS_LOCK_ENABLE | TEGRA_PLL_LOCK_MISC;
|
pll_flags |= TEGRA_PLL_HAS_LOCK_ENABLE | TEGRA_PLL_LOCK_MISC;
|
||||||
|
|
||||||
|
pll_params->vco_min = _clip_vco_min(pll_params->vco_min, parent_rate);
|
||||||
|
|
||||||
pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags,
|
pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags,
|
||||||
freq_table, lock);
|
freq_table, lock);
|
||||||
if (IS_ERR(pll))
|
if (IS_ERR(pll))
|
||||||
|
@ -1498,11 +1571,23 @@ struct clk *tegra_clk_register_pllm(const char *name, const char *parent_name,
|
||||||
spinlock_t *lock)
|
spinlock_t *lock)
|
||||||
{
|
{
|
||||||
struct tegra_clk_pll *pll;
|
struct tegra_clk_pll *pll;
|
||||||
struct clk *clk;
|
struct clk *clk, *parent;
|
||||||
|
unsigned long parent_rate;
|
||||||
|
|
||||||
if (!pll_params->pdiv_tohw)
|
if (!pll_params->pdiv_tohw)
|
||||||
return ERR_PTR(-EINVAL);
|
return ERR_PTR(-EINVAL);
|
||||||
|
|
||||||
|
parent = __clk_lookup(parent_name);
|
||||||
|
if (IS_ERR(parent)) {
|
||||||
|
WARN(1, "parent clk %s of %s must be registered first\n",
|
||||||
|
name, parent_name);
|
||||||
|
return ERR_PTR(-EINVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
parent_rate = __clk_get_rate(parent);
|
||||||
|
|
||||||
|
pll_params->vco_min = _clip_vco_min(pll_params->vco_min, parent_rate);
|
||||||
|
|
||||||
pll_flags |= TEGRA_PLL_BYPASS;
|
pll_flags |= TEGRA_PLL_BYPASS;
|
||||||
pll_flags |= TEGRA_PLL_HAS_LOCK_ENABLE;
|
pll_flags |= TEGRA_PLL_HAS_LOCK_ENABLE;
|
||||||
pll_flags |= TEGRA_PLLM;
|
pll_flags |= TEGRA_PLLM;
|
||||||
|
@ -1543,14 +1628,16 @@ struct clk *tegra_clk_register_pllc(const char *name, const char *parent_name,
|
||||||
return ERR_PTR(-EINVAL);
|
return ERR_PTR(-EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
parent_rate = __clk_get_rate(parent);
|
||||||
|
|
||||||
|
pll_params->vco_min = _clip_vco_min(pll_params->vco_min, parent_rate);
|
||||||
|
|
||||||
pll_flags |= TEGRA_PLL_BYPASS;
|
pll_flags |= TEGRA_PLL_BYPASS;
|
||||||
pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags,
|
pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags,
|
||||||
freq_table, lock);
|
freq_table, lock);
|
||||||
if (IS_ERR(pll))
|
if (IS_ERR(pll))
|
||||||
return ERR_CAST(pll);
|
return ERR_CAST(pll);
|
||||||
|
|
||||||
parent_rate = __clk_get_rate(parent);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Most of PLLC register fields are shadowed, and can not be read
|
* Most of PLLC register fields are shadowed, and can not be read
|
||||||
* directly from PLL h/w. Hence, actual PLLC boot state is unknown.
|
* directly from PLL h/w. Hence, actual PLLC boot state is unknown.
|
||||||
|
|
|
@ -1077,63 +1077,6 @@ static __init void tegra114_utmi_param_configure(void __iomem *clk_base)
|
||||||
writel_relaxed(reg, clk_base + UTMIPLL_HW_PWRDN_CFG0);
|
writel_relaxed(reg, clk_base + UTMIPLL_HW_PWRDN_CFG0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __init _clip_vco_min(struct tegra_clk_pll_params *pll_params)
|
|
||||||
{
|
|
||||||
pll_params->vco_min =
|
|
||||||
DIV_ROUND_UP(pll_params->vco_min, pll_ref_freq) * pll_ref_freq;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int __init _setup_dynamic_ramp(struct tegra_clk_pll_params *pll_params,
|
|
||||||
void __iomem *clk_base)
|
|
||||||
{
|
|
||||||
u32 val;
|
|
||||||
u32 step_a, step_b;
|
|
||||||
|
|
||||||
switch (pll_ref_freq) {
|
|
||||||
case 12000000:
|
|
||||||
case 13000000:
|
|
||||||
case 26000000:
|
|
||||||
step_a = 0x2B;
|
|
||||||
step_b = 0x0B;
|
|
||||||
break;
|
|
||||||
case 16800000:
|
|
||||||
step_a = 0x1A;
|
|
||||||
step_b = 0x09;
|
|
||||||
break;
|
|
||||||
case 19200000:
|
|
||||||
step_a = 0x12;
|
|
||||||
step_b = 0x08;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
pr_err("%s: Unexpected reference rate %lu\n",
|
|
||||||
__func__, pll_ref_freq);
|
|
||||||
WARN_ON(1);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
val = step_a << pll_params->stepa_shift;
|
|
||||||
val |= step_b << pll_params->stepb_shift;
|
|
||||||
writel_relaxed(val, clk_base + pll_params->dyn_ramp_reg);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void __init _init_iddq(struct tegra_clk_pll_params *pll_params,
|
|
||||||
void __iomem *clk_base)
|
|
||||||
{
|
|
||||||
u32 val, val_iddq;
|
|
||||||
|
|
||||||
val = readl_relaxed(clk_base + pll_params->base_reg);
|
|
||||||
val_iddq = readl_relaxed(clk_base + pll_params->iddq_reg);
|
|
||||||
|
|
||||||
if (val & BIT(30))
|
|
||||||
WARN_ON(val_iddq & BIT(pll_params->iddq_bit_idx));
|
|
||||||
else {
|
|
||||||
val_iddq |= BIT(pll_params->iddq_bit_idx);
|
|
||||||
writel_relaxed(val_iddq, clk_base + pll_params->iddq_reg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void __init tegra114_pll_init(void __iomem *clk_base,
|
static void __init tegra114_pll_init(void __iomem *clk_base,
|
||||||
void __iomem *pmc)
|
void __iomem *pmc)
|
||||||
{
|
{
|
||||||
|
@ -1141,9 +1084,6 @@ static void __init tegra114_pll_init(void __iomem *clk_base,
|
||||||
struct clk *clk;
|
struct clk *clk;
|
||||||
|
|
||||||
/* PLLC */
|
/* PLLC */
|
||||||
_clip_vco_min(&pll_c_params);
|
|
||||||
if (_setup_dynamic_ramp(&pll_c_params, clk_base) >= 0) {
|
|
||||||
_init_iddq(&pll_c_params, clk_base);
|
|
||||||
clk = tegra_clk_register_pllxc("pll_c", "pll_ref", clk_base,
|
clk = tegra_clk_register_pllxc("pll_c", "pll_ref", clk_base,
|
||||||
pmc, 0, 0, &pll_c_params, TEGRA_PLL_USE_LOCK,
|
pmc, 0, 0, &pll_c_params, TEGRA_PLL_USE_LOCK,
|
||||||
pll_c_freq_table, NULL);
|
pll_c_freq_table, NULL);
|
||||||
|
@ -1159,10 +1099,8 @@ static void __init tegra114_pll_init(void __iomem *clk_base,
|
||||||
CLK_SET_RATE_PARENT, 0, NULL);
|
CLK_SET_RATE_PARENT, 0, NULL);
|
||||||
clk_register_clkdev(clk, "pll_c_out1", NULL);
|
clk_register_clkdev(clk, "pll_c_out1", NULL);
|
||||||
clks[TEGRA114_CLK_PLL_C_OUT1] = clk;
|
clks[TEGRA114_CLK_PLL_C_OUT1] = clk;
|
||||||
}
|
|
||||||
|
|
||||||
/* PLLC2 */
|
/* PLLC2 */
|
||||||
_clip_vco_min(&pll_c2_params);
|
|
||||||
clk = tegra_clk_register_pllc("pll_c2", "pll_ref", clk_base, pmc, 0, 0,
|
clk = tegra_clk_register_pllc("pll_c2", "pll_ref", clk_base, pmc, 0, 0,
|
||||||
&pll_c2_params, TEGRA_PLL_USE_LOCK,
|
&pll_c2_params, TEGRA_PLL_USE_LOCK,
|
||||||
pll_cx_freq_table, NULL);
|
pll_cx_freq_table, NULL);
|
||||||
|
@ -1170,7 +1108,6 @@ static void __init tegra114_pll_init(void __iomem *clk_base,
|
||||||
clks[TEGRA114_CLK_PLL_C2] = clk;
|
clks[TEGRA114_CLK_PLL_C2] = clk;
|
||||||
|
|
||||||
/* PLLC3 */
|
/* PLLC3 */
|
||||||
_clip_vco_min(&pll_c3_params);
|
|
||||||
clk = tegra_clk_register_pllc("pll_c3", "pll_ref", clk_base, pmc, 0, 0,
|
clk = tegra_clk_register_pllc("pll_c3", "pll_ref", clk_base, pmc, 0, 0,
|
||||||
&pll_c3_params, TEGRA_PLL_USE_LOCK,
|
&pll_c3_params, TEGRA_PLL_USE_LOCK,
|
||||||
pll_cx_freq_table, NULL);
|
pll_cx_freq_table, NULL);
|
||||||
|
@ -1232,7 +1169,6 @@ static void __init tegra114_pll_init(void __iomem *clk_base,
|
||||||
clks[TEGRA114_CLK_PLL_P_OUT4] = clk;
|
clks[TEGRA114_CLK_PLL_P_OUT4] = clk;
|
||||||
|
|
||||||
/* PLLM */
|
/* PLLM */
|
||||||
_clip_vco_min(&pll_m_params);
|
|
||||||
clk = tegra_clk_register_pllm("pll_m", "pll_ref", clk_base, pmc,
|
clk = tegra_clk_register_pllm("pll_m", "pll_ref", clk_base, pmc,
|
||||||
CLK_IGNORE_UNUSED | CLK_SET_RATE_GATE, 0,
|
CLK_IGNORE_UNUSED | CLK_SET_RATE_GATE, 0,
|
||||||
&pll_m_params, TEGRA_PLL_USE_LOCK,
|
&pll_m_params, TEGRA_PLL_USE_LOCK,
|
||||||
|
@ -1255,15 +1191,11 @@ static void __init tegra114_pll_init(void __iomem *clk_base,
|
||||||
CLK_SET_RATE_PARENT, 1, 1);
|
CLK_SET_RATE_PARENT, 1, 1);
|
||||||
|
|
||||||
/* PLLX */
|
/* PLLX */
|
||||||
_clip_vco_min(&pll_x_params);
|
|
||||||
if (_setup_dynamic_ramp(&pll_x_params, clk_base) >= 0) {
|
|
||||||
_init_iddq(&pll_x_params, clk_base);
|
|
||||||
clk = tegra_clk_register_pllxc("pll_x", "pll_ref", clk_base,
|
clk = tegra_clk_register_pllxc("pll_x", "pll_ref", clk_base,
|
||||||
pmc, CLK_IGNORE_UNUSED, 0, &pll_x_params,
|
pmc, CLK_IGNORE_UNUSED, 0, &pll_x_params,
|
||||||
TEGRA_PLL_USE_LOCK, pll_x_freq_table, NULL);
|
TEGRA_PLL_USE_LOCK, pll_x_freq_table, NULL);
|
||||||
clk_register_clkdev(clk, "pll_x", NULL);
|
clk_register_clkdev(clk, "pll_x", NULL);
|
||||||
clks[TEGRA114_CLK_PLL_X] = clk;
|
clks[TEGRA114_CLK_PLL_X] = clk;
|
||||||
}
|
|
||||||
|
|
||||||
/* PLLX_OUT0 */
|
/* PLLX_OUT0 */
|
||||||
clk = clk_register_fixed_factor(NULL, "pll_x_out0", "pll_x",
|
clk = clk_register_fixed_factor(NULL, "pll_x_out0", "pll_x",
|
||||||
|
@ -1356,7 +1288,6 @@ static void __init tegra114_pll_init(void __iomem *clk_base,
|
||||||
clks[TEGRA114_CLK_PLL_A_OUT0] = clk;
|
clks[TEGRA114_CLK_PLL_A_OUT0] = clk;
|
||||||
|
|
||||||
/* PLLRE */
|
/* PLLRE */
|
||||||
_clip_vco_min(&pll_re_vco_params);
|
|
||||||
clk = tegra_clk_register_pllre("pll_re_vco", "pll_ref", clk_base, pmc,
|
clk = tegra_clk_register_pllre("pll_re_vco", "pll_ref", clk_base, pmc,
|
||||||
0, 0, &pll_re_vco_params, TEGRA_PLL_USE_LOCK,
|
0, 0, &pll_re_vco_params, TEGRA_PLL_USE_LOCK,
|
||||||
NULL, &pll_re_lock, pll_ref_freq);
|
NULL, &pll_re_lock, pll_ref_freq);
|
||||||
|
|
Loading…
Reference in New Issue