[U-Boot] [PATCH v2 3/3] watchdog: Convert Xilinx Axi watchdog driver to driver model

Simon Glass sjg at chromium.org
Thu Jul 19 01:31:51 UTC 2018


Hi Shreenidhi,

On 14 July 2018 at 14:35, Shreenidhi Shedi <yesshedi at gmail.com> wrote:
> Xilinx Axi wdt driver conversion to driver model & Kconfig update
> for the same.
>
> Changes in V1:
>  - Xilinx Axi wdt driver conversion to DM initial version
>
> Changes in V2:
>  - Rectified print message
>  - Removed  stop instruction from probe
>
> Signed-off-by: Shreenidhi Shedi <yesshedi at gmail.com>
> ---
>
> Changes in v2: None
>
>  drivers/watchdog/Kconfig         |   8 +++
>  drivers/watchdog/xilinx_tb_wdt.c | 105 ++++++++++++++++++++++++-------
>  2 files changed, 89 insertions(+), 24 deletions(-)
>
> diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
> index 148c6a0d68..351d2af8d9 100644
> --- a/drivers/watchdog/Kconfig
> +++ b/drivers/watchdog/Kconfig
> @@ -103,4 +103,12 @@ config WDT_CDNS
>            Select this to enable Cadence watchdog timer, which can be found on some
>            Xilinx Microzed Platform.
>
> +config XILINX_TB_WATCHDOG
> +       bool "Xilinx Axi watchdog timer support"
> +       depends on WDT
> +       imply WATCHDOG
> +       help
> +          Select this to enable Xilinx Axi watchdog timer, which can be found on some
> +          Xilinx Microblaze Platform.

platforms?

> +
>  endmenu
> diff --git a/drivers/watchdog/xilinx_tb_wdt.c b/drivers/watchdog/xilinx_tb_wdt.c
> index 2274123e49..23ddbdfbee 100644
> --- a/drivers/watchdog/xilinx_tb_wdt.c
> +++ b/drivers/watchdog/xilinx_tb_wdt.c
> @@ -1,13 +1,17 @@
>  // SPDX-License-Identifier: GPL-2.0+
>  /*
> + * Xilinx Axi platforms watchdog timer driver.
> + *
> + * Author(s):  Michal Šimek <michal.simek at xilinx.com>
> + *             Shreenidhi Shedi <yesshedi at gmail.com>
> + *
>   * Copyright (c) 2011-2013 Xilinx Inc.
>   */
>
>  #include <common.h>
> -#include <asm/io.h>
> -#include <asm/microblaze_intc.h>
> -#include <asm/processor.h>
> -#include <watchdog.h>
> +#include <dm.h>
> +#include <wdt.h>
> +#include <linux/io.h>
>
>  #define XWT_CSR0_WRS_MASK      0x00000008 /* Reset status Mask */
>  #define XWT_CSR0_WDS_MASK      0x00000004 /* Timer state Mask */
> @@ -20,49 +24,102 @@ struct watchdog_regs {
>         u32 tbr; /* 0x8 */
>  };
>
> -static struct watchdog_regs *watchdog_base =
> -                       (struct watchdog_regs *)CONFIG_WATCHDOG_BASEADDR;
> +struct xlnx_wdt_priv {
> +       bool enable_once;
> +       struct watchdog_regs *regs;
> +};
>
> -void hw_watchdog_reset(void)
> +static int xlnx_wdt_reset(struct udevice *dev)

You could pass just regs to this function? Same below.

