From 7f3d53c8bf3b851837dc2f5dd85e0c6a0d0116a1 Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Wed, 2 Oct 2024 21:23:23 +0200 Subject: watchdog: gpio_wdt: add support for stoppable devices Back when I added this driver in commit 2ac8490412c9, I wrote The corresponding linux driver apparently has support for some watchdog circuits which can be disabled by tri-stating the gpio, but I have never actually encountered such a chip in the wild; That has changed now; I have a board with just such a watchdog on my desk currently. Add support for that. - For a hw_algo="toggle" device, the gpio is requested as output if the always-running flag is set, otherwise as input. - The ->start() method is updated to change the direction to output when required (i.e. it is not always-running). - The ->stop() method is implemented, but of course reports failure if always-running. As I still haven't met any hw_algo="level" devices, I'm not entirely sure how they fit in, but I'm borrowing logic from the corresponding linux driver: - In ->probe(), such devices always request the gpio as GPIOD_IS_OUT. - In ->stop(), the linux driver has an "eternal ping" comment and sets the gpio to (logic) high. Stefan: Added necessary changes in test/dm/wdt.c to fix CI build breakage, as suggested by Rasmus. Signed-off-by: Rasmus Villemoes Reviewed-by: Stefan Roese --- drivers/watchdog/gpio_wdt.c | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/watchdog/gpio_wdt.c b/drivers/watchdog/gpio_wdt.c index 2920c2c751f..e889861e917 100644 --- a/drivers/watchdog/gpio_wdt.c +++ b/drivers/watchdog/gpio_wdt.c @@ -45,14 +45,32 @@ static int gpio_wdt_start(struct udevice *dev, u64 timeout, ulong flags) if (priv->always_running) return 0; - return -ENOSYS; + dm_gpio_set_dir_flags(&priv->gpio, GPIOD_IS_OUT); + gpio_wdt_reset(dev); + + return 0; +} + +static int gpio_wdt_stop(struct udevice *dev) +{ + struct gpio_wdt_priv *priv = dev_get_priv(dev); + + if (priv->always_running) + return -EOPNOTSUPP; + + if (priv->hw_algo == HW_ALGO_TOGGLE) + dm_gpio_set_dir_flags(&priv->gpio, GPIOD_IS_IN); + else + dm_gpio_set_value(&priv->gpio, 1); + + return 0; } 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"); + int ret, flags; if (!algo) return -EINVAL; @@ -64,7 +82,9 @@ static int dm_probe(struct udevice *dev) return -EINVAL; priv->always_running = dev_read_bool(dev, "always-running"); - ret = gpio_request_by_name(dev, "gpios", 0, &priv->gpio, GPIOD_IS_OUT); + flags = priv->always_running || priv->hw_algo == HW_ALGO_LEVEL ? + GPIOD_IS_OUT : GPIOD_IS_IN; + ret = gpio_request_by_name(dev, "gpios", 0, &priv->gpio, flags); if (ret < 0) { dev_err(dev, "Request for wdt gpio failed: %d\n", ret); return ret; @@ -78,6 +98,7 @@ static int dm_probe(struct udevice *dev) static const struct wdt_ops gpio_wdt_ops = { .start = gpio_wdt_start, + .stop = gpio_wdt_stop, .reset = gpio_wdt_reset, }; -- cgit v1.2.3 From f9318b067f43aa1618036db8d77d34086d62dc06 Mon Sep 17 00:00:00 2001 From: Bastien Curutchet Date: Thu, 3 Oct 2024 10:42:55 +0200 Subject: drivers: watchdog: Add DaVinci's watchdog support Add support for the DaVinci's watchdog timer Signed-off-by: Bastien Curutchet Reviewed-by: Stefan Roese --- drivers/watchdog/Kconfig | 7 +++ drivers/watchdog/Makefile | 1 + drivers/watchdog/davinci_wdt.c | 131 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 139 insertions(+) create mode 100644 drivers/watchdog/davinci_wdt.c (limited to 'drivers') diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 90bc5653ee3..b6f7e4ee08a 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -175,6 +175,13 @@ config WDT_DA9063 help Enable support for the watchdog timer in Dialog DA9063. +config WDT_DAVINCI + bool "DaVinci watchdog timer support" + depends on WDT + help + Select this to enable the watchdog timer for DaVinci SoCs such as the + OMAP-L138. + config WDT_GPIO bool "External gpio watchdog support" depends on WDT diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 51be6ab9abe..cef98975d07 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -30,6 +30,7 @@ obj-$(CONFIG_WDT_CORTINA) += cortina_wdt.o obj-$(CONFIG_WDT_ORION) += orion_wdt.o obj-$(CONFIG_WDT_CDNS) += cdns_wdt.o obj-$(CONFIG_WDT_DA9063) += da9063-wdt.o +obj-$(CONFIG_WDT_DAVINCI) += davinci_wdt.o obj-$(CONFIG_WDT_FTWDT010) += ftwdt010_wdt.o obj-$(CONFIG_WDT_GPIO) += gpio_wdt.o obj-$(CONFIG_WDT_MAX6370) += max6370_wdt.o diff --git a/drivers/watchdog/davinci_wdt.c b/drivers/watchdog/davinci_wdt.c new file mode 100644 index 00000000000..fa8d7842e94 --- /dev/null +++ b/drivers/watchdog/davinci_wdt.c @@ -0,0 +1,131 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * DaVinci Watchdog driver + * + */ + +#include +#include +#include +#include + +/* Control Register */ +#define DAVINCI_WDT_ID 0x00 +#define DAVINCI_WDT_TIM12 0x10 +#define DAVINCI_WDT_TIM34 0x14 +#define DAVINCI_WDT_PRD12 0x18 +#define DAVINCI_WDT_PRD34 0x1C +#define DAVINCI_WDT_TCR 0x20 +#define DAVINCI_WDT_TGCR 0x24 +#define DAVINCI_WDT_WDTCR 0x28 + +#define DAVINCI_TCR_CONT_EN BIT(7) + +#define DAVINCI_TGCR_PLUSEN BIT(4) +#define DAVINCI_TGCR_WDT_MODE BIT(3) +#define DAVINCI_TGCR_TIM34RS BIT(1) +#define DAVINCI_TGCR_TIM12RS BIT(0) + +#define DAVINCI_WDTCR_INVALID_KEY (0x5555 << 16) +#define DAVINCI_WDTCR_WDKEY0 (0xA5C6 << 16) +#define DAVINCI_WDTCR_WDKEY1 (0xDA7E << 16) +#define DAVINCI_WDTCR_WDFLAG BIT(15) +#define DAVINCI_WDTCR_WDEN BIT(14) + +#define DEFAULT_THRESHOLD 0xA03200000 + +struct davinci_wdt_priv { + void __iomem *base; + struct clk *ref_clk; +}; + +static int davinci_wdt_start(struct udevice *dev, u64 timeout_ms, ulong flags) +{ + struct davinci_wdt_priv *priv = dev_get_priv(dev); + ulong rate = clk_get_rate(priv->ref_clk); + u64 threshold; + + if (!rate) + threshold = DEFAULT_THRESHOLD; + else + threshold = rate * timeout_ms / 1000; + + /* Reset control registers */ + writel(0, priv->base + DAVINCI_WDT_TCR); + writel(0, priv->base + DAVINCI_WDT_TGCR); + + /* Enable watchdog mode and timers */ + writel(DAVINCI_TGCR_WDT_MODE | DAVINCI_TGCR_TIM12RS | DAVINCI_TGCR_TIM34RS, + priv->base + DAVINCI_WDT_TGCR); + + /* Reset counters */ + writel(0, priv->base + DAVINCI_WDT_TIM12); + writel(0, priv->base + DAVINCI_WDT_TIM34); + + /* Set timeout threshold */ + writel(threshold & 0xFFFFFFFF, priv->base + DAVINCI_WDT_PRD12); + writel(threshold >> 32, priv->base + DAVINCI_WDT_PRD34); + + /* Enable counter */ + writel(DAVINCI_TCR_CONT_EN, priv->base + DAVINCI_WDT_TCR); + + /* Go to watchdog's active state */ + writel(DAVINCI_WDTCR_WDEN | DAVINCI_WDTCR_WDKEY0, priv->base + DAVINCI_WDT_WDTCR); + writel(DAVINCI_WDTCR_WDEN | DAVINCI_WDTCR_WDKEY1, priv->base + DAVINCI_WDT_WDTCR); + + return 0; +} + +static int davinci_wdt_expire_now(struct udevice *dev, ulong flags) +{ + struct davinci_wdt_priv *priv = dev_get_priv(dev); + + writel(DAVINCI_WDTCR_INVALID_KEY, priv->base + DAVINCI_WDT_WDTCR); + + return 0; +} + +static int davinci_wdt_restart(struct udevice *dev) +{ + struct davinci_wdt_priv *priv = dev_get_priv(dev); + + writel(DAVINCI_WDTCR_WDEN | DAVINCI_WDTCR_WDKEY0, priv->base + DAVINCI_WDT_WDTCR); + writel(DAVINCI_WDTCR_WDEN | DAVINCI_WDTCR_WDKEY1, priv->base + DAVINCI_WDT_WDTCR); + + return 0; +} + +static int davinci_wdt_probe(struct udevice *dev) +{ + struct davinci_wdt_priv *priv = dev_get_priv(dev); + + priv->base = dev_remap_addr_index(dev, 0); + if (!priv->base) + return -EFAULT; + + priv->ref_clk = devm_clk_get(dev, "ref"); + if (IS_ERR(priv->ref_clk)) + return PTR_ERR(priv->ref_clk); + + return 0; +} + +static const struct wdt_ops davinci_wdt_ops = { + .start = davinci_wdt_start, + .reset = davinci_wdt_restart, + .expire_now = davinci_wdt_expire_now, +}; + +static const struct udevice_id davinci_wdt_ids[] = { + {.compatible = "ti,davinci-wdt"}, + {} +}; + +U_BOOT_DRIVER(davinci_wdt) = { + .name = "davinci_wdt", + .id = UCLASS_WDT, + .probe = davinci_wdt_probe, + .of_match = davinci_wdt_ids, + .ops = &davinci_wdt_ops, + .priv_auto = sizeof(struct davinci_wdt_priv), +}; -- cgit v1.2.3 From 9e628922283834edaec342f335eb9726ab53570e Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Thu, 3 Oct 2024 23:27:52 +0200 Subject: led: include cyclic.h in led_sw_blink.c This makes use of the cyclic API but relies on implicitly getting the appropriate declarations through some nested include. Include the cyclic.h header directly. Signed-off-by: Rasmus Villemoes Reviewed-by: Simon Glass Reviewed-by: Stefan Roese --- drivers/led/led_sw_blink.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/led/led_sw_blink.c b/drivers/led/led_sw_blink.c index 06a43db340c..ee1546d02d4 100644 --- a/drivers/led/led_sw_blink.c +++ b/drivers/led/led_sw_blink.c @@ -5,6 +5,7 @@ * Author: Mikhail Kshevetskiy */ +#include #include #include #include -- cgit v1.2.3 From 4da44fa6467da0372e42be4c7c84e863d9d44258 Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Thu, 3 Oct 2024 23:27:59 +0200 Subject: i2c: rzg2l: include u-boot/schedule.h This TU currently relies on getting a declaration of schedule() through some nested include. Include the proper header directly. Signed-off-by: Rasmus Villemoes Reviewed-by: Simon Glass Reviewed-by: Stefan Roese --- drivers/i2c/rz_riic.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/i2c/rz_riic.c b/drivers/i2c/rz_riic.c index 5f3f8d1b24b..f292c824362 100644 --- a/drivers/i2c/rz_riic.c +++ b/drivers/i2c/rz_riic.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #define RIIC_ICCR1 0x00 -- cgit v1.2.3 From 02e352f0da0cad06c6db69d928308362a6835a9f Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Thu, 3 Oct 2024 23:28:00 +0200 Subject: ddr: altera: include u-boot/schedule.h These TUs currently rely on getting a declaration of schedule() through some nested include. Include the proper header directly. Signed-off-by: Rasmus Villemoes Reviewed-by: Simon Glass Reviewed-by: Stefan Roese --- drivers/ddr/altera/sdram_n5x.c | 1 + drivers/ddr/altera/sdram_soc64.c | 1 + 2 files changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/ddr/altera/sdram_n5x.c b/drivers/ddr/altera/sdram_n5x.c index db09986f64b..d1fc93b6bdd 100644 --- a/drivers/ddr/altera/sdram_n5x.c +++ b/drivers/ddr/altera/sdram_n5x.c @@ -22,6 +22,7 @@ #include #include #include +#include DECLARE_GLOBAL_DATA_PTR; diff --git a/drivers/ddr/altera/sdram_soc64.c b/drivers/ddr/altera/sdram_soc64.c index 9e57c2ecfa4..10a8e64af3d 100644 --- a/drivers/ddr/altera/sdram_soc64.c +++ b/drivers/ddr/altera/sdram_soc64.c @@ -24,6 +24,7 @@ #include #include #include +#include #define PGTABLE_OFF 0x4000 -- cgit v1.2.3 From ed3410ee6049a7683718e8255575ad55ee1bdefd Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Mon, 7 Oct 2024 19:47:16 +0200 Subject: watchdog: introduce separate SPL symbol for WDT_GPIO Currently, enabling WDT_GPIO on a board which uses SPL, but does not have SPL_WDT, SPL_DM_GPIO or SPL_OF_CONTROL enabled, breaks the build. Make it possible to use the WDT_GPIO driver on such boards by introducing a separate symbol controlling whether the driver is built for SPL. Make it default to WDT_GPIO such that boards that already have it enabled and all the SPL prerequisites satisfied will continue to have it in SPL. Signed-off-by: Rasmus Villemoes Reviewed-by: Tom Rini Reviewed-by: Stefan Roese --- drivers/watchdog/Kconfig | 9 +++++++++ drivers/watchdog/Makefile | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index b6f7e4ee08a..0e45f0a0922 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -191,6 +191,15 @@ config WDT_GPIO doc/device-tree-bindings/watchdog/gpio-wdt.txt for information on how to describe the watchdog in device tree. +config SPL_WDT_GPIO + bool "External gpio watchdog support in SPL" + depends on SPL_WDT + depends on SPL_DM_GPIO + depends on SPL_OF_REAL + default WDT_GPIO + help + Support for external watchdog fed by toggling a gpio in SPL. + config WDT_MAX6370 bool "MAX6370 watchdog timer support" depends on WDT diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index cef98975d07..0b107c008f7 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -32,7 +32,7 @@ obj-$(CONFIG_WDT_CDNS) += cdns_wdt.o obj-$(CONFIG_WDT_DA9063) += da9063-wdt.o obj-$(CONFIG_WDT_DAVINCI) += davinci_wdt.o obj-$(CONFIG_WDT_FTWDT010) += ftwdt010_wdt.o -obj-$(CONFIG_WDT_GPIO) += gpio_wdt.o +obj-$(CONFIG_$(SPL_TPL_)WDT_GPIO) += gpio_wdt.o obj-$(CONFIG_WDT_MAX6370) += max6370_wdt.o obj-$(CONFIG_WDT_MCF) += mcf_wdt.o obj-$(CONFIG_WDT_MESON_GXBB) += meson_gxbb_wdt.o -- cgit v1.2.3