summaryrefslogtreecommitdiff
path: root/zephyr/subsys/ap_pwrseq/power_signals.c
diff options
context:
space:
mode:
Diffstat (limited to 'zephyr/subsys/ap_pwrseq/power_signals.c')
-rw-r--r--zephyr/subsys/ap_pwrseq/power_signals.c82
1 files changed, 58 insertions, 24 deletions
diff --git a/zephyr/subsys/ap_pwrseq/power_signals.c b/zephyr/subsys/ap_pwrseq/power_signals.c
index 30961acd38..bbcd7ebcae 100644
--- a/zephyr/subsys/ap_pwrseq/power_signals.c
+++ b/zephyr/subsys/ap_pwrseq/power_signals.c
@@ -6,6 +6,7 @@
#include <kernel.h>
#include <toolchain.h>
#include <logging/log.h>
+#include <sys/atomic.h>
#include <power_signals.h>
@@ -75,25 +76,22 @@ DT_FOREACH_STATUS_OKAY_VARGS(intel_ap_pwrseq_adc, GEN_PS_ENTRY,
PWR_SIG_SRC_ADC, PWR_SIG_TAG_ADC)
};
-static power_signal_mask_t power_signals;
-static power_signal_mask_t debug_signals;
+#define PWR_SIGNAL_POLLED(id) PWR_SIGNAL_ENUM(id),
-void power_update_signals(void)
-{
- power_signal_mask_t n = 0;
+/*
+ * List of power signals that need to be polled.
+ */
+static const uint8_t polled_signals[] = {
+DT_FOREACH_STATUS_OKAY(intel_ap_pwrseq_external, PWR_SIGNAL_POLLED)
+};
- for (int i = 0; i < POWER_SIGNAL_COUNT; i++) {
- if (power_signal_get(i)) {
- n |= BIT(i);
- }
- }
- /* Check if any signals flagged for debug have changed. */
- if ((n ^ power_signals) & debug_signals) {
- LOG_INF("power update (0x%04x -> 0x%04x, 0x%04x changed)",
- power_signals, n, n ^ power_signals);
- }
- power_signals = n;
-}
+/*
+ * Bitmask of power signals updated via interrupt.
+ */
+static atomic_t interrupt_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)
{
@@ -105,14 +103,32 @@ 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)
+{
+ if (debug_signals & mask) {
+ LOG_INF("%s -> %d", power_signal_name(signal), value);
+ }
+}
+
power_signal_mask_t power_get_signals(void)
{
- return power_signals;
+ power_signal_mask_t mask = 0;
+
+ for (int i = 0; i < ARRAY_SIZE(polled_signals); i++) {
+ if (power_signal_get(polled_signals[i])) {
+ mask |= POWER_SIGNAL_MASK(polled_signals[i]);
+ }
+ }
+ return mask | output_signals |
+ atomic_get(&interrupt_power_signals);
}
-void power_signal_interrupt(void)
+void power_signal_interrupt(enum power_signal signal, int value)
{
- power_update_signals();
+ atomic_set_bit_to(&interrupt_power_signals, signal, value);
+ check_debug(POWER_SIGNAL_MASK(signal), signal, value);
}
int power_wait_mask_signals_timeout(power_signal_mask_t mask,
@@ -124,12 +140,11 @@ int power_wait_mask_signals_timeout(power_signal_mask_t mask,
}
want &= mask;
while (timeout-- > 0) {
- if ((power_signals & mask) == want) {
+ if ((power_get_signals() & mask) == want) {
return 0;
}
k_msleep(1);
}
- power_update_signals();
return -ETIMEDOUT;
}
@@ -166,6 +181,7 @@ int power_signal_get(enum power_signal signal)
int power_signal_set(enum power_signal signal, int value)
{
const struct ps_config *cp = &sig_config[signal];
+ int ret;
LOG_DBG("Set %s to %d", power_signal_name(signal), value);
switch (cp->source) {
@@ -174,14 +190,32 @@ int power_signal_set(enum power_signal signal, int value)
#if HAS_GPIO_SIGNALS
case PWR_SIG_SRC_GPIO:
- return power_signal_gpio_set(cp->src_enum, value);
+ ret = power_signal_gpio_set(cp->src_enum, value);
+ break;
#endif
#if HAS_EXT_SIGNALS
case PWR_SIG_SRC_EXT:
- return board_power_signal_set(signal, value);
+ ret = board_power_signal_set(signal, value);
+ break;
#endif
}
+ /*
+ * Output succeeded, update output 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);
+ }
+ }
+ return ret;
}
int power_signal_enable_interrupt(enum power_signal signal)