>  {
>         u32 reg;
> +       struct xlnx_wdt_priv *priv = dev_get_priv(dev);
> +
> +       debug("%s\n", __func__);
>
>         /* Read the current contents of TCSR0 */
> -       reg = readl(&watchdog_base->twcsr0);
> +       reg = readl(&priv->regs->twcsr0);
>
>         /* Clear the watchdog WDS bit */
>         if (reg & (XWT_CSR0_EWDT1_MASK | XWT_CSRX_EWDT2_MASK))
> -               writel(reg | XWT_CSR0_WDS_MASK, &watchdog_base->twcsr0);
> +               writel(reg | XWT_CSR0_WDS_MASK, &priv->regs->twcsr0);
> +
> +       return 0;
>  }
>
> -void hw_watchdog_disable(void)
> +static int xlnx_wdt_stop(struct udevice *dev)
>  {
>         u32 reg;
> +       struct xlnx_wdt_priv *priv = dev_get_priv(dev);
> +
> +       if (priv->enable_once) {
> +               puts("Can't stop Xilinx watchdog.\n");

debug()

> +               return -1;

return -EBUSY

-1 is -EPERM which might not be correct.

> +       }
>
>         /* Read the current contents of TCSR0 */
> -       reg = readl(&watchdog_base->twcsr0);
> +       reg = readl(&priv->regs->twcsr0);
>
> -       writel(reg & ~XWT_CSR0_EWDT1_MASK, &watchdog_base->twcsr0);
> -       writel(~XWT_CSRX_EWDT2_MASK, &watchdog_base->twcsr1);
> +       writel(reg & ~XWT_CSR0_EWDT1_MASK, &priv->regs->twcsr0);
> +       writel(~XWT_CSRX_EWDT2_MASK, &priv->regs->twcsr1);
>
>         puts("Watchdog disabled!\n");

Drivers should not output to the console.

> +
> +       return 0;
>  }
>
> -static void hw_watchdog_isr(void *arg)
> +static int xlnx_wdt_start(struct udevice *dev, u64 timeout, ulong flags)
>  {
> -       hw_watchdog_reset();
> +       struct xlnx_wdt_priv *priv = dev_get_priv(dev);
> +
> +       writel((XWT_CSR0_WRS_MASK | XWT_CSR0_WDS_MASK | XWT_CSR0_EWDT1_MASK),
> +              &priv->regs->twcsr0);
> +
> +       writel(XWT_CSRX_EWDT2_MASK, &priv->regs->twcsr1);
> +
> +       return 0;
>  }
>
> -void hw_watchdog_init(void)
> +static int xlnx_wdt_probe(struct udevice *dev)
>  {
> -       int ret;
> +       debug("%s: Probing wdt%u\n", __func__, dev->seq);
>
> -       writel((XWT_CSR0_WRS_MASK | XWT_CSR0_WDS_MASK | XWT_CSR0_EWDT1_MASK),
> -              &watchdog_base->twcsr0);
> -       writel(XWT_CSRX_EWDT2_MASK, &watchdog_base->twcsr1);
> +       return 0;
> +}
>
> -       ret = install_interrupt_handler(CONFIG_WATCHDOG_IRQ,
> -                                               hw_watchdog_isr, NULL);
> -       if (ret)
> -               puts("Watchdog IRQ registration failed.");
> +static int xlnx_wdt_ofdata_to_platdata(struct udevice *dev)
> +{
> +       struct xlnx_wdt_priv *priv = dev_get_priv(dev);
> +
> +       priv->regs = (struct watchdog_regs *)dev_read_addr(dev);
> +       if (IS_ERR(priv->regs))
> +               return PTR_ERR(priv->regs);
> +
> +       priv->enable_once = dev_read_u32_default(dev, "xlnx,wdt-enable-once",
> +                                                0);

Should that not be dev_read_bool()? Does it actually using an integer
to indicate a boolean? Is there a binding file for this?

> +
> +       debug("%s: wdt-enable-once %d\n", __func__, priv->enable_once);
> +
> +       return 0;
>  }
> +
> +static const struct wdt_ops xlnx_wdt_ops = {
> +       .start = xlnx_wdt_start,
> +       .reset = xlnx_wdt_reset,
> +       .stop = xlnx_wdt_stop,
> +};
> +
> +static const struct udevice_id xlnx_wdt_ids[] = {
> +       { .compatible = "xlnx,xps-timebase-wdt-1.00.a", },
> +       { .compatible = "xlnx,xps-timebase-wdt-1.01.a", },
> +       {},
> +};
> +
> +U_BOOT_DRIVER(xlnx_wdt) = {
> +       .name = "xlnx_wdt",
> +       .id = UCLASS_WDT,
> +       .of_match = xlnx_wdt_ids,
> +       .probe = xlnx_wdt_probe,
> +       .priv_auto_alloc_size = sizeof(struct xlnx_wdt_priv),
> +       .ofdata_to_platdata = xlnx_wdt_ofdata_to_platdata,
> +       .ops = &xlnx_wdt_ops,
> +};
> --
> 2.17.1
>

Regards,
Simon


More information about the U-Boot mailing list