static int __init calibrate_APIC_clock(void) { int apic, apic_start, tsc, tsc_start; int result; u64 wallclock_nsecs; /* * Put whatever arbitrary (but long enough) timeout * value into the APIC clock, we just want to get the * counter running for calibration. */ __setup_APIC_LVTT(1000000000, 0); apic_start = apic_read(APIC_TMCCT); #ifdef CONFIG_X86_PM_TIMER if (apic_calibrate_pmtmr && pmtmr_ioport) { pmtimer_wait(5000); /* 5ms wait */ apic = apic_read(APIC_TMCCT); result = (apic_start - apic) * 1000L / 5; printk("using pmtimer for lapic calibration\n"); wallclock_nsecs = 5000000; } else #endif { rdtscl(tsc_start); do { apic = apic_read(APIC_TMCCT); rdtscl(tsc); } while ((tsc - tsc_start) < TICK_COUNT && (apic - apic_start) < TICK_COUNT); result = (apic_start - apic) * 1000L * cpu_khz / (tsc - tsc_start); wallclock_nsecs = ((u64)tsc - (u64)tsc_start) * 1000000 / (u64)cpu_khz; } printk("result %d\n", result); printk(KERN_INFO "Detected %d.%03d MHz APIC timer.\n", result / 1000 / 1000, result / 1000 % 1000); /* Calculate the scaled math multiplication factor */ lapic_clockevent.mult = div_sc(apic_start - apic, wallclock_nsecs, 32); lapic_clockevent.max_delta_ns = clockevent_delta2ns(0x7FFFFF, &lapic_clockevent); printk("lapic max_delta_ns: %ld\n", lapic_clockevent.max_delta_ns); lapic_clockevent.min_delta_ns = clockevent_delta2ns(0xF, &lapic_clockevent); return result * APIC_DIVISOR / HZ; }
static void __init calibrate_APIC_clock(void) { unsigned apic, apic_start; unsigned long tsc, tsc_start; int result; local_irq_disable(); /* * Put whatever arbitrary (but long enough) timeout * value into the APIC clock, we just want to get the * counter running for calibration. * * No interrupt enable ! */ __setup_APIC_LVTT(250000000, 0, 0); apic_start = apic_read(APIC_TMCCT); #ifdef CONFIG_X86_PM_TIMER if (apic_calibrate_pmtmr && pmtmr_ioport) { pmtimer_wait(5000); /* 5ms wait */ apic = apic_read(APIC_TMCCT); result = (apic_start - apic) * 1000L / 5; } else #endif { rdtscll(tsc_start); do { apic = apic_read(APIC_TMCCT); rdtscll(tsc); } while ((tsc - tsc_start) < TICK_COUNT && (apic_start - apic) < TICK_COUNT); result = (apic_start - apic) * 1000L * tsc_khz / (tsc - tsc_start); } local_irq_enable(); printk(KERN_DEBUG "APIC timer calibration result %d\n", result); printk(KERN_INFO "Detected %d.%03d MHz APIC timer.\n", result / 1000 / 1000, result / 1000 % 1000); /* Calculate the scaled math multiplication factor */ lapic_clockevent.mult = div_sc(result, NSEC_PER_SEC, 32); lapic_clockevent.max_delta_ns = clockevent_delta2ns(0x7FFFFF, &lapic_clockevent); lapic_clockevent.min_delta_ns = clockevent_delta2ns(0xF, &lapic_clockevent); calibration_result = result / HZ; }
static int __init calibrate_APIC_clock(void) { unsigned apic, apic_start; unsigned long tsc, tsc_start; int result; /* * Put whatever arbitrary (but long enough) timeout * value into the APIC clock, we just want to get the * counter running for calibration. */ __setup_APIC_LVTT(4000000000); apic_start = apic_read(APIC_TMCCT); #ifdef CONFIG_X86_PM_TIMER if (apic_calibrate_pmtmr && pmtmr_ioport) { pmtimer_wait(5000); /* 5ms wait */ apic = apic_read(APIC_TMCCT); result = (apic_start - apic) * 1000L / 5; } else #endif { rdtscll(tsc_start); do { apic = apic_read(APIC_TMCCT); rdtscll(tsc); } while ((tsc - tsc_start) < TICK_COUNT && (apic_start - apic) < TICK_COUNT); result = (apic_start - apic) * 1000L * tsc_khz / (tsc - tsc_start); } printk("result %d\n", result); printk(KERN_INFO "Detected %d.%03d MHz APIC timer.\n", result / 1000 / 1000, result / 1000 % 1000); return result * APIC_DIVISOR / HZ; }