Esempio n. 1
0
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);
			}
		}
	}
}
Esempio n. 2
0
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);
				}
		}
	}
Esempio n. 3
0
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);
		}
	}
}
Esempio n. 4
0
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);
		}
	}
}