From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id BD472C433EF for ; Mon, 4 Jul 2022 13:50:00 +0000 (UTC) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id AD1F583F2F; Mon, 4 Jul 2022 15:49:58 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="OzU5Sbvk"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 543E084307; Mon, 4 Jul 2022 11:01:39 +0200 (CEST) Received: from mail-pg1-x534.google.com (mail-pg1-x534.google.com [IPv6:2607:f8b0:4864:20::534]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 2E44B83F2F for ; Mon, 4 Jul 2022 11:01:36 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=paaull.git@gmail.com Received: by mail-pg1-x534.google.com with SMTP id e132so8375359pgc.5 for ; Mon, 04 Jul 2022 02:01:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=uXJltgNY1SEInPO8VXvFT3HXPKwnEYOPEcsE6E62SU4=; b=OzU5SbvkyOcW0ppK6dlsnAD3AaP7EWXdwfUkYZuBV429iOcavXj1ew0FSwgoRaTkfC btTHb2MiknFwHX2vro3w5Ky1xYBg4R3uOCpTc9vSE/KAlZnvkSKP1JnkQs5EknZnwLzS O8msYpb23xY7H88FMUOkx7QEk8zTjFNDzZu3YpKEIk3wrtOsYVHpeGX8vEU5UuHCqVz2 SLpsRbSqE2/UMHFslzvza3PtSvyUWGH7v/oOjgGjs3o1KQLJyp6d0LnORp9vk4EUTDoU CjzK1SJc/Swc4wVTvxGu9ucr/M/5mZQ//2LlYgDUfgheT4ipI82De5geXY7g8kH2Jky4 rmkA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=uXJltgNY1SEInPO8VXvFT3HXPKwnEYOPEcsE6E62SU4=; b=79Ka8xSW9ynPDq72cXbzwk34oI5ajHhL9aFadoS37Eghrpor+lF8Ls4Be454/ukqT+ puPA4+q+VkD0cnpnQy5OGaEo9yv7Df6DlzXN6dA95XD42eq1Gj3xJgA4FAQyHOZQGqt/ gps/T1Su0LAoTSEJxcdf0TSCKAhQN3KQHvGW3Llsdr7iL0ixY1ensYNNe27V4yDkzjTC AtTH6jZqu7BlFuALvzscrwCMH7xWrQddnsyWOfq2X0V+1KN+H7CBLN7p3J2g89GBusR9 mXfNiQ/3RkW9nCntaFkw+vZkwI+FBGz2FXIi5ZyxYpELm9uMloJqrK/42jWp+FbzM8VT 9UZQ== X-Gm-Message-State: AJIora8mwFKW8jZCOCB+Z5O43gzM3+rkEgAOO5k8pEqOGBK0D0pnbQQ7 x0pxd8OHIkMnzpJjkG9NDTuiXdGdSiTMuA== X-Google-Smtp-Source: AGRyM1uO3fCHGjAtPxGeDE9Aeye04YbW0huCHeVev7KGQE1mhDM3zoPwPCnE6kYJ2HlhahRwZEZZ/g== X-Received: by 2002:a63:d614:0:b0:411:acdb:5c55 with SMTP id q20-20020a63d614000000b00411acdb5c55mr18147342pgg.245.1656925294044; Mon, 04 Jul 2022 02:01:34 -0700 (PDT) Received: from localhost.localdomain (159-196-163-161.9fc4a3.syd.nbn.aussiebb.net. [159.196.163.161]) by smtp.googlemail.com with ESMTPSA id g2-20020a170902934200b001624965d83bsm20399909plp.228.2022.07.04.02.01.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 04 Jul 2022 02:01:33 -0700 (PDT) From: Paul Doelle To: u-boot@lists.denx.de Cc: Paul Doelle Subject: [PATCH] watchdog: add pulse support to gpio watchdog driver Date: Mon, 4 Jul 2022 09:00:25 +0000 Message-Id: <20220704090025.472505-1-paaull.git@gmail.com> X-Mailer: git-send-email 2.25.1 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Mailman-Approved-At: Mon, 04 Jul 2022 15:49:57 +0200 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.6 at phobos.denx.de X-Virus-Status: Clean 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 --- arch/sandbox/dts/test.dts | 11 ++++- .../watchdog/gpio-wdt.txt | 8 +++- drivers/watchdog/gpio_wdt.c | 40 +++++++++++++--- test/dm/wdt.c | 46 ++++++++++++++++--- 4 files changed, 90 insertions(+), 15 deletions(-) diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index 8f93775ff4..4dc591d995 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -830,10 +830,19 @@ }; }; - gpio-wdt { + wdt-gpio-toggle { gpios = <&gpio_a 7 0>; compatible = "linux,wdt-gpio"; hw_margin_ms = <100>; + hw_algo = "toggle"; + always-running; + }; + + wdt-gpio-level { + gpios = <&gpio_a 7 0>; + compatible = "linux,wdt-gpio"; + hw_margin_ms = <100>; + hw_algo = "level"; always-running; }; diff --git a/doc/device-tree-bindings/watchdog/gpio-wdt.txt b/doc/device-tree-bindings/watchdog/gpio-wdt.txt index c9a8559a3e..746c2c081e 100644 --- a/doc/device-tree-bindings/watchdog/gpio-wdt.txt +++ b/doc/device-tree-bindings/watchdog/gpio-wdt.txt @@ -5,7 +5,12 @@ Describes a simple watchdog timer which is reset by toggling a gpio. Required properties: - compatible: Must be "linux,wdt-gpio". -- gpios: gpio to toggle when wdt driver reset method is called. +- gpios: From common gpio binding; gpio connection to WDT reset pin. +- hw_algo: The algorithm used by the driver. Should be one of the + following values: + - toggle: Toggle from high-to-low or low-to-high when resetting the watchdog. + - level: Maintain a constant high/low level, and trigger a short pulse when + resetting the watchdog. Active level is determined by the GPIO flags. - always-running: Boolean property indicating that the watchdog cannot be disabled. At present, U-Boot only supports this kind of GPIO watchdog. @@ -15,5 +20,6 @@ Example: gpio-wdt { gpios = <&gpio0 1 0>; compatible = "linux,wdt-gpio"; + hw_algo = "toggle"; always-running; }; diff --git a/drivers/watchdog/gpio_wdt.c b/drivers/watchdog/gpio_wdt.c index 982a66b3f9..fe06ec8cc9 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); diff --git a/test/dm/wdt.c b/test/dm/wdt.c index ee615f0e14..535f00a874 100644 --- a/test/dm/wdt.c +++ b/test/dm/wdt.c @@ -44,20 +44,20 @@ static int dm_test_wdt_base(struct unit_test_state *uts) } DM_TEST(dm_test_wdt_base, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); -static int dm_test_wdt_gpio(struct unit_test_state *uts) +static int dm_test_wdt_gpio_toggle(struct unit_test_state *uts) { /* * The sandbox wdt gpio is "connected" to gpio bank a, offset * 7. Use the sandbox back door to verify that the gpio-wdt - * driver behaves as expected. + * driver behaves as expected when using the 'toggle' algorithm. */ struct udevice *wdt, *gpio; const u64 timeout = 42; const int offset = 7; int val; - ut_assertok(uclass_get_device_by_driver(UCLASS_WDT, - DM_DRIVER_GET(wdt_gpio), &wdt)); + ut_assertok(uclass_get_device_by_name(UCLASS_WDT, + "wdt-gpio-toggle", &wdt)); ut_assertnonnull(wdt); ut_assertok(uclass_get_device_by_name(UCLASS_GPIO, "base-gpios", &gpio)); @@ -74,7 +74,39 @@ static int dm_test_wdt_gpio(struct unit_test_state *uts) return 0; } -DM_TEST(dm_test_wdt_gpio, UT_TESTF_SCAN_FDT); +DM_TEST(dm_test_wdt_gpio_toggle, UT_TESTF_SCAN_FDT); + +static int dm_test_wdt_gpio_level(struct unit_test_state *uts) +{ + /* + * The sandbox wdt gpio is "connected" to gpio bank a, offset + * 7. Use the sandbox back door to verify that the gpio-wdt + * driver behaves as expected when using the 'level' algorithm. + */ + struct udevice *wdt, *gpio; + const u64 timeout = 42; + const int offset = 7; + int val; + + ut_assertok(uclass_get_device_by_name(UCLASS_WDT, + "wdt-gpio-level", &wdt)); + ut_assertnonnull(wdt); + + ut_assertok(uclass_get_device_by_name(UCLASS_GPIO, "base-gpios", &gpio)); + ut_assertnonnull(gpio); + ut_assertok(wdt_start(wdt, timeout, 0)); + + val = sandbox_gpio_get_value(gpio, offset); + ut_assertok(wdt_reset(wdt)); + ut_asserteq(val, sandbox_gpio_get_value(gpio, offset)); + ut_assertok(wdt_reset(wdt)); + ut_asserteq(val, sandbox_gpio_get_value(gpio, offset)); + + ut_asserteq(-ENOSYS, wdt_stop(wdt)); + + return 0; +} +DM_TEST(dm_test_wdt_gpio_level, UT_TESTF_SCAN_FDT); static int dm_test_wdt_watchdog_reset(struct unit_test_state *uts) { @@ -86,8 +118,8 @@ static int dm_test_wdt_watchdog_reset(struct unit_test_state *uts) uint reset_count; int val; - ut_assertok(uclass_get_device_by_driver(UCLASS_WDT, - DM_DRIVER_GET(wdt_gpio), &gpio_wdt)); + ut_assertok(uclass_get_device_by_name(UCLASS_WDT, + "wdt-gpio-toggle", &gpio_wdt)); ut_assertnonnull(gpio_wdt); ut_assertok(uclass_get_device_by_driver(UCLASS_WDT, DM_DRIVER_GET(wdt_sandbox), &sandbox_wdt)); -- 2.25.1