linux-gpio.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/5] ARM: sa1100: split irq handling for low GPIOs
@ 2014-12-22 10:05 Dmitry Eremin-Solenikov
  2014-12-22 10:05 ` [PATCH 2/5] ARM: sa1100: merge both GPIO irqdomains Dmitry Eremin-Solenikov
                   ` (4 more replies)
  0 siblings, 5 replies; 7+ messages in thread
From: Dmitry Eremin-Solenikov @ 2014-12-22 10:05 UTC (permalink / raw)
  To: Russell King, Linus Walleij
  Cc: Alexandre Courbot, linux-arm-kernel, linux-gpio

Low GPIO pins use an interrupt in SC interrupts space. However it's
possible to handle them as if all the GPIO interrupts are instead tied
to single GPIO handler, which later decodes GEDR register and
chain-calls next IRQ handler. So split first 11 interrupts into system
part (IRQ_GPIO0_SC - IRQ_GPIO10_SC) which work exactly like the rest of
system controller interrupts and real GPIO interrupts
(IRQ_GPIO0..IRQ_GPIO10). A single handler sa1100_gpio_handler then
decodes and calls next handler.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
---
 arch/arm/mach-sa1100/include/mach/irqs.h | 73 +++++++++++++++------------
 arch/arm/mach-sa1100/irq.c               | 87 ++++++++++++++++++--------------
 drivers/gpio/gpio-sa1100.c               |  2 +-
 3 files changed, 93 insertions(+), 69 deletions(-)

diff --git a/arch/arm/mach-sa1100/include/mach/irqs.h b/arch/arm/mach-sa1100/include/mach/irqs.h
index de09834..734e30e 100644
--- a/arch/arm/mach-sa1100/include/mach/irqs.h
+++ b/arch/arm/mach-sa1100/include/mach/irqs.h
@@ -8,17 +8,17 @@
  * 2001/11/14	RMK	Cleaned up and standardised a lot of the IRQs.
  */
 
-#define	IRQ_GPIO0		1
-#define	IRQ_GPIO1		2
-#define	IRQ_GPIO2		3
-#define	IRQ_GPIO3		4
-#define	IRQ_GPIO4		5
-#define	IRQ_GPIO5		6
-#define	IRQ_GPIO6		7
-#define	IRQ_GPIO7		8
-#define	IRQ_GPIO8		9
-#define	IRQ_GPIO9		10
-#define	IRQ_GPIO10		11
+#define	IRQ_GPIO0_SC		1
+#define	IRQ_GPIO1_SC		2
+#define	IRQ_GPIO2_SC		3
+#define	IRQ_GPIO3_SC		4
+#define	IRQ_GPIO4_SC		5
+#define	IRQ_GPIO5_SC		6
+#define	IRQ_GPIO6_SC		7
+#define	IRQ_GPIO7_SC		8
+#define	IRQ_GPIO8_SC		9
+#define	IRQ_GPIO9_SC		10
+#define	IRQ_GPIO10_SC		11
 #define	IRQ_GPIO11_27		12
 #define	IRQ_LCD			13	/* LCD controller           */
 #define	IRQ_Ser0UDC		14	/* Ser. port 0 UDC          */
@@ -41,32 +41,43 @@
 #define	IRQ_RTC1Hz		31	/* RTC 1 Hz clock           */
 #define	IRQ_RTCAlrm		32	/* RTC Alarm                */
 
-#define	IRQ_GPIO11		33
-#define	IRQ_GPIO12		34
-#define	IRQ_GPIO13		35
-#define	IRQ_GPIO14		36
-#define	IRQ_GPIO15		37
-#define	IRQ_GPIO16		38
-#define	IRQ_GPIO17		39
-#define	IRQ_GPIO18		40
-#define	IRQ_GPIO19		41
-#define	IRQ_GPIO20		42
-#define	IRQ_GPIO21		43
-#define	IRQ_GPIO22		44
-#define	IRQ_GPIO23		45
-#define	IRQ_GPIO24		46
-#define	IRQ_GPIO25		47
-#define	IRQ_GPIO26		48
-#define	IRQ_GPIO27		49
+#define	IRQ_GPIO0		33
+#define	IRQ_GPIO1		34
+#define	IRQ_GPIO2		35
+#define	IRQ_GPIO3		36
+#define	IRQ_GPIO4		37
+#define	IRQ_GPIO5		38
+#define	IRQ_GPIO6		39
+#define	IRQ_GPIO7		40
+#define	IRQ_GPIO8		41
+#define	IRQ_GPIO9		42
+#define	IRQ_GPIO10		43
+#define	IRQ_GPIO11		44
+#define	IRQ_GPIO12		45
+#define	IRQ_GPIO13		46
+#define	IRQ_GPIO14		47
+#define	IRQ_GPIO15		48
+#define	IRQ_GPIO16		49
+#define	IRQ_GPIO17		50
+#define	IRQ_GPIO18		51
+#define	IRQ_GPIO19		52
+#define	IRQ_GPIO20		53
+#define	IRQ_GPIO21		54
+#define	IRQ_GPIO22		55
+#define	IRQ_GPIO23		56
+#define	IRQ_GPIO24		57
+#define	IRQ_GPIO25		58
+#define	IRQ_GPIO26		59
+#define	IRQ_GPIO27		60
 
 /*
  * The next 16 interrupts are for board specific purposes.  Since
  * the kernel can only run on one machine at a time, we can re-use
  * these.  If you need more, increase IRQ_BOARD_END, but keep it
- * within sensible limits.  IRQs 49 to 64 are available.
+ * within sensible limits.  IRQs 61 to 76 are available.
  */
