summaryrefslogtreecommitdiff
path: root/zephyr/subsys/ap_pwrseq
diff options
context:
space:
mode:
Diffstat (limited to 'zephyr/subsys/ap_pwrseq')
-rw-r--r--zephyr/subsys/ap_pwrseq/include/signal_vw.h7
-rw-r--r--zephyr/subsys/ap_pwrseq/include/x86_common_pwrseq.h3
-rw-r--r--zephyr/subsys/ap_pwrseq/include/x86_power_signals.h10
-rw-r--r--zephyr/subsys/ap_pwrseq/power_host_sleep.c6
-rw-r--r--zephyr/subsys/ap_pwrseq/power_signals.c68
-rw-r--r--zephyr/subsys/ap_pwrseq/signal_adc.c4
-rw-r--r--zephyr/subsys/ap_pwrseq/signal_gpio.c7
-rw-r--r--zephyr/subsys/ap_pwrseq/signal_vw.c73
-rw-r--r--zephyr/subsys/ap_pwrseq/x86_non_dsx_common_pwrseq_sm_handler.c32
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);