diff mbox

Odd behavior with dpll4_m4x2_ck on omap3 + DT

Message ID 522F1BF9.5050006@ti.com (mailing list archive)
State New, archived
Headers show

Commit Message

Tero Kristo Sept. 10, 2013, 1:17 p.m. UTC
On 09/10/2013 03:40 PM, Tomi Valkeinen wrote:
> On 10/09/13 15:24, Tero Kristo wrote:
>> On 09/10/2013 03:19 PM, Tomi Valkeinen wrote:
>>> On 10/09/13 15:12, Tero Kristo wrote:
>>>
>>>> If it claims it is not locked, it means the DPLL itself is disabled. You
>>>> could try clk_enable for the clock before doing clk_set_rate.
>>>
>>> Hmm, so is it required to enable the clock before setting the rate? If
>>> so, I think I'm using the clocks wrong in all the places =).
>>
>> In generic case, it is not. But DPLLs behave strangely if they go to low
>> power stop mode. If there is any downstream clock enabled for a specific
>> DPLL it is enabled and things work okay.
>>
>> One could also argue that the API behavior in OMAP is wrong currently,
>> as the bypass rate is something you are most likely never actually going
>> to use for anything....
>>
>> Just try the change and check the results.
>
> Ok, so as Stefan said, enabling the clock fixes the issue.
>
> How do you suggest we fix this? Changing omapdss to enable the clock
> before changing its rate is not very difficult, so it can be used as a
> quick fix. But it doesn't sound like a proper fix if this is not
> normally required.

The quick fix sounds good to me.

> And, maybe I'm missing something as I don't have good understanding of
> the PRCM's PLLs, but the current behavior sounds odd. So the DPLL is
> off, and in bypass mode. When we try to change the rate of the clock
> provided by the PLL, shouldn't it fail, as bypass mode's rate cannot be
> changed? Or better, change the non-bypass rate.

In theory, DPLLs can also be used in their bypass mode to feed customer 
nodes clocks. I just think the check in the clkoutx2_recalc is wrong, 
and should be enhanced to actually check what is the target mode for the 
clock once it is enabled. Maybe something like this would work properly:


>
> How is the DPLL4's clock rate 432000000 anyway in bypass mode. Isn't
> bypass mode usually plain sys-clock, or such?

This again reflects the rate that the clock has once it is enabled, the 
clkoutx2 does not.

Getting comment from someone like Paul would probably help here.

-Tero

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Comments

Mike Turquette Sept. 10, 2013, 9:17 p.m. UTC | #1
Quoting Tero Kristo (2013-09-10 06:17:45)
> On 09/10/2013 03:40 PM, Tomi Valkeinen wrote:
> > On 10/09/13 15:24, Tero Kristo wrote:
> >> On 09/10/2013 03:19 PM, Tomi Valkeinen wrote:
> >>> On 10/09/13 15:12, Tero Kristo wrote:
> >>>
> >>>> If it claims it is not locked, it means the DPLL itself is disabled. You
> >>>> could try clk_enable for the clock before doing clk_set_rate.
> >>>
> >>> Hmm, so is it required to enable the clock before setting the rate? If
> >>> so, I think I'm using the clocks wrong in all the places =).
> >>
> >> In generic case, it is not. But DPLLs behave strangely if they go to low
> >> power stop mode. If there is any downstream clock enabled for a specific
> >> DPLL it is enabled and things work okay.
> >>
> >> One could also argue that the API behavior in OMAP is wrong currently,
> >> as the bypass rate is something you are most likely never actually going
> >> to use for anything....
> >>
> >> Just try the change and check the results.
> >
> > Ok, so as Stefan said, enabling the clock fixes the issue.
> >
> > How do you suggest we fix this? Changing omapdss to enable the clock
> > before changing its rate is not very difficult, so it can be used as a
> > quick fix. But it doesn't sound like a proper fix if this is not
> > normally required.
> 
> The quick fix sounds good to me.
> 
> > And, maybe I'm missing something as I don't have good understanding of
> > the PRCM's PLLs, but the current behavior sounds odd. So the DPLL is
> > off, and in bypass mode. When we try to change the rate of the clock
> > provided by the PLL, shouldn't it fail, as bypass mode's rate cannot be
> > changed? Or better, change the non-bypass rate.
> 
> In theory, DPLLs can also be used in their bypass mode to feed customer 
> nodes clocks. I just think the check in the clkoutx2_recalc is wrong, 
> and should be enhanced to actually check what is the target mode for the 
> clock once it is enabled. Maybe something like this would work properly:
> 
> diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c
> index 3a0296c..ba218fb 100644
> --- a/arch/arm/mach-omap2/dpll3xxx.c
> +++ b/arch/arm/mach-omap2/dpll3xxx.c
> @@ -658,14 +658,12 @@ unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw,
> 
>          dd = pclk->dpll_data;
> 
> -       WARN_ON(!dd->enable_mask);
> -
> -       v = __raw_readl(dd->control_reg) & dd->enable_mask;
> -       v >>= __ffs(dd->enable_mask);
> -       if ((v != OMAP3XXX_EN_DPLL_LOCKED) || (dd->flags & DPLL_J_TYPE))
> +       if ((dd->flags & DPLL_J_TYPE) ||
> +           __clk_get_rate(dd->clk_bypass) == __clk_get_rate(pclk))

