From: Vladimir Zapolskiy Date: Fri, 1 Jul 2022 06:27:29 +0000 (+0300) Subject: clk: qcom: clk-alpha-pll: add Lucid EVO PLL configuration interfaces X-Git-Url: http://git.maquefel.me/?a=commitdiff_plain;h=260e36606a0391a300bbe412b339bb68fc7aa7d9;p=linux.git clk: qcom: clk-alpha-pll: add Lucid EVO PLL configuration interfaces 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 Signed-off-by: Vladimir Zapolskiy Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20220701062729.2757893-1-vladimir.zapolskiy@linaro.org --- diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c index 47879ee5a677d..cdb1035ae3ede 100644 --- a/drivers/clk/qcom/clk-alpha-pll.c +++ b/drivers/clk/qcom/clk-alpha-pll.c @@ -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); diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-pll.h index 6e9907deaf301..0b7a6859ca2c6 100644 --- a/drivers/clk/qcom/clk-alpha-pll.h +++ b/drivers/clk/qcom/clk-alpha-pll.h @@ -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