diff options
Diffstat (limited to 'drivers/char/hpet.c')
-rw-r--r-- | drivers/char/hpet.c | 70 |
1 files changed, 39 insertions, 31 deletions
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c index 0be700f4e8fd..ba0e74ad74bb 100644 --- a/drivers/char/hpet.c +++ b/drivers/char/hpet.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/bcd.h> | 29 | #include <linux/bcd.h> |
30 | #include <linux/seq_file.h> | 30 | #include <linux/seq_file.h> |
31 | #include <linux/bitops.h> | 31 | #include <linux/bitops.h> |
32 | #include <linux/clocksource.h> | ||
32 | 33 | ||
33 | #include <asm/current.h> | 34 | #include <asm/current.h> |
34 | #include <asm/uaccess.h> | 35 | #include <asm/uaccess.h> |
@@ -51,8 +52,34 @@ | |||
51 | 52 | ||
52 | #define HPET_RANGE_SIZE 1024 /* from HPET spec */ | 53 | #define HPET_RANGE_SIZE 1024 /* from HPET spec */ |
53 | 54 | ||
55 | #if BITS_PER_LONG == 64 | ||
56 | #define write_counter(V, MC) writeq(V, MC) | ||
57 | #define read_counter(MC) readq(MC) | ||
58 | #else | ||
59 | #define write_counter(V, MC) writel(V, MC) | ||
60 | #define read_counter(MC) readl(MC) | ||
61 | #endif | ||
62 | |||
54 | static u32 hpet_nhpet, hpet_max_freq = HPET_USER_FREQ; | 63 | static u32 hpet_nhpet, hpet_max_freq = HPET_USER_FREQ; |
55 | 64 | ||
65 | static void __iomem *hpet_mctr; | ||
66 | |||
67 | static cycle_t read_hpet(void) | ||
68 | { | ||
69 | return (cycle_t)read_counter((void __iomem *)hpet_mctr); | ||
70 | } | ||
71 | |||
72 | static struct clocksource clocksource_hpet = { | ||
73 | .name = "hpet", | ||
74 | .rating = 250, | ||
75 | .read = read_hpet, | ||
76 | .mask = 0xffffffffffffffff, | ||
77 | .mult = 0, /*to be caluclated*/ | ||
78 | .shift = 10, | ||
79 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | ||
80 | }; | ||
81 | static struct clocksource *hpet_clocksource; | ||
82 | |||
56 | /* A lock for concurrent access by app and isr hpet activity. */ | 83 | /* A lock for concurrent access by app and isr hpet activity. */ |
57 | static DEFINE_SPINLOCK(hpet_lock); | 84 | static DEFINE_SPINLOCK(hpet_lock); |
58 | /* A lock for concurrent intermodule access to hpet and isr hpet activity. */ | 85 | /* A lock for concurrent intermodule access to hpet and isr hpet activity. */ |
@@ -79,7 +106,7 @@ struct hpets { | |||
79 | struct hpets *hp_next; | 106 | struct hpets *hp_next; |
80 | struct hpet __iomem *hp_hpet; | 107 | struct hpet __iomem *hp_hpet; |
81 | unsigned long hp_hpet_phys; | 108 | unsigned long hp_hpet_phys; |
82 | struct time_interpolator *hp_interpolator; | 109 | struct clocksource *hp_clocksource; |
83 | unsigned long long hp_tick_freq; | 110 | unsigned long long hp_tick_freq; |
84 | unsigned long hp_delta; | 111 | unsigned long hp_delta; |
85 | unsigned int hp_ntimer; | 112 | unsigned int hp_ntimer; |
@@ -94,13 +121,6 @@ static struct hpets *hpets; | |||
94 | #define HPET_PERIODIC 0x0004 | 121 | #define HPET_PERIODIC 0x0004 |
95 | #define HPET_SHARED_IRQ 0x0008 | 122 | #define HPET_SHARED_IRQ 0x0008 |
96 | 123 | ||
97 | #if BITS_PER_LONG == 64 | ||
98 | #define write_counter(V, MC) writeq(V, MC) | ||
99 | #define read_counter(MC) readq(MC) | ||
100 | #else | ||
101 | #define write_counter(V, MC) writel(V, MC) | ||
102 | #define read_counter(MC) readl(MC) | ||
103 | #endif | ||
104 | 124 | ||
105 | #ifndef readq | 125 | #ifndef readq |
106 | static inline unsigned long long readq(void __iomem *addr) | 126 | static inline unsigned long long readq(void __iomem *addr) |
@@ -737,27 +757,6 @@ static ctl_table dev_root[] = { | |||
737 | 757 | ||
738 | static struct ctl_table_header *sysctl_header; | 758 | static struct ctl_table_header *sysctl_header; |
739 | 759 | ||
740 | static void hpet_register_interpolator(struct hpets *hpetp) | ||
741 | { | ||
742 | #ifdef CONFIG_TIME_INTERPOLATION | ||
743 | struct time_interpolator *ti; | ||
744 | |||
745 | ti = kzalloc(sizeof(*ti), GFP_KERNEL); | ||
746 | if (!ti) | ||
747 | return; | ||
748 | |||
749 | ti->source = TIME_SOURCE_MMIO64; | ||
750 | ti->shift = 10; | ||
751 | ti->addr = &hpetp->hp_hpet->hpet_mc; | ||
752 | ti->frequency = hpetp->hp_tick_freq; | ||
753 | ti->drift = HPET_DRIFT; | ||
754 | ti->mask = -1; | ||
755 | |||
756 | hpetp->hp_interpolator = ti; | ||
757 | register_time_interpolator(ti); | ||
758 | #endif | ||
759 | } | ||
760 | |||
761 | /* | 760 | /* |
762 | * Adjustment for when arming the timer with | 761 | * Adjustment for when arming the timer with |
763 | * initial conditions. That is, main counter | 762 | * initial conditions. That is, main counter |
@@ -909,7 +908,16 @@ int hpet_alloc(struct hpet_data *hdp) | |||
909 | } | 908 | } |
910 | 909 | ||
911 | hpetp->hp_delta = hpet_calibrate(hpetp); | 910 | hpetp->hp_delta = hpet_calibrate(hpetp); |
912 | hpet_register_interpolator(hpetp); | 911 | |
912 | if (!hpet_clocksource) { | ||
913 | hpet_mctr = (void __iomem *)&hpetp->hp_hpet->hpet_mc; | ||
914 | CLKSRC_FSYS_MMIO_SET(clocksource_hpet.fsys_mmio, hpet_mctr); | ||
915 | clocksource_hpet.mult = clocksource_hz2mult(hpetp->hp_tick_freq, | ||
916 | clocksource_hpet.shift); | ||
917 | clocksource_register(&clocksource_hpet); | ||
918 | hpetp->hp_clocksource = &clocksource_hpet; | ||
919 | hpet_clocksource = &clocksource_hpet; | ||
920 | } | ||
913 | 921 | ||
914 | return 0; | 922 | return 0; |
915 | } | 923 | } |
@@ -995,7 +1003,7 @@ static int hpet_acpi_add(struct acpi_device *device) | |||
995 | 1003 | ||
996 | static int hpet_acpi_remove(struct acpi_device *device, int type) | 1004 | static int hpet_acpi_remove(struct acpi_device *device, int type) |
997 | { | 1005 | { |
998 | /* XXX need to unregister interpolator, dealloc mem, etc */ | 1006 | /* XXX need to unregister clocksource, dealloc mem, etc */ |
999 | return -EINVAL; | 1007 | return -EINVAL; |
1000 | } | 1008 | } |
1001 | 1009 | ||