summaryrefslogtreecommitdiff
path: root/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchRootPorts.c
diff options
context:
space:
mode:
Diffstat (limited to 'ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchRootPorts.c')
-rw-r--r--ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchRootPorts.c2154
1 files changed, 2154 insertions, 0 deletions
diff --git a/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchRootPorts.c b/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchRootPorts.c
new file mode 100644
index 0000000..e9ae324
--- /dev/null
+++ b/ReferenceCode/Chipset/LynxPoint/PchInit/Dxe/PchRootPorts.c
@@ -0,0 +1,2154 @@
+/** @file
+ This file contains functions that initializes PCI Express Root Ports of PCH.
+
+@copyright
+ Copyright (c) 1999 - 2014 Intel Corporation. All rights reserved
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.
+
+ This file contains an 'Intel Peripheral Driver' and uniquely
+ identified as "Intel Reference Module" and is
+ licensed for Intel CPUs and chipsets under the terms of your
+ license agreement with Intel or your vendor. This file may
+ be modified by the user, subject to additional terms of the
+ license agreement
+
+**/
+#include "PchInit.h"
+// AMI_OVERRIDE, [EIP84720]>
+#include "Token.h"
+// AMI_OVERRIDE, [EIP84720]<
+
+#ifdef TRAD_FLAG
+UINT32 PchHPcieHsioAddr[] = {
+ 0xE9002E40,
+ 0xE9002C40,
+ 0xE9002A40,
+ 0xE9002840,
+ 0xE9002640,
+ 0xE9002440,
+ 0xE9002240,
+ 0xE9002040,
+ 0xEA002040,
+ 0xEA002240
+};
+#endif // TRAD_FLAG
+
+#ifdef ULT_FLAG
+UINT32 PchLpPcieHsioAddr[] = {
+ 0xE9002440,
+ 0xE9002640,
+ 0xE9000840,
+ 0xE9000A40,
+ 0xE9000C40,
+ 0xE9000E40,
+ 0xE9001040,
+ 0xE9001240,
+ 0xEA002040,
+ 0xEA002240,
+ 0xEA002440,
+ 0xEA002640
+};
+#endif // ULT_FLAG
+
+/**
+ Set an Init Root Port Downstream devices S3 dispatch item, this function may assert if any error happend
+
+ @param[in] RootPortBus Pci Bus Number of the root port
+ @param[in] RootPortDevice Pci Device Number of the root port
+ @param[in] RootPortFunc Pci Function Number of the root port
+ @param[in] TempBusNumberMin Minimal temp bus number that can be assigned to the root port (as secondary
+ bus number) and its down stream switches
+ @param[in] TempBusNumberMax Maximal temp bus number that can be assigned to the root port (as subordinate
+ bus number) and its down stream switches
+
+ @retval EFI_SUCCESS The function completed successfully
+**/
+EFI_STATUS
+SetInitRootPortDownstreamS3Item (
+ IN UINT8 RootPortBus,
+ IN UINT8 RootPortDevice,
+ IN UINT8 RootPortFunc,
+ IN UINT8 TempBusNumberMin,
+ IN UINT8 TempBusNumberMax
+ )
+{
+ EFI_STATUS Status;
+#ifdef EFI_S3_RESUME
+ STATIC EFI_PCH_S3_SUPPORT_PROTOCOL *PchS3Support;
+ STATIC EFI_PCH_S3_PARAMETER_INIT_PCIE_ROOT_PORT_DOWNSTREAM S3ParameterRootPortDownstream;
+ STATIC EFI_PCH_S3_DISPATCH_ITEM S3DispatchItem = {
+ PchS3ItemTypeInitPcieRootPortDownstream,
+ &S3ParameterRootPortDownstream
+ };
+ EFI_PHYSICAL_ADDRESS S3DispatchEntryPoint;
+
+ if (!PchS3Support) {
+ ///
+ /// Get the PCH S3 Support Protocol
+ ///
+ Status = gBS->LocateProtocol (
+ &gEfiPchS3SupportProtocolGuid,
+ NULL,
+ (VOID **) &PchS3Support
+ );
+ ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ S3ParameterRootPortDownstream.RootPortBus = RootPortBus;
+ S3ParameterRootPortDownstream.RootPortDevice = RootPortDevice;
+ S3ParameterRootPortDownstream.RootPortFunc = RootPortFunc;
+ S3ParameterRootPortDownstream.TempBusNumberMin = TempBusNumberMin;
+ S3ParameterRootPortDownstream.TempBusNumberMax = TempBusNumberMax;
+ Status = PchS3Support->SetDispatchItem (
+ PchS3Support,
+ &S3DispatchItem,
+ &S3DispatchEntryPoint
+ );
+ ASSERT_EFI_ERROR (Status);
+ ///
+ /// Save the script dispatch item in the Boot Script
+ ///
+ SCRIPT_DISPATCH (EFI_ACPI_S3_RESUME_SCRIPT_TABLE, S3DispatchEntryPoint);
+#else
+ Status = EFI_SUCCESS;
+#endif
+ return Status;
+}
+
+/**
+ Perform Initialization of the Downstream Root Ports.
+
+ @param[in] PchPlatformPolicy The PCH Platform Policy protocol
+ @param[in] RootComplexBar RCBA of the PCH
+ @param[in] PmBase The PM I/O Base address of the PCH
+ @param[in, out] FuncDisableReg The function disable register. IN / OUT parameter.
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER The PCIe Root Port Number of D28:F0 is not found
+ or invalid
+**/
+EFI_STATUS
+PchInitRootPorts (
+ IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy,
+ IN UINT32 RootComplexBar,
+ IN UINT16 PmBase,
+ IN OUT UINT32 *FuncDisableReg
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Data32And;
+ UINT32 Data32Or;
+ PCH_PCI_EXPRESS_CONFIG *PciExpressConfig;
+ UINT32 RpEnableMask;
+ UINT8 PortIndex;
+ UINTN RPBase;
+ UINT32 LoopTime;
+ UINTN PciD31F0RegBase;
+ UINTN PciD31F2RegBase;
+ UINTN PciD28F0RegBase;
+ UINTN PciD28F4RegBase;
+ UINT32 RpFnAnd;
+ UINT32 RpFnOr;
+ UINT32 StrpFuseCfg1;
+ UINT32 StrpFuseCfg2;
+ UINT8 RpLaneOwner;
+ UINT8 GbePort;
+ UINT8 NandPort;
+ UINT16 LpcDeviceId;
+ UINT32 BitMask;
+ UINT32 BitValue;
+ UINT8 FuncNum;
+ UINT8 RpPortFuncIndex;
+ UINT8 Func0PortNum;
+ ///
+ /// Whether a root port is hidden by another one with width > x1
+ ///
+ UINT32 RpHiddenMask;
+ ///
+ /// Subtractive Decode ports if enabled
+ ///
+ UINT32 SubDecodePort;
+ PCH_SERIES PchSeries;
+ UINT8 Mask;
+ BOOLEAN LanEnabled;
+
+ DEBUG ((EFI_D_INFO, "PchInitRootPorts() Start\n"));
+
+ PchSeries = GetPchSeries();
+ Status = EFI_SUCCESS;
+ RpEnableMask = 0;
+ RpHiddenMask = 0;
+ PciExpressConfig = PchPlatformPolicy->PciExpressConfig;
+ Data32And = 0xFFFFFFFF;
+ Data32Or = 0;
+ PciD31F0RegBase = MmPciAddress (
+ 0,
+ PchPlatformPolicy->BusNumber,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC,
+ 0
+ );
+ PciD31F2RegBase = MmPciAddress (
+ 0,
+ PchPlatformPolicy->BusNumber,
+ PCI_DEVICE_NUMBER_PCH_SATA,
+ PCI_FUNCTION_NUMBER_PCH_SATA,
+ 0
+ );
+ PciD28F0RegBase = MmPciAddress (
+ 0,
+ PchPlatformPolicy->BusNumber,
+ PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS,
+ GetPchPcieRpfn( RootComplexBar, PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_1),
+ 0
+ );
+ PciD28F4RegBase = MmPciAddress (
+ 0,
+ PchPlatformPolicy->BusNumber,
+ PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS,
+ GetPchPcieRpfn( RootComplexBar, PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_5),
+ 0
+ );
+ LpcDeviceId = MmioRead16 (PciD31F0RegBase + R_PCH_LPC_DEVICE_ID);
+ FuncNum = 0;
+ RpPortFuncIndex = 0;
+ Func0PortNum = 0xFF;
+ RpLaneOwner = 0;
+
+ ///
+ /// Configure root port function number mapping and configuration space hiding
+ /// Program at end of function
+ ///
+ RpFnAnd = 0xFFFFFFFF;
+ RpFnOr = 0;
+ for (PortIndex = 0; PortIndex < GetPchMaxPciePortNum (); PortIndex++) {
+ //
+ // if RootPortFunctionSwapping is enabled, Function number is equal to port index.
+ // else, use the function number mapping from platform policy.
+ //
+ if ((PchPlatformPolicy->Revision >= DXE_PCH_PLATFORM_POLICY_PROTOCOL_REVISION_3) &&
+ (PciExpressConfig->RootPortFunctionSwapping == 1)) {
+ FuncNum = PortIndex;
+ } else {
+ FuncNum = PciExpressConfig->RootPort[PortIndex].FunctionNumber;
+ }
+ RpFnAnd &= (UINT32) (~((B_PCH_RCRB_RPFN_RP1CH | B_PCH_RCRB_RPFN_RP1FN) << (PortIndex * S_PCH_RCRB_PRFN_RP_FIELD)));
+ RpFnOr |= (FuncNum) << (PortIndex * S_PCH_RCRB_PRFN_RP_FIELD);
+
+ if (FuncNum < GetPchMaxPciePortNum ()) {
+ ///
+ /// If FunctionNumber of the PCIE Root Port is duplicated, then disable the corresponding "Enable" field.
+ ///
+ if (RpPortFuncIndex & (UINT8) (1 << FuncNum)) {
+ DEBUG ((EFI_D_ERROR, " Hide Root Port %x since its FunctionNumber is duplicated.\n", PortIndex + 1));
+ ASSERT (FALSE);
+ PciExpressConfig->RootPort[PortIndex].Hide = PCH_DEVICE_ENABLE;
+ PciExpressConfig->RootPort[PortIndex].Enable = PCH_DEVICE_DISABLE;
+ RpHiddenMask |= (1 << PortIndex);
+ }
+ ///
+ /// Set RpPortFuncIndex while the FunctionNumber is used.
+ ///
+ RpPortFuncIndex |= (UINT8) (1 << FuncNum);
+ } else {
+ ///
+ /// If FunctionNumber of the PCIE Root Port is outside 7, the Root Port Config Hide bit will be set.
+ /// If so, then disable the corresponding "Enable" field.
+ ///
+ DEBUG ((EFI_D_ERROR, " Root Port %x will be hidden since its FunctionNumber is out of 7.\n", PortIndex + 1));
+ ASSERT (FALSE);
+ PciExpressConfig->RootPort[PortIndex].Enable = PCH_DEVICE_DISABLE;
+ RpHiddenMask |= (1 << PortIndex);
+ }
+
+ RpFnOr |= ((PciExpressConfig->RootPort[PortIndex].Hide) ? B_PCH_RCRB_RPFN_RP1CH : 0) << (PortIndex * S_PCH_RCRB_PRFN_RP_FIELD);
+ ///
+ /// Func0PortNum indicates which PCIe Root Port is D28:F0
+ ///
+ if (FuncNum == 0) {
+ Func0PortNum = PortIndex;
+ }
+ }
+
+ if (Func0PortNum >= GetPchMaxPciePortNum ()) {
+ DEBUG ((EFI_D_ERROR, "The PCIe Root Port Number of D28:F0 is not found or invalid!\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+ ///
+ /// Hide PCIE root port 1-4 according to the PCIE port configuration 1
+ ///
+ StrpFuseCfg1 = MmioRead32 (PciD28F0RegBase + R_PCH_PCIE_STRPFUSECFG);
+ switch (StrpFuseCfg1 & (UINT32) B_PCH_PCIE_STRPFUSECFG_RPC) {
+ case V_PCH_PCIE_STRPFUSECFG_RPC_2_1_1:
+ ///
+ /// Port Configuration = 01b: 1x2, 2x1 Port 1 (x2), Port 2 (disabled), Ports 3, 4 (x1)
+ ///
+ RpHiddenMask |= BIT1;
+ break;
+
+ case V_PCH_PCIE_STRPFUSECFG_RPC_2_2:
+ ///
+ /// Port Configuration = 10b: 2x2 Port 1 (x2), Port 3 (x2), Ports 2, 4 (disabled)
+ ///
+ RpHiddenMask |= (BIT1 | BIT3);
+ break;
+
+ case V_PCH_PCIE_STRPFUSECFG_RPC_4:
+ ///
+ /// Port Configuration = 11b: 1x4 Port 1 (x4), Ports 2-4 (disabled)
+ ///
+ RpHiddenMask |= (BIT1 | BIT2 | BIT3);
+ break;
+
+ default:
+ break;
+ }
+
+ if (PchSeries == PchH) {
+ ///
+ /// Hide PCIE root port 5-8 according to the PCIE port configuration
+ ///
+ StrpFuseCfg2 = MmioRead32 (PciD28F4RegBase + R_PCH_PCIE_STRPFUSECFG);
+ switch (StrpFuseCfg2 & (UINT32) B_PCH_PCIE_STRPFUSECFG_RPC) {
+ case V_PCH_PCIE_STRPFUSECFG_RPC_2_1_1:
+ ///
+ /// Port Configuration = 01b: 1x2, 2x1 Port 5 (x2), Port 6 (disabled), Ports 7, 8 (x1)
+ ///
+ RpHiddenMask |= BIT5;
+ break;
+
+ case V_PCH_PCIE_STRPFUSECFG_RPC_2_2:
+ ///
+ /// Port Configuration = 10b: 2x2 Port 5 (x2), Port 7 (x2), Ports 6, 8 (disabled)
+ ///
+ RpHiddenMask |= (BIT5 | BIT7);
+ break;
+
+ case V_PCH_PCIE_STRPFUSECFG_RPC_4:
+ ///
+ /// Port Configuration = 11b: 1x4 Port 5 (x4), Ports 6-8 (disabled)
+ ///
+ RpHiddenMask |= (BIT5 | BIT6 | BIT7);
+ break;
+
+ default:
+ break;
+ }
+ }
+ ///
+ /// If GBE Over PCIe Enabled, then System BIOS must disable the PCI Express* Root Port
+ ///
+ LanEnabled = !(MmioRead32 (RootComplexBar + R_PCH_RCRB_BUC) & B_PCH_RCRB_BUC_LAN_DIS);
+
+ if ((StrpFuseCfg1 & B_PCH_PCIE_STRPFUSECFG_GBE_PCIE_PEN) && LanEnabled) {
+ GbePort = (UINT8) ((StrpFuseCfg1 & B_PCH_PCIE_STRPFUSECFG_GBE_PCIEPORTSEL) >> N_PCH_PCIE_STRPFUSECFG_GBE_PCIEPORTSEL);
+ } else {
+ GbePort = 0xFF;
+ }
+ ///
+ /// If NAND Over PCIe Enabled, then System BIOS must disable the PCI Express* Root Port
+ ///
+ if ((MmioRead32 (PciD31F2RegBase + 0x300) & BIT0) != 0) {
+ NandPort = (UINT8) (((MmioRead32 (PciD31F2RegBase + 0x300)) & 0x1FE) >> 1);
+ } else {
+ NandPort = 0x00;
+ }
+ if (PchSeries == PchH) {
+ ///
+ /// PCH BIOS Spec Rev 0.5.0, Section 8.14 Additional PCI Express* Programming Steps
+ /// Step 3
+ /// Function disable unused PCIE port
+ /// Disable PCIe Port 1 if either of the conditions are met
+ /// i. B0:D28:F0 + 410h[4] = 0b and B0:D28:F0 + 410h[0] = 0b
+ /// ii. GbeOverPCIe is configured to use Pcie Port 1 and SATA port 4 is mapped to this lane instead of PCIe Port 1
+ /// iii. NandOverPCIe is configured to use PCIe Port 1
+ /// NOTE:
+ /// For condition ii, if Gbe is configured to Pcie Port 1, and Pcie Port 1 ownes the shared lane instead of SATA port 4,
+ /// then it supports Gbe + 8 PCIES configuration, and BIOS won't hide the Root Port 1.
+ ///
+ RpLaneOwner = MmioRead8 (PciD28F0RegBase + 0x410);
+ if ((((RpLaneOwner & (BIT4)) == 0x0) && ((RpLaneOwner & BIT0) == 0x0)) ||
+ ((GbePort == 0x0) && ((RpLaneOwner & (BIT4)) == 0)) ||
+ (NandPort == BIT0)) {
+ RpHiddenMask |= BIT0;
+ }
+ }
+ if (PchSeries == PchLp) {
+ ///
+ /// Function disabled unused PCIE port
+ /// Disable PCIe Port 1 if either of the conditions are met
+ /// i. B0:D28:F0 + 410h [1:0] = 00b or 10b
+ /// ii. NandOverPCIe is configured to use PCIe Port 1
+ ///
+ if (((MmioRead32 (PciD28F0RegBase + 0x410) & (BIT1 | BIT0)) == 0) ||
+ ((MmioRead32 (PciD28F0RegBase + 0x410) & (BIT1 | BIT0)) == BIT1) ||
+ (NandPort == BIT0)) {
+ RpHiddenMask |= BIT0;
+ }
+ }
+ if (PchSeries == PchH) {
+ ///
+ /// Disable PCIe Port 2 if either of the conditions are met
+ /// i. B0:D28:F0 + 410h [5] = 0b and B0:D28:F0 + 410h [2] = 0b
+ /// ii. GbeOverPCIe is configured to use Pcie Port 2 and SATA port 5 is mapped to this lane instead of PCIe Port 2
+ /// iii. NandOverPCIe is configured to use PCIe Port 2
+ /// NOTE:
+ /// For condition ii, if Gbe is configured to Pcie Port 2, and Pcie Port 2 ownes the shared lane instead of SATA port 5,
+ /// then it supports Gbe + 8 PCIES configuration, and BIOS won't hide the Root Port 2.
+ ///
+ if ((((RpLaneOwner & (BIT5)) == 0x0) && ((RpLaneOwner & BIT2) == 0x0)) ||
+ ((GbePort == 0x1) && ((RpLaneOwner & (BIT5)) == 0)) ||
+ (NandPort == BIT1)) {
+ RpHiddenMask |= BIT1;
+ }
+ }
+ if (PchSeries == PchLp) {
+ ///
+ /// Disable PCIe Port 2 if either of the conditions are met
+ /// i. B0:D28:F0 + 410h [3:2] = 00b or 10b
+ /// ii. NandOverPCIe is configured to use PCIe Port 2
+ ///
+ if (((MmioRead32 (PciD28F0RegBase + 0x410) & (BIT3 | BIT2)) == 0) ||
+ ((MmioRead32 (PciD28F0RegBase + 0x410) & (BIT3 | BIT2)) == BIT3) ||
+ (NandPort == BIT1)) {
+ RpHiddenMask |= BIT1;
+ }
+ }
+ ///
+ /// Disable PCIe Port 3 if GbeOverPCIe is configured to use Port 3
+ ///
+ if ((PchSeries == PchH) && (GbePort == 0x2)) {
+ RpHiddenMask |= BIT2;
+ }
+ if ((PchSeries == PchLp) && (GbePort == 0x0)) {
+ RpHiddenMask |= BIT2;
+ }
+ ///
+ /// Disable PCIe Port 4 if GbeOverPCIe is configured to use Port 4
+ ///
+ if ((PchSeries == PchH) && (GbePort == 0x3)) {
+ RpHiddenMask |= BIT3;
+ }
+ if ((PchSeries == PchLp) && (GbePort == 0x1)) {
+ RpHiddenMask |= BIT3;
+ }
+ ///
+ /// Disable PCIe Port 5 if GbeOverPCIe is configured to use Port 5
+ /// or NandOverPCIe is configure to use Port 5
+ ///
+ if ((PchSeries == PchH) && (GbePort == 0x4 || NandPort == BIT4)) {
+ RpHiddenMask |= BIT4;
+ }
+ ///
+ /// Disable PCIe Port 5 if GbeOverPCIe is configured to use Port 5
+ /// NandOverPCIe is configure to use Port 5
+ ///
+ if ((PchSeries == PchLp) && (GbePort == 0x2 || GbePort == 0x3 || GbePort == 0x4 || GbePort == 0x5 || NandPort == BIT4)) {
+ RpHiddenMask |= BIT4;
+ }
+ ///
+ /// Disable PCIe Port 6 if GbeOverPCIe is configured to use Port 6
+ /// or NandOverPCIe is configure to use Port 6
+ ///
+ if ((PchSeries == PchH) && (GbePort == 0x5 || NandPort == BIT5)) {
+ RpHiddenMask |= BIT5;
+ }
+ ///
+ /// Disable PCIe Port 6 if SATA P1-P4 is configured
+ /// to use Port 6 Lane 0 - Lane 3
+ /// or NandOverPCIe is configure to use Port 6
+ ///
+ if ((PchSeries == PchLp) && ((MmioRead32 (PciD28F0RegBase + 0x410) & (BIT7 | BIT6 | BIT5 | BIT4)) == 0x0) || NandPort == BIT5) {
+ RpHiddenMask |= BIT5;
+ }
+ if (PchSeries == PchH) {
+ ///
+ /// Disable PCIe Port 7 if GbeOverPCIe is configured to use Port 7
+ ///
+ if (GbePort == 0x6) {
+ RpHiddenMask |= BIT6;
+ }
+ ///
+ /// Disable PCIe Port 8 if GbeOverPCIe is configured to use Port 8
+ ///
+ if (GbePort == 0x7) {
+ RpHiddenMask |= BIT7;
+ }
+ }
+ if (((MmioRead32 ((UINTN) (RootComplexBar + 0x1030))) & ((UINT32) (BIT22))) &&
+ (PciExpressConfig->EnableSubDecode)) {
+ ///
+ /// Assert if Subtractive Decode Port is disabled by configuration
+ ///
+ ASSERT_EFI_ERROR ((RpHiddenMask & (B_PCH_RCRB_FUNC_DIS_PCI_EX_PORT1 <<
+ (PciExpressConfig->PchPcieSbdePort))) == 0x1);
+ SubDecodePort = PciExpressConfig->PchPcieSbdePort;
+ } else {
+ SubDecodePort = 0xFF;
+ }
+ ///
+ /// The port of function number 0 might be disabled.
+ /// Will swap the function number 0 to enabled port on the end of this function.
+ /// Gather the enabled root ports here.
+ ///
+ for (PortIndex = 0; PortIndex < GetPchMaxPciePortNum (); PortIndex++) {
+ if ((PciExpressConfig->RootPort[PortIndex].Enable) &&
+ (((*FuncDisableReg) & (B_PCH_RCRB_FUNC_DIS_PCI_EX_PORT1 << PortIndex)) == 0)) {
+ RpEnableMask |= 1 << PortIndex;
+ }
+ }
+ ///
+ /// Disable the port which is going to be hidden.
+ ///
+ if (RpEnableMask != 0) {
+ RpEnableMask &= ~(RpHiddenMask);
+ }
+ //
+ // If RootPortFunctionSwapping is disabled, force to enable the root port of function 0
+ //
+ if (!((PchPlatformPolicy->Revision >= DXE_PCH_PLATFORM_POLICY_PROTOCOL_REVISION_3) &&
+ (PciExpressConfig->RootPortFunctionSwapping == 1))) {
+ RpEnableMask |= 1 << Func0PortNum;
+ }
+ for (PortIndex = 0; PortIndex < GetPchMaxPciePortNum (); PortIndex++) {
+ FuncNum = GetPchPcieRpfn (RootComplexBar, PortIndex);
+ RPBase = MmPciAddress (
+ 0,
+ PchPlatformPolicy->BusNumber,
+ PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS,
+ FuncNum,
+ 0
+ );
+
+ ///
+ /// PCH BIOS Spec Rev 0.5.0 Section 8.2
+ /// Else if the port is hot-plug enable, do not disable the port. If BIOS wants to disable the port,
+ /// BIOS should not enable the hot plug capability or must disable the hot plug capability of the port.
+ /// Set B0:D28:Fn + 338h [26] = 0b at early POST. Done in PchInitPeim.c PchMiscInit().
+ ///
+ /// Enabled Slot implemented for the enabled PCIE Root Ports. This is due to new PCIe disabling methodtology
+ /// to check if any is populated on the slots.
+ ///
+ if ((RpHiddenMask & (1 << PortIndex)) == 0) {
+ MmioOr16 (RPBase + R_PCH_PCIE_XCAP, B_PCH_PCIE_XCAP_SI);
+ }
+
+ if ((RpHiddenMask & (1 << PortIndex)) != 0) {
+ *FuncDisableReg |= B_PCH_RCRB_FUNC_DIS_PCI_EX_PORT1 << PortIndex;
+ } else if (((RpEnableMask & (1 << PortIndex)) != 0) &&
+ ((MmioRead16 (RPBase + R_PCH_PCIE_SLSTS) & BIT6) == 0) &&
+ (PciExpressConfig->RootPort[PortIndex].HotPlug == 0) &&
+ (PortIndex != SubDecodePort)) {
+ ///
+ /// PCH BIOS Spec Rev 0.5.0 Section 8.2
+ /// Else if the port is not hot plug enable and no PCIe card is detected,
+ /// Set B0:D28:Fn + 338h [26] = 1b
+ /// Poll B0:D28:Fn + 328h [31:24] until 01h or else 50ms timeout
+ /// Set B0:D28:Fn + 408h [27] = 1b
+ /// Function disable the port at RCBA+ 3418
+ ///
+ Data32And = 0xFFFFFFFF;
+ Data32Or = (UINT32) BIT26;
+ MmioOr32 ((RPBase + 0x338), Data32Or);
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (RPBase + 0x338),
+ &Data32Or, // Data to be ORed
+ &Data32And // Data to be ANDed
+ );
+
+ BitMask = (UINT32) (BIT31 | BIT30 | BIT29 | BIT28 | BIT27 | BIT26 | BIT25 | BIT24);
+ BitValue = 1 << 24;
+ for (LoopTime = 0; LoopTime < 500; LoopTime++) {
+ if ((MmioRead32 (RPBase + 0x328) & BitMask) == BitValue) {
+ break;
+ } else {
+ PchPmTimerStall (100);
+ }
+ }
+ SCRIPT_MEM_POLL (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ RPBase + 0x328,
+ &BitMask,
+ &BitValue,
+ 50,
+ 1000
+ );
+
+ Data32And = 0xFFFFFFFF;
+ Data32Or = (UINT32) BIT27;
+ MmioOr32 ((RPBase + 0x408), Data32Or);
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (RPBase + 0x408),
+ &Data32Or, // Data to be ORed
+ &Data32And // Data to be ANDed
+ );
+ *FuncDisableReg |= B_PCH_RCRB_FUNC_DIS_PCI_EX_PORT1 << PortIndex;
+ } else if ((RpEnableMask & (1 << PortIndex)) == 0) {
+ ///
+ /// Else if the port is not hot plug enable, and BIOS wants to disable the port
+ /// If a PCIe card is detected, set B0:D28:Fn + 50h[4] = 1b
+ /// followed by function disable the port at RCBA + 3418h
+ ///
+ if ((MmioRead16 (RPBase + R_PCH_PCIE_SLSTS) & BIT6) != 0) {
+ MmioOr16 ((RPBase + R_PCH_PCIE_LCTL), (UINT16) BIT4);
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint16,
+ (UINTN) (RPBase + R_PCH_PCIE_LCTL),
+ 1,
+ (VOID *) (UINTN) (RPBase + R_PCH_PCIE_LCTL)
+ );
+ }
+ *FuncDisableReg |= B_PCH_RCRB_FUNC_DIS_PCI_EX_PORT1 << PortIndex;
+ } else {
+ ///
+ /// Configure the rootports
+ ///
+ Status = PchInitSingleRootPort (
+ (UINT8) PortIndex,
+ FuncNum,
+ PchPlatformPolicy,
+ PmBase,
+ RootComplexBar
+ );
+ if (!EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, " Root Port %x device enabled. RpEnableMask: 0x%x\n", PortIndex + 1, RpEnableMask));
+ }
+
+ if ((PciExpressConfig->RootPort[PortIndex].TransmitterHalfSwing) &&
+ (((MmioRead32 (RPBase + 0x328) & (0x00780000)) >> 19) == 0x7)) {
+ MmioOr8 (RPBase + R_PCH_PCIE_LCTL, B_PCH_PCIE_LCTL_LD);
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint8,
+ (UINTN) (RPBase + R_PCH_PCIE_LCTL),
+ 1,
+ (VOID *) (UINTN) (RPBase + R_PCH_PCIE_LCTL)
+ );
+ MmioOr16 (RPBase + R_PCH_PCIE_PECR1, BIT13);
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint16,
+ (UINTN) (RPBase + R_PCH_PCIE_PECR1),
+ 1,
+ (VOID *) (UINTN) (RPBase + R_PCH_PCIE_PECR1)
+ );
+ MmioAnd8 (RPBase + R_PCH_PCIE_LCTL, (UINT8) ~(B_PCH_PCIE_LCTL_LD));
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint8,
+ (UINTN) (RPBase + R_PCH_PCIE_LCTL),
+ 1,
+ (VOID *) (UINTN) (RPBase + R_PCH_PCIE_LCTL)
+ );
+ }
+ }
+
+ if (MmioRead32 (RPBase) == 0xFFFFFFFF) {
+ continue;
+ }
+
+ if ((PchSeries == PchH) && (PortIndex == 0 || PortIndex == 4)) {
+ ///
+ /// PCH BIOS Spec Rev 0.5.0, Section 8.14 Additional PCI Express* Programming Steps
+ /// Step 19
+ /// Set B0:F28:F0&F4 + F7h[3:2] = 00b
+ ///
+ MmioAnd8 (RPBase + 0xF7, (UINT8) ~(BIT3 | BIT2));
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint8,
+ (UINTN) (RPBase + 0xF7),
+ 1,
+ (VOID *) (UINTN) (RPBase + 0xF7)
+ );
+ }
+ if ((PchSeries == PchLp) && (PortIndex == 0 || PortIndex == 4 || PortIndex == 5)) {
+ ///
+ /// Set B0:F28:F0,F4&F5 + F7h[3:2] = 00b
+ ///
+ MmioAnd8 (RPBase + 0xF7, (UINT8) ~(BIT3 | BIT2));
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint8,
+ (UINTN) (RPBase + 0xF7),
+ 1,
+ (VOID *) (UINTN) (RPBase + 0xF7)
+ );
+ }
+
+ if ((RpHiddenMask & (1 << PortIndex)) == 0) {
+ ///
+ /// Disable the forwarding of EOI messages.
+ /// Set B0:D28:F0/F1/F2/F3/F4/F5/F6/F7 + D4h [1] = 1b
+ ///
+ #ifdef HOTPLUG_EOI_FLAG // AMI_OVERRIDE, [EIP84720]>
+ MmioOr8 (RPBase + 0xD4, (UINT8) (BIT1));
+ #else
+ //Supporting _RMV method in asl code, and reading hotplug capability register of root port
+ //if hotplug disable, then set EOI Forwarding Disable bit
+ #ifdef TBT_UP_PORT_FUNC_FLAG
+ if((TBT_UP_PORT_FUNC == PortIndex) || (!(MmioRead8 (RPBase + 0x54) & 0x40)))
+ #else
+ if(!(MmioRead8 (RPBase + 0x54) & 0x40))
+ #endif
+ MmioOr8 (RPBase + 0xD4, (UINT8) (BIT1));
+ #endif // AMI_OVERRIDE, [EIP84720]<
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint8,
+ (UINTN) (RPBase + 0xD4),
+ 1,
+ (VOID *) (UINTN) (RPBase + 0xD4)
+ );
+ }
+ }
+ //
+ // If RootPortFunctionSwapping is disabled, force to enable the root port of function 0
+ //
+ if (!((PchPlatformPolicy->Revision >= DXE_PCH_PLATFORM_POLICY_PROTOCOL_REVISION_3) &&
+ (PciExpressConfig->RootPortFunctionSwapping == 1))) {
+ Mask = (0xFF >>(8-GetPchMaxPciePortNum ()));
+ if (((*FuncDisableReg >> N_PCH_RCRB_FUNC_DIS_PCI_EX_PORT1) & Mask) != Mask) {
+ *FuncDisableReg &= ~(B_PCH_RCRB_FUNC_DIS_PCI_EX_PORT1 << Func0PortNum);
+ }
+ }
+
+ ///
+ /// Configure root port clock gating
+ ///
+ RpEnableMask = (UINT8)~(*FuncDisableReg >> 16);
+ if (PciExpressConfig->RootPortClockGating) {
+ PcieEnableClockGating (
+ PchPlatformPolicy->BusNumber,
+ PchPlatformPolicy,
+ RpEnableMask,
+ RpHiddenMask,
+ RootComplexBar,
+ NandPort
+ );
+ }
+
+ ///
+ /// Enable PCIE Relaxed Order. It always allows downstream completions to pass posted write.
+ /// Set B0:D28:Fx offset 320h [24,23] to 1, 1b.
+ /// Set RCBA 2314h[31,7] to 1, 1b.
+ /// Set RCBA 1114h[15,14] to 1, 1b.
+ ///
+ for (FuncNum = 0; FuncNum < GetPchMaxPciePortNum (); FuncNum++) {
+ RPBase = MmPciAddress (
+ 0,
+ PchPlatformPolicy->BusNumber,
+ PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS,
+ FuncNum,
+ 0
+ );
+ if (MmioRead16 (RPBase + R_PCH_PCIE_VENDOR_ID) == 0xFFFF) {
+ continue;
+ }
+ MmioOr32 (RPBase + R_PCH_PCIE_PECR2, (BIT24 | BIT23));
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (RPBase + R_PCH_PCIE_PECR2),
+ 1,
+ (VOID *) (UINTN) (RPBase + R_PCH_PCIE_PECR2)
+ );
+ }
+ MmioOr32 (RootComplexBar + R_PCH_RCRB_CIR2314, (BIT31 | BIT7));
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (RootComplexBar + R_PCH_RCRB_CIR2314),
+ 1,
+ (VOID *) (UINTN) (RootComplexBar + R_PCH_RCRB_CIR2314)
+ );
+ MmioOr16 (RootComplexBar + 0x1114, (BIT15 | BIT14));
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint16,
+ (UINTN) (RootComplexBar + 0x1114),
+ 1,
+ (VOID *) (UINTN) (RootComplexBar + 0x1114)
+ );
+
+ ///
+ /// PCH BIOS Spec Rev 0.5.0, Section 8.14 Additional PCI Express* Programming Steps
+ /// Step 4
+ /// Reconfigured the Function number using RPFN register at RCBA + 404h if function 0 (F0) is disabled
+ /// (If Port of function 0 is disable, swap the function number with other enabled port)
+ ///
+ if ((PchPlatformPolicy->Revision >= DXE_PCH_PLATFORM_POLICY_PROTOCOL_REVISION_3) &&
+ (PciExpressConfig->RootPortFunctionSwapping == 1)) {
+ Func0PortNum = 0xFF;
+ for (PortIndex = 0; PortIndex < GetPchMaxPciePortNum (); PortIndex++) {
+ FuncNum = (UINT8)((RpFnOr >> (PortIndex * S_PCH_RCRB_PRFN_RP_FIELD)) & B_PCH_RCRB_RPFN_RP1FN);
+ if (FuncNum == 0) {
+ Func0PortNum = PortIndex;
+ break;
+ }
+ }
+ if ((Func0PortNum < GetPchMaxPciePortNum ()) && ((RpEnableMask & (BIT0 << Func0PortNum)) == 0)) {
+ for (PortIndex = 0; PortIndex < GetPchMaxPciePortNum (); PortIndex++) {
+ if ((RpEnableMask & (BIT0 << PortIndex)) != 0) {
+ FuncNum = (UINT8)((RpFnOr >> (PortIndex * S_PCH_RCRB_PRFN_RP_FIELD)) & B_PCH_RCRB_RPFN_RP1FN);
+ RpFnOr &= ((UINT32)~(B_PCH_RCRB_RPFN_RP1FN << (Func0PortNum * S_PCH_RCRB_PRFN_RP_FIELD))) &
+ ((UINT32)~(B_PCH_RCRB_RPFN_RP1FN << (PortIndex * S_PCH_RCRB_PRFN_RP_FIELD)));
+ RpFnOr |= ((UINT32)(((UINT32)FuncNum) << (Func0PortNum * S_PCH_RCRB_PRFN_RP_FIELD)));
+ break;
+ }
+ }
+ }
+ }
+
+ MmioAndThenOr32 (RootComplexBar + R_PCH_RCRB_RPFN, RpFnAnd, RpFnOr);
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (RootComplexBar + R_PCH_RCRB_RPFN),
+ &RpFnOr, // Data to be ORed
+ &RpFnAnd // Data to be ANDed
+ );
+
+ DEBUG ((EFI_D_INFO, "PchInitRootPorts() End\n"));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Perform Root Port Initialization.
+
+ @param[in] RootPort The root port to be initialized (zero based)
+ @param[in] RootPortFunction The PCI function number of the root port
+ @param[in] PchPlatformPolicy The PCH Platform Policy protocol
+ @param[in] PmBase The PM I/O Base address of the PCH
+ @param[in] RootComplexBar RCBA of the PCH
+
+ @retval EFI_SUCCESS Device found. The root port must be enabled.
+ @retval EFI_NOT_FOUND No device is found on the root port. It may be disabled.
+ @exception EFI_UNSUPPORTED Unsupported operation.
+**/
+EFI_STATUS
+PchInitSingleRootPort (
+ IN UINT8 RootPort,
+ IN UINT8 RootPortFunction,
+ IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy,
+ IN UINT16 PmBase,
+ IN UINT32 RootComplexBar
+ )
+{
+ EFI_STATUS Status;
+ UINTN RPBase;
+ UINTN LpcBase;
+ UINTN PciD28F0RegBase;
+ UINTN PciD28F4RegBase;
+ UINTN PciD28F5RegBase;
+ UINT32 CapOffset;
+ UINT8 BusNumber;
+ UINT32 Data32;
+ UINT16 Data16;
+ UINT32 Data32Or;
+ UINT32 Data32And;
+ UINT16 Data16Or;
+ UINT16 Data16And;
+ UINT32 PcieNccSSc;
+ UINT8 DeviceLaneOwner;
+ UINT32 PchPcieHsioAddrPerPort[4];
+ UINT8 NumOfLanePerPort;
+ UINT8 LaneIndex;
+ PCH_PCI_EXPRESS_ROOT_PORT_CONFIG *RootPortConfig;
+ BOOLEAN DeviceFound;
+ PCH_SERIES PchSeries;
+ UINT32 DeviceClassDword;
+
+ PchSeries = GetPchSeries();
+ DeviceFound = FALSE;
+ RootPortConfig = &PchPlatformPolicy->PciExpressConfig->RootPort[RootPort];
+ BusNumber = PchPlatformPolicy->BusNumber;
+ RPBase = MmPciAddress (0, BusNumber, PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, RootPortFunction, 0);
+ LpcBase = MmPciAddress (0, BusNumber, PCI_DEVICE_NUMBER_PCH_LPC, PCI_FUNCTION_NUMBER_PCH_LPC, 0);
+ PciD28F0RegBase = MmPciAddress (0, BusNumber, PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, GetPchPcieRpfn( RootComplexBar, PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_1), 0);
+ PciD28F4RegBase = MmPciAddress (0, BusNumber, PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, GetPchPcieRpfn( RootComplexBar, PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_5), 0);
+ PciD28F5RegBase = 0;
+ DeviceClassDword = 0;
+ if (PchSeries == PchLp) {
+ PciD28F5RegBase = MmPciAddress (0, BusNumber, PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, GetPchPcieRpfn( RootComplexBar, PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_6), 0);
+ }
+ CapOffset = PcieFindCapId (
+ BusNumber,
+ PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS,
+ RootPortFunction,
+ 0x10
+ );
+
+ if (CapOffset == 0) {
+ return EFI_UNSUPPORTED;
+ }
+
+ PcieNccSSc = 0;
+ NumOfLanePerPort = 0;
+ switch (RootPort) {
+ case PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_1:
+ PcieNccSSc = MmioRead32 (PciD28F0RegBase + 0x32C) & BIT28;
+ break;
+
+ case PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_2:
+ PcieNccSSc = MmioRead32 (PciD28F0RegBase + 0x32C) & BIT29;
+ break;
+
+ case PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_3:
+ PcieNccSSc = MmioRead32 (PciD28F0RegBase + 0x32C) & BIT30;
+ break;
+
+ case PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_4:
+ PcieNccSSc = MmioRead32 (PciD28F0RegBase + 0x32C) & BIT31;
+ break;
+
+ case PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_5:
+ PcieNccSSc = MmioRead32 (PciD28F4RegBase + 0x32C) & BIT28;
+ break;
+
+ case PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_6:
+ if (PchSeries == PchH) {
+ PcieNccSSc = MmioRead32 (PciD28F4RegBase + 0x32C) & BIT29;
+ } else if (PchSeries == PchLp) {
+ PcieNccSSc = MmioRead32 (PciD28F5RegBase + 0x32C) & BIT29;
+ }
+ break;
+
+ case PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_7:
+ if (PchSeries == PchH) {
+ PcieNccSSc = MmioRead32 (PciD28F4RegBase + 0x32C) & BIT30;
+ }
+ break;
+
+ case PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_8:
+ if (PchSeries == PchH) {
+ PcieNccSSc = MmioRead32 (PciD28F4RegBase + 0x32C) & BIT31;
+ }
+ break;
+
+ default:
+ PcieNccSSc = 0;
+ }
+
+ ///
+ /// PCH BIOS Spec Rev 0.5.0, Section 8.14 Additional PCI Express* Programming Steps
+ /// Step 5
+ /// If corresponding Root Port 4 to 1 in B0:D28:F0 + 32Ch [31:28], Root Port 8 to 5
+ /// in B0:D28:F4 + 32Ch [31:28], is set, for EACH PORT (x):
+ ///
+ if (PcieNccSSc) {
+ ///
+ /// Step 5.1, 5.2
+ /// Set B0:D28:Fx + D4h[4] = 1b
+ /// Set B0:D28:Fx + D4h[3:2] = 10b
+ ///
+ MmioAndThenOr8 ((RPBase + 0xD4), (UINT8)~BIT2, BIT4 | BIT3);
+ ///
+ /// Step 5.3
+ /// Set B0:D28:Fx + D8h[20:18] = 111b
+ ///
+ MmioOr32 ((RPBase + 0xD8), BIT20 | BIT19 | BIT18);
+ ///
+ /// Step 5.4
+ /// Set B0:D28:Fx + 4Ch[17:15] = 100b, see also step 9.
+ ///
+ MmioAndThenOr32 ((RPBase + 0x4C), (UINT32)~(BIT16 | BIT15), BIT17);
+#ifdef ULT_FLAG
+ if (PchSeries == PchLp) {
+ ///
+ /// Step 5.5
+ /// Read the IOBP register below, increase the values by 2 and write back.
+ /// E9002440 [20:16], [12:8]
+ /// E9002640 [20:16], [12:8]
+ /// E9000840 [20:16], [12:8]
+ /// E9000A40 [20:16], [12:8]
+ /// E9000C40 [20:16], [12:8]
+ /// E9000E40 [20:16], [12:8]
+ /// E9001040 [20:16], [12:8]
+ /// E9001240 [20:16], [12:8]
+ /// EA002040 [20:16], [12:8]
+ /// EA002240 [20:16], [12:8]
+ /// EA002440 [20:16], [12:8]
+ /// EA002640 [20:16], [12:8]
+ ///
+ DeviceLaneOwner = MmioRead8 (PciD28F0RegBase + 0x410);
+ if (RootPort == PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_5) {
+ NumOfLanePerPort = 4;
+ PchPcieHsioAddrPerPort[0] = PchLpPcieHsioAddr[4];
+ PchPcieHsioAddrPerPort[1] = PchLpPcieHsioAddr[5];
+ PchPcieHsioAddrPerPort[2] = PchLpPcieHsioAddr[6];
+ PchPcieHsioAddrPerPort[3] = PchLpPcieHsioAddr[7];
+ } else if (RootPort == PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_6) {
+ NumOfLanePerPort = 0;
+ if ((DeviceLaneOwner & BIT4) == BIT4) {
+ PchPcieHsioAddrPerPort[NumOfLanePerPort++] = PchLpPcieHsioAddr[8];
+ }
+ if ((DeviceLaneOwner & BIT5) == BIT5) {
+ PchPcieHsioAddrPerPort[NumOfLanePerPort++] = PchLpPcieHsioAddr[9];
+ }
+ if ((DeviceLaneOwner & BIT6) == BIT6) {
+ PchPcieHsioAddrPerPort[NumOfLanePerPort++] = PchLpPcieHsioAddr[10];
+ }
+ if ((DeviceLaneOwner & BIT7) == BIT7) {
+ PchPcieHsioAddrPerPort[NumOfLanePerPort++] = PchLpPcieHsioAddr[11];
+ }
+ } else {
+ NumOfLanePerPort = 1;
+ PchPcieHsioAddrPerPort[0] = PchLpPcieHsioAddr[RootPort];
+ }
+ }
+#endif // ULT_FLAG
+#ifdef TRAD_FLAG
+ if (PchSeries == PchH) {
+ ///
+ /// Step 5.5
+ /// Read the IOBP register below, increase the values by 2 and write back.
+ /// Dedicated lane Setting
+ /// E9002040 [20:16], [12:8]
+ /// E9002240 [20:16], [12:8]
+ /// E9002440 [20:16], [12:8]
+ /// E9002640 [20:16], [12:8]
+ /// E9002840 [20:16], [12:8]
+ /// E9002A40 [20:16], [12:8]
+ /// Shared lane Setting
+ /// E9002C40 [20:16], [12:8]
+ /// E9002E40 [20:16], [12:8]
+ /// EA002040 [20:16], [12:8]
+ /// EA002240 [20:16], [12:8]
+ ///
+ DeviceLaneOwner = MmioRead8 (PciD28F0RegBase + 0x410);
+ NumOfLanePerPort = 1;
+ if (RootPort == PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_1) {
+ if ((DeviceLaneOwner & (BIT1 | BIT0)) == BIT0) {
+ PchPcieHsioAddrPerPort[0] = PchHPcieHsioAddr[0];
+ } else {
+ PchPcieHsioAddrPerPort[0] = PchHPcieHsioAddr[8];
+ }
+ } else if (RootPort == PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_2) {
+ if ((DeviceLaneOwner & (BIT3 | BIT2)) == BIT2) {
+ PchPcieHsioAddrPerPort[0] = PchHPcieHsioAddr[1];
+ } else {
+ PchPcieHsioAddrPerPort[0] = PchHPcieHsioAddr[9];
+ }
+ } else {
+ PchPcieHsioAddrPerPort[0] = PchHPcieHsioAddr[RootPort];
+ }
+ }
+#endif // TRAD_FLAG
+ for (LaneIndex = 0; LaneIndex < NumOfLanePerPort; LaneIndex++) {
+ Status = ReadIobp (
+ RootComplexBar,
+ PchPcieHsioAddrPerPort[LaneIndex],
+ &Data32
+ );
+ ASSERT_EFI_ERROR (Status);
+ Data32 += 0x00020200;
+ Status = ProgramIobp (
+ RootComplexBar,
+ PchPcieHsioAddrPerPort[LaneIndex],
+ 0x0,
+ Data32
+ );
+ ASSERT_EFI_ERROR (Status);
+ Status = SetProgramIobpS3Item (
+ RootComplexBar,
+ PchPcieHsioAddrPerPort[LaneIndex],
+ 0x0,
+ Data32
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+ ///
+ /// Step 5.6
+ /// Set B0:D28:Fx + 338h[26] = 0b
+ ///
+ MmioAnd32 ((RPBase + 0x338), (UINT32)~BIT26);
+ }
+
+ Data32 = MmioRead32 (RPBase + R_PCH_PCIE_DCAP2);
+ ///
+ /// PCH BIOS Spec Rev 0.5.5, Section 8.14.1 Power Optimizer Configuration
+ /// Step 1
+ /// Enable support Latency Tolerance Reporting (LTR)
+ /// Step 1.1
+ /// Program B0:D28:F0~F7 + 400h to 883C883Ch for ports which has a PCIe
+ /// device attached to it.
+ /// Done in PcieSetPm()
+ /// Step 1.2
+ /// Program B0:D28:F0~F7 + 404h [1:0] = 11b for ports which has a PCIe device
+ /// device attached to it.
+ /// Done in PcieSetPm()
+ /// Step 1.3
+ /// Program B0:D28:F0-F7 + 64h [11] = 1b
+ ///
+ if (PchPlatformPolicy->PwrOptConfig->PchPwrOptPcie[RootPort].LtrEnable == PCH_DEVICE_ENABLE) {
+ Data32 |= BIT11;
+ } else {
+ Data32 &= (UINT32) ~(BIT11);
+ }
+ ///
+ /// Step 2
+ /// Support Optimized Buffer Flush/Fill (OBFF)
+ /// Step 2.1
+ /// Program B0:D28:F0-F7 + 64h [19:18] = 2h
+ ///
+ if (PchPlatformPolicy->PwrOptConfig->PchPwrOptPcie[RootPort].ObffEnable == PCH_DEVICE_ENABLE) {
+ Data32 |= BIT19;
+ } else {
+ Data32 &= (UINT32) ~(BIT19 | BIT18);
+ }
+ MmioWrite32 (RPBase + R_PCH_PCIE_DCAP2, Data32);
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (RPBase + R_PCH_PCIE_DCAP2),
+ 1,
+ &Data32
+ );
+
+ Data16 = MmioRead16 (RPBase + R_PCH_PCIE_DCTL2);
+ ///
+ /// Step 1.4
+ /// Program B0:D28:F0-F7 + 68h [10] = 1b
+ ///
+ if (PchPlatformPolicy->PwrOptConfig->PchPwrOptPcie[RootPort].LtrEnable == PCH_DEVICE_ENABLE) {
+ Data16 |= BIT10;
+ } else {
+ Data16 &= (UINT16) ~(BIT10);
+ }
+ ///
+ /// Step 2.2
+ /// Program B0:D28:F0-F7 + 68h [14:13] = 3h
+ ///
+ if (PchPlatformPolicy->PwrOptConfig->PchPwrOptPcie[RootPort].ObffEnable == PCH_DEVICE_ENABLE) {
+ Data16 |= BIT14 | BIT13;
+ } else {
+ Data16 &= (UINT16) ~(BIT14 | BIT13);
+ }
+
+ MmioWrite16 (RPBase + R_PCH_PCIE_DCTL2, Data16);
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint16,
+ (UINTN) (RPBase + R_PCH_PCIE_DCTL2),
+ 1,
+ &Data16
+ );
+ ///
+ /// PCH BIOS Spec Rev 0.5.0, Section 8.14 Additional PCI Express* Programming Steps
+ /// Step 6
+ /// Set B0:D28:F0~F7 + 318h [31:16] = 1414h
+ ///
+ Data32Or = 0x14140000;
+ Data32And = (UINT32) (~(0xFFFF0000));
+ MmioAndThenOr32 (RPBase + 0x318, Data32And, Data32Or);
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (RPBase + 0x318),
+ &Data32Or, // Data to be ORed
+ &Data32And // Data to be ANDed
+ );
+
+ ///
+ /// Step 7
+ /// If B0:D28:F0 + F5h[0] = 1b or step 5 is TRUE, set B0:D28:F0~F7 + 4Ch[17:15] = 100b
+ /// Else set B0:D28:F0~F7 + 4Ch[17:15] = 010b
+ ///
+ if ((MmioRead8 (PciD28F0RegBase + 0xF5) & BIT0) || PcieNccSSc) {
+ Data32Or = BIT17;
+ } else {
+ Data32Or = BIT16;
+ }
+
+ Data32And = (UINT32) (~B_PCH_PCIE_LCAP_EL1);
+ MmioAndThenOr32 (RPBase + R_PCH_PCIE_LCAP, Data32And, Data32Or);
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (RPBase + R_PCH_PCIE_LCAP),
+ &Data32Or, // Data to be ORed
+ &Data32And // Data to be ANDed
+ );
+ ///
+ /// Step 8
+ /// Set B0:D28:F0~F7 + 314h[31:24] = 74h
+ /// Step 9
+ /// Set B0:D28:F0~F7 + 314h[23:16] = 3Ah
+ /// Step 10
+ /// Set B0:D28:F0~F7 + 314h[15:08] = 36h
+ /// Step 11
+ /// Set B0:D28:F0~F7 + 314h[07:00] = 1Bh
+ ///
+ Data32Or = 0x743A361B;
+ Data32And = (UINT32) (0x0);
+ MmioAndThenOr32 (RPBase + 0x314, Data32And, Data32Or);
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (RPBase + 0x314),
+ &Data32Or, // Data to be ORed
+ &Data32And // Data to be ANDed
+ );
+ ///
+ /// Step 12
+ /// Set B0:D28:F0~F7 + D8h[17:15] = 3h
+ ///
+ Data32And = (UINT32) (~B_PCH_PCIE_MPC_CCEL);
+ Data32Or = BIT16 | BIT15;
+ MmioAndThenOr32 (RPBase + R_PCH_PCIE_MPC, Data32And, Data32Or);
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (RPBase + R_PCH_PCIE_MPC),
+ &Data32Or, // Data to be ORed
+ &Data32And // Data to be ANDed
+ );
+ ///
+ /// Step 13
+ /// Set B0:D28:F0~F7 + 33Ch[24:0] = 854C74h
+ ///
+ Data32And = 0xFF000000;
+ Data32Or = 0x854C74;
+ MmioAndThenOr32 (RPBase + 0x33C, Data32And, Data32Or);
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (RPBase + 0x33C),
+ &Data32Or, // Data to be ORed
+ &Data32And // Data to be ANDed
+ );
+
+ ///
+ /// Step 16
+ /// Set B0:D28:F0~F7 + D8h[25] = 1b
+ ///
+ Data32And = (UINT32) ~(B_PCH_PCIE_MPC_IRRCE);
+ Data32Or = B_PCH_PCIE_MPC_IRRCE;
+ MmioAndThenOr32 (RPBase + R_PCH_PCIE_MPC, Data32And, Data32Or);
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (RPBase + R_PCH_PCIE_MPC),
+ &Data32Or, // Data to be ORed
+ &Data32And // Data to be ANDed
+ );
+ ///
+ /// Step 17
+ /// For system that support MCTP over PCIE set
+ /// Set B0:D28:F0~F7 + D8h[27] = 1b
+ /// Set B0:D28:F0~F7 + D8h[3] = 1b
+ ///
+ Data32And = (UINT32) ~(B_PCH_PCIE_MPC_MCTPSE | B_PCH_PCIE_MPC_MMBNCE);
+ Data32Or = B_PCH_PCIE_MPC_MCTPSE | B_PCH_PCIE_MPC_MMBNCE;
+ MmioAndThenOr32 (RPBase + R_PCH_PCIE_MPC, Data32And, Data32Or);
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (RPBase + R_PCH_PCIE_MPC),
+ &Data32Or, // Data to be ORed
+ &Data32And // Data to be ANDed
+ );
+ ///
+ /// Step 18
+ /// Set B0:D28:F0~F7 + F5h[7:4] = 0000b
+ ///
+ MmioAnd8 (RPBase + 0xF5, (UINT8) ~(BIT4 | BIT5 | BIT6 | BIT7));
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint8,
+ (UINTN) (RPBase + 0xF5),
+ 1,
+ (VOID *) (UINTN) (RPBase + 0xF5)
+ );
+ ///
+ /// Step 20
+ /// If there is no IOAPIC behind the root port, set EOI Forwarding Disable bit (B0:D28:F0-F7:D4h[1]) to 1b.
+ /// Done in PchPciExpressHelpersLibrary.c PcieSetEoiFwdDisable()
+ ///
+ /// Step 21
+ /// For systems that support Advanced Error Reporting set
+ /// B0:D28:F0~F7:100h[19:0] = 10001h
+ /// Else
+ /// B0:D28:F0~F7:100h[19:0] = 0h
+ ///
+ if (RootPortConfig->AdvancedErrorReporting) {
+ Data32 = (UINT32)(BIT16 | BIT0);
+ } else {
+ Data32 = 0;
+ }
+ ///
+ /// For LPT-LP, setup the next capability offset to 0x200
+ /// B0:D28:F0~F7:100h[29] = 1b
+ ///
+ if (PchSeries == PchLp) {
+ Data32 |= BIT29;
+ }
+ MmioWrite32 (RPBase + R_PCH_PCIE_AECH, Data32);
+
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (RPBase + R_PCH_PCIE_AECH),
+ 1,
+ (VOID *) (UINTN) (RPBase + R_PCH_PCIE_AECH)
+ );
+ ///
+ /// Step 22
+ /// System bios should initiate link retrain for all slots that has card populated after register restoration.
+ /// Done in PchPciExpressHelpersLibrary.c PchPcieInitRootPortDownstreamDevices ()
+ /// Step 23
+ /// System BIOS should read and write back to capability register B0:D28:F0 offsets 34h, 40h,
+ /// 80h and 90h after it has been configure or prior to boot
+ /// Done in PchInit.c PciERWORegInit ()
+ ///
+ /// Configure Extended Synch
+ ///
+ if (RootPortConfig->ExtSync) {
+ Data16And = (UINT16) (-1);
+ Data16Or = B_PCH_PCIE_LCTL_ES;
+ } else {
+ Data16And = (UINT16) (~B_PCH_PCIE_LCTL_ES);
+ Data16Or = 0;
+ }
+
+ MmioAndThenOr16 (RPBase + R_PCH_PCIE_LCTL, Data16And, Data16Or);
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint16,
+ (UINTN) (RPBase + R_PCH_PCIE_LCTL),
+ &Data16Or, // Data to be ORed
+ &Data16And // Data to be ANDed
+ );
+
+ if (PchSeries == PchLp) {
+ ///
+ /// Step 23
+ /// Program B0:D28:F0~F5:320h[21:20] to 01b and [8:6] to 011b
+ ///
+ Data32And = (UINT32) (~(BIT21 | BIT20 | BIT8 | BIT7 | BIT6));
+ Data32Or = BIT20 | BIT7 | BIT6;
+ MmioAndThenOr32 (RPBase + R_PCH_PCIE_PECR2, Data32And, Data32Or);
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (RPBase + R_PCH_PCIE_PECR2),
+ &Data32Or, // Data to be ORed
+ &Data32And // Data to be ANDed
+ );
+ }
+
+ ///
+ /// Configure Completion Timeout
+ ///
+ Data16And = (UINT16)~(B_PCH_PCIE_DCTL2_CTD | B_PCH_PCIE_DCTL2_CTV);
+ Data16Or = 0;
+ if (RootPortConfig->CompletionTimeout == PchPcieCompletionTO_Disabled) {
+ Data16Or = B_PCH_PCIE_DCTL2_CTD;
+ } else {
+ switch (RootPortConfig->CompletionTimeout) {
+ case PchPcieCompletionTO_Default:
+ Data16Or = V_PCH_PCIE_DCTL2_CTV_DEFAULT;
+ break;
+
+ case PchPcieCompletionTO_16_55ms:
+ Data16Or = V_PCH_PCIE_DCTL2_CTV_40MS_50MS;
+ break;
+
+ case PchPcieCompletionTO_65_210ms:
+ Data16Or = V_PCH_PCIE_DCTL2_CTV_160MS_170MS;
+ break;
+
+ case PchPcieCompletionTO_260_900ms:
+ Data16Or = V_PCH_PCIE_DCTL2_CTV_400MS_500MS;
+ break;
+
+ case PchPcieCompletionTO_1_3P5s:
+ Data16Or = V_PCH_PCIE_DCTL2_CTV_1P6S_1P7S;
+ break;
+
+ default:
+ Data16Or = 0;
+ break;
+ }
+ }
+
+ MmioAndThenOr16 (RPBase + R_PCH_PCIE_DCTL2, Data16And, Data16Or);
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint16,
+ (UINTN) (RPBase + R_PCH_PCIE_DCTL2),
+ &Data16Or, // Data to be ORed
+ &Data16And // Data to be ANDed
+ );
+
+ ///
+ /// Set the Slot Implmemented Bit. Note that this must be set before
+ /// presence is valid.
+ /// PCH BIOS Spec Rev 0.5.0 section 8.2.2, The System BIOS must
+ /// initialize the "Slot Implemented" bit of the PCI Express* Capabilities Register,
+ /// XCAP D28:F0~7:Reg 42h[8] of each available and enabled downstream root port.
+ /// Setting this bit will indicate that the PCI Express* link associated with this
+ /// port is connected to a slot (as compared to being connected to an integrated
+ /// device component).
+ ///
+ if (RootPortConfig->SlotImplemented) {
+ ///
+ /// Slot Implemented enabled earlier. Here will only save this register for enabled ports
+ ///
+ Data16Or = BIT8;
+ Data16And = 0xFFFF;
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint16,
+ (UINTN) (RPBase + CapOffset + 2),
+ &Data16Or, // Data to be ORed
+ &Data16And // Data to be ANDed
+ );
+ ///
+ /// For Root Port Slots Numbering on the CRBs.
+ ///
+ Data32Or = 0;
+ Data32And = (UINT32) (~(B_PCH_PCIE_SLCAP_SLV | B_PCH_PCIE_SLCAP_SLS | B_PCH_PCIE_SLCAP_PSN));
+ ///
+ /// PCH BIOS Spec Rev 0.5.0 section 8.8.2.1
+ /// Note: If Hot Plug is supported, then write a 1 to the Hot Plug Capable (bit6) and Hot Plug
+ /// Surprise (bit5) in the Slot Capabilities register, D28:F0~7:Reg 54h. Otherwise,
+ /// write 0 to the bits PCIe Hot Plug SCI Enable
+ ///
+ Data32And &= (UINT32) (~(B_PCH_PCIE_SLCAP_HPC | B_PCH_PCIE_SLCAP_HPS));
+ if (RootPortConfig->HotPlug) {
+ Data32Or |= B_PCH_PCIE_SLCAP_HPC | B_PCH_PCIE_SLCAP_HPS;
+ }
+ ///
+ /// Get the width from LCAP
+ /// Slot Type X1 X4/X8 X16
+ /// Default 10W 25W 75W
+ /// The slot power consumption and allocation is platform specific. Please refer to the
+ /// "PCI Express* Card Electromechanical (CEM) Spec" for details.
+ /// bugbug what's the default setting for X2
+ ///
+ if ((((MmioRead32 (RPBase + R_PCH_PCIE_LCAP)) & B_PCH_PCIE_LCAP_MLW) >> 4) == 0x01) {
+ Data32Or |= (UINT32) (100 << 7);
+ Data32Or |= (UINT32) (1 << 15);
+ } else if ((((MmioRead32 (RPBase + R_PCH_PCIE_LCAP)) & B_PCH_PCIE_LCAP_MLW) >> 4) >= 0x04) {
+ Data32Or |= (UINT32) (250 << 7);
+ Data32Or |= (UINT32) (1 << 15);
+ }
+
+ Data32Or |= (UINT32) (RootPortConfig->PhysicalSlotNumber << 19);
+ MmioAndThenOr32 (RPBase + R_PCH_PCIE_SLCAP, Data32And, Data32Or);
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (RPBase + R_PCH_PCIE_SLCAP),
+ &Data32Or, // Data to be ORed
+ &Data32And // Data to be ANDed
+ );
+ }
+ ///
+ /// Initialize downstream devices
+ ///
+ Status = PchPcieInitRootPortDownstreamDevices (
+ BusNumber,
+ (UINT8) PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS,
+ RootPortFunction,
+ PchPlatformPolicy->PciExpressConfig->TempRootPortBusNumMin,
+ PchPlatformPolicy->PciExpressConfig->TempRootPortBusNumMax,
+ &DeviceClassDword
+ );
+ if (Status == EFI_SUCCESS) {
+ DeviceFound = TRUE;
+ } else {
+ ///
+ /// Disable the forwarding of EOI messages.
+ /// Set B0:D28:F0/F1/F2/F3/F4/F5/F6/F7 + D4h [1] = 1b
+ ///
+ #ifdef HOTPLUG_EOI_FLAG // AMI_OVERRIDE, [EIP84720]>
+ MmioOr8 (RPBase + 0xD4, (UINT8) (BIT1));
+ #else
+ //Supporting _RMV method in asl code, and reading hotplug capability register of root port
+ //if hotplug disable, then set EOI Forwarding Disable bit
+ #ifdef TBT_UP_PORT_FUNC_FLAG
+ if((TBT_UP_PORT_FUNC == RootPortFunction) || (!(MmioRead8 (RPBase + 0x54) & 0x40)))
+ #else
+ if(!(MmioRead8 (RPBase + 0x54) & 0x40))
+ #endif
+ MmioOr8 (RPBase + 0xD4, (UINT8) (BIT1));
+ #endif // AMI_OVERRIDE, [EIP84720]<
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint8,
+ (UINTN) (RPBase + 0xD4),
+ 1,
+ (VOID *) (UINTN) (RPBase + 0xD4)
+ );
+ }
+ ///
+ /// Not checking the error status here - downstream device not present does not
+ /// mean an error of this root port. Our return status of EFI_SUCCESS means this
+ /// port is enabled and outer function depends on this return status to do
+ /// subsequent initializations.
+ ///
+ Status = SetInitRootPortDownstreamS3Item (
+ BusNumber,
+ (UINT8) PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS,
+ RootPortFunction,
+ PchPlatformPolicy->PciExpressConfig->TempRootPortBusNumMin,
+ PchPlatformPolicy->PciExpressConfig->TempRootPortBusNumMax
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Additional configurations
+ ///
+
+ ///
+ /// Enable Subtractive Decode of RootPort
+ /// Step 1
+ /// Ensure flash descriptor PCH Strap 9 Bit 14, which read RCBA + 1030h[22] = 1b
+ /// Step 2
+ /// Set B0:D28:Fn + ECh[1:0] = 11b,
+ /// If downstream is PCI-to-PCI bridge, then also set B0:D28:Fn + ECh[2] = 1b
+ ///
+ if ((RootPort == PchPlatformPolicy->PciExpressConfig->PchPcieSbdePort) &&
+ (MmioRead32 ((UINTN) (RootComplexBar + 0x1030)) & BIT22) &&
+ (PchPlatformPolicy->PciExpressConfig->EnableSubDecode))
+ {
+ Data32Or = (B_PCH_PCIE_PECR3_SDCDID | B_PCH_PCIE_PECR3_SDE);
+ if ((((DeviceClassDword >> 24) & 0xFF) == PCI_CLASS_BRIDGE) && // BCC
+ (((DeviceClassDword >> 16) & 0xFF) == PCI_CLASS_BRIDGE_CARDBUS)) // SCC
+ {
+ Data32Or |= BIT2;
+ }
+
+ MmioOr32 (RPBase + R_PCH_PCIE_PECR3, Data32Or);
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (RPBase + R_PCH_PCIE_PECR3),
+ 1,
+ (VOID *) (UINTN) (RPBase + R_PCH_PCIE_PECR3)
+ );
+ }
+
+ ///
+ /// Configure Error Reporting policy in the Device Control Register
+ ///
+ Data16And = (UINT16) (~(B_PCH_PCIE_DCTL_URE | B_PCH_PCIE_DCTL_FEE | B_PCH_PCIE_DCTL_NFE | B_PCH_PCIE_DCTL_CEE));
+ Data16Or = 0;
+
+ if (RootPortConfig->UnsupportedRequestReport) {
+ Data16Or |= B_PCH_PCIE_DCTL_URE;
+ }
+
+ if (RootPortConfig->FatalErrorReport) {
+ Data16Or |= B_PCH_PCIE_DCTL_FEE;
+ }
+
+ if (RootPortConfig->NoFatalErrorReport) {
+ Data16Or |= B_PCH_PCIE_DCTL_NFE;
+ }
+
+ if (RootPortConfig->CorrectableErrorReport) {
+ Data16Or |= B_PCH_PCIE_DCTL_CEE;
+ }
+
+ MmioAndThenOr16 (RPBase + R_PCH_PCIE_DCTL, Data16And, Data16Or);
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint16,
+ (UINTN) (RPBase + R_PCH_PCIE_DCTL),
+ &Data16Or, // Data to be ORed
+ &Data16And // Data to be ANDed
+ );
+
+ ///
+ /// Configure Interrupt / Error reporting in R_PCH_PCIE_RCTL
+ ///
+ Data16And = (UINT16) (~(B_PCH_PCIE_RCTL_PIE | B_PCH_PCIE_RCTL_SFE | B_PCH_PCIE_RCTL_SNE | B_PCH_PCIE_RCTL_SCE));
+ Data16Or = 0;
+
+ if (RootPortConfig->PmeInterrupt) {
+ Data16Or |= B_PCH_PCIE_RCTL_PIE;
+ }
+
+ if (RootPortConfig->SystemErrorOnFatalError) {
+ Data16Or |= B_PCH_PCIE_RCTL_SFE;
+ }
+
+ if (RootPortConfig->SystemErrorOnNonFatalError) {
+ Data16Or |= B_PCH_PCIE_RCTL_SNE;
+ }
+
+ if (RootPortConfig->SystemErrorOnCorrectableError) {
+ Data16Or |= B_PCH_PCIE_RCTL_SCE;
+ }
+
+ MmioAndThenOr16 (RPBase + R_PCH_PCIE_RCTL, Data16And, Data16Or);
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint16,
+ (UINTN) (RPBase + R_PCH_PCIE_RCTL),
+ &Data16Or, // Data to be ORed
+ &Data16And // Data to be ANDed
+ );
+
+ ///
+ /// Root PCI-E Powermanagement SCI Enable
+ ///
+ if (RootPortConfig->PmSci) {
+ ///
+ /// PCH BIOS Spec Rev 0.5.0 section 8.7.3 BIOS Enabling of Intel PCH PCI Express* PME SCI Generation
+ /// Step 1
+ /// Make sure that PME Interrupt Enable bit, D28:F0-7:Reg 5Ch[3] is cleared
+ ///
+ Data16And = (UINT16) (~B_PCH_PCIE_RCTL_PIE);
+ Data16Or = 0;
+ MmioAnd16 (RPBase + R_PCH_PCIE_RCTL, Data16And);
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint16,
+ (UINTN) (RPBase + R_PCH_PCIE_RCTL),
+ &Data16Or, // Data to be ORed
+ &Data16And // Data to be ANDed
+ );
+
+ ///
+ /// Step 2
+ /// Program Misc Port Config (MPC) register at PCI config space offset
+ /// D8h as follows:
+ /// Set Power Management SCI Enable bit, D28:F0~7:Reg D8h[31]
+ /// Clear Power Management SMI Enable bit, D28:F0~7:Reg D8h[0]
+ ///
+ Data32And = (UINT32) (~B_PCH_PCIE_MPC_PMME);
+ Data32Or = B_PCH_PCIE_MPC_PMCE;
+ MmioAndThenOr32 (RPBase + R_PCH_PCIE_MPC, Data32And, Data32Or);
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (RPBase + R_PCH_PCIE_MPC),
+ &Data32Or, // Data to be ORed
+ &Data32And // Data to be ANDed
+ );
+
+ ///
+ /// Step 3
+ /// Make sure GPE0 Register (PMBase+20h[9]), PCI_EXP_STS is 0, clear it if not zero
+ ///
+ if (PchSeries == PchLp) {
+ Data32Or = IoRead32 (PmBase + R_PCH_ACPI_GPE0_STS_127_96);
+ if ((Data32Or & B_PCH_ACPI_GPE0_STS_127_96_PCI_EXP) != 0) {
+ Data32Or = B_PCH_ACPI_GPE0_STS_127_96_PCI_EXP;
+ IoWrite32 (PmBase + R_PCH_ACPI_GPE0_STS_127_96, Data32Or);
+ SCRIPT_IO_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (PmBase + R_PCH_ACPI_GPE0_STS_127_96),
+ 1,
+ &Data32Or
+ );
+ }
+ } else if (PchSeries == PchH) {
+ Data32Or = IoRead32 (PmBase + R_PCH_ACPI_GPE0a_STS);
+ if ((Data32Or & B_PCH_ACPI_GPE0a_STS_PCI_EXP) != 0) {
+ Data32Or = B_PCH_ACPI_GPE0a_STS_PCI_EXP;
+ IoWrite32 (PmBase + R_PCH_ACPI_GPE0a_STS, Data32Or);
+ SCRIPT_IO_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (PmBase + R_PCH_ACPI_GPE0a_STS),
+ 1,
+ &Data32Or
+ );
+ }
+ }
+ ///
+ /// Step 4
+ /// Set BIOS_PCI_EXP_EN bit, D31:F0:Reg A0[10],
+ /// to globally enable the setting of the PCI_EXP_STS bit by a PCI Express* PME event.
+ ///
+ Data16Or = MmioRead16 (LpcBase + R_PCH_LPC_GEN_PMCON_1);
+ if ((Data16Or & B_PCH_LPC_GEN_PMCON_BIOS_PCI_EXP_EN) == 0) {
+ Data16And = 0xFFFF;
+ Data16Or = B_PCH_LPC_GEN_PMCON_BIOS_PCI_EXP_EN;
+ MmioOr16 (LpcBase + R_PCH_LPC_GEN_PMCON_1, Data16Or);
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint16,
+ (UINTN) (LpcBase + R_PCH_LPC_GEN_PMCON_1),
+ &Data16Or, // Data to be ORed
+ &Data16And // Data to be ANDed
+ );
+ }
+ }
+
+ if (RootPortConfig->HotPlug) {
+ ///
+ /// PCH BIOS Spec Rev 0.5.0 section 8.8.2.1
+ /// Step 1
+ /// Clear following status bits, by writing 1b to them, in the Slot
+ /// Status register at offset 1Ah of PCI Express Capability structure:
+ /// Attention Button Pressed (bit0)
+ /// Presence Detect Changed (bit3)
+ ///
+ Data16And = 0xFFFF;
+ Data16Or = (BIT3 | BIT0);
+ MmioOr16 (RPBase + CapOffset + 0x1A, Data16Or);
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint16,
+ (UINTN) (RPBase + CapOffset + 0x1A),
+ &Data16Or, // Data to be ORed
+ &Data16And // Data to be ANDed
+ );
+ ///
+ /// Step 2
+ /// Program the following bits in Slot Control register at offset 18h
+ /// of PCI Express* Capability structure:
+ /// Attention Button Pressed Enable (bit0) = 1b
+ /// Presence Detect Changed Enable (bit3) = 1b
+ /// Hot Plug Interrupt Enable (bit5) = 0b
+ ///
+ Data16And = (UINT16) (~BIT5);
+ Data16Or = (BIT3 | BIT0);
+ MmioAndThenOr16 (RPBase + CapOffset + 0x18, Data16And, Data16Or);
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint16,
+ (UINTN) (RPBase + CapOffset + 0x18),
+ &Data16Or, // Data to be ORed
+ &Data16And // Data to be ANDed
+ );
+ ///
+ /// Step 3
+ /// Program Misc Port Config (MPC) register at PCI config space offset
+ /// D8h as follows:
+ /// Hot Plug SCI Enable (HPCE, bit30) = 1b
+ /// Hot Plug SMI Enable (HPME, bit1) = 0b
+ ///
+ Data32And = (UINT32) (~B_PCH_PCIE_MPC_HPME);
+ Data32Or = B_PCH_PCIE_MPC_HPCE;
+ MmioAndThenOr32 (RPBase + R_PCH_PCIE_MPC, Data32And, Data32Or);
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (RPBase + R_PCH_PCIE_MPC),
+ &Data32Or, // Data to be ORed
+ &Data32And // Data to be ANDed
+ );
+ ///
+ /// Step 4
+ /// Clear GPE0 Register (PMBase+20h), bit1, HOT_PLUG_STS by writing 1
+ ///
+ if (PchSeries == PchLp) {
+ IoWrite32 (PmBase + R_PCH_ACPI_GPE0_STS_127_96, (UINT32) B_PCH_ACPI_GPE0_STS_127_96_HOT_PLUG);
+ } else if (PchSeries == PchH) {
+ IoWrite32 (PmBase + R_PCH_ACPI_GPE0a_STS, (UINT32) B_PCH_ACPI_GPE0a_STS_HOT_PLUG);
+ }
+
+ ///
+ /// PCH BIOS Spec Rev 0.5.0 section 8.9
+ /// BIOS should mask the reporting of Completion timeout (CT) errors byerrors by setting
+ /// the uncorrectable Error Mask register D28:F0~7:Reg 108h[14].
+ ///
+ Data32And = 0xFFFFFFFF;
+ Data32Or = B_PCH_PCIE_UEM_CT;
+ MmioOr32 (RPBase + R_PCH_PCIE_UEM, Data32Or);
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (RPBase + R_PCH_PCIE_UEM),
+ &Data32Or, // Data to be ORed
+ &Data32And // Data to be ANDed
+ );
+ }
+
+ if (DeviceFound == TRUE || (RootPortConfig->HotPlug == PCH_DEVICE_ENABLE)) {
+ return EFI_SUCCESS;
+ } else {
+ return EFI_NOT_FOUND;
+ }
+}
+
+/**
+ This is the function to enable the clock gating for PCI Express ports.
+
+ @param[in] BusNumber The Bus Number of the PCH device
+ @param[in] PchPlatformPolicy PCH Platform Policy protocol
+ @param[in] RpEnableMask Bit Mask indicating the enabled root ports
+ @param[in] RpHiddenMask Bit Mask indicating the root ports used for other > x1 root ports
+ @param[in] RootComplexBar Root complex base address
+
+ @retval EFI_SUCCESS Successfully completed.
+**/
+EFI_STATUS
+PcieEnableClockGating (
+ IN UINT8 BusNumber,
+ IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy,
+ IN UINT32 RpEnableMask,
+ IN UINT32 RpHiddenMask,
+ IN UINT32 RootComplexBar,
+ IN UINT32 NandPort
+ )
+{
+ UINTN RPBase;
+ UINT32 PortIndex;
+ UINT8 Data8Or;
+ UINT8 Data8And;
+ UINT32 Data32Or;
+ UINT32 Data32And;
+ UINT16 GpioBase;
+ BOOLEAN ClkreqPerPortSupported;
+ PCH_SERIES PchSeries;
+
+ PchSeries = GetPchSeries();
+ GpioBase = 0;
+
+ ///
+ /// PCH BIOS Spec Rev 0.5.0, section 19.10 Enabling Clock Gating
+ /// 2.1
+ /// For each enabled PCI Express* root port, program D28:F0~F7:Reg E1h[1:0] to 3h to enable dynamic clock gating.
+ /// System BIOS also require to set D28:F0~F7:Reg E8h[0] = 1b
+ /// 2.2
+ /// Additionally, if port 0 is in x2 mode, these bits should not be set for port 1.
+ /// Likewise, if port 0 is in x4 mode, these bits should not be set for ports 1, 2, or 3
+ ///
+ for (PortIndex = 0; PortIndex < GetPchMaxPciePortNum (); PortIndex++) {
+ ClkreqPerPortSupported = FALSE;
+ if (PchSeries == PchLp) {
+ GpioBase = MmioRead16 (
+ MmPciAddress (0,
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC,
+ R_PCH_LPC_GPIO_BASE)
+ ) & B_PCH_LPC_GPIO_BASE_BAR;
+ Data32Or = (IoRead32 ((UINTN) (GpioBase + R_PCH_GP_X_CONFIG0(18 + PortIndex))) & B_PCH_GPIO_OWN0_GPIO_USE_SEL);
+ if (Data32Or == 0) {
+ ClkreqPerPortSupported = TRUE;
+ }
+ }
+ if (((RpEnableMask & (1 << PortIndex)) != 0) && ((RpHiddenMask & (1 << PortIndex)) == 0)) {
+ RPBase = MmPciAddress (
+ 0,
+ BusNumber,
+ PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS,
+ GetPchPcieRpfn (RootComplexBar, (UINT8) PortIndex),
+ 0
+ );
+
+ Data8Or = B_PCH_PCIE_RPDCGEN_RPDLCGEN | B_PCH_PCIE_RPDCGEN_RPDBCGEN;
+ Data8And = 0xFF;
+ MmioOr8 (
+ RPBase + R_PCH_PCIE_RPDCGEN,
+ Data8Or
+ );
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint8,
+ (UINTN) (RPBase + R_PCH_PCIE_RPDCGEN),
+ &Data8Or, // Data to be ORed
+ &Data8And // Data to be ANDed
+ );
+
+ if (PchSeries == PchLp) {
+ ///
+ /// 2.3
+ /// Program D28:F0~F5:E2h[6] to 1b
+ ///
+ Data8Or = B_PCH_PCIE_RPPGEN_PTOTOP;
+ Data8And = (UINT8)~B_PCH_PCIE_RPPGEN_PTOTOP;
+ MmioOr8 (
+ RPBase + R_PCH_PCIE_RPPGEN,
+ Data8Or
+ );
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint8,
+ (UINTN) (RPBase + R_PCH_PCIE_RPPGEN),
+ &Data8Or, // Data to be ORed
+ &Data8And // Data to be ANDed
+ );
+
+ ///
+ /// 2.4
+ /// Program D28:F0~F5:E8h[3:2] to 10b before setting D28:F0~F5:E8h[1:0]
+ ///
+ Data8Or = BIT3;
+ Data8And = (UINT8)~(V_PCH_PCIE_PECR1_FIELD_3);
+ MmioAndThenOr8 (
+ RPBase + R_PCH_PCIE_PECR1,
+ Data8And,
+ Data8Or
+ );
+ }
+
+ Data32And = 0xFFFFFFFF;
+ Data32Or = (UINT32) BIT0;
+ MmioOr32 (RPBase + R_PCH_PCIE_PECR1, Data32Or);
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (RPBase + R_PCH_PCIE_PECR1),
+ &Data32Or, // Data to be ORed
+ &Data32And // Data to be ANDed
+ );
+ ///
+ /// Step 2.6
+ /// Set B0:D28:F0~F7 + 324h[5] = 1b
+ ///
+ MmioOr32 (RPBase + R_PCH_PCIE_PEETM, (UINT32) (BIT5));
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (RPBase + R_PCH_PCIE_PEETM),
+ 1,
+ (VOID *) (UINTN) (RPBase + R_PCH_PCIE_PEETM)
+ );
+//for Denlow SVR, refer Inel doc 493798, c state communication
+#ifdef PCH_DENLOW_SERVER_SUPPORT
+ /// Set B0:D28:F0~F7 + 324h[3] = 1b
+ ///
+ MmioOr32 (RPBase + R_PCH_PCIE_PEETM, (UINT32) (BIT3));
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (RPBase + R_PCH_PCIE_PEETM),
+ 1,
+ (VOID *) (UINTN) (RPBase + R_PCH_PCIE_PEETM)
+ );
+#endif
+ }
+
+ if (PchSeries == PchLp) {
+ ///
+ /// Program D28:F0~F5:E2h[5:4] to 11b prior to function disable the port
+ /// Program D28:F0~F5:420h[31] to 1b prior to function disable the port
+ ///
+ if ((RpEnableMask & (1 << PortIndex)) == 0) {
+ RPBase = MmPciAddress (
+ 0,
+ BusNumber,
+ PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS,
+ GetPchPcieRpfn (RootComplexBar, (UINT8) PortIndex),
+ 0
+ );
+ Data8Or = (B_PCH_PCIE_RPPGEN_LMSDOCGE | B_PCH_PCIE_RPPGEN_SEOCGE);
+ Data8And = (UINT8)~(B_PCH_PCIE_RPPGEN_LMSDOCGE | B_PCH_PCIE_RPPGEN_SEOCGE);
+ MmioOr8 (
+ RPBase + R_PCH_PCIE_RPPGEN,
+ Data8Or
+ );
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint8,
+ (UINTN) (RPBase + R_PCH_PCIE_RPPGEN),
+ &Data8Or, // Data to be ORed
+ &Data8And // Data to be ANDed
+ );
+ Data32Or = (B_PCH_PCIE_PCIEPMECTL_FDPGE);
+ Data32And = (UINT32)~(B_PCH_PCIE_PCIEPMECTL_FDPGE);
+ MmioOr32 (
+ RPBase + R_PCH_PCIE_PCIEPMECTL,
+ Data32Or
+ );
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (RPBase + R_PCH_PCIE_PCIEPMECTL),
+ &Data32Or, // Data to be ORed
+ &Data32And // Data to be ANDed
+ );
+ }
+ ///
+ /// Program D28:F0~F5:420h[30:29] to 111b
+ ///
+ if (ClkreqPerPortSupported) {
+ RPBase = MmPciAddress (
+ 0,
+ BusNumber,
+ PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS,
+ GetPchPcieRpfn (RootComplexBar, (UINT8) PortIndex),
+ 0
+ );
+ Data32Or = (B_PCH_PCIE_PCIEPMECTL_DLSULPGE | B_PCH_PCIE_PCIEPMECTL_DLSULDLSD);
+ Data32And = (UINT32)~(B_PCH_PCIE_PCIEPMECTL_DLSULPGE | B_PCH_PCIE_PCIEPMECTL_DLSULDLSD);
+ MmioOr32 (
+ RPBase + R_PCH_PCIE_PCIEPMECTL,
+ Data32Or
+ );
+ SCRIPT_MEM_READ_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (RPBase + R_PCH_PCIE_PCIEPMECTL),
+ &Data32Or, // Data to be ORed
+ &Data32And // Data to be ANDed
+ );
+ }
+ }
+ }
+
+ if (PchSeries == PchLp) {
+ ///
+ /// PCH BIOS Spec Rev 0.5.0, section 19.10
+ /// Step 2.4
+ /// Program D28:F0,F4&F5:Reg E1h[5:2] to 1111b
+ /// Program D28:F0,F4&F5:Reg E1h[7] to 1b
+ ///
+ for (PortIndex = 0; PortIndex < GetPchMaxPciePortNum (); PortIndex ++) {
+ if ((PortIndex == 0 || PortIndex == 4 || PortIndex == 5) && !(NandPort & (0x1 << PortIndex))) {
+ RPBase = MmPciAddress (
+ 0,
+ BusNumber,
+ PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS,
+ GetPchPcieRpfn (RootComplexBar, (UINT8) PortIndex),
+ 0
+ );
+ Data8Or =
+ (
+ B_PCH_PCIE_RPDCGEN_LCLKREQEN |
+ B_PCH_PCIE_RPDCGEN_BBCLKREQEN |
+ B_PCH_PCIE_RPDCGEN_SRDLCGEN |
+ B_PCH_PCIE_RPDCGEN_SRDBCGEN
+ );
+
+ MmioOr8 (RPBase + R_PCH_PCIE_RPDCGEN, Data8Or);
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint8,
+ (UINTN) (RPBase + R_PCH_PCIE_RPDCGEN),
+ 1,
+ (VOID *) (UINTN) (RPBase + R_PCH_PCIE_RPDCGEN)
+ );
+
+ ///
+ /// PCH BIOS Spec Rev 0.5.0, section 19.10
+ /// Step 2.5
+ /// If PCIe root ports 0-3 are all disabled, set B0:D28:F0 + E2h [0] = 1b and E1h [7] = 1b.
+ /// If PCIe root port 4 is disabled, set B0:D28:F4 + E2h [0] = 1b and E1h [7] = 1b.
+ /// If PCIe root port 5 is disabled, set B0:D28:F5 + E2h [0] = 1b and E1h [7] = 1b.
+ ///
+ if (((!(RpEnableMask & 0xF)) && (PortIndex == 0)) || ((!(RpEnableMask & (0x1 << PortIndex))) && (PortIndex >= 4))) {
+ MmioOr8 ((RPBase + 0xE2), BIT0);
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint8,
+ (UINTN) (RPBase + 0xE2),
+ 1,
+ (VOID *) (UINTN) (RPBase + 0xE2)
+ );
+
+ MmioOr8 (RPBase + R_PCH_PCIE_RPDCGEN, B_PCH_PCIE_RPDCGEN_RPSCGEN);
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint8,
+ (UINTN) (RPBase + R_PCH_PCIE_RPDCGEN),
+ 1,
+ (VOID *) (UINTN) (RPBase + R_PCH_PCIE_RPDCGEN)
+ );
+ }
+ }
+ }
+ ///
+ /// Additional steps
+ /// If all PCIe root ports are disabled, set B0:D28:F0 + E1h[6] to 1b
+ ///
+ if ((RpEnableMask & 0x3F) == 0) {
+ RPBase = MmPciAddress (
+ 0,
+ BusNumber,
+ PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS,
+ GetPchPcieRpfn(RootComplexBar, PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_1),
+ 0
+ );
+ MmioOr8 (
+ RPBase + R_PCH_PCIE_RPDCGEN,
+ B_PCH_PCIE_RPDCGEN_POCGE
+ );
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint8,
+ (UINTN) (RPBase + R_PCH_PCIE_RPDCGEN),
+ 1,
+ (VOID *) (UINTN) (RPBase + R_PCH_PCIE_RPDCGEN)
+ );
+ }
+ }
+ if (PchSeries == PchH) {
+ ///
+ /// PCH BIOS Spec Rev 0.5.5, section 19.10
+ /// Step 2.3
+ /// Program D28:F0&F4:Reg E1h[5:2] to 1111b
+ ///
+ for (PortIndex = 0; PortIndex < GetPchMaxPciePortNum (); PortIndex += 4) {
+ if (((RpHiddenMask & (1 << PortIndex)) == 0) && !(NandPort & (0x1 << PortIndex))) {
+ RPBase = MmPciAddress (
+ 0,
+ BusNumber,
+ PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS,
+ GetPchPcieRpfn (RootComplexBar, (UINT8) PortIndex),
+ 0
+ );
+ Data8Or =
+ (
+ B_PCH_PCIE_RPDCGEN_LCLKREQEN |
+ B_PCH_PCIE_RPDCGEN_BBCLKREQEN |
+ B_PCH_PCIE_RPDCGEN_SRDLCGEN |
+ B_PCH_PCIE_RPDCGEN_SRDBCGEN
+ );
+ MmioOr8 (RPBase + R_PCH_PCIE_RPDCGEN, Data8Or);
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint8,
+ (UINTN) (RPBase + R_PCH_PCIE_RPDCGEN),
+ 1,
+ (VOID *) (UINTN) (RPBase + R_PCH_PCIE_RPDCGEN)
+ );
+ ///
+ /// PCH BIOS Spec Rev 0.5.5, section 19.10
+ /// Step 2.4
+ /// If PCIe root ports 0-3 are all disabled, set B0:D28:F0 + E2h [0] = 1b and E1h [7] = 1b.
+ /// If PCIe root ports 4-7 are all disabled, set B0:D28:F4 + E2h [0] = 1b and E1h [7] = 1b.
+ ///
+ if (!(RpEnableMask & (0xF << PortIndex))) {
+ MmioOr8 ((RPBase + 0xE2), BIT0);
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint8,
+ (UINTN) (RPBase + 0xE2),
+ 1,
+ (VOID *) (UINTN) (RPBase + 0xE2)
+ );
+
+ MmioOr8 (RPBase + R_PCH_PCIE_RPDCGEN, B_PCH_PCIE_RPDCGEN_RPSCGEN);
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint8,
+ (UINTN) (RPBase + R_PCH_PCIE_RPDCGEN),
+ 1,
+ (VOID *) (UINTN) (RPBase + R_PCH_PCIE_RPDCGEN)
+ );
+ }
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}