From 5cf460dce9e479039fdf4f77a6cdab22b54bbd17 Mon Sep 17 00:00:00 2001 From: Shunxi Zhang Date: Fri, 9 May 2025 18:39:36 +0800 Subject: [PATCH] soc/mediatek/mt8196: Fix RTC protection register unlock failure Add flow of checking RTC unlock protection state after RTC protection unlock sequence. On failure, retry this flow several times. Additionally, change the time of CBUSY maximum timeout to 1 second. BRANCH=rauru BUG=b:392197855 TEST=emerge-rauru coreboot chromeos-bootimage, when suspend/warmboot/ coldboot, RTC boots and works normally. After 15 tests, the boot time will increase by approximately 1.3ms from 890.508ms to 891.832ms Signed-off-by: Shunxi Zhang Change-Id: Id4d537d9c60dc7520c446f1816ef95f9f1e0ff80 Reviewed-on: https://review.coreboot.org/c/coreboot/+/87638 Reviewed-by: Shunxi Zhang Reviewed-by: Yu-Ping Wu Reviewed-by: Yidi Lin Tested-by: build bot (Jenkins) --- .../mediatek/mt8196/include/soc/mt6685_rtc.h | 5 ++ src/soc/mediatek/mt8196/include/soc/rtc.h | 4 +- src/soc/mediatek/mt8196/mt6685_rtc.c | 54 ++++++++++++++----- 3 files changed, 49 insertions(+), 14 deletions(-) diff --git a/src/soc/mediatek/mt8196/include/soc/mt6685_rtc.h b/src/soc/mediatek/mt8196/include/soc/mt6685_rtc.h index e46fd90ff6..612d2d424e 100644 --- a/src/soc/mediatek/mt8196/include/soc/mt6685_rtc.h +++ b/src/soc/mediatek/mt8196/include/soc/mt6685_rtc.h @@ -49,6 +49,11 @@ #define RG_FQMTR_DATA 0x54a +#define RTC_SPAR_MACRO 0x5d8 +#define RTC_SPAR_PROT_STAT_SHIFT 6 +#define RTC_SPAR_PROT_STAT_MASK 0x3 +#define RTC_PROT_UNLOCK_SUCCESS 0x3 + #define RG_FQMTR_CLK_CK_PDN_SET 0x10c #define RG_FQMTR_CLK_CK_PDN_MASK 0x1 #define RG_FQMTR_CLK_CK_PDN_SHIFT 5 diff --git a/src/soc/mediatek/mt8196/include/soc/rtc.h b/src/soc/mediatek/mt8196/include/soc/rtc.h index b315998713..f45e4384ce 100644 --- a/src/soc/mediatek/mt8196/include/soc/rtc.h +++ b/src/soc/mediatek/mt8196/include/soc/rtc.h @@ -12,6 +12,7 @@ #include #include #include +#include #include /* RTC registers */ @@ -21,7 +22,7 @@ enum { RTC_BBPU_RELOAD = BIT(5), RTC_BBPU_CBUSY = BIT(6), - RTC_CBUSY_TIMEOUT_US = 8000, + RTC_CBUSY_TIMEOUT_US = USECS_PER_SEC, }; enum { @@ -59,6 +60,7 @@ enum { #define BBPU_RELOAD_TIMEOUT_US 100000 #define EOSC_CHECK_CLK_TIMEOUT_US 1000000 #define RECOVERY_RETRY_COUNT 3 +#define PROT_UNLOCK_RETRY_COUNT 3 struct rtc_clk_freq { u16 fqm26m_ck; diff --git a/src/soc/mediatek/mt8196/mt6685_rtc.c b/src/soc/mediatek/mt8196/mt6685_rtc.c index 95e8dd6907..36e29f5a2a 100644 --- a/src/soc/mediatek/mt8196/mt6685_rtc.c +++ b/src/soc/mediatek/mt8196/mt6685_rtc.c @@ -33,6 +33,34 @@ void rtc_write(u16 addr, u16 wdata) mt6685_write16(addr, wdata); } +static u16 rtc_get_prot_stat(void) +{ + u16 val; + u16 state = 0; + + udelay(100); + + rtc_read(RTC_SPAR_MACRO, &val); + + state = (val >> RTC_SPAR_PROT_STAT_SHIFT) & RTC_SPAR_PROT_STAT_MASK; + + return state; +} + +static bool mt6685_writeif_unlock(void) +{ + if (!retry(PROT_UNLOCK_RETRY_COUNT, + rtc_writeif_unlock() && + rtc_get_prot_stat() == RTC_PROT_UNLOCK_SUCCESS)) { + + printk(BIOS_ERR, "%s: retry failed!!\n", __func__); + + return false; + } + + return true; +} + static bool rtc_eosc_check_clock(const struct rtc_clk_freq *result) { if ((result->fqm26m_ck >= 3 && result->fqm26m_ck <= 7) && @@ -319,7 +347,7 @@ static bool rtc_init_after_recovery(void) /* write powerkeys */ if (!rtc_powerkey_init()) return false; - if (!rtc_writeif_unlock()) + if (!mt6685_writeif_unlock()) return false; if (!rtc_gpio_init()) return false; @@ -332,7 +360,7 @@ static bool rtc_init_after_recovery(void) if (!rtc_powerkey_init()) return false; - if (!rtc_writeif_unlock()) + if (!mt6685_writeif_unlock()) return false; secure_rtc_init(); @@ -366,9 +394,9 @@ static bool rtc_first_boot_init(void) if (!rtc_write_trigger()) return false; - if (!rtc_writeif_unlock()) { + if (!mt6685_writeif_unlock()) { printk(BIOS_ERR, - "%s: rtc_writeif_unlock failed after BBPU written\n", __func__); + "%s: mt6685_writeif_unlock failed after BBPU written\n", __func__); return false; } @@ -387,9 +415,9 @@ static bool rtc_first_boot_init(void) return false; } - if (!rtc_writeif_unlock()) { + if (!mt6685_writeif_unlock()) { printk(BIOS_ERR, - "%s: rtc_writeif_unlock failed after POWERKEY written\n", __func__); + "%s: mt6685_writeif_unlock failed after POWERKEY written\n", __func__); return false; } @@ -402,9 +430,9 @@ static bool rtc_first_boot_init(void) return false; } - if (!rtc_writeif_unlock()) { + if (!mt6685_writeif_unlock()) { printk(BIOS_ERR, - "%s rtc_writeif_unlock failed after BBPU written\n", __func__); + "%s mt6685_writeif_unlock failed after BBPU written\n", __func__); return false; } @@ -418,9 +446,9 @@ static bool rtc_first_boot_init(void) return false; } - if (!rtc_writeif_unlock()) { + if (!mt6685_writeif_unlock()) { printk(BIOS_ERR, - "%s rtc_writeif_unlock failed after POWERKEY written\n", __func__); + "%s mt6685_writeif_unlock failed after POWERKEY written\n", __func__); return false; } @@ -444,8 +472,8 @@ static void rtc_enable_dcxo(void) u16 con, osc32con, sec; /* Unlock for reload */ - if (!rtc_writeif_unlock()) - printk(BIOS_ERR, "rtc_writeif_unlock() failed\n"); + if (!mt6685_writeif_unlock()) + printk(BIOS_ERR, "mt6685_writeif_unlock() failed\n"); rtc_read(RTC_BBPU, &rdata); rtc_write(RTC_BBPU, rdata | RTC_BBPU_KEY | RTC_BBPU_RELOAD); @@ -525,7 +553,7 @@ void rtc_boot(void) rtc_read(RTC_BBPU, &rtc_bbpu); rtc_write(RTC_BBPU, rtc_bbpu | RTC_BBPU_KEY | RTC_BBPU_RELOAD); - if (!rtc_write_trigger() || !rtc_writeif_unlock()) { + if (!rtc_write_trigger() || !mt6685_writeif_unlock()) { rtc_recovery_flow(); } else { rtc_read(RTC_POWERKEY1, &rtc_pwrkey1);