From 3cbfba02fef9dae07a041fdbf2e89611d72d6f90 Mon Sep 17 00:00:00 2001 From: David Wei Date: Mon, 12 Jan 2015 09:37:20 +0000 Subject: Upload BSD-licensed Vlv2TbltDevicePkg and Vlv2DeviceRefCodePkg to https://svn.code.sf.net/p/edk2/code/trunk/edk2/, which are for MinnowBoard MAX open source project. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: David Wei Reviewed-by: Mike Wu Reviewed-by: Hot Tian git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@16599 6f19259b-4bc3-4df7-8a09-765794883524 --- Vlv2TbltDevicePkg/PlatformPei/BootMode.c | 403 +++++++++ Vlv2TbltDevicePkg/PlatformPei/CommonHeader.h | 65 ++ Vlv2TbltDevicePkg/PlatformPei/MemoryCallback.c | 160 ++++ Vlv2TbltDevicePkg/PlatformPei/Platform.c | 1063 ++++++++++++++++++++++++ Vlv2TbltDevicePkg/PlatformPei/Platform.h | 216 +++++ Vlv2TbltDevicePkg/PlatformPei/PlatformPei.inf | 136 +++ Vlv2TbltDevicePkg/PlatformPei/Stall.c | 95 +++ 7 files changed, 2138 insertions(+) create mode 100644 Vlv2TbltDevicePkg/PlatformPei/BootMode.c create mode 100644 Vlv2TbltDevicePkg/PlatformPei/CommonHeader.h create mode 100644 Vlv2TbltDevicePkg/PlatformPei/MemoryCallback.c create mode 100644 Vlv2TbltDevicePkg/PlatformPei/Platform.c create mode 100644 Vlv2TbltDevicePkg/PlatformPei/Platform.h create mode 100644 Vlv2TbltDevicePkg/PlatformPei/PlatformPei.inf create mode 100644 Vlv2TbltDevicePkg/PlatformPei/Stall.c (limited to 'Vlv2TbltDevicePkg/PlatformPei') diff --git a/Vlv2TbltDevicePkg/PlatformPei/BootMode.c b/Vlv2TbltDevicePkg/PlatformPei/BootMode.c new file mode 100644 index 0000000000..4d933a09db --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformPei/BootMode.c @@ -0,0 +1,403 @@ +/** @file + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + + BootMode.c + +Abstract: + + EFI PEIM to provide the platform support functionality on the Thurley. + + +--*/ +#include "CommonHeader.h" +#include "Platform.h" +#include "PlatformBaseAddresses.h" +#include "PchAccess.h" +#include "PlatformBootMode.h" +#include + +#include + +// +// Priority of our boot modes, highest priority first +// +EFI_BOOT_MODE mBootModePriority[] = { + BOOT_IN_RECOVERY_MODE, + BOOT_WITH_DEFAULT_SETTINGS, + BOOT_ON_FLASH_UPDATE, + BOOT_ON_S2_RESUME, + BOOT_ON_S3_RESUME, + BOOT_ON_S4_RESUME, + BOOT_WITH_MINIMAL_CONFIGURATION, + BOOT_ASSUMING_NO_CONFIGURATION_CHANGES, + BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS, + BOOT_WITH_FULL_CONFIGURATION, + BOOT_ON_S5_RESUME +}; + +EFI_PEI_NOTIFY_DESCRIPTOR mCapsuleNotifyList[1] = { + { + (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gPeiCapsulePpiGuid, + CapsulePpiNotifyCallback + } +}; + +BOOLEAN +GetSleepTypeAfterWakeup ( + IN CONST EFI_PEI_SERVICES **PeiServices, + OUT UINT16 *SleepType + ); + +EFI_STATUS +EFIAPI +CapsulePpiNotifyCallback ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ) +{ + EFI_STATUS Status; + EFI_BOOT_MODE BootMode; + PEI_CAPSULE_PPI *Capsule; + + Status = (*PeiServices)->GetBootMode((const EFI_PEI_SERVICES **)PeiServices, &BootMode); + ASSERT_EFI_ERROR (Status); + + if (BootMode == BOOT_ON_S3_RESUME) { + // + // Determine if we're in capsule update mode + // + Status = (*PeiServices)->LocatePpi ((const EFI_PEI_SERVICES **)PeiServices, + &gPeiCapsulePpiGuid, + 0, + NULL, + (VOID **)&Capsule + ); + + if (Status == EFI_SUCCESS) { + if (Capsule->CheckCapsuleUpdate ((EFI_PEI_SERVICES**)PeiServices) == EFI_SUCCESS) { + BootMode = BOOT_ON_FLASH_UPDATE; + Status = (*PeiServices)->SetBootMode((const EFI_PEI_SERVICES **)PeiServices, BootMode); + ASSERT_EFI_ERROR (Status); + } + } + } + + return Status; +} + +/** + Check CMOS register bit to determine if previous boot was successful + + @param PeiServices pointer to the PEI Service Table + + @retval TRUE - Previous Boot was success + @retval FALSE - Previous Boot wasn't success + +**/ +BOOLEAN +IsPreviousBootSuccessful( + IN CONST EFI_PEI_SERVICES **PeiServices + + ) +{ + EFI_STATUS Status; + BOOLEAN BootState; + UINTN DataSize; + CHAR16 VarName[] = BOOT_STATE_VARIABLE_NAME; + EFI_PEI_READ_ONLY_VARIABLE2_PPI *PeiVar; + + Status = (**PeiServices).LocatePpi ( + PeiServices, + &gEfiPeiReadOnlyVariable2PpiGuid, + 0, + NULL, + (void **)&PeiVar + ); + ASSERT_EFI_ERROR (Status); + + // + // Get last Boot State Variable to confirm that it is not a first boot . + // + + DataSize = sizeof (BOOLEAN); + Status = PeiVar->GetVariable ( + PeiVar, + VarName, + &gEfiBootStateGuid, + NULL, + &DataSize, + &BootState + ); + if (EFI_ERROR (Status) || (BootState == TRUE)) { + return FALSE; + } + + DEBUG ((EFI_D_INFO, "Previous boot cycle successfully completed handover to OS\n")); + return TRUE; +} +#ifdef NOCS_S3_SUPPORT +EFI_STATUS +UpdateBootMode ( + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + EFI_STATUS Status; + EFI_BOOT_MODE BootMode; + UINT16 SleepType; + CHAR16 *strBootMode; + + Status = (*PeiServices)->GetBootMode(PeiServices, &BootMode); + ASSERT_EFI_ERROR (Status); + if (BootMode == BOOT_IN_RECOVERY_MODE){ + return Status; + } + + // + // Let's assume things are OK if not told otherwise + // + BootMode = BOOT_WITH_FULL_CONFIGURATION; + + if (GetSleepTypeAfterWakeup (PeiServices, &SleepType)) { + switch (SleepType) { + case V_PCH_ACPI_PM1_CNT_S3: + BootMode = BOOT_ON_S3_RESUME; + Status = (*PeiServices)->NotifyPpi (PeiServices, &mCapsuleNotifyList[0]); + ASSERT_EFI_ERROR (Status); + break; + + case V_PCH_ACPI_PM1_CNT_S4: + BootMode = BOOT_ON_S4_RESUME; + break; + + case V_PCH_ACPI_PM1_CNT_S5: + BootMode = BOOT_ON_S5_RESUME; + break; + } // switch (SleepType) + } + + if (IsFastBootEnabled (PeiServices) && IsPreviousBootSuccessful (PeiServices)) { + DEBUG ((EFI_D_INFO, "Prioritizing Boot mode to BOOT_WITH_MINIMAL_CONFIGURATION\n")); + PrioritizeBootMode (&BootMode, BOOT_WITH_MINIMAL_CONFIGURATION); + } + + switch (BootMode) { + case BOOT_WITH_FULL_CONFIGURATION: + strBootMode = L"BOOT_WITH_FULL_CONFIGURATION"; + break; + case BOOT_WITH_MINIMAL_CONFIGURATION: + strBootMode = L"BOOT_WITH_MINIMAL_CONFIGURATION"; + break; + case BOOT_ASSUMING_NO_CONFIGURATION_CHANGES: + strBootMode = L"BOOT_ASSUMING_NO_CONFIGURATION_CHANGES"; + break; + case BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS: + strBootMode = L"BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS"; + break; + case BOOT_WITH_DEFAULT_SETTINGS: + strBootMode = L"BOOT_WITH_DEFAULT_SETTINGS"; + break; + case BOOT_ON_S4_RESUME: + strBootMode = L"BOOT_ON_S4_RESUME"; + break; + case BOOT_ON_S5_RESUME: + strBootMode = L"BOOT_ON_S5_RESUME"; + break; + case BOOT_ON_S2_RESUME: + strBootMode = L"BOOT_ON_S2_RESUME"; + break; + case BOOT_ON_S3_RESUME: + strBootMode = L"BOOT_ON_S3_RESUME"; + + break; + case BOOT_ON_FLASH_UPDATE: + strBootMode = L"BOOT_ON_FLASH_UPDATE"; + break; + case BOOT_IN_RECOVERY_MODE: + strBootMode = L"BOOT_IN_RECOVERY_MODE"; + break; + default: + strBootMode = L"Unknown boot mode"; + } // switch (BootMode) + + DEBUG ((EFI_D_ERROR, "Setting BootMode to %s\n", strBootMode)); + Status = (*PeiServices)->SetBootMode(PeiServices, BootMode); + ASSERT_EFI_ERROR (Status); + + return Status; +} +#endif + +/** + Get sleep type after wakeup + + @param PeiServices Pointer to the PEI Service Table. + @param SleepType Sleep type to be returned. + + @retval TRUE A wake event occured without power failure. + @retval FALSE Power failure occured or not a wakeup. + +**/ +BOOLEAN +GetSleepTypeAfterWakeup ( + IN CONST EFI_PEI_SERVICES **PeiServices, + OUT UINT16 *SleepType + ) +{ + UINT16 Pm1Sts; + UINT16 Pm1Cnt; + UINT16 GenPmCon1; + // + // VLV BIOS Specification 0.6.2 - Section 18.4, "Power Failure Consideration" + // + // When the SUS_PWR_FLR bit is set, it indicates the SUS well power is lost. + // This bit is in the SUS Well and defaults to 1’b1 based on RSMRST# assertion (not cleared by any type of reset). + // System BIOS should follow cold boot path if SUS_PWR_FLR (PBASE + 0x20[14]), + // GEN_RST_STS (PBASE + 0x20[9]) or PWRBTNOR_STS (ABASE + 0x00[11]) is set to 1’b1 + // regardless of the value in the SLP_TYP (ABASE + 0x04[12:10]) field. + // + GenPmCon1 = MmioRead16 (PMC_BASE_ADDRESS + R_PCH_PMC_GEN_PMCON_1); + + // + // Read the ACPI registers + // + Pm1Sts = IoRead16 (ACPI_BASE_ADDRESS + R_PCH_ACPI_PM1_STS); + Pm1Cnt = IoRead16 (ACPI_BASE_ADDRESS + R_PCH_ACPI_PM1_CNT); + + if ((GenPmCon1 & (B_PCH_PMC_GEN_PMCON_SUS_PWR_FLR | B_PCH_PMC_GEN_PMCON_GEN_RST_STS)) || + (Pm1Sts & B_PCH_ACPI_PM1_STS_PRBTNOR)) { + // + // If power failure indicator, then don't attempt s3 resume. + // Clear PM1_CNT of S3 and set it to S5 as we just had a power failure, and memory has + // lost already. This is to make sure no one will use PM1_CNT to check for S3 after + // power failure. + // + if ((Pm1Cnt & B_PCH_ACPI_PM1_CNT_SLP_TYP) == V_PCH_ACPI_PM1_CNT_S3) { + Pm1Cnt = ((Pm1Cnt & ~B_PCH_ACPI_PM1_CNT_SLP_TYP) | V_PCH_ACPI_PM1_CNT_S5); + IoWrite16 (ACPI_BASE_ADDRESS + R_PCH_ACPI_PM1_CNT, Pm1Cnt); + } + // + // Clear Wake Status (WAK_STS) + // + } + // + // Get sleep type if a wake event occurred and there is no power failure + // + if ((Pm1Cnt & B_PCH_ACPI_PM1_CNT_SLP_TYP) == V_PCH_ACPI_PM1_CNT_S3) { + *SleepType = Pm1Cnt & B_PCH_ACPI_PM1_CNT_SLP_TYP; + return TRUE; + } else if ((Pm1Cnt & B_PCH_ACPI_PM1_CNT_SLP_TYP) == V_PCH_ACPI_PM1_CNT_S4) { + *SleepType = Pm1Cnt & B_PCH_ACPI_PM1_CNT_SLP_TYP; + return TRUE; + } + return FALSE; +} + +BOOLEAN +EFIAPI +IsFastBootEnabled ( + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + EFI_STATUS Status; + EFI_PEI_READ_ONLY_VARIABLE2_PPI *PeiReadOnlyVarPpi; + UINTN VarSize; + SYSTEM_CONFIGURATION SystemConfiguration; + BOOLEAN FastBootEnabledStatus; + + FastBootEnabledStatus = FALSE; + Status = (**PeiServices).LocatePpi ( + PeiServices, + &gEfiPeiReadOnlyVariable2PpiGuid, + 0, + NULL, + (void **)&PeiReadOnlyVarPpi + ); + if (Status == EFI_SUCCESS) { + VarSize = sizeof (SYSTEM_CONFIGURATION); + Status = PeiReadOnlyVarPpi->GetVariable ( + PeiReadOnlyVarPpi, + PLATFORM_SETUP_VARIABLE_NAME, + &gEfiSetupVariableGuid, + NULL, + &VarSize, + &SystemConfiguration + ); + if (Status == EFI_SUCCESS) { + if (SystemConfiguration.FastBoot != 0) { + FastBootEnabledStatus = TRUE; + } + } + } + + return FastBootEnabledStatus; +} + +/** + Given the current boot mode, and a proposed new boot mode, determine + which has priority. If the new boot mode has higher priority, then + make it the current boot mode. + + @param CurrentBootMode pointer to current planned boot mode + @param NewBootMode proposed boot mode + + @retval EFI_NOT_FOUND if either boot mode is not recognized + @retval EFI_SUCCESS if both boot mode values were recognized and + were processed. +**/ +EFI_STATUS +PrioritizeBootMode ( + IN OUT EFI_BOOT_MODE *CurrentBootMode, + IN EFI_BOOT_MODE NewBootMode + ) +{ + UINT32 CurrentIndex; + UINT32 NewIndex; + + // + // Find the position of the current boot mode in our priority array + // + for ( CurrentIndex = 0; + CurrentIndex < sizeof (mBootModePriority) / sizeof (mBootModePriority[0]); + CurrentIndex++) { + if (mBootModePriority[CurrentIndex] == *CurrentBootMode) { + break; + } + } + if (CurrentIndex >= sizeof (mBootModePriority) / sizeof (mBootModePriority[0])) { + return EFI_NOT_FOUND; + } + + // + // Find the position of the new boot mode in our priority array + // + for ( NewIndex = 0; + NewIndex < sizeof (mBootModePriority) / sizeof (mBootModePriority[0]); + NewIndex++) { + if (mBootModePriority[NewIndex] == NewBootMode) { + // + // If this new boot mode occurs before the current boot mode in the + // priority array, then take it. + // + if (NewIndex < CurrentIndex) { + *CurrentBootMode = NewBootMode; + } + return EFI_SUCCESS; + } + } + return EFI_NOT_FOUND; +} diff --git a/Vlv2TbltDevicePkg/PlatformPei/CommonHeader.h b/Vlv2TbltDevicePkg/PlatformPei/CommonHeader.h new file mode 100644 index 0000000000..19e26acdcf --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformPei/CommonHeader.h @@ -0,0 +1,65 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +**/ + +#ifndef __COMMON_HEADER_H_ +#define __COMMON_HEADER_H_ + + + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#endif diff --git a/Vlv2TbltDevicePkg/PlatformPei/MemoryCallback.c b/Vlv2TbltDevicePkg/PlatformPei/MemoryCallback.c new file mode 100644 index 0000000000..82954d3a50 --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformPei/MemoryCallback.c @@ -0,0 +1,160 @@ +/** @file + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + + This file includes a memory call back function notified when MRC is done, + following action is performed in this file, + 1. ICH initialization after MRC. + 2. SIO initialization. + 3. Install ResetSystem and FinvFv PPI. + 4. Set MTRR for PEI + 5. Create FV HOB and Flash HOB + + +**/ + + +#include "CommonHeader.h" +#include "Platform.h" +#include +#include +#include +#include "VlvAccess.h" + + +EFI_PEI_PPI_DESCRIPTOR mPpiListRecoveryBootMode[] = { +{ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiPeiBootInRecoveryModePpiGuid, + NULL +} +}; + +#if 0 +STATIC +EFI_STATUS +GetMemorySize ( + IN CONST EFI_PEI_SERVICES **PeiServices, + OUT UINT64 *LowMemoryLength, + OUT UINT64 *HighMemoryLength + ) +{ + EFI_STATUS Status; + EFI_PEI_HOB_POINTERS Hob; + + *HighMemoryLength = 0; + *LowMemoryLength = 0x100000; + // + // Get the HOB list for processing + // + Status = (*PeiServices)->GetHobList (PeiServices, (void **)&Hob.Raw); + if (EFI_ERROR(Status)) { + return Status; + } + + // + // Collect memory ranges + // + while (!END_OF_HOB_LIST (Hob)) { + if (Hob.Header->HobType == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) { + if (Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) { + // + // Need memory above 1MB to be collected here + // + if (Hob.ResourceDescriptor->PhysicalStart >= 0x100000 && + Hob.ResourceDescriptor->PhysicalStart < (EFI_PHYSICAL_ADDRESS) 0x100000000) { + *LowMemoryLength += (UINT64) (Hob.ResourceDescriptor->ResourceLength); + } else if (Hob.ResourceDescriptor->PhysicalStart >= (EFI_PHYSICAL_ADDRESS) 0x100000000) { + *HighMemoryLength += (UINT64) (Hob.ResourceDescriptor->ResourceLength); + } + } + } + Hob.Raw = GET_NEXT_HOB (Hob); + } + + return EFI_SUCCESS; +} + +#endif +/** + This function will be called when MRC is done. + + @param PeiServices General purpose services available to every PEIM. + @param NotifyDescriptor Information about the notify event.. + @param Ppi The notify context. + + @retval EFI_SUCCESS If the function completed successfully. +**/ +EFI_STATUS +EFIAPI +MemoryDiscoveredPpiNotifyCallback ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ) +{ + + EFI_STATUS Status; + EFI_BOOT_MODE BootMode; + UINT32 Pages; + VOID* Memory; + UINTN Size; + + // + // Allocate LM memory and configure PDM if enabled by user. + // ConfigureLM(PeiServices); + // + Status = (*PeiServices)->GetBootMode ( + (const EFI_PEI_SERVICES **)PeiServices, + &BootMode + ); + + if (BootMode != BOOT_ON_S3_RESUME) { + Size = (PcdGet32 (PcdFlashFvRecovery2Base) - PcdGet32 (PcdFlashFvMainBase)) + FixedPcdGet32(PcdFlashFvRecovery2Size); + Pages= Size/0x1000; + + Memory = AllocatePages ( Pages ); + CopyMem(Memory , (VOID *) FixedPcdGet32(PcdFlashFvMainBase) , Size); + + // + // We don't verify just load + // + PeiServicesInstallFvInfoPpi ( + NULL, + (VOID *) ((UINTN) Memory + (PcdGet32 (PcdFlashFvRecovery2Base) - PcdGet32 (PcdFlashFvMainBase))), + PcdGet32 (PcdFlashFvRecovery2Size), + NULL, + NULL + ); + + PeiServicesInstallFvInfoPpi ( + NULL, + (VOID *) Memory, + PcdGet32 (PcdFlashFvMainSize), + NULL, + NULL + ); + + } + + if (BootMode == BOOT_ON_S3_RESUME) { + PeiServicesInstallFvInfoPpi ( + NULL, + (VOID *) (UINTN) (PcdGet32 (PcdFlashFvRecovery2Base)), + PcdGet32 (PcdFlashFvRecovery2Size), + NULL, + NULL + ); + } + + return EFI_SUCCESS; +} diff --git a/Vlv2TbltDevicePkg/PlatformPei/Platform.c b/Vlv2TbltDevicePkg/PlatformPei/Platform.c new file mode 100644 index 0000000000..1dab9ca851 --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformPei/Platform.c @@ -0,0 +1,1063 @@ +/** @file + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + +**/ + +#include "CommonHeader.h" + +#include "Platform.h" +#include +#include "PlatformBaseAddresses.h" +#include "PchAccess.h" +#include +#include "Platform.h" +#include "PchCommonDefinitions.h" +#include +#include +#include + +// +// Start::Alpine Valley platform +// +enum { + SMBUS_READ_BYTE, + SMBUS_WRITE_BYTE, + SMBUS_READ_BLOCK, + SMBUS_WRITE_BLOCK +}; + +#define EC_BASE 0xE0000000 + +// +// DEVICE 0 (Memroy Controller Hub) +// +#define MC_BUS 0x00 +#define MC_DEV 0x00 +#define MC_FUN 0x00 +#define MC_DEV_FUN (MC_DEV << 3) +#define MC_BUS_DEV_FUN ((MC_BUS << 8) + MC_DEV_FUN) + +// +// SysCtl SMBus address and block size +// +#define AV_SC_SMBUS_ADDRESS 0x60 +#define AV_SC_BYTE_LEN 1 +#define AV_SC_BLOCK_LEN 4 +#define AV_SC_SMBUS_WRCMD 1 +#define AV_SC_SMBUS_RDCMD 0 + +// +// SysCtl registers offset +// +#define AV_SC_REG_PLATFORM_ID 24 // 0x18 +#define AV_SC_REG_BOARD_ID 28 // 0x1C +#define AV_SC_REG_FAB_ID 32 // 0x20 +#define AV_SC_REG_ECO_ID 68 // 0x44 +#define AV_SC_REG_DDR_DAUGHTER_CARD_ID 144 // 0x90 +#define AV_SC_REG_SODIMM_CONFIG 36 + +// +// ID values +// +#define AV_SC_PLATFORM_ID_TABLET 0 +#define AV_SC_PLATFORM_ID_NETBOOK 2 +#define AV_SC_PLATFORM_ID_INTERPOSER 3 // Configuration TBD +#define AV_SC_BOARD_ID_AV_SVP 1492 + +#define BUS_TRIES 3 // How many times to retry on Bus Errors + +#define GTT_SIZE_1MB 1 +#define GTT_SIZE_2MB 2 + +#define PciCfg16Read( PciExpressBase, Bus, Device, Function, Register ) \ + MmioRead16(PciExpressBase + \ + (UINTN)(Bus << 20) + \ + (UINTN)(Device << 15) + \ + (UINTN)(Function << 12) + \ + (UINTN)(Register)) +#define PciCfg16Write( PciExpressBase, Bus, Device, Function, Register, Data ) \ + MmioWrite16(PciExpressBase + \ + (UINTN)(Bus << 20) + \ + (UINTN)(Device << 15) + \ + (UINTN)(Function << 12) + \ + (UINTN)(Register), \ + (UINT16)Data) + + +// +//Memory Test Manufacturing mode +// +UINT32 DataPatternForMemoryTest[] = { + 0x55555555, 0xAAAAAAAA, 0x55555510, 0x555555EF, 0x55555510, 0x555555EF, 0x55555510, 0x555555EF, + 0x55555555, 0xAAAAAAAA, 0x55551055, 0x5555EF55, 0x55551055, 0x5555EF55, 0x55551055, 0x5555EF55, + 0x55555555, 0xAAAAAAAA, 0x55105555, 0x55EF5555, 0x55105555, 0x55EF5555, 0x55105555, 0x55EF5555, + 0x55555555, 0xAAAAAAAA, 0x10555555, 0xEF555555, 0x10555555, 0xEF555555, 0x10555555, 0xEF555555 +}; +#define DATA_PATTERN_ARRAY_SIZE (sizeof(DataPatternForMemoryTest) / sizeof(UINT32)) + +// +//Memory Test Manufacturing mode +// +// +// The global indicator, the FvFileLoader callback will modify it to TRUE after loading PEIM into memory +// +BOOLEAN ImageInMemory = FALSE; + +EFI_STATUS +EFIAPI +Stall ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_STALL_PPI *This, + IN UINTN Microseconds + ); + +EFI_STATUS +EFIAPI +MfgMemoryTest ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN PEI_MFG_MEMORY_TEST_PPI *This, + IN UINT32 BeginAddress, + IN UINT32 MemoryLength + ); + +static EFI_PEI_STALL_PPI mStallPpi = { + PEI_STALL_RESOLUTION, + Stall +}; + +static PEI_MFG_MEMORY_TEST_PPI mPeiMfgMemoryTestPpi = { + MfgMemoryTest +}; + +static EFI_PEI_PPI_DESCRIPTOR mInstallStallPpi[] = { + { + EFI_PEI_PPI_DESCRIPTOR_PPI, + &gEfiPeiStallPpiGuid, + &mStallPpi + }, + { + EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, + &gPeiMfgMemoryTestPpiGuid, + &mPeiMfgMemoryTestPpi + } + }; + +EFI_PEI_NOTIFY_DESCRIPTOR mMemoryDiscoveredNotifyList[1] = { + { + (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiPeiMemoryDiscoveredPpiGuid, + MemoryDiscoveredPpiNotifyCallback + } +}; + +EFI_STATUS +EFIAPI +InstallMonoStatusCode ( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN CONST EFI_PEI_SERVICES **PeiServices + ); + + +EFI_STATUS +ReadPlatformIds ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN OUT EFI_PLATFORM_INFO_HOB *PlatformInfoHob + ); + +// +// Start::Alpine Valley platform +// +EFI_STATUS +PeiSmbusExec ( + UINT16 SmbusBase, + UINT8 SlvAddr, + UINT8 Operation, + UINT8 Offset, + UINT8 *Length, + UINT8 *Buffer + ); + +/** + This routine attempts to acquire the SMBus + + @retval FAILURE as failed + @retval SUCCESS as passed + +**/ +EFI_STATUS +AcquireBus ( + UINT16 SmbusBase + ) +{ + UINT8 StsReg; + + StsReg = 0; + StsReg = (UINT8)IoRead8(SmbusBase + R_PCH_SMBUS_HSTS); + if (StsReg & B_PCH_SMBUS_IUS) { + return EFI_DEVICE_ERROR; + } else if (StsReg & B_PCH_SMBUS_HBSY) { + // + // Clear Status Register and exit + // + // Wait for HSTS.HBSY to be clear + // + do { StsReg = (UINT8) IoRead8(SmbusBase+R_PCH_SMBUS_HSTS); } while ((StsReg & B_PCH_SMBUS_HBSY) != 0); + + // + // Clear all status bits + // + IoWrite8(SmbusBase+R_PCH_SMBUS_HSTS, 0xFE); + return EFI_SUCCESS; + } else { + // + // Clear out any odd status information (Will Not Clear In Use) + // + IoWrite8(SmbusBase+R_PCH_SMBUS_HSTS, StsReg); + return EFI_SUCCESS; + } +} +// +// End::Alpine Valley platform +// + +/** + This function checks the memory range in PEI. + + @param PeiServices Pointer to PEI Services. + @param This Pei memory test PPI pointer. + @param BeginAddress Beginning of the memory address to be checked. + @param MemoryLength Bytes of memory range to be checked. + @param Operation Type of memory check operation to be performed. + @param ErrorAddress Return the address of the error memory address. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_DEVICE_ERROR Memory test failed. It's not safe to use this range of memory. + +**/ +EFI_STATUS +EFIAPI +MfgMemoryTest ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN PEI_MFG_MEMORY_TEST_PPI *This, + IN UINT32 BeginAddress, + IN UINT32 MemoryLength + ) +{ + UINT32 i; + UINT32 memAddr; + UINT32 readData; + UINT32 xorData; + UINT32 TestFlag = 0; + memAddr = BeginAddress; + + // + //Output Message for MFG + // + DEBUG ((EFI_D_ERROR, "MFGMODE SET\n")); + + // + //Writting the pattern in defined location. + // + while (memAddr < (BeginAddress+MemoryLength)) { + for (i = 0; i < DATA_PATTERN_ARRAY_SIZE; i++) { + if (memAddr > (BeginAddress+MemoryLength -4)) { + memAddr = memAddr + 4; + break; + } + *((volatile UINT32*) memAddr) = DataPatternForMemoryTest[i]; + memAddr = memAddr + 4; + } + } + + // + //Verify the pattern. + // + memAddr = BeginAddress; + while (memAddr < (BeginAddress+MemoryLength)) { + for (i = 0; i < DATA_PATTERN_ARRAY_SIZE; i++) { + if (memAddr > (BeginAddress+MemoryLength -4)) { + memAddr = memAddr + 4; + break; + } + readData = *((volatile UINT32*) memAddr); + xorData = readData ^ DataPatternForMemoryTest[i]; + + // + // If xorData is nonzero, this particular memAddr has a failure. + // + if (xorData != 0x00000000) { + DEBUG ((EFI_D_ERROR, "Expected value....: %x\n", DataPatternForMemoryTest[i])); + DEBUG ((EFI_D_ERROR, "ReadData value....: %x\n", readData)); + DEBUG ((EFI_D_ERROR, "Pattern failure at....: %x\n", memAddr)); + TestFlag = 1; + } + memAddr = memAddr + 4; + } + } + if (TestFlag) { + return EFI_DEVICE_ERROR; + } + + // + //Output Message for MFG + // + DEBUG ((EFI_D_ERROR, "MFGMODE MEMORY TEST PASSED\n")); + return EFI_SUCCESS; +} + +BOOLEAN +IsRtcUipAlwaysSet ( + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + + EFI_PEI_STALL_PPI *StallPpi; + UINTN Count; + + (**PeiServices).LocatePpi (PeiServices, &gEfiPeiStallPpiGuid, 0, NULL, (void **)&StallPpi); + + for (Count = 0; Count < 500; Count++) { // Maximum waiting approximates to 1.5 seconds (= 3 msec * 500) + IoWrite8 (R_PCH_RTC_INDEX2, R_PCH_RTC_REGISTERA); + if ((IoRead8 (R_PCH_RTC_TARGET2) & B_PCH_RTC_REGISTERA_UIP) == 0) { + return FALSE; + } + + StallPpi->Stall (PeiServices, StallPpi, 3000); + } + + return TRUE; +} + +EFI_STATUS +RtcPowerFailureHandler ( + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + + UINT16 DataUint16; + UINT8 DataUint8; + BOOLEAN RtcUipIsAlwaysSet; + DataUint16 = MmioRead16 (PMC_BASE_ADDRESS + R_PCH_PMC_GEN_PMCON_1); + RtcUipIsAlwaysSet = IsRtcUipAlwaysSet (PeiServices); + if ((DataUint16 & B_PCH_PMC_GEN_PMCON_RTC_PWR_STS) || (RtcUipIsAlwaysSet)) { + // + // Execute the sequence below. This will ensure that the RTC state machine has been initialized. + // + // Step 1. + // BIOS clears this bit by writing a '0' to it. + // + if (DataUint16 & B_PCH_PMC_GEN_PMCON_RTC_PWR_STS) { + // + // Set to invalid date in order to reset the time to + // BIOS build time later in the boot (SBRUN.c file). + // + IoWrite8 (R_PCH_RTC_INDEX2, R_PCH_RTC_YEAR); + IoWrite8 (R_PCH_RTC_TARGET2, 0x0FF); + IoWrite8 (R_PCH_RTC_INDEX2, R_PCH_RTC_MONTH); + IoWrite8 (R_PCH_RTC_TARGET2, 0x0FF); + IoWrite8 (R_PCH_RTC_INDEX2, R_PCH_RTC_DAYOFMONTH); + IoWrite8 (R_PCH_RTC_TARGET2, 0x0FF); + IoWrite8 (R_PCH_RTC_INDEX2, R_PCH_RTC_DAYOFWEEK); + IoWrite8 (R_PCH_RTC_TARGET2, 0x0FF); + + IoWrite8 (R_PCH_RTC_INDEX2, R_PCH_RTC_SECONDSALARM); + IoWrite8 (R_PCH_RTC_TARGET2, 0x00); + IoWrite8 (R_PCH_RTC_INDEX2, R_PCH_RTC_MINUTESALARM); + IoWrite8 (R_PCH_RTC_TARGET2, 0x00); + IoWrite8 (R_PCH_RTC_INDEX2, R_PCH_RTC_HOURSALARM); + IoWrite8 (R_PCH_RTC_TARGET2, 0x00); + } + + // + // Step 2. + // Set RTC Register 0Ah[6:4] to '110' or '111'. + // + IoWrite8 (R_PCH_RTC_INDEX2, R_PCH_RTC_REGISTERA); + IoWrite8 (R_PCH_RTC_TARGET2, (V_PCH_RTC_REGISTERA_DV_DIV_RST1 | V_PCH_RTC_REGISTERA_RS_976P5US)); + + // + // Step 3. + // Set RTC Register 0Bh[7]. + // + IoWrite8 (R_PCH_RTC_INDEX2, R_PCH_RTC_REGISTERB); + DataUint8 = (IoRead8 (R_PCH_RTC_TARGET2) | B_PCH_RTC_REGISTERB_SET); + IoWrite8 (R_PCH_RTC_INDEX2, R_PCH_RTC_REGISTERB); + IoWrite8 (R_PCH_RTC_TARGET2, DataUint8); + + // + // Step 4. + // Set RTC Register 0Ah[6:4] to '010'. + // + IoWrite8 (R_PCH_RTC_INDEX2, R_PCH_RTC_REGISTERA); + IoWrite8 (R_PCH_RTC_TARGET2, (V_PCH_RTC_REGISTERA_DV_NORM_OP | V_PCH_RTC_REGISTERA_RS_976P5US)); + + // + // Step 5. + // Clear RTC Register 0Bh[7]. + // + IoWrite8 (R_PCH_RTC_INDEX2, R_PCH_RTC_REGISTERB); + DataUint8 = (IoRead8 (R_PCH_RTC_TARGET2) & (UINT8)~B_PCH_RTC_REGISTERB_SET); + IoWrite8 (R_PCH_RTC_INDEX2, R_PCH_RTC_REGISTERB); + IoWrite8 (R_PCH_RTC_TARGET2, DataUint8); + } + + return EFI_SUCCESS; +} + + +VOID +PchBaseInit ( + VOID + ) +{ + // + // Program ACPI Power Management I/O Space Base Address + // + MmioWrite16 ( + MmPciAddress (0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_ACPI_BASE + ), + (UINT16)((ACPI_BASE_ADDRESS & B_PCH_LPC_ACPI_BASE_BAR) | B_PCH_LPC_ACPI_BASE_EN) + ); + + // + // Program GPIO Base Address + // + MmioWrite16 ( + MmPciAddress (0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_GPIO_BASE + ), + (UINT16)((GPIO_BASE_ADDRESS & B_PCH_LPC_GPIO_BASE_BAR) | B_PCH_LPC_GPIO_BASE_EN) + ); + + // + // Set PMC Base Address + // + MmioWrite32 ( + MmPciAddress (0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_PMC_BASE + ), + (UINT32)((PMC_BASE_ADDRESS & B_PCH_LPC_PMC_BASE_BAR) | B_PCH_LPC_PMC_BASE_EN) + ); + + // + // Set IO Base Address + // + MmioWrite32 ( + MmPciAddress (0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_IO_BASE + ), + (UINT32)((IO_BASE_ADDRESS & B_PCH_LPC_IO_BASE_BAR) | B_PCH_LPC_IO_BASE_EN) + ); + + // + // Set ILB Base Address + // + MmioWrite32 ( + MmPciAddress (0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_ILB_BASE + ), + (UINT32)((ILB_BASE_ADDRESS & B_PCH_LPC_ILB_BASE_BAR) | B_PCH_LPC_ILB_BASE_EN) + ); + + // + // Set PUnit Base Address + // + MmioWrite32 ( + MmPciAddress (0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_PUNIT_BASE + ), + (UINT32)((PUNIT_BASE_ADDRESS & B_PCH_LPC_PUNIT_BASE_BAR) | B_PCH_LPC_PUNIT_BASE_EN) + ); + + // + // Set SPI Base Address + // + MmioWrite32 ( + MmPciAddress (0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_SPI_BASE + ), + (UINT32)((SPI_BASE_ADDRESS & B_PCH_LPC_SPI_BASE_BAR) | B_PCH_LPC_SPI_BASE_EN) + ); + + // + // Set Root Complex Base Address + // + MmioWrite32 ( + MmPciAddress (0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_RCBA + ), + (UINT32)((RCBA_BASE_ADDRESS & B_PCH_LPC_RCBA_BAR) | B_PCH_LPC_RCBA_EN) + ); + + // + // Set MPHY Base Address + // + MmioWrite32 ( + MmPciAddress (0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_MPHY_BASE + ), + (UINT32)((MPHY_BASE_ADDRESS & B_PCH_LPC_MPHY_BASE_BAR) | B_PCH_LPC_MPHY_BASE_EN) + ); + MmioWrite16 ( + MmPciAddress (0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_SMBUS, + PCI_FUNCTION_NUMBER_PCH_SMBUS, + R_PCH_SMBUS_BASE + ), + (UINT16)(SMBUS_BASE_ADDRESS & B_PCH_SMBUS_BASE_BAR) + ); + + MmioOr8 ( + MmPciAddress (0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_SMBUS, + PCI_FUNCTION_NUMBER_PCH_SMBUS, + R_PCH_SMBUS_PCICMD + ), + B_PCH_SMBUS_PCICMD_IOSE + ); + +} + +/** + This is the entrypoint of PEIM + + @param FileHandle Handle of the file being invoked. + @param PeiServices Describes the list of possible PEI Services. + + @retval EFI_SUCCESS if it completed successfully. +**/ +EFI_STATUS +EFIAPI +PeiInitPlatform ( + IN EFI_PEI_FILE_HANDLE FileHandle, + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + UINTN SmbusRegBase; + EFI_PLATFORM_INFO_HOB PlatformInfo; + EFI_STATUS Status= EFI_SUCCESS; + EFI_PEI_READ_ONLY_VARIABLE2_PPI *Variable = NULL; + UINTN VariableSize; + SYSTEM_CONFIGURATION SystemConfiguration; + UINT32 GGC = 0; + + EFI_PEI_PPI_DESCRIPTOR *mVlvMmioPolicyPpiDesc; + VLV_MMIO_POLICY_PPI *mVlvMmioPolicyPpi; + + ZeroMem (&PlatformInfo, sizeof(PlatformInfo)); + + Status = InstallMonoStatusCode(FileHandle, PeiServices); + ASSERT_EFI_ERROR (Status); + + + // + // Initialize Stall PPIs + // + Status = (*PeiServices)->InstallPpi (PeiServices, &mInstallStallPpi[0]); + ASSERT_EFI_ERROR (Status); + + Status = (*PeiServices)->NotifyPpi (PeiServices, &mMemoryDiscoveredNotifyList[0]); + ASSERT_EFI_ERROR (Status); + SmbusRegBase = PchPciDeviceMmBase ( + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_SMBUS, + PCI_FUNCTION_NUMBER_PCH_SMBUS + ); + // + // Since PEI has no PCI enumerator, set the BAR & I/O space enable ourselves + // + MmioAndThenOr32 (SmbusRegBase + R_PCH_SMBUS_BASE, B_PCH_SMBUS_BASE_BAR, SMBUS_BASE_ADDRESS); + + MmioOr8 (SmbusRegBase + R_PCH_SMBUS_PCICMD, B_PCH_SMBUS_PCICMD_IOSE); + + PchBaseInit(); + + // + //Todo: confirm if we need program 8254 + // + // Setting 8254 + // Program timer 1 as refresh timer + // + IoWrite8 (0x43, 0x54); + IoWrite8 (0x41, 0x12); + + // + // RTC power failure handling + // + RtcPowerFailureHandler (PeiServices); + + + PchMmPci32( 0, 0, 2, 0, 0x50) = 0x210; + + VariableSize = sizeof (SYSTEM_CONFIGURATION); + ZeroMem (&SystemConfiguration, VariableSize); + + // + // Obtain variable services + // + Status = (*PeiServices)->LocatePpi( + PeiServices, + &gEfiPeiReadOnlyVariable2PpiGuid, + 0, + NULL, + (void **)&Variable + ); + ASSERT_EFI_ERROR(Status); + Status = Variable->GetVariable ( + Variable, + L"Setup", + &gEfiSetupVariableGuid, + NULL, + &VariableSize, + &SystemConfiguration + ); + ASSERT_EFI_ERROR(Status); + if (EFI_ERROR (Status)) { + GGC = ((2 << 3) | 0x200); + PciCfg16Write(EC_BASE, 0, 2, 0, 0x50, GGC); + GGC = PciCfg16Read(EC_BASE, 0, 2, 0, 0x50); + DEBUG((EFI_D_INFO , "GGC: 0x%08x GMSsize:0x%08x\n", GGC, (GGC & (BIT7|BIT6|BIT5|BIT4|BIT3))>>3)); + } else { + if (SystemConfiguration.Igd == 1 && SystemConfiguration.PrimaryVideoAdaptor != 2) { + GGC = (SystemConfiguration.IgdDvmt50PreAlloc << 3) | + (SystemConfiguration.GTTSize == GTT_SIZE_1MB ? 0x100: 0x200); + PciCfg16Write(EC_BASE, 0, 2, 0, 0x50, GGC); + GGC = PciCfg16Read(EC_BASE, 0, 2, 0, 0x50); + DEBUG((EFI_D_INFO , "GGC: 0x%08x GMSsize:0x%08x\n", GGC, (GGC & (BIT7|BIT6|BIT5|BIT4|BIT3))>>3)); + } + } + + // + // Initialize PlatformInfo HOB + // + Status = ReadPlatformIds(PeiServices, &PlatformInfo); + ASSERT_EFI_ERROR (Status); + + // + // 0 -> Disable , 1 -> Enable + // + if(SystemConfiguration.CfioPnpSettings == 1) { + DEBUG((EFI_D_INFO, "CheckCfioPnpSettings: CFIO Pnp Settings Enabled\n")); + PlatformInfo.CfioEnabled = 1; + } else { + DEBUG((EFI_D_INFO, "CheckCfioPnpSettings: CFIO Pnp Settings Disabled\n")); + PlatformInfo.CfioEnabled = 0; + } + + // + // Build HOB for PlatformInfo + // + BuildGuidDataHob ( + &gEfiPlatformInfoGuid, + &PlatformInfo, + sizeof (EFI_PLATFORM_INFO_HOB) + ); + + + // + // Set the new boot mode for MRC + // +#ifdef NOCS_S3_SUPPORT + Status = UpdateBootMode (PeiServices); + ASSERT_EFI_ERROR (Status); +#endif + + DEBUG((EFI_D_INFO, "Setup MMIO size ... \n\n")); + + // + // Setup MMIO size + // + Status = (*PeiServices)->AllocatePool( + PeiServices, + sizeof (EFI_PEI_PPI_DESCRIPTOR), + (void **)&mVlvMmioPolicyPpiDesc + ); + ASSERT_EFI_ERROR (Status); + Status = (*PeiServices)->AllocatePool( + PeiServices, + sizeof (VLV_MMIO_POLICY_PPI), + (void **)&mVlvMmioPolicyPpi + ); + ASSERT_EFI_ERROR (Status); + (*PeiServices)->SetMem ( + (VOID *)mVlvMmioPolicyPpi, + sizeof (VLV_MMIO_POLICY_PPI), + 0 + ); + mVlvMmioPolicyPpiDesc->Flags = EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST; + mVlvMmioPolicyPpiDesc->Guid = &gVlvMmioPolicyPpiGuid; + mVlvMmioPolicyPpiDesc->Ppi = mVlvMmioPolicyPpi; + switch (SystemConfiguration.MmioSize) { + case 0: // 768MB + mVlvMmioPolicyPpi->MmioSize = 0x300; + break; + case 1: // 1GB + mVlvMmioPolicyPpi->MmioSize = 0x400; + break; + case 2: // 1.25GB + mVlvMmioPolicyPpi->MmioSize = 0x500; + break; + case 3: // 1.5GB + mVlvMmioPolicyPpi->MmioSize = 0x600; + break; + case 4: // 2GB + mVlvMmioPolicyPpi->MmioSize = 0x800; + break; + default: + mVlvMmioPolicyPpi->MmioSize = 0x800; + break; + } + Status = (*PeiServices)->InstallPpi( + PeiServices, + mVlvMmioPolicyPpiDesc + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +EFI_STATUS +ReadPlatformIds ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN OUT EFI_PLATFORM_INFO_HOB *PlatformInfoHob + ) +{ + { + EFI_STATUS Status = EFI_SUCCESS; + UINT8 FabId = 0; + UINTN DataSize; + EFI_PLATFORM_INFO_HOB TmpHob; + EFI_PEI_READ_ONLY_VARIABLE2_PPI *PeiVar; + + Status = (**PeiServices).LocatePpi ( + PeiServices, + &gEfiPeiReadOnlyVariable2PpiGuid, + 0, + NULL, + (void **)&PeiVar + ); + ASSERT_EFI_ERROR (Status); + + DataSize = sizeof (EFI_PLATFORM_INFO_HOB); + Status = PeiVar->GetVariable ( + PeiVar, + L"PlatformInfo", + &gEfiVlv2VariableGuid, + NULL, + &DataSize, + &TmpHob + ); + + if (Status == EFI_SUCCESS) { + PlatformInfoHob->BoardId = TmpHob.BoardId; + PlatformInfoHob->MemCfgID = TmpHob.MemCfgID; + PlatformInfoHob->BoardRev = TmpHob.BoardRev; + PlatformInfoHob->PlatformFlavor = TmpHob.PlatformFlavor; + return Status; + } + + + PlatformInfoHob->BoardId = BOARD_ID_MINNOW2; + DEBUG ((EFI_D_INFO, "I'm Minnow2!\n")); + + PlatformInfoHob->MemCfgID = 0; + PlatformInfoHob->BoardRev = FabId + 1; // FabId = 0 means FAB1 (BoardRev = 1), FabId = 1 means FAB2 (BoardRev = 2)... + PlatformInfoHob->PlatformFlavor = FlavorMobile; + } + + return EFI_SUCCESS; +} + +// +// Start::Alpine Valley platform +// +/** + This routine reads SysCtl registers + + @param SmbusBase SMBUS Base Address + @param SlvAddr Targeted Smbus Slave device address + @param Operation Which SMBus protocol will be used + @param Offset Offset of the register + @param Length Number of bytes + @param Buffer Buffer contains values read from registers + + @retval SUCCESS as passed + @retval Others as failed + +**/ +EFI_STATUS +PeiSmbusExec ( + UINT16 SmbusBase, + UINT8 SlvAddr, + UINT8 Operation, + UINT8 Offset, + UINT8 *Length, + UINT8 *Buffer + ) +{ + EFI_STATUS Status=EFI_SUCCESS; + UINT8 AuxcReg; + UINT8 SmbusOperation = 0; + UINT8 StsReg; + UINT8 SlvAddrReg; + UINT8 HostCmdReg; + UINT8 BlockCount = 0; + BOOLEAN BufferTooSmall; + UINT8 Index; + UINT8 *CallBuffer; + UINT8 RetryCount = BUS_TRIES; + + // + // MrcSmbusExec supports byte and block read. + // Only allow Byte or block access + // + if (!((*Length == AV_SC_BYTE_LEN) || (*Length == AV_SC_BLOCK_LEN))) { + return EFI_INVALID_PARAMETER; + } + + // + // See if its ok to use the bus based upon INUSE_STS bit. + // + Status = AcquireBus (SmbusBase); + ASSERT_EFI_ERROR(Status); + + CallBuffer = Buffer; + + // + //SmbStatus Bits of interest + //[6] = IUS (In Use Status) + //[4] = FAIL + //[3] = BERR (Bus Error = transaction collision) + //[2] = DERR (Device Error = Illegal Command Field, Unclaimed Cycle, Host Device Timeout, CRC Error) + //[1] = INTR (Successful completion of last command) + //[0] = HOST BUSY + // + // + // This is the main operation loop. If the operation results in a Smbus + // collision with another master on the bus, it attempts the requested + // transaction again at least BUS_TRIES attempts. + // + while (RetryCount--) { + // + // Operation Specifics (pre-execution) + // + Status = EFI_SUCCESS; + SlvAddrReg = SlvAddr; + HostCmdReg = Offset; + AuxcReg = 0; + + switch (Operation) { + + case SMBUS_WRITE_BYTE: + IoWrite8 (SmbusBase+R_PCH_SMBUS_HD0, CallBuffer[0]); + SmbusOperation = V_PCH_SMBUS_SMB_CMD_BYTE_DATA; + break; + + case SMBUS_READ_BYTE: + SmbusOperation = V_PCH_SMBUS_SMB_CMD_BYTE_DATA; + SlvAddrReg |= B_PCH_SMBUS_RW_SEL_READ; + if (*Length < 1) { + Status = EFI_INVALID_PARAMETER; + } + *Length = 1; + break; + + case SMBUS_WRITE_BLOCK: + SmbusOperation = V_PCH_SMBUS_SMB_CMD_BLOCK; + IoWrite8 (SmbusBase+R_PCH_SMBUS_HD0, *(UINT8 *) Length); + BlockCount = (UINT8) (*Length); + if ((*Length < 1) || (*Length > 32)) { + Status = EFI_INVALID_PARAMETER; + break; + } + AuxcReg |= B_PCH_SMBUS_E32B; + break; + + case SMBUS_READ_BLOCK: + SmbusOperation = V_PCH_SMBUS_SMB_CMD_BLOCK; + SlvAddrReg |= B_PCH_SMBUS_RW_SEL_READ; + if ((*Length < 1) || (*Length > 32)) { + Status = EFI_INVALID_PARAMETER; + break; + } + AuxcReg |= B_PCH_SMBUS_E32B; + break; + + default: + Status = EFI_INVALID_PARAMETER; + break; + } + + // + // Set Auxiliary Control register + // + IoWrite8 (SmbusBase+R_PCH_SMBUS_AUXC, AuxcReg); + + // + // Reset the pointer of the internal buffer + // + IoRead8 (SmbusBase+R_PCH_SMBUS_HCTL); + + // + // Now that the 32 byte buffer is turned on, we can write th block data + // into it + // + if (Operation == SMBUS_WRITE_BLOCK) { + for (Index = 0; Index < BlockCount; Index++) { + // + // Write next byte + // + IoWrite8 (SmbusBase+R_PCH_SMBUS_HBD, CallBuffer[Index]); + } + } + + // + // Set SMBus slave address for the device to read + // + IoWrite8(SmbusBase+R_PCH_SMBUS_TSA, SlvAddrReg); + + // + // + // Set Command register for the offset to read + // + IoWrite8(SmbusBase+R_PCH_SMBUS_HCMD, HostCmdReg ); + + // + // Set Control Register to Set "operation command" protocol and start bit + // + IoWrite8(SmbusBase+R_PCH_SMBUS_HCTL, (UINT8) (SmbusOperation + B_PCH_SMBUS_START)); + + // + // Wait for IO to complete + // + do { StsReg = (UINT8) IoRead8(SmbusBase+0); } while ((StsReg & (BIT4|BIT3|BIT2|BIT1)) == 0); + + if (StsReg & B_PCH_SMBUS_DERR) { + Status = EFI_DEVICE_ERROR; + break; + } else if (StsReg & B_PCH_SMBUS_BERR) { + // + // Clear the Bus Error for another try + // + Status = EFI_DEVICE_ERROR; + IoWrite8(SmbusBase+R_PCH_SMBUS_HSTS, B_PCH_SMBUS_BERR); + + // + // Clear Status Registers + // + IoWrite8(SmbusBase+R_PCH_SMBUS_HSTS, B_PCH_SMBUS_HSTS_ALL); + IoWrite8(SmbusBase+R_PCH_SMBUS_AUXS, B_PCH_SMBUS_CRCE); + + continue; + } + + // + // successfull completion + // Operation Specifics (post-execution) + // + switch (Operation) { + + case SMBUS_READ_BYTE: + CallBuffer[0] = (UINT8)(IoRead8 (SmbusBase+R_PCH_SMBUS_HD0)); + break; + + case SMBUS_WRITE_BLOCK: + IoWrite8(SmbusBase+R_PCH_SMBUS_HSTS, B_PCH_SMBUS_BYTE_DONE_STS); + break; + + case SMBUS_READ_BLOCK: + BufferTooSmall = FALSE; + + // + // Find out how many bytes will be in the block + // + BlockCount = (UINT8)(IoRead8 (SmbusBase+R_PCH_SMBUS_HD0)); + if (*Length < BlockCount) { + BufferTooSmall = TRUE; + } else { + for (Index = 0; Index < BlockCount; Index++) { + // + // Read the byte + // + CallBuffer[Index] = (UINT8)IoRead8 (SmbusBase+R_PCH_SMBUS_HBD); + } + } + + *Length = BlockCount; + if (BufferTooSmall) { + Status = EFI_BUFFER_TOO_SMALL; + } + break; + + default: + break; + }; + + if ((StsReg & B_PCH_SMBUS_BERR) && (Status == EFI_SUCCESS)) { + // + // Clear the Bus Error for another try + // + Status = EFI_DEVICE_ERROR; + IoWrite8(SmbusBase+R_PCH_SMBUS_HSTS, B_PCH_SMBUS_BERR); + + continue; + } else { + break; + } + } + + // + // Clear Status Registers and exit + // + IoWrite8(SmbusBase+R_PCH_SMBUS_HSTS, B_PCH_SMBUS_HSTS_ALL); + IoWrite8(SmbusBase+R_PCH_SMBUS_AUXS, B_PCH_SMBUS_CRCE); + IoWrite8(SmbusBase+R_PCH_SMBUS_AUXC, 0); + return Status; +} +// +// End::Alpine Valley platform +// + diff --git a/Vlv2TbltDevicePkg/PlatformPei/Platform.h b/Vlv2TbltDevicePkg/PlatformPei/Platform.h new file mode 100644 index 0000000000..12e4b658d0 --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformPei/Platform.h @@ -0,0 +1,216 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +**/ + + +#ifndef __PEI_PLATFORM_H__ +#define __PEI_PLATFORM_H__ + +#define PEI_STALL_RESOLUTION 1 +#define STALL_PEIM_SIGNATURE SIGNATURE_32('p','p','u','s') + +typedef struct { + UINT32 Signature; + EFI_FFS_FILE_HEADER *FfsHeader; + EFI_PEI_NOTIFY_DESCRIPTOR StallNotify; +} STALL_CALLBACK_STATE_INFORMATION; + +#define STALL_PEIM_FROM_THIS(a) CR (a, STALL_CALLBACK_STATE_INFORMATION, StallNotify, STALL_PEIM_SIGNATURE) + +#ifdef NOCS_S3_SUPPORT + +/** + Peform the boot mode determination logic + If the box is closed, then + 1. If it's first time to boot, it's boot with full config . + 2. If the ChassisIntrution is selected, force to be a boot with full config + 3. Otherwise it's boot with no change. + + @param PeiServices General purpose services available to every PEIM. + @param BootMode The detected boot mode. + + @retval EFI_SUCCESS if the boot mode could be set +**/ +EFI_STATUS +UpdateBootMode ( + IN CONST EFI_PEI_SERVICES **PeiServices + ); +#endif + +/** + This function reset the entire platform, including all processor and devices, and + reboots the system. + + @param PeiServices General purpose services available to every PEIM. + + @retval EFI_SUCCESS if it completed successfully. +**/ +EFI_STATUS +EFIAPI +ResetSystem ( + IN CONST EFI_PEI_SERVICES **PeiServices + ); + +/** + This function will be called when MRC is done. + + @param PeiServices General purpose services available to every PEIM. + @param NotifyDescriptor Information about the notify event.. + @param Ppi The notify context. + + @retval EFI_SUCCESS If the function completed successfully. +**/ +EFI_STATUS +EFIAPI +MemoryDiscoveredPpiNotifyCallback ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ); + +/** + This is the callback function notified by FvFileLoader PPI, it depends on FvFileLoader PPI to load + the PEIM into memory. + + @param PeiServices General purpose services available to every PEIM. + @param NotifyDescriptor The context of notification. + @param Ppi The notify PPI. + + @retval EFI_SUCCESS if it completed successfully. +**/ +EFI_STATUS +EFIAPI +FvFileLoaderPpiNotifyCallback ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ); + +/** + This function provides a blocking stall for reset at least the given number of microseconds + stipulated in the final argument. + + @param PeiServices General purpose services available to every PEIM. + @param this Pointer to the local data for the interface. + @param Microseconds number of microseconds for which to stall. + + @retval EFI_SUCCESS the function provided at least the required stall. +**/ +EFI_STATUS +EFIAPI +Stall ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_STALL_PPI *This, + IN UINTN Microseconds + ); + +/** + This function initialize recovery functionality by installing the recovery PPI. + + @param PeiServices General purpose services available to every PEIM. + + @retval EFI_SUCCESS If the interface could be successfully installed. +**/ +EFI_STATUS +EFIAPI +InitializeRecovery ( + IN EFI_PEI_SERVICES **PeiServices + ); + +/** + This function + 1. Calling MRC to initialize memory. + 2. Install EFI Memory. + 3. Capsule coalesce if capsule boot mode. + 4. Create HOB of system memory. + + @param PeiServices Pointer to the PEI Service Table + + @retval EFI_SUCCESS If it completes successfully. + +**/ +EFI_STATUS +MemoryInit ( + IN EFI_PEI_SERVICES **PeiServices + ); + +/** + This function provides the implementation of AtaController PPI Enable Channel function. + + @param PeiServices General purpose services available to every PEIM. + @param this Pointer to the local data for the interface. + @param ChannelMask This parameter is used to specify primary or slavery IDE channel. + + @retval EFI_SUCCESS Procedure returned successfully. +**/ +EFI_STATUS +EnableAtaChannel ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_ATA_CONTROLLER_PPI *This, + IN UINT8 ChannelMask + ); + +/** + This function provides the implementation of AtaController PPI Get IDE channel Register Base Address + + @param PeiServices General purpose services available to every PEIM. + @param this Pointer to the local data for the interface. + @param IdeRegsBaseAddr Pointer to IDE_REGS_BASE_ADDR struct, which is used to record + IDE Command and Control regeisters Base Address. + + @retval EFI_SUCCESS Procedure returned successfully. +**/ +EFI_STATUS +GetIdeRegsBaseAddr ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_ATA_CONTROLLER_PPI *This, + IN IDE_REGS_BASE_ADDR *IdeRegsBaseAddr + ); + +/** + This function provides the implementation to properly setup both LM & PDM functionality. + + @param PeiServices General purpose services available to every PEIM. + + @retval EFI_SUCCESS Procedure returned successfully. + +**/ +EFI_STATUS +ConfigureLM( + IN EFI_PEI_SERVICES **PeiServices + ); + +#include + +BOOLEAN +EFIAPI +IsFastBootEnabled ( + IN CONST EFI_PEI_SERVICES **PeiServices + ); + +EFI_STATUS +PrioritizeBootMode ( + IN OUT EFI_BOOT_MODE *CurrentBootMode, + IN EFI_BOOT_MODE NewBootMode + ); + +EFI_STATUS +EFIAPI +CapsulePpiNotifyCallback ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ); +#endif diff --git a/Vlv2TbltDevicePkg/PlatformPei/PlatformPei.inf b/Vlv2TbltDevicePkg/PlatformPei/PlatformPei.inf new file mode 100644 index 0000000000..af8bb19083 --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformPei/PlatformPei.inf @@ -0,0 +1,136 @@ +# +# +# Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved +# +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License that accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +# This PEIM includes 3 parts, pre memory initialization, MRC +# wrapper and post memory initialization. +# On pre memory, following action is performed, +# 1. Initizluize GMCH. +# 2. Detect boot mode. +# 3. Detect video adapter to determine whether we need pre allocated +# memory. +# +# After that MRC wrapper calls MRC to initialize memory and install a PPI +# notify to do post memory +# initialization. MRC wrapper performance following actions, +# 1. Install EFI Memory. +# 2. Capsule coalesce if capsule boot mode. +# 3. Create HOB of system memory. +# Note: MRC supports 3 kinds of chipsets including Lakeport, Glenwood and Mukilteo, +# so please don't define MACRO MUKILTEO_SUPPORT on Lakeport here. +# +# On post memory, following action is performed, +# 1. TC initialization after MRC. +# 2. SIO initialization. +# 3. Install ResetSystem and FinvFv PPI, relocate Stall to memory on +# recovery boot mode. +# 4. Set MTRR for PEI +# 5. Create FV HOB and Flash HOB +# 6. Install RecoveryModule and AtaController PPI if on recovery boot mode. +# +# This PEIM does not have any register access directly, it depends on +# IntelTCLib, TCAccess libraries to access Chipset +# registers. +# +# Platform.c - Provide main flow and entrypoint of PEIM. +# MemoryCallback.c - Includes a memory call back function notified when +# MRC is done. +# +# + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = PlatformPeim + FILE_GUID = 9618C0DC-50A4-496c-994F-7241F282ED01 + MODULE_TYPE = PEIM + VERSION_STRING = 1.0 + ENTRY_POINT = PeiInitPlatform + PI_SPECIFICATION_VERSION = 0x0001000A + +[sources.common] + Platform.c + Platform.h + MemoryCallback.c + CommonHeader.h + Stall.c + BootMode.c + + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + Vlv2TbltDevicePkg/PlatformPkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + Vlv2DeviceRefCodePkg/Vlv2DeviceRefCodePkg.dec + IA32FamilyCpuPkg/IA32FamilyCpuPkg.dec + UefiCpuPkg/UefiCpuPkg.dec + CryptoPkg/CryptoPkg.dec + EdkCompatibilityPkg/EdkCompatibilityPkg.dec + +[LibraryClasses] + PeimEntryPoint + DebugLib + HobLib + IoLib + MultiPlatformLib + MtrrLib + PerformanceLib + MonoStatusCodeLib + BaseCryptLib + PciLib + +[Ppis] + gEfiPeiStallPpiGuid + gPeiSpeakerInterfacePpiGuid + gEfiPeiMemoryDiscoveredPpiGuid + gVlvPolicyPpiGuid + gEfiPeiReadOnlyVariable2PpiGuid + gEfiPeiResetPpiGuid + gEfiEndOfPeiSignalPpiGuid + gEfiFindFvPpiGuid + gPeiCapsulePpiGuid + gEfiPeiBootInRecoveryModePpiGuid + gEfiPeiRecoveryModulePpiGuid + gEfiPeiDeviceRecoveryModulePpiGuid + gPeiCachePpiGuid + gEfiPeiMasterBootModePpiGuid + gEfiPeiSmbusPpiGuid + gPeiMfgMemoryTestPpiGuid + gPeiSha256HashPpiGuid + gVlvMmioPolicyPpiGuid + +[Guids] + gEfiSetupVariableGuid + gEfiPlatformInfoGuid + gEfiPlatformBootModeGuid + gEfiPlatformCpuInfoGuid + gEfiGlobalVariableGuid + gRecoveryOnFatFloppyDiskGuid + gRecoveryOnFatUsbDiskGuid + gRecoveryOnFatIdeDiskGuid + gRecoveryOnDataCdGuid + gMfgModeVariableGuid + gEfiNormalSetupGuid + gEfiBootStateGuid + gEfiVlv2VariableGuid + +[Pcd.common] + gPlatformModuleTokenSpaceGuid.PcdFlashFvMainBase + gPlatformModuleTokenSpaceGuid.PcdFlashFvMainSize + gPlatformModuleTokenSpaceGuid.PcdFlashFvRecovery2Base + gPlatformModuleTokenSpaceGuid.PcdFlashFvRecovery2Size + gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress + gPlatformModuleTokenSpaceGuid.PcdFlashAreaBaseAddress + gPlatformModuleTokenSpaceGuid.PcdFlashAreaSize +[Depex] + TRUE + diff --git a/Vlv2TbltDevicePkg/PlatformPei/Stall.c b/Vlv2TbltDevicePkg/PlatformPei/Stall.c new file mode 100644 index 0000000000..8c2ab99f1c --- /dev/null +++ b/Vlv2TbltDevicePkg/PlatformPei/Stall.c @@ -0,0 +1,95 @@ +/** @file + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + Stall.c + +Abstract: + + Produce Stall Ppi. + +--*/ + + +#include "CommonHeader.h" +#include "PlatformBaseAddresses.h" +#include "PchRegs.h" + +/** + Waits for at least the given number of microseconds. + + @param PeiServices General purpose services available to every PEIM. + @param This PPI instance structure. + @param Microseconds Desired length of time to wait. + + @retval EFI_SUCCESS If the desired amount of time was passed. + +**/ +EFI_STATUS +EFIAPI +Stall ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_STALL_PPI *This, + IN UINTN Microseconds + ) +{ + UINTN Ticks; + UINTN Counts; + UINT32 CurrentTick; + UINT32 OriginalTick; + UINT32 RemainingTick; + + if (Microseconds == 0) { + return EFI_SUCCESS; + } + + OriginalTick = IoRead32 (ACPI_BASE_ADDRESS + R_PCH_ACPI_PM1_TMR); + OriginalTick &= (V_PCH_ACPI_PM1_TMR_MAX_VAL - 1); + CurrentTick = OriginalTick; + + // + // The timer frequency is 3.579545MHz, so 1 ms corresponds to 3.58 clocks + // + Ticks = Microseconds * 358 / 100 + OriginalTick + 1; + + // + // The loops needed for timer overflow + // + Counts = (UINTN)RShiftU64((UINT64)Ticks, 24); + + // + // Remaining clocks within one loop + // + RemainingTick = Ticks & 0xFFFFFF; + + // + // Do not intend to use TMROF_STS bit of register PM1_STS, because this add extra + // one I/O operation, and may generate SMI + // + while (Counts != 0) { + CurrentTick = IoRead32 (ACPI_BASE_ADDRESS + R_PCH_ACPI_PM1_TMR) & B_PCH_ACPI_PM1_TMR_VAL; + if (CurrentTick <= OriginalTick) { + Counts--; + } + OriginalTick = CurrentTick; + } + + while ((RemainingTick > CurrentTick) && (OriginalTick <= CurrentTick)) { + OriginalTick = CurrentTick; + CurrentTick = IoRead32 (ACPI_BASE_ADDRESS + R_PCH_ACPI_PM1_TMR) & B_PCH_ACPI_PM1_TMR_VAL; + } + + return EFI_SUCCESS; +} -- cgit v1.2.3