* [PATCH v2] ARM: sa1100: improve irq handling
@ 2014-11-25 19:09 Dmitry Eremin-Solenikov
  2014-11-25 19:09 ` [PATCH v2 1/8] ARM: sa1100: switch to MULTI_IRQ_HANDLER Dmitry Eremin-Solenikov
                   ` (8 more replies)
  0 siblings, 9 replies; 10+ messages in thread
From: Dmitry Eremin-Solenikov @ 2014-11-25 19:09 UTC (permalink / raw)
  To: linux-arm-kernel
Hello,
This patch series makes sa1100 platform use MULTI_IRQ_HANDLER and irq
domains to handle interrupts on StrongARM platform. Also virtual irq
numbers are changed to start from 1 rather than 0. It doesn't change
the way how Linux programs the hardware, only software interfaces are
changed.
Changes since v1:
- Start IRQs from 1, freeing IRQ 0
- Merge identical functions in the last patch
- Other minor changes.
^ permalink raw reply	[flat|nested] 10+ messages in thread
* [PATCH v2 1/8] ARM: sa1100: switch to MULTI_IRQ_HANDLER
  2014-11-25 19:09 [PATCH v2] ARM: sa1100: improve irq handling Dmitry Eremin-Solenikov
@ 2014-11-25 19:09 ` Dmitry Eremin-Solenikov
  2014-11-25 19:09 ` [PATCH v2 2/8] ARM: sa1100: drop entry-macro.S Dmitry Eremin-Solenikov
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Dmitry Eremin-Solenikov @ 2014-11-25 19:09 UTC (permalink / raw)
  To: linux-arm-kernel
Add sa1100_handle_irq implementating handle_irq for sa1100 platform.
It is more or less a translation of old assembly code from assembler to
plain C. Also install this irq handler from sa1100_init_irq().
Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
---
 arch/arm/Kconfig           |  1 +
 arch/arm/mach-sa1100/irq.c | 20 ++++++++++++++++++++
 2 files changed, 21 insertions(+)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 89c4b5c..2f3f132 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -703,6 +703,7 @@ config ARCH_SA1100
 	select GENERIC_CLOCKEVENTS
 	select HAVE_IDE
 	select ISA
+	select MULTI_IRQ_HANDLER
 	select NEED_MACH_MEMORY_H
 	select SPARSE_IRQ
 	help
diff --git a/arch/arm/mach-sa1100/irq.c b/arch/arm/mach-sa1100/irq.c
index 2124f1fc..4a1bd5e 100644
--- a/arch/arm/mach-sa1100/irq.c
+++ b/arch/arm/mach-sa1100/irq.c
@@ -20,6 +20,7 @@
 #include <mach/hardware.h>
 #include <mach/irqs.h>
 #include <asm/mach/irq.h>
+#include <asm/exception.h>
 
 #include "generic.h"
 
@@ -291,6 +292,23 @@ static int __init sa1100irq_init_devicefs(void)
 
 device_initcall(sa1100irq_init_devicefs);
 
+static asmlinkage void __exception_irq_entry
+sa1100_handle_irq(struct pt_regs *regs)
+{
+	uint32_t icip, icmr, mask;
+
+	do {
+		icip = (ICIP);
+		icmr = (ICMR);
+		mask = icip & icmr;
+
+		if (mask == 0)
+			break;
+
+		handle_IRQ(ffs(mask) - 1 + IRQ_GPIO0, regs);
+	} while (1);
+}
+
 void __init sa1100_init_irq(void)
 {
 	unsigned int irq;
@@ -338,5 +356,7 @@ void __init sa1100_init_irq(void)
 	irq_set_chip(IRQ_GPIO11_27, &sa1100_normal_chip);
 	irq_set_chained_handler(IRQ_GPIO11_27, sa1100_high_gpio_handler);
 
+	set_handle_irq(sa1100_handle_irq);
+
 	sa1100_init_gpio();
 }
