summaryrefslogtreecommitdiff
path: root/drivers/watchdog
diff options
context:
space:
mode:
authorOctavian Purdila <octavian.purdila@nxp.com>2017-06-21 11:01:23 +0300
committerLeonard Crestez <leonard.crestez@nxp.com>2018-08-24 12:41:33 +0300
commite34ae04d7a994483412bcf34a5c4b083227acdbc (patch)
treedf6101c30b11c9d4fd017863ddad18b3209d04d7 /drivers/watchdog
parent7a8a62081a82212677c2ede47ad092775aea3d75 (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>
Diffstat (limited to 'drivers/watchdog')
-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)
{