]> err.no Git - linux-2.6/blob - drivers/watchdog/w83977f_wdt.c
Merge Linus' latest into master
[linux-2.6] / drivers / watchdog / w83977f_wdt.c
1 /*
2  *      W83977F Watchdog Timer Driver for Winbond W83977F I/O Chip
3  *
4  *      (c) Copyright 2005  Jose Goncalves <jose.goncalves@inov.pt>
5  *
6  *      Based on w83877f_wdt.c by Scott Jennings,
7  *           and wdt977.c by Woody Suwalski
8  *
9  *                      -----------------------
10  *
11  *      This program is free software; you can redistribute it and/or
12  *      modify it under the terms of the GNU General Public License
13  *      as published by the Free Software Foundation; either version
14  *      2 of the License, or (at your option) any later version.
15  *
16  */
17
18 #include <linux/module.h>
19 #include <linux/moduleparam.h>
20 #include <linux/types.h>
21 #include <linux/kernel.h>
22 #include <linux/fs.h>
23 #include <linux/miscdevice.h>
24 #include <linux/init.h>
25 #include <linux/ioport.h>
26 #include <linux/watchdog.h>
27 #include <linux/notifier.h>
28 #include <linux/reboot.h>
29 #include <linux/uaccess.h>
30 #include <linux/io.h>
31
32 #include <asm/system.h>
33
34 #define WATCHDOG_VERSION  "1.00"
35 #define WATCHDOG_NAME     "W83977F WDT"
36 #define PFX WATCHDOG_NAME ": "
37 #define DRIVER_VERSION    WATCHDOG_NAME " driver, v" WATCHDOG_VERSION "\n"
38
39 #define IO_INDEX_PORT     0x3F0
40 #define IO_DATA_PORT      (IO_INDEX_PORT+1)
41
42 #define UNLOCK_DATA       0x87
43 #define LOCK_DATA         0xAA
44 #define DEVICE_REGISTER   0x07
45
46 #define DEFAULT_TIMEOUT   45            /* default timeout in seconds */
47
48 static  int timeout = DEFAULT_TIMEOUT;
49 static  int timeoutW;                   /* timeout in watchdog counter units */
50 static  unsigned long timer_alive;
51 static  int testmode;
52 static  char expect_close;
53 static  DEFINE_SPINLOCK(spinlock);
54
55 module_param(timeout, int, 0);
56 MODULE_PARM_DESC(timeout,
57                 "Watchdog timeout in seconds (15..7635), default="
58                                 __MODULE_STRING(DEFAULT_TIMEOUT) ")");
59 module_param(testmode, int, 0);
60 MODULE_PARM_DESC(testmode, "Watchdog testmode (1 = no reboot), default=0");
61
62 static int nowayout = WATCHDOG_NOWAYOUT;
63 module_param(nowayout, int, 0);
64 MODULE_PARM_DESC(nowayout,
65                 "Watchdog cannot be stopped once started (default="
66                                 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
67
68 /*
69  * Start the watchdog
70  */
71
72 static int wdt_start(void)
73 {
74         unsigned long flags;
75
76         spin_lock_irqsave(&spinlock, flags);
77
78         /* Unlock the SuperIO chip */
79         outb_p(UNLOCK_DATA, IO_INDEX_PORT);
80         outb_p(UNLOCK_DATA, IO_INDEX_PORT);
81
82         /*
83          * Select device Aux2 (device=8) to set watchdog regs F2, F3 and F4.
84          * F2 has the timeout in watchdog counter units.
85          * F3 is set to enable watchdog LED blink at timeout.
86          * F4 is used to just clear the TIMEOUT'ed state (bit 0).
87          */
88         outb_p(DEVICE_REGISTER, IO_INDEX_PORT);
89         outb_p(0x08, IO_DATA_PORT);
90         outb_p(0xF2, IO_INDEX_PORT);
91         outb_p(timeoutW, IO_DATA_PORT);
92         outb_p(0xF3, IO_INDEX_PORT);
93         outb_p(0x08, IO_DATA_PORT);
94         outb_p(0xF4, IO_INDEX_PORT);
95         outb_p(0x00, IO_DATA_PORT);
96
97         /* Set device Aux2 active */
98         outb_p(0x30, IO_INDEX_PORT);
99         outb_p(0x01, IO_DATA_PORT);
100
101         /*
102          * Select device Aux1 (dev=7) to set GP16 as the watchdog output
103          * (in reg E6) and GP13 as the watchdog LED output (in reg E3).
104          * Map GP16 at pin 119.
105          * In test mode watch the bit 0 on F4 to indicate "triggered" or
106          * check watchdog LED on SBC.
107          */
108         outb_p(DEVICE_REGISTER, IO_INDEX_PORT);
109         outb_p(0x07, IO_DATA_PORT);
110         if (!testmode) {
111                 unsigned pin_map;
112
113                 outb_p(0xE6, IO_INDEX_PORT);
114                 outb_p(0x0A, IO_DATA_PORT);
115                 outb_p(0x2C, IO_INDEX_PORT);
116                 pin_map = inb_p(IO_DATA_PORT);
117                 pin_map |= 0x10;
118                 pin_map &= ~(0x20);
119                 outb_p(0x2C, IO_INDEX_PORT);
120                 outb_p(pin_map, IO_DATA_PORT);
121         }
122         outb_p(0xE3, IO_INDEX_PORT);
123         outb_p(0x08, IO_DATA_PORT);
124
125         /* Set device Aux1 active */
126         outb_p(0x30, IO_INDEX_PORT);
127         outb_p(0x01, IO_DATA_PORT);
128
129         /* Lock the SuperIO chip */
130         outb_p(LOCK_DATA, IO_INDEX_PORT);
131
132         spin_unlock_irqrestore(&spinlock, flags);
133
134         printk(KERN_INFO PFX "activated.\n");
135
136         return 0;
137 }
138
139 /*
140  * Stop the watchdog
141  */
142
143 static int wdt_stop(void)
144 {
145         unsigned long flags;
146
147         spin_lock_irqsave(&spinlock, flags);
148
149         /* Unlock the SuperIO chip */
150         outb_p(UNLOCK_DATA, IO_INDEX_PORT);
151         outb_p(UNLOCK_DATA, IO_INDEX_PORT);
152
153         /*
154          * Select device Aux2 (device=8) to set watchdog regs F2, F3 and F4.
155          * F2 is reset to its default value (watchdog timer disabled).
156          * F3 is reset to its default state.
157          * F4 clears the TIMEOUT'ed state (bit 0) - back to default.
158          */
159         outb_p(DEVICE_REGISTER, IO_INDEX_PORT);
160         outb_p(0x08, IO_DATA_PORT);
161         outb_p(0xF2, IO_INDEX_PORT);
162         outb_p(0xFF, IO_DATA_PORT);
163         outb_p(0xF3, IO_INDEX_PORT);
164         outb_p(0x00, IO_DATA_PORT);
165         outb_p(0xF4, IO_INDEX_PORT);
166         outb_p(0x00, IO_DATA_PORT);
167         outb_p(0xF2, IO_INDEX_PORT);
168         outb_p(0x00, IO_DATA_PORT);
169
170         /*
171          * Select device Aux1 (dev=7) to set GP16 (in reg E6) and
172          * Gp13 (in reg E3) as inputs.
173          */
174         outb_p(DEVICE_REGISTER, IO_INDEX_PORT);
175         outb_p(0x07, IO_DATA_PORT);
176         if (!testmode) {
177                 outb_p(0xE6, IO_INDEX_PORT);
178                 outb_p(0x01, IO_DATA_PORT);
179         }
180         outb_p(0xE3, IO_INDEX_PORT);
181         outb_p(0x01, IO_DATA_PORT);
182
183         /* Lock the SuperIO chip */
184         outb_p(LOCK_DATA, IO_INDEX_PORT);
185
186         spin_unlock_irqrestore(&spinlock, flags);
187
188         printk(KERN_INFO PFX "shutdown.\n");
189
190         return 0;
191 }
192
193 /*
194  * Send a keepalive ping to the watchdog
195  * This is done by simply re-writing the timeout to reg. 0xF2
196  */
197
198 static int wdt_keepalive(void)
199 {
200         unsigned long flags;
201
202         spin_lock_irqsave(&spinlock, flags);
203
204         /* Unlock the SuperIO chip */
205         outb_p(UNLOCK_DATA, IO_INDEX_PORT);
206         outb_p(UNLOCK_DATA, IO_INDEX_PORT);
207
208         /* Select device Aux2 (device=8) to kick watchdog reg F2 */
209         outb_p(DEVICE_REGISTER, IO_INDEX_PORT);
210         outb_p(0x08, IO_DATA_PORT);
211         outb_p(0xF2, IO_INDEX_PORT);
212         outb_p(timeoutW, IO_DATA_PORT);
213
214         /* Lock the SuperIO chip */
215         outb_p(LOCK_DATA, IO_INDEX_PORT);
216
217         spin_unlock_irqrestore(&spinlock, flags);
218
219         return 0;
220 }
221
222 /*
223  * Set the watchdog timeout value
224  */
225
226 static int wdt_set_timeout(int t)
227 {
228         int tmrval;
229
230         /*
231          * Convert seconds to watchdog counter time units, rounding up.
232          * On PCM-5335 watchdog units are 30 seconds/step with 15 sec startup
233          * value. This information is supplied in the PCM-5335 manual and was
234          * checked by me on a real board. This is a bit strange because W83977f
235          * datasheet says counter unit is in minutes!
236          */
237         if (t < 15)
238                 return -EINVAL;
239
240         tmrval = ((t + 15) + 29) / 30;
241
242         if (tmrval > 255)
243                 return -EINVAL;
244
245         /*
246          * timeout is the timeout in seconds,
247          * timeoutW is the timeout in watchdog counter units.
248          */
249         timeoutW = tmrval;
250         timeout = (timeoutW * 30) - 15;
251         return 0;
252 }
253
254 /*
255  * Get the watchdog status
256  */
257
258 static int wdt_get_status(int *status)
259 {
260         int new_status;
261         unsigned long flags;
262
263         spin_lock_irqsave(&spinlock, flags);
264
265         /* Unlock the SuperIO chip */
266         outb_p(UNLOCK_DATA, IO_INDEX_PORT);
267         outb_p(UNLOCK_DATA, IO_INDEX_PORT);
268
269         /* Select device Aux2 (device=8) to read watchdog reg F4 */
270         outb_p(DEVICE_REGISTER, IO_INDEX_PORT);
271         outb_p(0x08, IO_DATA_PORT);
272         outb_p(0xF4, IO_INDEX_PORT);
273         new_status = inb_p(IO_DATA_PORT);
274
275         /* Lock the SuperIO chip */
276         outb_p(LOCK_DATA, IO_INDEX_PORT);
277
278         spin_unlock_irqrestore(&spinlock, flags);
279
280         *status = 0;
281         if (new_status & 1)
282                 *status |= WDIOF_CARDRESET;
283
284         return 0;
285 }
286
287
288 /*
289  *      /dev/watchdog handling
290  */
291
292 static int wdt_open(struct inode *inode, struct file *file)
293 {
294         /* If the watchdog is alive we don't need to start it again */
295         if (test_and_set_bit(0, &timer_alive))
296                 return -EBUSY;
297
298         if (nowayout)
299                 __module_get(THIS_MODULE);
300
301         wdt_start();
302         return nonseekable_open(inode, file);
303 }
304
305 static int wdt_release(struct inode *inode, struct file *file)
306 {
307         /*
308          * Shut off the timer.
309          * Lock it in if it's a module and we set nowayout
310          */
311         if (expect_close == 42) {
312                 wdt_stop();
313                 clear_bit(0, &timer_alive);
314         } else {
315                 wdt_keepalive();
316                 printk(KERN_CRIT PFX
317                         "unexpected close, not stopping watchdog!\n");
318         }
319         expect_close = 0;
320         return 0;
321 }
322
323 /*
324  *      wdt_write:
325  *      @file: file handle to the watchdog
326  *      @buf: buffer to write (unused as data does not matter here
327  *      @count: count of bytes
328  *      @ppos: pointer to the position to write. No seeks allowed
329  *
330  *      A write to a watchdog device is defined as a keepalive signal. Any
331  *      write of data will do, as we we don't define content meaning.
332  */
333
334 static ssize_t wdt_write(struct file *file, const char __user *buf,
335                             size_t count, loff_t *ppos)
336 {
337         /* See if we got the magic character 'V' and reload the timer */
338         if (count) {
339                 if (!nowayout) {
340                         size_t ofs;
341
342                         /* note: just in case someone wrote the
343                            magic character long ago */
344                         expect_close = 0;
345
346                         /* scan to see whether or not we got the
347                            magic character */
348                         for (ofs = 0; ofs != count; ofs++) {
349                                 char c;
350                                 if (get_user(c, buf + ofs))
351                                         return -EFAULT;
352                                 if (c == 'V')
353                                         expect_close = 42;
354                         }
355                 }
356
357                 /* someone wrote to us, we should restart timer */
358                 wdt_keepalive();
359         }
360         return count;
361 }
362
363 /*
364  *      wdt_ioctl:
365  *      @inode: inode of the device
366  *      @file: file handle to the device
367  *      @cmd: watchdog command
368  *      @arg: argument pointer
369  *
370  *      The watchdog API defines a common set of functions for all watchdogs
371  *      according to their available features.
372  */
373
374 static struct watchdog_info ident = {
375         .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING,
376         .firmware_version =     1,
377         .identity = WATCHDOG_NAME,
378 };
379
380 static long wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
381 {
382         int status;
383         int new_options, retval = -EINVAL;
384         int new_timeout;
385         union {
386                 struct watchdog_info __user *ident;
387                 int __user *i;
388         } uarg;
389
390         uarg.i = (int __user *)arg;
391
392         switch (cmd) {
393         case WDIOC_GETSUPPORT:
394                 return copy_to_user(uarg.ident, &ident,
395                                                 sizeof(ident)) ? -EFAULT : 0;
396
397         case WDIOC_GETSTATUS:
398                 wdt_get_status(&status);
399                 return put_user(status, uarg.i);
400
401         case WDIOC_GETBOOTSTATUS:
402                 return put_user(0, uarg.i);
403
404         case WDIOC_SETOPTIONS:
405                 if (get_user(new_options, uarg.i))
406                         return -EFAULT;
407
408                 if (new_options & WDIOS_DISABLECARD) {
409                         wdt_stop();
410                         retval = 0;
411                 }
412
413                 if (new_options & WDIOS_ENABLECARD) {
414                         wdt_start();
415                         retval = 0;
416                 }
417
418                 return retval;
419
420         case WDIOC_KEEPALIVE:
421                 wdt_keepalive();
422                 return 0;
423
424         case WDIOC_SETTIMEOUT:
425                 if (get_user(new_timeout, uarg.i))
426                         return -EFAULT;
427
428                 if (wdt_set_timeout(new_timeout))
429                     return -EINVAL;
430
431                 wdt_keepalive();
432                 /* Fall */
433
434         case WDIOC_GETTIMEOUT:
435                 return put_user(timeout, uarg.i);
436
437         default:
438                 return -ENOTTY;
439
440         }
441 }
442
443 static int wdt_notify_sys(struct notifier_block *this, unsigned long code,
444         void *unused)
445 {
446         if (code == SYS_DOWN || code == SYS_HALT)
447                 wdt_stop();
448         return NOTIFY_DONE;
449 }
450
451 static const struct file_operations wdt_fops = {
452         .owner          = THIS_MODULE,
453         .llseek         = no_llseek,
454         .write          = wdt_write,
455         .unlocked_ioctl = wdt_ioctl,
456         .open           = wdt_open,
457         .release        = wdt_release,
458 };
459
460 static struct miscdevice wdt_miscdev = {
461         .minor          = WATCHDOG_MINOR,
462         .name           = "watchdog",
463         .fops           = &wdt_fops,
464 };
465
466 static struct notifier_block wdt_notifier = {
467         .notifier_call = wdt_notify_sys,
468 };
469
470 static int __init w83977f_wdt_init(void)
471 {
472         int rc;
473
474         printk(KERN_INFO PFX DRIVER_VERSION);
475
476         /*
477          * Check that the timeout value is within it's range;
478          * if not reset to the default
479          */
480         if (wdt_set_timeout(timeout)) {
481                 wdt_set_timeout(DEFAULT_TIMEOUT);
482                 printk(KERN_INFO PFX
483                     "timeout value must be 15 <= timeout <= 7635, using %d\n",
484                                                         DEFAULT_TIMEOUT);
485         }
486
487         if (!request_region(IO_INDEX_PORT, 2, WATCHDOG_NAME)) {
488                 printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
489                         IO_INDEX_PORT);
490                 rc = -EIO;
491                 goto err_out;
492         }
493
494         rc = register_reboot_notifier(&wdt_notifier);
495         if (rc) {
496                 printk(KERN_ERR PFX
497                         "cannot register reboot notifier (err=%d)\n", rc);
498                 goto err_out_region;
499         }
500
501         rc = misc_register(&wdt_miscdev);
502         if (rc) {
503                 printk(KERN_ERR PFX
504                         "cannot register miscdev on minor=%d (err=%d)\n",
505                                                 wdt_miscdev.minor, rc);
506                 goto err_out_reboot;
507         }
508
509         printk(KERN_INFO PFX
510                 "initialized. timeout=%d sec (nowayout=%d testmode=%d)\n",
511                                         timeout, nowayout, testmode);
512
513         return 0;
514
515 err_out_reboot:
516         unregister_reboot_notifier(&wdt_notifier);
517 err_out_region:
518         release_region(IO_INDEX_PORT, 2);
519 err_out:
520         return rc;
521 }
522
523 static void __exit w83977f_wdt_exit(void)
524 {
525         wdt_stop();
526         misc_deregister(&wdt_miscdev);
527         unregister_reboot_notifier(&wdt_notifier);
528         release_region(IO_INDEX_PORT, 2);
529 }
530
531 module_init(w83977f_wdt_init);
532 module_exit(w83977f_wdt_exit);
533
534 MODULE_AUTHOR("Jose Goncalves <jose.goncalves@inov.pt>");
535 MODULE_DESCRIPTION("Driver for watchdog timer in W83977F I/O chip");
536 MODULE_LICENSE("GPL");
537 MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);