Reference board: i.MX6 SabreLite
Kernel version: 3.10.17, yocto. SD card mage delivered by Freescale for testing this issue.
Additional software: “uvccapture” utlity. (Any UVC cam streaming SW, e.g. “cheese” can be used).
Additional hardware: Webcam supporting UVC (USB Video Class). Logitech conference (and others) cam used for test. And one or more USB extender cables.
Observed behavior: When USB extender cables of certain length and quality are used, it is possible to stream video from the webcam, but with errors (XactErr in the isochronous transactions indicate CRC error in the data stream). Under these conditions, the i.MX6 USB host port can lock up: It cannot be “stopped”, it doesn’t generate any interrupts, Current Connect Status is not updated). The port is of course expected to keep functioning under bit error conditions.
Steps to reproduce:
You need a connection to the webcam that is good enough to allow enumeration etc., but still generates CRC errors during streaming. It may require some experimenting to find a combination of webcam and extender cable to obtain this situation. To help in this, it is usefull to add a line of test output from uvccapture for each captured image, showing the image size in bytes. When there are CRC errors, you will either see the frame rate drop, or the image size sometimes be very small. Many other methods and tools can be used too.
Under this condition – non-zero CRC error rate in the isochronous data stream, the streaming will stop completely within some minutes. Now, the USB host port (USB Core 1) in i.MX6 is no longer functioning at all.
Now, we try to stop the USB controller by setting RS=0 (bit 0 in the USBCMD register). This should result in the HCH becoming 1 (bit 12 in the USBSTS register):
root@imx6qsabrelite:~# ./mr 0x2184384
root@imx6qsabrelite:~# ./mr 0x2184344
0x000C4088 < - STS, HCH=0
root@imx6qsabrelite:~# ./mr 0x2184340
0x00010B15 <- CMD, RS=1
root@imx6qsabrelite:~# ./mw 0x2184340 0x00010B14 <- CMD, set RS=0
root@imx6qsabrelite:~# ./mr 0x2184344
0x000C4088 <- STS, HCH still 0
(mr/mw are simply memory read/write utilities).
Trying the above sequence before running the test, sets bit 12 (HCH) in the USBSTS register as expected.
The RS->HCH relation should work, no matter what. I would like very much to be proven wrong, but it seems to me that the fact that setting RS=0 does not set HCH=1 is a “smoking gun” indication of a very low level issue in the USB host controller.
An easy way to prove something is wrong is to try accessing a device (USB stick) on the other USB host port on the SabreLite. This port is “dead” too, of course, as it connects through the hub to the same USB host port on i.MX6.
More observations on the error condition:
- - The USB controller stops generating interrupts
- - The CCS (Current Connect Status) bit in the PORTSC1 register does not change when the “device” is disconnected. (The “device” is the hub chip; it can be “disconnected” by asserting it’s reset signal).
- - The FRINDEX register is still updating.
- - Often, if not always, the “lock up” occurs in connection with XactErr being reported in not just 1, but 2 transactions, within the same iTD.
- - A “port reset” (setting bit 8 in PORTSC1) can get the USB controller out of the deadlock: It can be stopped/started again etc. But it doesn’t make the USB port operational for the driver (quite naturally).
- - The issue was originally found on our own hardware design, and with kernel 3.0.35. The point to notice is that our hardware design is similar to SabreLite, except that we use a Cypress hub chip. SabreLite uses a Microchip hub. So, the issue is not related to interaction with a specific type of hub.
The only way we found to make the USB host operational again in relation to software, is to reboot.
Thanks in advance for comments and suggestions regarding this issue.