summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c39
-rw-r--r--MdeModulePkg/Bus/Pci/XhciDxe/Xhci.h2
-rw-r--r--MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.c178
-rw-r--r--MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.h93
4 files changed, 296 insertions, 16 deletions
diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c b/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c
index 381d7a9..c05431f 100644
--- a/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c
+++ b/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c
@@ -399,24 +399,31 @@ XhcGetRootHubPortStatus (
//
// According to XHCI 1.1 spec November 2017,
- // bit 10~13 of the root port status register identifies the speed of the attached device.
+ // Section 7.2 xHCI Support Protocol Capability
//
- switch ((State & XHC_PORTSC_PS) >> 10) {
- case 2:
- PortStatus->PortStatus |= USB_PORT_STAT_LOW_SPEED;
- break;
+ PortStatus->PortStatus = XhcCheckUsbPortSpeedUsedPsic (Xhc, ((State & XHC_PORTSC_PS) >> 10));
+ if (PortStatus->PortStatus == 0) {
+ //
+ // According to XHCI 1.1 spec November 2017,
+ // bit 10~13 of the root port status register identifies the speed of the attached device.
+ //
+ switch ((State & XHC_PORTSC_PS) >> 10) {
+ case 2:
+ PortStatus->PortStatus |= USB_PORT_STAT_LOW_SPEED;
+ break;
- case 3:
- PortStatus->PortStatus |= USB_PORT_STAT_HIGH_SPEED;
- break;
+ case 3:
+ PortStatus->PortStatus |= USB_PORT_STAT_HIGH_SPEED;
+ break;
- case 4:
- case 5:
- PortStatus->PortStatus |= USB_PORT_STAT_SUPER_SPEED;
- break;
+ case 4:
+ case 5:
+ PortStatus->PortStatus |= USB_PORT_STAT_SUPER_SPEED;
+ break;
- default:
- break;
+ default:
+ break;
+ }
}
//
@@ -1826,6 +1833,8 @@ XhcCreateUsbHc (
Xhc->ExtCapRegBase = ExtCapReg << 2;
Xhc->UsbLegSupOffset = XhcGetCapabilityAddr (Xhc, XHC_CAP_USB_LEGACY);
Xhc->DebugCapSupOffset = XhcGetCapabilityAddr (Xhc, XHC_CAP_USB_DEBUG);
+ Xhc->Usb2SupOffset = XhcGetSupportedProtocolCapabilityAddr (Xhc, XHC_SUPPORTED_PROTOCOL_DW0_MAJOR_REVISION_USB2);
+ Xhc->Usb3SupOffset = XhcGetSupportedProtocolCapabilityAddr (Xhc, XHC_SUPPORTED_PROTOCOL_DW0_MAJOR_REVISION_USB3);
DEBUG ((DEBUG_INFO, "XhcCreateUsb3Hc: Capability length 0x%x\n", Xhc->CapLength));
DEBUG ((DEBUG_INFO, "XhcCreateUsb3Hc: HcSParams1 0x%x\n", Xhc->HcSParams1));
@@ -1835,6 +1844,8 @@ XhcCreateUsbHc (
DEBUG ((DEBUG_INFO, "XhcCreateUsb3Hc: RTSOff 0x%x\n", Xhc->RTSOff));
DEBUG ((DEBUG_INFO, "XhcCreateUsb3Hc: UsbLegSupOffset 0x%x\n", Xhc->UsbLegSupOffset));
DEBUG ((DEBUG_INFO, "XhcCreateUsb3Hc: DebugCapSupOffset 0x%x\n", Xhc->DebugCapSupOffset));
+ DEBUG ((DEBUG_INFO, "XhcCreateUsb3Hc: Usb2SupOffset 0x%x\n", Xhc->Usb2SupOffset));
+ DEBUG ((DEBUG_INFO, "XhcCreateUsb3Hc: Usb3SupOffset 0x%x\n", Xhc->Usb3SupOffset));
//
// Create AsyncRequest Polling Timer
diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.h b/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.h
index 5054d79..ca223bd 100644
--- a/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.h
+++ b/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.h
@@ -227,6 +227,8 @@ struct _USB_XHCI_INSTANCE {
UINT32 ExtCapRegBase;
UINT32 UsbLegSupOffset;
UINT32 DebugCapSupOffset;
+ UINT32 Usb2SupOffset;
+ UINT32 Usb3SupOffset;
UINT64 *DCBAA;
VOID *DCBAAMap;
UINT32 MaxSlotsEn;
diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.c b/MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.c
index 80be331..2b4a4b2 100644
--- a/MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.c
+++ b/MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.c
@@ -576,6 +576,184 @@ XhcGetCapabilityAddr (
}
/**
+ 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
+
+ @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
+ )
+{
+ XHC_SUPPORTED_PROTOCOL_DW2 PortId;
+ XHC_SUPPORTED_PROTOCOL_PROTOCOL_SPEED_ID Reg;
+ UINT32 Count;
+
+ 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);
+
+ 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
+
+ @return The USB Port Speed.
+
+**/
+UINT16
+XhcCheckUsbPortSpeedUsedPsic (
+ IN USB_XHCI_INSTANCE *Xhc,
+ IN UINT8 PortSpeed
+ )
+{
+ 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);
+ 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);
+ 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.
diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.h b/MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.h
index 4950eed..5fe2ba4 100644
--- a/MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.h
+++ b/MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.h
@@ -25,8 +25,9 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#define USB_HUB_CLASS_CODE 0x09
#define USB_HUB_SUBCLASS_CODE 0x00
-#define XHC_CAP_USB_LEGACY 0x01
-#define XHC_CAP_USB_DEBUG 0x0A
+#define XHC_CAP_USB_LEGACY 0x01
+#define XHC_CAP_USB_DEBUG 0x0A
+#define XHC_CAP_USB_SUPPORTED_PROTOCOL 0x02
// ============================================//
// XHCI register offset //
@@ -74,6 +75,18 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#define USBLEGSP_BIOS_SEMAPHORE BIT16 // HC BIOS Owned Semaphore
#define USBLEGSP_OS_SEMAPHORE BIT24 // HC OS Owned Semaphore
+//
+// xHCI Supported Protocol Capability
+//
+#define XHC_SUPPORTED_PROTOCOL_DW0_MAJOR_REVISION_USB2 0x02
+#define XHC_SUPPORTED_PROTOCOL_DW0_MAJOR_REVISION_USB3 0x03
+#define XHC_SUPPORTED_PROTOCOL_NAME_STRING_OFFSET 0x04
+#define XHC_SUPPORTED_PROTOCOL_NAME_STRING_VALUE 0x20425355
+#define XHC_SUPPORTED_PROTOCOL_DW2_OFFSET 0x08
+#define XHC_SUPPORTED_PROTOCOL_PSI_OFFSET 0x10
+#define XHC_SUPPORTED_PROTOCOL_USB2_HIGH_SPEED_PSIM 480
+#define XHC_SUPPORTED_PROTOCOL_USB2_LOW_SPEED_PSIM 1500
+
#pragma pack (1)
typedef struct {
UINT8 MaxSlots; // Number of Device Slots
@@ -130,6 +143,52 @@ typedef union {
HCCPARAMS Data;
} XHC_HCCPARAMS;
+//
+// xHCI Supported Protocol Cabability
+//
+typedef struct {
+ UINT8 CapId;
+ UINT8 NextExtCapReg;
+ UINT8 RevMinor;
+ UINT8 RevMajor;
+} SUPPORTED_PROTOCOL_DW0;
+
+typedef union {
+ UINT32 Dword;
+ SUPPORTED_PROTOCOL_DW0 Data;
+} XHC_SUPPORTED_PROTOCOL_DW0;
+
+typedef struct {
+ UINT32 NameString;
+} XHC_SUPPORTED_PROTOCOL_DW1;
+
+typedef struct {
+ UINT8 CompPortOffset;
+ UINT8 CompPortCount;
+ UINT16 ProtocolDef : 12;
+ UINT16 Psic : 4;
+} SUPPORTED_PROTOCOL_DW2;
+
+typedef union {
+ UINT32 Dword;
+ SUPPORTED_PROTOCOL_DW2 Data;
+} XHC_SUPPORTED_PROTOCOL_DW2;
+
+typedef struct {
+ UINT16 Psiv : 4;
+ UINT16 Psie : 2;
+ UINT16 Plt : 2;
+ UINT16 Pfd : 1;
+ UINT16 RsvdP : 5;
+ UINT16 Lp : 2;
+ UINT16 Psim;
+} SUPPORTED_PROTOCOL_PROTOCOL_SPEED_ID;
+
+typedef union {
+ UINT32 Dword;
+ SUPPORTED_PROTOCOL_PROTOCOL_SPEED_ID Data;
+} XHC_SUPPORTED_PROTOCOL_PROTOCOL_SPEED_ID;
+
#pragma pack ()
//
@@ -546,4 +605,34 @@ XhcGetCapabilityAddr (
IN UINT8 CapId
);
+/**
+ 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
+ );
+
+/**
+ Find SpeedField value match with Port Speed ID value.
+
+ @param Xhc The XHCI Instance.
+ @param Speed The Port Speed filed in USB PortSc register
+
+ @return The USB Port Speed.
+
+**/
+UINT16
+XhcCheckUsbPortSpeedUsedPsic (
+ IN USB_XHCI_INSTANCE *Xhc,
+ IN UINT8 Speed
+ );
+
#endif