summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilipp Tomsich <philipp.tomsich@theobroma-systems.com>2017-03-03 18:16:06 +0100
committerPhilipp Tomsich <philipp.tomsich@theobroma-systems.com>2017-03-09 01:40:25 +0100
commitd3195c112354ffa9e25651057b491623d760d1a2 (patch)
tree37c9f550e868703ad29565e8de128a6e3e077f98
parent86fb4c92859d945dc84c4d938fb4cb06b903476d (diff)
[f] revise DM_ALLOW_MULTIPLE_DRIVERS for SJG-comments
-rw-r--r--drivers/core/Kconfig1
-rw-r--r--drivers/core/lists.c87
-rw-r--r--include/dm/lists.h6
3 files changed, 55 insertions, 39 deletions
diff --git a/drivers/core/Kconfig b/drivers/core/Kconfig
index 913101ce87..4af8505695 100644
--- a/drivers/core/Kconfig
+++ b/drivers/core/Kconfig
@@ -34,7 +34,6 @@ config DM_WARN
config DM_ALLOW_MULTIPLE_DRIVERS
bool "Allow multiple drivers to bind for one node"
depends on DM
- default n
help
The driver model in U-Boot originally did not allow multiple
drivers to bind for a single device node.
diff --git a/drivers/core/lists.c b/drivers/core/lists.c
index 912469381b..af1657c6e2 100644
--- a/drivers/core/lists.c
+++ b/drivers/core/lists.c
@@ -126,15 +126,55 @@ static int driver_check_compatible(const struct udevice_id *of_match,
return -ENOENT;
}
-int lists_bind_fdt(struct udevice *parent, const void *blob, int offset,
- struct udevice **devp)
+static bool driver_bind_next(struct driver **entryp, struct udevice *parent,
+ const char *name, int offset, const char *compat,
+ struct udevice **devp)
{
struct driver *driver = ll_entry_start(struct driver, driver);
const int n_ents = ll_entry_count(struct driver, driver);
+ struct driver *entry = *entryp;
+ struct udevice *dev;
const struct udevice_id *id;
+ bool found = false;
+ int ret;
+
+ for (; entry != driver + n_ents; entry++) {
+ ret = driver_check_compatible(entry->of_match, &id,
+ compat);
+ if (!ret)
+ break;
+ }
+
+ if (entry == driver + n_ents) {
+ *entryp = NULL;
+ return false;
+ }
+
+ dm_dbg(" - found match at '%s'\n", entry->name);
+ ret = device_bind_with_driver_data(parent, entry, name,
+ id->data, offset, &dev);
+ if (ret == -ENODEV)
+ dm_dbg("Driver '%s' refuses to bind\n", entry->name);
+
+ if (ret) {
+ dm_warn("Error binding driver '%s': %d\n", entry->name, ret);
+ } else {
+ found = true;
+ if (devp)
+ *devp = dev;
+ }
+
+ *entryp = entry + 1; /* advance onto the next element */
+ return found;
+}
+
+int lists_bind_fdt(struct udevice *parent, const void *blob, int offset,
+ struct udevice **devp)
+{
+ struct driver *driver = ll_entry_start(struct driver, driver);
struct driver *entry;
- struct udevice *dev;
bool found = false;
+ bool allow_multiple = CONFIG_IS_ENABLED(DM_ALLOW_MULTIPLE_DRIVERS);
const char *name, *compat_list, *compat;
int compat_length, i;
int result = 0;
@@ -166,42 +206,13 @@ int lists_bind_fdt(struct udevice *parent, const void *blob, int offset,
dm_dbg(" - attempt to match compatible string '%s'\n",
compat);
- entry = driver;
-#if defined(CONFIG_DM_ALLOW_MULTIPLE_DRIVERS)
-allow_more_matches:
-#endif
- for (; 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_with_driver_data(parent, entry, name,
- id->data, offset, &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;
-#if defined(CONFIG_DM_ALLOW_MULTIPLE_DRIVERS)
- else {
- entry++;
- goto allow_more_matches;
- }
-#endif
+ for (entry = driver; entry;) {
+ found = driver_bind_next(&entry, parent, name,
+ offset, compat, devp);
+
+ if (found && (devp || !allow_multiple))
+ return 0;
}
- break;
}
if (!found && !result && ret != -ENODEV)
diff --git a/include/dm/lists.h b/include/dm/lists.h
index 4513d6a311..e300f4f4c9 100644
--- a/include/dm/lists.h
+++ b/include/dm/lists.h
@@ -65,6 +65,12 @@ int lists_bind_fdt(struct udevice *parent, const void *blob, int offset,
*
* This binds a new device to a driver.
*
+ * If DM_ALLOW_MULTIPLE_DRIVERS is configured and devp is NULL, it
+ * will continue through the list of drivers and bind all drivers that
+ * match the compatible string. If not configured or devp is
+ * non-NULL, it will stop after the first driver that successfully
+ * binds.
+ *
* @parent: Parent device
* @drv_name: Name of driver to attach to this parent
* @dev_name: Name of the new device thus created