aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/watchdog/iTCO_wdt.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/watchdog/iTCO_wdt.c')
-rw-r--r--drivers/watchdog/iTCO_wdt.c71
1 files changed, 49 insertions, 22 deletions
diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c
index 8da886035374..2c6c2b4ad8bf 100644
--- a/drivers/watchdog/iTCO_wdt.c
+++ b/drivers/watchdog/iTCO_wdt.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * intel TCO Watchdog Driver 2 * intel TCO Watchdog Driver
3 * 3 *
4 * (c) Copyright 2006-2009 Wim Van Sebroeck <wim@iguana.be>. 4 * (c) Copyright 2006-2010 Wim Van Sebroeck <wim@iguana.be>.
5 * 5 *
6 * This program is free software; you can redistribute it and/or 6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License 7 * modify it under the terms of the GNU General Public License
@@ -26,12 +26,15 @@
26 * document number 301473-002, 301474-026: 82801F (ICH6) 26 * document number 301473-002, 301474-026: 82801F (ICH6)
27 * document number 313082-001, 313075-006: 631xESB, 632xESB 27 * document number 313082-001, 313075-006: 631xESB, 632xESB
28 * document number 307013-003, 307014-024: 82801G (ICH7) 28 * document number 307013-003, 307014-024: 82801G (ICH7)
29 * document number 322896-001, 322897-001: NM10
29 * document number 313056-003, 313057-017: 82801H (ICH8) 30 * document number 313056-003, 313057-017: 82801H (ICH8)
30 * document number 316972-004, 316973-012: 82801I (ICH9) 31 * document number 316972-004, 316973-012: 82801I (ICH9)
31 * document number 319973-002, 319974-002: 82801J (ICH10) 32 * document number 319973-002, 319974-002: 82801J (ICH10)
32 * document number 322169-001, 322170-003: 5 Series, 3400 Series (PCH) 33 * document number 322169-001, 322170-003: 5 Series, 3400 Series (PCH)
33 * document number 320066-003, 320257-008: EP80597 (IICH) 34 * document number 320066-003, 320257-008: EP80597 (IICH)
34 * document number TBD : Cougar Point (CPT) 35 * document number 324645-001, 324646-001: Cougar Point (CPT)
36 * document number TBD : Patsburg (PBG)
37 * document number TBD : DH89xxCC
35 */ 38 */
36 39
37/* 40/*
@@ -40,7 +43,7 @@
40 43
41/* Module and version information */ 44/* Module and version information */
42#define DRV_NAME "iTCO_wdt" 45#define DRV_NAME "iTCO_wdt"
43#define DRV_VERSION "1.05" 46#define DRV_VERSION "1.06"
44#define PFX DRV_NAME ": " 47#define PFX DRV_NAME ": "
45 48
46/* Includes */ 49/* Includes */
@@ -84,6 +87,7 @@ enum iTCO_chipsets {
84 TCO_ICH7DH, /* ICH7DH */ 87 TCO_ICH7DH, /* ICH7DH */
85 TCO_ICH7M, /* ICH7-M & ICH7-U */ 88 TCO_ICH7M, /* ICH7-M & ICH7-U */
86 TCO_ICH7MDH, /* ICH7-M DH */ 89 TCO_ICH7MDH, /* ICH7-M DH */
90 TCO_NM10, /* NM10 */
87 TCO_ICH8, /* ICH8 & ICH8R */ 91 TCO_ICH8, /* ICH8 & ICH8R */
88 TCO_ICH8DH, /* ICH8DH */ 92 TCO_ICH8DH, /* ICH8DH */
89 TCO_ICH8DO, /* ICH8DO */ 93 TCO_ICH8DO, /* ICH8DO */
@@ -146,6 +150,9 @@ enum iTCO_chipsets {
146 TCO_CPT29, /* Cougar Point */ 150 TCO_CPT29, /* Cougar Point */
147 TCO_CPT30, /* Cougar Point */ 151 TCO_CPT30, /* Cougar Point */
148 TCO_CPT31, /* Cougar Point */ 152 TCO_CPT31, /* Cougar Point */
153 TCO_PBG1, /* Patsburg */
154 TCO_PBG2, /* Patsburg */
155 TCO_DH89XXCC, /* DH89xxCC */
149}; 156};
150 157
151static struct { 158static struct {
@@ -171,6 +178,7 @@ static struct {
171 {"ICH7DH", 2}, 178 {"ICH7DH", 2},
172 {"ICH7-M or ICH7-U", 2}, 179 {"ICH7-M or ICH7-U", 2},
173 {"ICH7-M DH", 2}, 180 {"ICH7-M DH", 2},
181 {"NM10", 2},
174 {"ICH8 or ICH8R", 2}, 182 {"ICH8 or ICH8R", 2},
175 {"ICH8DH", 2}, 183 {"ICH8DH", 2},
176 {"ICH8DO", 2}, 184 {"ICH8DO", 2},
@@ -233,6 +241,9 @@ static struct {
233 {"Cougar Point", 2}, 241 {"Cougar Point", 2},
234 {"Cougar Point", 2}, 242 {"Cougar Point", 2},
235 {"Cougar Point", 2}, 243 {"Cougar Point", 2},
244 {"Patsburg", 2},
245 {"Patsburg", 2},
246 {"DH89xxCC", 2},
236 {NULL, 0} 247 {NULL, 0}
237}; 248};
238 249
@@ -286,6 +297,7 @@ static struct pci_device_id iTCO_wdt_pci_tbl[] = {
286 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_30, TCO_ICH7DH)}, 297 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_30, TCO_ICH7DH)},
287 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_1, TCO_ICH7M)}, 298 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_1, TCO_ICH7M)},
288 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_31, TCO_ICH7MDH)}, 299 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_31, TCO_ICH7MDH)},
300 { ITCO_PCI_DEVICE(0x27bc, TCO_NM10)},
289 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_0, TCO_ICH8)}, 301 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_0, TCO_ICH8)},
290 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_2, TCO_ICH8DH)}, 302 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_2, TCO_ICH8DH)},
291 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_3, TCO_ICH8DO)}, 303 { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_3, TCO_ICH8DO)},
@@ -348,6 +360,9 @@ static struct pci_device_id iTCO_wdt_pci_tbl[] = {
348 { ITCO_PCI_DEVICE(0x1c5d, TCO_CPT29)}, 360 { ITCO_PCI_DEVICE(0x1c5d, TCO_CPT29)},
349 { ITCO_PCI_DEVICE(0x1c5e, TCO_CPT30)}, 361 { ITCO_PCI_DEVICE(0x1c5e, TCO_CPT30)},
350 { ITCO_PCI_DEVICE(0x1c5f, TCO_CPT31)}, 362 { ITCO_PCI_DEVICE(0x1c5f, TCO_CPT31)},
363 { ITCO_PCI_DEVICE(0x1d40, TCO_PBG1)},
364 { ITCO_PCI_DEVICE(0x1d41, TCO_PBG2)},
365 { ITCO_PCI_DEVICE(0x2310, TCO_DH89XXCC)},
351 { 0, }, /* End of list */ 366 { 0, }, /* End of list */
352}; 367};
353MODULE_DEVICE_TABLE(pci, iTCO_wdt_pci_tbl); 368MODULE_DEVICE_TABLE(pci, iTCO_wdt_pci_tbl);
@@ -374,7 +389,7 @@ static char expect_release;
374static struct { /* this is private data for the iTCO_wdt device */ 389static struct { /* this is private data for the iTCO_wdt device */
375 /* TCO version/generation */ 390 /* TCO version/generation */
376 unsigned int iTCO_version; 391 unsigned int iTCO_version;
377 /* The cards ACPIBASE address (TCOBASE = ACPIBASE+0x60) */ 392 /* The device's ACPIBASE address (TCOBASE = ACPIBASE+0x60) */
378 unsigned long ACPIBASE; 393 unsigned long ACPIBASE;
379 /* NO_REBOOT flag is Memory-Mapped GCS register bit 5 (TCO version 2)*/ 394 /* NO_REBOOT flag is Memory-Mapped GCS register bit 5 (TCO version 2)*/
380 unsigned long __iomem *gcs; 395 unsigned long __iomem *gcs;
@@ -391,8 +406,8 @@ static struct platform_device *iTCO_wdt_platform_device;
391#define WATCHDOG_HEARTBEAT 30 /* 30 sec default heartbeat */ 406#define WATCHDOG_HEARTBEAT 30 /* 30 sec default heartbeat */
392static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */ 407static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */
393module_param(heartbeat, int, 0); 408module_param(heartbeat, int, 0);
394MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. " 409MODULE_PARM_DESC(heartbeat, "Watchdog timeout in seconds. "
395 "(2<heartbeat<39 (TCO v1) or 613 (TCO v2), default=" 410 "5..76 (TCO v1) or 3..614 (TCO v2), default="
396 __MODULE_STRING(WATCHDOG_HEARTBEAT) ")"); 411 __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
397 412
398static int nowayout = WATCHDOG_NOWAYOUT; 413static int nowayout = WATCHDOG_NOWAYOUT;
@@ -467,7 +482,7 @@ static int iTCO_wdt_start(void)
467 if (iTCO_wdt_unset_NO_REBOOT_bit()) { 482 if (iTCO_wdt_unset_NO_REBOOT_bit()) {
468 spin_unlock(&iTCO_wdt_private.io_lock); 483 spin_unlock(&iTCO_wdt_private.io_lock);
469 printk(KERN_ERR PFX "failed to reset NO_REBOOT flag, " 484 printk(KERN_ERR PFX "failed to reset NO_REBOOT flag, "
470 "reboot disabled by hardware\n"); 485 "reboot disabled by hardware/BIOS\n");
471 return -EIO; 486 return -EIO;
472 } 487 }
473 488
@@ -523,8 +538,13 @@ static int iTCO_wdt_keepalive(void)
523 /* Reload the timer by writing to the TCO Timer Counter register */ 538 /* Reload the timer by writing to the TCO Timer Counter register */
524 if (iTCO_wdt_private.iTCO_version == 2) 539 if (iTCO_wdt_private.iTCO_version == 2)
525 outw(0x01, TCO_RLD); 540 outw(0x01, TCO_RLD);
526 else if (iTCO_wdt_private.iTCO_version == 1) 541 else if (iTCO_wdt_private.iTCO_version == 1) {
542 /* Reset the timeout status bit so that the timer
543 * needs to count down twice again before rebooting */
544 outw(0x0008, TCO1_STS); /* write 1 to clear bit */
545
527 outb(0x01, TCO_RLD); 546 outb(0x01, TCO_RLD);
547 }
528 548
529 spin_unlock(&iTCO_wdt_private.io_lock); 549 spin_unlock(&iTCO_wdt_private.io_lock);
530 return 0; 550 return 0;
@@ -537,6 +557,11 @@ static int iTCO_wdt_set_heartbeat(int t)
537 unsigned int tmrval; 557 unsigned int tmrval;
538 558
539 tmrval = seconds_to_ticks(t); 559 tmrval = seconds_to_ticks(t);
560
561 /* For TCO v1 the timer counts down twice before rebooting */
562 if (iTCO_wdt_private.iTCO_version == 1)
563 tmrval /= 2;
564
540 /* from the specs: */ 565 /* from the specs: */
541 /* "Values of 0h-3h are ignored and should not be attempted" */ 566 /* "Values of 0h-3h are ignored and should not be attempted" */
542 if (tmrval < 0x04) 567 if (tmrval < 0x04)
@@ -593,6 +618,8 @@ static int iTCO_wdt_get_timeleft(int *time_left)
593 spin_lock(&iTCO_wdt_private.io_lock); 618 spin_lock(&iTCO_wdt_private.io_lock);
594 val8 = inb(TCO_RLD); 619 val8 = inb(TCO_RLD);
595 val8 &= 0x3f; 620 val8 &= 0x3f;
621 if (!(inw(TCO1_STS) & 0x0008))
622 val8 += (inb(TCOv1_TMR) & 0x3f);
596 spin_unlock(&iTCO_wdt_private.io_lock); 623 spin_unlock(&iTCO_wdt_private.io_lock);
597 624
598 *time_left = (val8 * 6) / 10; 625 *time_left = (val8 * 6) / 10;
@@ -769,8 +796,8 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev,
769 base_address &= 0x0000ff80; 796 base_address &= 0x0000ff80;
770 if (base_address == 0x00000000) { 797 if (base_address == 0x00000000) {
771 /* Something's wrong here, ACPIBASE has to be set */ 798 /* Something's wrong here, ACPIBASE has to be set */
772 printk(KERN_ERR PFX "failed to get TCOBASE address\n"); 799 printk(KERN_ERR PFX "failed to get TCOBASE address, "
773 pci_dev_put(pdev); 800 "device disabled by hardware/BIOS\n");
774 return -ENODEV; 801 return -ENODEV;
775 } 802 }
776 iTCO_wdt_private.iTCO_version = 803 iTCO_wdt_private.iTCO_version =
@@ -785,7 +812,8 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev,
785 if (iTCO_wdt_private.iTCO_version == 2) { 812 if (iTCO_wdt_private.iTCO_version == 2) {
786 pci_read_config_dword(pdev, 0xf0, &base_address); 813 pci_read_config_dword(pdev, 0xf0, &base_address);
787 if ((base_address & 1) == 0) { 814 if ((base_address & 1) == 0) {
788 printk(KERN_ERR PFX "RCBA is disabled by hardware\n"); 815 printk(KERN_ERR PFX "RCBA is disabled by hardware"
816 "/BIOS, device disabled\n");
789 ret = -ENODEV; 817 ret = -ENODEV;
790 goto out; 818 goto out;
791 } 819 }
@@ -796,7 +824,7 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev,
796 /* Check chipset's NO_REBOOT bit */ 824 /* Check chipset's NO_REBOOT bit */
797 if (iTCO_wdt_unset_NO_REBOOT_bit() && iTCO_vendor_check_noreboot_on()) { 825 if (iTCO_wdt_unset_NO_REBOOT_bit() && iTCO_vendor_check_noreboot_on()) {
798 printk(KERN_INFO PFX "unable to reset NO_REBOOT flag, " 826 printk(KERN_INFO PFX "unable to reset NO_REBOOT flag, "
799 "platform may have disabled it\n"); 827 "device disabled by hardware/BIOS\n");
800 ret = -ENODEV; /* Cannot reset NO_REBOOT bit */ 828 ret = -ENODEV; /* Cannot reset NO_REBOOT bit */
801 goto out_unmap; 829 goto out_unmap;
802 } 830 }
@@ -807,7 +835,8 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev,
807 /* The TCO logic uses the TCO_EN bit in the SMI_EN register */ 835 /* The TCO logic uses the TCO_EN bit in the SMI_EN register */
808 if (!request_region(SMI_EN, 4, "iTCO_wdt")) { 836 if (!request_region(SMI_EN, 4, "iTCO_wdt")) {
809 printk(KERN_ERR PFX 837 printk(KERN_ERR PFX
810 "I/O address 0x%04lx already in use\n", SMI_EN); 838 "I/O address 0x%04lx already in use, "
839 "device disabled\n", SMI_EN);
811 ret = -EIO; 840 ret = -EIO;
812 goto out_unmap; 841 goto out_unmap;
813 } 842 }
@@ -819,8 +848,8 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev,
819 /* The TCO I/O registers reside in a 32-byte range pointed to 848 /* The TCO I/O registers reside in a 32-byte range pointed to
820 by the TCOBASE value */ 849 by the TCOBASE value */
821 if (!request_region(TCOBASE, 0x20, "iTCO_wdt")) { 850 if (!request_region(TCOBASE, 0x20, "iTCO_wdt")) {
822 printk(KERN_ERR PFX "I/O address 0x%04lx already in use\n", 851 printk(KERN_ERR PFX "I/O address 0x%04lx already in use "
823 TCOBASE); 852 "device disabled\n", TCOBASE);
824 ret = -EIO; 853 ret = -EIO;
825 goto unreg_smi_en; 854 goto unreg_smi_en;
826 } 855 }
@@ -832,9 +861,9 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev,
832 TCOBASE); 861 TCOBASE);
833 862
834 /* Clear out the (probably old) status */ 863 /* Clear out the (probably old) status */
835 outb(8, TCO1_STS); /* Clear the Time Out Status bit */ 864 outw(0x0008, TCO1_STS); /* Clear the Time Out Status bit */
836 outb(2, TCO2_STS); /* Clear SECOND_TO_STS bit */ 865 outw(0x0002, TCO2_STS); /* Clear SECOND_TO_STS bit */
837 outb(4, TCO2_STS); /* Clear BOOT_STS bit */ 866 outw(0x0004, TCO2_STS); /* Clear BOOT_STS bit */
838 867
839 /* Make sure the watchdog is not running */ 868 /* Make sure the watchdog is not running */
840 iTCO_wdt_stop(); 869 iTCO_wdt_stop();
@@ -844,8 +873,7 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev,
844 if (iTCO_wdt_set_heartbeat(heartbeat)) { 873 if (iTCO_wdt_set_heartbeat(heartbeat)) {
845 iTCO_wdt_set_heartbeat(WATCHDOG_HEARTBEAT); 874 iTCO_wdt_set_heartbeat(WATCHDOG_HEARTBEAT);
846 printk(KERN_INFO PFX 875 printk(KERN_INFO PFX
847 "heartbeat value must be 2 < heartbeat < 39 (TCO v1) " 876 "timeout value out of range, using %d\n", heartbeat);
848 "or 613 (TCO v2), using %d\n", heartbeat);
849 } 877 }
850 878
851 ret = misc_register(&iTCO_wdt_miscdev); 879 ret = misc_register(&iTCO_wdt_miscdev);
@@ -869,7 +897,6 @@ out_unmap:
869 if (iTCO_wdt_private.iTCO_version == 2) 897 if (iTCO_wdt_private.iTCO_version == 2)
870 iounmap(iTCO_wdt_private.gcs); 898 iounmap(iTCO_wdt_private.gcs);
871out: 899out:
872 pci_dev_put(iTCO_wdt_private.pdev);
873 iTCO_wdt_private.ACPIBASE = 0; 900 iTCO_wdt_private.ACPIBASE = 0;
874 return ret; 901 return ret;
875} 902}
@@ -910,7 +937,7 @@ static int __devinit iTCO_wdt_probe(struct platform_device *dev)
910 } 937 }
911 938
912 if (!found) 939 if (!found)
913 printk(KERN_INFO PFX "No card detected\n"); 940 printk(KERN_INFO PFX "No device detected.\n");
914 941
915 return ret; 942 return ret;
916} 943}