Skip to contentSkip to conversation

ARM: Exynos: Add irq_domain and device tree support for combiner

PATCH Superseded Thomas Abraham 3 participants 7 messages Feb 21, 2012 – Mar 13, 2012

Subsystems (4)

v4 of 5 Superseded Latest is v5 →

lore
Share & tools
lore
#0 lore raw

v4 cover ARM: Exynos: Add irq_domain and device tree support for combiner

Changes since v3:
- In dt case, the use of fixed gic linux irq number to map the combiner interrupt output is removed. This is replaced with the interrupt number obtained from the gic irq domain. (Thanks to Rob Herring and Grant Likely for this suggestion).
- Split the patch into two parts - irq_domain and device tree support addition.

Changes since v2:
- Rebased to Grant's irqdomain/next branch.

Changes since v1:
- Includes all changes suggested by Rob Herring.
- Tested with SPARSE_IRQ enabled.

This patchset adds irq_domain and device tree support for the Exynos Interrupt Combiner controller.

The first patch adds a common irq domain for the interrupts managed by the interrupt combiners. All the instances of irq combiner reference the common irq domain for translating hardware interrupts to linux irq number.

The second patch adds a interrupt specifier translator to support device tree based instantiation. It can translate interrupt specifiers for device nodes which use combiner as their interrupt parent.

This patchset is based on
http://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git [for-next]

with all irq_domain (v5) patches merged from
http://git.secretlab.ca/git/linux-2.6.git [irqdomain/next]

Thomas Abraham (2):
ARM: Exynos: Add irq_domain support for interrupt combiner
ARM: Exynos: Add device tree support for interrupt combiner

 .../bindings/arm/samsung/interrupt-combiner.txt    |   48 +++++++++
 arch/arm/mach-exynos/common.c                      |  112 ++++++++++++++++----
 2 files changed, 140 insertions(+), 20 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/samsung/interrupt-combiner.txt
#1 lore raw

PATCH v4 1/2 ARM: Exynos: Add irq_domain support for interrupt combiner

Add irq_domain support for hardware interrupts of the interrupt combiner. The hardware interrupts of all the instances of the combiner are grouped in a single irq_domain.

---
 arch/arm/mach-exynos/common.c |   65 ++++++++++++++++++++++++++++------------
 1 files changed, 45 insertions(+), 20 deletions(-)
arch/arm/mach-exynos/common.c +45 -20
index f494db8..0c06fa6 100644
@@ -19,6 +19,8 @@
 #include <linux/serial_core.h>
 #include <linux/of.h>
 #include <linux/of_irq.h>
+#include <linux/export.h>
+#include <linux/irqdomain.h>
 
 #include <asm/proc-fns.h>
 #include <asm/exception.h>
@@ -284,6 +286,7 @@ struct combiner_chip_data {
 	void __iomem *base;
 };
 
+static struct irq_domain *combiner_irq_domain;
 static struct combiner_chip_data combiner_data[MAX_COMBINER_NR];
 
 static inline void __iomem *combiner_base(struct irq_data *data)
@@ -296,14 +299,14 @@ static inline void __iomem *combiner_base(struct irq_data *data)
 
 static void combiner_mask_irq(struct irq_data *data)
 {
-	u32 mask = 1 << (data->irq % 32);
+	u32 mask = 1 << (data->hwirq % 32);
 
 	__raw_writel(mask, combiner_base(data) + COMBINER_ENABLE_CLEAR);
 }
 
 static void combiner_unmask_irq(struct irq_data *data)
 {
-	u32 mask = 1 << (data->irq % 32);
+	u32 mask = 1 << (data->hwirq % 32);
 
 	__raw_writel(mask, combiner_base(data) + COMBINER_ENABLE_SET);
 }
@@ -352,30 +355,58 @@ static void __init combiner_cascade_irq(unsigned int combiner_nr, unsigned int i
 	irq_set_chained_handler(irq, combiner_handle_cascade_irq);
 }
 
