aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clocksource
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/clocksource')
-rw-r--r--drivers/clocksource/acpi_pm.c36
1 files changed, 36 insertions, 0 deletions
diff --git a/drivers/clocksource/acpi_pm.c b/drivers/clocksource/acpi_pm.c
index 7fcb77a9d011..8ab61ef97b4c 100644
--- a/drivers/clocksource/acpi_pm.c
+++ b/drivers/clocksource/acpi_pm.c
@@ -142,6 +142,39 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_LE,
142 acpi_pm_check_graylist); 142 acpi_pm_check_graylist);
143#endif 143#endif
144 144
145#ifndef CONFIG_X86_64
146#include "mach_timer.h"
147#define PMTMR_EXPECTED_RATE \
148 ((CALIBRATE_LATCH * (PMTMR_TICKS_PER_SEC >> 10)) / (CLOCK_TICK_RATE>>10))
149/*
150 * Some boards have the PMTMR running way too fast. We check
151 * the PMTMR rate against PIT channel 2 to catch these cases.
152 */
153static int verify_pmtmr_rate(void)
154{
155 u32 value1, value2;
156 unsigned long count, delta;
157
158 mach_prepare_counter();
159 value1 = read_pmtmr();
160 mach_countup(&count);
161 value2 = read_pmtmr();
162 delta = (value2 - value1) & ACPI_PM_MASK;
163
164 /* Check that the PMTMR delta is within 5% of what we expect */
165 if (delta < (PMTMR_EXPECTED_RATE * 19) / 20 ||
166 delta > (PMTMR_EXPECTED_RATE * 21) / 20) {
167 printk(KERN_INFO "PM-Timer running at invalid rate: %lu%% "
168 "of normal - aborting.\n",
169 100UL * delta / PMTMR_EXPECTED_RATE);
170 return -1;
171 }
172
173 return 0;
174}
175#else
176#define verify_pmtmr_rate() (0)
177#endif
145 178
146static int __init init_acpi_pm_clocksource(void) 179static int __init init_acpi_pm_clocksource(void)
147{ 180{
@@ -173,6 +206,9 @@ static int __init init_acpi_pm_clocksource(void)
173 return -ENODEV; 206 return -ENODEV;
174 207
175pm_good: 208pm_good:
209 if (verify_pmtmr_rate() != 0)
210 return -ENODEV;
211
176 return clocksource_register(&clocksource_acpi_pm); 212 return clocksource_register(&clocksource_acpi_pm);
177} 213}
178 214