Commit da32f974 authored by Matthew Wilcox's avatar Matthew Wilcox Committed by Linus Torvalds

[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: default avatarMatthew Wilcox <willy@parisc-linux.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 01c7a821
......@@ -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();
}
......
......@@ -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 /
......
......@@ -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);
int irq = asic->global_irq[local_irq];
if (irq <= 0) {
irq = gsc_assign_irq(&gsc_asic_interrupt_type, asic);
if (irq == NO_IRQ)
return;
*irqp = irq;
asic->global_irq[local_irq] = irq;
}
*irqp = 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) {
......
......@@ -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,
};
......@@ -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. */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment