aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorSarah Sharp <sarah.a.sharp@linux.intel.com>2011-11-10 19:02:13 -0500
committerSarah Sharp <sarah.a.sharp@linux.intel.com>2012-05-18 18:41:52 -0400
commit797b0ca5e6283b4cc0bdeeb0e5915f21522ba85f (patch)
treed0403d305832896a4b13a96ee43090c41d7ddc81 /drivers/usb
parent33b2831ac870d50cc8e01c317b07fb1e69c13fe1 (diff)
xhci: Add roothub code to set U1/U2 timeouts.
USB 3.0 hubs can be put into a mode where the hub can automatically request that the link go into a deeper link power state after the link has been idle for a specified amount of time. Each of the new USB 3.0 link states (U1 and U2) have their own timeout that can be programmed per port. Change the xHCI roothub emulation code to handle the request to set the U1 and U2 timeouts. Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/host/xhci-hub.c19
-rw-r--r--drivers/usb/host/xhci.h2
2 files changed, 21 insertions, 0 deletions
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index 89850a82d51..2732ef660c5 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -475,6 +475,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
475 struct xhci_bus_state *bus_state; 475 struct xhci_bus_state *bus_state;
476 u16 link_state = 0; 476 u16 link_state = 0;
477 u16 wake_mask = 0; 477 u16 wake_mask = 0;
478 u16 timeout = 0;
478 479
479 max_ports = xhci_get_ports(hcd, &port_array); 480 max_ports = xhci_get_ports(hcd, &port_array);
480 bus_state = &xhci->bus_state[hcd_index(hcd)]; 481 bus_state = &xhci->bus_state[hcd_index(hcd)];
@@ -623,6 +624,8 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
623 link_state = (wIndex & 0xff00) >> 3; 624 link_state = (wIndex & 0xff00) >> 3;
624 if (wValue == USB_PORT_FEAT_REMOTE_WAKE_MASK) 625 if (wValue == USB_PORT_FEAT_REMOTE_WAKE_MASK)
625 wake_mask = wIndex & 0xff00; 626 wake_mask = wIndex & 0xff00;
627 /* The MSB of wIndex is the U1/U2 timeout */
628 timeout = (wIndex & 0xff00) >> 8;
626 wIndex &= 0xff; 629 wIndex &= 0xff;
627 if (!wIndex || wIndex > max_ports) 630 if (!wIndex || wIndex > max_ports)
628 goto error; 631 goto error;
@@ -747,6 +750,22 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
747 750
748 temp = xhci_readl(xhci, port_array[wIndex]); 751 temp = xhci_readl(xhci, port_array[wIndex]);
749 break; 752 break;
753 case USB_PORT_FEAT_U1_TIMEOUT:
754 if (hcd->speed != HCD_USB3)
755 goto error;
756 temp = xhci_readl(xhci, port_array[wIndex] + 1);
757 temp &= ~PORT_U1_TIMEOUT_MASK;
758 temp |= PORT_U1_TIMEOUT(timeout);
759 xhci_writel(xhci, temp, port_array[wIndex] + 1);
760 break;
761 case USB_PORT_FEAT_U2_TIMEOUT:
762 if (hcd->speed != HCD_USB3)
763 goto error;
764 temp = xhci_readl(xhci, port_array[wIndex] + 1);
765 temp &= ~PORT_U2_TIMEOUT_MASK;
766 temp |= PORT_U2_TIMEOUT(timeout);
767 xhci_writel(xhci, temp, port_array[wIndex] + 1);
768 break;
750 default: 769 default:
751 goto error; 770 goto error;
752 } 771 }
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index ac142760fd3..58d527ccb24 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -362,8 +362,10 @@ struct xhci_op_regs {
362 * Timeout can be up to 127us. 0xFF means an infinite timeout. 362 * Timeout can be up to 127us. 0xFF means an infinite timeout.
363 */ 363 */
364#define PORT_U1_TIMEOUT(p) ((p) & 0xff) 364#define PORT_U1_TIMEOUT(p) ((p) & 0xff)
365#define PORT_U1_TIMEOUT_MASK 0xff
365/* Inactivity timer value for transitions into U2 */ 366/* Inactivity timer value for transitions into U2 */
366#define PORT_U2_TIMEOUT(p) (((p) & 0xff) << 8) 367#define PORT_U2_TIMEOUT(p) (((p) & 0xff) << 8)
368#define PORT_U2_TIMEOUT_MASK (0xff << 8)
367/* Bits 24:31 for port testing */ 369/* Bits 24:31 for port testing */
368 370
369/* USB2 Protocol PORTSPMSC */ 371/* USB2 Protocol PORTSPMSC */