I spent some time debugging this, and it looks like fastboot is hanging because one of the USB DMA buffers is left in an active state following a non-fatal error during fastboot init.
When I run fastboot on the target, I get the following output:
MX53-ARD-DDR3 U-Boot > fastboot
fastboot is in init......flash target is MMC:0
USB Mini b cable Connected!
fastboot initialized
USB_SUSPEND
USB_RESET
USB_RESET
Invalid string index 238
The "Invalid string index 238" message seems to be normal enough (based on google search), but the error handler in Freescale's implementation stalls USB endpoint 0 and returns early. I changed the code to prevent this from happening, and now fastboot is working reliably. Patch details below:
diff -r 9f3d80b181e5 -r 2d4af89a12a2 bootable/bootloader/uboot-imx/drivers/usb/gadget/imx_udc.c
--- a/bootable/bootloader/uboot-imx/drivers/usb/gadget/imx_udc.c Fri Jul 11 15:20:44 2014 +0100
+++ b/bootable/bootloader/uboot-imx/drivers/usb/gadget/imx_udc.c Mon Jul 14 16:52:36 2014 +0100
@@ -555,49 +555,52 @@
mxc_udc_queue_update(0, NULL, 0, 0xffffffff);
}
if (ep0_recv_setup(ep0_urb)) {
- mxc_ep0_stall();
- return;
- }
- switch (s->bRequest) {
- case USB_REQ_GET_STATUS:
- if ((s->bmRequestType & (USB_DIR_IN | USB_TYPE_MASK)) !=
- (USB_DIR_IN | USB_TYPE_STANDARD))
- break;
- ch9getstatus(s->bmRequestType, s->wValue,
- s->wIndex, s->wLength);
- return;
- case USB_REQ_SET_ADDRESS:
- if (s->bmRequestType != (USB_DIR_OUT |
- USB_TYPE_STANDARD | USB_RECIP_DEVICE))
- break;
- mxc_udc.setaddr = 1;
- mxc_udc.ep0_dir = USB_DIR_IN;
- mxc_udc_queue_update(0, NULL, 0, 0xffffffff);
- usbd_device_event_irq(udc_device, DEVICE_ADDRESS_ASSIGNED, 0);
- return;
- case USB_REQ_SET_CONFIGURATION:
- usbd_device_event_irq(udc_device, DEVICE_CONFIGURED, 0);
- case USB_REQ_CLEAR_FEATURE:
- case USB_REQ_SET_FEATURE:
- {
- int rc = -1;
- if ((s->bmRequestType & (USB_RECIP_MASK | USB_TYPE_MASK)) ==
- (USB_RECIP_ENDPOINT | USB_TYPE_STANDARD))
- rc = 0;
- else if ((s->bmRequestType &
- (USB_RECIP_MASK | USB_TYPE_MASK)) ==
- (USB_RECIP_DEVICE | USB_TYPE_STANDARD))
- rc = 0;
- else
- break;
- if (rc == 0) {
+ /* Eliminated the stall, as it caused problems for subsequent
+ * fastboot operations. Also restructured code so that tidy-up
+ * still happens. */
+ //mxc_ep0_stall();
+ } else {
+ switch (s->bRequest) {
+ case USB_REQ_GET_STATUS:
+ if ((s->bmRequestType & (USB_DIR_IN | USB_TYPE_MASK)) !=
+ (USB_DIR_IN | USB_TYPE_STANDARD))
+ break;
+ ch9getstatus(s->bmRequestType, s->wValue,
+ s->wIndex, s->wLength);
+ return;
+ case USB_REQ_SET_ADDRESS:
+ if (s->bmRequestType != (USB_DIR_OUT |
+ USB_TYPE_STANDARD | USB_RECIP_DEVICE))
+ break;
+ mxc_udc.setaddr = 1;
mxc_udc.ep0_dir = USB_DIR_IN;
mxc_udc_queue_update(0, NULL, 0, 0xffffffff);
+ usbd_device_event_irq(udc_device, DEVICE_ADDRESS_ASSIGNED, 0);
+ return;
+ case USB_REQ_SET_CONFIGURATION:
+ usbd_device_event_irq(udc_device, DEVICE_CONFIGURED, 0);
+ case USB_REQ_CLEAR_FEATURE:
+ case USB_REQ_SET_FEATURE:
+ {
+ int rc = -1;
+ if ((s->bmRequestType & (USB_RECIP_MASK | USB_TYPE_MASK)) ==
+ (USB_RECIP_ENDPOINT | USB_TYPE_STANDARD))
+ rc = 0;
+ else if ((s->bmRequestType &
+ (USB_RECIP_MASK | USB_TYPE_MASK)) ==
+ (USB_RECIP_DEVICE | USB_TYPE_STANDARD))
+ rc = 0;
+ else
+ break;
+ if (rc == 0) {
+ mxc_udc.ep0_dir = USB_DIR_IN;
+ mxc_udc_queue_update(0, NULL, 0, 0xffffffff);
+ }
+ return;
}
- return;
- }
- default:
- break;
+ default:
+ break;
+ }
}
if (s->wLength) {
mxc_udc.ep0_dir = (s->bmRequestType & USB_DIR_IN) ?