diff options
author | Andrew McRae <amcrae@google.com> | 2022-04-14 23:33:04 +1000 |
---|---|---|
committer | Chromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com> | 2022-04-28 01:44:46 +0000 |
commit | b245a5459af01e1c66568466c1477dd907efa2eb (patch) | |
tree | 8ddf24164e256802b2e23cfce9329f08566a1407 | |
parent | 496d601b8b7f487a3373beee2e3909304c979d7e (diff) | |
download | chrome-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>
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 */ |