diff options
author | Ingo Molnar <mingo@elte.hu> | 2008-09-14 12:24:00 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-09-14 12:24:00 -0400 |
commit | 83bd6998b04fc1bb7280b14f16b2bdbdc07c914b (patch) | |
tree | af1bbe2bac5752b69b1ac58bf5d822c735da439b /arch/x86/kernel/hpet.c | |
parent | e7250b8ae3870f37f660c2f65cafcaba85e3bfd3 (diff) | |
parent | adee14b2e1557d0a8559f29681732d05a89dfc35 (diff) |
Merge commit 'v2.6.27-rc6' into timers/hpet
Diffstat (limited to 'arch/x86/kernel/hpet.c')
-rw-r--r-- | arch/x86/kernel/hpet.c | 43 |
1 files changed, 37 insertions, 6 deletions
diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c index 82d459186fd8..acf62fc233da 100644 --- a/arch/x86/kernel/hpet.c +++ b/arch/x86/kernel/hpet.c | |||
@@ -214,8 +214,8 @@ static void hpet_legacy_clockevent_register(void) | |||
214 | /* Calculate the min / max delta */ | 214 | /* Calculate the min / max delta */ |
215 | hpet_clockevent.max_delta_ns = clockevent_delta2ns(0x7FFFFFFF, | 215 | hpet_clockevent.max_delta_ns = clockevent_delta2ns(0x7FFFFFFF, |
216 | &hpet_clockevent); | 216 | &hpet_clockevent); |
217 | hpet_clockevent.min_delta_ns = clockevent_delta2ns(0x30, | 217 | /* 5 usec minimum reprogramming delta. */ |
218 | &hpet_clockevent); | 218 | hpet_clockevent.min_delta_ns = 5000; |
219 | 219 | ||
220 | /* | 220 | /* |
221 | * Start hpet with the boot cpu mask and make it | 221 | * Start hpet with the boot cpu mask and make it |
@@ -274,15 +274,22 @@ static void hpet_legacy_set_mode(enum clock_event_mode mode, | |||
274 | } | 274 | } |
275 | 275 | ||
276 | static int hpet_legacy_next_event(unsigned long delta, | 276 | static int hpet_legacy_next_event(unsigned long delta, |
277 | struct clock_event_device *evt) | 277 | struct clock_event_device *evt) |
278 | { | 278 | { |
279 | unsigned long cnt; | 279 | u32 cnt; |
280 | 280 | ||
281 | cnt = hpet_readl(HPET_COUNTER); | 281 | cnt = hpet_readl(HPET_COUNTER); |
282 | cnt += delta; | 282 | cnt += (u32) delta; |
283 | hpet_writel(cnt, HPET_T0_CMP); | 283 | hpet_writel(cnt, HPET_T0_CMP); |
284 | 284 | ||
285 | return ((long)(hpet_readl(HPET_COUNTER) - cnt ) > 0) ? -ETIME : 0; | 285 | /* |
286 | * We need to read back the CMP register to make sure that | ||
287 | * what we wrote hit the chip before we compare it to the | ||
288 | * counter. | ||
289 | */ | ||
290 | WARN_ON((u32)hpet_readl(HPET_T0_CMP) != cnt); | ||
291 | |||
292 | return (s32)((u32)hpet_readl(HPET_COUNTER) - cnt) >= 0 ? -ETIME : 0; | ||
286 | } | 293 | } |
287 | 294 | ||
288 | /* | 295 | /* |
@@ -363,6 +370,7 @@ static int hpet_clocksource_register(void) | |||
363 | int __init hpet_enable(void) | 370 | int __init hpet_enable(void) |
364 | { | 371 | { |
365 | unsigned long id; | 372 | unsigned long id; |
373 | int i; | ||
366 | 374 | ||
367 | if (!is_hpet_capable()) | 375 | if (!is_hpet_capable()) |
368 | return 0; | 376 | return 0; |
@@ -373,6 +381,29 @@ int __init hpet_enable(void) | |||
373 | * Read the period and check for a sane value: | 381 | * Read the period and check for a sane value: |
374 | */ | 382 | */ |
375 | hpet_period = hpet_readl(HPET_PERIOD); | 383 | hpet_period = hpet_readl(HPET_PERIOD); |
384 | |||
385 | /* | ||
386 | * AMD SB700 based systems with spread spectrum enabled use a | ||
387 | * SMM based HPET emulation to provide proper frequency | ||
388 | * setting. The SMM code is initialized with the first HPET | ||
389 | * register access and takes some time to complete. During | ||
390 | * this time the config register reads 0xffffffff. We check | ||
391 | * for max. 1000 loops whether the config register reads a non | ||
392 | * 0xffffffff value to make sure that HPET is up and running | ||
393 | * before we go further. A counting loop is safe, as the HPET | ||
394 | * access takes thousands of CPU cycles. On non SB700 based | ||
395 | * machines this check is only done once and has no side | ||
396 | * effects. | ||
397 | */ | ||
398 | for (i = 0; hpet_readl(HPET_CFG) == 0xFFFFFFFF; i++) { | ||
399 | if (i == 1000) { | ||
400 | printk(KERN_WARNING | ||
401 | "HPET config register value = 0xFFFFFFFF. " | ||
402 | "Disabling HPET\n"); | ||
403 | goto out_nohpet; | ||
404 | } | ||
405 | } | ||
406 | |||
376 | if (hpet_period < HPET_MIN_PERIOD || hpet_period > HPET_MAX_PERIOD) | 407 | if (hpet_period < HPET_MIN_PERIOD || hpet_period > HPET_MAX_PERIOD) |
377 | goto out_nohpet; | 408 | goto out_nohpet; |
378 | 409 | ||