-#define IRQ_BOARD_START		50
-#define IRQ_BOARD_END		66
+#define IRQ_BOARD_START		61
+#define IRQ_BOARD_END		77
 
 /*
  * Figure out the MAX IRQ number.
diff --git a/arch/arm/mach-sa1100/irq.c b/arch/arm/mach-sa1100/irq.c
index 63e2901..2dc6a2a 100644
--- a/arch/arm/mach-sa1100/irq.c
+++ b/arch/arm/mach-sa1100/irq.c
@@ -87,7 +87,7 @@ static struct irq_domain *sa1100_normal_irqdomain;
  */
 static int GPIO_IRQ_rising_edge;
 static int GPIO_IRQ_falling_edge;
-static int GPIO_IRQ_mask = (1 << 11) - 1;
+static int GPIO_IRQ_mask;
 
 static int sa1100_gpio_type(struct irq_data *d, unsigned int type)
 {
@@ -124,6 +124,26 @@ static void sa1100_gpio_ack(struct irq_data *d)
 	GEDR = BIT(d->hwirq);
 }
 
+static void sa1100_gpio_mask(struct irq_data *d)
+{
+	unsigned int mask = BIT(d->hwirq);
+
+	GPIO_IRQ_mask &= ~mask;
+
+	GRER &= ~mask;
+	GFER &= ~mask;
+}
+
+static void sa1100_gpio_unmask(struct irq_data *d)
+{
+	unsigned int mask = BIT(d->hwirq);
+
+	GPIO_IRQ_mask |= mask;
+
+	GRER = GPIO_IRQ_rising_edge & GPIO_IRQ_mask;
+	GFER = GPIO_IRQ_falling_edge & GPIO_IRQ_mask;
+}
+
 static int sa1100_gpio_wake(struct irq_data *d, unsigned int on)
 {
 	if (on)
@@ -139,8 +159,8 @@ static int sa1100_gpio_wake(struct irq_data *d, unsigned int on)
 static struct irq_chip sa1100_low_gpio_chip = {
 	.name		= "GPIO-l",
 	.irq_ack	= sa1100_gpio_ack,
-	.irq_mask	= sa1100_mask_irq,
-	.irq_unmask	= sa1100_unmask_irq,
+	.irq_mask	= sa1100_gpio_mask,
+	.irq_unmask	= sa1100_gpio_unmask,
 	.irq_set_type	= sa1100_gpio_type,
 	.irq_set_wake	= sa1100_gpio_wake,
 };
@@ -163,16 +183,16 @@ static struct irq_domain_ops sa1100_low_gpio_irqdomain_ops = {
 static struct irq_domain *sa1100_low_gpio_irqdomain;
 
 /*
- * IRQ11 (GPIO11 through 27) handler.  We enter here with the
+ * IRQ 0-11 (GPIO) handler.  We enter here with the
  * irq_controller_lock held, and IRQs disabled.  Decode the IRQ
  * and call the handler.
  */
 static void
-sa1100_high_gpio_handler(unsigned int irq, struct irq_desc *desc)
+sa1100_gpio_handler(unsigned int irq, struct irq_desc *desc)
 {
 	unsigned int mask;
 
-	mask = GEDR & 0xfffff800;
+	mask = GEDR;
 	do {
 		/*
 		 * clear down all currently active IRQ sources.
@@ -180,8 +200,7 @@ sa1100_high_gpio_handler(unsigned int irq, struct irq_desc *desc)
 		 */
 		GEDR = mask;
 
-		irq = IRQ_GPIO11;
-		mask >>= 11;
+		irq = IRQ_GPIO0;
 		do {
 			if (mask & 1)
 				generic_handle_irq(irq);
@@ -189,7 +208,7 @@ sa1100_high_gpio_handler(unsigned int irq, struct irq_desc *desc)
 			irq++;
 		} while (mask);
 
-		mask = GEDR & 0xfffff800;
+		mask = GEDR;
 	} while (mask);
 }
 
@@ -198,31 +217,11 @@ sa1100_high_gpio_handler(unsigned int irq, struct irq_desc *desc)
  * In addition, the IRQs are all collected up into one bit in the
  * interrupt controller registers.
  */
-static void sa1100_high_gpio_mask(struct irq_data *d)
-{
-	unsigned int mask = BIT(d->hwirq);
-
-	GPIO_IRQ_mask &= ~mask;
-
-	GRER &= ~mask;
-	GFER &= ~mask;
-}
-
-static void sa1100_high_gpio_unmask(struct irq_data *d)
-{
-	unsigned int mask = BIT(d->hwirq);
-
-	GPIO_IRQ_mask |= mask;
-
-	GRER = GPIO_IRQ_rising_edge & GPIO_IRQ_mask;
-	GFER = GPIO_IRQ_falling_edge & GPIO_IRQ_mask;
-}
-
 static struct irq_chip sa1100_high_gpio_chip = {
 	.name		= "GPIO-h",
 	.irq_ack	= sa1100_gpio_ack,
-	.irq_mask	= sa1100_high_gpio_mask,
-	.irq_unmask	= sa1100_high_gpio_unmask,
+	.irq_mask	= sa1100_gpio_mask,
+	.irq_unmask	= sa1100_gpio_unmask,
 	.irq_set_type	= sa1100_gpio_type,
 	.irq_set_wake	= sa1100_gpio_wake,
 };
@@ -325,7 +324,7 @@ sa1100_handle_irq(struct pt_regs *regs)
 		if (mask == 0)
 			break;
 
-		handle_IRQ(ffs(mask) - 1 + IRQ_GPIO0, regs);
+		handle_IRQ(ffs(mask) - 1 + IRQ_GPIO0_SC, regs);
 	} while (1);
 }
 
@@ -350,22 +349,36 @@ void __init sa1100_init_irq(void)
 	 */
 	ICCR = 1;
 
