[U-Boot] [PATCH v1 2/7] clk: at91: Improve the clock implementation

Wenyou.Yang at microchip.com Wenyou.Yang at microchip.com
Sun Sep 18 08:58:03 CEST 2016


Hi Stephen, 

Thank you for your review, and detailed comments.

The version 2 has been sent out, please give your advices.

> -----Original Message-----
> From: Stephen Warren [mailto:swarren at wwwdotorg.org]
> Sent: 2016年9月14日 3:34
> To: Wenyou Yang - A41535 <Wenyou.Yang at microchip.com>
> Cc: U-Boot Mailing List <u-boot at lists.denx.de>; Stephen Warren
> <swarren at nvidia.com>
> Subject: Re: [U-Boot] [PATCH v1 2/7] clk: at91: Improve the clock implementation
> 
> On 09/12/2016 07:54 PM, Wenyou Yang wrote:
> > For the peripheral clock, provide the clock ops for the clock
> > provider, such as spi0_clk. The .of_xlate is to get the clk->id, the
> > .enable is to enable the spi0 peripheral clock, the .get_rate is to
> > get the clock frequency.
> >
> > The driver for periph32ck node is responsible for recursively binding
> > its children as clk devices, not provide the clock ops.
> >
> > So do the generated clock and system clock.
> 
> > diff --git a/drivers/clk/at91/clk-generated.c
> > b/drivers/clk/at91/clk-generated.c
> 
> > +/**
> > + * generated_clk_bind() - for the generated clock driver
> > + * Recursively bind its children as clk devices.
> > + *
> > + * @return: 0 on success, or negative error code on failure  */
> > +static int generated_clk_bind(struct udevice *dev)
> ... (code to enumerate/instantiate all child DT nodes)
> > +}
> > +
> > +static const struct udevice_id generated_clk_match[] = {
> > +	{ .compatible = "atmel,sama5d2-clk-generated" },
> > +	{}
> > +};
> > +
> > +U_BOOT_DRIVER(generated_clk) = {
> > +	.name = "generated-clk",
> > +	.id = UCLASS_CLK,
> > +	.of_match = generated_clk_match,
> > +	.bind = generated_clk_bind,
> > +};
> 
> This driver shouldn't be UCLASS_CLK, and can't be without any clock ops
> implemented. It appears to be for another DT node that solely exists to house
> various sub-nodes which are the actual clock providers. I believe you should
> make this UCLASS_MISC. I guess you need to keep the custom bind function,
> since all the child nodes that it enumerates explicitly don't have a compatible value,
> so you can't rely on e.g. the default UCLASS_SIMPLE_BUS bind function to
> enumerate them.
> 
> BTW, while reading ./arch/arm/dts/sama5d2.dtsi, I noticed:
> 
> sdmmc0_gclk: sdmmc0_gclk {
> 	#clock-cells = <0>;
> 	reg = <31>;
> };
> 
> Doesn't dtc complain about that? The node has a reg property, yet there is no unit
> address in the node name to match it. Instead, that node should be:

Yes, there are dtc complains like this,

"Warning (unit_address_vs_reg): Node /ahb/apb/pmc at f0014000/periph64ck/sdmmc0_hclk has a reg or ranges property, but no unit name"

I will send a patches to fix this warning.

Others are accepted too.

> 
> sdmmc0_gclk: sdmmc0_gclk at 31 {
> 	#clock-cells = <0>;
> 	reg = <31>;
> };
> 
> > +static int generic_clk_of_xlate(struct clk *clk,
> > +			       struct fdtdec_phandle_args *args)
> >  {
> > -	struct pmc_platdata *plat = dev_get_platdata(clk->dev);
> > +	int periph;
> 
> The following should likely be added here:
> 
>          if (args->args_count) {
>                  debug("Invaild args_count: %d\n", args->args_count);
>                  return -EINVAL;
>          }
> 
> > +	periph = fdtdec_get_uint(gd->fdt_blob, clk->dev->of_offset, "reg", -1);
> > +	if (periph < 0)
> > +		return -EINVAL;
> > +
> > +	clk->id = periph;
> 
> I guess that's OK. of_xlate is really intended to parse/process the clocks property
> in the client DT node. However, I suppose parsing the referenced DT node is
> probably OK too. Has this Atmel clock binding, and a similar clock driver
> implementation (including custom of_xlate) been reviewed for inclusion in the
> Linux kernel? I'd be curious if the same technique was/wasn't allowed there.
> 
> > +static int generic_clk_probe(struct udevice *dev)
> ...
> > +	dev = dev_get_parent(dev);
> > +	dev = dev_get_parent(dev);
> 
> That line is duplicated.
> 
> > diff --git a/drivers/clk/at91/clk-peripheral.c
> > b/drivers/clk/at91/clk-peripheral.c
> 
> The same comments as above all apply to this file too.
> 
> > +static ulong periph_get_rate(struct clk *clk)
> >  {
> > +	struct udevice *dev;
> > +	struct clk clk_dev;
> > +	int ret;
> >
> > +	dev = dev_get_parent(clk->dev);
> > +	ret = clk_request(dev, &clk_dev);
> 
> You haven't filled in clk_dev.id here. That needs to be filled in before calling
> clk_request().
> 
> > +	if (ret)
> > +		return ret;
> > +
> > +	ret = clk_get_by_index(dev, 0, &clk_dev);
> 
> This over-writes everything in clk_dev, thus making the call to
> clk_request() above pointless.
> 
> > +	if (ret)
> > +		return ret;
> > +
> > +	return clk_get_rate(&clk_dev);
> 
> You need to call clk_free(&clk_dev) before returning. This comment applies to
> generated_clk_get_rate()/generic_clk_get_rate() too (in the previous file),
> although that problem existed before this patch.
> 
> > +static int periph_clk_probe(struct udevice *dev) {
> > +	struct periph_clk_platdata *plat = dev_get_platdata(dev);
> > +
> > +	dev = dev_get_parent(dev);
> > +	dev = dev_get_parent(dev);
> > +	plat->reg_base = (struct at91_pmc *)dev_get_addr_ptr(dev);
> 
> It would be helpful documentation-wise to use separate variables for those parents;
> make the variable name indicate what the parent is expected to be:
> 
> dev_periph_container = dev_get_parent(dev); dev_pmc =
> dev_get_parent(dev_periph_container);
> 
> > diff --git a/drivers/clk/at91/clk-system.c
> > b/drivers/clk/at91/clk-system.c
> 
> Likewise, all the same comments above apply to this file too.
> 
> > +/**
> > + * at91_system_clk_bind() - for the system clock driver
> > + * Recursively bind its children as clk devices.
> > + *
> > + * @return: 0 on success, or negative error code on failure  */
> > +static int at91_system_clk_bind(struct udevice *dev) {
> ...
> > +		/*
> > +		 * If this node has "compatible" property, this is not
> > +		 * a pin configuration node, but a normal device. skip.
> > +		 */
> 
> This is nothing to do with pin configuration, but clocks.
> 
> This function is duplicated at least 3 times in this patch. It might be useful to
> implement it in some common location, and just call it from all the different clock
> drivers. You'd need to pass in a string for the driver name to bind to, but that's the
> only difference I see.
> 
> I wouldn't be surprised if other parts of the Atmel clock drivers could be shared too;
> of_xlate is probably common, and perhaps get_rate for some clocks that are
> derived from parent clocks. Still, cleaning that up might be a job for a separate
> series.


Best Regards,
Wenyou Yang


More information about the U-Boot mailing list