aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/watchdog
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/watchdog')
-rw-r--r--drivers/watchdog/Kconfig6
-rw-r--r--drivers/watchdog/Makefile1
-rw-r--r--drivers/watchdog/alim1535_wdt.c20
-rw-r--r--drivers/watchdog/alim7101_wdt.c18
-rw-r--r--drivers/watchdog/ar7_wdt.c2
-rw-r--r--drivers/watchdog/bfin_wdt.c2
-rw-r--r--drivers/watchdog/it8712f_wdt.c2
-rw-r--r--drivers/watchdog/mpc5200_wdt.c2
-rw-r--r--drivers/watchdog/mtx-1_wdt.c2
-rw-r--r--drivers/watchdog/sbc60xxwdt.c18
-rw-r--r--drivers/watchdog/scx200_wdt.c10
-rw-r--r--drivers/watchdog/txx9wdt.c276
-rw-r--r--drivers/watchdog/w83877f_wdt.c18
-rw-r--r--drivers/watchdog/w83977f_wdt.c18
-rw-r--r--drivers/watchdog/wdt.c30
-rw-r--r--drivers/watchdog/wdt977.c18
16 files changed, 375 insertions, 68 deletions
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index fbd61127b9d9..899fc13d0612 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -639,6 +639,12 @@ config AR7_WDT
639 help 639 help
640 Hardware driver for the TI AR7 Watchdog Timer. 640 Hardware driver for the TI AR7 Watchdog Timer.
641 641
642config TXX9_WDT
643 tristate "Toshiba TXx9 Watchdog Timer"
644 depends on CPU_TX39XX || CPU_TX49XX
645 help
646 Hardware driver for the built-in watchdog timer on TXx9 MIPS SoCs.
647
642# PARISC Architecture 648# PARISC Architecture
643 649
644# POWERPC Architecture 650# POWERPC Architecture
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 87483cc63252..ebc21146d40c 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -93,6 +93,7 @@ obj-$(CONFIG_INDYDOG) += indydog.o
93obj-$(CONFIG_WDT_MTX1) += mtx-1_wdt.o 93obj-$(CONFIG_WDT_MTX1) += mtx-1_wdt.o
94obj-$(CONFIG_WDT_RM9K_GPI) += rm9k_wdt.o 94obj-$(CONFIG_WDT_RM9K_GPI) += rm9k_wdt.o
95obj-$(CONFIG_AR7_WDT) += ar7_wdt.o 95obj-$(CONFIG_AR7_WDT) += ar7_wdt.o
96obj-$(CONFIG_TXX9_WDT) += txx9wdt.o
96 97
97# PARISC Architecture 98# PARISC Architecture
98 99
diff --git a/drivers/watchdog/alim1535_wdt.c b/drivers/watchdog/alim1535_wdt.c
index b481cc0e32e4..2b1fbdb2fcf7 100644
--- a/drivers/watchdog/alim1535_wdt.c
+++ b/drivers/watchdog/alim1535_wdt.c
@@ -413,18 +413,18 @@ static int __init watchdog_init(void)
413 /* Calculate the watchdog's timeout */ 413 /* Calculate the watchdog's timeout */
414 ali_settimer(timeout); 414 ali_settimer(timeout);
415 415
416 ret = misc_register(&ali_miscdev); 416 ret = register_reboot_notifier(&ali_notifier);
417 if (ret != 0) { 417 if (ret != 0) {
418 printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", 418 printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
419 WATCHDOG_MINOR, ret); 419 ret);
420 goto out; 420 goto out;
421 } 421 }
422 422
423 ret = register_reboot_notifier(&ali_notifier); 423 ret = misc_register(&ali_miscdev);
424 if (ret != 0) { 424 if (ret != 0) {
425 printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", 425 printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
426 ret); 426 WATCHDOG_MINOR, ret);
427 goto unreg_miscdev; 427 goto unreg_reboot;
428 } 428 }
429 429
430 printk(KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d)\n", 430 printk(KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d)\n",
@@ -432,8 +432,8 @@ static int __init watchdog_init(void)
432 432
433out: 433out:
434 return ret; 434 return ret;
435unreg_miscdev: 435unreg_reboot:
436 misc_deregister(&ali_miscdev); 436 unregister_reboot_notifier(&ali_notifier);
437 goto out; 437 goto out;
438} 438}
439 439
@@ -449,8 +449,8 @@ static void __exit watchdog_exit(void)
449 ali_stop(); 449 ali_stop();
450 450
451 /* Deregister */ 451 /* Deregister */
452 unregister_reboot_notifier(&ali_notifier);
453 misc_deregister(&ali_miscdev); 452 misc_deregister(&ali_miscdev);
453 unregister_reboot_notifier(&ali_notifier);
454 pci_dev_put(ali_pci); 454 pci_dev_put(ali_pci);
455} 455}
456 456
diff --git a/drivers/watchdog/alim7101_wdt.c b/drivers/watchdog/alim7101_wdt.c
index 67aed9f8c362..238273c98656 100644
--- a/drivers/watchdog/alim7101_wdt.c
+++ b/drivers/watchdog/alim7101_wdt.c
@@ -377,18 +377,18 @@ static int __init alim7101_wdt_init(void)
377 timeout); 377 timeout);
378 } 378 }
379 379
380 rc = misc_register(&wdt_miscdev); 380 rc = register_reboot_notifier(&wdt_notifier);
381 if (rc) { 381 if (rc) {
382 printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", 382 printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
383 wdt_miscdev.minor, rc); 383 rc);
384 goto err_out; 384 goto err_out;
385 } 385 }
386 386
387 rc = register_reboot_notifier(&wdt_notifier); 387 rc = misc_register(&wdt_miscdev);
388 if (rc) { 388 if (rc) {
389 printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", 389 printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
390 rc); 390 wdt_miscdev.minor, rc);
391 goto err_out_miscdev; 391 goto err_out_reboot;
392 } 392 }
393 393
394 if (nowayout) { 394 if (nowayout) {
@@ -399,8 +399,8 @@ static int __init alim7101_wdt_init(void)
399 timeout, nowayout); 399 timeout, nowayout);
400 return 0; 400 return 0;
401 401
402err_out_miscdev: 402err_out_reboot:
403 misc_deregister(&wdt_miscdev); 403 unregister_reboot_notifier(&wdt_notifier);
404err_out: 404err_out:
405 pci_dev_put(alim7101_pmu); 405 pci_dev_put(alim7101_pmu);
406 return rc; 406 return rc;
diff --git a/drivers/watchdog/ar7_wdt.c b/drivers/watchdog/ar7_wdt.c
index cdaab8c3d3d0..2eb48c0df32c 100644
--- a/drivers/watchdog/ar7_wdt.c
+++ b/drivers/watchdog/ar7_wdt.c
@@ -279,7 +279,7 @@ static int ar7_wdt_ioctl(struct inode *inode, struct file *file,
279 } 279 }
280} 280}
281 281
282static struct file_operations ar7_wdt_fops = { 282static const struct file_operations ar7_wdt_fops = {
283 .owner = THIS_MODULE, 283 .owner = THIS_MODULE,
284 .write = ar7_wdt_write, 284 .write = ar7_wdt_write,
285 .ioctl = ar7_wdt_ioctl, 285 .ioctl = ar7_wdt_ioctl,
diff --git a/drivers/watchdog/bfin_wdt.c b/drivers/watchdog/bfin_wdt.c
index 31dc7a69e90c..472be10f0686 100644
--- a/drivers/watchdog/bfin_wdt.c
+++ b/drivers/watchdog/bfin_wdt.c
@@ -390,7 +390,7 @@ static struct platform_driver bfin_wdt_driver = {
390 .resume = bfin_wdt_resume, 390 .resume = bfin_wdt_resume,
391}; 391};
392 392
393static struct file_operations bfin_wdt_fops = { 393static const struct file_operations bfin_wdt_fops = {
394 .owner = THIS_MODULE, 394 .owner = THIS_MODULE,
395 .llseek = no_llseek, 395 .llseek = no_llseek,
396 .write = bfin_wdt_write, 396 .write = bfin_wdt_write,
diff --git a/drivers/watchdog/it8712f_wdt.c b/drivers/watchdog/it8712f_wdt.c
index 6330fc02464e..1b6d7d1b715d 100644
--- a/drivers/watchdog/it8712f_wdt.c
+++ b/drivers/watchdog/it8712f_wdt.c
@@ -296,7 +296,7 @@ it8712f_wdt_release(struct inode *inode, struct file *file)
296 return 0; 296 return 0;
297} 297}
298 298
299static struct file_operations it8712f_wdt_fops = { 299static const struct file_operations it8712f_wdt_fops = {
300 .owner = THIS_MODULE, 300 .owner = THIS_MODULE,
301 .llseek = no_llseek, 301 .llseek = no_llseek,
302 .write = it8712f_wdt_write, 302 .write = it8712f_wdt_write,
diff --git a/drivers/watchdog/mpc5200_wdt.c b/drivers/watchdog/mpc5200_wdt.c
index 11f6a111e75b..80a91d4cea11 100644
--- a/drivers/watchdog/mpc5200_wdt.c
+++ b/drivers/watchdog/mpc5200_wdt.c
@@ -158,7 +158,7 @@ static int mpc5200_wdt_release(struct inode *inode, struct file *file)
158 return 0; 158 return 0;
159} 159}
160 160
161static struct file_operations mpc5200_wdt_fops = { 161static const struct file_operations mpc5200_wdt_fops = {
162 .owner = THIS_MODULE, 162 .owner = THIS_MODULE,
163 .write = mpc5200_wdt_write, 163 .write = mpc5200_wdt_write,
164 .ioctl = mpc5200_wdt_ioctl, 164 .ioctl = mpc5200_wdt_ioctl,
diff --git a/drivers/watchdog/mtx-1_wdt.c b/drivers/watchdog/mtx-1_wdt.c
index dcfd401a7ad7..98451747d3cd 100644
--- a/drivers/watchdog/mtx-1_wdt.c
+++ b/drivers/watchdog/mtx-1_wdt.c
@@ -180,7 +180,7 @@ static ssize_t mtx1_wdt_write(struct file *file, const char *buf, size_t count,
180 return count; 180 return count;
181} 181}
182 182
183static struct file_operations mtx1_wdt_fops = { 183static const struct file_operations mtx1_wdt_fops = {
184 .owner = THIS_MODULE, 184 .owner = THIS_MODULE,
185 .llseek = no_llseek, 185 .llseek = no_llseek,
186 .ioctl = mtx1_wdt_ioctl, 186 .ioctl = mtx1_wdt_ioctl,
diff --git a/drivers/watchdog/sbc60xxwdt.c b/drivers/watchdog/sbc60xxwdt.c
index e4f3cb6090bc..ef76f01625e7 100644
--- a/drivers/watchdog/sbc60xxwdt.c
+++ b/drivers/watchdog/sbc60xxwdt.c
@@ -359,20 +359,20 @@ static int __init sbc60xxwdt_init(void)
359 } 359 }
360 } 360 }
361 361
362 rc = misc_register(&wdt_miscdev); 362 rc = register_reboot_notifier(&wdt_notifier);
363 if (rc) 363 if (rc)
364 { 364 {
365 printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", 365 printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
366 wdt_miscdev.minor, rc); 366 rc);
367 goto err_out_region2; 367 goto err_out_region2;
368 } 368 }
369 369
370 rc = register_reboot_notifier(&wdt_notifier); 370 rc = misc_register(&wdt_miscdev);
371 if (rc) 371 if (rc)
372 { 372 {
373 printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", 373 printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
374 rc); 374 wdt_miscdev.minor, rc);
375 goto err_out_miscdev; 375 goto err_out_reboot;
376 } 376 }
377 377
378 printk(KERN_INFO PFX "WDT driver for 60XX single board computer initialised. timeout=%d sec (nowayout=%d)\n", 378 printk(KERN_INFO PFX "WDT driver for 60XX single board computer initialised. timeout=%d sec (nowayout=%d)\n",
@@ -380,8 +380,8 @@ static int __init sbc60xxwdt_init(void)
380 380
381 return 0; 381 return 0;
382 382
383err_out_miscdev: 383err_out_reboot:
384 misc_deregister(&wdt_miscdev); 384 unregister_reboot_notifier(&wdt_notifier);
385err_out_region2: 385err_out_region2:
386 if ((wdt_stop != 0x45) && (wdt_stop != wdt_start)) 386 if ((wdt_stop != 0x45) && (wdt_stop != wdt_start))
387 release_region(wdt_stop,1); 387 release_region(wdt_stop,1);
diff --git a/drivers/watchdog/scx200_wdt.c b/drivers/watchdog/scx200_wdt.c
index d4fd0fa2f176..d55882bca319 100644
--- a/drivers/watchdog/scx200_wdt.c
+++ b/drivers/watchdog/scx200_wdt.c
@@ -231,17 +231,17 @@ static int __init scx200_wdt_init(void)
231 231
232 sema_init(&open_semaphore, 1); 232 sema_init(&open_semaphore, 1);
233 233
234 r = misc_register(&scx200_wdt_miscdev); 234 r = register_reboot_notifier(&scx200_wdt_notifier);
235 if (r) { 235 if (r) {
236 printk(KERN_ERR NAME ": unable to register reboot notifier");
236 release_region(scx200_cb_base + SCx200_WDT_OFFSET, 237 release_region(scx200_cb_base + SCx200_WDT_OFFSET,
237 SCx200_WDT_SIZE); 238 SCx200_WDT_SIZE);
238 return r; 239 return r;
239 } 240 }
240 241
241 r = register_reboot_notifier(&scx200_wdt_notifier); 242 r = misc_register(&scx200_wdt_miscdev);
242 if (r) { 243 if (r) {
243 printk(KERN_ERR NAME ": unable to register reboot notifier"); 244 unregister_reboot_notifier(&scx200_wdt_notifier);
244 misc_deregister(&scx200_wdt_miscdev);
245 release_region(scx200_cb_base + SCx200_WDT_OFFSET, 245 release_region(scx200_cb_base + SCx200_WDT_OFFSET,
246 SCx200_WDT_SIZE); 246 SCx200_WDT_SIZE);
247 return r; 247 return r;
@@ -252,8 +252,8 @@ static int __init scx200_wdt_init(void)
252 252
253static void __exit scx200_wdt_cleanup(void) 253static void __exit scx200_wdt_cleanup(void)
254{ 254{
255 unregister_reboot_notifier(&scx200_wdt_notifier);
256 misc_deregister(&scx200_wdt_miscdev); 255 misc_deregister(&scx200_wdt_miscdev);
256 unregister_reboot_notifier(&scx200_wdt_notifier);
257 release_region(scx200_cb_base + SCx200_WDT_OFFSET, 257 release_region(scx200_cb_base + SCx200_WDT_OFFSET,
258 SCx200_WDT_SIZE); 258 SCx200_WDT_SIZE);
259} 259}
diff --git a/drivers/watchdog/txx9wdt.c b/drivers/watchdog/txx9wdt.c
new file mode 100644
index 000000000000..328b3c7211ef
--- /dev/null
+++ b/drivers/watchdog/txx9wdt.c
@@ -0,0 +1,276 @@
1/*
2 * txx9wdt: A Hardware Watchdog Driver for TXx9 SoCs
3 *
4 * Copyright (C) 2007 Atsushi Nemoto <anemo@mba.ocn.ne.jp>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10#include <linux/module.h>
11#include <linux/moduleparam.h>
12#include <linux/types.h>
13#include <linux/miscdevice.h>
14#include <linux/watchdog.h>
15#include <linux/fs.h>
16#include <linux/reboot.h>
17#include <linux/init.h>
18#include <linux/uaccess.h>
19#include <linux/platform_device.h>
20#include <linux/clk.h>
21#include <linux/err.h>
22#include <linux/io.h>
23#include <asm/txx9tmr.h>
24
25#define TIMER_MARGIN 60 /* Default is 60 seconds */
26
27static int timeout = TIMER_MARGIN; /* in seconds */
28module_param(timeout, int, 0);
29MODULE_PARM_DESC(timeout,
30 "Watchdog timeout in seconds. "
31 "(0<timeout<((2^" __MODULE_STRING(TXX9_TIMER_BITS) ")/(IMCLK/256)), "
32 "default=" __MODULE_STRING(TIMER_MARGIN) ")");
33
34static int nowayout = WATCHDOG_NOWAYOUT;
35module_param(nowayout, int, 0);
36MODULE_PARM_DESC(nowayout,
37 "Watchdog cannot be stopped once started "
38 "(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
39
40#define WD_TIMER_CCD 7 /* 1/256 */
41#define WD_TIMER_CLK (clk_get_rate(txx9_imclk) / (2 << WD_TIMER_CCD))
42#define WD_MAX_TIMEOUT ((0xffffffff >> (32 - TXX9_TIMER_BITS)) / WD_TIMER_CLK)
43
44static unsigned long txx9wdt_alive;
45static int expect_close;
46static struct txx9_tmr_reg __iomem *txx9wdt_reg;
47static struct clk *txx9_imclk;
48
49static void txx9wdt_ping(void)
50{
51 __raw_writel(TXx9_TMWTMR_TWIE | TXx9_TMWTMR_TWC, &txx9wdt_reg->wtmr);
52}
53
54static void txx9wdt_start(void)
55{
56 __raw_writel(WD_TIMER_CLK * timeout, &txx9wdt_reg->cpra);
57 __raw_writel(WD_TIMER_CCD, &txx9wdt_reg->ccdr);
58 __raw_writel(0, &txx9wdt_reg->tisr); /* clear pending interrupt */
59 __raw_writel(TXx9_TMTCR_TCE | TXx9_TMTCR_CCDE | TXx9_TMTCR_TMODE_WDOG,
60 &txx9wdt_reg->tcr);
61 __raw_writel(TXx9_TMWTMR_TWIE | TXx9_TMWTMR_TWC, &txx9wdt_reg->wtmr);
62}
63
64static void txx9wdt_stop(void)
65{
66 __raw_writel(TXx9_TMWTMR_WDIS, &txx9wdt_reg->wtmr);
67 __raw_writel(__raw_readl(&txx9wdt_reg->tcr) & ~TXx9_TMTCR_TCE,
68 &txx9wdt_reg->tcr);
69}
70
71static int txx9wdt_open(struct inode *inode, struct file *file)
72{
73 if (test_and_set_bit(0, &txx9wdt_alive))
74 return -EBUSY;
75
76 if (__raw_readl(&txx9wdt_reg->tcr) & TXx9_TMTCR_TCE) {
77 clear_bit(0, &txx9wdt_alive);
78 return -EBUSY;
79 }
80
81 if (nowayout)
82 __module_get(THIS_MODULE);
83
84 txx9wdt_start();
85 return nonseekable_open(inode, file);
86}
87
88static int txx9wdt_release(struct inode *inode, struct file *file)
89{
90 if (expect_close)
91 txx9wdt_stop();
92 else {
93 printk(KERN_CRIT "txx9wdt: "
94 "Unexpected close, not stopping watchdog!\n");
95 txx9wdt_ping();
96 }
97 clear_bit(0, &txx9wdt_alive);
98 expect_close = 0;
99 return 0;
100}
101
102static ssize_t txx9wdt_write(struct file *file, const char __user *data,
103 size_t len, loff_t *ppos)
104{
105 if (len) {
106 if (!nowayout) {
107 size_t i;
108
109 expect_close = 0;
110 for (i = 0; i != len; i++) {
111 char c;
112 if (get_user(c, data + i))
113 return -EFAULT;
114 if (c == 'V')
115 expect_close = 1;
116 }
117 }
118 txx9wdt_ping();
119 }
120 return len;
121}
122
123static int txx9wdt_ioctl(struct inode *inode, struct file *file,
124 unsigned int cmd, unsigned long arg)
125{
126 void __user *argp = (void __user *)arg;
127 int __user *p = argp;
128 int new_timeout;
129 static struct watchdog_info ident = {
130 .options = WDIOF_SETTIMEOUT |
131 WDIOF_KEEPALIVEPING |
132 WDIOF_MAGICCLOSE,
133 .firmware_version = 0,
134 .identity = "Hardware Watchdog for TXx9",
135 };
136
137 switch (cmd) {
138 default:
139 return -ENOTTY;
140 case WDIOC_GETSUPPORT:
141 return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
142 case WDIOC_GETSTATUS:
143 case WDIOC_GETBOOTSTATUS:
144 return put_user(0, p);
145 case WDIOC_KEEPALIVE:
146 txx9wdt_ping();
147 return 0;
148 case WDIOC_SETTIMEOUT:
149 if (get_user(new_timeout, p))
150 return -EFAULT;
151 if (new_timeout < 1 || new_timeout > WD_MAX_TIMEOUT)
152 return -EINVAL;
153 timeout = new_timeout;
154 txx9wdt_stop();
155 txx9wdt_start();
156 /* Fall */
157 case WDIOC_GETTIMEOUT:
158 return put_user(timeout, p);
159 }
160}
161
162static int txx9wdt_notify_sys(struct notifier_block *this, unsigned long code,
163 void *unused)
164{
165 if (code == SYS_DOWN || code == SYS_HALT)
166 txx9wdt_stop();
167 return NOTIFY_DONE;
168}
169
170static const struct file_operations txx9wdt_fops = {
171 .owner = THIS_MODULE,
172 .llseek = no_llseek,
173 .write = txx9wdt_write,
174 .ioctl = txx9wdt_ioctl,
175 .open = txx9wdt_open,
176 .release = txx9wdt_release,
177};
178
179static struct miscdevice txx9wdt_miscdev = {
180 .minor = WATCHDOG_MINOR,
181 .name = "watchdog",
182 .fops = &txx9wdt_fops,
183};
184
185static struct notifier_block txx9wdt_notifier = {
186 .notifier_call = txx9wdt_notify_sys
187};
188
189static int __init txx9wdt_probe(struct platform_device *dev)
190{
191 struct resource *res;
192 int ret;
193
194 txx9_imclk = clk_get(NULL, "imbus_clk");
195 if (IS_ERR(txx9_imclk)) {
196 ret = PTR_ERR(txx9_imclk);
197 txx9_imclk = NULL;
198 goto exit;
199 }
200 ret = clk_enable(txx9_imclk);
201 if (ret) {
202 clk_put(txx9_imclk);
203 txx9_imclk = NULL;
204 goto exit;
205 }
206
207 res = platform_get_resource(dev, IORESOURCE_MEM, 0);
208 if (!res)
209 goto exit_busy;
210 if (!devm_request_mem_region(&dev->dev,
211 res->start, res->end - res->start + 1,
212 "txx9wdt"))
213 goto exit_busy;
214 txx9wdt_reg = devm_ioremap(&dev->dev,
215 res->start, res->end - res->start + 1);
216 if (!txx9wdt_reg)
217 goto exit_busy;
218
219 ret = register_reboot_notifier(&txx9wdt_notifier);
220 if (ret)
221 goto exit;
222
223 ret = misc_register(&txx9wdt_miscdev);
224 if (ret) {
225 unregister_reboot_notifier(&txx9wdt_notifier);
226 goto exit;
227 }
228
229 printk(KERN_INFO "Hardware Watchdog Timer for TXx9: "
230 "timeout=%d sec (max %ld) (nowayout= %d)\n",
231 timeout, WD_MAX_TIMEOUT, nowayout);
232
233 return 0;
234exit_busy:
235 ret = -EBUSY;
236exit:
237 if (txx9_imclk) {
238 clk_disable(txx9_imclk);
239 clk_put(txx9_imclk);
240 }
241 return ret;
242}
243
244static int __exit txx9wdt_remove(struct platform_device *dev)
245{
246 misc_deregister(&txx9wdt_miscdev);
247 unregister_reboot_notifier(&txx9wdt_notifier);
248 clk_disable(txx9_imclk);
249 clk_put(txx9_imclk);
250 return 0;
251}
252
253static struct platform_driver txx9wdt_driver = {
254 .remove = __exit_p(txx9wdt_remove),
255 .driver = {
256 .name = "txx9wdt",
257 .owner = THIS_MODULE,
258 },
259};
260
261static int __init watchdog_init(void)
262{
263 return platform_driver_probe(&txx9wdt_driver, txx9wdt_probe);
264}
265
266static void __exit watchdog_exit(void)
267{
268 platform_driver_unregister(&txx9wdt_driver);
269}
270
271module_init(watchdog_init);
272module_exit(watchdog_exit);
273
274MODULE_DESCRIPTION("TXx9 Watchdog Driver");
275MODULE_LICENSE("GPL");
276MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/watchdog/w83877f_wdt.c b/drivers/watchdog/w83877f_wdt.c
index bcc9d48955de..f510a3a595e6 100644
--- a/drivers/watchdog/w83877f_wdt.c
+++ b/drivers/watchdog/w83877f_wdt.c
@@ -373,20 +373,20 @@ static int __init w83877f_wdt_init(void)
373 goto err_out_region1; 373 goto err_out_region1;
374 } 374 }
375 375
376 rc = misc_register(&wdt_miscdev); 376 rc = register_reboot_notifier(&wdt_notifier);
377 if (rc) 377 if (rc)
378 { 378 {
379 printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", 379 printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
380 wdt_miscdev.minor, rc); 380 rc);
381 goto err_out_region2; 381 goto err_out_region2;
382 } 382 }
383 383
384 rc = register_reboot_notifier(&wdt_notifier); 384 rc = misc_register(&wdt_miscdev);
385 if (rc) 385 if (rc)
386 { 386 {
387 printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", 387 printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
388 rc); 388 wdt_miscdev.minor, rc);
389 goto err_out_miscdev; 389 goto err_out_reboot;
390 } 390 }
391 391
392 printk(KERN_INFO PFX "WDT driver for W83877F initialised. timeout=%d sec (nowayout=%d)\n", 392 printk(KERN_INFO PFX "WDT driver for W83877F initialised. timeout=%d sec (nowayout=%d)\n",
@@ -394,8 +394,8 @@ static int __init w83877f_wdt_init(void)
394 394
395 return 0; 395 return 0;
396 396
397err_out_miscdev: 397err_out_reboot:
398 misc_deregister(&wdt_miscdev); 398 unregister_reboot_notifier(&wdt_notifier);
399err_out_region2: 399err_out_region2:
400 release_region(WDT_PING,1); 400 release_region(WDT_PING,1);
401err_out_region1: 401err_out_region1:
diff --git a/drivers/watchdog/w83977f_wdt.c b/drivers/watchdog/w83977f_wdt.c
index b475529d2475..b209bcd7f789 100644
--- a/drivers/watchdog/w83977f_wdt.c
+++ b/drivers/watchdog/w83977f_wdt.c
@@ -494,20 +494,20 @@ static int __init w83977f_wdt_init(void)
494 goto err_out; 494 goto err_out;
495 } 495 }
496 496
497 rc = misc_register(&wdt_miscdev); 497 rc = register_reboot_notifier(&wdt_notifier);
498 if (rc) 498 if (rc)
499 { 499 {
500 printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", 500 printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
501 wdt_miscdev.minor, rc); 501 rc);
502 goto err_out_region; 502 goto err_out_region;
503 } 503 }
504 504
505 rc = register_reboot_notifier(&wdt_notifier); 505 rc = misc_register(&wdt_miscdev);
506 if (rc) 506 if (rc)
507 { 507 {
508 printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", 508 printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
509 rc); 509 wdt_miscdev.minor, rc);
510 goto err_out_miscdev; 510 goto err_out_reboot;
511 } 511 }
512 512
513 printk(KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d testmode=%d)\n", 513 printk(KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d testmode=%d)\n",
@@ -515,8 +515,8 @@ static int __init w83977f_wdt_init(void)
515 515
516 return 0; 516 return 0;
517 517
518err_out_miscdev: 518err_out_reboot:
519 misc_deregister(&wdt_miscdev); 519 unregister_reboot_notifier(&wdt_notifier);
520err_out_region: 520err_out_region:
521 release_region(IO_INDEX_PORT,2); 521 release_region(IO_INDEX_PORT,2);
522err_out: 522err_out:
diff --git a/drivers/watchdog/wdt.c b/drivers/watchdog/wdt.c
index 53d0bb410df8..756fb15fdce7 100644
--- a/drivers/watchdog/wdt.c
+++ b/drivers/watchdog/wdt.c
@@ -70,6 +70,8 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" _
70static int io=0x240; 70static int io=0x240;
71static int irq=11; 71static int irq=11;
72 72
73static DEFINE_SPINLOCK(wdt_lock);
74
73module_param(io, int, 0); 75module_param(io, int, 0);
74MODULE_PARM_DESC(io, "WDT io port (default=0x240)"); 76MODULE_PARM_DESC(io, "WDT io port (default=0x240)");
75module_param(irq, int, 0); 77module_param(irq, int, 0);
@@ -109,6 +111,8 @@ static void wdt_ctr_load(int ctr, int val)
109 111
110static int wdt_start(void) 112static int wdt_start(void)
111{ 113{
114 unsigned long flags;
115 spin_lock_irqsave(&wdt_lock, flags);
112 inb_p(WDT_DC); /* Disable watchdog */ 116 inb_p(WDT_DC); /* Disable watchdog */
113 wdt_ctr_mode(0,3); /* Program CTR0 for Mode 3: Square Wave Generator */ 117 wdt_ctr_mode(0,3); /* Program CTR0 for Mode 3: Square Wave Generator */
114 wdt_ctr_mode(1,2); /* Program CTR1 for Mode 2: Rate Generator */ 118 wdt_ctr_mode(1,2); /* Program CTR1 for Mode 2: Rate Generator */
@@ -117,6 +121,7 @@ static int wdt_start(void)
117 wdt_ctr_load(1,wd_heartbeat); /* Heartbeat */ 121 wdt_ctr_load(1,wd_heartbeat); /* Heartbeat */
118 wdt_ctr_load(2,65535); /* Length of reset pulse */ 122 wdt_ctr_load(2,65535); /* Length of reset pulse */
119 outb_p(0, WDT_DC); /* Enable watchdog */ 123 outb_p(0, WDT_DC); /* Enable watchdog */
124 spin_unlock_irqrestore(&wdt_lock, flags);
120 return 0; 125 return 0;
121} 126}
122 127
@@ -128,9 +133,12 @@ static int wdt_start(void)
128 133
129static int wdt_stop (void) 134static int wdt_stop (void)
130{ 135{
136 unsigned long flags;
137 spin_lock_irqsave(&wdt_lock, flags);
131 /* Turn the card off */ 138 /* Turn the card off */
132 inb_p(WDT_DC); /* Disable watchdog */ 139 inb_p(WDT_DC); /* Disable watchdog */
133 wdt_ctr_load(2,0); /* 0 length reset pulses now */ 140 wdt_ctr_load(2,0); /* 0 length reset pulses now */
141 spin_unlock_irqrestore(&wdt_lock, flags);
134 return 0; 142 return 0;
135} 143}
136 144
@@ -143,11 +151,14 @@ static int wdt_stop (void)
143 151
144static int wdt_ping(void) 152static int wdt_ping(void)
145{ 153{
154 unsigned long flags;
155 spin_lock_irqsave(&wdt_lock, flags);
146 /* Write a watchdog value */ 156 /* Write a watchdog value */
147 inb_p(WDT_DC); /* Disable watchdog */ 157 inb_p(WDT_DC); /* Disable watchdog */
148 wdt_ctr_mode(1,2); /* Re-Program CTR1 for Mode 2: Rate Generator */ 158 wdt_ctr_mode(1,2); /* Re-Program CTR1 for Mode 2: Rate Generator */
149 wdt_ctr_load(1,wd_heartbeat); /* Heartbeat */ 159 wdt_ctr_load(1,wd_heartbeat); /* Heartbeat */
150 outb_p(0, WDT_DC); /* Enable watchdog */ 160 outb_p(0, WDT_DC); /* Enable watchdog */
161 spin_unlock_irqrestore(&wdt_lock, flags);
151 return 0; 162 return 0;
152} 163}
153 164
@@ -182,7 +193,12 @@ static int wdt_set_heartbeat(int t)
182 193
183static int wdt_get_status(int *status) 194static int wdt_get_status(int *status)
184{ 195{
185 unsigned char new_status=inb_p(WDT_SR); 196 unsigned char new_status;
197 unsigned long flags;
198
199 spin_lock_irqsave(&wdt_lock, flags);
200 new_status = inb_p(WDT_SR);
201 spin_unlock_irqrestore(&wdt_lock, flags);
186 202
187 *status=0; 203 *status=0;
188 if (new_status & WDC_SR_ISOI0) 204 if (new_status & WDC_SR_ISOI0)
@@ -214,8 +230,12 @@ static int wdt_get_status(int *status)
214 230
215static int wdt_get_temperature(int *temperature) 231static int wdt_get_temperature(int *temperature)
216{ 232{
217 unsigned short c=inb_p(WDT_RT); 233 unsigned short c;
234 unsigned long flags;
218 235
236 spin_lock_irqsave(&wdt_lock, flags);
237 c = inb_p(WDT_RT);
238 spin_unlock_irqrestore(&wdt_lock, flags);
219 *temperature = (c * 11 / 15) + 7; 239 *temperature = (c * 11 / 15) + 7;
220 return 0; 240 return 0;
221} 241}
@@ -237,7 +257,10 @@ static irqreturn_t wdt_interrupt(int irq, void *dev_id)
237 * Read the status register see what is up and 257 * Read the status register see what is up and
238 * then printk it. 258 * then printk it.
239 */ 259 */
240 unsigned char status=inb_p(WDT_SR); 260 unsigned char status;
261
262 spin_lock(&wdt_lock);
263 status = inb_p(WDT_SR);
241 264
242 printk(KERN_CRIT "WDT status %d\n", status); 265 printk(KERN_CRIT "WDT status %d\n", status);
243 266
@@ -265,6 +288,7 @@ static irqreturn_t wdt_interrupt(int irq, void *dev_id)
265 printk(KERN_CRIT "Reset in 5ms.\n"); 288 printk(KERN_CRIT "Reset in 5ms.\n");
266#endif 289#endif
267 } 290 }
291 spin_unlock(&wdt_lock);
268 return IRQ_HANDLED; 292 return IRQ_HANDLED;
269} 293}
270 294
diff --git a/drivers/watchdog/wdt977.c b/drivers/watchdog/wdt977.c
index 9b7f6b6edef6..fb4b876c9fda 100644
--- a/drivers/watchdog/wdt977.c
+++ b/drivers/watchdog/wdt977.c
@@ -470,20 +470,20 @@ static int __init wd977_init(void)
470 } 470 }
471 } 471 }
472 472
473 rc = misc_register(&wdt977_miscdev); 473 rc = register_reboot_notifier(&wdt977_notifier);
474 if (rc) 474 if (rc)
475 { 475 {
476 printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", 476 printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
477 wdt977_miscdev.minor, rc); 477 rc);
478 goto err_out_region; 478 goto err_out_region;
479 } 479 }
480 480
481 rc = register_reboot_notifier(&wdt977_notifier); 481 rc = misc_register(&wdt977_miscdev);
482 if (rc) 482 if (rc)
483 { 483 {
484 printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", 484 printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
485 rc); 485 wdt977_miscdev.minor, rc);
486 goto err_out_miscdev; 486 goto err_out_reboot;
487 } 487 }
488 488
489 printk(KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d, testmode=%i)\n", 489 printk(KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d, testmode=%i)\n",
@@ -491,8 +491,8 @@ static int __init wd977_init(void)
491 491
492 return 0; 492 return 0;
493 493
494err_out_miscdev: 494err_out_reboot:
495 misc_deregister(&wdt977_miscdev); 495 unregister_reboot_notifier(&wdt977_notifier);
496err_out_region: 496err_out_region:
497 if (!machine_is_netwinder()) 497 if (!machine_is_netwinder())
498 release_region(IO_INDEX_PORT,2); 498 release_region(IO_INDEX_PORT,2);