summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew McRae <amcrae@google.com>2022-04-14 23:33:04 +1000
committerChromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com>2022-04-28 01:44:46 +0000
commitb245a5459af01e1c66568466c1477dd907efa2eb (patch)
tree8ddf24164e256802b2e23cfce9329f08566a1407
parent496d601b8b7f487a3373beee2e3909304c979d7e (diff)
downloadchrome-ec-b245a5459af01e1c66568466c1477dd907efa2eb.tar.gz
zephyr: ap_pwrseq: Sync CPU state with signals
Synchronize the CPU state by checking the power signals. BUG=b:227970724 TEST=zmake build nivviks; flash & run BRANCH=none Cq-Depend: chromium:3607315 Signed-off-by: Andrew McRae <amcrae@google.com> Change-Id: Ice983c9be114076d5925ef94a2b1f9a6e6742506 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3586792 Reviewed-by: Vijay P Hiremath <vijay.p.hiremath@intel.com> Reviewed-by: Peter Marheine <pmarheine@chromium.org>
-rw-r--r--zephyr/subsys/ap_pwrseq/include/x86_non_dsx_common_pwrseq_sm_handler.h1
-rw-r--r--zephyr/subsys/ap_pwrseq/x86_non_dsx_adlp_pwrseq_sm.c93
-rw-r--r--zephyr/subsys/ap_pwrseq/x86_non_dsx_common_pwrseq_sm_handler.c48
3 files changed, 138 insertions, 4 deletions
diff --git a/zephyr/subsys/ap_pwrseq/include/x86_non_dsx_common_pwrseq_sm_handler.h b/zephyr/subsys/ap_pwrseq/include/x86_non_dsx_common_pwrseq_sm_handler.h
index cd7aa87b1d..4d127a5672 100644
--- a/zephyr/subsys/ap_pwrseq/include/x86_non_dsx_common_pwrseq_sm_handler.h
+++ b/zephyr/subsys/ap_pwrseq/include/x86_non_dsx_common_pwrseq_sm_handler.h
@@ -22,6 +22,7 @@
enum power_states_ndsx chipset_pwr_sm_run(enum power_states_ndsx curr_state);
void init_chipset_pwr_seq_state(void);
+enum power_states_ndsx chipset_pwr_seq_get_state(void);
void request_exit_hardoff(bool should_exit);
enum power_states_ndsx pwr_sm_get_state(void);
void apshutdown(void);
diff --git a/zephyr/subsys/ap_pwrseq/x86_non_dsx_adlp_pwrseq_sm.c b/zephyr/subsys/ap_pwrseq/x86_non_dsx_adlp_pwrseq_sm.c
index 5567915737..3280aaec35 100644
--- a/zephyr/subsys/ap_pwrseq/x86_non_dsx_adlp_pwrseq_sm.c
+++ b/zephyr/subsys/ap_pwrseq/x86_non_dsx_adlp_pwrseq_sm.c
@@ -162,6 +162,99 @@ void init_chipset_pwr_seq_state(void)
power_signal_set(PWR_SYS_RST, 0);
}
+/**
+ * Determine the current state of the CPU from the
+ * power signals.
+ */
+enum power_states_ndsx chipset_pwr_seq_get_state(void)
+{
+#define MASK_ALL_POWER_GOOD \
+ (POWER_SIGNAL_MASK(PWR_RSMRST) | \
+ POWER_SIGNAL_MASK(PWR_ALL_SYS_PWRGD) | \
+ POWER_SIGNAL_MASK(PWR_DSW_PWROK) | \
+ POWER_SIGNAL_MASK(PWR_PG_PP1P05))
+#define MASK_S0 \
+ (MASK_ALL_POWER_GOOD | \
+ POWER_SIGNAL_MASK(PWR_SLP_S0) | \
+ POWER_SIGNAL_MASK(PWR_SLP_S3) | \
+ POWER_SIGNAL_MASK(PWR_SLP_SUS) | \
+ POWER_SIGNAL_MASK(PWR_SLP_S4) | \
+ POWER_SIGNAL_MASK(PWR_SLP_S5))
+#define MASK_S5 \
+ (MASK_ALL_POWER_GOOD | \
+ POWER_SIGNAL_MASK(PWR_SLP_S5))
+
+ /*
+ * Chip is shut down.
+ */
+ if ((power_get_signals() & MASK_ALL_POWER_GOOD) == 0) {
+ LOG_DBG("Power rails off, G3 state");
+ return SYS_POWER_STATE_G3;
+ }
+ /*
+ * If not all the power rails are available,
+ * then force shutdown to G3 to get to known state.
+ */
+ if ((power_get_signals() & MASK_ALL_POWER_GOOD)
+ != MASK_ALL_POWER_GOOD) {
+ ap_power_force_shutdown(AP_POWER_SHUTDOWN_G3);
+ LOG_INF("Not all power rails up, forcing shutdown");
+ return SYS_POWER_STATE_G3;
+ }
+
+ /*
+ * All the power rails are good, so
+ * wait for virtual wire signals to become available.
+ * Not sure how long to wait? 5 seconds total.
+ */
+ for (int delay = 0; delay < 500; k_msleep(10), delay++) {
+#if defined(CONFIG_PLATFORM_EC_ESPI_VW_SLP_S3)
+ if (power_signal_get(PWR_SLP_S3) < 0)
+ continue;
+#endif
+#if defined(CONFIG_PLATFORM_EC_ESPI_VW_SLP_S4)
+ if (power_signal_get(PWR_SLP_S4) < 0)
+ continue;
+#endif
+#if defined(CONFIG_PLATFORM_EC_ESPI_VW_SLP_S5)
+ if (power_signal_get(PWR_SLP_S5) < 0)
+ continue;
+#endif
+ /*
+ * All signals valid.
+ */
+ LOG_DBG("All VW signals valid after %d ms", delay * 10);
+ break;
+ }
+ /*
+ * S0, all power OK, no suspend or sleep on.
+ */
+ if ((power_get_signals() & MASK_S0) == MASK_ALL_POWER_GOOD) {
+ LOG_DBG("CPU in S0 state");
+ return SYS_POWER_STATE_S0;
+ }
+ /*
+ * S3, all power OK, PWR_SLP_S3 on.
+ */
+ if ((power_get_signals() & MASK_S0) ==
+ (MASK_ALL_POWER_GOOD | POWER_SIGNAL_MASK(PWR_SLP_S3))) {
+ LOG_DBG("CPU in S3 state");
+ return SYS_POWER_STATE_S3;
+ }
+ /*
+ * S5, all power OK, PWR_SLP_S5 on.
+ */
+ if ((power_get_signals() & MASK_S5) == MASK_S5) {
+ LOG_DBG("CPU in S5 state");
+ return SYS_POWER_STATE_S5;
+ }
+ /*
+ * Unable to determine state, force to G3.
+ */
+ ap_power_force_shutdown(AP_POWER_SHUTDOWN_G3);
+ LOG_INF("Unable to determine CPU state, forcing shutdown");
+ return SYS_POWER_STATE_G3;
+}
enum power_states_ndsx chipset_pwr_sm_run(enum power_states_ndsx curr_state)
{
diff --git a/zephyr/subsys/ap_pwrseq/x86_non_dsx_common_pwrseq_sm_handler.c b/zephyr/subsys/ap_pwrseq/x86_non_dsx_common_pwrseq_sm_handler.c
index fc1e900edd..f6d93fe655 100644
--- a/zephyr/subsys/ap_pwrseq/x86_non_dsx_common_pwrseq_sm_handler.c
+++ b/zephyr/subsys/ap_pwrseq/x86_non_dsx_common_pwrseq_sm_handler.c
@@ -421,13 +421,56 @@ static int common_pwr_sm_run(int state)
return state;
}
+/*
+ * Determine the current CPU state and ensure it
+ * is matching what is required.
+ */
+static void pwr_seq_set_initial_state(void)
+{
+ uint32_t reset_flags = system_get_reset_flags();
+ /* Determine current state using chipset specific handler */
+ enum power_states_ndsx state = chipset_pwr_seq_get_state();
+
+ /*
+ * Check reset flags, and ensure CPU is in correct state.
+ */
+ if (reset_flags & EC_RESET_FLAG_AP_OFF) {
+ /*
+ * AP is expected to be off.
+ * If it isn't, force shutdown.
+ */
+ if (state != SYS_POWER_STATE_G3) {
+ ap_power_force_shutdown(AP_POWER_SHUTDOWN_G3);
+ }
+ pwr_sm_set_state(SYS_POWER_STATE_G3);
+ return;
+ }
+ /*
+ * Not in warm boot, but CPU is not shutdown.
+ */
+ if (((reset_flags & EC_RESET_FLAG_SYSJUMP) == 0) &&
+ (state != SYS_POWER_STATE_G3)) {
+ ap_power_force_shutdown(AP_POWER_SHUTDOWN_G3);
+ state = SYS_POWER_STATE_G3;
+ }
+ /*
+ * If CPU is off, set the state to start powering it up.
+ */
+ if (state == SYS_POWER_STATE_G3) {
+ state = SYS_POWER_STATE_G3S5;
+ }
+ pwr_sm_set_state(state);
+}
+
static void pwrseq_loop_thread(void *p1, void *p2, void *p3)
{
int32_t t_wait_ms = 10;
enum power_states_ndsx curr_state, new_state;
power_signal_mask_t this_in_signals;
power_signal_mask_t last_in_signals = 0;
- enum power_states_ndsx last_state = pwr_sm_get_state();
+ enum power_states_ndsx last_state = -1;
+
+ pwr_seq_set_initial_state();
while (1) {
curr_state = pwr_sm_get_state();
@@ -495,8 +538,6 @@ static void init_pwr_seq_state(void)
{
init_chipset_pwr_seq_state();
request_exit_hardoff(false);
-
- pwr_sm_set_state(SYS_POWER_STATE_G3S5);
}
/* Initialize power sequence system state */
@@ -506,7 +547,6 @@ static int pwrseq_init(const struct device *dev)
/* Initialize signal handlers */
power_signal_init();
- /* TODO: Define initial state of power sequence */
LOG_DBG("Init pwr seq state");
init_pwr_seq_state();
/* Create power sequence state handler core function thread */