diff options
author | Alec Berg <alecaberg@chromium.org> | 2013-11-04 12:00:24 -0800 |
---|---|---|
committer | chrome-internal-fetch <chrome-internal-fetch@google.com> | 2013-11-05 03:38:08 +0000 |
commit | 48dfd8c5ee5679c13b3931cac843b4e3dc1f9ed4 (patch) | |
tree | 4373b26eae8db24404df1d9dfbb65647b18a2071 | |
parent | c47e4ec7d1c28c2fb97640ede5900e6381ea39cc (diff) | |
download | chrome-ec-48dfd8c5ee5679c13b3931cac843b4e3dc1f9ed4.tar.gz |
lm4: Fixed low power idle doesn't always wake up.stabilize-4920.6.Brelease-R32-4920.B
Temporary fix to the bug in which we miss wake events when in deep
sleep with the LFIOSC (32kHz) clock and the EC is cold. This fix
involves simply using a faster clock, 250kHz, when in low speed
deep sleep. This fix consumes more power but solves the bug.
Renamed EC console command dsleepmask to dsleep.
BRANCH=none
BUG=chrome-os-partner:23678
TEST=Go in to low speed deep sleep by going into either S3 or G3
and letting the EC console timeout. Then freeze-spray the EC chip.
Wake up the EC via the console and make sure that the idlestats
show that we have not missed a deadline.
Change-Id: I4f9844f1937bc8c95cf1540502f7d8fb4cbc097e
Signed-off-by: Alec Berg <alecaberg@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/175614
Reviewed-by: Randall Spangler <rspangler@chromium.org>
-rw-r--r-- | chip/lm4/clock.c | 38 | ||||
-rw-r--r-- | include/config.h | 6 |
2 files changed, 32 insertions, 12 deletions
diff --git a/chip/lm4/clock.c b/chip/lm4/clock.c index 3f40264ef5..bb3ca3be30 100644 --- a/chip/lm4/clock.c +++ b/chip/lm4/clock.c @@ -236,7 +236,7 @@ void __idle(void) timestamp_t t0, t1, rtc_t0, rtc_t1; int next_delay = 0; int time_for_dsleep, margin_us; - int use_lfiosc; + int use_low_speed_clock; /* Enable the hibernate IRQ used to wake up from deep sleep */ system_enable_hib_interrupt(); @@ -301,25 +301,37 @@ void __idle(void) } /* - * Determine if we should use the LFIOSC (30kHz) or the - * PIOSC (16MHz) for the clock in deep sleep. Use the - * LFIOSC only if the sleep mask specifies that low + * Determine if we should use a lower clock speed or + * keep the same (16MHz) clock in deep sleep. Use the + * lower speed only if the sleep mask specifies that low * speed sleep is allowed, the console UART TX is not * busy, and the console UART buffer is empty. */ - use_lfiosc = LOW_SPEED_DEEP_SLEEP_ALLOWED && + use_low_speed_clock = LOW_SPEED_DEEP_SLEEP_ALLOWED && !uart_tx_in_progress() && uart_buffer_empty(); - /* Set the deep sleep clock register. */ - LM4_SYSTEM_DSLPCLKCFG = use_lfiosc ? 0x32 : 0x10; +#ifdef CONFIG_LOW_POWER_USE_LFIOSC + /* Set the deep sleep clock register. Use either the + * normal PIOSC (16MHz) or the LFIOSC (32kHz). */ + LM4_SYSTEM_DSLPCLKCFG = use_low_speed_clock ? + 0x32 : 0x10; +#else + /* + * Set the deep sleep clock register. Use either the + * PIOSC with no divider (16MHz) or the PIOSC with + * a /64 divider (250kHz). + */ + LM4_SYSTEM_DSLPCLKCFG = use_low_speed_clock ? + 0x1f800010 : 0x10; +#endif /* - * If using low speed (LFIOSC) clock, disable console. + * If using low speed clock, disable console. * This will also convert the console RX pin to a GPIO * and set an edge interrupt to wake us from deep sleep * if any action occurs on console. */ - if (use_lfiosc) + if (use_low_speed_clock) uart_enter_dsleep(); /* Set deep sleep bit. */ @@ -350,7 +362,7 @@ void __idle(void) force_time(t1); /* If using low speed clock, re-enable the console. */ - if (use_lfiosc) + if (use_low_speed_clock) uart_exit_dsleep(); /* Record time spent in deep sleep. */ @@ -358,6 +370,8 @@ void __idle(void) /* Calculate how close we were to missing deadline */ margin_us = next_delay - (int)(rtc_t1.val - rtc_t0.val); + if (margin_us < 0) + CPRINTF("[%T overslept by %dus]\n", -margin_us); /* Record the closest to missing a deadline. */ if (margin_us < dsleep_recovery_margin_us) @@ -699,7 +713,7 @@ DECLARE_CONSOLE_COMMAND(idlestats, command_idle_stats, /** * Configure deep sleep clock settings. */ -static int command_dsleepmask(int argc, char **argv) +static int command_dsleep(int argc, char **argv) { int v; @@ -734,7 +748,7 @@ static int command_dsleepmask(int argc, char **argv) return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(dsleepmask, command_dsleepmask, +DECLARE_CONSOLE_COMMAND(dsleep, command_dsleep, "[ on | off | <timeout> sec]", "Deep sleep clock settings:\nUse 'on' to force deep " "sleep not to use low speed clock.\nUse 'off' to " diff --git a/include/config.h b/include/config.h index 97262e78d2..f9e2a806a3 100644 --- a/include/config.h +++ b/include/config.h @@ -485,7 +485,13 @@ */ #define CONFIG_LID_SWITCH +/* + * Low power idle options. These are disabled by default and all boards that + * want to use low power idle must define it. When using the LFIOSC, the low + * frequency clock will be used to conserve even more power when possible. + */ #undef CONFIG_LOW_POWER_IDLE +#undef CONFIG_LOW_POWER_USE_LFIOSC /* Support LPC interface */ #undef CONFIG_LPC |