aboutsummaryrefslogtreecommitdiff
path: root/checks.c
diff options
context:
space:
mode:
authorRob Herring <robh@kernel.org>2018-03-06 18:49:15 -0600
committerDavid Gibson <david@gibson.dropbear.id.au>2018-03-07 14:32:28 +1100
commit2347c96edcbea4cf59f47430a0de14d4fdedb0af (patch)
tree1bc952a9d92cec3c00deb3ce61e7a2dbd9509f75 /checks.c
parent8f1b35f88395adea01ce1100c5faa27dacbc8410 (diff)
downloaddtc-2347c96edcbea4cf59f47430a0de14d4fdedb0af.zip
dtc-2347c96edcbea4cf59f47430a0de14d4fdedb0af.tar.gz
dtc-2347c96edcbea4cf59f47430a0de14d4fdedb0af.tar.bz2
checks: add a check for duplicate unit-addresses of child nodes
Child nodes with the same unit-address (and different node names) are either an error or just bad DT design. Typical errors are the unit-address is just wrong (i.e. doesn't match reg value) or multiple children using the same overlapping area. Overlapping regions are considered an error in new bindings, but do exist in some existing trees. This check should flag most but not all of those errors. Finding all cases would require doing address translations and creating a full map of address spaces. Mixing more than one address/number space at a level is bad design. It only works if both spaces can use the same #address-cells and #size-cells sizes. It also complicates parsing have a mixture of types of child nodes. The best practice in this case is adding child container nodes for each address/number space or using additional address bits/cells to encode different address spaces. Signed-off-by: Rob Herring <robh@kernel.org> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Diffstat (limited to 'checks.c')
-rw-r--r--checks.c31
1 files changed, 31 insertions, 0 deletions
diff --git a/checks.c b/checks.c
index f589d7e..a6ac4bb 100644
--- a/checks.c
+++ b/checks.c
@@ -1023,6 +1023,36 @@ static void check_avoid_unnecessary_addr_size(struct check *c, struct dt_info *d
}
WARNING(avoid_unnecessary_addr_size, check_avoid_unnecessary_addr_size, NULL, &avoid_default_addr_size);
+static void check_unique_unit_address(struct check *c, struct dt_info *dti,
+ struct node *node)
+{
+ struct node *childa;
+
+ if (node->addr_cells < 0 || node->size_cells < 0)
+ return;
+
+ if (!node->children)
+ return;
+
+ for_each_child(node, childa) {
+ struct node *childb;
+ const char *addr_a = get_unitname(childa);
+
+ if (!strlen(addr_a))
+ continue;
+
+ for_each_child(node, childb) {
+ const char *addr_b = get_unitname(childb);
+ if (childa == childb)
+ break;
+
+ if (streq(addr_a, addr_b))
+ FAIL(c, dti, childb, "duplicate unit-address (also used in node %s)", childa->fullpath);
+ }
+ }
+}
+WARNING(unique_unit_address, check_unique_unit_address, NULL, &avoid_default_addr_size);
+
static void check_obsolete_chosen_interrupt_controller(struct check *c,
struct dt_info *dti,
struct node *node)
@@ -1396,6 +1426,7 @@ static struct check *check_table[] = {
&avoid_default_addr_size,
&avoid_unnecessary_addr_size,
+ &unique_unit_address,
&obsolete_chosen_interrupt_controller,
&chosen_node_is_root, &chosen_node_bootargs, &chosen_node_stdout_path,