summaryrefslogtreecommitdiff
path: root/ReferenceCode/Chipset/SystemAgent/SaInit/Pei/SaDmiPeim.c
diff options
context:
space:
mode:
Diffstat (limited to 'ReferenceCode/Chipset/SystemAgent/SaInit/Pei/SaDmiPeim.c')
-rw-r--r--ReferenceCode/Chipset/SystemAgent/SaInit/Pei/SaDmiPeim.c450
1 files changed, 450 insertions, 0 deletions
diff --git a/ReferenceCode/Chipset/SystemAgent/SaInit/Pei/SaDmiPeim.c b/ReferenceCode/Chipset/SystemAgent/SaInit/Pei/SaDmiPeim.c
new file mode 100644
index 0000000..ea817d8
--- /dev/null
+++ b/ReferenceCode/Chipset/SystemAgent/SaInit/Pei/SaDmiPeim.c
@@ -0,0 +1,450 @@
+/** @file
+ SA Dmi PEI Initialization library
+
+@copyright
+ Copyright (c) 1999 - 2012 Intel Corporation. All rights reserved
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.
+
+ This file contains an 'Intel Peripheral Driver' and uniquely
+ identified as "Intel Reference Module" and is
+ licensed for Intel CPUs and chipsets under the terms of your
+ license agreement with Intel or your vendor. This file may
+ be modified by the user, subject to additional terms of the
+ license agreement
+
+**/
+#include "SaDmiPeim.h"
+#include "PciExpressInit.h"
+
+///
+/// Functions
+///
+/**
+ Initialize DMI Tc/Vc mapping through SA-PCH.
+
+ @param[in] PeiServices - General purpose services available to every PEIM.
+ @param[in] SaPlatformPolicyPpi - Instance of SA_PLATFORM_POLICY_PPI
+
+ @retval EFI_SUCCESS
+**/
+EFI_STATUS
+SaDmiTcVcInit (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN SA_PLATFORM_POLICY_PPI *SaPlatformPolicyPpi
+ )
+{
+ EFI_STATUS Status;
+ UINT64 MchBar;
+ UINT64 DmiBar;
+ PCH_INIT_PPI *PchInitPpi;
+ PCH_DMI_TC_VC_PPI *PchDmiTcVcMapPpi;
+ CPU_FAMILY CpuFamilyId;
+ UINT8 i;
+
+ MchBar = McD0PciCfg64 (R_SA_MCHBAR) &~BIT0;
+ DmiBar = McD0PciCfg64 (R_SA_DMIBAR) &~BIT0;
+ CpuFamilyId = GetCpuFamily();
+
+ ///
+ /// Locate PchInitPpi and PchDmiTcVcMapPpi
+ ///
+ Status = (*PeiServices)->LocatePpi (PeiServices, &gPchInitPpiGuid, 0, NULL, (VOID **) &PchInitPpi);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = (*PeiServices)->LocatePpi (PeiServices, &gPchDmiTcVcMapPpiGuid, 0, NULL, (VOID **) &PchDmiTcVcMapPpi);
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// SA OPI Initialization
+ ///
+ if (CpuFamilyId == EnumCpuHswUlt) {
+ MmioOr8 ((UINTN) (DmiBar + 0xA78), BIT1);
+ }
+
+ ///
+ /// Update DmiTcVcMapping based on Policy
+ ///
+ PchDmiTcVcMapPpi->DmiVc[DmiVcTypeVc1].Enable = (BOOLEAN) SaPlatformPolicyPpi->PcieConfig->DmiVc1;
+ PchDmiTcVcMapPpi->DmiVc[DmiVcTypeVcp].Enable = (BOOLEAN) SaPlatformPolicyPpi->PcieConfig->DmiVcp;
+ PchDmiTcVcMapPpi->DmiVc[DmiVcTypeVcm].Enable = (BOOLEAN) SaPlatformPolicyPpi->PcieConfig->DmiVcm;
+
+ for (i = 0; i < DmiTcTypeMax; i++) {
+ if (((PchDmiTcVcMapPpi->DmiTc[i].Vc == DmiVcTypeVc1) && (PchDmiTcVcMapPpi->DmiVc[DmiVcTypeVc1].Enable == FALSE)) ||
+ ((PchDmiTcVcMapPpi->DmiTc[i].Vc == DmiVcTypeVcp) && (PchDmiTcVcMapPpi->DmiVc[DmiVcTypeVcp].Enable == FALSE)) ||
+ ((PchDmiTcVcMapPpi->DmiTc[i].Vc == DmiVcTypeVcm) && (PchDmiTcVcMapPpi->DmiVc[DmiVcTypeVcm].Enable == FALSE))
+ ) {
+ PchDmiTcVcMapPpi->DmiTc[i].Vc = DmiVcTypeVc0;
+ }
+ }
+ ///
+ /// Program NB TC/VC mapping
+ ///
+ SaSetDmiTcVcMapping (PchDmiTcVcMapPpi, DmiBar);
+
+ ///
+ /// Call PchDmiTcVcProgPoll
+ ///
+ Status = PchInitPpi->DmiTcVcProgPoll (PeiServices);
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Poll NB negotiation completion
+ ///
+ SaPollDmiVcStatus (PchDmiTcVcMapPpi, DmiBar);
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+
+}
+
+/**
+ Map SA DMI TCs to VC
+
+ @param[in] PchDmiTcVcMapPpi - Instance of PCH_DMI_TC_VC_PPI
+ @param[in] DmiBar - DMIBAR address
+
+ @retval EFI_SUCCESS - Succeed.
+ @retval EFI_INVALID_PARAMETER - Wrong phase parameter passed in.
+**/
+EFI_STATUS
+SaSetDmiTcVcMapping (
+ IN PCH_DMI_TC_VC_PPI *PchDmiTcVcMapPpi,
+ IN UINT64 DmiBar
+ )
+{
+ UINT32 Data32And;
+ UINT32 Data32Or;
+ UINT8 Data8And;
+ UINT8 Data8Or;
+ UINT8 Index;
+ UINT16 Register;
+ UINT8 VcId;
+ UINT8 VcMap[DmiVcTypeMax] = { 0 };
+
+ ///
+ /// Set the TC/VC mappings
+ ///
+ for (Index = 0; Index < DmiTcTypeMax; Index++) {
+ VcMap[PchDmiTcVcMapPpi->DmiTc[Index].Vc] |= (BIT0 << Index);
+ }
+ ///
+ /// System BIOS must perform the following steps for VC0 configuration.
+ /// Program the TCs/VC0 map by setting DMIBAR offset 014h [7:1] = '0111 101b'.
+ ///
+ /// Private Virtual Channel Configuration
+ /// Step1. Assign Virtual Channel ID 2 to VCp:
+ /// Programming the DMIVCPRCTL DMI Port Register DMIBAR Offset 02Ch[26:24] = '010b'.
+ ///
+ /// Step2. Set TC2 to VCp:
+ /// Program the DMIVCPRCTL DMI Port Register DMIBAR offset 02Ch [7:1] = '0000 010b'.
+ ///
+ /// Step3. Enable VCp by programming the DMIVCPRCTL DMI Port Register DMIBAR Offset 02Ch[31] = '1b'.
+ ///
+ /// Virtual Channel for ME (VCm) Configuration
+ /// This is configured by ConfigMemMe
+ ///
+ /// Step1. Assign Virtual Channel ID 7 to VCm:
+ /// Programming the DMIVCMRCTL DMI Port Register DMIBAR Offset 038h[26:24] = '111b'.
+ ///
+ /// Step2. Enable VCm:
+ /// Programming the DMIVMPRCTL DMI Port Register DMIBAR Offset 038h[31] = '1b'.
+ ///
+ /// Step3. Enable VCm by programming the DMIVCMRCTL DMI Port Register DMIBAR Offset 038h[31] = '1b'.
+ ///
+ for (Index = 0; Index < DmiVcTypeMax; Index++) {
+ if (PchDmiTcVcMapPpi->DmiVc[Index].Enable == PCH_DEVICE_ENABLE) {
+ ///
+ /// Map TCs to VC, Set the VC ID, Enable VC
+ ///
+ VcId = PchDmiTcVcMapPpi->DmiVc[Index].VcId,
+
+ Data32And = (UINT32) (~(V_SA_DMIBAR_DMIVCCTL_ID | B_SA_DMIBAR_DMIVCCTL_TVM_MASK));
+ Data32Or = VcId << N_SA_DMIBAR_DMIVCCTL_ID;
+ Data32Or |= VcMap[Index];
+ Data32Or |= N_SA_DMIBAR_DMIVCCTL_EN;
+
+ switch (Index) {
+ case DmiVcTypeVc0:
+ Register = R_SA_DMIBAR_DMIVC0RCTL_OFFSET;
+ break;
+
+ case DmiVcTypeVc1:
+ Register = R_SA_DMIBAR_DMIVC1RCTL_OFFSET;
+ break;
+
+ case DmiVcTypeVcp:
+ Register = R_SA_DMIBAR_DMIVCPRCTL_OFFSET;
+ break;
+
+ case DmiVcTypeVcm:
+ Register = R_SA_DMIBAR_DMIVCMRCTL_OFFSET;
+ break;
+
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+
+ MmioAndThenOr32 ((UINTN) (DmiBar + Register), Data32And, Data32Or);
+ }
+ }
+ ///
+ /// System BIOS must program the extended VC Count:
+ /// Set the DMI Port Register DMIBAR Offset 004h[2:0]=001b
+ ///
+ Data8And = (UINT8) (~0x07);
+ if (PchDmiTcVcMapPpi->DmiVc[DmiVcTypeVc1].Enable == TRUE) {
+ Data8Or = 1;
+ } else {
+ Data8Or = 0;
+ }
+
+ MmioAndThenOr8 ((UINTN) (DmiBar + R_SA_DMIBAR_DMIPVCCAP1_OFFSET), Data8And, Data8Or);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Poll SA DMI negotiation completion
+
+ @param[in] PchDmiTcVcMapPpi - Instance of PCH_DMI_TC_VC_PPI
+ @param[in] DmiBar - DMIBAR address
+
+ @retval EFI_SUCCESS - Succeed.
+ @retval EFI_INVALID_PARAMETER - Wrong phase parameter passed in.
+**/
+EFI_STATUS
+SaPollDmiVcStatus (
+ IN PCH_DMI_TC_VC_PPI *PchDmiTcVcMapPpi,
+ IN UINT64 DmiBar
+ )
+{
+ UINT8 Index;
+ UINT16 Register;
+
+ ///
+ /// 6.2.3.2 - Step 4, Poll until VC1 has been negotiated
+ /// Read the DMIVC1RSTS DMI Port Register Offset 026h until [1]==0
+ ///
+ /// 6.2.3.3 - Step4. Poll the VCp Negotiation Pending bit until it reads 0:
+ /// Read the DMIVCPRSTS DMI Port Register Offset 032h until [1]==0
+ ///
+ /// 6.2.3.4 - Step4. Poll the VCm Negotiation Pending bit until it reads 0:
+ /// Read the DMIVCMRSTS DMI Port Register Offset 03Eh until [1]==0
+ ///
+ for (Index = 0; Index < DmiVcTypeMax; Index++) {
+ if (PchDmiTcVcMapPpi->DmiVc[Index].Enable == PCH_DEVICE_ENABLE) {
+ switch (Index) {
+ case DmiVcTypeVc0:
+ Register = R_SA_DMIBAR_DMIVC0RSTS_OFFSET;
+ break;
+
+ case DmiVcTypeVc1:
+ Register = R_SA_DMIBAR_DMIVC1RSTS_OFFSET;
+ break;
+
+ case DmiVcTypeVcp:
+ Register = R_SA_DMIBAR_DMIVCPRSTS_OFFSET;
+ break;
+
+ case DmiVcTypeVcm:
+ Register = R_SA_DMIBAR_DMIVCMRSTS_OFFSET;
+ break;
+
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+ ///
+ /// Wait for negotiation to complete
+ ///
+ while ((MmioRead16 ((UINTN) (DmiBar + Register)) & B_SA_DMIBAR_DMISTS_NP) != 0);
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+#ifdef DMI_FLAG
+/**
+ Initialize DMI.
+
+ @param[in] PeiServices - General purpose services available to every PEIM.
+ @param[in] SaPlatformPolicyPpi - Instance of SA_PLATFORM_POLICY_PPI
+
+ @retval EFI_SUCCESS
+**/
+EFI_STATUS
+DmiInit (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN SA_PLATFORM_POLICY_PPI *SaPlatformPolicyPpi
+ )
+{
+ EFI_STATUS Status;
+ UINT64 MchBar;
+ UINT64 DmiBar;
+ PCH_INIT_PPI *PchInitPpi;
+ PCH_PLATFORM_POLICY_PPI *PchPlatformPolicyPpi;
+ UINT8 CpuSteppingId;
+ BOOLEAN DmiGen2Enable;
+ UINT16 LinkStatus;
+ UINT32 Data32Or;
+
+ ///
+ /// Read the CPU stepping
+ ///
+ CpuSteppingId = GetCpuStepping();
+
+ ///
+ /// BridgeId = (UINT8) (McD0PciCfg16 (R_MC_DEVICE_ID) & 0xF0);
+ /// BridgeSteppingId = BridgeId + CpuSteppingId;
+ ///
+ MchBar = McD0PciCfg64 (R_SA_MCHBAR) &~BIT0;
+ DmiBar = McD0PciCfg64 (R_SA_DMIBAR) &~BIT0;
+
+ ///
+ /// Get RCBA through the PchPlatformPolicy PPI
+ ///
+ Status = (**PeiServices).LocatePpi (
+ PeiServices,
+ &gPchPlatformPolicyPpiGuid,
+ 0,
+ NULL,
+ &PchPlatformPolicyPpi
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "Can't locate PchPlatformPolicy PPI - exiting.\n"));
+ return Status;
+ }
+ ///
+ /// Perform DMI Recipe steps
+ ///
+ DEBUG ((EFI_D_INFO, "DMI Recipe...\n"));
+ PegDmiRecipe (SaPlatformPolicyPpi, (UINT32) MchBar, (UINT32) DmiBar, 0, 0);
+
+ ///
+ /// Additional DMI steps. See SA BIOS Spec.
+ ///
+ DEBUG ((EFI_D_INFO, "Run AdditionalDmiProgramSteps!\n"));
+ AdditionalDmiProgramSteps (SaPlatformPolicyPpi, (UINT32) MchBar, (UINT32) DmiBar);
+
+ DmiGen2Enable = TRUE;
+ if ((SaPlatformPolicyPpi->PcieConfig->DmiGen2 == 0) ||
+ ((MmioRead8 ((UINTN) PchPlatformPolicyPpi->Rcba + R_PCH_RCRB_LCAP) & (BIT0 | BIT1 | BIT2 | BIT3)) == 0x1) ||
+ (McDevFunPciCfg32 (0, 0, 0, R_SA_MC_CAPID0_A_OFFSET) & BIT22)
+ ) {
+ DEBUG ((EFI_D_WARN, "DMI Gen2 is Disabled or not capable, staying at Gen1 !\n"));
+ DmiGen2Enable = FALSE;
+ }
+
+ if (DmiGen2Enable) {
+ ///
+ /// Locate PchInitPpi
+ ///
+ Status = (*PeiServices)->LocatePpi (PeiServices, &gPchInitPpiGuid, 0, NULL, &PchInitPpi);
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Program PCH TLS to Gen 2
+ ///
+ PchInitPpi->DmiGen2Prog (PeiServices);
+
+ ///
+ /// Program CPU Max Link Speed to Gen 2
+ ///
+ MmioAndThenOr32 ((UINTN) (DmiBar + R_SA_DMIBAR_LCAP_OFFSET), (UINT32)~0xF, 2);
+ }
+ Data32Or = (MmioRead32 ((UINTN) (DmiBar + R_SA_DMIBAR_LCAP_OFFSET)) & (BIT3 | BIT2 | BIT1 | BIT0));
+ MmioAndThenOr32 ((UINTN) (DmiBar + R_SA_DMIBAR_LCTL2_OFFSET), (UINT32)~(BIT3 | BIT2 | BIT1 | BIT0), Data32Or);
+
+ ///
+ /// Retrain link
+ ///
+ DmiLinkTrain (DmiBar);
+
+ ///
+ /// Retrain link if it is GEN2 Capable and it is not yet set to GEN2
+ ///
+ if (DmiGen2Enable &&
+ ((((MmioRead16 ((UINTN) (DmiBar + R_SA_DMIBAR_LSTS_OFFSET))) & 0x0F) != DMI_GEN2) ||
+ (((MmioRead16 ((UINTN) PchPlatformPolicyPpi->Rcba + R_PCH_RCRB_LSTS)) & 0x0F) != DMI_GEN2))
+ ) {
+ DEBUG ((EFI_D_INFO, "DMI Link re-train to set GEN2\n"));
+ DmiLinkTrain (DmiBar);
+ }
+ ///
+ /// Get the current link status
+ ///
+ LinkStatus = MmioRead16 ((UINTN) (DmiBar + R_SA_DMIBAR_LSTS_OFFSET));
+ DEBUG ((EFI_D_INFO, "DMI trained to x%d at Gen%d\n", (LinkStatus >> 4) & 0x3F, LinkStatus & 0x0F));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ DMI link training
+
+ @param[in] DmiBar - DMIBAR address
+**/
+VOID
+DmiLinkTrain (
+ IN UINT64 DmiBar
+ )
+{
+ ///
+ /// Retrain link
+ ///
+ MmioOr8 ((UINTN) (DmiBar + R_SA_DMIBAR_LCTL_OFFSET), BIT5);
+
+ ///
+ /// Wait for link training complete
+ ///
+ while ((MmioRead16 ((UINTN) (DmiBar + R_SA_DMIBAR_LSTS_OFFSET)) & BIT11) != 0)
+ ;
+}
+
+/**
+ Additional DMI Programming Steps at PEI
+
+ @param[in] SaPlatformPolicyPpi - pointer to SA_PLATFORM_POLICY_PPI
+ @param[in] MchBar - MCHBAR address
+ @param[in] DmiBar - DMIBAR address
+**/
+VOID
+AdditionalDmiProgramSteps (
+ IN SA_PLATFORM_POLICY_PPI *SaPlatformPolicyPpi,
+ IN UINT32 MchBar,
+ IN UINT32 DmiBar
+ )
+{
+ UINT32 Data32And;
+ UINT32 Data32Or;
+
+ ///
+ /// Disable DMI and PEG Debug Align Message - set 0x258[29] = '1b'
+ ///
+ Data32And = (UINT32) ~BIT29;
+ Data32Or = BIT29;
+ Mmio32AndThenOr (DmiBar, R_SA_DMIBAR_CFG4_OFFSET, Data32And, Data32Or);
+
+ ///
+ /// Overwrite DMICC (DMIBAR offset 0x208) to 0x6B5
+ ///
+ Data32And = (UINT32)~(BIT10 | BIT9 | BIT8 | BIT7 | BIT6 | BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0);
+ Data32Or = 0x6B5;
+ Mmio32AndThenOr (DmiBar, R_SA_DMIBAR_DMICC_OFFSET, Data32And, Data32Or);
+
+ ///
+ /// Set L0SLAT[15:0] to 0x2020
+ ///
+ Data32And = (UINT32) ~(0xFFFF);
+ Data32Or = 0x00002020;
+ Mmio32AndThenOr (DmiBar, R_SA_DMIBAR_L0SLAT_OFFSET, Data32And, Data32Or);
+}
+#endif // DMI_FLAG