1 /***************************************************************************/
4 * linux/drivers/char/mcfwatchdog.c
6 * Copyright (C) 1999-2000, Greg Ungerer (gerg@snapgear.com)
7 * Copyright (C) 2000 Lineo Inc. (www.lineo.com)
10 * 10/28/2004 Christian Magnusson <mag@mag.cx>
11 * Bug: MCFSIM_SYPCR can only be written once after reset!
12 * MCF5272 support copied from 2.4.x driver.
13 * Reset on overflow. (For 5206e at least)
14 * Added module support.
15 * I have noticed that some flash-identification from mtd
16 * locks the processor too long, and therefor this watchdog
17 * has to be used as a module and started after mtd is done.
21 /***************************************************************************/
23 #include <linux/module.h>
24 #include <linux/miscdevice.h>
25 #include <linux/watchdog.h>
27 #include <linux/kernel.h>
28 #include <linux/sched.h>
29 #include <linux/param.h>
30 #include <linux/notifier.h>
31 #include <linux/reboot.h>
33 #include <asm/traps.h>
34 #include <asm/machdep.h>
35 #include <asm/coldfire.h>
36 #include <asm/mcftimer.h>
37 #include <asm/mcfsim.h>
39 #include <asm/delay.h>
41 /***************************************************************************/
44 * Define the watchdog vector.
47 #define IRQ_WATCHDOG 92
50 #define IRQ_WATCHDOG 250
51 #define TIMEPOLL HZ/100
54 #if defined(CONFIG_M5206e)
58 /***************************************************************************/
60 void watchdog_alive(unsigned long arg
);
61 static irqreturn_t
watchdog_timeout(int irq
, void *dummy
, struct pt_regs
*fp
);
64 extern void dump(struct pt_regs
*fp
);
68 * Data for registering the watchdog alive routine with ticker.
70 static struct timer_list watchdog_timerlist
;
72 static int watchdog_overflows
;
76 * The old mask 5307 has a broken watchdog timer. It will interrupt
77 * you regardless of writing to its "alive" register. It can still
78 * be useful but you have to play some tricks with it. This code
79 * supports a clock ticker timeout. If the right number of clock
80 * ticks are not counted then it is assumed that the watchdog saved
81 * us from a bad bus cycle.
83 #define SWTREF_COUNT 25
85 int swt_inwatchdog
= 0; /* Has watchdog expired */
86 int swt_doit
= 0; /* Start delay before tripping */
87 int swt_lastjiffies
= 0; /* Tick count at last watchdog */
88 int swt_reference
= SWTREF_COUNT
; /* Refereence tick count */
92 static struct file_operations watchdog_fops
= {
96 static struct miscdevice watchdog_miscdev
= {
97 .minor
= WATCHDOG_MINOR
,
99 .fops
= &watchdog_fops
,
102 /***************************************************************************/
105 * Software Watchdog Timer enable. Seems to be the same across all
106 * ColdFire CPU members.
108 void watchdog_enable(void)
111 *(volatile unsigned short *)(MCF_MBAR
+ MCFSIM_WRRR
) = 0x2001; // upper watchdog limit
112 *(volatile unsigned short *)(MCF_MBAR
+ MCFSIM_WIRR
) = 0x1000; // we don't do interrupts, just reset (o;
113 *(volatile unsigned short *)(MCF_MBAR
+ MCFSIM_WCR
) = 0x0000; // clear counter
114 #else /* CONFIG_M5272 */
115 volatile unsigned char *mbar
= (volatile unsigned char *) MCF_MBAR
;
116 *(mbar
+ MCFSIM_SWSR
) = 0x55;
117 *(mbar
+ MCFSIM_SWSR
) = 0xaa; // kick watchdog
120 SYPCR Can only be written once after system reset!
121 0x80 Software Watchdog, 0="Disable" / 1="Enable"
122 0x40 Software Watchdog, 0="level7 interrupt" / 1="reset"
123 0x20 Watchdog prescaled (SWP), 0="1" / 1="512"
127 000=2^9 001=2^11 010=2^13 011=2^15 / System Freq.
128 100=2^18 101=2^20 110=2^22 111=2^24 / System Freq.
129 0x04 Bus Timeout Monitor BMTE 0="Disable" / 1="Enable"
130 0x02 Bus Monitor Timing BMT1
131 0x01 Bus Monitor Timing BMT0
133 00=1024 01=512 10=256 11=128 system clocks
135 #ifdef CONFIG_OLDMASK
136 *(mbar
+ MCFSIM_SYPCR
) = 0xbe; // level 7 interrupt, 2^22
140 *(mbar
+ MCFSIM_SYPCR
) = 0xfe; // reset, 2^22
142 *(mbar
+ MCFSIM_SYPCR
) = 0xbe; // level 7 interrupt, 2^22
143 #endif /* RESET_ON_SWTR */
144 #endif /* CONFIG_OLDMASK */
145 #endif /* CONFIG_M5272 */
148 /***************************************************************************/
150 void watchdog_disable(void)
153 *(volatile unsigned short *)(MCF_MBAR
+ MCFSIM_WRRR
) = 0xFFFE;
154 *(volatile unsigned short *)(MCF_MBAR
+ MCFSIM_WIRR
) = 0x0000;
155 *(volatile unsigned short *)(MCF_MBAR
+ MCFSIM_WCR
) = 0x0000;
157 volatile unsigned char *mbar
= (volatile unsigned char *) MCF_MBAR
;
159 If watchdog is set to 'reset', this function is useless...
160 If timer is disabled, this reset will occour at once.
162 *(mbar
+ MCFSIM_SWSR
) = 0x55;
163 *(mbar
+ MCFSIM_SWSR
) = 0xaa;
166 SYPCR Can only be written once after system reset!
167 This will probably be ignored according to MCF5206E User Manual
169 *(mbar
+ MCFSIM_SYPCR
) = 0x00 /*0x3e*/;
171 mcf_setimr(mcf_getimr() | MCFSIM_IMR_SWD
);
173 del_timer(&watchdog_timerlist
);
176 /***************************************************************************/
178 static int watchdog_notify_sys(struct notifier_block
*this, unsigned long code
,
181 if(code
==SYS_DOWN
|| code
==SYS_HALT
) {
182 /* Turn the card off */
185 If watchdog is set to 'reset', this function is useless...
186 When timer is disabled, reset will occour during reboot...
192 static struct notifier_block watchdog_notifier
= {
193 .notifier_call
= watchdog_notify_sys
,
196 /***************************************************************************/
199 * Process a watchdog timeout interrupt. For a normal clean watchdog
200 * we just do a process dump. For old broken 5307 we need to verify
201 * if this was a real watchdog event or not...
203 static irqreturn_t
watchdog_timeout(int irq
, void *dummy
, struct pt_regs
*fp
)
205 #ifdef CONFIG_OLDMASK
208 * Debuging code for software watchdog. If we get in here
209 * and timer interrupt counts don't match we know that a
210 * bad external bus cycle must have locked the CPU.
212 if ((swt_doit
++ > TIMEDELAY
) &&
213 ((swt_lastjiffies
+ swt_reference
) > jiffies
)) {
214 if (swt_inwatchdog
) {
217 mcf_setimr(mcf_getimr() | MCFSIM_IMR_SWD
);
218 printk("%s(%d): Double WATCHDOG PANIC!!\n",
225 swt_doit
= TIMEDELAY
- 8; /* 8 seconds grace */
226 printk("mcfwatchdog: expired last=%d(%d) jiffies=%d!\n",
227 swt_lastjiffies
, swt_reference
, jiffies
);
231 force_sig(SIGSEGV
, current
);
234 swt_lastjiffies
= jiffies
;
238 /* nothing will be done... reset will occour */
239 #else /* RESET_ON_SWTR */
240 // lev7 interrupt is used.
241 if(++watchdog_overflows
>= 10) {
243 printk("mcfwatchdog: expired!\n");
247 mcf_setimr(mcf_getimr() | MCFSIM_IMR_SWD
);
249 for (;;) ; // hang until reboot
251 volatile unsigned char *mbar
= (volatile unsigned char *) MCF_MBAR
;
252 *(mbar
+ MCFSIM_SWSR
) = 0x55;
253 *(mbar
+ MCFSIM_SWSR
) = 0xaa; // kick watchdog
255 #endif /* RESET_ON_SWTR */
256 #endif /* CONFIG_OLDMASK */
260 /***************************************************************************/
262 static int __init
watchdog_init(void)
264 printk("mcfwatchdog: initializing at vector=%d\n", IRQ_WATCHDOG
);
266 if(misc_register(&watchdog_miscdev
))
269 if(register_reboot_notifier(&watchdog_notifier
)) {
270 printk("watchdog: cannot register reboot notifier\n");
274 request_irq(IRQ_WATCHDOG
, watchdog_timeout
, SA_INTERRUPT
,
275 "Watchdog Timer", &watchdog_miscdev
);
277 init_timer (&watchdog_timerlist
);
278 watchdog_timerlist
.function
= watchdog_alive
;
279 watchdog_timerlist
.expires
= (jiffies
+ 1);
280 add_timer(&watchdog_timerlist
);
284 volatile unsigned long *icrp
;
285 icrp
= (volatile unsigned long *) (MCF_MBAR
+ MCFSIM_ICR4
);
286 *icrp
= (*icrp
& 0x77707777) | 0x000E0000;
289 #else /* CONFIG_M5272 */
291 volatile unsigned char *mbar
= (volatile unsigned char *) MCF_MBAR
;
294 ch
= *(mbar
+ MCFSIM_RSR
);
295 printk("mcfwatchdog: Last reset was generated by %s\n",
296 (ch
&0x80 ? "HRST": (ch
&0x20 ? "SWTR":"")));
299 // high priority just to make sure watchdog won't overflow.
300 *(mbar
+ MCFSIM_SWDICR
) = MCFSIM_ICR_LEVEL1
| MCFSIM_ICR_PRI1
;
302 *(mbar
+ MCFSIM_SWDICR
) = MCFSIM_ICR_LEVEL1
| MCFSIM_ICR_PRI3
;
304 *(mbar
+ MCFSIM_SWIVR
) = IRQ_WATCHDOG
;
305 mcf_setimr(mcf_getimr() & ~MCFSIM_IMR_SWD
);
308 printk("mcfwatchdog: Coldfire watchdog is enabled, \"%s\" is generated on error\n",
309 ((*(mbar
+ MCFSIM_SYPCR
) & 0x40)?
310 "Reset" : "Level7 interrupt"));
313 if(*(mbar
+ MCFSIM_SYPCR
) & 0x40) {
314 printk("mcfwatchdog: Warning: If module is unloaded, Watchdog will reset card.\n");
318 #endif /* CONFIG_M5272 */
322 /***************************************************************************/
324 static void __exit
watchdog_exit(void)
327 /* Reset watchdog counter */
328 *(volatile unsigned short *)(MCF_MBAR
+ MCFSIM_WCR
) = 0x0000;
330 volatile unsigned char *mbar
= (volatile unsigned char *) MCF_MBAR
;
331 *(mbar
+ MCFSIM_RSR
) = 0; // clear reset cause
333 unregister_reboot_notifier(&watchdog_notifier
);
334 misc_deregister(&watchdog_miscdev
);
336 printk("mcfwatchdog: Coldfire watchdog is disabled and unloaded\n");
339 /***************************************************************************/
341 void watchdog_alive(unsigned long arg
)
344 /* Reset watchdog counter */
345 *(volatile unsigned short *)(MCF_MBAR
+ MCFSIM_WCR
) = 0x0000;
347 volatile unsigned char *mbar
= (volatile unsigned char *) MCF_MBAR
;
348 *(mbar
+ MCFSIM_SWSR
) = 0x55;
349 *(mbar
+ MCFSIM_SWSR
) = 0xaa; // kick watchdog
351 /* Re-arm the watchdog alive poll */
352 mod_timer(&watchdog_timerlist
, jiffies
+TIMEPOLL
);
353 watchdog_overflows
= 0;
356 /***************************************************************************/
358 module_init(watchdog_init
);
359 module_exit(watchdog_exit
);
361 MODULE_AUTHOR("Greg Ungerer");
362 MODULE_DESCRIPTION("Coldfire Watchdog Driver");
363 MODULE_LICENSE("GPL");
365 /***************************************************************************/