From a9f10ca76d784023fc45f01f025b54e9960f4ec1 Mon Sep 17 00:00:00 2001
From: Grant Likely <grant.likely@linaro.org>
Date: Fri, 11 Oct 2013 22:04:23 +0100
Subject: of: Add testcases for interrupt parsing

This patch extends the DT selftest code with some test cases for the
interrupt parsing functions.

Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
---
 arch/arm/boot/dts/testcases/tests-interrupts.dtsi | 41 +++++++++++++++++++++++
 arch/arm/boot/dts/testcases/tests.dtsi            |  1 +
 2 files changed, 42 insertions(+)
 create mode 100644 arch/arm/boot/dts/testcases/tests-interrupts.dtsi

(limited to 'arch/arm/boot')

diff --git a/arch/arm/boot/dts/testcases/tests-interrupts.dtsi b/arch/arm/boot/dts/testcases/tests-interrupts.dtsi
new file mode 100644
index 000000000000..6ecda716e9d4
--- /dev/null
+++ b/arch/arm/boot/dts/testcases/tests-interrupts.dtsi
@@ -0,0 +1,41 @@
+
+/ {
+	testcase-data {
+		interrupts {
+			#address-cells = <0>;
+			test_intc0: intc0 {
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+
+			test_intc1: intc1 {
+				interrupt-controller;
+				#interrupt-cells = <3>;
+			};
+
+			test_intc2: intc2 {
+				interrupt-controller;
+				#interrupt-cells = <2>;
+			};
+
+			test_intmap0: intmap0 {
+				#interrupt-cells = <1>;
+				#address-cells = <0>;
+				interrupt-map = <1 &test_intc0 9>,
+						<2 &test_intc1 10 11 12>,
+						<3 &test_intc2 13 14>,
+						<4 &test_intc2 15 16>;
+			};
+
+			interrupts0 {
+				interrupt-parent = <&test_intc0>;
+				interrupts = <1>, <2>, <3>, <4>;
+			};
+
+			interrupts1 {
+				interrupt-parent = <&test_intmap0>;
+				interrupts = <1>, <2>, <3>, <4>;
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/testcases/tests.dtsi b/arch/arm/boot/dts/testcases/tests.dtsi
index a7c5067622e8..3f123ecc9dd7 100644
--- a/arch/arm/boot/dts/testcases/tests.dtsi
+++ b/arch/arm/boot/dts/testcases/tests.dtsi
@@ -1 +1,2 @@
 /include/ "tests-phandle.dtsi"
+/include/ "tests-interrupts.dtsi"
-- 
cgit v1.2.3


From 79d9701559a9f3e9b2021fbd292f5e70ad75f686 Mon Sep 17 00:00:00 2001
From: Grant Likely <grant.likely@linaro.org>
Date: Thu, 19 Sep 2013 16:47:37 -0500
Subject: of/irq: create interrupts-extended property

The standard interrupts property in device tree can only handle
interrupts coming from a single interrupt parent. If a device is wired
to multiple interrupt controllers, then it needs to be attached to a
node with an interrupt-map property to demux the interrupt specifiers
which is confusing. It would be a lot easier if there was a form of the
interrupts property that allows for a separate interrupt phandle for
each interrupt specifier.

This patch does exactly that by creating a new interrupts-extended
property which reuses the phandle+arguments pattern used by GPIOs and
other core bindings.

Signed-off-by: Grant Likely <grant.likely@linaro.org>
Acked-by: Tony Lindgren <tony@atomide.com>
Acked-by: Kumar Gala <galak@codeaurora.org>
[grant.likely: removed versatile platform hunks into separate patch]
Cc: Rob Herring <rob.herring@calxeda.com>
---
 .../bindings/interrupt-controller/interrupts.txt   | 29 +++++++--
 arch/arm/boot/dts/testcases/tests-interrupts.dtsi  | 16 +++++
 drivers/of/irq.c                                   | 16 +++--
 drivers/of/selftest.c                              | 70 ++++++++++++++++++++++
 4 files changed, 120 insertions(+), 11 deletions(-)

(limited to 'arch/arm/boot')

diff --git a/Documentation/devicetree/bindings/interrupt-controller/interrupts.txt b/Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
index 72a06c0ab1db..1486497a24c1 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
+++ b/Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
@@ -4,16 +4,33 @@ Specifying interrupt information for devices
 1) Interrupt client nodes
 -------------------------
 
-Nodes that describe devices which generate interrupts must contain an
-"interrupts" property. This property must contain a list of interrupt
-specifiers, one per output interrupt. The format of the interrupt specifier is
-determined by the interrupt controller to which the interrupts are routed; see
-section 2 below for details.
+Nodes that describe devices which generate interrupts must contain an either an
+"interrupts" property or an "interrupts-extended" property. These properties
+contain a list of interrupt specifiers, one per output interrupt. The format of
+the interrupt specifier is determined by the interrupt controller to which the
+interrupts are routed; see section 2 below for details.
+
+  Example:
+	interrupt-parent = <&intc1>;
+	interrupts = <5 0>, <6 0>;
 
 The "interrupt-parent" property is used to specify the controller to which
 interrupts are routed and contains a single phandle referring to the interrupt
 controller node. This property is inherited, so it may be specified in an
-interrupt client node or in any of its parent nodes.
+interrupt client node or in any of its parent nodes. Interrupts listed in the
+"interrupts" property are always in reference to the node's interrupt parent.
+
+The "interrupts-extended" property is a special form for use when a node needs
+to reference multiple interrupt parents. Each entry in this property contains
+both the parent phandle and the interrupt specifier. "interrupts-extended"
+should only be used when a device has multiple interrupt parents.
+
+  Example:
+	interrupts-extended = <&intc1 5 1>, <&intc2 1 0>;
+
+A device node may contain either "interrupts" or "interrupts-extended", but not
+both. If both properties are present, then the operating system should log an
+error and use only the data in "interrupts".
 
 2) Interrupt controller nodes
 -----------------------------
diff --git a/arch/arm/boot/dts/testcases/tests-interrupts.dtsi b/arch/arm/boot/dts/testcases/tests-interrupts.dtsi
index 6ecda716e9d4..560d6bf680b6 100644
--- a/arch/arm/boot/dts/testcases/tests-interrupts.dtsi
+++ b/arch/arm/boot/dts/testcases/tests-interrupts.dtsi
@@ -27,6 +27,12 @@
 						<4 &test_intc2 15 16>;
 			};
 
+			test_intmap1: intmap1 {
+				#interrupt-cells = <2>;
+				#address-cells = <0>;
+				interrupt-map = <1 2 &test_intc0 15>;
+			};
+
 			interrupts0 {
 				interrupt-parent = <&test_intc0>;
 				interrupts = <1>, <2>, <3>, <4>;
@@ -36,6 +42,16 @@
 				interrupt-parent = <&test_intmap0>;
 				interrupts = <1>, <2>, <3>, <4>;
 			};
+
+			interrupts-extended0 {
+				interrupts-extended = <&test_intc0 1>,
+						      <&test_intc1 2 3 4>,
+						      <&test_intc2 5 6>,
+						      <&test_intmap0 1>,
+						      <&test_intmap0 2>,
+						      <&test_intmap0 3>,
+						      <&test_intmap1 1 2>;
+			};
 		};
 	};
 };
