diff options
| -rw-r--r-- | drivers/char/ipmi/ipmi_watchdog.c | 13 | ||||
| -rw-r--r-- | drivers/watchdog/Kconfig | 2 | ||||
| -rw-r--r-- | drivers/watchdog/bcm63xx_wdt.c | 4 | ||||
| -rw-r--r-- | drivers/watchdog/coh901327_wdt.c | 7 | ||||
| -rw-r--r-- | drivers/watchdog/f71808e_wdt.c | 4 | ||||
| -rw-r--r-- | drivers/watchdog/iTCO_wdt.c | 213 | ||||
| -rw-r--r-- | drivers/watchdog/ie6xx_wdt.c | 4 | ||||
| -rw-r--r-- | drivers/watchdog/of_xilinx_wdt.c | 2 | ||||
| -rw-r--r-- | drivers/watchdog/omap_wdt.c | 17 | ||||
| -rw-r--r-- | drivers/watchdog/orion_wdt.c | 203 | ||||
| -rw-r--r-- | drivers/watchdog/s3c2410_wdt.c | 16 | ||||
| -rw-r--r-- | drivers/watchdog/sch311x_wdt.c | 10 |
12 files changed, 121 insertions, 374 deletions
diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c index 7ed356e52035..37b8be7cba95 100644 --- a/drivers/char/ipmi/ipmi_watchdog.c +++ b/drivers/char/ipmi/ipmi_watchdog.c | |||
| @@ -141,17 +141,6 @@ | |||
| 141 | 141 | ||
| 142 | #define IPMI_WDOG_TIMER_NOT_INIT_RESP 0x80 | 142 | #define IPMI_WDOG_TIMER_NOT_INIT_RESP 0x80 |
| 143 | 143 | ||
| 144 | /* These are here until the real ones get into the watchdog.h interface. */ | ||
| 145 | #ifndef WDIOC_GETTIMEOUT | ||
| 146 | #define WDIOC_GETTIMEOUT _IOW(WATCHDOG_IOCTL_BASE, 20, int) | ||
| 147 | #endif | ||
| 148 | #ifndef WDIOC_SET_PRETIMEOUT | ||
| 149 | #define WDIOC_SET_PRETIMEOUT _IOW(WATCHDOG_IOCTL_BASE, 21, int) | ||
| 150 | #endif | ||
| 151 | #ifndef WDIOC_GET_PRETIMEOUT | ||
| 152 | #define WDIOC_GET_PRETIMEOUT _IOW(WATCHDOG_IOCTL_BASE, 22, int) | ||
| 153 | #endif | ||
| 154 | |||
| 155 | static DEFINE_MUTEX(ipmi_watchdog_mutex); | 144 | static DEFINE_MUTEX(ipmi_watchdog_mutex); |
| 156 | static bool nowayout = WATCHDOG_NOWAYOUT; | 145 | static bool nowayout = WATCHDOG_NOWAYOUT; |
| 157 | 146 | ||
| @@ -732,7 +721,6 @@ static int ipmi_ioctl(struct file *file, | |||
| 732 | return -EFAULT; | 721 | return -EFAULT; |
| 733 | return 0; | 722 | return 0; |
| 734 | 723 | ||
| 735 | case WDIOC_SET_PRETIMEOUT: | ||
| 736 | case WDIOC_SETPRETIMEOUT: | 724 | case WDIOC_SETPRETIMEOUT: |
| 737 | i = copy_from_user(&val, argp, sizeof(int)); | 725 | i = copy_from_user(&val, argp, sizeof(int)); |
| 738 | if (i) | 726 | if (i) |
| @@ -740,7 +728,6 @@ static int ipmi_ioctl(struct file *file, | |||
| 740 | pretimeout = val; | 728 | pretimeout = val; |
| 741 | return ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY); | 729 | return ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY); |
| 742 | 730 | ||
| 743 | case WDIOC_GET_PRETIMEOUT: | ||
| 744 | case WDIOC_GETPRETIMEOUT: | 731 | case WDIOC_GETPRETIMEOUT: |
| 745 | i = copy_to_user(argp, &pretimeout, sizeof(pretimeout)); | 732 | i = copy_to_user(argp, &pretimeout, sizeof(pretimeout)); |
| 746 | if (i) | 733 | if (i) |
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index c450cfcd702f..53d75719078e 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig | |||
| @@ -279,6 +279,7 @@ config DAVINCI_WATCHDOG | |||
| 279 | config ORION_WATCHDOG | 279 | config ORION_WATCHDOG |
| 280 | tristate "Orion watchdog" | 280 | tristate "Orion watchdog" |
| 281 | depends on ARCH_ORION5X || ARCH_KIRKWOOD | 281 | depends on ARCH_ORION5X || ARCH_KIRKWOOD |
| 282 | select WATCHDOG_CORE | ||
| 282 | help | 283 | help |
| 283 | Say Y here if to include support for the watchdog timer | 284 | Say Y here if to include support for the watchdog timer |
| 284 | in the Marvell Orion5x and Kirkwood ARM SoCs. | 285 | in the Marvell Orion5x and Kirkwood ARM SoCs. |
| @@ -578,6 +579,7 @@ config INTEL_SCU_WATCHDOG | |||
| 578 | config ITCO_WDT | 579 | config ITCO_WDT |
| 579 | tristate "Intel TCO Timer/Watchdog" | 580 | tristate "Intel TCO Timer/Watchdog" |
| 580 | depends on (X86 || IA64) && PCI | 581 | depends on (X86 || IA64) && PCI |
| 582 | select WATCHDOG_CORE | ||
| 581 | select LPC_ICH | 583 | select LPC_ICH |
| 582 | ---help--- | 584 | ---help--- |
| 583 | Hardware driver for the intel TCO timer based watchdog devices. | 585 | Hardware driver for the intel TCO timer based watchdog devices. |
diff --git a/drivers/watchdog/bcm63xx_wdt.c b/drivers/watchdog/bcm63xx_wdt.c index 8379dc32fd90..551880bfd629 100644 --- a/drivers/watchdog/bcm63xx_wdt.c +++ b/drivers/watchdog/bcm63xx_wdt.c | |||
| @@ -302,7 +302,7 @@ static void bcm63xx_wdt_shutdown(struct platform_device *pdev) | |||
| 302 | bcm63xx_wdt_pause(); | 302 | bcm63xx_wdt_pause(); |
| 303 | } | 303 | } |
| 304 | 304 | ||
| 305 | static struct platform_driver bcm63xx_wdt = { | 305 | static struct platform_driver bcm63xx_wdt_driver = { |
| 306 | .probe = bcm63xx_wdt_probe, | 306 | .probe = bcm63xx_wdt_probe, |
| 307 | .remove = __devexit_p(bcm63xx_wdt_remove), | 307 | .remove = __devexit_p(bcm63xx_wdt_remove), |
| 308 | .shutdown = bcm63xx_wdt_shutdown, | 308 | .shutdown = bcm63xx_wdt_shutdown, |
| @@ -312,7 +312,7 @@ static struct platform_driver bcm63xx_wdt = { | |||
| 312 | } | 312 | } |
| 313 | }; | 313 | }; |
| 314 | 314 | ||
| 315 | module_platform_driver(bcm63xx_wdt); | 315 | module_platform_driver(bcm63xx_wdt_driver); |
| 316 | 316 | ||
| 317 | MODULE_AUTHOR("Miguel Gaio <miguel.gaio@efixo.com>"); | 317 | MODULE_AUTHOR("Miguel Gaio <miguel.gaio@efixo.com>"); |
| 318 | MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>"); | 318 | MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>"); |
diff --git a/drivers/watchdog/coh901327_wdt.c b/drivers/watchdog/coh901327_wdt.c index 6876430a9f5e..cb5da5c3ece2 100644 --- a/drivers/watchdog/coh901327_wdt.c +++ b/drivers/watchdog/coh901327_wdt.c | |||
| @@ -263,6 +263,7 @@ static int __exit coh901327_remove(struct platform_device *pdev) | |||
| 263 | watchdog_unregister_device(&coh901327_wdt); | 263 | watchdog_unregister_device(&coh901327_wdt); |
| 264 | coh901327_disable(); | 264 | coh901327_disable(); |
| 265 | free_irq(irq, pdev); | 265 | free_irq(irq, pdev); |
| 266 | clk_unprepare(clk); | ||
| 266 | clk_put(clk); | 267 | clk_put(clk); |
| 267 | iounmap(virtbase); | 268 | iounmap(virtbase); |
| 268 | release_mem_region(phybase, physize); | 269 | release_mem_region(phybase, physize); |
| @@ -300,9 +301,9 @@ static int __init coh901327_probe(struct platform_device *pdev) | |||
| 300 | dev_err(&pdev->dev, "could not get clock\n"); | 301 | dev_err(&pdev->dev, "could not get clock\n"); |
| 301 | goto out_no_clk; | 302 | goto out_no_clk; |
| 302 | } | 303 | } |
| 303 | ret = clk_enable(clk); | 304 | ret = clk_prepare_enable(clk); |
| 304 | if (ret) { | 305 | if (ret) { |
| 305 | dev_err(&pdev->dev, "could not enable clock\n"); | 306 | dev_err(&pdev->dev, "could not prepare and enable clock\n"); |
| 306 | goto out_no_clk_enable; | 307 | goto out_no_clk_enable; |
| 307 | } | 308 | } |
| 308 | 309 | ||
| @@ -369,7 +370,7 @@ static int __init coh901327_probe(struct platform_device *pdev) | |||
| 369 | out_no_wdog: | 370 | out_no_wdog: |
| 370 | free_irq(irq, pdev); | 371 | free_irq(irq, pdev); |
| 371 | out_no_irq: | 372 | out_no_irq: |
| 372 | clk_disable(clk); | 373 | clk_disable_unprepare(clk); |
| 373 | out_no_clk_enable: | 374 | out_no_clk_enable: |
| 374 | clk_put(clk); | 375 | clk_put(clk); |
| 375 | out_no_clk: | 376 | out_no_clk: |
diff --git a/drivers/watchdog/f71808e_wdt.c b/drivers/watchdog/f71808e_wdt.c index c65b0a5a020c..016bd9355190 100644 --- a/drivers/watchdog/f71808e_wdt.c +++ b/drivers/watchdog/f71808e_wdt.c | |||
| @@ -56,6 +56,7 @@ | |||
| 56 | #define SIO_F71858_ID 0x0507 /* Chipset ID */ | 56 | #define SIO_F71858_ID 0x0507 /* Chipset ID */ |
| 57 | #define SIO_F71862_ID 0x0601 /* Chipset ID */ | 57 | #define SIO_F71862_ID 0x0601 /* Chipset ID */ |
| 58 | #define SIO_F71869_ID 0x0814 /* Chipset ID */ | 58 | #define SIO_F71869_ID 0x0814 /* Chipset ID */ |
| 59 | #define SIO_F71869A_ID 0x1007 /* Chipset ID */ | ||
| 59 | #define SIO_F71882_ID 0x0541 /* Chipset ID */ | 60 | #define SIO_F71882_ID 0x0541 /* Chipset ID */ |
| 60 | #define SIO_F71889_ID 0x0723 /* Chipset ID */ | 61 | #define SIO_F71889_ID 0x0723 /* Chipset ID */ |
| 61 | 62 | ||
| @@ -195,7 +196,7 @@ static inline int superio_enter(int base) | |||
| 195 | return -EBUSY; | 196 | return -EBUSY; |
| 196 | } | 197 | } |
| 197 | 198 | ||
| 198 | /* according to the datasheet the key must be send twice! */ | 199 | /* according to the datasheet the key must be sent twice! */ |
| 199 | outb(SIO_UNLOCK_KEY, base); | 200 | outb(SIO_UNLOCK_KEY, base); |
| 200 | outb(SIO_UNLOCK_KEY, base); | 201 | outb(SIO_UNLOCK_KEY, base); |
| 201 | 202 | ||
| @@ -756,6 +757,7 @@ static int __init f71808e_find(int sioaddr) | |||
| 756 | err = f71862fg_pin_configure(0); /* validate module parameter */ | 757 | err = f71862fg_pin_configure(0); /* validate module parameter */ |
| 757 | break; | 758 | break; |
| 758 | case SIO_F71869_ID: | 759 | case SIO_F71869_ID: |
| 760 | case SIO_F71869A_ID: | ||
| 759 | watchdog.type = f71869; | 761 | watchdog.type = f71869; |
| 760 | break; | 762 | break; |
| 761 | case SIO_F71882_ID: | 763 | case SIO_F71882_ID: |
diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c index 9c2c27c3b424..ceed39f26011 100644 --- a/drivers/watchdog/iTCO_wdt.c +++ b/drivers/watchdog/iTCO_wdt.c | |||
| @@ -47,7 +47,7 @@ | |||
| 47 | 47 | ||
| 48 | /* Module and version information */ | 48 | /* Module and version information */ |
| 49 | #define DRV_NAME "iTCO_wdt" | 49 | #define DRV_NAME "iTCO_wdt" |
| 50 | #define DRV_VERSION "1.07" | 50 | #define DRV_VERSION "1.10" |
| 51 | 51 | ||
| 52 | /* Includes */ | 52 | /* Includes */ |
| 53 | #include <linux/module.h> /* For module specific items */ | 53 | #include <linux/module.h> /* For module specific items */ |
| @@ -88,8 +88,6 @@ | |||
| 88 | #define TCOv2_TMR (TCOBASE + 0x12) /* TCOv2 Timer Initial Value */ | 88 | #define TCOv2_TMR (TCOBASE + 0x12) /* TCOv2 Timer Initial Value */ |
| 89 | 89 | ||
| 90 | /* internal variables */ | 90 | /* internal variables */ |
| 91 | static unsigned long is_active; | ||
| 92 | static char expect_release; | ||
| 93 | static struct { /* this is private data for the iTCO_wdt device */ | 91 | static struct { /* this is private data for the iTCO_wdt device */ |
| 94 | /* TCO version/generation */ | 92 | /* TCO version/generation */ |
| 95 | unsigned int iTCO_version; | 93 | unsigned int iTCO_version; |
| @@ -106,12 +104,12 @@ static struct { /* this is private data for the iTCO_wdt device */ | |||
| 106 | } iTCO_wdt_private; | 104 | } iTCO_wdt_private; |
| 107 | 105 | ||
| 108 | /* module parameters */ | 106 | /* module parameters */ |
| 109 | #define WATCHDOG_HEARTBEAT 30 /* 30 sec default heartbeat */ | 107 | #define WATCHDOG_TIMEOUT 30 /* 30 sec default heartbeat */ |
| 110 | static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */ | 108 | static int heartbeat = WATCHDOG_TIMEOUT; /* in seconds */ |
| 111 | module_param(heartbeat, int, 0); | 109 | module_param(heartbeat, int, 0); |
| 112 | MODULE_PARM_DESC(heartbeat, "Watchdog timeout in seconds. " | 110 | MODULE_PARM_DESC(heartbeat, "Watchdog timeout in seconds. " |
| 113 | "5..76 (TCO v1) or 3..614 (TCO v2), default=" | 111 | "5..76 (TCO v1) or 3..614 (TCO v2), default=" |
| 114 | __MODULE_STRING(WATCHDOG_HEARTBEAT) ")"); | 112 | __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); |
| 115 | 113 | ||
| 116 | static bool nowayout = WATCHDOG_NOWAYOUT; | 114 | static bool nowayout = WATCHDOG_NOWAYOUT; |
| 117 | module_param(nowayout, bool, 0); | 115 | module_param(nowayout, bool, 0); |
| @@ -178,13 +176,13 @@ static int iTCO_wdt_unset_NO_REBOOT_bit(void) | |||
| 178 | return ret; /* returns: 0 = OK, -EIO = Error */ | 176 | return ret; /* returns: 0 = OK, -EIO = Error */ |
| 179 | } | 177 | } |
| 180 | 178 | ||
| 181 | static int iTCO_wdt_start(void) | 179 | static int iTCO_wdt_start(struct watchdog_device *wd_dev) |
| 182 | { | 180 | { |
| 183 | unsigned int val; | 181 | unsigned int val; |
| 184 | 182 | ||
| 185 | spin_lock(&iTCO_wdt_private.io_lock); | 183 | spin_lock(&iTCO_wdt_private.io_lock); |
| 186 | 184 | ||
| 187 | iTCO_vendor_pre_start(iTCO_wdt_private.smi_res, heartbeat); | 185 | iTCO_vendor_pre_start(iTCO_wdt_private.smi_res, wd_dev->timeout); |
| 188 | 186 | ||
| 189 | /* disable chipset's NO_REBOOT bit */ | 187 | /* disable chipset's NO_REBOOT bit */ |
| 190 | if (iTCO_wdt_unset_NO_REBOOT_bit()) { | 188 | if (iTCO_wdt_unset_NO_REBOOT_bit()) { |
| @@ -212,7 +210,7 @@ static int iTCO_wdt_start(void) | |||
| 212 | return 0; | 210 | return 0; |
| 213 | } | 211 | } |
| 214 | 212 | ||
| 215 | static int iTCO_wdt_stop(void) | 213 | static int iTCO_wdt_stop(struct watchdog_device *wd_dev) |
| 216 | { | 214 | { |
| 217 | unsigned int val; | 215 | unsigned int val; |
| 218 | 216 | ||
| @@ -236,11 +234,11 @@ static int iTCO_wdt_stop(void) | |||
| 236 | return 0; | 234 | return 0; |
| 237 | } | 235 | } |
| 238 | 236 | ||
| 239 | static int iTCO_wdt_keepalive(void) | 237 | static int iTCO_wdt_ping(struct watchdog_device *wd_dev) |
| 240 | { | 238 | { |
| 241 | spin_lock(&iTCO_wdt_private.io_lock); | 239 | spin_lock(&iTCO_wdt_private.io_lock); |
| 242 | 240 | ||
| 243 | iTCO_vendor_pre_keepalive(iTCO_wdt_private.smi_res, heartbeat); | 241 | iTCO_vendor_pre_keepalive(iTCO_wdt_private.smi_res, wd_dev->timeout); |
| 244 | 242 | ||
| 245 | /* Reload the timer by writing to the TCO Timer Counter register */ | 243 | /* Reload the timer by writing to the TCO Timer Counter register */ |
| 246 | if (iTCO_wdt_private.iTCO_version == 2) | 244 | if (iTCO_wdt_private.iTCO_version == 2) |
| @@ -257,7 +255,7 @@ static int iTCO_wdt_keepalive(void) | |||
| 257 | return 0; | 255 | return 0; |
| 258 | } | 256 | } |
| 259 | 257 | ||
| 260 | static int iTCO_wdt_set_heartbeat(int t) | 258 | static int iTCO_wdt_set_timeout(struct watchdog_device *wd_dev, unsigned int t) |
| 261 | { | 259 | { |
| 262 | unsigned int val16; | 260 | unsigned int val16; |
| 263 | unsigned char val8; | 261 | unsigned char val8; |
| @@ -304,14 +302,15 @@ static int iTCO_wdt_set_heartbeat(int t) | |||
| 304 | return -EINVAL; | 302 | return -EINVAL; |
| 305 | } | 303 | } |
| 306 | 304 | ||
| 307 | heartbeat = t; | 305 | wd_dev->timeout = t; |
| 308 | return 0; | 306 | return 0; |
| 309 | } | 307 | } |
| 310 | 308 | ||
| 311 | static int iTCO_wdt_get_timeleft(int *time_left) | 309 | static unsigned int iTCO_wdt_get_timeleft(struct watchdog_device *wd_dev) |
| 312 | { | 310 | { |
| 313 | unsigned int val16; | 311 | unsigned int val16; |
| 314 | unsigned char val8; | 312 | unsigned char val8; |
| 313 | unsigned int time_left = 0; | ||
| 315 | 314 | ||
| 316 | /* read the TCO Timer */ | 315 | /* read the TCO Timer */ |
| 317 | if (iTCO_wdt_private.iTCO_version == 2) { | 316 | if (iTCO_wdt_private.iTCO_version == 2) { |
| @@ -320,7 +319,7 @@ static int iTCO_wdt_get_timeleft(int *time_left) | |||
| 320 | val16 &= 0x3ff; | 319 | val16 &= 0x3ff; |
| 321 | spin_unlock(&iTCO_wdt_private.io_lock); | 320 | spin_unlock(&iTCO_wdt_private.io_lock); |
| 322 | 321 | ||
| 323 | *time_left = (val16 * 6) / 10; | 322 | time_left = (val16 * 6) / 10; |
| 324 | } else if (iTCO_wdt_private.iTCO_version == 1) { | 323 | } else if (iTCO_wdt_private.iTCO_version == 1) { |
| 325 | spin_lock(&iTCO_wdt_private.io_lock); | 324 | spin_lock(&iTCO_wdt_private.io_lock); |
| 326 | val8 = inb(TCO_RLD); | 325 | val8 = inb(TCO_RLD); |
| @@ -329,156 +328,35 @@ static int iTCO_wdt_get_timeleft(int *time_left) | |||
| 329 | val8 += (inb(TCOv1_TMR) & 0x3f); | 328 | val8 += (inb(TCOv1_TMR) & 0x3f); |
| 330 | spin_unlock(&iTCO_wdt_private.io_lock); | 329 | spin_unlock(&iTCO_wdt_private.io_lock); |
| 331 | 330 | ||
| 332 | *time_left = (val8 * 6) / 10; | 331 | time_left = (val8 * 6) / 10; |
| 333 | } else | ||
| 334 | return -EINVAL; | ||
| 335 | return 0; | ||
| 336 | } | ||
| 337 | |||
| 338 | /* | ||
| 339 | * /dev/watchdog handling | ||
| 340 | */ | ||
| 341 | |||
| 342 | static int iTCO_wdt_open(struct inode *inode, struct file *file) | ||
| 343 | { | ||
| 344 | /* /dev/watchdog can only be opened once */ | ||
| 345 | if (test_and_set_bit(0, &is_active)) | ||
| 346 | return -EBUSY; | ||
| 347 | |||
| 348 | /* | ||
| 349 | * Reload and activate timer | ||
| 350 | */ | ||
| 351 | iTCO_wdt_start(); | ||
| 352 | return nonseekable_open(inode, file); | ||
| 353 | } | ||
| 354 | |||
| 355 | static int iTCO_wdt_release(struct inode *inode, struct file *file) | ||
| 356 | { | ||
| 357 | /* | ||
| 358 | * Shut off the timer. | ||
| 359 | */ | ||
| 360 | if (expect_release == 42) { | ||
| 361 | iTCO_wdt_stop(); | ||
| 362 | } else { | ||
| 363 | pr_crit("Unexpected close, not stopping watchdog!\n"); | ||
| 364 | iTCO_wdt_keepalive(); | ||
| 365 | } | ||
| 366 | clear_bit(0, &is_active); | ||
| 367 | expect_release = 0; | ||
| 368 | return 0; | ||
| 369 | } | ||
| 370 | |||
| 371 | static ssize_t iTCO_wdt_write(struct file *file, const char __user *data, | ||
| 372 | size_t len, loff_t *ppos) | ||
| 373 | { | ||
| 374 | /* See if we got the magic character 'V' and reload the timer */ | ||
| 375 | if (len) { | ||
| 376 | if (!nowayout) { | ||
| 377 | size_t i; | ||
| 378 | |||
| 379 | /* note: just in case someone wrote the magic | ||
| 380 | character five months ago... */ | ||
| 381 | expect_release = 0; | ||
| 382 | |||
| 383 | /* scan to see whether or not we got the | ||
| 384 | magic character */ | ||
| 385 | for (i = 0; i != len; i++) { | ||
| 386 | char c; | ||
| 387 | if (get_user(c, data + i)) | ||
| 388 | return -EFAULT; | ||
| 389 | if (c == 'V') | ||
| 390 | expect_release = 42; | ||
| 391 | } | ||
| 392 | } | ||
| 393 | |||
| 394 | /* someone wrote to us, we should reload the timer */ | ||
| 395 | iTCO_wdt_keepalive(); | ||
| 396 | } | ||
| 397 | return len; | ||
| 398 | } | ||
| 399 | |||
| 400 | static long iTCO_wdt_ioctl(struct file *file, unsigned int cmd, | ||
| 401 | unsigned long arg) | ||
| 402 | { | ||
| 403 | int new_options, retval = -EINVAL; | ||
| 404 | int new_heartbeat; | ||
| 405 | void __user *argp = (void __user *)arg; | ||
| 406 | int __user *p = argp; | ||
| 407 | static const struct watchdog_info ident = { | ||
| 408 | .options = WDIOF_SETTIMEOUT | | ||
| 409 | WDIOF_KEEPALIVEPING | | ||
| 410 | WDIOF_MAGICCLOSE, | ||
| 411 | .firmware_version = 0, | ||
| 412 | .identity = DRV_NAME, | ||
| 413 | }; | ||
| 414 | |||
| 415 | switch (cmd) { | ||
| 416 | case WDIOC_GETSUPPORT: | ||
| 417 | return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; | ||
| 418 | case WDIOC_GETSTATUS: | ||
| 419 | case WDIOC_GETBOOTSTATUS: | ||
| 420 | return put_user(0, p); | ||
| 421 | |||
| 422 | case WDIOC_SETOPTIONS: | ||
| 423 | { | ||
| 424 | if (get_user(new_options, p)) | ||
| 425 | return -EFAULT; | ||
| 426 | |||
| 427 | if (new_options & WDIOS_DISABLECARD) { | ||
| 428 | iTCO_wdt_stop(); | ||
| 429 | retval = 0; | ||
| 430 | } | ||
| 431 | if (new_options & WDIOS_ENABLECARD) { | ||
| 432 | iTCO_wdt_keepalive(); | ||
| 433 | iTCO_wdt_start(); | ||
| 434 | retval = 0; | ||
| 435 | } | ||
| 436 | return retval; | ||
| 437 | } | ||
| 438 | case WDIOC_KEEPALIVE: | ||
| 439 | iTCO_wdt_keepalive(); | ||
| 440 | return 0; | ||
| 441 | |||
| 442 | case WDIOC_SETTIMEOUT: | ||
| 443 | { | ||
| 444 | if (get_user(new_heartbeat, p)) | ||
| 445 | return -EFAULT; | ||
| 446 | if (iTCO_wdt_set_heartbeat(new_heartbeat)) | ||
| 447 | return -EINVAL; | ||
| 448 | iTCO_wdt_keepalive(); | ||
| 449 | /* Fall */ | ||
| 450 | } | ||
| 451 | case WDIOC_GETTIMEOUT: | ||
| 452 | return put_user(heartbeat, p); | ||
| 453 | case WDIOC_GETTIMELEFT: | ||
| 454 | { | ||
| 455 | int time_left; | ||
| 456 | if (iTCO_wdt_get_timeleft(&time_left)) | ||
| 457 | return -EINVAL; | ||
| 458 | return put_user(time_left, p); | ||
| 459 | } | ||
| 460 | default: | ||
| 461 | return -ENOTTY; | ||
| 462 | } | 332 | } |
| 333 | return time_left; | ||
| 463 | } | 334 | } |
| 464 | 335 | ||
| 465 | /* | 336 | /* |
| 466 | * Kernel Interfaces | 337 | * Kernel Interfaces |
| 467 | */ | 338 | */ |
| 468 | 339 | ||
| 469 | static const struct file_operations iTCO_wdt_fops = { | 340 | static const struct watchdog_info ident = { |
| 341 | .options = WDIOF_SETTIMEOUT | | ||
| 342 | WDIOF_KEEPALIVEPING | | ||
| 343 | WDIOF_MAGICCLOSE, | ||
| 344 | .firmware_version = 0, | ||
| 345 | .identity = DRV_NAME, | ||
| 346 | }; | ||
| 347 | |||
| 348 | static const struct watchdog_ops iTCO_wdt_ops = { | ||
| 470 | .owner = THIS_MODULE, | 349 | .owner = THIS_MODULE, |
| 471 | .llseek = no_llseek, | 350 | .start = iTCO_wdt_start, |
| 472 | .write = iTCO_wdt_write, | 351 | .stop = iTCO_wdt_stop, |
| 473 | .unlocked_ioctl = iTCO_wdt_ioctl, | 352 | .ping = iTCO_wdt_ping, |
| 474 | .open = iTCO_wdt_open, | 353 | .set_timeout = iTCO_wdt_set_timeout, |
| 475 | .release = iTCO_wdt_release, | 354 | .get_timeleft = iTCO_wdt_get_timeleft, |
| 476 | }; | 355 | }; |
| 477 | 356 | ||
| 478 | static struct miscdevice iTCO_wdt_miscdev = { | 357 | static struct watchdog_device iTCO_wdt_watchdog_dev = { |
| 479 | .minor = WATCHDOG_MINOR, | 358 | .info = &ident, |
| 480 | .name = "watchdog", | 359 | .ops = &iTCO_wdt_ops, |
| 481 | .fops = &iTCO_wdt_fops, | ||
| 482 | }; | 360 | }; |
| 483 | 361 | ||
| 484 | /* | 362 | /* |
| @@ -489,10 +367,10 @@ static void __devexit iTCO_wdt_cleanup(void) | |||
| 489 | { | 367 | { |
| 490 | /* Stop the timer before we leave */ | 368 | /* Stop the timer before we leave */ |
| 491 | if (!nowayout) | 369 | if (!nowayout) |
| 492 | iTCO_wdt_stop(); | 370 | iTCO_wdt_stop(&iTCO_wdt_watchdog_dev); |
| 493 | 371 | ||
| 494 | /* Deregister */ | 372 | /* Deregister */ |
| 495 | misc_deregister(&iTCO_wdt_miscdev); | 373 | watchdog_unregister_device(&iTCO_wdt_watchdog_dev); |
| 496 | 374 | ||
| 497 | /* release resources */ | 375 | /* release resources */ |
| 498 | release_region(iTCO_wdt_private.tco_res->start, | 376 | release_region(iTCO_wdt_private.tco_res->start, |
| @@ -605,20 +483,25 @@ static int __devinit iTCO_wdt_probe(struct platform_device *dev) | |||
| 605 | outw(0x0002, TCO2_STS); /* Clear SECOND_TO_STS bit */ | 483 | outw(0x0002, TCO2_STS); /* Clear SECOND_TO_STS bit */ |
| 606 | outw(0x0004, TCO2_STS); /* Clear BOOT_STS bit */ | 484 | outw(0x0004, TCO2_STS); /* Clear BOOT_STS bit */ |
| 607 | 485 | ||
| 486 | iTCO_wdt_watchdog_dev.bootstatus = 0; | ||
| 487 | iTCO_wdt_watchdog_dev.timeout = WATCHDOG_TIMEOUT; | ||
| 488 | watchdog_set_nowayout(&iTCO_wdt_watchdog_dev, nowayout); | ||
| 489 | iTCO_wdt_watchdog_dev.parent = dev->dev.parent; | ||
| 490 | |||
| 608 | /* Make sure the watchdog is not running */ | 491 | /* Make sure the watchdog is not running */ |
| 609 | iTCO_wdt_stop(); | 492 | iTCO_wdt_stop(&iTCO_wdt_watchdog_dev); |
| 610 | 493 | ||
| 611 | /* Check that the heartbeat value is within it's range; | 494 | /* Check that the heartbeat value is within it's range; |
| 612 | if not reset to the default */ | 495 | if not reset to the default */ |
| 613 | if (iTCO_wdt_set_heartbeat(heartbeat)) { | 496 | if (iTCO_wdt_set_timeout(&iTCO_wdt_watchdog_dev, heartbeat)) { |
| 614 | iTCO_wdt_set_heartbeat(WATCHDOG_HEARTBEAT); | 497 | iTCO_wdt_set_timeout(&iTCO_wdt_watchdog_dev, WATCHDOG_TIMEOUT); |
| 615 | pr_info("timeout value out of range, using %d\n", heartbeat); | 498 | pr_info("timeout value out of range, using %d\n", |
| 499 | WATCHDOG_TIMEOUT); | ||
| 616 | } | 500 | } |
| 617 | 501 | ||
| 618 | ret = misc_register(&iTCO_wdt_miscdev); | 502 | ret = watchdog_register_device(&iTCO_wdt_watchdog_dev); |
| 619 | if (ret != 0) { | 503 | if (ret != 0) { |
| 620 | pr_err("cannot register miscdev on minor=%d (err=%d)\n", | 504 | pr_err("cannot register watchdog device (err=%d)\n", ret); |
| 621 | WATCHDOG_MINOR, ret); | ||
| 622 | goto unreg_tco; | 505 | goto unreg_tco; |
| 623 | } | 506 | } |
| 624 | 507 | ||
| @@ -659,7 +542,7 @@ static int __devexit iTCO_wdt_remove(struct platform_device *dev) | |||
| 659 | 542 | ||
| 660 | static void iTCO_wdt_shutdown(struct platform_device *dev) | 543 | static void iTCO_wdt_shutdown(struct platform_device *dev) |
| 661 | { | 544 | { |
| 662 | iTCO_wdt_stop(); | 545 | iTCO_wdt_stop(NULL); |
| 663 | } | 546 | } |
| 664 | 547 | ||
| 665 | static struct platform_driver iTCO_wdt_driver = { | 548 | static struct platform_driver iTCO_wdt_driver = { |
diff --git a/drivers/watchdog/ie6xx_wdt.c b/drivers/watchdog/ie6xx_wdt.c index 5f0d776f902c..8f541b940053 100644 --- a/drivers/watchdog/ie6xx_wdt.c +++ b/drivers/watchdog/ie6xx_wdt.c | |||
| @@ -232,7 +232,7 @@ static void __devinit ie6xx_wdt_debugfs_init(void) | |||
| 232 | S_IFREG | S_IRUGO, NULL, NULL, &ie6xx_wdt_dbg_operations); | 232 | S_IFREG | S_IRUGO, NULL, NULL, &ie6xx_wdt_dbg_operations); |
| 233 | } | 233 | } |
| 234 | 234 | ||
| 235 | static void __devexit ie6xx_wdt_debugfs_exit(void) | 235 | static void ie6xx_wdt_debugfs_exit(void) |
| 236 | { | 236 | { |
| 237 | debugfs_remove(ie6xx_wdt_data.debugfs); | 237 | debugfs_remove(ie6xx_wdt_data.debugfs); |
| 238 | } | 238 | } |
| @@ -242,7 +242,7 @@ static void __devinit ie6xx_wdt_debugfs_init(void) | |||
| 242 | { | 242 | { |
| 243 | } | 243 | } |
| 244 | 244 | ||
| 245 | static void __devexit ie6xx_wdt_debugfs_exit(void) | 245 | static void ie6xx_wdt_debugfs_exit(void) |
| 246 | { | 246 | { |
| 247 | } | 247 | } |
| 248 | #endif | 248 | #endif |
diff --git a/drivers/watchdog/of_xilinx_wdt.c b/drivers/watchdog/of_xilinx_wdt.c index 55d2f66dbeae..294fb4e00521 100644 --- a/drivers/watchdog/of_xilinx_wdt.c +++ b/drivers/watchdog/of_xilinx_wdt.c | |||
| @@ -297,7 +297,7 @@ static int __devinit xwdt_probe(struct platform_device *pdev) | |||
| 297 | 297 | ||
| 298 | no_timeout = 0; | 298 | no_timeout = 0; |
| 299 | 299 | ||
| 300 | pfreq = (u32 *)of_get_property(pdev->dev.of_node->parent, | 300 | pfreq = (u32 *)of_get_property(pdev->dev.of_node, |
| 301 | "clock-frequency", NULL); | 301 | "clock-frequency", NULL); |
| 302 | 302 | ||
| 303 | if (pfreq == NULL) { | 303 | if (pfreq == NULL) { |
diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c index 02ebfd5f0e65..fceec4f4eb7e 100644 --- a/drivers/watchdog/omap_wdt.c +++ b/drivers/watchdog/omap_wdt.c | |||
| @@ -126,8 +126,6 @@ static void omap_wdt_set_timeout(struct omap_wdt_dev *wdev) | |||
| 126 | u32 pre_margin = GET_WLDR_VAL(timer_margin); | 126 | u32 pre_margin = GET_WLDR_VAL(timer_margin); |
| 127 | void __iomem *base = wdev->base; | 127 | void __iomem *base = wdev->base; |
| 128 | 128 | ||
| 129 | pm_runtime_get_sync(wdev->dev); | ||
| 130 | |||
| 131 | /* just count up at 32 KHz */ | 129 | /* just count up at 32 KHz */ |
| 132 | while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x04) | 130 | while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x04) |
| 133 | cpu_relax(); | 131 | cpu_relax(); |
| @@ -135,8 +133,6 @@ static void omap_wdt_set_timeout(struct omap_wdt_dev *wdev) | |||
| 135 | __raw_writel(pre_margin, base + OMAP_WATCHDOG_LDR); | 133 | __raw_writel(pre_margin, base + OMAP_WATCHDOG_LDR); |
| 136 | while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x04) | 134 | while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x04) |
| 137 | cpu_relax(); | 135 | cpu_relax(); |
| 138 | |||
| 139 | pm_runtime_put_sync(wdev->dev); | ||
| 140 | } | 136 | } |
| 141 | 137 | ||
| 142 | /* | 138 | /* |
| @@ -166,8 +162,6 @@ static int omap_wdt_open(struct inode *inode, struct file *file) | |||
| 166 | omap_wdt_ping(wdev); /* trigger loading of new timeout value */ | 162 | omap_wdt_ping(wdev); /* trigger loading of new timeout value */ |
| 167 | omap_wdt_enable(wdev); | 163 | omap_wdt_enable(wdev); |
| 168 | 164 | ||
| 169 | pm_runtime_put_sync(wdev->dev); | ||
| 170 | |||
| 171 | return nonseekable_open(inode, file); | 165 | return nonseekable_open(inode, file); |
| 172 | } | 166 | } |
| 173 | 167 | ||
| @@ -179,8 +173,6 @@ static int omap_wdt_release(struct inode *inode, struct file *file) | |||
| 179 | * Shut off the timer unless NOWAYOUT is defined. | 173 | * Shut off the timer unless NOWAYOUT is defined. |
| 180 | */ | 174 | */ |
| 181 | #ifndef CONFIG_WATCHDOG_NOWAYOUT | 175 | #ifndef CONFIG_WATCHDOG_NOWAYOUT |
| 182 | pm_runtime_get_sync(wdev->dev); | ||
| 183 | |||
| 184 | omap_wdt_disable(wdev); | 176 | omap_wdt_disable(wdev); |
| 185 | 177 | ||
| 186 | pm_runtime_put_sync(wdev->dev); | 178 | pm_runtime_put_sync(wdev->dev); |
| @@ -199,11 +191,9 @@ static ssize_t omap_wdt_write(struct file *file, const char __user *data, | |||
| 199 | 191 | ||
| 200 | /* Refresh LOAD_TIME. */ | 192 | /* Refresh LOAD_TIME. */ |
| 201 | if (len) { | 193 | if (len) { |
| 202 | pm_runtime_get_sync(wdev->dev); | ||
| 203 | spin_lock(&wdt_lock); | 194 | spin_lock(&wdt_lock); |
| 204 | omap_wdt_ping(wdev); | 195 | omap_wdt_ping(wdev); |
| 205 | spin_unlock(&wdt_lock); | 196 | spin_unlock(&wdt_lock); |
| 206 | pm_runtime_put_sync(wdev->dev); | ||
| 207 | } | 197 | } |
| 208 | return len; | 198 | return len; |
| 209 | } | 199 | } |
| @@ -236,18 +226,15 @@ static long omap_wdt_ioctl(struct file *file, unsigned int cmd, | |||
| 236 | (int __user *)arg); | 226 | (int __user *)arg); |
| 237 | return put_user(0, (int __user *)arg); | 227 | return put_user(0, (int __user *)arg); |
| 238 | case WDIOC_KEEPALIVE: | 228 | case WDIOC_KEEPALIVE: |
| 239 | pm_runtime_get_sync(wdev->dev); | ||
| 240 | spin_lock(&wdt_lock); | 229 | spin_lock(&wdt_lock); |
| 241 | omap_wdt_ping(wdev); | 230 | omap_wdt_ping(wdev); |
| 242 | spin_unlock(&wdt_lock); | 231 | spin_unlock(&wdt_lock); |
| 243 | pm_runtime_put_sync(wdev->dev); | ||
| 244 | return 0; | 232 | return 0; |
| 245 | case WDIOC_SETTIMEOUT: | 233 | case WDIOC_SETTIMEOUT: |
| 246 | if (get_user(new_margin, (int __user *)arg)) | 234 | if (get_user(new_margin, (int __user *)arg)) |
| 247 | return -EFAULT; | 235 | return -EFAULT; |
| 248 | omap_wdt_adjust_timeout(new_margin); | 236 | omap_wdt_adjust_timeout(new_margin); |
| 249 | 237 | ||
| 250 | pm_runtime_get_sync(wdev->dev); | ||
| 251 | spin_lock(&wdt_lock); | 238 | spin_lock(&wdt_lock); |
| 252 | omap_wdt_disable(wdev); | 239 | omap_wdt_disable(wdev); |
| 253 | omap_wdt_set_timeout(wdev); | 240 | omap_wdt_set_timeout(wdev); |
| @@ -255,7 +242,6 @@ static long omap_wdt_ioctl(struct file *file, unsigned int cmd, | |||
| 255 | 242 | ||
| 256 | omap_wdt_ping(wdev); | 243 | omap_wdt_ping(wdev); |
| 257 | spin_unlock(&wdt_lock); | 244 | spin_unlock(&wdt_lock); |
| 258 | pm_runtime_put_sync(wdev->dev); | ||
| 259 | /* Fall */ | 245 | /* Fall */ |
| 260 | case WDIOC_GETTIMEOUT: | 246 | case WDIOC_GETTIMEOUT: |
| 261 | return put_user(timer_margin, (int __user *)arg); | 247 | return put_user(timer_margin, (int __user *)arg); |
| @@ -363,7 +349,6 @@ static void omap_wdt_shutdown(struct platform_device *pdev) | |||
| 363 | struct omap_wdt_dev *wdev = platform_get_drvdata(pdev); | 349 | struct omap_wdt_dev *wdev = platform_get_drvdata(pdev); |
| 364 | 350 | ||
| 365 | if (wdev->omap_wdt_users) { | 351 | if (wdev->omap_wdt_users) { |
| 366 | pm_runtime_get_sync(wdev->dev); | ||
| 367 | omap_wdt_disable(wdev); | 352 | omap_wdt_disable(wdev); |
| 368 | pm_runtime_put_sync(wdev->dev); | 353 | pm_runtime_put_sync(wdev->dev); |
| 369 | } | 354 | } |
| @@ -403,7 +388,6 @@ static int omap_wdt_suspend(struct platform_device *pdev, pm_message_t state) | |||
| 403 | struct omap_wdt_dev *wdev = platform_get_drvdata(pdev); | 388 | struct omap_wdt_dev *wdev = platform_get_drvdata(pdev); |
| 404 | 389 | ||
| 405 | if (wdev->omap_wdt_users) { | 390 | if (wdev->omap_wdt_users) { |
| 406 | pm_runtime_get_sync(wdev->dev); | ||
| 407 | omap_wdt_disable(wdev); | 391 | omap_wdt_disable(wdev); |
| 408 | pm_runtime_put_sync(wdev->dev); | 392 | pm_runtime_put_sync(wdev->dev); |
| 409 | } | 393 | } |
| @@ -419,7 +403,6 @@ static int omap_wdt_resume(struct platform_device *pdev) | |||
| 419 | pm_runtime_get_sync(wdev->dev); | 403 | pm_runtime_get_sync(wdev->dev); |
| 420 | omap_wdt_enable(wdev); | 404 | omap_wdt_enable(wdev); |
| 421 | omap_wdt_ping(wdev); | 405 | omap_wdt_ping(wdev); |
| 422 | pm_runtime_put_sync(wdev->dev); | ||
| 423 | } | 406 | } |
| 424 | 407 | ||
| 425 | return 0; | 408 | return 0; |
diff --git a/drivers/watchdog/orion_wdt.c b/drivers/watchdog/orion_wdt.c index 0f5736949c61..a73bea4aa1ba 100644 --- a/drivers/watchdog/orion_wdt.c +++ b/drivers/watchdog/orion_wdt.c | |||
| @@ -16,22 +16,21 @@ | |||
| 16 | #include <linux/moduleparam.h> | 16 | #include <linux/moduleparam.h> |
| 17 | #include <linux/types.h> | 17 | #include <linux/types.h> |
| 18 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
| 19 | #include <linux/fs.h> | ||
| 20 | #include <linux/miscdevice.h> | 19 | #include <linux/miscdevice.h> |
| 21 | #include <linux/platform_device.h> | 20 | #include <linux/platform_device.h> |
| 22 | #include <linux/watchdog.h> | 21 | #include <linux/watchdog.h> |
| 23 | #include <linux/init.h> | 22 | #include <linux/init.h> |
| 24 | #include <linux/uaccess.h> | ||
| 25 | #include <linux/io.h> | 23 | #include <linux/io.h> |
| 26 | #include <linux/spinlock.h> | 24 | #include <linux/spinlock.h> |
| 27 | #include <linux/clk.h> | 25 | #include <linux/clk.h> |
| 26 | #include <linux/err.h> | ||
| 28 | #include <mach/bridge-regs.h> | 27 | #include <mach/bridge-regs.h> |
| 29 | 28 | ||
| 30 | /* | 29 | /* |
| 31 | * Watchdog timer block registers. | 30 | * Watchdog timer block registers. |
| 32 | */ | 31 | */ |
| 33 | #define TIMER_CTRL 0x0000 | 32 | #define TIMER_CTRL 0x0000 |
| 34 | #define WDT_EN 0x0010 | 33 | #define WDT_EN 0x0010 |
| 35 | #define WDT_VAL 0x0024 | 34 | #define WDT_VAL 0x0024 |
| 36 | 35 | ||
| 37 | #define WDT_MAX_CYCLE_COUNT 0xffffffff | 36 | #define WDT_MAX_CYCLE_COUNT 0xffffffff |
| @@ -44,27 +43,27 @@ static unsigned int wdt_max_duration; /* (seconds) */ | |||
| 44 | static struct clk *clk; | 43 | static struct clk *clk; |
| 45 | static unsigned int wdt_tclk; | 44 | static unsigned int wdt_tclk; |
| 46 | static void __iomem *wdt_reg; | 45 | static void __iomem *wdt_reg; |
| 47 | static unsigned long wdt_status; | ||
| 48 | static DEFINE_SPINLOCK(wdt_lock); | 46 | static DEFINE_SPINLOCK(wdt_lock); |
| 49 | 47 | ||
| 50 | static void orion_wdt_ping(void) | 48 | static int orion_wdt_ping(struct watchdog_device *wdt_dev) |
| 51 | { | 49 | { |
| 52 | spin_lock(&wdt_lock); | 50 | spin_lock(&wdt_lock); |
| 53 | 51 | ||
| 54 | /* Reload watchdog duration */ | 52 | /* Reload watchdog duration */ |
| 55 | writel(wdt_tclk * heartbeat, wdt_reg + WDT_VAL); | 53 | writel(wdt_tclk * wdt_dev->timeout, wdt_reg + WDT_VAL); |
| 56 | 54 | ||
| 57 | spin_unlock(&wdt_lock); | 55 | spin_unlock(&wdt_lock); |
| 56 | return 0; | ||
| 58 | } | 57 | } |
| 59 | 58 | ||
| 60 | static void orion_wdt_enable(void) | 59 | static int orion_wdt_start(struct watchdog_device *wdt_dev) |
| 61 | { | 60 | { |
| 62 | u32 reg; | 61 | u32 reg; |
| 63 | 62 | ||
| 64 | spin_lock(&wdt_lock); | 63 | spin_lock(&wdt_lock); |
| 65 | 64 | ||
| 66 | /* Set watchdog duration */ | 65 | /* Set watchdog duration */ |
| 67 | writel(wdt_tclk * heartbeat, wdt_reg + WDT_VAL); | 66 | writel(wdt_tclk * wdt_dev->timeout, wdt_reg + WDT_VAL); |
| 68 | 67 | ||
| 69 | /* Clear watchdog timer interrupt */ | 68 | /* Clear watchdog timer interrupt */ |
| 70 | reg = readl(BRIDGE_CAUSE); | 69 | reg = readl(BRIDGE_CAUSE); |
| @@ -82,9 +81,10 @@ static void orion_wdt_enable(void) | |||
| 82 | writel(reg, RSTOUTn_MASK); | 81 | writel(reg, RSTOUTn_MASK); |
| 83 | 82 | ||
| 84 | spin_unlock(&wdt_lock); | 83 | spin_unlock(&wdt_lock); |
| 84 | return 0; | ||
| 85 | } | 85 | } |
| 86 | 86 | ||
| 87 | static void orion_wdt_disable(void) | 87 | static int orion_wdt_stop(struct watchdog_device *wdt_dev) |
| 88 | { | 88 | { |
| 89 | u32 reg; | 89 | u32 reg; |
| 90 | 90 | ||
| @@ -101,139 +101,44 @@ static void orion_wdt_disable(void) | |||
| 101 | writel(reg, wdt_reg + TIMER_CTRL); | 101 | writel(reg, wdt_reg + TIMER_CTRL); |
| 102 | 102 | ||
| 103 | spin_unlock(&wdt_lock); | 103 | spin_unlock(&wdt_lock); |
| 104 | return 0; | ||
| 104 | } | 105 | } |
| 105 | 106 | ||
| 106 | static int orion_wdt_get_timeleft(int *time_left) | 107 | static unsigned int orion_wdt_get_timeleft(struct watchdog_device *wdt_dev) |
| 107 | { | 108 | { |
| 109 | unsigned int time_left; | ||
| 110 | |||
| 108 | spin_lock(&wdt_lock); | 111 | spin_lock(&wdt_lock); |
| 109 | *time_left = readl(wdt_reg + WDT_VAL) / wdt_tclk; | 112 | time_left = readl(wdt_reg + WDT_VAL) / wdt_tclk; |
| 110 | spin_unlock(&wdt_lock); | 113 | spin_unlock(&wdt_lock); |
| 111 | return 0; | ||
| 112 | } | ||
| 113 | 114 | ||
| 114 | static int orion_wdt_open(struct inode *inode, struct file *file) | 115 | return time_left; |
| 115 | { | ||
| 116 | if (test_and_set_bit(WDT_IN_USE, &wdt_status)) | ||
| 117 | return -EBUSY; | ||
| 118 | clear_bit(WDT_OK_TO_CLOSE, &wdt_status); | ||
| 119 | orion_wdt_enable(); | ||
| 120 | return nonseekable_open(inode, file); | ||
| 121 | } | 116 | } |
| 122 | 117 | ||
| 123 | static ssize_t orion_wdt_write(struct file *file, const char *data, | 118 | static int orion_wdt_set_timeout(struct watchdog_device *wdt_dev, |
| 124 | size_t len, loff_t *ppos) | 119 | unsigned int timeout) |
| 125 | { | 120 | { |
| 126 | if (len) { | 121 | wdt_dev->timeout = timeout; |
| 127 | if (!nowayout) { | ||
| 128 | size_t i; | ||
| 129 | |||
| 130 | clear_bit(WDT_OK_TO_CLOSE, &wdt_status); | ||
| 131 | for (i = 0; i != len; i++) { | ||
| 132 | char c; | ||
| 133 | |||
| 134 | if (get_user(c, data + i)) | ||
| 135 | return -EFAULT; | ||
| 136 | if (c == 'V') | ||
| 137 | set_bit(WDT_OK_TO_CLOSE, &wdt_status); | ||
| 138 | } | ||
| 139 | } | ||
| 140 | orion_wdt_ping(); | ||
| 141 | } | ||
| 142 | return len; | ||
| 143 | } | ||
| 144 | |||
| 145 | static int orion_wdt_settimeout(int new_time) | ||
| 146 | { | ||
| 147 | if ((new_time <= 0) || (new_time > wdt_max_duration)) | ||
| 148 | return -EINVAL; | ||
| 149 | |||
| 150 | /* Set new watchdog time to be used when | ||
| 151 | * orion_wdt_enable() or orion_wdt_ping() is called. */ | ||
| 152 | heartbeat = new_time; | ||
| 153 | return 0; | 122 | return 0; |
| 154 | } | 123 | } |
| 155 | 124 | ||
| 156 | static const struct watchdog_info ident = { | 125 | static const struct watchdog_info orion_wdt_info = { |
| 157 | .options = WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT | | 126 | .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, |
| 158 | WDIOF_KEEPALIVEPING, | 127 | .identity = "Orion Watchdog", |
| 159 | .identity = "Orion Watchdog", | ||
| 160 | }; | 128 | }; |
| 161 | 129 | ||
| 162 | static long orion_wdt_ioctl(struct file *file, unsigned int cmd, | 130 | static const struct watchdog_ops orion_wdt_ops = { |
| 163 | unsigned long arg) | 131 | .owner = THIS_MODULE, |
| 164 | { | 132 | .start = orion_wdt_start, |
| 165 | int ret = -ENOTTY; | 133 | .stop = orion_wdt_stop, |
| 166 | int time; | 134 | .ping = orion_wdt_ping, |
| 167 | 135 | .set_timeout = orion_wdt_set_timeout, | |
| 168 | switch (cmd) { | 136 | .get_timeleft = orion_wdt_get_timeleft, |
| 169 | case WDIOC_GETSUPPORT: | ||
| 170 | ret = copy_to_user((struct watchdog_info *)arg, &ident, | ||
| 171 | sizeof(ident)) ? -EFAULT : 0; | ||
| 172 | break; | ||
| 173 | |||
| 174 | case WDIOC_GETSTATUS: | ||
| 175 | case WDIOC_GETBOOTSTATUS: | ||
| 176 | ret = put_user(0, (int *)arg); | ||
| 177 | break; | ||
| 178 | |||
| 179 | case WDIOC_KEEPALIVE: | ||
| 180 | orion_wdt_ping(); | ||
| 181 | ret = 0; | ||
| 182 | break; | ||
| 183 | |||
| 184 | case WDIOC_SETTIMEOUT: | ||
| 185 | ret = get_user(time, (int *)arg); | ||
| 186 | if (ret) | ||
| 187 | break; | ||
| 188 | |||
| 189 | if (orion_wdt_settimeout(time)) { | ||
| 190 | ret = -EINVAL; | ||
| 191 | break; | ||
| 192 | } | ||
| 193 | orion_wdt_ping(); | ||
| 194 | /* Fall through */ | ||
| 195 | |||
| 196 | case WDIOC_GETTIMEOUT: | ||
| 197 | ret = put_user(heartbeat, (int *)arg); | ||
| 198 | break; | ||
| 199 | |||
| 200 | case WDIOC_GETTIMELEFT: | ||
| 201 | if (orion_wdt_get_timeleft(&time)) { | ||
| 202 | ret = -EINVAL; | ||
| 203 | break; | ||
| 204 | } | ||
| 205 | ret = put_user(time, (int *)arg); | ||
| 206 | break; | ||
| 207 | } | ||
| 208 | return ret; | ||
| 209 | } | ||
| 210 | |||
| 211 | static int orion_wdt_release(struct inode *inode, struct file *file) | ||
| 212 | { | ||
| 213 | if (test_bit(WDT_OK_TO_CLOSE, &wdt_status)) | ||
| 214 | orion_wdt_disable(); | ||
| 215 | else | ||
| 216 | pr_crit("Device closed unexpectedly - timer will not stop\n"); | ||
| 217 | clear_bit(WDT_IN_USE, &wdt_status); | ||
| 218 | clear_bit(WDT_OK_TO_CLOSE, &wdt_status); | ||
| 219 | |||
| 220 | return 0; | ||
| 221 | } | ||
| 222 | |||
| 223 | |||
| 224 | static const struct file_operations orion_wdt_fops = { | ||
| 225 | .owner = THIS_MODULE, | ||
| 226 | .llseek = no_llseek, | ||
| 227 | .write = orion_wdt_write, | ||
| 228 | .unlocked_ioctl = orion_wdt_ioctl, | ||
| 229 | .open = orion_wdt_open, | ||
| 230 | .release = orion_wdt_release, | ||
| 231 | }; | 137 | }; |
| 232 | 138 | ||
| 233 | static struct miscdevice orion_wdt_miscdev = { | 139 | static struct watchdog_device orion_wdt = { |
| 234 | .minor = WATCHDOG_MINOR, | 140 | .info = &orion_wdt_info, |
| 235 | .name = "watchdog", | 141 | .ops = &orion_wdt_ops, |
| 236 | .fops = &orion_wdt_fops, | ||
| 237 | }; | 142 | }; |
| 238 | 143 | ||
| 239 | static int __devinit orion_wdt_probe(struct platform_device *pdev) | 144 | static int __devinit orion_wdt_probe(struct platform_device *pdev) |
| @@ -241,29 +146,34 @@ static int __devinit orion_wdt_probe(struct platform_device *pdev) | |||
| 241 | struct resource *res; | 146 | struct resource *res; |
| 242 | int ret; | 147 | int ret; |
| 243 | 148 | ||
| 244 | clk = clk_get(&pdev->dev, NULL); | 149 | clk = devm_clk_get(&pdev->dev, NULL); |
| 245 | if (IS_ERR(clk)) { | 150 | if (IS_ERR(clk)) { |
| 246 | printk(KERN_ERR "Orion Watchdog missing clock\n"); | 151 | dev_err(&pdev->dev, "Orion Watchdog missing clock\n"); |
| 247 | return -ENODEV; | 152 | return -ENODEV; |
| 248 | } | 153 | } |
| 249 | clk_prepare_enable(clk); | 154 | clk_prepare_enable(clk); |
| 250 | wdt_tclk = clk_get_rate(clk); | 155 | wdt_tclk = clk_get_rate(clk); |
| 251 | 156 | ||
| 252 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 157 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 253 | 158 | wdt_reg = devm_ioremap(&pdev->dev, res->start, resource_size(res)); | |
| 254 | wdt_reg = ioremap(res->start, resource_size(res)); | 159 | if (!wdt_reg) |
| 255 | 160 | return -ENOMEM; | |
| 256 | if (orion_wdt_miscdev.parent) | ||
| 257 | return -EBUSY; | ||
| 258 | orion_wdt_miscdev.parent = &pdev->dev; | ||
| 259 | 161 | ||
| 260 | wdt_max_duration = WDT_MAX_CYCLE_COUNT / wdt_tclk; | 162 | wdt_max_duration = WDT_MAX_CYCLE_COUNT / wdt_tclk; |
| 261 | if (orion_wdt_settimeout(heartbeat)) | 163 | |
| 164 | if ((heartbeat < 1) || (heartbeat > wdt_max_duration)) | ||
| 262 | heartbeat = wdt_max_duration; | 165 | heartbeat = wdt_max_duration; |
| 263 | 166 | ||
| 264 | ret = misc_register(&orion_wdt_miscdev); | 167 | orion_wdt.timeout = heartbeat; |
| 265 | if (ret) | 168 | orion_wdt.min_timeout = 1; |
| 169 | orion_wdt.max_timeout = wdt_max_duration; | ||
| 170 | |||
| 171 | watchdog_set_nowayout(&orion_wdt, nowayout); | ||
| 172 | ret = watchdog_register_device(&orion_wdt); | ||
| 173 | if (ret) { | ||
| 174 | clk_disable_unprepare(clk); | ||
| 266 | return ret; | 175 | return ret; |
| 176 | } | ||
| 267 | 177 | ||
| 268 | pr_info("Initial timeout %d sec%s\n", | 178 | pr_info("Initial timeout %d sec%s\n", |
| 269 | heartbeat, nowayout ? ", nowayout" : ""); | 179 | heartbeat, nowayout ? ", nowayout" : ""); |
| @@ -272,27 +182,14 @@ static int __devinit orion_wdt_probe(struct platform_device *pdev) | |||
| 272 | 182 | ||
| 273 | static int __devexit orion_wdt_remove(struct platform_device *pdev) | 183 | static int __devexit orion_wdt_remove(struct platform_device *pdev) |
| 274 | { | 184 | { |
| 275 | int ret; | 185 | watchdog_unregister_device(&orion_wdt); |
| 276 | |||
| 277 | if (test_bit(WDT_IN_USE, &wdt_status)) { | ||
| 278 | orion_wdt_disable(); | ||
| 279 | clear_bit(WDT_IN_USE, &wdt_status); | ||
| 280 | } | ||
| 281 | |||
| 282 | ret = misc_deregister(&orion_wdt_miscdev); | ||
| 283 | if (!ret) | ||
| 284 | orion_wdt_miscdev.parent = NULL; | ||
| 285 | |||
| 286 | clk_disable_unprepare(clk); | 186 | clk_disable_unprepare(clk); |
| 287 | clk_put(clk); | 187 | return 0; |
| 288 | |||
| 289 | return ret; | ||
| 290 | } | 188 | } |
| 291 | 189 | ||
| 292 | static void orion_wdt_shutdown(struct platform_device *pdev) | 190 | static void orion_wdt_shutdown(struct platform_device *pdev) |
| 293 | { | 191 | { |
| 294 | if (test_bit(WDT_IN_USE, &wdt_status)) | 192 | orion_wdt_stop(&orion_wdt); |
| 295 | orion_wdt_disable(); | ||
| 296 | } | 193 | } |
| 297 | 194 | ||
| 298 | static struct platform_driver orion_wdt_driver = { | 195 | static struct platform_driver orion_wdt_driver = { |
diff --git a/drivers/watchdog/s3c2410_wdt.c b/drivers/watchdog/s3c2410_wdt.c index 200ece5e2a22..9245b4d23bfe 100644 --- a/drivers/watchdog/s3c2410_wdt.c +++ b/drivers/watchdog/s3c2410_wdt.c | |||
| @@ -519,21 +519,7 @@ static struct platform_driver s3c2410wdt_driver = { | |||
| 519 | }, | 519 | }, |
| 520 | }; | 520 | }; |
| 521 | 521 | ||
| 522 | 522 | module_platform_driver(s3c2410wdt_driver); | |
| 523 | static int __init watchdog_init(void) | ||
| 524 | { | ||
| 525 | pr_info("S3C2410 Watchdog Timer, (c) 2004 Simtec Electronics\n"); | ||
| 526 | |||
| 527 | return platform_driver_register(&s3c2410wdt_driver); | ||
| 528 | } | ||
| 529 | |||
| 530 | static void __exit watchdog_exit(void) | ||
| 531 | { | ||
| 532 | platform_driver_unregister(&s3c2410wdt_driver); | ||
| 533 | } | ||
| 534 | |||
| 535 | module_init(watchdog_init); | ||
| 536 | module_exit(watchdog_exit); | ||
| 537 | 523 | ||
| 538 | MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>, " | 524 | MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>, " |
| 539 | "Dimitry Andric <dimitry.andric@tomtom.com>"); | 525 | "Dimitry Andric <dimitry.andric@tomtom.com>"); |
diff --git a/drivers/watchdog/sch311x_wdt.c b/drivers/watchdog/sch311x_wdt.c index f8477002b728..9681ada0f252 100644 --- a/drivers/watchdog/sch311x_wdt.c +++ b/drivers/watchdog/sch311x_wdt.c | |||
| @@ -136,6 +136,8 @@ static void sch311x_wdt_set_timeout(int t) | |||
| 136 | 136 | ||
| 137 | static void sch311x_wdt_start(void) | 137 | static void sch311x_wdt_start(void) |
| 138 | { | 138 | { |
| 139 | unsigned char t; | ||
| 140 | |||
| 139 | spin_lock(&sch311x_wdt_data.io_lock); | 141 | spin_lock(&sch311x_wdt_data.io_lock); |
| 140 | 142 | ||
| 141 | /* set watchdog's timeout */ | 143 | /* set watchdog's timeout */ |
| @@ -149,7 +151,8 @@ static void sch311x_wdt_start(void) | |||
| 149 | * Bit 4-6 (Reserved) | 151 | * Bit 4-6 (Reserved) |
| 150 | * Bit 7, Output Type: 0 = Push Pull Bit, 1 = Open Drain | 152 | * Bit 7, Output Type: 0 = Push Pull Bit, 1 = Open Drain |
| 151 | */ | 153 | */ |
| 152 | outb(0x0e, sch311x_wdt_data.runtime_reg + GP60); | 154 | t = inb(sch311x_wdt_data.runtime_reg + GP60); |
| 155 | outb((t & ~0x0d) | 0x0c, sch311x_wdt_data.runtime_reg + GP60); | ||
| 153 | 156 | ||
| 154 | spin_unlock(&sch311x_wdt_data.io_lock); | 157 | spin_unlock(&sch311x_wdt_data.io_lock); |
| 155 | 158 | ||
| @@ -157,10 +160,13 @@ static void sch311x_wdt_start(void) | |||
| 157 | 160 | ||
| 158 | static void sch311x_wdt_stop(void) | 161 | static void sch311x_wdt_stop(void) |
| 159 | { | 162 | { |
| 163 | unsigned char t; | ||
| 164 | |||
| 160 | spin_lock(&sch311x_wdt_data.io_lock); | 165 | spin_lock(&sch311x_wdt_data.io_lock); |
| 161 | 166 | ||
| 162 | /* stop the watchdog */ | 167 | /* stop the watchdog */ |
| 163 | outb(0x01, sch311x_wdt_data.runtime_reg + GP60); | 168 | t = inb(sch311x_wdt_data.runtime_reg + GP60); |
| 169 | outb((t & ~0x0d) | 0x01, sch311x_wdt_data.runtime_reg + GP60); | ||
| 164 | /* disable timeout by setting it to 0 */ | 170 | /* disable timeout by setting it to 0 */ |
| 165 | sch311x_wdt_set_timeout(0); | 171 | sch311x_wdt_set_timeout(0); |
| 166 | 172 | ||
