]>
git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.c
89f073e1d83f89037d7f4b35cae4a77eed48ca39
3 The XHCI register operation routines.
5 Copyright (c) 2011 - 2017, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 Read 1-byte width XHCI capability register.
21 @param Xhc The XHCI Instance.
22 @param Offset The offset of the 1-byte width capability register.
24 @return The register content read.
25 @retval If err, return 0xFF.
30 IN USB_XHCI_INSTANCE
*Xhc
,
37 Status
= Xhc
->PciIo
->Mem
.Read (
46 if (EFI_ERROR (Status
)) {
47 DEBUG ((EFI_D_ERROR
, "XhcReadCapReg: Pci Io read error - %r at %d\n", Status
, Offset
));
55 Read 4-bytes width XHCI capability register.
57 @param Xhc The XHCI Instance.
58 @param Offset The offset of the 4-bytes width capability register.
60 @return The register content read.
61 @retval If err, return 0xFFFFFFFF.
66 IN USB_XHCI_INSTANCE
*Xhc
,
73 Status
= Xhc
->PciIo
->Mem
.Read (
82 if (EFI_ERROR (Status
)) {
83 DEBUG ((EFI_D_ERROR
, "XhcReadCapReg: Pci Io read error - %r at %d\n", Status
, Offset
));
91 Read 4-bytes width XHCI Operational register.
93 @param Xhc The XHCI Instance.
94 @param Offset The offset of the 4-bytes width operational register.
96 @return The register content read.
97 @retval If err, return 0xFFFFFFFF.
102 IN USB_XHCI_INSTANCE
*Xhc
,
109 ASSERT (Xhc
->CapLength
!= 0);
111 Status
= Xhc
->PciIo
->Mem
.Read (
115 Xhc
->CapLength
+ Offset
,
120 if (EFI_ERROR (Status
)) {
121 DEBUG ((EFI_D_ERROR
, "XhcReadOpReg: Pci Io Read error - %r at %d\n", Status
, Offset
));
129 Write the data to the 4-bytes width XHCI operational register.
131 @param Xhc The XHCI Instance.
132 @param Offset The offset of the 4-bytes width operational register.
133 @param Data The data to write.
138 IN USB_XHCI_INSTANCE
*Xhc
,
145 ASSERT (Xhc
->CapLength
!= 0);
147 Status
= Xhc
->PciIo
->Mem
.Write (
151 Xhc
->CapLength
+ Offset
,
156 if (EFI_ERROR (Status
)) {
157 DEBUG ((EFI_D_ERROR
, "XhcWriteOpReg: Pci Io Write error: %r at %d\n", Status
, Offset
));
166 Write the data to the XHCI door bell register.
168 @param Xhc The XHCI Instance.
169 @param Offset The offset of the door bell register.
170 @param Data The data to write.
174 XhcWriteDoorBellReg (
175 IN USB_XHCI_INSTANCE
*Xhc
,
182 ASSERT (Xhc
->DBOff
!= 0);
184 Status
= Xhc
->PciIo
->Mem
.Write (
193 if (EFI_ERROR (Status
)) {
194 DEBUG ((EFI_D_ERROR
, "XhcWriteOpReg: Pci Io Write error: %r at %d\n", Status
, Offset
));
199 Read XHCI runtime register.
201 @param Xhc The XHCI Instance.
202 @param Offset The offset of the runtime register.
204 @return The register content read
209 IN USB_XHCI_INSTANCE
*Xhc
,
216 ASSERT (Xhc
->RTSOff
!= 0);
218 Status
= Xhc
->PciIo
->Mem
.Read (
222 Xhc
->RTSOff
+ Offset
,
227 if (EFI_ERROR (Status
)) {
228 DEBUG ((EFI_D_ERROR
, "XhcReadRuntimeReg: Pci Io Read error - %r at %d\n", Status
, Offset
));
236 Write the data to the XHCI runtime register.
238 @param Xhc The XHCI Instance.
239 @param Offset The offset of the runtime register.
240 @param Data The data to write.
245 IN USB_XHCI_INSTANCE
*Xhc
,
252 ASSERT (Xhc
->RTSOff
!= 0);
254 Status
= Xhc
->PciIo
->Mem
.Write (
258 Xhc
->RTSOff
+ Offset
,
263 if (EFI_ERROR (Status
)) {
264 DEBUG ((EFI_D_ERROR
, "XhcWriteRuntimeReg: Pci Io Write error: %r at %d\n", Status
, Offset
));
269 Read XHCI extended capability register.
271 @param Xhc The XHCI Instance.
272 @param Offset The offset of the extended capability register.
274 @return The register content read
279 IN USB_XHCI_INSTANCE
*Xhc
,
286 ASSERT (Xhc
->ExtCapRegBase
!= 0);
288 Status
= Xhc
->PciIo
->Mem
.Read (
292 Xhc
->ExtCapRegBase
+ Offset
,
297 if (EFI_ERROR (Status
)) {
298 DEBUG ((EFI_D_ERROR
, "XhcReadExtCapReg: Pci Io Read error - %r at %d\n", Status
, Offset
));
306 Write the data to the XHCI extended capability register.
308 @param Xhc The XHCI Instance.
309 @param Offset The offset of the extended capability register.
310 @param Data The data to write.
315 IN USB_XHCI_INSTANCE
*Xhc
,
322 ASSERT (Xhc
->ExtCapRegBase
!= 0);
324 Status
= Xhc
->PciIo
->Mem
.Write (
328 Xhc
->ExtCapRegBase
+ Offset
,
333 if (EFI_ERROR (Status
)) {
334 DEBUG ((EFI_D_ERROR
, "XhcWriteExtCapReg: Pci Io Write error: %r at %d\n", Status
, Offset
));
340 Set one bit of the runtime register while keeping other bits.
342 @param Xhc The XHCI Instance.
343 @param Offset The offset of the runtime register.
344 @param Bit The bit mask of the register to set.
348 XhcSetRuntimeRegBit (
349 IN USB_XHCI_INSTANCE
*Xhc
,
356 Data
= XhcReadRuntimeReg (Xhc
, Offset
);
358 XhcWriteRuntimeReg (Xhc
, Offset
, Data
);
362 Clear one bit of the runtime register while keeping other bits.
364 @param Xhc The XHCI Instance.
365 @param Offset The offset of the runtime register.
366 @param Bit The bit mask of the register to set.
370 XhcClearRuntimeRegBit (
371 IN USB_XHCI_INSTANCE
*Xhc
,
378 Data
= XhcReadRuntimeReg (Xhc
, Offset
);
380 XhcWriteRuntimeReg (Xhc
, Offset
, Data
);
384 Set one bit of the operational register while keeping other bits.
386 @param Xhc The XHCI Instance.
387 @param Offset The offset of the operational register.
388 @param Bit The bit mask of the register to set.
393 IN USB_XHCI_INSTANCE
*Xhc
,
400 Data
= XhcReadOpReg (Xhc
, Offset
);
402 XhcWriteOpReg (Xhc
, Offset
, Data
);
407 Clear one bit of the operational register while keeping other bits.
409 @param Xhc The XHCI Instance.
410 @param Offset The offset of the operational register.
411 @param Bit The bit mask of the register to clear.
416 IN USB_XHCI_INSTANCE
*Xhc
,
423 Data
= XhcReadOpReg (Xhc
, Offset
);
425 XhcWriteOpReg (Xhc
, Offset
, Data
);
429 Wait the operation register's bit as specified by Bit
430 to become set (or clear).
432 @param Xhc The XHCI Instance.
433 @param Offset The offset of the operation register.
434 @param Bit The bit of the register to wait for.
435 @param WaitToSet Wait the bit to set or clear.
436 @param Timeout The time to wait before abort (in millisecond, ms).
438 @retval EFI_SUCCESS The bit successfully changed by host controller.
439 @retval EFI_TIMEOUT The time out occurred.
444 IN USB_XHCI_INSTANCE
*Xhc
,
447 IN BOOLEAN WaitToSet
,
454 Loop
= Timeout
* XHC_1_MILLISECOND
;
456 for (Index
= 0; Index
< Loop
; Index
++) {
457 if (XHC_REG_BIT_IS_SET (Xhc
, Offset
, Bit
) == WaitToSet
) {
461 gBS
->Stall (XHC_1_MICROSECOND
);
470 @param Xhc The XHCI Instance.
474 XhcSetBiosOwnership (
475 IN USB_XHCI_INSTANCE
*Xhc
480 if (Xhc
->UsbLegSupOffset
== 0xFFFFFFFF) {
484 DEBUG ((EFI_D_INFO
, "XhcSetBiosOwnership: called to set BIOS ownership\n"));
486 Buffer
= XhcReadExtCapReg (Xhc
, Xhc
->UsbLegSupOffset
);
487 Buffer
= ((Buffer
& (~USBLEGSP_OS_SEMAPHORE
)) | USBLEGSP_BIOS_SEMAPHORE
);
488 XhcWriteExtCapReg (Xhc
, Xhc
->UsbLegSupOffset
, Buffer
);
494 @param Xhc The XHCI Instance.
498 XhcClearBiosOwnership (
499 IN USB_XHCI_INSTANCE
*Xhc
504 if (Xhc
->UsbLegSupOffset
== 0xFFFFFFFF) {
508 DEBUG ((EFI_D_INFO
, "XhcClearBiosOwnership: called to clear BIOS ownership\n"));
510 Buffer
= XhcReadExtCapReg (Xhc
, Xhc
->UsbLegSupOffset
);
511 Buffer
= ((Buffer
& (~USBLEGSP_BIOS_SEMAPHORE
)) | USBLEGSP_OS_SEMAPHORE
);
512 XhcWriteExtCapReg (Xhc
, Xhc
->UsbLegSupOffset
, Buffer
);
516 Calculate the offset of the XHCI capability.
518 @param Xhc The XHCI Instance.
519 @param CapId The XHCI Capability ID.
521 @return The offset of XHCI legacy support capability register.
525 XhcGetCapabilityAddr (
526 IN USB_XHCI_INSTANCE
*Xhc
,
538 // Check if the extended capability register's capability id is USB Legacy Support.
540 Data
= XhcReadExtCapReg (Xhc
, ExtCapOffset
);
541 if ((Data
& 0xFF) == CapId
) {
545 // If not, then traverse all of the ext capability registers till finding out it.
547 NextExtCapReg
= (UINT8
)((Data
>> 8) & 0xFF);
548 ExtCapOffset
+= (NextExtCapReg
<< 2);
549 } while (NextExtCapReg
!= 0);
555 Whether the XHCI host controller is halted.
557 @param Xhc The XHCI Instance.
559 @retval TRUE The controller is halted.
560 @retval FALSE It isn't halted.
565 IN USB_XHCI_INSTANCE
*Xhc
568 return XHC_REG_BIT_IS_SET (Xhc
, XHC_USBSTS_OFFSET
, XHC_USBSTS_HALT
);
573 Whether system error occurred.
575 @param Xhc The XHCI Instance.
577 @retval TRUE System error happened.
578 @retval FALSE No system error.
583 IN USB_XHCI_INSTANCE
*Xhc
586 return XHC_REG_BIT_IS_SET (Xhc
, XHC_USBSTS_OFFSET
, XHC_USBSTS_HSE
);
590 Set USBCMD Host System Error Enable(HSEE) Bit if PCICMD SERR# Enable Bit is set.
592 The USBCMD HSEE Bit will be reset to default 0 by USBCMD Host Controller Reset(HCRST).
593 This function is to set USBCMD HSEE Bit if PCICMD SERR# Enable Bit is set.
595 @param Xhc The XHCI Instance.
600 IN USB_XHCI_INSTANCE
*Xhc
604 EFI_PCI_IO_PROTOCOL
*PciIo
;
608 Status
= PciIo
->Pci
.Read (
615 if (!EFI_ERROR (Status
)) {
616 if ((XhciCmd
& EFI_PCI_COMMAND_SERR
) != 0) {
617 XhcSetOpRegBit (Xhc
, XHC_USBCMD_OFFSET
, XHC_USBCMD_HSEE
);
623 Reset the XHCI host controller.
625 @param Xhc The XHCI Instance.
626 @param Timeout Time to wait before abort (in millisecond, ms).
628 @retval EFI_SUCCESS The XHCI host controller is reset.
629 @return Others Failed to reset the XHCI before Timeout.
634 IN USB_XHCI_INSTANCE
*Xhc
,
640 Status
= EFI_SUCCESS
;
642 DEBUG ((EFI_D_INFO
, "XhcResetHC!\n"));
644 // Host can only be reset when it is halt. If not so, halt it
646 if (!XHC_REG_BIT_IS_SET (Xhc
, XHC_USBSTS_OFFSET
, XHC_USBSTS_HALT
)) {
647 Status
= XhcHaltHC (Xhc
, Timeout
);
649 if (EFI_ERROR (Status
)) {
654 if ((Xhc
->DebugCapSupOffset
== 0xFFFFFFFF) || ((XhcReadExtCapReg (Xhc
, Xhc
->DebugCapSupOffset
) & 0xFF) != XHC_CAP_USB_DEBUG
) ||
655 ((XhcReadExtCapReg (Xhc
, Xhc
->DebugCapSupOffset
+ XHC_DC_DCCTRL
) & BIT0
) == 0)) {
656 XhcSetOpRegBit (Xhc
, XHC_USBCMD_OFFSET
, XHC_USBCMD_RESET
);
658 // Some XHCI host controllers require to have extra 1ms delay before accessing any MMIO register during reset.
659 // Otherwise there may have the timeout case happened.
660 // The below is a workaround to solve such problem.
662 gBS
->Stall (XHC_1_MILLISECOND
);
663 Status
= XhcWaitOpRegBit (Xhc
, XHC_USBCMD_OFFSET
, XHC_USBCMD_RESET
, FALSE
, Timeout
);
665 if (!EFI_ERROR (Status
)) {
667 // The USBCMD HSEE Bit will be reset to default 0 by USBCMD HCRST.
668 // Set USBCMD HSEE Bit if PCICMD SERR# Enable Bit is set.
679 Halt the XHCI host controller.
681 @param Xhc The XHCI Instance.
682 @param Timeout Time to wait before abort (in millisecond, ms).
684 @return EFI_SUCCESS The XHCI host controller is halt.
685 @return EFI_TIMEOUT Failed to halt the XHCI before Timeout.
690 IN USB_XHCI_INSTANCE
*Xhc
,
696 XhcClearOpRegBit (Xhc
, XHC_USBCMD_OFFSET
, XHC_USBCMD_RUN
);
697 Status
= XhcWaitOpRegBit (Xhc
, XHC_USBSTS_OFFSET
, XHC_USBSTS_HALT
, TRUE
, Timeout
);
703 Set the XHCI host controller to run.
705 @param Xhc The XHCI Instance.
706 @param Timeout Time to wait before abort (in millisecond, ms).
708 @return EFI_SUCCESS The XHCI host controller is running.
709 @return EFI_TIMEOUT Failed to set the XHCI to run before Timeout.
714 IN USB_XHCI_INSTANCE
*Xhc
,
720 XhcSetOpRegBit (Xhc
, XHC_USBCMD_OFFSET
, XHC_USBCMD_RUN
);
721 Status
= XhcWaitOpRegBit (Xhc
, XHC_USBSTS_OFFSET
, XHC_USBSTS_HALT
, FALSE
, Timeout
);