clk: tegra: move some PLLC and PLLXC init to clk-pll.c
authorPeter De Schrijver <pdeschrijver@nvidia.com>
Fri, 6 Sep 2013 11:37:37 +0000 (14:37 +0300)
committerPeter De Schrijver <pdeschrijver@nvidia.com>
Tue, 26 Nov 2013 16:46:21 +0000 (18:46 +0200)
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>
drivers/clk/tegra/clk-pll.c
drivers/clk/tegra/clk-tegra114.c

index 25734348242f6f815536eb2ca96bb98c0cb9bf89..8f51147185dbeaff0d0568f7f784d04320e0f9e5 100644 (file)
@@ -773,6 +773,48 @@ static int _pll_fixed_mdiv(struct tegra_clk_pll_params *pll_params,
                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)
 {
        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)
 {
        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)
                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 = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags,
                              freq_table, lock);
@@ -1455,6 +1525,9 @@ struct clk *tegra_clk_register_pllre(const char *name, const char *parent_name,
        struct clk *clk;
 
        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,
                              freq_table, lock);
        if (IS_ERR(pll))
@@ -1498,11 +1571,23 @@ struct clk *tegra_clk_register_pllm(const char *name, const char *parent_name,
                          spinlock_t *lock)
 {
        struct tegra_clk_pll *pll;
-       struct clk *clk;
+       struct clk *clk, *parent;
+       unsigned long parent_rate;
 
        if (!pll_params->pdiv_tohw)
                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_HAS_LOCK_ENABLE;
        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);
        }
 
+       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 = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags,
                              freq_table, lock);
        if (IS_ERR(pll))
                return ERR_CAST(pll);
 
-       parent_rate = __clk_get_rate(parent);
-
        /*
         * Most of PLLC register fields are shadowed, and can not be read
         * directly from PLL h/w. Hence, actual PLLC boot state is unknown.
index 9729af823eaf3f6663605f76c53cc6a66d79a895..fa562e3e8f19a806e37e587b83e78e18b9307db5 100644 (file)
@@ -1077,63 +1077,6 @@ static __init void tegra114_utmi_param_configure(void __iomem *clk_base)
        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,
                                     void __iomem *pmc)
 {
@@ -1141,28 +1084,23 @@ static void __init tegra114_pll_init(void __iomem *clk_base,
        struct clk *clk;
 
        /* 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,
-                               pmc, 0, 0, &pll_c_params, TEGRA_PLL_USE_LOCK,
-                               pll_c_freq_table, NULL);
-               clk_register_clkdev(clk, "pll_c", NULL);
-               clks[TEGRA114_CLK_PLL_C] = clk;
-
-               /* PLLC_OUT1 */
-               clk = tegra_clk_register_divider("pll_c_out1_div", "pll_c",
-                               clk_base + PLLC_OUT, 0, TEGRA_DIVIDER_ROUND_UP,
-                               8, 8, 1, NULL);
-               clk = tegra_clk_register_pll_out("pll_c_out1", "pll_c_out1_div",
-                                       clk_base + PLLC_OUT, 1, 0,
-                                       CLK_SET_RATE_PARENT, 0, NULL);
-               clk_register_clkdev(clk, "pll_c_out1", NULL);
-               clks[TEGRA114_CLK_PLL_C_OUT1] = clk;
-       }
+       clk = tegra_clk_register_pllxc("pll_c", "pll_ref", clk_base,
+                       pmc, 0, 0, &pll_c_params, TEGRA_PLL_USE_LOCK,
+                       pll_c_freq_table, NULL);
+       clk_register_clkdev(clk, "pll_c", NULL);
+       clks[TEGRA114_CLK_PLL_C] = clk;
+
+       /* PLLC_OUT1 */
+       clk = tegra_clk_register_divider("pll_c_out1_div", "pll_c",
+                       clk_base + PLLC_OUT, 0, TEGRA_DIVIDER_ROUND_UP,
+                       8, 8, 1, NULL);
+       clk = tegra_clk_register_pll_out("pll_c_out1", "pll_c_out1_div",
+                               clk_base + PLLC_OUT, 1, 0,
+                               CLK_SET_RATE_PARENT, 0, NULL);
+       clk_register_clkdev(clk, "pll_c_out1", NULL);
+       clks[TEGRA114_CLK_PLL_C_OUT1] = clk;
 
        /* PLLC2 */
-       _clip_vco_min(&pll_c2_params);
        clk = tegra_clk_register_pllc("pll_c2", "pll_ref", clk_base, pmc, 0, 0,
                             &pll_c2_params, TEGRA_PLL_USE_LOCK,
                             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;
 
        /* PLLC3 */
-       _clip_vco_min(&pll_c3_params);
        clk = tegra_clk_register_pllc("pll_c3", "pll_ref", clk_base, pmc, 0, 0,
                             &pll_c3_params, TEGRA_PLL_USE_LOCK,
                             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;
 
        /* PLLM */
-       _clip_vco_min(&pll_m_params);
        clk = tegra_clk_register_pllm("pll_m", "pll_ref", clk_base, pmc,
                             CLK_IGNORE_UNUSED | CLK_SET_RATE_GATE, 0,
                             &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);
 
        /* 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,
-                               pmc, CLK_IGNORE_UNUSED, 0, &pll_x_params,
-                               TEGRA_PLL_USE_LOCK, pll_x_freq_table, NULL);
-               clk_register_clkdev(clk, "pll_x", NULL);
-               clks[TEGRA114_CLK_PLL_X] = clk;
-       }
+       clk = tegra_clk_register_pllxc("pll_x", "pll_ref", clk_base,
+                       pmc, CLK_IGNORE_UNUSED, 0, &pll_x_params,
+                       TEGRA_PLL_USE_LOCK, pll_x_freq_table, NULL);
+       clk_register_clkdev(clk, "pll_x", NULL);
+       clks[TEGRA114_CLK_PLL_X] = clk;
 
        /* PLLX_OUT0 */
        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;
 
        /* PLLRE */
-       _clip_vco_min(&pll_re_vco_params);
        clk = tegra_clk_register_pllre("pll_re_vco", "pll_ref", clk_base, pmc,
                             0, 0, &pll_re_vco_params, TEGRA_PLL_USE_LOCK,
                             NULL, &pll_re_lock, pll_ref_freq);