diff options
-rw-r--r-- | arch/x86/kernel/tsc.c | 56 |
1 files changed, 41 insertions, 15 deletions
diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c index aa11413e7c1d..ebb9bf824a07 100644 --- a/arch/x86/kernel/tsc.c +++ b/arch/x86/kernel/tsc.c | |||
@@ -122,6 +122,43 @@ static u64 tsc_read_refs(u64 *pm, u64 *hpet) | |||
122 | return ULLONG_MAX; | 122 | return ULLONG_MAX; |
123 | } | 123 | } |
124 | 124 | ||
125 | /* | ||
126 | * Calculate the TSC frequency from HPET reference | ||
127 | */ | ||
128 | static unsigned long calc_hpet_ref(u64 deltatsc, u64 hpet1, u64 hpet2) | ||
129 | { | ||
130 | u64 tmp; | ||
131 | |||
132 | if (hpet2 < hpet1) | ||
133 | hpet2 += 0x100000000ULL; | ||
134 | hpet2 -= hpet1; | ||
135 | tmp = ((u64)hpet2 * hpet_readl(HPET_PERIOD)); | ||
136 | do_div(tmp, 1000000); | ||
137 | do_div(deltatsc, tmp); | ||
138 | |||
139 | return (unsigned long) deltatsc; | ||
140 | } | ||
141 | |||
142 | /* | ||
143 | * Calculate the TSC frequency from PMTimer reference | ||
144 | */ | ||
145 | static unsigned long calc_pmtimer_ref(u64 deltatsc, u64 pm1, u64 pm2) | ||
146 | { | ||
147 | u64 tmp; | ||
148 | |||
149 | if (!pm1 && !pm2) | ||
150 | return ULONG_MAX; | ||
151 | |||
152 | if (pm2 < pm1) | ||
153 | pm2 += (u64)ACPI_PM_OVRRUN; | ||
154 | pm2 -= pm1; | ||
155 | tmp = pm2 * 1000000000LL; | ||
156 | do_div(tmp, PMTMR_TICKS_PER_SEC); | ||
157 | do_div(deltatsc, tmp); | ||
158 | |||
159 | return (unsigned long) deltatsc; | ||
160 | } | ||
161 | |||
125 | #define CAL_MS 50 | 162 | #define CAL_MS 50 |
126 | #define CAL_LATCH (CLOCK_TICK_RATE / (1000 / CAL_MS)) | 163 | #define CAL_LATCH (CLOCK_TICK_RATE / (1000 / CAL_MS)) |
127 | #define CAL_PIT_LOOPS 5000 | 164 | #define CAL_PIT_LOOPS 5000 |
@@ -247,22 +284,11 @@ unsigned long native_calibrate_tsc(void) | |||
247 | continue; | 284 | continue; |
248 | 285 | ||
249 | tsc2 = (tsc2 - tsc1) * 1000000LL; | 286 | tsc2 = (tsc2 - tsc1) * 1000000LL; |
287 | if (hpet) | ||
288 | tsc2 = calc_hpet_ref(tsc2, hpet1, hpet2); | ||
289 | else | ||
290 | tsc2 = calc_pmtimer_ref(tsc2, pm1, pm2); | ||
250 | 291 | ||
251 | if (hpet) { | ||
252 | if (hpet2 < hpet1) | ||
253 | hpet2 += 0x100000000ULL; | ||
254 | hpet2 -= hpet1; | ||
255 | tsc1 = ((u64)hpet2 * hpet_readl(HPET_PERIOD)); | ||
256 | do_div(tsc1, 1000000); | ||
257 | } else { | ||
258 | if (pm2 < pm1) | ||
259 | pm2 += (u64)ACPI_PM_OVRRUN; | ||
260 | pm2 -= pm1; | ||
261 | tsc1 = pm2 * 1000000000LL; | ||
262 | do_div(tsc1, PMTMR_TICKS_PER_SEC); | ||
263 | } | ||
264 | |||
265 | do_div(tsc2, tsc1); | ||
266 | tsc_ref_min = min(tsc_ref_min, (unsigned long) tsc2); | 292 | tsc_ref_min = min(tsc_ref_min, (unsigned long) tsc2); |
267 | } | 293 | } |
268 | 294 | ||