From 121927e37be0725139d5b07d08361ac266685808 Mon Sep 17 00:00:00 2001 From: Jim Liu Date: Thu, 7 Aug 2025 13:32:22 +0800 Subject: misc: npcm_host_intf: Add Arbel eSPI workaround Enabling an eSPI channel(e.g. Peripheral Channel) during an eSPI transaction might cause the BMC eSPI module to transition to a wrong state and therefore respond with FATAL_ERROR on incoming transaction. Add workaround to avoid the module getting into the wrong state. Signed-off-by: Stanley Chu Signed-off-by: Jim Liu --- drivers/misc/npcm_host_intf.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers/misc') diff --git a/drivers/misc/npcm_host_intf.c b/drivers/misc/npcm_host_intf.c index 58bab888c3c..2c89bd7a167 100644 --- a/drivers/misc/npcm_host_intf.c +++ b/drivers/misc/npcm_host_intf.c @@ -22,6 +22,8 @@ /* ESPI Register offsets */ #define ESPICFG 0x4 #define ESPIHINDP 0x80 +#define ESPI_TEN 0xF0 +#define ESPI_ENG 0xF1 /* MFSEL bit fileds */ #define MFSEL1_LPCSEL BIT(26) @@ -40,6 +42,9 @@ #define AUTO_HS2 BIT(12) #define AUTO_HS3 BIT(16) +#define ESPI_TEN_ENABLE 0x55 +#define ESPI_TEN_DISABLE 0 + static int npcm_host_intf_bind(struct udevice *dev) { struct regmap *syscon; @@ -83,6 +88,13 @@ static int npcm_host_intf_bind(struct udevice *dev) val &= ~(CHSUPP_MASK | IOMODE_MASK | MAXFREQ_MASK); val |= IOMODE_SDQ | MAXFREQ_33MHZ | FIELD_PREP(CHSUPP_MASK, ch_supp); writel(val, base + ESPICFG); + + if (device_is_compatible(dev, "nuvoton,npcm845-host-intf")) { + /* Workaround: avoid eSPI module getting into wrong state */ + writeb(ESPI_TEN_ENABLE, base + ESPI_TEN); + writeb(BIT(6), base + ESPI_ENG); + writeb(ESPI_TEN_DISABLE, base + ESPI_TEN); + } } else if (!strcmp(type, "lpc")) { /* Select LPC pin function */ regmap_update_bits(syscon, MFSEL4, MFSEL4_ESPISEL, 0); -- cgit v1.2.3 From 987880581646d5836d2485e5f7a5af6ce8600da1 Mon Sep 17 00:00:00 2001 From: Jim Liu Date: Thu, 7 Aug 2025 13:32:23 +0800 Subject: misc: npcm_host_intf: Disable pending KCS/BPC interrupts If there is an unhandled KCS/BPC pending interrupt after reboot, the KCS/BPC Linux driver may trigger interrupts immediately upon registering the irq. However, since the driver is not yet initialized to handle them, this can lead to unexpected behavior. To prevent this, disable KCS/BPC interrupts in u-boot to avoid pending interrupts from being raised before the Linux driver is fully initialized. Signed-off-by: Stanley Chu Signed-off-by: Jim Liu --- drivers/misc/npcm_host_intf.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) (limited to 'drivers/misc') diff --git a/drivers/misc/npcm_host_intf.c b/drivers/misc/npcm_host_intf.c index 2c89bd7a167..e3b0663625b 100644 --- a/drivers/misc/npcm_host_intf.c +++ b/drivers/misc/npcm_host_intf.c @@ -45,10 +45,20 @@ #define ESPI_TEN_ENABLE 0x55 #define ESPI_TEN_DISABLE 0 +/* KCS/BPC interrupt control */ +#define BPCFEN 0x46 +#define FRIE BIT(3) +#define HRIE BIT(4) +#define KCS1CTL 0x18 +#define KCS2CTL 0x2a +#define KCS3CTL 0x3c +#define IBFIE BIT(0) +#define OBEIE BIT(1) + static int npcm_host_intf_bind(struct udevice *dev) { struct regmap *syscon; - void __iomem *base; + void __iomem *base, *kcs_base; u32 ch_supp, val; u32 ioaddr; const char *type; @@ -104,6 +114,15 @@ static int npcm_host_intf_bind(struct udevice *dev) /* Release host wait */ setbits_8(SMC_CTL_REG_ADDR, SMC_CTL_HOSTWAIT); + kcs_base = dev_read_addr_index_ptr(dev, 1); + if (kcs_base) { + /* Disable KCS/BPC interrupts */ + clrbits_8(kcs_base + BPCFEN, FRIE | HRIE); + clrbits_8(kcs_base + KCS1CTL, IBFIE | OBEIE); + clrbits_8(kcs_base + KCS2CTL, IBFIE | OBEIE); + clrbits_8(kcs_base + KCS3CTL, IBFIE | OBEIE); + } + return 0; } -- cgit v1.2.3