From 1fc45d6483d77b9fbe84e546f4e6afe665ba827a Mon Sep 17 00:00:00 2001 From: Paul Doelle Date: Mon, 4 Jul 2022 09:00:25 +0000 Subject: watchdog: add pulse support to gpio watchdog driver A common external watchdog circuit is kept alive by triggering a short pulse on the reset pin. This patch adds support for this use case, while making the algorithm configurable in the devicetree. The "linux,wdt-gpio" driver being modified is based off the equivalent driver in the Linux kernel, which provides support for this algorithm. This patch brings parity to this driver, and is kept aligned with the functionality and devicetree configuration in the kernel. It should be noted that this adds a required property named 'hw_algo' to the devicetree binding, following suit with the kernel. I'm happy to make this backward-compatible if preferred. Signed-off-by: Paul Doelle Reviewed-by: Stefan Roese --- drivers/watchdog/gpio_wdt.c | 40 ++++++++++++++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/watchdog/gpio_wdt.c b/drivers/watchdog/gpio_wdt.c index 982a66b3f9d..fe06ec8cc90 100644 --- a/drivers/watchdog/gpio_wdt.c +++ b/drivers/watchdog/gpio_wdt.c @@ -4,20 +4,38 @@ #include #include #include +#include + +enum { + HW_ALGO_TOGGLE, + HW_ALGO_LEVEL, +}; struct gpio_wdt_priv { - struct gpio_desc gpio; - bool always_running; - int state; + struct gpio_desc gpio; + unsigned int hw_algo; + bool always_running; + int state; }; static int gpio_wdt_reset(struct udevice *dev) { struct gpio_wdt_priv *priv = dev_get_priv(dev); - priv->state = !priv->state; - - return dm_gpio_set_value(&priv->gpio, priv->state); + switch (priv->hw_algo) { + case HW_ALGO_TOGGLE: + /* Toggle output pin */ + priv->state = !priv->state; + dm_gpio_set_value(&priv->gpio, priv->state); + break; + case HW_ALGO_LEVEL: + /* Pulse */ + dm_gpio_set_value(&priv->gpio, 1); + udelay(1); + dm_gpio_set_value(&priv->gpio, 0); + break; + } + return 0; } static int gpio_wdt_start(struct udevice *dev, u64 timeout, ulong flags) @@ -34,6 +52,16 @@ static int dm_probe(struct udevice *dev) { struct gpio_wdt_priv *priv = dev_get_priv(dev); int ret; + const char *algo = dev_read_string(dev, "hw_algo"); + + if (!algo) + return -EINVAL; + if (!strcmp(algo, "toggle")) + priv->hw_algo = HW_ALGO_TOGGLE; + else if (!strcmp(algo, "level")) + priv->hw_algo = HW_ALGO_LEVEL; + else + return -EINVAL; priv->always_running = dev_read_bool(dev, "always-running"); ret = gpio_request_by_name(dev, "gpios", 0, &priv->gpio, GPIOD_IS_OUT); -- cgit v1.3.1