bind/unbind command not working for usb_ether
Patrice CHOTARD
patrice.chotard at foss.st.com
Tue Feb 15 14:28:58 CET 2022
Hi Tim
On 2/10/22 18:04, Tim Harvey wrote:
> Greetings,
>
> I'm trying to understand how to use the U-Boot bind command to bind
> the usb_ether driver to the usb class to register a USB ethernet
> gadget network device as referenced in:
> commit 02291d83fdaaf ("doc: add bind/unbind command documentation")
> commit 49c752c93a78 ("cmd: Add bind/unbind commands to bind a device
> to a driver from the command line")
>
For example, i made some trial on STM32MP1 platform:
At boot, we got :
STM32MP> dm tree
Class Index Probed Driver Name
-----------------------------------------------------------
root 0 [ + ] root_driver root_driver
firmware 0 [ ] psci |-- psci
sysreset 0 [ ] psci-sysreset | `-- psci-sysreset
.....
blk 0 [ + ] mmc_blk | | `-- mmc at 58005000.blk
ethernet 0 [ + ] eth_eqos | |-- ethernet at 5800a000
eth_phy_ge 0 [ + ] eth_phy_generic_drv | | `-- ethernet-phy at 0
usb 0 [ ] ehci_generic | |-- usb at 5800d000
video 0 [ ] stm32_display | |-- display-controller at 5a001000
.....
As you can see, there is already an ethernet interface used.
We unbind the ethernet interface before binding the usb_ether gadget to the usb class.
First unbind the generic ethernet phy (eth_phy_generic_drv) and the ethernet driver
(eth_eqos).
STM32MP> unbind eth_phy_generic 0
STM32MP> unbind ethernet 0
STM32MP> dm tree
Class Index Probed Driver Name
-----------------------------------------------------------
root 0 [ + ] root_driver root_driver
firmware 0 [ ] psci |-- psci
sysreset 0 [ ] psci-sysreset | `-- psci-sysreset
....
blk 0 [ + ] mmc_blk | | `-- mmc at 58005000.blk
usb 0 [ ] ehci_generic | |-- usb at 5800d000
video 0 [ ] stm32_display | |-- display-controller at 5a001000
....
Ethernet and phy driver are both unbinded.
Now we can bind the usb_eher to the usb class
STM32MP> bind usb 0 usb_ether
STM32MP> dm tree
Class Index Probed Driver Name
-----------------------------------------------------------
root 0 [ + ] root_driver root_driver
firmware 0 [ ] psci |-- psci
sysreset 0 [ ] psci-sysreset | `-- psci-sysreset
....
blk 0 [ + ] mmc_blk | | `-- mmc at 58005000.blk
usb 0 [ ] ehci_generic | |-- usb at 5800d000
ethernet 0 [ ] usb_ether | | `-- usb_ether
video 0 [ ] stm32_display | |-- display-controller at 5a001000
....
usb_ether is now binded.
As example, if you can then use some ethernet command as dhcp or ping :
STM32MP> dhcp
using dwc2-udc, OUT ep2out-bulk IN ep1in-bulk STATUS ep3in-int
MAC de:ad:be:ef:00:01
HOST MAC de:ad:be:ef:00:00
RNDIS ready
high speed config #2: 2 mA, Ethernet Gadget, using RNDIS
USB RNDIS network up!
BOOTP broadcast 1
> I have enabled:
> CONFIG_DM_USB=y
> CONFIG_USB_GADGET=y
> CONFIG_USB_ETHER=y
>
In my case i enabled also CONFIG_USB_ETH_RNDIS=y
Patrice
> However the 'usb_ether' driver is never registered and thus doesn't
> appear in a 'dm tree' list and can't be bound to the usb controller.
>
> With the help of Heiko I've found two ways to get the usb_ether driver
> to register:
>
> dt-way:
> - add of match in ether.c:
> diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
> index 63d552bc8b..8e2a05a5af 100644
> --- a/drivers/usb/gadget/ether.c
> +++ b/drivers/usb/gadget/ether.c
> @@ -2690,10 +2690,16 @@ int usb_ether_init(void)
> return 0;
> }
>
> +static const struct udevice_id usb_ether_ids[] = {
> + { .compatible = "gadget,usb_ether" },
> + { }
> +};
> +
> U_BOOT_DRIVER(eth_usb) = {
> .name = "usb_ether",
> .id = UCLASS_ETH,
> .probe = usb_eth_probe,
> + .of_match = usb_ether_ids,
> .ops = &usb_eth_ops,
> .priv_auto_alloc_size = sizeof(struct ether_priv),
> .platdata_auto_alloc_size = sizeof(struct eth_pdata),
> - then add it directly in your board u-boot.dts:
> +&usbotg1 {
> + usb_ether0 {
> + compatible = "gadget,usb_ether";
> + status = "okay";
> + };
> +};
>
>
> The non-dt way:
> - bind it manually in board code with:
> {
> struct udevice *dev;
> struct udevice *usb_dev;
> int ret;
>
> ret = uclass_first_device(UCLASS_USB, &usb_dev);
> if (!usb_dev || ret)
> printf("%s: No USB device found\n", __func__);
>
> ret = device_bind_driver(usb_dev, "usb_ether", "usb_ether", &dev);
> if (!dev || ret)
> printf("%s: usb - not able to bind usb_ether
> device\n", __func__);
> }
> - Note that this is the same code from usb_ether_init() but with
> UCLASS_USB instead of UCLASS_USB_GADGET_GENERIC
>
> What is the intended way to bind the usb_ether gadget device at runtime?
>
> Additionally Heiko found that once bound and usb_ether is registered
> as a network device using a network command like ping/tftpboot calls
> usb_setup_ehci_gadget() which removes the USB driver ... and so also
> the child usb ethernet gadget device then re-probes only the usb
> driver and not the gadget thus fails. I compared this to how the 'ums'
> command works and that also removes the usb driver and child nodes but
> because ums isn't a gadget driver it doesn't get removed and works.
>
> Best Regards,
>
> Tim
More information about the U-Boot
mailing list