Pull video into test branch
[linux-drm-fsl-dcu.git] / arch / i386 / kernel / hpet.c
1 #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
9 #define HPET_MASK       CLOCKSOURCE_MASK(32)
10 #define HPET_SHIFT      22
11
12 /* FSEC = 10^-15 NSEC = 10^-9 */
13 #define FSEC_PER_NSEC   1000000
14
15 static void *hpet_ptr;
16
17 static cycle_t read_hpet(void)
18 {
19         return (cycle_t)readl(hpet_ptr);
20 }
21
22 static struct clocksource clocksource_hpet = {
23         .name           = "hpet",
24         .rating         = 250,
25         .read           = read_hpet,
26         .mask           = HPET_MASK,
27         .mult           = 0, /* set below */
28         .shift          = HPET_SHIFT,
29         .is_continuous  = 1,
30 };
31
32 static int __init init_hpet_clocksource(void)
33 {
34         unsigned long hpet_period;
35         void __iomem* hpet_base;
36         u64 tmp;
37         int err;
38
39         if (!is_hpet_enabled())
40                 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
65         err = clocksource_register(&clocksource_hpet);
66         if (err)
67                 iounmap(hpet_base);
68
69         return err;
70 }
71
72 module_init(init_hpet_clocksource);