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