From ebdb6a62aa46f144bdb24da2eea3677ba4329482 Mon Sep 17 00:00:00 2001 From: Shawn Nematbakhsh Date: Fri, 4 Nov 2016 14:33:24 -0700 Subject: [PATCH] npcx: Fix hwtimers - Wait for ITEN bit to be set / cleared, since writing this bit just sets a 'request'. - Ensure ITIM_EVENT_NO reg is set with minimum value 1, per the datasheet. - Don't dsleep if our wake event is in the past (eg. wake event will occur any time now) BUG=chrome-os-partner:59240 BRANCH=gru TEST=Manual on kevin, verify that dsleep period never exceeds expected wait period. Also verify that EC watchdog doesn't occur after 5 hours in S3. Signed-off-by: Shawn Nematbakhsh Change-Id: Iedb2723c3f12b74dea66082b1d8b8ce1b6e7d945 Reviewed-on: https://chromium-review.googlesource.com/409672 Commit-Ready: Shawn N Tested-by: Shawn N Reviewed-by: Shawn N --- chip/npcx/clock.c | 13 +++++++++---- chip/npcx/hwtimer.c | 14 ++++++++++++-- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/chip/npcx/clock.c b/chip/npcx/clock.c index 044afad142..718d7733b7 100644 --- a/chip/npcx/clock.c +++ b/chip/npcx/clock.c @@ -286,6 +286,7 @@ void __idle(void) #else timestamp_t t0, t1; + uint32_t next_evt; uint32_t next_evt_us; uint16_t evt_count; @@ -307,12 +308,16 @@ void __idle(void) /* Compute event delay */ t0 = get_time(); - next_evt_us = __hw_clock_event_get() - t0.le.lo; + next_evt = __hw_clock_event_get(); /* Do we have enough time before next event to deep sleep. */ - if (DEEP_SLEEP_ALLOWED && (next_evt_us > WAKE_INTERVAL) - /* Make sure it's over console expired time */ - && (t0.val > console_expire_time.val)) { + if (DEEP_SLEEP_ALLOWED && + /* Ensure event hasn't already expired */ + next_evt > t0.le.lo && + /* Ensure we have sufficient time before expiration */ + next_evt - t0.le.lo > WAKE_INTERVAL && + /* Make sure it's over console expired time */ + t0.val > console_expire_time.val) { #if DEBUG_CLK /* Use GPIO to indicate SLEEP mode */ CLEAR_BIT(NPCX_PDOUT(0), 0); diff --git a/chip/npcx/hwtimer.c b/chip/npcx/hwtimer.c index 753d37f9c5..48204724eb 100644 --- a/chip/npcx/hwtimer.c +++ b/chip/npcx/hwtimer.c @@ -16,6 +16,7 @@ #include "console.h" #include "task.h" #include "timer.h" +#include "util.h" /* Use ITIM32 as main hardware timer */ #define TICK_ITIM32_MAX_CNT 0xFFFFFFFF @@ -86,6 +87,7 @@ void __hw_clock_event_set(uint32_t deadline) /* Event module disable */ CLEAR_BIT(NPCX_ITCTS(ITIM_EVENT_NO), NPCX_ITCTS_ITEN); + /* * ITIM count down : event expired : Unit: 1/32768 sec * It must exceed evt_expired_us for process_timers function @@ -96,11 +98,20 @@ void __hw_clock_event_set(uint32_t deadline) evt_cnt, evt_cnt_us); evt_cnt = TICK_EVT_MAX_CNT; } - NPCX_ITCNT16(ITIM_EVENT_NO) = evt_cnt; + + /* Wait for module disable to take effect before updating count */ + while (IS_BIT_SET(NPCX_ITCTS(ITIM_EVENT_NO), NPCX_ITCTS_ITEN)) + ; + + NPCX_ITCNT16(ITIM_EVENT_NO) = MAX(evt_cnt, 1); /* Event module enable */ SET_BIT(NPCX_ITCTS(ITIM_EVENT_NO), NPCX_ITCTS_ITEN); + /* Wait for module enable */ + while (!IS_BIT_SET(NPCX_ITCTS(ITIM_EVENT_NO), NPCX_ITCTS_ITEN)) + ; + /* Enable interrupt of ITIM */ task_enable_irq(ITIM16_INT(ITIM_EVENT_NO)); } @@ -200,7 +211,6 @@ void hw_clock_source_set_preload(uint32_t ts, uint8_t clear) { /* ITIM32 module disable */ CLEAR_BIT(NPCX_ITCTS(ITIM32), NPCX_ITCTS_ITEN); - CLEAR_BIT(NPCX_ITCTS(ITIM32), NPCX_ITCTS_CKSEL); /* Set preload counter to current time */