summaryrefslogtreecommitdiff
path: root/power
diff options
context:
space:
mode:
authorWai-Hong Tam <waihong@google.com>2020-07-23 15:58:48 -0700
committerCommit Bot <commit-bot@chromium.org>2020-08-08 01:47:11 +0000
commit67944274aa8b0639e3e23eacd8cf277908874d5f (patch)
tree6bf9a3cf6b9a7a65ddff44e3f8d1f76446cc90ee /power
parenta627487b4f934f3f10973f25398d75e051daeb2a (diff)
downloadchrome-ec-67944274aa8b0639e3e23eacd8cf277908874d5f.tar.gz
sc7180: Support the sleep failure detection to SC7180 power sequence
This only adds the sleep failure detection support to SC7180 power sequence but not enable it yet. The board has to explicitly define the following CONFIG to enable this feature: * CONFIG_CHIPSET_RESUME_INIT_HOOK * CONFIG_POWER_SLEEP_FAILURE_DETECTION Without defining the CONFIGs, the only change is to disable/enable the AP_SUSPEND signal interrupt; the suspend/resume hooks are unchanged, i.e. not wait for the host sleep event. With defining the CONFIGs, the suspend failure detection is enabled. When AP_SUSPEND is deasserted, only the RESUME_INIT hook is triggered to initialize the SPI interface, such that EC can receive the host sleep event. The RESUME hook is delayed to be triggered until AP sends the resume event. If AP_SUSPEND becomes asserted before receiving the host event, will back to S3 and the SUSPEND_COMPLETE hook is triggered to disable the SPI interface. If no host event is received and no AP_SUSPEND assertion, a timeout happens and wake the AP with a HANG_DETECT event. BRANCH=None BUG=b:148149387 TEST=Tried the following scenaiors (the CONFIGs not defined): (1) On AP_SUSPEND assertion, SUSPEND hook triggered, go to S3; (2) On AP_SUSPEND deassertion, RESUME hook triggered, go to S0. Checked the follower CL for the configs defined. Change-Id: I28301921a4c85aab092cdc8af9d6ff4b1da7ec61 Signed-off-by: Wai-Hong Tam <waihong@google.com> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2321876 Reviewed-by: Ting Shen <phoenixshen@chromium.org> Reviewed-by: Stephen Boyd <swboyd@chromium.org>
Diffstat (limited to 'power')
-rw-r--r--power/sc7180.c103
1 files changed, 98 insertions, 5 deletions
diff --git a/power/sc7180.c b/power/sc7180.c
index d31728bfc7..fe093ad535 100644
--- a/power/sc7180.c
+++ b/power/sc7180.c
@@ -785,6 +785,61 @@ static inline int chipset_get_sleep_signal(void)
return fake_suspend;
}
+static void suspend_hang_detected(void)
+{
+ CPRINTS("Warning: Detected sleep hang! Waking host up!");
+ host_set_single_event(EC_HOST_EVENT_HANG_DETECT);
+}
+
+static void power_reset_host_sleep_state(void)
+{
+ power_set_host_sleep_state(HOST_SLEEP_EVENT_DEFAULT_RESET);
+ sleep_reset_tracking();
+ power_chipset_handle_host_sleep_event(HOST_SLEEP_EVENT_DEFAULT_RESET,
+ NULL);
+}
+
+static void handle_chipset_reset(void)
+{
+ if (chipset_in_state(CHIPSET_STATE_STANDBY)) {
+ CPRINTS("Chipset reset: exit s3");
+ power_reset_host_sleep_state();
+ task_wake(TASK_ID_CHIPSET);
+ }
+}
+DECLARE_HOOK(HOOK_CHIPSET_RESET, handle_chipset_reset, HOOK_PRIO_FIRST);
+
+__override void power_chipset_handle_host_sleep_event(
+ enum host_sleep_event state,
+ struct host_sleep_event_context *ctx)
+{
+ CPRINTS("Handle sleep: %d", state);
+
+ if (state == HOST_SLEEP_EVENT_S3_SUSPEND) {
+ /*
+ * Indicate to power state machine that a new host event for
+ * S3 suspend has been received and so chipset suspend
+ * notification needs to be sent to listeners.
+ */
+ sleep_set_notify(SLEEP_NOTIFY_SUSPEND);
+ sleep_start_suspend(ctx, suspend_hang_detected);
+ power_signal_enable_interrupt(GPIO_AP_SUSPEND);
+
+ } else if (state == HOST_SLEEP_EVENT_S3_RESUME) {
+ /*
+ * Wake up chipset task and indicate to power state machine that
+ * listeners need to be notified of chipset resume.
+ */
+ sleep_set_notify(SLEEP_NOTIFY_RESUME);
+ task_wake(TASK_ID_CHIPSET);
+ power_signal_disable_interrupt(GPIO_AP_SUSPEND);
+ sleep_complete_resume(ctx);
+
+ } else if (state == HOST_SLEEP_EVENT_DEFAULT_RESET) {
+ power_signal_disable_interrupt(GPIO_AP_SUSPEND);
+ }
+}
+
/**
* Power handler for steady states
*
@@ -844,6 +899,12 @@ enum power_state power_handle_state(enum power_state state)
/* Call hooks now that AP is running */
hook_notify(HOOK_CHIPSET_STARTUP);
+
+ /*
+ * Clearing the sleep failure detection tracking on the path
+ * to S0 to handle any reset conditions.
+ */
+ power_reset_host_sleep_state();
return POWER_S3;
case POWER_S3:
@@ -863,24 +924,41 @@ enum power_state power_handle_state(enum power_state state)
* AP has woken up and it deasserts the suspend signal;
* go to S0.
*
- * TODO(b/148149387): Add the hang detection that waits for a
- * host event before transits the state. It prevents changing
- * the state for modem paging.
+ * In S0, it will wait for a host event and then trigger the
+ * RESUME hook.
*/
if (!chipset_get_sleep_signal())
return POWER_S3S0;
break;
case POWER_S3S0:
+#ifdef CONFIG_CHIPSET_RESUME_INIT_HOOK
+ /*
+ * Notify the RESUME_INIT hooks, i.e. enabling SPI driver
+ * to receive host commands/events. The normal RESUME hook
+ * will be notified later, after receive a host resume event.
+ */
+ hook_notify(HOOK_CHIPSET_RESUME_INIT);
+#else
hook_notify(HOOK_CHIPSET_RESUME);
+#endif
+ sleep_resume_transition();
disable_sleep(SLEEP_MASK_AP_RUN);
return POWER_S0;
case POWER_S0:
shutdown_from_s0 = check_for_power_off_event();
- if (shutdown_from_s0 || chipset_get_sleep_signal())
+ if (shutdown_from_s0) {
return POWER_S0S3;
+ } else if (power_get_host_sleep_state()
+ == HOST_SLEEP_EVENT_S3_SUSPEND &&
+ chipset_get_sleep_signal()) {
+ return POWER_S0S3;
+ }
+ /* When receive the host event, trigger the RESUME hook. */
+ sleep_notify_transition(SLEEP_NOTIFY_RESUME,
+ HOOK_CHIPSET_RESUME);
break;
case POWER_S0S3:
@@ -891,8 +969,23 @@ enum power_state power_handle_state(enum power_state state)
if (power_button_was_pressed)
timer_cancel(TASK_ID_CHIPSET);
- /* Call hooks here since we don't know it prior to AP suspend */
+#ifdef CONFIG_CHIPSET_RESUME_INIT_HOOK
+ /*
+ * Pair with the HOOK_CHIPSET_RESUME_INIT, i.e. disabling SPI
+ * driver, by notifying the SUSPEND_COMPLETE hook. The normal
+ * SUSPEND hook will be notified afterward.
+ */
+ hook_notify(HOOK_CHIPSET_SUSPEND_COMPLETE);
+#else
hook_notify(HOOK_CHIPSET_SUSPEND);
+#endif
+ /*
+ * Call SUSPEND hooks only if we haven't notified listeners of
+ * S3 suspend.
+ */
+ sleep_notify_transition(SLEEP_NOTIFY_SUSPEND,
+ HOOK_CHIPSET_SUSPEND);
+ sleep_suspend_transition();
enable_sleep(SLEEP_MASK_AP_RUN);
return POWER_S3;