Generic clock parent enumeration
Subsystems (2)
RFC PATCH 1/1 Generic clock parent enumeration
Hi,
here is my proposal for the enumeration of a clock parents and the
first implementation of clk_set_parent() based on it. It depends on the generic-clk-v2 patchset.
The basic idea is that only the clock can provide a way to walk all the parent clocks that it can be attached to. This has multiple purposes:
1. generic clock framework is able to find the best parent a given clock can be attached to in order to satisfy an arbitrary requirement (ie the lowest number of enabled parent clocks, energy constrains, clock network tuning, etc)
2. generic clock framework is able to check in an implementation independent way if a given clock is suitable to be parent of another one
3. the proposed implementation of the generic clk_set_parent()
--- drivers/clk/clk.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++-- include/linux/clk.h | 32 ++++++++++++++++++++++---- 2 files changed, 88 insertions(+), 7 deletions(-)
drivers/clk/clk.c +61 -2
@@ -241,10 +241,69 @@ struct clk *clk_get_parent(struct clk *c }EXPORT_SYMBOL_GPL (clk_get_parent); +struct clk *clk_next_parent (struct clk *clk,void **data) +{ +if (!clk || !data || !clk->ops->next_parent) +return NULL ; + +return clk->ops->next_parent (clk->hw, data); +} +EXPORT_SYMBOL_GPL (clk_next_parent); + +static int clk_is_valid_parent (struct clk *clk,struct clk *candidate) +{ +struct clk *parent; +void *data; + +for_each_clk_parent (clk, parent, data) +if (parent == candidate) +return 1 ; + +return 0 ; +} + +static int __clk_set_parent (struct clk *clk,struct clk *new_parent) +{ +int ret; + +if (!clk) +return -EINVAL ; + +if (WARN_ON (clk->prepare_count >0 )) +return -EBUSY ; + +if (clk->parent == new_parent) +return 0 ; + +if (!clk->ops->set_parent) +return -EINVAL ; + +if (!clk_is_valid_parent (clk, new_parent)) +return -EINVAL ; + + ret = clk->ops->set_parent (clk->hw, new_parent->hw); +if (ret) +return ret; + +if (clk->parent) +hlist_del (&clk->child_node); +if (new_parent) +hlist_add_head (&clk->child_node, &new_parent->children); + + clk->parent = new_parent; +clk_recalc_rates (clk); +return 0 ; +} +int clk_set_parent (struct clk *clk,struct clk *parent) { -/* not yet implemented */ -return -ENOSYS ; +int ret; + +mutex_lock (&prepare_lock); + ret =__clk_set_parent (clk, parent); +mutex_unlock (&prepare_lock); + +return ret; }EXPORT_SYMBOL_GPL (clk_set_parent);
include/linux/clk.h +27 -5
@@ -55,17 +55,24 @@ struct clk_hw {* held. Optional, but recommended - if this op is not set, * clk_get_rate will return 0. * -* @get_parent Query the parent of this clock; for clocks with multiple -* possible parents, query the hardware for the current -* parent. Currently only called when the clock is first -* registered. -* * @set_rate Change the rate of this clock. If this callback returns * CLK_SET_RATE_PROPAGATE, the rate change will be propagated to * the parent clock (which may propagate again). The requested * rate of the parent is passed back from the callback in the * second 'unsigned long *' argument. * +* @get_parent Query the parent of this clock; for clocks with multiple +* possible parents, query the hardware for the current +* parent. Currently only called when the clock is first +* registered. +* +* @next_parent Used to enumerate all the parents that the given clock is +* able to attach to. +* +* @set_parent Change the internal clock state/configuration so that the +* clock is attached to the new parent. The new parent is +* guaranteed to be one of those returned by next_parent(). +* * The clk_enable/clk_disable and clk_prepare/clk_unprepare pairs allow * implementations to split any work between atomic (enable) and sleepable * (prepare) contexts. If a clock requires sleeping code to be turned on, this
@@ -87,6 +94,8 @@ struct clk_hw_ops {int (*set_rate)(struct clk_hw *,unsigned long ,unsigned long *);struct clk * (*get_parent)(struct clk_hw *); +struct clk * (*next_parent)(struct clk_hw *,void **); +int (*set_parent)(struct clk_hw *,struct clk_hw *); };enum {
@@ -295,6 +304,19 @@ int clk_set_parent(struct clk *clk, strustruct clk *clk_get_parent (struct clk *clk);/** +* clk_next_parent - get the next valid parent of the given clock +* @clk: clock source +* @data: iterator's private data +* +* Returns struct clk corresponding to the next parent clock source, +* or NULL if no more (if any) valid parents are left. +*/ +struct clk *clk_next_parent (struct clk *clk,void **data); + +#define for_each_clk_parent (clk, parent, data) \ + for ((data) = NULL; ((parent) = clk_next_parent(clk, &data)); ) + +/** * clk_get_sys - get a clock based upon the device name * @dev_id: device name * @con_id: connection ID
RFC PATCH 1/1 Generic clock parent enumeration
Quoted 6 lines · Domenico Andreoli
Hi,
here is my proposal for the enumeration of a clock parents and the
first implementation ofclk_set_parent()based on it. It depends on the generic-clk-v2 patchset.
Quoted 7 lines
The basic idea is that only the clock can provide a way to walk all the parent clocks that it can be attached to. This has multiple purposes:
1. generic clock framework is able to find the best parent a given clock can be attached to in order to satisfy an arbitrary requirement (ie the lowest number of enabled parent clocks, energy constrains, clock network tuning, etc)
Is there any use case that you have to let clk core select parent? In my opinion, clk parent don't change frequently. most time display driver do that, which must has ideas of clk tree topology.
Quoted 4 lines
2. generic clock framework is able to check in an implementation independent way if a given clock is suitable to be parent of another one
Only mux clk driver needs it.
Richard
Quoted 6 lines
3. the proposed implementation of the generic
clk_set_parent()Signed-off-by Domenico Andreoli <[email protected]>
RFC PATCH 1/1 Generic clock parent enumeration
Quoted 5 lines · Richard Zhao
Quoted 4 lines · Domenico Andreoli
The basic idea is that only the clock can provide a way to walk all the parent clocks that it can be attached to. This has multiple purposes:
Quoted 8 lines
Quoted 4 lines
1. generic clock framework is able to find the best parent a given clock can be attached to in order to satisfy an arbitrary requirement (ie the lowest number of enabled parent clocks, energy constrains, clock network tuning, etc)
Is there any use case that you have to let clk core select parent? In my opinion, clk parent don't change frequently. most time display driver do that, which must has ideas of clk tree topology.
If there is not such case then I don't see the need of a generic set parent at all.
Quoted 5 lines
Quoted 3 lines
2. generic clock framework is able to check in an implementation independent way if a given clock is suitable to be parent of another one
Only mux clk driver needs it.
I think that OF may want to attach nodes to their parents and detect topology errors without knowing the inner details.
Quoted 1 line
Richard
thanks,
Domenico