aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorSimon Glass2023-09-26 08:14:42 -0600
committerTom Rini2023-10-06 14:38:13 -0400
commit67fb2159fb3438359fa0fc3f8cb491ffe8d57c0f (patch)
tree6a61f1cb1fe3ecc763fac9bdb6b1ac17e67490e6 /drivers
parentc15862ffdd5f7797338808cf7645786109bcddc3 (diff)
dm: core: Add a way to delete a node
Add a function to delete a node in an existing tree. Signed-off-by: Simon Glass <sjg@chromium.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/core/of_access.c65
-rw-r--r--drivers/core/ofnode.c23
2 files changed, 88 insertions, 0 deletions
diff --git a/drivers/core/of_access.c b/drivers/core/of_access.c
index 1bb4d8eab70..c8db743f529 100644
--- a/drivers/core/of_access.c
+++ b/drivers/core/of_access.c
@@ -1040,3 +1040,68 @@ int of_add_subnode(struct device_node *parent, const char *name, int len,
return 0;
}
+
+int __of_remove_property(struct device_node *np, struct property *prop)
+{
+ struct property **next;
+
+ for (next = &np->properties; *next; next = &(*next)->next) {
+ if (*next == prop)
+ break;
+ }
+ if (!*next)
+ return -ENODEV;
+
+ /* found the node */
+ *next = prop->next;
+
+ return 0;
+}
+
+int of_remove_property(struct device_node *np, struct property *prop)
+{
+ int rc;
+
+ mutex_lock(&of_mutex);
+
+ rc = __of_remove_property(np, prop);
+
+ mutex_unlock(&of_mutex);
+
+ return rc;
+}
+
+int of_remove_node(struct device_node *to_remove)
+{
+ struct device_node *parent = to_remove->parent;
+ struct device_node *np, *prev;
+
+ if (!parent)
+ return -EPERM;
+ prev = NULL;
+ __for_each_child_of_node(parent, np) {
+ if (np == to_remove)
+ break;
+ prev = np;
+ }
+ if (!np)
+ return -EFAULT;
+
+ /* if there is a previous node, link it to this one's sibling */
+ if (prev)
+ prev->sibling = np->sibling;
+ else
+ parent->child = np->sibling;
+
+ /*
+ * don't free it, since if this is an unflattened tree, all the memory
+ * was alloced in one block; this pointer will be somewhere in the
+ * middle of that
+ *
+ * TODO(sjg@chromium.org): Consider marking nodes as 'allocated'?
+ *
+ * free(np);
+ */
+
+ return 0;
+}
diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c
index 403ee06ad94..a5efedf6af3 100644
--- a/drivers/core/ofnode.c
+++ b/drivers/core/ofnode.c
@@ -1779,6 +1779,29 @@ int ofnode_add_subnode(ofnode node, const char *name, ofnode *subnodep)
return ret; /* 0 or -EEXIST */
}
+int ofnode_delete(ofnode *nodep)
+{
+ ofnode node = *nodep;
+ int ret;
+
+ assert(ofnode_valid(node));
+ if (ofnode_is_np(node)) {
+ ret = of_remove_node(ofnode_to_np(node));
+ } else {
+ void *fdt = ofnode_to_fdt(node);
+ int offset = ofnode_to_offset(node);
+
+ ret = fdt_del_node(fdt, offset);
+ if (ret)
+ ret = -EFAULT;
+ }
+ if (ret)
+ return ret;
+ *nodep = ofnode_null();
+
+ return 0;
+}
+
int ofnode_copy_props(ofnode dst, ofnode src)
{
struct ofprop prop;