/* * Install handler for Neponset IRQ. Note that we have to loop here * since the ETHERNET and USAR IRQs are level based, and we need to * ensure that the IRQ signal is deasserted before returning. This * is rather unfortunate. */ static void neponset_irq_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs) { unsigned int irr; while (1) { struct irqdesc *d; /* * Acknowledge the parent IRQ. */ desc->chip->ack(irq); /* * Read the interrupt reason register. Let's have all * active IRQ bits high. Note: there is a typo in the * Neponset user's guide for the SA1111 IRR level. */ irr = IRR ^ (IRR_ETHERNET | IRR_USAR); if ((irr & (IRR_ETHERNET | IRR_USAR | IRR_SA1111)) == 0) break; /* * Since there is no individual mask, we have to * mask the parent IRQ. This is safe, since we'll * recheck the register for any pending IRQs. */ if (irr & (IRR_ETHERNET | IRR_USAR)) { desc->chip->mask(irq); if (irr & IRR_ETHERNET) { d = irq_desc + IRQ_NEPONSET_SMC9196; desc_handle_irq(IRQ_NEPONSET_SMC9196, d, regs); } if (irr & IRR_USAR) { d = irq_desc + IRQ_NEPONSET_USAR; desc_handle_irq(IRQ_NEPONSET_USAR, d, regs); } desc->chip->unmask(irq); } if (irr & IRR_SA1111) { d = irq_desc + IRQ_NEPONSET_SA1111; desc_handle_irq(IRQ_NEPONSET_SA1111, d, regs); } } }
static void s3c2412_irq_demux_cfsdi(unsigned int irq, struct irq_desc *desc) { unsigned int subsrc, submsk; subsrc = __raw_readl(S3C2410_SUBSRCPND); submsk = __raw_readl(S3C2410_INTSUBMSK); subsrc &= ~submsk; if (subsrc & INTBIT(IRQ_S3C2412_SDI)) desc_handle_irq(IRQ_S3C2412_SDI, irq_desc + IRQ_S3C2412_SDI); if (subsrc & INTBIT(IRQ_S3C2412_CF)) desc_handle_irq(IRQ_S3C2412_CF, irq_desc + IRQ_S3C2412_CF); }
static void ixdp2x01_irq_handler(unsigned int irq, struct irq_desc *desc) { u32 ex_interrupt; int i; desc->chip->mask(irq); ex_interrupt = *IXDP2X01_INT_STAT_REG & valid_irq_mask; if (!ex_interrupt) { printk(KERN_ERR "Spurious IXDP2X01 CPLD interrupt!\n"); return; } for (i = 0; i < IXP2000_BOARD_IRQS; i++) { if (ex_interrupt & (1 << i)) { struct irq_desc *cpld_desc; int cpld_irq = IXP2000_BOARD_IRQ(0) + i; cpld_desc = irq_desc + cpld_irq; desc_handle_irq(cpld_irq, cpld_desc); } } desc->chip->unmask(irq); }
static inline void s3c2443_irq_demux(unsigned int irq, unsigned int len) { unsigned int subsrc, submsk; unsigned int end; struct irq_desc *mydesc; /* read the current pending interrupts, and the mask * for what it is available */ subsrc = __raw_readl(S3C2410_SUBSRCPND); submsk = __raw_readl(S3C2410_INTSUBMSK); subsrc &= ~submsk; subsrc >>= (irq - S3C2410_IRQSUB(0)); subsrc &= (1 << len)-1; end = len + irq; mydesc = irq_desc + irq; for (; irq < end && subsrc; irq++) { if (subsrc & 1) desc_handle_irq(irq, mydesc); mydesc++; subsrc >>= 1; } }
/* Although we have two interrupt lines for the timers, we only have one * status register which clears all pending timer interrupts on reading. So * we have to handle all timer interrupts in one place. */ static void h7202_timerx_demux_handler(unsigned int irq_unused, struct irqdesc *desc, struct pt_regs *regs) { unsigned int mask, irq; mask = CPU_REG (TIMER_VIRT, TIMER_TOPSTAT); if ( mask & TSTAT_T0INT ) { write_seqlock(&xtime_lock); timer_tick(regs); write_sequnlock(&xtime_lock); if( mask == TSTAT_T0INT ) return; } mask >>= 1; irq = IRQ_TIMER1; desc = irq_desc + irq; while (mask) { if (mask & 1) desc_handle_irq(irq, desc, regs); irq++; desc++; mask >>= 1; } }
void orion_gpio_irq_handler(int pinoff) { u32 cause; int pin; cause = readl(GPIO_DATA_IN(pinoff)) & readl(GPIO_LEVEL_MASK(pinoff)); cause |= readl(GPIO_EDGE_CAUSE(pinoff)) & readl(GPIO_EDGE_MASK(pinoff)); for (pin = pinoff; pin < pinoff + 8; pin++) { int irq = gpio_to_irq(pin); struct irq_desc *desc = irq_desc + irq; if (!(cause & (1 << (pin & 31)))) continue; if ((desc->status & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) { /* Swap polarity (race with GPIO line) */ u32 polarity; polarity = readl(GPIO_IN_POL(pin)); polarity ^= 1 << (pin & 31); writel(polarity, GPIO_IN_POL(pin)); } desc_handle_irq(irq, desc); } }
/* * IRQ11 (GPIO11 through 27) handler. We enter here with the * irq_controller_lock held, and IRQs disabled. Decode the IRQ * and call the handler. */ static void sa1100_high_gpio_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs) { unsigned int mask; mask = GEDR & 0xfffff800; do { /* * clear down all currently active IRQ sources. * We will be processing them all. */ GEDR = mask; irq = IRQ_GPIO11; desc = irq_desc + irq; mask >>= 11; do { if (mask & 1) desc_handle_irq(irq, desc, regs); mask >>= 1; irq++; desc++; } while (mask); mask = GEDR & 0xfffff800; } while (mask); }
static void kev7a400_cpld_handler (unsigned int irq, struct irq_desc *desc) { u32 mask = CPLD_LATCHED_INTS; irq = IRQ_KEV7A400_CPLD; for (; mask; mask >>= 1, ++irq) if (mask & 1) desc_handle_irq(irq, desc); }
/************************************************************************* * IRQ handling IXP2000 *************************************************************************/ static void ixp2000_GPIO_irq_handler(unsigned int irq, struct irq_desc *desc) { int i; unsigned long status = *IXP2000_GPIO_INST; for (i = 0; i <= 7; i++) { if (status & (1<<i)) { desc = irq_desc + i + IRQ_IXP2000_GPIO0; desc_handle_irq(i + IRQ_IXP2000_GPIO0, desc); } } }
/* * Error interrupts. These are used extensively by the microengine drivers */ static void ixp2000_err_irq_handler(unsigned int irq, struct irq_desc *desc) { int i; unsigned long status = *IXP2000_IRQ_ERR_STATUS; for(i = 31; i >= 0; i--) { if(status & (1 << i)) { desc = irq_desc + IRQ_IXP2000_DRAM0_MIN_ERR + i; desc_handle_irq(IRQ_IXP2000_DRAM0_MIN_ERR + i, desc); } } }
static void isa_irq_handler(unsigned int irq, struct irq_desc *desc) { unsigned int isa_irq = *(unsigned char *)PCIIACK_BASE; if (isa_irq < _ISA_IRQ(0) || isa_irq >= _ISA_IRQ(16)) { do_bad_IRQ(isa_irq, desc); return; } desc = irq_desc + isa_irq; desc_handle_irq(isa_irq, desc); }
static void mainstone_irq_handler(unsigned int irq, struct irq_desc *desc) { unsigned long pending = MST_INTSETCLR & mainstone_irq_enabled; do { GEDR(0) = GPIO_bit(0); /* clear useless edge notification */ if (likely(pending)) { irq = MAINSTONE_IRQ(0) + __ffs(pending); desc = irq_desc + irq; desc_handle_irq(irq, desc); } pending = MST_INTSETCLR & mainstone_irq_enabled; } while (pending); }
static void lubbock_irq_handler(unsigned int irq, struct irq_desc *desc) { unsigned long pending = LUB_IRQ_SET_CLR & lubbock_irq_enabled; do { GEDR(0) = GPIO_bit(0); /* clear our parent irq */ if (likely(pending)) { irq = LUBBOCK_IRQ(0) + __ffs(pending); desc = irq_desc + irq; desc_handle_irq(irq, desc); } pending = LUB_IRQ_SET_CLR & lubbock_irq_enabled; } while (pending); }
static void gpio_irq_handler(unsigned irq, struct irq_desc *desc) { unsigned pin; struct irq_desc *gpio; struct at91_gpio_bank *bank; void __iomem *pio; u32 isr; bank = get_irq_chip_data(irq); pio = bank->regbase; /* temporarily mask (level sensitive) parent IRQ */ desc->chip->ack(irq); for (;;) { /* Reading ISR acks pending (edge triggered) GPIO interrupts. * When there none are pending, we're finished unless we need * to process multiple banks (like ID_PIOCDE on sam9263). */ isr = __raw_readl(pio + PIO_ISR) & __raw_readl(pio + PIO_IMR); if (!isr) { if (!bank->next) break; bank = bank->next; pio = bank->regbase; continue; } pin = bank->chipbase; gpio = &irq_desc[pin]; while (isr) { if (isr & 1) { if (unlikely(gpio->depth)) { /* * The core ARM interrupt handler lazily disables IRQs so * another IRQ must be generated before it actually gets * here to be disabled on the GPIO controller. */ gpio_irq_mask(pin); } else desc_handle_irq(pin, gpio); } pin++; gpio++; isr >>= 1; } } desc->chip->unmask(irq); /* now it may re-trigger */ }
static void imx_gpio_handler(unsigned int mask, unsigned int irq, struct irqdesc *desc, struct pt_regs *regs) { desc = irq_desc + irq; while (mask) { if (mask & 1) { DEBUG_IRQ("handling irq %d\n", irq); desc_handle_irq(irq, desc, regs); } irq++; desc++; mask >>= 1; } }
static void pcm990_irq_handler(unsigned int irq, struct irq_desc *desc) { unsigned long pending = (~PCM990_INTSETCLR) & pcm990_irq_enabled; do { GEDR(PCM990_CTRL_INT_IRQ_GPIO) = GPIO_bit(PCM990_CTRL_INT_IRQ_GPIO); if (likely(pending)) { irq = PCM027_IRQ(0) + __ffs(pending); desc = irq_desc + irq; desc_handle_irq(irq, desc); } pending = (~PCM990_INTSETCLR) & pcm990_irq_enabled; } while (pending); }
static void a9m9750dev_fpga_demux_handler(unsigned int irq, struct irq_desc *desc) { int stat = FPGA_ISR; while (stat != 0) { int irqno = fls(stat) - 1; stat &= ~(1 << irqno); desc = irq_desc + FPGA_IRQ(irqno); desc_handle_irq(irqno, desc); } }
static void h720x_gpio_handler(unsigned int mask, unsigned int irq, struct irq_desc *desc) { IRQDBG("%s irq: %d\n", __func__, irq); desc = irq_desc + irq; while (mask) { if (mask & 1) { IRQDBG("handling irq %d\n", irq); desc_handle_irq(irq, desc); } irq++; desc++; mask >>= 1; } }
static void imx_fpga_handler(unsigned int mask, unsigned int irq, struct irq_desc *desc) { pr_debug("%s: mask:0x%04x\n", __FUNCTION__, mask); desc = irq_desc + irq; while (mask) { if (mask & 1) { pr_debug("handling irq %d\n", irq); desc_handle_irq(irq, desc); } irq++; desc++; mask >>= 1; } }
static void lpd270_irq_handler(unsigned int irq, struct irq_desc *desc) { unsigned long pending; pending = __raw_readw(LPD270_INT_STATUS) & lpd270_irq_enabled; do { GEDR(0) = GPIO_bit(0); /* clear useless edge notification */ if (likely(pending)) { irq = LPD270_IRQ(0) + __ffs(pending); desc = irq_desc + irq; desc_handle_irq(irq, desc); pending = __raw_readw(LPD270_INT_STATUS) & lpd270_irq_enabled; } } while (pending); }
static void pmu_irq_handler(unsigned int irq, struct irq_desc *desc) { unsigned long cause = readl(PMU_INTERRUPT_CAUSE); cause &= readl(PMU_INTERRUPT_MASK); if (cause == 0) { do_bad_IRQ(irq, desc); return; } for (irq = 0; irq < NR_PMU_IRQS; irq++) { if (!(cause & (1 << irq))) continue; irq = pmu_to_irq(irq); desc = irq_desc + irq; desc_handle_irq(irq, desc); } }
static void egpio_handler(unsigned int irq, struct irq_desc *desc) { int i; // Read current pins. u16 readval = egpio[0]; // Process all set pins. for (i=0; i<LAST_EGPIO; i++) { int irqpin = i+8; if (!(readval & (1<<irqpin))) continue; // Ack/unmask current pin. egpio[0] = ~(1<<irqpin); // Handle irq irq = IRQ_EGPIO(i); desc = &irq_desc[irq]; desc_handle_irq(irq, desc); } }
static void ixdp2351_intb_handler(unsigned int irq, struct irq_desc *desc) { u16 ex_interrupt = *IXDP2351_CPLD_INTB_STAT_REG & IXDP2351_INTB_IRQ_VALID; int i; desc->chip->ack(irq); for (i = 0; i < IXDP2351_INTB_IRQ_NUM; i++) { if (ex_interrupt & (1 << i)) { struct irq_desc *cpld_desc; int cpld_irq = IXP23XX_MACH_IRQ(IXDP2351_INTB_IRQ_BASE + i); cpld_desc = irq_desc + cpld_irq; desc_handle_irq(cpld_irq, cpld_desc); } } desc->chip->unmask(irq); }
static void sic_handle_irq(unsigned int irq, struct irq_desc *desc) { unsigned long status = readl(VA_SIC_BASE + SIC_IRQ_STATUS); if (status == 0) { do_bad_IRQ(irq, desc); return; } do { irq = ffs(status) - 1; status &= ~(1 << irq); irq += IRQ_SIC_START; desc = irq_desc + irq; desc_handle_irq(irq, desc); } while (status); }
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); } } }
static void gpio_irq_handler(unsigned irq, struct irq_desc *desc) { unsigned pin; struct irq_desc *gpio; void __iomem *pio; u32 isr; pio = get_irq_chip_data(irq); /* temporarily mask (level sensitive) parent IRQ */ desc->chip->ack(irq); for (;;) { /* reading ISR acks the pending (edge triggered) GPIO interrupt */ isr = __raw_readl(pio + PIO_ISR) & __raw_readl(pio + PIO_IMR); if (!isr) break; pin = (unsigned) get_irq_data(irq); gpio = &irq_desc[pin]; while (isr) { if (isr & 1) { if (unlikely(gpio->depth)) { /* * The core ARM interrupt handler lazily disables IRQs so * another IRQ must be generated before it actually gets * here to be disabled on the GPIO controller. */ gpio_irq_mask(pin); } else desc_handle_irq(pin, gpio); } pin++; gpio++; isr >>= 1; } } desc->chip->unmask(irq); /* now it may re-trigger */ }
static void iop13xx_msi_handler(unsigned int irq, struct irq_desc *desc) { int i, j; unsigned long status; /* read IMIPR registers and find any active interrupts, * then call ISR for each active interrupt */ for (i = 0; i < ARRAY_SIZE(read_imipr); i++) { status = (read_imipr[i])(); if (!status) continue; do { j = find_first_bit(&status, 32); (write_imipr[i])(1 << j); /* write back to clear bit */ desc = irq_desc + IRQ_IOP13XX_MSI_0 + j + (32*i); desc_handle_irq(IRQ_IOP13XX_MSI_0 + j + (32*i), desc); status = (read_imipr[i])(); } while (status); } }
/* * PNX EXTINT : only EXTINT 3 is managed by Linux * We need to unmask the GPIO bank interrupt as soon as possible to * avoid missing GPIO interrupts for other lines in the bank. * Then we need to mask-read-clear-unmask the triggered GPIO lines * in the bank to avoid missing nested interrupts for a GPIO line. * If we wait to unmask individual GPIO lines in the bank after the * line's interrupt handler has been run, we may miss some nested * interrupts. */ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc) { unsigned long isr; unsigned long flags; unsigned int gpio_irq; /* LPA TBD */ desc->chip->ack(irq); /* read status */ hw_raw_local_irq_save ( flags ); isr = __raw_readl(EXTINT_STATUS_REG) & __raw_readl(EXTINT_ENABLE3_REG); /* clear IRQ source(s)*/ __raw_writel(~isr, EXTINT_STATUS_REG); hw_raw_local_irq_restore ( flags ); gpio_irq = IRQ_COUNT; for (; isr != 0; isr >>= 1, gpio_irq++) { struct irq_desc *d; if (!(isr & 1)) continue; d = irq_desc + gpio_irq; #ifdef CONFIG_DEBUG_EXTINT printk(KERN_ERR "got something from EXTINT#%i line\n", gpio_irq - IRQ_COUNT); #endif desc_handle_irq(gpio_irq, d); } #ifdef CONFIG_NKERNEL /* * interrupt forwarding routine of osware masks INTC_IID_EXT2 * so we have to unmask it after irq handling */ hw_raw_local_irq_save ( flags ); __raw_writel((1<<26 | 1<<16), INTC_REQUESTx(IRQ_EXTINT3)); hw_raw_local_irq_restore ( flags ); #endif }
/* Although we have two interrupt lines for the timers, we only have one * status register which clears all pending timer interrupts on reading. So * we have to handle all timer interrupts in one place. */ static void h7202_timerx_demux_handler(unsigned int irq_unused, struct irq_desc *desc) { unsigned int mask, irq; mask = CPU_REG (TIMER_VIRT, TIMER_TOPSTAT); if ( mask & TSTAT_T0INT ) { timer_tick(); if( mask == TSTAT_T0INT ) return; } mask >>= 1; irq = IRQ_TIMER1; desc = irq_desc + irq; while (mask) { if (mask & 1) desc_handle_irq(irq, desc); irq++; desc++; mask >>= 1; } }
/* * TODO: Should this just be done at ASM level? */ static void pci_handler(unsigned int irq, struct irq_desc *desc) { u32 pci_interrupt; unsigned int irqno; struct irq_desc *int_desc; pci_interrupt = *IXP23XX_PCI_XSCALE_INT_STATUS; desc->chip->ack(irq); /* See which PCI_INTA, or PCI_INTB interrupted */ if (pci_interrupt & (1 << 26)) { irqno = IRQ_IXP23XX_INTB; } else if (pci_interrupt & (1 << 27)) { irqno = IRQ_IXP23XX_INTA; } else { BUG(); } int_desc = irq_desc + irqno; desc_handle_irq(irqno, int_desc); desc->chip->unmask(irq); }