From 7ba45ff0f96c3e07decb61b3334431439f01aecd Mon Sep 17 00:00:00 2001 From: Dino Li Date: Thu, 8 May 2025 14:26:07 +0800 Subject: [PATCH] espi/it8xxx2: waiting till completion of VW send to host On it8xxx2, there are VW transmitted registers indicating that VW signal has been transmitted to host. This patch checks the register to ensure successful transmission of VW state change. fixes: #89298 Signed-off-by: Dino Li --- drivers/espi/espi_it8xxx2.c | 89 +++++++++++++++++++++++-------------- 1 file changed, 55 insertions(+), 34 deletions(-) diff --git a/drivers/espi/espi_it8xxx2.c b/drivers/espi/espi_it8xxx2.c index 02bf92828eeb6..8b5cc77c64652 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; }