[PATCH v3 05/10] arm: sa1100: use ioremap'ped access instead of direct register access

Dmitry Eremin-Solenikov dbaryshkov at gmail.com
Sat Dec 14 23:28:12 EST 2013


Ioremap MMIO register regions and use readl/writel family of functions
to access IRQ and GPIO edge detection registers.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 arch/arm/mach-sa1100/irq.c | 127 +++++++++++++++++++++++++++++++--------------
 1 file changed, 89 insertions(+), 38 deletions(-)

diff --git a/arch/arm/mach-sa1100/irq.c b/arch/arm/mach-sa1100/irq.c
index 341d296..5b2e183 100644
--- a/arch/arm/mach-sa1100/irq.c
+++ b/arch/arm/mach-sa1100/irq.c
@@ -17,13 +17,26 @@
 #include <linux/ioport.h>
 #include <linux/syscore_ops.h>
 
-#include <mach/hardware.h>
 #include <mach/irqs.h>
 #include <asm/mach/irq.h>
 #include <asm/exception.h>
 
 #include "generic.h"
 
+static void __iomem *irq_regbase;
+
+#define ICIP_OFFSET	0x00  /* IC IRQ Pending reg.             */
+#define ICMR_OFFSET	0x04  /* IC Mask Reg.                    */
+#define ICLR_OFFSET	0x08  /* IC Level Reg.                   */
+#define ICCR_OFFSET	0x0C  /* IC Control Reg.                 */
+#define ICFP_OFFSET	0x10  /* IC FIQ Pending reg.             */
+#define ICPR_OFFSET	0x20  /* IC Pending Reg.                 */
+
+static void __iomem *gpio_regbase;
+
+#define GRER_OFFSET	0x10  /* GPIO Rising-Edge detect Reg.    */
+#define GFER_OFFSET	0x14  /* GPIO Falling-Edge detect Reg.   */
+#define GEDR_OFFSET	0x18  /* GPIO Edge Detect status Reg.    */
 
 /*
  * SA1100 GPIO edge detection for IRQs:
@@ -65,8 +78,10 @@ static int sa1100_gpio_type(struct irq_data *d, unsigned int type)
 	} else
 		GPIO_IRQ_falling_edge &= ~mask;
 
-	GRER = GPIO_IRQ_rising_edge & GPIO_IRQ_mask;
-	GFER = GPIO_IRQ_falling_edge & GPIO_IRQ_mask;
+	writel_relaxed(GPIO_IRQ_rising_edge & GPIO_IRQ_mask,
+			gpio_regbase + GRER_OFFSET);
+	writel_relaxed(GPIO_IRQ_falling_edge & GPIO_IRQ_mask,
+			gpio_regbase + GFER_OFFSET);
 
 	return 0;
 }
@@ -76,17 +91,21 @@ static int sa1100_gpio_type(struct irq_data *d, unsigned int type)
  */
 static void sa1100_low_gpio_ack(struct irq_data *d)
 {
-	GEDR = (1 << d->irq);
+	writel_relaxed((1 << d->irq), gpio_regbase + GEDR_OFFSET);
 }
 
 static void sa1100_low_gpio_mask(struct irq_data *d)
 {
-	ICMR &= ~(1 << d->irq);
+	unsigned int r = readl_relaxed(irq_regbase + ICMR_OFFSET);
+	r &= ~BIT(d->irq);
+	writel_relaxed(r, irq_regbase + ICMR_OFFSET);
 }
 
 static void sa1100_low_gpio_unmask(struct irq_data *d)
 {
-	ICMR |= 1 << d->irq;
+	unsigned int r = readl_relaxed(irq_regbase + ICMR_OFFSET);
+	r |= BIT(d->irq);
+	writel_relaxed(r, irq_regbase + ICMR_OFFSET);
 }
 
 static int sa1100_low_gpio_wake(struct irq_data *d, unsigned int on)
@@ -118,13 +137,13 @@ sa1100_high_gpio_handler(unsigned int irq, struct irq_desc *desc)
 {
 	unsigned int mask;
 
-	mask = GEDR & 0xfffff800;
+	mask = readl_relaxed(gpio_regbase + GEDR_OFFSET) & 0xfffff800;
 	do {
 		/*
 		 * clear down all currently active IRQ sources.
 		 * We will be processing them all.
 		 */
-		GEDR = mask;
+		writel_relaxed(mask, gpio_regbase + GEDR_OFFSET);
 
 		irq = IRQ_GPIO11;
 		mask >>= 11;
@@ -135,7 +154,7 @@ sa1100_high_gpio_handler(unsigned int irq, struct irq_desc *desc)
 			irq++;
 		} while (mask);
 
-		mask = GEDR & 0xfffff800;
+		mask = readl_relaxed(gpio_regbase + GEDR_OFFSET) & 0xfffff800;
 	} while (mask);
 }
 
