Make use of the fact that the two chips are the same and can be handled by setting the baseaddr of the second chip with an offset of 0x04 to the first. Signed-off-by: Thomas Gleixner --- arch/arm/common/sa1111.c | 193 +++++++---------------------------------------- 1 file changed, 31 insertions(+), 162 deletions(-) Index: linux-2.6/arch/arm/common/sa1111.c =================================================================== --- linux-2.6.orig/arch/arm/common/sa1111.c +++ linux-2.6/arch/arm/common/sa1111.c @@ -231,35 +231,6 @@ sa1111_irq_handler(unsigned int irq, str desc->irq_data.chip->irq_unmask(&desc->irq_data); } -#define SA1111_IRQMASK_LO(x) (1 << (x - sachip->irq_base)) -#define SA1111_IRQMASK_HI(x) (1 << (x - sachip->irq_base - 32)) - -static void sa1111_ack_irq(struct irq_data *d) -{ -} - -static void sa1111_mask_lowirq(struct irq_data *d) -{ - struct sa1111 *sachip = irq_data_get_irq_chip_data(d); - void __iomem *mapbase = sachip->base + SA1111_INTC; - unsigned long ie0; - - ie0 = sa1111_readl(mapbase + SA1111_INTEN0); - ie0 &= ~SA1111_IRQMASK_LO(d->irq); - writel(ie0, mapbase + SA1111_INTEN0); -} - -static void sa1111_unmask_lowirq(struct irq_data *d) -{ - struct sa1111 *sachip = irq_data_get_irq_chip_data(d); - void __iomem *mapbase = sachip->base + SA1111_INTC; - unsigned long ie0; - - ie0 = sa1111_readl(mapbase + SA1111_INTEN0); - ie0 |= SA1111_IRQMASK_LO(d->irq); - sa1111_writel(ie0, mapbase + SA1111_INTEN0); -} - /* * Attempt to re-trigger the interrupt. The SA1111 contains a register * (INTSET) which claims to do this. However, in practice no amount of @@ -267,11 +238,11 @@ static void sa1111_unmask_lowirq(struct * be triggered. In fact, its very difficult, if not impossible to get * INTSET to re-trigger the interrupt. */ -static int sa1111_retrigger_lowirq(struct irq_data *d) +static int sa1111_retrigger(struct irq_data *d) { - struct sa1111 *sachip = irq_data_get_irq_chip_data(d); - void __iomem *mapbase = sachip->base + SA1111_INTC; - unsigned int mask = SA1111_IRQMASK_LO(d->irq); + struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); + u32 mask = 1 << (d->irq - gc->irq_base); + void __iomem *mapbase = gc->reg_base; unsigned long ip0; int i; @@ -289,11 +260,11 @@ static int sa1111_retrigger_lowirq(struc return i == 8 ? -1 : 0; } -static int sa1111_type_lowirq(struct irq_data *d, unsigned int flags) +static int sa1111_set_type(struct irq_data *d, unsigned int flags) { - struct sa1111 *sachip = irq_data_get_irq_chip_data(d); - void __iomem *mapbase = sachip->base + SA1111_INTC; - unsigned int mask = SA1111_IRQMASK_LO(d->irq); + struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); + u32 mask = 1 << (d->irq - gc->irq_base); + void __iomem *mapbase = gc->reg_base; unsigned long ip0; if (flags == IRQ_TYPE_PROBE) @@ -309,15 +280,14 @@ static int sa1111_type_lowirq(struct irq ip0 |= mask; sa1111_writel(ip0, mapbase + SA1111_INTPOL0); sa1111_writel(ip0, mapbase + SA1111_WAKEPOL0); - return 0; } -static int sa1111_wake_lowirq(struct irq_data *d, unsigned int on) +static int sa1111_set_wake(struct irq_data *d, unsigned int on) { - struct sa1111 *sachip = irq_data_get_irq_chip_data(d); - void __iomem *mapbase = sachip->base + SA1111_INTC; - unsigned int mask = SA1111_IRQMASK_LO(d->irq); + struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); + u32 mask = 1 << (d->irq - gc->irq_base); + void __iomem *mapbase = gc->reg_base; unsigned long we0; we0 = sa1111_readl(mapbase + SA1111_WAKEEN0); @@ -326,126 +296,33 @@ static int sa1111_wake_lowirq(struct irq else we0 &= ~mask; sa1111_writel(we0, mapbase + SA1111_WAKEEN0); - - return 0; -} - -static struct irq_chip sa1111_low_chip = { - .name = "SA1111-l", - .irq_ack = sa1111_ack_irq, - .irq_mask = sa1111_mask_lowirq, - .irq_unmask = sa1111_unmask_lowirq, - .irq_retrigger = sa1111_retrigger_lowirq, - .irq_set_type = sa1111_type_lowirq, - .irq_set_wake = sa1111_wake_lowirq, -}; - -static void sa1111_mask_highirq(struct irq_data *d) -{ - struct sa1111 *sachip = irq_data_get_irq_chip_data(d); - void __iomem *mapbase = sachip->base + SA1111_INTC; - unsigned long ie1; - - ie1 = sa1111_readl(mapbase + SA1111_INTEN1); - ie1 &= ~SA1111_IRQMASK_HI(d->irq); - sa1111_writel(ie1, mapbase + SA1111_INTEN1); -} - -static void sa1111_unmask_highirq(struct irq_data *d) -{ - struct sa1111 *sachip = irq_data_get_irq_chip_data(d); - void __iomem *mapbase = sachip->base + SA1111_INTC; - unsigned long ie1; - - ie1 = sa1111_readl(mapbase + SA1111_INTEN1); - ie1 |= SA1111_IRQMASK_HI(d->irq); - sa1111_writel(ie1, mapbase + SA1111_INTEN1); -} - -/* - * Attempt to re-trigger the interrupt. The SA1111 contains a register - * (INTSET) which claims to do this. However, in practice no amount of - * manipulation of INTEN and INTSET guarantees that the interrupt will - * be triggered. In fact, its very difficult, if not impossible to get - * INTSET to re-trigger the interrupt. - */ -static int sa1111_retrigger_highirq(struct irq_data *d) -{ - struct sa1111 *sachip = irq_data_get_irq_chip_data(d); - void __iomem *mapbase = sachip->base + SA1111_INTC; - unsigned int mask = SA1111_IRQMASK_HI(d->irq); - unsigned long ip1; - int i; - - ip1 = sa1111_readl(mapbase + SA1111_INTPOL1); - for (i = 0; i < 8; i++) { - sa1111_writel(ip1 ^ mask, mapbase + SA1111_INTPOL1); - sa1111_writel(ip1, mapbase + SA1111_INTPOL1); - if (sa1111_readl(mapbase + SA1111_INTSTATCLR1) & mask) - break; - } - - if (i == 8) - printk(KERN_ERR "Danger Will Robinson: failed to " - "re-trigger IRQ%d\n", d->irq); - return i == 8 ? -1 : 0; -} - -static int sa1111_type_highirq(struct irq_data *d, unsigned int flags) -{ - struct sa1111 *sachip = irq_data_get_irq_chip_data(d); - void __iomem *mapbase = sachip->base + SA1111_INTC; - unsigned int mask = SA1111_IRQMASK_HI(d->irq); - unsigned long ip1; - - if (flags == IRQ_TYPE_PROBE) - return 0; - - if ((!(flags & IRQ_TYPE_EDGE_RISING) ^ !(flags & IRQ_TYPE_EDGE_FALLING)) == 0) - return -EINVAL; - - ip1 = sa1111_readl(mapbase + SA1111_INTPOL1); - if (flags & IRQ_TYPE_EDGE_RISING) - ip1 &= ~mask; - else - ip1 |= mask; - sa1111_writel(ip1, mapbase + SA1111_INTPOL1); - sa1111_writel(ip1, mapbase + SA1111_WAKEPOL1); - return 0; } -static int sa1111_wake_highirq(struct irq_data *d, unsigned int on) +static void sa1111_setup_gc(const char *name, unsigned int irq_base, + unsigned int cnt, void __iomem *reg_base) { - struct sa1111 *sachip = irq_data_get_irq_chip_data(d); - void __iomem *mapbase = sachip->base + SA1111_INTC; - unsigned int mask = SA1111_IRQMASK_HI(d->irq); - unsigned long we1; + struct irq_chip_generic *gc; + struct irq_chip_type *ct; - we1 = sa1111_readl(mapbase + SA1111_WAKEEN1); - if (on) - we1 |= mask; - else - we1 &= ~mask; - sa1111_writel(we1, mapbase + SA1111_WAKEEN1); + gc = irq_alloc_generic_chip(name, 1, irq_base, reg_base, handle_edge_irq); + ct = gc->chip_types; + ct->chip.irq_ack = irq_gc_noop; + ct->chip.irq_mask = irq_gc_mask_clr_bit; + ct->chip.irq_unmask = irq_gc_mask_set_bit; + ct->chip.irq_retrigger = sa1111_retrigger; + ct->chip.irq_set_type = sa1111_set_type; + ct->chip.irq_set_wake = sa1111_set_wake; + ct->regs.mask = SA1111_INTEN0; - return 0; + irq_setup_generic_chip(gc, IRQ_MSK(cnt), IRQ_NOREQUEST | IRQ_NOPROBE, 0); } -static struct irq_chip sa1111_high_chip = { - .name = "SA1111-h", - .irq_ack = sa1111_ack_irq, - .irq_mask = sa1111_mask_highirq, - .irq_unmask = sa1111_unmask_highirq, - .irq_retrigger = sa1111_retrigger_highirq, - .irq_set_type = sa1111_type_highirq, - .irq_set_wake = sa1111_wake_highirq, -}; +#define SA1111_IRQMASK_HI(x) (1 << (x - sachip->irq_base - 32)) static void sa1111_setup_irq(struct sa1111 *sachip) { void __iomem *irqbase = sachip->base + SA1111_INTC; - unsigned int irq; /* * We're guaranteed that this region hasn't been taken. @@ -471,19 +348,11 @@ static void sa1111_setup_irq(struct sa11 sa1111_writel(~0, irqbase + SA1111_INTSTATCLR0); sa1111_writel(~0, irqbase + SA1111_INTSTATCLR1); - for (irq = IRQ_GPAIN0; irq <= SSPROR; irq++) { - irq_set_chip_and_handler(irq, &sa1111_low_chip, - handle_edge_irq); - irq_set_chip_data(irq, sachip); - set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); - } + sa1111_setup_gc("SA1111-l", IRQ_GPAIN0, SSPROR + 1 - IRQ_GPAIN0, + irqbase); - for (irq = AUDXMTDMADONEA; irq <= IRQ_S1_BVD1_STSCHG; irq++) { - irq_set_chip_and_handler(irq, &sa1111_high_chip, - handle_edge_irq); - irq_set_chip_data(irq, sachip); - set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); - } + sa1111_setup_gc("SA1111-l", AUDXMTDMADONEA, + IRQ_S1_BVD1_STSCHG + 1 - AUDXMTDMADONEA, irqbase + 0x4); /* * Register SA1111 interrupt