[PATCH v2] watchdog: add amlogic watchdog support

Stefan Roese sr at denx.de
Fri Jun 24 12:20:53 CEST 2022


Hi Neil,

On 21.06.22 11:17, Neil Armstrong wrote:
> Hi Stefan,
> 
> On 20/06/2022 16:55, Stefan Roese wrote:
>> On 13.06.22 16:00, Philippe Boos wrote:
>>> Add support for hardware watchdog timer for Amlogic SoCs.
>>> This driver has been heavily inspired by his Linux equivalent
>>> (meson_gxbb_wdt.c).
>>>
>>> Reviewed-by: Jerome Brunet <jbrunet at baylibre.com>
>>> Reviewed-by: Neil Armstrong <narmstrong at baylibre.com>
>>>
>>> Signed-off-by: Philippe Boos <pboos at baylibre.com>
>>>
>>
>> Reviewed-by: Stefan Roese <sr at denx.de>
> 
> Should I take it into my tree ?

I would have pushed it via my watchdog tree, after the merge-window has
been opened. But you can also push it via your tree, if you have some
dependencies or prefer this somehow. Feel free, to handle this in the
way you prefer. ;)

Thanks,
Stefan

> Thanks,
> Neil
> 
>>
>> Thanks,
>> Stefan
>>
>>> ---
>>>
>>> Your recommendations have been implemented. I let you check this 
>>> version 2.
>>> The reset works well when triggered by the wdt command in u-boot.
>>>
>>> This watchdog driver has been tested on a GXL libretech-cc board and 
>>> also on
>>> a custom G12a board. I did the following test cases:
>>>   * boot with a faulty boot command, then we reach watchdog reset 
>>> successfully,
>>>   * boot a Linux kernel with and without watchdog support, and check 
>>> if it is
>>>     working as expected.
>>>
>>>
>>>   MAINTAINERS                       |   1 +
>>>   doc/board/amlogic/index.rst       |   2 +
>>>   drivers/watchdog/Kconfig          |   7 ++
>>>   drivers/watchdog/Makefile         |   1 +
>>>   drivers/watchdog/meson_gxbb_wdt.c | 136 ++++++++++++++++++++++++++++++
>>>   5 files changed, 147 insertions(+)
>>>   create mode 100644 drivers/watchdog/meson_gxbb_wdt.c
>>>
>>> diff --git a/MAINTAINERS b/MAINTAINERS
>>> index 28e4d38238..ab3ef041f7 100644
>>> --- a/MAINTAINERS
>>> +++ b/MAINTAINERS
>>> @@ -160,6 +160,7 @@ F:    drivers/spi/meson_spifc.c
>>>   F:    drivers/pinctrl/meson/
>>>   F:    drivers/power/domain/meson-gx-pwrc-vpu.c
>>>   F:    drivers/video/meson/
>>> +F:    drivers/watchdog/meson_gxbb_wdt.c
>>>   F:    include/configs/meson64.h
>>>   F:    include/configs/meson64_android.h
>>>   F:    doc/board/amlogic/
>>> diff --git a/doc/board/amlogic/index.rst b/doc/board/amlogic/index.rst
>>> index 9c7fadf2c0..cc2ba50889 100644
>>> --- a/doc/board/amlogic/index.rst
>>> +++ b/doc/board/amlogic/index.rst
>>> @@ -73,6 +73,8 @@ This matrix concerns the actual source code version.
>>>   
>>> +-------------------------------+-----------+-----------------+--------------+-------------+------------+-------------+--------------+ 
>>>
>>>   | PCIe (+NVMe)                  | *N/A*     | *N/A*           | 
>>> *N/A*        | **Yes**     | **Yes**    | **Yes**     | **Yes**      |
>>>   
>>> +-------------------------------+-----------+-----------------+--------------+-------------+------------+-------------+--------------+ 
>>>
>>> +| Watchdog                      | *N/A*     | **Yes**         | 
>>> *N/A*        | *N/A*       | *N/A*      | *N/A*       | *N/A*        |
>>> ++-------------------------------+-----------+-----------------+--------------+-------------+------------+-------------+--------------+ 
>>>
>>>   Boot Documentation
>>>   ------------------
>>> diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
>>> index c3eb8a8aec..da0fa5396f 100644
>>> --- a/drivers/watchdog/Kconfig
>>> +++ b/drivers/watchdog/Kconfig
>>> @@ -175,6 +175,13 @@ config WDT_MAX6370
>>>       help
>>>         Select this to enable max6370 watchdog timer.
>>> +config WDT_MESON_GXBB
>>> +    bool "Amlogic watchdog timer support"
>>> +    depends on WDT
>>> +    help
>>> +      Select this to enable Meson watchdog timer,
>>> +      which can be found on some Amlogic platforms.
>>> +
>>>   config WDT_MPC8xx
>>>       bool "MPC8xx watchdog timer support"
>>>       depends on WDT && MPC8xx
>>> diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
>>> index 1f6199beca..0e2f582a5f 100644
>>> --- a/drivers/watchdog/Makefile
>>> +++ b/drivers/watchdog/Makefile
>>> @@ -27,6 +27,7 @@ obj-$(CONFIG_WDT_ORION) += orion_wdt.o
>>>   obj-$(CONFIG_WDT_CDNS) += cdns_wdt.o
>>>   obj-$(CONFIG_WDT_GPIO) += gpio_wdt.o
>>>   obj-$(CONFIG_WDT_MAX6370) += max6370_wdt.o
>>> +obj-$(CONFIG_WDT_MESON_GXBB) += meson_gxbb_wdt.o
>>>   obj-$(CONFIG_WDT_MPC8xx) += mpc8xx_wdt.o
>>>   obj-$(CONFIG_WDT_MT7620) += mt7620_wdt.o
>>>   obj-$(CONFIG_WDT_MT7621) += mt7621_wdt.o
>>> diff --git a/drivers/watchdog/meson_gxbb_wdt.c 
>>> b/drivers/watchdog/meson_gxbb_wdt.c
>>> new file mode 100644
>>> index 0000000000..6ab005813f
>>> --- /dev/null
>>> +++ b/drivers/watchdog/meson_gxbb_wdt.c
>>> @@ -0,0 +1,136 @@
>>> +// SPDX-License-Identifier: GPL-2.0+
>>> +/*
>>> + * Copyright (c) 2022 BayLibre, SAS.
>>> + */
>>> +
>>> +#include <clk.h>
>>> +#include <dm.h>
>>> +#include <dm/device_compat.h>
>>> +#include <reset.h>
>>> +#include <wdt.h>
>>> +#include <asm/io.h>
>>> +#include <linux/bitops.h>
>>> +
>>> +#define GXBB_WDT_CTRL_REG            0x0
>>> +#define GXBB_WDT_TCNT_REG            0x8
>>> +#define GXBB_WDT_RSET_REG            0xc
>>> +
>>> +#define GXBB_WDT_CTRL_SYS_RESET_NOW        BIT(26)
>>> +#define GXBB_WDT_CTRL_CLKDIV_EN            BIT(25)
>>> +#define GXBB_WDT_CTRL_CLK_EN            BIT(24)
>>> +#define GXBB_WDT_CTRL_EE_RESET            BIT(21)
>>> +#define GXBB_WDT_CTRL_EN            BIT(18)
>>> +
>>> +#define GXBB_WDT_CTRL_DIV_MASK            GENMASK(17, 0)
>>> +#define GXBB_WDT_TCNT_SETUP_MASK        GENMASK(15, 0)
>>> +
>>> +
>>> +struct amlogic_wdt_priv {
>>> +    void __iomem *reg_base;
>>> +};
>>> +
>>> +static int amlogic_wdt_set_timeout(struct udevice *dev, u64 timeout_ms)
>>> +{
>>> +    struct amlogic_wdt_priv *data = dev_get_priv(dev);
>>> +
>>> +    if (timeout_ms > GXBB_WDT_TCNT_SETUP_MASK) {
>>> +        dev_warn(dev, "%s: timeout_ms=%llu: maximum watchdog timeout 
>>> exceeded\n",
>>> +                 __func__, timeout_ms);
>>> +        timeout_ms = GXBB_WDT_TCNT_SETUP_MASK;
>>> +    }
>>> +
>>> +    writel(timeout_ms, data->reg_base + GXBB_WDT_TCNT_REG);
>>> +
>>> +    return 0;
>>> +}
>>> +
>>> +static int amlogic_wdt_stop(struct udevice *dev)
>>> +{
>>> +    struct amlogic_wdt_priv *data = dev_get_priv(dev);
>>> +
>>> +    writel(readl(data->reg_base + GXBB_WDT_CTRL_REG) & 
>>> ~GXBB_WDT_CTRL_EN,
>>> +           data->reg_base + GXBB_WDT_CTRL_REG);
>>> +
>>> +    return 0;
>>> +}
>>> +
>>> +static int amlogic_wdt_start(struct udevice *dev, u64 time_ms, ulong 
>>> flags)
>>> +{
>>> +    struct amlogic_wdt_priv *data = dev_get_priv(dev);
>>> +
>>> +    writel(readl(data->reg_base + GXBB_WDT_CTRL_REG) | 
>>> GXBB_WDT_CTRL_EN,
>>> +           data->reg_base + GXBB_WDT_CTRL_REG);
>>> +
>>> +    return amlogic_wdt_set_timeout(dev, time_ms);
>>> +}
>>> +
>>> +static int amlogic_wdt_reset(struct udevice *dev)
>>> +{
>>> +    struct amlogic_wdt_priv *data = dev_get_priv(dev);
>>> +
>>> +    writel(0, data->reg_base + GXBB_WDT_RSET_REG);
>>> +
>>> +    return 0;
>>> +}
>>> +
>>> +static int amlogic_wdt_expire_now(struct udevice *dev, ulong flags)
>>> +{
>>> +    struct amlogic_wdt_priv *data = dev_get_priv(dev);
>>> +
>>> +    writel(0, data->reg_base + GXBB_WDT_CTRL_SYS_RESET_NOW);
>>> +
>>> +    return 0;
>>> +}
>>> +
>>> +static int amlogic_wdt_probe(struct udevice *dev)
>>> +{
>>> +    struct amlogic_wdt_priv *data = dev_get_priv(dev);
>>> +    int ret;
>>> +
>>> +    data->reg_base = dev_remap_addr(dev);
>>> +    if (!data->reg_base)
>>> +        return -EINVAL;
>>> +
>>> +    struct clk clk;
>>> +
>>> +    ret = clk_get_by_index(dev, 0, &clk);
>>> +    if (ret)
>>> +        return ret;
>>> +
>>> +    ret = clk_enable(&clk);
>>> +    if (ret) {
>>> +        clk_free(&clk);
>>> +        return ret;
>>> +    }
>>> +
>>> +    /* Setup with 1ms timebase */
>>> +    writel(((clk_get_rate(&clk) / 1000) & GXBB_WDT_CTRL_DIV_MASK) |
>>> +           GXBB_WDT_CTRL_EE_RESET |
>>> +           GXBB_WDT_CTRL_CLK_EN |
>>> +           GXBB_WDT_CTRL_CLKDIV_EN,
>>> +           data->reg_base + GXBB_WDT_CTRL_REG);
>>> +
>>> +    return 0;
>>> +}
>>> +
>>> +static const struct wdt_ops amlogic_wdt_ops = {
>>> +    .start = amlogic_wdt_start,
>>> +    .reset = amlogic_wdt_reset,
>>> +    .stop = amlogic_wdt_stop,
>>> +    .expire_now = amlogic_wdt_expire_now,
>>> +};
>>> +
>>> +static const struct udevice_id amlogic_wdt_ids[] = {
>>> +    { .compatible = "amlogic,meson-gxbb-wdt" },
>>> +    {}
>>> +};
>>> +
>>> +U_BOOT_DRIVER(amlogic_wdt) = {
>>> +    .name = "amlogic_wdt",
>>> +    .id = UCLASS_WDT,
>>> +    .of_match = amlogic_wdt_ids,
>>> +    .priv_auto = sizeof(struct amlogic_wdt_priv),
>>> +    .probe = amlogic_wdt_probe,
>>> +    .ops = &amlogic_wdt_ops,
>>> +    .flags = DM_FLAG_PRE_RELOC,
>>> +};
>>
>> Viele Grüße,
>> Stefan Roese
>>
> 

Viele Grüße,
Stefan Roese

-- 
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-51 Fax: (+49)-8142-66989-80 Email: sr at denx.de


More information about the U-Boot mailing list