root/drivers/watchdog/wdt977.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. wdt977_start
  2. wdt977_stop
  3. wdt977_keepalive
  4. wdt977_set_timeout
  5. wdt977_get_status
  6. wdt977_open
  7. wdt977_release
  8. wdt977_write
  9. wdt977_ioctl
  10. wdt977_notify_sys
  11. wd977_init
  12. wd977_exit

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

/* [<][>][^][v][top][bottom][index][help] */