mirror of
https://github.com/brain-hackers/u-boot-brain
synced 2024-08-23 10:28:51 +09:00
![Sean Anderson](/assets/img/avatar_default.png)
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 <seanga2@gmail.com> Acked-by: Lukasz Majewski <lukma@denx.de>
103 lines
4.5 KiB
Plaintext
103 lines
4.5 KiB
Plaintext
Introduction:
|
|
=============
|
|
|
|
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.
|
|
|
|
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).
|
|
|
|
* 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).
|
|
|
|
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.
|
|
|
|
* 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).
|
|
|
|
* 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
|
|
clock related members (like pointer to clk). As of this writing there is no
|
|
such need, so to avoid extra allocations (as it can be auto allocated by
|
|
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.
|
|
|
|
The above feature had not been used for following reasons:
|
|
- The original CCF Linux kernel driver is the "manager" for clocks - it
|
|
decides when clock is instantiated (and when memory for it is allocated).
|
|
|
|
- Using it would change the original structure of the CCF code.
|
|
|
|
- To bind (via clk_register()) the clock device with U-Boot driver model we
|
|
first need udevice for it (the "chicken and egg problem").
|
|
|
|
* 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. 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'. 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.
|
|
|
|
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.
|
|
|
|
Testing (sandbox):
|
|
==================
|
|
|
|
make mrproper; make sandbox_defconfig; make -j4
|
|
./u-boot -i -d arch/sandbox/dts/test.dtb
|
|
=> ut dm clk
|
|
|
|
or in a more "scriptable" way (with -v to print debug output):
|
|
./u-boot --fdt arch/sandbox/dts/test.dtb --command "ut dm clk_ccf" -v
|
|
|
|
To do:
|
|
------
|
|
|
|
* Use of OF_PLATDATA in the SPL setup for CCF - as it is now - the SPL grows
|
|
considerably and using CCF in boards with tiny resources (OCRAM) is
|
|
problematic.
|
|
|
|
* On demand port other parts of CCF to U-Boot - as now only features _really_
|
|
needed by DM/DTS converted drivers are used.
|