[RFC PATCH 02/35] clk: ti: gate/interface: add support for clk_ops->disable_unused

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



While executing clk_disable_unused during boot, the dflt clk operations
to disable the clocks include usecounting mechanism for clockdomains,
which is indexed badly in case a direct clock disable call is made. This
can potentially cause the underlying clockdomain to be disabled in
certain cases. Fixed by adding a separate disable_unused clk_ops, which
does not access the clockdomain functionality at all, and won't mess up
the usecounting.

Signed-off-by: Tero Kristo <t-kristo@xxxxxx>
---
 arch/arm/mach-omap2/clock.c |   27 +++++++++++++++++++++------
 drivers/clk/ti/composite.c  |    1 +
 drivers/clk/ti/gate.c       |    2 ++
 drivers/clk/ti/interface.c  |    1 +
 include/linux/clk/ti.h      |    1 +
 5 files changed, 26 insertions(+), 6 deletions(-)

diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c
index 6124db5..2b096c7 100644
--- a/arch/arm/mach-omap2/clock.c
+++ b/arch/arm/mach-omap2/clock.c
@@ -345,15 +345,12 @@ err:
 }
 
 /**
- * omap2_dflt_clk_disable - disable a clock in the hardware
+ * omap2_dflt_clk_disable_ll - low level disable a clock in the hardware
  * @hw: struct clk_hw * of the clock to disable
  *
- * Disable the clock @hw in the hardware, and call into the OMAP
- * clockdomain code to "disable" the corresponding clockdomain if all
- * clocks/hwmods in that clockdomain are now disabled.  No return
- * value.
+ * Disable the clock @hw in the hardware. No return value.
  */
-void omap2_dflt_clk_disable(struct clk_hw *hw)
+void omap2_dflt_clk_disable_ll(struct clk_hw *hw)
 {
 	struct clk_hw_omap *clk;
 	u32 v;
@@ -376,6 +373,24 @@ void omap2_dflt_clk_disable(struct clk_hw *hw)
 		v &= ~(1 << clk->enable_bit);
 	omap2_clk_writel(v, clk, clk->enable_reg);
 	/* No OCP barrier needed here since it is a disable operation */
+}
+
+/**
+ * omap2_dflt_clk_disable - disable a clock in the hardware
+ * @hw: struct clk_hw * of the clock to disable
+ *
+ * Disable the clock @hw in the hardware, and call into the OMAP
+ * clockdomain code to "disable" the corresponding clockdomain if all
+ * clocks/hwmods in that clockdomain are now disabled.  No return
+ * value.
+ */
+void omap2_dflt_clk_disable(struct clk_hw *hw)
+{
+	struct clk_hw_omap *clk;
+
+	clk = to_clk_hw_omap(hw);
+
+	omap2_dflt_clk_disable_ll(hw);
 
 	if (clkdm_control && clk->clkdm)
 		clkdm_clk_disable(clk->clkdm, hw->clk);
diff --git a/drivers/clk/ti/composite.c b/drivers/clk/ti/composite.c
index 3654f61..9e10191 100644
--- a/drivers/clk/ti/composite.c
+++ b/drivers/clk/ti/composite.c
@@ -57,6 +57,7 @@ static const struct clk_ops ti_composite_divider_ops = {
 static const struct clk_ops ti_composite_gate_ops = {
 	.enable		= &omap2_dflt_clk_enable,
 	.disable	= &omap2_dflt_clk_disable,
+	.disable_unused	= &omap2_dflt_clk_disable_ll,
 	.is_enabled	= &omap2_dflt_clk_is_enabled,
 };
 
diff --git a/drivers/clk/ti/gate.c b/drivers/clk/ti/gate.c
index d493307..e2d4d1e 100644
--- a/drivers/clk/ti/gate.c
+++ b/drivers/clk/ti/gate.c
@@ -41,6 +41,7 @@ static const struct clk_ops omap_gate_clk_ops = {
 	.init		= &omap2_init_clk_clkdm,
 	.enable		= &omap2_dflt_clk_enable,
 	.disable	= &omap2_dflt_clk_disable,
+	.disable_unused	= &omap2_dflt_clk_disable_ll,
 	.is_enabled	= &omap2_dflt_clk_is_enabled,
 };
 
@@ -48,6 +49,7 @@ static const struct clk_ops omap_gate_clk_hsdiv_restore_ops = {
 	.init		= &omap2_init_clk_clkdm,
 	.enable		= &omap36xx_gate_clk_enable_with_hsdiv_restore,
 	.disable	= &omap2_dflt_clk_disable,
+	.disable_unused	= &omap2_dflt_clk_disable_ll,
 	.is_enabled	= &omap2_dflt_clk_is_enabled,
 };
 
diff --git a/drivers/clk/ti/interface.c b/drivers/clk/ti/interface.c
index 265d91f..c037259 100644
--- a/drivers/clk/ti/interface.c
+++ b/drivers/clk/ti/interface.c
@@ -29,6 +29,7 @@ static const struct clk_ops ti_interface_clk_ops = {
 	.init		= &omap2_init_clk_clkdm,
 	.enable		= &omap2_dflt_clk_enable,
 	.disable	= &omap2_dflt_clk_disable,
+	.disable_unused	= &omap2_dflt_clk_disable_ll,
 	.is_enabled	= &omap2_dflt_clk_is_enabled,
 };
 
diff --git a/include/linux/clk/ti.h b/include/linux/clk/ti.h
index 6784400..c8c0543 100644
--- a/include/linux/clk/ti.h
+++ b/include/linux/clk/ti.h
@@ -306,6 +306,7 @@ int omap3_dpll4_set_rate(struct clk_hw *clk, unsigned long rate,
 int omap3_dpll4_set_rate_and_parent(struct clk_hw *hw, unsigned long rate,
 				    unsigned long parent_rate, u8 index);
 int omap2_dflt_clk_enable(struct clk_hw *hw);
+void omap2_dflt_clk_disable_ll(struct clk_hw *hw);
 void omap2_dflt_clk_disable(struct clk_hw *hw);
 int omap2_dflt_clk_is_enabled(struct clk_hw *hw);
 void omap3_clk_lock_dpll5(void);
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Arm (vger)]     [ARM Kernel]     [ARM MSM]     [Linux Tegra]     [Linux WPAN Networking]     [Linux Wireless Networking]     [Maemo Users]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux