All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] arm: exynos4: add support for dt irq specifier to linux virq conversion
@ 2011-09-03 13:25 ` Thomas Abraham
  0 siblings, 0 replies; 5+ messages in thread
From: Thomas Abraham @ 2011-09-03 13:25 UTC (permalink / raw)
  To: devicetree-discuss
  Cc: grant.likely, linux-samsung-soc, kgene.kim, linux-arm-kernel

Add support for conversion of device tree interrupt specifier to linux
virq domain for GIC and Interrupt combiner controllers.

Signed-off-by: Thomas Abraham <thomas.abraham@linaro.org>
---
For GIC controller, this patch is based on Rob Herring's
"[RFC PATCH 0/3] Yet another GIC OF binding series" patchset
with v2 of the third patch in that series.

The concept of irq domain for interrupt combiner controller
is based on Grant's 'simple' irq converter.

 .../devicetree/bindings/irq/samsung-combiner.txt   |   24 ++++++++
 arch/arm/mach-exynos4/cpu.c                        |   56 +++++++++++++++++++-
 2 files changed, 79 insertions(+), 1 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/irq/samsung-combiner.txt

diff --git a/Documentation/devicetree/bindings/irq/samsung-combiner.txt b/Documentation/devicetree/bindings/irq/samsung-combiner.txt
new file mode 100644
index 0000000..b020f79
--- /dev/null
+++ b/Documentation/devicetree/bindings/irq/samsung-combiner.txt
@@ -0,0 +1,24 @@
+* Exynos4 Interrupt Combiner Controller
+
+Samsung's Exynos4 architecture includes a interrupt combiner which
+can combine interrupt sources as a group and provide a single
+interrupt request for the group. The interrupt request from each
+group are connected to a parent interrupt controller, which is GIC
+in case of Exynos4.
+
+Required properties:
+- compatible: should be "samsung,exynos4-combiner".
+- interrupt-cells: should be <2>. The meaning of the cells are
+    * First Cell: Combiner Group Number.
+    * Second Cell: Interrupt within the group.
+- reg: Base address and size of interrupt combiner registers.
+- interrupt-controller: Identifies the node as an interrupt controller.
+
+Example:
+
+	combiner: interrupt-controller@10440000 {
+		compatible = "samsung,exynos4-combiner";
+		#interrupt-cells = <2>;
+		interrupt-controller;
+		reg = <0x10440000 0x200>;
+	};
diff --git a/arch/arm/mach-exynos4/cpu.c b/arch/arm/mach-exynos4/cpu.c
index 746d6fc..de3d6e4 100644
--- a/arch/arm/mach-exynos4/cpu.c
+++ b/arch/arm/mach-exynos4/cpu.c
@@ -10,6 +10,10 @@
 
 #include <linux/sched.h>
 #include <linux/sysdev.h>
+#include <linux/of_irq.h>
+#include <linux/of.h>
+#include <linux/irqdomain.h>
+#include <linux/slab.h>
 
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
@@ -31,6 +35,7 @@
 
 #include <mach/regs-irq.h>
 #include <mach/regs-pmu.h>
+#include <mach/irqs.h>
 
 extern int combiner_init(unsigned int combiner_nr, void __iomem *base,
 			 unsigned int irq_start);
@@ -182,13 +187,62 @@ static void exynos4_gic_irq_eoi(struct irq_data *d)
 			    (EXYNOS4_GIC_BANK_OFFSET * smp_processor_id());
 }
 
+#ifdef CONFIG_OF
+/* Translate dt irq specifier to linux virq for interrupt combiner controller */
+static int exynos4_irq_domain_combiner_dt_translate(struct irq_domain *d,
+			struct device_node *controller,
+			const u32 *intspec, unsigned int intsize,
+			unsigned long *out_hwirq, unsigned int *out_type)
+{
+	if (d->of_node != controller)
+		return -EINVAL;
+	if (intsize < 2)
+		return -EINVAL;
+
+	*out_hwirq = COMBINER_IRQ(intspec[0], intspec[1]);
+	*out_type = IRQ_TYPE_NONE;
+	return 0;
+}
+
+static struct irq_domain_ops exynos4_irq_domain_combiner_ops = {
+	.dt_translate = exynos4_irq_domain_combiner_dt_translate,
+};
+#endif
+
 void __init exynos4_init_irq(void)
 {
 	int irq;
-
-	gic_init(0, IRQ_SPI(0), S5P_VA_GIC_DIST, S5P_VA_GIC_CPU);
+#ifdef CONFIG_OF
+	struct of_intc_desc desc;
+	struct irq_domain *domain;
+	struct device_node *node;
+
+	memset(&desc, 0, sizeof(desc));
+	desc.irq_base = IRQ_SPI(0);
+	desc.controller = of_find_compatible_node(NULL, NULL,
+				"arm,cortex-a9-gic");
+	if (desc.controller)
+		gic_of_init(&desc);
+	else
+#endif
+		gic_init(0, IRQ_SPI(0), S5P_VA_GIC_DIST, S5P_VA_GIC_CPU);
 	gic_arch_extn.irq_eoi = exynos4_gic_irq_eoi;
 
+#ifdef CONFIG_OF
+	node = of_find_compatible_node(NULL, NULL,
+			"samsung,exynos4-combiner");
+	if (node) {
+		domain = kzalloc(sizeof(*domain), GFP_KERNEL);
+		if (domain) {
+			domain->of_node = node;
+			domain->ops = &exynos4_irq_domain_combiner_ops;
+			irq_domain_add(domain);
+		} else {
+			WARN_ON(1);
+		}
+	}
+#endif
+
 	for (irq = 0; irq < MAX_COMBINER_NR; irq++) {
 
 		combiner_init(irq, (void __iomem *)S5P_VA_COMBINER(irq),
-- 
1.6.6.rc2

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

* [PATCH] arm: exynos4: add support for dt irq specifier to linux virq conversion
@ 2011-09-03 13:25 ` Thomas Abraham
  0 siblings, 0 replies; 5+ messages in thread