Two quick asides here:

1) might be nice if the J_TYPE pll was it's own clock type

2) would be nice if the check for bypass used something like:

if (clk_get_parent(hw->clk) == dd->bypass_clk)
	rate = parent_rate;

Which implies that the DPLLs become proper mux clocks.

Regards,
Mike

>                  rate = parent_rate;
>          else
>                  rate = parent_rate * 2;
> +
>          return rate;
>   }
> 
> 
> >
> > How is the DPLL4's clock rate 432000000 anyway in bypass mode. Isn't
> > bypass mode usually plain sys-clock, or such?
> 
> This again reflects the rate that the clock has once it is enabled, the 
> clkoutx2 does not.
> 
> Getting comment from someone like Paul would probably help here.
> 
> -Tero
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Mike Turquette Sept. 10, 2013, 9:57 p.m. UTC | #2
On Tue, Sep 10, 2013 at 2:17 PM, Mike Turquette <mturquette@linaro.org> wrote:
> Quoting Tero Kristo (2013-09-10 06:17:45)
>> On 09/10/2013 03:40 PM, Tomi Valkeinen wrote:
>> > On 10/09/13 15:24, Tero Kristo wrote:
>> >> On 09/10/2013 03:19 PM, Tomi Valkeinen wrote:
>> >>> On 10/09/13 15:12, Tero Kristo wrote:
>> >>>
>> >>>> If it claims it is not locked, it means the DPLL itself is disabled. You
>> >>>> could try clk_enable for the clock before doing clk_set_rate.
>> >>>
>> >>> Hmm, so is it required to enable the clock before setting the rate? If
>> >>> so, I think I'm using the clocks wrong in all the places =).
>> >>
>> >> In generic case, it is not. But DPLLs behave strangely if they go to low
>> >> power stop mode. If there is any downstream clock enabled for a specific
>> >> DPLL it is enabled and things work okay.
>> >>
>> >> One could also argue that the API behavior in OMAP is wrong currently,
>> >> as the bypass rate is something you are most likely never actually going
>> >> to use for anything....
>> >>
>> >> Just try the change and check the results.
>> >
>> > Ok, so as Stefan said, enabling the clock fixes the issue.
>> >
>> > How do you suggest we fix this? Changing omapdss to enable the clock
>> > before changing its rate is not very difficult, so it can be used as a
>> > quick fix. But it doesn't sound like a proper fix if this is not
>> > normally required.
>>
>> The quick fix sounds good to me.
>>
>> > And, maybe I'm missing something as I don't have good understanding of
>> > the PRCM's PLLs, but the current behavior sounds odd. So the DPLL is
>> > off, and in bypass mode. When we try to change the rate of the clock
>> > provided by the PLL, shouldn't it fail, as bypass mode's rate cannot be
>> > changed? Or better, change the non-bypass rate.
>>
>> In theory, DPLLs can also be used in their bypass mode to feed customer
>> nodes clocks. I just think the check in the clkoutx2_recalc is wrong,
>> and should be enhanced to actually check what is the target mode for the
>> clock once it is enabled. Maybe something like this would work properly:
>>
>> diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c
>> index 3a0296c..ba218fb 100644
>> --- a/arch/arm/mach-omap2/dpll3xxx.c
>> +++ b/arch/arm/mach-omap2/dpll3xxx.c
>> @@ -658,14 +658,12 @@ unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw,
>>
>>          dd = pclk->dpll_data;
>>
>> -       WARN_ON(!dd->enable_mask);
>> -
>> -       v = __raw_readl(dd->control_reg) & dd->enable_mask;
>> -       v >>= __ffs(dd->enable_mask);
>> -       if ((v != OMAP3XXX_EN_DPLL_LOCKED) || (dd->flags & DPLL_J_TYPE))
>> +       if ((dd->flags & DPLL_J_TYPE) ||
>> +           __clk_get_rate(dd->clk_bypass) == __clk_get_rate(pclk))
>
> Two quick asides here:
>
> 1) might be nice if the J_TYPE pll was it's own clock type
>
> 2) would be nice if the check for bypass used something like:
>
> if (clk_get_parent(hw->clk) == dd->bypass_clk)
>         rate = parent_rate;
>
> Which implies that the DPLLs become proper mux clocks.

