[PATCH v3 02/13] watchdog: stm32_iwdg: detect whether the watchdog is running

From: Antonio Borneo

Date: Fri Nov 06 2026 - 11:36:11 EST


From: Clément Le Goffic <clement.legoffic@xxxxxxxxxxx>

On STM32MP13x and STM32MP2xx platforms, the ONF bit in the IWDG
status register indicates whether the watchdog is running. This
feature was introduced with IWDG hardware version 3.1 and is not
available on older versions, such as the one used on STM32MP15x.

On older hardware versions, determine the watchdog state by
writing the current reload value back to the reload register,
then checking the RVU (Reload Value Update) bit in the status
register. The update completes only if the watchdog is already
running.

Use this state information to service only watchdogs that were
started by earlier boot stages.

Signed-off-by: Clément Le Goffic <clement.legoffic@xxxxxxxxxxx>
Signed-off-by: Antonio Borneo <antonio.borneo@xxxxxxxxxxx>
---
drivers/watchdog/stm32_iwdg.c | 45 +++++++++++++++++++++++------------
1 file changed, 30 insertions(+), 15 deletions(-)

diff --git a/drivers/watchdog/stm32_iwdg.c b/drivers/watchdog/stm32_iwdg.c
index 30b4cbf20afa9..ce3e1f96ef50a 100644
--- a/drivers/watchdog/stm32_iwdg.c
+++ b/drivers/watchdog/stm32_iwdg.c
@@ -49,6 +49,7 @@
/* IWDG_SR register bit mask */
#define SR_PVU BIT(0) /* Watchdog prescaler value update */
#define SR_RVU BIT(1) /* Watchdog counter reload value update */
+#define SR_ONF BIT(8) /* Watchdog enable status bit */

#define EWCR_EWIT GENMASK(11, 0) /* Watchdog counter window value */
#define EWCR_EWIC BIT(14) /* Watchdog early interrupt acknowledge */
@@ -57,6 +58,9 @@
/* IWDG_VERR register mask */
#define VERR_MASK GENMASK(7, 0)

+/* IWDG Compatibility */
+#define ONF_MIN_VER 0x31
+
/* set timeout to 100000 us */
#define TIMEOUT_US 100000
#define SLEEP_US 1000
@@ -250,6 +254,31 @@ static int stm32_iwdg_clk_init(struct platform_device *pdev,
return 0;
}

+static bool stm32_iwdg_is_running(struct stm32_iwdg *wdt)
+{
+ bool running;
+ u32 rlr, sr;
+ int ret;
+
+ if (wdt->hw_version >= ONF_MIN_VER)
+ return (reg_read(wdt->regs, IWDG_SR) & SR_ONF) != 0;
+
+ /*
+ * Workaround for old versions without IWDG_SR_ONF bit:
+ * - write in IWDG_RLR_OFFSET
+ * - wait for sync
+ * - if sync succeeds, then iwdg is running
+ */
+ reg_write(wdt->regs, IWDG_KR, KR_KEY_EWA);
+ rlr = reg_read(wdt->regs, IWDG_RLR);
+ reg_write(wdt->regs, IWDG_RLR, rlr);
+ ret = readl_poll_timeout(wdt->regs + IWDG_SR, sr, !(sr & SR_RVU), SLEEP_US, TIMEOUT_US);
+ running = ret ? false : true;
+ reg_write(wdt->regs, IWDG_KR, KR_KEY_DWA);
+
+ return running;
+}
+
static const struct watchdog_info stm32_iwdg_info = {
.options = WDIOF_SETTIMEOUT |
WDIOF_MAGICCLOSE |
@@ -362,23 +391,9 @@ static int stm32_iwdg_probe(struct platform_device *pdev)
watchdog_set_nowayout(wdd, WATCHDOG_NOWAYOUT);
watchdog_init_timeout(wdd, 0, dev);

- /*
- * In case of CONFIG_WATCHDOG_HANDLE_BOOT_ENABLED is set
- * (Means U-Boot/bootloaders leaves the watchdog running)
- * When we get here we should make a decision to prevent
- * any side effects before user space daemon will take care of it.
- * The best option, taking into consideration that there is no
- * way to read values back from hardware, is to enforce watchdog
- * being run with deterministic values.
- */
- if (IS_ENABLED(CONFIG_WATCHDOG_HANDLE_BOOT_ENABLED)) {
- ret = stm32_iwdg_start(wdd);
- if (ret)
- return ret;
-
+ if (IS_ENABLED(CONFIG_WATCHDOG_HANDLE_BOOT_ENABLED) && stm32_iwdg_is_running(wdt))
/* Make sure the watchdog is serviced */
set_bit(WDOG_HW_RUNNING, &wdd->status);
- }

ret = devm_watchdog_register_device(dev, wdd);
if (ret)
--
2.34.1