diff options
author | Bill Richardson <wfrichar@chromium.org> | 2016-06-24 14:52:27 -0700 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2016-06-25 02:29:10 -0700 |
commit | 9a644c429af9f299445962892666685233cb0a1b (patch) | |
tree | 43210d5a992b2bff167afc207d323bd25d902c6e | |
parent | 264bca7e40cccd6f8576f69a6af32bd5bd0c1bfc (diff) | |
download | chrome-ec-9a644c429af9f299445962892666685233cb0a1b.tar.gz |
Cr50: Set the default idle action to Sleep
When the Cr50 doesn't have anything else to do and it's been a
while since anyone has communicated with it (10 seconds via UART,
1 second via SPI, and the USB bus has stopped sending SOF
packets), it enters one of three idle states:
wfi = fully powered, just waiting for an interrupt.
sleep = low power mode, but RAM is preserved. It resumes quickly.
deep sleep = hibernate. RAM is lost, resume is a warm boot
You can get/set the idle state with the "idle" console command.
BUG=chrome-os-partner:49955,chrome-os-partner:54331
BRANCH=none
TEST=make buildall
To test it:
* I've only tested on the debug board, because I need a serial
console (not serial-over-USB) to see if it's asleep or not.
* I haven't been able to knowingly force USB Suspend on my
workstation, so to fake it I just unplug the USB cables.
* Wait 10-12 seconds after typing anything on the serial console,
then press a key. If the Cr50 was asleep, the first character
will be lost. If it wasn't, you'll see the character echoed
immediately.
Change-Id: Icc213e50b0c38f8c2b16bcd9960e2e5550b43180
Signed-off-by: Bill Richardson <wfrichar@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/356123
Reviewed-by: Vadim Bendebury <vbendeb@chromium.org>
-rw-r--r-- | chip/g/idle.c | 21 |
1 files changed, 16 insertions, 5 deletions
diff --git a/chip/g/idle.c b/chip/g/idle.c index dc003d3eef..1686474ba9 100644 --- a/chip/g/idle.c +++ b/chip/g/idle.c @@ -12,13 +12,17 @@ /* What to do when we're just waiting */ static enum { - IDLE_WFI, /* default */ + DONT_KNOW, + IDLE_WFI, IDLE_SLEEP, IDLE_DEEP_SLEEP, NUM_CHOICES } idle_action; +#define IDLE_DEFAULT IDLE_SLEEP + static const char const *idle_name[] = { + "invalid", "wfi", "sleep", "deep sleep", @@ -31,7 +35,7 @@ static int command_idle(int argc, char **argv) if (argc > 1) { c = tolower(argv[1][0]); - for (i = 0; i < ARRAY_SIZE(idle_name); i++) + for (i = 1; i < ARRAY_SIZE(idle_name); i++) if (idle_name[i][0] == c) { idle_action = i; break; @@ -129,10 +133,17 @@ void __idle(void) { int sleep_ok, sleep_delay_passed; - /* Preserved across soft reboots, but not hard */ + /* + * This register is preserved across soft reboots, but not hard. It + * defaults to zero, which is how we can tell whether this is the + * preserved value or not. We only need to remember it because we might + * change it with the console command. + */ idle_action = GREG32(PMU, PWRDN_SCRATCH17); - if (idle_action >= NUM_CHOICES) - idle_action = IDLE_WFI; + if (idle_action == DONT_KNOW || idle_action >= NUM_CHOICES) { + idle_action = IDLE_DEFAULT; + GREG32(PMU, PWRDN_SCRATCH17) = idle_action; + } while (1) { |