summaryrefslogtreecommitdiff
path: root/drivers/usb
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/host/usb-uclass.c36
1 files changed, 36 insertions, 0 deletions
diff --git a/drivers/usb/host/usb-uclass.c b/drivers/usb/host/usb-uclass.c
index 7a03435ba7..e5fe949f25 100644
--- a/drivers/usb/host/usb-uclass.c
+++ b/drivers/usb/host/usb-uclass.c
@@ -249,6 +249,37 @@ static void remove_inactive_children(struct uclass *uc, struct udevice *bus)
}
}
+static int usb_probe_companion(struct udevice *bus)
+{
+ struct udevice *companion_dev;
+ int ret;
+
+ /*
+ * Enforce optional companion controller is marked as such in order to
+ * 1st scan the primary controller, before the companion controller
+ * (ownership is given to companion when low or full speed devices
+ * have been detected).
+ */
+ ret = uclass_get_device_by_phandle(UCLASS_USB, bus, "companion", &companion_dev);
+ if (!ret) {
+ struct usb_bus_priv *companion_bus_priv;
+
+ debug("%s is the companion of %s\n", companion_dev->name, bus->name);
+ companion_bus_priv = dev_get_uclass_priv(companion_dev);
+ companion_bus_priv->companion = true;
+ } else if (ret && ret != -ENOENT && ret != -ENODEV) {
+ /*
+ * Treat everything else than no companion or disabled
+ * companion as an error. (It may not be enabled on boards
+ * that have a High-Speed HUB to handle FS and LS traffic).
+ */
+ printf("Failed to get companion (ret=%d)\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
int usb_init(void)
{
int controllers_initialized = 0;
@@ -299,6 +330,11 @@ int usb_init(void)
printf("probe failed, error %d\n", ret);
continue;
}
+
+ ret = usb_probe_companion(bus);
+ if (ret)
+ continue;
+
controllers_initialized++;
usb_started = true;
}