Please disregard the above! I'm reviewing the OMAP v6 CCF series and
does these things already. Very cool.

Regards,
Mike

>
> Regards,
> Mike
>
>>                  rate = parent_rate;
>>          else
>>                  rate = parent_rate * 2;
>> +
>>          return rate;
>>   }
>>
>>
>> >
>> > How is the DPLL4's clock rate 432000000 anyway in bypass mode. Isn't
>> > bypass mode usually plain sys-clock, or such?
>>
>> This again reflects the rate that the clock has once it is enabled, the
>> clkoutx2 does not.
>>
>> Getting comment from someone like Paul would probably help here.
>>
>> -Tero
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Tomi Valkeinen Sept. 11, 2013, 7:21 a.m. UTC | #3
On 10/09/13 16:17, Tero Kristo wrote:

> In theory, DPLLs can also be used in their bypass mode to feed customer
> nodes clocks. I just think the check in the clkoutx2_recalc is wrong,
> and should be enhanced to actually check what is the target mode for the
> clock once it is enabled. Maybe something like this would work properly:
> 
> diff --git a/arch/arm/mach-omap2/dpll3xxx.c
> b/arch/arm/mach-omap2/dpll3xxx.c
> index 3a0296c..ba218fb 100644
> --- a/arch/arm/mach-omap2/dpll3xxx.c
> +++ b/arch/arm/mach-omap2/dpll3xxx.c
> @@ -658,14 +658,12 @@ unsigned long omap3_clkoutx2_recalc(struct clk_hw
> *hw,
> 
>         dd = pclk->dpll_data;
> 
> -       WARN_ON(!dd->enable_mask);
> -
> -       v = __raw_readl(dd->control_reg) & dd->enable_mask;
> -       v >>= __ffs(dd->enable_mask);
> -       if ((v != OMAP3XXX_EN_DPLL_LOCKED) || (dd->flags & DPLL_J_TYPE))
> +       if ((dd->flags & DPLL_J_TYPE) ||
> +           __clk_get_rate(dd->clk_bypass) == __clk_get_rate(pclk))
>                 rate = parent_rate;
>         else
>                 rate = parent_rate * 2;
> +
>         return rate;
>  }

Stefan, are you able to test the above?

I'd rather have a proper fix for this, than hack omapdss =).

>> How is the DPLL4's clock rate 432000000 anyway in bypass mode. Isn't
>> bypass mode usually plain sys-clock, or such?
> 
> This again reflects the rate that the clock has once it is enabled, the
> clkoutx2 does not.

Ok. Then it does sound like the clkoutx2 is calculated wrong, as you say.

 Tomi
Stefan Roese Sept. 13, 2013, 7:51 a.m. UTC | #4
On 11.09.2013 09:21, Tomi Valkeinen wrote:
> On 10/09/13 16:17, Tero Kristo wrote:
> 
>> In theory, DPLLs can also be used in their bypass mode to feed customer
>> nodes clocks. I just think the check in the clkoutx2_recalc is wrong,
>> and should be enhanced to actually check what is the target mode for the
>> clock once it is enabled. Maybe something like this would work properly:
>>
>> diff --git a/arch/arm/mach-omap2/dpll3xxx.c
>> b/arch/arm/mach-omap2/dpll3xxx.c
>> index 3a0296c..ba218fb 100644
>> --- a/arch/arm/mach-omap2/dpll3xxx.c
>> +++ b/arch/arm/mach-omap2/dpll3xxx.c
>> @@ -658,14 +658,12 @@ unsigned long omap3_clkoutx2_recalc(struct clk_hw
>> *hw,
>>
>>         dd = pclk->dpll_data;
>>
>> -       WARN_ON(!dd->enable_mask);
>> -
>> -       v = __raw_readl(dd->control_reg) & dd->enable_mask;
>> -       v >>= __ffs(dd->enable_mask);
>> -       if ((v != OMAP3XXX_EN_DPLL_LOCKED) || (dd->flags & DPLL_J_TYPE))
>> +       if ((dd->flags & DPLL_J_TYPE) ||
>> +           __clk_get_rate(dd->clk_bypass) == __clk_get_rate(pclk))
>>                 rate = parent_rate;
>>         else
>>                 rate = parent_rate * 2;
>> +
>>         return rate;
>>  }
> 
> Stefan, are you able to test the above?
> 
> I'd rather have a proper fix for this, than hack omapdss =).

