summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNishanth Menon <nm@ti.com>2012-02-23 17:34:52 +0800
committerAndy Green <andy.green@linaro.org>2012-06-20 10:27:34 +0800
commit47e82853a804d1ce19e86078c1bf305907144ac5 (patch)
tree69a5a51c7c0e370bbd64590b4799653506244cde
parentfd98e92d8a99dbd81f2aff5d3fb1c0c9affca8a4 (diff)
OMAP4: PM: provide support for cold reset of device
OMAP4 has support for cold resetting the device. It is not recommended to use this as the default behavior, however certain modules in OMAP have no other mechanism to reset themselves once certain bad states have been hit. Signed-off-by: Nishanth Menon <nm@ti.com>
-rw-r--r--arch/arm/mach-omap2/pm.h9
-rw-r--r--arch/arm/mach-omap2/pm44xx.c29
-rw-r--r--arch/arm/mach-omap2/prminst44xx.c17
-rw-r--r--arch/arm/mach-omap2/prminst44xx.h2
4 files changed, 57 insertions, 0 deletions
diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
index 565253e4818..59095b45596 100644
--- a/arch/arm/mach-omap2/pm.h
+++ b/arch/arm/mach-omap2/pm.h
@@ -63,6 +63,15 @@ static inline int omap4_opp_init(void)
}
#endif
+#ifdef CONFIG_PM
+int omap4_pm_cold_reset(char *reason);
+#else
+int omap4_pm_cold_reset(char *reason)
+{
+ return -EINVAL;
+}
+#endif
+
/*
* cpuidle mach specific parameters
*
diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c
index 44ff05d0649..a564fc4afd2 100644
--- a/arch/arm/mach-omap2/pm44xx.c
+++ b/arch/arm/mach-omap2/pm44xx.c
@@ -335,6 +335,35 @@ static int omap4_pm_suspend(void)
#endif /* CONFIG_SUSPEND */
/**
+ * omap4_pm_cold_reset() - Cold reset OMAP4
+ * @reason: why am I resetting.
+ *
+ * As per the TRM, it is recommended that we set all the power domains to
+ * ON state before we trigger cold reset.
+ */
+int omap4_pm_cold_reset(char *reason)
+{
+ struct power_state *pwrst;
+
+ /* Switch ON all pwrst registers */
+ list_for_each_entry(pwrst, &pwrst_list, node) {
+ if (pwrst->pwrdm->pwrsts_logic_ret)
+ pwrdm_set_logic_retst(pwrst->pwrdm, PWRDM_POWER_ON);
+ if (pwrst->pwrdm->pwrsts)
+ omap_set_pwrdm_state(pwrst->pwrdm, PWRDM_POWER_ON);
+ }
+
+ WARN(1, "Arch Cold reset has been triggered due to %s\n", reason);
+ omap4_prminst_global_cold_sw_reset(); /* never returns */
+
+ /* If we reached here - something bad went on.. */
+ BUG();
+
+ /* make the compiler happy */
+ return -EINTR;
+}
+
+/**
* get_achievable_state() - Provide achievable state
* @available_states: what states are available
* @req_min_state: what state is the minimum we'd like to hit
diff --git a/arch/arm/mach-omap2/prminst44xx.c b/arch/arm/mach-omap2/prminst44xx.c
index 6781783a72c..3486509a1c2 100644
--- a/arch/arm/mach-omap2/prminst44xx.c
+++ b/arch/arm/mach-omap2/prminst44xx.c
@@ -174,3 +174,20 @@ void omap4_prminst_global_warm_sw_reset(void)
OMAP4430_PRM_DEVICE_INST,
OMAP4_PRM_RSTCTRL_OFFSET);
}
+
+void omap4_prminst_global_cold_sw_reset(void)
+{
+ u32 v;
+
+ v = omap4_prm_read_inst_reg(OMAP4430_PRM_DEVICE_INST,
+ OMAP4_RM_RSTCTRL);
+ v |= OMAP4430_RST_GLOBAL_COLD_SW_MASK;
+ omap4_prm_write_inst_reg(v, OMAP4430_PRM_DEVICE_INST,
+ OMAP4_RM_RSTCTRL);
+
+ /* OCP barrier */
+ v = omap4_prm_read_inst_reg(OMAP4430_PRM_DEVICE_INST,
+ OMAP4_RM_RSTCTRL);
+}
+
+
diff --git a/arch/arm/mach-omap2/prminst44xx.h b/arch/arm/mach-omap2/prminst44xx.h
index 46f2efb3659..b5ff09f8cde 100644
--- a/arch/arm/mach-omap2/prminst44xx.h
+++ b/arch/arm/mach-omap2/prminst44xx.h
@@ -23,6 +23,8 @@ extern u32 omap4_prminst_rmw_inst_reg_bits(u32 mask, u32 bits, u8 part,
extern void omap4_prminst_global_warm_sw_reset(void);
+extern void omap4_prminst_global_cold_sw_reset(void);
+
extern int omap4_prminst_is_hardreset_asserted(u8 shift, u8 part, s16 inst,
u16 rstctrl_offs);
extern int omap4_prminst_assert_hardreset(u8 shift, u8 part, s16 inst,