clk: qcom: clk-alpha-pll: add Lucid EVO PLL configuration interfaces
authorVladimir Zapolskiy <vladimir.zapolskiy@linaro.org>
Fri, 1 Jul 2022 06:27:29 +0000 (09:27 +0300)
committerBjorn Andersson <bjorn.andersson@linaro.org>
Wed, 6 Jul 2022 20:20:59 +0000 (15:20 -0500)
Add controls for Lucid EVO PLL configuration and export control functions
to clock controller drivers, the PLL is used by Qualcomm SM8450 camera
and display clock controllers.

Reviewed-by: Vinod Koul <vkoul@kernel.org>
Signed-off-by: Vladimir Zapolskiy <vladimir.zapolskiy@linaro.org>
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
Link: https://lore.kernel.org/r/20220701062729.2757893-1-vladimir.zapolskiy@linaro.org
drivers/clk/qcom/clk-alpha-pll.c
drivers/clk/qcom/clk-alpha-pll.h

index 47879ee5a677d744ef0bdebe86a8c481e73a3481..cdb1035ae3ede0aeafbe0874f0cdcd8b899dc48c 100644 (file)
@@ -191,8 +191,10 @@ EXPORT_SYMBOL_GPL(clk_alpha_pll_regs);
 #define LUCID_5LPE_ENABLE_VOTE_RUN     BIT(21)
 
 /* LUCID EVO PLL specific settings and offsets */
+#define LUCID_EVO_PCAL_NOT_DONE                BIT(8)
 #define LUCID_EVO_ENABLE_VOTE_RUN       BIT(25)
 #define LUCID_EVO_PLL_L_VAL_MASK        GENMASK(15, 0)
+#define LUCID_EVO_PLL_CAL_L_VAL_SHIFT  16
 
 /* ZONDA PLL specific */
 #define ZONDA_PLL_OUT_MASK     0xf
@@ -1994,6 +1996,32 @@ const struct clk_ops clk_alpha_pll_zonda_ops = {
 };
 EXPORT_SYMBOL_GPL(clk_alpha_pll_zonda_ops);
 
+void clk_lucid_evo_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
+                                const struct alpha_pll_config *config)
+{
+       u32 lval = config->l;
+
+       lval |= TRION_PLL_CAL_VAL << LUCID_EVO_PLL_CAL_L_VAL_SHIFT;
+       clk_alpha_pll_write_config(regmap, PLL_L_VAL(pll), lval);
+       clk_alpha_pll_write_config(regmap, PLL_ALPHA_VAL(pll), config->alpha);
+       clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL(pll), config->config_ctl_val);
+       clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL_U(pll), config->config_ctl_hi_val);
+       clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL_U1(pll), config->config_ctl_hi1_val);
+       clk_alpha_pll_write_config(regmap, PLL_USER_CTL(pll), config->user_ctl_val);
+       clk_alpha_pll_write_config(regmap, PLL_USER_CTL_U(pll), config->user_ctl_hi_val);
+       clk_alpha_pll_write_config(regmap, PLL_TEST_CTL(pll), config->test_ctl_val);
+       clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U(pll), config->test_ctl_hi_val);
+       clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U1(pll), config->test_ctl_hi1_val);
+
+       /* Disable PLL output */
+       regmap_update_bits(regmap, PLL_MODE(pll), PLL_OUTCTRL, 0);
+
+       /* Set operation mode to STANDBY and de-assert the reset */
+       regmap_write(regmap, PLL_OPMODE(pll), PLL_STANDBY);
+       regmap_update_bits(regmap, PLL_MODE(pll), PLL_RESET_N, PLL_RESET_N);
+}
+EXPORT_SYMBOL_GPL(clk_lucid_evo_pll_configure);
+
 static int alpha_pll_lucid_evo_enable(struct clk_hw *hw)
 {
        struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
@@ -2079,6 +2107,31 @@ static void alpha_pll_lucid_evo_disable(struct clk_hw *hw)
        regmap_write(regmap, PLL_OPMODE(pll), PLL_STANDBY);
 }
 
+static int alpha_pll_lucid_evo_prepare(struct clk_hw *hw)
+{
+       struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
+       struct clk_hw *p;
+       u32 val = 0;
+       int ret;
+
+       /* Return early if calibration is not needed. */
+       regmap_read(pll->clkr.regmap, PLL_MODE(pll), &val);
+       if (!(val & LUCID_EVO_PCAL_NOT_DONE))
+               return 0;
+
+       p = clk_hw_get_parent(hw);
+       if (!p)
+               return -EINVAL;
+
+       ret = alpha_pll_lucid_evo_enable(hw);
+       if (ret)
+               return ret;
+
+       alpha_pll_lucid_evo_disable(hw);
+
+       return 0;
+}
+
 static unsigned long alpha_pll_lucid_evo_recalc_rate(struct clk_hw *hw,
                                                     unsigned long parent_rate)
 {
@@ -2114,3 +2167,14 @@ const struct clk_ops clk_alpha_pll_postdiv_lucid_evo_ops = {
        .set_rate = clk_lucid_evo_pll_postdiv_set_rate,
 };
 EXPORT_SYMBOL_GPL(clk_alpha_pll_postdiv_lucid_evo_ops);
+
+const struct clk_ops clk_alpha_pll_lucid_evo_ops = {
+       .prepare = alpha_pll_lucid_evo_prepare,
+       .enable = alpha_pll_lucid_evo_enable,
+       .disable = alpha_pll_lucid_evo_disable,
+       .is_enabled = clk_trion_pll_is_enabled,
+       .recalc_rate = alpha_pll_lucid_evo_recalc_rate,
+       .round_rate = clk_alpha_pll_round_rate,
+       .set_rate = alpha_pll_lucid_5lpe_set_rate,
+};
+EXPORT_SYMBOL_GPL(clk_alpha_pll_lucid_evo_ops);
index 6e9907deaf3010dd613ddcd0a022e8ba170fda2c..0b7a6859ca2c686a5e7ed184bd177ab7751c2fb7 100644 (file)
@@ -152,6 +152,8 @@ extern const struct clk_ops clk_alpha_pll_postdiv_lucid_5lpe_ops;
 
 extern const struct clk_ops clk_alpha_pll_zonda_ops;
 #define clk_alpha_pll_postdiv_zonda_ops clk_alpha_pll_postdiv_fabia_ops
+
+extern const struct clk_ops clk_alpha_pll_lucid_evo_ops;
 extern const struct clk_ops clk_alpha_pll_fixed_lucid_evo_ops;
 extern const struct clk_ops clk_alpha_pll_postdiv_lucid_evo_ops;
 
@@ -168,6 +170,7 @@ void clk_agera_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
 
 void clk_zonda_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
                             const struct alpha_pll_config *config);
-
+void clk_lucid_evo_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
+                                const struct alpha_pll_config *config);
 
 #endif