Пример #1
0
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);
}
Пример #2
0
/*
 * 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);
}
Пример #7
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");
}
Пример #8
0
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;
}
Пример #9
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;
}
Пример #10
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));
}
Пример #12
0
unsigned long intc_get_pending(unsigned int group)
{
	return intc_readl(&intc0, INTREQ0 + 4 * group);
}