]> pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/watchdog/shwdt.c
Merge branch 'omap-clock-fixes' of git://git.pwsan.com/linux-2.6
[linux-2.6-omap-h63xx.git] / drivers / 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 <linux/io.h>
32 #include <linux/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 separate 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 void sh_wdt_ping(unsigned long data);
69
70 static unsigned long shwdt_is_open;
71 static const struct watchdog_info sh_wdt_info;
72 static char shwdt_expect_close;
73 static DEFINE_TIMER(timer, sh_wdt_ping, 0, 0);
74 static unsigned long next_heartbeat;
75 static DEFINE_SPINLOCK(shwdt_lock);
76
77 #define WATCHDOG_HEARTBEAT 30                   /* 30 sec default heartbeat */
78 static int heartbeat = WATCHDOG_HEARTBEAT;      /* in seconds */
79
80 static int nowayout = WATCHDOG_NOWAYOUT;
81
82 /**
83  *      sh_wdt_start - Start the Watchdog
84  *
85  *      Starts the watchdog.
86  */
87 static void sh_wdt_start(void)
88 {
89         __u8 csr;
90         unsigned long flags;
91
92         spin_lock_irqsave(&shwdt_lock, flags);
93
94         next_heartbeat = jiffies + (heartbeat * HZ);
95         mod_timer(&timer, next_ping_period(clock_division_ratio));
96
97         csr = sh_wdt_read_csr();
98         csr |= WTCSR_WT | clock_division_ratio;
99         sh_wdt_write_csr(csr);
100
101         sh_wdt_write_cnt(0);
102
103         /*
104          * These processors have a bit of an inconsistent initialization
105          * process.. starting with SH-3, RSTS was moved to WTCSR, and the
106          * RSTCSR register was removed.
107          *
108          * On the SH-2 however, in addition with bits being in different
109          * locations, we must deal with RSTCSR outright..
110          */
111         csr = sh_wdt_read_csr();
112         csr |= WTCSR_TME;
113         csr &= ~WTCSR_RSTS;
114         sh_wdt_write_csr(csr);
115
116 #ifdef CONFIG_CPU_SH2
117         /*
118          * Whoever came up with the RSTCSR semantics must've been smoking
119          * some of the good stuff, since in addition to the WTCSR/WTCNT write
120          * brain-damage, it's managed to fuck things up one step further..
121          *
122          * If we need to clear the WOVF bit, the upper byte has to be 0xa5..
123          * but if we want to touch RSTE or RSTS, the upper byte has to be
124          * 0x5a..
125          */
126         csr = sh_wdt_read_rstcsr();
127         csr &= ~RSTCSR_RSTS;
128         sh_wdt_write_rstcsr(csr);
129 #endif
130         spin_unlock_irqrestore(&shwdt_lock, flags);
131 }
132
133 /**
134  *      sh_wdt_stop - Stop the Watchdog
135  *      Stops the watchdog.
136  */
137 static void sh_wdt_stop(void)
138 {
139         __u8 csr;
140         unsigned long flags;
141
142         spin_lock_irqsave(&shwdt_lock, flags);
143
144         del_timer(&timer);
145
146         csr = sh_wdt_read_csr();
147         csr &= ~WTCSR_TME;
148         sh_wdt_write_csr(csr);
149         spin_unlock_irqrestore(&shwdt_lock, flags);
150 }
151
152 /**
153  *      sh_wdt_keepalive - Keep the Userspace Watchdog Alive
154  *      The Userspace watchdog got a KeepAlive: schedule the next heartbeat.
155  */
156 static inline void sh_wdt_keepalive(void)
157 {
158         unsigned long flags;
159
160         spin_lock_irqsave(&shwdt_lock, flags);
161         next_heartbeat = jiffies + (heartbeat * HZ);
162         spin_unlock_irqrestore(&shwdt_lock, flags);
163 }
164
165 /**
166  *      sh_wdt_set_heartbeat - Set the Userspace Watchdog heartbeat
167  *      Set the Userspace Watchdog heartbeat
168  */
169 static int sh_wdt_set_heartbeat(int t)
170 {
171         unsigned long flags;
172
173         if (unlikely(t < 1 || t > 3600)) /* arbitrary upper limit */
174                 return -EINVAL;
175
176         spin_lock_irqsave(&shwdt_lock, flags);
177         heartbeat = t;
178         spin_unlock_irqrestore(&shwdt_lock, flags);
179         return 0;
180 }
181
182 /**
183  *      sh_wdt_ping - Ping the Watchdog
184  *      @data: Unused
185  *
186  *      Clears overflow bit, resets timer counter.
187  */
188 static void sh_wdt_ping(unsigned long data)
189 {
190         unsigned long flags;
191
192         spin_lock_irqsave(&shwdt_lock, flags);
193         if (time_before(jiffies, next_heartbeat)) {
194                 __u8 csr;
195
196                 csr = sh_wdt_read_csr();
197                 csr &= ~WTCSR_IOVF;
198                 sh_wdt_write_csr(csr);
199
200                 sh_wdt_write_cnt(0);
201
202                 mod_timer(&timer, next_ping_period(clock_division_ratio));
203         } else
204                 printk(KERN_WARNING PFX "Heartbeat lost! Will not ping "
205                        "the watchdog\n");
206         spin_unlock_irqrestore(&shwdt_lock, flags);
207 }
208
209 /**
210  *      sh_wdt_open - Open the Device
211  *      @inode: inode of device
212  *      @file: file handle of device
213  *
214  *      Watchdog device is opened and started.
215  */
216 static int sh_wdt_open(struct inode *inode, struct file *file)
217 {
218         if (test_and_set_bit(0, &shwdt_is_open))
219                 return -EBUSY;
220         if (nowayout)
221                 __module_get(THIS_MODULE);
222
223         sh_wdt_start();
224
225         return nonseekable_open(inode, file);
226 }
227
228 /**
229  *      sh_wdt_close - Close the Device
230  *      @inode: inode of device
231  *      @file: file handle of device
232  *
233  *      Watchdog device is closed and stopped.
234  */
235 static int sh_wdt_close(struct inode *inode, struct file *file)
236 {
237         if (shwdt_expect_close == 42) {
238                 sh_wdt_stop();
239         } else {
240                 printk(KERN_CRIT PFX "Unexpected close, not "
241                        "stopping watchdog!\n");
242                 sh_wdt_keepalive();
243         }
244
245         clear_bit(0, &shwdt_is_open);
246         shwdt_expect_close = 0;
247
248         return 0;
249 }
250
251 /**
252  *      sh_wdt_write - Write to Device
253  *      @file: file handle of device
254  *      @buf: buffer to write
255  *      @count: length of buffer
256  *      @ppos: offset
257  *
258  *      Pings the watchdog on write.
259  */
260 static ssize_t sh_wdt_write(struct file *file, const char *buf,
261                             size_t count, loff_t *ppos)
262 {
263         if (count) {
264                 if (!nowayout) {
265                         size_t i;
266
267                         shwdt_expect_close = 0;
268
269                         for (i = 0; i != count; i++) {
270                                 char c;
271                                 if (get_user(c, buf + i))
272                                         return -EFAULT;
273                                 if (c == 'V')
274                                         shwdt_expect_close = 42;
275                         }
276                 }
277                 sh_wdt_keepalive();
278         }
279
280         return count;
281 }
282
283 /**
284  *      sh_wdt_mmap - map WDT/CPG registers into userspace
285  *      @file: file structure for the device
286  *      @vma: VMA to map the registers into
287  *
288  *      A simple mmap() implementation for the corner cases where the counter
289  *      needs to be mapped in userspace directly. Due to the relatively small
290  *      size of the area, neighbouring registers not necessarily tied to the
291  *      CPG will also be accessible through the register page, so this remains
292  *      configurable for users that really know what they're doing.
293  *
294  *      Additionaly, the register page maps in the CPG register base relative
295  *      to the nearest page-aligned boundary, which requires that userspace do
296  *      the appropriate CPU subtype math for calculating the page offset for
297  *      the counter value.
298  */
299 static int sh_wdt_mmap(struct file *file, struct vm_area_struct *vma)
300 {
301         int ret = -ENOSYS;
302
303 #ifdef CONFIG_SH_WDT_MMAP
304         unsigned long addr;
305
306         /* Only support the simple cases where we map in a register page. */
307         if (((vma->vm_end - vma->vm_start) != PAGE_SIZE) || vma->vm_pgoff)
308                 return -EINVAL;
309
310         /*
311          * Pick WTCNT as the start, it's usually the first register after the
312          * FRQCR, and neither one are generally page-aligned out of the box.
313          */
314         addr = WTCNT & ~(PAGE_SIZE - 1);
315
316         vma->vm_flags |= VM_IO;
317         vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
318
319         if (io_remap_pfn_range(vma, vma->vm_start, addr >> PAGE_SHIFT,
320                                PAGE_SIZE, vma->vm_page_prot)) {
321                 printk(KERN_ERR PFX "%s: io_remap_pfn_range failed\n",
322                        __func__);
323                 return -EAGAIN;
324         }
325
326         ret = 0;
327 #endif
328
329         return ret;
330 }
331
332 /**
333  *      sh_wdt_ioctl - Query Device
334  *      @file: file handle of device
335  *      @cmd: watchdog command
336  *      @arg: argument
337  *
338  *      Query basic information from the device or ping it, as outlined by the
339  *      watchdog API.
340  */
341 static long sh_wdt_ioctl(struct file *file, unsigned int cmd,
342                                                         unsigned long arg)
343 {
344         int new_heartbeat;
345         int options, retval = -EINVAL;
346
347         switch (cmd) {
348         case WDIOC_GETSUPPORT:
349                 return copy_to_user((struct watchdog_info *)arg,
350                           &sh_wdt_info, sizeof(sh_wdt_info)) ? -EFAULT : 0;
351         case WDIOC_GETSTATUS:
352         case WDIOC_GETBOOTSTATUS:
353                 return put_user(0, (int *)arg);
354         case WDIOC_SETOPTIONS:
355                 if (get_user(options, (int *)arg))
356                         return -EFAULT;
357
358                 if (options & WDIOS_DISABLECARD) {
359                         sh_wdt_stop();
360                         retval = 0;
361                 }
362
363                 if (options & WDIOS_ENABLECARD) {
364                         sh_wdt_start();
365                         retval = 0;
366                 }
367
368                 return retval;
369         case WDIOC_KEEPALIVE:
370                 sh_wdt_keepalive();
371                 return 0;
372         case WDIOC_SETTIMEOUT:
373                 if (get_user(new_heartbeat, (int *)arg))
374                         return -EFAULT;
375
376                 if (sh_wdt_set_heartbeat(new_heartbeat))
377                         return -EINVAL;
378
379                 sh_wdt_keepalive();
380                 /* Fall */
381         case WDIOC_GETTIMEOUT:
382                 return put_user(heartbeat, (int *)arg);
383         default:
384                 return -ENOTTY;
385         }
386         return 0;
387 }
388
389 /**
390  *      sh_wdt_notify_sys - Notifier Handler
391  *      @this: notifier block
392  *      @code: notifier event
393  *      @unused: unused
394  *
395  *      Handles specific events, such as turning off the watchdog during a
396  *      shutdown event.
397  */
398 static int sh_wdt_notify_sys(struct notifier_block *this,
399                              unsigned long code, void *unused)
400 {
401         if (code == SYS_DOWN || code == SYS_HALT)
402                 sh_wdt_stop();
403
404         return NOTIFY_DONE;
405 }
406
407 static const struct file_operations sh_wdt_fops = {
408         .owner          = THIS_MODULE,
409         .llseek         = no_llseek,
410         .write          = sh_wdt_write,
411         .unlocked_ioctl = sh_wdt_ioctl,
412         .open           = sh_wdt_open,
413         .release        = sh_wdt_close,
414         .mmap           = sh_wdt_mmap,
415 };
416
417 static const struct watchdog_info sh_wdt_info = {
418         .options                = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT |
419                                   WDIOF_MAGICCLOSE,
420         .firmware_version       = 1,
421         .identity               = "SH WDT",
422 };
423
424 static struct notifier_block sh_wdt_notifier = {
425         .notifier_call          = sh_wdt_notify_sys,
426 };
427
428 static struct miscdevice sh_wdt_miscdev = {
429         .minor          = WATCHDOG_MINOR,
430         .name           = "watchdog",
431         .fops           = &sh_wdt_fops,
432 };
433
434 /**
435  *      sh_wdt_init - Initialize module
436  *      Registers the device and notifier handler. Actual device
437  *      initialization is handled by sh_wdt_open().
438  */
439 static int __init sh_wdt_init(void)
440 {
441         int rc;
442
443         if (clock_division_ratio < 0x5 || clock_division_ratio > 0x7) {
444                 clock_division_ratio = WTCSR_CKS_4096;
445                 printk(KERN_INFO PFX
446                   "clock_division_ratio value must be 0x5<=x<=0x7, using %d\n",
447                                 clock_division_ratio);
448         }
449
450         rc = sh_wdt_set_heartbeat(heartbeat);
451         if (unlikely(rc)) {
452                 heartbeat = WATCHDOG_HEARTBEAT;
453                 printk(KERN_INFO PFX
454                         "heartbeat value must be 1<=x<=3600, using %d\n",
455                                                                 heartbeat);
456         }
457
458         rc = register_reboot_notifier(&sh_wdt_notifier);
459         if (unlikely(rc)) {
460                 printk(KERN_ERR PFX
461                         "Can't register reboot notifier (err=%d)\n", rc);
462                 return rc;
463         }
464
465         rc = misc_register(&sh_wdt_miscdev);
466         if (unlikely(rc)) {
467                 printk(KERN_ERR PFX
468                         "Can't register miscdev on minor=%d (err=%d)\n",
469                                                 sh_wdt_miscdev.minor, rc);
470                 unregister_reboot_notifier(&sh_wdt_notifier);
471                 return rc;
472         }
473
474         printk(KERN_INFO PFX "initialized. heartbeat=%d sec (nowayout=%d)\n",
475                 heartbeat, nowayout);
476
477         return 0;
478 }
479
480 /**
481  *      sh_wdt_exit - Deinitialize module
482  *      Unregisters the device and notifier handler. Actual device
483  *      deinitialization is handled by sh_wdt_close().
484  */
485 static void __exit sh_wdt_exit(void)
486 {
487         misc_deregister(&sh_wdt_miscdev);
488         unregister_reboot_notifier(&sh_wdt_notifier);
489 }
490
491 MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>");
492 MODULE_DESCRIPTION("SuperH watchdog driver");
493 MODULE_LICENSE("GPL");
494 MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
495
496 module_param(clock_division_ratio, int, 0);
497 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) ")");
498
499 module_param(heartbeat, int, 0);
500 MODULE_PARM_DESC(heartbeat,
501         "Watchdog heartbeat in seconds. (1 <= heartbeat <= 3600, default="
502                                 __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
503
504 module_param(nowayout, int, 0);
505 MODULE_PARM_DESC(nowayout,
506         "Watchdog cannot be stopped once started (default="
507                                 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
508
509 module_init(sh_wdt_init);
510 module_exit(sh_wdt_exit);