driver: watchdog: npcx: support longer watchdog timeout
In the current driver, the longest time of the watchdog timeout is ~8 seconds because the pre-scalar is fixed at 32 (WDCP=5). This commit removes this limitation by dynamically calculating the pre-scalar according to the watchdog timeout setting from the API. Signed-off-by: Jun Lin <CHLin56@nuvoton.com> Signed-off-by: Tom Chang <CHChang19@nuvoton.com>
This commit is contained in:
parent
b3ffe0aede
commit
c864024c32
2 changed files with 36 additions and 14 deletions
|
@ -12,12 +12,11 @@ config WDT_NPCX
|
|||
processors.
|
||||
Say y if you wish to use watchdog on NPCX MCU.
|
||||
|
||||
config WDT_NPCX_DELAY_CYCLES
|
||||
int "Number of delay cycles before generating watchdog event/signal"
|
||||
config WDT_NPCX_WARNING_LEADING_TIME_MS
|
||||
int "Milliseconds before generating watchdog event/signal"
|
||||
depends on WDT_NPCX
|
||||
range 1 255
|
||||
default 10
|
||||
default 500
|
||||
help
|
||||
This option defines the window in which a watchdog event must be
|
||||
handled, in units of 31ms. After this time window, the watchdog reset
|
||||
triggers immediately.
|
||||
handled. After this time window, the watchdog reset triggers
|
||||
immediately.
|
||||
|
|
|
@ -46,10 +46,13 @@ LOG_MODULE_REGISTER(wdt_npcx, CONFIG_WDT_LOG_LEVEL);
|
|||
#define NPCX_WDT_CLK LFCLK
|
||||
|
||||
/*
|
||||
* Maximum watchdog window time. Since the watchdog counter is 8-bits, maximum
|
||||
* time supported by npcx watchdog is 256 * (32 * 32) / 32768 = 8 sec.
|
||||
* Maximum watchdog window time. Keep the timer and watchdog clock prescaler
|
||||
* (TWCP) to 0x5. Since the watchdog counter is 8-bits, maximum time supported
|
||||
* by npcx watchdog is 256 * (32 * 32768) / 32768 = 8192 sec.
|
||||
* The maximum time supported of T0OUT is 65536 * 32 / 32768 = 64 sec.
|
||||
* Thus, the maximum time of watchdog set here is 64 sec.
|
||||
*/
|
||||
#define NPCX_WDT_MAX_WND_TIME 8000UL
|
||||
#define NPCX_WDT_MAX_WND_TIME 64000UL
|
||||
|
||||
/*
|
||||
* Minimum watchdog window time. Ensure we have waited at least 3 watchdog
|
||||
|
@ -139,7 +142,7 @@ static void wdt_t0out_isr(const struct device *dev, struct npcx_wui *wui)
|
|||
ARG_UNUSED(wui);
|
||||
|
||||
LOG_DBG("WDT reset will issue after %d delay cycle! WUI(%d %d %d)",
|
||||
CONFIG_WDT_NPCX_DELAY_CYCLES, wui->table, wui->group, wui->bit);
|
||||
CONFIG_WDT_NPCX_WARNING_LEADING_TIME_MS, wui->table, wui->group, wui->bit);
|
||||
|
||||
/* Handle watchdog event here. */
|
||||
if (data->cb) {
|
||||
|
@ -208,6 +211,9 @@ static int wdt_npcx_setup(const struct device *dev, uint8_t options)
|
|||
struct twd_reg *const inst = HAL_INSTANCE(dev);
|
||||
const struct wdt_npcx_config *const config = dev->config;
|
||||
struct wdt_npcx_data *const data = dev->data;
|
||||
uint32_t wd_cnt, pre_scal;
|
||||
uint8_t wdcp;
|
||||
|
||||
int rv;
|
||||
|
||||
/* Disable irq of t0-out expired event first */
|
||||
|
@ -242,9 +248,24 @@ static int wdt_npcx_setup(const struct device *dev, uint8_t options)
|
|||
inst->TWDT0 = MAX(DIV_ROUND_UP(data->timeout * NPCX_WDT_CLK,
|
||||
32 * 1000) - 1, 1);
|
||||
|
||||
/* Configure 8-bit watchdog counter */
|
||||
inst->WDCNT = MIN(DIV_ROUND_UP(data->timeout, 32) +
|
||||
CONFIG_WDT_NPCX_DELAY_CYCLES, 0xff);
|
||||
/* Configure 8-bit watchdog counter
|
||||
* Change the prescaler of watchdog clock for larger timeout
|
||||
*/
|
||||
wd_cnt = DIV_ROUND_UP((data->timeout + CONFIG_WDT_NPCX_WARNING_LEADING_TIME_MS) *
|
||||
NPCX_WDT_CLK,
|
||||
32 * 1000);
|
||||
|
||||
pre_scal = DIV_ROUND_UP(wd_cnt, 255);
|
||||
|
||||
/*
|
||||
* Find the smallest power of 2 greater than or equal to the
|
||||
* prescaler
|
||||
*/
|
||||
wdcp = LOG2(pre_scal - 1) + 1;
|
||||
pre_scal = 1 << wdcp;
|
||||
|
||||
inst->WDCP = wdcp;
|
||||
inst->WDCNT = wd_cnt / pre_scal;
|
||||
|
||||
LOG_DBG("WDT setup: TWDT0, WDCNT are %d, %d", inst->TWDT0, inst->WDCNT);
|
||||
|
||||
|
@ -265,12 +286,14 @@ static int wdt_npcx_disable(const struct device *dev)
|
|||
const struct wdt_npcx_config *const config = dev->config;
|
||||
struct wdt_npcx_data *const data = dev->data;
|
||||
struct twd_reg *const inst = HAL_INSTANCE(dev);
|
||||
uint16_t min_wnd_t;
|
||||
|
||||
/*
|
||||
* Ensure we have waited at least 3 watchdog ticks before
|
||||
* stopping watchdog
|
||||
*/
|
||||
while (k_uptime_get() - data->last_watchdog_touch < NPCX_WDT_MIN_WND_TIME) {
|
||||
min_wnd_t = DIV_ROUND_UP(3 * NPCX_WDT_CLK, 32 * (1 << inst->WDCP));
|
||||
while (k_uptime_get() - data->last_watchdog_touch < min_wnd_t) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue