From 51978d9d611da67f940a339abd41d4dba5074d91 Mon Sep 17 00:00:00 2001 From: Jun Lin Date: Wed, 27 Apr 2022 16:42:37 +0800 Subject: [PATCH] driver: eSPI: npcx: workaround the errata rev1_2, No.3.10 Enabling an eSPI channel (r.g. Peripheral Channel, Virtual Wire Channel, etc.) during an eSPI transaction might (with low probability) cause the eSPI_SIF module to transition to a wrong state and therefore response with FATAL_ERROR on an incoming transaction. This CL workarounds this issue by clearing the bit 4 of NPCX eSPI specific register#2. Signed-off-by: Jun Lin --- drivers/espi/Kconfig.npcx | 11 +++++++++++ drivers/espi/espi_npcx.c | 8 ++++++++ soc/arm/nuvoton_npcx/common/reg/reg_def.h | 24 ++++++++++++++++------- soc/arm/nuvoton_npcx/common/registers.c | 1 + 4 files changed, 37 insertions(+), 7 deletions(-) diff --git a/drivers/espi/Kconfig.npcx b/drivers/espi/Kconfig.npcx index 20b345a8321..f19d7ee46bb 100644 --- a/drivers/espi/Kconfig.npcx +++ b/drivers/espi/Kconfig.npcx @@ -30,6 +30,17 @@ config ESPI_NPCX_PERIPHERAL_HOST_CMD_PARAM_SIZE Please notice the valid value in npcx ec series for this option is 8/16/32/64/128/256/512/1024/2048/4096 bytes. +config ESPI_NPCX_BYPASS_CH_ENABLE_FATAL_ERROR + bool + depends on SOC_SERIES_NPCX7 || SOC_SERIES_NPCX9 + default y + help + Workaround the issue documented in NPCX99nF errata rev1_2, No.3.10. + Enabling an eSPI channel during an eSPI transaction might + (with low probability) cause the eSPI_SIF module to transition to + a wrong state and therefore response with FATAL_ERROR on an incoming + transaction. + # The default value 'y' for the existing options if ESPI_NPCX is selected. if ESPI_NPCX diff --git a/drivers/espi/espi_npcx.c b/drivers/espi/espi_npcx.c index 339646df63e..2e12ab75342 100644 --- a/drivers/espi/espi_npcx.c +++ b/drivers/espi/espi_npcx.c @@ -865,6 +865,14 @@ static int espi_npcx_init(const struct device *dev) return ret; } + if (IS_ENABLED(CONFIG_ESPI_NPCX_BYPASS_CH_ENABLE_FATAL_ERROR)) { + /* Enable the access to the NPCX_ONLY_ESPI_REG2 register */ + inst->NPCX_ONLY_ESPI_REG1 = NPCX_ONLY_ESPI_REG1_UNLOCK_REG2; + inst->NPCX_ONLY_ESPI_REG2 &= ~BIT(NPCX_ONLY_ESPI_REG2_TRANS_END_CONFIG); + /* Disable the access to the NPCX_ONLY_ESPI_REG2 register */ + inst->NPCX_ONLY_ESPI_REG1 = NPCX_ONLY_ESPI_REG1_LOCK_REG2; + } + /* Enable events which share the same espi bus interrupt */ for (i = 0; i < ARRAY_SIZE(espi_bus_isr_tbl); i++) { inst->ESPIIE |= BIT(espi_bus_isr_tbl[i].int_en_bit); diff --git a/soc/arm/nuvoton_npcx/common/reg/reg_def.h b/soc/arm/nuvoton_npcx/common/reg/reg_def.h index d25ad434325..3e25be06abd 100644 --- a/soc/arm/nuvoton_npcx/common/reg/reg_def.h +++ b/soc/arm/nuvoton_npcx/common/reg/reg_def.h @@ -636,29 +636,36 @@ struct espi_reg { volatile uint32_t PERCFG; /* 0x04C: Peripheral Channel Control */ volatile uint32_t PERCTL; - volatile uint32_t reserved2[44]; + /* 0x050: Status Image Register */ + volatile uint16_t STATUS_IMG; + volatile uint16_t reserved2[79]; + /* 0x0F0: NPCX specific eSPI Register1 */ + volatile uint8_t NPCX_ONLY_ESPI_REG1; + /* 0x0F1: NPCX specific eSPI Register2 */ + volatile uint8_t NPCX_ONLY_ESPI_REG2; + volatile uint16_t reserved3[7]; /* 0x100 - 127: Virtual Wire Event Slave-to-Master 0 - 9 */ volatile uint32_t VWEVSM[10]; - volatile uint32_t reserved3[6]; + volatile uint32_t reserved4[6]; /* 0x140 - 16F: Virtual Wire Event Master-to-Slave 0 - 11 */ volatile uint32_t VWEVMS[12]; - volatile uint32_t reserved4[99]; + volatile uint32_t reserved5[99]; /* 0x2FC: Virtual Wire Channel Control */ volatile uint32_t VWCTL; /* 0x300 - 34F: OOB Receive Buffer 0 - 19 */ volatile uint32_t OOBRXBUF[20]; - volatile uint32_t reserved5[12]; + volatile uint32_t reserved6[12]; /* 0x380 - 3CF: OOB Transmit Buffer 0-19 */ volatile uint32_t OOBTXBUF[20]; - volatile uint32_t reserved6[11]; + volatile uint32_t reserved7[11]; /* 0x3FC: OOB Channel Control used in 'direct' mode */ volatile uint32_t OOBCTL_DIRECT; /* 0x400 - 443: Flash Receive Buffer 0-16 */ volatile uint32_t FLASHRXBUF[17]; - volatile uint32_t reserved7[15]; + volatile uint32_t reserved8[15]; /* 0x480 - 497: Flash Transmit Buffer 0-5 */ volatile uint32_t FLASHTXBUF[6]; - volatile uint32_t reserved8[25]; + volatile uint32_t reserved9[25]; /* 0x4FC: Flash Channel Control used in 'direct' mode */ volatile uint32_t FLASHCTL_DIRECT; }; @@ -753,6 +760,9 @@ struct espi_reg { #define NPCX_FLASHCTL_CHKSUMSEL 15 #define NPCX_FLASHCTL_AMTEN 16 +#define NPCX_ONLY_ESPI_REG1_UNLOCK_REG2 0x55 +#define NPCX_ONLY_ESPI_REG1_LOCK_REG2 0 +#define NPCX_ONLY_ESPI_REG2_TRANS_END_CONFIG 4 /* * Mobile System Wake-Up Control (MSWC) device registers */ diff --git a/soc/arm/nuvoton_npcx/common/registers.c b/soc/arm/nuvoton_npcx/common/registers.c index 9da3a4ac421..c6633298d52 100644 --- a/soc/arm/nuvoton_npcx/common/registers.c +++ b/soc/arm/nuvoton_npcx/common/registers.c @@ -64,6 +64,7 @@ NPCX_REG_OFFSET_CHECK(twd_reg, WDCP, 0x010); /* ESPI register structure check */ NPCX_REG_SIZE_CHECK(espi_reg, 0x500); NPCX_REG_OFFSET_CHECK(espi_reg, FLASHCFG, 0x034); +NPCX_REG_OFFSET_CHECK(espi_reg, NPCX_ONLY_ESPI_REG1, 0x0f0); NPCX_REG_OFFSET_CHECK(espi_reg, VWEVMS, 0x140); NPCX_REG_OFFSET_CHECK(espi_reg, VWCTL, 0x2fc); NPCX_REG_OFFSET_CHECK(espi_reg, OOBTXBUF, 0x380);