]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Usb/UsbBusPei/HubPeim.c
MdeModulePkg: Change use of EFI_D_* to DEBUG_*
[mirror_edk2.git] / MdeModulePkg / Bus / Usb / UsbBusPei / HubPeim.c
1 /** @file
2 Usb Hub Request Support In PEI Phase
3
4 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
5
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8 **/
9
10 #include "UsbPeim.h"
11 #include "HubPeim.h"
12 #include "PeiUsbLib.h"
13
14 /**
15 Get a given hub port status.
16
17 @param PeiServices General-purpose services that are available to every PEIM.
18 @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
19 @param Port Usb hub port number (starting from 1).
20 @param PortStatus Current Hub port status and change status.
21
22 @retval EFI_SUCCESS Port status is obtained successfully.
23 @retval EFI_DEVICE_ERROR Cannot get the port status due to a hardware error.
24 @retval Others Other failure occurs.
25
26 **/
27 EFI_STATUS
28 PeiHubGetPortStatus (
29 IN EFI_PEI_SERVICES **PeiServices,
30 IN PEI_USB_IO_PPI *UsbIoPpi,
31 IN UINT8 Port,
32 OUT UINT32 *PortStatus
33 )
34 {
35 EFI_USB_DEVICE_REQUEST DeviceRequest;
36
37 ZeroMem (&DeviceRequest, sizeof (EFI_USB_DEVICE_REQUEST));
38
39 //
40 // Fill Device request packet
41 //
42 DeviceRequest.RequestType = USB_HUB_GET_PORT_STATUS_REQ_TYPE;
43 DeviceRequest.Request = USB_HUB_GET_PORT_STATUS;
44 DeviceRequest.Index = Port;
45 DeviceRequest.Length = (UINT16) sizeof (UINT32);
46
47
48 return UsbIoPpi->UsbControlTransfer (
49 PeiServices,
50 UsbIoPpi,
51 &DeviceRequest,
52 EfiUsbDataIn,
53 PcdGet32 (PcdUsbTransferTimeoutValue),
54 PortStatus,
55 sizeof (UINT32)
56 );
57
58 }
59
60 /**
61 Set specified feature to a given hub port.
62
63 @param PeiServices General-purpose services that are available to every PEIM.
64 @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
65 @param Port Usb hub port number (starting from 1).
66 @param Value New feature value.
67
68 @retval EFI_SUCCESS Port feature is set successfully.
69 @retval EFI_DEVICE_ERROR Cannot set the port feature due to a hardware error.
70 @retval Others Other failure occurs.
71
72 **/
73 EFI_STATUS
74 PeiHubSetPortFeature (
75 IN EFI_PEI_SERVICES **PeiServices,
76 IN PEI_USB_IO_PPI *UsbIoPpi,
77 IN UINT8 Port,
78 IN UINT8 Value
79 )
80 {
81 EFI_USB_DEVICE_REQUEST DeviceRequest;
82
83 ZeroMem (&DeviceRequest, sizeof (EFI_USB_DEVICE_REQUEST));
84
85 //
86 // Fill Device request packet
87 //
88 DeviceRequest.RequestType = USB_HUB_SET_PORT_FEATURE_REQ_TYPE;
89 DeviceRequest.Request = USB_HUB_SET_PORT_FEATURE;
90 DeviceRequest.Value = Value;
91 DeviceRequest.Index = Port;
92
93 return UsbIoPpi->UsbControlTransfer (
94 PeiServices,
95 UsbIoPpi,
96 &DeviceRequest,
97 EfiUsbNoData,
98 PcdGet32 (PcdUsbTransferTimeoutValue),
99 NULL,
100 0
101 );
102 }
103
104 /**
105 Clear specified feature on a given hub port.
106
107 @param PeiServices General-purpose services that are available to every PEIM.
108 @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
109 @param Port Usb hub port number (starting from 1).
110 @param Value Feature value that will be cleared from the hub port.
111
112 @retval EFI_SUCCESS Port feature is cleared successfully.
113 @retval EFI_DEVICE_ERROR Cannot clear the port feature due to a hardware error.
114 @retval Others Other failure occurs.
115
116 **/
117 EFI_STATUS
118 PeiHubClearPortFeature (
119 IN EFI_PEI_SERVICES **PeiServices,
120 IN PEI_USB_IO_PPI *UsbIoPpi,
121 IN UINT8 Port,
122 IN UINT8 Value
123 )
124 {
125 EFI_USB_DEVICE_REQUEST DeviceRequest;
126
127 ZeroMem (&DeviceRequest, sizeof (EFI_USB_DEVICE_REQUEST));
128
129 //
130 // Fill Device request packet
131 //
132 DeviceRequest.RequestType = USB_HUB_CLEAR_FEATURE_PORT_REQ_TYPE;
133 DeviceRequest.Request = USB_HUB_CLEAR_FEATURE_PORT;
134 DeviceRequest.Value = Value;
135 DeviceRequest.Index = Port;
136
137 return UsbIoPpi->UsbControlTransfer (
138 PeiServices,
139 UsbIoPpi,
140 &DeviceRequest,
141 EfiUsbNoData,
142 PcdGet32 (PcdUsbTransferTimeoutValue),
143 NULL,
144 0
145 );
146 }
147
148 /**
149 Get a given hub status.
150
151 @param PeiServices General-purpose services that are available to every PEIM.
152 @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
153 @param HubStatus Current Hub status and change status.
154
155 @retval EFI_SUCCESS Hub status is obtained successfully.
156 @retval EFI_DEVICE_ERROR Cannot get the hub status due to a hardware error.
157 @retval Others Other failure occurs.
158
159 **/
160 EFI_STATUS
161 PeiHubGetHubStatus (
162 IN EFI_PEI_SERVICES **PeiServices,
163 IN PEI_USB_IO_PPI *UsbIoPpi,
164 OUT UINT32 *HubStatus
165 )
166 {
167 EFI_USB_DEVICE_REQUEST DeviceRequest;
168
169 ZeroMem (&DeviceRequest, sizeof (EFI_USB_DEVICE_REQUEST));
170
171 //
172 // Fill Device request packet
173 //
174 DeviceRequest.RequestType = USB_HUB_GET_HUB_STATUS_REQ_TYPE;
175 DeviceRequest.Request = USB_HUB_GET_HUB_STATUS;
176 DeviceRequest.Length = (UINT16) sizeof (UINT32);
177
178 return UsbIoPpi->UsbControlTransfer (
179 PeiServices,
180 UsbIoPpi,
181 &DeviceRequest,
182 EfiUsbDataIn,
183 PcdGet32 (PcdUsbTransferTimeoutValue),
184 HubStatus,
185 sizeof (UINT32)
186 );
187 }
188
189
190
191 /**
192 Clear specified feature on a given hub.
193
194 @param PeiServices General-purpose services that are available to every PEIM.
195 @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
196 @param Value Feature value that will be cleared from the hub port.
197
198 @retval EFI_SUCCESS Hub feature is cleared successfully.
199 @retval EFI_DEVICE_ERROR Cannot clear the hub feature due to a hardware error.
200 @retval Others Other failure occurs.
201
202 **/
203 EFI_STATUS
204 PeiHubClearHubFeature (
205 IN EFI_PEI_SERVICES **PeiServices,
206 IN PEI_USB_IO_PPI *UsbIoPpi,
207 IN UINT8 Value
208 )
209 {
210 EFI_USB_DEVICE_REQUEST DeviceRequest;
211
212 ZeroMem (&DeviceRequest, sizeof (EFI_USB_DEVICE_REQUEST));
213
214 //
215 // Fill Device request packet
216 //
217 DeviceRequest.RequestType = USB_HUB_CLEAR_FEATURE_REQ_TYPE;
218 DeviceRequest.Request = USB_HUB_CLEAR_FEATURE;
219 DeviceRequest.Value = Value;
220
221 return UsbIoPpi->UsbControlTransfer (
222 PeiServices,
223 UsbIoPpi,
224 &DeviceRequest,
225 EfiUsbNoData,
226 PcdGet32 (PcdUsbTransferTimeoutValue),
227 NULL,
228 0
229 );
230 }
231
232 /**
233 Get a given (SuperSpeed) hub descriptor.
234
235 @param PeiServices General-purpose services that are available to every PEIM.
236 @param PeiUsbDevice Indicates the hub controller device.
237 @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
238 @param DescriptorSize The length of Hub Descriptor buffer.
239 @param HubDescriptor Caller allocated buffer to store the hub descriptor if
240 successfully returned.
241
242 @retval EFI_SUCCESS Hub descriptor is obtained successfully.
243 @retval EFI_DEVICE_ERROR Cannot get the hub descriptor due to a hardware error.
244 @retval Others Other failure occurs.
245
246 **/
247 EFI_STATUS
248 PeiGetHubDescriptor (
249 IN EFI_PEI_SERVICES **PeiServices,
250 IN PEI_USB_DEVICE *PeiUsbDevice,
251 IN PEI_USB_IO_PPI *UsbIoPpi,
252 IN UINTN DescriptorSize,
253 OUT EFI_USB_HUB_DESCRIPTOR *HubDescriptor
254 )
255 {
256 EFI_USB_DEVICE_REQUEST DevReq;
257 UINT8 DescType;
258
259 ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST));
260
261 DescType = (PeiUsbDevice->DeviceSpeed == EFI_USB_SPEED_SUPER) ?
262 USB_DT_SUPERSPEED_HUB :
263 USB_DT_HUB;
264
265 //
266 // Fill Device request packet
267 //
268 DevReq.RequestType = USB_RT_HUB | 0x80;
269 DevReq.Request = USB_HUB_GET_DESCRIPTOR;
270 DevReq.Value = (UINT16) (DescType << 8);
271 DevReq.Length = (UINT16) DescriptorSize;
272
273 return UsbIoPpi->UsbControlTransfer (
274 PeiServices,
275 UsbIoPpi,
276 &DevReq,
277 EfiUsbDataIn,
278 PcdGet32 (PcdUsbTransferTimeoutValue),
279 HubDescriptor,
280 (UINT16)DescriptorSize
281 );
282 }
283
284 /**
285 Read the whole usb hub descriptor. It is necessary
286 to do it in two steps because hub descriptor is of
287 variable length.
288
289 @param PeiServices General-purpose services that are available to every PEIM.
290 @param PeiUsbDevice Indicates the hub controller device.
291 @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
292 @param HubDescriptor Caller allocated buffer to store the hub descriptor if
293 successfully returned.
294
295 @retval EFI_SUCCESS Hub descriptor is obtained successfully.
296 @retval EFI_DEVICE_ERROR Cannot get the hub descriptor due to a hardware error.
297 @retval Others Other failure occurs.
298
299 **/
300 EFI_STATUS
301 PeiUsbHubReadDesc (
302 IN EFI_PEI_SERVICES **PeiServices,
303 IN PEI_USB_DEVICE *PeiUsbDevice,
304 IN PEI_USB_IO_PPI *UsbIoPpi,
305 OUT EFI_USB_HUB_DESCRIPTOR *HubDescriptor
306 )
307 {
308 EFI_STATUS Status;
309
310 //
311 // First get the hub descriptor length
312 //
313 Status = PeiGetHubDescriptor (PeiServices, PeiUsbDevice, UsbIoPpi, 2, HubDescriptor);
314
315 if (EFI_ERROR (Status)) {
316 return Status;
317 }
318
319 //
320 // Get the whole hub descriptor
321 //
322 return PeiGetHubDescriptor (PeiServices, PeiUsbDevice, UsbIoPpi, HubDescriptor->Length, HubDescriptor);
323 }
324
325 /**
326 USB hub control transfer to set the hub depth.
327
328 @param PeiServices General-purpose services that are available to every PEIM.
329 @param PeiUsbDevice Indicates the hub controller device.
330 @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
331
332 @retval EFI_SUCCESS Depth of the hub is set.
333 @retval Others Failed to set the depth.
334
335 **/
336 EFI_STATUS
337 PeiUsbHubCtrlSetHubDepth (
338 IN EFI_PEI_SERVICES **PeiServices,
339 IN PEI_USB_DEVICE *PeiUsbDevice,
340 IN PEI_USB_IO_PPI *UsbIoPpi
341 )
342 {
343 EFI_USB_DEVICE_REQUEST DevReq;
344 ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST));
345
346 //
347 // Fill Device request packet
348 //
349 DevReq.RequestType = USB_RT_HUB;
350 DevReq.Request = USB_HUB_REQ_SET_DEPTH;
351 DevReq.Value = PeiUsbDevice->Tier;
352 DevReq.Length = 0;
353
354 return UsbIoPpi->UsbControlTransfer (
355 PeiServices,
356 UsbIoPpi,
357 &DevReq,
358 EfiUsbNoData,
359 PcdGet32 (PcdUsbTransferTimeoutValue),
360 NULL,
361 0
362 );
363 }
364
365 /**
366 Configure a given hub.
367
368 @param PeiServices General-purpose services that are available to every PEIM.
369 @param PeiUsbDevice Indicating the hub controller device that will be configured
370
371 @retval EFI_SUCCESS Hub configuration is done successfully.
372 @retval EFI_DEVICE_ERROR Cannot configure the hub due to a hardware error.
373
374 **/
375 EFI_STATUS
376 PeiDoHubConfig (
377 IN EFI_PEI_SERVICES **PeiServices,
378 IN PEI_USB_DEVICE *PeiUsbDevice
379 )
380 {
381 UINT8 HubDescBuffer[256];
382 EFI_USB_HUB_DESCRIPTOR *HubDescriptor;
383 EFI_STATUS Status;
384 EFI_USB_HUB_STATUS HubStatus;
385 UINTN Index;
386 PEI_USB_IO_PPI *UsbIoPpi;
387
388 UsbIoPpi = &PeiUsbDevice->UsbIoPpi;
389
390 //
391 // The length field of descriptor is UINT8 type, so the buffer
392 // with 256 bytes is enough to hold the descriptor data.
393 //
394 HubDescriptor = (EFI_USB_HUB_DESCRIPTOR *) HubDescBuffer;
395
396 //
397 // Get the hub descriptor
398 //
399 Status = PeiUsbHubReadDesc (
400 PeiServices,
401 PeiUsbDevice,
402 UsbIoPpi,
403 HubDescriptor
404 );
405 if (EFI_ERROR (Status)) {
406 return EFI_DEVICE_ERROR;
407 }
408
409 PeiUsbDevice->DownStreamPortNo = HubDescriptor->NbrPorts;
410
411 if (PeiUsbDevice->DeviceSpeed == EFI_USB_SPEED_SUPER) {
412 DEBUG ((DEBUG_INFO, "PeiDoHubConfig: Set Hub Depth as 0x%x\n", PeiUsbDevice->Tier));
413 PeiUsbHubCtrlSetHubDepth (
414 PeiServices,
415 PeiUsbDevice,
416 UsbIoPpi
417 );
418 } else {
419 //
420 // Power all the hub ports
421 //
422 for (Index = 0; Index < PeiUsbDevice->DownStreamPortNo; Index++) {
423 Status = PeiHubSetPortFeature (
424 PeiServices,
425 UsbIoPpi,
426 (UINT8) (Index + 1),
427 EfiUsbPortPower
428 );
429 if (EFI_ERROR (Status)) {
430 DEBUG (( DEBUG_ERROR, "PeiDoHubConfig: PeiHubSetPortFeature EfiUsbPortPower failed %x\n", Index));
431 continue;
432 }
433 }
434
435 DEBUG (( DEBUG_INFO, "PeiDoHubConfig: HubDescriptor.PwrOn2PwrGood: 0x%x\n", HubDescriptor->PwrOn2PwrGood));
436 if (HubDescriptor->PwrOn2PwrGood > 0) {
437 MicroSecondDelay (HubDescriptor->PwrOn2PwrGood * USB_SET_PORT_POWER_STALL);
438 }
439
440 //
441 // Clear Hub Status Change
442 //
443 Status = PeiHubGetHubStatus (
444 PeiServices,
445 UsbIoPpi,
446 (UINT32 *) &HubStatus
447 );
448 if (EFI_ERROR (Status)) {
449 return EFI_DEVICE_ERROR;
450 } else {
451 //
452 // Hub power supply change happens
453 //
454 if ((HubStatus.HubChangeStatus & HUB_CHANGE_LOCAL_POWER) != 0) {
455 PeiHubClearHubFeature (
456 PeiServices,
457 UsbIoPpi,
458 C_HUB_LOCAL_POWER
459 );
460 }
461 //
462 // Hub change overcurrent happens
463 //
464 if ((HubStatus.HubChangeStatus & HUB_CHANGE_OVERCURRENT) != 0) {
465 PeiHubClearHubFeature (
466 PeiServices,
467 UsbIoPpi,
468 C_HUB_OVER_CURRENT
469 );
470 }
471 }
472 }
473
474 return EFI_SUCCESS;
475 }
476
477 /**
478 Send reset signal over the given root hub port.
479
480 @param PeiServices General-purpose services that are available to every PEIM.
481 @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.
482 @param PortNum Usb hub port number (starting from 1).
483
484 **/
485 VOID
486 PeiResetHubPort (
487 IN EFI_PEI_SERVICES **PeiServices,
488 IN PEI_USB_IO_PPI *UsbIoPpi,
489 IN UINT8 PortNum
490 )
491 {
492 EFI_STATUS Status;
493 UINTN Index;
494 EFI_USB_PORT_STATUS HubPortStatus;
495
496 MicroSecondDelay (100 * 1000);
497
498 //
499 // reset root port
500 //
501 PeiHubSetPortFeature (
502 PeiServices,
503 UsbIoPpi,
504 PortNum,
505 EfiUsbPortReset
506 );
507
508 //
509 // Drive the reset signal for worst 20ms. Check USB 2.0 Spec
510 // section 7.1.7.5 for timing requirements.
511 //
512 MicroSecondDelay (USB_SET_PORT_RESET_STALL);
513
514 //
515 // Check USB_PORT_STAT_C_RESET bit to see if the resetting state is done.
516 //
517 ZeroMem (&HubPortStatus, sizeof (EFI_USB_PORT_STATUS));
518
519 for (Index = 0; Index < USB_WAIT_PORT_STS_CHANGE_LOOP; Index++) {
520 Status = PeiHubGetPortStatus (
521 PeiServices,
522 UsbIoPpi,
523 PortNum,
524 (UINT32 *) &HubPortStatus
525 );
526
527 if (EFI_ERROR (Status)) {
528 return;
529 }
530
531 if (USB_BIT_IS_SET (HubPortStatus.PortChangeStatus, USB_PORT_STAT_C_RESET)) {
532 break;
533 }
534
535 MicroSecondDelay (USB_WAIT_PORT_STS_CHANGE_STALL);
536 }
537
538 if (Index == USB_WAIT_PORT_STS_CHANGE_LOOP) {
539 DEBUG ((DEBUG_ERROR, "PeiResetHubPort: reset not finished in time on port %d\n", PortNum));
540 return;
541 }
542
543 //
544 // clear reset change root port
545 //
546 PeiHubClearPortFeature (
547 PeiServices,
548 UsbIoPpi,
549 PortNum,
550 EfiUsbPortResetChange
551 );
552
553 MicroSecondDelay (1 * 1000);
554
555 PeiHubClearPortFeature (
556 PeiServices,
557 UsbIoPpi,
558 PortNum,
559 EfiUsbPortConnectChange
560 );
561
562 //
563 // Set port enable
564 //
565 PeiHubSetPortFeature (
566 PeiServices,
567 UsbIoPpi,
568 PortNum,
569 EfiUsbPortEnable
570 );
571
572 //
573 // Clear any change status
574 //
575
576 PeiHubClearPortFeature (
577 PeiServices,
578 UsbIoPpi,
579 PortNum,
580 EfiUsbPortEnableChange
581 );
582
583 MicroSecondDelay (10 * 1000);
584
585 return;
586 }