Commit 334a9d8131254e06685b2af0c0f3cc7b3ec5bd04

Authored by Jingchang Lu
Committed by Wim Van Sebroeck
1 parent 05e487d905

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