diff options
-rw-r--r-- | Documentation/00-INDEX | 2 | ||||
-rw-r--r-- | Documentation/timers/00-INDEX | 10 | ||||
-rw-r--r-- | Documentation/timers/hpet.txt (renamed from Documentation/hpet.txt) | 0 | ||||
-rw-r--r-- | drivers/char/hpet.c | 63 | ||||
-rw-r--r-- | include/linux/hpet.h | 3 |
5 files changed, 75 insertions, 3 deletions
diff --git a/Documentation/00-INDEX b/Documentation/00-INDEX index 6de71308a906..cfaa505dfd06 100644 --- a/Documentation/00-INDEX +++ b/Documentation/00-INDEX | |||
@@ -161,8 +161,6 @@ hayes-esp.txt | |||
161 | - info on using the Hayes ESP serial driver. | 161 | - info on using the Hayes ESP serial driver. |
162 | highuid.txt | 162 | highuid.txt |
163 | - notes on the change from 16 bit to 32 bit user/group IDs. | 163 | - notes on the change from 16 bit to 32 bit user/group IDs. |
164 | hpet.txt | ||
165 | - High Precision Event Timer Driver for Linux. | ||
166 | timers/ | 164 | timers/ |
167 | - info on the timer related topics | 165 | - info on the timer related topics |
168 | hw_random.txt | 166 | hw_random.txt |
diff --git a/Documentation/timers/00-INDEX b/Documentation/timers/00-INDEX new file mode 100644 index 000000000000..397dc35e1323 --- /dev/null +++ b/Documentation/timers/00-INDEX | |||
@@ -0,0 +1,10 @@ | |||
1 | 00-INDEX | ||
2 | - this file | ||
3 | highres.txt | ||
4 | - High resolution timers and dynamic ticks design notes | ||
5 | hpet.txt | ||
6 | - High Precision Event Timer Driver for Linux | ||
7 | hrtimers.txt | ||
8 | - subsystem for high-resolution kernel timers | ||
9 | timer_stats.txt | ||
10 | - timer usage statistics | ||
diff --git a/Documentation/hpet.txt b/Documentation/timers/hpet.txt index 6ad52d9dad6c..6ad52d9dad6c 100644 --- a/Documentation/hpet.txt +++ b/Documentation/timers/hpet.txt | |||
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c index b3f5dbc6d880..f3981ffe20f0 100644 --- a/drivers/char/hpet.c +++ b/drivers/char/hpet.c | |||
@@ -185,6 +185,67 @@ static irqreturn_t hpet_interrupt(int irq, void *data) | |||
185 | return IRQ_HANDLED; | 185 | return IRQ_HANDLED; |
186 | } | 186 | } |
187 | 187 | ||
188 | static void hpet_timer_set_irq(struct hpet_dev *devp) | ||
189 | { | ||
190 | unsigned long v; | ||
191 | int irq, gsi; | ||
192 | struct hpet_timer __iomem *timer; | ||
193 | |||
194 | spin_lock_irq(&hpet_lock); | ||
195 | if (devp->hd_hdwirq) { | ||
196 | spin_unlock_irq(&hpet_lock); | ||
197 | return; | ||
198 | } | ||
199 | |||
200 | timer = devp->hd_timer; | ||
201 | |||
202 | /* we prefer level triggered mode */ | ||
203 | v = readl(&timer->hpet_config); | ||
204 | if (!(v & Tn_INT_TYPE_CNF_MASK)) { | ||
205 | v |= Tn_INT_TYPE_CNF_MASK; | ||
206 | writel(v, &timer->hpet_config); | ||
207 | } | ||
208 | spin_unlock_irq(&hpet_lock); | ||
209 | |||
210 | v = (readq(&timer->hpet_config) & Tn_INT_ROUTE_CAP_MASK) >> | ||
211 | Tn_INT_ROUTE_CAP_SHIFT; | ||
212 | |||
213 | /* | ||
214 | * In PIC mode, skip IRQ0-4, IRQ6-9, IRQ12-15 which is always used by | ||
215 | * legacy device. In IO APIC mode, we skip all the legacy IRQS. | ||
216 | */ | ||
217 | if (acpi_irq_model == ACPI_IRQ_MODEL_PIC) | ||
218 | v &= ~0xf3df; | ||
219 | else | ||
220 | v &= ~0xffff; | ||
221 | |||
222 | for (irq = find_first_bit(&v, HPET_MAX_IRQ); irq < HPET_MAX_IRQ; | ||
223 | irq = find_next_bit(&v, HPET_MAX_IRQ, 1 + irq)) { | ||
224 | |||
225 | if (irq >= NR_IRQS) { | ||
226 | irq = HPET_MAX_IRQ; | ||
227 | break; | ||
228 | } | ||
229 | |||
230 | gsi = acpi_register_gsi(irq, ACPI_LEVEL_SENSITIVE, | ||
231 | ACPI_ACTIVE_LOW); | ||
232 | if (gsi > 0) | ||
233 | break; | ||
234 | |||
235 | /* FIXME: Setup interrupt source table */ | ||
236 | } | ||
237 | |||
238 | if (irq < HPET_MAX_IRQ) { | ||
239 | spin_lock_irq(&hpet_lock); | ||
240 | v = readl(&timer->hpet_config); | ||
241 | v |= irq << Tn_INT_ROUTE_CNF_SHIFT; | ||
242 | writel(v, &timer->hpet_config); | ||
243 | devp->hd_hdwirq = gsi; | ||
244 | spin_unlock_irq(&hpet_lock); | ||
245 | } | ||
246 | return; | ||
247 | } | ||
248 | |||
188 | static int hpet_open(struct inode *inode, struct file *file) | 249 | static int hpet_open(struct inode *inode, struct file *file) |
189 | { | 250 | { |
190 | struct hpet_dev *devp; | 251 | struct hpet_dev *devp; |
@@ -219,6 +280,8 @@ static int hpet_open(struct inode *inode, struct file *file) | |||
219 | spin_unlock_irq(&hpet_lock); | 280 | spin_unlock_irq(&hpet_lock); |
220 | unlock_kernel(); | 281 | unlock_kernel(); |
221 | 282 | ||
283 | hpet_timer_set_irq(devp); | ||
284 | |||
222 | return 0; | 285 | return 0; |
223 | } | 286 | } |
224 | 287 | ||
diff --git a/include/linux/hpet.h b/include/linux/hpet.h index 2dc29ce6c8e4..6d2626b63a9a 100644 --- a/include/linux/hpet.h +++ b/include/linux/hpet.h | |||
@@ -37,6 +37,7 @@ struct hpet { | |||
37 | #define hpet_compare _u1._hpet_compare | 37 | #define hpet_compare _u1._hpet_compare |
38 | 38 | ||
39 | #define HPET_MAX_TIMERS (32) | 39 | #define HPET_MAX_TIMERS (32) |
40 | #define HPET_MAX_IRQ (32) | ||
40 | 41 | ||
41 | /* | 42 | /* |
42 | * HPET general capabilities register | 43 | * HPET general capabilities register |
@@ -64,7 +65,7 @@ struct hpet { | |||
64 | */ | 65 | */ |
65 | 66 | ||
66 | #define Tn_INT_ROUTE_CAP_MASK (0xffffffff00000000ULL) | 67 | #define Tn_INT_ROUTE_CAP_MASK (0xffffffff00000000ULL) |
67 | #define Tn_INI_ROUTE_CAP_SHIFT (32UL) | 68 | #define Tn_INT_ROUTE_CAP_SHIFT (32UL) |
68 | #define Tn_FSB_INT_DELCAP_MASK (0x8000UL) | 69 | #define Tn_FSB_INT_DELCAP_MASK (0x8000UL) |
69 | #define Tn_FSB_INT_DELCAP_SHIFT (15) | 70 | #define Tn_FSB_INT_DELCAP_SHIFT (15) |
70 | #define Tn_FSB_EN_CNF_MASK (0x4000UL) | 71 | #define Tn_FSB_EN_CNF_MASK (0x4000UL) |