[PATCHv2 4/6] clk: ti: clkctrl: add API to notify reset status

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

 



When an IP has both a clkctrl clock being fed into it and has hardware
reset lines, the control for these must be synced against each other.
While disabling a clock, all the hardware reset lines must be asserted
at the same time, and while enabling, resets must be deasserted.
Otherwise, the IP module fails to transition from to idle/active. To
handle this situation properly, a callback is added for clkctrl clocks
which is used by the PRM reset driver to tell the status of the reset
lines. This info is then used to sync state.

Signed-off-by: Tero Kristo <t-kristo@xxxxxx>
---
 drivers/clk/ti/clkctrl.c | 44 ++++++++++++++++++++++++++++++++++++++++
 include/linux/clk/ti.h   |  1 +
 2 files changed, 45 insertions(+)

diff --git a/drivers/clk/ti/clkctrl.c b/drivers/clk/ti/clkctrl.c
index e3e0a66a6ce2..47a0d1398c6f 100644
--- a/drivers/clk/ti/clkctrl.c
+++ b/drivers/clk/ti/clkctrl.c
@@ -25,6 +25,8 @@
 #include "clock.h"
 
 #define NO_IDLEST			0
+#define HAS_RESET			1
+#define RESET_ASSERTED			2
 
 #define OMAP4_MODULEMODE_MASK		0x3
 
@@ -164,6 +166,9 @@ static int _omap4_clkctrl_clk_enable(struct clk_hw *hw)
 	if (test_bit(NO_IDLEST, &clk->flags))
 		return 0;
 
+	if (test_bit(RESET_ASSERTED, &clk->flags))
+		return 0;
+
 	/* Wait until module is enabled */
 	while (!_omap4_is_ready(ti_clk_ll_ops->clk_readl(&clk->enable_reg))) {
 		if (_omap4_is_timeout(&timeout, OMAP4_MAX_MODULE_READY_TIME)) {
@@ -193,6 +198,10 @@ static void _omap4_clkctrl_clk_disable(struct clk_hw *hw)
 	if (test_bit(NO_IDLEST, &clk->flags))
 		goto exit;
 
+	if (test_bit(HAS_RESET, &clk->flags) &&
+	    !test_bit(RESET_ASSERTED, &clk->flags))
+		goto exit;
+
 	/* Wait until module is disabled */
 	while (!_omap4_is_idle(ti_clk_ll_ops->clk_readl(&clk->enable_reg))) {
 		if (_omap4_is_timeout(&timeout,
@@ -680,3 +689,38 @@ u32 ti_clk_is_in_standby(struct clk *clk)
 	return false;
 }
 EXPORT_SYMBOL_GPL(ti_clk_is_in_standby);
+
+/**
+ * ti_clk_notify_resets - Notify the clock driver associated reset status
+ * @clk: clock to notify reset status for
+ * @asserted: true if all HW reset lines are asserted
+ *
+ * Some clkctrl clocks have associated resets for them which effectively
+ * prevent the clock to transition from/to idle if the reset state is not
+ * in sync. For the clock to transition to idle properly, all associated
+ * resets must be asserted, and to leave idle, vice versa. To provide the
+ * current reset status, the reset driver should issue this callback.
+ */
+void ti_clk_notify_resets(struct clk *clk, bool asserted)
+{
+	struct clk_hw *hw;
+	struct clk_hw_omap *hwclk;
+
+	if (!clk)
+		return;
+
+	hw = __clk_get_hw(clk);
+
+	if (!omap2_clk_is_hw_omap(hw))
+		return;
+
+	hwclk = to_clk_hw_omap(hw);
+
+	set_bit(HAS_RESET, &hwclk->flags);
+
+	if (asserted)
+		set_bit(RESET_ASSERTED, &hwclk->flags);
+	else
+		clear_bit(RESET_ASSERTED, &hwclk->flags);
+}
+EXPORT_SYMBOL_GPL(ti_clk_notify_resets);
diff --git a/include/linux/clk/ti.h b/include/linux/clk/ti.h
index 3fb777f7103a..ae34e3f5cf7a 100644
--- a/include/linux/clk/ti.h
+++ b/include/linux/clk/ti.h
@@ -299,6 +299,7 @@ struct ti_clk_features {
 void ti_clk_setup_features(struct ti_clk_features *features);
 const struct ti_clk_features *ti_clk_get_features(void);
 u32 ti_clk_is_in_standby(struct clk *clk);
+void ti_clk_notify_resets(struct clk *clk, bool asserted);
 int omap3_noncore_dpll_save_context(struct clk_hw *hw);
 void omap3_noncore_dpll_restore_context(struct clk_hw *hw);
 
-- 
2.17.1

--
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki



[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