aboutsummaryrefslogtreecommitdiff
path: root/src/cpu/x86/lapic/apic_timer.c
diff options
context:
space:
mode:
authorStefan Reinauer <reinauer@chromium.org>2012-04-03 16:11:02 -0700
committerStefan Reinauer <stefan.reinauer@coreboot.org>2012-04-05 23:35:13 +0200
commit5b6404e4195157eac8d97ae5bf30f45612109d57 (patch)
tree8e6998db4f8b3c98876b610882596ba67c9a152c /src/cpu/x86/lapic/apic_timer.c
parentcab72d9b7b4bec1ee9464ed565edf7b192ef5c69 (diff)
Fix timer frequency detection on Sandybridge
Change-Id: Ide720bd91cde56a0afdd231d93500c371b1ffbe8 Signed-off-by: Duncan Laurie <dlaurie@google.com> Signed-off-by: Stefan Reinauer <reinauer@google.com> Reviewed-on: http://review.coreboot.org/870 Reviewed-by: Ronald G. Minnich <rminnich@gmail.com> Tested-by: build bot (Jenkins)
Diffstat (limited to 'src/cpu/x86/lapic/apic_timer.c')
-rw-r--r--src/cpu/x86/lapic/apic_timer.c48
1 files changed, 36 insertions, 12 deletions
diff --git a/src/cpu/x86/lapic/apic_timer.c b/src/cpu/x86/lapic/apic_timer.c
index 826f5b6ad4..bb6cca7d9a 100644
--- a/src/cpu/x86/lapic/apic_timer.c
+++ b/src/cpu/x86/lapic/apic_timer.c
@@ -20,6 +20,7 @@
#include <stdint.h>
#include <delay.h>
+#include <arch/cpu.h>
#include <cpu/x86/msr.h>
#include <cpu/x86/lapic.h>
@@ -27,14 +28,40 @@
* memory init.
*/
-#define FSB_CLOCK_STS 0xcd
+static u32 timer_fsb = 0;
-static u32 timer_fsb = 200; // default to 200MHz
+static int set_timer_fsb(void)
+{
+ struct cpuinfo_x86 c;
+ int core_fsb[8] = { -1, 133, -1, 166, -1, 100, -1, -1 };
+ int core2_fsb[8] = { 266, 133, 200, 166, -1, 100, -1, -1 };
+
+ get_fms(&c, cpuid_eax(1));
+ if (c.x86 != 6)
+ return -1;
+
+ switch (c.x86_model) {
+ case 0xe: /* Core Solo/Duo */
+ case 0x1c: /* Atom */
+ timer_fsb = core_fsb[rdmsr(0xcd).lo & 7];
+ break;
+ case 0xf: /* Core 2*/
+ case 0x17: /* Enhanced Core */
+ timer_fsb = core2_fsb[rdmsr(0xcd).lo & 7];
+ break;
+ case 0x2a: /* SandyBridge BCLK fixed at 100MHz*/
+ timer_fsb = 100;
+ break;
+ default:
+ timer_fsb = 200;
+ break;
+ }
+
+ return 0;
+}
void init_timer(void)
{
- msr_t fsb_clock_sts;
-
/* Set the apic timer to no interrupts and periodic mode */
lapic_write(LAPIC_LVTT, (LAPIC_LVT_TIMER_PERIODIC | LAPIC_LVT_MASKED));
@@ -45,19 +72,16 @@ void init_timer(void)
lapic_write(LAPIC_TMICT, 0xffffffff);
/* Set FSB frequency to a reasonable value */
- fsb_clock_sts = rdmsr(FSB_CLOCK_STS);
- switch ((fsb_clock_sts.lo >> 4) & 0x07) {
- case 0: timer_fsb = 266; break;
- case 1: timer_fsb = 133; break;
- case 2: timer_fsb = 200; break;
- case 3: timer_fsb = 166; break;
- case 5: timer_fsb = 100; break;
- }
+ set_timer_fsb();
}
void udelay(u32 usecs)
{
u32 start, value, ticks;
+
+ if (!timer_fsb)
+ init_timer();
+
/* Calculate the number of ticks to run, our FSB runs at timer_fsb Mhz */
ticks = usecs * timer_fsb;
start = lapic_read(LAPIC_TMCCT);