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 | | `-- m...@58005000.blk ethernet 0 [ + ] eth_eqos | |-- ethernet@5800a000 eth_phy_ge 0 [ + ] eth_phy_generic_drv | | `-- ethernet-phy@0 usb 0 [ ] ehci_generic | |-- usb@5800d000 video 0 [ ] stm32_display | |-- display-controller@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 | | `-- m...@58005000.blk usb 0 [ ] ehci_generic | |-- usb@5800d000 video 0 [ ] stm32_display | |-- display-controller@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 | | `-- m...@58005000.blk usb 0 [ ] ehci_generic | |-- usb@5800d000 ethernet 0 [ ] usb_ether | | `-- usb_ether video 0 [ ] stm32_display | |-- display-controller@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