aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86_64/kernel/hpet.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86_64/kernel/hpet.c')
-rw-r--r--arch/x86_64/kernel/hpet.c64
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 */
21int hpet_use_timer; /* Use counter of hpet for time keeping, 21int hpet_use_timer; /* Use counter of hpet for time keeping,
22 * otherwise PIT 22 * otherwise PIT
23 */ 23 */
24unsigned 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
32static __init int late_hpet_init(void) 26static __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
454static void *hpet_ptr;
455
456static cycle_t read_hpet(void)
457{
458 return (cycle_t)readl(hpet_ptr);
459}
460
461struct 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
471static 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
505module_init(init_hpet_clocksource);