blob: 45a8685bb60bb5e21e638cd6c0b6df95586606f2 [file] [log] [blame]
john stultz5d0cf412006-06-26 00:25:12 -07001#include <linux/clocksource.h>
2#include <linux/errno.h>
3#include <linux/hpet.h>
4#include <linux/init.h>
5
6#include <asm/hpet.h>
7#include <asm/io.h>
8
Jim Cromie7f9f3032006-06-26 00:25:15 -07009#define HPET_MASK CLOCKSOURCE_MASK(32)
john stultz5d0cf412006-06-26 00:25:12 -070010#define HPET_SHIFT 22
11
12/* FSEC = 10^-15 NSEC = 10^-9 */
13#define FSEC_PER_NSEC 1000000
14
15static void *hpet_ptr;
16
17static cycle_t read_hpet(void)
18{
19 return (cycle_t)readl(hpet_ptr);
20}
21
22static struct clocksource clocksource_hpet = {
23 .name = "hpet",
24 .rating = 250,
25 .read = read_hpet,
Jim Cromie7f9f3032006-06-26 00:25:15 -070026 .mask = HPET_MASK,
john stultz5d0cf412006-06-26 00:25:12 -070027 .mult = 0, /* set below */
28 .shift = HPET_SHIFT,
29 .is_continuous = 1,
30};
31
32static int __init init_hpet_clocksource(void)
33{
34 unsigned long hpet_period;
35 void __iomem* hpet_base;
36 u64 tmp;
Amol Ladfa5cecd2006-12-07 02:14:02 +010037 int err;
john stultz5d0cf412006-06-26 00:25:12 -070038
john stultz30f31742006-08-31 21:27:37 -070039 if (!is_hpet_enabled())
john stultz5d0cf412006-06-26 00:25:12 -070040 return -ENODEV;
41
42 /* calculate the hpet address: */
43 hpet_base =
44 (void __iomem*)ioremap_nocache(hpet_address, HPET_MMAP_SIZE);
45 hpet_ptr = hpet_base + HPET_COUNTER;
46
47 /* calculate the frequency: */
48 hpet_period = readl(hpet_base + HPET_PERIOD);
49
50 /*
51 * hpet period is in femto seconds per cycle
52 * so we need to convert this to ns/cyc units
53 * aproximated by mult/2^shift
54 *
55 * fsec/cyc * 1nsec/1000000fsec = nsec/cyc = mult/2^shift
56 * fsec/cyc * 1ns/1000000fsec * 2^shift = mult
57 * fsec/cyc * 2^shift * 1nsec/1000000fsec = mult
58 * (fsec/cyc << shift)/1000000 = mult
59 * (hpet_period << shift)/FSEC_PER_NSEC = mult
60 */
61 tmp = (u64)hpet_period << HPET_SHIFT;
62 do_div(tmp, FSEC_PER_NSEC);
63 clocksource_hpet.mult = (u32)tmp;
64
Amol Ladfa5cecd2006-12-07 02:14:02 +010065 err = clocksource_register(&clocksource_hpet);
66 if (err)
67 iounmap(hpet_base);
68
69 return err;
john stultz5d0cf412006-06-26 00:25:12 -070070}
71
72module_init(init_hpet_clocksource);