diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-01-28 17:00:01 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-01-28 17:00:01 -0500 |
commit | 8561b089afbaed2651591e5a4574fdca451d82f2 (patch) | |
tree | 3c3bd24884eb65a89b0b896bcd7790e6144cebfc | |
parent | e189f3495c4e30fc84fc9241096edf3932e23439 (diff) | |
parent | b47a166ed0baaaa30112532bad41b21e7c5e4d31 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/wim/linux-2.6-watchdog
* git://git.kernel.org/pub/scm/linux/kernel/git/wim/linux-2.6-watchdog:
[WATCHDOG] constify function pointer tables
[WATCHDOG] TXx9 watchdog driver
[WATCHDOG] misc_register patch
[WATCHDOG] wdt: fix locking
-rw-r--r-- | drivers/watchdog/Kconfig | 6 | ||||
-rw-r--r-- | drivers/watchdog/Makefile | 1 | ||||
-rw-r--r-- | drivers/watchdog/alim1535_wdt.c | 20 | ||||
-rw-r--r-- | drivers/watchdog/alim7101_wdt.c | 18 | ||||
-rw-r--r-- | drivers/watchdog/ar7_wdt.c | 2 | ||||
-rw-r--r-- | drivers/watchdog/bfin_wdt.c | 2 | ||||
-rw-r--r-- | drivers/watchdog/it8712f_wdt.c | 2 | ||||
-rw-r--r-- | drivers/watchdog/mpc5200_wdt.c | 2 | ||||
-rw-r--r-- | drivers/watchdog/mtx-1_wdt.c | 2 | ||||
-rw-r--r-- | drivers/watchdog/sbc60xxwdt.c | 18 | ||||
-rw-r--r-- | drivers/watchdog/scx200_wdt.c | 10 | ||||
-rw-r--r-- | drivers/watchdog/txx9wdt.c | 276 | ||||
-rw-r--r-- | drivers/watchdog/w83877f_wdt.c | 18 | ||||
-rw-r--r-- | drivers/watchdog/w83977f_wdt.c | 18 | ||||
-rw-r--r-- | drivers/watchdog/wdt.c | 30 | ||||
-rw-r--r-- | drivers/watchdog/wdt977.c | 18 |
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 | ||
642 | config 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 | |||
93 | obj-$(CONFIG_WDT_MTX1) += mtx-1_wdt.o | 93 | obj-$(CONFIG_WDT_MTX1) += mtx-1_wdt.o |
94 | obj-$(CONFIG_WDT_RM9K_GPI) += rm9k_wdt.o | 94 | obj-$(CONFIG_WDT_RM9K_GPI) += rm9k_wdt.o |
95 | obj-$(CONFIG_AR7_WDT) += ar7_wdt.o | 95 | obj-$(CONFIG_AR7_WDT) += ar7_wdt.o |
96 | obj-$(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 | ||
433 | out: | 433 | out: |
434 | return ret; | 434 | return ret; |
435 | unreg_miscdev: | 435 | unreg_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 | ||
402 | err_out_miscdev: | 402 | err_out_reboot: |
403 | misc_deregister(&wdt_miscdev); | 403 | unregister_reboot_notifier(&wdt_notifier); |
404 | err_out: | 404 | err_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 | ||
282 | static struct file_operations ar7_wdt_fops = { | 282 | static 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 | ||
393 | static struct file_operations bfin_wdt_fops = { | 393 | static 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 | ||
299 | static struct file_operations it8712f_wdt_fops = { | 299 | static 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 | ||
161 | static struct file_operations mpc5200_wdt_fops = { | 161 | static 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 | ||
183 | static struct file_operations mtx1_wdt_fops = { | 183 | static 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 | ||
383 | err_out_miscdev: | 383 | err_out_reboot: |
384 | misc_deregister(&wdt_miscdev); | 384 | unregister_reboot_notifier(&wdt_notifier); |
385 | err_out_region2: | 385 | err_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 | ||
253 | static void __exit scx200_wdt_cleanup(void) | 253 | static 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 | |||
27 | static int timeout = TIMER_MARGIN; /* in seconds */ | ||
28 | module_param(timeout, int, 0); | ||
29 | MODULE_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 | |||
34 | static int nowayout = WATCHDOG_NOWAYOUT; | ||
35 | module_param(nowayout, int, 0); | ||
36 | MODULE_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 | |||
44 | static unsigned long txx9wdt_alive; | ||
45 | static int expect_close; | ||
46 | static struct txx9_tmr_reg __iomem *txx9wdt_reg; | ||
47 | static struct clk *txx9_imclk; | ||
48 | |||
49 | static void txx9wdt_ping(void) | ||
50 | { | ||
51 | __raw_writel(TXx9_TMWTMR_TWIE | TXx9_TMWTMR_TWC, &txx9wdt_reg->wtmr); | ||
52 | } | ||
53 | |||
54 | static 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 | |||
64 | static 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 | |||
71 | static 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 | |||
88 | static 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 | |||
102 | static 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 | |||
123 | static 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 | |||
162 | static 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 | |||
170 | static 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 | |||
179 | static struct miscdevice txx9wdt_miscdev = { | ||
180 | .minor = WATCHDOG_MINOR, | ||
181 | .name = "watchdog", | ||
182 | .fops = &txx9wdt_fops, | ||
183 | }; | ||
184 | |||
185 | static struct notifier_block txx9wdt_notifier = { | ||
186 | .notifier_call = txx9wdt_notify_sys | ||
187 | }; | ||
188 | |||
189 | static 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; | ||
234 | exit_busy: | ||
235 | ret = -EBUSY; | ||
236 | exit: | ||
237 | if (txx9_imclk) { | ||
238 | clk_disable(txx9_imclk); | ||
239 | clk_put(txx9_imclk); | ||
240 | } | ||
241 | return ret; | ||
242 | } | ||
243 | |||
244 | static 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 | |||
253 | static struct platform_driver txx9wdt_driver = { | ||
254 | .remove = __exit_p(txx9wdt_remove), | ||
255 | .driver = { | ||
256 | .name = "txx9wdt", | ||
257 | .owner = THIS_MODULE, | ||
258 | }, | ||
259 | }; | ||
260 | |||
261 | static int __init watchdog_init(void) | ||
262 | { | ||
263 | return platform_driver_probe(&txx9wdt_driver, txx9wdt_probe); | ||
264 | } | ||
265 | |||
266 | static void __exit watchdog_exit(void) | ||
267 | { | ||
268 | platform_driver_unregister(&txx9wdt_driver); | ||
269 | } | ||
270 | |||
271 | module_init(watchdog_init); | ||
272 | module_exit(watchdog_exit); | ||
273 | |||
274 | MODULE_DESCRIPTION("TXx9 Watchdog Driver"); | ||
275 | MODULE_LICENSE("GPL"); | ||
276 | MODULE_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 | ||
397 | err_out_miscdev: | 397 | err_out_reboot: |
398 | misc_deregister(&wdt_miscdev); | 398 | unregister_reboot_notifier(&wdt_notifier); |
399 | err_out_region2: | 399 | err_out_region2: |
400 | release_region(WDT_PING,1); | 400 | release_region(WDT_PING,1); |
401 | err_out_region1: | 401 | err_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 | ||
518 | err_out_miscdev: | 518 | err_out_reboot: |
519 | misc_deregister(&wdt_miscdev); | 519 | unregister_reboot_notifier(&wdt_notifier); |
520 | err_out_region: | 520 | err_out_region: |
521 | release_region(IO_INDEX_PORT,2); | 521 | release_region(IO_INDEX_PORT,2); |
522 | err_out: | 522 | err_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=" _ | |||
70 | static int io=0x240; | 70 | static int io=0x240; |
71 | static int irq=11; | 71 | static int irq=11; |
72 | 72 | ||
73 | static DEFINE_SPINLOCK(wdt_lock); | ||
74 | |||
73 | module_param(io, int, 0); | 75 | module_param(io, int, 0); |
74 | MODULE_PARM_DESC(io, "WDT io port (default=0x240)"); | 76 | MODULE_PARM_DESC(io, "WDT io port (default=0x240)"); |
75 | module_param(irq, int, 0); | 77 | module_param(irq, int, 0); |
@@ -109,6 +111,8 @@ static void wdt_ctr_load(int ctr, int val) | |||
109 | 111 | ||
110 | static int wdt_start(void) | 112 | static 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 | ||
129 | static int wdt_stop (void) | 134 | static 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 | ||
144 | static int wdt_ping(void) | 152 | static 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 | ||
183 | static int wdt_get_status(int *status) | 194 | static 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 | ||
215 | static int wdt_get_temperature(int *temperature) | 231 | static 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 | ||
494 | err_out_miscdev: | 494 | err_out_reboot: |
495 | misc_deregister(&wdt977_miscdev); | 495 | unregister_reboot_notifier(&wdt977_notifier); |
496 | err_out_region: | 496 | err_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); |