bind/unbind command not working for usb_ether

Patrice CHOTARD patrice.chotard at foss.st.com
Tue Feb 15 14:30:30 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