diff options
Diffstat (limited to 'zephyr/subsys/ap_pwrseq/signal_vw.c')
-rw-r--r-- | zephyr/subsys/ap_pwrseq/signal_vw.c | 132 |
1 files changed, 72 insertions, 60 deletions
diff --git a/zephyr/subsys/ap_pwrseq/signal_vw.c b/zephyr/subsys/ap_pwrseq/signal_vw.c index de2756c137..0e9e4affff 100644 --- a/zephyr/subsys/ap_pwrseq/signal_vw.c +++ b/zephyr/subsys/ap_pwrseq/signal_vw.c @@ -1,4 +1,4 @@ -/* Copyright 2022 The Chromium OS Authors. All rights reserved. +/* Copyright 2022 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -9,40 +9,47 @@ #include "signal_vw.h" -#define MY_COMPAT intel_ap_pwrseq_vw +#define MY_COMPAT intel_ap_pwrseq_vw #if HAS_VW_SIGNALS +/* + * A callback must be registered on the ESPI device (for the + * bus events that are required to be handled) that calls + * power_signal_espi_cb(). + * + * This registration is done in a common ESPI initialisation module so + * that there is no possibility of missing events. + */ + LOG_MODULE_DECLARE(ap_pwrseq, CONFIG_AP_PWRSEQ_LOG_LEVEL); -#define INIT_ESPI_SIGNAL(id) \ -{ \ - .espi_signal = DT_STRING_UPPER_TOKEN(id, virtual_wire), \ - .signal = PWR_SIGNAL_ENUM(id), \ - .invert = DT_PROP(id, vw_invert), \ -}, +#define INIT_ESPI_SIGNAL(id) \ + { \ + .espi_signal = DT_STRING_UPPER_TOKEN(id, virtual_wire), \ + .signal = PWR_SIGNAL_ENUM(id), \ + .invert = DT_PROP(id, vw_invert), \ + }, /* * Struct containing the eSPI virtual wire config. */ struct vw_config { - uint8_t espi_signal; /* associated VW signal */ - uint8_t signal; /* power signal */ - bool invert; /* Invert the signal value */ + uint8_t espi_signal; /* associated VW signal */ + uint8_t signal; /* power signal */ + bool invert; /* Invert the signal value */ }; -const static struct vw_config vw_config[] = { -DT_FOREACH_STATUS_OKAY(MY_COMPAT, INIT_ESPI_SIGNAL) -}; +const static struct vw_config vw_config[] = { DT_FOREACH_STATUS_OKAY( + MY_COMPAT, INIT_ESPI_SIGNAL) }; /* * 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. + * Mask of valid signals. A signal is considered valid once an + * initial value has been received for it. */ static atomic_t signal_valid; @@ -50,36 +57,63 @@ static atomic_t signal_valid; BUILD_ASSERT(ARRAY_SIZE(vw_config) <= (sizeof(atomic_t) * 8)); -static void espi_handler(const struct device *dev, - struct espi_callback *cb, - struct espi_event event) +/* + * Set the value of the VW signal, and optionally + * call the power signal interrupt handling. + */ +static void vw_set(int index, int data, bool notify) +{ + bool value = vw_config[index].invert ? !data : !!data; + + atomic_set_bit_to(&signal_data, index, value); + atomic_set_bit(&signal_valid, index); + if (notify) { + power_signal_interrupt(vw_config[index].signal, value); + } +} + +/* + * Update all the VW signals. + */ +static void vw_update_all(bool notify) +{ + 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) { + vw_set(i, vw_value, notify); + } + } +} + +void power_signal_espi_cb(const struct device *dev, struct espi_callback *cb, + struct espi_event event) { - LOG_DBG("ESPI event type 0x%x %d:%d", event.evt_type, - event.evt_details, event.evt_data); + LOG_DBG("ESPI event type 0x%x %d:%d", event.evt_type, event.evt_details, + event.evt_data); switch (event.evt_type) { default: - __ASSERT(0, "ESPI unknown event type: %d", - event.evt_type); + __ASSERT(0, "ESPI unknown event type: %d", event.evt_type); break; - case ESPI_BUS_RESET: - /* - * Clear the signal valid mask. - */ - atomic_clear(&signal_valid); + case ESPI_BUS_EVENT_CHANNEL_READY: + /* Virtual wire channel status change */ + if (event.evt_details == ESPI_CHANNEL_VWIRE) { + if (event.evt_data) { + /* If now ready, update all the signals */ + vw_update_all(true); + } else { + /* If not ready, invalidate the signals */ + 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) { - bool value = vw_config[i].invert - ? !event.evt_data - : !!event.evt_data; - - atomic_set_bit_to(&signal_data, i, value); - atomic_set_bit(&signal_valid, i); - power_signal_interrupt(vw_config[i].signal, - value); + vw_set(i, event.evt_data, true); } } break; @@ -97,34 +131,12 @@ int power_signal_vw_get(enum pwr_sig_vw vw) void power_signal_vw_init(void) { - static struct espi_callback espi_cb; - - /* Assumes ESPI device is already configured. */ - - /* Configure handler for eSPI events */ - espi_init_callback(&espi_cb, espi_handler, - 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); - atomic_set_bit(&signal_valid, i); - - } - } + vw_update_all(false); } } |