From e850164bac08a5b3b4cd09f587775e68ad1b40c2 Mon Sep 17 00:00:00 2001 From: Aaron Durbin Date: Mon, 29 Apr 2013 22:22:55 -0500 Subject: tsc: provide monotonic timer Implement the timer_monotonic_get() using the TSC. Change-Id: I5118da6fb9bccc75d2ce012317612e0ab20a2cac Signed-off-by: Aaron Durbin Reviewed-on: http://review.coreboot.org/3155 Tested-by: build bot (Jenkins) Reviewed-by: Ronald G. Minnich --- src/cpu/x86/Kconfig | 7 +++++++ src/cpu/x86/tsc/delay_tsc.c | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/src/cpu/x86/Kconfig b/src/cpu/x86/Kconfig index 6b70ae7c6c..5cf40fa4a9 100644 --- a/src/cpu/x86/Kconfig +++ b/src/cpu/x86/Kconfig @@ -25,6 +25,13 @@ config UDELAY_TSC bool default n +config TSC_MONOTONIC_TIMER + def_bool n + depends on UDELAY_TSC + select HAVE_MONOTONIC_TIMER + help + Expose monotonic time using the TSC. + config UDELAY_TIMER2 bool default n diff --git a/src/cpu/x86/tsc/delay_tsc.c b/src/cpu/x86/tsc/delay_tsc.c index 1907a9cfec..e4993d0dd5 100644 --- a/src/cpu/x86/tsc/delay_tsc.c +++ b/src/cpu/x86/tsc/delay_tsc.c @@ -164,3 +164,40 @@ void udelay(unsigned us) count = rdtscll(); } } + +#if CONFIG_TSC_MONOTONIC_TIMER +#include + +static struct monotonic_counter { + int initialized; + struct mono_time time; + uint64_t last_value; +} mono_counter; + +void timer_monotonic_get(struct mono_time *mt) +{ + uint64_t current_tick; + uint64_t ticks_elapsed; + + if (!mono_counter.initialized) { + init_timer(); + mono_counter.last_value = rdtscll(); + mono_counter.initialized = 1; + } + + current_tick = rdtscll(); + ticks_elapsed = current_tick - mono_counter.last_value; + + /* Update current time and tick values only if a full tick occurred. */ + if (ticks_elapsed >= clocks_per_usec) { + uint64_t usecs_elapsed; + + usecs_elapsed = ticks_elapsed / clocks_per_usec; + mono_time_add_usecs(&mono_counter.time, (long)usecs_elapsed); + mono_counter.last_value = current_tick; + } + + /* Save result. */ + *mt = mono_counter.time; +} +#endif -- cgit v1.2.3