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