Merge branch 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee13...
[pandora-kernel.git] / drivers / char / watchdog / shwdt.c
1 /*
2  * drivers/char/watchdog/shwdt.c
3  *
4  * Watchdog driver for integrated watchdog in the SuperH processors.
5  *
6  * Copyright (C) 2001, 2002, 2003 Paul Mundt <lethal@linux-sh.org>
7  *
8  * This program is free software; you can redistribute it and/or modify it
9  * under the terms of the GNU General Public License as published by the
10  * Free Software Foundation; either version 2 of the License, or (at your
11  * option) any later version.
12  *
13  * 14-Dec-2001 Matt Domsch <Matt_Domsch@dell.com>
14  *     Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
15  *
16  * 19-Apr-2002 Rob Radez <rob@osinvestor.com>
17  *     Added expect close support, made emulated timeout runtime changeable
18  *     general cleanups, add some ioctls
19  */
20 #include <linux/module.h>
21 #include <linux/moduleparam.h>
22 #include <linux/init.h>
23 #include <linux/types.h>
24 #include <linux/miscdevice.h>
25 #include <linux/watchdog.h>
26 #include <linux/reboot.h>
27 #include <linux/notifier.h>
28 #include <linux/ioport.h>
29 #include <linux/fs.h>
30 #include <linux/mm.h>
31 #include <asm/io.h>
32 #include <asm/uaccess.h>
33 #include <asm/watchdog.h>
34
35 #define PFX "shwdt: "
36
37 /*
38  * Default clock division ratio is 5.25 msecs. For an additional table of
39  * values, consult the asm-sh/watchdog.h. Overload this at module load
40  * time.
41  *
42  * In order for this to work reliably we need to have HZ set to 1000 or
43  * something quite higher than 100 (or we need a proper high-res timer
44  * implementation that will deal with this properly), otherwise the 10ms
45  * resolution of a jiffy is enough to trigger the overflow. For things like
46  * the SH-4 and SH-5, this isn't necessarily that big of a problem, though
47  * for the SH-2 and SH-3, this isn't recommended unless the WDT is absolutely
48  * necssary.
49  *
50  * As a result of this timing problem, the only modes that are particularly
51  * feasible are the 4096 and the 2048 divisors, which yeild 5.25 and 2.62ms
52  * overflow periods respectively.
53  *
54  * Also, since we can't really expect userspace to be responsive enough
55  * before the overflow happens, we maintain two seperate timers .. One in
56  * the kernel for clearing out WOVF every 2ms or so (again, this depends on
57  * HZ == 1000), and another for monitoring userspace writes to the WDT device.
58  *
59  * As such, we currently use a configurable heartbeat interval which defaults
60  * to 30s. In this case, the userspace daemon is only responsible for periodic
61  * writes to the device before the next heartbeat is scheduled. If the daemon
62  * misses its deadline, the kernel timer will allow the WDT to overflow.
63  */
64 static int clock_division_ratio = WTCSR_CKS_4096;
65
66 #define next_ping_period(cks)   msecs_to_jiffies(cks - 4)
67
68 static unsigned long shwdt_is_open;
69 static struct watchdog_info sh_wdt_info;
70 static char shwdt_expect_close;
71 static struct timer_list timer;
72 static unsigned long next_heartbeat;
73
74 #define WATCHDOG_HEARTBEAT 30                   /* 30 sec default heartbeat */
75 static int heartbeat = WATCHDOG_HEARTBEAT;      /* in seconds */
76
77 static int nowayout = WATCHDOG_NOWAYOUT;
78
79 /**
80  *      sh_wdt_start - Start the Watchdog
81  *
82  *      Starts the watchdog.
83  */
84 static void sh_wdt_start(void)
85 {
86         __u8 csr;
87
88         next_heartbeat = jiffies + (heartbeat * HZ);
89         mod_timer(&timer, next_ping_period(clock_division_ratio));
90
91         csr = sh_wdt_read_csr();
92         csr |= WTCSR_WT | clock_division_ratio;
93         sh_wdt_write_csr(csr);
94
95         sh_wdt_write_cnt(0);
96
97         /*
98          * These processors have a bit of an inconsistent initialization
99          * process.. starting with SH-3, RSTS was moved to WTCSR, and the
100          * RSTCSR register was removed.
101          *
102          * On the SH-2 however, in addition with bits being in different
103          * locations, we must deal with RSTCSR outright..
104          */
105         csr = sh_wdt_read_csr();
106         csr |= WTCSR_TME;
107         csr &= ~WTCSR_RSTS;
108         sh_wdt_write_csr(csr);
109
110 #ifdef CONFIG_CPU_SH2
111         /*
112          * Whoever came up with the RSTCSR semantics must've been smoking
113          * some of the good stuff, since in addition to the WTCSR/WTCNT write
114          * brain-damage, it's managed to fuck things up one step further..
115          *
116          * If we need to clear the WOVF bit, the upper byte has to be 0xa5..
117          * but if we want to touch RSTE or RSTS, the upper byte has to be
118          * 0x5a..
119          */
120         csr = sh_wdt_read_rstcsr();
121         csr &= ~RSTCSR_RSTS;
122         sh_wdt_write_rstcsr(csr);
123 #endif
124 }
125
126 /**
127  *      sh_wdt_stop - Stop the Watchdog
128  *      Stops the watchdog.
129  */
130 static void sh_wdt_stop(void)
131 {
132         __u8 csr;
133
134         del_timer(&timer);
135
136         csr = sh_wdt_read_csr();
137         csr &= ~WTCSR_TME;
138         sh_wdt_write_csr(csr);
139 }
140
141 /**
142  *      sh_wdt_keepalive - Keep the Userspace Watchdog Alive
143  *      The Userspace watchdog got a KeepAlive: schedule the next heartbeat.
144  */
145 static inline void sh_wdt_keepalive(void)
146 {
147         next_heartbeat = jiffies + (heartbeat * HZ);
148 }
149
150 /**
151  *      sh_wdt_set_heartbeat - Set the Userspace Watchdog heartbeat
152  *      Set the Userspace Watchdog heartbeat
153  */
154 static int sh_wdt_set_heartbeat(int t)
155 {
156         if (unlikely((t < 1) || (t > 3600))) /* arbitrary upper limit */
157                 return -EINVAL;
158
159         heartbeat = t;
160         return 0;
161 }
162
163 /**
164  *      sh_wdt_ping - Ping the Watchdog
165  *      @data: Unused
166  *
167  *      Clears overflow bit, resets timer counter.
168  */
169 static void sh_wdt_ping(unsigned long data)
170 {
171         if (time_before(jiffies, next_heartbeat)) {
172                 __u8 csr;
173
174                 csr = sh_wdt_read_csr();
175                 csr &= ~WTCSR_IOVF;
176                 sh_wdt_write_csr(csr);
177
178                 sh_wdt_write_cnt(0);
179
180                 mod_timer(&timer, next_ping_period(clock_division_ratio));
181         } else
182                 printk(KERN_WARNING PFX "Heartbeat lost! Will not ping "
183                        "the watchdog\n");
184 }
185
186 /**
187  *      sh_wdt_open - Open the Device
188  *      @inode: inode of device
189  *      @file: file handle of device
190  *
191  *      Watchdog device is opened and started.
192  */
193 static int sh_wdt_open(struct inode *inode, struct file *file)
194 {
195         if (test_and_set_bit(0, &shwdt_is_open))
196                 return -EBUSY;
197         if (nowayout)
198                 __module_get(THIS_MODULE);
199
200         sh_wdt_start();
201
202         return nonseekable_open(inode, file);
203 }
204
205 /**
206  *      sh_wdt_close - Close the Device
207  *      @inode: inode of device
208  *      @file: file handle of device
209  *
210  *      Watchdog device is closed and stopped.
211  */
212 static int sh_wdt_close(struct inode *inode, struct file *file)
213 {
214         if (shwdt_expect_close == 42) {
215                 sh_wdt_stop();
216         } else {
217                 printk(KERN_CRIT PFX "Unexpected close, not "
218                        "stopping watchdog!\n");
219                 sh_wdt_keepalive();
220         }
221
222         clear_bit(0, &shwdt_is_open);
223         shwdt_expect_close = 0;
224
225         return 0;
226 }
227
228 /**
229  *      sh_wdt_write - Write to Device
230  *      @file: file handle of device
231  *      @buf: buffer to write
232  *      @count: length of buffer
233  *      @ppos: offset
234  *
235  *      Pings the watchdog on write.
236  */
237 static ssize_t sh_wdt_write(struct file *file, const char *buf,
238                             size_t count, loff_t *ppos)
239 {
240         if (count) {
241                 if (!nowayout) {
242                         size_t i;
243
244                         shwdt_expect_close = 0;
245
246                         for (i = 0; i != count; i++) {
247                                 char c;
248                                 if (get_user(c, buf + i))
249                                         return -EFAULT;
250                                 if (c == 'V')
251                                         shwdt_expect_close = 42;
252                         }
253                 }
254                 sh_wdt_keepalive();
255         }
256
257         return count;
258 }
259
260 /**
261  *      sh_wdt_mmap - map WDT/CPG registers into userspace
262  *      @file: file structure for the device
263  *      @vma: VMA to map the registers into
264  *
265  *      A simple mmap() implementation for the corner cases where the counter
266  *      needs to be mapped in userspace directly. Due to the relatively small
267  *      size of the area, neighbouring registers not necessarily tied to the
268  *      CPG will also be accessible through the register page, so this remains
269  *      configurable for users that really know what they're doing.
270  *
271  *      Additionaly, the register page maps in the CPG register base relative
272  *      to the nearest page-aligned boundary, which requires that userspace do
273  *      the appropriate CPU subtype math for calculating the page offset for
274  *      the counter value.
275  */
276 static int sh_wdt_mmap(struct file *file, struct vm_area_struct *vma)
277 {
278         int ret = -ENOSYS;
279
280 #ifdef CONFIG_SH_WDT_MMAP
281         unsigned long addr;
282
283         /* Only support the simple cases where we map in a register page. */
284         if (((vma->vm_end - vma->vm_start) != PAGE_SIZE) || vma->vm_pgoff)
285                 return -EINVAL;
286
287         /*
288          * Pick WTCNT as the start, it's usually the first register after the
289          * FRQCR, and neither one are generally page-aligned out of the box.
290          */
291         addr = WTCNT & ~(PAGE_SIZE - 1);
292
293         vma->vm_flags |= VM_IO;
294         vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
295
296         if (io_remap_pfn_range(vma, vma->vm_start, addr >> PAGE_SHIFT,
297                                PAGE_SIZE, vma->vm_page_prot)) {
298                 printk(KERN_ERR PFX "%s: io_remap_pfn_range failed\n",
299                        __FUNCTION__);
300                 return -EAGAIN;
301         }
302
303         ret = 0;
304 #endif
305
306         return ret;
307 }
308
309 /**
310  *      sh_wdt_ioctl - Query Device
311  *      @inode: inode of device
312  *      @file: file handle of device
313  *      @cmd: watchdog command
314  *      @arg: argument
315  *
316  *      Query basic information from the device or ping it, as outlined by the
317  *      watchdog API.
318  */
319 static int sh_wdt_ioctl(struct inode *inode, struct file *file,
320                         unsigned int cmd, unsigned long arg)
321 {
322         int new_heartbeat;
323         int options, retval = -EINVAL;
324
325         switch (cmd) {
326                 case WDIOC_GETSUPPORT:
327                         return copy_to_user((struct watchdog_info *)arg,
328                                           &sh_wdt_info,
329                                           sizeof(sh_wdt_info)) ? -EFAULT : 0;
330                 case WDIOC_GETSTATUS:
331                 case WDIOC_GETBOOTSTATUS:
332                         return put_user(0, (int *)arg);
333                 case WDIOC_KEEPALIVE:
334                         sh_wdt_keepalive();
335                         return 0;
336                 case WDIOC_SETTIMEOUT:
337                         if (get_user(new_heartbeat, (int *)arg))
338                                 return -EFAULT;
339
340                         if (sh_wdt_set_heartbeat(new_heartbeat))
341                                 return -EINVAL;
342
343                         sh_wdt_keepalive();
344                         /* Fall */
345                 case WDIOC_GETTIMEOUT:
346                         return put_user(heartbeat, (int *)arg);
347                 case WDIOC_SETOPTIONS:
348                         if (get_user(options, (int *)arg))
349                                 return -EFAULT;
350
351                         if (options & WDIOS_DISABLECARD) {
352                                 sh_wdt_stop();
353                                 retval = 0;
354                         }
355
356                         if (options & WDIOS_ENABLECARD) {
357                                 sh_wdt_start();
358                                 retval = 0;
359                         }
360
361                         return retval;
362                 default:
363                         return -ENOIOCTLCMD;
364         }
365
366         return 0;
367 }
368
369 /**
370  *      sh_wdt_notify_sys - Notifier Handler
371  *      @this: notifier block
372  *      @code: notifier event
373  *      @unused: unused
374  *
375  *      Handles specific events, such as turning off the watchdog during a
376  *      shutdown event.
377  */
378 static int sh_wdt_notify_sys(struct notifier_block *this,
379                              unsigned long code, void *unused)
380 {
381         if (code == SYS_DOWN || code == SYS_HALT)
382                 sh_wdt_stop();
383
384         return NOTIFY_DONE;
385 }
386
387 static const struct file_operations sh_wdt_fops = {
388         .owner          = THIS_MODULE,
389         .llseek         = no_llseek,
390         .write          = sh_wdt_write,
391         .ioctl          = sh_wdt_ioctl,
392         .open           = sh_wdt_open,
393         .release        = sh_wdt_close,
394         .mmap           = sh_wdt_mmap,
395 };
396
397 static struct watchdog_info sh_wdt_info = {
398         .options                = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT |
399                                   WDIOF_MAGICCLOSE,
400         .firmware_version       = 1,
401         .identity               = "SH WDT",
402 };
403
404 static struct notifier_block sh_wdt_notifier = {
405         .notifier_call          = sh_wdt_notify_sys,
406 };
407
408 static struct miscdevice sh_wdt_miscdev = {
409         .minor          = WATCHDOG_MINOR,
410         .name           = "watchdog",
411         .fops           = &sh_wdt_fops,
412 };
413
414 /**
415  *      sh_wdt_init - Initialize module
416  *      Registers the device and notifier handler. Actual device
417  *      initialization is handled by sh_wdt_open().
418  */
419 static int __init sh_wdt_init(void)
420 {
421         int rc;
422
423         if ((clock_division_ratio < 0x5) || (clock_division_ratio > 0x7)) {
424                 clock_division_ratio = WTCSR_CKS_4096;
425                 printk(KERN_INFO PFX "clock_division_ratio value must "
426                        "be 0x5<=x<=0x7, using %d\n", clock_division_ratio);
427         }
428
429         rc = sh_wdt_set_heartbeat(heartbeat);
430         if (unlikely(rc)) {
431                 heartbeat = WATCHDOG_HEARTBEAT;
432                 printk(KERN_INFO PFX "heartbeat value must "
433                        "be 1<=x<=3600, using %d\n", heartbeat);
434         }
435
436         init_timer(&timer);
437         timer.function = sh_wdt_ping;
438         timer.data = 0;
439
440         rc = register_reboot_notifier(&sh_wdt_notifier);
441         if (unlikely(rc)) {
442                 printk(KERN_ERR PFX "Can't register reboot notifier (err=%d)\n",
443                        rc);
444                 return rc;
445         }
446
447         rc = misc_register(&sh_wdt_miscdev);
448         if (unlikely(rc)) {
449                 printk(KERN_ERR PFX "Can't register miscdev on "
450                        "minor=%d (err=%d)\n", sh_wdt_miscdev.minor, rc);
451                 unregister_reboot_notifier(&sh_wdt_notifier);
452                 return rc;
453         }
454
455         printk(KERN_INFO PFX "initialized. heartbeat=%d sec (nowayout=%d)\n",
456                 heartbeat, nowayout);
457
458         return 0;
459 }
460
461 /**
462  *      sh_wdt_exit - Deinitialize module
463  *      Unregisters the device and notifier handler. Actual device
464  *      deinitialization is handled by sh_wdt_close().
465  */
466 static void __exit sh_wdt_exit(void)
467 {
468         misc_deregister(&sh_wdt_miscdev);
469         unregister_reboot_notifier(&sh_wdt_notifier);
470 }
471
472 MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>");
473 MODULE_DESCRIPTION("SuperH watchdog driver");
474 MODULE_LICENSE("GPL");
475 MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
476
477 module_param(clock_division_ratio, int, 0);
478 MODULE_PARM_DESC(clock_division_ratio, "Clock division ratio. Valid ranges are from 0x5 (1.31ms) to 0x7 (5.25ms). (default=" __MODULE_STRING(clock_division_ratio) ")");
479
480 module_param(heartbeat, int, 0);
481 MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (1<=heartbeat<=3600, default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
482
483 module_param(nowayout, int, 0);
484 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
485
486 module_init(sh_wdt_init);
487 module_exit(sh_wdt_exit);