diff options
Diffstat (limited to 'ReferenceCode/Chipset/LynxPoint/PchInit/Pei')
11 files changed, 4040 insertions, 0 deletions
diff --git a/ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchDmiPeim.c b/ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchDmiPeim.c new file mode 100644 index 0000000..a53bf8b --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchDmiPeim.c @@ -0,0 +1,831 @@ +/** @file + This file contains functions for PCH DMI TC/VC programing and status polling + +@copyright + Copyright (c) 2009 - 2013 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 + +**/ +// AMI_OVERRIDE >>> +#ifdef AMI_RC_DEBUG +#include "PeiLib.h" +#endif +// AMI_OVERRIDE <<< +#include "PchInitPeim.h" +#include "HeciRegs.h" +#include "MeAccess.h" +#include "ChipsetInitHob.h" + +// +// GUID Definitions +// +EFI_GUID gChipsetInitHobGuid = CHIPSET_INIT_INFO_HOB_GUID; + +/** + Programing transaction classes of the corresponding virtual channel and Enable it + + @param[in] RootComplexBar PCH Root Complex Base Address + @param[in] Vc The virtual channel number for programing + @param[in] VcId The Identifier to be used for this virtual channel + @param[in] VcMap The transaction classes are mapped to this virtual channel. + When a bit is set, this transaction class is mapped to the virtual channel + + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_SUCCESS The function completed successfully +**/ +EFI_STATUS +PchSetDmiTcVcMapping ( + IN UINT32 RootComplexBar, + IN UINT8 Vc, + IN UINT8 VcId, + IN UINT8 VcMap + ) +{ + UINTN Address; + UINT32 VxCtlAnd; + UINT32 VxCtlOr; + + Address = RootComplexBar; + + VxCtlAnd = (UINT32) (~(B_PCH_RCRB_V1CTL_ID | V_PCH_RCRB_V1CTL_TVM_MASK)); + VxCtlOr = (VcId << N_PCH_RCRB_V1CTL_ID) & B_PCH_RCRB_V1CTL_ID; + VxCtlOr |= VcMap; + VxCtlOr |= B_PCH_RCRB_V1CTL_EN; + + switch (Vc) { + case DmiVcTypeVc0: + Address += R_PCH_RCRB_V0CTL; + break; + + case DmiVcTypeVc1: + Address += R_PCH_RCRB_V1CTL; + break; + + case DmiVcTypeVcp: + Address += R_PCH_RCRB_CIR2030; + break; + + case DmiVcTypeVcm: + Address += R_PCH_RCRB_CIR2040; + break; + + default: + return EFI_INVALID_PARAMETER; + } + + MmioAndThenOr32 (Address, VxCtlAnd, VxCtlOr); + if ((Vc == DmiVcTypeVc1) || (Vc == DmiVcTypeVcp)) { + // + // Reads back for posted write to take effect + // + MmioRead32 (Address); + } + + return EFI_SUCCESS; +} + +/** + Polling negotiation status of the corresponding virtual channel + + @param[in] RootComplexBar PCH Root Complex Base Address + @param[in] Vc The virtual channel number for programing + + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_SUCCESS The function completed successfully +**/ +EFI_STATUS +PchPollDmiVcStatus ( + IN UINT32 RootComplexBar, + IN UINT8 Vc + ) +{ + UINTN Address; + + Address = RootComplexBar; + + switch (Vc) { + case DmiVcTypeVc0: + Address += R_PCH_RCRB_V0STS; + break; + + case DmiVcTypeVc1: + Address += R_PCH_RCRB_V1STS; + break; + + case DmiVcTypeVcp: + Address += 0x2036; + break; + + case DmiVcTypeVcm: + Address += 0x2046; + break; + + default: + return EFI_INVALID_PARAMETER; + } + // + // Wait for negotiation to complete + // + while ((MmioRead16 (Address) & B_PCH_RCRB_V1STS_NP) != 0); + + return EFI_SUCCESS; +} + +/** + The function performing TC/VC mapping program, and poll all PCH Virtual Channel + until negotiation completion + + @param[in] PeiServices General purpose services available to every PEIM. + + @retval EFI_SUCCESS The function completed successfully + @retval Others All other error conditions encountered result in an ASSERT. +**/ +EFI_STATUS +EFIAPI +PchDmiTcVcProgPoll ( + IN EFI_PEI_SERVICES **PeiServices + ) +{ + EFI_STATUS Status; + PCH_DMI_TC_VC_PPI *PchDmiTcVcMapPpi; + UINT32 RootComplexBar; + UINT8 Index; + UINT8 VcMap[DmiVcTypeMax] = { 0 }; + + /// + /// Locate PchDmiTcVcMap Ppi + /// + Status = (*PeiServices)->LocatePpi (PeiServices, &gPchDmiTcVcMapPpiGuid, 0, NULL, (VOID **)&PchDmiTcVcMapPpi); + ASSERT_EFI_ERROR (Status); + RootComplexBar = PCH_RCRB_BASE; + + /// + /// PCH BIOS Spec Rev 0.5.0, Section 7.1.5 + /// Step 3.1 + /// RCBA + Offset 50h[19] = 1b + /// Step 3.2 + /// RCBA + Offset 50h[23:20] = 2h and RCBA + Offset 50h[17] = 1b, + /// ensure that D29/D26:F0:88h [2] = 0b (Done at PchMiscInit() on PchInitPeim.c) + /// + MmioAndThenOr32 (RootComplexBar + R_PCH_RCRB_CIR0050, (UINT32) (~0x00F00000), (UINT32) (0x00200000)); + + if (PchDmiTcVcMapPpi->DmiVc[DmiVcTypeVcp].Enable == PCH_DEVICE_ENABLE) { + MmioOr32 (RootComplexBar + R_PCH_RCRB_CIR0050, BIT17 | BIT19); + } + /// + /// Reads back for posted write to take effect + /// + MmioRead32 (RootComplexBar + R_PCH_RCRB_CIR0050); + + /// + /// Step 3.3, Step 3.4, Step 3.5, Step 3,6, Set the TC/VC mappings + /// + for (Index = 0; Index < DmiTcTypeMax; Index++) { + DEBUG ((EFI_D_INFO, "TC:%0x VC:%0x!\n", Index, PchDmiTcVcMapPpi->DmiTc[Index].Vc)); + VcMap[PchDmiTcVcMapPpi->DmiTc[Index].Vc] |= (BIT0 << Index); + } + + for (Index = 0; Index < DmiVcTypeMax; Index++) { + DEBUG ((EFI_D_INFO, "VC:%0x VCID:%0x Enable:%0x!\n",Index, PchDmiTcVcMapPpi->DmiVc[Index].VcId, PchDmiTcVcMapPpi->DmiVc[Index].Enable)); + if (PchDmiTcVcMapPpi->DmiVc[Index].Enable == PCH_DEVICE_ENABLE) { + PchSetDmiTcVcMapping ( + RootComplexBar, + Index, + PchDmiTcVcMapPpi->DmiVc[Index].VcId, + VcMap[Index] + ); + } + } + /// + /// Step 3.7 + /// Set RCBA + Offset 50h[31] = 1b + /// Lock down the TC mapping if no further changes are required to bits [30:16] + /// + MmioOr32 (RootComplexBar + R_PCH_RCRB_CIR0050, B_PCH_RCRB_CIR0_TCLOCKDN); + /// + /// Reads back for posted write to take effect + /// + MmioRead32 (RootComplexBar + R_PCH_RCRB_CIR0050); + + /// + /// Step 3.8 + /// After both above and System Agent DMI TC/VC mapping are programmed, + /// poll VC negotiation pending status until is zero: + /// 3.8.1 RCBA + Offset 201Ah[1] + /// 3.8.2 RCBA + Offset 2026h[1] + /// 3.8.3 RCBA + Offset 2036h[1] + /// 3.8.4 RCBA + Offset 2046h[1] + /// + for (Index = 0; Index < DmiVcTypeMax; Index++) { + if (PchDmiTcVcMapPpi->DmiVc[Index].Enable == PCH_DEVICE_ENABLE) { + PchPollDmiVcStatus (RootComplexBar, Index); + } + } + + return EFI_SUCCESS; +} + +/** + The function set the Target Link Speed in PCH to DMI GEN 2. + + @param[in] PeiServices General purpose services available to every PEIM. + + @retval None +**/ +VOID +EFIAPI +PchDmiGen2Prog ( + IN EFI_PEI_SERVICES **PeiServices + ) +{ +#ifdef TRAD_FLAG + UINT32 RootComplexBar; + + if (GetPchSeries() == PchH) { + DEBUG ((EFI_D_INFO, "PchDmiGen2Prog() Start\n")); + RootComplexBar = PCH_RCRB_BASE; + + /// + /// PCH BIOS Spec Rev 0.5.0, Section 7.1.5 + /// Step 2 + /// Configure DMI Link Speed as early as possible + /// Step 2.1 + /// Please refer to the System Agent BIOS Writer's Guide on Supported Link Speed + /// field in Link Capabilities register in CPU complex. (Done in SA code) + /// Step 2.2 + /// If the Supported Link Speed in CPU complex is 0010b (Done in SA code) + /// and RCBA + Offset 21A4h[3:0] = 0010b + /// + if ((MmioRead32 (RootComplexBar + R_PCH_RCRB_LCAP) & B_PCH_RCRB_LCAP_MLS) == 0x02) { + /// + /// Step 2.2.1 + /// Set RCBA + Offset 21B0h[3:0] = 0010b + /// + MmioAndThenOr8 (RootComplexBar + 0x21B0, (UINT8)~(BIT3 | BIT2 | BIT1 | BIT0), (UINT8) BIT1); + /// + /// Step 2.2.2 + /// Please refer to the System Agent BIOS Writer's Guide to perform DMI Link Retrain after + /// configures new DMI Link Speed. (Done in SA code) + /// + } + DEBUG ((EFI_D_INFO, "PchDmiGen2Prog() End\n")); + } +#endif // TRAD_FLAG +} + +/** + The function program DMI miscellaneous registers. + + @param[in] PchPlatformPolicyPpi The PCH Platform Policy PPI instance + + @retval EFI_SUCCESS The DMI required settings programmed correctly +**/ +EFI_STATUS +EFIAPI +PchDmiMiscProg ( + IN EFI_PEI_SERVICES **PeiServices, + IN PCH_PLATFORM_POLICY_PPI *PchPlatformPolicyPpi + ) +{ + UINT32 RootComplexBar; + EFI_STATUS Status; + UINT16 LpcDeviceId; + UINTN PciD31F0RegBase; + UINTN PciD28F0RegBase; + UINTN PciD20F0RegBase; + UINT32 Data32And; + UINT32 Data32Or; + UINT16 i; + UINT16 size; + UINT8 DeviceLaneOwner; + UINT32 StrpFuseCfg1; + UINT8 GbePort; +#ifdef ULT_FLAG + UINTN RPBase; + UINT8 PortIndex; +#endif // ULT_FLAG + PCH_SERIES PchSeries; + UINT8 PchSteppingValue; + UINT32 Msg; + UINT32 MsgTimeout; + UINT32 PchChipsetInitTableId; + UINT32 PchChipsetInitTableLength; + UINT8 *PchChipsetInitTable; + HECI_FWS_REGISTER MeHfs; + CHIPSET_INIT_INFO_HOB *ChipsetInitHob; + EFI_BOOT_MODE BootMode; +#ifdef TRAD_FLAG + IOBP_MMIO_TABLE_STRUCT *PchDmiHsio; +#endif // TRAD_FLAG + IOBP_MMIO_TABLE_STRUCT *PchUsb3Hsio; + IOBP_MMIO_TABLE_STRUCT *PchUsb3SharedHsio; + IOBP_MMIO_TABLE_STRUCT *PchGbeSharedHsio; + + PchSeries = GetPchSeries(); + Status = EFI_SUCCESS; + RootComplexBar = PchPlatformPolicyPpi->Rcba; + PchChipsetInitTable = NULL; + PchChipsetInitTableLength = 0; + Msg = 0; + MsgTimeout = MAX_ME_MSG_ACK_TIMEOUT; + PciD31F0RegBase = MmPciAddress ( + 0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + 0 + ); + PciD28F0RegBase = MmPciAddress ( + 0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, + PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_1, + 0 + ); + PciD20F0RegBase = MmPciAddress ( + 0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_XHCI, + PCI_FUNCTION_NUMBER_PCH_XHCI, + 0 + ); + LpcDeviceId = MmioRead16 (PciD31F0RegBase + R_PCH_LPC_DEVICE_ID); + PchSteppingValue = PchStepping(); + // + // Get PchSeries and assign the appropriate ChipsetInit table + // + switch (PchSteppingValue) { +#ifdef ULT_FLAG + case LptLpB0: + case LptLpB1: + case LptLpB2: + PchChipsetInitTable = PchChipsetInitTableLptLp_Bx; + PchChipsetInitTableLength = sizeof(PchChipsetInitTableLptLp_Bx); + break; +#endif // ULT_FLAG +#ifdef TRAD_FLAG + case LptHB0: + PchChipsetInitTable = PchChipsetInitTableLptH_B0; + PchChipsetInitTableLength = sizeof(PchChipsetInitTableLptH_B0); + break; + case LptHC0: + case LptHC1: + case LptHC2: + PchChipsetInitTable = PchChipsetInitTableLptH_Cx; + PchChipsetInitTableLength = sizeof(PchChipsetInitTableLptH_Cx); + break; +#endif // TRAD_FLAG + default: + DEBUG ((EFI_D_ERROR, "Unsupported PCH Stepping\n")); + } + + // + // GetBoodMode, do not perform ChipsetInit check on S3 RESUME + // + Status = PeiServicesGetBootMode(&BootMode); + if(BootMode != BOOT_ON_S3_RESUME) { + // + // Create Hob to send ChipsetInit table status to DXE phase. + // + DEBUG((EFI_D_INFO, "(Hsio) Creating HOB to adjust Hsio settings from DXE, if required.\n")); + Status = (**PeiServices).CreateHob ( + PeiServices, + EFI_HOB_TYPE_GUID_EXTENSION, + sizeof (CHIPSET_INIT_INFO_HOB), + &ChipsetInitHob + ); + ASSERT_EFI_ERROR (Status); + + // + // Initialize ChipsetInitHob + // + ChipsetInitHob->Header.Name = gChipsetInitHobGuid; + ChipsetInitHob->ChipsetInitTableLen = PchChipsetInitTableLength; + ChipsetInitHob->ChipsetInitTableUpdReq = 0; + + // + // Set the Host To ME flag requestint the Hsio ChipsetInit Table Version applied by ME FW + // + HeciPciAndThenOr32(R_ME_H_GS, 0, (H2M_HSIO_MESSAGE | H2M_HSIO_CMD_GETHSIOVER)); + + // + // Wait for the acknowledge from the FW, once it completes data should be in the FWSTS register + // Wait max of 100ms for FW to acknowledge. + // + do { + // + // Delay 1us. Need to give some time for ME to respond. + // + PchPmTimerStall(1); + MeHfs.ul = HeciPciRead32(R_ME_HFS); + MsgTimeout--; + if (MsgTimeout == 0) { + DEBUG ((EFI_D_INFO, "(Hsio) ME FW failed to acknowledge the GETHsioVER command.\n")); + Status = EFI_TIMEOUT; + // + // Do not assert until a supporting ME FW is available + // + // ASSERT_EFI_ERROR(Status); + break; + } + } while (MeHfs.r.BiosMessageAck != M2H_HSIO_MSG_ACK); + if (MsgTimeout > 0) { + DEBUG ((EFI_D_INFO, "(Hsio) The GETHsioVER command was acknowledged by ME FW.\n")); + } + + // + // If successfully got the ACK from ME, then the Hsio Version info should be in the FWSTATUS register + // Otherwise, just continue Hsio programming assuming the ChipsetInit settings programmed through other means. + // + if (Status == EFI_SUCCESS) { + // + // Receive the Hsio Version reported by ME FW. + // + Msg = HeciPciRead32(R_ME_HFS_5); + DEBUG((EFI_D_INFO, "(Hsio) ME Reported Hsio Version:%d CRC=0x%04X Response=%d us\n", (Msg>>16), (Msg&0xFFFF), MAX_ME_MSG_ACK_TIMEOUT - MsgTimeout)); + + // + // Send final message back to ME so that it can restore the FWSTS5 value (used for other messaging) + // + HeciPciAndThenOr32 (R_ME_H_GS, 0, H2M_HSIO_MESSAGE | H2M_HSIO_CMD_CLOSE); + + // + // Get ChipsetInit table indentifier from the one found in the code + // + if(PchChipsetInitTable != NULL) { + PchChipsetInitTableId = *((UINT32*)PchChipsetInitTable); + DEBUG((EFI_D_INFO, "(Hsio) BIOS Hsio Version:%d CRC=0x%04X Length=%d bytes.\n", (PchChipsetInitTableId>>16),(PchChipsetInitTableId&0xFFFF), PchChipsetInitTableLength)); + + // + // If expected table id is not found, then skip the rest of the Hsio programming until it can be updated from DXE + // + if (Msg != PchChipsetInitTableId) { + // + // Pass the expected ChipsetInit table to the DXE code that will apply the settings to ME and reset. + // + ChipsetInitHob->ChipsetInitTableUpdReq = 1; + // + // Copy the ChipsetInit settings from local table into the HOB + // + if (sizeof(ChipsetInitHob->ChipsetInitTable) >= PchChipsetInitTableLength) { + CopyMem (ChipsetInitHob->ChipsetInitTable, PchChipsetInitTable, PchChipsetInitTableLength); + } else { + ASSERT(FALSE); // Table should always fit into HOB structure. + } + + // + // Skip the Hsio programming, DMI setting in ChipsetInit table should be good enough to get through DMI init. + // + return Status; + } + } else { + ASSERT(FALSE); + } + } + } + + /// + /// PCH BIOS Spec Rev 0.5.0, Section 7.1.5 + /// Step 1.1 + /// RCBA + Offset 2088h = 00109000h + /// + MmioWrite32 ( + (RootComplexBar + R_PCH_RCRB_CIR2088), + 0x00109000 + ); + /// + /// Step 1.2 + /// RCBA + offset 20ACh[30] = 1b + /// + MmioOr32 (RootComplexBar + R_PCH_RCRB_REC, BIT30); + if (PchSeries == PchH) { + /// + /// Step 1.3 + /// Set RCBA + Offset 2340h[7:0] = 1Bh + /// + MmioWrite8 (RootComplexBar + 0x2340, 0x1B); + /// + /// Step 1.4 + /// Set RCBA + Offset 2340h[23:16] = 3Ah + /// + Data32And = (UINT32) 0xFF00FFFF; + Data32Or = (UINT32) (0x3A << 16); + + MmioAndThenOr32 ( + RootComplexBar + 0x2340, + Data32And, + Data32Or + ); + /// + /// Step 1.5 + /// Program RCBA + Offset 2324[31:0] = 00854C74h + /// + MmioWrite32 (RootComplexBar + 0x2324, 0x00854C74); + } + + /// + /// Program Hsio Setting + /// + DeviceLaneOwner = MmioRead8 (PciD28F0RegBase + 0x410); + StrpFuseCfg1 = MmioRead32 (PciD28F0RegBase + R_PCH_PCIE_STRPFUSECFG); +#ifdef TRAD_FLAG + /// + /// PCH BIOS Spec Rev 0.5.6, Section 7.1.5 + /// Step 6 + /// Bios is required to program IOBP setting according to the following table: + /// Table 7-10 DMI Lane Setting + /// + if (PchSeries == PchH) { + switch (PchSteppingValue) { + case LptHB0: + size = (sizeof (PchDmiHsioLptH_B0) / sizeof (IOBP_MMIO_TABLE_STRUCT)); + PchDmiHsio = PchDmiHsioLptH_B0; + break; + default: + PchDmiHsio = NULL; + size = 0; + DEBUG ((EFI_D_ERROR, "Unsupported PCH Stepping\n")); + } + for (i = 0; i < size; i++) { + Status = ProgramIobp ( + RootComplexBar, + PchDmiHsio[i].Address, + PchDmiHsio[i].AndMask, + PchDmiHsio[i].OrMask + ); + ASSERT_EFI_ERROR (Status); + } + } +#endif // TRAD_FLAG + + /// + /// PCH BIOS Spec Rev 0.5.6, Section 7.1.5 + /// Table 7-3 USB3 dedicated lane Setting + /// + switch (PchSteppingValue) { +#ifdef ULT_FLAG + case LptLpB0: + case LptLpB1: + case LptLpB2: + size = (sizeof (PchUsb3HsioLptLp_Bx) / sizeof (IOBP_MMIO_TABLE_STRUCT)); + PchUsb3Hsio = PchUsb3HsioLptLp_Bx; + break; +#endif // ULT_FLAG +#ifdef TRAD_FLAG + case LptHB0: + size = (sizeof (PchUsb3HsioLptH_B0) / sizeof (IOBP_MMIO_TABLE_STRUCT)); + PchUsb3Hsio = PchUsb3HsioLptH_B0; + break; + case LptHC0: + case LptHC1: + case LptHC2: + size = (sizeof (PchUsb3HsioLptH_Cx) / sizeof (IOBP_MMIO_TABLE_STRUCT)); + PchUsb3Hsio = PchUsb3HsioLptH_Cx; + break; +#endif // TRAD_FLAG + default: + PchUsb3Hsio = NULL; + size = 0; + DEBUG ((EFI_D_ERROR, "Unsupported PCH Stepping\n")); + } + for (i = 0; i < size; i++) { + Status = ProgramIobp ( + RootComplexBar, + PchUsb3Hsio[i].Address, + PchUsb3Hsio[i].AndMask, + PchUsb3Hsio[i].OrMask + ); + ASSERT_EFI_ERROR (Status); + } + + /// + /// PCH BIOS Spec Rev 0.5.6, Section 7.1.5 + /// Table 7-5 USB3 Shared laneSetting + /// + switch (PchSteppingValue) { +#ifdef ULT_FLAG + case LptLpB0: + case LptLpB1: + case LptLpB2: + size = (sizeof (PchUsb3SharedHsioLptLp_Bx) / sizeof (IOBP_MMIO_TABLE_STRUCT)); + PchUsb3SharedHsio = PchUsb3SharedHsioLptLp_Bx; + break; +#endif // ULT_FLAG +#ifdef TRAD_FLAG + case LptHB0: + size = (sizeof (PchUsb3SharedHsioLptH_B0) / sizeof (IOBP_MMIO_TABLE_STRUCT)); + PchUsb3SharedHsio = PchUsb3SharedHsioLptH_B0; + break; + case LptHC0: + case LptHC1: + case LptHC2: + size = (sizeof (PchUsb3SharedHsioLptH_Cx) / sizeof (IOBP_MMIO_TABLE_STRUCT)); + PchUsb3SharedHsio = PchUsb3SharedHsioLptH_Cx; + break; +#endif // TRAD_FLAG + default: + PchUsb3SharedHsio = NULL; + size = 0; + DEBUG ((EFI_D_ERROR, "Unsupported PCH Stepping\n")); + } + for (i = 0; i < size; i++) { + if (PchSeries == PchLp) { + if ((((PchUsb3SharedHsio[i].Address & 0xFE00) == 0x2400) && ((DeviceLaneOwner & (BIT1 | BIT0)) != BIT1)) || + (((PchUsb3SharedHsio[i].Address & 0xFE00) == 0x2600) && ((DeviceLaneOwner & (BIT3 | BIT2)) != BIT3))) { + continue; + } + } else if (PchSeries == PchH) { + if ((((PchUsb3SharedHsio[i].Address & 0xFE00) == 0x2C00) && ((DeviceLaneOwner & (BIT3 | BIT2)) != BIT3)) || + (((PchUsb3SharedHsio[i].Address & 0xFE00) == 0x2E00) && ((DeviceLaneOwner & (BIT1 | BIT0)) != BIT1))) { + continue; + } + } + Status = ProgramIobp ( + RootComplexBar, + PchUsb3SharedHsio[i].Address, + PchUsb3SharedHsio[i].AndMask, + PchUsb3SharedHsio[i].OrMask + ); + ASSERT_EFI_ERROR (Status); + } + + /// + /// Table 7-9 Gbe Lane Setting + /// Bios should check the PCIE port that is assigned to Gbe and program the following address accordingly + /// + switch (PchSteppingValue) { +#ifdef ULT_FLAG + case LptLpB0: + case LptLpB1: + case LptLpB2: + PchGbeSharedHsio = PchGbeSharedHsioLptLp_Bx; + size = (sizeof (PchGbeSharedHsioLptLp_Bx) / sizeof (IOBP_MMIO_TABLE_STRUCT)); + break; +#endif // ULT_FLAG +#ifdef TRAD_FLAG + case LptHB0: + PchGbeSharedHsio = PchGbeSharedHsioLptH_B0; + size = (sizeof (PchGbeSharedHsioLptH_B0) / sizeof (IOBP_MMIO_TABLE_STRUCT)); + break; + case LptHC0: + case LptHC1: + case LptHC2: + PchGbeSharedHsio = PchGbeSharedHsioLptH_Cx; + size = (sizeof (PchGbeSharedHsioLptH_Cx) / sizeof (IOBP_MMIO_TABLE_STRUCT)); + break; +#endif // TRAD_FLAG + default: + PchGbeSharedHsio = NULL; + size = 0; + DEBUG ((EFI_D_ERROR, "Unsupported PCH Stepping\n")); + } + + + if (PchGbeSharedHsio != NULL) { + if ((StrpFuseCfg1 & B_PCH_PCIE_STRPFUSECFG_GBE_PCIE_PEN) != 0) { + GbePort = (UINT8) ((StrpFuseCfg1 & B_PCH_PCIE_STRPFUSECFG_GBE_PCIEPORTSEL) >> N_PCH_PCIE_STRPFUSECFG_GBE_PCIEPORTSEL); + } else { + GbePort = 0xFF; + } + + if (GbePort != 0xFF) { +#ifdef ULT_FLAG + if (PchSeries == PchLp) { + if (GbePort <= 0x5) { + Status = ProgramIobp ( + RootComplexBar, + PchGbeSharedHsio[GbePort].Address, + PchGbeSharedHsio[GbePort].AndMask, + PchGbeSharedHsio[GbePort].OrMask + ); + ASSERT_EFI_ERROR (Status); + } + } +#endif // ULT_FLAG +#ifdef TRAD_FLAG + if (PchSeries == PchH) { + if (GbePort == 0x0) { + if ((DeviceLaneOwner & (BIT1 | BIT0)) == BIT0) { + Status = ProgramIobp ( + RootComplexBar, + PchGbeSharedHsio[GbePort].Address, + PchGbeSharedHsio[GbePort].AndMask, + PchGbeSharedHsio[GbePort].OrMask + ); + ASSERT_EFI_ERROR (Status); + } + } else if (GbePort == 0x1) { + if ((DeviceLaneOwner & (BIT3 | BIT2)) == BIT2) { + Status = ProgramIobp ( + RootComplexBar, + PchGbeSharedHsio[GbePort].Address, + PchGbeSharedHsio[GbePort].AndMask, + PchGbeSharedHsio[GbePort].OrMask + ); + ASSERT_EFI_ERROR (Status); + } + } else { + Status = ProgramIobp ( + RootComplexBar, + PchGbeSharedHsio[GbePort].Address, + PchGbeSharedHsio[GbePort].AndMask, + PchGbeSharedHsio[GbePort].OrMask + ); + ASSERT_EFI_ERROR (Status); + } + } +#endif // TRAD_FLAG + } + } + /// + /// Step 7 + /// For LP, clear B0:D28:F0~F7:110h[13, 12, 8:6, 0] = 1b, 1b, 111b, 1b + /// For LP, clear B0:D28:F0~F7:104h[20, 18:14, 12, 4] = 1b, 11111b, 1b, 1b + /// +#ifdef ULT_FLAG + if (GetPchSeries() == PchLp) { + for (PortIndex = 0; PortIndex < GetPchMaxPciePortNum (); PortIndex++) { + RPBase = MmPciAddress ( + 0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, + PortIndex, + 0 + ); + MmioOr32 (RPBase + R_PCH_PCIE_CES, (UINT32)(B_PCH_PCIE_CES_ANFES | B_PCH_PCIE_CES_RTT | + B_PCH_PCIE_CES_RNR | B_PCH_PCIE_CES_BD | + B_PCH_PCIE_CES_BT | B_PCH_PCIE_CES_RE)); + MmioOr32 (RPBase + R_PCH_PCIE_UES, (UINT32)(B_PCH_PCIE_UES_URE | B_PCH_PCIE_UES_MT | + B_PCH_PCIE_UES_RO | B_PCH_PCIE_UES_UC | + B_PCH_PCIE_UES_CA | B_PCH_PCIE_UES_CT | + B_PCH_PCIE_UES_PT | B_PCH_PCIE_UES_DLPE)); + } + } +#endif //ULT_FLAG + + /// + /// Step 8 + /// Bios is required to program IOBP setting according to the table 7-7 to 7-8 + /// using 7.1.4 IOSF SBI with OPCODE "PHY Configuration Register". + /// Done in PchSataInit(). + /// + /// PCH BIOS Spec Rev 0.5.1, Section 7.1.5 + /// Step 9 + /// IOBP Programming: + /// For Mobile: + /// BIOS is required to program IOBP setting according to Table 7-11 and + /// Table 7-12 using settings in Section 7.1.4 with OPCODE "PHY Configuration Register". + /// For Desktop: + /// BIOS is required to program IOBP setting according to Table 7-13 and + /// Table 7-14 using settings in Section 7.1.4 with OPCODE "PHY Configuration Register". + /// Done in PchSataInit(). + /// + /// Step 10, 11 + /// Set D20:F0:B0h[7] to 0b + /// Set D20:F0:B0h[16] to 1b + /// + Data32And = (UINT32) ~(BIT7); + Data32Or = (UINT32) (BIT16); + + MmioAndThenOr32 ( + PciD20F0RegBase + 0xB0, + Data32And, + Data32Or + ); + if (GetPchSeries() == PchLp) { + /// + /// Step 12 + /// Sideband Minimum Duration. T_SB_MIN = 16ns + /// RCBA + Offset 260Ch[15:0]=0010h + /// + MmioWrite16 ( + (RootComplexBar + 0x260C), + 0x0010 + ); + /// + /// Step x + /// Program Iobp 0xEC000106 to 3100h + /// + Status = ProgramIobp ( + RootComplexBar, + 0xEC000106, + (UINT32)~(0x00003100), + 0x00003100 + ); + ASSERT_EFI_ERROR (Status); + } + return Status; +} diff --git a/ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchInitCommon.h b/ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchInitCommon.h new file mode 100644 index 0000000..be59220 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchInitCommon.h @@ -0,0 +1,73 @@ +/** @file + Header file for the PCH Common Init PEIM. + +@copyright + Copyright (c) 2009 - 2012 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 +**/ +#ifndef _PCH_INIT_COMMON_PEIM_H_ +#define _PCH_INIT_COMMON_PEIM_H_ + +#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000) +#include "EdkIIGluePeim.h" +#include EFI_PPI_CONSUMER (PchPlatformPolicy) +#include EFI_PPI_CONSUMER (PchUsbPolicy) +#endif + +#define PCH_INIT_COMMON_SCRIPT_IO_WRITE(TableName, Width, Address, Count, Buffer) + +#define PCH_INIT_COMMON_SCRIPT_IO_READ_WRITE(TableName, Width, Address, Data, DataMask) + +#define PCH_INIT_COMMON_SCRIPT_MEM_WRITE(TableName, Width, Address, Count, Buffer) + +#define PCH_INIT_COMMON_SCRIPT_MEM_READ_WRITE(TableName, Width, Address, Data, DataMask) + +#define PCH_INIT_COMMON_SCRIPT_PCI_CFG_WRITE(TableName, Width, Address, Count, Buffer) + +#define PCH_INIT_COMMON_SCRIPT_PCI_CFG_READ_WRITE(TableName, Width, Address, Data, DataMask) + +#define PCH_INIT_COMMON_SCRIPT_STALL(TableName, Duration) + +#define PCH_INIT_COMMON_SCRIPT_SAVE_IOBP_S3_ITEM(RootComplexBar, Address, AndMask, OrMask) \ + EFI_SUCCESS + +#ifdef USB_PRECONDITION_ENABLE_FLAG +/// +/// Execute function when running in PEI +/// +#define USB_RUN_IN_PEI TRUE + +/// +/// Execute function when running in DXE +/// It is always FALSE for PEI phase check +/// +#define USB_RUN_IN_DXE FALSE + +/// +/// USB precondition policy check +/// +#define USB_PRECONDITION_POLICY_SUPPORT(UsbPolicy) \ + ((UsbPolicy)->UsbPrecondition) + +#endif // USB_PRECONDITION_ENABLE_FLAG + +/// +/// USB3 port setting policy check +/// +#define USB3PORT_SETTING_POLICY_SUPPORT(Revision) \ + ((Revision >= PCH_PLATFORM_POLICY_PPI_REVISION_3)) + +#endif diff --git a/ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchInitPeim.c b/ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchInitPeim.c new file mode 100644 index 0000000..12133c7 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchInitPeim.c @@ -0,0 +1,2232 @@ +/** @file + The PCH Init PEIM implements the PCH PEI Init PPI. + +@copyright + Copyright (c) 2004 - 2013 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 "PchInitPeim.h" + +// +// Global variables +// +static PCH_DMI_TC_VC_PPI mPchDmiTcVcMap = { + { + DmiVcTypeVc0, + DmiVcTypeVc1, + DmiVcTypeVcp, + DmiVcTypeVc0, + DmiVcTypeVc0, + DmiVcTypeVc0, + DmiVcTypeVc0, + DmiVcTypeVcm + }, + { + {PCH_DEVICE_ENABLE, (UINT8) 0}, + {PCH_DEVICE_ENABLE, (UINT8) 1}, + {PCH_DEVICE_ENABLE, (UINT8) 2}, + {PCH_DEVICE_ENABLE, (UINT8) 7} + } +}; + +static PCH_INIT_PPI mPchInitPpi = { + PchUsbInit, + PchDmiTcVcProgPoll, + PchDmiGen2Prog, + PchCpuStrapSet +}; + +static EFI_PEI_PPI_DESCRIPTOR mPpiListVariable = { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gPchInitPpiGuid, + &mPchInitPpi +}; + +static EFI_PEI_PPI_DESCRIPTOR mPpiPchPeiInitDone = { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gPchPeiInitDonePpiGuid, + NULL +}; + +static EFI_PEI_NOTIFY_DESCRIPTOR mNotifyList = { + EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, + &gPchPlatformPolicyPpiGuid, + PchInitialize +}; + +EFI_GUID gEfiPeiEndOfPeiPhasePpiGuid = EFI_PEI_END_OF_PEI_PHASE_PPI_GUID; +static EFI_PEI_NOTIFY_DESCRIPTOR mPchS3ResumeNotifyDesc = { + (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiPeiEndOfPeiPhasePpiGuid, + PchS3ResumeAtEndOfPei +}; +// +// Functions +// + +/** + Internal function performing SATA init needed in PEI phase + + @param[in] PeiServices General purpose services available to every PEIM. + @param[in] PchPlatformPolicyPpi The PCH Platform Policy PPI instance + + @retval EFI_SUCCESS No platform reset action is taken. System can continue boot flow. + @retval Others Won't return if platform reset action is taken +**/ +EFI_STATUS +EFIAPI +PchSataInit ( + IN EFI_PEI_SERVICES **PeiServices, + IN PCH_PLATFORM_POLICY_PPI *PchPlatformPolicyPpi + ) +{ + + UINT32 Data32And; + UINT32 Data32Or; + UINTN PciD31F0RegBase; + UINT16 LpcDeviceId; + UINTN PciD31F2RegBase; + UINTN PciD28F0RegBase; + BOOLEAN SkipSataInit; + UINT16 i; + UINT16 GSpeed; + UINT16 PortId; + UINT8 RxEq; + UINT32 OrMask; + UINT16 size; + UINT32 RootComplexBar; + UINT8 DeviceLaneOwner; + EFI_STATUS Status; + PCH_SERIES PchSeries; + UINT32 PchSataTraceId; +#ifdef TRAD_FLAG + IOBP_MMIO_TABLE_STRUCT *PchSataHsio; + IOBP_MMIO_TABLE_STRUCT *PchSataHsio_MB; + IOBP_MMIO_TABLE_STRUCT *PchSataHsio_DT; + IOBP_SATA_RXEQ_TABLE *PchSataRxEqHsio; +#endif // TRAD_FLAG + IOBP_MMIO_TABLE_STRUCT *PchSataSharedHsio; + IOBP_MMIO_TABLE_STRUCT *PchSataSharedHsio_MB; + IOBP_MMIO_TABLE_STRUCT *PchSataSharedHsio_DT; + IOBP_SATA_RXEQ_TABLE *PchSataRxEqSharedHsio; + + DEBUG ((EFI_D_INFO, "PchSataInit() - Start\n")); + + PchSeries = GetPchSeries(); + RootComplexBar = PCH_RCRB_BASE; + PciD31F0RegBase = MmPciAddress ( + 0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + 0 + ); + LpcDeviceId = MmioRead16 (PciD31F0RegBase + R_PCH_LPC_DEVICE_ID); + PciD31F2RegBase = MmPciAddress ( + 0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_SATA, + PCI_FUNCTION_NUMBER_PCH_SATA, + 0 + ); + PciD28F0RegBase = MmPciAddress ( + 0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, + PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_1, + 0 + ); + SkipSataInit = FALSE; + + /// + /// Skip SATA init if any of SATA port0 ~ port3 is enabled + /// + if ((MmioRead8 (PciD31F2RegBase + R_PCH_SATA_PCS) & (UINT8) (B_PCH_SATA_PCS_PORT3_EN | + B_PCH_SATA_PCS_PORT2_EN | + B_PCH_SATA_PCS_PORT1_EN | + B_PCH_SATA_PCS_PORT0_EN)) != 0) { + SkipSataInit = TRUE; + } + if (PchSeries == PchH) { + /// + /// Skip SATA init if SATA port4 or port5 is enabled + /// + if ((MmioRead8 (PciD31F2RegBase + R_PCH_SATA_PCS) & (UINT8) (B_PCH_SATA_PCS_PORT5_EN | + B_PCH_SATA_PCS_PORT4_EN)) != 0) { + SkipSataInit = TRUE; + } + } + if (SkipSataInit == TRUE) { + if (PchSeries == PchH) { + /// + /// Any SATA port should not be enabled unless CPU only reset. + /// The value of 0xEA000AAC[5:4] is 10b after issuing CPU only reset. + /// Note: + /// The default value of 0xEA000AAC[5:4] is 00b. + /// The following "if" condition will need to update while the + /// BIOS recommended setting of 0xEA000AAC[5:4] is changed. + /// Asset if any SATA port is enabled before SATA Hsio initialization is done + /// + Status = ReadIobp (RootComplexBar, 0xEA000AAC, &Data32And); + if ((Data32And & (UINT32) (BIT4 | BIT5)) != 0x20) { + DEBUG ((EFI_D_ERROR, "Please do not enable any SATA port before SATA Hsio initialization is done.\n")); + ASSERT (0); + } + } + } else { + /// + /// Assume SATA mode will be AHCI, SATA Port 0 - Port 5 are all for D31:F2 + /// + if (PchSeries == PchH) { + MmioAndThenOr8 ( + PciD31F2RegBase + R_PCH_SATA_MAP, + (UINT8) (~B_PCH_SATA_MAP_SMS_MASK), + (UINT8) (V_PCH_SATA_MAP_SMS_AHCI | B_PCH_SATA_PORT_TO_CONTROLLER_CFG) + ); + } else if (PchSeries == PchLp) { + MmioAndThenOr8 ( + PciD31F2RegBase + R_PCH_SATA_MAP, + (UINT8) (~B_PCH_SATA_MAP_SMS_MASK), + (UINT8) (V_PCH_SATA_MAP_SMS_AHCI) + ); + } + /// + /// PCH BIOS Spec Rev 0.5.0 section 14.1.7 Additional Programming Requirements during + /// SATA Initialization + /// Step 2 + /// System BIOS must set D31:F2:Reg 94h[8:0] = 183h as part of the chipset initialization + /// prior to SATA configuration. These bits should be restored while resuming from a S3 + /// sleep state. + /// + Data32And = (UINT32)~(BIT8 | BIT7 | BIT6 | BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0); + Data32Or = 0x183; + MmioAndThenOr32 ( + (UINTN) (PciD31F2RegBase + R_PCH_SATA_SCLKCG), + Data32And, + Data32Or + ); + /// + /// Step 3 + /// D31:F2:Reg 92h[15] = 1b + /// Set OOB Retry Mode bit of Port Control and Status (PCS) register + /// These bits should be restored while resuming from a S3 sleep state + /// + MmioOr16 ((UINTN) (PciD31F2RegBase + R_PCH_SATA_PCS), (UINT16) (B_PCH_SATA_PCS_OOB_RETRY)); + /// + /// Step 4 + /// System BIOS must program SATA Hsio table as stated in Table 7-7 to 7-8 BEFORE the SATA + /// ports are enabled. + /// + /// PCH BIOS Spec Rev 0.5.6, Section 7.1.5 + /// Step 8 + /// Bios is required to program IOBP setting according to the table 7-7 to 7-8 + /// using 7.1.4 IOSF SBI with OPCODE "PHY Configuration Register". + /// Table 7-7 SATA dedicated lane setting + /// + DeviceLaneOwner = MmioRead8 (PciD28F0RegBase + 0x410); +#ifdef TRAD_FLAG + switch (PchStepping()) { + case LptHB0: + size = (sizeof (PchSataHsioLptH_B0) / sizeof (IOBP_MMIO_TABLE_STRUCT)); + PchSataHsio = PchSataHsioLptH_B0; + break; + case LptHC0: + case LptHC1: + case LptHC2: + size = (sizeof (PchSataHsioLptH_Cx) / sizeof (IOBP_MMIO_TABLE_STRUCT)); + PchSataHsio = PchSataHsioLptH_Cx; + break; + default: + PchSataHsio = NULL; + size = 0; + DEBUG ((EFI_D_ERROR, "Unsupported PCH Stepping\n")); + } + + for (i = 0; i < size; i++) { + Status = ProgramIobp ( + RootComplexBar, + PchSataHsio[i].Address, + PchSataHsio[i].AndMask, + PchSataHsio[i].OrMask + ); + ASSERT_EFI_ERROR (Status); + } +#endif // TRAD_FLAG + /// + /// Table 7-8 SATA Shared lane setting + /// + switch (PchStepping()) { +#ifdef ULT_FLAG + case LptLpB0: + case LptLpB1: + case LptLpB2: + size = (sizeof (PchSataSharedHsioLptLp_Bx) / sizeof (IOBP_MMIO_TABLE_STRUCT)); + PchSataSharedHsio = PchSataSharedHsioLptLp_Bx; + break; +#endif // ULT_FLAG +#ifdef TRAD_FLAG + case LptHB0: + size = (sizeof (PchSataSharedHsioLptH_B0) / sizeof (IOBP_MMIO_TABLE_STRUCT)); + PchSataSharedHsio = PchSataSharedHsioLptH_B0; + break; + case LptHC0: + case LptHC1: + case LptHC2: + size = (sizeof (PchSataSharedHsioLptH_Cx) / sizeof (IOBP_MMIO_TABLE_STRUCT)); + PchSataSharedHsio = PchSataSharedHsioLptH_Cx; + break; +#endif // TRAD_FLAG + default: + size = 0; + PchSataSharedHsio = NULL; + DEBUG ((EFI_D_ERROR, "Unsupported PCH Stepping\n")); + } + for (i = 0; i < size; i++) { + if (PchSeries == PchLp) { + if ((((PchSataSharedHsio[i].Address & 0xFE00) == 0x2000) && ((DeviceLaneOwner & BIT4) == BIT4)) || + (((PchSataSharedHsio[i].Address & 0xFE00) == 0x2200) && ((DeviceLaneOwner & BIT5) == BIT5)) || + (((PchSataSharedHsio[i].Address & 0xFE00) == 0x2400) && ((DeviceLaneOwner & BIT6) == BIT6)) || + (((PchSataSharedHsio[i].Address & 0xFE00) == 0x2600) && ((DeviceLaneOwner & BIT7) == BIT7))) { + continue; + } + } else if (PchSeries == PchH) { + if ((((PchSataSharedHsio[i].Address & 0xFE00) == 0x2000) && ((DeviceLaneOwner & BIT4) == BIT4)) || + (((PchSataSharedHsio[i].Address & 0xFE00) == 0x2200) && ((DeviceLaneOwner & BIT5) == BIT5))) { + continue; + } + } + Status = ProgramIobp ( + RootComplexBar, + PchSataSharedHsio[i].Address, + PchSataSharedHsio[i].AndMask, + PchSataSharedHsio[i].OrMask + ); + ASSERT_EFI_ERROR (Status); + } + + /// + /// PCH BIOS Spec Rev 0.5.1, Section 7.1.5 + /// Step 9 + /// IOBP Programming: + /// For Mobile: + /// BIOS is required to program IOBP setting according to Table 7-11 and + /// Table 7-12 using settings in Section 7.1.4 with OPCODE "PHY Configuration Register". + /// + if (IS_PCH_LPT_LPC_DEVICE_ID_MOBILE (LpcDeviceId)) { +#ifdef TRAD_FLAG + /// + /// Table 7-11 SATA Dedicated Lane Setting + /// + switch (PchStepping()) { + case LptHB0: + size = (sizeof (PchSataHsioLptH_MB_B0) / sizeof (IOBP_MMIO_TABLE_STRUCT)); + PchSataHsio_MB = PchSataHsioLptH_MB_B0; + break; + case LptHC0: + case LptHC1: + case LptHC2: + size = (sizeof (PchSataHsioLptH_MB_Cx) / sizeof (IOBP_MMIO_TABLE_STRUCT)); + PchSataHsio_MB = PchSataHsioLptH_MB_Cx; + break; + default: + size = 0; + PchSataHsio_MB = NULL; + DEBUG ((EFI_D_ERROR, "Unsupported PCH Stepping\n")); + } + for (i = 0; i < size; i++) { + Status = ProgramIobp ( + RootComplexBar, + PchSataHsio_MB[i].Address, + PchSataHsio_MB[i].AndMask, + PchSataHsio_MB[i].OrMask + ); + ASSERT_EFI_ERROR (Status); + } +#endif // TRAD_FLAG + /// + /// Table 7-12 SATA Shared Lane Setting + /// + switch (PchStepping()) { +#ifdef ULT_FLAG + case LptLpB0: + case LptLpB1: + case LptLpB2: + size = (sizeof (PchSataSharedHsioLptLp_MB_Bx) / sizeof (IOBP_MMIO_TABLE_STRUCT)); + PchSataSharedHsio_MB = PchSataSharedHsioLptLp_MB_Bx; + break; +#endif // ULT_FLAG +#ifdef TRAD_FLAG + case LptHB0: + size = (sizeof (PchSataSharedHsioLptH_MB_B0) / sizeof (IOBP_MMIO_TABLE_STRUCT)); + PchSataSharedHsio_MB = PchSataSharedHsioLptH_MB_B0; + break; + case LptHC0: + case LptHC1: + case LptHC2: + size = (sizeof (PchSataSharedHsioLptH_MB_Cx) / sizeof (IOBP_MMIO_TABLE_STRUCT)); + PchSataSharedHsio_MB = PchSataSharedHsioLptH_MB_Cx; + break; +#endif // TRAD_FLAG + default: + size = 0; + PchSataSharedHsio_MB = NULL; + DEBUG ((EFI_D_ERROR, "Unsupported PCH Stepping\n")); + } + for (i = 0; i < size; i++) { + if (PchSeries == PchLp) { + if ((((PchSataSharedHsio_MB[i].Address & 0xFE00) == 0x2000) && ((DeviceLaneOwner & BIT4) == BIT4)) || + (((PchSataSharedHsio_MB[i].Address & 0xFE00) == 0x2200) && ((DeviceLaneOwner & BIT5) == BIT5)) || + (((PchSataSharedHsio_MB[i].Address & 0xFE00) == 0x2400) && ((DeviceLaneOwner & BIT6) == BIT6)) || + (((PchSataSharedHsio_MB[i].Address & 0xFE00) == 0x2600) && ((DeviceLaneOwner & BIT7) == BIT7))) { + continue; + } + } else if (PchSeries == PchH) { + if ((((PchSataSharedHsio_MB[i].Address & 0xFE00) == 0x2000) && ((DeviceLaneOwner & BIT4) == BIT4)) || + (((PchSataSharedHsio_MB[i].Address & 0xFE00) == 0x2200) && ((DeviceLaneOwner & BIT5) == BIT5))) { + continue; + } + } + Status = ProgramIobp ( + RootComplexBar, + PchSataSharedHsio_MB[i].Address, + PchSataSharedHsio_MB[i].AndMask, + PchSataSharedHsio_MB[i].OrMask + ); + ASSERT_EFI_ERROR (Status); + } + } else { + /// + /// For Desktop: + /// BIOS is required to program IOBP setting according to Table 7-13 and + /// Table 7-14 using settings in Section 7.1.4 with OPCODE "PHY Configuration Register". + /// Table 7-13 SATA Dedicated Lane Setting + /// +#ifdef TRAD_FLAG + switch (PchStepping()) { + case LptHB0: + size = (sizeof (PchSataHsioLptH_DT_B0) / sizeof (IOBP_MMIO_TABLE_STRUCT)); + PchSataHsio_DT = PchSataHsioLptH_DT_B0; + break; + case LptHC0: + case LptHC1: + case LptHC2: + size = (sizeof (PchSataHsioLptH_DT_Cx) / sizeof (IOBP_MMIO_TABLE_STRUCT)); + PchSataHsio_DT = PchSataHsioLptH_DT_Cx; + break; + default: + size = 0; + PchSataHsio_DT = NULL; + DEBUG ((EFI_D_ERROR, "Unsupported PCH Stepping\n")); + } + for (i = 0; i < size; i++) { + Status = ProgramIobp ( + RootComplexBar, + PchSataHsio_DT[i].Address, + PchSataHsio_DT[i].AndMask, + PchSataHsio_DT[i].OrMask + ); + ASSERT_EFI_ERROR (Status); + } +#endif // TRAD_FLAG + /// + /// Table 7-14 SATA Shared Lane Setting + /// + switch (PchStepping()) { +#ifdef ULT_FLAG + case LptLpB0: + case LptLpB1: + case LptLpB2: + size = (sizeof (PchSataSharedHsioLptLp_DT_Bx) / sizeof (IOBP_MMIO_TABLE_STRUCT)); + PchSataSharedHsio_DT = PchSataSharedHsioLptLp_DT_Bx; + break; +#endif // ULT_FLAG +#ifdef TRAD_FLAG + case LptHB0: + size = (sizeof (PchSataSharedHsioLptH_DT_B0) / sizeof (IOBP_MMIO_TABLE_STRUCT)); + PchSataSharedHsio_DT = PchSataSharedHsioLptH_DT_B0; + break; + case LptHC0: + case LptHC1: + case LptHC2: + size = (sizeof (PchSataSharedHsioLptH_DT_Cx) / sizeof (IOBP_MMIO_TABLE_STRUCT)); + PchSataSharedHsio_DT = PchSataSharedHsioLptH_DT_Cx; + break; +#endif // TRAD_FLAG + default: + size = 0; + PchSataSharedHsio_DT = NULL; + DEBUG ((EFI_D_ERROR, "Unsupported PCH Stepping\n")); + } + for (i = 0; i < size; i++) { + if (PchSeries == PchLp) { + if ((((PchSataSharedHsio_DT[i].Address & 0xFE00) == 0x2000) && ((DeviceLaneOwner & BIT4) == BIT4)) || + (((PchSataSharedHsio_DT[i].Address & 0xFE00) == 0x2200) && ((DeviceLaneOwner & BIT5) == BIT5)) || + (((PchSataSharedHsio_DT[i].Address & 0xFE00) == 0x2400) && ((DeviceLaneOwner & BIT6) == BIT6)) || + (((PchSataSharedHsio_DT[i].Address & 0xFE00) == 0x2600) && ((DeviceLaneOwner & BIT7) == BIT7))) { + continue; + } + } else if (PchSeries == PchH) { + if ((((PchSataSharedHsio_DT[i].Address & 0xFE00) == 0x2000) && ((DeviceLaneOwner & BIT4) == BIT4)) || + (((PchSataSharedHsio_DT[i].Address & 0xFE00) == 0x2200) && ((DeviceLaneOwner & BIT5) == BIT5))) { + continue; + } + } + Status = ProgramIobp ( + RootComplexBar, + PchSataSharedHsio_DT[i].Address, + PchSataSharedHsio_DT[i].AndMask, + PchSataSharedHsio_DT[i].OrMask + ); + ASSERT_EFI_ERROR (Status); + } + } + + /// + /// Table 7-15 SATA RxEq Dedicated Lane Setting + /// + PchSataTraceId = 0; +#ifdef TRAD_FLAG + switch (PchStepping()) { + case LptHC0: + case LptHC1: + case LptHC2: + size = (sizeof (PchSataRxEqHsioLptH_Cx) / sizeof (IOBP_SATA_RXEQ_TABLE)); + PchSataRxEqHsio = PchSataRxEqHsioLptH_Cx; + break; + default: + PchSataRxEqHsio = NULL; + size = 0; + DEBUG ((EFI_D_ERROR, "Unsupported PCH Stepping\n")); + } + + for(PortId = 0; PortId < GetPchMaxSataPortNum (); PortId++){ + for(GSpeed = 0; GSpeed < 3; GSpeed++){ + if(PchPlatformPolicyPpi->SataConfig->SataTraceConfig->PortRxEq[PortId].GenSpeed[GSpeed].Enable == PCH_DEVICE_ENABLE) { + PchSataTraceId = PCH_SATA_RXEQ_ID(PortId, GSpeed); + for (i = 0; i < size; i++) { + if(PchSataRxEqHsio[i].TraceId == PchSataTraceId) { + RxEq = PchPlatformPolicyPpi->SataConfig->SataTraceConfig->PortRxEq[PortId].GenSpeed[GSpeed].RxEq; + OrMask = (((UINT32) (((RxEq) << 24 ) + ((RxEq) << 16 ) + ((RxEq) << 8 ) + RxEq)) & ((UINT32)~(PchSataRxEqHsio[i].AndMask))); + Status = ProgramIobp ( + RootComplexBar, + PchSataRxEqHsio[i].Address, + PchSataRxEqHsio[i].AndMask, + OrMask + ); + ASSERT_EFI_ERROR (Status); + } + } + } + } + } +#endif // TRAD_FLAG + + /// + /// Table 7-16 SATA RxEq Shared Lane Setting + /// + switch (PchStepping()) { +#ifdef ULT_FLAG + case LptLpB0: + case LptLpB1: + case LptLpB2: + size = (sizeof (PchSataRxEqSharedHsioLptLp_Bx) / sizeof (IOBP_SATA_RXEQ_TABLE)); + PchSataRxEqSharedHsio = PchSataRxEqSharedHsioLptLp_Bx; + break; +#endif // ULT_FLAG +#ifdef TRAD_FLAG + case LptHC0: + case LptHC1: + case LptHC2: + size = (sizeof (PchSataRxEqSharedHsioLptH_Cx) / sizeof (IOBP_SATA_RXEQ_TABLE)); + PchSataRxEqSharedHsio = PchSataRxEqSharedHsioLptH_Cx; + break; +#endif // TRAD_FLAG + default: + size = 0; + PchSataRxEqSharedHsio = NULL; + DEBUG ((EFI_D_ERROR, "Unsupported PCH Stepping\n")); + } + + for(PortId = 0; PortId < GetPchMaxSataPortNum (); PortId++){ + for(GSpeed = 0; GSpeed < 3; GSpeed++){ + if(PchPlatformPolicyPpi->SataConfig->SataTraceConfig->PortRxEq[PortId].GenSpeed[GSpeed].Enable == PCH_DEVICE_ENABLE) { + PchSataTraceId = PCH_SATA_RXEQ_ID(PortId, GSpeed); + for (i = 0; i < size; i++) { + if(PchSataRxEqSharedHsio[i].TraceId == PchSataTraceId) { + if (PchSeries == PchLp) { + if ((((PchSataRxEqSharedHsio[i].Address & 0xFE00) == 0x2000) && ((DeviceLaneOwner & BIT4) == BIT4)) || + (((PchSataRxEqSharedHsio[i].Address & 0xFE00) == 0x2200) && ((DeviceLaneOwner & BIT5) == BIT5)) || + (((PchSataRxEqSharedHsio[i].Address & 0xFE00) == 0x2400) && ((DeviceLaneOwner & BIT6) == BIT6)) || + (((PchSataRxEqSharedHsio[i].Address & 0xFE00) == 0x2600) && ((DeviceLaneOwner & BIT7) == BIT7))) + { + continue; + } + } else if (PchSeries == PchH) { + if ((((PchSataRxEqSharedHsio[i].Address & 0xFE00) == 0x2000) && ((DeviceLaneOwner & BIT4) == BIT4)) || + (((PchSataRxEqSharedHsio[i].Address & 0xFE00) == 0x2200) && ((DeviceLaneOwner & BIT5) == BIT5))) + { + continue; + } + } + RxEq = PchPlatformPolicyPpi->SataConfig->SataTraceConfig->PortRxEq[PortId].GenSpeed[GSpeed].RxEq; + OrMask = (((UINT32) (((RxEq) << 24 ) + ((RxEq) << 16 ) + ((RxEq) << 8 ) + RxEq)) & ((UINT32)~(PchSataRxEqSharedHsio[i].AndMask))); + Status = ProgramIobp ( + RootComplexBar, + PchSataRxEqSharedHsio[i].Address, + PchSataRxEqSharedHsio[i].AndMask, + OrMask + ); + ASSERT_EFI_ERROR (Status); + } + } + } + } + } + /// + /// PCH BIOS Spec Rev 0.5.0 section 14.1.7 Additional Programming Requirements during + /// SATA Initialization + /// Step 5 + /// Program D31:F2:98h[22] to 1b for desktop and mobile platform only. + /// + if (IS_PCH_LPT_LPC_DEVICE_ID_DESKTOP (LpcDeviceId) || + IS_PCH_LPT_LPC_DEVICE_ID_MOBILE (LpcDeviceId)) { + MmioOr32 ( + (UINTN) (PciD31F2RegBase + 0x98), + (UINT32) (BIT22) + ); + } + /// + /// Step 6 + /// Program D31:F2:98h[19] = 1b + /// + MmioOr32 ( + (UINTN) (PciD31F2RegBase + 0x98), + (UINT32) (BIT19) + ); + /// + /// Step 7 + /// Program D31:F2:98h[12:7] = 04h + /// + Data32And = (UINT32) (~(BIT7 | BIT8 | BIT10 | BIT11 | BIT12)); + Data32Or = (UINT32) (BIT9); + MmioAndThenOr32 ( + (UINTN) (PciD31F2RegBase + 0x98), + Data32And, + Data32Or + ); + /// + /// Step 8 + /// Program D31:F2:98h[20] to 1b + /// + MmioOr32 ((UINTN) (PciD31F2RegBase + 0x98), (UINT32) (BIT20)); + /// + /// Step 9 + /// Program D31:F2:98h[6:5] to 01b + /// + MmioAndThenOr32 ( + (UINTN) (PciD31F2RegBase + 0x98), + (UINT32) (~(BIT6 | BIT5)), + BIT5 + ); + /// + /// Step 10 + /// Program D31:F2:98h [18] to 1b + /// + Data32Or = (UINT32) (BIT18); + MmioOr32 ( + (UINTN) (PciD31F2RegBase + 0x98), + Data32Or + ); + /// + /// Step 11 + /// Program D31:F2:98h[29] to 1b + /// Done in PchInitBeforeBoot() + /// + /// Step 12 + /// Program D31:F2:9Ch[5] to 1b (Note: this must be programmed together with D31:F2:9Ch[7:6] + /// in word write) + /// Done in ConfigureSata () + /// + /// Step 13 + /// When SATA in IDE mode + /// a. Program D31:F2:34h [7:0] to 70h + /// b. Program D31:F2:70h [15:8] to 0h + /// Done in PchMiscInit () + /// + /// Step 14 + /// Program D31:F2:9Ch[31] to 1b at the End of Post + /// Done in PchInitBeforeBoot() + /// + /// Enable the SATA port0 ~ port3. + /// + if (PchSeries == PchH) { + MmioOr8 ( + PciD31F2RegBase + R_PCH_SATA_PCS, + (UINT8) (B_PCH_SATA_PCS_PORT3_EN | B_PCH_SATA_PCS_PORT2_EN | B_PCH_SATA_PCS_PORT1_EN | B_PCH_SATA_PCS_PORT0_EN) + ); + } + if (PchSeries == PchLp) { + /// + /// If D28:F0:410h[7] = 1b, System BIOS should not enable the SATA port0 + /// If D28:F0:410h[6] = 1b, System BIOS should not enable the SATA port1 + /// If D28:F0:410h[5] = 1b, System BIOS should not enable the SATA port2 + /// If D28:F0:410h[4] = 1b, System BIOS should not enable the SATA port3 + /// + if ((MmioRead8 (PciD28F0RegBase + 0x410) & BIT7) == 0) { + MmioOr8 ( + PciD31F2RegBase + R_PCH_SATA_PCS, + (UINT8) B_PCH_SATA_PCS_PORT0_EN + ); + } + if ((MmioRead8 (PciD28F0RegBase + 0x410) & BIT6) == 0) { + MmioOr8 ( + PciD31F2RegBase + R_PCH_SATA_PCS, + (UINT8) B_PCH_SATA_PCS_PORT1_EN + ); + } + if ((MmioRead8 (PciD28F0RegBase + 0x410) & BIT5) == 0) { + MmioOr8 ( + PciD31F2RegBase + R_PCH_SATA_PCS, + (UINT8) B_PCH_SATA_PCS_PORT2_EN + ); + } + if ((MmioRead8 (PciD28F0RegBase + 0x410) & BIT4) == 0) { + MmioOr8 ( + PciD31F2RegBase + R_PCH_SATA_PCS, + (UINT8) B_PCH_SATA_PCS_PORT3_EN + ); + } + } + if (PchSeries == PchH) { + /// + /// Enable the SATA port4 and port5. + /// Step 1.a + /// If D28:F0:410h[4] = 1b, System BIOS should not enable the SATA port4 + /// Step 1.b + /// If D28:F0:410h[5] = 1b, System BIOS should not enable the SATA port5 + /// + if ((MmioRead8 (PciD28F0RegBase + 0x410) & BIT4) == 0) { + MmioOr8 ( + PciD31F2RegBase + R_PCH_SATA_PCS, + (UINT8) B_PCH_SATA_PCS_PORT4_EN + ); + } + if ((MmioRead8 (PciD28F0RegBase + 0x410) & BIT5) == 0) { + MmioOr8 ( + PciD31F2RegBase + R_PCH_SATA_PCS, + (UINT8) B_PCH_SATA_PCS_PORT5_EN + ); + } + } + } + + DEBUG ((EFI_D_INFO, "PchSataInit() - End\n")); + + return EFI_SUCCESS; +} + +/** + The function is used while doing CPU Only Reset, where PCH may be required + to initialize strap data before soft reset. + + @param[in] PeiServices General purpose services available to every PEIM + @param[in] Operation Get/Set Cpu Strap Set Data + @param[in, out] CpuStrapSet Cpu Strap Set Data + + @retval EFI_SUCCESS The function completed successfully. + @exception EFI_UNSUPPORTED The function is not supported. +**/ +EFI_STATUS +EFIAPI +PchCpuStrapSet ( + IN EFI_PEI_SERVICES **PeiServices, + IN CPU_STRAP_OPERATION Operation, + IN OUT UINT16 *CpuStrapSet + ) +{ + UINT32 RootComplexBar; + + DEBUG ((EFI_D_INFO, "PchCpuStrapSet() - Start\n")); + + RootComplexBar = PCH_RCRB_BASE; + + switch (Operation) { + case GetCpuStrapSetData: + /// + /// Get CPU Strap Settings select. 0 = from descriptor, 1 = from PCH + /// + if ((MmioRead8 ((UINTN) (RootComplexBar + R_PCH_SPI_SRDC)) & B_PCH_SPI_SRDC_SRDS) == 0) { + /// + /// Read Strap from Flash Descriptor + /// + *CpuStrapSet = 0; + return EFI_SUCCESS; + } else { + /// + /// Read Strap from PCH Soft Strap. + /// + *CpuStrapSet = MmioRead16 ((UINTN) (RootComplexBar + R_PCH_SPI_SRD)); + } + break; + + case SetCpuStrapSetData: + /// + /// PCH BIOS Spec Rev 0.5.0, Section 4.3 Soft Reset Control + /// 2. If there are CPU configuration changes, program the strap setting into the + /// Soft Reset Data register located at SPIBAR Offset F8h [15:0] (RCBA + Offset 38F8h [15:0]) + /// and follow the steps outlined in the "CPU Only Reset BIOS Flow" section of the Processor + /// BIOS Writer's Guide and skip steps 3 and 4. + /// a. Program Soft Reset Data Register SPIBAR + F8h [13:0] (RCBA + 38F8h [13:0]) + /// (details in Processor BIOS Writer's Guide) + /// b. Set RCBA + Offset 38F4h[0] = 1b + /// c. Set RCBA + Offset 38F0h[0] = 1b + /// d. Skip steps 3 and 4. + /// + MmioWrite16 ((UINTN) (RootComplexBar + R_PCH_SPI_SRD), *CpuStrapSet); + MmioOr8 ((UINTN) (RootComplexBar + R_PCH_SPI_SRDC), B_PCH_SPI_SRDC_SRDS); + MmioOr8 ((UINTN) (RootComplexBar + R_PCH_SPI_SRDL), B_PCH_SPI_SRDL_SSL); + break; + + case LockCpuStrapSetData: + MmioOr8 ((UINTN) (RootComplexBar + R_PCH_SPI_SRDL), B_PCH_SPI_SRDL_SSL); + break; + + default: + break; + } + + DEBUG ((EFI_D_INFO, "PchCpuStrapSet() - End\n")); + + return EFI_SUCCESS; +} + +/** + This function may trigger platform reset depending on the current GbE status, + the intended GbE enabling, and current ME status. (When ME is enabled, this function + may trigger a Global reset.) + This function may not return if it triggers an platform reset and the BIOS boot flow + restarts. + If this function returns EFI_SUCCESS it indicates there is no need for platform + reset in this boot, and boot flow continues. + If this function returns EFI_DEVICE_ERROR, something error happens. + + @param[in] PeiServices General purpose services available to every PEIM. + @param[in] PchPlatformPolicyPpi The PCH Platform Policy PPI instance + + @retval EFI_SUCCESS No platform reset action is taken. System can continue boot flow. + @retval Others Won't return if platform reset action is taken +**/ +EFI_STATUS +EFIAPI +PchGbeMandatedReset ( + IN EFI_PEI_SERVICES **PeiServices, + IN PCH_PLATFORM_POLICY_PPI *PchPlatformPolicyPpi + ) +{ + UINT8 RegData8; + UINTN PciD25F0RegBase; + UINT32 GbEMemBar; + UINT32 TempGbEMemBar; + UINT16 CmdReg; + BOOLEAN ResetRequired; + BOOLEAN GbeRegion; + PCH_RESET_PPI *PchResetPpi; + EFI_STATUS Status; + PCH_RESET_TYPE PchResetType; + + PciD25F0RegBase = 0; + GbEMemBar = 0; + ResetRequired = FALSE; + + /// + /// Read the BUC register + /// + RegData8 = MmioRead8 (PchPlatformPolicyPpi->Rcba + R_PCH_RCRB_BUC); + + GbeRegion = PchIsGbeRegionValid (PchPlatformPolicyPpi->Rcba); + + /// + /// If no change of status, just return success + /// + if (((RegData8 & B_PCH_RCRB_BUC_LAN_DIS) && + !PchPlatformPolicyPpi->GbeConfig->EnableGbe) || + (!(RegData8 & B_PCH_RCRB_BUC_LAN_DIS) && + PchPlatformPolicyPpi->GbeConfig->EnableGbe)) { + return EFI_SUCCESS; + } + + + Status = (*PeiServices)->LocatePpi ( + PeiServices, + &gPchResetPpiGuid, + 0, + NULL, + (VOID **)&PchResetPpi + ); + + ASSERT_EFI_ERROR (Status); + + /// + /// Before modifying LAN Disable bit, make sure it's not locked. + /// If it's locked, issus a GlobalReset to unlock it. + /// + RegData8 = MmioRead8 (PchPlatformPolicyPpi->Rcba + R_PCH_RCRB_FDSW); + if (RegData8 & B_PCH_RCRB_FDSW_FDSWL) { + DEBUG ((EFI_D_ERROR, "PchGbeMandatedReset: resetting the board via CF9 to unlock LAN Disable register...\n")); + PchResetPpi->Reset (PchResetPpi, GlobalReset); + /// + /// Shouldn't reach here + /// + return EFI_SUCCESS; + } + + /// + /// PCH BIOS Spec Rev 0.5.0, Section 10.2.1/10.2.2 Enable/Disable the GbE Clock Gating + /// Step 3 + /// Set RCBA + 341Ch[23] + /// Done in ConfigureClockGating() + /// + /// PCH BIOS Spec Rev 0.5.0, Section 10.2 Enabling / Disabling the Internal GbE Controller + /// In PCH systems, changing the internal GbE controller from disabled to enabled + /// during POST requires a system reset (IO port CF9h = 0Eh) immediately after clearing the LAN disable + /// bit in the BUC register, RCBA + 3414[5]. If ME is enabled and the LAN disable bit + /// has changed, then system BIOS must set D31:F0:Reg 0ACh[20] prior to issuing a platform reset (IO port CF9h = 0x6 or 0xE). + /// + /// Therefore, the flow is as below: + /// When LAN changes from disabled to enabled + /// If ME is not existed, require a power cycle reset. + /// If ME is enabled, require a global reset. + /// When LAN changes from enabled to disabled + /// If ME is not existed, no power cycle reset is required. + /// If ME is enabled, and Me is using Gbe (by checking GBEBAR+0x5B54[15]=1), require a global reset. + /// + + /// + /// Set the BUC register + /// + if (PchPlatformPolicyPpi->GbeConfig->EnableGbe) { + /// + /// Change internal Gbe from disabled to enabled + /// + if (GbeRegion == TRUE) { + ResetRequired = TRUE; + /// + /// PCH BIOS Spec Rev 0.5.0, Section 10.2.1 Enable the Internal GbE Controller + /// Step 1 + /// Set RCBA + 3414h[5] = 0b + /// + MmioAnd8 (PchPlatformPolicyPpi->Rcba + R_PCH_RCRB_BUC, (UINT8) (~B_PCH_RCRB_BUC_LAN_DIS)); + } + } else { + /// + /// Change internal Gbe from enabled to disabled + /// + if (GbeRegion == TRUE) { + /// + /// PCH BIOS Spec Rev 0.5.0, Section 10.2.2 Disable the Internal GbE Controller + /// Step 1a + /// If Intel ME enable then detect if it supports GBe. Read FWSM_S[15] bit in MBARA + offset 5B54h register. + /// + PciD25F0RegBase = MmPciAddress ( + 0, + PchPlatformPolicyPpi->BusNumber, + PCI_DEVICE_NUMBER_PCH_LAN, + PCI_FUNCTION_NUMBER_PCH_LAN, + 0 + ); + /// + /// Store current value of PCH_LAN_MEM_BASE_A + /// + TempGbEMemBar = MmioRead32 (PciD25F0RegBase + R_PCH_LAN_MEM_BASE_A); + /// + /// As PCI enumeration has not been done, set PCH_LAN_MBARB per the platform policy + /// + MmioWrite32 (PciD25F0RegBase + R_PCH_LAN_MEM_BASE_A, PchPlatformPolicyPpi->PlatformData->TempMemBaseAddr); + /// + /// Store the setting of R_PCH_LAN_CMD + /// + CmdReg = MmioRead16 (PciD25F0RegBase + R_PCH_LAN_CMD); + /// + /// Enable memory space decoding in command register + /// + MmioOr16 (PciD25F0RegBase + R_PCH_LAN_CMD, (UINT16) B_PCH_LAN_CMD_MSE); + /// + /// Check if GbE device exists + /// + GbEMemBar = MmioRead32 (PciD25F0RegBase + R_PCH_LAN_MEM_BASE_A) & B_PCH_LAN_MBARA_BA; + + if (GbEMemBar != 0xFFFFFFFF) { + if ((MmioRead16 (GbEMemBar + 0x5B54)) & BIT15) { + ResetRequired = TRUE; + } + } + /// + /// Restore the setting of R_PCH_LAN_CMD + /// + MmioWrite16 (PciD25F0RegBase + R_PCH_LAN_CMD, CmdReg); + /// + /// Restore the value of PCH_LAN_MEM_BASE_A + /// + MmioWrite32 (PciD25F0RegBase + R_PCH_LAN_MEM_BASE_A, TempGbEMemBar); + } + /// + /// Step 1 + /// Set RCBA + 3414h[5] = 1b + /// + MmioOr8 (PchPlatformPolicyPpi->Rcba + R_PCH_RCRB_BUC, (UINT8) B_PCH_RCRB_BUC_LAN_DIS); + } + /// + /// PCH BIOS Spec Rev 0.5.0, Section 10.2.1 & 10.2.2 + /// Step 2 + /// Read back for posted write to take effect + /// + MmioRead8 (PchPlatformPolicyPpi->Rcba + R_PCH_RCRB_BUC); + + if (!ResetRequired) { + return EFI_SUCCESS; + } + + DEBUG ((EFI_D_ERROR, "PchGbeMandatedReset: resetting the board via CF9...\n")); + if ((MmioRead32 (PchPlatformPolicyPpi->Rcba + R_PCH_RCRB_FD2) & B_PCH_RCRB_FD2_MEI1D) == 0) { + if (PchPlatformPolicyPpi->PlatformData->EcPresent) { + PchResetType = GlobalResetWithEc; + } else { + PchResetType = GlobalReset; + } + } else { + PchResetType = PowerCycleReset; + } + + PchResetPpi->Reset (PchResetPpi, PchResetType); + /// + /// Shouldn't reach here + /// + return EFI_SUCCESS; +} + +/** + Internal function performing miscellaneous init needed in early PEI phase + + @param[in] PchPlatformPolicyPpi The PCH Platform Policy PPI instance + + @retval EFI_SUCCESS Succeeds. + @retval EFI_DEVICE_ERROR Device error, aborts abnormally. +**/ +EFI_STATUS +PchMiscInit ( + IN PCH_PLATFORM_POLICY_PPI *PchPlatformPolicyPpi + ) +{ + EFI_STATUS Status; + UINT8 Index; + UINTN PciD31F2RegBase; + UINTN PciD31F5RegBase; + UINTN PciD28F0RegBase; + UINTN PciD31F0RegBase; + UINT16 LpcDeviceId; + PCH_HPET_CONFIG *HpetConfig; + UINT16 Data16; + UINT32 Data32; + UINT32 Data32And; + UINT32 Data32Or; + UINTN RPBase; + BOOLEAN RpSpeedChanged; + UINT32 RootComplexBar; + + const USB_CONTROLLER EhciControllersMap[PchEhciControllerMax] = { + { + PCI_DEVICE_NUMBER_PCH_USB, + PCI_FUNCTION_NUMBER_PCH_EHCI + }, + { + PCI_DEVICE_NUMBER_PCH_USB_EXT, + PCI_FUNCTION_NUMBER_PCH_EHCI2 + } + }; + PCH_SERIES PchSeries; + + PchSeries = GetPchSeries(); + PciD31F0RegBase = MmPciAddress ( + 0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + 0 + ); + PciD31F2RegBase = MmPciAddress ( + 0, + PchPlatformPolicyPpi->BusNumber, + PCI_DEVICE_NUMBER_PCH_SATA, + PCI_FUNCTION_NUMBER_PCH_SATA, + 0 + ); + PciD31F5RegBase = 0; + if (PchSeries == PchH) { + PciD31F5RegBase = MmPciAddress ( + 0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_SATA, + PCI_FUNCTION_NUMBER_PCH_SATA2, + 0 + ); + } + PciD28F0RegBase = MmPciAddress ( + 0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, + PCI_FUNCTION_NUMBER_PCH_PCIE_ROOT_PORT_1, + 0 + ); + HpetConfig = PchPlatformPolicyPpi->HpetConfig; + /// + /// Set B0:D31:F0 + ACh[20] = 0 at early boot + /// + MmioAnd32 (PciD31F0RegBase + R_PCH_LPC_PMIR, (UINT32)~(B_PCH_LPC_PMIR_CF9GR)); + + /// + /// PCH BIOS Spec Rev 0.5.0, Section 8.14 Additional PCI Express* Programming Steps + /// NOTE: Detection of Non-Complaint PCI Express Devices in Gen2 Ports + /// Some non-graphics PCI Express devices do not follow PCI Express Specification and currently report + /// the incorrect Gen capability or link width. This may cause the improper detection of the card + /// by the Intel Gen2 PCI Express port. + /// The following settings may improve the ability of an Intel Gen2 PCI Express port to detect + /// these non-compliant PCI Express devices. + /// If BIOS cannot detect or train the device: Set B0:D28:F0~F7 + 70h [3:0]= 1h + /// Wait 100 ms for link to train up + /// Please note the above setting is "as-is" as Intel cannot verify all non-compliant devices. + /// You need to ensure that the workaround works with devices you are planning to use. + /// + RpSpeedChanged = FALSE; + for (Index = 0; Index < GetPchMaxPciePortNum (); Index++) { + RPBase = MmPciAddress ( + 0, + PchPlatformPolicyPpi->BusNumber, + PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, + Index, + 0 + ); + if (MmioRead16 (RPBase + R_PCH_PCIE_VENDOR_ID) == 0xFFFF) { + continue; + } + + switch (PchPlatformPolicyPpi->PcieConfig->PcieSpeed[Index]) { + case PchPcieGen1: + Data16 = BIT0; + break; + case PchPcieGen2: + case PchPcieAuto: + default: + Data16 = BIT1; + break; + } + if ((MmioRead16 (RPBase + R_PCH_PCIE_LCTL2) & (UINT16) (B_PCH_PCIE_LCTL2_TLS)) != Data16) { + MmioAndThenOr16 (RPBase + R_PCH_PCIE_LCTL2, (UINT16)~(B_PCH_PCIE_LCTL2_TLS), Data16); + RpSpeedChanged = TRUE; + } + } + // + // Merge all delay for change link speed of RPs together to reduce the delay time. + // + if (RpSpeedChanged) { + PchPmTimerStall (100 * 1000); + } + + for (Index = 0; Index < GetPchMaxPciePortNum (); Index++) { + RPBase = MmPciAddress ( + 0, + PchPlatformPolicyPpi->BusNumber, + PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORTS, + Index, + 0 + ); + if (MmioRead16 (RPBase + R_PCH_PCIE_VENDOR_ID) == 0xFFFF) { + continue; + } + /// + /// 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. + /// + MmioAnd32 ((RPBase + 0x338), (UINT32) ~BIT26); + + /// + /// PCH BIOS Spec Rev 0.5.0, Section 8.14 Additional PCI Express* Programming Steps + /// Step 1 + /// Before MRC execution, system BIOS must program the following register. + /// B0:D28:F0 + F4h[6:5] = 0b + /// B0:D28:F0 + F4h[7] = 1b + /// + if (Index == 0) { + MmioAndThenOr8 ((RPBase + 0xF4), (UINT8) ~(BIT5 | BIT6), BIT7); + } + } + + for (Index = 0; Index < GetPchEhciMaxControllerNum (); Index++) { + /// + /// PCH BIOS Spec Rev 0.5.0 Section 7.1.5 Additional PCH DMI Programming Steps + /// Step 3.2 + /// RCBA + Offset 50h[23:20] = 2h and RCBA + Offset 50h[17] = 1b (Done at + /// PchDmiTcVcProgPoll() on PchDmiPeim.c) + /// and also ensure that D29/D26:F0:88h [2] = 0b + /// + Data32 = MmioRead32 ( + (UINTN) MmPciAddress (0, + PchPlatformPolicyPpi->BusNumber, + EhciControllersMap[Index].Device, + EhciControllersMap[Index].Function, + 0x88) + ); + Data32 &= (UINT32) (~BIT2); + MmioWrite32 ( + MmPciAddress (0, + PchPlatformPolicyPpi->BusNumber, + EhciControllersMap[Index].Device, + EhciControllersMap[Index].Function, + 0x88), + Data32 + ); + } + /// + /// Initial and enable HPET High Precision Timer memory address for basic usage + /// + if (HpetConfig->Enable == PCH_DEVICE_ENABLE) { + MmioAndThenOr32 ( + (UINTN) (PchPlatformPolicyPpi->Rcba + R_PCH_RCRB_HPTC), + (UINT32)~B_PCH_RCRB_HPTC_AS, + (UINT32) (((HpetConfig->Base >> N_PCH_HPET_ADDR_ASEL) & B_PCH_RCRB_HPTC_AS) | B_PCH_RCRB_HPTC_AE) + ); + /// + /// Read back for posted write to take effect + /// + MmioRead32 (PchPlatformPolicyPpi->Rcba + R_PCH_RCRB_HPTC); + /// + /// Set HPET Timer enable to start counter spinning + /// + MmioOr32 (HpetConfig->Base + 0x10, 0x1); + } + + if (PchPlatformPolicyPpi->Port80Route == PchReservedPageToLpc) { + MmioAnd32 (PchPlatformPolicyPpi->Rcba + R_PCH_RCRB_GCS, (UINT32) (~B_PCH_RCRB_GCS_RPR)); + } else { + MmioOr32 (PchPlatformPolicyPpi->Rcba + R_PCH_RCRB_GCS, (UINT32) B_PCH_RCRB_GCS_RPR); + } + /// + /// Read back for posted write to take effect + /// + MmioRead32 (PchPlatformPolicyPpi->Rcba + R_PCH_RCRB_GCS); + +#ifdef TRAD_FLAG + if (PchSeries == PchH) { + if (PchPlatformPolicyPpi->SataConfig->SataMode == PchSataModeIde) { + /// + /// PCH BIOS Spec Rev 0.5.0 section 14.1.7 Additional Programming Requirements during + /// Step 13 + /// When SATA in IDE mode + /// a. Program D31:F2:34h [7:0] to 70h + /// + Data32And = (UINT32) ~(0xFF); + Data32Or = (UINT32) (0x70); + MmioAndThenOr32 ( + (UINTN) (PciD31F2RegBase + 0x34), + Data32And, + Data32Or + ); + /// + /// b. Program D31:F2:70h [15:8] to 0h + /// + Data32And = (UINT32) ~(0xFF00); + MmioAnd32 ( + (UINTN) (PciD31F2RegBase + 0x70), + Data32And + ); + /// + /// IDE mode, SATA Port 0 - Port 3 are for D31:F2, Port4 and Port 5 are for D31:F5 + /// + MmioAnd8 ( + PciD31F2RegBase + R_PCH_SATA_MAP, + (UINT8)~(B_PCH_SATA_MAP_SMS_MASK | B_PCH_SATA_PORT_TO_CONTROLLER_CFG) + ); + /// + /// PCH BIOS Spec Rev 0.5.0 section 14.1.7 Additional Programming Requirements during + /// SATA Initialization + /// Step 1 + /// If D28:F0:410h[5:4] = 11b, System BIOS must disable D31:F5 by setting SAD2 bit, + /// RCBA + 3418[25] + /// + if ((MmioRead8 (PciD28F0RegBase + 0x410) & (UINT8) (BIT5 | BIT4)) == (UINT8) (BIT5 | BIT4)) { + MmioOr32 (PchPlatformPolicyPpi->Rcba + R_PCH_RCRB_FUNC_DIS, (UINT32) B_PCH_RCRB_FUNC_DIS_SATA2); + /// + /// Reads back for posted write to take effect + /// + MmioRead32 (PchPlatformPolicyPpi->Rcba + R_PCH_RCRB_FUNC_DIS); + } else { + /// + /// Enable the SATA port4 and port5. + /// Step 1.a + /// If D28:F0:410h[4] = 1b, System BIOS should not enable the SATA port4 + /// Step 1.b + /// If D28:F0:410h[5] = 1b, System BIOS should not enable the SATA port5 + /// + if ((MmioRead8 (PciD28F0RegBase + 0x410) & BIT4) == 0) { + MmioOr8 ( + PciD31F5RegBase + R_PCH_SATA_PCS, + (UINT8) B_PCH_SATA2_PCS_PORT4_EN + ); + } + if ((MmioRead8 (PciD28F0RegBase + 0x410) & BIT5) == 0) { + MmioOr8 ( + PciD31F5RegBase + R_PCH_SATA_PCS, + (UINT8) B_PCH_SATA2_PCS_PORT5_EN + ); + } + } + } else { + MmioOr32 (PchPlatformPolicyPpi->Rcba + R_PCH_RCRB_FUNC_DIS, (UINT32) B_PCH_RCRB_FUNC_DIS_SATA2); + /// + /// Reads back for posted write to take effect + /// + MmioRead32 (PchPlatformPolicyPpi->Rcba + R_PCH_RCRB_FUNC_DIS); + } + } +#endif //TRAD_FLAG +#ifdef ULT_FLAG + if (PchSeries == PchLp) { + if (PchPlatformPolicyPpi->SataConfig->SataMode == PchSataModeLoopbackTest) { + /// + /// Set D31:F2:90h[7:6] to 00b + /// + MmioAnd8 ( + PciD31F2RegBase + R_PCH_SATA_MAP, + (UINT8)~(B_PCH_SATA_MAP_SMS_MASK) + ); + /// + /// Set D31:F2 + SIR Index 00h[15] = 1b + /// + MmioWrite8 (PciD31F2RegBase + R_PCH_SATA_SIRI, 0x00); + Data32And = 0xFFFF7FFF; + Data32Or = 0x00008000; + MmioAndThenOr32 ( + (UINTN) (PciD31F2RegBase + R_PCH_SATA_STRD), + Data32And, + Data32Or + ); + } + } +#endif // ULT_FLAG + if (PchPlatformPolicyPpi->SataConfig->SataMode == PchSataModeRaid) { + LpcDeviceId = MmioRead16 (PciD31F0RegBase + R_PCH_LPC_DEVICE_ID); + if (IS_PCH_LPT_RAID_AVAILABLE (LpcDeviceId)) { + MmioAndThenOr8 ( + PciD31F2RegBase + R_PCH_SATA_MAP, + (UINT8) (~B_PCH_SATA_MAP_SMS_MASK), + (UINT8) (V_PCH_SATA_MAP_SMS_RAID) + ); + } else { + DEBUG ((EFI_D_INFO, "PCH Device ID : 0x%x\n", LpcDeviceId)); + DEBUG ((EFI_D_ERROR, "This SKU doesn't support RAID feature. Set to AHCI mode.\n")); + } + } + + // + // The following three ICC isCLK settings must be done for S3/S4/S5 before ICC HW is locked. + // For S3 path, the ICC HW is locked just after DID message. So program those in PEI. + // + if (PchSeries == PchLp) { + RootComplexBar = PchPlatformPolicyPpi->Rcba; + /// + /// Set the isCLK PLL lock speed in the ICC HW. + /// Set bits 13:12 and bits 10:8, clear bit 11, fast lock time = 11us + /// NOTE: Lock occurs after EOP message sent, and this write will fail until core well reset. On write failure + /// expectation is that the register was previously programmed and values are maintained in HW registers. + /// + Status = ProgramIobp(RootComplexBar, 0xED00015C, (UINT32)~(BIT11), (BIT13|BIT12|BIT10|BIT9|BIT8)); + + /// + /// Set the isCLK freeze timer in the ICC HW. + /// Set bits 23:22, Clk timer = 1 clk + /// NOTE: Lock occurs after EOP message sent, and this write will fail until core well reset. On write failure + /// expectation is that the register was previously programmed and values are maintained in HW registers. + /// + Status = ProgramIobp(RootComplexBar, 0xED000118, (UINT32)0xFFFFFFFF, (UINT32) (BIT23|BIT22)); + + /// + /// Set bit 21 and 18, expand Vcont Window + /// + Status = ProgramIobp(RootComplexBar, 0xED000120, (UINT32)0xFFFFFFFF, (UINT32) (BIT21|BIT18)); + } + + return EFI_SUCCESS; +} + +/** + Perform Thermal Management Support initialization + + @param[in] PchPlatformPolicyPpi The PCH Platform Policy PPI instance + + @retval EFI_SUCCESS Succeeds. + @retval EFI_DEVICE_ERROR Device error, aborts abnormally. +**/ +EFI_STATUS +PchThermalInit ( + IN PCH_PLATFORM_POLICY_PPI *PchPlatformPolicyPpi + ) +{ + UINTN PciD31F6RegBase; + UINTN PciD0F0RegBase; + UINT32 ThermalBaseB; + PCH_MEMORY_THROTTLING *MemoryThrottling; + UINT32 Data32And; + UINT32 Data32Or; + UINT32 Softstrap15; + + PciD31F6RegBase = MmPciAddress ( + 0, + PchPlatformPolicyPpi->BusNumber, + PCI_DEVICE_NUMBER_PCH_THERMAL, + PCI_FUNCTION_NUMBER_PCH_THERMAL, + 0 + ); + PciD0F0RegBase = MmPciAddress (0, 0, 0, 0, 0); + + MemoryThrottling = PchPlatformPolicyPpi->ThermalMgmt->MemoryThrottling; + ThermalBaseB = PchPlatformPolicyPpi->PlatformData->TempMemBaseAddr; + + /// + /// D31:F6:Reg 44h[31:0], with a 64-bit BAR for BIOS. + /// Enable the BAR by setting the SPTYPEN bit, D31:F6:Reg 40h[0]. + /// + MmioWrite32 (PciD31F6RegBase + R_PCH_THERMAL_TBARB, ThermalBaseB); + MmioWrite32 (PciD31F6RegBase + R_PCH_THERMAL_TBARBH, 0); + MmioOr32 (PciD31F6RegBase + R_PCH_THERMAL_TBARB, (UINT32) B_PCH_THERMAL_SPTYPEN); + + /// + /// PCH BIOS Spec Rev 0.5.0, 17.2 Thermal Subsystem Device Initialization + /// The System BIOS must perform the following steps to initialize the PCH thermal subsystem device, D31:F6. + /// Step 1 + /// Enable Thermal Subsystem device by making sure FD.TTD is cleared. + /// The default value of FD.TTD is cleared. + /// + /// Step 2 + /// Optionally program Device 31 Interrupt Pin/Route registers + /// Left this to platform code + /// + /// Step 3 + /// Go through general PCI enumeration and assign standard PCI resource, including TBARB, TBARBH, etc. + /// Left this to platform code + /// + /// Step 4 + /// Initialize relevant Thermal subsystems for the desired features. + /// + + /// + /// PCH BIOS Spec Rev 0.5.0, Section 17.3.1 Initializing Lynx Point Thermal Sensors + /// Step 1 + /// Set various trip points based on the particular usage model. Note that Cat Trip must always be programmed. + /// - CTT must be programmed for Cat Trip, CTT must never be changed while the TS enable is set. + /// This rule prevents a spurious trip from occurring and causing a system shutdown. + /// TSC must then be written to 0x81 to enable the power down and lock the register. + /// TSC programming is done in PchPm.c ThermalLockDown() + /// - TAHV and TAHL may be programmed if the BIOS or driver wish to force a SW notification for PCH temperature + /// - If TAHL/TAHV programmed much later in the flow when a driver is loaded, this means that the TS had been + /// enabled long before this, the thermal sensor must be disabled when TAHL/TAHV are programmed, and then + /// re-enabled. + /// - TSPIEN or TSGPEN may be programmed to cause either an interrupt or SMI/SCI. + /// - It is recommended that TAHV, TALV, TSPIEN and TSGPEN be left at their default value, unless there is a + /// specific usage that requires these to be programmed. + /// + if (GetPchSeries() == PchLp) { + MmioWrite16 (ThermalBaseB + R_PCH_TBARB_CTT, V_PCH_TBARB_CTT_LPTLP); + } else { + MmioWrite16 (ThermalBaseB + R_PCH_TBARB_CTT, V_PCH_TBARB_CTT_LPTH); + } + + /// + /// Step 2 + /// Clear trip status from TSS/TAS. BIOS should write 0xFF to clear any bit that was inadvertently set while programming + /// the TS. This write of 0xFF should be done before continuing to the next steps. + /// + MmioWrite8 (ThermalBaseB + R_PCH_TBARB_TSS, 0xFF); + MmioWrite8 (ThermalBaseB + R_PCH_TBARB_TAS, 0xFF); + + /// + /// Step 3 + /// Enable the desired thermal trip alert methods, i.e. GPE (TSGPEN), SMI (TSMIC) or Interrupt (TSPIEN). + /// Only one of the methods should be enabled and the method will be depending on the platform implementation. + /// - TSGPEN: BIOS should leave this as default 00h, unless it is required to enable GPE. + /// - TSMIC: BIOS should leave TSMIC[7:0] as default 00h, unless the SMI handler is loaded + /// and it's safe to enable SMI for these events. + /// - TSPIEN: BIOS should leave this as default 0x00, so that a driver can enable later + /// + MmioWrite8 (ThermalBaseB + R_PCH_TBARB_TSGPEN, 0x00); + MmioWrite8 (ThermalBaseB + R_PCH_TBARB_TSPIEN, 0x00); + + /// + /// If PCHSTRP15[14] is 1, PMC will set up SML1 for temp reporting to an EC + /// + MmioAndThenOr32 ( + PCH_RCRB_BASE + R_PCH_SPI_FDOC, + (UINT32) (~(B_PCH_SPI_FDOC_FDSS_MASK | B_PCH_SPI_FDOC_FDSI_MASK)), + (UINT32) (V_PCH_SPI_FDOC_FDSS_PCHS | R_PCH_SPI_STRP15) + ); + + Softstrap15 = MmioRead32 (PCH_RCRB_BASE + R_PCH_SPI_FDOD); + + if ((Softstrap15 & R_PCH_SPI_STRP15_SML1_THRMSEL) != 0) { + /// + /// Step 4 + /// If thermal reporting to an EC over SMBus is supported, then write 0x01 to TSREL, else leave at default. + /// + MmioWrite8 (ThermalBaseB + R_PCH_TBARB_TSREL, 0x01); + } + + /// + /// Step 5 + /// If the PCH_Hot pin reporting is supported, then write the temperature value and set the enable in PHL. + /// Done in PchPm.c ThermalLockDown() + /// + /// Step 6 + /// If thermal throttling is supported, then set the desired values in TL. + /// Done in PchPm.c ThermalLockDown() + /// + /// Step 7 + /// Enable thermal sensor by programming TSEL register to 0x01. + /// Done in PchPm.c ThermalLockDown() + /// + /// Step 8 + /// Lock down the thermal reporting to prevent outside agents from changing the values + /// Done in PchPm.c ThermalLockDown() + /// + + /// + /// Clear BAR and disable access + /// + MmioAnd32 ((UINTN) (PciD31F6RegBase + R_PCH_THERMAL_TBARB), (UINT32)~B_PCH_THERMAL_SPTYPEN); + MmioWrite32 ((UINTN) (PciD31F6RegBase + R_PCH_THERMAL_TBARB), 0); + + /// + /// PCH BIOS Spec Rev 0.5.0, Section 17.5.1 Memory Bandwidth Throttling + /// If the platform supports an external memory thermal sensor (TS-on-DIMM or TS-on-Board), + /// system BIOS needs to program the registers bellow. + /// Here are the settings used in the Intel CRB: + /// 1. Program RCBA + 33D4h [31:28] = 1100b, for GPIO_D and GPIO_C to PM_SYNC Enable + /// 2. Program RCBA + 33D4h [15:12] = 1100b, for GPIO_D and GPIO_C C0 Transmit Enable. + /// 3. Program RCBA + 33C8h [11:8] = 0100b to select GPIO 4 to GPIO_C (EXTTS#0) and + /// GPIO 5 to GPIO_D (EXTTS#1) + /// GPIOBASE + 00h [5:4] = 11b (Done in platform code) + /// + if (MemoryThrottling->Enable == PCH_DEVICE_ENABLE) { + Data32And = 0x0FFF0FFF; + Data32Or = 0; + if (MemoryThrottling->TsGpioPinSetting[TsGpioC].PmsyncEnable == PCH_DEVICE_ENABLE) { + Data32Or |= BIT30; + } + + if (MemoryThrottling->TsGpioPinSetting[TsGpioD].PmsyncEnable == PCH_DEVICE_ENABLE) { + Data32Or |= BIT31; + } + + if (MemoryThrottling->TsGpioPinSetting[TsGpioC].C0TransmitEnable == PCH_DEVICE_ENABLE) { + Data32Or |= BIT14; + } + + if (MemoryThrottling->TsGpioPinSetting[TsGpioD].C0TransmitEnable == PCH_DEVICE_ENABLE) { + Data32Or |= BIT15; + } + + MmioAndThenOr32 ( + PchPlatformPolicyPpi->Rcba + R_PCH_RCRB_CIR33D4, + Data32And, + Data32Or + ); + + Data32And = 0xFFFFF0FF; + Data32Or = 0; + if (MemoryThrottling->TsGpioPinSetting[TsGpioC].PinSelection == 1) { + Data32Or |= B_PCH_RCRB_PMSYNC_GPIO_C_SEL; + } + + if (MemoryThrottling->TsGpioPinSetting[TsGpioD].PinSelection == 1) { + Data32Or |= B_PCH_RCRB_PMSYNC_GPIO_D_SEL; + } + + MmioAndThenOr32 ( + PchPlatformPolicyPpi->Rcba + R_PCH_RCRB_PMSYNC, + Data32And, + Data32Or + ); + } + + return EFI_SUCCESS; +} + +/** + Initialize IOAPIC according to IoApicConfig policy of the PCH + Platform Policy PPI + + @param[in] PchPlatformPolicyPpi The PCH Platform Policy PPI instance + + @retval EFI_SUCCESS Succeeds. + @retval EFI_DEVICE_ERROR Device error, aborts abnormally. +**/ +EFI_STATUS +PchIoApicInit ( + IN PCH_PLATFORM_POLICY_PPI *PchPlatformPolicyPpi + ) +{ + UINT32 RootComplexBar; + PCH_IOAPIC_CONFIG *IoApicConfig; + UINT32 IoApicAddress; + UINT32 IoApicId; + + RootComplexBar = PchPlatformPolicyPpi->Rcba; + IoApicConfig = PchPlatformPolicyPpi->IoApicConfig; + + if (IoApicConfig->ApicRangeSelect != MmioRead8 (RootComplexBar + R_PCH_RCRB_OIC)) { + /// + /// Program APIC Range Select bits that define address bits 19:12 for the IOxAPIC range. + /// This value must not be changed unless the IOxAPIC Enable bit is cleared. + /// + MmioAnd16 ((UINTN) (RootComplexBar + R_PCH_RCRB_OIC), (UINT16)~(B_PCH_RCRB_OIC_AEN)); + /// + /// Program APIC Range Select bits at RCBA + 31FEh[7:0] + /// + MmioAndThenOr16 ( + RootComplexBar + R_PCH_RCRB_OIC, + (UINT16)~(V_PCH_RCRB_OIC_ASEL), + (UINT16) IoApicConfig->ApicRangeSelect + ); + } + /// + /// PCH BIOS Spec Rev 0.5.0, Section 6.6.2.1 + /// 1. Enable the IOAPIC by setting the APIC Enable bit, RCBA + offset 31FFh, Bit[0] if the + /// system needs to use the IOxAPIC. The APIC Enable bits needs read back after the bit is written. + /// + MmioOr16 ((UINTN) (RootComplexBar + R_PCH_RCRB_OIC), (UINT16) B_PCH_RCRB_OIC_AEN); + /// + /// Reads back for posted write to take effect + /// + MmioRead16 (RootComplexBar + R_PCH_RCRB_OIC); + + /// + /// Get current IO APIC ID + /// + IoApicAddress = (UINT32) (MmioRead8 (RootComplexBar + R_PCH_RCRB_OIC) << N_PCH_IO_APIC_ASEL); + MmioWrite8 ((UINTN) (R_PCH_IO_APIC_INDEX | IoApicAddress), 0); + IoApicId = MmioRead32 ((UINTN) (R_PCH_IO_APIC_DATA | IoApicAddress)) >> 24; + /// + /// IO APIC ID is at APIC Identification Register [27:24] + /// + if ((IoApicConfig->IoApicId != IoApicId) && (IoApicConfig->IoApicId < 0x10)) { + /// + /// Program APIC ID + /// + MmioWrite8 ((UINTN) (R_PCH_IO_APIC_INDEX | IoApicAddress), 0); + MmioWrite32 ((UINTN) (R_PCH_IO_APIC_DATA | IoApicAddress), (UINT32) (IoApicConfig->IoApicId << 24)); + } + + if (GetPchSeries() == PchLp) { + if (IoApicConfig->IoApicEntry24_39 == PCH_DEVICE_DISABLE) { + /// + /// Program IOAPIC Entry 24-39 Disable bit at RCBA + 31FEh[11] + /// + MmioOr16 (RootComplexBar + R_PCH_RCRB_OIC, (UINT16) B_PCH_RCRB_OIC_OA24_39_D); + } + } + + return EFI_SUCCESS; +} + +/** + This function performs basic initialization for PCH in PEI phase. + If any of the base address arguments is zero, this function will disable the corresponding + decoding, otherwise this function will enable the decoding. + This function locks down the PMBase. + + @param[in] PeiServices General purpose services available to every PEIM. + @param[in] NotifyDescriptor The notification structure this PEIM registered on install. + @param[in] Ppi The memory discovered PPI. Not used. + + @retval EFI_SUCCESS Succeeds. + @retval EFI_DEVICE_ERROR Device error, aborts abnormally. +**/ +EFI_STATUS +EFIAPI +PchInitialize ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ) +{ + EFI_STATUS Status; + UINT8 Data8Or; + UINT8 Data8And; + PCH_PLATFORM_POLICY_PPI *PchPlatformPolicyPpi; +#ifdef EFI_DEBUG + UINT8 Index; +#endif +#ifdef USB_PRECONDITION_ENABLE_FLAG + EFI_BOOT_MODE BootMode; +#endif // USB_PRECONDITION_ENABLE_FLAG + UINTN AcpiBarAddress; + UINTN GpioBarAddress; + + DEBUG ((EFI_D_INFO, "PchInitialize() - Start\n")); + + /// + /// Get platform policy settings through the PchPlatformPolicy PPI + /// + Status = (**PeiServices).LocatePpi ( + PeiServices, + &gPchPlatformPolicyPpiGuid, + 0, + NULL, + (VOID **)&PchPlatformPolicyPpi + ); + ASSERT_EFI_ERROR (Status); +#ifdef EFI_DEBUG + DEBUG ((EFI_D_INFO, "\n------------------------ PchPlatformPolicyPpi Dump Begin -----------------\n")); + DEBUG ((EFI_D_INFO, "Revision : 0x%x\n", PchPlatformPolicyPpi->Revision)); + DEBUG ((EFI_D_INFO, "BusNumber : 0x%x\n", PchPlatformPolicyPpi->BusNumber)); + DEBUG ((EFI_D_INFO, "Rcba : 0x%x\n", PchPlatformPolicyPpi->Rcba)); + DEBUG ((EFI_D_INFO, "PmBase : 0x%x\n", PchPlatformPolicyPpi->PmBase)); + DEBUG ((EFI_D_INFO, "GpioBase : 0x%x\n", PchPlatformPolicyPpi->GpioBase)); + + DEBUG ((EFI_D_INFO, "PCH GBE Configuration --- \n")); + DEBUG ((EFI_D_INFO, " EnableGbe : 0x%x\n", PchPlatformPolicyPpi->GbeConfig->EnableGbe)); + + DEBUG ((EFI_D_INFO, "\n------------------------ PCH THERMAL Configuration -----------------\n")); + DEBUG ((EFI_D_INFO, "PCH MEMORY THERMAL MANAGEMENT --- \n")); + DEBUG ( + (EFI_D_INFO, + "MemoryThrottling->Enable : 0x%x\n", + PchPlatformPolicyPpi->ThermalMgmt->MemoryThrottling->Enable) + ); + DEBUG ( + (EFI_D_INFO, + "MemoryThrottling->TsGpioPinSetting[TsGpioC].PmsyncEnable : 0x%x\n", + PchPlatformPolicyPpi->ThermalMgmt->MemoryThrottling->TsGpioPinSetting[TsGpioC].PmsyncEnable) + ); + DEBUG ( + (EFI_D_INFO, + "MemoryThrottling->TsGpioPinSetting[TsGpioD].PmsyncEnable : 0x%x\n", + PchPlatformPolicyPpi->ThermalMgmt->MemoryThrottling->TsGpioPinSetting[TsGpioD].PmsyncEnable) + ); + DEBUG ( + (EFI_D_INFO, + "MemoryThrottling->TsGpioPinSetting[TsGpioC].C0TransmitEnable : 0x%x\n", + PchPlatformPolicyPpi->ThermalMgmt->MemoryThrottling->TsGpioPinSetting[TsGpioC].C0TransmitEnable) + ); + DEBUG ( + (EFI_D_INFO, + "MemoryThrottling->TsGpioPinSetting[TsGpioD].C0TransmitEnable : 0x%x\n", + PchPlatformPolicyPpi->ThermalMgmt->MemoryThrottling->TsGpioPinSetting[TsGpioD].C0TransmitEnable) + ); + DEBUG ( + (EFI_D_INFO, + "MemoryThrottling->TsGpioPinSetting[TsGpioC].PinSelection : 0x%x\n", + PchPlatformPolicyPpi->ThermalMgmt->MemoryThrottling->TsGpioPinSetting[TsGpioC].PinSelection) + ); + DEBUG ( + (EFI_D_INFO, + "MemoryThrottling->TsGpioPinSetting[TsGpioD].PinSelection : 0x%x\n", + PchPlatformPolicyPpi->ThermalMgmt->MemoryThrottling->TsGpioPinSetting[TsGpioD].PinSelection) + ); + + DEBUG ((EFI_D_INFO, "PCH HPET Configuration --- \n")); + DEBUG ((EFI_D_INFO, " Enable : 0x%x\n", PchPlatformPolicyPpi->HpetConfig->Enable)); + DEBUG ((EFI_D_INFO, " Base : 0x%x\n", PchPlatformPolicyPpi->HpetConfig->Base)); + + DEBUG ((EFI_D_INFO, "PCH RESERVED PAGE ROUTE --- \n")); + if (PchPlatformPolicyPpi->Port80Route == PchReservedPageToLpc) { + DEBUG ((EFI_D_INFO, " Port80Route : PchReservedPageToLpc\n")); + } else if (PchPlatformPolicyPpi->Port80Route == PchReservedPageToPcie) { + DEBUG ((EFI_D_INFO, " Port80Route : PchReservedPageToPciE\n")); + } + + DEBUG ((EFI_D_INFO, "PCH SATA Mode --- \nSataMode : ")); + switch (PchPlatformPolicyPpi->SataConfig->SataMode) { + case PchSataModeIde: + DEBUG ((EFI_D_INFO, "PchSataModeIde")); + break; + case PchSataModeAhci: + DEBUG ((EFI_D_INFO, "PchSataModeAhci")); + break; + case PchSataModeRaid: + DEBUG ((EFI_D_INFO, "PchSataModeRaid")); + break; + case PchSataModeLoopbackTest: + DEBUG ((EFI_D_INFO, "PchSataModeLoopbackTest")); + break; + default: + break; + } + + DEBUG ((EFI_D_INFO, "\nPCH IO APIC Configuration --- \n")); + DEBUG ((EFI_D_INFO, " IoApicId : 0x%x\n", PchPlatformPolicyPpi->IoApicConfig->IoApicId)); + DEBUG ((EFI_D_INFO, " ApicRangeSelect : 0x%x\n", PchPlatformPolicyPpi->IoApicConfig->ApicRangeSelect)); + + DEBUG ((EFI_D_INFO, "PCH PCIE Speed--- \n")); + for (Index = 0; Index < GetPchMaxPciePortNum (); Index++) { + if (PchPlatformPolicyPpi->PcieConfig->PcieSpeed[Index] == PchPcieGen1) { + DEBUG ((EFI_D_INFO, " PCIE Port %x Speed: PchPcieGen1\n", Index)); + } else if (PchPlatformPolicyPpi->PcieConfig->PcieSpeed[Index] == PchPcieGen2) { + DEBUG ((EFI_D_INFO, " PCIE Port %x Speed: PchPcieGen2\n", Index)); + } else if (PchPlatformPolicyPpi->PcieConfig->PcieSpeed[Index] == PchPcieAuto) { + DEBUG ((EFI_D_INFO, " PCIE Port %x Speed: PchPcieAuto\n", Index)); + } + } + + DEBUG ((EFI_D_INFO, "Platform Data Configuration --- \n")); + DEBUG ((EFI_D_INFO, " EcPresent : %x\n", PchPlatformPolicyPpi->PlatformData->EcPresent)); + DEBUG ((EFI_D_INFO, " SmmBwp : %x\n", PchPlatformPolicyPpi->PlatformData->SmmBwp)); + + DEBUG ((EFI_D_INFO, "\n------------------------ PchPlatformPolicyPpi Dump End -----------------\n")); +#endif + /// + /// Set Rcba + /// + ASSERT ((PchPlatformPolicyPpi->Rcba & (UINT32) (~B_PCH_LPC_RCBA_BAR)) == 0); + MmioAndThenOr32 ( + MmPciAddress (0, + PchPlatformPolicyPpi->BusNumber, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_RCBA), + (UINT32) (~B_PCH_LPC_RCBA_BAR), + PchPlatformPolicyPpi->Rcba | B_PCH_LPC_RCBA_EN + ); + + /// + /// Set PM Base + /// + AcpiBarAddress = MmPciAddress (0, + PchPlatformPolicyPpi->BusNumber, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_ACPI_BASE + ); + MmioWrite32 (AcpiBarAddress, PchPlatformPolicyPpi->PmBase); + ASSERT ((MmioRead32 (AcpiBarAddress) & B_PCH_LPC_ACPI_BASE_BAR) == PchPlatformPolicyPpi->PmBase); + if (PchPlatformPolicyPpi->PmBase != 0) { + /// + /// Enable PM Base + /// + MmioOr8 ( + MmPciAddress (0, + PchPlatformPolicyPpi->BusNumber, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_ACPI_CNT), + (UINT8) B_PCH_LPC_ACPI_CNT_ACPI_EN + ); + } else { + /// + /// Disable PM Base + /// + MmioAnd8 ( + MmPciAddress (0, + PchPlatformPolicyPpi->BusNumber, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_ACPI_CNT), + (UINT8) (~B_PCH_LPC_ACPI_CNT_ACPI_EN) + ); + } + /// + /// Lock down the PM Base + /// + MmioOr8 ( + MmPciAddress (0, + PchPlatformPolicyPpi->BusNumber, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_GEN_PMCON_LOCK), + (UINT8) (B_PCH_LPC_GEN_PMCON_LOCK_ABASE_LK) + ); + + /// + /// Set GPIO Base + /// + GpioBarAddress = MmPciAddress (0, + PchPlatformPolicyPpi->BusNumber, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_GPIO_BASE + ); + MmioWrite32 (GpioBarAddress, PchPlatformPolicyPpi->GpioBase); + ASSERT ((MmioRead32 (GpioBarAddress) & B_PCH_LPC_GPIO_BASE_BAR) == PchPlatformPolicyPpi->GpioBase); + if (PchPlatformPolicyPpi->GpioBase != 0) { + /// + /// Enable GPIO Base + /// + MmioOr8 ( + MmPciAddress (0, + PchPlatformPolicyPpi->BusNumber, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_GPIO_CNT), + (UINT8) B_PCH_LPC_GPIO_CNT_GPIO_EN + ); + } else { + /// + /// Disable GPIO Base + /// + MmioAnd8 ( + MmPciAddress (0, + PchPlatformPolicyPpi->BusNumber, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_GPIO_CNT), + (UINT8) (~B_PCH_LPC_GPIO_CNT_GPIO_EN) + ); + } + + if (PchPlatformPolicyPpi->PlatformData->SmmBwp == 0) { + /// + /// Clear SMM_BWP bit (D31:F0:RegDCh[5]) + /// + Data8And = (UINT8) ~B_PCH_LPC_BIOS_CNTL_SMM_BWP; + Data8Or = 0x00; + } else { + /// + /// Set SMM_BWP and BLE bit (D31:F0:RegDCh[5][1]) + /// + Data8And = 0xFF; + Data8Or = (UINT8) (B_PCH_LPC_BIOS_CNTL_SMM_BWP + B_PCH_LPC_BIOS_CNTL_BLE); + } + + MmioAndThenOr8 ( + MmPciAddress (0, + PchPlatformPolicyPpi->BusNumber, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_BIOS_CNTL), + Data8And, + Data8Or + ); + + Status = PchSataInit (PeiServices, PchPlatformPolicyPpi); + ASSERT_EFI_ERROR (Status); + + Status = PchDmiMiscProg (PeiServices, PchPlatformPolicyPpi); + ASSERT_EFI_ERROR (Status); + + Status = PchGbeMandatedReset (PeiServices, PchPlatformPolicyPpi); + ASSERT_EFI_ERROR (Status); + + Status = PchMiscInit (PchPlatformPolicyPpi); + ASSERT_EFI_ERROR (Status); + Status = PchThermalInit (PchPlatformPolicyPpi); + ASSERT_EFI_ERROR (Status); + Status = PchIoApicInit (PchPlatformPolicyPpi); + ASSERT_EFI_ERROR (Status); + +#ifdef USB_PRECONDITION_ENABLE_FLAG + if (PchPlatformPolicyPpi->Revision > PCH_PLATFORM_POLICY_PPI_REVISION_1) { + /// + /// If it is in S3 boot path or recovery mode, do nothing + /// + Status = (*PeiServices)->GetBootMode (PeiServices, &BootMode); + if (!EFI_ERROR (Status)) { + if ((BootMode != BOOT_ON_S3_RESUME) && (BootMode != BOOT_IN_RECOVERY_MODE)) { + if (PchPlatformPolicyPpi->UsbConfig->UsbPrecondition) { + + /// + /// Initialize PCH USB when USB_PRECONDITION feature is enabled by USB_CONFIG policy + /// Initialize PCH EHCI and XHCI by the same MMIO resource one by one + /// + Status = PchStartUsbInit ( + PchPlatformPolicyPpi->UsbConfig, + PchPlatformPolicyPpi->PlatformData->TempMemBaseAddr, + PchPlatformPolicyPpi->PlatformData->TempMemBaseAddr, + PchPlatformPolicyPpi->Revision + ); + ASSERT_EFI_ERROR (Status); + } + } + } + } +#endif // USB_PRECONDITION_ENABLE_FLAG + DEBUG ((EFI_D_INFO, "PchInitialize() - End\n")); + + /// + /// Install the PCH PEI Init Done PPI + /// + Status = (**PeiServices).InstallPpi (PeiServices, &mPpiPchPeiInitDone); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +/** + Internal function performing miscellaneous init needed in very early PEI phase + + @param[in] RootComplexBar RootComplexBar address of this PCH device + + @retval None +**/ +VOID +PchMiscEarlyInit ( + IN UINT32 RootComplexBar + ) +{ + UINTN PciD31F0RegBase; + UINT8 Nmi; + UINT8 Data8; + UINT32 Data32Or; + + DEBUG ((EFI_D_INFO, "PchMiscEarlyInit() - Start\n")); + /// + /// PCH BIOS Spec Rev 0.5.0, Section 7.1.3 PCH Display Port Enable + /// Step 1 + /// Set RCBA + 3424h = 0010h + /// + MmioWrite16 ((UINTN) (RootComplexBar + R_PCH_RCRB_DISPBDF), (UINT16) 0x10); + + /// + /// Step 2 + /// Set RCBA + 3428h[0] = 1b + /// + Data32Or = B_PCH_RCRB_FD2_DBDFEN; + MmioOr32 ((UINTN) (RootComplexBar + R_PCH_RCRB_FD2), Data32Or); + + /// + /// PCH BIOS Spec Rev 0.5.0, Section 19.3 Power Failure Considerations + /// RTC_PWR_STS bit, GEN_PMCON_3 (D31:F0:A4h[2]) + /// When the RTC_PWR_STS bit is set, it indicates that the RTCRST# signal went low. + /// Software should clear this bit. For example, changing the RTC battery sets this bit. + /// System BIOS should reset CMOS to default values if the RTC_PWR_STS bit is set. + /// The System BIOS should execute the sequence below if the RTC_PWR_STS bit is set + /// before memory initialization. This will ensure that the RTC state machine has been + /// initialized. + /// 1. If the RTC_PWR_STS bit is set which indicates a new coin-cell battery insertion or a + /// battery failure, steps 2 through 5 should be executed. + /// 2. Set RTC Register 0Ah[6:4] to 110b or 111b + /// 3. Set RTC Register 0Bh[7]. + /// 4. Set RTC Register 0Ah[6:4] to 010b + /// 5. Clear RTC Register 0Bh[7]. + /// + PciD31F0RegBase = MmPciAddress ( + 0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + 0 + ); + + if ((MmioRead16 (PciD31F0RegBase + R_PCH_LPC_GEN_PMCON_3) & + (UINT16) B_PCH_LPC_GEN_PMCON_RTC_PWR_STS) != 0) { + /// + /// Enable Alternate Access Mode + /// Note: The RTC Index field (including the NMI mask at bit7) is write-only + /// for normal operation and can only be read in Alt Access Mode. + /// + PchAlternateAccessMode (RootComplexBar, TRUE); + /// + /// Read NMI Enable bit + /// + Nmi = IoRead8 (R_PCH_NMI_EN) & (UINT8) B_PCH_NMI_EN_NMI_EN; + /// + /// Disable Alternate Access Mode + /// + PchAlternateAccessMode (RootComplexBar, FALSE); + /// + /// 2. Set RTC Register 0Ah[6:4] to 110b or 111b + /// + IoWrite8 (R_PCH_RTC_INDEX, (UINT8) (R_PCH_RTC_REGA | Nmi)); + Data8 = IoRead8 (R_PCH_RTC_TARGET) & (UINT8) ~(BIT6 | BIT5 | BIT4); + Data8 |= (UINT8) (BIT6 | BIT5); + IoWrite8 (R_PCH_RTC_TARGET, Data8); + /// + /// 3. Set RTC Register 0Bh[7]. + /// + IoWrite8 (R_PCH_RTC_INDEX, (UINT8) (R_PCH_RTC_REGB | Nmi)); + IoOr8 (R_PCH_RTC_TARGET, (UINT8) B_PCH_RTC_REGB_SET); + /// + /// 4. Set RTC Register 0Ah[6:4] to 010b + /// + IoWrite8 (R_PCH_RTC_INDEX, (UINT8) (R_PCH_RTC_REGA | Nmi)); + Data8 = IoRead8 (R_PCH_RTC_TARGET) & (UINT8) ~(BIT6 | BIT5 | BIT4); + Data8 |= (UINT8) (BIT5); + IoWrite8 (R_PCH_RTC_TARGET, Data8); + /// + /// 5. Clear RTC Register 0Bh[7]. + /// + IoWrite8 (R_PCH_RTC_INDEX, (UINT8) (R_PCH_RTC_REGB | Nmi)); + IoAnd8 (R_PCH_RTC_TARGET, (UINT8) ~B_PCH_RTC_REGB_SET); + } + /// + /// PCH BIOS Spec Rev 0.5.0, Section 19.1 Handling Status Registers + /// System BIOS must set 1b to clear the following registers during power-on + /// and resuming from Sx sleep state. + /// - RCBA + Offset 3310h[0] = 1b + /// Done in ConfigureMiscItems () + /// - RCBA + Offset 3310h[4] = 1b, needs to be done as early as possible during PEI + /// - RCBA + Offset 3310h[5] = 1b + /// Done in ConfigureMiscItems () + /// + MmioWrite32 ( + (UINTN) (RootComplexBar + R_PCH_RCRB_PRSTS), + (UINT32) (B_PCH_RCRB_PRSTS_FIELD_1) + ); + + DEBUG ((EFI_D_INFO, "PchMiscEarlyInit() - End\n")); + + return; +} + +/// +/// Entry point +/// + +/** + Installs the PCH PEI Init PPI + Performing Pch early init after PchPlatfromPolicy PPI produced + + @param[in] FfsHeader Not used. + @param[in] PeiServices General purpose services available to every PEIM. + + @retval EFI_SUCCESS The function completes successfully + @retval EFI_OUT_OF_RESOURCES Insufficient resources to create database +**/ +EFI_STATUS +EFIAPI +InstallPchInitPpi ( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_PEI_SERVICES **PeiServices + ) +{ + EFI_STATUS Status; + UINT32 RootComplexBar; + EFI_PEI_PPI_DESCRIPTOR *PchDmiTcVcMapPpiDesc; + PCH_DMI_TC_VC_PPI *PchDmiTcVcMapPpi; + + DEBUG ((EFI_D_INFO, "InstallPchInitPpi() - Start\n")); + + /// + /// Check if Rcba has been set + /// + RootComplexBar = PCH_RCRB_BASE; + DEBUG ((EFI_D_INFO, "Rcba needs to be programmed before here\n")); + ASSERT ((RootComplexBar & (UINT32) (~B_PCH_LPC_RCBA_BAR)) == 0); + /// + /// Perform miscellaneous init needed in very early PEI phase + /// + PchMiscEarlyInit (RootComplexBar); + + /// + /// Install the DMI TC VC PPI + /// Allocate descriptor and PPI structures. Since these are dynamically updated + /// + PchDmiTcVcMapPpiDesc = (EFI_PEI_PPI_DESCRIPTOR *) AllocateZeroPool (sizeof (EFI_PEI_PPI_DESCRIPTOR)); + if (PchDmiTcVcMapPpiDesc == NULL) { + DEBUG ((EFI_D_ERROR, "Failed to allocate memory for PchDmiTcVcMapPpiDesc! \n")); + return EFI_OUT_OF_RESOURCES; + } + + PchDmiTcVcMapPpi = (PCH_DMI_TC_VC_PPI *) AllocateZeroPool (sizeof (PCH_DMI_TC_VC_PPI)); + if (PchDmiTcVcMapPpi == NULL) { + DEBUG ((EFI_D_ERROR, "Failed to allocate memory for PchDmiTcVcMapPpi! \n")); + return EFI_OUT_OF_RESOURCES; + } + + CopyMem (PchDmiTcVcMapPpi, &mPchDmiTcVcMap, sizeof (PCH_DMI_TC_VC_PPI)); + + PchDmiTcVcMapPpiDesc->Flags = EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST; + PchDmiTcVcMapPpiDesc->Guid = &gPchDmiTcVcMapPpiGuid; + PchDmiTcVcMapPpiDesc->Ppi = PchDmiTcVcMapPpi; + Status = (**PeiServices).InstallPpi (PeiServices, PchDmiTcVcMapPpiDesc); + ASSERT_EFI_ERROR (Status); + + /// + /// Install the PCH PEI Init PPI + /// + Status = (**PeiServices).InstallPpi (PeiServices, &mPpiListVariable); + ASSERT_EFI_ERROR (Status); + + /// + /// Performing Pch early init after PchPlatfromPolicy PPI produced + /// + Status = (**PeiServices).NotifyPpi (PeiServices, &mNotifyList); + ASSERT_EFI_ERROR (Status); + + Status = (**PeiServices).NotifyPpi (PeiServices, &mPchS3ResumeNotifyDesc); + ASSERT_EFI_ERROR (Status); + + DEBUG ((EFI_D_INFO, "InstallPchInitPpi() - End\n")); + + return Status; +} + +/** + This function trigger SMI through Iotrap to perform PCH register save and restore in SMI + + @param[in] PeiServices - Pointer to PEI Services Table. + @param[in] NotifyDesc - Pointer to the descriptor for the Notification event that + caused this function to execute. + @param[in] Ppi - Pointer to the PPI data associated with this function. + + @retval EFI_STATUS - Always return EFI_SUCCESS +**/ +EFI_STATUS +PchS3ResumeAtEndOfPei ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc, + IN VOID *Ppi + ) +{ + EFI_STATUS Status; + EFI_BOOT_MODE BootMode; + PCH_LATE_INIT_SMM_VARIABLE SaveRestoreData; + UINTN VariableSize; + PEI_READ_ONLY_VARIABLE_PPI *VariableServices; + + Status = PeiServicesGetBootMode (&BootMode); + DEBUG ((EFI_D_INFO, "[PCH] BootMode = %X\n", BootMode)); + + if (BootMode != BOOT_ON_S3_RESUME) { + return EFI_SUCCESS; + } + /// + /// Locate Variable Ppi + /// + Status = (*PeiServices)->LocatePpi (PeiServices, &gPeiReadOnlyVariablePpiGuid, 0, NULL, &VariableServices); + ASSERT_EFI_ERROR (Status); + + VariableSize = sizeof (PCH_LATE_INIT_SMM_VARIABLE); + Status = VariableServices->PeiGetVariable ( + PeiServices, + PCH_INIT_PEI_VARIABLE_NAME, + &gPchInitPeiVariableGuid, + NULL, + &VariableSize, + &SaveRestoreData + ); + + if (EFI_ERROR(Status)) { + return EFI_SUCCESS; + } + + /// + /// Write to IO trap address to trigger SMI for register restoration + /// + DEBUG ((EFI_D_INFO, "S3 SMI register restoration\n")); + IoWrite16 (SaveRestoreData.IoTrapAddress, 0x0); + + return EFI_SUCCESS; +} diff --git a/ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchInitPeim.cif b/ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchInitPeim.cif new file mode 100644 index 0000000..f8cc797 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchInitPeim.cif @@ -0,0 +1,17 @@ +<component> + name = "PchInitPeim" + category = ModulePart + LocalRoot = "ReferenceCode\Chipset\LynxPoint\PchInit\Pei" + RefName = "PchInitPeim" +[files] +"PchInitPeim.sdl" +"PchInitPeim.mak" +"PchInitPeim.h" +"PchInitPeim.c" +"PchInitPeim.dxs" +"PchInitPeim.inf" +"PchUsbInit.c" +"PchInitCommon.h" +"PchDmiPeim.c" +"PchUsbPreconditionPeim.c" +<endComponent> diff --git a/ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchInitPeim.dxs b/ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchInitPeim.dxs new file mode 100644 index 0000000..a2a2f80 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchInitPeim.dxs @@ -0,0 +1,39 @@ +/** @file + Dependency expression source file. + +@copyright + Copyright (c) 2004 - 2012 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 a 'Sample Driver' and is licensed as such + under the terms of your license agreement with Intel or your + vendor. This file may be modified by the user, subject to + the additional terms of the license agreement + +**/ + + +// +// Common for R8 and R9 codebase +// +#include "AutoGen.h" +#include "PeimDepex.h" + +// +// BUILD_WITH_GLUELIB and BUILD_WITH_EDKII_GLUE_LIB are both "defined" in R8 codebase; +// BUILD_WITH_EDKII_GLUE_LIB is defined in Edk-Dev-Snapshot-20070228 and later version +// BUILD_WITH_GLUELIB and BUILD_WITH_EDKII_GLUE_LIB are "not defined" in R9 codebase. +// +#if defined (BUILD_WITH_GLUELIB) || defined (BUILD_WITH_EDKII_GLUE_LIB) +#include "EfiDepex.h" +#endif + +DEPENDENCY_START + TRUE +DEPENDENCY_END diff --git a/ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchInitPeim.h b/ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchInitPeim.h new file mode 100644 index 0000000..1e433db --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchInitPeim.h @@ -0,0 +1,253 @@ +/** @file + Header file for the PCH Init PEIM + +@copyright + Copyright (c) 2004 - 2012 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 +**/ +#ifndef _PCH_INIT_PEIM_H_ +#define _PCH_INIT_PEIM_H_ + +#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000) + +#include "EdkIIGluePeim.h" +#include "PchInitVar.h" +#include "PchAccess.h" +#include "PchPlatformLib.h" +#include "PchUsbCommon.h" +#include "IobpDefinitions.h" +#include "PchHsio.h" +#include EFI_PPI_PRODUCER (PchInit) +#include EFI_PPI_PRODUCER (PchDmiTcVcMap) +#include EFI_PPI_CONSUMER (MemoryDiscovered) +#include EFI_PPI_CONSUMER (PchUsbPolicy) +#include EFI_PPI_CONSUMER (PchPlatformPolicy) +#include EFI_PPI_CONSUMER (PchReset) +#include EFI_PPI_PRODUCER (PchPeiInitDone) +#endif + +// +// ChipsetInit settings defines +// +#define H2M_HSIO_MESSAGE (0x7 << 28)///< Master type for all H2M Hsio messages +#define H2M_HSIO_CMD_GETHSIOVER 1 ///< Triggers Hsio version to be sent through ME/Host FW Status registers +#define H2M_HSIO_CMD_CLOSE 0 ///< Triggers H2M Hsio interface to close and revert FW Status registers +#define M2H_HSIO_MSG_ACK 0x7 ///< Ack sent in response to any H2M Hsio messages +#define MAX_ME_MSG_ACK_TIMEOUT 0x186A0 // Wait max of 100ms for FW to acknowledge. + +/** + Internal function performing SATA init needed in PEI phase + + @param[in] PeiServices General purpose services available to every PEIM. + @param[in] PchPlatformPolicyPpi The PCH Platform Policy PPI instance + + @retval None +**/ +EFI_STATUS +EFIAPI +PchSataInit ( + IN EFI_PEI_SERVICES **PeiServices, + IN PCH_PLATFORM_POLICY_PPI *PchPlatformPolicyPpi + ); + +/** + This function may trigger platform reset depending on the current GbE status, + the intended GbE enabling, and current ME status. (When ME is enabled, this function + may trigger a Global reset.) + This function may not return if it triggers an platform reset and the BIOS boot flow + restarts. + If this function returns EFI_SUCCESS it indicates there is no need for platform + reset in this boot, and boot flow continues. + If this function returns EFI_DEVICE_ERROR, something error happens. + + @param[in] PeiServices General purpose services available to every PEIM. + @param[in] PchPlatformPolicyPpi The PCH Platform Policy PPI instance + + @retval EFI_SUCCESS No platform reset action is taken. System can continue boot flow. + @retval Others Won't return if platform reset action is taken +**/ +EFI_STATUS +EFIAPI +PchGbeMandatedReset ( + IN EFI_PEI_SERVICES **PeiServices, + IN PCH_PLATFORM_POLICY_PPI *PchPlatformPolicyPpi + ); + +/** + Perform Thermal Management Support initialization + + @param[in] PchPlatformPolicyPpi The PCH Platform Policy PPI instance + + @retval EFI_SUCCESS Succeeds. + @retval EFI_DEVICE_ERROR Device error, aborts abnormally. +**/ +EFI_STATUS +PchThermalInit ( + IN PCH_PLATFORM_POLICY_PPI *PchPlatformPolicyPpi + ); + +/** + Initialize IOAPIC according to IoApicConfig policy of the PCH + Platform Policy PPI + + @param[in] PchPlatformPolicyPpi The PCH Platform Policy PPI instance + + @retval EFI_SUCCESS Succeeds. + @retval EFI_DEVICE_ERROR Device error, aborts abnormally. +**/ +EFI_STATUS +PchIoApicInit ( + IN PCH_PLATFORM_POLICY_PPI *PchPlatformPolicyPpi + ); + +/** + This function performs basic initialization for PCH in PEI phase. + If any of the base address arguments is zero, this function will disable the corresponding + decoding, otherwise this function will enable the decoding. + This function locks down the PMBase. + + @param[in] PeiServices General purpose services available to every PEIM. + @param[in] NotifyDescriptor The notification structure this PEIM registered on install. + @param[in] Ppi The memory discovered PPI. Not used. + + @retval EFI_SUCCESS Succeeds. + @retval EFI_DEVICE_ERROR Device error, aborts abnormally. +**/ +EFI_STATUS +EFIAPI +PchInitialize ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ); + +/** + The function performing USB init in PEI phase. This could be used by USB recovery + or debug features that need USB initialization during PEI phase. + Note: Before executing this function, please be sure that PCH_INIT_PPI.Initialize + has been done and PchUsbPolicyPpi has been installed. + + @param[in] PeiServices General purpose services available to every PEIM + + @retval EFI_SUCCESS The function completed successfully + @retval Others All other error conditions encountered result in an ASSERT. +**/ +EFI_STATUS +EFIAPI +PchUsbInit ( + IN EFI_PEI_SERVICES **PeiServices + ); + +/** + The function performing TC/VC mapping program, and poll all PCH Virtual Channel + until negotiation completion + + @param[in] PeiServices General purpose services available to every PEIM. + + @retval EFI_SUCCESS The function completed successfully + @retval Others All other error conditions encountered result in an ASSERT. +**/ +EFI_STATUS +EFIAPI +PchDmiTcVcProgPoll ( + IN EFI_PEI_SERVICES **PeiServices + ); + +/** + The function set the Target Link Speed in PCH to DMI GEN 2. + + @param[in] PeiServices General purpose services available to every PEIM. + + @retval None +**/ +VOID +EFIAPI +PchDmiGen2Prog ( + IN EFI_PEI_SERVICES **PeiServices + ); + +/** + The function program DMI miscellaneous registers. + + @param[in] PeiServices General purpose services available to every PEIM + @param[in] PchPlatformPolicyPpi The PCH Platform Policy PPI instance + + @retval EFI_SUCCESS The DMI required settings programmed correctly +**/ +EFI_STATUS +EFIAPI +PchDmiMiscProg ( + IN EFI_PEI_SERVICES **PeiServices, + IN PCH_PLATFORM_POLICY_PPI *PchPlatformPolicyPpi + ); + +/** + The function is used while doing CPU Only Reset, where PCH may be required + to initialize strap data before soft reset. + + @param[in] PeiServices General purpose services available to every PEIM + @param[in] Operation Get/Set Cpu Strap Set Data + @param[in, out] CpuStrapSet Cpu Strap Set Data + + @retval EFI_SUCCESS The function completed successfully. + @exception EFI_UNSUPPORTED The function is not supported. +**/ +EFI_STATUS +EFIAPI +PchCpuStrapSet ( + IN EFI_PEI_SERVICES **PeiServices, + IN CPU_STRAP_OPERATION Operation, + IN OUT UINT16 *CpuStrapSet + ); + +/** + The function performing USB init in PEI phase. This could be + used by USB recovery ,debug features or usb precondition + enabled case that need USB initialization during PEI phase. + Please be sure the function should not be executed in if the + boot mode is S3 resume. + + @param[in] PeiServices General purpose services available to every PEIM + + @retval EFI_SUCCESS The function completed successfully + @retval Others All other error conditions encountered result in an ASSERT. +**/ +EFI_STATUS +PchStartUsbInit ( + IN PCH_USB_CONFIG *UsbConfig, + IN UINT32 EhciMemBaseAddr, + IN UINT32 XhciMemBaseAddr, + IN UINT8 Revision + ); + +/** + This function handles Pch S3 resume task + + @param[in] PeiServices - Pointer to PEI Services Table. + @param[in] NotifyDesc - Pointer to the descriptor for the Notification event that + caused this function to execute. + @param[in] Ppi - Pointer to the PPI data associated with this function. + + @retval EFI_STATUS - Always return EFI_SUCCESS +**/ +EFI_STATUS +PchS3ResumeAtEndOfPei ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc, + IN VOID *Ppi + ); + +#endif diff --git a/ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchInitPeim.inf b/ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchInitPeim.inf new file mode 100644 index 0000000..02e4639 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchInitPeim.inf @@ -0,0 +1,108 @@ +## @file +# Component description file for the PCH Init PEIM. +# +#@copyright +# Copyright (c) 2004 - 2013 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 a 'Sample Driver' and is licensed as such +# under the terms of your license agreement with Intel or your +# vendor. This file may be modified by the user, subject to +# the additional terms of the license agreement +# + +[defines] +BASE_NAME = PchInitPeim +FILE_GUID = FD236AE7-0791-48c4-B29E-29BDEEE1A838 +COMPONENT_TYPE = PE32_PEIM + +[sources.common] + PchInitPeim.h + PchInitPeim.c + PchUsbInit.c + ../Common/PchUsbCommon.c + ../Common/PchInitVar.c + ../Common/PchHsio.c + ../Common/PchHsioLptHB0.c + ../Common/PchHsioLptHCx.c + ../Common/PchHsioLptLpBx.c + PchDmiPeim.c + + PchUsbPreconditionPeim.c +# +# Edk II Glue Driver Entry Point +# + EdkIIGluePeimEntryPoint.c + +[includes.common] + . + ../Common + $(EDK_SOURCE)/Foundation/Efi + $(EDK_SOURCE)/Foundation/Include + $(EDK_SOURCE)/Foundation/Efi/Include + $(EDK_SOURCE)/Foundation/Framework/Include + $(EFI_SOURCE)/$(PROJECT_PCH_ROOT) + $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Include + $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Include/Library + $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Protocol/PchPlatformPolicy + $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Guid/ChipsetInitHob + $(EFI_SOURCE)/$(PROJECT_ME_ROOT) + $(EFI_SOURCE)/$(PROJECT_ME_ROOT)/Heci/Include + $(EFI_SOURCE)/$(PROJECT_ME_ROOT)/Library/MeKernel/include +# +# EDK II Glue Library utilizes some standard headers from EDK +# + $(EFI_SOURCE) + $(EDK_SOURCE)/Foundation + $(EDK_SOURCE)/Foundation/Framework + $(EDK_SOURCE)/Foundation/Include/IndustryStandard + $(EDK_SOURCE)/Foundation/Core/Dxe + $(EDK_SOURCE)/Foundation/Include/Pei + $(EDK_SOURCE)/Foundation/library/Pei/Include + $(EDK_SOURCE)/Foundation/Library/Dxe/Include + $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Include + $(EDK_SOURCE)/Foundation/Efi + $(EDK_SOURCE)/Foundation/Efi/Include + $(EDK_SOURCE)/Foundation/Framework/Include + $(EDK_SOURCE)/Foundation/Include + +[libraries.common] + $(PROJECT_PCH_FAMILY)PpiLib + EdkFrameworkPpiLib + EdkIIGlueBaseIoLibIntrinsic + EdkIIGlueBaseMemoryLib + EdkIIGluePeiDebugLibReportStatusCode + EdkIIGluePeiReportStatusCodeLib + EdkIIGluePeiServicesLib + EdkIIGluePeiMemoryAllocationLib + EdkIIGluePeiFirmwarePerformanceLib + EdkIIGlueBasePciLibPciExpress + EdkPpiLib + PchPlatformLib + PeiLib + $(PROJECT_PCH_FAMILY)PpiLib + EdkIIGluePeiFirmwarePerformanceLib + PchPlatformLib + MeLibPpi + MeGuidLib + +[nmake.common] + IMAGE_ENTRY_POINT = _ModuleEntryPoint + DPX_SOURCE = PchInitPeim.dxs +# +# Module Entry Point +# + C_FLAGS = $(C_FLAGS) -D __EDKII_GLUE_MODULE_ENTRY_POINT__=InstallPchInitPpi + C_FLAGS = $(C_FLAGS) -D __EDKII_GLUE_BASE_IO_LIB_INTRINSIC__ \ + -D __EDKII_GLUE_BASE_MEMORY_LIB__ \ + -D __EDKII_GLUE_PEI_DEBUG_LIB_REPORT_STATUS_CODE__ \ + -D __EDKII_GLUE_PEI_REPORT_STATUS_CODE_LIB__ \ + -D __EDKII_GLUE_PEI_SERVICES_LIB__ \ + -D __EDKII_GLUE_PEI_MEMORY_ALLOCATION_LIB__ \ + -D __EDKII_GLUE_BASE_PCI_LIB_PCI_EXPRESS__ diff --git a/ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchInitPeim.mak b/ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchInitPeim.mak new file mode 100644 index 0000000..0bd26c3 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchInitPeim.mak @@ -0,0 +1,117 @@ +#************************************************************************* +#************************************************************************* +#** ** +#** (C)Copyright 1985-2011, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#************************************************************************* +#************************************************************************* + +#************************************************************************* +# $Header: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchInitPeim/PchInitPeim.mak 4 12/18/12 4:53a Scottyang $ +# +# $Revision: 4 $ +# +# $Date: 12/18/12 4:53a $ +#************************************************************************* +# Revision History +# ---------------- +# $Log: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchInitPeim/PchInitPeim.mak $ +# +# 4 12/18/12 4:53a Scottyang +# [TAG] EIP109697 +# [Category] Improvement +# [Description] Update PCH RC 0.8.1 +# [Files] ReferenceCode\Chipset\LynxPoint\*.*, SBDxe.c, SBPEI.c, SB.sd, +# SbSetupData.c, GetSetupDate.c +# +# 3 11/20/12 8:36a Scottyang +# [TAG] EIP107014 +# [Category] Improvement +# [Description] Update RC 0.8.0 +# [Files] ReferenceCode\Chipset\LynxPoint\*.*, SBDxe.c, SB.sd, +# SbSetupData.c, GetSetupDate.c +# +# 2 2/24/12 2:13a Victortu +# Updated to support 4.6.5.3_IntelEDK_1117_Patch7_00. +# +# 1 2/08/12 8:53a Yurenlai +# Intel Lynx Point/SB eChipset initially releases. +# +#************************************************************************* + +#--------------------------------------------------------------------------- +# Create PchInitPeim module +#--------------------------------------------------------------------------- +EDK : PchInitPeim +PchInitPeim : $(BUILD_DIR)\PchInitPeim.mak PchInitPeimBin + + +$(BUILD_DIR)\PchInitPeim.mak : $(PchInitPeim_DIR)\$(@B).cif $(PchInitPeim_DIR)\$(@B).mak $(BUILD_RULES) + $(CIF2MAK) $(PchInitPeim_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS) + +PchInitPeim_INCLUDES=\ + /I$(INTEL_PCH_DIR)\PchInit\Common\ + $(INTEL_PCH_INCLUDES)\ + $(EdkIIGlueLib_INCLUDES)\ + /I$(INTEL_PCH_DIR)\Guid\SurvivabilityHob\ + $(ME_INCLUDES)\ + +PchInitPeim_DEFINES = $(MY_DEFINES)\ + /D"__EDKII_GLUE_MODULE_ENTRY_POINT__=InstallPchInitPpi"\ + /D __EDKII_GLUE_BASE_IO_LIB_INTRINSIC__ \ + /D __EDKII_GLUE_PEI_DEBUG_LIB_REPORT_STATUS_CODE__ \ + /D __EDKII_GLUE_PEI_REPORT_STATUS_CODE_LIB__ \ + /D __EDKII_GLUE_PEI_SERVICES_LIB__ \ + /D __EDKII_GLUE_PEI_MEMORY_ALLOCATION_LIB__ \ + /D __EDKII_GLUE_BASE_PCI_LIB_PCI_EXPRESS__ + +PchInitPeim_LIB_LINKS =\ + $(GuidLib_LIB) \ + $(PchPlatformPeiLib_LIB) \ + $(IntelPchPpiLib_LIB)\ + $(EDKFRAMEWORKPPILIB) \ + $(EdkIIGlueBaseLib_LIB)\ + $(EdkIIGlueBaseLibIA32_LIB)\ + $(EdkIIGlueBaseIoLibIntrinsic_LIB) \ + $(EdkIIGluePeiDebugLibReportStatusCode_LIB) \ + $(EdkIIGluePeiReportStatusCodeLib_LIB) \ + $(EdkIIGluePeiServicesLib_LIB) \ + $(EdkIIGluePeiMemoryAllocationLib_LIB) \ + $(EdkIIGlueBasePciLibCf8_LIB) \ + $(PchUsbCommonPeiLib_LIB)\ + $(EdkIIGlueBasePciLibPciExpress_LIB)\ + $(PEILIB) + +PchInitPeimBin: $(PchInitPeim_LIB_LINKS) + $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\ + /f $(BUILD_DIR)\PchInitPeim.mak all \ + "MY_INCLUDES=$(PchInitPeim_INCLUDES)"\ + "MY_DEFINES=$(PchInitPeim_DEFINES)"\ + NAME=PchInitPeim\ + MAKEFILE=$(BUILD_DIR)\PchInitPeim.mak \ + GUID=FD236AE7-0791-48c4-B29E-29BDEEE1A838\ + ENTRY_POINT=_ModuleEntryPoint \ + TYPE=PEIM \ + EDKIIModule=PEIM\ + DEPEX1=$(PchInitPeim_DIR)\PchInitPeim.dxs\ + DEPEX1_TYPE=EFI_SECTION_PEI_DEPEX\ + COMPRESS=0 +#************************************************************************* +#************************************************************************* +#** ** +#** (C)Copyright 1985-2011, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#************************************************************************* +#************************************************************************* diff --git a/ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchInitPeim.sdl b/ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchInitPeim.sdl new file mode 100644 index 0000000..cfde1c7 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchInitPeim.sdl @@ -0,0 +1,67 @@ +#************************************************************************* +#************************************************************************* +#** ** +#** (C)Copyright 1985-2011, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#************************************************************************* +#************************************************************************* + +#************************************************************************* +# $Header: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchInitPeim/PchInitPeim.sdl 1 2/08/12 8:53a Yurenlai $ +# +# $Revision: 1 $ +# +# $Date: 2/08/12 8:53a $ +#************************************************************************* +# Revision History +# ---------------- +# $Log: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchInitPeim/PchInitPeim.sdl $ +# +# 1 2/08/12 8:53a Yurenlai +# Intel Lynx Point/SB eChipset initially releases. +# +#************************************************************************* +TOKEN + Name = "PchInitPeim_SUPPORT" + Value = "1" + Help = "Main switch to enable PchInitPeim support in Project" + TokenType = Boolean + TargetEQU = Yes + TargetMAK = Yes + Master = Yes +End + +PATH + Name = "PchInitPeim_DIR" +End + +MODULE + File = "PchInitPeim.mak" + Help = "Includes PchInitPeim.mak to Project" +End + +ELINK + Name = "$(BUILD_DIR)\PchInitPeim.ffs" + Parent = "FV_BB" + InvokeOrder = AfterParent +End + +#************************************************************************* +#************************************************************************* +#** ** +#** (C)Copyright 1985-2011, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#************************************************************************* +#************************************************************************* diff --git a/ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchUsbInit.c b/ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchUsbInit.c new file mode 100644 index 0000000..44381fc --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchUsbInit.c @@ -0,0 +1,198 @@ +/** @file + Initializes PCH USB Controllers. + +@copyright + Copyright (c) 2009 - 2013 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 "PchInitPeim.h" + +/** + The function performing USB init in PEI phase. This could be used by USB recovery + or debug features that need USB initialization during PEI phase. + Note: Before executing this function, please be sure that PCH_INIT_PPI.Initialize + has been done and PchUsbPolicyPpi has been installed. + + @param[in] PeiServices General purpose services available to every PEIM + + @retval EFI_SUCCESS The function completed successfully + @retval Others All other error conditions encountered result in an ASSERT. +**/ +EFI_STATUS +EFIAPI +PchUsbInit ( + IN EFI_PEI_SERVICES **PeiServices + ) +{ + EFI_STATUS Status; + PCH_USB_POLICY_PPI *PchUsbPolicyPpi; + + DEBUG ((EFI_D_INFO, "PchUsbInit() - Start\n")); + + /// + /// Get PchUsbPolicy PPI for PCH_USB_CONFIG + /// + Status = (**PeiServices).LocatePpi ( + PeiServices, + &gPchUsbPolicyPpiGuid, + 0, + NULL, + (VOID **)&PchUsbPolicyPpi + ); + + if (Status == EFI_SUCCESS) { +#ifdef EFI_DEBUG + DEBUG ((EFI_D_INFO, "\n------------------------ PchUsbPolicyPpi Dump Begin -----------------\n")); + DEBUG ((EFI_D_INFO, "Revision : 0x%x\n", PchUsbPolicyPpi->Revision)); + DEBUG ((EFI_D_INFO, "Mode : 0x%x\n", PchUsbPolicyPpi->Mode)); + DEBUG ((EFI_D_INFO, "EhciMemBaseAddr : 0x%x\n", PchUsbPolicyPpi->EhciMemBaseAddr)); + DEBUG ((EFI_D_INFO, "EhciMemLength : 0x%x\n", PchUsbPolicyPpi->EhciMemLength)); + DEBUG ((EFI_D_INFO, "XhciMemBaseAddr : 0x%x\n", PchUsbPolicyPpi->XhciMemBaseAddr)); +#endif + Status = PchStartUsbInit ( + PchUsbPolicyPpi->UsbConfig, + (UINT32) PchUsbPolicyPpi->EhciMemBaseAddr, + (UINT32) PchUsbPolicyPpi->XhciMemBaseAddr, + PchUsbPolicyPpi->Revision + ); +#ifdef EFI_DEBUG + DEBUG ((EFI_D_INFO, "\n")); + DEBUG ((EFI_D_INFO, "\n------------------------ PchUsbPolicyPpi Dump End -----------------\n")); +#endif + } + DEBUG ((EFI_D_INFO, "PchUsbInit() - End\n")); + return Status; +} + +/** + The function performing USB init in PEI phase. This could be + used by USB recovery ,debug features or usb precondition + enabled case that need USB initialization during PEI phase. + Please be sure the function should not be executed in if the + boot mode is S3 resume. + + @param[in] UsbConfig Pointer to a PCH_USB_CONFIG that provides the platform setting + @param[in] EhciMemBaseAddr Predefined Ehci memory base address for Ehci hc configuration + @param[in] XhciMemBaseAddr Predefined Xhci memory base address for Xhci hc configuration + @param[in] Revision Revision of PCH_USB_CONFIG + + @retval EFI_SUCCESS The function completed successfully + @retval Others All other error conditions encountered result in an ASSERT +**/ +EFI_STATUS +PchStartUsbInit ( + IN PCH_USB_CONFIG *UsbConfig, + IN UINT32 EhciMemBaseAddr, + IN UINT32 XhciMemBaseAddr, + IN UINT8 Revision + ) +{ + EFI_STATUS Status; + UINT32 RootComplexBar; + UINT32 FuncDisableReg; +#ifdef EFI_DEBUG + UINT8 i; +#endif + + DEBUG ((EFI_D_INFO, "PchStartUsbInit() - Start\n")); + Status = EFI_INVALID_PARAMETER; + if (UsbConfig != NULL) { +#ifdef EFI_DEBUG + DEBUG ((EFI_D_INFO, "Revision : 0x%x\n", Revision)); + DEBUG ((EFI_D_INFO, "EhciMemBaseAddr : 0x%x\n", EhciMemBaseAddr)); + DEBUG ((EFI_D_INFO, "XhciMemBaseAddr : 0x%x\n", XhciMemBaseAddr)); + + DEBUG ((EFI_D_INFO, "\n")); + DEBUG ((EFI_D_INFO, "------------------------ PCH_USB_CONFIG Dump Start -----------------\n")); + DEBUG ((EFI_D_INFO, " PCH_USB_CONFIG UsbPerPortCtl= %x\n", UsbConfig->UsbPerPortCtl)); + DEBUG ((EFI_D_INFO, " PCH_USB_CONFIG Ehci1Usbr= %x\n", UsbConfig->Ehci1Usbr)); + DEBUG ((EFI_D_INFO, " PCH_USB_CONFIG Ehci2Usbr= %x\n", UsbConfig->Ehci2Usbr)); + for (i = 0; i < GetPchUsbMaxPhysicalPortNum (); i++) { + DEBUG ((EFI_D_INFO, " PCH_USB_CONFIG PortSettings[%d] Enabled= %x\n", i, UsbConfig->PortSettings[i].Enable)); + DEBUG ((EFI_D_INFO, " PCH_USB_CONFIG PortSettings[%d] Location = %x\n", i, UsbConfig->PortSettings[i].Location)); + } + + for (i = 0; i < GetPchXhciMaxUsb3PortNum (); i++) { + DEBUG ((EFI_D_INFO, " PCH_USB_CONFIG Port30Settings[%d] Enabled= %x\n", i, UsbConfig->Port30Settings[i].Enable)); + } + + for (i = 0; i < GetPchEhciMaxControllerNum (); i++) { + DEBUG ((EFI_D_INFO, " PCH_USB_CONFIG Usb20Settings[%d] Enabled= %x\n", i, UsbConfig->Usb20Settings[i].Enable)); + } + + DEBUG ((EFI_D_INFO, " PCH_USB_CONFIG Usb30Settings.Mode= %x\n", UsbConfig->Usb30Settings.Mode)); + DEBUG ((EFI_D_INFO, " PCH_USB_CONFIG Usb30Settings.PreBootSupport= %x\n", UsbConfig->Usb30Settings.PreBootSupport)); + DEBUG ((EFI_D_INFO, " XhciStreams is obsoleted, it doesn't effect any setting change since Revision 2.\n")); + DEBUG ((EFI_D_INFO, " PCH_USB_CONFIG Usb30Settings.ManualMode= %x\n", UsbConfig->Usb30Settings.ManualMode)); + DEBUG ((EFI_D_INFO, " PCH_USB_CONFIG Usb30Settings.XhciIdleL1= %x\n", UsbConfig->Usb30Settings.XhciIdleL1)); + + for (i = 0; i < GetPchUsbMaxPhysicalPortNum (); i++) { + if (UsbConfig->Usb30Settings.ManualModeUsb20PerPinRoute[i] == 0) { + DEBUG ((EFI_D_INFO, " PCH_USB_CONFIG Usb30Settings.ManualModeUsb20PerPinRoute[%d]= EHCI\n", i)); + } else { + DEBUG ((EFI_D_INFO, " PCH_USB_CONFIG Usb30Settings.ManualModeUsb20PerPinRoute[%d]= XHCI\n", i)); + } + } + + for (i = 0; i < GetPchXhciMaxUsb3PortNum (); i++) { + DEBUG ((EFI_D_INFO, + "PCH_USB_CONFIG Usb30Settings.ManualModeUsb30PerPinEnable[%d]= %x\n", + i, + UsbConfig->Usb30Settings.ManualModeUsb30PerPinEnable[i])); + } + + for (i = 0; i < GetPchUsbMaxPhysicalPortNum (); i++) { + DEBUG ((EFI_D_INFO, " PCH_USB_CONFIG Usb20OverCurrentPins[%d]= OC%x\n", i, UsbConfig->Usb20OverCurrentPins[i])); + } + + for (i = 0; i < GetPchXhciMaxUsb3PortNum (); i++) { + DEBUG ((EFI_D_INFO, " PCH_USB_CONFIG Usb30OverCurrentPins[%d]= OC%x\n", i, UsbConfig->Usb30OverCurrentPins[i])); + } + + for (i = 0; i < GetPchEhciMaxUsbPortNum (); i++) { + DEBUG ((EFI_D_INFO, " PCH_USB_CONFIG Usb20PortLength[%d]= %x.%0x\n", i, UsbConfig->PortSettings[i].Usb20PortLength >> 4, UsbConfig->PortSettings[i].Usb20PortLength & 0xF)); + } + DEBUG ((EFI_D_INFO, "\n")); + DEBUG ((EFI_D_INFO, "\n------------------------ PCH_USB_CONFIG Dump End -----------------\n")); +#endif + RootComplexBar = PCH_RCRB_BASE; + FuncDisableReg = MmioRead32 (RootComplexBar + R_PCH_RCRB_FUNC_DIS); + + Status = CommonUsbInit ( + UsbConfig, + (UINT32) EhciMemBaseAddr, + (UINT32) XhciMemBaseAddr, + 0, + RootComplexBar, + &FuncDisableReg, + Revision + ); + + ASSERT_EFI_ERROR (Status); + + MmioWrite32 ((UINTN) (RootComplexBar + R_PCH_RCRB_FUNC_DIS), (UINT32) (FuncDisableReg)); + // + // Reads back for posted write to take effect + // + MmioRead32 ((UINTN) (RootComplexBar + R_PCH_RCRB_FUNC_DIS)); + } + + DEBUG ((EFI_D_INFO, "PchStartUsbInit() - End\n")); + + return Status; + +} diff --git a/ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchUsbPreconditionPeim.c b/ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchUsbPreconditionPeim.c new file mode 100644 index 0000000..0735fd6 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchUsbPreconditionPeim.c @@ -0,0 +1,105 @@ +/** @file + + PCH USB precondition feature support in PEI phase + +@copyright + Copyright (c) 2012 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 "PchInitPeim.h" + +#ifdef USB_PRECONDITION_ENABLE_FLAG + +extern USB_CONTROLLER EhciControllersMap[]; + +/** + Perform USB precondition on EHCI, it is the HC on USB HC in PEI phase + + @param[in] Device The device number of the EHCI + @param[in] EhciMmioBase Memory base address of EHCI Controller + + @retval None +**/ +VOID +EhciPrecondition ( + IN UINT8 Device, + IN UINT32 EhciMmioBase + ) +{ + UINTN HcResetTimeout; + + HcResetTimeout = 0; + while ((HcResetTimeout < 200) && + (MmioRead32 (EhciMmioBase + R_PCH_EHCI_USB2CMD) & B_PCH_EHCI_USB2CMD_HCRESET)) { + PchPmTimerStall (100); + HcResetTimeout++; + } + + if ((MmioRead32 (EhciMmioBase + R_PCH_EHCI_USB2CMD) & B_PCH_EHCI_USB2CMD_HCRESET) == 0) { + // + // Route all ports to this EHCI + // + MmioWrite32 ((EhciMmioBase + R_PCH_EHCI_CONFIGFLAG), BIT0); + } +} + +/** + Perform USB precondition on XHCI, it is the HC on USB HC in PEI phase + + @param[in] BusNumber The Bus number of the XHCI + @param[in] Device The device number of the XHCI + @param[in] Function The function number of the XHCI + @param[in] XhciMmioBase Memory base address of XHCI Controller + @param[in] XhciUSB2Ptr Pointer to USB2 protocol port register + @param[in] HsPortCount The number of USB2 protocol port supported by this XHCI + + @retval None +**/ +VOID +XhciPrecondition ( + IN UINT8 BusNumber, + IN UINT8 Device, + IN UINT8 Function, + IN UINT32 XhciMmioBase, + IN UINTN *XhciUSB2Ptr, + IN UINTN HsPortCount, + IN UINTN *XhciUSB3Ptr, + IN UINTN SsPortCount + ) +{ + UINT32 Data32; + UINTN HcHaltTimeout; + + // + // Set the XHC to halt state before reset + // + HcHaltTimeout = 0; + if (!(MmioRead32 (XhciMmioBase + R_PCH_XHCI_USBSTS) & BIT0)) { + Data32 = MmioRead32 (XhciMmioBase + R_PCH_XHCI_USBCMD); + MmioWrite32 ((XhciMmioBase + R_PCH_XHCI_USBCMD), (Data32 &~B_PCH_XHCI_USBCMD_RS)); + while ((HcHaltTimeout < 200) && + (!(MmioRead32 (XhciMmioBase + R_PCH_XHCI_USBSTS) & BIT0))) { + PchPmTimerStall (100); + HcHaltTimeout++; + } + } + + if (MmioRead32 (XhciMmioBase + R_PCH_XHCI_USBSTS) & BIT0) { + MmioOr16 ((XhciMmioBase + R_PCH_XHCI_USBCMD), BIT1); + } +} + +#endif // USB_PRECONDITION_ENABLE_FLAG |