summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlec Berg <alecaberg@chromium.org>2013-11-04 12:00:24 -0800
committerchrome-internal-fetch <chrome-internal-fetch@google.com>2013-11-05 03:38:08 +0000
commit48dfd8c5ee5679c13b3931cac843b4e3dc1f9ed4 (patch)
tree4373b26eae8db24404df1d9dfbb65647b18a2071
parentc47e4ec7d1c28c2fb97640ede5900e6381ea39cc (diff)
downloadchrome-ec-release-R32-4920.B.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.c38
-rw-r--r--include/config.h6
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