aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorPaul Walmsley <paul@pwsan.com>2010-12-21 17:39:15 -0500
committerPaul Walmsley <paul@pwsan.com>2010-12-21 21:57:40 -0500
commitff2516fbef20ed9edd9cc2fc8b8b48d5cb5a932f (patch)
tree29cc55d6a7c6e7b255a6d32e4590377ce9983123 /arch
parent81fbc5ef9b22df2e2198dd0c530719a263a8d1c5 (diff)
OMAP2+: wd_timer: disable on boot via hwmod postsetup mechanism
The OMAP watchdog timer IP blocks require a specific set of register writes to occur before they will be disabled[1], even if the device clocks appear to be disabled in the CM_*CLKEN registers. In the MPU watchdog case, failure to execute this reset sequence will eventually cause the watchdog to reset the OMAP unexpectedly. Previously, the code to disable this watchdog was manually called from mach-omap2/devices.c during device initialization. This causes the watchdog to be unconditionally disabled for a portion of kernel initialization. This should be controllable by the board-*.c files, since some system integrators will want full watchdog coverage of kernel initialization. Also, the watchdog disable code was not connected to the hwmod shutdown code. This means that calling omap_hwmod_shutdown() will not, in fact, disable the watchdog, and the goal of omap_hwmod_shutdown() is to be able to shutdown any on-chip OMAP device. To resolve the latter problem, populate the pre_shutdown pointer in the watchdog timer hwmod classes with a function that executes the watchdog shutdown sequence. This allows the hwmod code to fully disable the watchdog. Then, to allow some board files to support watchdog coverage throughout kernel initialization, add common code to mach-omap2/io.c to cause the MPU watchdog to be disabled on boot unless a board file specifically requests it to remain enabled. Board files can do this by changing the watchdog timer hwmod's postsetup state between the omap2_init_common_infrastructure() and omap2_init_common_devices() function calls. 1. OMAP34xx Multimedia Device Silicon Revision 3.1.x Rev. ZH [SWPU222H], Section 16.4.3.6, "Start/Stop Sequence for WDTs (Using WDTi.WSPR Register)" Signed-off-by: Paul Walmsley <paul@pwsan.com> Cc: BenoƮt Cousson <b-cousson@ti.com> Cc: Kevin Hilman <khilman@deeprootsystems.com> Cc: Charulatha Varadarajan <charu@ti.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-omap2/devices.c15
-rw-r--r--arch/arm/mach-omap2/io.c18
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_2420_data.c6
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_2430_data.c6
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_3xxx_data.c6
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_44xx_data.c6
-rw-r--r--arch/arm/mach-omap2/wd_timer.c16
7 files changed, 35 insertions, 38 deletions
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
index 9221a486b51f..381f4eb92352 100644
--- a/arch/arm/mach-omap2/devices.c
+++ b/arch/arm/mach-omap2/devices.c
@@ -33,7 +33,6 @@
33 33
34#include "mux.h" 34#include "mux.h"
35#include "control.h" 35#include "control.h"
36#include "wd_timer.h"
37 36
38#if defined(CONFIG_VIDEO_OMAP2) || defined(CONFIG_VIDEO_OMAP2_MODULE) 37#if defined(CONFIG_VIDEO_OMAP2) || defined(CONFIG_VIDEO_OMAP2_MODULE)
39 38
@@ -956,26 +955,12 @@ static inline void omap_init_vout(void) {}
956 955
957/*-------------------------------------------------------------------------*/ 956/*-------------------------------------------------------------------------*/
958 957
959static int omap2_disable_wdt(struct omap_hwmod *oh, void *unused)
960{
961 return omap2_wd_timer_disable(oh);
962}
963
964static void __init omap_disable_wdt(void)
965{
966 if (cpu_class_is_omap2())
967 omap_hwmod_for_each_by_class("wd_timer",
968 omap2_disable_wdt, NULL);
969 return;
970}
971
972static int __init omap2_init_devices(void) 958static int __init omap2_init_devices(void)
973{ 959{
974 /* 960 /*
975 * please keep these calls, and their implementations above, 961 * please keep these calls, and their implementations above,
976 * in alphabetical order so they're easier to sort through. 962 * in alphabetical order so they're easier to sort through.
977 */ 963 */
978 omap_disable_wdt();
979 omap_hsmmc_reset(); 964 omap_hsmmc_reset();
980 omap_init_audio(); 965 omap_init_audio();
981 omap_init_camera(); 966 omap_init_camera();
diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
index 7362b69a154d..d87e23a24dcd 100644
--- a/arch/arm/mach-omap2/io.c
+++ b/arch/arm/mach-omap2/io.c
@@ -361,6 +361,24 @@ void __init omap2_init_common_infrastructure(void)
361#endif 361#endif
362 omap_hwmod_for_each(_set_hwmod_postsetup_state, &postsetup_state); 362 omap_hwmod_for_each(_set_hwmod_postsetup_state, &postsetup_state);
363 363
364 /*
365 * Set the default postsetup state for unusual modules (like
366 * MPU WDT).
367 *
368 * The postsetup_state is not actually used until
369 * omap_hwmod_late_init(), so boards that desire full watchdog
370 * coverage of kernel initialization can reprogram the
371 * postsetup_state between the calls to
372 * omap2_init_common_infra() and omap2_init_common_devices().
373 *
374 * XXX ideally we could detect whether the MPU WDT was currently
375 * enabled here and make this conditional
376 */
377 postsetup_state = _HWMOD_STATE_DISABLED;
378 omap_hwmod_for_each_by_class("wd_timer",
379 _set_hwmod_postsetup_state,
380 &postsetup_state);
381
364 omap_pm_if_early_init(); 382 omap_pm_if_early_init();
365 383
366 if (cpu_is_omap2420()) 384 if (cpu_is_omap2420())
diff --git a/arch/arm/mach-omap2/omap_hwmod_2420_data.c b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
index 42606f6b0cdf..b85c630b64d6 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2420_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
@@ -23,6 +23,7 @@
23 23
24#include "cm-regbits-24xx.h" 24#include "cm-regbits-24xx.h"
25#include "prm-regbits-24xx.h" 25#include "prm-regbits-24xx.h"
26#include "wd_timer.h"
26 27
27/* 28/*
28 * OMAP2420 hardware module integration data 29 * OMAP2420 hardware module integration data
@@ -312,8 +313,9 @@ static struct omap_hwmod_class_sysconfig omap2420_wd_timer_sysc = {
312}; 313};
313 314
314static struct omap_hwmod_class omap2420_wd_timer_hwmod_class = { 315static struct omap_hwmod_class omap2420_wd_timer_hwmod_class = {
315 .name = "wd_timer", 316 .name = "wd_timer",
316 .sysc = &omap2420_wd_timer_sysc, 317 .sysc = &omap2420_wd_timer_sysc,
318 .pre_shutdown = &omap2_wd_timer_disable
317}; 319};
318 320
319/* wd_timer2 */ 321/* wd_timer2 */
diff --git a/arch/arm/mach-omap2/omap_hwmod_2430_data.c b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
index 3315d241feef..3c2c724796a2 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2430_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
@@ -23,6 +23,7 @@
23 23
24#include "prm-regbits-24xx.h" 24#include "prm-regbits-24xx.h"
25#include "cm-regbits-24xx.h" 25#include "cm-regbits-24xx.h"
26#include "wd_timer.h"
26 27
27/* 28/*
28 * OMAP2430 hardware module integration data 29 * OMAP2430 hardware module integration data
@@ -311,8 +312,9 @@ static struct omap_hwmod_class_sysconfig omap2430_wd_timer_sysc = {
311}; 312};
312 313
313static struct omap_hwmod_class omap2430_wd_timer_hwmod_class = { 314static struct omap_hwmod_class omap2430_wd_timer_hwmod_class = {
314 .name = "wd_timer", 315 .name = "wd_timer",
315 .sysc = &omap2430_wd_timer_sysc, 316 .sysc = &omap2430_wd_timer_sysc,
317 .pre_shutdown = &omap2_wd_timer_disable
316}; 318};
317 319
318/* wd_timer2 */ 320/* wd_timer2 */
diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
index d5acb63ba9e0..89a943e9459c 100644
--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
@@ -26,6 +26,7 @@
26 26
27#include "prm-regbits-34xx.h" 27#include "prm-regbits-34xx.h"
28#include "cm-regbits-34xx.h" 28#include "cm-regbits-34xx.h"
29#include "wd_timer.h"
29 30
30/* 31/*
31 * OMAP3xxx hardware module integration data 32 * OMAP3xxx hardware module integration data
@@ -423,8 +424,9 @@ static struct omap_hwmod_class_sysconfig i2c_sysc = {
423}; 424};
424 425
425static struct omap_hwmod_class omap3xxx_wd_timer_hwmod_class = { 426static struct omap_hwmod_class omap3xxx_wd_timer_hwmod_class = {
426 .name = "wd_timer", 427 .name = "wd_timer",
427 .sysc = &omap3xxx_wd_timer_sysc, 428 .sysc = &omap3xxx_wd_timer_sysc,
429 .pre_shutdown = &omap2_wd_timer_disable
428}; 430};
429 431
430/* wd_timer2 */ 432/* wd_timer2 */
diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
index f9778fba8322..f136f7f2274c 100644
--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
@@ -29,6 +29,7 @@
29 29
30#include "cm.h" 30#include "cm.h"
31#include "prm-regbits-44xx.h" 31#include "prm-regbits-44xx.h"
32#include "wd_timer.h"
32 33
33/* Base offset for all OMAP4 interrupts external to MPUSS */ 34/* Base offset for all OMAP4 interrupts external to MPUSS */
34#define OMAP44XX_IRQ_GIC_START 32 35#define OMAP44XX_IRQ_GIC_START 32
@@ -728,8 +729,9 @@ static struct omap_hwmod_class_sysconfig omap44xx_uart_sysc = {
728}; 729};
729 730
730static struct omap_hwmod_class omap44xx_wd_timer_hwmod_class = { 731static struct omap_hwmod_class omap44xx_wd_timer_hwmod_class = {
731 .name = "wd_timer", 732 .name = "wd_timer",
732 .sysc = &omap44xx_wd_timer_sysc, 733 .sysc = &omap44xx_wd_timer_sysc,
734 .pre_shutdown = &omap2_wd_timer_disable
733}; 735};
734 736
735/* wd_timer2 */ 737/* wd_timer2 */
diff --git a/arch/arm/mach-omap2/wd_timer.c b/arch/arm/mach-omap2/wd_timer.c
index 06c256d38988..b0c4907ab3ca 100644
--- a/arch/arm/mach-omap2/wd_timer.c
+++ b/arch/arm/mach-omap2/wd_timer.c
@@ -27,7 +27,6 @@
27int omap2_wd_timer_disable(struct omap_hwmod *oh) 27int omap2_wd_timer_disable(struct omap_hwmod *oh)
28{ 28{
29 void __iomem *base; 29 void __iomem *base;
30 int ret;
31 30
32 if (!oh) { 31 if (!oh) {
33 pr_err("%s: Could not look up wdtimer_hwmod\n", __func__); 32 pr_err("%s: Could not look up wdtimer_hwmod\n", __func__);
@@ -41,14 +40,6 @@ int omap2_wd_timer_disable(struct omap_hwmod *oh)
41 return -EINVAL; 40 return -EINVAL;
42 } 41 }
43 42
44 /* Enable the clocks before accessing the WDT registers */
45 ret = omap_hwmod_enable(oh);
46 if (ret) {
47 pr_err("%s: Could not enable clocks for %s\n",
48 oh->name, __func__);
49 return ret;
50 }
51
52 /* sequence required to disable watchdog */ 43 /* sequence required to disable watchdog */
53 __raw_writel(0xAAAA, base + OMAP_WDT_SPR); 44 __raw_writel(0xAAAA, base + OMAP_WDT_SPR);
54 while (__raw_readl(base + OMAP_WDT_WPS) & 0x10) 45 while (__raw_readl(base + OMAP_WDT_WPS) & 0x10)
@@ -58,11 +49,6 @@ int omap2_wd_timer_disable(struct omap_hwmod *oh)
58 while (__raw_readl(base + OMAP_WDT_WPS) & 0x10) 49 while (__raw_readl(base + OMAP_WDT_WPS) & 0x10)
59 cpu_relax(); 50 cpu_relax();
60 51
61 ret = omap_hwmod_idle(oh); 52 return 0;
62 if (ret)
63 pr_err("%s: Could not disable clocks for %s\n",
64 oh->name, __func__);
65
66 return ret;
67} 53}
68 54