From: Thomas Abraham @ 2011-09-03 13:25 UTC (permalink / raw)
  To: linux-arm-kernel

Add support for conversion of device tree interrupt specifier to linux
virq domain for GIC and Interrupt combiner controllers.

Signed-off-by: Thomas Abraham <thomas.abraham@linaro.org>
---
For GIC controller, this patch is based on Rob Herring's
"[RFC PATCH 0/3] Yet another GIC OF binding series" patchset
with v2 of the third patch in that series.

The concept of irq domain for interrupt combiner controller
is based on Grant's 'simple' irq converter.

 .../devicetree/bindings/irq/samsung-combiner.txt   |   24 ++++++++
 arch/arm/mach-exynos4/cpu.c                        |   56 +++++++++++++++++++-
 2 files changed, 79 insertions(+), 1 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/irq/samsung-combiner.txt

diff --git a/Documentation/devicetree/bindings/irq/samsung-combiner.txt b/Documentation/devicetree/bindings/irq/samsung-combiner.txt
new file mode 100644
index 0000000..b020f79
--- /dev/null
+++ b/Documentation/devicetree/bindings/irq/samsung-combiner.txt
@@ -0,0 +1,24 @@
+* Exynos4 Interrupt Combiner Controller
+
+Samsung's Exynos4 architecture includes a interrupt combiner which
+can combine interrupt sources as a group and provide a single
+interrupt request for the group. The interrupt request from each
+group are connected to a parent interrupt controller, which is GIC
+in case of Exynos4.
+
+Required properties:
+- compatible: should be "samsung,exynos4-combiner".
+- interrupt-cells: should be <2>. The meaning of the cells are
+    * First Cell: Combiner Group Number.
+    * Second Cell: Interrupt within the group.
+- reg: Base address and size of interrupt combiner registers.
+- interrupt-controller: Identifies the node as an interrupt controller.
+
+Example:
+
+	combiner: interrupt-controller at 10440000 {
+		compatible = "samsung,exynos4-combiner";
+		#interrupt-cells = <2>;
+		interrupt-controller;
+		reg = <0x10440000 0x200>;
+	};
diff --git a/arch/arm/mach-exynos4/cpu.c b/arch/arm/mach-exynos4/cpu.c
index 746d6fc..de3d6e4 100644
--- a/arch/arm/mach-exynos4/cpu.c
+++ b/arch/arm/mach-exynos4/cpu.c
@@ -10,6 +10,10 @@
 
 #include <linux/sched.h>
 #include <linux/sysdev.h>
+#include <linux/of_irq.h>
+#include <linux/of.h>
+#include <linux/irqdomain.h>
+#include <linux/slab.h>
 
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
@@ -31,6 +35,7 @@
 
 #include <mach/regs-irq.h>
 #include <mach/regs-pmu.h>
+#include <mach/irqs.h>
 
 extern int combiner_init(unsigned int combiner_nr, void __iomem *base,
 			 unsigned int irq_start);
@@ -182,13 +187,62 @@ static void exynos4_gic_irq_eoi(struct irq_data *d)
 			    (EXYNOS4_GIC_BANK_OFFSET * smp_processor_id());
 }
 
