From b383d4c6b8218300c14c6f853853cc09ea761c9d Mon Sep 17 00:00:00 2001 From: Vic Yang Date: Mon, 6 Aug 2012 21:53:50 +0800 Subject: Hibernate when in G3 for 24 hours To save power, make the EC hibernate after we go into G3 for 24 hours. BUG=chrome-os-partner:9386 TEST=Use "hibdelay 5" to change the delay to 5 seconds. Remove AC power, power down and check device hibernates after 5 seconds in G3. Connect AC power, power down, wait for G3. Remove AC power and check device hibernates after 5 seconds. Change-Id: I6fb907c904798076a763f22bd35f53f7424d6200 Reviewed-on: https://gerrit.chromium.org/gerrit/29400 Reviewed-by: Randall Spangler Commit-Ready: Vic Yang Tested-by: Vic Yang --- common/x86_power.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 62 insertions(+), 2 deletions(-) diff --git a/common/x86_power.c b/common/x86_power.c index 4d4e0fef5d..c58617c788 100644 --- a/common/x86_power.c +++ b/common/x86_power.c @@ -102,6 +102,11 @@ static uint32_t in_debug; /* Signal values which print debug output */ static int want_g3_exit; /* Should we exit the G3 state? */ static int throttle_cpu; /* Throttle CPU? */ +/* When did we enter G3? */ +static uint64_t last_shutdown_time; +/* Delay before go into hibernation in seconds*/ +static uint32_t hibernate_delay = 86400; /* 24 Hrs */ + /* Update input signal state */ static void update_in_signals(void) { @@ -330,6 +335,11 @@ static int x86_power_ac_change(void) } else { CPRINTF("[%T x86 AC off]\n"); /* TODO: (crosbug.com/p/9609) disable turbo */ + + if (state == X86_G3) { + last_shutdown_time = get_time().val; + task_wake(TASK_ID_X86POWER); + } } return EC_SUCCESS; @@ -357,6 +367,9 @@ static int x86_power_init(void) update_in_signals(); in_want = 0; + /* The initial state is G3. Set shut down timestamp to now. */ + last_shutdown_time = get_time().val; + /* * If we're switching between images without rebooting, see if the x86 * is already powered on; if so, leave it there instead of cycling @@ -408,6 +421,8 @@ DECLARE_HOOK(HOOK_INIT, x86_power_init, HOOK_PRIO_INIT_CHIPSET); void x86_power_task(void) { + uint64_t time_now; + while (1) { CPRINTF("[%T x86 power state %d = %s, in 0x%04x]\n", state, state_names[state], in_signals); @@ -420,9 +435,24 @@ void x86_power_task(void) break; } - /* Steady state; wait for a message */ in_want = 0; - task_wait_event(-1); + if (power_ac_present()) + task_wait_event(-1); + else { + uint64_t target_time = last_shutdown_time + + hibernate_delay * 1000000ull; + time_now = get_time().val; + if (time_now > target_time) { + /* Time's up. Hibernate as long as + * possible. */ + system_hibernate(0xffffffff, 0); + } + else { + /* Wait for a message */ + task_wait_event(target_time - time_now); + } + } + break; case X86_S5: @@ -625,6 +655,9 @@ void x86_power_task(void) gpio_set_level(GPIO_PCH_DPWROK, 0); gpio_set_level(GPIO_PCH_RSMRSTn, 0); + /* Record the time we go into G3 */ + last_shutdown_time = get_time().val; + state = X86_G3; break; } @@ -702,6 +735,33 @@ DECLARE_CONSOLE_COMMAND(x86indebug, command_x86indebug, "Get/set x86 input debug mask", NULL); +static int command_hibernation_delay(int argc, char **argv) +{ + char *e; + uint32_t time_g3 = ((uint32_t)(get_time().val - last_shutdown_time)) + / 1000000; + + if (argc >= 2) { + uint32_t s = strtoi(argv[1], &e, 0); + if (*e) + return EC_ERROR_PARAM1; + + hibernate_delay = s; + } + + /* Print the current setting */ + ccprintf("Hibernation delay: %d s\n", hibernate_delay); + if (state == X86_G3 && !power_ac_present()) { + ccprintf("Time G3: %d s\n", time_g3); + ccprintf("Time left: %d s\n", hibernate_delay - time_g3); + } + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(hibdelay, command_hibernation_delay, + "[sec]", + "Set the delay before going into hibernation", + NULL); + /*****************************************************************************/ /* Host commands */ -- cgit v1.2.1