diff --git a/drivers/of/irq.c b/drivers/of/irq.c
index 7c4ff122785f..8cc62b4a7988 100644
--- a/drivers/of/irq.c
+++ b/drivers/of/irq.c
@@ -292,17 +292,23 @@ int of_irq_parse_one(struct device_node *device, int index, struct of_phandle_ar
 	if (of_irq_workarounds & OF_IMAP_OLDWORLD_MAC)
 		return of_irq_parse_oldworld(device, index, out_irq);
 
+	/* Get the reg property (if any) */
+	addr = of_get_property(device, "reg", NULL);
+
 	/* Get the interrupts property */
 	intspec = of_get_property(device, "interrupts", &intlen);
-	if (intspec == NULL)
-		return -EINVAL;
+	if (intspec == NULL) {
+		/* Try the new-style interrupts-extended */
+		res = of_parse_phandle_with_args(device, "interrupts-extended",
+						"#interrupt-cells", index, out_irq);
+		if (res)
+			return -EINVAL;
+		return of_irq_parse_raw(addr, out_irq);
+	}
 	intlen /= sizeof(*intspec);
 
 	pr_debug(" intspec=%d intlen=%d\n", be32_to_cpup(intspec), intlen);
 
-	/* Get the reg property (if any) */
-	addr = of_get_property(device, "reg", NULL);
-
 	/* Look for the interrupt parent. */
 	p = of_irq_find_parent(device);
 	if (p == NULL)
diff --git a/drivers/of/selftest.c b/drivers/of/selftest.c
index 9c80f0b7556b..e21012bde639 100644
--- a/drivers/of/selftest.c
+++ b/drivers/of/selftest.c
@@ -231,6 +231,75 @@ static void __init of_selftest_parse_interrupts(void)
 	of_node_put(np);
 }
 
