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