[PATCH V2] clk: bcm2835: mark enabled pll_dividers as critical

Martin Sperl kernel at martin.sperl.org
Wed Apr 27 07:55:21 PDT 2016


> On 27.04.2016, at 07:31, Martin Sperl <kernel at martin.sperl.org> wrote:
> 
> 
> 
>> On 27.04.2016, at 03:30, Eric Anholt <eric at anholt.net> wrote:
>> 
>> Martin Sperl <kernel at martin.sperl.org> writes:
>> 
>>> Sent from my iPad
>>>> On 26.04.2016, at 21:31, Eric Anholt <eric at anholt.net> wrote:
>>>> 
>>>> kernel at martin.sperl.org writes:
>>>> 
>>>>> From: Martin Sperl <kernel at martin.sperl.org>
>>>>> 
>>>>> The bcm2835 firmware enables several clocks and plls before
>>>>> booting the linux kernel.
>>>>> 
>>>>> These plls should never get disabled as it may result in a
>>>>> stopped system clock and more.
>>>>> 
>>>>> So during probing we check if the pll_divider is enabled
>>>>> and if it is then mark that pll_divider as critical.
>>>>> As a consequence this will also enable the corresponding parent pll.
>>>>> 
>>>>> Here the list of pll_div that are marked as critical:
>>>>> [    2.022437] bcm2835-clk 20101000.cprman: found enabled pll_div plla_core - marking it as critical
>>>>> [    2.031640] bcm2835-clk 20101000.cprman: found enabled pll_div pllb_arm - marking it as critical
>>>>> [    2.040966] bcm2835-clk 20101000.cprman: found enabled pll_div pllc_core0 - marking it as critical
>>>>> [    2.050351] bcm2835-clk 20101000.cprman: found enabled pll_div pllc_per - marking it as critical
>>>>> [    2.059427] bcm2835-clk 20101000.cprman: found enabled pll_div plld_core - marking it as critical
>>>>> [    2.068590] bcm2835-clk 20101000.cprman: found enabled pll_div plld_per - marking it as critical
>>>>> [    2.077724] bcm2835-clk 20101000.cprman: found enabled pll_div pllh_pix - marking it as critical
>>>> 
>>>> Yeah, pllh_pix isn't critical, though.  We want it to get turned off
>>>> when the driver asks to disable its clock, or we're going to just waste
>>>> a pile of power.
>>>> 
>>>> I'm sending out a patch that marks the VPU clock as critical (it's the
>>>> also AXI bus, so it certainly is critical), which should solve your
>>>> aux_uart clock disabling problem, I think.
>>> 
>>> The problem is that it also fails on the pcm clock alone when pllc or 
>>> plld_per are used as parent, but it is fine when osc is used...
>> 
>> For that you're going to want the HAND_OFF patches that mturquette is
>> working on: Don't let the clock and its parents get turned off until a
>> driver has shown up that has referenced the clock and done at least a
>> prepare on it once.
> That one was the one I thought of as well, but it does not solve the
> issue at all, because:
> 
> Speaker-test opens the audio device for 32bit 41200 samples
> Which in turn uses the i2s driver
> Which enable_prepares the clock (uses pllc_per or plld_per)
> Plays sound until the end
> Then speaker test closes the audio device
> Which disables/unprepared the PCM clock
> Which disables/unprepares plld_per
> Which disables/unprepares plld
> Machine crashes
> 
> For those last few steps the handsoff still would release the
> Pll-div and pll as it has been claimed correctly first.
> 
> Maybe handsoff would work if applied to the individual
> Clocks (not the pll or pllc), but I am not sure if this is a correct
> assumption, as I do not know if handsoff would propagate 
> up the clock tree.
> 
> So the critical flag seems the "best" approach for now,
> But as you have said: it is not ideal as it never disables
> Any clocks when they are not really needed.
> 
> But so that we can continue we need something 
> that works now (even if it is not perfect)
> 
> Another approach would be knowing the list of clocks 
> that the firmware claims/owns and mark only those as "critical”.
I did a test with HAND_OFF and that works very well indeed!

