aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/watchdog/s3c2410_wdt.c36
1 files changed, 36 insertions, 0 deletions
diff --git a/drivers/watchdog/s3c2410_wdt.c b/drivers/watchdog/s3c2410_wdt.c
index 015256e496ae..8532c3e2aea7 100644
--- a/drivers/watchdog/s3c2410_wdt.c
+++ b/drivers/watchdog/s3c2410_wdt.c
@@ -41,6 +41,8 @@
41#include <linux/of.h> 41#include <linux/of.h>
42#include <linux/mfd/syscon.h> 42#include <linux/mfd/syscon.h>
43#include <linux/regmap.h> 43#include <linux/regmap.h>
44#include <linux/reboot.h>
45#include <linux/delay.h>
44 46
45#define S3C2410_WTCON 0x00 47#define S3C2410_WTCON 0x00
46#define S3C2410_WTDAT 0x04 48#define S3C2410_WTDAT 0x04
@@ -128,6 +130,7 @@ struct s3c2410_wdt {
128 unsigned long wtdat_save; 130 unsigned long wtdat_save;
129 struct watchdog_device wdt_device; 131 struct watchdog_device wdt_device;
130 struct notifier_block freq_transition; 132 struct notifier_block freq_transition;
133 struct notifier_block restart_handler;
131 struct s3c2410_wdt_variant *drv_data; 134 struct s3c2410_wdt_variant *drv_data;
132 struct regmap *pmureg; 135 struct regmap *pmureg;
133}; 136};
@@ -449,6 +452,31 @@ static inline void s3c2410wdt_cpufreq_deregister(struct s3c2410_wdt *wdt)
449} 452}
450#endif 453#endif
451 454
455static int s3c2410wdt_restart(struct notifier_block *this,
456 unsigned long mode, void *cmd)
457{
458 struct s3c2410_wdt *wdt = container_of(this, struct s3c2410_wdt,
459 restart_handler);
460 void __iomem *wdt_base = wdt->reg_base;
461
462 /* disable watchdog, to be safe */
463 writel(0, wdt_base + S3C2410_WTCON);
464
465 /* put initial values into count and data */
466 writel(0x80, wdt_base + S3C2410_WTCNT);
467 writel(0x80, wdt_base + S3C2410_WTDAT);
468
469 /* set the watchdog to go and reset... */
470 writel(S3C2410_WTCON_ENABLE | S3C2410_WTCON_DIV16 |
471 S3C2410_WTCON_RSTEN | S3C2410_WTCON_PRESCALE(0x20),
472 wdt_base + S3C2410_WTCON);
473
474 /* wait for reset to assert... */
475 mdelay(500);
476
477 return NOTIFY_DONE;
478}
479
452static inline unsigned int s3c2410wdt_get_bootstatus(struct s3c2410_wdt *wdt) 480static inline unsigned int s3c2410wdt_get_bootstatus(struct s3c2410_wdt *wdt)
453{ 481{
454 unsigned int rst_stat; 482 unsigned int rst_stat;
@@ -603,6 +631,12 @@ static int s3c2410wdt_probe(struct platform_device *pdev)
603 631
604 platform_set_drvdata(pdev, wdt); 632 platform_set_drvdata(pdev, wdt);
605 633
634 wdt->restart_handler.notifier_call = s3c2410wdt_restart;
635 wdt->restart_handler.priority = 128;
636 ret = register_restart_handler(&wdt->restart_handler);
637 if (ret)
638 pr_err("cannot register restart handler, %d\n", ret);
639
606 /* print out a statement of readiness */ 640 /* print out a statement of readiness */
607 641
608 wtcon = readl(wdt->reg_base + S3C2410_WTCON); 642 wtcon = readl(wdt->reg_base + S3C2410_WTCON);
@@ -632,6 +666,8 @@ static int s3c2410wdt_remove(struct platform_device *dev)
632 int ret; 666 int ret;
633 struct s3c2410_wdt *wdt = platform_get_drvdata(dev); 667 struct s3c2410_wdt *wdt = platform_get_drvdata(dev);
634 668
669 unregister_restart_handler(&wdt->restart_handler);
670
635 ret = s3c2410wdt_mask_and_disable_reset(wdt, true); 671 ret = s3c2410wdt_mask_and_disable_reset(wdt, true);
636 if (ret < 0) 672 if (ret < 0)
637 return ret; 673 return ret;