Commit 8953e802 authored by Matthew Wilcox's avatar Matthew Wilcox Committed by Linus Torvalds

[PATCH] Generic IRQ support for PA-RISC

Make PA-RISC use the generic interrupt handling code.  We need one tiny
change to the generic code -- the addition of a data pointer to irq_desc.
This shouldn't be a problem in terms of increasing size of irq_desc for
other architectures as the struct is cacheline aligned.  It's now 32
bytes on 32-bit platforms and 44/48 bytes on 64-bit platforms (assuming
spinlock_t is 4 bytes on 32-bit and 4 or 8 bytes on 64-bit).
Signed-off-by: default avatarMatthew Wilcox <matthew@wil.cx>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent ad8c410c
...@@ -39,6 +39,12 @@ config GENERIC_CALIBRATE_DELAY ...@@ -39,6 +39,12 @@ config GENERIC_CALIBRATE_DELAY
config GENERIC_ISA_DMA config GENERIC_ISA_DMA
bool bool
config GENERIC_HARDIRQS
def_bool y
config GENERIC_IRQ_PROBE
def_bool y
# unless you want to implement ACPI on PA-RISC ... ;-) # unless you want to implement ACPI on PA-RISC ... ;-)
config PM config PM
bool bool
......
This diff is collapsed.
...@@ -277,7 +277,7 @@ ipi_send(int cpu, enum ipi_message_type op) ...@@ -277,7 +277,7 @@ ipi_send(int cpu, enum ipi_message_type op)
spin_lock_irqsave(&(p->lock),flags); spin_lock_irqsave(&(p->lock),flags);
p->pending_ipi |= 1 << op; p->pending_ipi |= 1 << op;
__raw_writel(IRQ_OFFSET(IPI_IRQ), cpu_data[cpu].hpa); gsc_writel(IPI_IRQ - CPU_IRQ_BASE, cpu_data[cpu].hpa);
spin_unlock_irqrestore(&(p->lock),flags); spin_unlock_irqrestore(&(p->lock),flags);
} }
...@@ -533,7 +533,7 @@ int __init smp_boot_one_cpu(int cpuid) ...@@ -533,7 +533,7 @@ int __init smp_boot_one_cpu(int cpuid)
** EIR{0}). MEM_RENDEZ is valid only when it is nonzero and the ** EIR{0}). MEM_RENDEZ is valid only when it is nonzero and the
** contents of memory are valid." ** contents of memory are valid."
*/ */
__raw_writel(IRQ_OFFSET(TIMER_IRQ), cpu_data[cpuid].hpa); gsc_writel(TIMER_IRQ - CPU_IRQ_BASE, cpu_data[cpuid].hpa);
mb(); mb();
/* /*
......
...@@ -2,11 +2,6 @@ ...@@ -2,11 +2,6 @@
# Makefile for most of the non-PCI devices in PA-RISC machines # Makefile for most of the non-PCI devices in PA-RISC machines
# #
obj-y :=
obj-m :=
obj-n :=
obj- :=
# I/O SAPIC is also on IA64 platforms. # I/O SAPIC is also on IA64 platforms.
# The two could be merged into a common source some day. # The two could be merged into a common source some day.
obj-$(CONFIG_IOSAPIC) += iosapic.o obj-$(CONFIG_IOSAPIC) += iosapic.o
...@@ -17,7 +12,7 @@ obj-$(CONFIG_PCI_LBA) += lba_pci.o ...@@ -17,7 +12,7 @@ obj-$(CONFIG_PCI_LBA) += lba_pci.o
# obj-$(CONFIG_IOMMU_CCIO) += ccio-rm-dma.o # obj-$(CONFIG_IOMMU_CCIO) += ccio-rm-dma.o
obj-$(CONFIG_IOMMU_CCIO) += ccio-dma.o obj-$(CONFIG_IOMMU_CCIO) += ccio-dma.o
obj-y += gsc.o obj-$(CONFIG_GSC) += gsc.o
obj-$(CONFIG_HPPB) += hppb.o obj-$(CONFIG_HPPB) += hppb.o
obj-$(CONFIG_GSC_DINO) += dino.o obj-$(CONFIG_GSC_DINO) += dino.o
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/irq.h> #include <linux/interrupt.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/types.h> #include <linux/types.h>
...@@ -30,25 +30,27 @@ ...@@ -30,25 +30,27 @@
#define VIPER_INT_WORD 0xFFFBF088 /* addr of viper interrupt word */ #define VIPER_INT_WORD 0xFFFBF088 /* addr of viper interrupt word */
static int asp_choose_irq(struct parisc_device *dev) static void asp_choose_irq(struct parisc_device *dev, void *ctrl)
{ {
int irq = -1; int irq;
switch (dev->id.sversion) { switch (dev->id.sversion) {
case 0x71: irq = 22; break; /* SCSI */ case 0x71: irq = 9; break; /* SCSI */
case 0x72: irq = 23; break; /* LAN */ case 0x72: irq = 8; break; /* LAN */
case 0x73: irq = 30; break; /* HIL */ case 0x73: irq = 1; break; /* HIL */
case 0x74: irq = 24; break; /* Centronics */ case 0x74: irq = 7; break; /* Centronics */
case 0x75: irq = (dev->hw_path == 4) ? 26 : 25; break; /* RS232 */ case 0x75: irq = (dev->hw_path == 4) ? 5 : 6; break; /* RS232 */
case 0x76: irq = 21; break; /* EISA BA */ case 0x76: irq = 10; break; /* EISA BA */
case 0x77: irq = 20; break; /* Graphics1 */ case 0x77: irq = 11; break; /* Graphics1 */
case 0x7a: irq = 18; break; /* Audio (Bushmaster) */ case 0x7a: irq = 13; break; /* Audio (Bushmaster) */
case 0x7b: irq = 18; break; /* Audio (Scorpio) */ case 0x7b: irq = 13; break; /* Audio (Scorpio) */
case 0x7c: irq = 28; break; /* FW SCSI */ case 0x7c: irq = 3; break; /* FW SCSI */
case 0x7d: irq = 27; break; /* FDDI */ case 0x7d: irq = 4; break; /* FDDI */
case 0x7f: irq = 18; break; /* Audio (Outfield) */ case 0x7f: irq = 13; break; /* Audio (Outfield) */
default: return; /* Unknown */
} }
return irq;
gsc_asic_assign_irq(ctrl, irq, &dev->irq);
} }
/* There are two register ranges we're interested in. Interrupt / /* There are two register ranges we're interested in. Interrupt /
...@@ -62,11 +64,11 @@ static int asp_choose_irq(struct parisc_device *dev) ...@@ -62,11 +64,11 @@ static int asp_choose_irq(struct parisc_device *dev)
int __init int __init
asp_init_chip(struct parisc_device *dev) asp_init_chip(struct parisc_device *dev)
{ {
struct busdevice *asp; struct gsc_asic *asp;
struct gsc_irq gsc_irq; struct gsc_irq gsc_irq;
int irq, ret; int ret;
asp = kmalloc(sizeof(struct busdevice), GFP_KERNEL); asp = kmalloc(sizeof(*asp), GFP_KERNEL);
if(!asp) if(!asp)
return -ENOMEM; return -ENOMEM;
...@@ -79,37 +81,34 @@ asp_init_chip(struct parisc_device *dev) ...@@ -79,37 +81,34 @@ asp_init_chip(struct parisc_device *dev)
/* the IRQ ASP should use */ /* the IRQ ASP should use */
ret = -EBUSY; ret = -EBUSY;
irq = gsc_claim_irq(&gsc_irq, ASP_GSC_IRQ); dev->irq = gsc_claim_irq(&gsc_irq, ASP_GSC_IRQ);
if (irq < 0) { if (dev->irq < 0) {
printk(KERN_ERR "%s(): cannot get GSC irq\n", __FUNCTION__); printk(KERN_ERR "%s(): cannot get GSC irq\n", __FUNCTION__);
goto out; goto out;
} }
ret = request_irq(gsc_irq.irq, busdev_barked, 0, "asp", asp); asp->eim = ((u32) gsc_irq.txn_addr) | gsc_irq.txn_data;
ret = request_irq(gsc_irq.irq, gsc_asic_intr, 0, "asp", asp);
if (ret < 0) if (ret < 0)
goto out; goto out;
/* Save this for debugging later */
asp->parent_irq = gsc_irq.irq;
asp->eim = ((u32) gsc_irq.txn_addr) | gsc_irq.txn_data;
/* Program VIPER to interrupt on the ASP irq */ /* Program VIPER to interrupt on the ASP irq */
gsc_writel((1 << (31 - ASP_GSC_IRQ)),VIPER_INT_WORD); gsc_writel((1 << (31 - ASP_GSC_IRQ)),VIPER_INT_WORD);
/* Done init'ing, register this driver */ /* Done init'ing, register this driver */
ret = gsc_common_irqsetup(dev, asp); ret = gsc_common_setup(dev, asp);
if (ret) if (ret)
goto out; goto out;
fixup_child_irqs(dev, asp->busdev_region->data.irqbase, asp_choose_irq); gsc_fixup_irqs(dev, asp, asp_choose_irq);
/* Mongoose is a sibling of Asp, not a child... */ /* Mongoose is a sibling of Asp, not a child... */
fixup_child_irqs(dev->parent, asp->busdev_region->data.irqbase, gsc_fixup_irqs(parisc_parent(dev), asp, asp_choose_irq);
asp_choose_irq);
/* initialize the chassis LEDs */ /* initialize the chassis LEDs */
#ifdef CONFIG_CHASSIS_LCD_LED #ifdef CONFIG_CHASSIS_LCD_LED
register_led_driver(DISPLAY_MODEL_OLD_ASP, LED_CMD_REG_NONE, register_led_driver(DISPLAY_MODEL_OLD_ASP, LED_CMD_REG_NONE,
(char *)ASP_LED_ADDR); ASP_LED_ADDR);
#endif #endif
return 0; return 0;
......
...@@ -57,7 +57,6 @@ ...@@ -57,7 +57,6 @@
#include <asm/page.h> #include <asm/page.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/irq.h>
#include <asm/hardware.h> #include <asm/hardware.h>
#include "gsc.h" #include "gsc.h"
...@@ -146,10 +145,8 @@ struct dino_device ...@@ -146,10 +145,8 @@ struct dino_device
spinlock_t dinosaur_pen; spinlock_t dinosaur_pen;
unsigned long txn_addr; /* EIR addr to generate interrupt */ unsigned long txn_addr; /* EIR addr to generate interrupt */
u32 txn_data; /* EIR data assign to each dino */ u32 txn_data; /* EIR data assign to each dino */
int irq; /* Virtual IRQ dino uses */
struct irq_region *dino_region; /* region for this Dino */
u32 imr; /* IRQ's which are enabled */ u32 imr; /* IRQ's which are enabled */
int global_irq[12]; /* map IMR bit to global irq */
#ifdef DINO_DEBUG #ifdef DINO_DEBUG
unsigned int dino_irr0; /* save most recent IRQ line stat */ unsigned int dino_irr0; /* save most recent IRQ line stat */
#endif #endif
...@@ -298,45 +295,37 @@ struct pci_port_ops dino_port_ops = { ...@@ -298,45 +295,37 @@ struct pci_port_ops dino_port_ops = {
.outl = dino_out32 .outl = dino_out32
}; };
static void static void dino_disable_irq(unsigned int irq)
dino_mask_irq(void *irq_dev, int irq)
{ {
struct dino_device *dino_dev = DINO_DEV(irq_dev); struct dino_device *dino_dev = irq_desc[irq].handler_data;
int local_irq = gsc_find_local_irq(irq, dino_dev->global_irq, irq);
DBG(KERN_WARNING "%s(0x%p, %d)\n", __FUNCTION__, irq_dev, irq); DBG(KERN_WARNING "%s(0x%p, %d)\n", __FUNCTION__, irq_dev, irq);
if (NULL == irq_dev || irq > DINO_IRQS || irq < 0) { /* Clear the matching bit in the IMR register */
printk(KERN_WARNING "%s(0x%lx, %d) - not a dino irq?\n", dino_dev->imr &= ~(DINO_MASK_IRQ(local_irq));
__FUNCTION__, (long) irq_dev, irq); __raw_writel(dino_dev->imr, dino_dev->hba.base_addr+DINO_IMR);
BUG();
} else {
/*
** Clear the matching bit in the IMR register
*/
dino_dev->imr &= ~(DINO_MASK_IRQ(irq));
gsc_writel(dino_dev->imr, dino_dev->hba.base_addr+DINO_IMR);
}
} }
static void dino_enable_irq(unsigned int irq)
static void
dino_unmask_irq(void *irq_dev, int irq)
{ {
struct dino_device *dino_dev = DINO_DEV(irq_dev); struct dino_device *dino_dev = irq_desc[irq].handler_data;
int local_irq = gsc_find_local_irq(irq, dino_dev->global_irq, irq);
u32 tmp; u32 tmp;
DBG(KERN_WARNING "%s(0x%p, %d)\n", __FUNCTION__, irq_dev, irq); DBG(KERN_WARNING "%s(0x%p, %d)\n", __FUNCTION__, irq_dev, irq);
if (NULL == irq_dev || irq > DINO_IRQS) { /*
printk(KERN_WARNING "%s(): %d not a dino irq?\n", ** clear pending IRQ bits
__FUNCTION__, irq); **
BUG(); ** This does NOT change ILR state!
return; ** See comment below for ILR usage.
} */
__raw_readl(dino_dev->hba.base_addr+DINO_IPR);
/* set the matching bit in the IMR register */ /* set the matching bit in the IMR register */
dino_dev->imr |= DINO_MASK_IRQ(irq); /* used in dino_isr() */ dino_dev->imr |= DINO_MASK_IRQ(local_irq); /* used in dino_isr() */
gsc_writel( dino_dev->imr, dino_dev->hba.base_addr+DINO_IMR); __raw_writel( dino_dev->imr, dino_dev->hba.base_addr+DINO_IMR);
/* Emulate "Level Triggered" Interrupt /* Emulate "Level Triggered" Interrupt
** Basically, a driver is blowing it if the IRQ line is asserted ** Basically, a driver is blowing it if the IRQ line is asserted
...@@ -347,38 +336,28 @@ dino_unmask_irq(void *irq_dev, int irq) ...@@ -347,38 +336,28 @@ dino_unmask_irq(void *irq_dev, int irq)
** dino_isr() will read IPR and find nothing. But then catch this ** dino_isr() will read IPR and find nothing. But then catch this
** when it also checks ILR. ** when it also checks ILR.
*/ */
tmp = gsc_readl(dino_dev->hba.base_addr+DINO_ILR); tmp = __raw_readl(dino_dev->hba.base_addr+DINO_ILR);
if (tmp & DINO_MASK_IRQ(irq)) { if (tmp & DINO_MASK_IRQ(local_irq)) {
DBG(KERN_WARNING "%s(): IRQ asserted! (ILR 0x%x)\n", DBG(KERN_WARNING "%s(): IRQ asserted! (ILR 0x%x)\n",
__FUNCTION__, tmp); __FUNCTION__, tmp);
gsc_writel(dino_dev->txn_data, dino_dev->txn_addr); gsc_writel(dino_dev->txn_data, dino_dev->txn_addr);
} }
} }
static unsigned int dino_startup_irq(unsigned int irq)
static void
dino_enable_irq(void *irq_dev, int irq)
{ {
struct dino_device *dino_dev = DINO_DEV(irq_dev); dino_enable_irq(irq);
return 0;
/*
** clear pending IRQ bits
**
** This does NOT change ILR state!
** See comments in dino_unmask_irq() for ILR usage.
*/
gsc_readl(dino_dev->hba.base_addr+DINO_IPR);
dino_unmask_irq(irq_dev, irq);
} }
static struct hw_interrupt_type dino_interrupt_type = {
static struct irq_region_ops dino_irq_ops = { .typename = "GSC-PCI",
.disable_irq = dino_mask_irq, /* ??? */ .startup = dino_startup_irq,
.enable_irq = dino_enable_irq, .shutdown = dino_disable_irq,
.mask_irq = dino_mask_irq, .enable = dino_enable_irq,
.unmask_irq = dino_unmask_irq .disable = dino_disable_irq,
.ack = no_ack_irq,
.end = no_end_irq,
}; };
...@@ -391,34 +370,28 @@ static struct irq_region_ops dino_irq_ops = { ...@@ -391,34 +370,28 @@ static struct irq_region_ops dino_irq_ops = {
static irqreturn_t static irqreturn_t
dino_isr(int irq, void *intr_dev, struct pt_regs *regs) dino_isr(int irq, void *intr_dev, struct pt_regs *regs)
{ {
struct dino_device *dino_dev = DINO_DEV(intr_dev); struct dino_device *dino_dev = intr_dev;
u32 mask; u32 mask;
int ilr_loop = 100; int ilr_loop = 100;
extern void do_irq(struct irqaction *a, int i, struct pt_regs *p);
/* read and acknowledge pending interrupts */ /* read and acknowledge pending interrupts */
#ifdef DINO_DEBUG #ifdef DINO_DEBUG
dino_dev->dino_irr0 = dino_dev->dino_irr0 =
#endif #endif
mask = gsc_readl(dino_dev->hba.base_addr+DINO_IRR0) & DINO_IRR_MASK; mask = __raw_readl(dino_dev->hba.base_addr+DINO_IRR0) & DINO_IRR_MASK;
ilr_again:
while (mask)
{
int irq;
irq = __ffs(mask);
mask &= ~(1<<irq); if (mask == 0)
return IRQ_NONE;
DBG(KERN_WARNING "%s(%x, %p) mask %0x\n", ilr_again:
do {
int local_irq = __ffs(mask);
int irq = dino_dev->global_irq[local_irq];
DBG(KERN_DEBUG "%s(%d, %p) mask 0x%x\n",
__FUNCTION__, irq, intr_dev, mask); __FUNCTION__, irq, intr_dev, mask);
do_irq(&dino_dev->dino_region->action[irq], __do_IRQ(irq, regs);
dino_dev->dino_region->data.irqbase + irq, mask &= ~(1 << local_irq);
regs); } while (mask);
}
/* Support for level triggered IRQ lines. /* Support for level triggered IRQ lines.
** **
...@@ -427,27 +400,40 @@ dino_isr(int irq, void *intr_dev, struct pt_regs *regs) ...@@ -427,27 +400,40 @@ dino_isr(int irq, void *intr_dev, struct pt_regs *regs)
** device drivers may assume lines are level triggered (and not ** device drivers may assume lines are level triggered (and not
** edge triggered like EISA/ISA can be). ** edge triggered like EISA/ISA can be).
*/ */
mask = gsc_readl(dino_dev->hba.base_addr+DINO_ILR) & dino_dev->imr; mask = __raw_readl(dino_dev->hba.base_addr+DINO_ILR) & dino_dev->imr;
if (mask) { if (mask) {
if (--ilr_loop > 0) if (--ilr_loop > 0)
goto ilr_again; goto ilr_again;
printk(KERN_ERR "Dino %lx: stuck interrupt %d\n", dino_dev->hba.base_addr, mask); printk(KERN_ERR "Dino 0x%p: stuck interrupt %d\n",
dino_dev->hba.base_addr, mask);
return IRQ_NONE; return IRQ_NONE;
} }
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static int dino_choose_irq(struct parisc_device *dev) static void dino_assign_irq(struct dino_device *dino, int local_irq, int *irqp)
{
int irq = gsc_assign_irq(&dino_interrupt_type, dino);
if (irq == NO_IRQ)
return;
*irqp = irq;
dino->global_irq[local_irq] = irq;
}
static void dino_choose_irq(struct parisc_device *dev, void *ctrl)
{ {
int irq = -1; int irq;
struct dino_device *dino = ctrl;
switch (dev->id.sversion) { switch (dev->id.sversion) {
case 0x00084: irq = 8; break; /* PS/2 */ case 0x00084: irq = 8; break; /* PS/2 */
case 0x0008c: irq = 10; break; /* RS232 */ case 0x0008c: irq = 10; break; /* RS232 */
case 0x00096: irq = 8; break; /* PS/2 */ case 0x00096: irq = 8; break; /* PS/2 */
default: return; /* Unknown */
} }
return irq; dino_assign_irq(dino, irq, &dev->irq);
} }
static void __init static void __init
...@@ -664,11 +650,15 @@ dino_fixup_bus(struct pci_bus *bus) ...@@ -664,11 +650,15 @@ dino_fixup_bus(struct pci_bus *bus)
u32 irq_pin; u32 irq_pin;
dino_cfg_read(dev->bus, dev->devfn, PCI_INTERRUPT_PIN, 1, &irq_pin); dino_cfg_read(dev->bus, dev->devfn,
dev->irq = (irq_pin + PCI_SLOT(dev->devfn) - 1) % 4 ; PCI_INTERRUPT_PIN, 1, &irq_pin);
dino_cfg_write(dev->bus, dev->devfn, PCI_INTERRUPT_LINE, 1, dev->irq); irq_pin = (irq_pin + PCI_SLOT(dev->devfn) - 1) % 4 ;
dev->irq += dino_dev->dino_region->data.irqbase; printk(KERN_WARNING "Device %s has undefined IRQ, "
printk(KERN_WARNING "Device %s has undefined IRQ, setting to %d\n", dev->slot_name, irq_pin); "setting to %d\n", dev->slot_name,
irq_pin);
dino_cfg_write(dev->bus, dev->devfn,
PCI_INTERRUPT_LINE, 1, irq_pin);
dino_assign_irq(dino_dev, irq_pin, &dev->irq);
#else #else
dev->irq = 65535; dev->irq = 65535;
printk(KERN_WARNING "Device %s has unassigned IRQ\n", dev->slot_name); printk(KERN_WARNING "Device %s has unassigned IRQ\n", dev->slot_name);
...@@ -676,7 +666,7 @@ dino_fixup_bus(struct pci_bus *bus) ...@@ -676,7 +666,7 @@ dino_fixup_bus(struct pci_bus *bus)
} else { } else {
/* Adjust INT_LINE for that busses region */ /* Adjust INT_LINE for that busses region */
dev->irq += dino_dev->dino_region->data.irqbase; dino_assign_irq(dino_dev, dev->irq, &dev->irq);
} }
} }
} }
...@@ -830,7 +820,7 @@ static int __init dino_common_init(struct parisc_device *dev, ...@@ -830,7 +820,7 @@ static int __init dino_common_init(struct parisc_device *dev,
** still only has 11 IRQ input lines - just map some of them ** still only has 11 IRQ input lines - just map some of them
** to a different processor. ** to a different processor.
*/ */
dino_dev->irq = gsc_alloc_irq(&gsc_irq); dev->irq = gsc_alloc_irq(&gsc_irq);
dino_dev->txn_addr = gsc_irq.txn_addr; dino_dev->txn_addr = gsc_irq.txn_addr;
dino_dev->txn_data = gsc_irq.txn_data; dino_dev->txn_data = gsc_irq.txn_data;
eim = ((u32) gsc_irq.txn_addr) | gsc_irq.txn_data; eim = ((u32) gsc_irq.txn_addr) | gsc_irq.txn_data;
...@@ -839,49 +829,36 @@ static int __init dino_common_init(struct parisc_device *dev, ...@@ -839,49 +829,36 @@ static int __init dino_common_init(struct parisc_device *dev,
** Dino needs a PA "IRQ" to get a processor's attention. ** Dino needs a PA "IRQ" to get a processor's attention.
** arch/parisc/kernel/irq.c returns an EIRR bit. ** arch/parisc/kernel/irq.c returns an EIRR bit.
*/ */
if (dino_dev->irq < 0) { if (dev->irq < 0) {
printk(KERN_WARNING "%s: gsc_alloc_irq() failed\n", name); printk(KERN_WARNING "%s: gsc_alloc_irq() failed\n", name);
return 1; return 1;
} }
status = request_irq(dino_dev->irq, dino_isr, 0, name, dino_dev); status = request_irq(dev->irq, dino_isr, 0, name, dino_dev);
if (status) { if (status) {
printk(KERN_WARNING "%s: request_irq() failed with %d\n", printk(KERN_WARNING "%s: request_irq() failed with %d\n",
name, status); name, status);
return 1; return 1;
} }
/*
** Tell generic interrupt support we have 11 bits which need
** be checked in the interrupt handler.
*/
dino_dev->dino_region = alloc_irq_region(DINO_IRQS, &dino_irq_ops,
name, dino_dev);
if (NULL == dino_dev->dino_region) {
printk(KERN_WARNING "%s: alloc_irq_region() failed\n", name);
return 1;
}
/* Support the serial port which is sometimes attached on built-in /* Support the serial port which is sometimes attached on built-in
* Dino / Cujo chips. * Dino / Cujo chips.
*/ */
fixup_child_irqs(dev, dino_dev->dino_region->data.irqbase, gsc_fixup_irqs(dev, dino_dev, dino_choose_irq);
dino_choose_irq);
/* /*
** This enables DINO to generate interrupts when it sees ** This enables DINO to generate interrupts when it sees
** any of its inputs *change*. Just asserting an IRQ ** any of its inputs *change*. Just asserting an IRQ
** before it's enabled (ie unmasked) isn't good enough. ** before it's enabled (ie unmasked) isn't good enough.
*/ */
gsc_writel(eim, dino_dev->hba.base_addr+DINO_IAR0); __raw_writel(eim, dino_dev->hba.base_addr+DINO_IAR0);
/* /*
** Some platforms don't clear Dino's IRR0 register at boot time. ** Some platforms don't clear Dino's IRR0 register at boot time.
** Reading will clear it now. ** Reading will clear it now.
*/ */
gsc_readl(dino_dev->hba.base_addr+DINO_IRR0); __raw_readl(dino_dev->hba.base_addr+DINO_IRR0);
/* allocate I/O Port resource region */ /* allocate I/O Port resource region */
res = &dino_dev->hba.io_space; res = &dino_dev->hba.io_space;
......
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/irq.h> #include <linux/interrupt.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/pci.h> #include <linux/pci.h>
...@@ -142,7 +142,7 @@ static unsigned int eisa_irq_level; /* default to edge triggered */ ...@@ -142,7 +142,7 @@ static unsigned int eisa_irq_level; /* default to edge triggered */
/* called by free irq */ /* called by free irq */
static void eisa_disable_irq(void *irq_dev, int irq) static void eisa_disable_irq(unsigned int irq)
{ {
unsigned long flags; unsigned long flags;
...@@ -162,7 +162,7 @@ static void eisa_disable_irq(void *irq_dev, int irq) ...@@ -162,7 +162,7 @@ static void eisa_disable_irq(void *irq_dev, int irq)
} }
/* called by request irq */ /* called by request irq */
static void eisa_enable_irq(void *irq_dev, int irq) static void eisa_enable_irq(unsigned int irq)
{ {
unsigned long flags; unsigned long flags;
EISA_DBG("enable irq %d\n", irq); EISA_DBG("enable irq %d\n", irq);
...@@ -180,52 +180,24 @@ static void eisa_enable_irq(void *irq_dev, int irq) ...@@ -180,52 +180,24 @@ static void eisa_enable_irq(void *irq_dev, int irq)
EISA_DBG("pic1 mask %02x\n", eisa_in8(0xa1)); EISA_DBG("pic1 mask %02x\n", eisa_in8(0xa1));
} }
static void eisa_mask_irq(void *irq_dev, int irq) static unsigned int eisa_startup_irq(unsigned int irq)
{ {
unsigned long flags; eisa_enable_irq(irq);
EISA_DBG("mask irq %d\n", irq); return 0;
/* mask irq */
spin_lock_irqsave(&eisa_irq_lock, flags);
if (irq & 8) {
slave_mask |= (1 << (irq&7));
eisa_out8(slave_mask, 0xa1);
} else {
master_mask |= (1 << (irq&7));
eisa_out8(master_mask, 0x21);
}
spin_unlock_irqrestore(&eisa_irq_lock, flags);
}
static void eisa_unmask_irq(void *irq_dev, int irq)
{
unsigned long flags;
EISA_DBG("unmask irq %d\n", irq);
/* unmask */
spin_lock_irqsave(&eisa_irq_lock, flags);
if (irq & 8) {
slave_mask &= ~(1 << (irq&7));
eisa_out8(slave_mask, 0xa1);
} else {
master_mask &= ~(1 << (irq&7));
eisa_out8(master_mask, 0x21);
}
spin_unlock_irqrestore(&eisa_irq_lock, flags);
} }
static struct irqaction action[IRQ_PER_REGION]; static struct hw_interrupt_type eisa_interrupt_type = {
.typename = "EISA",
/* EISA needs to be fixed at IRQ region #0 (EISA_IRQ_REGION) */ .startup = eisa_startup_irq,
static struct irq_region eisa_irq_region = { .shutdown = eisa_disable_irq,
.ops = { eisa_disable_irq, eisa_enable_irq, eisa_mask_irq, eisa_unmask_irq }, .enable = eisa_enable_irq,
.data = { .name = "EISA", .irqbase = 0 }, .disable = eisa_disable_irq,
.action = action, .ack = no_ack_irq,
.end = no_end_irq,
}; };
static irqreturn_t eisa_irq(int _, void *intr_dev, struct pt_regs *regs) static irqreturn_t eisa_irq(int wax_irq, void *intr_dev, struct pt_regs *regs)
{ {
extern void do_irq(struct irqaction *a, int i, struct pt_regs *p);
int irq = gsc_readb(0xfc01f000); /* EISA supports 16 irqs */ int irq = gsc_readb(0xfc01f000); /* EISA supports 16 irqs */
unsigned long flags; unsigned long flags;
...@@ -259,8 +231,7 @@ static irqreturn_t eisa_irq(int _, void *intr_dev, struct pt_regs *regs) ...@@ -259,8 +231,7 @@ static irqreturn_t eisa_irq(int _, void *intr_dev, struct pt_regs *regs)
} }
spin_unlock_irqrestore(&eisa_irq_lock, flags); spin_unlock_irqrestore(&eisa_irq_lock, flags);
__do_IRQ(irq, regs);
do_irq(&eisa_irq_region.action[irq], EISA_IRQ_REGION + irq, regs);
spin_lock_irqsave(&eisa_irq_lock, flags); spin_lock_irqsave(&eisa_irq_lock, flags);
/* unmask */ /* unmask */
...@@ -281,6 +252,11 @@ static irqreturn_t dummy_irq2_handler(int _, void *dev, struct pt_regs *regs) ...@@ -281,6 +252,11 @@ static irqreturn_t dummy_irq2_handler(int _, void *dev, struct pt_regs *regs)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static struct irqaction irq2_action = {
.handler = dummy_irq2_handler,
.name = "cascade",
};
static void init_eisa_pic(void) static void init_eisa_pic(void)
{ {
unsigned long flags; unsigned long flags;
...@@ -331,7 +307,7 @@ static void init_eisa_pic(void) ...@@ -331,7 +307,7 @@ static void init_eisa_pic(void)
static int __devinit eisa_probe(struct parisc_device *dev) static int __devinit eisa_probe(struct parisc_device *dev)
{ {
int result; int i, result;
char *name = is_mongoose(dev) ? "Mongoose" : "Wax"; char *name = is_mongoose(dev) ? "Mongoose" : "Wax";
...@@ -361,18 +337,18 @@ static int __devinit eisa_probe(struct parisc_device *dev) ...@@ -361,18 +337,18 @@ static int __devinit eisa_probe(struct parisc_device *dev)
} }
pcibios_register_hba(&eisa_dev.hba); pcibios_register_hba(&eisa_dev.hba);
result = request_irq(dev->irq, eisa_irq, SA_SHIRQ, "EISA", NULL); result = request_irq(dev->irq, eisa_irq, SA_SHIRQ, "EISA", &eisa_dev);
if (result) { if (result) {
printk(KERN_ERR "EISA: request_irq failed!\n"); printk(KERN_ERR "EISA: request_irq failed!\n");
return result; return result;
} }
/* Reserve IRQ2 */ /* Reserve IRQ2 */
action[2].handler = dummy_irq2_handler; irq_desc[2].action = &irq2_action;
action[2].name = "cascade";
eisa_irq_region.data.dev = dev; for (i = 0; i < 16; i++) {
irq_region[0] = &eisa_irq_region; irq_desc[i].handler = &eisa_interrupt_type;
}
EISA_bus = 1; EISA_bus = 1;
if (dev->num_addrs) { if (dev->num_addrs) {
......
...@@ -25,15 +25,9 @@ ...@@ -25,15 +25,9 @@
#include <asm/hardware.h> #include <asm/hardware.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/irq.h>
#include "gsc.h" #include "gsc.h"
/* This sets the vmerge boundary and size, it's here because it has to
* be available on all platforms (zero means no-virtual merging) */
unsigned long parisc_vmerge_boundary = 0;
unsigned long parisc_vmerge_max_size = 0;
#undef DEBUG #undef DEBUG
#ifdef DEBUG #ifdef DEBUG
...@@ -61,7 +55,7 @@ int gsc_claim_irq(struct gsc_irq *i, int irq) ...@@ -61,7 +55,7 @@ int gsc_claim_irq(struct gsc_irq *i, int irq)
{ {
int c = irq; int c = irq;
irq += IRQ_FROM_REGION(CPU_IRQ_REGION); /* virtualize the IRQ first */ irq += CPU_IRQ_BASE; /* virtualize the IRQ first */
irq = txn_claim_irq(irq); irq = txn_claim_irq(irq);
if (irq < 0) { if (irq < 0) {
...@@ -79,116 +73,146 @@ int gsc_claim_irq(struct gsc_irq *i, int irq) ...@@ -79,116 +73,146 @@ int gsc_claim_irq(struct gsc_irq *i, int irq)
EXPORT_SYMBOL(gsc_alloc_irq); EXPORT_SYMBOL(gsc_alloc_irq);
EXPORT_SYMBOL(gsc_claim_irq); EXPORT_SYMBOL(gsc_claim_irq);
/* IRQ bits must be numbered from Most Significant Bit */
#define GSC_FIX_IRQ(x) (31-(x))
#define GSC_MASK_IRQ(x) (1<<(GSC_FIX_IRQ(x)))
/* Common interrupt demultiplexer used by Asp, Lasi & Wax. */ /* Common interrupt demultiplexer used by Asp, Lasi & Wax. */
irqreturn_t busdev_barked(int busdev_irq, void *dev, struct pt_regs *regs) irqreturn_t gsc_asic_intr(int gsc_asic_irq, void *dev, struct pt_regs *regs)
{ {
unsigned long irq; unsigned long irr;
struct busdevice *busdev = (struct busdevice *) dev; struct gsc_asic *gsc_asic = dev;
/* irr = gsc_readl(gsc_asic->hpa + OFFSET_IRR);
Don't need to protect OFFSET_IRR with spinlock since this is if (irr == 0)
the only place it's touched. return IRQ_NONE;
Protect busdev_region by disabling this region's interrupts,
modifying the region, and then re-enabling the region.
*/
irq = gsc_readl(busdev->hpa+OFFSET_IRR); DEBPRINTK("%s intr, mask=0x%x\n", gsc_asic->name, irr);
if (irq == 0) {
printk(KERN_ERR "%s: barking without apparent reason.\n", busdev->name); do {
} else { int local_irq = __ffs(irr);
DEBPRINTK ("%s (0x%x) barked, mask=0x%x, irq=%d\n", unsigned int irq = gsc_asic->global_irq[local_irq];
busdev->name, busdev->busdev_region->data.irqbase, __do_IRQ(irq, regs);
irq, GSC_FIX_IRQ(ffs(irq))+1 ); irr &= ~(1 << local_irq);
} while (irr);
do_irq_mask(irq, busdev->busdev_region, regs);
}
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static void int gsc_find_local_irq(unsigned int irq, int *global_irqs, int limit)
busdev_disable_irq(void *irq_dev, int irq)
{ {
/* Disable the IRQ line by clearing the bit in the IMR */ int local_irq;
u32 imr = gsc_readl(BUSDEV_DEV(irq_dev)->hpa+OFFSET_IMR);
imr &= ~(GSC_MASK_IRQ(irq));
DEBPRINTK( KERN_WARNING "%s(%p, %d) %s: IMR 0x%x\n", for (local_irq = 0; local_irq < limit; local_irq++) {
__FUNCTION__, irq_dev, irq, BUSDEV_DEV(irq_dev)->name, imr); if (global_irqs[local_irq] == irq)
return local_irq;
}
gsc_writel(imr, BUSDEV_DEV(irq_dev)->hpa+OFFSET_IMR); return NO_IRQ;
} }
static void gsc_asic_disable_irq(unsigned int irq)
{
struct gsc_asic *irq_dev = irq_desc[irq].handler_data;
int local_irq = gsc_find_local_irq(irq, irq_dev->global_irq, 32);
u32 imr;
DEBPRINTK(KERN_DEBUG "%s(%d) %s: IMR 0x%x\n", __FUNCTION__, irq,
irq_dev->name, imr);
/* Disable the IRQ line by clearing the bit in the IMR */
imr = gsc_readl(irq_dev->hpa + OFFSET_IMR);
imr &= ~(1 << local_irq);
gsc_writel(imr, irq_dev->hpa + OFFSET_IMR);
}
static void static void gsc_asic_enable_irq(unsigned int irq)
busdev_enable_irq(void *irq_dev, int irq)
{ {
/* Enable the IRQ line by setting the bit in the IMR */ struct gsc_asic *irq_dev = irq_desc[irq].handler_data;
unsigned long addr = BUSDEV_DEV(irq_dev)->hpa + OFFSET_IMR; int local_irq = gsc_find_local_irq(irq, irq_dev->global_irq, 32);
u32 imr = gsc_readl(addr); u32 imr;
imr |= GSC_MASK_IRQ(irq);
DEBPRINTK (KERN_WARNING "%s(%p, %d) %s: IMR 0x%x\n", DEBPRINTK(KERN_DEBUG "%s(%d) %s: IMR 0x%x\n", __FUNCTION__, irq,
__FUNCTION__, irq_dev, irq, BUSDEV_DEV(irq_dev)->name, imr); irq_dev->name, imr);
gsc_writel(imr, addr); /* Enable the IRQ line by setting the bit in the IMR */
// gsc_writel(~0L, addr); imr = gsc_readl(irq_dev->hpa + OFFSET_IMR);
imr |= 1 << local_irq;
gsc_writel(imr, irq_dev->hpa + OFFSET_IMR);
/*
* FIXME: read IPR to make sure the IRQ isn't already pending.
* If so, we need to read IRR and manually call do_irq().
*/
}
/* FIXME: read IPR to make sure the IRQ isn't already pending. static unsigned int gsc_asic_startup_irq(unsigned int irq)
** If so, we need to read IRR and manually call do_irq_mask(). {
** This code should be shared with busdev_unmask_irq(). gsc_asic_enable_irq(irq);
*/ return 0;
} }
static void static struct hw_interrupt_type gsc_asic_interrupt_type = {
busdev_mask_irq(void *irq_dev, int irq) .typename = "GSC-ASIC",
.startup = gsc_asic_startup_irq,
.shutdown = gsc_asic_disable_irq,
.enable = gsc_asic_enable_irq,
.disable = gsc_asic_disable_irq,
.ack = no_ack_irq,
.end = no_end_irq,
};
int gsc_assign_irq(struct hw_interrupt_type *type, void *data)
{ {
/* FIXME: Clear the IMR bit in busdev for that IRQ */ static int irq = GSC_IRQ_BASE;
if (irq > GSC_IRQ_MAX)
return NO_IRQ;
irq_desc[irq].handler = type;
irq_desc[irq].handler_data = data;
return irq++;
} }
static void void gsc_asic_assign_irq(struct gsc_asic *asic, int local_irq, int *irqp)
busdev_unmask_irq(void *irq_dev, int irq)
{ {
/* FIXME: Read IPR. Set the IMR bit in busdev for that IRQ. int irq = gsc_assign_irq(&gsc_asic_interrupt_type, asic);
call do_irq_mask() if IPR is non-zero if (irq == NO_IRQ)
*/ return;
*irqp = irq;
asic->global_irq[local_irq] = irq;
} }
struct irq_region_ops busdev_irq_ops = { void gsc_fixup_irqs(struct parisc_device *parent, void *ctrl,
.disable_irq = busdev_disable_irq, void (*choose_irq)(struct parisc_device *, void *))
.enable_irq = busdev_enable_irq, {
.mask_irq = busdev_mask_irq, struct device *dev;
.unmask_irq = busdev_unmask_irq
};
list_for_each_entry(dev, &parent->dev.children, node) {
struct parisc_device *padev = to_parisc_device(dev);
int gsc_common_irqsetup(struct parisc_device *parent, struct busdevice *busdev) /* work-around for 715/64 and others which have parent
at path [5] and children at path [5/0/x] */
if (padev->id.hw_type == HPHW_FAULTY)
return gsc_fixup_irqs(padev, ctrl, choose_irq);
choose_irq(padev, ctrl);
}
}
int gsc_common_setup(struct parisc_device *parent, struct gsc_asic *gsc_asic)
{ {
struct resource *res; struct resource *res;
busdev->gsc = parent; gsc_asic->gsc = parent;
/* the IRQs we simulate */
busdev->busdev_region = alloc_irq_region(32, &busdev_irq_ops,
busdev->name, busdev);
if (!busdev->busdev_region)
return -ENOMEM;
/* allocate resource region */ /* allocate resource region */
res = request_mem_region(busdev->hpa, 0x100000, busdev->name); res = request_mem_region(gsc_asic->hpa, 0x100000, gsc_asic->name);
if (res) { if (res) {
res->flags = IORESOURCE_MEM; /* do not mark it busy ! */ res->flags = IORESOURCE_MEM; /* do not mark it busy ! */
} }
#if 0 #if 0
printk(KERN_WARNING "%s IRQ %d EIM 0x%x", busdev->name, printk(KERN_WARNING "%s IRQ %d EIM 0x%x", gsc_asic->name,
busdev->parent_irq, busdev->eim); parent->irq, gsc_asic->eim);
if (gsc_readl(busdev->hpa + OFFSET_IMR)) if (gsc_readl(gsc_asic->hpa + OFFSET_IMR))
printk(" IMR is non-zero! (0x%x)", printk(" IMR is non-zero! (0x%x)",
gsc_readl(busdev->hpa + OFFSET_IMR)); gsc_readl(gsc_asic->hpa + OFFSET_IMR));
printk("\n"); printk("\n");
#endif #endif
......
...@@ -25,22 +25,23 @@ struct gsc_irq { ...@@ -25,22 +25,23 @@ struct gsc_irq {
int irq; /* virtual IRQ */ int irq; /* virtual IRQ */
}; };
struct busdevice { struct gsc_asic {
struct parisc_device *gsc; struct parisc_device *gsc;
unsigned long hpa; unsigned long hpa;
char *name; char *name;
int version; int version;
int type; int type;
int parent_irq;
int eim; int eim;
struct irq_region *busdev_region; int global_irq[32];
}; };
/* short cut to keep the compiler happy */ int gsc_common_setup(struct parisc_device *parent, struct gsc_asic *gsc_asic);
#define BUSDEV_DEV(x) ((struct busdevice *) (x)) int gsc_alloc_irq(struct gsc_irq *dev); /* dev needs an irq */
int gsc_claim_irq(struct gsc_irq *dev, int irq); /* dev needs this irq */
int gsc_assign_irq(struct hw_interrupt_type *type, void *data);
int gsc_find_local_irq(unsigned int irq, int *global_irq, int limit);
void gsc_fixup_irqs(struct parisc_device *parent, void *ctrl,
void (*choose)(struct parisc_device *child, void *ctrl));
void gsc_asic_assign_irq(struct gsc_asic *asic, int local_irq, int *irqp);
int gsc_common_irqsetup(struct parisc_device *parent, struct busdevice *busdev); irqreturn_t gsc_asic_intr(int irq, void *dev, struct pt_regs *regs);
extern int gsc_alloc_irq(struct gsc_irq *dev); /* dev needs an irq */
extern int gsc_claim_irq(struct gsc_irq *dev, int irq); /* dev needs this irq */
irqreturn_t busdev_barked(int busdev_irq, void *dev, struct pt_regs *regs);
This diff is collapsed.
...@@ -136,23 +136,20 @@ struct vector_info { ...@@ -136,23 +136,20 @@ struct vector_info {
u32 eoi_data; /* IA64: ? PA: swapped txn_data */ u32 eoi_data; /* IA64: ? PA: swapped txn_data */
int txn_irq; /* virtual IRQ number for processor */ int txn_irq; /* virtual IRQ number for processor */
ulong txn_addr; /* IA64: id_eid PA: partial HPA */ ulong txn_addr; /* IA64: id_eid PA: partial HPA */
ulong txn_data; /* IA64: vector PA: EIR bit */ u32 txn_data; /* CPU interrupt bit */
u8 status; /* status/flags */ u8 status; /* status/flags */
u8 irqline; /* INTINn(IRQ) */ u8 irqline; /* INTINn(IRQ) */
char name[32]; /* user visible identity */
}; };
struct iosapic_info { struct iosapic_info {
struct iosapic_info *isi_next; /* list of I/O SAPIC */ struct iosapic_info * isi_next; /* list of I/O SAPIC */
void __iomem * addr; /* remapped address */
unsigned long isi_hpa; /* physical base address */ unsigned long isi_hpa; /* physical base address */
struct irq_region *isi_region; /* each I/O SAPIC is one region */ struct vector_info * isi_vector; /* IRdT (IRQ line) array */
struct vector_info *isi_vector; /* IRdT (IRQ line) array */
int isi_num_vectors; /* size of IRdT array */ int isi_num_vectors; /* size of IRdT array */
int isi_status; /* status/flags */ int isi_status; /* status/flags */
unsigned int isi_version; /* DEBUG: data fr version reg */ unsigned int isi_version; /* DEBUG: data fr version reg */
/* round up to next cacheline */
char isi_name[20]; /* identify region for users */
}; };
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/irq.h> #include <linux/interrupt.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/pm.h> #include <linux/pm.h>
...@@ -35,33 +35,30 @@ ...@@ -35,33 +35,30 @@
#define LASI_IO_CONF 0x7FFFE /* LASI primary configuration register */ #define LASI_IO_CONF 0x7FFFE /* LASI primary configuration register */
#define LASI_IO_CONF2 0x7FFFF /* LASI secondary configuration register */ #define LASI_IO_CONF2 0x7FFFF /* LASI secondary configuration register */
static int lasi_choose_irq(struct parisc_device *dev) static void lasi_choose_irq(struct parisc_device *dev, void *ctrl)
{ {
int irq; int irq;
/*
** "irq" bits below are numbered relative to most significant bit.
*/
switch (dev->id.sversion) { switch (dev->id.sversion) {
case 0x74: irq = 24; break; /* Centronics */ case 0x74: irq = 7; break; /* Centronics */
case 0x7B: irq = 18; break; /* Audio */ case 0x7B: irq = 13; break; /* Audio */
case 0x81: irq = 17; break; /* Lasi itself */ case 0x81: irq = 14; break; /* Lasi itself */
case 0x82: irq = 22; break; /* SCSI */ case 0x82: irq = 9; break; /* SCSI */
case 0x83: irq = 11; break; /* Floppy */ case 0x83: irq = 20; break; /* Floppy */
case 0x84: irq = 5; break; /* PS/2 Keyboard */ case 0x84: irq = 26; break; /* PS/2 Keyboard */
case 0x87: irq = 13; break; /* ISDN */ case 0x87: irq = 18; break; /* ISDN */
case 0x8A: irq = 23; break; /* LAN */ case 0x8A: irq = 8; break; /* LAN */
case 0x8C: irq = 26; break; /* RS232 */ case 0x8C: irq = 5; break; /* RS232 */
case 0x8D: irq = (dev->hw_path == 13) ? 15 : 14; case 0x8D: irq = (dev->hw_path == 13) ? 16 : 17; break;
break; /* Telephone */ /* Telephone */
default: irq = -1; break; /* unknown */ default: return; /* unknown */
} }
return irq; gsc_asic_assign_irq(ctrl, irq, &dev->irq);
} }
static void __init static void __init
lasi_init_irq(struct busdevice *this_lasi) lasi_init_irq(struct gsc_asic *this_lasi)
{ {
unsigned long lasi_base = this_lasi->hpa; unsigned long lasi_base = this_lasi->hpa;
...@@ -170,11 +167,11 @@ static void lasi_power_off(void) ...@@ -170,11 +167,11 @@ static void lasi_power_off(void)
int __init int __init
lasi_init_chip(struct parisc_device *dev) lasi_init_chip(struct parisc_device *dev)
{ {
struct busdevice *lasi; struct gsc_asic *lasi;
struct gsc_irq gsc_irq; struct gsc_irq gsc_irq;
int irq, ret; int ret;
lasi = kmalloc(sizeof(struct busdevice), GFP_KERNEL); lasi = kmalloc(sizeof(*lasi), GFP_KERNEL);
if (!lasi) if (!lasi)
return -ENOMEM; return -ENOMEM;
...@@ -193,36 +190,33 @@ lasi_init_chip(struct parisc_device *dev) ...@@ -193,36 +190,33 @@ lasi_init_chip(struct parisc_device *dev)
lasi_init_irq(lasi); lasi_init_irq(lasi);
/* the IRQ lasi should use */ /* the IRQ lasi should use */
irq = gsc_alloc_irq(&gsc_irq); dev->irq = gsc_alloc_irq(&gsc_irq);
if (irq < 0) { if (dev->irq < 0) {
printk(KERN_ERR "%s(): cannot get GSC irq\n", printk(KERN_ERR "%s(): cannot get GSC irq\n",
__FUNCTION__); __FUNCTION__);
kfree(lasi); kfree(lasi);
return -EBUSY; return -EBUSY;
} }
ret = request_irq(gsc_irq.irq, busdev_barked, 0, "lasi", lasi); lasi->eim = ((u32) gsc_irq.txn_addr) | gsc_irq.txn_data;
ret = request_irq(gsc_irq.irq, gsc_asic_intr, 0, "lasi", lasi);
if (ret < 0) { if (ret < 0) {
kfree(lasi); kfree(lasi);
return ret; return ret;
} }
/* Save this for debugging later */
lasi->parent_irq = gsc_irq.irq;
lasi->eim = ((u32) gsc_irq.txn_addr) | gsc_irq.txn_data;
/* enable IRQ's for devices below LASI */ /* enable IRQ's for devices below LASI */
gsc_writel(lasi->eim, lasi->hpa + OFFSET_IAR); gsc_writel(lasi->eim, lasi->hpa + OFFSET_IAR);
/* Done init'ing, register this driver */ /* Done init'ing, register this driver */
ret = gsc_common_irqsetup(dev, lasi); ret = gsc_common_setup(dev, lasi);
if (ret) { if (ret) {
kfree(lasi); kfree(lasi);
return ret; return ret;
} }
fixup_child_irqs(dev, lasi->busdev_region->data.irqbase, gsc_fixup_irqs(dev, lasi, lasi_choose_irq);
lasi_choose_irq);
/* initialize the power off function */ /* initialize the power off function */
/* FIXME: Record the LASI HPA for the power off function. This should /* FIXME: Record the LASI HPA for the power off function. This should
......
...@@ -41,11 +41,9 @@ ...@@ -41,11 +41,9 @@
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <asm/byteorder.h> #include <asm/byteorder.h>
#include <asm/irq.h> /* for struct irq_region support */
#include <asm/pdc.h> #include <asm/pdc.h>
#include <asm/pdcpat.h> #include <asm/pdcpat.h>
#include <asm/page.h> #include <asm/page.h>
#include <asm/segment.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/hardware.h> /* for register_parisc_driver() stuff */ #include <asm/hardware.h> /* for register_parisc_driver() stuff */
......
...@@ -72,7 +72,6 @@ ...@@ -72,7 +72,6 @@
#include <asm/io.h> #include <asm/io.h>
#include <asm/hardware.h> #include <asm/hardware.h>
#include <asm/irq.h>
#include <asm/superio.h> #include <asm/superio.h>
static struct superio_device sio_dev; static struct superio_device sio_dev;
...@@ -87,9 +86,8 @@ static struct superio_device sio_dev; ...@@ -87,9 +86,8 @@ static struct superio_device sio_dev;
#endif #endif
static irqreturn_t static irqreturn_t
superio_interrupt(int irq, void *devp, struct pt_regs *regs) superio_interrupt(int parent_irq, void *devp, struct pt_regs *regs)
{ {
struct superio_device *sio = (struct superio_device *)devp;
u8 results; u8 results;
u8 local_irq; u8 local_irq;
...@@ -108,7 +106,7 @@ superio_interrupt(int irq, void *devp, struct pt_regs *regs) ...@@ -108,7 +106,7 @@ superio_interrupt(int irq, void *devp, struct pt_regs *regs)
* We don't know if an interrupt was/is pending and thus * We don't know if an interrupt was/is pending and thus
* just call the handler for that IRQ as if it were pending. * just call the handler for that IRQ as if it were pending.
*/ */
return IRQ_HANDLED; return IRQ_NONE;
} }
/* Check to see which device is interrupting */ /* Check to see which device is interrupting */
...@@ -116,7 +114,6 @@ superio_interrupt(int irq, void *devp, struct pt_regs *regs) ...@@ -116,7 +114,6 @@ superio_interrupt(int irq, void *devp, struct pt_regs *regs)
if (local_irq == 2 || local_irq > 7) { if (local_irq == 2 || local_irq > 7) {
printk(KERN_ERR "SuperIO: slave interrupted!\n"); printk(KERN_ERR "SuperIO: slave interrupted!\n");
BUG();
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -133,9 +130,7 @@ superio_interrupt(int irq, void *devp, struct pt_regs *regs) ...@@ -133,9 +130,7 @@ superio_interrupt(int irq, void *devp, struct pt_regs *regs)
} }
/* Call the appropriate device's interrupt */ /* Call the appropriate device's interrupt */
do_irq(&sio->irq_region->action[local_irq], __do_IRQ(local_irq, regs);
sio->irq_region->data.irqbase + local_irq,
regs);
/* set EOI - forces a new interrupt if a lower priority device /* set EOI - forces a new interrupt if a lower priority device
* still needs service. * still needs service.
...@@ -280,12 +275,11 @@ superio_init(struct superio_device *sio) ...@@ -280,12 +275,11 @@ superio_init(struct superio_device *sio)
} }
static void static void superio_disable_irq(unsigned int irq)
superio_disable_irq(void *dev, int local_irq)
{ {
u8 r8; u8 r8;
if ((local_irq < 1) || (local_irq == 2) || (local_irq > 7)) { if ((irq < 1) || (irq == 2) || (irq > 7)) {
printk(KERN_ERR "SuperIO: Illegal irq number.\n"); printk(KERN_ERR "SuperIO: Illegal irq number.\n");
BUG(); BUG();
return; return;
...@@ -294,45 +288,40 @@ superio_disable_irq(void *dev, int local_irq) ...@@ -294,45 +288,40 @@ superio_disable_irq(void *dev, int local_irq)
/* Mask interrupt */ /* Mask interrupt */
r8 = inb(IC_PIC1+1); r8 = inb(IC_PIC1+1);
r8 |= (1 << local_irq); r8 |= (1 << irq);
outb (r8,IC_PIC1+1); outb (r8,IC_PIC1+1);
} }
static void static void superio_enable_irq(unsigned int irq)
superio_enable_irq(void *dev, int local_irq)
{ {
u8 r8; u8 r8;
if ((local_irq < 1) || (local_irq == 2) || (local_irq > 7)) { if ((irq < 1) || (irq == 2) || (irq > 7)) {
printk(KERN_ERR "SuperIO: Illegal irq number (%d).\n", local_irq); printk(KERN_ERR "SuperIO: Illegal irq number (%d).\n", irq);
BUG(); BUG();
return; return;
} }
/* Unmask interrupt */ /* Unmask interrupt */
r8 = inb(IC_PIC1+1); r8 = inb(IC_PIC1+1);
r8 &= ~(1 << local_irq); r8 &= ~(1 << irq);
outb (r8,IC_PIC1+1); outb (r8,IC_PIC1+1);
} }
static unsigned int superio_startup_irq(unsigned int irq)
static void
superio_mask_irq(void *dev, int local_irq)
{
BUG();
}
static void
superio_unmask_irq(void *dev, int local_irq)
{ {
BUG(); superio_enable_irq(irq);
return 0;
} }
static struct irq_region_ops superio_irq_ops = { static struct hw_interrupt_type superio_interrupt_type = {
.disable_irq = superio_disable_irq, .typename = "SuperIO",
.enable_irq = superio_enable_irq, .startup = superio_startup_irq,
.mask_irq = superio_mask_irq, .shutdown = superio_disable_irq,
.unmask_irq = superio_unmask_irq .enable = superio_enable_irq,
.disable = superio_disable_irq,
.ack = no_ack_irq,
.end = no_end_irq,
}; };
#ifdef DEBUG_SUPERIO_INIT #ifdef DEBUG_SUPERIO_INIT
...@@ -345,7 +334,7 @@ static unsigned short expected_device[3] = { ...@@ -345,7 +334,7 @@ static unsigned short expected_device[3] = {
int superio_fixup_irq(struct pci_dev *pcidev) int superio_fixup_irq(struct pci_dev *pcidev)
{ {
int local_irq; int local_irq, i;
#ifdef DEBUG_SUPERIO_INIT #ifdef DEBUG_SUPERIO_INIT
int fn; int fn;
...@@ -362,15 +351,8 @@ int superio_fixup_irq(struct pci_dev *pcidev) ...@@ -362,15 +351,8 @@ int superio_fixup_irq(struct pci_dev *pcidev)
__builtin_return_address(0)); __builtin_return_address(0));
#endif #endif
if (!sio_dev.irq_region) { for (i = 0; i < 16; i++) {
/* Allocate an irq region for SuperIO devices */ irq_desc[i].handler = &superio_interrupt_type;
sio_dev.irq_region = alloc_irq_region(SUPERIO_NIRQS,
&superio_irq_ops,
"SuperIO", (void *) &sio_dev);
if (!sio_dev.irq_region) {
printk(KERN_WARNING "SuperIO: alloc_irq_region failed\n");
return -1;
}
} }
/* /*
...@@ -396,7 +378,7 @@ int superio_fixup_irq(struct pci_dev *pcidev) ...@@ -396,7 +378,7 @@ int superio_fixup_irq(struct pci_dev *pcidev)
break; break;
} }
return(sio_dev.irq_region->data.irqbase + local_irq); return local_irq;
} }
static struct uart_port serial[] = { static struct uart_port serial[] = {
...@@ -416,25 +398,13 @@ static struct uart_port serial[] = { ...@@ -416,25 +398,13 @@ static struct uart_port serial[] = {
} }
}; };
void __devinit static void __devinit superio_serial_init(void)
superio_serial_init(void)
{ {
#ifdef CONFIG_SERIAL_8250 #ifdef CONFIG_SERIAL_8250
int retval; int retval;
#ifdef CONFIG_SERIAL_8250_CONSOLE
extern void serial8250_console_init(void); /* drivers/serial/8250.c */
#endif
if (!sio_dev.irq_region)
return; /* superio not present */
if (!serial) {
printk(KERN_WARNING "SuperIO: Could not get memory for serial struct.\n");
return;
}
serial[0].iobase = sio_dev.sp1_base; serial[0].iobase = sio_dev.sp1_base;
serial[0].irq = sio_dev.irq_region->data.irqbase + SP1_IRQ; serial[0].irq = SP1_IRQ;
retval = early_serial_setup(&serial[0]); retval = early_serial_setup(&serial[0]);
if (retval < 0) { if (retval < 0) {
...@@ -442,12 +412,8 @@ superio_serial_init(void) ...@@ -442,12 +412,8 @@ superio_serial_init(void)
return; return;
} }
#ifdef CONFIG_SERIAL_8250_CONSOLE
serial8250_console_init();
#endif
serial[1].iobase = sio_dev.sp2_base; serial[1].iobase = sio_dev.sp2_base;
serial[1].irq = sio_dev.irq_region->data.irqbase + SP2_IRQ; serial[1].irq = SP2_IRQ;
retval = early_serial_setup(&serial[1]); retval = early_serial_setup(&serial[1]);
if (retval < 0) if (retval < 0)
...@@ -456,13 +422,12 @@ superio_serial_init(void) ...@@ -456,13 +422,12 @@ superio_serial_init(void)
} }
static void __devinit static void __devinit superio_parport_init(void)
superio_parport_init(void)
{ {
#ifdef CONFIG_PARPORT_PC #ifdef CONFIG_PARPORT_PC
if (!parport_pc_probe_port(sio_dev.pp_base, if (!parport_pc_probe_port(sio_dev.pp_base,
0 /*base_hi*/, 0 /*base_hi*/,
sio_dev.irq_region->data.irqbase + PAR_IRQ, PAR_IRQ,
PARPORT_DMA_NONE /* dma */, PARPORT_DMA_NONE /* dma */,
NULL /*struct pci_dev* */) ) NULL /*struct pci_dev* */) )
...@@ -471,7 +436,7 @@ superio_parport_init(void) ...@@ -471,7 +436,7 @@ superio_parport_init(void)
} }
void superio_fixup_pci(struct pci_dev *pdev) static void superio_fixup_pci(struct pci_dev *pdev)
{ {
u8 prog; u8 prog;
......
...@@ -21,28 +21,28 @@ ...@@ -21,28 +21,28 @@
#include <asm/io.h> #include <asm/io.h>
#include <asm/hardware.h> #include <asm/hardware.h>
#include <asm/irq.h>
#include "gsc.h" #include "gsc.h"
#define WAX_GSC_IRQ 7 /* Hardcoded Interrupt for GSC */ #define WAX_GSC_IRQ 7 /* Hardcoded Interrupt for GSC */
#define WAX_GSC_NMI_IRQ 29 #define WAX_GSC_NMI_IRQ 29
static int wax_choose_irq(struct parisc_device *dev) static void wax_choose_irq(struct parisc_device *dev, void *ctrl)
{ {
int irq = -1; int irq;
switch (dev->id.sversion) { switch (dev->id.sversion) {
case 0x73: irq = 30; break; /* HIL */ case 0x73: irq = 1; break; /* HIL */
case 0x8c: irq = 25; break; /* RS232 */ case 0x8c: irq = 6; break; /* RS232 */
case 0x90: irq = 21; break; /* WAX EISA BA */ case 0x90: irq = 10; break; /* WAX EISA BA */
default: return; /* Unknown */
} }
return irq; gsc_asic_assign_irq(ctrl, irq, &dev->irq);
} }
static void __init static void __init
wax_init_irq(struct busdevice *wax) wax_init_irq(struct gsc_asic *wax)
{ {
unsigned long base = wax->hpa; unsigned long base = wax->hpa;
...@@ -50,7 +50,7 @@ wax_init_irq(struct busdevice *wax) ...@@ -50,7 +50,7 @@ wax_init_irq(struct busdevice *wax)
gsc_writel(0x00000000, base+OFFSET_IMR); gsc_writel(0x00000000, base+OFFSET_IMR);
/* clear pending interrupts */ /* clear pending interrupts */
(volatile u32) gsc_readl(base+OFFSET_IRR); gsc_readl(base+OFFSET_IRR);
/* We're not really convinced we want to reset the onboard /* We're not really convinced we want to reset the onboard
* devices. Firmware does it for us... * devices. Firmware does it for us...
...@@ -69,11 +69,12 @@ wax_init_irq(struct busdevice *wax) ...@@ -69,11 +69,12 @@ wax_init_irq(struct busdevice *wax)
int __init int __init
wax_init_chip(struct parisc_device *dev) wax_init_chip(struct parisc_device *dev)
{ {
struct busdevice *wax; struct gsc_asic *wax;
struct parisc_device *parent;
struct gsc_irq gsc_irq; struct gsc_irq gsc_irq;
int irq, ret; int ret;
wax = kmalloc(sizeof(struct busdevice), GFP_KERNEL); wax = kmalloc(sizeof(*wax), GFP_KERNEL);
if (!wax) if (!wax)
return -ENOMEM; return -ENOMEM;
...@@ -87,40 +88,37 @@ wax_init_chip(struct parisc_device *dev) ...@@ -87,40 +88,37 @@ wax_init_chip(struct parisc_device *dev)
wax_init_irq(wax); wax_init_irq(wax);
/* the IRQ wax should use */ /* the IRQ wax should use */
irq = gsc_claim_irq(&gsc_irq, WAX_GSC_IRQ); dev->irq = gsc_claim_irq(&gsc_irq, WAX_GSC_IRQ);
if (irq < 0) { if (dev->irq < 0) {
printk(KERN_ERR "%s(): cannot get GSC irq\n", printk(KERN_ERR "%s(): cannot get GSC irq\n",
__FUNCTION__); __FUNCTION__);
kfree(wax); kfree(wax);
return -EBUSY; return -EBUSY;
} }
ret = request_irq(gsc_irq.irq, busdev_barked, 0, "wax", wax); wax->eim = ((u32) gsc_irq.txn_addr) | gsc_irq.txn_data;
ret = request_irq(gsc_irq.irq, gsc_asic_intr, 0, "wax", wax);
if (ret < 0) { if (ret < 0) {
kfree(wax); kfree(wax);
return ret; return ret;
} }
/* Save this for debugging later */
wax->parent_irq = gsc_irq.irq;
wax->eim = ((u32) gsc_irq.txn_addr) | gsc_irq.txn_data;
/* enable IRQ's for devices below WAX */ /* enable IRQ's for devices below WAX */
gsc_writel(wax->eim, wax->hpa + OFFSET_IAR); gsc_writel(wax->eim, wax->hpa + OFFSET_IAR);
/* Done init'ing, register this driver */ /* Done init'ing, register this driver */
ret = gsc_common_irqsetup(dev, wax); ret = gsc_common_setup(dev, wax);
if (ret) { if (ret) {
kfree(wax); kfree(wax);
return ret; return ret;
} }
fixup_child_irqs(dev, wax->busdev_region->data.irqbase, gsc_fixup_irqs(dev, wax, wax_choose_irq);
wax_choose_irq);
/* On 715-class machines, Wax EISA is a sibling of Wax, not a child. */ /* On 715-class machines, Wax EISA is a sibling of Wax, not a child. */
if (dev->parent->id.hw_type != HPHW_IOA) { parent = parisc_parent(dev);
fixup_child_irqs(dev->parent, wax->busdev_region->data.irqbase, if (parent->id.hw_type != HPHW_IOA) {
wax_choose_irq); gsc_fixup_irqs(parent, wax, wax_choose_irq);
} }
return ret; return ret;
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <linux/config.h> #include <linux/config.h>
#include <linux/threads.h> #include <linux/threads.h>
#include <linux/cache.h> #include <linux/cache.h>
#include <linux/irq.h>
typedef struct { typedef struct {
unsigned long __softirq_pending; /* set_bit is used on this */ unsigned long __softirq_pending; /* set_bit is used on this */
...@@ -28,11 +29,13 @@ typedef struct { ...@@ -28,11 +29,13 @@ typedef struct {
#define HARDIRQ_BITS 16 #define HARDIRQ_BITS 16
/* /*
* The hardirq mask has to be large enough to have space for potentially all IRQ sources * The hardirq mask has to be large enough to have space for potentially all
* in the system nesting on a single CPU: * IRQ sources in the system nesting on a single CPU:
*/ */
#if (1 << HARDIRQ_BITS) < NR_IRQS #if (1 << HARDIRQ_BITS) < NR_IRQS
# error HARDIRQ_BITS is too low! # error HARDIRQ_BITS is too low!
#endif #endif
void ack_bad_irq(unsigned int irq);
#endif /* _PARISC_HARDIRQ_H */ #endif /* _PARISC_HARDIRQ_H */
...@@ -12,6 +12,6 @@ ...@@ -12,6 +12,6 @@
* <tomsoft@informatik.tu-chemnitz.de> * <tomsoft@informatik.tu-chemnitz.de>
*/ */
#include <asm/irq.h> extern void hw_resend_irq(struct hw_interrupt_type *, unsigned int);
#endif #endif
/* /*
* linux/include/asm-parisc/irq.h * include/asm-parisc/irq.h
* *
* (C) 1992, 1993 Linus Torvalds, (C) 1997 Ingo Molnar, * Copyright 2005 Matthew Wilcox <matthew@wil.cx>
* Copyright 1999 SuSE GmbH
*
* IRQ/IPI changes taken from work by Thomas Radke
* <tomsoft@informatik.tu-chemnitz.de>
*/ */
#ifndef _ASM_PARISC_IRQ_H #ifndef _ASM_PARISC_IRQ_H
#define _ASM_PARISC_IRQ_H #define _ASM_PARISC_IRQ_H
#include <asm/ptrace.h>
#include <asm/types.h>
#include <asm/errno.h>
#include <linux/string.h>
#include <linux/interrupt.h>
#include <linux/config.h> #include <linux/config.h>
#include <asm/types.h>
#define NO_IRQ (-1)
#define CPU_IRQ_REGION 1 #ifdef CONFIG_GSC
#define TIMER_IRQ (IRQ_FROM_REGION(CPU_IRQ_REGION) | 0) #define GSC_IRQ_BASE 16
#define IPI_IRQ (IRQ_FROM_REGION(CPU_IRQ_REGION) | 1) #define GSC_IRQ_MAX 63
#define CPU_IRQ_BASE 64
/* This should be 31 for PA1.1 binaries and 63 for PA-2.0 wide mode */
#define MAX_CPU_IRQ (BITS_PER_LONG - 1)
#if BITS_PER_LONG == 32
# define IRQ_REGION_SHIFT 5
#else #else
# define IRQ_REGION_SHIFT 6 #define CPU_IRQ_BASE 16
#endif #endif
#define IRQ_PER_REGION (1 << IRQ_REGION_SHIFT) #define TIMER_IRQ (CPU_IRQ_BASE + 0)
#define NR_IRQ_REGS 16 #define IPI_IRQ (CPU_IRQ_BASE + 1)
#define NR_IRQS (NR_IRQ_REGS * IRQ_PER_REGION) #define CPU_IRQ_MAX (CPU_IRQ_BASE + (BITS_PER_LONG - 1))
#define IRQ_REGION(irq) ((irq) >> IRQ_REGION_SHIFT)
#define IRQ_OFFSET(irq) ((irq) & ((1<<IRQ_REGION_SHIFT)-1))
#define IRQ_FROM_REGION(reg) ((reg) << IRQ_REGION_SHIFT)
#define EISA_IRQ_REGION 0 /* region 0 needs to be reserved for EISA */
#define EISA_MAX_IRQS 16 /* max. (E)ISA irq line */
struct irq_region_ops {
void (*disable_irq)(void *dev, int irq);
void (* enable_irq)(void *dev, int irq);
void (* mask_irq)(void *dev, int irq);
void (* unmask_irq)(void *dev, int irq);
};
struct irq_region_data {
void *dev;
const char *name;
int irqbase;
unsigned int status[IRQ_PER_REGION]; /* IRQ status */
};
struct irq_region { #define NR_IRQS (CPU_IRQ_MAX + 1)
struct irq_region_ops ops;
struct irq_region_data data;
struct irqaction *action;
};
extern struct irq_region *irq_region[NR_IRQ_REGS];
static __inline__ int irq_canonicalize(int irq) static __inline__ int irq_canonicalize(int irq)
{ {
#ifdef CONFIG_EISA return (irq == 2) ? 9 : irq;
return (irq == (IRQ_FROM_REGION(EISA_IRQ_REGION)+2)
? (IRQ_FROM_REGION(EISA_IRQ_REGION)+9) : irq);
#else
return irq;
#endif
} }
extern void disable_irq(int); struct hw_interrupt_type;
#define disable_irq_nosync(i) disable_irq(i)
extern void enable_irq(int);
extern void do_irq(struct irqaction *a, int i, struct pt_regs *p);
extern void do_irq_mask(unsigned long mask, struct irq_region *region,
struct pt_regs *regs);
extern struct irq_region *alloc_irq_region(int count, struct irq_region_ops *ops, /*
const char *name, void *dev); * Some useful "we don't have to do anything here" handlers. Should
* probably be provided by the generic code.
*/
void no_ack_irq(unsigned int irq);
void no_end_irq(unsigned int irq);
extern int txn_alloc_irq(void); extern int txn_alloc_irq(void);
extern int txn_claim_irq(int); extern int txn_claim_irq(int);
extern unsigned int txn_alloc_data(int, unsigned int); extern unsigned int txn_alloc_data(int, unsigned int);
extern unsigned long txn_alloc_addr(int); extern unsigned long txn_alloc_addr(int);
extern int cpu_claim_irq(unsigned int irq, struct hw_interrupt_type *, void *);
/* soft power switch support (power.c) */ /* soft power switch support (power.c) */
extern struct tasklet_struct power_tasklet; extern struct tasklet_struct power_tasklet;
struct irqaction;
int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *);
#endif /* _ASM_PARISC_IRQ_H */ #endif /* _ASM_PARISC_IRQ_H */
...@@ -56,7 +56,6 @@ struct superio_device { ...@@ -56,7 +56,6 @@ struct superio_device {
u32 pp_base; u32 pp_base;
u32 acpi_base; u32 acpi_base;
int suckyio_irq_enabled; int suckyio_irq_enabled;
struct irq_region *irq_region;
struct pci_dev *lio_pdev; /* pci device for legacy IO (fn 1) */ struct pci_dev *lio_pdev; /* pci device for legacy IO (fn 1) */
struct pci_dev *usb_pdev; /* pci device for USB (fn 2) */ struct pci_dev *usb_pdev; /* pci device for USB (fn 2) */
}; };
...@@ -81,11 +80,6 @@ struct superio_device { ...@@ -81,11 +80,6 @@ struct superio_device {
|| ((x)->device == PCI_DEVICE_ID_NS_87560_LIO) \ || ((x)->device == PCI_DEVICE_ID_NS_87560_LIO) \
|| ((x)->device == PCI_DEVICE_ID_NS_87560_USB) ) ) || ((x)->device == PCI_DEVICE_ID_NS_87560_USB) ) )
struct hwif_s;
extern void superio_inform_irq(int irq);
extern void superio_serial_init(void); /* called by rs_init() */
extern int superio_fixup_irq(struct pci_dev *pcidev); /* called by iosapic */ extern int superio_fixup_irq(struct pci_dev *pcidev); /* called by iosapic */
extern void superio_fixup_pci(struct pci_dev *pdev);
#endif /* _PARISC_SUPERIO_H */ #endif /* _PARISC_SUPERIO_H */
...@@ -59,9 +59,10 @@ typedef struct hw_interrupt_type hw_irq_controller; ...@@ -59,9 +59,10 @@ typedef struct hw_interrupt_type hw_irq_controller;
* Pad this out to 32 bytes for cache and indexing reasons. * Pad this out to 32 bytes for cache and indexing reasons.
*/ */
typedef struct irq_desc { typedef struct irq_desc {
unsigned int status; /* IRQ status */
hw_irq_controller *handler; hw_irq_controller *handler;
void *handler_data;
struct irqaction *action; /* IRQ action list */ struct irqaction *action; /* IRQ action list */
unsigned int status; /* IRQ status */
unsigned int depth; /* nested irq disables */ unsigned int depth; /* nested irq disables */
unsigned int irq_count; /* For detecting broken interrupts */ unsigned int irq_count; /* For detecting broken interrupts */
unsigned int irqs_unhandled; unsigned int irqs_unhandled;
......
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