aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/watchdog/iTCO_wdt.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/watchdog/iTCO_wdt.c')
-rw-r--r--drivers/char/watchdog/iTCO_wdt.c48
1 files changed, 43 insertions, 5 deletions
diff --git a/drivers/char/watchdog/iTCO_wdt.c b/drivers/char/watchdog/iTCO_wdt.c
index aaac94db0d8b..7eac922df867 100644
--- a/drivers/char/watchdog/iTCO_wdt.c
+++ b/drivers/char/watchdog/iTCO_wdt.c
@@ -35,6 +35,10 @@
35 * 82801GDH (ICH7DH) : document number 307013-002, 307014-009, 35 * 82801GDH (ICH7DH) : document number 307013-002, 307014-009,
36 * 82801GBM (ICH7-M) : document number 307013-002, 307014-009, 36 * 82801GBM (ICH7-M) : document number 307013-002, 307014-009,
37 * 82801GHM (ICH7-M DH) : document number 307013-002, 307014-009, 37 * 82801GHM (ICH7-M DH) : document number 307013-002, 307014-009,
38 * 82801HB (ICH8) : document number 313056-002, 313057-004,
39 * 82801HR (ICH8R) : document number 313056-002, 313057-004,
40 * 82801HH (ICH8DH) : document number 313056-002, 313057-004,
41 * 82801HO (ICH8DO) : document number 313056-002, 313057-004,
38 * 6300ESB (6300ESB) : document number 300641-003 42 * 6300ESB (6300ESB) : document number 300641-003
39 */ 43 */
40 44
@@ -44,8 +48,8 @@
44 48
45/* Module and version information */ 49/* Module and version information */
46#define DRV_NAME "iTCO_wdt" 50#define DRV_NAME "iTCO_wdt"
47#define DRV_VERSION "1.00" 51#define DRV_VERSION "1.01"
48#define DRV_RELDATE "30-Jul-2006" 52#define DRV_RELDATE "11-Nov-2006"
49#define PFX DRV_NAME ": " 53#define PFX DRV_NAME ": "
50 54
51/* Includes */ 55/* Includes */
@@ -85,6 +89,9 @@ enum iTCO_chipsets {
85 TCO_ICH7, /* ICH7 & ICH7R */ 89 TCO_ICH7, /* ICH7 & ICH7R */
86 TCO_ICH7M, /* ICH7-M */ 90 TCO_ICH7M, /* ICH7-M */
87 TCO_ICH7MDH, /* ICH7-M DH */ 91 TCO_ICH7MDH, /* ICH7-M DH */
92 TCO_ICH8, /* ICH8 & ICH8R */
93 TCO_ICH8DH, /* ICH8DH */
94 TCO_ICH8DO, /* ICH8DO */
88}; 95};
89 96
90static struct { 97static struct {
@@ -108,6 +115,9 @@ static struct {
108 {"ICH7 or ICH7R", 2}, 115 {"ICH7 or ICH7R", 2},
109 {"ICH7-M", 2}, 116 {"ICH7-M", 2},
110 {"ICH7-M DH", 2}, 117 {"ICH7-M DH", 2},
118 {"ICH8 or ICH8R", 2},
119 {"ICH8DH", 2},
120 {"ICH8DO", 2},
111 {NULL,0} 121 {NULL,0}
112}; 122};
113 123
@@ -135,6 +145,9 @@ static struct pci_device_id iTCO_wdt_pci_tbl[] = {
135 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH7 }, 145 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH7 },
136 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH7M }, 146 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH7M },
137 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_31, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH7MDH }, 147 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_31, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH7MDH },
148 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH8 },
149 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH8DH },
150 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH8DO },
138 { 0, }, /* End of list */ 151 { 0, }, /* End of list */
139}; 152};
140MODULE_DEVICE_TABLE (pci, iTCO_wdt_pci_tbl); 153MODULE_DEVICE_TABLE (pci, iTCO_wdt_pci_tbl);
@@ -176,6 +189,21 @@ static int nowayout = WATCHDOG_NOWAYOUT;
176module_param(nowayout, int, 0); 189module_param(nowayout, int, 0);
177MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); 190MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
178 191
192/* iTCO Vendor Specific Support hooks */
193#ifdef CONFIG_ITCO_VENDOR_SUPPORT
194extern void iTCO_vendor_pre_start(unsigned long, unsigned int);
195extern void iTCO_vendor_pre_stop(unsigned long);
196extern void iTCO_vendor_pre_keepalive(unsigned long, unsigned int);
197extern void iTCO_vendor_pre_set_heartbeat(unsigned int);
198extern int iTCO_vendor_check_noreboot_on(void);
199#else
200#define iTCO_vendor_pre_start(acpibase, heartbeat) {}
201#define iTCO_vendor_pre_stop(acpibase) {}
202#define iTCO_vendor_pre_keepalive(acpibase,heartbeat) {}
203#define iTCO_vendor_pre_set_heartbeat(heartbeat) {}
204#define iTCO_vendor_check_noreboot_on() 1 /* 1=check noreboot; 0=don't check */
205#endif
206
179/* 207/*
180 * Some TCO specific functions 208 * Some TCO specific functions
181 */ 209 */
@@ -236,6 +264,8 @@ static int iTCO_wdt_start(void)
236 264
237 spin_lock(&iTCO_wdt_private.io_lock); 265 spin_lock(&iTCO_wdt_private.io_lock);
238 266
267 iTCO_vendor_pre_start(iTCO_wdt_private.ACPIBASE, heartbeat);
268
239 /* disable chipset's NO_REBOOT bit */ 269 /* disable chipset's NO_REBOOT bit */
240 if (iTCO_wdt_unset_NO_REBOOT_bit()) { 270 if (iTCO_wdt_unset_NO_REBOOT_bit()) {
241 printk(KERN_ERR PFX "failed to reset NO_REBOOT flag, reboot disabled by hardware\n"); 271 printk(KERN_ERR PFX "failed to reset NO_REBOOT flag, reboot disabled by hardware\n");
@@ -260,6 +290,8 @@ static int iTCO_wdt_stop(void)
260 290
261 spin_lock(&iTCO_wdt_private.io_lock); 291 spin_lock(&iTCO_wdt_private.io_lock);
262 292
293 iTCO_vendor_pre_stop(iTCO_wdt_private.ACPIBASE);
294
263 /* Bit 11: TCO Timer Halt -> 1 = The TCO timer is disabled */ 295 /* Bit 11: TCO Timer Halt -> 1 = The TCO timer is disabled */
264 val = inw(TCO1_CNT); 296 val = inw(TCO1_CNT);
265 val |= 0x0800; 297 val |= 0x0800;
@@ -280,6 +312,8 @@ static int iTCO_wdt_keepalive(void)
280{ 312{
281 spin_lock(&iTCO_wdt_private.io_lock); 313 spin_lock(&iTCO_wdt_private.io_lock);
282 314
315 iTCO_vendor_pre_keepalive(iTCO_wdt_private.ACPIBASE, heartbeat);
316
283 /* Reload the timer by writing to the TCO Timer Counter register */ 317 /* Reload the timer by writing to the TCO Timer Counter register */
284 if (iTCO_wdt_private.iTCO_version == 2) { 318 if (iTCO_wdt_private.iTCO_version == 2) {
285 outw(0x01, TCO_RLD); 319 outw(0x01, TCO_RLD);
@@ -306,6 +340,8 @@ static int iTCO_wdt_set_heartbeat(int t)
306 ((iTCO_wdt_private.iTCO_version == 1) && (tmrval > 0x03f))) 340 ((iTCO_wdt_private.iTCO_version == 1) && (tmrval > 0x03f)))
307 return -EINVAL; 341 return -EINVAL;
308 342
343 iTCO_vendor_pre_set_heartbeat(tmrval);
344
309 /* Write new heartbeat to watchdog */ 345 /* Write new heartbeat to watchdog */
310 if (iTCO_wdt_private.iTCO_version == 2) { 346 if (iTCO_wdt_private.iTCO_version == 2) {
311 spin_lock(&iTCO_wdt_private.io_lock); 347 spin_lock(&iTCO_wdt_private.io_lock);
@@ -355,7 +391,8 @@ static int iTCO_wdt_get_timeleft (int *time_left)
355 spin_unlock(&iTCO_wdt_private.io_lock); 391 spin_unlock(&iTCO_wdt_private.io_lock);
356 392
357 *time_left = (val8 * 6) / 10; 393 *time_left = (val8 * 6) / 10;
358 } 394 } else
395 return -EINVAL;
359 return 0; 396 return 0;
360} 397}
361 398
@@ -426,7 +463,6 @@ static int iTCO_wdt_ioctl (struct inode *inode, struct file *file,
426{ 463{
427 int new_options, retval = -EINVAL; 464 int new_options, retval = -EINVAL;
428 int new_heartbeat; 465 int new_heartbeat;
429 int time_left;
430 void __user *argp = (void __user *)arg; 466 void __user *argp = (void __user *)arg;
431 int __user *p = argp; 467 int __user *p = argp;
432 static struct watchdog_info ident = { 468 static struct watchdog_info ident = {
@@ -486,6 +522,8 @@ static int iTCO_wdt_ioctl (struct inode *inode, struct file *file,
486 522
487 case WDIOC_GETTIMELEFT: 523 case WDIOC_GETTIMELEFT:
488 { 524 {
525 int time_left;
526
489 if (iTCO_wdt_get_timeleft(&time_left)) 527 if (iTCO_wdt_get_timeleft(&time_left))
490 return -EINVAL; 528 return -EINVAL;
491 529
@@ -554,7 +592,7 @@ static int iTCO_wdt_init(struct pci_dev *pdev, const struct pci_device_id *ent,
554 } 592 }
555 593
556 /* Check chipset's NO_REBOOT bit */ 594 /* Check chipset's NO_REBOOT bit */
557 if (iTCO_wdt_unset_NO_REBOOT_bit()) { 595 if (iTCO_wdt_unset_NO_REBOOT_bit() && iTCO_vendor_check_noreboot_on()) {
558 printk(KERN_ERR PFX "failed to reset NO_REBOOT flag, reboot disabled by hardware\n"); 596 printk(KERN_ERR PFX "failed to reset NO_REBOOT flag, reboot disabled by hardware\n");
559 ret = -ENODEV; /* Cannot reset NO_REBOOT bit */ 597 ret = -ENODEV; /* Cannot reset NO_REBOOT bit */
560 goto out; 598 goto out;