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#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.14"
  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 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  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 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                        printk(KERN_CRIT PFX
 432                               "unexpected close, not stopping watchdog!\n");
 433                }
 434        }
 435        clear_bit(WDTS_DEV_OPEN, &wdt_status);
 436        return 0;
 437}
 438
 439/**
 440 *      wdt_write - watchdog file_operations .write
 441 *      @file: file handle to the watchdog
 442 *      @buf: buffer to write
 443 *      @count: count of bytes
 444 *      @ppos: pointer to the position to write. No seeks allowed
 445 *
 446 *      A write to a watchdog device is defined as a keepalive signal. Any
 447 *      write of data will do, as we don't define content meaning.
 448 *
 449 *      Used within the file operation of the watchdog device.
 450 */
 451
 452static ssize_t wdt_write(struct file *file, const char __user *buf,
 453                            size_t count, loff_t *ppos)
 454{
 455        if (count) {
 456                clear_bit(WDTS_EXPECTED, &wdt_status);
 457                wdt_keepalive();
 458        }
 459        if (!nowayout) {
 460                size_t ofs;
 461
 462        /* note: just in case someone wrote the magic character long ago */
 463                for (ofs = 0; ofs != count; ofs++) {
 464                        char c;
 465                        if (get_user(c, buf + ofs))
 466                                return -EFAULT;
 467                        if (c == WD_MAGIC)
 468                                set_bit(WDTS_EXPECTED, &wdt_status);
 469                }
 470        }
 471        return count;
 472}
 473
 474static const struct watchdog_info ident = {
 475        .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING,
 476        .firmware_version =     1,
 477        .identity = WATCHDOG_NAME,
 478};
 479
 480/**
 481 *      wdt_ioctl - watchdog file_operations .unlocked_ioctl
 482 *      @file: file handle to the device
 483 *      @cmd: watchdog command
 484 *      @arg: argument pointer
 485 *
 486 *      The watchdog API defines a common set of functions for all watchdogs
 487 *      according to their available features.
 488 *
 489 *      Used within the file operation of the watchdog device.
 490 */
 491
 492static long wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 493{
 494        int rc = 0, status, new_options, new_timeout;
 495        union {
 496                struct watchdog_info __user *ident;
 497                int __user *i;
 498        } uarg;
 499
 500        uarg.i = (int __user *)arg;
 501
 502        switch (cmd) {
 503        case WDIOC_GETSUPPORT:
 504                return copy_to_user(uarg.ident,
 505                                    &ident, sizeof(ident)) ? -EFAULT : 0;
 506
 507        case WDIOC_GETSTATUS:
 508                rc = wdt_get_status(&status);
 509                if (rc)
 510                        return rc;
 511                return put_user(status, uarg.i);
 512
 513        case WDIOC_GETBOOTSTATUS:
 514                return put_user(0, uarg.i);
 515
 516        case WDIOC_KEEPALIVE:
 517                wdt_keepalive();
 518                return 0;
 519
 520        case WDIOC_SETOPTIONS:
 521                if (get_user(new_options, uarg.i))
 522                        return -EFAULT;
 523
 524                switch (new_options) {
 525                case WDIOS_DISABLECARD:
 526                        if (test_bit(WDTS_TIMER_RUN, &wdt_status)) {
 527                                rc = wdt_stop();
 528                                if (rc)
 529                                        return rc;
 530                        }
 531                        clear_bit(WDTS_TIMER_RUN, &wdt_status);
 532                        return 0;
 533
 534                case WDIOS_ENABLECARD:
 535                        if (!test_and_set_bit(WDTS_TIMER_RUN, &wdt_status)) {
 536                                rc = wdt_start();
 537                                if (rc) {
 538                                        clear_bit(WDTS_TIMER_RUN, &wdt_status);
 539                                        return rc;
 540                                }
 541                        }
 542                        return 0;
 543
 544                default:
 545                        return -EFAULT;
 546                }
 547
 548        case WDIOC_SETTIMEOUT:
 549                if (get_user(new_timeout, uarg.i))
 550                        return -EFAULT;
 551                rc = wdt_set_timeout(new_timeout);
 552        case WDIOC_GETTIMEOUT:
 553                if (put_user(timeout, uarg.i))
 554                        return -EFAULT;
 555                return rc;
 556
 557        default:
 558                return -ENOTTY;
 559        }
 560}
 561
 562static int wdt_notify_sys(struct notifier_block *this, unsigned long code,
 563        void *unused)
 564{
 565        if (code == SYS_DOWN || code == SYS_HALT)
 566                wdt_stop();
 567        return NOTIFY_DONE;
 568}
 569
 570static const struct file_operations wdt_fops = {
 571        .owner          = THIS_MODULE,
 572        .llseek         = no_llseek,
 573        .write          = wdt_write,
 574        .unlocked_ioctl = wdt_ioctl,
 575        .open           = wdt_open,
 576        .release        = wdt_release,
 577};
 578
 579static struct miscdevice wdt_miscdev = {
 580        .minor          = WATCHDOG_MINOR,
 581        .name           = "watchdog",
 582        .fops           = &wdt_fops,
 583};
 584
 585static struct notifier_block wdt_notifier = {
 586        .notifier_call = wdt_notify_sys,
 587};
 588
 589static int __init it87_wdt_init(void)
 590{
 591        int rc = 0;
 592        int try_gameport = !nogameport;
 593        u8  chip_rev;
 594        int gp_rreq_fail = 0;
 595
 596        wdt_status = 0;
 597
 598        rc = superio_enter();
 599        if (rc)
 600                return rc;
 601
 602        chip_type = superio_inw(CHIPID);
 603        chip_rev  = superio_inb(CHIPREV) & 0x0f;
 604        superio_exit();
 605
 606        switch (chip_type) {
 607        case IT8702_ID:
 608                max_units = 255;
 609                break;
 610        case IT8712_ID:
 611                max_units = (chip_rev < 8) ? 255 : 65535;
 612                break;
 613        case IT8716_ID:
 614        case IT8726_ID:
 615                max_units = 65535;
 616                break;
 617        case IT8718_ID:
 618        case IT8720_ID:
 619        case IT8721_ID:
 620                max_units = 65535;
 621                try_gameport = 0;
 622                break;
 623        case IT8705_ID:
 624                printk(KERN_ERR PFX
 625                       "Unsupported Chip found, Chip %04x Revision %02x\n",
 626                       chip_type, chip_rev);
 627                return -ENODEV;
 628        case NO_DEV_ID:
 629                printk(KERN_ERR PFX "no device\n");
 630                return -ENODEV;
 631        default:
 632                printk(KERN_ERR PFX
 633                       "Unknown Chip found, Chip %04x Revision %04x\n",
 634                       chip_type, chip_rev);
 635                return -ENODEV;
 636        }
 637
 638        rc = superio_enter();
 639        if (rc)
 640                return rc;
 641
 642        superio_select(GPIO);
 643        superio_outb(WDT_TOV1, WDTCFG);
 644        superio_outb(0x00, WDTCTRL);
 645
 646        /* First try to get Gameport support */
 647        if (try_gameport) {
 648                superio_select(GAMEPORT);
 649                base = superio_inw(BASEREG);
 650                if (!base) {
 651                        base = GP_BASE_DEFAULT;
 652                        superio_outw(base, BASEREG);
 653                }
 654                gpact = superio_inb(ACTREG);
 655                superio_outb(0x01, ACTREG);
 656                if (request_region(base, 1, WATCHDOG_NAME))
 657                        set_bit(WDTS_USE_GP, &wdt_status);
 658                else
 659                        gp_rreq_fail = 1;
 660        }
 661
 662        /* If we haven't Gameport support, try to get CIR support */
 663        if (!test_bit(WDTS_USE_GP, &wdt_status)) {
 664                if (!request_region(CIR_BASE, 8, WATCHDOG_NAME)) {
 665                        if (gp_rreq_fail)
 666                                printk(KERN_ERR PFX
 667                                        "I/O Address 0x%04x and 0x%04x"
 668                                        " already in use\n", base, CIR_BASE);
 669                        else
 670                                printk(KERN_ERR PFX
 671                                        "I/O Address 0x%04x already in use\n",
 672                                        CIR_BASE);
 673                        rc = -EIO;
 674                        goto err_out;
 675                }
 676                base = CIR_BASE;
 677
 678                superio_select(CIR);
 679                superio_outw(base, BASEREG);
 680                superio_outb(0x00, CIR_ILS);
 681                ciract = superio_inb(ACTREG);
 682                superio_outb(0x01, ACTREG);
 683                if (gp_rreq_fail) {
 684                        superio_select(GAMEPORT);
 685                        superio_outb(gpact, ACTREG);
 686                }
 687        }
 688
 689        if (timeout < 1 || timeout > max_units * 60) {
 690                timeout = DEFAULT_TIMEOUT;
 691                printk(KERN_WARNING PFX
 692                       "Timeout value out of range, use default %d sec\n",
 693                       DEFAULT_TIMEOUT);
 694        }
 695
 696        if (timeout > max_units)
 697                timeout = wdt_round_time(timeout);
 698
 699        rc = register_reboot_notifier(&wdt_notifier);
 700        if (rc) {
 701                printk(KERN_ERR PFX
 702                       "Cannot register reboot notifier (err=%d)\n", rc);
 703                goto err_out_region;
 704        }
 705
 706        rc = misc_register(&wdt_miscdev);
 707        if (rc) {
 708                printk(KERN_ERR PFX
 709                       "Cannot register miscdev on minor=%d (err=%d)\n",
 710                        wdt_miscdev.minor, rc);
 711                goto err_out_reboot;
 712        }
 713
 714        /* Initialize CIR to use it as keepalive source */
 715        if (!test_bit(WDTS_USE_GP, &wdt_status)) {
 716                outb(0x00, CIR_RCR(base));
 717                outb(0xc0, CIR_TCR1(base));
 718                outb(0x5c, CIR_TCR2(base));
 719                outb(0x10, CIR_IER(base));
 720                outb(0x00, CIR_BDHR(base));
 721                outb(0x01, CIR_BDLR(base));
 722                outb(0x09, CIR_IER(base));
 723        }
 724
 725        printk(KERN_INFO PFX "Chip IT%04x revision %d initialized. "
 726                "timeout=%d sec (nowayout=%d testmode=%d exclusive=%d "
 727                "nogameport=%d)\n", chip_type, chip_rev, timeout,
 728                nowayout, testmode, exclusive, nogameport);
 729
 730        superio_exit();
 731        return 0;
 732
 733err_out_reboot:
 734        unregister_reboot_notifier(&wdt_notifier);
 735err_out_region:
 736        release_region(base, test_bit(WDTS_USE_GP, &wdt_status) ? 1 : 8);
 737        if (!test_bit(WDTS_USE_GP, &wdt_status)) {
 738                superio_select(CIR);
 739                superio_outb(ciract, ACTREG);
 740        }
 741err_out:
 742        if (try_gameport) {
 743                superio_select(GAMEPORT);
 744                superio_outb(gpact, ACTREG);
 745        }
 746
 747        superio_exit();
 748        return rc;
 749}
 750
 751static void __exit it87_wdt_exit(void)
 752{
 753        if (superio_enter() == 0) {
 754                superio_select(GPIO);
 755                superio_outb(0x00, WDTCTRL);
 756                superio_outb(0x00, WDTCFG);
 757                superio_outb(0x00, WDTVALLSB);
 758                if (max_units > 255)
 759                        superio_outb(0x00, WDTVALMSB);
 760                if (test_bit(WDTS_USE_GP, &wdt_status)) {
 761                        superio_select(GAMEPORT);
 762                        superio_outb(gpact, ACTREG);
 763                } else {
 764                        superio_select(CIR);
 765                        superio_outb(ciract, ACTREG);
 766                }
 767                superio_exit();
 768        }
 769
 770        misc_deregister(&wdt_miscdev);
 771        unregister_reboot_notifier(&wdt_notifier);
 772        release_region(base, test_bit(WDTS_USE_GP, &wdt_status) ? 1 : 8);
 773}
 774
 775module_init(it87_wdt_init);
 776module_exit(it87_wdt_exit);
 777
 778MODULE_AUTHOR("Oliver Schuster");
 779MODULE_DESCRIPTION("Hardware Watchdog Device Driver for IT87xx EC-LPC I/O");
 780MODULE_LICENSE("GPL");
 781MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
 782