+#ifdef CONFIG_OF
+/* Translate dt irq specifier to linux virq for interrupt combiner controller */
+static int exynos4_irq_domain_combiner_dt_translate(struct irq_domain *d,
+			struct device_node *controller,
+			const u32 *intspec, unsigned int intsize,
+			unsigned long *out_hwirq, unsigned int *out_type)
+{
+	if (d->of_node != controller)
+		return -EINVAL;
+	if (intsize < 2)
+		return -EINVAL;
+
+	*out_hwirq = COMBINER_IRQ(intspec[0], intspec[1]);
+	*out_type = IRQ_TYPE_NONE;
+	return 0;
+}
+
+static struct irq_domain_ops exynos4_irq_domain_combiner_ops = {
+	.dt_translate = exynos4_irq_domain_combiner_dt_translate,
+};
+#endif
+
 void __init exynos4_init_irq(void)
 {
 	int irq;
-
-	gic_init(0, IRQ_SPI(0), S5P_VA_GIC_DIST, S5P_VA_GIC_CPU);
+#ifdef CONFIG_OF
+	struct of_intc_desc desc;
+	struct irq_domain *domain;
+	struct device_node *node;
+
+	memset(&desc, 0, sizeof(desc));
+	desc.irq_base = IRQ_SPI(0);
+	desc.controller = of_find_compatible_node(NULL, NULL,
+				"arm,cortex-a9-gic");
+	if (desc.controller)
+		gic_of_init(&desc);
+	else
+#endif
+		gic_init(0, IRQ_SPI(0), S5P_VA_GIC_DIST, S5P_VA_GIC_CPU);
 	gic_arch_extn.irq_eoi = exynos4_gic_irq_eoi;
 
+#ifdef CONFIG_OF
+	node = of_find_compatible_node(NULL, NULL,
+			"samsung,exynos4-combiner");
+	if (node) {
+		domain = kzalloc(sizeof(*domain), GFP_KERNEL);
+		if (domain) {
+			domain->of_node = node;
+			domain->ops = &exynos4_irq_domain_combiner_ops;
+			irq_domain_add(domain);
+		} else {
+			WARN_ON(1);
+		}
+	}
+#endif
+
 	for (irq = 0; irq < MAX_COMBINER_NR; irq++) {
 
 		combiner_init(irq, (void __iomem *)S5P_VA_COMBINER(irq),
-- 
1.6.6.rc2

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

* Re: [PATCH] arm: exynos4: Add support for dt irq specifier to linux virq conversion
  2011-07-31  3:46 ` Grant Likely
@ 2011-07-31 21:11   ` Thomas Abraham
  0 siblings, 0 replies; 5+ messages in thread
From: Thomas Abraham @ 2011-07-31 21:11 UTC (permalink / raw)
  To: Grant Likely
  Cc: devicetree-discuss, linux-samsung-soc, nala.la, kgene.kim, chaos.youn

Hi Grant,

On 31 July 2011 04:46, Grant Likely <grant.likely@secretlab.ca> wrote:
> On Wed, Jul 27, 2011 at 11:54:28PM +0530, Thomas Abraham wrote:
>> Exynos4 includes two interrupt controllers - External GIC and External
>> Interrupt Combiner. External GIC can handle 16 software generated
>> interrupts (SGI), 16 Private Peripheral Interrupts (PPI) and 128
>> Shared Peripheral Interrupts (SPI). External Interrupt Combiner manages
>> 32 groups of 8 interrupts each and feeds 32 interrupts as SPI interrupts
>> to the External GIC controller.
>>
>> This patch supports conversion of device tree interrupt specifier to
>> linux virq domain for both the interrupt controllers. The concept of
>> this patch is derived from Grant's 'simple' irq converter.
>>
>> This patch is based on Grant's following patchset
>> [PATCH v3 0/2] Simple irq_domain implementation
>>
>> Signed-off-by: Thomas Abraham <thomas.abraham@linaro.org>
>> ---
>>  Documentation/devicetree/bindings/arm/samsung.txt |   72 +++++++++++++
>>  arch/arm/mach-exynos4/Makefile                    |    1 +
>>  arch/arm/mach-exynos4/include/mach/irqs.h         |    3 +
>>  arch/arm/mach-exynos4/irqdomain.c                 |  117 +++++++++++++++++++++
>>  arch/arm/mach-exynos4/mach-exynos4-dt.c           |    8 +-
>>  5 files changed, 196 insertions(+), 5 deletions(-)
>>  create mode 100644 arch/arm/mach-exynos4/irqdomain.c
>>
>> diff --git a/Documentation/devicetree/bindings/arm/samsung.txt b/Documentation/devicetree/bindings/arm/samsung.txt

[...]

>> +
>> +External GIC properties:
>> +  - compatible: should be "samsung,exynos4-ext-gic".
>> +  - interrupt-cells: should be <2>. The meaning of the cells are
>> +      * First Cell: Interrupt Number.
>> +      * Second Cell: Type of Interrupt (0-SPI, 1-SGI, 2-PPI).
>
> Type should probably be the first cell.  That's how this has been
> handled in the past for other hardware.  Also, the gic binding is
> going to be shared for a bunch of ARM hardware, not just Exynos.  Can
> you split this patch into two parts; one for gic and one for the
> exynos combiner?

Ok. I will split this patch and change the order of the cells.

>
>> +  - reg: The GIC includes a Distributor Interface and CPU Interface and
>> +    hence requires two base addresses. The property format is
>> +    <Distributor-Base Distributor-Size>, <CPU-Base CPU Size>
>> +
>> +  Example:
>> +
>> +     EXT_GIC:interrupt-controller@10490000 {
>> +             compatible = "samsung,exynos4-ext-gic";
>> +             #interrupt-cells = <2>;
>> +             interrupt-controller;
>> +             reg = <0x10490000 0x1000>, <0x10480000 0x100>;
>> +     };
>> +
>> +  Devices using External GIC as the interrupt parent should specify two
>> +  cells for the interrupts property as shown below.
>> +
>> +     watchdog@10060000 {
>> +             compatible = "samsung,s3c2410-wdt";
>> +             reg = <0x10060000 0x400>;
>> +             interrupt-parent = <&EXT_GIC>;
>> +             interrupts = <43 0>;
>> +     };
>> +
>> +External Interrupt Combiner properties:
>> +  - compatible: should be "samsung,exynos4-ext-combiner".
>> +  - interrupt-cells: should be <2>. The meaning of the cells are
>> +      * First Cell: Combiner Group Number.
>> +      * Second Cell: Interrupt within the group.
>
> I was under the impression that the irq groupings are programmable,
> and that the combiner irq inputs are a flat numbering layout.  Is that
> correct?  If so, then #interrupt-cells should probably be 1, and the
> grouping should probably be configuration properties on the combiner
> node.

Each interrupt group in a combiner has fixed set of interrupts and is
not programmable. Each irq input to a interrupt group combiner has a
fixed number. So there is no programmable irq numbers supported by the
irq-combiner.

>
>> +  - reg: Base address and size of interrupt combiner registers.
>> +
>> +  Example:
>> +
>> +     EXT_COMBINER:interrupt-controller@10440000 {
>> +             compatible = "samsung,exynos4-ext-combiner";
>> +             #interrupt-cells = <2>;
>> +             interrupt-controller;
>> +             reg = <0x10440000 0x200>;
>> +     };
>> +
>> +  Devices using External Interrupt Combiner as the interrupt parent should
>> +  specify two cells for the interrupts property as shown below.
>> +
>> +     watchdog@10060000 {
>> +             compatible = "samsung,s3c2410-wdt";
>> +             reg = <0x10060000 0x400>;
>> +             interrupt-parent = <&EXT_COMBINER>;
>> +             interrupts = <4 2>;
>> +     };

[...]

>> +
>> +/*
>> + * The interrupt specifier for External GIC controller uses to two cells in
>> + * the device tree source file. The second cell denotes the type of the
>> + * interrupt (SPI/SGI/PPI). The following macros are used to represent
>> + * these different types of interrupt.
>> + */
>> +#define      EXT_GIC_SPI     0
>> +#define      EXT_GIC_SGI     1
>> +#define      EXT_GIC_PPI     2
>
> Nit: I prefer enums over preprocessor macros, but not a big deal.
>

Ok. I will add a enum for the type of GIC interrupt.

Thanks for your comments on the patch.

Regards,
Thomas.

[...]

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

* Re: [PATCH] arm: exynos4: Add support for dt irq specifier to linux virq conversion
  2011-07-27 18:24 [PATCH] arm: exynos4: Add " Thomas Abraham
@ 2011-07-31  3:46 ` Grant Likely
  2011-07-31 21:11   ` Thomas Abraham
  0 siblings, 1 reply; 5+ messages in thread
From: Grant Likely @ 2011-07-31  3:46 UTC (permalink / raw)
  To: Thomas Abraham
  Cc: devicetree-discuss, linux-samsung-soc, nala.la, kgene.kim, chaos.youn

On Wed, Jul 27, 2011 at 11:54:28PM +0530, Thomas Abraham wrote:
> Exynos4 includes two interrupt controllers - External GIC and External
> Interrupt Combiner. External GIC can handle 16 software generated
> interrupts (SGI), 16 Private Peripheral Interrupts (PPI) and 128
> Shared Peripheral Interrupts (SPI). External Interrupt Combiner manages
> 32 groups of 8 interrupts each and feeds 32 interrupts as SPI interrupts
> to the External GIC controller.
> 
> This patch supports conversion of device tree interrupt specifier to
> linux virq domain for both the interrupt controllers. The concept of
> this patch is derived from Grant's 'simple' irq converter.
> 
> This patch is based on Grant's following patchset
> [PATCH v3 0/2] Simple irq_domain implementation
> 
> Signed-off-by: Thomas Abraham <thomas.abraham@linaro.org>
> ---
>  Documentation/devicetree/bindings/arm/samsung.txt |   72 +++++++++++++
>  arch/arm/mach-exynos4/Makefile                    |    1 +
>  arch/arm/mach-exynos4/include/mach/irqs.h         |    3 +
>  arch/arm/mach-exynos4/irqdomain.c                 |  117 +++++++++++++++++++++
>  arch/arm/mach-exynos4/mach-exynos4-dt.c           |    8 +-
>  5 files changed, 196 insertions(+), 5 deletions(-)
>  create mode 100644 arch/arm/mach-exynos4/irqdomain.c
> 
> diff --git a/Documentation/devicetree/bindings/arm/samsung.txt b/Documentation/devicetree/bindings/arm/samsung.txt
> index 5676bca..878aa01 100644
> --- a/Documentation/devicetree/bindings/arm/samsung.txt
> +++ b/Documentation/devicetree/bindings/arm/samsung.txt
> @@ -6,3 +6,75 @@ Required root node properties:
>    - compatible = "samsung,smdkv310", "samsung,exynos4210'.
>        (a) "samsung,smdkv310" - for Samsung's SMDKV310 eval board.
>        (b) "samsung,exynos4210" - for boards based on Exynos4210 processor.
> +
> +
> +Exynos4 Interrupt Controllers
> +-----------------------------
> +
> +Samsung's Exynos4 architecture includes two interrupt controllers.
> +  - External GIC
> +  - External Interrupt Combiner.
> +
> +The external GIC can manage
> +  - 16 Software Generated Interrupts (SGI).
> +  - 16 Private Peripheral Interrupts (PPI).
> +  - 128 Shared Peripheral Interrupts (SPI).
> +
> +Out of the 128 Shared Peripheral Interrupts (SPI's), 32 interrupts
> +are sourced from a interrupt combiner. The interrupt combiner provides
> +32 groups of interrupts with a maximum of 8 interrupts combined per
> +group.
> +
> +External GIC properties:
> +  - compatible: should be "samsung,exynos4-ext-gic".
> +  - interrupt-cells: should be <2>. The meaning of the cells are
> +      * First Cell: Interrupt Number.
> +      * Second Cell: Type of Interrupt (0-SPI, 1-SGI, 2-PPI).

Type should probably be the first cell.  That's how this has been
handled in the past for other hardware.  Also, the gic binding is
going to be shared for a bunch of ARM hardware, not just Exynos.  Can
you split this patch into two parts; one for gic and one for the
exynos combiner?

> +  - reg: The GIC includes a Distributor Interface and CPU Interface and
> +    hence requires two base addresses. The property format is
> +    <Distributor-Base Distributor-Size>, <CPU-Base CPU Size>
> +
> +  Example:
> +
> +	EXT_GIC:interrupt-controller@10490000 {
> +		compatible = "samsung,exynos4-ext-gic";
> +		#interrupt-cells = <2>;
> +		interrupt-controller;
> +		reg = <0x10490000 0x1000>, <0x10480000 0x100>;
> +	};
> +
> +  Devices using External GIC as the interrupt parent should specify two
> +  cells for the interrupts property as shown below.
> +
> +	watchdog@10060000 {
> +		compatible = "samsung,s3c2410-wdt";
> +		reg = <0x10060000 0x400>;
> +		interrupt-parent = <&EXT_GIC>;
> +		interrupts = <43 0>;
> +	};
> +
> +External Interrupt Combiner properties:
> +  - compatible: should be "samsung,exynos4-ext-combiner".
> +  - interrupt-cells: should be <2>. The meaning of the cells are
> +      * First Cell: Combiner Group Number.
> +      * Second Cell: Interrupt within the group.

I was under the impression that the irq groupings are programmable,
and that the combiner irq inputs are a flat numbering layout.  Is that
correct?  If so, then #interrupt-cells should probably be 1, and the
grouping should probably be configuration properties on the combiner
node.

> +  - reg: Base address and size of interrupt combiner registers.
> +
> +  Example:
> +
> +	EXT_COMBINER:interrupt-controller@10440000 {
> +		compatible = "samsung,exynos4-ext-combiner";
> +		#interrupt-cells = <2>;
> +		interrupt-controller;
> +		reg = <0x10440000 0x200>;
> +	};
> +
> +  Devices using External Interrupt Combiner as the interrupt parent should
> +  specify two cells for the interrupts property as shown below.
> +
> +	watchdog@10060000 {
> +		compatible = "samsung,s3c2410-wdt";
> +		reg = <0x10060000 0x400>;
> +		interrupt-parent = <&EXT_COMBINER>;
> +		interrupts = <4 2>;
> +	};
> diff --git a/arch/arm/mach-exynos4/Makefile b/arch/arm/mach-exynos4/Makefile
> index ac91f4f..fd532c7 100644
> --- a/arch/arm/mach-exynos4/Makefile
> +++ b/arch/arm/mach-exynos4/Makefile
> @@ -32,6 +32,7 @@ obj-$(CONFIG_MACH_ARMLEX4210)		+= mach-armlex4210.o
>  obj-$(CONFIG_MACH_UNIVERSAL_C210)	+= mach-universal_c210.o
>  obj-$(CONFIG_MACH_NURI)			+= mach-nuri.o
>  obj-$(CONFIG_MACH_EXYNOS4_DT)		+= mach-exynos4-dt.o
> +obj-$(CONFIG_OF_IRQ)			+= irqdomain.o
>  
>  # device support
>  
> diff --git a/arch/arm/mach-exynos4/include/mach/irqs.h b/arch/arm/mach-exynos4/include/mach/irqs.h
> index 934d2a4..c120aad 100644
> --- a/arch/arm/mach-exynos4/include/mach/irqs.h
> +++ b/arch/arm/mach-exynos4/include/mach/irqs.h
> @@ -15,6 +15,9 @@
>  
>  #include <plat/irqs.h>
>  
> +/* SGI: Software Generated Interrupt */
> +#define IRQ_SGI(x)		S5P_IRQ(x)
> +
>  /* PPI: Private Peripheral Interrupt */
>  
>  #define IRQ_PPI(x)		S5P_IRQ(x+16)
> diff --git a/arch/arm/mach-exynos4/irqdomain.c b/arch/arm/mach-exynos4/irqdomain.c
> new file mode 100644
> index 0000000..f50fa20
> --- /dev/null
> +++ b/arch/arm/mach-exynos4/irqdomain.c
> @@ -0,0 +1,117 @@
> +/*
> + * Exynos4 irq domain conversion from dt irq specifier to linux virq domain
> + *
> + * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
> + *		http://www.samsung.com
> + *
> + * Exynos4 includes two interrupt controllers - External GIC and External
> + * Interrupt Combiner. This file provides support for converting interrupt
> + * specified in device tree to linux virq domain for both the controllers.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> +*/
> +
> +#include <linux/irq.h>
> +#include <linux/irqdomain.h>
> +#include <linux/module.h>
> +#include <linux/mutex.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/slab.h>
> +
> +#include <mach/irqs.h>
> +
> +/*
> + * The interrupt specifier for External GIC controller uses to two cells in
> + * the device tree source file. The second cell denotes the type of the
> + * interrupt (SPI/SGI/PPI). The following macros are used to represent
> + * these different types of interrupt.
> + */
> +#define	EXT_GIC_SPI	0
> +#define	EXT_GIC_SGI	1
> +#define	EXT_GIC_PPI	2

Nit: I prefer enums over preprocessor macros, but not a big deal.

> +
> +/* Translate dt irq specifier to linux virq for external GIC controller */
> +static int exynos4_irq_domain_ext_gic_dt_translate(struct irq_domain *d,
> +			    struct device_node *controller,
> +			    const u32 *intspec, unsigned int intsize,
> +			    unsigned long *out_hwirq, unsigned int *out_type)
> +{
> +	if (d->of_node != controller)
> +		return -EINVAL;
> +	if (intsize < 2)
> +		return -EINVAL;
> +
> +	switch (intspec[1]) {
> +	case EXT_GIC_SPI:
> +		*out_hwirq = IRQ_SPI(intspec[0]);
> +		break;
> +	case EXT_GIC_SGI:
> +		*out_hwirq = IRQ_SGI(intspec[0]);
> +		break;
> +	case EXT_GIC_PPI:
> +		*out_hwirq = IRQ_PPI(intspec[0]);
> +		break;
> +	default:
> +		pr_info("irq_domain register: invalid ext gic intr type\n");
> +		return -EINVAL;
> +	}
> +
> +	*out_type = IRQ_TYPE_NONE;
> +	return 0;
> +}
> +
> +/* Translate dt irq specifier to linux virq for external combiner controller */
> +static int exynos4_irq_domain_ext_combiner_dt_translate(struct irq_domain *d,
> +			    struct device_node *controller,
> +			    const u32 *intspec, unsigned int intsize,
> +			    unsigned long *out_hwirq, unsigned int *out_type)
> +{
> +	if (d->of_node != controller)
> +		return -EINVAL;
> +	if (intsize < 2)
> +		return -EINVAL;
> +
> +	*out_hwirq = COMBINER_IRQ(intspec[0], intspec[1]);
> +	*out_type = IRQ_TYPE_NONE;
> +	return 0;
> +}
> +
> +static struct irq_domain_ops exynos4_irq_domain_ext_gic_ops = {
> +	.dt_translate = exynos4_irq_domain_ext_gic_dt_translate,
> +};
> +
> +static struct irq_domain_ops exynos4_irq_domain_ext_combiner_ops = {
> +	.dt_translate = exynos4_irq_domain_ext_combiner_dt_translate,
> +};
> +
> +static struct of_device_id exynos4_irq_ctrl_of_match[] = {
> +	{ .compatible = "samsung,exynos4-ext-gic",
> +		.data = &exynos4_irq_domain_ext_gic_ops, },
> +	{ .compatible = "samsung,exynos4-ext-combiner",
> +		.data = &exynos4_irq_domain_ext_combiner_ops, },
> +	{},
> +};
> +
> +void exynos4_register_irq_domain_dt(void)
> +{
> +	struct device_node *controller;
> +	struct irq_domain *domain;
> +	const struct of_device_id *match;
> +
> +	for_each_matching_node(controller, exynos4_irq_ctrl_of_match) {
> +		domain = kzalloc(sizeof(*domain), GFP_KERNEL);
> +		if (!domain) {
> +			WARN_ON(1);
> +			return;
> +		}
> +
> +		match = of_match_node(exynos4_irq_ctrl_of_match, controller);
> +		domain->of_node = of_node_get(controller);
> +		domain->ops = match->data;
> +		irq_domain_add(domain);
> +	}
> +}
> +EXPORT_SYMBOL_GPL(exynos4_register_irq_domain_dt);
> diff --git a/arch/arm/mach-exynos4/mach-exynos4-dt.c b/arch/arm/mach-exynos4/mach-exynos4-dt.c
> index 120665a..450a9ed 100644
> --- a/arch/arm/mach-exynos4/mach-exynos4-dt.c
> +++ b/arch/arm/mach-exynos4/mach-exynos4-dt.c
> @@ -16,6 +16,7 @@
>  #include <linux/io.h>
>  #include <linux/of_platform.h>
>  #include <linux/irq.h>
> +#include <linux/irqdomain.h>
>  
>  #include <asm/mach/arch.h>
>  #include <asm/mach-types.h>
> @@ -85,14 +86,11 @@ static void __init exynos4_dt_map_io(void)
>  	s3c24xx_init_uarts(smdkv310_uartcfgs, ARRAY_SIZE(smdkv310_uartcfgs));
>  }
>  
> -static const struct of_device_id intc_of_match[] __initconst = {
> -	{ .compatible = "samsung,exynos4-gic", },
> -	{}
> -};
> +extern void exynos4_register_irq_domain_dt(void);
>  
>  static void __init exynos4_dt_machine_init(void)
>  {
> -	irq_domain_generate_simple(intc_of_match, EXYNOS4_PA_GIC_DIST, 0);
> +	exynos4_register_irq_domain_dt();
>  	of_platform_populate(NULL, of_default_bus_match_table,
>  				exynos4_auxdata_lookup, NULL);
>  }
> -- 
> 1.6.6.rc2
> 

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

* [PATCH] arm: exynos4: Add support for dt irq specifier to linux virq conversion
@ 2011-07-27 18:24 Thomas Abraham
  2011-07-31  3:46 ` Grant Likely
  0 siblings, 1 reply; 5+ messages in thread
From: Thomas Abraham @ 2011-07-27 18:24 UTC (permalink / raw)
  To: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
  Cc: kgene.kim-Sze3O3UU22JBDgjK7y7TUQ,
	linux-samsung-soc-u79uwXL29TY76Z2rM5mHXA,
	chaos.youn-Sze3O3UU22JBDgjK7y7TUQ

Exynos4 includes two interrupt controllers - External GIC and External
Interrupt Combiner. External GIC can handle 16 software generated
interrupts (SGI), 16 Private Peripheral Interrupts (PPI) and 128
Shared Peripheral Interrupts (SPI). External Interrupt Combiner manages
32 groups of 8 interrupts each and feeds 32 interrupts as SPI interrupts
to the External GIC controller.

This patch supports conversion of device tree interrupt specifier to
linux virq domain for both the interrupt controllers. The concept of
this patch is derived from Grant's 'simple' irq converter.

This patch is based on Grant's following patchset
[PATCH v3 0/2] Simple irq_domain implementation

Signed-off-by: Thomas Abraham <thomas.abraham-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
 Documentation/devicetree/bindings/arm/samsung.txt |   72 +++++++++++++
 arch/arm/mach-exynos4/Makefile                    |    1 +
 arch/arm/mach-exynos4/include/mach/irqs.h         |    3 +
 arch/arm/mach-exynos4/irqdomain.c                 |  117 +++++++++++++++++++++
 arch/arm/mach-exynos4/mach-exynos4-dt.c           |    8 +-
 5 files changed, 196 insertions(+), 5 deletions(-)
 create mode 100644 arch/arm/mach-exynos4/irqdomain.c

diff --git a/Documentation/devicetree/bindings/arm/samsung.txt b/Documentation/devicetree/bindings/arm/samsung.txt
index 5676bca..878aa01 100644
--- a/Documentation/devicetree/bindings/arm/samsung.txt
+++ b/Documentation/devicetree/bindings/arm/samsung.txt
@@ -6,3 +6,75 @@ Required root node properties:
   - compatible = "samsung,smdkv310", "samsung,exynos4210'.
       (a) "samsung,smdkv310" - for Samsung's SMDKV310 eval board.
       (b) "samsung,exynos4210" - for boards based on Exynos4210 processor.
+
+
+Exynos4 Interrupt Controllers
+-----------------------------
+
+Samsung's Exynos4 architecture includes two interrupt controllers.
+  - External GIC
+  - External Interrupt Combiner.
+
+The external GIC can manage
+  - 16 Software Generated Interrupts (SGI).
+  - 16 Private Peripheral Interrupts (PPI).
+  - 128 Shared Peripheral Interrupts (SPI).
+
+Out of the 128 Shared Peripheral Interrupts (SPI's), 32 interrupts
+are sourced from a interrupt combiner. The interrupt combiner provides
+32 groups of interrupts with a maximum of 8 interrupts combined per
+group.
+
+External GIC properties:
+  - compatible: should be "samsung,exynos4-ext-gic".
+  - interrupt-cells: should be <2>. The meaning of the cells are
+      * First Cell: Interrupt Number.
+      * Second Cell: Type of Interrupt (0-SPI, 1-SGI, 2-PPI).
+  - reg: The GIC includes a Distributor Interface and CPU Interface and
+    hence requires two base addresses. The property format is
+    <Distributor-Base Distributor-Size>, <CPU-Base CPU Size>
+
+  Example:
+
+	EXT_GIC:interrupt-controller@10490000 {
+		compatible = "samsung,exynos4-ext-gic";
+		#interrupt-cells = <2>;
+		interrupt-controller;
+		reg = <0x10490000 0x1000>, <0x10480000 0x100>;
+	};
+
+  Devices using External GIC as the interrupt parent should specify two
+  cells for the interrupts property as shown below.
+
+	watchdog@10060000 {
+		compatible = "samsung,s3c2410-wdt";
+		reg = <0x10060000 0x400>;
+		interrupt-parent = <&EXT_GIC>;
+		interrupts = <43 0>;
+	};
+
+External Interrupt Combiner properties:
+  - compatible: should be "samsung,exynos4-ext-combiner".
+  - interrupt-cells: should be <2>. The meaning of the cells are
+      * First Cell: Combiner Group Number.
+      * Second Cell: Interrupt within the group.
+  - reg: Base address and size of interrupt combiner registers.
+
+  Example:
+
+	EXT_COMBINER:interrupt-controller@10440000 {
+		compatible = "samsung,exynos4-ext-combiner";
+		#interrupt-cells = <2>;
+		interrupt-controller;
+		reg = <0x10440000 0x200>;
+	};
+
+  Devices using External Interrupt Combiner as the interrupt parent should
+  specify two cells for the interrupts property as shown below.
+
+	watchdog@10060000 {
+		compatible = "samsung,s3c2410-wdt";
+		reg = <0x10060000 0x400>;
+		interrupt-parent = <&EXT_COMBINER>;
+		interrupts = <4 2>;
+	};
diff --git a/arch/arm/mach-exynos4/Makefile b/arch/arm/mach-exynos4/Makefile
index ac91f4f..fd532c7 100644
--- a/arch/arm/mach-exynos4/Makefile
+++ b/arch/arm/mach-exynos4/Makefile
@@ -32,6 +32,7 @@ obj-$(CONFIG_MACH_ARMLEX4210)		+= mach-armlex4210.o
 obj-$(CONFIG_MACH_UNIVERSAL_C210)	+= mach-universal_c210.o
 obj-$(CONFIG_MACH_NURI)			+= mach-nuri.o
 obj-$(CONFIG_MACH_EXYNOS4_DT)		+= mach-exynos4-dt.o
+obj-$(CONFIG_OF_IRQ)			+= irqdomain.o
 
 # device support
 
diff --git a/arch/arm/mach-exynos4/include/mach/irqs.h b/arch/arm/mach-exynos4/include/mach/irqs.h
index 934d2a4..c120aad 100644
--- a/arch/arm/mach-exynos4/include/mach/irqs.h
+++ b/arch/arm/mach-exynos4/include/mach/irqs.h
@@ -15,6 +15,9 @@
 
 #include <plat/irqs.h>
 
+/* SGI: Software Generated Interrupt */
+#define IRQ_SGI(x)		S5P_IRQ(x)
+
 /* PPI: Private Peripheral Interrupt */
 
 #define IRQ_PPI(x)		S5P_IRQ(x+16)
diff --git a/arch/arm/mach-exynos4/irqdomain.c b/arch/arm/mach-exynos4/irqdomain.c
new file mode 100644
index 0000000..f50fa20
--- /dev/null
+++ b/arch/arm/mach-exynos4/irqdomain.c
@@ -0,0 +1,117 @@
+/*
+ * Exynos4 irq domain conversion from dt irq specifier to linux virq domain
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Exynos4 includes two interrupt controllers - External GIC and External
+ * Interrupt Combiner. This file provides support for converting interrupt
+ * specified in device tree to linux virq domain for both the controllers.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+
+#include <mach/irqs.h>
+
+/*
+ * The interrupt specifier for External GIC controller uses to two cells in
+ * the device tree source file. The second cell denotes the type of the
+ * interrupt (SPI/SGI/PPI). The following macros are used to represent
+ * these different types of interrupt.
+ */
+#define	EXT_GIC_SPI	0
+#define	EXT_GIC_SGI	1
+#define	EXT_GIC_PPI	2
+
+/* Translate dt irq specifier to linux virq for external GIC controller */
+static int exynos4_irq_domain_ext_gic_dt_translate(struct irq_domain *d,
+			    struct device_node *controller,
+			    const u32 *intspec, unsigned int intsize,
+			    unsigned long *out_hwirq, unsigned int *out_type)
+{
+	if (d->of_node != controller)
+		return -EINVAL;
+	if (intsize < 2)
+		return -EINVAL;
+
+	switch (intspec[1]) {
+	case EXT_GIC_SPI:
+		*out_hwirq = IRQ_SPI(intspec[0]);
+		break;
+	case EXT_GIC_SGI:
+		*out_hwirq = IRQ_SGI(intspec[0]);
+		break;
+	case EXT_GIC_PPI:
+		*out_hwirq = IRQ_PPI(intspec[0]);
+		break;
+	default:
+		pr_info("irq_domain register: invalid ext gic intr type\n");
+		return -EINVAL;
+	}
+
+	*out_type = IRQ_TYPE_NONE;
+	return 0;
+}
+
+/* Translate dt irq specifier to linux virq for external combiner controller */
+static int exynos4_irq_domain_ext_combiner_dt_translate(struct irq_domain *d,
+			    struct device_node *controller,
+			    const u32 *intspec, unsigned int intsize,
+			    unsigned long *out_hwirq, unsigned int *out_type)
+{
+	if (d->of_node != controller)
+		return -EINVAL;
+	if (intsize < 2)
+		return -EINVAL;
+
+	*out_hwirq = COMBINER_IRQ(intspec[0], intspec[1]);
+	*out_type = IRQ_TYPE_NONE;
+	return 0;
+}
+
+static struct irq_domain_ops exynos4_irq_domain_ext_gic_ops = {
+	.dt_translate = exynos4_irq_domain_ext_gic_dt_translate,
+};
+
+static struct irq_domain_ops exynos4_irq_domain_ext_combiner_ops = {
+	.dt_translate = exynos4_irq_domain_ext_combiner_dt_translate,
+};
+
+static struct of_device_id exynos4_irq_ctrl_of_match[] = {
+	{ .compatible = "samsung,exynos4-ext-gic",
+		.data = &exynos4_irq_domain_ext_gic_ops, },
+	{ .compatible = "samsung,exynos4-ext-combiner",
+		.data = &exynos4_irq_domain_ext_combiner_ops, },
+	{},
+};
+
+void exynos4_register_irq_domain_dt(void)
+{
+	struct device_node *controller;
+	struct irq_domain *domain;
+	const struct of_device_id *match;
+
+	for_each_matching_node(controller, exynos4_irq_ctrl_of_match) {
+		domain = kzalloc(sizeof(*domain), GFP_KERNEL);
+		if (!domain) {
+			WARN_ON(1);
+			return;
+		}
+
+		match = of_match_node(exynos4_irq_ctrl_of_match, controller);
+		domain->of_node = of_node_get(controller);
+		domain->ops = match->data;
+		irq_domain_add(domain);
+	}
+}
+EXPORT_SYMBOL_GPL(exynos4_register_irq_domain_dt);
diff --git a/arch/arm/mach-exynos4/mach-exynos4-dt.c b/arch/arm/mach-exynos4/mach-exynos4-dt.c
index 120665a..450a9ed 100644
--- a/arch/arm/mach-exynos4/mach-exynos4-dt.c
+++ b/arch/arm/mach-exynos4/mach-exynos4-dt.c
@@ -16,6 +16,7 @@
 #include <linux/io.h>
 #include <linux/of_platform.h>
 #include <linux/irq.h>
+#include <linux/irqdomain.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
@@ -85,14 +86,11 @@ static void __init exynos4_dt_map_io(void)
 	s3c24xx_init_uarts(smdkv310_uartcfgs, ARRAY_SIZE(smdkv310_uartcfgs));
 }
 
-static const struct of_device_id intc_of_match[] __initconst = {
-	{ .compatible = "samsung,exynos4-gic", },
-	{}
-};
+extern void exynos4_register_irq_domain_dt(void);
 
 static void __init exynos4_dt_machine_init(void)
 {
-	irq_domain_generate_simple(intc_of_match, EXYNOS4_PA_GIC_DIST, 0);
+	exynos4_register_irq_domain_dt();
 	of_platform_populate(NULL, of_default_bus_match_table,
 				exynos4_auxdata_lookup, NULL);
 }
-- 
1.6.6.rc2

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

end of thread, other threads:[~2011-09-03 13:25 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-09-03 13:25 [PATCH] arm: exynos4: add support for dt irq specifier to linux virq conversion Thomas Abraham
2011-09-03 13:25 ` Thomas Abraham
  -- strict thread matches above, loose matches on Subject: below --
2011-07-27 18:24 [PATCH] arm: exynos4: Add " Thomas Abraham
2011-07-31  3:46 ` Grant Likely
2011-07-31 21:11   ` Thomas Abraham

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.