From a12366a807a8fbba67b6da6e842e8296af60aba0 Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Thu, 13 Jan 2022 16:57:31 +0100 Subject: [PATCH 1/4] MAINTAINERS: Add watchdog maintainers entry I've been handling "inofficially" the watchdog related patches for a few years now. Let's make this official and add a tree for it and also add myself here in the MAINTAINERS file. Signed-off-by: Stefan Roese Cc: Tom Rini Cc: Harald Seiler Reviewed-by: Tom Rini --- MAINTAINERS | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 0f39bc6bc9..82fc49e31d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1326,6 +1326,14 @@ F: include/virtio*.h F: test/dm/virtio.c F: doc/develop/driver-model/virtio.rst +WATCHDOG +M: Stefan Roese +S: Maintained +T: git https://source.denx.de/u-boot/custodians/u-boot-watchdog.git +F: cmd/wdt.c +F: drivers/watchdog/ +F: include/watchdog*.h + X86 M: Simon Glass M: Bin Meng From a12492ebbc88dab74b1d6e27d8194a56eb1fbbff Mon Sep 17 00:00:00 2001 From: Philippe Reynes Date: Thu, 10 Feb 2022 18:17:54 +0100 Subject: [PATCH 2/4] drivers: watchdog: wdt-uclass.c: add a property u-boot, noautostart Since commit 492ee6b8d0e7 ("watchdog: wdt-uclass.c: handle all DM watchdogs in watchdog_reset()"), all the watchdog are started when the config WATCHDOG_AUTOSTART. To avoid a binary choice none/all, a property u-boot,noautostart may be added in the watchdog node of the u-boot device tree to not autostart this watchdog. Signed-off-by: Philippe Reynes Reviewed-by: Simon Glass Reviewed-by: Stefan Roese --- drivers/watchdog/wdt-uclass.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/watchdog/wdt-uclass.c b/drivers/watchdog/wdt-uclass.c index 6d0f473867..dbf556467d 100644 --- a/drivers/watchdog/wdt-uclass.c +++ b/drivers/watchdog/wdt-uclass.c @@ -36,6 +36,8 @@ struct wdt_priv { ulong next_reset; /* Whether watchdog_start() has been called on the device. */ bool running; + /* No autostart */ + bool noautostart; }; static void init_watchdog_dev(struct udevice *dev) @@ -52,7 +54,7 @@ static void init_watchdog_dev(struct udevice *dev) dev->name); } - if (!IS_ENABLED(CONFIG_WATCHDOG_AUTOSTART)) { + if (!IS_ENABLED(CONFIG_WATCHDOG_AUTOSTART) || priv->noautostart) { printf("WDT: Not starting %s\n", dev->name); return; } @@ -256,16 +258,19 @@ static int wdt_pre_probe(struct udevice *dev) * indicated by a hw_margin_ms property. */ ulong reset_period = 1000; + bool noautostart = false; struct wdt_priv *priv; if (CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)) { timeout = dev_read_u32_default(dev, "timeout-sec", timeout); reset_period = dev_read_u32_default(dev, "hw_margin_ms", 4 * reset_period) / 4; + noautostart = dev_read_bool(dev, "u-boot,noautostart"); } priv = dev_get_uclass_priv(dev); priv->timeout = timeout; priv->reset_period = reset_period; + priv->noautostart = noautostart; /* * Pretend this device was last reset "long" ago so the first * watchdog_reset will actually call its ->reset method. From 65066773a3e4c3f1dfc5eac8400ca7a7268e4fb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Wed, 23 Feb 2022 14:21:40 +0100 Subject: [PATCH 3/4] watchdog: armada_37xx: Probe driver also when watchdog is already running MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If Armada 37xx watchdog is started before U-Boot then CNTR_CTRL_ACTIVE bit is set, U-Boot armada-37xx-wdt.c driver fails to initialize and so U-Boot is unable to use or kick this watchdog. Do not check for CNTR_CTRL_ACTIVE bit and always initialize watchdog. Same behavior is implemented in Linux kernel driver. This change allows to activate watchdog in firmware which loads U-Boot. Signed-off-by: Pali Rohár Reviewed-by: Marek Behún Reviewed-by: Stefan Roese --- drivers/watchdog/armada-37xx-wdt.c | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/drivers/watchdog/armada-37xx-wdt.c b/drivers/watchdog/armada-37xx-wdt.c index 2e119b9b5a..bacebbc792 100644 --- a/drivers/watchdog/armada-37xx-wdt.c +++ b/drivers/watchdog/armada-37xx-wdt.c @@ -58,13 +58,11 @@ static void counter_disable(struct a37xx_wdt *priv, int id) clrbits_le32(priv->reg + CNTR_CTRL(id), CNTR_CTRL_ENABLE); } -static int init_counter(struct a37xx_wdt *priv, int id, u32 mode, u32 trig_src) +static void init_counter(struct a37xx_wdt *priv, int id, u32 mode, u32 trig_src) { u32 reg; reg = readl(priv->reg + CNTR_CTRL(id)); - if (reg & CNTR_CTRL_ACTIVE) - return -EBUSY; reg &= ~(CNTR_CTRL_MODE_MASK | CNTR_CTRL_PRESCALE_MASK | CNTR_CTRL_TRIG_SRC_MASK); @@ -79,8 +77,6 @@ static int init_counter(struct a37xx_wdt *priv, int id, u32 mode, u32 trig_src) reg |= trig_src; writel(reg, priv->reg + CNTR_CTRL(id)); - - return 0; } static int a37xx_wdt_reset(struct udevice *dev) @@ -116,16 +112,9 @@ static int a37xx_wdt_expire_now(struct udevice *dev, ulong flags) static int a37xx_wdt_start(struct udevice *dev, u64 ms, ulong flags) { struct a37xx_wdt *priv = dev_get_priv(dev); - int err; - err = init_counter(priv, 0, CNTR_CTRL_MODE_ONESHOT, 0); - if (err < 0) - return err; - - err = init_counter(priv, 1, CNTR_CTRL_MODE_HWSIG, - CNTR_CTRL_TRIG_SRC_PREV_CNTR); - if (err < 0) - return err; + init_counter(priv, 0, CNTR_CTRL_MODE_ONESHOT, 0); + init_counter(priv, 1, CNTR_CTRL_MODE_HWSIG, CNTR_CTRL_TRIG_SRC_PREV_CNTR); priv->timeout = ms * priv->clk_rate / 1000 / CNTR_CTRL_PRESCALE_MIN; From 817e153fe546c2da9df8e8affc94d12036815659 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Tue, 8 Mar 2022 07:25:50 +0100 Subject: [PATCH 4/4] watchdog: rti_wdt: Add 10% safety margin to clock frequency When running against RC_OSC_32k, the watchdog may suffer from running faster than expected, expiring earlier. The Linux kernel adds a 10% margin to the timeout calculation by slowing down the read clock rate accordingly. Do the same here, also to have comparable preset values for both drivers. Along this, fix the name of the local var holding to frequency - in Hz, not kHz. Signed-off-by: Jan Kiszka Signed-off-by: Stefan Roese --- drivers/watchdog/rti_wdt.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/watchdog/rti_wdt.c b/drivers/watchdog/rti_wdt.c index 253286d349..8d93f19b98 100644 --- a/drivers/watchdog/rti_wdt.c +++ b/drivers/watchdog/rti_wdt.c @@ -41,7 +41,7 @@ struct rti_wdt_priv { phys_addr_t regs; - unsigned int clk_khz; + unsigned int clk_hz; }; #ifdef CONFIG_WDT_K3_RTI_LOAD_FW @@ -139,7 +139,7 @@ static int rti_wdt_start(struct udevice *dev, u64 timeout_ms, ulong flags) if (ret < 0) return ret; - timer_margin = timeout_ms * priv->clk_khz / 1000; + timer_margin = timeout_ms * priv->clk_hz / 1000; timer_margin >>= WDT_PRELOAD_SHIFT; if (timer_margin > WDT_PRELOAD_MAX) timer_margin = WDT_PRELOAD_MAX; @@ -185,7 +185,15 @@ static int rti_wdt_probe(struct udevice *dev) if (ret) return ret; - priv->clk_khz = clk_get_rate(&clk); + priv->clk_hz = clk_get_rate(&clk); + + /* + * If watchdog is running at 32k clock, it is not accurate. + * Adjust frequency down in this case so that it does not expire + * earlier than expected. + */ + if (priv->clk_hz < 32768) + priv->clk_hz = priv->clk_hz * 9 / 10; return 0; }