summaryrefslogtreecommitdiff
path: root/ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchInitPeim.c
diff options
context:
space:
mode:
Diffstat (limited to 'ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchInitPeim.c')
-rw-r--r--ReferenceCode/Chipset/LynxPoint/PchInit/Pei/PchInitPeim.c2232
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;
+}