void innovator_fpga_IRQ_demux(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs) { struct irqdesc *d; u32 stat; int fpga_irq; /* * Acknowledge the parent IRQ. */ desc->chip->ack(irq); for (;;) { stat = get_fpga_unmasked_irqs(); if (!stat) { break; } for (fpga_irq = IH_FPGA_BASE; (fpga_irq < (IH_FPGA_BASE + NR_FPGA_IRQS)) && stat; fpga_irq++, stat >>= 1) { if (stat & 1) { d = irq_desc + fpga_irq; d->handle(fpga_irq, d, regs); desc->chip->unmask(irq); } } } }
static void innovator_fpga_IRQ_demux(int irq, void *dev_id, struct pt_regs *regs) { u32 stat; int fpga_irq; for (;;) { stat = get_fpga_unmasked_irqs(); if (!stat) { #ifdef CONFIG_INNOVATOR_MISSED_IRQS /* We are having a problem with missed Ethernet * interrupts on Innovators with FPGA Revision 2.0. * When an interrupt is missed, the Ethernet controller * is always asserting a level interrupt request, but * no interrupt request is latched in the FPGA * interrupt status register. Our (unproven) theory * is that there is a race condition in the FPGA such * that if the status register is read at the same time * a new interrupt request is asserted that the request * will be cleared before it is ever latched in the * status register and a zero will be returned. * Our only workaround for this situation is to call * all of the installed FPGA interrupt handlers after * we read a zero from the FPGA status register. This * seems to be completely effective at eliminating the * missed Ethernet interrupts. We're assuming that all * of the edge-sensitive FPGA interrupts are subject to * the same problem, although we haven't observed it for * anything other than Ethernet. */ u32 mask = inb(OMAP1510P1_FPGA_IMR_LO) | (inb(OMAP1510P1_FPGA_IMR_HI) << 8) | (inb(INNOVATOR_FPGA_IMR2) << 16); if (!mask) break; for (fpga_irq = IH_FPGA_BASE; (fpga_irq < (IH_FPGA_BASE + NR_FPGA_IRQS)) && mask; fpga_irq++, mask >>= 1) { if ((mask & 1) && (fpga_irq != INT_FPGA_TS)) { do_IRQ(fpga_irq, regs); } } #endif /* CONFIG_INNOVATOR_MISSED_IRQS */ break; } for (fpga_irq = IH_FPGA_BASE; (fpga_irq < (IH_FPGA_BASE + NR_FPGA_IRQS)) && stat; fpga_irq++, stat >>= 1) { if (stat & 1) { do_IRQ(fpga_irq, regs); } } }
void innovator_fpga_IRQ_demux(unsigned int irq, struct irq_desc *desc) { u32 stat; int fpga_irq; stat = get_fpga_unmasked_irqs(); if (!stat) return; for (fpga_irq = OMAP_FPGA_IRQ_BASE; (fpga_irq < OMAP_FPGA_IRQ_END) && stat; fpga_irq++, stat >>= 1) { if (stat & 1) { generic_handle_irq(fpga_irq); } } }
void innovator_fpga_IRQ_demux(unsigned int irq, struct irq_desc *desc) { struct irq_desc *d; u32 stat; int fpga_irq; stat = get_fpga_unmasked_irqs(); if (!stat) return; for (fpga_irq = OMAP1510_IH_FPGA_BASE; (fpga_irq < (OMAP1510_IH_FPGA_BASE + NR_FPGA_IRQS)) && stat; fpga_irq++, stat >>= 1) { if (stat & 1) { d = irq_desc + fpga_irq; desc_handle_irq(fpga_irq, d); } } }