Re: [PATCH v1 1/7] clk: qcom: clk-alpha-pll: Add support for Fabia PLL calibration

From: Stephen Boyd
Date: Tue Nov 05 2019 - 19:37:03 EST


Quoting Taniya Das (2019-10-31 05:21:07)
> diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c
> index 055318f..8cb77ca 100644
> --- a/drivers/clk/qcom/clk-alpha-pll.c
> +++ b/drivers/clk/qcom/clk-alpha-pll.c
> @@ -1141,15 +1160,11 @@ static int alpha_pll_fabia_set_rate(struct clk_hw *hw, unsigned long rate,
> unsigned long prate)
> {
> struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
> - u32 val, l, alpha_width = pll_alpha_width(pll);
> + u32 l, alpha_width = pll_alpha_width(pll);
> u64 a;
> unsigned long rrate;
> int ret = 0;
>
> - ret = regmap_read(pll->clkr.regmap, PLL_MODE(pll), &val);
> - if (ret)
> - return ret;
> -
> rrate = alpha_pll_round_rate(rate, prate, &l, &a, alpha_width);
>
> /*

How is this diff related? Looks like it should be split off into another
patch to remove a useless register read.

> @@ -1167,7 +1182,66 @@ static int alpha_pll_fabia_set_rate(struct clk_hw *hw, unsigned long rate,
> return __clk_alpha_pll_update_latch(pll);
> }
>
> +static int alpha_pll_fabia_prepare(struct clk_hw *hw)
> +{

Why are we doing this in prepare vs. doing it at PLL configuration time?
Does it need to be recalibrated each time the PLL is enabled?

> + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
> + const struct pll_vco *vco;
> + struct clk_hw *parent_hw;
> + unsigned long cal_freq, rrate;
> + u32 cal_l, regval, alpha_width = pll_alpha_width(pll);
> + u64 a;
> + int ret;
> +
> + /* Check if calibration needs to be done i.e. PLL is in reset */
> + ret = regmap_read(pll->clkr.regmap, PLL_MODE(pll), &regval);

Please use 'val' instead of 'regval' as regval almost never appears in
this file already.

> + if (ret)
> + return ret;
> +
> + /* Return early if calibration is not needed. */
> + if (regval & PLL_RESET_N)
> + return 0;
> +
> + vco = alpha_pll_find_vco(pll, clk_hw_get_rate(hw));
> + if (!vco) {
> + pr_err("alpha pll: not in a valid vco range\n");
> + return -EINVAL;
> + }
> +
> + cal_freq = DIV_ROUND_CLOSEST((pll->vco_table[0].min_freq +
> + pll->vco_table[0].max_freq) * 54, 100);

Do we need to cast the first argument to a u64 to avoid overflow?

> +
> + parent_hw = clk_hw_get_parent(hw);
> + if (!parent_hw)
> + return -EINVAL;
> +
> + rrate = alpha_pll_round_rate(cal_freq, clk_hw_get_rate(parent_hw),
> + &cal_l, &a, alpha_width);
> + /*
> + * Due to a limited number of bits for fractional rate programming, the
> + * rounded up rate could be marginally higher than the requested rate.
> + */
> + if (rrate > (cal_freq + FABIA_PLL_RATE_MARGIN) || rrate < cal_freq) {
> + pr_err("Call set rate on the PLL with rounded rates!\n");

This message is weird. Drivers shouldn't need to call set rate with
rounded rates. What is going on?

> + return -EINVAL;
> + }
> +
> + /* Setup PLL for calibration frequency */
> + regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL(pll), cal_l);
> +
> + /* Bringup the pll at calibration frequency */

capitalize PLL.

> + ret = clk_alpha_pll_enable(hw);
> + if (ret) {
> + pr_err("alpha pll calibration failed\n");
> + return ret;
> + }
> +
> + clk_alpha_pll_disable(hw);
> +
> + return 0;
> +}
> +