diff --git a/drivers/espi/espi_it8xxx2.c b/drivers/espi/espi_it8xxx2.c index 02bf92828ee..8b5cc77c646 100644 --- a/drivers/espi/espi_it8xxx2.c +++ b/drivers/espi/espi_it8xxx2.c @@ -648,6 +648,12 @@ IT8XXX2_ESPI_REG_SIZE_CHECK(espi_queue1_regs, 0xc0); IT8XXX2_ESPI_REG_OFFSET_CHECK(espi_queue1_regs, UPSTREAM_DATA, 0x00); IT8XXX2_ESPI_REG_OFFSET_CHECK(espi_queue1_regs, PUT_FLASH_NP_DATA, 0x80); +/* Register used to record VWx data transmitted to the eSPI host. */ +#define IT8XXX2_ESPI_VW_REC_VW4 0xe1 +#define IT8XXX2_ESPI_VW_REC_VW5 0xe2 +#define IT8XXX2_ESPI_VW_REC_VW6 0xe3 +#define IT8XXX2_ESPI_VW_REC_VW40 0xe4 + struct espi_it8xxx2_wuc { /* WUC control device structure */ const struct device *wucs; @@ -682,9 +688,10 @@ struct espi_it8xxx2_data { }; struct vw_channel_t { - uint8_t vw_index; /* VW index of signal */ - uint8_t level_mask; /* level bit of signal */ - uint8_t valid_mask; /* valid bit of signal */ + uint8_t vw_index; /* VW index of signal */ + uint8_t level_mask; /* level bit of signal */ + uint8_t valid_mask; /* valid bit of signal */ + uint8_t vw_sent_reg; /* vw signal sent to host */ }; struct vwidx_isr_t { @@ -1171,41 +1178,44 @@ static void pmc2_it8xxx2_init(const struct device *dev) } #endif +#define IT8XXX2_ESPI_VW_SEND_TIMEOUT_US (USEC_PER_MSEC * 10) + /* eSPI api functions */ -#define VW_CHAN(signal, index, level, valid) \ - [signal] = {.vw_index = index, .level_mask = level, .valid_mask = valid} +#define VW_CHAN(signal, index, level, valid, reg) \ + [signal] = {.vw_index = index, .level_mask = level, \ + .valid_mask = valid, .vw_sent_reg = reg} /* VW signals used in eSPI */ static const struct vw_channel_t vw_channel_list[] = { - VW_CHAN(ESPI_VWIRE_SIGNAL_SLP_S3, 0x02, BIT(0), BIT(4)), - VW_CHAN(ESPI_VWIRE_SIGNAL_SLP_S4, 0x02, BIT(1), BIT(5)), - VW_CHAN(ESPI_VWIRE_SIGNAL_SLP_S5, 0x02, BIT(2), BIT(6)), - VW_CHAN(ESPI_VWIRE_SIGNAL_OOB_RST_WARN, 0x03, BIT(2), BIT(6)), - VW_CHAN(ESPI_VWIRE_SIGNAL_PLTRST, 0x03, BIT(1), BIT(5)), - VW_CHAN(ESPI_VWIRE_SIGNAL_SUS_STAT, 0x03, BIT(0), BIT(4)), - VW_CHAN(ESPI_VWIRE_SIGNAL_NMIOUT, 0x07, BIT(2), BIT(6)), - VW_CHAN(ESPI_VWIRE_SIGNAL_SMIOUT, 0x07, BIT(1), BIT(5)), - VW_CHAN(ESPI_VWIRE_SIGNAL_HOST_RST_WARN, 0x07, BIT(0), BIT(4)), - VW_CHAN(ESPI_VWIRE_SIGNAL_SLP_A, 0x41, BIT(3), BIT(7)), - VW_CHAN(ESPI_VWIRE_SIGNAL_SUS_PWRDN_ACK, 0x41, BIT(1), BIT(5)), - VW_CHAN(ESPI_VWIRE_SIGNAL_SUS_WARN, 0x41, BIT(0), BIT(4)), - VW_CHAN(ESPI_VWIRE_SIGNAL_SLP_WLAN, 0x42, BIT(1), BIT(5)), - VW_CHAN(ESPI_VWIRE_SIGNAL_SLP_LAN, 0x42, BIT(0), BIT(4)), - VW_CHAN(ESPI_VWIRE_SIGNAL_HOST_C10, 0x47, BIT(0), BIT(4)), - VW_CHAN(ESPI_VWIRE_SIGNAL_DNX_WARN, 0x4a, BIT(1), BIT(5)), - VW_CHAN(ESPI_VWIRE_SIGNAL_PME, 0x04, BIT(3), BIT(7)), - VW_CHAN(ESPI_VWIRE_SIGNAL_WAKE, 0x04, BIT(2), BIT(6)), - VW_CHAN(ESPI_VWIRE_SIGNAL_OOB_RST_ACK, 0x04, BIT(0), BIT(4)), - VW_CHAN(ESPI_VWIRE_SIGNAL_TARGET_BOOT_STS, 0x05, BIT(3), BIT(7)), - VW_CHAN(ESPI_VWIRE_SIGNAL_ERR_NON_FATAL, 0x05, BIT(2), BIT(6)), - VW_CHAN(ESPI_VWIRE_SIGNAL_ERR_FATAL, 0x05, BIT(1), BIT(5)), - VW_CHAN(ESPI_VWIRE_SIGNAL_TARGET_BOOT_DONE, 0x05, BIT(0), BIT(4)), - VW_CHAN(ESPI_VWIRE_SIGNAL_HOST_RST_ACK, 0x06, BIT(3), BIT(7)), - VW_CHAN(ESPI_VWIRE_SIGNAL_RST_CPU_INIT, 0x06, BIT(2), BIT(6)), - VW_CHAN(ESPI_VWIRE_SIGNAL_SMI, 0x06, BIT(1), BIT(5)), - VW_CHAN(ESPI_VWIRE_SIGNAL_SCI, 0x06, BIT(0), BIT(4)), - VW_CHAN(ESPI_VWIRE_SIGNAL_DNX_ACK, 0x40, BIT(1), BIT(5)), - VW_CHAN(ESPI_VWIRE_SIGNAL_SUS_ACK, 0x40, BIT(0), BIT(4)), + VW_CHAN(ESPI_VWIRE_SIGNAL_SLP_S3, 0x02, BIT(0), BIT(4), 0), + VW_CHAN(ESPI_VWIRE_SIGNAL_SLP_S4, 0x02, BIT(1), BIT(5), 0), + VW_CHAN(ESPI_VWIRE_SIGNAL_SLP_S5, 0x02, BIT(2), BIT(6), 0), + VW_CHAN(ESPI_VWIRE_SIGNAL_OOB_RST_WARN, 0x03, BIT(2), BIT(6), 0), + VW_CHAN(ESPI_VWIRE_SIGNAL_PLTRST, 0x03, BIT(1), BIT(5), 0), + VW_CHAN(ESPI_VWIRE_SIGNAL_SUS_STAT, 0x03, BIT(0), BIT(4), 0), + VW_CHAN(ESPI_VWIRE_SIGNAL_NMIOUT, 0x07, BIT(2), BIT(6), 0), + VW_CHAN(ESPI_VWIRE_SIGNAL_SMIOUT, 0x07, BIT(1), BIT(5), 0), + VW_CHAN(ESPI_VWIRE_SIGNAL_HOST_RST_WARN, 0x07, BIT(0), BIT(4), 0), + VW_CHAN(ESPI_VWIRE_SIGNAL_SLP_A, 0x41, BIT(3), BIT(7), 0), + VW_CHAN(ESPI_VWIRE_SIGNAL_SUS_PWRDN_ACK, 0x41, BIT(1), BIT(5), 0), + VW_CHAN(ESPI_VWIRE_SIGNAL_SUS_WARN, 0x41, BIT(0), BIT(4), 0), + VW_CHAN(ESPI_VWIRE_SIGNAL_SLP_WLAN, 0x42, BIT(1), BIT(5), 0), + VW_CHAN(ESPI_VWIRE_SIGNAL_SLP_LAN, 0x42, BIT(0), BIT(4), 0), + VW_CHAN(ESPI_VWIRE_SIGNAL_HOST_C10, 0x47, BIT(0), BIT(4), 0), + VW_CHAN(ESPI_VWIRE_SIGNAL_DNX_WARN, 0x4a, BIT(1), BIT(5), 0), + VW_CHAN(ESPI_VWIRE_SIGNAL_PME, 0x04, BIT(3), BIT(7), IT8XXX2_ESPI_VW_REC_VW4), + VW_CHAN(ESPI_VWIRE_SIGNAL_WAKE, 0x04, BIT(2), BIT(6), IT8XXX2_ESPI_VW_REC_VW4), + VW_CHAN(ESPI_VWIRE_SIGNAL_OOB_RST_ACK, 0x04, BIT(0), BIT(4), IT8XXX2_ESPI_VW_REC_VW4), + VW_CHAN(ESPI_VWIRE_SIGNAL_TARGET_BOOT_STS, 0x05, BIT(3), BIT(7), IT8XXX2_ESPI_VW_REC_VW5), + VW_CHAN(ESPI_VWIRE_SIGNAL_ERR_NON_FATAL, 0x05, BIT(2), BIT(6), IT8XXX2_ESPI_VW_REC_VW5), + VW_CHAN(ESPI_VWIRE_SIGNAL_ERR_FATAL, 0x05, BIT(1), BIT(5), IT8XXX2_ESPI_VW_REC_VW5), + VW_CHAN(ESPI_VWIRE_SIGNAL_TARGET_BOOT_DONE, 0x05, BIT(0), BIT(4), IT8XXX2_ESPI_VW_REC_VW5), + VW_CHAN(ESPI_VWIRE_SIGNAL_HOST_RST_ACK, 0x06, BIT(3), BIT(7), IT8XXX2_ESPI_VW_REC_VW6), + VW_CHAN(ESPI_VWIRE_SIGNAL_RST_CPU_INIT, 0x06, BIT(2), BIT(6), IT8XXX2_ESPI_VW_REC_VW6), + VW_CHAN(ESPI_VWIRE_SIGNAL_SMI, 0x06, BIT(1), BIT(5), IT8XXX2_ESPI_VW_REC_VW6), + VW_CHAN(ESPI_VWIRE_SIGNAL_SCI, 0x06, BIT(0), BIT(4), IT8XXX2_ESPI_VW_REC_VW6), + VW_CHAN(ESPI_VWIRE_SIGNAL_DNX_ACK, 0x40, BIT(1), BIT(5), IT8XXX2_ESPI_VW_REC_VW40), + VW_CHAN(ESPI_VWIRE_SIGNAL_SUS_ACK, 0x40, BIT(0), BIT(4), IT8XXX2_ESPI_VW_REC_VW40), }; static int espi_it8xxx2_configure(const struct device *dev, @@ -1288,6 +1298,7 @@ static int espi_it8xxx2_send_vwire(const struct device *dev, uint8_t vw_index = vw_channel_list[signal].vw_index; uint8_t level_mask = vw_channel_list[signal].level_mask; uint8_t valid_mask = vw_channel_list[signal].valid_mask; + uint8_t vw_sent = vw_channel_list[signal].vw_sent_reg; if (signal > ARRAY_SIZE(vw_channel_list)) { return -EIO; @@ -1301,6 +1312,16 @@ static int espi_it8xxx2_send_vwire(const struct device *dev, vw_reg->VW_INDEX[vw_index] |= valid_mask; + if (espi_it8xxx2_channel_ready(dev, ESPI_CHANNEL_VWIRE) && vw_sent) { + if (!WAIT_FOR(vw_reg->VW_INDEX[vw_index] == + sys_read8(config->base_espi_vw + vw_sent), + IT8XXX2_ESPI_VW_SEND_TIMEOUT_US, k_busy_wait(10))) { + LOG_WRN("VW send to host has timed out vw[0x%x] = 0x%x", + vw_index, vw_reg->VW_INDEX[vw_index]); + return -ETIMEDOUT; + } + } + return 0; }