diff options
Diffstat (limited to 'zephyr/subsys/ap_pwrseq')
-rw-r--r-- | zephyr/subsys/ap_pwrseq/include/signal_vw.h | 7 | ||||
-rw-r--r-- | zephyr/subsys/ap_pwrseq/include/x86_common_pwrseq.h | 3 | ||||
-rw-r--r-- | zephyr/subsys/ap_pwrseq/include/x86_power_signals.h | 10 | ||||
-rw-r--r-- | zephyr/subsys/ap_pwrseq/power_host_sleep.c | 6 | ||||
-rw-r--r-- | zephyr/subsys/ap_pwrseq/power_signals.c | 68 | ||||
-rw-r--r-- | zephyr/subsys/ap_pwrseq/signal_adc.c | 4 | ||||
-rw-r--r-- | zephyr/subsys/ap_pwrseq/signal_gpio.c | 7 | ||||
-rw-r--r-- | zephyr/subsys/ap_pwrseq/signal_vw.c | 73 | ||||
-rw-r--r-- | zephyr/subsys/ap_pwrseq/x86_non_dsx_common_pwrseq_sm_handler.c | 32 |
9 files changed, 109 insertions, 101 deletions
diff --git a/zephyr/subsys/ap_pwrseq/include/signal_vw.h b/zephyr/subsys/ap_pwrseq/include/signal_vw.h index bb05d15a71..d005daaa40 100644 --- a/zephyr/subsys/ap_pwrseq/include/signal_vw.h +++ b/zephyr/subsys/ap_pwrseq/include/signal_vw.h @@ -45,11 +45,4 @@ int power_signal_vw_get(enum pwr_sig_vw vw); */ void power_signal_vw_init(void); -/** - * @brief External notification when the bus is ready or not. - * - * @param ready true When signals are valid, false when bus is not ready. - */ -void notify_espi_ready(bool ready); - #endif /* __AP_PWRSEQ_SIGNAL_VW_H__ */ diff --git a/zephyr/subsys/ap_pwrseq/include/x86_common_pwrseq.h b/zephyr/subsys/ap_pwrseq/include/x86_common_pwrseq.h index 6eee6ce140..9b6c60b53c 100644 --- a/zephyr/subsys/ap_pwrseq/include/x86_common_pwrseq.h +++ b/zephyr/subsys/ap_pwrseq/include/x86_common_pwrseq.h @@ -18,9 +18,6 @@ struct pwrseq_context { enum power_states_ndsx power_state; /* Indicate should exit G3 power state or not */ bool want_g3_exit; -#if defined(PWRSEQ_REQUIRE_ESPI) - bool espi_ready; -#endif }; diff --git a/zephyr/subsys/ap_pwrseq/include/x86_power_signals.h b/zephyr/subsys/ap_pwrseq/include/x86_power_signals.h index 8ec4770e99..1832c4877c 100644 --- a/zephyr/subsys/ap_pwrseq/include/x86_power_signals.h +++ b/zephyr/subsys/ap_pwrseq/include/x86_power_signals.h @@ -24,16 +24,6 @@ #define IN_ALL_S0_VALUE IN_PGOOD_ALL_CORE #define CHIPSET_G3S5_POWERUP_SIGNAL IN_PCH_SLP_SUS_DEASSERTED -#if defined(CONFIG_PLATFORM_EC_ESPI_VW_SLP_S3) || \ - defined(CONFIG_PLATFORM_EC_ESPI_VW_SLP_S4) || \ - defined(CONFIG_PLATFORM_EC_ESPI_VW_SLP_S5) -/* - * Set if ESPI signals are required, so need to check - * whether ESPI is ready or not - */ -#define PWRSEQ_REQUIRE_ESPI -#endif - #else #warning("Input power signals state flags not defined"); #endif diff --git a/zephyr/subsys/ap_pwrseq/power_host_sleep.c b/zephyr/subsys/ap_pwrseq/power_host_sleep.c index 13e6aba765..2e7df63c51 100644 --- a/zephyr/subsys/ap_pwrseq/power_host_sleep.c +++ b/zephyr/subsys/ap_pwrseq/power_host_sleep.c @@ -203,7 +203,7 @@ void ap_power_chipset_handle_host_sleep_event( * notification needs to be sent to listeners. */ ap_power_sleep_set_notify(AP_POWER_SLEEP_SUSPEND); - power_signal_enable_interrupt(PWR_SLP_S0); + power_signal_enable(PWR_SLP_S0); } else if (state == HOST_SLEEP_EVENT_S0IX_RESUME) { /* @@ -212,7 +212,7 @@ void ap_power_chipset_handle_host_sleep_event( */ ap_power_sleep_set_notify(AP_POWER_SLEEP_RESUME); power_s0ix_resume_restore_masks(); - power_signal_disable_interrupt(PWR_SLP_S0); + power_signal_disable(PWR_SLP_S0); /* * If the sleep signal timed out and never transitioned, then @@ -223,7 +223,7 @@ void ap_power_chipset_handle_host_sleep_event( power_update_wake_mask(); } else if (state == HOST_SLEEP_EVENT_DEFAULT_RESET) { - power_signal_disable_interrupt(PWR_SLP_S0); + power_signal_disable(PWR_SLP_S0); } #endif /* CONFIG_AP_PWRSEQ_S0IX */ } diff --git a/zephyr/subsys/ap_pwrseq/power_signals.c b/zephyr/subsys/ap_pwrseq/power_signals.c index c463e8e82e..7df7b3ef00 100644 --- a/zephyr/subsys/ap_pwrseq/power_signals.c +++ b/zephyr/subsys/ap_pwrseq/power_signals.c @@ -86,16 +86,18 @@ DT_FOREACH_STATUS_OKAY(intel_ap_pwrseq_external, PWR_SIGNAL_POLLED) }; /* - * Bitmask of power signals updated via interrupt. + * Bitmasks of power signals. A previous copy is held so that + * logging of changes can occur if the signal is in the debug mask. */ -static atomic_t interrupt_power_signals; +static atomic_t power_signals, prev_power_signals; -static power_signal_mask_t output_signals; static power_signal_mask_t debug_signals; void power_set_debug(power_signal_mask_t debug) { debug_signals = debug; + /* Copy the current values */ + atomic_set(&prev_power_signals, atomic_get(&power_signals)); } power_signal_mask_t power_get_debug(void) @@ -103,12 +105,19 @@ power_signal_mask_t power_get_debug(void) return debug_signals; } -static inline void check_debug(power_signal_mask_t mask, - enum power_signal signal, - int value) +static inline void check_debug(enum power_signal signal) { - if (debug_signals & mask) { - LOG_INF("%s -> %d", power_signal_name(signal), value); + /* + * Only check for debug display if the logging level requires it. + */ + if ((CONFIG_AP_PWRSEQ_LOG_LEVEL >= LOG_LEVEL_INF) && + (debug_signals & POWER_SIGNAL_MASK(signal))) { + bool value = atomic_test_bit(&power_signals, signal); + + if (value != atomic_test_bit(&prev_power_signals, signal)) { + LOG_INF("%s -> %d", power_signal_name(signal), value); + atomic_set_bit_to(&prev_power_signals, signal, value); + } } } @@ -121,14 +130,13 @@ power_signal_mask_t power_get_signals(void) mask |= POWER_SIGNAL_MASK(polled_signals[i]); } } - return mask | output_signals | - atomic_get(&interrupt_power_signals); + return mask | atomic_get(&power_signals); } void power_signal_interrupt(enum power_signal signal, int value) { - atomic_set_bit_to(&interrupt_power_signals, signal, value); - check_debug(POWER_SIGNAL_MASK(signal), signal, value); + atomic_set_bit_to(&power_signals, signal, value); + check_debug(signal); } int power_wait_mask_signals_timeout(power_signal_mask_t mask, @@ -209,19 +217,11 @@ int power_signal_set(enum power_signal signal, int value) #endif } /* - * Output succeeded, update output mask. + * Output succeeded, update mask. */ if (ret == 0) { - power_signal_mask_t mask = POWER_SIGNAL_MASK(signal); - power_signal_mask_t old = output_signals; - - if (value) - output_signals |= mask; - else - output_signals &= ~mask; - if (old != output_signals) { - check_debug(mask, signal, value); - } + atomic_set_bit_to(&power_signals, signal, value); + check_debug(signal); } return ret; } @@ -295,4 +295,26 @@ void power_signal_init(void) if (IS_ENABLED(HAS_ADC_SIGNALS)) { power_signal_adc_init(); } + /* + * Initialise the mask with the current values. + * This includes the outputs as well. + */ + for (int i = 0; i < POWER_SIGNAL_COUNT; i++) { + if (power_signal_get(i) == 1) { + atomic_set_bit(&power_signals, i); + } + } + /* + * Some signals are polled (such as the board external signals), + * so clear these values from the initial state so they + * don't get OR'ed in later on. + */ + for (int i = 0; i < ARRAY_SIZE(polled_signals); i++) { + atomic_clear_bit(&power_signals, i); + } + /* + * Save the current state so that new changes can be + * checked against the debug mask. + */ + atomic_set(&prev_power_signals, atomic_get(&power_signals)); } diff --git a/zephyr/subsys/ap_pwrseq/signal_adc.c b/zephyr/subsys/ap_pwrseq/signal_adc.c index 9898c8e4bd..17038ba2ea 100644 --- a/zephyr/subsys/ap_pwrseq/signal_adc.c +++ b/zephyr/subsys/ap_pwrseq/signal_adc.c @@ -175,6 +175,10 @@ void power_signal_adc_init(void) /* Set high and low trigger callbacks */ sensor_trigger_set(config[i].dev_trig_high, &trig, high_cb[i]); sensor_trigger_set(config[i].dev_trig_low, &trig, low_cb[i]); + /* + * TODO: Get current value and initialise adc_state. + * + */ power_signal_adc_enable(i); } } diff --git a/zephyr/subsys/ap_pwrseq/signal_gpio.c b/zephyr/subsys/ap_pwrseq/signal_gpio.c index b4888f8cff..e28df96e6b 100644 --- a/zephyr/subsys/ap_pwrseq/signal_gpio.c +++ b/zephyr/subsys/ap_pwrseq/signal_gpio.c @@ -6,7 +6,7 @@ #include <power_signals.h> #include <signal_gpio.h> #include <drivers/gpio.h> -#include "system.h" +#include "sysjump.h" #define MY_COMPAT intel_ap_pwrseq_gpio @@ -121,8 +121,11 @@ void power_signal_gpio_init(void) /* * If there has been a sysjump, do not set the output * to the deasserted state. + * We can't use system_jumped_late() since that is not + * initialised at this point. */ - gpio_flags_t out_flags = system_jumped_late() ? + struct jump_data *jdata = get_jump_data(); + gpio_flags_t out_flags = (jdata && jdata->magic == JUMP_DATA_MAGIC) ? GPIO_OUTPUT : GPIO_OUTPUT_INACTIVE; for (int i = 0; i < ARRAY_SIZE(gpio_config); i++) { diff --git a/zephyr/subsys/ap_pwrseq/signal_vw.c b/zephyr/subsys/ap_pwrseq/signal_vw.c index b0abe4fe13..a42be8ae85 100644 --- a/zephyr/subsys/ap_pwrseq/signal_vw.c +++ b/zephyr/subsys/ap_pwrseq/signal_vw.c @@ -3,6 +3,7 @@ * found in the LICENSE file. */ +#include <atomic.h> #include <drivers/espi.h> #include <x86_non_dsx_common_pwrseq_sm_handler.h> @@ -34,18 +35,20 @@ const static struct vw_config vw_config[] = { DT_FOREACH_STATUS_OKAY(MY_COMPAT, INIT_ESPI_SIGNAL) }; -static bool signal_data[ARRAY_SIZE(vw_config)]; +/* + * Current signal value. + */ +static atomic_t signal_data; +/* + * Mask of valid signals. If the bus is reset, this is cleared, + * and when a signal is updated the associated bit is set to indicate + * the signal is valid. + */ +static atomic_t signal_valid; #define espi_dev DEVICE_DT_GET(DT_CHOSEN(intel_ap_pwrseq_espi)) -/* - * Mask of updated signals. If the bus is reset, this is cleared, - * and it is only when all the signals have been updated that - * notification is sent that the signals are ready. - */ -static uint8_t espi_mask; -static bool espi_not_valid; -BUILD_ASSERT(ARRAY_SIZE(vw_config) <= 8); +BUILD_ASSERT(ARRAY_SIZE(vw_config) <= (sizeof(atomic_t) * 8)); static void espi_handler(const struct device *dev, struct espi_callback *cb, @@ -61,53 +64,35 @@ static void espi_handler(const struct device *dev, case ESPI_BUS_RESET: /* - * Notify that the bus isn't ready, and clear - * the signal mask. + * Clear the signal valid mask. */ - notify_espi_ready(false); - espi_mask = 0; - espi_not_valid = true; + atomic_clear(&signal_valid); break; case ESPI_BUS_EVENT_VWIRE_RECEIVED: for (int i = 0; i < ARRAY_SIZE(vw_config); i++) { if (event.evt_details == vw_config[i].espi_signal) { - int value = vw_config[i].invert + bool value = vw_config[i].invert ? !event.evt_data : !!event.evt_data; - signal_data[i] = value; - if (espi_not_valid) { - espi_mask |= BIT(i); - } + atomic_set_bit_to(&signal_data, i, value); + atomic_set_bit(&signal_valid, i); power_signal_interrupt(vw_config[i].signal, value); } } - /* - * When all the signals have been updated, notify that - * the ESPI signals are valid. - */ - if (espi_not_valid && - espi_mask == BIT_MASK(ARRAY_SIZE(vw_config))) { - espi_not_valid = false; - LOG_DBG("ESPI signals valid"); - /* - * TODO(b/222946923): Convert to generalised - * callback pattern. - */ - notify_espi_ready(true); - } break; } } int power_signal_vw_get(enum pwr_sig_vw vw) { - if (vw < 0 || vw >= ARRAY_SIZE(vw_config)) { + if (vw < 0 || vw >= ARRAY_SIZE(vw_config) || + !atomic_test_bit(&signal_valid, vw)) { return -EINVAL; } - return signal_data[vw]; + return atomic_test_bit(&signal_data, vw); } void power_signal_vw_init(void) @@ -138,6 +123,24 @@ void power_signal_vw_init(void) ESPI_BUS_RESET | ESPI_BUS_EVENT_VWIRE_RECEIVED); espi_add_callback(espi_dev, &espi_cb); + /* + * Check whether the bus is ready, and if so, + * initialise the current values of the signals. + */ + if (espi_get_channel_status(espi_dev, ESPI_CHANNEL_VWIRE)) { + for (int i = 0; i < ARRAY_SIZE(vw_config); i++) { + uint8_t vw_value; + + if (espi_receive_vwire(espi_dev, + vw_config[i].espi_signal, + &vw_value) == 0) { + atomic_set_bit_to(&signal_data, i, + vw_config[i].invert + ? !vw_value + : !!vw_value); + } + } + } } #endif /* HAS_VW_SIGNALS */ 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 34c3d5df18..bcc34bd32d 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 @@ -42,34 +42,26 @@ const char pwrsm_dbg[][25] = { #endif }; -#ifdef PWRSEQ_REQUIRE_ESPI - -void notify_espi_ready(bool ready) -{ - pwrseq_ctx.espi_ready = ready; -} -#endif - /* * Returns true if all signals in mask are valid. + * This is only done for virtual wire signals. */ static inline bool signals_valid(power_signal_mask_t signals) { -#ifdef PWRSEQ_REQUIRE_ESPI - if (!pwrseq_ctx.espi_ready) { #if defined(CONFIG_PLATFORM_EC_ESPI_VW_SLP_S3) - if (signals & POWER_SIGNAL_MASK(PWR_SLP_S3)) - return false; + if ((signals & POWER_SIGNAL_MASK(PWR_SLP_S3)) && + power_signal_get(PWR_SLP_S3) < 0) + return false; #endif #if defined(CONFIG_PLATFORM_EC_ESPI_VW_SLP_S4) - if (signals & POWER_SIGNAL_MASK(PWR_SLP_S3)) - return false; + if ((signals & POWER_SIGNAL_MASK(PWR_SLP_S4)) && + power_signal_get(PWR_SLP_S4) < 0) + return false; #endif #if defined(CONFIG_PLATFORM_EC_ESPI_VW_SLP_S5) - if (signals & POWER_SIGNAL_MASK(PWR_SLP_S3)) - return false; -#endif - } + if ((signals & POWER_SIGNAL_MASK(PWR_SLP_S5)) && + power_signal_get(PWR_SLP_S5) < 0) + return false; #endif return true; } @@ -526,4 +518,8 @@ static int pwrseq_init(const struct device *dev) return 0; } +/* + * The initialisation must occur after system I/O initialisation that + * the signals depend upon, such as GPIO, ADC etc. + */ SYS_INIT(pwrseq_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY); |