diff options
| -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); |
