devicetree: add DT_NODE_FULL_NAME()

This macro returns a node's name with unit-adddress, given its node
identifier.

The node name is useful information for the user to utilize for debug
information, similar to DT_NODE_PATH, or DT_LABEL.

Signed-off-by: Kumar Gala <kumar.gala@linaro.org>
diff --git a/doc/guides/dts/macros.bnf b/doc/guides/dts/macros.bnf
index b5e9ba0..6211198 100644
--- a/doc/guides/dts/macros.bnf
+++ b/doc/guides/dts/macros.bnf
@@ -59,6 +59,8 @@
 node-macro =/ %s"DT_N" path-id %s"_ORD"
 ; The node's path, as a string literal
 node-macro =/ %s"DT_N" path-id %s"_PATH"
+; The node's name@unit-addr, as a string literal
+node-macro =/ %s"DT_N" path-id %s"_FULL_NAME"
 ; The dependency ordinals of a node's requirements (direct dependencies).
 node-macro =/ %s"DT_N" path-id %s"_REQUIRES_ORDS"
 ; The dependency ordinals of a node supports (reverse direct dependencies).
diff --git a/include/devicetree.h b/include/devicetree.h
index 6d7b103..5d5e9d9 100644
--- a/include/devicetree.h
+++ b/include/devicetree.h
@@ -400,6 +400,28 @@
 #define DT_NODE_PATH(node_id) DT_CAT(node_id, _PATH)
 
 /**
+ * @brief Get a devicetree node's name with unit-address as a string literal
+ *
+ * This returns the node name and unit-address from a node identifier.
+ *
+ * Example devicetree fragment:
+ *
+ *     / {
+ *             soc {
+ *                     node: my-node@12345678 { ... };
+ *             };
+ *     };
+ *
+ * Example usage:
+ *
+ *    DT_NODE_FULL_NAME(DT_NODELABEL(node)) // "my-node@12345678"
+ *
+ * @param node_id node identifier
+ * @return the node's name with unit-address as a string in the devicetree
+ */
+#define DT_NODE_FULL_NAME(node_id) DT_CAT(node_id, _FULL_NAME)
+
+/**
  * @brief Do node_id1 and node_id2 refer to the same node?
  *
  * Both "node_id1" and "node_id2" must be node identifiers for nodes
diff --git a/scripts/dts/gen_defines.py b/scripts/dts/gen_defines.py
index 2d8bb56..51b2e5c 100755
--- a/scripts/dts/gen_defines.py
+++ b/scripts/dts/gen_defines.py
@@ -98,6 +98,10 @@
             out_comment("Node's full path:")
             out_dt_define(f"{node.z_path_id}_PATH", f'"{escape(node.path)}"')
 
+            out_comment("Node's name with unit-address:")
+            out_dt_define(f"{node.z_path_id}_FULL_NAME",
+                          f'"{escape(node.name)}"')
+
             if node.parent is not None:
                 out_comment(f"Node parent ({node.parent.path}) identifier:")
                 out_dt_define(f"{node.z_path_id}_PARENT",
diff --git a/tests/lib/devicetree/api/src/main.c b/tests/lib/devicetree/api/src/main.c
index c1d77a2..381a2b2 100644
--- a/tests/lib/devicetree/api/src/main.c
+++ b/tests/lib/devicetree/api/src/main.c
@@ -1665,6 +1665,17 @@
 			     "/test/gpio@deadbeef"), "");
 }
 
+static void test_node_name(void)
+{
+	zassert_true(!strcmp(DT_NODE_FULL_NAME(DT_ROOT), "/"), "");
+	zassert_true(!strcmp(DT_NODE_FULL_NAME(TEST_DEADBEEF),
+			     "gpio@deadbeef"), "");
+	zassert_true(!strcmp(DT_NODE_FULL_NAME(TEST_TEMP),
+			     "temperature-sensor"), "");
+	zassert_true(strcmp(DT_NODE_FULL_NAME(TEST_REG),
+			     "reg-holder"), "");
+}
+
 static void test_same_node(void)
 {
 	zassert_true(DT_SAME_NODE(TEST_DEADBEEF, TEST_DEADBEEF), "");
@@ -1706,6 +1717,7 @@
 			 ztest_unit_test(test_great_grandchild),
 			 ztest_unit_test(test_dep_ord),
 			 ztest_unit_test(test_path),
+			 ztest_unit_test(test_node_name),
 			 ztest_unit_test(test_same_node)
 		);
 	ztest_run_test_suite(devicetree_api);