Commit 334a9d8131254e06685b2af0c0f3cc7b3ec5bd04
Committed by
Wim Van Sebroeck
1 parent
05e487d905
Exists in
ti-lsk-linux-4.1.y
and in
10 other branches
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>
Showing 1 changed file with 37 additions and 0 deletions Side-by-side Diff
drivers/watchdog/imx2_wdt.c
... | ... | @@ -22,14 +22,17 @@ |
22 | 22 | */ |
23 | 23 | |
24 | 24 | #include <linux/clk.h> |
25 | +#include <linux/delay.h> | |
25 | 26 | #include <linux/init.h> |
26 | 27 | #include <linux/io.h> |
27 | 28 | #include <linux/jiffies.h> |
28 | 29 | #include <linux/kernel.h> |
29 | 30 | #include <linux/module.h> |
30 | 31 | #include <linux/moduleparam.h> |
32 | +#include <linux/notifier.h> | |
31 | 33 | #include <linux/of_address.h> |
32 | 34 | #include <linux/platform_device.h> |
35 | +#include <linux/reboot.h> | |
33 | 36 | #include <linux/regmap.h> |
34 | 37 | #include <linux/timer.h> |
35 | 38 | #include <linux/watchdog.h> |
... | ... | @@ -59,6 +62,7 @@ |
59 | 62 | struct regmap *regmap; |
60 | 63 | struct timer_list timer; /* Pings the watchdog when closed */ |
61 | 64 | struct watchdog_device wdog; |
65 | + struct notifier_block restart_handler; | |
62 | 66 | }; |
63 | 67 | |
64 | 68 | static bool nowayout = WATCHDOG_NOWAYOUT; |
... | ... | @@ -77,6 +81,31 @@ |
77 | 81 | .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, |
78 | 82 | }; |
79 | 83 | |
84 | +static 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 | + | |
80 | 109 | static inline void imx2_wdt_setup(struct watchdog_device *wdog) |
81 | 110 | { |
82 | 111 | struct imx2_wdt_device *wdev = watchdog_get_drvdata(wdog); |
... | ... | @@ -251,6 +280,12 @@ |
251 | 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 | 289 | dev_info(&pdev->dev, "timeout %d sec (nowayout=%d)\n", |
255 | 290 | wdog->timeout, nowayout); |
256 | 291 | |
... | ... | @@ -261,6 +296,8 @@ |
261 | 296 | { |
262 | 297 | struct watchdog_device *wdog = platform_get_drvdata(pdev); |
263 | 298 | struct imx2_wdt_device *wdev = watchdog_get_drvdata(wdog); |
299 | + | |
300 | + unregister_restart_handler(&wdev->restart_handler); | |
264 | 301 | |
265 | 302 | watchdog_unregister_device(wdog); |
266 | 303 |