Most of the time the UDC is bound to a driver when a dedicated command is executed, like 'dfu'. But the ethernet gadget driver must be bound by calling usb_ether_init() in the code otherwise the USB ethernet adapter is not visible to the ethernet core.
In DM context, the platform code should not be used to bind UDC to a particular driver, so adding a new command to bind a USB device port to a driver. usage example: usbdev bind 0 usb_ether usbdev unbind 0 Signed-off-by: Jean-Jacques Hiblot <jjhib...@ti.com> --- cmd/usb.c | 71 +++++++++++++++++++++++++++++++++++++++++++- drivers/core/device-remove.c | 11 +------ include/dm/device-internal.h | 15 ++++++++++ 3 files changed, 86 insertions(+), 11 deletions(-) diff --git a/cmd/usb.c b/cmd/usb.c index 0ccb1b5..03245cb 100644 --- a/cmd/usb.c +++ b/cmd/usb.c @@ -14,6 +14,8 @@ #include <command.h> #include <console.h> #include <dm.h> +#include <dm/lists.h> +#include <dm/device-internal.h> #include <dm/uclass-internal.h> #include <memalign.h> #include <asm/byteorder.h> @@ -753,7 +755,6 @@ U_BOOT_CMD( #endif /* CONFIG_USB_STORAGE */ ); - #ifdef CONFIG_USB_STORAGE U_BOOT_CMD( usbboot, 3, 1, do_usbboot, @@ -761,3 +762,71 @@ U_BOOT_CMD( "loadAddr dev:part" ); #endif /* CONFIG_USB_STORAGE */ + +#ifdef CONFIG_DM_USB_DEV +int do_usbdev(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + struct udevice *dev; + struct udevice *usb_dev; + int port; + int ret; + bool bind; + static const char * const supported_drivers[] = { +#ifdef CONFIG_USB_ETHER + "usb_ether", +#endif + }; + + if (argc < 2) + return CMD_RET_USAGE; + + if ((strncmp(argv[1], "bind", 4) == 0) && (argc == 4)) { + port = simple_strtoul(argv[2], NULL, 10); + printf("Binding USB port %d to %s\n", port, argv[3]); + bind = true; + } else if ((strncmp(argv[1], "unbind", 6) == 0) && (argc == 3)) { + port = simple_strtoul(argv[2], NULL, 10); + printf("Unbinding USB port %d\n", port); + bind = false; + } else if ((strncmp(argv[1], "list", 4) == 0) && (argc == 2)) { + int i; + + for (i = 0; i < ARRAY_SIZE(supported_drivers); i++) + printf("%s\n", supported_drivers[i]); + + return CMD_RET_SUCCESS; + } else { + return CMD_RET_USAGE; + } + + ret = uclass_find_device(UCLASS_USB_DEV_GENERIC, port, &usb_dev); + if (!usb_dev || ret) { + printf("Cannot find UDC %d\n", port); + return CMD_RET_FAILURE; + } + + if (bind) { + ret = device_bind_driver(usb_dev, argv[3], "gadget", &dev); + if (!dev || ret) { + printf("Unable to bind. err:%d\n", ret); + return CMD_RET_FAILURE; + } + } else { + ret = device_chld_unbind(usb_dev); + if (ret) { + printf("Unable to bind. err:%d\n", ret); + return CMD_RET_FAILURE; + } + } + + return CMD_RET_SUCCESS; +} + +U_BOOT_CMD( + usbdev, 4, 0, do_usbdev, + "USB gadget driver", + "bind dev# driver- bind the USB device port to a driver\n" + "unbind dev# - unbind the USB device port to a driver\n" + "list - display the list of available gadget drivers" +); +#endif /* CONFIG_DM_USB_DEV */ diff --git a/drivers/core/device-remove.c b/drivers/core/device-remove.c index 1cf2278..b0b5ea3 100644 --- a/drivers/core/device-remove.c +++ b/drivers/core/device-remove.c @@ -17,16 +17,7 @@ #include <dm/uclass-internal.h> #include <dm/util.h> -/** - * device_chld_unbind() - Unbind all device's children from the device - * - * On error, the function continues to unbind all children, and reports the - * first error. - * - * @dev: The device that is to be stripped of its children - * @return 0 on success, -ve on error - */ -static int device_chld_unbind(struct udevice *dev) +int device_chld_unbind(struct udevice *dev) { struct udevice *pos, *n; int ret, saved_ret = 0; diff --git a/include/dm/device-internal.h b/include/dm/device-internal.h index 5a4d50c..b4f44c8 100644 --- a/include/dm/device-internal.h +++ b/include/dm/device-internal.h @@ -120,6 +120,21 @@ int device_unbind(struct udevice *dev); static inline int device_unbind(struct udevice *dev) { return 0; } #endif +/** + * device_chld_unbind() - Unbind all device's children from the device + * + * On error, the function continues to unbind all children, and reports the + * first error. + * + * @dev: The device that is to be stripped of its children + * @return 0 on success, -ve on error + */ +#if CONFIG_IS_ENABLED(DM_DEVICE_REMOVE) +int device_chld_unbind(struct udevice *dev); +#else +static inline int device_chld_unbind(struct udevice *dev) { return 0; } +#endif + #if CONFIG_IS_ENABLED(DM_DEVICE_REMOVE) void device_free(struct udevice *dev); #else -- 2.7.4 _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot