diff --git a/src/soc/intel/apollolake/include/soc/pm.h b/src/soc/intel/apollolake/include/soc/pm.h index 34b9f965ae..e8ec645b1f 100644 --- a/src/soc/intel/apollolake/include/soc/pm.h +++ b/src/soc/intel/apollolake/include/soc/pm.h @@ -173,8 +173,13 @@ #define COLD_BOOT_STS (1 << 27) #define COLD_RESET_STS (1 << 26) #define WARM_RESET_STS (1 << 25) +#define GLOBAL_RESET_STS (1 << 24) #define SRS (1 << 20) +#define MS4V (1 << 18) #define RPS (1 << 2) +#define GEN_PMCON1_CLR1_BITS (COLD_BOOT_STS | COLD_RESET_STS | \ + WARM_RESET_STS | GLOBAL_RESET_STS | \ + SRS | MS4V) #define GEN_PMCON2 0x1024 #define GEN_PMCON3 0x1028 # define SLP_S3_ASSERT_WIDTH_SHIFT 10 diff --git a/src/soc/intel/apollolake/pmutil.c b/src/soc/intel/apollolake/pmutil.c index dbaed70ca3..05590bd8f8 100644 --- a/src/soc/intel/apollolake/pmutil.c +++ b/src/soc/intel/apollolake/pmutil.c @@ -232,5 +232,21 @@ int soc_get_rtc_failed(void) int vbnv_cmos_failed(void) { - return rtc_failed(read32((void *)(read_pmc_mmio_bar() + GEN_PMCON1))); + uintptr_t pmc_bar = read_pmc_mmio_bar(); + uint32_t gen_pmcon1 = read32((void *)(pmc_bar + GEN_PMCON1)); + int rtc_failure = rtc_failed(gen_pmcon1); + + if (rtc_failure) { + printk(BIOS_INFO, "RTC failed!\n"); + + /* We do not want to write 1 to clear-1 bits. Set them to 0. */ + gen_pmcon1 &= ~GEN_PMCON1_CLR1_BITS; + + /* RPS is write 0 to clear. */ + gen_pmcon1 &= ~RPS; + + write32((void *)(pmc_bar + GEN_PMCON1), gen_pmcon1); + } + + return rtc_failure; }