From 93423aabd0654b796ab8222685913e1ab942e391 Mon Sep 17 00:00:00 2001 From: Jun Lin Date: Wed, 19 Apr 2023 09:41:30 +0800 Subject: npcx: watchdog: support the longer watchdog timeout In the current pre-scalar setting (fixed to 0), the max watchdog timeout that the user can set is ~8 seconds. It is not enough for some application requirements such as FPMCU. This commit extends the max timeout by adjusting the pre-scalar dynamically. BRANCH=none BUG=b:273577369 TEST=pass "make buildall -j" TEST=Change the CONFIG_WATCHDOG_PERIOD_MS > 8 seconds; type console command "watims ${timeout}"; make sure watchdog panic occurs as expected. TEST=Set the CONFIG_WATCHDOG_PERIOD_MS to the default (1600); make sure WDCNT and WDCP are the same before/after applying this commit. Change-Id: I11b764811f65f0956593ab6725a619a1a44464c4 Signed-off-by: Jun Lin Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/4444452 Reviewed-by: David Cross Tested-by: David Cross Commit-Queue: David Cross Reviewed-by: Bobby Casey --- chip/npcx/watchdog.c | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/chip/npcx/watchdog.c b/chip/npcx/watchdog.c index 7998378565..1172f3ac12 100644 --- a/chip/npcx/watchdog.c +++ b/chip/npcx/watchdog.c @@ -142,14 +142,14 @@ DECLARE_HOOK(HOOK_TICK, watchdog_reload, HOOK_PRIO_DEFAULT); int watchdog_init(void) { #if SUPPORT_WDG + const uint32_t pre_wdcnt = WDCNT_VALUE; + /* Touch watchdog before init if it is already running */ if (IS_BIT_SET(NPCX_T0CSR, NPCX_T0CSR_WD_RUN)) touch_watchdog_count(); /* Keep prescaler ratio timer0 clock to 1:1024 */ NPCX_TWCP = 0x0A; - /* Keep prescaler ratio watchdog clock to 1:1 */ - NPCX_WDCP = 0; /* Clear watchdog reset status initially*/ SET_BIT(NPCX_T0CSR, NPCX_T0CSR_WDRST_STS); @@ -164,10 +164,30 @@ int watchdog_init(void) SET_BIT(NPCX_T0CSR, NPCX_T0CSR_TESDIS); /* - * Set WDCNT initial reload value and T0OUT timeout period - * WDCNT = 0 will generate watchdog reset + * Calculate and set WDCNT initial reload value and T0OUT timeout + * period + * When WDCNT counts down to 0: generate watchdog reset */ - NPCX_WDCNT = WDCNT_VALUE; + if (pre_wdcnt <= 255) { + /* Keep prescaler ratio watchdog clock to 1:1 */ + NPCX_WDCP = 0; + NPCX_WDCNT = pre_wdcnt; + } else { + uint8_t wdcp; + uint8_t pre_scal; + + pre_scal = DIV_ROUND_UP(pre_wdcnt, 255); + + /* + * Find the smallest power of 2 greater than or equal to the + * prescaler + */ + wdcp = __fls(pre_scal - 1) + 1; + pre_scal = 1 << wdcp; + + NPCX_WDCP = wdcp; + NPCX_WDCNT = pre_wdcnt / pre_scal; + } /* Disable interrupt */ interrupt_disable(); -- cgit v1.2.1