diff options
author | Vivek Gautam <gautam.vivek@samsung.com> | 2013-04-12 16:34:35 +0530 |
---|---|---|
committer | Marek Vasut <marex@denx.de> | 2013-05-05 23:54:22 +0200 |
commit | 020bbcb76b5be0d5406d2ae7c26dbdb013ead812 (patch) | |
tree | 514516d7255a259dd155edef84af0ae610fc174e | |
parent | 605bd75af565011aa46e6d80a32e2aa03aff8159 (diff) | |
download | u-boot-imx-020bbcb76b5be0d5406d2ae7c26dbdb013ead812.zip u-boot-imx-020bbcb76b5be0d5406d2ae7c26dbdb013ead812.tar.gz u-boot-imx-020bbcb76b5be0d5406d2ae7c26dbdb013ead812.tar.bz2 |
usb: hub: Power-cycle on root-hub ports
XHCI ports are powered on after a H/W reset, however
EHCI ports are not. So disabling and re-enabling power
on all ports invariably.
Signed-off-by: Amar <amarendra.xt@samsung.com>
Signed-off-by: Vivek Gautam <gautam.vivek@samsung.com>
-rw-r--r-- | common/usb_hub.c | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/common/usb_hub.c b/common/usb_hub.c index f2a0285..e4f4e3c 100644 --- a/common/usb_hub.c +++ b/common/usb_hub.c @@ -100,11 +100,45 @@ static void usb_hub_power_on(struct usb_hub_device *hub) int i; struct usb_device *dev; unsigned pgood_delay = hub->desc.bPwrOn2PwrGood * 2; + ALLOC_CACHE_ALIGN_BUFFER(struct usb_port_status, portsts, 1); + unsigned short portstatus; + int ret; dev = hub->pusb_dev; /* Enable power to the ports */ debug("enabling power on all ports\n"); for (i = 0; i < dev->maxchild; i++) { + /* + * Power-cycle the ports here: aka, + * turning them off and turning on again. + */ + usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_POWER); + debug("port %d returns %lX\n", i + 1, dev->status); + + /* Wait at least 2*bPwrOn2PwrGood for PP to change */ + mdelay(pgood_delay); + + ret = usb_get_port_status(dev, i + 1, portsts); + if (ret < 0) { + debug("port %d: get_port_status failed\n", i + 1); + return; + } + + /* + * Check to confirm the state of Port Power: + * xHCI says "After modifying PP, s/w shall read + * PP and confirm that it has reached the desired state + * before modifying it again, undefined behavior may occur + * if this procedure is not followed". + * EHCI doesn't say anything like this, but no harm in keeping + * this. + */ + portstatus = le16_to_cpu(portsts->wPortStatus); + if (portstatus & (USB_PORT_STAT_POWER << 1)) { + debug("port %d: Port power change failed\n", i + 1); + return; + } + usb_set_port_feature(dev, i + 1, USB_PORT_FEAT_POWER); debug("port %d returns %lX\n", i + 1, dev->status); } |