Commit b6d7852cf8b7ced786937d3d080956b0c7be9836

Authored by Vipin Kumar
Committed by Marek Vasut
1 parent c5a927c61f

usbh/ehci: Increase timeout for enumeration

The current logic reads the port status just once after usb_hub_power_on and
expects the portstatus and portchange to report the connection status
immediately and correctly.

Few pen drives are not able to report both of them immediately ie. those pens
report the connection change but not the connected state after the first read.
This opportunity once lost is gone for ever because the u-boot, unlike linux or
any other OS, works in polling mode.

This patch modifies the logic to read the port status continuously until the
portstatus and portchange both report a connection change as well as a connected
state or no connection change and no connection. This logic is placed in a
timeout of 10 sec. At the end of it, the pen drive would have either reported a
ONE or a ZERO in bit 1 of portstatus as well as portchange.

It enhances the set of pen drives which can eventually be detected by u-boot

Note: This 10 second timeout is based purely on several experiments done with
the broken pen drives

Signed-off-by: Vipin Kumar <vipin.kumar@st.com>
Acked-by: Igor Grinberg <grinberg@compulab.co.il>

Showing 1 changed file with 28 additions and 5 deletions Side-by-side Diff

... ... @@ -396,14 +396,37 @@
396 396 for (i = 0; i < dev->maxchild; i++) {
397 397 ALLOC_CACHE_ALIGN_BUFFER(struct usb_port_status, portsts, 1);
398 398 unsigned short portstatus, portchange;
  399 + int ret;
  400 + ulong start = get_timer(0);
399 401  
400   - if (usb_get_port_status(dev, i + 1, portsts) < 0) {
401   - USB_HUB_PRINTF("get_port_status failed\n");
  402 + /*
  403 + * Wait for (whichever finishes first)
  404 + * - A maximum of 10 seconds
  405 + * This is a purely observational value driven by connecting
  406 + * a few broken pen drives and taking the max * 1.5 approach
  407 + * - connection_change and connection state to report same
  408 + * state
  409 + */
  410 + do {
  411 + ret = usb_get_port_status(dev, i + 1, portsts);
  412 + if (ret < 0) {
  413 + USB_HUB_PRINTF("get_port_status failed\n");
  414 + break;
  415 + }
  416 +
  417 + portstatus = le16_to_cpu(portsts->wPortStatus);
  418 + portchange = le16_to_cpu(portsts->wPortChange);
  419 +
  420 + if ((portchange & USB_PORT_STAT_C_CONNECTION) ==
  421 + (portstatus & USB_PORT_STAT_CONNECTION))
  422 + break;
  423 +
  424 + mdelay(100);
  425 + } while (get_timer(start) < CONFIG_SYS_HZ * 10);
  426 +
  427 + if (ret < 0)
402 428 continue;
403   - }
404 429  
405   - portstatus = le16_to_cpu(portsts->wPortStatus);
406   - portchange = le16_to_cpu(portsts->wPortChange);
407 430 USB_HUB_PRINTF("Port %d Status %X Change %X\n",
408 431 i + 1, portstatus, portchange);
409 432