int apic_verbosity;
 int apic_runs_main_timer;
+int apic_calibrate_pmtmr __initdata;
 
 int disable_apic_timer __initdata;
 
        __setup_APIC_LVTT(1000000000);
 
        apic_start = apic_read(APIC_TMCCT);
-       rdtscl(tsc_start);
-
-       do {
+#ifdef CONFIG_X86_PM_TIMER
+       if (apic_calibrate_pmtmr && pmtmr_ioport) {
+               pmtimer_wait(5000);  /* 5ms wait */
                apic = apic_read(APIC_TMCCT);
-               rdtscl(tsc);
-       } while ((tsc - tsc_start) < TICK_COUNT && (apic - apic_start) < TICK_COUNT);
+               result = (apic_start - apic) * 1000L / 5;
+       } 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);
+       }
+       printk("result %d\n", result);
 
-       result = (apic_start - apic) * 1000L * cpu_khz / (tsc - tsc_start);
 
        printk(KERN_INFO "Detected %d.%03d MHz APIC timer.\n",
                result / 1000 / 1000, result / 1000 % 1000);
 }
 __setup("noapicmaintimer", setup_noapicmaintimer);
 
+static __init int setup_apicpmtimer(char *s)
+{
+       apic_calibrate_pmtmr = 1;
+       return setup_apicmaintimer(NULL);
+}
+__setup("apicpmtimer", setup_apicpmtimer);
+
 /* dummy parsing: see setup.c */
 
 __setup("disableapic", setup_disableapic); 
 
        return lost - 1;
 }
 
+static unsigned pmtimer_wait_tick(void)
+{
+       u32 a, b;
+       for (a = b = inl(pmtmr_ioport) & ACPI_PM_MASK;
+            a == b;
+            b = inl(pmtmr_ioport) & ACPI_PM_MASK)
+               ;
+       return b;
+}
+
+/* note: wait time is rounded up to one tick */
+void pmtimer_wait(unsigned us)
+{
+       u32 a, b;
+       a = pmtimer_wait_tick();
+       do {
+               b = inl(pmtmr_ioport);
+       } while (cyc2us(b - a) < us);
+}
+
 void pmtimer_resume(void)
 {
        last_pmtmr_tick = inl(pmtmr_ioport);
 
 extern void time_init_gtod(void);
 extern int pmtimer_mark_offset(void);
 extern void pmtimer_resume(void);
+extern void pmtimer_wait(unsigned);
 extern unsigned int do_gettimeoffset_pm(void);
 #ifdef CONFIG_X86_PM_TIMER
 extern u32 pmtmr_ioport;