diff options
Diffstat (limited to 'drivers/watchdog/iTCO_wdt.c')
-rw-r--r-- | drivers/watchdog/iTCO_wdt.c | 29 |
1 files changed, 20 insertions, 9 deletions
diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c index 8da886035374..69de8713b8e4 100644 --- a/drivers/watchdog/iTCO_wdt.c +++ b/drivers/watchdog/iTCO_wdt.c | |||
@@ -40,7 +40,7 @@ | |||
40 | 40 | ||
41 | /* Module and version information */ | 41 | /* Module and version information */ |
42 | #define DRV_NAME "iTCO_wdt" | 42 | #define DRV_NAME "iTCO_wdt" |
43 | #define DRV_VERSION "1.05" | 43 | #define DRV_VERSION "1.06" |
44 | #define PFX DRV_NAME ": " | 44 | #define PFX DRV_NAME ": " |
45 | 45 | ||
46 | /* Includes */ | 46 | /* Includes */ |
@@ -391,8 +391,8 @@ static struct platform_device *iTCO_wdt_platform_device; | |||
391 | #define WATCHDOG_HEARTBEAT 30 /* 30 sec default heartbeat */ | 391 | #define WATCHDOG_HEARTBEAT 30 /* 30 sec default heartbeat */ |
392 | static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */ | 392 | static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */ |
393 | module_param(heartbeat, int, 0); | 393 | module_param(heartbeat, int, 0); |
394 | MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. " | 394 | MODULE_PARM_DESC(heartbeat, "Watchdog timeout in seconds. " |
395 | "(2<heartbeat<39 (TCO v1) or 613 (TCO v2), default=" | 395 | "5..76 (TCO v1) or 3..614 (TCO v2), default=" |
396 | __MODULE_STRING(WATCHDOG_HEARTBEAT) ")"); | 396 | __MODULE_STRING(WATCHDOG_HEARTBEAT) ")"); |
397 | 397 | ||
398 | static int nowayout = WATCHDOG_NOWAYOUT; | 398 | static int nowayout = WATCHDOG_NOWAYOUT; |
@@ -523,8 +523,13 @@ static int iTCO_wdt_keepalive(void) | |||
523 | /* Reload the timer by writing to the TCO Timer Counter register */ | 523 | /* Reload the timer by writing to the TCO Timer Counter register */ |
524 | if (iTCO_wdt_private.iTCO_version == 2) | 524 | if (iTCO_wdt_private.iTCO_version == 2) |
525 | outw(0x01, TCO_RLD); | 525 | outw(0x01, TCO_RLD); |
526 | else if (iTCO_wdt_private.iTCO_version == 1) | 526 | else if (iTCO_wdt_private.iTCO_version == 1) { |
527 | /* Reset the timeout status bit so that the timer | ||
528 | * needs to count down twice again before rebooting */ | ||
529 | outw(0x0008, TCO1_STS); /* write 1 to clear bit */ | ||
530 | |||
527 | outb(0x01, TCO_RLD); | 531 | outb(0x01, TCO_RLD); |
532 | } | ||
528 | 533 | ||
529 | spin_unlock(&iTCO_wdt_private.io_lock); | 534 | spin_unlock(&iTCO_wdt_private.io_lock); |
530 | return 0; | 535 | return 0; |
@@ -537,6 +542,11 @@ static int iTCO_wdt_set_heartbeat(int t) | |||
537 | unsigned int tmrval; | 542 | unsigned int tmrval; |
538 | 543 | ||
539 | tmrval = seconds_to_ticks(t); | 544 | tmrval = seconds_to_ticks(t); |
545 | |||
546 | /* For TCO v1 the timer counts down twice before rebooting */ | ||
547 | if (iTCO_wdt_private.iTCO_version == 1) | ||
548 | tmrval /= 2; | ||
549 | |||
540 | /* from the specs: */ | 550 | /* from the specs: */ |
541 | /* "Values of 0h-3h are ignored and should not be attempted" */ | 551 | /* "Values of 0h-3h are ignored and should not be attempted" */ |
542 | if (tmrval < 0x04) | 552 | if (tmrval < 0x04) |
@@ -593,6 +603,8 @@ static int iTCO_wdt_get_timeleft(int *time_left) | |||
593 | spin_lock(&iTCO_wdt_private.io_lock); | 603 | spin_lock(&iTCO_wdt_private.io_lock); |
594 | val8 = inb(TCO_RLD); | 604 | val8 = inb(TCO_RLD); |
595 | val8 &= 0x3f; | 605 | val8 &= 0x3f; |
606 | if (!(inw(TCO1_STS) & 0x0008)) | ||
607 | val8 += (inb(TCOv1_TMR) & 0x3f); | ||
596 | spin_unlock(&iTCO_wdt_private.io_lock); | 608 | spin_unlock(&iTCO_wdt_private.io_lock); |
597 | 609 | ||
598 | *time_left = (val8 * 6) / 10; | 610 | *time_left = (val8 * 6) / 10; |
@@ -832,9 +844,9 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev, | |||
832 | TCOBASE); | 844 | TCOBASE); |
833 | 845 | ||
834 | /* Clear out the (probably old) status */ | 846 | /* Clear out the (probably old) status */ |
835 | outb(8, TCO1_STS); /* Clear the Time Out Status bit */ | 847 | outw(0x0008, TCO1_STS); /* Clear the Time Out Status bit */ |
836 | outb(2, TCO2_STS); /* Clear SECOND_TO_STS bit */ | 848 | outw(0x0002, TCO2_STS); /* Clear SECOND_TO_STS bit */ |
837 | outb(4, TCO2_STS); /* Clear BOOT_STS bit */ | 849 | outw(0x0004, TCO2_STS); /* Clear BOOT_STS bit */ |
838 | 850 | ||
839 | /* Make sure the watchdog is not running */ | 851 | /* Make sure the watchdog is not running */ |
840 | iTCO_wdt_stop(); | 852 | iTCO_wdt_stop(); |
@@ -844,8 +856,7 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev, | |||
844 | if (iTCO_wdt_set_heartbeat(heartbeat)) { | 856 | if (iTCO_wdt_set_heartbeat(heartbeat)) { |
845 | iTCO_wdt_set_heartbeat(WATCHDOG_HEARTBEAT); | 857 | iTCO_wdt_set_heartbeat(WATCHDOG_HEARTBEAT); |
846 | printk(KERN_INFO PFX | 858 | printk(KERN_INFO PFX |
847 | "heartbeat value must be 2 < heartbeat < 39 (TCO v1) " | 859 | "timeout value out of range, using %d\n", heartbeat); |
848 | "or 613 (TCO v2), using %d\n", heartbeat); | ||
849 | } | 860 | } |
850 | 861 | ||
851 | ret = misc_register(&iTCO_wdt_miscdev); | 862 | ret = misc_register(&iTCO_wdt_miscdev); |