[U-Boot] [PATCH v3 3/4] core: Add dev_{disable,enable}_by_path

Mario Six mario.six at gdsys.cc
Tue Jun 26 06:46:50 UTC 2018


We cannot use device structures to disable devices, since getting
them with the API functions would bind and activate the device, which
would fail if the underlying device does not exist.

---

Hence, add a function to disable devices by path in a live device tree.

Signed-off-by: Mario Six <mario.six at gdsys.cc>

v2 -> v3:
* Renamed res to ret
* Introduced device_find_by_ofnode() function
* Fixed error handling in some places

v1 -> v2:
* Simplified np_to_ofnode(of_find_node_by_path(path)) to ofnode_path(path)
* Switched to returning -ENOSYS if livetree is not enabled

---
 drivers/core/device.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++
 include/dm/device.h   | 16 +++++++++++
 2 files changed, 94 insertions(+)

diff --git a/drivers/core/device.c b/drivers/core/device.c
index e048e1a6595..c0037a2eeaf 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -501,6 +501,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;
@@ -717,3 +744,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);
+}
diff --git a/include/dm/device.h b/include/dm/device.h
index 49078bc6b36..7d569f91979 100644
--- a/include/dm/device.h
+++ b/include/dm/device.h
@@ -586,6 +586,22 @@ bool device_is_compatible(struct udevice *dev, const char *compat);
 bool of_machine_is_compatible(const char *compat);

 /**
+ * dev_disable_by_path() - Disable a device given its device tree path
+ *
+ * @path:	The device tree path identifying the device to be disabled
+ * @return 0 on success, -ve on error
+ */
+int dev_disable_by_path(const char *path);
+
+/**
+ * dev_enable_by_path() - Enable a device given its device tree path
+ *
+ * @path:	The device tree path identifying the device to be enabled
+ * @return 0 on success, -ve on error
+ */
+int dev_enable_by_path(const char *path);
+
+/**
  * device_is_on_pci_bus - Test if a device is on a PCI bus
  *
  * @dev:	device to test
--
2.11.0



More information about the U-Boot mailing list