summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Wilcox <willy@parisc-linux.org>2005-03-11 17:14:51 -0800
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-03-11 17:14:51 -0800
commitda32f974a05e11ec2f6c85cd01736b2965639b58 (patch)
treea07db26a75d8eee278987be1851c8d77c3ac9863
parent01c7a821e0f92091b5d6d5bf7101193569719dc3 (diff)
[PATCH] PA-RISC GSC interrupt fixes
Two problems occurred with the recent switch to virtual interrupt numbers. The first is that two devices (eg Lasi PS/2 mouse and keyboard) can share the same physical interrupt and should therefore share the same virtual interrupt rather than have a new one assigned to them. Fix this by initialising the global_irq array to NO_IRQ, then checking the array before assigning a new one. The second is that some GSC devices (eg HIL and EISA) can have two interrupts; one for normal interrupts and the other for NMI or high-priority. To fix this, I introduced an auxiliary IRQ to the parisc_device and fill it in in Asp and Wax. Signed-off-by: Matthew Wilcox <willy@parisc-linux.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--drivers/input/serio/hp_sdc.c9
-rw-r--r--drivers/parisc/asp.c8
-rw-r--r--drivers/parisc/gsc.c20
-rw-r--r--drivers/parisc/wax.c26
-rw-r--r--include/asm-parisc/parisc-device.h1
5 files changed, 42 insertions, 22 deletions
diff --git a/drivers/input/serio/hp_sdc.c b/drivers/input/serio/hp_sdc.c
index 4110d5254e99..e011f83fa535 100644
--- a/drivers/input/serio/hp_sdc.c
+++ b/drivers/input/serio/hp_sdc.c
@@ -874,11 +874,10 @@ static int __init hp_sdc_init_hppa(struct parisc_device *d)
hp_sdc.dev = d;
hp_sdc.irq = d->irq;
- /* TODO: Is NMI == IRQ - 1 all cases, or is there a way to query? */
- hp_sdc.nmi = d->irq - 1;
- hp_sdc.base_io = (unsigned long) d->hpa;
- hp_sdc.data_io = (unsigned long) d->hpa + 0x800;
- hp_sdc.status_io = (unsigned long) d->hpa + 0x801;
+ hp_sdc.nmi = d->aux_irq;
+ hp_sdc.base_io = d->hpa;
+ hp_sdc.data_io = d->hpa + 0x800;
+ hp_sdc.status_io = d->hpa + 0x801;
return hp_sdc_init();
}
diff --git a/drivers/parisc/asp.c b/drivers/parisc/asp.c
index e351219f6fab..388609967133 100644
--- a/drivers/parisc/asp.c
+++ b/drivers/parisc/asp.c
@@ -53,6 +53,14 @@ static void asp_choose_irq(struct parisc_device *dev, void *ctrl)
}
gsc_asic_assign_irq(ctrl, irq, &dev->irq);
+
+ switch (dev->id.sversion) {
+ case 0x73: irq = 2; break; /* i8042 High-priority */
+ case 0x76: irq = 0; break; /* EISA BA */
+ default: return; /* Other */
+ }
+
+ gsc_asic_assign_irq(ctrl, irq, &dev->aux_irq);
}
/* There are two register ranges we're interested in. Interrupt /
diff --git a/drivers/parisc/gsc.c b/drivers/parisc/gsc.c
index 3c3dbc59051a..af5e02526a18 100644
--- a/drivers/parisc/gsc.c
+++ b/drivers/parisc/gsc.c
@@ -171,12 +171,16 @@ int gsc_assign_irq(struct hw_interrupt_type *type, void *data)
void gsc_asic_assign_irq(struct gsc_asic *asic, int local_irq, int *irqp)
{
- int irq = gsc_assign_irq(&gsc_asic_interrupt_type, asic);
- if (irq == NO_IRQ)
- return;
-
+ int irq = asic->global_irq[local_irq];
+
+ if (irq <= 0) {
+ irq = gsc_assign_irq(&gsc_asic_interrupt_type, asic);
+ if (irq == NO_IRQ)
+ return;
+
+ asic->global_irq[local_irq] = irq;
+ }
*irqp = irq;
- asic->global_irq[local_irq] = irq;
}
void gsc_fixup_irqs(struct parisc_device *parent, void *ctrl,
@@ -198,9 +202,15 @@ void gsc_fixup_irqs(struct parisc_device *parent, void *ctrl,
int gsc_common_setup(struct parisc_device *parent, struct gsc_asic *gsc_asic)
{
struct resource *res;
+ int i;
gsc_asic->gsc = parent;
+ /* Initialise local irq -> global irq mapping */
+ for (i = 0; i < 32; i++) {
+ gsc_asic->global_irq[i] = NO_IRQ;
+ }
+
/* allocate resource region */
res = request_mem_region(gsc_asic->hpa, 0x100000, gsc_asic->name);
if (res) {
diff --git a/drivers/parisc/wax.c b/drivers/parisc/wax.c
index c384d5e80279..e547d7d024d8 100644
--- a/drivers/parisc/wax.c
+++ b/drivers/parisc/wax.c
@@ -25,20 +25,27 @@
#include "gsc.h"
#define WAX_GSC_IRQ 7 /* Hardcoded Interrupt for GSC */
-#define WAX_GSC_NMI_IRQ 29
static void wax_choose_irq(struct parisc_device *dev, void *ctrl)
{
int irq;
switch (dev->id.sversion) {
- case 0x73: irq = 1; break; /* HIL */
- case 0x8c: irq = 6; break; /* RS232 */
- case 0x90: irq = 10; break; /* WAX EISA BA */
+ case 0x73: irq = 1; break; /* i8042 General */
+ case 0x8c: irq = 6; break; /* Serial */
+ case 0x90: irq = 10; break; /* EISA */
default: return; /* Unknown */
}
gsc_asic_assign_irq(ctrl, irq, &dev->irq);
+
+ switch (dev->id.sversion) {
+ case 0x73: irq = 2; break; /* i8042 High-priority */
+ case 0x90: irq = 0; break; /* EISA NMI */
+ default: return; /* No secondary IRQ */
+ }
+
+ gsc_asic_assign_irq(ctrl, irq, &dev->aux_irq);
}
static void __init
@@ -46,7 +53,7 @@ wax_init_irq(struct gsc_asic *wax)
{
unsigned long base = wax->hpa;
- /* Stop WAX barking for a bit */
+ /* Wax-off */
gsc_writel(0x00000000, base+OFFSET_IMR);
/* clear pending interrupts */
@@ -59,11 +66,6 @@ wax_init_irq(struct gsc_asic *wax)
/* Resets */
// gsc_writel(0xFFFFFFFF, base+0x1000); /* HIL */
// gsc_writel(0xFFFFFFFF, base+0x2000); /* RS232-B on Wax */
-
- /* Ok we hit it on the head with a hammer, our Dog is now
- ** comatose and muzzled. Devices will now unmask WAX
- ** interrupts as they are registered as irq's in the WAX range.
- */
}
int __init
@@ -78,7 +80,7 @@ wax_init_chip(struct parisc_device *dev)
if (!wax)
return -ENOMEM;
- wax->name = "Wax";
+ wax->name = "wax";
wax->hpa = dev->hpa;
wax->version = 0; /* gsc_readb(wax->hpa+WAX_VER); */
@@ -132,7 +134,7 @@ static struct parisc_device_id wax_tbl[] = {
MODULE_DEVICE_TABLE(parisc, wax_tbl);
struct parisc_driver wax_driver = {
- .name = "Wax",
+ .name = "wax",
.id_table = wax_tbl,
.probe = wax_init_chip,
};
diff --git a/include/asm-parisc/parisc-device.h b/include/asm-parisc/parisc-device.h
index 594c1d91589b..ef69ab4b17a9 100644
--- a/include/asm-parisc/parisc-device.h
+++ b/include/asm-parisc/parisc-device.h
@@ -6,6 +6,7 @@ struct parisc_device {
struct parisc_driver *driver; /* Driver for this device */
char name[80]; /* The hardware description */
int irq;
+ int aux_irq; /* Some devices have a second IRQ */
char hw_path; /* The module number on this bus */
unsigned int num_addrs; /* some devices have additional address ranges. */