|
@@ -186,7 +186,7 @@ static struct resource lapic_resource = {
|
|
|
.flags = IORESOURCE_MEM | IORESOURCE_BUSY,
|
|
|
};
|
|
|
|
|
|
-static unsigned int calibration_result;
|
|
|
+unsigned int lapic_timer_frequency = 0;
|
|
|
|
|
|
static void apic_pm_activate(void);
|
|
|
|
|
@@ -454,7 +454,7 @@ static void lapic_timer_setup(enum clock_event_mode mode,
|
|
|
switch (mode) {
|
|
|
case CLOCK_EVT_MODE_PERIODIC:
|
|
|
case CLOCK_EVT_MODE_ONESHOT:
|
|
|
- __setup_APIC_LVTT(calibration_result,
|
|
|
+ __setup_APIC_LVTT(lapic_timer_frequency,
|
|
|
mode != CLOCK_EVT_MODE_PERIODIC, 1);
|
|
|
break;
|
|
|
case CLOCK_EVT_MODE_UNUSED:
|
|
@@ -638,6 +638,25 @@ static int __init calibrate_APIC_clock(void)
|
|
|
long delta, deltatsc;
|
|
|
int pm_referenced = 0;
|
|
|
|
|
|
+ /**
|
|
|
+ * check if lapic timer has already been calibrated by platform
|
|
|
+ * specific routine, such as tsc calibration code. if so, we just fill
|
|
|
+ * in the clockevent structure and return.
|
|
|
+ */
|
|
|
+
|
|
|
+ if (lapic_timer_frequency) {
|
|
|
+ apic_printk(APIC_VERBOSE, "lapic timer already calibrated %d\n",
|
|
|
+ lapic_timer_frequency);
|
|
|
+ lapic_clockevent.mult = div_sc(lapic_timer_frequency/APIC_DIVISOR,
|
|
|
+ TICK_NSEC, lapic_clockevent.shift);
|
|
|
+ lapic_clockevent.max_delta_ns =
|
|
|
+ clockevent_delta2ns(0x7FFFFF, &lapic_clockevent);
|
|
|
+ lapic_clockevent.min_delta_ns =
|
|
|
+ clockevent_delta2ns(0xF, &lapic_clockevent);
|
|
|
+ lapic_clockevent.features &= ~CLOCK_EVT_FEAT_DUMMY;
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
local_irq_disable();
|
|
|
|
|
|
/* Replace the global interrupt handler */
|
|
@@ -679,12 +698,12 @@ static int __init calibrate_APIC_clock(void)
|
|
|
lapic_clockevent.min_delta_ns =
|
|
|
clockevent_delta2ns(0xF, &lapic_clockevent);
|
|
|
|
|
|
- calibration_result = (delta * APIC_DIVISOR) / LAPIC_CAL_LOOPS;
|
|
|
+ lapic_timer_frequency = (delta * APIC_DIVISOR) / LAPIC_CAL_LOOPS;
|
|
|
|
|
|
apic_printk(APIC_VERBOSE, "..... delta %ld\n", delta);
|
|
|
apic_printk(APIC_VERBOSE, "..... mult: %u\n", lapic_clockevent.mult);
|
|
|
apic_printk(APIC_VERBOSE, "..... calibration result: %u\n",
|
|
|
- calibration_result);
|
|
|
+ lapic_timer_frequency);
|
|
|
|
|
|
if (cpu_has_tsc) {
|
|
|
apic_printk(APIC_VERBOSE, "..... CPU clock speed is "
|
|
@@ -695,13 +714,13 @@ static int __init calibrate_APIC_clock(void)
|
|
|
|
|
|
apic_printk(APIC_VERBOSE, "..... host bus clock speed is "
|
|
|
"%u.%04u MHz.\n",
|
|
|
- calibration_result / (1000000 / HZ),
|
|
|
- calibration_result % (1000000 / HZ));
|
|
|
+ lapic_timer_frequency / (1000000 / HZ),
|
|
|
+ lapic_timer_frequency % (1000000 / HZ));
|
|
|
|
|
|
/*
|
|
|
* Do a sanity check on the APIC calibration result
|
|
|
*/
|
|
|
- if (calibration_result < (1000000 / HZ)) {
|
|
|
+ if (lapic_timer_frequency < (1000000 / HZ)) {
|
|
|
local_irq_enable();
|
|
|
pr_warning("APIC frequency too slow, disabling apic timer\n");
|
|
|
return -1;
|