Okay, I finally found some time to test this. The patch above generates
this warning:

arch/arm/mach-omap2/dpll3xxx.c: In function 'omap3_clkoutx2_recalc':
arch/arm/mach-omap2/dpll3xxx.c:663:6: warning: passing argument 1 of '__clk_get_rate' from incompatible pointer type [enabled by default]
include/linux/clk-provider.h:423:15: note: expected 'struct clk *' but argument is of type 'struct clk_hw_omap *'

I then changed it (not 100% sure if correctly) to this version:

+       if ((dd->flags & DPLL_J_TYPE) ||
+           __clk_get_rate(dd->clk_bypass) == __clk_get_rate(pclk->hw.clk))

And this seems to work. At least the clock rate mismatch warning does not
appear with this patch applied (and without the clk_enable) in the
bootlog any more.

Thanks,
Stefan

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Tero Kristo Sept. 13, 2013, 11:34 a.m. UTC | #5
On 09/13/2013 10:51 AM, Stefan Roese wrote:
> On 11.09.2013 09:21, Tomi Valkeinen wrote:
>> On 10/09/13 16:17, Tero Kristo wrote:
>>
>>> In theory, DPLLs can also be used in their bypass mode to feed customer
>>> nodes clocks. I just think the check in the clkoutx2_recalc is wrong,
>>> and should be enhanced to actually check what is the target mode for the
>>> clock once it is enabled. Maybe something like this would work properly:
>>>
>>> diff --git a/arch/arm/mach-omap2/dpll3xxx.c
>>> b/arch/arm/mach-omap2/dpll3xxx.c
>>> index 3a0296c..ba218fb 100644
>>> --- a/arch/arm/mach-omap2/dpll3xxx.c
>>> +++ b/arch/arm/mach-omap2/dpll3xxx.c
>>> @@ -658,14 +658,12 @@ unsigned long omap3_clkoutx2_recalc(struct clk_hw
>>> *hw,
>>>
>>>          dd = pclk->dpll_data;
>>>
>>> -       WARN_ON(!dd->enable_mask);
>>> -
>>> -       v = __raw_readl(dd->control_reg) & dd->enable_mask;
>>> -       v >>= __ffs(dd->enable_mask);
>>> -       if ((v != OMAP3XXX_EN_DPLL_LOCKED) || (dd->flags & DPLL_J_TYPE))
>>> +       if ((dd->flags & DPLL_J_TYPE) ||
>>> +           __clk_get_rate(dd->clk_bypass) == __clk_get_rate(pclk))
>>>                  rate = parent_rate;
>>>          else
>>>                  rate = parent_rate * 2;
>>> +
>>>          return rate;
>>>   }
>>
>> Stefan, are you able to test the above?
>>
>> I'd rather have a proper fix for this, than hack omapdss =).
>
> Okay, I finally found some time to test this. The patch above generates
> this warning:
>
> arch/arm/mach-omap2/dpll3xxx.c: In function 'omap3_clkoutx2_recalc':
> arch/arm/mach-omap2/dpll3xxx.c:663:6: warning: passing argument 1 of '__clk_get_rate' from incompatible pointer type [enabled by default]
> include/linux/clk-provider.h:423:15: note: expected 'struct clk *' but argument is of type 'struct clk_hw_omap *'

Yea sorry about that, I just quickly hacked the patch together without 
testing it at all. :P

>
> I then changed it (not 100% sure if correctly) to this version:
>
> +       if ((dd->flags & DPLL_J_TYPE) ||
> +           __clk_get_rate(dd->clk_bypass) == __clk_get_rate(pclk->hw.clk))
>
> And this seems to work. At least the clock rate mismatch warning does not
> appear with this patch applied (and without the clk_enable) in the
> bootlog any more.

