summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-omap2/io.c18
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c3
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_3xxx_data.c3
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_44xx_data.c1
-rw-r--r--arch/arm/mach-omap2/wd_timer.c45
-rw-r--r--arch/arm/mach-omap2/wd_timer.h1
6 files changed, 51 insertions, 20 deletions
diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
index 065bd768987..fafcc35b970 100644
--- a/arch/arm/mach-omap2/io.c
+++ b/arch/arm/mach-omap2/io.c
@@ -363,24 +363,6 @@ static void __init omap_hwmod_init_postsetup(void)
#endif
omap_hwmod_for_each(_set_hwmod_postsetup_state, &postsetup_state);
- /*
- * Set the default postsetup state for unusual modules (like
- * MPU WDT).
- *
- * The postsetup_state is not actually used until
- * omap_hwmod_late_init(), so boards that desire full watchdog
- * coverage of kernel initialization can reprogram the
- * postsetup_state between the calls to
- * omap2_init_common_infra() and omap_sdrc_init().
- *
- * XXX ideally we could detect whether the MPU WDT was currently
- * enabled here and make this conditional
- */
- postsetup_state = _HWMOD_STATE_DISABLED;
- omap_hwmod_for_each_by_class("wd_timer",
- _set_hwmod_postsetup_state,
- &postsetup_state);
-
omap_pm_if_early_init();
}
diff --git a/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c b/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
index 5941f14130a..83eafd96eca 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
@@ -89,7 +89,8 @@ static struct omap_hwmod_class_sysconfig omap2xxx_wd_timer_sysc = {
struct omap_hwmod_class omap2xxx_wd_timer_hwmod_class = {
.name = "wd_timer",
.sysc = &omap2xxx_wd_timer_sysc,
- .pre_shutdown = &omap2_wd_timer_disable
+ .pre_shutdown = &omap2_wd_timer_disable,
+ .reset = &omap2_wd_timer_reset,
};
/*
diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
index 2432574123c..fd48797fa95 100644
--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
@@ -418,7 +418,8 @@ static struct omap_hwmod_class_sysconfig i2c_sysc = {
static struct omap_hwmod_class omap3xxx_wd_timer_hwmod_class = {
.name = "wd_timer",
.sysc = &omap3xxx_wd_timer_sysc,
- .pre_shutdown = &omap2_wd_timer_disable
+ .pre_shutdown = &omap2_wd_timer_disable,
+ .reset = &omap2_wd_timer_reset,
};
static struct omap_hwmod omap3xxx_wd_timer2_hwmod = {
diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
index c997c97c08b..950454a3fa3 100644
--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
@@ -3535,6 +3535,7 @@ static struct omap_hwmod_class omap44xx_wd_timer_hwmod_class = {
.name = "wd_timer",
.sysc = &omap44xx_wd_timer_sysc,
.pre_shutdown = &omap2_wd_timer_disable,
+ .reset = &omap2_wd_timer_reset,
};
/* wd_timer2 */
diff --git a/arch/arm/mach-omap2/wd_timer.c b/arch/arm/mach-omap2/wd_timer.c
index 4067669d96c..b2f1c67043a 100644
--- a/arch/arm/mach-omap2/wd_timer.c
+++ b/arch/arm/mach-omap2/wd_timer.c
@@ -14,6 +14,7 @@
#include <plat/omap_hwmod.h>
#include "wd_timer.h"
+#include "common.h"
/*
* In order to avoid any assumptions from bootloader regarding WDT
@@ -25,6 +26,8 @@
#define OMAP_WDT_WPS 0x34
#define OMAP_WDT_SPR 0x48
+/* Maximum microseconds to wait for OMAP module to softreset */
+#define MAX_MODULE_SOFTRESET_WAIT 10000
int omap2_wd_timer_disable(struct omap_hwmod *oh)
{
@@ -54,3 +57,45 @@ int omap2_wd_timer_disable(struct omap_hwmod *oh)
return 0;
}
+/**
+ * omap2_wdtimer_reset - reset and disable the WDTIMER IP block
+ * @oh: struct omap_hwmod *
+ *
+ * After the WDTIMER IP blocks are reset on OMAP2/3, we must also take
+ * care to execute the special watchdog disable sequence. This is
+ * because the watchdog is re-armed upon OCP softreset. (On OMAP4,
+ * this behavior was apparently changed and the watchdog is no longer
+ * re-armed after an OCP soft-reset.) Returns -ETIMEDOUT if the reset
+ * did not complete, or 0 upon success.
+ *
+ * XXX Most of this code should be moved to the omap_hwmod.c layer
+ * during a normal merge window. omap_hwmod_softreset() should be
+ * renamed to omap_hwmod_set_ocp_softreset(), and omap_hwmod_softreset()
+ * should call the hwmod _ocp_softreset() code.
+ */
+int omap2_wd_timer_reset(struct omap_hwmod *oh)
+{
+ int c = 0;
+
+ /* Write to the SOFTRESET bit */
+ omap_hwmod_softreset(oh);
+
+ /* Poll on RESETDONE bit */
+ omap_test_timeout((omap_hwmod_read(oh,
+ oh->class->sysc->syss_offs)
+ & SYSS_RESETDONE_MASK),
+ MAX_MODULE_SOFTRESET_WAIT, c);
+
+ if (oh->class->sysc->srst_udelay)
+ udelay(oh->class->sysc->srst_udelay);
+
+ if (c == MAX_MODULE_SOFTRESET_WAIT)
+ pr_warning("%s: %s: softreset failed (waited %d usec)\n",
+ __func__, oh->name, MAX_MODULE_SOFTRESET_WAIT);
+ else
+ pr_debug("%s: %s: softreset in %d usec\n", __func__,
+ oh->name, c);
+
+ return (c == MAX_MODULE_SOFTRESET_WAIT) ? -ETIMEDOUT :
+ omap2_wd_timer_disable(oh);
+}
diff --git a/arch/arm/mach-omap2/wd_timer.h b/arch/arm/mach-omap2/wd_timer.h
index e0054a2d550..f6bbba73b53 100644
--- a/arch/arm/mach-omap2/wd_timer.h
+++ b/arch/arm/mach-omap2/wd_timer.h
@@ -13,5 +13,6 @@
#include <plat/omap_hwmod.h>
extern int omap2_wd_timer_disable(struct omap_hwmod *oh);
+extern int omap2_wd_timer_reset(struct omap_hwmod *oh);
#endif