Hi Lukasz > From: Lukasz Majewski [mailto:lu...@denx.de] > Sent: Friday, February 07, 2020 5:22 AM > To: Sean Anderson > Cc: U-Boot Mailing List; Rick Jian-Zhi Chen(陳建志); Lukas Auer > Subject: Re: [PATCH v3 01/12] clk: Always use the supplied struct clk > > Hi Sean, > > > CCF clocks should always use the struct clock passed to their methods > > for extracting the driver-specific clock information struct. > > Previously, many functions would use the clk->dev->priv if the device > > was bound. This could cause problems with composite clocks. The > > individual clocks in a composite clock did not have the ->dev field > > filled in. This was fine, because the device-specific clock > > information would be used. However, since there was no ->dev, there > > was no way to get the parent clock. This caused the recalc_rate method > > of the CCF divider clock to fail. One option would be to use the > > clk->priv field to get the composite clock and from there get the > > appropriate parent device. However, this would tie the implementation > > to the composite clock. In general, different devices should not rely > > on the contents of ->priv from another device. > > > > The simple solution to this problem is to just always use the supplied > > struct clock. The composite clock now fills in the ->dev pointer of > > its child clocks. This allows child clocks to make calls like > > clk_get_parent() without issue. > > > > imx avoided the above problem by using a custom get_rate function with > > composite clocks. > > > > Signed-off-by: Sean Anderson <sean...@gmail.com> > > Thank you Sean for your CCF enhancement and updating the ccf.txt > documentation entry. > > Acked-by: Lukasz Majewski <lu...@denx.de> > > I don't mind if RISC-V SoC maintainer pulls the whole series (including CCF > patches).
OK Thanks for your review. Regards, Rick > > > --- > > Changes for v3: > > - Documented new assumptions in the CCF > > - Wrapped docs to 80 columns > > > > doc/imx/clk/ccf.txt | 63 > > +++++++++++++++++----------------- drivers/clk/clk-composite.c | > > 8 +++++ drivers/clk/clk-divider.c | 6 ++-- > > drivers/clk/clk-fixed-factor.c | 3 +- > > drivers/clk/clk-gate.c | 6 ++-- > > drivers/clk/clk-mux.c | 12 +++---- > > drivers/clk/imx/clk-gate2.c | 4 +-- > > 7 files changed, 51 insertions(+), 51 deletions(-) > > > > diff --git a/doc/imx/clk/ccf.txt b/doc/imx/clk/ccf.txt index > > 36b60dc438..e40ac360e8 100644 > > --- a/doc/imx/clk/ccf.txt > > +++ b/doc/imx/clk/ccf.txt > > @@ -1,42 +1,37 @@ > > Introduction: > > ============= > > > > -This documentation entry describes the Common Clock Framework [CCF] > > -port from Linux kernel (v5.1.12) to U-Boot. > > +This documentation entry describes the Common Clock Framework [CCF] > > port from +Linux kernel (v5.1.12) to U-Boot. > > > > -This code is supposed to bring CCF to IMX based devices (imx6q, imx7 > > -imx8). Moreover, it also provides some common clock code, which would > > -allow easy porting of CCF Linux code to other platforms. > > +This code is supposed to bring CCF to IMX based devices (imx6q, imx7 > > imx8). +Moreover, it also provides some common clock code, which would > > allow easy +porting of CCF Linux code to other platforms. > > > > Design decisions: > > ================= > > > > -* U-Boot's driver model [DM] for clk differs from Linux CCF. The most > > - notably difference is the lack of support for hierarchical clocks > > and > > - "clock as a manager driver" (single clock DTS node acts as a > > starting > > - point for all other clocks). > > +* U-Boot's driver model [DM] for clk differs from Linux CCF. The > > most notably > > + difference is the lack of support for hierarchical clocks and > > "clock as a > > + manager driver" (single clock DTS node acts as a starting point > > for all other > > + clocks). > > > > -* The clk_get_rate() caches the previously read data if > > CLK_GET_RATE_NOCACHE > > - is not set (no need for recursive access). > > +* The clk_get_rate() caches the previously read data if > > CLK_GET_RATE_NOCACHE is > > + not set (no need for recursive access). > > > > -* On purpose the "manager" clk driver (clk-imx6q.c) is not using > > large > > - table to store pointers to clocks - e.g. > > clk[IMX6QDL_CLK_USDHC2_SEL] = .... > > - Instead we use udevice's linked list for the same class > > (UCLASS_CLK). +* On purpose the "manager" clk driver (clk-imx6q.c) is > > not using large table to > > + store pointers to clocks - e.g. clk[IMX6QDL_CLK_USDHC2_SEL] = .... > > Instead we > > + use udevice's linked list for the same class (UCLASS_CLK). > > > > Rationale: > > ---------- > > - When porting the code as is from Linux, one would need ~1KiB of > > RAM to > > - store it. This is way too much if we do plan to use this driver > > in SPL. > > + When porting the code as is from Linux, one would need ~1KiB of > > RAM to store > > + it. This is way too much if we do plan to use this driver in SPL. > > > > * The "central" structure of this patch series is struct udevice and > > its uclass_priv field contains the struct clk pointer (to the > > originally created one). > > > > -* Up till now U-Boot's driver model (DM) CLK operates on udevice > > (main > > - access to clock is by udevice ops) > > - In the CCF the access to struct clk (embodying pointer to *dev) is > > - possible via dev_get_clk_ptr() (it is a wrapper on > > dev_get_uclass_priv()). - > > * To keep things simple the struct udevice's uclass_priv pointer is > > used to store back pointer to corresponding struct clk. However, it is > > possible to modify clk-uclass.c file and add there struct uc_clk_priv, > > which would have @@ -45,13 +40,17 @@ Design decisions: > > setting .per_device_auto_alloc_size = sizeof(struct uc_clk_priv)) > > the uclass_priv stores the pointer to struct clk. > > > > +* Non-CCF clocks do not have a pointer to a clock in clk->dev->priv. > > In the case > > + of composite clocks, clk->dev->priv may not match clk. Drivers > > should always > > + use the struct clk which is passed to them, and not clk->dev->priv. > > + > > * It is advised to add common clock code (like already added rate and > > flags) to the struct clk, which is a top level description of the > > clock. > > * U-Boot's driver model already provides the facility to > > automatically allocate > > - (via private_alloc_size) device private data (accessible via > > dev->priv). > > - It may look appealing to use this feature to allocate private > > structures for > > - CCF clk devices e.g. divider (struct clk_divider *divider) for > > IMX6Q clock. > > + (via private_alloc_size) device private data (accessible via > > dev->priv). It > > + may look appealing to use this feature to allocate private > > structures for CCF > > + clk devices e.g. divider (struct clk_divider *divider) for IMX6Q > > clock. > > The above feature had not been used for following reasons: > > - The original CCF Linux kernel driver is the "manager" for clocks > > - it @@ -64,21 +63,23 @@ Design decisions: > > > > * I've added the clk_get_parent(), which reads parent's > > dev->uclass_priv to provide parent's struct clk pointer. This seems > > the easiest way to get > > - child/parent relationship for struct clk in U-Boot's udevice based > > clocks. > > + child/parent relationship for struct clk in U-Boot's udevice based > > clocks. In > > + the future arbitrary parents may be supported by adding a > > get_parent function > > + to clk_ops. > > > > * Linux's CCF 'struct clk_core' corresponds to U-Boot's udevice in > > 'struct clk'. Clock IP block agnostic flags from 'struct clk_core' > > (e.g. NOCACHE) have been > > - moved from this struct one level up to 'struct clk'. > > + moved from this struct one level up to 'struct clk'. Many flags are > > + unimplemented at the moment. > > > > * For tests the new ./test/dm/clk_ccf.c and > > ./drivers/clk/clk_sandbox_ccf.c files have been introduced. The latter > > setups the CCF clock structure for > > - sandbox by reusing, if possible, generic clock primitives - like > > divier > > - and mux. The former file provides code to tests this setup. > > + sandbox by reusing, if possible, generic clock primitives - like > > divier and > > + mux. The former file provides code to tests this setup. > > > > For sandbox new CONFIG_SANDBOX_CLK_CCF Kconfig define has been > > introduced. > > - All new primitives added for new architectures must have > > corresponding test > > - in the two aforementioned files. > > - > > + All new primitives added for new architectures must have > > corresponding test in > > + the two aforementioned files. > > > > Testing (sandbox): > > ================== > > diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c > > index a5626c33d1..d0f273d47f 100644 > > --- a/drivers/clk/clk-composite.c > > +++ b/drivers/clk/clk-composite.c > > @@ -145,6 +145,14 @@ struct clk *clk_register_composite(struct device > > *dev, const char *name, goto err; > > } > > > > + if (composite->mux) > > + composite->mux->dev = clk->dev; > > + if (composite->rate) > > + composite->rate->dev = clk->dev; > > + if (composite->gate) > > + composite->gate->dev = clk->dev; > > + > > + > > return clk; > > > > err: > > diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c > > index 822e09b084..bfa05f24a3 100644 > > --- a/drivers/clk/clk-divider.c > > +++ b/drivers/clk/clk-divider.c > > @@ -70,8 +70,7 @@ unsigned long divider_recalc_rate(struct clk *hw, > > unsigned long parent_rate, static ulong > > clk_divider_recalc_rate(struct clk *clk) { > > - struct clk_divider *divider = > > to_clk_divider(clk_dev_binded(clk) ? > > - dev_get_clk_ptr(clk->dev) : clk); > > + struct clk_divider *divider = to_clk_divider(clk); > > unsigned long parent_rate = clk_get_parent_rate(clk); > > unsigned int val; > > > > @@ -150,8 +149,7 @@ int divider_get_val(unsigned long rate, unsigned > > long parent_rate, static ulong clk_divider_set_rate(struct clk *clk, > > unsigned long > > rate) { > > - struct clk_divider *divider = > > to_clk_divider(clk_dev_binded(clk) ? > > - dev_get_clk_ptr(clk->dev) : clk); > > + struct clk_divider *divider = to_clk_divider(clk); > > unsigned long parent_rate = clk_get_parent_rate(clk); > > int value; > > u32 val; > > diff --git a/drivers/clk/clk-fixed-factor.c > > b/drivers/clk/clk-fixed-factor.c index 711b0588bc..d2401cf440 100644 > > --- a/drivers/clk/clk-fixed-factor.c > > +++ b/drivers/clk/clk-fixed-factor.c > > @@ -18,8 +18,7 @@ > > > > static ulong clk_factor_recalc_rate(struct clk *clk) { > > - struct clk_fixed_factor *fix = > > - to_clk_fixed_factor(dev_get_clk_ptr(clk->dev)); > > + struct clk_fixed_factor *fix = to_clk_fixed_factor(clk); > > unsigned long parent_rate = clk_get_parent_rate(clk); > > unsigned long long int rate; > > > > diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c index > > 70b8794554..b2933bc24a 100644 > > --- a/drivers/clk/clk-gate.c > > +++ b/drivers/clk/clk-gate.c > > @@ -43,8 +43,7 @@ > > */ > > static void clk_gate_endisable(struct clk *clk, int enable) { > > - struct clk_gate *gate = to_clk_gate(clk_dev_binded(clk) ? > > - dev_get_clk_ptr(clk->dev) : clk); > > + struct clk_gate *gate = to_clk_gate(clk); > > int set = gate->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0; > > u32 reg; > > > > @@ -86,8 +85,7 @@ static int clk_gate_disable(struct clk *clk) > > > > int clk_gate_is_enabled(struct clk *clk) { > > - struct clk_gate *gate = to_clk_gate(clk_dev_binded(clk) ? > > - dev_get_clk_ptr(clk->dev) : clk); > > + struct clk_gate *gate = to_clk_gate(clk); > > u32 reg; > > > > #if CONFIG_IS_ENABLED(SANDBOX_CLK_CCF) > > diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c index > > 5acc0b8cbd..67b4afef28 100644 > > --- a/drivers/clk/clk-mux.c > > +++ b/drivers/clk/clk-mux.c > > @@ -35,8 +35,7 @@ > > int clk_mux_val_to_index(struct clk *clk, u32 *table, unsigned int > > flags, unsigned int val) { > > - struct clk_mux *mux = to_clk_mux(clk_dev_binded(clk) ? > > - dev_get_clk_ptr(clk->dev) : clk); > > + struct clk_mux *mux = to_clk_mux(clk); > > int num_parents = mux->num_parents; > > > > if (table) { > > @@ -79,8 +78,7 @@ unsigned int clk_mux_index_to_val(u32 *table, > > unsigned int flags, u8 index) > > u8 clk_mux_get_parent(struct clk *clk) { > > - struct clk_mux *mux = to_clk_mux(clk_dev_binded(clk) ? > > - dev_get_clk_ptr(clk->dev) : clk); > > + struct clk_mux *mux = to_clk_mux(clk); > > u32 val; > > > > #if CONFIG_IS_ENABLED(SANDBOX_CLK_CCF) > > @@ -97,8 +95,7 @@ u8 clk_mux_get_parent(struct clk *clk) static int > > clk_fetch_parent_index(struct clk *clk, > > struct clk *parent) > > { > > - struct clk_mux *mux = to_clk_mux(clk_dev_binded(clk) ? > > - dev_get_clk_ptr(clk->dev) : clk); > > + struct clk_mux *mux = to_clk_mux(clk); > > > > int i; > > > > @@ -115,8 +112,7 @@ static int clk_fetch_parent_index(struct clk *clk, > > > > static int clk_mux_set_parent(struct clk *clk, struct clk *parent) { > > - struct clk_mux *mux = to_clk_mux(clk_dev_binded(clk) ? > > - dev_get_clk_ptr(clk->dev) : clk); > > + struct clk_mux *mux = to_clk_mux(clk); > > int index; > > u32 val; > > u32 reg; > > diff --git a/drivers/clk/imx/clk-gate2.c b/drivers/clk/imx/clk-gate2.c > > index 1b9db6e791..e32c0cb53e 100644 > > --- a/drivers/clk/imx/clk-gate2.c > > +++ b/drivers/clk/imx/clk-gate2.c > > @@ -37,7 +37,7 @@ struct clk_gate2 { > > > > static int clk_gate2_enable(struct clk *clk) { > > - struct clk_gate2 *gate = > > to_clk_gate2(dev_get_clk_ptr(clk->dev)); > > + struct clk_gate2 *gate = to_clk_gate2(clk); > > u32 reg; > > > > reg = readl(gate->reg); > > @@ -50,7 +50,7 @@ static int clk_gate2_enable(struct clk *clk) > > > > static int clk_gate2_disable(struct clk *clk) { > > - struct clk_gate2 *gate = > > to_clk_gate2(dev_get_clk_ptr(clk->dev)); > > + struct clk_gate2 *gate = to_clk_gate2(clk); > > u32 reg; > > > > reg = readl(gate->reg); > > > > > 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: lu...@denx.de > CONFIDENTIALITY NOTICE: > > This e-mail (and its attachments) may contain confidential and legally > privileged information or information protected from disclosure. If you are > not the intended recipient, you are hereby notified that any disclosure, > copying, distribution, or use of the information contained herein is strictly > prohibited. In this case, please immediately notify the sender by return > e-mail, delete the message (and any accompanying documents) and destroy all > printed hard copies. Thank you for your cooperation. > > Copyright ANDES TECHNOLOGY CORPORATION - All Rights Reserved.