Yea, looks good to me, however I guess I would like second opinion on 
this also.

-Tero

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Mike Turquette Sept. 16, 2013, 7:45 p.m. UTC | #6
Quoting Tero Kristo (2013-09-13 04:34:54)
> On 09/13/2013 10:51 AM, Stefan Roese wrote:
> > On 11.09.2013 09:21, Tomi Valkeinen wrote:
> >> On 10/09/13 16:17, Tero Kristo wrote:
> >>
> >>> In theory, DPLLs can also be used in their bypass mode to feed customer
> >>> nodes clocks. I just think the check in the clkoutx2_recalc is wrong,
> >>> and should be enhanced to actually check what is the target mode for the
> >>> clock once it is enabled. Maybe something like this would work properly:
> >>>
> >>> diff --git a/arch/arm/mach-omap2/dpll3xxx.c
> >>> b/arch/arm/mach-omap2/dpll3xxx.c
> >>> index 3a0296c..ba218fb 100644
> >>> --- a/arch/arm/mach-omap2/dpll3xxx.c
> >>> +++ b/arch/arm/mach-omap2/dpll3xxx.c
> >>> @@ -658,14 +658,12 @@ unsigned long omap3_clkoutx2_recalc(struct clk_hw
> >>> *hw,
> >>>
> >>>          dd = pclk->dpll_data;
> >>>
> >>> -       WARN_ON(!dd->enable_mask);
> >>> -
> >>> -       v = __raw_readl(dd->control_reg) & dd->enable_mask;
> >>> -       v >>= __ffs(dd->enable_mask);
> >>> -       if ((v != OMAP3XXX_EN_DPLL_LOCKED) || (dd->flags & DPLL_J_TYPE))
> >>> +       if ((dd->flags & DPLL_J_TYPE) ||
> >>> +           __clk_get_rate(dd->clk_bypass) == __clk_get_rate(pclk))
> >>>                  rate = parent_rate;
> >>>          else
> >>>                  rate = parent_rate * 2;
> >>> +
> >>>          return rate;
> >>>   }
> >>
> >> Stefan, are you able to test the above?
> >>
> >> I'd rather have a proper fix for this, than hack omapdss =).
> >
> > Okay, I finally found some time to test this. The patch above generates
> > this warning:
> >
> > arch/arm/mach-omap2/dpll3xxx.c: In function 'omap3_clkoutx2_recalc':
> > arch/arm/mach-omap2/dpll3xxx.c:663:6: warning: passing argument 1 of '__clk_get_rate' from incompatible pointer type [enabled by default]
> > include/linux/clk-provider.h:423:15: note: expected 'struct clk *' but argument is of type 'struct clk_hw_omap *'
> 
> Yea sorry about that, I just quickly hacked the patch together without 
> testing it at all. :P
> 
> >
> > I then changed it (not 100% sure if correctly) to this version:
> >
> > +       if ((dd->flags & DPLL_J_TYPE) ||
> > +           __clk_get_rate(dd->clk_bypass) == __clk_get_rate(pclk->hw.clk))
> >
> > And this seems to work. At least the clock rate mismatch warning does not
> > appear with this patch applied (and without the clk_enable) in the
> > bootlog any more.
> 
> Yea, looks good to me, however I guess I would like second opinion on 
> this also.

Looks right to me.

Regards,
Mike

