summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlec Berg <alecaberg@chromium.org>2013-11-04 12:00:24 -0800
committerDave Parker <dparker@chromium.org>2013-11-20 22:02:48 +0000
commit4d5e7608c81e2d4439ca89eafe0b304618587b82 (patch)
treee58a36b80dbf869c25de816a5fe9ee4f25bb4731
parent82bd75809c77045b5ac9a737aff43109861c9122 (diff)
downloadchrome-ec-4d5e7608c81e2d4439ca89eafe0b304618587b82.tar.gz
CHERRY-PICK: lm4: Fixed low power idle doesn't always wake up.
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=leon BUG=chrome-os-partner:24136 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: I2e98a39274060033c3812c1efc9965dba37bc87f Original-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> Reviewed-on: https://chromium-review.googlesource.com/177348 Reviewed-by: Dave Parker <dparker@chromium.org> Tested-by: Dave Parker <dparker@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 bbd2e503d1..1d58e59e3d 100644
--- a/chip/lm4/clock.c
+++ b/chip/lm4/clock.c
@@ -235,7 +235,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();
@@ -300,25 +300,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. */
@@ -349,7 +361,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. */
@@ -357,6 +369,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)
@@ -697,7 +711,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;
@@ -732,7 +746,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 651fcd0616..6ee78526f6 100644
--- a/include/config.h
+++ b/include/config.h
@@ -408,7 +408,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
/* Compile support for LPC interface */
#undef CONFIG_LPC