Commit 1ae6b1ad authored by Tom Rini's avatar Tom Rini

PPC32: Cleanup the i8259 code slightly. Allow for polling of interrupts again

and combine i8259_poll() and i8259_irq().
parent 6db2ecc9
......@@ -67,7 +67,7 @@ obj-$(CONFIG_ADIR) += i8259.o indirect_pci.o pci_auto.o \
todc_time.o
obj-$(CONFIG_EV64260) += gt64260_common.o gt64260_pic.o \
indirect_pci.o todc_time.o pci_auto.o
obj-$(CONFIG_GEMINI) += open_pic.o
obj-$(CONFIG_GEMINI) += open_pic.o i8259.o
obj-$(CONFIG_K2) += i8259.o indirect_pci.o todc_time.o \
pci_auto.o
obj-$(CONFIG_LOPEC) += mpc10x_common.o indirect_pci.o pci_auto.o \
......
......@@ -21,17 +21,37 @@ static spinlock_t i8259_lock = SPIN_LOCK_UNLOCKED;
int i8259_pic_irq_offset;
/* Acknowledge the irq using the PCI host bridge's interrupt acknowledge
* feature. (Polling is somehow broken on some IBM and Motorola PReP boxes.)
/*
* Acknowledge the IRQ using either the PCI host bridge's interrupt
* acknowledge feature or poll. How i8259_init() is called determines
* which is called. It should be noted that polling is broken on some
* IBM and Motorola PReP boxes so we must use the int-ack feature on them.
*/
int i8259_irq(struct pt_regs *regs)
int
i8259_irq(struct pt_regs *regs)
{
int irq;
spin_lock/*_irqsave*/(&i8259_lock/*, flags*/);
spin_lock(&i8259_lock);
/* Either int-ack or poll for the IRQ */
if (pci_intack)
irq = *pci_intack;
else {
/* Perform an interrupt acknowledge cycle on controller 1. */
outb(0x0C, 0x20); /* prepare for poll */
irq = inb(0x20) & 7;
if (irq == 2 ) {
/*
* Interrupt is cascaded so perform interrupt
* acknowledge on controller 2.
*/
outb(0x0C, 0xA0); /* prepare for poll */
irq = (inb(0xA0) & 7) + 8;
}
}
irq = *pci_intack;
if (irq==7) {
if (irq == 7) {
/*
* This may be a spurious interrupt.
*
......@@ -39,47 +59,13 @@ int i8259_irq(struct pt_regs *regs)
* significant bit is not set then there is no valid
* interrupt.
*/
if(~inb(0x20)&0x80) {
if (!pci_intack)
outb(0x0B, 0x20); /* ISR register */
if(~inb(0x20) & 0x80)
irq = -1;
}
}
spin_unlock/*_irqrestore*/(&i8259_lock/*, flags*/);
return irq;
}
/* Poke the 8259's directly using poll commands. */
int i8259_poll(void)
{
int irq;
spin_lock/*_irqsave*/(&i8259_lock/*, flags*/);
/*
* Perform an interrupt acknowledge cycle on controller 1
*/
outb(0x0C, 0x20); /* prepare for poll */
irq = inb(0x20) & 7;
if (irq == 2) {
/*
* Interrupt is cascaded so perform interrupt
* acknowledge on controller 2
*/
outb(0x0C, 0xA0); /* prepare for poll */
irq = (inb(0xA0) & 7) + 8;
} else if (irq==7) {
/*
* This may be a spurious interrupt
*
* Read the interrupt status register. If the most
* significant bit is not set then there is no valid
* interrupt
*/
outb(0x0b, 0x20);
if(~inb(0x20)&0x80) {
spin_unlock/*_irqrestore*/(&i8259_lock/*, flags*/);
return -1;
}
}
spin_unlock/*_irqrestore*/(&i8259_lock/*, flags*/);
spin_unlock(&i8259_lock);
return irq;
}
......@@ -171,11 +157,13 @@ static struct resource pic_edgectrl_iores = {
"8259 edge control", 0x4d0, 0x4d1, IORESOURCE_BUSY
};
/* i8259_init()
/*
* i8259_init()
* intack_addr - PCI interrupt acknowledge (real) address which will return
* the active irq from the 8259
*/
void __init i8259_init(long intack_addr)
void __init
i8259_init(long intack_addr)
{
unsigned long flags;
......@@ -209,9 +197,6 @@ void __init i8259_init(long intack_addr)
request_resource(&ioport_resource, &pic2_iores);
request_resource(&ioport_resource, &pic_edgectrl_iores);
/* XXX remove me after board maintainers fix their i8259_init calls */
if (intack_addr == 0)
panic("You must supply a PCI interrupt acknowledge address to i8259_init()\n");
pci_intack = ioremap(intack_addr, 1);
if (intack_addr != 0)
pci_intack = ioremap(intack_addr, 1);
}
......@@ -799,26 +799,20 @@ static void openpic_ipi_action(int cpl, void *dev_id, struct pt_regs *regs)
#endif /* CONFIG_SMP */
/* This one may be merged with PReP and CHRP */
int
openpic_get_irq(struct pt_regs *regs)
{
/*
* Clean up needed. -VAL
*/
int irq = openpic_irq();
/* Management of the cascade should be moved out of here */
/* Yep - because openpic !=> i8259, for one thing. -VAL */
if (open_pic_irq_offset && irq == open_pic_irq_offset)
{
#ifndef CONFIG_GEMINI
irq = i8259_irq(regs); /* get IRQ from cascade */
#endif
/*
* This needs to be cleaned up. We don't necessarily have
* an i8259 cascaded or even a cascade.
*/
if (open_pic_irq_offset && irq == open_pic_irq_offset) {
/* Get the IRQ from the cascade. */
irq = i8259_irq(regs);
openpic_eoi();
}
if (irq == OPENPIC_VEC_SPURIOUS + open_pic_irq_offset)
} else if (irq == OPENPIC_VEC_SPURIOUS + open_pic_irq_offset)
irq = -1;
return irq;
}
......
......@@ -9,8 +9,7 @@
extern struct hw_interrupt_type i8259_pic;
void i8259_init(long);
int i8259_irq(struct pt_regs *regs);
int i8259_poll(void);
extern void i8259_init(long intack_addr);
extern int i8259_irq(struct pt_regs *regs);
#endif /* _PPC_KERNEL_i8259_H */
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