mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2026-01-14 08:36:39 +00:00
npcx: lpc: fixed bug that ec gets stuck in lpc_sib_wait_hostxx routines.
If an ITIM32 timeout event occurred during lpc_sib_wait_host_read_done() and lpc_sib_wait_host_write_done() routines, in rare case, ec might have a chance to gets stuck since ec's interrupts are disabled when CSWR/CSRD bits are high forever. (Normally, CSWR/CSRD bits won't be always high. These bits are high forever also means something wrong on LPC/eSPI bus.) In order to prevent this situation, the CL checks TO_STS bit of ITCTS in these routines. If this bit is set, restoring ITIM32 preload counter value to maximum value and processing overflow will be done by force_time(). BRANCH=eve,fizz,poppy BUG=b:76182199 TEST=No build errors for npcx series. Passed test command of CL 979389 on npcx_evb. No symptom occurred during warm reset stress test on soraka. Change-Id: Ic645f7c5a2a1e49a3c1f3d7e089dd66b4bb75ac6 Signed-off-by: Mulin Chao <mlchao@nuvoton.com> Reviewed-on: https://chromium-review.googlesource.com/979874 Reviewed-by: Nicolas Boichat <drinkcat@chromium.org>
This commit is contained in:
@@ -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)
|
||||
{
|
||||
/*
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user