diff options
-rw-r--r-- | src/cpu/x86/Kconfig | 7 | ||||
-rw-r--r-- | src/cpu/x86/tsc/Makefile.inc | 4 | ||||
-rw-r--r-- | src/cpu/x86/tsc/delay_tsc.c | 27 | ||||
-rw-r--r-- | src/include/cpu/x86/tsc.h | 4 |
4 files changed, 39 insertions, 3 deletions
diff --git a/src/cpu/x86/Kconfig b/src/cpu/x86/Kconfig index 5cf40fa4a9..c64a8e477b 100644 --- a/src/cpu/x86/Kconfig +++ b/src/cpu/x86/Kconfig @@ -25,6 +25,13 @@ config UDELAY_TSC bool default n +config TSC_CONSTANT_RATE + def_bool n + depends on UDELAY_TSC + help + This option asserts that the TSC ticks at a known constant rate. + Therefore, no TSC calibration is required. + config TSC_MONOTONIC_TIMER def_bool n depends on UDELAY_TSC diff --git a/src/cpu/x86/tsc/Makefile.inc b/src/cpu/x86/tsc/Makefile.inc index 44bfe85170..3bbae847f8 100644 --- a/src/cpu/x86/tsc/Makefile.inc +++ b/src/cpu/x86/tsc/Makefile.inc @@ -1,2 +1,6 @@ ramstage-$(CONFIG_UDELAY_TSC) += delay_tsc.c +romstage-$(CONFIG_TSC_CONSTANT_RATE) += delay_tsc.c +ifeq ($(CONFIG_HAVE_SMI_HANDLER),y) +smm-$(CONFIG_TSC_CONSTANT_RATE) += delay_tsc.c +endif diff --git a/src/cpu/x86/tsc/delay_tsc.c b/src/cpu/x86/tsc/delay_tsc.c index e4993d0dd5..0540496f5e 100644 --- a/src/cpu/x86/tsc/delay_tsc.c +++ b/src/cpu/x86/tsc/delay_tsc.c @@ -5,8 +5,16 @@ #include <smp/spinlock.h> #include <delay.h> +#if !defined(__PRE_RAM__) + static unsigned long clocks_per_usec; +#if CONFIG_TSC_CONSTANT_RATE +static unsigned long calibrate_tsc(void) +{ + return tsc_freq_mhz(); +} +#else /* CONFIG_TSC_CONSTANT_RATE */ #if !CONFIG_TSC_CALIBRATE_WITH_IO #define CLOCK_TICK_RATE 1193180U /* Underlying HZ */ @@ -139,6 +147,7 @@ static unsigned long long calibrate_tsc(void) #endif /* CONFIG_TSC_CALIBRATE_WITH_IO */ +#endif /* CONFIG_TSC_CONSTANT_RATE */ void init_timer(void) { @@ -148,15 +157,27 @@ void init_timer(void) } } +static inline unsigned long get_clocks_per_usec(void) +{ + init_timer(); + return clocks_per_usec; +} +#else /* !defined(__PRE_RAM__) */ +/* romstage calls into cpu/board specific function every time. */ +static inline unsigned long get_clocks_per_usec(void) +{ + return tsc_freq_mhz(); +} +#endif /* !defined(__PRE_RAM__) */ + void udelay(unsigned us) { unsigned long long count; unsigned long long stop; unsigned long long clocks; - init_timer(); clocks = us; - clocks *= clocks_per_usec; + clocks *= get_clocks_per_usec(); count = rdtscll(); stop = clocks + count; while(stop > count) { @@ -165,7 +186,7 @@ void udelay(unsigned us) } } -#if CONFIG_TSC_MONOTONIC_TIMER +#if CONFIG_TSC_MONOTONIC_TIMER && !defined(__PRE_RAM__) && !defined(__SMM__) #include <timer.h> static struct monotonic_counter { diff --git a/src/include/cpu/x86/tsc.h b/src/include/cpu/x86/tsc.h index 6ce7f5fc7d..8e49a669eb 100644 --- a/src/include/cpu/x86/tsc.h +++ b/src/include/cpu/x86/tsc.h @@ -40,4 +40,8 @@ static inline unsigned long long rdtscll(void) } #endif +#if CONFIG_TSC_CONSTANT_RATE +unsigned long tsc_freq_mhz(void); +#endif + #endif /* CPU_X86_TSC_H */ |