summaryrefslogtreecommitdiffstats
path: root/drivers/core/device.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/core/device.c')
-rw-r--r--drivers/core/device.c78
1 files changed, 78 insertions, 0 deletions
diff --git a/drivers/core/device.c b/drivers/core/device.c
index fd59fe1e0f..feed43c8c3 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -516,6 +516,33 @@ static int device_get_device_tail(struct udevice *dev, int ret,
return 0;
}
+/**
+ * device_find_by_ofnode() - Return device associated with given ofnode
+ *
+ * The returned device is *not* activated.
+ *
+ * @node: The ofnode for which a associated device should be looked up
+ * @devp: Pointer to structure to hold the found device
+ * Return: 0 if OK, -ve on error
+ */
+static int device_find_by_ofnode(ofnode node, struct udevice **devp)
+{
+ struct uclass *uc;
+ struct udevice *dev;
+ int ret;
+
+ list_for_each_entry(uc, &gd->uclass_root, sibling_node) {
+ ret = uclass_find_device_by_ofnode(uc->uc_drv->id, node,
+ &dev);
+ if (!ret || dev) {
+ *devp = dev;
+ return 0;
+ }
+ }
+
+ return -ENODEV;
+}
+
int device_get_child(struct udevice *parent, int index, struct udevice **devp)
{
struct udevice *dev;
@@ -739,3 +766,54 @@ bool of_machine_is_compatible(const char *compat)
return !fdt_node_check_compatible(fdt, 0, compat);
}
+
+int dev_disable_by_path(const char *path)
+{
+ struct uclass *uc;
+ ofnode node = ofnode_path(path);
+ struct udevice *dev;
+ int ret = 1;
+
+ if (!of_live_active())
+ return -ENOSYS;
+
+ list_for_each_entry(uc, &gd->uclass_root, sibling_node) {
+ ret = uclass_find_device_by_ofnode(uc->uc_drv->id, node, &dev);
+ if (!ret)
+ break;
+ }
+
+ if (ret)
+ return ret;
+
+ ret = device_remove(dev, DM_REMOVE_NORMAL);
+ if (ret)
+ return ret;
+
+ ret = device_unbind(dev);
+ if (ret)
+ return ret;
+
+ return ofnode_set_enabled(node, false);
+}
+
+int dev_enable_by_path(const char *path)
+{
+ ofnode node = ofnode_path(path);
+ ofnode pnode = ofnode_get_parent(node);
+ struct udevice *parent;
+ int ret = 1;
+
+ if (!of_live_active())
+ return -ENOSYS;
+
+ ret = device_find_by_ofnode(pnode, &parent);
+ if (ret)
+ return ret;
+
+ ret = ofnode_set_enabled(node, true);
+ if (ret)
+ return ret;
+
+ return lists_bind_fdt(parent, node, NULL);
+}