xref: /openbmc/linux/drivers/usb/host/xhci-hub.c (revision 58bcac11fd94f950abc7b8466c5ceac7be07a00e)
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