• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <cpu/x86/smm.h>
4 #include <delay.h>
5 #include <device/device.h>
6 #include <device/pci.h>
7 #include <device/pci_ids.h>
8 #include <device/mmio.h>
9 #include <device/pci_ops.h>
10 #include "chip.h"
11 #include "iobp.h"
12 #include "pch.h"
13 
14 #ifdef __SIMPLE_DEVICE__
usb_xhci_mem_base(pci_devfn_t dev)15 static u8 *usb_xhci_mem_base(pci_devfn_t dev)
16 #else
17 static u8 *usb_xhci_mem_base(struct device *dev)
18 #endif
19 {
20 	u32 mem_base = pci_read_config32(dev, PCI_BASE_ADDRESS_0);
21 
22 	/* Check if the controller is disabled or not present */
23 	if (mem_base == 0 || mem_base == 0xffffffff)
24 		return 0;
25 
26 	return (u8 *)(mem_base & ~0xf);
27 }
28 
usb_xhci_port_count_usb3(u8 * mem_base)29 static int usb_xhci_port_count_usb3(u8 *mem_base)
30 {
31 	if (!mem_base) {
32 		/* Do not proceed if BAR is invalid */
33 		return 0;
34 	}
35 
36 	if (pch_is_lp()) {
37 		/* LynxPoint-LP has 4 SS ports */
38 		return 4;
39 	}
40 
41 	/* LynxPoint-H can have 0, 2, 4, or 6 SS ports */
42 	u32 fus = read32(mem_base + XHCI_USB3FUS);
43 	fus >>= XHCI_USB3FUS_SS_SHIFT;
44 	fus &= XHCI_USB3FUS_SS_MASK;
45 	switch (fus) {
46 	case 3: return 0;
47 	case 2: return 2;
48 	case 1: return 4;
49 	case 0:
50 	default: return 6;
51 	}
52 }
53 
usb_xhci_reset_status_usb3(u8 * mem_base,int port)54 static void usb_xhci_reset_status_usb3(u8 *mem_base, int port)
55 {
56 	u8 *portsc = mem_base + XHCI_USB3_PORTSC(port);
57 	u32 status = read32(portsc);
58 	/* Do not set Port Enabled/Disabled field */
59 	status &= ~XHCI_USB3_PORTSC_PED;
60 	/* Clear all change status bits */
61 	status |= XHCI_USB3_PORTSC_CHST;
62 	write32(portsc, status);
63 }
64 
usb_xhci_reset_port_usb3(u8 * mem_base,int port)65 static void usb_xhci_reset_port_usb3(u8 *mem_base, int port)
66 {
67 	u8 *portsc = mem_base + XHCI_USB3_PORTSC(port);
68 	write32(portsc, read32(portsc) | XHCI_USB3_PORTSC_WPR);
69 }
70 
71 #define XHCI_RESET_DELAY_US	1000 /* 1ms */
72 #define XHCI_RESET_TIMEOUT	100  /* 100ms */
73 
74 /*
75  * 1) Wait until port is done polling
76  * 2) If port is disconnected
77  *  a) Issue warm port reset
78  *  b) Poll for warm reset complete
79  *  c) Write 1 to port change status bits
80  */
81 #ifdef __SIMPLE_DEVICE__
usb_xhci_reset_usb3(pci_devfn_t dev,int all)82 static void usb_xhci_reset_usb3(pci_devfn_t dev, int all)
83 #else
84 static void usb_xhci_reset_usb3(struct device *dev, int all)
85 #endif
86 {
87 	u32 status, port_disabled;
88 	int timeout, port;
89 	u8 *mem_base = usb_xhci_mem_base(dev);
90 	int port_count = usb_xhci_port_count_usb3(mem_base);
91 
92 	if (!port_count)
93 		return;
94 
95 	/* Get mask of disabled ports */
96 	port_disabled = pci_read_config32(dev, XHCI_USB3PDO);
97 
98 	/* Wait until all enabled ports are done polling */
99 	for (timeout = XHCI_RESET_TIMEOUT; timeout; timeout--) {
100 		int complete = 1;
101 		for (port = 0; port < port_count; port++) {
102 			/* Skip disabled ports */
103 			if (port_disabled & (1 << port))
104 				continue;
105 			/* Read port link status field */
106 			status = read32(mem_base + XHCI_USB3_PORTSC(port));
107 			status &= XHCI_USB3_PORTSC_PLS;
108 			if (status == XHCI_PLSR_POLLING)
109 				complete = 0;
110 		}
111 		/* Exit if all ports not polling */
112 		if (complete)
113 			break;
114 		udelay(XHCI_RESET_DELAY_US);
115 	}
116 
117 	/* Reset all requested ports */
118 	for (port = 0; port < port_count; port++) {
119 		u8 *portsc = mem_base + XHCI_USB3_PORTSC(port);
120 		/* Skip disabled ports */
121 		if (port_disabled & (1 << port))
122 			continue;
123 		status = read32(portsc) & XHCI_USB3_PORTSC_PLS;
124 		/* Reset all or only disconnected ports */
125 		if (all || (status == XHCI_PLSR_RXDETECT ||
126 			    status == XHCI_PLSR_POLLING))
127 			usb_xhci_reset_port_usb3(mem_base, port);
128 		else
129 			port_disabled |= 1 << port;
130 	}
131 
132 	/* Wait for warm reset complete on all reset ports */
133 	for (timeout = XHCI_RESET_TIMEOUT; timeout; timeout--) {
134 		int complete = 1;
135 		for (port = 0; port < port_count; port++) {
136 			/* Only check ports that were reset */
137 			if (port_disabled & (1 << port))
138 				continue;
139 			/* Check if warm reset is complete */
140 			status = read32(mem_base + XHCI_USB3_PORTSC(port));
141 			if (!(status & XHCI_USB3_PORTSC_WRC))
142 				complete = 0;
143 		}
144 		/* Check for warm reset complete in any port */
145 		if (complete)
146 			break;
147 		udelay(XHCI_RESET_DELAY_US);
148 	}
149 
150 	/* Clear port change status bits */
151 	for (port = 0; port < port_count; port++)
152 		usb_xhci_reset_status_usb3(mem_base, port);
153 }
154 
155 #ifdef __SIMPLE_DEVICE__
156 
157 /* Handler for XHCI controller on entry to S3/S4/S5 */
usb_xhci_sleep_prepare(pci_devfn_t dev,u8 slp_typ)158 void usb_xhci_sleep_prepare(pci_devfn_t dev, u8 slp_typ)
159 {
160 	u32 reg32;
161 	u8 *mem_base = usb_xhci_mem_base(dev);
162 
163 	if (!mem_base || slp_typ < ACPI_S3)
164 		return;
165 
166 	if (pch_is_lp()) {
167 		/* Set D0 state */
168 		pci_update_config16(dev, XHCI_PWR_CTL_STS, ~PWR_CTL_SET_MASK, PWR_CTL_SET_D0);
169 
170 		/* Clear PCI 0xB0[14:13] */
171 		pci_and_config32(dev, 0xb0, ~((1 << 14) | (1 << 13)));
172 
173 		/* Clear MMIO 0x816c[14,2] */
174 		reg32 = read32(mem_base + 0x816c);
175 		reg32 &= ~((1 << 14) | (1 << 2));
176 		write32(mem_base + 0x816c, reg32);
177 
178 		/* Reset disconnected USB3 ports */
179 		usb_xhci_reset_usb3(dev, 0);
180 
181 		/* Set MMIO 0x80e0[15] */
182 		reg32 = read32(mem_base + 0x80e0);
183 		reg32 |= (1 << 15);
184 		write32(mem_base + 0x80e0, reg32);
185 	}
186 
187 	/* Set D3Hot state and enable PME */
188 	pci_or_config16(dev, XHCI_PWR_CTL_STS, PWR_CTL_SET_D3);
189 	pci_or_config16(dev, XHCI_PWR_CTL_STS, PWR_CTL_STATUS_PME);
190 	pci_or_config16(dev, XHCI_PWR_CTL_STS, PWR_CTL_ENABLE_PME);
191 }
192 
193 /* Route all ports to XHCI controller */
usb_xhci_route_all(void)194 void usb_xhci_route_all(void)
195 {
196 	u32 port_mask, route;
197 
198 	/* Skip if EHCI is already disabled */
199 	if (RCBA32(FD) & PCH_DISABLE_EHCI1)
200 		return;
201 
202 	/* Set D0 state */
203 	pci_update_config16(PCH_XHCI_DEV, XHCI_PWR_CTL_STS, ~PWR_CTL_SET_MASK, PWR_CTL_SET_D0);
204 
205 	/* Set USB3 superspeed enable */
206 	port_mask = pci_read_config32(PCH_XHCI_DEV, XHCI_USB3PRM);
207 	route = pci_read_config32(PCH_XHCI_DEV, XHCI_USB3PR);
208 	route &= ~XHCI_USB3PR_SSEN;
209 	route |= XHCI_USB3PR_SSEN & port_mask;
210 	pci_write_config32(PCH_XHCI_DEV, XHCI_USB3PR, route);
211 
212 	/* Route USB2 ports to XHCI controller */
213 	port_mask = pci_read_config32(PCH_XHCI_DEV, XHCI_USB2PRM);
214 	route = pci_read_config32(PCH_XHCI_DEV, XHCI_USB2PR);
215 	route &= ~XHCI_USB2PR_HCSEL;
216 	route |= XHCI_USB2PR_HCSEL & port_mask;
217 	pci_write_config32(PCH_XHCI_DEV, XHCI_USB2PR, route);
218 
219 	/* Disable EHCI controller */
220 	usb_ehci_disable(PCH_EHCI1_DEV);
221 
222 	/* LynxPoint-H has a second EHCI controller */
223 	if (!pch_is_lp())
224 		usb_ehci_disable(PCH_EHCI2_DEV);
225 
226 	/* Reset and clear port change status */
227 	usb_xhci_reset_usb3(PCH_XHCI_DEV, 1);
228 }
229 
230 #else /* !__SIMPLE_DEVICE__ */
231 
usb_xhci_clock_gating(struct device * dev)232 static void usb_xhci_clock_gating(struct device *dev)
233 {
234 	u32 reg32;
235 
236 	/* IOBP 0xE5004001[7:6] = 11b */
237 	pch_iobp_update(0xe5004001, ~0, (1 << 7) | (1 << 6));
238 
239 	reg32 = pci_read_config32(dev, 0x40);
240 	reg32 &= ~(1 << 23); /* unsupported request */
241 
242 	if (pch_is_lp()) {
243 		/* D20:F0:40h[18,17,8] = 111b */
244 		reg32 |= (1 << 18) | (1 << 17) | (1 << 8);
245 		/* D20:F0:40h[21,20,19] = 110b to enable XHCI Idle L1 */
246 		reg32 &= ~(1 << 19);
247 		reg32 |= (1 << 21) | (1 << 20);
248 	} else {
249 		/* D20:F0:40h[21,20,18,17,8] = 11111b */
250 		reg32 |= (1 << 21) | (1 << 20) | (1 << 18) | (1 << 17) | (1 << 8);
251 	}
252 
253 	/* Avoid writing upper byte as it is write-once */
254 	pci_write_config16(dev, 0x40, (u16)(reg32 & 0xffff));
255 	pci_write_config8(dev, 0x40 + 2, (u8)((reg32 >> 16) & 0xff));
256 
257 	/* D20:F0:44h[9,7,3] = 111b */
258 	pci_or_config16(dev, 0x44, (1 << 9) | (1 << 7) | (1 << 3));
259 
260 	reg32 = pci_read_config32(dev, 0xa0);
261 	if (pch_is_lp()) {
262 		/* D20:F0:A0h[18] = 1 */
263 		reg32 |= (1 << 18);
264 	} else {
265 		/* D20:F0:A0h[6] = 1 */
266 		reg32 |= (1 << 6);
267 	}
268 	pci_write_config32(dev, 0xa0, reg32);
269 
270 	/* D20:F0:A4h[13] = 0 */
271 	pci_and_config32(dev, 0xa4, ~(1 << 13));
272 }
273 
usb_xhci_init(struct device * dev)274 static void usb_xhci_init(struct device *dev)
275 {
276 	u32 reg32;
277 	u8 *mem_base = usb_xhci_mem_base(dev);
278 	struct southbridge_intel_lynxpoint_config *config = dev->chip_info;
279 
280 	/* D20:F0:74h[1:0] = 00b (set D0 state) */
281 	pci_update_config16(dev, XHCI_PWR_CTL_STS, ~PWR_CTL_SET_MASK, PWR_CTL_SET_D0);
282 
283 	/* Enable clock gating first */
284 	usb_xhci_clock_gating(dev);
285 
286 	reg32 = read32(mem_base + 0x8144);
287 	if (pch_is_lp()) {
288 		/* XHCIBAR + 8144h[8,7,6] = 111b */
289 		reg32 |= (1 << 8) | (1 << 7) | (1 << 6);
290 	} else {
291 		/* XHCIBAR + 8144h[8,7,6] = 100b */
292 		reg32 &= ~((1 << 7) | (1 << 6));
293 		reg32 |= (1 << 8);
294 	}
295 	write32(mem_base + 0x8144, reg32);
296 
297 	if (pch_is_lp()) {
298 		/* XHCIBAR + 816Ch[19:0] = 000e0038h */
299 		reg32 = read32(mem_base + 0x816c);
300 		reg32 &= ~0x000fffff;
301 		reg32 |= 0x000e0038;
302 		write32(mem_base + 0x816c, reg32);
303 
304 		/* D20:F0:B0h[17,14,13] = 100b */
305 		pci_update_config32(dev, 0xb0, ~((1 << 14) | (1 << 13)), 1 << 17);
306 	}
307 
308 	reg32 = pci_read_config32(dev, 0x50);
309 	if (pch_is_lp()) {
310 		/* D20:F0:50h[28:0] = 0FCE2E5Fh */
311 		reg32 &= ~0x1fffffff;
312 		reg32 |= 0x0fce2e5f;
313 	} else {
314 		/* D20:F0:50h[26:0] = 07886E9Fh */
315 		reg32 &= ~0x07ffffff;
316 		reg32 |= 0x07886e9f;
317 	}
318 	pci_write_config32(dev, 0x50, reg32);
319 
320 	/* D20:F0:44h[31] = 1 (Access Control Bit) */
321 	pci_or_config32(dev, 0x44, 1 << 31);
322 
323 	/* D20:F0:40h[31,23] = 10b (OC Configuration Done) */
324 	pci_update_config32(dev, 0x40, ~(1 << 23), 1 << 31); /* unsupported request */
325 
326 	if (acpi_is_wakeup_s3()) {
327 		/* Reset ports that are disabled or
328 		 * polling before returning to the OS. */
329 		usb_xhci_reset_usb3(dev, 0);
330 	} else if (config && config->xhci_default) {
331 		/* Route all ports to XHCI */
332 		apm_control(APM_CNT_ROUTE_ALL_XHCI);
333 	}
334 }
335 
336 static struct device_operations usb_xhci_ops = {
337 	.read_resources		= pci_dev_read_resources,
338 	.set_resources		= pci_dev_set_resources,
339 	.enable_resources	= pci_dev_enable_resources,
340 	.init			= usb_xhci_init,
341 	.ops_pci		= &pci_dev_ops_pci,
342 };
343 
344 static const unsigned short pci_device_ids[] = {
345 	PCI_DID_INTEL_LPT_H_XHCI,
346 	PCI_DID_INTEL_LPT_H_XHCI_9,
347 	PCI_DID_INTEL_LPT_LP_XHCI,
348 	0
349 };
350 
351 static const struct pci_driver pch_usb_xhci __pci_driver = {
352 	.ops	 = &usb_xhci_ops,
353 	.vendor	 = PCI_VID_INTEL,
354 	.devices = pci_device_ids,
355 };
356 #endif /* !__SIMPLE_DEVICE__ */
357