On Sun, 12 May 2019 23:34:53 +0200 Marek Vasut <ma...@denx.de> wrote:
> Add DM and DT probing support to iMX watchdog driver. This should > allow boards to move over to this driver, enable SYSRESET_WATCHDOG > to handle cpu_reset() if required. > > Signed-off-by: Marek Vasut <ma...@denx.de> > Cc: Peng Fan <peng....@freescale.com> > Cc: Stefano Babic <sba...@denx.de> > --- > drivers/watchdog/Kconfig | 2 +- > drivers/watchdog/imx_watchdog.c | 119 > +++++++++++++++++++++++++++----- 2 files changed, 104 insertions(+), > 17 deletions(-) > > diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig > index f909d40f45..b2ebe528ab 100644 > --- a/drivers/watchdog/Kconfig > +++ b/drivers/watchdog/Kconfig > @@ -129,7 +129,7 @@ config XILINX_TB_WATCHDOG > > config IMX_WATCHDOG > bool "Enable Watchdog Timer support for IMX and LSCH2 of NXP" > - select HW_WATCHDOG > + select HW_WATCHDOG if !WDT > help > Select this to enable the IMX and LSCH2 of Layerscape > watchdog driver. > diff --git a/drivers/watchdog/imx_watchdog.c > b/drivers/watchdog/imx_watchdog.c index 14cc618074..53a3e9f5c7 100644 > --- a/drivers/watchdog/imx_watchdog.c > +++ b/drivers/watchdog/imx_watchdog.c > @@ -5,7 +5,9 @@ > */ > > #include <common.h> > +#include <dm.h> > #include <asm/io.h> > +#include <wdt.h> > #include <watchdog.h> > #include <asm/arch/imx-regs.h> > #ifdef CONFIG_FSL_LSCH2 > @@ -13,20 +15,40 @@ > #endif > #include <fsl_wdog.h> > > -#ifdef CONFIG_IMX_WATCHDOG > -void hw_watchdog_reset(void) > +static void imx_watchdog_expire_now(struct watchdog_regs *wdog) > +{ > + clrsetbits_le16(&wdog->wcr, WCR_WT_MSK, WCR_WDE); > + > + writew(0x5555, &wdog->wsr); > + writew(0xaaaa, &wdog->wsr); /* load minimum 1/2 > second timeout */ > + while (1) { > + /* > + * spin for .5 seconds before reset > + */ > + } > +} > + > +#if !defined(CONFIG_IMX_WATCHDOG) || \ > + (defined(CONFIG_IMX_WATCHDOG) && !CONFIG_IS_ENABLED(WDT)) > +void __attribute__((weak)) reset_cpu(ulong addr) > { > -#ifndef CONFIG_WATCHDOG_RESET_DISABLE > struct watchdog_regs *wdog = (struct watchdog_regs > *)WDOG1_BASE_ADDR; > + imx_watchdog_expire_now(wdog); > +} > +#endif > + > +#if defined(CONFIG_IMX_WATCHDOG) > +static void imx_watchdog_reset(struct watchdog_regs *wdog) > +{ > +#ifndef CONFIG_WATCHDOG_RESET_DISABLE > writew(0x5555, &wdog->wsr); > writew(0xaaaa, &wdog->wsr); > #endif /* CONFIG_WATCHDOG_RESET_DISABLE*/ > } > > -void hw_watchdog_init(void) > +static void imx_watchdog_init(struct watchdog_regs *wdog) > { > - struct watchdog_regs *wdog = (struct watchdog_regs > *)WDOG1_BASE_ADDR; u16 timeout; > > /* > @@ -44,21 +66,86 @@ void hw_watchdog_init(void) > writew(WCR_WDZST | WCR_WDBG | WCR_WDE | WCR_WDT | WCR_SRS | > WCR_WDA | SET_WCR_WT(timeout), &wdog->wcr); > #endif /* CONFIG_FSL_LSCH2*/ > - hw_watchdog_reset(); > + imx_watchdog_reset(wdog); > } > -#endif > > -void __attribute__((weak)) reset_cpu(ulong addr) > +#if !CONFIG_IS_ENABLED(WDT) > +void hw_watchdog_reset(void) > { > struct watchdog_regs *wdog = (struct watchdog_regs > *)WDOG1_BASE_ADDR; > - clrsetbits_le16(&wdog->wcr, WCR_WT_MSK, WCR_WDE); > + imx_watchdog_reset(wdog); > +} > > - writew(0x5555, &wdog->wsr); > - writew(0xaaaa, &wdog->wsr); /* load minimum 1/2 > second timeout */ > - while (1) { > - /* > - * spin for .5 seconds before reset > - */ > - } > +void hw_watchdog_init(void) > +{ > + struct watchdog_regs *wdog = (struct watchdog_regs > *)WDOG1_BASE_ADDR; + > + imx_watchdog_init(wdog); > +} > +#else > +struct imx_wdt_priv { > + void __iomem *base; > +}; > + > +static int imx_wdt_reset(struct udevice *dev) > +{ > + struct imx_wdt_priv *priv = dev_get_priv(dev); > + > + imx_watchdog_reset(priv->base); > + > + return 0; > +} > + > +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); > + hang(); > + > + return 0; > +} > + > +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); > + > + return 0; > +} > + > +static int imx_wdt_probe(struct udevice *dev) > +{ > + struct imx_wdt_priv *priv = dev_get_priv(dev); > + > + priv->base = dev_read_addr_ptr(dev); > + if (!priv->base) > + return -ENOENT; > + > + return 0; > } > + > +static const struct wdt_ops imx_wdt_ops = { > + .start = imx_wdt_start, > + .reset = imx_wdt_reset, > + .expire_now = imx_wdt_expire_now, > +}; > + > +static const struct udevice_id imx_wdt_ids[] = { > + { .compatible = "fsl,imx21-wdt" }, > + {} > +}; > + > +U_BOOT_DRIVER(imx_wdt) = { > + .name = "imx_wdt", > + .id = UCLASS_WDT, > + .of_match = imx_wdt_ids, > + .probe = imx_wdt_probe, > + .ops = &imx_wdt_ops, > + .priv_auto_alloc_size = sizeof(struct imx_wdt_priv), > + .flags = DM_FLAG_PRE_RELOC, > +}; > +#endif > +#endif Tested-by: Lukasz Majewski <lu...@denx.de> Test-HW: i.MX6Q - display5 For the record - one needs to add following code to dts file: + wdt-reboot { + compatible = "wdt-reboot"; + wdt = <&wdog1>; + }; @ _defconfig: +CONFIG_SYSRESET=y +CONFIG_SYSRESET_WATCHDOG=y @ include/<board_config>.h +#if defined(CONFIG_SPL_BUILD) +#undef CONFIG_WDT +#undef CONFIG_WATCHDOG +#define CONFIG_HW_WATCHDOG +#endif Best regards, Lukasz Majewski -- DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lu...@denx.de
pgpvyShXW8YFq.pgp
Description: OpenPGP digital signature
_______________________________________________ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot