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 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 int 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, int, 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 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 452 static 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 474 static 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 492 static 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 562 static 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 570 static 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 579 static struct miscdevice wdt_miscdev = { 580 .minor = WATCHDOG_MINOR, 581 .name = "watchdog", 582 .fops = &wdt_fops, 583 }; 584 585 static struct notifier_block wdt_notifier = { 586 .notifier_call = wdt_notify_sys, 587 }; 588 589 static 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 733 err_out_reboot: 734 unregister_reboot_notifier(&wdt_notifier); 735 err_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 } 741 err_out: 742 if (try_gameport) { 743 superio_select(GAMEPORT); 744 superio_outb(gpact, ACTREG); 745 } 746 747 superio_exit(); 748 return rc; 749 } 750 751 static 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 775 module_init(it87_wdt_init); 776 module_exit(it87_wdt_exit); 777 778 MODULE_AUTHOR("Oliver Schuster"); 779 MODULE_DESCRIPTION("Hardware Watchdog Device Driver for IT87xx EC-LPC I/O"); 780 MODULE_LICENSE("GPL"); 781 MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); 782