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 <CHLin56@nuvoton.com>
This commit is contained in:
Jun Lin 2022-04-27 16:42:37 +08:00 committed by Carles Cufí
commit 51978d9d61
4 changed files with 37 additions and 7 deletions

View file

@ -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 Please notice the valid value in npcx ec series for this option is
8/16/32/64/128/256/512/1024/2048/4096 bytes. 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. # The default value 'y' for the existing options if ESPI_NPCX is selected.
if ESPI_NPCX if ESPI_NPCX

View file

@ -865,6 +865,14 @@ static int espi_npcx_init(const struct device *dev)
return ret; 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 */ /* Enable events which share the same espi bus interrupt */
for (i = 0; i < ARRAY_SIZE(espi_bus_isr_tbl); i++) { for (i = 0; i < ARRAY_SIZE(espi_bus_isr_tbl); i++) {
inst->ESPIIE |= BIT(espi_bus_isr_tbl[i].int_en_bit); inst->ESPIIE |= BIT(espi_bus_isr_tbl[i].int_en_bit);

View file

@ -636,29 +636,36 @@ struct espi_reg {
volatile uint32_t PERCFG; volatile uint32_t PERCFG;
/* 0x04C: Peripheral Channel Control */ /* 0x04C: Peripheral Channel Control */
volatile uint32_t PERCTL; 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 */ /* 0x100 - 127: Virtual Wire Event Slave-to-Master 0 - 9 */
volatile uint32_t VWEVSM[10]; 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 */ /* 0x140 - 16F: Virtual Wire Event Master-to-Slave 0 - 11 */
volatile uint32_t VWEVMS[12]; volatile uint32_t VWEVMS[12];
volatile uint32_t reserved4[99]; volatile uint32_t reserved5[99];
/* 0x2FC: Virtual Wire Channel Control */ /* 0x2FC: Virtual Wire Channel Control */
volatile uint32_t VWCTL; volatile uint32_t VWCTL;
/* 0x300 - 34F: OOB Receive Buffer 0 - 19 */ /* 0x300 - 34F: OOB Receive Buffer 0 - 19 */
volatile uint32_t OOBRXBUF[20]; volatile uint32_t OOBRXBUF[20];
volatile uint32_t reserved5[12]; volatile uint32_t reserved6[12];
/* 0x380 - 3CF: OOB Transmit Buffer 0-19 */ /* 0x380 - 3CF: OOB Transmit Buffer 0-19 */
volatile uint32_t OOBTXBUF[20]; volatile uint32_t OOBTXBUF[20];
volatile uint32_t reserved6[11]; volatile uint32_t reserved7[11];
/* 0x3FC: OOB Channel Control used in 'direct' mode */ /* 0x3FC: OOB Channel Control used in 'direct' mode */
volatile uint32_t OOBCTL_DIRECT; volatile uint32_t OOBCTL_DIRECT;
/* 0x400 - 443: Flash Receive Buffer 0-16 */ /* 0x400 - 443: Flash Receive Buffer 0-16 */
volatile uint32_t FLASHRXBUF[17]; volatile uint32_t FLASHRXBUF[17];
volatile uint32_t reserved7[15]; volatile uint32_t reserved8[15];
/* 0x480 - 497: Flash Transmit Buffer 0-5 */ /* 0x480 - 497: Flash Transmit Buffer 0-5 */
volatile uint32_t FLASHTXBUF[6]; volatile uint32_t FLASHTXBUF[6];
volatile uint32_t reserved8[25]; volatile uint32_t reserved9[25];
/* 0x4FC: Flash Channel Control used in 'direct' mode */ /* 0x4FC: Flash Channel Control used in 'direct' mode */
volatile uint32_t FLASHCTL_DIRECT; volatile uint32_t FLASHCTL_DIRECT;
}; };
@ -753,6 +760,9 @@ struct espi_reg {
#define NPCX_FLASHCTL_CHKSUMSEL 15 #define NPCX_FLASHCTL_CHKSUMSEL 15
#define NPCX_FLASHCTL_AMTEN 16 #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 * Mobile System Wake-Up Control (MSWC) device registers
*/ */

View file

@ -64,6 +64,7 @@ NPCX_REG_OFFSET_CHECK(twd_reg, WDCP, 0x010);
/* ESPI register structure check */ /* ESPI register structure check */
NPCX_REG_SIZE_CHECK(espi_reg, 0x500); NPCX_REG_SIZE_CHECK(espi_reg, 0x500);
NPCX_REG_OFFSET_CHECK(espi_reg, FLASHCFG, 0x034); 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, VWEVMS, 0x140);
NPCX_REG_OFFSET_CHECK(espi_reg, VWCTL, 0x2fc); NPCX_REG_OFFSET_CHECK(espi_reg, VWCTL, 0x2fc);
NPCX_REG_OFFSET_CHECK(espi_reg, OOBTXBUF, 0x380); NPCX_REG_OFFSET_CHECK(espi_reg, OOBTXBUF, 0x380);