> 
> -Tero
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Tomi Valkeinen Sept. 27, 2013, 8:41 a.m. UTC | #7
On 13/09/13 14:34, Kristo, Tero wrote:
> On 09/13/2013 10:51 AM, Stefan Roese wrote:
>> On 11.09.2013 09:21, Tomi Valkeinen wrote:
>>> On 10/09/13 16:17, Tero Kristo wrote:
>>>
>>>> In theory, DPLLs can also be used in their bypass mode to feed customer
>>>> nodes clocks. I just think the check in the clkoutx2_recalc is wrong,
>>>> and should be enhanced to actually check what is the target mode for the
>>>> clock once it is enabled. Maybe something like this would work properly:
>>>>
>>>> diff --git a/arch/arm/mach-omap2/dpll3xxx.c
>>>> b/arch/arm/mach-omap2/dpll3xxx.c
>>>> index 3a0296c..ba218fb 100644
>>>> --- a/arch/arm/mach-omap2/dpll3xxx.c
>>>> +++ b/arch/arm/mach-omap2/dpll3xxx.c
>>>> @@ -658,14 +658,12 @@ unsigned long omap3_clkoutx2_recalc(struct clk_hw
>>>> *hw,
>>>>
>>>>          dd = pclk->dpll_data;
>>>>
>>>> -       WARN_ON(!dd->enable_mask);
>>>> -
>>>> -       v = __raw_readl(dd->control_reg) & dd->enable_mask;
>>>> -       v >>= __ffs(dd->enable_mask);
>>>> -       if ((v != OMAP3XXX_EN_DPLL_LOCKED) || (dd->flags & DPLL_J_TYPE))
>>>> +       if ((dd->flags & DPLL_J_TYPE) ||
>>>> +           __clk_get_rate(dd->clk_bypass) == __clk_get_rate(pclk))
>>>>                  rate = parent_rate;
>>>>          else
>>>>                  rate = parent_rate * 2;
>>>> +
>>>>          return rate;
>>>>   }
>>>
>>> Stefan, are you able to test the above?
>>>
>>> I'd rather have a proper fix for this, than hack omapdss =).
>>
>> Okay, I finally found some time to test this. The patch above generates
>> this warning:
>>
>> arch/arm/mach-omap2/dpll3xxx.c: In function 'omap3_clkoutx2_recalc':
>> arch/arm/mach-omap2/dpll3xxx.c:663:6: warning: passing argument 1 of '__clk_get_rate' from incompatible pointer type [enabled by default]
>> include/linux/clk-provider.h:423:15: note: expected 'struct clk *' but argument is of type 'struct clk_hw_omap *'
> 
> Yea sorry about that, I just quickly hacked the patch together without 
> testing it at all. :P
> 
>>
>> I then changed it (not 100% sure if correctly) to this version:
>>
>> +       if ((dd->flags & DPLL_J_TYPE) ||
>> +           __clk_get_rate(dd->clk_bypass) == __clk_get_rate(pclk->hw.clk))
>>
>> And this seems to work. At least the clock rate mismatch warning does not
>> appear with this patch applied (and without the clk_enable) in the
>> bootlog any more.
> 
> Yea, looks good to me, however I guess I would like second opinion on 
> this also.

Tero, can you queue this patch? Or who should handle this?

 Tomi
Tero Kristo Sept. 27, 2013, 11:24 a.m. UTC | #8
On 09/27/2013 11:41 AM, Tomi Valkeinen wrote:
> On 13/09/13 14:34, Kristo, Tero wrote:
>> On 09/13/2013 10:51 AM, Stefan Roese wrote:
>>> On 11.09.2013 09:21, Tomi Valkeinen wrote:
>>>> On 10/09/13 16:17, Tero Kristo wrote:
>>>>
>>>>> In theory, DPLLs can also be used in their bypass mode to feed customer
>>>>> nodes clocks. I just think the check in the clkoutx2_recalc is wrong,
>>>>> and should be enhanced to actually check what is the target mode for the
>>>>> clock once it is enabled. Maybe something like this would work properly:
>>>>>
>>>>> diff --git a/arch/arm/mach-omap2/dpll3xxx.c
>>>>> b/arch/arm/mach-omap2/dpll3xxx.c
>>>>> index 3a0296c..ba218fb 100644
>>>>> --- a/arch/arm/mach-omap2/dpll3xxx.c
>>>>> +++ b/arch/arm/mach-omap2/dpll3xxx.c
>>>>> @@ -658,14 +658,12 @@ unsigned long omap3_clkoutx2_recalc(struct clk_hw
>>>>> *hw,
>>>>>
>>>>>           dd = pclk->dpll_data;
>>>>>
>>>>> -       WARN_ON(!dd->enable_mask);
>>>>> -
>>>>> -       v = __raw_readl(dd->control_reg) & dd->enable_mask;
>>>>> -       v >>= __ffs(dd->enable_mask);
>>>>> -       if ((v != OMAP3XXX_EN_DPLL_LOCKED) || (dd->flags & DPLL_J_TYPE))
>>>>> +       if ((dd->flags & DPLL_J_TYPE) ||
>>>>> +           __clk_get_rate(dd->clk_bypass) == __clk_get_rate(pclk))
>>>>>                   rate = parent_rate;
>>>>>           else
>>>>>                   rate = parent_rate * 2;
>>>>> +
>>>>>           return rate;
>>>>>    }
>>>>
>>>> Stefan, are you able to test the above?
>>>>
>>>> I'd rather have a proper fix for this, than hack omapdss =).
>>>
>>> Okay, I finally found some time to test this. The patch above generates
>>> this warning:
>>>
>>> arch/arm/mach-omap2/dpll3xxx.c: In function 'omap3_clkoutx2_recalc':
>>> arch/arm/mach-omap2/dpll3xxx.c:663:6: warning: passing argument 1 of '__clk_get_rate' from incompatible pointer type [enabled by default]
>>> include/linux/clk-provider.h:423:15: note: expected 'struct clk *' but argument is of type 'struct clk_hw_omap *'
>>
>> Yea sorry about that, I just quickly hacked the patch together without
>> testing it at all. :P
>>
>>>
>>> I then changed it (not 100% sure if correctly) to this version:
>>>
>>> +       if ((dd->flags & DPLL_J_TYPE) ||
>>> +           __clk_get_rate(dd->clk_bypass) == __clk_get_rate(pclk->hw.clk))
>>>
>>> And this seems to work. At least the clock rate mismatch warning does not
>>> appear with this patch applied (and without the clk_enable) in the
>>> bootlog any more.
>>
>> Yea, looks good to me, however I guess I would like second opinion on
>> this also.
>
> Tero, can you queue this patch? Or who should handle this?

