summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVadim Bendebury <vbendeb@chromium.org>2012-12-03 13:59:20 +0000
committerSimon Glass <sjg@chromium.org>2012-12-06 14:30:43 -0800
commit7c71034d3ca2f4bd01812e94e813d35a78a27e34 (patch)
tree683e5a0996921d383c21e3b7654e31807d063953
parentb83058cd235acca426b1964e3aa394f7ecf16ccc (diff)
x86: Provide tick counter and frequency reference for Intel core architecture
Some u-boot modules rely on availability of get_ticks() and get_tbclk() functions, reporting a free running clock and its frequency respectively. Traditionally these functions return number and frequency of timer interrupts. Intel's core architecture processors however are known to run the rdtsc instruction at a constant rate of the so called 'Max Non Turbo ratio' times the external clock frequency which is 100MHz. This is just as good for the timer tick functions in question. Signed-off-by: Vadim Bendebury <vbendeb@chromium.org> Signed-off-by: Simon Glass <sjg@chromium.org>
-rw-r--r--arch/x86/cpu/interrupts.c31
1 files changed, 31 insertions, 0 deletions
diff --git a/arch/x86/cpu/interrupts.c b/arch/x86/cpu/interrupts.c
index e7887152f7..dd30a05a9d 100644
--- a/arch/x86/cpu/interrupts.c
+++ b/arch/x86/cpu/interrupts.c
@@ -34,6 +34,8 @@
#include <asm/io.h>
#include <asm/processor-flags.h>
#include <linux/compiler.h>
+#include <asm/msr.h>
+#include <asm/u-boot-x86.h>
#define DECLARE_INTERRUPT(x) \
".globl irq_"#x"\n" \
@@ -615,3 +617,32 @@ asm(".globl irq_common_entry\n" \
DECLARE_INTERRUPT(253) \
DECLARE_INTERRUPT(254) \
DECLARE_INTERRUPT(255));
+
+#if defined(CONFIG_INTEL_CORE_ARCH)
+/*
+ * Get the number of CPU time counter ticks since it was read first time after
+ * restart. This yields a free running counter guaranteed to take almost 6
+ * years to wrap around even at 100GHz clock rate.
+ */
+u64 get_ticks(void)
+{
+ static u64 tick_base;
+ u64 now_tick = rdtsc();
+
+ if (!tick_base)
+ tick_base = now_tick;
+
+ return now_tick - tick_base;
+}
+
+#define PLATFORM_INFO_MSR 0xce
+
+unsigned long get_tbclk(void)
+{
+ u32 ratio;
+ u64 platform_info = native_read_msr(PLATFORM_INFO_MSR);
+
+ ratio = (platform_info >> 8) & 0xff;
+ return 100 * 1000 * 1000 * ratio; /* 100MHz times Max Non Turbo ratio */
+}
+#endif