diff --git a/drivers/watchdog/wdt_npcx.c b/drivers/watchdog/wdt_npcx.c index 24979ce88defb..c3245a50b7898 100644 --- a/drivers/watchdog/wdt_npcx.c +++ b/drivers/watchdog/wdt_npcx.c @@ -61,7 +61,8 @@ LOG_MODULE_REGISTER(wdt_npcx, CONFIG_WDT_LOG_LEVEL); #define NPCX_WDT_MIN_WND_TIME 100UL /* Timeout for reloading and restarting Timer 0. (Unit:ms) */ -#define NPCX_T0CSR_RST_TIMEOUT 2 +#define NPCX_T0CSR_RST_CLEAR_TIMEOUT 2 +#define NPCX_T0CSR_RST_SET_TIMEOUT 1 /* Timeout for stopping watchdog. (Unit:ms) */ #define NPCX_WATCHDOG_STOP_TIMEOUT 1 @@ -100,10 +101,22 @@ static inline int wdt_t0out_reload(const struct device *dev) /* Reload and restart T0 timer */ inst->T0CSR = (inst->T0CSR & ~BIT(NPCX_T0CSR_WDRST_STS)) | BIT(NPCX_T0CSR_RST); + /* + * Wait for the T0CSR_RST bit to change from 0 to 1. This transition is expected to occur + * over multiple LFCLK cycles. If a timeout occurs, we can assume that the bit has changed + * from 0 -> 1 -> 0, but the polling thread missed it because it was preempted by + * higher-priority threads. In this case, we can simply return. + */ + st = k_uptime_get(); + while (!IS_BIT_SET(inst->T0CSR, NPCX_T0CSR_RST)) { + if (k_uptime_get() - st > NPCX_T0CSR_RST_SET_TIMEOUT) { + return 0; + } + } /* Wait for timer is loaded and restart */ st = k_uptime_get(); while (IS_BIT_SET(inst->T0CSR, NPCX_T0CSR_RST)) { - if (k_uptime_get() - st > NPCX_T0CSR_RST_TIMEOUT) { + if (k_uptime_get() - st > NPCX_T0CSR_RST_CLEAR_TIMEOUT) { /* RST bit is still set? */ if (IS_BIT_SET(inst->T0CSR, NPCX_T0CSR_RST)) { LOG_ERR("Timeout: reload T0 timer!");