diff options
Diffstat (limited to 'drivers/char/watchdog/s3c2410_wdt.c')
-rw-r--r-- | drivers/char/watchdog/s3c2410_wdt.c | 87 |
1 files changed, 55 insertions, 32 deletions
diff --git a/drivers/char/watchdog/s3c2410_wdt.c b/drivers/char/watchdog/s3c2410_wdt.c index f85ac898a49a..8b292bf343c4 100644 --- a/drivers/char/watchdog/s3c2410_wdt.c +++ b/drivers/char/watchdog/s3c2410_wdt.c | |||
@@ -27,7 +27,10 @@ | |||
27 | * Fixed tmr_count / wdt_count confusion | 27 | * Fixed tmr_count / wdt_count confusion |
28 | * Added configurable debug | 28 | * Added configurable debug |
29 | * | 29 | * |
30 | * 11-Jan-2004 BJD Fixed divide-by-2 in timeout code | 30 | * 11-Jan-2005 BJD Fixed divide-by-2 in timeout code |
31 | * | ||
32 | * 25-Jan-2005 DA Added suspend/resume support | ||
33 | * Replaced reboot notifier with .shutdown method | ||
31 | * | 34 | * |
32 | * 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA | 35 | * 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA |
33 | */ | 36 | */ |
@@ -40,8 +43,6 @@ | |||
40 | #include <linux/miscdevice.h> | 43 | #include <linux/miscdevice.h> |
41 | #include <linux/watchdog.h> | 44 | #include <linux/watchdog.h> |
42 | #include <linux/fs.h> | 45 | #include <linux/fs.h> |
43 | #include <linux/notifier.h> | ||
44 | #include <linux/reboot.h> | ||
45 | #include <linux/init.h> | 46 | #include <linux/init.h> |
46 | #include <linux/device.h> | 47 | #include <linux/device.h> |
47 | #include <linux/interrupt.h> | 48 | #include <linux/interrupt.h> |
@@ -317,20 +318,6 @@ static int s3c2410wdt_ioctl(struct inode *inode, struct file *file, | |||
317 | } | 318 | } |
318 | } | 319 | } |
319 | 320 | ||
320 | /* | ||
321 | * Notifier for system down | ||
322 | */ | ||
323 | |||
324 | static int s3c2410wdt_notify_sys(struct notifier_block *this, unsigned long code, | ||
325 | void *unused) | ||
326 | { | ||
327 | if(code==SYS_DOWN || code==SYS_HALT) { | ||
328 | /* Turn the WDT off */ | ||
329 | s3c2410wdt_stop(); | ||
330 | } | ||
331 | return NOTIFY_DONE; | ||
332 | } | ||
333 | |||
334 | /* kernel interface */ | 321 | /* kernel interface */ |
335 | 322 | ||
336 | static struct file_operations s3c2410wdt_fops = { | 323 | static struct file_operations s3c2410wdt_fops = { |
@@ -348,10 +335,6 @@ static struct miscdevice s3c2410wdt_miscdev = { | |||
348 | .fops = &s3c2410wdt_fops, | 335 | .fops = &s3c2410wdt_fops, |
349 | }; | 336 | }; |
350 | 337 | ||
351 | static struct notifier_block s3c2410wdt_notifier = { | ||
352 | .notifier_call = s3c2410wdt_notify_sys, | ||
353 | }; | ||
354 | |||
355 | /* interrupt handler code */ | 338 | /* interrupt handler code */ |
356 | 339 | ||
357 | static irqreturn_t s3c2410wdt_irq(int irqno, void *param, | 340 | static irqreturn_t s3c2410wdt_irq(int irqno, void *param, |
@@ -432,18 +415,10 @@ static int s3c2410wdt_probe(struct device *dev) | |||
432 | } | 415 | } |
433 | } | 416 | } |
434 | 417 | ||
435 | ret = register_reboot_notifier(&s3c2410wdt_notifier); | ||
436 | if (ret) { | ||
437 | printk (KERN_ERR PFX "cannot register reboot notifier (%d)\n", | ||
438 | ret); | ||
439 | return ret; | ||
440 | } | ||
441 | |||
442 | ret = misc_register(&s3c2410wdt_miscdev); | 418 | ret = misc_register(&s3c2410wdt_miscdev); |
443 | if (ret) { | 419 | if (ret) { |
444 | printk (KERN_ERR PFX "cannot register miscdev on minor=%d (%d)\n", | 420 | printk (KERN_ERR PFX "cannot register miscdev on minor=%d (%d)\n", |
445 | WATCHDOG_MINOR, ret); | 421 | WATCHDOG_MINOR, ret); |
446 | unregister_reboot_notifier(&s3c2410wdt_notifier); | ||
447 | return ret; | 422 | return ret; |
448 | } | 423 | } |
449 | 424 | ||
@@ -479,15 +454,63 @@ static int s3c2410wdt_remove(struct device *dev) | |||
479 | return 0; | 454 | return 0; |
480 | } | 455 | } |
481 | 456 | ||
457 | static void s3c2410wdt_shutdown(struct device *dev) | ||
458 | { | ||
459 | s3c2410wdt_stop(); | ||
460 | } | ||
461 | |||
462 | #ifdef CONFIG_PM | ||
463 | |||
464 | static unsigned long wtcon_save; | ||
465 | static unsigned long wtdat_save; | ||
466 | |||
467 | static int s3c2410wdt_suspend(struct device *dev, u32 state, u32 level) | ||
468 | { | ||
469 | if (level == SUSPEND_POWER_DOWN) { | ||
470 | /* Save watchdog state, and turn it off. */ | ||
471 | wtcon_save = readl(wdt_base + S3C2410_WTCON); | ||
472 | wtdat_save = readl(wdt_base + S3C2410_WTDAT); | ||
473 | |||
474 | /* Note that WTCNT doesn't need to be saved. */ | ||
475 | s3c2410wdt_stop(); | ||
476 | } | ||
477 | |||
478 | return 0; | ||
479 | } | ||
480 | |||
481 | static int s3c2410wdt_resume(struct device *dev, u32 level) | ||
482 | { | ||
483 | if (level == RESUME_POWER_ON) { | ||
484 | /* Restore watchdog state. */ | ||
485 | |||
486 | writel(wtdat_save, wdt_base + S3C2410_WTDAT); | ||
487 | writel(wtdat_save, wdt_base + S3C2410_WTCNT); /* Reset count */ | ||
488 | writel(wtcon_save, wdt_base + S3C2410_WTCON); | ||
489 | |||
490 | printk(KERN_INFO PFX "watchdog %sabled\n", | ||
491 | (wtcon_save & S3C2410_WTCON_ENABLE) ? "en" : "dis"); | ||
492 | } | ||
493 | |||
494 | return 0; | ||
495 | } | ||
496 | |||
497 | #else | ||
498 | #define s3c2410wdt_suspend NULL | ||
499 | #define s3c2410wdt_resume NULL | ||
500 | #endif /* CONFIG_PM */ | ||
501 | |||
502 | |||
482 | static struct device_driver s3c2410wdt_driver = { | 503 | static struct device_driver s3c2410wdt_driver = { |
483 | .name = "s3c2410-wdt", | 504 | .name = "s3c2410-wdt", |
484 | .bus = &platform_bus_type, | 505 | .bus = &platform_bus_type, |
485 | .probe = s3c2410wdt_probe, | 506 | .probe = s3c2410wdt_probe, |
486 | .remove = s3c2410wdt_remove, | 507 | .remove = s3c2410wdt_remove, |
508 | .shutdown = s3c2410wdt_shutdown, | ||
509 | .suspend = s3c2410wdt_suspend, | ||
510 | .resume = s3c2410wdt_resume, | ||
487 | }; | 511 | }; |
488 | 512 | ||
489 | 513 | ||
490 | |||
491 | static char banner[] __initdata = KERN_INFO "S3C2410 Watchdog Timer, (c) 2004 Simtec Electronics\n"; | 514 | static char banner[] __initdata = KERN_INFO "S3C2410 Watchdog Timer, (c) 2004 Simtec Electronics\n"; |
492 | 515 | ||
493 | static int __init watchdog_init(void) | 516 | static int __init watchdog_init(void) |
@@ -499,13 +522,13 @@ static int __init watchdog_init(void) | |||
499 | static void __exit watchdog_exit(void) | 522 | static void __exit watchdog_exit(void) |
500 | { | 523 | { |
501 | driver_unregister(&s3c2410wdt_driver); | 524 | driver_unregister(&s3c2410wdt_driver); |
502 | unregister_reboot_notifier(&s3c2410wdt_notifier); | ||
503 | } | 525 | } |
504 | 526 | ||
505 | module_init(watchdog_init); | 527 | module_init(watchdog_init); |
506 | module_exit(watchdog_exit); | 528 | module_exit(watchdog_exit); |
507 | 529 | ||
508 | MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); | 530 | MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>, " |
531 | "Dimitry Andric <dimitry.andric@tomtom.com>"); | ||
509 | MODULE_DESCRIPTION("S3C2410 Watchdog Device Driver"); | 532 | MODULE_DESCRIPTION("S3C2410 Watchdog Device Driver"); |
510 | MODULE_LICENSE("GPL"); | 533 | MODULE_LICENSE("GPL"); |
511 | MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); | 534 | MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); |