Message ID | 20240326-alpha-pll-fix-stromer-set-rate-v2-1-48ae83af71c8@gmail.com (mailing list archive) |
---|---|
State | Changes Requested, archived |
Headers | show |
Series | [v2] clk: qcom: clk-alpha-pll: fix rate setting for Stromer PLLs | expand |
On Tue, 26 Mar 2024 at 14:16, Gabor Juhos <j4g8y7@gmail.com> 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@vger.kernel.org > Fixes: e47a4f55f240 ("clk: qcom: clk-alpha-pll: Add support for Stromer PLLs") > Signed-off-by: Gabor Juhos <j4g8y7@gmail.com> > --- > 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@gmail.com > > Depends on the following patch: > https://lore.kernel.org/r/20240315-apss-ipq-pll-ipq5018-hang-v2-1-6fe30ada2009@gmail.com > --- > drivers/clk/qcom/clk-alpha-pll.c | 4 ++++ > 1 file changed, 4 insertions(+) Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
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@vger.kernel.org > Fixes: e47a4f55f240 ("clk: qcom: clk-alpha-pll: Add support for Stromer PLLs") > Signed-off-by: Gabor Juhos <j4g8y7@gmail.com> > --- > 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@gmail.com > > Depends on the following patch: > https://lore.kernel.org/r/20240315-apss-ipq-pll-ipq5018-hang-v2-1-6fe30ada2009@gmail.com > --- > 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
2024. 03. 26. 21:51 keltezéssel, Konrad Dybcio írta: ... >> 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()? No, not in this patch at least. The clk_alpha_pll_stromer_set_rate() function assumes that the alpha register is 40 bits wide, and currently it does not use pll_alpha_width() at all. Originally, I have converted the function to use it, but that made the change unnecessarily complex since it was a mix of a fix and of a rework. The current patch is a simplified version of that, but i forgot to drop the comparison at the end of the process. In order to keep this fix as simple as possible and backportable to stable kernels, I would rather remove the comparison to reduce the change to a single-line addition. Then modifying the code to use pll_alpha_width() can be done in a separate change. Regards, Gabor
On 26.03.2024 11:16 PM, Gabor Juhos wrote: > 2024. 03. 26. 21:51 keltezéssel, Konrad Dybcio írta: > > ... >>> 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()? > > No, not in this patch at least. > > The clk_alpha_pll_stromer_set_rate() function assumes that the alpha register is > 40 bits wide, and currently it does not use pll_alpha_width() at all. > Originally, I have converted the function to use it, but that made the change > unnecessarily complex since it was a mix of a fix and of a rework. > > The current patch is a simplified version of that, but i forgot to drop the > comparison at the end of the process. > > In order to keep this fix as simple as possible and backportable to stable > kernels, I would rather remove the comparison to reduce the change to a > single-line addition. Then modifying the code to use pll_alpha_width() can be > done in a separate change. Sounds good Konrad
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; + regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL(pll), a); regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL_U(pll), a >> ALPHA_BITWIDTH);
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@vger.kernel.org Fixes: e47a4f55f240 ("clk: qcom: clk-alpha-pll: Add support for Stromer PLLs") Signed-off-by: Gabor Juhos <j4g8y7@gmail.com> --- 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@gmail.com Depends on the following patch: https://lore.kernel.org/r/20240315-apss-ipq-pll-ipq5018-hang-v2-1-6fe30ada2009@gmail.com --- drivers/clk/qcom/clk-alpha-pll.c | 4 ++++ 1 file changed, 4 insertions(+) --- base-commit: 5eab983c5e31e5f0bf2d583731e320e21814d1b7 change-id: 20240324-alpha-pll-fix-stromer-set-rate-472376e624f0 Best regards,