Commit 797b0ca5 authored by Sarah Sharp's avatar Sarah Sharp

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: default avatarSarah Sharp <sarah.a.sharp@linux.intel.com>
parent 33b2831a
...@@ -475,6 +475,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, ...@@ -475,6 +475,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
struct xhci_bus_state *bus_state; struct xhci_bus_state *bus_state;
u16 link_state = 0; u16 link_state = 0;
u16 wake_mask = 0; u16 wake_mask = 0;
u16 timeout = 0;
max_ports = xhci_get_ports(hcd, &port_array); max_ports = xhci_get_ports(hcd, &port_array);
bus_state = &xhci->bus_state[hcd_index(hcd)]; 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,6 +624,8 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
link_state = (wIndex & 0xff00) >> 3; link_state = (wIndex & 0xff00) >> 3;
if (wValue == USB_PORT_FEAT_REMOTE_WAKE_MASK) if (wValue == USB_PORT_FEAT_REMOTE_WAKE_MASK)
wake_mask = wIndex & 0xff00; wake_mask = wIndex & 0xff00;
/* The MSB of wIndex is the U1/U2 timeout */
timeout = (wIndex & 0xff00) >> 8;
wIndex &= 0xff; wIndex &= 0xff;
if (!wIndex || wIndex > max_ports) if (!wIndex || wIndex > max_ports)
goto error; goto error;
...@@ -747,6 +750,22 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, ...@@ -747,6 +750,22 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
temp = xhci_readl(xhci, port_array[wIndex]); temp = xhci_readl(xhci, port_array[wIndex]);
break; break;
case USB_PORT_FEAT_U1_TIMEOUT:
if (hcd->speed != HCD_USB3)
goto error;
temp = xhci_readl(xhci, port_array[wIndex] + 1);
temp &= ~PORT_U1_TIMEOUT_MASK;
temp |= PORT_U1_TIMEOUT(timeout);
xhci_writel(xhci, temp, port_array[wIndex] + 1);
break;
case USB_PORT_FEAT_U2_TIMEOUT:
if (hcd->speed != HCD_USB3)
goto error;
temp = xhci_readl(xhci, port_array[wIndex] + 1);
temp &= ~PORT_U2_TIMEOUT_MASK;
temp |= PORT_U2_TIMEOUT(timeout);
xhci_writel(xhci, temp, port_array[wIndex] + 1);
break;
default: default:
goto error; goto error;
} }
......
...@@ -362,8 +362,10 @@ struct xhci_op_regs { ...@@ -362,8 +362,10 @@ struct xhci_op_regs {
* Timeout can be up to 127us. 0xFF means an infinite timeout. * Timeout can be up to 127us. 0xFF means an infinite timeout.
*/ */
#define PORT_U1_TIMEOUT(p) ((p) & 0xff) #define PORT_U1_TIMEOUT(p) ((p) & 0xff)
#define PORT_U1_TIMEOUT_MASK 0xff
/* Inactivity timer value for transitions into U2 */ /* Inactivity timer value for transitions into U2 */
#define PORT_U2_TIMEOUT(p) (((p) & 0xff) << 8) #define PORT_U2_TIMEOUT(p) (((p) & 0xff) << 8)
#define PORT_U2_TIMEOUT_MASK (0xff << 8)
/* Bits 24:31 for port testing */ /* Bits 24:31 for port testing */
/* USB2 Protocol PORTSPMSC */ /* USB2 Protocol PORTSPMSC */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment