[U-Boot] [PATCH v1 2/2] clk: at91: Add .ops callback for clk_generic

Stephen Warren swarren at wwwdotorg.org
Fri Sep 2 19:37:58 CEST 2016


On 09/01/2016 07:46 PM, Wenyou.Yang at microchip.com wrote:
> Hi Stephen,
>
>>> Subject: [PATCH v1 2/2] clk: at91: Add .ops callback for clk_generic
>>>
>>> To avoid the wild pointer as NULL->of_xlate, add an empty .ops
>>> callback for the clk_generic driver.
>>
>> This shouldn't be needed. If this driver isn't a clock provider, and it cannot be a
>> clock provider without implementing and clock ops, then nothing should be calling
>> of_xlate through its ops pointer, and the driver shouldn't be a UCLASS_CLK.
>
> The Atmel clock tree structure has some difference, take the following spi0 node as an example.
> The 'spi0' node use the 'clocks' phandle to refer to the 'spi0_clk' node to enable its clock.
>
> The 'spi0_clk' doesn't provide .ops->enable(), only its peripheral ID via 'reg' property.
> It uses its parent node (i.e. periph32ck) .ops->enable(), shared with other sibling nodes.
>
> These nodes as 'spi0_clk' don't have .compatible, which is bound with the 'clk_generic' driver.
> If not provide .ops for the 'clk_generic' driver, it will produce the wild pointer as NULL->of_xlate
> when call clk_get_by_index() in the spi driver.

The way clocks are looked in in DT currently requires that:

1) The phandle in the clocks property is parsed. That is the node ID of 
&spi0_clk is found.

2) All devices of UCLASS_CLK are search to find the device with 
.of_offset that matches the phandle parsed in (1) above.

3) That device's driver's uclass ops of_xlate is called to translate the 
rest of the client node's clock specifier (in your case, there are 0 
cells, so no data is extracted, but the U-Boot core clock node doesn't 
know that, since this is binding-specific).

Thus, there /must/ be a struct udevice for the spi0_clk node, and it 
must have an ops pointer, and either a working of_xlate pointer or NULL 
to use the default xlate function.

This is all simply how the code works; your driver must fit into this 
mechanism.

Now, the one way your driver would be able to defer all clock operations 
to the driver for the periph32ck node is if the of_xlate for the 
spi0_clk node were to edit the struct clk's .dev field to point it back 
at the driver for the periph32ck node, and set a value in struct clk's 
.id field that is hard-coded rather than derived from the client's DT 
clock specifier. However, I know you aren't using that technique, since 
your patch relies on the default of_xlate function for the spi0_clk node 
(since you provide an ops pointer, but don't fill in any of the function 
pointers within it, and hence the of_xlate pointer defaults to NULL, and 
hence clk_get_by_index() uses clk_of_xlate_default().

So here's how you need to make it work:

1)

A driver should exist for the periph32ck node. This driver's uclass is 
likely *not* UCLASS_CLK since it doesn't provide any clocks; there is no 
#clock-cells property in ths node in DT.

This driver needs to somehow create a device for each child node, so 
that the clock core can find those devices.

2)

The device for the spi0_clk node needs to be UCLASS_CLK, needs to 
provide an ops pointer, and can either use the default of_xlate or 
provide a custom one if needed. request and free ops are also required.

In particular, the ops pointer for this device *must* provide some other 
clock ops so that clients can do something useful with the clock. At 
least one of enable, disable, get_rate, set_rate are required.

Now, the *implementation* of this driver can call functions in the 
parent driver if you need, so that all the code is in one place. There's 
nothing preventing that.


More information about the U-Boot mailing list