15fd54aceSGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
20f2a7930SSarah Sharp /*
30f2a7930SSarah Sharp * xHCI host controller driver
40f2a7930SSarah Sharp *
50f2a7930SSarah Sharp * Copyright (C) 2008 Intel Corp.
60f2a7930SSarah Sharp *
70f2a7930SSarah Sharp * Author: Sarah Sharp
80f2a7930SSarah Sharp * Some code borrowed from the Linux EHCI driver.
90f2a7930SSarah Sharp */
100f2a7930SSarah Sharp
11ddba5cd0SMathias Nyman
12ddba5cd0SMathias Nyman #include <linux/slab.h>
130f2a7930SSarah Sharp #include <asm/unaligned.h>
14eb02aaf2SThinh Nguyen #include <linux/bitfield.h>
150f2a7930SSarah Sharp
160f2a7930SSarah Sharp #include "xhci.h"
174bdfe4c3SXenia Ragiadakou #include "xhci-trace.h"
180f2a7930SSarah Sharp
199777e3ceSAndiry Xu #define PORT_WAKE_BITS (PORT_WKOC_E | PORT_WKDISC_E | PORT_WKCONN_E)
209777e3ceSAndiry Xu #define PORT_RWC_BITS (PORT_CSC | PORT_PEC | PORT_WRC | PORT_OCC | \
219777e3ceSAndiry Xu PORT_RC | PORT_PLC | PORT_PE)
229777e3ceSAndiry Xu
23eb02aaf2SThinh Nguyen /* Default sublink speed attribute of each lane */
24eb02aaf2SThinh Nguyen static u32 ssp_cap_default_ssa[] = {
25eb02aaf2SThinh Nguyen 0x00050034, /* USB 3.0 SS Gen1x1 id:4 symmetric rx 5Gbps */
26eb02aaf2SThinh Nguyen 0x000500b4, /* USB 3.0 SS Gen1x1 id:4 symmetric tx 5Gbps */
27eb02aaf2SThinh Nguyen 0x000a4035, /* USB 3.1 SSP Gen2x1 id:5 symmetric rx 10Gbps */
28eb02aaf2SThinh Nguyen 0x000a40b5, /* USB 3.1 SSP Gen2x1 id:5 symmetric tx 10Gbps */
29eb02aaf2SThinh Nguyen 0x00054036, /* USB 3.2 SSP Gen1x2 id:6 symmetric rx 5Gbps */
30eb02aaf2SThinh Nguyen 0x000540b6, /* USB 3.2 SSP Gen1x2 id:6 symmetric tx 5Gbps */
31eb02aaf2SThinh Nguyen 0x000a4037, /* USB 3.2 SSP Gen2x2 id:7 symmetric rx 10Gbps */
32eb02aaf2SThinh Nguyen 0x000a40b7, /* USB 3.2 SSP Gen2x2 id:7 symmetric tx 10Gbps */
33eb02aaf2SThinh Nguyen };
34eb02aaf2SThinh Nguyen
xhci_create_usb3x_bos_desc(struct xhci_hcd * xhci,char * buf,u16 wLength)35eb02aaf2SThinh Nguyen static int xhci_create_usb3x_bos_desc(struct xhci_hcd *xhci, char *buf,
36eb02aaf2SThinh Nguyen u16 wLength)
37eb02aaf2SThinh Nguyen {
38eb02aaf2SThinh Nguyen struct usb_bos_descriptor *bos;
39eb02aaf2SThinh Nguyen struct usb_ss_cap_descriptor *ss_cap;
40eb02aaf2SThinh Nguyen struct usb_ssp_cap_descriptor *ssp_cap;
41eb02aaf2SThinh Nguyen struct xhci_port_cap *port_cap = NULL;
42eb02aaf2SThinh Nguyen u16 bcdUSB;
43eb02aaf2SThinh Nguyen u32 reg;
44eb02aaf2SThinh Nguyen u32 min_rate = 0;
45eb02aaf2SThinh Nguyen u8 min_ssid;
46eb02aaf2SThinh Nguyen u8 ssac;
47eb02aaf2SThinh Nguyen u8 ssic;
48eb02aaf2SThinh Nguyen int offset;
49eb02aaf2SThinh Nguyen int i;
50eb02aaf2SThinh Nguyen
51eb02aaf2SThinh Nguyen /* BOS descriptor */
52eb02aaf2SThinh Nguyen bos = (struct usb_bos_descriptor *)buf;
53eb02aaf2SThinh Nguyen bos->bLength = USB_DT_BOS_SIZE;
54eb02aaf2SThinh Nguyen bos->bDescriptorType = USB_DT_BOS;
55eb02aaf2SThinh Nguyen bos->wTotalLength = cpu_to_le16(USB_DT_BOS_SIZE +
56eb02aaf2SThinh Nguyen USB_DT_USB_SS_CAP_SIZE);
57eb02aaf2SThinh Nguyen bos->bNumDeviceCaps = 1;
58eb02aaf2SThinh Nguyen
59eb02aaf2SThinh Nguyen /* Create the descriptor for port with the highest revision */
60eb02aaf2SThinh Nguyen for (i = 0; i < xhci->num_port_caps; i++) {
61eb02aaf2SThinh Nguyen u8 major = xhci->port_caps[i].maj_rev;
62eb02aaf2SThinh Nguyen u8 minor = xhci->port_caps[i].min_rev;
63eb02aaf2SThinh Nguyen u16 rev = (major << 8) | minor;
64eb02aaf2SThinh Nguyen
65eb02aaf2SThinh Nguyen if (i == 0 || bcdUSB < rev) {
66eb02aaf2SThinh Nguyen bcdUSB = rev;
67eb02aaf2SThinh Nguyen port_cap = &xhci->port_caps[i];
68eb02aaf2SThinh Nguyen }
69eb02aaf2SThinh Nguyen }
70eb02aaf2SThinh Nguyen
71eb02aaf2SThinh Nguyen if (bcdUSB >= 0x0310) {
72eb02aaf2SThinh Nguyen if (port_cap->psi_count) {
73eb02aaf2SThinh Nguyen u8 num_sym_ssa = 0;
74eb02aaf2SThinh Nguyen
75eb02aaf2SThinh Nguyen for (i = 0; i < port_cap->psi_count; i++) {
76eb02aaf2SThinh Nguyen if ((port_cap->psi[i] & PLT_MASK) == PLT_SYM)
77eb02aaf2SThinh Nguyen num_sym_ssa++;
78eb02aaf2SThinh Nguyen }
79eb02aaf2SThinh Nguyen
80eb02aaf2SThinh Nguyen ssac = port_cap->psi_count + num_sym_ssa - 1;
81eb02aaf2SThinh Nguyen ssic = port_cap->psi_uid_count - 1;
82eb02aaf2SThinh Nguyen } else {
83eb02aaf2SThinh Nguyen if (bcdUSB >= 0x0320)
84eb02aaf2SThinh Nguyen ssac = 7;
85eb02aaf2SThinh Nguyen else
86eb02aaf2SThinh Nguyen ssac = 3;
87eb02aaf2SThinh Nguyen
88eb02aaf2SThinh Nguyen ssic = (ssac + 1) / 2 - 1;
89eb02aaf2SThinh Nguyen }
90eb02aaf2SThinh Nguyen
91eb02aaf2SThinh Nguyen bos->bNumDeviceCaps++;
92eb02aaf2SThinh Nguyen bos->wTotalLength = cpu_to_le16(USB_DT_BOS_SIZE +
93eb02aaf2SThinh Nguyen USB_DT_USB_SS_CAP_SIZE +
94eb02aaf2SThinh Nguyen USB_DT_USB_SSP_CAP_SIZE(ssac));
95eb02aaf2SThinh Nguyen }
96eb02aaf2SThinh Nguyen
97eb02aaf2SThinh Nguyen if (wLength < USB_DT_BOS_SIZE + USB_DT_USB_SS_CAP_SIZE)
98eb02aaf2SThinh Nguyen return wLength;
99eb02aaf2SThinh Nguyen
100eb02aaf2SThinh Nguyen /* SuperSpeed USB Device Capability */
101eb02aaf2SThinh Nguyen ss_cap = (struct usb_ss_cap_descriptor *)&buf[USB_DT_BOS_SIZE];
102eb02aaf2SThinh Nguyen ss_cap->bLength = USB_DT_USB_SS_CAP_SIZE;
103eb02aaf2SThinh Nguyen ss_cap->bDescriptorType = USB_DT_DEVICE_CAPABILITY;
104eb02aaf2SThinh Nguyen ss_cap->bDevCapabilityType = USB_SS_CAP_TYPE;
105eb02aaf2SThinh Nguyen ss_cap->bmAttributes = 0; /* set later */
106eb02aaf2SThinh Nguyen ss_cap->wSpeedSupported = cpu_to_le16(USB_5GBPS_OPERATION);
107eb02aaf2SThinh Nguyen ss_cap->bFunctionalitySupport = USB_LOW_SPEED_OPERATION;
108eb02aaf2SThinh Nguyen ss_cap->bU1devExitLat = 0; /* set later */
109eb02aaf2SThinh Nguyen ss_cap->bU2DevExitLat = 0; /* set later */
110eb02aaf2SThinh Nguyen
111eb02aaf2SThinh Nguyen reg = readl(&xhci->cap_regs->hcc_params);
112eb02aaf2SThinh Nguyen if (HCC_LTC(reg))
113eb02aaf2SThinh Nguyen ss_cap->bmAttributes |= USB_LTM_SUPPORT;
114eb02aaf2SThinh Nguyen
115eb02aaf2SThinh Nguyen if ((xhci->quirks & XHCI_LPM_SUPPORT)) {
116eb02aaf2SThinh Nguyen reg = readl(&xhci->cap_regs->hcs_params3);
117eb02aaf2SThinh Nguyen ss_cap->bU1devExitLat = HCS_U1_LATENCY(reg);
118eb02aaf2SThinh Nguyen ss_cap->bU2DevExitLat = cpu_to_le16(HCS_U2_LATENCY(reg));
119eb02aaf2SThinh Nguyen }
120eb02aaf2SThinh Nguyen
121eb02aaf2SThinh Nguyen if (wLength < le16_to_cpu(bos->wTotalLength))
122eb02aaf2SThinh Nguyen return wLength;
123eb02aaf2SThinh Nguyen
124eb02aaf2SThinh Nguyen if (bcdUSB < 0x0310)
125eb02aaf2SThinh Nguyen return le16_to_cpu(bos->wTotalLength);
126eb02aaf2SThinh Nguyen
127eb02aaf2SThinh Nguyen ssp_cap = (struct usb_ssp_cap_descriptor *)&buf[USB_DT_BOS_SIZE +
128eb02aaf2SThinh Nguyen USB_DT_USB_SS_CAP_SIZE];
129eb02aaf2SThinh Nguyen ssp_cap->bLength = USB_DT_USB_SSP_CAP_SIZE(ssac);
130eb02aaf2SThinh Nguyen ssp_cap->bDescriptorType = USB_DT_DEVICE_CAPABILITY;
131eb02aaf2SThinh Nguyen ssp_cap->bDevCapabilityType = USB_SSP_CAP_TYPE;
132eb02aaf2SThinh Nguyen ssp_cap->bReserved = 0;
133eb02aaf2SThinh Nguyen ssp_cap->wReserved = 0;
134eb02aaf2SThinh Nguyen ssp_cap->bmAttributes =
135eb02aaf2SThinh Nguyen cpu_to_le32(FIELD_PREP(USB_SSP_SUBLINK_SPEED_ATTRIBS, ssac) |
136eb02aaf2SThinh Nguyen FIELD_PREP(USB_SSP_SUBLINK_SPEED_IDS, ssic));
137eb02aaf2SThinh Nguyen
138eb02aaf2SThinh Nguyen if (!port_cap->psi_count) {
139eb02aaf2SThinh Nguyen for (i = 0; i < ssac + 1; i++)
140eb02aaf2SThinh Nguyen ssp_cap->bmSublinkSpeedAttr[i] =
141eb02aaf2SThinh Nguyen cpu_to_le32(ssp_cap_default_ssa[i]);
142eb02aaf2SThinh Nguyen
143eb02aaf2SThinh Nguyen min_ssid = 4;
144eb02aaf2SThinh Nguyen goto out;
145eb02aaf2SThinh Nguyen }
146eb02aaf2SThinh Nguyen
147eb02aaf2SThinh Nguyen offset = 0;
148eb02aaf2SThinh Nguyen for (i = 0; i < port_cap->psi_count; i++) {
149eb02aaf2SThinh Nguyen u32 psi;
150eb02aaf2SThinh Nguyen u32 attr;
151eb02aaf2SThinh Nguyen u8 ssid;
152eb02aaf2SThinh Nguyen u8 lp;
153eb02aaf2SThinh Nguyen u8 lse;
154eb02aaf2SThinh Nguyen u8 psie;
155eb02aaf2SThinh Nguyen u16 lane_mantissa;
156eb02aaf2SThinh Nguyen u16 psim;
157eb02aaf2SThinh Nguyen u16 plt;
158eb02aaf2SThinh Nguyen
159eb02aaf2SThinh Nguyen psi = port_cap->psi[i];
160eb02aaf2SThinh Nguyen ssid = XHCI_EXT_PORT_PSIV(psi);
161eb02aaf2SThinh Nguyen lp = XHCI_EXT_PORT_LP(psi);
162eb02aaf2SThinh Nguyen psie = XHCI_EXT_PORT_PSIE(psi);
163eb02aaf2SThinh Nguyen psim = XHCI_EXT_PORT_PSIM(psi);
164eb02aaf2SThinh Nguyen plt = psi & PLT_MASK;
165eb02aaf2SThinh Nguyen
166eb02aaf2SThinh Nguyen lse = psie;
167eb02aaf2SThinh Nguyen lane_mantissa = psim;
168eb02aaf2SThinh Nguyen
169eb02aaf2SThinh Nguyen /* Shift to Gbps and set SSP Link Protocol if 10Gpbs */
170eb02aaf2SThinh Nguyen for (; psie < USB_SSP_SUBLINK_SPEED_LSE_GBPS; psie++)
171eb02aaf2SThinh Nguyen psim /= 1000;
172eb02aaf2SThinh Nguyen
173eb02aaf2SThinh Nguyen if (!min_rate || psim < min_rate) {
174eb02aaf2SThinh Nguyen min_ssid = ssid;
175eb02aaf2SThinh Nguyen min_rate = psim;
176eb02aaf2SThinh Nguyen }
177eb02aaf2SThinh Nguyen
178eb02aaf2SThinh Nguyen /* Some host controllers don't set the link protocol for SSP */
179eb02aaf2SThinh Nguyen if (psim >= 10)
180eb02aaf2SThinh Nguyen lp = USB_SSP_SUBLINK_SPEED_LP_SSP;
181eb02aaf2SThinh Nguyen
182eb02aaf2SThinh Nguyen /*
183eb02aaf2SThinh Nguyen * PSIM and PSIE represent the total speed of PSI. The BOS
184eb02aaf2SThinh Nguyen * descriptor SSP sublink speed attribute lane mantissa
185eb02aaf2SThinh Nguyen * describes the lane speed. E.g. PSIM and PSIE for gen2x2
186eb02aaf2SThinh Nguyen * is 20Gbps, but the BOS descriptor lane speed mantissa is
187eb02aaf2SThinh Nguyen * 10Gbps. Check and modify the mantissa value to match the
188eb02aaf2SThinh Nguyen * lane speed.
189eb02aaf2SThinh Nguyen */
190eb02aaf2SThinh Nguyen if (bcdUSB == 0x0320 && plt == PLT_SYM) {
191eb02aaf2SThinh Nguyen /*
192eb02aaf2SThinh Nguyen * The PSI dword for gen1x2 and gen2x1 share the same
193eb02aaf2SThinh Nguyen * values. But the lane speed for gen1x2 is 5Gbps while
194eb02aaf2SThinh Nguyen * gen2x1 is 10Gbps. If the previous PSI dword SSID is
195eb02aaf2SThinh Nguyen * 5 and the PSIE and PSIM match with SSID 6, let's
196eb02aaf2SThinh Nguyen * assume that the controller follows the default speed
197eb02aaf2SThinh Nguyen * id with SSID 6 for gen1x2.
198eb02aaf2SThinh Nguyen */
199eb02aaf2SThinh Nguyen if (ssid == 6 && psie == 3 && psim == 10 && i) {
200eb02aaf2SThinh Nguyen u32 prev = port_cap->psi[i - 1];
201eb02aaf2SThinh Nguyen
202eb02aaf2SThinh Nguyen if ((prev & PLT_MASK) == PLT_SYM &&
203eb02aaf2SThinh Nguyen XHCI_EXT_PORT_PSIV(prev) == 5 &&
204eb02aaf2SThinh Nguyen XHCI_EXT_PORT_PSIE(prev) == 3 &&
205eb02aaf2SThinh Nguyen XHCI_EXT_PORT_PSIM(prev) == 10) {
206eb02aaf2SThinh Nguyen lse = USB_SSP_SUBLINK_SPEED_LSE_GBPS;
207eb02aaf2SThinh Nguyen lane_mantissa = 5;
208eb02aaf2SThinh Nguyen }
209eb02aaf2SThinh Nguyen }
210eb02aaf2SThinh Nguyen
211eb02aaf2SThinh Nguyen if (psie == 3 && psim > 10) {
212eb02aaf2SThinh Nguyen lse = USB_SSP_SUBLINK_SPEED_LSE_GBPS;
213eb02aaf2SThinh Nguyen lane_mantissa = 10;
214eb02aaf2SThinh Nguyen }
215eb02aaf2SThinh Nguyen }
216eb02aaf2SThinh Nguyen
217eb02aaf2SThinh Nguyen attr = (FIELD_PREP(USB_SSP_SUBLINK_SPEED_SSID, ssid) |
218eb02aaf2SThinh Nguyen FIELD_PREP(USB_SSP_SUBLINK_SPEED_LP, lp) |
219eb02aaf2SThinh Nguyen FIELD_PREP(USB_SSP_SUBLINK_SPEED_LSE, lse) |
220eb02aaf2SThinh Nguyen FIELD_PREP(USB_SSP_SUBLINK_SPEED_LSM, lane_mantissa));
221eb02aaf2SThinh Nguyen
222eb02aaf2SThinh Nguyen switch (plt) {
223eb02aaf2SThinh Nguyen case PLT_SYM:
224eb02aaf2SThinh Nguyen attr |= FIELD_PREP(USB_SSP_SUBLINK_SPEED_ST,
225eb02aaf2SThinh Nguyen USB_SSP_SUBLINK_SPEED_ST_SYM_RX);
226eb02aaf2SThinh Nguyen ssp_cap->bmSublinkSpeedAttr[offset++] = cpu_to_le32(attr);
227eb02aaf2SThinh Nguyen
228eb02aaf2SThinh Nguyen attr &= ~USB_SSP_SUBLINK_SPEED_ST;
229eb02aaf2SThinh Nguyen attr |= FIELD_PREP(USB_SSP_SUBLINK_SPEED_ST,
230eb02aaf2SThinh Nguyen USB_SSP_SUBLINK_SPEED_ST_SYM_TX);
231eb02aaf2SThinh Nguyen ssp_cap->bmSublinkSpeedAttr[offset++] = cpu_to_le32(attr);
232eb02aaf2SThinh Nguyen break;
233eb02aaf2SThinh Nguyen case PLT_ASYM_RX:
234eb02aaf2SThinh Nguyen attr |= FIELD_PREP(USB_SSP_SUBLINK_SPEED_ST,
235eb02aaf2SThinh Nguyen USB_SSP_SUBLINK_SPEED_ST_ASYM_RX);
236eb02aaf2SThinh Nguyen ssp_cap->bmSublinkSpeedAttr[offset++] = cpu_to_le32(attr);
237eb02aaf2SThinh Nguyen break;
238eb02aaf2SThinh Nguyen case PLT_ASYM_TX:
239eb02aaf2SThinh Nguyen attr |= FIELD_PREP(USB_SSP_SUBLINK_SPEED_ST,
240eb02aaf2SThinh Nguyen USB_SSP_SUBLINK_SPEED_ST_ASYM_TX);
241eb02aaf2SThinh Nguyen ssp_cap->bmSublinkSpeedAttr[offset++] = cpu_to_le32(attr);
242eb02aaf2SThinh Nguyen break;
243eb02aaf2SThinh Nguyen }
244eb02aaf2SThinh Nguyen }
245eb02aaf2SThinh Nguyen out:
246eb02aaf2SThinh Nguyen ssp_cap->wFunctionalitySupport =
247eb02aaf2SThinh Nguyen cpu_to_le16(FIELD_PREP(USB_SSP_MIN_SUBLINK_SPEED_ATTRIBUTE_ID,
248eb02aaf2SThinh Nguyen min_ssid) |
249eb02aaf2SThinh Nguyen FIELD_PREP(USB_SSP_MIN_RX_LANE_COUNT, 1) |
250eb02aaf2SThinh Nguyen FIELD_PREP(USB_SSP_MIN_TX_LANE_COUNT, 1));
251eb02aaf2SThinh Nguyen
252eb02aaf2SThinh Nguyen return le16_to_cpu(bos->wTotalLength);
253eb02aaf2SThinh Nguyen }
254eb02aaf2SThinh Nguyen
xhci_common_hub_descriptor(struct xhci_hcd * xhci,struct usb_hub_descriptor * desc,int ports)2554bbb0aceSSarah Sharp static void xhci_common_hub_descriptor(struct xhci_hcd *xhci,
2564bbb0aceSSarah Sharp struct usb_hub_descriptor *desc, int ports)
2570f2a7930SSarah Sharp {
2580f2a7930SSarah Sharp u16 temp;
2590f2a7930SSarah Sharp
2600f2a7930SSarah Sharp desc->bHubContrCurrent = 0;
2610f2a7930SSarah Sharp
2620f2a7930SSarah Sharp desc->bNbrPorts = ports;
2630f2a7930SSarah Sharp temp = 0;
264c8421147SAman Deep /* Bits 1:0 - support per-port power switching, or power always on */
2650f2a7930SSarah Sharp if (HCC_PPC(xhci->hcc_params))
266c8421147SAman Deep temp |= HUB_CHAR_INDV_PORT_LPSM;
2670f2a7930SSarah Sharp else
268c8421147SAman Deep temp |= HUB_CHAR_NO_LPSM;
2690f2a7930SSarah Sharp /* Bit 2 - root hubs are not part of a compound device */
2700f2a7930SSarah Sharp /* Bits 4:3 - individual port over current protection */
271c8421147SAman Deep temp |= HUB_CHAR_INDV_PORT_OCPM;
2720f2a7930SSarah Sharp /* Bits 6:5 - no TTs in root ports */
2730f2a7930SSarah Sharp /* Bit 7 - no port indicators */
27428ccd296SMatt Evans desc->wHubCharacteristics = cpu_to_le16(temp);
2750f2a7930SSarah Sharp }
2760f2a7930SSarah Sharp
2774bbb0aceSSarah Sharp /* Fill in the USB 2.0 roothub descriptor */
xhci_usb2_hub_descriptor(struct usb_hcd * hcd,struct xhci_hcd * xhci,struct usb_hub_descriptor * desc)2784bbb0aceSSarah Sharp static void xhci_usb2_hub_descriptor(struct usb_hcd *hcd, struct xhci_hcd *xhci,
2794bbb0aceSSarah Sharp struct usb_hub_descriptor *desc)
2804bbb0aceSSarah Sharp {
2814bbb0aceSSarah Sharp int ports;
2824bbb0aceSSarah Sharp u16 temp;
2834bbb0aceSSarah Sharp __u8 port_removable[(USB_MAXCHILDREN + 1 + 7) / 8];
2844bbb0aceSSarah Sharp u32 portsc;
2854bbb0aceSSarah Sharp unsigned int i;
286e740b019SMathias Nyman struct xhci_hub *rhub;
2874bbb0aceSSarah Sharp
288e740b019SMathias Nyman rhub = &xhci->usb2_rhub;
289e740b019SMathias Nyman ports = rhub->num_ports;
2904bbb0aceSSarah Sharp xhci_common_hub_descriptor(xhci, desc, ports);
291c8421147SAman Deep desc->bDescriptorType = USB_DT_HUB;
2924bbb0aceSSarah Sharp temp = 1 + (ports / 8);
293c8421147SAman Deep desc->bDescLength = USB_DT_HUB_NONVAR_SIZE + 2 * temp;
294e1959fafSMathias Nyman desc->bPwrOn2PwrGood = 10; /* xhci section 5.4.8 says 20ms */
2954bbb0aceSSarah Sharp
2964bbb0aceSSarah Sharp /* The Device Removable bits are reported on a byte granularity.
2974bbb0aceSSarah Sharp * If the port doesn't exist within that byte, the bit is set to 0.
2984bbb0aceSSarah Sharp */
2994bbb0aceSSarah Sharp memset(port_removable, 0, sizeof(port_removable));
3004bbb0aceSSarah Sharp for (i = 0; i < ports; i++) {
301e740b019SMathias Nyman portsc = readl(rhub->ports[i]->addr);
3024bbb0aceSSarah Sharp /* If a device is removable, PORTSC reports a 0, same as in the
3034bbb0aceSSarah Sharp * hub descriptor DeviceRemovable bits.
3044bbb0aceSSarah Sharp */
3054bbb0aceSSarah Sharp if (portsc & PORT_DEV_REMOVE)
3064bbb0aceSSarah Sharp /* This math is hairy because bit 0 of DeviceRemovable
3074bbb0aceSSarah Sharp * is reserved, and bit 1 is for port 1, etc.
3084bbb0aceSSarah Sharp */
3094bbb0aceSSarah Sharp port_removable[(i + 1) / 8] |= 1 << ((i + 1) % 8);
3104bbb0aceSSarah Sharp }
3114bbb0aceSSarah Sharp
3124bbb0aceSSarah Sharp /* ch11.h defines a hub descriptor that has room for USB_MAXCHILDREN
3134bbb0aceSSarah Sharp * ports on it. The USB 2.0 specification says that there are two
3144bbb0aceSSarah Sharp * variable length fields at the end of the hub descriptor:
3154bbb0aceSSarah Sharp * DeviceRemovable and PortPwrCtrlMask. But since we can have less than
3164bbb0aceSSarah Sharp * USB_MAXCHILDREN ports, we may need to use the DeviceRemovable array
3174bbb0aceSSarah Sharp * to set PortPwrCtrlMask bits. PortPwrCtrlMask must always be set to
3184bbb0aceSSarah Sharp * 0xFF, so we initialize the both arrays (DeviceRemovable and
3194bbb0aceSSarah Sharp * PortPwrCtrlMask) to 0xFF. Then we set the DeviceRemovable for each
3204bbb0aceSSarah Sharp * set of ports that actually exist.
3214bbb0aceSSarah Sharp */
3224bbb0aceSSarah Sharp memset(desc->u.hs.DeviceRemovable, 0xff,
3234bbb0aceSSarah Sharp sizeof(desc->u.hs.DeviceRemovable));
3244bbb0aceSSarah Sharp memset(desc->u.hs.PortPwrCtrlMask, 0xff,
3254bbb0aceSSarah Sharp sizeof(desc->u.hs.PortPwrCtrlMask));
3264bbb0aceSSarah Sharp
3274bbb0aceSSarah Sharp for (i = 0; i < (ports + 1 + 7) / 8; i++)
3284bbb0aceSSarah Sharp memset(&desc->u.hs.DeviceRemovable[i], port_removable[i],
3294bbb0aceSSarah Sharp sizeof(__u8));
3304bbb0aceSSarah Sharp }
3314bbb0aceSSarah Sharp
3324bbb0aceSSarah Sharp /* Fill in the USB 3.0 roothub descriptor */
xhci_usb3_hub_descriptor(struct usb_hcd * hcd,struct xhci_hcd * xhci,struct usb_hub_descriptor * desc)3334bbb0aceSSarah Sharp static void xhci_usb3_hub_descriptor(struct usb_hcd *hcd, struct xhci_hcd *xhci,
3344bbb0aceSSarah Sharp struct usb_hub_descriptor *desc)
3354bbb0aceSSarah Sharp {
3364bbb0aceSSarah Sharp int ports;
3374bbb0aceSSarah Sharp u16 port_removable;
3384bbb0aceSSarah Sharp u32 portsc;
3394bbb0aceSSarah Sharp unsigned int i;
340e740b019SMathias Nyman struct xhci_hub *rhub;
3414bbb0aceSSarah Sharp
342e740b019SMathias Nyman rhub = &xhci->usb3_rhub;
343e740b019SMathias Nyman ports = rhub->num_ports;
3444bbb0aceSSarah Sharp xhci_common_hub_descriptor(xhci, desc, ports);
345c8421147SAman Deep desc->bDescriptorType = USB_DT_SS_HUB;
346c8421147SAman Deep desc->bDescLength = USB_DT_SS_HUB_SIZE;
347e1959fafSMathias Nyman desc->bPwrOn2PwrGood = 50; /* usb 3.1 may fail if less than 100ms */
3484bbb0aceSSarah Sharp
3494bbb0aceSSarah Sharp /* header decode latency should be zero for roothubs,
3504bbb0aceSSarah Sharp * see section 4.23.5.2.
3514bbb0aceSSarah Sharp */
3524bbb0aceSSarah Sharp desc->u.ss.bHubHdrDecLat = 0;
3534bbb0aceSSarah Sharp desc->u.ss.wHubDelay = 0;
3544bbb0aceSSarah Sharp
3554bbb0aceSSarah Sharp port_removable = 0;
3564bbb0aceSSarah Sharp /* bit 0 is reserved, bit 1 is for port 1, etc. */
3574bbb0aceSSarah Sharp for (i = 0; i < ports; i++) {
358e740b019SMathias Nyman portsc = readl(rhub->ports[i]->addr);
3594bbb0aceSSarah Sharp if (portsc & PORT_DEV_REMOVE)
3604bbb0aceSSarah Sharp port_removable |= 1 << (i + 1);
3614bbb0aceSSarah Sharp }
36227c411c9SLan Tianyu
36327c411c9SLan Tianyu desc->u.ss.DeviceRemovable = cpu_to_le16(port_removable);
3644bbb0aceSSarah Sharp }
3654bbb0aceSSarah Sharp
xhci_hub_descriptor(struct usb_hcd * hcd,struct xhci_hcd * xhci,struct usb_hub_descriptor * desc)3664bbb0aceSSarah Sharp static void xhci_hub_descriptor(struct usb_hcd *hcd, struct xhci_hcd *xhci,
3674bbb0aceSSarah Sharp struct usb_hub_descriptor *desc)
3684bbb0aceSSarah Sharp {
3694bbb0aceSSarah Sharp
370b50107bbSMathias Nyman if (hcd->speed >= HCD_USB3)
3714bbb0aceSSarah Sharp xhci_usb3_hub_descriptor(hcd, xhci, desc);
3724bbb0aceSSarah Sharp else
3734bbb0aceSSarah Sharp xhci_usb2_hub_descriptor(hcd, xhci, desc);
3744bbb0aceSSarah Sharp
3754bbb0aceSSarah Sharp }
3764bbb0aceSSarah Sharp
xhci_port_speed(unsigned int port_status)3770f2a7930SSarah Sharp static unsigned int xhci_port_speed(unsigned int port_status)
3780f2a7930SSarah Sharp {
3790f2a7930SSarah Sharp if (DEV_LOWSPEED(port_status))
380288ead45SAlan Stern return USB_PORT_STAT_LOW_SPEED;
3810f2a7930SSarah Sharp if (DEV_HIGHSPEED(port_status))
382288ead45SAlan Stern return USB_PORT_STAT_HIGH_SPEED;
3830f2a7930SSarah Sharp /*
3840f2a7930SSarah Sharp * FIXME: Yes, we should check for full speed, but the core uses that as
3850f2a7930SSarah Sharp * a default in portspeed() in usb/core/hub.c (which is the only place
386288ead45SAlan Stern * USB_PORT_STAT_*_SPEED is used).
3870f2a7930SSarah Sharp */
3880f2a7930SSarah Sharp return 0;
3890f2a7930SSarah Sharp }
3900f2a7930SSarah Sharp
3910f2a7930SSarah Sharp /*
3920f2a7930SSarah Sharp * These bits are Read Only (RO) and should be saved and written to the
3930f2a7930SSarah Sharp * registers: 0, 3, 10:13, 30
3940f2a7930SSarah Sharp * connect status, over-current status, port speed, and device removable.
3950f2a7930SSarah Sharp * connect status and port speed are also sticky - meaning they're in
3960f2a7930SSarah Sharp * the AUX well and they aren't changed by a hot, warm, or cold reset.
3970f2a7930SSarah Sharp */
3980f2a7930SSarah Sharp #define XHCI_PORT_RO ((1<<0) | (1<<3) | (0xf<<10) | (1<<30))
3990f2a7930SSarah Sharp /*
4000f2a7930SSarah Sharp * These bits are RW; writing a 0 clears the bit, writing a 1 sets the bit:
4010f2a7930SSarah Sharp * bits 5:8, 9, 14:15, 25:27
4020f2a7930SSarah Sharp * link state, port power, port indicator state, "wake on" enable state
4030f2a7930SSarah Sharp */
4040f2a7930SSarah Sharp #define XHCI_PORT_RWS ((0xf<<5) | (1<<9) | (0x3<<14) | (0x7<<25))
4050f2a7930SSarah Sharp /*
4060f2a7930SSarah Sharp * These bits are RW; writing a 1 sets the bit, writing a 0 has no effect:
4070f2a7930SSarah Sharp * bit 4 (port reset)
4080f2a7930SSarah Sharp */
4090f2a7930SSarah Sharp #define XHCI_PORT_RW1S ((1<<4))
4100f2a7930SSarah Sharp /*
4110f2a7930SSarah Sharp * These bits are RW; writing a 1 clears the bit, writing a 0 has no effect:
4120f2a7930SSarah Sharp * bits 1, 17, 18, 19, 20, 21, 22, 23
4130f2a7930SSarah Sharp * port enable/disable, and
4140f2a7930SSarah Sharp * change bits: connect, PED, warm port reset changed (reserved zero for USB 2.0 ports),
4150f2a7930SSarah Sharp * over-current, reset, link state, and L1 change
4160f2a7930SSarah Sharp */
4170f2a7930SSarah Sharp #define XHCI_PORT_RW1CS ((1<<1) | (0x7f<<17))
4180f2a7930SSarah Sharp /*
4190f2a7930SSarah Sharp * Bit 16 is RW, and writing a '1' to it causes the link state control to be
4200f2a7930SSarah Sharp * latched in
4210f2a7930SSarah Sharp */
4220f2a7930SSarah Sharp #define XHCI_PORT_RW ((1<<16))
4230f2a7930SSarah Sharp /*
4240f2a7930SSarah Sharp * These bits are Reserved Zero (RsvdZ) and zero should be written to them:
4250f2a7930SSarah Sharp * bits 2, 24, 28:31
4260f2a7930SSarah Sharp */
4270f2a7930SSarah Sharp #define XHCI_PORT_RZ ((1<<2) | (1<<24) | (0xf<<28))
4280f2a7930SSarah Sharp
429*705c333aSMathias Nyman /**
430*705c333aSMathias Nyman * xhci_port_state_to_neutral() - Clean up read portsc value back into writeable
431*705c333aSMathias Nyman * @state: u32 port value read from portsc register to be cleanup up
432*705c333aSMathias Nyman *
4330f2a7930SSarah Sharp * Given a port state, this function returns a value that would result in the
4340f2a7930SSarah Sharp * port being in the same state, if the value was written to the port status
4350f2a7930SSarah Sharp * control register.
4360f2a7930SSarah Sharp * Save Read Only (RO) bits and save read/write bits where
4370f2a7930SSarah Sharp * writing a 0 clears the bit and writing a 1 sets the bit (RWS).
4380f2a7930SSarah Sharp * For all other types (RW1S, RW1CS, RW, and RZ), writing a '0' has no effect.
439*705c333aSMathias Nyman *
440*705c333aSMathias Nyman * Return: u32 value that can be written back to portsc register without
441*705c333aSMathias Nyman * changing port state.
4420f2a7930SSarah Sharp */
443*705c333aSMathias Nyman
xhci_port_state_to_neutral(u32 state)44456192531SAndiry Xu u32 xhci_port_state_to_neutral(u32 state)
4450f2a7930SSarah Sharp {
4460f2a7930SSarah Sharp /* Save read-only status and port state */
4470f2a7930SSarah Sharp return (state & XHCI_PORT_RO) | (state & XHCI_PORT_RWS);
4480f2a7930SSarah Sharp }
449*705c333aSMathias Nyman EXPORT_SYMBOL_GPL(xhci_port_state_to_neutral);
4500f2a7930SSarah Sharp
451*705c333aSMathias Nyman /**
452*705c333aSMathias Nyman * xhci_find_slot_id_by_port() - Find slot id of a usb device on a roothub port
453*705c333aSMathias Nyman * @hcd: pointer to hcd of the roothub
454*705c333aSMathias Nyman * @xhci: pointer to xhci structure
455*705c333aSMathias Nyman * @port: one-based port number of the port in this roothub.
456*705c333aSMathias Nyman *
457*705c333aSMathias Nyman * Return: Slot id of the usb device connected to the root port, 0 if not found
458be88fe4fSAndiry Xu */
459*705c333aSMathias Nyman
xhci_find_slot_id_by_port(struct usb_hcd * hcd,struct xhci_hcd * xhci,u16 port)4605233630fSSarah Sharp int xhci_find_slot_id_by_port(struct usb_hcd *hcd, struct xhci_hcd *xhci,
4615233630fSSarah Sharp u16 port)
462be88fe4fSAndiry Xu {
463be88fe4fSAndiry Xu int slot_id;
464be88fe4fSAndiry Xu int i;
465f6ff0ac8SSarah Sharp enum usb_device_speed speed;
466be88fe4fSAndiry Xu
467be88fe4fSAndiry Xu slot_id = 0;
468be88fe4fSAndiry Xu for (i = 0; i < MAX_HC_SLOTS; i++) {
4692278446eSMathias Nyman if (!xhci->devs[i] || !xhci->devs[i]->udev)
470be88fe4fSAndiry Xu continue;
471f6ff0ac8SSarah Sharp speed = xhci->devs[i]->udev->speed;
472b50107bbSMathias Nyman if (((speed >= USB_SPEED_SUPER) == (hcd->speed >= HCD_USB3))
473fe30182cSSarah Sharp && xhci->devs[i]->fake_port == port) {
474be88fe4fSAndiry Xu slot_id = i;
475be88fe4fSAndiry Xu break;
476be88fe4fSAndiry Xu }
477be88fe4fSAndiry Xu }
478be88fe4fSAndiry Xu
479be88fe4fSAndiry Xu return slot_id;
480be88fe4fSAndiry Xu }
481*705c333aSMathias Nyman EXPORT_SYMBOL_GPL(xhci_find_slot_id_by_port);
482be88fe4fSAndiry Xu
483be88fe4fSAndiry Xu /*
484be88fe4fSAndiry Xu * Stop device
485be88fe4fSAndiry Xu * It issues stop endpoint command for EP 0 to 30. And wait the last command
486be88fe4fSAndiry Xu * to complete.
487be88fe4fSAndiry Xu * suspend will set to 1, if suspend bit need to set in command.
488be88fe4fSAndiry Xu */
xhci_stop_device(struct xhci_hcd * xhci,int slot_id,int suspend)489be88fe4fSAndiry Xu static int xhci_stop_device(struct xhci_hcd *xhci, int slot_id, int suspend)
490be88fe4fSAndiry Xu {
491be88fe4fSAndiry Xu struct xhci_virt_device *virt_dev;
492be88fe4fSAndiry Xu struct xhci_command *cmd;
493be88fe4fSAndiry Xu unsigned long flags;
494be88fe4fSAndiry Xu int ret;
495be88fe4fSAndiry Xu int i;
496be88fe4fSAndiry Xu
497be88fe4fSAndiry Xu ret = 0;
498be88fe4fSAndiry Xu virt_dev = xhci->devs[slot_id];
49988716a93SJim Lin if (!virt_dev)
50088716a93SJim Lin return -ENODEV;
50188716a93SJim Lin
502a711edeeSFelipe Balbi trace_xhci_stop_device(virt_dev);
503a711edeeSFelipe Balbi
504103afda0SMathias Nyman cmd = xhci_alloc_command(xhci, true, GFP_NOIO);
50574e0b564SLu Baolu if (!cmd)
506be88fe4fSAndiry Xu return -ENOMEM;
507be88fe4fSAndiry Xu
508be88fe4fSAndiry Xu spin_lock_irqsave(&xhci->lock, flags);
509be88fe4fSAndiry Xu for (i = LAST_EP_INDEX; i > 0; i--) {
510ddba5cd0SMathias Nyman if (virt_dev->eps[i].ring && virt_dev->eps[i].ring->dequeue) {
51128a2369fSShyam Sundar S K struct xhci_ep_ctx *ep_ctx;
512ddba5cd0SMathias Nyman struct xhci_command *command;
51328a2369fSShyam Sundar S K
51428a2369fSShyam Sundar S K ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->out_ctx, i);
51528a2369fSShyam Sundar S K
51628a2369fSShyam Sundar S K /* Check ep is running, required by AMD SNPS 3.1 xHC */
51728a2369fSShyam Sundar S K if (GET_EP_CTX_STATE(ep_ctx) != EP_STATE_RUNNING)
51828a2369fSShyam Sundar S K continue;
51928a2369fSShyam Sundar S K
520103afda0SMathias Nyman command = xhci_alloc_command(xhci, false, GFP_NOWAIT);
521ddba5cd0SMathias Nyman if (!command) {
522ddba5cd0SMathias Nyman spin_unlock_irqrestore(&xhci->lock, flags);
523b3207c65SMayank Rana ret = -ENOMEM;
524b3207c65SMayank Rana goto cmd_cleanup;
525be88fe4fSAndiry Xu }
526b3207c65SMayank Rana
527b3207c65SMayank Rana ret = xhci_queue_stop_endpoint(xhci, command, slot_id,
528b3207c65SMayank Rana i, suspend);
529b3207c65SMayank Rana if (ret) {
530b3207c65SMayank Rana spin_unlock_irqrestore(&xhci->lock, flags);
531b3207c65SMayank Rana xhci_free_command(xhci, command);
532b3207c65SMayank Rana goto cmd_cleanup;
533ddba5cd0SMathias Nyman }
534ddba5cd0SMathias Nyman }
535b3207c65SMayank Rana }
536b3207c65SMayank Rana ret = xhci_queue_stop_endpoint(xhci, cmd, slot_id, 0, suspend);
537b3207c65SMayank Rana if (ret) {
538b3207c65SMayank Rana spin_unlock_irqrestore(&xhci->lock, flags);
539b3207c65SMayank Rana goto cmd_cleanup;
540b3207c65SMayank Rana }
541b3207c65SMayank Rana
542be88fe4fSAndiry Xu xhci_ring_cmd_db(xhci);
543be88fe4fSAndiry Xu spin_unlock_irqrestore(&xhci->lock, flags);
544be88fe4fSAndiry Xu
545be88fe4fSAndiry Xu /* Wait for last stop endpoint command to finish */
546c311e391SMathias Nyman wait_for_completion(cmd->completion);
547c311e391SMathias Nyman
5480b7c105aSFelipe Balbi if (cmd->status == COMP_COMMAND_ABORTED ||
549604d02a2SMathias Nyman cmd->status == COMP_COMMAND_RING_STOPPED) {
550c311e391SMathias Nyman xhci_warn(xhci, "Timeout while waiting for stop endpoint command\n");
551be88fe4fSAndiry Xu ret = -ETIME;
552be88fe4fSAndiry Xu }
553b3207c65SMayank Rana
554b3207c65SMayank Rana cmd_cleanup:
555be88fe4fSAndiry Xu xhci_free_command(xhci, cmd);
556be88fe4fSAndiry Xu return ret;
557be88fe4fSAndiry Xu }
558be88fe4fSAndiry Xu
559be88fe4fSAndiry Xu /*
560be88fe4fSAndiry Xu * Ring device, it rings the all doorbells unconditionally.
561be88fe4fSAndiry Xu */
xhci_ring_device(struct xhci_hcd * xhci,int slot_id)56256192531SAndiry Xu void xhci_ring_device(struct xhci_hcd *xhci, int slot_id)
563be88fe4fSAndiry Xu {
564b7f9696bSHans de Goede int i, s;
565b7f9696bSHans de Goede struct xhci_virt_ep *ep;
566be88fe4fSAndiry Xu
567b7f9696bSHans de Goede for (i = 0; i < LAST_EP_INDEX + 1; i++) {
568b7f9696bSHans de Goede ep = &xhci->devs[slot_id]->eps[i];
569b7f9696bSHans de Goede
570b7f9696bSHans de Goede if (ep->ep_state & EP_HAS_STREAMS) {
571b7f9696bSHans de Goede for (s = 1; s < ep->stream_info->num_streams; s++)
572b7f9696bSHans de Goede xhci_ring_ep_doorbell(xhci, slot_id, i, s);
573b7f9696bSHans de Goede } else if (ep->ring && ep->ring->dequeue) {
574be88fe4fSAndiry Xu xhci_ring_ep_doorbell(xhci, slot_id, i, 0);
575b7f9696bSHans de Goede }
576b7f9696bSHans de Goede }
577be88fe4fSAndiry Xu
578be88fe4fSAndiry Xu return;
579be88fe4fSAndiry Xu }
580be88fe4fSAndiry Xu
xhci_disable_port(struct xhci_hcd * xhci,struct xhci_port * port)581f6ff0ac8SSarah Sharp static void xhci_disable_port(struct xhci_hcd *xhci, struct xhci_port *port)
58228ccd296SMatt Evans {
5836219c047SSarah Sharp struct usb_hcd *hcd;
5846dd0a3a7SSarah Sharp u32 portsc;
585b50107bbSMathias Nyman
5866dd0a3a7SSarah Sharp hcd = port->rhub->hcd;
5876dd0a3a7SSarah Sharp
5886dd0a3a7SSarah Sharp /* Don't allow the USB core to disable SuperSpeed ports. */
5896dd0a3a7SSarah Sharp if (hcd->speed >= HCD_USB3) {
5906dd0a3a7SSarah Sharp xhci_dbg(xhci, "Ignoring request to disable SuperSpeed port.\n");
59141135de1SFelipe Balbi return;
59241135de1SFelipe Balbi }
59341135de1SFelipe Balbi
59441135de1SFelipe Balbi if (xhci->quirks & XHCI_BROKEN_PORT_PED) {
59541135de1SFelipe Balbi xhci_dbg(xhci,
59641135de1SFelipe Balbi "Broken Port Enabled/Disabled, ignoring port disable request.\n");
5976219c047SSarah Sharp return;
598204b7793SXenia Ragiadakou }
599b0ba9720SXenia Ragiadakou
600d70d5a84SMathias Nyman portsc = readl(port->addr);
601d70d5a84SMathias Nyman portsc = xhci_port_state_to_neutral(portsc);
6026219c047SSarah Sharp
6036219c047SSarah Sharp /* Write 1 to disable the port */
60434fb562aSSarah Sharp writel(portsc | PORT_PE, port->addr);
60528ccd296SMatt Evans
60634fb562aSSarah Sharp portsc = readl(port->addr);
60734fb562aSSarah Sharp xhci_dbg(xhci, "disable port %d-%d, portsc: 0x%x\n",
60834fb562aSSarah Sharp hcd->self.busnum, port->hcd_portnum + 1, portsc);
60934fb562aSSarah Sharp }
61034fb562aSSarah Sharp
xhci_clear_port_change_bit(struct xhci_hcd * xhci,u16 wValue,u16 wIndex,__le32 __iomem * addr,u32 port_status)61134fb562aSSarah Sharp static void xhci_clear_port_change_bit(struct xhci_hcd *xhci, u16 wValue,
61234fb562aSSarah Sharp u16 wIndex, __le32 __iomem *addr, u32 port_status)
61334fb562aSSarah Sharp {
61434fb562aSSarah Sharp char *port_change_bit;
615a11496ebSAndiry Xu u32 status;
616a11496ebSAndiry Xu
617a11496ebSAndiry Xu switch (wValue) {
618a11496ebSAndiry Xu case USB_PORT_FEAT_C_RESET:
61934fb562aSSarah Sharp status = PORT_RC;
62034fb562aSSarah Sharp port_change_bit = "reset";
62134fb562aSSarah Sharp break;
62234fb562aSSarah Sharp case USB_PORT_FEAT_C_BH_PORT_RESET:
62334fb562aSSarah Sharp status = PORT_WRC;
62434fb562aSSarah Sharp port_change_bit = "warm(BH) reset";
62534fb562aSSarah Sharp break;
62634fb562aSSarah Sharp case USB_PORT_FEAT_C_CONNECTION:
6276219c047SSarah Sharp status = PORT_CSC;
6286219c047SSarah Sharp port_change_bit = "connect";
6296219c047SSarah Sharp break;
6306219c047SSarah Sharp case USB_PORT_FEAT_C_OVER_CURRENT:
631be88fe4fSAndiry Xu status = PORT_OCC;
632be88fe4fSAndiry Xu port_change_bit = "over-current";
633be88fe4fSAndiry Xu break;
634be88fe4fSAndiry Xu case USB_PORT_FEAT_C_ENABLE:
63585387c0eSAndiry Xu status = PORT_PEC;
63685387c0eSAndiry Xu port_change_bit = "enable/disable";
63785387c0eSAndiry Xu break;
63885387c0eSAndiry Xu case USB_PORT_FEAT_C_SUSPEND:
6399425183dSLu Baolu status = PORT_PLC;
6409425183dSLu Baolu port_change_bit = "suspend/resume";
6419425183dSLu Baolu break;
6429425183dSLu Baolu case USB_PORT_FEAT_C_PORT_LINK_STATE:
64334fb562aSSarah Sharp status = PORT_PLC;
64434fb562aSSarah Sharp port_change_bit = "link state";
64534fb562aSSarah Sharp break;
64634fb562aSSarah Sharp case USB_PORT_FEAT_C_PORT_CONFIG_ERROR:
64734fb562aSSarah Sharp status = PORT_CEC;
648204b7793SXenia Ragiadakou port_change_bit = "config error";
649b0ba9720SXenia Ragiadakou break;
650d70d5a84SMathias Nyman default:
651d70d5a84SMathias Nyman /* Should never happen */
652d70d5a84SMathias Nyman return;
65334fb562aSSarah Sharp }
65434fb562aSSarah Sharp /* Change bits are all write 1 to clear */
655ffd4b4fcSMathias Nyman writel(port_status | status, addr);
656ffd4b4fcSMathias Nyman port_status = readl(addr);
657ffd4b4fcSMathias Nyman
658ffd4b4fcSMathias Nyman xhci_dbg(xhci, "clear port%d %s change, portsc: 0x%x\n",
659ffd4b4fcSMathias Nyman wIndex + 1, port_change_bit, port_status);
660ffd4b4fcSMathias Nyman }
661ffd4b4fcSMathias Nyman
xhci_get_rhub(struct usb_hcd * hcd)662ffd4b4fcSMathias Nyman struct xhci_hub *xhci_get_rhub(struct usb_hcd *hcd)
663ffd4b4fcSMathias Nyman {
664a6ff6cbfSGuoqing Zhang struct xhci_hcd *xhci = hcd_to_xhci(hcd);
665a6ff6cbfSGuoqing Zhang
666a6ff6cbfSGuoqing Zhang if (hcd->speed >= HCD_USB3)
667a6ff6cbfSGuoqing Zhang return &xhci->usb3_rhub;
668a6ff6cbfSGuoqing Zhang return &xhci->usb2_rhub;
6698531aa16SMathias Nyman }
670ec1dafe8SMathias Nyman
671dce174e0SJules Irenge /*
672a6ff6cbfSGuoqing Zhang * xhci_set_port_power() must be called with xhci->lock held.
673e740b019SMathias Nyman * It will release and re-aquire the lock while calling ACPI
674e740b019SMathias Nyman * method.
675a6ff6cbfSGuoqing Zhang */
xhci_set_port_power(struct xhci_hcd * xhci,struct xhci_port * port,bool on,unsigned long * flags)676a6ff6cbfSGuoqing Zhang static void xhci_set_port_power(struct xhci_hcd *xhci, struct xhci_port *port,
677e740b019SMathias Nyman bool on, unsigned long *flags)
678e740b019SMathias Nyman __must_hold(&xhci->lock)
679e740b019SMathias Nyman {
680d70d5a84SMathias Nyman struct usb_hcd *hcd;
681d70d5a84SMathias Nyman u32 temp;
682d70d5a84SMathias Nyman
683d70d5a84SMathias Nyman hcd = port->rhub->hcd;
684a6ff6cbfSGuoqing Zhang temp = readl(port->addr);
685d70d5a84SMathias Nyman
686a6ff6cbfSGuoqing Zhang xhci_dbg(xhci, "set port power %d-%d %s, portsc: 0x%x\n",
687a6ff6cbfSGuoqing Zhang hcd->self.busnum, port->hcd_portnum + 1, on ? "ON" : "OFF", temp);
688e740b019SMathias Nyman
689d70d5a84SMathias Nyman temp = xhci_port_state_to_neutral(temp);
690a6ff6cbfSGuoqing Zhang
691a6ff6cbfSGuoqing Zhang if (on) {
692e740b019SMathias Nyman /* Power on */
693a6ff6cbfSGuoqing Zhang writel(temp | PORT_POWER, port->addr);
694a6ff6cbfSGuoqing Zhang readl(port->addr);
695ec1dafe8SMathias Nyman } else {
696a6ff6cbfSGuoqing Zhang /* Power off */
697a6ff6cbfSGuoqing Zhang writel(temp & ~PORT_POWER, port->addr);
698a6ff6cbfSGuoqing Zhang }
699a6ff6cbfSGuoqing Zhang
700a6ff6cbfSGuoqing Zhang spin_unlock_irqrestore(&xhci->lock, *flags);
701ec1dafe8SMathias Nyman temp = usb_acpi_power_manageable(hcd->self.root_hub,
702a6ff6cbfSGuoqing Zhang port->hcd_portnum);
703a6ff6cbfSGuoqing Zhang if (temp)
7040f1d832eSGuoqing Zhang usb_acpi_set_power_state(hcd->self.root_hub,
7050f1d832eSGuoqing Zhang port->hcd_portnum, on);
7060f1d832eSGuoqing Zhang spin_lock_irqsave(&xhci->lock, *flags);
7070f1d832eSGuoqing Zhang }
708e740b019SMathias Nyman
xhci_port_set_test_mode(struct xhci_hcd * xhci,u16 test_mode,u16 wIndex)7090f1d832eSGuoqing Zhang static void xhci_port_set_test_mode(struct xhci_hcd *xhci,
710e740b019SMathias Nyman u16 test_mode, u16 wIndex)
711e740b019SMathias Nyman {
712e740b019SMathias Nyman u32 temp;
7130f1d832eSGuoqing Zhang struct xhci_port *port;
714e740b019SMathias Nyman
7150f1d832eSGuoqing Zhang /* xhci only supports test mode for usb2 ports */
71662fb45d3SGreg Kroah-Hartman port = xhci->usb2_rhub.ports[wIndex];
7170f1d832eSGuoqing Zhang temp = readl(port->addr + PORTPMSC);
7180f1d832eSGuoqing Zhang temp |= test_mode << PORT_TEST_MODE_SHIFT;
7190f1d832eSGuoqing Zhang writel(temp, port->addr + PORTPMSC);
7200f1d832eSGuoqing Zhang xhci->test_mode = test_mode;
721ec1dafe8SMathias Nyman if (test_mode == USB_TEST_FORCE_ENABLE)
722055b185aSJules Irenge xhci_start(xhci);
7230f1d832eSGuoqing Zhang }
724873f3236SHeiner Kallweit
xhci_enter_test_mode(struct xhci_hcd * xhci,u16 test_mode,u16 wIndex,unsigned long * flags)7250f1d832eSGuoqing Zhang static int xhci_enter_test_mode(struct xhci_hcd *xhci,
7260f1d832eSGuoqing Zhang u16 test_mode, u16 wIndex, unsigned long *flags)
7270f1d832eSGuoqing Zhang __must_hold(&xhci->lock)
7280f1d832eSGuoqing Zhang {
729576d5546SPeter Chen int i, retval;
7300f1d832eSGuoqing Zhang
731b64149caSLu Baolu /* Disable all Device Slots */
732b64149caSLu Baolu xhci_dbg(xhci, "Disable all slots\n");
733b64149caSLu Baolu spin_unlock_irqrestore(&xhci->lock, *flags);
734cd3f1790SLu Baolu for (i = 1; i <= HCS_MAX_SLOTS(xhci->hcs_params1); i++) {
7357faac195SMathias Nyman if (!xhci->devs[i])
7360f1d832eSGuoqing Zhang continue;
7370f1d832eSGuoqing Zhang
7380f1d832eSGuoqing Zhang retval = xhci_disable_slot(xhci, i);
7390f1d832eSGuoqing Zhang xhci_free_virt_device(xhci, i);
740576d5546SPeter Chen if (retval)
7410f1d832eSGuoqing Zhang xhci_err(xhci, "Failed to disable slot %d, %d. Enter test mode anyway\n",
7420f1d832eSGuoqing Zhang i, retval);
7430f1d832eSGuoqing Zhang }
744e740b019SMathias Nyman spin_lock_irqsave(&xhci->lock, *flags);
745873f3236SHeiner Kallweit /* Put all ports to the Disable state by clear PP */
7460f1d832eSGuoqing Zhang xhci_dbg(xhci, "Disable all port (PP = 0)\n");
747e740b019SMathias Nyman /* Power off USB3 ports*/
748ec1dafe8SMathias Nyman for (i = 0; i < xhci->usb3_rhub.num_ports; i++)
7490f1d832eSGuoqing Zhang xhci_set_port_power(xhci, xhci->usb3_rhub.ports[i], false, flags);
7500f1d832eSGuoqing Zhang /* Power off USB2 ports*/
7510f1d832eSGuoqing Zhang for (i = 0; i < xhci->usb2_rhub.num_ports; i++)
7520f1d832eSGuoqing Zhang xhci_set_port_power(xhci, xhci->usb2_rhub.ports[i], false, flags);
7530f1d832eSGuoqing Zhang /* Stop the controller */
7540f1d832eSGuoqing Zhang xhci_dbg(xhci, "Stop controller\n");
7550f1d832eSGuoqing Zhang retval = xhci_halt(xhci);
7560f1d832eSGuoqing Zhang if (retval)
7570f1d832eSGuoqing Zhang return retval;
7580f1d832eSGuoqing Zhang /* Disable runtime PM for test mode */
7590f1d832eSGuoqing Zhang pm_runtime_forbid(xhci_to_hcd(xhci)->self.controller);
7600f1d832eSGuoqing Zhang /* Set PORTPMSC.PTC field to enter selected test mode */
7610f1d832eSGuoqing Zhang /* Port is selected by wIndex. port_id = wIndex + 1 */
7620f1d832eSGuoqing Zhang xhci_dbg(xhci, "Enter Test Mode: %d, Port_id=%d\n",
7630f1d832eSGuoqing Zhang test_mode, wIndex + 1);
7640f1d832eSGuoqing Zhang xhci_port_set_test_mode(xhci, test_mode, wIndex);
7650f1d832eSGuoqing Zhang return retval;
7660f1d832eSGuoqing Zhang }
7670f1d832eSGuoqing Zhang
xhci_exit_test_mode(struct xhci_hcd * xhci)7680f1d832eSGuoqing Zhang static int xhci_exit_test_mode(struct xhci_hcd *xhci)
7690f1d832eSGuoqing Zhang {
7700f1d832eSGuoqing Zhang int retval;
7710f1d832eSGuoqing Zhang
77262fb45d3SGreg Kroah-Hartman if (!xhci->test_mode) {
7730f1d832eSGuoqing Zhang xhci_err(xhci, "Not in test mode, do nothing.\n");
7740f1d832eSGuoqing Zhang return 0;
7750f1d832eSGuoqing Zhang }
7760f1d832eSGuoqing Zhang if (xhci->test_mode == USB_TEST_FORCE_ENABLE &&
7770f1d832eSGuoqing Zhang !(xhci->xhc_state & XHCI_STATE_HALTED)) {
7780f1d832eSGuoqing Zhang retval = xhci_halt(xhci);
7790f1d832eSGuoqing Zhang if (retval)
78014073ce9SMathias Nyman return retval;
7810f1d832eSGuoqing Zhang }
7820f1d832eSGuoqing Zhang pm_runtime_allow(xhci_to_hcd(xhci)->self.controller);
7836b7f40f7SMathias Nyman xhci->test_mode = 0;
7846b7f40f7SMathias Nyman return xhci_reset(xhci, XHCI_RESET_SHORT_USEC);
785c9682dffSAndiry Xu }
786c9682dffSAndiry Xu
xhci_set_link_state(struct xhci_hcd * xhci,struct xhci_port * port,u32 link_state)787d70d5a84SMathias Nyman void xhci_set_link_state(struct xhci_hcd *xhci, struct xhci_port *port,
788c9682dffSAndiry Xu u32 link_state)
789d70d5a84SMathias Nyman {
790d70d5a84SMathias Nyman u32 temp;
791c9682dffSAndiry Xu u32 portsc;
792c9682dffSAndiry Xu
7936b7f40f7SMathias Nyman portsc = readl(port->addr);
794d70d5a84SMathias Nyman temp = xhci_port_state_to_neutral(portsc);
795d70d5a84SMathias Nyman temp &= ~PORT_PLS_MASK;
796d70d5a84SMathias Nyman temp |= PORT_LINK_STROBE | link_state;
797d70d5a84SMathias Nyman writel(temp, port->addr);
798c9682dffSAndiry Xu
799c9682dffSAndiry Xu xhci_dbg(xhci, "Set port %d-%d link state, portsc: 0x%x, write 0x%x",
800ed384bd3SFelipe Balbi port->rhub->hcd->self.busnum, port->hcd_portnum + 1,
801fdcf74ffSMathias Nyman portsc, temp);
8024296c70aSSarah Sharp }
8034296c70aSSarah Sharp
xhci_set_remote_wake_mask(struct xhci_hcd * xhci,struct xhci_port * port,u16 wake_mask)8044296c70aSSarah Sharp static void xhci_set_remote_wake_mask(struct xhci_hcd *xhci,
805fdcf74ffSMathias Nyman struct xhci_port *port, u16 wake_mask)
8064296c70aSSarah Sharp {
8074296c70aSSarah Sharp u32 temp;
8084296c70aSSarah Sharp
8094296c70aSSarah Sharp temp = readl(port->addr);
8104296c70aSSarah Sharp temp = xhci_port_state_to_neutral(temp);
8114296c70aSSarah Sharp
8124296c70aSSarah Sharp if (wake_mask & USB_PORT_FEAT_REMOTE_WAKE_CONNECT)
8134296c70aSSarah Sharp temp |= PORT_WKCONN_E;
8144296c70aSSarah Sharp else
8154296c70aSSarah Sharp temp &= ~PORT_WKCONN_E;
8164296c70aSSarah Sharp
8174296c70aSSarah Sharp if (wake_mask & USB_PORT_FEAT_REMOTE_WAKE_DISCONNECT)
8184296c70aSSarah Sharp temp |= PORT_WKDISC_E;
8194296c70aSSarah Sharp else
8204296c70aSSarah Sharp temp &= ~PORT_WKDISC_E;
8214296c70aSSarah Sharp
8224296c70aSSarah Sharp if (wake_mask & USB_PORT_FEAT_REMOTE_WAKE_OVER_CURRENT)
823fdcf74ffSMathias Nyman temp |= PORT_WKOC_E;
8244296c70aSSarah Sharp else
8254296c70aSSarah Sharp temp &= ~PORT_WKOC_E;
826d2f52c9eSAndiry Xu
827eaefcf24SMathias Nyman writel(temp, port->addr);
828eaefcf24SMathias Nyman }
829d2f52c9eSAndiry Xu
830d2f52c9eSAndiry Xu /* Test and clear port RWC bit */
xhci_test_and_clear_bit(struct xhci_hcd * xhci,struct xhci_port * port,u32 port_bit)831d2f52c9eSAndiry Xu void xhci_test_and_clear_bit(struct xhci_hcd *xhci, struct xhci_port *port,
832eaefcf24SMathias Nyman u32 port_bit)
833d2f52c9eSAndiry Xu {
834d2f52c9eSAndiry Xu u32 temp;
835d2f52c9eSAndiry Xu
836eaefcf24SMathias Nyman temp = readl(port->addr);
837d2f52c9eSAndiry Xu if (temp & port_bit) {
838d2f52c9eSAndiry Xu temp = xhci_port_state_to_neutral(temp);
839d2f52c9eSAndiry Xu temp |= port_bit;
8408bea2bd3SStanislaw Ledwon writel(temp, port->addr);
84196908589SFelipe Balbi }
84296908589SFelipe Balbi }
8438bea2bd3SStanislaw Ledwon
8448bea2bd3SStanislaw Ledwon /* Updates Link Status for super Speed port */
xhci_hub_report_usb3_link_state(struct xhci_hcd * xhci,u32 * status,u32 status_reg)8458bea2bd3SStanislaw Ledwon static void xhci_hub_report_usb3_link_state(struct xhci_hcd *xhci,
8468bea2bd3SStanislaw Ledwon u32 *status, u32 status_reg)
8478bea2bd3SStanislaw Ledwon {
8488bea2bd3SStanislaw Ledwon u32 pls = status_reg & PORT_PLS_MASK;
8498bea2bd3SStanislaw Ledwon
8508bea2bd3SStanislaw Ledwon /* When the CAS bit is set then warm reset
8518bea2bd3SStanislaw Ledwon * should be performed on port
8528bea2bd3SStanislaw Ledwon */
8538bea2bd3SStanislaw Ledwon if (status_reg & PORT_CAS) {
8548bea2bd3SStanislaw Ledwon /* The CAS bit can be set while the port is
8558bea2bd3SStanislaw Ledwon * in any link state.
8568bea2bd3SStanislaw Ledwon * Only roothubs have CAS bit, so we
8578bea2bd3SStanislaw Ledwon * pretend to be in compliance mode
8588bea2bd3SStanislaw Ledwon * unless we're already in compliance
8598bea2bd3SStanislaw Ledwon * or the inactive state.
8608bea2bd3SStanislaw Ledwon */
8618bea2bd3SStanislaw Ledwon if (pls != USB_SS_PORT_LS_COMP_MOD &&
8628bea2bd3SStanislaw Ledwon pls != USB_SS_PORT_LS_SS_INACTIVE) {
8638bea2bd3SStanislaw Ledwon pls = USB_SS_PORT_LS_COMP_MOD;
8648bea2bd3SStanislaw Ledwon }
8658bea2bd3SStanislaw Ledwon /* Return also connection bit -
86671c731a2SAlexis R. Cortes * hub state machine resets port
86771c731a2SAlexis R. Cortes * when this bit is set.
868904df64aSKai-Heng Feng */
869904df64aSKai-Heng Feng pls |= USB_PORT_STAT_CONNECTION;
870904df64aSKai-Heng Feng } else {
871904df64aSKai-Heng Feng /*
872904df64aSKai-Heng Feng * Resume state is an xHCI internal state. Do not report it to
873904df64aSKai-Heng Feng * usb core, instead, pretend to be U3, thus usb core knows
874904df64aSKai-Heng Feng * it's not ready for transfer.
875904df64aSKai-Heng Feng */
876904df64aSKai-Heng Feng if (pls == XDEV_RESUME) {
877904df64aSKai-Heng Feng *status |= USB_SS_PORT_LS_U3;
87871c731a2SAlexis R. Cortes return;
87971c731a2SAlexis R. Cortes }
88071c731a2SAlexis R. Cortes
88171c731a2SAlexis R. Cortes /*
88271c731a2SAlexis R. Cortes * If CAS bit isn't set but the Port is already at
88371c731a2SAlexis R. Cortes * Compliance Mode, fake a connection so the USB core
88471c731a2SAlexis R. Cortes * notices the Compliance state and resets the port.
88596908589SFelipe Balbi * This resolves an issue generated by the SN65LVPE502CP
88696908589SFelipe Balbi * in which sometimes the port enters compliance mode
88771c731a2SAlexis R. Cortes * caused by a delay on the host-device negotiation.
8888bea2bd3SStanislaw Ledwon */
88971c731a2SAlexis R. Cortes if ((xhci->quirks & XHCI_COMP_MODE_QUIRK) &&
8908bea2bd3SStanislaw Ledwon (pls == USB_SS_PORT_LS_COMP_MOD))
8918bea2bd3SStanislaw Ledwon pls |= USB_PORT_STAT_CONNECTION;
8928bea2bd3SStanislaw Ledwon }
8938bea2bd3SStanislaw Ledwon
89471c731a2SAlexis R. Cortes /* update status field */
89571c731a2SAlexis R. Cortes *status |= pls;
89671c731a2SAlexis R. Cortes }
89771c731a2SAlexis R. Cortes
89871c731a2SAlexis R. Cortes /*
89971c731a2SAlexis R. Cortes * Function for Compliance Mode Quirk.
90071c731a2SAlexis R. Cortes *
9015f20cf12SSachin Kamat * This Function verifies if all xhc USB3 ports have entered U0, if so,
9025f20cf12SSachin Kamat * the compliance mode timer is deleted. A port won't enter
90371c731a2SAlexis R. Cortes * compliance mode if it has previously entered U0.
904e740b019SMathias Nyman */
xhci_del_comp_mod_timer(struct xhci_hcd * xhci,u32 status,u16 wIndex)90571c731a2SAlexis R. Cortes static void xhci_del_comp_mod_timer(struct xhci_hcd *xhci, u32 status,
90671c731a2SAlexis R. Cortes u16 wIndex)
90771c731a2SAlexis R. Cortes {
90871c731a2SAlexis R. Cortes u32 all_ports_seen_u0 = ((1 << xhci->usb3_rhub.num_ports) - 1);
90971c731a2SAlexis R. Cortes bool port_in_u0 = ((status & PORT_PLS_MASK) == XDEV_U0);
91071c731a2SAlexis R. Cortes
91171c731a2SAlexis R. Cortes if (!(xhci->quirks & XHCI_COMP_MODE_QUIRK))
91271c731a2SAlexis R. Cortes return;
91371c731a2SAlexis R. Cortes
9144bdfe4c3SXenia Ragiadakou if ((xhci->port_status_u0 != all_ports_seen_u0) && port_in_u0) {
9154bdfe4c3SXenia Ragiadakou xhci->port_status_u0 |= 1 << wIndex;
9164bdfe4c3SXenia Ragiadakou if (xhci->port_status_u0 == all_ports_seen_u0) {
9174bdfe4c3SXenia Ragiadakou del_timer_sync(&xhci->comp_mode_recovery_timer);
91871c731a2SAlexis R. Cortes xhci_dbg_trace(xhci, trace_xhci_dbg_quirks,
91971c731a2SAlexis R. Cortes "All USB3 ports have entered U0 already!");
92071c731a2SAlexis R. Cortes xhci_dbg_trace(xhci, trace_xhci_dbg_quirks,
92171c731a2SAlexis R. Cortes "Compliance Mode Recovery Timer Deleted.");
922e67ebf1bSMathias Nyman }
923e67ebf1bSMathias Nyman }
924bd82873fSMathias Nyman }
925e67ebf1bSMathias Nyman
xhci_handle_usb2_port_link_resume(struct xhci_port * port,u32 portsc,unsigned long * flags)926e67ebf1bSMathias Nyman static int xhci_handle_usb2_port_link_resume(struct xhci_port *port,
927e67ebf1bSMathias Nyman u32 portsc,
928e67ebf1bSMathias Nyman unsigned long *flags)
929e67ebf1bSMathias Nyman {
930e67ebf1bSMathias Nyman struct xhci_bus_state *bus_state;
931e67ebf1bSMathias Nyman struct xhci_hcd *xhci;
932e67ebf1bSMathias Nyman struct usb_hcd *hcd;
933e67ebf1bSMathias Nyman int slot_id;
934e67ebf1bSMathias Nyman u32 wIndex;
935e67ebf1bSMathias Nyman
936e67ebf1bSMathias Nyman hcd = port->rhub->hcd;
937e67ebf1bSMathias Nyman bus_state = &port->rhub->bus_state;
938e67ebf1bSMathias Nyman xhci = hcd_to_xhci(hcd);
939e67ebf1bSMathias Nyman wIndex = port->hcd_portnum;
940e67ebf1bSMathias Nyman
941e67ebf1bSMathias Nyman if ((portsc & PORT_RESET) || !(portsc & PORT_PE)) {
942e67ebf1bSMathias Nyman return -EINVAL;
943e67ebf1bSMathias Nyman }
944e67ebf1bSMathias Nyman /* did port event handler already start resume timing? */
945e67ebf1bSMathias Nyman if (!port->resume_timestamp) {
946e67ebf1bSMathias Nyman /* If not, maybe we are in a host initated resume? */
947e67ebf1bSMathias Nyman if (test_bit(wIndex, &bus_state->resuming_ports)) {
948e67ebf1bSMathias Nyman /* Host initated resume doesn't time the resume
949e67ebf1bSMathias Nyman * signalling using resume_done[].
950e67ebf1bSMathias Nyman * It manually sets RESUME state, sleeps 20ms
951e67ebf1bSMathias Nyman * and sets U0 state. This should probably be
952e67ebf1bSMathias Nyman * changed, but not right now.
953e67ebf1bSMathias Nyman */
954e67ebf1bSMathias Nyman } else {
955e67ebf1bSMathias Nyman /* port resume was discovered now and here,
956e67ebf1bSMathias Nyman * start resume timing
957e67ebf1bSMathias Nyman */
958e67ebf1bSMathias Nyman unsigned long timeout = jiffies +
959e67ebf1bSMathias Nyman msecs_to_jiffies(USB_RESUME_TIMEOUT);
960e67ebf1bSMathias Nyman
961e67ebf1bSMathias Nyman set_bit(wIndex, &bus_state->resuming_ports);
962e67ebf1bSMathias Nyman port->resume_timestamp = timeout;
963e67ebf1bSMathias Nyman mod_timer(&hcd->rh_timer, timeout);
964e67ebf1bSMathias Nyman usb_hcd_start_port_resume(&hcd->self, wIndex);
965e67ebf1bSMathias Nyman }
966e67ebf1bSMathias Nyman /* Has resume been signalled for USB_RESUME_TIME yet? */
967d70d5a84SMathias Nyman } else if (time_after_eq(jiffies, port->resume_timestamp)) {
968d70d5a84SMathias Nyman int time_left;
969d70d5a84SMathias Nyman
970e67ebf1bSMathias Nyman xhci_dbg(xhci, "resume USB2 port %d-%d\n",
971e67ebf1bSMathias Nyman hcd->self.busnum, wIndex + 1);
972e67ebf1bSMathias Nyman
973e67ebf1bSMathias Nyman port->resume_timestamp = 0;
974e67ebf1bSMathias Nyman clear_bit(wIndex, &bus_state->resuming_ports);
975e67ebf1bSMathias Nyman
976e67ebf1bSMathias Nyman reinit_completion(&port->rexit_done);
977e67ebf1bSMathias Nyman port->rexit_active = true;
978bd82873fSMathias Nyman
979e67ebf1bSMathias Nyman xhci_test_and_clear_bit(xhci, port, PORT_PLC);
980e67ebf1bSMathias Nyman xhci_set_link_state(xhci, port, XDEV_U0);
981e67ebf1bSMathias Nyman
982bd82873fSMathias Nyman spin_unlock_irqrestore(&xhci->lock, *flags);
983e67ebf1bSMathias Nyman time_left = wait_for_completion_timeout(
984e67ebf1bSMathias Nyman &port->rexit_done,
985e67ebf1bSMathias Nyman msecs_to_jiffies(XHCI_MAX_REXIT_TIMEOUT_MS));
986e67ebf1bSMathias Nyman spin_lock_irqsave(&xhci->lock, *flags);
987e67ebf1bSMathias Nyman
988e67ebf1bSMathias Nyman if (time_left) {
989e67ebf1bSMathias Nyman slot_id = xhci_find_slot_id_by_port(hcd, xhci,
990e67ebf1bSMathias Nyman wIndex + 1);
991e67ebf1bSMathias Nyman if (!slot_id) {
992e67ebf1bSMathias Nyman xhci_dbg(xhci, "slot_id is zero\n");
993e67ebf1bSMathias Nyman return -ENODEV;
994e67ebf1bSMathias Nyman }
995e67ebf1bSMathias Nyman xhci_ring_device(xhci, slot_id);
996d70d5a84SMathias Nyman } else {
997d70d5a84SMathias Nyman int port_status = readl(port->addr);
998e67ebf1bSMathias Nyman
999e67ebf1bSMathias Nyman xhci_warn(xhci, "Port resume timed out, port %d-%d: 0x%x\n",
1000e67ebf1bSMathias Nyman hcd->self.busnum, wIndex + 1, port_status);
1001e67ebf1bSMathias Nyman /*
1002e67ebf1bSMathias Nyman * keep rexit_active set if U0 transition failed so we
1003e67ebf1bSMathias Nyman * know to report PORT_STAT_SUSPEND status back to
1004e67ebf1bSMathias Nyman * usbcore. It will be cleared later once the port is
1005e67ebf1bSMathias Nyman * out of RESUME/U3 state
1006e67ebf1bSMathias Nyman */
1007e67ebf1bSMathias Nyman }
1008e67ebf1bSMathias Nyman
1009e67ebf1bSMathias Nyman usb_hcd_end_port_resume(&hcd->self, wIndex);
1010e67ebf1bSMathias Nyman bus_state->port_c_suspend |= 1 << wIndex;
1011e67ebf1bSMathias Nyman bus_state->suspended_ports &= ~(1 << wIndex);
1012e67ebf1bSMathias Nyman }
1013e67ebf1bSMathias Nyman
1014e67ebf1bSMathias Nyman return 0;
1015e67ebf1bSMathias Nyman }
1016e67ebf1bSMathias Nyman
xhci_get_ext_port_status(u32 raw_port_status,u32 port_li)1017395f5409SMathias Nyman static u32 xhci_get_ext_port_status(u32 raw_port_status, u32 port_li)
1018395f5409SMathias Nyman {
1019395f5409SMathias Nyman u32 ext_stat = 0;
1020395f5409SMathias Nyman int speed_id;
1021395f5409SMathias Nyman
1022395f5409SMathias Nyman /* only support rx and tx lane counts of 1 in usb3.1 spec */
1023395f5409SMathias Nyman speed_id = DEV_PORT_SPEED(raw_port_status);
1024395f5409SMathias Nyman ext_stat |= speed_id; /* bits 3:0, RX speed id */
1025395f5409SMathias Nyman ext_stat |= speed_id << 4; /* bits 7:4, TX speed id */
1026395f5409SMathias Nyman
1027395f5409SMathias Nyman ext_stat |= PORT_RX_LANES(port_li) << 8; /* bits 11:8 Rx lane count */
1028395f5409SMathias Nyman ext_stat |= PORT_TX_LANES(port_li) << 12; /* bits 15:12 Tx lane count */
1029395f5409SMathias Nyman
1030395f5409SMathias Nyman return ext_stat;
1031395f5409SMathias Nyman }
1032395f5409SMathias Nyman
xhci_get_usb3_port_status(struct xhci_port * port,u32 * status,u32 portsc)10335f78a54fSMathias Nyman static void xhci_get_usb3_port_status(struct xhci_port *port, u32 *status,
10345f78a54fSMathias Nyman u32 portsc)
10355f78a54fSMathias Nyman {
1036a231ec41SMathias Nyman struct xhci_bus_state *bus_state;
10375f78a54fSMathias Nyman struct xhci_hcd *xhci;
1038057d476fSMathias Nyman struct usb_hcd *hcd;
10395f78a54fSMathias Nyman u32 link_state;
10405f78a54fSMathias Nyman u32 portnum;
10415f78a54fSMathias Nyman
1042a231ec41SMathias Nyman bus_state = &port->rhub->bus_state;
10435f78a54fSMathias Nyman xhci = hcd_to_xhci(port->rhub->hcd);
1044057d476fSMathias Nyman hcd = port->rhub->hcd;
10455f78a54fSMathias Nyman link_state = portsc & PORT_PLS_MASK;
10465f78a54fSMathias Nyman portnum = port->hcd_portnum;
10475f78a54fSMathias Nyman
10485f78a54fSMathias Nyman /* USB3 specific wPortChange bits
10495f78a54fSMathias Nyman *
10505f78a54fSMathias Nyman * Port link change with port in resume state should not be
10515f78a54fSMathias Nyman * reported to usbcore, as this is an internal state to be
10525f78a54fSMathias Nyman * handled by xhci driver. Reporting PLC to usbcore may
10535f78a54fSMathias Nyman * cause usbcore clearing PLC first and port change event
10545f78a54fSMathias Nyman * irq won't be generated.
10555f78a54fSMathias Nyman */
10565f78a54fSMathias Nyman
10575f78a54fSMathias Nyman if (portsc & PORT_PLC && (link_state != XDEV_RESUME))
10585f78a54fSMathias Nyman *status |= USB_PORT_STAT_C_LINK_STATE << 16;
10595f78a54fSMathias Nyman if (portsc & PORT_WRC)
10605f78a54fSMathias Nyman *status |= USB_PORT_STAT_C_BH_RESET << 16;
10615f78a54fSMathias Nyman if (portsc & PORT_CEC)
10625f78a54fSMathias Nyman *status |= USB_PORT_STAT_C_CONFIG_ERROR << 16;
10635f78a54fSMathias Nyman
10645f78a54fSMathias Nyman /* USB3 specific wPortStatus bits */
1065a231ec41SMathias Nyman if (portsc & PORT_POWER)
10665f78a54fSMathias Nyman *status |= USB_SS_PORT_STAT_POWER;
1067a231ec41SMathias Nyman
1068a231ec41SMathias Nyman /* no longer suspended or resuming */
1069a231ec41SMathias Nyman if (link_state != XDEV_U3 &&
1070a231ec41SMathias Nyman link_state != XDEV_RESUME &&
10715f78a54fSMathias Nyman link_state != XDEV_RECOVERY) {
1072057d476fSMathias Nyman /* remote wake resume signaling complete */
1073057d476fSMathias Nyman if (bus_state->port_remote_wakeup & (1 << portnum)) {
1074057d476fSMathias Nyman bus_state->port_remote_wakeup &= ~(1 << portnum);
1075057d476fSMathias Nyman usb_hcd_end_port_resume(&hcd->self, portnum);
1076057d476fSMathias Nyman }
1077057d476fSMathias Nyman bus_state->suspended_ports &= ~(1 << portnum);
1078057d476fSMathias Nyman }
1079057d476fSMathias Nyman
10805f78a54fSMathias Nyman xhci_hub_report_usb3_link_state(xhci, status, portsc);
10815f78a54fSMathias Nyman xhci_del_comp_mod_timer(xhci, portsc, portnum);
10825f78a54fSMathias Nyman }
10835f78a54fSMathias Nyman
xhci_get_usb2_port_status(struct xhci_port * port,u32 * status,u32 portsc,unsigned long * flags)108470e9b53dSMathias Nyman static void xhci_get_usb2_port_status(struct xhci_port *port, u32 *status,
1085bd82873fSMathias Nyman u32 portsc, unsigned long *flags)
108670e9b53dSMathias Nyman {
1087a231ec41SMathias Nyman struct xhci_bus_state *bus_state;
108870e9b53dSMathias Nyman u32 link_state;
1089a231ec41SMathias Nyman u32 portnum;
1090e67ebf1bSMathias Nyman int err;
109170e9b53dSMathias Nyman
1092a231ec41SMathias Nyman bus_state = &port->rhub->bus_state;
109370e9b53dSMathias Nyman link_state = portsc & PORT_PLS_MASK;
1094a231ec41SMathias Nyman portnum = port->hcd_portnum;
109570e9b53dSMathias Nyman
109670e9b53dSMathias Nyman /* USB2 wPortStatus bits */
109770e9b53dSMathias Nyman if (portsc & PORT_POWER) {
109870e9b53dSMathias Nyman *status |= USB_PORT_STAT_POWER;
109970e9b53dSMathias Nyman
110070e9b53dSMathias Nyman /* link state is only valid if port is powered */
110170e9b53dSMathias Nyman if (link_state == XDEV_U3)
110270e9b53dSMathias Nyman *status |= USB_PORT_STAT_SUSPEND;
110370e9b53dSMathias Nyman if (link_state == XDEV_U2)
110470e9b53dSMathias Nyman *status |= USB_PORT_STAT_L1;
1105a231ec41SMathias Nyman if (link_state == XDEV_U0) {
110670c05e4cSHenry Lin if (bus_state->suspended_ports & (1 << portnum)) {
110770c05e4cSHenry Lin bus_state->suspended_ports &= ~(1 << portnum);
110870c05e4cSHenry Lin bus_state->port_c_suspend |= 1 << portnum;
1109a231ec41SMathias Nyman }
1110a231ec41SMathias Nyman }
1111a231ec41SMathias Nyman if (link_state == XDEV_RESUME) {
1112a231ec41SMathias Nyman err = xhci_handle_usb2_port_link_resume(port, portsc,
1113a231ec41SMathias Nyman flags);
1114a231ec41SMathias Nyman if (err < 0)
1115a231ec41SMathias Nyman *status = 0xffffffff;
1116e67ebf1bSMathias Nyman else if (port->resume_timestamp || port->rexit_active)
1117e67ebf1bSMathias Nyman *status |= USB_PORT_STAT_SUSPEND;
1118e67ebf1bSMathias Nyman }
1119e67ebf1bSMathias Nyman }
1120e67ebf1bSMathias Nyman
1121e67ebf1bSMathias Nyman /*
112270e9b53dSMathias Nyman * Clear usb2 resume signalling variables if port is no longer suspended
112370e9b53dSMathias Nyman * or resuming. Port either resumed to U0/U1/U2, disconnected, or in a
112470e9b53dSMathias Nyman * error state. Resume related variables should be cleared in all those cases.
1125eae5b176SSarah Sharp */
1126eae5b176SSarah Sharp if (link_state != XDEV_U3 && link_state != XDEV_RESUME) {
1127eae5b176SSarah Sharp if (port->resume_timestamp ||
1128eae5b176SSarah Sharp test_bit(portnum, &bus_state->resuming_ports)) {
1129eae5b176SSarah Sharp port->resume_timestamp = 0;
1130eae5b176SSarah Sharp clear_bit(portnum, &bus_state->resuming_ports);
1131eae5b176SSarah Sharp usb_hcd_end_port_resume(&port->rhub->hcd->self, portnum);
1132eae5b176SSarah Sharp }
11338b3d4570SSarah Sharp port->rexit_active = 0;
1134eae5b176SSarah Sharp bus_state->suspended_ports &= ~(1 << portnum);
1135eae5b176SSarah Sharp }
1136eae5b176SSarah Sharp }
11378b3d4570SSarah Sharp
1138bd82873fSMathias Nyman /*
11398b3d4570SSarah Sharp * Converts a raw xHCI port status into the format that external USB 2.0 or USB
11408b3d4570SSarah Sharp * 3.0 hubs use.
1141eae5b176SSarah Sharp *
1142eae5b176SSarah Sharp * Possible side effects:
1143e740b019SMathias Nyman * - Mark a port as being done with device resume,
1144e740b019SMathias Nyman * and ring the endpoint doorbells.
1145e740b019SMathias Nyman * - Stop the Synopsys redriver Compliance Mode polling.
1146e740b019SMathias Nyman * - Drop and reacquire the xHCI lock, in order to wait for port resume.
1147e740b019SMathias Nyman */
xhci_get_port_status(struct usb_hcd * hcd,struct xhci_bus_state * bus_state,u16 wIndex,u32 raw_port_status,unsigned long * flags)1148eae5b176SSarah Sharp static u32 xhci_get_port_status(struct usb_hcd *hcd,
11493c2ddb44SMathias Nyman struct xhci_bus_state *bus_state,
1150eae5b176SSarah Sharp u16 wIndex, u32 raw_port_status,
1151eae5b176SSarah Sharp unsigned long *flags)
1152eae5b176SSarah Sharp __releases(&xhci->lock)
1153eae5b176SSarah Sharp __acquires(&xhci->lock)
1154eae5b176SSarah Sharp {
1155eae5b176SSarah Sharp u32 status = 0;
1156eae5b176SSarah Sharp struct xhci_hub *rhub;
1157eae5b176SSarah Sharp struct xhci_port *port;
115870e9b53dSMathias Nyman
11593c2ddb44SMathias Nyman rhub = xhci_get_rhub(hcd);
11603c2ddb44SMathias Nyman port = rhub->ports[wIndex];
11613c2ddb44SMathias Nyman
11623c2ddb44SMathias Nyman /* common wPortChange bits */
11633c2ddb44SMathias Nyman if (raw_port_status & PORT_CSC)
11643c2ddb44SMathias Nyman status |= USB_PORT_STAT_C_CONNECTION << 16;
11653c2ddb44SMathias Nyman if (raw_port_status & PORT_PEC)
11663c2ddb44SMathias Nyman status |= USB_PORT_STAT_C_ENABLE << 16;
11673c2ddb44SMathias Nyman if ((raw_port_status & PORT_OCC))
11683c2ddb44SMathias Nyman status |= USB_PORT_STAT_C_OVERCURRENT << 16;
11693c2ddb44SMathias Nyman if ((raw_port_status & PORT_RC))
11703c2ddb44SMathias Nyman status |= USB_PORT_STAT_C_RESET << 16;
11713c2ddb44SMathias Nyman
11725f78a54fSMathias Nyman /* common wPortStatus bits */
11735f78a54fSMathias Nyman if (raw_port_status & PORT_CONNECT) {
117470e9b53dSMathias Nyman status |= USB_PORT_STAT_CONNECTION;
1175e67ebf1bSMathias Nyman status |= xhci_port_speed(raw_port_status);
1176e67ebf1bSMathias Nyman }
1177f69115fdSMathias Nyman if (raw_port_status & PORT_PE)
1178f69115fdSMathias Nyman status |= USB_PORT_STAT_ENABLE;
1179f69115fdSMathias Nyman if (raw_port_status & PORT_OC)
1180f69115fdSMathias Nyman status |= USB_PORT_STAT_OVERCURRENT;
1181f69115fdSMathias Nyman if (raw_port_status & PORT_RESET)
1182f69115fdSMathias Nyman status |= USB_PORT_STAT_RESET;
1183f69115fdSMathias Nyman
1184f69115fdSMathias Nyman /* USB2 and USB3 specific bits, including Port Link State */
1185f69115fdSMathias Nyman if (hcd->speed >= HCD_USB3)
1186f69115fdSMathias Nyman xhci_get_usb3_port_status(port, &status, raw_port_status);
1187330e2d61SAnshuman Gupta else
1188f69115fdSMathias Nyman xhci_get_usb2_port_status(port, &status, raw_port_status,
1189f69115fdSMathias Nyman flags);
1190eae5b176SSarah Sharp
11915e6389fdSMathias Nyman if (bus_state->port_c_suspend & (1 << wIndex))
1192eae5b176SSarah Sharp status |= USB_PORT_STAT_C_SUSPEND << 16;
1193eae5b176SSarah Sharp
1194eae5b176SSarah Sharp return status;
1195eae5b176SSarah Sharp }
11960f2a7930SSarah Sharp
xhci_hub_control(struct usb_hcd * hcd,u16 typeReq,u16 wValue,u16 wIndex,char * buf,u16 wLength)11970f2a7930SSarah Sharp int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
11980f2a7930SSarah Sharp u16 wIndex, char *buf, u16 wLength)
11990f2a7930SSarah Sharp {
1200a0885924Shuajun li struct xhci_hcd *xhci = hcd_to_xhci(hcd);
12010f2a7930SSarah Sharp int max_ports;
1202c9682dffSAndiry Xu unsigned long flags;
12030f2a7930SSarah Sharp u32 temp, status;
1204be88fe4fSAndiry Xu int retval = 0;
120520b67cf5SSarah Sharp int slot_id;
12062c441780SAndiry Xu struct xhci_bus_state *bus_state;
12074296c70aSSarah Sharp u16 link_state = 0;
1208797b0ca5SSarah Sharp u16 wake_mask = 0;
12090f1d832eSGuoqing Zhang u16 timeout = 0;
1210e740b019SMathias Nyman u16 test_mode = 0;
1211e740b019SMathias Nyman struct xhci_hub *rhub;
12120f2a7930SSarah Sharp struct xhci_port **ports;
1213e740b019SMathias Nyman struct xhci_port *port;
1214e740b019SMathias Nyman int portnum1;
1215925f349dSMathias Nyman
1216f6187f42SMathias Nyman rhub = xhci_get_rhub(hcd);
12170f2a7930SSarah Sharp ports = rhub->ports;
12180f2a7930SSarah Sharp max_ports = rhub->num_ports;
12190f2a7930SSarah Sharp bus_state = &rhub->bus_state;
12200f2a7930SSarah Sharp portnum1 = wIndex & 0xff;
12210f2a7930SSarah Sharp
12220f2a7930SSarah Sharp spin_lock_irqsave(&xhci->lock, flags);
12230f2a7930SSarah Sharp switch (typeReq) {
12240f2a7930SSarah Sharp case GetHubStatus:
12254bbb0aceSSarah Sharp /* No power source, over-current reported per port */
12264bbb0aceSSarah Sharp memset(buf, 0, 4);
12274bbb0aceSSarah Sharp break;
12284bbb0aceSSarah Sharp case GetHubDescriptor:
1229b50107bbSMathias Nyman /* Check to make sure userspace is asking for the USB 3.0 hub
12304bbb0aceSSarah Sharp * descriptor for the USB 3.0 roothub. If not, we stall the
12314bbb0aceSSarah Sharp * endpoint, like external hubs do.
12324bbb0aceSSarah Sharp */
12334bbb0aceSSarah Sharp if (hcd->speed >= HCD_USB3 &&
12344bbb0aceSSarah Sharp (wLength < USB_DT_SS_HUB_SIZE ||
12354bbb0aceSSarah Sharp wValue != (USB_DT_SS_HUB << 8))) {
1236f6ff0ac8SSarah Sharp xhci_dbg(xhci, "Wrong hub descriptor type for "
1237f6ff0ac8SSarah Sharp "USB 3.0 roothub.\n");
12380f2a7930SSarah Sharp goto error;
123948e82361SSarah Sharp }
124048e82361SSarah Sharp xhci_hub_descriptor(hcd, xhci,
124148e82361SSarah Sharp (struct usb_hub_descriptor *) buf);
124248e82361SSarah Sharp break;
12435693e0b7SMathias Nyman case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
124448e82361SSarah Sharp if ((wValue & 0xff00) != (USB_DT_BOS << 8))
124548e82361SSarah Sharp goto error;
1246eb02aaf2SThinh Nguyen
124748e82361SSarah Sharp if (hcd->speed < HCD_USB3)
12485693e0b7SMathias Nyman goto error;
12490f2a7930SSarah Sharp
1250a0885924Shuajun li retval = xhci_create_usb3x_bos_desc(xhci, buf, wLength);
12510f2a7930SSarah Sharp spin_unlock_irqrestore(&xhci->lock, flags);
12520f2a7930SSarah Sharp return retval;
1253e740b019SMathias Nyman case GetPortStatus:
1254d9f11ba9SMathias Nyman if (!portnum1 || portnum1 > max_ports)
1255d9f11ba9SMathias Nyman goto error;
1256f9de8151SSarah Sharp
1257f9de8151SSarah Sharp wIndex--;
1258f9de8151SSarah Sharp port = ports[portnum1 - 1];
125928c06e58SMathias Nyman temp = readl(port->addr);
1260eaefcf24SMathias Nyman if (temp == ~(u32)0) {
1261bd82873fSMathias Nyman xhci_hc_died(xhci);
1262eae5b176SSarah Sharp retval = -ENODEV;
126356192531SAndiry Xu break;
1264eae5b176SSarah Sharp }
1265d70d5a84SMathias Nyman trace_xhci_get_port_status(wIndex, temp);
1266d70d5a84SMathias Nyman status = xhci_get_port_status(hcd, bus_state, wIndex, temp,
1267eae5b176SSarah Sharp &flags);
12680f2a7930SSarah Sharp if (status == 0xffffffff)
1269395f5409SMathias Nyman goto error;
1270395f5409SMathias Nyman
1271395f5409SMathias Nyman xhci_dbg(xhci, "Get port status %d-%d read: 0x%x, return 0x%x",
1272395f5409SMathias Nyman hcd->self.busnum, portnum1, temp, status);
1273395f5409SMathias Nyman
1274395f5409SMathias Nyman put_unaligned(cpu_to_le32(status), (__le32 *) buf);
1275395f5409SMathias Nyman /* if USB 3.1 extended port status return additional 4 bytes */
1276395f5409SMathias Nyman if (wValue == 0x02) {
1277395f5409SMathias Nyman u32 port_li;
1278e740b019SMathias Nyman
1279395f5409SMathias Nyman if (hcd->speed < HCD_USB31 || wLength != 8) {
12806269e4c7SRuslan Bilovol xhci_err(xhci, "get ext port status invalid parameter\n");
1281395f5409SMathias Nyman retval = -EINVAL;
12820f2a7930SSarah Sharp break;
12830f2a7930SSarah Sharp }
12842c441780SAndiry Xu port_li = readl(port->addr + PORTLI);
12852c441780SAndiry Xu status = xhci_get_ext_port_status(temp, port_li);
12864296c70aSSarah Sharp put_unaligned_le32(status, &buf[4]);
12874296c70aSSarah Sharp }
12880f1d832eSGuoqing Zhang break;
12890f1d832eSGuoqing Zhang case SetPortFeature:
1290797b0ca5SSarah Sharp if (wValue == USB_PORT_FEAT_LINK_STATE)
1291797b0ca5SSarah Sharp link_state = (wIndex & 0xff00) >> 3;
12920f2a7930SSarah Sharp if (wValue == USB_PORT_FEAT_REMOTE_WAKE_MASK)
1293a0885924Shuajun li wake_mask = wIndex & 0xff00;
12940f2a7930SSarah Sharp if (wValue == USB_PORT_FEAT_TEST)
12950f2a7930SSarah Sharp test_mode = (wIndex & 0xff00) >> 8;
1296e740b019SMathias Nyman /* The MSB of wIndex is the U1/U2 timeout */
1297d9f11ba9SMathias Nyman timeout = (wIndex & 0xff00) >> 8;
1298d9f11ba9SMathias Nyman
1299f9de8151SSarah Sharp wIndex &= 0xff;
1300f9de8151SSarah Sharp if (!portnum1 || portnum1 > max_ports)
1301f9de8151SSarah Sharp goto error;
13020f2a7930SSarah Sharp
13034bbb0aceSSarah Sharp port = ports[portnum1 - 1];
13040f2a7930SSarah Sharp wIndex--;
1305be88fe4fSAndiry Xu temp = readl(port->addr);
1306e740b019SMathias Nyman if (temp == ~(u32)0) {
130765580b43SAndiry Xu xhci_hc_died(xhci);
130865580b43SAndiry Xu retval = -ENODEV;
13096b7f40f7SMathias Nyman break;
131065580b43SAndiry Xu }
131165580b43SAndiry Xu temp = xhci_port_state_to_neutral(temp);
131265580b43SAndiry Xu /* FIXME: What new port features do we need to support? */
131365580b43SAndiry Xu switch (wValue) {
131465580b43SAndiry Xu case USB_PORT_FEAT_SUSPEND:
1315be88fe4fSAndiry Xu temp = readl(port->addr);
1316be88fe4fSAndiry Xu if ((temp & PORT_PLS_MASK) != XDEV_U0) {
1317be88fe4fSAndiry Xu /* Resume the port to U0 first */
1318be88fe4fSAndiry Xu xhci_set_link_state(xhci, port, XDEV_U0);
1319e740b019SMathias Nyman spin_unlock_irqrestore(&xhci->lock, flags);
1320be88fe4fSAndiry Xu msleep(10);
1321be88fe4fSAndiry Xu spin_lock_irqsave(&xhci->lock, flags);
1322d70d5a84SMathias Nyman }
1323d70d5a84SMathias Nyman /* In spec software should not attempt to suspend
1324be88fe4fSAndiry Xu * a port unless the port reports that it is in the
1325be88fe4fSAndiry Xu * enabled (PED = ‘1’,PLS < ‘3’) state.
1326be88fe4fSAndiry Xu */
13275233630fSSarah Sharp temp = readl(port->addr);
13285233630fSSarah Sharp if ((temp & PORT_PE) == 0 || (temp & PORT_RESET)
1329be88fe4fSAndiry Xu || (temp & PORT_PLS_MASK) >= XDEV_U3) {
1330be88fe4fSAndiry Xu xhci_warn(xhci, "USB core suspending port %d-%d not in U0/U1/U2\n",
1331be88fe4fSAndiry Xu hcd->self.busnum, portnum1);
1332be88fe4fSAndiry Xu goto error;
1333be88fe4fSAndiry Xu }
1334be88fe4fSAndiry Xu
1335be88fe4fSAndiry Xu slot_id = xhci_find_slot_id_by_port(hcd, xhci,
1336be88fe4fSAndiry Xu portnum1);
1337be88fe4fSAndiry Xu if (!slot_id) {
13386b7f40f7SMathias Nyman xhci_warn(xhci, "slot_id is zero\n");
1339be88fe4fSAndiry Xu goto error;
1340be88fe4fSAndiry Xu }
1341be88fe4fSAndiry Xu /* unlock to execute stop endpoint commands */
1342be88fe4fSAndiry Xu spin_unlock_irqrestore(&xhci->lock, flags);
1343be88fe4fSAndiry Xu xhci_stop_device(xhci, slot_id, 1);
1344e740b019SMathias Nyman spin_lock_irqsave(&xhci->lock, flags);
134520b67cf5SSarah Sharp
1346be88fe4fSAndiry Xu xhci_set_link_state(xhci, port, XDEV_U3);
13472c441780SAndiry Xu
1348e740b019SMathias Nyman spin_unlock_irqrestore(&xhci->lock, flags);
134941e7e056SSarah Sharp msleep(10); /* wait device to enter */
135041e7e056SSarah Sharp spin_lock_irqsave(&xhci->lock, flags);
13518aaf19b8SKai-Heng Feng
13528aaf19b8SKai-Heng Feng temp = readl(port->addr);
135341e7e056SSarah Sharp bus_state->suspended_ports |= 1 << wIndex;
135441e7e056SSarah Sharp break;
135541e7e056SSarah Sharp case USB_PORT_FEAT_LINK_STATE:
135641e7e056SSarah Sharp temp = readl(port->addr);
135741e7e056SSarah Sharp /* Disable port */
135841e7e056SSarah Sharp if (link_state == USB_SS_PORT_LS_SS_DISABLED) {
135941e7e056SSarah Sharp xhci_dbg(xhci, "Disable port %d-%d\n",
136041e7e056SSarah Sharp hcd->self.busnum, portnum1);
1361e740b019SMathias Nyman temp = xhci_port_state_to_neutral(temp);
1362e740b019SMathias Nyman /*
136341e7e056SSarah Sharp * Clear all change bits, so that we get a new
136441e7e056SSarah Sharp * connection event.
136541e7e056SSarah Sharp */
136641e7e056SSarah Sharp temp |= PORT_CSC | PORT_PEC | PORT_WRC |
136741e7e056SSarah Sharp PORT_OCC | PORT_RC | PORT_PLC |
13688aaf19b8SKai-Heng Feng PORT_CEC;
13698aaf19b8SKai-Heng Feng writel(temp | PORT_PE, port->addr);
13706b7f40f7SMathias Nyman temp = readl(port->addr);
137141e7e056SSarah Sharp break;
1372e740b019SMathias Nyman }
137341e7e056SSarah Sharp
137441e7e056SSarah Sharp /* Put link in RxDetect (enable port) */
137541e7e056SSarah Sharp if (link_state == USB_SS_PORT_LS_RX_DETECT) {
13764b562bd2SJack Pham xhci_dbg(xhci, "Enable port %d-%d\n",
13774b562bd2SJack Pham hcd->self.busnum, portnum1);
13784b562bd2SJack Pham xhci_set_link_state(xhci, port, link_state);
13794b562bd2SJack Pham temp = readl(port->addr);
13804b562bd2SJack Pham break;
13814b562bd2SJack Pham }
13824b562bd2SJack Pham
13834b562bd2SJack Pham /*
13844b562bd2SJack Pham * For xHCI 1.1 according to section 4.19.1.2.4.1 a
13854b562bd2SJack Pham * root hub port's transition to compliance mode upon
13864b562bd2SJack Pham * detecting LFPS timeout may be controlled by an
13874b562bd2SJack Pham * Compliance Transition Enabled (CTE) flag (not
13884b562bd2SJack Pham * software visible). This flag is set by writing 0xA
13894b562bd2SJack Pham * to PORTSC PLS field which will allow transition to
13904b562bd2SJack Pham * compliance mode the next time LFPS timeout is
13914b562bd2SJack Pham * encountered. A warm reset will clear it.
13924b562bd2SJack Pham *
13934b562bd2SJack Pham * The CTE flag is only supported if the HCCPARAMS2 CTC
13944b562bd2SJack Pham * flag is set, otherwise, the compliance substate is
13954b562bd2SJack Pham * automatically entered as on 1.0 and prior.
13964b562bd2SJack Pham */
13974b562bd2SJack Pham if (link_state == USB_SS_PORT_LS_COMP_MOD) {
13984b562bd2SJack Pham if (!HCC2_CTC(xhci->hcc_params2)) {
13994b562bd2SJack Pham xhci_dbg(xhci, "CTC flag is 0, port already supports entering compliance mode\n");
14004b562bd2SJack Pham break;
14018aaf19b8SKai-Heng Feng }
14028aaf19b8SKai-Heng Feng
14036b7f40f7SMathias Nyman if ((temp & PORT_CONNECT)) {
14044b562bd2SJack Pham xhci_warn(xhci, "Can't set compliance mode when port is connected\n");
14056b7f40f7SMathias Nyman goto error;
1406e740b019SMathias Nyman }
14074b562bd2SJack Pham
14084b562bd2SJack Pham xhci_dbg(xhci, "Enable compliance mode transition for port %d-%d\n",
14091208d8a8SMathias Nyman hcd->self.busnum, portnum1);
14101208d8a8SMathias Nyman xhci_set_link_state(xhci, port, link_state);
14111208d8a8SMathias Nyman
14121208d8a8SMathias Nyman temp = readl(port->addr);
14131208d8a8SMathias Nyman break;
14141208d8a8SMathias Nyman }
14151208d8a8SMathias Nyman /* Port must be enabled */
14168aaf19b8SKai-Heng Feng if (!(temp & PORT_PE)) {
14178aaf19b8SKai-Heng Feng retval = -ENODEV;
14188aaf19b8SKai-Heng Feng break;
14192c441780SAndiry Xu }
14202c441780SAndiry Xu /* Can't set port link state above '3' (U3) */
14210200b9f7SKai-Heng Feng if (link_state > USB_SS_PORT_LS_U3) {
1422ceca4938SMathias Nyman xhci_warn(xhci, "Cannot set port %d-%d link state %d\n",
1423ceca4938SMathias Nyman hcd->self.busnum, portnum1, link_state);
1424ceca4938SMathias Nyman goto error;
1425ceca4938SMathias Nyman }
1426ceca4938SMathias Nyman
1427ceca4938SMathias Nyman /*
1428ceca4938SMathias Nyman * set link to U0, steps depend on current link state.
14290200b9f7SKai-Heng Feng * U3: set link to U0 and wait for u3exit completion.
1430ceca4938SMathias Nyman * U1/U2: no PLC complete event, only set link to U0.
1431ceca4938SMathias Nyman * Resume/Recovery: device initiated U0, only wait for
14320200b9f7SKai-Heng Feng * completion
1433ceca4938SMathias Nyman */
1434ceca4938SMathias Nyman if (link_state == USB_SS_PORT_LS_U0) {
1435ceca4938SMathias Nyman u32 pls = temp & PORT_PLS_MASK;
1436ceca4938SMathias Nyman bool wait_u0 = false;
1437ceca4938SMathias Nyman
1438ceca4938SMathias Nyman /* already in U0 */
1439ceca4938SMathias Nyman if (pls == XDEV_U0)
14400200b9f7SKai-Heng Feng break;
1441ceca4938SMathias Nyman if (pls == XDEV_U3 ||
1442ceca4938SMathias Nyman pls == XDEV_RESUME ||
14430200b9f7SKai-Heng Feng pls == XDEV_RECOVERY) {
14440200b9f7SKai-Heng Feng wait_u0 = true;
1445ceca4938SMathias Nyman reinit_completion(&port->u3exit_done);
1446ceca4938SMathias Nyman }
1447ceca4938SMathias Nyman if (pls <= XDEV_U3) /* U1, U2, U3 */
1448ceca4938SMathias Nyman xhci_set_link_state(xhci, port, USB_SS_PORT_LS_U0);
1449ceca4938SMathias Nyman if (!wait_u0) {
14500200b9f7SKai-Heng Feng if (pls > XDEV_U3)
14510200b9f7SKai-Heng Feng goto error;
145233597f0cSMathias Nyman break;
14538aaf19b8SKai-Heng Feng }
14548aaf19b8SKai-Heng Feng spin_unlock_irqrestore(&xhci->lock, flags);
14550200b9f7SKai-Heng Feng if (!wait_for_completion_timeout(&port->u3exit_done,
14560200b9f7SKai-Heng Feng msecs_to_jiffies(500)))
14570200b9f7SKai-Heng Feng xhci_dbg(xhci, "missing U0 port change event for port %d-%d\n",
14580200b9f7SKai-Heng Feng hcd->self.busnum, portnum1);
14590200b9f7SKai-Heng Feng spin_lock_irqsave(&xhci->lock, flags);
14602c441780SAndiry Xu temp = readl(port->addr);
14610200b9f7SKai-Heng Feng break;
14622c441780SAndiry Xu }
14632c441780SAndiry Xu
14642c441780SAndiry Xu if (link_state == USB_SS_PORT_LS_U3) {
14652c441780SAndiry Xu int retries = 16;
14662c441780SAndiry Xu slot_id = xhci_find_slot_id_by_port(hcd, xhci,
14672c441780SAndiry Xu portnum1);
14682c441780SAndiry Xu if (slot_id) {
14692c441780SAndiry Xu /* unlock to execute stop endpoint
14702c441780SAndiry Xu * commands */
14712c441780SAndiry Xu spin_unlock_irqrestore(&xhci->lock,
14720200b9f7SKai-Heng Feng flags);
14732c441780SAndiry Xu xhci_stop_device(xhci, slot_id, 1);
1474eb002726SKai-Heng Feng spin_lock_irqsave(&xhci->lock, flags);
1475eb002726SKai-Heng Feng }
1476eb002726SKai-Heng Feng xhci_set_link_state(xhci, port, USB_SS_PORT_LS_U3);
1477eb002726SKai-Heng Feng spin_unlock_irqrestore(&xhci->lock, flags);
1478eb002726SKai-Heng Feng while (retries--) {
1479eb002726SKai-Heng Feng usleep_range(4000, 8000);
14802c441780SAndiry Xu temp = readl(port->addr);
1481e740b019SMathias Nyman if ((temp & PORT_PLS_MASK) == XDEV_U3)
14822c441780SAndiry Xu break;
14830200b9f7SKai-Heng Feng }
14842c441780SAndiry Xu spin_lock_irqsave(&xhci->lock, flags);
14850f2a7930SSarah Sharp temp = readl(port->addr);
14860f2a7930SSarah Sharp bus_state->suspended_ports |= 1 << wIndex;
14870f2a7930SSarah Sharp }
14880f2a7930SSarah Sharp break;
148937ebb549SPetr Mladek case USB_PORT_FEAT_POWER:
14900f2a7930SSarah Sharp /*
14910f2a7930SSarah Sharp * Turn on ports, even if there isn't per-port switching.
1492ec1dafe8SMathias Nyman * HC will report connect events even before this is set.
14930f2a7930SSarah Sharp * However, hub_wq will ignore the roothub events until
14940f2a7930SSarah Sharp * the roothub is registered.
14950f2a7930SSarah Sharp */
1496e740b019SMathias Nyman xhci_set_port_power(xhci, port, true, &flags);
14970f2a7930SSarah Sharp break;
1498e740b019SMathias Nyman case USB_PORT_FEAT_RESET:
14998aaf19b8SKai-Heng Feng temp = (temp | PORT_RESET);
15008aaf19b8SKai-Heng Feng writel(temp, port->addr);
15010f2a7930SSarah Sharp
15024296c70aSSarah Sharp temp = readl(port->addr);
1503fdcf74ffSMathias Nyman xhci_dbg(xhci, "set port reset, actual port %d-%d status = 0x%x\n",
1504fdcf74ffSMathias Nyman hcd->self.busnum, portnum1, temp);
1505e740b019SMathias Nyman break;
15068aaf19b8SKai-Heng Feng case USB_PORT_FEAT_REMOTE_WAKE_MASK:
15078aaf19b8SKai-Heng Feng xhci_set_remote_wake_mask(xhci, port, wake_mask);
15084296c70aSSarah Sharp temp = readl(port->addr);
1509a11496ebSAndiry Xu xhci_dbg(xhci, "set port remote wake mask, actual port %d-%d status = 0x%x\n",
1510a11496ebSAndiry Xu hcd->self.busnum, portnum1, temp);
1511e740b019SMathias Nyman break;
1512e740b019SMathias Nyman case USB_PORT_FEAT_BH_PORT_RESET:
1513a11496ebSAndiry Xu temp |= PORT_WR;
1514797b0ca5SSarah Sharp writel(temp, port->addr);
1515b50107bbSMathias Nyman temp = readl(port->addr);
1516797b0ca5SSarah Sharp break;
1517e740b019SMathias Nyman case USB_PORT_FEAT_U1_TIMEOUT:
1518797b0ca5SSarah Sharp if (hcd->speed < HCD_USB3)
1519797b0ca5SSarah Sharp goto error;
1520e740b019SMathias Nyman temp = readl(port->addr + PORTPMSC);
1521797b0ca5SSarah Sharp temp &= ~PORT_U1_TIMEOUT_MASK;
1522797b0ca5SSarah Sharp temp |= PORT_U1_TIMEOUT(timeout);
1523b50107bbSMathias Nyman writel(temp, port->addr + PORTPMSC);
1524797b0ca5SSarah Sharp break;
1525e740b019SMathias Nyman case USB_PORT_FEAT_U2_TIMEOUT:
1526797b0ca5SSarah Sharp if (hcd->speed < HCD_USB3)
1527797b0ca5SSarah Sharp goto error;
1528e740b019SMathias Nyman temp = readl(port->addr + PORTPMSC);
1529797b0ca5SSarah Sharp temp &= ~PORT_U2_TIMEOUT_MASK;
15300f1d832eSGuoqing Zhang temp |= PORT_U2_TIMEOUT(timeout);
15310f1d832eSGuoqing Zhang writel(temp, port->addr + PORTPMSC);
15320f1d832eSGuoqing Zhang break;
15330f1d832eSGuoqing Zhang case USB_PORT_FEAT_TEST:
153462fb45d3SGreg Kroah-Hartman /* 4.19.6 Port Test Modes (USB2 Test Mode) */
153562fb45d3SGreg Kroah-Hartman if (hcd->speed != HCD_USB2)
15360f1d832eSGuoqing Zhang goto error;
1537ec1dafe8SMathias Nyman if (test_mode > USB_TEST_FORCE_ENABLE ||
1538ec1dafe8SMathias Nyman test_mode < USB_TEST_J)
15390f1d832eSGuoqing Zhang goto error;
15400f2a7930SSarah Sharp retval = xhci_enter_test_mode(xhci, test_mode, wIndex,
15410f2a7930SSarah Sharp &flags);
15420f2a7930SSarah Sharp break;
15435308a91bSSarah Sharp default:
1544e740b019SMathias Nyman goto error;
15450f2a7930SSarah Sharp }
15460f2a7930SSarah Sharp /* unblock any posted writes */
1547a0885924Shuajun li temp = readl(port->addr);
15480f2a7930SSarah Sharp break;
15490f2a7930SSarah Sharp case ClearPortFeature:
1550e740b019SMathias Nyman if (!portnum1 || portnum1 > max_ports)
1551d9f11ba9SMathias Nyman goto error;
1552d9f11ba9SMathias Nyman
1553f9de8151SSarah Sharp port = ports[portnum1 - 1];
1554f9de8151SSarah Sharp
1555f9de8151SSarah Sharp wIndex--;
15564bbb0aceSSarah Sharp temp = readl(port->addr);
15570f2a7930SSarah Sharp if (temp == ~(u32)0) {
15580f2a7930SSarah Sharp xhci_hc_died(xhci);
1559be88fe4fSAndiry Xu retval = -ENODEV;
1560e740b019SMathias Nyman break;
1561be88fe4fSAndiry Xu }
1562be88fe4fSAndiry Xu /* FIXME: What new port features do we need to support? */
1563be88fe4fSAndiry Xu temp = xhci_port_state_to_neutral(temp);
1564be88fe4fSAndiry Xu switch (wValue) {
15655ac04bf1SAndiry Xu case USB_PORT_FEAT_SUSPEND:
1566be88fe4fSAndiry Xu temp = readl(port->addr);
1567be88fe4fSAndiry Xu xhci_dbg(xhci, "clear USB_PORT_FEAT_SUSPEND\n");
1568a7114230SAndiry Xu xhci_dbg(xhci, "PORTSC %04x\n", temp);
1569f69115fdSMathias Nyman if (temp & PORT_RESET)
1570330e2d61SAnshuman Gupta goto error;
15716b7f40f7SMathias Nyman if ((temp & PORT_PLS_MASK) == XDEV_U3) {
1572c9682dffSAndiry Xu if ((temp & PORT_PE) == 0)
1573c9682dffSAndiry Xu goto error;
15747d3b016aSMathias Nyman
1575be88fe4fSAndiry Xu set_bit(wIndex, &bus_state->resuming_ports);
15766b7f40f7SMathias Nyman usb_hcd_start_port_resume(&hcd->self, wIndex);
1577c9682dffSAndiry Xu xhci_set_link_state(xhci, port, XDEV_RESUME);
1578f69115fdSMathias Nyman spin_unlock_irqrestore(&xhci->lock, flags);
1579330e2d61SAnshuman Gupta msleep(USB_RESUME_TIMEOUT);
1580be88fe4fSAndiry Xu spin_lock_irqsave(&xhci->lock, flags);
158120b67cf5SSarah Sharp xhci_set_link_state(xhci, port, XDEV_U0);
1582be88fe4fSAndiry Xu clear_bit(wIndex, &bus_state->resuming_ports);
15835233630fSSarah Sharp usb_hcd_end_port_resume(&hcd->self, wIndex);
15845233630fSSarah Sharp }
1585be88fe4fSAndiry Xu bus_state->port_c_suspend |= 1 << wIndex;
1586be88fe4fSAndiry Xu
1587be88fe4fSAndiry Xu slot_id = xhci_find_slot_id_by_port(hcd, xhci,
1588be88fe4fSAndiry Xu portnum1);
1589be88fe4fSAndiry Xu if (!slot_id) {
1590be88fe4fSAndiry Xu xhci_dbg(xhci, "slot_id is zero\n");
1591be88fe4fSAndiry Xu goto error;
159220b67cf5SSarah Sharp }
1593df561f66SGustavo A. R. Silva xhci_ring_device(xhci, slot_id);
15940f2a7930SSarah Sharp break;
1595a11496ebSAndiry Xu case USB_PORT_FEAT_C_SUSPEND:
15960f2a7930SSarah Sharp bus_state->port_c_suspend &= ~(1 << wIndex);
15970f2a7930SSarah Sharp fallthrough;
15986219c047SSarah Sharp case USB_PORT_FEAT_C_RESET:
159985387c0eSAndiry Xu case USB_PORT_FEAT_C_BH_PORT_RESET:
16009425183dSLu Baolu case USB_PORT_FEAT_C_CONNECTION:
160134fb562aSSarah Sharp case USB_PORT_FEAT_C_OVER_CURRENT:
1602e740b019SMathias Nyman case USB_PORT_FEAT_C_ENABLE:
16030f2a7930SSarah Sharp case USB_PORT_FEAT_C_PORT_LINK_STATE:
16046219c047SSarah Sharp case USB_PORT_FEAT_C_PORT_CONFIG_ERROR:
1605f6ff0ac8SSarah Sharp xhci_clear_port_change_bit(xhci, wValue, wIndex,
1606e740b019SMathias Nyman port->addr, temp);
16076219c047SSarah Sharp break;
1608693d8eb8SLan Tianyu case USB_PORT_FEAT_ENABLE:
1609ec1dafe8SMathias Nyman xhci_disable_port(xhci, port);
1610693d8eb8SLan Tianyu break;
16110f1d832eSGuoqing Zhang case USB_PORT_FEAT_POWER:
16120f1d832eSGuoqing Zhang xhci_set_port_power(xhci, port, false, &flags);
16130f1d832eSGuoqing Zhang break;
16140f2a7930SSarah Sharp case USB_PORT_FEAT_TEST:
16150f2a7930SSarah Sharp retval = xhci_exit_test_mode(xhci);
16160f2a7930SSarah Sharp break;
16170f2a7930SSarah Sharp default:
16180f2a7930SSarah Sharp goto error;
16190f2a7930SSarah Sharp }
16200f2a7930SSarah Sharp break;
16210f2a7930SSarah Sharp default:
16220f2a7930SSarah Sharp error:
16230f2a7930SSarah Sharp /* "stall" on error */
16240f2a7930SSarah Sharp retval = -EPIPE;
16250f2a7930SSarah Sharp }
16260f2a7930SSarah Sharp spin_unlock_irqrestore(&xhci->lock, flags);
16270f2a7930SSarah Sharp return retval;
16280f2a7930SSarah Sharp }
16290f2a7930SSarah Sharp EXPORT_SYMBOL_GPL(xhci_hub_control);
16300f2a7930SSarah Sharp
16310f2a7930SSarah Sharp /*
16320f2a7930SSarah Sharp * Returns 0 if the status hasn't changed, or the number of bytes in buf.
16330f2a7930SSarah Sharp * Ports are 0-indexed from the HCD point of view,
16340f2a7930SSarah Sharp * and 1-indexed from the USB core pointer of view.
16350f2a7930SSarah Sharp *
16360f2a7930SSarah Sharp * Note that the status change bits will be cleared as soon as a port status
16370f2a7930SSarah Sharp * change event is generated, so we use the saved status from that event.
16380f2a7930SSarah Sharp */
xhci_hub_status_data(struct usb_hcd * hcd,char * buf)163956192531SAndiry Xu int xhci_hub_status_data(struct usb_hcd *hcd, char *buf)
16400f2a7930SSarah Sharp {
16410f2a7930SSarah Sharp unsigned long flags;
1642a0885924Shuajun li u32 temp, status;
164320b67cf5SSarah Sharp u32 mask;
1644c52804a4SSarah Sharp int i, retval;
1645e740b019SMathias Nyman struct xhci_hcd *xhci = hcd_to_xhci(hcd);
1646e740b019SMathias Nyman int max_ports;
16470f2a7930SSarah Sharp struct xhci_bus_state *bus_state;
1648e740b019SMathias Nyman bool reset_change = false;
1649e740b019SMathias Nyman struct xhci_hub *rhub;
1650925f349dSMathias Nyman struct xhci_port **ports;
1651f6187f42SMathias Nyman
16520f2a7930SSarah Sharp rhub = xhci_get_rhub(hcd);
16530f2a7930SSarah Sharp ports = rhub->ports;
1654a0885924Shuajun li max_ports = rhub->num_ports;
1655419a8e81SWilliam Gulland bus_state = &rhub->bus_state;
1656f370b996SAndiry Xu
1657f370b996SAndiry Xu /* Initial status is no changes */
1658f370b996SAndiry Xu retval = (max_ports + 8) / 8;
1659f370b996SAndiry Xu memset(buf, 0, retval);
1660f370b996SAndiry Xu
166172f68bf5SMathias Nyman /*
166272f68bf5SMathias Nyman * Inform the usbcore about resume-in-progress by returning
1663f370b996SAndiry Xu * a non-zero value even if there are no status changes.
16640f2a7930SSarah Sharp */
166533e32158SMathias Nyman spin_lock_irqsave(&xhci->lock, flags);
166633e32158SMathias Nyman
166733e32158SMathias Nyman status = bus_state->resuming_ports;
166833e32158SMathias Nyman
166933e32158SMathias Nyman /*
167033e32158SMathias Nyman * SS devices are only visible to roothub after link training completes.
167133e32158SMathias Nyman * Keep polling roothubs for a grace period after xHC start
167233e32158SMathias Nyman */
167333e32158SMathias Nyman if (xhci->run_graceperiod) {
167433e32158SMathias Nyman if (time_before(jiffies, xhci->run_graceperiod))
167533e32158SMathias Nyman status = 1;
16769425183dSLu Baolu else
167756192531SAndiry Xu xhci->run_graceperiod = 0;
16780f2a7930SSarah Sharp }
1679a0885924Shuajun li
1680e740b019SMathias Nyman mask = PORT_CSC | PORT_PEC | PORT_OCC | PORT_PLC | PORT_WRC | PORT_CEC;
1681d9f11ba9SMathias Nyman
1682d9f11ba9SMathias Nyman /* For each port, did anything change? If so, set that bit in buf. */
1683f9de8151SSarah Sharp for (i = 0; i < max_ports; i++) {
1684f9de8151SSarah Sharp temp = readl(ports[i]->addr);
1685f9de8151SSarah Sharp if (temp == ~(u32)0) {
16863f8499acSMathias Nyman xhci_hc_died(xhci);
16873f8499acSMathias Nyman retval = -ENODEV;
168856192531SAndiry Xu break;
168920b67cf5SSarah Sharp }
169020b67cf5SSarah Sharp trace_xhci_hub_status_data(i, temp);
169120b67cf5SSarah Sharp
1692419a8e81SWilliam Gulland if ((temp & mask) != 0 ||
16930f2a7930SSarah Sharp (bus_state->port_c_suspend & 1 << i) ||
16940f2a7930SSarah Sharp (ports[i]->resume_timestamp && time_after_eq(
1695c52804a4SSarah Sharp jiffies, ports[i]->resume_timestamp))) {
1696c52804a4SSarah Sharp buf[(i + 1) / 8] |= 1 << (i + 1) % 8;
1697e9fb08d6SMathias Nyman status = 1;
1698e9fb08d6SMathias Nyman }
1699c52804a4SSarah Sharp if ((temp & PORT_RC))
1700c52804a4SSarah Sharp reset_change = true;
1701669bc5a1SMathias Nyman if (temp & PORT_OC)
1702669bc5a1SMathias Nyman status = 1;
1703c52804a4SSarah Sharp }
17040f2a7930SSarah Sharp if (!status && !reset_change) {
17050f2a7930SSarah Sharp xhci_dbg(xhci, "%s: stopping usb%d port polling\n",
17060f2a7930SSarah Sharp __func__, hcd->self.busnum);
17070f2a7930SSarah Sharp clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
17089777e3ceSAndiry Xu }
17099777e3ceSAndiry Xu spin_unlock_irqrestore(&xhci->lock, flags);
17109777e3ceSAndiry Xu return status ? retval : 0;
17119777e3ceSAndiry Xu }
17129777e3ceSAndiry Xu
17139777e3ceSAndiry Xu #ifdef CONFIG_PM
1714518e848eSSarah Sharp
xhci_bus_suspend(struct usb_hcd * hcd)171520b67cf5SSarah Sharp int xhci_bus_suspend(struct usb_hcd *hcd)
17169777e3ceSAndiry Xu {
1717e740b019SMathias Nyman struct xhci_hcd *xhci = hcd_to_xhci(hcd);
1718e740b019SMathias Nyman int max_ports, port_index;
17192f31a67fSMathias Nyman struct xhci_bus_state *bus_state;
17202f31a67fSMathias Nyman unsigned long flags;
17219777e3ceSAndiry Xu struct xhci_hub *rhub;
1722e740b019SMathias Nyman struct xhci_port **ports;
1723e740b019SMathias Nyman u32 portsc_buf[USB_MAXCHILDREN];
1724925f349dSMathias Nyman bool wake_enabled;
1725f6187f42SMathias Nyman
17262f31a67fSMathias Nyman rhub = xhci_get_rhub(hcd);
17279777e3ceSAndiry Xu ports = rhub->ports;
17289777e3ceSAndiry Xu max_ports = rhub->num_ports;
17299777e3ceSAndiry Xu bus_state = &rhub->bus_state;
17302f31a67fSMathias Nyman wake_enabled = hcd->self.root_hub->do_remote_wakeup;
1731fac4271dSZhuang Jin Can
1732fac4271dSZhuang Jin Can spin_lock_irqsave(&xhci->lock, flags);
17339777e3ceSAndiry Xu
1734669bc5a1SMathias Nyman if (wake_enabled) {
1735669bc5a1SMathias Nyman if (bus_state->resuming_ports || /* USB2 */
17369777e3ceSAndiry Xu bus_state->port_remote_wakeup) { /* USB3 */
17379777e3ceSAndiry Xu spin_unlock_irqrestore(&xhci->lock, flags);
17389777e3ceSAndiry Xu xhci_dbg(xhci, "usb%d bus suspend to fail because a port is resuming\n",
17392f31a67fSMathias Nyman hcd->self.busnum);
17402f31a67fSMathias Nyman return -EBUSY;
17412f31a67fSMathias Nyman }
17422f31a67fSMathias Nyman }
174320b67cf5SSarah Sharp /*
17442f31a67fSMathias Nyman * Prepare ports for suspend, but don't write anything before all ports
1745518e848eSSarah Sharp * are checked and we know bus suspend can proceed
17469777e3ceSAndiry Xu */
1747d92f2c59SMathias Nyman bus_state->bus_suspended = 0;
1748d92f2c59SMathias Nyman port_index = max_ports;
1749e740b019SMathias Nyman while (port_index--) {
17509777e3ceSAndiry Xu u32 t1, t2;
17512f31a67fSMathias Nyman int retries = 10;
17529777e3ceSAndiry Xu retry:
1753d92f2c59SMathias Nyman t1 = readl(ports[port_index]->addr);
1754d92f2c59SMathias Nyman t2 = xhci_port_state_to_neutral(t1);
1755d92f2c59SMathias Nyman portsc_buf[port_index] = 0;
1756d92f2c59SMathias Nyman
1757d92f2c59SMathias Nyman /*
175845f750c1SMathias Nyman * Give a USB3 port in link training time to finish, but don't
17599777e3ceSAndiry Xu * prevent suspend as port might be stuck
1760d92f2c59SMathias Nyman */
1761d92f2c59SMathias Nyman if ((hcd->speed >= HCD_USB3) && retries-- &&
17628aaf19b8SKai-Heng Feng (t1 & PORT_PLS_MASK) == XDEV_POLLING) {
17638aaf19b8SKai-Heng Feng spin_unlock_irqrestore(&xhci->lock, flags);
1764d92f2c59SMathias Nyman msleep(XHCI_PORT_POLLING_LFPS_TIME);
17659777e3ceSAndiry Xu spin_lock_irqsave(&xhci->lock, flags);
1766e9fb08d6SMathias Nyman xhci_dbg(xhci, "port %d-%d polling in bus suspend, waiting\n",
1767e9fb08d6SMathias Nyman hcd->self.busnum, port_index + 1);
1768e9fb08d6SMathias Nyman goto retry;
1769e9fb08d6SMathias Nyman }
1770e9fb08d6SMathias Nyman /* bail out if port detected a over-current condition */
1771e9fb08d6SMathias Nyman if (t1 & PORT_OC) {
1772e9fb08d6SMathias Nyman bus_state->bus_suspended = 0;
17732f31a67fSMathias Nyman spin_unlock_irqrestore(&xhci->lock, flags);
17742f31a67fSMathias Nyman xhci_dbg(xhci, "Bus suspend bailout, port over-current detected\n");
17752f31a67fSMathias Nyman return -EBUSY;
17762f31a67fSMathias Nyman }
17772f31a67fSMathias Nyman /* suspend ports in U0, or bail out for new connect changes */
17782f31a67fSMathias Nyman if ((t1 & PORT_PE) && (t1 & PORT_PLS_MASK) == XDEV_U0) {
17792f31a67fSMathias Nyman if ((t1 & PORT_CSC) && wake_enabled) {
17802f31a67fSMathias Nyman bus_state->bus_suspended = 0;
17818aaf19b8SKai-Heng Feng spin_unlock_irqrestore(&xhci->lock, flags);
17828aaf19b8SKai-Heng Feng xhci_dbg(xhci, "Bus suspend bailout, port connect change\n");
17839777e3ceSAndiry Xu return -EBUSY;
17849777e3ceSAndiry Xu }
178520b67cf5SSarah Sharp xhci_dbg(xhci, "port %d-%d not suspended\n",
17869777e3ceSAndiry Xu hcd->self.busnum, port_index + 1);
17874296c70aSSarah Sharp t2 &= ~PORT_PLS_MASK;
1788ceb6c9c8SRafael J. Wysocki t2 |= PORT_LINK_STROBE | XDEV_U3;
17894296c70aSSarah Sharp set_bit(port_index, &bus_state->bus_suspended);
17904296c70aSSarah Sharp }
17912f31a67fSMathias Nyman /* USB core sets remote wake mask for USB 3.0 hubs,
17929777e3ceSAndiry Xu * including the USB 3.0 roothub, but only if CONFIG_PM
17939777e3ceSAndiry Xu * is enabled, so also enable remote wake here.
17949777e3ceSAndiry Xu */
17959777e3ceSAndiry Xu if (wake_enabled) {
17969777e3ceSAndiry Xu if (t1 & PORT_CONNECT) {
17979777e3ceSAndiry Xu t2 |= PORT_WKOC_E | PORT_WKDISC_E;
17989777e3ceSAndiry Xu t2 &= ~PORT_WKCONN_E;
1799bde0716dSJoe Lee } else {
1800bde0716dSJoe Lee t2 |= PORT_WKOC_E | PORT_WKCONN_E;
1801bde0716dSJoe Lee t2 &= ~PORT_WKDISC_E;
1802bde0716dSJoe Lee }
1803bde0716dSJoe Lee
1804bde0716dSJoe Lee if ((xhci->quirks & XHCI_U2_DISABLE_WAKE) &&
1805bde0716dSJoe Lee (hcd->speed < HCD_USB3)) {
18069777e3ceSAndiry Xu if (usb_amd_pt_check_port(hcd->self.controller,
18079777e3ceSAndiry Xu port_index))
18089777e3ceSAndiry Xu t2 &= ~PORT_WAKE_BITS;
18099777e3ceSAndiry Xu }
18109777e3ceSAndiry Xu } else
18112f31a67fSMathias Nyman t2 &= ~PORT_WAKE_BITS;
18122f31a67fSMathias Nyman
18132f31a67fSMathias Nyman t1 = xhci_port_state_to_neutral(t1);
18142f31a67fSMathias Nyman if (t1 != t2)
18152f31a67fSMathias Nyman portsc_buf[port_index] = t2;
18162f31a67fSMathias Nyman }
18172f31a67fSMathias Nyman
18182f31a67fSMathias Nyman /* write port settings, stopping and suspending ports if needed */
18192f31a67fSMathias Nyman port_index = max_ports;
18202f31a67fSMathias Nyman while (port_index--) {
18212f31a67fSMathias Nyman if (!portsc_buf[port_index])
18222f31a67fSMathias Nyman continue;
18232f31a67fSMathias Nyman if (test_bit(port_index, &bus_state->bus_suspended)) {
18242f31a67fSMathias Nyman int slot_id;
18252f31a67fSMathias Nyman
18262f31a67fSMathias Nyman slot_id = xhci_find_slot_id_by_port(hcd, xhci,
18272f31a67fSMathias Nyman port_index + 1);
18282f31a67fSMathias Nyman if (slot_id) {
18292f31a67fSMathias Nyman spin_unlock_irqrestore(&xhci->lock, flags);
18302f31a67fSMathias Nyman xhci_stop_device(xhci, slot_id, 1);
18319777e3ceSAndiry Xu spin_lock_irqsave(&xhci->lock, flags);
18329777e3ceSAndiry Xu }
183320b67cf5SSarah Sharp }
18349777e3ceSAndiry Xu writel(portsc_buf[port_index], ports[port_index]->addr);
1835c1373f10SLi Jun }
1836c1373f10SLi Jun hcd->state = HC_STATE_SUSPENDED;
1837c1373f10SLi Jun bus_state->next_statechange = jiffies + msecs_to_jiffies(10);
1838c1373f10SLi Jun spin_unlock_irqrestore(&xhci->lock, flags);
18399777e3ceSAndiry Xu
18409777e3ceSAndiry Xu if (bus_state->bus_suspended)
18419777e3ceSAndiry Xu usleep_range(5000, 10000);
1842346e9973SMathias Nyman
1843346e9973SMathias Nyman return 0;
1844346e9973SMathias Nyman }
1845346e9973SMathias Nyman
1846346e9973SMathias Nyman /*
1847fdcf74ffSMathias Nyman * Workaround for missing Cold Attach Status (CAS) if device re-plugged in S3.
1848346e9973SMathias Nyman * warm reset a USB3 device stuck in polling or compliance mode after resume.
1849346e9973SMathias Nyman * See Intel 100/c230 series PCH specification update Doc #332692-006 Errata #8
1850346e9973SMathias Nyman */
xhci_port_missing_cas_quirk(struct xhci_port * port)1851fdcf74ffSMathias Nyman static bool xhci_port_missing_cas_quirk(struct xhci_port *port)
1852346e9973SMathias Nyman {
1853346e9973SMathias Nyman u32 portsc;
1854346e9973SMathias Nyman
1855346e9973SMathias Nyman portsc = readl(port->addr);
1856346e9973SMathias Nyman
1857346e9973SMathias Nyman /* if any of these are set we are not stuck */
1858346e9973SMathias Nyman if (portsc & (PORT_CONNECT | PORT_CAS))
1859346e9973SMathias Nyman return false;
1860346e9973SMathias Nyman
1861346e9973SMathias Nyman if (((portsc & PORT_PLS_MASK) != XDEV_POLLING) &&
1862346e9973SMathias Nyman ((portsc & PORT_PLS_MASK) != XDEV_COMP_MODE))
1863346e9973SMathias Nyman return false;
1864fdcf74ffSMathias Nyman
1865346e9973SMathias Nyman /* clear wakeup/change bits, and do a warm port reset */
1866fdcf74ffSMathias Nyman portsc &= ~(PORT_RWC_BITS | PORT_CEC | PORT_WAKE_BITS);
1867346e9973SMathias Nyman portsc |= PORT_WR;
1868346e9973SMathias Nyman writel(portsc, port->addr);
1869346e9973SMathias Nyman /* flush write */
18709777e3ceSAndiry Xu readl(port->addr);
18719777e3ceSAndiry Xu return true;
18729777e3ceSAndiry Xu }
187320b67cf5SSarah Sharp
xhci_bus_resume(struct usb_hcd * hcd)18749777e3ceSAndiry Xu int xhci_bus_resume(struct usb_hcd *hcd)
1875a85c0f8dSMathias Nyman {
187641485a90SMathias Nyman struct xhci_hcd *xhci = hcd_to_xhci(hcd);
187741485a90SMathias Nyman struct xhci_bus_state *bus_state;
1878a85c0f8dSMathias Nyman unsigned long flags;
1879a85c0f8dSMathias Nyman int max_ports, port_index;
1880e740b019SMathias Nyman int slot_id;
1881e740b019SMathias Nyman int sret;
18829777e3ceSAndiry Xu u32 next_state;
1883e740b019SMathias Nyman u32 temp, portsc;
1884e740b019SMathias Nyman struct xhci_hub *rhub;
1885925f349dSMathias Nyman struct xhci_port **ports;
1886f6187f42SMathias Nyman
18879777e3ceSAndiry Xu rhub = xhci_get_rhub(hcd);
188820b67cf5SSarah Sharp ports = rhub->ports;
18899777e3ceSAndiry Xu max_ports = rhub->num_ports;
18909777e3ceSAndiry Xu bus_state = &rhub->bus_state;
18919777e3ceSAndiry Xu
18929777e3ceSAndiry Xu if (time_before(jiffies, bus_state->next_statechange))
18939777e3ceSAndiry Xu msleep(5);
18949777e3ceSAndiry Xu
18959777e3ceSAndiry Xu spin_lock_irqsave(&xhci->lock, flags);
18969777e3ceSAndiry Xu if (!HCD_HW_ACCESSIBLE(hcd)) {
18979777e3ceSAndiry Xu spin_unlock_irqrestore(&xhci->lock, flags);
1898b0ba9720SXenia Ragiadakou return -ESHUTDOWN;
18999777e3ceSAndiry Xu }
1900204b7793SXenia Ragiadakou
19019777e3ceSAndiry Xu /* delay the irqs */
1902a85c0f8dSMathias Nyman temp = readl(&xhci->op_regs->command);
1903a85c0f8dSMathias Nyman temp &= ~CMD_EIE;
1904a85c0f8dSMathias Nyman writel(temp, &xhci->op_regs->command);
1905a85c0f8dSMathias Nyman
1906a85c0f8dSMathias Nyman /* bus specific resume for ports we suspended at bus_suspend */
1907a85c0f8dSMathias Nyman if (hcd->speed >= HCD_USB3)
1908518e848eSSarah Sharp next_state = XDEV_U0;
1909518e848eSSarah Sharp else
1910e740b019SMathias Nyman next_state = XDEV_RESUME;
1911346e9973SMathias Nyman
1912346e9973SMathias Nyman port_index = max_ports;
1913346e9973SMathias Nyman while (port_index--) {
1914346e9973SMathias Nyman portsc = readl(ports[port_index]->addr);
1915fdcf74ffSMathias Nyman
19168aaf19b8SKai-Heng Feng /* warm reset CAS limited ports stuck in polling/compliance */
19178aaf19b8SKai-Heng Feng if ((xhci->quirks & XHCI_MISSING_CAS) &&
1918a85c0f8dSMathias Nyman (hcd->speed >= HCD_USB3) &&
1919346e9973SMathias Nyman xhci_port_missing_cas_quirk(ports[port_index])) {
1920346e9973SMathias Nyman xhci_dbg(xhci, "reset stuck port %d-%d\n",
1921a85c0f8dSMathias Nyman hcd->self.busnum, port_index + 1);
1922a85c0f8dSMathias Nyman clear_bit(port_index, &bus_state->bus_suspended);
1923a85c0f8dSMathias Nyman continue;
1924a85c0f8dSMathias Nyman }
1925a85c0f8dSMathias Nyman /* resume if we suspended the link, and it is still suspended */
1926a85c0f8dSMathias Nyman if (test_bit(port_index, &bus_state->bus_suspended))
1927a85c0f8dSMathias Nyman switch (portsc & PORT_PLS_MASK) {
1928a85c0f8dSMathias Nyman case XDEV_U3:
1929a85c0f8dSMathias Nyman portsc = xhci_port_state_to_neutral(portsc);
1930a85c0f8dSMathias Nyman portsc &= ~PORT_PLS_MASK;
1931a85c0f8dSMathias Nyman portsc |= PORT_LINK_STROBE | next_state;
1932a85c0f8dSMathias Nyman break;
1933a85c0f8dSMathias Nyman case XDEV_RESUME:
1934a85c0f8dSMathias Nyman /* resume already initiated */
1935a85c0f8dSMathias Nyman break;
1936a85c0f8dSMathias Nyman default:
19379777e3ceSAndiry Xu /* not in a resumeable state, ignore it */
1938a85c0f8dSMathias Nyman clear_bit(port_index,
1939a85c0f8dSMathias Nyman &bus_state->bus_suspended);
1940e740b019SMathias Nyman break;
19419777e3ceSAndiry Xu }
19429777e3ceSAndiry Xu /* disable wake for all ports, write new link state if needed */
1943a85c0f8dSMathias Nyman portsc &= ~(PORT_RWC_BITS | PORT_CEC | PORT_WAKE_BITS);
1944a85c0f8dSMathias Nyman writel(portsc, ports[port_index]->addr);
1945a85c0f8dSMathias Nyman }
194641485a90SMathias Nyman
19477d3b016aSMathias Nyman /* USB2 specific resume signaling delay and U0 link state transition */
194841485a90SMathias Nyman if (hcd->speed < HCD_USB3) {
194941485a90SMathias Nyman if (bus_state->bus_suspended) {
1950a85c0f8dSMathias Nyman spin_unlock_irqrestore(&xhci->lock, flags);
1951a85c0f8dSMathias Nyman msleep(USB_RESUME_TIMEOUT);
1952a85c0f8dSMathias Nyman spin_lock_irqsave(&xhci->lock, flags);
1953eaefcf24SMathias Nyman }
1954a85c0f8dSMathias Nyman for_each_set_bit(port_index, &bus_state->bus_suspended,
19556b7f40f7SMathias Nyman BITS_PER_LONG) {
1956a85c0f8dSMathias Nyman /* Clear PLC to poll it later for U0 transition */
195741485a90SMathias Nyman xhci_test_and_clear_bit(xhci, ports[port_index],
195841485a90SMathias Nyman PORT_PLC);
1959a85c0f8dSMathias Nyman xhci_set_link_state(xhci, ports[port_index], XDEV_U0);
1960a85c0f8dSMathias Nyman }
1961e740b019SMathias Nyman }
196241485a90SMathias Nyman
1963a85c0f8dSMathias Nyman /* poll for U0 link state complete, both USB2 and USB3 */
19648aaf19b8SKai-Heng Feng for_each_set_bit(port_index, &bus_state->bus_suspended, BITS_PER_LONG) {
19658aaf19b8SKai-Heng Feng sret = xhci_handshake(ports[port_index]->addr, PORT_PLC,
1966a85c0f8dSMathias Nyman PORT_PLC, 10 * 1000);
1967a85c0f8dSMathias Nyman if (sret) {
1968eaefcf24SMathias Nyman xhci_warn(xhci, "port %d-%d resume PLC timeout\n",
196941485a90SMathias Nyman hcd->self.busnum, port_index + 1);
197041485a90SMathias Nyman continue;
197141485a90SMathias Nyman }
197241485a90SMathias Nyman xhci_test_and_clear_bit(xhci, ports[port_index], PORT_PLC);
1973b0ba9720SXenia Ragiadakou slot_id = xhci_find_slot_id_by_port(hcd, xhci, port_index + 1);
19749777e3ceSAndiry Xu if (slot_id)
197520b67cf5SSarah Sharp xhci_ring_device(xhci, slot_id);
19769777e3ceSAndiry Xu }
1977b0ba9720SXenia Ragiadakou (void) readl(&xhci->op_regs->command);
19789777e3ceSAndiry Xu
1979204b7793SXenia Ragiadakou bus_state->next_statechange = jiffies + msecs_to_jiffies(5);
1980b0ba9720SXenia Ragiadakou /* re-enable irqs */
19819777e3ceSAndiry Xu temp = readl(&xhci->op_regs->command);
19829777e3ceSAndiry Xu temp |= CMD_EIE;
19839777e3ceSAndiry Xu writel(temp, &xhci->op_regs->command);
19849777e3ceSAndiry Xu temp = readl(&xhci->op_regs->command);
19859777e3ceSAndiry Xu
19868f9cc83cSAlan Stern spin_unlock_irqrestore(&xhci->lock, flags);
19878f9cc83cSAlan Stern return 0;
1988f6187f42SMathias Nyman }
19898f9cc83cSAlan Stern
xhci_get_resuming_ports(struct usb_hcd * hcd)19908f9cc83cSAlan Stern unsigned long xhci_get_resuming_ports(struct usb_hcd *hcd)
1991f6187f42SMathias Nyman {
19928f9cc83cSAlan Stern struct xhci_hub *rhub = xhci_get_rhub(hcd);
19938f9cc83cSAlan Stern
1994436a3890SSarah Sharp /* USB3 port wakeups are reported via usb_wakeup_notification() */
1995 return rhub->bus_state.resuming_ports; /* USB2 ports only */
1996 }
1997
1998 #endif /* CONFIG_PM */
1999