mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-06-07 15:18:15 +00:00
xHCI: Set link state support
This patch adds support for Set Port Feature(PORT_LINK_STATE) request. The most significant byte (bits 15..8) of the wIndex field specifies the U state the host software wants to put the link connected to the port into. This request is only valid when the PORT_ENABLE bit is set and the PORT_LINK_STATE should not be above value '5' (Rx.Detect). This request will be later used to replace the set/clear suspend USB3 protocol ports in hub driver. Signed-off-by: Andiry Xu <andiry.xu@amd.com> Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
This commit is contained in:
parent
85387c0ea3
commit
2c44178032
1 changed files with 41 additions and 0 deletions
|
@ -387,6 +387,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
|
||||||
__le32 __iomem **port_array;
|
__le32 __iomem **port_array;
|
||||||
int slot_id;
|
int slot_id;
|
||||||
struct xhci_bus_state *bus_state;
|
struct xhci_bus_state *bus_state;
|
||||||
|
u16 link_state = 0;
|
||||||
|
|
||||||
if (hcd->speed == HCD_USB3) {
|
if (hcd->speed == HCD_USB3) {
|
||||||
ports = xhci->num_usb3_ports;
|
ports = xhci->num_usb3_ports;
|
||||||
|
@ -497,6 +498,8 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
|
||||||
put_unaligned(cpu_to_le32(status), (__le32 *) buf);
|
put_unaligned(cpu_to_le32(status), (__le32 *) buf);
|
||||||
break;
|
break;
|
||||||
case SetPortFeature:
|
case SetPortFeature:
|
||||||
|
if (wValue == USB_PORT_FEAT_LINK_STATE)
|
||||||
|
link_state = (wIndex & 0xff00) >> 3;
|
||||||
wIndex &= 0xff;
|
wIndex &= 0xff;
|
||||||
if (!wIndex || wIndex > ports)
|
if (!wIndex || wIndex > ports)
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -545,6 +548,44 @@ 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]);
|
||||||
bus_state->suspended_ports |= 1 << wIndex;
|
bus_state->suspended_ports |= 1 << wIndex;
|
||||||
break;
|
break;
|
||||||
|
case USB_PORT_FEAT_LINK_STATE:
|
||||||
|
temp = xhci_readl(xhci, port_array[wIndex]);
|
||||||
|
/* Software should not attempt to set
|
||||||
|
* port link state above '5' (Rx.Detect) and the port
|
||||||
|
* must be enabled.
|
||||||
|
*/
|
||||||
|
if ((temp & PORT_PE) == 0 ||
|
||||||
|
(link_state > USB_SS_PORT_LS_RX_DETECT)) {
|
||||||
|
xhci_warn(xhci, "Cannot set link state.\n");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (link_state == USB_SS_PORT_LS_U3) {
|
||||||
|
slot_id = xhci_find_slot_id_by_port(hcd, xhci,
|
||||||
|
wIndex + 1);
|
||||||
|
if (slot_id) {
|
||||||
|
/* unlock to execute stop endpoint
|
||||||
|
* commands */
|
||||||
|
spin_unlock_irqrestore(&xhci->lock,
|
||||||
|
flags);
|
||||||
|
xhci_stop_device(xhci, slot_id, 1);
|
||||||
|
spin_lock_irqsave(&xhci->lock, flags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
temp = xhci_port_state_to_neutral(temp);
|
||||||
|
temp &= ~PORT_PLS_MASK;
|
||||||
|
temp |= PORT_LINK_STROBE | link_state;
|
||||||
|
xhci_writel(xhci, temp, port_array[wIndex]);
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&xhci->lock, flags);
|
||||||
|
msleep(20); /* wait device to enter */
|
||||||
|
spin_lock_irqsave(&xhci->lock, flags);
|
||||||
|
|
||||||
|
temp = xhci_readl(xhci, port_array[wIndex]);
|
||||||
|
if (link_state == USB_SS_PORT_LS_U3)
|
||||||
|
bus_state->suspended_ports |= 1 << wIndex;
|
||||||
|
break;
|
||||||
case USB_PORT_FEAT_POWER:
|
case USB_PORT_FEAT_POWER:
|
||||||
/*
|
/*
|
||||||
* Turn on ports, even if there isn't per-port switching.
|
* Turn on ports, even if there isn't per-port switching.
|
||||||
|
|
Loading…
Add table
Reference in a new issue