summaryrefslogtreecommitdiff
path: root/arch/x86/platform/mrst
diff options
context:
space:
mode:
authorDirk Brandewie <dirk.brandewie@gmail.com>2011-11-10 17:42:53 +0400
committerIngo Molnar <mingo@elte.hu>2011-11-10 19:20:59 +0400
commit0a9153261d54c432bc0bdc88607f24c835ac729c (patch)
tree25fe6a310d3f3ecb9f873c8e49c852f1f4c5abe1 /arch/x86/platform/mrst
parent1ade93efd0a3dda5b0c0afda8ab8f4bd12938c1b (diff)
downloadlinux-0a9153261d54c432bc0bdc88607f24c835ac729c.tar.xz
x86/mrst: Add support for Penwell clock calibration
Signed-off-by: Dirk Brandewie <dirk.brandewie@gmail.com> Signed-off-by: Alan Cox <alan@linux.intel.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/platform/mrst')
-rw-r--r--arch/x86/platform/mrst/mrst.c33
1 files changed, 28 insertions, 5 deletions
diff --git a/arch/x86/platform/mrst/mrst.c b/arch/x86/platform/mrst/mrst.c
index 6ed7afdaf4af..b7f14e5b2c66 100644
--- a/arch/x86/platform/mrst/mrst.c
+++ b/arch/x86/platform/mrst/mrst.c
@@ -187,11 +187,34 @@ int __init sfi_parse_mrtc(struct sfi_table_header *table)
static unsigned long __init mrst_calibrate_tsc(void)
{
unsigned long flags, fast_calibrate;
-
- local_irq_save(flags);
- fast_calibrate = apbt_quick_calibrate();
- local_irq_restore(flags);
-
+ if (__mrst_cpu_chip == MRST_CPU_CHIP_PENWELL) {
+ u32 lo, hi, ratio, fsb;
+
+ rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
+ pr_debug("IA32 perf status is 0x%x, 0x%0x\n", lo, hi);
+ ratio = (hi >> 8) & 0x1f;
+ pr_debug("ratio is %d\n", ratio);
+ if (!ratio) {
+ pr_err("read a zero ratio, should be incorrect!\n");
+ pr_err("force tsc ratio to 16 ...\n");
+ ratio = 16;
+ }
+ rdmsr(MSR_FSB_FREQ, lo, hi);
+ if ((lo & 0x7) == 0x7)
+ fsb = PENWELL_FSB_FREQ_83SKU;
+ else
+ fsb = PENWELL_FSB_FREQ_100SKU;
+ fast_calibrate = ratio * fsb;
+ pr_debug("read penwell tsc %lu khz\n", fast_calibrate);
+ lapic_timer_frequency = fsb * 1000 / HZ;
+ /* mark tsc clocksource as reliable */
+ set_cpu_cap(&boot_cpu_data, X86_FEATURE_TSC_RELIABLE);
+ } else {
+ local_irq_save(flags);
+ fast_calibrate = apbt_quick_calibrate();
+ local_irq_restore(flags);
+ }
+
if (fast_calibrate)
return fast_calibrate;