diff options
7 files changed, 165 insertions, 4 deletions
diff --git a/zephyr/subsys/ap_pwrseq/CMakeLists.txt b/zephyr/subsys/ap_pwrseq/CMakeLists.txt index c1761e6824..f08bb3e476 100644 --- a/zephyr/subsys/ap_pwrseq/CMakeLists.txt +++ b/zephyr/subsys/ap_pwrseq/CMakeLists.txt @@ -3,4 +3,6 @@ zephyr_include_directories(include) zephyr_sources_ifdef(CONFIG_X86_NON_DSX_PWRSEQ x86_non_dsx_common_pwrseq_sm_handler.c) +zephyr_sources_ifdef(CONFIG_X86_NON_DSX_PWRSEQ_CONSOLE + x86_non_dsx_common_pwrseq_console.c) zephyr_sources_ifdef(CONFIG_X86_NON_DSX_PWRSEQ_ADL x86_non_dsx_adlp_pwrseq_sm.c) diff --git a/zephyr/subsys/ap_pwrseq/Kconfig b/zephyr/subsys/ap_pwrseq/Kconfig index 6d2b7ddfb2..4367f0b11a 100644 --- a/zephyr/subsys/ap_pwrseq/Kconfig +++ b/zephyr/subsys/ap_pwrseq/Kconfig @@ -27,6 +27,15 @@ config X86_NON_DSX_PWRSEQ_ADL This enables AP power sequecing support for Intel Alderlake family of chipset. +config X86_NON_DSX_PWRSEQ_CONSOLE + bool "Console commands for x86 Non Deep Sx power sequencing" + depends on X86_NON_DSX_PWRSEQ + default n + help + This option enables Non Deep Sleep Well power sequencing shell + console commands to debug. + + config X86_NON_DSW_PWRSEQ_STACK_SIZE int "AP pwrseq stack size (in bytes)" default 1024 diff --git a/zephyr/subsys/ap_pwrseq/include/x86_common_pwrseq.h b/zephyr/subsys/ap_pwrseq/include/x86_common_pwrseq.h index b468508c37..d46a2183fa 100644 --- a/zephyr/subsys/ap_pwrseq/include/x86_common_pwrseq.h +++ b/zephyr/subsys/ap_pwrseq/include/x86_common_pwrseq.h @@ -55,6 +55,23 @@ enum power_states_ndsx { SYS_POWER_STATE_S0S3, }; +/* + * AP hard shutdowns are logged on the same path as resets. + */ +enum pwrseq_chipset_shutdown_reason { + PWRSEQ_CHIPSET_SHUTDOWN_POWERFAIL, + /* Forcing a shutdown as part of EC initialization */ + PWRSEQ_CHIPSET_SHUTDOWN_INIT, + /* Forcing shutdown with command */ + PWRSEQ_CHIPSET_SHUTDOWN_CONSOLE_CMD, + /* Forcing a shutdown to effect entry to G3. */ + PWRSEQ_CHIPSET_SHUTDOWN_G3, + /* Force a chipset shutdown from the power button through EC */ + PWRSEQ_CHIPSET_SHUTDOWN_BUTTON, + + PWRSEQ_CHIPSET_SHUTDOWN_COUNT, +}; + /* This encapsulates the attributes of the state machine */ struct pwrseq_context { /* On power-on start boot up sequence */ 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 4212443366..fe1aae194f 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 @@ -42,8 +42,15 @@ struct common_pwrseq_config { enum power_states_ndsx chipset_pwr_sm_run( enum power_states_ndsx curr_state, const struct common_pwrseq_config *com_cfg); -void init_chipset_pwr_seq_state(void); void all_sig_pass_thru_handler(void); +void chipset_force_shutdown(enum pwrseq_chipset_shutdown_reason reason, + const struct common_pwrseq_config *com_cfg); +void chipset_reset(enum pwrseq_chipset_shutdown_reason reason); void common_rsmrst_pass_thru_handler(void); +void init_chipset_pwr_seq_state(void); +enum power_states_ndsx pwr_sm_get_state(void); +void apshutdown(void); + +extern const char pwrsm_dbg[][25]; #endif /* __X86_NON_DSX_COMMON_H__ */ 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 fed8240788..c579a86f32 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 @@ -165,6 +165,17 @@ void s0_action_handler(const struct common_pwrseq_config *com_cfg) generate_sys_pwrok_handler(com_cfg); } +/* This should be overridden if there is no power sequencer chip */ +__attribute__((weak)) int intel_x86_get_pg_ec_dsw_pwrok( + const struct common_pwrseq_config *com_cfg) +{ +#if PWRSEQ_GPIO_PRESENT(pg_ec_dsw_pwroks_gpios) + return gpio_pin_get_dt(&com_cfg->pg_ec_dsw_pwrok); +#else + return 0; +#endif +} + void intel_x86_sys_reset_delay(void) { /* @@ -174,6 +185,65 @@ void intel_x86_sys_reset_delay(void) k_msleep(chip_cfg.sys_reset_delay_ms); } +void chipset_reset(enum pwrseq_chipset_shutdown_reason reason) +{ + /* + * Irrespective of cold_reset value, always toggle SYS_RESET_L to + * perform a chipset reset. RCIN# which was used earlier to trigger + * a warm reset is known to not work in certain cases where the CPU + * is in a bad state (crbug.com/721853). + * + * The EC cannot control warm vs cold reset of the chipset using + * SYS_RESET_L; it's more of a request. + */ + LOG_DBG("%s: %d", __func__, reason); + + /* + * Toggling SYS_RESET_L will not have any impact when it's already + * low (i,e. Chipset is in reset state). + */ + if (gpio_pin_get_dt(&(chip_cfg.sys_rst_l)) == 0) { + LOG_DBG("Chipset is in reset state"); + return; + } + + gpio_pin_set_dt(&(chip_cfg.sys_rst_l), 0); + intel_x86_sys_reset_delay(); + gpio_pin_set_dt(&(chip_cfg.sys_rst_l), 1); +} + +void chipset_force_shutdown(enum pwrseq_chipset_shutdown_reason reason, + const struct common_pwrseq_config *com_cfg) +{ + int timeout_ms = 50; + + /* TODO: below + * report_ap_reset(reason); + */ + + /* Turn off RMSRST_L to meet tPCH12 */ + gpio_pin_set_dt(&com_cfg->ec_pch_rsmrst_odl, 0); + + /* Turn off S5 rails */ + gpio_pin_set_dt(&com_cfg->enable_pp5000_a, 0); + + /* + * TODO(b/179519791): Replace this wait with + * power_wait_signals_timeout() + */ + /* Now wait for DSW_PWROK and RSMRST_ODL to go away. */ + while (intel_x86_get_pg_ec_dsw_pwrok(com_cfg) && + gpio_pin_get_dt(&com_cfg->pg_ec_rsmrst_odl) && + (timeout_ms > 0)) { + k_msleep(1); + timeout_ms--; + }; + + if (!timeout_ms) + LOG_DBG("DSW_PWROK or RSMRST_ODL didn't go low! Assuming G3."); +} + + void g3s5_action_handler(const struct common_pwrseq_config *com_cfg) { gpio_pin_set_dt(&com_cfg->enable_pp5000_a, 1); diff --git a/zephyr/subsys/ap_pwrseq/x86_non_dsx_common_pwrseq_console.c b/zephyr/subsys/ap_pwrseq/x86_non_dsx_common_pwrseq_console.c new file mode 100644 index 0000000000..7d9ac38541 --- /dev/null +++ b/zephyr/subsys/ap_pwrseq/x86_non_dsx_common_pwrseq_console.c @@ -0,0 +1,43 @@ +/* Copyright 2022 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include <shell/shell.h> +#include <x86_non_dsx_common_pwrseq_sm_handler.h> + +LOG_MODULE_DECLARE(ap_pwrseq, 4); + +/* Console commands */ +static int powerinfo_handler(const struct shell *shell, size_t argc, + char **argv) +{ + int state; + + state = pwr_sm_get_state(); + shell_fprintf(shell, SHELL_INFO, "Power state = %d (%s)\n", + state, pwrsm_dbg[state]); + return 0; +} + +SHELL_CMD_REGISTER(powerinfo, NULL, NULL, powerinfo_handler); + +static int apshutdown_handler(const struct shell *shell, size_t argc, + char **argv) +{ + apshutdown(); + return 0; +} + +SHELL_CMD_REGISTER(apshutdown, NULL, NULL, apshutdown_handler); + +static int apreset_handler(const struct shell *shell, size_t argc, + char **argv) +{ + chipset_reset(PWRSEQ_CHIPSET_SHUTDOWN_CONSOLE_CMD); + return 0; +} + +SHELL_CMD_REGISTER(apreset, NULL, NULL, apreset_handler); + +/* End of console commands */ 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 cdb4e63cdd..8c23b4de8a 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 @@ -132,6 +132,15 @@ void pwr_sm_set_state(enum power_states_ndsx new_state) pwrseq_ctx.power_state = new_state; } +void apshutdown(void) +{ + if (pwr_sm_get_state() != SYS_POWER_STATE_G3) { + chipset_force_shutdown(PWRSEQ_CHIPSET_SHUTDOWN_CONSOLE_CMD, + &com_cfg); + pwr_sm_set_state(SYS_POWER_STATE_G3); + } +} + /* Check RSMRST is fine to move from S5 to higher state */ int check_rsmrst_ok(void) { @@ -184,7 +193,11 @@ static int common_pwr_sm_run(int state) rsmrst_pass_thru_handler(); return SYS_POWER_STATE_S5S4; } - break; + return SYS_POWER_STATE_S5G3; + + case SYS_POWER_STATE_S5G3: + chipset_force_shutdown(PWRSEQ_CHIPSET_SHUTDOWN_G3, &com_cfg); + return SYS_POWER_STATE_G3; case SYS_POWER_STATE_S5S4: /* Check if the PCH has come out of suspend state */ @@ -192,7 +205,8 @@ static int common_pwr_sm_run(int state) LOG_DBG("RSMRST is ok"); return SYS_POWER_STATE_S4; } - break; + LOG_DBG("RSMRST is not ok"); + return SYS_POWER_STATE_S5; case SYS_POWER_STATE_S4: return SYS_POWER_STATE_S3; @@ -216,7 +230,6 @@ static int common_pwr_sm_run(int state) case SYS_POWER_STATE_S4S5: case SYS_POWER_STATE_S3S4: case SYS_POWER_STATE_S0S3: - case SYS_POWER_STATE_S5G3: break; default: |