summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOctavian Purdila <octavian.purdila@nxp.com>2017-06-21 11:01:23 +0300
committerOctavian Purdila <octavian.purdila@nxp.com>2017-06-28 16:59:58 +0300
commit378e9e0975ca57edee37b82f5013aec0e86d2973 (patch)
tree2e293c71a14e9718ed937db655c2d4113246878e
parentd7d6f21052218881c0497e8829343e0db850df31 (diff)
MLK-15083 watchdog: imx2_wdt: fallback to timeout reset if explicit reset fails
If explicit reset fails fallback using the watchdog timeout. We already have set the timeout counter to 0, but we might need to ping the watchdog to load the new timeout, if a previous watchdog timeout value has already been set. We also decrease the time we spend waiting, to give a chance to log that the explicit reset failed and that we fallback to watchdog timeout reset. Signed-off-by: Octavian Purdila <octavian.purdila@nxp.com>
-rw-r--r--drivers/watchdog/imx2_wdt.c45
1 files changed, 26 insertions, 19 deletions
diff --git a/drivers/watchdog/imx2_wdt.c b/drivers/watchdog/imx2_wdt.c
index 712d089c7592..f3352aa04f64 100644
--- a/drivers/watchdog/imx2_wdt.c
+++ b/drivers/watchdog/imx2_wdt.c
@@ -93,6 +93,26 @@ static const struct watchdog_info imx2_wdt_pretimeout_info = {
WDIOF_PRETIMEOUT,
};
+static int imx2_wdt_ping(struct watchdog_device *wdog)
+{
+ struct imx2_wdt_device *wdev = watchdog_get_drvdata(wdog);
+
+ regmap_write(wdev->regmap, IMX2_WDT_WSR, IMX2_WDT_SEQ1);
+ regmap_write(wdev->regmap, IMX2_WDT_WSR, IMX2_WDT_SEQ2);
+ return 0;
+}
+
+
+static inline bool imx2_wdt_is_running(struct imx2_wdt_device *wdev)
+{
+ u32 val;
+
+ regmap_read(wdev->regmap, IMX2_WDT_WCR, &val);
+
+ return val & IMX2_WDT_WCR_WDE;
+}
+
+
static int imx2_wdt_restart(struct watchdog_device *wdog, unsigned long action,
void *data)
{
@@ -108,6 +128,9 @@ static int imx2_wdt_restart(struct watchdog_device *wdog, unsigned long action,
/* Assert SRS signal */
regmap_write(wdev->regmap, IMX2_WDT_WCR, wcr_enable);
+ if (imx2_wdt_is_running(wdev))
+ imx2_wdt_ping(wdog);
+
/*
* Due to imx6q errata ERR004346 (WDOG: WDOG SRS bit requires to be
* written twice), we add another two writes to ensure there must be at
@@ -119,7 +142,9 @@ static int imx2_wdt_restart(struct watchdog_device *wdog, unsigned long action,
regmap_write(wdev->regmap, IMX2_WDT_WCR, wcr_enable);
/* wait for reset to assert... */
- mdelay(500);
+ mdelay(100);
+ dev_err(wdog->parent, "failed to assert %s reset, trying with timeout\n",
+ wdev->ext_reset ? "external" : "internal");
return 0;
}
@@ -153,24 +178,6 @@ static inline void imx2_wdt_setup(struct watchdog_device *wdog)
regmap_write(wdev->regmap, IMX2_WDT_WCR, val);
}
-static inline bool imx2_wdt_is_running(struct imx2_wdt_device *wdev)
-{
- u32 val;
-
- regmap_read(wdev->regmap, IMX2_WDT_WCR, &val);
-
- return val & IMX2_WDT_WCR_WDE;
-}
-
-static int imx2_wdt_ping(struct watchdog_device *wdog)
-{
- struct imx2_wdt_device *wdev = watchdog_get_drvdata(wdog);
-
- regmap_write(wdev->regmap, IMX2_WDT_WSR, IMX2_WDT_SEQ1);
- regmap_write(wdev->regmap, IMX2_WDT_WSR, IMX2_WDT_SEQ2);
- return 0;
-}
-
static int imx2_wdt_set_timeout(struct watchdog_device *wdog,
unsigned int new_timeout)
{