|
@@ -187,11 +187,34 @@ int __init sfi_parse_mrtc(struct sfi_table_header *table)
|
|
static unsigned long __init mrst_calibrate_tsc(void)
|
|
static unsigned long __init mrst_calibrate_tsc(void)
|
|
{
|
|
{
|
|
unsigned long flags, fast_calibrate;
|
|
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)
|
|
if (fast_calibrate)
|
|
return fast_calibrate;
|
|
return fast_calibrate;
|
|
|
|
|