+	sa1100_normal_irqdomain = irq_domain_add_legacy(NULL,
+			32, IRQ_GPIO0_SC, 0,
+			&sa1100_normal_irqdomain_ops, NULL);
+
 	sa1100_low_gpio_irqdomain = irq_domain_add_legacy(NULL,
 			11, IRQ_GPIO0, 0,
 			&sa1100_low_gpio_irqdomain_ops, NULL);
 
-	sa1100_normal_irqdomain = irq_domain_add_legacy(NULL,
-			21, IRQ_GPIO11_27, 11,
-			&sa1100_normal_irqdomain_ops, NULL);
-
 	sa1100_high_gpio_irqdomain = irq_domain_add_legacy(NULL,
 			17, IRQ_GPIO11, 11,
 			&sa1100_high_gpio_irqdomain_ops, NULL);
 
 	/*
+	 * Install handlers for GPIO 0-10 edge detect interrupts
+	 */
+	irq_set_chained_handler(IRQ_GPIO0_SC, sa1100_gpio_handler);
+	irq_set_chained_handler(IRQ_GPIO1_SC, sa1100_gpio_handler);
+	irq_set_chained_handler(IRQ_GPIO2_SC, sa1100_gpio_handler);
+	irq_set_chained_handler(IRQ_GPIO3_SC, sa1100_gpio_handler);
+	irq_set_chained_handler(IRQ_GPIO4_SC, sa1100_gpio_handler);
+	irq_set_chained_handler(IRQ_GPIO5_SC, sa1100_gpio_handler);
+	irq_set_chained_handler(IRQ_GPIO6_SC, sa1100_gpio_handler);
+	irq_set_chained_handler(IRQ_GPIO7_SC, sa1100_gpio_handler);
+	irq_set_chained_handler(IRQ_GPIO8_SC, sa1100_gpio_handler);
+	irq_set_chained_handler(IRQ_GPIO9_SC, sa1100_gpio_handler);
+	irq_set_chained_handler(IRQ_GPIO10_SC, sa1100_gpio_handler);
+	/*
 	 * Install handler for GPIO 11-27 edge detect interrupts
 	 */
-	irq_set_chained_handler(IRQ_GPIO11_27, sa1100_high_gpio_handler);
+	irq_set_chained_handler(IRQ_GPIO11_27, sa1100_gpio_handler);
 
 	set_handle_irq(sa1100_handle_irq);
 
diff --git a/drivers/gpio/gpio-sa1100.c b/drivers/gpio/gpio-sa1100.c
index a90be34..5b5d3c7 100644
--- a/drivers/gpio/gpio-sa1100.c
+++ b/drivers/gpio/gpio-sa1100.c
@@ -50,7 +50,7 @@ static int sa1100_direction_output(struct gpio_chip *chip, unsigned offset, int
 
 static int sa1100_to_irq(struct gpio_chip *chip, unsigned offset)
 {
-	return offset < 11 ? (IRQ_GPIO0 + offset) : (IRQ_GPIO11 - 11 + offset);
+	return IRQ_GPIO0 + offset;
 }
 
 static struct gpio_chip sa1100_gpio_chip = {
-- 
2.1.3


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 2/5] ARM: sa1100: merge both GPIO irqdomains
  2014-12-22 10:05 [PATCH 1/5] ARM: sa1100: split irq handling for low GPIOs Dmitry Eremin-Solenikov
@ 2014-12-22 10:05 ` Dmitry Eremin-Solenikov
  2014-12-22 10:05 ` [PATCH 3/5] ARM: sa1100: switch to irq_domain_add_simple() Dmitry Eremin-Solenikov
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 7+ messages in thread
From: Dmitry Eremin-Solenikov @ 2014-12-22 10:05 UTC (permalink / raw)
  To: Russell King, Linus Walleij
  Cc: Alexandre Courbot, linux-arm-kernel, linux-gpio

Now there is no difference between low and high GPIO irqdomains. Merge
them into single irqdomain handling all GPIOs.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
---
 arch/arm/mach-sa1100/irq.c | 57 +++++++++-------------------------------------
 1 file changed, 11 insertions(+), 46 deletions(-)

diff --git a/arch/arm/mach-sa1100/irq.c b/arch/arm/mach-sa1100/irq.c
index 2dc6a2a..5589b23 100644
--- a/arch/arm/mach-sa1100/irq.c
+++ b/arch/arm/mach-sa1100/irq.c
@@ -154,10 +154,10 @@ static int sa1100_gpio_wake(struct irq_data *d, unsigned int on)
 }
 
 /*
- * This is for IRQs from 0 to 10.
+ * This is for GPIO IRQs
  */
