From: Claudiu Beznea <claudiu.beznea.uj@xxxxxxxxxxxxxx> The Renesas RZ/G3S SoC has a suspend mode where power to most components is turned off and RAM is switched to self-refresh. Resuming from this low-power mode is done with the help of the bootloader. During resume, the bootloader re-enables the clocks for the modules needed in the resume process (e.g. SDHI or serial). After that, control is passed to Linux. If Linux has not probed a driver for one of the modules enabled by the bootloader, or if the module was previously in a runtime-suspended state, the corresponding clocks remain enabled after resume, even though they have no consumers or they were previously disabled. To avoid keeping these clocks enabled unnecessarily, make the clk_disable_unused() function available to other drivers. Drivers can then call it during resume to disable any unused clocks. Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@xxxxxxxxxxxxxx> --- drivers/clk/clk.c | 9 +++++---- include/linux/clk.h | 12 ++++++++++++ 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index b821b2cdb155..5278030b0ad8 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -1460,7 +1460,7 @@ static void clk_core_disable_unprepare(struct clk_core *core) clk_core_unprepare_lock(core); } -static void __init clk_unprepare_unused_subtree(struct clk_core *core) +static void clk_unprepare_unused_subtree(struct clk_core *core) { struct clk_core *child; @@ -1485,7 +1485,7 @@ static void __init clk_unprepare_unused_subtree(struct clk_core *core) } } -static void __init clk_disable_unused_subtree(struct clk_core *core) +static void clk_disable_unused_subtree(struct clk_core *core) { struct clk_core *child; unsigned long flags; @@ -1526,7 +1526,7 @@ static void __init clk_disable_unused_subtree(struct clk_core *core) clk_core_disable_unprepare(core->parent); } -static bool clk_ignore_unused __initdata; +static bool clk_ignore_unused; static int __init clk_ignore_unused_setup(char *__unused) { clk_ignore_unused = true; @@ -1534,7 +1534,7 @@ static int __init clk_ignore_unused_setup(char *__unused) } __setup("clk_ignore_unused", clk_ignore_unused_setup); -static int __init clk_disable_unused(void) +int clk_disable_unused(void) { struct clk_core *core; int ret; @@ -1574,6 +1574,7 @@ static int __init clk_disable_unused(void) return 0; } late_initcall_sync(clk_disable_unused); +EXPORT_SYMBOL_GPL(clk_disable_unused); static int clk_core_determine_round_nolock(struct clk_core *core, struct clk_rate_request *req) diff --git a/include/linux/clk.h b/include/linux/clk.h index b607482ca77e..7eb0e5eb9aba 100644 --- a/include/linux/clk.h +++ b/include/linux/clk.h @@ -950,6 +950,13 @@ int clk_save_context(void); */ void clk_restore_context(void); +/** + * clk_disable_unused - disable unused clocks + * + * Disable unused clocks at boot or resume time. + */ +int clk_disable_unused(void); + #else /* !CONFIG_HAVE_CLK */ static inline struct clk *clk_get(struct device *dev, const char *id) @@ -1136,6 +1143,11 @@ static inline int clk_save_context(void) static inline void clk_restore_context(void) {} +static inline int clk_disbale_unused(void) +{ + return 0; +} + #endif /* clk_prepare_enable helps cases using clk_enable in non-atomic context. */ -- 2.43.0