193 lines
5.2 KiB
Diff
193 lines
5.2 KiB
Diff
From efd4032754a57bc258eafe30fde684ec47dc36e1 Mon Sep 17 00:00:00 2001
|
|
From: Grant Likely <grant.likely@linaro.org>
|
|
Date: Thu, 19 Dec 2013 09:31:00 -0300
|
|
Subject: [PATCH 189/203] 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>
|
|
|
|
Conflicts:
|
|
arch/arm/boot/dts/testcases/tests-interrupts.dtsi
|
|
drivers/of/selftest.c
|
|
---
|
|
drivers/of/selftest.c | 146 +++++++++++++++++++++++++++++++++++++++++++++++++-
|
|
1 file changed, 145 insertions(+), 1 deletion(-)
|
|
|
|
--- a/drivers/of/selftest.c
|
|
+++ b/drivers/of/selftest.c
|
|
@@ -154,6 +154,147 @@ static void __init of_selftest_property_
|
|
selftest(rc == -EILSEQ, "unterminated string; rc=%i", rc);
|
|
}
|
|
|
|
+static void __init of_selftest_parse_interrupts(void)
|
|
+{
|
|
+ struct device_node *np;
|
|
+ struct of_phandle_args args;
|
|
+ int i, rc;
|
|
+
|
|
+ np = of_find_node_by_path("/testcase-data/interrupts/interrupts0");
|
|
+ if (!np) {
|
|
+ pr_err("missing testcase data\n");
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ for (i = 0; i < 4; i++) {
|
|
+ bool passed = true;
|
|
+ args.args_count = 0;
|
|
+ rc = of_irq_parse_one(np, i, &args);
|
|
+
|
|
+ passed &= !rc;
|
|
+ passed &= (args.args_count == 1);
|
|
+ passed &= (args.args[0] == (i + 1));
|
|
+
|
|
+ selftest(passed, "index %i - data error on node %s rc=%i\n",
|
|
+ i, args.np->full_name, rc);
|
|
+ }
|
|
+ of_node_put(np);
|
|
+
|
|
+ np = of_find_node_by_path("/testcase-data/interrupts/interrupts1");
|
|
+ if (!np) {
|
|
+ pr_err("missing testcase data\n");
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ for (i = 0; i < 4; i++) {
|
|
+ bool passed = true;
|
|
+ args.args_count = 0;
|
|
+ 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] == 9);
|
|
+ break;
|
|
+ case 1:
|
|
+ passed &= !rc;
|
|
+ passed &= (args.args_count == 3);
|
|
+ passed &= (args.args[0] == 10);
|
|
+ passed &= (args.args[1] == 11);
|
|
+ passed &= (args.args[2] == 12);
|
|
+ break;
|
|
+ case 2:
|
|
+ passed &= !rc;
|
|
+ passed &= (args.args_count == 2);
|
|
+ passed &= (args.args[0] == 13);
|
|
+ passed &= (args.args[1] == 14);
|
|
+ break;
|
|
+ case 3:
|
|
+ passed &= !rc;
|
|
+ passed &= (args.args_count == 2);
|
|
+ passed &= (args.args[0] == 15);
|
|
+ passed &= (args.args[1] == 16);
|
|
+ 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 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;
|
|
@@ -168,7 +309,10 @@ static int __init of_selftest(void)
|
|
pr_info("start of selftest - you will see error messages\n");
|
|
of_selftest_parse_phandle_with_args();
|
|
of_selftest_property_match_string();
|
|
- pr_info("end of selftest - %s\n", selftest_passed ? "PASS" : "FAIL");
|
|
+ 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;
|
|
}
|
|
late_initcall(of_selftest);
|