-static struct irq_chip sa1100_low_gpio_chip = {
-	.name		= "GPIO-l",
+static struct irq_chip sa1100_gpio_chip = {
+	.name		= "GPIO",
 	.irq_ack	= sa1100_gpio_ack,
 	.irq_mask	= sa1100_gpio_mask,
 	.irq_unmask	= sa1100_gpio_unmask,
@@ -165,22 +165,22 @@ static struct irq_chip sa1100_low_gpio_chip = {
 	.irq_set_wake	= sa1100_gpio_wake,
 };
 
-static int sa1100_low_gpio_irqdomain_map(struct irq_domain *d,
+static int sa1100_gpio_irqdomain_map(struct irq_domain *d,
 		unsigned int irq, irq_hw_number_t hwirq)
 {
-	irq_set_chip_and_handler(irq, &sa1100_low_gpio_chip,
+	irq_set_chip_and_handler(irq, &sa1100_gpio_chip,
 				 handle_edge_irq);
 	set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
 
 	return 0;
 }
 
-static struct irq_domain_ops sa1100_low_gpio_irqdomain_ops = {
-	.map = sa1100_low_gpio_irqdomain_map,
+static struct irq_domain_ops sa1100_gpio_irqdomain_ops = {
+	.map = sa1100_gpio_irqdomain_map,
 	.xlate = irq_domain_xlate_onetwocell,
 };
 
-static struct irq_domain *sa1100_low_gpio_irqdomain;
+static struct irq_domain *sa1100_gpio_irqdomain;
 
 /*
  * IRQ 0-11 (GPIO) handler.  We enter here with the
@@ -212,37 +212,6 @@ sa1100_gpio_handler(unsigned int irq, struct irq_desc *desc)
 	} while (mask);
 }
 
-/*
- * Like GPIO0 to 10, GPIO11-27 IRQs need to be handled specially.
- * In addition, the IRQs are all collected up into one bit in the
- * interrupt controller registers.
- */
-static struct irq_chip sa1100_high_gpio_chip = {
-	.name		= "GPIO-h",
-	.irq_ack	= sa1100_gpio_ack,
-	.irq_mask	= sa1100_gpio_mask,
-	.irq_unmask	= sa1100_gpio_unmask,
-	.irq_set_type	= sa1100_gpio_type,
-	.irq_set_wake	= sa1100_gpio_wake,
-};
-
-static int sa1100_high_gpio_irqdomain_map(struct irq_domain *d,
-		unsigned int irq, irq_hw_number_t hwirq)
-{
-	irq_set_chip_and_handler(irq, &sa1100_high_gpio_chip,
-				 handle_edge_irq);
-	set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
-
-	return 0;
-}
-
-static struct irq_domain_ops sa1100_high_gpio_irqdomain_ops = {
-	.map = sa1100_high_gpio_irqdomain_map,
-	.xlate = irq_domain_xlate_onetwocell,
-};
-
-static struct irq_domain *sa1100_high_gpio_irqdomain;
-
 static struct resource irq_resource =
 	DEFINE_RES_MEM_NAMED(0x90050000, SZ_64K, "irqs");
 
@@ -353,13 +322,9 @@ void __init sa1100_init_irq(void)
 			32, IRQ_GPIO0_SC, 0,
 			&sa1100_normal_irqdomain_ops, NULL);
 
-	sa1100_low_gpio_irqdomain = irq_domain_add_legacy(NULL,
-			11, IRQ_GPIO0, 0,
-			&sa1100_low_gpio_irqdomain_ops, NULL);
-
-	sa1100_high_gpio_irqdomain = irq_domain_add_legacy(NULL,
-			17, IRQ_GPIO11, 11,
-			&sa1100_high_gpio_irqdomain_ops, NULL);
+	sa1100_gpio_irqdomain = irq_domain_add_legacy(NULL,
+			28, IRQ_GPIO0, 0,
+			&sa1100_gpio_irqdomain_ops, NULL);
 
 	/*
 	 * Install handlers for GPIO 0-10 edge detect interrupts
-- 
2.1.3


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 3/5] ARM: sa1100: switch to irq_domain_add_simple()
  2014-12-22 10:05 [PATCH 1/5] ARM: sa1100: split irq handling for low GPIOs Dmitry Eremin-Solenikov
  2014-12-22 10:05 ` [PATCH 2/5] ARM: sa1100: merge both GPIO irqdomains Dmitry Eremin-Solenikov
@ 2014-12-22 10:05 ` Dmitry Eremin-Solenikov
  2014-12-22 10:05 ` [PATCH 4/5] ARM: sa1100: move GPIO-related IRQ code to gpio driver Dmitry Eremin-Solenikov
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 7+ messages in thread
From: Dmitry Eremin-Solenikov @ 2014-12-22 10:05 UTC (permalink / raw)
  To: Russell King, Linus Walleij
  Cc: Alexandre Courbot, linux-arm-kernel, linux-gpio

As now both SC and GPIO irq domains start from 0 hwirq and do not
contain holes, switch to using irq_domain_add_simple() instead of
irq_domain_add_legacy().

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

diff --git a/arch/arm/mach-sa1100/irq.c b/arch/arm/mach-sa1100/irq.c
index 5589b23..a9dfe8e 100644
--- a/arch/arm/mach-sa1100/irq.c
+++ b/arch/arm/mach-sa1100/irq.c
@@ -318,12 +318,12 @@ void __init sa1100_init_irq(void)
 	 */
 	ICCR = 1;
 
-	sa1100_normal_irqdomain = irq_domain_add_legacy(NULL,
-			32, IRQ_GPIO0_SC, 0,
+	sa1100_normal_irqdomain = irq_domain_add_simple(NULL,
+			32, IRQ_GPIO0_SC,
 			&sa1100_normal_irqdomain_ops, NULL);
 
-	sa1100_gpio_irqdomain = irq_domain_add_legacy(NULL,
-			28, IRQ_GPIO0, 0,
+	sa1100_gpio_irqdomain = irq_domain_add_simple(NULL,
+			28, IRQ_GPIO0,
 			&sa1100_gpio_irqdomain_ops, NULL);
 
 	/*
-- 
2.1.3


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 4/5] ARM: sa1100: move GPIO-related IRQ code to gpio driver
  2014-12-22 10:05 [PATCH 1/5] ARM: sa1100: split irq handling for low GPIOs Dmitry Eremin-Solenikov
  2014-12-22 10:05 ` [PATCH 2/5] ARM: sa1100: merge both GPIO irqdomains Dmitry Eremin-Solenikov
  2014-12-22 10:05 ` [PATCH 3/5] ARM: sa1100: switch to irq_domain_add_simple() Dmitry Eremin-Solenikov
@ 2014-12-22 10:05 ` Dmitry Eremin-Solenikov
  2014-12-22 10:05 ` [PATCH 5/5] ARM: sa1100: use handle_domain_irq Dmitry Eremin-Solenikov
  2015-01-14  9:35 ` [PATCH 1/5] ARM: sa1100: split irq handling for low GPIOs Linus Walleij
  4 siblings, 0 replies; 7+ messages in thread
From: Dmitry Eremin-Solenikov @ 2014-12-22 10:05 UTC (permalink / raw)
  To: Russell King, Linus Walleij
  Cc: Alexandre Courbot, linux-arm-kernel, linux-gpio

As a part of driver consolidation, move GPIO-related IRQ code to
drivers/gpio/gpio-sa1100.c. The code does not use GPIOLIB_IRQCHIP (yet),
because sa1100 does not have a device for gpios, which is a requirement
for GPIOLIB_IRQCHIP. This will be the next step.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
---
 arch/arm/mach-sa1100/irq.c | 174 ---------------------------------------
 drivers/gpio/gpio-sa1100.c | 197 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 197 insertions(+), 174 deletions(-)

diff --git a/arch/arm/mach-sa1100/irq.c b/arch/arm/mach-sa1100/irq.c
index a9dfe8e..a7d116a 100644
--- a/arch/arm/mach-sa1100/irq.c
+++ b/arch/arm/mach-sa1100/irq.c
@@ -80,138 +80,6 @@ static struct irq_domain_ops sa1100_normal_irqdomain_ops = {
 
 static struct irq_domain *sa1100_normal_irqdomain;
 
-/*
- * SA1100 GPIO edge detection for IRQs:
- * IRQs are generated on Falling-Edge, Rising-Edge, or both.
- * Use this instead of directly setting GRER/GFER.
- */
-static int GPIO_IRQ_rising_edge;
-static int GPIO_IRQ_falling_edge;
-static int GPIO_IRQ_mask;
-
-static int sa1100_gpio_type(struct irq_data *d, unsigned int type)
-{
-	unsigned int mask;
-
-	mask = BIT(d->hwirq);
-
-	if (type == IRQ_TYPE_PROBE) {
-		if ((GPIO_IRQ_rising_edge | GPIO_IRQ_falling_edge) & mask)
-			return 0;
-		type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
-	}
-
-	if (type & IRQ_TYPE_EDGE_RISING) {
-		GPIO_IRQ_rising_edge |= mask;
-	} else
-		GPIO_IRQ_rising_edge &= ~mask;
-	if (type & IRQ_TYPE_EDGE_FALLING) {
-		GPIO_IRQ_falling_edge |= mask;
-	} else
-		GPIO_IRQ_falling_edge &= ~mask;
-
-	GRER = GPIO_IRQ_rising_edge & GPIO_IRQ_mask;
-	GFER = GPIO_IRQ_falling_edge & GPIO_IRQ_mask;
-
-	return 0;
-}
-
-/*
- * GPIO IRQs must be acknowledged.
- */
-static void sa1100_gpio_ack(struct irq_data *d)
-{
-	GEDR = BIT(d->hwirq);
-}
-
-static void sa1100_gpio_mask(struct irq_data *d)
-{
-	unsigned int mask = BIT(d->hwirq);
-
-	GPIO_IRQ_mask &= ~mask;
-
-	GRER &= ~mask;
-	GFER &= ~mask;
-}
-
-static void sa1100_gpio_unmask(struct irq_data *d)
-{
-	unsigned int mask = BIT(d->hwirq);
-
-	GPIO_IRQ_mask |= mask;
-
-	GRER = GPIO_IRQ_rising_edge & GPIO_IRQ_mask;
-	GFER = GPIO_IRQ_falling_edge & GPIO_IRQ_mask;
-}
-
-static int sa1100_gpio_wake(struct irq_data *d, unsigned int on)
-{
-	if (on)
-		PWER |= BIT(d->hwirq);
-	else
-		PWER &= ~BIT(d->hwirq);
-	return 0;
-}
-
-/*
- * This is for GPIO IRQs
- */
-static struct irq_chip sa1100_gpio_chip = {
-	.name		= "GPIO",
-	.irq_ack	= sa1100_gpio_ack,
-	.irq_mask	= sa1100_gpio_mask,
-	.irq_unmask	= sa1100_gpio_unmask,
-	.irq_set_type	= sa1100_gpio_type,
-	.irq_set_wake	= sa1100_gpio_wake,
-};
-
-static int sa1100_gpio_irqdomain_map(struct irq_domain *d,
-		unsigned int irq, irq_hw_number_t hwirq)
-{
-	irq_set_chip_and_handler(irq, &sa1100_gpio_chip,
-				 handle_edge_irq);
-	set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
-
-	return 0;
-}
-
-static struct irq_domain_ops sa1100_gpio_irqdomain_ops = {
-	.map = sa1100_gpio_irqdomain_map,
-	.xlate = irq_domain_xlate_onetwocell,
-};
-
-static struct irq_domain *sa1100_gpio_irqdomain;
-
-/*
- * IRQ 0-11 (GPIO) handler.  We enter here with the
- * irq_controller_lock held, and IRQs disabled.  Decode the IRQ
- * and call the handler.
- */
-static void
-sa1100_gpio_handler(unsigned int irq, struct irq_desc *desc)
-{
-	unsigned int mask;
-
-	mask = GEDR;
-	do {
-		/*
-		 * clear down all currently active IRQ sources.
-		 * We will be processing them all.
-		 */
-		GEDR = mask;
-
-		irq = IRQ_GPIO0;
-		do {
-			if (mask & 1)
-				generic_handle_irq(irq);
-			mask >>= 1;
-			irq++;
-		} while (mask);
-
-		mask = GEDR;
-	} while (mask);
-}
-
 static struct resource irq_resource =
 	DEFINE_RES_MEM_NAMED(0x90050000, SZ_64K, "irqs");
 
@@ -238,17 +106,6 @@ static int sa1100irq_suspend(void)
 		  IC_GPIO6|IC_GPIO5|IC_GPIO4|IC_GPIO3|IC_GPIO2|
 		  IC_GPIO1|IC_GPIO0);
 
-	/*
-	 * Set the appropriate edges for wakeup.
-	 */
-	GRER = PWER & GPIO_IRQ_rising_edge;
-	GFER = PWER & GPIO_IRQ_falling_edge;
-	
-	/*
-	 * Clear any pending GPIO interrupts.
-	 */
-	GEDR = GEDR;
-
 	return 0;
 }
 
@@ -260,9 +117,6 @@ static void sa1100irq_resume(void)
 		ICCR = st->iccr;
 		ICLR = st->iclr;
 
-		GRER = GPIO_IRQ_rising_edge & GPIO_IRQ_mask;
-		GFER = GPIO_IRQ_falling_edge & GPIO_IRQ_mask;
-
 		ICMR = st->icmr;
 	}
 }
@@ -307,11 +161,6 @@ void __init sa1100_init_irq(void)
 	/* all IRQs are IRQ, not FIQ */
 	ICLR = 0;
 
-	/* clear all GPIO edge detects */
-	GFER = 0;
-	GRER = 0;
-	GEDR = -1;
-
 	/*
 	 * Whatever the doc says, this has to be set for the wait-on-irq
 	 * instruction to work... on a SA1100 rev 9 at least.
@@ -322,29 +171,6 @@ void __init sa1100_init_irq(void)
 			32, IRQ_GPIO0_SC,
 			&sa1100_normal_irqdomain_ops, NULL);
 
-	sa1100_gpio_irqdomain = irq_domain_add_simple(NULL,
-			28, IRQ_GPIO0,
-			&sa1100_gpio_irqdomain_ops, NULL);
-
-	/*
-	 * Install handlers for GPIO 0-10 edge detect interrupts
-	 */
-	irq_set_chained_handler(IRQ_GPIO0_SC, sa1100_gpio_handler);
-	irq_set_chained_handler(IRQ_GPIO1_SC, sa1100_gpio_handler);
-	irq_set_chained_handler(IRQ_GPIO2_SC, sa1100_gpio_handler);
-	irq_set_chained_handler(IRQ_GPIO3_SC, sa1100_gpio_handler);
-	irq_set_chained_handler(IRQ_GPIO4_SC, sa1100_gpio_handler);
-	irq_set_chained_handler(IRQ_GPIO5_SC, sa1100_gpio_handler);
-	irq_set_chained_handler(IRQ_GPIO6_SC, sa1100_gpio_handler);
-	irq_set_chained_handler(IRQ_GPIO7_SC, sa1100_gpio_handler);
-	irq_set_chained_handler(IRQ_GPIO8_SC, sa1100_gpio_handler);
-	irq_set_chained_handler(IRQ_GPIO9_SC, sa1100_gpio_handler);
-	irq_set_chained_handler(IRQ_GPIO10_SC, sa1100_gpio_handler);
-	/*
-	 * Install handler for GPIO 11-27 edge detect interrupts
-	 */
-	irq_set_chained_handler(IRQ_GPIO11_27, sa1100_gpio_handler);
-
 	set_handle_irq(sa1100_handle_irq);
 
 	sa1100_init_gpio();
diff --git a/drivers/gpio/gpio-sa1100.c b/drivers/gpio/gpio-sa1100.c
index 5b5d3c7..bec397a 100644
--- a/drivers/gpio/gpio-sa1100.c
+++ b/drivers/gpio/gpio-sa1100.c
@@ -11,6 +11,7 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/io.h>
+#include <linux/syscore_ops.h>
 #include <mach/hardware.h>
 #include <mach/irqs.h>
 
@@ -64,7 +65,203 @@ static struct gpio_chip sa1100_gpio_chip = {
 	.ngpio			= GPIO_MAX + 1,
 };
 
+/*
+ * SA1100 GPIO edge detection for IRQs:
+ * IRQs are generated on Falling-Edge, Rising-Edge, or both.
+ * Use this instead of directly setting GRER/GFER.
+ */
+static int GPIO_IRQ_rising_edge;
+static int GPIO_IRQ_falling_edge;
+static int GPIO_IRQ_mask;
+
+static int sa1100_gpio_type(struct irq_data *d, unsigned int type)
+{
+	unsigned int mask;
+
+	mask = BIT(d->hwirq);
+
+	if (type == IRQ_TYPE_PROBE) {
+		if ((GPIO_IRQ_rising_edge | GPIO_IRQ_falling_edge) & mask)
+			return 0;
+		type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
+	}
+
+	if (type & IRQ_TYPE_EDGE_RISING)
+		GPIO_IRQ_rising_edge |= mask;
+	else
+		GPIO_IRQ_rising_edge &= ~mask;
+	if (type & IRQ_TYPE_EDGE_FALLING)
+		GPIO_IRQ_falling_edge |= mask;
+	else
+		GPIO_IRQ_falling_edge &= ~mask;
+
+	GRER = GPIO_IRQ_rising_edge & GPIO_IRQ_mask;
+	GFER = GPIO_IRQ_falling_edge & GPIO_IRQ_mask;
+
+	return 0;
+}
+
+/*
+ * GPIO IRQs must be acknowledged.
+ */
+static void sa1100_gpio_ack(struct irq_data *d)
+{
+	GEDR = BIT(d->hwirq);
+}
+
+static void sa1100_gpio_mask(struct irq_data *d)
+{
+	unsigned int mask = BIT(d->hwirq);
+
+	GPIO_IRQ_mask &= ~mask;
+
+	GRER &= ~mask;
+	GFER &= ~mask;
+}
+
+static void sa1100_gpio_unmask(struct irq_data *d)
+{
+	unsigned int mask = BIT(d->hwirq);
+
+	GPIO_IRQ_mask |= mask;
+
+	GRER = GPIO_IRQ_rising_edge & GPIO_IRQ_mask;
+	GFER = GPIO_IRQ_falling_edge & GPIO_IRQ_mask;
+}
+
+static int sa1100_gpio_wake(struct irq_data *d, unsigned int on)
+{
+	if (on)
+		PWER |= BIT(d->hwirq);
+	else
+		PWER &= ~BIT(d->hwirq);
+	return 0;
+}
+
+/*
+ * This is for GPIO IRQs
+ */
+static struct irq_chip sa1100_gpio_irq_chip = {
+	.name		= "GPIO",
+	.irq_ack	= sa1100_gpio_ack,
+	.irq_mask	= sa1100_gpio_mask,
+	.irq_unmask	= sa1100_gpio_unmask,
+	.irq_set_type	= sa1100_gpio_type,
+	.irq_set_wake	= sa1100_gpio_wake,
+};
+
+static int sa1100_gpio_irqdomain_map(struct irq_domain *d,
+		unsigned int irq, irq_hw_number_t hwirq)
+{
+	irq_set_chip_and_handler(irq, &sa1100_gpio_irq_chip,
+				 handle_edge_irq);
+	set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+
+	return 0;
+}
+
+static struct irq_domain_ops sa1100_gpio_irqdomain_ops = {
+	.map = sa1100_gpio_irqdomain_map,
+	.xlate = irq_domain_xlate_onetwocell,
+};
+
+static struct irq_domain *sa1100_gpio_irqdomain;
+
+/*
+ * IRQ 0-11 (GPIO) handler.  We enter here with the
+ * irq_controller_lock held, and IRQs disabled.  Decode the IRQ
+ * and call the handler.
+ */
+static void
+sa1100_gpio_handler(unsigned int irq, struct irq_desc *desc)
+{
+	unsigned int mask;
+
+	mask = GEDR;
+	do {
+		/*
+		 * clear down all currently active IRQ sources.
+		 * We will be processing them all.
+		 */
+		GEDR = mask;
+
+		irq = IRQ_GPIO0;
+		do {
+			if (mask & 1)
+				generic_handle_irq(irq);
+			mask >>= 1;
+			irq++;
+		} while (mask);
+
+		mask = GEDR;
+	} while (mask);
+}
+
+static int sa1100_gpio_suspend(void)
+{
+	/*
+	 * Set the appropriate edges for wakeup.
+	 */
+	GRER = PWER & GPIO_IRQ_rising_edge;
+	GFER = PWER & GPIO_IRQ_falling_edge;
+
+	/*
+	 * Clear any pending GPIO interrupts.
+	 */
+	GEDR = GEDR;
+
+	return 0;
+}
+
+static void sa1100_gpio_resume(void)
+{
+	GRER = GPIO_IRQ_rising_edge & GPIO_IRQ_mask;
+	GFER = GPIO_IRQ_falling_edge & GPIO_IRQ_mask;
+}
+
+static struct syscore_ops sa1100_gpio_syscore_ops = {
+	.suspend	= sa1100_gpio_suspend,
+	.resume		= sa1100_gpio_resume,
+};
+
+static int __init sa1100_gpio_init_devicefs(void)
+{
+	register_syscore_ops(&sa1100_gpio_syscore_ops);
+	return 0;
+}
+
+device_initcall(sa1100_gpio_init_devicefs);
+
 void __init sa1100_init_gpio(void)
 {
+	/* clear all GPIO edge detects */
+	GFER = 0;
+	GRER = 0;
+	GEDR = -1;
+
 	gpiochip_add(&sa1100_gpio_chip);
+
+	sa1100_gpio_irqdomain = irq_domain_add_simple(NULL,
+			28, IRQ_GPIO0,
+			&sa1100_gpio_irqdomain_ops, NULL);
+
+	/*
+	 * Install handlers for GPIO 0-10 edge detect interrupts
+	 */
+	irq_set_chained_handler(IRQ_GPIO0_SC, sa1100_gpio_handler);
+	irq_set_chained_handler(IRQ_GPIO1_SC, sa1100_gpio_handler);
+	irq_set_chained_handler(IRQ_GPIO2_SC, sa1100_gpio_handler);
+	irq_set_chained_handler(IRQ_GPIO3_SC, sa1100_gpio_handler);
+	irq_set_chained_handler(IRQ_GPIO4_SC, sa1100_gpio_handler);
+	irq_set_chained_handler(IRQ_GPIO5_SC, sa1100_gpio_handler);
+	irq_set_chained_handler(IRQ_GPIO6_SC, sa1100_gpio_handler);
+	irq_set_chained_handler(IRQ_GPIO7_SC, sa1100_gpio_handler);
+	irq_set_chained_handler(IRQ_GPIO8_SC, sa1100_gpio_handler);
+	irq_set_chained_handler(IRQ_GPIO9_SC, sa1100_gpio_handler);
+	irq_set_chained_handler(IRQ_GPIO10_SC, sa1100_gpio_handler);
+	/*
+	 * Install handler for GPIO 11-27 edge detect interrupts
+	 */
+	irq_set_chained_handler(IRQ_GPIO11_27, sa1100_gpio_handler);
+
 }
-- 
2.1.3


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 5/5] ARM: sa1100: use handle_domain_irq
  2014-12-22 10:05 [PATCH 1/5] ARM: sa1100: split irq handling for low GPIOs Dmitry Eremin-Solenikov
                   ` (2 preceding siblings ...)
  2014-12-22 10:05 ` [PATCH 4/5] ARM: sa1100: move GPIO-related IRQ code to gpio driver Dmitry Eremin-Solenikov
@ 2014-12-22 10:05 ` Dmitry Eremin-Solenikov
  2015-01-14  9:35 ` [PATCH 1/5] ARM: sa1100: split irq handling for low GPIOs Linus Walleij
  4 siblings, 0 replies; 7+ messages in thread
From: Dmitry Eremin-Solenikov @ 2014-12-22 10:05 UTC (permalink / raw)
  To: Russell King, Linus Walleij
  Cc: Alexandre Courbot, linux-arm-kernel, linux-gpio

Use handle_domain_irq instead of handle_IRQ to automatically map
hardware irq number to virq.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
---
 arch/arm/mach-sa1100/irq.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-sa1100/irq.c b/arch/arm/mach-sa1100/irq.c
index a7d116a..65aebfa 100644
--- a/arch/arm/mach-sa1100/irq.c
+++ b/arch/arm/mach-sa1100/irq.c
@@ -147,7 +147,8 @@ sa1100_handle_irq(struct pt_regs *regs)
 		if (mask == 0)
 			break;
 
-		handle_IRQ(ffs(mask) - 1 + IRQ_GPIO0_SC, regs);
+		handle_domain_irq(sa1100_normal_irqdomain,
+				ffs(mask) - 1, regs);
 	} while (1);
 }
 
