123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946 |
- /** @file
- The XHCI register operation routines.
- Copyright (c) 2011 - 2017, Intel Corporation. All rights reserved.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
- **/
- #include "Xhci.h"
- /**
- Read 1-byte width XHCI capability register.
- @param Xhc The XHCI Instance.
- @param Offset The offset of the 1-byte width capability register.
- @return The register content read.
- @retval If err, return 0xFF.
- **/
- UINT8
- XhcReadCapReg8 (
- IN USB_XHCI_INSTANCE *Xhc,
- IN UINT32 Offset
- )
- {
- UINT8 Data;
- EFI_STATUS Status;
- Status = Xhc->PciIo->Mem.Read (
- Xhc->PciIo,
- EfiPciIoWidthUint8,
- XHC_BAR_INDEX,
- (UINT64)Offset,
- 1,
- &Data
- );
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "XhcReadCapReg: Pci Io read error - %r at %d\n", Status, Offset));
- Data = 0xFF;
- }
- return Data;
- }
- /**
- Read 4-bytes width XHCI capability register.
- @param Xhc The XHCI Instance.
- @param Offset The offset of the 4-bytes width capability register.
- @return The register content read.
- @retval If err, return 0xFFFFFFFF.
- **/
- UINT32
- XhcReadCapReg (
- IN USB_XHCI_INSTANCE *Xhc,
- IN UINT32 Offset
- )
- {
- UINT32 Data;
- EFI_STATUS Status;
- Status = Xhc->PciIo->Mem.Read (
- Xhc->PciIo,
- EfiPciIoWidthUint32,
- XHC_BAR_INDEX,
- (UINT64)Offset,
- 1,
- &Data
- );
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "XhcReadCapReg: Pci Io read error - %r at %d\n", Status, Offset));
- Data = 0xFFFFFFFF;
- }
- return Data;
- }
- /**
- Read 4-bytes width XHCI Operational register.
- @param Xhc The XHCI Instance.
- @param Offset The offset of the 4-bytes width operational register.
- @return The register content read.
- @retval If err, return 0xFFFFFFFF.
- **/
- UINT32
- XhcReadOpReg (
- IN USB_XHCI_INSTANCE *Xhc,
- IN UINT32 Offset
- )
- {
- UINT32 Data;
- EFI_STATUS Status;
- ASSERT (Xhc->CapLength != 0);
- Status = Xhc->PciIo->Mem.Read (
- Xhc->PciIo,
- EfiPciIoWidthUint32,
- XHC_BAR_INDEX,
- Xhc->CapLength + Offset,
- 1,
- &Data
- );
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "XhcReadOpReg: Pci Io Read error - %r at %d\n", Status, Offset));
- Data = 0xFFFFFFFF;
- }
- return Data;
- }
- /**
- Write the data to the 4-bytes width XHCI operational register.
- @param Xhc The XHCI Instance.
- @param Offset The offset of the 4-bytes width operational register.
- @param Data The data to write.
- **/
- VOID
- XhcWriteOpReg (
- IN USB_XHCI_INSTANCE *Xhc,
- IN UINT32 Offset,
- IN UINT32 Data
- )
- {
- EFI_STATUS Status;
- ASSERT (Xhc->CapLength != 0);
- Status = Xhc->PciIo->Mem.Write (
- Xhc->PciIo,
- EfiPciIoWidthUint32,
- XHC_BAR_INDEX,
- Xhc->CapLength + Offset,
- 1,
- &Data
- );
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "XhcWriteOpReg: Pci Io Write error: %r at %d\n", Status, Offset));
- }
- }
- /**
- Write the data to the XHCI door bell register.
- @param Xhc The XHCI Instance.
- @param Offset The offset of the door bell register.
- @param Data The data to write.
- **/
- VOID
- XhcWriteDoorBellReg (
- IN USB_XHCI_INSTANCE *Xhc,
- IN UINT32 Offset,
- IN UINT32 Data
- )
- {
- EFI_STATUS Status;
- ASSERT (Xhc->DBOff != 0);
- Status = Xhc->PciIo->Mem.Write (
- Xhc->PciIo,
- EfiPciIoWidthUint32,
- XHC_BAR_INDEX,
- Xhc->DBOff + Offset,
- 1,
- &Data
- );
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "XhcWriteOpReg: Pci Io Write error: %r at %d\n", Status, Offset));
- }
- }
- /**
- Read XHCI runtime register.
- @param Xhc The XHCI Instance.
- @param Offset The offset of the runtime register.
- @return The register content read
- **/
- UINT32
- XhcReadRuntimeReg (
- IN USB_XHCI_INSTANCE *Xhc,
- IN UINT32 Offset
- )
- {
- UINT32 Data;
- EFI_STATUS Status;
- ASSERT (Xhc->RTSOff != 0);
- Status = Xhc->PciIo->Mem.Read (
- Xhc->PciIo,
- EfiPciIoWidthUint32,
- XHC_BAR_INDEX,
- Xhc->RTSOff + Offset,
- 1,
- &Data
- );
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "XhcReadRuntimeReg: Pci Io Read error - %r at %d\n", Status, Offset));
- Data = 0xFFFFFFFF;
- }
- return Data;
- }
- /**
- Write the data to the XHCI runtime register.
- @param Xhc The XHCI Instance.
- @param Offset The offset of the runtime register.
- @param Data The data to write.
- **/
- VOID
- XhcWriteRuntimeReg (
- IN USB_XHCI_INSTANCE *Xhc,
- IN UINT32 Offset,
- IN UINT32 Data
- )
- {
- EFI_STATUS Status;
- ASSERT (Xhc->RTSOff != 0);
- Status = Xhc->PciIo->Mem.Write (
- Xhc->PciIo,
- EfiPciIoWidthUint32,
- XHC_BAR_INDEX,
- Xhc->RTSOff + Offset,
- 1,
- &Data
- );
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "XhcWriteRuntimeReg: Pci Io Write error: %r at %d\n", Status, Offset));
- }
- }
- /**
- Read XHCI extended capability register.
- @param Xhc The XHCI Instance.
- @param Offset The offset of the extended capability register.
- @return The register content read
- **/
- UINT32
- XhcReadExtCapReg (
- IN USB_XHCI_INSTANCE *Xhc,
- IN UINT32 Offset
- )
- {
- UINT32 Data;
- EFI_STATUS Status;
- ASSERT (Xhc->ExtCapRegBase != 0);
- Status = Xhc->PciIo->Mem.Read (
- Xhc->PciIo,
- EfiPciIoWidthUint32,
- XHC_BAR_INDEX,
- Xhc->ExtCapRegBase + Offset,
- 1,
- &Data
- );
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "XhcReadExtCapReg: Pci Io Read error - %r at %d\n", Status, Offset));
- Data = 0xFFFFFFFF;
- }
- return Data;
- }
- /**
- Write the data to the XHCI extended capability register.
- @param Xhc The XHCI Instance.
- @param Offset The offset of the extended capability register.
- @param Data The data to write.
- **/
- VOID
- XhcWriteExtCapReg (
- IN USB_XHCI_INSTANCE *Xhc,
- IN UINT32 Offset,
- IN UINT32 Data
- )
- {
- EFI_STATUS Status;
- ASSERT (Xhc->ExtCapRegBase != 0);
- Status = Xhc->PciIo->Mem.Write (
- Xhc->PciIo,
- EfiPciIoWidthUint32,
- XHC_BAR_INDEX,
- Xhc->ExtCapRegBase + Offset,
- 1,
- &Data
- );
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "XhcWriteExtCapReg: Pci Io Write error: %r at %d\n", Status, Offset));
- }
- }
- /**
- Set one bit of the runtime register while keeping other bits.
- @param Xhc The XHCI Instance.
- @param Offset The offset of the runtime register.
- @param Bit The bit mask of the register to set.
- **/
- VOID
- XhcSetRuntimeRegBit (
- IN USB_XHCI_INSTANCE *Xhc,
- IN UINT32 Offset,
- IN UINT32 Bit
- )
- {
- UINT32 Data;
- Data = XhcReadRuntimeReg (Xhc, Offset);
- Data |= Bit;
- XhcWriteRuntimeReg (Xhc, Offset, Data);
- }
- /**
- Clear one bit of the runtime register while keeping other bits.
- @param Xhc The XHCI Instance.
- @param Offset The offset of the runtime register.
- @param Bit The bit mask of the register to set.
- **/
- VOID
- XhcClearRuntimeRegBit (
- IN USB_XHCI_INSTANCE *Xhc,
- IN UINT32 Offset,
- IN UINT32 Bit
- )
- {
- UINT32 Data;
- Data = XhcReadRuntimeReg (Xhc, Offset);
- Data &= ~Bit;
- XhcWriteRuntimeReg (Xhc, Offset, Data);
- }
- /**
- Set one bit of the operational register while keeping other bits.
- @param Xhc The XHCI Instance.
- @param Offset The offset of the operational register.
- @param Bit The bit mask of the register to set.
- **/
- VOID
- XhcSetOpRegBit (
- IN USB_XHCI_INSTANCE *Xhc,
- IN UINT32 Offset,
- IN UINT32 Bit
- )
- {
- UINT32 Data;
- Data = XhcReadOpReg (Xhc, Offset);
- Data |= Bit;
- XhcWriteOpReg (Xhc, Offset, Data);
- }
- /**
- Clear one bit of the operational register while keeping other bits.
- @param Xhc The XHCI Instance.
- @param Offset The offset of the operational register.
- @param Bit The bit mask of the register to clear.
- **/
- VOID
- XhcClearOpRegBit (
- IN USB_XHCI_INSTANCE *Xhc,
- IN UINT32 Offset,
- IN UINT32 Bit
- )
- {
- UINT32 Data;
- Data = XhcReadOpReg (Xhc, Offset);
- Data &= ~Bit;
- XhcWriteOpReg (Xhc, Offset, Data);
- }
- /**
- Wait the operation register's bit as specified by Bit
- to become set (or clear).
- @param Xhc The XHCI Instance.
- @param Offset The offset of the operation register.
- @param Bit The bit of the register to wait for.
- @param WaitToSet Wait the bit to set or clear.
- @param Timeout The time to wait before abort (in millisecond, ms).
- @retval EFI_SUCCESS The bit successfully changed by host controller.
- @retval EFI_TIMEOUT The time out occurred.
- @retval EFI_OUT_OF_RESOURCES Memory for the timer event could not be allocated.
- **/
- EFI_STATUS
- XhcWaitOpRegBit (
- IN USB_XHCI_INSTANCE *Xhc,
- IN UINT32 Offset,
- IN UINT32 Bit,
- IN BOOLEAN WaitToSet,
- IN UINT32 Timeout
- )
- {
- EFI_STATUS Status;
- EFI_EVENT TimeoutEvent;
- TimeoutEvent = NULL;
- if (Timeout == 0) {
- return EFI_TIMEOUT;
- }
- Status = gBS->CreateEvent (
- EVT_TIMER,
- TPL_CALLBACK,
- NULL,
- NULL,
- &TimeoutEvent
- );
- if (EFI_ERROR (Status)) {
- goto DONE;
- }
- Status = gBS->SetTimer (
- TimeoutEvent,
- TimerRelative,
- EFI_TIMER_PERIOD_MILLISECONDS (Timeout)
- );
- if (EFI_ERROR (Status)) {
- goto DONE;
- }
- do {
- if (XHC_REG_BIT_IS_SET (Xhc, Offset, Bit) == WaitToSet) {
- Status = EFI_SUCCESS;
- goto DONE;
- }
- gBS->Stall (XHC_1_MICROSECOND);
- } while (EFI_ERROR (gBS->CheckEvent (TimeoutEvent)));
- Status = EFI_TIMEOUT;
- DONE:
- if (TimeoutEvent != NULL) {
- gBS->CloseEvent (TimeoutEvent);
- }
- return Status;
- }
- /**
- Set Bios Ownership
- @param Xhc The XHCI Instance.
- **/
- VOID
- XhcSetBiosOwnership (
- IN USB_XHCI_INSTANCE *Xhc
- )
- {
- UINT32 Buffer;
- if (Xhc->UsbLegSupOffset == 0xFFFFFFFF) {
- return;
- }
- DEBUG ((DEBUG_INFO, "XhcSetBiosOwnership: called to set BIOS ownership\n"));
- Buffer = XhcReadExtCapReg (Xhc, Xhc->UsbLegSupOffset);
- Buffer = ((Buffer & (~USBLEGSP_OS_SEMAPHORE)) | USBLEGSP_BIOS_SEMAPHORE);
- XhcWriteExtCapReg (Xhc, Xhc->UsbLegSupOffset, Buffer);
- }
- /**
- Clear Bios Ownership
- @param Xhc The XHCI Instance.
- **/
- VOID
- XhcClearBiosOwnership (
- IN USB_XHCI_INSTANCE *Xhc
- )
- {
- UINT32 Buffer;
- if (Xhc->UsbLegSupOffset == 0xFFFFFFFF) {
- return;
- }
- DEBUG ((DEBUG_INFO, "XhcClearBiosOwnership: called to clear BIOS ownership\n"));
- Buffer = XhcReadExtCapReg (Xhc, Xhc->UsbLegSupOffset);
- Buffer = ((Buffer & (~USBLEGSP_BIOS_SEMAPHORE)) | USBLEGSP_OS_SEMAPHORE);
- XhcWriteExtCapReg (Xhc, Xhc->UsbLegSupOffset, Buffer);
- }
- /**
- Calculate the offset of the XHCI capability.
- @param Xhc The XHCI Instance.
- @param CapId The XHCI Capability ID.
- @return The offset of XHCI legacy support capability register.
- **/
- UINT32
- XhcGetCapabilityAddr (
- IN USB_XHCI_INSTANCE *Xhc,
- IN UINT8 CapId
- )
- {
- UINT32 ExtCapOffset;
- UINT8 NextExtCapReg;
- UINT32 Data;
- ExtCapOffset = 0;
- do {
- //
- // Check if the extended capability register's capability id is USB Legacy Support.
- //
- Data = XhcReadExtCapReg (Xhc, ExtCapOffset);
- if ((Data & 0xFF) == CapId) {
- return ExtCapOffset;
- }
- //
- // If not, then traverse all of the ext capability registers till finding out it.
- //
- NextExtCapReg = (UINT8)((Data >> 8) & 0xFF);
- ExtCapOffset += (NextExtCapReg << 2);
- } while (NextExtCapReg != 0);
- return 0xFFFFFFFF;
- }
- /**
- Calculate the offset of the xHCI Supported Protocol Capability.
- @param Xhc The XHCI Instance.
- @param MajorVersion The USB Major Version in xHCI Support Protocol Capability Field
- @return The offset of xHCI Supported Protocol capability register.
- **/
- UINT32
- XhcGetSupportedProtocolCapabilityAddr (
- IN USB_XHCI_INSTANCE *Xhc,
- IN UINT8 MajorVersion
- )
- {
- UINT32 ExtCapOffset;
- UINT8 NextExtCapReg;
- UINT32 Data;
- UINT32 NameString;
- XHC_SUPPORTED_PROTOCOL_DW0 UsbSupportDw0;
- if (Xhc == NULL) {
- return 0;
- }
- ExtCapOffset = 0;
- do {
- //
- // Check if the extended capability register's capability id is USB Legacy Support.
- //
- Data = XhcReadExtCapReg (Xhc, ExtCapOffset);
- UsbSupportDw0.Dword = Data;
- if ((Data & 0xFF) == XHC_CAP_USB_SUPPORTED_PROTOCOL) {
- if (UsbSupportDw0.Data.RevMajor == MajorVersion) {
- NameString = XhcReadExtCapReg (Xhc, ExtCapOffset + XHC_SUPPORTED_PROTOCOL_NAME_STRING_OFFSET);
- if (NameString == XHC_SUPPORTED_PROTOCOL_NAME_STRING_VALUE) {
- //
- // Ensure Name String field is xHCI supported protocols in xHCI Supported Protocol Capability Offset 04h
- //
- return ExtCapOffset;
- }
- }
- }
- //
- // If not, then traverse all of the ext capability registers till finding out it.
- //
- NextExtCapReg = (UINT8)((Data >> 8) & 0xFF);
- ExtCapOffset += (NextExtCapReg << 2);
- } while (NextExtCapReg != 0);
- return 0xFFFFFFFF;
- }
- /**
- Find PortSpeed value match Protocol Speed ID Value (PSIV).
- @param Xhc The XHCI Instance.
- @param ExtCapOffset The USB Major Version in xHCI Support Protocol Capability Field
- @param PortSpeed The Port Speed Field in USB PortSc register
- @param PortNumber The Port Number (0-indexed)
- @return The Protocol Speed ID (PSI) from xHCI Supported Protocol capability register.
- **/
- UINT32
- XhciPsivGetPsid (
- IN USB_XHCI_INSTANCE *Xhc,
- IN UINT32 ExtCapOffset,
- IN UINT8 PortSpeed,
- IN UINT8 PortNumber
- )
- {
- XHC_SUPPORTED_PROTOCOL_DW2 PortId;
- XHC_SUPPORTED_PROTOCOL_PROTOCOL_SPEED_ID Reg;
- UINT32 Count;
- UINT32 MinPortIndex;
- UINT32 MaxPortIndex;
- if ((Xhc == NULL) || (ExtCapOffset == 0xFFFFFFFF)) {
- return 0;
- }
- //
- // According to XHCI 1.1 spec November 2017,
- // Section 7.2 xHCI Supported Protocol Capability
- // 1. Get the PSIC(Protocol Speed ID Count) value.
- // 2. The PSID register boundary should be Base address + PSIC * 0x04
- //
- PortId.Dword = XhcReadExtCapReg (Xhc, ExtCapOffset + XHC_SUPPORTED_PROTOCOL_DW2_OFFSET);
- //
- // According to XHCI 1.1 spec November 2017, valid values
- // for CompPortOffset are 1 to CompPortCount - 1.
- //
- // PortNumber is zero-indexed, so subtract 1.
- //
- if ((PortId.Data.CompPortOffset == 0) || (PortId.Data.CompPortCount == 0)) {
- return 0;
- }
- MinPortIndex = PortId.Data.CompPortOffset - 1;
- MaxPortIndex = MinPortIndex + PortId.Data.CompPortCount - 1;
- if ((PortNumber < MinPortIndex) || (PortNumber > MaxPortIndex)) {
- return 0;
- }
- for (Count = 0; Count < PortId.Data.Psic; Count++) {
- Reg.Dword = XhcReadExtCapReg (Xhc, ExtCapOffset + XHC_SUPPORTED_PROTOCOL_PSI_OFFSET + (Count << 2));
- if (Reg.Data.Psiv == PortSpeed) {
- return Reg.Dword;
- }
- }
- return 0;
- }
- /**
- Find PortSpeed value match case in XHCI Supported Protocol Capability
- @param Xhc The XHCI Instance.
- @param PortSpeed The Port Speed Field in USB PortSc register
- @param PortNumber The Port Number (0-indexed)
- @return The USB Port Speed.
- **/
- UINT16
- XhcCheckUsbPortSpeedUsedPsic (
- IN USB_XHCI_INSTANCE *Xhc,
- IN UINT8 PortSpeed,
- IN UINT8 PortNumber
- )
- {
- XHC_SUPPORTED_PROTOCOL_PROTOCOL_SPEED_ID SpField;
- UINT16 UsbSpeedIdMap;
- if (Xhc == NULL) {
- return 0;
- }
- SpField.Dword = 0;
- UsbSpeedIdMap = 0;
- //
- // Check xHCI Supported Protocol Capability, find the PSIV field to match
- // PortSpeed definition when the Major Revision is 03h.
- //
- if (Xhc->Usb3SupOffset != 0xFFFFFFFF) {
- SpField.Dword = XhciPsivGetPsid (Xhc, Xhc->Usb3SupOffset, PortSpeed, PortNumber);
- if (SpField.Dword != 0) {
- //
- // Found the corresponding PORTSC value in PSIV field of USB3 offset.
- //
- UsbSpeedIdMap = USB_PORT_STAT_SUPER_SPEED;
- }
- }
- //
- // Check xHCI Supported Protocol Capability, find the PSIV field to match
- // PortSpeed definition when the Major Revision is 02h.
- //
- if ((UsbSpeedIdMap == 0) && (Xhc->Usb2SupOffset != 0xFFFFFFFF)) {
- SpField.Dword = XhciPsivGetPsid (Xhc, Xhc->Usb2SupOffset, PortSpeed, PortNumber);
- if (SpField.Dword != 0) {
- //
- // Found the corresponding PORTSC value in PSIV field of USB2 offset.
- //
- if (SpField.Data.Psie == 2) {
- //
- // According to XHCI 1.1 spec November 2017,
- // Section 7.2.1 the Protocol Speed ID Exponent (PSIE) field definition,
- // PSIE value shall be applied to Protocol Speed ID Mantissa when calculating, value 2 shall represent bit rate in Mb/s
- //
- if (SpField.Data.Psim == XHC_SUPPORTED_PROTOCOL_USB2_HIGH_SPEED_PSIM) {
- //
- // PSIM shows as default High-speed protocol, apply to High-speed mapping
- //
- UsbSpeedIdMap = USB_PORT_STAT_HIGH_SPEED;
- }
- } else if (SpField.Data.Psie == 1) {
- //
- // According to XHCI 1.1 spec November 2017,
- // Section 7.2.1 the Protocol Speed ID Exponent (PSIE) field definition,
- // PSIE value shall be applied to Protocol Speed ID Mantissa when calculating, value 1 shall represent bit rate in Kb/s
- //
- if (SpField.Data.Psim == XHC_SUPPORTED_PROTOCOL_USB2_LOW_SPEED_PSIM) {
- //
- // PSIM shows as default Low-speed protocol, apply to Low-speed mapping
- //
- UsbSpeedIdMap = USB_PORT_STAT_LOW_SPEED;
- }
- }
- }
- }
- return UsbSpeedIdMap;
- }
- /**
- Whether the XHCI host controller is halted.
- @param Xhc The XHCI Instance.
- @retval TRUE The controller is halted.
- @retval FALSE It isn't halted.
- **/
- BOOLEAN
- XhcIsHalt (
- IN USB_XHCI_INSTANCE *Xhc
- )
- {
- return XHC_REG_BIT_IS_SET (Xhc, XHC_USBSTS_OFFSET, XHC_USBSTS_HALT);
- }
- /**
- Whether system error occurred.
- @param Xhc The XHCI Instance.
- @retval TRUE System error happened.
- @retval FALSE No system error.
- **/
- BOOLEAN
- XhcIsSysError (
- IN USB_XHCI_INSTANCE *Xhc
- )
- {
- return XHC_REG_BIT_IS_SET (Xhc, XHC_USBSTS_OFFSET, XHC_USBSTS_HSE);
- }
- /**
- Set USBCMD Host System Error Enable(HSEE) Bit if PCICMD SERR# Enable Bit is set.
- The USBCMD HSEE Bit will be reset to default 0 by USBCMD Host Controller Reset(HCRST).
- This function is to set USBCMD HSEE Bit if PCICMD SERR# Enable Bit is set.
- @param Xhc The XHCI Instance.
- **/
- VOID
- XhcSetHsee (
- IN USB_XHCI_INSTANCE *Xhc
- )
- {
- EFI_STATUS Status;
- EFI_PCI_IO_PROTOCOL *PciIo;
- UINT16 XhciCmd;
- PciIo = Xhc->PciIo;
- Status = PciIo->Pci.Read (
- PciIo,
- EfiPciIoWidthUint16,
- PCI_COMMAND_OFFSET,
- sizeof (XhciCmd) / sizeof (UINT16),
- &XhciCmd
- );
- if (!EFI_ERROR (Status)) {
- if ((XhciCmd & EFI_PCI_COMMAND_SERR) != 0) {
- XhcSetOpRegBit (Xhc, XHC_USBCMD_OFFSET, XHC_USBCMD_HSEE);
- }
- }
- }
- /**
- Reset the XHCI host controller.
- @param Xhc The XHCI Instance.
- @param Timeout Time to wait before abort (in millisecond, ms).
- @retval EFI_SUCCESS The XHCI host controller is reset.
- @return Others Failed to reset the XHCI before Timeout.
- **/
- EFI_STATUS
- XhcResetHC (
- IN USB_XHCI_INSTANCE *Xhc,
- IN UINT32 Timeout
- )
- {
- EFI_STATUS Status;
- Status = EFI_SUCCESS;
- DEBUG ((DEBUG_INFO, "XhcResetHC!\n"));
- //
- // Host can only be reset when it is halt. If not so, halt it
- //
- if (!XHC_REG_BIT_IS_SET (Xhc, XHC_USBSTS_OFFSET, XHC_USBSTS_HALT)) {
- Status = XhcHaltHC (Xhc, Timeout);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- }
- if ((Xhc->DebugCapSupOffset == 0xFFFFFFFF) || ((XhcReadExtCapReg (Xhc, Xhc->DebugCapSupOffset) & 0xFF) != XHC_CAP_USB_DEBUG) ||
- ((XhcReadExtCapReg (Xhc, Xhc->DebugCapSupOffset + XHC_DC_DCCTRL) & BIT0) == 0))
- {
- XhcSetOpRegBit (Xhc, XHC_USBCMD_OFFSET, XHC_USBCMD_RESET);
- //
- // Some XHCI host controllers require to have extra 1ms delay before accessing any MMIO register during reset.
- // Otherwise there may have the timeout case happened.
- // The below is a workaround to solve such problem.
- //
- gBS->Stall (XHC_1_MILLISECOND);
- Status = XhcWaitOpRegBit (Xhc, XHC_USBCMD_OFFSET, XHC_USBCMD_RESET, FALSE, Timeout);
- if (!EFI_ERROR (Status)) {
- //
- // The USBCMD HSEE Bit will be reset to default 0 by USBCMD HCRST.
- // Set USBCMD HSEE Bit if PCICMD SERR# Enable Bit is set.
- //
- XhcSetHsee (Xhc);
- }
- }
- return Status;
- }
- /**
- Halt the XHCI host controller.
- @param Xhc The XHCI Instance.
- @param Timeout Time to wait before abort (in millisecond, ms).
- @return EFI_SUCCESS The XHCI host controller is halt.
- @return EFI_TIMEOUT Failed to halt the XHCI before Timeout.
- **/
- EFI_STATUS
- XhcHaltHC (
- IN USB_XHCI_INSTANCE *Xhc,
- IN UINT32 Timeout
- )
- {
- EFI_STATUS Status;
- XhcClearOpRegBit (Xhc, XHC_USBCMD_OFFSET, XHC_USBCMD_RUN);
- Status = XhcWaitOpRegBit (Xhc, XHC_USBSTS_OFFSET, XHC_USBSTS_HALT, TRUE, Timeout);
- return Status;
- }
- /**
- Set the XHCI host controller to run.
- @param Xhc The XHCI Instance.
- @param Timeout Time to wait before abort (in millisecond, ms).
- @return EFI_SUCCESS The XHCI host controller is running.
- @return EFI_TIMEOUT Failed to set the XHCI to run before Timeout.
- **/
- EFI_STATUS
- XhcRunHC (
- IN USB_XHCI_INSTANCE *Xhc,
- IN UINT32 Timeout
- )
- {
- EFI_STATUS Status;
- XhcSetOpRegBit (Xhc, XHC_USBCMD_OFFSET, XHC_USBCMD_RUN);
- Status = XhcWaitOpRegBit (Xhc, XHC_USBSTS_OFFSET, XHC_USBSTS_HALT, FALSE, Timeout);
- return Status;
- }
|