On 26.03.2024 1:15 PM, Gabor Juhos wrote: > The clk_alpha_pll_stromer_set_rate() function writes inproper > values into the ALPHA_VAL{,_U} registers which results in wrong > clock rates when the alpha value is used. > > The broken behaviour can be seen on IPQ5018 for example, when > dynamic scaling sets the CPU frequency to 800000 KHz. In this > case the CPU cores are running only at 792031 KHz: > > # cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq > 800000 > # cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_cur_freq > 792031 > > This happens because the function ignores the fact that the alpha > value calculated by the alpha_pll_round_rate() function is only > 32 bits wide which must be extended to 40 bits if it is used on > a hardware which supports 40 bits wide values. > > Extend the clk_alpha_pll_stromer_set_rate() function to convert > the alpha value to 40 bits before wrinting that into the registers > in order to ensure that the hardware really uses the requested rate. > > After the change the CPU frequency is correct: > > # cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq > 800000 > # cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_cur_freq > 800000 > > Cc: stable@xxxxxxxxxxxxxxx > Fixes: e47a4f55f240 ("clk: qcom: clk-alpha-pll: Add support for Stromer PLLs") > Signed-off-by: Gabor Juhos <j4g8y7@xxxxxxxxx> > --- > Changes in v2: > - fix subject prefix > - rebase on v6.9-rc1 > - Link to v1: https://lore.kernel.org/r/20240324-alpha-pll-fix-stromer-set-rate-v1-1-335b0b157219@xxxxxxxxx > > Depends on the following patch: > https://lore.kernel.org/r/20240315-apss-ipq-pll-ipq5018-hang-v2-1-6fe30ada2009@xxxxxxxxx > --- > drivers/clk/qcom/clk-alpha-pll.c | 4 ++++ > 1 file changed, 4 insertions(+) > > diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c > index 8a412ef47e163..8e98198d4b4b6 100644 > --- a/drivers/clk/qcom/clk-alpha-pll.c > +++ b/drivers/clk/qcom/clk-alpha-pll.c > @@ -2490,6 +2490,10 @@ static int clk_alpha_pll_stromer_set_rate(struct clk_hw *hw, unsigned long rate, > rate = alpha_pll_round_rate(rate, prate, &l, &a, ALPHA_REG_BITWIDTH); > > regmap_write(pll->clkr.regmap, PLL_L_VAL(pll), l); > + > + if (ALPHA_REG_BITWIDTH > ALPHA_BITWIDTH) > + a <<= ALPHA_REG_BITWIDTH - ALPHA_BITWIDTH; Uh.. that's not right, this is comparing two constants Did you mean to use pll_alpha_width()? Konrad