MOXA linux-2.6.x / linux-2.6.19-uc1 from UC-7110-LX-BOOTLOADER-1.9_VERSION-4.2.tgz
[linux-2.6.19-moxart.git] / drivers / char / mcfwatchdog.c
blob15ce431b2227422ca6d80a643e639ed9c3cb0af3
1 /***************************************************************************/
3 /*
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)
9 * Changes:
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>
26 #include <linux/fs.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>
32 #include <asm/irq.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>
38 #include <asm/irq.h>
39 #include <asm/delay.h>
41 /***************************************************************************/
44 * Define the watchdog vector.
46 #ifdef CONFIG_M5272
47 #define IRQ_WATCHDOG 92
48 #define TIMEPOLL 100
49 #else
50 #define IRQ_WATCHDOG 250
51 #define TIMEPOLL HZ/100
52 #endif
54 #if defined(CONFIG_M5206e)
55 #define RESET_ON_SWTR
56 #endif
58 /***************************************************************************/
60 void watchdog_alive(unsigned long arg);
61 static irqreturn_t watchdog_timeout(int irq, void *dummy, struct pt_regs *fp);
63 #ifndef MODULE
64 extern void dump(struct pt_regs *fp);
65 #endif
68 * Data for registering the watchdog alive routine with ticker.
70 static struct timer_list watchdog_timerlist;
72 static int watchdog_overflows;
74 #ifdef CONFIG_OLDMASK
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 */
89 #endif
92 static struct file_operations watchdog_fops = {
93 .owner = THIS_MODULE,
96 static struct miscdevice watchdog_miscdev = {
97 .minor = WATCHDOG_MINOR,
98 .name = "watchdog",
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)
110 #ifdef CONFIG_M5272
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"
124 0x10 Timing SWT1
125 0x08 Timing SWT0
126 SWT|SWT1|SWT0
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
132 BMT1|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
137 #else
139 #ifdef RESET_ON_SWTR
140 *(mbar + MCFSIM_SYPCR) = 0xfe; // reset, 2^22
141 #else
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)
152 #ifdef CONFIG_M5272
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;
156 #else
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;
164 #if 0
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*/;
170 #endif
171 mcf_setimr(mcf_getimr() | MCFSIM_IMR_SWD);
172 #endif
173 del_timer(&watchdog_timerlist);
176 /***************************************************************************/
178 static int watchdog_notify_sys(struct notifier_block *this, unsigned long code,
179 void *unused)
181 if(code==SYS_DOWN || code==SYS_HALT) {
182 /* Turn the card off */
183 watchdog_disable();
185 If watchdog is set to 'reset', this function is useless...
186 When timer is disabled, reset will occour during reboot...
189 return NOTIFY_DONE;
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
206 #define TIMEDELAY 45
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) {
215 cli();
216 watchdog_disable();
217 mcf_setimr(mcf_getimr() | MCFSIM_IMR_SWD);
218 printk("%s(%d): Double WATCHDOG PANIC!!\n",
219 __FILE__, __LINE__);
220 for (;;)
224 swt_inwatchdog++;
225 swt_doit = TIMEDELAY - 8; /* 8 seconds grace */
226 printk("mcfwatchdog: expired last=%d(%d) jiffies=%d!\n",
227 swt_lastjiffies, swt_reference, jiffies);
228 #ifndef MODULE
229 dump(fp);
230 #endif
231 force_sig(SIGSEGV, current);
232 swt_inwatchdog = 0;
234 swt_lastjiffies = jiffies;
235 #else
237 #ifdef RESET_ON_SWTR
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");
244 #ifndef MODULE
245 dump(fp);
246 #endif
247 mcf_setimr(mcf_getimr() | MCFSIM_IMR_SWD);
248 HARD_RESET_NOW();
249 for (;;) ; // hang until reboot
250 } else {
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 */
257 return IRQ_HANDLED;
260 /***************************************************************************/
262 static int __init watchdog_init(void)
264 printk("mcfwatchdog: initializing at vector=%d\n", IRQ_WATCHDOG);
266 if(misc_register(&watchdog_miscdev))
267 return -ENODEV;
269 if(register_reboot_notifier(&watchdog_notifier)) {
270 printk("watchdog: cannot register reboot notifier\n");
271 return 1;
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);
282 #ifdef CONFIG_M5272
284 volatile unsigned long *icrp;
285 icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR4);
286 *icrp = (*icrp & 0x77707777) | 0x000E0000;
287 watchdog_enable();
289 #else /* CONFIG_M5272 */
291 volatile unsigned char *mbar = (volatile unsigned char *) MCF_MBAR;
292 unsigned char ch;
294 ch = *(mbar + MCFSIM_RSR);
295 printk("mcfwatchdog: Last reset was generated by %s\n",
296 (ch&0x80 ? "HRST": (ch&0x20 ? "SWTR":"")));
298 #ifdef RESET_ON_SWTR
299 // high priority just to make sure watchdog won't overflow.
300 *(mbar + MCFSIM_SWDICR) = MCFSIM_ICR_LEVEL1 | MCFSIM_ICR_PRI1;
301 #else
302 *(mbar + MCFSIM_SWDICR) = MCFSIM_ICR_LEVEL1 | MCFSIM_ICR_PRI3;
303 #endif
304 *(mbar + MCFSIM_SWIVR) = IRQ_WATCHDOG;
305 mcf_setimr(mcf_getimr() & ~MCFSIM_IMR_SWD);
306 watchdog_enable();
308 printk("mcfwatchdog: Coldfire watchdog is enabled, \"%s\" is generated on error\n",
309 ((*(mbar + MCFSIM_SYPCR) & 0x40)?
310 "Reset" : "Level7 interrupt"));
312 #ifdef MODULE
313 if(*(mbar + MCFSIM_SYPCR) & 0x40) {
314 printk("mcfwatchdog: Warning: If module is unloaded, Watchdog will reset card.\n");
316 #endif
318 #endif /* CONFIG_M5272 */
319 return 0;
322 /***************************************************************************/
324 static void __exit watchdog_exit(void)
326 #ifdef CONFIG_M5272
327 /* Reset watchdog counter */
328 *(volatile unsigned short *)(MCF_MBAR + MCFSIM_WCR) = 0x0000;
329 #else
330 volatile unsigned char *mbar = (volatile unsigned char *) MCF_MBAR;
331 *(mbar + MCFSIM_RSR) = 0; // clear reset cause
332 #endif
333 unregister_reboot_notifier(&watchdog_notifier);
334 misc_deregister(&watchdog_miscdev);
335 watchdog_disable();
336 printk("mcfwatchdog: Coldfire watchdog is disabled and unloaded\n");
339 /***************************************************************************/
341 void watchdog_alive(unsigned long arg)
343 #ifdef CONFIG_M5272
344 /* Reset watchdog counter */
345 *(volatile unsigned short *)(MCF_MBAR + MCFSIM_WCR) = 0x0000;
346 #else
347 volatile unsigned char *mbar = (volatile unsigned char *) MCF_MBAR;
348 *(mbar + MCFSIM_SWSR) = 0x55;
349 *(mbar + MCFSIM_SWSR) = 0xaa; // kick watchdog
350 #endif
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 /***************************************************************************/