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