diff --git a/chip/npcx/hwtimer.c b/chip/npcx/hwtimer.c index 206f5f219c..8d92990048 100644 --- a/chip/npcx/hwtimer.c +++ b/chip/npcx/hwtimer.c @@ -267,6 +267,28 @@ void __hw_clock_source_irq(void) } DECLARE_IRQ(NPCX_IRQ_ITIM32, __hw_clock_source_irq, 2); +/* Handle ITIM32 overflow if interrupt is disabled */ +void __hw_clock_handle_overflow(uint32_t clksrc_high) +{ + timestamp_t newtime; + + /* Overflow occurred? */ + if (!IS_BIT_SET(NPCX_ITCTS(ITIM32), NPCX_ITCTS_TO_STS)) + return; + + /* Clear timeout status */ + SET_BIT(NPCX_ITCTS(ITIM32), NPCX_ITCTS_TO_STS); + + /* + * Restore ITIM32 preload counter value to maximum and execute + * process_timers() later in ISR by trigger software interrupt in + * force_time(). + */ + newtime.le.hi = clksrc_high + 1; + newtime.le.lo = 0; + force_time(newtime); +} + static void update_prescaler(void) { /* diff --git a/chip/npcx/hwtimer_chip.h b/chip/npcx/hwtimer_chip.h index 08cf8e278f..3b00b0dea5 100644 --- a/chip/npcx/hwtimer_chip.h +++ b/chip/npcx/hwtimer_chip.h @@ -32,4 +32,7 @@ uint16_t __hw_clock_event_count(void); /* Returns time delay because of deep idle */ uint32_t __hw_clock_get_sleep_time(uint16_t pre_evt_cnt); +/* Handle ITIM32 overflow if interrupt is disabled */ +void __hw_clock_handle_overflow(uint32_t clksrc_high); + #endif /* __CROS_EC_HWTIMER_CHIP_H */ diff --git a/chip/npcx/lpc.c b/chip/npcx/lpc.c index 518e15f957..0f2c295d4a 100644 --- a/chip/npcx/lpc.c +++ b/chip/npcx/lpc.c @@ -13,6 +13,7 @@ #include "gpio.h" #include "hooks.h" #include "host_command.h" +#include "hwtimer_chip.h" #include "keyboard_protocol.h" #include "lpc.h" #include "lpc_chip.h" @@ -337,14 +338,17 @@ void lpc_keyboard_put_char(uint8_t chr, int send_irq) */ static void lpc_sib_wait_host_read_done(void) { - timestamp_t deadline; + timestamp_t deadline, start; - deadline.val = get_time().val + LPC_HOST_TRANSACTION_TIMEOUT_US; + start = get_time(); + deadline.val = start.val + LPC_HOST_TRANSACTION_TIMEOUT_US; while (IS_BIT_SET(NPCX_SIBCTRL, NPCX_SIBCTRL_CSRD)) { if (timestamp_expired(deadline, NULL)) { CPRINTS("Unexpected time of host read transaction"); break; } + /* Handle ITIM32 overflow condition */ + __hw_clock_handle_overflow(start.le.hi); } } @@ -353,14 +357,17 @@ static void lpc_sib_wait_host_read_done(void) */ static void lpc_sib_wait_host_write_done(void) { - timestamp_t deadline; + timestamp_t deadline, start; - deadline.val = get_time().val + LPC_HOST_TRANSACTION_TIMEOUT_US; + start = get_time(); + deadline.val = start.val + LPC_HOST_TRANSACTION_TIMEOUT_US; while (IS_BIT_SET(NPCX_SIBCTRL, NPCX_SIBCTRL_CSWR)) { if (timestamp_expired(deadline, NULL)) { CPRINTS("Unexpected time of host write transaction"); break; } + /* Handle ITIM32 overflow condition */ + __hw_clock_handle_overflow(start.le.hi); } }