diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-08-19 10:43:48 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-08-19 10:43:48 -0400 |
commit | 7ac0bbf99d44c827c88aa7a9064050526e723ebb (patch) | |
tree | 40fa86f2044b419380f4f50d1aadffa41100222e | |
parent | f325f1643abca9fac5b8e04e9faa46effc984a61 (diff) | |
parent | a9ecdc0fdc54aa499604dbd43132988effcac9b4 (diff) |
Merge tag 'devicetree-for-linus' of git://git.secretlab.ca/git/linux
Pull devicetree fixes from Grant Likely:
"Three more commits needed for v3.17: A bug fix for reserved regions
based at address zero, a clarification on how to interpret existence
of both interrupts and interrupts-extended properties, and a fix to
allow device tree testcases to run on any platform"
* tag 'devicetree-for-linus' of git://git.secretlab.ca/git/linux:
of/irq: Fix lookup to use 'interrupts-extended' property first
Enabling OF selftest to run without machine's devicetree
of: Allow mem_reserve of memory with a base address of zero
-rw-r--r-- | Documentation/devicetree/bindings/interrupt-controller/interrupts.txt | 12 | ||||
-rw-r--r-- | drivers/of/fdt.c | 2 | ||||
-rw-r--r-- | drivers/of/irq.c | 17 | ||||
-rw-r--r-- | drivers/of/selftest.c | 40 |
4 files changed, 48 insertions, 23 deletions
diff --git a/Documentation/devicetree/bindings/interrupt-controller/interrupts.txt b/Documentation/devicetree/bindings/interrupt-controller/interrupts.txt index 1486497a24c1..ce6a1a072028 100644 --- a/Documentation/devicetree/bindings/interrupt-controller/interrupts.txt +++ b/Documentation/devicetree/bindings/interrupt-controller/interrupts.txt | |||
@@ -4,11 +4,13 @@ Specifying interrupt information for devices | |||
4 | 1) Interrupt client nodes | 4 | 1) Interrupt client nodes |
5 | ------------------------- | 5 | ------------------------- |
6 | 6 | ||
7 | Nodes that describe devices which generate interrupts must contain an either an | 7 | Nodes that describe devices which generate interrupts must contain an |
8 | "interrupts" property or an "interrupts-extended" property. These properties | 8 | "interrupts" property, an "interrupts-extended" property, or both. If both are |
9 | contain a list of interrupt specifiers, one per output interrupt. The format of | 9 | present, the latter should take precedence; the former may be provided simply |
10 | the interrupt specifier is determined by the interrupt controller to which the | 10 | for compatibility with software that does not recognize the latter. These |
11 | interrupts are routed; see section 2 below for details. | 11 | properties contain a list of interrupt specifiers, one per output interrupt. The |
12 | format of the interrupt specifier is determined by the interrupt controller to | ||
13 | which the interrupts are routed; see section 2 below for details. | ||
12 | 14 | ||
13 | Example: | 15 | Example: |
14 | interrupt-parent = <&intc1>; | 16 | interrupt-parent = <&intc1>; |
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index f46a24ffa3fe..79cb8313c7d8 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c | |||
@@ -453,7 +453,7 @@ static int __init __reserved_mem_reserve_reg(unsigned long node, | |||
453 | base = dt_mem_next_cell(dt_root_addr_cells, &prop); | 453 | base = dt_mem_next_cell(dt_root_addr_cells, &prop); |
454 | size = dt_mem_next_cell(dt_root_size_cells, &prop); | 454 | size = dt_mem_next_cell(dt_root_size_cells, &prop); |
455 | 455 | ||
456 | if (base && size && | 456 | if (size && |
457 | early_init_dt_reserve_memory_arch(base, size, nomap) == 0) | 457 | early_init_dt_reserve_memory_arch(base, size, nomap) == 0) |
458 | pr_debug("Reserved memory: reserved region for node '%s': base %pa, size %ld MiB\n", | 458 | pr_debug("Reserved memory: reserved region for node '%s': base %pa, size %ld MiB\n", |
459 | uname, &base, (unsigned long)size / SZ_1M); | 459 | uname, &base, (unsigned long)size / SZ_1M); |
diff --git a/drivers/of/irq.c b/drivers/of/irq.c index 3e06a699352d..1471e0a223a5 100644 --- a/drivers/of/irq.c +++ b/drivers/of/irq.c | |||
@@ -301,16 +301,17 @@ int of_irq_parse_one(struct device_node *device, int index, struct of_phandle_ar | |||
301 | /* Get the reg property (if any) */ | 301 | /* Get the reg property (if any) */ |
302 | addr = of_get_property(device, "reg", NULL); | 302 | addr = of_get_property(device, "reg", NULL); |
303 | 303 | ||
304 | /* Try the new-style interrupts-extended first */ | ||
305 | res = of_parse_phandle_with_args(device, "interrupts-extended", | ||
306 | "#interrupt-cells", index, out_irq); | ||
307 | if (!res) | ||
308 | return of_irq_parse_raw(addr, out_irq); | ||
309 | |||
304 | /* Get the interrupts property */ | 310 | /* Get the interrupts property */ |
305 | intspec = of_get_property(device, "interrupts", &intlen); | 311 | intspec = of_get_property(device, "interrupts", &intlen); |
306 | if (intspec == NULL) { | 312 | if (intspec == NULL) |
307 | /* Try the new-style interrupts-extended */ | 313 | return -EINVAL; |
308 | res = of_parse_phandle_with_args(device, "interrupts-extended", | 314 | |
309 | "#interrupt-cells", index, out_irq); | ||
310 | if (res) | ||
311 | return -EINVAL; | ||
312 | return of_irq_parse_raw(addr, out_irq); | ||
313 | } | ||
314 | intlen /= sizeof(*intspec); | 315 | intlen /= sizeof(*intspec); |
315 | 316 | ||
316 | pr_debug(" intspec=%d intlen=%d\n", be32_to_cpup(intspec), intlen); | 317 | pr_debug(" intspec=%d intlen=%d\n", be32_to_cpup(intspec), intlen); |
diff --git a/drivers/of/selftest.c b/drivers/of/selftest.c index d41002667833..a737cb5974de 100644 --- a/drivers/of/selftest.c +++ b/drivers/of/selftest.c | |||
@@ -27,6 +27,7 @@ static struct selftest_results { | |||
27 | #define NO_OF_NODES 2 | 27 | #define NO_OF_NODES 2 |
28 | static struct device_node *nodes[NO_OF_NODES]; | 28 | static struct device_node *nodes[NO_OF_NODES]; |
29 | static int last_node_index; | 29 | static int last_node_index; |
30 | static bool selftest_live_tree; | ||
30 | 31 | ||
31 | #define selftest(result, fmt, ...) { \ | 32 | #define selftest(result, fmt, ...) { \ |
32 | if (!(result)) { \ | 33 | if (!(result)) { \ |
@@ -630,13 +631,6 @@ static int attach_node_and_children(struct device_node *np) | |||
630 | { | 631 | { |
631 | struct device_node *next, *root = np, *dup; | 632 | struct device_node *next, *root = np, *dup; |
632 | 633 | ||
633 | if (!np) { | ||
634 | pr_warn("%s: No tree to attach; not running tests\n", | ||
635 | __func__); | ||
636 | return -ENODATA; | ||
637 | } | ||
638 | |||
639 | |||
640 | /* skip root node */ | 634 | /* skip root node */ |
641 | np = np->child; | 635 | np = np->child; |
642 | /* storing a copy in temporary node */ | 636 | /* storing a copy in temporary node */ |
@@ -672,12 +666,12 @@ static int attach_node_and_children(struct device_node *np) | |||
672 | static int __init selftest_data_add(void) | 666 | static int __init selftest_data_add(void) |
673 | { | 667 | { |
674 | void *selftest_data; | 668 | void *selftest_data; |
675 | struct device_node *selftest_data_node; | 669 | struct device_node *selftest_data_node, *np; |
676 | extern uint8_t __dtb_testcases_begin[]; | 670 | extern uint8_t __dtb_testcases_begin[]; |
677 | extern uint8_t __dtb_testcases_end[]; | 671 | extern uint8_t __dtb_testcases_end[]; |
678 | const int size = __dtb_testcases_end - __dtb_testcases_begin; | 672 | const int size = __dtb_testcases_end - __dtb_testcases_begin; |
679 | 673 | ||
680 | if (!size || !of_allnodes) { | 674 | if (!size) { |
681 | pr_warn("%s: No testcase data to attach; not running tests\n", | 675 | pr_warn("%s: No testcase data to attach; not running tests\n", |
682 | __func__); | 676 | __func__); |
683 | return -ENODATA; | 677 | return -ENODATA; |
@@ -692,6 +686,22 @@ static int __init selftest_data_add(void) | |||
692 | return -ENOMEM; | 686 | return -ENOMEM; |
693 | } | 687 | } |
694 | of_fdt_unflatten_tree(selftest_data, &selftest_data_node); | 688 | of_fdt_unflatten_tree(selftest_data, &selftest_data_node); |
689 | if (!selftest_data_node) { | ||
690 | pr_warn("%s: No tree to attach; not running tests\n", __func__); | ||
691 | return -ENODATA; | ||
692 | } | ||
693 | |||
694 | if (!of_allnodes) { | ||
695 | /* enabling flag for removing nodes */ | ||
696 | selftest_live_tree = true; | ||
697 | of_allnodes = selftest_data_node; | ||
698 | |||
699 | for_each_of_allnodes(np) | ||
700 | __of_attach_node_sysfs(np); | ||
701 | of_aliases = of_find_node_by_path("/aliases"); | ||
702 | of_chosen = of_find_node_by_path("/chosen"); | ||
703 | return 0; | ||
704 | } | ||
695 | 705 | ||
696 | /* attach the sub-tree to live tree */ | 706 | /* attach the sub-tree to live tree */ |
697 | return attach_node_and_children(selftest_data_node); | 707 | return attach_node_and_children(selftest_data_node); |
@@ -723,6 +733,18 @@ static void selftest_data_remove(void) | |||
723 | struct device_node *np; | 733 | struct device_node *np; |
724 | struct property *prop; | 734 | struct property *prop; |
725 | 735 | ||
736 | if (selftest_live_tree) { | ||
737 | of_node_put(of_aliases); | ||
738 | of_node_put(of_chosen); | ||
739 | of_aliases = NULL; | ||
740 | of_chosen = NULL; | ||
741 | for_each_child_of_node(of_allnodes, np) | ||
742 | detach_node_and_children(np); | ||
743 | __of_detach_node_sysfs(of_allnodes); | ||
744 | of_allnodes = NULL; | ||
745 | return; | ||
746 | } | ||
747 | |||
726 | while (last_node_index >= 0) { | 748 | while (last_node_index >= 0) { |
727 | if (nodes[last_node_index]) { | 749 | if (nodes[last_node_index]) { |
728 | np = of_find_node_by_path(nodes[last_node_index]->full_name); | 750 | np = of_find_node_by_path(nodes[last_node_index]->full_name); |