Commit 6c3b617b authored by Jun Lin's avatar Jun Lin Committed by Benjamin Cabé
Browse files

drivers: watchdog: npcx: fix T0 timer reload procedure



The correct procedure to reload the T0 timer is:
    1. Load TWDT0 register with the new value or write 1 to RST bit in
       T0CSR register to load the old value.
    2. Wait until RST bit in T0CSR register becomes 1.
    3. Wait until RST bit in T0CSR register becomes 0.
The current watchdog driver misses step 2.
Fix the issue in this commit.

Signed-off-by: default avatarJun Lin <CHLin56@nuvoton.com>
parent 1280f432
Loading
Loading
Loading
Loading
+15 −2
Original line number Diff line number Diff line
@@ -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!");