Commit bc677ff4 authored by Tim Harvey's avatar Tim Harvey Committed by Wim Van Sebroeck

watchdog: imx2_wdt: add external reset support via dt prop

The IMX6 watchdog supports assertion of a signal (WDOG_B) which
can be pinmux'd to an external pin. This is typically used for boards that
have PMIC's in control of the IMX6 power rails. In fact, failure to use
such an external reset on boards with external PMIC's can result in various
hangs due to the IMX6 not being fully reset [1] as well as the board failing
to reset because its PMIC has not been reset to provide adequate voltage for
the CPU when coming out of reset at 800Mhz.

This uses a new device-tree property 'fsl,ext-reset-output' to indicate the
board has such a reset and to cause the watchdog to be configured to assert
WDOG_B instead of an internal reset both on a watchdog timeout and in
system_restart.

[1] http://lists.infradead.org/pipermail/linux-arm-kernel/2015-March/333689.html

Cc: Fabio Estevam <festevam@gmail.com>
Cc: Lucas Stach <l.stach@pengutronix.de>
Cc: Stefan Roese <sr@denx.de>
Cc: Iain Paton <ipaton0@gmail.com>
Cc: Sascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: default avatarTim Harvey <tharvey@gateworks.com>
Reviewed-by: default avatarLucas Stach <l.stach@pengutronix.de>
Acked-by: default avatarShawn Guo <shawn.guo@linaro.org>
Tested-by: default avatarAkshay Bhat <akshay.bhat@timesys.com>
Signed-off-by: default avatarGuenter Roeck <linux@roeck-us.net>
Signed-off-by: default avatarWim Van Sebroeck <wim@iguana.be>
parent ebbf677a
...@@ -5,10 +5,12 @@ Required properties: ...@@ -5,10 +5,12 @@ Required properties:
- reg : Should contain WDT registers location and length - reg : Should contain WDT registers location and length
- interrupts : Should contain WDT interrupt - interrupts : Should contain WDT interrupt
Optional property: Optional properties:
- big-endian: If present the watchdog device's registers are implemented - big-endian: If present the watchdog device's registers are implemented
in big endian mode, otherwise in native mode(same with CPU), for more in big endian mode, otherwise in native mode(same with CPU), for more
detail please see: Documentation/devicetree/bindings/regmap/regmap.txt. detail please see: Documentation/devicetree/bindings/regmap/regmap.txt.
- fsl,ext-reset-output: If present the watchdog device is configured to
assert its external reset (WDOG_B) instead of issuing a software reset.
Examples: Examples:
......
...@@ -37,6 +37,8 @@ ...@@ -37,6 +37,8 @@
#define IMX2_WDT_WCR 0x00 /* Control Register */ #define IMX2_WDT_WCR 0x00 /* Control Register */
#define IMX2_WDT_WCR_WT (0xFF << 8) /* -> Watchdog Timeout Field */ #define IMX2_WDT_WCR_WT (0xFF << 8) /* -> Watchdog Timeout Field */
#define IMX2_WDT_WCR_WDA (1 << 5) /* -> External Reset WDOG_B */
#define IMX2_WDT_WCR_SRS (1 << 4) /* -> Software Reset Signal */
#define IMX2_WDT_WCR_WRE (1 << 3) /* -> WDOG Reset Enable */ #define IMX2_WDT_WCR_WRE (1 << 3) /* -> WDOG Reset Enable */
#define IMX2_WDT_WCR_WDE (1 << 2) /* -> Watchdog Enable */ #define IMX2_WDT_WCR_WDE (1 << 2) /* -> Watchdog Enable */
#define IMX2_WDT_WCR_WDZST (1 << 0) /* -> Watchdog timer Suspend */ #define IMX2_WDT_WCR_WDZST (1 << 0) /* -> Watchdog timer Suspend */
...@@ -59,6 +61,7 @@ struct imx2_wdt_device { ...@@ -59,6 +61,7 @@ struct imx2_wdt_device {
struct clk *clk; struct clk *clk;
struct regmap *regmap; struct regmap *regmap;
struct watchdog_device wdog; struct watchdog_device wdog;
bool ext_reset;
}; };
static bool nowayout = WATCHDOG_NOWAYOUT; static bool nowayout = WATCHDOG_NOWAYOUT;
...@@ -83,6 +86,12 @@ static int imx2_wdt_restart(struct watchdog_device *wdog, unsigned long action, ...@@ -83,6 +86,12 @@ static int imx2_wdt_restart(struct watchdog_device *wdog, unsigned long action,
struct imx2_wdt_device *wdev = watchdog_get_drvdata(wdog); struct imx2_wdt_device *wdev = watchdog_get_drvdata(wdog);
unsigned int wcr_enable = IMX2_WDT_WCR_WDE; unsigned int wcr_enable = IMX2_WDT_WCR_WDE;
/* Use internal reset or external - not both */
if (wdev->ext_reset)
wcr_enable |= IMX2_WDT_WCR_SRS; /* do not assert int reset */
else
wcr_enable |= IMX2_WDT_WCR_WDA; /* do not assert ext-reset */
/* Assert SRS signal */ /* Assert SRS signal */
regmap_write(wdev->regmap, IMX2_WDT_WCR, wcr_enable); regmap_write(wdev->regmap, IMX2_WDT_WCR, wcr_enable);
/* /*
...@@ -112,8 +121,12 @@ static inline void imx2_wdt_setup(struct watchdog_device *wdog) ...@@ -112,8 +121,12 @@ static inline void imx2_wdt_setup(struct watchdog_device *wdog)
val |= IMX2_WDT_WCR_WDZST; val |= IMX2_WDT_WCR_WDZST;
/* Strip the old watchdog Time-Out value */ /* Strip the old watchdog Time-Out value */
val &= ~IMX2_WDT_WCR_WT; val &= ~IMX2_WDT_WCR_WT;
/* Generate reset if WDOG times out */ /* Generate internal chip-level reset if WDOG times out */
if (!wdev->ext_reset)
val &= ~IMX2_WDT_WCR_WRE; val &= ~IMX2_WDT_WCR_WRE;
/* Or if external-reset assert WDOG_B reset only on time-out */
else
val |= IMX2_WDT_WCR_WRE;
/* Keep Watchdog Disabled */ /* Keep Watchdog Disabled */
val &= ~IMX2_WDT_WCR_WDE; val &= ~IMX2_WDT_WCR_WDE;
/* Set the watchdog's Time-Out value */ /* Set the watchdog's Time-Out value */
...@@ -230,6 +243,8 @@ static int __init imx2_wdt_probe(struct platform_device *pdev) ...@@ -230,6 +243,8 @@ static int __init imx2_wdt_probe(struct platform_device *pdev)
regmap_read(wdev->regmap, IMX2_WDT_WRSR, &val); regmap_read(wdev->regmap, IMX2_WDT_WRSR, &val);
wdog->bootstatus = val & IMX2_WDT_WRSR_TOUT ? WDIOF_CARDRESET : 0; wdog->bootstatus = val & IMX2_WDT_WRSR_TOUT ? WDIOF_CARDRESET : 0;
wdev->ext_reset = of_property_read_bool(pdev->dev.of_node,
"fsl,ext-reset-output");
wdog->timeout = clamp_t(unsigned, timeout, 1, IMX2_WDT_MAX_TIME); wdog->timeout = clamp_t(unsigned, timeout, 1, IMX2_WDT_MAX_TIME);
if (wdog->timeout != timeout) if (wdog->timeout != timeout)
dev_warn(&pdev->dev, "Initial timeout out of range! Clamped from %u to %u\n", dev_warn(&pdev->dev, "Initial timeout out of range! Clamped from %u to %u\n",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment