diff mbox series

[PATCHv2,6/8] scripts/dtc: Update to upstream version v1.4.6-21-g84e414b0b5bc

Message ID 20200311221118.4579-6-trini@konsulko.com
State Accepted
Commit 6e916dfd9da1648edce687affed682115cb1e7d6
Headers show
Series [PATCHv2,1/8] spl: Kconfig: Escape '$(ARCH)' in LDSCRIPT entries | expand

Commit Message

Tom Rini March 11, 2020, 10:11 p.m. UTC
From: Rob Herring <robh at kernel.org>

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

[From Linux Kernel commit 50aafd60898a8b3edf2f60e014a8288da3b2e5e3]
Signed-off-by: Rob Herring <robh at kernel.org>

[For applying to U-Boot]
Signed-off-by: Tom Rini <trini at konsulko.com>
---
 scripts/dtc/checks.c      | 186 +++++++++++++++++++++++++++++++++++++-
 scripts/dtc/dtc-parser.y  |  22 ++---
 scripts/dtc/livetree.c    |  12 ++-
 scripts/dtc/version_gen.h |   2 +-
 4 files changed, 206 insertions(+), 16 deletions(-)

Comments

Rob Herring March 13, 2020, 8:01 p.m. UTC | #1
On Wed, Mar 11, 2020 at 5:11 PM Tom Rini <trini at konsulko.com> wrote:
>
> From: Rob Herring <robh at kernel.org>
>
> 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

That's 100s of commits behind master. Any reason why (IIRC, you revert
the unaligned handling change)? In particular, there's a fix for GCC
10 and clang with commit:

0e9225eb0dfe Remove redundant YYLOC global declaration

Only just now pointed out to me for updating the kernel copy. Though I
guess this could be handled with '-fcommon' instead.

Rob


>
> [From Linux Kernel commit 50aafd60898a8b3edf2f60e014a8288da3b2e5e3]
> Signed-off-by: Rob Herring <robh at kernel.org>
>
> [For applying to U-Boot]
> Signed-off-by: Tom Rini <trini at konsulko.com>
> ---
>  scripts/dtc/checks.c      | 186 +++++++++++++++++++++++++++++++++++++-
>  scripts/dtc/dtc-parser.y  |  22 ++---
>  scripts/dtc/livetree.c    |  12 ++-
>  scripts/dtc/version_gen.h |   2 +-
>  4 files changed, 206 insertions(+), 16 deletions(-)
>
> diff --git a/scripts/dtc/checks.c b/scripts/dtc/checks.c
> index 40879677c8c3..c35aa6f88639 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,
>                      child2;
>                      child2 = child2->next_sibling)
>                         if (streq(child->name, child2->name))
> -                               FAIL(c, dti, node, "Duplicate node name");
> +                               FAIL(c, dti, child2, "Duplicate node name");
>  }
>  ERROR(duplicate_node_names, check_duplicate_node_names, NULL);
>
> @@ -317,6 +317,11 @@ static void check_unit_address_vs_reg(struct check *c, struct dt_info *dti,
>         const char *unitname = get_unitname(node);
>         struct property *prop = get_property(node, "reg");
>
> +       if (get_subnode(node, "__overlay__")) {
> +               /* HACK: Overlay fragments are a special case */
> +               return;
> +       }
> +
>         if (!prop) {
>                 prop = get_property(node, "ranges");
>                 if (prop && !prop->val.len)
> @@ -1030,6 +1035,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)
> @@ -1370,6 +1405,152 @@ static void check_interrupts_property(struct check *c,
>  }
>  WARNING(interrupts_property, check_interrupts_property, &phandle_references);
>
> +static const struct bus_type graph_port_bus = {
> +       .name = "graph-port",
> +};
> +
> +static const struct bus_type graph_ports_bus = {
> +       .name = "graph-ports",
> +};
> +
> +static void check_graph_nodes(struct check *c, struct dt_info *dti,
> +                             struct node *node)
> +{
> +       struct node *child;
> +
> +       for_each_child(node, child) {
> +               if (!(strprefixeq(child->name, child->basenamelen, "endpoint") ||
> +                     get_property(child, "remote-endpoint")))
> +                       continue;
> +
> +               node->bus = &graph_port_bus;
> +
> +               /* The parent of 'port' nodes can be either 'ports' or a device */
> +               if (!node->parent->bus &&
> +                   (streq(node->parent->name, "ports") || get_property(node, "reg")))
> +                       node->parent->bus = &graph_ports_bus;
> +
> +               break;
> +       }
> +
> +}
> +WARNING(graph_nodes, check_graph_nodes, NULL);
> +
> +static void check_graph_child_address(struct check *c, struct dt_info *dti,
> +                                     struct node *node)
> +{
> +       int cnt = 0;
> +       struct node *child;
> +
> +       if (node->bus != &graph_ports_bus && node->bus != &graph_port_bus)
> +               return;
> +
> +       for_each_child(node, child) {
> +               struct property *prop = get_property(child, "reg");
> +
> +               /* No error if we have any non-zero unit address */
> +               if (prop && propval_cell(prop) != 0)
> +                       return;
> +
> +               cnt++;
> +       }
> +
> +       if (cnt == 1 && node->addr_cells != -1)
> +               FAIL(c, dti, node, "graph node has single child node '%s', #address-cells/#size-cells are not necessary",
> +                    node->children->name);
> +}
> +WARNING(graph_child_address, check_graph_child_address, NULL, &graph_nodes);
> +
> +static void check_graph_reg(struct check *c, struct dt_info *dti,
> +                           struct node *node)
> +{
> +       char unit_addr[9];
> +       const char *unitname = get_unitname(node);
> +       struct property *prop;
> +
> +       prop = get_property(node, "reg");
> +       if (!prop || !unitname)
> +               return;
> +
> +       if (!(prop->val.val && prop->val.len == sizeof(cell_t))) {
> +               FAIL(c, dti, node, "graph node malformed 'reg' property");
> +               return;
> +       }
> +
> +       snprintf(unit_addr, sizeof(unit_addr), "%x", propval_cell(prop));
> +       if (!streq(unitname, unit_addr))
> +               FAIL(c, dti, node, "graph node unit address error, expected \"%s\"",
> +                    unit_addr);
> +
> +       if (node->parent->addr_cells != 1)
> +               FAIL_PROP(c, dti, node, get_property(node, "#address-cells"),
> +                         "graph node '#address-cells' is %d, must be 1",
> +                         node->parent->addr_cells);
> +       if (node->parent->size_cells != 0)
> +               FAIL_PROP(c, dti, node, get_property(node, "#size-cells"),
> +                         "graph node '#size-cells' is %d, must be 0",
> +                         node->parent->size_cells);
> +}
> +
> +static void check_graph_port(struct check *c, struct dt_info *dti,
> +                            struct node *node)
> +{
> +       if (node->bus != &graph_port_bus)
> +               return;
> +
> +       if (!strprefixeq(node->name, node->basenamelen, "port"))
> +               FAIL(c, dti, node, "graph port node name should be 'port'");
> +
> +       check_graph_reg(c, dti, node);
> +}
> +WARNING(graph_port, check_graph_port, NULL, &graph_nodes);
> +
> +static struct node *get_remote_endpoint(struct check *c, struct dt_info *dti,
> +                                       struct node *endpoint)
> +{
> +       int phandle;
> +       struct node *node;
> +       struct property *prop;
> +
> +       prop = get_property(endpoint, "remote-endpoint");
> +       if (!prop)
> +               return NULL;
> +
> +       phandle = propval_cell(prop);
> +       /* Give up if this is an overlay with external references */
> +       if (phandle == 0 || phandle == -1)
> +               return NULL;
> +
> +       node = get_node_by_phandle(dti->dt, phandle);
> +       if (!node)
> +               FAIL_PROP(c, dti, endpoint, prop, "graph phandle is not valid");
> +
> +       return node;
> +}
> +
> +static void check_graph_endpoint(struct check *c, struct dt_info *dti,
> +                                struct node *node)
> +{
> +       struct node *remote_node;
> +
> +       if (!node->parent || node->parent->bus != &graph_port_bus)
> +               return;
> +
> +       if (!strprefixeq(node->name, node->basenamelen, "endpoint"))
> +               FAIL(c, dti, node, "graph endpont node name should be 'endpoint'");
> +
> +       check_graph_reg(c, dti, node);
> +
> +       remote_node = get_remote_endpoint(c, dti, node);
> +       if (!remote_node)
> +               return;
> +
> +       if (get_remote_endpoint(c, dti, remote_node) != node)
> +               FAIL(c, dti, node, "graph connection to node '%s' is not bidirectional",
> +                    remote_node->fullpath);
> +}
> +WARNING(graph_endpoint, check_graph_endpoint, NULL, &graph_nodes);
> +
>  static struct check *check_table[] = {
>         &duplicate_node_names, &duplicate_property_names,
>         &node_name_chars, &node_name_format, &property_name_chars,
> @@ -1404,6 +1585,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,
>
> @@ -1430,6 +1612,8 @@ static struct check *check_table[] = {
>
>         &alias_paths,
>
> +       &graph_nodes, &graph_child_address, &graph_port, &graph_endpoint,
> +
>         &always_fail,
>  };
>
> diff --git a/scripts/dtc/dtc-parser.y b/scripts/dtc/dtc-parser.y
> index 66ff7f7d8eb7..011a5b25539a 100644
> --- a/scripts/dtc/dtc-parser.y
> +++ b/scripts/dtc/dtc-parser.y
> @@ -191,18 +191,18 @@ devicetree:
>                 }
>         | devicetree DT_REF nodedef
>                 {
> -                       struct node *target = get_node_by_ref($1, $2);
> -
> -                       if (target) {
> -                               merge_nodes(target, $3);
> +                       /*
> +                        * We rely on the rule being always:
> +                        *   versioninfo plugindecl memreserves devicetree
> +                        * so $-1 is what we want (plugindecl)
> +                        */
> +                       if ($<flags>-1 & DTSF_PLUGIN) {
> +                               add_orphan_node($1, $3, $2);
>                         } else {
> -                               /*
> -                                * We rely on the rule being always:
> -                                *   versioninfo plugindecl memreserves devicetree
> -                                * so $-1 is what we want (plugindecl)
> -                                */
> -                               if ($<flags>-1 & DTSF_PLUGIN)
> -                                       add_orphan_node($1, $3, $2);
> +                               struct node *target = get_node_by_ref($1, $2);
> +
> +                               if (target)
> +                                       merge_nodes(target, $3);
>                                 else
>                                         ERROR(&@2, "Label or path %s not found", $2);
>                         }
> diff --git a/scripts/dtc/livetree.c b/scripts/dtc/livetree.c
> index 81b6c484542d..6e4c367f54b3 100644
> --- a/scripts/dtc/livetree.c
> +++ b/scripts/dtc/livetree.c
> @@ -238,10 +238,16 @@ struct node * add_orphan_node(struct node *dt, struct node *new_node, char *ref)
>         struct data d = empty_data;
>         char *name;
>
> -       d = data_add_marker(d, REF_PHANDLE, ref);
> -       d = data_append_integer(d, 0xffffffff, 32);
> +       if (ref[0] == '/') {
> +               d = data_append_data(d, ref, strlen(ref) + 1);
>
> -       p = build_property("target", d);
> +               p = build_property("target-path", d);
> +       } else {
> +               d = data_add_marker(d, REF_PHANDLE, ref);
> +               d = data_append_integer(d, 0xffffffff, 32);
> +
> +               p = build_property("target", d);
> +       }
>
>         xasprintf(&name, "fragment@%u",
>                         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"
> --
> 2.17.1
>
Tom Rini March 13, 2020, 8:10 p.m. UTC | #2
On Fri, Mar 13, 2020 at 03:01:05PM -0500, Rob Herring wrote:
> On Wed, Mar 11, 2020 at 5:11 PM Tom Rini <trini at konsulko.com> wrote:
> >
> > From: Rob Herring <robh at kernel.org>
> >
> > 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
> 
> That's 100s of commits behind master. Any reason why (IIRC, you revert
> the unaligned handling change)? In particular, there's a fix for GCC
> 10 and clang with commit:
> 
> 0e9225eb0dfe Remove redundant YYLOC global declaration
> 
> Only just now pointed out to me for updating the kernel copy. Though I
> guess this could be handled with '-fcommon' instead.

I'm (slowly) getting all of the U-Boot Kbuild/Kconfig (and so, dtc)
infrastructure in-line with Linux again, and then try and keep it up to
date.
Tom Rini March 17, 2020, 3:29 p.m. UTC | #3
On Wed, Mar 11, 2020 at 06:11:16PM -0400, Tom Rini wrote:

> From: Rob Herring <robh at kernel.org>
> 
> 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
> 
> [From Linux Kernel commit 50aafd60898a8b3edf2f60e014a8288da3b2e5e3]
> Signed-off-by: Rob Herring <robh at kernel.org>
> 
> [For applying to U-Boot]
> Signed-off-by: Tom Rini <trini at konsulko.com>

Applied to u-boot/next, thanks!
diff mbox series

Patch

diff --git a/scripts/dtc/checks.c b/scripts/dtc/checks.c
index 40879677c8c3..c35aa6f88639 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,
 		     child2;
 		     child2 = child2->next_sibling)
 			if (streq(child->name, child2->name))
-				FAIL(c, dti, node, "Duplicate node name");
+				FAIL(c, dti, child2, "Duplicate node name");
 }
 ERROR(duplicate_node_names, check_duplicate_node_names, NULL);
 
@@ -317,6 +317,11 @@  static void check_unit_address_vs_reg(struct check *c, struct dt_info *dti,
 	const char *unitname = get_unitname(node);
 	struct property *prop = get_property(node, "reg");
 
+	if (get_subnode(node, "__overlay__")) {
+		/* HACK: Overlay fragments are a special case */
+		return;
+	}
+
 	if (!prop) {
 		prop = get_property(node, "ranges");
 		if (prop && !prop->val.len)
@@ -1030,6 +1035,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)
@@ -1370,6 +1405,152 @@  static void check_interrupts_property(struct check *c,
 }
 WARNING(interrupts_property, check_interrupts_property, &phandle_references);
 
+static const struct bus_type graph_port_bus = {
+	.name = "graph-port",
+};
+
+static const struct bus_type graph_ports_bus = {
+	.name = "graph-ports",
+};
+
+static void check_graph_nodes(struct check *c, struct dt_info *dti,
+			      struct node *node)
+{
+	struct node *child;
+
+	for_each_child(node, child) {
+		if (!(strprefixeq(child->name, child->basenamelen, "endpoint") ||
+		      get_property(child, "remote-endpoint")))
+			continue;
+
+		node->bus = &graph_port_bus;
+
+		/* The parent of 'port' nodes can be either 'ports' or a device */
+		if (!node->parent->bus &&
+		    (streq(node->parent->name, "ports") || get_property(node, "reg")))
+			node->parent->bus = &graph_ports_bus;
+
+		break;
+	}
+
+}
+WARNING(graph_nodes, check_graph_nodes, NULL);
+
+static void check_graph_child_address(struct check *c, struct dt_info *dti,
+				      struct node *node)
+{
+	int cnt = 0;
+	struct node *child;
+
+	if (node->bus != &graph_ports_bus && node->bus != &graph_port_bus)
+		return;
+
+	for_each_child(node, child) {
+		struct property *prop = get_property(child, "reg");
+
+		/* No error if we have any non-zero unit address */
+		if (prop && propval_cell(prop) != 0)
+			return;
+
+		cnt++;
+	}
+
+	if (cnt == 1 && node->addr_cells != -1)
+		FAIL(c, dti, node, "graph node has single child node '%s', #address-cells/#size-cells are not necessary",
+		     node->children->name);
+}
+WARNING(graph_child_address, check_graph_child_address, NULL, &graph_nodes);
+
+static void check_graph_reg(struct check *c, struct dt_info *dti,
+			    struct node *node)
+{
+	char unit_addr[9];
+	const char *unitname = get_unitname(node);
+	struct property *prop;
+
+	prop = get_property(node, "reg");
+	if (!prop || !unitname)
+		return;
+
+	if (!(prop->val.val && prop->val.len == sizeof(cell_t))) {
+		FAIL(c, dti, node, "graph node malformed 'reg' property");
+		return;
+	}
+
+	snprintf(unit_addr, sizeof(unit_addr), "%x", propval_cell(prop));
+	if (!streq(unitname, unit_addr))
+		FAIL(c, dti, node, "graph node unit address error, expected \"%s\"",
+		     unit_addr);
+
+	if (node->parent->addr_cells != 1)
+		FAIL_PROP(c, dti, node, get_property(node, "#address-cells"),
+			  "graph node '#address-cells' is %d, must be 1",
+			  node->parent->addr_cells);
+	if (node->parent->size_cells != 0)
+		FAIL_PROP(c, dti, node, get_property(node, "#size-cells"),
+			  "graph node '#size-cells' is %d, must be 0",
+			  node->parent->size_cells);
+}
+
+static void check_graph_port(struct check *c, struct dt_info *dti,
+			     struct node *node)
+{
+	if (node->bus != &graph_port_bus)
+		return;
+
+	if (!strprefixeq(node->name, node->basenamelen, "port"))
+		FAIL(c, dti, node, "graph port node name should be 'port'");
+
+	check_graph_reg(c, dti, node);
+}
+WARNING(graph_port, check_graph_port, NULL, &graph_nodes);
+
+static struct node *get_remote_endpoint(struct check *c, struct dt_info *dti,
+					struct node *endpoint)
+{
+	int phandle;
+	struct node *node;
+	struct property *prop;
+
+	prop = get_property(endpoint, "remote-endpoint");
+	if (!prop)
+		return NULL;
+
+	phandle = propval_cell(prop);
+	/* Give up if this is an overlay with external references */
+	if (phandle == 0 || phandle == -1)
+		return NULL;
+
+	node = get_node_by_phandle(dti->dt, phandle);
+	if (!node)
+		FAIL_PROP(c, dti, endpoint, prop, "graph phandle is not valid");
+
+	return node;
+}
+
+static void check_graph_endpoint(struct check *c, struct dt_info *dti,
+				 struct node *node)
+{
+	struct node *remote_node;
+
+	if (!node->parent || node->parent->bus != &graph_port_bus)
+		return;
+
+	if (!strprefixeq(node->name, node->basenamelen, "endpoint"))
+		FAIL(c, dti, node, "graph endpont node name should be 'endpoint'");
+
+	check_graph_reg(c, dti, node);
+
+	remote_node = get_remote_endpoint(c, dti, node);
+	if (!remote_node)
+		return;
+
+	if (get_remote_endpoint(c, dti, remote_node) != node)
+		FAIL(c, dti, node, "graph connection to node '%s' is not bidirectional",
+		     remote_node->fullpath);
+}
+WARNING(graph_endpoint, check_graph_endpoint, NULL, &graph_nodes);
+
 static struct check *check_table[] = {
 	&duplicate_node_names, &duplicate_property_names,
 	&node_name_chars, &node_name_format, &property_name_chars,
@@ -1404,6 +1585,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,
 
@@ -1430,6 +1612,8 @@  static struct check *check_table[] = {
 
 	&alias_paths,
 
+	&graph_nodes, &graph_child_address, &graph_port, &graph_endpoint,
+
 	&always_fail,
 };
 
diff --git a/scripts/dtc/dtc-parser.y b/scripts/dtc/dtc-parser.y
index 66ff7f7d8eb7..011a5b25539a 100644
--- a/scripts/dtc/dtc-parser.y
+++ b/scripts/dtc/dtc-parser.y
@@ -191,18 +191,18 @@  devicetree:
 		}
 	| devicetree DT_REF nodedef
 		{
-			struct node *target = get_node_by_ref($1, $2);
-
-			if (target) {
-				merge_nodes(target, $3);
+			/*
+			 * We rely on the rule being always:
+			 *   versioninfo plugindecl memreserves devicetree
+			 * so $-1 is what we want (plugindecl)
+			 */
+			if ($<flags>-1 & DTSF_PLUGIN) {
+				add_orphan_node($1, $3, $2);
 			} else {
-				/*
-				 * We rely on the rule being always:
-				 *   versioninfo plugindecl memreserves devicetree
-				 * so $-1 is what we want (plugindecl)
-				 */
-				if ($<flags>-1 & DTSF_PLUGIN)
-					add_orphan_node($1, $3, $2);
+				struct node *target = get_node_by_ref($1, $2);
+
+				if (target)
+					merge_nodes(target, $3);
 				else
 					ERROR(&@2, "Label or path %s not found", $2);
 			}
diff --git a/scripts/dtc/livetree.c b/scripts/dtc/livetree.c
index 81b6c484542d..6e4c367f54b3 100644
--- a/scripts/dtc/livetree.c
+++ b/scripts/dtc/livetree.c
@@ -238,10 +238,16 @@  struct node * add_orphan_node(struct node *dt, struct node *new_node, char *ref)
 	struct data d = empty_data;
 	char *name;
 
-	d = data_add_marker(d, REF_PHANDLE, ref);
-	d = data_append_integer(d, 0xffffffff, 32);
+	if (ref[0] == '/') {
+		d = data_append_data(d, ref, strlen(ref) + 1);
 
-	p = build_property("target", d);
+		p = build_property("target-path", d);
+	} else {
+		d = data_add_marker(d, REF_PHANDLE, ref);
+		d = data_append_integer(d, 0xffffffff, 32);
+
+		p = build_property("target", d);
+	}
 
 	xasprintf(&name, "fragment@%u",
 			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"