[U-Boot] [PATCH 0/2] imx watchdog updates

Update the iMX watchdog driver functionality to more closely match the Linux driver by controlling the external reset bits according to the device tree settings, and using the immediate reset bits when told to expire now.
Robert Hancock (2): watchdog: imx: Add DT ext-reset handling watchdog: imx: Use immediate reset bits for expire_now
drivers/watchdog/imx_watchdog.c | 41 ++++++++++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 13 deletions(-)

The Linux imx2_wdt driver uses a fsl,ext-reset-output boolean in the device tree to specify whether the board design should use the external reset instead of the internal reset. Use this boolean to determine which mode to use rather than using external reset unconditionally.
For the legacy non-DM mode, the external reset is always used in order to maintain the previous behavior.
Signed-off-by: Robert Hancock hancock@sedsystems.ca --- drivers/watchdog/imx_watchdog.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-)
diff --git a/drivers/watchdog/imx_watchdog.c b/drivers/watchdog/imx_watchdog.c index 53a3e9f..05bbfe0 100644 --- a/drivers/watchdog/imx_watchdog.c +++ b/drivers/watchdog/imx_watchdog.c @@ -47,9 +47,10 @@ static void imx_watchdog_reset(struct watchdog_regs *wdog) #endif /* CONFIG_WATCHDOG_RESET_DISABLE*/ }
-static void imx_watchdog_init(struct watchdog_regs *wdog) +static void imx_watchdog_init(struct watchdog_regs *wdog, bool ext_reset) { u16 timeout; + u16 wcr;
/* * The timer watchdog can be set between @@ -61,11 +62,14 @@ static void imx_watchdog_init(struct watchdog_regs *wdog) #endif timeout = (CONFIG_WATCHDOG_TIMEOUT_MSECS / 500) - 1; #ifdef CONFIG_FSL_LSCH2 - writew((WCR_WDA | WCR_SRS | WCR_WDE) << 8 | timeout, &wdog->wcr); + wcr = (WCR_WDA | WCR_SRS | WCR_WDE) << 8 | timeout; #else - writew(WCR_WDZST | WCR_WDBG | WCR_WDE | WCR_WDT | WCR_SRS | - WCR_WDA | SET_WCR_WT(timeout), &wdog->wcr); + wcr = WCR_WDZST | WCR_WDBG | WCR_WDE | WCR_SRS | + WCR_WDA | SET_WCR_WT(timeout); + if (ext_reset) + wcr |= WCR_WDT; #endif /* CONFIG_FSL_LSCH2*/ + writew(wcr, &wdog->wcr); imx_watchdog_reset(wdog); }
@@ -81,11 +85,12 @@ void hw_watchdog_init(void) { struct watchdog_regs *wdog = (struct watchdog_regs *)WDOG1_BASE_ADDR;
- imx_watchdog_init(wdog); + imx_watchdog_init(wdog, true); } #else struct imx_wdt_priv { void __iomem *base; + bool ext_reset; };
static int imx_wdt_reset(struct udevice *dev) @@ -111,7 +116,7 @@ static int imx_wdt_start(struct udevice *dev, u64 timeout, ulong flags) { struct imx_wdt_priv *priv = dev_get_priv(dev);
- imx_watchdog_init(priv->base); + imx_watchdog_init(priv->base, priv->ext_reset);
return 0; } @@ -124,6 +129,8 @@ static int imx_wdt_probe(struct udevice *dev) if (!priv->base) return -ENOENT;
+ priv->ext_reset = dev_read_bool(dev, "fsl,ext-reset-output"); + return 0; }

On 8/6/19 7:05 PM, Robert Hancock wrote:
The Linux imx2_wdt driver uses a fsl,ext-reset-output boolean in the device tree to specify whether the board design should use the external reset instead of the internal reset. Use this boolean to determine which mode to use rather than using external reset unconditionally.
For the legacy non-DM mode, the external reset is always used in order to maintain the previous behavior.
Signed-off-by: Robert Hancock hancock@sedsystems.ca
[...]
@@ -124,6 +129,8 @@ static int imx_wdt_probe(struct udevice *dev) if (!priv->base) return -ENOENT;
- priv->ext_reset = dev_read_bool(dev, "fsl,ext-reset-output");
Do we need a vendor-specific, undocumented, DT property ?

On 2019-08-06 11:11 a.m., Marek Vasut wrote:
On 8/6/19 7:05 PM, Robert Hancock wrote:
The Linux imx2_wdt driver uses a fsl,ext-reset-output boolean in the device tree to specify whether the board design should use the external reset instead of the internal reset. Use this boolean to determine which mode to use rather than using external reset unconditionally.
For the legacy non-DM mode, the external reset is always used in order to maintain the previous behavior.
Signed-off-by: Robert Hancock hancock@sedsystems.ca
[...]
@@ -124,6 +129,8 @@ static int imx_wdt_probe(struct udevice *dev) if (!priv->base) return -ENOENT;
- priv->ext_reset = dev_read_bool(dev, "fsl,ext-reset-output");
Do we need a vendor-specific, undocumented, DT property ?
It is documented in Linux in Documentation/devicetree/bindings/watchdog/fsl-imx-wdt.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.
I'm not aware of anything non-vendor-specific defined for this.

