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/config.h>
24 #include <linux/module.h>
25 #include <linux/miscdevice.h>
26 #include <linux/watchdog.h>
28 #include <linux/kernel.h>
29 #include <linux/sched.h>
30 #include <linux/param.h>
31 #include <linux/notifier.h>
32 #include <linux/reboot.h>
34 #include <asm/traps.h>
35 #include <asm/machdep.h>
36 #include <asm/coldfire.h>
37 #include <asm/mcftimer.h>
38 #include <asm/mcfsim.h>
40 #include <asm/delay.h>
42 /***************************************************************************/
45 * Define the watchdog vector.
48 #define IRQ_WATCHDOG 92
51 #define IRQ_WATCHDOG 250
52 #define TIMEPOLL HZ/100
55 #if defined(CONFIG_M5206e)
59 /***************************************************************************/
61 void watchdog_alive(unsigned long arg
);
62 static irqreturn_t
watchdog_timeout(int irq
, void *dummy
, struct pt_regs
*fp
);
65 extern void dump(struct pt_regs
*fp
);
69 * Data for registering the watchdog alive routine with ticker.
71 static struct timer_list watchdog_timerlist
;
73 static int watchdog_overflows
;
77 * The old mask 5307 has a broken watchdog timer. It will interrupt
78 * you regardless of writing to its "alive" register. It can still
79 * be useful but you have to play some tricks with it. This code
80 * supports a clock ticker timeout. If the right number of clock
81 * ticks are not counted then it is assumed that the watchdog saved
82 * us from a bad bus cycle.
84 #define SWTREF_COUNT 25
86 int swt_inwatchdog
= 0; /* Has watchdog expired */
87 int swt_doit
= 0; /* Start delay before tripping */
88 int swt_lastjiffies
= 0; /* Tick count at last watchdog */
89 int swt_reference
= SWTREF_COUNT
; /* Refereence tick count */
93 static struct file_operations watchdog_fops
= {
97 static struct miscdevice watchdog_miscdev
= {
98 .minor
= WATCHDOG_MINOR
,
100 .fops
= &watchdog_fops
,
103 /***************************************************************************/
106 * Software Watchdog Timer enable. Seems to be the same across all
107 * ColdFire CPU members.
109 void watchdog_enable(void)
112 *(volatile unsigned short *)(MCF_MBAR
+ MCFSIM_WRRR
) = 0x2001; // upper watchdog limit
113 *(volatile unsigned short *)(MCF_MBAR
+ MCFSIM_WIRR
) = 0x1000; // we don't do interrupts, just reset (o;
114 *(volatile unsigned short *)(MCF_MBAR
+ MCFSIM_WCR
) = 0x0000; // clear counter
115 #else /* CONFIG_M5272 */
116 volatile unsigned char *mbar
= (volatile unsigned char *) MCF_MBAR
;
117 *(mbar
+ MCFSIM_SWSR
) = 0x55;
118 *(mbar
+ MCFSIM_SWSR
) = 0xaa; // kick watchdog
121 SYPCR Can only be written once after system reset!
122 0x80 Software Watchdog, 0="Disable" / 1="Enable"
123 0x40 Software Watchdog, 0="level7 interrupt" / 1="reset"
124 0x20 Watchdog prescaled (SWP), 0="1" / 1="512"
128 000=2^9 001=2^11 010=2^13 011=2^15 / System Freq.
129 100=2^18 101=2^20 110=2^22 111=2^24 / System Freq.
130 0x04 Bus Timeout Monitor BMTE 0="Disable" / 1="Enable"
131 0x02 Bus Monitor Timing BMT1
132 0x01 Bus Monitor Timing BMT0
134 00=1024 01=512 10=256 11=128 system clocks
136 #ifdef CONFIG_OLDMASK
137 *(mbar
+ MCFSIM_SYPCR
) = 0xbe; // level 7 interrupt, 2^22
141 *(mbar
+ MCFSIM_SYPCR
) = 0xfe; // reset, 2^22
143 *(mbar
+ MCFSIM_SYPCR
) = 0xbe; // level 7 interrupt, 2^22
144 #endif /* RESET_ON_SWTR */
145 #endif /* CONFIG_OLDMASK */
146 #endif /* CONFIG_M5272 */
149 /***************************************************************************/
151 void watchdog_disable(void)
154 *(volatile unsigned short *)(MCF_MBAR
+ MCFSIM_WRRR
) = 0xFFFE;
155 *(volatile unsigned short *)(MCF_MBAR
+ MCFSIM_WIRR
) = 0x0000;
156 *(volatile unsigned short *)(MCF_MBAR
+ MCFSIM_WCR
) = 0x0000;
158 volatile unsigned char *mbar
= (volatile unsigned char *) MCF_MBAR
;
160 If watchdog is set to 'reset', this function is useless...
161 If timer is disabled, this reset will occour at once.
163 *(mbar
+ MCFSIM_SWSR
) = 0x55;
164 *(mbar
+ MCFSIM_SWSR
) = 0xaa;
167 SYPCR Can only be written once after system reset!
168 This will probably be ignored according to MCF5206E User Manual
170 *(mbar
+ MCFSIM_SYPCR
) = 0x00 /*0x3e*/;
172 mcf_setimr(mcf_getimr() | MCFSIM_IMR_SWD
);
174 del_timer(&watchdog_timerlist
);
177 /***************************************************************************/
179 static int watchdog_notify_sys(struct notifier_block
*this, unsigned long code
,
182 if(code
==SYS_DOWN
|| code
==SYS_HALT
) {
183 /* Turn the card off */
186 If watchdog is set to 'reset', this function is useless...
187 When timer is disabled, reset will occour during reboot...
193 static struct notifier_block watchdog_notifier
= {
194 .notifier_call
= watchdog_notify_sys
,
197 /***************************************************************************/
200 * Process a watchdog timeout interrupt. For a normal clean watchdog
201 * we just do a process dump. For old broken 5307 we need to verify
202 * if this was a real watchdog event or not...
204 static irqreturn_t
watchdog_timeout(int irq
, void *dummy
, struct pt_regs
*fp
)
206 #ifdef CONFIG_OLDMASK
209 * Debuging code for software watchdog. If we get in here
210 * and timer interrupt counts don't match we know that a
211 * bad external bus cycle must have locked the CPU.
213 if ((swt_doit
++ > TIMEDELAY
) &&
214 ((swt_lastjiffies
+ swt_reference
) > jiffies
)) {
215 if (swt_inwatchdog
) {
218 mcf_setimr(mcf_getimr() | MCFSIM_IMR_SWD
);
219 printk("%s(%d): Double WATCHDOG PANIC!!\n",
226 swt_doit
= TIMEDELAY
- 8; /* 8 seconds grace */
227 printk("mcfwatchdog: expired last=%d(%d) jiffies=%d!\n",
228 swt_lastjiffies
, swt_reference
, jiffies
);
232 force_sig(SIGSEGV
, current
);
235 swt_lastjiffies
= jiffies
;
239 /* nothing will be done... reset will occour */
240 #else /* RESET_ON_SWTR */
241 // lev7 interrupt is used.
242 if(++watchdog_overflows
>= 10) {
244 printk("mcfwatchdog: expired!\n");
248 mcf_setimr(mcf_getimr() | MCFSIM_IMR_SWD
);
250 for (;;) ; // hang until reboot
252 volatile unsigned char *mbar
= (volatile unsigned char *) MCF_MBAR
;
253 *(mbar
+ MCFSIM_SWSR
) = 0x55;
254 *(mbar
+ MCFSIM_SWSR
) = 0xaa; // kick watchdog
256 #endif /* RESET_ON_SWTR */
257 #endif /* CONFIG_OLDMASK */
261 /***************************************************************************/
263 static int __init
watchdog_init(void)
265 printk("mcfwatchdog: initializing at vector=%d\n", IRQ_WATCHDOG
);
267 if(misc_register(&watchdog_miscdev
))
270 if(register_reboot_notifier(&watchdog_notifier
)) {
271 printk("watchdog: cannot register reboot notifier\n");
275 request_irq(IRQ_WATCHDOG
, watchdog_timeout
, SA_INTERRUPT
,
276 "Watchdog Timer", &watchdog_miscdev
);
278 init_timer (&watchdog_timerlist
);
279 watchdog_timerlist
.function
= watchdog_alive
;
280 watchdog_timerlist
.expires
= (jiffies
+ 1);
281 add_timer(&watchdog_timerlist
);
285 volatile unsigned long *icrp
;
286 icrp
= (volatile unsigned long *) (MCF_MBAR
+ MCFSIM_ICR4
);
287 *icrp
= (*icrp
& 0x77707777) | 0x000E0000;
290 #else /* CONFIG_M5272 */
292 volatile unsigned char *mbar
= (volatile unsigned char *) MCF_MBAR
;
295 ch
= *(mbar
+ MCFSIM_RSR
);
296 printk("mcfwatchdog: Last reset was generated by %s\n",
297 (ch
&0x80 ? "HRST": (ch
&0x20 ? "SWTR":"")));
300 // high priority just to make sure watchdog won't overflow.
301 *(mbar
+ MCFSIM_SWDICR
) = MCFSIM_ICR_LEVEL1
| MCFSIM_ICR_PRI1
;
303 *(mbar
+ MCFSIM_SWDICR
) = MCFSIM_ICR_LEVEL1
| MCFSIM_ICR_PRI3
;
305 *(mbar
+ MCFSIM_SWIVR
) = IRQ_WATCHDOG
;
306 mcf_setimr(mcf_getimr() & ~MCFSIM_IMR_SWD
);
309 printk("mcfwatchdog: Coldfire watchdog is enabled, \"%s\" is generated on error\n",
310 ((*(mbar
+ MCFSIM_SYPCR
) & 0x40)?
311 "Reset" : "Level7 interrupt"));
314 if(*(mbar
+ MCFSIM_SYPCR
) & 0x40) {
315 printk("mcfwatchdog: Warning: If module is unloaded, Watchdog will reset card.\n");
319 #endif /* CONFIG_M5272 */
323 /***************************************************************************/
325 static void __exit
watchdog_exit(void)
328 /* Reset watchdog counter */
329 *(volatile unsigned short *)(MCF_MBAR
+ MCFSIM_WCR
) = 0x0000;
331 volatile unsigned char *mbar
= (volatile unsigned char *) MCF_MBAR
;
332 *(mbar
+ MCFSIM_RSR
) = 0; // clear reset cause
334 unregister_reboot_notifier(&watchdog_notifier
);
335 misc_deregister(&watchdog_miscdev
);
337 printk("mcfwatchdog: Coldfire watchdog is disabled and unloaded\n");
340 /***************************************************************************/
342 void watchdog_alive(unsigned long arg
)
345 /* Reset watchdog counter */
346 *(volatile unsigned short *)(MCF_MBAR
+ MCFSIM_WCR
) = 0x0000;
348 volatile unsigned char *mbar
= (volatile unsigned char *) MCF_MBAR
;
349 *(mbar
+ MCFSIM_SWSR
) = 0x55;
350 *(mbar
+ MCFSIM_SWSR
) = 0xaa; // kick watchdog
352 /* Re-arm the watchdog alive poll */
353 mod_timer(&watchdog_timerlist
, jiffies
+TIMEPOLL
);
354 watchdog_overflows
= 0;
357 /***************************************************************************/
359 module_init(watchdog_init
);
360 module_exit(watchdog_exit
);
362 MODULE_AUTHOR("Greg Ungerer");
363 MODULE_DESCRIPTION("Coldfire Watchdog Driver");
364 MODULE_LICENSE("GPL");
366 /***************************************************************************/