summaryrefslogtreecommitdiff
path: root/chip/npcx/system.c
diff options
context:
space:
mode:
authorWealian Liao <whliao@nuvoton.corp-partner.google.com>2020-10-29 01:55:56 -0700
committerCommit Bot <commit-bot@chromium.org>2021-01-12 02:35:14 +0000
commit88b780027ddfc0afa55c4cf3c6d5606d7676cbca (patch)
tree32aac28aa0a1c737aecea4162b43a7599a035bef /chip/npcx/system.c
parent72106b0e0997ac8d0df70335471659372466133b (diff)
downloadchrome-ec-88b780027ddfc0afa55c4cf3c6d5606d7676cbca.tar.gz
npcx/system: LCT compensate for MTC in PSL_hibernate
NPCX chip uses the MTC module as the RTC counter. However, in PSL hibernate, MTC will stop counting. NPCX9 supports the LCT module which could count continuously when VCC1 power is off. The CL uses LCT to compensate for the MTC counter value after PSL hibernate wake-up. The LCT maximum counting value is 16 weeks. BRANCH=none BUG=b:165777478, b:171919875 TEST=pass "make buildall" TEST=Check the RTC value in the following scenario: 1. "hibernate" and wake up EC by PSL input. 2. "hibernate 30" and wake up EC after timeout. 3. "hibernate 30" and wake up EC by PSL input before timeout. Signed-off-by: Wealian Liao <whliao@nuvoton.corp-partner.google.com> Change-Id: I39e370a437f40749acbd3a35a8b37ebec70f1bf2 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2506864 Reviewed-by: Keith Short <keithshort@chromium.org>
Diffstat (limited to 'chip/npcx/system.c')
-rw-r--r--chip/npcx/system.c40
1 files changed, 35 insertions, 5 deletions
diff --git a/chip/npcx/system.c b/chip/npcx/system.c
index a779c050bf..e2fb468414 100644
--- a/chip/npcx/system.c
+++ b/chip/npcx/system.c
@@ -534,6 +534,9 @@ static void system_set_lct_alarm(uint32_t seconds, uint32_t microseconds)
#ifdef CONFIG_HIBERNATE_PSL
/* Enable LCT event to PSL */
npcx_lct_config(seconds, 1, 0);
+ /* save the start time of LCT */
+ if (IS_ENABLED(CONFIG_HOSTCMD_RTC) || IS_ENABLED(CONFIG_CMD_RTC))
+ bbram_data_write(BBRM_DATA_INDEX_LCT_TIME, seconds);
#else
/* Enable LCT event interrupt and MIWU */
npcx_lct_config(seconds, 0, 1);
@@ -617,21 +620,48 @@ void __enter_hibernate(uint32_t seconds, uint32_t microseconds)
for (i = NPCX_IRQ_0 ; i < NPCX_IRQ_COUNT ; i++)
task_clear_pending_irq(i);
- /*
- * Set RTC interrupt in time to wake up before
- * next event.
- */
- if (seconds || microseconds)
+ /* Set the timer interrupt for wake up. */
#ifdef NPCX_LCT_SUPPORT
+ if (seconds || microseconds) {
system_set_lct_alarm(seconds, microseconds);
+ } else if (IS_ENABLED(CONFIG_HIBERNATE_PSL_COMPENSATE_RTC)) {
+ system_set_lct_alarm(NPCX_LCT_MAX, 0);
+ }
#else
+ if (seconds || microseconds)
system_set_rtc_alarm(seconds, microseconds);
#endif
/* execute hibernate func depend on chip series */
__hibernate_npcx_series();
+}
+
+#ifdef CONFIG_HIBERNATE_PSL_COMPENSATE_RTC
+#ifndef NPCX_LCT_SUPPORT
+#error "Do not enable CONFIG_HIBERNATE_PSL_COMPENSATE_RTC if npcx ec doesn't \
+support LCT!"
+#endif
+/*
+ * The function uses the LCT counter value to compensate for RTC after hibernate
+ * wake-up. Because system_set_rtc() will invoke udelay(), the function should
+ * execute after timer_init(). The function also should execute before
+ * npcx_lct_init() which will clear all LCT register.
+ */
+void system_compensate_rtc(void)
+{
+ uint32_t rtc_time, ltc_start_time;
+ ltc_start_time = bbram_data_read(BBRM_DATA_INDEX_LCT_TIME);
+ if (ltc_start_time == 0)
+ return;
+
+ rtc_time = system_get_rtc_sec();
+ rtc_time += ltc_start_time - npcx_lct_get_time();
+ system_set_rtc(rtc_time);
+ /* Clear BBRAM data to avoid compensating again. */
+ bbram_data_write(BBRM_DATA_INDEX_LCT_TIME, 0);
}
+#endif
#endif /* CONFIG_SUPPORT_CHIP_HIBERNATION */
static char system_to_hex(uint8_t val)