[PATCH v4 1/5] clk: sunxi-ng: common: Support minimum and maximum rate

Måns Rullgård mans at mansr.com
Wed May 22 18:07:21 UTC 2024


Frank Oltmanns <frank at oltmanns.dev> writes:

> Hi Måns,
>
> 21.05.2024 15:43:10 Måns Rullgård <mans at mansr.com>:
>
>> Frank Oltmanns <frank at oltmanns.dev> writes:
>>
>>> The Allwinner SoC's typically have an upper and lower limit for their
>>> clocks' rates. Up until now, support for that has been implemented
>>> separately for each clock type.
>>>
>>> Implement that functionality in the sunxi-ng's common part making use of
>>> the CCF rate liming capabilities, so that it is available for all clock
>>> types.
>>>
>>> Suggested-by: Maxime Ripard <mripard at kernel.org>
>>> Signed-off-by: Frank Oltmanns <frank at oltmanns.dev>
>>> Cc: stable at vger.kernel.org
>>> ---
>>> drivers/clk/sunxi-ng/ccu_common.c | 19 +++++++++++++++++++
>>> drivers/clk/sunxi-ng/ccu_common.h |  3 +++
>>> 2 files changed, 22 insertions(+)
>>
>> This just landed in 6.6 stable, and it broke HDMI output on an A20 based
>> device, the clocks ending up all wrong as seen in this diff of
>> /sys/kernel/debug/clk/clk_summary:
>>
>> @@ -70,16 +71,14 @@
>>            apb1-i2c0                  0       0        0        24000000    0
>>
>>         pll-gpu                       0       0        0        1200000000  0
>> -       pll-video1                    3       3        1        159000000   0
>> +       pll-video1                    2       2        1        159000000   0
>>            hdmi                       1       1        0        39750000    0
>>
>>            tcon0-ch1-sclk2            1       1        1        39750000    0
>>               tcon0-ch1-sclk1         1       1        1        39750000    0
>>
>> -          pll-video1-2x              1       1        0        318000000   0
>> +          pll-video1-2x              0       0        0        318000000   0
>>
>> -             hdmi-tmds               2       2        0        39750000    0
>> -                hdmi-ddc             1       1        0        1987500     0
>>         pll-periph-base               2       2        0        1200000000  0
>>            mbus                       1       1        0        300000000   0
>>            pll-periph-sata            0       0        0        100000000   0
>> @@ -199,7 +198,7 @@
>>
>>            ace                        0       0        0        384000000   0
>>            ve                         0       0        0        384000000   0
>> -       pll-video0                    4       4        2        297000000   0
>> +       pll-video0                    5       5        2        297000000   0
>>            hdmi1                      0       0        0        297000000   0
>>            tcon1-ch1-sclk2            0       0        0        297000000   0
>>               tcon1-ch1-sclk1         0       0        0        297000000   0
>> @@ -222,8 +221,10 @@
>>
>>            de-be0                     1       1        1        297000000   0
>>
>> -          pll-video0-2x              0       0        0        594000000   0
>> +          pll-video0-2x              1       1        0        594000000   0
>>
>> +             hdmi-tmds               2       2        0        594000000   0
>> +                hdmi-ddc             1       1        0        29700000    0
>>         pll-audio-base                0       0        0        1500000     0
>>            pll-audio-8x               0       0        0        3000000     0
>>               i2s2                    0       0        0        3000000     0
>>
>> Reverting this commit makes it work again.
>
> Thank you for your detailed report!
>
> I've had a first look at hdmi-tmds and hdmi-ddc, and neither seems to
> be calling ccu_is_better_rate() in their determine_rate()
> functions. Their parents have the exact same rates in your diff, so,
> my current working assumption is that they can't be the cause either.
>
> I'll have a more detailed look over the weekend. Until then, if anyone
> has some ideas where I should have a look next, please share your
> thoughts.

In case it's relevant, this system doesn't use the HDMI DDC, the
physical DDC pins being connected to a different I2C adapter for
various reasons.

From the clk_summary diff, I see a few things:

1. hdmi-tmds has changed parent from pll-video1-2x to pll-video0-2x.
2. The ratio of hdmi-tmds to its parent has changed from 1/8 to 1.
3. The resulting rate bears no relation to the pixel clock from EDID.

I tried kernel 6.9.1 as well, and that doesn't work either.  I'll keep
digging and try to narrow it down.

>>> diff --git a/drivers/clk/sunxi-ng/ccu_common.c b/drivers/clk/sunxi-ng/ccu_common.c
>>> index 8babce55302f..ac0091b4ce24 100644
>>> --- a/drivers/clk/sunxi-ng/ccu_common.c
>>> +++ b/drivers/clk/sunxi-ng/ccu_common.c
>>> @@ -44,6 +44,16 @@ bool ccu_is_better_rate(struct ccu_common *common,
>>>             unsigned long current_rate,
>>>             unsigned long best_rate)
>>> {
>>> +   unsigned long min_rate, max_rate;
>>> +
>>> +   clk_hw_get_rate_range(&common->hw, &min_rate, &max_rate);
>>> +
>>> +   if (current_rate > max_rate)
>>> +       return false;
>>> +
>>> +   if (current_rate < min_rate)
>>> +       return false;
>>> +
>>>     if (common->features & CCU_FEATURE_CLOSEST_RATE)
>>>         return abs(current_rate - target_rate) < abs(best_rate - target_rate);
>>>
>>> @@ -122,6 +132,7 @@ static int sunxi_ccu_probe(struct sunxi_ccu *ccu, struct device *dev,
>>>
>>>     for (i = 0; i < desc->hw_clks->num ; i++) {
>>>         struct clk_hw *hw = desc->hw_clks->hws[i];
>>> +       struct ccu_common *common = hw_to_ccu_common(hw);
>>>         const char *name;
>>>
>>>         if (!hw)
>>> @@ -136,6 +147,14 @@ static int sunxi_ccu_probe(struct sunxi_ccu *ccu, struct device *dev,
>>>             pr_err("Couldn't register clock %d - %s\n", i, name);
>>>             goto err_clk_unreg;
>>>         }
>>> +
>>> +       if (common->max_rate)
>>> +           clk_hw_set_rate_range(hw, common->min_rate,
>>> +                         common->max_rate);
>>> +       else
>>> +           WARN(common->min_rate,
>>> +                "No max_rate, ignoring min_rate of clock %d - %s\n",
>>> +                i, name);
>>>     }
>>>
>>>     ret = of_clk_add_hw_provider(node, of_clk_hw_onecell_get,
>>> diff --git a/drivers/clk/sunxi-ng/ccu_common.h b/drivers/clk/sunxi-ng/ccu_common.h
>>> index 942a72c09437..329734f8cf42 100644
>>> --- a/drivers/clk/sunxi-ng/ccu_common.h
>>> +++ b/drivers/clk/sunxi-ng/ccu_common.h
>>> @@ -31,6 +31,9 @@ struct ccu_common {
>>>     u16     lock_reg;
>>>     u32     prediv;
>>>
>>> +   unsigned long   min_rate;
>>> +   unsigned long   max_rate;
>>> +
>>>     unsigned long   features;
>>>     spinlock_t  *lock;
>>>     struct clk_hw   hw;
>>>
>>> --
>>>
>>> 2.44.0
>>>
>>
>> --
>> Måns Rullgård
>

-- 
Måns Rullgård


More information about the dri-devel mailing list