@@ -148,17 +167,22 @@ static void sa1100_high_gpio_ack(struct irq_data *d)
 {
 	unsigned int mask = GPIO11_27_MASK(d->irq);
 
-	GEDR = mask;
+	writel_relaxed(mask, gpio_regbase + GEDR_OFFSET);
 }
 
 static void sa1100_high_gpio_mask(struct irq_data *d)
 {
 	unsigned int mask = GPIO11_27_MASK(d->irq);
+	unsigned int r;
 
 	GPIO_IRQ_mask &= ~mask;
 
-	GRER &= ~mask;
-	GFER &= ~mask;
+	r = readl_relaxed(gpio_regbase + GRER_OFFSET);
+	r &= ~mask;
+	writel_relaxed(r, gpio_regbase + GRER_OFFSET);
+	r = readl_relaxed(gpio_regbase + GFER_OFFSET);
+	r &= ~mask;
+	writel_relaxed(r, gpio_regbase + GFER_OFFSET);
 }
 
 static void sa1100_high_gpio_unmask(struct irq_data *d)
@@ -167,8 +191,10 @@ static void sa1100_high_gpio_unmask(struct irq_data *d)
 
 	GPIO_IRQ_mask |= mask;
 
-	GRER = GPIO_IRQ_rising_edge & GPIO_IRQ_mask;
-	GFER = GPIO_IRQ_falling_edge & GPIO_IRQ_mask;
+	writel_relaxed(GPIO_IRQ_rising_edge & GPIO_IRQ_mask,
+			gpio_regbase + GRER_OFFSET);
+	writel_relaxed(GPIO_IRQ_falling_edge & GPIO_IRQ_mask,
+			gpio_regbase + GFER_OFFSET);
 }
 
 static int sa1100_high_gpio_wake(struct irq_data *d, unsigned int on)
@@ -196,12 +222,16 @@ static struct irq_chip sa1100_high_gpio_chip = {
  */
 static void sa1100_mask_irq(struct irq_data *d)
 {
-	ICMR &= ~(1 << d->irq);
+	unsigned int r = readl_relaxed(irq_regbase + ICMR_OFFSET);
+	r &= ~BIT(d->irq);
+	writel_relaxed(r, irq_regbase + ICMR_OFFSET);
 }
 
 static void sa1100_unmask_irq(struct irq_data *d)
 {
-	ICMR |= (1 << d->irq);
+	unsigned int r = readl_relaxed(irq_regbase + ICMR_OFFSET);
+	r |= BIT(d->irq);
+	writel_relaxed(r, irq_regbase + ICMR_OFFSET);
 }
 
 /*
@@ -223,6 +253,9 @@ static struct irq_chip sa1100_normal_chip = {
 static struct resource irq_resource =
 	DEFINE_RES_MEM_NAMED(0x90050000, SZ_64K, "irqs");
 
+static struct resource gpio_resource =
+	DEFINE_RES_MEM_NAMED(0x90040000, 20, "gpios");
+
 static struct sa1100irq_state {
 	unsigned int	saved;
 	unsigned int	icmr;
@@ -235,27 +268,28 @@ static int sa1100irq_suspend(void)
 	struct sa1100irq_state *st = &sa1100irq_state;
 
 	st->saved = 1;
-	st->icmr = ICMR;
-	st->iclr = ICLR;
-	st->iccr = ICCR;
+	st->icmr = readl_relaxed(irq_regbase + ICMR_OFFSET);
+	st->iclr = readl_relaxed(irq_regbase + ICLR_OFFSET);
+	st->iccr = readl_relaxed(irq_regbase + ICCR_OFFSET);
 
 	/*
 	 * Disable all GPIO-based interrupts.
 	 */
-	ICMR &= ~(IC_GPIO11_27|IC_GPIO10|IC_GPIO9|IC_GPIO8|IC_GPIO7|
-		  IC_GPIO6|IC_GPIO5|IC_GPIO4|IC_GPIO3|IC_GPIO2|
-		  IC_GPIO1|IC_GPIO0);
+	writel_relaxed(st->icmr & ~0xfff, irq_regbase + ICMR_OFFSET);
 
 	/*
 	 * Set the appropriate edges for wakeup.
 	 */
-	GRER = GPIO_IRQ_wake_mask & GPIO_IRQ_rising_edge;
-	GFER = GPIO_IRQ_wake_mask & GPIO_IRQ_falling_edge;
+	writel_relaxed(GPIO_IRQ_wake_mask & GPIO_IRQ_rising_edge,
+			gpio_regbase + GRER_OFFSET);
+	writel_relaxed(GPIO_IRQ_wake_mask & GPIO_IRQ_falling_edge,
+			gpio_regbase + GFER_OFFSET);
 	
 	/*
 	 * Clear any pending GPIO interrupts.
 	 */
-	GEDR = GEDR;
+	writel_relaxed(readl_relaxed(gpio_regbase + GEDR_OFFSET),
+			gpio_regbase + GEDR_OFFSET);
 
 	return 0;
 }
