summaryrefslogtreecommitdiff
path: root/Silicon/Intel/LewisburgPkg/Library
diff options
context:
space:
mode:
Diffstat (limited to 'Silicon/Intel/LewisburgPkg/Library')
-rw-r--r--Silicon/Intel/LewisburgPkg/Library/DxeRuntimeResetSystemLib/DxeRuntimeResetSystemLib.inf70
-rw-r--r--Silicon/Intel/LewisburgPkg/Library/DxeRuntimeResetSystemLib/PchReset.c598
-rw-r--r--Silicon/Intel/LewisburgPkg/Library/DxeRuntimeResetSystemLib/PchReset.h111
-rw-r--r--Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmGpioLib/GpioInit.c409
-rw-r--r--Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmGpioLib/GpioLib.c2744
-rw-r--r--Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmGpioLib/GpioLibrary.h222
-rw-r--r--Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmGpioLib/GpioNativeLib.c454
-rw-r--r--Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmGpioLib/PchSklGpioData.c65
-rw-r--r--Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmGpioLib/PeiDxeSmmGpioLib.inf55
-rw-r--r--Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchCycleDecodingLib/PchCycleDecodingLib.c1176
-rw-r--r--Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchCycleDecodingLib/PeiDxeSmmPchCycleDecodingLib.inf40
-rw-r--r--Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchGbeLib/PchGbeLib.c166
-rw-r--r--Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchGbeLib/PeiDxeSmmPchGbeLib.inf44
-rw-r--r--Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchInfoLib/PchInfoLib.c511
-rw-r--r--Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchInfoLib/PchInfoStrLib.c297
-rw-r--r--Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchInfoLib/PeiDxeSmmPchInfoLib.inf39
-rw-r--r--Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchP2sbLib/PchP2sbLib.c337
-rw-r--r--Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchP2sbLib/PeiDxeSmmPchP2sbLib.inf37
-rw-r--r--Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchPcrLib/PchPcrLib.c459
-rw-r--r--Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchPcrLib/PeiDxeSmmPchPcrLib.inf38
-rw-r--r--Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchPmcLib/PchPmcLib.c159
-rw-r--r--Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchPmcLib/PeiDxeSmmPchPmcLib.inf38
-rw-r--r--Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchSbiAccessLib/PchSbiAccessLib.c376
-rw-r--r--Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchSbiAccessLib/PeiDxeSmmPchSbiAccessLib.inf38
-rw-r--r--Silicon/Intel/LewisburgPkg/Library/PeiPchPolicyLib/PchPrintPolicy.c736
-rw-r--r--Silicon/Intel/LewisburgPkg/Library/PeiPchPolicyLib/PeiPchPolicyLib.c587
-rw-r--r--Silicon/Intel/LewisburgPkg/Library/PeiPchPolicyLib/PeiPchPolicyLib.inf58
-rw-r--r--Silicon/Intel/LewisburgPkg/Library/PeiPchPolicyLib/PeiPchPolicyLibrary.h31
-rw-r--r--Silicon/Intel/LewisburgPkg/Library/PeiPchPolicyLib/Rvp3PolicyLib.c211
-rw-r--r--Silicon/Intel/LewisburgPkg/Library/SmmSpiFlashCommonLib/SmmSpiFlashCommonLib.inf56
-rw-r--r--Silicon/Intel/LewisburgPkg/Library/SmmSpiFlashCommonLib/SpiFlashCommon.c198
-rw-r--r--Silicon/Intel/LewisburgPkg/Library/SmmSpiFlashCommonLib/SpiFlashCommonSmmLib.c59
32 files changed, 10419 insertions, 0 deletions
diff --git a/Silicon/Intel/LewisburgPkg/Library/DxeRuntimeResetSystemLib/DxeRuntimeResetSystemLib.inf b/Silicon/Intel/LewisburgPkg/Library/DxeRuntimeResetSystemLib/DxeRuntimeResetSystemLib.inf
new file mode 100644
index 0000000000..353aafa572
--- /dev/null
+++ b/Silicon/Intel/LewisburgPkg/Library/DxeRuntimeResetSystemLib/DxeRuntimeResetSystemLib.inf
@@ -0,0 +1,70 @@
+### @file
+#
+# Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which 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.
+#
+###
+
+[Defines]
+ INF_VERSION = 0x00010017
+ BASE_NAME = DxeRuntimeResetSystemLib
+ FILE_GUID = 5602DBE0-2576-44CB-95FF-53D5A18C775F
+ VERSION_STRING = 1.0
+ MODULE_TYPE = DXE_RUNTIME_DRIVER
+ LIBRARY_CLASS = ResetSystemLib
+ CONSTRUCTOR = InstallPchReset
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 EBC
+#
+
+[LibraryClasses]
+ IoLib
+ BaseLib
+ DebugLib
+ BaseMemoryLib
+ MemoryAllocationLib
+ UefiDriverEntryPoint
+ UefiBootServicesTableLib
+ UefiRuntimeServicesTableLib
+ UefiRuntimeLib
+ PchCycleDecodingLib
+ DxeServicesTableLib
+ PchResetCommonLib
+ HobLib
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ LewisburgPkg/PchRcPkg.dec
+ PurleyRcPkg/RcPkg.dec
+
+[Sources]
+ PchReset.c
+ PchReset.h
+
+
+[Protocols]
+ gPchResetCallbackProtocolGuid ## CONSUMES
+
+[Guids]
+ gEfiEventVirtualAddressChangeGuid
+ gEfiCapsuleVendorGuid
+ gPchPowerCycleResetGuid
+ gPchGlobalResetGuid
+ gPchGlobalResetWithEcGuid
+ gPchPolicyHobGuid
+
+
+[Depex]
+ gEfiPciRootBridgeIoProtocolGuid AND # SERVER_BIOS_FLAG
+ TRUE \ No newline at end of file
diff --git a/Silicon/Intel/LewisburgPkg/Library/DxeRuntimeResetSystemLib/PchReset.c b/Silicon/Intel/LewisburgPkg/Library/DxeRuntimeResetSystemLib/PchReset.c
new file mode 100644
index 0000000000..cdc0f19c17
--- /dev/null
+++ b/Silicon/Intel/LewisburgPkg/Library/DxeRuntimeResetSystemLib/PchReset.c
@@ -0,0 +1,598 @@
+/** @file
+
+Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+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.
+
+**/
+
+#include "PchReset.h"
+
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_RESET_INSTANCE *mPchResetInstance;
+STATIC UINT8 mDaysOfMonthInfo[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_RESET_DATA mPchPowerCycleReset = {
+ PCH_PLATFORM_SPECIFIC_RESET_STRING,
+ PCH_POWER_CYCLE_RESET_GUID
+};
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_RESET_DATA mPchGlobalReset = {
+ PCH_PLATFORM_SPECIFIC_RESET_STRING,
+ PCH_GLOBAL_RESET_GUID
+};
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_RESET_DATA mPchGlobalResetWithEc = {
+ PCH_PLATFORM_SPECIFIC_RESET_STRING,
+ PCH_GLOBAL_RESET_WITH_EC_GUID
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mCapsuleResetType = 0;
+
+/**
+ Check if it is leap year
+
+ @param[in] Year year to be check
+
+ @retval True year is leap year
+ @retval FALSE year is not a leap year
+**/
+BOOLEAN
+IsLeapYear (
+ IN UINT16 Year
+ )
+{
+ return (Year % 4 == 0) && ((Year % 100 != 0) || (Year % 400 == 0));
+}
+
+/**
+ Set System Wakeup Alarm.
+
+ @param[in] WakeAfter Time offset in seconds to wake from S3
+
+ @retval EFI_SUCCESS Timer started successfully
+**/
+STATIC
+EFI_STATUS
+SetSystemWakeupAlarm (
+ IN UINT32 WakeAfter
+ )
+{
+ EFI_STATUS Status;
+ EFI_TIME Time;
+ EFI_TIME_CAPABILITIES Capabilities;
+ UINT32 Reminder;
+ UINT16 ABase;
+ UINT8 DayOfMonth;
+
+ ///
+ /// For an instant wake 2 seconds is a safe value
+ ///
+ if (WakeAfter < 2) {
+ WakeAfter = 2;
+ }
+
+ Status = EfiGetTime (&Time, &Capabilities);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Reminder = WakeAfter + (UINT32) Time.Second;
+ Time.Second = Reminder % 60;
+ Reminder = Reminder / 60;
+ Reminder = Reminder + (UINT32) Time.Minute;
+ Time.Minute = Reminder % 60;
+ Reminder = Reminder / 60;
+ Reminder = Reminder + (UINT32) Time.Hour;
+ Time.Hour = Reminder % 24;
+ Reminder = Reminder / 24;
+
+ if (Reminder > 0) {
+ Reminder = Reminder + (UINT32) Time.Day;
+ if ((Time.Month == 2) && IsLeapYear (Time.Year)) {
+ DayOfMonth = 29;
+ } else {
+ DayOfMonth = mDaysOfMonthInfo[Time.Month - 1];
+ }
+ if (Reminder > DayOfMonth) {
+ Time.Day = (UINT8)Reminder - DayOfMonth;
+ Reminder = 1;
+ } else {
+ Time.Day = (UINT8)Reminder;
+ Reminder = 0;
+ }
+ }
+ if (Reminder > 0) {
+ if (Time.Month == 12) {
+ Time.Month = 1;
+ Time.Year = Time.Year + 1;
+ } else {
+ Time.Month = Time.Month + 1;
+ }
+ }
+
+ Status = EfiSetWakeupTime (TRUE, &Time);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ ABase = mPchResetInstance->PchAcpiBase;
+
+
+ ///
+ /// Clear RTC PM1 status
+ ///
+ IoWrite16 (ABase + R_PCH_ACPI_PM1_STS, B_PCH_ACPI_PM1_STS_RTC);
+
+ ///
+ /// set RTC_EN bit in PM1_EN to wake up from the alarm
+ ///
+ IoWrite16 (
+ ABase + R_PCH_ACPI_PM1_EN,
+ (IoRead16 (ABase + R_PCH_ACPI_PM1_EN) | B_PCH_ACPI_PM1_EN_RTC)
+ );
+ return Status;
+}
+
+/**
+ Retrieve PCH platform specific ResetData
+
+ @param[in] Guid PCH platform specific reset GUID.
+ @param[out] DataSize The size of ResetData in bytes.
+
+ @retval ResetData A platform specific reset that the exact type of
+ the reset is defined by the EFI_GUID that follows
+ the Null-terminated Unicode string.
+ @retval NULL If Guid is not defined in PCH platform specific reset.
+**/
+VOID *
+EFIAPI
+GetResetData (
+ IN EFI_GUID *Guid,
+ OUT UINTN *DataSize
+ )
+{
+ *DataSize = 0;
+ if (CompareGuid (Guid, &gPchPowerCycleResetGuid)) {
+ *DataSize = sizeof (mPchPowerCycleReset);
+ return (VOID *)&mPchPowerCycleReset;
+ } else if (CompareGuid (Guid, &gPchGlobalResetGuid)) {
+ *DataSize = sizeof (mPchGlobalReset);
+ return (VOID *)&mPchGlobalReset;
+ } else if (CompareGuid (Guid, &gPchGlobalResetWithEcGuid)) {
+ *DataSize = sizeof (mPchGlobalResetWithEc);
+ return (VOID *)&mPchGlobalResetWithEc;
+ }
+
+ return NULL;
+}
+
+/**
+ Execute Pch Reset from the host controller.
+
+ @param[in] This Pointer to the PCH_RESET_PROTOCOL instance.
+ @param[in] ResetType UEFI defined reset type.
+ @param[in] DataSize The size of ResetData in bytes.
+ @param[in] ResetData Optional element used to introduce a platform specific reset.
+ The exact type of the reset is defined by the EFI_GUID that follows
+ the Null-terminated Unicode string.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER If ResetType is invalid.
+**/
+EFI_STATUS
+EFIAPI
+Reset (
+ IN PCH_RESET_PROTOCOL *This,
+ IN EFI_RESET_TYPE ResetType,
+ IN UINTN DataSize,
+ IN VOID *ResetData OPTIONAL
+ )
+{
+ PCH_RESET_INSTANCE *PchResetInstance;
+ EFI_STATUS Status;
+ PCH_RESET_TYPE PchResetType;
+
+ PchResetInstance = PCH_RESET_INSTANCE_FROM_THIS (This);
+ PchResetType = (PCH_RESET_TYPE)ResetType;
+
+ Status = PchReset (PchResetInstance, PchResetType);
+
+ return Status;
+}
+
+/**
+ Calling this function causes a system-wide reset. This sets
+ all circuitry within the system to its initial state. This type of reset
+ is asynchronous to system operation and operates without regard to
+ cycle boundaries.
+
+ System reset should not return, if it returns, it means the system does
+ not support cold reset.
+**/
+VOID
+EFIAPI
+ResetCold (
+ VOID
+ )
+{
+ PchReset (mPchResetInstance, (PCH_RESET_TYPE) EfiResetCold);
+}
+
+/**
+ Calling this function causes a system-wide initialization. The processors
+ are set to their initial state, and pending cycles are not corrupted.
+
+ System reset should not return, if it returns, it means the system does
+ not support warm reset.
+**/
+VOID
+EFIAPI
+ResetWarm (
+ VOID
+ )
+{
+ PchReset (mPchResetInstance, (PCH_RESET_TYPE) EfiResetWarm);
+}
+
+/**
+ Calling this function causes the system to enter a power state equivalent
+ to the ACPI G2/S5 or G3 states.
+
+ System shutdown should not return, if it returns, it means the system does
+ not support shut down reset.
+**/
+VOID
+EFIAPI
+ResetShutdown (
+ VOID
+ )
+{
+ PchReset (mPchResetInstance, (PCH_RESET_TYPE) EfiResetShutdown);
+}
+
+/**
+ Calling this function causes the system to enter a power state for platform specific.
+
+ @param[in] ResetStatus The status code for the reset.
+ @param[in] DataSize The size of ResetData in bytes.
+ @param[in] ResetData Optional element used to introduce a platform specific reset.
+ The exact type of the reset is defined by the EFI_GUID that follows
+ the Null-terminated Unicode string.
+
+**/
+VOID
+EFIAPI
+ResetPlatformSpecific (
+ IN EFI_STATUS ResetStatus,
+ IN UINTN DataSize,
+ IN VOID *ResetData OPTIONAL
+ )
+{
+ EFI_GUID *GuidPtr;
+
+ if (ResetData == NULL) {
+ if (!EfiAtRuntime ()) {
+ DEBUG ((DEBUG_ERROR, "[DxeRuntimeResetSystemLib] ResetData is not available.\n"));
+ }
+ return;
+ }
+ GuidPtr = (EFI_GUID *) ((UINT8 *) ResetData + DataSize - sizeof (EFI_GUID));
+ if (CompareGuid (GuidPtr, &gPchPowerCycleResetGuid)) {
+ PchReset (mPchResetInstance, (PCH_RESET_TYPE) PowerCycleReset);
+ } else if (CompareGuid (GuidPtr, &gPchGlobalResetGuid)) {
+ PchReset (mPchResetInstance, (PCH_RESET_TYPE) GlobalReset);
+ } else if (CompareGuid (GuidPtr, &gPchGlobalResetWithEcGuid)) {
+ PchReset (mPchResetInstance, (PCH_RESET_TYPE) GlobalResetWithEc);
+ } else {
+ return;
+ }
+}
+
+/**
+ Calling this function causes the system to enter a power state for capsule update.
+
+ Reset update should not return, if it returns, it means the system does
+ not support capsule update.
+
+**/
+VOID
+EFIAPI
+EnterS3WithImmediateWake (
+ VOID
+ )
+{
+ PchReset (mPchResetInstance, (PCH_RESET_TYPE) EfiResetWarm);
+}
+
+/**
+ <b>PchReset Runtime DXE Driver Entry Point</b>\n
+ - <b>Introduction</b>\n
+ The PchReset Runtime DXE driver provide a standard way for other modules to
+ use the PCH Reset Interface in DXE/SMM/Runtime environments. It has no longer
+ hooked ResetSystem() function of the runtime service table.
+
+ - @pre
+ - If there is any driver which needs to run the callback function right before
+ issuing the reset, PCH Reset Callback Protocol will need to be installed
+ before PCH Reset Runtime DXE driver. If PchReset Runtime DXE driver is run
+ before Status Code Runtime Protocol is installed and there is the need
+ to use Status code in the driver, it will be necessary to add EFI_STATUS_CODE_RUNTIME_PROTOCOL_GUID
+ to the dependency file.
+ - @link _PCH_RESET_CALLBACK_PROTOCOL PCH_RESET_CALLBACK_PROTOCOL @endlink
+
+ - @result
+ The Reset driver produces @link _PCH_RESET_PROTOCOL PCH_RESET_PROTOCOL @endlink
+
+ @param[in] ImageHandle Image handle of the loaded driver
+ @param[in] SystemTable Pointer to the System Table
+
+ @retval EFI_SUCCESS Thread can be successfully created
+ @retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure
+ @retval EFI_DEVICE_ERROR Cannot create the timer service
+**/
+EFI_STATUS
+EFIAPI
+InstallPchReset (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ UINT64 BaseAddress;
+ UINT64 Length;
+ UINT32 PwrmBaseAddress;
+ EFI_GCD_MEMORY_SPACE_DESCRIPTOR MemorySpaceDescriptor;
+ UINT64 Attributes;
+ EFI_EVENT AddressChangeEvent;
+ EFI_PEI_HOB_POINTERS HobPtr;
+ PCH_POLICY_HOB *PchPolicyHob;
+
+ DEBUG ((DEBUG_INFO, "InstallPchReset() Start\n"));
+
+ //
+ // Set PMC PCI address space to RUNTIME MEMORY.
+ //
+ BaseAddress = MmPciBase(
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_PMC,
+ PCI_FUNCTION_NUMBER_PCH_PMC
+ );
+ Length = 0x1000; // 4KB
+
+ Status = gDS->GetMemorySpaceDescriptor (BaseAddress, &MemorySpaceDescriptor);
+ ASSERT_EFI_ERROR (Status);
+
+ Attributes = MemorySpaceDescriptor.Attributes | EFI_MEMORY_RUNTIME;
+
+ Status = gDS->SetMemorySpaceAttributes (
+ BaseAddress,
+ Length,
+ Attributes
+ );
+ ASSERT_EFI_ERROR (Status);
+ //
+ // Set PWRM MMIO address space to RUNTIME MEMORY.
+ //
+ PchPwrmBaseGet (&PwrmBaseAddress);
+ Length = 0x10000; // 64KB
+
+ Status = gDS->GetMemorySpaceDescriptor (PwrmBaseAddress, &MemorySpaceDescriptor);
+ ASSERT_EFI_ERROR (Status);
+
+ Attributes = MemorySpaceDescriptor.Attributes | EFI_MEMORY_RUNTIME;
+
+ Status = gDS->SetMemorySpaceAttributes (
+ PwrmBaseAddress,
+ Length,
+ Attributes
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Allocate Runtime memory for the PchReset protocol instance.
+ ///
+ mPchResetInstance = AllocateRuntimeZeroPool (sizeof (PCH_RESET_INSTANCE));
+ if (mPchResetInstance == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = PchResetConstructor (mPchResetInstance);
+
+ ///
+ /// Create Address Change event
+ ///
+ ///
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ PchResetVirtualAddressChangeEvent,
+ NULL,
+ &gEfiEventVirtualAddressChangeGuid,
+ &AddressChangeEvent
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ HobPtr.Guid = GetFirstGuidHob (&gPchPolicyHobGuid);
+ if (HobPtr.Guid != NULL) {
+ PchPolicyHob = GET_GUID_HOB_DATA (HobPtr.Guid);
+ mCapsuleResetType = PchPolicyHob->PmConfig.CapsuleResetType;
+ }
+ ///
+ /// The Lib Deconstruct will automatically be called when entrypoint return error.
+ ///
+ DEBUG ((DEBUG_INFO, "InstallPchReset() End\n"));
+
+ return Status;
+}
+
+/**
+ If need be, do any special reset required for capsules. For this
+ implementation where we're called from the ResetSystem() api,
+ just set our capsule variable and return to let the caller
+ do a soft reset.
+**/
+VOID
+CapsuleS3Reset (
+ VOID
+ )
+{
+ UINT32 Data32;
+ UINT32 Eflags;
+ UINT16 ABase;
+
+ DEBUG ((DEBUG_INFO, "Capsule Present: Will be issuing S3 reset.\n"));
+
+ ///
+ /// Wake up system 2 seconds after putting system into S3 to complete the reset operation.
+ ///
+ SetSystemWakeupAlarm (2);
+ ///
+ /// Process capsules across a system reset.
+ ///
+ ABase = mPchResetInstance->PchAcpiBase;
+ ASSERT (ABase != 0);
+
+ Data32 = IoRead32 ((UINTN) (ABase + R_PCH_ACPI_PM1_CNT));
+
+ Data32 = (UINT32) ((Data32 & ~(B_PCH_ACPI_PM1_CNT_SLP_TYP + B_PCH_ACPI_PM1_CNT_SLP_EN)) | V_PCH_ACPI_PM1_CNT_S3);
+
+ Eflags = (UINT32) AsmReadEflags ();
+
+ if ((Eflags & 0x200)) {
+ DisableInterrupts ();
+ }
+
+ AsmWbinvd ();
+ AsmWriteCr0 (AsmReadCr0 () | 0x060000000);
+
+ IoWrite32 (
+ (UINTN) (ABase + R_PCH_ACPI_PM1_CNT),
+ (UINT32) Data32
+ );
+
+ Data32 = Data32 | B_PCH_ACPI_PM1_CNT_SLP_EN;
+
+ IoWrite32 (
+ (UINTN) (ABase + R_PCH_ACPI_PM1_CNT),
+ (UINT32) Data32
+ );
+
+ if ((Eflags & 0x200)) {
+ EnableInterrupts ();
+ }
+ ///
+ /// Should not return
+ ///
+ CpuDeadLoop ();
+}
+
+/**
+ Execute call back function for Pch Reset.
+
+ @param[in] PchResetType Pch Reset Types which includes PowerCycle, Globalreset.
+
+ @retval EFI_SUCCESS The callback function has been done successfully
+ @retval EFI_NOT_FOUND Failed to find Pch Reset Callback protocol. Or, none of
+ callback protocol is installed.
+ @retval Others Do not do any reset from PCH
+**/
+EFI_STATUS
+EFIAPI
+PchResetCallback (
+ IN PCH_RESET_TYPE PchResetType
+ )
+{
+ EFI_STATUS Status;
+ UINTN NumHandles;
+ EFI_HANDLE *HandleBuffer;
+ UINTN Index;
+ PCH_RESET_CALLBACK_PROTOCOL *PchResetCallback;
+ UINTN Size;
+ UINTN CapsuleDataPtr;
+
+ if (EfiAtRuntime () == FALSE) {
+ DEBUG((DEBUG_ERROR, "Not in Runtime"));
+ ///
+ /// Retrieve all instances of Pch Reset Callback protocol
+ ///
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gPchResetCallbackProtocolGuid,
+ NULL,
+ &NumHandles,
+ &HandleBuffer
+ );
+
+ if (EFI_ERROR (Status)) {
+ ///
+ /// Those drivers that need to install Pch Reset Callback protocol have the responsibility
+ /// to make sure themselves execute before Pch Reset Runtime driver.
+ ///
+ if (Status == EFI_NOT_FOUND) {
+ DEBUG ((DEBUG_ERROR | DEBUG_INFO, "Or, none of Pch Reset callback protocol is installed.\n"));
+ }
+
+ return Status;
+ }
+
+ for (Index = 0; Index < NumHandles; Index++) {
+ Status = gBS->HandleProtocol (
+ HandleBuffer[Index],
+ &gPchResetCallbackProtocolGuid,
+ (VOID **) &PchResetCallback
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ if (!EFI_ERROR (Status)) {
+ DEBUG((EFI_D_ERROR, "Calling PchResetCallback %d\n", Index));
+ PchResetCallback->ResetCallback (PchResetType);
+ } else {
+ DEBUG ((DEBUG_ERROR | DEBUG_INFO, "Failed to locate Pch Reset Callback protocol.\n"));
+ return Status;
+ }
+ }
+ }
+ DEBUG((EFI_D_ERROR, "PchResetCallback After Runtime Check\n"));
+ if(PchResetType == WarmReset) {
+ ///
+ /// Check if there are pending capsules to process
+ ///
+ DEBUG((EFI_D_ERROR, "PchResetCallback Warmreset\n"));
+ Size = sizeof (CapsuleDataPtr);
+ Status = EfiGetVariable (
+ EFI_CAPSULE_VARIABLE_NAME,
+ &gEfiCapsuleVendorGuid,
+ NULL,
+ &Size,
+ (VOID *) &CapsuleDataPtr
+ );
+ if (Status == EFI_SUCCESS) {
+ if (mCapsuleResetType == CAPSULE_RESET_S3) { //default value S3 resume
+ CapsuleS3Reset ();
+ }
+ AsmWbinvd ();
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Fixup internal data pointers so that the services can be called in virtual mode.
+
+ @param[in] Event The event registered.
+ @param[in] Context Event context. Not used in this event handler.
+
+**/
+VOID
+EFIAPI
+PchResetVirtualAddressChangeEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID *) &(mPchResetInstance->PchPmcBase));
+ gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID *) &(mPchResetInstance->PchPwrmBase));
+ gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID *) &(mPchResetInstance));
+}
diff --git a/Silicon/Intel/LewisburgPkg/Library/DxeRuntimeResetSystemLib/PchReset.h b/Silicon/Intel/LewisburgPkg/Library/DxeRuntimeResetSystemLib/PchReset.h
new file mode 100644
index 0000000000..bfcd15888c
--- /dev/null
+++ b/Silicon/Intel/LewisburgPkg/Library/DxeRuntimeResetSystemLib/PchReset.h
@@ -0,0 +1,111 @@
+/** @file
+
+Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+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 _PCH_RESET_H
+#define _PCH_RESET_H
+
+#include <Library/IoLib.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiRuntimeLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Guid/EventGroup.h>
+#include <Library/MmPciBaseLib.h>
+#include <Protocol/PchReset.h>
+#include <PchAccess.h>
+#include <Library/PchCycleDecodingLib.h>
+#include <IncludePrivate/Library/PchResetCommonLib.h>
+#include <IncludePrivate/PchPolicyHob.h>
+#include <Library/HobLib.h>
+
+#define EFI_INTERNAL_POINTER 0x04
+
+#define PCH_RESET_INSTANCE_FROM_THIS(a) \
+ CR ( \
+ a, \
+ PCH_RESET_INSTANCE, \
+ PchResetInterface.PchResetProtocol, \
+ PCH_RESET_SIGNATURE \
+ )
+
+#define CAPSULE_RESET_S3 0
+#define CAPSULE_RESET_WARM 1
+
+/**
+ <b>PchReset Runtime DXE Driver Entry Point</b>\n
+ - <b>Introduction</b>\n
+ The PchReset Runtime DXE driver provide a standard way for other modules to
+ use the PCH Reset Interface in DXE/SMM/Runtime environments. It has no longer
+ hooked ResetSystem() function of the runtime service table.
+
+ - @pre
+ - If there is any driver which needs to run the callback function right before
+ issuing the reset, PCH Reset Callback Protocol will need to be installed
+ before PCH Reset Runtime DXE driver. If PchReset Runtime DXE driver is run
+ before Status Code Runtime Protocol is installed and there is the need
+ to use Status code in the driver, it will be necessary to add EFI_STATUS_CODE_RUNTIME_PROTOCOL_GUID
+ to the dependency file.
+ - @link _PCH_RESET_CALLBACK_PROTOCOL PCH_RESET_CALLBACK_PROTOCOL @endlink
+
+ - @result
+ The Reset driver produces @link _PCH_RESET_PROTOCOL PCH_RESET_PROTOCOL @endlink
+
+ @param[in] ImageHandle Image handle of the loaded driver
+ @param[in] SystemTable Pointer to the System Table
+
+ @retval EFI_SUCCESS Thread can be successfully created
+ @retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure
+ @retval EFI_DEVICE_ERROR Cannot create the timer service
+**/
+EFI_STATUS
+EFIAPI
+InstallPchReset (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Execute call back function for Pch Reset.
+
+ @param[in] PchResetType Pch Reset Types which includes PowerCycle, Globalreset.
+
+ @retval EFI_SUCCESS The callback function has been done successfully
+ @retval EFI_NOT_FOUND Failed to find Pch Reset Callback protocol. Or, none of
+ callback protocol is installed.
+ @retval Others Do not do any reset from PCH
+**/
+EFI_STATUS
+EFIAPI
+PchResetCallback (
+ IN PCH_RESET_TYPE PchResetType
+ );
+
+/**
+ Fixup internal data pointers so that the services can be called in virtual mode.
+
+ @param[in] Event The event registered.
+ @param[in] Context Event context. Not used in this event handler.
+
+**/
+VOID
+EFIAPI
+PchResetVirtualAddressChangeEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+#endif
diff --git a/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmGpioLib/GpioInit.c b/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmGpioLib/GpioInit.c
new file mode 100644
index 0000000000..422ecfcee1
--- /dev/null
+++ b/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmGpioLib/GpioInit.c
@@ -0,0 +1,409 @@
+/** @file
+
+Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+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.
+
+**/
+
+#include "GpioLibrary.h"
+
+
+/**
+ This procedure will handle requirement on SATA DEVSLPx pins.
+
+ @param[in] GpioPad GPIO pad
+ @param[in] PadMode GPIO PadMode value
+ @param[in out] Dw0Reg Value for PADCFG_DW0 register
+ @param[in out] Dw0RegMask Mask of bits which will change in PADCFG_DWO register
+
+ @retval None
+
+**/
+static
+VOID
+GpioHandleSataDevSlpPad (
+ IN GPIO_PAD GpioPad,
+ IN UINT32 PadMode,
+ IN OUT UINT32 *Dw0Reg,
+ IN OUT UINT32 *Dw0RegMask
+ )
+{
+ //
+ // For SATA DEVSLPx pins if used in native 1 mode then ensure that PadRstCfg
+ // is set to "00" - Powergood
+ //
+ if (GpioIsPadASataDevSlpPin (GpioPad, PadMode)) {
+ //
+ // Set PadRstCfg to Powergood
+ //
+ *Dw0RegMask |= B_PCH_GPIO_RST_CONF;
+ *Dw0Reg |= ((GpioResetPwrGood >> 1) << N_PCH_GPIO_RST_CONF);
+ }
+}
+
+/**
+ This SKL PCH specific procedure will initialize multiple SKL PCH GPIO pins
+
+ @param[in] NumberofItem Number of GPIO pads to be updated
+ @param[in] GpioInitTableAddress GPIO initialization table
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+static
+EFI_STATUS
+GpioConfigureSklPch (
+ IN UINT32 NumberOfItems,
+ IN GPIO_INIT_CONFIG *GpioInitTableAddress
+ )
+{
+ UINT32 Index;
+ UINT32 Dw0Reg;
+ UINT32 Dw0RegMask;
+ UINT32 Dw1Reg;
+ UINT32 Dw1RegMask;
+ UINT32 PadCfgReg;
+ UINT32 HostSoftOwnReg[V_PCH_GPIO_GROUP_MAX];
+ UINT32 HostSoftOwnRegMask[V_PCH_GPIO_GROUP_MAX];
+ UINT32 GpiGpeEnReg[V_PCH_GPIO_GROUP_MAX];
+ UINT32 GpiGpeEnRegMask[V_PCH_GPIO_GROUP_MAX];
+ GPIO_GROUP_INFO *GpioGroupInfo;
+ UINTN GpioGroupInfoLength;
+ GPIO_GROUP GpioGroupOffset;
+ UINT32 NumberOfGroups;
+ GPIO_PAD_OWN PadOwnVal;
+ GPIO_INIT_CONFIG *GpioData;
+ GPIO_GROUP Group;
+ UINT32 GroupIndex;
+ UINT32 PadNumber;
+ PCH_SERIES PchSeries;
+
+ PchSeries = GetPchSeries ();
+ PadOwnVal = GpioPadOwnHost;
+
+ ZeroMem (HostSoftOwnReg, sizeof (HostSoftOwnReg));
+ ZeroMem (HostSoftOwnRegMask, sizeof (HostSoftOwnRegMask));
+ ZeroMem (GpiGpeEnReg, sizeof (GpiGpeEnReg));
+ ZeroMem (GpiGpeEnRegMask, sizeof (GpiGpeEnRegMask));
+
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+
+ GpioGroupOffset = GpioGetLowestGroup ();
+ NumberOfGroups = GpioGetNumberOfGroups ();
+
+ for (Index = 0; Index < NumberOfItems; Index ++) {
+
+ Dw0RegMask = 0;
+ Dw0Reg = 0;
+ Dw1RegMask = 0;
+ Dw1Reg = 0;
+
+ GpioData = &GpioInitTableAddress[Index];
+
+ Group = GpioGetGroupFromGpioPad (GpioData->GpioPad);
+ GroupIndex = GpioGetGroupIndexFromGpioPad (GpioData->GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioData->GpioPad);
+
+ if (GroupIndex >= V_PCH_GPIO_GROUP_MAX) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Invalid Group Index (GroupIndex=%d, Pad=%d)!\n", GroupIndex, PadNumber));
+ ASSERT (FALSE);
+ continue;
+ }
+
+DEBUG_CODE_BEGIN();
+ if (!(((PchSeries == PchH) && (GPIO_GET_CHIPSET_ID(GpioData->GpioPad) == GPIO_SKL_H_CHIPSET_ID)) ||
+ ((PchSeries == PchLp) && (GPIO_GET_CHIPSET_ID(GpioData->GpioPad) == GPIO_SKL_LP_CHIPSET_ID)))) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Incorrect GpioPad define used on this chipset (Group=%d, Pad=%d)!\n", GroupIndex, PadNumber));
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+DEBUG_CODE_END();
+
+ //
+ // Check if group argument exceeds GPIO group range
+ //
+ if ((Group < GpioGroupOffset) || (Group >= NumberOfGroups + GpioGroupOffset)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check if legal pin number
+ //
+ if (PadNumber >= GpioGroupInfo[GroupIndex].PadPerGroup){
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (GpioIsPadLocked (GroupIndex, PadNumber)) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Pad is locked (Group=%d, Pad=%d)!\n", GroupIndex, PadNumber));
+ continue;
+ }
+
+ if (DebugCodeEnabled ()) {
+
+ //
+ // Check if selected GPIO Pad is not owned by CSME/ISH
+ //
+ GpioGetPadOwnership (GpioData->GpioPad, &PadOwnVal);
+
+ if (PadOwnVal != GpioPadOwnHost) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Accessing pad not owned by host (Group=%d, Pad=%d)!\n", GroupIndex, PadNumber));
+ DEBUG ((DEBUG_ERROR, "** Please make sure the GPIO usage in sync between CSME and BIOS configuration. \n"));
+ DEBUG ((DEBUG_ERROR, "** All the GPIO occupied by CSME should not do any configuration by BIOS.\n"));
+ continue;
+ }
+
+ }
+
+ //
+ // Configure Reset Type (PadRstCfg)
+ //
+ Dw0RegMask |= ((((GpioData->GpioConfig.PowerConfig & GPIO_CONF_RESET_MASK) >> GPIO_CONF_RESET_BIT_POS) == GpioHardwareDefault) ? 0x0 : B_PCH_GPIO_RST_CONF);
+ Dw0Reg |= (((GpioData->GpioConfig.PowerConfig & GPIO_CONF_RESET_MASK) >> (GPIO_CONF_RESET_BIT_POS + 1)) << N_PCH_GPIO_RST_CONF);
+
+ //
+ // Configure how interrupt is triggered (RxEvCfg)
+ //
+ Dw0RegMask |= ((((GpioData->GpioConfig.InterruptConfig & GPIO_CONF_INT_TRIG_MASK) >> GPIO_CONF_INT_TRIG_BIT_POS) == GpioHardwareDefault) ? 0x0 : B_PCH_GPIO_RX_LVL_EDG);
+ Dw0Reg |= (((GpioData->GpioConfig.InterruptConfig & GPIO_CONF_INT_TRIG_MASK) >> (GPIO_CONF_INT_TRIG_BIT_POS + 1)) << N_PCH_GPIO_RX_LVL_EDG);
+
+
+ //
+ // Configure interrupt generation (GPIRoutIOxAPIC/SCI/SMI/NMI)
+ //
+ Dw0RegMask |= ((((GpioData->GpioConfig.InterruptConfig & GPIO_CONF_INT_ROUTE_MASK) >> GPIO_CONF_INT_ROUTE_BIT_POS) == GpioHardwareDefault) ? 0x0 : (B_PCH_GPIO_RX_NMI_ROUTE | B_PCH_GPIO_RX_SCI_ROUTE | B_PCH_GPIO_RX_SMI_ROUTE | B_PCH_GPIO_RX_APIC_ROUTE));
+ Dw0Reg |= (((GpioData->GpioConfig.InterruptConfig & GPIO_CONF_INT_ROUTE_MASK) >> (GPIO_CONF_INT_ROUTE_BIT_POS + 1)) << N_PCH_GPIO_RX_NMI_ROUTE);
+
+ //
+ // Configure GPIO direction (GPIORxDis and GPIOTxDis)
+ //
+ Dw0RegMask |= ((((GpioData->GpioConfig.Direction & GPIO_CONF_DIR_MASK) >> GPIO_CONF_DIR_BIT_POS) == GpioHardwareDefault) ? 0x0 : (B_PCH_GPIO_RXDIS | B_PCH_GPIO_TXDIS));
+ Dw0Reg |= (((GpioData->GpioConfig.Direction & GPIO_CONF_DIR_MASK) >> (GPIO_CONF_DIR_BIT_POS + 1)) << N_PCH_GPIO_TXDIS);
+
+ //
+ // Configure GPIO input inversion (RXINV)
+ //
+ Dw0RegMask |= ((((GpioData->GpioConfig.Direction & GPIO_CONF_INV_MASK) >> GPIO_CONF_INV_BIT_POS) == GpioHardwareDefault) ? 0x0 : B_PCH_GPIO_RXINV);
+ Dw0Reg |= (((GpioData->GpioConfig.Direction & GPIO_CONF_INV_MASK) >> (GPIO_CONF_INV_BIT_POS + 1)) << N_PCH_GPIO_RXINV);
+
+ //
+ // Configure GPIO output state (GPIOTxState)
+ //
+ Dw0RegMask |= ((((GpioData->GpioConfig.OutputState & GPIO_CONF_OUTPUT_MASK) >> GPIO_CONF_OUTPUT_BIT_POS) == GpioHardwareDefault) ? 0x0 : B_PCH_GPIO_TX_STATE);
+ Dw0Reg |= (((GpioData->GpioConfig.OutputState & GPIO_CONF_OUTPUT_MASK) >> (GPIO_CONF_OUTPUT_BIT_POS + 1)) << N_PCH_GPIO_TX_STATE);
+
+ //
+ // Configure GPIO RX raw override to '1' (RXRAW1)
+ //
+ Dw0RegMask |= ((((GpioData->GpioConfig.OtherSettings & GPIO_CONF_RXRAW_MASK) >> GPIO_CONF_RXRAW_BIT_POS) == GpioHardwareDefault) ? 0x0 : B_PCH_GPIO_RX_RAW1);
+ Dw0Reg |= (((GpioData->GpioConfig.OtherSettings & GPIO_CONF_RXRAW_MASK) >> (GPIO_CONF_RXRAW_BIT_POS + 1)) << N_PCH_GPIO_RX_RAW1);
+
+ //
+ // Configure GPIO Pad Mode (PMode)
+ //
+ if (((GpioData->GpioPad == GPIO_SKL_H_GPP_B2) ||
+ (GpioData->GpioPad == GPIO_SKL_H_GPD7) ||
+ (GpioData->GpioPad == GPIO_SKL_H_GPD9)) &&
+ (GpioData->GpioConfig.PadMode != GpioPadModeGpio)) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Group/Index: %d/%d, Pad: %d cannot be set as NATIVE. Force it to GPIO mode!\n", Group, GroupIndex, PadNumber));
+ Dw0RegMask |= B_PCH_GPIO_PAD_MODE;
+ Dw0Reg |= ((GpioPadModeGpio >> (GPIO_CONF_PAD_MODE_BIT_POS + 1)) << N_PCH_GPIO_PAD_MODE);
+ } else {
+ Dw0RegMask |= ((((GpioData->GpioConfig.PadMode & GPIO_CONF_PAD_MODE_MASK) >> GPIO_CONF_PAD_MODE_BIT_POS) == GpioHardwareDefault) ? 0x0 : B_PCH_GPIO_PAD_MODE);
+ Dw0Reg |= (((GpioData->GpioConfig.PadMode & GPIO_CONF_PAD_MODE_MASK) >> (GPIO_CONF_PAD_MODE_BIT_POS + 1)) << N_PCH_GPIO_PAD_MODE);
+ }
+
+ //
+ // Configure GPIO termination (Term)
+ //
+ Dw1RegMask |= ((((GpioData->GpioConfig.ElectricalConfig & GPIO_CONF_TERM_MASK) >> GPIO_CONF_TERM_BIT_POS) == GpioHardwareDefault) ? 0x0 : B_PCH_GPIO_TERM);
+ Dw1Reg |= (((GpioData->GpioConfig.ElectricalConfig & GPIO_CONF_TERM_MASK) >> (GPIO_CONF_TERM_BIT_POS + 1)) << N_PCH_GPIO_TERM);
+
+ //
+ // Configure GPIO pad tolerance (padtol)
+ //
+ Dw1RegMask |= ((((GpioData->GpioConfig.ElectricalConfig & GPIO_CONF_PADTOL_MASK) >> GPIO_CONF_PADTOL_BIT_POS) == GpioHardwareDefault) ? 0x0 : B_PCH_GPIO_PADTOL);
+ Dw1Reg |= (((GpioData->GpioConfig.ElectricalConfig & GPIO_CONF_PADTOL_MASK) >> (GPIO_CONF_PADTOL_BIT_POS + 1)) << N_PCH_GPIO_PADTOL);
+
+ //
+ // Check for additional requirements on setting PADCFG register
+ //
+ GpioHandleSataDevSlpPad (GpioData->GpioPad, GpioData->GpioConfig.PadMode, &Dw0Reg, &Dw0RegMask);
+
+ //
+ // Create PADCFG register offset using group and pad number
+ //
+ PadCfgReg = 0x8 * PadNumber + GpioGroupInfo[GroupIndex].PadCfgOffset;
+
+ //
+ // Write PADCFG DW0 register
+ //
+ MmioAndThenOr32 (
+ (UINTN)PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, PadCfgReg),
+ ~(UINT32)Dw0RegMask,
+ (UINT32)Dw0Reg
+ );
+
+ //
+ // Write PADCFG DW1 register
+ //
+ MmioAndThenOr32 (
+ (UINTN)PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, PadCfgReg + 0x4),
+ ~(UINT32)Dw1RegMask,
+ (UINT32)Dw1Reg
+ );
+ //
+ // Update value to be programmed in HOSTSW_OWN register
+ //
+ HostSoftOwnRegMask[GroupIndex] |= (GpioData->GpioConfig.HostSoftPadOwn & 0x1) << PadNumber;
+ HostSoftOwnReg[GroupIndex] |= (GpioData->GpioConfig.HostSoftPadOwn >> 0x1) << PadNumber;
+
+ //
+ // Update value to be programmed in GPI_GPE_EN register
+ //
+ GpiGpeEnRegMask[GroupIndex] |= (GpioData->GpioConfig.InterruptConfig & 0x1) << PadNumber;
+ GpiGpeEnReg[GroupIndex] |= ((GpioData->GpioConfig.InterruptConfig & GpioIntSci) >> 3) << PadNumber;
+ }
+
+ for (Index = 0; Index < NumberOfGroups; Index++) {
+ //
+ // Write HOSTSW_OWN registers
+ //
+ if (GpioGroupInfo[Index].HostOwnOffset != NO_REGISTER_FOR_PROPERTY) {
+ MmioAndThenOr32 (
+ (UINTN)PCH_PCR_ADDRESS (GpioGroupInfo[Index].Community, GpioGroupInfo[Index].HostOwnOffset),
+ ~(UINT32)HostSoftOwnRegMask[Index],
+ (UINT32)HostSoftOwnReg[Index]
+ );
+ }
+
+ //
+ // Write GPI_GPE_EN registers
+ //
+ if (GpioGroupInfo[Index].GpiGpeEnOffset != NO_REGISTER_FOR_PROPERTY) {
+ MmioAndThenOr32 (
+ (UINTN)PCH_PCR_ADDRESS (GpioGroupInfo[Index].Community, GpioGroupInfo[Index].GpiGpeEnOffset),
+ ~(UINT32)GpiGpeEnRegMask[Index],
+ (UINT32)GpiGpeEnReg[Index]
+ );
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will clear all status bits of any GPIO interrupts.
+
+ @param[in] none
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+static
+EFI_STATUS
+GpioClearAllGpioInterrupts (
+ VOID
+ )
+{
+ GPIO_GROUP Group;
+ GPIO_GROUP_INFO *GpioGroupInfo;
+ GPIO_GROUP GpioGroupLowest;
+ GPIO_GROUP GpioGroupHighest;
+ UINT32 GroupIndex;
+ UINTN GpioGroupInfoLength;
+
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+
+ GpioGroupLowest = GpioGetLowestGroup ();
+ GpioGroupHighest = GpioGetHighestGroup ();
+
+ for (Group = GpioGroupLowest; Group <= GpioGroupHighest; Group++) {
+ GroupIndex = GpioGetGroupIndexFromGroup (Group);
+ //
+ // Check if group has GPI IS register
+ //
+ if (GpioGroupInfo[Group].GpiIsOffset != NO_REGISTER_FOR_PROPERTY) {
+ //
+ // Clear all GPI_IS Status bits by writing '1'
+ //
+ MmioWrite32 (
+ PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, GpioGroupInfo[GroupIndex].GpiIsOffset),
+ (UINT32)0xFFFFFFFF
+ );
+ }
+
+ //
+ // Check if group has GPI_GPE_STS register
+ //
+ if (GpioGroupInfo[GroupIndex].GpiGpeStsOffset != NO_REGISTER_FOR_PROPERTY) {
+ //
+ // Clear all GPI_GPE_STS Status bits by writing '1'
+ //
+ MmioWrite32 (
+ PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, GpioGroupInfo[GroupIndex].GpiGpeStsOffset),
+ (UINT32)0xFFFFFFFF
+ );
+ }
+
+ //
+ // Check if group has SMI_STS register
+ //
+ if (GpioGroupInfo[GroupIndex].SmiStsOffset != NO_REGISTER_FOR_PROPERTY) {
+ //
+ // Clear all SMI_STS Status bits by writing '1'
+ //
+ MmioWrite32 (
+ PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, GpioGroupInfo[GroupIndex].SmiStsOffset),
+ (UINT32)0xFFFFFFFF
+ );
+ }
+
+ //
+ // Check if group has NMI_STS register
+ //
+ if (GpioGroupInfo[GroupIndex].NmiStsOffset != NO_REGISTER_FOR_PROPERTY) {
+ //
+ // Clear all NMI_STS Status bits by writing '1'
+ //
+ MmioWrite32 (
+ PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, GpioGroupInfo[GroupIndex].NmiStsOffset),
+ (UINT32)0xFFFFFFFF
+ );
+ }
+
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will initialize multiple GPIO pins. Use GPIO_INIT_CONFIG structure.
+ Structure contains fields that can be used to configure each pad.
+ Pad not configured using GPIO_INIT_CONFIG will be left with hardware default values.
+ Separate fields could be set to hardware default if it does not matter, except
+ GpioPad and PadMode.
+ Some GpioPads are configured and switched to native mode by RC, those include:
+ SerialIo pins, ISH pins, ClkReq Pins
+
+ @param[in] NumberofItem Number of GPIO pads to be updated
+ @param[in] GpioInitTableAddress GPIO initialization table
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioConfigurePads (
+ IN UINT32 NumberOfItems,
+ IN GPIO_INIT_CONFIG *GpioInitTableAddress
+ )
+{
+ EFI_STATUS Status;
+ Status = GpioConfigureSklPch (NumberOfItems, GpioInitTableAddress);
+ GpioClearAllGpioInterrupts ();
+ return Status;
+}
diff --git a/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmGpioLib/GpioLib.c b/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmGpioLib/GpioLib.c
new file mode 100644
index 0000000000..0b82c2b8df
--- /dev/null
+++ b/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmGpioLib/GpioLib.c
@@ -0,0 +1,2744 @@
+/** @file
+
+Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+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.
+
+**/
+
+#include "GpioLibrary.h"
+#include <Uefi/UefiMultiPhase.h>
+#include <Pi/PiMultiPhase.h>
+#include <Library/HobLib.h>
+
+//
+// Possible registers to be accessed using GpioReadWriteReg() function
+//
+typedef enum {
+ GpioHostOwnershipRegister = 0,
+ GpioGpeEnableRegister,
+ GpioSmiEnableRegister,
+ GpioNmiEnableRegister,
+ GpioPadConfigLockRegister,
+ GpioPadLockOutputRegister
+} GPIO_REG;
+
+/**
+ This procedure will write or read GPIO Pad Configuration register
+
+ @param[in] GpioPad GPIO pad
+ @param[in] DwReg Choose PADCFG register: 0:DW0, 1:DW1
+ @param[in] Mask Mask
+ @param[in] Write Perform read(0) or write(1)
+ @param[in,out] ReadWriteValue Read/Write data
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+ @retval EFI_UNSUPPORTED Host cannot access this pad
+**/
+static
+EFI_STATUS
+GpioReadWritePadCfgReg (
+ IN GPIO_PAD GpioPad,
+ IN UINT8 DwReg,
+ IN UINT32 Mask,
+ IN BOOLEAN Write,
+ IN OUT UINT32 *ReadWriteVal
+ )
+{
+ UINT32 PadCfgReg;
+ GPIO_GROUP_INFO *GpioGroupInfo;
+ UINTN GpioGroupInfoLength;
+ UINT32 GroupIndex;
+ UINT32 PadNumber;
+
+
+ GPIO_PAD_OWN PadOwnVal;
+
+
+ GroupIndex = GpioGetGroupIndexFromGpioPad (GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+
+DEBUG_CODE_BEGIN();
+ if (!GpioIsCorrectPadForThisChipset (GpioPad)) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Incorrect GpioPad define used on this chipset (Group=%d, Pad=%d)!\n", GroupIndex, PadNumber));
+ return EFI_UNSUPPORTED;
+ }
+DEBUG_CODE_END();
+
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+
+ //
+ // Check if group argument exceeds GPIO GROUP INFO array
+ //
+ if ((UINTN)GroupIndex >= GpioGroupInfoLength) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Group argument (%d) exceeds GPIO group range\n", GroupIndex));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check if legal pin number
+ //
+ if (PadNumber >= GpioGroupInfo[GroupIndex].PadPerGroup) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Pin number (%d) exceeds possible range for this group\n", PadNumber));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Write && (DwReg == 1 || (Mask & ~B_PCH_GPIO_TX_STATE) != 0) && GpioIsPadLocked (GroupIndex, PadNumber)) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Pad is locked (Group=%d, Pad=%d)!\n", GroupIndex, PadNumber));
+ return EFI_WRITE_PROTECTED;
+ }
+
+DEBUG_CODE_BEGIN();
+ //
+ // Check if selected GPIO Pad is not owned by CSME/ISH
+ // If GPIO is not owned by Host all access to PadCfg will be dropped
+ //
+ GpioGetPadOwnership (GpioPad, &PadOwnVal);
+ if (PadOwnVal != GpioPadOwnHost) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Accessing pad not owned by host (Group=%d, Pad=%d)!\n", GroupIndex, PadNumber));
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+DEBUG_CODE_END();
+
+ //
+ // Create Pad Configuration register offset
+ //
+ PadCfgReg = 0x8 * PadNumber + GpioGroupInfo[GroupIndex].PadCfgOffset;
+ if(DwReg == 1) {
+ PadCfgReg += 0x4;
+ }
+
+ if (Write) {
+ MmioAndThenOr32 (
+ (UINTN)PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, PadCfgReg),
+ (UINT32)(~Mask),
+ (UINT32)(*ReadWriteVal & Mask)
+ );
+ } else {
+ *ReadWriteVal = MmioRead32 (PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, PadCfgReg));
+ *ReadWriteVal &= Mask;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will write or read GPIO register
+
+ @param[in] RegType GPIO register type
+ @param[in] Group GPIO group
+ @param[in] DwNum Register number for current group (parameter applicable in accessing whole register).
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[in] GpioPad GPIO pad
+ @param[in] Write Perform read(0) or write(1)
+ @param[in] OnePad Access whole register(0) or one pad(1)
+ @param[in,out] ReadWriteValue Read/Write data
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group, pad or DwNum parameter number
+**/
+static
+EFI_STATUS
+GpioReadWriteReg (
+ IN GPIO_REG RegType,
+ IN GPIO_GROUP Group,
+ IN UINT32 DwNum,
+ IN GPIO_PAD GpioPad,
+ IN BOOLEAN Write,
+ IN BOOLEAN OnePad,
+ IN OUT UINT32 *ReadWriteVal
+ )
+{
+ UINT32 Mask;
+ UINT32 RegOffset;
+ UINT32 GroupIndex;
+ UINT32 PadNumber;
+ GPIO_GROUP_INFO *GpioGroupInfo;
+ UINTN GpioGroupInfoLength;
+
+ RegOffset = 0;
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+
+ if (OnePad) {
+ GroupIndex = GpioGetGroupIndexFromGpioPad (GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+DEBUG_CODE_BEGIN();
+ if (!GpioIsCorrectPadForThisChipset (GpioPad)) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Incorrect GpioPad define used on this chipset (Group=%d, Pad=%d)!\n", GroupIndex, PadNumber));
+ return EFI_UNSUPPORTED;
+ }
+DEBUG_CODE_END();
+ } else {
+ GroupIndex = GpioGetGroupIndexFromGroup (Group);
+ PadNumber = 0;
+ }
+ //
+ // Check if group argument exceeds GPIO GROUP INFO array
+ //
+ if ((UINTN)GroupIndex >= GpioGroupInfoLength) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Group argument (%d) exceeds GPIO group range\n", GroupIndex));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ switch (RegType) {
+ case GpioHostOwnershipRegister:
+ RegOffset = GpioGroupInfo[GroupIndex].HostOwnOffset;
+ break;
+ case GpioGpeEnableRegister:
+ RegOffset = GpioGroupInfo[GroupIndex].GpiGpeEnOffset;
+ break;
+ case GpioSmiEnableRegister:
+ RegOffset = GpioGroupInfo[GroupIndex].SmiEnOffset;
+ break;
+ case GpioNmiEnableRegister:
+ RegOffset = GpioGroupInfo[GroupIndex].NmiEnOffset;
+ break;
+ case GpioPadConfigLockRegister:
+ RegOffset = GpioGroupInfo[GroupIndex].PadCfgLockOffset;
+ break;
+ case GpioPadLockOutputRegister:
+ RegOffset = GpioGroupInfo[GroupIndex].PadCfgLockTxOffset;
+ break;
+ default:
+ ASSERT (FALSE);
+ break;
+ }
+
+ //
+ // Check if selected register exists
+ //
+ if (RegOffset == NO_REGISTER_FOR_PROPERTY) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Access one GPIO Pad
+ //
+ if (OnePad) {
+ //
+ // Check if legal pin number
+ //
+ if (PadNumber >= GpioGroupInfo[GroupIndex].PadPerGroup){
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Pin number (%d) exceeds possible range for this group\n", PadNumber));
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // For future use. If there are more then 32 pads per group then certain
+ // group information would be split into more then one DWord register.
+ //
+ RegOffset += (PadNumber >> 5) * 0x4;
+ //
+ // Calculate pad bit position within DWord register
+ //
+ PadNumber %= 32;
+ Mask = BIT0 << PadNumber;
+
+ if (Write) {
+ MmioAndThenOr32 (
+ (UINTN)PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, RegOffset),
+ (UINT32)(~Mask),
+ (UINT32)((*ReadWriteVal << PadNumber) & Mask)
+ );
+ } else {
+ *ReadWriteVal = MmioRead32 (PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, RegOffset));
+ *ReadWriteVal = (*ReadWriteVal & Mask) >> PadNumber;
+ }
+ //
+ // Access whole register
+ //
+ } else {
+ //
+ // Check if DwNum argument does not exceed number of DWord registers
+ // resulting from available pads for certain group
+ //
+ if (DwNum > ((GpioGroupInfo[GroupIndex].PadPerGroup - 1) >> 5)){
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // For future use. If there are more then 32 pads per group then certain
+ // group information would be split into more then one DWord register.
+ // For SKL PCH DwNum must be 0.
+ //
+ RegOffset += DwNum *0x4;
+
+ if (Write) {
+ MmioWrite32 (
+ (UINTN)PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, RegOffset),
+ (UINT32)(*ReadWriteVal)
+ );
+ } else {
+ *ReadWriteVal = MmioRead32 (PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, RegOffset));
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will write GPIO Lock/LockTx register using SBI.
+
+ @param[in] RegType GPIO register (Lock or LockTx)
+ @param[in] Unlock Lock pads(0) or unlock(1)
+ @param[in] Group GPIO group number
+ @param[in] DwNum Register number for current group (parameter applicable in accessing whole register).
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[in] PadsToModify Bit mask for pads that are going to be modified
+ @param[in] GpioPad GPIO pad
+ @param[in] OnePad Access whole register(0) or one pad(1)
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group, pad or DwNum parameter number
+**/
+static
+EFI_STATUS
+GpioLockPadsUsingSbi (
+ IN GPIO_REG RegType,
+ IN BOOLEAN Unlock,
+ IN GPIO_GROUP Group,
+ IN UINT32 DwNum,
+ IN UINT32 PadsToModify,
+ IN GPIO_PAD GpioPad,
+ IN BOOLEAN OnePad
+ )
+{
+ UINT8 Response;
+ EFI_STATUS Status;
+ GPIO_GROUP_INFO *GpioGroupInfo;
+ UINTN GpioGroupInfoLength;
+ UINT32 RegOffset;
+ UINT32 OldPadCfgLockRegVal;
+ UINT32 NewPadCfgLockRegVal;
+ UINT32 GroupIndex;
+ UINT32 PadNumber;
+
+ RegOffset = 0;
+ OldPadCfgLockRegVal = 0;
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+
+ if (OnePad) {
+ GroupIndex = GpioGetGroupIndexFromGpioPad (GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+ Group = GpioGetGroupFromGpioPad (GpioPad);
+DEBUG_CODE_BEGIN();
+ if (!GpioIsCorrectPadForThisChipset (GpioPad)) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Incorrect GpioPad define used on this chipset (Group=%d, Pad=%d)!\n", GroupIndex, PadNumber));
+ return EFI_UNSUPPORTED;
+ }
+DEBUG_CODE_END();
+ } else {
+ GroupIndex = GpioGetGroupIndexFromGroup (Group);
+ PadNumber = 0;
+ }
+
+ //
+ // Check if group argument exceeds GPIO GROUP INFO array
+ //
+ if ((UINTN)GroupIndex >= GpioGroupInfoLength) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Group argument (%d) exceeds GPIO group range\n", GroupIndex));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ switch (RegType) {
+ case GpioPadConfigLockRegister:
+ RegOffset = GpioGroupInfo[GroupIndex].PadCfgLockOffset;
+ break;
+ case GpioPadLockOutputRegister:
+ RegOffset = GpioGroupInfo[GroupIndex].PadCfgLockTxOffset;
+ break;
+ default:
+ ASSERT (FALSE);
+ break;
+ }
+
+ //
+ // Check if selected register exists
+ //
+ if (RegOffset == NO_REGISTER_FOR_PROPERTY) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Access one GPIO Pad
+ //
+ if (OnePad) {
+ //
+ // Check if legal pin number
+ //
+ if (PadNumber >= GpioGroupInfo[GroupIndex].PadPerGroup){
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Pin number (%d) exceeds possible range for this group\n", PadNumber));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // For future use. If there are more then 32 pads per group then certain
+ // group information would be split into more then one DWord register.
+ //
+ DwNum = (PadNumber >> 5);
+ RegOffset += DwNum * 0x4;
+ //
+ // Calculate pad bit position within DWord register
+ //
+ PadNumber %= 32;
+
+ switch (RegType) {
+ case GpioPadConfigLockRegister:
+ GpioGetPadCfgLockForGroupDw (Group, DwNum, &OldPadCfgLockRegVal);
+ break;
+ case GpioPadLockOutputRegister:
+ GpioGetPadCfgLockTxForGroupDw (Group, DwNum, &OldPadCfgLockRegVal);
+ break;
+ }
+ if (Unlock) {
+ NewPadCfgLockRegVal = OldPadCfgLockRegVal & (~(0x1 << PadNumber));
+ } else {
+ NewPadCfgLockRegVal = OldPadCfgLockRegVal | (0x1 << PadNumber);
+ }
+
+ } else {
+ //
+ // Access whole register
+ //
+
+ //
+ // Check if DwNum argument does not exceed number of DWord registers
+ // resulting from available pads for certain group
+ //
+ if (DwNum > ((GpioGroupInfo[GroupIndex].PadPerGroup - 1) >> 5)){
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // For future use. If there are more then 32 pads per group then certain
+ // group information would be split into more then one DWord register.
+ // For SKL PCH DwNum must be 0.
+ //
+ RegOffset += DwNum *0x4;
+
+ switch (RegType) {
+ case GpioPadConfigLockRegister:
+ GpioGetPadCfgLockForGroupDw (Group, DwNum, &OldPadCfgLockRegVal);
+ break;
+ case GpioPadLockOutputRegister:
+ GpioGetPadCfgLockTxForGroupDw (Group, DwNum, &OldPadCfgLockRegVal);
+ break;
+ }
+ if (Unlock) {
+ NewPadCfgLockRegVal = OldPadCfgLockRegVal & (~PadsToModify);
+ } else {
+ NewPadCfgLockRegVal = OldPadCfgLockRegVal | PadsToModify;
+ }
+ }
+
+ Status = PchSbiExecution (
+ GpioGroupInfo[GroupIndex].Community,
+ RegOffset,
+ GpioLockUnlock,
+ FALSE,
+ &NewPadCfgLockRegVal,
+ &Response
+ );
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+/**
+ This procedure will read multiple GPIO settings
+
+ @param[in] GpioPad GPIO Pad
+ @param[out] GpioData GPIO data structure
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioGetPadConfig (
+ IN GPIO_PAD GpioPad,
+ OUT GPIO_CONFIG *GpioData
+ )
+{
+ UINT32 Dw0Reg;
+ UINT32 Dw1Reg;
+ UINT32 PadCfgReg;
+ UINT32 RegVal;
+ GPIO_GROUP_INFO *GpioGroupInfo;
+ UINTN GpioGroupInfoLength;
+ GPIO_GROUP Group;
+ UINT32 GroupIndex;
+ UINT32 PadNumber;
+
+ GPIO_PAD_OWN PadOwnVal;
+
+
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+
+ Group = GpioGetGroupFromGpioPad (GpioPad);
+ GroupIndex = GpioGetGroupIndexFromGpioPad (GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+
+DEBUG_CODE_BEGIN();
+ if (!GpioIsCorrectPadForThisChipset (GpioPad)) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Incorrect GpioPad define used on this chipset (Group=%d, Pad=%d)!\n", GroupIndex, PadNumber));
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ GpioGetPadOwnership (GpioPad, &PadOwnVal);
+ if (PadOwnVal != GpioPadOwnHost) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Accessing pad not owned by host (Group=%d, Pad=%d)!\n", GroupIndex, PadNumber));
+ return EFI_UNSUPPORTED;
+ }
+DEBUG_CODE_END();
+
+ //
+ // Check if group argument exceeds GPIO group range
+ //
+ if ((Group < GpioGetLowestGroup ()) || (Group > GpioGetHighestGroup ())) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Group argument (%d) exceeds GPIO group range\n", GroupIndex));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check if legal pin number
+ //
+ if (PadNumber >= GpioGroupInfo[GroupIndex].PadPerGroup){
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Pin number (%d) exceeds possible range for this group\n", PadNumber));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Create PADCFG register offset using group and pad number
+ //
+ PadCfgReg = 0x8 * PadNumber + GpioGroupInfo[GroupIndex].PadCfgOffset;
+
+ //
+ // Read PADCFG DW0 register
+ //
+ Dw0Reg = MmioRead32 ((UINTN)PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, PadCfgReg));
+
+ //
+ // Read PADCFG DW1 register
+ //
+ Dw1Reg = MmioRead32 ((UINTN)PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, PadCfgReg + 0x4));
+
+
+ //
+ // Get Reset Type (PadRstCfg)
+ //
+ GpioData->PowerConfig = ((Dw0Reg & B_PCH_GPIO_RST_CONF) >> (N_PCH_GPIO_RST_CONF - (GPIO_CONF_RESET_BIT_POS + 1))) | (0x1 << GPIO_CONF_RESET_BIT_POS);
+
+ //
+ // Get how interrupt is triggered (RxEvCfg)
+ //
+ GpioData->InterruptConfig = ((Dw0Reg & B_PCH_GPIO_RX_LVL_EDG) >> (N_PCH_GPIO_RX_LVL_EDG - (GPIO_CONF_INT_TRIG_BIT_POS + 1))) | (0x1 << GPIO_CONF_INT_TRIG_BIT_POS);
+
+ //
+ // Get interrupt generation (GPIRoutIOxAPIC/SCI/SMI/NMI)
+ //
+ GpioData->InterruptConfig |= ((Dw0Reg & (B_PCH_GPIO_RX_NMI_ROUTE | B_PCH_GPIO_RX_SCI_ROUTE | B_PCH_GPIO_RX_SMI_ROUTE | B_PCH_GPIO_RX_APIC_ROUTE)) >> (N_PCH_GPIO_RX_NMI_ROUTE - (GPIO_CONF_INT_ROUTE_BIT_POS + 1))) | (0x1 << GPIO_CONF_INT_ROUTE_BIT_POS);
+
+ //
+ // Get GPIO direction (GPIORxDis and GPIOTxDis)
+ //
+ GpioData->Direction = ((Dw0Reg & (B_PCH_GPIO_RXDIS | B_PCH_GPIO_TXDIS)) >> (N_PCH_GPIO_TXDIS - (GPIO_CONF_DIR_BIT_POS + 1))) | (0x1 << GPIO_CONF_DIR_BIT_POS);
+
+ //
+ // Get GPIO input inversion (RXINV)
+ //
+ GpioData->Direction |= ((Dw0Reg & B_PCH_GPIO_RXINV) >> (N_PCH_GPIO_RXINV - (GPIO_CONF_INV_BIT_POS + 1))) | (0x1 << GPIO_CONF_INV_BIT_POS);
+
+ //
+ // Get GPIO output state (GPIOTxState)
+ //
+ GpioData->OutputState = ((Dw0Reg & B_PCH_GPIO_TX_STATE) << (N_PCH_GPIO_TX_STATE + (GPIO_CONF_OUTPUT_BIT_POS + 1))) | (0x1 << GPIO_CONF_OUTPUT_BIT_POS) ;
+
+ //
+ // Configure GPIO RX raw override to '1' (RXRAW1)
+ //
+ GpioData->OtherSettings = ((Dw0Reg & B_PCH_GPIO_RX_RAW1) >> (N_PCH_GPIO_RX_RAW1 - (GPIO_CONF_RXRAW_BIT_POS + 1))) | (0x1 << GPIO_CONF_RXRAW_BIT_POS) ;
+
+ //
+ // Get GPIO Pad Mode (PMode)
+ //
+ GpioData->PadMode = ((Dw0Reg & B_PCH_GPIO_PAD_MODE) >> (N_PCH_GPIO_PAD_MODE - (GPIO_CONF_PAD_MODE_BIT_POS + 1))) | (0x1 << GPIO_CONF_PAD_MODE_BIT_POS);
+
+ //
+ // Get GPIO termination (Term)
+ //
+ GpioData->ElectricalConfig = ((Dw1Reg & B_PCH_GPIO_TERM) >> (N_PCH_GPIO_TERM - (GPIO_CONF_TERM_BIT_POS + 1))) | (0x1 << GPIO_CONF_TERM_BIT_POS) ;
+
+ //
+ // Get GPIO pad tolerance (padtol)
+ //
+ GpioData->ElectricalConfig |= ((Dw1Reg & B_PCH_GPIO_PADTOL) >> (N_PCH_GPIO_PADTOL - (GPIO_CONF_PADTOL_BIT_POS + 1))) | (0x1 << GPIO_CONF_PADTOL_BIT_POS) ;
+
+ //
+ // Read HOSTSW_OWN registers
+ //
+ RegVal = MmioRead32 ((UINTN)PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, GpioGroupInfo[GroupIndex].HostOwnOffset));
+
+ //
+ // Get Host Software Ownership
+ //
+ GpioData->HostSoftPadOwn = (((RegVal >> PadNumber) & 0x1) << (GPIO_CONF_HOST_OWN_BIT_POS + 1)) | (0x1 << GPIO_CONF_HOST_OWN_BIT_POS);
+
+ //
+ // Read PADCFGLOCK register
+ //
+ RegVal = MmioRead32 ((UINTN)PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, GpioGroupInfo[GroupIndex].PadCfgLockOffset));
+
+ //
+ // Get Pad Configuration Lock state
+ //
+ GpioData->LockConfig = (((RegVal >> PadNumber) & 0x1) << 1) | 0x1;
+
+ //
+ // Read PADCFGLOCKTX register
+ //
+ RegVal = MmioRead32 ((UINTN)PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, GpioGroupInfo[GroupIndex].PadCfgLockTxOffset));
+
+ //
+ // Get Pad Configuration Lock Tx state
+ //
+ GpioData->LockConfig |= (((RegVal >> PadNumber) & 0x1) << 2) | 0x1;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will configure multiple GPIO settings
+
+ @param[in] GpioPad GPIO Pad
+ @param[in] GpioData GPIO data structure
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioSetPadConfig (
+ IN GPIO_PAD GpioPad,
+ IN GPIO_CONFIG *GpioData
+ )
+{
+ UINT32 Dw0Reg;
+ UINT32 Dw0RegMask;
+ UINT32 Dw1Reg;
+ UINT32 Dw1RegMask;
+ UINT32 PadCfgReg;
+ UINT32 HostSoftOwnReg;
+ UINT32 HostSoftOwnRegMask;
+ UINT32 GpiGpeEnReg;
+ UINT32 GpiGpeEnRegMask;
+ GPIO_GROUP_INFO *GpioGroupInfo;
+ UINTN GpioGroupInfoLength;
+ GPIO_GROUP Group;
+ UINT32 GroupIndex;
+ UINT32 PadNumber;
+
+ GPIO_PAD_OWN PadOwnVal;
+
+
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+
+ Dw0RegMask = 0;
+ Dw0Reg = 0;
+ Dw1RegMask = 0;
+ Dw1Reg = 0;
+
+ Group = GpioGetGroupFromGpioPad (GpioPad);
+ GroupIndex = GpioGetGroupIndexFromGpioPad (GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+
+DEBUG_CODE_BEGIN();
+ if (!GpioIsCorrectPadForThisChipset (GpioPad)) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Incorrect GpioPad define used on this chipset (Group=%d, Pad=%d)!\n", GroupIndex, PadNumber));
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ GpioGetPadOwnership (GpioPad, &PadOwnVal);
+ if (PadOwnVal != GpioPadOwnHost) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Accessing pad not owned by host (Group=%d, Pad=%d)!\n", GroupIndex, PadNumber));
+ return EFI_UNSUPPORTED;
+ }
+DEBUG_CODE_END();
+ //
+ // Check if group argument exceeds GPIO group range
+ //
+ if ((Group < GpioGetLowestGroup ()) || (Group > GpioGetHighestGroup ())) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Group argument (%d) exceeds GPIO group range\n", GroupIndex));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check if legal pin number
+ //
+ if (PadNumber >= GpioGroupInfo[GroupIndex].PadPerGroup) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Pin number (%d) exceeds possible range for this group\n", PadNumber));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (GpioIsPadLocked (GroupIndex, PadNumber)) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Pad is locked (Group=%d, Pad=%d)!\n", GroupIndex, PadNumber));
+ return EFI_WRITE_PROTECTED;
+ }
+
+ //
+ // Configure Reset Type (PadRstCfg)
+ //
+ Dw0RegMask |= ((((GpioData->PowerConfig & GPIO_CONF_RESET_MASK) >> GPIO_CONF_RESET_BIT_POS) == GpioHardwareDefault) ? 0x0 : B_PCH_GPIO_RST_CONF);
+ Dw0Reg |= (((GpioData->PowerConfig & GPIO_CONF_RESET_MASK) >> (GPIO_CONF_RESET_BIT_POS + 1)) << N_PCH_GPIO_RST_CONF);
+
+ //
+ // Configure how interrupt is triggered (RxEvCfg)
+ //
+ Dw0RegMask |= ((((GpioData->InterruptConfig & GPIO_CONF_INT_TRIG_MASK) >> GPIO_CONF_INT_TRIG_BIT_POS) == GpioHardwareDefault) ? 0x0 : B_PCH_GPIO_RX_LVL_EDG);
+ Dw0Reg |= (((GpioData->InterruptConfig & GPIO_CONF_INT_TRIG_MASK) >> (GPIO_CONF_INT_TRIG_BIT_POS + 1)) << N_PCH_GPIO_RX_LVL_EDG);
+
+ //
+ // Configure interrupt generation (GPIRoutIOxAPIC/SCI/SMI/NMI)
+ //
+ Dw0RegMask |= ((((GpioData->InterruptConfig & GPIO_CONF_INT_ROUTE_MASK) >> GPIO_CONF_INT_ROUTE_BIT_POS) == GpioHardwareDefault) ? 0x0 : (B_PCH_GPIO_RX_NMI_ROUTE | B_PCH_GPIO_RX_SCI_ROUTE | B_PCH_GPIO_RX_SMI_ROUTE | B_PCH_GPIO_RX_APIC_ROUTE));
+ Dw0Reg |= (((GpioData->InterruptConfig & GPIO_CONF_INT_ROUTE_MASK) >> (GPIO_CONF_INT_ROUTE_BIT_POS + 1)) << N_PCH_GPIO_RX_NMI_ROUTE);
+
+ //
+ // Configure GPIO direction (GPIORxDis and GPIOTxDis)
+ //
+ Dw0RegMask |= ((((GpioData->Direction & GPIO_CONF_DIR_MASK) >> GPIO_CONF_DIR_BIT_POS) == GpioHardwareDefault) ? 0x0 : (B_PCH_GPIO_RXDIS | B_PCH_GPIO_TXDIS));
+ Dw0Reg |= (((GpioData->Direction & GPIO_CONF_DIR_MASK) >> (GPIO_CONF_DIR_BIT_POS + 1)) << N_PCH_GPIO_TXDIS);
+
+ //
+ // Configure GPIO input inversion (RXINV)
+ //
+ Dw0RegMask |= ((((GpioData->Direction & GPIO_CONF_INV_MASK) >> GPIO_CONF_INV_BIT_POS) == GpioHardwareDefault) ? 0x0 : B_PCH_GPIO_RXINV);
+ Dw0Reg |= (((GpioData->Direction & GPIO_CONF_INV_MASK) >> (GPIO_CONF_INV_BIT_POS + 1)) << N_PCH_GPIO_RXINV);
+
+ //
+ // Configure GPIO output state (GPIOTxState)
+ //
+ Dw0RegMask |= ((((GpioData->OutputState & GPIO_CONF_OUTPUT_MASK) >> GPIO_CONF_OUTPUT_BIT_POS) == GpioHardwareDefault) ? 0x0 : B_PCH_GPIO_TX_STATE);
+ Dw0Reg |= (((GpioData->OutputState & GPIO_CONF_OUTPUT_MASK) >> (GPIO_CONF_OUTPUT_BIT_POS + 1)) << N_PCH_GPIO_TX_STATE);
+
+ //
+ // Configure GPIO RX raw override to '1' (RXRAW1)
+ //
+ Dw0RegMask |= ((((GpioData->OtherSettings & GPIO_CONF_RXRAW_MASK) >> GPIO_CONF_RXRAW_BIT_POS) == GpioHardwareDefault) ? 0x0 : B_PCH_GPIO_RX_RAW1);
+ Dw0Reg |= (((GpioData->OtherSettings & GPIO_CONF_RXRAW_MASK) >> (GPIO_CONF_RXRAW_BIT_POS + 1)) << N_PCH_GPIO_RX_RAW1);
+
+ //
+ // Configure GPIO Pad Mode (PMode)
+ //
+ Dw0RegMask |= ((((GpioData->PadMode & GPIO_CONF_PAD_MODE_MASK) >> GPIO_CONF_PAD_MODE_BIT_POS) == GpioHardwareDefault) ? 0x0 : B_PCH_GPIO_PAD_MODE);
+ Dw0Reg |= (((GpioData->PadMode & GPIO_CONF_PAD_MODE_MASK) >> (GPIO_CONF_PAD_MODE_BIT_POS + 1)) << N_PCH_GPIO_PAD_MODE);
+
+ //
+ // Configure GPIO termination (Term)
+ //
+ Dw1RegMask |= ((((GpioData->ElectricalConfig & GPIO_CONF_TERM_MASK) >> GPIO_CONF_TERM_BIT_POS) == GpioHardwareDefault) ? 0x0 : B_PCH_GPIO_TERM);
+ Dw1Reg |= (((GpioData->ElectricalConfig & GPIO_CONF_TERM_MASK) >> (GPIO_CONF_TERM_BIT_POS + 1)) << N_PCH_GPIO_TERM);
+
+ //
+ // Configure GPIO pad tolerance (padtol)
+ //
+ Dw1RegMask |= ((((GpioData->ElectricalConfig & GPIO_CONF_PADTOL_MASK) >> GPIO_CONF_PADTOL_BIT_POS) == GpioHardwareDefault) ? 0x0 : B_PCH_GPIO_PADTOL);
+ Dw1Reg |= (((GpioData->ElectricalConfig & GPIO_CONF_PADTOL_MASK) >> (GPIO_CONF_PADTOL_BIT_POS + 1)) << N_PCH_GPIO_PADTOL);
+
+ //
+ // Create PADCFG register offset using group and pad number
+ //
+ PadCfgReg = 0x8 * PadNumber + GpioGroupInfo[GroupIndex].PadCfgOffset;
+
+ //
+ // Write PADCFG DW0 register
+ //
+ MmioAndThenOr32 (
+ (UINTN)PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, PadCfgReg),
+ ~(UINT32)Dw0RegMask,
+ (UINT32)Dw0Reg
+ );
+
+ //
+ // Write PADCFG DW1 register
+ //
+ MmioAndThenOr32 (
+ (UINTN)PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, PadCfgReg + 0x4),
+ ~(UINT32)Dw1RegMask,
+ (UINT32)Dw1Reg
+ );
+
+ //
+ // Update value to be programmed in HOSTSW_OWN register
+ //
+ HostSoftOwnRegMask = (GpioData->HostSoftPadOwn & 0x1) << PadNumber;
+ HostSoftOwnReg = (GpioData->HostSoftPadOwn >> 0x1) << PadNumber;
+
+ //
+ // Write HOSTSW_OWN registers
+ //
+ MmioAndThenOr32 (
+ (UINTN)PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, GpioGroupInfo[GroupIndex].HostOwnOffset),
+ ~(UINT32)HostSoftOwnRegMask,
+ (UINT32)HostSoftOwnReg
+ );
+
+ //
+ // Update value to be programmed in GPI_GPE_EN register
+ //
+ GpiGpeEnRegMask = (GpioData->InterruptConfig & 0x1) << PadNumber;
+ GpiGpeEnReg = ((GpioData->InterruptConfig & GpioIntSci) >> 3) << PadNumber;
+
+ //
+ // Write GPI_GPE_EN registers
+ //
+ MmioAndThenOr32 (
+ (UINTN)PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, GpioGroupInfo[GroupIndex].GpiGpeEnOffset),
+ ~(UINT32)GpiGpeEnRegMask,
+ (UINT32)GpiGpeEnReg
+ );
+
+ //
+ // Program Pad Configuration Lock
+ //
+ if ((GpioData->LockConfig & GpioPadConfigLock) == GpioPadConfigLock) {
+ GpioLockPadsUsingSbi (
+ GpioPadConfigLockRegister,
+ FALSE,
+ 0,
+ 0,
+ 0,
+ GpioPad,
+ TRUE
+ );
+ }
+
+ //
+ // Program Pad Configuration Lock Tx
+ //
+ if ((GpioData->LockConfig & GpioOutputStateLock) == GpioOutputStateLock) {
+ GpioLockPadsUsingSbi (
+ GpioPadLockOutputRegister,
+ FALSE,
+ 0,
+ 0,
+ 0,
+ GpioPad,
+ TRUE
+ );
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will set GPIO output level
+
+ @param[in] GpioPad GPIO pad
+ @param[in] Value Output value
+ 0: OutputLow, 1: OutputHigh
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioSetOutputValue (
+ IN GPIO_PAD GpioPad,
+ IN UINT32 Value
+ )
+{
+ EFI_STATUS Status;
+
+ Status = GpioReadWritePadCfgReg (
+ GpioPad,
+ 0,
+ B_PCH_GPIO_TX_STATE,
+ TRUE,
+ &Value
+ );
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+/**
+ This procedure will get GPIO output level
+
+ @param[in] GpioPad GPIO pad
+ @param[out] OutputVal GPIO Output value
+ 0: OutputLow, 1: OutputHigh
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioGetOutputValue (
+ IN GPIO_PAD GpioPad,
+ OUT UINT32 *OutputVal
+ )
+{
+ EFI_STATUS Status;
+
+ Status = GpioReadWritePadCfgReg (
+ GpioPad,
+ 0,
+ B_PCH_GPIO_TX_STATE,
+ FALSE,
+ OutputVal
+ );
+ ASSERT_EFI_ERROR (Status);
+ *OutputVal >>= N_PCH_GPIO_TX_STATE;
+
+ return Status;
+}
+
+/**
+ This procedure will get GPIO input level
+
+ @param[in] GpioPad GPIO pad
+ @param[out] InputVal GPIO Input value
+ 0: InputLow, 1: InpuHigh
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioGetInputValue (
+ IN GPIO_PAD GpioPad,
+ OUT UINT32 *InputVal
+ )
+{
+ EFI_STATUS Status;
+
+ Status = GpioReadWritePadCfgReg (
+ GpioPad,
+ 0,
+ B_PCH_GPIO_RX_STATE,
+ FALSE,
+ InputVal
+ );
+ ASSERT_EFI_ERROR (Status);
+ *InputVal >>= N_PCH_GPIO_RX_STATE;
+
+ return Status;
+}
+
+/**
+ This procedure will get GPIO IOxAPIC interrupt number
+
+ @param[in] GpioPad GPIO pad
+ @param[out] IrqNum IRQ number
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioGetPadIoApicIrqNumber (
+ IN GPIO_PAD GpioPad,
+ OUT UINT32 *IrqNum
+ )
+{
+ EFI_STATUS Status;
+
+ Status = GpioReadWritePadCfgReg (
+ GpioPad,
+ 1,
+ B_PCH_GPIO_INTSEL,
+ FALSE,
+ IrqNum
+ );
+ ASSERT_EFI_ERROR (Status);
+ *IrqNum >>= N_PCH_GPIO_INTSEL;
+
+ return Status;
+}
+
+/**
+ This procedure will configure GPIO input inversion
+
+ @param[in] GpioPad GPIO pad
+ @param[in] Value Value for GPIO input inversion
+ 0: No input inversion, 1: Invert input
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioSetInputInversion (
+ IN GPIO_PAD GpioPad,
+ IN UINT32 Value
+ )
+{
+ EFI_STATUS Status;
+
+ Value <<= N_PCH_GPIO_RXINV;
+ Status = GpioReadWritePadCfgReg (
+ GpioPad,
+ 0,
+ B_PCH_GPIO_RXINV,
+ TRUE,
+ &Value
+ );
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+/**
+ This procedure will get GPIO pad input inversion value
+
+ @param[in] GpioPad GPIO pad
+ @param[out] InvertState GPIO inversion state
+ 0: No input inversion, 1: Inverted input
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioGetInputInversion (
+ IN GPIO_PAD GpioPad,
+ OUT UINT32 *InvertState
+ )
+{
+ EFI_STATUS Status;
+
+ Status = GpioReadWritePadCfgReg (
+ GpioPad,
+ 0,
+ B_PCH_GPIO_RXINV,
+ FALSE,
+ InvertState
+ );
+ ASSERT_EFI_ERROR (Status);
+ *InvertState >>= N_PCH_GPIO_RXINV;
+
+ return Status;
+}
+
+/**
+ This procedure will set GPIO interrupt settings
+
+ @param[in] GpioPad GPIO pad
+ @param[in] Value Value of Level/Edge
+ use GPIO_INT_CONFIG as argument
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioSetPadInterruptConfig (
+ IN GPIO_PAD GpioPad,
+ IN GPIO_INT_CONFIG Value
+ )
+{
+ EFI_STATUS Status;
+ UINT32 RxLvlEdgeValue;
+ UINT32 IntRouteValue;
+ UINT32 GpeEnable;
+
+ Status = EFI_SUCCESS;
+
+ if (((Value & GPIO_CONF_INT_TRIG_MASK) >> GPIO_CONF_INT_TRIG_BIT_POS) != GpioHardwareDefault) {
+ RxLvlEdgeValue = ((Value & GPIO_CONF_INT_TRIG_MASK) >> (GPIO_CONF_INT_TRIG_BIT_POS + 1)) << N_PCH_GPIO_RX_LVL_EDG;
+
+ Status = GpioReadWritePadCfgReg (
+ GpioPad,
+ 0,
+ B_PCH_GPIO_RX_LVL_EDG,
+ TRUE,
+ &RxLvlEdgeValue
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ if (((Value & GPIO_CONF_INT_ROUTE_MASK) >> GPIO_CONF_INT_ROUTE_BIT_POS) != GpioHardwareDefault) {
+
+ IntRouteValue = ((Value & GPIO_CONF_INT_ROUTE_MASK) >> (GPIO_CONF_INT_ROUTE_BIT_POS + 1)) << N_PCH_GPIO_RX_NMI_ROUTE;
+
+ Status = GpioReadWritePadCfgReg (
+ GpioPad,
+ 0,
+ (B_PCH_GPIO_RX_NMI_ROUTE | B_PCH_GPIO_RX_SCI_ROUTE | B_PCH_GPIO_RX_SMI_ROUTE | B_PCH_GPIO_RX_APIC_ROUTE),
+ TRUE,
+ &IntRouteValue
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ if ((Value & GpioIntSci) == GpioIntSci) {
+ GpeEnable = 0x1;
+ } else {
+ GpeEnable = 0x0;
+ }
+
+ Status = GpioReadWriteReg (
+ GpioGpeEnableRegister,
+ 0,
+ 0,
+ GpioPad,
+ TRUE,
+ TRUE,
+ &GpeEnable
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ return Status;
+}
+
+/**
+ This procedure will set GPIO electrical settings
+
+ @param[in] GpioPad GPIO pad
+ @param[in] Value Value of termination
+ use GPIO_ELECTRICAL_CONFIG as argument
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioSetPadElectricalConfig (
+ IN GPIO_PAD GpioPad,
+ IN GPIO_ELECTRICAL_CONFIG Value
+ )
+{
+ EFI_STATUS Status;
+ UINT32 TermValue;
+ UINT32 PadTolValue;
+
+ Status = EFI_SUCCESS;
+
+ if (((Value & GPIO_CONF_TERM_MASK) >> GPIO_CONF_TERM_BIT_POS) != GpioHardwareDefault) {
+ TermValue = ((Value & GPIO_CONF_TERM_MASK) >> (GPIO_CONF_TERM_BIT_POS + 1)) << N_PCH_GPIO_TERM;
+
+ Status = GpioReadWritePadCfgReg (
+ GpioPad,
+ 1,
+ B_PCH_GPIO_TERM,
+ TRUE,
+ &TermValue
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ if (((Value & GPIO_CONF_PADTOL_MASK) >> GPIO_CONF_PADTOL_BIT_POS) != GpioHardwareDefault) {
+ PadTolValue = ((Value & GPIO_CONF_PADTOL_MASK) >> (GPIO_CONF_PADTOL_BIT_POS + 1)) << N_PCH_GPIO_PADTOL;
+
+ Status = GpioReadWritePadCfgReg (
+ GpioPad,
+ 1,
+ B_PCH_GPIO_PADTOL,
+ TRUE,
+ &PadTolValue
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+ return Status;
+}
+
+/**
+ This procedure will set GPIO Reset settings
+
+ @param[in] GpioPad GPIO pad
+ @param[in] Value Value for Pad Reset Configuration
+ use GPIO_RESET_CONFIG as argument
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioSetPadResetConfig (
+ IN GPIO_PAD GpioPad,
+ IN GPIO_RESET_CONFIG Value
+ )
+{
+ EFI_STATUS Status;
+ UINT32 ResetValue;
+
+ Status = EFI_SUCCESS;
+
+ if (((Value & GPIO_CONF_RESET_MASK) >> GPIO_CONF_RESET_BIT_POS) != GpioHardwareDefault) {
+ ResetValue = ((Value & GPIO_CONF_RESET_MASK) >> (GPIO_CONF_RESET_BIT_POS + 1)) << N_PCH_GPIO_RST_CONF;
+
+ Status = GpioReadWritePadCfgReg (
+ GpioPad,
+ 0,
+ B_PCH_GPIO_RST_CONF,
+ TRUE,
+ &ResetValue
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+ return Status;
+}
+
+/**
+ This procedure will get GPIO Reset settings
+
+ @param[in] GpioPad GPIO pad
+ @param[in] Value Value of Pad Reset Configuration
+ based on GPIO_RESET_CONFIG
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioGetPadResetConfig (
+ IN GPIO_PAD GpioPad,
+ IN GPIO_RESET_CONFIG *Value
+ )
+{
+ EFI_STATUS Status;
+ UINT32 ResetValue;
+
+ Status = GpioReadWritePadCfgReg (
+ GpioPad,
+ 0,
+ B_PCH_GPIO_RST_CONF,
+ FALSE,
+ &ResetValue
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Get Reset Type (PadRstCfg)
+ //
+ *Value = (ResetValue >> (N_PCH_GPIO_RST_CONF - (GPIO_CONF_RESET_BIT_POS + 1))) | (0x1 << GPIO_CONF_RESET_BIT_POS);
+
+ return Status;
+}
+
+/**
+ This procedure will get GPIO Host Software Pad Ownership for certain group
+
+ @param[in] Group GPIO group
+ @param[in] DwNum Host Ownership register number for current group.
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[out] HostSwRegVal Value of Host Software Pad Ownership register
+ Bit position - PadNumber
+ Bit value - 0: ACPI Mode, 1: GPIO Driver mode
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or DwNum parameter number
+**/
+EFI_STATUS
+GpioGetHostSwOwnershipForGroupDw (
+ IN GPIO_GROUP Group,
+ IN UINT32 DwNum,
+ OUT UINT32 *HostSwRegVal
+ )
+{
+ EFI_STATUS Status;
+
+ Status = GpioReadWriteReg (
+ GpioHostOwnershipRegister,
+ Group,
+ DwNum,
+ 0,
+ FALSE,
+ FALSE,
+ HostSwRegVal
+ );
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+/**
+ This procedure will get GPIO Host Software Pad Ownership for certain group
+
+ @param[in] Group GPIO group
+ @param[in] DwNum Host Ownership register number for current group
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[in] HostSwRegVal Value of Host Software Pad Ownership register
+ Bit position - PadNumber
+ Bit value - 0: ACPI Mode, 1: GPIO Driver mode
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or DwNum parameter number
+**/
+EFI_STATUS
+GpioSetHostSwOwnershipForGroupDw (
+ IN GPIO_GROUP Group,
+ IN UINT32 DwNum,
+ IN UINT32 HostSwRegVal
+ )
+{
+ EFI_STATUS Status;
+
+ Status = GpioReadWriteReg (
+ GpioHostOwnershipRegister,
+ Group,
+ DwNum,
+ 0,
+ TRUE,
+ FALSE,
+ &HostSwRegVal
+ );
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+/**
+ This procedure will get Gpio Pad Host Software Ownership
+
+ @param[in] GpioPad GPIO pad
+ @param[out] PadHostSwOwn Value of Host Software Pad Owner
+ 0: ACPI Mode, 1: GPIO Driver mode
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioGetHostSwOwnershipForPad (
+ IN GPIO_PAD GpioPad,
+ OUT UINT32 *PadHostSwOwn
+ )
+{
+ EFI_STATUS Status;
+
+ Status = GpioReadWriteReg (
+ GpioHostOwnershipRegister,
+ 0,
+ 0,
+ GpioPad,
+ FALSE,
+ TRUE,
+ PadHostSwOwn
+ );
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+/**
+ This procedure will set Gpio Pad Host Software Ownership
+
+ @param[in] GpioPad GPIO pad
+ @param[in] PadHostSwOwn Pad Host Software Owner
+ 0: ACPI Mode, 1: GPIO Driver mode
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioSetHostSwOwnershipForPad (
+ IN GPIO_PAD GpioPad,
+ IN UINT32 PadHostSwOwn
+ )
+{
+ EFI_STATUS Status;
+
+ Status = GpioReadWriteReg (
+ GpioHostOwnershipRegister,
+ 0,
+ 0,
+ GpioPad,
+ TRUE,
+ TRUE,
+ &PadHostSwOwn
+ );
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+/**
+ This procedure will get Gpio Pad Ownership
+
+ @param[in] GpioPad GPIO pad
+ @param[out] PadOwnVal Value of Pad Ownership
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioGetPadOwnership (
+ IN GPIO_PAD GpioPad,
+ OUT GPIO_PAD_OWN *PadOwnVal
+ )
+{
+ UINT32 Mask;
+ UINT32 RegOffset;
+ UINT32 GroupIndex;
+ UINT32 PadNumber;
+ GPIO_GROUP_INFO *GpioGroupInfo;
+ UINTN GpioGroupInfoLength;
+ UINT32 PadOwnRegValue;
+
+ GroupIndex = GpioGetGroupIndexFromGpioPad (GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+
+ //
+ // Check if group argument exceeds GPIO GROUP INFO array
+ //
+ if ((UINTN)GroupIndex >= GpioGroupInfoLength) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Group argument (%d) exceeds GPIO group range\n", GroupIndex));
+ ASSERT(FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check if legal pin number
+ //
+ if (PadNumber >= GpioGroupInfo[GroupIndex].PadPerGroup) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Pin number (%d) exceeds possible range for this group\n", PadNumber));
+ ASSERT(FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Calculate RegOffset using Pad Ownership offset and GPIO Pad number.
+ // One DWord register contains information for 8 pads.
+ //
+ RegOffset = GpioGroupInfo[GroupIndex].PadOwnOffset + (PadNumber >> 3) * 0x4;
+
+ //
+ // Calculate pad bit position within DWord register
+ //
+ PadNumber %= 8;
+ Mask = (BIT1 | BIT0) << (PadNumber * 4);
+
+ PadOwnRegValue = MmioRead32 (PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, RegOffset));
+
+ *PadOwnVal = (GPIO_PAD_OWN)((PadOwnRegValue & Mask) >> (PadNumber * 4));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will check state of Pad Config Lock for pads within one group
+
+ @param[in] Group GPIO group
+ @param[in] DwNum PadCfgLock register number for current group.
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[out] PadCfgLockRegVal Value of PadCfgLock register
+ Bit position - PadNumber
+ Bit value - 0: NotLocked, 1: Locked
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or DwNum parameter number
+**/
+EFI_STATUS
+GpioGetPadCfgLockForGroupDw (
+ IN GPIO_GROUP Group,
+ IN UINT32 DwNum,
+ OUT UINT32 *PadCfgLockRegVal
+ )
+{
+ EFI_STATUS Status;
+
+ Status = GpioReadWriteReg (
+ GpioPadConfigLockRegister,
+ Group,
+ DwNum,
+ 0,
+ FALSE,
+ FALSE,
+ PadCfgLockRegVal
+ );
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+/**
+ This procedure will check state of Pad Config Lock for selected pad
+
+ @param[in] GpioPad GPIO pad
+ @param[out] PadCfgLock PadCfgLock for selected pad
+ 0: NotLocked, 1: Locked
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioGetPadCfgLock (
+ IN GPIO_PAD GpioPad,
+ OUT UINT32 *PadCfgLock
+ )
+{
+ EFI_STATUS Status;
+
+ Status = GpioReadWriteReg (
+ GpioPadConfigLockRegister,
+ 0,
+ 0,
+ GpioPad,
+ FALSE,
+ TRUE,
+ PadCfgLock
+ );
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+/**
+ This procedure will check state of Pad Config Tx Lock for pads within one group
+
+ @param[in] Group GPIO group
+ @param[in] DwNum PadCfgLockTx register number for current group.
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[out] PadCfgLockTxRegVal Value of PadCfgLockTx register
+ Bit position - PadNumber
+ Bit value - 0: NotLockedTx, 1: LockedTx
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or DwNum parameter number
+**/
+EFI_STATUS
+GpioGetPadCfgLockTxForGroupDw (
+ IN GPIO_GROUP Group,
+ IN UINT32 DwNum,
+ OUT UINT32 *PadCfgLockTxRegVal
+ )
+{
+ EFI_STATUS Status;
+
+ Status = GpioReadWriteReg (
+ GpioPadLockOutputRegister,
+ Group,
+ DwNum,
+ 0,
+ FALSE,
+ FALSE,
+ PadCfgLockTxRegVal
+ );
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+/**
+ This procedure will check state of Pad Config Tx Lock for selected pad
+
+ @param[in] GpioPad GPIO pad
+ @param[out] PadCfgLock PadCfgLockTx for selected pad
+ 0: NotLockedTx, 1: LockedTx
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioGetPadCfgLockTx (
+ IN GPIO_PAD GpioPad,
+ OUT UINT32 *PadCfgLockTx
+ )
+{
+ EFI_STATUS Status;
+
+ Status = GpioReadWriteReg (
+ GpioPadLockOutputRegister,
+ 0,
+ 0,
+ GpioPad,
+ FALSE,
+ TRUE,
+ PadCfgLockTx
+ );
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+/**
+ This procedure will clear PadCfgLock for selected pads within one group.
+ This function should be used only inside SMI.
+
+ @param[in] Group GPIO group
+ @param[in] DwNum PadCfgLock register number for current group.
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[in] PadsToUnlock Bitmask for pads which are going to be unlocked,
+ Bit position - PadNumber
+ Bit value - 0: DoNotUnlock, 1: Unlock
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioUnlockPadCfgForGroupDw (
+ IN GPIO_GROUP Group,
+ IN UINT32 DwNum,
+ IN UINT32 PadsToUnlock
+ )
+{
+ EFI_STATUS Status;
+
+ Status = GpioLockPadsUsingSbi (
+ GpioPadConfigLockRegister,
+ TRUE,
+ Group,
+ DwNum,
+ PadsToUnlock,
+ 0,
+ FALSE
+ );
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+/**
+ This procedure will clear PadCfgLock for selected pad.
+ This function should be used only inside SMI.
+
+ @param[in] GpioPad GPIO pad
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioUnlockPadCfg (
+ IN GPIO_PAD GpioPad
+ )
+{
+ EFI_STATUS Status;
+
+ Status = GpioLockPadsUsingSbi (
+ GpioPadConfigLockRegister,
+ TRUE,
+ 0,
+ 0,
+ 0,
+ GpioPad,
+ TRUE
+ );
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+/**
+ This procedure will set PadCfgLock for selected pads within one group
+
+ @param[in] Group GPIO group
+ @param[in] DwNum PadCfgLock register number for current group.
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[in] PadsToLock Bitmask for pads which are going to be locked
+ Bit position - PadNumber
+ Bit value - 0: DoNotLock, 1: Lock
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or DwNum parameter number
+**/
+EFI_STATUS
+GpioLockPadCfgForGroupDw (
+ IN GPIO_GROUP Group,
+ IN UINT32 DwNum,
+ IN UINT32 PadsToLock
+ )
+{
+ EFI_STATUS Status;
+
+ Status = GpioLockPadsUsingSbi (
+ GpioPadConfigLockRegister,
+ FALSE,
+ Group,
+ DwNum,
+ PadsToLock,
+ 0,
+ FALSE
+ );
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+/**
+ This procedure will set PadCfgLock for selected pad
+
+ @param[in] GpioPad GPIO pad
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioLockPadCfg (
+ IN GPIO_PAD GpioPad
+ )
+{
+ EFI_STATUS Status;
+
+ Status = GpioLockPadsUsingSbi (
+ GpioPadConfigLockRegister,
+ FALSE,
+ 0,
+ 0,
+ 0,
+ GpioPad,
+ TRUE
+ );
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+/**
+ This procedure will clear PadCfgLockTx for selected pads within one group.
+ This function should be used only inside SMI.
+
+ @param[in] Group GPIO group
+ @param[in] DwNum PadCfgLockTx register number for current group.
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[in] PadsToUnlockTx Bitmask for pads which are going to be unlocked,
+ Bit position - PadNumber
+ Bit value - 0: DoNotUnLockTx, 1: LockTx
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioUnlockPadCfgTxForGroupDw (
+ IN GPIO_GROUP Group,
+ IN UINT32 DwNum,
+ IN UINT32 PadsToUnlockTx
+ )
+{
+ EFI_STATUS Status;
+
+ Status = GpioLockPadsUsingSbi (
+ GpioPadLockOutputRegister,
+ TRUE,
+ Group,
+ DwNum,
+ PadsToUnlockTx,
+ 0,
+ FALSE
+ );
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+/**
+ This procedure will clear PadCfgLockTx for selected pad.
+ This function should be used only inside SMI.
+
+ @param[in] GpioPad GPIO pad
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioUnlockPadCfgTx (
+ IN GPIO_PAD GpioPad
+ )
+{
+ EFI_STATUS Status;
+
+ Status = GpioLockPadsUsingSbi (
+ GpioPadLockOutputRegister,
+ TRUE,
+ 0,
+ 0,
+ 0,
+ GpioPad,
+ TRUE
+ );
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+/**
+ This procedure will set PadCfgLockTx for selected pads within one group
+
+ @param[in] Group GPIO group
+ @param[in] DwNum PadCfgLock register number for current group.
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[in] PadsToLockTx Bitmask for pads which are going to be locked,
+ Bit position - PadNumber
+ Bit value - 0: DoNotLockTx, 1: LockTx
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or DwNum parameter number
+**/
+EFI_STATUS
+GpioLockPadCfgTxForGroupDw (
+ IN GPIO_GROUP Group,
+ IN UINT32 DwNum,
+ IN UINT32 PadsToLockTx
+ )
+{
+ EFI_STATUS Status;
+
+ Status = GpioLockPadsUsingSbi (
+ GpioPadLockOutputRegister,
+ FALSE,
+ Group,
+ DwNum,
+ PadsToLockTx,
+ 0,
+ FALSE
+ );
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+/**
+ This procedure will set PadCfgLockTx for selected pad
+
+ @param[in] GpioPad GPIO pad
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioLockPadCfgTx (
+ IN GPIO_PAD GpioPad
+ )
+{
+ EFI_STATUS Status;
+
+ Status = GpioLockPadsUsingSbi (
+ GpioPadLockOutputRegister,
+ FALSE,
+ 0,
+ 0,
+ 0,
+ GpioPad,
+ TRUE
+ );
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+
+/**
+ This procedure will get Group to GPE mapping.
+
+ @param[out] GroupToGpeDw0 GPIO group to be mapped to GPE_DW0
+ @param[out] GroupToGpeDw1 GPIO group to be mapped to GPE_DW1
+ @param[out] GroupToGpeDw2 GPIO group to be mapped to GPE_DW2
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioGetGroupToGpeDwX (
+ IN GPIO_GROUP *GroupToGpeDw0,
+ IN GPIO_GROUP *GroupToGpeDw1,
+ IN GPIO_GROUP *GroupToGpeDw2
+ )
+{
+ UINT32 Data32;
+ UINT32 PchPwrmBase;
+ GPIO_GROUP GpioGroupOffset;
+
+ GpioGroupOffset = GpioGetLowestGroup ();
+
+
+ PchPwrmBaseGet (&PchPwrmBase);
+
+ Data32 = MmioRead32 ((UINTN) (PchPwrmBase + R_PCH_PWRM_GPIO_CFG));
+
+ *GroupToGpeDw0 = ((Data32 & B_PCH_PWRM_GPIO_CFG_GPE0_DW0) >> N_PCH_PWRM_GPIO_CFG_GPE0_DW0) + GpioGroupOffset;
+ *GroupToGpeDw1 = ((Data32 & B_PCH_PWRM_GPIO_CFG_GPE0_DW1) >> N_PCH_PWRM_GPIO_CFG_GPE0_DW1) + GpioGroupOffset;
+ *GroupToGpeDw2 = ((Data32 & B_PCH_PWRM_GPIO_CFG_GPE0_DW2) >> N_PCH_PWRM_GPIO_CFG_GPE0_DW2) + GpioGroupOffset;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will set Group to GPE mapping.
+
+ @param[in] GroupToGpeDw0 GPIO group to be mapped to GPE_DW0
+ @param[in] GroupToGpeDw1 GPIO group to be mapped to GPE_DW1
+ @param[in] GroupToGpeDw2 GPIO group to be mapped to GPE_DW2
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioSetGroupToGpeDwX (
+ IN GPIO_GROUP GroupToGpeDw0,
+ IN GPIO_GROUP GroupToGpeDw1,
+ IN GPIO_GROUP GroupToGpeDw2
+ )
+{
+ UINT32 Data32Or;
+ UINT32 Data32And;
+ UINT32 PchPwrmBase;
+ GPIO_GROUP GpioGroupLowest;
+ GPIO_GROUP GpioGroupHighest;
+
+ GpioGroupLowest = GpioGetLowestGroup ();
+ GpioGroupHighest = GpioGetHighestGroup ();
+
+ //
+ // Check if group argument exceeds GPIO group range
+ //
+ if (((UINT32)GroupToGpeDw0 < GpioGroupLowest) || ((UINT32)GroupToGpeDw0 > GpioGroupHighest) ||
+ ((UINT32)GroupToGpeDw1 < GpioGroupLowest) || ((UINT32)GroupToGpeDw1 > GpioGroupHighest) ||
+ ((UINT32)GroupToGpeDw2 < GpioGroupLowest) || ((UINT32)GroupToGpeDw2 > GpioGroupHighest)) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Group argument exceeds GPIO group range\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check if each group number is unique
+ //
+ if ((GroupToGpeDw0 == GroupToGpeDw1) ||
+ (GroupToGpeDw0 == GroupToGpeDw2) ||
+ (GroupToGpeDw1 == GroupToGpeDw2)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Values in GPE0_DWx registers are 0 based (GPP_A = 0h)
+ //
+ GroupToGpeDw0 = GpioGetGroupIndexFromGroup(GroupToGpeDw0);
+ GroupToGpeDw1 = GpioGetGroupIndexFromGroup(GroupToGpeDw1);
+ GroupToGpeDw2 = GpioGetGroupIndexFromGroup(GroupToGpeDw2);
+
+ PchPwrmBaseGet (&PchPwrmBase);
+
+ //
+ // Program GPIO_CFG (PMRMBASE + 120h) register
+ //
+ Data32And = (UINT32) ~(B_PCH_PWRM_GPIO_CFG_GPE0_DW2 | B_PCH_PWRM_GPIO_CFG_GPE0_DW1 | B_PCH_PWRM_GPIO_CFG_GPE0_DW0);
+ Data32Or = (UINT32)((GroupToGpeDw2 << N_PCH_PWRM_GPIO_CFG_GPE0_DW2) |
+ (GroupToGpeDw1 << N_PCH_PWRM_GPIO_CFG_GPE0_DW1) |
+ (GroupToGpeDw0 << N_PCH_PWRM_GPIO_CFG_GPE0_DW0));
+
+ MmioAndThenOr32 (
+ (UINTN) (PchPwrmBase + R_PCH_PWRM_GPIO_CFG),
+ Data32And,
+ Data32Or
+ );
+
+ Data32And = (UINT32) ~(B_PCH_PCR_GPIO_MISCCFG_GPE0_DW2 | B_PCH_PCR_GPIO_MISCCFG_GPE0_DW1 | B_PCH_PCR_GPIO_MISCCFG_GPE0_DW0);
+ Data32Or = (UINT32)((GroupToGpeDw2 << N_PCH_PCR_GPIO_MISCCFG_GPE0_DW2) |
+ (GroupToGpeDw1 << N_PCH_PCR_GPIO_MISCCFG_GPE0_DW1) |
+ (GroupToGpeDw0 << N_PCH_PCR_GPIO_MISCCFG_GPE0_DW0));
+ //
+ // Program MISCCFG register for Community 0
+ //
+ MmioAndThenOr32 (
+ (UINTN)PCH_PCR_ADDRESS (PID_GPIOCOM0, R_PCH_PCR_GPIO_MISCCFG),
+ Data32And,
+ Data32Or
+ );
+
+ //
+ // Program MISCCFG register for Community 1
+ //
+ MmioAndThenOr32 (
+ (UINTN)PCH_PCR_ADDRESS (PID_GPIOCOM1, R_PCH_PCR_GPIO_MISCCFG),
+ Data32And,
+ Data32Or
+ );
+
+ //
+ // Program MISCCFG register for Community 2
+ //
+ MmioAndThenOr32 (
+ (UINTN)PCH_PCR_ADDRESS (PID_GPIOCOM2, R_PCH_PCR_GPIO_MISCCFG),
+ Data32And,
+ Data32Or
+ );
+
+ //
+ // Program MISCCFG register for Community 3
+ //
+ MmioAndThenOr32 (
+ (UINTN)PCH_PCR_ADDRESS (PID_GPIOCOM3, R_PCH_PCR_GPIO_MISCCFG),
+ Data32And,
+ Data32Or
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will get GPE number for provided GpioPad.
+ PCH allows to configure mapping between GPIO groups and related GPE (GpioSetGroupToGpeDwX())
+ what results in the fact that certain Pad can cause different General Purpose Event. Only three
+ GPIO groups can be mapped to cause unique GPE (1-tier), all others groups will be under one common
+ event (GPE_111 for 2-tier).
+
+ 1-tier:
+ Returned GpeNumber is in range <0,95>. GpioGetGpeNumber() can be used
+ to determine what _LXX ACPI method would be called on event on selected GPIO pad
+
+ 2-tier:
+ Returned GpeNumber is 0x6F (111). All GPIO pads which are not mapped to 1-tier GPE
+ will be under one master GPE_111 which is linked to _L6F ACPI method. If it is needed to determine
+ what Pad from 2-tier has caused the event, _L6F method should check GPI_GPE_STS and GPI_GPE_EN
+ registers for all GPIO groups not mapped to 1-tier GPE.
+
+ @param[in] GpioPad GPIO pad
+ @param[out] GpeNumber GPE number
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioGetGpeNumber (
+ IN GPIO_PAD GpioPad,
+ OUT UINT32 *GpeNumber
+ )
+{
+ GPIO_GROUP GroupToGpeDw0;
+ GPIO_GROUP GroupToGpeDw1;
+ GPIO_GROUP GroupToGpeDw2;
+ GPIO_GROUP GpioGroupLowest;
+ GPIO_GROUP GpioGroupHighest;
+ UINT32 GroupIndex;
+ GPIO_GROUP Group;
+ UINT32 PadNumber;
+ GPIO_GROUP_INFO *GpioGroupInfo;
+ UINTN GpioGroupInfoLength;
+
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+
+ Group = GpioGetGroupFromGpioPad (GpioPad);
+ GroupIndex = GpioGetGroupIndexFromGpioPad (GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+
+DEBUG_CODE_BEGIN();
+ if (!GpioIsCorrectPadForThisChipset (GpioPad)) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Incorrect GpioPad define used on this chipset (Group=%d, Pad=%d)!\n", GroupIndex, PadNumber));
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+DEBUG_CODE_END();
+
+ GpioGroupLowest = GpioGetLowestGroup ();
+ GpioGroupHighest = GpioGetHighestGroup ();
+
+ //
+ // Check if group argument exceeds GPIO group range
+ //
+ if ((GroupIndex < GpioGetGroupIndexFromGroup (GpioGroupLowest)) || (GroupIndex > GpioGetGroupIndexFromGroup (GpioGroupHighest))) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Group argument (%d) exceeds GPIO group range\n", GroupIndex));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check if legal pad number
+ //
+ if (PadNumber >= GpioGroupInfo[GroupIndex].PadPerGroup) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Pin number (%d) exceeds possible range for this group\n", PadNumber));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Get GPIO groups mapping to 1-tier GPE
+ //
+ GpioGetGroupToGpeDwX (&GroupToGpeDw0,&GroupToGpeDw1,&GroupToGpeDw2);
+
+ if (Group == GroupToGpeDw0) {
+ *GpeNumber = PadNumber;
+ } else if (Group== GroupToGpeDw1) {
+ *GpeNumber = PadNumber + 32;
+ } else if (Group == GroupToGpeDw2) {
+ *GpeNumber = PadNumber + 64;
+ } else {
+ //
+ // If Group number doesn't match any of above then
+ // it means than certain pad is routed to 2-tier GPE
+ // which all are under GPE_111 (0x6F)
+ //
+ *GpeNumber = PCH_GPIO_2_TIER_MASTER_GPE_NUMBER;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure is used to clear SMI STS for a specified Pad
+
+ @param[in] GpioPad GPIO pad
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioClearGpiSmiSts (
+ IN GPIO_PAD GpioPad
+ )
+{
+ UINT32 GroupIndex;
+ UINT32 PadNumber;
+ GPIO_GROUP_INFO *GpioGroupInfo;
+ UINTN GpioGroupInfoLength;
+
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+
+ GroupIndex = GpioGetGroupIndexFromGpioPad (GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+
+DEBUG_CODE_BEGIN();
+ if (!GpioIsCorrectPadForThisChipset (GpioPad)) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Incorrect GpioPad define used on this chipset (Group=%d, Pad=%d)!\n", GroupIndex, PadNumber));
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+DEBUG_CODE_END();
+
+ //
+ // Check if group argument exceeds GPIO GROUP INFO array
+ //
+ if ((UINTN)GroupIndex >= GpioGroupInfoLength) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Group argument (%d) exceeds GPIO group range\n", GroupIndex));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check if legal pad number
+ //
+ if (PadNumber >= GpioGroupInfo[GroupIndex].PadPerGroup) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Pin number (%d) exceeds possible range for this group\n", PadNumber));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check if group has GPI SMI register
+ //
+ if (GpioGroupInfo[GroupIndex].SmiStsOffset == NO_REGISTER_FOR_PROPERTY) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Clear all GPI SMI Status bits by writing '1'
+ //
+ MmioWrite32 (
+ PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, GpioGroupInfo[GroupIndex].SmiStsOffset),
+ (UINT32)(BIT0 << PadNumber)
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure is used by PchSmiDispatcher and will clear
+ all GPI SMI Status bits
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioClearAllGpiSmiSts (
+ VOID
+ )
+{
+ UINT32 GroupIndex;
+ GPIO_GROUP_INFO *GpioGroupInfo;
+ UINTN GpioGroupInfoLength;
+
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+
+ for (GroupIndex = 0; GroupIndex < GpioGroupInfoLength; GroupIndex++) {
+ //
+ // Check if group has GPI SMI register
+ //
+ if (GpioGroupInfo[GroupIndex].SmiStsOffset == NO_REGISTER_FOR_PROPERTY) {
+ continue;
+ }
+ //
+ // Clear all GPI SMI Status bits by writing '1'
+ //
+ MmioWrite32 (
+ PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, GpioGroupInfo[GroupIndex].SmiStsOffset),
+ (UINT32)0xFFFFFFFF
+ );
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure is used to disable all GPI SMI
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioDisableAllGpiSmi (
+ VOID
+ )
+{
+ GPIO_GROUP_INFO *GpioGroupInfo;
+ UINT32 GroupIndex;
+ UINTN GpioGroupInfoLength;
+
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+
+ for (GroupIndex = 0; GroupIndex < GpioGroupInfoLength; GroupIndex++) {
+ //
+ // Check if group has GPI SMI register
+ //
+ if (GpioGroupInfo[GroupIndex].SmiEnOffset == NO_REGISTER_FOR_PROPERTY) {
+ continue;
+ }
+
+ //
+ // Disable all GPI SMI
+ //
+ MmioWrite32 (
+ PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, GpioGroupInfo[GroupIndex].SmiEnOffset),
+ (UINT32)0x0
+ );
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure is used to register GPI SMI dispatch function.
+
+ @param[in] GpioPad GPIO pad
+ @param[out] GpiNum GPI number
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioGetGpiSmiNum (
+ IN GPIO_PAD GpioPad,
+ OUT UINTN *GpiNum
+ )
+{
+ UINT32 GroupIndex;
+ UINT32 Index;
+ UINT32 PadNumber;
+ GPIO_GROUP_INFO *GpioGroupInfo;
+ UINTN GpioGroupInfoLength;
+
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+
+ GroupIndex = GpioGetGroupIndexFromGpioPad (GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+
+DEBUG_CODE_BEGIN();
+ if (!GpioIsCorrectPadForThisChipset (GpioPad)) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Incorrect GpioPad define used on this chipset (Group=%d, Pad=%d)!\n", GroupIndex, PadNumber));
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+DEBUG_CODE_END();
+
+ //
+ // Check if group argument exceeds GPIO GROUP INFO array
+ //
+ if ((UINTN)GroupIndex >= GpioGroupInfoLength) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Group argument (%d) exceeds GPIO group range\n", GroupIndex));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check if legal pad number
+ //
+ if (PadNumber >= GpioGroupInfo[GroupIndex].PadPerGroup){
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Pin number (%d) exceeds possible range for this group\n", PadNumber));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *GpiNum = 0;
+
+ for (Index = 0; Index < (UINT32)GroupIndex; Index++) {
+ *GpiNum += (UINTN)(GpioGroupInfo[Index].PadPerGroup);
+ }
+ *GpiNum += (UINTN)PadNumber;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure is used to check GPIO inputs belongs to 2 tier or 1 tier architecture
+
+ @param[in] GpioPad GPIO pad
+
+ @retval Data 0 means 1-tier, 1 means 2-tier
+**/
+BOOLEAN
+GpioCheckFor2Tier (
+ IN GPIO_PAD GpioPad
+ )
+{
+ UINT32 Data32;
+
+ GpioGetGpeNumber (GpioPad, &Data32);
+ if(Data32 == PCH_GPIO_2_TIER_MASTER_GPE_NUMBER) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ This procedure is used to clear GPE STS for a specified GpioPad
+
+ @param[in] GpioPad GPIO pad
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioClearGpiGpeSts (
+ IN GPIO_PAD GpioPad
+ )
+{
+ UINT32 GroupIndex;
+ UINT32 PadNumber;
+ GPIO_GROUP_INFO *GpioGroupInfo;
+ UINTN GpioGroupInfoLength;
+
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+
+ GroupIndex = GpioGetGroupIndexFromGpioPad (GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+
+ //
+ // Check if group argument exceeds GPIO GROUP INFO array
+ //
+ if ((UINTN)GroupIndex >= GpioGroupInfoLength) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Group argument (%d) exceeds GPIO group range\n", GroupIndex));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check if legal pad number
+ //
+ if (PadNumber >= GpioGroupInfo[GroupIndex].PadPerGroup) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Pin number (%d) exceeds possible range for this group\n", PadNumber));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check if group has GPI GPE register
+ //
+ if (GpioGroupInfo[GroupIndex].GpiGpeStsOffset == NO_REGISTER_FOR_PROPERTY) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Check for 2-tier
+ if(!(GpioCheckFor2Tier (GpioPad))) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Clear all GPI SMI Status bits by writing '1'
+ //
+ MmioWrite32 (
+ PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, GpioGroupInfo[GroupIndex].GpiGpeStsOffset),
+ (UINT32)(BIT0 << PadNumber)
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure is used to read GPE STS for a specified Pad
+
+ @param[in] GpioPad GPIO pad
+ @param[out] Data GPE STS data
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioGetGpiGpeSts (
+ IN GPIO_PAD GpioPad,
+ OUT UINT32* Data
+ )
+{
+ UINT32 Data32;
+ UINT32 Mask;
+ UINT32 GroupIndex;
+ UINT32 PadNumber;
+ GPIO_GROUP_INFO *GpioGroupInfo;
+ UINTN GpioGroupInfoLength;
+
+ *Data = 0xFFFFFFFF;
+
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+
+ GroupIndex = GpioGetGroupIndexFromGpioPad (GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+
+ //
+ // Check if group argument exceeds GPIO GROUP INFO array
+ //
+ if ((UINTN)GroupIndex >= GpioGroupInfoLength) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Group argument (%d) exceeds GPIO group range\n", GroupIndex));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check if legal pad number
+ //
+ if (PadNumber >= GpioGroupInfo[GroupIndex].PadPerGroup) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Pin number (%d) exceeds possible range for this group\n", PadNumber));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check if group has GPI GPE register
+ //
+ if (GpioGroupInfo[GroupIndex].GpiGpeStsOffset == NO_REGISTER_FOR_PROPERTY) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Check for 2-tier
+ if(!(GpioCheckFor2Tier (GpioPad))) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Read GPI GPE Status bits
+ //
+ Data32 = MmioRead32(
+ PCH_PCR_ADDRESS(GpioGroupInfo[GroupIndex].Community, GpioGroupInfo[GroupIndex].GpiGpeStsOffset)
+ );
+
+ Mask = (UINT32)(BIT0 << PadNumber);
+ Data32 = (Data32 & Mask) >> PadNumber;
+ *Data = Data32;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will set GPIO Input Rout SCI
+
+ @param[in] GpioPad GPIO pad
+ @param[in] Value Value for GPIRoutSCI
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioSetGpiRoutSci (
+ IN GPIO_PAD GpioPad,
+ IN UINT32 Value
+ )
+{
+ EFI_STATUS Status;
+
+ Value <<= N_PCH_GPIO_RX_SCI_ROUTE;
+ Status = GpioReadWritePadCfgReg (
+ GpioPad,
+ 0,
+ B_PCH_GPIO_RX_SCI_ROUTE,
+ TRUE,
+ &Value
+ );
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+/**
+ This procedure will set GPIO Input Rout SMI
+
+ @param[in] GpioPad GPIO pad
+ @param[in] Value Value for GPIRoutSMI
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioSetGpiRoutSmi (
+ IN GPIO_PAD GpioPad,
+ IN UINT32 Value
+ )
+{
+ EFI_STATUS Status;
+
+ Value <<= N_PCH_GPIO_RX_SMI_ROUTE;
+ Status = GpioReadWritePadCfgReg (
+ GpioPad,
+ 0,
+ B_PCH_GPIO_RX_SMI_ROUTE,
+ TRUE,
+ &Value
+ );
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+/**
+ This procedure will set GPI SMI Enable setting for selected pad
+
+ @param[in] GpioPad GPIO pad
+ @param[in] PadGpiSmiEn GPI SMI Enable setting for selected pad
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioSetGpiSmiPadEn (
+ IN GPIO_PAD GpioPad,
+ IN UINT32 PadGpiSmiEn
+ )
+{
+ GPIO_GROUP Group;
+ GPIO_GROUP GpioGroupOffset;
+ UINT32 NumberOfGroups;
+ EFI_STATUS Status;
+
+ GpioGroupOffset = GpioGetLowestGroup ();
+ NumberOfGroups = GpioGetNumberOfGroups ();
+
+ Group = GpioGetGroupFromGpioPad (GpioPad);
+
+ //
+ // Check if group argument exceeds GPIO group range
+ //
+ if ((Group < GpioGroupOffset) || (Group >= NumberOfGroups + GpioGroupOffset)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = GpioReadWriteReg (
+ GpioSmiEnableRegister,
+ Group,
+ 0,
+ GpioPad,
+ TRUE,
+ TRUE,
+ &PadGpiSmiEn
+ );
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+/**
+ This procedure will set GPI General Purpose Event Enable setting for selected pad
+
+ @param[in] GpioPad GPIO pad
+ @param[in] PadGpiGpeEn GPI General Purpose Event Enable setting for selected pad
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioSetGpiGpePadEn (
+ IN GPIO_PAD GpioPad,
+ IN UINT32 PadGpiGpeEn
+ )
+{
+ GPIO_GROUP Group;
+ GPIO_GROUP GpioGroupOffset;
+ UINT32 NumberOfGroups;
+ EFI_STATUS Status;
+
+ GpioGroupOffset = GpioGetLowestGroup ();
+ NumberOfGroups = GpioGetNumberOfGroups ();
+
+ Group = GpioGetGroupFromGpioPad (GpioPad);
+
+ //
+ // Check if group argument exceeds GPIO group range
+ //
+ if ((Group < GpioGroupOffset) || (Group >= NumberOfGroups + GpioGroupOffset)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+
+ Status = GpioReadWriteReg (
+ GpioGpeEnableRegister,
+ Group,
+ 0,
+ GpioPad,
+ TRUE,
+ TRUE,
+ &PadGpiGpeEn
+ );
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+/**
+ Check if given GPIO Pad is locked
+
+ @param[in] GroupIndex GPIO group index
+ @param[in] PadNumber GPIO pad number
+
+ @retval TRUE Pad is locked
+ @retval FALSE Pad is not locked
+**/
+BOOLEAN
+GpioIsPadLocked (
+ IN UINT32 GroupIndex,
+ IN GPIO_PAD PadNumber
+ )
+{
+ UINT32 RegVal;
+ GPIO_GROUP_INFO *GpioGroupInfo;
+ UINTN GpioGroupInfoLength;
+
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+
+ // Read PADCFGLOCK register
+ //
+ RegVal = MmioRead32 ((UINTN)PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, GpioGroupInfo[GroupIndex].PadCfgLockOffset));
+
+ return (((RegVal >> PadNumber) & 0x1) == 1);
+}
+
+/**
+ Locks multiple GPIO pads using GPIO_INIT_CONFIG array.
+ Only locking is applied and no other GPIO pad configuration is changed.
+
+ @param[in] NumberOfItems Number of GPIO pads to be locked
+ @param[in] GpioInitTableAddress GPIO initialization table
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+ @retval EFI_UNSUPPORTED Incorrect GPIO pad definition
+**/
+static
+EFI_STATUS
+GpioLockPads (
+ IN UINT32 NumberOfItems,
+ IN GPIO_INIT_CONFIG *GpioInitTableAddress
+ )
+{
+ UINT32 Index;
+ UINT32 PadsToLock[V_PCH_GPIO_GROUP_MAX];
+ UINT32 PadsToLockTx[V_PCH_GPIO_GROUP_MAX];
+ GPIO_GROUP_INFO *GpioGroupInfo;
+ UINTN GpioGroupInfoLength;
+ GPIO_GROUP GpioGroupOffset;
+ UINT32 NumberOfGroups;
+ GPIO_PAD_OWN PadOwnVal;
+ GPIO_INIT_CONFIG *GpioData;
+ GPIO_GROUP Group;
+ UINT32 GroupIndex;
+ UINT32 PadNumber;
+ PCH_SERIES PchSeries;
+
+ PchSeries = GetPchSeries ();
+ PadOwnVal = GpioPadOwnHost;
+
+ ZeroMem (PadsToLock, sizeof (PadsToLock));
+ ZeroMem (PadsToLockTx, sizeof (PadsToLockTx));
+
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+
+ GpioGroupOffset = GpioGetLowestGroup ();
+ NumberOfGroups = GpioGetNumberOfGroups ();
+
+ for (Index = 0; Index < NumberOfItems; Index ++) {
+
+ GpioData = &GpioInitTableAddress[Index];
+
+ Group = GpioGetGroupFromGpioPad (GpioData->GpioPad);
+ GroupIndex = GpioGetGroupIndexFromGpioPad (GpioData->GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioData->GpioPad);
+
+ //
+ // Checking GroupIndex to avoid Buffer Overflows or Array Out of Index
+ //
+ if (GroupIndex >= V_PCH_GPIO_GROUP_MAX) {
+ ASSERT (FALSE);
+ continue;
+ }
+
+ //
+ // Check if group argument exceeds GPIO group range
+ //
+ if ((Group < GpioGroupOffset) || (Group >= NumberOfGroups + GpioGroupOffset)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check if legal pin number
+ //
+ if (PadNumber >= GpioGroupInfo[GroupIndex].PadPerGroup){
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check if selected GPIO Pad is not owned by CSME/ISH
+ //
+ GpioGetPadOwnership (GpioData->GpioPad, &PadOwnVal);
+
+ if (PadOwnVal != GpioPadOwnHost) {
+ continue;
+ }
+
+ //
+ // Update information on Pad Configuration Lock
+ //
+ PadsToLock[GroupIndex] |= ((GpioData->GpioConfig.LockConfig >> 0x1) & 0x1) << PadNumber;
+
+ //
+ // Update information on Pad Configuration Lock Tx
+ //
+ PadsToLockTx[GroupIndex] |= ((GpioData->GpioConfig.LockConfig >> 0x2) & 0x1) << PadNumber;
+ }
+
+ for (Index = 0; Index < NumberOfGroups; Index++) {
+ //
+ // Write Pad Configuration Lock
+ //
+ if (PadsToLock[Index] != 0) {
+ GpioLockPadCfgForGroupDw (Index + GpioGroupOffset, 0, PadsToLock[Index]);
+ }
+
+ //
+ // Write Pad Configuration Lock Tx
+ //
+ if (PadsToLockTx[Index] != 0) {
+ GpioLockPadCfgTxForGroupDw (Index + GpioGroupOffset, 0, PadsToLockTx[Index]);
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Locks GPIO pads according to GPIO_INIT_CONFIG array from
+ gPlatformGpioConfigGuid HOB. Only locking is applied and no other GPIO pad
+ configuration is changed.
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_NOT_FOUND gPlatformGpioConfigGuid not found
+**/
+EFI_STATUS
+GpioLockGpios (
+ VOID
+ )
+{
+ EFI_HOB_GUID_TYPE *GpioConfigHob;
+ GPIO_INIT_CONFIG *GpioConfig;
+ UINT16 GpioConfigSize;
+
+ GpioConfigHob = GetFirstGuidHob (&gPlatformGpioConfigGuid);
+ if (GpioConfigHob == NULL) {
+ return EFI_NOT_FOUND;
+ }
+ ASSERT (GET_GUID_HOB_DATA_SIZE (GpioConfigHob) % sizeof (GpioConfig[0]) == 0);
+ GpioConfigSize = GET_GUID_HOB_DATA_SIZE (GpioConfigHob) / sizeof (GpioConfig[0]);
+ GpioConfig = GET_GUID_HOB_DATA (GpioConfigHob);
+ GpioLockPads (GpioConfigSize, GpioConfig);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Unlocks all PCH GPIO pads
+
+ @retval None
+**/
+VOID
+GpioUnlockAllGpios (
+ VOID
+ )
+{
+ GPIO_GROUP GpioGroupOffset;
+ UINT32 NumberOfGroups;
+ UINT32 Index;
+
+ GpioGroupOffset = GpioGetLowestGroup ();
+ NumberOfGroups = GpioGetNumberOfGroups ();
+
+ for (Index = 0; Index < NumberOfGroups; Index++) {
+ //
+ // Reset Pad Configuration Lock
+ //
+ GpioUnlockPadCfgForGroupDw (Index + GpioGroupOffset, 0, 0xFFFFFFFF);
+
+ //
+ // Reset Pad Configuration Lock Tx
+ //
+ GpioUnlockPadCfgTxForGroupDw (Index + GpioGroupOffset, 0, 0xFFFFFFFF);
+ }
+}
+
diff --git a/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmGpioLib/GpioLibrary.h b/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmGpioLib/GpioLibrary.h
new file mode 100644
index 0000000000..8618099e24
--- /dev/null
+++ b/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmGpioLib/GpioLibrary.h
@@ -0,0 +1,222 @@
+/** @file
+
+Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+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 _GPIO_LIBRARY_H_
+#define _GPIO_LIBRARY_H_
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <PchAccess.h>
+#include <Library/PchPcrLib.h>
+#include <GpioPinsSklH.h>
+#include <Library/GpioLib.h>
+#include <Library/GpioNativeLib.h>
+#include <Library/MmPciBaseLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/PchCycleDecodingLib.h>
+#include <Library/PchSbiAccessLib.h>
+
+typedef struct {
+ GPIO_PAD Pad;
+ GPIO_PAD_MODE Mode;
+} GPIO_PAD_NATIVE_FUNCTION;
+
+
+// BIT15-0 - pad number
+// BIT31-16 - group info
+// BIT23- 16 - group index
+// BIT31- 24 - chipset ID
+#define PAD_INFO_MASK 0x0000FFFF
+#define GROUP_INFO_POSITION 16
+#define GROUP_INFO_MASK 0xFFFF0000
+#define GROUP_INDEX_MASK 0x00FF0000
+#define UNIQUE_ID_MASK 0xFF000000
+#define UNIQUE_ID_POSITION 24
+
+#define GPIO_PAD_DEF(Group,Pad) (UINT32)((Group << 16) + Pad)
+#define GPIO_GROUP_DEF(Index,ChipsetId) (Index | (ChipsetId << 8))
+#define GPIO_GET_GROUP_INDEX(Group) (Group & 0xFF)
+#define GPIO_GET_GROUP_FROM_PAD(Pad) (Pad >> 16)
+#define GPIO_GET_GROUP_INDEX_FROM_PAD(Pad) GPIO_GET_GROUP_INDEX ((Pad >> 16))
+#define GPIO_GET_PAD_NUMBER(Pad) (Pad & 0xFFFF)
+#define GPIO_GET_CHIPSET_ID(Pad) (Pad >> 24)
+
+//
+// Unique ID used in GpioPad defines
+//
+#define GPIO_SKL_H_CHIPSET_ID 0x1
+#define GPIO_SKL_LP_CHIPSET_ID 0x2
+
+//
+// Below defines are based on GPIO_CONFIG structure fields
+//
+#define GPIO_CONF_PAD_MODE_MASK 0xF
+#define GPIO_CONF_PAD_MODE_BIT_POS 0
+#define GPIO_CONF_HOST_OWN_MASK 0x3
+#define GPIO_CONF_HOST_OWN_BIT_POS 0
+#define GPIO_CONF_DIR_MASK 0x7
+#define GPIO_CONF_DIR_BIT_POS 0
+#define GPIO_CONF_INV_MASK 0x18
+#define GPIO_CONF_INV_BIT_POS 3
+#define GPIO_CONF_OUTPUT_MASK 0x3
+#define GPIO_CONF_OUTPUT_BIT_POS 0
+#define GPIO_CONF_INT_ROUTE_MASK 0x1F
+#define GPIO_CONF_INT_ROUTE_BIT_POS 0
+#define GPIO_CONF_INT_TRIG_MASK 0xE0
+#define GPIO_CONF_INT_TRIG_BIT_POS 5
+#define GPIO_CONF_RESET_MASK 0x7
+#define GPIO_CONF_RESET_BIT_POS 0
+#define GPIO_CONF_TERM_MASK 0x1F
+#define GPIO_CONF_TERM_BIT_POS 0
+#define GPIO_CONF_PADTOL_MASK 0x60
+#define GPIO_CONF_PADTOL_BIT_POS 5
+#define GPIO_CONF_LOCK_MASK 0x7
+#define GPIO_CONF_LOCK_BIT_POS 0
+#define GPIO_CONF_RXRAW_MASK 0x3
+#define GPIO_CONF_RXRAW_BIT_POS 0
+
+//
+// Structure for storing information about registers offset, community,
+// maximal pad number for available groups
+//
+typedef struct {
+ UINT32 Community;
+ UINT32 PadOwnOffset;
+ UINT32 HostOwnOffset;
+ UINT32 GpiIsOffset;
+ UINT32 GpiIeOffset;
+ UINT32 GpiGpeStsOffset;
+ UINT32 GpiGpeEnOffset;
+ UINT32 SmiStsOffset;
+ UINT32 SmiEnOffset;
+ UINT32 NmiStsOffset;
+ UINT32 NmiEnOffset;
+ UINT32 PadCfgLockOffset;
+ UINT32 PadCfgLockTxOffset;
+ UINT32 PadCfgOffset;
+ UINT32 PadPerGroup;
+} GPIO_GROUP_INFO;
+
+//
+// If in GPIO_GROUP_INFO structure certain register doesn't exist
+// it will have value equal to NO_REGISTER_FOR_PROPERTY
+//
+#define NO_REGISTER_FOR_PROPERTY (~0u)
+
+
+/**
+ This procedure is used to check if GpioPad is valid for certain chipset
+
+ @param[in] GpioPad GPIO pad
+
+ @retval TRUE This pin is valid on this chipset
+ FALSE Incorrect pin
+**/
+BOOLEAN
+GpioIsCorrectPadForThisChipset (
+ IN GPIO_PAD GpioPad
+ );
+
+
+/**
+ This procedure will retrieve address and length of GPIO info table
+
+ @param[out] GpioGroupInfoTableLength Length of GPIO group table
+
+ @retval Pointer to GPIO group table
+
+**/
+GPIO_GROUP_INFO*
+GpioGetGroupInfoTable (
+ OUT UINTN *GpioGroupInfoTableLength
+ );
+
+/**
+ This procedure will set GPIO mode
+
+ @param[in] GpioPad GPIO pad
+ @param[out] PadModeValue GPIO pad mode value
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+SetGpioPadMode (
+ IN GPIO_PAD GpioPad,
+ IN GPIO_PAD_MODE PadModeValue
+ );
+
+/**
+ This procedure will get GPIO mode
+
+ @param[in] GpioPad GPIO pad
+ @param[out] PadModeValue GPIO pad mode value
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GetGpioPadMode (
+ IN GPIO_PAD GpioPad,
+ OUT GPIO_PAD_MODE *PadModeValue
+ );
+
+/**
+ This function checks if GPIO pin is a GSPI chip select pin
+
+ @param[in] GpioPad GPIO pad
+ @param[in] PadMode GPIO pad mode
+
+ @retval TRUE Pin is in GPIO mode
+ FALSE Pin is in native mode
+**/
+BOOLEAN
+GpioIsGpioPadAGSpiCsbPin (
+ IN GPIO_PAD GpioPad,
+ IN GPIO_PAD_MODE PadMode
+ );
+
+/**
+ This function checks if GPIO pin is a SataDevSlp pin
+
+ @param[in] GpioPad GPIO pad
+ @param[in] PadMode GPIO pad mode
+
+ @retval TRUE Pin is in GPIO mode
+ FALSE Pin is in native mode
+**/
+BOOLEAN
+GpioIsPadASataDevSlpPin (
+ IN GPIO_PAD GpioPad,
+ IN GPIO_PAD_MODE PadMode
+ );
+
+/**
+ Check if given GPIO Pad is locked
+
+ @param[in] GroupIndex GPIO group index
+ @param[in] PadNumber GPIO pad number
+
+ @retval TRUE Pad is locked
+ @retval FALSE Pad is not locked
+**/
+BOOLEAN
+GpioIsPadLocked (
+ IN UINT32 GroupIndex,
+ IN GPIO_PAD PadNumber
+ );
+
+#endif // _GPIO_LIBRARY_H_
diff --git a/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmGpioLib/GpioNativeLib.c b/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmGpioLib/GpioNativeLib.c
new file mode 100644
index 0000000000..a86c144679
--- /dev/null
+++ b/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmGpioLib/GpioNativeLib.c
@@ -0,0 +1,454 @@
+/** @file
+
+Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+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.
+
+**/
+
+#include "GpioLibrary.h"
+
+//
+// Chipset specific data
+//
+//SATA
+extern GPIO_PAD_NATIVE_FUNCTION mPchHSataPortResetToGpioMap[PCH_H_AHCI_MAX_PORTS];
+extern GPIO_PAD_NATIVE_FUNCTION mPchHSataDevSlpPinToGpioMap[PCH_H_AHCI_MAX_PORTS];
+
+//
+// SKX specific
+//
+extern GPIO_GROUP_INFO mPchGpioGroupInfo[V_PCH_GPIO_GROUP_MAX];
+
+/**
+ This procedure will set GPIO mode
+
+ @param[in] GpioPad GPIO pad
+ @param[out] PadModeValue GPIO pad mode value
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+SetGpioPadMode (
+ IN GPIO_PAD GpioPad,
+ IN GPIO_PAD_MODE PadModeValue
+ )
+{
+ GPIO_PAD_OWN PadOwnVal;
+ UINT32 PadCfgReg;
+ GPIO_GROUP_INFO *GpioGroupInfo;
+ UINTN GpioGroupInfoLength;
+ UINT32 PadNumber;
+ UINT32 GroupIndex;
+ UINT32 Dw0Reg;
+ UINT32 Dw0RegMask;
+
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+
+ GroupIndex = GpioGetGroupIndexFromGpioPad (GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+
+DEBUG_CODE_BEGIN();
+ if (!GpioIsCorrectPadForThisChipset (GpioPad)) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Incorrect GpioPad define used on this chipset (Group=%d, Pad=%d)!\n", GroupIndex, PadNumber));
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+DEBUG_CODE_END();
+
+ GpioGetPadOwnership (GpioPad, &PadOwnVal);
+
+ if (PadOwnVal != GpioPadOwnHost) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Accessing pad not owned by host (Group=%d, Pad=%d)!\n", GroupIndex, PadNumber));
+ return EFI_UNSUPPORTED;
+ }
+
+ if (GpioIsPadLocked (GroupIndex, PadNumber)) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Pad is locked (Group=%d, Pad=%d)!\n", GroupIndex, PadNumber));
+ return EFI_WRITE_PROTECTED;
+ }
+
+ //
+ // Create Pad Configuration register offset
+ //
+ PadCfgReg = 0x8 * PadNumber + GpioGroupInfo[GroupIndex].PadCfgOffset;
+
+ Dw0RegMask = ((((PadModeValue & GPIO_CONF_PAD_MODE_MASK) >> GPIO_CONF_PAD_MODE_BIT_POS) == GpioHardwareDefault) ? 0x0 : B_PCH_GPIO_PAD_MODE);
+ Dw0Reg = (((PadModeValue & GPIO_CONF_PAD_MODE_MASK) >> (GPIO_CONF_PAD_MODE_BIT_POS + 1)) << N_PCH_GPIO_PAD_MODE);
+
+ MmioAndThenOr32 (
+ (UINTN)PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, PadCfgReg),
+ ~(UINT32)Dw0RegMask,
+ (UINT32)Dw0Reg
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will get GPIO mode
+
+ @param[in] GpioPad GPIO pad
+ @param[out] PadModeValue GPIO pad mode value
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GetGpioPadMode (
+ IN GPIO_PAD GpioPad,
+ OUT GPIO_PAD_MODE *PadModeValue
+ )
+{
+ GPIO_PAD_OWN PadOwnVal;
+ UINT32 PadCfgReg;
+ GPIO_GROUP_INFO *GpioGroupInfo;
+ UINTN GpioGroupInfoLength;
+ UINT32 PadNumber;
+ UINT32 GroupIndex;
+ UINT32 Dw0Reg;
+
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+
+ GroupIndex = GpioGetGroupIndexFromGpioPad (GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+
+DEBUG_CODE_BEGIN();
+ if (!GpioIsCorrectPadForThisChipset (GpioPad)) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Incorrect GpioPad define used on this chipset (Group=%d, Pad=%d)!\n", GroupIndex, PadNumber));
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+DEBUG_CODE_END();
+
+ GpioGetPadOwnership (GpioPad, &PadOwnVal);
+
+ if (PadOwnVal != GpioPadOwnHost) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Accessing pad not owned by host (Group=%d, Pad=%d)!\n", GroupIndex, PadNumber));
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Create Pad Configuration register offset
+ //
+ PadCfgReg = 0x8 * PadNumber + GpioGroupInfo[GroupIndex].PadCfgOffset;
+
+ Dw0Reg = MmioRead32 ((UINTN)PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, PadCfgReg));
+
+ *PadModeValue = ((Dw0Reg & B_PCH_GPIO_PAD_MODE) >> (N_PCH_GPIO_PAD_MODE - (GPIO_CONF_PAD_MODE_BIT_POS + 1))) | (0x1 << GPIO_CONF_PAD_MODE_BIT_POS);
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This procedure will retrieve address and length of GPIO info table
+
+ @param[out] GpioGroupInfoTableLength Length of GPIO group table
+
+ @retval Pointer to GPIO group table
+
+**/
+GPIO_GROUP_INFO*
+GpioGetGroupInfoTable (
+ OUT UINTN *GpioGroupInfoTableLength
+ )
+{
+ if (GetPchGeneration () == SklPch) {
+ *GpioGroupInfoTableLength = sizeof (mPchGpioGroupInfo) / sizeof (GPIO_GROUP_INFO);
+ return mPchGpioGroupInfo;
+ } else {
+ *GpioGroupInfoTableLength = 0;
+ return NULL;
+ }
+}
+
+
+/**
+ This procedure is used to check if GpioPad is valid for certain chipset
+
+ @param[in] GpioPad GPIO pad
+
+ @retval TRUE This pin is valid on this chipset
+ FALSE Incorrect pin
+**/
+BOOLEAN
+GpioIsCorrectPadForThisChipset (
+ IN GPIO_PAD GpioPad
+ )
+{
+DEBUG_CODE_BEGIN();
+ PCH_SERIES PchSeries;
+
+ PchSeries = GetPchSeries ();
+
+ if ((PchSeries == PchH) && (GPIO_GET_CHIPSET_ID(GpioPad) == GPIO_SKL_H_CHIPSET_ID)) {
+ return TRUE;
+ } else if ((PchSeries == PchLp) && (GPIO_GET_CHIPSET_ID(GpioPad) == GPIO_SKL_LP_CHIPSET_ID)) {
+ return TRUE;
+ }
+
+DEBUG_CODE_END();
+ return FALSE;
+}
+
+
+/**
+ This procedure will get number of pads for certain GPIO group
+
+ @param[in] Group GPIO group number
+
+ @retval Value Pad number for group
+ If illegal group number then return 0
+**/
+UINT32
+GpioGetPadPerGroup (
+ IN GPIO_GROUP Group
+ )
+{
+ GPIO_GROUP_INFO *GpioGroupInfo;
+ UINTN GpioGroupInfoLength;
+ UINT32 GroupIndex;
+ //
+ // Check if group argument exceeds GPIO GROUP INFO array
+ //
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+ GroupIndex = GpioGetGroupIndexFromGroup (Group);
+
+ if ((UINTN)GroupIndex >= GpioGroupInfoLength) {
+ ASSERT(FALSE);
+ return 0;
+ } else {
+ return GpioGroupInfo[GroupIndex].PadPerGroup;
+ }
+}
+
+/**
+ This procedure will get number of groups
+
+ @param[in] none
+
+ @retval Value Group number
+**/
+UINT8
+GpioGetNumberOfGroups (
+ VOID
+ )
+{
+ return V_PCH_H_GPIO_GROUP_MAX;
+}
+/**
+ This procedure will get lowest group
+
+ @param[in] none
+
+ @retval Value Lowest Group
+**/
+GPIO_GROUP
+GpioGetLowestGroup (
+ VOID
+ )
+{
+ return (UINT32)GPIO_SKL_H_GROUP_GPP_A;
+}
+/**
+ This procedure will get highest group
+
+ @param[in] none
+
+ @retval Value Highest Group
+**/
+GPIO_GROUP
+GpioGetHighestGroup (
+ VOID
+ )
+{
+ return (UINT32)GPIO_SKL_H_GROUP_GPD;
+}
+
+/**
+ This procedure will get group number
+
+ @param[in] GpioPad Gpio Pad
+
+ @retval Value Group number
+**/
+GPIO_GROUP
+GpioGetGroupFromGpioPad (
+ IN GPIO_PAD GpioPad
+ )
+{
+ return GPIO_GET_GROUP_FROM_PAD (GpioPad);
+}
+
+/**
+ This procedure will get group index (0 based)
+
+ @param[in] GpioPad Gpio Pad
+
+ @retval Value Group Index
+**/
+UINT32
+GpioGetGroupIndexFromGpioPad (
+ IN GPIO_PAD GpioPad
+ )
+{
+ return (UINT32)GPIO_GET_GROUP_INDEX_FROM_PAD (GpioPad);
+}
+
+/**
+ This procedure will get group index (0 based) from group
+
+ @param[in] GpioGroup Gpio Group
+
+ @retval Value Group Index
+**/
+UINT32
+GpioGetGroupIndexFromGroup (
+ IN GPIO_GROUP GpioGroup
+ )
+{
+ return (UINT32)GPIO_GET_GROUP_INDEX (GpioGroup);
+}
+
+/**
+ This procedure will get pad number (0 based) from Gpio Pad
+
+ @param[in] GpioPad Gpio Pad
+
+ @retval Value Pad Number
+**/
+UINT32
+GpioGetPadNumberFromGpioPad (
+ IN GPIO_PAD GpioPad
+ )
+{
+ return (UINT32)GPIO_GET_PAD_NUMBER (GpioPad);
+}
+/**
+ This procedure will return GpioPad from Group and PadNumber
+
+ @param[in] Group GPIO group
+ @param[in] PadNumber GPIO PadNumber
+
+ @retval GpioPad GpioPad
+**/
+GPIO_PAD
+GpioGetGpioPadFromGroupAndPadNumber (
+ IN GPIO_GROUP Group,
+ IN UINT32 PadNumber
+ )
+{
+ return GPIO_PAD_DEF(Group,PadNumber);
+}
+
+
+
+/**
+ This function checks if GPIO pin for SATA reset port is in GPIO MODE
+
+ @param[in] SataPort SATA port number
+
+ @retval TRUE Pin is in GPIO mode
+ FALSE Pin is in native mode
+**/
+BOOLEAN
+GpioIsSataResetPortInGpioMode (
+ IN UINTN SataPort
+ )
+{
+ EFI_STATUS Status;
+ UINT32 GpioPin;
+ GPIO_PAD_MODE GpioMode;
+
+
+ ASSERT (SataPort < PCH_H_AHCI_MAX_PORTS);
+ GpioPin = mPchHSataPortResetToGpioMap[SataPort].Pad;
+
+ Status = GetGpioPadMode (GpioPin, &GpioMode);
+ if ((EFI_ERROR (Status)) || (GpioMode != GpioPadModeGpio)) {
+ return FALSE;
+ } else {
+ return TRUE;
+ }
+}
+
+
+/**
+ This function checks if GPIO pin is a SataDevSlp pin
+
+ @param[in] GpioPad GPIO pad
+ @param[in] PadMode GPIO pad mode
+
+ @retval TRUE Pin is in GPIO mode
+ FALSE Pin is in native mode
+**/
+BOOLEAN
+GpioIsPadASataDevSlpPin (
+ IN GPIO_PAD GpioPad,
+ IN GPIO_PAD_MODE PadMode
+ )
+{
+ UINT32 SataDevSlpPinMax;
+ UINT32 SataDevSlpPinIndex;
+ GPIO_PAD_OWN PadOwnership;
+ GPIO_PAD_NATIVE_FUNCTION *SataDevSlpPinToGpioMap;
+
+ SataDevSlpPinToGpioMap = mPchHSataDevSlpPinToGpioMap;
+ SataDevSlpPinMax = sizeof(mPchHSataDevSlpPinToGpioMap)/sizeof(GPIO_PAD_NATIVE_FUNCTION);
+
+ for (SataDevSlpPinIndex = 0; SataDevSlpPinIndex < SataDevSlpPinMax; SataDevSlpPinIndex++) {
+ if ((GpioPad == SataDevSlpPinToGpioMap[SataDevSlpPinIndex].Pad) &&
+ (PadMode == SataDevSlpPinToGpioMap[SataDevSlpPinIndex].Mode)) {
+ GpioGetPadOwnership (SataDevSlpPinToGpioMap[SataDevSlpPinIndex].Pad , &PadOwnership);
+ if (PadOwnership == GpioPadOwnHost) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+ }
+ }
+ return FALSE;
+}
+
+/**
+ This function checks if SataDevSlp pin is in native mode
+
+ @param[in] SataPort SATA port
+ @param[out] DevSlpPad DevSlpPad
+
+ @retval TRUE DevSlp is in native mode
+ FALSE DevSlp is not in native mode
+**/
+BOOLEAN
+GpioIsSataDevSlpPinEnabled (
+ IN UINTN SataPort,
+ OUT GPIO_PAD *DevSlpPad
+ )
+{
+ GPIO_PAD_MODE DevSlpPadMode;
+ GPIO_PAD DevSlpGpioPad;
+ GPIO_PAD_MODE GpioMode;
+ EFI_STATUS Status;
+
+ ASSERT (SataPort < PCH_H_AHCI_MAX_PORTS);
+ DevSlpGpioPad = mPchHSataDevSlpPinToGpioMap[SataPort].Pad;
+ DevSlpPadMode = mPchHSataDevSlpPinToGpioMap[SataPort].Mode;
+
+ Status = GetGpioPadMode (DevSlpGpioPad, &GpioMode);
+
+ if (EFI_ERROR (Status) || (GpioMode != DevSlpPadMode)) {
+ *DevSlpPad = 0x0;
+ return FALSE;
+ } else {
+ *DevSlpPad = DevSlpGpioPad;
+ return TRUE;
+ }
+}
+
diff --git a/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmGpioLib/PchSklGpioData.c b/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmGpioLib/PchSklGpioData.c
new file mode 100644
index 0000000000..62d93d6c86
--- /dev/null
+++ b/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmGpioLib/PchSklGpioData.c
@@ -0,0 +1,65 @@
+/** @file
+
+Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+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.
+
+**/
+
+#include "GpioLibrary.h"
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_GROUP_INFO mPchGpioGroupInfo[] = {
+ {PID_GPIOCOM0, R_PCH_H_PCR_GPIO_GPP_A_PAD_OWN, R_PCH_PCR_GPIO_GPP_A_HOSTSW_OWN, R_PCH_PCR_GPIO_GPP_A_GPI_IS, R_PCH_PCR_GPIO_GPP_A_GPI_IE, R_PCH_PCR_GPIO_GPP_A_GPI_GPE_STS, R_PCH_PCR_GPIO_GPP_A_GPI_GPE_EN, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, R_PCH_H_PCR_GPIO_GPP_A_PADCFGLOCK, R_PCH_H_PCR_GPIO_GPP_A_PADCFGLOCKTX, R_PCH_PCR_GPIO_GPP_A_PADCFG_OFFSET, V_PCH_GPIO_GPP_A_PAD_MAX}, //SKX PCH-Server GPP_A
+ {PID_GPIOCOM0, R_PCH_H_PCR_GPIO_GPP_B_PAD_OWN, R_PCH_PCR_GPIO_GPP_B_HOSTSW_OWN, R_PCH_PCR_GPIO_GPP_B_GPI_IS, R_PCH_PCR_GPIO_GPP_B_GPI_IE, R_PCH_PCR_GPIO_GPP_B_GPI_GPE_STS, R_PCH_PCR_GPIO_GPP_B_GPI_GPE_EN, R_PCH_PCR_GPIO_GPP_B_SMI_STS, R_PCH_PCR_GPIO_GPP_B_SMI_EN, R_PCH_PCR_GPIO_GPP_B_NMI_STS, R_PCH_PCR_GPIO_GPP_B_NMI_EN, R_PCH_H_PCR_GPIO_GPP_B_PADCFGLOCK, R_PCH_H_PCR_GPIO_GPP_B_PADCFGLOCKTX, R_PCH_PCR_GPIO_GPP_B_PADCFG_OFFSET, V_PCH_GPIO_GPP_B_PAD_MAX}, //SKX PCH-Server GPP_B
+ {PID_GPIOCOM1, R_PCH_H_PCR_GPIO_GPP_C_PAD_OWN, R_PCH_PCR_GPIO_GPP_C_HOSTSW_OWN, R_PCH_PCR_GPIO_GPP_C_GPI_IS, R_PCH_PCR_GPIO_GPP_C_GPI_IE, R_PCH_PCR_GPIO_GPP_C_GPI_GPE_STS, R_PCH_PCR_GPIO_GPP_C_GPI_GPE_EN, R_PCH_PCR_GPIO_GPP_C_SMI_STS, R_PCH_PCR_GPIO_GPP_C_SMI_EN, R_PCH_PCR_GPIO_GPP_C_NMI_STS, R_PCH_PCR_GPIO_GPP_C_NMI_EN, R_PCH_H_PCR_GPIO_GPP_C_PADCFGLOCK, R_PCH_H_PCR_GPIO_GPP_C_PADCFGLOCKTX, R_PCH_PCR_GPIO_GPP_C_PADCFG_OFFSET, V_PCH_GPIO_GPP_C_PAD_MAX}, //SKX PCH-Server GPP_C
+ {PID_GPIOCOM1, R_PCH_H_PCR_GPIO_GPP_D_PAD_OWN, R_PCH_PCR_GPIO_GPP_D_HOSTSW_OWN, R_PCH_PCR_GPIO_GPP_D_GPI_IS, R_PCH_PCR_GPIO_GPP_D_GPI_IE, R_PCH_PCR_GPIO_GPP_D_GPI_GPE_STS, R_PCH_PCR_GPIO_GPP_D_GPI_GPE_EN, R_PCH_PCR_GPIO_GPP_D_SMI_STS, R_PCH_PCR_GPIO_GPP_D_SMI_EN, R_PCH_PCR_GPIO_GPP_D_NMI_STS, R_PCH_PCR_GPIO_GPP_D_NMI_EN, R_PCH_H_PCR_GPIO_GPP_D_PADCFGLOCK, R_PCH_H_PCR_GPIO_GPP_D_PADCFGLOCKTX, R_PCH_PCR_GPIO_GPP_D_PADCFG_OFFSET, V_PCH_GPIO_GPP_D_PAD_MAX}, //SKX PCH-Server GPP_D
+ {PID_GPIOCOM1, R_PCH_H_PCR_GPIO_GPP_E_PAD_OWN, R_PCH_PCR_GPIO_GPP_E_HOSTSW_OWN, R_PCH_PCR_GPIO_GPP_E_GPI_IS, R_PCH_PCR_GPIO_GPP_E_GPI_IE, R_PCH_PCR_GPIO_GPP_E_GPI_GPE_STS, R_PCH_PCR_GPIO_GPP_E_GPI_GPE_EN, R_PCH_PCR_GPIO_GPP_E_SMI_STS, R_PCH_PCR_GPIO_GPP_E_SMI_EN, R_PCH_PCR_GPIO_GPP_E_NMI_STS, R_PCH_PCR_GPIO_GPP_E_NMI_EN, R_PCH_H_PCR_GPIO_GPP_E_PADCFGLOCK, R_PCH_H_PCR_GPIO_GPP_E_PADCFGLOCKTX, R_PCH_PCR_GPIO_GPP_E_PADCFG_OFFSET, V_PCH_H_GPIO_GPP_E_PAD_MAX}, //SKX PCH-Server GPP_E
+ {PID_GPIOCOM0, R_PCH_H_PCR_GPIO_GPP_F_PAD_OWN, R_PCH_H_PCR_GPIO_GPP_F_HOSTSW_OWN, R_PCH_H_PCR_GPIO_GPP_F_GPI_IS, R_PCH_H_PCR_GPIO_GPP_F_GPI_IE, R_PCH_H_PCR_GPIO_GPP_F_GPI_GPE_STS, R_PCH_H_PCR_GPIO_GPP_F_GPI_GPE_EN, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, R_PCH_H_PCR_GPIO_GPP_F_PADCFGLOCK, R_PCH_H_PCR_GPIO_GPP_F_PADCFGLOCKTX, R_PCH_H_PCR_GPIO_GPP_F_PADCFG_OFFSET, V_PCH_GPIO_GPP_F_PAD_MAX}, //SKX PCH-Server GPP_F
+ {PID_GPIOCOM5, R_PCH_H_PCR_GPIO_GPP_G_PAD_OWN, R_PCH_H_PCR_GPIO_GPP_G_HOSTSW_OWN, R_PCH_H_PCR_GPIO_GPP_G_GPI_IS, R_PCH_H_PCR_GPIO_GPP_G_GPI_IE, R_PCH_H_PCR_GPIO_GPP_G_GPI_GPE_STS, R_PCH_H_PCR_GPIO_GPP_G_GPI_GPE_EN, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, R_PCH_H_PCR_GPIO_GPP_G_PADCFGLOCK, R_PCH_H_PCR_GPIO_GPP_G_PADCFGLOCKTX, R_PCH_H_PCR_GPIO_GPP_G_PADCFG_OFFSET, V_PCH_H_GPIO_GPP_G_PAD_MAX}, //SKX PCH-Server GPP_G
+ {PID_GPIOCOM5, R_PCH_H_PCR_GPIO_GPP_H_PAD_OWN, R_PCH_H_PCR_GPIO_GPP_H_HOSTSW_OWN, R_PCH_H_PCR_GPIO_GPP_H_GPI_IS, R_PCH_H_PCR_GPIO_GPP_H_GPI_IE, R_PCH_H_PCR_GPIO_GPP_H_GPI_GPE_STS, R_PCH_H_PCR_GPIO_GPP_H_GPI_GPE_EN, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, R_PCH_H_PCR_GPIO_GPP_H_PADCFGLOCK, R_PCH_H_PCR_GPIO_GPP_H_PADCFGLOCKTX, R_PCH_H_PCR_GPIO_GPP_H_PADCFG_OFFSET, V_PCH_H_GPIO_GPP_H_PAD_MAX}, //SKX PCH-Server GPP_H
+ {PID_GPIOCOM3, R_PCH_H_PCR_GPIO_GPP_I_PAD_OWN, R_PCH_H_PCR_GPIO_GPP_I_HOSTSW_OWN, R_PCH_H_PCR_GPIO_GPP_I_GPI_IS, R_PCH_H_PCR_GPIO_GPP_I_GPI_IE, R_PCH_H_PCR_GPIO_GPP_I_GPI_GPE_STS, R_PCH_H_PCR_GPIO_GPP_I_GPI_GPE_EN, R_PCH_H_PCR_GPIO_GPP_I_SMI_STS,R_PCH_H_PCR_GPIO_GPP_I_SMI_EN, R_PCH_H_PCR_GPIO_GPP_I_NMI_STS,R_PCH_H_PCR_GPIO_GPP_I_NMI_EN, R_PCH_H_PCR_GPIO_GPP_I_PADCFGLOCK, R_PCH_H_PCR_GPIO_GPP_I_PADCFGLOCKTX, R_PCH_H_PCR_GPIO_GPP_I_PADCFG_OFFSET, V_PCH_H_GPIO_GPP_I_PAD_MAX}, //SKX PCH-Server GPP_I
+ {PID_GPIOCOM4, R_PCH_H_PCR_GPIO_GPP_J_PAD_OWN, R_PCH_H_PCR_GPIO_GPP_J_HOSTSW_OWN, R_PCH_H_PCR_GPIO_GPP_J_GPI_IS, R_PCH_H_PCR_GPIO_GPP_J_GPI_IE, R_PCH_H_PCR_GPIO_GPP_J_GPI_GPE_STS, R_PCH_H_PCR_GPIO_GPP_J_GPI_GPE_EN, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, R_PCH_H_PCR_GPIO_GPP_J_PADCFGLOCK, R_PCH_H_PCR_GPIO_GPP_J_PADCFGLOCKTX, R_PCH_H_PCR_GPIO_GPP_J_PADCFG_OFFSET, V_PCH_H_GPIO_GPP_J_PAD_MAX}, //SKX PCH-Server GPP_J
+ {PID_GPIOCOM4, R_PCH_H_PCR_GPIO_GPP_K_PAD_OWN, R_PCH_H_PCR_GPIO_GPP_K_HOSTSW_OWN, R_PCH_H_PCR_GPIO_GPP_K_GPI_IS, R_PCH_H_PCR_GPIO_GPP_K_GPI_IE, R_PCH_H_PCR_GPIO_GPP_K_GPI_GPE_STS, R_PCH_H_PCR_GPIO_GPP_K_GPI_GPE_EN, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, R_PCH_H_PCR_GPIO_GPP_K_PADCFGLOCK, R_PCH_H_PCR_GPIO_GPP_K_PADCFGLOCKTX, R_PCH_H_PCR_GPIO_GPP_K_PADCFG_OFFSET, V_PCH_H_GPIO_GPP_K_PAD_MAX}, //SKX PCH-Server GPP_K
+ {PID_GPIOCOM5, R_PCH_H_PCR_GPIO_GPP_L_PAD_OWN, R_PCH_H_PCR_GPIO_GPP_L_HOSTSW_OWN, R_PCH_H_PCR_GPIO_GPP_L_GPI_IS, R_PCH_H_PCR_GPIO_GPP_L_GPI_IE, R_PCH_H_PCR_GPIO_GPP_K_GPI_GPE_STS, R_PCH_H_PCR_GPIO_GPP_L_GPI_GPE_EN, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, R_PCH_H_PCR_GPIO_GPP_L_PADCFGLOCK, R_PCH_H_PCR_GPIO_GPP_L_PADCFGLOCKTX, R_PCH_H_PCR_GPIO_GPP_L_PADCFG_OFFSET, V_PCH_H_GPIO_GPP_L_PAD_MAX}, //SKX PCH-Server GPP_L
+ {PID_GPIOCOM2, R_PCH_H_PCR_GPIO_GPD_PAD_OWN, R_PCH_PCR_GPIO_GPD_HOSTSW_OWN, R_PCH_PCR_GPIO_GPD_GPI_IS, R_PCH_PCR_GPIO_GPD_GPI_IE, R_PCH_PCR_GPIO_GPD_GPI_GPE_STS, R_PCH_PCR_GPIO_GPD_GPI_GPE_EN, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, R_PCH_H_PCR_GPIO_GPD_PADCFGLOCK, R_PCH_H_PCR_GPIO_GPD_PADCFGLOCKTX, R_PCH_PCR_GPIO_GPD_PADCFG_OFFSET, V_PCH_GPIO_GPD_PAD_MAX} //SKX PCH-Server GPD
+};
+
+
+//
+// SATA reset port to GPIO pin mapping
+// SATAGP_x -> GPIO pin y
+//
+
+GPIO_PAD_NATIVE_FUNCTION mPchHSataPortResetToGpioMap[PCH_H_AHCI_MAX_PORTS] =
+{
+ {GPIO_SKL_H_GPP_E0, GpioPadModeNative2},
+ {GPIO_SKL_H_GPP_E1, GpioPadModeNative2},
+ {GPIO_SKL_H_GPP_E2, GpioPadModeNative2},
+ {GPIO_SKL_H_GPP_F0, GpioPadModeNative2},
+ {GPIO_SKL_H_GPP_F1, GpioPadModeNative2},
+ {GPIO_SKL_H_GPP_F2, GpioPadModeNative2},
+ {GPIO_SKL_H_GPP_F3, GpioPadModeNative2},
+ {GPIO_SKL_H_GPP_F4, GpioPadModeNative2}
+};
+
+//
+// SATADevSlpPin to GPIO pin mapping
+// SATA_DEVSLP_x -> GPIO pin y
+//
+
+GPIO_PAD_NATIVE_FUNCTION mPchHSataDevSlpPinToGpioMap[PCH_H_AHCI_MAX_PORTS] =
+{
+ {GPIO_SKL_H_GPP_E4, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_E5, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_E6, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_F5, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_F6, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_F7, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_F8, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_F9, GpioPadModeNative1}
+};
diff --git a/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmGpioLib/PeiDxeSmmGpioLib.inf b/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmGpioLib/PeiDxeSmmGpioLib.inf
new file mode 100644
index 0000000000..0d7c56c0d0
--- /dev/null
+++ b/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmGpioLib/PeiDxeSmmGpioLib.inf
@@ -0,0 +1,55 @@
+### @file
+#
+# Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which 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.
+#
+###
+
+[Defines]
+ INF_VERSION = 0x00010017
+ BASE_NAME = PeiDxeSmmGpioLib
+ FILE_GUID = 16EC5CA8-8195-4847-B6CB-662BD7B763F2
+ VERSION_STRING = 1.0
+ MODULE_TYPE = BASE
+ LIBRARY_CLASS = GpioLib
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+
+
+[LibraryClasses]
+ BaseLib
+ IoLib
+ DebugLib
+ MmPciLib
+ PchCycleDecodingLib
+ PchSbiAccessLib
+ PchPcrLib #SERVER_BIOS
+ HobLib
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ PurleyRcPkg/RcPkg.dec
+ LewisburgPkg/PchRcPkg.dec #SERVER_BIOS
+
+
+[Sources]
+ GpioLib.c
+ GpioLibrary.h
+ GpioNativeLib.c
+ GpioInit.c
+ PchSklGpioData.c
+
+[Guids]
+ gPlatformGpioConfigGuid
diff --git a/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchCycleDecodingLib/PchCycleDecodingLib.c b/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchCycleDecodingLib/PchCycleDecodingLib.c
new file mode 100644
index 0000000000..3629bc5157
--- /dev/null
+++ b/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchCycleDecodingLib/PchCycleDecodingLib.c
@@ -0,0 +1,1176 @@
+/** @file
+
+Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+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.
+
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/MmPciBaseLib.h>
+#include <PchAccess.h>
+#include <Library/PchInfoLib.h>
+#include <Library/PchPcrLib.h>
+#include <Library/PchP2sbLib.h>
+#include <Library/PchCycleDecodingLib.h>
+
+/**
+ Set PCH ACPI base address.
+ The Address should not be 0 and should be 256 bytes alignment, and it is IO space, so must not exceed 0xFFFF.
+ This cycle decoding is allowed to set when DMIC.SRL is 0.
+ Programming steps:
+ 1. clear PMC PCI offset 44h [7] to diable ACPI base address first before changing base address.
+ 2. program PMC PCI offset 40h [15:2] to ACPI base address.
+ 3. set PMC PCI offset 44h [7] to enable ACPI base address.
+ 4. program "ACPI Base Address" PCR[DMI] + 27B4h[23:18, 15:2, 0] to [0x3F, PMC PCI Offset 40h bit[15:2], 1].
+ 5. Program "ACPI Base Destination ID"
+ For SPT-LP: Program PCR[DMI] + 27B8h[31:0] to 0x23A0
+ For SPT-H: Program PCR[DMI] + 27B8h[31:0] to 0x23A8
+
+ @param[in] Address Address for ACPI base address.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid base address passed.
+ @retval EFI_UNSUPPORTED DMIC.SRL is set.
+**/
+EFI_STATUS
+EFIAPI
+PchAcpiBaseSet (
+ IN UINT16 Address
+ )
+{
+ UINTN PmcBase;
+ UINT32 Dmic;
+ UINT32 Data32;
+ PCH_SERIES PchSeries;
+
+ PchSeries = GetPchSeries ();
+
+ if (((Address & 0x00FF) != 0) ||
+ (Address == 0))
+ {
+ DEBUG((DEBUG_ERROR, "PchAcpiBaseSet Error. Invalid Address: %x.\n", Address));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+ PchPcrRead32 (PID_DMI, R_PCH_PCR_DMI_DMIC, &Dmic);
+ if ((Dmic & B_PCH_PCR_DMI_DMIC_SRL) != 0) {
+ DEBUG((DEBUG_ERROR, "PchAcpiBaseSet Error. DMIC.SRL is set.\n"));
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ PmcBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_PMC,
+ PCI_FUNCTION_NUMBER_PCH_PMC
+ );
+ if (MmioRead16 (PmcBase) == 0xFFFF) {
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+ //
+ // Disable ABASE in PMC Device first before changing base address.
+ //
+ MmioAnd8 (
+ PmcBase + R_PCH_PMC_ACPI_CNT,
+ (UINT8) ~B_PCH_PMC_ACPI_CNT_ACPI_EN
+ );
+ //
+ // Program ABASE in PMC Device
+ //
+ MmioAndThenOr16 (
+ PmcBase + R_PCH_PMC_ACPI_BASE,
+ (UINT16) (~B_PCH_PMC_ACPI_BASE_BAR),
+ Address
+ );
+ //
+ // Enable ABASE in PMC Device
+ //
+ MmioOr8 (
+ PmcBase + R_PCH_PMC_ACPI_CNT,
+ B_PCH_PMC_ACPI_CNT_ACPI_EN
+ );
+ //
+ // Program "ACPI Base Address" PCR[DMI] + 27B4h[23:18, 15:2, 0] to [0x3F, PMC PCI Offset 40h bit[15:2], 1]
+ //
+ PchPcrWrite32 (
+ PID_DMI, R_PCH_PCR_DMI_ACPIBA,
+ (0x00FC0001 + Address)
+ );
+ //
+ // Program "ACPI Base Destination ID"
+ // For SPT-LP:
+ // Program PCR[DMI] + 27B8h[31:0] to 0x23A0
+ // For SPT-H:
+ // Program PCR[DMI] + 27B8h[31:0] to 0x23A8
+ //
+ if(PchSeries == PchLp){
+ Data32 = 0x23A0;
+ } else {
+ Data32 = 0x23A8;
+ }
+ PchPcrWrite32 (
+ PID_DMI, R_PCH_PCR_DMI_ACPIBDID,
+ Data32
+ );
+ return EFI_SUCCESS;
+}
+
+/**
+ Get PCH ACPI base address.
+
+ @param[out] Address Address of ACPI base address.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid pointer passed.
+**/
+EFI_STATUS
+EFIAPI
+PchAcpiBaseGet (
+ OUT UINT16 *Address
+ )
+{
+ UINTN PmcBase;
+
+ if (Address == NULL) {
+ DEBUG((DEBUG_ERROR, "PchAcpiBaseGet Error. Invalid pointer.\n"));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PmcBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_PMC,
+ PCI_FUNCTION_NUMBER_PCH_PMC
+ );
+ if (MmioRead16 (PmcBase) == 0xFFFF) {
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+ *Address = MmioRead16 (PmcBase + R_PCH_PMC_ACPI_BASE) & B_PCH_PMC_ACPI_BASE_BAR;
+ return EFI_SUCCESS;
+}
+
+/**
+ Set PCH PWRM base address.
+ This cycle decoding is allowed to set when DMIC.SRL is 0.
+ Programming steps:
+ 1. clear PMC PCI offset 44h [8] to diable PWRM base address first before changing PWRM base address.
+ 2. program PMC PCI offset 48h [31:16] to PM base address.
+ 3. set PMC PCI offset 44h [8] to enable PWRM base address.
+ 4. program "PM Base Address Memory Range Base" PCR[DMI] + 27ACh[15:0] to the same value programmed in PMC PCI Offset 48h bit[31:16], this has an implication of making sure the PWRMBASE to be 64KB aligned.
+ program "PM Base Address Memory Range Limit" PCR[DMI] + 27ACh[31:16] to the value programmed in PMC PCI Offset 48h bit[31:16], this has an implication of making sure the memory allocated to PWRMBASE to be 64KB in size.
+ 5. Program "PM Base Control"
+ For SPT-LP: Program PCR[DMI] + 27B0h[31, 30:0] to [1, 0x23A0]
+ For SPT-H: Program PCR[DMI] + 27B0h[31, 30:0] to [1, 0x23A8]
+
+ @param[in] Address Address for PWRM base address.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid base address passed.
+ @retval EFI_UNSUPPORTED DMIC.SRL is set.
+**/
+EFI_STATUS
+EFIAPI
+PchPwrmBaseSet (
+ IN UINT32 Address
+ )
+{
+ UINTN PmcBase;
+ UINT32 Dmic;
+ UINT32 Data32;
+ PCH_SERIES PchSeries;
+
+ PchSeries = GetPchSeries ();
+
+ if (((Address & (~B_PCH_PMC_PWRM_BASE_BAR)) != 0) ||
+ (Address == 0))
+ {
+ DEBUG((DEBUG_ERROR, "PchPwrmBaseSet Error. Invalid Address: %x.\n", Address));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+ PchPcrRead32 (PID_DMI, R_PCH_PCR_DMI_DMIC, &Dmic);
+ if ((Dmic & B_PCH_PCR_DMI_DMIC_SRL) != 0) {
+ DEBUG((DEBUG_ERROR, "PchPwrmBaseSet Error. DMIC.SRL is set.\n"));
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ PmcBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_PMC,
+ PCI_FUNCTION_NUMBER_PCH_PMC
+ );
+ if (MmioRead16 (PmcBase) == 0xFFFF) {
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+ //
+ // Disable PWRMBASE in PMC Device first before changing PWRM base address.
+ //
+ MmioAnd16 (
+ PmcBase + R_PCH_PMC_ACPI_CNT,
+ (UINT16) ~B_PCH_PMC_ACPI_CNT_PWRM_EN
+ );
+ //
+ // Program PWRMBASE in PMC Device
+ //
+ MmioAndThenOr32 (
+ PmcBase + R_PCH_PMC_PWRM_BASE,
+ (UINT32) (~B_PCH_PMC_PWRM_BASE_BAR),
+ Address
+ );
+ //
+ // Enable PWRMBASE in PMC Device
+ //
+ MmioOr16 (
+ PmcBase + R_PCH_PMC_ACPI_CNT,
+ B_PCH_PMC_ACPI_CNT_PWRM_EN
+ );
+ //
+ // Program "PM Base Address Memory Range Base" PCR[DMI] + 27ACh[15:0] to the same value programmed in PMC PCI Offset 48h bit[31:16], this has an implication of making sure the PWRMBASE to be 64KB aligned.
+ // Program "PM Base Address Memory Range Limit" PCR[DMI] + 27ACh[31:16] to the value programmed in PMC PCI Offset 48h bit[31:16], this has an implication of making sure the memory allocated to PWRMBASE to be 64KB in size.
+ //
+ PchPcrWrite32 (
+ PID_DMI, R_PCH_PCR_DMI_PMBASEA,
+ ((Address & 0xFFFF0000) | (Address >> 16))
+ );
+ //
+ // Program "PM Base Control"
+ // For SPT-LP:
+ // Program PCR[DMI] + 27B0h[31, 30:0] to [1, 0x23A0]
+ // For SPT-H:
+ // Program PCR[DMI] + 27B0h[31, 30:0] to [1, 0x23A8]
+ //
+ if(PchSeries == PchLp){
+ Data32 = 0x800023A0;
+ } else {
+ Data32 = 0x800023A8;
+ }
+ PchPcrWrite32 (
+ PID_DMI, R_PCH_PCR_DMI_PMBASEC,
+ Data32
+ );
+ return EFI_SUCCESS;
+}
+
+/**
+ Get PCH PWRM base address.
+
+ @param[out] Address Address of PWRM base address.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid pointer passed.
+**/
+EFI_STATUS
+EFIAPI
+PchPwrmBaseGet (
+ OUT UINT32 *Address
+ )
+{
+ UINTN PmcBase;
+
+ if (Address == NULL) {
+ DEBUG((DEBUG_ERROR, "PchPwrmBaseGet Error. Invalid pointer.\n"));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PmcBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_PMC,
+ PCI_FUNCTION_NUMBER_PCH_PMC
+ );
+ if (MmioRead16 (PmcBase) == 0xFFFF) {
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+ *Address = MmioRead32 (PmcBase + R_PCH_PMC_PWRM_BASE) & B_PCH_PMC_PWRM_BASE_BAR;
+ return EFI_SUCCESS;
+}
+
+/**
+ Set PCH TCO base address.
+ This cycle decoding is allowed to set when DMIC.SRL is 0.
+ Programming steps:
+ 1. set Smbus PCI offset 54h [8] to enable TCO base address.
+ 2. program Smbus PCI offset 50h [15:5] to TCO base address.
+ 3. set Smbus PCI offset 54h [8] to enable TCO base address.
+ 4. program "TCO Base Address" PCR[DMI] + 2778h[15:5, 1] to [Smbus PCI offset 50h[15:5], 1].
+
+ @param[in] Address Address for TCO base address.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid base address passed.
+ @retval EFI_UNSUPPORTED DMIC.SRL is set.
+**/
+EFI_STATUS
+EFIAPI
+PchTcoBaseSet (
+ IN UINT16 Address
+ )
+{
+ UINTN SmbusBase;
+ UINT32 Dmic;
+
+ if ((Address & ~B_PCH_SMBUS_TCOBASE_BAR) != 0) {
+ DEBUG((DEBUG_ERROR, "PchTcoBaseSet Error. Invalid Address: %x.\n", Address));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+ PchPcrRead32 (PID_DMI, R_PCH_PCR_DMI_DMIC, &Dmic);
+ if ((Dmic & B_PCH_PCR_DMI_DMIC_SRL) != 0) {
+ DEBUG((DEBUG_ERROR, "PchTcoBaseSet Error. DMIC.SRL is set.\n"));
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ SmbusBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_SMBUS,
+ PCI_FUNCTION_NUMBER_PCH_SMBUS
+ );
+ if (MmioRead16 (SmbusBase) == 0xFFFF) {
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+ //
+ // Verify TCO base is not locked.
+ //
+ if ((MmioRead8 (SmbusBase + R_PCH_SMBUS_TCOCTL) & B_PCH_SMBUS_TCOCTL_TCO_BASE_LOCK) != 0) {
+ ASSERT (FALSE);
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Disable TCO in SMBUS Device first before changing base address.
+ //
+ MmioAnd8 (
+ SmbusBase + R_PCH_SMBUS_TCOCTL + 1,
+ (UINT8) ~(B_PCH_SMBUS_TCOCTL_TCO_BASE_EN >> 8)
+ );
+ //
+ // Program TCO in SMBUS Device
+ //
+ MmioAndThenOr16 (
+ SmbusBase + R_PCH_SMBUS_TCOBASE,
+ (UINT16) (~B_PCH_SMBUS_TCOBASE_BAR),
+ Address
+ );
+ //
+ // Enable TCO in SMBUS Device
+ //
+ MmioOr8 (
+ SmbusBase + R_PCH_SMBUS_TCOCTL + 1,
+ (B_PCH_SMBUS_TCOCTL_TCO_BASE_EN >> 8)
+ );
+ //
+ // Program "TCO Base Address" PCR[DMI] + 2778h[15:5, 1] to [SMBUS PCI offset 50h[15:5], 1].
+ //
+ PchPcrWrite16 (
+ PID_DMI, R_PCH_PCR_DMI_TCOBASE,
+ (Address | BIT1)
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Get PCH TCO base address.
+
+ @param[out] Address Address of TCO base address.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid pointer passed.
+**/
+EFI_STATUS
+EFIAPI
+PchTcoBaseGet (
+ OUT UINT16 *Address
+ )
+{
+ if (Address == NULL) {
+ DEBUG((DEBUG_ERROR, "PchTcoBaseGet Error. Invalid pointer.\n"));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Read "TCO Base Address" PCR[DMI] + 2778h[15:5]
+ // Don't read TCO base address from SMBUS PCI register since SMBUS might be disabled.
+ //
+ PchPcrRead16 (
+ PID_DMI, R_PCH_PCR_DMI_TCOBASE,
+ Address
+ );
+ *Address &= B_PCH_PCR_DMI_TCOBASE_TCOBA;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Set PCH LPC/eSPI generic IO range.
+ For generic IO range, the base address must align to 4 and less than 0xFFFF, and the length must be power of 2
+ and less than or equal to 256. Moreover, the address must be length aligned.
+ This function basically checks the address and length, which should not overlap with all other generic ranges.
+ If no more generic range register available, it returns out of resource error.
+ This cycle decoding is allowed to set when DMIC.SRL is 0.
+ Some IO ranges below 0x100 have fixed target. The target might be ITSS,RTC,LPC,PMC or terminated inside P2SB
+ but all predefined and can't be changed. IO range below 0x100 will be rejected in this function except below ranges:
+ 0x00-0x1F,
+ 0x44-0x4B,
+ 0x54-0x5F,
+ 0x68-0x6F,
+ 0x80-0x8F,
+ 0xC0-0xFF
+ Steps of programming generic IO range:
+ 1. Program LPC/eSPI PCI Offset 84h ~ 93h of Mask, Address, and Enable.
+ 2. Program LPC/eSPI Generic IO Range #, PCR[DMI] + 2730h ~ 273Fh to the same value programmed in LPC/eSPI PCI Offset 84h~93h.
+
+ @param[in] Address Address for generic IO range base address.
+ @param[in] Length Length of generic IO range.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid base address or length passed.
+ @retval EFI_OUT_OF_RESOURCES No more generic range available.
+ @retval EFI_UNSUPPORTED DMIC.SRL is set.
+**/
+EFI_STATUS
+EFIAPI
+PchLpcGenIoRangeSet (
+ IN UINT16 Address,
+ IN UINTN Length
+ , IN UINT8 SlaveDevice
+ )
+{
+ EFI_STATUS Status;
+ PCH_LPC_GEN_IO_RANGE_LIST LpcGenIoRangeList;
+ UINTN LpcBase;
+ UINTN Index;
+ UINTN BaseAddr;
+ UINTN MaskLength;
+ UINTN TempMaxAddr;
+ UINT32 Data32;
+ UINTN ArraySize;
+ static struct EXCEPT_RANGE {
+ UINT8 Start;
+ UINT8 Length;
+ } ExceptRanges[] = { {0x00, 0x20}, {0x44, 0x08}, {0x54, 0x0C}, {0x68, 0x08}, {0x80, 0x10}, {0xC0, 0x40} };
+
+ Index = 0;
+ //
+ // Note: Inside this function, don't use debug print since it's could used before debug print ready.
+ //
+
+ //
+ // For generic IO range, the base address must align to 4 and less than 0xFFFF,
+ // the length must be power of 2 and less than or equal to 256, and the address must be length aligned.
+ // IO range below 0x100 will be rejected in this function except below ranges:
+ // 0x00-0x1F,
+ // 0x44-0x4B,
+ // 0x54-0x5F,
+ // 0x68-0x6F,
+ // 0x80-0x8F,
+ // 0xC0-0xFF
+ //
+ if (((Length & (Length - 1)) != 0) ||
+ ((Address & (UINT16)~B_PCH_LPC_GENX_DEC_IOBAR) != 0) ||
+ (Length > 256))
+ {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+ if (Address < 0x100) {
+ ArraySize = sizeof (ExceptRanges) / sizeof (struct EXCEPT_RANGE);
+ for (Index = 0; Index < ArraySize; Index++) {
+ if ((Address >= ExceptRanges[Index].Start) &&
+ ((Address + Length) <= ((UINTN)ExceptRanges[Index].Start + (UINTN)ExceptRanges[Index].Length)))
+ {
+ break;
+ }
+ }
+ if (Index >= ArraySize) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ //
+ // check if range overlap
+ //
+ Status = PchLpcGenIoRangeGet (&LpcGenIoRangeList, SlaveDevice);
+ if (EFI_ERROR (Status)) {
+ ASSERT (FALSE);
+ return Status;
+ }
+ if (SlaveDevice == LPC_ESPI_FIRST_SLAVE) {
+ for (Index = 0; Index < PCH_LPC_GEN_IO_RANGE_MAX; Index++) {
+ BaseAddr = LpcGenIoRangeList.Range[Index].BaseAddr;
+ MaskLength = LpcGenIoRangeList.Range[Index].Length;
+ if (BaseAddr == 0) {
+ continue;
+ }
+ if (((Address >= BaseAddr) && (Address < (BaseAddr + MaskLength))) ||
+ (((Address + Length) > BaseAddr) && ((Address + Length) <= (BaseAddr + MaskLength))))
+ {
+ if ((Address >= BaseAddr) && (Length <= MaskLength)) {
+ //
+ // return SUCCESS while range is covered.
+ //
+ return EFI_SUCCESS;
+ }
+
+ if ((Address + Length) > (BaseAddr + MaskLength)) {
+ TempMaxAddr = Address + Length;
+ } else {
+ TempMaxAddr = BaseAddr + MaskLength;
+ }
+ if (Address > BaseAddr) {
+ Address = (UINT16) BaseAddr;
+ }
+ Length = TempMaxAddr - Address;
+ break;
+ }
+ }
+ //
+ // If no range overlap
+ //
+ if (Index >= PCH_LPC_GEN_IO_RANGE_MAX) {
+ //
+ // Find a empty register
+ //
+ for (Index = 0; Index < PCH_LPC_GEN_IO_RANGE_MAX; Index++) {
+ BaseAddr = LpcGenIoRangeList.Range[Index].BaseAddr;
+ if (BaseAddr == 0) {
+ break;
+ }
+ }
+ if (Index >= PCH_LPC_GEN_IO_RANGE_MAX) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ }
+ } else {
+ BaseAddr = LpcGenIoRangeList.Range[0].BaseAddr;
+ MaskLength = LpcGenIoRangeList.Range[0].Length;
+ if (BaseAddr != 0) {
+ if (((Address >= BaseAddr) && (Address < (BaseAddr + MaskLength))) ||
+ (((Address + Length) > BaseAddr) && ((Address + Length) <= (BaseAddr + MaskLength))))
+ {
+ if ((Address >= BaseAddr) && (Length <= MaskLength)) {
+ //
+ // return SUCCESS while range is covered.
+ //
+ return EFI_SUCCESS;
+ } else {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ }
+ }
+ }
+ //
+ // This cycle decoding is only allowed to set when DMIC.SRL is 0.
+ //
+ PchPcrRead32 (PID_DMI, R_PCH_PCR_DMI_DMIC, &Data32);
+ if ((Data32 & B_PCH_PCR_DMI_DMIC_SRL) != 0) {
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Program LPC/eSPI generic IO range register accordingly.
+ //
+ LpcBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC
+ );
+ Data32 = (UINT32) (((Length - 1) << 16) & B_PCH_LPC_GENX_DEC_IODRA);
+ Data32 |= (UINT32) Address;
+ Data32 |= B_PCH_LPC_GENX_DEC_EN;
+
+ if (SlaveDevice == LPC_ESPI_FIRST_SLAVE) {
+ //
+ // Program LPC/eSPI PCI Offset 84h ~ 93h of Mask, Address, and Enable.
+ //
+ MmioWrite32 (
+ LpcBase + R_PCH_LPC_GEN1_DEC + Index * 4,
+ Data32
+ );
+ //
+ // Program LPC Generic IO Range #, PCR[DMI] + 2730h ~ 273Fh to the same value programmed in LPC/eSPI PCI Offset 84h~93h.
+ //
+ PchPcrWrite32 (
+ PID_DMI, (UINT16) (R_PCH_PCR_DMI_LPCLGIR1 + Index * 4),
+ Data32
+ );
+ } else {
+ ASSERT(FALSE);
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Get PCH LPC/eSPI generic IO range list.
+ This function returns a list of base address, length, and enable for all LPC/eSPI generic IO range regsiters.
+
+ @param[out] LpcGenIoRangeList Return all LPC/eSPI generic IO range register status.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid base address passed.
+**/
+EFI_STATUS
+EFIAPI
+PchLpcGenIoRangeGet (
+ OUT PCH_LPC_GEN_IO_RANGE_LIST *LpcGenIoRangeList
+ , IN UINT8 SlaveDevice
+ )
+{
+ UINTN Index;
+ UINTN LpcBase;
+ UINT32 Data32;
+
+ //
+ // Note: Inside this function, don't use debug print since it's could used before debug print ready.
+ //
+
+ if (LpcGenIoRangeList == NULL) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ LpcBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC
+ );
+
+ if (SlaveDevice == LPC_ESPI_FIRST_SLAVE) {
+ for (Index = 0; Index < PCH_LPC_GEN_IO_RANGE_MAX; Index++) {
+ Data32 = MmioRead32 (LpcBase + R_PCH_LPC_GEN1_DEC + Index * 4);
+ LpcGenIoRangeList->Range[Index].BaseAddr = Data32 & B_PCH_LPC_GENX_DEC_IOBAR;
+ LpcGenIoRangeList->Range[Index].Length = ((Data32 & B_PCH_LPC_GENX_DEC_IODRA) >> 16) + 4;
+ LpcGenIoRangeList->Range[Index].Enable = Data32 & B_PCH_LPC_GENX_DEC_EN;
+ }
+ } else {
+ ASSERT(FALSE);
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Set PCH LPC/eSPI memory range decoding.
+ This cycle decoding is allowed to set when DMIC.SRL is 0.
+ Programming steps:
+ 1. Program LPC/eSPI PCI Offset 98h [0] to [0] to disable memory decoding first before changing base address.
+ 2. Program LPC/eSPI PCI Offset 98h [31:16, 0] to [Address, 1].
+ 3. Program LPC/eSPI Memory Range, PCR[DMI] + 2740h to the same value programmed in LPC/eSPI PCI Offset 98h.
+
+ @param[in] Address Address for memory base address.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid base address or length passed.
+ @retval EFI_OUT_OF_RESOURCES No more generic range available.
+ @retval EFI_UNSUPPORTED DMIC.SRL is set.
+**/
+EFI_STATUS
+EFIAPI
+PchLpcMemRangeSet (
+ IN UINT32 Address
+ , IN UINT8 SlaveDevice
+ )
+{
+ UINTN LpcBase;
+ UINT32 Dmic;
+ UINTN LpcReg;
+ UINT16 DmiReg;
+
+ if ((Address & (~B_PCH_LPC_LGMR_MA)) != 0) {
+ DEBUG((DEBUG_ERROR, "PchLpcMemRangeSet Error. Invalid Address: %x.\n", Address));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+ PchPcrRead32 (PID_DMI, R_PCH_PCR_DMI_DMIC, &Dmic);
+ if ((Dmic & B_PCH_PCR_DMI_DMIC_SRL) != 0) {
+ DEBUG((DEBUG_ERROR, "PchLpcMemRangeSet Error. DMIC.SRL is set.\n"));
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ LpcBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC
+ );
+ if (SlaveDevice == ESPI_SECONDARY_SLAVE) {
+ ASSERT(FALSE);
+ } else {
+ LpcReg = LpcBase + R_PCH_LPC_LGMR;
+ DmiReg = R_PCH_PCR_DMI_LPCGMR;
+ }
+ //
+ // Program LPC/eSPI PCI Offset 98h [0] (LPC/ePSI first slave) or A8h [0] (eSPI secondary slave) to [0] to disable memory decoding first before changing base address.
+ //
+ MmioAnd32 (
+ LpcReg,
+ (UINT32) ~B_PCH_LPC_LGMR_LMRD_EN
+ );
+ //
+ // Program LPC/eSPI PCI Offset 98h [31:16, 0] (LPC/ eSPI first slave) or A8h [31:16, 0] (eSPI secondary slave) to [Address, 1].
+ //
+ MmioWrite32 (
+ LpcReg,
+ (Address | B_PCH_LPC_LGMR_LMRD_EN)
+ );
+ //
+ // Program LPC Memory Range, PCR[DMI] + 2740h (LPC/eSPI first slave) or 27C0h (eSPI secondary slave) to the same value programmed in LPC/eSPI PCI Offset 98h.
+ //
+ PchPcrWrite32 (
+ PID_DMI, DmiReg,
+ (Address | B_PCH_LPC_LGMR_LMRD_EN)
+ );
+ return EFI_SUCCESS;
+}
+
+/**
+ Get PCH LPC/eSPI memory range decoding address.
+
+ @param[out] Address Address of LPC/eSPI memory decoding base address.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid base address passed.
+**/
+EFI_STATUS
+EFIAPI
+PchLpcMemRangeGet (
+ OUT UINT32 *Address
+ , IN UINT8 SlaveDevice
+ )
+{
+ UINTN LpcBase;
+
+ if (Address == NULL) {
+ DEBUG((DEBUG_ERROR, "PchLpcMemRangeGet Error. Invalid pointer.\n"));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ LpcBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC
+ );
+ if (SlaveDevice == LPC_ESPI_FIRST_SLAVE) {
+ *Address = MmioRead32 (LpcBase + R_PCH_LPC_LGMR) & B_PCH_LPC_LGMR_MA;
+ } else {
+ ASSERT(FALSE);
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Set PCH BIOS range deocding.
+ This will check General Control and Status bit 10 (GCS.BBS) to identify SPI or LPC/eSPI and program BDE register accordingly.
+ Please check EDS for detail of BiosDecodeEnable bit definition.
+ bit 15: F8-FF Enable
+ bit 14: F0-F8 Enable
+ bit 13: E8-EF Enable
+ bit 12: E0-E8 Enable
+ bit 11: D8-DF Enable
+ bit 10: D0-D7 Enable
+ bit 9: C8-CF Enable
+ bit 8: C0-C7 Enable
+ bit 7: Legacy F Segment Enable
+ bit 6: Legacy E Segment Enable
+ bit 5: Reserved
+ bit 4: Reserved
+ bit 3: 70-7F Enable
+ bit 2: 60-6F Enable
+ bit 1: 50-5F Enable
+ bit 0: 40-4F Enable
+ This cycle decoding is allowed to set when DMIC.SRL is 0.
+ Programming steps:
+ 1. if GCS.BBS is 0 (SPI), program SPI offset D8h to BiosDecodeEnable.
+ if GCS.BBS is 1 (LPC/eSPi), program LPC offset D8h to BiosDecodeEnable.
+ 2. program LPC BIOS Decode Enable, PCR[DMI] + 2744h to the same value programmed in LPC or SPI Offset D8h.
+
+ @param[in] BiosDecodeEnable Bios decode enable setting.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_UNSUPPORTED DMIC.SRL is set.
+**/
+EFI_STATUS
+EFIAPI
+PchBiosDecodeEnableSet (
+ IN UINT16 BiosDecodeEnable
+ )
+{
+ UINTN BaseAddr;
+ UINT32 DmiGcsBbs;
+ UINT32 Dmic;
+
+ PchPcrRead32 (PID_DMI, R_PCH_PCR_DMI_DMIC, &Dmic);
+ if ((Dmic & B_PCH_PCR_DMI_DMIC_SRL) != 0) {
+ DEBUG((DEBUG_ERROR, "PchBiosDecodeEnableSet Error. DMIC.SRL is set.\n"));
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ PchPcrRead32 (PID_DMI, R_PCH_PCR_DMI_GCS, &DmiGcsBbs);
+ DmiGcsBbs &= B_PCH_PCR_DMI_BBS;
+ //
+ // Check General Control and Status (GCS) [10]
+ // '0': SPI
+ // '1': LPC/eSPI
+ //
+ if (DmiGcsBbs == 0) {
+ BaseAddr = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_SPI,
+ PCI_FUNCTION_NUMBER_PCH_SPI
+ );
+ //
+ // if GCS.BBS is 0 (SPI), program SPI offset D8h to BiosDecodeEnable.
+ //
+ MmioWrite16 (BaseAddr + R_PCH_SPI_BDE, BiosDecodeEnable);
+ } else {
+ BaseAddr = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC
+ );
+ //
+ // if GCS.BBS is 1 (LPC/eSPi), program LPC offset D8h to BiosDecodeEnable.
+ //
+ MmioWrite16 (BaseAddr + R_PCH_LPC_BDE, BiosDecodeEnable);
+ }
+
+ //
+ // program LPC BIOS Decode Enable, PCR[DMI] + 2744h to the same value programmed in LPC or SPI Offset D8h.
+ //
+ PchPcrWrite16 (PID_DMI, R_PCH_PCR_DMI_LPCBDE, BiosDecodeEnable);
+ return EFI_SUCCESS;
+}
+
+/**
+ Set PCH LPC/eSPI IO decode ranges.
+ Program LPC/eSPI I/O Decode Ranges, PCR[DMI] + 2770h[15:0] to the same value programmed in LPC/eSPI PCI offset 80h.
+ Please check EDS for detail of LPC/eSPI IO decode ranges bit definition.
+ Bit 12: FDD range
+ Bit 9:8: LPT range
+ Bit 6:4: ComB range
+ Bit 2:0: ComA range
+
+ @param[in] LpcIoDecodeRanges LPC/eSPI IO decode ranges bit settings.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_UNSUPPORTED DMIC.SRL is set.
+**/
+EFI_STATUS
+EFIAPI
+PchLpcIoDecodeRangesSet (
+ IN UINT16 LpcIoDecodeRanges
+ )
+{
+ UINTN LpcBaseAddr;
+ UINT32 Dmic;
+
+ //
+ // Note: Inside this function, don't use debug print since it's could used before debug print ready.
+ //
+
+ LpcBaseAddr = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC
+ );
+ //
+ // check if setting is identical
+ //
+ if (LpcIoDecodeRanges == MmioRead16 (LpcBaseAddr + R_PCH_LPC_IOD)) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // This cycle decoding is only allowed to set when DMIC.SRL is 0.
+ //
+ PchPcrRead32 (PID_DMI, R_PCH_PCR_DMI_DMIC, &Dmic);
+ if ((Dmic & B_PCH_PCR_DMI_DMIC_SRL) != 0) {
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // program LPC/eSPI PCI offset 80h.
+ //
+ MmioWrite16 (LpcBaseAddr + R_PCH_LPC_IOD, LpcIoDecodeRanges);
+
+ //
+ // program LPC I/O Decode Ranges, PCR[DMI] + 2770h[15:0] to the same value programmed in LPC/eSPI PCI offset 80h.
+ //
+ PchPcrWrite16 (PID_DMI, R_PCH_PCR_DMI_LPCIOD, LpcIoDecodeRanges);
+ return EFI_SUCCESS;
+}
+
+/**
+ Set PCH LPC/eSPI IO enable decoding.
+ Setup LPC/eSPI I/O Enables, PCR[DMI] + 2774h[15:0] to the same value program in LPC/eSPI PCI offset 82h.
+ Note: Bit[15:10] of the source decode register is Read-Only. The IO range indicated by the Enables field
+ in LPC/eSPI PCI offset 82h[13:10] is always forwarded by DMI to subtractive agent for handling.
+ Please check EDS for detail of Lpc/eSPI IO decode ranges bit definition.
+
+ @param[in] LpcIoEnableDecoding LPC/eSPI IO enable decoding bit settings.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_UNSUPPORTED DMIC.SRL is set.
+**/
+EFI_STATUS
+EFIAPI
+PchLpcIoEnableDecodingSet (
+ IN UINT16 LpcIoEnableDecoding
+ , IN UINT8 SlaveDevice
+ )
+{
+ UINTN LpcBaseAddr;
+ UINT32 Dmic;
+ UINTN LpcReg;
+
+ if (SlaveDevice == LPC_ESPI_FIRST_SLAVE) {
+ LpcReg = R_PCH_LPC_IOE;
+ } else {
+ ASSERT(FALSE);
+ }
+
+ //
+ // Note: Inside this function, don't use debug print since it's could used before debug print ready.
+ //
+
+ LpcBaseAddr = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC
+ );
+ if (LpcIoEnableDecoding == MmioRead16 (LpcBaseAddr + LpcReg)) {
+ return EFI_SUCCESS;
+ }
+ //
+ // This cycle decoding is only allowed to set when DMIC.SRL is 0.
+ //
+ PchPcrRead32 (PID_DMI, R_PCH_PCR_DMI_DMIC, &Dmic);
+ if ((Dmic & B_PCH_PCR_DMI_DMIC_SRL) != 0) {
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // program PCI offset 82h for LPC/eSPI CS#0 or offset A0h for eSPI CS#1.
+ //
+ MmioWrite16 (LpcBaseAddr + LpcReg, LpcIoEnableDecoding);
+
+ if (SlaveDevice == ESPI_SECONDARY_SLAVE) {
+ //
+ // For eSPI CS#1 device program PCI offset 82h respectively
+ //
+ MmioWrite16 (LpcBaseAddr + R_PCH_LPC_IOE, (LpcIoEnableDecoding | MmioRead16(LpcBaseAddr + R_PCH_LPC_IOE)));
+ }
+
+ //
+ // program LPC I/O Decode Ranges, PCR[DMI] + 2774h[15:0] to the same value programmed in LPC/eSPI PCI offset 82h.
+ //
+ PchPcrWrite16 (PID_DMI, R_PCH_PCR_DMI_LPCIOE, LpcIoEnableDecoding);
+ return EFI_SUCCESS;
+}
+
+
+//
+// PCH-LP RPR destination ID table
+//
+UINT16 PchLpRprDidTable[] = {
+ 0x2188, // Dest ID of RP1
+ 0x2189, // Dest ID of RP2
+ 0x218A, // Dest ID of RP3
+ 0x218B, // Dest ID of RP4
+ 0x2198, // Dest ID of RP5
+ 0x2199, // Dest ID of RP6
+ 0x219A, // Dest ID of RP7
+ 0x219B, // Dest ID of RP8
+ 0x21A8, // Dest ID of RP9
+ 0x21A9, // Dest ID of RP10
+ 0x21AA, // Dest ID of RP11
+ 0x21AB // Dest ID of RP12
+};
+
+//
+// PCH-H RPR destination ID table
+//
+UINT16 PchHRprDidTable[] = {
+ 0x2180, // Dest ID of RP1
+ 0x2181, // Dest ID of RP2
+ 0x2182, // Dest ID of RP3
+ 0x2183, // Dest ID of RP4
+ 0x2188, // Dest ID of RP5
+ 0x2189, // Dest ID of RP6
+ 0x218A, // Dest ID of RP7
+ 0x218B, // Dest ID of RP8
+ 0x2198, // Dest ID of RP9
+ 0x2199, // Dest ID of RP10
+ 0x219A, // Dest ID of RP11
+ 0x219B, // Dest ID of RP12
+ 0x21A8, // Dest ID of RP13
+ 0x21A9, // Dest ID of RP14
+ 0x21AA, // Dest ID of RP15
+ 0x21AB, // Dest ID of RP16
+ 0x21B8, // Dest ID of RP17
+ 0x21B9, // Dest ID of RP18
+ 0x21BA, // Dest ID of RP19
+ 0x21BB, // Dest ID of RP20
+};
+
+/**
+ Set PCH IO port 80h cycle decoding to PCIE root port.
+ System BIOS is likely to do this very soon after reset before PCI bus enumeration.
+ This cycle decoding is allowed to set when DMIC.SRL is 0.
+ Programming steps:
+ 1. Program "RPR Destination ID", PCR[DMI] + 274Ch[31:16] to the Dest ID of RP.
+ 2. Program "Reserved Page Route", PCR[DMI] + 274Ch[11] to '1'. Use byte write on GCS+1 and leave the BILD bit which is RWO.
+
+ @param[in] RpPhyNumber PCIE root port physical number.
+
+ @retval EFI_SUCCESS Successfully completed.
+**/
+EFI_STATUS
+EFIAPI
+PchIoPort80DecodeSet (
+ IN UINTN RpPhyNumber
+ )
+{
+ UINT32 Dmic;
+ UINT16 *PchRprDidTable;
+
+ PchPcrRead32 (PID_DMI, R_PCH_PCR_DMI_DMIC, &Dmic);
+ if ((Dmic & B_PCH_PCR_DMI_DMIC_SRL) != 0) {
+ DEBUG((DEBUG_ERROR, "PchIoPort80DecodeSet Error. DMIC.SRL is set.\n"));
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ ///
+ /// IO port 80h is typically used by decoder/LED hardware for debug purposes.
+ /// By default PCH will forward IO port 80h cycles to LPC bus. The Reserved Page Route (RPR) bit
+ /// of General Control and Status register, located at PCR[DMI] + 274Ch[11] , allows software to
+ /// re-direct IO port 80h cycles to PCIe bus so that a target (for example, a debug card) on
+ /// PCIe bus can receive and claim these cycles.
+ /// The "RPR Destination ID", PCR[DMI] + 274Ch[31:16] need to be set accordingly to point
+ /// to the root port that decode this range. Reading from Port 80h may not return valid values
+ /// if the POST-card itself do not shadow the writes. Unlike LPC, PCIe does not shadow the Port 80 writes.
+ ///
+
+ if (GetPchSeries () == PchLp) {
+ PchRprDidTable = PchLpRprDidTable;
+ } else {
+ PchRprDidTable = PchHRprDidTable;
+ }
+
+ //
+ // Program "RPR Destination ID", PCR[DMI] + 274Ch[31:16] to the Dest ID of RP.
+ //
+ PchPcrWrite16 (PID_DMI, R_PCH_PCR_DMI_GCS + 2, PchRprDidTable[RpPhyNumber]);
+ //
+ // Program "Reserved Page Route", PCR[DMI] + 274Ch[11] to '1'.
+ // Use byte write on GCS+1 and leave the BILD bit which is RWO.
+ //
+ PchPcrAndThenOr8 (PID_DMI, R_PCH_PCR_DMI_GCS + 1, 0xFF, (B_PCH_PCR_DMI_RPR >> 8));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Get IO APIC regsiters base address.
+ It returns IO APIC INDEX, DATA, and EOI regsiter address once the parameter is not NULL.
+ This function will be unavailable after P2SB is hidden by PSF.
+
+ @param[out] IoApicIndex Buffer of IO APIC INDEX regsiter address
+ @param[out] IoApicData Buffer of IO APIC DATA regsiter address
+
+ @retval EFI_SUCCESS Successfully completed.
+**/
+EFI_STATUS
+PchIoApicBaseGet (
+ OPTIONAL OUT UINT32 *IoApicIndex,
+ OPTIONAL OUT UINT32 *IoApicData
+ )
+{
+ EFI_STATUS Status;
+ UINT16 RegIoac;
+ UINT32 RangeSelect;
+
+ Status = PchP2sbCfgGet16 (R_PCH_P2SB_IOAC, &RegIoac);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ RangeSelect = (RegIoac & B_PCH_P2SB_IOAC_ASEL) << N_PCH_IO_APIC_ASEL;
+
+ if (IoApicIndex != NULL) {
+ *IoApicIndex = R_PCH_IO_APIC_INDEX + RangeSelect;
+ }
+ if (IoApicData != NULL) {
+ *IoApicData = R_PCH_IO_APIC_DATA + RangeSelect;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Get HPET base address.
+ This function will be unavailable after P2SB is hidden by PSF.
+
+ @param[out] HpetBase Buffer of HPET base address
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchHpetBaseGet (
+ OUT UINT32 *HpetBase
+ )
+{
+ EFI_STATUS Status;
+ UINT8 RegHptc;
+
+ if (HpetBase == NULL) {
+ DEBUG((DEBUG_ERROR, "PchHpetBaseGet Error. Invalid pointer.\n"));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = PchP2sbCfgGet8 (R_PCH_P2SB_HPTC, &RegHptc);
+
+ switch (RegHptc & B_PCH_P2SB_HPTC_AS) {
+ case 0:
+ *HpetBase = V_PCH_HPET_BASE0;
+ break;
+ case 1:
+ *HpetBase = V_PCH_HPET_BASE1;
+ break;
+ case 2:
+ *HpetBase = V_PCH_HPET_BASE2;
+ break;
+ case 3:
+ *HpetBase = V_PCH_HPET_BASE3;
+ break;
+ default:
+ break;
+ }
+
+ return EFI_SUCCESS;
+}
+
diff --git a/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchCycleDecodingLib/PeiDxeSmmPchCycleDecodingLib.inf b/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchCycleDecodingLib/PeiDxeSmmPchCycleDecodingLib.inf
new file mode 100644
index 0000000000..c0cf90854f
--- /dev/null
+++ b/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchCycleDecodingLib/PeiDxeSmmPchCycleDecodingLib.inf
@@ -0,0 +1,40 @@
+### @file
+#
+# Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which 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.
+#
+###
+
+[Defines]
+ INF_VERSION = 0x00010017
+ BASE_NAME = PeiDxeSmmPchCycleDecodingLib
+ FILE_GUID = 676C749F-9CD1-46B7-BAFD-4B1BC36B4C8E
+ VERSION_STRING = 1.0
+ MODULE_TYPE = BASE
+ LIBRARY_CLASS = PchCycleDecodingLib
+
+
+[LibraryClasses]
+ BaseLib
+ IoLib
+ DebugLib
+ MmPciLib
+ PchInfoLib
+ PchPcrLib
+ PchP2sbLib
+
+[Packages]
+ MdePkg/MdePkg.dec
+ LewisburgPkg/PchRcPkg.dec #SERVER_BIOS
+ PurleyRcPkg/RcPkg.dec #SERVER_BIOS
+
+
+[Sources]
+ PchCycleDecodingLib.c
diff --git a/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchGbeLib/PchGbeLib.c b/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchGbeLib/PchGbeLib.c
new file mode 100644
index 0000000000..9d3304a1aa
--- /dev/null
+++ b/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchGbeLib/PchGbeLib.c
@@ -0,0 +1,166 @@
+/** @file
+
+Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+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.
+
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/MmPciBaseLib.h>
+#include <Library/PchPmcLib.h>
+#include <PchAccess.h>
+#include <Library/PchInfoLib.h>
+#include <Library/PchPcrLib.h>
+#include <Library/PchCycleDecodingLib.h>
+
+#include <PiPei.h>
+#include <Ppi/Spi.h>
+#include <Library/PeiServicesLib.h>
+extern EFI_GUID gPeiSpiPpiGuid;
+/**
+ Check whether GbE region is valid
+ Check SPI region directly since GbE might be disabled in SW.
+
+ @retval TRUE Gbe Region is valid
+ @retval FALSE Gbe Region is invalid
+**/
+BOOLEAN
+PchIsGbeRegionValid (
+ VOID
+ )
+{
+ UINT32 SpiBar;
+ SpiBar = MmioRead32 (MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_SPI,
+ PCI_FUNCTION_NUMBER_PCH_SPI)
+ + R_PCH_SPI_BAR0) & ~B_PCH_SPI_BAR0_MASK;
+ ASSERT (SpiBar != 0);
+ if (MmioRead32 (SpiBar + R_PCH_SPI_FREG3_GBE) != B_PCH_SPI_FREGX_BASE_MASK) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ Returns GbE over PCIe port number based on a soft strap.
+
+ @return Root port number (1-based)
+ @retval 0 GbE over PCIe disabled
+**/
+UINT32
+PchGetGbePortNumber (
+ VOID
+ )
+{
+ UINT32 GbePortSel;
+ UINT32 PcieStrapFuse;
+
+ PchPcrRead32 (PID_FIAWM26, R_PCH_PCR_FIA_STRPFUSECFG1_REG_BASE, &PcieStrapFuse);
+ if ((PcieStrapFuse & B_PCH_PCR_FIA_STRPFUSECFG1_GBE_PCIE_PEN) == 0) {
+ return 0; // GbE disabled
+ }
+ GbePortSel = (PcieStrapFuse & B_PCH_PCR_FIA_STRPFUSECFG1_GBE_PCIEPORTSEL) >> N_PCH_PCR_FIA_STRPFUSECFG1_GBE_PCIEPORTSEL;
+
+ switch (GbePortSel) {
+ case 0: return 3 + 1;
+ case 1: return 4 + 1;
+ case 2: return 5 + 1;
+ case 3: return 8 + 1;
+ case 4: return 11 + 1;
+ }
+
+ DEBUG((DEBUG_ERROR, "Invalid GbE port\n"));
+ ASSERT (FALSE);
+ return 0;
+}
+
+/**
+ Check whether LAN controller is enabled in the platform.
+
+ @retval TRUE GbE is enabled
+ @retval FALSE GbE is disabled
+**/
+BOOLEAN
+PchIsGbePresent (
+ VOID
+ )
+{
+
+ UINT32 SoftstrapVal;
+ EFI_SPI_PROTOCOL *SpiProtocol = NULL;
+ EFI_STATUS Status;
+ UINTN GbePciBase;
+
+ if (PchIsDwrFlow() == TRUE) {
+ return FALSE;
+ }
+
+ GbePciBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LAN,
+ PCI_FUNCTION_NUMBER_PCH_LAN
+ );
+
+ //
+ // Check GBE disable strap
+ //
+ Status = PeiServicesLocatePpi (
+ &gPeiSpiPpiGuid,
+ 0,
+ NULL,
+ (VOID **) &SpiProtocol
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = SpiProtocol->ReadPchSoftStrap(SpiProtocol, 0x1DC, 4, &SoftstrapVal);
+ if (!EFI_ERROR(Status)) {
+ if ((SoftstrapVal & BIT14) == BIT14) {
+ return FALSE;
+ }
+ }
+ //
+ // Check FIA strap/fuse
+ //
+ if (PchGetGbePortNumber () == 0) {
+ return FALSE;
+ }
+ //
+ // Check GbE NVM
+ //
+ if (PchIsGbeRegionValid () == FALSE) {
+ return FALSE;
+ }
+ if (MmioRead32 (GbePciBase) == 0xFFFFFFFF) {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**
+ Check whether LAN controller is enabled in the platform.
+
+ @deprecated Use PchIsGbePresent instead.
+
+ @retval TRUE GbE is enabled
+ @retval FALSE GbE is disabled
+**/
+BOOLEAN
+PchIsGbeAvailable (
+ VOID
+ )
+{
+ return PchIsGbePresent ();
+}
+
+
diff --git a/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchGbeLib/PeiDxeSmmPchGbeLib.inf b/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchGbeLib/PeiDxeSmmPchGbeLib.inf
new file mode 100644
index 0000000000..59388180f1
--- /dev/null
+++ b/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchGbeLib/PeiDxeSmmPchGbeLib.inf
@@ -0,0 +1,44 @@
+### @file
+#
+# Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which 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.
+#
+###
+
+[Defines]
+ INF_VERSION = 0x00010017
+ BASE_NAME = PeiDxeSmmPchGbeLib
+ FILE_GUID = FC022ED0-6EB3-43E1-A740-0BA27CBBD010
+ VERSION_STRING = 1.0
+ MODULE_TYPE = BASE
+ LIBRARY_CLASS = PchGbeLib
+
+
+[LibraryClasses]
+ BaseLib
+ IoLib
+ DebugLib
+ MmPciLib
+ PchInfoLib
+ PchPcrLib
+ PchCycleDecodingLib
+ PchPmcLib #SERVER_BIOS
+
+[Packages]
+ MdePkg/MdePkg.dec
+ LewisburgPkg/PchRcPkg.dec #SERVER_BIOS
+ PurleyRcPkg/RcPkg.dec #SERVER_BIOS
+
+[Sources]
+ PchGbeLib.c
+
+[Ppis]
+ gPeiSpiPpiGuid
+
diff --git a/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchInfoLib/PchInfoLib.c b/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchInfoLib/PchInfoLib.c
new file mode 100644
index 0000000000..31966dd609
--- /dev/null
+++ b/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchInfoLib/PchInfoLib.c
@@ -0,0 +1,511 @@
+/** @file
+
+Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+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.
+
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/MmPciBaseLib.h>
+#include <Library/PchInfoLib.h>
+#include <PchAccess.h>
+
+#define PCH_DO_STRINGIFY(x) #x
+#define PCH_STRINGIFY(x) PCH_DO_STRINGIFY(x)
+
+//
+// This module variables are used for cache the static result.
+// @note: please pay attention to the PEI phase, the module variables on ROM
+// and can't be modified.
+//
+GLOBAL_REMOVE_IF_UNREFERENCED UINTN mLpcBaseAddr = 0;
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_STEPPING mPchStepping = PchSteppingMax;
+GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mIsPchSupported = 0xFF;
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_SERIES mPchSeries = PchUnknownSeries;
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_GENERATION mPchGeneration = PchUnknownGeneration;
+
+/**
+ Return Pch stepping type
+
+ @retval PCH_STEPPING Pch stepping type
+**/
+PCH_STEPPING
+EFIAPI
+PchStepping (
+ VOID
+ )
+{
+ UINT8 RevId;
+ UINT16 LpcDeviceId;
+ UINTN LpcBaseAddress;
+
+ if (mPchStepping != PchSteppingMax) {
+ return mPchStepping;
+ }
+
+ LpcBaseAddress = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC
+ );
+ RevId = MmioRead8 (LpcBaseAddress + PCI_REVISION_ID_OFFSET);
+
+ LpcDeviceId = MmioRead16 (LpcBaseAddress + PCI_DEVICE_ID_OFFSET);
+
+ if (IS_PCH_H_LPC_DEVICE_ID (LpcDeviceId)) {
+ switch (RevId) {
+ case V_PCH_LPC_RID_0:
+ mPchStepping = PchHA0;
+ return PchHA0;
+
+ case V_PCH_LPC_RID_10:
+ mPchStepping = PchHB0;
+ return PchHB0;
+
+ case V_PCH_LPC_RID_20:
+ mPchStepping = PchHC0;
+ return PchHC0;
+
+ case V_PCH_LPC_RID_30:
+ mPchStepping = PchHD0;
+ return PchHD0;
+
+ case V_PCH_LPC_RID_31:
+ mPchStepping = PchHD1;
+ return PchHD1;
+
+ default:
+ DEBUG ((DEBUG_ERROR, "Unsupported PCH Stepping. Supporting PCH stepping starting from %a and above\n", PCH_STRINGIFY(PCH_H_MIN_SUPPORTED_STEPPING))) ;
+ return PchSteppingMax;
+ }
+ }
+
+ if (IS_PCH_LP_LPC_DEVICE_ID (LpcDeviceId)) {
+ switch (RevId) {
+#ifdef SIMICS_FLAG
+ case V_PCH_LPC_RID_0:
+ mPchStepping = PchLpA0;
+ return PchLpA0;
+#endif
+
+ case V_PCH_LPC_RID_10:
+ mPchStepping = PchLpB0;
+ return PchLpB0;
+
+ case V_PCH_LPC_RID_11:
+ mPchStepping = PchLpB1;
+ return PchLpB1;
+
+ case V_PCH_LPC_RID_20:
+ mPchStepping = PchLpC0;
+ return PchLpC0;
+
+ case V_PCH_LPC_RID_21:
+ mPchStepping = PchLpC1;
+ return PchLpC1;
+
+ default:
+ DEBUG ((DEBUG_ERROR, "Unsupported PCH Stepping. Supporting PCH stepping starting from %a and above\n", PCH_STRINGIFY(PCH_LP_MIN_SUPPORTED_STEPPING))) ;
+ return PchSteppingMax;
+ }
+ }
+
+#ifdef SKXD_EN
+ if (IS_PCH_LBG_D_SSKU_LPC_DEVICE_ID (LpcDeviceId)) {
+ switch (RevId) {
+ case V_PCH_LBG_LPC_RID_3:
+ return LbgB1_D;
+ default:
+ DEBUG ((DEBUG_ERROR, "Unsupported PCH Stepping. Supporting PCH stepping starting from %s and above\n", PCH_STRINGIFY(V_PCH_LBG_LPC_RID_3)));
+ return PchSteppingMax;
+ }
+ }
+#endif // SKXD_EN
+
+ if (IS_PCH_LBG_LPC_DEVICE_ID (LpcDeviceId)) {
+ if (RevId == 0) {
+ return LbgA0;
+ } else {
+ switch (RevId) {
+ case V_PCH_LBG_LPC_RID_0:
+ return LbgA0;
+ case V_PCH_LBG_LPC_RID_2:
+ return LbgB0;
+ case V_PCH_LBG_LPC_RID_3:
+ return LbgB1;
+ case V_PCH_LBG_LPC_RID_4:
+ return LbgB2;
+ case V_PCH_LBG_LPC_RID_8:
+ return LbgS0;
+ case V_PCH_LBG_LPC_RID_9:
+ return LbgS1;
+ default:
+ DEBUG ((DEBUG_ERROR, "Unsupported PCH Stepping. Supporting PCH stepping starting from %s and above\n", PCH_STRINGIFY(PCH_LBG_MIN_SUPPORTED_STEPPING)));
+ ASSERT (FALSE);
+ return PchSteppingMax;
+ }
+ }
+ }
+ return PchSteppingMax;
+}
+
+/**
+ Determine if PCH is supported
+
+ @retval TRUE PCH is supported
+ @retval FALSE PCH is not supported
+**/
+BOOLEAN
+IsPchSupported (
+ VOID
+ )
+{
+ UINT16 LpcDeviceId;
+ UINT16 LpcVendorId;
+ UINTN LpcBaseAddress;
+
+ if (mIsPchSupported != 0xFF) {
+ return (BOOLEAN) mIsPchSupported;
+ }
+
+ LpcBaseAddress = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC
+ );
+
+ LpcDeviceId = MmioRead16 (LpcBaseAddress + PCI_DEVICE_ID_OFFSET);
+ LpcVendorId = MmioRead16 (LpcBaseAddress + PCI_VENDOR_ID_OFFSET);
+
+ ///
+ /// Verify that this is a supported chipset
+ ///
+ if ((LpcVendorId == V_PCH_LPC_VENDOR_ID) &&
+ (IS_PCH_LBG_LPC_DEVICE_ID (LpcDeviceId)))
+ {
+ mIsPchSupported = TRUE;
+ return TRUE;
+ } else {
+ DEBUG ((DEBUG_ERROR, "PCH code doesn't support the LpcDeviceId: 0x%04x!\n", LpcDeviceId));
+ mIsPchSupported = FALSE;
+ return FALSE;
+ }
+}
+
+/**
+ Return Pch Series
+
+ @retval PCH_SERIES Pch Series
+**/
+PCH_SERIES
+EFIAPI
+GetPchSeries (
+ VOID
+ )
+{
+ UINT16 LpcDeviceId;
+ UINT32 PchSeries;
+ UINTN LpcBaseAddress;
+
+ if (mPchSeries != PchUnknownSeries) {
+ return mPchSeries;
+ }
+
+ LpcBaseAddress = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC
+ );
+
+ LpcDeviceId = MmioRead16 (LpcBaseAddress + PCI_DEVICE_ID_OFFSET);
+
+ if (IS_PCH_LBG_LPC_DEVICE_ID (LpcDeviceId)) {
+ PchSeries = PchH;
+ } else if (IS_PCH_LP_LPC_DEVICE_ID (LpcDeviceId)) {
+ PchSeries = PchLp;
+ } else {
+ PchSeries = PchUnknownSeries;
+ DEBUG ((DEBUG_ERROR, "Unsupported PCH SKU, LpcDeviceId: 0x%04x!\n", LpcDeviceId));
+ ASSERT (FALSE);
+ }
+ mPchSeries = PchSeries;
+
+ return PchSeries;
+}
+
+/**
+ Return Pch Generation
+
+ @retval PCH_GENERATION Pch Generation
+**/
+PCH_GENERATION
+EFIAPI
+GetPchGeneration (
+ VOID
+ )
+{
+ UINT16 LpcDeviceId;
+ UINT32 PchGen;
+ UINTN LpcBaseAddress;
+
+ if (mPchGeneration != PchUnknownGeneration) {
+ return mPchGeneration;
+ }
+
+ LpcBaseAddress = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC
+ );
+ LpcDeviceId = MmioRead16 (LpcBaseAddress + PCI_DEVICE_ID_OFFSET);
+
+ if (IS_PCH_LBG_LPC_DEVICE_ID (LpcDeviceId)) {
+ PchGen = SklPch;
+ } else {
+ PchGen = PchUnknownGeneration;
+ DEBUG ((DEBUG_ERROR, "Unsupported PCH SKU, LpcDeviceId: 0x%04x!\n", LpcDeviceId));
+ ASSERT (FALSE);
+ }
+ mPchGeneration = PchGen;
+
+ return PchGen;
+}
+
+/**
+ Get Pch Maximum Pcie Root Port Number
+
+ @retval Pch Maximum Pcie Root Port Number
+**/
+UINT8
+EFIAPI
+GetPchMaxPciePortNum (
+ VOID
+ )
+{
+ PCH_SERIES PchSeries;
+
+ PchSeries = GetPchSeries ();
+ switch (PchSeries) {
+ case PchLp:
+ return PCH_LP_PCIE_MAX_ROOT_PORTS;
+
+ case PchH:
+ return PCH_H_PCIE_MAX_ROOT_PORTS;
+
+ default:
+ return 0;
+ }
+}
+
+
+/**
+ Get Pch Maximum Sata Port Number
+
+ @retval Pch Maximum Sata Port Number
+**/
+UINT8
+EFIAPI
+GetPchMaxSataPortNum (
+ VOID
+ )
+{
+ PCH_SERIES PchSeries;
+
+ PchSeries = GetPchSeries ();
+ switch (PchSeries) {
+ case PchLp:
+ return PCH_LP_AHCI_MAX_PORTS;
+
+ case PchH:
+ return PCH_H_AHCI_MAX_PORTS;
+
+ default:
+ return 0;
+ }
+}
+
+/**
+ Get Pch Usb Maximum Physical Port Number
+
+ @retval Pch Usb Maximum Physical Port Number
+**/
+UINT8
+EFIAPI
+GetPchUsbMaxPhysicalPortNum (
+ VOID
+ )
+{
+ PCH_SERIES PchSeries;
+
+ PchSeries = GetPchSeries ();
+ switch (PchSeries) {
+ case PchLp:
+ return PCH_LP_XHCI_MAX_USB2_PHYSICAL_PORTS;
+
+ case PchH:
+ return PCH_H_XHCI_MAX_USB2_PHYSICAL_PORTS;
+
+ default:
+ return 0;
+ }
+}
+
+/**
+ Get Pch Maximum Usb2 Port Number of XHCI Controller
+
+ @retval Pch Maximum Usb2 Port Number of XHCI Controller
+**/
+UINT8
+EFIAPI
+GetPchXhciMaxUsb2PortNum (
+ VOID
+ )
+{
+ PCH_SERIES PchSeries;
+
+ PchSeries = GetPchSeries ();
+ switch (PchSeries) {
+ case PchLp:
+ return PCH_LP_XHCI_MAX_USB2_PORTS;
+
+ case PchH:
+ return PCH_H_XHCI_MAX_USB2_PORTS;
+
+ default:
+ return 0;
+ }
+}
+
+/**
+ Get Pch Maximum Usb3 Port Number of XHCI Controller
+
+ @retval Pch Maximum Usb3 Port Number of XHCI Controller
+**/
+UINT8
+EFIAPI
+GetPchXhciMaxUsb3PortNum (
+ VOID
+ )
+{
+ PCH_SERIES PchSeries;
+
+ PchSeries = GetPchSeries ();
+ switch (PchSeries) {
+ case PchLp:
+ return PCH_LP_XHCI_MAX_USB3_PORTS;
+
+ case PchH:
+ return PCH_H_XHCI_MAX_USB3_PORTS;
+
+ default:
+ return 0;
+ }
+}
+
+/**
+ Determine if sSata controller is present or not
+
+ @param[in] None
+
+ @retval TRUE or FALSE
+**/
+BOOLEAN
+EFIAPI
+GetIsPchsSataPresent (
+ VOID
+ )
+{
+ UINT16 sSataDeviceId;
+ UINTN sSataBaseAddress;
+
+ sSataBaseAddress = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_EVA,
+ PCI_FUNCTION_NUMBER_PCH_SSATA
+ );
+
+ sSataDeviceId = MmioRead16 ( sSataBaseAddress + PCI_DEVICE_ID_OFFSET);
+
+ if (sSataDeviceId != 0xffff){
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+/**
+ Get Pch Maximum sSata Controller Number
+
+ @param[in] None
+
+ @retval Pch Maximum sSata Controller Number
+**/
+
+UINT8
+EFIAPI
+GetPchMaxsSataPortNum (
+ VOID
+ )
+{
+ return PCH_SSATA_MAX_PORTS;
+}
+
+/**
+
+ Get Pch Maximum Sata Controller Number
+
+ @param[in] None
+
+ @retval Pch Maximum Sata Controller Number
+
+**/
+UINT8
+EFIAPI
+GetPchMaxsSataControllerNum (
+ VOID
+ )
+{
+ return PCH_SSATA_MAX_CONTROLLERS;
+}
+
+/**
+ Return Pch Lpc Device Id
+
+ @retval UINT16 Pch DeviceId
+**/
+UINT16
+EFIAPI
+GetPchLpcDeviceId (
+ VOID
+ )
+{
+ UINTN LpcBaseAddress;
+
+ if (mPchSeries != PchUnknownSeries) {
+ return mPchSeries;
+ }
+
+ LpcBaseAddress = mLpcBaseAddr;
+ if (LpcBaseAddress == 0) {
+ LpcBaseAddress = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC
+ );
+ mLpcBaseAddr = LpcBaseAddress;
+ }
+
+ return MmioRead16 (LpcBaseAddress + PCI_DEVICE_ID_OFFSET);
+}
+
diff --git a/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchInfoLib/PchInfoStrLib.c b/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchInfoLib/PchInfoStrLib.c
new file mode 100644
index 0000000000..641277c083
--- /dev/null
+++ b/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchInfoLib/PchInfoStrLib.c
@@ -0,0 +1,297 @@
+/** @file
+
+Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+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.
+
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/MmPciBaseLib.h>
+#include <Library/PchInfoLib.h>
+#include <PchAccess.h>
+
+/**
+ Structure for PCH stepping string mapping
+**/
+struct PCH_STEPPING_STRING {
+ PCH_STEPPING Stepping;
+ CHAR8 *String;
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+struct PCH_STEPPING_STRING mSteppingStrs[] = {
+ {PchHA0, "A0"},
+ {PchHB0, "B0"},
+ {PchHC0, "C0"},
+ {PchHD0, "D0"},
+ {PchHD1, "D1"},
+#ifdef SIMICS_FLAG
+ {PchLpA0, "A0"},
+#endif
+ {PchLpB0, "B0"},
+ {PchLpB1, "B1"},
+ {PchLpC0, "C0"},
+ {PchLpC1, "C1"},
+ {LbgA0, "A0"},
+ {LbgB0, "B0"},
+ {LbgB1, "B1"},
+ {LbgB2, "B2"},
+ {LbgS0, "S0"},
+ {LbgS1, "S1"},
+ {PchSteppingMax, NULL}
+};
+
+/**
+ Structure for PCH series string mapping
+**/
+struct PCH_SERIES_STRING {
+ PCH_SERIES Series;
+ CHAR8 *String;
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+struct PCH_SERIES_STRING mSeriesStrs[] = {
+ {PchH, "SKL PCH-H"},
+ {PchLp, "SKL PCH-LP"},
+ {PchUnknownSeries, NULL}
+};
+
+/**
+ Structure for PCH sku string mapping
+**/
+struct PCH_SKU_STRING {
+ UINT16 Id;
+ CHAR8 *String;
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+struct PCH_SKU_STRING mSkuStrs[] = {
+ //
+ // SKL PCH H Desktop LPC Device IDs
+ //
+ {V_PCH_H_LPC_DEVICE_ID_DT_SUPER_SKU, "Super SKU"},
+ {V_PCH_H_LPC_DEVICE_ID_DT_0, "Super SKU (locked)"},
+ {V_PCH_H_LPC_DEVICE_ID_DT_1, "H110"},
+ {V_PCH_H_LPC_DEVICE_ID_DT_2, "H170"},
+ {V_PCH_H_LPC_DEVICE_ID_DT_3, "Z170"},
+ {V_PCH_H_LPC_DEVICE_ID_DT_4, "Q170"},
+ {V_PCH_H_LPC_DEVICE_ID_DT_5, "Q150"},
+ {V_PCH_H_LPC_DEVICE_ID_DT_6, "B150"},
+ {V_PCH_H_LPC_DEVICE_ID_UNFUSE, "Unfused SKU"},
+ //
+ // SKL PCH H Server/WS LPC Device IDs
+ //
+ {V_PCH_H_LPC_DEVICE_ID_SVR_0, "C236"},
+ {V_PCH_H_LPC_DEVICE_ID_SVR_1, "C232"},
+ {V_PCH_H_LPC_DEVICE_ID_SVR_2, "CM236"},
+ {V_PCH_H_LPC_DEVICE_ID_A14B, "Super SKU (Unlocked)"},
+ {V_PCH_LBG_LPC_DEVICE_ID_UNFUSED, "LBG Unfused SKU"},
+ {V_PCH_LBG_LPC_DEVICE_ID_SS_0, "LBG SuperSKU - 0"},
+ {V_PCH_LBG_LPC_DEVICE_ID_SS_4_SD, "LBG SuperSKU - 4/SD"},
+ {V_PCH_LBG_LPC_DEVICE_ID_SS_T80_NS, "LBG SuperSKU - T80/SD"},
+ {V_PCH_LBG_LPC_DEVICE_ID_SS_1G, "LBG SuperSKU - 1G"},
+ {V_PCH_LBG_LPC_DEVICE_ID_SS_T, "LBG SuperSKU - T"},
+ {V_PCH_LBG_LPC_DEVICE_ID_SS_L, "LBG SuperSKU - L"},
+ {V_PCH_LBG_PROD_LPC_DEVICE_ID_0, "LBG QS/PRQ - 0"},
+ {V_PCH_LBG_PROD_LPC_DEVICE_ID_1G, "LBG QS/PRQ - 1G"},
+ {V_PCH_LBG_PROD_LPC_DEVICE_ID_2, "LBG QS/PRQ - 2"},
+ {V_PCH_LBG_PROD_LPC_DEVICE_ID_4, "LBG QS/PRQ - 4"},
+ {V_PCH_LBG_PROD_LPC_DEVICE_ID_E, "LBG QS/PRQ - E"},
+ {V_PCH_LBG_PROD_LPC_DEVICE_ID_M, "LBG QS/PRQ - M"},
+ {V_PCH_LBG_PROD_LPC_DEVICE_ID_T, "LBG QS/PRQ - T"},
+ {V_PCH_LBG_PROD_LPC_DEVICE_ID_LP, "LBG QS/PRQ - LP"},
+ //
+ // SKL PCH H Mobile LPC Device IDs
+ //
+ {V_PCH_H_LPC_DEVICE_ID_MB_0, "QM170"},
+ {V_PCH_H_LPC_DEVICE_ID_MB_1, "HM170"},
+ {V_PCH_H_LPC_DEVICE_ID_MB_2, "QMS170"},
+ {V_PCH_H_LPC_DEVICE_ID_MB_SUPER_SKU, "Super SKU"},
+ //
+ // SKL PCH LP Mobile LPC Device IDs
+ //
+ {V_PCH_LP_LPC_DEVICE_ID_UNFUSE, "Unfused SKU"},
+ {V_PCH_LP_LPC_DEVICE_ID_MB_SUPER_SKU, "Super SKU"},
+ {V_PCH_LP_LPC_DEVICE_ID_MB_0, "Super SKU (locked)"},
+ {V_PCH_LP_LPC_DEVICE_ID_MB_1, "(U) Base SKU"},
+ {V_PCH_LP_LPC_DEVICE_ID_MB_2, "(Y) Premium SKU"},
+ {V_PCH_LP_LPC_DEVICE_ID_MB_3, "(U) Premium SKU"},
+ {0xFFFF, NULL}
+};
+
+/**
+ Get PCH stepping ASCII string
+ The return string is zero terminated.
+
+ @param [in] PchStep Pch stepping
+ @param [out] Buffer Output buffer of string
+ @param [in,out] BufferSize Size of input buffer,
+ and return required string size when buffer is too small.
+
+ @retval EFI_SUCCESS String copy successfully
+ @retval EFI_INVALID_PARAMETER The stepping is not supported, or parameters are NULL
+ @retval EFI_BUFFER_TOO_SMALL Input buffer size is too small
+**/
+EFI_STATUS
+PchGetSteppingStr (
+ IN PCH_STEPPING PchStep,
+ OUT CHAR8 *Buffer,
+ IN OUT UINT32 *BufferSize
+ )
+{
+ UINTN Index;
+ UINT32 StrLength;
+ CHAR8 *Str;
+ EFI_STATUS Status;
+
+ if ((Buffer == NULL) || (BufferSize == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (*BufferSize > 0) {
+ Buffer[0] = 0;
+ }
+
+ Str = NULL;
+ StrLength = 0;
+ for (Index = 0; mSteppingStrs[Index].Stepping != PchSteppingMax; Index++) {
+ if (PchStep == mSteppingStrs[Index].Stepping) {
+ StrLength = (UINT32) AsciiStrLen (mSteppingStrs[Index].String);
+ Str = mSteppingStrs[Index].String;
+ break;
+ }
+ }
+ if (StrLength == 0) {
+ // Unsupported Stepping
+ // ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+ if (*BufferSize <= StrLength) {
+ *BufferSize = StrLength + 1;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+ Status = AsciiStrCpyS (Buffer, *BufferSize, Str);
+ ASSERT_EFI_ERROR(Status);
+ return Status;
+}
+
+/**
+ Get PCH series ASCII string
+ The return string is zero terminated.
+
+ @param [in] PchSeries Pch series
+ @param [out] Buffer Output buffer of string
+ @param [in,out] BufferSize Size of input buffer,
+ and return required string size when buffer is too small.
+
+ @retval EFI_SUCCESS String copy successfully
+ @retval EFI_INVALID_PARAMETER The series is not supported, or parameters are NULL
+ @retval EFI_BUFFER_TOO_SMALL Input buffer size is too small
+**/
+EFI_STATUS
+PchGetSeriesStr (
+ IN PCH_SERIES PchSeries,
+ OUT CHAR8 *Buffer,
+ IN OUT UINT32 *BufferSize
+ )
+{
+ UINTN Index;
+ UINT32 StrLength;
+ CHAR8 *Str;
+ EFI_STATUS Status;
+
+ if ((Buffer == NULL) || (BufferSize == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (*BufferSize > 0) {
+ Buffer[0] = 0;
+ }
+
+ Str = NULL;
+ StrLength = 0;
+ for (Index = 0; mSeriesStrs[Index].Series != PchUnknownSeries; Index++) {
+ if (PchSeries == mSeriesStrs[Index].Series) {
+ StrLength = (UINT32) AsciiStrLen (mSeriesStrs[Index].String);
+ Str = mSeriesStrs[Index].String;
+ break;
+ }
+ }
+ if (StrLength == 0) {
+ // Unsupported Series
+ // ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+ if (*BufferSize <= StrLength) {
+ *BufferSize = StrLength + 1;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+ Status = AsciiStrCpyS (Buffer, *BufferSize, Str);
+ ASSERT_EFI_ERROR(Status);
+ return Status;
+}
+
+/**
+ Get PCH Sku ASCII string
+ The return string is zero terminated.
+
+ @param [in] LpcDid LPC device id
+ @param [out] Buffer Output buffer of string
+ @param [in,out] BufferSize Size of input buffer,
+ and return required string size when buffer is too small.
+
+ @retval EFI_SUCCESS String copy successfully
+ @retval EFI_INVALID_PARAMETER The series is not supported, or parameters are NULL
+ @retval EFI_BUFFER_TOO_SMALL Input buffer size is too small
+**/
+EFI_STATUS
+PchGetSkuStr (
+ IN UINT16 LpcDid,
+ OUT CHAR8 *Buffer,
+ IN OUT UINT32 *BufferSize
+ )
+{
+ UINTN Index;
+ UINT32 StrLength;
+ CHAR8 *Str;
+ EFI_STATUS Status;
+
+ if ((Buffer == NULL) || (BufferSize == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (*BufferSize > 0) {
+ Buffer[0] = 0;
+ }
+
+ Str = NULL;
+ StrLength = 0;
+ for (Index = 0; mSkuStrs[Index].Id != 0xFFFF; Index++) {
+ if (LpcDid == mSkuStrs[Index].Id) {
+ StrLength = (UINT32) AsciiStrLen (mSkuStrs[Index].String);
+ Str = mSkuStrs[Index].String;
+ }
+ }
+ if (StrLength == 0) {
+ // Unsupported Sku
+ // ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+ if (*BufferSize <= StrLength) {
+ *BufferSize = StrLength + 1;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+ Status = AsciiStrCpyS (Buffer, *BufferSize, Str);
+ ASSERT_EFI_ERROR(Status);
+ return Status;
+}
diff --git a/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchInfoLib/PeiDxeSmmPchInfoLib.inf b/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchInfoLib/PeiDxeSmmPchInfoLib.inf
new file mode 100644
index 0000000000..2b3fdeb495
--- /dev/null
+++ b/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchInfoLib/PeiDxeSmmPchInfoLib.inf
@@ -0,0 +1,39 @@
+### @file
+#
+# Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which 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.
+#
+###
+
+[Defines]
+ INF_VERSION = 0x00010017
+ BASE_NAME = PeiDxeSmmPchInfoLib
+ FILE_GUID = D43F3086-1D7E-4FF5-AE6A-3B0E15B11329
+ VERSION_STRING = 1.0
+ MODULE_TYPE = BASE
+ LIBRARY_CLASS = PchInfoLib
+
+
+[LibraryClasses]
+ BaseLib
+ IoLib
+ DebugLib
+ MmPciLib
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ LewisburgPkg/PchRcPkg.dec #SERVER_BIOS
+ PurleyRcPkg/RcPkg.dec #SERVER_BIOS
+
+
+[Sources]
+ PchInfoLib.c
+ PchInfoStrLib.c
diff --git a/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchP2sbLib/PchP2sbLib.c b/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchP2sbLib/PchP2sbLib.c
new file mode 100644
index 0000000000..6e91828d64
--- /dev/null
+++ b/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchP2sbLib/PchP2sbLib.c
@@ -0,0 +1,337 @@
+/** @file
+
+Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+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.
+
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/MmPciBaseLib.h>
+#include <PchAccess.h>
+
+/**
+ Get P2SB pci configuration register. (This is internal function)
+ It returns register at Offset of P2SB controller and size in 1byte/2bytes/4bytes.
+ The Offset should not exceed 255 and must be aligned with size.
+ This function will be unavailable after P2SB is hidden by PSF.
+
+ @param[in] Offset Register offset of P2SB controller.
+ @param[in] Size Size for read. Must be 1 or 2 or 4.
+ @param[out] OutData Buffer of Output Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+STATIC
+EFI_STATUS
+PchP2sbCfgGet (
+ IN UINTN Offset,
+ IN UINTN Size,
+ OUT UINT32 *OutData
+ )
+{
+ UINTN P2sbBase;
+ BOOLEAN DevicePresent;
+
+ if ((Offset > 255) ||
+ ((Offset & (Size - 1)) != 0))
+ {
+ DEBUG ((DEBUG_ERROR, "PchP2sbCfgGet error. Invalid Offset: %x Size: %x", Offset, Size));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ P2sbBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_P2SB,
+ PCI_FUNCTION_NUMBER_PCH_P2SB
+ );
+ DevicePresent = (MmioRead16 (P2sbBase + PCI_VENDOR_ID_OFFSET) != 0xFFFF);
+ if (!DevicePresent) {
+ MmioWrite8 (P2sbBase + R_PCH_P2SB_E0 + 1, 0);
+ }
+ ASSERT (MmioRead16 (P2sbBase + PCI_VENDOR_ID_OFFSET) != 0xFFFF);
+
+ switch (Size) {
+ case 4:
+ *(UINT32*)OutData = MmioRead32 (P2sbBase + Offset);
+ break;
+ case 2:
+ *(UINT16*)OutData = MmioRead16 (P2sbBase + Offset);
+ break;
+ case 1:
+ *(UINT8*) OutData = MmioRead8 (P2sbBase + Offset);
+ break;
+ default:
+ break;
+ }
+
+ if (!DevicePresent) {
+ MmioWrite8 (P2sbBase + R_PCH_P2SB_E0 + 1, BIT0);
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Get P2SB pci configuration register.
+ It returns register at Offset of P2SB controller and size in 4bytes.
+ The Offset should not exceed 255 and must be aligned with size.
+ This function will be unavailable after P2SB is hidden by PSF.
+
+ @param[in] Offset Register offset of P2SB controller.
+ @param[out] OutData Buffer of Output Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchP2sbCfgGet32 (
+ IN UINTN Offset,
+ OUT UINT32 *OutData
+ )
+{
+ return PchP2sbCfgGet (Offset, 4, (UINT32*) OutData);
+}
+
+/**
+ Get P2SB pci configuration register.
+ It returns register at Offset of P2SB controller and size in 2bytes.
+ The Offset should not exceed 255 and must be aligned with size.
+ This function will be unavailable after P2SB is hidden by PSF.
+
+ @param[in] Offset Register offset of P2SB controller.
+ @param[out] OutData Buffer of Output Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchP2sbCfgGet16 (
+ IN UINTN Offset,
+ OUT UINT16 *OutData
+ )
+{
+ return PchP2sbCfgGet (Offset, 2, (UINT32*) OutData);
+}
+
+/**
+ Get P2SB pci configuration register.
+ It returns register at Offset of P2SB controller and size in 1byte.
+ The Offset should not exceed 255 and must be aligned with size.
+ This function will be unavailable after P2SB is hidden by PSF.
+
+ @param[in] Offset Register offset of P2SB controller.
+ @param[out] OutData Buffer of Output Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchP2sbCfgGet8 (
+ IN UINTN Offset,
+ OUT UINT8 *OutData
+ )
+{
+ return PchP2sbCfgGet (Offset, 1, (UINT32*) OutData);
+}
+
+/**
+ Set P2SB pci configuration register. (This is internal function)
+ It programs register at Offset of P2SB controller and size in 1byte/2bytes/4bytes.
+ The Offset should not exceed 255 and must be aligned with size.
+ This function will be unavailable after P2SB is hidden by PSF.
+
+ @param[in] Offset Register offset of P2SB controller.
+ @param[in] Size Size for read. Must be 1 or 2 or 4.
+ @param[in] AndData AND Data. Must be the same size as Size parameter.
+ @param[in] OrData OR Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+STATIC
+EFI_STATUS
+PchP2sbCfgSet (
+ IN UINTN Offset,
+ IN UINTN Size,
+ IN UINT32 AndData,
+ IN UINT32 OrData
+ )
+{
+ UINTN P2sbBase;
+ BOOLEAN DevicePresent;
+ UINT32 Data32;
+
+ if ((Offset > 255) ||
+ ((Offset & (Size - 1)) != 0))
+ {
+ DEBUG ((DEBUG_ERROR, "PchP2sbCfgSet error. Invalid Offset: %x Size: %x", Offset, Size));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Data32 = 0;
+
+ P2sbBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_P2SB,
+ PCI_FUNCTION_NUMBER_PCH_P2SB
+ );
+ DevicePresent = (MmioRead16 (P2sbBase + PCI_VENDOR_ID_OFFSET) != 0xFFFF);
+ if (!DevicePresent) {
+ MmioWrite8 (P2sbBase + R_PCH_P2SB_E0 + 1, 0);
+ }
+ ASSERT (MmioRead16 (P2sbBase + PCI_VENDOR_ID_OFFSET) != 0xFFFF);
+
+ switch (Size) {
+ case 4:
+ Data32 = MmioRead32 (P2sbBase + Offset);
+ Data32 &= AndData;
+ Data32 |= OrData;
+ MmioWrite32 (P2sbBase + Offset, (UINT32) Data32);
+ break;
+ case 2:
+ Data32 = MmioRead16 (P2sbBase + Offset);
+ Data32 &= AndData;
+ Data32 |= OrData;
+ MmioWrite16 (P2sbBase + Offset, (UINT16) Data32);
+ break;
+ case 1:
+ Data32 = MmioRead8 (P2sbBase + Offset);
+ Data32 &= AndData;
+ Data32 |= OrData;
+ MmioWrite8 (P2sbBase + Offset, (UINT8) Data32);
+ break;
+ default:
+ break;
+ }
+
+ if (!DevicePresent) {
+ MmioWrite8 (P2sbBase + R_PCH_P2SB_E0 + 1, BIT0);
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Set P2SB pci configuration register.
+ It programs register at Offset of P2SB controller and size in 4bytes.
+ The Offset should not exceed 255 and must be aligned with size.
+ This function will be unavailable after P2SB is hidden by PSF.
+
+ @param[in] Offset Register offset of P2SB controller.
+ @param[in] AndData AND Data. Must be the same size as Size parameter.
+ @param[in] OrData OR Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchP2sbCfgSet32 (
+ IN UINTN Offset,
+ IN UINT32 AndData,
+ IN UINT32 OrData
+ )
+{
+ return PchP2sbCfgSet (Offset, 4, AndData, OrData);
+}
+
+/**
+ Set P2SB pci configuration register.
+ It programs register at Offset of P2SB controller and size in 2bytes.
+ The Offset should not exceed 255 and must be aligned with size.
+ This function will be unavailable after P2SB is hidden by PSF.
+
+ @param[in] Offset Register offset of P2SB controller.
+ @param[in] AndData AND Data. Must be the same size as Size parameter.
+ @param[in] OrData OR Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchP2sbCfgSet16 (
+ IN UINTN Offset,
+ IN UINT16 AndData,
+ IN UINT16 OrData
+ )
+{
+ return PchP2sbCfgSet (Offset, 2, AndData, OrData);
+}
+
+/**
+ Set P2SB pci configuration register.
+ It programs register at Offset of P2SB controller and size in 1bytes.
+ The Offset should not exceed 255 and must be aligned with size.
+ This function will be unavailable after P2SB is hidden by PSF.
+
+ @param[in] Offset Register offset of P2SB controller.
+ @param[in] AndData AND Data. Must be the same size as Size parameter.
+ @param[in] OrData OR Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchP2sbCfgSet8 (
+ IN UINTN Offset,
+ IN UINT8 AndData,
+ IN UINT8 OrData
+ )
+{
+ return PchP2sbCfgSet (Offset, 1, AndData, OrData);
+}
+
+/**
+ Hide P2SB device.
+
+ @param[in] P2sbBase Pci base address of P2SB controller.
+
+ @retval EFI_SUCCESS Always return success.
+**/
+EFI_STATUS
+PchHideP2sb (
+ IN UINTN P2sbBase
+ )
+{
+ MmioWrite8 (P2sbBase + R_PCH_P2SB_E0 + 1, BIT0);
+ return EFI_SUCCESS;
+}
+
+/**
+ Reveal P2SB device.
+ Also return the original P2SB status which is for Hidding P2SB or not after.
+ If OrgStatus is not NULL, then TRUE means P2SB is unhidden,
+ and FALSE means P2SB is hidden originally.
+
+ @param[in] P2sbBase Pci base address of P2SB controller.
+ @param[out] OrgStatus Original P2SB hidding/unhidden status
+
+ @retval EFI_SUCCESS Always return success.
+**/
+EFI_STATUS
+PchRevealP2sb (
+ IN UINTN P2sbBase,
+ OUT BOOLEAN *OrgStatus
+ )
+{
+ BOOLEAN DevicePresent;
+
+ DevicePresent = (MmioRead16 (P2sbBase + PCI_VENDOR_ID_OFFSET) != 0xFFFF);
+ if (OrgStatus != NULL) {
+ *OrgStatus = DevicePresent;
+ }
+ if (!DevicePresent) {
+ MmioWrite8 (P2sbBase + R_PCH_P2SB_E0 + 1, 0);
+ }
+ return EFI_SUCCESS;
+}
diff --git a/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchP2sbLib/PeiDxeSmmPchP2sbLib.inf b/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchP2sbLib/PeiDxeSmmPchP2sbLib.inf
new file mode 100644
index 0000000000..4f57152b2e
--- /dev/null
+++ b/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchP2sbLib/PeiDxeSmmPchP2sbLib.inf
@@ -0,0 +1,37 @@
+### @file
+#
+# Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which 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.
+#
+###
+
+[Defines]
+ INF_VERSION = 0x00010017
+ BASE_NAME = PeiDxeSmmPchP2sbLib
+ FILE_GUID = FB044F6F-5F9F-48AB-AE12-1C0B829C8AD7
+ VERSION_STRING = 1.0
+ MODULE_TYPE = BASE
+ LIBRARY_CLASS = PchP2sbLib
+
+
+[LibraryClasses]
+ BaseLib
+ IoLib
+ DebugLib
+ MmPciLib
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ LewisburgPkg/PchRcPkg.dec #SERVER_BIOS
+ PurleyRcPkg/RcPkg.dec #SERVER_BIOS
+
+[Sources]
+ PchP2sbLib.c
diff --git a/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchPcrLib/PchPcrLib.c b/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchPcrLib/PchPcrLib.c
new file mode 100644
index 0000000000..032349bd4e
--- /dev/null
+++ b/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchPcrLib/PchPcrLib.c
@@ -0,0 +1,459 @@
+/** @file
+
+Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+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.
+
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/MmPciBaseLib.h>
+#include <PchAccess.h>
+#include <Library/PchInfoLib.h>
+
+/**
+ Read PCR register. (This is internal function)
+ It returns PCR register and size in 1byte/2bytes/4bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of this Port ID
+ @param[in] Size Size for read. Must be 1 or 2 or 4.
+ @param[out] OutData Buffer of Output Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+STATIC
+EFI_STATUS
+PchPcrRead (
+ IN PCH_SBI_PID Pid,
+ IN UINT16 Offset,
+ IN UINTN Size,
+ OUT UINT32 *OutData
+ )
+{
+ if ((Offset & (Size - 1)) != 0) {
+ DEBUG ((DEBUG_ERROR, "PchPcrRead error. Invalid Offset: %x Size: %x", Offset, Size));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // @todo SKL PCH: check PID that not expected to use this routine, such as CAM_FLIS, CSME0
+ //
+
+ switch (Size) {
+ case 4:
+ *(UINT32*)OutData = MmioRead32 (PCH_PCR_ADDRESS (Pid, Offset));
+ break;
+ case 2:
+ *(UINT16*)OutData = MmioRead16 (PCH_PCR_ADDRESS (Pid, Offset));
+ break;
+ case 1:
+ *(UINT8*) OutData = MmioRead8 (PCH_PCR_ADDRESS (Pid, Offset));
+ break;
+ default:
+ break;
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Read PCR register.
+ It returns PCR register and size in 4bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of this Port ID
+ @param[out] OutData Buffer of Output Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchPcrRead32 (
+ IN PCH_SBI_PID Pid,
+ IN UINT16 Offset,
+ OUT UINT32 *OutData
+ )
+{
+ return PchPcrRead (Pid, Offset, 4, (UINT32*) OutData);
+}
+
+/**
+ Read PCR register.
+ It returns PCR register and size in 2bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of this Port ID
+ @param[out] OutData Buffer of Output Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchPcrRead16 (
+ IN PCH_SBI_PID Pid,
+ IN UINT16 Offset,
+ OUT UINT16 *OutData
+ )
+{
+ return PchPcrRead (Pid, Offset, 2, (UINT32*) OutData);
+}
+
+/**
+ Read PCR register.
+ It returns PCR register and size in 1bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of this Port ID
+ @param[out] OutData Buffer of Output Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchPcrRead8 (
+ IN PCH_SBI_PID Pid,
+ IN UINT16 Offset,
+ OUT UINT8 *OutData
+ )
+{
+ return PchPcrRead (Pid, Offset, 1, (UINT32*) OutData);
+}
+
+BOOLEAN
+PchPcrWriteMmioCheck (
+ IN PCH_SBI_PID Pid,
+ IN UINT16 Offset
+ )
+{
+DEBUG_CODE_BEGIN();
+ PCH_SERIES PchSeries;
+
+ PchSeries = GetPchSeries ();
+ //
+ // 1. USB2 AFE register must use SBI method
+ //
+
+ //
+ // 2. GPIO unlock register field must use SBI method
+ //
+ if (Pid == PID_GPIOCOM0) {
+ if (((PchSeries == PchLp) &&
+ ((Offset == R_PCH_LP_PCR_GPIO_GPP_A_PADCFGLOCK) ||
+ (Offset == R_PCH_LP_PCR_GPIO_GPP_A_PADCFGLOCKTX) ||
+ (Offset == R_PCH_LP_PCR_GPIO_GPP_B_PADCFGLOCK) ||
+ (Offset == R_PCH_LP_PCR_GPIO_GPP_B_PADCFGLOCKTX))) ||
+ ((PchSeries == PchH) &&
+ ((Offset == R_PCH_H_PCR_GPIO_GPP_A_PADCFGLOCK) ||
+ (Offset == R_PCH_H_PCR_GPIO_GPP_A_PADCFGLOCKTX) ||
+ (Offset == R_PCH_H_PCR_GPIO_GPP_B_PADCFGLOCK) ||
+ (Offset == R_PCH_H_PCR_GPIO_GPP_B_PADCFGLOCKTX))))
+ {
+ return FALSE;
+ }
+ }
+ if (Pid == PID_GPIOCOM1) {
+ if (((PchSeries == PchLp) &&
+ ((Offset == R_PCH_LP_PCR_GPIO_GPP_C_PADCFGLOCK) ||
+ (Offset == R_PCH_LP_PCR_GPIO_GPP_C_PADCFGLOCKTX) ||
+ (Offset == R_PCH_LP_PCR_GPIO_GPP_D_PADCFGLOCK) ||
+ (Offset == R_PCH_LP_PCR_GPIO_GPP_D_PADCFGLOCKTX) ||
+ (Offset == R_PCH_LP_PCR_GPIO_GPP_E_PADCFGLOCK) ||
+ (Offset == R_PCH_LP_PCR_GPIO_GPP_E_PADCFGLOCKTX))) ||
+ ((PchSeries == PchH) &&
+ ((Offset == R_PCH_H_PCR_GPIO_GPP_C_PADCFGLOCK) ||
+ (Offset == R_PCH_H_PCR_GPIO_GPP_C_PADCFGLOCKTX) ||
+ (Offset == R_PCH_H_PCR_GPIO_GPP_D_PADCFGLOCK) ||
+ (Offset == R_PCH_H_PCR_GPIO_GPP_D_PADCFGLOCKTX) ||
+ (Offset == R_PCH_H_PCR_GPIO_GPP_E_PADCFGLOCK) ||
+ (Offset == R_PCH_H_PCR_GPIO_GPP_E_PADCFGLOCKTX) ||
+ (Offset == R_PCH_H_PCR_GPIO_GPP_F_PADCFGLOCK) ||
+ (Offset == R_PCH_H_PCR_GPIO_GPP_F_PADCFGLOCKTX) ||
+ (Offset == R_PCH_H_PCR_GPIO_GPP_G_PADCFGLOCK) ||
+ (Offset == R_PCH_H_PCR_GPIO_GPP_G_PADCFGLOCKTX) ||
+ (Offset == R_PCH_H_PCR_GPIO_GPP_H_PADCFGLOCK) ||
+ (Offset == R_PCH_H_PCR_GPIO_GPP_H_PADCFGLOCKTX))))
+ {
+ return FALSE;
+ }
+ }
+ if (Pid == PID_GPIOCOM2) {
+ if (((PchSeries == PchLp) &&
+ ((Offset == R_PCH_LP_PCR_GPIO_GPD_PADCFGLOCK) ||
+ (Offset == R_PCH_LP_PCR_GPIO_GPD_PADCFGLOCKTX))) ||
+ ((PchSeries == PchH) &&
+ ((Offset == R_PCH_H_PCR_GPIO_GPD_PADCFGLOCK) ||
+ (Offset == R_PCH_H_PCR_GPIO_GPD_PADCFGLOCKTX))))
+ {
+ return FALSE;
+ }
+ }
+ if (Pid == PID_GPIOCOM3) {
+ if (((PchSeries == PchLp) &&
+ ((Offset == R_PCH_LP_PCR_GPIO_GPP_F_PADCFGLOCK) ||
+ (Offset == R_PCH_LP_PCR_GPIO_GPP_F_PADCFGLOCKTX) ||
+ (Offset == R_PCH_LP_PCR_GPIO_GPP_G_PADCFGLOCK) ||
+ (Offset == R_PCH_LP_PCR_GPIO_GPP_G_PADCFGLOCKTX))) ||
+ ((PchSeries == PchH) &&
+ ((Offset == R_PCH_H_PCR_GPIO_GPP_I_PADCFGLOCK) ||
+ (Offset == R_PCH_H_PCR_GPIO_GPP_I_PADCFGLOCKTX))))
+ {
+ return FALSE;
+ }
+ }
+ //
+ // 3. CIO2 FLIS regsiter must use SBI method
+ //
+
+ //
+ // 4. CSME0 based PCR should use the SBI method due to the FID requirement
+ //
+ if (Pid == PID_CSME0) {
+ return FALSE;
+ }
+DEBUG_CODE_END();
+ return TRUE;
+
+}
+
+/**
+ Write PCR register. (This is internal function)
+ It programs PCR register and size in 1byte/2bytes/4bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of Port ID.
+ @param[in] Size Size for read. Must be 1 or 2 or 4.
+ @param[in] AndData AND Data. Must be the same size as Size parameter.
+ @param[in] OrData OR Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+STATIC
+EFI_STATUS
+PchPcrWrite (
+ IN PCH_SBI_PID Pid,
+ IN UINT16 Offset,
+ IN UINTN Size,
+ IN UINT32 InData
+ )
+{
+ if ((Offset & (Size - 1)) != 0) {
+ DEBUG ((DEBUG_ERROR, "PchPcrWrite error. Invalid Offset: %x Size: %x", Offset, Size));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+DEBUG_CODE_BEGIN();
+ if (!PchPcrWriteMmioCheck (Pid, Offset)) {
+ DEBUG ((DEBUG_ERROR, "PchPcrWrite error. Pid: %x Offset: %x should access through SBI interface", Pid, Offset));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+DEBUG_CODE_END();
+
+ //
+ // Write the PCR register with provided data
+ // Then read back PCR register to prevent from back to back write.
+ //
+ switch (Size) {
+ case 4:
+ MmioWrite32 (PCH_PCR_ADDRESS (Pid, Offset), (UINT32)InData);
+ break;
+ case 2:
+ MmioWrite16 (PCH_PCR_ADDRESS (Pid, Offset), (UINT16)InData);
+ break;
+ case 1:
+ MmioWrite8 (PCH_PCR_ADDRESS (Pid, Offset), (UINT8) InData);
+ break;
+ default:
+ break;
+ }
+ MmioRead32 (PCH_PCR_ADDRESS (PID_LPC, R_PCH_PCR_LPC_GCFD));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Write PCR register.
+ It programs PCR register and size in 4bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of Port ID.
+ @param[in] InData Input Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchPcrWrite32 (
+ IN PCH_SBI_PID Pid,
+ IN UINT16 Offset,
+ IN UINT32 InData
+ )
+{
+ return PchPcrWrite (Pid, Offset, 4, InData);
+}
+
+/**
+ Write PCR register.
+ It programs PCR register and size in 2bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of Port ID.
+ @param[in] InData Input Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchPcrWrite16 (
+ IN PCH_SBI_PID Pid,
+ IN UINT16 Offset,
+ IN UINT16 InData
+ )
+{
+ return PchPcrWrite (Pid, Offset, 2, InData);
+}
+
+/**
+ Write PCR register.
+ It programs PCR register and size in 1bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of Port ID.
+ @param[in] InData Input Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchPcrWrite8 (
+ IN PCH_SBI_PID Pid,
+ IN UINT16 Offset,
+ IN UINT8 InData
+ )
+{
+ return PchPcrWrite (Pid, Offset, 1, InData);
+}
+
+/**
+ Write PCR register.
+ It programs PCR register and size in 4bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of Port ID.
+ @param[in] AndData AND Data. Must be the same size as Size parameter.
+ @param[in] OrData OR Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchPcrAndThenOr32 (
+ IN PCH_SBI_PID Pid,
+ IN UINT16 Offset,
+ IN UINT32 AndData,
+ IN UINT32 OrData
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Data32;
+
+ Data32 = 0x00;
+ Status = PchPcrRead (Pid, Offset, 4, &Data32);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Data32 &= AndData;
+ Data32 |= OrData;
+ Status = PchPcrWrite (Pid, Offset, 4, Data32);
+ return Status;
+}
+
+/**
+ Write PCR register.
+ It programs PCR register and size in 2bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of Port ID.
+ @param[in] AndData AND Data. Must be the same size as Size parameter.
+ @param[in] OrData OR Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchPcrAndThenOr16 (
+ IN PCH_SBI_PID Pid,
+ IN UINT16 Offset,
+ IN UINT16 AndData,
+ IN UINT16 OrData
+ )
+{
+ EFI_STATUS Status;
+ UINT16 Data16;
+
+ Data16 = 0x00;
+ Status = PchPcrRead (Pid, Offset, 2, (UINT32*) &Data16);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Data16 &= AndData;
+ Data16 |= OrData;
+ Status = PchPcrWrite (Pid, Offset, 2, Data16);
+ return Status;
+}
+
+/**
+ Write PCR register.
+ It programs PCR register and size in 1bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of Port ID.
+ @param[in] AndData AND Data. Must be the same size as Size parameter.
+ @param[in] OrData OR Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchPcrAndThenOr8 (
+ IN PCH_SBI_PID Pid,
+ IN UINT16 Offset,
+ IN UINT8 AndData,
+ IN UINT8 OrData
+ )
+{
+ EFI_STATUS Status;
+ UINT8 Data8;
+
+ Status = PchPcrRead (Pid, Offset, 1, (UINT32*) &Data8);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Data8 &= AndData;
+ Data8 |= OrData;
+ Status = PchPcrWrite (Pid, Offset, 1, Data8);
+ return Status;
+}
+
diff --git a/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchPcrLib/PeiDxeSmmPchPcrLib.inf b/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchPcrLib/PeiDxeSmmPchPcrLib.inf
new file mode 100644
index 0000000000..c54dc2c4e2
--- /dev/null
+++ b/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchPcrLib/PeiDxeSmmPchPcrLib.inf
@@ -0,0 +1,38 @@
+### @file
+#
+# Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which 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.
+#
+###
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiDxeSmmPchPcrLib
+FILE_GUID = 117C8D19-445B-46BF-B624-109F63709375
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = PchPcrLib
+
+
+[LibraryClasses]
+BaseLib
+IoLib
+DebugLib
+MmPciLib
+PchInfoLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+LewisburgPkg/PchRcPkg.dec #SERVER_BIOS
+PurleyRcPkg/RcPkg.dec #SERVER_BIOS
+
+[Sources]
+PchPcrLib.c
diff --git a/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchPmcLib/PchPmcLib.c b/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchPmcLib/PchPmcLib.c
new file mode 100644
index 0000000000..9796cb0561
--- /dev/null
+++ b/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchPmcLib/PchPmcLib.c
@@ -0,0 +1,159 @@
+/** @file
+
+Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+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.
+
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/MmPciBaseLib.h>
+#include <PchAccess.h>
+#include <Library/PchCycleDecodingLib.h>
+#include <Library/PchPmcLib.h>
+
+/**
+ Query PCH to determine the Pm Status
+ NOTE:
+ It's matter when did platform code use this library, since some status could be cleared by write one clear.
+ Therefore this funciton is not always return the same result in one boot.
+ It's suggested that platform code read this status in the beginning of post.
+ For the ColdBoot case, this function only returns one case of the cold boot. Some cold boot case might
+ depends on the power cycle scenario and should check with different condtion.
+
+ @param[in] PmStatus - The Pch Pm Status to be probed
+
+ @retval Return TRUE if Status querried is Valid or FALSE if otherwise
+**/
+BOOLEAN
+GetPchPmStatus (
+ PCH_PM_STATUS PmStatus
+ )
+{
+ UINTN PmcRegBase;
+ UINT32 PchPwrmBase;
+ UINT32 PmConA;
+ UINT32 PmConB;
+ UINT32 GblRst0;
+
+ PmcRegBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_PMC,
+ PCI_FUNCTION_NUMBER_PCH_PMC
+ );
+ PchPwrmBaseGet (&PchPwrmBase);
+
+ PmConA = MmioRead32 (PmcRegBase + R_PCH_PMC_GEN_PMCON_A);
+ PmConB = MmioRead32 (PmcRegBase + R_PCH_PMC_GEN_PMCON_B);
+ GblRst0 = MmioRead32 (PchPwrmBase + R_PCH_PWRM_124);
+
+ switch(PmStatus){
+ case PchWarmBoot:
+
+ if (PmConA & B_PCH_PMC_GEN_PMCON_A_MEM_SR) {
+ return TRUE;
+ }
+ break;
+
+ case PwrFlr:
+ if (PmConB & B_PCH_PMC_GEN_PMCON_B_PWR_FLR) {
+ return TRUE;
+ }
+ break;
+
+ case PwrFlrSys:
+ if (GblRst0 & BIT12) {
+ return TRUE;
+ }
+ break;
+
+ case PwrFlrPch:
+ if (GblRst0 & BIT11) {
+ return TRUE;
+ }
+ break;
+
+ case PchColdBoot:
+ ///
+ /// Check following conditions for cold boot.
+ ///
+ if ((GblRst0 & BIT11) && // PCHPWR_FLR
+ (GblRst0 & BIT12) && // SYSPWR_FLR
+ (!(PmConA & B_PCH_PMC_GEN_PMCON_A_MEM_SR))) {
+ return TRUE;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return FALSE;
+}
+
+/**
+ Funtion to check if Battery lost or CMOS cleared.
+
+ @reval TRUE Battery is always present.
+ @reval FALSE CMOS is cleared.
+**/
+BOOLEAN
+EFIAPI
+PchIsRtcBatteryGood (
+ VOID
+ )
+{
+ UINTN Data;
+ UINTN PmcBaseAddress;
+
+ //
+ // Check if the CMOS battery is present
+ // Checks RTC_PWR_STS bit in the GEN_PMCON_3 register
+ //
+ PmcBaseAddress = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_PMC,
+ PCI_FUNCTION_NUMBER_PCH_PMC
+ );
+
+ Data = MmioRead32 (PmcBaseAddress + R_PCH_PMC_GEN_PMCON_B);
+ if ((Data & B_PCH_PMC_GEN_PMCON_B_RTC_PWR_STS) == 0) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ Funtion to check if DWR occurs
+
+ @reval TRUE DWR occurs
+ @reval FALSE Normal boot flow
+**/
+BOOLEAN
+EFIAPI
+PchIsDwrFlow (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINT32 PchPwrmBase;
+
+ Status = PchPwrmBaseGet (&PchPwrmBase);
+ ASSERT (PchPwrmBase != 0);
+
+ if ((PchPwrmBase != 0) &&
+ (MmioRead32 (PchPwrmBase + R_PCH_PWRM_HPR_CAUSE0) & B_PCH_PWRM_HPR_CAUSE0_GBL_TO_HOST)) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
diff --git a/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchPmcLib/PeiDxeSmmPchPmcLib.inf b/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchPmcLib/PeiDxeSmmPchPmcLib.inf
new file mode 100644
index 0000000000..ffb37a199a
--- /dev/null
+++ b/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchPmcLib/PeiDxeSmmPchPmcLib.inf
@@ -0,0 +1,38 @@
+### @file
+#
+# Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which 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.
+#
+###
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiDxeSmmPchPmcLib
+FILE_GUID = 9D60C364-5086-41E3-BC9D-C62AB7233DBF
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = PchPmcLib
+
+
+[LibraryClasses]
+BaseLib
+IoLib
+DebugLib
+MmPciLib
+PchCycleDecodingLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+LewisburgPkg/PchRcPkg.dec #SERVER_BIOS
+PurleyRcPkg/RcPkg.dec #SERVER_BIOS
+
+[Sources]
+PchPmcLib.c
diff --git a/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchSbiAccessLib/PchSbiAccessLib.c b/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchSbiAccessLib/PchSbiAccessLib.c
new file mode 100644
index 0000000000..444b2822c7
--- /dev/null
+++ b/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchSbiAccessLib/PchSbiAccessLib.c
@@ -0,0 +1,376 @@
+/** @file
+
+Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+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.
+
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/MmPciBaseLib.h>
+#include <PchAccess.h>
+#include <Library/PchP2sbLib.h>
+#include <Library/PchSbiAccessLib.h>
+
+/**
+ Execute PCH SBI message
+ Take care of that there is no lock protection when using SBI programming in both POST time and SMI.
+ It will clash with POST time SBI programming when SMI happen.
+ Programmer MUST do the save and restore opration while using the PchSbiExecution inside SMI
+ to prevent from racing condition.
+ This function will reveal P2SB and hide P2SB if it's originally hidden. If more than one SBI access
+ needed, it's better to unhide the P2SB before calling and hide it back after done.
+
+ When the return value is "EFI_SUCCESS", the "Response" do not need to be checked as it would have been
+ SBI_SUCCESS. If the return value is "EFI_DEVICE_ERROR", then this would provide additional information
+ when needed.
+
+ @param[in] Pid Port ID of the SBI message
+ @param[in] Offset Offset of the SBI message
+ @param[in] Opcode Opcode
+ @param[in] Posted Posted message
+ @param[in, out] Data32 Read/Write data
+ @param[out] Response Response
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_DEVICE_ERROR Transaction fail
+ @retval EFI_INVALID_PARAMETER Invalid parameter
+**/
+EFI_STATUS
+EFIAPI
+PchSbiExecution (
+ IN PCH_SBI_PID Pid,
+ IN UINT64 Offset,
+ IN PCH_SBI_OPCODE Opcode,
+ IN BOOLEAN Posted,
+ IN OUT UINT32 *Data32,
+ OUT UINT8 *Response
+ )
+{
+
+
+ return PchSbiExecutionEx ( Pid,
+ Offset,
+ Opcode,
+ Posted,
+ 0x000F,
+ 0x0000,
+ 0x0000,
+ Data32,
+ Response
+ );
+}
+
+/**
+ Full function for executing PCH SBI message
+ Take care of that there is no lock protection when using SBI programming in both POST time and SMI.
+ It will clash with POST time SBI programming when SMI happen.
+ Programmer MUST do the save and restore opration while using the PchSbiExecution inside SMI
+ to prevent from racing condition.
+ This function will reveal P2SB and hide P2SB if it's originally hidden. If more than one SBI access
+ needed, it's better to unhide the P2SB before calling and hide it back after done.
+
+ When the return value is "EFI_SUCCESS", the "Response" do not need to be checked as it would have been
+ SBI_SUCCESS. If the return value is "EFI_DEVICE_ERROR", then this would provide additional information
+ when needed.
+
+ @param[in] Pid Port ID of the SBI message
+ @param[in] Offset Offset of the SBI message
+ @param[in] Opcode Opcode
+ @param[in] Posted Posted message
+ @param[in] Fbe First byte enable
+ @param[in] Bar Bar
+ @param[in] Fid Function ID
+ @param[in, out] Data32 Read/Write data
+ @param[out] Response Response
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_DEVICE_ERROR Transaction fail
+ @retval EFI_INVALID_PARAMETER Invalid parameter
+**/
+EFI_STATUS
+EFIAPI
+PchSbiExecutionEx (
+ IN PCH_SBI_PID Pid,
+ IN UINT64 Offset,
+ IN PCH_SBI_OPCODE Opcode,
+ IN BOOLEAN Posted,
+ IN UINT16 Fbe,
+ IN UINT16 Bar,
+ IN UINT16 Fid,
+ IN OUT UINT32 *Data32,
+ OUT UINT8 *Response
+ )
+{
+ EFI_STATUS Status;
+ UINTN P2sbBase;
+ BOOLEAN P2sbOrgStatus;
+ UINTN Timeout;
+ UINT16 SbiStat;
+
+ //
+ // Check opcode valid
+ //
+ switch (Opcode) {
+ case PciConfigRead:
+ case PciConfigWrite:
+ case PrivateControlRead:
+ case PrivateControlWrite:
+ case GpioLockUnlock:
+ break;
+ default:
+ return EFI_INVALID_PARAMETER;
+ break;
+ }
+
+ P2sbOrgStatus = FALSE;
+ P2sbBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_P2SB,
+ PCI_FUNCTION_NUMBER_PCH_P2SB
+ );
+ PchRevealP2sb (P2sbBase, &P2sbOrgStatus);
+ ///
+ /// BWG Section 2.2.1
+ /// 1. Poll P2SB PCI offset D8h[0] = 0b
+ /// Make sure the previous opeartion is completed.
+ ///
+ Timeout = 0xFFFFFFF;
+ while (Timeout > 0){
+ SbiStat = MmioRead16 (P2sbBase + R_PCH_P2SB_SBISTAT);
+ if ((SbiStat & B_PCH_P2SB_SBISTAT_INITRDY) == 0) {
+ break;
+ }
+ Timeout--;
+ }
+ if (Timeout == 0) {
+ Status = EFI_DEVICE_ERROR;
+ goto ExitPchSbiExecutionEx;
+ }
+ //
+ // Initial Response status
+ //
+ *Response = SBI_INVALID_RESPONSE;
+ Status = EFI_SUCCESS;
+ SbiStat = 0;
+ ///
+ /// 2. Write P2SB PCI offset D0h[31:0] with Address and Destination Port ID
+ ///
+ MmioWrite32 (P2sbBase + R_PCH_P2SB_SBIADDR, (UINT32) ((Pid << 24) | (UINT16)Offset));
+ ///
+ /// 3. Write P2SB PCI offset DCh[31:0] with extended address, which is expected to be 0 in SKL PCH.
+ ///
+ MmioWrite32 (P2sbBase + R_PCH_P2SB_SBIEXTADDR, (UINT32) RShiftU64 (Offset, 16));
+ ///
+ /// 5. Set P2SB PCI offset D8h[15:8] = 00000110b for read
+ /// Set P2SB PCI offset D8h[15:8] = 00000111b for write
+ //
+ // Set SBISTAT[15:8] to the opcode passed in
+ // Set SBISTAT[7] to the posted passed in
+ //
+ MmioAndThenOr16 (
+ (P2sbBase + R_PCH_P2SB_SBISTAT),
+ (UINT16) ~(B_PCH_P2SB_SBISTAT_OPCODE | B_PCH_P2SB_SBISTAT_POSTED),
+ (UINT16) ((Opcode << 8) | (Posted << 7))
+ );
+ ///
+ /// 6. Write P2SB PCI offset DAh[15:0] = F000h
+ ///
+ //
+ // Set RID[15:0] = Fbe << 12 | Bar << 8 | Fid
+ //
+ MmioWrite16 (
+ (P2sbBase + R_PCH_P2SB_SBIRID),
+ (((Fbe & 0x000F) << 12) | ((Bar & 0x0007) << 8) | (Fid & 0x00FF))
+ );
+
+ switch (Opcode) {
+ case PciConfigWrite:
+ case PrivateControlWrite:
+ case GpioLockUnlock:
+ ///
+ /// 4. Write P2SB PCI offset D4h[31:0] with the intended data accordingly
+ ///
+ MmioWrite32 ((P2sbBase + R_PCH_P2SB_SBIDATA), *Data32);
+ break;
+ default:
+ ///
+ /// 4. Write P2SB PCI offset D4h[31:0] with dummy data such as 0,
+ /// because all D0-DFh register range must be touched in SKL PCH
+ /// for a successful SBI transaction.
+ ///
+ MmioWrite32 ((P2sbBase + R_PCH_P2SB_SBIDATA), 0);
+ break;
+ }
+ ///
+ /// 7. Set P2SB PCI offset D8h[0] = 1b, Poll P2SB PCI offset D8h[0] = 0b
+ ///
+ //
+ // Set SBISTAT[0] = 1b, trigger the SBI operation
+ //
+ MmioOr16 (P2sbBase + R_PCH_P2SB_SBISTAT, (UINT16) B_PCH_P2SB_SBISTAT_INITRDY);
+ //
+ // Poll SBISTAT[0] = 0b, Polling for Busy bit
+ //
+ Timeout = 0xFFFFFFF;
+ while (Timeout > 0){
+ SbiStat = MmioRead16 (P2sbBase + R_PCH_P2SB_SBISTAT);
+ if ((SbiStat & B_PCH_P2SB_SBISTAT_INITRDY) == 0) {
+ break;
+ }
+ Timeout--;
+ }
+ if (Timeout == 0) {
+ //
+ // If timeout, it's fatal error.
+ //
+ Status = EFI_DEVICE_ERROR;
+ } else {
+ ///
+ /// 8. Check if P2SB PCI offset D8h[2:1] = 00b for successful transaction
+ ///
+ *Response = (UINT8)((SbiStat & B_PCH_P2SB_SBISTAT_RESPONSE) >> N_PCH_P2SB_SBISTAT_RESPONSE);
+ if (*Response == SBI_SUCCESSFUL) {
+ switch (Opcode) {
+ case PciConfigRead:
+ case PrivateControlRead:
+ ///
+ /// 9. Read P2SB PCI offset D4h[31:0] for SBI data
+ ///
+ *Data32 = MmioRead32 (P2sbBase + R_PCH_P2SB_SBIDATA);
+ break;
+ default:
+ break;
+ }
+ Status = EFI_SUCCESS;
+ } else {
+ Status = EFI_DEVICE_ERROR;
+ }
+ }
+
+ExitPchSbiExecutionEx:
+ if (!P2sbOrgStatus) {
+ PchHideP2sb (P2sbBase);
+ }
+ return Status;
+}
+
+/**
+ This function saves all PCH SBI registers.
+ The save and restore operations must be done while using the PchSbiExecution inside SMM.
+ It prevents the racing condition of PchSbiExecution re-entry between POST and SMI.
+ Before using this function, make sure the P2SB is not hidden.
+
+ @param[in, out] PchSbiRegister Structure for saving the registers
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_DEVICE_ERROR Device is hidden.
+**/
+EFI_STATUS
+EFIAPI
+PchSbiRegisterSave (
+ IN OUT PCH_SBI_REGISTER_STRUCT *PchSbiRegister
+ )
+{
+ UINTN P2sbBase;
+ UINTN Timeout;
+ UINT16 SbiStat;
+
+ P2sbBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_P2SB,
+ PCI_FUNCTION_NUMBER_PCH_P2SB
+ );
+ if (MmioRead16 (P2sbBase + PCI_VENDOR_ID_OFFSET) == 0xFFFF) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Make sure it's not busy.
+ // Poll SBISTAT[0] = 0b
+ //
+ Timeout = 0xFFFFFFF;
+ while ((Timeout--) > 0){
+ SbiStat = MmioRead16 (P2sbBase + R_PCH_P2SB_SBISTAT);
+ if ((SbiStat & B_PCH_P2SB_SBISTAT_INITRDY) == 0) {
+ break;
+ }
+ }
+ if (Timeout == 0) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Save original SBI registers
+ //
+ PchSbiRegister->SbiAddr = MmioRead32 (P2sbBase + R_PCH_P2SB_SBIADDR);
+ PchSbiRegister->SbiExtAddr = MmioRead32 (P2sbBase + R_PCH_P2SB_SBIEXTADDR);
+ PchSbiRegister->SbiData = MmioRead32 (P2sbBase + R_PCH_P2SB_SBIDATA);
+ PchSbiRegister->SbiStat = MmioRead16 (P2sbBase + R_PCH_P2SB_SBISTAT);
+ PchSbiRegister->SbiRid = MmioRead16 (P2sbBase + R_PCH_P2SB_SBIRID);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function restores all PCH SBI registers
+ The save and restore operations must be done while using the PchSbiExecution inside SMM.
+ It prevents the racing condition of PchSbiExecution re-entry between POST and SMI.
+ Before using this function, make sure the P2SB is not hidden.
+
+ @param[in] PchSbiRegister Structure for restoring the registers
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_DEVICE_ERROR Device is hidden.
+**/
+EFI_STATUS
+EFIAPI
+PchSbiRegisterRestore (
+ IN PCH_SBI_REGISTER_STRUCT *PchSbiRegister
+ )
+{
+ UINTN P2sbBase;
+ UINTN Timeout;
+ UINT16 SbiStat;
+
+ P2sbBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_P2SB,
+ PCI_FUNCTION_NUMBER_PCH_P2SB
+ );
+ if (MmioRead16 (P2sbBase + PCI_VENDOR_ID_OFFSET) == 0xFFFF) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Make sure it's not busy.
+ // Poll SBISTAT[0] = 0b
+ //
+ Timeout = 0xFFFFFFF;
+ while ((Timeout--) > 0){
+ SbiStat = MmioRead16 (P2sbBase + R_PCH_P2SB_SBISTAT);
+ if ((SbiStat & B_PCH_P2SB_SBISTAT_INITRDY) == 0) {
+ break;
+ }
+ }
+ if (Timeout == 0) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Restore original SBI registers
+ //
+ MmioWrite32 (P2sbBase + R_PCH_P2SB_SBIADDR , PchSbiRegister->SbiAddr);
+ MmioWrite32 (P2sbBase + R_PCH_P2SB_SBIEXTADDR, PchSbiRegister->SbiExtAddr);
+ MmioWrite32 (P2sbBase + R_PCH_P2SB_SBIDATA , PchSbiRegister->SbiData);
+ MmioWrite16 (P2sbBase + R_PCH_P2SB_SBISTAT , PchSbiRegister->SbiStat);
+ MmioWrite16 (P2sbBase + R_PCH_P2SB_SBIRID , PchSbiRegister->SbiRid);
+
+ return EFI_SUCCESS;
+}
+
diff --git a/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchSbiAccessLib/PeiDxeSmmPchSbiAccessLib.inf b/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchSbiAccessLib/PeiDxeSmmPchSbiAccessLib.inf
new file mode 100644
index 0000000000..4f6d2a8a21
--- /dev/null
+++ b/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchSbiAccessLib/PeiDxeSmmPchSbiAccessLib.inf
@@ -0,0 +1,38 @@
+### @file
+#
+# Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which 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.
+#
+###
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiDxeSmmPchSbiAccessLib
+FILE_GUID = 96ECB0FB-A975-4DC8-B88A-D90C3378CE87
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = PchSbiAccessLib
+
+
+[LibraryClasses]
+BaseLib
+IoLib
+DebugLib
+MmPciLib
+PchP2sbLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+LewisburgPkg/PchRcPkg.dec #SERVER_BIOS
+PurleyRcPkg/RcPkg.dec #SERVER_BIOS
+
+[Sources]
+PchSbiAccessLib.c
diff --git a/Silicon/Intel/LewisburgPkg/Library/PeiPchPolicyLib/PchPrintPolicy.c b/Silicon/Intel/LewisburgPkg/Library/PeiPchPolicyLib/PchPrintPolicy.c
new file mode 100644
index 0000000000..a555ff9c6e
--- /dev/null
+++ b/Silicon/Intel/LewisburgPkg/Library/PeiPchPolicyLib/PchPrintPolicy.c
@@ -0,0 +1,736 @@
+/** @file
+
+Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+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.
+
+**/
+
+#include "PeiPchPolicyLibrary.h"
+
+/**
+ Print PCH_USB_CONFIG and serial out.
+
+ @param[in] UsbConfig Pointer to a PCH_USB_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintUsbConfig (
+ IN CONST PCH_USB_CONFIG *UsbConfig
+ )
+{
+ UINT32 i;
+
+ DEBUG ((DEBUG_INFO, "------------------ PCH USB Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, " UsbPrecondition= %x\n", UsbConfig->UsbPrecondition));
+ DEBUG ((DEBUG_INFO, " DisableComplianceMode= %x\n", UsbConfig->DisableComplianceMode));
+
+ for (i = 0; i < GetPchUsbMaxPhysicalPortNum (); i++) {
+ DEBUG ((DEBUG_INFO, " PortUsb20[%d].Enabled= %x\n", i, UsbConfig->PortUsb20[i].Enable));
+ DEBUG ((DEBUG_INFO, " PortUsb20[%d].OverCurrentPin= OC%x\n", i, UsbConfig->PortUsb20[i].OverCurrentPin));
+ DEBUG ((DEBUG_INFO, " PortUsb20[%d].Afe.Petxiset= %x\n", i, UsbConfig->PortUsb20[i].Afe.Petxiset));
+ DEBUG ((DEBUG_INFO, " PortUsb20[%d].Afe.Txiset= %x\n", i, UsbConfig->PortUsb20[i].Afe.Txiset));
+ DEBUG ((DEBUG_INFO, " PortUsb20[%d].Afe.Predeemp= %x\n", i, UsbConfig->PortUsb20[i].Afe.Predeemp));
+ DEBUG ((DEBUG_INFO, " PortUsb20[%d].Afe.Pehalfbit= %x\n", i, UsbConfig->PortUsb20[i].Afe.Pehalfbit));
+ }
+
+ for (i = 0; i < GetPchXhciMaxUsb3PortNum (); i++) {
+ DEBUG ((DEBUG_INFO, " PortUsb30[%d] Enabled= %x\n", i, UsbConfig->PortUsb30[i].Enable));
+ DEBUG ((DEBUG_INFO, " PortUsb30[%d].OverCurrentPin= OC%x\n", i, UsbConfig->PortUsb30[i].OverCurrentPin));
+ DEBUG ((DEBUG_INFO, " PortUsb30[%d].HsioTxDeEmph = %x\n", i, UsbConfig->PortUsb30[i].HsioTxDeEmph));
+ DEBUG ((DEBUG_INFO, " PortUsb30[%d].HsioTxDeEmphEnable = %x\n", i, UsbConfig->PortUsb30[i].HsioTxDeEmphEnable));
+ DEBUG ((DEBUG_INFO, " PortUsb30[%d].HsioTxDownscaleAmp = %x\n", i, UsbConfig->PortUsb30[i].HsioTxDownscaleAmp));
+ DEBUG ((DEBUG_INFO, " PortUsb30[%d].HsioTxDownscaleAmpEnable = %x\n", i, UsbConfig->PortUsb30[i].HsioTxDownscaleAmpEnable));
+ }
+
+ DEBUG ((DEBUG_INFO, " XdciConfig.Enable= %x\n", UsbConfig->XdciConfig.Enable));
+
+ for (i = 0; i < PCH_XHCI_MAX_SSIC_PORT_COUNT; i++) {
+ DEBUG ((DEBUG_INFO, " SsicPort[%d].Enable = %x\n", i, UsbConfig->SsicConfig.SsicPort[i].Enable));
+ }
+
+}
+
+/**
+ Print PCH_PCIE_CONFIG and serial out.
+
+ @param[in] PcieConfig Pointer to a PCH_PCIE_CONFIG that provides the platform setting
+ @param[in] HsioPcieConfig Pointer to a PCH_HSIO_PCIE_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintPcieConfig (
+ IN CONST PCH_PCIE_CONFIG *PcieConfig,
+ IN CONST PCH_HSIO_PCIE_CONFIG *HsioPcieConfig
+ )
+{
+ UINT32 i;
+
+ DEBUG ((DEBUG_INFO, "------------------ PCH PCIE Config ------------------\n"));
+ for (i = 0; i < GetPchMaxPciePortNum (); i++) {
+ DEBUG ((DEBUG_INFO, " RootPort[%d] Enabled= %x\n", i, PcieConfig->RootPort[i].Enable));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] HotPlug= %x\n", i, PcieConfig->RootPort[i].HotPlug));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] PmSci= %x\n", i, PcieConfig->RootPort[i].PmSci));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] ExtSync= %x\n", i, PcieConfig->RootPort[i].ExtSync));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] ClkReqSupported= %x\n", i, PcieConfig->RootPort[i].ClkReqSupported));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] ClkReqNumber= %x\n", i, PcieConfig->RootPort[i].ClkReqNumber));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] ClkReqDetect= %x\n", i, PcieConfig->RootPort[i].ClkReqDetect));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] UnsupportedRequestReport= %x\n", i, PcieConfig->RootPort[i].UnsupportedRequestReport));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] FatalErrorReport= %x\n", i, PcieConfig->RootPort[i].FatalErrorReport));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] NoFatalErrorReport= %x\n", i, PcieConfig->RootPort[i].NoFatalErrorReport));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] CorrectableErrorReport= %x\n", i, PcieConfig->RootPort[i].CorrectableErrorReport));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] SystemErrorOnFatalError= %x\n", i, PcieConfig->RootPort[i].SystemErrorOnFatalError));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] SystemErrorOnNonFatalError= %x\n", i, PcieConfig->RootPort[i].SystemErrorOnNonFatalError));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] SystemErrorOnCorrectableError= %x\n", i, PcieConfig->RootPort[i].SystemErrorOnCorrectableError));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] MaxPayload= %x\n", i, PcieConfig->RootPort[i].MaxPayload));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] AcsEnabled= %x\n", i, PcieConfig->RootPort[i].AcsEnabled));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] AdvancedErrorReporting= %x\n", i, PcieConfig->RootPort[i].AdvancedErrorReporting));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] TransmitterHalfSwing= %x\n", i, PcieConfig->RootPort[i].TransmitterHalfSwing));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] PcieSpeed= %x\n", i, PcieConfig->RootPort[i].PcieSpeed));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] Gen3EqPh3Method= %x\n", i, PcieConfig->RootPort[i].Gen3EqPh3Method));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] PhysicalSlotNumber= %x\n", i, PcieConfig->RootPort[i].PhysicalSlotNumber));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] CompletionTimeout= %x\n", i, PcieConfig->RootPort[i].CompletionTimeout));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] Aspm= %x\n", i, PcieConfig->RootPort[i].Aspm));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] L1Substates= %x\n", i, PcieConfig->RootPort[i].L1Substates));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] LtrEnable= %x\n", i, PcieConfig->RootPort[i].LtrEnable));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] LtrConfigLock= %x\n", i, PcieConfig->RootPort[i].LtrConfigLock));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] LtrMaxSnoopLatency= %x\n", i, PcieConfig->RootPort[i].LtrMaxSnoopLatency));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] LtrMaxNoSnoopLatency= %x\n", i, PcieConfig->RootPort[i].LtrMaxNoSnoopLatency));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] SnoopLatencyOverrideMode= %x\n", i, PcieConfig->RootPort[i].SnoopLatencyOverrideMode));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] SnoopLatencyOverrideMultiplier= %x\n", i, PcieConfig->RootPort[i].SnoopLatencyOverrideMultiplier));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] SnoopLatencyOverrideValue= %x\n", i, PcieConfig->RootPort[i].SnoopLatencyOverrideValue));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] NonSnoopLatencyOverrideMode= %x\n", i, PcieConfig->RootPort[i].NonSnoopLatencyOverrideMode));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] NonSnoopLatencyOverrideMultiplier= %x\n", i, PcieConfig->RootPort[i].NonSnoopLatencyOverrideMultiplier));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] NonSnoopLatencyOverrideValue= %x\n", i, PcieConfig->RootPort[i].NonSnoopLatencyOverrideValue));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] SlotPowerLimitScale= %x\n", i, PcieConfig->RootPort[i].SlotPowerLimitScale));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] SlotPowerLimitValue= %x\n", i, PcieConfig->RootPort[i].SlotPowerLimitValue));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] Uptp= %x\n", i, PcieConfig->RootPort[i].Uptp));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] Dptp= %x\n", i, PcieConfig->RootPort[i].Dptp));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] HsioRxSetCtleEnable= %x\n", i, HsioPcieConfig->Lane[i].HsioRxSetCtleEnable));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] HsioRxSetCtle= %x\n", i, HsioPcieConfig->Lane[i].HsioRxSetCtle));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] HsioTxGen1DownscaleAmpEnable= %x\n", i, HsioPcieConfig->Lane[i].HsioTxGen1DownscaleAmpEnable));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] HsioTxGen1DownscaleAmp= %x\n", i, HsioPcieConfig->Lane[i].HsioTxGen1DownscaleAmp));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] HsioTxGen2DownscaleAmpEnable= %x\n", i, HsioPcieConfig->Lane[i].HsioTxGen2DownscaleAmpEnable));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] HsioTxGen2DownscaleAmp= %x\n", i, HsioPcieConfig->Lane[i].HsioTxGen2DownscaleAmp));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] HsioTxGen3DownscaleAmpEnable= %x\n", i, HsioPcieConfig->Lane[i].HsioTxGen3DownscaleAmpEnable));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] HsioTxGen3DownscaleAmp= %x\n", i, HsioPcieConfig->Lane[i].HsioTxGen3DownscaleAmp));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] HsioTxGen1DeEmphEnable= %x\n", i, HsioPcieConfig->Lane[i].HsioTxGen1DeEmphEnable));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] HsioTxGen1DeEmph= %x\n", i, HsioPcieConfig->Lane[i].HsioTxGen1DeEmph));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] HsioTxGen2DeEmph3p5Enable= %x\n", i, HsioPcieConfig->Lane[i].HsioTxGen2DeEmph3p5Enable));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] HsioTxGen2DeEmph3p5= %x\n", i, HsioPcieConfig->Lane[i].HsioTxGen2DeEmph3p5));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] HsioTxGen2DeEmph6p0Enable= %x\n", i, HsioPcieConfig->Lane[i].HsioTxGen2DeEmph6p0Enable));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] HsioTxGen2DeEmph6p0= %x\n", i, HsioPcieConfig->Lane[i].HsioTxGen2DeEmph6p0));
+
+ }
+ DEBUG ((DEBUG_INFO, " EnablePort8xhDecode= %x\n", PcieConfig->EnablePort8xhDecode));
+ DEBUG ((DEBUG_INFO, " PchPciePort8xhDecodePortIndex= %x\n", PcieConfig->PchPciePort8xhDecodePortIndex));
+ DEBUG ((DEBUG_INFO, " DisableRootPortClockGating= %x\n", PcieConfig->DisableRootPortClockGating));
+ DEBUG ((DEBUG_INFO, " EnablePeerMemoryWrite= %x\n", PcieConfig->EnablePeerMemoryWrite));
+ DEBUG ((DEBUG_INFO, " AllowNoLtrIccPllShutdown= %x\n", PcieConfig->AllowNoLtrIccPllShutdown));
+ DEBUG ((DEBUG_INFO, " ComplianceTestMode= %x\n", PcieConfig->ComplianceTestMode));
+ DEBUG ((DEBUG_INFO, " RpFunctionSwap= %x\n", PcieConfig->RpFunctionSwap));
+}
+
+/**
+ Print PCH_PCIE_CONFIG2 and serial out.
+
+ @param[in] PcieConfig2 Pointer to a PCH_PCIE_CONFIG2 that provides the platform setting
+
+**/
+VOID
+PchPrintPcieConfig2 (
+ IN CONST PCH_PCIE_CONFIG2 *PcieConfig2
+ )
+{
+ UINT32 Index;
+
+ DEBUG ((DEBUG_INFO, "------------------ PCH PCIE Config2 -----------------\n"));
+ for (Index = 0; Index < PCH_PCIE_SWEQ_COEFFS_MAX; Index++) {
+ DEBUG ((DEBUG_INFO, " SwEqCoeffCm[%d] = %x\n", Index, PcieConfig2->SwEqCoeffList[Index].Cm));
+ DEBUG ((DEBUG_INFO, " SwEqCoeffCp[%d] = %x\n", Index, PcieConfig2->SwEqCoeffList[Index].Cp));
+ }
+}
+
+/**
+ Print PCH_SATA_CONFIG and serial out.
+
+ @param[in] SataConfig Pointer to a PCH_SATA_CONFIG that provides the platform setting
+ @param[in] HsioSataConfig Pointer to a PCH_HSIO_SATA_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintSataConfig (
+ IN CONST PCH_SATA_CONFIG *SataConfig,
+ IN VOID *HsioSataConfigPtr,
+ IN UINT8 SataControllerNo
+ )
+{
+ UINT32 i;
+
+ UINT32 MaxSataPortNum;
+ PCH_HSIO_SATA_CONFIG *HsioSataConfig;
+
+ HsioSataConfig = HsioSataConfigPtr;
+
+ if (SataControllerNo == PCH_SATA_FIRST_CONTROLLER) {
+ DEBUG ((DEBUG_INFO, "------------------- PCH Primary SATA Config ------------------\n"));
+ MaxSataPortNum = GetPchMaxSataPortNum ();
+ } else {
+ DEBUG ((DEBUG_INFO, "------------------ PCH Secondary SATA Config ------------------\n"));
+ MaxSataPortNum = GetPchMaxsSataPortNum ();
+ }
+ DEBUG ((DEBUG_INFO, " Enable= %x\n", SataConfig->Enable));
+ DEBUG ((DEBUG_INFO, " SataMode= %x\n", SataConfig->SataMode));
+
+
+ for (i = 0; i < MaxSataPortNum; i++) {
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] Enabled= %x\n", i, SataConfig->PortSettings[i].Enable));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] HotPlug= %x\n", i, SataConfig->PortSettings[i].HotPlug));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] InterlockSw= %x\n", i, SataConfig->PortSettings[i].InterlockSw));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] External= %x\n", i, SataConfig->PortSettings[i].External));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] SpinUp= %x\n", i, SataConfig->PortSettings[i].SpinUp));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] SolidStateDrive= %x\n", i, SataConfig->PortSettings[i].SolidStateDrive));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] DevSlp= %x\n", i, SataConfig->PortSettings[i].DevSlp));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] EnableDitoConfig= %x\n", i, SataConfig->PortSettings[i].EnableDitoConfig));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] DmVal= %x\n", i, SataConfig->PortSettings[i].DmVal));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] DitoVal= %x\n", i, SataConfig->PortSettings[i].DitoVal));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] ZpOdd= %x\n", i, SataConfig->PortSettings[i].ZpOdd));
+
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioRxGen1EqBoostMagEnable= %x\n", i, HsioSataConfig->PortLane[i].HsioRxGen1EqBoostMagEnable));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioRxGen1EqBoostMag= %x\n", i, HsioSataConfig->PortLane[i].HsioRxGen1EqBoostMag));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioRxGen2EqBoostMagEnable= %x\n", i, HsioSataConfig->PortLane[i].HsioRxGen2EqBoostMagEnable));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioRxGen2EqBoostMag= %x\n", i, HsioSataConfig->PortLane[i].HsioRxGen2EqBoostMag));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioRxGen3EqBoostMagEnable= %x\n", i, HsioSataConfig->PortLane[i].HsioRxGen3EqBoostMagEnable));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioRxGen3EqBoostMag= %x\n", i, HsioSataConfig->PortLane[i].HsioRxGen3EqBoostMag));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioTxGen1DownscaleAmpEnable= %x\n", i, HsioSataConfig->PortLane[i].HsioTxGen1DownscaleAmpEnable));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioTxGen1DownscaleAmp= %x\n", i, HsioSataConfig->PortLane[i].HsioTxGen1DownscaleAmp));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioTxGen2DownscaleAmpEnable= %x\n", i, HsioSataConfig->PortLane[i].HsioTxGen2DownscaleAmpEnable));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioTxGen2DownscaleAmp= %x\n", i, HsioSataConfig->PortLane[i].HsioTxGen2DownscaleAmp));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioTxGen3DownscaleAmpEnable= %x\n", i, HsioSataConfig->PortLane[i].HsioTxGen3DownscaleAmpEnable));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioTxGen3DownscaleAmp= %x\n", i, HsioSataConfig->PortLane[i].HsioTxGen3DownscaleAmp));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioTxGen1DeEmphEnable= %x\n", i, HsioSataConfig->PortLane[i].HsioTxGen1DeEmphEnable));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioTxGen1DeEmph= %x\n", i, HsioSataConfig->PortLane[i].HsioTxGen1DeEmph));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioTxGen2DeEmphEnable= %x\n", i, HsioSataConfig->PortLane[i].HsioTxGen2DeEmphEnable));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioTxGen2DeEmph= %x\n", i, HsioSataConfig->PortLane[i].HsioTxGen2DeEmph));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioTxGen3DeEmphEnable= %x\n", i, HsioSataConfig->PortLane[i].HsioTxGen3DeEmphEnable));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] HsioTxGen3DeEmph= %x\n", i, HsioSataConfig->PortLane[i].HsioTxGen3DeEmph));
+ }
+
+ DEBUG ((DEBUG_INFO, " RaidAlternateId= %x\n", SataConfig->Rst.RaidAlternateId));
+ DEBUG ((DEBUG_INFO, " Raid0= %x\n", SataConfig->Rst.Raid0));
+ DEBUG ((DEBUG_INFO, " Raid1= %x\n", SataConfig->Rst.Raid1));
+ DEBUG ((DEBUG_INFO, " Raid10= %x\n", SataConfig->Rst.Raid10));
+ DEBUG ((DEBUG_INFO, " Raid5= %x\n", SataConfig->Rst.Raid5));
+ DEBUG ((DEBUG_INFO, " Irrt= %x\n", SataConfig->Rst.Irrt));
+ DEBUG ((DEBUG_INFO, " OromUiBanner= %x\n", SataConfig->Rst.OromUiBanner));
+ DEBUG ((DEBUG_INFO, " OromUiDelay= %x\n", SataConfig->Rst.OromUiDelay));
+ DEBUG ((DEBUG_INFO, " HddUnlock= %x\n", SataConfig->Rst.HddUnlock));
+ DEBUG ((DEBUG_INFO, " LedLocate= %x\n", SataConfig->Rst.LedLocate));
+ DEBUG ((DEBUG_INFO, " IrrtOnly= %x\n", SataConfig->Rst.IrrtOnly));
+ DEBUG ((DEBUG_INFO, " SmartStorage= %x\n", SataConfig->Rst.SmartStorage));
+
+ DEBUG ((DEBUG_INFO, " SpeedSupport= %x\n", SataConfig->SpeedLimit));
+ DEBUG ((DEBUG_INFO, " eSATASpeedLimit= %x\n", SataConfig->eSATASpeedLimit));
+ DEBUG ((DEBUG_INFO, " TestMode= %x\n", SataConfig->TestMode));
+ DEBUG ((DEBUG_INFO, " SalpSupport= %x\n", SataConfig->SalpSupport));
+ DEBUG ((DEBUG_INFO, " PwrOptEnable= %x\n", SataConfig->PwrOptEnable));
+
+ for (i = 0; i < PCH_MAX_RST_PCIE_STORAGE_CR; i++) {
+ DEBUG ((DEBUG_INFO, " RstPcieStorageRemap[%d].Enable = %x\n", i, SataConfig->RstPcieStorageRemap[i].Enable));
+ DEBUG ((DEBUG_INFO, " RstPcieStorageRemap[%d].RstPcieStoragePort = %x\n", i, SataConfig->RstPcieStorageRemap[i].RstPcieStoragePort));
+ DEBUG ((DEBUG_INFO, " RstPcieStorageRemap[%d].DeviceResetDelay = %x\n", i, SataConfig->RstPcieStorageRemap[i].DeviceResetDelay));
+ }
+}
+
+/**
+ Print PCH_IOAPIC_CONFIG and serial out.
+
+ @param[in] IoApicConfig Pointer to a PCH_IOAPIC_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintIoApicConfig (
+ IN CONST PCH_IOAPIC_CONFIG *IoApicConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ PCH IOAPIC Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, " BdfValid= %x\n", IoApicConfig->BdfValid));
+ DEBUG ((DEBUG_INFO, " BusNumber= %x\n", IoApicConfig->BusNumber));
+ DEBUG ((DEBUG_INFO, " DeviceNumber= %x\n", IoApicConfig->DeviceNumber));
+ DEBUG ((DEBUG_INFO, " FunctionNumber= %x\n", IoApicConfig->FunctionNumber));
+ DEBUG ((DEBUG_INFO, " IoApicId= %x\n", IoApicConfig->IoApicId));
+ DEBUG ((DEBUG_INFO, " ApicRangeSelect= %x\n", IoApicConfig->ApicRangeSelect));
+ DEBUG ((DEBUG_INFO, " IoApicEntry24_119= %x\n", IoApicConfig->IoApicEntry24_119));
+}
+
+/**
+ Print PCH_HPET_CONFIG and serial out.
+
+ @param[in] HpetConfig Pointer to a PCH_HPET_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintHpetConfig (
+ IN CONST PCH_HPET_CONFIG *HpetConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ PCH HPET Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, " Enable %x\n", HpetConfig->Enable));
+ DEBUG ((DEBUG_INFO, " BdfValid %x\n", HpetConfig->BdfValid));
+ DEBUG ((DEBUG_INFO, " BusNumber %x\n", HpetConfig->BusNumber));
+ DEBUG ((DEBUG_INFO, " DeviceNumber %x\n", HpetConfig->DeviceNumber));
+ DEBUG ((DEBUG_INFO, " FunctionNumber %x\n", HpetConfig->FunctionNumber));
+ DEBUG ((DEBUG_INFO, " Base %x\n", HpetConfig->Base));
+}
+
+/**
+ Print PCH_LOCK_DOWN_CONFIG and serial out.
+
+ @param[in] LockDownConfig Pointer to a PCH_LOCK_DOWN_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintLockDownConfig (
+ IN CONST PCH_LOCK_DOWN_CONFIG *LockDownConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ PCH Lock Down Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, " GlobalSmi= %x\n", LockDownConfig->GlobalSmi));
+ DEBUG ((DEBUG_INFO, " BiosInterface= %x\n", LockDownConfig->BiosInterface));
+ DEBUG ((DEBUG_INFO, " RtcLock= %x\n", LockDownConfig->RtcLock));
+ DEBUG ((DEBUG_INFO, " BiosLock= %x\n", LockDownConfig->BiosLock));
+ DEBUG ((DEBUG_INFO, " SpiEiss= %x\n", LockDownConfig->SpiEiss));
+}
+
+/**
+ Print PCH_SMBUS_CONFIG and serial out.
+
+ @param[in] SmbusConfig Pointer to a PCH_SMBUS_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintSmbusConfig (
+ IN CONST PCH_SMBUS_CONFIG *SmbusConfig
+ )
+{
+ UINT32 i;
+
+ DEBUG ((DEBUG_INFO, "------------------ PCH SMBUS Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, " Enable= %x\n", SmbusConfig->Enable));
+ DEBUG ((DEBUG_INFO, " ArpEnable= %x\n", SmbusConfig->ArpEnable));
+ DEBUG ((DEBUG_INFO, " DynamicPowerGating= %x\n", SmbusConfig->DynamicPowerGating));
+ DEBUG ((DEBUG_INFO, " SmbusIoBase= %x\n", SmbusConfig->SmbusIoBase));
+ DEBUG ((DEBUG_INFO, " NumRsvdSmbusAddresses= %x\n", SmbusConfig->NumRsvdSmbusAddresses));
+ DEBUG ((DEBUG_INFO, " RsvdSmbusAddressTable= {"));
+ for (i = 0; i < SmbusConfig->NumRsvdSmbusAddresses; ++i) {
+ DEBUG ((DEBUG_INFO, " %02xh", SmbusConfig->RsvdSmbusAddressTable[i]));
+ }
+ DEBUG ((DEBUG_INFO, " }\n"));
+}
+
+/**
+ Print PCH_HDAUDIO_CONFIG and serial out.
+
+ @param[in] HdaConfig Pointer to a PCH_HDAUDIO_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintHdAudioConfig (
+ IN CONST PCH_HDAUDIO_CONFIG *HdaConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ PCH HD-Audio Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, " HDA Enable = %x\n", HdaConfig->Enable));
+ DEBUG ((DEBUG_INFO, " DSP Enable = %x\n", HdaConfig->DspEnable));
+ DEBUG ((DEBUG_INFO, " DSP UAA Compliance = %x\n", HdaConfig->DspUaaCompliance));
+ DEBUG ((DEBUG_INFO, " iDisp Codec Disconnect = %x\n", HdaConfig->IDispCodecDisconnect));
+ DEBUG ((DEBUG_INFO, " Pme = %x\n", HdaConfig->Pme));
+ DEBUG ((DEBUG_INFO, " I/O Buffer Ownership = %x\n", HdaConfig->IoBufferOwnership));
+ DEBUG ((DEBUG_INFO, " I/O Buffer Voltage = %x\n", HdaConfig->IoBufferVoltage));
+ DEBUG ((DEBUG_INFO, " VC Type = %x\n", HdaConfig->VcType));
+ DEBUG ((DEBUG_INFO, " HD-A Link Frequency = %x\n", HdaConfig->HdAudioLinkFrequency));
+ DEBUG ((DEBUG_INFO, " iDisp Link Frequency = %x\n", HdaConfig->IDispLinkFrequency));
+ DEBUG ((DEBUG_INFO, " iDisp Link T-Mode = %x\n", HdaConfig->IDispLinkTmode));
+ DEBUG ((DEBUG_INFO, " DSP Endpoint DMIC = %x\n", HdaConfig->DspEndpointDmic));
+ DEBUG ((DEBUG_INFO, " DSP Endpoint I2S = %x\n", HdaConfig->DspEndpointI2s));
+ DEBUG ((DEBUG_INFO, " DSP Endpoint BT = %x\n", HdaConfig->DspEndpointBluetooth));
+ DEBUG ((DEBUG_INFO, " DSP Feature Mask = %x\n", HdaConfig->DspFeatureMask));
+ DEBUG ((DEBUG_INFO, " DSP PP Module Mask = %x\n", HdaConfig->DspPpModuleMask));
+ DEBUG ((DEBUG_INFO, " ResetWaitTimer = %x\n", HdaConfig->ResetWaitTimer));
+}
+
+/**
+ Print PCH_PM_CONFIG and serial out.
+
+ @param[in] PmConfig Pointer to a PCH_PM_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintPmConfig (
+ IN CONST PCH_PM_CONFIG *PmConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ PCH PM Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, " PowerResetStatusClear MeWakeSts = %x\n", PmConfig->PowerResetStatusClear.MeWakeSts));
+ DEBUG ((DEBUG_INFO, " PowerResetStatusClear MeHrstColdSts = %x\n", PmConfig->PowerResetStatusClear.MeHrstColdSts));
+ DEBUG ((DEBUG_INFO, " PowerResetStatusClear MeHrstWarmSts = %x\n", PmConfig->PowerResetStatusClear.MeHrstWarmSts));
+ DEBUG ((DEBUG_INFO, " PowerResetStatusClear MeHostPowerDn = %x\n", PmConfig->PowerResetStatusClear.MeHostPowerDn));
+ DEBUG ((DEBUG_INFO, " PowerResetStatusClear WolOvrWkSts = %x\n", PmConfig->PowerResetStatusClear.WolOvrWkSts));
+
+ DEBUG ((DEBUG_INFO, " WakeConfig PmeB0S5Dis = %x\n", PmConfig->WakeConfig.PmeB0S5Dis));
+ DEBUG ((DEBUG_INFO, " WakeConfig WolEnableOverride = %x\n", PmConfig->WakeConfig.WolEnableOverride));
+ DEBUG ((DEBUG_INFO, " WakeConfig LanWakeFromDeepSx = %x\n", PmConfig->WakeConfig.LanWakeFromDeepSx));
+ DEBUG ((DEBUG_INFO, " WakeConfig PcieWakeFromDeepSx = %x\n", PmConfig->WakeConfig.PcieWakeFromDeepSx));
+ DEBUG ((DEBUG_INFO, " WakeConfig WoWlanEnable = %x\n", PmConfig->WakeConfig.WoWlanEnable));
+ DEBUG ((DEBUG_INFO, " WakeConfig WoWlanDeepSxEnable = %x\n", PmConfig->WakeConfig.WoWlanDeepSxEnable));
+
+ DEBUG ((DEBUG_INFO, " PchDeepSxPol = %x\n", PmConfig->PchDeepSxPol));
+ DEBUG ((DEBUG_INFO, " PchSlpS3MinAssert = %x\n", PmConfig->PchSlpS3MinAssert));
+ DEBUG ((DEBUG_INFO, " PchSlpS4MinAssert = %x\n", PmConfig->PchSlpS4MinAssert));
+ DEBUG ((DEBUG_INFO, " PchSlpSusMinAssert = %x\n", PmConfig->PchSlpSusMinAssert));
+ DEBUG ((DEBUG_INFO, " PchSlpAMinAssert = %x\n", PmConfig->PchSlpAMinAssert));
+ DEBUG ((DEBUG_INFO, " PciClockRun = %x\n", PmConfig->PciClockRun));
+ DEBUG ((DEBUG_INFO, " SlpStrchSusUp = %x\n", PmConfig->SlpStrchSusUp));
+ DEBUG ((DEBUG_INFO, " SlpLanLowDc = %x\n", PmConfig->SlpLanLowDc));
+ DEBUG ((DEBUG_INFO, " PwrBtnOverridePeriod = %x\n", PmConfig->PwrBtnOverridePeriod));
+ DEBUG ((DEBUG_INFO, " DisableEnergyReport = %x\n", PmConfig->DisableEnergyReport));
+ DEBUG ((DEBUG_INFO, " DisableDsxAcPresentPulldown = %x\n", PmConfig->DisableDsxAcPresentPulldown));
+ DEBUG ((DEBUG_INFO, " PmcReadDisable = %x\n", PmConfig->PmcReadDisable));
+ DEBUG ((DEBUG_INFO, " PchPwrCycDur = %x\n", PmConfig->PchPwrCycDur));
+ DEBUG ((DEBUG_INFO, " PciePllSsc = %x\n", PmConfig->PciePllSsc));
+ DEBUG ((DEBUG_INFO, " CapsuleResetType = %x\n", PmConfig->CapsuleResetType));
+ DEBUG ((DEBUG_INFO, " DisableNativePowerButton = %x\n", PmConfig->DisableNativePowerButton));
+ DEBUG ((DEBUG_INFO, " SlpS0Enabled = %x\n", PmConfig->SlpS0Enable));
+}
+
+/**
+ Print PCH_DMI_CONFIG and serial out.
+
+ @param[in] DmiConfig Pointer to a PCH_DMI_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintDmiConfig (
+ IN CONST PCH_DMI_CONFIG *DmiConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ PCH DMI Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, " DmiAspm= %x\n", DmiConfig->DmiAspm));
+ DEBUG ((DEBUG_INFO, " PwrOptEnable= %x\n", DmiConfig->PwrOptEnable));
+
+}
+
+/**
+ Print PCH_LPC_SIRQ_CONFIG and serial out.
+
+ @param[in] SerialIrqConfig Pointer to a PCH_LPC_SIRQ_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintSerialIrqConfig (
+ IN CONST PCH_LPC_SIRQ_CONFIG *SerialIrqConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ PCH LPC SIRQ Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, " SirqEnable= %x\n", SerialIrqConfig->SirqEnable));
+ DEBUG ((DEBUG_INFO, " SirqMode= %x\n", SerialIrqConfig->SirqMode));
+ DEBUG ((DEBUG_INFO, " StartFramePulse= %x\n", SerialIrqConfig->StartFramePulse));
+}
+
+/**
+ Print PCH_THERMAL_CONFIG and serial out.
+
+ @param[in] ThermalConfig Pointer to a PCH_THERMAL_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintThermalConfig (
+ IN CONST PCH_THERMAL_CONFIG *ThermalConfig
+ )
+{
+ UINTN i;
+
+ DEBUG ((DEBUG_INFO, "------------------ PCH Thermal Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, " TsmicLock= %x\n", ThermalConfig->TsmicLock));
+ DEBUG ((DEBUG_INFO, " ThermalThrottling TTLevels T0Level %x centigrade degree\n", ThermalConfig->ThermalThrottling.TTLevels.T0Level));
+ DEBUG ((DEBUG_INFO, " ThermalThrottling TTLevels T1Level %x centigrade degree\n", ThermalConfig->ThermalThrottling.TTLevels.T1Level));
+ DEBUG ((DEBUG_INFO, " ThermalThrottling TTLevels T2Level %x centigrade degree\n", ThermalConfig->ThermalThrottling.TTLevels.T2Level));
+ DEBUG ((DEBUG_INFO, " ThermalThrottling TTLevels TTEnable %x\n", ThermalConfig->ThermalThrottling.TTLevels.TTEnable));
+ DEBUG ((DEBUG_INFO, " ThermalThrottling TTLevels TTState13Enable %x\n", ThermalConfig->ThermalThrottling.TTLevels.TTState13Enable));
+ DEBUG ((DEBUG_INFO, " ThermalThrottling TTLevels TTLock %x\n", ThermalConfig->ThermalThrottling.TTLevels.TTLock));
+ DEBUG ((DEBUG_INFO, " ThermalThrottling TTLevels SuggestedSetting %x\n", ThermalConfig->ThermalThrottling.TTLevels.SuggestedSetting));
+ DEBUG ((DEBUG_INFO, " ThermalThrottling TTLevels PchCrossThrottling %x\n", ThermalConfig->ThermalThrottling.TTLevels.PchCrossThrottling));
+
+ DEBUG ((DEBUG_INFO, " ThermalThrottling DmiHaAWC DmiTsawEn %x\n", ThermalConfig->ThermalThrottling.DmiHaAWC.DmiTsawEn));
+ DEBUG ((DEBUG_INFO, " ThermalThrottling DmiHaAWC TS0TW %x\n", ThermalConfig->ThermalThrottling.DmiHaAWC.TS0TW));
+ DEBUG ((DEBUG_INFO, " ThermalThrottling DmiHaAWC TS1TW %x\n", ThermalConfig->ThermalThrottling.DmiHaAWC.TS1TW));
+ DEBUG ((DEBUG_INFO, " ThermalThrottling DmiHaAWC TS2TW %x\n", ThermalConfig->ThermalThrottling.DmiHaAWC.TS2TW));
+ DEBUG ((DEBUG_INFO, " ThermalThrottling DmiHaAWC TS3TW %x\n", ThermalConfig->ThermalThrottling.DmiHaAWC.TS3TW));
+ DEBUG ((DEBUG_INFO, " ThermalThrottling DmiHaAWC SuggestedSetting %x\n", ThermalConfig->ThermalThrottling.DmiHaAWC.SuggestedSetting));
+
+ DEBUG ((DEBUG_INFO, " ThermalThrottling SataTT P0T1M %x\n", ThermalConfig->ThermalThrottling.SataTT.P0T1M));
+ DEBUG ((DEBUG_INFO, " ThermalThrottling SataTT P0T2M %x\n", ThermalConfig->ThermalThrottling.SataTT.P0T2M));
+ DEBUG ((DEBUG_INFO, " ThermalThrottling SataTT P0T3M %x\n", ThermalConfig->ThermalThrottling.SataTT.P0T3M));
+ DEBUG ((DEBUG_INFO, " ThermalThrottling SataTT P0TDisp %x\n", ThermalConfig->ThermalThrottling.SataTT.P0TDisp));
+ DEBUG ((DEBUG_INFO, " ThermalThrottling SataTT P0Tinact %x\n", ThermalConfig->ThermalThrottling.SataTT.P0Tinact));
+ DEBUG ((DEBUG_INFO, " ThermalThrottling SataTT P0TDispFinit %x\n", ThermalConfig->ThermalThrottling.SataTT.P0TDispFinit));
+ DEBUG ((DEBUG_INFO, " ThermalThrottling SataTT P1T1M %x\n", ThermalConfig->ThermalThrottling.SataTT.P1T1M));
+ DEBUG ((DEBUG_INFO, " ThermalThrottling SataTT P1T2M %x\n", ThermalConfig->ThermalThrottling.SataTT.P1T2M));
+ DEBUG ((DEBUG_INFO, " ThermalThrottling SataTT P1T3M %x\n", ThermalConfig->ThermalThrottling.SataTT.P1T3M));
+ DEBUG ((DEBUG_INFO, " ThermalThrottling SataTT P1TDisp %x\n", ThermalConfig->ThermalThrottling.SataTT.P1TDisp));
+ DEBUG ((DEBUG_INFO, " ThermalThrottling SataTT P1Tinact %x\n", ThermalConfig->ThermalThrottling.SataTT.P1Tinact));
+ DEBUG ((DEBUG_INFO, " ThermalThrottling SataTT P1TDispFinit %x\n", ThermalConfig->ThermalThrottling.SataTT.P1TDispFinit));
+ DEBUG ((DEBUG_INFO, " ThermalThrottling SataTT SuggestedSetting %x\n", ThermalConfig->ThermalThrottling.SataTT.SuggestedSetting));
+
+ DEBUG ((DEBUG_INFO, " MemoryThrottling Enable= %x\n", ThermalConfig->MemoryThrottling.Enable));
+ for (i = 0; i < MaxTsGpioPin; i++) {
+ DEBUG ((DEBUG_INFO, " MemoryThrottling TsGpioPinSetting PmsyncEnable= %x\n", ThermalConfig->MemoryThrottling.TsGpioPinSetting[i].PmsyncEnable));
+ DEBUG ((DEBUG_INFO, " MemoryThrottling TsGpioPinSetting C0TransmitEnable= %x\n", ThermalConfig->MemoryThrottling.TsGpioPinSetting[i].C0TransmitEnable));
+ DEBUG ((DEBUG_INFO, " MemoryThrottling TsGpioPinSetting PinSelection= %x\n", ThermalConfig->MemoryThrottling.TsGpioPinSetting[i].PinSelection));
+ }
+ DEBUG ((DEBUG_INFO, " PchHotLevel = %x\n", ThermalConfig->PchHotLevel));
+ DEBUG ((DEBUG_INFO, " ThermalDeviceEnable %x\n", ThermalConfig->ThermalDeviceEnable));
+}
+
+/**
+ Print PCH_GENERAL_CONFIG and serial out.
+
+ @param[in] PchConfig Pointer to a PCH_GENERAL_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintGeneralConfig (
+ IN CONST PCH_GENERAL_CONFIG *PchConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ PCH General Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, " SubSystemVendorId= %x\n", PchConfig->SubSystemVendorId));
+ DEBUG ((DEBUG_INFO, " SubSystemId= %x\n", PchConfig->SubSystemId));
+ DEBUG ((DEBUG_INFO, " Crid= %x\n", PchConfig->Crid));
+}
+
+/**
+ Print PCH_LAN_CONFIG and serial out.
+
+ @param[in] LanConfig Pointer to a PCH_LAN_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintLanConfig (
+ IN CONST PCH_LAN_CONFIG *LanConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ PCH LAN Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, " Enable= %x\n", LanConfig->Enable));
+ DEBUG ((DEBUG_INFO, " K1OffEnable= %x\n", LanConfig->K1OffEnable));
+ DEBUG ((DEBUG_INFO, " ClkReqSupported= %d\n", LanConfig->ClkReqSupported));
+ DEBUG ((DEBUG_INFO, " ClkReqNumber= %d\n", LanConfig->ClkReqNumber));
+}
+
+
+/**
+ Print PCH_INTERRUPT_CONFIG and serial out
+
+ @param[in] InterruptConfig Pointer to Interrupt Configuration structure
+
+**/
+VOID
+PchPrintInterruptConfig (
+ IN CONST PCH_INTERRUPT_CONFIG *InterruptConfig
+ )
+{
+ UINTN i;
+ //
+ // Print interrupt information
+ //
+ DEBUG ((DEBUG_INFO, "------------------ PCH Interrupt Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, " Interrupt assignment:\n"));
+ DEBUG ((DEBUG_INFO, " Dxx:Fx INTx IRQ\n"));
+ for (i = 0; i < InterruptConfig->NumOfDevIntConfig; i++) {
+ DEBUG ((DEBUG_INFO, " D%02d:F%d %d %03d\n",
+ InterruptConfig->DevIntConfig[i].Device,
+ InterruptConfig->DevIntConfig[i].Function,
+ InterruptConfig->DevIntConfig[i].IntX,
+ InterruptConfig->DevIntConfig[i].Irq));
+ }
+ DEBUG ((DEBUG_INFO, " Legacy PIC interrupt routing:\n"));
+ DEBUG ((DEBUG_INFO, " PIRQx IRQx\n"));
+ for (i = 0; i < PCH_MAX_PXRC_CONFIG; i++) {
+ DEBUG ((DEBUG_INFO, " PIRQ%c -> IRQ%d\n", i + 65, InterruptConfig->PxRcConfig[i]));
+ }
+ DEBUG ((DEBUG_INFO, " Other interrupt configuration:\n"));
+ DEBUG ((DEBUG_INFO, " GpioIrqRoute= %d\n", InterruptConfig->GpioIrqRoute));
+ DEBUG ((DEBUG_INFO, " SciIrqSelect= %d\n", InterruptConfig->SciIrqSelect));
+ DEBUG ((DEBUG_INFO, " TcoIrqEnable= %d\n", InterruptConfig->TcoIrqEnable));
+ DEBUG ((DEBUG_INFO, " TcoIrqSelect= %d\n", InterruptConfig->TcoIrqSelect));
+}
+
+
+/**
+ Print PCH_FLASH_PROTECTION_CONFIG and serial out.
+
+ @param[in] FlashProtectConfig Pointer to a PCH_FLASH_PROTECTION_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintFlashProtectionConfig (
+ IN CONST PCH_FLASH_PROTECTION_CONFIG *FlashProtectConfig
+ )
+{
+ UINT32 i;
+
+ DEBUG ((DEBUG_INFO, "------------------ PCH Flash Protection Config ------------------\n"));
+ for (i = 0; i < PCH_FLASH_PROTECTED_RANGES; ++i) {
+ DEBUG ((DEBUG_INFO, " WriteProtectionEnable[%d]= %x\n", i, FlashProtectConfig->ProtectRange[i].WriteProtectionEnable));
+ DEBUG ((DEBUG_INFO, " ReadProtectionEnable[%d]= %x\n", i, FlashProtectConfig->ProtectRange[i].ReadProtectionEnable));
+ DEBUG ((DEBUG_INFO, " ProtectedRangeLimit[%d]= %x\n", i, FlashProtectConfig->ProtectRange[i].ProtectedRangeLimit));
+ DEBUG ((DEBUG_INFO, " ProtectedRangeBase[%d]= %x\n", i, FlashProtectConfig->ProtectRange[i].ProtectedRangeBase));
+ }
+}
+
+/**
+ Print PCH_WDT_CONFIG and serial out.
+
+ @param[in] WdtConfig Pointer to a PCH_WDT_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintWdtConfig (
+ IN CONST PCH_WDT_CONFIG *WdtConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ PCH WDT Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, "DisableAndLock= %x\n", WdtConfig->DisableAndLock));
+}
+
+/**
+ Print PCH_P2SB_CONFIG and serial out.
+
+ @param[in] P2sbConfig Pointer to a PCH_P2SB_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintP2sbConfig (
+ IN CONST PCH_P2SB_CONFIG *P2sbConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ PCH P2SB Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, "SbiUnlock= %x\n", P2sbConfig->SbiUnlock));
+ DEBUG ((DEBUG_INFO, "PsfUnlock= %x\n", P2sbConfig->PsfUnlock));
+}
+
+/**
+ Print PCH_DCI_CONFIG and serial out.
+
+ @param[in] DciConfig Pointer to a PCH_DCI_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintDciConfig (
+ IN CONST PCH_DCI_CONFIG *DciConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ PCH DCI Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, "DciEn= %x\n", DciConfig->DciEn));
+ DEBUG ((DEBUG_INFO, "DciAutoDetect= %x\n", DciConfig->DciAutoDetect));
+}
+
+/**
+ Print PCH_LPC_CONFIG and serial out.
+
+ @param[in] LpcConfig Pointer to a PCH_LPC_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintLpcConfig (
+ IN CONST PCH_LPC_CONFIG *LpcConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ PCH LPC Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, "EnhancePort8xhDecoding= %x\n", LpcConfig->EnhancePort8xhDecoding));
+}
+
+/**
+ Print PCH_SPI_CONFIG and serial out.
+
+ @param[in] SpiConfig Pointer to a PCH_SPI_CONFIG that provides the platform setting
+
+**/
+VOID
+PchPrintSpiConfig (
+ IN CONST PCH_SPI_CONFIG *SpiConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ PCH SPI Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, "ShowSpiController= %x\n", SpiConfig->ShowSpiController));
+}
+
+/**
+ Print whole PCH_POLICY_PPI and serial out.
+
+ @param[in] PchPolicyPpi The RC Policy PPI instance
+
+**/
+VOID
+PchPrintPolicyPpi (
+ IN PCH_POLICY_PPI *PchPolicyPpi
+ )
+{
+DEBUG_CODE_BEGIN();
+ DEBUG ((DEBUG_INFO, "------------------------ PCH Print Platform Protocol Start ------------------------\n"));
+ DEBUG ((DEBUG_INFO, " Revision= %x\n", PchPolicyPpi->Revision));
+ DEBUG ((DEBUG_INFO, " Port80Route= %x\n", PchPolicyPpi->Port80Route));
+ DEBUG ((DEBUG_INFO, " AcpiBase= %x\n", PchPolicyPpi->AcpiBase));
+
+ PchPrintGeneralConfig (&PchPolicyPpi->PchConfig);
+
+ PchPrintPcieConfig (&PchPolicyPpi->PcieConfig, &PchPolicyPpi->HsioPcieConfig);
+
+ PchPrintPcieConfig2 (&PchPolicyPpi->PcieConfig2);
+
+ PchPrintSataConfig (&PchPolicyPpi->SataConfig, &PchPolicyPpi->HsioSataConfig, PCH_SATA_FIRST_CONTROLLER);
+ PchPrintSataConfig (&PchPolicyPpi->sSataConfig, &PchPolicyPpi->HsiosSataConfig, PCH_SATA_SECOND_CONTROLLER);
+ PchPrintUsbConfig (&PchPolicyPpi->UsbConfig);
+
+ PchPrintIoApicConfig (&PchPolicyPpi->IoApicConfig);
+
+ PchPrintHpetConfig (&PchPolicyPpi->HpetConfig);
+
+ PchPrintHdAudioConfig (&PchPolicyPpi->HdAudioConfig);
+
+ PchPrintLanConfig (&PchPolicyPpi->LanConfig);
+
+ PchPrintSmbusConfig (&PchPolicyPpi->SmbusConfig);
+
+ PchPrintLockDownConfig (&PchPolicyPpi->LockDownConfig);
+
+ PchPrintThermalConfig (&PchPolicyPpi->ThermalConfig);
+
+ PchPrintPmConfig (&PchPolicyPpi->PmConfig);
+
+ PchPrintDmiConfig (&PchPolicyPpi->DmiConfig);
+
+ PchPrintSerialIrqConfig (&PchPolicyPpi->SerialIrqConfig);
+
+
+ PchPrintFlashProtectionConfig (&PchPolicyPpi->FlashProtectConfig);
+
+ PchPrintWdtConfig (&PchPolicyPpi->WdtConfig);
+
+ PchPrintP2sbConfig (&PchPolicyPpi->P2sbConfig);
+
+ PchPrintDciConfig (&PchPolicyPpi->DciConfig);
+
+ PchPrintLpcConfig (&PchPolicyPpi->LpcConfig);
+
+ PchPrintSpiConfig (&PchPolicyPpi->SpiConfig);
+
+ DEBUG ((DEBUG_INFO, "------------------------ PCH Print Platform Protocol End --------------------------\n"));
+DEBUG_CODE_END();
+}
+
diff --git a/Silicon/Intel/LewisburgPkg/Library/PeiPchPolicyLib/PeiPchPolicyLib.c b/Silicon/Intel/LewisburgPkg/Library/PeiPchPolicyLib/PeiPchPolicyLib.c
new file mode 100644
index 0000000000..f5ec0d5fb1
--- /dev/null
+++ b/Silicon/Intel/LewisburgPkg/Library/PeiPchPolicyLib/PeiPchPolicyLib.c
@@ -0,0 +1,587 @@
+/** @file
+
+Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+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.
+
+**/
+
+#include "PeiPchPolicyLibrary.h"
+#include <Library/PchPmcLib.h>
+
+/**
+ mDevIntConfig[] table contains data on INTx and IRQ for each device.
+ IRQ value for devices which use ITSS INTx->PIRQx mapping need to be set in a way
+ that for each multifunctional Dxx:Fy same interrupt pins must map to the same IRQ.
+ Those IRQ values will be used to update ITSS.PIRx register.
+ In APIC relationship between PIRQs and IRQs is:
+ PIRQA -> IRQ16
+ PIRQB -> IRQ17
+ PIRQC -> IRQ18
+ PIRQD -> IRQ19
+ PIRQE -> IRQ20
+ PIRQF -> IRQ21
+ PIRQG -> IRQ22
+ PIRQH -> IRQ23
+
+ Devices which use INTx->PIRQy mapping are: cAVS(in PCI mode), SMBus, GbE, TraceHub, PCIe,
+ SATA, HECI, IDE-R, KT Redirection, xHCI, Thermal Subsystem, Camera IO Host Controller
+
+ PCI Express Root Ports mapping should be programmed only with values as in below table (D27/28/29)
+ otherwise _PRT methods in ACPI for RootPorts would require additional patching as
+ PCIe Endpoint Device Interrupt is further subjected to INTx to PIRQy Mapping
+
+ Configured IRQ values are not used if an OS chooses to be in PIC instead of APIC mode
+**/
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_DEVICE_INTERRUPT_CONFIG mDevIntConfig[] = {
+// {31, 0, PchNoInt, 0}, // LPC/eSPI Interface, doesn't use interrupts
+// {31, 1, PchNoInt, 0}, // P2SB, doesn't use interrupts
+// {31, 2, PchNoInt, 0}, // PMC , doesn't use interrupts
+ {31, 3, PchIntA, 16}, // cAVS(Audio, Voice, Speach), INTA is default, programmed in PciCfgSpace 3Dh
+ {31, 4, PchIntA, 16}, // SMBus Controller, no default value, programmed in PciCfgSpace 3Dh
+// {31, 5, PchNoInt, 0}, // SPI , doesn't use interrupts
+ {31, 6, PchIntA, 16}, // GbE Controller, INTA is default, programmed in PciCfgSpace 3Dh
+ {31, 7, PchIntA, 16}, // TraceHub, INTA is default, RO register
+ {29, 0, PchIntA, 16}, // PCI Express Port 9, INT is default, programmed in PciCfgSpace + FCh
+ {29, 1, PchIntB, 17}, // PCI Express Port 10, INT is default, programmed in PciCfgSpace + FCh
+ {29, 2, PchIntC, 18}, // PCI Express Port 11, INT is default, programmed in PciCfgSpace + FCh
+ {29, 3, PchIntD, 19}, // PCI Express Port 12, INT is default, programmed in PciCfgSpace + FCh
+ {29, 4, PchIntA, 16}, // PCI Express Port 13 (SKL PCH-H Only), INT is default, programmed in PciCfgSpace + FCh
+ {29, 5, PchIntB, 17}, // PCI Express Port 14 (SKL PCH-H Only), INT is default, programmed in PciCfgSpace + FCh
+ {29, 6, PchIntC, 18}, // PCI Express Port 15 (SKL PCH-H Only), INT is default, programmed in PciCfgSpace + FCh
+ {29, 7, PchIntD, 19}, // PCI Express Port 16 (SKL PCH-H Only), INT is default, programmed in PciCfgSpace + FCh
+ {28, 0, PchIntA, 16}, // PCI Express Port 1, INT is default, programmed in PciCfgSpace + FCh
+ {28, 1, PchIntB, 17}, // PCI Express Port 2, INT is default, programmed in PciCfgSpace + FCh
+ {28, 2, PchIntC, 18}, // PCI Express Port 3, INT is default, programmed in PciCfgSpace + FCh
+ {28, 3, PchIntD, 19}, // PCI Express Port 4, INT is default, programmed in PciCfgSpace + FCh
+ {28, 4, PchIntA, 16}, // PCI Express Port 5, INT is default, programmed in PciCfgSpace + FCh
+ {28, 5, PchIntB, 17}, // PCI Express Port 6, INT is default, programmed in PciCfgSpace + FCh
+ {28, 6, PchIntC, 18}, // PCI Express Port 7, INT is default, programmed in PciCfgSpace + FCh
+ {28, 7, PchIntD, 19}, // PCI Express Port 8, INT is default, programmed in PciCfgSpace + FCh
+ {27, 0, PchIntA, 16}, // PCI Express Port 17 (SKL PCH-H Only), INT is default, programmed in PciCfgSpace + FCh
+ {27, 1, PchIntB, 17}, // PCI Express Port 18 (SKL PCH-H Only), INT is default, programmed in PciCfgSpace + FCh
+ {27, 2, PchIntC, 18}, // PCI Express Port 19 (SKL PCH-H Only), INT is default, programmed in PciCfgSpace + FCh
+ {27, 3, PchIntD, 19}, // PCI Express Port 20 (SKL PCH-H Only), INT is default, programmed in PciCfgSpace + FCh
+// {24, 0, 0, 0}, // Reserved (used by RST PCIe Storage Cycle Router)
+ {23, 0, PchIntA, 16}, // SATA Controller, INTA is default, programmed in PciCfgSpace + 3Dh
+ {22, 0, PchIntA, 16}, // CSME: HECI #1
+ {22, 1, PchIntB, 17}, // CSME: HECI #2
+ {22, 2, PchIntC, 18}, // CSME: IDE-Redirection (IDE-R)
+ {22, 3, PchIntD, 19}, // CSME: Keyboard and Text (KT) Redirection
+ {22, 4, PchIntA, 16}, // CSME: HECI #3
+// {22, 7, PchNoInt, 0}, // CSME: WLAN
+ {20, 0, PchIntA, 16}, // USB 3.0 xHCI Controller, no default value, programmed in PciCfgSpace 3Dh
+ {20, 2, PchIntC, 18}, // Thermal Subsystem
+// {20, 4, 0, 0}, // TraceHub Phantom (ACPI) Function
+// {18, 0, PchNoInt, 0}, // CSME: KVMcc, doesn't use interrupts
+// {18, 1, PchNoInt, 0}, // CSME: Clink, doesn't use interrupts
+// {18, 2, PchNoInt, 0}, // CSME: PMT, doesn't use interrupts
+// {18, 3, 0, 0}, // CSME: CSE UMA
+// {18, 4, 0, 0} // CSME: fTPM DMA
+ {17, 5, PchIntA, 16} // SSATA controller.
+#ifdef IE_SUPPORT
+ ,
+// {16, 0, PchIntA, 16}, // IE: HECI #1
+// {16, 1, PchIntB, 17}, // IE: HECI #2
+// {16, 2, PchIntC, 18}, // IE: IDE-Redirection (IDE-R)
+ {16, 3, PchIntD, 19} // IE: Keyboard and Text (KT) Redirection
+// {16, 4, PchIntA, 16} // IE: HECI #3
+#endif // IE_SUPPORT
+};
+
+//
+// mLpOnlyDevIntConfig[] table contains data on INTx and IRQ for devices that exist on SPT-LP but not on SPT-H.
+//
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_DEVICE_INTERRUPT_CONFIG mLpOnlyDevIntConfig[] = {
+ {25, 1, PchIntB, 33}, // SerialIo I2C Controller #5, INTA is default, programmed in PCR[SERIALIO] + PCICFGCTRL[6]
+ {25, 2, PchIntC, 34} // SerialIo I2C Controller #4, INTA is default, programmed in PCR[SERIALIO] + PCICFGCTRL[5]
+};
+/**
+ mPxRcConfig[] table contains data for 8259 routing (how PIRQx is mapped to IRQy).
+ This information is used by systems which choose to use legacy PIC
+ interrupt controller. Only IRQ3-7,9-12,14,15 are valid. Values from this table
+ will be programmed into ITSS.PxRC registers.
+**/
+GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mPxRcConfig[] = {
+ 11, // PARC: PIRQA -> IRQ11
+ 10, // PBRC: PIRQB -> IRQ10
+ 11, // PCRC: PIRQC -> IRQ11
+ 11, // PDRC: PIRQD -> IRQ11
+ 11, // PERC: PIRQE -> IRQ11
+ 11, // PFRC: PIRQF -> IRQ11
+ 11, // PGRC: PIRQG -> IRQ11
+ 11 // PHRC: PIRQH -> IRQ11
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mSmbusRsvdAddresses[] = {
+ 0xA0,
+ 0xA2,
+ 0xA4,
+ 0xA6
+};
+
+/**
+ PchCreatePolicyDefaults creates the default setting of PCH Policy.
+ It allocates and zero out buffer, and fills in the Intel default settings.
+
+ @param[out] PchPolicyPpi The pointer to get PCH Policy PPI instance
+
+ @retval EFI_SUCCESS The policy default is initialized.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create buffer
+**/
+EFI_STATUS
+EFIAPI
+PchCreatePolicyDefaults (
+ OUT PCH_POLICY_PPI **PchPolicyPpi
+ )
+{
+ PCH_POLICY_PPI *PchPolicy;
+ PCH_SERIES PchSeries;
+ UINT32 PortIndex;
+ UINT32 Index;
+ UINT8 IntConfigTableEntries;
+
+ PchSeries = GetPchSeries ();
+
+ PchPolicy = (PCH_POLICY_PPI *) AllocateZeroPool (sizeof (PCH_POLICY_PPI));
+ if (PchPolicy == NULL) {
+ ASSERT (FALSE);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Policy not listed here are set to 0/FALSE as default.
+ //
+
+ /********************************
+ General initialization
+ ********************************/
+ PchPolicy->Revision = PCH_POLICY_REVISION;
+ PchPolicy->AcpiBase = PcdGet16 (PcdPchAcpiIoPortBaseAddress);
+ PchPolicy->TempMemBaseAddr = PCH_TEMP_BASE_ADDRESS;
+
+ /********************************
+ PCH general configuration
+ ********************************/
+ //
+ // Default Svid Sdid configuration
+ //
+ PchPolicy->PchConfig.SubSystemVendorId = V_PCH_INTEL_VENDOR_ID;
+ PchPolicy->PchConfig.SubSystemId = V_PCH_DEFAULT_SID;
+
+ /********************************
+ PCI Express related settings
+ ********************************/
+
+ PchPolicy->TempPciBusMin = 2;
+ PchPolicy->TempPciBusMax = 10;
+
+ PchPolicy->PcieConfig.RpFunctionSwap = TRUE;
+
+ for (PortIndex = 0; PortIndex < GetPchMaxPciePortNum (); PortIndex++) {
+ PchPolicy->PcieConfig.RootPort[PortIndex].Aspm = PchPcieAspmAutoConfig;
+ PchPolicy->PcieConfig.RootPort[PortIndex].Enable = TRUE;
+ PchPolicy->PcieConfig.RootPort[PortIndex].PmSci = TRUE;
+ PchPolicy->PcieConfig.RootPort[PortIndex].AcsEnabled = TRUE;
+
+ PchPolicy->PcieConfig.RootPort[PortIndex].MaxPayload = PchPcieMaxPayload256;
+
+ PchPolicy->PcieConfig.RootPort[PortIndex].PhysicalSlotNumber = (UINT8) PortIndex;
+
+ PchPolicy->PcieConfig.RootPort[PortIndex].L1Substates = PchPcieL1SubstatesL1_1_2;
+
+ //
+ // PCIe LTR Configuration.
+ //
+ PchPolicy->PcieConfig.RootPort[PortIndex].LtrEnable = TRUE;
+ if (PchSeries == PchLp) {
+ PchPolicy->PcieConfig.RootPort[PortIndex].LtrMaxSnoopLatency = 0x1003;
+ PchPolicy->PcieConfig.RootPort[PortIndex].LtrMaxNoSnoopLatency = 0x1003;
+ }
+ if (PchSeries == PchH) {
+ PchPolicy->PcieConfig.RootPort[PortIndex].LtrMaxSnoopLatency = 0x0846;
+ PchPolicy->PcieConfig.RootPort[PortIndex].LtrMaxNoSnoopLatency = 0x0846;
+ }
+ PchPolicy->PcieConfig.RootPort[PortIndex].SnoopLatencyOverrideMode = 2;
+ PchPolicy->PcieConfig.RootPort[PortIndex].SnoopLatencyOverrideMultiplier = 2;
+ PchPolicy->PcieConfig.RootPort[PortIndex].SnoopLatencyOverrideValue = 60;
+ PchPolicy->PcieConfig.RootPort[PortIndex].NonSnoopLatencyOverrideMode = 2;
+ PchPolicy->PcieConfig.RootPort[PortIndex].NonSnoopLatencyOverrideMultiplier = 2;
+ PchPolicy->PcieConfig.RootPort[PortIndex].NonSnoopLatencyOverrideValue = 60;
+
+ PchPolicy->PcieConfig.RootPort[PortIndex].Uptp = 5;
+ PchPolicy->PcieConfig.RootPort[PortIndex].Dptp = 7;
+ }
+
+ for (Index = 0; Index < GetPchMaxPciePortNum (); ++Index) {
+ PchPolicy->PcieConfig.EqPh3LaneParam[Index].Cm = 6;
+ PchPolicy->PcieConfig.EqPh3LaneParam[Index].Cp = 6;
+ }
+
+ PchPolicy->PcieConfig2.SwEqCoeffList[0].Cm = 6;
+ PchPolicy->PcieConfig2.SwEqCoeffList[0].Cp = 8;
+ PchPolicy->PcieConfig2.SwEqCoeffList[1].Cm = 8;
+ PchPolicy->PcieConfig2.SwEqCoeffList[1].Cp = 2;
+ PchPolicy->PcieConfig2.SwEqCoeffList[2].Cm = 10;
+ PchPolicy->PcieConfig2.SwEqCoeffList[2].Cp = 6;
+ PchPolicy->PcieConfig2.SwEqCoeffList[3].Cm = 12;
+ PchPolicy->PcieConfig2.SwEqCoeffList[3].Cp = 8;
+ PchPolicy->PcieConfig2.SwEqCoeffList[4].Cm = 14;
+ PchPolicy->PcieConfig2.SwEqCoeffList[4].Cp = 2;
+
+ /********************************
+ SATA related settings
+ ********************************/
+ PchPolicy->SataConfig.Enable = TRUE;
+ PchPolicy->SataConfig.SalpSupport = TRUE;
+ PchPolicy->SataConfig.SataMode = PchSataModeAhci;
+
+ for (PortIndex = 0; PortIndex < GetPchMaxSataPortNum (); PortIndex++) {
+ PchPolicy->SataConfig.PortSettings[PortIndex].Enable = TRUE;
+ PchPolicy->SataConfig.PortSettings[PortIndex].DmVal = 15;
+ PchPolicy->SataConfig.PortSettings[PortIndex].DitoVal = 625;
+ }
+
+ PchPolicy->SataConfig.Rst.Raid0 = TRUE;
+ PchPolicy->SataConfig.Rst.Raid1 = TRUE;
+ PchPolicy->SataConfig.Rst.Raid10 = TRUE;
+ PchPolicy->SataConfig.Rst.Raid5 = TRUE;
+ PchPolicy->SataConfig.Rst.Irrt = TRUE;
+ PchPolicy->SataConfig.Rst.OromUiBanner = TRUE;
+ PchPolicy->SataConfig.Rst.OromUiDelay = PchSataOromDelay2sec;
+ PchPolicy->SataConfig.Rst.HddUnlock = TRUE;
+ PchPolicy->SataConfig.Rst.LedLocate = TRUE;
+ PchPolicy->SataConfig.Rst.IrrtOnly = TRUE;
+ PchPolicy->SataConfig.Rst.SmartStorage = TRUE;
+
+ for (Index = 0; Index < PCH_MAX_RST_PCIE_STORAGE_CR; Index++) {
+ PchPolicy->SataConfig.RstPcieStorageRemap[Index].DeviceResetDelay = 100;
+ }
+ /********************************
+ sSATA related settings
+ ********************************/
+ PchPolicy->sSataConfig.Enable = TRUE;
+ // PchPolicy->sSataConfig.TestMode = FALSE;
+ // PchPolicy->sSataConfig.LegacyMode = FALSE;
+ PchPolicy->sSataConfig.SalpSupport = TRUE;
+ // PchPolicy->sSataConfig.eSATASpeedLimit = FALSE;
+ PchPolicy->sSataConfig.SataMode = PchSataModeAhci;
+ // PchPolicy->sSataConfig.SpeedLimit = PchsSataSpeedDefault;
+
+ for (PortIndex = 0; PortIndex < GetPchMaxsSataPortNum (); PortIndex++) {
+ PchPolicy->sSataConfig.PortSettings[PortIndex].Enable = TRUE;
+ // PchPolicy->sSataConfig.PortSettings[PortIndex].HotPlug = FALSE;
+ // PchPolicy->sSataConfig.PortSettings[PortIndex].InterlockSw = FALSE;
+ // PchPolicy->sSataConfig.PortSettings[PortIndex].External = FALSE;
+ // PchPolicy->sSataConfig.PortSettings[PortIndex].SpinUp = FALSE;
+ // PchPolicy->sSataConfig.PortSettings[PortIndex].SolidStateDrive = FALSE;
+ // PchPolicy->sSataConfig.PortSettings[PortIndex].DevSlp = FALSE;
+ // PchPolicy->sSataConfig.PortSettings[PortIndex].EnableDitoConfig = FALSE;
+ PchPolicy->sSataConfig.PortSettings[PortIndex].DmVal = 15;
+ PchPolicy->sSataConfig.PortSettings[PortIndex].DitoVal = 625;
+ }
+
+ // PchPolicy->sSataConfig.Rst.RaidAlternateId = FALSE;
+ PchPolicy->sSataConfig.Rst.Raid0 = TRUE;
+ PchPolicy->sSataConfig.Rst.Raid1 = TRUE;
+ PchPolicy->sSataConfig.Rst.Raid10 = TRUE;
+ PchPolicy->sSataConfig.Rst.Raid5 = TRUE;
+ PchPolicy->sSataConfig.Rst.Irrt = TRUE;
+ PchPolicy->sSataConfig.Rst.OromUiBanner = TRUE;
+ PchPolicy->sSataConfig.Rst.OromUiDelay = PchSataOromDelay2sec;
+ PchPolicy->sSataConfig.Rst.HddUnlock = TRUE;
+ PchPolicy->sSataConfig.Rst.LedLocate = TRUE;
+ PchPolicy->sSataConfig.Rst.IrrtOnly = TRUE;
+ PchPolicy->sSataConfig.Rst.SmartStorage = TRUE;
+
+ for (Index = 0; Index < PCH_MAX_RST_PCIE_STORAGE_CR; Index++) {
+ //PchPolicy->sSataConfig.RstPcieStorageRemap[Index].Enable = 0;
+ //PchPolicy->sSataConfig.RstPcieStorageRemap[Index].RstPcieStoragePort = 0;
+ PchPolicy->sSataConfig.RstPcieStorageRemap[Index].DeviceResetDelay = 100;
+ }
+
+ /********************************
+ USB related configuration
+ ********************************/
+ for (PortIndex = 0; PortIndex < GetPchXhciMaxUsb2PortNum (); PortIndex++) {
+ PchPolicy->UsbConfig.PortUsb20[PortIndex].Enable = TRUE;
+ }
+
+ for (PortIndex = 0; PortIndex < GetPchXhciMaxUsb3PortNum (); PortIndex++) {
+ PchPolicy->UsbConfig.PortUsb30[PortIndex].Enable = TRUE;
+ }
+ //
+ //XHCI Wake On USB Disabled
+ //
+ PchPolicy->UsbConfig.XhciWakeOnUsb = FALSE;
+ //
+ // USB Port Over Current Pins mapping, please set as per board layout.
+ // Default is PchUsbOverCurrentPin0(0)
+ //
+ PchPolicy->UsbConfig.PortUsb20[ 2].OverCurrentPin = PchUsbOverCurrentPin1;
+ PchPolicy->UsbConfig.PortUsb20[ 3].OverCurrentPin = PchUsbOverCurrentPin1;
+ PchPolicy->UsbConfig.PortUsb20[ 4].OverCurrentPin = PchUsbOverCurrentPin2;
+ PchPolicy->UsbConfig.PortUsb20[ 5].OverCurrentPin = PchUsbOverCurrentPin2;
+ PchPolicy->UsbConfig.PortUsb20[ 6].OverCurrentPin = PchUsbOverCurrentPin3;
+ PchPolicy->UsbConfig.PortUsb20[ 7].OverCurrentPin = PchUsbOverCurrentPin3;
+ PchPolicy->UsbConfig.PortUsb20[ 8].OverCurrentPin = PchUsbOverCurrentPin4;
+ PchPolicy->UsbConfig.PortUsb20[ 9].OverCurrentPin = PchUsbOverCurrentPin4;
+ PchPolicy->UsbConfig.PortUsb20[10].OverCurrentPin = PchUsbOverCurrentPin5;
+ PchPolicy->UsbConfig.PortUsb20[11].OverCurrentPin = PchUsbOverCurrentPin5;
+ PchPolicy->UsbConfig.PortUsb20[12].OverCurrentPin = PchUsbOverCurrentPin6;
+ PchPolicy->UsbConfig.PortUsb20[13].OverCurrentPin = PchUsbOverCurrentPin6;
+ PchPolicy->UsbConfig.PortUsb20[14].OverCurrentPin = PchUsbOverCurrentPin7;
+ PchPolicy->UsbConfig.PortUsb20[15].OverCurrentPin = PchUsbOverCurrentPin7;
+
+ PchPolicy->UsbConfig.PortUsb30[2].OverCurrentPin = PchUsbOverCurrentPin1;
+ PchPolicy->UsbConfig.PortUsb30[3].OverCurrentPin = PchUsbOverCurrentPin1;
+ PchPolicy->UsbConfig.PortUsb30[4].OverCurrentPin = PchUsbOverCurrentPin2;
+ PchPolicy->UsbConfig.PortUsb30[5].OverCurrentPin = PchUsbOverCurrentPin2;
+ PchPolicy->UsbConfig.PortUsb30[6].OverCurrentPin = PchUsbOverCurrentPin3;
+ PchPolicy->UsbConfig.PortUsb30[7].OverCurrentPin = PchUsbOverCurrentPin3;
+ PchPolicy->UsbConfig.PortUsb30[8].OverCurrentPin = PchUsbOverCurrentPin4;
+ PchPolicy->UsbConfig.PortUsb30[9].OverCurrentPin = PchUsbOverCurrentPin4;
+
+ //
+ // Default values of USB2 AFE settings.
+ //
+ for (Index = 0; Index < PCH_H_XHCI_MAX_USB2_PORTS; Index++) {
+
+ PchPolicy->UsbConfig.PortUsb20[Index].Afe.Petxiset = 7;
+ PchPolicy->UsbConfig.PortUsb20[Index].Afe.Txiset = 0;
+ PchPolicy->UsbConfig.PortUsb20[Index].Afe.Predeemp = 2;
+
+ PchPolicy->UsbConfig.PortUsb20[Index].Afe.Pehalfbit = 1;
+ }
+
+ //
+ // Enable/Disable SSIC support in the setup menu
+ //
+ for (PortIndex = 0; PortIndex < PCH_XHCI_MAX_SSIC_PORT_COUNT; PortIndex++) {
+ PchPolicy->UsbConfig.SsicConfig.SsicPort[PortIndex].Enable = FALSE;
+ }
+
+ //
+ // xDCI configuration
+ //
+ PchPolicy->UsbConfig.XdciConfig.Enable = FALSE;
+
+
+ /********************************
+ Io Apic configuration
+ ********************************/
+ PchPolicy->IoApicConfig.IoApicId = 0x02;
+ PchPolicy->IoApicConfig.IoApicEntry24_119 = FALSE;
+
+ /********************************
+ HPET Configuration
+ ********************************/
+ PchPolicy->HpetConfig.Enable = TRUE;
+ PchPolicy->HpetConfig.Base = PCH_HPET_BASE_ADDRESS;
+
+ /********************************
+ HD-Audio configuration
+ ********************************/
+ PchPolicy->HdAudioConfig.Enable = PCH_HDAUDIO_AUTO;
+ PchPolicy->HdAudioConfig.DspEnable = TRUE;
+ PchPolicy->HdAudioConfig.HdAudioLinkFrequency = PchHdaLinkFreq24MHz;
+ PchPolicy->HdAudioConfig.IDispLinkFrequency = PchHdaLinkFreq96MHz;
+ PchPolicy->HdAudioConfig.ResetWaitTimer = 600; // Must be at least 521us (25 frames)
+ PchPolicy->HdAudioConfig.DspEndpointDmic = PchHdaDmic4chArray;
+
+ /********************************
+ Lan configuration
+ ********************************/
+ PchPolicy->LanConfig.Enable = TRUE;
+ /********************************
+ SMBus configuration
+ ********************************/
+ PchPolicy->SmbusConfig.Enable = TRUE;
+ PchPolicy->SmbusConfig.SmbusIoBase = PcdGet16 (PcdSmbusBaseAddress);
+ ASSERT (sizeof (mSmbusRsvdAddresses) <= PCH_MAX_SMBUS_RESERVED_ADDRESS);
+ PchPolicy->SmbusConfig.NumRsvdSmbusAddresses = sizeof (mSmbusRsvdAddresses);
+ CopyMem (
+ PchPolicy->SmbusConfig.RsvdSmbusAddressTable,
+ mSmbusRsvdAddresses,
+ sizeof (mSmbusRsvdAddresses)
+ );
+
+ /********************************
+ Lockdown configuration
+ ********************************/
+ PchPolicy->LockDownConfig.GlobalSmi = TRUE;
+ //
+ // PCH BIOS Spec Flash Security Recommendations,
+ // Intel strongly recommends that BIOS sets the BIOS Interface Lock Down bit. Enabling this bit
+ // will mitigate malicious software attempts to replace the system BIOS option ROM with its own code.
+ // Here we always enable this as a Policy.
+ //
+ PchPolicy->LockDownConfig.BiosInterface = TRUE;
+ PchPolicy->LockDownConfig.RtcLock = TRUE;
+
+ /********************************
+ Thermal configuration.
+ ********************************/
+ PchPolicy->ThermalConfig.ThermalDeviceEnable = 0;
+ PchPolicy->ThermalConfig.TsmicLock = TRUE;
+ PchPolicy->ThermalConfig.ThermalThrottling.TTLevels.SuggestedSetting = TRUE;
+ PchPolicy->ThermalConfig.ThermalThrottling.TTLevels.PchCrossThrottling = TRUE;
+ PchPolicy->ThermalConfig.ThermalThrottling.DmiHaAWC.SuggestedSetting = TRUE;
+ PchPolicy->ThermalConfig.ThermalThrottling.SataTT.SuggestedSetting = TRUE;
+ PchPolicy->ThermalConfig.MemoryThrottling.TsGpioPinSetting[TsGpioC].PmsyncEnable = TRUE;
+ PchPolicy->ThermalConfig.MemoryThrottling.TsGpioPinSetting[TsGpioC].C0TransmitEnable = TRUE;
+ PchPolicy->ThermalConfig.MemoryThrottling.TsGpioPinSetting[TsGpioD].PmsyncEnable = TRUE;
+ PchPolicy->ThermalConfig.MemoryThrottling.TsGpioPinSetting[TsGpioD].C0TransmitEnable = TRUE;
+
+ /********************************
+ MiscPm Configuration
+ ********************************/
+ PchPolicy->PmConfig.PowerResetStatusClear.MeWakeSts = TRUE;
+ PchPolicy->PmConfig.PowerResetStatusClear.MeHrstColdSts = TRUE;
+ PchPolicy->PmConfig.PowerResetStatusClear.MeHrstWarmSts = TRUE;
+ PchPolicy->PmConfig.PowerResetStatusClear.WolOvrWkSts = TRUE;
+
+ PchPolicy->PmConfig.WakeConfig.WolEnableOverride = TRUE;
+ PchPolicy->PmConfig.WakeConfig.LanWakeFromDeepSx = TRUE;
+
+ PchPolicy->PmConfig.PchSlpS3MinAssert = PchSlpS350ms;
+ PchPolicy->PmConfig.PchSlpS4MinAssert = PchSlpS44s;
+ PchPolicy->PmConfig.PchSlpSusMinAssert = PchSlpSus4s;
+ PchPolicy->PmConfig.PchSlpAMinAssert = PchSlpA2s;
+
+ PchPolicy->PmConfig.PmcReadDisable = TRUE;
+ PchPolicy->PmConfig.SlpLanLowDc = TRUE;
+ PchPolicy->PmConfig.PciePllSsc = 0xFF;
+
+ PchPolicy->PmConfig.SlpS0Enable = TRUE;
+
+ PchPolicy->PmConfig.GrPfetDurOnDef = PchPmGrPfetDur5us;
+
+ /********************************
+ DMI related settings
+ ********************************/
+ PchPolicy->DmiConfig.DmiAspm = TRUE;
+ PchPolicy->DmiConfig.DmiStopAndScreamEnable = FALSE;
+
+ /********************************
+ Serial IRQ Configuration
+ ********************************/
+ PchPolicy->SerialIrqConfig.SirqEnable = TRUE;
+ PchPolicy->SerialIrqConfig.SirqMode = PchQuietMode;
+ PchPolicy->SerialIrqConfig.StartFramePulse = PchSfpw4Clk;
+
+
+ /********************************
+ Interrupt Configuration
+ ********************************/
+ IntConfigTableEntries = sizeof (mDevIntConfig) / sizeof (PCH_DEVICE_INTERRUPT_CONFIG);
+ ASSERT (IntConfigTableEntries <= PCH_MAX_DEVICE_INTERRUPT_CONFIG);
+ PchPolicy->PchInterruptConfig.NumOfDevIntConfig = IntConfigTableEntries;
+ CopyMem (
+ PchPolicy->PchInterruptConfig.DevIntConfig,
+ mDevIntConfig,
+ sizeof (mDevIntConfig)
+ );
+ if (GetPchSeries () == PchLp) {
+ CopyMem (
+ &(PchPolicy->PchInterruptConfig.DevIntConfig[IntConfigTableEntries]),
+ mLpOnlyDevIntConfig,
+ sizeof (mLpOnlyDevIntConfig)
+ );
+ PchPolicy->PchInterruptConfig.NumOfDevIntConfig += (sizeof (mLpOnlyDevIntConfig) / sizeof (PCH_DEVICE_INTERRUPT_CONFIG));
+ }
+
+ ASSERT ((sizeof (mPxRcConfig) / sizeof (UINT8)) <= PCH_MAX_PXRC_CONFIG);
+ CopyMem (
+ PchPolicy->PchInterruptConfig.PxRcConfig,
+ mPxRcConfig,
+ sizeof (mPxRcConfig)
+ );
+
+ PchPolicy->PchInterruptConfig.GpioIrqRoute = 14;
+ PchPolicy->PchInterruptConfig.SciIrqSelect = 9;
+ PchPolicy->PchInterruptConfig.TcoIrqSelect = 9;
+
+
+ /********************************
+ Port 61h emulation
+ ********************************/
+ PchPolicy->Port61hSmmConfig.Enable = TRUE;
+
+
+ /********************************
+ DCI Configuration
+ ********************************/
+ PchPolicy->DciConfig.DciAutoDetect = TRUE;
+
+ /********************************
+ LPC Configuration
+ ********************************/
+ PchPolicy->LpcConfig.EnhancePort8xhDecoding = TRUE;
+
+ /********************************
+ Power Optimizer related settings
+ ********************************/
+ PchPolicy->SataConfig.PwrOptEnable = TRUE;
+ PchPolicy->sSataConfig.PwrOptEnable = TRUE;
+
+
+ PchPolicy->AdrConfig.PchAdrEn = FORCE_ENABLE;
+ PchPolicy->AdrConfig.AdrGpioSel = PM_SYNC_GPIO_B;
+ PchPolicy->AdrConfig.AdrHostPartitionReset = FORCE_DISABLE;
+ PchPolicy->AdrConfig.AdrTimerEn = FORCE_ENABLE;
+ PchPolicy->AdrConfig.AdrTimerVal = V_PCH_LBG_MROM_ADRTIMERCTRL_ADR_TMR_100US;
+ PchPolicy->AdrConfig.AdrMultiplierVal = V_PCH_LBG_MROM_ADRTIMERCTRL_ADR_MULT_1;
+
+ *PchPolicyPpi = PchPolicy;
+ return EFI_SUCCESS;
+}
+
+/**
+ PchInstallPolicyPpi installs PchPolicyPpi.
+ While installed, RC assumes the Policy is ready and finalized. So please update and override
+ any setting before calling this function.
+
+ @param[in] PchPolicyPpi The pointer to PCH Policy PPI instance
+
+ @retval EFI_SUCCESS The policy is installed.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create buffer
+**/
+EFI_STATUS
+EFIAPI
+PchInstallPolicyPpi (
+ IN PCH_POLICY_PPI *PchPolicyPpi
+ )
+{
+ EFI_STATUS Status;
+ EFI_PEI_PPI_DESCRIPTOR *PchPolicyPpiDesc;
+
+ PchPolicyPpiDesc = (EFI_PEI_PPI_DESCRIPTOR *) AllocateZeroPool (sizeof (EFI_PEI_PPI_DESCRIPTOR));
+ if (PchPolicyPpiDesc == NULL) {
+ ASSERT (FALSE);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ PchPolicyPpiDesc->Flags = EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST;
+ PchPolicyPpiDesc->Guid = &gPchPlatformPolicyPpiGuid;
+ PchPolicyPpiDesc->Ppi = PchPolicyPpi;
+
+ //
+ // Print whole PCH_POLICY_PPI and serial out.
+ //
+ if (PchIsDwrFlow() == FALSE) {
+ PchPrintPolicyPpi (PchPolicyPpi);
+ }
+
+ //
+ // Install PCH Policy PPI
+ //
+ Status = PeiServicesInstallPpi (PchPolicyPpiDesc);
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
diff --git a/Silicon/Intel/LewisburgPkg/Library/PeiPchPolicyLib/PeiPchPolicyLib.inf b/Silicon/Intel/LewisburgPkg/Library/PeiPchPolicyLib/PeiPchPolicyLib.inf
new file mode 100644
index 0000000000..fa433c9333
--- /dev/null
+++ b/Silicon/Intel/LewisburgPkg/Library/PeiPchPolicyLib/PeiPchPolicyLib.inf
@@ -0,0 +1,58 @@
+### @file
+#
+# Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which 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.
+#
+###
+
+[Defines]
+ INF_VERSION = 0x00010017
+ BASE_NAME = PeiPchPolicyLib
+ FILE_GUID = BB1AC992-B2CA-4744-84B7-915C185576C5
+ VERSION_STRING = 1.0
+ MODULE_TYPE = PEIM
+ LIBRARY_CLASS = PchPolicyLib
+
+
+[LibraryClasses]
+ DebugLib
+ IoLib
+ PcdLib
+ PeiServicesLib
+ BaseMemoryLib
+ MemoryAllocationLib
+ PchInfoLib
+ PchPmcLib #SERVER_BIOS
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ LewisburgPkg/PchRcPkg.dec #SERVER_BIOS
+
+
+[Pcd]
+ gEfiPchTokenSpaceGuid.PcdPchAcpiIoPortBaseAddress #SERVER_BIOS
+ gEfiPchTokenSpaceGuid.PcdSmbusBaseAddress #SERVER_BIOS
+ gEfiPchTokenSpaceGuid.PcdSerialIoUartDebugEnable
+ gEfiPchTokenSpaceGuid.PcdSerialIoUartNumber
+
+
+[Sources]
+ PeiPchPolicyLib.c
+ PeiPchPolicyLibrary.h
+ PchPrintPolicy.c
+ Rvp3PolicyLib.c
+
+
+[Ppis]
+ gPchPlatformPolicyPpiGuid ## PRODUCES # SERVER_BIOS
+
+[Depex]
+ gPchInitPreMemDonePpiGuid \ No newline at end of file
diff --git a/Silicon/Intel/LewisburgPkg/Library/PeiPchPolicyLib/PeiPchPolicyLibrary.h b/Silicon/Intel/LewisburgPkg/Library/PeiPchPolicyLib/PeiPchPolicyLibrary.h
new file mode 100644
index 0000000000..9932afdc04
--- /dev/null
+++ b/Silicon/Intel/LewisburgPkg/Library/PeiPchPolicyLib/PeiPchPolicyLibrary.h
@@ -0,0 +1,31 @@
+/** @file
+
+Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+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_PCH_POLICY_LIBRARY_H_
+#define _PEI_PCH_POLICY_LIBRARY_H_
+
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PchInfoLib.h>
+#include <Ppi/PchPolicy.h>
+#include <PchAccess.h>
+#include <Library/PchSerialIoLib.h>
+#include <Library/PchPolicyLib.h>
+
+#define PCH_HPET_BASE_ADDRESS 0xFED00000
+
+
+#endif // _PEI_PCH_POLICY_LIBRARY_H_
diff --git a/Silicon/Intel/LewisburgPkg/Library/PeiPchPolicyLib/Rvp3PolicyLib.c b/Silicon/Intel/LewisburgPkg/Library/PeiPchPolicyLib/Rvp3PolicyLib.c
new file mode 100644
index 0000000000..62cc91f821
--- /dev/null
+++ b/Silicon/Intel/LewisburgPkg/Library/PeiPchPolicyLib/Rvp3PolicyLib.c
@@ -0,0 +1,211 @@
+/** @file
+
+Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+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.
+
+**/
+
+#include "PeiPchPolicyLibrary.h"
+
+/*
+ Apply RVP3 PCH specific default settings
+
+ @param[in] PchPolicyPpi The pointer to PCH Policy PPI instance
+*/
+VOID
+EFIAPI
+PchRvp3DefaultPolicy (
+ IN PCH_POLICY_PPI *PchPolicy
+ )
+{
+ UINTN Index;
+
+ //
+ // PCIE RP
+ //
+ for (Index = 0; Index < GetPchMaxPciePortNum (); Index++) {
+ PchPolicy->PcieConfig.RootPort[Index].ClkReqDetect = TRUE;
+ PchPolicy->PcieConfig.RootPort[Index].AdvancedErrorReporting = TRUE;
+ }
+
+ PchPolicy->PcieConfig.RootPort[0].ClkReqSupported = TRUE;
+ PchPolicy->PcieConfig.RootPort[0].ClkReqNumber = 2;
+ PchPolicy->HsioPcieConfig.Lane[0].HsioRxSetCtleEnable = TRUE;
+ PchPolicy->HsioPcieConfig.Lane[0].HsioRxSetCtle = 6;
+
+ PchPolicy->HsioPcieConfig.Lane[1].HsioRxSetCtleEnable = TRUE;
+ PchPolicy->HsioPcieConfig.Lane[1].HsioRxSetCtle = 6;
+
+ PchPolicy->HsioPcieConfig.Lane[2].HsioRxSetCtleEnable = TRUE;
+ PchPolicy->HsioPcieConfig.Lane[2].HsioRxSetCtle = 6;
+
+ PchPolicy->HsioPcieConfig.Lane[3].HsioRxSetCtleEnable = TRUE;
+ PchPolicy->HsioPcieConfig.Lane[3].HsioRxSetCtle = 6;
+
+ PchPolicy->PcieConfig.RootPort[4].ClkReqSupported = TRUE;
+ PchPolicy->PcieConfig.RootPort[4].ClkReqNumber = 3;
+
+ PchPolicy->PcieConfig.RootPort[5].ClkReqSupported = TRUE;
+ PchPolicy->PcieConfig.RootPort[5].ClkReqNumber = 1;
+ PchPolicy->HsioPcieConfig.Lane[5].HsioRxSetCtleEnable = TRUE;
+ PchPolicy->HsioPcieConfig.Lane[5].HsioRxSetCtle = 8;
+
+ PchPolicy->HsioPcieConfig.Lane[7].HsioRxSetCtleEnable = TRUE;
+ PchPolicy->HsioPcieConfig.Lane[7].HsioRxSetCtle = 8;
+
+ PchPolicy->PcieConfig.RootPort[8].ClkReqSupported = TRUE;
+ PchPolicy->PcieConfig.RootPort[8].ClkReqNumber = 5;
+ PchPolicy->HsioPcieConfig.Lane[8].HsioRxSetCtleEnable = TRUE;
+ PchPolicy->HsioPcieConfig.Lane[8].HsioRxSetCtle = 8;
+
+ PchPolicy->PcieConfig.RootPort[9].ClkReqSupported = TRUE;
+ PchPolicy->PcieConfig.RootPort[9].ClkReqNumber = 4;
+ PchPolicy->HsioPcieConfig.Lane[9].HsioRxSetCtleEnable = TRUE;
+ PchPolicy->HsioPcieConfig.Lane[9].HsioRxSetCtle = 8;
+
+ PchPolicy->HsioPcieConfig.Lane[10].HsioRxSetCtleEnable = TRUE;
+ PchPolicy->HsioPcieConfig.Lane[10].HsioRxSetCtle = 8;
+
+ PchPolicy->HsioPcieConfig.Lane[11].HsioRxSetCtleEnable = TRUE;
+ PchPolicy->HsioPcieConfig.Lane[11].HsioRxSetCtle = 8;
+
+ //
+ // SATA
+ //
+ PchPolicy->HsioSataConfig.PortLane[0].HsioRxGen3EqBoostMagEnable = TRUE;
+ PchPolicy->HsioSataConfig.PortLane[0].HsioRxGen3EqBoostMag = 4;
+ PchPolicy->HsioSataConfig.PortLane[0].HsioTxGen1DownscaleAmpEnable = TRUE;
+ PchPolicy->HsioSataConfig.PortLane[0].HsioTxGen1DownscaleAmp = 0x2C;
+ PchPolicy->HsioSataConfig.PortLane[0].HsioTxGen2DownscaleAmpEnable = 0;
+ PchPolicy->HsioSataConfig.PortLane[0].HsioTxGen2DownscaleAmp = 0;
+
+ //
+ // USB
+ //
+ PchPolicy->UsbConfig.PortUsb20[0].Afe.Petxiset = 7;
+ PchPolicy->UsbConfig.PortUsb20[0].Afe.Txiset = 0;
+ PchPolicy->UsbConfig.PortUsb20[0].Afe.Predeemp = 2;
+ PchPolicy->UsbConfig.PortUsb20[0].Afe.Pehalfbit = 1;
+
+ PchPolicy->UsbConfig.PortUsb20[1].Afe.Petxiset = 7;
+ PchPolicy->UsbConfig.PortUsb20[1].Afe.Txiset = 0;
+ PchPolicy->UsbConfig.PortUsb20[1].Afe.Predeemp = 2;
+ PchPolicy->UsbConfig.PortUsb20[1].Afe.Pehalfbit = 1;
+
+ PchPolicy->UsbConfig.PortUsb20[2].Afe.Petxiset = 7;
+ PchPolicy->UsbConfig.PortUsb20[2].Afe.Txiset = 0;
+ PchPolicy->UsbConfig.PortUsb20[2].Afe.Predeemp = 2;
+ PchPolicy->UsbConfig.PortUsb20[2].Afe.Pehalfbit = 1;
+
+ PchPolicy->UsbConfig.PortUsb20[3].Afe.Petxiset = 7;
+ PchPolicy->UsbConfig.PortUsb20[3].Afe.Txiset = 0;
+ PchPolicy->UsbConfig.PortUsb20[3].Afe.Predeemp = 2;
+ PchPolicy->UsbConfig.PortUsb20[3].Afe.Pehalfbit = 1;
+
+ PchPolicy->UsbConfig.PortUsb20[4].Afe.Petxiset = 7;
+ PchPolicy->UsbConfig.PortUsb20[4].Afe.Txiset = 0;
+ PchPolicy->UsbConfig.PortUsb20[4].Afe.Predeemp = 2;
+ PchPolicy->UsbConfig.PortUsb20[4].Afe.Pehalfbit = 1;
+
+ PchPolicy->UsbConfig.PortUsb20[5].Afe.Petxiset = 7;
+ PchPolicy->UsbConfig.PortUsb20[5].Afe.Txiset = 0;
+ PchPolicy->UsbConfig.PortUsb20[5].Afe.Predeemp = 2;
+ PchPolicy->UsbConfig.PortUsb20[5].Afe.Pehalfbit = 1;
+
+ PchPolicy->UsbConfig.PortUsb20[6].Afe.Petxiset = 7;
+ PchPolicy->UsbConfig.PortUsb20[6].Afe.Txiset = 0;
+ PchPolicy->UsbConfig.PortUsb20[6].Afe.Predeemp = 2;
+ PchPolicy->UsbConfig.PortUsb20[6].Afe.Pehalfbit = 1;
+
+ PchPolicy->UsbConfig.PortUsb20[7].Afe.Petxiset = 7;
+ PchPolicy->UsbConfig.PortUsb20[7].Afe.Txiset = 0;
+ PchPolicy->UsbConfig.PortUsb20[7].Afe.Predeemp = 2;
+ PchPolicy->UsbConfig.PortUsb20[7].Afe.Pehalfbit = 1;
+
+ PchPolicy->UsbConfig.PortUsb20[8].Afe.Petxiset = 7;
+ PchPolicy->UsbConfig.PortUsb20[8].Afe.Txiset = 5;
+ PchPolicy->UsbConfig.PortUsb20[8].Afe.Predeemp = 2;
+ PchPolicy->UsbConfig.PortUsb20[8].Afe.Pehalfbit = 1;
+
+ PchPolicy->UsbConfig.PortUsb20[9].Afe.Petxiset = 7;
+ PchPolicy->UsbConfig.PortUsb20[9].Afe.Txiset = 0;
+ PchPolicy->UsbConfig.PortUsb20[9].Afe.Predeemp = 2;
+ PchPolicy->UsbConfig.PortUsb20[9].Afe.Pehalfbit = 1;
+
+ // OC Map for USB2 Ports
+ PchPolicy->UsbConfig.PortUsb20[ 0].OverCurrentPin = PchUsbOverCurrentPin0;
+ PchPolicy->UsbConfig.PortUsb20[ 1].OverCurrentPin = PchUsbOverCurrentPin2;
+ PchPolicy->UsbConfig.PortUsb20[ 2].OverCurrentPin = PchUsbOverCurrentPinSkip;
+ PchPolicy->UsbConfig.PortUsb20[ 3].OverCurrentPin = PchUsbOverCurrentPinSkip;
+ PchPolicy->UsbConfig.PortUsb20[ 4].OverCurrentPin = PchUsbOverCurrentPin2;
+ PchPolicy->UsbConfig.PortUsb20[ 5].OverCurrentPin = PchUsbOverCurrentPinSkip;
+ PchPolicy->UsbConfig.PortUsb20[ 6].OverCurrentPin = PchUsbOverCurrentPinSkip;
+ PchPolicy->UsbConfig.PortUsb20[ 7].OverCurrentPin = PchUsbOverCurrentPinSkip;
+ PchPolicy->UsbConfig.PortUsb20[ 8].OverCurrentPin = PchUsbOverCurrentPin1;
+ PchPolicy->UsbConfig.PortUsb20[ 9].OverCurrentPin = PchUsbOverCurrentPinSkip;
+ PchPolicy->UsbConfig.PortUsb20[10].OverCurrentPin = PchUsbOverCurrentPinSkip;
+ PchPolicy->UsbConfig.PortUsb20[11].OverCurrentPin = PchUsbOverCurrentPinSkip;
+ PchPolicy->UsbConfig.PortUsb20[12].OverCurrentPin = PchUsbOverCurrentPinSkip;
+ PchPolicy->UsbConfig.PortUsb20[13].OverCurrentPin = PchUsbOverCurrentPinSkip;
+
+ // OC Map for USB3 Ports
+ PchPolicy->UsbConfig.PortUsb30[0].OverCurrentPin = PchUsbOverCurrentPin0;
+ PchPolicy->UsbConfig.PortUsb30[1].OverCurrentPin = PchUsbOverCurrentPinSkip;
+ PchPolicy->UsbConfig.PortUsb30[2].OverCurrentPin = PchUsbOverCurrentPinSkip;
+ PchPolicy->UsbConfig.PortUsb30[3].OverCurrentPin = PchUsbOverCurrentPin1;
+ PchPolicy->UsbConfig.PortUsb30[4].OverCurrentPin = PchUsbOverCurrentPinSkip;
+ PchPolicy->UsbConfig.PortUsb30[5].OverCurrentPin = PchUsbOverCurrentPinSkip;
+
+ PchPolicy->UsbConfig.SsicConfig.SsicPort[0].Enable = TRUE;
+ PchPolicy->UsbConfig.SsicConfig.SsicPort[1].Enable = TRUE;
+
+ //
+ // IOAPIC
+ //
+ PchPolicy->IoApicConfig.BdfValid = 1;
+ PchPolicy->IoApicConfig.BusNumber = 0xF0;
+ PchPolicy->IoApicConfig.DeviceNumber = 0x1F;
+ PchPolicy->IoApicConfig.FunctionNumber = 0;
+
+ //
+ // LAN
+ //
+ PchPolicy->LanConfig.K1OffEnable = TRUE;
+ PchPolicy->LanConfig.ClkReqSupported = TRUE;
+ PchPolicy->LanConfig.ClkReqNumber = 3;
+
+ //
+ // LOCK DOWN
+ //
+ PchPolicy->LockDownConfig.SpiEiss = TRUE;
+ PchPolicy->LockDownConfig.BiosLock = TRUE;
+
+ //
+ // THERMAL
+ //
+ PchPolicy->ThermalConfig.ThermalThrottling.TTLevels.PchCrossThrottling = FALSE;
+
+ //
+ // PM CONFIG
+ //
+ PchPolicy->PmConfig.PciClockRun = TRUE;
+
+ //
+ // DMI
+ //
+ PchPolicy->DmiConfig.PwrOptEnable = TRUE;
+
+
+ //
+ // TRACEHUB
+ //
+ PchPolicy->PchTraceHubConfig.MemReg0Size = 0x100000; // 1MB
+ PchPolicy->PchTraceHubConfig.MemReg1Size = 0x100000; // 1MB
+
+}
diff --git a/Silicon/Intel/LewisburgPkg/Library/SmmSpiFlashCommonLib/SmmSpiFlashCommonLib.inf b/Silicon/Intel/LewisburgPkg/Library/SmmSpiFlashCommonLib/SmmSpiFlashCommonLib.inf
new file mode 100644
index 0000000000..0972343872
--- /dev/null
+++ b/Silicon/Intel/LewisburgPkg/Library/SmmSpiFlashCommonLib/SmmSpiFlashCommonLib.inf
@@ -0,0 +1,56 @@
+### @file
+#
+# Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which 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.
+#
+###
+
+[Defines]
+ INF_VERSION = 0x00010017
+ BASE_NAME = SmmSpiFlashCommonLib
+ FILE_GUID = 9632D96E-E849-4217-9217-DC500B8AAE47
+ VERSION_STRING = 1.0
+ MODULE_TYPE = DXE_SMM_DRIVER
+ LIBRARY_CLASS = SpiFlashCommonLib|DXE_SMM_DRIVER
+ CONSTRUCTOR = SmmSpiFlashCommonLibConstructor
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[LibraryClasses]
+ PciLib
+ IoLib
+ MemoryAllocationLib
+ BaseLib
+ UefiLib
+ SmmServicesTableLib
+ BaseMemoryLib
+ DebugLib
+ MmPciLib
+
+[Packages]
+ MdePkg/MdePkg.dec
+ LewisburgPkg/PchRcPkg.dec
+
+[Pcd]
+ gEfiPchTokenSpaceGuid.PcdFlashAreaBaseAddress ## CONSUMES
+ gEfiPchTokenSpaceGuid.PcdFlashAreaSize ## CONSUMES
+
+[Sources]
+ SpiFlashCommonSmmLib.c
+ SpiFlashCommon.c
+
+[Protocols]
+ gEfiSmmSpiProtocolGuid ## CONSUMES
+
+[Depex.X64.DXE_SMM_DRIVER]
+ gEfiSmmSpiProtocolGuid
diff --git a/Silicon/Intel/LewisburgPkg/Library/SmmSpiFlashCommonLib/SpiFlashCommon.c b/Silicon/Intel/LewisburgPkg/Library/SmmSpiFlashCommonLib/SpiFlashCommon.c
new file mode 100644
index 0000000000..9d1e3fb60e
--- /dev/null
+++ b/Silicon/Intel/LewisburgPkg/Library/SmmSpiFlashCommonLib/SpiFlashCommon.c
@@ -0,0 +1,198 @@
+/** @file
+
+Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+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.
+
+**/
+
+#include <Library/SpiFlashCommonLib.h>
+#include <Library/IoLib.h>
+#include <Library/PciLib.h>
+#include <Protocol/Spi.h>
+
+
+EFI_SPI_PROTOCOL *mSpiProtocol;
+
+//
+// FlashAreaBaseAddress and Size for boottime and runtime usage.
+//
+UINTN mFlashAreaBaseAddress = 0;
+UINTN mFlashAreaSize = 0;
+
+/**
+ Enable block protection on the Serial Flash device.
+
+ @retval EFI_SUCCESS Opertion is successful.
+ @retval EFI_DEVICE_ERROR If there is any device errors.
+
+**/
+EFI_STATUS
+EFIAPI
+SpiFlashLock (
+ VOID
+ )
+{
+ return EFI_SUCCESS;
+}
+
+/**
+ Read NumBytes bytes of data from the address specified by
+ PAddress into Buffer.
+
+ @param[in] Address The starting physical address of the read.
+ @param[in,out] NumBytes On input, the number of bytes to read. On output, the number
+ of bytes actually read.
+ @param[out] Buffer The destination data buffer for the read.
+
+ @retval EFI_SUCCESS Opertion is successful.
+ @retval EFI_DEVICE_ERROR If there is any device errors.
+
+**/
+EFI_STATUS
+EFIAPI
+SpiFlashRead (
+ IN UINTN Address,
+ IN OUT UINT32 *NumBytes,
+ OUT UINT8 *Buffer
+ )
+{
+ ASSERT ((NumBytes != NULL) && (Buffer != NULL));
+ if ((NumBytes == NULL) || (Buffer == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // This function is implemented specifically for those platforms
+ // at which the SPI device is memory mapped for read. So this
+ // function just do a memory copy for Spi Flash Read.
+ //
+ CopyMem (Buffer, (VOID *) Address, *NumBytes);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Write NumBytes bytes of data from Buffer to the address specified by
+ PAddresss.
+
+ @param[in] Address The starting physical address of the write.
+ @param[in,out] NumBytes On input, the number of bytes to write. On output,
+ the actual number of bytes written.
+ @param[in] Buffer The source data buffer for the write.
+
+ @retval EFI_SUCCESS Opertion is successful.
+ @retval EFI_DEVICE_ERROR If there is any device errors.
+
+**/
+EFI_STATUS
+EFIAPI
+SpiFlashWrite (
+ IN UINTN Address,
+ IN OUT UINT32 *NumBytes,
+ IN UINT8 *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINTN Offset;
+ UINT32 Length;
+ UINT32 RemainingBytes;
+
+ ASSERT ((NumBytes != NULL) && (Buffer != NULL));
+ if ((NumBytes == NULL) || (Buffer == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ASSERT (Address >= mFlashAreaBaseAddress);
+
+ Offset = Address - mFlashAreaBaseAddress;
+
+ ASSERT ((*NumBytes + Offset) <= mFlashAreaSize);
+
+ Status = EFI_SUCCESS;
+ RemainingBytes = *NumBytes;
+
+
+ while (RemainingBytes > 0) {
+ if (RemainingBytes > SECTOR_SIZE_4KB) {
+ Length = SECTOR_SIZE_4KB;
+ } else {
+ Length = RemainingBytes;
+ }
+ Status = mSpiProtocol->FlashWrite (
+ mSpiProtocol,
+ FlashRegionBios,
+ (UINT32) Offset,
+ Length,
+ Buffer
+ );
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+ RemainingBytes -= Length;
+ Offset += Length;
+ Buffer += Length;
+ }
+
+ //
+ // Actual number of bytes written
+ //
+ *NumBytes -= RemainingBytes;
+
+ return Status;
+}
+
+/**
+ Erase the block starting at Address.
+
+ @param[in] Address The starting physical address of the block to be erased.
+ This library assume that caller garantee that the PAddress
+ is at the starting address of this block.
+ @param[in] NumBytes On input, the number of bytes of the logical block to be erased.
+ On output, the actual number of bytes erased.
+
+ @retval EFI_SUCCESS. Opertion is successful.
+ @retval EFI_DEVICE_ERROR If there is any device errors.
+
+**/
+EFI_STATUS
+EFIAPI
+SpiFlashBlockErase (
+ IN UINTN Address,
+ IN UINTN *NumBytes
+ )
+{
+ EFI_STATUS Status;
+ UINTN Offset;
+ UINTN RemainingBytes;
+
+ ASSERT (NumBytes != NULL);
+ if (NumBytes == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ASSERT (Address >= mFlashAreaBaseAddress);
+
+ Offset = Address - mFlashAreaBaseAddress;
+
+ ASSERT ((*NumBytes % SECTOR_SIZE_4KB) == 0);
+ ASSERT ((*NumBytes + Offset) <= mFlashAreaSize);
+
+ Status = EFI_SUCCESS;
+ RemainingBytes = *NumBytes;
+
+
+ Status = mSpiProtocol->FlashErase (
+ mSpiProtocol,
+ FlashRegionBios,
+ (UINT32) Offset,
+ (UINT32) RemainingBytes
+ );
+ return Status;
+}
+
diff --git a/Silicon/Intel/LewisburgPkg/Library/SmmSpiFlashCommonLib/SpiFlashCommonSmmLib.c b/Silicon/Intel/LewisburgPkg/Library/SmmSpiFlashCommonLib/SpiFlashCommonSmmLib.c
new file mode 100644
index 0000000000..befff4c8dd
--- /dev/null
+++ b/Silicon/Intel/LewisburgPkg/Library/SmmSpiFlashCommonLib/SpiFlashCommonSmmLib.c
@@ -0,0 +1,59 @@
+/** @file
+
+Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+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.
+
+**/
+
+#include <Library/SpiFlashCommonLib.h>
+#include <Library/SmmServicesTableLib.h>
+#include <Protocol/Spi.h>
+
+extern EFI_SPI_PROTOCOL *mSpiProtocol;
+
+extern UINTN mFlashAreaBaseAddress;
+extern UINTN mFlashAreaSize;
+
+/**
+ The library constructuor.
+
+ The function does the necessary initialization work for this library
+ instance.
+
+ @param[in] ImageHandle The firmware allocated handle for the UEFI image.
+ @param[in] SystemTable A pointer to the EFI system table.
+
+ @retval EFI_SUCCESS The function always return EFI_SUCCESS for now.
+ It will ASSERT on error for debug version.
+ @retval EFI_ERROR Please reference LocateProtocol for error code details.
+**/
+EFI_STATUS
+EFIAPI
+SmmSpiFlashCommonLibConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ mFlashAreaBaseAddress = (UINTN)PcdGet32 (PcdFlashAreaBaseAddress);
+ mFlashAreaSize = (UINTN)PcdGet32 (PcdFlashAreaSize);
+
+ //
+ // Locate the SMM SPI protocol.
+ //
+ Status = gSmst->SmmLocateProtocol (
+ &gEfiSmmSpiProtocolGuid,
+ NULL,
+ (VOID **) &mSpiProtocol
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}