Merge branch 'linux-2.6'
[pandora-kernel.git] / drivers / char / watchdog / wdt977.c
1 /*
2  *      Wdt977  0.04:   A Watchdog Device for Netwinder W83977AF chip
3  *
4  *      (c) Copyright 1998 Rebel.com (Woody Suwalski <woody@netwinder.org>)
5  *
6  *                      -----------------------
7  *
8  *      This program is free software; you can redistribute it and/or
9  *      modify it under the terms of the GNU General Public License
10  *      as published by the Free Software Foundation; either version
11  *      2 of the License, or (at your option) any later version.
12  *
13  *                      -----------------------
14  *      14-Dec-2001 Matt Domsch <Matt_Domsch@dell.com>
15  *           Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
16  *      19-Dec-2001 Woody Suwalski: Netwinder fixes, ioctl interface
17  *      06-Jan-2002 Woody Suwalski: For compatibility, convert all timeouts
18  *                                  from minutes to seconds.
19  *      07-Jul-2003 Daniele Bellucci: Audit return code of misc_register in
20  *                                    nwwatchdog_init.
21  *      25-Oct-2005 Woody Suwalski: Convert addresses to #defs, add spinlocks
22  *                                  remove limitiation to be used on Netwinders only
23  */
24
25 #include <linux/module.h>
26 #include <linux/moduleparam.h>
27 #include <linux/types.h>
28 #include <linux/kernel.h>
29 #include <linux/fs.h>
30 #include <linux/miscdevice.h>
31 #include <linux/init.h>
32 #include <linux/ioport.h>
33 #include <linux/watchdog.h>
34 #include <linux/notifier.h>
35 #include <linux/reboot.h>
36
37 #include <asm/io.h>
38 #include <asm/system.h>
39 #include <asm/mach-types.h>
40 #include <asm/uaccess.h>
41
42 #define WATCHDOG_VERSION  "0.04"
43 #define WATCHDOG_NAME     "Wdt977"
44 #define PFX WATCHDOG_NAME ": "
45 #define DRIVER_VERSION    WATCHDOG_NAME " driver, v" WATCHDOG_VERSION "\n"
46
47 #define IO_INDEX_PORT   0x370           /* on some systems it can be 0x3F0 */
48 #define IO_DATA_PORT    (IO_INDEX_PORT+1)
49
50 #define UNLOCK_DATA     0x87
51 #define LOCK_DATA       0xAA
52 #define DEVICE_REGISTER 0x07
53
54
55 #define DEFAULT_TIMEOUT 60                      /* default timeout in seconds */
56
57 static  int timeout = DEFAULT_TIMEOUT;
58 static  int timeoutM;                           /* timeout in minutes */
59 static  unsigned long timer_alive;
60 static  int testmode;
61 static  char expect_close;
62 static  spinlock_t spinlock;
63
64 module_param(timeout, int, 0);
65 MODULE_PARM_DESC(timeout,"Watchdog timeout in seconds (60..15300), default=" __MODULE_STRING(DEFAULT_TIMEOUT) ")");
66 module_param(testmode, int, 0);
67 MODULE_PARM_DESC(testmode,"Watchdog testmode (1 = no reboot), default=0");
68
69 static int nowayout = WATCHDOG_NOWAYOUT;
70 module_param(nowayout, int, 0);
71 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
72
73 /*
74  * Start the watchdog
75  */
76
77 static int wdt977_start(void)
78 {
79         unsigned long flags;
80
81         spin_lock_irqsave(&spinlock, flags);
82
83         /* unlock the SuperIO chip */
84         outb_p(UNLOCK_DATA, IO_INDEX_PORT);
85         outb_p(UNLOCK_DATA, IO_INDEX_PORT);
86
87         /* select device Aux2 (device=8) and set watchdog regs F2, F3 and F4
88          * F2 has the timeout in minutes
89          * F3 could be set to the POWER LED blink (with GP17 set to PowerLed)
90          *   at timeout, and to reset timer on kbd/mouse activity (not impl.)
91          * F4 is used to just clear the TIMEOUT'ed state (bit 0)
92          */
93         outb_p(DEVICE_REGISTER, IO_INDEX_PORT);
94         outb_p(0x08, IO_DATA_PORT);
95         outb_p(0xF2, IO_INDEX_PORT);
96         outb_p(timeoutM, IO_DATA_PORT);
97         outb_p(0xF3, IO_INDEX_PORT);
98         outb_p(0x00, IO_DATA_PORT);     /* another setting is 0E for kbd/mouse/LED */
99         outb_p(0xF4, IO_INDEX_PORT);
100         outb_p(0x00, IO_DATA_PORT);
101
102         /* at last select device Aux1 (dev=7) and set GP16 as a watchdog output */
103         /* in test mode watch the bit 1 on F4 to indicate "triggered" */
104         if (!testmode)
105         {
106                 outb_p(DEVICE_REGISTER, IO_INDEX_PORT);
107                 outb_p(0x07, IO_DATA_PORT);
108                 outb_p(0xE6, IO_INDEX_PORT);
109                 outb_p(0x08, IO_DATA_PORT);
110         }
111
112         /* lock the SuperIO chip */
113         outb_p(LOCK_DATA, IO_INDEX_PORT);
114
115         spin_unlock_irqrestore(&spinlock, flags);
116         printk(KERN_INFO PFX "activated.\n");
117
118         return 0;
119 }
120
121 /*
122  * Stop the watchdog
123  */
124
125 static int wdt977_stop(void)
126 {
127         unsigned long flags;
128         spin_lock_irqsave(&spinlock, flags);
129
130         /* unlock the SuperIO chip */
131         outb_p(UNLOCK_DATA, IO_INDEX_PORT);
132         outb_p(UNLOCK_DATA, IO_INDEX_PORT);
133
134         /* select device Aux2 (device=8) and set watchdog regs F2,F3 and F4
135         * F3 is reset to its default state
136         * F4 can clear the TIMEOUT'ed state (bit 0) - back to default
137         * We can not use GP17 as a PowerLed, as we use its usage as a RedLed
138         */
139         outb_p(DEVICE_REGISTER, IO_INDEX_PORT);
140         outb_p(0x08, IO_DATA_PORT);
141         outb_p(0xF2, IO_INDEX_PORT);
142         outb_p(0xFF, IO_DATA_PORT);
143         outb_p(0xF3, IO_INDEX_PORT);
144         outb_p(0x00, IO_DATA_PORT);
145         outb_p(0xF4, IO_INDEX_PORT);
146         outb_p(0x00, IO_DATA_PORT);
147         outb_p(0xF2, IO_INDEX_PORT);
148         outb_p(0x00, IO_DATA_PORT);
149
150         /* at last select device Aux1 (dev=7) and set GP16 as a watchdog output */
151         outb_p(DEVICE_REGISTER, IO_INDEX_PORT);
152         outb_p(0x07, IO_DATA_PORT);
153         outb_p(0xE6, IO_INDEX_PORT);
154         outb_p(0x08, IO_DATA_PORT);
155
156         /* lock the SuperIO chip */
157         outb_p(LOCK_DATA, IO_INDEX_PORT);
158
159         spin_unlock_irqrestore(&spinlock, flags);
160         printk(KERN_INFO PFX "shutdown.\n");
161
162         return 0;
163 }
164
165 /*
166  * Send a keepalive ping to the watchdog
167  * This is done by simply re-writing the timeout to reg. 0xF2
168  */
169
170 static int wdt977_keepalive(void)
171 {
172         unsigned long flags;
173         spin_lock_irqsave(&spinlock, flags);
174
175         /* unlock the SuperIO chip */
176         outb_p(UNLOCK_DATA, IO_INDEX_PORT);
177         outb_p(UNLOCK_DATA, IO_INDEX_PORT);
178
179         /* select device Aux2 (device=8) and kicks watchdog reg F2 */
180         /* F2 has the timeout in minutes */
181         outb_p(DEVICE_REGISTER, IO_INDEX_PORT);
182         outb_p(0x08, IO_DATA_PORT);
183         outb_p(0xF2, IO_INDEX_PORT);
184         outb_p(timeoutM, IO_DATA_PORT);
185
186         /* lock the SuperIO chip */
187         outb_p(LOCK_DATA, IO_INDEX_PORT);
188         spin_unlock_irqrestore(&spinlock, flags);
189
190         return 0;
191 }
192
193 /*
194  * Set the watchdog timeout value
195  */
196
197 static int wdt977_set_timeout(int t)
198 {
199         int tmrval;
200
201         /* convert seconds to minutes, rounding up */
202         tmrval = (t + 59) / 60;
203
204         if (machine_is_netwinder()) {
205                 /* we have a hw bug somewhere, so each 977 minute is actually only 30sec
206                  *  this limits the max timeout to half of device max of 255 minutes...
207                  */
208                 tmrval += tmrval;
209         }
210
211         if ((tmrval < 1) || (tmrval > 255))
212                 return -EINVAL;
213
214         /* timeout is the timeout in seconds, timeoutM is the timeout in minutes) */
215         timeout = t;
216         timeoutM = tmrval;
217         return 0;
218 }
219
220 /*
221  * Get the watchdog status
222  */
223
224 static int wdt977_get_status(int *status)
225 {
226         int new_status;
227         unsigned long flags;
228
229         spin_lock_irqsave(&spinlock, flags);
230
231         /* unlock the SuperIO chip */
232         outb_p(UNLOCK_DATA, IO_INDEX_PORT);
233         outb_p(UNLOCK_DATA, IO_INDEX_PORT);
234
235         /* select device Aux2 (device=8) and read watchdog reg F4 */
236         outb_p(DEVICE_REGISTER, IO_INDEX_PORT);
237         outb_p(0x08, IO_DATA_PORT);
238         outb_p(0xF4, IO_INDEX_PORT);
239         new_status = inb_p(IO_DATA_PORT);
240
241         /* lock the SuperIO chip */
242         outb_p(LOCK_DATA, IO_INDEX_PORT);
243
244         spin_unlock_irqrestore(&spinlock, flags);
245
246         *status=0;
247         if (new_status & 1)
248                 *status |= WDIOF_CARDRESET;
249
250         return 0;
251 }
252
253
254 /*
255  *      /dev/watchdog handling
256  */
257
258 static int wdt977_open(struct inode *inode, struct file *file)
259 {
260         /* If the watchdog is alive we don't need to start it again */
261         if( test_and_set_bit(0,&timer_alive) )
262                 return -EBUSY;
263
264         if (nowayout)
265                 __module_get(THIS_MODULE);
266
267         wdt977_start();
268         return nonseekable_open(inode, file);
269 }
270
271 static int wdt977_release(struct inode *inode, struct file *file)
272 {
273         /*
274          *      Shut off the timer.
275          *      Lock it in if it's a module and we set nowayout
276          */
277         if (expect_close == 42)
278         {
279                 wdt977_stop();
280                 clear_bit(0,&timer_alive);
281         } else {
282                 wdt977_keepalive();
283                 printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");
284         }
285         expect_close = 0;
286         return 0;
287 }
288
289
290 /*
291  *      wdt977_write:
292  *      @file: file handle to the watchdog
293  *      @buf: buffer to write (unused as data does not matter here
294  *      @count: count of bytes
295  *      @ppos: pointer to the position to write. No seeks allowed
296  *
297  *      A write to a watchdog device is defined as a keepalive signal. Any
298  *      write of data will do, as we we don't define content meaning.
299  */
300
301 static ssize_t wdt977_write(struct file *file, const char __user *buf,
302                             size_t count, loff_t *ppos)
303 {
304         if (count)
305         {
306                 if (!nowayout)
307                 {
308                         size_t i;
309
310                         /* In case it was set long ago */
311                         expect_close = 0;
312
313                         for (i = 0; i != count; i++)
314                         {
315                                 char c;
316                                 if (get_user(c, buf + i))
317                                         return -EFAULT;
318                                 if (c == 'V')
319                                         expect_close = 42;
320                         }
321                 }
322
323                 /* someone wrote to us, we should restart timer */
324                 wdt977_keepalive();
325         }
326         return count;
327 }
328
329 /*
330  *      wdt977_ioctl:
331  *      @inode: inode of the device
332  *      @file: file handle to the device
333  *      @cmd: watchdog command
334  *      @arg: argument pointer
335  *
336  *      The watchdog API defines a common set of functions for all watchdogs
337  *      according to their available features.
338  */
339
340 static struct watchdog_info ident = {
341         .options =              WDIOF_SETTIMEOUT |
342                                 WDIOF_MAGICCLOSE |
343                                 WDIOF_KEEPALIVEPING,
344         .firmware_version =     1,
345         .identity =             WATCHDOG_NAME,
346 };
347
348 static int wdt977_ioctl(struct inode *inode, struct file *file,
349         unsigned int cmd, unsigned long arg)
350 {
351         int status;
352         int new_options, retval = -EINVAL;
353         int new_timeout;
354         union {
355                 struct watchdog_info __user *ident;
356                 int __user *i;
357         } uarg;
358
359         uarg.i = (int __user *)arg;
360
361         switch(cmd)
362         {
363         default:
364                 return -ENOIOCTLCMD;
365
366         case WDIOC_GETSUPPORT:
367                 return copy_to_user(uarg.ident, &ident,
368                         sizeof(ident)) ? -EFAULT : 0;
369
370         case WDIOC_GETSTATUS:
371                 wdt977_get_status(&status);
372                 return put_user(status, uarg.i);
373
374         case WDIOC_GETBOOTSTATUS:
375                 return put_user(0, uarg.i);
376
377         case WDIOC_KEEPALIVE:
378                 wdt977_keepalive();
379                 return 0;
380
381         case WDIOC_SETOPTIONS:
382                 if (get_user (new_options, uarg.i))
383                         return -EFAULT;
384
385                 if (new_options & WDIOS_DISABLECARD) {
386                         wdt977_stop();
387                         retval = 0;
388                 }
389
390                 if (new_options & WDIOS_ENABLECARD) {
391                         wdt977_start();
392                         retval = 0;
393                 }
394
395                 return retval;
396
397         case WDIOC_SETTIMEOUT:
398                 if (get_user(new_timeout, uarg.i))
399                         return -EFAULT;
400
401                 if (wdt977_set_timeout(new_timeout))
402                     return -EINVAL;
403
404                 wdt977_keepalive();
405                 /* Fall */
406
407         case WDIOC_GETTIMEOUT:
408                 return put_user(timeout, uarg.i);
409
410         }
411 }
412
413 static int wdt977_notify_sys(struct notifier_block *this, unsigned long code,
414         void *unused)
415 {
416         if(code==SYS_DOWN || code==SYS_HALT)
417                 wdt977_stop();
418         return NOTIFY_DONE;
419 }
420
421 static const struct file_operations wdt977_fops=
422 {
423         .owner          = THIS_MODULE,
424         .llseek         = no_llseek,
425         .write          = wdt977_write,
426         .ioctl          = wdt977_ioctl,
427         .open           = wdt977_open,
428         .release        = wdt977_release,
429 };
430
431 static struct miscdevice wdt977_miscdev=
432 {
433         .minor          = WATCHDOG_MINOR,
434         .name           = "watchdog",
435         .fops           = &wdt977_fops,
436 };
437
438 static struct notifier_block wdt977_notifier = {
439         .notifier_call = wdt977_notify_sys,
440 };
441
442 static int __init wd977_init(void)
443 {
444         int rc;
445
446         //if (!machine_is_netwinder())
447         //      return -ENODEV;
448
449         printk(KERN_INFO PFX DRIVER_VERSION);
450
451         spin_lock_init(&spinlock);
452
453         /* Check that the timeout value is within it's range ; if not reset to the default */
454         if (wdt977_set_timeout(timeout))
455         {
456                 wdt977_set_timeout(DEFAULT_TIMEOUT);
457                 printk(KERN_INFO PFX "timeout value must be 60<timeout<15300, using %d\n",
458                         DEFAULT_TIMEOUT);
459         }
460
461         /* on Netwinder the IOports are already reserved by
462          * arch/arm/mach-footbridge/netwinder-hw.c
463          */
464         if (!machine_is_netwinder())
465         {
466                 if (!request_region(IO_INDEX_PORT, 2, WATCHDOG_NAME))
467                 {
468                         printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
469                                 IO_INDEX_PORT);
470                         rc = -EIO;
471                         goto err_out;
472                 }
473         }
474
475         rc = misc_register(&wdt977_miscdev);
476         if (rc)
477         {
478                 printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
479                         wdt977_miscdev.minor, rc);
480                 goto err_out_region;
481         }
482
483         rc = register_reboot_notifier(&wdt977_notifier);
484         if (rc)
485         {
486                 printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
487                         rc);
488                 goto err_out_miscdev;
489         }
490
491         printk(KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d, testmode=%i)\n",
492                 timeout, nowayout, testmode);
493
494         return 0;
495
496 err_out_miscdev:
497         misc_deregister(&wdt977_miscdev);
498 err_out_region:
499         if (!machine_is_netwinder())
500                 release_region(IO_INDEX_PORT,2);
501 err_out:
502         return rc;
503 }
504
505 static void __exit wd977_exit(void)
506 {
507         wdt977_stop();
508         misc_deregister(&wdt977_miscdev);
509         unregister_reboot_notifier(&wdt977_notifier);
510         release_region(IO_INDEX_PORT,2);
511 }
512
513 module_init(wd977_init);
514 module_exit(wd977_exit);
515
516 MODULE_AUTHOR("Woody Suwalski <woodys@xandros.com>");
517 MODULE_DESCRIPTION("W83977AF Watchdog driver");
518 MODULE_LICENSE("GPL");
519 MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);