I can't queue anything as I don't have maintainership on any of this 
stuff. Paul / Tony should go with this.

-Tero

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Tomi Valkeinen Sept. 30, 2013, 7:56 a.m. UTC | #9
On 27/09/13 14:24, Tero Kristo wrote:

>> Tero, can you queue this patch? Or who should handle this?
> 
> I can't queue anything as I don't have maintainership on any of this
> stuff. Paul / Tony should go with this.

Well, I mainly meant preparing a patch with proper description and
sending to relevant maintainers.

For some reason I can't reproduce the issue with 3.12-rc1. I guess some
other driver enables the clock now, which wasn't there in 3.11. So as
far as DSS is concerned, things look fine now without the patch. But if
the clock code is wrong, as I understood, maybe it's still good to have
the patch applied.

 Tomi
Paul Walmsley Oct. 7, 2013, 8:21 a.m. UTC | #10
On Tue, 10 Sep 2013, Tero Kristo wrote:

> In theory, DPLLs can also be used in their bypass mode to feed customer nodes
> clocks. I just think the check in the clkoutx2_recalc is wrong, and should be
> enhanced to actually check what is the target mode for the clock once it is
> enabled. Maybe something like this would work properly:
> 
> diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c
> index 3a0296c..ba218fb 100644
> --- a/arch/arm/mach-omap2/dpll3xxx.c
> +++ b/arch/arm/mach-omap2/dpll3xxx.c
> @@ -658,14 +658,12 @@ unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw,
> 
>         dd = pclk->dpll_data;
> 
> -       WARN_ON(!dd->enable_mask);
> -
> -       v = __raw_readl(dd->control_reg) & dd->enable_mask;
> -       v >>= __ffs(dd->enable_mask);
> -       if ((v != OMAP3XXX_EN_DPLL_LOCKED) || (dd->flags & DPLL_J_TYPE))
> +       if ((dd->flags & DPLL_J_TYPE) ||
> +           __clk_get_rate(dd->clk_bypass) == __clk_get_rate(pclk))
>                 rate = parent_rate;
>         else
>                 rate = parent_rate * 2;
> +
>         return rate;
>  }
> 

[...]

> Getting comment from someone like Paul would probably help here.

Looks like this is a regression from the CCF port.

Seems to me that the code above assumes that when the DPLL's rate is set 
to the same rate as the bypass clock's rate, we can assume that the DPLL 
is in bypass.  I wonder if that's valid in a case where a previous OS or 
bootloader may have programmed the DPLL.

Sounds to me like the best way to fix it would be to test whether this 
code is intended to return the "target rate" (when the struct clk 
representing the DPLL is disabled), versus the "current rate" (when the 
struct clk representing the DPLL is enabled).  If it's the target rate, 
then there's no point checking the current state of the hardware.  A check 
similar to the above would probably be fine.  Otherwise, seems best to use 
the existing code that does test the PLL state.



