static asmlinkage void __exception_irq_entry omap_intc_handle_irq(struct pt_regs *regs) { u32 irqnr = 0; int handled_irq = 0; int i; do { for (i = 0; i < omap_nr_pending; i++) { irqnr = intc_readl(INTC_PENDING_IRQ0 + (0x20 * i)); if (irqnr) goto out; } out: if (!irqnr) break; irqnr = intc_readl(INTC_SIR); irqnr &= ACTIVEIRQ_MASK; if (irqnr) { handle_domain_irq(domain, irqnr, regs); handled_irq = 1; } } while (irqnr); /* * If an irq is masked or deasserted while active, we will * keep ending up here with no irq handled. So remove it from * the INTC with an ack. */ if (!handled_irq) omap_ack_irq(NULL); }
/* * All interrupts go via intc at some point. */ asmlinkage void do_IRQ(int level, struct pt_regs *regs) { struct irq_desc *desc; struct pt_regs *old_regs; unsigned int irq; unsigned long status_reg; local_irq_disable(); old_regs = set_irq_regs(regs); irq_enter(); irq = intc_readl(&intc0, INTCAUSE0 - 4 * level); desc = irq_desc + irq; desc->handle_irq(irq, desc); /* * Clear all interrupt level masks so that we may handle * interrupts during softirq processing. If this is a nested * interrupt, interrupts must stay globally disabled until we * return. */ status_reg = sysreg_read(SR); status_reg &= ~(SYSREG_BIT(I0M) | SYSREG_BIT(I1M) | SYSREG_BIT(I2M) | SYSREG_BIT(I3M)); sysreg_write(SR, status_reg); irq_exit(); set_irq_regs(old_regs); }
static void __init omap_irq_enable_protection(void) { u32 reg; reg = intc_readl(INTC_PROTECTION); reg |= INTC_PROTECTION_ENABLE; intc_writel(INTC_PROTECTION, reg); }
int omap_irq_pending(void) { int i; for (i = 0; i < omap_nr_pending; i++) if (intc_readl(INTC_PENDING_IRQ0 + (0x20 * i))) return 1; return 0; }
static asmlinkage void __exception_irq_entry omap_intc_handle_irq(struct pt_regs *regs) { u32 irqnr; irqnr = intc_readl(INTC_SIR); irqnr &= ACTIVEIRQ_MASK; WARN_ONCE(!irqnr, "Spurious IRQ ?\n"); handle_domain_irq(domain, irqnr, regs); }
static void __init omap_irq_soft_reset(void) { unsigned long tmp; tmp = intc_readl(INTC_REVISION) & 0xff; pr_info("IRQ: Found an INTC at 0x%p (revision %ld.%ld) with %d interrupts\n", omap_irq_base, tmp >> 4, tmp & 0xf, omap_nr_irqs); tmp = intc_readl(INTC_SYSCONFIG); tmp |= 1 << 1; /* soft reset */ intc_writel(INTC_SYSCONFIG, tmp); while (!(intc_readl(INTC_SYSSTATUS) & 0x1)) /* Wait for reset to complete */; /* Enable autoidle */ intc_writel(INTC_SYSCONFIG, 1 << 0); }
void __init init_IRQ(void) { extern void _evba(void); extern void irq_level0(void); struct resource *regs; struct clk *pclk; unsigned int i; u32 offset, readback; regs = platform_get_resource(&at32_intc0_device, IORESOURCE_MEM, 0); if (!regs) { printk(KERN_EMERG "intc: no mmio resource defined\n"); goto fail; } pclk = clk_get(&at32_intc0_device.dev, "pclk"); if (IS_ERR(pclk)) { printk(KERN_EMERG "intc: no clock defined\n"); goto fail; } clk_enable(pclk); intc0.regs = ioremap(regs->start, regs->end - regs->start + 1); if (!intc0.regs) { printk(KERN_EMERG "intc: failed to map registers (0x%08lx)\n", (unsigned long)regs->start); goto fail; } /* * Initialize all interrupts to level 0 (lowest priority). The * priority level may be changed by calling * irq_set_priority(). * */ offset = (unsigned long)&irq_level0 - (unsigned long)&_evba; for (i = 0; i < NR_INTERNAL_IRQS; i++) { intc_writel(&intc0, INTPR0 + 4 * i, offset); readback = intc_readl(&intc0, INTPR0 + 4 * i); if (readback == offset) set_irq_chip_and_handler(i, &intc0.chip, handle_simple_irq); } /* Unmask all interrupt levels */ sysreg_write(SR, (sysreg_read(SR) & ~(SR_I3M | SR_I2M | SR_I1M | SR_I0M))); return; fail: panic("Interrupt controller initialization failed!\n"); }
static int intc_suspend(void) { int i; if (unlikely(!irqs_disabled())) { pr_err("intc_suspend: called with interrupts enabled\n"); return -EINVAL; } if (unlikely(!intc0.suspend_ipr)) { pr_err("intc_suspend: suspend_ipr not initialized\n"); return -EINVAL; } for (i = 0; i < 64; i++) { intc0.saved_ipr[i] = intc_readl(&intc0, INTPR0 + 4 * i); intc_writel(&intc0, INTPR0 + 4 * i, intc0.suspend_ipr); } return 0; }
static int intc_suspend(struct sys_device *sdev, pm_message_t state) { struct intc *intc = container_of(sdev, struct intc, sysdev); int i; if (unlikely(!irqs_disabled())) { pr_err("intc_suspend: called with interrupts enabled\n"); return -EINVAL; } if (unlikely(!intc->suspend_ipr)) { pr_err("intc_suspend: suspend_ipr not initialized\n"); return -EINVAL; } for (i = 0; i < 64; i++) { intc->saved_ipr[i] = intc_readl(intc, INTPR0 + 4 * i); intc_writel(intc, INTPR0 + 4 * i, intc->suspend_ipr); } return 0; }
asmlinkage void do_IRQ(int level, struct pt_regs *regs) { struct pt_regs *old_regs; unsigned int irq; unsigned long status_reg; local_irq_disable(); old_regs = set_irq_regs(regs); irq_enter(); irq = intc_readl(&intc0, INTCAUSE0 - 4 * level); generic_handle_irq(irq); status_reg = sysreg_read(SR); status_reg &= ~(SYSREG_BIT(I0M) | SYSREG_BIT(I1M) | SYSREG_BIT(I2M) | SYSREG_BIT(I3M)); sysreg_write(SR, status_reg); irq_exit(); set_irq_regs(old_regs); }
void omap_intc_save_context(void) { int i; intc_context.sysconfig = intc_readl(INTC_SYSCONFIG); intc_context.protection = intc_readl(INTC_PROTECTION); intc_context.idle = intc_readl(INTC_IDLE); intc_context.threshold = intc_readl(INTC_THRESHOLD); for (i = 0; i < omap_nr_irqs; i++) intc_context.ilr[i] = intc_readl((INTC_ILR0 + 0x4 * i)); for (i = 0; i < INTCPS_NR_MIR_REGS; i++) intc_context.mir[i] = intc_readl(INTC_MIR0 + (0x20 * i)); }
unsigned long intc_get_pending(unsigned int group) { return intc_readl(&intc0, INTREQ0 + 4 * group); }