1 /****************************************************************************/
3 * SnapGear Hardware Watchdog driver (this WD cannot be stopped)
5 * Copyright 2004 David McCullough <davidm@snapgear.com>, All Rights Reserved.
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version
10 * 2 of the License, or (at your option) any later version.
12 * based on softdog.c by Alan Cox <alan@redhat.com>
14 /****************************************************************************/
16 #include <linux/module.h>
17 #include <linux/types.h>
18 #include <linux/kernel.h>
21 #include <linux/miscdevice.h>
22 #include <linux/watchdog.h>
23 #include <linux/smp_lock.h>
24 #include <linux/init.h>
25 #include <linux/reboot.h>
26 #include <asm/uaccess.h>
27 #include <asm/irq_regs.h>
29 /****************************************************************************/
31 * here we put the platform specific bits (headers/poke function)
34 #ifdef CONFIG_SH_SECUREEDGE5410
37 static inline void enable_dog(void) {}
39 static inline void poke_the_dog(void)
42 dummy
= * (volatile char *) 0xb8000000;
45 static inline void the_dog_is_dead(void) {}
47 #define HAS_HW_SERVICE 1
50 #ifdef CONFIG_MACH_IPD
53 static volatile char *dog_addr
= NULL
;
55 static inline void enable_dog(void)
57 dog_addr
= (char *) ioremap(0x20000000, 32);
60 static inline void poke_the_dog(void)
63 volatile char dummy
= *dog_addr
;
67 static inline void the_dog_is_dead(void) {}
69 #define HAS_HW_SERVICE 1
72 #if defined(CONFIG_MACH_ESS710) || defined(CONFIG_MACH_IVPN) || \
73 defined(CONFIG_MACH_SG560) || defined(CONFIG_MACH_SG580) || \
74 defined(CONFIG_MACH_SG640) || defined(CONFIG_MACH_SG720) || \
75 defined(CONFIG_MACH_SG590)
78 static inline void enable_dog(void)
80 *IXP4XX_GPIO_GPCLKR
&= 0xffff0000;
83 static inline void poke_the_dog(void)
85 *IXP4XX_GPIO_GPOUTR
^= 0x4000;
88 static inline void the_dog_is_dead(void) {}
90 #define HAS_HW_SERVICE 1
93 #if defined(CONFIG_MACH_SG8100)
96 static inline void enable_dog(void)
100 static inline void poke_the_dog(void)
102 *IXP4XX_GPIO_GPOUTR
^= 0x2000;
105 static inline void the_dog_is_dead(void) {}
107 #define HAS_HW_SERVICE 1
110 #if defined(CONFIG_MACH_SG565) || defined(CONFIG_MACH_SHIVA1100)
113 static volatile unsigned char *wdtcs2
;
115 static inline void enable_dog(void)
117 /* CS7 is watchdog alive. Set it to 8bit and writable */
118 *SG565_WATCHDOG_EXP_CS
= 0xbfff0003;
119 wdtcs2
= (volatile unsigned char *) ioremap(SG565_WATCHDOG_BASE_PHYS
, 512);
122 static inline void poke_the_dog(void)
128 static inline void the_dog_is_dead(void) {}
130 #define HAS_HW_SERVICE 1
133 #ifdef CONFIG_GEODEWATCHDOG
136 static inline void enable_dog(void) {}
138 static inline void poke_the_dog(void)
142 outl((v
| 0x200), 0x6410);
143 outl((v
& ~0x200), 0x6410);
146 static inline void the_dog_is_dead(void) {}
148 #define HAS_HW_SERVICE 1
151 #ifndef HAS_HW_SERVICE
152 static inline void enable_dog(void) {}
153 static inline void poke_the_dog(void) {}
154 static inline void the_dog_is_dead(void)
156 machine_restart(NULL
);
157 printk(KERN_CRIT
"snapdog: reboot failed!.\n");
161 /****************************************************************************/
163 static unsigned long snapdog_last
= 0;
164 static unsigned long snapdog_next
= 0;
165 static int snapdog_service_required
= 0;
166 static unsigned long snapdog_busy
= 0;
167 static int snapdog_kernel
= 0;
168 static int snapdog_timeout
= 60;
169 static int snapdog_ltimeout
= 300;
170 static int snapdog_use_long_timeout
= 0;
171 static int snapdog_quiet
= 0;
172 static int snapdog_warned
= 0;
173 static int snapdog_stackdump
= 64;
175 module_param(snapdog_kernel
, int, 0);
176 MODULE_PARM_DESC(snapdog_kernel
,
177 "Watchdog is kernel only (userland servicing not required)");
179 module_param(snapdog_timeout
, int, 0);
180 MODULE_PARM_DESC(snapdog_timeout
,
181 "Watchdog timeout for user service in seconds");
183 module_param(snapdog_ltimeout
, int, 0);
184 MODULE_PARM_DESC(snapdog_ltimeout
,
185 "Watchdog 'long' timeout for user service in seconds");
187 module_param(snapdog_stackdump
, int, 0);
188 MODULE_PARM_DESC(snapdog_stackdump
,
189 "Number of long words to dump from the stack");
191 /****************************************************************************/
193 * a really dumb stack dump, we may need better on some platforms
194 * at least this one is implemented, unlike dump_stack which is largely
198 static void snapdog_show_stack(struct pt_regs
*regs
)
201 unsigned long *addr
= &i
;
203 printk("Kernel stack:");
204 for (i
= 0; i
< snapdog_stackdump
; i
++) {
206 printk("\n%08lx:", (unsigned long) addr
);
207 printk(" 0x%08lx", *addr
++);
212 /****************************************************************************/
214 * Because we need to service this guy from deep in other more critical
215 * code, we export a function to do this that we can call where
218 * Also the watchdog never stops, it is always running. We must service
219 * it until we are opened, then we stop servicing it if we are not looked
220 * after appropriately.
222 * I know there are much more clever ways to code the following, but then
223 * who would understand it, let alone know it did the right thing when
228 snapdog_service(void)
230 struct pt_regs
*regs
;
231 int the_dog_is_alive
= 0;
233 if (snapdog_kernel
) {
234 the_dog_is_alive
= 1;
235 } else if (!snapdog_service_required
) {
236 the_dog_is_alive
= 1;
237 } else if (snapdog_next
< snapdog_last
) {
238 if (jiffies
< snapdog_next
|| jiffies
> snapdog_last
)
239 the_dog_is_alive
= 1;
240 } else if (jiffies
>= snapdog_last
&& jiffies
< snapdog_next
) {
241 the_dog_is_alive
= 1;
244 if (the_dog_is_alive
)
246 else if (!snapdog_warned
) {
248 printk(KERN_CRIT
"snapdog: expired, allowing system reboot.\n");
249 regs
= get_irq_regs();
252 snapdog_show_stack(regs
);
258 EXPORT_SYMBOL(snapdog_service
);
260 /****************************************************************************/
262 * bump the userland expiry
266 snapdog_user_service(void)
268 snapdog_last
= jiffies
;
269 if (snapdog_use_long_timeout
)
270 snapdog_next
= snapdog_last
+ HZ
* snapdog_ltimeout
;
272 snapdog_next
= snapdog_last
+ HZ
* snapdog_timeout
;
276 /****************************************************************************/
278 * Allow only one person to hold it open
282 snapdog_open(struct inode
*inode
, struct file
*file
)
284 if (test_and_set_bit(0, &snapdog_busy
))
288 snapdog_service_required
= 1;
289 if (snapdog_use_long_timeout
) {
290 /* Opening reverts to using short timeouts */
291 snapdog_use_long_timeout
= 0;
293 if (!snapdog_quiet
) {
294 printk(KERN_INFO
"snapdog: now using short timeouts.\n");
297 snapdog_user_service();
299 if (!snapdog_quiet
) {
300 printk(KERN_INFO
"snapdog: user servicing enabled (short=%d,long=%d).\n",
301 snapdog_timeout
, snapdog_ltimeout
);
305 /* Opening turns off quiet mode */
312 /****************************************************************************/
315 snapdog_release(struct inode
*inode
, struct file
*file
)
318 if (!snapdog_quiet
) {
319 if (!snapdog_service_required
) {
321 "snapdog: disabled user servicing of watchdog timer.\n");
322 } else if (snapdog_use_long_timeout
) {
324 "snapdog: device closed, watchdog will reboot!\n");
327 clear_bit(0, &snapdog_busy
);
333 /****************************************************************************/
336 snapdog_write(struct file
*file
, const char __user
*data
, size_t len
, loff_t
*ppos
)
338 /* Can't seek (pwrite) on this device */
339 if (*ppos
!= file
->f_pos
)
348 for (i
= 0; i
!= len
; i
++) {
350 if (get_user(c
, data
+ i
))
353 snapdog_service_required
= 0;
356 if (!snapdog_quiet
) {
357 printk(KERN_INFO
"snapdog: now using long timeouts.\n");
359 snapdog_use_long_timeout
= 1;
366 snapdog_user_service();
372 /****************************************************************************/
381 static struct watchdog_info ident
= {
382 .options
= WDIOF_MAGICCLOSE
,
383 .identity
= "HW/SW Watchdog for SnapGear",
388 return(-ENOIOCTLCMD
);
390 case WDIOC_GETSUPPORT
:
391 if (copy_to_user((struct watchdog_info __user
*) arg
, &ident
, sizeof(ident
)))
395 case WDIOC_GETSTATUS
:
396 case WDIOC_GETBOOTSTATUS
:
397 return(put_user(0, (int __user
*) arg
));
399 case WDIOC_KEEPALIVE
:
400 snapdog_user_service();
405 /****************************************************************************/
407 static struct file_operations snapdog_fops
= {
408 .owner
= THIS_MODULE
,
409 .write
= snapdog_write
,
410 .ioctl
= snapdog_ioctl
,
411 .open
= snapdog_open
,
412 .release
= snapdog_release
,
416 static struct miscdevice snapdog_miscdev
= {
417 .minor
= WATCHDOG_MINOR
,
419 .fops
= &snapdog_fops
,
422 /****************************************************************************/
424 static const char banner
[] __initdata
=
425 KERN_INFO
"snapdog: HW/SW watchdog timer for SnapGear/Others\n";
434 ret
= misc_register(&snapdog_miscdev
);
443 /****************************************************************************/
448 misc_deregister(&snapdog_miscdev
);
451 /****************************************************************************/
453 module_init(watchdog_init
);
454 module_exit(watchdog_exit
);
455 MODULE_AUTHOR("David McCullough <davidm@snapgear.com>");
456 MODULE_DESCRIPTION("Driver for SnapGear HW/SW watchdog timer(s)");
457 MODULE_LICENSE("GPL");
459 /****************************************************************************/