Lines 42-47
Link Here
|
42 |
#include <asm/apic.h> |
42 |
#include <asm/apic.h> |
43 |
#endif |
43 |
#endif |
44 |
|
44 |
|
|
|
45 |
/* |
46 |
* timer_mult is a mutiplier used to work around some very buggy |
47 |
* hardware where the PIT timer runs way too fast. |
48 |
*/ |
49 |
u16 timer_mult = 1000; |
50 |
|
45 |
#ifdef CONFIG_CPU_FREQ |
51 |
#ifdef CONFIG_CPU_FREQ |
46 |
static void cpufreq_delayed_get(void); |
52 |
static void cpufreq_delayed_get(void); |
47 |
#endif |
53 |
#endif |
Lines 53-58
Link Here
|
53 |
|
59 |
|
54 |
static int nohpet __initdata = 0; |
60 |
static int nohpet __initdata = 0; |
55 |
static int notsc __initdata = 0; |
61 |
static int notsc __initdata = 0; |
|
|
62 |
static int use_pmtimer __initdata = 0; |
56 |
|
63 |
|
57 |
#undef HPET_HACK_ENABLE_DANGEROUS |
64 |
#undef HPET_HACK_ENABLE_DANGEROUS |
58 |
|
65 |
|
Lines 724-729
Link Here
|
724 |
outb((inb(0x61) & ~0x02) | 0x01, 0x61); |
731 |
outb((inb(0x61) & ~0x02) | 0x01, 0x61); |
725 |
|
732 |
|
726 |
outb(0xb0, 0x43); |
733 |
outb(0xb0, 0x43); |
|
|
734 |
|
735 |
/* |
736 |
* (PIT_TICK_RATE / (1000 / 50)) is 59659, |
737 |
* so we can't use the timer_mult here. |
738 |
*/ |
727 |
outb((PIT_TICK_RATE / (1000 / 50)) & 0xff, 0x42); |
739 |
outb((PIT_TICK_RATE / (1000 / 50)) & 0xff, 0x42); |
728 |
outb((PIT_TICK_RATE / (1000 / 50)) >> 8, 0x42); |
740 |
outb((PIT_TICK_RATE / (1000 / 50)) >> 8, 0x42); |
729 |
rdtscll(start); |
741 |
rdtscll(start); |
Lines 734-740
Link Here
|
734 |
|
746 |
|
735 |
spin_unlock_irqrestore(&i8253_lock, flags); |
747 |
spin_unlock_irqrestore(&i8253_lock, flags); |
736 |
|
748 |
|
737 |
return (end - start) / 50; |
749 |
/* |
|
|
750 |
* It's safer to use timer_mult on the |
751 |
* computed value. |
752 |
*/ |
753 |
return timer_mult * (end - start) / (50 * 1000); |
738 |
} |
754 |
} |
739 |
|
755 |
|
740 |
#ifdef CONFIG_HPET |
756 |
#ifdef CONFIG_HPET |
Lines 863-870
Link Here
|
863 |
|
879 |
|
864 |
spin_lock_irqsave(&i8253_lock, flags); |
880 |
spin_lock_irqsave(&i8253_lock, flags); |
865 |
outb_p(0x34, 0x43); /* binary, mode 2, LSB/MSB, ch 0 */ |
881 |
outb_p(0x34, 0x43); /* binary, mode 2, LSB/MSB, ch 0 */ |
866 |
outb_p(LATCH & 0xff, 0x40); /* LSB */ |
882 |
outb_p((LATCH * timer_mult / 1000) & 0xff, 0x40); /* LSB */ |
867 |
outb_p(LATCH >> 8, 0x40); /* MSB */ |
883 |
outb_p((LATCH * timer_mult / 1000) >> 8, 0x40); /* MSB */ |
868 |
spin_unlock_irqrestore(&i8253_lock, flags); |
884 |
spin_unlock_irqrestore(&i8253_lock, flags); |
869 |
} |
885 |
} |
870 |
|
886 |
|
Lines 909-919
Link Here
|
909 |
vxtime_hz = (1000000000000000L + hpet_period / 2) / |
925 |
vxtime_hz = (1000000000000000L + hpet_period / 2) / |
910 |
hpet_period; |
926 |
hpet_period; |
911 |
|
927 |
|
912 |
if (hpet_use_timer) { |
928 |
if (hpet_use_timer && !use_pmtimer) { |
913 |
cpu_khz = hpet_calibrate_tsc(); |
929 |
cpu_khz = hpet_calibrate_tsc(); |
914 |
timename = "HPET"; |
930 |
timename = "HPET"; |
915 |
#ifdef CONFIG_X86_PM_TIMER |
931 |
#ifdef CONFIG_X86_PM_TIMER |
916 |
} else if (pmtmr_ioport) { |
932 |
} else if ((pmtmr_ioport) && verify_pmtmr_rate(use_pmtimer)) { |
917 |
vxtime_hz = PM_TIMER_FREQUENCY; |
933 |
vxtime_hz = PM_TIMER_FREQUENCY; |
918 |
timename = "PM"; |
934 |
timename = "PM"; |
919 |
pit_init(); |
935 |
pit_init(); |
Lines 1302-1305
Link Here
|
1302 |
|
1318 |
|
1303 |
__setup("notsc", notsc_setup); |
1319 |
__setup("notsc", notsc_setup); |
1304 |
|
1320 |
|
|
|
1321 |
static int __init pmtmr_setup(char *s) |
1322 |
{ |
1323 |
use_pmtimer = 1; |
1324 |
return 0; |
1325 |
} |
1326 |
|
1327 |
__setup("pmtmr", pmtmr_setup); |
1328 |
|
1329 |
|
1305 |
|
1330 |
|