aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/watchdog
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-07-24 16:26:08 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-07-24 16:26:08 -0400
commit3539fc544f39017cf3403b9319fb4d74b5116135 (patch)
treed2bcf279d54a78479ffeb3549d8b3c45de6704e1 /drivers/watchdog
parent2b849570264d9f802485e327b7a4b0c52991d26a (diff)
parent0dd6e4847ed8a42e81df6ffaa71129245a6d9d72 (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/Kconfig2
-rw-r--r--drivers/watchdog/bcm63xx_wdt.c4
-rw-r--r--drivers/watchdog/coh901327_wdt.c7
-rw-r--r--drivers/watchdog/f71808e_wdt.c4
-rw-r--r--drivers/watchdog/iTCO_wdt.c213
-rw-r--r--drivers/watchdog/ie6xx_wdt.c4
-rw-r--r--drivers/watchdog/of_xilinx_wdt.c2
-rw-r--r--drivers/watchdog/omap_wdt.c17
-rw-r--r--drivers/watchdog/orion_wdt.c203
-rw-r--r--drivers/watchdog/s3c2410_wdt.c16
-rw-r--r--drivers/watchdog/sch311x_wdt.c10
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
279config ORION_WATCHDOG 279config 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
578config ITCO_WDT 579config 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
305static struct platform_driver bcm63xx_wdt = { 305static 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
315module_platform_driver(bcm63xx_wdt); 315module_platform_driver(bcm63xx_wdt_driver);
316 316
317MODULE_AUTHOR("Miguel Gaio <miguel.gaio@efixo.com>"); 317MODULE_AUTHOR("Miguel Gaio <miguel.gaio@efixo.com>");
318MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>"); 318MODULE_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)
369out_no_wdog: 370out_no_wdog:
370 free_irq(irq, pdev); 371 free_irq(irq, pdev);
371out_no_irq: 372out_no_irq:
372 clk_disable(clk); 373 clk_disable_unprepare(clk);
373out_no_clk_enable: 374out_no_clk_enable:
374 clk_put(clk); 375 clk_put(clk);
375out_no_clk: 376out_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 */
91static unsigned long is_active;
92static char expect_release;
93static struct { /* this is private data for the iTCO_wdt device */ 91static 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 */
110static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */ 108static int heartbeat = WATCHDOG_TIMEOUT; /* in seconds */
111module_param(heartbeat, int, 0); 109module_param(heartbeat, int, 0);
112MODULE_PARM_DESC(heartbeat, "Watchdog timeout in seconds. " 110MODULE_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
116static bool nowayout = WATCHDOG_NOWAYOUT; 114static bool nowayout = WATCHDOG_NOWAYOUT;
117module_param(nowayout, bool, 0); 115module_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
181static int iTCO_wdt_start(void) 179static 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
215static int iTCO_wdt_stop(void) 213static 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
239static int iTCO_wdt_keepalive(void) 237static 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
260static int iTCO_wdt_set_heartbeat(int t) 258static 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
311static int iTCO_wdt_get_timeleft(int *time_left) 309static 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
342static 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
355static 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
371static 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
400static 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
469static const struct file_operations iTCO_wdt_fops = { 340static 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
348static 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
478static struct miscdevice iTCO_wdt_miscdev = { 357static 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
660static void iTCO_wdt_shutdown(struct platform_device *dev) 543static void iTCO_wdt_shutdown(struct platform_device *dev)
661{ 544{
662 iTCO_wdt_stop(); 545 iTCO_wdt_stop(NULL);
663} 546}
664 547
665static struct platform_driver iTCO_wdt_driver = { 548static 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
235static void __devexit ie6xx_wdt_debugfs_exit(void) 235static 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
245static void __devexit ie6xx_wdt_debugfs_exit(void) 245static 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) */
44static struct clk *clk; 43static struct clk *clk;
45static unsigned int wdt_tclk; 44static unsigned int wdt_tclk;
46static void __iomem *wdt_reg; 45static void __iomem *wdt_reg;
47static unsigned long wdt_status;
48static DEFINE_SPINLOCK(wdt_lock); 46static DEFINE_SPINLOCK(wdt_lock);
49 47
50static void orion_wdt_ping(void) 48static 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
60static void orion_wdt_enable(void) 59static 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
87static void orion_wdt_disable(void) 87static 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
106static int orion_wdt_get_timeleft(int *time_left) 107static 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
114static 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
123static ssize_t orion_wdt_write(struct file *file, const char *data, 118static 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
145static 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
156static const struct watchdog_info ident = { 125static 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
162static long orion_wdt_ioctl(struct file *file, unsigned int cmd, 130static 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
211static 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
224static 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
233static struct miscdevice orion_wdt_miscdev = { 139static 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
239static int __devinit orion_wdt_probe(struct platform_device *pdev) 144static 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
273static int __devexit orion_wdt_remove(struct platform_device *pdev) 183static 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
292static void orion_wdt_shutdown(struct platform_device *pdev) 190static 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
298static struct platform_driver orion_wdt_driver = { 195static 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 522module_platform_driver(s3c2410wdt_driver);
523static 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
530static void __exit watchdog_exit(void)
531{
532 platform_driver_unregister(&s3c2410wdt_driver);
533}
534
535module_init(watchdog_init);
536module_exit(watchdog_exit);
537 523
538MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>, " 524MODULE_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
137static void sch311x_wdt_start(void) 137static 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
158static void sch311x_wdt_stop(void) 161static 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