diff options
author | Matthew Wilcox <willy@parisc-linux.org> | 2005-03-11 17:14:51 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-03-11 17:14:51 -0800 |
commit | da32f974a05e11ec2f6c85cd01736b2965639b58 (patch) | |
tree | a07db26a75d8eee278987be1851c8d77c3ac9863 | |
parent | 01c7a821e0f92091b5d6d5bf7101193569719dc3 (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.c | 9 | ||||
-rw-r--r-- | drivers/parisc/asp.c | 8 | ||||
-rw-r--r-- | drivers/parisc/gsc.c | 20 | ||||
-rw-r--r-- | drivers/parisc/wax.c | 26 | ||||
-rw-r--r-- | include/asm-parisc/parisc-device.h | 1 |
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. */ |