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: [email protected]
Fixes: e47a4f55f240 ("clk: qcom: clk-alpha-pll: Add support for Stromer PLLs")
Signed-off-by: Gabor Juhos <[email protected]>
---
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/[email protected]
---
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;
+
regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL(pll), a);
regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL_U(pll),
a >> ALPHA_BITWIDTH);
---
base-commit: 5eab983c5e31e5f0bf2d583731e320e21814d1b7
change-id: 20240324-alpha-pll-fix-stromer-set-rate-472376e624f0
Best regards,
--
Gabor Juhos <[email protected]>
On Tue, 26 Mar 2024 at 14:16, Gabor Juhos <[email protected]> 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: [email protected]
> Fixes: e47a4f55f240 ("clk: qcom: clk-alpha-pll: Add support for Stromer PLLs")
> Signed-off-by: Gabor Juhos <[email protected]>
> ---
> 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/[email protected]
> ---
> drivers/clk/qcom/clk-alpha-pll.c | 4 ++++
> 1 file changed, 4 insertions(+)
Reviewed-by: Dmitry Baryshkov <[email protected]>
--
With best wishes
Dmitry
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: [email protected]
> Fixes: e47a4f55f240 ("clk: qcom: clk-alpha-pll: Add support for Stromer PLLs")
> Signed-off-by: Gabor Juhos <[email protected]>
> ---
> 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/[email protected]
> ---
> 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