diff options
Diffstat (limited to 'ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchInitPeim.c')
-rw-r--r-- | ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchInitPeim.c | 2232 |
1 files changed, 2232 insertions, 0 deletions
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; +} |