summaryrefslogtreecommitdiff
path: root/chip/npcx/hwtimer.c
diff options
context:
space:
mode:
authorMulin Chao <mlchao@nuvoton.com>2016-02-16 14:17:42 +0800
committerchrome-bot <chrome-bot@chromium.org>2016-05-11 21:24:32 -0700
commit3ccb91fe10271f8af6f097483efac9a177d11a31 (patch)
treefa3e6ecf1d4bf8dd53c8a12dce4ff0389ff02367 /chip/npcx/hwtimer.c
parentb6b6430daa81e44519e92e37fe57ccd8312cfcf1 (diff)
downloadchrome-ec-3ccb91fe10271f8af6f097483efac9a177d11a31.tar.gz
npcx: Fixed bug that unexpected value of timer which source clock is 32K
In rare case, FW read the unexpected counter value of timer which source clock is 32K (Watchdog timer and ITIM16/32 which use 32K source clock). The root cause is the clocks between reading registers and timer's are asynchronous. It has a chance to get invalid counter value when timer is under transaction edge. The solution is using two consecutive equal readings to make sure the counter value is valid. Beside different source clocks of timer, we also found there's chip's bug which causes unexpected value of timer. If an interrupt that occurs very shortly before entering deep idle with instant wakeup, it might result in disruptive execution (such as skipping some instructions or hard fault) after "wfi". The workaround is adding the same bypass for idle in deep idle section. Modified sources: 1. clock.c: Add bypass for instant wakeup from deep sleep. 2. hwtimer.c: Add consecutive reading function for event timer. 3. watchdog.c: Add consecutive reading function for watchdog timer. BUG=chrome-os-partner:34346 TEST=make buildall -j; test nuvoton IC specific drivers BRANCH=none Change-Id: I7c9f1fb9618a3c29826d8f4599864a8dac4203bf Signed-off-by: Mulin Chao <mlchao@nuvoton.com> Reviewed-on: https://chromium-review.googlesource.com/327356 Reviewed-by: Shawn N <shawnn@chromium.org>
Diffstat (limited to 'chip/npcx/hwtimer.c')
-rw-r--r--chip/npcx/hwtimer.c10
1 files changed, 8 insertions, 2 deletions
diff --git a/chip/npcx/hwtimer.c b/chip/npcx/hwtimer.c
index 5a7fa8b38c..196fcf985c 100644
--- a/chip/npcx/hwtimer.c
+++ b/chip/npcx/hwtimer.c
@@ -117,7 +117,13 @@ uint32_t __hw_clock_event_get(void)
/* Get current counter value of event timer */
uint16_t __hw_clock_event_count(void)
{
- return NPCX_ITCNT16(ITIM_EVENT_NO);
+ uint16_t cnt;
+ /* Wait for two consecutive equal values are read */
+ do {
+ cnt = NPCX_ITCNT16(ITIM_EVENT_NO);
+ } while (cnt != NPCX_ITCNT16(ITIM_EVENT_NO));
+
+ return cnt;
}
/* Returns time delay cause of deep idle */
@@ -125,7 +131,7 @@ uint32_t __hw_clock_get_sleep_time(uint16_t pre_evt_cnt)
{
fp_t evt_tick = FLOAT_TO_FP(SECOND/(float)INT_32K_CLOCK);
uint32_t sleep_time;
- uint16_t cnt = NPCX_ITCNT16(ITIM_EVENT_NO);
+ uint16_t cnt = __hw_clock_event_count();
/* Event has been triggered but timer ISR dosen't handle it */
if (IS_BIT_SET(NPCX_ITCTS(ITIM_EVENT_NO), NPCX_ITCTS_TO_STS))