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