aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86_64/kernel/pmtimer.c
diff options
context:
space:
mode:
authorAndi Kleen <ak@suse.de>2006-02-03 15:51:41 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-02-04 19:43:15 -0500
commit0c3749c41f5eee0da36bbf92b2793338b4d8574f (patch)
tree3af004c5533ab04297004f5ec40da4c6801b8fda /arch/x86_64/kernel/pmtimer.c
parent099f318b8d97490e58c595eb1b6d3415da5ccc03 (diff)
[PATCH] x86_64: Calibrate APIC timer using PM timer
On some broken motherboards (at least one NForce3 based AMD64 laptop) the PIT timer runs at a incorrect frequency. This patch adds a new option "apicpmtimer" that allows to use the APIC timer and calibrate it using the PMTimer. It requires the earlier patch that allows to run the main timer from the APIC. Specifying apicpmtimer implies apicmaintimer. The option defaults to off for now. I tested it on a few systems and the resulting APIC timer frequencies were usually a bit off, but always <1%, which should be tolerable. TBD figure out heuristic to enable this automatically on the affected systems TBD perhaps do it on all NForce3s or using DMI? Signed-off-by: Andi Kleen <ak@suse.de> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/x86_64/kernel/pmtimer.c')
-rw-r--r--arch/x86_64/kernel/pmtimer.c20
1 files changed, 20 insertions, 0 deletions
diff --git a/arch/x86_64/kernel/pmtimer.c b/arch/x86_64/kernel/pmtimer.c
index 8b2655ae4e61..5c51d10408a6 100644
--- a/arch/x86_64/kernel/pmtimer.c
+++ b/arch/x86_64/kernel/pmtimer.c
@@ -80,6 +80,26 @@ int pmtimer_mark_offset(void)
80 return lost - 1; 80 return lost - 1;
81} 81}
82 82
83static unsigned pmtimer_wait_tick(void)
84{
85 u32 a, b;
86 for (a = b = inl(pmtmr_ioport) & ACPI_PM_MASK;
87 a == b;
88 b = inl(pmtmr_ioport) & ACPI_PM_MASK)
89 ;
90 return b;
91}
92
93/* note: wait time is rounded up to one tick */
94void pmtimer_wait(unsigned us)
95{
96 u32 a, b;
97 a = pmtimer_wait_tick();
98 do {
99 b = inl(pmtmr_ioport);
100 } while (cyc2us(b - a) < us);
101}
102
83void pmtimer_resume(void) 103void pmtimer_resume(void)
84{ 104{
85 last_pmtmr_tick = inl(pmtmr_ioport); 105 last_pmtmr_tick = inl(pmtmr_ioport);