123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415 |
- How USB works with driver model
- ===============================
- Introduction
- ------------
- Driver model USB support makes use of existing features but changes how
- drivers are found. This document provides some information intended to help
- understand how things work with USB in U-Boot when driver model is enabled.
- Enabling driver model for USB
- -----------------------------
- A new CONFIG_DM_USB option is provided to enable driver model for USB. This
- causes the USB uclass to be included, and drops the equivalent code in
- usb.c. In particular the usb_init() function is then implemented by the
- uclass.
- Support for EHCI and XHCI
- -------------------------
- So far OHCI is not supported. Both EHCI and XHCI drivers should be declared
- as drivers in the USB uclass. For example:
- static const struct udevice_id ehci_usb_ids[] = {
- { .compatible = "nvidia,tegra20-ehci", .data = USB_CTLR_T20 },
- { .compatible = "nvidia,tegra30-ehci", .data = USB_CTLR_T30 },
- { .compatible = "nvidia,tegra114-ehci", .data = USB_CTLR_T114 },
- { }
- };
- U_BOOT_DRIVER(usb_ehci) = {
- .name = "ehci_tegra",
- .id = UCLASS_USB,
- .of_match = ehci_usb_ids,
- .ofdata_to_platdata = ehci_usb_ofdata_to_platdata,
- .probe = tegra_ehci_usb_probe,
- .remove = tegra_ehci_usb_remove,
- .ops = &ehci_usb_ops,
- .platdata_auto_alloc_size = sizeof(struct usb_platdata),
- .priv_auto_alloc_size = sizeof(struct fdt_usb),
- .flags = DM_FLAG_ALLOC_PRIV_DMA,
- };
- Here ehci_usb_ids is used to list the controllers that the driver supports.
- Each has its own data value. Controllers must be in the UCLASS_USB uclass.
- The ofdata_to_platdata() method allows the controller driver to grab any
- necessary settings from the device tree.
- The ops here are ehci_usb_ops. All EHCI drivers will use these same ops in
- most cases, since they are all EHCI-compatible. For EHCI there are also some
- special operations that can be overridden when calling ehci_register().
- The driver can use priv_auto_alloc_size to set the size of its private data.
- This can hold run-time information needed by the driver for operation. It
- exists when the device is probed (not when it is bound) and is removed when
- the driver is removed.
- Note that usb_platdata is currently only used to deal with setting up a bus
- in USB device mode (OTG operation). It can be omitted if that is not
- supported.
- The driver's probe() method should do the basic controller init and then
- call ehci_register() to register itself as an EHCI device. It should call
- ehci_deregister() in the remove() method. Registering a new EHCI device
- does not by itself cause the bus to be scanned.
- The old ehci_hcd_init() function is no-longer used. Nor is it necessary to
- set up the USB controllers from board init code. When 'usb start' is used,
- each controller will be probed and its bus scanned.
- XHCI works in a similar way.
- Data structures
- ---------------
- The following primary data structures are in use:
- - struct usb_device
- This holds information about a device on the bus. All devices have
- this structure, even the root hub. The controller itself does not
- have this structure. You can access it for a device 'dev' with
- dev_get_parent_priv(dev). It matches the old structure except that the
- parent and child information is not present (since driver model
- handles that). Once the device is set up, you can find the device
- descriptor and current configuration descriptor in this structure.
- - struct usb_platdata
- This holds platform data for a controller. So far this is only used
- as a work-around for controllers which can act as USB devices in OTG
- mode, since the gadget framework does not use driver model.
- - struct usb_dev_platdata
- This holds platform data for a device. You can access it for a
- device 'dev' with dev_get_parent_platdata(dev). It holds the device
- address and speed - anything that can be determined before the device
- driver is actually set up. When probing the bus this structure is
- used to provide essential information to the device driver.
- - struct usb_bus_priv
- This is private information for each controller, maintained by the
- controller uclass. It is mostly used to keep track of the next
- device address to use.
- Of these, only struct usb_device was used prior to driver model.
- USB buses
- ---------
- Given a controller, you know the bus - it is the one attached to the
- controller. Each controller handles exactly one bus. Every controller has a
- root hub attached to it. This hub, which is itself a USB device, can provide
- one or more 'ports' to which additional devices can be attached. It is
- possible to power up a hub and find out which of its ports have devices
- attached.
- Devices are given addresses starting at 1. The root hub is always address 1,
- and from there the devices are numbered in sequence. The USB uclass takes
- care of this numbering automatically during enumeration.
- USB devices are enumerated by finding a device on a particular hub, and
- setting its address to the next available address. The USB bus stretches out
- in a tree structure, potentially with multiple hubs each with several ports
- and perhaps other hubs. Some hubs will have their own power since otherwise
- the 5V 500mA power supplied by the controller will not be sufficient to run
- very many devices.
- Enumeration in U-Boot takes a long time since devices are probed one at a
- time, and each is given sufficient time to wake up and announce itself. The
- timeouts are set for the slowest device.
- Up to 127 devices can be on each bus. USB has four bus speeds: low
- (1.5Mbps), full (12Mbps), high (480Mbps) which is only available with USB2
- and newer (EHCI), and super (5Gbps) which is only available with USB3 and
- newer (XHCI). If you connect a super-speed device to a high-speed hub, you
- will only get high-speed.
- USB operations
- --------------
- As before driver model, messages can be sent using submit_bulk_msg() and the
- like. These are now implemented by the USB uclass and route through the
- controller drivers. Note that messages are not sent to the driver of the
- device itself - i.e. they don't pass down the stack to the controller.
- U-Boot simply finds the controller to which the device is attached, and sends
- the message there with an appropriate 'pipe' value so it can be addressed
- properly. Having said that, the USB device which should receive the message
- is passed in to the driver methods, for use by sandbox. This design decision
- is open for review and the code impact of changing it is small since the
- methods are typically implemented by the EHCI and XHCI stacks.
- Controller drivers (in UCLASS_USB) themselves provide methods for sending
- each message type. For XHCI an additional alloc_device() method is provided
- since XHCI needs to allocate a device context before it can even read the
- device's descriptor.
- These methods use a 'pipe' which is a collection of bit fields used to
- describe the type of message, direction of transfer and the intended
- recipient (device number).
- USB Devices
- -----------
- USB devices are found using a simple algorithm which works through the
- available hubs in a depth-first search. Devices can be in any uclass, but
- are attached to a parent hub (or controller in the case of the root hub) and
- so have parent data attached to them (this is struct usb_device).
- By the time the device's probe() method is called, it is enumerated and is
- ready to talk to the host.
- The enumeration process needs to work out which driver to attach to each USB
- device. It does this by examining the device class, interface class, vendor
- ID, product ID, etc. See struct usb_driver_entry for how drivers are matched
- with USB devices - you can use the USB_DEVICE() macro to declare a USB
- driver. For example, usb_storage.c defines a USB_DEVICE() to handle storage
- devices, and it will be used for all USB devices which match.
- Technical details on enumeration flow
- -------------------------------------
- It is useful to understand precisely how a USB bus is enumerating to avoid
- confusion when dealing with USB devices.
- Device initialisation happens roughly like this:
- - At some point the 'usb start' command is run
- - This calls usb_init() which works through each controller in turn
- - The controller is probed(). This does no enumeration.
- - Then usb_scan_bus() is called. This calls usb_scan_device() to scan the
- (only) device that is attached to the controller - a root hub
- - usb_scan_device() sets up a fake struct usb_device and calls
- usb_setup_device(), passing the port number to be scanned, in this case port
- 0
- - usb_setup_device() first calls usb_prepare_device() to set the device
- address, then usb_select_config() to select the first configuration
- - at this point the device is enumerated but we do not have a real struct
- udevice for it. But we do have the descriptor in struct usb_device so we can
- use this to figure out what driver to use
- - back in usb_scan_device(), we call usb_find_child() to try to find an
- existing device which matches the one we just found on the bus. This can
- happen if the device is mentioned in the device tree, or if we previously
- scanned the bus and so the device was created before
- - if usb_find_child() does not find an existing device, we call
- usb_find_and_bind_driver() which tries to bind one
- - usb_find_and_bind_driver() searches all available USB drivers (declared
- with USB_DEVICE()). If it finds a match it binds that driver to create a new
- device.
- - If it does not, it binds a generic driver. A generic driver is good enough
- to allow access to the device (sending it packets, etc.) but all
- functionality will need to be implemented outside the driver model.
- - in any case, when usb_find_child() and/or usb_find_and_bind_driver() are
- done, we have a device with the correct uclass. At this point we want to
- probe the device
- - first we store basic information about the new device (address, port,
- speed) in its parent platform data. We cannot store it its private data
- since that will not exist until the device is probed.
- - then we call device_probe() which probes the device
- - the first probe step is actually the USB controller's (or USB hubs's)
- child_pre_probe() method. This gets called before anything else and is
- intended to set up a child device ready to be used with its parent bus. For
- USB this calls usb_child_pre_probe() which grabs the information that was
- stored in the parent platform data and stores it in the parent private data
- (which is struct usb_device, a real one this time). It then calls
- usb_select_config() again to make sure that everything about the device is
- set up
- - note that we have called usb_select_config() twice. This is inefficient
- but the alternative is to store additional information in the platform data.
- The time taken is minimal and this way is simpler
- - at this point the device is set up and ready for use so far as the USB
- subsystem is concerned
- - the device's probe() method is then called. It can send messages and do
- whatever else it wants to make the device work.
- Note that the first device is always a root hub, and this must be scanned to
- find any devices. The above steps will have created a hub (UCLASS_USB_HUB),
- given it address 1 and set the configuration.
- For hubs, the hub uclass has a post_probe() method. This means that after
- any hub is probed, the uclass gets to do some processing. In this case
- usb_hub_post_probe() is called, and the following steps take place:
- - usb_hub_post_probe() calls usb_hub_scan() to scan the hub, which in turn
- calls usb_hub_configure()
- - hub power is enabled
- - we loop through each port on the hub, performing the same steps for each
- - first, check if there is a device present. This happens in
- usb_hub_port_connect_change(). If so, then usb_scan_device() is called to
- scan the device, passing the appropriate port number.
- - you will recognise usb_scan_device() from the steps above. It sets up the
- device ready for use. If it is a hub, it will scan that hub before it
- continues here (recursively, depth-first)
- - once all hub ports are scanned in this way, the hub is ready for use and
- all of its downstream devices also
- - additional controllers are scanned in the same way
- The above method has some nice properties:
- - the bus enumeration happens by virtue of driver model's natural device flow
- - most logic is in the USB controller and hub uclasses; the actual device
- drivers do not need to know they are on a USB bus, at least so far as
- enumeration goes
- - hub scanning happens automatically after a hub is probed
- Hubs
- ----
- USB hubs are scanned as in the section above. While hubs have their own
- uclass, they share some common elements with controllers:
- - they both attach private data to their children (struct usb_device,
- accessible for a child with dev_get_parent_priv(child))
- - they both use usb_child_pre_probe() to set up their children as proper USB
- devices
- Example - Mass Storage
- ----------------------
- As an example of a USB device driver, see usb_storage.c. It uses its own
- uclass and declares itself as follows:
- U_BOOT_DRIVER(usb_mass_storage) = {
- .name = "usb_mass_storage",
- .id = UCLASS_MASS_STORAGE,
- .of_match = usb_mass_storage_ids,
- .probe = usb_mass_storage_probe,
- };
- static const struct usb_device_id mass_storage_id_table[] = {
- { .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS,
- .bInterfaceClass = USB_CLASS_MASS_STORAGE},
- { } /* Terminating entry */
- };
- USB_DEVICE(usb_mass_storage, mass_storage_id_table);
- The USB_DEVICE() macro attaches the given table of matching information to
- the given driver. Note that the driver is declared in U_BOOT_DRIVER() as
- 'usb_mass_storage' and this must match the first parameter of USB_DEVICE.
- When usb_find_and_bind_driver() is called on a USB device with the
- bInterfaceClass value of USB_CLASS_MASS_STORAGE, it will automatically find
- this driver and use it.
- Counter-example: USB Ethernet
- -----------------------------
- As an example of the old way of doing things, see usb_ether.c. When the bus
- is scanned, all Ethernet devices will be created as generic USB devices (in
- uclass UCLASS_USB_DEV_GENERIC). Then, when the scan is completed,
- usb_host_eth_scan() will be called. This looks through all the devices on
- each bus and manually figures out which are Ethernet devices in the ways of
- yore.
- In fact, usb_ether should be moved to driver model. Each USB Ethernet driver
- (e.g drivers/usb/eth/asix.c) should include a USB_DEVICE() declaration, so
- that it will be found as part of normal USB enumeration. Then, instead of a
- generic USB driver, a real (driver-model-aware) driver will be used. Since
- Ethernet now supports driver model, this should be fairly easy to achieve,
- and then usb_ether.c and the usb_host_eth_scan() will melt away.
- 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:
- 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.
- Future work
- -----------
- It is pretty uncommon to have a large USB bus with lots of hubs on an
- embedded system. In fact anything other than a root hub is uncommon. Still
- it would be possible to speed up enumeration in two ways:
- - breadth-first search would allow devices to be reset and probed in
- parallel to some extent
- - enumeration could be lazy, in the sense that we could enumerate just the
- root hub at first, then only progress to the next 'level' when a device is
- used that we cannot find. This could be made easier if the devices were
- statically declared in the device tree (which is acceptable for production
- boards where the same, known, things are on each bus).
- But in common cases the current algorithm is sufficient.
- Other things that need doing:
- - Convert usb_ether to use driver model as described above
- - Test that keyboards work (and convert to driver model)
- - Move the USB gadget framework to driver model
- - Implement OHCI in driver model
- - Implement USB PHYs in driver model
- - Work out a clever way to provide lazy init for USB devices
- --
- Simon Glass <sjg@chromium.org>
- 23-Mar-15
|