[PATCH 1/2] clk: Export clk_disable_unused()

Claudiu
2025-08-21T09:41:57Z

From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>

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@bp.renesas.com>
---
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