|
@@ -12,6 +12,12 @@
|
|
#include <asm/timex.h>
|
|
#include <asm/timex.h>
|
|
#include <asm/hpet.h>
|
|
#include <asm/hpet.h>
|
|
|
|
|
|
|
|
+#define HPET_MASK 0xFFFFFFFF
|
|
|
|
+#define HPET_SHIFT 22
|
|
|
|
+
|
|
|
|
+/* FSEC = 10^-15 NSEC = 10^-9 */
|
|
|
|
+#define FSEC_PER_NSEC 1000000
|
|
|
|
+
|
|
int nohpet __initdata;
|
|
int nohpet __initdata;
|
|
|
|
|
|
unsigned long hpet_address;
|
|
unsigned long hpet_address;
|
|
@@ -106,9 +112,31 @@ int hpet_timer_stop_set_go(unsigned long tick)
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static cycle_t read_hpet(void)
|
|
|
|
+{
|
|
|
|
+ return (cycle_t)hpet_readl(HPET_COUNTER);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static cycle_t __vsyscall_fn vread_hpet(void)
|
|
|
|
+{
|
|
|
|
+ return readl((void __iomem *)fix_to_virt(VSYSCALL_HPET) + 0xf0);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+struct clocksource clocksource_hpet = {
|
|
|
|
+ .name = "hpet",
|
|
|
|
+ .rating = 250,
|
|
|
|
+ .read = read_hpet,
|
|
|
|
+ .mask = (cycle_t)HPET_MASK,
|
|
|
|
+ .mult = 0, /* set below */
|
|
|
|
+ .shift = HPET_SHIFT,
|
|
|
|
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
|
|
|
|
+ .vread = vread_hpet,
|
|
|
|
+};
|
|
|
|
+
|
|
int hpet_arch_init(void)
|
|
int hpet_arch_init(void)
|
|
{
|
|
{
|
|
unsigned int id;
|
|
unsigned int id;
|
|
|
|
+ u64 tmp;
|
|
|
|
|
|
if (!hpet_address)
|
|
if (!hpet_address)
|
|
return -1;
|
|
return -1;
|
|
@@ -132,6 +160,22 @@ int hpet_arch_init(void)
|
|
|
|
|
|
hpet_use_timer = (id & HPET_ID_LEGSUP);
|
|
hpet_use_timer = (id & HPET_ID_LEGSUP);
|
|
|
|
|
|
|
|
+ /*
|
|
|
|
+ * hpet period is in femto seconds per cycle
|
|
|
|
+ * so we need to convert this to ns/cyc units
|
|
|
|
+ * aproximated by mult/2^shift
|
|
|
|
+ *
|
|
|
|
+ * fsec/cyc * 1nsec/1000000fsec = nsec/cyc = mult/2^shift
|
|
|
|
+ * fsec/cyc * 1ns/1000000fsec * 2^shift = mult
|
|
|
|
+ * fsec/cyc * 2^shift * 1nsec/1000000fsec = mult
|
|
|
|
+ * (fsec/cyc << shift)/1000000 = mult
|
|
|
|
+ * (hpet_period << shift)/FSEC_PER_NSEC = mult
|
|
|
|
+ */
|
|
|
|
+ tmp = (u64)hpet_period << HPET_SHIFT;
|
|
|
|
+ do_div(tmp, FSEC_PER_NSEC);
|
|
|
|
+ clocksource_hpet.mult = (u32)tmp;
|
|
|
|
+ clocksource_register(&clocksource_hpet);
|
|
|
|
+
|
|
return hpet_timer_stop_set_go(hpet_tick);
|
|
return hpet_timer_stop_set_go(hpet_tick);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -444,68 +488,3 @@ static int __init nohpet_setup(char *s)
|
|
}
|
|
}
|
|
|
|
|
|
__setup("nohpet", nohpet_setup);
|
|
__setup("nohpet", nohpet_setup);
|
|
-
|
|
|
|
-#define HPET_MASK 0xFFFFFFFF
|
|
|
|
-#define HPET_SHIFT 22
|
|
|
|
-
|
|
|
|
-/* FSEC = 10^-15 NSEC = 10^-9 */
|
|
|
|
-#define FSEC_PER_NSEC 1000000
|
|
|
|
-
|
|
|
|
-static void *hpet_ptr;
|
|
|
|
-
|
|
|
|
-static cycle_t read_hpet(void)
|
|
|
|
-{
|
|
|
|
- return (cycle_t)readl(hpet_ptr);
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static cycle_t __vsyscall_fn vread_hpet(void)
|
|
|
|
-{
|
|
|
|
- return readl((void __iomem *)fix_to_virt(VSYSCALL_HPET) + 0xf0);
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-struct clocksource clocksource_hpet = {
|
|
|
|
- .name = "hpet",
|
|
|
|
- .rating = 250,
|
|
|
|
- .read = read_hpet,
|
|
|
|
- .mask = (cycle_t)HPET_MASK,
|
|
|
|
- .mult = 0, /* set below */
|
|
|
|
- .shift = HPET_SHIFT,
|
|
|
|
- .flags = CLOCK_SOURCE_IS_CONTINUOUS,
|
|
|
|
- .vread = vread_hpet,
|
|
|
|
-};
|
|
|
|
-
|
|
|
|
-static int __init init_hpet_clocksource(void)
|
|
|
|
-{
|
|
|
|
- unsigned long hpet_period;
|
|
|
|
- void __iomem *hpet_base;
|
|
|
|
- u64 tmp;
|
|
|
|
-
|
|
|
|
- if (!hpet_address)
|
|
|
|
- return -ENODEV;
|
|
|
|
-
|
|
|
|
- /* calculate the hpet address: */
|
|
|
|
- hpet_base = ioremap_nocache(hpet_address, HPET_MMAP_SIZE);
|
|
|
|
- hpet_ptr = hpet_base + HPET_COUNTER;
|
|
|
|
-
|
|
|
|
- /* calculate the frequency: */
|
|
|
|
- hpet_period = readl(hpet_base + HPET_PERIOD);
|
|
|
|
-
|
|
|
|
- /*
|
|
|
|
- * hpet period is in femto seconds per cycle
|
|
|
|
- * so we need to convert this to ns/cyc units
|
|
|
|
- * aproximated by mult/2^shift
|
|
|
|
- *
|
|
|
|
- * fsec/cyc * 1nsec/1000000fsec = nsec/cyc = mult/2^shift
|
|
|
|
- * fsec/cyc * 1ns/1000000fsec * 2^shift = mult
|
|
|
|
- * fsec/cyc * 2^shift * 1nsec/1000000fsec = mult
|
|
|
|
- * (fsec/cyc << shift)/1000000 = mult
|
|
|
|
- * (hpet_period << shift)/FSEC_PER_NSEC = mult
|
|
|
|
- */
|
|
|
|
- tmp = (u64)hpet_period << HPET_SHIFT;
|
|
|
|
- do_div(tmp, FSEC_PER_NSEC);
|
|
|
|
- clocksource_hpet.mult = (u32)tmp;
|
|
|
|
-
|
|
|
|
- return clocksource_register(&clocksource_hpet);
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-module_init(init_hpet_clocksource);
|
|
|