-static void __init combiner_init(unsigned int combiner_nr, void __iomem *base,
-			  unsigned int irq_start)
+static void __init combiner_init_one(unsigned int combiner_nr,
+						void __iomem *base)
 {
-	unsigned int i;
-
 	if (combiner_nr >= MAX_COMBINER_NR)
 		BUG();
 
 	combiner_data[combiner_nr].base = base;
-	combiner_data[combiner_nr].irq_offset = irq_start;
+	combiner_data[combiner_nr].irq_offset = irq_find_mapping(
+		combiner_irq_domain, combiner_nr * MAX_IRQ_IN_COMBINER);
 	combiner_data[combiner_nr].irq_mask = 0xff << ((combiner_nr % 4) << 3);
 
 	/* Disable all interrupts */
 
 	__raw_writel(combiner_data[combiner_nr].irq_mask,
 		     base + COMBINER_ENABLE_CLEAR);
+}
+
+static int combiner_irq_domain_map(struct irq_domain *d, unsigned int irq,
+					irq_hw_number_t hw)
+{
+	irq_set_chip_and_handler(irq, &combiner_chip, handle_level_irq);
+	irq_set_chip_data(irq, &combiner_data[hw >> 3]);
+	set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+	return 0;
+}
 
-	/* Setup the Linux IRQ subsystem */
+static struct irq_domain_ops combiner_irq_domain_ops = {
+	.map = combiner_irq_domain_map,
+};
 
