Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1629c9ab authored by Russell King's avatar Russell King
Browse files

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: default avatarRussell King <rmk+kernel@armlinux.org.uk>
parent 17cf5011
Loading
Loading
Loading
Loading
+48 −141
Original line number Original line Diff line number Diff line
@@ -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_LO(x)	(1 << (x - sachip->irq_base))
#define SA1111_IRQMASK_HI(x)	(1 << (x - sachip->irq_base - 32))
#define SA1111_IRQMASK_HI(x)	(1 << (x - sachip->irq_base - 32))


static void sa1111_ack_irq(struct irq_data *d)
static u32 sa1111_irqmask(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);
	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);
}


/*
	return BIT((d->irq - sachip->irq_base) & 31);
 * 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;
}
}


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);
	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 = {
static void sa1111_mask_irq(struct irq_data *d)
	.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);
	struct sa1111 *sachip = irq_data_get_irq_chip_data(d);
	void __iomem *mapbase = sachip->base + SA1111_INTC;
	void __iomem *mapbase = sachip->base + SA1111_INTC + sa1111_irqbank(d);
	unsigned long ie1;
	u32 ie;


	ie1 = sa1111_readl(mapbase + SA1111_INTEN1);
	ie = sa1111_readl(mapbase + SA1111_INTEN0);
	ie1 &= ~SA1111_IRQMASK_HI(d->irq);
	ie &= ~sa1111_irqmask(d);
	sa1111_writel(ie1, mapbase + SA1111_INTEN1);
	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);
	struct sa1111 *sachip = irq_data_get_irq_chip_data(d);
	void __iomem *mapbase = sachip->base + SA1111_INTC;
	void __iomem *mapbase = sachip->base + SA1111_INTC + sa1111_irqbank(d);
	unsigned long ie1;
	u32 ie;


	ie1 = sa1111_readl(mapbase + SA1111_INTEN1);
	ie = sa1111_readl(mapbase + SA1111_INTEN0);
	ie1 |= SA1111_IRQMASK_HI(d->irq);
	ie |= sa1111_irqmask(d);
	sa1111_writel(ie1, mapbase + SA1111_INTEN1);
	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
 * be triggered.  In fact, its very difficult, if not impossible to get
 * INTSET to re-trigger the interrupt.
 * 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);
	struct sa1111 *sachip = irq_data_get_irq_chip_data(d);
	void __iomem *mapbase = sachip->base + SA1111_INTC;
	void __iomem *mapbase = sachip->base + SA1111_INTC + sa1111_irqbank(d);
	unsigned int mask = SA1111_IRQMASK_HI(d->irq);
	u32 ip, mask = sa1111_irqmask(d);
	unsigned long ip1;
	int i;
	int i;


	ip1 = sa1111_readl(mapbase + SA1111_INTPOL1);
	ip = sa1111_readl(mapbase + SA1111_INTPOL0);
	for (i = 0; i < 8; i++) {
	for (i = 0; i < 8; i++) {
		sa1111_writel(ip1 ^ mask, mapbase + SA1111_INTPOL1);
		sa1111_writel(ip ^ mask, mapbase + SA1111_INTPOL0);
		sa1111_writel(ip1, mapbase + SA1111_INTPOL1);
		sa1111_writel(ip, mapbase + SA1111_INTPOL0);
		if (sa1111_readl(mapbase + SA1111_INTSTATCLR1) & mask)
		if (sa1111_readl(mapbase + SA1111_INTSTATCLR0) & mask)
			break;
			break;
	}
	}


@@ -390,12 +301,11 @@ static int sa1111_retrigger_highirq(struct irq_data *d)
	return i == 8 ? -1 : 0;
	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);
	struct sa1111 *sachip = irq_data_get_irq_chip_data(d);
	void __iomem *mapbase = sachip->base + SA1111_INTC;
	void __iomem *mapbase = sachip->base + SA1111_INTC + sa1111_irqbank(d);
	unsigned int mask = SA1111_IRQMASK_HI(d->irq);
	u32 ip, mask = sa1111_irqmask(d);
	unsigned long ip1;


	if (flags == IRQ_TYPE_PROBE)
	if (flags == IRQ_TYPE_PROBE)
		return 0;
		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)
	if ((!(flags & IRQ_TYPE_EDGE_RISING) ^ !(flags & IRQ_TYPE_EDGE_FALLING)) == 0)
		return -EINVAL;
		return -EINVAL;


	ip1 = sa1111_readl(mapbase + SA1111_INTPOL1);
	ip = sa1111_readl(mapbase + SA1111_INTPOL0);
	if (flags & IRQ_TYPE_EDGE_RISING)
	if (flags & IRQ_TYPE_EDGE_RISING)
		ip1 &= ~mask;
		ip &= ~mask;
	else
	else
		ip1 |= mask;
		ip |= mask;
	sa1111_writel(ip1, mapbase + SA1111_INTPOL1);
	sa1111_writel(ip, mapbase + SA1111_INTPOL0);
	sa1111_writel(ip1, mapbase + SA1111_WAKEPOL1);
	sa1111_writel(ip, mapbase + SA1111_WAKEPOL0);


	return 0;
	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);
	struct sa1111 *sachip = irq_data_get_irq_chip_data(d);
	void __iomem *mapbase = sachip->base + SA1111_INTC;
	void __iomem *mapbase = sachip->base + SA1111_INTC + sa1111_irqbank(d);
	unsigned int mask = SA1111_IRQMASK_HI(d->irq);
	u32 we, mask = sa1111_irqmask(d);
	unsigned long we1;


	we1 = sa1111_readl(mapbase + SA1111_WAKEEN1);
	we = sa1111_readl(mapbase + SA1111_WAKEEN0);
	if (on)
	if (on)
		we1 |= mask;
		we |= mask;
	else
	else
		we1 &= ~mask;
		we &= ~mask;
	sa1111_writel(we1, mapbase + SA1111_WAKEEN1);
	sa1111_writel(we, mapbase + SA1111_WAKEEN0);


	return 0;
	return 0;
}
}


static struct irq_chip sa1111_high_chip = {
static struct irq_chip sa1111_irq_chip = {
	.name		= "SA1111-h",
	.name		= "SA1111",
	.irq_ack	= sa1111_ack_irq,
	.irq_ack	= sa1111_ack_irq,
	.irq_mask	= sa1111_mask_highirq,
	.irq_mask	= sa1111_mask_irq,
	.irq_unmask	= sa1111_unmask_highirq,
	.irq_unmask	= sa1111_unmask_irq,
	.irq_retrigger	= sa1111_retrigger_highirq,
	.irq_retrigger	= sa1111_retrigger_irq,
	.irq_set_type	= sa1111_type_highirq,
	.irq_set_type	= sa1111_type_irq,
	.irq_set_wake	= sa1111_wake_highirq,
	.irq_set_wake	= sa1111_wake_irq,
};
};


static int sa1111_setup_irq(struct sa1111 *sachip, unsigned irq_base)
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++) {
	for (i = IRQ_GPAIN0; i <= SSPROR; i++) {
		irq = sachip->irq_base + i;
		irq = sachip->irq_base + i;
		irq_set_chip_and_handler(irq, &sa1111_low_chip,
		irq_set_chip_and_handler(irq, &sa1111_irq_chip, handle_edge_irq);
					 handle_edge_irq);
		irq_set_chip_data(irq, sachip);
		irq_set_chip_data(irq, sachip);
		irq_clear_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE);
		irq_clear_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE);
	}
	}


	for (i = AUDXMTDMADONEA; i <= IRQ_S1_BVD1_STSCHG; i++) {
	for (i = AUDXMTDMADONEA; i <= IRQ_S1_BVD1_STSCHG; i++) {
		irq = sachip->irq_base + i;
		irq = sachip->irq_base + i;
		irq_set_chip_and_handler(irq, &sa1111_high_chip,
		irq_set_chip_and_handler(irq, &sa1111_irq_chip, handle_edge_irq);
					 handle_edge_irq);
		irq_set_chip_data(irq, sachip);
		irq_set_chip_data(irq, sachip);
		irq_clear_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE);
		irq_clear_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE);
	}
	}