summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--chip/g/hwtimer.c27
-rw-r--r--chip/g/init_chip.h1
-rw-r--r--common/timer.c2
-rw-r--r--include/timer.h5
4 files changed, 34 insertions, 1 deletions
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
@@ -117,6 +117,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.
*
* This function is for the power management implementation which wants to fix