[U-Boot] [PATCH] driver: watchdog: Add new iMX/LSCH2 WDT driver

Robert Hancock hancock at sedsystems.ca
Wed Jun 19 15:41:22 UTC 2019


On 2019-06-18 11:32 p.m., Stefan Roese wrote:
> Hi Robert,
> 
> (Cc'ing Marek and Heiko)
> 
> On 18.06.19 17:52, Robert Hancock wrote:
>> This is a new watchdog timer driver for iMX and LSCH2 using the WDT
>> framework and driver model. This allows ensuring that U-Boot uses the
>> same watchdog timer instance and same settings (ex: internal or external
>> reset) specified in the device tree.
>>
>> This driver can be used in preference to the old imx_watchdog driver for
>> boards which have been converted to use the driver model.
>>
>> Signed-off-by: Robert Hancock <hancock at sedsystems.ca>
> 
> Marek just recently added DM (WDT) support to the imx driver:
> 
> https://patchwork.ozlabs.org/patch/1112591/
> https://patchwork.ozlabs.org/patch/1112592/
> 
> Please take a look at this driver.

It looks like that may be a better base for this support. There are a
few things in my version that are still missing in the existing imx
driver such as the external reset output handling and the better
immediate reset handling, but if Marek's patch is being accepted I can
implement that support on top of those changes.

> 
> Thanks,
> Stefan
> 
>> ---
>>   drivers/watchdog/Kconfig   |  14 ++++--
>>   drivers/watchdog/Makefile  |   3 ++
>>   drivers/watchdog/imx_wdt.c | 112
>> +++++++++++++++++++++++++++++++++++++++++++++
>>   3 files changed, 126 insertions(+), 3 deletions(-)
>>   create mode 100644 drivers/watchdog/imx_wdt.c
>>
>> diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
>> index dbafb74..0e8c8e5 100644
>> --- a/drivers/watchdog/Kconfig
>> +++ b/drivers/watchdog/Kconfig
>> @@ -27,11 +27,11 @@ config BCM2835_WDT
>>         hardware, with a max timeout of ~15secs.
>>     config IMX_WATCHDOG
>> -    bool "Enable Watchdog Timer support for IMX and LSCH2 of NXP"
>> +    bool "Enable legacy Watchdog Timer support for IMX and LSCH2 of NXP"
>>       select HW_WATCHDOG
>>       help
>> -       Select this to enable the IMX and LSCH2 of Layerscape watchdog
>> -       driver.
>> +       Select this to enable the IMX and LSCH2 of Layerscape legacy
>> watchdog
>> +       driver (not using driver model).
>>     config OMAP_WATCHDOG
>>       bool "TI OMAP watchdog driver"
>> @@ -109,6 +109,14 @@ config WDT_CDNS
>>          Select this to enable Cadence watchdog timer, which can be
>> found on some
>>          Xilinx Microzed Platform.
>>   +config WDT_IMX
>> +    bool "iMX/LSCH2 watchdog timer support"
>> +    depends on WDT && (ARCH_MX25 || ARCH_MX31 || ARCH_MX35 ||
>> ARCH_MX5 || ARCH_MX6 || ARCH_MX7 || ARCH_VF610)
>> +    imply WATCHDOG
>> +    help
>> +       Select this to enable the IMX and LSCH2 of Layerscape watchdog
>> +       driver using driver model.
>> +
>>   config WDT_MPC8xx
>>       bool "MPC8xx watchdog timer support"
>>       depends on WDT && MPC8xx
>> diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
>> index e3f4fdb..49dd457 100644
>> --- a/drivers/watchdog/Makefile
>> +++ b/drivers/watchdog/Makefile
>> @@ -5,11 +5,13 @@
>>     obj-$(CONFIG_WDT_AT91) += at91sam9_wdt.o
>>   obj-$(CONFIG_FTWDT010_WATCHDOG) += ftwdt010_wdt.o
>> +ifndef CONFIG_WDT_IMX
>>   ifneq (,$(filter $(SOC), mx25 mx31 mx35 mx5 mx6 mx7 vf610))
>>   obj-y += imx_watchdog.o
>>   else
>>   obj-$(CONFIG_IMX_WATCHDOG) += imx_watchdog.o
>>   endif
>> +endif
>>   obj-$(CONFIG_S5P)               += s5p_wdt.o
>>   obj-$(CONFIG_XILINX_TB_WATCHDOG) += xilinx_tb_wdt.o
>>   obj-$(CONFIG_OMAP_WATCHDOG) += omap_wdt.o
>> @@ -24,6 +26,7 @@ obj-$(CONFIG_WDT_BCM6345) += bcm6345_wdt.o
>>   obj-$(CONFIG_BCM2835_WDT)       += bcm2835_wdt.o
>>   obj-$(CONFIG_WDT_ORION) += orion_wdt.o
>>   obj-$(CONFIG_WDT_CDNS) += cdns_wdt.o
>> +obj-$(CONFIG_WDT_IMX) += imx_wdt.o
>>   obj-$(CONFIG_WDT_MPC8xx) += mpc8xx_wdt.o
>>   obj-$(CONFIG_WDT_MT7621) += mt7621_wdt.o
>>   obj-$(CONFIG_WDT_MTK) += mtk_wdt.o
>> diff --git a/drivers/watchdog/imx_wdt.c b/drivers/watchdog/imx_wdt.c
>> new file mode 100644
>> index 0000000..1b4a5e6
>> --- /dev/null
>> +++ b/drivers/watchdog/imx_wdt.c
>> @@ -0,0 +1,112 @@
>> +// SPDX-License-Identifier: GPL-2.0+
>> +/*
>> + * imx_wdt.c - WDT driver for Freescale/NXP i.MX on-chip watchdog
>> + * Copyright (c) 2019 SED Systems, a division of Calian Ltd.
>> + *
>> + * Based on Linux 4.19 drivers/watchdog/imx2_wdt.c which is:
>> + *  Copyright (C) 2010 Wolfram Sang, Pengutronix e.K.
>> <w.sang at pengutronix.de>
>> + *  Copyright (C) 2014 Freescale Semiconductor, Inc.
>> + *
>> + */
>> +
>> +#include <common.h>
>> +#include <dm.h>
>> +#include <errno.h>
>> +#include <wdt.h>
>> +#include <asm/io.h>
>> +#include <asm/arch/imx-regs.h>
>> +#include <fsl_wdog.h>
>> +
>> +struct imx_wdt_priv {
>> +    struct watchdog_regs *regs;
>> +    bool ext_reset;
>> +};
>> +
>> +static int imx_wdt_start(struct udevice *dev, u64 timeout, ulong flags)
>> +{
>> +    struct imx_wdt_priv *priv = dev_get_priv(dev);
>> +    u16 timeout_reg = (timeout / 500) - 1;
>> +    u16 wcr = WCR_WDZST | WCR_WDBG | WCR_WDE | WCR_SRS |
>> +          WCR_WDA | SET_WCR_WT(timeout_reg);
>> +
>> +    if (priv->ext_reset)
>> +        wcr |= WCR_WDT;
>> +
>> +    debug("%s timeout %llu, wcr %04hX\n", __func__, timeout, wcr);
>> +
>> +    writew(wcr, &priv->regs->wcr);
>> +
>> +    return 0;
>> +}
>> +
>> +static int imx_wdt_reset(struct udevice *dev)
>> +{
>> +    struct imx_wdt_priv *priv = dev_get_priv(dev);
>> +
>> +    writew(0x5555, &priv->regs->wsr);
>> +    writew(0xaaaa, &priv->regs->wsr);
>> +    return 0;
>> +}
>> +
>> +static int imx_wdt_expire_now(struct udevice *dev, ulong flags)
>> +{
>> +    struct imx_wdt_priv *priv = dev_get_priv(dev);
>> +    u16 wcr = WCR_WDE;
>> +
>> +    if (priv->ext_reset)
>> +        wcr |= WCR_SRS; /* do not assert internal reset */
>> +    else
>> +        wcr |= WCR_WDA; /* do not assert external reset */
>> +
>> +    debug("%s wcr %04hX\n", __func__, wcr);
>> +
>> +    /* Write 3 times to ensure it works, due to IMX6Q errata
>> ERR004346 */
>> +    writew(wcr, &priv->regs->wcr);
>> +    writew(wcr, &priv->regs->wcr);
>> +    writew(wcr, &priv->regs->wcr);
>> +
>> +    return 0;
>> +}
>> +
>> +static int imx_wdt_ofdata_to_platdata(struct udevice *dev)
>> +{
>> +    struct imx_wdt_priv *priv = dev_get_priv(dev);
>> +
>> +    priv->regs = devfdt_get_addr_ptr(dev);
>> +    if (IS_ERR(priv->regs))
>> +        return PTR_ERR(priv->regs);
>> +
>> +    priv->ext_reset = dev_read_bool(dev, "fsl,ext-reset-output");
>> +
>> +    debug("%s: ext_reset %d\n", __func__, (int)priv->ext_reset);
>> +    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",  },
>> +    {}
>> +};
>> +
>> +static int imx_wdt_probe(struct udevice *dev)
>> +{
>> +    debug("%s() wdt%u\n", __func__, dev->seq);
>> +
>> +    return 0;
>> +}
>> +
>> +U_BOOT_DRIVER(imx_wdt) = {
>> +    .name = "imx_wdt",
>> +    .id = UCLASS_WDT,
>> +    .of_match = imx_wdt_ids,
>> +    .probe = imx_wdt_probe,
>> +    .priv_auto_alloc_size = sizeof(struct imx_wdt_priv),
>> +    .ofdata_to_platdata = imx_wdt_ofdata_to_platdata,
>> +    .ops = &imx_wdt_ops,
>> +    .flags = DM_FLAG_PRE_RELOC,
>> +};
>>
> 
> Viele Grüße,
> Stefan
> 

-- 
Robert Hancock
Senior Software Developer
SED Systems, a division of Calian Ltd.
Email: hancock at sedsystems.ca


More information about the U-Boot mailing list