aboutsummaryrefslogtreecommitdiffstats
path: root/scripts
diff options
context:
space:
mode:
authorRob Herring <robh@kernel.org>2018-05-08 14:07:49 -0400
committerRob Herring <robh@kernel.org>2018-05-14 20:45:01 -0400
commit50aafd60898a8b3edf2f60e014a8288da3b2e5e3 (patch)
tree9bbb9713e3cc6e0c2e3cea71943e9338b937e0b7 /scripts
parent9601000cd57e395b56642596903f59d61d91e176 (diff)
scripts/dtc: Update to upstream version v1.4.6-21-g84e414b0b5bc
This adds the following commits from upstream: 84e414b0b5bc tests: Add a test case for the omit-if-no-ref keyword 4038fd90056e dtc: add ability to make nodes conditional on them being referenced e1f139ea4900 checks: drop warning for missing PCI bridge bus-range f4eba68d89ee checks: Print duplicate node name instead of parent name 46df1fb1b211 .travis.yml: Run valgrind checks via Travis 14a3002a1aee tests: Update valgrind suppressions for sw_tree1 02c5fe9debc0 tests: Remove valgrind error from tests/get_path df536831d02c checks: add graph binding checks 2347c96edcbe checks: add a check for duplicate unit-addresses of child nodes 8f1b35f88395 Correct overlay syntactic sugar for generating target-path fragments afbddcd418fb Suppress warnings on overlay fragments 119e27300359 Improve tests for dtc overlay generation Signed-off-by: Rob Herring <robh@kernel.org>
Diffstat (limited to 'scripts')
-rw-r--r--scripts/dtc/checks.c199
-rw-r--r--scripts/dtc/dtc-lexer.l7
-rw-r--r--scripts/dtc/dtc-parser.y39
-rw-r--r--scripts/dtc/dtc.h4
-rw-r--r--scripts/dtc/livetree.c26
-rw-r--r--scripts/dtc/version_gen.h2
6 files changed, 261 insertions, 16 deletions
diff --git a/scripts/dtc/checks.c b/scripts/dtc/checks.c
index 815eaf140ab5..a2cc1036c915 100644
--- a/scripts/dtc/checks.c
+++ b/scripts/dtc/checks.c
@@ -255,7 +255,7 @@ static void check_duplicate_node_names(struct check *c, struct dt_info *dti,
255 child2; 255 child2;
256 child2 = child2->next_sibling) 256 child2 = child2->next_sibling)
257 if (streq(child->name, child2->name)) 257 if (streq(child->name, child2->name))
258 FAIL(c, dti, node, "Duplicate node name"); 258 FAIL(c, dti, child2, "Duplicate node name");
259} 259}
260ERROR(duplicate_node_names, check_duplicate_node_names, NULL); 260ERROR(duplicate_node_names, check_duplicate_node_names, NULL);
261 261
@@ -317,6 +317,11 @@ static void check_unit_address_vs_reg(struct check *c, struct dt_info *dti,
317 const char *unitname = get_unitname(node); 317 const char *unitname = get_unitname(node);
318 struct property *prop = get_property(node, "reg"); 318 struct property *prop = get_property(node, "reg");
319 319
320 if (get_subnode(node, "__overlay__")) {
321 /* HACK: Overlay fragments are a special case */
322 return;
323 }
324
320 if (!prop) { 325 if (!prop) {
321 prop = get_property(node, "ranges"); 326 prop = get_property(node, "ranges");
322 if (prop && !prop->val.len) 327 if (prop && !prop->val.len)
@@ -579,6 +584,8 @@ static void fixup_phandle_references(struct check *c, struct dt_info *dti,
579 584
580 phandle = get_node_phandle(dt, refnode); 585 phandle = get_node_phandle(dt, refnode);
581 *((fdt32_t *)(prop->val.val + m->offset)) = cpu_to_fdt32(phandle); 586 *((fdt32_t *)(prop->val.val + m->offset)) = cpu_to_fdt32(phandle);
587
588 reference_node(refnode);
582 } 589 }
583 } 590 }
584} 591}
@@ -609,11 +616,21 @@ static void fixup_path_references(struct check *c, struct dt_info *dti,
609 path = refnode->fullpath; 616 path = refnode->fullpath;
610 prop->val = data_insert_at_marker(prop->val, m, path, 617 prop->val = data_insert_at_marker(prop->val, m, path,
611 strlen(path) + 1); 618 strlen(path) + 1);
619
620 reference_node(refnode);
612 } 621 }
613 } 622 }
614} 623}
615ERROR(path_references, fixup_path_references, NULL, &duplicate_node_names); 624ERROR(path_references, fixup_path_references, NULL, &duplicate_node_names);
616 625
626static void fixup_omit_unused_nodes(struct check *c, struct dt_info *dti,
627 struct node *node)
628{
629 if (node->omit_if_unused && !node->is_referenced)
630 delete_node(node);
631}
632ERROR(omit_unused_nodes, fixup_omit_unused_nodes, NULL, &phandle_references, &path_references);
633
617/* 634/*
618 * Semantic checks 635 * Semantic checks
619 */ 636 */
@@ -1017,6 +1034,36 @@ static void check_avoid_unnecessary_addr_size(struct check *c, struct dt_info *d
1017} 1034}
1018WARNING(avoid_unnecessary_addr_size, check_avoid_unnecessary_addr_size, NULL, &avoid_default_addr_size); 1035WARNING(avoid_unnecessary_addr_size, check_avoid_unnecessary_addr_size, NULL, &avoid_default_addr_size);
1019 1036
1037static void check_unique_unit_address(struct check *c, struct dt_info *dti,
1038 struct node *node)
1039{
1040 struct node *childa;
1041
1042 if (node->addr_cells < 0 || node->size_cells < 0)
1043 return;
1044
1045 if (!node->children)
1046 return;
1047
1048 for_each_child(node, childa) {
1049 struct node *childb;
1050 const char *addr_a = get_unitname(childa);
1051
1052 if (!strlen(addr_a))
1053 continue;
1054
1055 for_each_child(node, childb) {
1056 const char *addr_b = get_unitname(childb);
1057 if (childa == childb)
1058 break;
1059
1060 if (streq(addr_a, addr_b))
1061 FAIL(c, dti, childb, "duplicate unit-address (also used in node %s)", childa->fullpath);
1062 }
1063 }
1064}
1065WARNING(unique_unit_address, check_unique_unit_address, NULL, &avoid_default_addr_size);
1066
1020static void check_obsolete_chosen_interrupt_controller(struct check *c, 1067static void check_obsolete_chosen_interrupt_controller(struct check *c,
1021 struct dt_info *dti, 1068 struct dt_info *dti,
1022 struct node *node) 1069 struct node *node)
@@ -1357,6 +1404,152 @@ static void check_interrupts_property(struct check *c,
1357} 1404}
1358WARNING(interrupts_property, check_interrupts_property, &phandle_references); 1405WARNING(interrupts_property, check_interrupts_property, &phandle_references);
1359 1406
1407static const struct bus_type graph_port_bus = {
1408 .name = "graph-port",
1409};
1410
1411static const struct bus_type graph_ports_bus = {
1412 .name = "graph-ports",
1413};
1414
1415static void check_graph_nodes(struct check *c, struct dt_info *dti,
1416 struct node *node)
1417{
1418 struct node *child;
1419
1420 for_each_child(node, child) {
1421 if (!(strprefixeq(child->name, child->basenamelen, "endpoint") ||
1422 get_property(child, "remote-endpoint")))
1423 continue;
1424
1425 node->bus = &graph_port_bus;
1426
1427 /* The parent of 'port' nodes can be either 'ports' or a device */
1428 if (!node->parent->bus &&
1429 (streq(node->parent->name, "ports") || get_property(node, "reg")))
1430 node->parent->bus = &graph_ports_bus;
1431
1432 break;
1433 }
1434
1435}
1436WARNING(graph_nodes, check_graph_nodes, NULL);
1437
1438static void check_graph_child_address(struct check *c, struct dt_info *dti,
1439 struct node *node)
1440{
1441 int cnt = 0;
1442 struct node *child;
1443
1444 if (node->bus != &graph_ports_bus && node->bus != &graph_port_bus)
1445 return;
1446
1447 for_each_child(node, child) {
1448 struct property *prop = get_property(child, "reg");
1449
1450 /* No error if we have any non-zero unit address */
1451 if (prop && propval_cell(prop) != 0)
1452 return;
1453
1454 cnt++;
1455 }
1456
1457 if (cnt == 1 && node->addr_cells != -1)
1458 FAIL(c, dti, node, "graph node has single child node '%s', #address-cells/#size-cells are not necessary",
1459 node->children->name);
1460}
1461WARNING(graph_child_address, check_graph_child_address, NULL, &graph_nodes);
1462
1463static void check_graph_reg(struct check *c, struct dt_info *dti,
1464 struct node *node)
1465{
1466 char unit_addr[9];
1467 const char *unitname = get_unitname(node);
1468 struct property *prop;
1469
1470 prop = get_property(node, "reg");
1471 if (!prop || !unitname)
1472 return;
1473
1474 if (!(prop->val.val && prop->val.len == sizeof(cell_t))) {
1475 FAIL(c, dti, node, "graph node malformed 'reg' property");
1476 return;
1477 }
1478
1479 snprintf(unit_addr, sizeof(unit_addr), "%x", propval_cell(prop));
1480 if (!streq(unitname, unit_addr))
1481 FAIL(c, dti, node, "graph node unit address error, expected \"%s\"",
1482 unit_addr);
1483
1484 if (node->parent->addr_cells != 1)
1485 FAIL_PROP(c, dti, node, get_property(node, "#address-cells"),
1486 "graph node '#address-cells' is %d, must be 1",
1487 node->parent->addr_cells);
1488 if (node->parent->size_cells != 0)
1489 FAIL_PROP(c, dti, node, get_property(node, "#size-cells"),
1490 "graph node '#size-cells' is %d, must be 0",
1491 node->parent->size_cells);
1492}
1493
1494static void check_graph_port(struct check *c, struct dt_info *dti,
1495 struct node *node)
1496{
1497 if (node->bus != &graph_port_bus)
1498 return;
1499
1500 if (!strprefixeq(node->name, node->basenamelen, "port"))
1501 FAIL(c, dti, node, "graph port node name should be 'port'");
1502
1503 check_graph_reg(c, dti, node);
1504}
1505WARNING(graph_port, check_graph_port, NULL, &graph_nodes);
1506
1507static struct node *get_remote_endpoint(struct check *c, struct dt_info *dti,
1508 struct node *endpoint)
1509{
1510 int phandle;
1511 struct node *node;
1512 struct property *prop;
1513
1514 prop = get_property(endpoint, "remote-endpoint");
1515 if (!prop)
1516 return NULL;
1517
1518 phandle = propval_cell(prop);
1519 /* Give up if this is an overlay with external references */
1520 if (phandle == 0 || phandle == -1)
1521 return NULL;
1522
1523 node = get_node_by_phandle(dti->dt, phandle);
1524 if (!node)
1525 FAIL_PROP(c, dti, endpoint, prop, "graph phandle is not valid");
1526
1527 return node;
1528}
1529
1530static void check_graph_endpoint(struct check *c, struct dt_info *dti,
1531 struct node *node)
1532{
1533 struct node *remote_node;
1534
1535 if (!node->parent || node->parent->bus != &graph_port_bus)
1536 return;
1537
1538 if (!strprefixeq(node->name, node->basenamelen, "endpoint"))
1539 FAIL(c, dti, node, "graph endpont node name should be 'endpoint'");
1540
1541 check_graph_reg(c, dti, node);
1542
1543 remote_node = get_remote_endpoint(c, dti, node);
1544 if (!remote_node)
1545 return;
1546
1547 if (get_remote_endpoint(c, dti, remote_node) != node)
1548 FAIL(c, dti, node, "graph connection to node '%s' is not bidirectional",
1549 remote_node->fullpath);
1550}
1551WARNING(graph_endpoint, check_graph_endpoint, NULL, &graph_nodes);
1552
1360static struct check *check_table[] = { 1553static struct check *check_table[] = {
1361 &duplicate_node_names, &duplicate_property_names, 1554 &duplicate_node_names, &duplicate_property_names,
1362 &node_name_chars, &node_name_format, &property_name_chars, 1555 &node_name_chars, &node_name_format, &property_name_chars,
@@ -1366,6 +1559,7 @@ static struct check *check_table[] = {
1366 1559
1367 &explicit_phandles, 1560 &explicit_phandles,
1368 &phandle_references, &path_references, 1561 &phandle_references, &path_references,
1562 &omit_unused_nodes,
1369 1563
1370 &address_cells_is_cell, &size_cells_is_cell, &interrupt_cells_is_cell, 1564 &address_cells_is_cell, &size_cells_is_cell, &interrupt_cells_is_cell,
1371 &device_type_is_string, &model_is_string, &status_is_string, 1565 &device_type_is_string, &model_is_string, &status_is_string,
@@ -1390,6 +1584,7 @@ static struct check *check_table[] = {
1390 1584
1391 &avoid_default_addr_size, 1585 &avoid_default_addr_size,
1392 &avoid_unnecessary_addr_size, 1586 &avoid_unnecessary_addr_size,
1587 &unique_unit_address,
1393 &obsolete_chosen_interrupt_controller, 1588 &obsolete_chosen_interrupt_controller,
1394 &chosen_node_is_root, &chosen_node_bootargs, &chosen_node_stdout_path, 1589 &chosen_node_is_root, &chosen_node_bootargs, &chosen_node_stdout_path,
1395 1590
@@ -1416,6 +1611,8 @@ static struct check *check_table[] = {
1416 1611
1417 &alias_paths, 1612 &alias_paths,
1418 1613
1614 &graph_nodes, &graph_child_address, &graph_port, &graph_endpoint,
1615
1419 &always_fail, 1616 &always_fail,
1420}; 1617};
1421 1618
diff --git a/scripts/dtc/dtc-lexer.l b/scripts/dtc/dtc-lexer.l
index fd825ebba69c..615b7ec6588f 100644
--- a/scripts/dtc/dtc-lexer.l
+++ b/scripts/dtc/dtc-lexer.l
@@ -153,6 +153,13 @@ static void PRINTF(1, 2) lexical_error(const char *fmt, ...);
153 return DT_DEL_NODE; 153 return DT_DEL_NODE;
154 } 154 }
155 155
156<*>"/omit-if-no-ref/" {
157 DPRINT("Keyword: /omit-if-no-ref/\n");
158 DPRINT("<PROPNODENAME>\n");
159 BEGIN(PROPNODENAME);
160 return DT_OMIT_NO_REF;
161 }
162
156<*>{LABEL}: { 163<*>{LABEL}: {
157 DPRINT("Label: %s\n", yytext); 164 DPRINT("Label: %s\n", yytext);
158 yylval.labelref = xstrdup(yytext); 165 yylval.labelref = xstrdup(yytext);
diff --git a/scripts/dtc/dtc-parser.y b/scripts/dtc/dtc-parser.y
index 44af170abfea..011a5b25539a 100644
--- a/scripts/dtc/dtc-parser.y
+++ b/scripts/dtc/dtc-parser.y
@@ -63,6 +63,7 @@ extern bool treesource_error;
63%token DT_BITS 63%token DT_BITS
64%token DT_DEL_PROP 64%token DT_DEL_PROP
65%token DT_DEL_NODE 65%token DT_DEL_NODE
66%token DT_OMIT_NO_REF
66%token <propnodename> DT_PROPNODENAME 67%token <propnodename> DT_PROPNODENAME
67%token <integer> DT_LITERAL 68%token <integer> DT_LITERAL
68%token <integer> DT_CHAR_LITERAL 69%token <integer> DT_CHAR_LITERAL
@@ -190,18 +191,18 @@ devicetree:
190 } 191 }
191 | devicetree DT_REF nodedef 192 | devicetree DT_REF nodedef
192 { 193 {
193 struct node *target = get_node_by_ref($1, $2); 194 /*
194 195 * We rely on the rule being always:
195 if (target) { 196 * versioninfo plugindecl memreserves devicetree
196 merge_nodes(target, $3); 197 * so $-1 is what we want (plugindecl)
198 */
199 if ($<flags>-1 & DTSF_PLUGIN) {
200 add_orphan_node($1, $3, $2);
197 } else { 201 } else {
198 /* 202 struct node *target = get_node_by_ref($1, $2);
199 * We rely on the rule being always: 203
200 * versioninfo plugindecl memreserves devicetree 204 if (target)
201 * so $-1 is what we want (plugindecl) 205 merge_nodes(target, $3);
202 */
203 if ($<flags>-1 & DTSF_PLUGIN)
204 add_orphan_node($1, $3, $2);
205 else 206 else
206 ERROR(&@2, "Label or path %s not found", $2); 207 ERROR(&@2, "Label or path %s not found", $2);
207 } 208 }
@@ -219,6 +220,18 @@ devicetree:
219 220
220 $$ = $1; 221 $$ = $1;
221 } 222 }
223 | devicetree DT_OMIT_NO_REF DT_REF ';'
224 {
225 struct node *target = get_node_by_ref($1, $3);
226
227 if (target)
228 omit_node_if_unused(target);
229 else
230 ERROR(&@3, "Label or path %s not found", $3);
231
232
233 $$ = $1;
234 }
222 ; 235 ;
223 236
224nodedef: 237nodedef:
@@ -523,6 +536,10 @@ subnode:
523 { 536 {
524 $$ = name_node(build_node_delete(), $2); 537 $$ = name_node(build_node_delete(), $2);
525 } 538 }
539 | DT_OMIT_NO_REF subnode
540 {
541 $$ = omit_node_if_unused($2);
542 }
526 | DT_LABEL subnode 543 | DT_LABEL subnode
527 { 544 {
528 add_label(&$2->labels, $1); 545 add_label(&$2->labels, $1);
diff --git a/scripts/dtc/dtc.h b/scripts/dtc/dtc.h
index 3b18a42b866e..6d667701ab6a 100644
--- a/scripts/dtc/dtc.h
+++ b/scripts/dtc/dtc.h
@@ -168,6 +168,8 @@ struct node {
168 168
169 struct label *labels; 169 struct label *labels;
170 const struct bus_type *bus; 170 const struct bus_type *bus;
171
172 bool omit_if_unused, is_referenced;
171}; 173};
172 174
173#define for_each_label_withdel(l0, l) \ 175#define for_each_label_withdel(l0, l) \
@@ -202,6 +204,8 @@ struct property *reverse_properties(struct property *first);
202struct node *build_node(struct property *proplist, struct node *children); 204struct node *build_node(struct property *proplist, struct node *children);
203struct node *build_node_delete(void); 205struct node *build_node_delete(void);
204struct node *name_node(struct node *node, char *name); 206struct node *name_node(struct node *node, char *name);
207struct node *omit_node_if_unused(struct node *node);
208struct node *reference_node(struct node *node);
205struct node *chain_node(struct node *first, struct node *list); 209struct node *chain_node(struct node *first, struct node *list);
206struct node *merge_nodes(struct node *old_node, struct node *new_node); 210struct node *merge_nodes(struct node *old_node, struct node *new_node);
207struct node *add_orphan_node(struct node *old_node, struct node *new_node, char *ref); 211struct node *add_orphan_node(struct node *old_node, struct node *new_node, char *ref);
diff --git a/scripts/dtc/livetree.c b/scripts/dtc/livetree.c
index 57b7db2ed153..6e4c367f54b3 100644
--- a/scripts/dtc/livetree.c
+++ b/scripts/dtc/livetree.c
@@ -134,6 +134,20 @@ struct node *name_node(struct node *node, char *name)
134 return node; 134 return node;
135} 135}
136 136
137struct node *omit_node_if_unused(struct node *node)
138{
139 node->omit_if_unused = 1;
140
141 return node;
142}
143
144struct node *reference_node(struct node *node)
145{
146 node->is_referenced = 1;
147
148 return node;
149}
150
137struct node *merge_nodes(struct node *old_node, struct node *new_node) 151struct node *merge_nodes(struct node *old_node, struct node *new_node)
138{ 152{
139 struct property *new_prop, *old_prop; 153 struct property *new_prop, *old_prop;
@@ -224,10 +238,16 @@ struct node * add_orphan_node(struct node *dt, struct node *new_node, char *ref)
224 struct data d = empty_data; 238 struct data d = empty_data;
225 char *name; 239 char *name;
226 240
227 d = data_add_marker(d, REF_PHANDLE, ref); 241 if (ref[0] == '/') {
228 d = data_append_integer(d, 0xffffffff, 32); 242 d = data_append_data(d, ref, strlen(ref) + 1);
229 243
230 p = build_property("target", d); 244 p = build_property("target-path", d);
245 } else {
246 d = data_add_marker(d, REF_PHANDLE, ref);
247 d = data_append_integer(d, 0xffffffff, 32);
248
249 p = build_property("target", d);
250 }
231 251
232 xasprintf(&name, "fragment@%u", 252 xasprintf(&name, "fragment@%u",
233 next_orphan_fragment++); 253 next_orphan_fragment++);
diff --git a/scripts/dtc/version_gen.h b/scripts/dtc/version_gen.h
index ad87849e333b..b00f14ff7a17 100644
--- a/scripts/dtc/version_gen.h
+++ b/scripts/dtc/version_gen.h
@@ -1 +1 @@
#define DTC_VERSION "DTC 1.4.6-gaadd0b65" #define DTC_VERSION "DTC 1.4.6-g84e414b0"