@@ -265,13 +299,15 @@ static void sa1100irq_resume(void)
 	struct sa1100irq_state *st = &sa1100irq_state;
 
 	if (st->saved) {
-		ICCR = st->iccr;
-		ICLR = st->iclr;
+		writel_relaxed(st->iccr, irq_regbase + ICCR_OFFSET);
+		writel_relaxed(st->iclr, irq_regbase + ICLR_OFFSET);
 
-		GRER = GPIO_IRQ_rising_edge & GPIO_IRQ_mask;
-		GFER = GPIO_IRQ_falling_edge & GPIO_IRQ_mask;
+		writel_relaxed(GPIO_IRQ_rising_edge & GPIO_IRQ_mask,
+				gpio_regbase + GRER_OFFSET);
+		writel_relaxed(GPIO_IRQ_falling_edge & GPIO_IRQ_mask,
+				gpio_regbase + GFER_OFFSET);
 
-		ICMR = st->icmr;
+		writel_relaxed(st->icmr, irq_regbase + ICMR_OFFSET);
 	}
 }
 
@@ -294,8 +330,8 @@ sa1100_handle_irq(struct pt_regs *regs)
 	uint32_t icip, icmr, mask;
 
 	do {
-		icip = (ICIP);
-		icmr = (ICMR);
+		icip = readl_relaxed(irq_regbase + ICIP_OFFSET);
+		icmr = readl_relaxed(irq_regbase + ICMR_OFFSET);
 		mask = icip & icmr;
 
 		if (mask == 0)
@@ -310,23 +346,38 @@ void __init sa1100_init_irq(void)
 	unsigned int irq;
 
 	request_resource(&iomem_resource, &irq_resource);
+	request_resource(&iomem_resource, &gpio_resource);
+
+	irq_regbase = ioremap(irq_resource.start,
+			resource_size(&irq_resource));
+	if (!irq_regbase) {
+		pr_err("Can not remap IRQ registers!\n");
+		return;
+	}
+
+	gpio_regbase = ioremap(gpio_resource.start,
+			resource_size(&gpio_resource));
+	if (!gpio_regbase) {
+		pr_err("Can not remap IRQ registers!\n");
+		return;
+	}
 
 	/* disable all IRQs */
-	ICMR = 0;
+	writel_relaxed(0, irq_regbase + ICMR_OFFSET);
 
 	/* all IRQs are IRQ, not FIQ */
-	ICLR = 0;
+	writel_relaxed(0, irq_regbase + ICLR_OFFSET);
 
 	/* clear all GPIO edge detects */
-	GFER = 0;
-	GRER = 0;
-	GEDR = -1;
+	writel_relaxed(0, gpio_regbase + GFER_OFFSET);
+	writel_relaxed(0, gpio_regbase + GRER_OFFSET);
+	writel_relaxed(~0, gpio_regbase + GEDR_OFFSET);
 
 	/*
 	 * Whatever the doc says, this has to be set for the wait-on-irq
 	 * instruction to work... on a SA1100 rev 9 at least.
 	 */
-	ICCR = 1;
+	writel_relaxed(1, irq_regbase + ICCR_OFFSET);
 
 	for (irq = 0; irq <= 10; irq++) {
 		irq_set_chip_and_handler(irq, &sa1100_low_gpio_chip,
-- 
1.8.5.1




More information about the linux-arm-kernel mailing list