aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/clk/clk.c13
-rw-r--r--include/linux/clk-provider.h6
2 files changed, 17 insertions, 2 deletions
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 9955ad7e786e..251e45d6024d 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -219,8 +219,17 @@ static void clk_disable_unused_subtree(struct clk *clk)
if (clk->flags & CLK_IGNORE_UNUSED)
goto unlock_out;
- if (__clk_is_enabled(clk) && clk->ops->disable)
- clk->ops->disable(clk->hw);
+ /*
+ * some gate clocks have special needs during the disable-unused
+ * sequence. call .disable_unused if available, otherwise fall
+ * back to .disable
+ */
+ if (__clk_is_enabled(clk)) {
+ if (clk->ops->disable_unused)
+ clk->ops->disable_unused(clk->hw);
+ else if (clk->ops->disable)
+ clk->ops->disable(clk->hw);
+ }
unlock_out:
spin_unlock_irqrestore(&enable_lock, flags);
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 3593a3ce3f0d..1c94d18514e2 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -57,6 +57,11 @@ struct clk_hw;
* This function must not sleep. Optional, if this op is not
* set then the enable count will be used.
*
+ * @disable_unused: Disable the clock atomically. Only called from
+ * clk_disable_unused for gate clocks with special needs.
+ * Called with enable_lock held. This function must not
+ * sleep.
+ *
* @recalc_rate Recalculate the rate of this clock, by querying hardware. The
* parent rate is an input parameter. It is up to the caller to
* ensure that the prepare_mutex is held across this call.
@@ -106,6 +111,7 @@ struct clk_ops {
int (*enable)(struct clk_hw *hw);
void (*disable)(struct clk_hw *hw);
int (*is_enabled)(struct clk_hw *hw);
+ void (*disable_unused)(struct clk_hw *hw);
unsigned long (*recalc_rate)(struct clk_hw *hw,
unsigned long parent_rate);
long (*round_rate)(struct clk_hw *hw, unsigned long,