diff mbox

regression: Clock changes in next-20141205 break at least omap4

Message ID 5481F79D.4010504@codeaurora.org (mailing list archive)
State New, archived
Headers show

Commit Message

Stephen Boyd Dec. 5, 2014, 6:21 p.m. UTC
On 12/05/2014 08:55 AM, Tony Lindgren wrote:
> Hi,
>
> Looks like commit 646cafc6aa4d ("clk: Change clk_ops->determine_rate
> to return a clk_hw as the best parent") breaks booting at least for
> omap4.

Do you get a compilation warning in arch/arm/mach-omap2/dpll3xxx.c ?
From what I can tell omap3_noncore_dpll_determine_rate() hasn't been
updated to take a clk_hw pointer instead of clk pointer. It was there in
the original patch and I'm not sure why Mike dropped that part while
applying.

Comments

Tony Lindgren Dec. 5, 2014, 6:38 p.m. UTC | #1
* Stephen Boyd <sboyd@codeaurora.org> [141205 10:23]:
> On 12/05/2014 08:55 AM, Tony Lindgren wrote:
> > Hi,
> >
> > Looks like commit 646cafc6aa4d ("clk: Change clk_ops->determine_rate
> > to return a clk_hw as the best parent") breaks booting at least for
> > omap4.
> 
> Do you get a compilation warning in arch/arm/mach-omap2/dpll3xxx.c ?

Yes so it seems.

> From what I can tell omap3_noncore_dpll_determine_rate() hasn't been
> updated to take a clk_hw pointer instead of clk pointer. It was there in
> the original patch and I'm not sure why Mike dropped that part while
> applying.

OK that makes sense, Mike should apply that part too. Note that also
include/linux/clk/ti.h needs changed accordingly for struct clk_hw,
which you probably had in your orignal patch too. Assuming that's there,
please feel free to add:

Acked-by: Tony Lindgren <tony@atomide.com>
 
> diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c
> index 20e120d..c2da2a0 100644
> --- a/arch/arm/mach-omap2/dpll3xxx.c
> +++ b/arch/arm/mach-omap2/dpll3xxx.c
> @@ -474,7 +474,7 @@ void omap3_noncore_dpll_disable(struct clk_hw *hw)
>   */
>  long omap3_noncore_dpll_determine_rate(struct clk_hw *hw, unsigned long rate,
>  				       unsigned long *best_parent_rate,
> -				       struct clk **best_parent_clk)
> +				       struct clk_hw **best_parent_clk)
>  {
>  	struct clk_hw_omap *clk = to_clk_hw_omap(hw);
>  	struct dpll_data *dd;
> @@ -488,10 +488,10 @@ long omap3_noncore_dpll_determine_rate(struct clk_hw *hw, unsigned long rate,
>  
>  	if (__clk_get_rate(dd->clk_bypass) == rate &&
>  	    (dd->modes & (1 << DPLL_LOW_POWER_BYPASS))) {
> -		*best_parent_clk = dd->clk_bypass;
> +		*best_parent_clk = __clk_get_hw(dd->clk_bypass);
>  	} else {
>  		rate = omap2_dpll_round_rate(hw, rate, best_parent_rate);
> -		*best_parent_clk = dd->clk_ref;
> +		*best_parent_clk = __clk_get_hw(dd->clk_ref);
>  	}
>  
>  	*best_parent_rate = rate;
> diff --git a/arch/arm/mach-omap2/dpll44xx.c b/arch/arm/mach-omap2/dpll44xx.c
> index 535822f..0e58e5a 100644
> --- a/arch/arm/mach-omap2/dpll44xx.c
> +++ b/arch/arm/mach-omap2/dpll44xx.c
> @@ -223,7 +223,7 @@ out:
>   */
>  long omap4_dpll_regm4xen_determine_rate(struct clk_hw *hw, unsigned long rate,
>  					unsigned long *best_parent_rate,
> -					struct clk **best_parent_clk)
> +					struct clk_hw **best_parent_clk)
>  {
>  	struct clk_hw_omap *clk = to_clk_hw_omap(hw);
>  	struct dpll_data *dd;
> @@ -237,11 +237,11 @@ long omap4_dpll_regm4xen_determine_rate(struct clk_hw *hw, unsigned long rate,
>  
>  	if (__clk_get_rate(dd->clk_bypass) == rate &&
>  	    (dd->modes & (1 << DPLL_LOW_POWER_BYPASS))) {
> -		*best_parent_clk = dd->clk_bypass;
> +		*best_parent_clk = __clk_get_hw(dd->clk_bypass);
>  	} else {
>  		rate = omap4_dpll_regm4xen_round_rate(hw, rate,
>  						      best_parent_rate);
> -		*best_parent_clk = dd->clk_ref;
> +		*best_parent_clk = __clk_get_hw(dd->clk_ref);
>  	}
>  
>  	*best_parent_rate = rate;
> 
> -- 
> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
> a Linux Foundation Collaborative Project
>
Paul Walmsley Dec. 16, 2014, 12:21 a.m. UTC | #2
On 12/15/2014 03:02 PM, Mike Turquette wrote:
> Quoting Paul Walmsley (2014-12-12 15:28:32)
>> On Fri, 12 Dec 2014, Mike Turquette wrote:
>>
>>> Quoting Tony Lindgren (2014-12-05 10:38:49)
>>>> * Stephen Boyd <sboyd@codeaurora.org> [141205 10:23]:
>>>>> On 12/05/2014 08:55 AM, Tony Lindgren wrote:
>>>>>> Hi,
>>>>>>
>>>>>> Looks like commit 646cafc6aa4d ("clk: Change clk_ops->determine_rate
>>>>>> to return a clk_hw as the best parent") breaks booting at least for
>>>>>> omap4.
>>>>> Do you get a compilation warning in arch/arm/mach-omap2/dpll3xxx.c ?
>>>> Yes so it seems.
>>>>
>>>>>  From what I can tell omap3_noncore_dpll_determine_rate() hasn't been
>>>>> updated to take a clk_hw pointer instead of clk pointer. It was there in
>>>>> the original patch and I'm not sure why Mike dropped that part while
>>>>> applying.
>>>> OK that makes sense, Mike should apply that part too. Note that also
>>>> include/linux/clk/ti.h needs changed accordingly for struct clk_hw,
>>>> which you probably had in your orignal patch too. Assuming that's there,
>>>> please feel free to add:
>>>>
>>>> Acked-by: Tony Lindgren <tony@atomide.com>
>>> I figured out what went wrong here. When I applied Tomeu's changes the
>>> OMAP stuff did not apply at all. In fact the .determine_rate callbacks
>>> did not exist in clk-next. Paul merged that stuff through his tree[0]. I
>>> don't know why I didn't follow up on that at the time.
>>>
>>> So we need to come up with a solution. Paul can take the OMAP portion of
>>> Tomeu's changes[1] for OMAP, but I believe compilation will be broken in
>>> his tree until it meets up with mine in linux-next. Or we could set up a
>>> shared immutable branch that provides the needed changes.
>>>
>>> I could either set up a shared branch that includes Tomeu's changes that
>>> Paul could merge (will require a rebase of the tip of my tree) or Paul
>>> could provide a shared branch of the changes to dpll3xxx.c and
>>> dpll4xxx.c that I could merge in.
>>>
>>> Or I could remove Tomeu's patches from my tree since we're right up
>>> against the merge window but I would rather not do that since he has
>>> worked tirelessly on this topic.
>>>
>>> [0] http://www.spinics.net/lists/arm-kernel/msg377288.html
>>> [1] https://lkml.org/lkml/2014/12/2/70
>> I don't think there's much that I can do at this point.  My tree is quite
>> topologically distant from Linus's tree (pjw/omap-pending ->
>> tmlind/linux-omap -> arm/arm-soc -> torvalds/linux).  So anything I do is
>> high-latency.  My pull request for Tero's patches was sent to Tony a month
>> ago.
> Paul,
>
> I identified the patch in your tree that is missing in mine and, with
> Tony's help, applied your for-v3.19/omap-a signed tag to my tree. With
> these 5 patches in place I have applied Tero's two patches from
> Friday[0].
>
> Paul & Tony, are you OK for me to take both of Tero's patches? I'm
> already taking stuff in late so it is no trouble for me to pick up "ARM:
> OMAP3: clock: fix boot breakage in legacy mode" while I'm at it.
>
> I'm going to let this get at least one cycle in linux-next before
> sending my PR late this week. Hopefully Kevin (Cc'd) can check on the
> omap boards in his autobuilder once my tree hits -next?
>
> Let me know if I missed anything. Thanks for the great teamwork, gang.
>
> [0] http://lkml.kernel.org/r/<1418390521-7541-1-git-send-email-t-kristo@ti.com>
>
> Regards,
> Mike

I think Tony's taking the second patch from Tero.

- Paul
Tony Lindgren Dec. 16, 2014, 12:38 a.m. UTC | #3
* Paul Walmsley <pwalmsley@nvidia.com> [141215 16:23]:
> On 12/15/2014 03:02 PM, Mike Turquette wrote:
> >Quoting Paul Walmsley (2014-12-12 15:28:32)
> >>On Fri, 12 Dec 2014, Mike Turquette wrote:
> >>
> >>>Quoting Tony Lindgren (2014-12-05 10:38:49)
> >>>>* Stephen Boyd <sboyd@codeaurora.org> [141205 10:23]:
> >>>>>On 12/05/2014 08:55 AM, Tony Lindgren wrote:
> >>>>>>Hi,
> >>>>>>
> >>>>>>Looks like commit 646cafc6aa4d ("clk: Change clk_ops->determine_rate
> >>>>>>to return a clk_hw as the best parent") breaks booting at least for
> >>>>>>omap4.
> >>>>>Do you get a compilation warning in arch/arm/mach-omap2/dpll3xxx.c ?
> >>>>Yes so it seems.
> >>>>
> >>>>> From what I can tell omap3_noncore_dpll_determine_rate() hasn't been
> >>>>>updated to take a clk_hw pointer instead of clk pointer. It was there in
> >>>>>the original patch and I'm not sure why Mike dropped that part while
> >>>>>applying.
> >>>>OK that makes sense, Mike should apply that part too. Note that also
> >>>>include/linux/clk/ti.h needs changed accordingly for struct clk_hw,
> >>>>which you probably had in your orignal patch too. Assuming that's there,
> >>>>please feel free to add:
> >>>>
> >>>>Acked-by: Tony Lindgren <tony@atomide.com>
> >>>I figured out what went wrong here. When I applied Tomeu's changes the
> >>>OMAP stuff did not apply at all. In fact the .determine_rate callbacks
> >>>did not exist in clk-next. Paul merged that stuff through his tree[0]. I
> >>>don't know why I didn't follow up on that at the time.
> >>>
> >>>So we need to come up with a solution. Paul can take the OMAP portion of
> >>>Tomeu's changes[1] for OMAP, but I believe compilation will be broken in
> >>>his tree until it meets up with mine in linux-next. Or we could set up a
> >>>shared immutable branch that provides the needed changes.
> >>>
> >>>I could either set up a shared branch that includes Tomeu's changes that
> >>>Paul could merge (will require a rebase of the tip of my tree) or Paul
> >>>could provide a shared branch of the changes to dpll3xxx.c and
> >>>dpll4xxx.c that I could merge in.
> >>>
> >>>Or I could remove Tomeu's patches from my tree since we're right up
> >>>against the merge window but I would rather not do that since he has
> >>>worked tirelessly on this topic.
> >>>
> >>>[0] http://www.spinics.net/lists/arm-kernel/msg377288.html
> >>>[1] https://lkml.org/lkml/2014/12/2/70
> >>I don't think there's much that I can do at this point.  My tree is quite
> >>topologically distant from Linus's tree (pjw/omap-pending ->
> >>tmlind/linux-omap -> arm/arm-soc -> torvalds/linux).  So anything I do is
> >>high-latency.  My pull request for Tero's patches was sent to Tony a month
> >>ago.
> >Paul,
> >
> >I identified the patch in your tree that is missing in mine and, with
> >Tony's help, applied your for-v3.19/omap-a signed tag to my tree. With
> >these 5 patches in place I have applied Tero's two patches from
> >Friday[0].
> >
> >Paul & Tony, are you OK for me to take both of Tero's patches? I'm
> >already taking stuff in late so it is no trouble for me to pick up "ARM:
> >OMAP3: clock: fix boot breakage in legacy mode" while I'm at it.
> >
> >I'm going to let this get at least one cycle in linux-next before
> >sending my PR late this week. Hopefully Kevin (Cc'd) can check on the
> >omap boards in his autobuilder once my tree hits -next?
> >
> >Let me know if I missed anything. Thanks for the great teamwork, gang.
> >
> >[0] http://lkml.kernel.org/r/<1418390521-7541-1-git-send-email-t-kristo@ti.com>
> >
> >Regards,
> >Mike
> 
> I think Tony's taking the second patch from Tero.

If it applies to what Mike has now queued, please take that too Mike:

Acked-by: Tony Lindgren <tony@atomide.com>
Paul Walmsley Dec. 16, 2014, 1:31 a.m. UTC | #4
On 12/15/2014 05:38 PM, Tony Lindgren wrote:
> * Paul Walmsley <pwalmsley@nvidia.com> [141215 16:23]:
>> On 12/15/2014 03:02 PM, Mike Turquette wrote:
>>> Quoting Paul Walmsley (2014-12-12 15:28:32)
>>>> On Fri, 12 Dec 2014, Mike Turquette wrote:
>>>>
>>>>> Quoting Tony Lindgren (2014-12-05 10:38:49)
>>>>>> * Stephen Boyd <sboyd@codeaurora.org> [141205 10:23]:
>>>>>>> On 12/05/2014 08:55 AM, Tony Lindgren wrote:
>>>>>>>> Hi,
>>>>>>>>
>>>>>>>> Looks like commit 646cafc6aa4d ("clk: Change clk_ops->determine_rate
>>>>>>>> to return a clk_hw as the best parent") breaks booting at least for
>>>>>>>> omap4.
>>>>>>> Do you get a compilation warning in arch/arm/mach-omap2/dpll3xxx.c ?
>>>>>> Yes so it seems.
>>>>>>
>>>>>>>  From what I can tell omap3_noncore_dpll_determine_rate() hasn't been
>>>>>>> updated to take a clk_hw pointer instead of clk pointer. It was there in
>>>>>>> the original patch and I'm not sure why Mike dropped that part while
>>>>>>> applying.
>>>>>> OK that makes sense, Mike should apply that part too. Note that also
>>>>>> include/linux/clk/ti.h needs changed accordingly for struct clk_hw,
>>>>>> which you probably had in your orignal patch too. Assuming that's there,
>>>>>> please feel free to add:
>>>>>>
>>>>>> Acked-by: Tony Lindgren <tony@atomide.com>
>>>>> I figured out what went wrong here. When I applied Tomeu's changes the
>>>>> OMAP stuff did not apply at all. In fact the .determine_rate callbacks
>>>>> did not exist in clk-next. Paul merged that stuff through his tree[0]. I
>>>>> don't know why I didn't follow up on that at the time.
>>>>>
>>>>> So we need to come up with a solution. Paul can take the OMAP portion of
>>>>> Tomeu's changes[1] for OMAP, but I believe compilation will be broken in
>>>>> his tree until it meets up with mine in linux-next. Or we could set up a
>>>>> shared immutable branch that provides the needed changes.
>>>>>
>>>>> I could either set up a shared branch that includes Tomeu's changes that
>>>>> Paul could merge (will require a rebase of the tip of my tree) or Paul
>>>>> could provide a shared branch of the changes to dpll3xxx.c and
>>>>> dpll4xxx.c that I could merge in.
>>>>>
>>>>> Or I could remove Tomeu's patches from my tree since we're right up
>>>>> against the merge window but I would rather not do that since he has
>>>>> worked tirelessly on this topic.
>>>>>
>>>>> [0] http://www.spinics.net/lists/arm-kernel/msg377288.html
>>>>> [1] https://lkml.org/lkml/2014/12/2/70
>>>> I don't think there's much that I can do at this point.  My tree is quite
>>>> topologically distant from Linus's tree (pjw/omap-pending ->
>>>> tmlind/linux-omap -> arm/arm-soc -> torvalds/linux).  So anything I do is
>>>> high-latency.  My pull request for Tero's patches was sent to Tony a month
>>>> ago.
>>> Paul,
>>>
>>> I identified the patch in your tree that is missing in mine and, with
>>> Tony's help, applied your for-v3.19/omap-a signed tag to my tree. With
>>> these 5 patches in place I have applied Tero's two patches from
>>> Friday[0].
>>>
>>> Paul & Tony, are you OK for me to take both of Tero's patches? I'm
>>> already taking stuff in late so it is no trouble for me to pick up "ARM:
>>> OMAP3: clock: fix boot breakage in legacy mode" while I'm at it.
>>>
>>> I'm going to let this get at least one cycle in linux-next before
>>> sending my PR late this week. Hopefully Kevin (Cc'd) can check on the
>>> omap boards in his autobuilder once my tree hits -next?
>>>
>>> Let me know if I missed anything. Thanks for the great teamwork, gang.
>>>
>>> [0] http://lkml.kernel.org/r/<1418390521-7541-1-git-send-email-t-kristo@ti.com>
>>>
>>> Regards,
>>> Mike
>> I think Tony's taking the second patch from Tero.
> If it applies to what Mike has now queued, please take that too Mike:
>
> Acked-by: Tony Lindgren <tony@atomide.com>

I just took a quick glance at Tero's second patch, and it looks like a 
hack to me.  Better to fix the problem in the core CCF code if 
possible.  I don't think there's any reason why a PLL couldn't have just 
one parent clock.  But I'm fine with merging it as a short-term fix if 
fixing the core code is difficult or risky.

- Paul
Stephen Boyd Dec. 16, 2014, 7:01 p.m. UTC | #5
On 12/15/2014 05:31 PM, Paul Walmsley wrote:
>
> I just took a quick glance at Tero's second patch, and it looks like a
> hack to me.  Better to fix the problem in the core CCF code if
> possible.  I don't think there's any reason why a PLL couldn't have
> just one parent clock.  But I'm fine with merging it as a short-term
> fix if fixing the core code is difficult or risky.

Can you describe what's wrong? Does the PLL have a mux with two inputs
that map to the same clock?
Paul Walmsley Dec. 16, 2014, 8:01 p.m. UTC | #6
+ Tero

On 12/16/2014 12:01 PM, Stephen Boyd wrote:
> On 12/15/2014 05:31 PM, Paul Walmsley wrote:
>> I just took a quick glance at Tero's second patch, and it looks like a
>> hack to me.  Better to fix the problem in the core CCF code if
>> possible.  I don't think there's any reason why a PLL couldn't have
>> just one parent clock.  But I'm fine with merging it as a short-term
>> fix if fixing the core code is difficult or risky.
> Can you describe what's wrong?

Took a closer look at it, at your prompting.

The first observation is that the issue seems to be limited to 
TI-specific clock code in drivers/clk/ti.  So nothing to worry about in 
terms of the CCF core, it looks.

The second observation is that this appears to only be a problem due to 
the current DT data in arch/arm/boot/dts/omap3xxx-clocks.dtsi:

     dpll3_ck: dpll3_ck {
         #clock-cells = <0>;
         compatible = "ti,omap3-dpll-core-clock";
         clocks = <&sys_ck>, <&sys_ck>;
         reg = <0x0d00>, <0x0d20>, <0x0d40>, <0x0d30>;
     };


It lists two entries for the "clocks" node for some reason. 
of_ti_dpll_setup() only seems to require one.

So unless there's some good reason to list two of them in the DTS file, 
the right fix would probably have been to fix the DT data.

> Does the PLL have a mux with two inputs that map to the same clock?
>

I don't think so.

...

Generally speaking, I suspect the way we model PLLs isn't quite right 
(although it's been a while since I've looked at that particular code).  
This was probably my fault, in the final analysis, for taking a shortcut 
here a long time ago.

Unless one wishes to implement support for multiple clock parents, it's 
probably not quite right to state that a PLL's reference clock is a 
"parent" in a clock tree sense.  When a PLL is active, the output clock 
originates from a VCO of some kind that is internal to the PLL.  The 
reference clock is just used by the PLL internal logic to close the 
control loop.  Some PLL-like clock sources use a third clock that is 
used to clock some of the PLL's internal logic (let's call this a 
"functional clock.")

So the reference clock and functional clock are (usually) required by 
the PLL to operate, and should therefore be required by the PLL clock 
driver code in the kernel; but one could claim that they aren't 
technically parent clocks of the PLL in a clock tree sense, since the 
downstream output clock isn't directly derived from either of those clocks.

Otherwise if we want to represent those clocks accurately in the Linux 
clock tree, we probably need to state that clocks can have multiple 
"parents" that often need to be active simultaneously, and we should 
propagate usecount changes accordingly up all of the parent paths.

...

Anyway, thanks for following up on this,

- Paul
Russell King - ARM Linux Dec. 16, 2014, 8:23 p.m. UTC | #7
On Tue, Dec 16, 2014 at 01:01:17PM -0700, Paul Walmsley wrote:
> So the reference clock and functional clock are (usually) required by the
> PLL to operate, and should therefore be required by the PLL clock driver
> code in the kernel; but one could claim that they aren't technically parent
> clocks of the PLL in a clock tree sense, since the downstream output clock
> isn't directly derived from either of those clocks.

The reference clock is the parent clock for a PLL, and the output clock
is a derivative of the reference clock.  The PLL maths show that very
clearly.
Paul Walmsley Dec. 16, 2014, 8:45 p.m. UTC | #8
On Tue, 16 Dec 2014, Russell King - ARM Linux wrote:

> On Tue, Dec 16, 2014 at 01:01:17PM -0700, Paul Walmsley wrote:
> > So the reference clock and functional clock are (usually) required by the
> > PLL to operate, and should therefore be required by the PLL clock driver
> > code in the kernel; but one could claim that they aren't technically parent
> > clocks of the PLL in a clock tree sense, since the downstream output clock
> > isn't directly derived from either of those clocks.
> 
> The reference clock is the parent clock for a PLL, and the output clock 
> is a derivative of the reference clock. The PLL maths show that very 
> clearly.

The PLL's internal oscillator is the electrical source of the PLL's output 
clock.  The reference clock is just used to discipline that internal 
oscillator.  Even that's not necessary - the reference clock can be 
optional on some clock source implementations, which can run the internal 
oscillator in open-loop mode.

The question of what the appropriate "parent" clock(s) should be is really 
a question of how the software chooses to model it, and has more to do 
with use-counts, constraints, etc.  I don't believe we have documented a 
precise definition for what a "parent clock" is, in the Linux clock 
framework context.


- Paul
Russell King - ARM Linux Dec. 16, 2014, 8:57 p.m. UTC | #9
On Tue, Dec 16, 2014 at 08:45:25PM +0000, Paul Walmsley wrote:
> On Tue, 16 Dec 2014, Russell King - ARM Linux wrote:
> 
> > On Tue, Dec 16, 2014 at 01:01:17PM -0700, Paul Walmsley wrote:
> > > So the reference clock and functional clock are (usually) required by the
> > > PLL to operate, and should therefore be required by the PLL clock driver
> > > code in the kernel; but one could claim that they aren't technically parent
> > > clocks of the PLL in a clock tree sense, since the downstream output clock
> > > isn't directly derived from either of those clocks.
> > 
> > The reference clock is the parent clock for a PLL, and the output clock 
> > is a derivative of the reference clock. The PLL maths show that very 
> > clearly.
> 
> The PLL's internal oscillator is the electrical source of the PLL's output 
> clock.  The reference clock is just used to discipline that internal 
> oscillator.  Even that's not necessary - the reference clock can be 
> optional on some clock source implementations, which can run the internal 
> oscillator in open-loop mode.

I would argue that running a PLL in open-loop mode is an exceptional
circumstance: in such scenarios, many PLLs will head towards a certain
frequency (depending on their design) and some may be rather unstable
in open loop mode.  Only those which have been explicitly designed to
be stable in open loop mode should be run that way.

And arguably, a PLL without a reference clock is not a phase *locked*
loop at all - the clue is in the name.  A PLL without a reference clock
is merely an oscillator.  There is no "phase lock" what so ever.

> The question of what the appropriate "parent" clock(s) should be is really 
> a question of how the software chooses to model it, and has more to do 
> with use-counts, constraints, etc.  I don't believe we have documented a 
> precise definition for what a "parent clock" is, in the Linux clock 
> framework context.

If a PLL is designed to be operated in open loop mode, then the parent
clock should be optional, otherwise the parent clock is rather fundamental
to the PLLs operation, in the same way that the parent clock is
fundamental to a divider's operation.

You can argue that taking away the "reference" clock to a divider gives
a known output (which happens to be 0Hz) but a steady state can still be
a perfectly valid clock signal too if it changes state at some point. :)

In much the same way, some PLLs are designed to disable their output
when they are not in lock.  Much like that divider above with no
reference input.

This really is a question about how you view a PLL, and it's one which
can be debated for a very long time, and everyone will have perfectly
valid but conflicting ideas on it.
Paul Walmsley Dec. 16, 2014, 10:25 p.m. UTC | #10
+ paul@pwsan.com (I prefer not having to deal with MS Exchange when 
possible :-) )

On Tue, 16 Dec 2014, Russell King - ARM Linux wrote:

> On Tue, Dec 16, 2014 at 08:45:25PM +0000, Paul Walmsley wrote:
> > On Tue, 16 Dec 2014, Russell King - ARM Linux wrote:
> > 
> > > On Tue, Dec 16, 2014 at 01:01:17PM -0700, Paul Walmsley wrote:
> > > > So the reference clock and functional clock are (usually) required by the
> > > > PLL to operate, and should therefore be required by the PLL clock driver
> > > > code in the kernel; but one could claim that they aren't technically parent
> > > > clocks of the PLL in a clock tree sense, since the downstream output clock
> > > > isn't directly derived from either of those clocks.
> > > 
> > > The reference clock is the parent clock for a PLL, and the output clock 
> > > is a derivative of the reference clock. The PLL maths show that very 
> > > clearly.
> > 
> > The PLL's internal oscillator is the electrical source of the PLL's output 
> > clock.  The reference clock is just used to discipline that internal 
> > oscillator.  Even that's not necessary - the reference clock can be 
> > optional on some clock source implementations, which can run the internal 
> > oscillator in open-loop mode.
> 
> I would argue that running a PLL in open-loop mode is an exceptional
> circumstance: in such scenarios, many PLLs will head towards a certain
> frequency (depending on their design) and some may be rather unstable
> in open loop mode.  Only those which have been explicitly designed to
> be stable in open loop mode should be run that way.
> 
> And arguably, a PLL without a reference clock is not a phase *locked*
> loop at all - the clue is in the name.  A PLL without a reference clock
> is merely an oscillator.  There is no "phase lock" what so ever.

...

> This really is a question about how you view a PLL, and it's one which
> can be debated for a very long time, and everyone will have perfectly
> valid but conflicting ideas on it.

Yep, I agree with most of what you wrote.  I was mostly thinking about our 
Linux data structures and software abstraction for clocks that have 
multiple input clocks that all need to be simultaneously active for the IP 
block to work.  PLLs and PLL-like clock sources which take multiple input 
clocks just happened to be the examples of this phenomenon that came to 
mind.

Those multiple input clocks could all be considered "parents" from a 
use-counting point of view, and we could expect the core clock code to 
deal with them.  Or one could take the electrical point of view and 
consider only one of the input clocks to be the "parent" -- whatever's 
directly driving the output clock -- and fix up the gating and constraint 
details in the driver code for that clock source.

I don't think this pot is boiling over at the moment; but, just something 
for us to reflect on.


- Paul
Lucas Stach Dec. 17, 2014, 9:52 a.m. UTC | #11
Am Dienstag, den 16.12.2014, 22:25 +0000 schrieb Paul Walmsley:
> + paul@pwsan.com (I prefer not having to deal with MS Exchange when 
> possible :-) )
> 
> On Tue, 16 Dec 2014, Russell King - ARM Linux wrote:
> 
> > On Tue, Dec 16, 2014 at 08:45:25PM +0000, Paul Walmsley wrote:
> > > On Tue, 16 Dec 2014, Russell King - ARM Linux wrote:
> > > 
> > > > On Tue, Dec 16, 2014 at 01:01:17PM -0700, Paul Walmsley wrote:
> > > > > So the reference clock and functional clock are (usually) required by the
> > > > > PLL to operate, and should therefore be required by the PLL clock driver
> > > > > code in the kernel; but one could claim that they aren't technically parent
> > > > > clocks of the PLL in a clock tree sense, since the downstream output clock
> > > > > isn't directly derived from either of those clocks.
> > > > 
> > > > The reference clock is the parent clock for a PLL, and the output clock 
> > > > is a derivative of the reference clock. The PLL maths show that very 
> > > > clearly.
> > > 
> > > The PLL's internal oscillator is the electrical source of the PLL's output 
> > > clock.  The reference clock is just used to discipline that internal 
> > > oscillator.  Even that's not necessary - the reference clock can be 
> > > optional on some clock source implementations, which can run the internal 
> > > oscillator in open-loop mode.
> > 
> > I would argue that running a PLL in open-loop mode is an exceptional
> > circumstance: in such scenarios, many PLLs will head towards a certain
> > frequency (depending on their design) and some may be rather unstable
> > in open loop mode.  Only those which have been explicitly designed to
> > be stable in open loop mode should be run that way.
> > 
> > And arguably, a PLL without a reference clock is not a phase *locked*
> > loop at all - the clue is in the name.  A PLL without a reference clock
> > is merely an oscillator.  There is no "phase lock" what so ever.
> 
> ...
> 
> > This really is a question about how you view a PLL, and it's one which
> > can be debated for a very long time, and everyone will have perfectly
> > valid but conflicting ideas on it.
> 
> Yep, I agree with most of what you wrote.  I was mostly thinking about our 
> Linux data structures and software abstraction for clocks that have 
> multiple input clocks that all need to be simultaneously active for the IP 
> block to work.  PLLs and PLL-like clock sources which take multiple input 
> clocks just happened to be the examples of this phenomenon that came to 
> mind.
> 
> Those multiple input clocks could all be considered "parents" from a 
> use-counting point of view, and we could expect the core clock code to 
> deal with them.  Or one could take the electrical point of view and 
> consider only one of the input clocks to be the "parent" -- whatever's 
> directly driving the output clock -- and fix up the gating and constraint 
> details in the driver code for that clock source.
> 
> I don't think this pot is boiling over at the moment; but, just something 
> for us to reflect on.
> 
Maybe I'm thinking about this too lightly, but I think we already have
the right abstractions in place.

The clock tree in Linux is always modeled along the flow of reference
clocks. So typically the root of the tree is something like an
oscillator and everything spreads out from this in a parent/child
relation. So clearly the reference clock of a PLL is the PLLs parent. If
the PLL is running in open-loop mode (isn't this rather direct frequency
synthesis?) is has no parent and is the root of a tree itself.

If a PLL needs a functional clock to drive some internal logic, that
doesn't directly influence the clock synthesis from reference to
resulting clock, that clock would be no parent to the PLL. The PLL is
merely a consumer of this clock just like every other device in the
system.

Regards,
Lucas
Tero Kristo Dec. 17, 2014, 11:59 a.m. UTC | #12
On 12/17/2014 11:52 AM, Lucas Stach wrote:
> Am Dienstag, den 16.12.2014, 22:25 +0000 schrieb Paul Walmsley:
>> + paul@pwsan.com (I prefer not having to deal with MS Exchange when
>> possible :-) )
>>
>> On Tue, 16 Dec 2014, Russell King - ARM Linux wrote:
>>
>>> On Tue, Dec 16, 2014 at 08:45:25PM +0000, Paul Walmsley wrote:
>>>> On Tue, 16 Dec 2014, Russell King - ARM Linux wrote:
>>>>
>>>>> On Tue, Dec 16, 2014 at 01:01:17PM -0700, Paul Walmsley wrote:
>>>>>> So the reference clock and functional clock are (usually) required by the
>>>>>> PLL to operate, and should therefore be required by the PLL clock driver
>>>>>> code in the kernel; but one could claim that they aren't technically parent
>>>>>> clocks of the PLL in a clock tree sense, since the downstream output clock
>>>>>> isn't directly derived from either of those clocks.
>>>>>
>>>>> The reference clock is the parent clock for a PLL, and the output clock
>>>>> is a derivative of the reference clock. The PLL maths show that very
>>>>> clearly.
>>>>
>>>> The PLL's internal oscillator is the electrical source of the PLL's output
>>>> clock.  The reference clock is just used to discipline that internal
>>>> oscillator.  Even that's not necessary - the reference clock can be
>>>> optional on some clock source implementations, which can run the internal
>>>> oscillator in open-loop mode.
>>>
>>> I would argue that running a PLL in open-loop mode is an exceptional
>>> circumstance: in such scenarios, many PLLs will head towards a certain
>>> frequency (depending on their design) and some may be rather unstable
>>> in open loop mode.  Only those which have been explicitly designed to
>>> be stable in open loop mode should be run that way.
>>>
>>> And arguably, a PLL without a reference clock is not a phase *locked*
>>> loop at all - the clue is in the name.  A PLL without a reference clock
>>> is merely an oscillator.  There is no "phase lock" what so ever.
>>
>> ...
>>
>>> This really is a question about how you view a PLL, and it's one which
>>> can be debated for a very long time, and everyone will have perfectly
>>> valid but conflicting ideas on it.
>>
>> Yep, I agree with most of what you wrote.  I was mostly thinking about our
>> Linux data structures and software abstraction for clocks that have
>> multiple input clocks that all need to be simultaneously active for the IP
>> block to work.  PLLs and PLL-like clock sources which take multiple input
>> clocks just happened to be the examples of this phenomenon that came to
>> mind.
>>
>> Those multiple input clocks could all be considered "parents" from a
>> use-counting point of view, and we could expect the core clock code to
>> deal with them.  Or one could take the electrical point of view and
>> consider only one of the input clocks to be the "parent" -- whatever's
>> directly driving the output clock -- and fix up the gating and constraint
>> details in the driver code for that clock source.
>>
>> I don't think this pot is boiling over at the moment; but, just something
>> for us to reflect on.
>>
> Maybe I'm thinking about this too lightly, but I think we already have
> the right abstractions in place.
>
> The clock tree in Linux is always modeled along the flow of reference
> clocks. So typically the root of the tree is something like an
> oscillator and everything spreads out from this in a parent/child
> relation. So clearly the reference clock of a PLL is the PLLs parent. If
> the PLL is running in open-loop mode (isn't this rather direct frequency
> synthesis?) is has no parent and is the root of a tree itself.
>
> If a PLL needs a functional clock to drive some internal logic, that
> doesn't directly influence the clock synthesis from reference to
> resulting clock, that clock would be no parent to the PLL. The PLL is
> merely a consumer of this clock just like every other device in the
> system.
>
> Regards,
> Lucas

The dual parent issue required by the DPLL code is caused by the 
introduction of determine-rate / set-parent / set-rate-and-parent logic 
to OMAP DPPLs. I took a short-cut here, making the assumption that every 
DPLL has both of these clocks defined (which basically they do have, as 
every DPLL technically has both reference and bypass clocks, but which 
can be the same clock => thus the declaration itself is missing in some 
cases.) The clock data is modelled like this for every other TI SoC 
(which use DT clock data), except for omap3 legacy clock data, thus the 
patch to tweak the clock data itself. It would be much harder to modify 
the clock code itself to take this into account, rather than just add 
the missing parents to the clock data, thus the approach taken in the 
patch. We can of course discuss whether it is okay to have DPLLs 
modelled as they are right now. I think them as composite clocks 
containing mux, gate and divider/multiplier logic within a single black 
box, we could split them up, but I don't see much need for that. If it 
works, don't break it.

Regarding the omap3 clock data patch, I have also just posted new patch 
set that will move the omap3 legacy clock data under clock driver, until 
we figure out what to finally do with this (use the DT clocks, or 
introduce loadable clock data modules or something.) Thus, the data 
patch is kind of a temporary one, or thats the intention at least, but I 
wouldn't call it a hack. It is there to fix the issues introduced by the 
set-parent / set-rate-and-parent logic, which was required by the 
changes to the core clock set-rate.

-Tero
Paul Walmsley Dec. 18, 2014, 7:23 p.m. UTC | #13
On Wed, 17 Dec 2014, Lucas Stach wrote:

> Maybe I'm thinking about this too lightly, but I think we already have
> the right abstractions in place.
> 
> The clock tree in Linux is always modeled along the flow of reference
> clocks. So typically the root of the tree is something like an
> oscillator and everything spreads out from this in a parent/child
> relation. So clearly the reference clock of a PLL is the PLLs parent. If
> the PLL is running in open-loop mode (isn't this rather direct frequency
> synthesis?) is has no parent and is the root of a tree itself.
> 
> If a PLL needs a functional clock to drive some internal logic, that
> doesn't directly influence the clock synthesis from reference to
> resulting clock, that clock would be no parent to the PLL. The PLL is
> merely a consumer of this clock just like every other device in the
> system.

I suspect we're using different terminology.

From my point of view, a reference clock is an input clock signal that is 
used by another clock generator IP block or clock measurement IP block.  
The use is to measure and (optionally) discipline another oscillator.  
Thus the clock generator/measurement IP block generally does not 
electrically propagate the reference clock outside of the block.  
(Although some of the reference clock's characteristics, like phase noise 
or frequency stability, may be propagated indirectly.)  Only a small 
number of clock tree entities makes use of reference clocks.  

By contrast, we could use the term "source clock" in the SoC context to 
mean a clock signal that directly drives a downstream IP block, in an 
electrical sense.  These clocks are directly propagated through dividers 
and muxes.

If you're willing to play along with this terminology, then a PLL's 
"source clock" would be its internal VCO/DCO, which thus would be the root 
clock of the PLL.

Flipping over from hardware to software, in the Linux clock tree, there's 
usually not much point to modeling the VCO/DCO directly because it tends 
not to be under the direct control of the OS, and it is usually tightly 
integrated into the PLLs from a hardware point of view.  But unlike most 
of the Linux clock tree nodes that are downstream from clock sources, 
which use clocks that are electrically driven by the clock source, the 
clock signal that PLLs and PLL-like clocks generate is not directly driven 
by the reference clock.

So why is a reference clock listed as a Linux parent clock of an OMAP PLL?  
At least for OMAP, it was sort of shoehorned in to represent a gating 
dependency.  It was a way of stating that the reference clock had to be 
enabled for the PLL to generate an output clock.  (The off-chip crystal 
oscillator that drives most of the PLL reference clocks could be disabled 
when all of its users were idle, to save energy.)  But this type of gating 
dependency is equally true for, say, a separate functional clock that the 
clock source requires in order to operate.  (OMAP PLLs didn't have a 
separate functional clock, at least not that I was aware of; but that's 
not true for some similar clock sources used in other SoCs.)

The clock framework wasn't re-entrant back then, and we wanted to avoid 
implementing re-entrancy because we were worried that it could turn into a 
mess.  So we just wound up listing the reference clock as the PLL's Linux 
parent clock.

My original comment was just intended to be a reflection on what it means 
to be a "parent clock" in the Linux clock tree sense.  If it's intended to 
represent "source clocks" as they are defined above, then PLLs and 
PLL-like clocks should be root nodes, except for the few cases where it's 
useful to add a node for the underlying source oscillator directly (for 
example, if open-loop mode is supported).

This might be the right way forward for the time being, and I like the 
idea of stating that Linux parent clocks should represent electrical 
"source clock" relationships.  

That raises the question of what to do about the additional gating 
relationships.  At the moment, the clock type code needs to be responsible 
for calling clk_enable() etc. on all of the reference and functional 
clocks that need to be ungated for the clock source to work.  But it has 
always seemed preferable to me to represent fundamental hardware 
structural constraints in data.  If the data structures are well-defined, 
then the data should be relatively easy to analyze, reason about, 
generate, validate, share across platforms, and operate upon iteratively; 
unlike custom per-clocktype code, which often isn't.


- Paul
Mike Turquette Dec. 18, 2014, 11:37 p.m. UTC | #14
Quoting Paul Walmsley (2014-12-18 11:23:07)
> On Wed, 17 Dec 2014, Lucas Stach wrote:
> 
> > Maybe I'm thinking about this too lightly, but I think we already have
> > the right abstractions in place.
> > 
> > The clock tree in Linux is always modeled along the flow of reference
> > clocks. So typically the root of the tree is something like an
> > oscillator and everything spreads out from this in a parent/child
> > relation. So clearly the reference clock of a PLL is the PLLs parent. If
> > the PLL is running in open-loop mode (isn't this rather direct frequency
> > synthesis?) is has no parent and is the root of a tree itself.
> > 
> > If a PLL needs a functional clock to drive some internal logic, that
> > doesn't directly influence the clock synthesis from reference to
> > resulting clock, that clock would be no parent to the PLL. The PLL is
> > merely a consumer of this clock just like every other device in the
> > system.
> 
> I suspect we're using different terminology.
> 
> From my point of view, a reference clock is an input clock signal that is 
> used by another clock generator IP block or clock measurement IP block.  
> The use is to measure and (optionally) discipline another oscillator.  
> Thus the clock generator/measurement IP block generally does not 
> electrically propagate the reference clock outside of the block.  
> (Although some of the reference clock's characteristics, like phase noise 
> or frequency stability, may be propagated indirectly.)  Only a small 
> number of clock tree entities makes use of reference clocks.  
> 
> By contrast, we could use the term "source clock" in the SoC context to 
> mean a clock signal that directly drives a downstream IP block, in an 
> electrical sense.  These clocks are directly propagated through dividers 
> and muxes.
> 
> If you're willing to play along with this terminology, then a PLL's 
> "source clock" would be its internal VCO/DCO, which thus would be the root 
> clock of the PLL.
> 
> Flipping over from hardware to software, in the Linux clock tree, there's 
> usually not much point to modeling the VCO/DCO directly because it tends 
> not to be under the direct control of the OS, and it is usually tightly 
> integrated into the PLLs from a hardware point of view.  But unlike most 
> of the Linux clock tree nodes that are downstream from clock sources, 
> which use clocks that are electrically driven by the clock source, the 
> clock signal that PLLs and PLL-like clocks generate is not directly driven 
> by the reference clock.

Hi Paul,

This is debatable given that the formula to determine the OMAP DPLL
output rate directly depends upon the rate of the input clock (osc,
32Khz, hsd, bypass, etc). I'm not speaking for all PLLs, just for the
OMAP ones that I am familiar with.

> 
> So why is a reference clock listed as a Linux parent clock of an OMAP PLL?  
> At least for OMAP, it was sort of shoehorned in to represent a gating 
> dependency.  It was a way of stating that the reference clock had to be 
> enabled for the PLL to generate an output clock.  (The off-chip crystal 
> oscillator that drives most of the PLL reference clocks could be disabled 
> when all of its users were idle, to save energy.)  But this type of gating 
> dependency is equally true for, say, a separate functional clock that the 
> clock source requires in order to operate.  (OMAP PLLs didn't have a 
> separate functional clock, at least not that I was aware of; but that's 
> not true for some similar clock sources used in other SoCs.)

Using your terminology above, it is possible to do what you want to do
today without any change to the clock framework. Simply make each DPLL a
device. That device calls clk_get, clk_prepare_enable on the input
reference clock. Coincidentally these new DPLL device are clock
providers themselves and they provide root clocks of their own which are
the DPLLs and corresponding Mx outputs. This model would treat the
reference clock as something that drives the DPLL device's logic, but
not as a part of the clock signal chain.

I don't personally agree with the idea that the reference clock is not a
parent of the DPLL, but I don't oppose any change to the OMAP clock
driver along those lines so long as it is done in a sane way. It seems
there is never just one correct way to look at these things.

> 
> The clock framework wasn't re-entrant back then, and we wanted to avoid 
> implementing re-entrancy because we were worried that it could turn into a 
> mess.  So we just wound up listing the reference clock as the PLL's Linux 
> parent clock.
> 
> My original comment was just intended to be a reflection on what it means 
> to be a "parent clock" in the Linux clock tree sense.  If it's intended to 
> represent "source clocks" as they are defined above, then PLLs and 
> PLL-like clocks should be root nodes, except for the few cases where it's 
> useful to add a node for the underlying source oscillator directly (for 
> example, if open-loop mode is supported).
> 
> This might be the right way forward for the time being, and I like the 
> idea of stating that Linux parent clocks should represent electrical 
> "source clock" relationships.  
> 
> That raises the question of what to do about the additional gating 
> relationships.  At the moment, the clock type code needs to be responsible 
> for calling clk_enable() etc. on all of the reference and functional 
> clocks that need to be ungated for the clock source to work.  But it has 
> always seemed preferable to me to represent fundamental hardware 
> structural constraints in data.  If the data structures are well-defined, 
> then the data should be relatively easy to analyze, reason about, 
> generate, validate, share across platforms, and operate upon iteratively; 
> unlike custom per-clocktype code, which often isn't.

I completely agree that the interfaces and abstractions in the clock
framework do not scale well. As an example, there could be much more
reuse if callbacks such as .get_best_div() existed and the large variety
of .round_rate() implementations could be replaced by a single generic
one.

Easier mixing and matching of callbacks would be great as well. We don't
quite have polymorphism but something better could be achieved than the
complex clock type. Namely the ability to combine various clock hardware
ops at run-time without having to always generate unique struct clk_ops
per platform.

I think there are lots of ideas out there on how to improve this stuff.

Regards,
Mike

> 
> 
> - Paul
Paul Walmsley Dec. 19, 2014, 2:15 a.m. UTC | #15
On Thu, 18 Dec 2014, Mike Turquette wrote:

> Quoting Paul Walmsley (2014-12-18 11:23:07)
>
> > Flipping over from hardware to software, in the Linux clock tree, there's 
> > usually not much point to modeling the VCO/DCO directly because it tends 
> > not to be under the direct control of the OS, and it is usually tightly 
> > integrated into the PLLs from a hardware point of view.  But unlike most 
> > of the Linux clock tree nodes that are downstream from clock sources, 
> > which use clocks that are electrically driven by the clock source, the 
> > clock signal that PLLs and PLL-like clocks generate is not directly driven 
> > by the reference clock.
> 
> Hi Paul,

Hi Mike,

> This is debatable given that the formula to determine the OMAP DPLL 
> output rate directly depends upon the rate of the input clock (osc, 
> 32Khz, hsd, bypass, etc). I'm not speaking for all PLLs, just for the 
> OMAP ones that I am familiar with.

The frequency and phase noise characteristics of the PLL's output signal 
are partially a function of the reference clock.  But that's only because 
the reference clock is used to steer the VCO.  It's not because the 
reference clock itself appears on the PLL output.  Even if the reference 
clock dividers and VCO loop dividers were both set to divide-by-one, the 
reference clock still would not appear on the PLL output - merely a 
simulacrum of it, originating by the VCO.  The PLL's output clock is, 
electrically, directly driven by the VCO.

Page 5 of this PDF has a nice frequency synthesis PLL block diagram with 
integer dividers:

    http://www.ti.com/lit/an/swra029/swra029.pdf

To rephrase, if, in the block diagram above, one were to remove everything 
from the TCXO reference clock on the left to the triangle to the left of 
the VCO, and to replace all that with a constant voltage input to the VCO, 
you'd still get a clock signal out of the IP block, even though the 
reference clock would no longer exist.

> > So why is a reference clock listed as a Linux parent clock of an OMAP PLL?  
> > At least for OMAP, it was sort of shoehorned in to represent a gating 
> > dependency.  It was a way of stating that the reference clock had to be 
> > enabled for the PLL to generate an output clock.  (The off-chip crystal 
> > oscillator that drives most of the PLL reference clocks could be disabled 
> > when all of its users were idle, to save energy.)  But this type of gating 
> > dependency is equally true for, say, a separate functional clock that the 
> > clock source requires in order to operate.  (OMAP PLLs didn't have a 
> > separate functional clock, at least not that I was aware of; but that's 
> > not true for some similar clock sources used in other SoCs.)
> 
> Using your terminology above, it is possible to do what you want to do
> today without any change to the clock framework. Simply make each DPLL a
> device. That device calls clk_get, clk_prepare_enable on the input
> reference clock. 

I think I did something like that with the Tegra DFLL driver last year.  
Except the clock provider device was the DFLL IP block itself, with its 
own registers, etc., and not an additional abstraction, if I recall 
correctly.

My interest is mostly to determine whether some of that special-case code 
can be converted into data that the CCF core can operate on, in a 
consistent manner that would be useful across platforms, and in a way that 
several people could potentially agree on.

> Coincidentally these new DPLL device are clock providers themselves and 
> they provide root clocks of their own which are the DPLLs and 
> corresponding Mx outputs. This model would treat the reference clock as 
> something that drives the DPLL device's logic, but not as a part of the 
> clock signal chain.
> 
> I don't personally agree with the idea that the reference clock is not a
> parent of the DPLL,

I'd be interested to know how you would define a parent clock, if it 
differs from the electrical "source clock" definition that I mentioned.

The Linux clock tree is a software abstraction.  So one could define 
"parent clock" however one wishes.  (That's not to say that all 
definitions are equally useful...) 

One could state, for example, that a parent clock is any clock that has 
some effect on the output of the child clock.  That would be one 
definition which might be consistent with your comments.  The problem with 
that is that it means that a clock can have multiple simultaneously-active 
parents, which I'd naïvely think we'd want to avoid, if we could.

I also have to admit that my bias is towards definitions with some kind of 
relationship to the hardware, which helps avoid the "utter relativism" 
problem that you mention below.

> but I don't oppose any change to the OMAP clock driver along those lines 
> so long as it is done in a sane way. It seems there is never just one 
> correct way to look at these things.

I'd say that to the extent that one could come up with concrete 
definitions for terms like "parent clocks," it allows others to reason 
about how the CCF should work, helps distinguish between data and code 
changes that do and don't make sense, and helps others understand which 
changes might be acceptable to maintainers.

> > The clock framework wasn't re-entrant back then, and we wanted to avoid 
> > implementing re-entrancy because we were worried that it could turn into a 
> > mess.  So we just wound up listing the reference clock as the PLL's Linux 
> > parent clock.
> > 
> > My original comment was just intended to be a reflection on what it means 
> > to be a "parent clock" in the Linux clock tree sense.  If it's intended to 
> > represent "source clocks" as they are defined above, then PLLs and 
> > PLL-like clocks should be root nodes, except for the few cases where it's 
> > useful to add a node for the underlying source oscillator directly (for 
> > example, if open-loop mode is supported).
> > 
> > This might be the right way forward for the time being, and I like the 
> > idea of stating that Linux parent clocks should represent electrical 
> > "source clock" relationships.  
> > 
> > That raises the question of what to do about the additional gating 
> > relationships.  At the moment, the clock type code needs to be responsible 
> > for calling clk_enable() etc. on all of the reference and functional 
> > clocks that need to be ungated for the clock source to work.  But it has 
> > always seemed preferable to me to represent fundamental hardware 
> > structural constraints in data.  If the data structures are well-defined, 
> > then the data should be relatively easy to analyze, reason about, 
> > generate, validate, share across platforms, and operate upon iteratively; 
> > unlike custom per-clocktype code, which often isn't.
> 
> I completely agree that the interfaces and abstractions in the clock
> framework do not scale well. As an example, there could be much more
> reuse if callbacks such as .get_best_div() existed and the large variety
> of .round_rate() implementations could be replaced by a single generic
> one.
> 
> Easier mixing and matching of callbacks would be great as well. We don't
> quite have polymorphism but something better could be achieved than the
> complex clock type. Namely the ability to combine various clock hardware
> ops at run-time without having to always generate unique struct clk_ops
> per platform.
> 
> I think there are lots of ideas out there on how to improve this stuff.

Oh, just in case it isn't clear, my objective wasn't to criticize the 
existing CCF.  Just thinking that if it was possible to come to an 
agreement on how to define some of these entities, it might make it easier 
to reason together about ways to work on the core code and data 
structures.  I'd hate to spend a bunch of time working on changes that you 
would eventually nack because we might not agree on what a parent clock is 
:-)


- Paul
Paul Walmsley Dec. 19, 2014, 4:45 p.m. UTC | #16
On Wed, 17 Dec 2014, Tero Kristo wrote:

> The dual parent issue required by the DPLL code is caused by the introduction
> of determine-rate / set-parent / set-rate-and-parent logic to OMAP DPPLs. I
> took a short-cut here, making the assumption that every DPLL has both of these
> clocks defined (which basically they do have, as every DPLL technically has
> both reference and bypass clocks, but which can be the same clock => thus the
> declaration itself is missing in some cases.) The clock data is modelled like
> this for every other TI SoC (which use DT clock data), except for omap3 legacy
> clock data, thus the patch to tweak the clock data itself. It would be much
> harder to modify the clock code itself to take this into account, rather than
> just add the missing parents to the clock data, thus the approach taken in the
> patch. We can of course discuss whether it is okay to have DPLLs modelled as
> they are right now. I think them as composite clocks containing mux, gate and
> divider/multiplier logic within a single black box, we could split them up,
> but I don't see much need for that. If it works, don't break it.
> 
> Regarding the omap3 clock data patch, I have also just posted new patch set
> that will move the omap3 legacy clock data under clock driver, until we figure
> out what to finally do with this (use the DT clocks, or introduce loadable
> clock data modules or something.) Thus, the data patch is kind of a temporary
> one, or thats the intention at least, but I wouldn't call it a hack. It is
> there to fix the issues introduced by the set-parent / set-rate-and-parent
> logic, which was required by the changes to the core clock set-rate.

OK, I understand now why the OMAP3 clock DT data takes two of the same 
clock - one is for the reference and one is for bypass.  So I retract my 
earlier statement about it being a hack, and am fine with Tero's original 
patch.

I suppose I should resuscitate the uImage booter for the OMAP3 boards here 
at least.  I dropped those out of the testbed thinking that we'd switch 
over to DT-only fairly quickly; that turned out not to be the case.


- Paul
Mike Turquette Dec. 20, 2014, 12:23 a.m. UTC | #17
Quoting Paul Walmsley (2014-12-18 18:15:59)
> On Thu, 18 Dec 2014, Mike Turquette wrote:
> 
> > Quoting Paul Walmsley (2014-12-18 11:23:07)
> >
> > > Flipping over from hardware to software, in the Linux clock tree, there's 
> > > usually not much point to modeling the VCO/DCO directly because it tends 
> > > not to be under the direct control of the OS, and it is usually tightly 
> > > integrated into the PLLs from a hardware point of view.  But unlike most 
> > > of the Linux clock tree nodes that are downstream from clock sources, 
> > > which use clocks that are electrically driven by the clock source, the 
> > > clock signal that PLLs and PLL-like clocks generate is not directly driven 
> > > by the reference clock.
> > 
> > Hi Paul,
> 
> Hi Mike,
> 
> > This is debatable given that the formula to determine the OMAP DPLL 
> > output rate directly depends upon the rate of the input clock (osc, 
> > 32Khz, hsd, bypass, etc). I'm not speaking for all PLLs, just for the 
> > OMAP ones that I am familiar with.
> 
> The frequency and phase noise characteristics of the PLL's output signal 
> are partially a function of the reference clock.  But that's only because 
> the reference clock is used to steer the VCO.  It's not because the 
> reference clock itself appears on the PLL output.  Even if the reference 
> clock dividers and VCO loop dividers were both set to divide-by-one, the 
> reference clock still would not appear on the PLL output - merely a 
> simulacrum of it, originating by the VCO.  The PLL's output clock is, 
> electrically, directly driven by the VCO.
> 
> Page 5 of this PDF has a nice frequency synthesis PLL block diagram with 
> integer dividers:
> 
>     http://www.ti.com/lit/an/swra029/swra029.pdf
> 
> To rephrase, if, in the block diagram above, one were to remove everything 
> from the TCXO reference clock on the left to the triangle to the left of 
> the VCO, and to replace all that with a constant voltage input to the VCO, 
> you'd still get a clock signal out of the IP block, even though the 
> reference clock would no longer exist.

Yes, your point is completely valid. But TI's own clock tree diagrams
(which sadly do not make it into any TRM that I know of) show a cascade
starting at sys_clk, continuing through each DPLL, the Mx output and so
on and so forth. I would link it if it was public :-/

Samsung's Exynos TRMs do a great job of illustrating the clock tree
paths and my feedback to the TRM team at TI never seemed to take root.

In addition the clock tree tool from TI[0] follows the same trend. This
tool is developed by an independent team that has no relationship to the
folks working on SoC operating system software.

In short, the manufacturer's visualization of the clock signal chain
treats the system clock as a parent of the DPLLs.

> 
> > > So why is a reference clock listed as a Linux parent clock of an OMAP PLL?  
> > > At least for OMAP, it was sort of shoehorned in to represent a gating 
> > > dependency.  It was a way of stating that the reference clock had to be 
> > > enabled for the PLL to generate an output clock.  (The off-chip crystal 
> > > oscillator that drives most of the PLL reference clocks could be disabled 
> > > when all of its users were idle, to save energy.)  But this type of gating 
> > > dependency is equally true for, say, a separate functional clock that the 
> > > clock source requires in order to operate.  (OMAP PLLs didn't have a 
> > > separate functional clock, at least not that I was aware of; but that's 
> > > not true for some similar clock sources used in other SoCs.)
> > 
> > Using your terminology above, it is possible to do what you want to do
> > today without any change to the clock framework. Simply make each DPLL a
> > device. That device calls clk_get, clk_prepare_enable on the input
> > reference clock. 
> 
> I think I did something like that with the Tegra DFLL driver last year.  
> Except the clock provider device was the DFLL IP block itself, with its 
> own registers, etc., and not an additional abstraction, if I recall 
> correctly.

This sounds like what I had in mind, if I was not clear above.

> 
> My interest is mostly to determine whether some of that special-case code 
> can be converted into data that the CCF core can operate on, in a 
> consistent manner that would be useful across platforms, and in a way that 
> several people could potentially agree on.
> 
> > Coincidentally these new DPLL device are clock providers themselves and 
> > they provide root clocks of their own which are the DPLLs and 
> > corresponding Mx outputs. This model would treat the reference clock as 
> > something that drives the DPLL device's logic, but not as a part of the 
> > clock signal chain.
> > 
> > I don't personally agree with the idea that the reference clock is not a
> > parent of the DPLL,
> 
> I'd be interested to know how you would define a parent clock, if it 
> differs from the electrical "source clock" definition that I mentioned.

My less-rigorous definition is a clock signal which is fed into some
sink (in this case another clock generator IP) and has a tangential
relationship or effect on its output rate. In the event of more than one
active clock signal going into the IP block, then the current parent is
the one that has the most reasonable affect on the clock signal rate of
the downstream clock generator.

In short, the parent is the one that you think, "oh gee, that's the
parent clock" the first time that you look at the schematic.

> 
> The Linux clock tree is a software abstraction.  So one could define 
> "parent clock" however one wishes.  (That's not to say that all 
> definitions are equally useful...) 
> 
> One could state, for example, that a parent clock is any clock that has 
> some effect on the output of the child clock.  That would be one 
> definition which might be consistent with your comments.  The problem with 
> that is that it means that a clock can have multiple simultaneously-active 
> parents, which I'd naïvely think we'd want to avoid, if we could.

You're right to say that we're talking about a software abstraction. In
general we should model this abstraction after the hardware as much as
possible to keep debugging and our understanding of the platform sane.
Though there are limits to how closely we want to model the hardware
(please imagine a clever joke about "struct spinning_electron" here).

I'm happy to update the documentation with guidelines for how driver
writers should partition things to stay in line with their hardware once
we have that discussion and settle on some guidelines.

Understanding of the hardware varies wildly though, often due to poor or
zero documentation. And additionally I don't want to create any new
hoops for people to jump through if it brings no tangible gain to the
software (better debugability, decreased code size, better power
savings, more awesomer apis exposed to device drivers, etc).

Finally, I know I continue to argue the point, but I would not have any
problem merging changes to remove sys_clk as the parent of the DPLLs. I
guess I'm just feeling argumentative. If you and the TI folks feel like
that is the right way to go then by all means.

[0] http://www.ti.com/general/docs/wtbu/wtbudocumentcenter.tsp?templateId=6123&navigationId=12804

Regards,
Mike

> 
> I also have to admit that my bias is towards definitions with some kind of 
> relationship to the hardware, which helps avoid the "utter relativism" 
> problem that you mention below.
> 
> > but I don't oppose any change to the OMAP clock driver along those lines 
> > so long as it is done in a sane way. It seems there is never just one 
> > correct way to look at these things.
> 
> I'd say that to the extent that one could come up with concrete 
> definitions for terms like "parent clocks," it allows others to reason 
> about how the CCF should work, helps distinguish between data and code 
> changes that do and don't make sense, and helps others understand which 
> changes might be acceptable to maintainers.
> 
> > > The clock framework wasn't re-entrant back then, and we wanted to avoid 
> > > implementing re-entrancy because we were worried that it could turn into a 
> > > mess.  So we just wound up listing the reference clock as the PLL's Linux 
> > > parent clock.
> > > 
> > > My original comment was just intended to be a reflection on what it means 
> > > to be a "parent clock" in the Linux clock tree sense.  If it's intended to 
> > > represent "source clocks" as they are defined above, then PLLs and 
> > > PLL-like clocks should be root nodes, except for the few cases where it's 
> > > useful to add a node for the underlying source oscillator directly (for 
> > > example, if open-loop mode is supported).
> > > 
> > > This might be the right way forward for the time being, and I like the 
> > > idea of stating that Linux parent clocks should represent electrical 
> > > "source clock" relationships.  
> > > 
> > > That raises the question of what to do about the additional gating 
> > > relationships.  At the moment, the clock type code needs to be responsible 
> > > for calling clk_enable() etc. on all of the reference and functional 
> > > clocks that need to be ungated for the clock source to work.  But it has 
> > > always seemed preferable to me to represent fundamental hardware 
> > > structural constraints in data.  If the data structures are well-defined, 
> > > then the data should be relatively easy to analyze, reason about, 
> > > generate, validate, share across platforms, and operate upon iteratively; 
> > > unlike custom per-clocktype code, which often isn't.
> > 
> > I completely agree that the interfaces and abstractions in the clock
> > framework do not scale well. As an example, there could be much more
> > reuse if callbacks such as .get_best_div() existed and the large variety
> > of .round_rate() implementations could be replaced by a single generic
> > one.
> > 
> > Easier mixing and matching of callbacks would be great as well. We don't
> > quite have polymorphism but something better could be achieved than the
> > complex clock type. Namely the ability to combine various clock hardware
> > ops at run-time without having to always generate unique struct clk_ops
> > per platform.
> > 
> > I think there are lots of ideas out there on how to improve this stuff.
> 
> Oh, just in case it isn't clear, my objective wasn't to criticize the 
> existing CCF.  Just thinking that if it was possible to come to an 
> agreement on how to define some of these entities, it might make it easier 
> to reason together about ways to work on the core code and data 
> structures.  I'd hate to spend a bunch of time working on changes that you 
> would eventually nack because we might not agree on what a parent clock is 
> :-)
> 
> 
> - Paul
diff mbox

