diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-07-24 16:26:08 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-07-24 16:26:08 -0400 |
commit | 3539fc544f39017cf3403b9319fb4d74b5116135 (patch) | |
tree | d2bcf279d54a78479ffeb3549d8b3c45de6704e1 /drivers/watchdog | |
parent | 2b849570264d9f802485e327b7a4b0c52991d26a (diff) | |
parent | 0dd6e4847ed8a42e81df6ffaa71129245a6d9d72 (diff) |
Merge git://www.linux-watchdog.org/linux-watchdog
Pull watchdog changes from Wim Van Sebroeck:
- conversion of iTCO_wdt and orion_wdt to the generic watchdog API
- uses module_platform_driver() for s3c2410_wdt
- Adds support for Jetway JNF99 Motherboard
- various fixes
* git://www.linux-watchdog.org/linux-watchdog:
watchdog: orion_wdt: Convert driver to watchdog core
watchdog: s3c2410_wdt: Use module_platform_driver()
watchdog: sch311x_wdt: Fix Polarity when starting watchdog
Watchdog: OMAP: Fix the runtime pm code to avoid module getting stuck intransition state.
watchdog: ie6xx_wdt: section mismatch in ie6xx_wdt_probe()
watchdog: bcm63xx_wdt: fix driver section mismatch
watchdog: iTCO_wdt.c: convert to watchdog core
char/ipmi: remove local ioctl defines replaced by generic ones
watchdog: xilinx: Read clock frequency directly from DT node
watchdog: coh901327_wdt: use clk_prepare/unprepare
watchdog: f71808e_wdt: Add support for Jetway JNF99 motherboard
Diffstat (limited to 'drivers/watchdog')
-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 |
11 files changed, 121 insertions, 361 deletions
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 | ||