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