-- 
2.1.3


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/5] ARM: sa1100: split irq handling for low GPIOs
  2014-12-22 10:05 [PATCH 1/5] ARM: sa1100: split irq handling for low GPIOs Dmitry Eremin-Solenikov
                   ` (3 preceding siblings ...)
  2014-12-22 10:05 ` [PATCH 5/5] ARM: sa1100: use handle_domain_irq Dmitry Eremin-Solenikov
@ 2015-01-14  9:35 ` Linus Walleij
  2015-01-14  9:36   ` Dmitry Eremin-Solenikov
  4 siblings, 1 reply; 7+ messages in thread
From: Linus Walleij @ 2015-01-14  9:35 UTC (permalink / raw)
  To: Dmitry Eremin-Solenikov
  Cc: Russell King, Alexandre Courbot,
	linux-arm-kernel@lists.infradead.org, linux-gpio@vger.kernel.org

On Mon, Dec 22, 2014 at 11:05 AM, Dmitry Eremin-Solenikov
<dbaryshkov@gmail.com> wrote:

> Low GPIO pins use an interrupt in SC interrupts space. However it's
> possible to handle them as if all the GPIO interrupts are instead tied
> to single GPIO handler, which later decodes GEDR register and
> chain-calls next IRQ handler. So split first 11 interrupts into system
> part (IRQ_GPIO0_SC - IRQ_GPIO10_SC) which work exactly like the rest of
> system controller interrupts and real GPIO interrupts
> (IRQ_GPIO0..IRQ_GPIO10). A single handler sa1100_gpio_handler then
> decodes and calls next handler.
>
> Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>

