Message ID | 20220704185733.1288578-1-abel.vesa@linaro.org (mailing list archive) |
---|---|
State | Not Applicable |
Headers | show |
Series | [RFC] clk: Add clk_hw based provider enable/disable API | expand |
On 22-07-04 21:57:33, Abel Vesa wrote: > 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. > Ignore this one please. There is a new RFC here: https://lore.kernel.org/lkml/20220706150411.708213-1-abel.vesa@linaro.org/ > Signed-off-by: Abel Vesa <abel.vesa@linaro.org> > --- > 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 >
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,
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@linaro.org> --- drivers/clk/clk.c | 25 +++++++++++++++++++++++++ include/linux/clk-provider.h | 2 ++ 2 files changed, 27 insertions(+)