[PATCH 10/19] ofnode: Allow writing to a flat tree

Simon Glass sjg at chromium.org
Wed Jul 20 18:59:38 CEST 2022


In generally it is not permitted to implement an ofnode function only for
flat tree or live tree. Both must be supported. Also the code for
live tree access should be in of_access.c rather than ofnode.c which is
really just for holding the API-conversion code.

Update ofnode_write_prop() accordingly and fix the test so it can work
with flat tree too.

Signed-off-by: Simon Glass <sjg at chromium.org>
---

 drivers/core/of_access.c | 43 +++++++++++++++++++++++++++++++++
 drivers/core/ofnode.c    | 51 ++++------------------------------------
 include/dm/of_access.h   | 12 ++++++++++
 include/dm/ofnode.h      | 18 ++++++++++++++
 test/dm/ofnode.c         | 14 +++++------
 5 files changed, 85 insertions(+), 53 deletions(-)

diff --git a/drivers/core/of_access.c b/drivers/core/of_access.c
index 0e5915a43e6..a52f5a6b18b 100644
--- a/drivers/core/of_access.c
+++ b/drivers/core/of_access.c
@@ -887,3 +887,46 @@ struct device_node *of_get_stdout(void)
 {
 	return of_stdout;
 }
+
+int of_write_prop(struct device_node *np, const char *propname, int len,
+		  const void *value)
+{
+	struct property *pp;
+	struct property *pp_last = NULL;
+	struct property *new;
+
+	if (!np)
+		return -EINVAL;
+
+	for (pp = np->properties; pp; pp = pp->next) {
+		if (strcmp(pp->name, propname) == 0) {
+			/* Property exists -> change value */
+			pp->value = (void *)value;
+			pp->length = len;
+			return 0;
+		}
+		pp_last = pp;
+	}
+
+	if (!pp_last)
+		return -ENOENT;
+
+	/* Property does not exist -> append new property */
+	new = malloc(sizeof(struct property));
+	if (!new)
+		return -ENOMEM;
+
+	new->name = strdup(propname);
+	if (!new->name) {
+		free(new);
+		return -ENOMEM;
+	}
+
+	new->value = (void *)value;
+	new->length = len;
+	new->next = NULL;
+
+	pp_last->next = new;
+
+	return 0;
+}
diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c
index 1c9542a3567..b7a55589a1c 100644
--- a/drivers/core/ofnode.c
+++ b/drivers/core/ofnode.c
@@ -1108,55 +1108,17 @@ ofnode ofnode_by_prop_value(ofnode from, const char *propname,
 int ofnode_write_prop(ofnode node, const char *propname, const void *value,
 		      int len)
 {
-	const struct device_node *np = ofnode_to_np(node);
-	struct property *pp;
-	struct property *pp_last = NULL;
-	struct property *new;
-
-	if (!of_live_active())
-		return -ENOSYS;
-
-	if (!np)
-		return -EINVAL;
-
-	for (pp = np->properties; pp; pp = pp->next) {
-		if (strcmp(pp->name, propname) == 0) {
-			/* Property exists -> change value */
-			pp->value = (void *)value;
-			pp->length = len;
-			return 0;
-		}
-		pp_last = pp;
-	}
-
-	if (!pp_last)
-		return -ENOENT;
-
-	/* Property does not exist -> append new property */
-	new = malloc(sizeof(struct property));
-	if (!new)
-		return -ENOMEM;
-
-	new->name = strdup(propname);
-	if (!new->name) {
-		free(new);
-		return -ENOMEM;
-	}
-
-	new->value = (void *)value;
-	new->length = len;
-	new->next = NULL;
-
-	pp_last->next = new;
+	if (of_live_active())
+		return of_write_prop(ofnode_to_npw(node), propname, len, value);
+	else
+		return fdt_setprop((void *)gd->fdt_blob, ofnode_to_offset(node),
+				   propname, value, len);
 
 	return 0;
 }
 
 int ofnode_write_string(ofnode node, const char *propname, const char *value)
 {
-	if (!of_live_active())
-		return -ENOSYS;
-
 	assert(ofnode_valid(node));
 
 	debug("%s: %s = %s", __func__, propname, value);
@@ -1166,9 +1128,6 @@ int ofnode_write_string(ofnode node, const char *propname, const char *value)
 
 int ofnode_set_enabled(ofnode node, bool value)
 {
-	if (!of_live_active())
-		return -ENOSYS;
-
 	assert(ofnode_valid(node));
 
 	if (value)
diff --git a/include/dm/of_access.h b/include/dm/of_access.h
index 078f2ea06cd..5b7821d0a1b 100644
--- a/include/dm/of_access.h
+++ b/include/dm/of_access.h
@@ -519,4 +519,16 @@ int of_alias_get_highest_id(const char *stem);
  */
 struct device_node *of_get_stdout(void);
 
+/**
+ * of_write_prop() - Write a property to the device tree
+ *
+ * @np:		device node to which the property value is to be written
+ * @propname:	name of the property to write
+ * @value:	value of the property
+ * @len:	length of the property in bytes
+ * Returns: 0 if OK, -ve on error
+ */
+int of_write_prop(struct device_node *np, const char *propname, int len,
+		  const void *value);
+
 #endif
diff --git a/include/dm/ofnode.h b/include/dm/ofnode.h
index 071a9d63f67..16c8890b097 100644
--- a/include/dm/ofnode.h
+++ b/include/dm/ofnode.h
@@ -44,6 +44,24 @@ static inline const struct device_node *ofnode_to_np(ofnode node)
 	return node.np;
 }
 
+/**
+ * ofnode_to_npw() - convert an ofnode to a writeable live DT node pointer
+ *
+ * This cannot be called if the reference contains an offset.
+ *
+ * @node: Reference containing struct device_node * (possibly invalid)
+ * Return: pointer to device node (can be NULL)
+ */
+static inline struct device_node *ofnode_to_npw(ofnode node)
+{
+#ifdef OF_CHECKS
+	if (!of_live_active())
+		return NULL;
+#endif
+	/* Drop constant */
+	return (struct device_node *)node.np;
+}
+
 /**
  * ofnode_to_offset() - convert an ofnode to a flat DT offset
  *
diff --git a/test/dm/ofnode.c b/test/dm/ofnode.c
index ce96f9d1ee2..bd598d23e44 100644
--- a/test/dm/ofnode.c
+++ b/test/dm/ofnode.c
@@ -549,9 +549,9 @@ static int dm_test_ofnode_livetree_writing(struct unit_test_state *uts)
 	/* Test enabling devices */
 	node = ofnode_path("/usb at 2");
 
-	ut_assert(!of_device_is_available(ofnode_to_np(node)));
-	ofnode_set_enabled(node, true);
-	ut_assert(of_device_is_available(ofnode_to_np(node)));
+	ut_assert(!ofnode_is_enabled(node));
+	ut_assertok(ofnode_set_enabled(node, true));
+	ut_asserteq(true, ofnode_is_enabled(node));
 
 	device_bind_driver_to_node(dm_root(), "usb_sandbox", "usb at 2", node,
 				   &dev);
@@ -577,11 +577,11 @@ static int dm_test_ofnode_livetree_writing(struct unit_test_state *uts)
 	device_remove(dev, DM_REMOVE_NORMAL);
 	device_unbind(dev);
 
-	ut_assert(of_device_is_available(ofnode_to_np(node)));
-	ofnode_set_enabled(node, false);
-	ut_assert(!of_device_is_available(ofnode_to_np(node)));
+	ut_assert(ofnode_is_enabled(node));
+	ut_assertok(ofnode_set_enabled(node, false));
+	ut_assert(!ofnode_is_enabled(node));
 
 	return 0;
 }
 DM_TEST(dm_test_ofnode_livetree_writing,
-	UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT | UT_TESTF_LIVE_TREE);
+	UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT | UT_TESTF_LIVE_OR_FLAT);
-- 
2.37.0.170.g444d1eabd0-goog



More information about the U-Boot mailing list