]>
git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.c
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.
434 @retval EFI_OUT_OF_RESOURCES Memory for the timer event could not be allocated.
439 IN USB_XHCI_INSTANCE
*Xhc
,
442 IN BOOLEAN WaitToSet
,
447 EFI_EVENT TimeoutEvent
;
455 Status
= gBS
->CreateEvent (
463 if (EFI_ERROR(Status
)) {
467 Status
= gBS
->SetTimer (TimeoutEvent
,
469 EFI_TIMER_PERIOD_MILLISECONDS(Timeout
));
471 if (EFI_ERROR(Status
)) {
476 if (XHC_REG_BIT_IS_SET (Xhc
, Offset
, Bit
) == WaitToSet
) {
477 Status
= EFI_SUCCESS
;
481 gBS
->Stall (XHC_1_MICROSECOND
);
482 } while (EFI_ERROR(gBS
->CheckEvent (TimeoutEvent
)));
484 Status
= EFI_TIMEOUT
;
487 if (TimeoutEvent
!= NULL
) {
488 gBS
->CloseEvent (TimeoutEvent
);
497 @param Xhc The XHCI Instance.
501 XhcSetBiosOwnership (
502 IN USB_XHCI_INSTANCE
*Xhc
507 if (Xhc
->UsbLegSupOffset
== 0xFFFFFFFF) {
511 DEBUG ((EFI_D_INFO
, "XhcSetBiosOwnership: called to set BIOS ownership\n"));
513 Buffer
= XhcReadExtCapReg (Xhc
, Xhc
->UsbLegSupOffset
);
514 Buffer
= ((Buffer
& (~USBLEGSP_OS_SEMAPHORE
)) | USBLEGSP_BIOS_SEMAPHORE
);
515 XhcWriteExtCapReg (Xhc
, Xhc
->UsbLegSupOffset
, Buffer
);
521 @param Xhc The XHCI Instance.
525 XhcClearBiosOwnership (
526 IN USB_XHCI_INSTANCE
*Xhc
531 if (Xhc
->UsbLegSupOffset
== 0xFFFFFFFF) {
535 DEBUG ((EFI_D_INFO
, "XhcClearBiosOwnership: called to clear BIOS ownership\n"));
537 Buffer
= XhcReadExtCapReg (Xhc
, Xhc
->UsbLegSupOffset
);
538 Buffer
= ((Buffer
& (~USBLEGSP_BIOS_SEMAPHORE
)) | USBLEGSP_OS_SEMAPHORE
);
539 XhcWriteExtCapReg (Xhc
, Xhc
->UsbLegSupOffset
, Buffer
);
543 Calculate the offset of the XHCI capability.
545 @param Xhc The XHCI Instance.
546 @param CapId The XHCI Capability ID.
548 @return The offset of XHCI legacy support capability register.
552 XhcGetCapabilityAddr (
553 IN USB_XHCI_INSTANCE
*Xhc
,
565 // Check if the extended capability register's capability id is USB Legacy Support.
567 Data
= XhcReadExtCapReg (Xhc
, ExtCapOffset
);
568 if ((Data
& 0xFF) == CapId
) {
572 // If not, then traverse all of the ext capability registers till finding out it.
574 NextExtCapReg
= (UINT8
)((Data
>> 8) & 0xFF);
575 ExtCapOffset
+= (NextExtCapReg
<< 2);
576 } while (NextExtCapReg
!= 0);
582 Whether the XHCI host controller is halted.
584 @param Xhc The XHCI Instance.
586 @retval TRUE The controller is halted.
587 @retval FALSE It isn't halted.
592 IN USB_XHCI_INSTANCE
*Xhc
595 return XHC_REG_BIT_IS_SET (Xhc
, XHC_USBSTS_OFFSET
, XHC_USBSTS_HALT
);
600 Whether system error occurred.
602 @param Xhc The XHCI Instance.
604 @retval TRUE System error happened.
605 @retval FALSE No system error.
610 IN USB_XHCI_INSTANCE
*Xhc
613 return XHC_REG_BIT_IS_SET (Xhc
, XHC_USBSTS_OFFSET
, XHC_USBSTS_HSE
);
617 Set USBCMD Host System Error Enable(HSEE) Bit if PCICMD SERR# Enable Bit is set.
619 The USBCMD HSEE Bit will be reset to default 0 by USBCMD Host Controller Reset(HCRST).
620 This function is to set USBCMD HSEE Bit if PCICMD SERR# Enable Bit is set.
622 @param Xhc The XHCI Instance.
627 IN USB_XHCI_INSTANCE
*Xhc
631 EFI_PCI_IO_PROTOCOL
*PciIo
;
635 Status
= PciIo
->Pci
.Read (
639 sizeof (XhciCmd
) / sizeof (UINT16
),
642 if (!EFI_ERROR (Status
)) {
643 if ((XhciCmd
& EFI_PCI_COMMAND_SERR
) != 0) {
644 XhcSetOpRegBit (Xhc
, XHC_USBCMD_OFFSET
, XHC_USBCMD_HSEE
);
650 Reset the XHCI host controller.
652 @param Xhc The XHCI Instance.
653 @param Timeout Time to wait before abort (in millisecond, ms).
655 @retval EFI_SUCCESS The XHCI host controller is reset.
656 @return Others Failed to reset the XHCI before Timeout.
661 IN USB_XHCI_INSTANCE
*Xhc
,
667 Status
= EFI_SUCCESS
;
669 DEBUG ((EFI_D_INFO
, "XhcResetHC!\n"));
671 // Host can only be reset when it is halt. If not so, halt it
673 if (!XHC_REG_BIT_IS_SET (Xhc
, XHC_USBSTS_OFFSET
, XHC_USBSTS_HALT
)) {
674 Status
= XhcHaltHC (Xhc
, Timeout
);
676 if (EFI_ERROR (Status
)) {
681 if ((Xhc
->DebugCapSupOffset
== 0xFFFFFFFF) || ((XhcReadExtCapReg (Xhc
, Xhc
->DebugCapSupOffset
) & 0xFF) != XHC_CAP_USB_DEBUG
) ||
682 ((XhcReadExtCapReg (Xhc
, Xhc
->DebugCapSupOffset
+ XHC_DC_DCCTRL
) & BIT0
) == 0)) {
683 XhcSetOpRegBit (Xhc
, XHC_USBCMD_OFFSET
, XHC_USBCMD_RESET
);
685 // Some XHCI host controllers require to have extra 1ms delay before accessing any MMIO register during reset.
686 // Otherwise there may have the timeout case happened.
687 // The below is a workaround to solve such problem.
689 gBS
->Stall (XHC_1_MILLISECOND
);
690 Status
= XhcWaitOpRegBit (Xhc
, XHC_USBCMD_OFFSET
, XHC_USBCMD_RESET
, FALSE
, Timeout
);
692 if (!EFI_ERROR (Status
)) {
694 // The USBCMD HSEE Bit will be reset to default 0 by USBCMD HCRST.
695 // Set USBCMD HSEE Bit if PCICMD SERR# Enable Bit is set.
706 Halt the XHCI host controller.
708 @param Xhc The XHCI Instance.
709 @param Timeout Time to wait before abort (in millisecond, ms).
711 @return EFI_SUCCESS The XHCI host controller is halt.
712 @return EFI_TIMEOUT Failed to halt the XHCI before Timeout.
717 IN USB_XHCI_INSTANCE
*Xhc
,
723 XhcClearOpRegBit (Xhc
, XHC_USBCMD_OFFSET
, XHC_USBCMD_RUN
);
724 Status
= XhcWaitOpRegBit (Xhc
, XHC_USBSTS_OFFSET
, XHC_USBSTS_HALT
, TRUE
, Timeout
);
730 Set the XHCI host controller to run.
732 @param Xhc The XHCI Instance.
733 @param Timeout Time to wait before abort (in millisecond, ms).
735 @return EFI_SUCCESS The XHCI host controller is running.
736 @return EFI_TIMEOUT Failed to set the XHCI to run before Timeout.
741 IN USB_XHCI_INSTANCE
*Xhc
,
747 XhcSetOpRegBit (Xhc
, XHC_USBCMD_OFFSET
, XHC_USBCMD_RUN
);
748 Status
= XhcWaitOpRegBit (Xhc
, XHC_USBSTS_OFFSET
, XHC_USBSTS_HALT
, FALSE
, Timeout
);