diff options
author | Archana Patni <archana.patni@intel.com> | 2016-11-08 12:45:40 +0530 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2016-11-17 16:09:44 -0800 |
commit | b8406119c2c51acc46c551ef0930c51153657613 (patch) | |
tree | 7db348bfbc3affa88c6d452f70e7f349674ac642 /power | |
parent | 82aaccad4022737ba4c21cbeb119d73e51dff5f1 (diff) | |
download | chrome-ec-b8406119c2c51acc46c551ef0930c51153657613.tar.gz |
Apollolake: Enter/exit from S0ix based on host commands from kernel
This patch changes the entry/exit model for S0ix from a PCH
SLP_S0 signal based model to a hybrid host event/direct interrupt
model. The kernel will send host events on kernel freeze/thaw exit;
EC will initiate the S0ix entry based on host command and exit via
another host command from kernel.
The assertion of SLP_S0 comes later than HC(suspend) and deasserion
of SLP_S0 comes earlier than HC(resume).
________ ________
SLP_S0 |______________________|
_____ ________
HC |___________________________|
BRANCH=none
BUG=chrome-os-partner:58740
TEST=Build/flash EC and check 'echo freeze > /sys/power/state'
command in OS shell. Verify idle state transitions during display off
and periodic wakes from S0ix do not lead to state transitions in EC.
Change-Id: Ie18c6c2ac8998f59141641567d1d740cd72c2d2e
Signed-off-by: Kyoung Kim <kyoung.il.kim@intel.com>
Signed-off-by: Subramony Sesha <subramony.sesha@intel.com>
Signed-off-by: Divagar Mohandass <divagar.mohandass@intel.com>
Signed-off-by: Archana Patni <archana.patni@intel.com>
Reviewed-on: https://chromium-review.googlesource.com/401072
Commit-Ready: Vijay P Hiremath <vijay.p.hiremath@intel.com>
Tested-by: Vijay P Hiremath <vijay.p.hiremath@intel.com>
Reviewed-by: Shawn N <shawnn@chromium.org>
Reviewed-by: Furquan Shaikh <furquan@chromium.org>
Diffstat (limited to 'power')
-rw-r--r-- | power/apollolake.c | 79 | ||||
-rw-r--r-- | power/common.c | 25 |
2 files changed, 43 insertions, 61 deletions
diff --git a/power/apollolake.c b/power/apollolake.c index 3710579c3e..b93a1e25c2 100644 --- a/power/apollolake.c +++ b/power/apollolake.c @@ -11,6 +11,8 @@ #include "console.h" #include "hooks.h" #include "host_command.h" +#include "lid_switch.h" +#include "lpc.h" #include "power.h" #include "power_button.h" #include "system.h" @@ -25,20 +27,13 @@ /* Input state flags */ #define IN_RSMRST_N POWER_SIGNAL_MASK(X86_RSMRST_N) #define IN_ALL_SYS_PG POWER_SIGNAL_MASK(X86_ALL_SYS_PG) -#define IN_SLP_S0_N POWER_SIGNAL_MASK(X86_SLP_S0_N) #define IN_SLP_S3_N POWER_SIGNAL_MASK(X86_SLP_S3_N) #define IN_SLP_S4_N POWER_SIGNAL_MASK(X86_SLP_S4_N) #define IN_SUSPWRDNACK POWER_SIGNAL_MASK(X86_SUSPWRDNACK) #define IN_SUS_STAT_N POWER_SIGNAL_MASK(X86_SUS_STAT_N) -#ifdef CONFIG_POWER_S0IX -#define IN_ALL_PM_SLP_DEASSERTED (IN_SLP_S0_N | \ - IN_SLP_S3_N | \ - IN_SLP_S4_N) -#else #define IN_ALL_PM_SLP_DEASSERTED (IN_SLP_S3_N | \ IN_SLP_S4_N) -#endif #define IN_PGOOD_ALL_CORE (IN_RSMRST_N) @@ -228,7 +223,8 @@ static enum power_state _power_handle_state(enum power_state state) chipset_force_shutdown(); return POWER_S0S3; #ifdef CONFIG_POWER_S0IX - } else if ((gpio_get_level(GPIO_PCH_SLP_S0_L) == 0) && + } else if ((power_get_host_sleep_state() == + HOST_SLEEP_EVENT_S0IX_SUSPEND) && (gpio_get_level(GPIO_PCH_SLP_S3_L) == 1)) { return POWER_S0S0ix; #endif @@ -244,7 +240,8 @@ static enum power_state _power_handle_state(enum power_state state) /* * TODO: add code for unexpected power loss */ - if ((gpio_get_level(GPIO_PCH_SLP_S0_L) == 1) && + if ((power_get_host_sleep_state() == + HOST_SLEEP_EVENT_S0IX_RESUME) && (gpio_get_level(GPIO_PCH_SLP_S3_L) == 1)) { return POWER_S0ixS0; } @@ -294,6 +291,14 @@ static enum power_state _power_handle_state(enum power_state state) /* Call hooks now that rails are up */ hook_notify(HOOK_CHIPSET_STARTUP); + +#ifdef CONFIG_POWER_S0IX + /* + * Clearing the S0ix flag on the path to S0 + * to handle any reset conditions. + */ + power_reset_host_sleep_state(HOST_SLEEP_EVENT_S0IX_RESUME); +#endif return POWER_S3; case POWER_S3S0: @@ -340,6 +345,10 @@ static enum power_state _power_handle_state(enum power_state state) */ enable_sleep(SLEEP_MASK_AP_RUN); +#ifdef CONFIG_POWER_S0IX + /* re-init S0ix flag */ + power_reset_host_sleep_state(HOST_SLEEP_EVENT_S0IX_RESUME); +#endif return POWER_S3; #ifdef CONFIG_POWER_S0IX @@ -424,58 +433,6 @@ enum power_state power_handle_state(enum power_state state) return new_state; } -#ifdef CONFIG_POWER_S0IX -static struct { - int required; /* indicates de-bounce required. */ - int done; /* debounced */ -} slp_s0_debounce = { - .required = 0, - .done = 1, -}; - -int chipset_get_ps_debounced_level(enum gpio_signal signal) -{ - /* - * If power state is updated in power_update_signal() by any interrupts - * other than SLP_S0 during the 1 msec pulse(invalid SLP_S0 signal), - * reading SLP_S0 should be corrected with slp_s0_debounce.done flag. - */ - int level = gpio_get_level(signal); - - return (signal == GPIO_PCH_SLP_S0_L) ? - (level & slp_s0_debounce.done) : level; -} - -static void slp_s0_assertion_deferred(void) -{ - int s0_level = gpio_get_level(GPIO_PCH_SLP_S0_L); - /* - (s0_level != 0) || - ((s0_level == 0) && (slp_s0_debounce.required == 0)) - */ - if (s0_level == slp_s0_debounce.required) { - if (s0_level) - slp_s0_debounce.done = 1; /* debounced! */ - - power_signal_interrupt(GPIO_PCH_SLP_S0_L); - } - - slp_s0_debounce.required = 0; -} -DECLARE_DEFERRED(slp_s0_assertion_deferred); - -void power_signal_interrupt_S0(enum gpio_signal signal) -{ - if (gpio_get_level(GPIO_PCH_SLP_S0_L)) { - slp_s0_debounce.required = 1; - hook_call_deferred(slp_s0_assertion_deferred, 3 * MSEC); - } else if (slp_s0_debounce.required == 0) { - slp_s0_debounce.done = 0; - slp_s0_assertion_deferred(); - } -} -#endif - /** * chipset check if PLTRST# is valid. * diff --git a/power/common.c b/power/common.c index 832e1cc251..c9f58e92db 100644 --- a/power/common.c +++ b/power/common.c @@ -735,6 +735,23 @@ static int host_command_host_sleep_event(struct host_cmd_handler_args *args) const struct ec_params_host_sleep_event *p = args->params; host_sleep_state = p->sleep_event; + +#ifdef CONFIG_POWER_S0IX + if (p->sleep_event == HOST_SLEEP_EVENT_S0IX_SUSPEND) { + CPRINTS("S0ix sus evt"); + task_wake(TASK_ID_CHIPSET); + } else if (p->sleep_event == HOST_SLEEP_EVENT_S0IX_RESUME) { + CPRINTS("S0ix res evt"); + /* + * For all scenarios where lid is not open + * this will be trigerred when other wake + * sources like keyboard, trackpad are used. + */ + if (!chipset_in_state(CHIPSET_STATE_ON)) + task_wake(TASK_ID_CHIPSET); + } +#endif /* CONFIG_POWER_S0IX */ + return EC_RES_SUCCESS; } DECLARE_HOST_COMMAND(EC_CMD_HOST_SLEEP_EVENT, @@ -745,4 +762,12 @@ enum host_sleep_event power_get_host_sleep_state(void) { return host_sleep_state; } + +#ifdef CONFIG_POWER_S0IX +void power_reset_host_sleep_state(enum host_sleep_event sleep_event) +{ + host_sleep_state = sleep_event; +} +#endif /* CONFIG_POWER_S0IX */ + #endif /* CONFIG_POWER_TRACK_HOST_SLEEP_STATE */ |