-	for (i = irq_start; i < combiner_data[combiner_nr].irq_offset
-				+ MAX_IRQ_IN_COMBINER; i++) {
-		irq_set_chip_and_handler(i, &combiner_chip, handle_level_irq);
-		irq_set_chip_data(i, &combiner_data[combiner_nr]);
-		set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
+void __init combiner_init(void __iomem *combiner_base, struct device_node *np)
+{
+	int i, irq_base;
+	int nr_irq = MAX_COMBINER_NR * MAX_IRQ_IN_COMBINER;
+
+	irq_base = irq_alloc_descs(COMBINER_IRQ(0, 0), 1, nr_irq, 0);
+	if (IS_ERR_VALUE(irq_base)) {
+		irq_base = COMBINER_IRQ(0, 0);
+		pr_warning("combiner_init_irq_domain: irq desc alloc failed. "
+			"Continuing with %d as linux irq base\n", irq_base);
+	}
+
+	combiner_irq_domain = irq_domain_add_legacy(np, nr_irq, irq_base, 0,
+				&combiner_irq_domain_ops, &combiner_data);
+	if (WARN_ON(!combiner_irq_domain)) {
+		pr_warning("combiner_init_irq_domain: irq domain init failed\n");
+		return;
+	}
+
+	for (i = 0; i < MAX_COMBINER_NR; i++) {
+		combiner_init_one(i, combiner_base + (i >> 2) * 0x10);
+		combiner_cascade_irq(i, IRQ_SPI(i));
 	}
 }
 
@@ -388,7 +419,6 @@ static const struct of_device_id exynos4_dt_irq_match[] = {
 
 void __init exynos4_init_irq(void)
 {
-	int irq;
 	unsigned int gic_bank_offset;
 
 	gic_bank_offset = soc_is_exynos4412() ? 0x4000 : 0x8000;
@@ -400,12 +430,7 @@ void __init exynos4_init_irq(void)
 		of_irq_init(exynos4_dt_irq_match);
 #endif
 
-	for (irq = 0; irq < MAX_COMBINER_NR; irq++) {
-
-		combiner_init(irq, (void __iomem *)S5P_VA_COMBINER(irq),
-				COMBINER_IRQ(irq, 0));
-		combiner_cascade_irq(irq, IRQ_SPI(irq));
-	}
+	combiner_init(S5P_VA_COMBINER_BASE, NULL);
 
 	/*
 	 * The parameters of s5p_init_irq() are for VIC init.
Signature · 1 line
1.6.6.rc2
#2 lore raw

PATCH v4 2/2 ARM: Exynos: Add device tree support for interrupt combiner

In reply to Thomas Abraham

Add device tree based instantiation of the interrupt combiner controller.

Cc Grant Likely <[email protected]>
Cc Rob Herring <[email protected]>
---
 .../bindings/arm/samsung/interrupt-combiner.txt    |   48 ++++++++++++++++++
 arch/arm/mach-exynos/common.c                      |   53 ++++++++++++++++++-
 2 files changed, 98 insertions(+), 3 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/samsung/interrupt-combiner.txt
Documentation/devicetree/bindings/arm/samsung/interrupt-combiner.txt new file +48 -0
new file mode 100644
index 0000000..2a57211
@@ -0,0 +1,48 @@
+* Samsung Exynos Interrupt Combiner Controller
+
+Samsung's Exynos4 architecture includes a interrupt combiner controller 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, such as GIC in case of Exynos4210.
+
+The interrupt combiner controller consists of multiple combiners. Upto eight
+interrupt sources can be connected to a combiner. The combiner outputs one
+combined interrupt for its eight interrupt sources. The combined interrupt
+is usually connected to a parent interrupt controller.
+
+A single node in the device tree is used to describe the interrupt combiner
+controller module (which includes multiple combiners). A combiner in the
+interrupt controller module shares config/control registers with other
+combiners. For example, a 32-bit interrupt enable/disable config register
+can accommodate upto 4 interrupt combiners (with each combiner supporting
+upto 8 interrupt sources).
+
+Required properties:
+- compatible: should be "samsung,exynos4210-combiner".
+- interrupt-controller: Identifies the node as an interrupt controller.
+- #interrupt-cells: should be <2>. The meaning of the cells are
+	* First Cell: Combiner Group Number.
+	* Second Cell: Interrupt number within the group.
+- reg: Base address and size of interrupt combiner registers.
+- interrupts: The list of interrupts generated by the combiners which are then
+    connected to a parent interrupt controller. The format of the interrupt
+    specifier depends in the interrupt parent controller.
+
+Optional properties:
+- interrupt-parent: pHandle of the parent interrupt controller, if not
+  inherited from the parent node.
+
+Example:
+
+	The following is a an example from the Exynos4210 SoC dtsi file.
+
+	combiner:interrupt-controller@10440000 {
+		compatible = "samsung,exynos4210-combiner";
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		reg = <0x10440000 0x1000>;
+		interrupts = <0 0 0>, <0 1 0>, <0 2 0>, <0 3 0>,
+			     <0 4 0>, <0 5 0>, <0 6 0>, <0 7 0>,
+			     <0 8 0>, <0 9 0>, <0 10 0>, <0 11 0>,
+			     <0 12 0>, <0 13 0>, <0 14 0>, <0 15 0>;
+	};
arch/arm/mach-exynos/common.c +50 -3

94 lines not on this page · raw message

Signature · 1 line
1.6.6.rc2
#3 lore raw

PATCH v4 2/2 ARM: Exynos: Add device tree support for interrupt combiner

Quoted 7 lines · Thomas Abraham

Add device tree based instantiation of the interrupt combiner controller.

Cc Grant Likely <[email protected]>
Cc Rob Herring <[email protected]>

---

arch/arm/mach-exynos/common.c void __init combiner_init(void __iomem *combiner_base, struct device_node *np) · line 439

Quoted 9 lines
arch/arm/mach-exynos/common.c +5 -1
@@ -406,13 +432,33 @@ void __init combiner_init(void __iomem *combiner_base, struct device_node *np)
 
 	for (i = 0; i < MAX_COMBINER_NR; i++) {
 		combiner_init_one(i, combiner_base + (i >> 2) * 0x10);
-		combiner_cascade_irq(i, IRQ_SPI(i));
+#ifdef CONFIG_OF
+		irq = np ? irq_of_parse_and_map(np, i) : IRQ_SPI(i);
+#else
+		irq = IRQ_SPI(i);
+#endif

Hmmm, the #ifdef is rather ugly. I'd rather have an empty irq_of_parse_and_map() that always returns 0.

The patch series is fine, and you can add my acked-by, but please send a follow-up patch to clean it up.

#4 lore raw

PATCH v4 2/2 ARM: Exynos: Add device tree support for interrupt combiner

Quoted 21 lines · Grant Likely
Quoted 7 lines · Thomas Abraham

Add device tree based instantiation of the interrupt combiner controller.

Cc Grant Likely <[email protected]>
Cc Rob Herring <[email protected]>

---

Review void __init combiner_init(void __iomem *combiner_base, struct device_node *np) · line 439

Quoted 9 lines
(quoted diff) +5 -1
@@ -406,13 +432,33 @@ void __init combiner_init(void __iomem *combiner_base, struct device_node *np)
 
 ? ? ? for (i = 0; i < MAX_COMBINER_NR; i++) {
 ? ? ? ? ? ? ? combiner_init_one(i, combiner_base + (i >> 2) * 0x10);
- ? ? ? ? ? ? combiner_cascade_irq(i, IRQ_SPI(i));
+#ifdef CONFIG_OF
+ ? ? ? ? ? ? irq = np ? irq_of_parse_and_map(np, i) : IRQ_SPI(i);
+#else
+ ? ? ? ? ? ? irq = IRQ_SPI(i);
+#endif

Hmmm, the #ifdef is rather ugly. ?I'd rather have an empty irq_of_parse_and_map() that always returns 0.

Quoted 5 lines

The patch series is fine, and you can add my acked-by, but please send a follow-up patch to clean it up.

Thanks. I will send a follow-up to clean it.

Regards,
Thomas.

#5 lore raw

v4 cover ARM: Exynos: Add irq_domain and device tree support for combiner

In reply to Thomas Abraham

Hi Rob/Grant,

Quoted 29 lines · Thomas Abraham

Changes since v3:
- In dt case, the use of fixed gic linux irq number to map the combiner ?interrupt output is removed. This is replaced with the interrupt number ?obtained from the gic irq domain. (Thanks to Rob Herring and Grant ?Likely for this suggestion).
- Split the patch into two parts - irq_domain and device tree support ?addition.

Changes since v2:
- Rebased to Grant's irqdomain/next branch.

Changes since v1:
- Includes all changes suggested by Rob Herring.
- Tested with SPARSE_IRQ enabled.

This patchset adds irq_domain and device tree support for the Exynos Interrupt Combiner controller.

The first patch adds a common irq domain for the interrupts managed by the interrupt combiners. All the instances of irq combiner reference the common irq domain for translating hardware interrupts to linux irq number.

The second patch adds a interrupt specifier translator to support device tree based instantiation. It can translate interrupt specifiers for device nodes which use combiner as their interrupt parent.

This patchset is based on
http://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git [for-next]

Quoted 6 lines

with all irq_domain (v5) patches merged from
http://git.secretlab.ca/git/linux-2.6.git [irqdomain/next]

Thomas Abraham (2):
?ARM: Exynos: Add irq_domain support for interrupt combiner ?ARM: Exynos: Add device tree support for interrupt combiner

Any comments on this patch series? If it helps, I can repost this patch series. This patch series is a pre-requsite for the irq-domain and dt support for wakeup interrupts, which Rob has acked.

Thanks,
Thomas.

Quoted 11 lines

?.../bindings/arm/samsung/interrupt-combiner.txt ? ?| ? 48 +++++++++ ?arch/arm/mach-exynos/common.c ? ? ? ? ? ? ? ? ? ? ?| ?112 ++++++++++++++++---- ?2 files changed, 140 insertions(+), 20 deletions(-)
?create mode 100644 Documentation/devicetree/bindings/arm/samsung/interrupt-combiner.txt

--
To unsubscribe from this list: send the line "unsubscribe linux-samsung-soc" in the body of a message to majordomo at vger.kernel.org
More majordomo info at ?http://vger.kernel.org/majordomo-info.html

#6 lore raw

v4 cover ARM: Exynos: Add irq_domain and device tree support for combiner

In reply to Thomas Abraham
Quoted 32 lines · Thomas Abraham

Changes since v3:
- In dt case, the use of fixed gic linux irq number to map the combiner interrupt output is removed. This is replaced with the interrupt number obtained from the gic irq domain. (Thanks to Rob Herring and Grant Likely for this suggestion).
- Split the patch into two parts - irq_domain and device tree support addition.

Changes since v2:
- Rebased to Grant's irqdomain/next branch.

Changes since v1:
- Includes all changes suggested by Rob Herring.
- Tested with SPARSE_IRQ enabled.

This patchset adds irq_domain and device tree support for the Exynos Interrupt Combiner controller.

The first patch adds a common irq domain for the interrupts managed by the interrupt combiners. All the instances of irq combiner reference the common irq domain for translating hardware interrupts to linux irq number.

The second patch adds a interrupt specifier translator to support device tree based instantiation. It can translate interrupt specifiers for device nodes which use combiner as their interrupt parent.

This patchset is based on
http://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git [for-next]

with all irq_domain (v5) patches merged from
http://git.secretlab.ca/git/linux-2.6.git [irqdomain/next]

Quoted 8 lines

Thomas Abraham (2):
ARM: Exynos: Add irq_domain support for interrupt combiner
ARM: Exynos: Add device tree support for interrupt combiner

 .../bindings/arm/samsung/interrupt-combiner.txt    |   48 +++++++++
 arch/arm/mach-exynos/common.c                      |  112 ++++++++++++++++----
 2 files changed, 140 insertions(+), 20 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/samsung/interrupt-combiner.txt

Rob