From: Markus Schneider-Pargmann (TI.com) Date: Tue, 27 Jan 2026 11:03:37 +0000 (+0100) Subject: dm: core: Support multiple drivers with same compatibles X-Git-Tag: v2026.04-rc2~52^2~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6668b8e7cc68;p=thirdparty%2Fu-boot.git dm: core: Support multiple drivers with same compatibles 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. The loop had to be adjusted a bit to still support the 'drv' argument properly. Some simplifications were done as well. The modification will only add additional loop iterations if -ENODEV is returned. Otherwise the exit and continue conditions for the loop stay the same and do not cause any additional iterations and should not impact performance. 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. Reviewed-by: Simon Glass Acked-by: Dinesh Maniyam Signed-off-by: Markus Schneider-Pargmann (TI.com) --- diff --git a/drivers/core/lists.c b/drivers/core/lists.c index 9d1ca38212e..813c3de52b2 100644 --- a/drivers/core/lists.c +++ b/drivers/core/lists.c @@ -235,50 +235,51 @@ 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++) { + /* Search for drivers with matching drv or existing of_match */ if (drv) { if (drv != entry) continue; - if (!entry->of_match) - break; + } else if (!entry->of_match) { + continue; } - ret = driver_check_compatible(entry->of_match, &id, - compat); - if (!ret) - 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; + + id = NULL; + if (entry->of_match) { + ret = driver_check_compatible(entry->of_match, &id, + compat); + if (ret) + continue; + log_debug(" - found match at driver '%s' for '%s'\n", + entry->name, id->compatible); + } + + if (pre_reloc_only) { + if (!ofnode_pre_reloc(node) && + !(entry->flags & DM_FLAG_PRE_RELOC)) { + log_debug("Skipping device pre-relocation\n"); + return 0; + } + } + + ret = device_bind_with_driver_data(parent, entry, name, + id ? id->data : 0, node, + &dev); + if (!drv && 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); } - } - 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 { if (devp) *devp = dev; + return 0; } - break; } if (ret != -ENODEV)