diff options
Diffstat (limited to 'arch/x86_64/kernel/hpet.c')
-rw-r--r-- | arch/x86_64/kernel/hpet.c | 64 |
1 files changed, 58 insertions, 6 deletions
diff --git a/arch/x86_64/kernel/hpet.c b/arch/x86_64/kernel/hpet.c index 08ab37c966c2..c23738899ae9 100644 --- a/arch/x86_64/kernel/hpet.c +++ b/arch/x86_64/kernel/hpet.c | |||
@@ -21,12 +21,6 @@ unsigned long hpet_tick; /* HPET clocks / interrupt */ | |||
21 | int hpet_use_timer; /* Use counter of hpet for time keeping, | 21 | int hpet_use_timer; /* Use counter of hpet for time keeping, |
22 | * otherwise PIT | 22 | * otherwise PIT |
23 | */ | 23 | */ |
24 | unsigned int do_gettimeoffset_hpet(void) | ||
25 | { | ||
26 | /* cap counter read to one tick to avoid inconsistencies */ | ||
27 | unsigned long counter = hpet_readl(HPET_COUNTER) - vxtime.last; | ||
28 | return (min(counter,hpet_tick) * vxtime.quot) >> US_SCALE; | ||
29 | } | ||
30 | 24 | ||
31 | #ifdef CONFIG_HPET | 25 | #ifdef CONFIG_HPET |
32 | static __init int late_hpet_init(void) | 26 | static __init int late_hpet_init(void) |
@@ -451,3 +445,61 @@ static int __init nohpet_setup(char *s) | |||
451 | 445 | ||
452 | __setup("nohpet", nohpet_setup); | 446 | __setup("nohpet", nohpet_setup); |
453 | 447 | ||
448 | #define HPET_MASK 0xFFFFFFFF | ||
449 | #define HPET_SHIFT 22 | ||
450 | |||
451 | /* FSEC = 10^-15 NSEC = 10^-9 */ | ||
452 | #define FSEC_PER_NSEC 1000000 | ||
453 | |||
454 | static void *hpet_ptr; | ||
455 | |||
456 | static cycle_t read_hpet(void) | ||
457 | { | ||
458 | return (cycle_t)readl(hpet_ptr); | ||
459 | } | ||
460 | |||
461 | struct clocksource clocksource_hpet = { | ||
462 | .name = "hpet", | ||
463 | .rating = 250, | ||
464 | .read = read_hpet, | ||
465 | .mask = (cycle_t)HPET_MASK, | ||
466 | .mult = 0, /* set below */ | ||
467 | .shift = HPET_SHIFT, | ||
468 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | ||
469 | }; | ||
470 | |||
471 | static int __init init_hpet_clocksource(void) | ||
472 | { | ||
473 | unsigned long hpet_period; | ||
474 | void __iomem *hpet_base; | ||
475 | u64 tmp; | ||
476 | |||
477 | if (!hpet_address) | ||
478 | return -ENODEV; | ||
479 | |||
480 | /* calculate the hpet address: */ | ||
481 | hpet_base = ioremap_nocache(hpet_address, HPET_MMAP_SIZE); | ||
482 | hpet_ptr = hpet_base + HPET_COUNTER; | ||
483 | |||
484 | /* calculate the frequency: */ | ||
485 | hpet_period = readl(hpet_base + HPET_PERIOD); | ||
486 | |||
487 | /* | ||
488 | * hpet period is in femto seconds per cycle | ||
489 | * so we need to convert this to ns/cyc units | ||
490 | * aproximated by mult/2^shift | ||
491 | * | ||
492 | * fsec/cyc * 1nsec/1000000fsec = nsec/cyc = mult/2^shift | ||
493 | * fsec/cyc * 1ns/1000000fsec * 2^shift = mult | ||
494 | * fsec/cyc * 2^shift * 1nsec/1000000fsec = mult | ||
495 | * (fsec/cyc << shift)/1000000 = mult | ||
496 | * (hpet_period << shift)/FSEC_PER_NSEC = mult | ||
497 | */ | ||
498 | tmp = (u64)hpet_period << HPET_SHIFT; | ||
499 | do_div(tmp, FSEC_PER_NSEC); | ||
500 | clocksource_hpet.mult = (u32)tmp; | ||
501 | |||
502 | return clocksource_register(&clocksource_hpet); | ||
503 | } | ||
504 | |||
505 | module_init(init_hpet_clocksource); | ||