2  * drivers/char/watchdog/shwdt.c
 
   4  * Watchdog driver for integrated watchdog in the SuperH processors.
 
   6  * Copyright (C) 2001, 2002, 2003 Paul Mundt <lethal@linux-sh.org>
 
   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.
 
  13  * 14-Dec-2001 Matt Domsch <Matt_Domsch@dell.com>
 
  14  *     Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
 
  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
 
  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>
 
  32 #include <linux/uaccess.h>
 
  33 #include <asm/watchdog.h>
 
  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
 
  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
 
  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.
 
  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.
 
  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.
 
  64 static int clock_division_ratio = WTCSR_CKS_4096;
 
  66 #define next_ping_period(cks)   msecs_to_jiffies(cks - 4)
 
  68 static void sh_wdt_ping(unsigned long data);
 
  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);
 
  77 #define WATCHDOG_HEARTBEAT 30                   /* 30 sec default heartbeat */
 
  78 static int heartbeat = WATCHDOG_HEARTBEAT;      /* in seconds */
 
  80 static int nowayout = WATCHDOG_NOWAYOUT;
 
  83  *      sh_wdt_start - Start the Watchdog
 
  85  *      Starts the watchdog.
 
  87 static void sh_wdt_start(void)
 
  92         spin_lock_irqsave(&shwdt_lock, flags);
 
  94         next_heartbeat = jiffies + (heartbeat * HZ);
 
  95         mod_timer(&timer, next_ping_period(clock_division_ratio));
 
  97         csr = sh_wdt_read_csr();
 
  98         csr |= WTCSR_WT | clock_division_ratio;
 
  99         sh_wdt_write_csr(csr);
 
 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.
 
 108          * On the SH-2 however, in addition with bits being in different
 
 109          * locations, we must deal with RSTCSR outright..
 
 111         csr = sh_wdt_read_csr();
 
 114         sh_wdt_write_csr(csr);
 
 116 #ifdef CONFIG_CPU_SH2
 
 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..
 
 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
 
 126         csr = sh_wdt_read_rstcsr();
 
 128         sh_wdt_write_rstcsr(csr);
 
 130         spin_unlock_irqrestore(&shwdt_lock, flags);
 
 134  *      sh_wdt_stop - Stop the Watchdog
 
 135  *      Stops the watchdog.
 
 137 static void sh_wdt_stop(void)
 
 142         spin_lock_irqsave(&shwdt_lock, flags);
 
 146         csr = sh_wdt_read_csr();
 
 148         sh_wdt_write_csr(csr);
 
 149         spin_unlock_irqrestore(&shwdt_lock, flags);
 
 153  *      sh_wdt_keepalive - Keep the Userspace Watchdog Alive
 
 154  *      The Userspace watchdog got a KeepAlive: schedule the next heartbeat.
 
 156 static inline void sh_wdt_keepalive(void)
 
 160         spin_lock_irqsave(&shwdt_lock, flags);
 
 161         next_heartbeat = jiffies + (heartbeat * HZ);
 
 162         spin_unlock_irqrestore(&shwdt_lock, flags);
 
 166  *      sh_wdt_set_heartbeat - Set the Userspace Watchdog heartbeat
 
 167  *      Set the Userspace Watchdog heartbeat
 
 169 static int sh_wdt_set_heartbeat(int t)
 
 173         if (unlikely(t < 1 || t > 3600)) /* arbitrary upper limit */
 
 176         spin_lock_irqsave(&shwdt_lock, flags);
 
 178         spin_unlock_irqrestore(&shwdt_lock, flags);
 
 183  *      sh_wdt_ping - Ping the Watchdog
 
 186  *      Clears overflow bit, resets timer counter.
 
 188 static void sh_wdt_ping(unsigned long data)
 
 192         spin_lock_irqsave(&shwdt_lock, flags);
 
 193         if (time_before(jiffies, next_heartbeat)) {
 
 196                 csr = sh_wdt_read_csr();
 
 198                 sh_wdt_write_csr(csr);
 
 202                 mod_timer(&timer, next_ping_period(clock_division_ratio));
 
 204                 printk(KERN_WARNING PFX "Heartbeat lost! Will not ping "
 
 206         spin_unlock_irqrestore(&shwdt_lock, flags);
 
 210  *      sh_wdt_open - Open the Device
 
 211  *      @inode: inode of device
 
 212  *      @file: file handle of device
 
 214  *      Watchdog device is opened and started.
 
 216 static int sh_wdt_open(struct inode *inode, struct file *file)
 
 218         if (test_and_set_bit(0, &shwdt_is_open))
 
 221                 __module_get(THIS_MODULE);
 
 225         return nonseekable_open(inode, file);
 
 229  *      sh_wdt_close - Close the Device
 
 230  *      @inode: inode of device
 
 231  *      @file: file handle of device
 
 233  *      Watchdog device is closed and stopped.
 
 235 static int sh_wdt_close(struct inode *inode, struct file *file)
 
 237         if (shwdt_expect_close == 42) {
 
 240                 printk(KERN_CRIT PFX "Unexpected close, not "
 
 241                        "stopping watchdog!\n");
 
 245         clear_bit(0, &shwdt_is_open);
 
 246         shwdt_expect_close = 0;
 
 252  *      sh_wdt_write - Write to Device
 
 253  *      @file: file handle of device
 
 254  *      @buf: buffer to write
 
 255  *      @count: length of buffer
 
 258  *      Pings the watchdog on write.
 
 260 static ssize_t sh_wdt_write(struct file *file, const char *buf,
 
 261                             size_t count, loff_t *ppos)
 
 267                         shwdt_expect_close = 0;
 
 269                         for (i = 0; i != count; i++) {
 
 271                                 if (get_user(c, buf + i))
 
 274                                         shwdt_expect_close = 42;
 
 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
 
 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.
 
 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
 
 299 static int sh_wdt_mmap(struct file *file, struct vm_area_struct *vma)
 
 303 #ifdef CONFIG_SH_WDT_MMAP
 
 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)
 
 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.
 
 314         addr = WTCNT & ~(PAGE_SIZE - 1);
 
 316         vma->vm_flags |= VM_IO;
 
 317         vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
 
 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",
 
 333  *      sh_wdt_ioctl - Query Device
 
 334  *      @file: file handle of device
 
 335  *      @cmd: watchdog command
 
 338  *      Query basic information from the device or ping it, as outlined by the
 
 341 static long sh_wdt_ioctl(struct file *file, unsigned int cmd,
 
 345         int options, retval = -EINVAL;
 
 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))
 
 358                 if (options & WDIOS_DISABLECARD) {
 
 363                 if (options & WDIOS_ENABLECARD) {
 
 369         case WDIOC_KEEPALIVE:
 
 372         case WDIOC_SETTIMEOUT:
 
 373                 if (get_user(new_heartbeat, (int *)arg))
 
 376                 if (sh_wdt_set_heartbeat(new_heartbeat))
 
 381         case WDIOC_GETTIMEOUT:
 
 382                 return put_user(heartbeat, (int *)arg);
 
 390  *      sh_wdt_notify_sys - Notifier Handler
 
 391  *      @this: notifier block
 
 392  *      @code: notifier event
 
 395  *      Handles specific events, such as turning off the watchdog during a
 
 398 static int sh_wdt_notify_sys(struct notifier_block *this,
 
 399                              unsigned long code, void *unused)
 
 401         if (code == SYS_DOWN || code == SYS_HALT)
 
 407 static const struct file_operations sh_wdt_fops = {
 
 408         .owner          = THIS_MODULE,
 
 410         .write          = sh_wdt_write,
 
 411         .unlocked_ioctl = sh_wdt_ioctl,
 
 413         .release        = sh_wdt_close,
 
 417 static const struct watchdog_info sh_wdt_info = {
 
 418         .options                = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT |
 
 420         .firmware_version       = 1,
 
 421         .identity               = "SH WDT",
 
 424 static struct notifier_block sh_wdt_notifier = {
 
 425         .notifier_call          = sh_wdt_notify_sys,
 
 428 static struct miscdevice sh_wdt_miscdev = {
 
 429         .minor          = WATCHDOG_MINOR,
 
 431         .fops           = &sh_wdt_fops,
 
 435  *      sh_wdt_init - Initialize module
 
 436  *      Registers the device and notifier handler. Actual device
 
 437  *      initialization is handled by sh_wdt_open().
 
 439 static int __init sh_wdt_init(void)
 
 443         if (clock_division_ratio < 0x5 || clock_division_ratio > 0x7) {
 
 444                 clock_division_ratio = WTCSR_CKS_4096;
 
 446                   "clock_division_ratio value must be 0x5<=x<=0x7, using %d\n",
 
 447                                 clock_division_ratio);
 
 450         rc = sh_wdt_set_heartbeat(heartbeat);
 
 452                 heartbeat = WATCHDOG_HEARTBEAT;
 
 454                         "heartbeat value must be 1<=x<=3600, using %d\n",
 
 458         rc = register_reboot_notifier(&sh_wdt_notifier);
 
 461                         "Can't register reboot notifier (err=%d)\n", rc);
 
 465         rc = misc_register(&sh_wdt_miscdev);
 
 468                         "Can't register miscdev on minor=%d (err=%d)\n",
 
 469                                                 sh_wdt_miscdev.minor, rc);
 
 470                 unregister_reboot_notifier(&sh_wdt_notifier);
 
 474         printk(KERN_INFO PFX "initialized. heartbeat=%d sec (nowayout=%d)\n",
 
 475                 heartbeat, nowayout);
 
 481  *      sh_wdt_exit - Deinitialize module
 
 482  *      Unregisters the device and notifier handler. Actual device
 
 483  *      deinitialization is handled by sh_wdt_close().
 
 485 static void __exit sh_wdt_exit(void)
 
 487         misc_deregister(&sh_wdt_miscdev);
 
 488         unregister_reboot_notifier(&sh_wdt_notifier);
 
 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);
 
 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) ")");
 
 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) ")");
 
 504 module_param(nowayout, int, 0);
 
 505 MODULE_PARM_DESC(nowayout,
 
 506         "Watchdog cannot be stopped once started (default="
 
 507                                 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
 509 module_init(sh_wdt_init);
 
 510 module_exit(sh_wdt_exit);