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 <ot_zexin.wang@mediatek.corp-partner.google.com>
Change-Id: Idd2763688c7ab6992a7c185e9e52b60bda88c94c
Reviewed-on: https://review.coreboot.org/c/coreboot/+/87744
Reviewed-by: Yu-Ping Wu <yupingso@google.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Yidi Lin <yidilin@google.com>
This commit is contained in:
Zexin Wang 2024-12-17 19:32:58 +08:00 committed by Yu-Ping Wu
commit 2bec5a9d9a
7 changed files with 33 additions and 1 deletions

View file

@ -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 */

View file

@ -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 */

View file

@ -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

View file

@ -0,0 +1,12 @@
/* SPDX-License-Identifier: GPL-2.0-only OR MIT */
#include <device/mmio.h>
#include <soc/addressmap.h>
#include <soc/efuse.h>
#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);
}

View file

@ -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,

View file

@ -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__*/

View file

@ -7,11 +7,21 @@
#include <device/mmio.h>
#include <soc/addressmap.h>
#include <soc/efuse.h>
#include <soc/wdt.h>
#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);
}