+static void __init of_selftest_parse_interrupts_extended(void)
+{
+	struct device_node *np;
+	struct of_phandle_args args;
+	int i, rc;
+
+	np = of_find_node_by_path("/testcase-data/interrupts/interrupts-extended0");
+	if (!np) {
+		pr_err("missing testcase data\n");
+		return;
+	}
+
+	for (i = 0; i < 7; i++) {
+		bool passed = true;
+		rc = of_irq_parse_one(np, i, &args);
+
+		/* Test the values from tests-phandle.dtsi */
+		switch (i) {
+		case 0:
+			passed &= !rc;
+			passed &= (args.args_count == 1);
+			passed &= (args.args[0] == 1);
+			break;
+		case 1:
+			passed &= !rc;
+			passed &= (args.args_count == 3);
+			passed &= (args.args[0] == 2);
+			passed &= (args.args[1] == 3);
+			passed &= (args.args[2] == 4);
+			break;
+		case 2:
+			passed &= !rc;
+			passed &= (args.args_count == 2);
+			passed &= (args.args[0] == 5);
+			passed &= (args.args[1] == 6);
+			break;
+		case 3:
+			passed &= !rc;
+			passed &= (args.args_count == 1);
+			passed &= (args.args[0] == 9);
+			break;
+		case 4:
+			passed &= !rc;
+			passed &= (args.args_count == 3);
+			passed &= (args.args[0] == 10);
+			passed &= (args.args[1] == 11);
+			passed &= (args.args[2] == 12);
+			break;
+		case 5:
+			passed &= !rc;
+			passed &= (args.args_count == 2);
+			passed &= (args.args[0] == 13);
+			passed &= (args.args[1] == 14);
+			break;
+		case 6:
+			passed &= !rc;
+			passed &= (args.args_count == 1);
+			passed &= (args.args[0] == 15);
+			break;
+		default:
+			passed = false;
+		}
+
+		selftest(passed, "index %i - data error on node %s rc=%i\n",
+			 i, args.np->full_name, rc);
+	}
+	of_node_put(np);
+}
+
 static int __init of_selftest(void)
 {
 	struct device_node *np;
@@ -246,6 +315,7 @@ static int __init of_selftest(void)
 	of_selftest_parse_phandle_with_args();
 	of_selftest_property_match_string();
 	of_selftest_parse_interrupts();
+	of_selftest_parse_interrupts_extended();
 	pr_info("end of selftest - %i passed, %i failed\n",
 		selftest_results.passed, selftest_results.failed);
 	return 0;
-- 
cgit v1.2.3


From 0976c946a610d06e907335b7a3afa6db046f8e1b Mon Sep 17 00:00:00 2001
From: Grant Likely <grant.likely@linaro.org>
Date: Mon, 28 Oct 2013 16:50:11 -0700
Subject: arm/versatile: Fix versatile irq specifications.

Two of the versatile irq definitions are incorrect, mostly because two
devices have connections to more than one interrupt controller. Fix them
by using the new interrupts-extended property to fan out without using
an awful interrupt-map nexus node.

Signed-off-by: Grant Likely <grant.likely@linaro.org>
---
 arch/arm/boot/dts/versatile-ab.dts | 2 +-
 arch/arm/boot/dts/versatile-pb.dts | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

(limited to 'arch/arm/boot')

diff --git a/arch/arm/boot/dts/versatile-ab.dts b/arch/arm/boot/dts/versatile-ab.dts
index dde75ae8b4b1..e01e5a081def 100644
--- a/arch/arm/boot/dts/versatile-ab.dts
+++ b/arch/arm/boot/dts/versatile-ab.dts
@@ -185,7 +185,7 @@
 			mmc@5000 {
 				compatible = "arm,primecell";
 				reg = < 0x5000 0x1000>;
-				interrupts = <22 34>;
+				interrupts-extended = <&vic 22 &sic 2>;
 			};
 			kmi@6000 {
 				compatible = "arm,pl050", "arm,primecell";
diff --git a/arch/arm/boot/dts/versatile-pb.dts b/arch/arm/boot/dts/versatile-pb.dts
index 7e8175269064..f43907c40c93 100644
--- a/arch/arm/boot/dts/versatile-pb.dts
+++ b/arch/arm/boot/dts/versatile-pb.dts
@@ -41,7 +41,7 @@
 			mmc@b000 {
 				compatible = "arm,primecell";
 				reg = <0xb000 0x1000>;
-				interrupts = <23 34>;
+				interrupts-extended = <&vic 23 &sic 2>;
 			};
 		};
 	};
