1233 lines
32 KiB
C
1233 lines
32 KiB
C
/** @file
|
|
|
|
;******************************************************************************
|
|
;* Copyright (c) 2017 - 2020, Insyde Software Corp. All Rights Reserved.
|
|
;*
|
|
;* You may not reproduce, distribute, publish, display, perform, modify, adapt,
|
|
;* transmit, broadcast, present, recite, release, license or otherwise exploit
|
|
;* any part of this publication in any form, by any means, without the prior
|
|
;* written permission of Insyde Software Corporation.
|
|
;*
|
|
;******************************************************************************
|
|
**/
|
|
|
|
#include <Library/IoLib.h>
|
|
#include <Library/PeiServicesLib.h>
|
|
#include <Library/BaseMemoryLib.h>
|
|
#include <Library/DebugLib.h>
|
|
#include <Library/PciSegmentLib.h>
|
|
#include <Library/PchInfoLib.h>
|
|
#include <Register/UsbRegs.h>
|
|
#include <IndustryStandard/Pci22.h>
|
|
|
|
#include <Register/PchRegs.h>
|
|
#include <Register/PmcRegs.h>
|
|
#include <PchBdfAssignment.h>
|
|
#include "PchDdtUsbPei.h"
|
|
/**
|
|
Helper function for gathering of xHCI controller features and infromation
|
|
|
|
@param[in] XhciPciBase xHCI PCI config space address
|
|
@param[out] HcInfo xHCI controller information structure
|
|
**/
|
|
STATIC
|
|
VOID
|
|
GetXhciControllerInfo (
|
|
IN UINT64 XhciPciBase,
|
|
OUT USB_CONTROLLER_INFO *HcInfo
|
|
)
|
|
{
|
|
UINT16 ControllerDid;
|
|
|
|
ZeroMem (HcInfo, sizeof (USB_CONTROLLER_INFO));
|
|
|
|
// Check device DID from given PCI config space
|
|
ControllerDid = PciSegmentRead16 (XhciPciBase + PCI_DEVICE_ID_OFFSET);
|
|
HcInfo->DeviceId = ControllerDid;
|
|
|
|
switch (HcInfo->DeviceId) {
|
|
case V_XHCI_DID_CNP_LP:
|
|
case V_XHCI_DID_CNP_H:
|
|
HcInfo->OnSouth = TRUE;
|
|
HcInfo->IpVersion = V16_0;
|
|
break;
|
|
|
|
case V_XHCI_DID_CPU_V17_0_1:
|
|
HcInfo->IpVersion = V17_0;
|
|
HcInfo->OnSouth = FALSE;
|
|
break;
|
|
|
|
case V_XHCI_DID_PCH_V17_1_1:
|
|
HcInfo->OnSouth = TRUE;
|
|
HcInfo->IpVersion = V17_1;
|
|
break;
|
|
|
|
case V_XHCI_DID_PCH_V17_1_2:
|
|
case V_XHCI_DID_PCH_V17_1_3:
|
|
HcInfo->OnSouth = TRUE;
|
|
HcInfo->IpVersion = V17_1;
|
|
break;
|
|
}
|
|
|
|
if ((HcInfo->DeviceId == V_XHCI_DID_PCH_V17_1_2) ||
|
|
(HcInfo->DeviceId == V_XHCI_DID_PCH_V17_1_3)) {
|
|
HcInfo->UsbLtrHigh = V_XHCI_LTR_HIT_2;
|
|
HcInfo->UsbLtrMid = V_XHCI_LTR_MIT_2;
|
|
HcInfo->UsbLtrLow = V_XHCI_LTR_LIT_2;
|
|
} else {
|
|
HcInfo->UsbLtrHigh = V_XHCI_LTR_HIT_1;
|
|
HcInfo->UsbLtrMid = V_XHCI_LTR_MIT_1;
|
|
HcInfo->UsbLtrLow = V_XHCI_LTR_LIT_1;
|
|
}
|
|
|
|
DEBUG ((DEBUG_INFO, "xHCI Controller DID: 0x%4X\n", ControllerDid));
|
|
DEBUG ((DEBUG_INFO, "Params:\n UsbIpVersion: 0x%2X, Device: 0x%4X\n", HcInfo->IpVersion, HcInfo->DeviceId));
|
|
}
|
|
|
|
|
|
/**
|
|
Program and enable XHCI Memory Space
|
|
|
|
@param[in] XhciPciBase XHCI PCI Base Address
|
|
@param[in] XhciMmioBase Memory base address of XHCI Controller
|
|
|
|
**/
|
|
VOID
|
|
DdtXhciMemorySpaceOpen (
|
|
IN UINT64 XhciPciBase,
|
|
IN UINT32 XhciMmioBase
|
|
)
|
|
{
|
|
//
|
|
// Assign memory resources
|
|
//
|
|
PciSegmentWrite32 (XhciPciBase + R_XHCI_CFG_BAR0, XhciMmioBase);
|
|
PciSegmentWrite32 (XhciPciBase + R_XHCI_CFG_BAR0 + 4, 0);
|
|
|
|
PciSegmentOr16 (
|
|
XhciPciBase + PCI_COMMAND_OFFSET,
|
|
(UINT16) (EFI_PCI_COMMAND_MEMORY_SPACE)
|
|
);
|
|
|
|
}
|
|
|
|
/*
|
|
Helper function to return supported number of USB2 ports reported by Host Controller
|
|
|
|
@param[in] XhciMmioBase Memory BAR of the xHCI controller
|
|
*/
|
|
STATIC
|
|
UINT32
|
|
GetUsb2PortCount (
|
|
IN UINTN XhciMmioBase
|
|
)
|
|
{
|
|
return ((MmioRead32 (XhciMmioBase + R_XHCI_MEM_XECP_SUPP_USB2_2) & B_XHCI_MEM_XECP_SUPP_USBX_2_CPC) >> N_XHCI_MEM_XECP_SUPP_USBX_2_CPC);
|
|
}
|
|
|
|
/*
|
|
Helper function to return supported number of USB3 ports reported by Host Controller
|
|
|
|
@param[in] XhciMmioBase Memory BAR of the xHCI controller
|
|
*/
|
|
STATIC
|
|
UINT32
|
|
GetUsb3PortCount (
|
|
IN UINTN XhciMmioBase
|
|
)
|
|
{
|
|
return ((MmioRead32 (XhciMmioBase + R_XHCI_MEM_XECP_SUPP_USB3_2) & B_XHCI_MEM_XECP_SUPP_USBX_2_CPC) >> N_XHCI_MEM_XECP_SUPP_USBX_2_CPC);
|
|
}
|
|
|
|
/**
|
|
Performs basic configuration of USB3 (xHCI) controller.
|
|
|
|
@param[in] HcInfo xHCI controller information structure
|
|
@param[in] XhciPciBase xHCI PCI config space address
|
|
@param[in] XhciMmioBase Memory base address of xHCI Controller
|
|
|
|
@retval None
|
|
**/
|
|
VOID
|
|
DdtXhciHcInit (
|
|
IN USB_CONTROLLER_INFO *HcInfo,
|
|
IN UINT64 XhciPciBase,
|
|
IN UINT32 XhciMmioBase
|
|
)
|
|
{
|
|
UINT32 Data32;
|
|
UINT32 Data32Or;
|
|
UINT32 Data32And;
|
|
UINT32 HsPortCount;
|
|
UINT32 SsPortCount;
|
|
UINT32 XhciUsb3Pdo;
|
|
UINT32 XhciUsb3PortsMask;
|
|
|
|
DEBUG ((DEBUG_INFO, "XhciHcInit XhciMmio Base = 0x%x\n", XhciMmioBase));
|
|
|
|
HsPortCount = GetUsb2PortCount (XhciMmioBase);
|
|
SsPortCount = GetUsb3PortCount (XhciMmioBase);
|
|
|
|
DEBUG ((DEBUG_INFO, "Number of supported Super Speed Ports = %d\n", SsPortCount));
|
|
DEBUG ((DEBUG_INFO, "Number of supported High Speed Ports = %d\n", HsPortCount));
|
|
|
|
//
|
|
// XHCC1 - XHC System Bus Configuration 1
|
|
// Address Offset: 0x40
|
|
// Value: [21:19] 110b, [18] 1b, [8] 1b
|
|
// Writes to this registers needs to be performed per bytes to avoid touching bit 31
|
|
// Bit 31 is used to lock RW/L bits and can be writen once.
|
|
//
|
|
PciSegmentOr8 (
|
|
XhciPciBase + R_XHCI_CFG_XHCC1 + 1,
|
|
(UINT32) (BIT0)
|
|
);
|
|
PciSegmentOr8 (
|
|
XhciPciBase + R_XHCI_CFG_XHCC1 + 2,
|
|
(UINT32) (BIT5 | BIT4 | BIT2)
|
|
);
|
|
|
|
//
|
|
// DBGDEV_CTRL_REG1 - Debug Device Control Register 1
|
|
// Address Offset: 0x8754
|
|
// Value: [9] 1b
|
|
//
|
|
MmioOr32 (
|
|
(XhciMmioBase + R_XHCI_MEM_DBGDEV_CTRL_REG1),
|
|
(UINT32) (BIT9)
|
|
);
|
|
|
|
//
|
|
// XHCC2 - XHC System Bus Configuration 2
|
|
// Address Offset: 0x44
|
|
// Value: [24:22] 001b, [21] 1b, [20:14] 1111111b, [10] 1b, [9:8] 10b, [7:6] 10b, [5:3] 001b, [2:0] 000b
|
|
// Additionally for IP V17.0 and V17.1 [22] 1b [0] 1b
|
|
// Additionally for IP V17.0 only [25:23] 111b [2:1] 11b
|
|
//
|
|
Data32Or = (BIT21 | BIT20 | BIT19 | BIT18 | BIT17 | BIT16 | BIT15 | BIT14 | BIT10 | BIT9 | BIT7 | BIT3);
|
|
if ((HcInfo->IpVersion == V17_0) || (HcInfo->IpVersion == V17_1)) {
|
|
Data32Or |= (BIT22 | BIT0);
|
|
}
|
|
if (HcInfo->IpVersion == V17_0) {
|
|
Data32Or |= (BIT25 | BIT24 | BIT23 | BIT2 | BIT1);
|
|
}
|
|
PciSegmentOr32 (
|
|
XhciPciBase + R_XHCI_CFG_XHCC2,
|
|
Data32Or
|
|
);
|
|
|
|
//
|
|
// PMCTRL2 - Power Management Control 2
|
|
// Address Offset: 0x8468
|
|
// Value: [5] 1b, [0] 1b
|
|
// This bits must be set before setting USB_SRAM_PG_EN (bit27) in XHCLKGTEN
|
|
// This setting doesn't apply to CNP-LP Ax steppings
|
|
//
|
|
if (!((HcInfo->DeviceId == V_XHCI_DID_CNP_LP) && (PchStepping () < PCH_B0))) {
|
|
MmioOr32 (
|
|
(XhciMmioBase + R_XHCI_MEM_PMCTRL2),
|
|
(UINT32) (BIT5 | BIT0)
|
|
);
|
|
}
|
|
|
|
//
|
|
// XHCLKGTEN - Clock Gating
|
|
// Address Offset: 0x50
|
|
// Value: 0x0FDF6D3F
|
|
// Additionally for devices with IDs 0x38ED or 0x3DED
|
|
// [17:16] 11b, [6] 0b
|
|
//
|
|
Data32 = 0x0FDF6D3F;
|
|
if ((HcInfo->DeviceId == V_XHCI_DID_PCH_V17_1_2) ||
|
|
(HcInfo->DeviceId == V_XHCI_DID_PCH_V17_1_3)) {
|
|
Data32 |= (BIT17 | BIT16);
|
|
Data32 &= (UINT32)~(BIT6);
|
|
}
|
|
PciSegmentWrite32 (
|
|
(XhciPciBase + R_XHCI_CFG_XHCLKGTEN),
|
|
Data32
|
|
);
|
|
|
|
//
|
|
// MSI_NEXT - Next Item Pointer
|
|
// Address Offset: 0x81
|
|
// Value: [7:0] 90h
|
|
//
|
|
PciSegmentWrite8 (
|
|
(XhciPciBase + R_XHCI_CFG_MSI_NEXT),
|
|
0x90
|
|
);
|
|
|
|
//
|
|
// PCE - Power Control Enables
|
|
// Address Offset: 0xA2
|
|
// Value: [5] 1b, [3] 1b, [2] 1b, [1] 1b
|
|
//
|
|
PciSegmentOr16 (
|
|
(XhciPciBase + R_XHCI_CFG_PCE),
|
|
(UINT16) (BIT5 | BIT3 | BIT2 | BIT1)
|
|
);
|
|
|
|
//
|
|
// HSCFG2 - High Speed Configuration 2
|
|
// Address Offset: 0xA4
|
|
// [15:13] 000b
|
|
// [12:11] 11b
|
|
//
|
|
PciSegmentAndThenOr32 (
|
|
(XhciPciBase + R_XHCI_CFG_HSCFG2),
|
|
(UINT32) ~(BIT15 | BIT14 | BIT13),
|
|
(UINT32) (BIT12 | BIT11)
|
|
);
|
|
|
|
//
|
|
// SSCFG1 - SuperSpeed Configuration 1
|
|
// Address Offset: 0xA8
|
|
// Value: [17] 1b, [14] 1b
|
|
//
|
|
PciSegmentOr32 (
|
|
(XhciPciBase + R_XHCI_CFG_SSCFG1),
|
|
(UINT32) (BIT17 | BIT14)
|
|
);
|
|
|
|
//
|
|
// XHCC3 - XHC System Bus Configuration 3
|
|
// Address Offset: 0xFC
|
|
// Value: [4] 1b
|
|
//
|
|
PciSegmentOr32 (
|
|
(XhciPciBase + R_XHCI_CFG_XHCC3),
|
|
(UINT32) (BIT4)
|
|
);
|
|
|
|
if (HcInfo->IpVersion == V16_0) {
|
|
//
|
|
// HCIVERSION - Host Controller Interface Version Number
|
|
// Address Offset: 0x02
|
|
// Set [15:0] = 0110h
|
|
// Only for IP V16.0
|
|
//
|
|
//[-start-200420-IB17800060-modify]//
|
|
//RC 1181.1 define change.
|
|
//if HcInfo->IpVersion > V18_0 , V_XHCI_MEM_HCIVERSION_0120
|
|
//if HcInfo->IpVersion <= V18_0 , V_XHCI_MEM_HCIVERSION_0110
|
|
//MmioAndThenOr32 (
|
|
// (XhciMmioBase + R_XHCI_MEM_CAPLENGTH),
|
|
// (UINT32) B_XHCI_MEM_HCIVERSION,
|
|
// (UINT32) (V_XHCI_MEM_HCIVERSION << N_XHCI_MEM_HCIVERSION)
|
|
// );
|
|
MmioAndThenOr32 (
|
|
(XhciMmioBase + R_XHCI_MEM_CAPLENGTH),
|
|
(UINT32) B_XHCI_MEM_HCIVERSION,
|
|
(UINT32) (V_XHCI_MEM_HCIVERSION_0110 << N_XHCI_MEM_HCIVERSION)
|
|
);
|
|
//[-end-200420-IB17800060-modify]//
|
|
}
|
|
|
|
//
|
|
// HCSPARAMS3 - Structural Parameters 3
|
|
// Address Offset: 0x0C
|
|
// Value: [31:16] = A0h, [7:0] = 0Ah
|
|
// For CNP-LP A0 [31:16] = 0x0200
|
|
//
|
|
Data32Or = 0x00A0000A;
|
|
if ((HcInfo->DeviceId == V_XHCI_DID_CNP_LP) && (PchStepping () == PCH_A0)) {
|
|
Data32Or = (0x0200 << N_XHCI_MEM_HCSPARAMS3_U2DEL) | (Data32Or & B_XHCI_MEM_HCSPARAMS3_U1DEL);
|
|
}
|
|
MmioAndThenOr32 (
|
|
(XhciMmioBase + R_XHCI_MEM_HCSPARAMS3),
|
|
B_XHCI_MEM_HCSPARAMS3,
|
|
Data32Or
|
|
);
|
|
|
|
//
|
|
// HCCPARAMS1 - Capability Parameters 1
|
|
// Address Offset: 0x10
|
|
// Value: [11] 1b
|
|
//
|
|
MmioOr32 (
|
|
(XhciMmioBase + R_XHCI_MEM_HCCPARAMS1),
|
|
(UINT32) (BIT11)
|
|
);
|
|
|
|
//
|
|
// HCCPARAMS2 - Capability Parameters 2
|
|
// Address Offset: 0x1C
|
|
// Value: [6] 1b, [4] 1b
|
|
//
|
|
MmioOr32 (
|
|
(XhciMmioBase + R_XHCI_MEM_HCCPARAMS2),
|
|
(UINT32) (BIT6 | BIT4)
|
|
);
|
|
|
|
//
|
|
// XECP_CMDM_CTRL_REG1 - Command Manager Control 1
|
|
// Address Offset: 0x818C
|
|
// Value: [20] 0b, [16] 1b, [8] 0b
|
|
//
|
|
MmioAndThenOr32 (
|
|
(XhciMmioBase + R_XHCI_MEM_XECP_CMDM_CTRL_REG1),
|
|
(UINT32)~(BIT20 | BIT8),
|
|
(UINT32) (BIT16)
|
|
);
|
|
|
|
//
|
|
// HOST_CTRL_ODMA_REG - Host Control ODMA Register
|
|
// Address Offset: 0x8098
|
|
// Value: [2:1] 00b
|
|
//
|
|
MmioAnd32 (
|
|
(XhciMmioBase + R_XHCI_MEM_HOST_CTRL_ODMA_REG),
|
|
(UINT32)~(BIT2 | BIT1)
|
|
);
|
|
|
|
//
|
|
// PMCTRL - Power Management Control
|
|
// Address Offset: 0x80A4
|
|
// Value: [30] 1b, [27] 1b, [24] 1b, [16] 1b, [15:8] 50h, [3] 1b, [2] 1b
|
|
//
|
|
MmioAndThenOr32 (
|
|
(XhciMmioBase + R_XHCI_MEM_PMCTRL),
|
|
(UINT32) ~(B_XHCI_MEM_PMCTRL_SSU3LFPS_DET),
|
|
(UINT32) (BIT30 | BIT27 | BIT24 | (0x50 << N_XHCI_MEM_PMCTRL_SSU3LPFS_DET) | BIT3 | BIT2)
|
|
);
|
|
|
|
//
|
|
// AUX_CTRL_REG3 - Aux PM Control 3 Register
|
|
// Address Offset: 0x81C8
|
|
// Value: [6] 1b
|
|
//
|
|
MmioOr32 (
|
|
(XhciMmioBase + R_XHCI_MEM_AUX_CTRL_REG3),
|
|
(UINT32) (BIT6)
|
|
);
|
|
|
|
//
|
|
// SSPE - Super Speed Port Enables
|
|
// Address Offset: 0x80B8
|
|
// Value: [30] 1b
|
|
//
|
|
MmioOr32 (
|
|
(XhciMmioBase + R_XHCI_MEM_SSPE),
|
|
(UINT32) (BIT30)
|
|
);
|
|
|
|
//
|
|
// AUX_CTRL_REG1 - AUX Power Management Control
|
|
// Address Offset: 0x80E0
|
|
// Value: [16] 0b, [6] 1b
|
|
// For CNP Ax steppings [16] 1b
|
|
//
|
|
Data32Or = (UINT32) (BIT6);
|
|
if (((HcInfo->DeviceId == V_XHCI_DID_CNP_LP) || (HcInfo->DeviceId == V_XHCI_DID_CNP_H)) && (PchStepping () < PCH_B0)) {
|
|
Data32Or |= BIT16;
|
|
}
|
|
MmioAndThenOr32 (
|
|
(XhciMmioBase + R_XHCI_MEM_AUX_CTRL_REG1),
|
|
(UINT32) ~(BIT16),
|
|
Data32Or
|
|
);
|
|
|
|
//
|
|
// HOST_CTRL_SCH_REG - Host Control Scheduler
|
|
// Address Offset: 0x8094
|
|
// Value: [23] 1b, [22] 1b, [6] 1b
|
|
//
|
|
MmioOr32 (
|
|
(XhciMmioBase + R_XHCI_MEM_HOST_CTRL_SCH_REG),
|
|
(UINT32) (BIT23 | BIT22 | BIT6)
|
|
);
|
|
|
|
//
|
|
// HOST_CTRL_PORT_LINK_REG - SuperSpeed Port Link Control
|
|
// Address Offset: 0x80EC
|
|
// Value: [17] 1b
|
|
//
|
|
MmioOr32 (
|
|
(XhciMmioBase + R_XHCI_MEM_HOST_CTRL_PORT_LINK_REG),
|
|
(UINT32) (BIT17)
|
|
);
|
|
|
|
//
|
|
// USB2_LINK_MGR_CTRL_REG1 - USB2 Port Link Control 1, 2, 3, 4
|
|
// Address Offset: 0x80F0
|
|
// [127:96] is mapped to DW4 at offset 80FCh-80FFh [25] 1b
|
|
// [31:0] is mapped to DW1 at offset 80F0h-80F3h [20] 0b
|
|
//
|
|
MmioOr32 (
|
|
(XhciMmioBase + R_XHCI_MEM_USB2_LINK_MGR_CTRL_REG1_DW4),
|
|
(UINT32) (BIT25)
|
|
);
|
|
MmioAnd32 (
|
|
(XhciMmioBase + R_XHCI_MEM_USB2_LINK_MGR_CTRL_REG1_DW1),
|
|
(UINT32) ~(BIT20)
|
|
);
|
|
if (((HcInfo->DeviceId == V_XHCI_DID_CNP_LP) && (PchStepping () >= PCH_B0)) || (HcInfo->DeviceId == V_XHCI_DID_CNP_H)) {
|
|
MmioOr32 (
|
|
(XhciMmioBase + R_XHCI_MEM_USB2_LINK_MGR_CTRL_REG1_DW1),
|
|
(UINT32) (BIT22)
|
|
);
|
|
}
|
|
|
|
//
|
|
// HOST_CTRL_BW_CTRL_REG - Host Controller Bandwith Control Register
|
|
// Address Offset: 0x8100
|
|
// Value: [21] 1b [20] 1b
|
|
// Program only for IP V16.0 or for devices with IDs:
|
|
// 0x8A13, 0x34ED or 0x38ED
|
|
//
|
|
if ((HcInfo->IpVersion == V16_0) ||
|
|
(HcInfo->DeviceId == V_XHCI_DID_CPU_V17_0_1) ||
|
|
(HcInfo->DeviceId == V_XHCI_DID_PCH_V17_1_1) ||
|
|
(HcInfo->DeviceId == V_XHCI_DID_PCH_V17_1_2)) {
|
|
MmioOr32 (
|
|
(XhciMmioBase + R_XHCI_MEM_HOST_CTRL_BW_CTRL_REG),
|
|
(UINT32) (BIT20 | BIT21)
|
|
);
|
|
}
|
|
|
|
//
|
|
// HOST_IF_CTRL_REG - Host Controller Interface Control Register
|
|
// Address Offset: 0x8108
|
|
// Value: [30] 1b
|
|
//
|
|
MmioOr32 (
|
|
(XhciMmioBase + R_XHCI_MEM_HOST_IF_CTRL_REG),
|
|
(UINT32) (BIT30)
|
|
);
|
|
|
|
//
|
|
// HOST_CTRL_TRM_REG2 - Host Controller Transfer Manager Control 2
|
|
// Address Offset: 0x8110
|
|
// Value: [20] 1b, [11] 1b, [2] 0b,
|
|
//
|
|
MmioAndThenOr32 (
|
|
(XhciMmioBase + R_XHCI_MEM_HOST_CTRL_TRM_REG2),
|
|
(UINT32)~(BIT2),
|
|
(UINT32) (BIT20 | BIT11)
|
|
);
|
|
|
|
//
|
|
// HOST_CTRL_BW_MAX_REG - MAX BW Control Reg 4
|
|
// Address Offset: 0x8128
|
|
// Value: V16_0 [47:36] - 0xFFF for CNP A0, 0x528 (default) for rest
|
|
// Value: [23:12] 0x753
|
|
//
|
|
if (HcInfo->OnSouth) {
|
|
if (((HcInfo->DeviceId == V_XHCI_DID_CNP_LP) || (HcInfo->DeviceId == V_XHCI_DID_CNP_H)) && (PchStepping () == PCH_A0)) {
|
|
MmioOr32 (
|
|
(XhciMmioBase + R_XHCI_MEM_HOST_CTRL_BW_MAX_REG + 4),
|
|
(UINT32) (0xFFF << 4)
|
|
);
|
|
}
|
|
MmioAndThenOr32 (
|
|
(XhciMmioBase + R_XHCI_MEM_HOST_CTRL_BW_MAX_REG),
|
|
(UINT32)~(B_XHCI_MEM_HOST_CTRL_BW_MAX_REG_MAX_HS_BW),
|
|
(UINT32) (0x753 << N_XHCI_MEM_HOST_CTRL_BW_MAX_REG_MAX_HS_BW)
|
|
);
|
|
}
|
|
|
|
//
|
|
// AUX_CTRL_REG2 - Aux PM Control Register 2
|
|
// Address Offset: 0x8154
|
|
// Value: [21] 0b, [13] 1b
|
|
//
|
|
MmioAndThenOr32 (
|
|
(XhciMmioBase + R_XHCI_MEM_AUX_CTRL_REG2),
|
|
(UINT32) ~(BIT21),
|
|
(UINT32) (BIT13)
|
|
);
|
|
|
|
//
|
|
// xHCI Aux Clock Control Register
|
|
// Address Offset: 0x816C
|
|
// [11:8] 0h
|
|
// [19] 1b, [18] 1b, [17] 1b, [16] 1b, [14] 1b, [5] 1b, [4] 1b, [3] 1b, [2] 1b
|
|
//
|
|
MmioAndThenOr32 (
|
|
(XhciMmioBase + R_XHCI_MEM_AUXCLKCTL),
|
|
(UINT32) ~(BIT11 | BIT10 | BIT9 | BIT8),
|
|
(UINT32) (BIT19 | BIT18 | BIT17 | BIT16 | BIT14 | BIT5 | BIT4 | BIT3 | BIT2)
|
|
);
|
|
|
|
//
|
|
// HOST_IF_PWR_CTRL_REG0 - Power Scheduler Control 0
|
|
// Address Offset: 0x8140
|
|
// Value: [31:24] 0xFF, [23:12] 0x00F, [11:0] 0x03C
|
|
//
|
|
MmioWrite32 (
|
|
(XhciMmioBase + R_XHCI_MEM_HOST_IF_PWR_CTRL_REG0),
|
|
0xFF00F03C
|
|
);
|
|
|
|
//
|
|
// HOST_IF_PWR_CTRL_REG1 - Power Scheduler Control 1
|
|
// Address Offset: 0x8144
|
|
// Value: [24] 1b
|
|
// Applies only to devices with IDs 0x38ED or 0x3DED
|
|
//
|
|
if ((HcInfo->DeviceId == V_XHCI_DID_PCH_V17_1_2) ||
|
|
(HcInfo->DeviceId == V_XHCI_DID_PCH_V17_1_3)) {
|
|
MmioOr32 (
|
|
(XhciMmioBase + R_XHCI_MEM_HOST_IF_PWR_CTRL_REG1),
|
|
(UINT32) (BIT24)
|
|
);
|
|
}
|
|
|
|
//
|
|
// USBLPM - USB LPM Parameters
|
|
// Address Offset: 0x8170
|
|
// Value: [16] 0b
|
|
//
|
|
MmioAnd32 (
|
|
(XhciMmioBase + R_XHCI_MEM_USBLPM),
|
|
(UINT32)~(BIT16)
|
|
);
|
|
|
|
//
|
|
// xHC Latency Tolerance Parameters - LTV Control
|
|
// Address Offset: 0x8174
|
|
// Value: [30] 1b
|
|
// [24] 1b
|
|
// [11:0] 0xC0A (for xHCI in PCH)
|
|
//
|
|
Data32And = (UINT32)~(0);
|
|
Data32Or = (BIT30 | BIT24);
|
|
|
|
if (HcInfo->OnSouth) {
|
|
Data32And = (UINT32)~(0xFFF);
|
|
Data32Or |= 0xC0A;
|
|
}
|
|
MmioAndThenOr32 (
|
|
(XhciMmioBase + R_XHCI_MEM_XLTP_LTV1),
|
|
Data32And,
|
|
Data32Or
|
|
);
|
|
|
|
//
|
|
// xHC Latency Tolerance Parameters - High Idle Time Control
|
|
// Address Offset: 0x817C
|
|
//
|
|
// For devices with IDs 0x38ED or 0x3DED
|
|
// Value - 0x00050001
|
|
// else
|
|
// Value - 0x033200A3
|
|
//
|
|
MmioWrite32 (
|
|
(XhciMmioBase + R_XHCI_MEM_LTVHIT),
|
|
HcInfo->UsbLtrHigh
|
|
);
|
|
|
|
//
|
|
// xHC Latency Tolerance Parameters - Medium Idle Time Control
|
|
// Address Offset: 0x8180
|
|
//
|
|
// For devices with IDs 0x38ED or 0x3DED
|
|
// Value - 0x00050001
|
|
// else
|
|
// Value - 0x00CB0028
|
|
//
|
|
MmioWrite32 (
|
|
(XhciMmioBase + R_XHCI_MEM_LTVMIT),
|
|
HcInfo->UsbLtrMid
|
|
);
|
|
|
|
//
|
|
// xHC Latency Tolerance Parameters - Low Idle Time Control
|
|
// Address Offset: 0x8184
|
|
//
|
|
// For devices with IDs 0x38ED or 0x3DED
|
|
// Value - 0x00050001
|
|
// else
|
|
// Value - 0x00CB001E
|
|
//
|
|
MmioWrite32 (
|
|
(XhciMmioBase + R_XHCI_MEM_LTVLIT),
|
|
HcInfo->UsbLtrLow
|
|
);
|
|
|
|
//
|
|
// Host Controller Misc Reg
|
|
// Address Offset: 0x80B0
|
|
// Value: [23] 1b, [18:16] 000b
|
|
//
|
|
MmioAndThenOr32 (
|
|
(XhciMmioBase + R_XHCI_MEM_HOST_CTRL_MISC_REG),
|
|
(UINT32)~(BIT18| BIT17 | BIT16),
|
|
(UINT32) (BIT23)
|
|
);
|
|
|
|
//
|
|
// Host Controller Misc Reg 2
|
|
// Address Offset: 0x80B4
|
|
// Value: [28] 1b, [7] 1b, [2] 1b
|
|
//
|
|
MmioOr32 (
|
|
(XhciMmioBase + R_XHCI_MEM_HOST_CTRL_MISC_REG_2),
|
|
(UINT32) (BIT28 | BIT7 | BIT2)
|
|
);
|
|
|
|
//
|
|
// HOST_BW_OV_HS_REG - High Speed TT Bandwidth Overhead
|
|
// Address Offset: 0x80C8
|
|
// Value: For IP V16.0 or V17.1 [23:12] 0Ah
|
|
// [11:0] 0h
|
|
//
|
|
//
|
|
Data32And = (UINT32)~(B_XHCI_MEM_HOST_BW_OV_HS_REG_OVHD_HSTTBW);
|
|
Data32Or = 0;
|
|
if ((HcInfo->IpVersion == V16_0) || (HcInfo->IpVersion == V17_1)) {
|
|
Data32And &= (UINT32)~(B_XHCI_MEM_HOST_BW_OV_HS_REG_OVHD_HSBW);
|
|
Data32Or = (0xA << N_XHCI_MEM_HOST_BW_OV_HS_REG_OVHD_HSBW);
|
|
}
|
|
MmioAndThenOr32 (
|
|
(XhciMmioBase + R_XHCI_MEM_HOST_BW_OV_HS_REG),
|
|
Data32And,
|
|
Data32Or
|
|
);
|
|
|
|
//
|
|
// THROTT - XHCI Throttle Control
|
|
// Address Offset: 0x819C
|
|
// Value: [20] 1b, [14] 1b, [13] 1b, [12] 1b, [11:8] 0x3, [7:4] 0x7, [3:0] 0xD
|
|
// For IP V16.0 [16] 1b
|
|
//
|
|
Data32Or = (UINT32) (BIT20 | BIT14 | BIT13 | BIT12 | BIT9 | BIT8 | BIT6 | BIT5 | BIT4 | BIT3 | BIT2 | BIT0);
|
|
if (HcInfo->IpVersion == V16_0) {
|
|
Data32Or |= (BIT16);
|
|
}
|
|
MmioAndThenOr32 (
|
|
(XhciMmioBase + R_XHCI_MEM_THROTT),
|
|
(UINT32) ~(BIT11 | BIT10 | BIT7 | BIT1),
|
|
Data32Or
|
|
);
|
|
|
|
//
|
|
// THROTT2 - XHCI Throttle Control2
|
|
// Address Offset: 0x81B4
|
|
// Value: [31:0] 0h
|
|
//
|
|
MmioWrite32 (
|
|
(XhciMmioBase + R_XHCI_MEM_THROTT2),
|
|
0x0
|
|
);
|
|
|
|
//
|
|
// D0I2CTRL - D0I2 Control Register
|
|
// Address Offset: 0x81BC
|
|
// Value: [31] 1b, [29:26] 4h, [25:22] 4h, [20:16] 4h, [15:4] 20h
|
|
// For USB IP V16.0 or device with ID 0x8A13
|
|
// [3] 1b
|
|
//
|
|
Data32Or = (UINT32) (BIT31 | BIT28 | BIT24 | BIT18 | (0x20 << N_XHCI_MEM_D0I2CTRL_MSI_IDLE_THRESHOLD));
|
|
if ((HcInfo->IpVersion == V16_0) ||
|
|
(HcInfo->DeviceId == V_XHCI_DID_PCH_V17_1_1) ||
|
|
(HcInfo->IsCpuStepA0)) {
|
|
Data32Or |= BIT3;
|
|
}
|
|
MmioAndThenOr32 (
|
|
(XhciMmioBase + R_XHCI_MEM_D0I2CTRL),
|
|
(UINT32)~(0x3FDFFFF0),
|
|
Data32Or
|
|
);
|
|
|
|
//
|
|
// D0i2SchAlarmCtrl - D0i2 Scheduler Alarm Control Register
|
|
// Address Offset: 0x81C0
|
|
// Value: [28:16] 0Fh, [12:0] 05h
|
|
//
|
|
MmioAndThenOr32 (
|
|
(XhciMmioBase + R_XHCI_MEM_D0I2SCH_ALARM_CTRL),
|
|
(UINT32)~(0x1FFF1FFF),
|
|
(UINT32) (BIT19 | BIT18 | BIT17 | BIT16 | BIT2 | BIT0)
|
|
);
|
|
|
|
//
|
|
// USB2PMCTRL - USB2 Power Management Control
|
|
// Address Offset: 0x81C4
|
|
// Value: [11] 1b, [8] 1b, [3:2] 10b, [1:0] 10b
|
|
//
|
|
MmioOr32 (
|
|
(XhciMmioBase + R_XHCI_MEM_USB2PMCTRL),
|
|
(UINT32) (BIT11 | BIT8 | BIT3 | BIT1)
|
|
);
|
|
|
|
//
|
|
// TRBPRFCTRLREG1 - TRB Prefetch Control Register 1
|
|
// Address Offset: 0x81D0
|
|
// Value: [23] 1b, [2] 1b
|
|
// For CNP-LP Ax steppings [25] 1b else [25] 0b
|
|
// For CNP-H or CNP-LP Bx or newer [0] 1b
|
|
//
|
|
Data32Or = (UINT32) (BIT23 | BIT2);
|
|
Data32And = (UINT32)~(0);
|
|
if (((HcInfo->DeviceId == V_XHCI_DID_CNP_LP) && (PchStepping () >= PCH_B0)) || (HcInfo->DeviceId == V_XHCI_DID_CNP_H)) {
|
|
Data32And &= (UINT32)~(BIT25);
|
|
}
|
|
if ((HcInfo->DeviceId == V_XHCI_DID_CNP_H) || (PchStepping () >= PCH_B0)) {
|
|
Data32Or |= BIT0;
|
|
}
|
|
|
|
MmioAndThenOr32 (
|
|
(XhciMmioBase + R_XHCI_MEM_TRBPRFCTRLREG1),
|
|
Data32And,
|
|
Data32Or
|
|
);
|
|
|
|
//
|
|
// TRBPRFCACHEINVREG - TRB Prefetch Cache Invalidation Register 1
|
|
// Address Offset: 0x81D8
|
|
// Value: [23:17] 7Fh,
|
|
//
|
|
MmioOr32 (
|
|
(XhciMmioBase + R_XHCI_MEM_TRBPRFCACHEINVREG),
|
|
(0x7F << N_XHCI_MEM_TRBPRFCACHEINVREG_EN_TRB_FLUSH)
|
|
);
|
|
|
|
//
|
|
// HOST_CTRL_SUS_LINK_PORT_REG
|
|
// Address Offset: 0x81F8
|
|
// Value: [8:7] 1h
|
|
//
|
|
MmioAndThenOr32 (
|
|
(XhciMmioBase + R_XHCI_MEM_HOST_CTRL_SUS_LINK_PORT_REG),
|
|
(UINT32) ~(BIT8 | BIT7),
|
|
(UINT32) (BIT7)
|
|
);
|
|
|
|
if ((HcInfo->IpVersion == V17_0) || (HcInfo->IpVersion == V17_1)) {
|
|
//
|
|
// PMREQ Control Register
|
|
// Address Offset: 0x83D0
|
|
// Value: [15] 1b
|
|
// Applies only to IP V17.0 and V17.1
|
|
// Additionally for device with ID 0x34ED
|
|
// [12] 1b
|
|
//
|
|
Data32Or = (UINT32) (BIT15);
|
|
if (HcInfo->DeviceId == V_XHCI_DID_PCH_V17_1_1) {
|
|
Data32Or |= BIT12;
|
|
}
|
|
MmioOr32 (
|
|
(XhciMmioBase + R_XHCI_MEM_PMREQ_CTRL_REG),
|
|
Data32Or
|
|
);
|
|
|
|
if ((HcInfo->DeviceId == V_XHCI_DID_PCH_V17_1_1) ||
|
|
((HcInfo->DeviceId == V_XHCI_DID_CPU_V17_0_1) && (HcInfo->IsCpuStepA0))) {
|
|
//
|
|
// Enhanced Clock Gate Control Policy Reguster
|
|
// Address Offset: 0x83D8
|
|
// Applies only to devices with IDs 0x8A13 or 0x34ED
|
|
// Values: [3:2] 11b
|
|
//
|
|
MmioOr32 (
|
|
(XhciMmioBase + R_XHCI_MEM_ENH_CLK_GATE_CTRL),
|
|
(UINT32) (BIT3 | BIT2)
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
// DBCCTL - DBC Control
|
|
// Address Offset: 0x8760
|
|
// Values: [6:2] 1Fh [0] 1b
|
|
//
|
|
MmioOr32 (
|
|
(XhciMmioBase + R_XHCI_MEM_DBC_DBCCTL),
|
|
(UINT32) ((0x1F << N_XHCI_MEM_DBC_DBCCTL_DISC_RXD_CNT) | BIT0)
|
|
);
|
|
|
|
//
|
|
// HOST_CTRL_SSP_LINK_REG2
|
|
// Address Offset: 0x8E68
|
|
// Value: [24:23] 3h for CNP Ax else 0h
|
|
// [4] 1b for CNP Ax else 0b
|
|
//
|
|
if (((HcInfo->DeviceId == V_XHCI_DID_CNP_LP) || (HcInfo->DeviceId == V_XHCI_DID_CNP_H)) && (PchStepping () < PCH_B0)) {
|
|
MmioOr32 (
|
|
(XhciMmioBase + R_XHCI_MEM_HOST_CTRL_SSP_LINK_REG2),
|
|
(UINT32) (BIT24 | BIT23 | BIT4)
|
|
);
|
|
}
|
|
|
|
//
|
|
// HOST_CTRL_SSP_LFPS_REG2
|
|
// Address Offset: 0x8E74
|
|
// Value: [22:18] 3h
|
|
//
|
|
MmioAndThenOr32 (
|
|
XhciMmioBase + R_XHCI_MEM_HOST_CTRL_SSP_LFPS_REG2,
|
|
(UINT32) ~(0x7C0000),
|
|
(UINT32) (BIT19 | BIT18)
|
|
);
|
|
|
|
//
|
|
// HOST_CTRL_SSP_LFPS_REG3
|
|
// Address Offset: 0x8E78
|
|
// Value: [4:0] 3h
|
|
//
|
|
MmioAndThenOr32 (
|
|
XhciMmioBase + R_XHCI_MEM_HOST_CTRL_SSP_LFPS_REG3,
|
|
(UINT32) ~(0x1F),
|
|
(UINT32) (BIT1 | BIT0)
|
|
);
|
|
|
|
//
|
|
// HOST_CTRL_SSP_CONFIG_REG1
|
|
// Address Offset: 0x8E80
|
|
// Value: [29] 1b
|
|
//
|
|
MmioOr32 (
|
|
XhciMmioBase + R_XHCI_MEM_HOST_CTRL_SSP_CONFIG_REG1,
|
|
(UINT32) (BIT29)
|
|
);
|
|
|
|
//
|
|
// HOST_CTRL_USB3_RECAL
|
|
// Address Offset: 0x8E84
|
|
// Value:
|
|
// For IP V16.0 [30:28] = 111b, [19:18] = 10b
|
|
// For IP V17.0 [31] = 0b
|
|
//
|
|
if ((HcInfo->IpVersion == V16_0) || (HcInfo->IpVersion == V17_0)) {
|
|
switch (HcInfo->IpVersion) {
|
|
case V16_0:
|
|
Data32And = (UINT32)~(BIT18);
|
|
Data32Or = (UINT32) (BIT30 | BIT29 | BIT28 | BIT19);
|
|
break;
|
|
case V17_0:
|
|
Data32And = (UINT32)~(BIT31);
|
|
Data32Or = 0;
|
|
break;
|
|
default:
|
|
Data32And = (UINT32)~(0);
|
|
Data32Or = 0;
|
|
break;
|
|
}
|
|
MmioAndThenOr32 (
|
|
XhciMmioBase + R_XHCI_MEM_HOST_CTRL_USB3_RECAL,
|
|
Data32And,
|
|
Data32Or
|
|
);
|
|
}
|
|
|
|
//
|
|
// Set 1 to enable Super Speed Ports terminations on enabled ports only (PDO = 0)
|
|
// Required for Deep S3
|
|
//
|
|
XhciUsb3PortsMask = (UINT32)((1 << SsPortCount) - 1);
|
|
XhciUsb3Pdo = MmioRead32 (XhciMmioBase + R_PCH_XHCI_MEM_USB3PDO) & XhciUsb3PortsMask;
|
|
Data32 = (~XhciUsb3Pdo) & XhciUsb3PortsMask;
|
|
|
|
MmioAndThenOr32 (
|
|
XhciMmioBase + R_XHCI_MEM_SSPE,
|
|
(UINT32)~(XhciUsb3PortsMask),
|
|
Data32
|
|
);
|
|
|
|
//
|
|
// SSIC related programming
|
|
//
|
|
MmioOr32(
|
|
XhciMmioBase + R_XHCI_MEM_SSIC_CONF_REG2_PORT_1,
|
|
(UINT32) (B_XHCI_MEM_SSIC_CONF_REG2_PORT_UNUSED | B_XHCI_MEM_SSIC_CONF_REG2_PROG_DONE)
|
|
);
|
|
|
|
MmioOr32(
|
|
XhciMmioBase + R_XHCI_MEM_SSIC_CONF_REG2_PORT_2,
|
|
(UINT32) (B_XHCI_MEM_SSIC_CONF_REG2_PORT_UNUSED | B_XHCI_MEM_SSIC_CONF_REG2_PROG_DONE)
|
|
);
|
|
|
|
}
|
|
|
|
STATIC
|
|
BOOLEAN
|
|
IsS3Wakeup (
|
|
IN CONST EFI_PEI_SERVICES **PeiServices,
|
|
IN EFI_PEI_CPU_IO_PPI *CpuIo
|
|
)
|
|
{
|
|
UINT16 Pm1Sts;
|
|
UINT16 Pm1Cnt;
|
|
|
|
|
|
//
|
|
// Read the ACPI registers
|
|
//
|
|
Pm1Sts = CpuIo->IoRead16 (PeiServices, CpuIo, PcdGet16 (PcdPerfPkgAcpiIoPortBaseAddress) + R_ACPI_IO_PM1_STS);
|
|
Pm1Cnt = CpuIo->IoRead16 (PeiServices, CpuIo, PcdGet16 (PcdPerfPkgAcpiIoPortBaseAddress) + R_ACPI_IO_PM1_CNT);
|
|
|
|
//
|
|
// No power failure while S3_Resume, and only enter S3 boot mode once after OS standby.
|
|
//
|
|
if ((Pm1Sts & B_ACPI_IO_PM1_STS_WAK) != 0 && (Pm1Cnt & B_ACPI_IO_PM1_CNT_SLP_TYP) == V_ACPI_IO_PM1_CNT_S3) {
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
/**
|
|
Clear and disable XHCI Memory Space
|
|
|
|
@param[in] XhciPciBase XHCI PCI Base Address
|
|
**/
|
|
STATIC
|
|
VOID
|
|
DdtXhciMemorySpaceClose (
|
|
IN UINT64 XhciPciBase
|
|
)
|
|
{
|
|
//
|
|
// Clear memory resources
|
|
//
|
|
PciSegmentAnd16 (
|
|
XhciPciBase + PCI_COMMAND_OFFSET,
|
|
(UINT16) ~(EFI_PCI_COMMAND_MEMORY_SPACE)
|
|
);
|
|
|
|
PciSegmentWrite32 ((XhciPciBase + R_XHCI_CFG_BAR0), 0);
|
|
PciSegmentWrite32 ((XhciPciBase + R_XHCI_CFG_BAR0 + 4), 0);
|
|
}
|
|
|
|
/**
|
|
Returns USB3 PortSC register address base offset in xHCI MMIO space which
|
|
can be later used for iteration through all USB3 PortSC registers
|
|
|
|
@param[in] XhciMmioBase Memory BAR of the xHCI controller
|
|
|
|
@retval UINT32 Calculated PortSC register offset
|
|
**/
|
|
STATIC
|
|
UINT32
|
|
GetUsb3PortScBase (
|
|
IN UINT32 XhciMmioBase
|
|
)
|
|
{
|
|
UINT32 Usb2PortCount;
|
|
|
|
Usb2PortCount = GetUsb2PortCount (XhciMmioBase);
|
|
return (R_XHCI_MEM_PORTSC_START_OFFSET + (Usb2PortCount * S_XHCI_MEM_PORTSC_PORT_SPACING));
|
|
}
|
|
|
|
/**
|
|
Function for checking if one of the USB3 ports is used for debug purposes
|
|
|
|
@param[in] XhciMmioBase Memory BAR of the xHCI controller
|
|
@param[out] RetDebugEnable Debug 0 indexed port number if found, otherwise 0xFF returned
|
|
|
|
@retval BOOLEAN TRUE if debug port found on one of the ports
|
|
**/
|
|
STATIC
|
|
BOOLEAN
|
|
GetDebugPortIndex (
|
|
IN UINT32 XhciMmioBase,
|
|
OUT UINT32 *RetDebugPortSsIndex
|
|
)
|
|
{
|
|
UINT32 DebugPortSsIndex;
|
|
UINT32 SsPortCount;
|
|
UINT32 HsPortCount;
|
|
UINT32 DebugPort;
|
|
UINT32 CapabilityPointer;
|
|
UINT32 Capability;
|
|
BOOLEAN DebugEnable;
|
|
|
|
HsPortCount = GetUsb2PortCount (XhciMmioBase);
|
|
SsPortCount = GetUsb3PortCount (XhciMmioBase);
|
|
|
|
//
|
|
// Get debug enable status in order to skip some XHCI init which
|
|
// may break XHCI debug
|
|
//
|
|
CapabilityPointer = (UINT32) (XhciMmioBase + (MmioRead32 (XhciMmioBase + R_XHCI_MEM_HCCPARAMS1) >> 16) * 4);
|
|
DebugEnable = FALSE;
|
|
DebugPortSsIndex = 0xFF;
|
|
Capability = MmioRead32 (CapabilityPointer);
|
|
|
|
DEBUG ((DEBUG_INFO, "XHCI Capability Pointer = 0x%x\n", CapabilityPointer));
|
|
|
|
while (TRUE) {
|
|
if ((Capability & B_XHCI_MEM_CAPABILITY_ID) == V_XHCI_MEM_DBC_DCID) {
|
|
//
|
|
// Check DCR bit in DCCTRL register (Debug Capability Base + 20h), if set, debug device is running
|
|
//
|
|
if ((MmioRead32 (CapabilityPointer + R_XHCI_MEM_DBC_DCCTRL) & B_XHCI_MEM_DBC_DCCTRL_DCR) != 0) {
|
|
DebugEnable = TRUE;
|
|
//
|
|
// Get debug port number [24:31] in DCST register which starts from 1
|
|
//
|
|
DebugPort = (MmioRead32 (CapabilityPointer + R_XHCI_MEM_DBC_DCST) >> N_XHCI_MEM_DBC_DCST_DBG_PORT_NUMBER);
|
|
//
|
|
// Veryfing if debug port number falls within Super Speed port boundaries
|
|
//
|
|
if (DebugPort > HsPortCount) {
|
|
if (DebugPort - HsPortCount < SsPortCount) {
|
|
//
|
|
// Translate to 0-based super speed port numbering
|
|
//
|
|
DebugPortSsIndex = DebugPort - HsPortCount - 1;
|
|
DEBUG ((DEBUG_INFO, "DebugPortSsIndex = ?%d\n", DebugPortSsIndex));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if ((((Capability & B_XHCI_MEM_CAPABILITY_NEXT_CAP_PTR) >> N_XHCI_MEM_CAPABILITY_NEXT_CAP_PTR) & B_XHCI_MEM_CAPABILITY_ID) == 0) {
|
|
//
|
|
// Reached the end of list, quit
|
|
//
|
|
break;
|
|
}
|
|
CapabilityPointer += ((Capability & B_XHCI_MEM_CAPABILITY_NEXT_CAP_PTR) >> N_XHCI_MEM_CAPABILITY_NEXT_CAP_PTR) * 4;
|
|
Capability = MmioRead32 (CapabilityPointer);
|
|
}
|
|
|
|
*RetDebugPortSsIndex = DebugPortSsIndex;
|
|
|
|
return DebugEnable;
|
|
}
|
|
|
|
/*
|
|
Helper function to initiate reset on USB3 ports
|
|
|
|
@param[in] XhciMmioBase Memory BAR of the xHCI controller
|
|
*/
|
|
STATIC
|
|
VOID
|
|
XhciInitiatePortReset (
|
|
IN UINT32 XhciMmioBase
|
|
)
|
|
{
|
|
BOOLEAN DebugEnable;
|
|
UINT32 PortSCxUsb3Base;
|
|
UINT32 DebugPortSsIndex;
|
|
UINT32 UsbPort;
|
|
UINT32 SsPortCount;
|
|
//
|
|
// Perform WPR on USB3 port except for the port has DBC enabled.
|
|
//
|
|
//
|
|
// Get debug enable status in order to skip some XHCI init which
|
|
// may break XHCI debug
|
|
//
|
|
DebugEnable = FALSE;
|
|
PortSCxUsb3Base = GetUsb3PortScBase (XhciMmioBase);
|
|
SsPortCount = GetUsb3PortCount (XhciMmioBase);
|
|
|
|
//
|
|
// Perform WPR on USB3 port except for the port has DBC enabled.
|
|
//
|
|
DebugEnable = GetDebugPortIndex (XhciMmioBase, &DebugPortSsIndex);
|
|
|
|
//
|
|
// Initiate warm reset to all USB3 ports except for the USB3 port which has Dbc enabled
|
|
//
|
|
for (UsbPort = 0; UsbPort < SsPortCount; UsbPort++) {
|
|
if ((DebugEnable) && (UsbPort == DebugPortSsIndex)) {
|
|
continue;
|
|
}
|
|
MmioAndThenOr32 (
|
|
XhciMmioBase + (PortSCxUsb3Base + (UsbPort * S_XHCI_MEM_PORTSC_PORT_SPACING)),
|
|
(UINT32) ~ (B_XHCI_MEM_PORTSCXUSB3_PED),
|
|
B_XHCI_MEM_PORTSCXUSB3_WPR
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
Configures PCH xHCI device
|
|
|
|
@param[in] SiPolicy The SI Policy PPI instance
|
|
@param[in] TempMemBaseAddr Temporary Memory Base Address for PCI
|
|
devices to be used to initialize MMIO
|
|
registers.
|
|
|
|
@retval EFI_SUCCESS The function completed successfully
|
|
@retval EFI_OUT_OF_RESOURCES Do not have enough resources to initialize the driver
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
DdtConfigureXhci (
|
|
IN UINT32 TempMemBaseAddr,
|
|
IN BOOLEAN IsS3BootMode
|
|
)
|
|
{
|
|
USB_CONTROLLER_INFO HcInfo;
|
|
UINT32 XhciMmioBase;
|
|
UINT64 XhciPciBase;
|
|
|
|
|
|
DEBUG ((DEBUG_INFO, "DdtConfigureXhci() - Start\n"));
|
|
|
|
XhciMmioBase = TempMemBaseAddr;
|
|
|
|
XhciPciBase = PCI_SEGMENT_LIB_ADDRESS (
|
|
DEFAULT_PCI_SEGMENT_NUMBER_PCH,
|
|
DEFAULT_PCI_BUS_NUMBER_PCH,
|
|
PCI_DEVICE_NUMBER_PCH_XHCI,
|
|
PCI_FUNCTION_NUMBER_PCH_XHCI,
|
|
0
|
|
);
|
|
|
|
GetXhciControllerInfo (XhciPciBase, &HcInfo);
|
|
|
|
///
|
|
/// Assign memory resources
|
|
///
|
|
DdtXhciMemorySpaceOpen (
|
|
XhciPciBase,
|
|
XhciMmioBase
|
|
);
|
|
|
|
MmioOr32 (
|
|
XhciMmioBase + R_XHCI_MEM_HOST_CTRL_PORT_LINK_REG,
|
|
(UINT32) (BIT0)
|
|
);
|
|
|
|
DdtXhciHcInit (
|
|
&HcInfo,
|
|
XhciPciBase,
|
|
XhciMmioBase
|
|
);
|
|
|
|
//
|
|
// Initiate USB ports reset after Host Controller initialization is done
|
|
//
|
|
|
|
if (!(IsS3BootMode)) {
|
|
XhciInitiatePortReset (XhciMmioBase);
|
|
}
|
|
|
|
///
|
|
/// Clear memory resources
|
|
///
|
|
DdtXhciMemorySpaceClose (
|
|
XhciPciBase
|
|
);
|
|
|
|
DEBUG ((DEBUG_INFO, "DdtConfigureXhci() - End\n"));
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS
|
|
EFIAPI
|
|
PchDdtUsbPeiEntryPoint (
|
|
IN EFI_PEI_FILE_HANDLE FileHandle,
|
|
IN CONST EFI_PEI_SERVICES **PeiServices
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
BOOLEAN IsS3BootMode;
|
|
|
|
IsS3BootMode = IsS3Wakeup (PeiServices, (**PeiServices).CpuIo);
|
|
//
|
|
// Configure PCH xHCI
|
|
//
|
|
Status = DdtConfigureXhci (PcdGet32 (PcdSiliconInitTempMemBaseAddr), IsS3BootMode);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
return Status;
|
|
}
|