aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaxime Ripard <maxime.ripard@bootlin.com>2018-05-03 22:27:26 +0200
committerDavid Gibson <david@gibson.dropbear.id.au>2018-05-04 11:48:46 +1000
commit4038fd90056e81f9a9dc107570431e4e20e526bd (patch)
treecd90d18616be6300fad399db8450353d9e3ed5cc
parente1f139ea4900fd0324c646822b4061fec6e08321 (diff)
downloaddtc-4038fd90056e81f9a9dc107570431e4e20e526bd.zip
dtc-4038fd90056e81f9a9dc107570431e4e20e526bd.tar.gz
dtc-4038fd90056e81f9a9dc107570431e4e20e526bd.tar.bz2
dtc: add ability to make nodes conditional on them being referenced
A number of platforms have a need to reduce the number of DT nodes, mostly because of two similar constraints: the size of the DT blob, and the time it takes to parse it. As the DT is used in more and more SoCs, and by more projects, some constraints start to appear in bootloaders running from SRAM with an order of magnitude of 10kB. A typical DT is in the same order of magnitude, so any effort to reduce the blob size is welcome in such an environment. Some platforms also want to reach very fast boot time, and the time it takes to parse a typical DT starts to be noticeable. Both of these issues can be mitigated by reducing the number of nodes in the DT. The biggest provider of nodes is usually the pin controller and its subnodes, usually one for each valid pin configuration in a given SoC. Obviously, a single, fixed, set of these nodes will be used by a given board, so we can introduce a node property that will tell the DT compiler to drop the nodes when they are not referenced in the tree, and as such wouldn't be useful in the targetted system. Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com> Reviewed-by: Rob Herring <robh@kernel.org> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
-rw-r--r--checks.c13
-rw-r--r--dtc-lexer.l7
-rw-r--r--dtc-parser.y17
-rw-r--r--dtc.h4
-rw-r--r--livetree.c14
5 files changed, 55 insertions, 0 deletions
diff --git a/checks.c b/checks.c
index dca45ac..a2cc103 100644
--- a/checks.c
+++ b/checks.c
@@ -584,6 +584,8 @@ static void fixup_phandle_references(struct check *c, struct dt_info *dti,
phandle = get_node_phandle(dt, refnode);
*((fdt32_t *)(prop->val.val + m->offset)) = cpu_to_fdt32(phandle);
+
+ reference_node(refnode);
}
}
}
@@ -614,11 +616,21 @@ static void fixup_path_references(struct check *c, struct dt_info *dti,
path = refnode->fullpath;
prop->val = data_insert_at_marker(prop->val, m, path,
strlen(path) + 1);
+
+ reference_node(refnode);
}
}
}
ERROR(path_references, fixup_path_references, NULL, &duplicate_node_names);
+static void fixup_omit_unused_nodes(struct check *c, struct dt_info *dti,
+ struct node *node)
+{
+ if (node->omit_if_unused && !node->is_referenced)
+ delete_node(node);
+}
+ERROR(omit_unused_nodes, fixup_omit_unused_nodes, NULL, &phandle_references, &path_references);
+
/*
* Semantic checks
*/
@@ -1547,6 +1559,7 @@ static struct check *check_table[] = {
&explicit_phandles,
&phandle_references, &path_references,
+ &omit_unused_nodes,
&address_cells_is_cell, &size_cells_is_cell, &interrupt_cells_is_cell,
&device_type_is_string, &model_is_string, &status_is_string,
diff --git a/dtc-lexer.l b/dtc-lexer.l
index fd825eb..615b7ec 100644
--- a/dtc-lexer.l
+++ b/dtc-lexer.l
@@ -153,6 +153,13 @@ static void PRINTF(1, 2) lexical_error(const char *fmt, ...);
return DT_DEL_NODE;
}
+<*>"/omit-if-no-ref/" {
+ DPRINT("Keyword: /omit-if-no-ref/\n");
+ DPRINT("<PROPNODENAME>\n");
+ BEGIN(PROPNODENAME);
+ return DT_OMIT_NO_REF;
+ }
+
<*>{LABEL}: {
DPRINT("Label: %s\n", yytext);
yylval.labelref = xstrdup(yytext);
diff --git a/dtc-parser.y b/dtc-parser.y
index 25e92d6..011a5b2 100644
--- a/dtc-parser.y
+++ b/dtc-parser.y
@@ -63,6 +63,7 @@ extern bool treesource_error;
%token DT_BITS
%token DT_DEL_PROP
%token DT_DEL_NODE
+%token DT_OMIT_NO_REF
%token <propnodename> DT_PROPNODENAME
%token <integer> DT_LITERAL
%token <integer> DT_CHAR_LITERAL
@@ -219,6 +220,18 @@ devicetree:
$$ = $1;
}
+ | devicetree DT_OMIT_NO_REF DT_REF ';'
+ {
+ struct node *target = get_node_by_ref($1, $3);
+
+ if (target)
+ omit_node_if_unused(target);
+ else
+ ERROR(&@3, "Label or path %s not found", $3);
+
+
+ $$ = $1;
+ }
;
nodedef:
@@ -523,6 +536,10 @@ subnode:
{
$$ = name_node(build_node_delete(), $2);
}
+ | DT_OMIT_NO_REF subnode
+ {
+ $$ = omit_node_if_unused($2);
+ }
| DT_LABEL subnode
{
add_label(&$2->labels, $1);
diff --git a/dtc.h b/dtc.h
index 3b18a42..6d66770 100644
--- a/dtc.h
+++ b/dtc.h
@@ -168,6 +168,8 @@ struct node {
struct label *labels;
const struct bus_type *bus;
+
+ bool omit_if_unused, is_referenced;
};
#define for_each_label_withdel(l0, l) \
@@ -202,6 +204,8 @@ struct property *reverse_properties(struct property *first);
struct node *build_node(struct property *proplist, struct node *children);
struct node *build_node_delete(void);
struct node *name_node(struct node *node, char *name);
+struct node *omit_node_if_unused(struct node *node);
+struct node *reference_node(struct node *node);
struct node *chain_node(struct node *first, struct node *list);
struct node *merge_nodes(struct node *old_node, struct node *new_node);
struct node *add_orphan_node(struct node *old_node, struct node *new_node, char *ref);
diff --git a/livetree.c b/livetree.c
index f691c9b..6e4c367 100644
--- a/livetree.c
+++ b/livetree.c
@@ -134,6 +134,20 @@ struct node *name_node(struct node *node, char *name)
return node;
}
+struct node *omit_node_if_unused(struct node *node)
+{
+ node->omit_if_unused = 1;
+
+ return node;
+}
+
+struct node *reference_node(struct node *node)
+{
+ node->is_referenced = 1;
+
+ return node;
+}
+
struct node *merge_nodes(struct node *old_node, struct node *new_node)
{
struct property *new_prop, *old_prop;