diff options
author | raywu <raywu0301@gmail.com> | 2018-06-15 00:00:50 +0800 |
---|---|---|
committer | raywu <raywu0301@gmail.com> | 2018-06-15 00:00:50 +0800 |
commit | b7c51c9cf4864df6aabb99a1ae843becd577237c (patch) | |
tree | eebe9b0d0ca03062955223097e57da84dd618b9a /ReferenceCode/ME/PchMeUma/PchMeUma.c | |
download | zprj-b7c51c9cf4864df6aabb99a1ae843becd577237c.tar.xz |
Diffstat (limited to 'ReferenceCode/ME/PchMeUma/PchMeUma.c')
-rw-r--r-- | ReferenceCode/ME/PchMeUma/PchMeUma.c | 765 |
1 files changed, 765 insertions, 0 deletions
diff --git a/ReferenceCode/ME/PchMeUma/PchMeUma.c b/ReferenceCode/ME/PchMeUma/PchMeUma.c new file mode 100644 index 0000000..dd8b51b --- /dev/null +++ b/ReferenceCode/ME/PchMeUma/PchMeUma.c @@ -0,0 +1,765 @@ +/** @file + Framework PEIM to PchMeUma + +@copyright + Copyright (c) 2010 - 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 + +**/ + +// +// Statements that include other files +// +#include "EdkIIGluePeim.h" +#include "MeAccess.h" +#include "HeciRegs.h" +#include "Pci22.h" +#include "PchMeUma.h" +#include "PchPlatformLib.h" +#include "PttHciDeviceLib.h" +#include "PttHciRegs.h" +#include EFI_PPI_DEFINITION (PchMeUma) +#ifdef PTT_FLAG +#include EFI_PPI_DEFINITION (MePlatformPolicyPei) +#endif +#include EFI_PPI_DEFINITION (Stall) +#include EFI_PPI_CONSUMER (Wdt) + +// +// Function Declarations +// +static PCH_ME_UMA_PPI mPchMeUmaPpi = { + MeSendUmaSize, + CpuReplacementCheck, + MeConfigDidReg, + HandleMeBiosAction +}; + +static EFI_PEI_PPI_DESCRIPTOR mPchMeUmaPpiList[] = { + { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gPchMeUmaPpiGuid, + &mPchMeUmaPpi + } +}; + +/** + This procedure will read and return the amount of ME UMA requested + by ME ROM from the HECI device. + + @param[in] PeiServices General purpose services available to every PEIM. + @param[in] FfsHeader Pointer to the FFS file header + + @retval UINT32 Return ME UMA Size + @retval EFI_SUCCESS Do not check for ME UMA +**/ +UINT32 +MeSendUmaSize ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_FFS_FILE_HEADER *FfsHeader + ) +{ + UINT32 Timeout; + HECI_MISC_SHDW_REGISTER MeMiscShdw; + HECI_FWS_REGISTER MeHfs; + EFI_STATUS Status; + PEI_STALL_PPI *StallPpi; + + MeMiscShdw.ul = HeciPciRead32 (R_ME_MISC_SHDW); + MeHfs.ul = HeciPciRead32 (R_ME_HFS); + Timeout = 0x0; + + if (MeHfs.r.MeOperationMode == ME_OPERATION_MODE_DEBUG) { + DEBUG ((EFI_D_INFO, "ME debug mode, do not check for ME UMA. \n")); + return EFI_SUCCESS; + } + + if (MeHfs.r.ErrorCode != 0) { + DEBUG ((EFI_D_INFO, "ME error, do not check for ME UMA. \n")); + return EFI_SUCCESS; + } + /// + /// Poll on MUSZV until it indicates a valid size is present or 5s timeout expires. + /// + Status = (*PeiServices)->LocatePpi (PeiServices, &gPeiStallPpiGuid, 0, NULL, (VOID **) &StallPpi); + ASSERT_PEI_ERROR (PeiServices, Status); + + PERF_START_EX (FfsHeader, L"MUSZV", NULL, AsmReadTsc (), 0x4000); + while ((MeMiscShdw.r.MUSZV == 0) && (Timeout < MUSZV_TIMEOUT_MULTIPLIER)) { + StallPpi->Stall (PeiServices, StallPpi, STALL_1_MILLISECOND); + MeMiscShdw.ul = HeciPciRead32 (R_ME_MISC_SHDW); + Timeout++; + } + + if (Timeout >= MUSZV_TIMEOUT_MULTIPLIER) { + DEBUG ((EFI_D_INFO, "Timeout occurred waiting for MUSZV. \n")); + return EFI_SUCCESS; + } + PERF_END_EX (FfsHeader, L"MUSZV", NULL, AsmReadTsc (), 0x4001); + + /// + /// Return MeUmaSize value + /// + DEBUG ((EFI_D_INFO, "ME UMA Size Requested: %x\n", MeMiscShdw.r.MUSZ)); + + return MeMiscShdw.r.MUSZ; +} + +/** + Init and Install ME Hob + + @param[in] PeiServices General purpose services available to every PEIM. + + @retval EFI_SUCCESS +**/ +EFI_STATUS +InstallMeHob ( + IN EFI_PEI_SERVICES **PeiServices + ) +{ + EFI_STATUS Status; + ME_DATA_HOB *MeDataHob; + + /// + /// Create HOB for ME Data + /// + Status = (**PeiServices).CreateHob ( + PeiServices, + EFI_HOB_TYPE_GUID_EXTENSION, + sizeof (ME_DATA_HOB), + &MeDataHob + ); + ASSERT_EFI_ERROR (Status); + + /// + /// Initialize default HOB data + /// + MeDataHob->EfiHobGuidType.Name = gMeDataHobGuid; + ZeroMem (&(MeDataHob->FtpmBufferAddress), sizeof (UINT64)); + + DEBUG ((EFI_D_INFO, "ME Data HOB installed\n")); + + return EFI_SUCCESS; +} + +#ifdef PTT_FLAG +/** + Internal function performing Heci platform ME Debug Dump in PEI phase + + @param[in] PeiMePolicyPpi Policy Ppi + + @retval None +**/ +VOID +DumpMePlatformPolicyPei ( + IN PEI_ME_PLATFORM_POLICY_PPI *PeiMePolicyPpi + ) +{ + DEBUG ((EFI_D_INFO, "\n------------------------ MePlatformPolicyPpi Dump Begin -----------------\n")); + DEBUG ((EFI_D_INFO, " Revision : 0x%x\n", PeiMePolicyPpi->Revision)); + DEBUG ((EFI_D_INFO, " FTpmSwitch : 0x%x\n", PeiMePolicyPpi->FTpmSwitch)); + DEBUG ((EFI_D_INFO, "\n------------------------ MePlatformPolicyPpi Dump End -------------------\n")); +} +#endif + +/** + This procedure will determine whether or not the CPU was replaced + during system power loss or via dynamic fusing. + Calling this procedure could result in a warm reset (if ME FW is requesting one). + + @param[in] PeiServices General purpose services available to every PEIM. + @param[in] FfsHeader Not used. + @param[out] ForceFullTraining When set = 0x1, MRC will be forced to perform a full + memory training cycle. + + @retval EFI_SUCCESS The function completed successfully. +**/ +EFI_STATUS +CpuReplacementCheck ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_FFS_FILE_HEADER *FfsHeader, + OUT UINT8 *ForceFullTraining + ) +{ + HECI_GS_SHDW_REGISTER MeFwsts2; + EFI_STATUS Status; + UINT32 Timeout; + PEI_STALL_PPI *StallPpi; + Status = EFI_SUCCESS; + Timeout = 0x0; + + /// + /// Read ME FWS2 + /// + MeFwsts2.ul = HeciPciRead32 (R_ME_GS_SHDW); + DEBUG ((EFI_D_INFO, "MeFwsts2 = %x.\n", MeFwsts2.r)); + + /// + /// Locate Stall Ppi + /// + Status = (*PeiServices)->LocatePpi (PeiServices, &gPeiStallPpiGuid, 0, NULL, (VOID **) &StallPpi); + ASSERT_PEI_ERROR (PeiServices, Status); + + PERF_START_EX (FfsHeader, L"CPURLOP", NULL, AsmReadTsc (), 0x4010); + /// + /// Poll 50 ms on CPU Replaced Valid bit + /// + while ((((MeFwsts2.r.CpuReplacedValid == 0) && Timeout < CPURV_TIMEOUT_MULTIPLIER)) + ) { + StallPpi->Stall (PeiServices, StallPpi, STALL_1_MILLISECOND); + MeFwsts2.ul = HeciPciRead32 (R_ME_GS_SHDW); + Timeout++; + } + PERF_END_EX (FfsHeader, L"CPURLOP", NULL, AsmReadTsc (), 0x4011); + + DEBUG ((EFI_D_INFO, "CpuReplacedValid = %x, ", MeFwsts2.r.CpuReplacedValid)); + DEBUG ((EFI_D_INFO, "CpuReplacedStatus = %x, ", MeFwsts2.r.CpuReplacedSts)); + DEBUG ((EFI_D_INFO, "WarmRstReqForDF = %x.\n", MeFwsts2.r.WarmRstReqForDF)); + + if (Timeout >= CPURV_TIMEOUT_MULTIPLIER || MeFwsts2.r.CpuReplacedValid == 0x0) { + DEBUG ((EFI_D_ERROR, "Timeout occurred, the CPU Replacement Valid Bit is not set.\n")); + *ForceFullTraining = 0x1; + } else { + if (MeFwsts2.r.CpuReplacedValid == 0x1) { + if (MeFwsts2.r.WarmRstReqForDF == 0x1) { + /// + /// Clear DISB and Issue a Non-Power Cycle Reset + /// + Status = ClearDisb (); + Status = PerformReset (PeiServices, CBM_DIR_NON_PCR); + } + + if ((MeFwsts2.r.CpuReplacedSts == 0x1 && MeFwsts2.r.WarmRstReqForDF == 0x0)) { + *ForceFullTraining = 0x1; + } + } + } + + return Status; +} + +/** + This procedure will configure the ME Host General Status register, + indicating that DRAM Initialization is complete and ME FW may + begin using the allocated ME UMA space. + + @param[in] PeiServices General purpose services available to every PEIM. + @param[in] FfsHeader Pointer to the FFS file header + @param[in] MrcBootMode MRC BootMode + @param[in] InitStat H_GS[27:24] Status + @param[in] FtpmStolenBase The base of FTPM + @retval EFI_SUCCESS +**/ +EFI_STATUS +MeConfigDidReg ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN MRC_BOOT_MODE_T MrcBootMode, + IN UINT8 InitStat, + IN UINT32 FtpmStolenBase, + IN UINT32 MeUmaSize + ) +{ + UINT32 MeUmaBase; + UINT32 MeUmaBaseExt; + UINT32 MeHgs; + UINT32 Timeout; + HECI_FWS_REGISTER MeHfs; + EFI_STATUS Status; + PEI_STALL_PPI *StallPpi; +#ifdef PTT_FLAG + PEI_ME_PLATFORM_POLICY_PPI *PeiMePolicyPpi; + EFI_GUID gPeiMePlatformPolicyPpiGuid = PEI_ME_PLATFORM_POLICY_PPI_GUID; + ME_DATA_HOB *MeDataHob; + EFI_GUID gMeDataHobGuid = ME_DATA_HOB_GUID; + UINT32 RegRead; + UINT32 WaitTime; +#endif //PTT_FLAG + +#ifdef PTT_FLAG + /// + /// Get platform policy settings through the MePlatformPolicy PPI + /// + Status = (**PeiServices).LocatePpi ( + PeiServices, + &gPeiMePlatformPolicyPpiGuid, + 0, + NULL, + (VOID **) &PeiMePolicyPpi + ); + ASSERT_PEI_ERROR (PeiServices, Status); + + DumpMePlatformPolicyPei (PeiMePolicyPpi); +#endif //PTT_FLAG + + + Status = (*PeiServices)->LocatePpi (PeiServices, &gPeiStallPpiGuid, 0, NULL, (VOID **) &StallPpi); + ASSERT_PEI_ERROR (PeiServices, Status); + + MeHgs = 0x0; + Timeout = 0x0; + MeHfs.ul = HeciPciRead32 (R_ME_HFS); + + DEBUG ((EFI_D_INFO, "ME status: 0x%08x\n", MeHfs.ul)); + + if (MeHfs.r.MeOperationMode == ME_OPERATION_MODE_DEBUG) { + DEBUG ((EFI_D_INFO, "ME debug mode, do not check for ME UMA. \n")); + return EFI_SUCCESS; + } + + if (MeHfs.r.ErrorCode != 0) { + DEBUG ((EFI_D_INFO, "ME error, do not check for ME UMA. \n")); + return EFI_SUCCESS; + } + + DEBUG ((EFI_D_INFO, "Entered ME DRAM Init Done procedure.\n")); + +#ifdef PTT_FLAG + if ((GetPchSeries() == PchLp) && + (MmioRead32 (R_PTT_HCI_BASE_ADDRESS + R_PTT_HCI_STS)& BIT0) && + (PeiMePolicyPpi->FTpmSwitch == 0) && + (InitStat != 0x1)) { + /// + /// Install ME HOBs + /// + InstallMeHob (PeiServices); + + MeDataHob = NULL; + MeDataHob = GetFirstGuidHob (&gMeDataHobGuid); + + if (MeDataHob != NULL) { + MeDataHob->FtpmBufferAddress = FtpmStolenBase; + DEBUG ((EFI_D_INFO, " Ftpm Allocated Buffer Address: %x\n", MeDataHob->FtpmBufferAddress )); + + /// + /// Poll Ready Bit + /// + RegRead = 0; + for (WaitTime = 0; WaitTime < PTT_HCI_TIMEOUT_B * 3; WaitTime += PTT_HCI_POLLING_PERIOD){ + RegRead = MmioRead32 (R_PTT_HCI_BASE_ADDRESS + R_PTT_HCI_STS); + DEBUG ((EFI_D_INFO, " Ftpm Waiting on Ready Bit, HCI_STS Register = %x\n", RegRead)); + if((BIT1 & RegRead) != 0){ + MmioWrite64 ((UINTN)(R_PTT_HCI_BASE_ADDRESS + R_PTT_HCI_CRB),(UINTN) MeDataHob->FtpmBufferAddress ); + /// + /// Issue command to start. + /// + MmioWrite32 ((UINTN)R_PTT_HCI_BASE_ADDRESS + R_PTT_HCI_CA_START, V_PTT_HCI_BUFFER_ADDRESS_RDY); + if( MeUmaSize == 32 ) + { + /// + /// Trigger interrupt command processing only for 5MB sku + /// + MmioWrite32 ((UINTN)R_PTT_HCI_BASE_ADDRESS + R_PTT_HCI_CMD, 0); + } + break; + } + StallPpi->Stall (PeiServices, StallPpi, PTT_HCI_POLLING_PERIOD); + } + + /// + /// Poll state, wait for Ftpm to finish processing + /// + for (WaitTime = 0; WaitTime < PTT_HCI_TIMEOUT_B; WaitTime += PTT_HCI_POLLING_PERIOD){ + RegRead = MmioRead32 (R_PTT_HCI_BASE_ADDRESS + R_PTT_HCI_CA_START); + if (RegRead == 0){ + break; + } + StallPpi->Stall (PeiServices, StallPpi, PTT_HCI_POLLING_PERIOD); + } + } else { + DEBUG ((EFI_D_INFO, "ME DataHob error, MeDataHob not found\n")); + } + } +#endif + + /// + /// Read MESEGBASE value + /// + MeUmaBase = PciRead32 (PCI_LIB_ADDRESS (0, 0, 0, R_MESEG_BASE)); + MeUmaBaseExt = PciRead32 (PCI_LIB_ADDRESS (0, 0, 0, R_MESEG_BASE + 0x04)); + DEBUG ((EFI_D_INFO, " MeUmaBase read: %x\n", MeUmaBase)); + + /// + /// Write DRAM Init Done (DID) data to the ME H_GS[23:0]. + /// H_GS[23:16] = extended UMA base address (reserved) + /// H_GS[15:0] = 1M aligned UMA base address + /// ME FW will 0 extend these values to determine MeUmaBase + /// + MeUmaBase = ((MeUmaBaseExt << 28) + (MeUmaBase >> 4)) >> 16; + MeHgs = MeUmaBase; + + /// + /// Set H_GS[31:28] = 0x1 indicating DRAM Init Done + /// + MeHgs |= B_ME_DID_TYPE_MASK; + + /// + /// RapidStart + /// + if (InitStat & 0x80) { + MeHgs |= B_ME_DID_RAPID_START_BIT; + } + + InitStat &= 0x7F; + + /// + /// Set H_GS[27:24] = Status + /// 0x0 = Success + /// 0x1 = No Memory in channels + /// 0x2 = Memory Init Error + /// 0x3 = Memory not preserved across reset + /// 0x4-0xF = Reserved + /// + MeHgs |= (InitStat << 24); + + PERF_START_EX (FfsHeader, L"DID", NULL, AsmReadTsc (), 0x4020); + HeciPciAndThenOr32 (R_ME_H_GS, 0, MeHgs); + DEBUG ((EFI_D_INFO, " ME H_GS written: %x\n", MeHgs)); + + /// + /// ME FW typically responds with the DID ACK w/in 1ms + /// Adding short delay to avoid wasting time in the timeout loop + /// + StallPpi->Stall (PeiServices, StallPpi, STALL_1_MILLISECOND + STALL_100_MICROSECONDS); + + /// + /// Read the ME H_FS Register to look for DID ACK. + /// + MeHfs.ul = HeciPciRead32 (R_ME_HFS); + DEBUG ((EFI_D_INFO, " HFS read before DID ACK: %x\n", MeHfs.r)); + + /// + /// ~5 second Timeout for DID ACK + /// + while (((MeHfs.r.BiosMessageAck == 0) && Timeout < DID_TIMEOUT_MULTIPLIER) + ) { + StallPpi->Stall (PeiServices, StallPpi, STALL_1_MILLISECOND); + MeHfs.ul = HeciPciRead32 (R_ME_HFS); + Timeout++; + } + + if ((Timeout >= DID_TIMEOUT_MULTIPLIER) + ) { + DEBUG ((EFI_D_ERROR, "Timeout occurred waiting for DID ACK.\n")); + } else { + DEBUG ((EFI_D_INFO, "ME DRAM Init Done ACK received.\n")); + DEBUG ((EFI_D_INFO, "HFS read after DID ACK: %x\n", MeHfs.r)); + } + PERF_END_EX (FfsHeader, L"DID", NULL, AsmReadTsc (), 0x4021); + + DEBUG ((EFI_D_ERROR, "BiosAction = %x\n", MeHfs.r.AckData)); + + return HandleMeBiosAction (PeiServices, MrcBootMode, (UINT8) MeHfs.r.AckData); +} + +/** + This procedure will enforce the BIOS Action that was requested by ME FW + as part of the DRAM Init Done message. + + @param[in] PeiServices General purpose services available to every PEIM. + @param[in] MrcBootMode MRC BootMode + @param[in] BiosAction Me requests BIOS to act + + @retval EFI_SUCCESS Always return EFI_SUCCESS +**/ +EFI_STATUS +HandleMeBiosAction ( + IN EFI_PEI_SERVICES **PeiServices, + IN MRC_BOOT_MODE_T MrcBootMode, + IN UINT8 BiosAction + ) +{ + EFI_STATUS Status; + HECI_GS_SHDW_REGISTER MeFwsts2; + /// + /// Read ME FWS2 + /// + MeFwsts2.ul = HeciPciRead32 (R_ME_GS_SHDW); + DEBUG ((EFI_D_INFO, "MeFwsts2 = %x.\n", MeFwsts2.r)); + + switch (BiosAction) { + case 0: + /// + /// Case: DID ACK was not received + /// + DEBUG ((EFI_D_ERROR, "DID Ack was not received, no BIOS Action to process.\n")); + break; + + case CBM_DIR_NON_PCR: + /// + /// Case: Perform Non-Power Cycle Reset + /// + DEBUG ((EFI_D_ERROR, "ME FW has requested a Non-PCR.\n")); + Status = PerformReset (PeiServices, CBM_DIR_NON_PCR); + break; + + case CBM_DIR_PCR: + /// + /// Case: Perform Power Cycle Reset + /// + DEBUG ((EFI_D_ERROR, "ME FW has requested a PCR.\n")); + Status = PerformReset (PeiServices, CBM_DIR_PCR); + break; + + case 3: + /// + /// Case: Go To S3 + /// + DEBUG ((EFI_D_INFO, "ME FW DID ACK has requested entry to S3. Not defined, continuing to POST.\n")); + break; + + case 4: + /// + /// Case: Go To S4 + /// + DEBUG ((EFI_D_INFO, "ME FW DID ACK has requested entry to S4. Not defined, continuing to POST.\n")); + break; + + case 5: + /// + /// Case: Go To S5 + /// + DEBUG ((EFI_D_INFO, "ME FW DID ACK has requested entry to S5. Not defined, continuing to POST.\n")); + break; + + case CBM_DIR_GLOBAL_RESET: + /// + /// Case: Perform Global Reset + /// + DEBUG ((EFI_D_ERROR, "ME FW has requested a Global Reset.\n")); + Status = PerformReset (PeiServices, CBM_DIR_GLOBAL_RESET); + break; + + case CBM_DIR_CONTINUE_POST: + /// + /// Case: Continue to POST + /// + DEBUG ((EFI_D_INFO, "ME FW DID Ack requested to continue to POST.\n")); + break; + } + + return EFI_SUCCESS; +} + +/** + This procedure will issue a Non-Power Cycle, Power Cycle, or Global Rest. + + @param[in] PeiServices General purpose services available to every PEIM. + @param[in] ResetType Type of reset to be issued. + + @retval EFI_SUCCESS The function completed successfully. + @retval All other error conditions encountered result in an ASSERT. +**/ +EFI_STATUS +PerformReset ( + IN EFI_PEI_SERVICES **PeiServices, + UINT8 ResetType + ) +{ + EFI_STATUS Status; + UINT32 ETR3; + UINT32 GpioBase; + UINT8 Reset; + WDT_PPI *Wdt; + PCH_SERIES PchSeries; + + ETR3 = 0; + Reset = 0; + GpioBase = 0; + Wdt = NULL; + PchSeries = GetPchSeries(); + + /// + /// Locate WDT PPI for access to Wdt->AllowKnownReset() + /// + Status = (*PeiServices)->LocatePpi ( + PeiServices, + &gWdtPpiGuid, + 0, + NULL, + (VOID **) &Wdt + ); + ASSERT_PEI_ERROR (PeiServices, Status); + + /// + /// Clear CF9GR of PCH (B0/D31/f0 offset 0x0AC[20] = 1b) to indicate Host reset + /// Make sure CWORWRE (CF9 Without Resume Well Reset Enable) is cleared + /// + ETR3 = PciRead32 (PCI_LIB_ADDRESS (0, PCI_DEVICE_NUMBER_PCH_LPC, 0, R_PCH_LPC_PMIR)); + ETR3 = ETR3 &~BIT20; + ETR3 = ETR3 &~BIT18; + PciWrite32 (PCI_LIB_ADDRESS (0, PCI_DEVICE_NUMBER_PCH_LPC, 0, R_PCH_LPC_PMIR), ETR3); + + Reset = IoRead8 (R_PCH_RST_CNT); + Reset &= 0xF1; + + /// + /// If global reset required + /// + if (ResetType == CBM_DIR_GLOBAL_RESET) { + /// + /// Get GPIO Base Address + /// + GpioBase = PciRead32 (PCI_LIB_ADDRESS (0, PCI_DEVICE_NUMBER_PCH_LPC, 0, R_PCH_LPC_GPIO_BASE)) &~BIT0; + } + + switch (ResetType) { + case CBM_DIR_NON_PCR: + /// + /// Case: Non Power Cycle Reset requested + /// + DEBUG ((EFI_D_ERROR, "ME FW DID ACK has requested a Non Power Cycle Reset.\n")); + Reset |= 0x06; + break; + + case CBM_DIR_PCR: + /// + /// Case: Power Cycle Reset requested + /// + Wdt->ReloadAndStart (2); + DEBUG ((EFI_D_INFO, "ME FW DID ACK has requested a Power Cycle Reset.\n")); + Reset |= 0x0E; + break; + + case CBM_DIR_GLOBAL_RESET: + /// + /// Case: Global Reset + /// + DEBUG ((EFI_D_ERROR, "ME FW DID Ack requested a global reset.\n")); + + /// + /// Drive GPIO[30] (SPDNA#) low prior to 0xCF9 write + /// + if (PchSeries == PchH) { + /// 1. Set GPIOBASE + offset 00h[30] = 1b (for non-Deep Sx enabled platforms) + /// 2. Set GPIOBASE + offset 04h[30] = 0b (for non-Deep Sx enabled platforms) + /// 3. Set GPIOBASE + offset 0Ch[30] = 0b (for non-Deep Sx enabled platforms) + /// 4. Set GPIOBASE + offset 60h[30] = 1b (for non-Deep Sx enabled platforms) + /// NOTE: For Deep Sx enabled platforms steps 1,2 and 3 should be skipped and pin should be left in native mode + /// 5. Set CF9GR bit, D31:F0:ACh[20], issue a Global Reset through a 0xCF9 write of either 06h or 0Eh commands. + /// Global Reset MEI Message + /// 1. BIOS makes sure GPIO30 is left in native mode (default mode) before sending a Global Reset MEI message. + /// + IoOr32 ((UINTN) (GpioBase + R_PCH_GPIO_USE_SEL), (UINT32) (BIT30)); + IoAnd32 ((UINTN) (GpioBase + R_PCH_GPIO_IO_SEL), (UINT32) (~BIT30)); + IoAnd32 ((UINTN) (GpioBase + R_PCH_GPIO_LVL), (UINT32) (~BIT30)); + } + + if (PchSeries == PchLp) { + /// 1. Set GPIOBASE + offset 1F0h[0] = 1b (for non-Deep Sx enabled platforms) + /// 2. Set GPIOBASE + offset 1F0h[2] = 0b (for non-Deep Sx enabled platforms) + /// 3. Set GPIOBASE + offset 1F0h[31] = 0b (for non-Deep Sx enabled platforms) + /// 4. Set GPIOBASE + offset 60h[30] = 1h (for non-Deep Sx enabled platforms) + /// NOTE: For Deep Sx enabled platforms steps 1,2 and 3 should be skipped and pin should be left in native mode + /// 5. Set CF9GR bit, D31:F0:ACh[20], issue a Global Reset through a 0xCF9 write of either 06h or 0Eh commands. + /// Global Reset MEI Message + /// 1. BIOS makes sure GPIO30 is left in native mode (default mode) before sending a Global Reset MEI message. + /// + IoOr32 ((UINTN) (GpioBase + R_PCH_GP_30_CONFIG0), (UINT32) (B_PCH_GPIO_OWN0_GPIO_USE_SEL)); + IoAnd32 ((UINTN) (GpioBase + R_PCH_GP_30_CONFIG0), (UINT32) (~B_PCH_GPIO_OWN0_GPIO_IO_SEL)); + IoAnd32 ((UINTN) (GpioBase + R_PCH_GP_30_CONFIG0), (UINT32) (~B_PCH_GPIO_OWN0_GPO_LVL)); + } + + IoOr32 ((UINTN) (GpioBase + R_PCH_GP_RST_SEL), (UINT32) (BIT30)); + + PciOr32 ( + PCI_LIB_ADDRESS (DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_PMIR), + (UINT32) (B_PCH_LPC_PMIR_CF9GR) + ); + + /// + /// Issue global reset CF9 = 0x0E + /// + DEBUG ((EFI_D_ERROR, "Issuing global reset.\n")); + Reset |= 0x0E; + break; + } + /// + /// Write PCH RST CNT, Issue Reset + /// + Wdt->AllowKnownReset (); + + IoWrite8 (R_PCH_RST_CNT, Reset); + + return EFI_SUCCESS; +} + +/** + This procedure will clear the DISB. + + @param[in] None + + @retval EFI_SUCCESS Always return EFI_SUCCESS +**/ +EFI_STATUS +ClearDisb ( + VOID + ) +{ + UINT16 Data16; + + Data16 = PciRead16 (PCI_LIB_ADDRESS (0, PCI_DEVICE_NUMBER_PCH_LPC, 0, R_PCH_LPC_GEN_PMCON_2)); + Data16 = Data16 &~B_PCH_LPC_GEN_PMCON_DRAM_INIT; + PciWrite16 (PCI_LIB_ADDRESS (0, PCI_DEVICE_NUMBER_PCH_LPC, 0, R_PCH_LPC_GEN_PMCON_2), Data16); + + return EFI_SUCCESS; +} + +/** + This procedure will clear the DISB. + + @param[in] None + + @retval EFI_SUCCESS Always return EFI_SUCCESS +**/ +EFI_STATUS +SetDISB ( + VOID + ) +{ + UINT16 Data16; + + Data16 = PciRead16 (PCI_LIB_ADDRESS (0, PCI_DEVICE_NUMBER_PCH_LPC, 0, R_PCH_LPC_GEN_PMCON_2)); + Data16 = Data16 & B_PCH_LPC_GEN_PMCON_DRAM_INIT; + PciWrite16 (PCI_LIB_ADDRESS (0, PCI_DEVICE_NUMBER_PCH_LPC, 0, R_PCH_LPC_GEN_PMCON_2), Data16); + + return EFI_SUCCESS; +} + +/** + This function is the entry point for this PEI. + + @param[in] FfsHeader Pointer to the FFS file header + @param[in] PeiServices Pointer to the PEI services table + + @retval Return Status based on errors that occurred while waiting for time to expire. +**/ +EFI_STATUS +EFIAPI +PchMeUmaEntry ( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_PEI_SERVICES **PeiServices + ) +{ + EFI_STATUS Status; + Status = EFI_SUCCESS; + Status = (*PeiServices)->InstallPpi (PeiServices, mPchMeUmaPpiList); + + return Status; +} |