On 8/6/19 8:49 PM, Robert Hancock wrote:
On 2019-08-06 11:11 a.m., Marek Vasut wrote:
On 8/6/19 7:05 PM, Robert Hancock wrote:
The Linux imx2_wdt driver uses a fsl,ext-reset-output boolean in the device tree to specify whether the board design should use the external reset instead of the internal reset. Use this boolean to determine which mode to use rather than using external reset unconditionally.
For the legacy non-DM mode, the external reset is always used in order to maintain the previous behavior.
Signed-off-by: Robert Hancock hancock@sedsystems.ca
[...]
@@ -124,6 +129,8 @@ static int imx_wdt_probe(struct udevice *dev) if (!priv->base) return -ENOENT;
- priv->ext_reset = dev_read_bool(dev, "fsl,ext-reset-output");
Do we need a vendor-specific, undocumented, DT property ?
It is documented in Linux in Documentation/devicetree/bindings/watchdog/fsl-imx-wdt.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.
I'm not aware of anything non-vendor-specific defined for this.
Aha, then please ignore my comment, thanks for clarifying.

On 2019-08-07 2:28 a.m., Marek Vasut wrote:
On 8/6/19 8:49 PM, Robert Hancock wrote:
On 2019-08-06 11:11 a.m., Marek Vasut wrote:
On 8/6/19 7:05 PM, Robert Hancock wrote:
The Linux imx2_wdt driver uses a fsl,ext-reset-output boolean in the device tree to specify whether the board design should use the external reset instead of the internal reset. Use this boolean to determine which mode to use rather than using external reset unconditionally.
For the legacy non-DM mode, the external reset is always used in order to maintain the previous behavior.
Signed-off-by: Robert Hancock hancock@sedsystems.ca
[...]
@@ -124,6 +129,8 @@ static int imx_wdt_probe(struct udevice *dev) if (!priv->base) return -ENOENT;
- priv->ext_reset = dev_read_bool(dev, "fsl,ext-reset-output");
Do we need a vendor-specific, undocumented, DT property ?
It is documented in Linux in Documentation/devicetree/bindings/watchdog/fsl-imx-wdt.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.
I'm not aware of anything non-vendor-specific defined for this.
Aha, then please ignore my comment, thanks for clarifying.
Any updates on this patch set? It is still outstanding in patchwork:
https://patchwork.ozlabs.org/project/uboot/list/?series=123623

On Wed, Oct 16, 2019 at 1:11 PM Robert Hancock hancock@sedsystems.ca wrote:
Any updates on this patch set? It is still outstanding in patchwork:
https://patchwork.ozlabs.org/project/uboot/list/?series=123623
Series looks good. Not sure if you added Stefano on Cc.

The Linux imx2_wdt driver uses a fsl,ext-reset-output boolean in the device tree to specify whether the board design should use the external reset instead of the internal reset. Use this boolean to determine which mode to use rather than using external reset unconditionally. For the legacy non-DM mode, the external reset is always used in order to maintain the previous behavior. Signed-off-by: Robert Hancock hancock@sedsystems.ca
Applied to u-boot-imx, master, thanks !
Best regards, Stefano Babic

The expire_now function was previously setting the watchdog timeout to minimum and waiting for the watchdog to expire. However, this watchdog also has bits to trigger immediate reset. Use those instead, like the Linux imx2_wdt driver does.
Signed-off-by: Robert Hancock hancock@sedsystems.ca --- drivers/watchdog/imx_watchdog.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-)
diff --git a/drivers/watchdog/imx_watchdog.c b/drivers/watchdog/imx_watchdog.c index 05bbfe0..c030360 100644 --- a/drivers/watchdog/imx_watchdog.c +++ b/drivers/watchdog/imx_watchdog.c @@ -15,15 +15,23 @@ #endif #include <fsl_wdog.h>
-static void imx_watchdog_expire_now(struct watchdog_regs *wdog) +static void imx_watchdog_expire_now(struct watchdog_regs *wdog, bool ext_reset) { - clrsetbits_le16(&wdog->wcr, WCR_WT_MSK, WCR_WDE); + u16 wcr = WCR_WDE; + + if (ext_reset) + wcr |= WCR_SRS; /* do not assert internal reset */ + else + wcr |= WCR_WDA; /* do not assert external reset */ + + /* Write 3 times to ensure it works, due to IMX6Q errata ERR004346 */ + writew(wcr, &wdog->wcr); + writew(wcr, &wdog->wcr); + writew(wcr, &wdog->wcr);
- writew(0x5555, &wdog->wsr); - writew(0xaaaa, &wdog->wsr); /* load minimum 1/2 second timeout */ while (1) { /* - * spin for .5 seconds before reset + * spin before reset */ } } @@ -34,7 +42,7 @@ void __attribute__((weak)) reset_cpu(ulong addr) { struct watchdog_regs *wdog = (struct watchdog_regs *)WDOG1_BASE_ADDR;
- imx_watchdog_expire_now(wdog); + imx_watchdog_expire_now(wdog, true); } #endif
@@ -106,7 +114,7 @@ static int imx_wdt_expire_now(struct udevice *dev, ulong flags) { struct imx_wdt_priv *priv = dev_get_priv(dev);
- imx_watchdog_expire_now(priv->base); + imx_watchdog_expire_now(priv->base, priv->ext_reset); hang();
return 0;

The expire_now function was previously setting the watchdog timeout to minimum and waiting for the watchdog to expire. However, this watchdog also has bits to trigger immediate reset. Use those instead, like the Linux imx2_wdt driver does. Signed-off-by: Robert Hancock hancock@sedsystems.ca
Applied to u-boot-imx, master, thanks !
Best regards, Stefano Babic
participants (4)
-
Fabio Estevam
-
Marek Vasut
-
Robert Hancock
-
sbabic@denx.de