aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/watchdog/Kconfig10
-rw-r--r--drivers/watchdog/it87_wdt.c81
2 files changed, 63 insertions, 28 deletions
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index cc53136122f9..5a5c024482fa 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -565,11 +565,11 @@ config IT87_WDT
565 tristate "IT87 Watchdog Timer" 565 tristate "IT87 Watchdog Timer"
566 depends on X86 && EXPERIMENTAL 566 depends on X86 && EXPERIMENTAL
567 ---help--- 567 ---help---
568 This is the driver for the hardware watchdog on the ITE 568 This is the driver for the hardware watchdog on the ITE IT8702,
569 IT8716, IT8718, IT8720, IT8726, IT8712(Version J,K) Super I/O 569 IT8712, IT8716, IT8718, IT8720, IT8726, IT8712 Super I/O chips.
570 chips. This watchdog simply watches your kernel to make sure 570 This watchdog simply watches your kernel to make sure it doesn't
571 it doesn't freeze, and if it does, it reboots your computer 571 freeze, and if it does, it reboots your computer after a certain
572 after a certain amount of time. 572 amount of time.
573 573
574 To compile this driver as a module, choose M here: the module will 574 To compile this driver as a module, choose M here: the module will
575 be called it87_wdt. 575 be called it87_wdt.
diff --git a/drivers/watchdog/it87_wdt.c b/drivers/watchdog/it87_wdt.c
index 455de7714618..dad29245a6a7 100644
--- a/drivers/watchdog/it87_wdt.c
+++ b/drivers/watchdog/it87_wdt.c
@@ -12,7 +12,7 @@
12 * http://www.ite.com.tw/ 12 * http://www.ite.com.tw/
13 * 13 *
14 * Support of the watchdog timers, which are available on 14 * Support of the watchdog timers, which are available on
15 * IT8716, IT8718, IT8720, IT8726 and IT8712 (J,K version). 15 * IT8702, IT8712, IT8716, IT8718, IT8720 and IT8726.
16 * 16 *
17 * This program is free software; you can redistribute it and/or 17 * This program is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU General Public License 18 * modify it under the terms of the GNU General Public License
@@ -76,6 +76,7 @@
76 76
77/* Chip Id numbers */ 77/* Chip Id numbers */
78#define NO_DEV_ID 0xffff 78#define NO_DEV_ID 0xffff
79#define IT8702_ID 0x8702
79#define IT8705_ID 0x8705 80#define IT8705_ID 0x8705
80#define IT8712_ID 0x8712 81#define IT8712_ID 0x8712
81#define IT8716_ID 0x8716 82#define IT8716_ID 0x8716
@@ -133,7 +134,7 @@
133#define WDTS_USE_GP 4 134#define WDTS_USE_GP 4
134#define WDTS_EXPECTED 5 135#define WDTS_EXPECTED 5
135 136
136static unsigned int base, gpact, ciract; 137static unsigned int base, gpact, ciract, max_units;
137static unsigned long wdt_status; 138static unsigned long wdt_status;
138static DEFINE_SPINLOCK(spinlock); 139static DEFINE_SPINLOCK(spinlock);
139 140
@@ -211,6 +212,33 @@ static inline void superio_outw(int val, int reg)
211 outb(val, VAL); 212 outb(val, VAL);
212} 213}
213 214
215/* Internal function, should be called after superio_select(GPIO) */
216static 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
235static int wdt_round_time(int t)
236{
237 t += 59;
238 t -= t % 60;
239 return t;
240}
241
214/* watchdog timer handling */ 242/* watchdog timer handling */
215 243
216static void wdt_keepalive(void) 244static void wdt_keepalive(void)
@@ -235,12 +263,7 @@ static void wdt_start(void)
235 superio_outb(WDT_GAMEPORT, WDTCTRL); 263 superio_outb(WDT_GAMEPORT, WDTCTRL);
236 else 264 else
237 superio_outb(WDT_CIRINT, WDTCTRL); 265 superio_outb(WDT_CIRINT, WDTCTRL);
238 if (!testmode) 266 wdt_update_timeout();
239 superio_outb(WDT_TOV1 | WDT_KRST | WDT_PWROK, WDTCFG);
240 else
241 superio_outb(WDT_TOV1, WDTCFG);
242 superio_outb(timeout>>8, WDTVALMSB);
243 superio_outb(timeout, WDTVALLSB);
244 267
245 superio_exit(); 268 superio_exit();
246 spin_unlock_irqrestore(&spinlock, flags); 269 spin_unlock_irqrestore(&spinlock, flags);
@@ -256,8 +279,9 @@ static void wdt_stop(void)
256 superio_select(GPIO); 279 superio_select(GPIO);
257 superio_outb(0x00, WDTCTRL); 280 superio_outb(0x00, WDTCTRL);
258 superio_outb(WDT_TOV1, WDTCFG); 281 superio_outb(WDT_TOV1, WDTCFG);
259 superio_outb(0x00, WDTVALMSB);
260 superio_outb(0x00, WDTVALLSB); 282 superio_outb(0x00, WDTVALLSB);
283 if (max_units > 255)
284 superio_outb(0x00, WDTVALMSB);
261 285
262 superio_exit(); 286 superio_exit();
263 spin_unlock_irqrestore(&spinlock, flags); 287 spin_unlock_irqrestore(&spinlock, flags);
@@ -267,8 +291,8 @@ static void wdt_stop(void)
267 * wdt_set_timeout - set a new timeout value with watchdog ioctl 291 * wdt_set_timeout - set a new timeout value with watchdog ioctl
268 * @t: timeout value in seconds 292 * @t: timeout value in seconds
269 * 293 *
270 * The hardware device has a 16 bit watchdog timer, thus the 294 * The hardware device has a 8 or 16 bit watchdog timer (depends on
271 * timeout time ranges between 1 and 65535 seconds. 295 * chip version) that can be configured to count seconds or minutes.
272 * 296 *
273 * Used within WDIOC_SETTIMEOUT watchdog device ioctl. 297 * Used within WDIOC_SETTIMEOUT watchdog device ioctl.
274 */ 298 */
@@ -277,19 +301,19 @@ static int wdt_set_timeout(int t)
277{ 301{
278 unsigned long flags; 302 unsigned long flags;
279 303
280 if (t < 1 || t > 65535) 304 if (t < 1 || t > max_units * 60)
281 return -EINVAL; 305 return -EINVAL;
282 306
283 timeout = t; 307 if (t > max_units)
308 timeout = wdt_round_time(t);
309 else
310 timeout = t;
284 311
285 spin_lock_irqsave(&spinlock, flags); 312 spin_lock_irqsave(&spinlock, flags);
286 if (test_bit(WDTS_TIMER_RUN, &wdt_status)) { 313 if (test_bit(WDTS_TIMER_RUN, &wdt_status)) {
287 superio_enter(); 314 superio_enter();
288
289 superio_select(GPIO); 315 superio_select(GPIO);
290 superio_outb(t>>8, WDTVALMSB); 316 wdt_update_timeout();
291 superio_outb(t, WDTVALLSB);
292
293 superio_exit(); 317 superio_exit();
294 } 318 }
295 spin_unlock_irqrestore(&spinlock, flags); 319 spin_unlock_irqrestore(&spinlock, flags);
@@ -535,6 +559,8 @@ static int __init it87_wdt_init(void)
535 u8 chip_rev; 559 u8 chip_rev;
536 unsigned long flags; 560 unsigned long flags;
537 561
562 wdt_status = 0;
563
538 spin_lock_irqsave(&spinlock, flags); 564 spin_lock_irqsave(&spinlock, flags);
539 superio_enter(); 565 superio_enter();
540 chip_type = superio_inw(CHIPID); 566 chip_type = superio_inw(CHIPID);
@@ -543,16 +569,21 @@ static int __init it87_wdt_init(void)
543 spin_unlock_irqrestore(&spinlock, flags); 569 spin_unlock_irqrestore(&spinlock, flags);
544 570
545 switch (chip_type) { 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;
546 case IT8716_ID: 578 case IT8716_ID:
547 case IT8726_ID: 579 case IT8726_ID:
580 max_units = 65535;
548 break; 581 break;
549 case IT8718_ID: 582 case IT8718_ID:
550 case IT8720_ID: 583 case IT8720_ID:
584 max_units = 65535;
551 try_gameport = 0; 585 try_gameport = 0;
552 break; 586 break;
553 case IT8712_ID:
554 if (chip_rev > 7)
555 break;
556 case IT8705_ID: 587 case IT8705_ID:
557 printk(KERN_ERR PFX 588 printk(KERN_ERR PFX
558 "Unsupported Chip found, Chip %04x Revision %02x\n", 589 "Unsupported Chip found, Chip %04x Revision %02x\n",
@@ -628,13 +659,16 @@ static int __init it87_wdt_init(void)
628 spin_unlock_irqrestore(&spinlock, flags); 659 spin_unlock_irqrestore(&spinlock, flags);
629 } 660 }
630 661
631 if (timeout < 1 || timeout > 65535) { 662 if (timeout < 1 || timeout > max_units * 60) {
632 timeout = DEFAULT_TIMEOUT; 663 timeout = DEFAULT_TIMEOUT;
633 printk(KERN_WARNING PFX 664 printk(KERN_WARNING PFX
634 "Timeout value out of range, use default %d sec\n", 665 "Timeout value out of range, use default %d sec\n",
635 DEFAULT_TIMEOUT); 666 DEFAULT_TIMEOUT);
636 } 667 }
637 668
669 if (timeout > max_units)
670 timeout = wdt_round_time(timeout);
671
638 rc = register_reboot_notifier(&wdt_notifier); 672 rc = register_reboot_notifier(&wdt_notifier);
639 if (rc) { 673 if (rc) {
640 printk(KERN_ERR PFX 674 printk(KERN_ERR PFX
@@ -661,7 +695,7 @@ static int __init it87_wdt_init(void)
661 outb(0x09, CIR_IER(base)); 695 outb(0x09, CIR_IER(base));
662 } 696 }
663 697
664 printk(KERN_INFO PFX "Chip it%04x revision %d initialized. " 698 printk(KERN_INFO PFX "Chip IT%04x revision %d initialized. "
665 "timeout=%d sec (nowayout=%d testmode=%d exclusive=%d " 699 "timeout=%d sec (nowayout=%d testmode=%d exclusive=%d "
666 "nogameport=%d)\n", chip_type, chip_rev, timeout, 700 "nogameport=%d)\n", chip_type, chip_rev, timeout,
667 nowayout, testmode, exclusive, nogameport); 701 nowayout, testmode, exclusive, nogameport);
@@ -703,8 +737,9 @@ static void __exit it87_wdt_exit(void)
703 superio_select(GPIO); 737 superio_select(GPIO);
704 superio_outb(0x00, WDTCTRL); 738 superio_outb(0x00, WDTCTRL);
705 superio_outb(0x00, WDTCFG); 739 superio_outb(0x00, WDTCFG);
706 superio_outb(0x00, WDTVALMSB);
707 superio_outb(0x00, WDTVALLSB); 740 superio_outb(0x00, WDTVALLSB);
741 if (max_units > 255)
742 superio_outb(0x00, WDTVALMSB);
708 if (test_bit(WDTS_USE_GP, &wdt_status)) { 743 if (test_bit(WDTS_USE_GP, &wdt_status)) {
709 superio_select(GAMEPORT); 744 superio_select(GAMEPORT);
710 superio_outb(gpact, ACTREG); 745 superio_outb(gpact, ACTREG);