summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cpu/x86/Kconfig7
-rw-r--r--src/cpu/x86/tsc/Makefile.inc4
-rw-r--r--src/cpu/x86/tsc/delay_tsc.c27
-rw-r--r--src/include/cpu/x86/tsc.h4
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 */