Lukasz Majewski | 9e1ac3d | 2019-06-24 15:50:35 +0200 | [diff] [blame] | 1 | Introduction: |
| 2 | ============= |
| 3 | |
Sean Anderson | cfc2f02 | 2020-06-24 06:41:06 -0400 | [diff] [blame] | 4 | This documentation entry describes the Common Clock Framework [CCF] port from |
| 5 | Linux kernel (v5.1.12) to U-Boot. |
Lukasz Majewski | 9e1ac3d | 2019-06-24 15:50:35 +0200 | [diff] [blame] | 6 | |
Sean Anderson | cfc2f02 | 2020-06-24 06:41:06 -0400 | [diff] [blame] | 7 | This code is supposed to bring CCF to IMX based devices (imx6q, imx7 imx8). |
| 8 | Moreover, it also provides some common clock code, which would allow easy |
| 9 | porting of CCF Linux code to other platforms. |
Lukasz Majewski | 9e1ac3d | 2019-06-24 15:50:35 +0200 | [diff] [blame] | 10 | |
| 11 | Design decisions: |
| 12 | ================= |
| 13 | |
Sean Anderson | cfc2f02 | 2020-06-24 06:41:06 -0400 | [diff] [blame] | 14 | * U-Boot's driver model [DM] for clk differs from Linux CCF. The most notably |
| 15 | difference is the lack of support for hierarchical clocks and "clock as a |
| 16 | manager driver" (single clock DTS node acts as a starting point for all other |
| 17 | clocks). |
Lukasz Majewski | 9e1ac3d | 2019-06-24 15:50:35 +0200 | [diff] [blame] | 18 | |
Sean Anderson | cfc2f02 | 2020-06-24 06:41:06 -0400 | [diff] [blame] | 19 | * The clk_get_rate() caches the previously read data if CLK_GET_RATE_NOCACHE is |
| 20 | not set (no need for recursive access). |
Lukasz Majewski | 9e1ac3d | 2019-06-24 15:50:35 +0200 | [diff] [blame] | 21 | |
Sean Anderson | cfc2f02 | 2020-06-24 06:41:06 -0400 | [diff] [blame] | 22 | * On purpose the "manager" clk driver (clk-imx6q.c) is not using large table to |
| 23 | store pointers to clocks - e.g. clk[IMX6QDL_CLK_USDHC2_SEL] = .... Instead we |
| 24 | use udevice's linked list for the same class (UCLASS_CLK). |
Lukasz Majewski | 9e1ac3d | 2019-06-24 15:50:35 +0200 | [diff] [blame] | 25 | |
| 26 | Rationale: |
| 27 | ---------- |
Sean Anderson | cfc2f02 | 2020-06-24 06:41:06 -0400 | [diff] [blame] | 28 | When porting the code as is from Linux, one would need ~1KiB of RAM to store |
| 29 | it. This is way too much if we do plan to use this driver in SPL. |
Lukasz Majewski | 9e1ac3d | 2019-06-24 15:50:35 +0200 | [diff] [blame] | 30 | |
| 31 | * The "central" structure of this patch series is struct udevice and its |
| 32 | uclass_priv field contains the struct clk pointer (to the originally created |
| 33 | one). |
| 34 | |
Lukasz Majewski | 9e1ac3d | 2019-06-24 15:50:35 +0200 | [diff] [blame] | 35 | * To keep things simple the struct udevice's uclass_priv pointer is used to |
| 36 | store back pointer to corresponding struct clk. However, it is possible to |
| 37 | modify clk-uclass.c file and add there struct uc_clk_priv, which would have |
| 38 | clock related members (like pointer to clk). As of this writing there is no |
| 39 | such need, so to avoid extra allocations (as it can be auto allocated by |
| 40 | setting .per_device_auto_alloc_size = sizeof(struct uc_clk_priv)) the |
| 41 | uclass_priv stores the pointer to struct clk. |
| 42 | |
Sean Anderson | cfc2f02 | 2020-06-24 06:41:06 -0400 | [diff] [blame] | 43 | * Non-CCF clocks do not have a pointer to a clock in clk->dev->priv. In the case |
| 44 | of composite clocks, clk->dev->priv may not match clk. Drivers should always |
| 45 | use the struct clk which is passed to them, and not clk->dev->priv. |
| 46 | |
Lukasz Majewski | 9e1ac3d | 2019-06-24 15:50:35 +0200 | [diff] [blame] | 47 | * It is advised to add common clock code (like already added rate and flags) to |
| 48 | the struct clk, which is a top level description of the clock. |
| 49 | |
| 50 | * U-Boot's driver model already provides the facility to automatically allocate |
Sean Anderson | cfc2f02 | 2020-06-24 06:41:06 -0400 | [diff] [blame] | 51 | (via private_alloc_size) device private data (accessible via dev->priv). It |
| 52 | may look appealing to use this feature to allocate private structures for CCF |
| 53 | clk devices e.g. divider (struct clk_divider *divider) for IMX6Q clock. |
Lukasz Majewski | 9e1ac3d | 2019-06-24 15:50:35 +0200 | [diff] [blame] | 54 | |
| 55 | The above feature had not been used for following reasons: |
| 56 | - The original CCF Linux kernel driver is the "manager" for clocks - it |
| 57 | decides when clock is instantiated (and when memory for it is allocated). |
| 58 | |
| 59 | - Using it would change the original structure of the CCF code. |
| 60 | |
| 61 | - To bind (via clk_register()) the clock device with U-Boot driver model we |
| 62 | first need udevice for it (the "chicken and egg problem"). |
| 63 | |
| 64 | * I've added the clk_get_parent(), which reads parent's dev->uclass_priv to |
| 65 | provide parent's struct clk pointer. This seems the easiest way to get |
Sean Anderson | cfc2f02 | 2020-06-24 06:41:06 -0400 | [diff] [blame] | 66 | child/parent relationship for struct clk in U-Boot's udevice based clocks. In |
| 67 | the future arbitrary parents may be supported by adding a get_parent function |
| 68 | to clk_ops. |
Lukasz Majewski | 9e1ac3d | 2019-06-24 15:50:35 +0200 | [diff] [blame] | 69 | |
| 70 | * Linux's CCF 'struct clk_core' corresponds to U-Boot's udevice in 'struct clk'. |
| 71 | Clock IP block agnostic flags from 'struct clk_core' (e.g. NOCACHE) have been |
Sean Anderson | cfc2f02 | 2020-06-24 06:41:06 -0400 | [diff] [blame] | 72 | moved from this struct one level up to 'struct clk'. Many flags are |
| 73 | unimplemented at the moment. |
Lukasz Majewski | 9e1ac3d | 2019-06-24 15:50:35 +0200 | [diff] [blame] | 74 | |
| 75 | * For tests the new ./test/dm/clk_ccf.c and ./drivers/clk/clk_sandbox_ccf.c |
| 76 | files have been introduced. The latter setups the CCF clock structure for |
Sean Anderson | cfc2f02 | 2020-06-24 06:41:06 -0400 | [diff] [blame] | 77 | sandbox by reusing, if possible, generic clock primitives - like divier and |
| 78 | mux. The former file provides code to tests this setup. |
Lukasz Majewski | 9e1ac3d | 2019-06-24 15:50:35 +0200 | [diff] [blame] | 79 | |
| 80 | For sandbox new CONFIG_SANDBOX_CLK_CCF Kconfig define has been introduced. |
Sean Anderson | cfc2f02 | 2020-06-24 06:41:06 -0400 | [diff] [blame] | 81 | All new primitives added for new architectures must have corresponding test in |
| 82 | the two aforementioned files. |
Lukasz Majewski | 9e1ac3d | 2019-06-24 15:50:35 +0200 | [diff] [blame] | 83 | |
| 84 | Testing (sandbox): |
| 85 | ================== |
| 86 | |
| 87 | make mrproper; make sandbox_defconfig; make -j4 |
| 88 | ./u-boot -i -d arch/sandbox/dts/test.dtb |
| 89 | => ut dm clk |
| 90 | |
| 91 | or in a more "scriptable" way (with -v to print debug output): |
| 92 | ./u-boot --fdt arch/sandbox/dts/test.dtb --command "ut dm clk_ccf" -v |
| 93 | |
| 94 | To do: |
| 95 | ------ |
| 96 | |
| 97 | * Use of OF_PLATDATA in the SPL setup for CCF - as it is now - the SPL grows |
| 98 | considerably and using CCF in boards with tiny resources (OCRAM) is |
| 99 | problematic. |
| 100 | |
| 101 | * On demand port other parts of CCF to U-Boot - as now only features _really_ |
| 102 | needed by DM/DTS converted drivers are used. |