From 2bec5a9d9a6fdadd72d28d68e25d14cf91b0e49c Mon Sep 17 00:00:00 2001 From: Zexin Wang Date: Tue, 17 Dec 2024 19:32:58 +0800 Subject: [PATCH] soc/mediatek/mt8189: Check eFuse ECC in WDT init When the number of eFuse reads exceeds a certain limit (with a maximum of 20 million), a bit flip from 1 to 0 may happen. When that happens, the bit flip will be automatically corrected by the eFuse hardware via ECC (Error Correction Code), and the EFUSE_ECC_ERR register bit will be set for the software to decide how to handle that. Therefore, this patch adds a check for the EFUSE_ECC_ERR register bit. If it's set due to a bit flip instead of a real error, we simply clear it to avoid triggering a WDT reset. BUG=b:379008996 BRANCH=none TEST=build passed and check the WDT status debug log. This log is added in local for test only. [INFO ] mtk_wdt_clear_efuse_ecc: wdt_sta = 0x0 Signed-off-by: Zexin Wang Change-Id: Idd2763688c7ab6992a7c185e9e52b60bda88c94c Reviewed-on: https://review.coreboot.org/c/coreboot/+/87744 Reviewed-by: Yu-Ping Wu Tested-by: build bot (Jenkins) Reviewed-by: Yidi Lin --- src/soc/mediatek/common/include/soc/wdt_common.h | 1 + src/soc/mediatek/common/wdt.c | 2 ++ src/soc/mediatek/mt8189/Makefile.mk | 1 + src/soc/mediatek/mt8189/efuse.c | 12 ++++++++++++ src/soc/mediatek/mt8189/include/soc/addressmap.h | 1 + src/soc/mediatek/mt8189/include/soc/efuse.h | 5 +++++ src/soc/mediatek/mt8189/wdt.c | 12 +++++++++++- 7 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 src/soc/mediatek/mt8189/efuse.c diff --git a/src/soc/mediatek/common/include/soc/wdt_common.h b/src/soc/mediatek/common/include/soc/wdt_common.h index 6d6d2ba758..02574263ae 100644 --- a/src/soc/mediatek/common/include/soc/wdt_common.h +++ b/src/soc/mediatek/common/include/soc/wdt_common.h @@ -57,5 +57,6 @@ static struct mtk_wdt_regs *const mtk_wdt = (void *)RGU_BASE; int mtk_wdt_init(void); void mtk_wdt_clr_status(void); void mtk_wdt_set_req(void); +void mtk_wdt_clear_efuse_ecc(void); #endif /* SOC_MEDIATEK_WDT_COMMON_H */ diff --git a/src/soc/mediatek/common/wdt.c b/src/soc/mediatek/common/wdt.c index 663fc2fd30..e4038aae02 100644 --- a/src/soc/mediatek/common/wdt.c +++ b/src/soc/mediatek/common/wdt.c @@ -10,6 +10,7 @@ __weak void mtk_wdt_clr_status(void) { /* do nothing */ } __weak void mtk_wdt_set_req(void) { /* do nothing */ } +__weak void mtk_wdt_clear_efuse_ecc(void) { /* do nothing */ } static inline void mtk_wdt_swreset(void) { @@ -36,6 +37,7 @@ int mtk_wdt_init(void) { uint32_t wdt_sta; + mtk_wdt_clear_efuse_ecc(); mtk_wdt_set_req(); /* Writing mode register will clear status register */ diff --git a/src/soc/mediatek/mt8189/Makefile.mk b/src/soc/mediatek/mt8189/Makefile.mk index c870dec5c7..237cbaab0e 100644 --- a/src/soc/mediatek/mt8189/Makefile.mk +++ b/src/soc/mediatek/mt8189/Makefile.mk @@ -10,6 +10,7 @@ all-y += ../common/timer_prepare.c timer.c all-y += ../common/uart.c bootblock-y += bootblock.c +bootblock-y += efuse.c bootblock-y += ../common/mmu_operations.c bootblock-y += ../common/mtcmos.c mtcmos.c bootblock-y += ../common/pll.c pll.c diff --git a/src/soc/mediatek/mt8189/efuse.c b/src/soc/mediatek/mt8189/efuse.c new file mode 100644 index 0000000000..726b5474bf --- /dev/null +++ b/src/soc/mediatek/mt8189/efuse.c @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0-only OR MIT */ + +#include +#include +#include + +#define MTK_EFUSE_ECC_ERROR_BIT BIT(7) + +bool mtk_efuse_ecc_has_error(void) +{ + return !!(read32(&mtk_efuse->ecc_status_reg) & MTK_EFUSE_ECC_ERROR_BIT); +} diff --git a/src/soc/mediatek/mt8189/include/soc/addressmap.h b/src/soc/mediatek/mt8189/include/soc/addressmap.h index 0f257cc543..3f6fe3e598 100644 --- a/src/soc/mediatek/mt8189/include/soc/addressmap.h +++ b/src/soc/mediatek/mt8189/include/soc/addressmap.h @@ -91,6 +91,7 @@ enum { IMP_IIC_WRAP_S_BASE = IO_PHYS + 0x01D74000, IOCFG_LT0_BASE = IO_PHYS + 0x01E20000, IOCFG_LT1_BASE = IO_PHYS + 0x01E30000, + EFUSEC_BASE = IO_PHYS + 0x01F10000, IOCFG_RT_BASE = IO_PHYS + 0x01F20000, IMP_IIC_WRAP_EN_BASE = IO_PHYS + 0x01F32000, MFGCFG_BASE = IO_PHYS + 0x03FBF000, diff --git a/src/soc/mediatek/mt8189/include/soc/efuse.h b/src/soc/mediatek/mt8189/include/soc/efuse.h index 031dd5ef78..2d872d46b5 100644 --- a/src/soc/mediatek/mt8189/include/soc/efuse.h +++ b/src/soc/mediatek/mt8189/include/soc/efuse.h @@ -11,10 +11,15 @@ struct efuse_regs { u32 cpu_id_reg; u32 reserved2[15]; u32 cpu_seg_id_reg; + u32 reserved3[14908]; + u32 ecc_status_reg; }; check_member(efuse_regs, cpu_id_reg, 0x7A0); check_member(efuse_regs, cpu_seg_id_reg, 0x7E0); +check_member(efuse_regs, ecc_status_reg, 0xF0D4); static struct efuse_regs *const mtk_efuse = (void *)EFUSEC_BASE; +bool mtk_efuse_ecc_has_error(void); + #endif /*__SOC_MEDIATEK_MT8189_INCLUDE_SOC_EFUSE_H__*/ diff --git a/src/soc/mediatek/mt8189/wdt.c b/src/soc/mediatek/mt8189/wdt.c index ca6518bc2e..ba991d2e96 100644 --- a/src/soc/mediatek/mt8189/wdt.c +++ b/src/soc/mediatek/mt8189/wdt.c @@ -7,11 +7,21 @@ #include #include +#include #include -#define MTK_WDT_CLR_STATUS 0x230001FF +#define MTK_WDT_CLR_STATUS 0x230001FF +#define MTK_WDT_CLR_EFUSE_ECC_ERR 0x2300000A +#define MTK_WDT_STA_EFUSE_ECC_ERR BIT(23) void mtk_wdt_clr_status(void) { write32(&mtk_wdt->wdt_mode, MTK_WDT_CLR_STATUS); } + +void mtk_wdt_clear_efuse_ecc(void) +{ + if ((read32(&mtk_wdt->wdt_status) & MTK_WDT_STA_EFUSE_ECC_ERR) && + !mtk_efuse_ecc_has_error()) + write32(&mtk_wdt->wdt_mode, MTK_WDT_CLR_EFUSE_ECC_ERR); +}