aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ppc/syslib/m8xx_wdt.c
diff options
context:
space:
mode:
authorMarcelo Tosatti <marcelo.tosatti@cyclades.com>2005-11-24 11:32:09 -0200
committerPaul Mackerras <paulus@samba.org>2006-01-09 14:50:51 +1100
commitfb64c2446b20bf0206a690e9e1df88b25ac421e6 (patch)
tree53d6e17957d29d881f8cff83ed952b4229d811bd /arch/ppc/syslib/m8xx_wdt.c
parent[PATCH] Fix code that saves NVGPRS in 32-bit signal frame (diff)
downloadlinux-dev-fb64c2446b20bf0206a690e9e1df88b25ac421e6.tar.xz
linux-dev-fb64c2446b20bf0206a690e9e1df88b25ac421e6.zip
[PATCH] ppc32: m8xx watchdog update
This updates m8xx_wdt as follows: 1) Remove now obsolete fpos check in the write() function. The driver is currently non functional due to this bug. 2) Use in/out macros for register access. 3) Allows m8xx_wdt to use a kernel timer instead of the builtin RTC/PIT for keep-alive trigger (which is responsible for servicing the watchdog until an userspace application takes over). For instance Cyclades PRxK boards (MPC 855T based) have a non-functional internal RTC/PIT unit. Behaviour for boards with RTC/PIT is unchaged. 4) The last change required moving the RTCSC register setting code to a weak function which can be overriden by board specific files. Otherwise the timer init code trashes the register making it impossible for m8xx_wdt to detect the situation. Signed-off-by: Marcelo Tosatti <marcelo.tosatti@cyclades.com> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/ppc/syslib/m8xx_wdt.c')
-rw-r--r--arch/ppc/syslib/m8xx_wdt.c92
1 files changed, 67 insertions, 25 deletions
diff --git a/arch/ppc/syslib/m8xx_wdt.c b/arch/ppc/syslib/m8xx_wdt.c
index a21632d37e5a..df6c9557b86a 100644
--- a/arch/ppc/syslib/m8xx_wdt.c
+++ b/arch/ppc/syslib/m8xx_wdt.c
@@ -19,6 +19,7 @@
#include <syslib/m8xx_wdt.h>
static int wdt_timeout;
+int m8xx_has_internal_rtc = 0;
static irqreturn_t m8xx_wdt_interrupt(int, void *, struct pt_regs *);
static struct irqaction m8xx_wdt_irqaction = {
@@ -45,35 +46,15 @@ static irqreturn_t m8xx_wdt_interrupt(int irq, void *dev, struct pt_regs *regs)
return IRQ_HANDLED;
}
-void __init m8xx_wdt_handler_install(bd_t * binfo)
+#define SYPCR_SWP 0x1
+#define SYPCR_SWE 0x4
+
+
+void __init m8xx_wdt_install_irq(volatile immap_t *imap, bd_t *binfo)
{
- volatile immap_t *imap = (volatile immap_t *)IMAP_ADDR;
u32 pitc;
- u32 sypcr;
u32 pitrtclk;
- sypcr = in_be32(&imap->im_siu_conf.sc_sypcr);
-
- if (!(sypcr & 0x04)) {
- printk(KERN_NOTICE "m8xx_wdt: wdt disabled (SYPCR: 0x%08X)\n",
- sypcr);
- return;
- }
-
- m8xx_wdt_reset();
-
- printk(KERN_NOTICE
- "m8xx_wdt: active wdt found (SWTC: 0x%04X, SWP: 0x%01X)\n",
- (sypcr >> 16), sypcr & 0x01);
-
- wdt_timeout = (sypcr >> 16) & 0xFFFF;
-
- if (!wdt_timeout)
- wdt_timeout = 0xFFFF;
-
- if (sypcr & 0x01)
- wdt_timeout *= 2048;
-
/*
* Fire trigger if half of the wdt ticked down
*/
@@ -98,6 +79,67 @@ void __init m8xx_wdt_handler_install(bd_t * binfo)
printk(KERN_NOTICE
"m8xx_wdt: keep-alive trigger installed (PITC: 0x%04X)\n", pitc);
+}
+
+static void m8xx_wdt_timer_func(unsigned long data);
+
+static struct timer_list m8xx_wdt_timer =
+ TIMER_INITIALIZER(m8xx_wdt_timer_func, 0, 0);
+
+void m8xx_wdt_stop_timer(void)
+{
+ del_timer(&m8xx_wdt_timer);
+}
+
+void m8xx_wdt_install_timer(void)
+{
+ m8xx_wdt_timer.expires = jiffies + (HZ/2);
+ add_timer(&m8xx_wdt_timer);
+}
+
+static void m8xx_wdt_timer_func(unsigned long data)
+{
+ m8xx_wdt_reset();
+ m8xx_wdt_install_timer();
+}
+
+void __init m8xx_wdt_handler_install(bd_t * binfo)
+{
+ volatile immap_t *imap = (volatile immap_t *)IMAP_ADDR;
+ u32 sypcr;
+
+ sypcr = in_be32(&imap->im_siu_conf.sc_sypcr);
+
+ if (!(sypcr & SYPCR_SWE)) {
+ printk(KERN_NOTICE "m8xx_wdt: wdt disabled (SYPCR: 0x%08X)\n",
+ sypcr);
+ return;
+ }
+
+ m8xx_wdt_reset();
+
+ printk(KERN_NOTICE
+ "m8xx_wdt: active wdt found (SWTC: 0x%04X, SWP: 0x%01X)\n",
+ (sypcr >> 16), sypcr & SYPCR_SWP);
+
+ wdt_timeout = (sypcr >> 16) & 0xFFFF;
+
+ if (!wdt_timeout)
+ wdt_timeout = 0xFFFF;
+
+ if (sypcr & SYPCR_SWP)
+ wdt_timeout *= 2048;
+
+ m8xx_has_internal_rtc = in_be16(&imap->im_sit.sit_rtcsc) & RTCSC_RTE;
+
+ /* if the internal RTC is off use a kernel timer */
+ if (!m8xx_has_internal_rtc) {
+ if (wdt_timeout < (binfo->bi_intfreq/HZ))
+ printk(KERN_ERR "m8xx_wdt: timeout too short for ktimer!\n");
+ m8xx_wdt_install_timer();
+ } else
+ m8xx_wdt_install_irq(imap, binfo);
+
wdt_timeout /= binfo->bi_intfreq;
}