
Hi Michael,
On Fri, 22 May 2020 at 01:32, Michael Walle michael@walle.cc wrote:
Hi Simon,
Am 2020-05-22 04:34, schrieb Simon Glass:
Hi Michael,
On Thu, 21 May 2020 at 17:28, Michael Walle michael@walle.cc wrote:
Am 2020-05-21 16:13, schrieb Bin Meng:
On Thu, May 21, 2020 at 12:40 AM Michael Walle michael@walle.cc wrote:
It is possible to specify a device tree node for an USB device. This is useful if you have a static USB setup and want to use aliases which point to these nodes, like on the Raspberry Pi. The nodes are matched against their hub port number, the compatible strings are not matched for now.
Signed-off-by: Michael Walle michael@walle.cc
This is a new patch in v5: Fixes the ethernet0 alias on Raspberry Pis. This has never been working, but wasn't a problem until recently. Patch 2/2 changes the allocation of the numbers and reserves possible aliases.
drivers/usb/host/usb-uclass.c | 41 ++++++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 5 deletions(-)
diff --git a/drivers/usb/host/usb-uclass.c b/drivers/usb/host/usb-uclass.c index cb79dfbbd5..f42c0625cb 100644 --- a/drivers/usb/host/usb-uclass.c +++ b/drivers/usb/host/usb-uclass.c @@ -494,6 +494,35 @@ static int usb_match_one_id(struct usb_device_descriptor *desc, return usb_match_one_id_intf(desc, int_desc, id); }
+static ofnode usb_get_ofnode(struct udevice *hub, int port) +{
ofnode node;
u32 reg;
if (!dev_has_of_node(hub))
return ofnode_null();
/*
* The USB controller and its USB hub are two different
udevices,
* but the device tree has only one node for both. Thus we are
* assigning this node to both udevices.
* If port is zero, the controller scans its root hub, thus we
* are using the same ofnode as the controller here.
*/
if (!port)
return dev_ofnode(hub);
ofnode_for_each_subnode(node, dev_ofnode(hub)) {
if (ofnode_read_u32(node, "reg", ®))
continue;
if (reg == port)
return node;
}
return ofnode_null();
+}
/**
- usb_find_and_bind_driver() - Find and bind the right USB driver
@@ -502,13 +531,14 @@ static int usb_match_one_id(struct usb_device_descriptor *desc, static int usb_find_and_bind_driver(struct udevice *parent, struct usb_device_descriptor *desc, struct usb_interface_descriptor *iface,
int bus_seq, int devnum,
int bus_seq, int devnum, int port, struct udevice **devp)
{ struct usb_driver_entry *start, *entry; int n_ents; int ret; char name[30], *str;
ofnode node = usb_get_ofnode(parent, port); *devp = NULL; debug("%s: Searching for driver\n", __func__);
@@ -533,8 +563,8 @@ static int usb_find_and_bind_driver(struct udevice *parent, * find another driver. For now this doesn't seem * necesssary, so just bind the first match. */
ret = device_bind(parent, drv, drv->name,
NULL, -1,
&dev);
ret = device_bind_ofnode(parent, drv,
drv->name, NULL,
node, &dev); if (ret) goto error; debug("%s: Match found: %s\n", __func__,
drv->name); @@ -651,9 +681,10 @@ int usb_scan_device(struct udevice *parent, int port, if (ret) { if (ret != -ENOENT) return ret;
ret = usb_find_and_bind_driver(parent,
&udev->descriptor, iface,
ret = usb_find_and_bind_driver(parent,
&udev->descriptor,
iface,
udev->controller_dev->seq,
udev->devnum, &dev);
udev->devnum, port,
&dev); if (ret) return ret; created = true; --
Do we have tests added ?
Adding tests for this isn't straight forward. Mostly because the device tree is used to add the emulated USB devices. OTOH we try to match the device tree to the scanned devices. To make things worse, the hierarchy of the USB hubs and usb devices doesn't seem to fit a "normal" device tree.
This is described in usb-info.rst
Eg. in sandbox/dts/test.dts it is: usb@1 { /* this is the controller */ hub { /* I don't know what this is */
The root hub
hub-emul { /* this is the root hub */
No, this is the emulation driver. I is added so that the root hub works.
flash-stick@0 { reg = <0>; /* this is an usb device on port _1_ of the root hub */
No, this is an emulation device. So when we probe the hub we will see this emulation driver and create a device.
Seems like my comments were missleading, they belong to the context (i.e. the comment above) not the comment below. Let me rephrase:
usb@1 /* this is the controller */ usb@1/hub /* I don't know what this is */ usb@1/hub/hub-emul /* this is the root hub */ usb@1/hub/hub-emul/flash-stick@0 /* this is an usb device on port _1_ of the root hub */
vs.
usb /* this is the controller & root hub */ usb/usb1@1 /* this is another _external_ hub on port 1 of the root hub */ usb/usb1@1/usbether@1 /* this is an usb device on port 1 of the external hub */
They don't match at all. Thus the new code won't match any device of the emulated usb hierarchy.
If you ignore the emulation nodes, they match. The emulation nodes are added so that there is actually something on the bus for your test code to see.
How do they match? You'd also have to ignore the root hub, as this is implicitly in the device controller. Additionally, port numbers are zero based for the emulation stuff vs one-based in the real device tree.
If I'm not mistaken, the equivalent to usb@1/hub/hub-emul/flash-stick@0 should be usb@1/flash-stick@1
The device tree here is to specify the emulation nodes. If you try it:
u-boot -D => dm tree .. usb 0 [ ] usb_sandbox |-- usb@1 usb_hub 0 [ ] usb_hub | `-- hub usb_emul 0 [ ] usb_sandbox_hub | `-- hub-emul usb_emul 1 [ ] usb_sandbox_flash | `-- flash-stick .. => usb start ... => dm tree ... usb 0 [ + ] usb_sandbox |-- usb@1 usb_hub 0 [ + ] usb_hub | `-- hub usb_emul 0 [ + ] usb_sandbox_hub | |-- hub-emul usb_emul 1 [ + ] usb_sandbox_flash | | `-- flash-stick usb_mass_s 0 [ + ] usb_mass_storage | `-- usb_mass_storage blk 0 [ ] usb_storage_blk | `-- usb_mass_storage.lun0 ... => usb tree USB device tree: 1 Hub (480 Mb/s, 100mA) | sandbox hub 2345 | +-2 Mass Storage (480 Mb/s, 100mA) sandbox flash flash-stick
You can see that it creates the USB devices when the emulators respond to requests about what is on the bus. That is the only reason the emulators are there. The 'reg' properties are not related to the USB port that is eventually assigned.
What you are doing is different. You are actually creating devices that you know to exist on the bus. Sandbox should support this too although I'm not sure if there is a test for it. That's the point of the emulators with sandbox - to test the USB stack.
You can also use 'u-boot -T' to run with the test device tree. This has 3 flash sticks and a fake USB keyboard.
Here's the docs I am referring to:
<<< Sandbox -------
All driver model uclasses must have tests and USB is no exception. To achieve this, a sandbox USB controller is provided. This can make use of emulation drivers which pretend to be USB devices. Emulations are provided for a hub and a flash stick. These are enough to create a pretend USB bus (defined by the sandbox device tree sandbox.dts) which can be scanned and used.
Tests in test/dm/usb.c make use of this feature. It allows much of the USB stack to be tested without real hardware being needed.
Here is an example device tree fragment:
.. code-block:: none
usb@1 { compatible = "sandbox,usb"; hub { compatible = "usb-hub"; usb,device-class = <USB_CLASS_HUB>; hub-emul { compatible = "sandbox,usb-hub"; #address-cells = <1>; #size-cells = <0>; flash-stick { reg = <0>; compatible = "sandbox,usb-flash"; sandbox,filepath = "flash.bin"; }; }; }; };
This defines a single controller, containing a root hub (which is required). The hub is emulated by a hub emulator, and the emulated hub has a single flash stick to emulate on one of its ports.
When 'usb start' is used, the following 'dm tree' output will be available::
usb [ + ] `-- usb@1 usb_hub [ + ] `-- hub usb_emul [ + ] |-- hub-emul usb_emul [ + ] | `-- flash-stick usb_mass_st [ + ] `-- usb_mass_storage
This may look confusing. Most of it mirrors the device tree, but the 'usb_mass_storage' device is not in the device tree. This is created by usb_find_and_bind_driver() based on the USB_DRIVER in usb_storage.c. While 'flash-stick' is the emulation device, 'usb_mass_storage' is the real U-Boot USB device driver that talks to it.
Regards, Simon