diff options
author | Aaron Durbin <adurbin@chromium.org> | 2013-04-29 22:22:55 -0500 |
---|---|---|
committer | Ronald G. Minnich <rminnich@gmail.com> | 2013-05-01 07:15:55 +0200 |
commit | e850164bac08a5b3b4cd09f587775e68ad1b40c2 (patch) | |
tree | 2e9ab9f1b1a7e878cdcfea71ad8c69269d8dfe0e | |
parent | fd8291c9d438917e334f4211fb1142b6a7bb7e32 (diff) |
tsc: provide monotonic timer
Implement the timer_monotonic_get() using the TSC.
Change-Id: I5118da6fb9bccc75d2ce012317612e0ab20a2cac
Signed-off-by: Aaron Durbin <adurbin@chromium.org>
Reviewed-on: http://review.coreboot.org/3155
Tested-by: build bot (Jenkins)
Reviewed-by: Ronald G. Minnich <rminnich@gmail.com>
-rw-r--r-- | src/cpu/x86/Kconfig | 7 | ||||
-rw-r--r-- | src/cpu/x86/tsc/delay_tsc.c | 37 |
2 files changed, 44 insertions, 0 deletions
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 <timer.h> + +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 |