aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/kernel/hpet_32.c59
1 files changed, 58 insertions, 1 deletions
diff --git a/arch/x86/kernel/hpet_32.c b/arch/x86/kernel/hpet_32.c
index 748abf0286d2..dbe0e1d44113 100644
--- a/arch/x86/kernel/hpet_32.c
+++ b/arch/x86/kernel/hpet_32.c
@@ -1,5 +1,6 @@
1#include <linux/clocksource.h> 1#include <linux/clocksource.h>
2#include <linux/clockchips.h> 2#include <linux/clockchips.h>
3#include <linux/delay.h>
3#include <linux/errno.h> 4#include <linux/errno.h>
4#include <linux/hpet.h> 5#include <linux/hpet.h>
5#include <linux/init.h> 6#include <linux/init.h>
@@ -7,6 +8,7 @@
7#include <linux/pm.h> 8#include <linux/pm.h>
8#include <linux/delay.h> 9#include <linux/delay.h>
9 10
11#include <asm/fixmap.h>
10#include <asm/hpet.h> 12#include <asm/hpet.h>
11#include <asm/i8253.h> 13#include <asm/i8253.h>
12#include <asm/io.h> 14#include <asm/io.h>
@@ -23,6 +25,10 @@
23unsigned long hpet_address; 25unsigned long hpet_address;
24static void __iomem *hpet_virt_address; 26static void __iomem *hpet_virt_address;
25 27
28/* Temporary hack. Cleanup after x86_64 clock events conversion */
29#undef hpet_readl
30#undef hpet_writel
31
26static inline unsigned long hpet_readl(unsigned long a) 32static inline unsigned long hpet_readl(unsigned long a)
27{ 33{
28 return readl(hpet_virt_address + a); 34 return readl(hpet_virt_address + a);
@@ -33,6 +39,24 @@ static inline void hpet_writel(unsigned long d, unsigned long a)
33 writel(d, hpet_virt_address + a); 39 writel(d, hpet_virt_address + a);
34} 40}
35 41
42#ifdef CONFIG_X86_64
43
44#include <asm/pgtable.h>
45
46static inline void hpet_set_mapping(void)
47{
48 set_fixmap_nocache(FIX_HPET_BASE, hpet_address);
49 __set_fixmap(VSYSCALL_HPET, hpet_address, PAGE_KERNEL_VSYSCALL_NOCACHE);
50 hpet_virt_address = (void __iomem *)fix_to_virt(FIX_HPET_BASE);
51}
52
53static inline void hpet_clear_mapping(void)
54{
55 hpet_virt_address = NULL;
56}
57
58#else
59
36static inline void hpet_set_mapping(void) 60static inline void hpet_set_mapping(void)
37{ 61{
38 hpet_virt_address = ioremap_nocache(hpet_address, HPET_MMAP_SIZE); 62 hpet_virt_address = ioremap_nocache(hpet_address, HPET_MMAP_SIZE);
@@ -43,6 +67,7 @@ static inline void hpet_clear_mapping(void)
43 iounmap(hpet_virt_address); 67 iounmap(hpet_virt_address);
44 hpet_virt_address = NULL; 68 hpet_virt_address = NULL;
45} 69}
70#endif
46 71
47/* 72/*
48 * HPET command line enable / disable 73 * HPET command line enable / disable
@@ -59,6 +84,13 @@ static int __init hpet_setup(char* str)
59} 84}
60__setup("hpet=", hpet_setup); 85__setup("hpet=", hpet_setup);
61 86
87static int __init disable_hpet(char *str)
88{
89 boot_hpet_disable = 1;
90 return 1;
91}
92__setup("nohpet", disable_hpet);
93
62static inline int is_hpet_capable(void) 94static inline int is_hpet_capable(void)
63{ 95{
64 return (!boot_hpet_disable && hpet_address); 96 return (!boot_hpet_disable && hpet_address);
@@ -225,6 +257,13 @@ static cycle_t read_hpet(void)
225 return (cycle_t)hpet_readl(HPET_COUNTER); 257 return (cycle_t)hpet_readl(HPET_COUNTER);
226} 258}
227 259
260#ifdef CONFIG_X86_64
261static cycle_t __vsyscall_fn vread_hpet(void)
262{
263 return readl((const void __iomem *)fix_to_virt(VSYSCALL_HPET) + 0xf0);
264}
265#endif
266
228static struct clocksource clocksource_hpet = { 267static struct clocksource clocksource_hpet = {
229 .name = "hpet", 268 .name = "hpet",
230 .rating = 250, 269 .rating = 250,
@@ -233,6 +272,9 @@ static struct clocksource clocksource_hpet = {
233 .shift = HPET_SHIFT, 272 .shift = HPET_SHIFT,
234 .flags = CLOCK_SOURCE_IS_CONTINUOUS, 273 .flags = CLOCK_SOURCE_IS_CONTINUOUS,
235 .resume = hpet_start_counter, 274 .resume = hpet_start_counter,
275#ifdef CONFIG_X86_64
276 .vread = vread_hpet,
277#endif
236}; 278};
237 279
238/* 280/*
@@ -331,7 +373,6 @@ int __init hpet_enable(void)
331 373
332 if (id & HPET_ID_LEGSUP) { 374 if (id & HPET_ID_LEGSUP) {
333 hpet_enable_int(); 375 hpet_enable_int();
334 hpet_reserve_platform_timers(id);
335 /* 376 /*
336 * Start hpet with the boot cpu mask and make it 377 * Start hpet with the boot cpu mask and make it
337 * global after the IO_APIC has been initialized. 378 * global after the IO_APIC has been initialized.
@@ -349,6 +390,22 @@ out_nohpet:
349 return 0; 390 return 0;
350} 391}
351 392
393/*
394 * Needs to be late, as the reserve_timer code calls kalloc !
395 *
396 * Not a problem on i386 as hpet_enable is called from late_time_init,
397 * but on x86_64 it is necessary !
398 */
399static __init int hpet_late_init(void)
400{
401 if (!is_hpet_capable())
402 return -ENODEV;
403
404 hpet_reserve_platform_timers(hpet_readl(HPET_ID));
405 return 0;
406}
407fs_initcall(hpet_late_init);
408
352#ifdef CONFIG_HPET_EMULATE_RTC 409#ifdef CONFIG_HPET_EMULATE_RTC
353 410
354/* HPET in LegacyReplacement Mode eats up RTC interrupt line. When, HPET 411/* HPET in LegacyReplacement Mode eats up RTC interrupt line. When, HPET