From aec991ef1ababdf4f6544e5f0820f0aeea293db9 Mon Sep 17 00:00:00 2001 From: Jun Lin Date: Fri, 17 Jan 2025 17:19:07 +0800 Subject: [PATCH] driver: espi: npcx: add option to reset SLP_Sx virtual wire Add a Kconfig option ESPI_NPCX_RESET_SLP_SX_VW_ON_ESPI_RST. When the option is enabled, the hardware resets the SLP_S3/SLP_S4/SLP_S5 virtual wires when the eSPI_Reset is asserted. This is required to synchronize these virtual wires on the ungraceful global reset. Signed-off-by: Jun Lin --- drivers/espi/Kconfig.npcx | 8 ++++++++ drivers/espi/espi_npcx.c | 11 +++++++++++ soc/nuvoton/npcx/common/reg/reg_def.h | 1 + 3 files changed, 20 insertions(+) diff --git a/drivers/espi/Kconfig.npcx b/drivers/espi/Kconfig.npcx index dbeadaddfa2..14c74fbd88e 100644 --- a/drivers/espi/Kconfig.npcx +++ b/drivers/espi/Kconfig.npcx @@ -134,4 +134,12 @@ config ESPI_NPCX_CAF_GLOBAL_RESET_WORKAROUND help Workaround the issue "Global Reset" in the npcx4 SoC errata. +config ESPI_NPCX_RESET_SLP_SX_VW_ON_ESPI_RST + bool "Reset SLP_Sx virtual wires when eSPI_RST is asserted" + help + The SLP_S3/SLP_S4/SLP_S5/ virtual wires are automatically reset when + eSPI_Reset is asserted on the global reset. + Don't enable this config if the platform implements the Deep-Sx + entry as EC needs to maintain these pins' states per request. + endif #ESPI_NPCX diff --git a/drivers/espi/espi_npcx.c b/drivers/espi/espi_npcx.c index 4a7f40b64c0..c741ada5650 100644 --- a/drivers/espi/espi_npcx.c +++ b/drivers/espi/espi_npcx.c @@ -91,6 +91,9 @@ static const struct espi_npcx_vw_ex espi_npcx_vw_ex_0[] = { #define NPCX_ESPI_MAXFREQ_50 3 #define NPCX_ESPI_MAXFREQ_66 4 +/* SLP_S3/SLP_S4/SLP_S5 Virtual Wire belong to Virtual Wire Index 2 */ +#define ESPI_VW_SLP_SX_INDEX 0x02 + /* Minimum delay before acknowledging a virtual wire */ #define NPCX_ESPI_VWIRE_ACK_DELAY 10ul /* 10 us */ @@ -498,6 +501,14 @@ static void espi_vw_config_input(const struct device *dev, struct espi_reg *const inst = HAL_INSTANCE(dev); int idx = config_in->reg_idx; + if (IS_ENABLED(CONFIG_ESPI_NPCX_RESET_SLP_SX_VW_ON_ESPI_RST)) { + uint8_t vwire_index = GET_FIELD(inst->VWEVMS[idx], NPCX_VWEVMS_INDEX); + + if (vwire_index == ESPI_VW_SLP_SX_INDEX) { + inst->VWEVMS[idx] |= BIT(NPCX_VWEVMS_ENESPIRST); + } + } + /* IE & WE bits are already set? */ if (IS_BIT_SET(inst->VWEVMS[idx], NPCX_VWEVMS_IE) && IS_BIT_SET(inst->VWEVMS[idx], NPCX_VWEVMS_WE)) { diff --git a/soc/nuvoton/npcx/common/reg/reg_def.h b/soc/nuvoton/npcx/common/reg/reg_def.h index b35089f65b6..012470ffb4f 100644 --- a/soc/nuvoton/npcx/common/reg/reg_def.h +++ b/soc/nuvoton/npcx/common/reg/reg_def.h @@ -775,6 +775,7 @@ struct espi_reg { #define NPCX_VWEVMS_INDEX FIELD(8, 7) #define NPCX_VWEVMS_INDEX_EN 15 #define NPCX_VWEVMS_IE 18 +#define NPCX_VWEVMS_ENESPIRST 19 #define NPCX_VWEVMS_WE 20 #define NPCX_VWEVSM_WIRE FIELD(0, 4) #define NPCX_VWEVSM_VALID FIELD(4, 4)