I applied all 5 patches and tested on the Compaq iPAQ H3600
with some GPIO lines with IRQs and all work as before.

Tested-by: Linus Walleij <linus.walleij@linaro.org>
for all 5 patches.

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/5] ARM: sa1100: split irq handling for low GPIOs
  2015-01-14  9:35 ` [PATCH 1/5] ARM: sa1100: split irq handling for low GPIOs Linus Walleij
@ 2015-01-14  9:36   ` Dmitry Eremin-Solenikov
  0 siblings, 0 replies; 7+ messages in thread
From: Dmitry Eremin-Solenikov @ 2015-01-14  9:36 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Russell King, Alexandre Courbot,
	linux-arm-kernel@lists.infradead.org, linux-gpio@vger.kernel.org

2015-01-14 12:35 GMT+03:00 Linus Walleij <linus.walleij@linaro.org>:
> On Mon, Dec 22, 2014 at 11:05 AM, Dmitry Eremin-Solenikov
> <dbaryshkov@gmail.com> wrote:
>
>> Low GPIO pins use an interrupt in SC interrupts space. However it's
>> possible to handle them as if all the GPIO interrupts are instead tied
>> to single GPIO handler, which later decodes GEDR register and
>> chain-calls next IRQ handler. So split first 11 interrupts into system
>> part (IRQ_GPIO0_SC - IRQ_GPIO10_SC) which work exactly like the rest of
>> system controller interrupts and real GPIO interrupts
>> (IRQ_GPIO0..IRQ_GPIO10). A single handler sa1100_gpio_handler then
>> decodes and calls next handler.
>>
>> Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
>
> I applied all 5 patches and tested on the Compaq iPAQ H3600
> with some GPIO lines with IRQs and all work as before.
>
> Tested-by: Linus Walleij <linus.walleij@linaro.org>
> for all 5 patches.

Thank you!

-- 
With best wishes
Dmitry

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2015-01-14  9:36 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-12-22 10:05 [PATCH 1/5] ARM: sa1100: split irq handling for low GPIOs Dmitry Eremin-Solenikov
2014-12-22 10:05 ` [PATCH 2/5] ARM: sa1100: merge both GPIO irqdomains Dmitry Eremin-Solenikov
2014-12-22 10:05 ` [PATCH 3/5] ARM: sa1100: switch to irq_domain_add_simple() Dmitry Eremin-Solenikov
2014-12-22 10:05 ` [PATCH 4/5] ARM: sa1100: move GPIO-related IRQ code to gpio driver Dmitry Eremin-Solenikov
2014-12-22 10:05 ` [PATCH 5/5] ARM: sa1100: use handle_domain_irq Dmitry Eremin-Solenikov
2015-01-14  9:35 ` [PATCH 1/5] ARM: sa1100: split irq handling for low GPIOs Linus Walleij
2015-01-14  9:36   ` Dmitry Eremin-Solenikov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).