3 The XHCI register operation routines.
5 Copyright (c) 2011 - 2017, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
13 Read 1-byte width XHCI capability register.
15 @param Xhc The XHCI Instance.
16 @param Offset The offset of the 1-byte width capability register.
18 @return The register content read.
19 @retval If err, return 0xFF.
24 IN USB_XHCI_INSTANCE
*Xhc
,
31 Status
= Xhc
->PciIo
->Mem
.Read (
40 if (EFI_ERROR (Status
)) {
41 DEBUG ((EFI_D_ERROR
, "XhcReadCapReg: Pci Io read error - %r at %d\n", Status
, Offset
));
49 Read 4-bytes width XHCI capability register.
51 @param Xhc The XHCI Instance.
52 @param Offset The offset of the 4-bytes width capability register.
54 @return The register content read.
55 @retval If err, return 0xFFFFFFFF.
60 IN USB_XHCI_INSTANCE
*Xhc
,
67 Status
= Xhc
->PciIo
->Mem
.Read (
76 if (EFI_ERROR (Status
)) {
77 DEBUG ((EFI_D_ERROR
, "XhcReadCapReg: Pci Io read error - %r at %d\n", Status
, Offset
));
85 Read 4-bytes width XHCI Operational register.
87 @param Xhc The XHCI Instance.
88 @param Offset The offset of the 4-bytes width operational register.
90 @return The register content read.
91 @retval If err, return 0xFFFFFFFF.
96 IN USB_XHCI_INSTANCE
*Xhc
,
103 ASSERT (Xhc
->CapLength
!= 0);
105 Status
= Xhc
->PciIo
->Mem
.Read (
109 Xhc
->CapLength
+ Offset
,
114 if (EFI_ERROR (Status
)) {
115 DEBUG ((EFI_D_ERROR
, "XhcReadOpReg: Pci Io Read error - %r at %d\n", Status
, Offset
));
123 Write the data to the 4-bytes width XHCI operational register.
125 @param Xhc The XHCI Instance.
126 @param Offset The offset of the 4-bytes width operational register.
127 @param Data The data to write.
132 IN USB_XHCI_INSTANCE
*Xhc
,
139 ASSERT (Xhc
->CapLength
!= 0);
141 Status
= Xhc
->PciIo
->Mem
.Write (
145 Xhc
->CapLength
+ Offset
,
150 if (EFI_ERROR (Status
)) {
151 DEBUG ((EFI_D_ERROR
, "XhcWriteOpReg: Pci Io Write error: %r at %d\n", Status
, Offset
));
160 Write the data to the XHCI door bell register.
162 @param Xhc The XHCI Instance.
163 @param Offset The offset of the door bell register.
164 @param Data The data to write.
168 XhcWriteDoorBellReg (
169 IN USB_XHCI_INSTANCE
*Xhc
,
176 ASSERT (Xhc
->DBOff
!= 0);
178 Status
= Xhc
->PciIo
->Mem
.Write (
187 if (EFI_ERROR (Status
)) {
188 DEBUG ((EFI_D_ERROR
, "XhcWriteOpReg: Pci Io Write error: %r at %d\n", Status
, Offset
));
193 Read XHCI runtime register.
195 @param Xhc The XHCI Instance.
196 @param Offset The offset of the runtime register.
198 @return The register content read
203 IN USB_XHCI_INSTANCE
*Xhc
,
210 ASSERT (Xhc
->RTSOff
!= 0);
212 Status
= Xhc
->PciIo
->Mem
.Read (
216 Xhc
->RTSOff
+ Offset
,
221 if (EFI_ERROR (Status
)) {
222 DEBUG ((EFI_D_ERROR
, "XhcReadRuntimeReg: Pci Io Read error - %r at %d\n", Status
, Offset
));
230 Write the data to the XHCI runtime register.
232 @param Xhc The XHCI Instance.
233 @param Offset The offset of the runtime register.
234 @param Data The data to write.
239 IN USB_XHCI_INSTANCE
*Xhc
,
246 ASSERT (Xhc
->RTSOff
!= 0);
248 Status
= Xhc
->PciIo
->Mem
.Write (
252 Xhc
->RTSOff
+ Offset
,
257 if (EFI_ERROR (Status
)) {
258 DEBUG ((EFI_D_ERROR
, "XhcWriteRuntimeReg: Pci Io Write error: %r at %d\n", Status
, Offset
));
263 Read XHCI extended capability register.
265 @param Xhc The XHCI Instance.
266 @param Offset The offset of the extended capability register.
268 @return The register content read
273 IN USB_XHCI_INSTANCE
*Xhc
,
280 ASSERT (Xhc
->ExtCapRegBase
!= 0);
282 Status
= Xhc
->PciIo
->Mem
.Read (
286 Xhc
->ExtCapRegBase
+ Offset
,
291 if (EFI_ERROR (Status
)) {
292 DEBUG ((EFI_D_ERROR
, "XhcReadExtCapReg: Pci Io Read error - %r at %d\n", Status
, Offset
));
300 Write the data to the XHCI extended capability register.
302 @param Xhc The XHCI Instance.
303 @param Offset The offset of the extended capability register.
304 @param Data The data to write.
309 IN USB_XHCI_INSTANCE
*Xhc
,
316 ASSERT (Xhc
->ExtCapRegBase
!= 0);
318 Status
= Xhc
->PciIo
->Mem
.Write (
322 Xhc
->ExtCapRegBase
+ Offset
,
327 if (EFI_ERROR (Status
)) {
328 DEBUG ((EFI_D_ERROR
, "XhcWriteExtCapReg: Pci Io Write error: %r at %d\n", Status
, Offset
));
334 Set one bit of the runtime register while keeping other bits.
336 @param Xhc The XHCI Instance.
337 @param Offset The offset of the runtime register.
338 @param Bit The bit mask of the register to set.
342 XhcSetRuntimeRegBit (
343 IN USB_XHCI_INSTANCE
*Xhc
,
350 Data
= XhcReadRuntimeReg (Xhc
, Offset
);
352 XhcWriteRuntimeReg (Xhc
, Offset
, Data
);
356 Clear one bit of the runtime register while keeping other bits.
358 @param Xhc The XHCI Instance.
359 @param Offset The offset of the runtime register.
360 @param Bit The bit mask of the register to set.
364 XhcClearRuntimeRegBit (
365 IN USB_XHCI_INSTANCE
*Xhc
,
372 Data
= XhcReadRuntimeReg (Xhc
, Offset
);
374 XhcWriteRuntimeReg (Xhc
, Offset
, Data
);
378 Set one bit of the operational register while keeping other bits.
380 @param Xhc The XHCI Instance.
381 @param Offset The offset of the operational register.
382 @param Bit The bit mask of the register to set.
387 IN USB_XHCI_INSTANCE
*Xhc
,
394 Data
= XhcReadOpReg (Xhc
, Offset
);
396 XhcWriteOpReg (Xhc
, Offset
, Data
);
401 Clear one bit of the operational register while keeping other bits.
403 @param Xhc The XHCI Instance.
404 @param Offset The offset of the operational register.
405 @param Bit The bit mask of the register to clear.
410 IN USB_XHCI_INSTANCE
*Xhc
,
417 Data
= XhcReadOpReg (Xhc
, Offset
);
419 XhcWriteOpReg (Xhc
, Offset
, Data
);
423 Wait the operation register's bit as specified by Bit
424 to become set (or clear).
426 @param Xhc The XHCI Instance.
427 @param Offset The offset of the operation register.
428 @param Bit The bit of the register to wait for.
429 @param WaitToSet Wait the bit to set or clear.
430 @param Timeout The time to wait before abort (in millisecond, ms).
432 @retval EFI_SUCCESS The bit successfully changed by host controller.
433 @retval EFI_TIMEOUT The time out occurred.
438 IN USB_XHCI_INSTANCE
*Xhc
,
441 IN BOOLEAN WaitToSet
,
448 Loop
= Timeout
* XHC_1_MILLISECOND
;
450 for (Index
= 0; Index
< Loop
; Index
++) {
451 if (XHC_REG_BIT_IS_SET (Xhc
, Offset
, Bit
) == WaitToSet
) {
455 gBS
->Stall (XHC_1_MICROSECOND
);
464 @param Xhc The XHCI Instance.
468 XhcSetBiosOwnership (
469 IN USB_XHCI_INSTANCE
*Xhc
474 if (Xhc
->UsbLegSupOffset
== 0xFFFFFFFF) {
478 DEBUG ((EFI_D_INFO
, "XhcSetBiosOwnership: called to set BIOS ownership\n"));
480 Buffer
= XhcReadExtCapReg (Xhc
, Xhc
->UsbLegSupOffset
);
481 Buffer
= ((Buffer
& (~USBLEGSP_OS_SEMAPHORE
)) | USBLEGSP_BIOS_SEMAPHORE
);
482 XhcWriteExtCapReg (Xhc
, Xhc
->UsbLegSupOffset
, Buffer
);
488 @param Xhc The XHCI Instance.
492 XhcClearBiosOwnership (
493 IN USB_XHCI_INSTANCE
*Xhc
498 if (Xhc
->UsbLegSupOffset
== 0xFFFFFFFF) {
502 DEBUG ((EFI_D_INFO
, "XhcClearBiosOwnership: called to clear BIOS ownership\n"));
504 Buffer
= XhcReadExtCapReg (Xhc
, Xhc
->UsbLegSupOffset
);
505 Buffer
= ((Buffer
& (~USBLEGSP_BIOS_SEMAPHORE
)) | USBLEGSP_OS_SEMAPHORE
);
506 XhcWriteExtCapReg (Xhc
, Xhc
->UsbLegSupOffset
, Buffer
);
510 Calculate the offset of the XHCI capability.
512 @param Xhc The XHCI Instance.
513 @param CapId The XHCI Capability ID.
515 @return The offset of XHCI legacy support capability register.
519 XhcGetCapabilityAddr (
520 IN USB_XHCI_INSTANCE
*Xhc
,
532 // Check if the extended capability register's capability id is USB Legacy Support.
534 Data
= XhcReadExtCapReg (Xhc
, ExtCapOffset
);
535 if ((Data
& 0xFF) == CapId
) {
539 // If not, then traverse all of the ext capability registers till finding out it.
541 NextExtCapReg
= (UINT8
)((Data
>> 8) & 0xFF);
542 ExtCapOffset
+= (NextExtCapReg
<< 2);
543 } while (NextExtCapReg
!= 0);
549 Whether the XHCI host controller is halted.
551 @param Xhc The XHCI Instance.
553 @retval TRUE The controller is halted.
554 @retval FALSE It isn't halted.
559 IN USB_XHCI_INSTANCE
*Xhc
562 return XHC_REG_BIT_IS_SET (Xhc
, XHC_USBSTS_OFFSET
, XHC_USBSTS_HALT
);
567 Whether system error occurred.
569 @param Xhc The XHCI Instance.
571 @retval TRUE System error happened.
572 @retval FALSE No system error.
577 IN USB_XHCI_INSTANCE
*Xhc
580 return XHC_REG_BIT_IS_SET (Xhc
, XHC_USBSTS_OFFSET
, XHC_USBSTS_HSE
);
584 Set USBCMD Host System Error Enable(HSEE) Bit if PCICMD SERR# Enable Bit is set.
586 The USBCMD HSEE Bit will be reset to default 0 by USBCMD Host Controller Reset(HCRST).
587 This function is to set USBCMD HSEE Bit if PCICMD SERR# Enable Bit is set.
589 @param Xhc The XHCI Instance.
594 IN USB_XHCI_INSTANCE
*Xhc
598 EFI_PCI_IO_PROTOCOL
*PciIo
;
602 Status
= PciIo
->Pci
.Read (
606 sizeof (XhciCmd
) / sizeof (UINT16
),
609 if (!EFI_ERROR (Status
)) {
610 if ((XhciCmd
& EFI_PCI_COMMAND_SERR
) != 0) {
611 XhcSetOpRegBit (Xhc
, XHC_USBCMD_OFFSET
, XHC_USBCMD_HSEE
);
617 Reset the XHCI host controller.
619 @param Xhc The XHCI Instance.
620 @param Timeout Time to wait before abort (in millisecond, ms).
622 @retval EFI_SUCCESS The XHCI host controller is reset.
623 @return Others Failed to reset the XHCI before Timeout.
628 IN USB_XHCI_INSTANCE
*Xhc
,
634 Status
= EFI_SUCCESS
;
636 DEBUG ((EFI_D_INFO
, "XhcResetHC!\n"));
638 // Host can only be reset when it is halt. If not so, halt it
640 if (!XHC_REG_BIT_IS_SET (Xhc
, XHC_USBSTS_OFFSET
, XHC_USBSTS_HALT
)) {
641 Status
= XhcHaltHC (Xhc
, Timeout
);
643 if (EFI_ERROR (Status
)) {
648 if ((Xhc
->DebugCapSupOffset
== 0xFFFFFFFF) || ((XhcReadExtCapReg (Xhc
, Xhc
->DebugCapSupOffset
) & 0xFF) != XHC_CAP_USB_DEBUG
) ||
649 ((XhcReadExtCapReg (Xhc
, Xhc
->DebugCapSupOffset
+ XHC_DC_DCCTRL
) & BIT0
) == 0)) {
650 XhcSetOpRegBit (Xhc
, XHC_USBCMD_OFFSET
, XHC_USBCMD_RESET
);
652 // Some XHCI host controllers require to have extra 1ms delay before accessing any MMIO register during reset.
653 // Otherwise there may have the timeout case happened.
654 // The below is a workaround to solve such problem.
656 gBS
->Stall (XHC_1_MILLISECOND
);
657 Status
= XhcWaitOpRegBit (Xhc
, XHC_USBCMD_OFFSET
, XHC_USBCMD_RESET
, FALSE
, Timeout
);
659 if (!EFI_ERROR (Status
)) {
661 // The USBCMD HSEE Bit will be reset to default 0 by USBCMD HCRST.
662 // Set USBCMD HSEE Bit if PCICMD SERR# Enable Bit is set.
673 Halt the XHCI host controller.
675 @param Xhc The XHCI Instance.
676 @param Timeout Time to wait before abort (in millisecond, ms).
678 @return EFI_SUCCESS The XHCI host controller is halt.
679 @return EFI_TIMEOUT Failed to halt the XHCI before Timeout.
684 IN USB_XHCI_INSTANCE
*Xhc
,
690 XhcClearOpRegBit (Xhc
, XHC_USBCMD_OFFSET
, XHC_USBCMD_RUN
);
691 Status
= XhcWaitOpRegBit (Xhc
, XHC_USBSTS_OFFSET
, XHC_USBSTS_HALT
, TRUE
, Timeout
);
697 Set the XHCI host controller to run.
699 @param Xhc The XHCI Instance.
700 @param Timeout Time to wait before abort (in millisecond, ms).
702 @return EFI_SUCCESS The XHCI host controller is running.
703 @return EFI_TIMEOUT Failed to set the XHCI to run before Timeout.
708 IN USB_XHCI_INSTANCE
*Xhc
,
714 XhcSetOpRegBit (Xhc
, XHC_USBCMD_OFFSET
, XHC_USBCMD_RUN
);
715 Status
= XhcWaitOpRegBit (Xhc
, XHC_USBSTS_OFFSET
, XHC_USBSTS_HALT
, FALSE
, Timeout
);