aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/watchdog
diff options
context:
space:
mode:
authorAlexandre Belloni <alexandre.belloni@free-electrons.com>2015-03-12 08:07:28 -0400
committerNicolas Ferre <nicolas.ferre@atmel.com>2015-03-16 12:03:02 -0400
commit9ab45f3fb2bebd048ffa2692e8f7cc89f3d379d4 (patch)
tree05a02c41aac62c2ed8f812ff93cf6414f2ca0204 /drivers/watchdog
parent8432f9e5e82a13b82a76171c89b0858e855c9da5 (diff)
watchdog: at91rm9200: implement restart handler
Restarting the at91rm9200 is done through programming the watchdog and waiting for it to reset. Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com> Reviewed-by: Guenter Roeck <linux@roeck-us.net> Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
Diffstat (limited to 'drivers/watchdog')
-rw-r--r--drivers/watchdog/at91rm9200_wdt.c32
1 files changed, 32 insertions, 0 deletions
diff --git a/drivers/watchdog/at91rm9200_wdt.c b/drivers/watchdog/at91rm9200_wdt.c
index e6fa87d85de3..41cecb55766c 100644
--- a/drivers/watchdog/at91rm9200_wdt.c
+++ b/drivers/watchdog/at91rm9200_wdt.c
@@ -12,6 +12,7 @@
12#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 12#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
13 13
14#include <linux/bitops.h> 14#include <linux/bitops.h>
15#include <linux/delay.h>
15#include <linux/errno.h> 16#include <linux/errno.h>
16#include <linux/fs.h> 17#include <linux/fs.h>
17#include <linux/init.h> 18#include <linux/init.h>
@@ -23,6 +24,7 @@
23#include <linux/module.h> 24#include <linux/module.h>
24#include <linux/moduleparam.h> 25#include <linux/moduleparam.h>
25#include <linux/platform_device.h> 26#include <linux/platform_device.h>
27#include <linux/reboot.h>
26#include <linux/regmap.h> 28#include <linux/regmap.h>
27#include <linux/types.h> 29#include <linux/types.h>
28#include <linux/watchdog.h> 30#include <linux/watchdog.h>
@@ -53,6 +55,27 @@ static unsigned long at91wdt_busy;
53 55
54/* ......................................................................... */ 56/* ......................................................................... */
55 57
58static int at91rm9200_restart(struct notifier_block *this,
59 unsigned long mode, void *cmd)
60{
61 /*
62 * Perform a hardware reset with the use of the Watchdog timer.
63 */
64 regmap_write(regmap_st, AT91_ST_WDMR,
65 AT91_ST_RSTEN | AT91_ST_EXTEN | 1);
66 regmap_write(regmap_st, AT91_ST_CR, AT91_ST_WDRST);
67
68 mdelay(2000);
69
70 pr_emerg("Unable to restart system\n");
71 return NOTIFY_DONE;
72}
73
74static struct notifier_block at91rm9200_restart_nb = {
75 .notifier_call = at91rm9200_restart,
76 .priority = 192,
77};
78
56/* 79/*
57 * Disable the watchdog. 80 * Disable the watchdog.
58 */ 81 */
@@ -228,6 +251,10 @@ static int at91wdt_probe(struct platform_device *pdev)
228 if (res) 251 if (res)
229 return res; 252 return res;
230 253
254 res = register_restart_handler(&at91rm9200_restart_nb);
255 if (res)
256 dev_warn(dev, "failed to register restart handler\n");
257
231 pr_info("AT91 Watchdog Timer enabled (%d seconds%s)\n", 258 pr_info("AT91 Watchdog Timer enabled (%d seconds%s)\n",
232 wdt_time, nowayout ? ", nowayout" : ""); 259 wdt_time, nowayout ? ", nowayout" : "");
233 return 0; 260 return 0;
@@ -235,8 +262,13 @@ static int at91wdt_probe(struct platform_device *pdev)
235 262
236static int at91wdt_remove(struct platform_device *pdev) 263static int at91wdt_remove(struct platform_device *pdev)
237{ 264{
265 struct device *dev = &pdev->dev;
238 int res; 266 int res;
239 267
268 res = unregister_restart_handler(&at91rm9200_restart_nb);
269 if (res)
270 dev_warn(dev, "failed to unregister restart handler\n");
271
240 res = misc_deregister(&at91wdt_miscdev); 272 res = misc_deregister(&at91wdt_miscdev);
241 if (!res) 273 if (!res)
242 at91wdt_miscdev.parent = NULL; 274 at91wdt_miscdev.parent = NULL;