summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOctavian Purdila <octavian.purdila@nxp.com>2017-06-21 08:01:23 +0000
committerFabio Estevam <festevam@gmail.com>2018-02-26 21:54:27 -0300
commit0e674a64b86e2bb00ab43f56104d3ea85dda0066 (patch)
treec187e9f8634e5b5204d33fe4e5e6284f04a77da2
parent20ebb9fb81ecf84b57197aaa2a44be017d48e597 (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> [fabio: Resolved conflict with 4.9.84] Signed-off-by: Fabio Estevam <festevam@gmail.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 93ccdb35c44f..fd28b660f475 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 void __imx2_wdt_set_timeout(struct watchdog_device *wdog,
unsigned int new_timeout)
{