Currently once a driver matched the compatible string of a device, other drivers are ignored. If the first matching driver returns -ENODEV, no other possibly matching drivers are iterated with that compatible of the device. Instead the next compatible in the list of compatibles is selected, assuming only one driver matches one compatible at a time.
To be able to use the bind function to return -ENODEV and continue matching other drivers with the same compatible, move the for loop a bit to continue the for loop after -ENODEV was returned. This is required for ti-musb-host and ti-musb-peripheral which both match on the same device but differ based on the dr_mode DT property. Depending on this property, the driver is either UCLASS_USB or UCLASS_USB_GADGET_GENERIc. By checking the DT property in the bind function and returning -ENODEV the other driver can probe instead. Signed-off-by: Markus Schneider-Pargmann (TI.com) <[email protected]> --- drivers/core/lists.c | 62 +++++++++++++++++++++++++++------------------------- 1 file changed, 32 insertions(+), 30 deletions(-) diff --git a/drivers/core/lists.c b/drivers/core/lists.c index c7be504b6fc69ec2870a6766eed35cb9eba46a97..144e31286b3bb53a90b4f8bb0d3fba6e25a47f9e 100644 --- a/drivers/core/lists.c +++ b/drivers/core/lists.c @@ -237,8 +237,9 @@ int lists_bind_fdt(struct udevice *parent, ofnode node, struct udevice **devp, log_debug(" - attempt to match compatible string '%s'\n", compat); - id = NULL; for (entry = driver; entry != driver + n_ents; entry++) { + id = NULL; + if (drv) { if (drv != entry) continue; @@ -247,39 +248,40 @@ int lists_bind_fdt(struct udevice *parent, ofnode node, struct udevice **devp, } ret = driver_check_compatible(entry->of_match, &id, compat); - if (!ret) - break; + if (ret) + continue; + if (pre_reloc_only) { + if (!ofnode_pre_reloc(node) && + !(entry->flags & DM_FLAG_PRE_RELOC)) { + log_debug("Skipping device pre-relocation\n"); + return 0; + } + } + + if (entry->of_match) + log_debug(" - found match at driver '%s' for '%s'\n", + entry->name, id->compatible); + ret = device_bind_with_driver_data(parent, entry, name, + id ? id->data : 0, node, + &dev); + if (ret == -ENODEV) { + log_debug("Driver '%s' refuses to bind\n", entry->name); + continue; + } + if (ret) { + dm_warn("Error binding driver '%s': %d\n", entry->name, + ret); + return log_msg_ret("bind", ret); + } + + found = true; + if (devp) + *devp = dev; + break; } if (entry == driver + n_ents) continue; - if (pre_reloc_only) { - if (!ofnode_pre_reloc(node) && - !(entry->flags & DM_FLAG_PRE_RELOC)) { - log_debug("Skipping device pre-relocation\n"); - return 0; - } - } - - if (entry->of_match) - log_debug(" - found match at driver '%s' for '%s'\n", - entry->name, id->compatible); - ret = device_bind_with_driver_data(parent, entry, name, - id ? id->data : 0, node, - &dev); - if (ret == -ENODEV) { - log_debug("Driver '%s' refuses to bind\n", entry->name); - continue; - } - if (ret) { - dm_warn("Error binding driver '%s': %d\n", entry->name, - ret); - return log_msg_ret("bind", ret); - } else { - found = true; - if (devp) - *devp = dev; - } break; } -- 2.51.0

