Hi Lukasz, On 1/29/20 7:29 PM, Lukasz Majewski wrote: >> 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.
Ok, so imagine I have a clk_divider in a composite clock. When clk_get_rate gets called on the composite clock, the composite clock then calls clk_divider_get_rate on the divider clock. The first thing that function does is call clk_get_parent_rate, which in turn calls clk_get_parent. This last call fails because the divider clock has a NULL ->dev. The end behaviour is that the parent rate looks like 0, which causes the divider to in turn return 0 as its rate. So while it doesn't throw a fit, we still end up with a bad result. >> - 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<------------ > Right, so at best doing dev_get_clk_ptr(clk->dev) in something like clk_divider_set_rate is a no-op, and at worst it breaks something. >> 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. They could, but none of them have compatible strings at the moment. >> , 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). Right, but clock implementations will never need to do this. Whatever clock they get passed is going to be the clock they should use. This is why I think the calls which I removed were unnecessary. In fact, through this discussion I think the patch as-submitted is probably the least-disruptive way to make composite clocks work in a useful way. The only thing it does is that sometimes clk->dev->priv != clk, but I don't think that anyone was relying on this being the case. >>> - 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? Well, the CCF doesn't use xlate or register, so this field is unused at the moment. > >> 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; > } What would use that predicate? > I'm just wondering if "normal" clocks shall set this clk->get_parent > pointer or continue to use clk->dev->parent? Hm, well after thinking it over, I think with the current system having a method for this would not do anything useful, since you still need to get the ops from the udevice (and then you could just use the default behaviour). If I could make big sweeping changes clock uclass, I would do something like: - Split off of_xlate, request, and free into a new clk_device_ops struct, with an optional pointer to clk_ops - Create a new struct clk_handle containing id, data, a pointer to struct udevice, and a pointer to struct clk - Add get_parent to clk_ops and change all ops to work on struct clk_handle - Add a pointer to clk_ops in struct clk, and remove dev, id, and data. So for users, the api would look like struct clk_handle clk = clk_get_by_index(dev, 0, &clk); clk_enable(&clk); ulong rate = clk_get_rate(&clk); Method calls would roughly look like ulong clk_get_rate(struct clk_handle *h) { struct clk_ops *ops; if (h->clk) ops = h->clk->ops; else ops = clk_dev_ops(h->dev)->ops; return ops->get_rate(h); } Getting the parent would use h->clk->ops->get_parent if it exists, and otherwise use h->dev to figure it out. For non-CCF drivers, the implementation could look something like ulong foo_get_rate(struct clk_handle *h) { /* Do something with h->id and h->dev */ } struct foo_clk_ops = { .get_rate = foo_get_rate, }; struct foo_clk_driver_ops = { .ops = &foo_clk_ops, }; For drivers using the CCF, the implementation could look like struct clk_gate *foo_gate; int foo_probe(struct udevice *dev) { foo_gate = /* ... */; } int foo_request(struct clk_handle *h) { h->clk = foo_gate->clk; } struct foo_clk_driver_ops = { .request = foo_request, }; So why these changes? - Clear separation between the different duties which are both currently handled by struct clk - Simplification for drivers using the CCF - Minimal changes for existing users - Clock consumers have almost the same api - Every clock driver will need to be changed, but most drivers which don't use CCF never use any fields in clk other than ->dev and ->id - No need to get the "canonical" clock, since it is pointed at by clk_handle->clk - Reduction in memory/driver usage since CCF clocks no longer need a udevice for each clock - Less function calls since each driver using CCF no longer needs to be a proxy for clock ops Now these are big changes, and definitely would be the subject of their own patch series. As-is, I think the patch as it exists now is the best way to get the most functionality from clk_composite with the least changes to other code. --Sean