diff options
author | Randall Spangler <rspangler@chromium.org> | 2013-10-29 14:16:40 -0700 |
---|---|---|
committer | chrome-internal-fetch <chrome-internal-fetch@google.com> | 2014-02-13 21:57:46 +0000 |
commit | 31ee166e8e1c3f18cb2fb6fc491c1d0ffd7b25f6 (patch) | |
tree | d6c80a69e823799f990a224d273aa2749d813883 | |
parent | a7529e03addfb399b4d3b131e9e259daa201a1ae (diff) | |
download | chrome-ec-31ee166e8e1c3f18cb2fb6fc491c1d0ffd7b25f6.tar.gz |
CHERRY-PICK: lm4: fix enabling RTC alarm
All hibernate register writes must wait for the WC bit. When we're
enabling the RTC alarm, it's important to wait for the WC bit
afterwards, too, or else we could go into deep sleep before the write
to HIBIM is committed.
Also make sure that the normal hibernate() path enables the RTC alarm
if it has a timeout. This bug wasn't noticed until the low-power idle
code called system_reset_rtc_alarm(), since before then HIBIM was
initialized to 1 and just stayed there.
BUG=chrome-os-partner:25661
BRANCH=anywhere we use low power idle (wolf/leon, too)
TEST=with hacked firmware, note that HIBIM=1 just before the wfi
instruction in chip/lm4/clock.c
Change-Id: I6fff333ca15dfca6f25c9103a73f4c8f1cbe05ac
Original-Change-Id: Ie01b106ac6a6c5894811f9a333715b22ef896f82
Signed-off-by: Randall Spangler <rspangler@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/175013
Reviewed-by: Alec Berg <alecaberg@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/186269
Tested-by: Dave Parker <dparker@chromium.org>
Commit-Queue: Dave Parker <dparker@chromium.org>
-rw-r--r-- | chip/lm4/registers.h | 1 | ||||
-rw-r--r-- | chip/lm4/system.c | 16 |
2 files changed, 16 insertions, 1 deletions
diff --git a/chip/lm4/registers.h b/chip/lm4/registers.h index ac25724197..b87a7b55ec 100644 --- a/chip/lm4/registers.h +++ b/chip/lm4/registers.h @@ -194,6 +194,7 @@ static inline int lm4_fan_addr(int ch, int offset) #define LM4_HIBCTL_RTCEN (1 << 0) #define LM4_HIBERNATE_HIBIM REG32(0x400fc014) #define LM4_HIBERNATE_HIBRIS REG32(0x400fc018) +#define LM4_HIBERNATE_HIBMIS REG32(0x400fc01c) #define LM4_HIBERNATE_HIBIC REG32(0x400fc020) #define LM4_HIBERNATE_HIBRTCT REG32(0x400fc024) #define LM4_HIBERNATE_HIBRTCSS REG32(0x400fc028) diff --git a/chip/lm4/system.c b/chip/lm4/system.c index 05f6def1bd..02586bfab1 100644 --- a/chip/lm4/system.c +++ b/chip/lm4/system.c @@ -190,7 +190,7 @@ void __attribute__((section(".iram.text"))) __enter_hibernate(int hibctl) * * @return the real-time clock seconds value. */ -static uint32_t system_get_rtc_sec_subsec(uint32_t *ss_ptr) +uint32_t system_get_rtc_sec_subsec(uint32_t *ss_ptr) { uint32_t rtc, rtc2; uint32_t rtcss, rtcss2; @@ -289,6 +289,14 @@ void system_set_rtc_alarm(uint32_t seconds, uint32_t microseconds) /* Enable RTC interrupt on match */ wait_for_hibctl_wc(); LM4_HIBERNATE_HIBIM = 1; + + /* + * Wait for the write to commit. This ensures that the RTC interrupt + * actually gets enabled. This is important if we're about to switch + * the system to the 30 kHz oscillator, which might prevent the write + * from comitting. + */ + wait_for_hibctl_wc(); } /** @@ -297,9 +305,11 @@ void system_set_rtc_alarm(uint32_t seconds, uint32_t microseconds) void system_reset_rtc_alarm(void) { /* Disable hibernate interrupts */ + wait_for_hibctl_wc(); LM4_HIBERNATE_HIBIM = 0; /* Clear interrupts */ + wait_for_hibctl_wc(); LM4_HIBERNATE_HIBIC = LM4_HIBERNATE_HIBRIS; } @@ -344,6 +354,10 @@ static void hibernate(uint32_t seconds, uint32_t microseconds, uint32_t flags) flags |= HIBDATA_WAKE_RTC; set_hibernate_rtc_match_time(seconds, microseconds); + + /* Enable RTC interrupt on match */ + wait_for_hibctl_wc(); + LM4_HIBERNATE_HIBIM = 1; } else { hibctl &= ~LM4_HIBCTL_RTCWEN; } |