diff options
| author | Grant Likely <grant.likely@linaro.org> | 2013-09-19 17:47:37 -0400 |
|---|---|---|
| committer | Grant Likely <grant.likely@linaro.org> | 2013-10-28 19:48:14 -0400 |
| commit | 79d9701559a9f3e9b2021fbd292f5e70ad75f686 (patch) | |
| tree | bbbcc05e19c73ffe9f6a5b71c8c45c5e051c2747 /drivers/of | |
| parent | f27446c3ad5b6d3b5b28ec0176e23d3ceca595d8 (diff) | |
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>
Diffstat (limited to 'drivers/of')
| -rw-r--r-- | drivers/of/irq.c | 16 | ||||
| -rw-r--r-- | drivers/of/selftest.c | 70 |
2 files changed, 81 insertions, 5 deletions
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 | |||
| 292 | if (of_irq_workarounds & OF_IMAP_OLDWORLD_MAC) | 292 | if (of_irq_workarounds & OF_IMAP_OLDWORLD_MAC) |
| 293 | return of_irq_parse_oldworld(device, index, out_irq); | 293 | return of_irq_parse_oldworld(device, index, out_irq); |
| 294 | 294 | ||
| 295 | /* Get the reg property (if any) */ | ||
| 296 | addr = of_get_property(device, "reg", NULL); | ||
| 297 | |||
| 295 | /* Get the interrupts property */ | 298 | /* Get the interrupts property */ |
| 296 | intspec = of_get_property(device, "interrupts", &intlen); | 299 | intspec = of_get_property(device, "interrupts", &intlen); |
| 297 | if (intspec == NULL) | 300 | if (intspec == NULL) { |
| 298 | return -EINVAL; | 301 | /* Try the new-style interrupts-extended */ |
| 302 | res = of_parse_phandle_with_args(device, "interrupts-extended", | ||
| 303 | "#interrupt-cells", index, out_irq); | ||
| 304 | if (res) | ||
| 305 | return -EINVAL; | ||
| 306 | return of_irq_parse_raw(addr, out_irq); | ||
| 307 | } | ||
| 299 | intlen /= sizeof(*intspec); | 308 | intlen /= sizeof(*intspec); |
| 300 | 309 | ||
| 301 | pr_debug(" intspec=%d intlen=%d\n", be32_to_cpup(intspec), intlen); | 310 | pr_debug(" intspec=%d intlen=%d\n", be32_to_cpup(intspec), intlen); |
| 302 | 311 | ||
| 303 | /* Get the reg property (if any) */ | ||
| 304 | addr = of_get_property(device, "reg", NULL); | ||
| 305 | |||
| 306 | /* Look for the interrupt parent. */ | 312 | /* Look for the interrupt parent. */ |
| 307 | p = of_irq_find_parent(device); | 313 | p = of_irq_find_parent(device); |
| 308 | if (p == NULL) | 314 | 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) | |||
| 231 | of_node_put(np); | 231 | of_node_put(np); |
| 232 | } | 232 | } |
| 233 | 233 | ||
| 234 | static void __init of_selftest_parse_interrupts_extended(void) | ||
| 235 | { | ||
| 236 | struct device_node *np; | ||
| 237 | struct of_phandle_args args; | ||
| 238 | int i, rc; | ||
| 239 | |||
| 240 | np = of_find_node_by_path("/testcase-data/interrupts/interrupts-extended0"); | ||
| 241 | if (!np) { | ||
| 242 | pr_err("missing testcase data\n"); | ||
| 243 | return; | ||
| 244 | } | ||
| 245 | |||
| 246 | for (i = 0; i < 7; i++) { | ||
| 247 | bool passed = true; | ||
| 248 | rc = of_irq_parse_one(np, i, &args); | ||
| 249 | |||
| 250 | /* Test the values from tests-phandle.dtsi */ | ||
| 251 | switch (i) { | ||
| 252 | case 0: | ||
| 253 | passed &= !rc; | ||
| 254 | passed &= (args.args_count == 1); | ||
| 255 | passed &= (args.args[0] == 1); | ||
| 256 | break; | ||
| 257 | case 1: | ||
| 258 | passed &= !rc; | ||
| 259 | passed &= (args.args_count == 3); | ||
| 260 | passed &= (args.args[0] == 2); | ||
| 261 | passed &= (args.args[1] == 3); | ||
| 262 | passed &= (args.args[2] == 4); | ||
| 263 | break; | ||
| 264 | case 2: | ||
| 265 | passed &= !rc; | ||
| 266 | passed &= (args.args_count == 2); | ||
| 267 | passed &= (args.args[0] == 5); | ||
| 268 | passed &= (args.args[1] == 6); | ||
| 269 | break; | ||
| 270 | case 3: | ||
| 271 | passed &= !rc; | ||
| 272 | passed &= (args.args_count == 1); | ||
| 273 | passed &= (args.args[0] == 9); | ||
| 274 | break; | ||
| 275 | case 4: | ||
| 276 | passed &= !rc; | ||
| 277 | passed &= (args.args_count == 3); | ||
| 278 | passed &= (args.args[0] == 10); | ||
| 279 | passed &= (args.args[1] == 11); | ||
| 280 | passed &= (args.args[2] == 12); | ||
| 281 | break; | ||
| 282 | case 5: | ||
| 283 | passed &= !rc; | ||
| 284 | passed &= (args.args_count == 2); | ||
| 285 | passed &= (args.args[0] == 13); | ||
| 286 | passed &= (args.args[1] == 14); | ||
| 287 | break; | ||
| 288 | case 6: | ||
| 289 | passed &= !rc; | ||
| 290 | passed &= (args.args_count == 1); | ||
| 291 | passed &= (args.args[0] == 15); | ||
| 292 | break; | ||
| 293 | default: | ||
| 294 | passed = false; | ||
| 295 | } | ||
| 296 | |||
| 297 | selftest(passed, "index %i - data error on node %s rc=%i\n", | ||
| 298 | i, args.np->full_name, rc); | ||
| 299 | } | ||
| 300 | of_node_put(np); | ||
| 301 | } | ||
| 302 | |||
| 234 | static int __init of_selftest(void) | 303 | static int __init of_selftest(void) |
| 235 | { | 304 | { |
| 236 | struct device_node *np; | 305 | struct device_node *np; |
| @@ -246,6 +315,7 @@ static int __init of_selftest(void) | |||
| 246 | of_selftest_parse_phandle_with_args(); | 315 | of_selftest_parse_phandle_with_args(); |
| 247 | of_selftest_property_match_string(); | 316 | of_selftest_property_match_string(); |
| 248 | of_selftest_parse_interrupts(); | 317 | of_selftest_parse_interrupts(); |
| 318 | of_selftest_parse_interrupts_extended(); | ||
| 249 | pr_info("end of selftest - %i passed, %i failed\n", | 319 | pr_info("end of selftest - %i passed, %i failed\n", |
| 250 | selftest_results.passed, selftest_results.failed); | 320 | selftest_results.passed, selftest_results.failed); |
| 251 | return 0; | 321 | return 0; |
