Patchwork [U-Boot,v2,14/21] x86: Provide tick counter and frequency reference for Intel core architecture

login
register
mail settings
Submitter Simon Glass
Date Dec. 3, 2012, 11:59 p.m.
Message ID <1354579160-2410-1-git-send-email-sjg@chromium.org>
Download mbox | patch
Permalink /patch/203506/
State Accepted, archived
Delegated to: Simon Glass
Headers show

Comments

Simon Glass - Dec. 3, 2012, 11:59 p.m.
From: Vadim Bendebury <vbendeb@chromium.org>

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>
---
Changes in v2:
- Use functions from Graeme's msr patch

 arch/x86/cpu/interrupts.c |   31 +++++++++++++++++++++++++++++++
 1 files changed, 31 insertions(+), 0 deletions(-)

Patch

diff --git a/arch/x86/cpu/interrupts.c b/arch/x86/cpu/interrupts.c
index e788715..dd30a05 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