-- 
2.1.3
^ permalink raw reply related	[flat|nested] 10+ messages in thread
* [PATCH v2 2/8] ARM: sa1100: drop entry-macro.S
  2014-11-25 19:09 [PATCH v2] ARM: sa1100: improve irq handling Dmitry Eremin-Solenikov
  2014-11-25 19:09 ` [PATCH v2 1/8] ARM: sa1100: switch to MULTI_IRQ_HANDLER Dmitry Eremin-Solenikov
@ 2014-11-25 19:09 ` Dmitry Eremin-Solenikov
  2014-11-25 19:09 ` [PATCH v2 3/8] ARM: sa1100: replace irq numbers with names in irq driver Dmitry Eremin-Solenikov
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Dmitry Eremin-Solenikov @ 2014-11-25 19:09 UTC (permalink / raw)
  To: linux-arm-kernel
As mach-sa1100 was converted to MULTI_IRQ_HANDLER, drop now-unused
entry-macro.S file.
Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
---
 arch/arm/mach-sa1100/include/mach/entry-macro.S | 41 -------------------------
 1 file changed, 41 deletions(-)
 delete mode 100644 arch/arm/mach-sa1100/include/mach/entry-macro.S
diff --git a/arch/arm/mach-sa1100/include/mach/entry-macro.S b/arch/arm/mach-sa1100/include/mach/entry-macro.S
deleted file mode 100644
index 8cf7630..0000000
--- a/arch/arm/mach-sa1100/include/mach/entry-macro.S
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * arch/arm/mach-sa1100/include/mach/entry-macro.S
- *
- * Low-level IRQ helper macros for SA1100-based platforms
- *
- * This file is licensed under  the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-		.macro  get_irqnr_preamble, base, tmp
-		mov	\base, #0xfa000000		@ ICIP = 0xfa050000
-		add	\base, \base, #0x00050000
-		.endm
-
-		.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
-		ldr	\irqstat, [\base]		@ get irqs
-		ldr	\irqnr, [\base, #4]		@ ICMR = 0xfa050004
-		ands	\irqstat, \irqstat, \irqnr
-		mov	\irqnr, #0
-		beq	1001f
-		tst	\irqstat, #0xff
-		moveq	\irqstat, \irqstat, lsr #8
-		addeq	\irqnr, \irqnr, #8
-		tsteq	\irqstat, #0xff
-		moveq	\irqstat, \irqstat, lsr #8
-		addeq	\irqnr, \irqnr, #8
-		tsteq	\irqstat, #0xff
-		moveq	\irqstat, \irqstat, lsr #8
-		addeq	\irqnr, \irqnr, #8
-		tst	\irqstat, #0x0f
-		moveq	\irqstat, \irqstat, lsr #4
-		addeq	\irqnr, \irqnr, #4
-		tst	\irqstat, #0x03
-		moveq	\irqstat, \irqstat, lsr #2
-		addeq	\irqnr, \irqnr, #2
-		tst	\irqstat, #0x01
-		addeqs	\irqnr, \irqnr, #1
-1001:
-		.endm
-
-- 
2.1.3
^ permalink raw reply related	[flat|nested] 10+ messages in thread
* [PATCH v2 3/8] ARM: sa1100: replace irq numbers with names in irq driver
  2014-11-25 19:09 [PATCH v2] ARM: sa1100: improve irq handling Dmitry Eremin-Solenikov
  2014-11-25 19:09 ` [PATCH v2 1/8] ARM: sa1100: switch to MULTI_IRQ_HANDLER Dmitry Eremin-Solenikov
  2014-11-25 19:09 ` [PATCH v2 2/8] ARM: sa1100: drop entry-macro.S Dmitry Eremin-Solenikov
@ 2014-11-25 19:09 ` Dmitry Eremin-Solenikov
  2014-11-25 19:09 ` [PATCH v2 4/8] ARM: sa1100: shift IRQs by one Dmitry Eremin-Solenikov
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Dmitry Eremin-Solenikov @ 2014-11-25 19:09 UTC (permalink / raw)
  To: linux-arm-kernel
In preparation for further changes replace direct IRQ numbers with
pre-defined names. This imposes no real code changes.
Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
---
 arch/arm/mach-sa1100/irq.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/arch/arm/mach-sa1100/irq.c b/arch/arm/mach-sa1100/irq.c
index 4a1bd5e..0b29d27 100644
--- a/arch/arm/mach-sa1100/irq.c
+++ b/arch/arm/mach-sa1100/irq.c
@@ -37,14 +37,14 @@ static int GPIO_IRQ_mask = (1 << 11) - 1;
 /*
  * To get the GPIO number from an IRQ number
  */
-#define GPIO_11_27_IRQ(i)	((i) - 21)
+#define GPIO_11_27_IRQ(i)	((i) + 11 - IRQ_GPIO11)
 #define GPIO11_27_MASK(irq)	(1 << GPIO_11_27_IRQ(irq))
 
 static int sa1100_gpio_type(struct irq_data *d, unsigned int type)
 {
 	unsigned int mask;
 
-	if (d->irq <= 10)
+	if (d->irq <= IRQ_GPIO10)
 		mask = 1 << d->irq;
 	else
 		mask = GPIO11_27_MASK(d->irq);
@@ -71,7 +71,7 @@ static int sa1100_gpio_type(struct irq_data *d, unsigned int type)
 }
 
 /*
- * GPIO IRQs must be acknowledged.  This is for IRQs from 0 to 10.
+ * GPIO IRQs must be acknowledged.  This is for IRQs from GPIO0 to 10.
  */
 static void sa1100_low_gpio_ack(struct irq_data *d)
 {
@@ -189,7 +189,7 @@ static struct irq_chip sa1100_high_gpio_chip = {
 
 /*
  * We don't need to ACK IRQs on the SA1100 unless they're GPIOs
- * this is for internal IRQs i.e. from 11 to 31.
+ * this is for internal IRQs i.e. from IRQ LCD to RTCAlrm.
  */
 static void sa1100_mask_irq(struct irq_data *d)
 {
@@ -332,19 +332,19 @@ void __init sa1100_init_irq(void)
 	 */
 	ICCR = 1;
 
-	for (irq = 0; irq <= 10; irq++) {
+	for (irq = IRQ_GPIO0; irq <= IRQ_GPIO10; irq++) {
 		irq_set_chip_and_handler(irq, &sa1100_low_gpio_chip,
 					 handle_edge_irq);
 		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
 	}
 
-	for (irq = 12; irq <= 31; irq++) {
+	for (irq = IRQ_LCD; irq <= IRQ_RTCAlrm; irq++) {
 		irq_set_chip_and_handler(irq, &sa1100_normal_chip,
 					 handle_level_irq);
 		set_irq_flags(irq, IRQF_VALID);
 	}
 
-	for (irq = 32; irq <= 48; irq++) {
+	for (irq = IRQ_GPIO11; irq <= IRQ_GPIO27; irq++) {
 		irq_set_chip_and_handler(irq, &sa1100_high_gpio_chip,
 					 handle_edge_irq);
 		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
-- 
2.1.3
^ permalink raw reply related	[flat|nested] 10+ messages in thread
* [PATCH v2 4/8] ARM: sa1100: shift IRQs by one
  2014-11-25 19:09 [PATCH v2] ARM: sa1100: improve irq handling Dmitry Eremin-Solenikov
                   ` (2 preceding siblings ...)
  2014-11-25 19:09 ` [PATCH v2 3/8] ARM: sa1100: replace irq numbers with names in irq driver Dmitry Eremin-Solenikov
@ 2014-11-25 19:09 ` Dmitry Eremin-Solenikov
  2014-11-25 19:09 ` [PATCH v2 5/8] ARM: sa1100: introduce irqdomains support Dmitry Eremin-Solenikov
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Dmitry Eremin-Solenikov @ 2014-11-25 19:09 UTC (permalink / raw)
  To: linux-arm-kernel
As IRQ0 should not be used (especially in when using irq domains), shift all
virtual IRQ numbers by one.
Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
---
 arch/arm/mach-sa1100/include/mach/irqs.h | 102 +++++++++++++++----------------
 1 file changed, 51 insertions(+), 51 deletions(-)
diff --git a/arch/arm/mach-sa1100/include/mach/irqs.h b/arch/arm/mach-sa1100/include/mach/irqs.h
index 3790298..de09834 100644
--- a/arch/arm/mach-sa1100/include/mach/irqs.h
+++ b/arch/arm/mach-sa1100/include/mach/irqs.h
@@ -8,56 +8,56 @@
  * 2001/11/14	RMK	Cleaned up and standardised a lot of the IRQs.
  */
 
-#define	IRQ_GPIO0		0
-#define	IRQ_GPIO1		1
-#define	IRQ_GPIO2		2
-#define	IRQ_GPIO3		3
-#define	IRQ_GPIO4		4
-#define	IRQ_GPIO5		5
-#define	IRQ_GPIO6		6
-#define	IRQ_GPIO7		7
-#define	IRQ_GPIO8		8
-#define	IRQ_GPIO9		9
-#define	IRQ_GPIO10		10
-#define	IRQ_GPIO11_27		11
-#define	IRQ_LCD  		12	/* LCD controller           */
-#define	IRQ_Ser0UDC		13	/* Ser. port 0 UDC          */
-#define	IRQ_Ser1SDLC		14	/* Ser. port 1 SDLC         */
-#define	IRQ_Ser1UART		15	/* Ser. port 1 UART         */
-#define	IRQ_Ser2ICP		16	/* Ser. port 2 ICP          */
-#define	IRQ_Ser3UART		17	/* Ser. port 3 UART         */
-#define	IRQ_Ser4MCP		18	/* Ser. port 4 MCP          */
-#define	IRQ_Ser4SSP		19	/* Ser. port 4 SSP          */
-#define	IRQ_DMA0 		20	/* DMA controller channel 0 */
-#define	IRQ_DMA1 		21	/* DMA controller channel 1 */
-#define	IRQ_DMA2 		22	/* DMA controller channel 2 */
-#define	IRQ_DMA3 		23	/* DMA controller channel 3 */
-#define	IRQ_DMA4 		24	/* DMA controller channel 4 */
-#define	IRQ_DMA5 		25	/* DMA controller channel 5 */
-#define	IRQ_OST0 		26	/* OS Timer match 0         */
-#define	IRQ_OST1 		27	/* OS Timer match 1         */
-#define	IRQ_OST2 		28	/* OS Timer match 2         */
-#define	IRQ_OST3 		29	/* OS Timer match 3         */
-#define	IRQ_RTC1Hz		30	/* RTC 1 Hz clock           */
-#define	IRQ_RTCAlrm		31	/* RTC Alarm                */
+#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_GPIO11_27		12
+#define	IRQ_LCD			13	/* LCD controller           */
+#define	IRQ_Ser0UDC		14	/* Ser. port 0 UDC          */
+#define	IRQ_Ser1SDLC		15	/* Ser. port 1 SDLC         */
+#define	IRQ_Ser1UART		16	/* Ser. port 1 UART         */
+#define	IRQ_Ser2ICP		17	/* Ser. port 2 ICP          */
+#define	IRQ_Ser3UART		18	/* Ser. port 3 UART         */
+#define	IRQ_Ser4MCP		19	/* Ser. port 4 MCP          */
+#define	IRQ_Ser4SSP		20	/* Ser. port 4 SSP          */
+#define	IRQ_DMA0		21	/* DMA controller channel 0 */
+#define	IRQ_DMA1		22	/* DMA controller channel 1 */
+#define	IRQ_DMA2		23	/* DMA controller channel 2 */
+#define	IRQ_DMA3		24	/* DMA controller channel 3 */
+#define	IRQ_DMA4		25	/* DMA controller channel 4 */
+#define	IRQ_DMA5		26	/* DMA controller channel 5 */
+#define	IRQ_OST0		27	/* OS Timer match 0         */
+#define	IRQ_OST1		28	/* OS Timer match 1         */
+#define	IRQ_OST2		29	/* OS Timer match 2         */
+#define	IRQ_OST3		30	/* OS Timer match 3         */
+#define	IRQ_RTC1Hz		31	/* RTC 1 Hz clock           */
+#define	IRQ_RTCAlrm		32	/* RTC Alarm                */
 
-#define	IRQ_GPIO11		32
-#define	IRQ_GPIO12		33
-#define	IRQ_GPIO13		34
-#define	IRQ_GPIO14		35
-#define	IRQ_GPIO15		36
-#define	IRQ_GPIO16		37
-#define	IRQ_GPIO17		38
-#define	IRQ_GPIO18		39
-#define	IRQ_GPIO19		40
-#define	IRQ_GPIO20		41
-#define	IRQ_GPIO21		42
-#define	IRQ_GPIO22		43
-#define	IRQ_GPIO23		44
-#define	IRQ_GPIO24		45
-#define	IRQ_GPIO25		46
-#define	IRQ_GPIO26		47
-#define	IRQ_GPIO27		48
+#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
 
 /*
  * The next 16 interrupts are for board specific purposes.  Since
@@ -65,8 +65,8 @@
  * these.  If you need more, increase IRQ_BOARD_END, but keep it
  * within sensible limits.  IRQs 49 to 64 are available.
  */
-#define IRQ_BOARD_START		49
-#define IRQ_BOARD_END		65
+#define IRQ_BOARD_START		50
+#define IRQ_BOARD_END		66
 
 /*
  * Figure out the MAX IRQ number.
-- 
2.1.3
^ permalink raw reply related	[flat|nested] 10+ messages in thread
* [PATCH v2 5/8] ARM: sa1100: introduce irqdomains support
  2014-11-25 19:09 [PATCH v2] ARM: sa1100: improve irq handling Dmitry Eremin-Solenikov
                   ` (3 preceding siblings ...)
  2014-11-25 19:09 ` [PATCH v2 4/8] ARM: sa1100: shift IRQs by one Dmitry Eremin-Solenikov
@ 2014-11-25 19:09 ` Dmitry Eremin-Solenikov
  2014-11-25 19:09 ` [PATCH v2 6/8] ARM: sa1100: merge GPIO multiplexer IRQ to "normal" irq domain Dmitry Eremin-Solenikov
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Dmitry Eremin-Solenikov @ 2014-11-25 19:09 UTC (permalink / raw)
  To: linux-arm-kernel
Use irqdomains to manage both system and GPIO interrupts on SA1100 SoC
family. This opens path to further cleanup and unification in sa1100 IRQ
drivers.
Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
---
 arch/arm/Kconfig           |  1 +
 arch/arm/mach-sa1100/irq.c | 78 ++++++++++++++++++++++++++++++++++++----------
 2 files changed, 62 insertions(+), 17 deletions(-)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 2f3f132..622e364 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -702,6 +702,7 @@ config ARCH_SA1100
 	select CPU_SA1100
 	select GENERIC_CLOCKEVENTS
 	select HAVE_IDE
+	select IRQ_DOMAIN
 	select ISA
 	select MULTI_IRQ_HANDLER
 	select NEED_MACH_MEMORY_H
diff --git a/arch/arm/mach-sa1100/irq.c b/arch/arm/mach-sa1100/irq.c
index 0b29d27..2d8be03 100644
--- a/arch/arm/mach-sa1100/irq.c
+++ b/arch/arm/mach-sa1100/irq.c
@@ -14,6 +14,7 @@
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/irq.h>
+#include <linux/irqdomain.h>
 #include <linux/ioport.h>
 #include <linux/syscore_ops.h>
 
@@ -106,6 +107,23 @@ static struct irq_chip sa1100_low_gpio_chip = {
 	.irq_set_wake	= sa1100_low_gpio_wake,
 };
 
+static int sa1100_low_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,
+				 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,
+	.xlate = irq_domain_xlate_onetwocell,
+};
+
+static struct irq_domain *sa1100_low_gpio_irqdomain;
+
 /*
  * IRQ11 (GPIO11 through 27) handler.  We enter here with the
  * irq_controller_lock held, and IRQs disabled.  Decode the IRQ
@@ -187,6 +205,23 @@ static struct irq_chip sa1100_high_gpio_chip = {
 	.irq_set_wake	= sa1100_high_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;
+
 /*
  * We don't need to ACK IRQs on the SA1100 unless they're GPIOs
  * this is for internal IRQs i.e. from IRQ LCD to RTCAlrm.
@@ -224,6 +259,23 @@ static struct irq_chip sa1100_normal_chip = {
 	.irq_set_wake	= sa1100_set_wake,
 };
 
+static int sa1100_normal_irqdomain_map(struct irq_domain *d,
+		unsigned int irq, irq_hw_number_t hwirq)
+{
+	irq_set_chip_and_handler(irq, &sa1100_normal_chip,
+				 handle_level_irq);
+	set_irq_flags(irq, IRQF_VALID);
+
+	return 0;
+}
+
+static struct irq_domain_ops sa1100_normal_irqdomain_ops = {
+	.map = sa1100_normal_irqdomain_map,
+	.xlate = irq_domain_xlate_onetwocell,
+};
+
+static struct irq_domain *sa1100_normal_irqdomain;
+
 static struct resource irq_resource =
 	DEFINE_RES_MEM_NAMED(0x90050000, SZ_64K, "irqs");
 
@@ -311,8 +363,6 @@ sa1100_handle_irq(struct pt_regs *regs)
 
 void __init sa1100_init_irq(void)
 {
-	unsigned int irq;
-
 	request_resource(&iomem_resource, &irq_resource);
 
 	/* disable all IRQs */
@@ -332,23 +382,17 @@ void __init sa1100_init_irq(void)
 	 */
 	ICCR = 1;
 
-	for (irq = IRQ_GPIO0; irq <= IRQ_GPIO10; irq++) {
-		irq_set_chip_and_handler(irq, &sa1100_low_gpio_chip,
-					 handle_edge_irq);
-		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
-	}
+	sa1100_low_gpio_irqdomain = irq_domain_add_legacy(NULL,
+			11, IRQ_GPIO0, 0,
+			&sa1100_low_gpio_irqdomain_ops, NULL);
 
-	for (irq = IRQ_LCD; irq <= IRQ_RTCAlrm; irq++) {
-		irq_set_chip_and_handler(irq, &sa1100_normal_chip,
-					 handle_level_irq);
-		set_irq_flags(irq, IRQF_VALID);
-	}
+	sa1100_normal_irqdomain = irq_domain_add_legacy(NULL,
+			20, IRQ_LCD, 12,
+			&sa1100_normal_irqdomain_ops, NULL);
 
-	for (irq = IRQ_GPIO11; irq <= IRQ_GPIO27; irq++) {
-		irq_set_chip_and_handler(irq, &sa1100_high_gpio_chip,
-					 handle_edge_irq);
-		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
-	}
+	sa1100_high_gpio_irqdomain = irq_domain_add_legacy(NULL,
+			17, IRQ_GPIO11, 11,
+			&sa1100_high_gpio_irqdomain_ops, NULL);
 
 	/*
 	 * Install handler for GPIO 11-27 edge detect interrupts
-- 
2.1.3
^ permalink raw reply related	[flat|nested] 10+ messages in thread
* [PATCH v2 6/8] ARM: sa1100: merge GPIO multiplexer IRQ to "normal" irq domain
  2014-11-25 19:09 [PATCH v2] ARM: sa1100: improve irq handling Dmitry Eremin-Solenikov
                   ` (4 preceding siblings ...)
  2014-11-25 19:09 ` [PATCH v2 5/8] ARM: sa1100: introduce irqdomains support Dmitry Eremin-Solenikov
@ 2014-11-25 19:09 ` Dmitry Eremin-Solenikov
  2014-11-25 19:09 ` [PATCH v2 7/8] ARM: sa1100: switch to hwirq usage Dmitry Eremin-Solenikov
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Dmitry Eremin-Solenikov @ 2014-11-25 19:09 UTC (permalink / raw)
  To: linux-arm-kernel
IRQ_GPIO11_27 is a shared IRQ receiving IRQs from "high" GPIOs. It is
still handled by sa1100_normal_chip, so there is no point to exclude it
from "normal" irq domain. The IRQF_VALID flag set by domain map function
will be cleared by irq_set_chained_handler() internally.
Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
---
 arch/arm/mach-sa1100/irq.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/arch/arm/mach-sa1100/irq.c b/arch/arm/mach-sa1100/irq.c
index 2d8be03..14a7633e 100644
--- a/arch/arm/mach-sa1100/irq.c
+++ b/arch/arm/mach-sa1100/irq.c
@@ -387,7 +387,7 @@ void __init sa1100_init_irq(void)
 			&sa1100_low_gpio_irqdomain_ops, NULL);
 
 	sa1100_normal_irqdomain = irq_domain_add_legacy(NULL,
-			20, IRQ_LCD, 12,
+			21, IRQ_GPIO11_27, 11,
 			&sa1100_normal_irqdomain_ops, NULL);
 
 	sa1100_high_gpio_irqdomain = irq_domain_add_legacy(NULL,
@@ -397,7 +397,6 @@ void __init sa1100_init_irq(void)
 	/*
 	 * Install handler for GPIO 11-27 edge detect interrupts
 	 */
-	irq_set_chip(IRQ_GPIO11_27, &sa1100_normal_chip);
 	irq_set_chained_handler(IRQ_GPIO11_27, sa1100_high_gpio_handler);
 
 	set_handle_irq(sa1100_handle_irq);
-- 
2.1.3
^ permalink raw reply related	[flat|nested] 10+ messages in thread
* [PATCH v2 7/8] ARM: sa1100: switch to hwirq usage
  2014-11-25 19:09 [PATCH v2] ARM: sa1100: improve irq handling Dmitry Eremin-Solenikov
                   ` (5 preceding siblings ...)
  2014-11-25 19:09 ` [PATCH v2 6/8] ARM: sa1100: merge GPIO multiplexer IRQ to "normal" irq domain Dmitry Eremin-Solenikov
@ 2014-11-25 19:09 ` Dmitry Eremin-Solenikov
  2014-11-25 19:09 ` [PATCH v2 8/8] ARM: sa1100: reorder IRQ handling code Dmitry Eremin-Solenikov
  2014-11-26 12:47 ` [PATCH v2] ARM: sa1100: improve irq handling Linus Walleij
  8 siblings, 0 replies; 10+ messages in thread
