Add a managed wrapper for clk_prepare_enable(). Signed-off-by: Rasmus Villemoes <linux@xxxxxxxxxxxxxxxxxx> --- .../driver-api/driver-model/devres.rst | 1 + drivers/clk/clk-devres.c | 29 +++++++++++++++++++ include/linux/clk.h | 13 +++++++++ 3 files changed, 43 insertions(+) diff --git a/Documentation/driver-api/driver-model/devres.rst b/Documentation/driver-api/driver-model/devres.rst index cd8b6e657b94..8ee2557f9ad7 100644 --- a/Documentation/driver-api/driver-model/devres.rst +++ b/Documentation/driver-api/driver-model/devres.rst @@ -253,6 +253,7 @@ CLOCK devm_clk_hw_register() devm_of_clk_add_hw_provider() devm_clk_hw_register_clkdev() + devm_clk_prepare_enable() DMA dmaenginem_async_device_register() diff --git a/drivers/clk/clk-devres.c b/drivers/clk/clk-devres.c index be160764911b..d5bfa8cd7347 100644 --- a/drivers/clk/clk-devres.c +++ b/drivers/clk/clk-devres.c @@ -156,3 +156,32 @@ struct clk *devm_get_clk_from_child(struct device *dev, return clk; } EXPORT_SYMBOL(devm_get_clk_from_child); + +static void devm_clk_disable_unprepare(struct device *dev, void *res) +{ + clk_disable_unprepare(*(struct clk **)res); +} + +int devm_clk_prepare_enable(struct device *dev, struct clk *clk) +{ + struct clk **ptr; + int ret; + + if (!clk) + return 0; + + ptr = devres_alloc(devm_clk_disable_unprepare, sizeof(*ptr), GFP_KERNEL); + if (!ptr) + return -ENOMEM; + + ret = clk_prepare_enable(clk); + if (!ret) { + *ptr = clk; + devres_add(dev, ptr); + } else { + devres_free(ptr); + } + + return ret; +} +EXPORT_SYMBOL(devm_clk_prepare_enable); diff --git a/include/linux/clk.h b/include/linux/clk.h index 266e8de3cb51..04d135520480 100644 --- a/include/linux/clk.h +++ b/include/linux/clk.h @@ -485,6 +485,19 @@ struct clk *devm_clk_get_optional(struct device *dev, const char *id); */ struct clk *devm_get_clk_from_child(struct device *dev, struct device_node *np, const char *con_id); +/** + * devm_clk_prepare_enable - prepare and enable a clock source + * @dev: device for clock "consumer" + * @clk: clock source + * + * This function calls clk_prepare_enable() on @clk, and ensures the + * clock will automatically be disabled and unprepared when the device + * is unbound from the bus. + * + * Must not be called from within atomic context. + */ +int devm_clk_prepare_enable(struct device *dev, struct clk *clk); + /** * clk_rate_exclusive_get - get exclusivity over the rate control of a * producer -- 2.29.2