From b44d8d1ee21e923e37a748ba767d8ae6bf95d873 Mon Sep 17 00:00:00 2001 From: Mary Ruthven Date: Fri, 9 Dec 2022 12:48:59 -0800 Subject: hwtimer: add support for tracking time since cold boot Pinweaver needs a timer that counts through deep sleep. This change keeps track of the time since cold boot in PWRDN_SCRATCH23. Before the low speed timer is cleared during init add the value to PWRDN_SCRATCH23. BUG=b:262036852,b:279759625 TEST=manual After hard reset the cold reset time and system time should be the same. > sysinfo Reset flags: 0x00000800 (hard) Reset count: 0 > get Time: 0x0000000006628dd7 = 107.122135 s since cold_reset: 107 s Verify the cold reset timer keeps counting during deep sleep. dut-control cold_reset:on [138.415843 AP off] [Reset cause: hibernate wake-pin] [Image: RW, ... [0.003864 Inits done] [0.009647 init_jittery_clock_locking_o... [0.039134 init took 22838] > get Time: 0x0000000000bf3e3a = 12.533306 s since cold_reset: 150 s > sysi Reset flags: 0x00000140 (hibernate wake-pin) Verify cold reset and system time are the same after H1_RST_L is pulsed dut-control gsc_reset:on gsc_reset:off > get Time: 0x00000000001cdea9 = 1.892009 s since cold_reset: 1 s > sysi Reset flags: 0x00000008 (power-on) Reset count: 1 Change-Id: Ie57324880c8b8068ddff62760848e161b2df903d Signed-off-by: Mary Ruthven Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/4093120 Reviewed-by: Vadim Bendebury Reviewed-by: Andrey Pronin --- chip/g/hwtimer.c | 27 +++++++++++++++++++++++++++ chip/g/init_chip.h | 1 + common/timer.c | 2 +- include/timer.h | 5 +++++ 4 files changed, 34 insertions(+), 1 deletion(-) diff --git a/chip/g/hwtimer.c b/chip/g/hwtimer.c index fe5db33858..e7e0b0b84e 100644 --- a/chip/g/hwtimer.c +++ b/chip/g/hwtimer.c @@ -4,10 +4,12 @@ */ #include "common.h" +#include "ec_commands.h" #include "hooks.h" #include "hwtimer.h" #include "init_chip.h" #include "registers.h" +#include "system.h" #include "task.h" #include "timer.h" #include "util.h" @@ -33,6 +35,11 @@ */ #define MAX_TIME_USEC 0xffffffff #define TIMELS_MAX (usecs_to_ticks(MAX_TIME_USEC)) +/* + * Seconds to add when the timer wraps. Round up to ensure cr50 doesn't lose + * time during the wrap around. + */ +#define OVERFLOW_TIME_S ((MAX_TIME_USEC + SECOND - 1) / SECOND) /* * The below calculation is lightweight and can be implemented using @@ -62,6 +69,19 @@ uint32_t __hw_clock_event_get(void) ticks_to_usecs(GREG32(TIMELS, EVENT(VALUE))); } +uint32_t get_seconds_since_cold_boot(void) +{ + uint32_t overflow_s = GREAD_FIELD(TIMELS, SOURCE(STATUS), WRAPPED) ? + OVERFLOW_TIME_S : 0; + return (GREG32(PMU, PWRDN_SCRATCH23) + overflow_s + + (__hw_clock_source_read() / SECOND)); +} + +static void save_seconds_since_cold_boot(void) +{ + GREG32(PMU, PWRDN_SCRATCH23) = get_seconds_since_cold_boot(); +} + void __hw_clock_event_clear(void) { /* one-shot, 32-bit, timer & interrupts disabled, 1:1 prescale */ @@ -125,6 +145,8 @@ void __hw_clock_source_irq(void) GWRITE(TIMELS, SOURCE(WAKEUP_ACK), 1); GWRITE(TIMELS, SOURCE(IAR), 1); + save_seconds_since_cold_boot(); + /* Reset the load value */ GREG32(TIMELS, SOURCE(LOAD)) = TIMELS_MAX; @@ -151,6 +173,11 @@ int __hw_clock_source_init(uint32_t start_t) GWRITE_FIELD(TIMELS, EVENT(CONTROL), RELOAD, 0); GWRITE_FIELD(TIMELS, EVENT(CONTROL), ENABLE, 0); + + /* Save time since deep sleep before resetting the SOURCE timer. */ + if (system_get_reset_flags() & EC_RESET_FLAG_HIBERNATE) + save_seconds_since_cold_boot(); + /* Configure timer0 */ GREG32(TIMELS, SOURCE(RELOADVAL)) = TIMELS_MAX; GWRITE_FIELD(TIMELS, SOURCE(CONTROL), WRAP, 1); diff --git a/chip/g/init_chip.h b/chip/g/init_chip.h index 7421b996f3..5414399bb4 100644 --- a/chip/g/init_chip.h +++ b/chip/g/init_chip.h @@ -26,6 +26,7 @@ * SCRATCH20 - Preserving EC-EFS context * SCRATCH21 - Preserving TPM_BOARD_CFG register * SCRATCH22 - Preserve FIPS power-up test status on Cr50 + * SCRATCH23 - Preserve time since cold boot * * PWRDN_SCRATCH 28 - 31 - Reserved for boot rom */ diff --git a/common/timer.c b/common/timer.c index e08fe88056..a43da30861 100644 --- a/common/timer.c +++ b/common/timer.c @@ -323,7 +323,7 @@ static int command_get_time(int argc, char **argv) { timestamp_t ts = get_time(); ccprintf("Time: 0x%016llx = %.6lld s\n", ts.val, ts.val); - + ccprintf("since cold_reset: %u s\n", get_seconds_since_cold_boot()); return EC_SUCCESS; } DECLARE_SAFE_CONSOLE_COMMAND(gettime, command_get_time, diff --git a/include/timer.h b/include/timer.h index 7c107d2185..bbdf3c3435 100644 --- a/include/timer.h +++ b/include/timer.h @@ -116,6 +116,11 @@ static inline void sleep(unsigned sec) */ timestamp_t get_time(void); +/** + * Get the time in seconds since cold boot. + */ +uint32_t get_seconds_since_cold_boot(void); + /** * Force the current value of the system timer. * -- cgit v1.2.1