summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArchana Patni <archana.patni@intel.com>2016-11-08 12:45:40 +0530
committerchrome-bot <chrome-bot@chromium.org>2016-11-17 16:09:44 -0800
commitb8406119c2c51acc46c551ef0930c51153657613 (patch)
tree7db348bfbc3affa88c6d452f70e7f349674ac642
parent82aaccad4022737ba4c21cbeb119d73e51dff5f1 (diff)
downloadchrome-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>
-rw-r--r--board/reef/board.c1
-rw-r--r--board/reef/board.h3
-rw-r--r--board/reef/gpio.inc2
-rw-r--r--include/power.h12
-rw-r--r--power/apollolake.c79
-rw-r--r--power/common.c25
6 files changed, 57 insertions, 65 deletions
diff --git a/board/reef/board.c b/board/reef/board.c
index 655a319506..ffa7e65d8d 100644
--- a/board/reef/board.c
+++ b/board/reef/board.c
@@ -114,7 +114,6 @@ void tablet_mode_interrupt(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_L"},
- {GPIO_PCH_SLP_S0_L, 1, "PMU_SLP_S0_N"},
{GPIO_PCH_SLP_S3_L, 1, "SLP_S3_DEASSERTED"},
{GPIO_PCH_SLP_S4_L, 1, "SLP_S4_DEASSERTED"},
{GPIO_SUSPWRNACK, 1, "SUSPWRNACK_DEASSERTED"},
diff --git a/board/reef/board.h b/board/reef/board.h
index d2c6166ee9..9464976fd9 100644
--- a/board/reef/board.h
+++ b/board/reef/board.h
@@ -113,6 +113,8 @@
#define CONFIG_POWER_BUTTON
#define CONFIG_POWER_BUTTON_X86
#define CONFIG_POWER_COMMON
+#define CONFIG_POWER_S0IX
+#define CONFIG_POWER_TRACK_HOST_SLEEP_STATE
/* EC */
#define CONFIG_ADC
@@ -219,7 +221,6 @@ enum pwm_channel {
enum power_signal {
X86_RSMRST_N = 0,
- X86_SLP_S0_N,
X86_SLP_S3_N,
X86_SLP_S4_N,
X86_SUSPWRDNACK,
diff --git a/board/reef/gpio.inc b/board/reef/gpio.inc
index 8a883251fc..3517fe9b23 100644
--- a/board/reef/gpio.inc
+++ b/board/reef/gpio.inc
@@ -21,7 +21,6 @@ GPIO_INT(USB_C0_CABLE_DET, PIN(C, 5), GPIO_INT_RISING, anx74xx_cable_det_interru
GPIO_INT(PCH_SLP_S4_L, PIN(8, 6), GPIO_INT_BOTH, power_signal_interrupt) /* SLP_S4_L */
GPIO_INT(PCH_SLP_S3_L, PIN(7, 3), GPIO_INT_BOTH, power_signal_interrupt) /* SLP_S3_L */
-GPIO_INT(PCH_SLP_S0_L, PIN(7, 5), GPIO_INT_BOTH, power_signal_interrupt) /* SLP_S0_L */
GPIO_INT(SUSPWRNACK, PIN(7, 2), GPIO_INT_BOTH, power_signal_interrupt)
GPIO_INT(RSMRST_L_PGOOD, PIN(6, 0), GPIO_INT_BOTH, power_signal_interrupt) /* PMIC_EC_RSMRST_ODL */
GPIO_INT(ALL_SYS_PGOOD, PIN(5, 0), GPIO_INT_BOTH, power_signal_interrupt) /* PMIC_EC_PWROK_OD */
@@ -66,6 +65,7 @@ GPIO(EC_I2C_POWER_SCL, PIN(D, 1), GPIO_INPUT)
GPIO(PCH_SMI_L, PIN(A, 6), GPIO_ODR_HIGH | GPIO_SEL_1P8V) /* EC_SMI_ODL */
GPIO(PCH_SCI_L, PIN(A, 7), GPIO_ODR_HIGH | GPIO_SEL_1P8V) /* EC_SCI_ODL */
+GPIO(PCH_SLP_S0_L, PIN(7, 5), GPIO_INPUT) /* SLP_S0_L */
/*
* BRD_ID1 is a an ADC pin which will be used to measure multiple values.
diff --git a/include/power.h b/include/power.h
index 6a133749bf..9c9e912c6d 100644
--- a/include/power.h
+++ b/include/power.h
@@ -142,5 +142,15 @@ void power_set_pause_in_s5(int pause);
* @return Believed sleep state of host.
*/
enum host_sleep_event power_get_host_sleep_state(void);
-#endif
+
+#ifdef CONFIG_POWER_S0IX
+/**
+ * Reset the sleep state reported by the host.
+ *
+ * @param sleep_event Reset sleep state.
+ */
+void power_reset_host_sleep_state(enum host_sleep_event sleep_event);
+#endif /* CONFIG_POWER_S0IX */
+#endif /* CONFIG_POWER_TRACK_HOST_SLEEP_STATE */
+
#endif /* __CROS_EC_POWER_H */
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 */