From: Dmitry Eremin-Solenikov @ 2014-11-25 19:09 UTC (permalink / raw)
  To: linux-arm-kernel
Switch internally to using hardware irq numbers (hwirq). In case of GPIO
interrupts, hwirq is equal to GPIO number. In case of system interrupts,
hwirq is equal to interrupt number in the interrupt controller.
Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
---
 arch/arm/mach-sa1100/irq.c | 37 ++++++++++++++-----------------------
 1 file changed, 14 insertions(+), 23 deletions(-)
diff --git a/arch/arm/mach-sa1100/irq.c b/arch/arm/mach-sa1100/irq.c
index 14a7633e..981db98 100644
--- a/arch/arm/mach-sa1100/irq.c
+++ b/arch/arm/mach-sa1100/irq.c
@@ -35,20 +35,11 @@ static int GPIO_IRQ_rising_edge;
 static int GPIO_IRQ_falling_edge;
 static int GPIO_IRQ_mask = (1 << 11) - 1;
 
-/*
- * To get the GPIO number from an IRQ number
- */
-#define GPIO_11_27_IRQ(i)	((i) + 11 - IRQ_GPIO11)
-#define GPIO11_27_MASK(irq)	(1 << GPIO_11_27_IRQ(irq))
-
 static int sa1100_gpio_type(struct irq_data *d, unsigned int type)
 {
 	unsigned int mask;
 
-	if (d->irq <= IRQ_GPIO10)
-		mask = 1 << d->irq;
-	else
-		mask = GPIO11_27_MASK(d->irq);
+	mask = BIT(d->hwirq);
 
 	if (type == IRQ_TYPE_PROBE) {
 		if ((GPIO_IRQ_rising_edge | GPIO_IRQ_falling_edge) & mask)
@@ -76,25 +67,25 @@ 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);
+	GEDR = BIT(d->hwirq);
 }
 
 static void sa1100_low_gpio_mask(struct irq_data *d)
 {
-	ICMR &= ~(1 << d->irq);
+	ICMR &= ~BIT(d->hwirq);
 }
 
 static void sa1100_low_gpio_unmask(struct irq_data *d)
 {
-	ICMR |= 1 << d->irq;
+	ICMR |= BIT(d->hwirq);
 }
 
 static int sa1100_low_gpio_wake(struct irq_data *d, unsigned int on)
 {
 	if (on)
-		PWER |= 1 << d->irq;
+		PWER |= BIT(d->hwirq);
 	else
-		PWER &= ~(1 << d->irq);
+		PWER &= ~BIT(d->hwirq);
 	return 0;
 }
 