Here the corresponding patch:
diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c
index 35f8de7..31417fd 100644
--- a/drivers/clk/bcm/clk-bcm2835.c
+++ b/drivers/clk/bcm/clk-bcm2835.c
@@ -1251,6 +1251,14 @@ static struct clk *bcm2835_register_clock(struct bcm2835_cprman *cprman,
                init.flags |= CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE;
        }

+       /* if the clock is running, then mark is as critical */
+       if (cprman_read(cprman, data->ctl_reg) & CM_ENABLE) {
+               dev_info(cprman->dev,
+                        "found enabled clock %s - enabling hand off\n",
+                        data->name);
+               init.flags |= CLK_ENABLE_HAND_OFF;
+       }
+
        clock = devm_kzalloc(cprman->dev, sizeof(*clock), GFP_KERNEL);
        if (!clock)
                return NULL;

Note that I am not sure if that is also needed for the pll
and pll-div - there may be some explicit consumers of the pll_div

At least that latest issue we have seen with the pcm clock has gone away.

Registered clocks with hand-off:
bcm2835-clk 20101000.cprman: found enabled clock timer - enabling hand off
bcm2835-clk 20101000.cprman: found enabled clock otp - enabling hand off
bcm2835-clk 20101000.cprman: found enabled clock uart - enabling hand off
bcm2835-clk 20101000.cprman: found enabled clock v3d - enabling hand off
bcm2835-clk 20101000.cprman: found enabled clock isp - enabling hand off
bcm2835-clk 20101000.cprman: found enabled clock h264 - enabling hand off
bcm2835-clk 20101000.cprman: found enabled clock vec - enabling hand off
bcm2835-clk 20101000.cprman: found enabled clock tsens - enabling hand off
bcm2835-clk 20101000.cprman: found enabled clock emmc - enabling hand off

Enabled clock count:
root at raspcm:~# grep -vE ^0 /sys/kernel/debug/clk/*/clk_enable_count
/sys/kernel/debug/clk/apb_pclk/clk_enable_count:1
/sys/kernel/debug/clk/clock/clk_enable_count:1
/sys/kernel/debug/clk/core/clk_enable_count:3
/sys/kernel/debug/clk/emmc/clk_enable_count:1
/sys/kernel/debug/clk/h264/clk_enable_count:1
/sys/kernel/debug/clk/isp/clk_enable_count:1
/sys/kernel/debug/clk/osc/clk_enable_count:7
/sys/kernel/debug/clk/otp/clk_enable_count:1
/sys/kernel/debug/clk/plla/clk_enable_count:1
/sys/kernel/debug/clk/plla_core/clk_enable_count:3
/sys/kernel/debug/clk/pllc/clk_enable_count:1
/sys/kernel/debug/clk/pllc_per/clk_enable_count:1
/sys/kernel/debug/clk/plld/clk_enable_count:1
/sys/kernel/debug/clk/plld_per/clk_enable_count:1
/sys/kernel/debug/clk/pllh_aux/clk_enable_count:1
/sys/kernel/debug/clk/pllh_aux_prediv/clk_enable_count:1
/sys/kernel/debug/clk/pllh/clk_enable_count:1
/sys/kernel/debug/clk/timer/clk_enable_count:1
/sys/kernel/debug/clk/tsens/clk_enable_count:1
/sys/kernel/debug/clk/uart0_pclk/clk_enable_count:1
/sys/kernel/debug/clk/uart/clk_enable_count:1
/sys/kernel/debug/clk/v3d/clk_enable_count:1
/sys/kernel/debug/clk/vec/clk_enable_count:1

That is a setup where the clock bcm2835 is only referenced in the device 
tree for pcm.

Using pcm-audio would trigger a machine halt before this patch.
Now this does not happen.

Hope that this is the best solution and an incentive to get those
CLK_ENABLE_HAND_OFF patches in as there is now the first user.

I will post this as a patch.

Martin




More information about the linux-rpi-kernel mailing list