summaryrefslogtreecommitdiffstats
path: root/arch/arm/common
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@armlinux.org.uk>2016-09-06 19:43:28 +0200
committerRussell King <rmk+kernel@armlinux.org.uk>2016-09-20 15:21:08 +0200
commit1629c9ab3679908d2e18ca306df1f07f48713f6b (patch)
treead2d296385fbe237317c26305c127ac3b09d139d /arch/arm/common
parentARM: sa1111: implement a gpio_chip for SA1111 GPIOs (diff)
downloadlinux-1629c9ab3679908d2e18ca306df1f07f48713f6b.tar.xz
linux-1629c9ab3679908d2e18ca306df1f07f48713f6b.zip
ARM: sa1111: clean up duplication in IRQ chip implementation
Clean up the duplication in the IRQ chip implementation - we can compute the register address from the interrupt number rather than duplicating the code for each register. Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
Diffstat (limited to 'arch/arm/common')
-rw-r--r--arch/arm/common/sa1111.c189
1 files changed, 48 insertions, 141 deletions
diff --git a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c
index 16cc3b5122ad..7f232ce50944 100644
--- a/arch/arm/common/sa1111.c
+++ b/arch/arm/common/sa1111.c
@@ -233,132 +233,44 @@ static void sa1111_irq_handler(struct irq_desc *desc)
#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)
+static u32 sa1111_irqmask(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
- * 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_lowirq(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);
- unsigned long ip0;
- int i;
-
- ip0 = sa1111_readl(mapbase + SA1111_INTPOL0);
- for (i = 0; i < 8; i++) {
- sa1111_writel(ip0 ^ mask, mapbase + SA1111_INTPOL0);
- sa1111_writel(ip0, mapbase + SA1111_INTPOL0);
- if (sa1111_readl(mapbase + SA1111_INTSTATCLR0) & mask)
- break;
- }
-
- if (i == 8)
- pr_err("Danger Will Robinson: failed to re-trigger IRQ%d\n",
- d->irq);
- return i == 8 ? -1 : 0;
+ return BIT((d->irq - sachip->irq_base) & 31);
}
-static int sa1111_type_lowirq(struct irq_data *d, unsigned int flags)
+static int sa1111_irqbank(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);
- unsigned long ip0;
-
- if (flags == IRQ_TYPE_PROBE)
- return 0;
-
- if ((!(flags & IRQ_TYPE_EDGE_RISING) ^ !(flags & IRQ_TYPE_EDGE_FALLING)) == 0)
- return -EINVAL;
-
- ip0 = sa1111_readl(mapbase + SA1111_INTPOL0);
- if (flags & IRQ_TYPE_EDGE_RISING)
- ip0 &= ~mask;
- else
- ip0 |= mask;
- sa1111_writel(ip0, mapbase + SA1111_INTPOL0);
- sa1111_writel(ip0, mapbase + SA1111_WAKEPOL0);
- return 0;
+ return ((d->irq - sachip->irq_base) / 32) * 4;
}
-static int sa1111_wake_lowirq(struct irq_data *d, unsigned int on)
+static void sa1111_ack_irq(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);
- unsigned long we0;
-
- we0 = sa1111_readl(mapbase + SA1111_WAKEEN0);
- if (on)
- we0 |= mask;
- 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)
+static void sa1111_mask_irq(struct irq_data *d)
{
struct sa1111 *sachip = irq_data_get_irq_chip_data(d);
- void __iomem *mapbase = sachip->base + SA1111_INTC;
- unsigned long ie1;
+ void __iomem *mapbase = sachip->base + SA1111_INTC + sa1111_irqbank(d);
+ u32 ie;
- ie1 = sa1111_readl(mapbase + SA1111_INTEN1);
- ie1 &= ~SA1111_IRQMASK_HI(d->irq);
- sa1111_writel(ie1, mapbase + SA1111_INTEN1);
+ ie = sa1111_readl(mapbase + SA1111_INTEN0);
+ ie &= ~sa1111_irqmask(d);
+ sa1111_writel(ie, mapbase + SA1111_INTEN0);
}
-static void sa1111_unmask_highirq(struct irq_data *d)
+static void sa1111_unmask_irq(struct irq_data *d)
{
struct sa1111 *sachip = irq_data_get_irq_chip_data(d);
- void __iomem *mapbase = sachip->base + SA1111_INTC;
- unsigned long ie1;
+ void __iomem *mapbase = sachip->base + SA1111_INTC + sa1111_irqbank(d);
+ u32 ie;
- ie1 = sa1111_readl(mapbase + SA1111_INTEN1);
- ie1 |= SA1111_IRQMASK_HI(d->irq);
- sa1111_writel(ie1, mapbase + SA1111_INTEN1);
+ ie = sa1111_readl(mapbase + SA1111_INTEN0);
+ ie |= sa1111_irqmask(d);
+ sa1111_writel(ie, mapbase + SA1111_INTEN0);
}
/*
@@ -368,19 +280,18 @@ static void sa1111_unmask_highirq(struct irq_data *d)
* 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)
+static int sa1111_retrigger_irq(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;
+ void __iomem *mapbase = sachip->base + SA1111_INTC + sa1111_irqbank(d);
+ u32 ip, mask = sa1111_irqmask(d);
int i;
- ip1 = sa1111_readl(mapbase + SA1111_INTPOL1);
+ ip = sa1111_readl(mapbase + SA1111_INTPOL0);
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)
+ sa1111_writel(ip ^ mask, mapbase + SA1111_INTPOL0);
+ sa1111_writel(ip, mapbase + SA1111_INTPOL0);
+ if (sa1111_readl(mapbase + SA1111_INTSTATCLR0) & mask)
break;
}
@@ -390,12 +301,11 @@ static int sa1111_retrigger_highirq(struct irq_data *d)
return i == 8 ? -1 : 0;
}
-static int sa1111_type_highirq(struct irq_data *d, unsigned int flags)
+static int sa1111_type_irq(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;
+ void __iomem *mapbase = sachip->base + SA1111_INTC + sa1111_irqbank(d);
+ u32 ip, mask = sa1111_irqmask(d);
if (flags == IRQ_TYPE_PROBE)
return 0;
@@ -403,42 +313,41 @@ static int sa1111_type_highirq(struct irq_data *d, unsigned int flags)
if ((!(flags & IRQ_TYPE_EDGE_RISING) ^ !(flags & IRQ_TYPE_EDGE_FALLING)) == 0)
return -EINVAL;
- ip1 = sa1111_readl(mapbase + SA1111_INTPOL1);
+ ip = sa1111_readl(mapbase + SA1111_INTPOL0);
if (flags & IRQ_TYPE_EDGE_RISING)
- ip1 &= ~mask;
+ ip &= ~mask;
else
- ip1 |= mask;
- sa1111_writel(ip1, mapbase + SA1111_INTPOL1);
- sa1111_writel(ip1, mapbase + SA1111_WAKEPOL1);
+ ip |= mask;
+ sa1111_writel(ip, mapbase + SA1111_INTPOL0);
+ sa1111_writel(ip, mapbase + SA1111_WAKEPOL0);
return 0;
}
-static int sa1111_wake_highirq(struct irq_data *d, unsigned int on)
+static int sa1111_wake_irq(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_HI(d->irq);
- unsigned long we1;
+ void __iomem *mapbase = sachip->base + SA1111_INTC + sa1111_irqbank(d);
+ u32 we, mask = sa1111_irqmask(d);
- we1 = sa1111_readl(mapbase + SA1111_WAKEEN1);
+ we = sa1111_readl(mapbase + SA1111_WAKEEN0);
if (on)
- we1 |= mask;
+ we |= mask;
else
- we1 &= ~mask;
- sa1111_writel(we1, mapbase + SA1111_WAKEEN1);
+ we &= ~mask;
+ sa1111_writel(we, mapbase + SA1111_WAKEEN0);
return 0;
}
-static struct irq_chip sa1111_high_chip = {
- .name = "SA1111-h",
+static struct irq_chip sa1111_irq_chip = {
+ .name = "SA1111",
.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,
+ .irq_mask = sa1111_mask_irq,
+ .irq_unmask = sa1111_unmask_irq,
+ .irq_retrigger = sa1111_retrigger_irq,
+ .irq_set_type = sa1111_type_irq,
+ .irq_set_wake = sa1111_wake_irq,
};
static int sa1111_setup_irq(struct sa1111 *sachip, unsigned irq_base)
@@ -484,16 +393,14 @@ static int sa1111_setup_irq(struct sa1111 *sachip, unsigned irq_base)
for (i = IRQ_GPAIN0; i <= SSPROR; i++) {
irq = sachip->irq_base + i;
- irq_set_chip_and_handler(irq, &sa1111_low_chip,
- handle_edge_irq);
+ irq_set_chip_and_handler(irq, &sa1111_irq_chip, handle_edge_irq);
irq_set_chip_data(irq, sachip);
irq_clear_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE);
}
for (i = AUDXMTDMADONEA; i <= IRQ_S1_BVD1_STSCHG; i++) {
irq = sachip->irq_base + i;
- irq_set_chip_and_handler(irq, &sa1111_high_chip,
- handle_edge_irq);
+ irq_set_chip_and_handler(irq, &sa1111_irq_chip, handle_edge_irq);
irq_set_chip_data(irq, sachip);
irq_clear_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE);
}