summaryrefslogtreecommitdiff
path: root/drivers/core
diff options
context:
space:
mode:
authorMarkus Schneider-Pargmann (TI.com) <[email protected]>2026-01-27 12:03:37 +0100
committerTom Rini <[email protected]>2026-01-28 09:20:59 -0600
commit6668b8e7cc68ee287ef87e18aadc97bf88cea4db (patch)
tree809226e290cfec39b2b0a181e1f9a44e9c4430eb /drivers/core
parent41cf66011fc80bd122c3ebbeda4218547c48c297 (diff)
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 <[email protected]> Acked-by: Dinesh Maniyam <[email protected]> Signed-off-by: Markus Schneider-Pargmann (TI.com) <[email protected]>
Diffstat (limited to 'drivers/core')
-rw-r--r--drivers/core/lists.c67
1 files changed, 34 insertions, 33 deletions
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)