aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/watchdog/i8xx_tco.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/watchdog/i8xx_tco.c')
-rw-r--r--drivers/char/watchdog/i8xx_tco.c50
1 files changed, 30 insertions, 20 deletions
diff --git a/drivers/char/watchdog/i8xx_tco.c b/drivers/char/watchdog/i8xx_tco.c
index b14d642439ed..a13395e2c372 100644
--- a/drivers/char/watchdog/i8xx_tco.c
+++ b/drivers/char/watchdog/i8xx_tco.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * i8xx_tco 0.07: TCO timer driver for i8xx chipsets 2 * i8xx_tco: TCO timer driver for i8xx chipsets
3 * 3 *
4 * (c) Copyright 2000 kernel concepts <nils@kernelconcepts.de>, All Rights Reserved. 4 * (c) Copyright 2000 kernel concepts <nils@kernelconcepts.de>, All Rights Reserved.
5 * http://www.kernelconcepts.de 5 * http://www.kernelconcepts.de
@@ -63,6 +63,9 @@
63 * 20050128 Wim Van Sebroeck <wim@iguana.be> 63 * 20050128 Wim Van Sebroeck <wim@iguana.be>
64 * 0.07 Added support for the ICH4-M, ICH6, ICH6R, ICH6-M, ICH6W and ICH6RW 64 * 0.07 Added support for the ICH4-M, ICH6, ICH6R, ICH6-M, ICH6W and ICH6RW
65 * chipsets. Also added support for the "undocumented" ICH7 chipset. 65 * chipsets. Also added support for the "undocumented" ICH7 chipset.
66 * 20050807 Wim Van Sebroeck <wim@iguana.be>
67 * 0.08 Make sure that the watchdog is only "armed" when started.
68 * (Kernel Bug 4251)
66 */ 69 */
67 70
68/* 71/*
@@ -87,7 +90,7 @@
87#include "i8xx_tco.h" 90#include "i8xx_tco.h"
88 91
89/* Module and version information */ 92/* Module and version information */
90#define TCO_VERSION "0.07" 93#define TCO_VERSION "0.08"
91#define TCO_MODULE_NAME "i8xx TCO timer" 94#define TCO_MODULE_NAME "i8xx TCO timer"
92#define TCO_DRIVER_NAME TCO_MODULE_NAME ", v" TCO_VERSION 95#define TCO_DRIVER_NAME TCO_MODULE_NAME ", v" TCO_VERSION
93#define PFX TCO_MODULE_NAME ": " 96#define PFX TCO_MODULE_NAME ": "
@@ -105,12 +108,7 @@ static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */
105module_param(heartbeat, int, 0); 108module_param(heartbeat, int, 0);
106MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (2<heartbeat<39, default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")"); 109MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (2<heartbeat<39, default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
107 110
108#ifdef CONFIG_WATCHDOG_NOWAYOUT 111static int nowayout = WATCHDOG_NOWAYOUT;
109static int nowayout = 1;
110#else
111static int nowayout = 0;
112#endif
113
114module_param(nowayout, int, 0); 112module_param(nowayout, int, 0);
115MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); 113MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
116 114
@@ -130,10 +128,18 @@ static int tco_timer_start (void)
130 unsigned char val; 128 unsigned char val;
131 129
132 spin_lock(&tco_lock); 130 spin_lock(&tco_lock);
131
132 /* disable chipset's NO_REBOOT bit */
133 pci_read_config_byte (i8xx_tco_pci, 0xd4, &val);
134 val &= 0xfd;
135 pci_write_config_byte (i8xx_tco_pci, 0xd4, val);
136
137 /* Bit 11: TCO Timer Halt -> 0 = The TCO timer is enabled to count */
133 val = inb (TCO1_CNT + 1); 138 val = inb (TCO1_CNT + 1);
134 val &= 0xf7; 139 val &= 0xf7;
135 outb (val, TCO1_CNT + 1); 140 outb (val, TCO1_CNT + 1);
136 val = inb (TCO1_CNT + 1); 141 val = inb (TCO1_CNT + 1);
142
137 spin_unlock(&tco_lock); 143 spin_unlock(&tco_lock);
138 144
139 if (val & 0x08) 145 if (val & 0x08)
@@ -143,13 +149,20 @@ static int tco_timer_start (void)
143 149
144static int tco_timer_stop (void) 150static int tco_timer_stop (void)
145{ 151{
146 unsigned char val; 152 unsigned char val, val1;
147 153
148 spin_lock(&tco_lock); 154 spin_lock(&tco_lock);
155 /* Bit 11: TCO Timer Halt -> 1 = The TCO timer is disabled */
149 val = inb (TCO1_CNT + 1); 156 val = inb (TCO1_CNT + 1);
150 val |= 0x08; 157 val |= 0x08;
151 outb (val, TCO1_CNT + 1); 158 outb (val, TCO1_CNT + 1);
152 val = inb (TCO1_CNT + 1); 159 val = inb (TCO1_CNT + 1);
160
161 /* Set the NO_REBOOT bit to prevent later reboots, just for sure */
162 pci_read_config_byte (i8xx_tco_pci, 0xd4, &val1);
163 val1 |= 0x02;
164 pci_write_config_byte (i8xx_tco_pci, 0xd4, val1);
165
153 spin_unlock(&tco_lock); 166 spin_unlock(&tco_lock);
154 167
155 if ((val & 0x08) == 0) 168 if ((val & 0x08) == 0)
@@ -160,6 +173,7 @@ static int tco_timer_stop (void)
160static int tco_timer_keepalive (void) 173static int tco_timer_keepalive (void)
161{ 174{
162 spin_lock(&tco_lock); 175 spin_lock(&tco_lock);
176 /* Reload the timer by writing to the TCO Timer Reload register */
163 outb (0x01, TCO1_RLD); 177 outb (0x01, TCO1_RLD);
164 spin_unlock(&tco_lock); 178 spin_unlock(&tco_lock);
165 return 0; 179 return 0;
@@ -401,7 +415,7 @@ static unsigned char __init i8xx_tco_getdevice (void)
401 */ 415 */
402 416
403 while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { 417 while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
404 if (pci_match_device(i8xx_tco_pci_tbl, dev)) { 418 if (pci_match_id(i8xx_tco_pci_tbl, dev)) {
405 i8xx_tco_pci = dev; 419 i8xx_tco_pci = dev;
406 break; 420 break;
407 } 421 }
@@ -422,9 +436,8 @@ static unsigned char __init i8xx_tco_getdevice (void)
422 printk (KERN_ERR PFX "failed to get TCOBASE address\n"); 436 printk (KERN_ERR PFX "failed to get TCOBASE address\n");
423 return 0; 437 return 0;
424 } 438 }
425 /* 439
426 * Check chipset's NO_REBOOT bit 440 /* Check chipset's NO_REBOOT bit */
427 */
428 pci_read_config_byte (i8xx_tco_pci, 0xd4, &val1); 441 pci_read_config_byte (i8xx_tco_pci, 0xd4, &val1);
429 if (val1 & 0x02) { 442 if (val1 & 0x02) {
430 val1 &= 0xfd; 443 val1 &= 0xfd;
@@ -435,6 +448,10 @@ static unsigned char __init i8xx_tco_getdevice (void)
435 return 0; /* Cannot reset NO_REBOOT bit */ 448 return 0; /* Cannot reset NO_REBOOT bit */
436 } 449 }
437 } 450 }
451 /* Disable reboots untill the watchdog starts */
452 val1 |= 0x02;
453 pci_write_config_byte (i8xx_tco_pci, 0xd4, val1);
454
438 /* Set the TCO_EN bit in SMI_EN register */ 455 /* Set the TCO_EN bit in SMI_EN register */
439 if (!request_region (SMI_EN + 1, 1, "i8xx TCO")) { 456 if (!request_region (SMI_EN + 1, 1, "i8xx TCO")) {
440 printk (KERN_ERR PFX "I/O address 0x%04x already in use\n", 457 printk (KERN_ERR PFX "I/O address 0x%04x already in use\n",
@@ -510,17 +527,10 @@ out:
510 527
511static void __exit watchdog_cleanup (void) 528static void __exit watchdog_cleanup (void)
512{ 529{
513 u8 val;
514
515 /* Stop the timer before we leave */ 530 /* Stop the timer before we leave */
516 if (!nowayout) 531 if (!nowayout)
517 tco_timer_stop (); 532 tco_timer_stop ();
518 533
519 /* Set the NO_REBOOT bit to prevent later reboots, just for sure */
520 pci_read_config_byte (i8xx_tco_pci, 0xd4, &val);
521 val |= 0x02;
522 pci_write_config_byte (i8xx_tco_pci, 0xd4, val);
523
524 /* Deregister */ 534 /* Deregister */
525 misc_deregister (&i8xx_tco_miscdev); 535 misc_deregister (&i8xx_tco_miscdev);
526 unregister_reboot_notifier(&i8xx_tco_notifier); 536 unregister_reboot_notifier(&i8xx_tco_notifier);