aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/watchdog/Kconfig23
-rw-r--r--drivers/watchdog/Makefile1
-rw-r--r--drivers/watchdog/bcm63xx_wdt.c350
-rw-r--r--drivers/watchdog/f71808e_wdt.c10
-rw-r--r--drivers/watchdog/iTCO_wdt.c26
-rw-r--r--drivers/watchdog/it8712f_wdt.c25
-rw-r--r--drivers/watchdog/it87_wdt.c96
-rw-r--r--drivers/watchdog/machzwd.c4
8 files changed, 479 insertions, 56 deletions
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index c356146bd712..4a291045ebac 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -409,11 +409,11 @@ config ALIM7101_WDT
409 Most people will say N. 409 Most people will say N.
410 410
411config F71808E_WDT 411config F71808E_WDT
412 tristate "Fintek F71808E and F71882FG Watchdog" 412 tristate "Fintek F71808E, F71882FG and F71889FG Watchdog"
413 depends on X86 && EXPERIMENTAL 413 depends on X86 && EXPERIMENTAL
414 help 414 help
415 This is the driver for the hardware watchdog on the Fintek 415 This is the driver for the hardware watchdog on the Fintek
416 F71808E and F71882FG Super I/O controllers. 416 F71808E, F71882FG and F71889FG Super I/O controllers.
417 417
418 You can compile this driver directly into the kernel, or use 418 You can compile this driver directly into the kernel, or use
419 it as a module. The module will be called f71808e_wdt. 419 it as a module. The module will be called f71808e_wdt.
@@ -565,10 +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 IT8716, 568 This is the driver for the hardware watchdog on the ITE IT8702,
569 IT8718, IT8726, IT8712(Version J,K) Super I/O chips. This watchdog 569 IT8712, IT8716, IT8718, IT8720, IT8726, IT8712 Super I/O chips.
570 simply watches your kernel to make sure it doesn't freeze, and if 570 This watchdog simply watches your kernel to make sure it doesn't
571 it does, it reboots your computer after a certain amount of time. 571 freeze, and if it does, it reboots your computer after a certain
572 amount of time.
572 573
573 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
574 be called it87_wdt. 575 be called it87_wdt.
@@ -916,6 +917,16 @@ config OCTEON_WDT
916 from the first interrupt, it is then only poked when the 917 from the first interrupt, it is then only poked when the
917 device is written. 918 device is written.
918 919
920config BCM63XX_WDT
921 tristate "Broadcom BCM63xx hardware watchdog"
922 depends on BCM63XX
923 help
924 Watchdog driver for the built in watchdog hardware in Broadcom
925 BCM63xx SoC.
926
927 To compile this driver as a loadable module, choose M here.
928 The module will be called bcm63xx_wdt.
929
919# PARISC Architecture 930# PARISC Architecture
920 931
921# POWERPC Architecture 932# POWERPC Architecture
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 8374503fcc6a..4b0ef386229d 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -109,6 +109,7 @@ obj-$(CONFIG_SBC_EPX_C3_WATCHDOG) += sbc_epx_c3.o
109 109
110# MIPS Architecture 110# MIPS Architecture
111obj-$(CONFIG_BCM47XX_WDT) += bcm47xx_wdt.o 111obj-$(CONFIG_BCM47XX_WDT) += bcm47xx_wdt.o
112obj-$(CONFIG_BCM63XX_WDT) += bcm63xx_wdt.o
112obj-$(CONFIG_RC32434_WDT) += rc32434_wdt.o 113obj-$(CONFIG_RC32434_WDT) += rc32434_wdt.o
113obj-$(CONFIG_INDYDOG) += indydog.o 114obj-$(CONFIG_INDYDOG) += indydog.o
114obj-$(CONFIG_WDT_MTX1) += mtx-1_wdt.o 115obj-$(CONFIG_WDT_MTX1) += mtx-1_wdt.o
diff --git a/drivers/watchdog/bcm63xx_wdt.c b/drivers/watchdog/bcm63xx_wdt.c
new file mode 100644
index 000000000000..a1debc89356b
--- /dev/null
+++ b/drivers/watchdog/bcm63xx_wdt.c
@@ -0,0 +1,350 @@
1/*
2 * Broadcom BCM63xx SoC watchdog driver
3 *
4 * Copyright (C) 2007, Miguel Gaio <miguel.gaio@efixo.com>
5 * Copyright (C) 2008, Florian Fainelli <florian@openwrt.org>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version
10 * 2 of the License, or (at your option) any later version.
11 */
12
13#include <linux/bitops.h>
14#include <linux/errno.h>
15#include <linux/fs.h>
16#include <linux/init.h>
17#include <linux/kernel.h>
18#include <linux/miscdevice.h>
19#include <linux/module.h>
20#include <linux/moduleparam.h>
21#include <linux/reboot.h>
22#include <linux/types.h>
23#include <linux/uaccess.h>
24#include <linux/watchdog.h>
25#include <linux/timer.h>
26#include <linux/jiffies.h>
27#include <linux/interrupt.h>
28#include <linux/ptrace.h>
29#include <linux/resource.h>
30#include <linux/platform_device.h>
31
32#include <bcm63xx_cpu.h>
33#include <bcm63xx_io.h>
34#include <bcm63xx_regs.h>
35#include <bcm63xx_timer.h>
36
37#define PFX KBUILD_MODNAME
38
39#define WDT_HZ 50000000 /* Fclk */
40#define WDT_DEFAULT_TIME 30 /* seconds */
41#define WDT_MAX_TIME 256 /* seconds */
42
43static struct {
44 void __iomem *regs;
45 struct timer_list timer;
46 int default_ticks;
47 unsigned long inuse;
48 atomic_t ticks;
49} bcm63xx_wdt_device;
50
51static int expect_close;
52
53static int wdt_time = WDT_DEFAULT_TIME;
54static int nowayout = WATCHDOG_NOWAYOUT;
55module_param(nowayout, int, 0);
56MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
57 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
58
59/* HW functions */
60static void bcm63xx_wdt_hw_start(void)
61{
62 bcm_writel(0xfffffffe, bcm63xx_wdt_device.regs + WDT_DEFVAL_REG);
63 bcm_writel(WDT_START_1, bcm63xx_wdt_device.regs + WDT_CTL_REG);
64 bcm_writel(WDT_START_2, bcm63xx_wdt_device.regs + WDT_CTL_REG);
65}
66
67static void bcm63xx_wdt_hw_stop(void)
68{
69 bcm_writel(WDT_STOP_1, bcm63xx_wdt_device.regs + WDT_CTL_REG);
70 bcm_writel(WDT_STOP_2, bcm63xx_wdt_device.regs + WDT_CTL_REG);
71}
72
73static void bcm63xx_wdt_isr(void *data)
74{
75 struct pt_regs *regs = get_irq_regs();
76
77 die(PFX " fire", regs);
78}
79
80static void bcm63xx_timer_tick(unsigned long unused)
81{
82 if (!atomic_dec_and_test(&bcm63xx_wdt_device.ticks)) {
83 bcm63xx_wdt_hw_start();
84 mod_timer(&bcm63xx_wdt_device.timer, jiffies + HZ);
85 } else
86 printk(KERN_CRIT PFX ": watchdog will restart system\n");
87}
88
89static void bcm63xx_wdt_pet(void)
90{
91 atomic_set(&bcm63xx_wdt_device.ticks, wdt_time);
92}
93
94static void bcm63xx_wdt_start(void)
95{
96 bcm63xx_wdt_pet();
97 bcm63xx_timer_tick(0);
98}
99
100static void bcm63xx_wdt_pause(void)
101{
102 del_timer_sync(&bcm63xx_wdt_device.timer);
103 bcm63xx_wdt_hw_stop();
104}
105
106static int bcm63xx_wdt_settimeout(int new_time)
107{
108 if ((new_time <= 0) || (new_time > WDT_MAX_TIME))
109 return -EINVAL;
110
111 wdt_time = new_time;
112
113 return 0;
114}
115
116static int bcm63xx_wdt_open(struct inode *inode, struct file *file)
117{
118 if (test_and_set_bit(0, &bcm63xx_wdt_device.inuse))
119 return -EBUSY;
120
121 bcm63xx_wdt_start();
122 return nonseekable_open(inode, file);
123}
124
125static int bcm63xx_wdt_release(struct inode *inode, struct file *file)
126{
127 if (expect_close == 42)
128 bcm63xx_wdt_pause();
129 else {
130 printk(KERN_CRIT PFX
131 ": Unexpected close, not stopping watchdog!\n");
132 bcm63xx_wdt_start();
133 }
134 clear_bit(0, &bcm63xx_wdt_device.inuse);
135 expect_close = 0;
136 return 0;
137}
138
139static ssize_t bcm63xx_wdt_write(struct file *file, const char *data,
140 size_t len, loff_t *ppos)
141{
142 if (len) {
143 if (!nowayout) {
144 size_t i;
145
146 /* In case it was set long ago */
147 expect_close = 0;
148
149 for (i = 0; i != len; i++) {
150 char c;
151 if (get_user(c, data + i))
152 return -EFAULT;
153 if (c == 'V')
154 expect_close = 42;
155 }
156 }
157 bcm63xx_wdt_pet();
158 }
159 return len;
160}
161
162static struct watchdog_info bcm63xx_wdt_info = {
163 .identity = PFX,
164 .options = WDIOF_SETTIMEOUT |
165 WDIOF_KEEPALIVEPING |
166 WDIOF_MAGICCLOSE,
167};
168
169
170static long bcm63xx_wdt_ioctl(struct file *file, unsigned int cmd,
171 unsigned long arg)
172{
173 void __user *argp = (void __user *)arg;
174 int __user *p = argp;
175 int new_value, retval = -EINVAL;
176
177 switch (cmd) {
178 case WDIOC_GETSUPPORT:
179 return copy_to_user(argp, &bcm63xx_wdt_info,
180 sizeof(bcm63xx_wdt_info)) ? -EFAULT : 0;
181
182 case WDIOC_GETSTATUS:
183 case WDIOC_GETBOOTSTATUS:
184 return put_user(0, p);
185
186 case WDIOC_SETOPTIONS:
187 if (get_user(new_value, p))
188 return -EFAULT;
189
190 if (new_value & WDIOS_DISABLECARD) {
191 bcm63xx_wdt_pause();
192 retval = 0;
193 }
194 if (new_value & WDIOS_ENABLECARD) {
195 bcm63xx_wdt_start();
196 retval = 0;
197 }
198
199 return retval;
200
201 case WDIOC_KEEPALIVE:
202 bcm63xx_wdt_pet();
203 return 0;
204
205 case WDIOC_SETTIMEOUT:
206 if (get_user(new_value, p))
207 return -EFAULT;
208
209 if (bcm63xx_wdt_settimeout(new_value))
210 return -EINVAL;
211
212 bcm63xx_wdt_pet();
213
214 case WDIOC_GETTIMEOUT:
215 return put_user(wdt_time, p);
216
217 default:
218 return -ENOTTY;
219
220 }
221}
222
223static int bcm63xx_wdt_notify_sys(struct notifier_block *this,
224 unsigned long code, void *unused)
225{
226 if (code == SYS_DOWN || code == SYS_HALT)
227 bcm63xx_wdt_pause();
228 return NOTIFY_DONE;
229}
230
231static const struct file_operations bcm63xx_wdt_fops = {
232 .owner = THIS_MODULE,
233 .llseek = no_llseek,
234 .write = bcm63xx_wdt_write,
235 .unlocked_ioctl = bcm63xx_wdt_ioctl,
236 .open = bcm63xx_wdt_open,
237 .release = bcm63xx_wdt_release,
238};
239
240static struct miscdevice bcm63xx_wdt_miscdev = {
241 .minor = WATCHDOG_MINOR,
242 .name = "watchdog",
243 .fops = &bcm63xx_wdt_fops,
244};
245
246static struct notifier_block bcm63xx_wdt_notifier = {
247 .notifier_call = bcm63xx_wdt_notify_sys,
248};
249
250
251static int bcm63xx_wdt_probe(struct platform_device *pdev)
252{
253 int ret;
254 struct resource *r;
255
256 setup_timer(&bcm63xx_wdt_device.timer, bcm63xx_timer_tick, 0L);
257
258 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
259 if (!r) {
260 dev_err(&pdev->dev, "failed to get resources\n");
261 return -ENODEV;
262 }
263
264 bcm63xx_wdt_device.regs = ioremap_nocache(r->start, r->end - r->start);
265 if (!bcm63xx_wdt_device.regs) {
266 dev_err(&pdev->dev, "failed to remap I/O resources\n");
267 return -ENXIO;
268 }
269
270 ret = bcm63xx_timer_register(TIMER_WDT_ID, bcm63xx_wdt_isr, NULL);
271 if (ret < 0) {
272 dev_err(&pdev->dev, "failed to register wdt timer isr\n");
273 goto unmap;
274 }
275
276 if (bcm63xx_wdt_settimeout(wdt_time)) {
277 bcm63xx_wdt_settimeout(WDT_DEFAULT_TIME);
278 dev_info(&pdev->dev,
279 ": wdt_time value must be 1 <= wdt_time <= 256, using %d\n",
280 wdt_time);
281 }
282
283 ret = register_reboot_notifier(&bcm63xx_wdt_notifier);
284 if (ret) {
285 dev_err(&pdev->dev, "failed to register reboot_notifier\n");
286 goto unregister_timer;
287 }
288
289 ret = misc_register(&bcm63xx_wdt_miscdev);
290 if (ret < 0) {
291 dev_err(&pdev->dev, "failed to register watchdog device\n");
292 goto unregister_reboot_notifier;
293 }
294
295 dev_info(&pdev->dev, " started, timer margin: %d sec\n",
296 WDT_DEFAULT_TIME);
297
298 return 0;
299
300unregister_reboot_notifier:
301 unregister_reboot_notifier(&bcm63xx_wdt_notifier);
302unregister_timer:
303 bcm63xx_timer_unregister(TIMER_WDT_ID);
304unmap:
305 iounmap(bcm63xx_wdt_device.regs);
306 return ret;
307}
308
309static int bcm63xx_wdt_remove(struct platform_device *pdev)
310{
311 if (!nowayout)
312 bcm63xx_wdt_pause();
313
314 misc_deregister(&bcm63xx_wdt_miscdev);
315
316 iounmap(bcm63xx_wdt_device.regs);
317
318 unregister_reboot_notifier(&bcm63xx_wdt_notifier);
319 bcm63xx_timer_unregister(TIMER_WDT_ID);
320
321 return 0;
322}
323
324static struct platform_driver bcm63xx_wdt = {
325 .probe = bcm63xx_wdt_probe,
326 .remove = bcm63xx_wdt_remove,
327 .driver = {
328 .name = "bcm63xx-wdt",
329 }
330};
331
332static int __init bcm63xx_wdt_init(void)
333{
334 return platform_driver_register(&bcm63xx_wdt);
335}
336
337static void __exit bcm63xx_wdt_exit(void)
338{
339 platform_driver_unregister(&bcm63xx_wdt);
340}
341
342module_init(bcm63xx_wdt_init);
343module_exit(bcm63xx_wdt_exit);
344
345MODULE_AUTHOR("Miguel Gaio <miguel.gaio@efixo.com>");
346MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>");
347MODULE_DESCRIPTION("Driver for the Broadcom BCM63xx SoC watchdog");
348MODULE_LICENSE("GPL");
349MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
350MODULE_ALIAS("platform:bcm63xx-wdt");
diff --git a/drivers/watchdog/f71808e_wdt.c b/drivers/watchdog/f71808e_wdt.c
index 7e5c266cda48..65e579635dba 100644
--- a/drivers/watchdog/f71808e_wdt.c
+++ b/drivers/watchdog/f71808e_wdt.c
@@ -308,6 +308,12 @@ static int watchdog_start(void)
308 superio_set_bit(watchdog.sioaddr, 0x29, 1); 308 superio_set_bit(watchdog.sioaddr, 0x29, 1);
309 break; 309 break;
310 310
311 case f71889fg:
312 /* set pin 40 to WDTRST# */
313 superio_outb(watchdog.sioaddr, 0x2b,
314 superio_inb(watchdog.sioaddr, 0x2b) & 0xcf);
315 break;
316
311 default: 317 default:
312 /* 318 /*
313 * 'default' label to shut up the compiler and catch 319 * 'default' label to shut up the compiler and catch
@@ -708,8 +714,10 @@ static int __init f71808e_find(int sioaddr)
708 case SIO_F71882_ID: 714 case SIO_F71882_ID:
709 watchdog.type = f71882fg; 715 watchdog.type = f71882fg;
710 break; 716 break;
711 case SIO_F71862_ID:
712 case SIO_F71889_ID: 717 case SIO_F71889_ID:
718 watchdog.type = f71889fg;
719 break;
720 case SIO_F71862_ID:
713 /* These have a watchdog, though it isn't implemented (yet). */ 721 /* These have a watchdog, though it isn't implemented (yet). */
714 err = -ENOSYS; 722 err = -ENOSYS;
715 goto exit; 723 goto exit;
diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c
index 69de8713b8e4..f7e90fe47b71 100644
--- a/drivers/watchdog/iTCO_wdt.c
+++ b/drivers/watchdog/iTCO_wdt.c
@@ -146,6 +146,7 @@ enum iTCO_chipsets {
146 TCO_CPT29, /* Cougar Point */ 146 TCO_CPT29, /* Cougar Point */
147 TCO_CPT30, /* Cougar Point */ 147 TCO_CPT30, /* Cougar Point */
148 TCO_CPT31, /* Cougar Point */ 148 TCO_CPT31, /* Cougar Point */
149 TCO_PBG, /* Patsburg */
149}; 150};
150 151
151static struct { 152static struct {
@@ -233,6 +234,7 @@ static struct {
233 {"Cougar Point", 2}, 234 {"Cougar Point", 2},
234 {"Cougar Point", 2}, 235 {"Cougar Point", 2},
235 {"Cougar Point", 2}, 236 {"Cougar Point", 2},
237 {"Patsburg", 2},
236 {NULL, 0} 238 {NULL, 0}
237}; 239};
238 240
@@ -348,6 +350,7 @@ static struct pci_device_id iTCO_wdt_pci_tbl[] = {
348 { ITCO_PCI_DEVICE(0x1c5d, TCO_CPT29)}, 350 { ITCO_PCI_DEVICE(0x1c5d, TCO_CPT29)},
349 { ITCO_PCI_DEVICE(0x1c5e, TCO_CPT30)}, 351 { ITCO_PCI_DEVICE(0x1c5e, TCO_CPT30)},
350 { ITCO_PCI_DEVICE(0x1c5f, TCO_CPT31)}, 352 { ITCO_PCI_DEVICE(0x1c5f, TCO_CPT31)},
353 { ITCO_PCI_DEVICE(0x1d40, TCO_PBG)},
351 { 0, }, /* End of list */ 354 { 0, }, /* End of list */
352}; 355};
353MODULE_DEVICE_TABLE(pci, iTCO_wdt_pci_tbl); 356MODULE_DEVICE_TABLE(pci, iTCO_wdt_pci_tbl);
@@ -374,7 +377,7 @@ static char expect_release;
374static struct { /* this is private data for the iTCO_wdt device */ 377static struct { /* this is private data for the iTCO_wdt device */
375 /* TCO version/generation */ 378 /* TCO version/generation */
376 unsigned int iTCO_version; 379 unsigned int iTCO_version;
377 /* The cards ACPIBASE address (TCOBASE = ACPIBASE+0x60) */ 380 /* The device's ACPIBASE address (TCOBASE = ACPIBASE+0x60) */
378 unsigned long ACPIBASE; 381 unsigned long ACPIBASE;
379 /* NO_REBOOT flag is Memory-Mapped GCS register bit 5 (TCO version 2)*/ 382 /* NO_REBOOT flag is Memory-Mapped GCS register bit 5 (TCO version 2)*/
380 unsigned long __iomem *gcs; 383 unsigned long __iomem *gcs;
@@ -467,7 +470,7 @@ static int iTCO_wdt_start(void)
467 if (iTCO_wdt_unset_NO_REBOOT_bit()) { 470 if (iTCO_wdt_unset_NO_REBOOT_bit()) {
468 spin_unlock(&iTCO_wdt_private.io_lock); 471 spin_unlock(&iTCO_wdt_private.io_lock);
469 printk(KERN_ERR PFX "failed to reset NO_REBOOT flag, " 472 printk(KERN_ERR PFX "failed to reset NO_REBOOT flag, "
470 "reboot disabled by hardware\n"); 473 "reboot disabled by hardware/BIOS\n");
471 return -EIO; 474 return -EIO;
472 } 475 }
473 476
@@ -781,8 +784,8 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev,
781 base_address &= 0x0000ff80; 784 base_address &= 0x0000ff80;
782 if (base_address == 0x00000000) { 785 if (base_address == 0x00000000) {
783 /* Something's wrong here, ACPIBASE has to be set */ 786 /* Something's wrong here, ACPIBASE has to be set */
784 printk(KERN_ERR PFX "failed to get TCOBASE address\n"); 787 printk(KERN_ERR PFX "failed to get TCOBASE address, "
785 pci_dev_put(pdev); 788 "device disabled by hardware/BIOS\n");
786 return -ENODEV; 789 return -ENODEV;
787 } 790 }
788 iTCO_wdt_private.iTCO_version = 791 iTCO_wdt_private.iTCO_version =
@@ -797,7 +800,8 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev,
797 if (iTCO_wdt_private.iTCO_version == 2) { 800 if (iTCO_wdt_private.iTCO_version == 2) {
798 pci_read_config_dword(pdev, 0xf0, &base_address); 801 pci_read_config_dword(pdev, 0xf0, &base_address);
799 if ((base_address & 1) == 0) { 802 if ((base_address & 1) == 0) {
800 printk(KERN_ERR PFX "RCBA is disabled by hardware\n"); 803 printk(KERN_ERR PFX "RCBA is disabled by hardware"
804 "/BIOS, device disabled\n");
801 ret = -ENODEV; 805 ret = -ENODEV;
802 goto out; 806 goto out;
803 } 807 }
@@ -808,7 +812,7 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev,
808 /* Check chipset's NO_REBOOT bit */ 812 /* Check chipset's NO_REBOOT bit */
809 if (iTCO_wdt_unset_NO_REBOOT_bit() && iTCO_vendor_check_noreboot_on()) { 813 if (iTCO_wdt_unset_NO_REBOOT_bit() && iTCO_vendor_check_noreboot_on()) {
810 printk(KERN_INFO PFX "unable to reset NO_REBOOT flag, " 814 printk(KERN_INFO PFX "unable to reset NO_REBOOT flag, "
811 "platform may have disabled it\n"); 815 "device disabled by hardware/BIOS\n");
812 ret = -ENODEV; /* Cannot reset NO_REBOOT bit */ 816 ret = -ENODEV; /* Cannot reset NO_REBOOT bit */
813 goto out_unmap; 817 goto out_unmap;
814 } 818 }
@@ -819,7 +823,8 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev,
819 /* The TCO logic uses the TCO_EN bit in the SMI_EN register */ 823 /* The TCO logic uses the TCO_EN bit in the SMI_EN register */
820 if (!request_region(SMI_EN, 4, "iTCO_wdt")) { 824 if (!request_region(SMI_EN, 4, "iTCO_wdt")) {
821 printk(KERN_ERR PFX 825 printk(KERN_ERR PFX
822 "I/O address 0x%04lx already in use\n", SMI_EN); 826 "I/O address 0x%04lx already in use, "
827 "device disabled\n", SMI_EN);
823 ret = -EIO; 828 ret = -EIO;
824 goto out_unmap; 829 goto out_unmap;
825 } 830 }
@@ -831,8 +836,8 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev,
831 /* The TCO I/O registers reside in a 32-byte range pointed to 836 /* The TCO I/O registers reside in a 32-byte range pointed to
832 by the TCOBASE value */ 837 by the TCOBASE value */
833 if (!request_region(TCOBASE, 0x20, "iTCO_wdt")) { 838 if (!request_region(TCOBASE, 0x20, "iTCO_wdt")) {
834 printk(KERN_ERR PFX "I/O address 0x%04lx already in use\n", 839 printk(KERN_ERR PFX "I/O address 0x%04lx already in use "
835 TCOBASE); 840 "device disabled\n", TCOBASE);
836 ret = -EIO; 841 ret = -EIO;
837 goto unreg_smi_en; 842 goto unreg_smi_en;
838 } 843 }
@@ -880,7 +885,6 @@ out_unmap:
880 if (iTCO_wdt_private.iTCO_version == 2) 885 if (iTCO_wdt_private.iTCO_version == 2)
881 iounmap(iTCO_wdt_private.gcs); 886 iounmap(iTCO_wdt_private.gcs);
882out: 887out:
883 pci_dev_put(iTCO_wdt_private.pdev);
884 iTCO_wdt_private.ACPIBASE = 0; 888 iTCO_wdt_private.ACPIBASE = 0;
885 return ret; 889 return ret;
886} 890}
@@ -921,7 +925,7 @@ static int __devinit iTCO_wdt_probe(struct platform_device *dev)
921 } 925 }
922 926
923 if (!found) 927 if (!found)
924 printk(KERN_INFO PFX "No card detected\n"); 928 printk(KERN_INFO PFX "No device detected.\n");
925 929
926 return ret; 930 return ret;
927} 931}
diff --git a/drivers/watchdog/it8712f_wdt.c b/drivers/watchdog/it8712f_wdt.c
index f52c162b1bea..b32c6c045b1a 100644
--- a/drivers/watchdog/it8712f_wdt.c
+++ b/drivers/watchdog/it8712f_wdt.c
@@ -75,15 +75,23 @@ static unsigned short address;
75#define WDT_CONFIG 0x72 /* WDT Register: Configuration */ 75#define WDT_CONFIG 0x72 /* WDT Register: Configuration */
76#define WDT_TIMEOUT 0x73 /* WDT Register: Timeout Value */ 76#define WDT_TIMEOUT 0x73 /* WDT Register: Timeout Value */
77 77
78#define WDT_RESET_GAME 0x10 78#define WDT_RESET_GAME 0x10 /* Reset timer on read or write to game port */
79#define WDT_RESET_KBD 0x20 79#define WDT_RESET_KBD 0x20 /* Reset timer on keyboard interrupt */
80#define WDT_RESET_MOUSE 0x40 80#define WDT_RESET_MOUSE 0x40 /* Reset timer on mouse interrupt */
81#define WDT_RESET_CIR 0x80 81#define WDT_RESET_CIR 0x80 /* Reset timer on consumer IR interrupt */
82 82
83#define WDT_UNIT_SEC 0x80 /* If 0 in MINUTES */ 83#define WDT_UNIT_SEC 0x80 /* If 0 in MINUTES */
84 84
85#define WDT_OUT_PWROK 0x10 85#define WDT_OUT_PWROK 0x10 /* Pulse PWROK on timeout */
86#define WDT_OUT_KRST 0x40 86#define WDT_OUT_KRST 0x40 /* Pulse reset on timeout */
87
88static int wdt_control_reg = WDT_RESET_GAME;
89module_param(wdt_control_reg, int, 0);
90MODULE_PARM_DESC(wdt_control_reg, "Value to write to watchdog control "
91 "register. The default WDT_RESET_GAME resets the timer on "
92 "game port reads that this driver generates. You can also "
93 "use KBD, MOUSE or CIR if you have some external way to "
94 "generate those interrupts.");
87 95
88static int superio_inb(int reg) 96static int superio_inb(int reg)
89{ 97{
@@ -131,7 +139,8 @@ static inline void superio_exit(void)
131 139
132static inline void it8712f_wdt_ping(void) 140static inline void it8712f_wdt_ping(void)
133{ 141{
134 inb(address); 142 if (wdt_control_reg & WDT_RESET_GAME)
143 inb(address);
135} 144}
136 145
137static void it8712f_wdt_update_margin(void) 146static void it8712f_wdt_update_margin(void)
@@ -170,7 +179,7 @@ static void it8712f_wdt_enable(void)
170 superio_enter(); 179 superio_enter();
171 superio_select(LDN_GPIO); 180 superio_select(LDN_GPIO);
172 181
173 superio_outb(WDT_RESET_GAME, WDT_CONTROL); 182 superio_outb(wdt_control_reg, WDT_CONTROL);
174 183
175 it8712f_wdt_update_margin(); 184 it8712f_wdt_update_margin();
176 185
diff --git a/drivers/watchdog/it87_wdt.c b/drivers/watchdog/it87_wdt.c
index b709b3b2d1ef..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, 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
@@ -45,7 +45,7 @@
45 45
46#include <asm/system.h> 46#include <asm/system.h>
47 47
48#define WATCHDOG_VERSION "1.12" 48#define WATCHDOG_VERSION "1.13"
49#define WATCHDOG_NAME "IT87 WDT" 49#define WATCHDOG_NAME "IT87 WDT"
50#define PFX WATCHDOG_NAME ": " 50#define PFX WATCHDOG_NAME ": "
51#define DRIVER_VERSION WATCHDOG_NAME " driver, v" WATCHDOG_VERSION "\n" 51#define DRIVER_VERSION WATCHDOG_NAME " driver, v" WATCHDOG_VERSION "\n"
@@ -76,10 +76,12 @@
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
82#define IT8718_ID 0x8718 83#define IT8718_ID 0x8718
84#define IT8720_ID 0x8720
83#define IT8726_ID 0x8726 /* the data sheet suggest wrongly 0x8716 */ 85#define IT8726_ID 0x8726 /* the data sheet suggest wrongly 0x8716 */
84 86
85/* GPIO Configuration Registers LDN=0x07 */ 87/* GPIO Configuration Registers LDN=0x07 */
@@ -92,7 +94,7 @@
92#define WDT_CIRINT 0x80 94#define WDT_CIRINT 0x80
93#define WDT_MOUSEINT 0x40 95#define WDT_MOUSEINT 0x40
94#define WDT_KYBINT 0x20 96#define WDT_KYBINT 0x20
95#define WDT_GAMEPORT 0x10 /* not it8718 */ 97#define WDT_GAMEPORT 0x10 /* not in it8718, it8720 */
96#define WDT_FORCE 0x02 98#define WDT_FORCE 0x02
97#define WDT_ZERO 0x01 99#define WDT_ZERO 0x01
98 100
@@ -132,7 +134,7 @@
132#define WDTS_USE_GP 4 134#define WDTS_USE_GP 4
133#define WDTS_EXPECTED 5 135#define WDTS_EXPECTED 5
134 136
135static unsigned int base, gpact, ciract; 137static unsigned int base, gpact, ciract, max_units;
136static unsigned long wdt_status; 138static unsigned long wdt_status;
137static DEFINE_SPINLOCK(spinlock); 139static DEFINE_SPINLOCK(spinlock);
138 140
@@ -210,6 +212,33 @@ static inline void superio_outw(int val, int reg)
210 outb(val, VAL); 212 outb(val, VAL);
211} 213}
212 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
213/* watchdog timer handling */ 242/* watchdog timer handling */
214 243
215static void wdt_keepalive(void) 244static void wdt_keepalive(void)
@@ -234,12 +263,7 @@ static void wdt_start(void)
234 superio_outb(WDT_GAMEPORT, WDTCTRL); 263 superio_outb(WDT_GAMEPORT, WDTCTRL);
235 else 264 else
236 superio_outb(WDT_CIRINT, WDTCTRL); 265 superio_outb(WDT_CIRINT, WDTCTRL);
237 if (!testmode) 266 wdt_update_timeout();
238 superio_outb(WDT_TOV1 | WDT_KRST | WDT_PWROK, WDTCFG);
239 else
240 superio_outb(WDT_TOV1, WDTCFG);
241 superio_outb(timeout>>8, WDTVALMSB);
242 superio_outb(timeout, WDTVALLSB);
243 267
244 superio_exit(); 268 superio_exit();
245 spin_unlock_irqrestore(&spinlock, flags); 269 spin_unlock_irqrestore(&spinlock, flags);
@@ -255,8 +279,9 @@ static void wdt_stop(void)
255 superio_select(GPIO); 279 superio_select(GPIO);
256 superio_outb(0x00, WDTCTRL); 280 superio_outb(0x00, WDTCTRL);
257 superio_outb(WDT_TOV1, WDTCFG); 281 superio_outb(WDT_TOV1, WDTCFG);
258 superio_outb(0x00, WDTVALMSB);
259 superio_outb(0x00, WDTVALLSB); 282 superio_outb(0x00, WDTVALLSB);
283 if (max_units > 255)
284 superio_outb(0x00, WDTVALMSB);
260 285
261 superio_exit(); 286 superio_exit();
262 spin_unlock_irqrestore(&spinlock, flags); 287 spin_unlock_irqrestore(&spinlock, flags);
@@ -266,8 +291,8 @@ static void wdt_stop(void)
266 * wdt_set_timeout - set a new timeout value with watchdog ioctl 291 * wdt_set_timeout - set a new timeout value with watchdog ioctl
267 * @t: timeout value in seconds 292 * @t: timeout value in seconds
268 * 293 *
269 * 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
270 * timeout time ranges between 1 and 65535 seconds. 295 * chip version) that can be configured to count seconds or minutes.
271 * 296 *
272 * Used within WDIOC_SETTIMEOUT watchdog device ioctl. 297 * Used within WDIOC_SETTIMEOUT watchdog device ioctl.
273 */ 298 */
@@ -276,19 +301,19 @@ static int wdt_set_timeout(int t)
276{ 301{
277 unsigned long flags; 302 unsigned long flags;
278 303
279 if (t < 1 || t > 65535) 304 if (t < 1 || t > max_units * 60)
280 return -EINVAL; 305 return -EINVAL;
281 306
282 timeout = t; 307 if (t > max_units)
308 timeout = wdt_round_time(t);
309 else
310 timeout = t;
283 311
284 spin_lock_irqsave(&spinlock, flags); 312 spin_lock_irqsave(&spinlock, flags);
285 if (test_bit(WDTS_TIMER_RUN, &wdt_status)) { 313 if (test_bit(WDTS_TIMER_RUN, &wdt_status)) {
286 superio_enter(); 314 superio_enter();
287
288 superio_select(GPIO); 315 superio_select(GPIO);
289 superio_outb(t>>8, WDTVALMSB); 316 wdt_update_timeout();
290 superio_outb(t, WDTVALLSB);
291
292 superio_exit(); 317 superio_exit();
293 } 318 }
294 spin_unlock_irqrestore(&spinlock, flags); 319 spin_unlock_irqrestore(&spinlock, flags);
@@ -529,10 +554,13 @@ static struct notifier_block wdt_notifier = {
529static int __init it87_wdt_init(void) 554static int __init it87_wdt_init(void)
530{ 555{
531 int rc = 0; 556 int rc = 0;
557 int try_gameport = !nogameport;
532 u16 chip_type; 558 u16 chip_type;
533 u8 chip_rev; 559 u8 chip_rev;
534 unsigned long flags; 560 unsigned long flags;
535 561
562 wdt_status = 0;
563
536 spin_lock_irqsave(&spinlock, flags); 564 spin_lock_irqsave(&spinlock, flags);
537 superio_enter(); 565 superio_enter();
538 chip_type = superio_inw(CHIPID); 566 chip_type = superio_inw(CHIPID);
@@ -541,13 +569,21 @@ static int __init it87_wdt_init(void)
541 spin_unlock_irqrestore(&spinlock, flags); 569 spin_unlock_irqrestore(&spinlock, flags);
542 570
543 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;
544 case IT8716_ID: 578 case IT8716_ID:
545 case IT8718_ID:
546 case IT8726_ID: 579 case IT8726_ID:
580 max_units = 65535;
581 break;
582 case IT8718_ID:
583 case IT8720_ID:
584 max_units = 65535;
585 try_gameport = 0;
547 break; 586 break;
548 case IT8712_ID:
549 if (chip_rev > 7)
550 break;
551 case IT8705_ID: 587 case IT8705_ID:
552 printk(KERN_ERR PFX 588 printk(KERN_ERR PFX
553 "Unsupported Chip found, Chip %04x Revision %02x\n", 589 "Unsupported Chip found, Chip %04x Revision %02x\n",
@@ -571,7 +607,7 @@ static int __init it87_wdt_init(void)
571 superio_outb(0x00, WDTCTRL); 607 superio_outb(0x00, WDTCTRL);
572 608
573 /* First try to get Gameport support */ 609 /* First try to get Gameport support */
574 if (chip_type != IT8718_ID && !nogameport) { 610 if (try_gameport) {
575 superio_select(GAMEPORT); 611 superio_select(GAMEPORT);
576 base = superio_inw(BASEREG); 612 base = superio_inw(BASEREG);
577 if (!base) { 613 if (!base) {
@@ -623,13 +659,16 @@ static int __init it87_wdt_init(void)
623 spin_unlock_irqrestore(&spinlock, flags); 659 spin_unlock_irqrestore(&spinlock, flags);
624 } 660 }
625 661
626 if (timeout < 1 || timeout > 65535) { 662 if (timeout < 1 || timeout > max_units * 60) {
627 timeout = DEFAULT_TIMEOUT; 663 timeout = DEFAULT_TIMEOUT;
628 printk(KERN_WARNING PFX 664 printk(KERN_WARNING PFX
629 "Timeout value out of range, use default %d sec\n", 665 "Timeout value out of range, use default %d sec\n",
630 DEFAULT_TIMEOUT); 666 DEFAULT_TIMEOUT);
631 } 667 }
632 668
669 if (timeout > max_units)
670 timeout = wdt_round_time(timeout);
671
633 rc = register_reboot_notifier(&wdt_notifier); 672 rc = register_reboot_notifier(&wdt_notifier);
634 if (rc) { 673 if (rc) {
635 printk(KERN_ERR PFX 674 printk(KERN_ERR PFX
@@ -656,7 +695,7 @@ static int __init it87_wdt_init(void)
656 outb(0x09, CIR_IER(base)); 695 outb(0x09, CIR_IER(base));
657 } 696 }
658 697
659 printk(KERN_INFO PFX "Chip it%04x revision %d initialized. " 698 printk(KERN_INFO PFX "Chip IT%04x revision %d initialized. "
660 "timeout=%d sec (nowayout=%d testmode=%d exclusive=%d " 699 "timeout=%d sec (nowayout=%d testmode=%d exclusive=%d "
661 "nogameport=%d)\n", chip_type, chip_rev, timeout, 700 "nogameport=%d)\n", chip_type, chip_rev, timeout,
662 nowayout, testmode, exclusive, nogameport); 701 nowayout, testmode, exclusive, nogameport);
@@ -676,7 +715,7 @@ err_out_region:
676 spin_unlock_irqrestore(&spinlock, flags); 715 spin_unlock_irqrestore(&spinlock, flags);
677 } 716 }
678err_out: 717err_out:
679 if (chip_type != IT8718_ID && !nogameport) { 718 if (try_gameport) {
680 spin_lock_irqsave(&spinlock, flags); 719 spin_lock_irqsave(&spinlock, flags);
681 superio_enter(); 720 superio_enter();
682 superio_select(GAMEPORT); 721 superio_select(GAMEPORT);
@@ -698,8 +737,9 @@ static void __exit it87_wdt_exit(void)
698 superio_select(GPIO); 737 superio_select(GPIO);
699 superio_outb(0x00, WDTCTRL); 738 superio_outb(0x00, WDTCTRL);
700 superio_outb(0x00, WDTCFG); 739 superio_outb(0x00, WDTCFG);
701 superio_outb(0x00, WDTVALMSB);
702 superio_outb(0x00, WDTVALLSB); 740 superio_outb(0x00, WDTVALLSB);
741 if (max_units > 255)
742 superio_outb(0x00, WDTVALMSB);
703 if (test_bit(WDTS_USE_GP, &wdt_status)) { 743 if (test_bit(WDTS_USE_GP, &wdt_status)) {
704 superio_select(GAMEPORT); 744 superio_select(GAMEPORT);
705 superio_outb(gpact, ACTREG); 745 superio_outb(gpact, ACTREG);
diff --git a/drivers/watchdog/machzwd.c b/drivers/watchdog/machzwd.c
index 2d118cf022fc..928035069396 100644
--- a/drivers/watchdog/machzwd.c
+++ b/drivers/watchdog/machzwd.c
@@ -143,7 +143,7 @@ static unsigned long next_heartbeat;
143#ifndef ZF_DEBUG 143#ifndef ZF_DEBUG
144# define dprintk(format, args...) 144# define dprintk(format, args...)
145#else 145#else
146# define dprintk(format, args...) printk(KERN_DEBUG PFX 146# define dprintk(format, args...) printk(KERN_DEBUG PFX \
147 ":%s:%d: " format, __func__, __LINE__ , ## args) 147 ":%s:%d: " format, __func__, __LINE__ , ## args)
148#endif 148#endif
149 149
@@ -388,7 +388,7 @@ static struct notifier_block zf_notifier = {
388 388
389static void __init zf_show_action(int act) 389static void __init zf_show_action(int act)
390{ 390{
391 char *str[] = { "RESET", "SMI", "NMI", "SCI" }; 391 static const char * const str[] = { "RESET", "SMI", "NMI", "SCI" };
392 392
393 printk(KERN_INFO PFX ": Watchdog using action = %s\n", str[act]); 393 printk(KERN_INFO PFX ": Watchdog using action = %s\n", str[act]);
394} 394}