From da4cd3da3d100c62c844c759103133130bf064d0 Mon Sep 17 00:00:00 2001 From: Bernardo Perez Priego Date: Tue, 1 Nov 2022 18:56:04 -0700 Subject: ap_pwrseq: Adapt power interface components to AP Power Sequence driver This CL make other components to follow AP Power Sequence driver. BUG=b:217952699 BRANCH=none TEST=zmake build Change-Id: I9d528fadd3074bfa9a2e9d1f36cfdeaf45015579 Signed-off-by: Bernardo Perez Priego Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3996453 Reviewed-by: Peter Marheine Commit-Queue: Peter Marheine Tested-by: Peter Marheine --- zephyr/app/ec/ec_app_main.c | 2 +- zephyr/include/ap_power/ap_power_events.h | 2 + zephyr/include/ap_power/ap_power_interface.h | 8 +- zephyr/include/ap_power/ap_pwrseq.h | 14 +- zephyr/shim/src/power_host_sleep_api.c | 31 +++++ zephyr/subsys/ap_pwrseq/ap_power_interface.c | 64 +++++++++ zephyr/subsys/ap_pwrseq/ap_pwrseq.c | 2 +- .../subsys/ap_pwrseq/include/ap_power_host_sleep.h | 8 ++ .../subsys/ap_pwrseq/include/x86_common_pwrseq.h | 2 + .../include/x86_non_dsx_common_pwrseq_sm_handler.h | 12 +- zephyr/subsys/ap_pwrseq/power_host_sleep.c | 28 ++++ zephyr/subsys/ap_pwrseq/power_signals.c | 13 ++ .../ap_pwrseq/x86_non_dsx_chipset_power_state.c | 84 ++++++++++++ .../ap_pwrseq/x86_non_dsx_common_pwrseq_console.c | 5 + .../x86_non_dsx_common_pwrseq_host_sleep.c | 12 ++ .../x86_non_dsx_common_pwrseq_sm_handler.c | 147 ++++++++++++++++----- 16 files changed, 394 insertions(+), 40 deletions(-) diff --git a/zephyr/app/ec/ec_app_main.c b/zephyr/app/ec/ec_app_main.c index 120003b7bc..6b8e113728 100644 --- a/zephyr/app/ec/ec_app_main.c +++ b/zephyr/app/ec/ec_app_main.c @@ -3,7 +3,7 @@ * found in the LICENSE file. */ -#include "ap_power/ap_pwrseq.h" +#include "ap_power/ap_power_interface.h" #include "button.h" #include "chipset.h" #include "cros_board_info.h" diff --git a/zephyr/include/ap_power/ap_power_events.h b/zephyr/include/ap_power/ap_power_events.h index 8a6a9764de..f729c68e9e 100644 --- a/zephyr/include/ap_power/ap_power_events.h +++ b/zephyr/include/ap_power/ap_power_events.h @@ -11,6 +11,8 @@ #ifndef __AP_POWER_AP_EVENTS_H__ #define __AP_POWER_AP_EVENTS_H__ +#include + /** * @brief Dispatch callbacks for an event. * diff --git a/zephyr/include/ap_power/ap_power_interface.h b/zephyr/include/ap_power/ap_power_interface.h index d2808f6075..9a36091deb 100644 --- a/zephyr/include/ap_power/ap_power_interface.h +++ b/zephyr/include/ap_power/ap_power_interface.h @@ -9,7 +9,6 @@ * * Defines the interface to the AP power sequence module, * which includes: - * - enums for the power state of the AP * - enums for the power state mask of the AP * - enums indicating the reason for shutdown * - enums for providing control values @@ -28,6 +27,7 @@ #include +#ifndef CONFIG_AP_PWRSEQ_DRIVER /** * @brief System power states for Non Deep Sleep Well * EC is an always on device in a Non Deep Sx system except when EC @@ -84,6 +84,7 @@ enum power_states_ndsx { SYS_POWER_STATE_S0S0ix, #endif }; +#endif /* CONFIG_AP_PWRSEQ_DRIVER */ /** * @brief Represents the state of the AP as a mask. @@ -218,4 +219,9 @@ void ap_power_force_shutdown(enum ap_power_shutdown_reason reason); */ void ap_power_init_reset_log(void); +/** + * @brief Starts the AP power sequence thread. + */ +void ap_pwrseq_task_start(void); + #endif /* __AP_POWER_AP_POWER_INTERFACE_H__ */ diff --git a/zephyr/include/ap_power/ap_pwrseq.h b/zephyr/include/ap_power/ap_pwrseq.h index f7324b0f6c..813b4f231b 100644 --- a/zephyr/include/ap_power/ap_pwrseq.h +++ b/zephyr/include/ap_power/ap_pwrseq.h @@ -8,10 +8,9 @@ #include #include -/** Starts the AP power sequence thread */ -void ap_pwrseq_task_start(void); - +#ifndef CONFIG_AP_PWRSEQ_DRIVER void ap_pwrseq_wake(void); +#else #ifdef __cplusplus extern "C" { @@ -31,7 +30,13 @@ extern "C" { AP_POWER_SUB_STATE_ENUM_DEF_WITH_COMMA)), \ ()))) -/** @brief AP power sequence valid power states. */ +/** + * @brief AP power sequence valid power states. + * + * Note: States enum list MUST remain arranged from the lowest to the highest + * power state. + * + **/ /* clang-format off */ enum ap_pwrseq_state { AP_POWER_STATE_UNINIT, /* EC and AP are Uninitialized */ @@ -203,4 +208,5 @@ int ap_pwrseq_register_state_exit_callback( #ifdef __cplusplus } #endif +#endif /* CONFIG_AP_PWRSEQ_DRIVER */ #endif /* _AP_PWRSEQ_H_ */ diff --git a/zephyr/shim/src/power_host_sleep_api.c b/zephyr/shim/src/power_host_sleep_api.c index 99d535bdff..95d9496782 100644 --- a/zephyr/shim/src/power_host_sleep_api.c +++ b/zephyr/shim/src/power_host_sleep_api.c @@ -7,6 +7,7 @@ #include #include +#ifndef CONFIG_AP_PWRSEQ_DRIVER static enum power_state translate_ap_power_state(enum power_states_ndsx ap_power_state) { @@ -34,6 +35,36 @@ int ap_power_get_lazy_wake_mask(enum power_states_ndsx state, return -EINVAL; return get_lazy_wake_mask(st, mask); } +#else +#include "ap_power/ap_pwrseq.h" + +static enum power_state +translate_ap_power_state(enum ap_pwrseq_state ap_power_state) +{ + switch (ap_power_state) { + case AP_POWER_STATE_S5: + return POWER_S5; + case AP_POWER_STATE_S3: + return POWER_S3; +#if CONFIG_AP_PWRSEQ_S0IX + case AP_POWER_STATE_S0IX: + return POWER_S0ix; +#endif + default: + return 0; + } +} + +int ap_power_get_lazy_wake_mask(enum ap_pwrseq_state state, host_event_t *mask) +{ + enum power_state st; + + st = translate_ap_power_state(state); + if (!st) + return -EINVAL; + return get_lazy_wake_mask(st, mask); +} +#endif /* CONFIG_AP_PWRSEQ_DRIVER */ #if CONFIG_AP_PWRSEQ_HOST_SLEEP void power_chipset_handle_host_sleep_event(enum host_sleep_event state, diff --git a/zephyr/subsys/ap_pwrseq/ap_power_interface.c b/zephyr/subsys/ap_pwrseq/ap_power_interface.c index 1461ed139b..684bcbb5e0 100644 --- a/zephyr/subsys/ap_pwrseq/ap_power_interface.c +++ b/zephyr/subsys/ap_pwrseq/ap_power_interface.c @@ -8,6 +8,7 @@ LOG_MODULE_DECLARE(ap_pwrseq, CONFIG_AP_PWRSEQ_LOG_LEVEL); +#ifndef CONFIG_AP_PWRSEQ_DRIVER bool ap_power_in_state(enum ap_power_state_mask state_mask) { int need_mask = 0; @@ -114,6 +115,69 @@ void ap_power_exit_hardoff(void) return; request_start_from_g3(); } +#else +bool ap_power_in_state(enum ap_power_state_mask state_mask) +{ + /* + * PWRSEQ_DRIVER will only expose stable power states (transitions + * occur automatically and are not visible to API consumers), so + * return ap_power_in_or_transitioning_to_state since it is + * equivalent to this function. + */ + return ap_power_in_or_transitioning_to_state(state_mask); +} + +bool ap_power_in_or_transitioning_to_state(enum ap_power_state_mask state_mask) +{ + const struct device *dev = ap_pwrseq_get_instance(); + + switch (ap_pwrseq_get_current_state(dev)) { + case AP_POWER_STATE_G3: + return state_mask & AP_POWER_STATE_HARD_OFF; + case AP_POWER_STATE_S5: + return state_mask & AP_POWER_STATE_SOFT_OFF; + case AP_POWER_STATE_S3: + case AP_POWER_STATE_S4: + return state_mask & AP_POWER_STATE_SUSPEND; +#if CONFIG_AP_PWRSEQ_S0IX + case AP_POWER_STATE_S0IX: + return state_mask & AP_POWER_STATE_STANDBY; +#endif + case AP_POWER_STATE_S0: + return state_mask & AP_POWER_STATE_ON; + default: + break; + } + /* Unknown power state; return false. */ + return 0; +} + +void ap_power_exit_hardoff(void) +{ + const struct device *dev = ap_pwrseq_get_instance(); + enum ap_pwrseq_state power_state; + + ap_pwrseq_state_lock(dev); + /* + * If not in the soft-off state, hard-off state, or headed there, + * nothing to do. + */ + power_state = ap_pwrseq_get_current_state(dev); + if (power_state == AP_POWER_STATE_G3 || + power_state == AP_POWER_STATE_S5) { + request_start_from_g3(); + } + + ap_pwrseq_state_unlock(dev); +} + +void ap_pwrseq_task_start(void) +{ + const struct device *dev = ap_pwrseq_get_instance(); + + ap_pwrseq_start(dev, chipset_pwr_seq_get_state()); +} +#endif /* CONFIG_AP_PWRSEQ_DRIVER */ void ap_power_init_reset_log(void) { diff --git a/zephyr/subsys/ap_pwrseq/ap_pwrseq.c b/zephyr/subsys/ap_pwrseq/ap_pwrseq.c index c02ec88363..6960938205 100644 --- a/zephyr/subsys/ap_pwrseq/ap_pwrseq.c +++ b/zephyr/subsys/ap_pwrseq/ap_pwrseq.c @@ -9,7 +9,7 @@ #include #include -LOG_MODULE_DECLARE(ap_pwrseq, CONFIG_AP_PWRSEQ_LOG_LEVEL); +LOG_MODULE_REGISTER(ap_pwrseq, CONFIG_AP_PWRSEQ_LOG_LEVEL); #define AP_PWRSEQ_EVENT_MASK GENMASK(AP_PWRSEQ_EVENT_COUNT - 1, 0) #define AP_PWRSEQ_STATES_MASK GENMASK(AP_POWER_STATE_COUNT - 1, 0) diff --git a/zephyr/subsys/ap_pwrseq/include/ap_power_host_sleep.h b/zephyr/subsys/ap_pwrseq/include/ap_power_host_sleep.h index 7251f96b76..e615f634b8 100644 --- a/zephyr/subsys/ap_pwrseq/include/ap_power_host_sleep.h +++ b/zephyr/subsys/ap_pwrseq/include/ap_power_host_sleep.h @@ -9,6 +9,10 @@ #include #include +#ifdef CONFIG_AP_PWRSEQ_DRIVER +#include "ap_power/ap_pwrseq.h" +#endif + /* * Deferred call to set active mask according to current power state */ @@ -22,8 +26,12 @@ void ap_power_set_active_wake_mask(void); * * @return 0 for success; -EINVAL if power state is not S3/S5/S0ix */ +#ifndef CONFIG_AP_PWRSEQ_DRIVER int ap_power_get_lazy_wake_mask(enum power_states_ndsx state, host_event_t *mask); +#else +int ap_power_get_lazy_wake_mask(enum ap_pwrseq_state state, host_event_t *mask); +#endif #if CONFIG_AP_PWRSEQ_S0IX /* For S0ix path, flag to notify sleep change */ diff --git a/zephyr/subsys/ap_pwrseq/include/x86_common_pwrseq.h b/zephyr/subsys/ap_pwrseq/include/x86_common_pwrseq.h index 75390b5005..b36b7f7714 100644 --- a/zephyr/subsys/ap_pwrseq/include/x86_common_pwrseq.h +++ b/zephyr/subsys/ap_pwrseq/include/x86_common_pwrseq.h @@ -13,10 +13,12 @@ #include #include +#ifndef CONFIG_AP_PWRSEQ_DRIVER /* This encapsulates the attributes of the state machine */ struct pwrseq_context { /* On power-on start boot up sequence */ enum power_states_ndsx power_state; }; +#endif #endif /* __X86_COMMON_PWRSEQ_H__ */ 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 9656d8982d..2f9b01fbee 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 @@ -10,20 +10,28 @@ #include #include +#ifdef CONFIG_AP_PWRSEQ_DRIVE +#include +#else #include #include +#endif #include #include +#ifndef CONFIG_AP_PWRSEQ_DRIVER /* The wait time is ~150 msec, allow for safety margin. */ #define IN_PCH_SLP_SUS_WAIT_TIME_MS 250 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_start_from_g3(void); enum power_states_ndsx pwr_sm_get_state(void); const char *const pwr_sm_get_state_name(enum power_states_ndsx state); +#else +enum ap_pwrseq_state chipset_pwr_seq_get_state(void); +const char *const pwr_sm_get_state_name(enum ap_pwrseq_state state); +#endif +void request_start_from_g3(void); void apshutdown(void); void ap_pwrseq_handle_chipset_reset(void); void set_start_from_g3_delay_seconds(uint32_t d_time); diff --git a/zephyr/subsys/ap_pwrseq/power_host_sleep.c b/zephyr/subsys/ap_pwrseq/power_host_sleep.c index 5c91b2503e..96335b066b 100644 --- a/zephyr/subsys/ap_pwrseq/power_host_sleep.c +++ b/zephyr/subsys/ap_pwrseq/power_host_sleep.c @@ -25,6 +25,7 @@ LOG_MODULE_DECLARE(ap_pwrseq, CONFIG_AP_PWRSEQ_LOG_LEVEL); * 4. If state is S0ix and no lazy or active wake mask is set, then use default * S0ix mask to be compatible with older BIOS versions. */ +#ifndef CONFIG_AP_PWRSEQ_DRIVER void power_update_wake_mask(void) { host_event_t wake_mask; @@ -44,6 +45,28 @@ void power_update_wake_mask(void) lpc_set_host_event_mask(LPC_HOST_EVENT_WAKE, wake_mask); } +#else +void power_update_wake_mask(void) +{ + const struct device *dev = ap_pwrseq_get_instance(); + host_event_t wake_mask; + enum ap_pwrseq_state state; + + state = ap_pwrseq_get_current_state(dev); + + if (state == AP_POWER_STATE_S0) + wake_mask = 0; + else if (lpc_is_active_wm_set_by_host() || + ap_power_get_lazy_wake_mask(state, &wake_mask)) + return; +#if CONFIG_AP_PWRSEQ_S0IX + if ((state == AP_POWER_STATE_S0IX) && (wake_mask == 0)) + wake_mask = DEFAULT_WAKE_MASK_S0IX; +#endif + + lpc_set_host_event_mask(LPC_HOST_EVENT_WAKE, wake_mask); +} +#endif /* CONFIG_AP_PWRSEQ_DRIVER */ static void power_update_wake_mask_deferred(struct k_work *work) { @@ -251,7 +274,12 @@ void ap_power_chipset_handle_host_sleep_event( power_signal_disable(PWR_SLP_S0); } #endif /* CONFIG_AP_PWRSEQ_S0IX */ + +#ifndef CONFIG_AP_PWRSEQ_DRIVER ap_pwrseq_wake(); +#else + ap_pwrseq_post_event(ap_pwrseq_get_instance(), AP_PWRSEQ_EVENT_HOST); +#endif /* CONFIG_AP_PWRSEQ_DRIVER */ } uint16_t host_get_sleep_timeout(void) diff --git a/zephyr/subsys/ap_pwrseq/power_signals.c b/zephyr/subsys/ap_pwrseq/power_signals.c index 765cc95707..84a8b8ad53 100644 --- a/zephyr/subsys/ap_pwrseq/power_signals.c +++ b/zephyr/subsys/ap_pwrseq/power_signals.c @@ -11,6 +11,9 @@ #include #include #include +#ifdef CONFIG_AP_PWRSEQ_DRIVER +#include +#endif #include #include @@ -133,13 +136,23 @@ power_signal_mask_t power_get_signals(void) return mask | atomic_get(&power_signals); } +#ifndef CONFIG_AP_PWRSEQ_DRIVER void power_signal_interrupt(enum power_signal signal, int value) { atomic_set_bit_to(&power_signals, signal, value); check_debug(signal); ap_pwrseq_wake(); } +#else +void power_signal_interrupt(enum power_signal signal, int value) +{ + const struct device *ap_pwrseq_dev = ap_pwrseq_get_instance(); + atomic_set_bit_to(&power_signals, signal, value); + check_debug(signal); + ap_pwrseq_post_event(ap_pwrseq_dev, AP_PWRSEQ_EVENT_POWER_SIGNAL); +} +#endif int power_wait_mask_signals_timeout(power_signal_mask_t mask, power_signal_mask_t want, int timeout) { diff --git a/zephyr/subsys/ap_pwrseq/x86_non_dsx_chipset_power_state.c b/zephyr/subsys/ap_pwrseq/x86_non_dsx_chipset_power_state.c index e4ce364cb1..e4da35b095 100644 --- a/zephyr/subsys/ap_pwrseq/x86_non_dsx_chipset_power_state.c +++ b/zephyr/subsys/ap_pwrseq/x86_non_dsx_chipset_power_state.c @@ -3,6 +3,9 @@ * found in the LICENSE file. */ +#ifdef CONFIG_AP_PWRSEQ_DRIVER +#include +#endif #include #include @@ -12,6 +15,7 @@ LOG_MODULE_DECLARE(ap_pwrseq, CONFIG_AP_PWRSEQ_LOG_LEVEL); * Determine the current state of the CPU from the * power signals. */ +#ifndef CONFIG_AP_PWRSEQ_DRIVER enum power_states_ndsx chipset_pwr_seq_get_state(void) { power_signal_mask_t sig = power_get_signals(); @@ -89,3 +93,83 @@ enum power_states_ndsx chipset_pwr_seq_get_state(void) ap_power_force_shutdown(AP_POWER_SHUTDOWN_G3); return SYS_POWER_STATE_G3; } +#else +enum ap_pwrseq_state chipset_pwr_seq_get_state(void) +{ + power_signal_mask_t sig; + + sig = power_get_signals(); + /* + * Chip is shut down, G3 state. + */ + if ((sig & MASK_ALL_POWER_GOOD) == 0) { + LOG_DBG("All power rails off, G3 state"); + return AP_POWER_STATE_G3; + } + /* + * Not enough power rails up to read VW signals. + * Force a shutdown. + */ + if ((sig & MASK_VW_POWER) != VALUE_VW_POWER) { + LOG_ERR("Not enough power signals on (%#x), forcing shutdown", + sig); + ap_power_force_shutdown(AP_POWER_SHUTDOWN_G3); + return AP_POWER_STATE_G3; + } + + /* + * Enough power signals are up, 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_HOST_INTERFACE_ESPI_VW_SLP_S3) + if (power_signal_get(PWR_SLP_S3) < 0) + continue; +#endif +#if defined(CONFIG_PLATFORM_EC_HOST_INTERFACE_ESPI_VW_SLP_S4) + if (power_signal_get(PWR_SLP_S4) < 0) + continue; +#endif +#if defined(CONFIG_PLATFORM_EC_HOST_INTERFACE_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; + } + /* Re-read the power signals */ + sig = power_get_signals(); + + /* + * S0, all power OK, no suspend or sleep on. + */ + if ((sig & MASK_S0) == VALUE_S0) { + LOG_DBG("CPU in S0 state"); + return AP_POWER_STATE_S0; + } + /* + * S3, all power OK, PWR_SLP_S3 on. + */ + if ((sig & MASK_S3) == VALUE_S3) { + LOG_DBG("CPU in S3 state"); + return AP_POWER_STATE_S3; + } + /* + * S5, some power signals on, PWR_SLP_S5 on. + */ + if ((sig & MASK_S5) == VALUE_S5) { + LOG_DBG("CPU in S5 state"); + return AP_POWER_STATE_S5; + } + /* + * Unable to determine state, force to G3. + */ + LOG_INF("Unable to determine CPU state (%#x), forcing shutdown", sig); + ap_power_force_shutdown(AP_POWER_SHUTDOWN_G3); + return AP_POWER_STATE_G3; +} +#endif /* CONFIG_AP_PWRSEQ_DRIVER */ 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 index 6ac2b5e0ba..a31d9e3f3a 100644 --- a/zephyr/subsys/ap_pwrseq/x86_non_dsx_common_pwrseq_console.c +++ b/zephyr/subsys/ap_pwrseq/x86_non_dsx_common_pwrseq_console.c @@ -15,7 +15,12 @@ LOG_MODULE_DECLARE(ap_pwrseq, CONFIG_AP_PWRSEQ_LOG_LEVEL); static int powerinfo_handler(const struct shell *shell, size_t argc, char **argv) { +#ifndef CONFIG_AP_PWRSEQ_DRIVER enum power_states_ndsx state = pwr_sm_get_state(); +#else + const struct device *dev = ap_pwrseq_get_instance(); + enum ap_pwrseq_state state = ap_pwrseq_get_current_state(dev); +#endif shell_fprintf(shell, SHELL_INFO, "power state %d = %s, in 0x%04x\n", state, pwr_sm_get_state_name(state), power_get_signals()); diff --git a/zephyr/subsys/ap_pwrseq/x86_non_dsx_common_pwrseq_host_sleep.c b/zephyr/subsys/ap_pwrseq/x86_non_dsx_common_pwrseq_host_sleep.c index 015cecb502..2e16aba1bb 100644 --- a/zephyr/subsys/ap_pwrseq/x86_non_dsx_common_pwrseq_host_sleep.c +++ b/zephyr/subsys/ap_pwrseq/x86_non_dsx_common_pwrseq_host_sleep.c @@ -34,6 +34,7 @@ void power_chipset_handle_sleep_hang(enum sleep_hang_type hang_type) * wake mask to pretend it did, so that the hang detect event wakes the * system. */ +#ifndef CONFIG_AP_PWRSEQ_DRIVER if (pwr_sm_get_state() == SYS_POWER_STATE_S0) { host_event_t sleep_wake_mask; @@ -41,6 +42,17 @@ void power_chipset_handle_sleep_hang(enum sleep_hang_type hang_type) &sleep_wake_mask); lpc_set_host_event_mask(LPC_HOST_EVENT_WAKE, sleep_wake_mask); } +#else + const struct device *dev = ap_pwrseq_get_instance(); + + if (ap_pwrseq_get_current_state(dev) == AP_POWER_STATE_S0) { + host_event_t sleep_wake_mask; + + ap_power_get_lazy_wake_mask(AP_POWER_STATE_S0IX, + &sleep_wake_mask); + lpc_set_host_event_mask(LPC_HOST_EVENT_WAKE, sleep_wake_mask); + } +#endif ccprintf("Warning: Detected sleep hang! Waking host up!"); host_set_single_event(EC_HOST_EVENT_HANG_DETECT); 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 3e33915f8f..829ac13f73 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 @@ -9,18 +9,22 @@ #include #include +#ifndef CONFIG_AP_PWRSEQ_DRIVER #include +#else +#include "ap_power/ap_pwrseq.h" +#include "ap_power/ap_pwrseq_sm.h" +#include "x86_non_dsx_common_pwrseq_sm_handler.h" +#include "zephyr_console_shim.h" +#endif -static K_KERNEL_STACK_DEFINE(pwrseq_thread_stack, CONFIG_AP_PWRSEQ_STACK_SIZE); -static struct k_thread pwrseq_thread_data; -static struct pwrseq_context pwrseq_ctx = { - .power_state = SYS_POWER_STATE_UNINIT, -}; -static struct k_sem pwrseq_sem; +/* Delay in ms when starting from G3 */ +static uint32_t start_from_g3_delay_ms; + +#ifdef CONFIG_AP_PWRSEQ_DEBUG_MODE_COMMAND +static bool in_debug_mode; +#endif -static void s5_inactive_timer_handler(struct k_timer *timer); -/* S5 inactive timer*/ -K_TIMER_DEFINE(s5_inactive_timer, s5_inactive_timer_handler, NULL); /* * Flags, may be set/cleared from other threads. */ @@ -30,12 +34,18 @@ enum { FLAGS_MAX, }; static ATOMIC_DEFINE(flags, FLAGS_MAX); -/* Delay in ms when starting from G3 */ -static uint32_t start_from_g3_delay_ms; -#ifdef CONFIG_AP_PWRSEQ_DEBUG_MODE_COMMAND -static bool in_debug_mode; -#endif +#ifndef CONFIG_AP_PWRSEQ_DRIVER +static K_KERNEL_STACK_DEFINE(pwrseq_thread_stack, CONFIG_AP_PWRSEQ_STACK_SIZE); +static struct k_thread pwrseq_thread_data; +static struct pwrseq_context pwrseq_ctx = { + .power_state = SYS_POWER_STATE_UNINIT, +}; +static struct k_sem pwrseq_sem; + +static void s5_inactive_timer_handler(struct k_timer *timer); +/* S5 inactive timer*/ +K_TIMER_DEFINE(s5_inactive_timer, s5_inactive_timer_handler, NULL); LOG_MODULE_REGISTER(ap_pwrseq, CONFIG_AP_PWRSEQ_LOG_LEVEL); @@ -65,6 +75,13 @@ static const char *const pwrsm_dbg[] = { [SYS_POWER_STATE_S0S0ix] = "S0S0ix", #endif }; +#else +static void x86_non_dsx_timer_handler(struct k_timer *timer); + +K_TIMER_DEFINE(x86_non_dsx_timer, x86_non_dsx_timer_handler, NULL); + +LOG_MODULE_DECLARE(ap_pwrseq, CONFIG_AP_PWRSEQ_LOG_LEVEL); +#endif /* CONFIG_AP_PWRSEQ_DRIVER */ /* * Returns true if all signals in mask are valid. @@ -100,6 +117,7 @@ static inline bool signals_valid_and_off(power_signal_mask_t signals) return signals_valid(signals) && power_signals_off(signals); } +#ifndef CONFIG_AP_PWRSEQ_DRIVER enum power_states_ndsx pwr_sm_get_state(void) { return pwrseq_ctx.power_state; @@ -149,18 +167,6 @@ void request_start_from_g3(void) ap_pwrseq_wake(); } -void ap_power_force_shutdown(enum ap_power_shutdown_reason reason) -{ -#ifdef CONFIG_AP_PWRSEQ_DEBUG_MODE_COMMAND - /* This prevents force shutdown if debug mode is enabled */ - if (in_debug_mode) { - LOG_WRN("debug_mode is enabled, preventing force shutdown"); - return; - } -#endif /* CONFIG_AP_PWRSEQ_DEBUG_MODE_COMMAND */ - board_ap_power_force_shutdown(); -} - static void s5_inactive_timer_handler(struct k_timer *timer) { ap_pwrseq_wake(); @@ -173,11 +179,6 @@ static void shutdown_and_notify(enum ap_power_shutdown_reason reason) ap_power_ev_send_callbacks(AP_POWER_SHUTDOWN_COMPLETE); } -void set_start_from_g3_delay_seconds(uint32_t d_time) -{ - start_from_g3_delay_ms = d_time * MSEC; -} - void apshutdown(void) { if (pwr_sm_get_state() != SYS_POWER_STATE_G3) { @@ -185,6 +186,88 @@ void apshutdown(void) pwr_sm_set_state(SYS_POWER_STATE_G3); } } +#else +const char *const pwr_sm_get_state_name(enum ap_pwrseq_state state) +{ + return ap_pwrseq_get_state_str(state); +} + +static void x86_non_dsx_timer_handler(struct k_timer *timer) +{ + if (atomic_test_bit(flags, S5_INACTIVE_TIMER_RUNNING)) { + ap_pwrseq_post_event(ap_pwrseq_get_instance(), + AP_PWRSEQ_EVENT_POWER_TIMEOUT); + } else if (atomic_test_bit(flags, START_FROM_G3)) { + ap_pwrseq_post_event(ap_pwrseq_get_instance(), + AP_PWRSEQ_EVENT_POWER_STARTUP); + } +} + +void request_start_from_g3(void) +{ + const struct device *dev = ap_pwrseq_get_instance(); + + LOG_INF("Request start from G3"); + /* + * If in S5, restart the timer to give the CPU more time + * to respond to a power button press (which is presumably + * why we are being called). This avoids having the S5 + * inactivity timer expiring before the AP can process + * the power button press and start up. + */ + if (ap_pwrseq_get_current_state(dev) == AP_POWER_STATE_S5 && + AP_PWRSEQ_DT_VALUE(s5_inactivity_timeout)) { + k_timer_start( + &x86_non_dsx_timer, + K_SECONDS(AP_PWRSEQ_DT_VALUE(s5_inactivity_timeout)), + K_NO_WAIT); + return; + } + + atomic_set_bit(flags, START_FROM_G3); + if (ap_pwrseq_get_current_state(dev) == AP_POWER_STATE_G3) { + if (start_from_g3_delay_ms) { + k_timer_start(&x86_non_dsx_timer, + K_MSEC(start_from_g3_delay_ms), + K_NO_WAIT); + start_from_g3_delay_ms = 0; + } else { + ap_pwrseq_post_event(dev, + AP_PWRSEQ_EVENT_POWER_STARTUP); + } + } +} + +void apshutdown(void) +{ + const struct device *dev = ap_pwrseq_get_instance(); + + ap_pwrseq_state_lock(dev); + + if (ap_pwrseq_get_current_state(dev) != AP_POWER_STATE_G3) { + ap_power_force_shutdown(AP_POWER_SHUTDOWN_G3); + } + + ap_pwrseq_state_unlock(dev); +} +#endif /* CONFIG_AP_PWRSEQ_DRIVER */ + +void ap_power_force_shutdown(enum ap_power_shutdown_reason reason) +{ +#ifdef CONFIG_AP_PWRSEQ_DEBUG_MODE_COMMAND + /* This prevents force shutdown if debug mode is enabled */ + if (in_debug_mode) { + LOG_WRN("debug_mode is enabled, preventing force shutdown"); + return; + } +#endif /* CONFIG_AP_PWRSEQ_DEBUG_MODE_COMMAND */ + board_ap_power_force_shutdown(); +} + +void set_start_from_g3_delay_seconds(uint32_t d_time) +{ + start_from_g3_delay_ms = d_time * MSEC; +} void ap_power_reset(enum ap_power_shutdown_reason reason) { @@ -242,6 +325,7 @@ void rsmrst_pass_thru_handler(void) } } +#ifndef CONFIG_AP_PWRSEQ_DRIVER /* Common power sequencing */ static int common_pwr_sm_run(int state) { @@ -666,6 +750,7 @@ static int pwrseq_init(const struct device *dev) * the signals depend upon, such as GPIO, ADC etc. */ SYS_INIT(pwrseq_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY); +#endif /* CONFIG_AP_PWRSEQ_DRIVER */ #ifdef CONFIG_AP_PWRSEQ_DEBUG_MODE_COMMAND /* -- cgit v1.2.1