-- 
cgit v1.2.3


From 78119fd1068cc068f6112a57a5f6de0e5b20245a Mon Sep 17 00:00:00 2001
From: Grant Likely <grant.likely@linaro.org>
Date: Fri, 1 Nov 2013 10:50:50 -0700
Subject: of/irq: Fix bug in interrupt parsing refactor.

Commit 2361613206e6, "of/irq: Refactor interrupt-map parsing" introduced
a bug. The irq parsing will fail for some nodes that don't have a reg
property. It is fixed by deferring the check for reg until it is
actually needed. Also adjust the testcase data to catch the bug.

Signed-off-by: Grant Likely <grant.likely@linaro.org>
Tested-by: Stephen Warren <swarren@nvidia.com>
Tested-by: Ming Lei <tom.leiming@gmail.com>
Tested-by: Stephen Warren <swarren@nvidia.com>
Cc: Rob Herring <rob.herring@calxeda.com>
---
 arch/arm/boot/dts/testcases/tests-interrupts.dtsi |  7 ++++---
 drivers/of/irq.c                                  | 20 ++++++++++----------
 2 files changed, 14 insertions(+), 13 deletions(-)

(limited to 'arch/arm/boot')

diff --git a/arch/arm/boot/dts/testcases/tests-interrupts.dtsi b/arch/arm/boot/dts/testcases/tests-interrupts.dtsi
index 560d6bf680b6..c843720bd3e5 100644
--- a/arch/arm/boot/dts/testcases/tests-interrupts.dtsi
+++ b/arch/arm/boot/dts/testcases/tests-interrupts.dtsi
@@ -2,7 +2,8 @@
 / {
 	testcase-data {
 		interrupts {
-			#address-cells = <0>;
+			#address-cells = <1>;
+			#size-cells = <1>;
 			test_intc0: intc0 {
 				interrupt-controller;
 				#interrupt-cells = <1>;
@@ -29,8 +30,7 @@
 
 			test_intmap1: intmap1 {
 				#interrupt-cells = <2>;
-				#address-cells = <0>;
-				interrupt-map = <1 2 &test_intc0 15>;
+				interrupt-map = <0x5000 1 2 &test_intc0 15>;
 			};
 
 			interrupts0 {
@@ -44,6 +44,7 @@
 			};
 
 			interrupts-extended0 {
+				reg = <0x5000 0x100>;
 				interrupts-extended = <&test_intc0 1>,
 						      <&test_intc1 2 3 4>,
 						      <&test_intc2 5 6>,
diff --git a/drivers/of/irq.c b/drivers/of/irq.c
index 8cc62b4a7988..52dba6a01423 100644
--- a/drivers/of/irq.c
+++ b/drivers/of/irq.c
@@ -147,18 +147,9 @@ int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq)
 
 	pr_debug(" -> addrsize=%d\n", addrsize);
 
-	/* If we were passed no "reg" property and we attempt to parse
-	 * an interrupt-map, then #address-cells must be 0.
-	 * Fail if it's not.
-	 */
-	if (addr == NULL && addrsize != 0) {
-		pr_debug(" -> no reg passed in when needed !\n");
-		return -EINVAL;
-	}
-
 	/* Precalculate the match array - this simplifies match loop */
 	for (i = 0; i < addrsize; i++)
-		initial_match_array[i] = addr[i];
+		initial_match_array[i] = addr ? addr[i] : 0;
 	for (i = 0; i < intsize; i++)
 		initial_match_array[addrsize + i] = cpu_to_be32(out_irq->args[i]);
 
@@ -174,6 +165,15 @@ int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq)
 			return 0;
 		}
 
+		/*
+		 * interrupt-map parsing does not work without a reg
+		 * property when #address-cells != 0
+		 */
+		if (addrsize && !addr) {
+			pr_debug(" -> no reg passed in when needed !\n");
+			goto fail;
+		}
+
 		/* Now look for an interrupt-map */
 		imap = of_get_property(ipar, "interrupt-map", &imaplen);
 		/* No interrupt map, check for an interrupt parent */
-- 
cgit v1.2.3