From af89cd45603483135bdd238fcb3fa871155a0ae1 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Fri, 20 May 2022 09:57:34 +0200 Subject: clk: Improve documentation for devm_clk_get() and its optional variant MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make use of "Context:" and "Return:". Mention that the clk is not to be expected to be prepared, previously only not being enabled was mentioned which probably dates from the times when the concept of clk preparation wasn't invented yet. Also describe devm_clk_get_optional() fully instead of just referencing devm_clk_get(). Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20220520075737.758761-2-u.kleine-koenig@pengutronix.de Reviewed-by: Russell King (Oracle) Signed-off-by: Stephen Boyd --- include/linux/clk.h | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) (limited to 'include/linux') diff --git a/include/linux/clk.h b/include/linux/clk.h index 39faa54efe88..c8fc398d2ad7 100644 --- a/include/linux/clk.h +++ b/include/linux/clk.h @@ -443,15 +443,16 @@ int __must_check devm_clk_bulk_get_all(struct device *dev, * @dev: device for clock "consumer" * @id: clock consumer ID * - * Returns a struct clk corresponding to the clock producer, or + * Context: May sleep. + * + * Return: a struct clk corresponding to the clock producer, or * valid IS_ERR() condition containing errno. The implementation * uses @dev and @id to determine the clock consumer, and thereby * the clock producer. (IOW, @id may be identical strings, but * clk_get may return different clock producers depending on @dev.) * - * Drivers must assume that the clock source is not enabled. - * - * devm_clk_get should not be called from within interrupt context. + * Drivers must assume that the clock source is neither prepared nor + * enabled. * * The clock will automatically be freed when the device is unbound * from the bus. @@ -464,8 +465,20 @@ struct clk *devm_clk_get(struct device *dev, const char *id); * @dev: device for clock "consumer" * @id: clock consumer ID * - * Behaves the same as devm_clk_get() except where there is no clock producer. - * In this case, instead of returning -ENOENT, the function returns NULL. + * Context: May sleep. + * + * Return: a struct clk corresponding to the clock producer, or + * valid IS_ERR() condition containing errno. The implementation + * uses @dev and @id to determine the clock consumer, and thereby + * the clock producer. If no such clk is found, it returns NULL + * which serves as a dummy clk. That's the only difference compared + * to devm_clk_get(). + * + * Drivers must assume that the clock source is neither prepared nor + * enabled. + * + * The clock will automatically be freed when the device is unbound + * from the bus. */ struct clk *devm_clk_get_optional(struct device *dev, const char *id); -- cgit v1.2.3 From 7ef9651e9792b08eb310c6beb202cbc947f43cab Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Fri, 20 May 2022 09:57:36 +0200 Subject: clk: Provide new devm_clk helpers for prepared and enabled clocks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When a driver keeps a clock prepared (or enabled) during the whole lifetime of the driver, these helpers allow to simplify the drivers. Reviewed-by: Jonathan Cameron Reviewed-by: Alexandru Ardelean Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20220520075737.758761-4-u.kleine-koenig@pengutronix.de Signed-off-by: Stephen Boyd --- drivers/clk/clk-devres.c | 27 ++++++++++++ include/linux/clk.h | 109 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 136 insertions(+) (limited to 'include/linux') diff --git a/drivers/clk/clk-devres.c b/drivers/clk/clk-devres.c index c822f4ef1584..43ccd20e0298 100644 --- a/drivers/clk/clk-devres.c +++ b/drivers/clk/clk-devres.c @@ -66,12 +66,39 @@ struct clk *devm_clk_get(struct device *dev, const char *id) } EXPORT_SYMBOL(devm_clk_get); +struct clk *devm_clk_get_prepared(struct device *dev, const char *id) +{ + return __devm_clk_get(dev, id, clk_get, clk_prepare, clk_unprepare); +} +EXPORT_SYMBOL_GPL(devm_clk_get_prepared); + +struct clk *devm_clk_get_enabled(struct device *dev, const char *id) +{ + return __devm_clk_get(dev, id, clk_get, + clk_prepare_enable, clk_disable_unprepare); +} +EXPORT_SYMBOL_GPL(devm_clk_get_enabled); + struct clk *devm_clk_get_optional(struct device *dev, const char *id) { return __devm_clk_get(dev, id, clk_get_optional, NULL, NULL); } EXPORT_SYMBOL(devm_clk_get_optional); +struct clk *devm_clk_get_optional_prepared(struct device *dev, const char *id) +{ + return __devm_clk_get(dev, id, clk_get_optional, + clk_prepare, clk_unprepare); +} +EXPORT_SYMBOL_GPL(devm_clk_get_optional_prepared); + +struct clk *devm_clk_get_optional_enabled(struct device *dev, const char *id) +{ + return __devm_clk_get(dev, id, clk_get_optional, + clk_prepare_enable, clk_disable_unprepare); +} +EXPORT_SYMBOL_GPL(devm_clk_get_optional_enabled); + struct clk_bulk_devres { struct clk_bulk_data *clks; int num_clks; diff --git a/include/linux/clk.h b/include/linux/clk.h index c8fc398d2ad7..c13061cabdfc 100644 --- a/include/linux/clk.h +++ b/include/linux/clk.h @@ -459,6 +459,47 @@ int __must_check devm_clk_bulk_get_all(struct device *dev, */ struct clk *devm_clk_get(struct device *dev, const char *id); +/** + * devm_clk_get_prepared - devm_clk_get() + clk_prepare() + * @dev: device for clock "consumer" + * @id: clock consumer ID + * + * Context: May sleep. + * + * Return: a struct clk corresponding to the clock producer, or + * valid IS_ERR() condition containing errno. The implementation + * uses @dev and @id to determine the clock consumer, and thereby + * the clock producer. (IOW, @id may be identical strings, but + * clk_get may return different clock producers depending on @dev.) + * + * The returned clk (if valid) is prepared. Drivers must however assume + * that the clock is not enabled. + * + * The clock will automatically be unprepared and freed when the device + * is unbound from the bus. + */ +struct clk *devm_clk_get_prepared(struct device *dev, const char *id); + +/** + * devm_clk_get_enabled - devm_clk_get() + clk_prepare_enable() + * @dev: device for clock "consumer" + * @id: clock consumer ID + * + * Context: May sleep. + * + * Return: a struct clk corresponding to the clock producer, or + * valid IS_ERR() condition containing errno. The implementation + * uses @dev and @id to determine the clock consumer, and thereby + * the clock producer. (IOW, @id may be identical strings, but + * clk_get may return different clock producers depending on @dev.) + * + * The returned clk (if valid) is prepared and enabled. + * + * The clock will automatically be disabled, unprepared and freed + * when the device is unbound from the bus. + */ +struct clk *devm_clk_get_enabled(struct device *dev, const char *id); + /** * devm_clk_get_optional - lookup and obtain a managed reference to an optional * clock producer. @@ -482,6 +523,50 @@ struct clk *devm_clk_get(struct device *dev, const char *id); */ struct clk *devm_clk_get_optional(struct device *dev, const char *id); +/** + * devm_clk_get_optional_prepared - devm_clk_get_optional() + clk_prepare() + * @dev: device for clock "consumer" + * @id: clock consumer ID + * + * Context: May sleep. + * + * Return: a struct clk corresponding to the clock producer, or + * valid IS_ERR() condition containing errno. The implementation + * uses @dev and @id to determine the clock consumer, and thereby + * the clock producer. If no such clk is found, it returns NULL + * which serves as a dummy clk. That's the only difference compared + * to devm_clk_get_prepared(). + * + * The returned clk (if valid) is prepared. Drivers must however + * assume that the clock is not enabled. + * + * The clock will automatically be unprepared and freed when the + * device is unbound from the bus. + */ +struct clk *devm_clk_get_optional_prepared(struct device *dev, const char *id); + +/** + * devm_clk_get_optional_enabled - devm_clk_get_optional() + + * clk_prepare_enable() + * @dev: device for clock "consumer" + * @id: clock consumer ID + * + * Context: May sleep. + * + * Return: a struct clk corresponding to the clock producer, or + * valid IS_ERR() condition containing errno. The implementation + * uses @dev and @id to determine the clock consumer, and thereby + * the clock producer. If no such clk is found, it returns NULL + * which serves as a dummy clk. That's the only difference compared + * to devm_clk_get_enabled(). + * + * The returned clk (if valid) is prepared and enabled. + * + * The clock will automatically be disabled, unprepared and freed + * when the device is unbound from the bus. + */ +struct clk *devm_clk_get_optional_enabled(struct device *dev, const char *id); + /** * devm_get_clk_from_child - lookup and obtain a managed reference to a * clock producer from child node. @@ -826,12 +911,36 @@ static inline struct clk *devm_clk_get(struct device *dev, const char *id) return NULL; } +static inline struct clk *devm_clk_get_prepared(struct device *dev, + const char *id) +{ + return NULL; +} + +static inline struct clk *devm_clk_get_enabled(struct device *dev, + const char *id) +{ + return NULL; +} + static inline struct clk *devm_clk_get_optional(struct device *dev, const char *id) { return NULL; } +static inline struct clk *devm_clk_get_optional_prepared(struct device *dev, + const char *id) +{ + return NULL; +} + +static inline struct clk *devm_clk_get_optional_enabled(struct device *dev, + const char *id) +{ + return NULL; +} + static inline int __must_check devm_clk_bulk_get(struct device *dev, int num_clks, struct clk_bulk_data *clks) { -- cgit v1.2.3 From 62c0aff64c8d6594357b6217db019552ea664b90 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 22 Jun 2022 20:11:47 +0300 Subject: clk: Remove never used devm_clk_*unregister() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For the entire history of the devm_clk_*unregister() existence they were used only once (*) in 2015. Remove them. *) The commit 264e3b75de4e ("clk: s2mps11: Simplify s2mps11_clk_probe unwind paths") exactly supports the point of the change proposed here. Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20220622171147.85603-1-andriy.shevchenko@linux.intel.com Acked-by: Uwe Kleine-König Signed-off-by: Stephen Boyd --- drivers/clk/clk.c | 48 -------------------------------------------- include/linux/clk-provider.h | 2 -- 2 files changed, 50 deletions(-) (limited to 'include/linux') diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index f00d4c1158d7..7fc191c15507 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -4279,54 +4279,6 @@ int devm_clk_hw_register(struct device *dev, struct clk_hw *hw) } EXPORT_SYMBOL_GPL(devm_clk_hw_register); -static int devm_clk_match(struct device *dev, void *res, void *data) -{ - struct clk *c = res; - if (WARN_ON(!c)) - return 0; - return c == data; -} - -static int devm_clk_hw_match(struct device *dev, void *res, void *data) -{ - struct clk_hw *hw = res; - - if (WARN_ON(!hw)) - return 0; - return hw == data; -} - -/** - * devm_clk_unregister - resource managed clk_unregister() - * @dev: device that is unregistering the clock data - * @clk: clock to unregister - * - * Deallocate a clock allocated with devm_clk_register(). Normally - * this function will not need to be called and the resource management - * code will ensure that the resource is freed. - */ -void devm_clk_unregister(struct device *dev, struct clk *clk) -{ - WARN_ON(devres_release(dev, devm_clk_unregister_cb, devm_clk_match, clk)); -} -EXPORT_SYMBOL_GPL(devm_clk_unregister); - -/** - * devm_clk_hw_unregister - resource managed clk_hw_unregister() - * @dev: device that is unregistering the hardware-specific clock data - * @hw: link to hardware-specific clock data - * - * Unregister a clk_hw registered with devm_clk_hw_register(). Normally - * this function will not need to be called and the resource management - * code will ensure that the resource is freed. - */ -void devm_clk_hw_unregister(struct device *dev, struct clk_hw *hw) -{ - WARN_ON(devres_release(dev, devm_clk_hw_unregister_cb, devm_clk_hw_match, - hw)); -} -EXPORT_SYMBOL_GPL(devm_clk_hw_unregister); - static void devm_clk_release(struct device *dev, void *res) { clk_put(*(struct clk **)res); diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index c10dc4c659e2..72d937c03a3e 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -1176,10 +1176,8 @@ int __must_check devm_clk_hw_register(struct device *dev, struct clk_hw *hw); int __must_check of_clk_hw_register(struct device_node *node, struct clk_hw *hw); void clk_unregister(struct clk *clk); -void devm_clk_unregister(struct device *dev, struct clk *clk); void clk_hw_unregister(struct clk_hw *hw); -void devm_clk_hw_unregister(struct device *dev, struct clk_hw *hw); /* helper functions */ const char *__clk_get_name(const struct clk *clk); -- cgit v1.2.3 From 909fcb195201f7c3aa81523cc182a4c9b52210e5 Mon Sep 17 00:00:00 2001 From: Marijn Suijten Date: Thu, 30 Jun 2022 00:53:21 +0200 Subject: clk: divider: Introduce devm_clk_hw_register_divider_parent_hw() Add the devres variant of clk_hw_register_divider_parent_hw() for registering a divider clock with clk_hw parent pointer instead of parent name. Signed-off-by: Marijn Suijten Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20220629225331.357308-2-marijn.suijten@somainline.org Signed-off-by: Stephen Boyd --- include/linux/clk-provider.h | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'include/linux') diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index c10dc4c659e2..4e07621849e6 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -831,6 +831,25 @@ struct clk *clk_register_divider_table(struct device *dev, const char *name, __devm_clk_hw_register_divider((dev), NULL, (name), (parent_name), NULL, \ NULL, (flags), (reg), (shift), (width), \ (clk_divider_flags), NULL, (lock)) +/** + * devm_clk_hw_register_divider_parent_hw - register a divider clock with the clock framework + * @dev: device registering this clock + * @name: name of this clock + * @parent_hw: pointer to parent clk + * @flags: framework-specific flags + * @reg: register address to adjust divider + * @shift: number of bits to shift the bitfield + * @width: width of the bitfield + * @clk_divider_flags: divider-specific flags for this clock + * @lock: shared register lock for this clock + */ +#define devm_clk_hw_register_divider_parent_hw(dev, name, parent_hw, flags, \ + reg, shift, width, \ + clk_divider_flags, lock) \ + __devm_clk_hw_register_divider((dev), NULL, (name), NULL, \ + (parent_hw), NULL, (flags), (reg), \ + (shift), (width), (clk_divider_flags), \ + NULL, (lock)) /** * devm_clk_hw_register_divider_table - register a table based divider clock * with the clock framework (devres variant) -- cgit v1.2.3 From df63af17f3375239e0be124844f304b4a4b60665 Mon Sep 17 00:00:00 2001 From: Marijn Suijten Date: Thu, 30 Jun 2022 00:53:22 +0200 Subject: clk: mux: Introduce devm_clk_hw_register_mux_parent_hws() Add the devres variant of clk_hw_register_mux_hws() for registering a mux clock with clk_hw parent pointers instead of parent names. Signed-off-by: Marijn Suijten Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20220629225331.357308-3-marijn.suijten@somainline.org Signed-off-by: Stephen Boyd --- include/linux/clk-provider.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'include/linux') diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 4e07621849e6..316c7e082934 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -980,6 +980,13 @@ struct clk *clk_register_mux_table(struct device *dev, const char *name, (parent_names), NULL, NULL, (flags), (reg), \ (shift), BIT((width)) - 1, (clk_mux_flags), \ NULL, (lock)) +#define devm_clk_hw_register_mux_parent_hws(dev, name, parent_hws, \ + num_parents, flags, reg, shift, \ + width, clk_mux_flags, lock) \ + __devm_clk_hw_register_mux((dev), NULL, (name), (num_parents), NULL, \ + (parent_hws), NULL, (flags), (reg), \ + (shift), BIT((width)) - 1, \ + (clk_mux_flags), NULL, (lock)) int clk_mux_val_to_index(struct clk_hw *hw, const u32 *table, unsigned int flags, unsigned int val); -- cgit v1.2.3 From 6ebd5247ad2aa210b3ff4481c6ed8aa32a032b12 Mon Sep 17 00:00:00 2001 From: Marijn Suijten Date: Thu, 30 Jun 2022 00:53:23 +0200 Subject: clk: fixed-factor: Introduce *clk_hw_register_fixed_factor_parent_hw() Add the devres and non-devres variant of clk_hw_register_fixed_factor_parent_hw() for registering a fixed factor clock with clk_hw parent pointer instead of parent name. Signed-off-by: Marijn Suijten Link: https://lore.kernel.org/r/20220629225331.357308-4-marijn.suijten@somainline.org Signed-off-by: Stephen Boyd --- drivers/clk/clk-fixed-factor.c | 45 +++++++++++++++++++++++++++++++++++++----- include/linux/clk-provider.h | 8 ++++++++ 2 files changed, 48 insertions(+), 5 deletions(-) (limited to 'include/linux') diff --git a/drivers/clk/clk-fixed-factor.c b/drivers/clk/clk-fixed-factor.c index e6b36247c16b..f734e34735a9 100644 --- a/drivers/clk/clk-fixed-factor.c +++ b/drivers/clk/clk-fixed-factor.c @@ -78,7 +78,8 @@ static void devm_clk_hw_register_fixed_factor_release(struct device *dev, void * static struct clk_hw * __clk_hw_register_fixed_factor(struct device *dev, struct device_node *np, - const char *name, const char *parent_name, int index, + const char *name, const char *parent_name, + const struct clk_hw *parent_hw, int index, unsigned long flags, unsigned int mult, unsigned int div, bool devm) { @@ -110,6 +111,8 @@ __clk_hw_register_fixed_factor(struct device *dev, struct device_node *np, init.flags = flags; if (parent_name) init.parent_names = &parent_name; + else if (parent_hw) + init.parent_hws = &parent_hw; else init.parent_data = &pdata; init.num_parents = 1; @@ -148,16 +151,48 @@ struct clk_hw *devm_clk_hw_register_fixed_factor_index(struct device *dev, const char *name, unsigned int index, unsigned long flags, unsigned int mult, unsigned int div) { - return __clk_hw_register_fixed_factor(dev, NULL, name, NULL, index, + return __clk_hw_register_fixed_factor(dev, NULL, name, NULL, NULL, index, flags, mult, div, true); } EXPORT_SYMBOL_GPL(devm_clk_hw_register_fixed_factor_index); +/** + * devm_clk_hw_register_fixed_factor_parent_hw - Register a fixed factor clock with + * pointer to parent clock + * @dev: device that is registering this clock + * @name: name of this clock + * @parent_hw: pointer to parent clk + * @flags: fixed factor flags + * @mult: multiplier + * @div: divider + * + * Return: Pointer to fixed factor clk_hw structure that was registered or + * an error pointer. + */ +struct clk_hw *devm_clk_hw_register_fixed_factor_parent_hw(struct device *dev, + const char *name, const struct clk_hw *parent_hw, + unsigned long flags, unsigned int mult, unsigned int div) +{ + return __clk_hw_register_fixed_factor(dev, NULL, name, NULL, parent_hw, + -1, flags, mult, div, true); +} +EXPORT_SYMBOL_GPL(devm_clk_hw_register_fixed_factor_parent_hw); + +struct clk_hw *clk_hw_register_fixed_factor_parent_hw(struct device *dev, + const char *name, const struct clk_hw *parent_hw, + unsigned long flags, unsigned int mult, unsigned int div) +{ + return __clk_hw_register_fixed_factor(dev, NULL, name, NULL, + parent_hw, -1, flags, mult, div, + false); +} +EXPORT_SYMBOL_GPL(clk_hw_register_fixed_factor_parent_hw); + struct clk_hw *clk_hw_register_fixed_factor(struct device *dev, const char *name, const char *parent_name, unsigned long flags, unsigned int mult, unsigned int div) { - return __clk_hw_register_fixed_factor(dev, NULL, name, parent_name, -1, + return __clk_hw_register_fixed_factor(dev, NULL, name, parent_name, NULL, -1, flags, mult, div, false); } EXPORT_SYMBOL_GPL(clk_hw_register_fixed_factor); @@ -204,7 +239,7 @@ struct clk_hw *devm_clk_hw_register_fixed_factor(struct device *dev, const char *name, const char *parent_name, unsigned long flags, unsigned int mult, unsigned int div) { - return __clk_hw_register_fixed_factor(dev, NULL, name, parent_name, -1, + return __clk_hw_register_fixed_factor(dev, NULL, name, parent_name, NULL, -1, flags, mult, div, true); } EXPORT_SYMBOL_GPL(devm_clk_hw_register_fixed_factor); @@ -231,7 +266,7 @@ static struct clk_hw *_of_fixed_factor_clk_setup(struct device_node *node) of_property_read_string(node, "clock-output-names", &clk_name); - hw = __clk_hw_register_fixed_factor(NULL, node, clk_name, NULL, 0, + hw = __clk_hw_register_fixed_factor(NULL, node, clk_name, NULL, NULL, 0, 0, mult, div, false); if (IS_ERR(hw)) { /* diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 316c7e082934..94458cb669f0 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -1032,6 +1032,14 @@ struct clk_hw *devm_clk_hw_register_fixed_factor(struct device *dev, struct clk_hw *devm_clk_hw_register_fixed_factor_index(struct device *dev, const char *name, unsigned int index, unsigned long flags, unsigned int mult, unsigned int div); + +struct clk_hw *devm_clk_hw_register_fixed_factor_parent_hw(struct device *dev, + const char *name, const struct clk_hw *parent_hw, + unsigned long flags, unsigned int mult, unsigned int div); + +struct clk_hw *clk_hw_register_fixed_factor_parent_hw(struct device *dev, + const char *name, const struct clk_hw *parent_hw, + unsigned long flags, unsigned int mult, unsigned int div); /** * struct clk_fractional_divider - adjustable fractional divider clock * -- cgit v1.2.3