Patch

diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c
index 20e120d..c2da2a0 100644
--- a/arch/arm/mach-omap2/dpll3xxx.c
+++ b/arch/arm/mach-omap2/dpll3xxx.c
@@ -474,7 +474,7 @@  void omap3_noncore_dpll_disable(struct clk_hw *hw)
  */
 long omap3_noncore_dpll_determine_rate(struct clk_hw *hw, unsigned long rate,
 				       unsigned long *best_parent_rate,
-				       struct clk **best_parent_clk)
+				       struct clk_hw **best_parent_clk)
 {
 	struct clk_hw_omap *clk = to_clk_hw_omap(hw);
 	struct dpll_data *dd;
@@ -488,10 +488,10 @@  long omap3_noncore_dpll_determine_rate(struct clk_hw *hw, unsigned long rate,
 
 	if (__clk_get_rate(dd->clk_bypass) == rate &&
 	    (dd->modes & (1 << DPLL_LOW_POWER_BYPASS))) {
-		*best_parent_clk = dd->clk_bypass;
+		*best_parent_clk = __clk_get_hw(dd->clk_bypass);
 	} else {
 		rate = omap2_dpll_round_rate(hw, rate, best_parent_rate);
-		*best_parent_clk = dd->clk_ref;
+		*best_parent_clk = __clk_get_hw(dd->clk_ref);
 	}
 
 	*best_parent_rate = rate;
diff --git a/arch/arm/mach-omap2/dpll44xx.c b/arch/arm/mach-omap2/dpll44xx.c
index 535822f..0e58e5a 100644
--- a/arch/arm/mach-omap2/dpll44xx.c
+++ b/arch/arm/mach-omap2/dpll44xx.c
@@ -223,7 +223,7 @@  out:
  */
 long omap4_dpll_regm4xen_determine_rate(struct clk_hw *hw, unsigned long rate,
 					unsigned long *best_parent_rate,
-					struct clk **best_parent_clk)
+					struct clk_hw **best_parent_clk)
 {
 	struct clk_hw_omap *clk = to_clk_hw_omap(hw);
 	struct dpll_data *dd;
@@ -237,11 +237,11 @@  long omap4_dpll_regm4xen_determine_rate(struct clk_hw *hw, unsigned long rate,
 
 	if (__clk_get_rate(dd->clk_bypass) == rate &&
 	    (dd->modes & (1 << DPLL_LOW_POWER_BYPASS))) {
-		*best_parent_clk = dd->clk_bypass;
+		*best_parent_clk = __clk_get_hw(dd->clk_bypass);
 	} else {
 		rate = omap4_dpll_regm4xen_round_rate(hw, rate,
 						      best_parent_rate);
-		*best_parent_clk = dd->clk_ref;
+		*best_parent_clk = __clk_get_hw(dd->clk_ref);
 	}
 
 	*best_parent_rate = rate;