All of lore.kernel.org
 help / color / mirror / Atom feed
From: Lukasz Majewski <lukma@denx.de>
To: u-boot@lists.denx.de
Subject: [PATCH v2 01/11] clk: Always use the supplied struct clk
Date: Thu, 30 Jan 2020 01:29:13 +0100	[thread overview]
Message-ID: <20200130012913.62624ec0@jawa> (raw)
In-Reply-To: <f51bcc27-6bcf-f0a7-559d-995e6199cdf8@gmail.com>

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>

  reply	other threads:[~2020-01-30  0:29 UTC|newest]

Thread overview: 45+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-01-15 22:45 [PATCH v2 00/11] riscv: Add Sipeed Maix support Sean Anderson
2020-01-15 22:47 ` [PATCH v2 01/11] clk: Always use the supplied struct clk Sean Anderson
     [not found]   ` <752D002CFF5D0F4FA35C0100F1D73F3FA46C88BE@ATCPCS16.andestech.com>
2020-01-21  1:54     ` Rick Chen
2020-01-21  2:02       ` Sean Anderson
2020-01-21  2:23         ` Rick Chen
2020-01-21  3:18           ` Sean Anderson
2020-01-23  5:53             ` Sean Anderson
2020-01-24 14:27             ` Lukasz Majewski
2020-01-24 23:22               ` Sean Anderson
2020-01-25 20:18                 ` Lukasz Majewski
2020-01-26 21:20   ` Lukasz Majewski
2020-01-26 22:07     ` Sean Anderson
2020-01-27 23:40       ` Lukasz Majewski
2020-01-28 16:11         ` Sean Anderson
2020-01-30  0:29           ` Lukasz Majewski [this message]
2020-01-30  5:47             ` Sean Anderson
2020-01-31  9:18               ` Lukasz Majewski
2020-01-15 22:49 ` [PATCH v2 02/11] clk: Check that ops of composite clock components, exist before calling Sean Anderson
2020-01-26 21:25   ` Lukasz Majewski
2020-01-15 22:50 ` [PATCH v2 03/11] riscv: Add headers for asm/global_data.h Sean Anderson
     [not found]   ` <752D002CFF5D0F4FA35C0100F1D73F3FA46C88DF@ATCPCS16.andestech.com>
2020-01-21  2:07     ` Rick Chen
2020-01-21  2:17       ` Sean Anderson
2020-01-26 22:04   ` Lukas Auer
2020-01-26 22:12     ` Sean Anderson
2020-01-26 22:23       ` Lukas Auer
2020-01-15 22:51 ` [PATCH v2 04/11] riscv: Add an option to default to RV64I Sean Anderson
     [not found]   ` <752D002CFF5D0F4FA35C0100F1D73F3FA46C88FE@ATCPCS16.andestech.com>
2020-01-21  2:16     ` Rick Chen
2020-01-15 22:53 ` [PATCH v2 05/11] riscv: Add option to disable writes to mcounteren Sean Anderson
2020-01-26 22:09   ` Lukas Auer
2020-01-26 22:24     ` Sean Anderson
2020-01-30 22:13       ` Lukas Auer
2020-01-15 22:55 ` [PATCH v2 06/11] riscv: Fix incorrect cpu frequency on RV64 Sean Anderson
2020-01-26 22:04   ` Lukas Auer
2020-01-15 23:04 ` [PATCH v2 07/11] riscv: Add initial Sipeed Maix support Sean Anderson
2020-01-26 22:17   ` Lukas Auer
2020-01-27  1:09     ` Sean Anderson
2020-01-30 22:21       ` Lukas Auer
2020-02-02  6:06         ` Sean Anderson
2020-01-15 23:16 ` [PATCH v2 00/11] riscv: Add " Sean Anderson
2020-01-15 23:18   ` [PATCH v2 08/11] riscv: Add device tree for K210 Sean Anderson
     [not found]     ` <752D002CFF5D0F4FA35C0100F1D73F3FA46C8947@ATCPCS16.andestech.com>
2020-01-21  2:54       ` Rick Chen
2020-01-15 23:20 ` [PATCH v2 09/11] riscv: Add K210 sysctl support Sean Anderson
2020-01-15 23:24 ` [PATCH v2 10/11] riscv: Add K210 pll support Sean Anderson
2020-01-15 23:26 ` [PATCH v2 11/11] riscv: Add K210 clock support Sean Anderson
2020-01-21  3:46 ` [PATCH v2 08/11] riscv: Add device tree for K210 Sean Anderson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200130012913.62624ec0@jawa \
    --to=lukma@denx.de \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.