Skip to content

Commit

Permalink
Merge branch 'devel-genirq' of git://git.kernel.org/pub/scm/linux/ker…
Browse files Browse the repository at this point in the history
…nel/git/tmlind/linux-omap-2.6 into devel-stable
  • Loading branch information
Russell King committed May 16, 2011
2 parents 1cf02bb + 667a11f commit f29251f
Showing 1 changed file with 25 additions and 72 deletions.
97 changes: 25 additions & 72 deletions arch/arm/mach-omap2/irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,83 +73,18 @@ static u32 intc_bank_read_reg(struct omap_irq_bank *bank, u16 reg)
return __raw_readl(bank->base_reg + reg);
}

static int previous_irq;

/*
* On 34xx we can get occasional spurious interrupts if the ack from
* an interrupt handler does not get posted before we unmask. Warn about
* the interrupt handlers that need to flush posted writes.
*/
static int omap_check_spurious(unsigned int irq)
{
u32 sir, spurious;

sir = intc_bank_read_reg(&irq_banks[0], INTC_SIR);
spurious = sir >> 7;

if (spurious) {
printk(KERN_WARNING "Spurious irq %i: 0x%08x, please flush "
"posted write for irq %i\n",
irq, sir, previous_irq);
return spurious;
}

return 0;
}

/* XXX: FIQ and additional INTC support (only MPU at the moment) */
static void omap_ack_irq(struct irq_data *d)
{
intc_bank_write_reg(0x1, &irq_banks[0], INTC_CONTROL);
}

static void omap_mask_irq(struct irq_data *d)
{
unsigned int irq = d->irq;
int offset = irq & (~(IRQ_BITS_PER_REG - 1));

if (cpu_is_omap34xx() && !cpu_is_ti816x()) {
int spurious = 0;

/*
* INT_34XX_GPT12_IRQ is also the spurious irq. Maybe because
* it is the highest irq number?
*/
if (irq == INT_34XX_GPT12_IRQ)
spurious = omap_check_spurious(irq);

if (!spurious)
previous_irq = irq;
}

irq &= (IRQ_BITS_PER_REG - 1);

intc_bank_write_reg(1 << irq, &irq_banks[0], INTC_MIR_SET0 + offset);
}

static void omap_unmask_irq(struct irq_data *d)
{
unsigned int irq = d->irq;
int offset = irq & (~(IRQ_BITS_PER_REG - 1));

irq &= (IRQ_BITS_PER_REG - 1);

intc_bank_write_reg(1 << irq, &irq_banks[0], INTC_MIR_CLEAR0 + offset);
}

static void omap_mask_ack_irq(struct irq_data *d)
{
omap_mask_irq(d);
irq_gc_mask_disable_reg(d);
omap_ack_irq(d);
}

static struct irq_chip omap_irq_chip = {
.name = "INTC",
.irq_ack = omap_mask_ack_irq,
.irq_mask = omap_mask_irq,
.irq_unmask = omap_unmask_irq,
};

static void __init omap_irq_bank_init_one(struct omap_irq_bank *bank)
{
unsigned long tmp;
Expand Down Expand Up @@ -186,11 +121,31 @@ int omap_irq_pending(void)
return 0;
}

static __init void
omap_alloc_gc(void __iomem *base, unsigned int irq_start, unsigned int num)
{
struct irq_chip_generic *gc;
struct irq_chip_type *ct;

gc = irq_alloc_generic_chip("INTC", 1, irq_start, base,
handle_level_irq);
ct = gc->chip_types;
ct->chip.irq_ack = omap_mask_ack_irq;
ct->chip.irq_mask = irq_gc_mask_disable_reg;
ct->chip.irq_unmask = irq_gc_unmask_enable_reg;

ct->regs.ack = INTC_CONTROL;
ct->regs.enable = INTC_MIR_CLEAR0;
ct->regs.disable = INTC_MIR_SET0;
irq_setup_generic_chip(gc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE,
IRQ_NOREQUEST | IRQ_NOPROBE, 0);
}

void __init omap_init_irq(void)
{
unsigned long nr_of_irqs = 0;
unsigned int nr_banks = 0;
int i;
int i, j;

for (i = 0; i < ARRAY_SIZE(irq_banks); i++) {
unsigned long base = 0;
Expand All @@ -215,17 +170,15 @@ void __init omap_init_irq(void)

omap_irq_bank_init_one(bank);

for (i = 0, j = 0; i < bank->nr_irqs; i += 32, j += 0x20)
omap_alloc_gc(bank->base_reg + j, i, 32);

nr_of_irqs += bank->nr_irqs;
nr_banks++;
}

printk(KERN_INFO "Total of %ld interrupts on %d active controller%s\n",
nr_of_irqs, nr_banks, nr_banks > 1 ? "s" : "");

for (i = 0; i < nr_of_irqs; i++) {
irq_set_chip_and_handler(i, &omap_irq_chip, handle_level_irq);
set_irq_flags(i, IRQF_VALID);
}
}

#ifdef CONFIG_ARCH_OMAP3
Expand Down

0 comments on commit f29251f

Please sign in to comment.