[U-Boot] [PATCH 12/22] dm: core: Add a method to find a driver for a livetree node

Simon Glass sjg at chromium.org
Wed Jan 18 06:51:48 CET 2017


We already have a means to locate drivers for flat device tree nodes. Add
a separate method for the live tree.

TODO: Refactor this to avoid code duplication.

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

 drivers/core/lists.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 include/dm/lists.h   |  5 ++++
 2 files changed, 81 insertions(+)

diff --git a/drivers/core/lists.c b/drivers/core/lists.c
index 72c55e205f9..b9bfbf5cc86 100644
--- a/drivers/core/lists.c
+++ b/drivers/core/lists.c
@@ -12,6 +12,7 @@
 #include <dm/device.h>
 #include <dm/device-internal.h>
 #include <dm/lists.h>
+#include <dm/of_access.h>
 #include <dm/platdata.h>
 #include <dm/uclass.h>
 #include <dm/util.h>
@@ -199,4 +200,79 @@ int lists_bind_fdt(struct udevice *parent, const void *blob, int offset,
 
 	return result;
 }
+
+#ifdef CONFIG_OF_LIVE
+/*
+ * TODO(sjg at chromium.org): Perhaps we can use np_to_offset(np)() to merge this
+ * function with lists_bind_fdt()
+ */
+int lists_bind_node(struct udevice *parent, struct device_node *np,
+		    struct udevice **devp)
+{
+	struct driver *driver = ll_entry_start(struct driver, driver);
+	const int n_ents = ll_entry_count(struct driver, driver);
+	const struct udevice_id *id;
+	struct driver *entry;
+	struct udevice *dev;
+	bool found = false;
+	const struct property *compat_prop;
+	const char *compat;
+	int compat_length, i;
+	int result = 0;
+	int ret = 0;
+
+	if (devp)
+		*devp = NULL;
+	dm_dbg("bind node %s\n", np->name);
+
+	compat_prop = of_find_property(np, "compatible", &compat_length);
+	if (!compat_prop) {
+		dm_dbg("Device '%s' has no compatible string\n", np->name);
+		return 0;
+	}
+
+	/*
+	 * Walk through the compatible string list, attempting to match each
+	 * compatible string in order such that we match in order of priority
+	 * from the first string to the last.
+	 */
+	for (i = 0; i < compat_prop->length; i += strlen(compat) + 1) {
+		compat = compat_prop->value + i;
+		dm_dbg("   - attempt to match compatible string '%s'\n",
+		       compat);
+
+		for (entry = driver; entry != driver + n_ents; entry++) {
+			ret = driver_check_compatible(entry->of_match, &id,
+						      compat);
+			if (!ret)
+				break;
+		}
+		if (entry == driver + n_ents)
+			continue;
+
+		dm_dbg("   - found match at '%s'\n", entry->name);
+		ret = device_bind_node_with_driver_data(parent, entry, np->name,
+							id->data, np, &dev);
+		if (ret == -ENODEV) {
+			dm_dbg("Driver '%s' refuses to bind\n", entry->name);
+			continue;
+		}
+		if (ret) {
+			dm_warn("Error binding driver '%s': %d\n", entry->name,
+				ret);
+			return ret;
+		} else {
+			found = true;
+			if (devp)
+				*devp = dev;
+		}
+		break;
+	}
+
+	if (!found && !result && ret != -ENODEV)
+		dm_dbg("No match for node '%s'\n", np->name);
+
+	return result;
+}
+#endif /* CONFIG_OF_LIVE */
 #endif
diff --git a/include/dm/lists.h b/include/dm/lists.h
index 4513d6a311a..2ca7079bc86 100644
--- a/include/dm/lists.h
+++ b/include/dm/lists.h
@@ -12,6 +12,8 @@
 
 #include <dm/uclass-id.h>
 
+struct device_node;
+
 /**
  * lists_driver_lookup_name() - Return u_boot_driver corresponding to name
  *
@@ -60,6 +62,9 @@ int lists_bind_drivers(struct udevice *parent, bool pre_reloc_only);
 int lists_bind_fdt(struct udevice *parent, const void *blob, int offset,
 		   struct udevice **devp);
 
+int lists_bind_node(struct udevice *parent, struct device_node *np,
+		    struct udevice **devp);
+
 /**
  * device_bind_driver() - bind a device to a driver
  *
-- 
2.11.0.483.g087da7b7c-goog



More information about the U-Boot mailing list