- Paul

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Mike Turquette Oct. 8, 2013, 1:35 a.m. UTC | #11
Quoting Paul Walmsley (2013-10-07 01:21:16)
> On Tue, 10 Sep 2013, Tero Kristo wrote:
> 
> > In theory, DPLLs can also be used in their bypass mode to feed customer nodes
> > clocks. I just think the check in the clkoutx2_recalc is wrong, and should be
> > enhanced to actually check what is the target mode for the clock once it is
> > enabled. Maybe something like this would work properly:
> > 
> > diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c
> > index 3a0296c..ba218fb 100644
> > --- a/arch/arm/mach-omap2/dpll3xxx.c
> > +++ b/arch/arm/mach-omap2/dpll3xxx.c
> > @@ -658,14 +658,12 @@ unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw,
> > 
> >         dd = pclk->dpll_data;
> > 
> > -       WARN_ON(!dd->enable_mask);
> > -
> > -       v = __raw_readl(dd->control_reg) & dd->enable_mask;
> > -       v >>= __ffs(dd->enable_mask);
> > -       if ((v != OMAP3XXX_EN_DPLL_LOCKED) || (dd->flags & DPLL_J_TYPE))
> > +       if ((dd->flags & DPLL_J_TYPE) ||
> > +           __clk_get_rate(dd->clk_bypass) == __clk_get_rate(pclk))
> >                 rate = parent_rate;
> >         else
> >                 rate = parent_rate * 2;
> > +
> >         return rate;
> >  }
> > 
> 
> [...]
> 
> > Getting comment from someone like Paul would probably help here.
> 
> Looks like this is a regression from the CCF port.
> 
> Seems to me that the code above assumes that when the DPLL's rate is set 
> to the same rate as the bypass clock's rate, we can assume that the DPLL 
> is in bypass.  I wonder if that's valid in a case where a previous OS or 
> bootloader may have programmed the DPLL.

Well it used to be that calling clk_set_rate(dpll, bypass_rate) would
put it in bypass, I don't know if that is still the case. But you are
right that having the implicit assumption that 'bypass rate' == 'DPLL in
bypass' is not safe since a bootloader could lock this PLL to the same
rate as it's bypass rate.

I hope that the bypass rate stuff does not get swept away in the changes
since it is an interesting way to save a little power.

Regards,
Mike

> 
> Sounds to me like the best way to fix it would be to test whether this 
> code is intended to return the "target rate" (when the struct clk 
> representing the DPLL is disabled), versus the "current rate" (when the 
> struct clk representing the DPLL is enabled).  If it's the target rate, 
> then there's no point checking the current state of the hardware.  A check 
> similar to the above would probably be fine.  Otherwise, seems best to use 
> the existing code that does test the PLL state.
> 
> 
> 
> - Paul
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Paul Walmsley Oct. 13, 2013, 8:17 p.m. UTC | #12
On Mon, 7 Oct 2013, Mike Turquette wrote:

> Well it used to be that calling clk_set_rate(dpll, bypass_rate) would
> put it in bypass, I don't know if that is still the case. But you are
> right that having the implicit assumption that 'bypass rate' == 'DPLL in
> bypass' is not safe since a bootloader could lock this PLL to the same
> rate as it's bypass rate.
> 
> I hope that the bypass rate stuff does not get swept away in the changes
> since it is an interesting way to save a little power.

Yeah, I don't think anyone's proposing to remove it, as far as I know.

Am more concerned about any similar lurking problems in low-level clock 
code that use the current state of the clock hardware to determine a 
possible future rate.  Am hoping that this particular issue is simply due 
to the state dependency between the CLKOUTX2 node and the PLL node.  
Considering this issue, in retrospect, it probably would have been better 
to merge the CLKOUTX2 node with the PLL.


- Paul
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c
index 3a0296c..ba218fb 100644
--- a/arch/arm/mach-omap2/dpll3xxx.c
+++ b/arch/arm/mach-omap2/dpll3xxx.c
@@ -658,14 +658,12 @@  unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw,

         dd = pclk->dpll_data;

-       WARN_ON(!dd->enable_mask);
-
-       v = __raw_readl(dd->control_reg) & dd->enable_mask;
-       v >>= __ffs(dd->enable_mask);
-       if ((v != OMAP3XXX_EN_DPLL_LOCKED) || (dd->flags & DPLL_J_TYPE))
+       if ((dd->flags & DPLL_J_TYPE) ||
+           __clk_get_rate(dd->clk_bypass) == __clk_get_rate(pclk))
                 rate = parent_rate;
         else
                 rate = parent_rate * 2;
+
         return rate;
  }