From 9b47a0812d963c4c02d47655741f63618bd41a22 Mon Sep 17 00:00:00 2001 From: Vijay Hiremath Date: Fri, 11 Nov 2016 08:19:15 -0800 Subject: skylake: Add support to S0iX based on host commands from Kernel Picked the code from Glados branch. Change-Id: I4bf114235c4d542dd7cf0dad6427c771e54d4611 https://chromium-review.googlesource.com/#/c/331358/ BUG=chrome-os-partner:59742 BRANCH=none TEST=make buildall -j Change-Id: Ib79f1209dfd9e6a9de0438cb1866bba2939e5393 Signed-off-by: Vijay Hiremath Reviewed-on: https://chromium-review.googlesource.com/410036 Commit-Ready: Vijay P Hiremath Tested-by: Vijay P Hiremath Reviewed-by: Furquan Shaikh Reviewed-by: Kevin K Wong --- board/chell/board.c | 1 - board/chell/board.h | 1 - board/chell/gpio.inc | 2 +- include/power.h | 10 ----- power/common.c | 4 -- power/skylake.c | 107 +++++++++++++++++++++++++-------------------------- 6 files changed, 54 insertions(+), 71 deletions(-) diff --git a/board/chell/board.c b/board/chell/board.c index a930e45051..2d59ab68fe 100644 --- a/board/chell/board.c +++ b/board/chell/board.c @@ -82,7 +82,6 @@ void usb1_evt(enum gpio_signal signal) /* power signal list. Must match order of enum power_signal. */ const struct power_signal_info power_signal_list[] = { {GPIO_RSMRST_L_PGOOD, 1, "RSMRST_N_PWRGD"}, - {GPIO_PCH_SLP_S0_L, 1, "SLP_S0_DEASSERTED"}, {GPIO_PCH_SLP_S3_L, 1, "SLP_S3_DEASSERTED"}, {GPIO_PCH_SLP_S4_L, 1, "SLP_S4_DEASSERTED"}, {GPIO_PCH_SLP_SUS_L, 1, "SLP_SUS_DEASSERTED"}, diff --git a/board/chell/board.h b/board/chell/board.h index ffac383c9f..7b7033208b 100644 --- a/board/chell/board.h +++ b/board/chell/board.h @@ -163,7 +163,6 @@ enum pwm_channel { /* power signal definitions */ enum power_signal { X86_RSMRST_L_PWRGD = 0, - X86_SLP_S0_DEASSERTED, X86_SLP_S3_DEASSERTED, X86_SLP_S4_DEASSERTED, X86_SLP_SUS_DEASSERTED, diff --git a/board/chell/gpio.inc b/board/chell/gpio.inc index 2d2d61c60f..d8da255b09 100644 --- a/board/chell/gpio.inc +++ b/board/chell/gpio.inc @@ -17,7 +17,6 @@ GPIO_INT(POWER_BUTTON_L, PIN(35), GPIO_INT_BOTH, power_button_interrupt) GPIO_INT(RSMRST_L_PGOOD, PIN(63), GPIO_INT_BOTH, power_signal_interrupt) GPIO_INT(PCH_SLP_S4_L, PIN(200), GPIO_INT_BOTH, power_signal_interrupt) GPIO_INT(PCH_SLP_S3_L, PIN(206), GPIO_INT_BOTH, power_signal_interrupt) -GPIO_INT(PCH_SLP_S0_L, PIN(211), GPIO_INT_BOTH, power_signal_interrupt_S0) GPIO_INT(PCH_SLP_SUS_L, PIN(12), GPIO_INT_BOTH, power_signal_interrupt) GPIO_INT(PMIC_INT_L, PIN(50), GPIO_INT_FALLING, power_signal_interrupt) GPIO_INT(PD_MCU_INT, PIN(122), GPIO_INT_FALLING | GPIO_PULL_UP, pd_mcu_interrupt) @@ -56,6 +55,7 @@ GPIO(PCH_RSMRST_L, PIN(143), GPIO_OUT_LOW) GPIO(PCH_RTCRST, PIN(163), GPIO_OUT_LOW) GPIO(SYS_RESET_L, PIN(121), GPIO_ODR_HIGH) GPIO(ENTERING_RW, PIN(41), GPIO_OUT_LOW) +GPIO(PCH_SLP_S0_L, PIN(211), GPIO_INPUT) /* Devices and power */ GPIO(PP1800_DX_DMIC_EN, PIN(11), GPIO_OUT_LOW) diff --git a/include/power.h b/include/power.h index b81a952156..6a133749bf 100644 --- a/include/power.h +++ b/include/power.h @@ -117,20 +117,10 @@ enum power_state power_handle_state(enum power_state state); */ #ifdef HAS_TASK_CHIPSET void power_signal_interrupt(enum gpio_signal signal); -#ifdef CONFIG_POWER_S0IX -void power_signal_interrupt_S0(enum gpio_signal signal); -#endif #else static inline void power_signal_interrupt(enum gpio_signal signal) { } -#ifdef CONFIG_POWER_S0IX -static inline void power_signal_interrupt_S0(enum gpio_signal signal) { } -#endif #endif /* !HAS_TASK_CHIPSET */ -#ifdef CONFIG_POWER_S0IX -int chipset_get_ps_debounced_level(enum gpio_signal signal); -#endif - /** * pause_in_s5 getter method. * diff --git a/power/common.c b/power/common.c index 789b872f2a..832e1cc251 100644 --- a/power/common.c +++ b/power/common.c @@ -74,16 +74,12 @@ static int pause_in_s5; static int power_signal_get_level(enum gpio_signal signal) { -#ifdef CONFIG_POWER_S0IX - return chipset_get_ps_debounced_level(signal); -#else #ifdef CONFIG_ESPI_VW_SIGNALS /* Check signal is from GPIOs or VWs */ if ((int)signal > VW_SIGNAL_BASE) return espi_vw_get_wire(signal); #endif return gpio_get_level(signal); -#endif } static int power_signal_enable_interrupt(enum gpio_signal signal) diff --git a/power/skylake.c b/power/skylake.c index 718ff5aeca..a90921e327 100644 --- a/power/skylake.c +++ b/power/skylake.c @@ -26,21 +26,13 @@ #define CPRINTS(format, args...) cprints(CC_CHIPSET, format, ## args) /* Input state flags */ -#define IN_PCH_SLP_S0_DEASSERTED POWER_SIGNAL_MASK(X86_SLP_S0_DEASSERTED) #define IN_PCH_SLP_S3_DEASSERTED POWER_SIGNAL_MASK(X86_SLP_S3_DEASSERTED) #define IN_PCH_SLP_S4_DEASSERTED POWER_SIGNAL_MASK(X86_SLP_S4_DEASSERTED) #define IN_PCH_SLP_SUS_DEASSERTED POWER_SIGNAL_MASK(X86_SLP_SUS_DEASSERTED) -#ifdef CONFIG_POWER_S0IX -#define IN_ALL_PM_SLP_DEASSERTED (IN_PCH_SLP_S0_DEASSERTED | \ - IN_PCH_SLP_S3_DEASSERTED | \ - IN_PCH_SLP_S4_DEASSERTED | \ - IN_PCH_SLP_SUS_DEASSERTED) -#else #define IN_ALL_PM_SLP_DEASSERTED (IN_PCH_SLP_S3_DEASSERTED | \ IN_PCH_SLP_S4_DEASSERTED | \ IN_PCH_SLP_SUS_DEASSERTED) -#endif /* * DPWROK is NC / stuffing option on initial boards. @@ -63,6 +55,19 @@ enum sys_sleep_state { SYS_SLEEP_S3 }; +#ifdef CONFIG_POWER_S0IX +static int slp_s0ix_host_evt = 1; +static int get_slp_s0ix_host_evt(void) +{ + return slp_s0ix_host_evt; +} + +static void set_slp_s0ix_host_evt(int val) +{ + slp_s0ix_host_evt = val; +} +#endif + /* Get system sleep state through GPIOs or VWs */ static int chipset_get_sleep_signal(enum sys_sleep_state state) { @@ -279,7 +284,7 @@ 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 ((get_slp_s0ix_host_evt() == 0) && (chipset_get_sleep_signal(SYS_SLEEP_S3) == 1)) { return POWER_S0S0ix; #endif @@ -295,7 +300,7 @@ 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 ((get_slp_s0ix_host_evt() == 1) && (chipset_get_sleep_signal(SYS_SLEEP_S3) == 1)) { return POWER_S0ixS0; } @@ -341,6 +346,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. + */ + set_slp_s0ix_host_evt(1); +#endif return POWER_S3; case POWER_S3S0: @@ -387,6 +400,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 */ + set_slp_s0ix_host_evt(1); +#endif return POWER_S3; #ifdef CONFIG_POWER_S0IX @@ -460,53 +477,35 @@ enum power_state power_handle_state(enum power_state 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) +/* + * EC enters S0ix via a host command and exits S0ix via the above + * lid open hook. The host event for exit is received but is a no-op for now. + * + * EC will not react directly to SLP_S0 signal interrupts anymore. + */ +static int host_event_sleep_event(struct host_cmd_handler_args *args) { - 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); + const struct ec_params_host_sleep_event *p = args->params; + + if (p->sleep_event == HOST_SLEEP_EVENT_S0IX_SUSPEND) { + CPRINTS("S0ix sus evt"); + set_slp_s0ix_host_evt(0); + task_wake(TASK_ID_CHIPSET); + } else if (p->sleep_event == HOST_SLEEP_EVENT_S0IX_RESUME) { + CPRINTS("S0ix res evt"); + set_slp_s0ix_host_evt(1); + /* + * 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); } - slp_s0_debounce.required = 0; + return EC_RES_SUCCESS; } -DECLARE_DEFERRED(slp_s0_assertion_deferred); +DECLARE_HOST_COMMAND(EC_CMD_HOST_SLEEP_EVENT, host_event_sleep_event, + EC_VER_MASK(0)); -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_data, 3 * MSEC); - } - else if (slp_s0_debounce.required == 0) { - slp_s0_debounce.done = 0; - slp_s0_assertion_deferred(); - } -} #endif -- cgit v1.2.1