summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron Durbin <adurbin@chromium.org>2013-05-01 15:27:09 -0500
committerRonald G. Minnich <rminnich@gmail.com>2013-05-07 18:35:04 +0200
commit8e73b5d9528401a50254eb968080b814b5418152 (patch)
treeeb63210a3be8114f72894c9ff78fbc70fb4d2426
parent7cb1ba9a61b244800eb65c08729f75d85a504de3 (diff)
x86: add TSC_CONSTANT_RATE option
Some boards use the local apic for udelay(), but they also provide their own implementation of udelay() for SMM. The reason for using the local apic for udelay() in ramstage is to not have to pay the penalty of calibrating the TSC frequency. Therefore provide a TSC_CONSTANT_RATE option to indicate that TSC calibration is not needed. Instead rely on the presence of a tsc_freq_mhz() function provided by the cpu/board. Additionally, assume that if TSC_CONSTANT_RATE is selected the udelay() function in SMM will be the tsc. Change-Id: I1629c2fbe3431772b4e80495160584fb6f599e9e Signed-off-by: Aaron Durbin <adurbin@chromium.org> Reviewed-on: http://review.coreboot.org/3168 Tested-by: build bot (Jenkins) Reviewed-by: Paul Menzel <paulepanter@users.sourceforge.net> Reviewed-by: Ronald G. Minnich <rminnich@gmail.com>
-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 */