|
@@ -184,6 +184,67 @@ static irqreturn_t hpet_interrupt(int irq, void *data)
|
|
|
return IRQ_HANDLED;
|
|
|
}
|
|
|
|
|
|
+static void hpet_timer_set_irq(struct hpet_dev *devp)
|
|
|
+{
|
|
|
+ unsigned long v;
|
|
|
+ int irq, gsi;
|
|
|
+ struct hpet_timer __iomem *timer;
|
|
|
+
|
|
|
+ spin_lock_irq(&hpet_lock);
|
|
|
+ if (devp->hd_hdwirq) {
|
|
|
+ spin_unlock_irq(&hpet_lock);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ timer = devp->hd_timer;
|
|
|
+
|
|
|
+ /* we prefer level triggered mode */
|
|
|
+ v = readl(&timer->hpet_config);
|
|
|
+ if (!(v & Tn_INT_TYPE_CNF_MASK)) {
|
|
|
+ v |= Tn_INT_TYPE_CNF_MASK;
|
|
|
+ writel(v, &timer->hpet_config);
|
|
|
+ }
|
|
|
+ spin_unlock_irq(&hpet_lock);
|
|
|
+
|
|
|
+ v = (readq(&timer->hpet_config) & Tn_INT_ROUTE_CAP_MASK) >>
|
|
|
+ Tn_INT_ROUTE_CAP_SHIFT;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * In PIC mode, skip IRQ0-4, IRQ6-9, IRQ12-15 which is always used by
|
|
|
+ * legacy device. In IO APIC mode, we skip all the legacy IRQS.
|
|
|
+ */
|
|
|
+ if (acpi_irq_model == ACPI_IRQ_MODEL_PIC)
|
|
|
+ v &= ~0xf3df;
|
|
|
+ else
|
|
|
+ v &= ~0xffff;
|
|
|
+
|
|
|
+ for (irq = find_first_bit(&v, HPET_MAX_IRQ); irq < HPET_MAX_IRQ;
|
|
|
+ irq = find_next_bit(&v, HPET_MAX_IRQ, 1 + irq)) {
|
|
|
+
|
|
|
+ if (irq >= NR_IRQS) {
|
|
|
+ irq = HPET_MAX_IRQ;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ gsi = acpi_register_gsi(irq, ACPI_LEVEL_SENSITIVE,
|
|
|
+ ACPI_ACTIVE_LOW);
|
|
|
+ if (gsi > 0)
|
|
|
+ break;
|
|
|
+
|
|
|
+ /* FIXME: Setup interrupt source table */
|
|
|
+ }
|
|
|
+
|
|
|
+ if (irq < HPET_MAX_IRQ) {
|
|
|
+ spin_lock_irq(&hpet_lock);
|
|
|
+ v = readl(&timer->hpet_config);
|
|
|
+ v |= irq << Tn_INT_ROUTE_CNF_SHIFT;
|
|
|
+ writel(v, &timer->hpet_config);
|
|
|
+ devp->hd_hdwirq = gsi;
|
|
|
+ spin_unlock_irq(&hpet_lock);
|
|
|
+ }
|
|
|
+ return;
|
|
|
+}
|
|
|
+
|
|
|
static int hpet_open(struct inode *inode, struct file *file)
|
|
|
{
|
|
|
struct hpet_dev *devp;
|
|
@@ -215,6 +276,8 @@ static int hpet_open(struct inode *inode, struct file *file)
|
|
|
devp->hd_flags |= HPET_OPEN;
|
|
|
spin_unlock_irq(&hpet_lock);
|
|
|
|
|
|
+ hpet_timer_set_irq(devp);
|
|
|
+
|
|
|
return 0;
|
|
|
}
|
|
|
|