Sometimes, a clock needs to be enabled or disabled by the provider, without actually touching the enable count. For example, a clock provider driver might choose to disable some unused clocks on sync state callback rather than on the default clk_disable_unused. Such clocks are usually enabled by bootloader and need to stay ungated until some driver built as module probes. So add clk_hw enable/disable to allow the clock provider drivers to disable such clocks on sync state callback. Signed-off-by: Abel Vesa <abel.vesa@xxxxxxxxxx> --- drivers/clk/clk.c | 25 +++++++++++++++++++++++++ include/linux/clk-provider.h | 2 ++ 2 files changed, 27 insertions(+) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index f00d4c1158d7..a727cffb6bba 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -1011,6 +1011,17 @@ void clk_disable(struct clk *clk) } EXPORT_SYMBOL_GPL(clk_disable); +void clk_hw_disable(const struct clk_hw *hw) +{ + struct clk_core *core = hw->core; + + trace_clk_disable(core); + if (core->ops->disable) + core->ops->disable(core->hw); + trace_clk_disable_complete(core); +} +EXPORT_SYMBOL_GPL(clk_hw_disable); + static int clk_core_enable(struct clk_core *core) { int ret = 0; @@ -1176,6 +1187,20 @@ int clk_enable(struct clk *clk) } EXPORT_SYMBOL_GPL(clk_enable); +int clk_hw_enable(const struct clk_hw *hw) +{ + struct clk_core *core = hw->core; + int ret = 0; + + trace_clk_enable(core); + if (core->ops->enable) + ret = core->ops->enable(core->hw); + trace_clk_enable_complete(core); + + return ret; +} +EXPORT_SYMBOL_GPL(clk_hw_enable); + /** * clk_is_enabled_when_prepared - indicate if preparing a clock also enables it. * @clk: clock source diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index c10dc4c659e2..0f9968a7a6d2 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -1212,6 +1212,8 @@ unsigned long clk_hw_get_flags(const struct clk_hw *hw); bool clk_hw_is_prepared(const struct clk_hw *hw); bool clk_hw_rate_is_protected(const struct clk_hw *hw); bool clk_hw_is_enabled(const struct clk_hw *hw); +int clk_hw_enable(const struct clk_hw *hw); +void clk_hw_disable(const struct clk_hw *hw); bool __clk_is_enabled(struct clk *clk); struct clk *__clk_lookup(const char *name); int __clk_mux_determine_rate(struct clk_hw *hw, -- 2.34.3