diff options
-rw-r--r-- | doc/imx/clk/ccf.txt | 63 | ||||
-rw-r--r-- | drivers/clk/clk-composite.c | 7 | ||||
-rw-r--r-- | drivers/clk/clk-divider.c | 6 | ||||
-rw-r--r-- | drivers/clk/clk-fixed-factor.c | 3 | ||||
-rw-r--r-- | drivers/clk/clk-gate.c | 6 | ||||
-rw-r--r-- | drivers/clk/clk-mux.c | 12 | ||||
-rw-r--r-- | drivers/clk/imx/clk-gate2.c | 4 |
7 files changed, 50 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 414185031e..2ff1d6b47f 100644 --- a/drivers/clk/clk-composite.c +++ b/drivers/clk/clk-composite.c @@ -147,6 +147,13 @@ 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 2a68719eb6..34658536c4 100644 --- a/drivers/clk/clk-divider.c +++ b/drivers/clk/clk-divider.c @@ -73,8 +73,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; @@ -153,8 +152,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 2ceb6bb171..0eb24b87fc 100644 --- a/drivers/clk/clk-fixed-factor.c +++ b/drivers/clk/clk-fixed-factor.c @@ -20,8 +20,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 23c1f2c4ba..98e4b80b32 100644 --- a/drivers/clk/clk-gate.c +++ b/drivers/clk/clk-gate.c @@ -46,8 +46,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; @@ -89,8 +88,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 c69cce0565..26991a5bc8 100644 --- a/drivers/clk/clk-mux.c +++ b/drivers/clk/clk-mux.c @@ -38,8 +38,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) { @@ -82,8 +81,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) @@ -100,8 +98,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; @@ -118,8 +115,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 b38890d5ba..40b2d4caab 100644 --- a/drivers/clk/imx/clk-gate2.c +++ b/drivers/clk/imx/clk-gate2.c @@ -39,7 +39,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); @@ -52,7 +52,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); |