@@ -162,14 +153,14 @@ sa1100_high_gpio_handler(unsigned int irq, struct irq_desc *desc)
  */
 static void sa1100_high_gpio_ack(struct irq_data *d)
 {
-	unsigned int mask = GPIO11_27_MASK(d->irq);
+	unsigned int mask = BIT(d->hwirq);
 
 	GEDR = mask;
 }
 
 static void sa1100_high_gpio_mask(struct irq_data *d)
 {
-	unsigned int mask = GPIO11_27_MASK(d->irq);
+	unsigned int mask = BIT(d->hwirq);
 
 	GPIO_IRQ_mask &= ~mask;
 
@@ -179,7 +170,7 @@ static void sa1100_high_gpio_mask(struct irq_data *d)
 
 static void sa1100_high_gpio_unmask(struct irq_data *d)
 {
-	unsigned int mask = GPIO11_27_MASK(d->irq);
+	unsigned int mask = BIT(d->hwirq);
 
 	GPIO_IRQ_mask |= mask;
 
@@ -190,9 +181,9 @@ static void sa1100_high_gpio_unmask(struct irq_data *d)
 static int sa1100_high_gpio_wake(struct irq_data *d, unsigned int on)
 {
 	if (on)
-		PWER |= GPIO11_27_MASK(d->irq);
+		PWER |= BIT(d->hwirq);
 	else
-		PWER &= ~GPIO11_27_MASK(d->irq);
+		PWER &= ~BIT(d->hwirq);
 	return 0;
 }
 
@@ -228,12 +219,12 @@ static struct irq_domain *sa1100_high_gpio_irqdomain;
  */
 static void sa1100_mask_irq(struct irq_data *d)
 {
-	ICMR &= ~(1 << d->irq);
+	ICMR &= ~BIT(d->hwirq);
 }
 
 static void sa1100_unmask_irq(struct irq_data *d)
 {
-	ICMR |= (1 << d->irq);
+	ICMR |= BIT(d->hwirq);
 }
 
 /*
@@ -241,7 +232,7 @@ static void sa1100_unmask_irq(struct irq_data *d)
  */
 static int sa1100_set_wake(struct irq_data *d, unsigned int on)
 {
-	if (d->irq == IRQ_RTCAlrm) {
+	if (BIT(d->hwirq) == IC_RTCAlrm) {
 		if (on)
 			PWER |= PWER_RTC;
 		else
-- 
2.1.3
^ permalink raw reply related	[flat|nested] 10+ messages in thread
* [PATCH v2 8/8] ARM: sa1100: reorder IRQ handling code
  2014-11-25 19:09 [PATCH v2] ARM: sa1100: improve irq handling Dmitry Eremin-Solenikov
                   ` (6 preceding siblings ...)
  2014-11-25 19:09 ` [PATCH v2 7/8] ARM: sa1100: switch to hwirq usage Dmitry Eremin-Solenikov
@ 2014-11-25 19:09 ` Dmitry Eremin-Solenikov
  2014-11-26 12:47 ` [PATCH v2] ARM: sa1100: improve irq handling Linus Walleij
  8 siblings, 0 replies; 10+ messages in thread
From: Dmitry Eremin-Solenikov @ 2014-11-25 19:09 UTC (permalink / raw)
  To: linux-arm-kernel
This patch just reorders functions/data inside sa1100 irq driver to be
able to merge functions that have the same code after converting to
irqdomains and hwirq. No real code changes.
Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
---
 arch/arm/mach-sa1100/irq.c | 155 +++++++++++++++++++--------------------------
 1 file changed, 66 insertions(+), 89 deletions(-)
diff --git a/arch/arm/mach-sa1100/irq.c b/arch/arm/mach-sa1100/irq.c
index 981db98..63e2901 100644
--- a/arch/arm/mach-sa1100/irq.c
+++ b/arch/arm/mach-sa1100/irq.c
@@ -27,6 +27,60 @@
 
 
 /*
+ * We don't need to ACK IRQs on the SA1100 unless they're GPIOs
+ * this is for internal IRQs i.e. from IRQ LCD to RTCAlrm.
+ */
+static void sa1100_mask_irq(struct irq_data *d)
+{
+	ICMR &= ~BIT(d->hwirq);
+}
+
+static void sa1100_unmask_irq(struct irq_data *d)
+{
+	ICMR |= BIT(d->hwirq);
+}
+
+/*
+ * Apart form GPIOs, only the RTC alarm can be a wakeup event.
+ */
+static int sa1100_set_wake(struct irq_data *d, unsigned int on)
+{
+	if (BIT(d->hwirq) == IC_RTCAlrm) {
+		if (on)
+			PWER |= PWER_RTC;
+		else
+			PWER &= ~PWER_RTC;
+		return 0;
+	}
+	return -EINVAL;
+}
+
+static struct irq_chip sa1100_normal_chip = {
+	.name		= "SC",
+	.irq_ack	= sa1100_mask_irq,
+	.irq_mask	= sa1100_mask_irq,
+	.irq_unmask	= sa1100_unmask_irq,
+	.irq_set_wake	= sa1100_set_wake,
+};
+
+static int sa1100_normal_irqdomain_map(struct irq_domain *d,
+		unsigned int irq, irq_hw_number_t hwirq)
+{
+	irq_set_chip_and_handler(irq, &sa1100_normal_chip,
+				 handle_level_irq);
+	set_irq_flags(irq, IRQF_VALID);
+
+	return 0;
+}
+
+static struct irq_domain_ops sa1100_normal_irqdomain_ops = {
+	.map = sa1100_normal_irqdomain_map,
+	.xlate = irq_domain_xlate_onetwocell,
+};
+
+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.
@@ -63,24 +117,14 @@ static int sa1100_gpio_type(struct irq_data *d, unsigned int type)
 }
 
 /*
- * GPIO IRQs must be acknowledged.  This is for IRQs from GPIO0 to 10.
+ * GPIO IRQs must be acknowledged.
  */
-static void sa1100_low_gpio_ack(struct irq_data *d)
+static void sa1100_gpio_ack(struct irq_data *d)
 {
 	GEDR = BIT(d->hwirq);
 }
 
-static void sa1100_low_gpio_mask(struct irq_data *d)
-{
-	ICMR &= ~BIT(d->hwirq);
-}
-
-static void sa1100_low_gpio_unmask(struct irq_data *d)
-{
-	ICMR |= BIT(d->hwirq);
-}
-
-static int sa1100_low_gpio_wake(struct irq_data *d, unsigned int on)
+static int sa1100_gpio_wake(struct irq_data *d, unsigned int on)
 {
 	if (on)
 		PWER |= BIT(d->hwirq);
@@ -89,13 +133,16 @@ static int sa1100_low_gpio_wake(struct irq_data *d, unsigned int on)
 	return 0;
 }
 
+/*
+ * This is for IRQs from 0 to 10.
+ */
 static struct irq_chip sa1100_low_gpio_chip = {
 	.name		= "GPIO-l",
-	.irq_ack	= sa1100_low_gpio_ack,
-	.irq_mask	= sa1100_low_gpio_mask,
-	.irq_unmask	= sa1100_low_gpio_unmask,
+	.irq_ack	= sa1100_gpio_ack,
+	.irq_mask	= sa1100_mask_irq,
+	.irq_unmask	= sa1100_unmask_irq,
 	.irq_set_type	= sa1100_gpio_type,
-	.irq_set_wake	= sa1100_low_gpio_wake,
+	.irq_set_wake	= sa1100_gpio_wake,
 };
 
 static int sa1100_low_gpio_irqdomain_map(struct irq_domain *d,
@@ -151,13 +198,6 @@ 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_ack(struct irq_data *d)
-{
-	unsigned int mask = BIT(d->hwirq);
-
-	GEDR = mask;
-}
-
 static void sa1100_high_gpio_mask(struct irq_data *d)
 {
 	unsigned int mask = BIT(d->hwirq);
@@ -178,22 +218,13 @@ static void sa1100_high_gpio_unmask(struct irq_data *d)
 	GFER = GPIO_IRQ_falling_edge & GPIO_IRQ_mask;
 }
 
-static int sa1100_high_gpio_wake(struct irq_data *d, unsigned int on)
-{
-	if (on)
-		PWER |= BIT(d->hwirq);
-	else
-		PWER &= ~BIT(d->hwirq);
-	return 0;
-}
-
 static struct irq_chip sa1100_high_gpio_chip = {
 	.name		= "GPIO-h",
-	.irq_ack	= sa1100_high_gpio_ack,
+	.irq_ack	= sa1100_gpio_ack,
 	.irq_mask	= sa1100_high_gpio_mask,
 	.irq_unmask	= sa1100_high_gpio_unmask,
 	.irq_set_type	= sa1100_gpio_type,
-	.irq_set_wake	= sa1100_high_gpio_wake,
+	.irq_set_wake	= sa1100_gpio_wake,
 };
 
 static int sa1100_high_gpio_irqdomain_map(struct irq_domain *d,
@@ -213,60 +244,6 @@ static struct irq_domain_ops sa1100_high_gpio_irqdomain_ops = {
 
 static struct irq_domain *sa1100_high_gpio_irqdomain;
 
-/*
- * We don't need to ACK IRQs on the SA1100 unless they're GPIOs
- * this is for internal IRQs i.e. from IRQ LCD to RTCAlrm.
- */
-static void sa1100_mask_irq(struct irq_data *d)
-{
-	ICMR &= ~BIT(d->hwirq);
-}
-
-static void sa1100_unmask_irq(struct irq_data *d)
-{
-	ICMR |= BIT(d->hwirq);
-}
-
-/*
- * Apart form GPIOs, only the RTC alarm can be a wakeup event.
- */
-static int sa1100_set_wake(struct irq_data *d, unsigned int on)
-{
-	if (BIT(d->hwirq) == IC_RTCAlrm) {
-		if (on)
-			PWER |= PWER_RTC;
-		else
-			PWER &= ~PWER_RTC;
-		return 0;
-	}
-	return -EINVAL;
-}
-
-static struct irq_chip sa1100_normal_chip = {
-	.name		= "SC",
-	.irq_ack	= sa1100_mask_irq,
-	.irq_mask	= sa1100_mask_irq,
-	.irq_unmask	= sa1100_unmask_irq,
-	.irq_set_wake	= sa1100_set_wake,
-};
-
-static int sa1100_normal_irqdomain_map(struct irq_domain *d,
-		unsigned int irq, irq_hw_number_t hwirq)
-{
-	irq_set_chip_and_handler(irq, &sa1100_normal_chip,
-				 handle_level_irq);
-	set_irq_flags(irq, IRQF_VALID);
-
-	return 0;
-}
-
-static struct irq_domain_ops sa1100_normal_irqdomain_ops = {
-	.map = sa1100_normal_irqdomain_map,
-	.xlate = irq_domain_xlate_onetwocell,
-};
-
-static struct irq_domain *sa1100_normal_irqdomain;
-
 static struct resource irq_resource =
 	DEFINE_RES_MEM_NAMED(0x90050000, SZ_64K, "irqs");
 
-- 
2.1.3
^ permalink raw reply related	[flat|nested] 10+ messages in thread
* [PATCH v2] ARM: sa1100: improve irq handling
  2014-11-25 19:09 [PATCH v2] ARM: sa1100: improve irq handling Dmitry Eremin-Solenikov
                   ` (7 preceding siblings ...)
  2014-11-25 19:09 ` [PATCH v2 8/8] ARM: sa1100: reorder IRQ handling code Dmitry Eremin-Solenikov
@ 2014-11-26 12:47 ` Linus Walleij
  8 siblings, 0 replies; 10+ messages in thread
From: Linus Walleij @ 2014-11-26 12:47 UTC (permalink / raw)
  To: linux-arm-kernel
On Tue, Nov 25, 2014 at 8:09 PM, Dmitry Eremin-Solenikov
<dbaryshkov@gmail.com> wrote:
> This patch series makes sa1100 platform use MULTI_IRQ_HANDLER and irq
> domains to handle interrupts on StrongARM platform. Also virtual irq
> numbers are changed to start from 1 rather than 0. It doesn't change
> the way how Linux programs the hardware, only software interfaces are
> changed.
>
> Changes since v1:
> - Start IRQs from 1, freeing IRQ 0
> - Merge identical functions in the last patch
> - Other minor changes.
Applied all patches and tested on h3600 on top of v3.18-rc6.
Works like a charm.
Tested-by: Linus Walleij <linus.walleij@linaro.org>
Yours,
Linus Walleij
^ permalink raw reply	[flat|nested] 10+ messages in thread
end of thread, other threads:[~2014-11-26 12:47 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-11-25 19:09 [PATCH v2] ARM: sa1100: improve irq handling Dmitry Eremin-Solenikov
2014-11-25 19:09 ` [PATCH v2 1/8] ARM: sa1100: switch to MULTI_IRQ_HANDLER Dmitry Eremin-Solenikov
2014-11-25 19:09 ` [PATCH v2 2/8] ARM: sa1100: drop entry-macro.S Dmitry Eremin-Solenikov
2014-11-25 19:09 ` [PATCH v2 3/8] ARM: sa1100: replace irq numbers with names in irq driver Dmitry Eremin-Solenikov
2014-11-25 19:09 ` [PATCH v2 4/8] ARM: sa1100: shift IRQs by one Dmitry Eremin-Solenikov
2014-11-25 19:09 ` [PATCH v2 5/8] ARM: sa1100: introduce irqdomains support Dmitry Eremin-Solenikov
2014-11-25 19:09 ` [PATCH v2 6/8] ARM: sa1100: merge GPIO multiplexer IRQ to "normal" irq domain Dmitry Eremin-Solenikov
2014-11-25 19:09 ` [PATCH v2 7/8] ARM: sa1100: switch to hwirq usage Dmitry Eremin-Solenikov
2014-11-25 19:09 ` [PATCH v2 8/8] ARM: sa1100: reorder IRQ handling code Dmitry Eremin-Solenikov
2014-11-26 12:47 ` [PATCH v2] ARM: sa1100: improve irq handling Linus Walleij
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).