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>
This commit is contained in:
Octavian Purdila 2017-06-21 08:01:23 +00:00 committed by Fabio Estevam
parent 20ebb9fb81
commit 0e674a64b8
1 changed files with 26 additions and 19 deletions

View File

@ -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)
{