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 138 static unsigned int base, gpact, ciract, max_units, chip_type; 139 static unsigned long wdt_status; 140 141 static int nogameport = DEFAULT_NOGAMEPORT; 142 static int exclusive = DEFAULT_EXCLUSIVE; 143 static int timeout = DEFAULT_TIMEOUT; 144 static int testmode = DEFAULT_TESTMODE; 145 static bool nowayout = DEFAULT_NOWAYOUT; 146 147 module_param(nogameport, int, 0); 148 MODULE_PARM_DESC(nogameport, "Forbid the activation of game port, default=" 149 __MODULE_STRING(DEFAULT_NOGAMEPORT)); 150 module_param(exclusive, int, 0); 151 MODULE_PARM_DESC(exclusive, "Watchdog exclusive device open, default=" 152 __MODULE_STRING(DEFAULT_EXCLUSIVE)); 153 module_param(timeout, int, 0); 154 MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds, default=" 155 __MODULE_STRING(DEFAULT_TIMEOUT)); 156 module_param(testmode, int, 0); 157 MODULE_PARM_DESC(testmode, "Watchdog test mode (1 = no reboot), default=" 158 __MODULE_STRING(DEFAULT_TESTMODE)); 159 module_param(nowayout, bool, 0); 160 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started, default=" 161 __MODULE_STRING(WATCHDOG_NOWAYOUT)); 162 163 /* Superio Chip */ 164 165 static 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 180 static inline void superio_exit(void) 181 { 182 outb(0x02, REG); 183 outb(0x02, VAL); 184 release_region(REG, 2); 185 } 186 187 static inline void superio_select(int ldn) 188 { 189 outb(LDNREG, REG); 190 outb(ldn, VAL); 191 } 192 193 static inline int superio_inb(int reg) 194 { 195 outb(reg, REG); 196 return inb(VAL); 197 } 198 199 static inline void superio_outb(int val, int reg) 200 { 201 outb(reg, REG); 202 outb(val, VAL); 203 } 204 205 static 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 215 static 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) */ 224 static 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 246 static int wdt_round_time(int t) 247 { 248 t += 59; 249 t -= t % 60; 250 return t; 251 } 252 253 /* watchdog timer handling */ 254 255 static 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 265 static 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 283 static 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 310 static 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 345 static 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 381 static 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 414 static 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 451 static 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 473 static 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 491 static 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 561 static 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 569 static 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 578 static struct miscdevice wdt_miscdev = { 579 .minor = WATCHDOG_MINOR, 580 .name = "watchdog", 581 .fops = &wdt_fops, 582 }; 583 584 static struct notifier_block wdt_notifier = { 585 .notifier_call = wdt_notify_sys, 586 }; 587 588 static 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 724 err_out_reboot: 725 unregister_reboot_notifier(&wdt_notifier); 726 err_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 } 732 err_out: 733 if (try_gameport) { 734 superio_select(GAMEPORT); 735 superio_outb(gpact, ACTREG); 736 } 737 738 superio_exit(); 739 return rc; 740 } 741 742 static 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 766 module_init(it87_wdt_init); 767 module_exit(it87_wdt_exit); 768 769 MODULE_AUTHOR("Oliver Schuster"); 770 MODULE_DESCRIPTION("Hardware Watchdog Device Driver for IT87xx EC-LPC I/O"); 771 MODULE_LICENSE("GPL"); 772 MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); 773