[PATCH v2 01/11] clk: Always use the supplied struct clk
Lukasz Majewski
lukma at denx.de
Thu Jan 30 01:29:13 CET 2020
Hi Sean,
> On 1/27/20 6:40 PM, Lukasz Majewski wrote:
> >> The real problem with the current approach (IMO) is that there is a
> >> mismatch between the clock structure and the clock function. If one
> >> calls clk_get_rate on some clock, the get_rate function is chosen
> >> based on clk->dev->ops.
> >
> > Yes, exactly. This seems logical to me -> the "top" structure is
> > struct clk, which is a device with proper ops.
> > (And in U-Boot the 'central' data structure with DM is struct
> > udevice).
> >> If that clock is a composite clock, the
> >> clk_composite_get_rate
> >
> > I've found only clk_composite_set_rate @ drivers/clk/clk-composite.c
> >
> > But, yes it calls its own clk_ops (*mux_ops, *rate_ops, *gate_ops).
> >
> >> will then choose the *real* get_rate function
> >> to call, and will call it with the appropriate component clock.
> >
> > Yes, the struct clk_composite has several clocks defined.
> >
> >> But
> >> then, the get_rate function says "Aha, I know better than you what
> >> clock should be passed to me" and calls itself with the composite
> >> clock struct instead!
> >
> > Wouldn't clk_get_rate just return 0 when it discovers that clk->dev
> > is NULL for not bound driver (the clk which builds a composite
> > driver)?
>
> Yes, but then clk_get_parent throws a fit, which gets called by
Could you explain what "throw a fit" means here? I'm a bit confused.
> clk_gate_*, clk_fixed_divider_*, clk_mux_*, etc. So this description
> is really for the case where only the first section of this patch is
> applied.
>
> >> This is really unintitive behaviour. If
> >> anything, this kind of behaviour should be moved up to
> >> clk_get_rate, where it can't cause any harm in composite clocks.
> >
> > Even better, the composite clocks shall be handled in the same way
> > as non composite ones.
> >
> >
> > To achieve that:
> >
> > 1. The struct clk shall be passed to all clk functions (IIRC this is
> > now true in U-Boot):
> > - then clk IP block specific structure (e.g. struct
> > clk_gate2) are accessible via container_of on clk pointer
>
> Ok, so I'm a bit confused about the design decisions here. It seems to
> me that there are two uses for struct clk:
> - struct clk as used by drivers not using the CCF. Here, the
> structure is effectively an extended parameter list,
> containing all the data needed to operate on some clock.
> clk->dev->priv contains whatever the driver wants, and
> doesn't necessarily have a struct clk. Because these clocks are mostly
> just parameters, they can be created with xlate and request;
> there is no one "canonical" struct clk for any given logical
> clock. These clocks can appear on a device tree, and be
> acquired by clk_get_by_*.
Yes.
> - struct clk as used by CCF clocks. Here the structure
> contains specific information configuring each clock. Each struct clk
> refers to a different logical clock. clk->dev->priv
> contains a struct clk (though this may not be the same struct clk).
The struct clk pointer is now stored in the struct's udevice
uclass_priv pointer.
For CCF it looks like below:
struct clk_gate2 -> struct clk -> struct udevice *dev -> struct udevice
/|\ |
| |
-------------uclass_priv<------------
> These clocks cannot appear in a device tree
I think they could, but I've followed the approach of Linux CCF in e.g.
i.MX6Q SoC.
>, and hence cannot be
> acquired by clk_get_by_* (except for clk_get_by_id which
> doesn't use the device tree). These clocks are not created
> by xlate and request.
Correct. Those clocks are instantiated in SoC specific file. For
example in ./drivers/clk/imx/clk-imx6q.c
> With this in mind, I'm not sure why one would ever need to call
> dev_get_clk_ptr. In the first case, clk->dev->priv could be anything,
> and probably not a clock. In the second case, one already has the
> "canonical" struct clk.
The problem is that clocks are linked together with struct udevice
(_NOT_ struct clk). All clocks are linked together and have the same
uclass - UCLASS_CLK.
To access clock - one needs to search this doubly linked list and you
get struct udevice from it.
(for example in ./cmd/clk.c)
And then you need a "back pointer" to struct clk to use clock
ops/functions. And this back pointer is stored in struct udevice's
uclass_priv pointer (accessed via dev_get_clk_ptr).
>
> > - There shall be clk->dev filled always. In the dev one
> > shall use dev->ops to do the necessary work (even for composite
> > clocks components)
>
> Do you mean having a struct device for every clock, even components
> of a composite clock? I think this is unnecessary, especially for a
> system with lots of composite clocks. Storing the clock ops in the
> composite clock's struct works fine, and is conceptually simple.
I agree. We shall avoid creating/instantiating unnecessary udevices.
>
> >
> > - The struct clk has flags field (clk->flags). New flags:
> > -- CCF_CLK_COMPOSITE_REGISTERED (visible with dm
> > tree) -- CCF_CLK_COMPOSITE_HIDDEN (used internally to
> > gate, mux, etc. the composite clock)
> >
> >
> > -- clk->dev->flags with CCF_CLK_COMPOSITE_REGISTERED
> > set puts all "servant" clocks to its child_head list
> > (clk->dev->child_head).
> >
> > __OR__
> >
> > -- we extend the ccf core to use struct uc_clk_priv
> > (as described:
> > https://gitlab.denx.de/u-boot/u-boot/blob/master/doc/imx/clk/ccf.txt#L40)
> > which would have
> >
> > struct uc_clk_priv {
> > struct clk *c; /* back pointer to clk */
> >
> > struct clk_composite *cc;
> > };
> >
> > struct clk_composite {
> > struct clk *mux;
> > struct clk *gate;
> > ...
> > (no ops here - they shall be in struct
> > udevice) };
> >
> > The overhead is to have extra 4 bytes (or use union
> > and check CCF_CLK_COMPOSITE flags).
> >
> >
> > For me the more natural seems the approach with using
> > clk->dev->child_head (maybe with some extra new flags defined).
> > U-Boot handles lists pretty well and maybe OF_PLATDATA could be
> > used as well.
>
> I like the private data approach, but couldn't we use the existing
> clk->data field? E.g. instead of having
>
> struct clk_foo {
> struct clk clk;
This is the approach took from the Linux kernel. This is somewhat
similar to having the struct clk_hw:
https://elixir.bootlin.com/linux/latest/source/drivers/clk/imx/clk-gate2.c#L27
> /* ... */
> };
>
> clk_register_foo(...)
> {
> struct clk_foo *foo;
> struct clk *clk;
>
> foo = kzalloc(sizeof(*foo));
> /* ... */
>
> clk = foo->clk;
> clk_register(...);
> }
>
> int clk_foo_get_rate(struct clk *clk)
> {
> struct clk_foo *foo = to_clk_foo(clk);
> /* ... */
> }
>
> we do
>
> struct clk_foo {
> /* ... */
> };
>
> clk_register_foo(...)
> {
> struct clk_foo *foo;
> struct clk *clk;
>
> foo = kzalloc(sizeof(*foo));
> clk = kzalloc(sizeof(*clk));
> /* ... */
>
> clk->data = foo;
According to the description of struct clk definition (@
./include/clk.h) the data field has other purposes.
Maybe we shall add a new member of struct clk?
> clk_register(...);
> }
>
> int clk_foo_get_rate(struct clk *clk)
> {
> struct clk_foo *foo = (struct clk_foo *)clk->data;
> /* ... */
> }
>
> Of course, now that I have written this all out, it really feels like
> the container_of approach all over again...
Indeed. Even the access cost is the same as the struct clk is always
placed as the first element of e.g. struct clk_gate2
>
> I think the best way of approaching this may be to simply introduce a
> get_parent op. CCF already does something like this with
> clk_mux_get_parent. This would also allow for some clocks to have a
> NULL ->dev.
I've thought about this some time ago and wondered if struct clk
shouldn't be extended a bit.
Maybe adding there a pointer to "get_parent" would simplify the overall
design of CCF?
Then one could set this callback pointer in e.g. clk_register_gate2 (or
clk_register_composite) and set clk->dev to NULL to indicate
"composite" clock?
So we would have:
static inline bool is_composite_clk(struct clk *clk)
{
return !clk->dev && clk->flags == CCF_CLK_COMPOSITE;
}
I'm just wondering if "normal" clocks shall set this clk->get_parent
pointer or continue to use clk->dev->parent?
>
> --Sean
Best regards,
Lukasz Majewski
--
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma at denx.de
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 488 bytes
Desc: OpenPGP digital signature
URL: <https://lists.denx.de/pipermail/u-boot/attachments/20200130/0431a6cb/attachment.sig>
More information about the U-Boot
mailing list