From 92d91adbdb38e5639c200ad65c4651274a8d07f9 Mon Sep 17 00:00:00 2001 From: Shawn Nematbakhsh Date: Wed, 9 Nov 2016 10:23:17 -0800 Subject: npcx: hwtimer: Fix 'slow' timer count just before overflow If our 32-bit usec timer is close to overflow, we may deep sleep several times in succession without making any adjustment to our count, causing deadlines on the other side (eg. HOOK_TICK expiration) to be reached much slower than expected. Avoid this by not entering deep sleep if our timer is about to overflow. This will result in a <= HOOK_TICK_INTERVAL (200ms interval) period of not entering deep sleep, every ~4300 seconds. BUG=chrome-os-partner:59240 BRANCH=gru TEST=Verify 3x kevin units survive 16 hours in S3 without EC watchdog. Change-Id: I2126458be8820f78212e19c2bb79242ff1194f6f Signed-off-by: Shawn Nematbakhsh Reviewed-on: https://chromium-review.googlesource.com/409673 Commit-Ready: Shawn N Tested-by: Shawn N Reviewed-by: Shawn N --- chip/npcx/clock.c | 7 +++++++ chip/npcx/hwtimer.c | 5 ----- chip/npcx/hwtimer_chip.h | 5 +++++ 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/chip/npcx/clock.c b/chip/npcx/clock.c index 718d7733b7..196248c592 100644 --- a/chip/npcx/clock.c +++ b/chip/npcx/clock.c @@ -312,6 +312,13 @@ void __idle(void) /* Do we have enough time before next event to deep sleep. */ if (DEEP_SLEEP_ALLOWED && + /* + * Our HW timer doesn't tick in deep sleep - we do manual + * adjustment based on sleep duration after wake. Avoid + * the tricky overflow case by waiting out the period just + * before overflow. + */ + next_evt != EVT_MAX_EXPIRED_US && /* Ensure event hasn't already expired */ next_evt > t0.le.lo && /* Ensure we have sufficient time before expiration */ diff --git a/chip/npcx/hwtimer.c b/chip/npcx/hwtimer.c index 48204724eb..366f1624f4 100644 --- a/chip/npcx/hwtimer.c +++ b/chip/npcx/hwtimer.c @@ -18,11 +18,6 @@ #include "timer.h" #include "util.h" -/* Use ITIM32 as main hardware timer */ -#define TICK_ITIM32_MAX_CNT 0xFFFFFFFF -/* Maximum deadline of event */ -#define EVT_MAX_EXPIRED_US 0xFFFFFFFF - /* Depth of event timer */ #define TICK_EVT_DEPTH 16 /* Depth of event timer Unit: bits */ #define TICK_EVT_INTERVAL (1 << TICK_EVT_DEPTH) /* Unit: us */ diff --git a/chip/npcx/hwtimer_chip.h b/chip/npcx/hwtimer_chip.h index 52b17c7dee..08cf8e278f 100644 --- a/chip/npcx/hwtimer_chip.h +++ b/chip/npcx/hwtimer_chip.h @@ -12,6 +12,11 @@ #define ITIM_EVENT_NO ITIM16_1 #define ITIM_WDG_NO ITIM16_5 +/* Use ITIM32 as main hardware timer */ +#define TICK_ITIM32_MAX_CNT 0xFFFFFFFF +/* Maximum deadline of event */ +#define EVT_MAX_EXPIRED_US TICK_ITIM32_MAX_CNT + /* Clock source for ITIM16 */ enum ITIM_SOURCE_CLOCK_T { ITIM_SOURCE_CLOCK_APB2 = 0, -- cgit v1.2.1