linux/drivers/watchdog/it87_wdt.c
<<
>>
Prefs
   1/*
   2 *      Watchdog Timer Driver
   3 *         for ITE IT87xx Environment Control - Low Pin Count Input / Output
   4 *
   5 *      (c) Copyright 2007  Oliver Schuster <olivers137@aol.com>
   6 *
   7 *      Based on softdog.c      by Alan Cox,
   8 *               83977f_wdt.c   by Jose Goncalves,
   9 *               it87.c         by Chris Gauthron, Jean Delvare
  10 *
  11 *      Data-sheets: Publicly available at the ITE website
  12 *                  http://www.ite.com.tw/
  13 *
  14 *      Support of the watchdog timers, which are available on
  15 *      IT8702, IT8712, IT8716, IT8718, IT8720 and IT8726.
  16 *
  17 *      This program is free software; you can redistribute it and/or
  18 *      modify it under the terms of the GNU General Public License
  19 *      as published by the Free Software Foundation; either version
  20 *      2 of the License, or (at your option) any later version.
  21 *
  22 *      This program is distributed in the hope that it will be useful,
  23 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
  24 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  25 *      GNU General Public License for more details.
  26 *
  27 *      You should have received a copy of the GNU General Public License
  28 *      along with this program; if not, write to the Free Software
  29 *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  30 */
  31
  32#include <linux/module.h>
  33#include <linux/moduleparam.h>
  34#include <linux/types.h>
  35#include <linux/kernel.h>
  36#include <linux/fs.h>
  37#include <linux/miscdevice.h>
  38#include <linux/init.h>
  39#include <linux/ioport.h>
  40#include <linux/watchdog.h>
  41#include <linux/notifier.h>
  42#include <linux/reboot.h>
  43#include <linux/uaccess.h>
  44#include <linux/io.h>
  45
  46#include <asm/system.h>
  47
  48#define WATCHDOG_VERSION        "1.13"
  49#define WATCHDOG_NAME           "IT87 WDT"
  50#define PFX                     WATCHDOG_NAME ": "
  51#define DRIVER_VERSION          WATCHDOG_NAME " driver, v" WATCHDOG_VERSION "\n"
  52#define WD_MAGIC                'V'
  53
  54/* Defaults for Module Parameter */
  55#define DEFAULT_NOGAMEPORT      0
  56#define DEFAULT_EXCLUSIVE       1
  57#define DEFAULT_TIMEOUT         60
  58#define DEFAULT_TESTMODE        0
  59#define DEFAULT_NOWAYOUT        WATCHDOG_NOWAYOUT
  60
  61/* IO Ports */
  62#define REG             0x2e
  63#define VAL             0x2f
  64
  65/* Logical device Numbers LDN */
  66#define GPIO            0x07
  67#define GAMEPORT        0x09
  68#define CIR             0x0a
  69
  70/* Configuration Registers and Functions */
  71#define LDNREG          0x07
  72#define CHIPID          0x20
  73#define CHIPREV         0x22
  74#define ACTREG          0x30
  75#define BASEREG         0x60
  76
  77/* Chip Id numbers */
  78#define NO_DEV_ID       0xffff
  79#define IT8702_ID       0x8702
  80#define IT8705_ID       0x8705
  81#define IT8712_ID       0x8712
  82#define IT8716_ID       0x8716
  83#define IT8718_ID       0x8718
  84#define IT8720_ID       0x8720
  85#define IT8726_ID       0x8726  /* the data sheet suggest wrongly 0x8716 */
  86
  87/* GPIO Configuration Registers LDN=0x07 */
  88#define WDTCTRL         0x71
  89#define WDTCFG          0x72
  90#define WDTVALLSB       0x73
  91#define WDTVALMSB       0x74
  92
  93/* GPIO Bits WDTCTRL */
  94#define WDT_CIRINT      0x80
  95#define WDT_MOUSEINT    0x40
  96#define WDT_KYBINT      0x20
  97#define WDT_GAMEPORT    0x10 /* not in it8718, it8720 */
  98#define WDT_FORCE       0x02
  99#define WDT_ZERO        0x01
 100
 101/* GPIO Bits WDTCFG */
 102#define WDT_TOV1        0x80
 103#define WDT_KRST        0x40
 104#define WDT_TOVE        0x20
 105#define WDT_PWROK       0x10
 106#define WDT_INT_MASK    0x0f
 107
 108/* CIR Configuration Register LDN=0x0a */
 109#define CIR_ILS         0x70
 110
 111/* The default Base address is not always available, we use this */
 112#define CIR_BASE        0x0208
 113
 114/* CIR Controller */
 115#define CIR_DR(b)       (b)
 116#define CIR_IER(b)      (b + 1)
 117#define CIR_RCR(b)      (b + 2)
 118#define CIR_TCR1(b)     (b + 3)
 119#define CIR_TCR2(b)     (b + 4)
 120#define CIR_TSR(b)      (b + 5)
 121#define CIR_RSR(b)      (b + 6)
 122#define CIR_BDLR(b)     (b + 5)
 123#define CIR_BDHR(b)     (b + 6)
 124#define CIR_IIR(b)      (b + 7)
 125
 126/* Default Base address of Game port */
 127#define GP_BASE_DEFAULT 0x0201
 128
 129/* wdt_status */
 130#define WDTS_TIMER_RUN  0
 131#define WDTS_DEV_OPEN   1
 132#define WDTS_KEEPALIVE  2
 133#define WDTS_LOCKED     3
 134#define WDTS_USE_GP     4
 135#define WDTS_EXPECTED   5
 136
 137static  unsigned int base, gpact, ciract, max_units;
 138static  unsigned long wdt_status;
 139static  DEFINE_SPINLOCK(spinlock);
 140
 141static  int nogameport = DEFAULT_NOGAMEPORT;
 142static  int exclusive  = DEFAULT_EXCLUSIVE;
 143static  int timeout    = DEFAULT_TIMEOUT;
 144static  int testmode   = DEFAULT_TESTMODE;
 145static  int nowayout   = DEFAULT_NOWAYOUT;
 146
 147module_param(nogameport, int, 0);
 148MODULE_PARM_DESC(nogameport, "Forbid the activation of game port, default="
 149                __MODULE_STRING(DEFAULT_NOGAMEPORT));
 150module_param(exclusive, int, 0);
 151MODULE_PARM_DESC(exclusive, "Watchdog exclusive device open, default="
 152                __MODULE_STRING(DEFAULT_EXCLUSIVE));
 153module_param(timeout, int, 0);
 154MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds, default="
 155                __MODULE_STRING(DEFAULT_TIMEOUT));
 156module_param(testmode, int, 0);
 157MODULE_PARM_DESC(testmode, "Watchdog test mode (1 = no reboot), default="
 158                __MODULE_STRING(DEFAULT_TESTMODE));
 159module_param(nowayout, int, 0);
 160MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started, default="
 161                __MODULE_STRING(WATCHDOG_NOWAYOUT));
 162
 163/* Superio Chip */
 164
 165static inline void superio_enter(void)
 166{
 167        outb(0x87, REG);
 168        outb(0x01, REG);
 169        outb(0x55, REG);
 170        outb(0x55, REG);
 171}
 172
 173static inline void superio_exit(void)
 174{
 175        outb(0x02, REG);
 176        outb(0x02, VAL);
 177}
 178
 179static inline void superio_select(int ldn)
 180{
 181        outb(LDNREG, REG);
 182        outb(ldn, VAL);
 183}
 184
 185static inline int superio_inb(int reg)
 186{
 187        outb(reg, REG);
 188        return inb(VAL);
 189}
 190
 191static inline void superio_outb(int val, int reg)
 192{
 193        outb(reg, REG);
 194        outb(val, VAL);
 195}
 196
 197static inline int superio_inw(int reg)
 198{
 199        int val;
 200        outb(reg++, REG);
 201        val = inb(VAL) << 8;
 202        outb(reg, REG);
 203        val |= inb(VAL);
 204        return val;
 205}
 206
 207static inline void superio_outw(int val, int reg)
 208{
 209        outb(reg++, REG);
 210        outb(val >> 8, VAL);
 211        outb(reg, REG);
 212        outb(val, VAL);
 213}
 214
 215/* Internal function, should be called after superio_select(GPIO) */
 216static void wdt_update_timeout(void)
 217{
 218        unsigned char cfg = WDT_KRST | WDT_PWROK;
 219        int tm = timeout;
 220
 221        if (testmode)
 222                cfg = 0;
 223
 224        if (tm <= max_units)
 225                cfg |= WDT_TOV1;
 226        else
 227                tm /= 60;
 228
 229        superio_outb(cfg, WDTCFG);
 230        superio_outb(tm, WDTVALLSB);
 231        if (max_units > 255)
 232                superio_outb(tm>>8, WDTVALMSB);
 233}
 234
 235static int wdt_round_time(int t)
 236{
 237        t += 59;
 238        t -= t % 60;
 239        return t;
 240}
 241
 242/* watchdog timer handling */
 243
 244static void wdt_keepalive(void)
 245{
 246        if (test_bit(WDTS_USE_GP, &wdt_status))
 247                inb(base);
 248        else
 249                /* The timer reloads with around 5 msec delay */
 250                outb(0x55, CIR_DR(base));
 251        set_bit(WDTS_KEEPALIVE, &wdt_status);
 252}
 253
 254static void wdt_start(void)
 255{
 256        unsigned long flags;
 257
 258        spin_lock_irqsave(&spinlock, flags);
 259        superio_enter();
 260
 261        superio_select(GPIO);
 262        if (test_bit(WDTS_USE_GP, &wdt_status))
 263                superio_outb(WDT_GAMEPORT, WDTCTRL);
 264        else
 265                superio_outb(WDT_CIRINT, WDTCTRL);
 266        wdt_update_timeout();
 267
 268        superio_exit();
 269        spin_unlock_irqrestore(&spinlock, flags);
 270}
 271
 272static void wdt_stop(void)
 273{
 274        unsigned long flags;
 275
 276        spin_lock_irqsave(&spinlock, flags);
 277        superio_enter();
 278
 279        superio_select(GPIO);
 280        superio_outb(0x00, WDTCTRL);
 281        superio_outb(WDT_TOV1, WDTCFG);
 282        superio_outb(0x00, WDTVALLSB);
 283        if (max_units > 255)
 284                superio_outb(0x00, WDTVALMSB);
 285
 286        superio_exit();
 287        spin_unlock_irqrestore(&spinlock, flags);
 288}
 289
 290/**
 291 *      wdt_set_timeout - set a new timeout value with watchdog ioctl
 292 *      @t: timeout value in seconds
 293 *
 294 *      The hardware device has a 8 or 16 bit watchdog timer (depends on
 295 *      chip version) that can be configured to count seconds or minutes.
 296 *
 297 *      Used within WDIOC_SETTIMEOUT watchdog device ioctl.
 298 */
 299
 300static int wdt_set_timeout(int t)
 301{
 302        unsigned long flags;
 303
 304        if (t < 1 || t > max_units * 60)
 305                return -EINVAL;
 306
 307        if (t > max_units)
 308                timeout = wdt_round_time(t);
 309        else
 310                timeout = t;
 311
 312        spin_lock_irqsave(&spinlock, flags);
 313        if (test_bit(WDTS_TIMER_RUN, &wdt_status)) {
 314                superio_enter();
 315                superio_select(GPIO);
 316                wdt_update_timeout();
 317                superio_exit();
 318        }
 319        spin_unlock_irqrestore(&spinlock, flags);
 320        return 0;
 321}
 322
 323/**
 324 *      wdt_get_status - determines the status supported by watchdog ioctl
 325 *      @status: status returned to user space
 326 *
 327 *      The status bit of the device does not allow to distinguish
 328 *      between a regular system reset and a watchdog forced reset.
 329 *      But, in test mode it is useful, so it is supported through
 330 *      WDIOC_GETSTATUS watchdog ioctl. Additionally the driver
 331 *      reports the keepalive signal and the acception of the magic.
 332 *
 333 *      Used within WDIOC_GETSTATUS watchdog device ioctl.
 334 */
 335
 336static int wdt_get_status(int *status)
 337{
 338        unsigned long flags;
 339
 340        *status = 0;
 341        if (testmode) {
 342                spin_lock_irqsave(&spinlock, flags);
 343                superio_enter();
 344                superio_select(GPIO);
 345                if (superio_inb(WDTCTRL) & WDT_ZERO) {
 346                        superio_outb(0x00, WDTCTRL);
 347                        clear_bit(WDTS_TIMER_RUN, &wdt_status);
 348                        *status |= WDIOF_CARDRESET;
 349                }
 350
 351                superio_exit();
 352                spin_unlock_irqrestore(&spinlock, flags);
 353        }
 354        if (test_and_clear_bit(WDTS_KEEPALIVE, &wdt_status))
 355                *status |= WDIOF_KEEPALIVEPING;
 356        if (test_bit(WDTS_EXPECTED, &wdt_status))
 357                *status |= WDIOF_MAGICCLOSE;
 358        return 0;
 359}
 360
 361/* /dev/watchdog handling */
 362
 363/**
 364 *      wdt_open - watchdog file_operations .open
 365 *      @inode: inode of the device
 366 *      @file: file handle to the device
 367 *
 368 *      The watchdog timer starts by opening the device.
 369 *
 370 *      Used within the file operation of the watchdog device.
 371 */
 372
 373static int wdt_open(struct inode *inode, struct file *file)
 374{
 375        if (exclusive && test_and_set_bit(WDTS_DEV_OPEN, &wdt_status))
 376                return -EBUSY;
 377        if (!test_and_set_bit(WDTS_TIMER_RUN, &wdt_status)) {
 378                if (nowayout && !test_and_set_bit(WDTS_LOCKED, &wdt_status))
 379                        __module_get(THIS_MODULE);
 380                wdt_start();
 381        }
 382        return nonseekable_open(inode, file);
 383}
 384
 385/**
 386 *      wdt_release - watchdog file_operations .release
 387 *      @inode: inode of the device
 388 *      @file: file handle to the device
 389 *
 390 *      Closing the watchdog device either stops the watchdog timer
 391 *      or in the case, that nowayout is set or the magic character
 392 *      wasn't written, a critical warning about an running watchdog
 393 *      timer is given.
 394 *
 395 *      Used within the file operation of the watchdog device.
 396 */
 397
 398static int wdt_release(struct inode *inode, struct file *file)
 399{
 400        if (test_bit(WDTS_TIMER_RUN, &wdt_status)) {
 401                if (test_and_clear_bit(WDTS_EXPECTED, &wdt_status)) {
 402                        wdt_stop();
 403                        clear_bit(WDTS_TIMER_RUN, &wdt_status);
 404                } else {
 405                        wdt_keepalive();
 406                        printk(KERN_CRIT PFX
 407                               "unexpected close, not stopping watchdog!\n");
 408                }
 409        }
 410        clear_bit(WDTS_DEV_OPEN, &wdt_status);
 411        return 0;
 412}
 413
 414/**
 415 *      wdt_write - watchdog file_operations .write
 416 *      @file: file handle to the watchdog
 417 *      @buf: buffer to write
 418 *      @count: count of bytes
 419 *      @ppos: pointer to the position to write. No seeks allowed
 420 *
 421 *      A write to a watchdog device is defined as a keepalive signal. Any
 422 *      write of data will do, as we don't define content meaning.
 423 *
 424 *      Used within the file operation of the watchdog device.
 425 */
 426
 427static ssize_t wdt_write(struct file *file, const char __user *buf,
 428                            size_t count, loff_t *ppos)
 429{
 430        if (count) {
 431                clear_bit(WDTS_EXPECTED, &wdt_status);
 432                wdt_keepalive();
 433        }
 434        if (!nowayout) {
 435                size_t ofs;
 436
 437        /* note: just in case someone wrote the magic character long ago */
 438                for (ofs = 0; ofs != count; ofs++) {
 439                        char c;
 440                        if (get_user(c, buf + ofs))
 441                                return -EFAULT;
 442                        if (c == WD_MAGIC)
 443                                set_bit(WDTS_EXPECTED, &wdt_status);
 444                }
 445        }
 446        return count;
 447}
 448
 449static const struct watchdog_info ident = {
 450        .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING,
 451        .firmware_version =     1,
 452        .identity = WATCHDOG_NAME,
 453};
 454
 455/**
 456 *      wdt_ioctl - watchdog file_operations .unlocked_ioctl
 457 *      @file: file handle to the device
 458 *      @cmd: watchdog command
 459 *      @arg: argument pointer
 460 *
 461 *      The watchdog API defines a common set of functions for all watchdogs
 462 *      according to their available features.
 463 *
 464 *      Used within the file operation of the watchdog device.
 465 */
 466
 467static long wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 468{
 469        int rc = 0, status, new_options, new_timeout;
 470        union {
 471                struct watchdog_info __user *ident;
 472                int __user *i;
 473        } uarg;
 474
 475        uarg.i = (int __user *)arg;
 476
 477        switch (cmd) {
 478        case WDIOC_GETSUPPORT:
 479                return copy_to_user(uarg.ident,
 480                                    &ident, sizeof(ident)) ? -EFAULT : 0;
 481
 482        case WDIOC_GETSTATUS:
 483                wdt_get_status(&status);
 484                return put_user(status, uarg.i);
 485
 486        case WDIOC_GETBOOTSTATUS:
 487                return put_user(0, uarg.i);
 488
 489        case WDIOC_KEEPALIVE:
 490                wdt_keepalive();
 491                return 0;
 492
 493        case WDIOC_SETOPTIONS:
 494                if (get_user(new_options, uarg.i))
 495                        return -EFAULT;
 496
 497                switch (new_options) {
 498                case WDIOS_DISABLECARD:
 499                        if (test_bit(WDTS_TIMER_RUN, &wdt_status))
 500                                wdt_stop();
 501                        clear_bit(WDTS_TIMER_RUN, &wdt_status);
 502                        return 0;
 503
 504                case WDIOS_ENABLECARD:
 505                        if (!test_and_set_bit(WDTS_TIMER_RUN, &wdt_status))
 506                                wdt_start();
 507                        return 0;
 508
 509                default:
 510                        return -EFAULT;
 511                }
 512
 513        case WDIOC_SETTIMEOUT:
 514                if (get_user(new_timeout, uarg.i))
 515                        return -EFAULT;
 516                rc = wdt_set_timeout(new_timeout);
 517        case WDIOC_GETTIMEOUT:
 518                if (put_user(timeout, uarg.i))
 519                        return -EFAULT;
 520                return rc;
 521
 522        default:
 523                return -ENOTTY;
 524        }
 525}
 526
 527static int wdt_notify_sys(struct notifier_block *this, unsigned long code,
 528        void *unused)
 529{
 530        if (code == SYS_DOWN || code == SYS_HALT)
 531                wdt_stop();
 532        return NOTIFY_DONE;
 533}
 534
 535static const struct file_operations wdt_fops = {
 536        .owner          = THIS_MODULE,
 537        .llseek         = no_llseek,
 538        .write          = wdt_write,
 539        .unlocked_ioctl = wdt_ioctl,
 540        .open           = wdt_open,
 541        .release        = wdt_release,
 542};
 543
 544static struct miscdevice wdt_miscdev = {
 545        .minor          = WATCHDOG_MINOR,
 546        .name           = "watchdog",
 547        .fops           = &wdt_fops,
 548};
 549
 550static struct notifier_block wdt_notifier = {
 551        .notifier_call = wdt_notify_sys,
 552};
 553
 554static int __init it87_wdt_init(void)
 555{
 556        int rc = 0;
 557        int try_gameport = !nogameport;
 558        u16 chip_type;
 559        u8  chip_rev;
 560        unsigned long flags;
 561
 562        wdt_status = 0;
 563
 564        spin_lock_irqsave(&spinlock, flags);
 565        superio_enter();
 566        chip_type = superio_inw(CHIPID);
 567        chip_rev  = superio_inb(CHIPREV) & 0x0f;
 568        superio_exit();
 569        spin_unlock_irqrestore(&spinlock, flags);
 570
 571        switch (chip_type) {
 572        case IT8702_ID:
 573                max_units = 255;
 574                break;
 575        case IT8712_ID:
 576                max_units = (chip_rev < 8) ? 255 : 65535;
 577                break;
 578        case IT8716_ID:
 579        case IT8726_ID:
 580                max_units = 65535;
 581                break;
 582        case IT8718_ID:
 583        case IT8720_ID:
 584                max_units = 65535;
 585                try_gameport = 0;
 586                break;
 587        case IT8705_ID:
 588                printk(KERN_ERR PFX
 589                       "Unsupported Chip found, Chip %04x Revision %02x\n",
 590                       chip_type, chip_rev);
 591                return -ENODEV;
 592        case NO_DEV_ID:
 593                printk(KERN_ERR PFX "no device\n");
 594                return -ENODEV;
 595        default:
 596                printk(KERN_ERR PFX
 597                       "Unknown Chip found, Chip %04x Revision %04x\n",
 598                       chip_type, chip_rev);
 599                return -ENODEV;
 600        }
 601
 602        spin_lock_irqsave(&spinlock, flags);
 603        superio_enter();
 604
 605        superio_select(GPIO);
 606        superio_outb(WDT_TOV1, WDTCFG);
 607        superio_outb(0x00, WDTCTRL);
 608
 609        /* First try to get Gameport support */
 610        if (try_gameport) {
 611                superio_select(GAMEPORT);
 612                base = superio_inw(BASEREG);
 613                if (!base) {
 614                        base = GP_BASE_DEFAULT;
 615                        superio_outw(base, BASEREG);
 616                }
 617                gpact = superio_inb(ACTREG);
 618                superio_outb(0x01, ACTREG);
 619                superio_exit();
 620                spin_unlock_irqrestore(&spinlock, flags);
 621                if (request_region(base, 1, WATCHDOG_NAME))
 622                        set_bit(WDTS_USE_GP, &wdt_status);
 623                else
 624                        rc = -EIO;
 625        } else {
 626                superio_exit();
 627                spin_unlock_irqrestore(&spinlock, flags);
 628        }
 629
 630        /* If we haven't Gameport support, try to get CIR support */
 631        if (!test_bit(WDTS_USE_GP, &wdt_status)) {
 632                if (!request_region(CIR_BASE, 8, WATCHDOG_NAME)) {
 633                        if (rc == -EIO)
 634                                printk(KERN_ERR PFX
 635                                        "I/O Address 0x%04x and 0x%04x"
 636                                        " already in use\n", base, CIR_BASE);
 637                        else
 638                                printk(KERN_ERR PFX
 639                                        "I/O Address 0x%04x already in use\n",
 640                                        CIR_BASE);
 641                        rc = -EIO;
 642                        goto err_out;
 643                }
 644                base = CIR_BASE;
 645                spin_lock_irqsave(&spinlock, flags);
 646                superio_enter();
 647
 648                superio_select(CIR);
 649                superio_outw(base, BASEREG);
 650                superio_outb(0x00, CIR_ILS);
 651                ciract = superio_inb(ACTREG);
 652                superio_outb(0x01, ACTREG);
 653                if (rc == -EIO) {
 654                        superio_select(GAMEPORT);
 655                        superio_outb(gpact, ACTREG);
 656                }
 657
 658                superio_exit();
 659                spin_unlock_irqrestore(&spinlock, flags);
 660        }
 661
 662        if (timeout < 1 || timeout > max_units * 60) {
 663                timeout = DEFAULT_TIMEOUT;
 664                printk(KERN_WARNING PFX
 665                       "Timeout value out of range, use default %d sec\n",
 666                       DEFAULT_TIMEOUT);
 667        }
 668
 669        if (timeout > max_units)
 670                timeout = wdt_round_time(timeout);
 671
 672        rc = register_reboot_notifier(&wdt_notifier);
 673        if (rc) {
 674                printk(KERN_ERR PFX
 675                       "Cannot register reboot notifier (err=%d)\n", rc);
 676                goto err_out_region;
 677        }
 678
 679        rc = misc_register(&wdt_miscdev);
 680        if (rc) {
 681                printk(KERN_ERR PFX
 682                       "Cannot register miscdev on minor=%d (err=%d)\n",
 683                        wdt_miscdev.minor, rc);
 684                goto err_out_reboot;
 685        }
 686
 687        /* Initialize CIR to use it as keepalive source */
 688        if (!test_bit(WDTS_USE_GP, &wdt_status)) {
 689                outb(0x00, CIR_RCR(base));
 690                outb(0xc0, CIR_TCR1(base));
 691                outb(0x5c, CIR_TCR2(base));
 692                outb(0x10, CIR_IER(base));
 693                outb(0x00, CIR_BDHR(base));
 694                outb(0x01, CIR_BDLR(base));
 695                outb(0x09, CIR_IER(base));
 696        }
 697
 698        printk(KERN_INFO PFX "Chip IT%04x revision %d initialized. "
 699                "timeout=%d sec (nowayout=%d testmode=%d exclusive=%d "
 700                "nogameport=%d)\n", chip_type, chip_rev, timeout,
 701                nowayout, testmode, exclusive, nogameport);
 702
 703        return 0;
 704
 705err_out_reboot:
 706        unregister_reboot_notifier(&wdt_notifier);
 707err_out_region:
 708        release_region(base, test_bit(WDTS_USE_GP, &wdt_status) ? 1 : 8);
 709        if (!test_bit(WDTS_USE_GP, &wdt_status)) {
 710                spin_lock_irqsave(&spinlock, flags);
 711                superio_enter();
 712                superio_select(CIR);
 713                superio_outb(ciract, ACTREG);
 714                superio_exit();
 715                spin_unlock_irqrestore(&spinlock, flags);
 716        }
 717err_out:
 718        if (try_gameport) {
 719                spin_lock_irqsave(&spinlock, flags);
 720                superio_enter();
 721                superio_select(GAMEPORT);
 722                superio_outb(gpact, ACTREG);
 723                superio_exit();
 724                spin_unlock_irqrestore(&spinlock, flags);
 725        }
 726
 727        return rc;
 728}
 729
 730static void __exit it87_wdt_exit(void)
 731{
 732        unsigned long flags;
 733        int nolock;
 734
 735        nolock = !spin_trylock_irqsave(&spinlock, flags);
 736        superio_enter();
 737        superio_select(GPIO);
 738        superio_outb(0x00, WDTCTRL);
 739        superio_outb(0x00, WDTCFG);
 740        superio_outb(0x00, WDTVALLSB);
 741        if (max_units > 255)
 742                superio_outb(0x00, WDTVALMSB);
 743        if (test_bit(WDTS_USE_GP, &wdt_status)) {
 744                superio_select(GAMEPORT);
 745                superio_outb(gpact, ACTREG);
 746        } else {
 747                superio_select(CIR);
 748                superio_outb(ciract, ACTREG);
 749        }
 750        superio_exit();
 751        if (!nolock)
 752                spin_unlock_irqrestore(&spinlock, flags);
 753
 754        misc_deregister(&wdt_miscdev);
 755        unregister_reboot_notifier(&wdt_notifier);
 756        release_region(base, test_bit(WDTS_USE_GP, &wdt_status) ? 1 : 8);
 757}
 758
 759module_init(it87_wdt_init);
 760module_exit(it87_wdt_exit);
 761
 762MODULE_AUTHOR("Oliver Schuster");
 763MODULE_DESCRIPTION("Hardware Watchdog Device Driver for IT87xx EC-LPC I/O");
 764MODULE_LICENSE("GPL");
 765MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
 766