aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/watchdog
diff options
context:
space:
mode:
authorJingchang Lu <jingchang.lu@freescale.com>2014-09-12 03:24:36 -0400
committerWim Van Sebroeck <wim@iguana.be>2014-10-20 15:04:50 -0400
commit334a9d8131254e06685b2af0c0f3cc7b3ec5bd04 (patch)
treebc7ea47ee66c67c69b8b1ad2e853e82a5ac83bd6 /drivers/watchdog
parent05e487d905ab29b5756d6d1e47e27eefa6693fb3 (diff)
watchdog: imx2_wdt: add restart handler support
Register the watchdog as the system restart function to the new introducing kernel restart call chain in the driver instead of providing the restart in machine desc. This restart handler function is from the mxc_restart() in arch/arm/mach-imx/system.c Signed-off-by: Jingchang Lu <jingchang.lu@freescale.com> Reviewed-by: Guenter Roeck <linux@roeck-us.net> Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
Diffstat (limited to 'drivers/watchdog')
-rw-r--r--drivers/watchdog/imx2_wdt.c37
1 files changed, 37 insertions, 0 deletions
diff --git a/drivers/watchdog/imx2_wdt.c b/drivers/watchdog/imx2_wdt.c
index f37bb05e7ec0..7e12f88bb4a6 100644
--- a/drivers/watchdog/imx2_wdt.c
+++ b/drivers/watchdog/imx2_wdt.c
@@ -22,14 +22,17 @@
22 */ 22 */
23 23
24#include <linux/clk.h> 24#include <linux/clk.h>
25#include <linux/delay.h>
25#include <linux/init.h> 26#include <linux/init.h>
26#include <linux/io.h> 27#include <linux/io.h>
27#include <linux/jiffies.h> 28#include <linux/jiffies.h>
28#include <linux/kernel.h> 29#include <linux/kernel.h>
29#include <linux/module.h> 30#include <linux/module.h>
30#include <linux/moduleparam.h> 31#include <linux/moduleparam.h>
32#include <linux/notifier.h>
31#include <linux/of_address.h> 33#include <linux/of_address.h>
32#include <linux/platform_device.h> 34#include <linux/platform_device.h>
35#include <linux/reboot.h>
33#include <linux/regmap.h> 36#include <linux/regmap.h>
34#include <linux/timer.h> 37#include <linux/timer.h>
35#include <linux/watchdog.h> 38#include <linux/watchdog.h>
@@ -59,6 +62,7 @@ struct imx2_wdt_device {
59 struct regmap *regmap; 62 struct regmap *regmap;
60 struct timer_list timer; /* Pings the watchdog when closed */ 63 struct timer_list timer; /* Pings the watchdog when closed */
61 struct watchdog_device wdog; 64 struct watchdog_device wdog;
65 struct notifier_block restart_handler;
62}; 66};
63 67
64static bool nowayout = WATCHDOG_NOWAYOUT; 68static bool nowayout = WATCHDOG_NOWAYOUT;
@@ -77,6 +81,31 @@ static const struct watchdog_info imx2_wdt_info = {
77 .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, 81 .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
78}; 82};
79 83
84static int imx2_restart_handler(struct notifier_block *this, unsigned long mode,
85 void *cmd)
86{
87 unsigned int wcr_enable = IMX2_WDT_WCR_WDE;
88 struct imx2_wdt_device *wdev = container_of(this,
89 struct imx2_wdt_device,
90 restart_handler);
91 /* Assert SRS signal */
92 regmap_write(wdev->regmap, 0, wcr_enable);
93 /*
94 * Due to imx6q errata ERR004346 (WDOG: WDOG SRS bit requires to be
95 * written twice), we add another two writes to ensure there must be at
96 * least two writes happen in the same one 32kHz clock period. We save
97 * the target check here, since the writes shouldn't be a huge burden
98 * for other platforms.
99 */
100 regmap_write(wdev->regmap, 0, wcr_enable);
101 regmap_write(wdev->regmap, 0, wcr_enable);
102
103 /* wait for reset to assert... */
104 mdelay(500);
105
106 return NOTIFY_DONE;
107}
108
80static inline void imx2_wdt_setup(struct watchdog_device *wdog) 109static inline void imx2_wdt_setup(struct watchdog_device *wdog)
81{ 110{
82 struct imx2_wdt_device *wdev = watchdog_get_drvdata(wdog); 111 struct imx2_wdt_device *wdev = watchdog_get_drvdata(wdog);
@@ -251,6 +280,12 @@ static int __init imx2_wdt_probe(struct platform_device *pdev)
251 return ret; 280 return ret;
252 } 281 }
253 282
283 wdev->restart_handler.notifier_call = imx2_restart_handler;
284 wdev->restart_handler.priority = 128;
285 ret = register_restart_handler(&wdev->restart_handler);
286 if (ret)
287 dev_err(&pdev->dev, "cannot register restart handler\n");
288
254 dev_info(&pdev->dev, "timeout %d sec (nowayout=%d)\n", 289 dev_info(&pdev->dev, "timeout %d sec (nowayout=%d)\n",
255 wdog->timeout, nowayout); 290 wdog->timeout, nowayout);
256 291
@@ -262,6 +297,8 @@ static int __exit imx2_wdt_remove(struct platform_device *pdev)
262 struct watchdog_device *wdog = platform_get_drvdata(pdev); 297 struct watchdog_device *wdog = platform_get_drvdata(pdev);
263 struct imx2_wdt_device *wdev = watchdog_get_drvdata(wdog); 298 struct imx2_wdt_device *wdev = watchdog_get_drvdata(wdog);
264 299
300 unregister_restart_handler(&wdev->restart_handler);
301
265 watchdog_unregister_device(wdog); 302 watchdog_unregister_device(wdog);
266 303
267 if (imx2_wdt_is_running(wdev)) { 304 if (imx2_wdt_is_running(wdev)) {