summaryrefslogtreecommitdiff
path: root/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate
diff options
context:
space:
mode:
Diffstat (limited to 'Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate')
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/BasePchSpiCommonLib/BasePchSpiCommonLib.inf35
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/BasePchSpiCommonLib/SpiCommon.c1058
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/DxePchHdaLib/DxePchHdaLib.inf51
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/DxePchHdaLib/PchHdaEndpoints.c318
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/DxePchHdaLib/PchHdaLib.c842
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/DxePchHdaLib/PchHdaNhltConfig.c336
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeI2cMasterCommonLib/I2cMasterCommonLib.c545
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeI2cMasterCommonLib/PeiDxeI2cMasterCommonLib.inf44
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmGpioPrivateLib/GpioNativePrivateLib.c305
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmGpioPrivateLib/GpioPrivateLib.c318
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmGpioPrivateLib/PchSklGpioPrivateData.c200
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmGpioPrivateLib/PeiDxeSmmGpioPrivateLib.inf49
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchInitCommonLib/PchInitCommon.c519
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchInitCommonLib/PchRpfn.c127
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchInitCommonLib/PeiDxeSmmPchInitCommonLib.inf42
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchPciExpressHelpersLib/PchPciExpressHelpersLibrary.c1933
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchPciExpressHelpersLib/PchPciExpressHelpersLibrary.h45
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchPciExpressHelpersLib/PeiDxeSmmPchPciExpressHelpersLib.inf52
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchPsfPrivateLib/PchPsfPrivateLib.c1169
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchPsfPrivateLib/PeiDxeSmmPchPsfPrivateLib.inf47
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchSmbusCommonLib/PchSmbusExec.c652
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchSmbusCommonLib/PeiDxeSmmPchSmbusCommonLib.inf35
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmRstPrivateLib/PeiDxeSmmRstPrivateLib.c216
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmRstPrivateLib/PeiDxeSmmRstPrivateLib.inf42
24 files changed, 8980 insertions, 0 deletions
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/BasePchSpiCommonLib/BasePchSpiCommonLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/BasePchSpiCommonLib/BasePchSpiCommonLib.inf
new file mode 100644
index 0000000000..128f7adcea
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/BasePchSpiCommonLib/BasePchSpiCommonLib.inf
@@ -0,0 +1,35 @@
+## @file
+# Component description file for the PchSpiCommonLib
+#
+# Copyright (c) 2017, 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 = 0x00010005
+ BASE_NAME = BasePchSpiCommonLib
+ FILE_GUID = A37CB67E-7D85-45B3-B07E-BF65BDB603E8
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PchSpiCommonLib
+
+[Sources]
+ SpiCommon.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ KabylakeSiliconPkg/SiPkg.dec
+ KabylakeSiliconPkg/KabylakeSiliconPrivate.dec
+
+[LibraryClasses]
+ IoLib
+ DebugLib
+ PchCycleDecodingLib
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/BasePchSpiCommonLib/SpiCommon.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/BasePchSpiCommonLib/SpiCommon.c
new file mode 100644
index 0000000000..46184d4994
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/BasePchSpiCommonLib/SpiCommon.c
@@ -0,0 +1,1058 @@
+/** @file
+ PCH SPI Common Driver implements the SPI Host Controller Compatibility Interface.
+
+Copyright (c) 2017, 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 <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <IndustryStandard/Pci30.h>
+#include <PchAccess.h>
+#include <Library/PchCycleDecodingLib.h>
+#include <Library/MmPciLib.h>
+#include <Protocol/Spi.h>
+#include <Library/PchSpiCommonLib.h>
+
+/**
+ Initialize an SPI protocol instance.
+
+ @param[in] SpiInstance Pointer to SpiInstance to initialize
+
+ @retval EFI_SUCCESS The protocol instance was properly initialized
+ @exception EFI_UNSUPPORTED The PCH is not supported by this module
+**/
+EFI_STATUS
+SpiProtocolConstructor (
+ IN SPI_INSTANCE *SpiInstance
+ )
+{
+ UINTN PchSpiBar0;
+ UINT32 Data32;
+
+ //
+ // Initialize the SPI protocol instance
+ //
+ SpiInstance->Signature = PCH_SPI_PRIVATE_DATA_SIGNATURE;
+ SpiInstance->Handle = NULL;
+ SpiInstance->SpiProtocol.Revision = PCH_SPI_SERVICES_REVISION;
+ SpiInstance->SpiProtocol.FlashRead = SpiProtocolFlashRead;
+ SpiInstance->SpiProtocol.FlashWrite = SpiProtocolFlashWrite;
+ SpiInstance->SpiProtocol.FlashErase = SpiProtocolFlashErase;
+ SpiInstance->SpiProtocol.FlashReadSfdp = SpiProtocolFlashReadSfdp;
+ SpiInstance->SpiProtocol.FlashReadJedecId = SpiProtocolFlashReadJedecId;
+ SpiInstance->SpiProtocol.FlashWriteStatus = SpiProtocolFlashWriteStatus;
+ SpiInstance->SpiProtocol.FlashReadStatus = SpiProtocolFlashReadStatus;
+ SpiInstance->SpiProtocol.GetRegionAddress = SpiProtocolGetRegionAddress;
+ SpiInstance->SpiProtocol.ReadPchSoftStrap = SpiProtocolReadPchSoftStrap;
+ SpiInstance->SpiProtocol.ReadCpuSoftStrap = SpiProtocolReadCpuSoftStrap;
+
+ SpiInstance->PchSpiBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_SPI,
+ PCI_FUNCTION_NUMBER_PCH_SPI
+ );
+
+ PchAcpiBaseGet (&(SpiInstance->PchAcpiBase));
+ ASSERT (SpiInstance->PchAcpiBase != 0);
+
+ PchSpiBar0 = MmioRead32 (SpiInstance->PchSpiBase + R_PCH_SPI_BAR0) & ~(B_PCH_SPI_BAR0_MASK);
+ if (PchSpiBar0 == 0) {
+ DEBUG ((DEBUG_ERROR, "ERROR : PchSpiBar0 is invalid!\n"));
+ ASSERT (FALSE);
+ }
+
+ if ((MmioRead32 (PchSpiBar0 + R_PCH_SPI_HSFSC) & B_PCH_SPI_HSFSC_FDV) == 0) {
+ DEBUG ((DEBUG_ERROR, "ERROR : SPI Flash Signature invalid, cannot use the Hardware Sequencing registers!\n"));
+ ASSERT (FALSE);
+ }
+
+ //
+ // Get Region 0 - 7 read Permission bits, region 8 and above are not permitted.
+ //
+ SpiInstance->ReadPermission = MmioRead8 (PchSpiBar0 + R_PCH_SPI_FRAP) & B_PCH_SPI_FRAP_BRRA_MASK;
+ DEBUG ((DEBUG_INFO, "Flash Region read Permission : %0x\n", SpiInstance->ReadPermission));
+ //
+ // Get Region 0 - 7 write Permission bits, region 8 and above are not permitted.
+ //
+ SpiInstance->WritePermission = (UINT8) ((MmioRead16 (PchSpiBar0 + R_PCH_SPI_FRAP) &
+ B_PCH_SPI_FRAP_BRWA_MASK) >> N_PCH_SPI_FRAP_BRWA);
+ DEBUG ((DEBUG_INFO, "Flash Region write Permission : %0x\n", SpiInstance->WritePermission));
+
+ SpiInstance->SfdpVscc0Value = MmioRead32 (PchSpiBar0 + R_PCH_SPI_SFDP0_VSCC0);
+ DEBUG ((DEBUG_INFO, "Component 0 SFDP VSCC value : %0x\n", SpiInstance->SfdpVscc0Value));
+ SpiInstance->SfdpVscc1Value = MmioRead32 (PchSpiBar0 + R_PCH_SPI_SFDP1_VSCC1);
+ DEBUG ((DEBUG_INFO, "Component 1 SFDP VSCC value : %0x\n", SpiInstance->SfdpVscc1Value));
+
+ //
+ // Select to Flash Map 0 Register to get the number of flash Component
+ //
+ MmioAndThenOr32 (
+ PchSpiBar0 + R_PCH_SPI_FDOC,
+ (UINT32) (~(B_PCH_SPI_FDOC_FDSS_MASK | B_PCH_SPI_FDOC_FDSI_MASK)),
+ (UINT32) (V_PCH_SPI_FDOC_FDSS_FSDM | R_PCH_SPI_FDBAR_FLASH_MAP0)
+ );
+
+ //
+ // Copy Zero based Number Of Components
+ //
+ SpiInstance->NumberOfComponents = (UINT8) ((MmioRead16 (PchSpiBar0 + R_PCH_SPI_FDOD) & B_PCH_SPI_FDBAR_NC) >> N_PCH_SPI_FDBAR_NC);
+ DEBUG ((DEBUG_INFO, "Component Number : %0x\n", SpiInstance->NumberOfComponents + 1));
+
+ MmioAndThenOr32 (
+ PchSpiBar0 + R_PCH_SPI_FDOC,
+ (UINT32) (~(B_PCH_SPI_FDOC_FDSS_MASK | B_PCH_SPI_FDOC_FDSI_MASK)),
+ (UINT32) (V_PCH_SPI_FDOC_FDSS_COMP | R_PCH_SPI_FCBA_FLCOMP)
+ );
+
+ //
+ // Copy Component 0 Density
+ //
+ Data32 = MmioRead32 (PchSpiBar0 + R_PCH_SPI_FDOD);
+ if (SpiInstance->NumberOfComponents > 0) {
+ SpiInstance->Component1StartAddr = V_PCH_SPI_FLCOMP_COMP_512KB <<
+ (Data32 & B_PCH_SPI_FLCOMP_COMP0_MASK);
+ DEBUG ((DEBUG_INFO, "Component 1 StartAddr : %0x\n", SpiInstance->Component1StartAddr));
+ SpiInstance->TotalFlashSize = SpiInstance->Component1StartAddr +
+ (V_PCH_SPI_FLCOMP_COMP_512KB <<
+ ((Data32 & B_PCH_SPI_FLCOMP_COMP1_MASK) >>
+ N_PCH_SPI_FLCOMP_COMP1));
+ } else {
+ SpiInstance->TotalFlashSize = V_PCH_SPI_FLCOMP_COMP_512KB <<
+ (Data32 & B_PCH_SPI_FLCOMP_COMP0_MASK);
+ }
+ DEBUG ((DEBUG_INFO, "Total Flash Size : %0x\n", SpiInstance->TotalFlashSize));
+
+ //
+ // Select FLASH_MAP1 to get Flash PCH Strap Base Address
+ //
+ MmioAndThenOr32 (
+ (PchSpiBar0 + R_PCH_SPI_FDOC),
+ (UINT32) (~(B_PCH_SPI_FDOC_FDSS_MASK | B_PCH_SPI_FDOC_FDSI_MASK)),
+ (UINT32) (V_PCH_SPI_FDOC_FDSS_FSDM | R_PCH_SPI_FDBAR_FLASH_MAP1)
+ );
+ //
+ // Align FPSBA with address bits for the PCH Strap portion of flash descriptor
+ //
+ Data32 = MmioRead32 (PchSpiBar0 + R_PCH_SPI_FDOD);
+ SpiInstance->PchStrapBaseAddr = (UINT16) (((Data32 & B_PCH_SPI_FDBAR_FPSBA)
+ >> N_PCH_SPI_FDBAR_FPSBA)
+ << N_PCH_SPI_FDBAR_FPSBA_REPR);
+ DEBUG ((DEBUG_INFO, "PchStrapBaseAddr : %0x\n", SpiInstance->PchStrapBaseAddr));
+ ASSERT (SpiInstance->PchStrapBaseAddr != 0);
+ //
+ // PCH Strap Length, [31:24] represents number of Dwords
+ //
+ SpiInstance->PchStrapSize = (UINT16) (((Data32 & B_PCH_SPI_FDBAR_PCHSL)
+ >> N_PCH_SPI_FDBAR_PCHSL)
+ * sizeof (UINT32));
+ DEBUG ((DEBUG_INFO, "PchStrapSize : %0x\n", SpiInstance->PchStrapSize));
+
+ //
+ // Select FLASH_MAP2 to get Flash CPU Strap Base Address
+ //
+ MmioAndThenOr32 (
+ (PchSpiBar0 + R_PCH_SPI_FDOC),
+ (UINT32) (~(B_PCH_SPI_FDOC_FDSS_MASK | B_PCH_SPI_FDOC_FDSI_MASK)),
+ (UINT32) (V_PCH_SPI_FDOC_FDSS_FSDM | R_PCH_SPI_FDBAR_FLASH_MAP2)
+ );
+ //
+ // Align FPSBA with address bits for the PCH Strap portion of flash descriptor
+ //
+ Data32 = MmioRead32 (PchSpiBar0 + R_PCH_SPI_FDOD);
+ SpiInstance->CpuStrapBaseAddr = (UINT16) (((Data32 & B_PCH_SPI_FDBAR_FCPUSBA)
+ >> N_PCH_SPI_FDBAR_FCPUSBA)
+ << N_PCH_SPI_FDBAR_FCPUSBA_REPR);
+ DEBUG ((DEBUG_INFO, "CpuStrapBaseAddr : %0x\n", SpiInstance->CpuStrapBaseAddr));
+ ASSERT (SpiInstance->CpuStrapBaseAddr != 0);
+ //
+ // CPU Strap Length, [15:8] represents number of Dwords
+ //
+ SpiInstance->CpuStrapSize = (UINT16) (((Data32 & B_PCH_SPI_FDBAR_CPUSL)
+ >> N_PCH_SPI_FDBAR_CPUSL)
+ * sizeof (UINT32));
+ DEBUG ((DEBUG_INFO, "CpuStrapSize : %0x\n", SpiInstance->CpuStrapSize));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Delay for at least the request number of microseconds for Runtime usage.
+
+ @param[in] ABase Acpi base address
+ @param[in] Microseconds Number of microseconds to delay.
+
+**/
+VOID
+EFIAPI
+PchPmTimerStallRuntimeSafe (
+ IN UINT16 ABase,
+ IN UINTN Microseconds
+ )
+{
+ UINTN Ticks;
+ UINTN Counts;
+ UINTN CurrentTick;
+ UINTN OriginalTick;
+ UINTN RemainingTick;
+
+ if (Microseconds == 0) {
+ return;
+ }
+
+ OriginalTick = IoRead32 ((UINTN) (ABase + R_PCH_ACPI_PM1_TMR)) & B_PCH_ACPI_PM1_TMR_VAL;
+ CurrentTick = OriginalTick;
+
+ //
+ // The timer frequency is 3.579545 MHz, so 1 ms corresponds 3.58 clocks
+ //
+ Ticks = Microseconds * 358 / 100 + OriginalTick + 1;
+
+ //
+ // The loops needed by timer overflow
+ //
+ Counts = Ticks / V_PCH_ACPI_PM1_TMR_MAX_VAL;
+
+ //
+ // Remaining clocks within one loop
+ //
+ RemainingTick = Ticks % V_PCH_ACPI_PM1_TMR_MAX_VAL;
+
+ //
+ // not intend to use TMROF_STS bit of register PM1_STS, because this adds extra
+ // one I/O operation, and maybe generate SMI
+ //
+ while ((Counts != 0) || (RemainingTick > CurrentTick)) {
+ CurrentTick = IoRead32 ((UINTN) (ABase + R_PCH_ACPI_PM1_TMR)) & B_PCH_ACPI_PM1_TMR_VAL;
+ //
+ // Check if timer overflow
+ //
+ if ((CurrentTick < OriginalTick)) {
+ if (Counts != 0) {
+ Counts--;
+ } else {
+ //
+ // If timer overflow and Counts equ to 0, that means we already stalled more than
+ // RemainingTick, break the loop here
+ //
+ break;
+ }
+ }
+
+ OriginalTick = CurrentTick;
+ }
+}
+
+/**
+ Read data from the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] FlashRegionType The Flash Region type for flash cycle which is listed in the Descriptor.
+ @param[in] Address The Flash Linear Address must fall within a region for which BIOS has access permissions.
+ @param[in] ByteCount Number of bytes in the data portion of the SPI cycle.
+ @param[out] Buffer The Pointer to caller-allocated buffer containing the dada received.
+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashRead (
+ IN PCH_SPI_PROTOCOL *This,
+ IN FLASH_REGION_TYPE FlashRegionType,
+ IN UINT32 Address,
+ IN UINT32 ByteCount,
+ OUT UINT8 *Buffer
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Sends the command to the SPI interface to execute.
+ //
+ Status = SendSpiCmd (
+ This,
+ FlashRegionType,
+ FlashCycleRead,
+ Address,
+ ByteCount,
+ Buffer
+ );
+ return Status;
+}
+
+/**
+ Write data to the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] FlashRegionType The Flash Region type for flash cycle which is listed in the Descriptor.
+ @param[in] Address The Flash Linear Address must fall within a region for which BIOS has access permissions.
+ @param[in] ByteCount Number of bytes in the data portion of the SPI cycle.
+ @param[in] Buffer Pointer to caller-allocated buffer containing the data sent during the SPI cycle.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashWrite (
+ IN PCH_SPI_PROTOCOL *This,
+ IN FLASH_REGION_TYPE FlashRegionType,
+ IN UINT32 Address,
+ IN UINT32 ByteCount,
+ IN UINT8 *Buffer
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Sends the command to the SPI interface to execute.
+ //
+ Status = SendSpiCmd (
+ This,
+ FlashRegionType,
+ FlashCycleWrite,
+ Address,
+ ByteCount,
+ Buffer
+ );
+ return Status;
+}
+
+/**
+ Erase some area on the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] FlashRegionType The Flash Region type for flash cycle which is listed in the Descriptor.
+ @param[in] Address The Flash Linear Address must fall within a region for which BIOS has access permissions.
+ @param[in] ByteCount Number of bytes in the data portion of the SPI cycle.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashErase (
+ IN PCH_SPI_PROTOCOL *This,
+ IN FLASH_REGION_TYPE FlashRegionType,
+ IN UINT32 Address,
+ IN UINT32 ByteCount
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Sends the command to the SPI interface to execute.
+ //
+ Status = SendSpiCmd (
+ This,
+ FlashRegionType,
+ FlashCycleErase,
+ Address,
+ ByteCount,
+ NULL
+ );
+ return Status;
+}
+
+/**
+ Read SFDP data from the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] ComponentNumber The Componen Number for chip select
+ @param[in] Address The starting byte address for SFDP data read.
+ @param[in] ByteCount Number of bytes in SFDP data portion of the SPI cycle
+ @param[out] SfdpData The Pointer to caller-allocated buffer containing the SFDP data received
+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashReadSfdp (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT8 ComponentNumber,
+ IN UINT32 Address,
+ IN UINT32 ByteCount,
+ OUT UINT8 *SfdpData
+ )
+{
+ SPI_INSTANCE *SpiInstance;
+ EFI_STATUS Status;
+ UINT32 FlashAddress;
+
+ SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
+ Status = EFI_SUCCESS;
+
+ if (ComponentNumber > SpiInstance->NumberOfComponents) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ FlashAddress = 0;
+ if (ComponentNumber == FlashComponent1) {
+ FlashAddress = SpiInstance->Component1StartAddr;
+ }
+ FlashAddress += Address;
+ //
+ // Sends the command to the SPI interface to execute.
+ //
+ Status = SendSpiCmd (
+ This,
+ FlashRegionAll,
+ FlashCycleReadSfdp,
+ FlashAddress,
+ ByteCount,
+ SfdpData
+ );
+ return Status;
+}
+
+/**
+ Read Jedec Id from the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] ComponentNumber The Componen Number for chip select
+ @param[in] ByteCount Number of bytes in JedecId data portion of the SPI cycle, the data size is 3 typically
+ @param[out] JedecId The Pointer to caller-allocated buffer containing JEDEC ID received
+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashReadJedecId (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT8 ComponentNumber,
+ IN UINT32 ByteCount,
+ OUT UINT8 *JedecId
+ )
+{
+ SPI_INSTANCE *SpiInstance;
+ EFI_STATUS Status;
+ UINT32 Address;
+
+ SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
+ Status = EFI_SUCCESS;
+
+ if (ComponentNumber > SpiInstance->NumberOfComponents) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Address = 0;
+ if (ComponentNumber == FlashComponent1) {
+ Address = SpiInstance->Component1StartAddr;
+ }
+
+ //
+ // Sends the command to the SPI interface to execute.
+ //
+ Status = SendSpiCmd (
+ This,
+ FlashRegionAll,
+ FlashCycleReadJedecId,
+ Address,
+ ByteCount,
+ JedecId
+ );
+ return Status;
+}
+
+/**
+ Write the status register in the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] ByteCount Number of bytes in Status data portion of the SPI cycle, the data size is 1 typically
+ @param[in] StatusValue The Pointer to caller-allocated buffer containing the value of Status register writing
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashWriteStatus (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT32 ByteCount,
+ IN UINT8 *StatusValue
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Sends the command to the SPI interface to execute.
+ //
+ Status = SendSpiCmd (
+ This,
+ FlashRegionAll,
+ FlashCycleWriteStatus,
+ 0,
+ ByteCount,
+ StatusValue
+ );
+ return Status;
+}
+
+/**
+ Read status register in the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] ByteCount Number of bytes in Status data portion of the SPI cycle, the data size is 1 typically
+ @param[out] StatusValue The Pointer to caller-allocated buffer containing the value of Status register received.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashReadStatus (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT32 ByteCount,
+ OUT UINT8 *StatusValue
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Sends the command to the SPI interface to execute.
+ //
+ Status = SendSpiCmd (
+ This,
+ FlashRegionAll,
+ FlashCycleReadStatus,
+ 0,
+ ByteCount,
+ StatusValue
+ );
+ return Status;
+}
+
+/**
+ Get the SPI region base and size, based on the enum type
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] FlashRegionType The Flash Region type for for the base address which is listed in the Descriptor.
+ @param[out] BaseAddress The Flash Linear Address for the Region 'n' Base
+ @param[out] RegionSize The size for the Region 'n'
+
+ @retval EFI_SUCCESS Read success
+ @retval EFI_INVALID_PARAMETER Invalid region type given
+ @retval EFI_DEVICE_ERROR The region is not used
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolGetRegionAddress (
+ IN PCH_SPI_PROTOCOL *This,
+ IN FLASH_REGION_TYPE FlashRegionType,
+ OUT UINT32 *BaseAddress,
+ OUT UINT32 *RegionSize
+ )
+{
+ SPI_INSTANCE *SpiInstance;
+ UINTN PchSpiBar0;
+ UINT32 ReadValue;
+
+ SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
+
+ if (FlashRegionType >= FlashRegionMax) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (FlashRegionType == FlashRegionAll) {
+ *BaseAddress = 0;
+ *RegionSize = SpiInstance->TotalFlashSize;
+ return EFI_SUCCESS;
+ }
+
+ PchSpiBar0 = AcquireSpiBar0 (SpiInstance);
+ ReadValue = MmioRead32 (PchSpiBar0 + (R_PCH_SPI_FREG0_FLASHD + (S_PCH_SPI_FREGX * ((UINT32) FlashRegionType))));
+ ReleaseSpiBar0 (SpiInstance);
+
+ //
+ // If the region is not used, the Region Base is 7FFFh and Region Limit is 0000h
+ //
+ if (ReadValue == B_PCH_SPI_FREGX_BASE_MASK) {
+ return EFI_DEVICE_ERROR;
+ }
+ *BaseAddress = ((ReadValue & B_PCH_SPI_FREGX_BASE_MASK) >> N_PCH_SPI_FREGX_BASE) <<
+ N_PCH_SPI_FREGX_BASE_REPR;
+ //
+ // Region limit address Bits[11:0] are assumed to be FFFh
+ //
+ *RegionSize = ((((ReadValue & B_PCH_SPI_FREGX_LIMIT_MASK) >> N_PCH_SPI_FREGX_LIMIT) + 1) <<
+ N_PCH_SPI_FREGX_LIMIT_REPR) - *BaseAddress;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Read PCH Soft Strap Values
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] SoftStrapAddr PCH Soft Strap address offset from FPSBA.
+ @param[in] ByteCount Number of bytes in SoftStrap data portion of the SPI cycle
+ @param[out] SoftStrapValue The Pointer to caller-allocated buffer containing PCH Soft Strap Value.
+ If the value of ByteCount is 0, the data type of SoftStrapValue should be UINT16 and SoftStrapValue will be PCH Soft Strap Length
+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolReadPchSoftStrap (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT32 SoftStrapAddr,
+ IN UINT32 ByteCount,
+ OUT VOID *SoftStrapValue
+ )
+{
+ SPI_INSTANCE *SpiInstance;
+ UINT32 StrapFlashAddr;
+ EFI_STATUS Status;
+
+ SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
+
+ if (ByteCount == 0) {
+ *(UINT16 *) SoftStrapValue = SpiInstance->PchStrapSize;
+ return EFI_SUCCESS;
+ }
+
+ if ((SoftStrapAddr + ByteCount) > (UINT32) SpiInstance->PchStrapSize) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // PCH Strap Flash Address = FPSBA + RamAddr
+ //
+ StrapFlashAddr = SpiInstance->PchStrapBaseAddr + SoftStrapAddr;
+
+ //
+ // Read PCH Soft straps from using execute command
+ //
+ Status = SendSpiCmd (
+ This,
+ FlashRegionDescriptor,
+ FlashCycleRead,
+ StrapFlashAddr,
+ ByteCount,
+ SoftStrapValue
+ );
+ return Status;
+}
+
+/**
+ Read CPU Soft Strap Values
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] SoftStrapAddr CPU Soft Strap address offset from FCPUSBA.
+ @param[in] ByteCount Number of bytes in SoftStrap data portion of the SPI cycle.
+ @param[out] SoftStrapValue The Pointer to caller-allocated buffer containing CPU Soft Strap Value.
+ If the value of ByteCount is 0, the data type of SoftStrapValue should be UINT16 and SoftStrapValue will be PCH Soft Strap Length
+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolReadCpuSoftStrap (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT32 SoftStrapAddr,
+ IN UINT32 ByteCount,
+ OUT VOID *SoftStrapValue
+ )
+{
+ SPI_INSTANCE *SpiInstance;
+ UINT32 StrapFlashAddr;
+ EFI_STATUS Status;
+
+ SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
+
+ if (ByteCount == 0) {
+ *(UINT16 *) SoftStrapValue = SpiInstance->CpuStrapSize;
+ return EFI_SUCCESS;
+ }
+
+ if ((SoftStrapAddr + ByteCount) > (UINT32) SpiInstance->CpuStrapSize) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // CPU Strap Flash Address = FCPUSBA + RamAddr
+ //
+ StrapFlashAddr = SpiInstance->CpuStrapBaseAddr + SoftStrapAddr;
+
+ //
+ // Read Cpu Soft straps from using execute command
+ //
+ Status = SendSpiCmd (
+ This,
+ FlashRegionDescriptor,
+ FlashCycleRead,
+ StrapFlashAddr,
+ ByteCount,
+ SoftStrapValue
+ );
+ return Status;
+}
+
+/**
+ This function sends the programmed SPI command to the slave device.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] SpiRegionType The SPI Region type for flash cycle which is listed in the Descriptor
+ @param[in] FlashCycleType The Flash SPI cycle type list in HSFC (Hardware Sequencing Flash Control Register) register
+ @param[in] Address The Flash Linear Address must fall within a region for which BIOS has access permissions.
+ @param[in] ByteCount Number of bytes in the data portion of the SPI cycle.
+ @param[in,out] Buffer Pointer to caller-allocated buffer containing the dada received or sent during the SPI cycle.
+
+ @retval EFI_SUCCESS SPI command completes successfully.
+ @retval EFI_DEVICE_ERROR Device error, the command aborts abnormally.
+ @retval EFI_ACCESS_DENIED Some unrecognized command encountered in hardware sequencing mode
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+**/
+EFI_STATUS
+SendSpiCmd (
+ IN PCH_SPI_PROTOCOL *This,
+ IN FLASH_REGION_TYPE FlashRegionType,
+ IN FLASH_CYCLE_TYPE FlashCycleType,
+ IN UINT32 Address,
+ IN UINT32 ByteCount,
+ IN OUT UINT8 *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Index;
+ SPI_INSTANCE *SpiInstance;
+ UINTN SpiBaseAddress;
+ UINTN PchSpiBar0;
+ UINT32 HardwareSpiAddr;
+ UINT32 FlashRegionSize;
+ UINT32 SpiDataCount;
+ UINT32 FlashCycle;
+ UINT8 BiosCtlSave;
+ UINT32 SmiEnSave;
+ UINT16 ABase;
+
+ Status = EFI_SUCCESS;
+ SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
+ SpiBaseAddress = SpiInstance->PchSpiBase;
+ PchSpiBar0 = AcquireSpiBar0 (SpiInstance);
+ SpiBaseAddress = SpiInstance->PchSpiBase;
+ ABase = SpiInstance->PchAcpiBase;
+
+ //
+ // Disable SMIs to make sure normal mode flash access is not interrupted by an SMI
+ // whose SMI handler accesses flash (e.g. for error logging)
+ //
+ // *** NOTE: if the SMI_LOCK bit is set (i.e., PMC PCI Offset A0h [4]='1'),
+ // clearing B_GBL_SMI_EN will not have effect. In this situation, some other
+ // synchronization methods must be applied here or in the consumer of the
+ // SendSpiCmd. An example method is disabling the specific SMI sources
+ // whose SMI handlers access flash before flash cycle and re-enabling the SMI
+ // sources after the flash cycle .
+ //
+ SmiEnSave = IoRead32 ((UINTN) (ABase + R_PCH_SMI_EN));
+ IoWrite32 ((UINTN) (ABase + R_PCH_SMI_EN), SmiEnSave & (UINT32) (~B_PCH_SMI_EN_GBL_SMI));
+ BiosCtlSave = MmioRead8 (SpiBaseAddress + R_PCH_SPI_BC) & B_PCH_SPI_BC_SRC;
+
+ //
+ // If it's write cycle, disable Prefetching, Caching and disable BIOS Write Protect
+ //
+ if ((FlashCycleType == FlashCycleWrite) ||
+ (FlashCycleType == FlashCycleErase)) {
+ Status = DisableBiosWriteProtect ();
+ if (EFI_ERROR (Status)) {
+ goto SendSpiCmdEnd;
+ }
+ MmioAndThenOr8 (
+ SpiBaseAddress + R_PCH_SPI_BC,
+ (UINT8) (~B_PCH_SPI_BC_SRC),
+ (UINT8) (V_PCH_SPI_BC_SRC_PREF_DIS_CACHE_DIS << N_PCH_SPI_BC_SRC)
+ );
+ }
+ //
+ // Make sure it's safe to program the command.
+ //
+ if (!WaitForSpiCycleComplete (This, PchSpiBar0, FALSE)) {
+ Status = EFI_DEVICE_ERROR;
+ goto SendSpiCmdEnd;
+ }
+
+ Status = SpiProtocolGetRegionAddress (This, FlashRegionType, &HardwareSpiAddr, &FlashRegionSize);
+ if (EFI_ERROR (Status)) {
+ goto SendSpiCmdEnd;
+ }
+ HardwareSpiAddr += Address;
+ if ((Address + ByteCount) > FlashRegionSize) {
+ Status = EFI_INVALID_PARAMETER;
+ goto SendSpiCmdEnd;
+ }
+
+ //
+ // Check for PCH SPI hardware sequencing required commands
+ //
+ FlashCycle = 0;
+ switch (FlashCycleType) {
+ case FlashCycleRead:
+ FlashCycle = (UINT32) (V_PCH_SPI_HSFSC_CYCLE_READ << N_PCH_SPI_HSFSC_CYCLE);
+ break;
+ case FlashCycleWrite:
+ FlashCycle = (UINT32) (V_PCH_SPI_HSFSC_CYCLE_WRITE << N_PCH_SPI_HSFSC_CYCLE);
+ break;
+ case FlashCycleErase:
+ if (((ByteCount % SIZE_4KB) != 0) ||
+ ((HardwareSpiAddr % SIZE_4KB) != 0)) {
+ ASSERT (FALSE);
+ Status = EFI_INVALID_PARAMETER;
+ goto SendSpiCmdEnd;
+ }
+ break;
+ case FlashCycleReadSfdp:
+ FlashCycle = (UINT32) (V_PCH_SPI_HSFSC_CYCLE_READ_SFDP << N_PCH_SPI_HSFSC_CYCLE);
+ break;
+ case FlashCycleReadJedecId:
+ FlashCycle = (UINT32) (V_PCH_SPI_HSFSC_CYCLE_READ_JEDEC_ID << N_PCH_SPI_HSFSC_CYCLE);
+ break;
+ case FlashCycleWriteStatus:
+ FlashCycle = (UINT32) (V_PCH_SPI_HSFSC_CYCLE_WRITE_STATUS << N_PCH_SPI_HSFSC_CYCLE);
+ break;
+ case FlashCycleReadStatus:
+ FlashCycle = (UINT32) (V_PCH_SPI_HSFSC_CYCLE_READ_STATUS << N_PCH_SPI_HSFSC_CYCLE);
+ break;
+ default:
+ //
+ // Unrecognized Operation
+ //
+ ASSERT (FALSE);
+ Status = EFI_INVALID_PARAMETER;
+ goto SendSpiCmdEnd;
+ break;
+ }
+
+ do {
+ SpiDataCount = ByteCount;
+ if ((FlashCycleType == FlashCycleRead) ||
+ (FlashCycleType == FlashCycleWrite) ||
+ (FlashCycleType == FlashCycleReadSfdp)) {
+ //
+ // Trim at 256 byte boundary per operation,
+ // - PCH SPI controller requires trimming at 4KB boundary
+ // - Some SPI chips require trimming at 256 byte boundary for write operation
+ // - Trimming has limited performance impact as we can read / write atmost 64 byte
+ // per operation
+ //
+ if (HardwareSpiAddr + ByteCount > ((HardwareSpiAddr + BIT8) &~(BIT8 - 1))) {
+ SpiDataCount = (((UINT32) (HardwareSpiAddr) + BIT8) &~(BIT8 - 1)) - (UINT32) (HardwareSpiAddr);
+ }
+ //
+ // Calculate the number of bytes to shift in/out during the SPI data cycle.
+ // Valid settings for the number of bytes duing each data portion of the
+ // PCH SPI cycles are: 0, 1, 2, 3, 4, 5, 6, 7, 8, 16, 24, 32, 40, 48, 56, 64
+ //
+ if (SpiDataCount >= 64) {
+ SpiDataCount = 64;
+ } else if ((SpiDataCount &~0x07) != 0) {
+ SpiDataCount = SpiDataCount &~0x07;
+ }
+ }
+ if (FlashCycleType == FlashCycleErase) {
+ if (((ByteCount / SIZE_64KB) != 0) &&
+ ((ByteCount % SIZE_64KB) == 0) &&
+ ((HardwareSpiAddr % SIZE_64KB) == 0)) {
+ if (HardwareSpiAddr < SpiInstance->Component1StartAddr) {
+ //
+ // Check whether Component0 support 64k Erase
+ //
+ if ((SpiInstance->SfdpVscc0Value & B_PCH_SPI_SFDPX_VSCCX_EO_64K) != 0) {
+ SpiDataCount = SIZE_64KB;
+ } else {
+ SpiDataCount = SIZE_4KB;
+ }
+ } else {
+ //
+ // Check whether Component1 support 64k Erase
+ //
+ if ((SpiInstance->SfdpVscc1Value & B_PCH_SPI_SFDPX_VSCCX_EO_64K) != 0) {
+ SpiDataCount = SIZE_64KB;
+ } else {
+ SpiDataCount = SIZE_4KB;
+ }
+ }
+ } else {
+ SpiDataCount = SIZE_4KB;
+ }
+ if (SpiDataCount == SIZE_4KB) {
+ FlashCycle = (UINT32) (V_PCH_SPI_HSFSC_CYCLE_4K_ERASE << N_PCH_SPI_HSFSC_CYCLE);
+ } else {
+ FlashCycle = (UINT32) (V_PCH_SPI_HSFSC_CYCLE_64K_ERASE << N_PCH_SPI_HSFSC_CYCLE);
+ }
+ }
+ //
+ // If it's write cycle, load data into the SPI data buffer.
+ //
+ if ((FlashCycleType == FlashCycleWrite) || (FlashCycleType == FlashCycleWriteStatus)) {
+ if ((SpiDataCount & 0x07) != 0) {
+ //
+ // Use Byte write if Data Count is 0, 1, 2, 3, 4, 5, 6, 7
+ //
+ for (Index = 0; Index < SpiDataCount; Index++) {
+ MmioWrite8 (PchSpiBar0 + R_PCH_SPI_FDATA00 + Index, Buffer[Index]);
+ }
+ } else {
+ //
+ // Use Dword write if Data Count is 8, 16, 24, 32, 40, 48, 56, 64
+ //
+ for (Index = 0; Index < SpiDataCount; Index += sizeof (UINT32)) {
+ MmioWrite32 (PchSpiBar0 + R_PCH_SPI_FDATA00 + Index, *(UINT32 *) (Buffer + Index));
+ }
+ }
+ }
+
+ //
+ // Set the Flash Address
+ //
+ MmioWrite32 (
+ (PchSpiBar0 + R_PCH_SPI_FADDR),
+ (UINT32) (HardwareSpiAddr & B_PCH_SPI_FADDR_MASK)
+ );
+
+ //
+ // Set Data count, Flash cycle, and Set Go bit to start a cycle
+ //
+ MmioAndThenOr32 (
+ PchSpiBar0 + R_PCH_SPI_HSFSC,
+ (UINT32) (~(B_PCH_SPI_HSFSC_FDBC_MASK | B_PCH_SPI_HSFSC_CYCLE_MASK)),
+ (UINT32) ((((SpiDataCount - 1) << N_PCH_SPI_HSFSC_FDBC) & B_PCH_SPI_HSFSC_FDBC_MASK) | FlashCycle | B_PCH_SPI_HSFSC_CYCLE_FGO)
+ );
+ //
+ // end of command execution
+ //
+ // Wait the SPI cycle to complete.
+ //
+ if (!WaitForSpiCycleComplete (This, PchSpiBar0, TRUE)) {
+ ASSERT (FALSE);
+ Status = EFI_DEVICE_ERROR;
+ goto SendSpiCmdEnd;
+ }
+ //
+ // If it's read cycle, load data into the call's buffer.
+ //
+ if ((FlashCycleType == FlashCycleRead) ||
+ (FlashCycleType == FlashCycleReadSfdp) ||
+ (FlashCycleType == FlashCycleReadJedecId) ||
+ (FlashCycleType == FlashCycleReadStatus)) {
+ if ((SpiDataCount & 0x07) != 0) {
+ //
+ // Use Byte read if Data Count is 0, 1, 2, 3, 4, 5, 6, 7
+ //
+ for (Index = 0; Index < SpiDataCount; Index++) {
+ Buffer[Index] = MmioRead8 (PchSpiBar0 + R_PCH_SPI_FDATA00 + Index);
+ }
+ } else {
+ //
+ // Use Dword read if Data Count is 8, 16, 24, 32, 40, 48, 56, 64
+ //
+ for (Index = 0; Index < SpiDataCount; Index += sizeof (UINT32)) {
+ *(UINT32 *) (Buffer + Index) = MmioRead32 (PchSpiBar0 + R_PCH_SPI_FDATA00 + Index);
+ }
+ }
+ }
+
+ HardwareSpiAddr += SpiDataCount;
+ Buffer += SpiDataCount;
+ ByteCount -= SpiDataCount;
+ } while (ByteCount > 0);
+
+SendSpiCmdEnd:
+ //
+ // Restore the settings for SPI Prefetching and Caching and enable BIOS Write Protect
+ //
+ if ((FlashCycleType == FlashCycleWrite) ||
+ (FlashCycleType == FlashCycleErase)) {
+ EnableBiosWriteProtect ();
+ MmioAndThenOr8 (
+ SpiBaseAddress + R_PCH_SPI_BC,
+ (UINT8) ~B_PCH_SPI_BC_SRC,
+ BiosCtlSave
+ );
+ }
+ //
+ // Restore SMIs.
+ //
+ IoWrite32 ((UINTN) (ABase + R_PCH_SMI_EN), SmiEnSave);
+
+ ReleaseSpiBar0 (SpiInstance);
+
+ return Status;
+}
+
+/**
+ Wait execution cycle to complete on the SPI interface.
+
+ @param[in] This The SPI protocol instance
+ @param[in] PchSpiBar0 Spi MMIO base address
+ @param[in] ErrorCheck TRUE if the SpiCycle needs to do the error check
+
+ @retval TRUE SPI cycle completed on the interface.
+ @retval FALSE Time out while waiting the SPI cycle to complete.
+ It's not safe to program the next command on the SPI interface.
+**/
+BOOLEAN
+WaitForSpiCycleComplete (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINTN PchSpiBar0,
+ IN BOOLEAN ErrorCheck
+ )
+{
+ UINT64 WaitTicks;
+ UINT64 WaitCount;
+ UINT32 Data32;
+ SPI_INSTANCE *SpiInstance;
+
+ SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
+
+ //
+ // Convert the wait period allowed into to tick count
+ //
+ WaitCount = WAIT_TIME / WAIT_PERIOD;
+ //
+ // Wait for the SPI cycle to complete.
+ //
+ for (WaitTicks = 0; WaitTicks < WaitCount; WaitTicks++) {
+ Data32 = MmioRead32 (PchSpiBar0 + R_PCH_SPI_HSFSC);
+ if ((Data32 & B_PCH_SPI_HSFSC_SCIP) == 0) {
+ MmioWrite32 (PchSpiBar0 + R_PCH_SPI_HSFSC, B_PCH_SPI_HSFSC_FCERR | B_PCH_SPI_HSFSC_FDONE);
+ if (((Data32 & B_PCH_SPI_HSFSC_FCERR) != 0) && (ErrorCheck == TRUE)) {
+ return FALSE;
+ } else {
+ return TRUE;
+ }
+ }
+ PchPmTimerStallRuntimeSafe (SpiInstance->PchAcpiBase, WAIT_PERIOD);
+ }
+ return FALSE;
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/DxePchHdaLib/DxePchHdaLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/DxePchHdaLib/DxePchHdaLib.inf
new file mode 100644
index 0000000000..52d7c8bbaf
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/DxePchHdaLib/DxePchHdaLib.inf
@@ -0,0 +1,51 @@
+## @file
+# Component information file for PCH HD Audio Library
+#
+# Copyright (c) 2017, 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 = DxePchHdaLib
+FILE_GUID = DA915B7F-EE08-4C1D-B3D0-DE7C52AB155A
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = PchHdaLib
+
+
+[LibraryClasses]
+BaseLib
+DebugLib
+MemoryAllocationLib
+BaseMemoryLib
+PchInfoLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+KabylakeSiliconPkg/KabylakeSiliconPrivate.dec
+
+
+[Pcd]
+ gSiPkgTokenSpaceGuid.PcdAcpiDefaultOemId
+ gSiPkgTokenSpaceGuid.PcdAcpiDefaultOemTableId
+ gSiPkgTokenSpaceGuid.PcdAcpiDefaultOemRevision
+ gSiPkgTokenSpaceGuid.PcdAcpiDefaultCreatorId
+ gSiPkgTokenSpaceGuid.PcdAcpiDefaultCreatorRevision
+
+
+[Sources]
+PchHdaLib.c
+PchHdaEndpoints.c
+PchHdaNhltConfig.c
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/DxePchHdaLib/PchHdaEndpoints.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/DxePchHdaLib/PchHdaEndpoints.c
new file mode 100644
index 0000000000..11c6ec0269
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/DxePchHdaLib/PchHdaEndpoints.c
@@ -0,0 +1,318 @@
+/** @file
+ This file contains HD Audio NHLT Endpoints definitions
+
+Copyright (c) 2017, 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 <PchHdaEndpoints.h>
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST WAVEFORMATEXTENSIBLE Ch1_48kHz16bitFormat =
+{
+ {
+ WAVE_FORMAT_EXTENSIBLE,
+ 1,
+ 48000,
+ 96000,
+ 2,
+ 16,
+ sizeof (WAVEFORMATEXTENSIBLE) - sizeof (WAVEFORMATEX)
+ },
+ {16},
+ KSAUDIO_SPEAKER_MONO,
+ KSDATAFORMAT_SUBTYPE_PCM
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST WAVEFORMATEXTENSIBLE Ch2_48kHz16bitFormat =
+{
+ {
+ WAVE_FORMAT_EXTENSIBLE,
+ 2,
+ 48000,
+ 192000,
+ 4,
+ 16,
+ sizeof (WAVEFORMATEXTENSIBLE) - sizeof (WAVEFORMATEX)
+ },
+ {16},
+ KSAUDIO_SPEAKER_STEREO,
+ KSDATAFORMAT_SUBTYPE_PCM
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST WAVEFORMATEXTENSIBLE Ch2_48kHz24bitFormat =
+{
+ {
+ WAVE_FORMAT_EXTENSIBLE,
+ 2,
+ 48000,
+ 384000,
+ 8,
+ 32,
+ sizeof (WAVEFORMATEXTENSIBLE) - sizeof (WAVEFORMATEX)
+ },
+ {24},
+ KSAUDIO_SPEAKER_STEREO,
+ KSDATAFORMAT_SUBTYPE_PCM
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST WAVEFORMATEXTENSIBLE Ch2_48kHz32bitFormat =
+{
+ {
+ WAVE_FORMAT_EXTENSIBLE,
+ 2,
+ 48000,
+ 384000,
+ 8,
+ 32,
+ sizeof (WAVEFORMATEXTENSIBLE) - sizeof (WAVEFORMATEX)
+ },
+ {32},
+ KSAUDIO_SPEAKER_STEREO,
+ KSDATAFORMAT_SUBTYPE_PCM
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST WAVEFORMATEXTENSIBLE Ch4_48kHz16bitFormat =
+{
+ {
+ WAVE_FORMAT_EXTENSIBLE,
+ 4,
+ 48000,
+ 384000,
+ 8,
+ 16,
+ sizeof (WAVEFORMATEXTENSIBLE) - sizeof (WAVEFORMATEX)
+ },
+ {16},
+ KSAUDIO_SPEAKER_QUAD,
+ KSDATAFORMAT_SUBTYPE_PCM
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST WAVEFORMATEXTENSIBLE Ch4_48kHz32bitFormat =
+{
+ {
+ WAVE_FORMAT_EXTENSIBLE,
+ 4,
+ 48000,
+ 384000,
+ 8,
+ 32,
+ sizeof (WAVEFORMATEXTENSIBLE) - sizeof (WAVEFORMATEX)
+ },
+ {32},
+ KSAUDIO_SPEAKER_QUAD,
+ KSDATAFORMAT_SUBTYPE_PCM
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST WAVEFORMATEXTENSIBLE NarrowbandFormat =
+{
+ {
+ WAVE_FORMAT_EXTENSIBLE,
+ 1,
+ 8000,
+ 16000,
+ 2,
+ 16,
+ sizeof (WAVEFORMATEXTENSIBLE) - sizeof (WAVEFORMATEX)
+ },
+ {16},
+ KSAUDIO_SPEAKER_MONO,
+ KSDATAFORMAT_SUBTYPE_PCM
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST WAVEFORMATEXTENSIBLE WidebandFormat =
+{
+ {
+ WAVE_FORMAT_EXTENSIBLE,
+ 1,
+ 16000,
+ 32000,
+ 2,
+ 16,
+ sizeof (WAVEFORMATEXTENSIBLE) - sizeof (WAVEFORMATEX)
+ },
+ {16},
+ KSAUDIO_SPEAKER_MONO,
+ KSDATAFORMAT_SUBTYPE_PCM
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST WAVEFORMATEXTENSIBLE A2dpFormat =
+{
+ {
+ WAVE_FORMAT_EXTENSIBLE,
+ 2,
+ 48000,
+ 384000,
+ 8,
+ 32,
+ sizeof (WAVEFORMATEXTENSIBLE) - sizeof (WAVEFORMATEX)
+ },
+ {24},
+ KSAUDIO_SPEAKER_STEREO,
+ KSDATAFORMAT_SUBTYPE_PCM
+};
+GLOBAL_REMOVE_IF_UNREFERENCED
+ENDPOINT_DESCRIPTOR HdaEndpointDmicX1 = {
+ 0, // EndpointDescriptorLength
+ HdaNhltLinkDmic, // LinkType
+ 0, // InstanceId
+ 0x8086, // HwVendorId
+ 0xae20, // HwDeviceId
+ 1, // HwRevisionId
+ 1, // HwSubsystemId
+ HdaNhltDeviceDmic, // DeviceType
+ 1, // Direction
+ 0, // VirtualBusId
+ { 0 }, // EndpointConfig
+ { 0 } // FormatsConfig
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+ENDPOINT_DESCRIPTOR HdaEndpointDmicX2 = {
+ 0, // EndpointDescriptorLength
+ HdaNhltLinkDmic, // LinkType
+ 0, // InstanceId
+ 0x8086, // HwVendorId
+ 0xae20, // HwDeviceId
+ 1, // HwRevisionId
+ 1, // HwSubsystemId
+ HdaNhltDeviceDmic, // DeviceType
+ 1, // Direction
+ 0, // VirtualBusId
+ { 0 }, // EndpointConfig
+ { 0 } // FormatsConfig
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+ENDPOINT_DESCRIPTOR HdaEndpointDmicX4 = {
+ 0, // EndpointDescriptorLength
+ HdaNhltLinkDmic, // LinkType
+ 0, // InstanceId
+ 0x8086, // HwVendorId
+ 0xae20, // HwDeviceId
+ 1, // HwRevisionId
+ 1, // HwSubsystemId
+ HdaNhltDeviceDmic, // DeviceType
+ 1, // Direction
+ 0, // VirtualBusId
+ { 0 }, // EndpointConfig
+ { 0 } // FormatsConfig
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+ENDPOINT_DESCRIPTOR HdaEndpointBtRender = {
+ 0, // EndpointDescriptorLength
+ HdaNhltLinkSsp, // LinkType
+ 0, // InstanceId
+ 0x8086, // HwVendorId
+ 0xae30, // HwDeviceId
+ 1, // HwRevisionId
+ 1, // HwSubsystemId
+ HdaNhltDeviceBt, // DeviceType
+ 0, // Direction
+ 2, // VirtualBusId
+ { 0 }, // EndpointConfig
+ { 0 } // FormatsConfig
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+ENDPOINT_DESCRIPTOR HdaEndpointBtCapture = {
+ 0, // EndpointDescriptorLength
+ HdaNhltLinkSsp, // LinkType
+ 0, // InstanceId
+ 0x8086, // HwVendorId
+ 0xae30, // HwDeviceId
+ 1, // HwRevisionId
+ 1, // HwSubsystemId
+ HdaNhltDeviceBt, // DeviceType
+ 1, // Direction
+ 2, // VirtualBusId
+ { 0 }, // EndpointConfig
+ { 0 } // FormatsConfig
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+ENDPOINT_DESCRIPTOR HdaEndpointI2sRender = {
+ 0, // EndpointDescriptorLength
+ HdaNhltLinkSsp, // LinkType
+ 1, // InstanceId
+ 0x8086, // HwVendorId
+ 0xae34, // HwDeviceId
+ 1, // HwRevisionId
+ 1, // HwSubsystemId
+ HdaNhltDeviceI2s, // DeviceType
+ 0, // Direction
+ 0, // VirtualBusId
+ { 0 }, // EndpointConfig
+ { 0 } // FormatsConfig
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+ENDPOINT_DESCRIPTOR HdaEndpointI2sCapture = {
+ 0, // EndpointDescriptorLength
+ HdaNhltLinkSsp, // LinkType
+ 1, // InstanceId
+ 0x8086, // HwVendorId
+ 0xae34, // HwDeviceId
+ 1, // HwRevisionId
+ 1, // HwSubsystemId
+ HdaNhltDeviceI2s, // DeviceType
+ 1, // Direction
+ 0, // VirtualBusId
+ { 0 }, // EndpointConfig
+ { 0 } // FormatsConfig
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 DmicX1Config[] =
+{
+ 0x00, // VirtualSlot
+ 0x00, // eIntcConfigTypeMicArray = 1 , eIntcConfigTypeGeneric = 0
+};
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 DmicX1ConfigSize = sizeof (DmicX1Config);
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 DmicX2Config[] =
+{
+ 0x00, // VirtualSlot
+ 0x01, // eIntcConfigTypeMicArray = 1 , eIntcConfigTypeGeneric = 0
+ 0x0A // ArrayType
+};
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 DmicX2ConfigSize = sizeof (DmicX2Config);
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 DmicX4Config[] =
+{
+ 0x00, // VirtualSlot
+ 0x01, // eIntcConfigTypeMicArray = 1 , eIntcConfigTypeGeneric = 0
+ 0x0D // ArrayType
+};
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 DmicX4ConfigSize = sizeof (DmicX4Config);
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 BtConfig[] = {0};
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 BtConfigSize = 0;
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 I2sRender1Config[] = {0};
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 I2sRender1ConfigSize = 0;
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 I2sRender2Config[] = {0x01};
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 I2sRender2ConfigSize = sizeof (I2sRender2Config);
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 I2sCaptureConfig[] = {0};
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 I2sCaptureConfigSize = 0;
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 NhltConfiguration[] = { 0xEFBEADDE };
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 NhltConfigurationSize = sizeof (NhltConfiguration);
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/DxePchHdaLib/PchHdaLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/DxePchHdaLib/PchHdaLib.c
new file mode 100644
index 0000000000..e577cd9038
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/DxePchHdaLib/PchHdaLib.c
@@ -0,0 +1,842 @@
+/** @file
+ PCH HD Audio Library implementation.
+
+Copyright (c) 2017, 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 <Uefi/UefiBaseType.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PchHdaLib.h>
+#include <Library/PchInfoLib.h>
+
+/**
+ Returns pointer to Endpoint ENDPOINT_DESCRIPTOR structure.
+
+ @param[in] *NhltTable Endpoint for which Format address is retrieved
+ @param[in] FormatIndex Index of Format to be retrieved
+
+ @retval Pointer to ENDPOINT_DESCRIPTOR structure with given index
+**/
+ENDPOINT_DESCRIPTOR *
+GetNhltEndpoint (
+ IN CONST NHLT_ACPI_TABLE *NhltTable,
+ IN CONST UINT8 EndpointIndex
+ )
+{
+ UINT8 i;
+ ENDPOINT_DESCRIPTOR *Endpoint;
+ Endpoint = (ENDPOINT_DESCRIPTOR*) (NhltTable->EndpointDescriptors);
+
+ if (EndpointIndex > NhltTable->EndpointCount) {
+ return NULL;
+ }
+
+ for (i = 0; i < EndpointIndex; i++) {
+ Endpoint = (ENDPOINT_DESCRIPTOR*) ((UINT8*) (Endpoint) + Endpoint->EndpointDescriptorLength);
+ }
+
+ return Endpoint;
+}
+
+/**
+ Returns pointer to Endpoint Specific Configuration SPECIFIC_CONFIG structure.
+
+ @param[in] *Endpoint Endpoint for which config address is retrieved
+
+ @retval Pointer to SPECIFIC_CONFIG structure with endpoint's capabilities
+**/
+SPECIFIC_CONFIG *
+GetNhltEndpointDeviceCapabilities (
+ IN CONST ENDPOINT_DESCRIPTOR *Endpoint
+ )
+{
+ return (SPECIFIC_CONFIG*) (&Endpoint->EndpointConfig);
+}
+
+/**
+ Returns pointer to all Formats Configuration FORMATS_CONFIG structure.
+
+ @param[in] *Endpoint Endpoint for which Formats address is retrieved
+
+ @retval Pointer to FORMATS_CONFIG structure
+**/
+FORMATS_CONFIG *
+GetNhltEndpointFormatsConfig (
+ IN CONST ENDPOINT_DESCRIPTOR *Endpoint
+ )
+{
+ FORMATS_CONFIG *FormatsConfig;
+ FormatsConfig = (FORMATS_CONFIG*) ((UINT8*) (&Endpoint->EndpointConfig)
+ + sizeof (Endpoint->EndpointConfig.CapabilitiesSize)
+ + Endpoint->EndpointConfig.CapabilitiesSize);
+
+ return FormatsConfig;
+}
+
+/**
+ Returns pointer to Format Configuration FORMAT_CONFIG structure.
+
+ @param[in] *Endpoint Endpoint for which Format address is retrieved
+ @param[in] FormatIndex Index of Format to be retrieved
+
+ @retval Pointer to FORMAT_CONFIG structure with given index
+**/
+FORMAT_CONFIG *
+GetNhltEndpointFormat (
+ IN CONST ENDPOINT_DESCRIPTOR *Endpoint,
+ IN CONST UINT8 FormatIndex
+ )
+{
+ UINT8 i;
+ UINT32 Length;
+ FORMATS_CONFIG *FormatsConfig;
+ FORMAT_CONFIG *Format;
+
+ Length = 0;
+ FormatsConfig = GetNhltEndpointFormatsConfig (Endpoint);
+ Format = FormatsConfig->FormatsConfiguration;
+
+ if (FormatIndex > FormatsConfig->FormatsCount) {
+ return NULL;
+ }
+
+ for (i = 0; i < FormatIndex; i++) {
+ Length = sizeof (Format->Format) + Format->FormatConfiguration.CapabilitiesSize
+ + sizeof (Format->FormatConfiguration.CapabilitiesSize);
+ Format = (FORMAT_CONFIG*) ((UINT8*) (Format) + Length);
+ }
+
+ return Format;
+}
+
+/**
+ Returns pointer to OED Configuration SPECIFIC_CONFIG structure.
+
+ @param[in] *NhltTable NHLT table for which OED address is retrieved
+
+ @retval Pointer to SPECIFIC_CONFIG structure with NHLT capabilities
+**/
+SPECIFIC_CONFIG *
+GetNhltOedConfig (
+ IN CONST NHLT_ACPI_TABLE *NhltTable
+ )
+{
+ ENDPOINT_DESCRIPTOR *Endpoint;
+ SPECIFIC_CONFIG *OedConfig;
+
+ Endpoint = GetNhltEndpoint (NhltTable, (NhltTable->EndpointCount));
+ OedConfig = (SPECIFIC_CONFIG*) ((UINT8*) (Endpoint));
+
+ return OedConfig;
+}
+
+/**
+ Prints Format configuration.
+
+ @param[in] *Format Format to be printed
+
+ @retval None
+**/
+VOID
+NhltFormatDump (
+ IN CONST FORMAT_CONFIG *Format
+ )
+{
+ UINT32 i;
+
+ DEBUG ((DEBUG_INFO, "------------------------------- FORMAT -------------------------------\n"));
+ DEBUG ((DEBUG_INFO, " Format->Format.Format.wFormatTag = 0x%x\n", Format->Format.Format.wFormatTag));
+ DEBUG ((DEBUG_INFO, " Format->Format.Format.nChannels = %d\n", Format->Format.Format.nChannels));
+ DEBUG ((DEBUG_INFO, " Format->Format.Format.nSamplesPerSec = %d\n", Format->Format.Format.nSamplesPerSec));
+ DEBUG ((DEBUG_INFO, " Format->Format.Format.nAvgBytesPerSec = %d\n", Format->Format.Format.nAvgBytesPerSec));
+ DEBUG ((DEBUG_INFO, " Format->Format.Format.nBlockAlign = %d\n", Format->Format.Format.nBlockAlign));
+ DEBUG ((DEBUG_INFO, " Format->Format.Format.wBitsPerSample = %d\n", Format->Format.Format.wBitsPerSample));
+ DEBUG ((DEBUG_INFO, " Format->Format.Format.cbSize = %d\n", Format->Format.Format.cbSize));
+ DEBUG ((DEBUG_INFO, " Format->Format.Samples = %d\n", Format->Format.Samples));
+ DEBUG ((DEBUG_INFO, " Format->Format.dwChannelMask = 0x%x\n", Format->Format.dwChannelMask));
+ DEBUG ((DEBUG_INFO, " Format->Format.SubFormat = %g\n", Format->Format.SubFormat));
+
+
+ DEBUG ((DEBUG_INFO, " Format->FormatConfiguration.CapabilitiesSize = %d B\n", Format->FormatConfiguration.CapabilitiesSize));
+ DEBUG ((DEBUG_VERBOSE, " Format->FormatConfiguration.Capabilities:"));
+ for (i = 0; i < ( Format->FormatConfiguration.CapabilitiesSize ) ; i++) {
+ if (i % 16 == 0) {
+ DEBUG ((DEBUG_VERBOSE, "\n"));
+ }
+ DEBUG ((DEBUG_VERBOSE, "0x%02x, ", Format->FormatConfiguration.Capabilities[i]));
+ }
+ DEBUG ((DEBUG_VERBOSE, "\n"));
+}
+
+/**
+ Prints Endpoint configuration.
+
+ @param[in] *Endpoint Endpoint to be printed
+
+ @retval None
+**/
+VOID
+NhltEndpointDump (
+ IN CONST ENDPOINT_DESCRIPTOR *Endpoint
+ )
+{
+ UINT8 i;
+ FORMATS_CONFIG *FormatsConfigs;
+ FORMAT_CONFIG *Format;
+
+ DEBUG ((DEBUG_INFO, "------------------------------ ENDPOINT ------------------------------\n"));
+ DEBUG ((DEBUG_INFO, " Endpoint->DeviceDescriptorLength = %d B\n", Endpoint->EndpointDescriptorLength));
+ DEBUG ((DEBUG_INFO, " Endpoint->LinkType = 0x%x\n", Endpoint->LinkType));
+ DEBUG ((DEBUG_INFO, " Endpoint->InstanceId = 0x%x\n", Endpoint->InstanceId));
+ DEBUG ((DEBUG_INFO, " Endpoint->HwVendorId = 0x%x\n", Endpoint->HwVendorId));
+ DEBUG ((DEBUG_INFO, " Endpoint->HwDeviceId = 0x%x\n", Endpoint->HwDeviceId));
+ DEBUG ((DEBUG_INFO, " Endpoint->HwRevisionId = 0x%x\n", Endpoint->HwRevisionId));
+ DEBUG ((DEBUG_INFO, " Endpoint->HwSubsystemId = 0x%x\n", Endpoint->HwSubsystemId));
+ DEBUG ((DEBUG_INFO, " Endpoint->DeviceType = 0x%x\n", Endpoint->DeviceType));
+ DEBUG ((DEBUG_INFO, " Endpoint->Direction = 0x%x\n", Endpoint->Direction));
+ DEBUG ((DEBUG_INFO, " Endpoint->VirtualBusId = 0x%x\n", Endpoint->VirtualBusId));
+
+ DEBUG ((DEBUG_INFO, " Endpoint->EndpointConfig.CapabilitiesSize = %d B\n", Endpoint->EndpointConfig.CapabilitiesSize));
+ DEBUG ((DEBUG_VERBOSE, " Endpoint->EndpointConfig.Capabilities:"));
+ for (i = 0; i < (Endpoint->EndpointConfig.CapabilitiesSize ) ; i++) {
+ if (i % 16 == 0) DEBUG ((DEBUG_VERBOSE, "\n"));
+ DEBUG ((DEBUG_VERBOSE, "0x%02x, ", Endpoint->EndpointConfig.Capabilities[i]));
+ }
+
+ FormatsConfigs = GetNhltEndpointFormatsConfig (Endpoint);
+
+ DEBUG ((DEBUG_INFO, "\n"));
+ DEBUG ((DEBUG_INFO, " Endpoint->FormatsConfig.FormatsCount = %d\n", FormatsConfigs->FormatsCount));
+ for (i = 0; i < FormatsConfigs->FormatsCount; i++) {
+ Format = GetNhltEndpointFormat (Endpoint, i);
+ if (Format != NULL) {
+ NhltFormatDump (Format);
+ }
+ }
+
+ DEBUG ((DEBUG_VERBOSE, "\n"));
+}
+
+/**
+ Prints OED (Offload Engine Driver) configuration.
+
+ @param[in] *OedConfig OED to be printed
+
+ @retval None
+**/
+VOID
+NhltOedConfigDump (
+ IN CONST SPECIFIC_CONFIG *OedConfig
+ )
+{
+ UINT8 i;
+
+ DEBUG ((DEBUG_INFO, "-------------------------- OED CONFIGURATION -------------------------\n"));
+ DEBUG ((DEBUG_INFO, " OedConfig->CapabilitiesSize = %d B\n", OedConfig->CapabilitiesSize));
+ DEBUG ((DEBUG_VERBOSE, " OedConfig->Capabilities:"));
+ for (i = 0; i < (OedConfig->CapabilitiesSize) ; i++) {
+ if (i % 16 == 0) DEBUG ((DEBUG_VERBOSE, "\n"));
+ DEBUG ((DEBUG_VERBOSE, "0x%02x, ", OedConfig->Capabilities[i]));
+ }
+
+ DEBUG ((DEBUG_VERBOSE, "\n"));
+}
+
+/**
+ Prints NHLT (Non HDA-Link Table) to be exposed via ACPI (aka. OED (Offload Engine Driver) Configuration Table).
+
+ @param[in] *NhltTable The NHLT table to print
+
+ @retval None
+**/
+VOID
+NhltAcpiTableDump (
+ IN NHLT_ACPI_TABLE *NhltTable
+ )
+{
+ DEBUG_CODE_BEGIN ();
+ UINT8 i;
+
+ DEBUG ((DEBUG_INFO, "\n"));
+ DEBUG ((DEBUG_INFO, "--- NHLT ACPI Table Dump [OED (Offload Engine Driver) Configuration] ---\n"));
+
+ DEBUG ((DEBUG_INFO, "sizeof NHLT_ACPI_TABLE = %d B\n", sizeof (NHLT_ACPI_TABLE)));
+ DEBUG ((DEBUG_INFO, "sizeof EFI_ACPI_DESCRIPTION_HEADER = %d B\n", sizeof (EFI_ACPI_DESCRIPTION_HEADER)));
+ DEBUG ((DEBUG_INFO, "sizeof ENDPOINT_DESCRIPTOR = %d B\n", sizeof (ENDPOINT_DESCRIPTOR)));
+ DEBUG ((DEBUG_INFO, "sizeof SPECIFIC_CONFIG = %d B\n", sizeof (SPECIFIC_CONFIG)));
+ DEBUG ((DEBUG_INFO, "sizeof FORMATS_CONFIG = %d B\n", sizeof (FORMATS_CONFIG)));
+ DEBUG ((DEBUG_INFO, "sizeof FORMAT_CONFIG = %d B\n", sizeof (FORMAT_CONFIG)));
+ DEBUG ((DEBUG_INFO, "sizeof WAVEFORMATEXTENSIBLE = %d B\n", sizeof (WAVEFORMATEXTENSIBLE)));
+
+ DEBUG ((DEBUG_INFO, " NHLT_ACPI_TABLE Header.Signature = 0x%08x\n", NhltTable->Header.Signature));
+ DEBUG ((DEBUG_INFO, " NHLT_ACPI_TABLE Header.Length = 0x%08x\n", NhltTable->Header.Length));
+ DEBUG ((DEBUG_INFO, " NHLT_ACPI_TABLE Header.Revision = 0x%02x\n", NhltTable->Header.Revision));
+ DEBUG ((DEBUG_INFO, " NHLT_ACPI_TABLE Header.Checksum = 0x%02x\n", NhltTable->Header.Checksum));
+ DEBUG ((DEBUG_INFO, " NHLT_ACPI_TABLE Header.OemId = %a\n", NhltTable->Header.OemId));
+ DEBUG ((DEBUG_INFO, " NHLT_ACPI_TABLE Header.OemTableId = 0x%lx\n", NhltTable->Header.OemTableId));
+ DEBUG ((DEBUG_INFO, " NHLT_ACPI_TABLE Header.OemRevision = 0x%08x\n", NhltTable->Header.OemRevision));
+ DEBUG ((DEBUG_INFO, " NHLT_ACPI_TABLE Header.CreatorId = 0x%08x\n", NhltTable->Header.CreatorId));
+ DEBUG ((DEBUG_INFO, " NHLT_ACPI_TABLE Header.CreatorRevision = 0x%08x\n", NhltTable->Header.CreatorRevision));
+ DEBUG ((DEBUG_INFO, "\n"));
+
+ DEBUG ((DEBUG_INFO, " NHLT_ACPI_TABLE EndpointCount = %d\n", NhltTable->EndpointCount));
+ for (i = 0; i < NhltTable->EndpointCount; i++) {
+ NhltEndpointDump (GetNhltEndpoint (NhltTable, i));
+ }
+
+ NhltOedConfigDump (GetNhltOedConfig (NhltTable));
+ DEBUG ((DEBUG_INFO, "----------------------------------------------------------------------\n"));
+
+ DEBUG_CODE_END ();
+}
+
+/**
+ Constructs FORMATS_CONFIGS structure based on given formats list.
+
+ @param[in][out] *Endpoint Endpoint for which format structures are created
+ @param[in] FormatBitmask Bitmask of formats supported for given endpoint
+
+ @retval Size of created FORMATS_CONFIGS structure
+**/
+UINT32
+NhltFormatsConstructor (
+ IN OUT ENDPOINT_DESCRIPTOR *Endpoint,
+ IN CONST UINT32 FormatsBitmask
+ )
+{
+ FORMATS_CONFIG *FormatsConfig;
+ FORMAT_CONFIG *Format;
+ UINT8 FormatIndex;
+ UINT32 FormatsConfigLength;
+
+ DEBUG ((DEBUG_INFO, "NhltFormatsConstructor() Start, FormatsBitmask = 0x%08x\n", FormatsBitmask));
+
+ FormatsConfig = NULL;
+ FormatIndex = 0;
+ FormatsConfigLength = 0;
+
+ if (!FormatsBitmask) {
+ DEBUG ((DEBUG_WARN, "No supported format found!\n"));
+ return 0;
+ }
+
+ FormatsConfig = GetNhltEndpointFormatsConfig (Endpoint);
+ FormatsConfig->FormatsCount = 0;
+
+ if (FormatsBitmask & B_HDA_DMIC_2CH_48KHZ_16BIT_FORMAT) {
+ DEBUG ((DEBUG_INFO, "Format: B_HDA_DMIC_2CH_48KHZ_16BIT_FORMAT\n"));
+
+ Format = GetNhltEndpointFormat (Endpoint, FormatIndex++);
+ if (Format != NULL) {
+ CopyMem (&(Format->Format), &Ch2_48kHz16bitFormat, sizeof (WAVEFORMATEXTENSIBLE));
+
+ Format->FormatConfiguration.CapabilitiesSize = DmicStereo16BitFormatConfigSize;
+ CopyMem (Format->FormatConfiguration.Capabilities, DmicStereo16BitFormatConfig, DmicStereo16BitFormatConfigSize);
+
+ FormatsConfigLength += sizeof (*Format)
+ - sizeof (Format->FormatConfiguration.Capabilities)
+ + Format->FormatConfiguration.CapabilitiesSize;
+ FormatsConfig->FormatsCount++;
+ }
+ }
+
+ if (FormatsBitmask & B_HDA_DMIC_2CH_48KHZ_32BIT_FORMAT) {
+ DEBUG ((DEBUG_INFO, "Format: B_HDA_DMIC_2CH_48KHZ_32BIT_FORMAT\n"));
+
+ Format = GetNhltEndpointFormat (Endpoint, FormatIndex++);
+ if (Format != NULL) {
+ CopyMem (&(Format->Format), &Ch2_48kHz32bitFormat, sizeof (WAVEFORMATEXTENSIBLE));
+
+ Format->FormatConfiguration.CapabilitiesSize = DmicStereo32BitFormatConfigSize;
+ CopyMem (Format->FormatConfiguration.Capabilities, DmicStereo32BitFormatConfig, DmicStereo32BitFormatConfigSize);
+
+ FormatsConfigLength += sizeof (*Format)
+ - sizeof (Format->FormatConfiguration.Capabilities)
+ + Format->FormatConfiguration.CapabilitiesSize;
+ FormatsConfig->FormatsCount++;
+ }
+ }
+
+ if (FormatsBitmask & B_HDA_DMIC_4CH_48KHZ_16BIT_FORMAT) {
+ DEBUG ((DEBUG_INFO, "Format: B_HDA_DMIC_4CH_48KHZ_16BIT_FORMAT\n"));
+
+ Format = GetNhltEndpointFormat (Endpoint, FormatIndex++);
+ if (Format != NULL) {
+ CopyMem (&(Format->Format), &Ch4_48kHz16bitFormat, sizeof (WAVEFORMATEXTENSIBLE));
+
+ Format->FormatConfiguration.CapabilitiesSize = DmicQuad16BitFormatConfigSize;
+ CopyMem (Format->FormatConfiguration.Capabilities, DmicQuad16BitFormatConfig, DmicQuad16BitFormatConfigSize);
+
+ FormatsConfigLength += sizeof (*Format)
+ - sizeof (Format->FormatConfiguration.Capabilities)
+ + Format->FormatConfiguration.CapabilitiesSize;
+ FormatsConfig->FormatsCount++;
+ }
+ }
+
+ if (FormatsBitmask & B_HDA_DMIC_4CH_48KHZ_32BIT_FORMAT) {
+ DEBUG ((DEBUG_INFO, "Format: B_HDA_DMIC_4CH_48KHZ_32BIT_FORMAT\n"));
+
+ Format = GetNhltEndpointFormat (Endpoint, FormatIndex++);
+ if (Format != NULL) {
+ CopyMem (&(Format->Format), &Ch4_48kHz32bitFormat, sizeof (WAVEFORMATEXTENSIBLE));
+
+ Format->FormatConfiguration.CapabilitiesSize = DmicQuad32BitFormatConfigSize;
+ CopyMem (Format->FormatConfiguration.Capabilities, DmicQuad32BitFormatConfig, DmicQuad32BitFormatConfigSize);
+
+ FormatsConfigLength += sizeof (*Format)
+ - sizeof (Format->FormatConfiguration.Capabilities)
+ + Format->FormatConfiguration.CapabilitiesSize;
+ FormatsConfig->FormatsCount++;
+ }
+ }
+
+ if (FormatsBitmask & B_HDA_DMIC_1CH_48KHZ_16BIT_FORMAT) {
+ DEBUG ((DEBUG_INFO, "Format: B_HDA_DMIC_1CH_48KHZ_16BIT_FORMAT\n"));
+
+ Format = GetNhltEndpointFormat (Endpoint, FormatIndex++);
+ if (Format != NULL) {
+ CopyMem (&(Format->Format), &Ch1_48kHz16bitFormat, sizeof (WAVEFORMATEXTENSIBLE));
+
+ Format->FormatConfiguration.CapabilitiesSize = DmicMono16BitFormatConfigSize;
+ CopyMem (Format->FormatConfiguration.Capabilities, DmicMono16BitFormatConfig, DmicMono16BitFormatConfigSize);
+
+ FormatsConfigLength += sizeof (*Format)
+ - sizeof (Format->FormatConfiguration.Capabilities)
+ + Format->FormatConfiguration.CapabilitiesSize;
+ FormatsConfig->FormatsCount++;
+ }
+ }
+
+ if (FormatsBitmask & B_HDA_BT_NARROWBAND_FORMAT) {
+ DEBUG ((DEBUG_INFO, "Format: B_HDA_BT_NARROWBAND_FORMAT\n"));
+
+ Format = GetNhltEndpointFormat (Endpoint, FormatIndex++);
+ if (Format != NULL) {
+ CopyMem (&(Format->Format), &NarrowbandFormat, sizeof (WAVEFORMATEXTENSIBLE));
+
+ Format->FormatConfiguration.CapabilitiesSize = BtFormatConfigSize;
+ CopyMem (Format->FormatConfiguration.Capabilities, BtFormatConfig, BtFormatConfigSize);
+
+ FormatsConfigLength += sizeof (*Format)
+ - sizeof (Format->FormatConfiguration.Capabilities)
+ + Format->FormatConfiguration.CapabilitiesSize;
+ FormatsConfig->FormatsCount++;
+ }
+ }
+
+ if (FormatsBitmask & B_HDA_BT_WIDEBAND_FORMAT) {
+ DEBUG ((DEBUG_INFO, "Format: B_HDA_BT_WIDEBAND_FORMAT\n"));
+
+ Format = GetNhltEndpointFormat (Endpoint, FormatIndex++);
+ if (Format != NULL) {
+ CopyMem (&(Format->Format), &WidebandFormat, sizeof (WAVEFORMATEXTENSIBLE));
+
+ Format->FormatConfiguration.CapabilitiesSize = BtFormatConfigSize;
+ CopyMem (Format->FormatConfiguration.Capabilities, BtFormatConfig, BtFormatConfigSize);
+
+ FormatsConfigLength += sizeof (*Format)
+ - sizeof (Format->FormatConfiguration.Capabilities)
+ + Format->FormatConfiguration.CapabilitiesSize;
+ FormatsConfig->FormatsCount++;
+ }
+ }
+
+ if (FormatsBitmask & B_HDA_BT_A2DP_FORMAT) {
+ DEBUG ((DEBUG_INFO, "Format: B_HDA_BT_A2DP_FORMAT\n"));
+
+ Format = GetNhltEndpointFormat (Endpoint, FormatIndex++);
+ if (Format != NULL) {
+ CopyMem (&(Format->Format), &A2dpFormat, sizeof (WAVEFORMATEXTENSIBLE));
+
+ Format->FormatConfiguration.CapabilitiesSize = BtFormatConfigSize;
+ CopyMem (Format->FormatConfiguration.Capabilities, BtFormatConfig, BtFormatConfigSize);
+
+ FormatsConfigLength += sizeof (*Format)
+ - sizeof (Format->FormatConfiguration.Capabilities)
+ + Format->FormatConfiguration.CapabilitiesSize;
+ FormatsConfig->FormatsCount++;
+ }
+ }
+
+ if (FormatsBitmask & B_HDA_I2S_RTK298_RENDER_4CH_48KHZ_24BIT_FORMAT) {
+ DEBUG ((DEBUG_INFO, "Format: B_HDA_I2S_RTK298_RENDER_4CH_48KHZ_24BIT_FORMAT\n"));
+
+ Format = GetNhltEndpointFormat (Endpoint, FormatIndex++);
+ if (Format != NULL) {
+ CopyMem (&(Format->Format), &Ch2_48kHz24bitFormat, sizeof (WAVEFORMATEXTENSIBLE));
+
+ Format->FormatConfiguration.CapabilitiesSize = I2sRtk298Render4ch48kHz24bitFormatConfigSize;
+ CopyMem (Format->FormatConfiguration.Capabilities, I2sRtk298Render4ch48kHz24bitFormatConfig, I2sRtk298Render4ch48kHz24bitFormatConfigSize);
+
+ FormatsConfigLength += sizeof (*Format)
+ - sizeof (Format->FormatConfiguration.Capabilities)
+ + Format->FormatConfiguration.CapabilitiesSize;
+ FormatsConfig->FormatsCount++;
+ }
+ }
+
+ if (FormatsBitmask & B_HDA_I2S_RTK298_CAPTURE_4CH_48KHZ_24BIT_FORMAT) {
+ DEBUG ((DEBUG_INFO, "Format: B_HDA_I2S_RTK298_CAPTURE_4CH_48KHZ_24BIT_FORMAT\n"));
+
+ Format = GetNhltEndpointFormat (Endpoint, FormatIndex++);
+ if (Format != NULL) {
+ CopyMem (&(Format->Format), &Ch2_48kHz24bitFormat, sizeof (WAVEFORMATEXTENSIBLE));
+
+ Format->FormatConfiguration.CapabilitiesSize = I2sRtk298Capture4ch48kHz24bitFormatConfigSize;
+ CopyMem (Format->FormatConfiguration.Capabilities, I2sRtk298Capture4ch48kHz24bitFormatConfig, I2sRtk298Capture4ch48kHz24bitFormatConfigSize);
+
+ FormatsConfigLength += sizeof (*Format)
+ - sizeof (Format->FormatConfiguration.Capabilities)
+ + Format->FormatConfiguration.CapabilitiesSize;
+ FormatsConfig->FormatsCount++;
+ }
+ }
+
+ if (FormatsBitmask & B_HDA_I2S_RTK286S_2CH_48KHZ_24BIT_FORMAT) {
+ DEBUG ((DEBUG_INFO, "Format: B_HDA_I2S_RTK286S_2CH_48KHZ_24BIT_FORMAT\n"));
+
+ Format = GetNhltEndpointFormat (Endpoint, FormatIndex++);
+ if (Format != NULL) {
+ CopyMem (&(Format->Format), &Ch2_48kHz24bitFormat, sizeof (WAVEFORMATEXTENSIBLE));
+
+ Format->FormatConfiguration.CapabilitiesSize = I2sRtk286S2ch48kHzFormatConfigSize;
+ CopyMem (Format->FormatConfiguration.Capabilities, I2sRtk286S2ch48kHzFormatConfig, I2sRtk286S2ch48kHzFormatConfigSize);
+
+ FormatsConfigLength += sizeof (*Format)
+ - sizeof (Format->FormatConfiguration.Capabilities)
+ + Format->FormatConfiguration.CapabilitiesSize;
+ FormatsConfig->FormatsCount++;
+ }
+ }
+
+ if (FormatsBitmask & B_HDA_I2S_ADI_4CH_48KHZ_32BIT_FORMAT) {
+ DEBUG ((DEBUG_INFO, "Format: B_HDA_I2S_ADI_4CH_48KHZ_32BIT_FORMAT\n"));
+
+ Format = GetNhltEndpointFormat (Endpoint, FormatIndex++);
+ if (Format != NULL) {
+ CopyMem (&(Format->Format), &Ch4_48kHz32bitFormat, sizeof (WAVEFORMATEXTENSIBLE));
+
+ Format->FormatConfiguration.CapabilitiesSize = I2sAdi4ch48kHzFormatConfigSize;
+ CopyMem (Format->FormatConfiguration.Capabilities, I2sAdi4ch48kHzFormatConfig, I2sAdi4ch48kHzFormatConfigSize);
+
+ FormatsConfigLength += sizeof (*Format)
+ - sizeof (Format->FormatConfiguration.Capabilities)
+ + Format->FormatConfiguration.CapabilitiesSize;
+ FormatsConfig->FormatsCount++;
+ }
+ }
+
+ if (FormatsBitmask & B_HDA_I2S_48KHZ_24BIT_MASTER_FORMAT) {
+ DEBUG ((DEBUG_INFO, "Format: B_HDA_I2S_48KHZ_24BIT_MASTER_FORMAT\n"));
+
+ Format = GetNhltEndpointFormat (Endpoint, FormatIndex++);
+ if (Format != NULL) {
+ CopyMem (&(Format->Format), &Ch2_48kHz24bitFormat, sizeof (WAVEFORMATEXTENSIBLE));
+
+ Format->FormatConfiguration.CapabilitiesSize = I2s48kHz24bitMasterFormatConfigSize;
+ CopyMem (Format->FormatConfiguration.Capabilities, I2s48kHz24bitMasterFormatConfig, I2s48kHz24bitMasterFormatConfigSize);
+
+ FormatsConfigLength += sizeof (*Format)
+ - sizeof (Format->FormatConfiguration.Capabilities)
+ + Format->FormatConfiguration.CapabilitiesSize;
+ FormatsConfig->FormatsCount++;
+ }
+ }
+
+ if (FormatsBitmask & B_HDA_I2S_48KHZ_24BIT_SLAVE_FORMAT) {
+ DEBUG ((DEBUG_INFO, "Format: B_HDA_I2S_48KHZ_24BIT_SLAVE_FORMAT\n"));
+
+ Format = GetNhltEndpointFormat (Endpoint, FormatIndex++);
+ if (Format != NULL) {
+ CopyMem (&(Format->Format), &Ch2_48kHz24bitFormat, sizeof (WAVEFORMATEXTENSIBLE));
+
+ Format->FormatConfiguration.CapabilitiesSize = I2s48kHz24bitSlaveFormatConfigSize;
+ CopyMem (Format->FormatConfiguration.Capabilities, I2s48kHz24bitSlaveFormatConfig, I2s48kHz24bitSlaveFormatConfigSize);
+
+ FormatsConfigLength += sizeof (*Format)
+ - sizeof (Format->FormatConfiguration.Capabilities)
+ + Format->FormatConfiguration.CapabilitiesSize;
+ FormatsConfig->FormatsCount++;
+ }
+ }
+
+ if (FormatsBitmask & B_HDA_I2S_PCM_8KHZ_16BIT_MASTER_FORMAT) {
+ DEBUG ((DEBUG_INFO, "Format: B_HDA_I2S_PCM_8KHZ_16BIT_MASTER_FORMAT\n"));
+
+ Format = GetNhltEndpointFormat (Endpoint, FormatIndex++);
+ if (Format != NULL) {
+ CopyMem (&(Format->Format), &NarrowbandFormat, sizeof (WAVEFORMATEXTENSIBLE));
+
+ Format->FormatConfiguration.CapabilitiesSize = I2sPcm8kHz16bitMasterFormatConfigSize;
+ CopyMem (Format->FormatConfiguration.Capabilities, I2sPcm8kHz16bitMasterFormatConfig, I2sPcm8kHz16bitMasterFormatConfigSize);
+
+ FormatsConfigLength += sizeof (*Format)
+ - sizeof (Format->FormatConfiguration.Capabilities)
+ + Format->FormatConfiguration.CapabilitiesSize;
+ FormatsConfig->FormatsCount++;
+ }
+ }
+
+ if (FormatsBitmask & B_HDA_I2S_PCM_8KHZ_16BIT_SLAVE_FORMAT) {
+ DEBUG ((DEBUG_INFO, "Format: B_HDA_I2S_PCM_8KHZ_16BIT_SLAVE_FORMAT\n"));
+
+ Format = GetNhltEndpointFormat (Endpoint, FormatIndex++);
+ if (Format != NULL) {
+ CopyMem (&(Format->Format), &NarrowbandFormat, sizeof (WAVEFORMATEXTENSIBLE));
+
+ Format->FormatConfiguration.CapabilitiesSize = I2sPcm8kHz16bitSlaveFormatConfigSize;
+ CopyMem (Format->FormatConfiguration.Capabilities, I2sPcm8kHz16bitSlaveFormatConfig, I2sPcm8kHz16bitSlaveFormatConfigSize);
+
+ FormatsConfigLength += sizeof (*Format)
+ - sizeof (Format->FormatConfiguration.Capabilities)
+ + Format->FormatConfiguration.CapabilitiesSize;
+ FormatsConfig->FormatsCount++;
+ }
+ }
+
+ DEBUG ((DEBUG_INFO, "NhltFormatsConstructor() End, FormatsCount = %d, FormatsConfigLength = %d B\n", FormatsConfig->FormatsCount, FormatsConfigLength));
+ return FormatsConfigLength;
+}
+
+/**
+ Constructs NHLT_ENDPOINT structure based on given endpoint type.
+
+ @param[in][out] *NhltTable NHLT table for which endpoint is created
+ @param[in] EndpointType Type of endpoint to be created
+ @param[in] EndpointFormatsBitmask Bitmask of formats supported by endpoint
+ @param[in] EndpointIndex Endpoint index in NHLT table
+
+ @retval Size of created NHLT_ENDPOINT structure
+**/
+UINT32
+NhltEndpointConstructor (
+ IN OUT NHLT_ACPI_TABLE *NhltTable,
+ IN NHLT_ENDPOINT EndpointType,
+ IN UINT32 EndpointFormatsBitmask,
+ IN UINT8 EndpointIndex
+ )
+{
+
+ ENDPOINT_DESCRIPTOR *Endpoint;
+ SPECIFIC_CONFIG *EndpointConfig;
+ CONST UINT8 *EndpointConfigBuffer;
+ UINT32 EndpointConfigBufferSize;
+ UINT32 EndpointDescriptorLength;
+
+ DEBUG ((DEBUG_INFO, "NhltEndpointConstructor() Start, EndpointIndex = %d\n", EndpointIndex));
+
+ EndpointDescriptorLength = 0;
+ Endpoint = GetNhltEndpoint (NhltTable, EndpointIndex);
+ if (Endpoint == NULL) {
+ return 0;
+ }
+ EndpointDescriptorLength = sizeof (ENDPOINT_DESCRIPTOR)
+ - sizeof (SPECIFIC_CONFIG)
+ - sizeof (FORMAT_CONFIG);
+
+ switch (EndpointType) {
+ case HdaDmicX1:
+ DEBUG ((DEBUG_INFO, "Endpoint: HdaDmicX1\n"));
+ CopyMem (Endpoint, &HdaEndpointDmicX1, sizeof (ENDPOINT_DESCRIPTOR));
+ EndpointConfigBuffer = DmicX1Config;
+ EndpointConfigBufferSize = DmicX1ConfigSize;
+ break;
+ case HdaDmicX2:
+ DEBUG ((DEBUG_INFO, "Endpoint: HdaDmicX2\n"));
+ CopyMem (Endpoint, &HdaEndpointDmicX2, sizeof (ENDPOINT_DESCRIPTOR));
+ EndpointConfigBuffer = DmicX2Config;
+ EndpointConfigBufferSize = DmicX2ConfigSize;
+ break;
+ case HdaDmicX4:
+ DEBUG ((DEBUG_INFO, "Endpoint: HdaDmicX4\n"));
+ CopyMem (Endpoint, &HdaEndpointDmicX4, sizeof (ENDPOINT_DESCRIPTOR));
+ EndpointConfigBuffer = DmicX4Config;
+ EndpointConfigBufferSize = DmicX4ConfigSize;
+ break;
+ case HdaBtRender:
+ DEBUG ((DEBUG_INFO, "Endpoint: HdaBtRender\n"));
+ CopyMem (Endpoint, &HdaEndpointBtRender, sizeof (ENDPOINT_DESCRIPTOR));
+ if (GetPchSeries () == PchH) {
+ Endpoint->VirtualBusId = 0;
+ }
+
+ EndpointConfigBuffer = BtConfig;
+ EndpointConfigBufferSize = BtConfigSize;
+ break;
+ case HdaBtCapture:
+ DEBUG ((DEBUG_INFO, "Endpoint: HdaBtCapture\n"));
+ CopyMem (Endpoint, &HdaEndpointBtCapture, sizeof (ENDPOINT_DESCRIPTOR));
+ if (GetPchSeries () == PchH) {
+ Endpoint->VirtualBusId = 0;
+ }
+
+ EndpointConfigBuffer = BtConfig;
+ EndpointConfigBufferSize = BtConfigSize;
+ break;
+ case HdaI2sRender1:
+ DEBUG ((DEBUG_INFO, "Endpoint: HdaI2sRender1\n"));
+ CopyMem (Endpoint, &HdaEndpointI2sRender, sizeof (ENDPOINT_DESCRIPTOR));
+ EndpointConfigBuffer = I2sRender1Config;
+ EndpointConfigBufferSize = I2sRender1ConfigSize;
+ break;
+ case HdaI2sRender2:
+ DEBUG ((DEBUG_INFO, "Endpoint: HdaI2sRender2\n"));
+ CopyMem (Endpoint, &HdaEndpointI2sRender, sizeof (ENDPOINT_DESCRIPTOR));
+ EndpointConfigBuffer = I2sRender2Config;
+ EndpointConfigBufferSize = I2sRender2ConfigSize;
+ break;
+ case HdaI2sCapture:
+ DEBUG ((DEBUG_INFO, "Endpoint: HdaI2sCapture\n"));
+ CopyMem (Endpoint, &HdaEndpointI2sCapture, sizeof (ENDPOINT_DESCRIPTOR));
+ EndpointConfigBuffer = I2sCaptureConfig;
+ EndpointConfigBufferSize = I2sCaptureConfigSize;
+ break;
+ default:
+ DEBUG ((DEBUG_WARN, "Unknown endpoint!\n"));
+ return 0;
+ }
+
+ EndpointConfig = GetNhltEndpointDeviceCapabilities (Endpoint);
+ EndpointConfig->CapabilitiesSize = EndpointConfigBufferSize;
+ CopyMem (EndpointConfig->Capabilities, EndpointConfigBuffer, EndpointConfig->CapabilitiesSize);
+ EndpointDescriptorLength += sizeof (*EndpointConfig)
+ - sizeof (EndpointConfig->Capabilities)
+ + EndpointConfig->CapabilitiesSize;
+
+ EndpointDescriptorLength += NhltFormatsConstructor (Endpoint, EndpointFormatsBitmask);
+ Endpoint->EndpointDescriptorLength = EndpointDescriptorLength;
+
+ DEBUG ((DEBUG_INFO, "NhltEndpointConstructor() End, EndpointDescriptorLength = %d B\n", Endpoint->EndpointDescriptorLength));
+ return Endpoint->EndpointDescriptorLength;
+}
+
+/**
+ Constructs SPECIFIC_CONFIG structure for OED configuration.
+
+ @param[in][out] *NhltTable NHLT table for which OED config is created
+
+ @retval Size of created SPECIFIC_CONFIG structure
+**/
+UINT32
+NhltOedConfigConstructor (
+ IN OUT NHLT_ACPI_TABLE *NhltTable
+ )
+{
+ SPECIFIC_CONFIG *OedConfig;
+ UINT32 OedConfigLength;
+
+ OedConfigLength = 0;
+ OedConfig = GetNhltOedConfig (NhltTable);
+
+ OedConfig->CapabilitiesSize = NhltConfigurationSize;
+ CopyMem (OedConfig->Capabilities, (UINT8*) NhltConfiguration, NhltConfigurationSize);
+
+ OedConfigLength = sizeof (*OedConfig)
+ - sizeof (OedConfig->Capabilities)
+ + OedConfig->CapabilitiesSize;
+
+ return OedConfigLength;
+}
+
+/**
+ Constructs NHLT_ACPI_TABLE structure based on given Endpoints list.
+
+ @param[in] *EndpointTable List of endpoints for NHLT
+ @param[in][out] **NhltTable NHLT table to be created
+ @param[in][out] *NhltTableSize Size of created NHLT table
+
+ @retval EFI_SUCCESS NHLT created successfully
+ @retval EFI_BAD_BUFFER_SIZE Not enough resources to allocate NHLT
+**/
+EFI_STATUS
+NhltConstructor (
+ IN PCH_HDA_NHLT_ENDPOINTS *EndpointTable,
+ IN OUT NHLT_ACPI_TABLE **NhltTable,
+ IN OUT UINT32 *NhltTableSize
+ )
+{
+ EFI_STATUS Status;
+ UINT8 Index;
+ UINT32 TableSize;
+ UINT32 EndpointDescriptorsLength;
+ UINT32 OedConfigLength;
+ NHLT_ACPI_TABLE *Table;
+
+
+ Status = EFI_SUCCESS;
+ TableSize = PCH_HDA_NHLT_TABLE_SIZE;
+ EndpointDescriptorsLength = 0;
+ OedConfigLength = 0;
+
+ Table = AllocateZeroPool (TableSize);
+
+ if (Table == NULL) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ Table->EndpointCount = 0;
+
+ for (Index = 0; Index < HdaEndpointMax; Index++) {
+ if (EndpointTable[Index].Enable == TRUE) {
+ EndpointDescriptorsLength += NhltEndpointConstructor (Table,
+ EndpointTable[Index].EndpointType,
+ EndpointTable[Index].EndpointFormatsBitmask,
+ Table->EndpointCount++);
+ }
+ }
+ DEBUG ((DEBUG_INFO, "NhltConstructor: EndpointCount = %d, All EndpointDescriptorsLength = %d B\n", Table->EndpointCount, EndpointDescriptorsLength));
+
+ OedConfigLength = NhltOedConfigConstructor (Table);
+ DEBUG ((DEBUG_INFO, "NhltConstructor: OedConfigLength = %d B\n", OedConfigLength));
+
+ TableSize = EndpointDescriptorsLength + OedConfigLength;
+
+ *NhltTableSize = TableSize;
+ *NhltTable = Table;
+
+ return Status;
+}
+
+/**
+ Constructs EFI_ACPI_DESCRIPTION_HEADER structure for NHLT table.
+
+ @param[in][out] *NhltTable NHLT table for which header will be created
+ @param[in] NhltTableSize Size of NHLT table
+
+ @retval None
+**/
+VOID
+NhltAcpiHeaderConstructor (
+ IN OUT NHLT_ACPI_TABLE *NhltTable,
+ IN UINT32 NhltTableSize
+ )
+{
+ DEBUG ((DEBUG_INFO, "NhltAcpiHeaderConstructor() Start\n"));
+
+ // Header
+ NhltTable->Header.Signature = NHLT_ACPI_TABLE_SIGNATURE;
+ NhltTable->Header.Length = (UINT32) (NhltTableSize + sizeof (NHLT_ACPI_TABLE) - sizeof (ENDPOINT_DESCRIPTOR) - sizeof (SPECIFIC_CONFIG));
+ NhltTable->Header.Revision = 0x0;
+ NhltTable->Header.Checksum = 0x0;
+
+ CopyMem (NhltTable->Header.OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (NhltTable->Header.OemId));
+ NhltTable->Header.OemTableId = PcdGet64 (PcdAcpiDefaultOemTableId);
+ NhltTable->Header.OemRevision = PcdGet32 (PcdAcpiDefaultOemRevision);
+ NhltTable->Header.CreatorId = PcdGet32 (PcdAcpiDefaultCreatorId);
+ NhltTable->Header.CreatorRevision = PcdGet32 (PcdAcpiDefaultCreatorRevision);
+
+ DEBUG ((DEBUG_INFO, "NhltAcpiHeaderConstructor(), NhltAcpiTable->Header.Length = %d B\n", NhltTable->Header.Length));
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/DxePchHdaLib/PchHdaNhltConfig.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/DxePchHdaLib/PchHdaNhltConfig.c
new file mode 100644
index 0000000000..46096a0ac3
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/DxePchHdaLib/PchHdaNhltConfig.c
@@ -0,0 +1,336 @@
+/** @file
+ This file contains HD Audio NHLT Configuration BLOBs
+
+Copyright (c) 2017, 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.
+
+**/
+
+//
+// DMIC Configuration BLOBs
+//
+// DMIC Config 2 channels, 16 bits, 2.4Mhz BCLK
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST UINT32 DmicStereo16BitFormatConfig[] =
+{
+ 0x00000000, 0xffffff10, 0xffff1010, 0xffff0101, 0xffff1100, 0x00000003, 0x00000003, 0x00300003, 0x00300003, 0x00000003, 0x0000c001, 0x04000900, 0x00000000, 0x00000803, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000091, 0x000402a0,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000091, 0x000e03b6, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008, 0x000fffae, 0x000fff12, 0x000ffdfb, 0x000ffc61, 0x000ffa5b,
+ 0x000ff82c, 0x000ff643, 0x000ff523, 0x000ff547, 0x000ff6f8, 0x000ffa29, 0x000ffe68, 0x000002e2, 0x0000068f, 0x00000875, 0x000007ef, 0x000004f3, 0x00000028, 0x000ffad3, 0x000ff68a, 0x000ff4c1, 0x000ff651, 0x000ffb22, 0x00000211, 0x00000929,
+ 0x00000e2c, 0x00000f3e, 0x00000b8e, 0x000003bb, 0x000ff9cb, 0x000ff0b0, 0x000feb71, 0x000fec2e, 0x000ff356, 0x000fff53, 0x00000cce, 0x0000179c, 0x00001bf8, 0x000017d1, 0x00000b9d, 0x000ffa79, 0x000fe96d, 0x000fddf8, 0x000fdc53, 0x000fe5f6,
+ 0x000ff8d5, 0x00000fbb, 0x000023a7, 0x00002def, 0x00002a6a, 0x00001905, 0x000ffe24, 0x000fe199, 0x000fcc68, 0x000fc5f7, 0x000fd18a, 0x000fece1, 0x00001079, 0x00003199, 0x00004578, 0x000044bc, 0x00002e15, 0x0000071b, 0x000fdb08, 0x000fb784,
+ 0x000fa877, 0x000fb41a, 0x000fd897, 0x00000c10, 0x00003f3b, 0x000061e1, 0x000067f6, 0x00004db0, 0x00001940, 0x000fd981, 0x000fa1ca, 0x000f841f, 0x000f8b6b, 0x000fb7a8, 0x000ffd3a, 0x000047e6, 0x000080ac, 0x000094cf, 0x00007beb, 0x00003b25,
+ 0x000fe44a, 0x000f90fe, 0x000f5b2e, 0x000f5512, 0x000f832c, 0x000fda2d, 0x000041a3, 0x00009ad1, 0x0000c9c2, 0x0000bdf2, 0x000077e2, 0x000009bc, 0x000f92ab, 0x000f360f, 0x000f110c, 0x000f318c, 0x000f9165, 0x00001750, 0x00009d91, 0x0000fc90,
+ 0x0001166e, 0x0000e025, 0x00006589, 0x000fc6c7, 0x000f2fea, 0x000eccac, 0x000ebbfa, 0x000f06a9, 0x000f9c25, 0x0000562c, 0x000102a9, 0x00017127, 0x0001802c, 0x000126dd, 0x0000782b, 0x000f9ea6, 0x000ed1f0, 0x000e4885, 0x000e298b, 0x000e8265,
+ 0x000f42a4, 0x00003f71, 0x00013d8c, 0x0001ff57, 0x0002537a, 0x0002209e, 0x00016b73, 0x000055ce, 0x000f1749, 0x000df142, 0x000d212b, 0x000cd43e, 0x000d1f22, 0x000dfb0f, 0x000f488e, 0x0000d6d5, 0x00026dc5, 0x0003d844, 0x0004ecd5, 0x00059301,
+ 0x0005c4ed, 0x00058d6f, 0x00050385, 0x0004448d, 0x00036e82, 0x00029b5d, 0x0001de2d, 0x00014211, 0x0000cac9, 0x0000765b, 0x00003f38, 0x00001e4a, 0x00000c93, 0x0000043b, 0x000000f9, 0x000fffd6, 0x00000217, 0x0000025b, 0x00000383, 0x00000507,
+ 0x000006e2, 0x00000916, 0x00000ba1, 0x00000e7b, 0x0000119a, 0x000014ec, 0x00001859, 0x00001bc7, 0x00001f15, 0x0000221d, 0x000024ba, 0x000026c3, 0x00002810, 0x0000287e, 0x000027ec, 0x00002640, 0x0000236c, 0x00001f6a, 0x00001a40, 0x00001402,
+ 0x00000cd3, 0x000004e2, 0x000ffc6b, 0x000ff3b7, 0x000feb17, 0x000fe2e2, 0x000fdb73, 0x000fd526, 0x000fd04f, 0x000fcd3a, 0x000fcc27, 0x000fcd42, 0x000fd0a5, 0x000fd64f, 0x000fde28, 0x000fe7fd, 0x000ff382, 0x0000004f, 0x00000deb, 0x00001bc8,
+ 0x0000294e, 0x000035dd, 0x000040d8, 0x000049a7, 0x00004fc4, 0x000052be, 0x00005242, 0x00004e1e, 0x0000464a, 0x00003ae5, 0x00002c3b, 0x00001ac1, 0x00000714, 0x000ff1f4, 0x000fdc3b, 0x000fc6d6, 0x000fb2c0, 0x000fa0ec, 0x000f9247, 0x000f87a1,
+ 0x000f81ad, 0x000f80ec, 0x000f85b1, 0x000f900d, 0x000f9fda, 0x000fb4aa, 0x000fcdda, 0x000fea84, 0x00000996, 0x000029d1, 0x000049e0, 0x00006855, 0x000083cf, 0x00009af4, 0x0000ac91, 0x0000b79e, 0x0000bb55, 0x0000b732, 0x0000ab0b, 0x00009703,
+ 0x00007b9f, 0x000059b2, 0x00003267, 0x00000729, 0x000fd9a4, 0x000faba8, 0x000f7f24, 0x000f5602, 0x000f3223, 0x000f153c, 0x000f00cf, 0x000ef60a, 0x000ef5c9, 0x000f0079, 0x000f161e, 0x000f3645, 0x000f600d, 0x000f9225, 0x000fcade, 0x00000833,
+ 0x000047e1, 0x00008777, 0x0000c473, 0x0000fc56, 0x00012cc0, 0x00015388, 0x00016ed4, 0x00017d2b, 0x00017d87, 0x00016f60, 0x000152b9, 0x0001281a, 0x0000f095, 0x0000adbd, 0x00006196, 0x00000e87, 0x000fb747, 0x000f5ec0, 0x000f07fc, 0x000eb605,
+ 0x000e6bcb, 0x000e2c0f, 0x000df944, 0x000dd57e, 0x000dc25f, 0x000dc10a, 0x000dd21a, 0x000df59c, 0x000e2b14, 0x000e717c, 0x000ec755, 0x000f2aad, 0x000f993a, 0x00001064, 0x00008d63, 0x00010d4f, 0x00018d3f, 0x00020a57, 0x000281e5, 0x0002f16e,
+ 0x000356c1, 0x0003b005, 0x0003fbc3, 0x000438ea, 0x000466d2, 0x0004853f, 0x00049457, 0x000494a1, 0x000486f4, 0x00046c73, 0x0004467a, 0x00041691, 0x0003de61, 0x00039fa1, 0x00035c0b, 0x0003154e, 0x0002cd02, 0x000284a2, 0x00023d80, 0x0001f8c4,
+ 0x0001b763, 0x00017a21, 0x00014192, 0x00010e16, 0x0000dfe3, 0x0000b706, 0x00009368, 0x000074d3, 0x00005af9, 0x0000457c, 0x000033ef, 0x000025df, 0x00001ad6, 0x00001262, 0x00000c13, 0x00000783, 0x00000457, 0x000002d8, 0x0000c001, 0x04000900,
+ 0x00000000, 0x00000803, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000091, 0x000402a0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000091, 0x000e03b6, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000008, 0x000fffae, 0x000fff12, 0x000ffdfb, 0x000ffc61, 0x000ffa5b, 0x000ff82c, 0x000ff643, 0x000ff523, 0x000ff547, 0x000ff6f8, 0x000ffa29, 0x000ffe68, 0x000002e2, 0x0000068f, 0x00000875, 0x000007ef, 0x000004f3,
+ 0x00000028, 0x000ffad3, 0x000ff68a, 0x000ff4c1, 0x000ff651, 0x000ffb22, 0x00000211, 0x00000929, 0x00000e2c, 0x00000f3e, 0x00000b8e, 0x000003bb, 0x000ff9cb, 0x000ff0b0, 0x000feb71, 0x000fec2e, 0x000ff356, 0x000fff53, 0x00000cce, 0x0000179c,
+ 0x00001bf8, 0x000017d1, 0x00000b9d, 0x000ffa79, 0x000fe96d, 0x000fddf8, 0x000fdc53, 0x000fe5f6, 0x000ff8d5, 0x00000fbb, 0x000023a7, 0x00002def, 0x00002a6a, 0x00001905, 0x000ffe24, 0x000fe199, 0x000fcc68, 0x000fc5f7, 0x000fd18a, 0x000fece1,
+ 0x00001079, 0x00003199, 0x00004578, 0x000044bc, 0x00002e15, 0x0000071b, 0x000fdb08, 0x000fb784, 0x000fa877, 0x000fb41a, 0x000fd897, 0x00000c10, 0x00003f3b, 0x000061e1, 0x000067f6, 0x00004db0, 0x00001940, 0x000fd981, 0x000fa1ca, 0x000f841f,
+ 0x000f8b6b, 0x000fb7a8, 0x000ffd3a, 0x000047e6, 0x000080ac, 0x000094cf, 0x00007beb, 0x00003b25, 0x000fe44a, 0x000f90fe, 0x000f5b2e, 0x000f5512, 0x000f832c, 0x000fda2d, 0x000041a3, 0x00009ad1, 0x0000c9c2, 0x0000bdf2, 0x000077e2, 0x000009bc,
+ 0x000f92ab, 0x000f360f, 0x000f110c, 0x000f318c, 0x000f9165, 0x00001750, 0x00009d91, 0x0000fc90, 0x0001166e, 0x0000e025, 0x00006589, 0x000fc6c7, 0x000f2fea, 0x000eccac, 0x000ebbfa, 0x000f06a9, 0x000f9c25, 0x0000562c, 0x000102a9, 0x00017127,
+ 0x0001802c, 0x000126dd, 0x0000782b, 0x000f9ea6, 0x000ed1f0, 0x000e4885, 0x000e298b, 0x000e8265, 0x000f42a4, 0x00003f71, 0x00013d8c, 0x0001ff57, 0x0002537a, 0x0002209e, 0x00016b73, 0x000055ce, 0x000f1749, 0x000df142, 0x000d212b, 0x000cd43e,
+ 0x000d1f22, 0x000dfb0f, 0x000f488e, 0x0000d6d5, 0x00026dc5, 0x0003d844, 0x0004ecd5, 0x00059301, 0x0005c4ed, 0x00058d6f, 0x00050385, 0x0004448d, 0x00036e82, 0x00029b5d, 0x0001de2d, 0x00014211, 0x0000cac9, 0x0000765b, 0x00003f38, 0x00001e4a,
+ 0x00000c93, 0x0000043b, 0x000000f9, 0x000fffd6, 0x00000217, 0x0000025b, 0x00000383, 0x00000507, 0x000006e2, 0x00000916, 0x00000ba1, 0x00000e7b, 0x0000119a, 0x000014ec, 0x00001859, 0x00001bc7, 0x00001f15, 0x0000221d, 0x000024ba, 0x000026c3,
+ 0x00002810, 0x0000287e, 0x000027ec, 0x00002640, 0x0000236c, 0x00001f6a, 0x00001a40, 0x00001402, 0x00000cd3, 0x000004e2, 0x000ffc6b, 0x000ff3b7, 0x000feb17, 0x000fe2e2, 0x000fdb73, 0x000fd526, 0x000fd04f, 0x000fcd3a, 0x000fcc27, 0x000fcd42,
+ 0x000fd0a5, 0x000fd64f, 0x000fde28, 0x000fe7fd, 0x000ff382, 0x0000004f, 0x00000deb, 0x00001bc8, 0x0000294e, 0x000035dd, 0x000040d8, 0x000049a7, 0x00004fc4, 0x000052be, 0x00005242, 0x00004e1e, 0x0000464a, 0x00003ae5, 0x00002c3b, 0x00001ac1,
+ 0x00000714, 0x000ff1f4, 0x000fdc3b, 0x000fc6d6, 0x000fb2c0, 0x000fa0ec, 0x000f9247, 0x000f87a1, 0x000f81ad, 0x000f80ec, 0x000f85b1, 0x000f900d, 0x000f9fda, 0x000fb4aa, 0x000fcdda, 0x000fea84, 0x00000996, 0x000029d1, 0x000049e0, 0x00006855,
+ 0x000083cf, 0x00009af4, 0x0000ac91, 0x0000b79e, 0x0000bb55, 0x0000b732, 0x0000ab0b, 0x00009703, 0x00007b9f, 0x000059b2, 0x00003267, 0x00000729, 0x000fd9a4, 0x000faba8, 0x000f7f24, 0x000f5602, 0x000f3223, 0x000f153c, 0x000f00cf, 0x000ef60a,
+ 0x000ef5c9, 0x000f0079, 0x000f161e, 0x000f3645, 0x000f600d, 0x000f9225, 0x000fcade, 0x00000833, 0x000047e1, 0x00008777, 0x0000c473, 0x0000fc56, 0x00012cc0, 0x00015388, 0x00016ed4, 0x00017d2b, 0x00017d87, 0x00016f60, 0x000152b9, 0x0001281a,
+ 0x0000f095, 0x0000adbd, 0x00006196, 0x00000e87, 0x000fb747, 0x000f5ec0, 0x000f07fc, 0x000eb605, 0x000e6bcb, 0x000e2c0f, 0x000df944, 0x000dd57e, 0x000dc25f, 0x000dc10a, 0x000dd21a, 0x000df59c, 0x000e2b14, 0x000e717c, 0x000ec755, 0x000f2aad,
+ 0x000f993a, 0x00001064, 0x00008d63, 0x00010d4f, 0x00018d3f, 0x00020a57, 0x000281e5, 0x0002f16e, 0x000356c1, 0x0003b005, 0x0003fbc3, 0x000438ea, 0x000466d2, 0x0004853f, 0x00049457, 0x000494a1, 0x000486f4, 0x00046c73, 0x0004467a, 0x00041691,
+ 0x0003de61, 0x00039fa1, 0x00035c0b, 0x0003154e, 0x0002cd02, 0x000284a2, 0x00023d80, 0x0001f8c4, 0x0001b763, 0x00017a21, 0x00014192, 0x00010e16, 0x0000dfe3, 0x0000b706, 0x00009368, 0x000074d3, 0x00005af9, 0x0000457c, 0x000033ef, 0x000025df,
+ 0x00001ad6, 0x00001262, 0x00000c13, 0x00000783, 0x00000457, 0x000002d8
+};
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 DmicStereo16BitFormatConfigSize = sizeof (DmicStereo16BitFormatConfig);
+
+// DMIC Config 2 channels, 32 bits, 2.4Mhz BCLK
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST UINT32 DmicStereo32BitFormatConfig[] =
+{
+ 0x00000000, 0xffffff10, 0xffff1010, 0xffff0101, 0xffff1100, 0x00000003, 0x00000003, 0x00380003, 0x00380003, 0x00000003, 0x0000c001, 0x04000900, 0x00000000, 0x00000803, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000091, 0x000402a0,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000091, 0x000e03b6, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008, 0x000fffae, 0x000fff12, 0x000ffdfb, 0x000ffc61, 0x000ffa5b,
+ 0x000ff82c, 0x000ff643, 0x000ff523, 0x000ff547, 0x000ff6f8, 0x000ffa29, 0x000ffe68, 0x000002e2, 0x0000068f, 0x00000875, 0x000007ef, 0x000004f3, 0x00000028, 0x000ffad3, 0x000ff68a, 0x000ff4c1, 0x000ff651, 0x000ffb22, 0x00000211, 0x00000929,
+ 0x00000e2c, 0x00000f3e, 0x00000b8e, 0x000003bb, 0x000ff9cb, 0x000ff0b0, 0x000feb71, 0x000fec2e, 0x000ff356, 0x000fff53, 0x00000cce, 0x0000179c, 0x00001bf8, 0x000017d1, 0x00000b9d, 0x000ffa79, 0x000fe96d, 0x000fddf8, 0x000fdc53, 0x000fe5f6,
+ 0x000ff8d5, 0x00000fbb, 0x000023a7, 0x00002def, 0x00002a6a, 0x00001905, 0x000ffe24, 0x000fe199, 0x000fcc68, 0x000fc5f7, 0x000fd18a, 0x000fece1, 0x00001079, 0x00003199, 0x00004578, 0x000044bc, 0x00002e15, 0x0000071b, 0x000fdb08, 0x000fb784,
+ 0x000fa877, 0x000fb41a, 0x000fd897, 0x00000c10, 0x00003f3b, 0x000061e1, 0x000067f6, 0x00004db0, 0x00001940, 0x000fd981, 0x000fa1ca, 0x000f841f, 0x000f8b6b, 0x000fb7a8, 0x000ffd3a, 0x000047e6, 0x000080ac, 0x000094cf, 0x00007beb, 0x00003b25,
+ 0x000fe44a, 0x000f90fe, 0x000f5b2e, 0x000f5512, 0x000f832c, 0x000fda2d, 0x000041a3, 0x00009ad1, 0x0000c9c2, 0x0000bdf2, 0x000077e2, 0x000009bc, 0x000f92ab, 0x000f360f, 0x000f110c, 0x000f318c, 0x000f9165, 0x00001750, 0x00009d91, 0x0000fc90,
+ 0x0001166e, 0x0000e025, 0x00006589, 0x000fc6c7, 0x000f2fea, 0x000eccac, 0x000ebbfa, 0x000f06a9, 0x000f9c25, 0x0000562c, 0x000102a9, 0x00017127, 0x0001802c, 0x000126dd, 0x0000782b, 0x000f9ea6, 0x000ed1f0, 0x000e4885, 0x000e298b, 0x000e8265,
+ 0x000f42a4, 0x00003f71, 0x00013d8c, 0x0001ff57, 0x0002537a, 0x0002209e, 0x00016b73, 0x000055ce, 0x000f1749, 0x000df142, 0x000d212b, 0x000cd43e, 0x000d1f22, 0x000dfb0f, 0x000f488e, 0x0000d6d5, 0x00026dc5, 0x0003d844, 0x0004ecd5, 0x00059301,
+ 0x0005c4ed, 0x00058d6f, 0x00050385, 0x0004448d, 0x00036e82, 0x00029b5d, 0x0001de2d, 0x00014211, 0x0000cac9, 0x0000765b, 0x00003f38, 0x00001e4a, 0x00000c93, 0x0000043b, 0x000000f9, 0x000fffd6, 0x00000217, 0x0000025b, 0x00000383, 0x00000507,
+ 0x000006e2, 0x00000916, 0x00000ba1, 0x00000e7b, 0x0000119a, 0x000014ec, 0x00001859, 0x00001bc7, 0x00001f15, 0x0000221d, 0x000024ba, 0x000026c3, 0x00002810, 0x0000287e, 0x000027ec, 0x00002640, 0x0000236c, 0x00001f6a, 0x00001a40, 0x00001402,
+ 0x00000cd3, 0x000004e2, 0x000ffc6b, 0x000ff3b7, 0x000feb17, 0x000fe2e2, 0x000fdb73, 0x000fd526, 0x000fd04f, 0x000fcd3a, 0x000fcc27, 0x000fcd42, 0x000fd0a5, 0x000fd64f, 0x000fde28, 0x000fe7fd, 0x000ff382, 0x0000004f, 0x00000deb, 0x00001bc8,
+ 0x0000294e, 0x000035dd, 0x000040d8, 0x000049a7, 0x00004fc4, 0x000052be, 0x00005242, 0x00004e1e, 0x0000464a, 0x00003ae5, 0x00002c3b, 0x00001ac1, 0x00000714, 0x000ff1f4, 0x000fdc3b, 0x000fc6d6, 0x000fb2c0, 0x000fa0ec, 0x000f9247, 0x000f87a1,
+ 0x000f81ad, 0x000f80ec, 0x000f85b1, 0x000f900d, 0x000f9fda, 0x000fb4aa, 0x000fcdda, 0x000fea84, 0x00000996, 0x000029d1, 0x000049e0, 0x00006855, 0x000083cf, 0x00009af4, 0x0000ac91, 0x0000b79e, 0x0000bb55, 0x0000b732, 0x0000ab0b, 0x00009703,
+ 0x00007b9f, 0x000059b2, 0x00003267, 0x00000729, 0x000fd9a4, 0x000faba8, 0x000f7f24, 0x000f5602, 0x000f3223, 0x000f153c, 0x000f00cf, 0x000ef60a, 0x000ef5c9, 0x000f0079, 0x000f161e, 0x000f3645, 0x000f600d, 0x000f9225, 0x000fcade, 0x00000833,
+ 0x000047e1, 0x00008777, 0x0000c473, 0x0000fc56, 0x00012cc0, 0x00015388, 0x00016ed4, 0x00017d2b, 0x00017d87, 0x00016f60, 0x000152b9, 0x0001281a, 0x0000f095, 0x0000adbd, 0x00006196, 0x00000e87, 0x000fb747, 0x000f5ec0, 0x000f07fc, 0x000eb605,
+ 0x000e6bcb, 0x000e2c0f, 0x000df944, 0x000dd57e, 0x000dc25f, 0x000dc10a, 0x000dd21a, 0x000df59c, 0x000e2b14, 0x000e717c, 0x000ec755, 0x000f2aad, 0x000f993a, 0x00001064, 0x00008d63, 0x00010d4f, 0x00018d3f, 0x00020a57, 0x000281e5, 0x0002f16e,
+ 0x000356c1, 0x0003b005, 0x0003fbc3, 0x000438ea, 0x000466d2, 0x0004853f, 0x00049457, 0x000494a1, 0x000486f4, 0x00046c73, 0x0004467a, 0x00041691, 0x0003de61, 0x00039fa1, 0x00035c0b, 0x0003154e, 0x0002cd02, 0x000284a2, 0x00023d80, 0x0001f8c4,
+ 0x0001b763, 0x00017a21, 0x00014192, 0x00010e16, 0x0000dfe3, 0x0000b706, 0x00009368, 0x000074d3, 0x00005af9, 0x0000457c, 0x000033ef, 0x000025df, 0x00001ad6, 0x00001262, 0x00000c13, 0x00000783, 0x00000457, 0x000002d8, 0x0000c001, 0x04000900,
+ 0x00000000, 0x00000803, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000091, 0x000402a0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000091, 0x000e03b6, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000008, 0x000fffae, 0x000fff12, 0x000ffdfb, 0x000ffc61, 0x000ffa5b, 0x000ff82c, 0x000ff643, 0x000ff523, 0x000ff547, 0x000ff6f8, 0x000ffa29, 0x000ffe68, 0x000002e2, 0x0000068f, 0x00000875, 0x000007ef, 0x000004f3,
+ 0x00000028, 0x000ffad3, 0x000ff68a, 0x000ff4c1, 0x000ff651, 0x000ffb22, 0x00000211, 0x00000929, 0x00000e2c, 0x00000f3e, 0x00000b8e, 0x000003bb, 0x000ff9cb, 0x000ff0b0, 0x000feb71, 0x000fec2e, 0x000ff356, 0x000fff53, 0x00000cce, 0x0000179c,
+ 0x00001bf8, 0x000017d1, 0x00000b9d, 0x000ffa79, 0x000fe96d, 0x000fddf8, 0x000fdc53, 0x000fe5f6, 0x000ff8d5, 0x00000fbb, 0x000023a7, 0x00002def, 0x00002a6a, 0x00001905, 0x000ffe24, 0x000fe199, 0x000fcc68, 0x000fc5f7, 0x000fd18a, 0x000fece1,
+ 0x00001079, 0x00003199, 0x00004578, 0x000044bc, 0x00002e15, 0x0000071b, 0x000fdb08, 0x000fb784, 0x000fa877, 0x000fb41a, 0x000fd897, 0x00000c10, 0x00003f3b, 0x000061e1, 0x000067f6, 0x00004db0, 0x00001940, 0x000fd981, 0x000fa1ca, 0x000f841f,
+ 0x000f8b6b, 0x000fb7a8, 0x000ffd3a, 0x000047e6, 0x000080ac, 0x000094cf, 0x00007beb, 0x00003b25, 0x000fe44a, 0x000f90fe, 0x000f5b2e, 0x000f5512, 0x000f832c, 0x000fda2d, 0x000041a3, 0x00009ad1, 0x0000c9c2, 0x0000bdf2, 0x000077e2, 0x000009bc,
+ 0x000f92ab, 0x000f360f, 0x000f110c, 0x000f318c, 0x000f9165, 0x00001750, 0x00009d91, 0x0000fc90, 0x0001166e, 0x0000e025, 0x00006589, 0x000fc6c7, 0x000f2fea, 0x000eccac, 0x000ebbfa, 0x000f06a9, 0x000f9c25, 0x0000562c, 0x000102a9, 0x00017127,
+ 0x0001802c, 0x000126dd, 0x0000782b, 0x000f9ea6, 0x000ed1f0, 0x000e4885, 0x000e298b, 0x000e8265, 0x000f42a4, 0x00003f71, 0x00013d8c, 0x0001ff57, 0x0002537a, 0x0002209e, 0x00016b73, 0x000055ce, 0x000f1749, 0x000df142, 0x000d212b, 0x000cd43e,
+ 0x000d1f22, 0x000dfb0f, 0x000f488e, 0x0000d6d5, 0x00026dc5, 0x0003d844, 0x0004ecd5, 0x00059301, 0x0005c4ed, 0x00058d6f, 0x00050385, 0x0004448d, 0x00036e82, 0x00029b5d, 0x0001de2d, 0x00014211, 0x0000cac9, 0x0000765b, 0x00003f38, 0x00001e4a,
+ 0x00000c93, 0x0000043b, 0x000000f9, 0x000fffd6, 0x00000217, 0x0000025b, 0x00000383, 0x00000507, 0x000006e2, 0x00000916, 0x00000ba1, 0x00000e7b, 0x0000119a, 0x000014ec, 0x00001859, 0x00001bc7, 0x00001f15, 0x0000221d, 0x000024ba, 0x000026c3,
+ 0x00002810, 0x0000287e, 0x000027ec, 0x00002640, 0x0000236c, 0x00001f6a, 0x00001a40, 0x00001402, 0x00000cd3, 0x000004e2, 0x000ffc6b, 0x000ff3b7, 0x000feb17, 0x000fe2e2, 0x000fdb73, 0x000fd526, 0x000fd04f, 0x000fcd3a, 0x000fcc27, 0x000fcd42,
+ 0x000fd0a5, 0x000fd64f, 0x000fde28, 0x000fe7fd, 0x000ff382, 0x0000004f, 0x00000deb, 0x00001bc8, 0x0000294e, 0x000035dd, 0x000040d8, 0x000049a7, 0x00004fc4, 0x000052be, 0x00005242, 0x00004e1e, 0x0000464a, 0x00003ae5, 0x00002c3b, 0x00001ac1,
+ 0x00000714, 0x000ff1f4, 0x000fdc3b, 0x000fc6d6, 0x000fb2c0, 0x000fa0ec, 0x000f9247, 0x000f87a1, 0x000f81ad, 0x000f80ec, 0x000f85b1, 0x000f900d, 0x000f9fda, 0x000fb4aa, 0x000fcdda, 0x000fea84, 0x00000996, 0x000029d1, 0x000049e0, 0x00006855,
+ 0x000083cf, 0x00009af4, 0x0000ac91, 0x0000b79e, 0x0000bb55, 0x0000b732, 0x0000ab0b, 0x00009703, 0x00007b9f, 0x000059b2, 0x00003267, 0x00000729, 0x000fd9a4, 0x000faba8, 0x000f7f24, 0x000f5602, 0x000f3223, 0x000f153c, 0x000f00cf, 0x000ef60a,
+ 0x000ef5c9, 0x000f0079, 0x000f161e, 0x000f3645, 0x000f600d, 0x000f9225, 0x000fcade, 0x00000833, 0x000047e1, 0x00008777, 0x0000c473, 0x0000fc56, 0x00012cc0, 0x00015388, 0x00016ed4, 0x00017d2b, 0x00017d87, 0x00016f60, 0x000152b9, 0x0001281a,
+ 0x0000f095, 0x0000adbd, 0x00006196, 0x00000e87, 0x000fb747, 0x000f5ec0, 0x000f07fc, 0x000eb605, 0x000e6bcb, 0x000e2c0f, 0x000df944, 0x000dd57e, 0x000dc25f, 0x000dc10a, 0x000dd21a, 0x000df59c, 0x000e2b14, 0x000e717c, 0x000ec755, 0x000f2aad,
+ 0x000f993a, 0x00001064, 0x00008d63, 0x00010d4f, 0x00018d3f, 0x00020a57, 0x000281e5, 0x0002f16e, 0x000356c1, 0x0003b005, 0x0003fbc3, 0x000438ea, 0x000466d2, 0x0004853f, 0x00049457, 0x000494a1, 0x000486f4, 0x00046c73, 0x0004467a, 0x00041691,
+ 0x0003de61, 0x00039fa1, 0x00035c0b, 0x0003154e, 0x0002cd02, 0x000284a2, 0x00023d80, 0x0001f8c4, 0x0001b763, 0x00017a21, 0x00014192, 0x00010e16, 0x0000dfe3, 0x0000b706, 0x00009368, 0x000074d3, 0x00005af9, 0x0000457c, 0x000033ef, 0x000025df,
+ 0x00001ad6, 0x00001262, 0x00000c13, 0x00000783, 0x00000457, 0x000002d8
+};
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 DmicStereo32BitFormatConfigSize = sizeof (DmicStereo32BitFormatConfig);
+
+// DMIC Config 4 channels, 16 bits, 2.4Mhz BCLK
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST UINT32 DmicQuad16BitFormatConfig[] =
+{
+ 0x00000000, 0xffffff10, 0xffff1010, 0xffff0101, 0xffff1100, 0x00000003, 0x00000003, 0x00320003, 0x00320003, 0x00000003, 0x0000c001, 0x04000900, 0x00000000, 0x00000803, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000091, 0x000402a0,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000091, 0x000e03b6, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008, 0x000fffae, 0x000fff12, 0x000ffdfb, 0x000ffc61, 0x000ffa5b,
+ 0x000ff82c, 0x000ff643, 0x000ff523, 0x000ff547, 0x000ff6f8, 0x000ffa29, 0x000ffe68, 0x000002e2, 0x0000068f, 0x00000875, 0x000007ef, 0x000004f3, 0x00000028, 0x000ffad3, 0x000ff68a, 0x000ff4c1, 0x000ff651, 0x000ffb22, 0x00000211, 0x00000929,
+ 0x00000e2c, 0x00000f3e, 0x00000b8e, 0x000003bb, 0x000ff9cb, 0x000ff0b0, 0x000feb71, 0x000fec2e, 0x000ff356, 0x000fff53, 0x00000cce, 0x0000179c, 0x00001bf8, 0x000017d1, 0x00000b9d, 0x000ffa79, 0x000fe96d, 0x000fddf8, 0x000fdc53, 0x000fe5f6,
+ 0x000ff8d5, 0x00000fbb, 0x000023a7, 0x00002def, 0x00002a6a, 0x00001905, 0x000ffe24, 0x000fe199, 0x000fcc68, 0x000fc5f7, 0x000fd18a, 0x000fece1, 0x00001079, 0x00003199, 0x00004578, 0x000044bc, 0x00002e15, 0x0000071b, 0x000fdb08, 0x000fb784,
+ 0x000fa877, 0x000fb41a, 0x000fd897, 0x00000c10, 0x00003f3b, 0x000061e1, 0x000067f6, 0x00004db0, 0x00001940, 0x000fd981, 0x000fa1ca, 0x000f841f, 0x000f8b6b, 0x000fb7a8, 0x000ffd3a, 0x000047e6, 0x000080ac, 0x000094cf, 0x00007beb, 0x00003b25,
+ 0x000fe44a, 0x000f90fe, 0x000f5b2e, 0x000f5512, 0x000f832c, 0x000fda2d, 0x000041a3, 0x00009ad1, 0x0000c9c2, 0x0000bdf2, 0x000077e2, 0x000009bc, 0x000f92ab, 0x000f360f, 0x000f110c, 0x000f318c, 0x000f9165, 0x00001750, 0x00009d91, 0x0000fc90,
+ 0x0001166e, 0x0000e025, 0x00006589, 0x000fc6c7, 0x000f2fea, 0x000eccac, 0x000ebbfa, 0x000f06a9, 0x000f9c25, 0x0000562c, 0x000102a9, 0x00017127, 0x0001802c, 0x000126dd, 0x0000782b, 0x000f9ea6, 0x000ed1f0, 0x000e4885, 0x000e298b, 0x000e8265,
+ 0x000f42a4, 0x00003f71, 0x00013d8c, 0x0001ff57, 0x0002537a, 0x0002209e, 0x00016b73, 0x000055ce, 0x000f1749, 0x000df142, 0x000d212b, 0x000cd43e, 0x000d1f22, 0x000dfb0f, 0x000f488e, 0x0000d6d5, 0x00026dc5, 0x0003d844, 0x0004ecd5, 0x00059301,
+ 0x0005c4ed, 0x00058d6f, 0x00050385, 0x0004448d, 0x00036e82, 0x00029b5d, 0x0001de2d, 0x00014211, 0x0000cac9, 0x0000765b, 0x00003f38, 0x00001e4a, 0x00000c93, 0x0000043b, 0x000000f9, 0x000fffd6, 0x00000217, 0x0000025b, 0x00000383, 0x00000507,
+ 0x000006e2, 0x00000916, 0x00000ba1, 0x00000e7b, 0x0000119a, 0x000014ec, 0x00001859, 0x00001bc7, 0x00001f15, 0x0000221d, 0x000024ba, 0x000026c3, 0x00002810, 0x0000287e, 0x000027ec, 0x00002640, 0x0000236c, 0x00001f6a, 0x00001a40, 0x00001402,
+ 0x00000cd3, 0x000004e2, 0x000ffc6b, 0x000ff3b7, 0x000feb17, 0x000fe2e2, 0x000fdb73, 0x000fd526, 0x000fd04f, 0x000fcd3a, 0x000fcc27, 0x000fcd42, 0x000fd0a5, 0x000fd64f, 0x000fde28, 0x000fe7fd, 0x000ff382, 0x0000004f, 0x00000deb, 0x00001bc8,
+ 0x0000294e, 0x000035dd, 0x000040d8, 0x000049a7, 0x00004fc4, 0x000052be, 0x00005242, 0x00004e1e, 0x0000464a, 0x00003ae5, 0x00002c3b, 0x00001ac1, 0x00000714, 0x000ff1f4, 0x000fdc3b, 0x000fc6d6, 0x000fb2c0, 0x000fa0ec, 0x000f9247, 0x000f87a1,
+ 0x000f81ad, 0x000f80ec, 0x000f85b1, 0x000f900d, 0x000f9fda, 0x000fb4aa, 0x000fcdda, 0x000fea84, 0x00000996, 0x000029d1, 0x000049e0, 0x00006855, 0x000083cf, 0x00009af4, 0x0000ac91, 0x0000b79e, 0x0000bb55, 0x0000b732, 0x0000ab0b, 0x00009703,
+ 0x00007b9f, 0x000059b2, 0x00003267, 0x00000729, 0x000fd9a4, 0x000faba8, 0x000f7f24, 0x000f5602, 0x000f3223, 0x000f153c, 0x000f00cf, 0x000ef60a, 0x000ef5c9, 0x000f0079, 0x000f161e, 0x000f3645, 0x000f600d, 0x000f9225, 0x000fcade, 0x00000833,
+ 0x000047e1, 0x00008777, 0x0000c473, 0x0000fc56, 0x00012cc0, 0x00015388, 0x00016ed4, 0x00017d2b, 0x00017d87, 0x00016f60, 0x000152b9, 0x0001281a, 0x0000f095, 0x0000adbd, 0x00006196, 0x00000e87, 0x000fb747, 0x000f5ec0, 0x000f07fc, 0x000eb605,
+ 0x000e6bcb, 0x000e2c0f, 0x000df944, 0x000dd57e, 0x000dc25f, 0x000dc10a, 0x000dd21a, 0x000df59c, 0x000e2b14, 0x000e717c, 0x000ec755, 0x000f2aad, 0x000f993a, 0x00001064, 0x00008d63, 0x00010d4f, 0x00018d3f, 0x00020a57, 0x000281e5, 0x0002f16e,
+ 0x000356c1, 0x0003b005, 0x0003fbc3, 0x000438ea, 0x000466d2, 0x0004853f, 0x00049457, 0x000494a1, 0x000486f4, 0x00046c73, 0x0004467a, 0x00041691, 0x0003de61, 0x00039fa1, 0x00035c0b, 0x0003154e, 0x0002cd02, 0x000284a2, 0x00023d80, 0x0001f8c4,
+ 0x0001b763, 0x00017a21, 0x00014192, 0x00010e16, 0x0000dfe3, 0x0000b706, 0x00009368, 0x000074d3, 0x00005af9, 0x0000457c, 0x000033ef, 0x000025df, 0x00001ad6, 0x00001262, 0x00000c13, 0x00000783, 0x00000457, 0x000002d8, 0x0000c001, 0x04000900,
+ 0x00000000, 0x00000803, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000091, 0x000402a0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000091, 0x000e03b6, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000008, 0x000fffae, 0x000fff12, 0x000ffdfb, 0x000ffc61, 0x000ffa5b, 0x000ff82c, 0x000ff643, 0x000ff523, 0x000ff547, 0x000ff6f8, 0x000ffa29, 0x000ffe68, 0x000002e2, 0x0000068f, 0x00000875, 0x000007ef, 0x000004f3,
+ 0x00000028, 0x000ffad3, 0x000ff68a, 0x000ff4c1, 0x000ff651, 0x000ffb22, 0x00000211, 0x00000929, 0x00000e2c, 0x00000f3e, 0x00000b8e, 0x000003bb, 0x000ff9cb, 0x000ff0b0, 0x000feb71, 0x000fec2e, 0x000ff356, 0x000fff53, 0x00000cce, 0x0000179c,
+ 0x00001bf8, 0x000017d1, 0x00000b9d, 0x000ffa79, 0x000fe96d, 0x000fddf8, 0x000fdc53, 0x000fe5f6, 0x000ff8d5, 0x00000fbb, 0x000023a7, 0x00002def, 0x00002a6a, 0x00001905, 0x000ffe24, 0x000fe199, 0x000fcc68, 0x000fc5f7, 0x000fd18a, 0x000fece1,
+ 0x00001079, 0x00003199, 0x00004578, 0x000044bc, 0x00002e15, 0x0000071b, 0x000fdb08, 0x000fb784, 0x000fa877, 0x000fb41a, 0x000fd897, 0x00000c10, 0x00003f3b, 0x000061e1, 0x000067f6, 0x00004db0, 0x00001940, 0x000fd981, 0x000fa1ca, 0x000f841f,
+ 0x000f8b6b, 0x000fb7a8, 0x000ffd3a, 0x000047e6, 0x000080ac, 0x000094cf, 0x00007beb, 0x00003b25, 0x000fe44a, 0x000f90fe, 0x000f5b2e, 0x000f5512, 0x000f832c, 0x000fda2d, 0x000041a3, 0x00009ad1, 0x0000c9c2, 0x0000bdf2, 0x000077e2, 0x000009bc,
+ 0x000f92ab, 0x000f360f, 0x000f110c, 0x000f318c, 0x000f9165, 0x00001750, 0x00009d91, 0x0000fc90, 0x0001166e, 0x0000e025, 0x00006589, 0x000fc6c7, 0x000f2fea, 0x000eccac, 0x000ebbfa, 0x000f06a9, 0x000f9c25, 0x0000562c, 0x000102a9, 0x00017127,
+ 0x0001802c, 0x000126dd, 0x0000782b, 0x000f9ea6, 0x000ed1f0, 0x000e4885, 0x000e298b, 0x000e8265, 0x000f42a4, 0x00003f71, 0x00013d8c, 0x0001ff57, 0x0002537a, 0x0002209e, 0x00016b73, 0x000055ce, 0x000f1749, 0x000df142, 0x000d212b, 0x000cd43e,
+ 0x000d1f22, 0x000dfb0f, 0x000f488e, 0x0000d6d5, 0x00026dc5, 0x0003d844, 0x0004ecd5, 0x00059301, 0x0005c4ed, 0x00058d6f, 0x00050385, 0x0004448d, 0x00036e82, 0x00029b5d, 0x0001de2d, 0x00014211, 0x0000cac9, 0x0000765b, 0x00003f38, 0x00001e4a,
+ 0x00000c93, 0x0000043b, 0x000000f9, 0x000fffd6, 0x00000217, 0x0000025b, 0x00000383, 0x00000507, 0x000006e2, 0x00000916, 0x00000ba1, 0x00000e7b, 0x0000119a, 0x000014ec, 0x00001859, 0x00001bc7, 0x00001f15, 0x0000221d, 0x000024ba, 0x000026c3,
+ 0x00002810, 0x0000287e, 0x000027ec, 0x00002640, 0x0000236c, 0x00001f6a, 0x00001a40, 0x00001402, 0x00000cd3, 0x000004e2, 0x000ffc6b, 0x000ff3b7, 0x000feb17, 0x000fe2e2, 0x000fdb73, 0x000fd526, 0x000fd04f, 0x000fcd3a, 0x000fcc27, 0x000fcd42,
+ 0x000fd0a5, 0x000fd64f, 0x000fde28, 0x000fe7fd, 0x000ff382, 0x0000004f, 0x00000deb, 0x00001bc8, 0x0000294e, 0x000035dd, 0x000040d8, 0x000049a7, 0x00004fc4, 0x000052be, 0x00005242, 0x00004e1e, 0x0000464a, 0x00003ae5, 0x00002c3b, 0x00001ac1,
+ 0x00000714, 0x000ff1f4, 0x000fdc3b, 0x000fc6d6, 0x000fb2c0, 0x000fa0ec, 0x000f9247, 0x000f87a1, 0x000f81ad, 0x000f80ec, 0x000f85b1, 0x000f900d, 0x000f9fda, 0x000fb4aa, 0x000fcdda, 0x000fea84, 0x00000996, 0x000029d1, 0x000049e0, 0x00006855,
+ 0x000083cf, 0x00009af4, 0x0000ac91, 0x0000b79e, 0x0000bb55, 0x0000b732, 0x0000ab0b, 0x00009703, 0x00007b9f, 0x000059b2, 0x00003267, 0x00000729, 0x000fd9a4, 0x000faba8, 0x000f7f24, 0x000f5602, 0x000f3223, 0x000f153c, 0x000f00cf, 0x000ef60a,
+ 0x000ef5c9, 0x000f0079, 0x000f161e, 0x000f3645, 0x000f600d, 0x000f9225, 0x000fcade, 0x00000833, 0x000047e1, 0x00008777, 0x0000c473, 0x0000fc56, 0x00012cc0, 0x00015388, 0x00016ed4, 0x00017d2b, 0x00017d87, 0x00016f60, 0x000152b9, 0x0001281a,
+ 0x0000f095, 0x0000adbd, 0x00006196, 0x00000e87, 0x000fb747, 0x000f5ec0, 0x000f07fc, 0x000eb605, 0x000e6bcb, 0x000e2c0f, 0x000df944, 0x000dd57e, 0x000dc25f, 0x000dc10a, 0x000dd21a, 0x000df59c, 0x000e2b14, 0x000e717c, 0x000ec755, 0x000f2aad,
+ 0x000f993a, 0x00001064, 0x00008d63, 0x00010d4f, 0x00018d3f, 0x00020a57, 0x000281e5, 0x0002f16e, 0x000356c1, 0x0003b005, 0x0003fbc3, 0x000438ea, 0x000466d2, 0x0004853f, 0x00049457, 0x000494a1, 0x000486f4, 0x00046c73, 0x0004467a, 0x00041691,
+ 0x0003de61, 0x00039fa1, 0x00035c0b, 0x0003154e, 0x0002cd02, 0x000284a2, 0x00023d80, 0x0001f8c4, 0x0001b763, 0x00017a21, 0x00014192, 0x00010e16, 0x0000dfe3, 0x0000b706, 0x00009368, 0x000074d3, 0x00005af9, 0x0000457c, 0x000033ef, 0x000025df,
+ 0x00001ad6, 0x00001262, 0x00000c13, 0x00000783, 0x00000457, 0x000002d8
+};
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 DmicQuad16BitFormatConfigSize = sizeof (DmicQuad16BitFormatConfig);
+
+// DMIC Config 4 channels, 32 bits, 2.4Mhz BCLK
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST UINT32 DmicQuad32BitFormatConfig[] =
+{
+ 0x00000000, 0xffffff10, 0xffff1010, 0xffff0101, 0xffff1100, 0x00000003, 0x00000003, 0x003a0003, 0x003a0003, 0x00000003, 0x0000c001, 0x04000900, 0x00000000, 0x00000803, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000091, 0x000402a0,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000091, 0x000e03b6, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008, 0x000fffae, 0x000fff12, 0x000ffdfb, 0x000ffc61, 0x000ffa5b,
+ 0x000ff82c, 0x000ff643, 0x000ff523, 0x000ff547, 0x000ff6f8, 0x000ffa29, 0x000ffe68, 0x000002e2, 0x0000068f, 0x00000875, 0x000007ef, 0x000004f3, 0x00000028, 0x000ffad3, 0x000ff68a, 0x000ff4c1, 0x000ff651, 0x000ffb22, 0x00000211, 0x00000929,
+ 0x00000e2c, 0x00000f3e, 0x00000b8e, 0x000003bb, 0x000ff9cb, 0x000ff0b0, 0x000feb71, 0x000fec2e, 0x000ff356, 0x000fff53, 0x00000cce, 0x0000179c, 0x00001bf8, 0x000017d1, 0x00000b9d, 0x000ffa79, 0x000fe96d, 0x000fddf8, 0x000fdc53, 0x000fe5f6,
+ 0x000ff8d5, 0x00000fbb, 0x000023a7, 0x00002def, 0x00002a6a, 0x00001905, 0x000ffe24, 0x000fe199, 0x000fcc68, 0x000fc5f7, 0x000fd18a, 0x000fece1, 0x00001079, 0x00003199, 0x00004578, 0x000044bc, 0x00002e15, 0x0000071b, 0x000fdb08, 0x000fb784,
+ 0x000fa877, 0x000fb41a, 0x000fd897, 0x00000c10, 0x00003f3b, 0x000061e1, 0x000067f6, 0x00004db0, 0x00001940, 0x000fd981, 0x000fa1ca, 0x000f841f, 0x000f8b6b, 0x000fb7a8, 0x000ffd3a, 0x000047e6, 0x000080ac, 0x000094cf, 0x00007beb, 0x00003b25,
+ 0x000fe44a, 0x000f90fe, 0x000f5b2e, 0x000f5512, 0x000f832c, 0x000fda2d, 0x000041a3, 0x00009ad1, 0x0000c9c2, 0x0000bdf2, 0x000077e2, 0x000009bc, 0x000f92ab, 0x000f360f, 0x000f110c, 0x000f318c, 0x000f9165, 0x00001750, 0x00009d91, 0x0000fc90,
+ 0x0001166e, 0x0000e025, 0x00006589, 0x000fc6c7, 0x000f2fea, 0x000eccac, 0x000ebbfa, 0x000f06a9, 0x000f9c25, 0x0000562c, 0x000102a9, 0x00017127, 0x0001802c, 0x000126dd, 0x0000782b, 0x000f9ea6, 0x000ed1f0, 0x000e4885, 0x000e298b, 0x000e8265,
+ 0x000f42a4, 0x00003f71, 0x00013d8c, 0x0001ff57, 0x0002537a, 0x0002209e, 0x00016b73, 0x000055ce, 0x000f1749, 0x000df142, 0x000d212b, 0x000cd43e, 0x000d1f22, 0x000dfb0f, 0x000f488e, 0x0000d6d5, 0x00026dc5, 0x0003d844, 0x0004ecd5, 0x00059301,
+ 0x0005c4ed, 0x00058d6f, 0x00050385, 0x0004448d, 0x00036e82, 0x00029b5d, 0x0001de2d, 0x00014211, 0x0000cac9, 0x0000765b, 0x00003f38, 0x00001e4a, 0x00000c93, 0x0000043b, 0x000000f9, 0x000fffd6, 0x00000217, 0x0000025b, 0x00000383, 0x00000507,
+ 0x000006e2, 0x00000916, 0x00000ba1, 0x00000e7b, 0x0000119a, 0x000014ec, 0x00001859, 0x00001bc7, 0x00001f15, 0x0000221d, 0x000024ba, 0x000026c3, 0x00002810, 0x0000287e, 0x000027ec, 0x00002640, 0x0000236c, 0x00001f6a, 0x00001a40, 0x00001402,
+ 0x00000cd3, 0x000004e2, 0x000ffc6b, 0x000ff3b7, 0x000feb17, 0x000fe2e2, 0x000fdb73, 0x000fd526, 0x000fd04f, 0x000fcd3a, 0x000fcc27, 0x000fcd42, 0x000fd0a5, 0x000fd64f, 0x000fde28, 0x000fe7fd, 0x000ff382, 0x0000004f, 0x00000deb, 0x00001bc8,
+ 0x0000294e, 0x000035dd, 0x000040d8, 0x000049a7, 0x00004fc4, 0x000052be, 0x00005242, 0x00004e1e, 0x0000464a, 0x00003ae5, 0x00002c3b, 0x00001ac1, 0x00000714, 0x000ff1f4, 0x000fdc3b, 0x000fc6d6, 0x000fb2c0, 0x000fa0ec, 0x000f9247, 0x000f87a1,
+ 0x000f81ad, 0x000f80ec, 0x000f85b1, 0x000f900d, 0x000f9fda, 0x000fb4aa, 0x000fcdda, 0x000fea84, 0x00000996, 0x000029d1, 0x000049e0, 0x00006855, 0x000083cf, 0x00009af4, 0x0000ac91, 0x0000b79e, 0x0000bb55, 0x0000b732, 0x0000ab0b, 0x00009703,
+ 0x00007b9f, 0x000059b2, 0x00003267, 0x00000729, 0x000fd9a4, 0x000faba8, 0x000f7f24, 0x000f5602, 0x000f3223, 0x000f153c, 0x000f00cf, 0x000ef60a, 0x000ef5c9, 0x000f0079, 0x000f161e, 0x000f3645, 0x000f600d, 0x000f9225, 0x000fcade, 0x00000833,
+ 0x000047e1, 0x00008777, 0x0000c473, 0x0000fc56, 0x00012cc0, 0x00015388, 0x00016ed4, 0x00017d2b, 0x00017d87, 0x00016f60, 0x000152b9, 0x0001281a, 0x0000f095, 0x0000adbd, 0x00006196, 0x00000e87, 0x000fb747, 0x000f5ec0, 0x000f07fc, 0x000eb605,
+ 0x000e6bcb, 0x000e2c0f, 0x000df944, 0x000dd57e, 0x000dc25f, 0x000dc10a, 0x000dd21a, 0x000df59c, 0x000e2b14, 0x000e717c, 0x000ec755, 0x000f2aad, 0x000f993a, 0x00001064, 0x00008d63, 0x00010d4f, 0x00018d3f, 0x00020a57, 0x000281e5, 0x0002f16e,
+ 0x000356c1, 0x0003b005, 0x0003fbc3, 0x000438ea, 0x000466d2, 0x0004853f, 0x00049457, 0x000494a1, 0x000486f4, 0x00046c73, 0x0004467a, 0x00041691, 0x0003de61, 0x00039fa1, 0x00035c0b, 0x0003154e, 0x0002cd02, 0x000284a2, 0x00023d80, 0x0001f8c4,
+ 0x0001b763, 0x00017a21, 0x00014192, 0x00010e16, 0x0000dfe3, 0x0000b706, 0x00009368, 0x000074d3, 0x00005af9, 0x0000457c, 0x000033ef, 0x000025df, 0x00001ad6, 0x00001262, 0x00000c13, 0x00000783, 0x00000457, 0x000002d8, 0x0000c001, 0x04000900,
+ 0x00000000, 0x00000803, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000091, 0x000402a0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000091, 0x000e03b6, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000008, 0x000fffae, 0x000fff12, 0x000ffdfb, 0x000ffc61, 0x000ffa5b, 0x000ff82c, 0x000ff643, 0x000ff523, 0x000ff547, 0x000ff6f8, 0x000ffa29, 0x000ffe68, 0x000002e2, 0x0000068f, 0x00000875, 0x000007ef, 0x000004f3,
+ 0x00000028, 0x000ffad3, 0x000ff68a, 0x000ff4c1, 0x000ff651, 0x000ffb22, 0x00000211, 0x00000929, 0x00000e2c, 0x00000f3e, 0x00000b8e, 0x000003bb, 0x000ff9cb, 0x000ff0b0, 0x000feb71, 0x000fec2e, 0x000ff356, 0x000fff53, 0x00000cce, 0x0000179c,
+ 0x00001bf8, 0x000017d1, 0x00000b9d, 0x000ffa79, 0x000fe96d, 0x000fddf8, 0x000fdc53, 0x000fe5f6, 0x000ff8d5, 0x00000fbb, 0x000023a7, 0x00002def, 0x00002a6a, 0x00001905, 0x000ffe24, 0x000fe199, 0x000fcc68, 0x000fc5f7, 0x000fd18a, 0x000fece1,
+ 0x00001079, 0x00003199, 0x00004578, 0x000044bc, 0x00002e15, 0x0000071b, 0x000fdb08, 0x000fb784, 0x000fa877, 0x000fb41a, 0x000fd897, 0x00000c10, 0x00003f3b, 0x000061e1, 0x000067f6, 0x00004db0, 0x00001940, 0x000fd981, 0x000fa1ca, 0x000f841f,
+ 0x000f8b6b, 0x000fb7a8, 0x000ffd3a, 0x000047e6, 0x000080ac, 0x000094cf, 0x00007beb, 0x00003b25, 0x000fe44a, 0x000f90fe, 0x000f5b2e, 0x000f5512, 0x000f832c, 0x000fda2d, 0x000041a3, 0x00009ad1, 0x0000c9c2, 0x0000bdf2, 0x000077e2, 0x000009bc,
+ 0x000f92ab, 0x000f360f, 0x000f110c, 0x000f318c, 0x000f9165, 0x00001750, 0x00009d91, 0x0000fc90, 0x0001166e, 0x0000e025, 0x00006589, 0x000fc6c7, 0x000f2fea, 0x000eccac, 0x000ebbfa, 0x000f06a9, 0x000f9c25, 0x0000562c, 0x000102a9, 0x00017127,
+ 0x0001802c, 0x000126dd, 0x0000782b, 0x000f9ea6, 0x000ed1f0, 0x000e4885, 0x000e298b, 0x000e8265, 0x000f42a4, 0x00003f71, 0x00013d8c, 0x0001ff57, 0x0002537a, 0x0002209e, 0x00016b73, 0x000055ce, 0x000f1749, 0x000df142, 0x000d212b, 0x000cd43e,
+ 0x000d1f22, 0x000dfb0f, 0x000f488e, 0x0000d6d5, 0x00026dc5, 0x0003d844, 0x0004ecd5, 0x00059301, 0x0005c4ed, 0x00058d6f, 0x00050385, 0x0004448d, 0x00036e82, 0x00029b5d, 0x0001de2d, 0x00014211, 0x0000cac9, 0x0000765b, 0x00003f38, 0x00001e4a,
+ 0x00000c93, 0x0000043b, 0x000000f9, 0x000fffd6, 0x00000217, 0x0000025b, 0x00000383, 0x00000507, 0x000006e2, 0x00000916, 0x00000ba1, 0x00000e7b, 0x0000119a, 0x000014ec, 0x00001859, 0x00001bc7, 0x00001f15, 0x0000221d, 0x000024ba, 0x000026c3,
+ 0x00002810, 0x0000287e, 0x000027ec, 0x00002640, 0x0000236c, 0x00001f6a, 0x00001a40, 0x00001402, 0x00000cd3, 0x000004e2, 0x000ffc6b, 0x000ff3b7, 0x000feb17, 0x000fe2e2, 0x000fdb73, 0x000fd526, 0x000fd04f, 0x000fcd3a, 0x000fcc27, 0x000fcd42,
+ 0x000fd0a5, 0x000fd64f, 0x000fde28, 0x000fe7fd, 0x000ff382, 0x0000004f, 0x00000deb, 0x00001bc8, 0x0000294e, 0x000035dd, 0x000040d8, 0x000049a7, 0x00004fc4, 0x000052be, 0x00005242, 0x00004e1e, 0x0000464a, 0x00003ae5, 0x00002c3b, 0x00001ac1,
+ 0x00000714, 0x000ff1f4, 0x000fdc3b, 0x000fc6d6, 0x000fb2c0, 0x000fa0ec, 0x000f9247, 0x000f87a1, 0x000f81ad, 0x000f80ec, 0x000f85b1, 0x000f900d, 0x000f9fda, 0x000fb4aa, 0x000fcdda, 0x000fea84, 0x00000996, 0x000029d1, 0x000049e0, 0x00006855,
+ 0x000083cf, 0x00009af4, 0x0000ac91, 0x0000b79e, 0x0000bb55, 0x0000b732, 0x0000ab0b, 0x00009703, 0x00007b9f, 0x000059b2, 0x00003267, 0x00000729, 0x000fd9a4, 0x000faba8, 0x000f7f24, 0x000f5602, 0x000f3223, 0x000f153c, 0x000f00cf, 0x000ef60a,
+ 0x000ef5c9, 0x000f0079, 0x000f161e, 0x000f3645, 0x000f600d, 0x000f9225, 0x000fcade, 0x00000833, 0x000047e1, 0x00008777, 0x0000c473, 0x0000fc56, 0x00012cc0, 0x00015388, 0x00016ed4, 0x00017d2b, 0x00017d87, 0x00016f60, 0x000152b9, 0x0001281a,
+ 0x0000f095, 0x0000adbd, 0x00006196, 0x00000e87, 0x000fb747, 0x000f5ec0, 0x000f07fc, 0x000eb605, 0x000e6bcb, 0x000e2c0f, 0x000df944, 0x000dd57e, 0x000dc25f, 0x000dc10a, 0x000dd21a, 0x000df59c, 0x000e2b14, 0x000e717c, 0x000ec755, 0x000f2aad,
+ 0x000f993a, 0x00001064, 0x00008d63, 0x00010d4f, 0x00018d3f, 0x00020a57, 0x000281e5, 0x0002f16e, 0x000356c1, 0x0003b005, 0x0003fbc3, 0x000438ea, 0x000466d2, 0x0004853f, 0x00049457, 0x000494a1, 0x000486f4, 0x00046c73, 0x0004467a, 0x00041691,
+ 0x0003de61, 0x00039fa1, 0x00035c0b, 0x0003154e, 0x0002cd02, 0x000284a2, 0x00023d80, 0x0001f8c4, 0x0001b763, 0x00017a21, 0x00014192, 0x00010e16, 0x0000dfe3, 0x0000b706, 0x00009368, 0x000074d3, 0x00005af9, 0x0000457c, 0x000033ef, 0x000025df,
+ 0x00001ad6, 0x00001262, 0x00000c13, 0x00000783, 0x00000457, 0x000002d8
+};
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 DmicQuad32BitFormatConfigSize = sizeof (DmicQuad32BitFormatConfig);
+
+// DMIC Config 1 channel, 16 bits
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST UINT32 DmicMono16BitFormatConfig[] =
+{
+ 0x00000000,
+ 0xfffffff0,0xfffffff0,0xfffffff0,0xfffffff0,
+ 3,
+ 3,
+ 0x00300003,
+ 0x00300003,
+ 0x3,
+ 0x0, 0x09001303, 0x0, 0x0301, 0, 0, 0, 0,
+ 0x10, 0x402a0, 0, 0, 0, 0, 0, 0,
+ 0x10, 0xe03ae, 0, 0, 0, 0, 0, 0,
+ 0x00008, 0xfffae, 0xfff12, 0xffdfb, 0xffc61, 0xffa5a, 0xff82b, 0xff641, 0xff520, 0xff544, 0xff6f4, 0xffa25, 0xffe65,
+ 0x002e0, 0x0068f, 0x00876, 0x007f1, 0x004f5, 0x0002a, 0xffad4, 0xff68a, 0xff4bf, 0xff64f, 0xffb20,
+ 0x0020f, 0x00929, 0x00e2d, 0x00f40, 0x00b92, 0x003bf, 0xff9cd, 0xff0b0, 0xfeb6e, 0xfec2a, 0xff351,
+ 0xfff4f, 0x00ccd, 0x0179d, 0x01bfc, 0x017d7, 0x00ba3, 0xffa7e, 0xfe96f, 0xfddf5, 0xfdc4d, 0xfe5ee,
+ 0xff8ce, 0x00fb7, 0x023a8, 0x02df5, 0x02a74, 0x01910, 0xffe2c, 0xfe19c, 0xfcc64, 0xfc5ee, 0xfd17e,
+ 0xfecd4, 0x01071, 0x03198, 0x0457e, 0x044c9, 0x02e24, 0x00728, 0xfdb0e, 0xfb781, 0xfa86b, 0xfb408,
+ 0xfd884, 0x00c02, 0x03f37, 0x061e8, 0x06807, 0x04dc5, 0x01954, 0xfd98c, 0xfa1c8, 0xf840f, 0xf8b52,
+ 0xfb78c, 0xffd23, 0x047db, 0x080b1, 0x094e3, 0x07c08, 0x03b41, 0xfe45e, 0xf9101, 0xf5b1e, 0xf54f4,
+ 0xf8307, 0xfda0b, 0x0418f, 0x09ad0, 0x0c9d6, 0x0be16, 0x0780b, 0x009dd, 0xf92ba, 0xf3606, 0xf10ed,
+ 0xf315e, 0xf9135, 0x0172c, 0x09d83, 0x0fc9e, 0x11695, 0x0e05b, 0x065bf, 0xfc6ed, 0xf2ff4, 0xecc96,
+ 0xebbc9, 0xf0668, 0xf9be7, 0x05601, 0x1029e, 0x17140, 0x18065, 0x12728, 0x07874, 0xf9edb, 0xed202,
+ 0xe486c, 0xe294d, 0xe820f, 0xf424a, 0x03f29, 0x13d68, 0x1ff61, 0x253b2, 0x220fa, 0x16be1, 0x05638,
+ 0xf1798, 0xdf165, 0xd211a, 0xcd3f9, 0xd1eb5, 0xdfa89, 0xf4802, 0x0d656, 0x26d63, 0x3d808, 0x4ecc3,
+ 0x59315, 0x5c520, 0x58db6, 0x503d6, 0x444dd, 0x36ecb, 0x29b9a, 0x1de5d, 0x14234, 0x0cae0, 0x07669,
+ 0x03f40, 0x01e4e, 0x00c95, 0x0043b, 0x000f9,0xff961, 0x00823, 0x0084f, 0x00a39, 0x00d21, 0x010a8, 0x0149a, 0x018cc, 0x01d15, 0x0214d, 0x02543, 0x028c8, 0x02baa,
+ 0x02db8, 0x02ec6, 0x02eac, 0x02d4c, 0x02a90, 0x02672, 0x020f9, 0x01a3b, 0x0125c, 0x00994, 0x00025,
+ 0xff662, 0xfeca3, 0xfe34c, 0xfdabe, 0xfd364, 0xfcd94, 0xfc9a4, 0xfc7dd, 0xfc86b, 0xfcb6e, 0xfd0e6,
+ 0xfd8bb, 0xfe2b9, 0xfee8f, 0xffbd5, 0x00a0c, 0x018a3, 0x026fc, 0x03474, 0x04065, 0x04a36, 0x0515a,
+ 0x0555a, 0x055df, 0x052b2, 0x04bc3, 0x0412c, 0x03332, 0x02242, 0x00ef3, 0xff9fb, 0xfe430, 0xfce78,
+ 0xfb9c6, 0xfa70f, 0xf973a, 0xf8b1e, 0xf836e, 0xf80b7, 0xf8355, 0xf8b6e, 0xf98ea, 0xfab78, 0xfc288,
+ 0xfdd52, 0xffadf, 0x01a0a, 0x03992, 0x05823, 0x07465, 0x08d0c, 0x0a0e3, 0x0aedc, 0x0b61f, 0x0b614,
+ 0x0ae6b, 0x09f23, 0x0888d, 0x06b4c, 0x04850, 0x020d3, 0xff647, 0xfca4f, 0xf9eae, 0xf7533, 0xf4fa8,
+ 0xf2fc0, 0xf1702, 0xf06ba, 0xeffe6, 0xf032d, 0xf10d3, 0xf28b4, 0xf4a42, 0xf7486, 0xfa62a, 0xfdd81,
+ 0x01896, 0x0553d, 0x09128, 0x0c9fe, 0x0fd6f, 0x1294e, 0x14ba5, 0x162cb, 0x16d75, 0x16ac4, 0x15a52,
+ 0x13c38, 0x1110d, 0x0d9e9, 0x09856, 0x04e4a, 0xffe17, 0xfaa51, 0xf55c4, 0xf0350, 0xeb5d6, 0xe7020,
+ 0xe34c8, 0xe0620, 0xde61c, 0xdd64b, 0xdd7bd, 0xdeb03, 0xe102a, 0xe46b5, 0xe8dab, 0xee397, 0xf4699,
+ 0xfb479, 0x02ab3, 0x0a691, 0x1253c, 0x1a3d9, 0x21f98, 0x295cc, 0x30400, 0x36803, 0x3bff8, 0x40a63,
+ 0x44628, 0x4729b, 0x48f76, 0x49cd2, 0x49b35, 0x48b71, 0x46ea5, 0x44632, 0x413a6, 0x3d8b3, 0x3971b,
+ 0x350a6, 0x30716, 0x2bc15, 0x27131, 0x227cb, 0x1e11d, 0x19e2a, 0x15fc1, 0x1267c, 0x0f2c0, 0x0c4c2,
+ 0x09c8b, 0x079fb, 0x05cd2, 0x044b2, 0x0312d, 0x021c5, 0x015f4, 0x0135e,
+ 0x0, 0x09001303, 0x0, 0x0301, 0, 0, 0, 0,
+ 0x10, 0x402a0, 0, 0, 0, 0, 0, 0,
+ 0x10, 0xe03ae, 0, 0, 0, 0, 0, 0,
+ 0x00008, 0xfffae, 0xfff12, 0xffdfb, 0xffc61, 0xffa5a, 0xff82b, 0xff641, 0xff520, 0xff544, 0xff6f4, 0xffa25, 0xffe65,
+ 0x002e0, 0x0068f, 0x00876, 0x007f1, 0x004f5, 0x0002a, 0xffad4, 0xff68a, 0xff4bf, 0xff64f, 0xffb20,
+ 0x0020f, 0x00929, 0x00e2d, 0x00f40, 0x00b92, 0x003bf, 0xff9cd, 0xff0b0, 0xfeb6e, 0xfec2a, 0xff351,
+ 0xfff4f, 0x00ccd, 0x0179d, 0x01bfc, 0x017d7, 0x00ba3, 0xffa7e, 0xfe96f, 0xfddf5, 0xfdc4d, 0xfe5ee,
+ 0xff8ce, 0x00fb7, 0x023a8, 0x02df5, 0x02a74, 0x01910, 0xffe2c, 0xfe19c, 0xfcc64, 0xfc5ee, 0xfd17e,
+ 0xfecd4, 0x01071, 0x03198, 0x0457e, 0x044c9, 0x02e24, 0x00728, 0xfdb0e, 0xfb781, 0xfa86b, 0xfb408,
+ 0xfd884, 0x00c02, 0x03f37, 0x061e8, 0x06807, 0x04dc5, 0x01954, 0xfd98c, 0xfa1c8, 0xf840f, 0xf8b52,
+ 0xfb78c, 0xffd23, 0x047db, 0x080b1, 0x094e3, 0x07c08, 0x03b41, 0xfe45e, 0xf9101, 0xf5b1e, 0xf54f4,
+ 0xf8307, 0xfda0b, 0x0418f, 0x09ad0, 0x0c9d6, 0x0be16, 0x0780b, 0x009dd, 0xf92ba, 0xf3606, 0xf10ed,
+ 0xf315e, 0xf9135, 0x0172c, 0x09d83, 0x0fc9e, 0x11695, 0x0e05b, 0x065bf, 0xfc6ed, 0xf2ff4, 0xecc96,
+ 0xebbc9, 0xf0668, 0xf9be7, 0x05601, 0x1029e, 0x17140, 0x18065, 0x12728, 0x07874, 0xf9edb, 0xed202,
+ 0xe486c, 0xe294d, 0xe820f, 0xf424a, 0x03f29, 0x13d68, 0x1ff61, 0x253b2, 0x220fa, 0x16be1, 0x05638,
+ 0xf1798, 0xdf165, 0xd211a, 0xcd3f9, 0xd1eb5, 0xdfa89, 0xf4802, 0x0d656, 0x26d63, 0x3d808, 0x4ecc3,
+ 0x59315, 0x5c520, 0x58db6, 0x503d6, 0x444dd, 0x36ecb, 0x29b9a, 0x1de5d, 0x14234, 0x0cae0, 0x07669,
+ 0x03f40, 0x01e4e, 0x00c95, 0x0043b, 0x000f9,0xff961, 0x00823, 0x0084f, 0x00a39, 0x00d21, 0x010a8, 0x0149a, 0x018cc, 0x01d15, 0x0214d, 0x02543, 0x028c8, 0x02baa,
+ 0x02db8, 0x02ec6, 0x02eac, 0x02d4c, 0x02a90, 0x02672, 0x020f9, 0x01a3b, 0x0125c, 0x00994, 0x00025,
+ 0xff662, 0xfeca3, 0xfe34c, 0xfdabe, 0xfd364, 0xfcd94, 0xfc9a4, 0xfc7dd, 0xfc86b, 0xfcb6e, 0xfd0e6,
+ 0xfd8bb, 0xfe2b9, 0xfee8f, 0xffbd5, 0x00a0c, 0x018a3, 0x026fc, 0x03474, 0x04065, 0x04a36, 0x0515a,
+ 0x0555a, 0x055df, 0x052b2, 0x04bc3, 0x0412c, 0x03332, 0x02242, 0x00ef3, 0xff9fb, 0xfe430, 0xfce78,
+ 0xfb9c6, 0xfa70f, 0xf973a, 0xf8b1e, 0xf836e, 0xf80b7, 0xf8355, 0xf8b6e, 0xf98ea, 0xfab78, 0xfc288,
+ 0xfdd52, 0xffadf, 0x01a0a, 0x03992, 0x05823, 0x07465, 0x08d0c, 0x0a0e3, 0x0aedc, 0x0b61f, 0x0b614,
+ 0x0ae6b, 0x09f23, 0x0888d, 0x06b4c, 0x04850, 0x020d3, 0xff647, 0xfca4f, 0xf9eae, 0xf7533, 0xf4fa8,
+ 0xf2fc0, 0xf1702, 0xf06ba, 0xeffe6, 0xf032d, 0xf10d3, 0xf28b4, 0xf4a42, 0xf7486, 0xfa62a, 0xfdd81,
+ 0x01896, 0x0553d, 0x09128, 0x0c9fe, 0x0fd6f, 0x1294e, 0x14ba5, 0x162cb, 0x16d75, 0x16ac4, 0x15a52,
+ 0x13c38, 0x1110d, 0x0d9e9, 0x09856, 0x04e4a, 0xffe17, 0xfaa51, 0xf55c4, 0xf0350, 0xeb5d6, 0xe7020,
+ 0xe34c8, 0xe0620, 0xde61c, 0xdd64b, 0xdd7bd, 0xdeb03, 0xe102a, 0xe46b5, 0xe8dab, 0xee397, 0xf4699,
+ 0xfb479, 0x02ab3, 0x0a691, 0x1253c, 0x1a3d9, 0x21f98, 0x295cc, 0x30400, 0x36803, 0x3bff8, 0x40a63,
+ 0x44628, 0x4729b, 0x48f76, 0x49cd2, 0x49b35, 0x48b71, 0x46ea5, 0x44632, 0x413a6, 0x3d8b3, 0x3971b,
+ 0x350a6, 0x30716, 0x2bc15, 0x27131, 0x227cb, 0x1e11d, 0x19e2a, 0x15fc1, 0x1267c, 0x0f2c0, 0x0c4c2,
+ 0x09c8b, 0x079fb, 0x05cd2, 0x044b2, 0x0312d, 0x021c5, 0x015f4, 0x0135e
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 DmicMono16BitFormatConfigSize = sizeof (DmicMono16BitFormatConfig);
+
+//
+// I2S Configuration BLOBs
+// Audio Format and Configuration details
+//
+// Frequency: 48kHz, PCM resolution: 24 bits
+// TDM slots: 4
+// Codec: Realtek ALC298, mode: slave
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST UINT32 I2sRtk298Render4ch48kHz24bitFormatConfig[] = {0x0, 0xffffff10, 0xffffff32, 0xffff3210, 0xffff3210, 0xffff3210, 0xffff3210, 0xffff3210, 0xffff3210, 0x83d00437, 0xc0700000, 0x0, 0x02010004, 0xf, 0xf, 0x4002, 0x4, 0x7070f00, 0x20, 0x00000001, 0x00000fff};
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 I2sRtk298Render4ch48kHz24bitFormatConfigSize = sizeof (I2sRtk298Render4ch48kHz24bitFormatConfig);
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST UINT32 I2sRtk298Capture4ch48kHz24bitFormatConfig[] = {0x0, 0xffffff10, 0xffffff10, 0xffffff10, 0xffffff10, 0xffffff10, 0xffffff10, 0xffffff10, 0xffffff10, 0x83d00437, 0xc0700000, 0x0, 0x02010004, 0xf, 0xf, 0x4002, 0x4, 0x7070f00, 0x20, 0x00000001, 0x00000fff};
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 I2sRtk298Capture4ch48kHz24bitFormatConfigSize = sizeof (I2sRtk298Capture4ch48kHz24bitFormatConfig);
+
+// Audio Format: 48kHz, 2channels, master clock
+// Codec: Realtek ALC286S
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST UINT32 I2sRtk286S2ch48kHzFormatConfig[] = { 0, 0xffffff10, 0xffffff32, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x83d00437, 0xc0700000, 0x0, 0x2990000, 0xf, 0xf, 0x4002, 0x0, 0x7070f00, 0x20, 0x1, 0xfff };
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 I2sRtk286S2ch48kHzFormatConfigSize = sizeof (I2sRtk286S2ch48kHzFormatConfig);
+
+// Audio Format: 48kHz, 4 channels
+// Codec: ADI SSM4567
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST UINT32 I2sAdi4ch48kHzFormatConfig[] = { 0, 0xffffff10, 0xffffff32, 0xffff3210, 0xffff3210, 0xffff3210, 0xffff3210, 0xffff3210, 0xffff3210, 0x83d00437, 0xc0700000, 0x0, 0x2010004, 0xf, 0xf, 0x4002, 0x4, 0x7070f00, 0x20, 0, 0 };
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 I2sAdi4ch48kHzFormatConfigSize = sizeof (I2sAdi4ch48kHzFormatConfig);
+
+// Audio Format: 24bit, 48kHz, Master
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST UINT32 I2s48kHz24bitMasterFormatConfig[] = { 0, 0xffffff10, 0xffffff10, 0xffffff10, 0xffffff10, 0xffffff10, 0xffffff10, 0xffffff10, 0xffffff10, 0x81d00937, 0xc0700000, 0x0, 0x02990000, 0x3, 0x3, 0x4002, 0x0, 0x7070f00, 0x20, 1, 0xFFF};
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 I2s48kHz24bitMasterFormatConfigSize = sizeof (I2s48kHz24bitMasterFormatConfig);
+
+// Audio Format: 24bit, 48kHz, Slave
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST UINT32 I2s48kHz24bitSlaveFormatConfig[] = { 0, 0xffffff10, 0xffffff10, 0xffffff10, 0xffffff10, 0xffffff10, 0xffffff10, 0xffffff10, 0xffffff10, 0x81d00037, 0xd3700000, 0x0, 0x02000000, 0x3, 0x3, 0x4002, 0x0, 0x7070f00, 0x00, 1, 0xFFF};
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 I2s48kHz24bitSlaveFormatConfigSize = sizeof (I2s48kHz24bitSlaveFormatConfig);
+
+// Audio Format: PCM 16bit, 8kHz, Master
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST UINT32 I2sPcm8kHz16bitMasterFormatConfig[] = { 0, 0xfffffff0, 0xfffffff0, 0xfffffff0, 0xfffffff0, 0xfffffff0, 0xfffffff0, 0xfffffff0, 0xfffffff0, 0x80c0953f, 0xc0400000, 0x0, 0x02010004, 0x1, 0x1, 0x4002, 0x4, 0x7020000, 0x20, 1, 0xFFF};
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 I2sPcm8kHz16bitMasterFormatConfigSize = sizeof (I2sPcm8kHz16bitMasterFormatConfig);
+
+// Audio Format: PCM 16bit, 8kHz, Slave
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST UINT32 I2sPcm8kHz16bitSlaveFormatConfig[] = { 0, 0xfffffff0, 0xfffffff0, 0xfffffff0, 0xfffffff0, 0xfffffff0, 0xfffffff0, 0xfffffff0, 0xfffffff0, 0x80c0003f, 0xd3400000, 0x0, 0x02000004, 0x1, 0x1, 0x4002, 0x0, 0x7020000, 0x00, 1, 0xFFF};
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 I2sPcm8kHz16bitSlaveFormatConfigSize = sizeof (I2sPcm8kHz16bitSlaveFormatConfig);
+
+//
+// BlueTooth Configuration BLOBs
+//
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST UINT32 BtFormatConfig[] =
+{
+ 0x0, 0xfffffff0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x80c0003f, 0xd3400000, 0x0, 0x02000005, 0x01, 0x01, 0x4002,
+ 0x0, 0x07020000, 0x0, 0x01, 0x0
+};
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 BtFormatConfigSize = sizeof (BtFormatConfig);
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeI2cMasterCommonLib/I2cMasterCommonLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeI2cMasterCommonLib/I2cMasterCommonLib.c
new file mode 100644
index 0000000000..32814bf773
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeI2cMasterCommonLib/I2cMasterCommonLib.c
@@ -0,0 +1,545 @@
+/** @file
+ Implement the I2C controller driver.
+
+Copyright (c) 2017, 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 <Uefi.h>
+#include <Base.h>
+#include <IndustryStandard/Pci.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/TimerLib.h>
+#include <Library/UefiLib.h>
+#include <PchAccess.h>
+#include <Library/PchSerialIoLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Protocol/I2cMaster.h>
+#include <Pi/PiI2c.h>
+#include <Library/DevicePathLib.h>
+#include <Library/I2cMasterCommonLib.h>
+
+/**
+ Prepare I2c controller for use: enable its mmio range, put in D0, get out of reset
+
+ @param[in] Context - driver context
+**/
+VOID
+PrepareController (
+ I2C_MASTER_CONTEXT *Context
+ )
+{
+ MmioOr32 (Context->ConfigAddress + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_MEMORY_SPACE | EFI_PCI_COMMAND_BUS_MASTER);
+ MmioAnd32 (Context->ConfigAddress + R_PCH_SERIAL_IO_PME_CTRL_STS, (UINT32) (~B_PCH_SERIAL_IO_PME_CTRL_STS_PWR_ST));
+ MmioOr32 (Context->MmioAddress + R_PCH_SERIAL_IO_PPR_RESETS,
+ B_PCH_SERIAL_IO_PPR_RESETS_FUNC | B_PCH_SERIAL_IO_PPR_RESETS_APB | B_PCH_SERIAL_IO_PPR_RESETS_IDMA);
+}
+
+/**
+ Determine the state of the I2C controller
+
+ @param[in] Context - driver context
+
+ @retval TRUE The I2C controller is active
+ @retval FALSE The I2C controller is idle
+**/
+BOOLEAN
+IsHardwareActive (
+ I2C_MASTER_CONTEXT *Context
+ )
+{
+ return (MmioRead32 (Context->MmioAddress + R_IC_STATUS) & B_IC_STATUS_ACTIVITY );
+}
+
+/**
+ Updates WriteOperation and WritePosition, two variables that determine
+ which part of Request is being committed to I2C bus.
+ This iterates over both Read and Write operations from a request, because
+ things that need to be written to WriteFifo are both I2c bus writes
+ and I2c bus reads (the command to perform bus read needs to be put into Write Fifo)
+
+ @param[in] Context - driver context
+**/
+VOID
+UpdateWritePosition (
+ I2C_MASTER_CONTEXT *Context
+ )
+{
+ if ( Context->WritePos == Context->Request->Operation[Context->WriteOp].LengthInBytes - 1) {
+ Context->WritePos = 0;
+ Context->WriteOp ++;
+ } else {
+ Context->WritePos ++;
+ }
+}
+
+/*
+ FindReadOp checks if current Operation is of Read type. If so, returns.
+ If not, increases ReadOp until it finds one or goes beyond Request's OperationCount
+
+ @param[in] Context - driver context
+*/
+VOID
+FindReadOp (
+ I2C_MASTER_CONTEXT *Context
+ )
+{
+ while (Context->ReadOp < Context->Request->OperationCount &&
+ !(Context->Request->Operation[Context->ReadOp].Flags & I2C_FLAG_READ)) {
+ Context->ReadOp++;
+ }
+}
+
+/**
+ Updates ReadOperation and ReadPosition, two variables that determine
+ which part of Request is being filled with data incoming from I2C reads.
+ This iterates only over Read operations from a request.
+
+ @param[in] Context - driver context
+**/
+VOID
+UpdateReadPosition (
+ I2C_MASTER_CONTEXT *Context
+ )
+{
+ if ( Context->ReadPos == Context->Request->Operation[Context->ReadOp].LengthInBytes - 1) {
+ Context->ReadPos = 0;
+ Context->ReadOp ++;
+ FindReadOp (Context);
+ } else {
+ Context->ReadPos ++;
+ }
+}
+
+/**
+ ValidateRequest checks if Request is valid and can be started
+
+ @param[in] Context - driver context
+ @param[in] RequestPacket
+
+ @retval EFI_SUCCESS Request is valid and can be started
+ @retval EFI_ALREADY_STARTED The controller is busy with another transfer
+ @retval EFI_BAD_BUFFER_SIZE Transfer size too big
+ @retval EFI_INVALID_PARAMETER RequestPacket is NULL, invalid Operation flags
+ @retval EFI_UNSUPPORTED "ping" operation attempted (0-byte transfer, address byte not followed by any data)
+**/
+EFI_STATUS
+ValidateRequest (
+ I2C_MASTER_CONTEXT *Context,
+ CONST EFI_I2C_REQUEST_PACKET *RequestPacket
+ )
+{
+ UINTN TotalSize;
+ UINTN Operation;
+ UINTN OperationSize;
+
+ if (Context->TransferInProgress) {
+ return EFI_ALREADY_STARTED;
+ }
+ if (RequestPacket == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (RequestPacket->OperationCount == 0) {
+ // 0-size operations ("pings") not supported
+ return EFI_UNSUPPORTED;
+ }
+
+ TotalSize = 0;
+
+ for (Operation=0; Operation < RequestPacket->OperationCount; Operation++) {
+ // unsupported flags?
+ if ((RequestPacket->Operation[Operation].Flags & (~I2C_FLAG_READ)) != 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+ OperationSize = RequestPacket->Operation[Operation].LengthInBytes;
+ // 0-size operations ("pings") not supported
+ if (OperationSize == 0) {
+ return EFI_UNSUPPORTED;
+ }
+ TotalSize += OperationSize;
+ // read operation too big?
+ if (RequestPacket->Operation[Operation].Flags & I2C_FLAG_READ) {
+ if (OperationSize > Context->Capabilities.MaximumReceiveBytes) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+ // write operation too big?
+ } else {
+ if (OperationSize > Context->Capabilities.MaximumTransmitBytes) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+ }
+ }
+ // total request too big?
+ if (TotalSize > Context->Capabilities.MaximumTotalBytes) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ IsLastFromRequest checks if WritePos and WriteOp point to the last byte of the request
+
+ @param[in] Context - driver context
+
+ @retval Boolean
+**/
+BOOLEAN
+IsLastFromRequest (
+ I2C_MASTER_CONTEXT *Context
+ )
+{
+ if ((Context->WriteOp == Context->Request->OperationCount - 1 ) &&
+ (Context->WritePos == Context->Request->Operation[Context->WriteOp].LengthInBytes - 1)) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+/**
+ IsFirstFromOperation checks if WritePos and WriteOp point to the first byte of an operation
+
+ @param[in] Context - driver context
+
+ @retval Boolean
+**/
+BOOLEAN
+IsFirstFromOperation (
+ I2C_MASTER_CONTEXT *Context
+ )
+{
+ if ((Context->WriteOp != 0) && (Context->WritePos == 0)) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+/**
+ InitializeTransfer checks if HW is ready to accept new transfer.
+ If so, sets up slave address
+
+ @param[in] Context - driver context
+
+ @retval Status
+**/
+EFI_STATUS
+InitializeTransfer (
+ I2C_MASTER_CONTEXT *Context,
+ UINTN SlaveAddress,
+ CONST EFI_I2C_REQUEST_PACKET *RequestPacket
+ )
+{
+ UINT32 Attempts = 10000;
+ UINT32 Address;
+
+ Context->Request = (EFI_I2C_REQUEST_PACKET*) RequestPacket;
+ Context->TransferStatus = EFI_SUCCESS;
+ Context->WriteOp = 0;
+ Context->WritePos = 0;
+ Context->ReadOp = 0;
+ FindReadOp (Context);
+ Context->ReadPos = 0;
+
+ if (MmioRead32 (Context->MmioAddress + R_IC_ENABLE) != 0) {
+ DEBUG (( DEBUG_ERROR, "Address change was attempted while a transfer was underway!\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ Address = SlaveAddress & 0xFF;
+ if (SlaveAddress & I2C_ADDRESSING_10_BIT
+ ) {
+ Address |= B_IC_TAR_10BITADDR_MASTER;
+ }
+ MmioWrite32 (Context->MmioAddress + R_IC_TAR, Address);
+ MmioWrite32 (Context->MmioAddress + R_IC_ENABLE, B_IC_EN );
+ //clear errors
+ MmioRead32 (Context->MmioAddress + R_IC_CLR_TX_ABRT);
+ MmioRead32 (Context->MmioAddress + R_IC_CLR_INTR);
+
+ while ( !(MmioRead32 (Context->MmioAddress + R_IC_ENABLE_STATUS ) & B_IC_EN)) {
+ //should never happen, but just to make sure BIOS doesn't hang in infinite loop...
+ MicroSecondDelay (1);
+ if (--Attempts == 0) {
+ MmioWrite32 (Context->MmioAddress + R_IC_ENABLE, 0 );
+ return EFI_DEVICE_ERROR;
+ }
+ }
+ Context->TransferInProgress = TRUE;
+ return EFI_SUCCESS;
+}
+
+/**
+ WriteFifo writes to I2c controller's transmit Fifo. Data written to Fifo could be
+ - data bytes to be written to an i2c slave
+ - read requests that trigger i2c bus reads
+ First transfer from each operation adds Restart bit which triggers Restart condition on bus
+ Last transfer from the whole Request adds Stop bit which triggers Stop condtion on bus
+ Driver keeps track of which parts of Request were already committed to hardware using
+ pointer consisting of WritePosition and WriteOperation variables. This pointer is updated
+ every time data byte/read request is committed to FIFO
+ WriteFifo executes while there's anything more to write and the write fifo isn't full
+
+ @param[in] Context - driver context
+**/
+VOID
+WriteFifo (
+ I2C_MASTER_CONTEXT *Context
+ )
+{
+ UINT32 Data;
+ while ( MmioRead32 (Context->MmioAddress + R_IC_STATUS ) & B_IC_STATUS_TFNF) {
+ if (Context->WriteOp >= Context->Request->OperationCount ) {
+ return; // request complete, nothing more to write
+ }
+
+ if (Context->Request->Operation[Context->WriteOp].Flags & I2C_FLAG_READ) {
+ Data = B_IC_CMD_READ;
+ } else {
+ Data = Context->Request->Operation[Context->WriteOp].Buffer[Context->WritePos];
+ }
+ if (IsLastFromRequest (Context)) {
+ Data |= B_IC_CMD_STOP;
+ }
+ if (IsFirstFromOperation (Context)) {
+ Data |= B_IC_CMD_RESTART;
+ }
+ MmioWrite32 (Context->MmioAddress + R_IC_DATA_CMD, Data);
+ UpdateWritePosition (Context);
+ }
+}
+
+/**
+ ReadFifo reads from I2c controller's receive Fifo. It contains data retrieved
+ from slave device as a result of executing read transfers, which were
+ triggered by putting read requests into Write Fifo. Retrieved data is copied into buffers
+ pointed to by Request structure.
+ Driver keeps track where to copy incoming data using pointer consisting of
+ ReadPosition and ReadOperation variables. This pointer is updated
+ every time data was retrieved from hardware
+ ReadFifo executes while there's data available and receive buffers were not filled
+
+ @param[in] Context - driver context
+**/
+VOID
+ReadFifo (
+ I2C_MASTER_CONTEXT *Context
+ )
+{
+ while ( MmioRead32 ( Context->MmioAddress + R_IC_STATUS ) & B_IC_STATUS_RFNE) {
+ if ( Context->ReadOp >= Context->Request->OperationCount ) {
+ return;
+ }
+ Context->Request->Operation[Context->ReadOp].Buffer[Context->ReadPos] = (0xFF & MmioRead32 (Context->MmioAddress + R_IC_DATA_CMD));
+ UpdateReadPosition (Context);
+ }
+}
+
+/**
+ CheckErrors checks if there were any transfer errors.
+
+ @param[in] Context - driver context
+**/
+VOID
+CheckErrors (
+ I2C_MASTER_CONTEXT *Context
+ )
+{
+ if (!(MmioRead32 (Context->MmioAddress + R_IC_INTR_STAT) & B_IC_INTR_TX_ABRT)) {
+ return;
+ }
+ if (MmioRead32 (Context->MmioAddress + R_IC_TX_ABRT_SOURCE) & B_IC_TX_ABRT_7B_ADDR_NACK) {
+ Context->TransferStatus = EFI_NO_RESPONSE;
+ } else {
+ Context->TransferStatus = EFI_DEVICE_ERROR;
+ }
+ DEBUG (( DEBUG_INFO, "I2c CheckErrors: %08x\n", MmioRead32 (Context->MmioAddress + R_IC_TX_ABRT_SOURCE)));
+}
+
+/**
+ Transfer is finished when all requested operations were placed in fifo,
+ all read requests were filled and hardware is inactive
+ The last part is necessary for write-only transfers where after
+ placing all writes in fifo sw needs to wait until they flush down the bus
+
+ @param[in] Context - driver context
+
+ @retval Boolean
+**/
+BOOLEAN
+IsTransferFinished (
+ I2C_MASTER_CONTEXT *Context
+ )
+{
+ if (( Context->WriteOp >= Context->Request->OperationCount ) &&
+ ( Context->ReadOp >= Context->Request->OperationCount ) &&
+ !IsHardwareActive (Context)) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+/*
+ Clean up Hw activity and errors
+ Return status to Request's submitter and signal the event that tells
+ it that the request is complete
+ Clear up Sw context to allow new request to start
+
+ @param[in] Context - driver context
+*/
+VOID
+FinishTransfer (
+ I2C_MASTER_CONTEXT *Context
+ )
+{
+ UINT32 Attempts = 10000;
+
+ MmioWrite32 ( Context->MmioAddress + R_IC_ENABLE, 0 );
+
+ while ( MmioRead32 ( Context->MmioAddress + R_IC_ENABLE_STATUS ) & B_IC_EN ) {
+ //try for 1ms; should take no more than 100us even at slowest bus speed, but just to make sure BIOS doesn't hang in infinite loop
+ MicroSecondDelay ( 1 );
+ if (--Attempts == 0) {
+ ASSERT (FALSE);
+ break;
+ }
+ }
+
+ //
+ //clear errors
+ //
+ MmioRead32 (Context->MmioAddress + R_IC_CLR_TX_ABRT);
+ MmioRead32 (Context->MmioAddress + R_IC_CLR_INTR);
+
+ //
+ //clean up context data
+ //
+ Context->TransferInProgress = FALSE;
+}
+
+/**
+ PerformTransfer. For synchronous transfer this function is called in a loop
+ and for asynchronous transfers, as a timer callback. It writes data and/or
+ read requests to hadrware, copies read data to destination buffers. When
+ transfer completes, it cleans up Sw context and Hw registers in preparation
+ for new transfer
+
+ @param[in] Context - driver context
+**/
+VOID
+PerformTransfer (
+ IN I2C_MASTER_CONTEXT *Context
+ )
+{
+ if (!Context->TransferInProgress) {
+ return;
+ }
+ if (EFI_ERROR (Context->TransferStatus) || IsTransferFinished (Context)) {
+ FinishTransfer (Context);
+ return;
+ }
+ WriteFifo (Context);
+ ReadFifo (Context);
+ CheckErrors (Context);
+}
+
+
+/**
+ Set the I2C controller bus clock frequency.
+
+ This routine must be called at or below TPL_NOTIFY.
+
+ The software and controller do a best case effort of using the specified
+ frequency for the I2C bus. If the frequency does not match exactly then
+ the controller will use lower frequency for the I2C to avoid exceeding
+ the operating conditions for any of the I2C devices on the bus.
+ For example if 400 KHz was specified and the controller's divide network
+ only supports 402 KHz or 398 KHz then the controller would be set to 398
+ KHz.
+
+ @param[in] MmioAddress Address of I2C controller
+ @param[in] BusClockHertz New I2C bus clock frequency in Hertz
+
+ @retval EFI_SUCCESS The bus frequency was set successfully.
+ @retval EFI_UNSUPPORTED The controller does not support this frequency.
+**/
+
+EFI_STATUS
+FrequencySet (
+ IN UINTN MmioAddress,
+ IN OUT UINTN *BusClockHertz
+ )
+{
+ UINT32 Speed;
+
+ if ( *BusClockHertz < 100*1000) {
+ //can't run that slowly
+ return EFI_UNSUPPORTED;
+ } else if ( *BusClockHertz < 400*1000) {
+ //for any request in range [100kHz, 400kHz), set 100kHz
+ *BusClockHertz = 100000;
+ Speed = V_IC_SPEED_STANDARD;
+ MmioWrite32 ( MmioAddress + R_IC_SDA_HOLD, 0x001C001C);
+ MmioWrite32 ( MmioAddress + R_IC_SS_SCL_HCNT, 528);
+ MmioWrite32 ( MmioAddress + R_IC_SS_SCL_LCNT, 640);
+ } else if ( *BusClockHertz < 1000*1000) {
+ //for any request in range [400kHz, 1MHz), set 400kHz
+ *BusClockHertz = 400000;
+ Speed = V_IC_SPEED_FAST;
+ MmioWrite32 ( MmioAddress + R_IC_SDA_HOLD, 0x001C001C);
+ MmioWrite32 ( MmioAddress + R_IC_FS_SCL_HCNT, 128);
+ MmioWrite32 ( MmioAddress + R_IC_FS_SCL_LCNT, 160);
+ } else {
+ //for any request in range [1MHz, +inf), set 1MHz. This silicon doesn't support 3.4MHz mode.
+ *BusClockHertz = 1000000;
+ Speed = V_IC_SPEED_FAST;
+ MmioWrite32 ( MmioAddress + R_IC_SDA_HOLD, 0x00280028);
+ MmioWrite32 ( MmioAddress + R_IC_FS_SCL_HCNT, 30);
+ MmioWrite32 ( MmioAddress + R_IC_FS_SCL_LCNT, 80);
+ }
+
+ MmioWrite32 ( MmioAddress + R_IC_CON, Speed | B_IC_RESTART_EN | B_IC_SLAVE_DISABLE | B_IC_MASTER_MODE);
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Reset the I2C controller
+
+ @param[in] MmioAddress Address of I2C controller
+
+ @retval Status
+**/
+EFI_STATUS
+I2cReset (
+ IN UINTN MmioAddress
+ )
+{
+ MmioAnd32 (
+ MmioAddress + R_PCH_SERIAL_IO_PPR_RESETS,
+ (UINT32) ~(B_PCH_SERIAL_IO_PPR_RESETS_FUNC | B_PCH_SERIAL_IO_PPR_RESETS_APB | B_PCH_SERIAL_IO_PPR_RESETS_IDMA)
+ );
+ MmioRead32 (MmioAddress + R_PCH_SERIAL_IO_PPR_RESETS);
+ MmioOr32 (
+ MmioAddress + R_PCH_SERIAL_IO_PPR_RESETS,
+ B_PCH_SERIAL_IO_PPR_RESETS_FUNC | B_PCH_SERIAL_IO_PPR_RESETS_APB | B_PCH_SERIAL_IO_PPR_RESETS_IDMA
+ );
+ MmioRead32 (MmioAddress + R_PCH_SERIAL_IO_PPR_RESETS);
+
+ return EFI_SUCCESS;
+}
+
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeI2cMasterCommonLib/PeiDxeI2cMasterCommonLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeI2cMasterCommonLib/PeiDxeI2cMasterCommonLib.inf
new file mode 100644
index 0000000000..a6af85a4a0
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeI2cMasterCommonLib/PeiDxeI2cMasterCommonLib.inf
@@ -0,0 +1,44 @@
+## @file
+# Component description file for the I2C port driver.
+#
+# Copyright (c) 2017, 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 = PeiDxeI2cMasterCommonLib
+FILE_GUID = D0E4E669-D467-42af-93D8-21513E226EEA
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = I2cMasterCommonLib
+
+
+[LibraryClasses]
+DebugLib
+PchSerialIoLib
+MmPciLib
+IoLib
+PciLib
+MmPciLib
+TimerLib
+PchInfoLib
+
+
+[Packages]
+KabylakeSiliconPkg/SiPkg.dec
+KabylakeSiliconPkg/KabylakeSiliconPrivate.dec
+MdePkg/MdePkg.dec
+
+
+[Sources]
+I2cMasterCommonLib.c
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmGpioPrivateLib/GpioNativePrivateLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmGpioPrivateLib/GpioNativePrivateLib.c
new file mode 100644
index 0000000000..89bf0a73ee
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmGpioPrivateLib/GpioNativePrivateLib.c
@@ -0,0 +1,305 @@
+/** @file
+ This file contains routines for GPIO native and chipset specific purpose
+ used by Reference Code only.
+
+Copyright (c) 2017, 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/BaseMemoryLib.h>
+#include <PchAccess.h>
+#include <Library/GpioLib.h>
+#include <Library/GpioNativeLib.h>
+#include <Library/GpioPrivateLib.h>
+#include <Library/PchInfoLib.h>
+#include <Pch/Library/PeiDxeSmmGpioLib/GpioLibrary.h>
+
+//
+// Chipset specific data
+//
+//ISH
+extern GPIO_PAD_NATIVE_FUNCTION mPchLpIshGPGpio[PCH_ISH_MAX_GP_PINS];
+extern GPIO_PAD_NATIVE_FUNCTION mPchHIshGPGpio[PCH_ISH_MAX_GP_PINS];
+extern GPIO_PAD_NATIVE_FUNCTION mPchLpIshI2cGpio[PCH_ISH_MAX_I2C_CONTROLLERS][PCH_ISH_PINS_PER_I2C_CONTROLLER];
+extern GPIO_PAD_NATIVE_FUNCTION mPchHIshI2cGpio[PCH_ISH_MAX_I2C_CONTROLLERS][PCH_ISH_PINS_PER_I2C_CONTROLLER];
+extern GPIO_PAD_NATIVE_FUNCTION mPchLpIshUartGpio[PCH_ISH_MAX_UART_CONTROLLERS][PCH_ISH_PINS_PER_UART_CONTROLLER];
+extern GPIO_PAD_NATIVE_FUNCTION mPchHIshUartGpio[PCH_ISH_MAX_UART_CONTROLLERS][PCH_ISH_PINS_PER_UART_CONTROLLER];
+extern GPIO_PAD_NATIVE_FUNCTION mPchLpIshSpiGpio[PCH_ISH_PINS_PER_SPI_CONTROLLER];
+extern GPIO_PAD_NATIVE_FUNCTION mPchHIshSpiGpio[PCH_ISH_PINS_PER_SPI_CONTROLLER];
+
+
+//PCIe SRCCLKREQB
+extern GPIO_PAD_NATIVE_FUNCTION mPchLpPcieSrcClkReqbPinToGpioMap[PCH_LP_PCIE_MAX_CLK_REQ];
+extern GPIO_PAD_NATIVE_FUNCTION mPchHPcieSrcClkReqbPinToGpioMap[PCH_H_PCIE_MAX_CLK_REQ];
+
+//PCH_HOT
+extern GPIO_PAD_NATIVE_FUNCTION mPchLpPchHotbPin;
+extern GPIO_PAD_NATIVE_FUNCTION mPchHPchHotbPin;
+
+//CPU GP
+extern GPIO_PAD_NATIVE_FUNCTION mPchLpCpuGpPinMap[4];
+extern GPIO_PAD_NATIVE_FUNCTION mPchHCpuGpPinMap[4];
+
+/**
+ This function sets ISH I2C controller pins into native mode
+
+ @param[in] IshI2cControllerNumber I2C controller
+
+ @retval Status
+**/
+EFI_STATUS
+GpioSetIshI2cPinsIntoNativeMode (
+ IN UINT32 IshI2cControllerNumber
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ GPIO_PAD_NATIVE_FUNCTION (*I2cGpio) [PCH_ISH_PINS_PER_I2C_CONTROLLER];
+
+ Status = EFI_SUCCESS;
+
+ if (GetPchSeries () == PchLp) {
+ I2cGpio = mPchLpIshI2cGpio;
+ } else {
+ I2cGpio = mPchHIshI2cGpio;
+ }
+
+ ASSERT (IshI2cControllerNumber < PCH_ISH_MAX_I2C_CONTROLLERS);
+
+ for (Index = 0; Index < PCH_ISH_PINS_PER_I2C_CONTROLLER; Index++) {
+ Status = SetGpioPadMode (I2cGpio[IshI2cControllerNumber][Index].Pad, I2cGpio[IshI2cControllerNumber][Index].Mode);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+ }
+ return Status;
+}
+
+/**
+ This function sets ISH UART controller pins into native mode
+
+ @param[in] IshUartControllerNumber UART controller
+
+ @retval Status
+**/
+EFI_STATUS
+GpioSetIshUartPinsIntoNativeMode (
+ IN UINT32 IshUartControllerNumber
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ GPIO_PAD_NATIVE_FUNCTION (*UartGpio) [PCH_ISH_PINS_PER_UART_CONTROLLER];
+
+ Status = EFI_SUCCESS;
+
+ if (GetPchSeries () == PchLp) {
+ UartGpio = mPchLpIshUartGpio;
+ } else {
+ UartGpio = mPchHIshUartGpio;
+ }
+
+ ASSERT (IshUartControllerNumber < PCH_ISH_MAX_UART_CONTROLLERS);
+
+ for (Index = 0; Index < PCH_ISH_PINS_PER_UART_CONTROLLER; Index++) {
+ Status = SetGpioPadMode (UartGpio[IshUartControllerNumber][Index].Pad, UartGpio[IshUartControllerNumber][Index].Mode);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+ }
+ return Status;
+}
+
+/**
+ This function sets ISH SPI controller pins into native mode
+
+ @param[in] none
+
+ @retval Status
+**/
+EFI_STATUS
+GpioSetIshSpiPinsIntoNativeMode (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ GPIO_PAD_NATIVE_FUNCTION *SpiGpio;
+
+ Status = EFI_SUCCESS;
+
+ if (GetPchSeries () == PchLp) {
+ SpiGpio = mPchLpIshSpiGpio;
+ } else {
+ SpiGpio = mPchHIshSpiGpio;
+ }
+
+ for (Index = 0; Index < PCH_ISH_PINS_PER_SPI_CONTROLLER; Index++) {
+ Status = SetGpioPadMode (SpiGpio[Index].Pad, SpiGpio[Index].Mode);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+ }
+ return Status;
+}
+
+/**
+ This function sets ISH GP pins into native mode
+
+ @param[in] IshGpPinNumber ISH GP pin number
+
+ @retval Status
+**/
+EFI_STATUS
+GpioSetIshGpPinsIntoNativeMode (
+ IN UINT32 IshGpPinNumber
+ )
+{
+ EFI_STATUS Status;
+ GPIO_PAD_NATIVE_FUNCTION *IshGp;
+
+ Status = EFI_SUCCESS;
+
+ if (GetPchSeries () == PchLp) {
+ IshGp = mPchLpIshGPGpio;
+ } else {
+ IshGp = mPchHIshGPGpio;
+ }
+ ASSERT (IshGpPinNumber < PCH_ISH_MAX_GP_PINS);
+
+ Status = SetGpioPadMode (IshGp[IshGpPinNumber].Pad, IshGp[IshGpPinNumber].Mode);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ return Status;
+}
+
+/**
+ Returns a pad for given CLKREQ# index.
+
+ @param[in] ClkreqIndex CLKREQ# number
+
+ @return CLKREQ# pad.
+**/
+GPIO_PAD
+GpioGetClkreqPad (
+ IN UINT32 ClkreqIndex
+ )
+{
+ if (GetPchSeries () == PchLp) {
+ ASSERT (ClkreqIndex < PCH_LP_PCIE_MAX_CLK_REQ);
+ return mPchLpPcieSrcClkReqbPinToGpioMap[ClkreqIndex].Pad;
+ } else {
+ ASSERT (ClkreqIndex < PCH_H_PCIE_MAX_CLK_REQ);
+ return mPchHPcieSrcClkReqbPinToGpioMap[ClkreqIndex].Pad;
+ }
+}
+
+/**
+ Enables CLKREQ# pad in native mode.
+
+ @param[in] ClkreqIndex CLKREQ# number
+
+ @return none
+**/
+VOID
+GpioEnableClkreq (
+ IN UINT32 ClkreqIndex
+ )
+{
+ GPIO_CONFIG PadConfig;
+ GPIO_PAD ClkreqPad;
+ GPIO_PAD_MODE PadMode;
+
+ ZeroMem (&PadConfig, sizeof (PadConfig));
+
+ if (GetPchSeries () == PchLp) {
+ ASSERT (ClkreqIndex < PCH_LP_PCIE_MAX_CLK_REQ);
+ ClkreqPad = mPchLpPcieSrcClkReqbPinToGpioMap[ClkreqIndex].Pad;
+ PadMode = mPchLpPcieSrcClkReqbPinToGpioMap[ClkreqIndex].Mode;
+ } else {
+ ASSERT (ClkreqIndex < PCH_H_PCIE_MAX_CLK_REQ);
+ ClkreqPad = mPchHPcieSrcClkReqbPinToGpioMap[ClkreqIndex].Pad;
+ PadMode = mPchHPcieSrcClkReqbPinToGpioMap[ClkreqIndex].Mode;
+ }
+
+ PadConfig.PadMode = PadMode;
+ PadConfig.Direction = GpioDirNone;
+ PadConfig.PowerConfig = GpioHostDeepReset;
+ DEBUG ((DEBUG_INFO, "Enabling CLKREQ%d\n", ClkreqIndex));
+ GpioSetPadConfig (ClkreqPad, &PadConfig);
+}
+
+/**
+ This function checks if GPIO pin for PCHHOTB is in NATIVE MODE
+
+ @param[in] none
+
+ @retval TRUE Pin is in PCHHOTB native mode
+ FALSE Pin is in gpio mode or is not owned by HOST
+**/
+BOOLEAN
+GpioIsPchHotbPinInNativeMode (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ GPIO_PAD_NATIVE_FUNCTION PchHotbPin;
+ GPIO_PAD_MODE GpioMode;
+
+
+ if (GetPchSeries () == PchLp) {
+ PchHotbPin = mPchLpPchHotbPin;
+ } else {
+ PchHotbPin = mPchHPchHotbPin;
+ }
+
+ Status = GetGpioPadMode (PchHotbPin.Pad, &GpioMode);
+
+ if ((EFI_ERROR (Status)) || (GpioMode != PchHotbPin.Mode)) {
+ return FALSE;
+ } else {
+ return TRUE;
+ }
+}
+
+/**
+ This function sets CPU GP pins into native mode
+
+ @param[in] CpuGpPinNum CPU GP pin number
+
+ @retval Status
+**/
+EFI_STATUS
+GpioSetCpuGpPinsIntoNativeMode (
+ IN UINT32 CpuGpPinNum
+ )
+{
+ EFI_STATUS Status;
+ GPIO_PAD_NATIVE_FUNCTION *CpuGpPins;
+
+ if (GetPchSeries () == PchLp) {
+ CpuGpPins = mPchLpCpuGpPinMap;
+ } else {
+ CpuGpPins = mPchHCpuGpPinMap;
+ }
+
+ ASSERT (CpuGpPinNum < 4);
+
+ Status = SetGpioPadMode (CpuGpPins[CpuGpPinNum].Pad, CpuGpPins[CpuGpPinNum].Mode);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+ return EFI_SUCCESS;
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmGpioPrivateLib/GpioPrivateLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmGpioPrivateLib/GpioPrivateLib.c
new file mode 100644
index 0000000000..b386e071f7
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmGpioPrivateLib/GpioPrivateLib.c
@@ -0,0 +1,318 @@
+/** @file
+ This file contains GPIO routines for RC usage
+
+Copyright (c) 2017, 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/BaseMemoryLib.h>
+#include <PchAccess.h>
+#include <Library/GpioLib.h>
+#include <Library/GpioNativeLib.h>
+#include <Library/GpioPrivateLib.h>
+#include <Library/PchCycleDecodingLib.h>
+#include <Pch/Library/PeiDxeSmmGpioLib/GpioLibrary.h>
+/**
+ This procedure will get value of selected gpio register
+
+ @param[in] Group GPIO group number
+ @param[in] Offset GPIO register offset
+ @param[out] RegVal Value of gpio register
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioGetReg (
+ IN GPIO_GROUP Group,
+ IN UINT32 Offset,
+ OUT UINT32 *RegVal
+ )
+{
+ GPIO_GROUP_INFO *GpioGroupInfo;
+ UINTN GpioGroupInfoLength;
+ UINTN GroupIndex;
+
+ GroupIndex = GpioGetGroupIndexFromGroup (Group);
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+ //
+ // Check if group argument exceeds GPIO GROUP INFO array
+ //
+ if ((UINTN) GroupIndex >= GpioGroupInfoLength) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *RegVal = MmioRead32 (PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, Offset));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will set value of selected gpio register
+
+ @param[in] Group GPIO group number
+ @param[in] Offset GPIO register offset
+ @param[in] RegVal Value of gpio register
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioSetReg (
+ IN GPIO_GROUP Group,
+ IN UINT32 Offset,
+ IN UINT32 RegVal
+ )
+{
+ GPIO_GROUP_INFO *GpioGroupInfo;
+ UINTN GpioGroupInfoLength;
+ UINTN GroupIndex;
+
+ GroupIndex = GpioGetGroupIndexFromGroup (Group);
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+ //
+ // Check if group argument exceeds GPIO GROUP INFO array
+ //
+ if ((UINTN) GroupIndex >= GpioGroupInfoLength) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ MmioWrite32 (PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, Offset), RegVal);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure is used by PchSmiDispatcher and will return information
+ needed to register GPI SMI. Relation between Index and GpioPad number is:
+ Index = GpioGroup + 24 * GpioPad
+
+ @param[in] Index GPI SMI number
+ @param[out] GpioPin GPIO pin
+ @param[out] GpiSmiBitOffset GPI SMI bit position within GpiSmi Registers
+ @param[out] GpiSmiEnRegAddress Address of GPI SMI Enable register
+ @param[out] GpiSmiStsRegAddress Address of GPI SMI status register
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioGetPadAndSmiRegs (
+ IN UINT32 Index,
+ OUT GPIO_PAD *GpioPin,
+ OUT UINT8 *GpiSmiBitOffset,
+ OUT UINT32 *GpiSmiEnRegAddress,
+ OUT UINT32 *GpiSmiStsRegAddress
+ )
+{
+ UINT32 GroupIndex;
+ UINT32 PadNumber;
+ GPIO_GROUP_INFO *GpioGroupInfo;
+ GPIO_GROUP GpioGroupOffset;
+ UINTN GpioGroupInfoLength;
+ UINT32 SmiRegOffset;
+
+ GPIO_PAD_OWN PadOwnVal;
+ UINT32 HostOwnVal;
+
+
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+
+ GpioGroupOffset = GpioGetLowestGroup ();
+
+ PadNumber = 0;
+ GroupIndex = 0;
+ for (GroupIndex = 0; GroupIndex < GpioGroupInfoLength; GroupIndex++) {
+ PadNumber = Index;
+ if (PadNumber < GpioGroupInfo[GroupIndex].PadPerGroup) {
+ //
+ // Found group and pad number
+ //
+ break;
+ }
+ Index = Index - GpioGroupInfo[GroupIndex].PadPerGroup;
+ }
+
+ //
+ // Check if legal pad number
+ //
+ if (PadNumber >= GpioGroupInfo[GroupIndex].PadPerGroup){
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check if selected group has GPI SMI Enable and Status registers
+ //
+ if (GpioGroupInfo[GroupIndex].SmiEnOffset == NO_REGISTER_FOR_PROPERTY) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ DEBUG_CODE_BEGIN ();
+ //
+ // Check if selected GPIO Pad is not owned by CSME/ISH/IE
+ //
+ GpioGetPadOwnership (GpioGetGpioPadFromGroupAndPadNumber (GroupIndex + GpioGroupOffset, PadNumber), &PadOwnVal);
+ if (PadOwnVal != GpioPadOwnHost) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Accessing pad not owned by host (Group=%d, Pad=%d)!\n",GroupIndex, PadNumber));
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Check if Host Software Pad Ownership is set to ACPI Mode
+ //
+ GpioGetHostSwOwnershipForPad (GpioGetGpioPadFromGroupAndPadNumber (GroupIndex + GpioGroupOffset, PadNumber), &HostOwnVal);
+ if (HostOwnVal != V_PCH_PCR_GPIO_HOSTSW_OWN_ACPI) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ DEBUG_CODE_END ();
+
+ *GpioPin = GpioGetGpioPadFromGroupAndPadNumber (GroupIndex + GpioGroupOffset, PadNumber);
+ *GpiSmiBitOffset = (UINT8)(PadNumber % 32);
+
+ SmiRegOffset = GpioGroupInfo[GroupIndex].SmiEnOffset + (PadNumber / 32) * 0x4;
+ *GpiSmiEnRegAddress = PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, SmiRegOffset);
+
+ SmiRegOffset = GpioGroupInfo[GroupIndex].SmiStsOffset + (PadNumber / 32) * 0x4;
+ *GpiSmiStsRegAddress = PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, SmiRegOffset);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will clear GPIO_UNLOCK_SMI_STS
+
+ @param[in] None
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioClearUnlockSmiSts (
+ VOID
+ )
+{
+ UINT16 AcpiBaseAddr;
+
+ PchAcpiBaseGet (&AcpiBaseAddr);
+
+ //
+ // GPIO_UNLOCK_SMI_STS is cleared by writing 1 to it. Other bits in
+ // R_PCH_SMI_STS registers are either RO or RW/1C so writing 0 to them
+ // will not change their state.
+ //
+ IoWrite32 (AcpiBaseAddr + R_PCH_SMI_STS, B_PCH_SMI_STS_GPIO_UNLOCK);
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This procedure will set GPIO Driver IRQ number
+
+ @param[in] Irq Irq number
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid IRQ number
+**/
+EFI_STATUS
+GpioSetIrq (
+ IN UINT8 Irq
+ )
+{
+ UINT32 Data32And;
+ UINT32 Data32Or;
+
+ //
+ // Check if Irq is 14 or 15
+ //
+ if ((Irq < 14) || (Irq > 15)) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Data32And = (UINT32) ~(B_PCH_PCR_GPIO_MISCCFG_IRQ_ROUTE);
+ Data32Or = (UINT32) (Irq - 14) << N_PCH_PCR_GPIO_MISCCFG_IRQ_ROUTE;
+
+ //
+ // Program MISCCFG register for Community 0
+ //
+ MmioAndThenOr32 (
+ PCH_PCR_ADDRESS (PID_GPIOCOM0, R_PCH_PCR_GPIO_MISCCFG),
+ Data32And,
+ Data32Or
+ );
+
+ //
+ // Program MISCCFG register for Community 1
+ //
+ MmioAndThenOr32 (
+ PCH_PCR_ADDRESS (PID_GPIOCOM1, R_PCH_PCR_GPIO_MISCCFG),
+ Data32And,
+ Data32Or
+ );
+
+ //
+ // Program MISCCFG register for Community 2
+ //
+ MmioAndThenOr32 (
+ PCH_PCR_ADDRESS (PID_GPIOCOM2, R_PCH_PCR_GPIO_MISCCFG),
+ Data32And,
+ Data32Or
+ );
+
+ //
+ // Program MISCCFG register for Community 3
+ //
+ MmioAndThenOr32 (
+ PCH_PCR_ADDRESS (PID_GPIOCOM3, R_PCH_PCR_GPIO_MISCCFG),
+ Data32And,
+ Data32Or
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will perform special handling of GPP_A_12 on PCH-LP.
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+GpioA12SpecialHandling (
+ VOID
+ )
+{
+ GPIO_PAD_OWN PadOwnVal;
+
+ //
+ // SKL PCH BWG 16.6. PCH-LP GPP_A_12 Special Handling
+ //
+ if (GetPchSeries () == PchLp) {
+ GpioGetPadOwnership (GPIO_SKL_LP_GPP_A12, &PadOwnVal);
+
+ //
+ // If the pad is host-own, BIOS has to always lock this pad after being initialized
+ //
+ if (PadOwnVal == GpioPadOwnHost) {
+ //
+ // Set PadCfgLock for GPP_A_12
+ //
+ GpioLockPadCfg (GPIO_SKL_LP_GPP_A12);
+ }
+ }
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmGpioPrivateLib/PchSklGpioPrivateData.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmGpioPrivateLib/PchSklGpioPrivateData.c
new file mode 100644
index 0000000000..3d8b128a1c
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmGpioPrivateLib/PchSklGpioPrivateData.c
@@ -0,0 +1,200 @@
+/** @file
+ This file contains SKL specific GPIO information
+
+Copyright (c) 2017, 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/BaseMemoryLib.h>
+#include <PchAccess.h>
+#include <Library/GpioLib.h>
+#include <Library/GpioNativeLib.h>
+#include <Library/GpioPrivateLib.h>
+#include <Pch/Library/PeiDxeSmmGpioLib/GpioLibrary.h>
+
+//
+// ISH GP pin
+//
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpIshGPGpio[PCH_ISH_MAX_GP_PINS] =
+{
+ {GPIO_SKL_LP_GPP_A18, GpioPadModeNative1},// ISH_GP_0
+ {GPIO_SKL_LP_GPP_A19, GpioPadModeNative1},// ISH_GP_1
+ {GPIO_SKL_LP_GPP_A20, GpioPadModeNative1},// ISH_GP_2
+ {GPIO_SKL_LP_GPP_A21, GpioPadModeNative1},// ISH_GP_3
+ {GPIO_SKL_LP_GPP_A22, GpioPadModeNative1},// ISH_GP_4
+ {GPIO_SKL_LP_GPP_A23, GpioPadModeNative1},// ISH_GP_5
+ {GPIO_SKL_LP_GPP_A12, GpioPadModeNative2},// ISH_GP_6
+ {GPIO_SKL_LP_GPP_A17, GpioPadModeNative2} // ISH_GP_7
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHIshGPGpio[PCH_ISH_MAX_GP_PINS] =
+{
+ {GPIO_SKL_H_GPP_A18, GpioPadModeNative1},// ISH_GP_0
+ {GPIO_SKL_H_GPP_A19, GpioPadModeNative1},// ISH_GP_1
+ {GPIO_SKL_H_GPP_A20, GpioPadModeNative1},// ISH_GP_2
+ {GPIO_SKL_H_GPP_A21, GpioPadModeNative1},// ISH_GP_3
+ {GPIO_SKL_H_GPP_A22, GpioPadModeNative1},// ISH_GP_4
+ {GPIO_SKL_H_GPP_A23, GpioPadModeNative1},// ISH_GP_5
+ {GPIO_SKL_H_GPP_A12, GpioPadModeNative2},// ISH_GP_6
+ {GPIO_SKL_H_GPP_A17, GpioPadModeNative1} // ISH_GP_7
+};
+//
+// ISH UART controller pins
+// ISH UART[controller number][pin: RXD/TXD/RTSB/CTSB]
+//
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpIshUartGpio[PCH_ISH_MAX_UART_CONTROLLERS][PCH_ISH_PINS_PER_UART_CONTROLLER] =
+{
+ { //UART0
+ {GPIO_SKL_LP_GPP_D13, GpioPadModeNative1},// ISH_UART0_RXD
+ {GPIO_SKL_LP_GPP_D14, GpioPadModeNative1},// ISH_UART0_TXD
+ {GPIO_SKL_LP_GPP_D15, GpioPadModeNative1},// ISH_UART0_RTS
+ {GPIO_SKL_LP_GPP_D16, GpioPadModeNative1} // ISH_UART0_CTS
+ },
+ { //UART1
+ {GPIO_SKL_LP_GPP_C12, GpioPadModeNative2},// ISH_UART1_RXD
+ {GPIO_SKL_LP_GPP_C13, GpioPadModeNative2},// ISH_UART1_TXD
+ {GPIO_SKL_LP_GPP_C14, GpioPadModeNative2},// ISH_UART1_RTSB
+ {GPIO_SKL_LP_GPP_C15, GpioPadModeNative2} // ISH_UART1_CTSB
+ }
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHIshUartGpio[PCH_ISH_MAX_UART_CONTROLLERS][PCH_ISH_PINS_PER_UART_CONTROLLER] =
+{
+ { //UART0
+ {GPIO_SKL_H_GPP_D13, GpioPadModeNative1},// ISH_UART0_RXD
+ {GPIO_SKL_H_GPP_D14, GpioPadModeNative1},// ISH_UART0_TXD
+ {GPIO_SKL_H_GPP_D15, GpioPadModeNative1},// ISH_UART0_RTS
+ {GPIO_SKL_H_GPP_D16, GpioPadModeNative1} // ISH_UART0_CTS
+ },
+ { //UART1
+ {GPIO_SKL_H_GPP_C12, GpioPadModeNative2},// ISH_UART1_RXD
+ {GPIO_SKL_H_GPP_C13, GpioPadModeNative2},// ISH_UART1_TXD
+ {GPIO_SKL_H_GPP_C14, GpioPadModeNative2},// ISH_UART1_RTS
+ {GPIO_SKL_H_GPP_C15, GpioPadModeNative2} // ISH_UART1_CTS
+ }
+};
+
+//
+// ISH I2C controller pins
+// ISH I2C[controller number][pin: SDA/SCL]
+//
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpIshI2cGpio[PCH_ISH_MAX_I2C_CONTROLLERS][PCH_ISH_PINS_PER_I2C_CONTROLLER] =
+{
+ { //I2C0
+ {GPIO_SKL_LP_GPP_D5, GpioPadModeNative1},// ISH_I2C0_SDA
+ {GPIO_SKL_LP_GPP_D6, GpioPadModeNative1} // ISH_I2C0_SCL
+ },
+ { //I2C1
+ {GPIO_SKL_LP_GPP_D7, GpioPadModeNative1},// ISH_I2C1_SDA
+ {GPIO_SKL_LP_GPP_D8, GpioPadModeNative1} // ISH_I2C1_SCL
+ },
+ { //I2C2
+ {GPIO_SKL_LP_GPP_F10, GpioPadModeNative2},// ISH_I2C2_SDA
+ {GPIO_SKL_LP_GPP_F11, GpioPadModeNative2} // ISH_I2C2_SCL
+ }
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHIshI2cGpio[PCH_ISH_MAX_I2C_CONTROLLERS][PCH_ISH_PINS_PER_I2C_CONTROLLER] =
+{
+ { //I2C0
+ {GPIO_SKL_H_GPP_H19, GpioPadModeNative1},// ISH_I2C0_SDA
+ {GPIO_SKL_H_GPP_H20, GpioPadModeNative1} // ISH_I2C0_SCL
+ },
+ { //I2C1
+ {GPIO_SKL_H_GPP_H21, GpioPadModeNative1},// ISH_I2C1_SDA
+ {GPIO_SKL_H_GPP_H22, GpioPadModeNative1} // ISH_I2C1_SCL
+ },
+ { //I2C2
+ {GPIO_SKL_H_GPP_D4, GpioPadModeNative1},// ISH_I2C2_SDA
+ {GPIO_SKL_H_GPP_D23, GpioPadModeNative1} // ISH_I2C2_SCL
+ }
+};
+
+//
+// ISH SPI controller pins
+// ISH SPI[pin: CSB/CLK/MISO/MOSI]
+//
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpIshSpiGpio[PCH_ISH_PINS_PER_SPI_CONTROLLER] =
+{
+ {GPIO_SKL_LP_GPP_D9, GpioPadModeNative1},// ISH_SPI_CSB
+ {GPIO_SKL_LP_GPP_D10, GpioPadModeNative1},// ISH_SPI_CLK
+ {GPIO_SKL_LP_GPP_D11, GpioPadModeNative1},// ISH_SPI_MISO
+ {GPIO_SKL_LP_GPP_D12, GpioPadModeNative1} // ISH_SPI_MOSI
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHIshSpiGpio[PCH_ISH_PINS_PER_SPI_CONTROLLER] =
+{
+ {GPIO_SKL_H_GPP_D9, GpioPadModeNative1},// ISH_SPI_CSB
+ {GPIO_SKL_H_GPP_D10, GpioPadModeNative1},// ISH_SPI_CLK
+ {GPIO_SKL_H_GPP_D11, GpioPadModeNative1},// ISH_SPI_MISO
+ {GPIO_SKL_H_GPP_D12, GpioPadModeNative1} // ISH_SPI_MOSI
+};
+
+//
+// GPIO pin for PCIE SCRCLKREQB
+// SCRCLKREQB_x -> GPIO pin y
+//
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpPcieSrcClkReqbPinToGpioMap[PCH_LP_PCIE_MAX_CLK_REQ] =
+{
+ {GPIO_SKL_LP_GPP_B5, GpioPadModeNative1},
+ {GPIO_SKL_LP_GPP_B6, GpioPadModeNative1},
+ {GPIO_SKL_LP_GPP_B7, GpioPadModeNative1},
+ {GPIO_SKL_LP_GPP_B8, GpioPadModeNative1},
+ {GPIO_SKL_LP_GPP_B9, GpioPadModeNative1},
+ {GPIO_SKL_LP_GPP_B10, GpioPadModeNative1}
+};
+
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHPcieSrcClkReqbPinToGpioMap[PCH_H_PCIE_MAX_CLK_REQ] =
+{
+ {GPIO_SKL_H_GPP_B5, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_B6, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_B7, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_B8, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_B9, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_B10, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_H0, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_H1, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_H2, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_H3, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_H4, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_H5, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_H6, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_H7, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_H8, GpioPadModeNative1},
+ {GPIO_SKL_H_GPP_H9, GpioPadModeNative1}
+};
+
+//
+// PCHHOTB pin
+//
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpPchHotbPin = {GPIO_SKL_LP_GPP_B23, GpioPadModeNative2};
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHPchHotbPin = {GPIO_SKL_H_GPP_B23, GpioPadModeNative2};
+
+//
+// CPU GP pins
+//
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchLpCpuGpPinMap[4] =
+{
+ {GPIO_SKL_LP_GPP_E3, GpioPadModeNative1}, // CPU_GP_0
+ {GPIO_SKL_LP_GPP_E7, GpioPadModeNative1}, // CPU_GP_1
+ {GPIO_SKL_LP_GPP_B3, GpioPadModeNative1}, // CPU_GP_2
+ {GPIO_SKL_LP_GPP_B4, GpioPadModeNative1}, // CPU_GP_3
+};
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_PAD_NATIVE_FUNCTION mPchHCpuGpPinMap[4] =
+{
+ {GPIO_SKL_H_GPP_E3, GpioPadModeNative1}, // CPU_GP_0
+ {GPIO_SKL_H_GPP_E7, GpioPadModeNative1}, // CPU_GP_1
+ {GPIO_SKL_H_GPP_B3, GpioPadModeNative1}, // CPU_GP_2
+ {GPIO_SKL_H_GPP_B4, GpioPadModeNative1}, // CPU_GP_3
+};
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmGpioPrivateLib/PeiDxeSmmGpioPrivateLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmGpioPrivateLib/PeiDxeSmmGpioPrivateLib.inf
new file mode 100644
index 0000000000..d2542a1673
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmGpioPrivateLib/PeiDxeSmmGpioPrivateLib.inf
@@ -0,0 +1,49 @@
+## @file
+# Component description file for the PeiDxeSmmGpioPrivateLib
+#
+# Copyright (c) 2017, 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 = PeiDxeSmmGpioPrivateLib
+FILE_GUID = E078A734-BEA0-47CF-A476-3742316D01FC
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = GpioPrivateLib
+#
+# 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
+ PchInfoLib
+ GpioLib
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ KabylakeSiliconPkg/SiPkg.dec
+ KabylakeSiliconPkg/KabylakeSiliconPrivate.dec
+
+
+[Sources]
+ GpioPrivateLib.c
+ GpioNativePrivateLib.c
+ PchSklGpioPrivateData.c
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchInitCommonLib/PchInitCommon.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchInitCommonLib/PchInitCommon.c
new file mode 100644
index 0000000000..a49bbc5c18
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchInitCommonLib/PchInitCommon.c
@@ -0,0 +1,519 @@
+/** @file
+ Pch common library for PCH INIT PEI/DXE/SMM modules
+
+Copyright (c) 2017, 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 <Uefi/UefiBaseType.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/IoLib.h>
+#include <Library/MmPciLib.h>
+#include <PchAccess.h>
+#include <PchPolicyCommon.h>
+#include <Library/PchCycleDecodingLib.h>
+#include <Library/PchPcieRpLib.h>
+#include <Library/PchP2sbLib.h>
+#include <Library/PchSbiAccessLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/S3BootScriptLib.h>
+#include <Library/TimerLib.h>
+
+extern CONST PCH_PCIE_CONTROLLER_INFO mPchPcieControllerInfo[];
+extern CONST UINT32 mPchPcieControllerInfoSize;
+
+#define PORT_PLS_TIMEOUT 100 ///< 100 * 10 us = 1ms timeout for USB3 PortSC PLS polling
+
+/**
+ This function returns PID according to PCIe controller index
+
+ @param[in] ControllerIndex PCIe controller index
+
+ @retval PCH_SBI_PID Returns PID for SBI Access
+**/
+PCH_SBI_PID
+PchGetPcieControllerSbiPid (
+ IN UINT32 ControllerIndex
+ )
+{
+ ASSERT (ControllerIndex < mPchPcieControllerInfoSize);
+ return mPchPcieControllerInfo[ControllerIndex].Pid;
+}
+
+/**
+ This function returns PID according to Root Port Number
+
+ @param[in] RpIndex Root Port Index (0-based)
+
+ @retval PCH_SBI_PID Returns PID for SBI Access
+**/
+PCH_SBI_PID
+GetRpSbiPid (
+ IN UINTN RpIndex
+ )
+{
+ return PchGetPcieControllerSbiPid ((UINT32) (RpIndex / PCH_PCIE_CONTROLLER_PORTS));
+}
+
+/**
+ Calculate root port device number based on physical port index.
+
+ @param[in] RpIndex Root port index (0-based).
+
+ @retval Root port device number.
+**/
+UINT32
+PchGetPcieRpDevice (
+ IN UINT32 RpIndex
+ )
+{
+ UINTN ControllerIndex;
+ ControllerIndex = RpIndex / PCH_PCIE_CONTROLLER_PORTS;
+ ASSERT (ControllerIndex < mPchPcieControllerInfoSize);
+ return mPchPcieControllerInfo[ControllerIndex].DevNum;
+}
+
+/**
+ This function reads Pci Config register via SBI Access
+
+ @param[in] RpIndex Root Port Index (0-based)
+ @param[in] Offset Offset of Config register
+ @param[out] *Data32 Value of Config register
+
+ @retval EFI_SUCCESS SBI Read successful.
+**/
+EFI_STATUS
+PchSbiRpPciRead32 (
+ IN UINT32 RpIndex,
+ IN UINT32 Offset,
+ OUT UINT32 *Data32
+ )
+{
+ EFI_STATUS Status;
+ UINT32 RpDevice;
+ UINT8 Response;
+ UINT16 Fid;
+
+
+ RpDevice = PchGetPcieRpDevice (RpIndex);
+ Fid = (UINT16) ((RpDevice << 3) | (RpIndex % 4 ));
+ Status = PchSbiExecutionEx (
+ GetRpSbiPid (RpIndex),
+ Offset,
+ PciConfigRead,
+ FALSE,
+ 0xF,
+ 0,
+ Fid,
+ Data32,
+ &Response
+ );
+ if (Status != EFI_SUCCESS) {
+ DEBUG ((DEBUG_ERROR,"Sideband Read Failed\n"));
+ ASSERT (FALSE);
+ }
+ return Status;
+}
+
+/**
+ This function And then Or Pci Config register via SBI Access
+
+ @param[in] RpIndex Root Port Index (0-based)
+ @param[in] Offset Offset of Config register
+ @param[in] Data32And Value of Config register to be And-ed
+ @param[in] Data32AOr Value of Config register to be Or-ed
+
+ @retval EFI_SUCCESS SBI Read and Write successful.
+**/
+EFI_STATUS
+PchSbiRpPciAndThenOr32 (
+ IN UINT32 RpIndex,
+ IN UINT32 Offset,
+ IN UINT32 Data32And,
+ IN UINT32 Data32Or
+ )
+{
+ EFI_STATUS Status;
+ UINT32 RpDevice;
+ UINT32 Data32;
+ UINT8 Response;
+ UINT16 Fid;
+
+ RpDevice = PchGetPcieRpDevice (RpIndex);
+ Status = PchSbiRpPciRead32 (RpIndex, Offset, &Data32);
+ if (Status == EFI_SUCCESS) {
+ Data32 &= Data32And;
+ Data32 |= Data32Or;
+ Fid = (UINT16) ((RpDevice << 3) | (RpIndex % 4 ));
+ Status = PchSbiExecutionEx (
+ GetRpSbiPid (RpIndex),
+ Offset,
+ PciConfigWrite,
+ FALSE,
+ 0xF,
+ 0,
+ Fid,
+ &Data32,
+ &Response
+ );
+ if (Status != EFI_SUCCESS) {
+ DEBUG ((DEBUG_ERROR,"Sideband Write Failed\n"));
+ ASSERT (FALSE);
+ }
+ } else {
+ ASSERT (FALSE);
+ }
+ return Status;
+}
+
+/**
+ Check if RST PCIe Storage Remapping is enabled based on policy
+
+ @param[in] RstPcieStorageRemap The PCH PCIe Storage remapping
+
+ @retval TRUE RST PCIe Storage Remapping is enabled
+ @retval FALSE RST PCIe Storage Remapping is disabled
+**/
+BOOLEAN
+IsRstPcieStorageRemapEnabled (
+ IN CONST PCH_RST_PCIE_STORAGE_CONFIG *RstPcieStorageRemap
+ )
+{
+ BOOLEAN RstPcieStorageRemapEnabled;
+ UINTN Index;
+
+ RstPcieStorageRemapEnabled = FALSE;
+
+ DEBUG ((DEBUG_INFO, "IsRstPcieStorageRemapEnabled Started\n"));
+
+ for (Index = 0; Index < PCH_MAX_RST_PCIE_STORAGE_CR; Index++) {
+ if (RstPcieStorageRemap[Index].Enable == 1) {
+ RstPcieStorageRemapEnabled = TRUE;
+ }
+ }
+
+ DEBUG ((DEBUG_INFO, "IsRstPcieStorageRemapEnabled Ended\n"));
+ return RstPcieStorageRemapEnabled;
+}
+
+/**
+ Disable the RST remap address decoding range while RST is disabled.
+
+ @param[in] AhciBar ABAR address
+**/
+VOID
+DisableRstRemapDecoding (
+ UINT32 AhciBar
+ )
+{
+ UINTN PciSataRegBase;
+ UINT32 OrgAhciBar;
+ UINT8 OrgCmd;
+
+ if (AhciBar == 0) {
+ DEBUG ((DEBUG_ERROR, "DisableRstRemapDecoding: Invalid AHCI BAR address.\n"));
+ ASSERT (FALSE);
+ return;
+ }
+
+ PciSataRegBase = MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_SATA, PCI_FUNCTION_NUMBER_PCH_SATA);
+ OrgCmd = MmioRead8 (PciSataRegBase + PCI_COMMAND_OFFSET);
+ OrgAhciBar = MmioRead32 (PciSataRegBase + R_PCH_SATA_AHCI_BAR);
+
+ if (AhciBar != OrgAhciBar) {
+ MmioWrite8 (PciSataRegBase + PCI_COMMAND_OFFSET, 0);
+ MmioWrite32 (PciSataRegBase + R_PCH_SATA_AHCI_BAR, AhciBar);
+ }
+ MmioWrite8 (PciSataRegBase + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_MEMORY_SPACE);
+
+ //
+ // Program "NVM Remap Memory BAR Enable", AHCIBar offset A4h [0] to ['0b']
+ // Also set NRMO AHCIBar offset A4h [27:16] to 0x00F, and MSL AHCIBar offset A4h [12:1] to 0.
+ //
+ DEBUG ((DEBUG_INFO, "DisableRstRemapDecoding: Program AHCIBar offset A4h [27:16, 12:1, 0] to [0x00F, 0, 0] to disable remap decoding\n"));
+ MmioWrite32 (AhciBar + R_PCH_SATA_VS_CAP, (0x00F << N_PCH_SATA_VS_CAP_NRMO));
+
+ if (AhciBar != OrgAhciBar) {
+ MmioWrite8 (PciSataRegBase + PCI_COMMAND_OFFSET, 0);
+ MmioWrite32 (PciSataRegBase + R_PCH_SATA_AHCI_BAR, OrgAhciBar);
+ }
+ MmioWrite8 (PciSataRegBase + PCI_COMMAND_OFFSET, OrgCmd);
+}
+
+/**
+ This function lock down the P2sb SBI before going into OS.
+
+ @param[in] SbiUnlock
+**/
+VOID
+ConfigureP2sbSbiLock (
+ IN CONST BOOLEAN SbiUnlock
+ )
+{
+ UINTN P2sbBase;
+ BOOLEAN P2sbOrgStatus;
+
+ if (SbiUnlock == FALSE) {
+ P2sbBase = MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_P2SB, PCI_FUNCTION_NUMBER_PCH_P2SB);
+ PchRevealP2sb (P2sbBase, &P2sbOrgStatus);
+
+ ///
+ /// Set P2SB PCI Offset 0xE0[31] to 1 to lock down SBI interface.
+ /// @note: SbiLock is write once. Please make sure it's not touched earlier.
+ ///
+ MmioOr8 (P2sbBase + R_PCH_P2SB_E0 + 3, BIT7);
+
+ if (!P2sbOrgStatus) {
+ PchHideP2sb (P2sbBase);
+ }
+ }
+}
+
+/**
+ Bios will remove the host accessing right to Sideband register range
+ prior to any 3rd party code execution.
+
+ 1) Set EPMASK5 Offset C4 (bits 29, 28, 27, 26, 17, 16 (PCH-LP only), 10, 1) to disable Sideband access for PSF and MIPI controller
+ 2) Set EPMASK7 Offset CC (bits 6, 5) to disable Sideband access for XHCI controller
+ 3) Set the "Endpoint Mask Lock!", P2SB PCI offset E2h bit[1] to 1.
+
+**/
+VOID
+RemoveSidebandAccess (
+ VOID
+ )
+{
+ UINTN P2sbBase;
+ BOOLEAN P2sbOrgStatus;
+
+ P2sbBase = MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_P2SB, PCI_FUNCTION_NUMBER_PCH_P2SB);
+ PchRevealP2sb (P2sbBase, &P2sbOrgStatus);
+
+ //
+ // Set EPMASK for ports B1, B0, AA, A1 (bits 17, 16 (PCH-LP only), 10, 1) to disable Sideband access for MIPI controller
+ // Set EPMASK for ports BD, BC, BB, BA (bits 29, 28, 27, 26) to disable Sideband access for PCI Root Bridge
+ //
+ if (GetPchSeries () == PchLp) {
+ MmioOr32 (P2sbBase + R_PCH_P2SB_EPMASK5, BIT29 | BIT28 | BIT27 | BIT26 | BIT17 | BIT16 | BIT10 | BIT1);
+ } else {
+ MmioOr32 (P2sbBase + R_PCH_P2SB_EPMASK5, BIT29 | BIT28 | BIT27 | BIT26 | BIT17 | BIT10 | BIT1);
+ }
+
+ //
+ // Set EPMASK for ports E6, E5 (bits 6, 5) to disable Sideband access for XHCI controller
+ //
+ MmioOr32(P2sbBase + R_PCH_P2SB_EPMASK7, BIT6 | BIT5);
+
+ DEBUG((DEBUG_INFO, "Lock the EPMASK registers\n"));
+
+ MmioOr8 (P2sbBase + R_PCH_P2SB_E0 + 2, BIT1);
+
+ if (!P2sbOrgStatus) {
+ PchHideP2sb (P2sbBase);
+ }
+}
+
+/**
+ Configure PMC static function disable lock
+**/
+VOID
+ConfigurePmcStaticFunctionDisableLock (
+ VOID
+ )
+{
+ UINT32 PchPwrmBase;
+ PchPwrmBaseGet (&PchPwrmBase);
+
+ MmioOr32 (PchPwrmBase + R_PCH_PWRM_ST_PG_FDIS_PMC_1, B_PCH_PWRM_ST_PG_FDIS_PMC_1_ST_FDIS_LK);
+}
+
+/**
+ Print registers value
+
+ @param[in] PrintMmioBase Mmio base address
+ @param[in] PrintSize Number of registers
+ @param[in] OffsetFromBase Offset from mmio base address
+
+ @retval None
+**/
+VOID
+PrintRegisters (
+ IN UINTN PrintMmioBase,
+ IN UINT32 PrintSize,
+ IN UINT32 OffsetFromBase
+ )
+{
+ UINT32 Offset;
+ DEBUG ((DEBUG_VERBOSE, " 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F"));
+ for (Offset = 0; Offset < PrintSize; Offset++) {
+ if ((Offset % 16) == 0) {
+ DEBUG ((DEBUG_VERBOSE, "\n %04X: ", (Offset + OffsetFromBase) & 0xFFF0));
+ }
+ DEBUG ((DEBUG_VERBOSE, "%02X ", MmioRead8 (PrintMmioBase + Offset)));
+ }
+ DEBUG ((DEBUG_VERBOSE, "\n"));
+}
+
+VOID
+PrintPchPciConfigSpace (
+ VOID
+ )
+{
+ DEBUG ((DEBUG_VERBOSE, "[ 0 - 00 - 0 ] Host Bridge\n"));
+ PrintRegisters (MmPciBase ( 0,0,0 ), 256, 0);
+ DEBUG ((DEBUG_VERBOSE, "[ 0 - 01 - 0 ] PCI Bridge (0-1) x16@1 (x16)\n"));
+ PrintRegisters (MmPciBase ( 0,1,0 ), 256, 0);
+ DEBUG ((DEBUG_VERBOSE, "[ 0 - 02 - 0 ] IGD\n"));
+ PrintRegisters (MmPciBase ( 0,2,0 ), 256, 0);
+ DEBUG ((DEBUG_VERBOSE, "[ 0 - 03 - 0 ] High Def Audio\n"));
+ PrintRegisters (MmPciBase (00, 03, 00), 256, 0);
+ DEBUG ((DEBUG_VERBOSE, "[ 0 - 20(0x14) - 0 ] XHCI Controller\n"));
+ PrintRegisters (MmPciBase (00, 20, 00), 256, 0);
+ DEBUG ((DEBUG_VERBOSE, "[ 0 - 22(0x16) - 0 ] ME\n"));
+ PrintRegisters (MmPciBase (00, 22, 00), 256, 0);
+ DEBUG ((DEBUG_VERBOSE, "[ 0 - 22(0x16) - 2 ] ME IDER\n"));
+ PrintRegisters (MmPciBase (00, 22, 02), 256, 0);
+ DEBUG ((DEBUG_VERBOSE, "[ 0 - 22(0x16) - 3 ] ME SOL\n"));
+ PrintRegisters (MmPciBase (00, 22, 03), 256, 0);
+ DEBUG ((DEBUG_VERBOSE, "[ 0 - 25(0x19) - 0 ] LAN\n"));
+ PrintRegisters (MmPciBase (00, 25, 00), 256, 0);
+ DEBUG ((DEBUG_VERBOSE, "[ 0 - 26(0x1A) - 0 ] EHCI Controller\n"));
+ PrintRegisters (MmPciBase (00, 26, 00), 256, 0);
+ DEBUG ((DEBUG_VERBOSE, "[ 0 - 27(0x1B) - 0 ] High Def Audio\n"));
+ PrintRegisters (MmPciBase (00, 27, 00), 256, 0);
+ DEBUG ((DEBUG_VERBOSE, "[ 0 - 28(0x1C) - 0 ] PCI Bridge (0-2) x0@1 (x1)\n"));
+ PrintRegisters (MmPciBase (00, 28, 00), 256, 0);
+ DEBUG ((DEBUG_VERBOSE, "PCI Bridge: AECH\n"));
+ PrintRegisters (MmPciBase (00, 28, 00) + 0x0100, 0x040,0x0100);
+ DEBUG ((DEBUG_VERBOSE, "PCI Bridge: DFT\n"));
+ PrintRegisters (MmPciBase (00, 28, 00) + 0x0310, 0x030,0x0310);
+ DEBUG ((DEBUG_VERBOSE, "PCI Bridge: VC0\n"));
+ PrintRegisters (MmPciBase (00, 28, 00) + 0x0340, 0x020,0x0340);
+ DEBUG ((DEBUG_VERBOSE, "PCI Bridge: Port Configuration Extension\n"));
+ PrintRegisters (MmPciBase (00, 28, 00) + 0x0400, 0x020,0x0400);
+ DEBUG ((DEBUG_VERBOSE, "[ 0 - 28(0x1C) - 6 ] PCI Bridge (0-3:10) x0@1 (x1)\n"));
+ PrintRegisters (MmPciBase (00, 28, 06), 256, 0);
+ DEBUG ((DEBUG_VERBOSE, "[ 0 - 29(0x1D) - 0 ] EHCI Controller\n"));
+ PrintRegisters (MmPciBase (00, 29, 00), 256, 0);
+ DEBUG ((DEBUG_VERBOSE, "[ 0 - 31(0x1F) - 0 ] ISA Bridge\n"));
+ PrintRegisters (MmPciBase (00, 31, 00), 256, 0);
+ DEBUG ((DEBUG_VERBOSE, "[ 0 - 31(0x1F) - 2 ] SATA\n"));
+ PrintRegisters (MmPciBase (00, 31, 02), 256, 0);
+ DEBUG ((DEBUG_VERBOSE, "[ 0 - 31(0x1F) - 4 ] SMBus Controller\n"));
+ PrintRegisters (MmPciBase (00, 31, 04), 256, 0);
+
+ DEBUG ((DEBUG_VERBOSE, "\n\n"));
+}
+
+/**
+ Program Xhci Port Disable Override
+
+ @param[in] XhciMmioBase xHCI controller MBAR0 address
+ @param[in] Usb2DisabledPorts Disabled USB2 ports where each port has its disabling bit
+ @param[in] Usb3DisabledPorts Disabled USB3 ports where each port has its disabling bit
+
+ @retval TRUE if platform reset is needed, otherwise FALSE is returned
+**/
+BOOLEAN
+UsbPdoProgramming (
+ IN UINTN XhciMmioBase,
+ IN UINT32 Usb2DisabledPorts,
+ IN UINT32 Usb3DisabledPorts
+ )
+{
+ UINT32 Index;
+ UINT32 XhciUsb2Pdo;
+ UINT32 XhciUsb3Pdo;
+ UINT32 XhciUsb2PdoRd;
+ UINT32 XhciUsb3PdoRd;
+ UINT32 XhciUsb3PortScStartingOffset;
+ UINT32 XhciUsb3PortScOffset;
+ UINT32 XhciPlsTimeout;
+
+ DEBUG ((DEBUG_INFO, "UsbPdoProgramming () start\n"));
+ DEBUG ((DEBUG_INFO, "xHCI: Usb2DisabledPorts = 0x%x\n", Usb2DisabledPorts));
+ DEBUG ((DEBUG_INFO, "xHCI: Usb3DisabledPorts = 0x%x\n", Usb3DisabledPorts));
+
+ //
+ // XHCI PDO for HS
+ //
+ if (GetPchSeries () == PchLp) {
+ XhciUsb2Pdo = MmioRead32 (XhciMmioBase + R_PCH_XHCI_USB2PDO) & B_PCH_XHCI_LP_USB2PDO_MASK;
+ } else {
+ XhciUsb2Pdo = MmioRead32 (XhciMmioBase + R_PCH_XHCI_USB2PDO) & B_PCH_XHCI_H_USB2PDO_MASK;
+ }
+ XhciUsb2Pdo |= Usb2DisabledPorts;
+
+ //
+ // XHCI PDO for SS
+ //
+ if (GetPchSeries () == PchLp) {
+ XhciUsb3Pdo = MmioRead32 (XhciMmioBase + R_PCH_XHCI_USB3PDO) & B_PCH_XHCI_LP_USB3PDO_MASK;
+ XhciUsb3PortScStartingOffset = R_PCH_LP_XHCI_PORTSC01USB3;
+ } else {
+ XhciUsb3Pdo = MmioRead32 (XhciMmioBase + R_PCH_XHCI_USB3PDO) & B_PCH_XHCI_H_USB3PDO_MASK;
+ XhciUsb3PortScStartingOffset = R_PCH_H_XHCI_PORTSC01USB3;
+ }
+
+ for (Index = 0; Index < GetPchXhciMaxUsb3PortNum (); Index++) {
+ // Check if port should be disabled
+ if ((Usb3DisabledPorts & (BIT0 << Index)) != 0) {
+ // Check if PDO bit has not been set yet
+ if (((XhciUsb3Pdo & (UINT32)(BIT0 << Index)) == 0)) {
+ // Calculate port PortSC register offset in xHCI MMIO space
+ XhciUsb3PortScOffset = (XhciUsb3PortScStartingOffset + (Index * 0x10));
+
+ // Disable port before setting PDO bit for it
+ MmioOr32 (XhciMmioBase + XhciUsb3PortScOffset, B_PCH_XHCI_PORTSCXUSB3_PED);
+
+ // Poll for PLS (PortSC[5:8]) to reach 0x4 before setting PDO for the port
+ for (XhciPlsTimeout = 0; XhciPlsTimeout < PORT_PLS_TIMEOUT; XhciPlsTimeout++) {
+ if ((MmioRead32 (XhciMmioBase + XhciUsb3PortScOffset) & B_PCH_XHCI_PORTSCXUSB3_PLS) == V_PCH_XHCI_PORTSCXUSB3_PLS_DISABLED) {
+ break;
+ }
+ MicroSecondDelay (10);
+ }
+
+ if (XhciPlsTimeout == PORT_PLS_TIMEOUT) {
+ DEBUG ((DEBUG_ERROR, "[xHCI PDO] PLS Polling for Disabled has timed out for port %d\n", Index + 1));
+ }
+
+ // A '1' in a bit position prevents the corresponding USB3 port from reporting a Device Connection to the XHC
+ XhciUsb3Pdo |= (UINT32) (B_PCH_XHCI_USB3PDO_DIS_PORT0 << Index);
+
+ // Put port back to RxDetect state
+ // Need to write LWS and PLS regs with same MMIO operation otherwise PLS write will be ignored
+ MmioOr32 (XhciMmioBase + XhciUsb3PortScOffset, (B_PCH_XHCI_PORTSCXUSB3_LWS | V_PCH_XHCI_PORTSCXUSB3_PLS_RXDETECT));
+ }
+ }
+ }
+
+ //
+ // USB2PDO and USB3PDO are Write-Once registers and bits in them are in the SUS Well.
+ //
+ MmioWrite32 (XhciMmioBase + R_PCH_XHCI_USB2PDO, XhciUsb2Pdo);
+ MmioWrite32 (XhciMmioBase + R_PCH_XHCI_USB3PDO, XhciUsb3Pdo);
+
+ XhciUsb2PdoRd = MmioRead32 (XhciMmioBase + R_PCH_XHCI_USB2PDO);
+ XhciUsb3PdoRd = MmioRead32 (XhciMmioBase + R_PCH_XHCI_USB3PDO);
+
+ //
+ // If USB2PDO and USB3PDO are not updated successfully perform Warm Reset to unlock RWO bits.
+ //
+ if ((XhciUsb2Pdo != XhciUsb2PdoRd) || (XhciUsb3Pdo != XhciUsb3PdoRd)) {
+ DEBUG ((DEBUG_ERROR, "UsbPdoProgramming: PDO register locked. Performing Warm Reset\n"));
+ return TRUE;
+ }
+
+ DEBUG ((DEBUG_INFO, "UsbPdoProgramming () end\n"));
+ return FALSE;
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchInitCommonLib/PchRpfn.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchInitCommonLib/PchRpfn.c
new file mode 100644
index 0000000000..77dd285430
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchInitCommonLib/PchRpfn.c
@@ -0,0 +1,127 @@
+/** @file
+ This file contains functions that configures PCI Express Root Ports function swapping.
+
+Copyright (c) 2017, 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 <Uefi/UefiBaseType.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/MmPciLib.h>
+#include <Library/PchPcieRpLib.h>
+#include <Library/PchPcrLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/PchPciExpressHelpersLib.h>
+#include <Library/PchInitCommonLib.h>
+#include <Library/PchPsfPrivateLib.h>
+#include <Library/S3BootScriptLib.h>
+
+/**
+ Configure root port function number mapping
+
+ @retval EFI_SUCCESS The function completed successfully
+**/
+EFI_STATUS
+PchConfigureRpfnMapping (
+ VOID
+ )
+{
+ UINT8 PortIndex;
+ UINT8 OriginalFuncZeroRp;
+ UINT8 MaxPciePortNum;
+ UINT32 Data32;
+ UINTN DevNum;
+ UINTN FuncNum;
+ UINTN RpBase;
+ UINT32 ControllerPcd[PCH_MAX_PCIE_CONTROLLERS];
+ PCH_SERIES PchSeries;
+ PCH_GENERATION PchGen;
+ UINT32 PcieControllers;
+ UINT32 ControllerIndex;
+ UINT32 FirstController;
+ PCH_SBI_PID ControllerPid;
+
+ DEBUG ((DEBUG_INFO,"PchConfigureRpfnMapping () Start\n"));
+
+ PchSeries = GetPchSeries ();
+ PchGen = GetPchGeneration ();
+ MaxPciePortNum = GetPchMaxPciePortNum ();
+
+ PcieControllers = GetPchMaxPcieControllerNum ();
+
+ for (ControllerIndex = 0; ControllerIndex < PcieControllers; ++ControllerIndex) {
+ PchPcrRead32 (PchGetPcieControllerSbiPid (ControllerIndex), R_PCH_PCR_SPX_PCD, &ControllerPcd[ControllerIndex]);
+ }
+
+ ///
+ /// Configure root port function number mapping
+ ///
+ for (PortIndex = 0; PortIndex < MaxPciePortNum; ) {
+ GetPchPcieRpDevFun (PortIndex, &DevNum, &FuncNum);
+ RpBase = MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH, (UINT32) DevNum, (UINT32) FuncNum);
+ //
+ // Search for first enabled function
+ //
+ if (MmioRead16 (RpBase) != 0xFFFF) {
+ if (FuncNum != 0) {
+ //
+ // First enabled root port that is not function zero will be swapped with function zero on the same device
+ // RP PCD register must sync with PSF RP function config register
+ //
+ ControllerIndex = PortIndex / 4;
+ OriginalFuncZeroRp = (PortIndex / 8) * 8;
+ FirstController = OriginalFuncZeroRp / 4;
+
+ //
+ // The enabled root port becomes function zero
+ //
+ ControllerPcd[ControllerIndex] &= (UINT32) ~(B_PCH_PCR_SPX_PCD_RP1FN << ((PortIndex % 4) * S_PCH_PCR_SPX_PCD_RP_FIELD));
+ ControllerPcd[ControllerIndex] |= 0u;
+ //
+ // Origianl function zero on the same device takes the numer of the current port
+ //
+ ControllerPcd[FirstController] &= (UINT32) ~B_PCH_PCR_SPX_PCD_RP1FN;
+ ControllerPcd[FirstController] |= (UINT32) FuncNum;
+
+ //
+ // Program PSF1 RP function config register.
+ //
+ PsfSetPcieFunctionWithS3BootScript (OriginalFuncZeroRp, (UINT32) FuncNum);
+ PsfSetPcieFunctionWithS3BootScript (PortIndex, 0);
+ }
+ //
+ // Once enabled root port was found move to next PCI device
+ //
+ PortIndex = ((PortIndex / 8) + 1) * 8;
+ continue;
+ }
+ //
+ // Continue search for first enabled root port
+ //
+ PortIndex++;
+ }
+
+ //
+ // Write to PCD and lock the register
+ //
+ for (ControllerIndex = 0; ControllerIndex < PcieControllers; ++ControllerIndex) {
+ ControllerPid = PchGetPcieControllerSbiPid (ControllerIndex);
+ Data32 = ControllerPcd[ControllerIndex] | B_PCH_PCR_SPX_PCD_SRL;
+ PchPcrWrite32 (ControllerPid, R_PCH_PCR_SPX_PCD, Data32);
+ PCH_PCR_BOOT_SCRIPT_WRITE (
+ S3BootScriptWidthUint32,
+ ControllerPid, R_PCH_PCR_SPX_PCD,
+ 1,
+ &Data32
+ );
+ }
+ return EFI_SUCCESS;
+}
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchInitCommonLib/PeiDxeSmmPchInitCommonLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchInitCommonLib/PeiDxeSmmPchInitCommonLib.inf
new file mode 100644
index 0000000000..df4900d964
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchInitCommonLib/PeiDxeSmmPchInitCommonLib.inf
@@ -0,0 +1,42 @@
+## @file
+# Component description file for the PchInitCommonLib
+#
+# Copyright (c) 2017, 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 = 0x00010005
+ BASE_NAME = PeiDxeSmmPchInitCommonLib
+ FILE_GUID = E9C4FE04-8A79-43FA-B3E0-603359C31B43
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PchInitCommonLib
+
+[Sources]
+ PchInitCommon.c
+ PchRpfn.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ KabylakeSiliconPkg/SiPkg.dec
+ KabylakeSiliconPkg/KabylakeSiliconPrivate.dec
+
+[LibraryClasses]
+ IoLib
+ DebugLib
+ PchCycleDecodingLib
+ PchPcieRpLib
+ PchP2sbLib
+ PchSbiAccessLib
+ PchInfoLib
+ PchPsfPrivateLib
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchPciExpressHelpersLib/PchPciExpressHelpersLibrary.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchPciExpressHelpersLib/PchPciExpressHelpersLibrary.c
new file mode 100644
index 0000000000..815b800db7
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchPciExpressHelpersLib/PchPciExpressHelpersLibrary.c
@@ -0,0 +1,1933 @@
+/** @file
+ This file contains routines that support PCI Express initialization
+
+Copyright (c) 2017, 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 "PchPciExpressHelpersLibrary.h"
+
+const UINT8 mPcieL1sTposMultiplier[] = {2, 10, 100};
+
+/*
+ Returns Tpower_on capability of device
+
+ @param[in] DeviceBase device base address
+ @param[in] L1ssCapOffset offset to L1substates capability in device's extended config space
+*/
+T_POWER_ON GetTpoCapability (
+ UINTN DeviceBase,
+ UINT32 L1ssCapOffset
+ )
+{
+ T_POWER_ON Tpo;
+ UINT32 L1ssCapabilities;
+
+ L1ssCapabilities = MmioRead32 (DeviceBase + L1ssCapOffset + R_PCIE_EX_L1SCAP_OFFSET);
+ Tpo.Scale = (L1ssCapabilities & B_PCIE_EX_L1SCAP_PTPOS) >> N_PCIE_EX_L1SCAP_PTPOS;
+ Tpo.Value = (L1ssCapabilities & B_PCIE_EX_L1SCAP_PTV) >> N_PCIE_EX_L1SCAP_PTV;
+ return Tpo;
+}
+
+/*
+ Returns Tpower_on currently programed in a device
+
+ @param[in] DeviceBase device base address
+ @param[in] L1ssCapOffset offset to L1substates capability in device's extended config space
+*/
+T_POWER_ON GetTpo (
+ UINTN DeviceBase,
+ UINT32 L1ssCapOffset
+ )
+{
+ T_POWER_ON Tpo;
+ UINT32 L1ssControl2;
+
+ L1ssControl2 = MmioRead32 (DeviceBase + L1ssCapOffset + R_PCIE_EX_L1SCTL2_OFFSET);
+ Tpo.Scale = L1ssControl2 & 0x3;
+ Tpo.Value = (L1ssControl2 & 0xF8) >> N_PCIE_EX_L1SCTL2_POWT;
+ return Tpo;
+}
+
+/*
+ Sets Tpower_on in a device
+ According to spec, Tpower_on can only be updated while L1.2 is disabled
+
+ @param[in] DeviceBase device base address
+ @param[in] L1ssCapOffset offset to L1substates capability in device's extended config space
+ @param[in] Tpo value to be programmed into Tpower_on
+*/
+VOID SetTpo (
+ UINTN DeviceBase,
+ UINT32 L1ssCapOffset,
+ T_POWER_ON Tpo
+ )
+{
+ UINT32 L1_2;
+
+ L1_2 = MmioRead32 (DeviceBase + L1ssCapOffset + R_PCIE_EX_L1SCTL1_OFFSET) & (BIT2 | BIT0);
+ MmioAnd32 (DeviceBase + L1ssCapOffset + R_PCIE_EX_L1SCTL1_OFFSET, (UINT32)(~ (BIT2 | BIT0)));
+ MmioAndThenOr32 (DeviceBase + L1ssCapOffset + R_PCIE_EX_L1SCTL2_OFFSET, (UINT32)(~0xFB), (Tpo.Value << 3) + Tpo.Scale);
+ MmioOr32 (DeviceBase + L1ssCapOffset + R_PCIE_EX_L1SCTL1_OFFSET, L1_2);
+}
+
+/*
+ Converts Tpower_on from value:scale notation to microseconds
+*/
+UINT32 TpoToUs (
+ T_POWER_ON Tpo
+ )
+{
+ static const UINT8 TpoScaleMultiplier[] = {2, 10, 100};
+
+ ASSERT (Tpo.Scale < TpoScaleMax);
+ if (Tpo.Scale >= TpoScaleMax) {
+ return 0;
+ }
+ return (TpoScaleMultiplier[Tpo.Scale] * Tpo.Value);
+}
+
+/**
+ Find the Offset to a given Capabilities ID
+ CAPID list:
+ 0x01 = PCI Power Management Interface
+ 0x04 = Slot Identification
+ 0x05 = MSI Capability
+ 0x10 = PCI Express Capability
+
+ @param[in] Bus Pci Bus Number
+ @param[in] Device Pci Device Number
+ @param[in] Function Pci Function Number
+ @param[in] CapId CAPID to search for
+
+ @retval 0 CAPID not found
+ @retval Other CAPID found, Offset of desired CAPID
+**/
+UINT8
+PcieFindCapId (
+ IN UINT8 Bus,
+ IN UINT8 Device,
+ IN UINT8 Function,
+ IN UINT8 CapId
+ )
+{
+ UINT8 CapHeaderOffset;
+ UINT8 CapHeaderId;
+ UINTN DeviceBase;
+
+ DeviceBase = MmPciBase (Bus, Device, Function);
+
+ DEBUG ((DEBUG_INFO,"PcieFindCapId () BDF %0x: %0x :%0x, CapId = %0x \n", Bus, Device, Function, CapId));
+ if ((MmioRead8 (DeviceBase + PCI_PRIMARY_STATUS_OFFSET) & EFI_PCI_STATUS_CAPABILITY) == 0x00) {
+ ///
+ /// Function has no capability pointer
+ ///
+ return 0;
+ } else {
+ ///
+ /// Check the header layout to determine the Offset of Capabilities Pointer Register
+ ///
+ if ((MmioRead8 (DeviceBase + PCI_HEADER_TYPE_OFFSET) & HEADER_LAYOUT_CODE) == (HEADER_TYPE_CARDBUS_BRIDGE)) {
+ ///
+ /// If CardBus bridge, start at Offset 0x14
+ ///
+ CapHeaderOffset = EFI_PCI_CARDBUS_BRIDGE_CAPABILITY_PTR;
+ } else {
+ ///
+ /// Otherwise, start at Offset 0x34
+ ///
+ CapHeaderOffset = PCI_CAPBILITY_POINTER_OFFSET;
+ }
+ ///
+ /// Get Capability Header, A pointer value of 00h is used to indicate the last capability in the list.
+ ///
+ CapHeaderId = 0;
+ CapHeaderOffset = MmioRead8 (DeviceBase + CapHeaderOffset) & ((UINT8) ~(BIT0 | BIT1));
+ while (CapHeaderOffset != 0 && CapHeaderId != 0xFF) {
+ CapHeaderId = MmioRead8 (DeviceBase + CapHeaderOffset);
+ if (CapHeaderId == CapId) {
+ if (CapHeaderOffset > PCI_MAXLAT_OFFSET) {
+ ///
+ /// Return valid capability offset
+ ///
+ return CapHeaderOffset;
+ } else {
+ ASSERT ((FALSE));
+ return 0;
+ }
+ }
+ ///
+ /// Each capability must be DWORD aligned.
+ /// The bottom two bits of all pointers (including the initial pointer at 34h) are reserved
+ /// and must be implemented as 00b although software must mask them to allow for future uses of these bits.
+ ///
+ CapHeaderOffset = MmioRead8 (DeviceBase + CapHeaderOffset + 1) & ((UINT8) ~(BIT0 | BIT1));
+ }
+ return 0;
+ }
+}
+
+/**
+ Search and return the offset of desired Pci Express Capability ID
+ CAPID list:
+ 0x0001 = Advanced Error Reporting Capability
+ 0x0002 = Virtual Channel Capability
+ 0x0003 = Device Serial Number Capability
+ 0x0004 = Power Budgeting Capability
+
+ @param[in] Bus Pci Bus Number
+ @param[in] Device Pci Device Number
+ @param[in] Function Pci Function Number
+ @param[in] CapId Extended CAPID to search for
+
+ @retval 0 CAPID not found, this includes situation where device doesn't exist
+ @retval Other CAPID found, Offset of desired CAPID
+**/
+UINT16
+PcieFindExtendedCapId (
+ IN UINT8 Bus,
+ IN UINT8 Device,
+ IN UINT8 Function,
+ IN UINT16 CapId
+ )
+{
+ UINT16 CapHeaderOffset;
+ UINT16 CapHeaderId;
+ UINTN DeviceBase;
+
+ DeviceBase = MmPciBase (Bus, Device, Function);
+
+ ///
+ /// Start to search at Offset 0x100
+ /// Get Capability Header, A pointer value of 00h is used to indicate the last capability in the list.
+ ///
+ CapHeaderId = 0;
+ CapHeaderOffset = R_PCH_PCIE_EXCAP_OFFSET;
+ while (CapHeaderOffset != 0 && CapHeaderId != MAX_UINT16) {
+ CapHeaderId = MmioRead16 (DeviceBase + CapHeaderOffset);
+ if (CapHeaderId == CapId) {
+ return CapHeaderOffset;
+ }
+ ///
+ /// Each capability must be DWORD aligned.
+ /// The bottom two bits of all pointers are reserved and must be implemented as 00b
+ /// although software must mask them to allow for future uses of these bits.
+ ///
+ CapHeaderOffset = (MmioRead16 (DeviceBase + CapHeaderOffset + 2) >> 4) & ((UINT16) ~(BIT0 | BIT1));
+ }
+
+ return 0;
+}
+
+/**
+ This returns ClkReq Number from Port Number
+
+ @param[in] PortIndex PCIe Port Number (Zero Base)
+
+ @retval ClkReq Number
+**/
+UINT8
+GetPortClkReqNumber (
+ IN UINT8 PortIndex
+ )
+{
+ UINT8 ClkReqNum;
+ PchPcrRead8 (PID_FIA, R_PCH_PCR_FIA_DRCRM1 + (PortIndex / 2), &ClkReqNum);
+ if (PortIndex % 2 == 0) {
+ ClkReqNum &= 0x0F;
+ } else {
+ ClkReqNum = ClkReqNum >> 4;
+ }
+ return ClkReqNum;
+}
+
+/**
+ Set Common clock to Root port and Endpoint PCI device
+
+ @param[in] Bus1 Root port Pci Bus Number
+ @param[in] Device1 Root port Pci Device Number
+ @param[in] Function1 Root port Pci Function Number
+ @param[in] Bus2 Endpoint Pci Bus Number
+ @param[in] Device2 Endpoint Pci Device Number
+
+ @exception EFI_UNSUPPORTED Unsupported operation.
+ @retval EFI_SUCCESS VC mapping correctly initialized
+**/
+EFI_STATUS
+PcieSetCommonClock (
+ IN UINT8 Bus1,
+ IN UINT8 Device1,
+ IN UINT8 Function1,
+ IN UINT8 Bus2,
+ IN UINT8 Device2
+ )
+{
+ UINT8 CapOffset1;
+ UINT8 CapOffset2;
+ BOOLEAN CommonClockSupport;
+ UINTN DeviceBase1;
+ UINTN DeviceBase2;
+ UINT16 RegData16;
+ UINT8 FunctionIndex;
+ UINT8 Function2;
+
+ DeviceBase1 = MmPciBase (Bus1, Device1, Function1);
+
+ ///
+ /// Get the pointer to the Port PCI Express Capability Structure.
+ ///
+ CommonClockSupport = FALSE;
+ CapOffset1 = PcieFindCapId (Bus1, Device1, Function1, EFI_PCI_CAPABILITY_ID_PCIEXP);
+ if (CapOffset1 == 0) {
+ return EFI_UNSUPPORTED;
+ }
+ ///
+ /// Check the Port Slot Clock Configuration Bit.
+ ///
+ if ((MmioRead16 (DeviceBase1 + CapOffset1 + R_PCIE_LSTS_OFFSET) & B_PCIE_LSTS_SCC) == 0) {
+ return EFI_UNSUPPORTED;
+ }
+
+ DeviceBase2 = MmPciBase (Bus2, Device2, 0);
+ ///
+ /// Check if EndPoint device is Multi-Function Device
+ ///
+ if (MmioRead8 (DeviceBase2 + PCI_HEADER_TYPE_OFFSET) & HEADER_TYPE_MULTI_FUNCTION) {
+ ///
+ /// If multi-function Device, check function 0-7
+ ///
+ Function2 = PCI_MAX_FUNC;
+ } else {
+ ///
+ /// Otherwise, check function 0 only
+ ///
+ Function2 = 0;
+ }
+
+ for (FunctionIndex = 0; FunctionIndex <= Function2; FunctionIndex++) {
+ DeviceBase2 = MmPciBase (Bus2, Device2, FunctionIndex);
+ ///
+ /// Check the Endpoint Slot Clock Configuration Bit.
+ ///
+ CapOffset2 = PcieFindCapId (Bus2, Device2, FunctionIndex, EFI_PCI_CAPABILITY_ID_PCIEXP);
+ if ((CapOffset2 != 0) && ((MmioRead16 (DeviceBase2 + CapOffset2 + R_PCIE_LSTS_OFFSET) & B_PCIE_LSTS_SCC) != 0)) {
+ ///
+ /// Common clock is supported, set common clock bit on root port
+ /// and the endpoint
+ ///
+ if (CommonClockSupport == FALSE) {
+ MmioOr8 (DeviceBase1 + CapOffset1 + R_PCIE_LCTL_OFFSET, B_PCIE_LCTL_CCC);
+ CommonClockSupport = TRUE;
+ }
+ MmioOr8 (DeviceBase2 + CapOffset2 + R_PCIE_LCTL_OFFSET, B_PCIE_LCTL_CCC);
+ }
+ }
+ ///
+ /// If common clock not supported on root port and endpoint, return EFI_UNSUPPORTED
+ ///
+ if (CommonClockSupport == FALSE) {
+ return EFI_UNSUPPORTED;
+ }
+ ///
+ /// Retrain the Link per PCI Express Specification.
+ ///
+ MmioOr8 (DeviceBase1 + CapOffset1 + R_PCIE_LCTL_OFFSET, B_PCIE_LCTL_RL);
+
+ ///
+ /// Wait until Re-Training has completed.
+ ///
+ do {
+ RegData16 = MmioRead16 (DeviceBase1 + CapOffset1 + R_PCIE_LSTS_OFFSET) & B_PCIE_LSTS_LT;
+ } while (RegData16 != 0);
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This function enables the CLKREQ# PM on all the end point functions
+
+ @param[in] Bus Pci Bus Number
+ @param[in] Device Pci Device Number
+ @param[in] RootDevice Rootport Device Number
+ @param[in] RootFunction Rootport Function Number
+
+ @retval None
+**/
+VOID
+PcieSetClkreq (
+ IN UINT8 EndPointBus,
+ IN UINT8 EndPointDevice,
+ IN UINT8 RootDevice,
+ IN UINT8 RootFunction
+ )
+{
+ UINT8 CapOffset;
+ UINTN DeviceBase;
+ UINT8 FunctionIndex;
+ UINT8 Function;
+ BOOLEAN ClkreqPerPortSupported;
+
+ DeviceBase = MmPciBase (EndPointBus, EndPointDevice, 0);
+ ClkreqPerPortSupported = TRUE;
+
+ ///
+ /// Check if EndPoint device is Multi-Function Device
+ ///
+ if (MmioRead8 (DeviceBase + PCI_HEADER_TYPE_OFFSET) & HEADER_TYPE_MULTI_FUNCTION) {
+ ///
+ /// If multi-function Device, check function 0-7
+ ///
+ Function = PCI_MAX_FUNC;
+ } else {
+ ///
+ /// Otherwise, check function 0 only
+ ///
+ Function = 0;
+ }
+ ///
+ /// Parse thro all the functions of the endpoint and find the PCIe Cap ID (offset 10h) and if
+ /// exists then enable the CLKREQ# bit (BIT8) on that function
+ ///
+ for (FunctionIndex = 0; FunctionIndex <= Function; FunctionIndex++) {
+ ///
+ /// Find the PCIe Cap Id (10h)
+ ///
+ CapOffset = PcieFindCapId (EndPointBus, EndPointDevice, FunctionIndex, EFI_PCI_CAPABILITY_ID_PCIEXP);
+ if (CapOffset == 0) {
+ continue;
+ }
+
+ DeviceBase = MmPciBase (EndPointBus, EndPointDevice, FunctionIndex);
+ ///
+ /// Check if CLKREQ# is supported by the endpoints
+ ///
+ if ((MmioRead32 (DeviceBase + CapOffset + R_PCIE_LCAP_OFFSET) & B_PCIE_LCAP_CPM) == 0) {
+ ///
+ /// CLKREQ# is not supported so dont do anything
+ ///
+ ClkreqPerPortSupported = FALSE;
+ break;
+ }
+ }
+
+ if (ClkreqPerPortSupported == FALSE) {
+ return;
+ }
+ ///
+ /// Now enable the CLKREQ#
+ ///
+ for (FunctionIndex = 0; FunctionIndex <= Function; FunctionIndex++) {
+ ///
+ /// Find the PCIe Cap Id (10h)
+ ///
+ CapOffset = PcieFindCapId (EndPointBus, EndPointDevice, FunctionIndex, EFI_PCI_CAPABILITY_ID_PCIEXP);
+ if (CapOffset == 0) {
+ continue;
+ }
+
+ DeviceBase = MmPciBase (EndPointBus, EndPointDevice, FunctionIndex);
+ MmioOr16 (DeviceBase + CapOffset + R_PCIE_LCTL_OFFSET, B_PCIE_LCTL_ECPM);
+ }
+}
+/**
+ This function get or set the Max Payload Size on all the end point functions
+
+ @param[in] EndPointBus The Bus Number of the Endpoint
+ @param[in] EndPointDevice The Device Number of the Endpoint
+ @param[in, out] MaxPayload The Max Payolad Size of the root port
+ @param[in] Operation True: Set the Max Payload Size on all the end point functions
+ False: Get the Max Payload Size on all the end point functions
+
+ @retval EFI_SUCCESS Successfully completed.
+**/
+EFI_STATUS
+PcieMaxPayloadSize (
+ IN UINT8 EndPointBus,
+ IN UINT8 EndPointDevice,
+ IN OUT UINT16 *MaxPayload,
+ IN BOOLEAN Operation
+ )
+{
+ UINTN DeviceBase;
+ UINT8 PcieCapOffset;
+ UINT16 EndPointMaxPayload;
+ UINT8 FunctionIndex;
+ UINT8 EndPointFunction;
+
+ ///
+ /// Obtain the Max Payload Size for all the end point functions
+ ///
+ DeviceBase = MmPciBase (EndPointBus, EndPointDevice, 0);
+ ///
+ /// Check if EndPoint device is Multi-Function Device
+ ///
+ if (MmioRead8 (DeviceBase + PCI_HEADER_TYPE_OFFSET) & HEADER_TYPE_MULTI_FUNCTION) {
+ ///
+ /// If multi-function Device, check function 0-7
+ ///
+ EndPointFunction = PCI_MAX_FUNC;
+ } else {
+ ///
+ /// Otherwise, check function 0 only
+ ///
+ EndPointFunction = 0;
+ }
+
+ for (FunctionIndex = 0; FunctionIndex <= EndPointFunction; FunctionIndex++) {
+ DeviceBase = MmPciBase (EndPointBus, EndPointDevice, FunctionIndex);
+ if (MmioRead16 (DeviceBase + PCI_VENDOR_ID_OFFSET) != MAX_UINT16) {
+ ///
+ /// Get the pointer to the Endpoint PCI Express Capability Structure.
+ ///
+ PcieCapOffset = PcieFindCapId (EndPointBus, EndPointDevice, FunctionIndex, EFI_PCI_CAPABILITY_ID_PCIEXP);
+ if (PcieCapOffset == 0) {
+ continue;
+ }
+
+ if (Operation == TRUE) {
+ ///
+ /// Set the Max Payload Size of the end point function
+ ///
+ MmioAndThenOr16 (
+ DeviceBase + PcieCapOffset + R_PCIE_DCTL_OFFSET,
+ (UINT16) ~(B_PCIE_DCTL_MPS),
+ *MaxPayload << N_PCIE_DCTL_MPS
+ );
+ } else {
+ ///
+ /// Get the end point function Max Payload Size support
+ ///
+ EndPointMaxPayload = MmioRead16 (DeviceBase + PcieCapOffset + R_PCIE_DCAP_OFFSET) & B_PCIE_DCAP_MPS;
+ ///
+ /// Obtain the minimum Max Payload Size between the PCIE root Port and the end point functions
+ ///
+ if (*MaxPayload > EndPointMaxPayload) {
+ *MaxPayload = EndPointMaxPayload;
+ }
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function disable the forwarding of EOI messages unless it discovers
+ an IOAPIC behind this root port.
+
+ @param[in] RootBus The Bus Number of the root port
+ @param[in] RootDevice The Device Number of the root port
+ @param[in] RootFunction The Function Number of the root port
+ @param[in] EndPointBus The Bus Number of the Endpoint
+ @param[in] EndPointDevice The Device Number of the Endpoint
+
+ @exception EFI_UNSUPPORTED Unsupported operation.
+ @retval EFI_SUCCESS Successfully completed.
+**/
+EFI_STATUS
+PcieSetEoiFwdDisable (
+ IN UINT8 RootBus,
+ IN UINT8 RootDevice,
+ IN UINT8 RootFunction,
+ IN UINT8 EndPointBus,
+ IN UINT8 EndPointDevice
+ )
+{
+ BOOLEAN IoApicBehind;
+ UINTN RootDeviceBase;
+ UINTN DeviceBase;
+ UINT8 ProgInterface;
+ UINT8 SubClassCode;
+ UINT8 BaseClassCode;
+ UINT8 FunctionIndex;
+ UINT8 EndPointFunction;
+ UINTN RootPortIndex;
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+ IoApicBehind = FALSE;
+ RootDeviceBase = MmPciBase (RootBus, RootDevice, RootFunction);
+
+ ///
+ /// Check if an IOAPIC behind the root port
+ ///
+ DeviceBase = MmPciBase (EndPointBus, EndPointDevice, 0);
+ ///
+ /// Check if EndPoint device is Multi-Function Device
+ ///
+ if (MmioRead8 (DeviceBase + PCI_HEADER_TYPE_OFFSET) & HEADER_TYPE_MULTI_FUNCTION) {
+ ///
+ /// If multi-function Device, check function 0-7
+ ///
+ EndPointFunction = PCI_MAX_FUNC;
+ } else {
+ ///
+ /// Otherwise, check function 0 only
+ ///
+ EndPointFunction = 0;
+ }
+
+ for (FunctionIndex = 0; FunctionIndex <= EndPointFunction; FunctionIndex++) {
+ DeviceBase = MmPciBase (EndPointBus, EndPointDevice, FunctionIndex);
+ BaseClassCode = MmioRead8 (DeviceBase + PCI_CLASSCODE_OFFSET + 2);
+ SubClassCode = MmioRead8 (DeviceBase + PCI_CLASSCODE_OFFSET + 1);
+ ProgInterface = MmioRead8 (DeviceBase + PCI_CLASSCODE_OFFSET);
+ if ((BaseClassCode == PCI_CLASS_SYSTEM_PERIPHERAL) &&
+ (SubClassCode == PCI_SUBCLASS_PIC) &&
+ ((ProgInterface == PCI_IF_APIC_CONTROLLER) ||
+ (ProgInterface == PCI_IF_APIC_CONTROLLER2))) {
+ IoApicBehind = TRUE;
+ }
+ }
+ ///
+ /// PCH BIOS Spec Section 8.15 Additional PCI Express* Programming Steps
+ /// Step 27
+ /// If there is no IOAPIC behind the root port, set EOI Forwarding Disable bit (PCIE RP PCI offset D4h[1]) to 1b.
+ ///
+ if (IoApicBehind == FALSE) {
+ MmioOr32 (RootDeviceBase + R_PCH_PCIE_MPC2, B_PCH_PCIE_MPC2_EOIFD);
+ } else {
+ ///
+ /// If there is an IOAPIC discovered behind root port program PSF Multicast registers
+ /// accordingly to SKL PCH BWG 5.14.4 PSF EOI Multicast Configuration
+ ///
+ ///
+ ///
+ Status = GetPchPcieRpNumber ((UINTN) RootDevice, (UINTN) RootFunction, &RootPortIndex);
+ ASSERT_EFI_ERROR (Status);
+
+ PsfConfigurEoiForPciePort ((UINT32)RootPortIndex);
+ }
+
+ return Status;
+}
+
+typedef enum {
+ CalculateAspm,
+ ManualAspm,
+ SetAspm
+} OPERATION;
+
+/**
+ This function compares the actual latency in LatencyValue1
+ with actual latency in LatencyValue2 and stores the minimum
+ back to LatencyValue1, in the required format.
+ If this is the first call, then LatencyValue1 will be replaced by LatencyValue2.
+
+ @param[in, out] LatencyValue1 - Current latency value
+ @param[in] LatencyValue2 - Latency value from the Table
+
+ @retval None
+**/
+VOID
+DetermineLatencyValue (
+ IN OUT UINT16 *LatencyValue1,
+ IN UINT16 LatencyValue2
+ )
+{
+ ASSERT (LTR_SCALE_VALUE (*LatencyValue1) < 6);
+ ASSERT (LTR_SCALE_VALUE (LatencyValue2) < 6);
+ ///
+ /// If there are more than one device behind a bridge that are part of the override table,
+ /// store the lower latency value and corresponding scale bits back to LatencyValue1
+ ///
+ if ((LTR_LATENCY_NS (*LatencyValue1) == 0) || (LTR_LATENCY_NS (*LatencyValue1) > LTR_LATENCY_NS (LatencyValue2))) {
+ *LatencyValue1 = LatencyValue2;
+ }
+}
+
+/**
+ This function checks exit latency of L1 and L0s and disables the ASPM state if it is longer than
+ the acceptable latency
+
+ @param[in] EndPointBase End Point Base Address
+ @param[in] EndPointPcieCapOffset The pointer to the End Point PCI Express Capability Structure
+ @param[in] RootDeviceBase The Root Port PCI Express Base address
+ @param[in] RootPcieCapOffset The pointer to the Root Port PCI Express Capability Structure
+ @param[in, out] EndPointAspm End Point ASPM setting
+
+ @retval none
+**/
+VOID
+AspmCheckExitLatency (
+ IN UINTN EndPointBase,
+ IN UINT8 EndPointPcieCapOffset,
+ IN UINTN RootDeviceBase,
+ IN UINT32 RootPcieCapOffset,
+ IN OUT UINT16* EndPointAspm
+ )
+{
+
+ UINT32 PortLxLat;
+ UINT32 EndPointLxLat;
+ UINT32 LxLat;
+
+ ///
+ /// Check if L1 should be enabled based on port and endpoint L1 exit latency.
+ ///
+ if ((*EndPointAspm) & BIT1) {
+ PortLxLat = MmioRead32 (RootDeviceBase + RootPcieCapOffset + R_PCIE_LCAP_OFFSET) & B_PCIE_LCAP_EL1;
+ EndPointLxLat = MmioRead32 (EndPointBase + EndPointPcieCapOffset + R_PCIE_LCAP_OFFSET) & B_PCIE_LCAP_EL1;
+
+ LxLat = PortLxLat;
+ if (PortLxLat < EndPointLxLat) {
+ LxLat = EndPointLxLat;
+ }
+ ///
+ /// check if the value is bigger than endpoint L1 acceptable exit latency, if it is
+ /// larger than accepted value, then we should disable L1
+ ///
+ LxLat >>= N_PCIE_LCAP_EL1;
+ if (LxLat > ((MmioRead32 (EndPointBase + EndPointPcieCapOffset + R_PCIE_DCAP_OFFSET) & B_PCIE_DCAP_E1AL) >> N_PCIE_DCAP_E1AL)) {
+ (*EndPointAspm) &= ~BIT1;
+ }
+ }
+ ///
+ /// Check if L0s should be enabled based on port and endpoint L0s exit latency.
+ ///
+ if ((*EndPointAspm) & BIT0) {
+ PortLxLat = MmioRead32 (RootDeviceBase + RootPcieCapOffset + R_PCIE_LCAP_OFFSET) & B_PCIE_LCAP_EL0;
+ EndPointLxLat = MmioRead32 (EndPointBase + EndPointPcieCapOffset + R_PCIE_LCAP_OFFSET) & B_PCIE_LCAP_EL0;
+
+ LxLat = PortLxLat;
+ if (PortLxLat < EndPointLxLat) {
+ LxLat = EndPointLxLat;
+ }
+ ///
+ /// check if the value is bigger than endpoint L0s acceptable exit latency, if it is
+ /// larger than accepted value, then we should disable L0s
+ ///
+ LxLat >>= N_PCIE_LCAP_EL0;
+ if (LxLat > ((MmioRead32 (EndPointBase + EndPointPcieCapOffset + R_PCIE_DCAP_OFFSET) & B_PCIE_DCAP_E0AL) >> N_PCIE_DCAP_E0AL)) {
+ (*EndPointAspm) &= ~BIT0;
+ }
+ }
+ return;
+}
+/**
+ This function gets override Aspm values if the end point is found in the override look up table
+
+ @param[in] EndPointBase End Point Base Address
+ @param[in] NumOfDevAspmOverride Number of Device specific ASPM policy override items
+ @param[in] DevAspmOverride Pointer to array of Device specific ASPM policy override items
+ @param[in] EndPointVendorId End Point Vendor Id
+ @param[in] EndPointDeviceId End Point Device Id
+ @param[in] EndPointRevId End Point Revision Id
+ @param[in, out] EndPointAspm End Point ASPM setting
+
+ @retval none
+**/
+
+VOID
+GetOverrideAspm (
+ IN UINTN EndPointBase,
+ IN UINT32 NumOfDevAspmOverride,
+ IN const PCH_PCIE_DEVICE_OVERRIDE* DevAspmOverride,
+ IN UINT16 EndPointVendorId,
+ IN UINT16 EndPointDeviceId,
+ IN UINT8 EndPointRevId,
+ IN OUT UINT16 *EndPointAspm
+ )
+{
+ UINT8 EndPointBaseClassCode;
+ UINT8 EndPointSubClassCode;
+ UINT8 PcieDeviceIndex;
+ ///
+ /// Mask APMC with values from lookup table.
+ /// RevID of 0xFF applies to all steppings.
+ ///
+ EndPointBaseClassCode = MmioRead8 (EndPointBase + R_PCI_BCC_OFFSET);
+ EndPointSubClassCode = MmioRead8 (EndPointBase + R_PCI_SCC_OFFSET);
+ for (PcieDeviceIndex = 0; PcieDeviceIndex < NumOfDevAspmOverride; PcieDeviceIndex++) {
+ if (((DevAspmOverride[PcieDeviceIndex].OverrideConfig & PchPcieL1L2Override) == PchPcieL1L2Override) &&
+ ((DevAspmOverride[PcieDeviceIndex].VendorId == EndPointVendorId) ||
+ (DevAspmOverride[PcieDeviceIndex].VendorId == 0xFFFF)) &&
+ ((DevAspmOverride[PcieDeviceIndex].DeviceId == EndPointDeviceId) ||
+ (DevAspmOverride[PcieDeviceIndex].DeviceId == 0xFFFF)) &&
+ ((DevAspmOverride[PcieDeviceIndex].RevId == EndPointRevId) ||
+ (DevAspmOverride[PcieDeviceIndex].RevId == 0xFF)) &&
+ ((DevAspmOverride[PcieDeviceIndex].BaseClassCode == EndPointBaseClassCode) ||
+ (DevAspmOverride[PcieDeviceIndex].BaseClassCode == 0xFF)) &&
+ ((DevAspmOverride[PcieDeviceIndex].SubClassCode == EndPointSubClassCode) ||
+ (DevAspmOverride[PcieDeviceIndex].SubClassCode == 0xFF))) {
+ ///
+ /// Override value of 0xFF applies to all.
+ ///
+ *EndPointAspm = DevAspmOverride[PcieDeviceIndex].EndPointAspm;
+ break;
+ }
+ }
+}
+
+/**
+ This function gets override L1 Substate Capability offset pointer
+ if the end point is found in the override look up table
+
+ @param[in] EndPointBase End Point Base Address
+ @param[in] NumOfDevAspmOverride Number of Device specific ASPM policy override items
+ @param[in] DevAspmOverride Pointer to array of Device specific ASPM policy override items
+ @param[in] EndPointVendorId End Point Vendor Id
+ @param[in] EndPointDeviceId End Point Device Id
+ @param[in] EndPointRevId End Point Revision Id
+ @param[out] EndPointL1SubStateCapOffset Pointer to L1 Substate Capability Structure
+ @param[out] EndPointL1SubStateCapMask L1 Substate Capability Mask
+ @param[out] EndPointL1sCommonModeRestoreTime L1 Substate Port Common Mode Restore Time
+ @param[out] EndPointL1sTpowerOnScale L1 Substate Port Tpower_on Scale
+ @param[out] EndPointL1sTpowerOnValue L1 Substate Port Tpower_on Value
+
+ @retval none
+**/
+
+VOID
+GetOverrideL1sCapOffsetAndValue (
+ IN UINTN EndPointBase,
+ IN UINT32 NumOfDevAspmOverride,
+ IN const PCH_PCIE_DEVICE_OVERRIDE* DevAspmOverride,
+ IN UINT16 EndPointVendorId,
+ IN UINT16 EndPointDeviceId,
+ IN UINT8 EndPointRevId,
+ OUT UINT16 *EndPointL1SubStateCapOffset,
+ OUT UINT8 *EndPointL1SubStateCapMask,
+ OUT UINT8 *EndPointL1sCommonModeRestoreTime,
+ OUT UINT8 *EndPointL1sTpowerOnScale,
+ OUT UINT8 *EndPointL1sTpowerOnValue
+ )
+{
+ UINT8 PcieDeviceIndex;
+ ///
+ /// Get the endpoint supports L1 Substates Capabilities from Override Table
+ ///
+ for (PcieDeviceIndex = 0; PcieDeviceIndex < NumOfDevAspmOverride; PcieDeviceIndex++) {
+ if (((DevAspmOverride[PcieDeviceIndex].OverrideConfig & PchPcieL1SubstatesOverride) == PchPcieL1SubstatesOverride) &&
+ (EndPointVendorId == DevAspmOverride[PcieDeviceIndex].VendorId) &&
+ (EndPointDeviceId == DevAspmOverride[PcieDeviceIndex].DeviceId) &&
+ ((EndPointRevId == DevAspmOverride[PcieDeviceIndex].RevId) ||
+ (DevAspmOverride[PcieDeviceIndex].RevId == 0xFF))) {
+ if ((EndPointVendorId == V_PCH_INTEL_VENDOR_ID) &&
+ ((EndPointDeviceId == 0x08B1) || (EndPointDeviceId == 0x08B2) ||
+ (EndPointDeviceId == 0x08B3) || (EndPointDeviceId == 0x08B4))
+ && ((MmioRead32 (EndPointBase + DevAspmOverride[PcieDeviceIndex].L1SubstatesCapOffset) & 0xFFFF) != 0xCAFE)) {
+ continue;
+ }
+ *EndPointL1SubStateCapOffset = DevAspmOverride[PcieDeviceIndex].L1SubstatesCapOffset;
+ *EndPointL1SubStateCapMask = DevAspmOverride[PcieDeviceIndex].L1SubstatesCapMask & 0x0F;
+ *EndPointL1sCommonModeRestoreTime = DevAspmOverride[PcieDeviceIndex].L1sCommonModeRestoreTime & 0xFF;
+ *EndPointL1sTpowerOnScale = DevAspmOverride[PcieDeviceIndex].L1sTpowerOnScale & 0x03;
+ *EndPointL1sTpowerOnValue = DevAspmOverride[PcieDeviceIndex].L1sTpowerOnValue & 0x1F;
+
+ break;
+ }
+ }
+}
+
+/**
+ This function configures the L1 Substates.
+ It can be used for Rootport and endpoint devices.
+
+ @param[in] DownstreamPort Indicates if the device about to be programmed is a downstream port
+ @param[in] DeviceBase Device PCI configuration base address
+ @param[in] L1SubstateExtCapOffset Pointer to L1 Substate Capability Structure
+ @param[in] PortL1SubstateCapSupport L1 Substate capability setting
+ @param[in] PortCommonModeRestoreTime Common Mode Restore Time
+ @param[in] PortTpowerOnValue Tpower_on Power On Wait Time
+ @param[in] PortTpowerOnScale Tpower-on Scale
+
+ @retval none
+**/
+VOID
+ConfigureL1s (
+ IN BOOLEAN DownstreamPort,
+ IN UINTN DeviceBase,
+ IN UINT16 L1SubstateExtCapOffset,
+ IN UINT32 PortL1SubstateCapSupport,
+ IN UINT32 PortCommonModeRestoreTime,
+ IN UINT32 PortTpowerOnValue,
+ IN UINT32 PortTpowerOnScale
+ )
+{
+ //
+ // For downstream port only:
+ // Program Common Mode Restore Time, but disable L1.2 first
+ //
+ if (DownstreamPort) {
+ MmioAnd32 (
+ DeviceBase + L1SubstateExtCapOffset + R_PCIE_EX_L1SCTL1_OFFSET,
+ (UINT32) ~(BIT2 | BIT0)
+ );
+
+ ///
+ /// b. Read L1 Sub-States Extended Capability Offset + 0x04[15:8], and Set the highest value advertised
+ /// between PCIe rootport and device to L1 Sub-States Extended Capability Offset + 0x08[15:8] on both
+ /// Pcie root port and device.
+ ///
+ MmioAndThenOr32 (
+ DeviceBase + L1SubstateExtCapOffset + R_PCIE_EX_L1SCTL1_OFFSET,
+ (UINT32) ~(0xFF00),
+ (UINT32) PortCommonModeRestoreTime << 8
+ );
+ }
+
+ ///
+ /// PCH BIOS Spec Section 8.3 ASPM on DMI and the PCI Express* Root Ports
+ /// Step 6
+ /// a. Read L1 Sub-States Extended Capability Offset + 0x04[3:0], and set the smallest common subset supported
+ /// by both PCIe rootport and device to L1 Sub-States Extended Capability Offset + 0x08[3:0]
+ ///
+ MmioAndThenOr32 (
+ DeviceBase + L1SubstateExtCapOffset + R_PCIE_EX_L1SCTL1_OFFSET,
+ (UINT32) ~(BIT3 | BIT2 | BIT1 | BIT0),
+ PortL1SubstateCapSupport
+ );
+ ///
+ /// c. Read L1 Sub-States Extended Capability Offset + 0x04[23:19] and [17:16], and Set the highest value
+ /// advertised between PCIe root port and device to L1 Sub-States Extended Capability Offset + 0x0C [7:0] on
+ /// both Pcie root port and device.
+ ///
+ MmioAndThenOr32 (
+ DeviceBase + L1SubstateExtCapOffset + R_PCIE_EX_L1SCTL2_OFFSET,
+ 0xFFFFFF04,
+ (UINT32) ((PortTpowerOnValue << N_PCIE_EX_L1SCTL2_POWT) | PortTpowerOnScale)
+ );
+ ///
+ /// d. Set L1 Sub-States Extended Capability Offset + 0x08[31:29] to 010b for both Pcie root port and device
+ /// e. Set L1 Sub-States Extended Capability Offset + 0x08[25:16] to 0010100000b for both Pcie root port and device
+ ///
+
+ MmioAndThenOr32 (
+ DeviceBase + L1SubstateExtCapOffset + R_PCIE_EX_L1SCTL1_OFFSET,
+ (UINT32) ~(0xE3FF0000),
+ (UINT32) (BIT30 | BIT23 | BIT21)
+ );
+}
+
+/**
+ This function gets the Latency Tolerance Reporting settings from override table
+ if the end point is found in the override look up table
+
+ @param[in] NumOfDevAspmOverride Number of Device specific ASPM policy override items
+ @param[in] DevAspmOverride Pointer to array of Device specific ASPM policy override items
+ @param[in] EndPointVendorId End Point Vendor Id
+ @param[in] EndPointDeviceId End Point Device Id
+ @param[in] EndPointRevId End Point Revision Id
+ @param[in, out] LtrOverrideVal Snoop and Non Snoop Latency Values
+ @param[out] ForceLtrOverride This endpoint needs LTR to be permanently overridden
+
+ @retval none
+**/
+VOID
+GetLtrOverride (
+ IN UINT32 NumOfDevAspmOverride,
+ IN const PCH_PCIE_DEVICE_OVERRIDE* DevAspmOverride,
+ IN UINT16 EndPointVendorId,
+ IN UINT16 EndPointDeviceId,
+ IN UINT8 EndPointRevId,
+ IN OUT UINT32* LtrOverrideVal,
+ OUT UINT8* ForceLtrOverride
+ )
+{
+ UINT8 PcieDeviceIndex;
+ UINT16 Data16;
+ UINT32 Data32;
+ ///
+ /// For each device detected, scan the LTR override table
+ /// If there are endpoints connected directly to the rootport then
+ /// LtrOverrideVal will be replaced by the value from the table for that endpoint
+ /// If there are endpoints that are behind a bridge and that are also part of the table then
+ /// LtrOverrideVal will maintain the minimum of all such values.
+ /// A non zero value of LtrOverrideVal will indicate:
+ /// i):That there is atleast one entry in the LTR override Table
+ /// ii):The final value to be programmed in offset 0x400. This value will be applied for all the devices
+ /// connected to this root port
+ ///
+ Data32 = *LtrOverrideVal;
+ for (PcieDeviceIndex = 0; PcieDeviceIndex < NumOfDevAspmOverride; PcieDeviceIndex++) {
+ if (((DevAspmOverride[PcieDeviceIndex].OverrideConfig & PchPcieLtrOverride) == PchPcieLtrOverride) &&
+ (DevAspmOverride[PcieDeviceIndex].VendorId == EndPointVendorId) &&
+ ((DevAspmOverride[PcieDeviceIndex].DeviceId == EndPointDeviceId) ||
+ (DevAspmOverride[PcieDeviceIndex].DeviceId == 0xFFFF)) &&
+ ((DevAspmOverride[PcieDeviceIndex].RevId == EndPointRevId) ||
+ (DevAspmOverride[PcieDeviceIndex].RevId == 0xFF))) {
+ ///
+ /// Get the Non-Snoop latency value from the table, compare and store the minimum
+ ///
+ if (DevAspmOverride[PcieDeviceIndex].NonSnoopLatency & BIT15) {
+ Data16 = (UINT16) ((Data32 & 0xFFFF0000) >> 16);
+ DetermineLatencyValue (
+ &Data16,
+ DevAspmOverride[PcieDeviceIndex].NonSnoopLatency);
+ Data32 = (Data32 & 0xFFFF) | ((UINT32) (Data16 << 16));
+ }
+ ///
+ /// Get the Snoop latency value from the table, compare and store the minimum
+ ///
+ if (DevAspmOverride[PcieDeviceIndex].SnoopLatency & BIT15) {
+ Data16 = (UINT16) (Data32 & 0xFFFF);
+ DetermineLatencyValue (
+ &Data16,
+ DevAspmOverride[PcieDeviceIndex].SnoopLatency);
+ Data32 = (Data32 & 0xFFFF0000) | (UINT32) Data16;
+ }
+ *LtrOverrideVal = Data32;
+ //
+ // Get the ForceLtrOverride value from table
+ //
+ if (DevAspmOverride[PcieDeviceIndex].ForceLtrOverride == TRUE) {
+ *ForceLtrOverride = TRUE;
+ }
+ break;
+ }
+ }
+ return;
+}
+
+
+/**
+ This function configures the Latency Tolerance Reporting Settings for endpoint devices
+
+ @param[in] RootPortConfig Rootport PCI Express Configuration
+ @param[in] EndPointBus Endpoint Bus Number
+ @param[in] EndPointDevice Endpoint Device Number
+ @param[in] EndPointFunction Endpoint Function Number
+ @param[in] EndPointBase Endpoint PCI Express Address
+ @param[in] EndPointPcieCapOffset Pointer to Endpoint PCI Express Capability Structure
+ @param[in] DeviceCapabilities2 Endpoint Value of Device Capabilities 2 Register (PciE Cap offset + 0x24)
+ @param[in] PchSeries Pch Series
+ @param[in] LtrOverrideVal Snoop and Non Snoop Latency Values
+
+ @retval none
+**/
+VOID
+ConfigureLtr (
+ IN CONST PCH_PCIE_ROOT_PORT_CONFIG* RootPortConfig,
+ IN UINT8 EndPointBus,
+ IN UINT8 EndPointDevice,
+ IN UINT8 EndPointFunction,
+ IN UINTN EndPointBase,
+ IN UINT8 EndPointPcieCapOffset,
+ IN UINT32 DeviceCapabilities2,
+ IN PCH_SERIES PchSeries,
+ IN UINT32* LtrOverrideVal
+ )
+{
+ UINT32 Data32;
+ UINT16 Data16;
+ UINT16 LtrExtendedCapOffset;
+ UINT16 DefaultMaxLatency;
+ DefaultMaxLatency = 0;
+ ///
+ /// PCH BIOS Spec Section 8.15.1 Power Optimizer Configuration
+ /// Step 3
+ /// If Endpoint device supports LTR, Device Capabilities 2 Register Offset 24h [11] = 1b,
+ ///
+ if ((DeviceCapabilities2 & B_PCIE_DCAP2_LTRMS) && (RootPortConfig->LtrEnable == TRUE)) {
+ ///
+ /// PCH BIOS Spec Section 8.15.1 Power Optimizer Configuration
+ /// Step 3.1
+ /// Program Endpoint LTR Mechanism Enable, Device Control 2 Register Offset 28h [10] = 1b
+ /// when device supports LTR but is not found in override table (table listing correct
+ /// latency requirements for devices that supports LTR and also for devices that do not
+ /// support LTR).
+ ///
+ MmioOr16 (EndPointBase + EndPointPcieCapOffset + R_PCIE_DCTL2_OFFSET, B_PCIE_DCTL2_LTREN);
+ }
+ ///
+ /// Get the pointer to the Endpoint PCI Express Extended Capability Structure
+ /// and configure the Max Snoop and Max No-Snoop Latency for the endpoint
+ ///
+ LtrExtendedCapOffset = PcieFindExtendedCapId (EndPointBus,
+ EndPointDevice,
+ EndPointFunction,
+ R_PCH_PCIE_LTRECH_CID);
+ if (LtrExtendedCapOffset != 0) {
+ Data32 = *LtrOverrideVal;
+ ///
+ /// PCH BIOS Spec Section 8.14.1 Power Optimizer Configuration
+ /// Step 3.2
+ /// If B0:Dxx:Fn + 400h is not programmed with snoop latency override value,
+ /// program endpoint max snoop latency register, Latency Tolerance Reporting (LTR)
+ /// Capability Offset 04h [15:0] = 1003h
+
+ DefaultMaxLatency = RootPortConfig->LtrMaxSnoopLatency;
+ Data16 = (UINT16) (Data32 & 0xFFFF);
+ ///
+ /// Set the max snoop latency to either the default max snoop latency or to the snoop latency override value
+ /// that is being programmed for this root port
+ ///
+ DetermineLatencyValue (&Data16, DefaultMaxLatency);
+ MmioAndThenOr16 (EndPointBase + LtrExtendedCapOffset + R_PCH_PCIE_LTRECH_MSLR_OFFSET,
+ (UINT16) (~0x1FFF),
+ Data16);
+ ///
+ /// PCH BIOS Spec Section 8.14.1 Power Optimizer Configuration
+ /// Step 3.3
+ /// If B0:Dxx:Fn + 400h is not programmed with non-snoop latency override value,
+ /// program endpoint max non-snoop Latency Register, Latency Tolerance Reporting (LTR)
+ /// Capability Offset 06h [15:0] = 1003h
+
+ DefaultMaxLatency = RootPortConfig->LtrMaxNoSnoopLatency;
+ Data16 = (UINT16) ((Data32 & 0xFFFF0000) >> 16);
+ DetermineLatencyValue (&Data16, DefaultMaxLatency);
+ MmioAndThenOr16 (
+ EndPointBase + LtrExtendedCapOffset
+ + R_PCH_PCIE_LTRECH_MNSLR_OFFSET,
+ (UINT16) (~0x1FFF),
+ Data16);
+ ///
+ /// Step 4
+ /// If not all devices support LTR
+ /// Program PWRMBASE + 20h = 00010003h
+ /// (Note this register should be saved and restored during S3 transitions)
+ /// Done in PchPcieSmm.c PchPciePmIoTrapSmiCallback ()
+ ///
+ }
+}
+
+/**
+ Calculate/Set EndPoint device Power management settings
+
+ @param[in] RootDeviceBase The Root Port PCI Express address
+ @param[in] RootPcieCapOffset The pointer to the Root Port PCI Express Capability Structure
+ @param[in] EndPointBus The Bus Number of the Endpoint
+ @param[in] NumOfDevAspmOverride Number of Device specific ASPM policy override items
+ @param[in] DevAspmOverride Pointer to array of Device specific ASPM policy override items
+ @param[in, out] LinkAspmVal Resulting Link ASPM value programmed
+ @param[in] Operation Operation Types
+ @param[in, out] LtrOverrideVal Resulting LTR override value to be programmed
+ @param[in] RootL1SubstateExtCapOffset The register offset of Root Port L1 Substates
+ @param[in, out] L1SubstatesSupported Input and return the result of L1 Substates support
+ @param[in, out] PortL1SubstateCapSupport Input and return Capability of L1 Substate setting
+ @param[in, out] PortCommonModeRestoreTime Input and return common mode restore time of L1 Substate setting
+ @param[in, out] PortTpowerOnValue Input and return power on value of L1 Substate setting
+ @param[in, out] PortTpowerOnScale Input and return power on scale of L1 Substate setting
+ @param[in] RootPortConfig Pcie Power Optimizer Configuration
+ @param[in, out] AspmOverride Input and return the Aspm Override enable for pre-1.1 devices
+ @param[in, out] ClkreqPerPortSupported Input to check if clkreq per port is supportted
+ @param[in, out] RpAndEndPointsLtrSupported Input to check if LTR per port is supportted
+ @param[out] ForceLtrOverride One of endpoints needs LTR to be permanently overridden
+
+ @retval EFI_SUCCESS Successfully completed
+ @retval EFI_NOT_FOUND Can not find device
+
+ @retval EFI_OUT_OF_RESOURCES The endpoint device is a bridge, but the Subordinate Bus Number of
+ the root port is not greater than its Secondary Bus Number. You may
+ get this error if PCI emulation is not done before this function gets
+ called and the Policy settings of "TempRootPortBusNumMax" and
+ "TempRootPortBusNumMin" do not provide enough resource for temp bus
+ number usage.
+**/
+EFI_STATUS
+PcieEndPointPm (
+ IN UINTN RootDeviceBase,
+ IN UINT32 RootPcieCapOffset,
+ IN UINT8 EndPointBus,
+ IN UINT32 NumOfDevAspmOverride,
+ IN CONST PCH_PCIE_DEVICE_OVERRIDE *DevAspmOverride,
+ IN OUT UINT16 *LinkAspmVal,
+ IN OPERATION Operation,
+ IN OUT UINT32 *LtrOverrideVal,
+ IN UINT16 RootL1SubstateExtCapOffset,
+ IN OUT BOOLEAN *L1SubstatesSupported,
+ IN OUT UINT32 *PortL1SubstateCapSupport,
+ IN OUT UINT32 *PortCommonModeRestoreTime,
+ IN OUT UINT32 *PortTpowerOnValue,
+ IN OUT UINT32 *PortTpowerOnScale,
+ IN CONST PCH_PCIE_ROOT_PORT_CONFIG *RootPortConfig,
+ IN OUT BOOLEAN *AspmOverride,
+ IN BOOLEAN *ClkreqPerPortSupported,
+ IN OUT BOOLEAN *RpAndEndPointsLtrSupported,
+ OUT UINT8 *ForceLtrOverride
+ )
+{
+ EFI_STATUS Status;
+ UINTN EndPointBase;
+ UINT8 EndPointFunction;
+ UINT8 EndPointPcieCapOffset;
+ UINT16 EndPointAspm;
+ UINT16 EndPointVendorId;
+ UINT16 EndPointDeviceId;
+ UINT8 EndPointRevId;
+ UINT8 DownStreamBusMin;
+ UINT8 ClassCode;
+ UINT8 RootDevSubBusNum;
+ BOOLEAN BusAssign;
+ UINT8 DeviceIndex;
+ UINT8 FunctionIndex;
+ UINT32 DeviceCapabilities2;
+ UINT16 EndPointL1SubStateCapOffset;
+ UINT32 EndPointL1Substates;
+ UINT8 EndPointL1sCommonModeRestoreTime;
+ UINT8 EndPointL1sTpowerOnScale;
+ UINT8 EndPointL1sTpowerOnValue;
+ UINT8 EndPointL1SubStateCapMask;
+ PCH_SERIES PchSeries;
+ BOOLEAN DownstreamPort;
+ UINT16 PcieEndCapOffset;
+ UINT16 PcieEndDeviceType;
+
+ PchSeries = GetPchSeries ();
+
+ DEBUG ((DEBUG_INFO, "PcieEndPointPm () Start EndPointBus %0x\n", EndPointBus));
+ for (DeviceIndex = 0; DeviceIndex <= PCI_MAX_DEVICE; DeviceIndex++) {
+ EndPointBase = MmPciBase (EndPointBus, DeviceIndex, 0);
+ if (MmioRead16 (EndPointBase + PCI_VENDOR_ID_OFFSET) == MAX_UINT16) {
+ continue;
+ }
+ ///
+ /// Check if EndPoint device is Multi-Function Device
+ ///
+ if (MmioRead8 (EndPointBase + PCI_HEADER_TYPE_OFFSET) & HEADER_TYPE_MULTI_FUNCTION) {
+ ///
+ /// If multi-function Device, check function 0-7
+ ///
+ EndPointFunction = PCI_MAX_FUNC;
+ } else {
+ ///
+ /// Otherwise, check function 0 only
+ ///
+ EndPointFunction = 0;
+ }
+
+ for (FunctionIndex = 0; FunctionIndex <= EndPointFunction; FunctionIndex++) {
+ EndPointBase = MmPciBase (EndPointBus, DeviceIndex, FunctionIndex);
+ if (MmioRead16 (EndPointBase + PCI_VENDOR_ID_OFFSET) == MAX_UINT16) {
+ continue;
+ }
+
+ //
+ // Get the pointer to the Endpoint PCI Express Capability Structure.
+ //
+ EndPointPcieCapOffset = PcieFindCapId (EndPointBus, DeviceIndex, FunctionIndex, EFI_PCI_CAPABILITY_ID_PCIEXP);
+ if (EndPointPcieCapOffset == 0) {
+ return EFI_NOT_FOUND;
+ }
+ EndPointVendorId = MmioRead16 (EndPointBase + PCI_VENDOR_ID_OFFSET);
+ EndPointDeviceId = MmioRead16 (EndPointBase + PCI_DEVICE_ID_OFFSET);
+ EndPointRevId = MmioRead8 (EndPointBase + PCI_REVISION_ID_OFFSET);
+
+ EndPointL1SubStateCapOffset = 0;
+ EndPointL1SubStateCapMask = 0;
+ EndPointL1sCommonModeRestoreTime = 0;
+ EndPointL1sTpowerOnScale = 0;
+ EndPointL1sTpowerOnValue = 0;
+ EndPointL1Substates = 0;
+
+ if (RootL1SubstateExtCapOffset != 0) {
+ ///
+ /// Get the endpoint supports L1 Substates Capabilities
+ ///
+ GetOverrideL1sCapOffsetAndValue (
+ EndPointBase,
+ NumOfDevAspmOverride,
+ DevAspmOverride,
+ EndPointVendorId,
+ EndPointDeviceId,
+ EndPointRevId,
+ &EndPointL1SubStateCapOffset,
+ &EndPointL1SubStateCapMask,
+ &EndPointL1sCommonModeRestoreTime,
+ &EndPointL1sTpowerOnScale,
+ &EndPointL1sTpowerOnValue
+ );
+
+ if (EndPointL1SubStateCapOffset == 0) {
+ EndPointL1SubStateCapOffset = PcieFindExtendedCapId (
+ EndPointBus,
+ DeviceIndex,
+ FunctionIndex,
+ V_PCIE_EX_L1S_CID
+ );
+ }
+ if (EndPointL1SubStateCapOffset != 0) {
+ EndPointL1Substates = MmioRead32 (EndPointBase + EndPointL1SubStateCapOffset + R_PCIE_EX_L1SCAP_OFFSET);
+ }
+ }
+
+ DeviceCapabilities2 = MmioRead32 (EndPointBase + EndPointPcieCapOffset + R_PCIE_DCAP2_OFFSET);
+ if (((DeviceCapabilities2 & B_PCIE_DCAP2_LTRMS) == 0) || (RootPortConfig->LtrEnable != TRUE)) {
+ *RpAndEndPointsLtrSupported = FALSE;
+ }
+ ///
+ /// Configure downstream device if present.
+ ///
+ if (Operation == CalculateAspm || Operation == ManualAspm) {
+ if ((MmioRead32 (EndPointBase + EndPointPcieCapOffset + R_PCIE_LCAP_OFFSET) & B_PCIE_LCAP_CPM) != B_PCIE_LCAP_CPM) {
+ *ClkreqPerPortSupported = FALSE;
+ }
+ EndPointAspm = (MmioRead16 (EndPointBase + EndPointPcieCapOffset + R_PCIE_LCAP_OFFSET) >> N_PCIE_LCAP_APMS) & 3;
+ DEBUG ((DEBUG_INFO, "Endpoint Device %0x Capability ASPM: %0x\n", DeviceIndex, EndPointAspm));
+ if (Operation == CalculateAspm) {
+ ///
+ /// Check endpoint for pre-1.1 devices based on the Role based Error Reporting Capability bit
+ /// and enable Aspm Override
+ ///
+ if (!(MmioRead16 (EndPointBase + EndPointPcieCapOffset + R_PCIE_DCAP_OFFSET) & BIT15)) {
+ DEBUG ((DEBUG_INFO, "Override root port ASPM to L1 for pre-1.1 devices\n"));
+ *AspmOverride = TRUE;
+ }
+ GetOverrideAspm (
+ EndPointBase,
+ NumOfDevAspmOverride,
+ DevAspmOverride,
+ EndPointVendorId,
+ EndPointDeviceId,
+ EndPointRevId,
+ &EndPointAspm
+ );
+ AspmCheckExitLatency (
+ EndPointBase,
+ EndPointPcieCapOffset,
+ RootDeviceBase,
+ RootPcieCapOffset,
+ &EndPointAspm
+ );
+ }
+
+ *LinkAspmVal &= EndPointAspm;
+ DEBUG ((DEBUG_INFO, "Calculate Endpoint Device %0x Aspm Value: %0x\n", DeviceIndex, EndPointAspm));
+ ///
+ /// Check if the endpoint supports L1 Substates Capabilities
+ ///
+ if ((EndPointL1SubStateCapOffset != 0) && (RootL1SubstateExtCapOffset != 0)) {
+ ///
+ /// a. Read L1 Sub-States Extended Capability Offset + 0x04[15:8], and program the highest value advertised
+ /// between PCIe rootport and device to L1 Sub-States Extended Capability Offset + 0x08[15:8] on
+ /// Pcie root port.
+ /// b. Read L1 Sub-States Extended Capability Offset + 0x04[23:19] and [17:16], and program the highest value
+ /// advertised between PCIe root port and device.to L1 Sub-States Extended Capability Offset + 0x08 [7:0] on
+ /// both Pcie root port and device.
+ /// c. Program L1 Sub-States Extended Capability Offset + 0x08[31:29] to 010b for both Pcie root port and device
+ /// d. Program L1 Sub-States Extended Capability Offset + 0x08[25:16] to 0010100000b for both Pcie root port and device
+ /// e. Program the L1 PM Sub-States Control 1 Register bits 3:0 to the smallest common subset supported by both sides.
+ ///
+ if (((UINT8) EndPointL1Substates & EndPointL1SubStateCapMask) == EndPointL1SubStateCapMask) {
+ *L1SubstatesSupported = TRUE;
+ if (EndPointL1sTpowerOnValue == 0) {
+ EndPointL1sCommonModeRestoreTime = (EndPointL1Substates >> 8) & 0xFF;
+ EndPointL1sTpowerOnScale = (EndPointL1Substates >> 16) & 0x3;
+ EndPointL1sTpowerOnValue = (EndPointL1Substates >> 19) & 0x1F;
+ }
+
+ if (EndPointL1SubStateCapMask == 0) {
+ *PortL1SubstateCapSupport &= (UINT32) (EndPointL1Substates & 0x0F);
+ } else {
+ *PortL1SubstateCapSupport &= (UINT32) EndPointL1SubStateCapMask;
+ }
+
+ if (EndPointL1sCommonModeRestoreTime > *PortCommonModeRestoreTime) {
+ *PortCommonModeRestoreTime = EndPointL1sCommonModeRestoreTime;
+ }
+
+ if (((UINT32) EndPointL1sTpowerOnValue * mPcieL1sTposMultiplier[EndPointL1sTpowerOnScale]) >
+ (*PortTpowerOnValue * mPcieL1sTposMultiplier[*PortTpowerOnScale])) {
+ *PortTpowerOnValue = EndPointL1sTpowerOnValue;
+ *PortTpowerOnScale = EndPointL1sTpowerOnScale;
+ }
+ }
+ }
+ ///
+ /// For each device detected, scan the LTR override table
+ /// If there are endpoints connected directly to the rootport then
+ /// LtrOverrideVal will be replaced by the value from the table for that endpoint
+ /// If there are endpoints that are behind a bridge and that are also part of the table then
+ /// LtrOverrideVal will maintain the minimum of all such values.
+ /// A non zero value of LtrOverrideVal will indicate:
+ /// i):That there is atleast one entry in the LTR override Table
+ /// ii):The final value to be programmed in offset 0x400. This value will be applied for all the devices
+ /// connected to this root port
+ ///
+ GetLtrOverride (
+ NumOfDevAspmOverride,
+ DevAspmOverride,
+ EndPointVendorId,
+ EndPointDeviceId,
+ EndPointRevId,
+ LtrOverrideVal,
+ ForceLtrOverride
+ );
+ } else if (Operation == SetAspm) {
+ if ((EndPointL1SubStateCapOffset != 0) && (*L1SubstatesSupported)) {
+ ///
+ /// a. Read L1 Sub-States Extended Capability Offset + 0x04[15:8], and program the highest value advertised
+ /// between PCIe rootport and device to L1 Sub-States Extended Capability Offset + 0x08[15:8] on
+ /// Pcie root port.
+ /// b. Read L1 Sub-States Extended Capability Offset + 0x04[23:19] and [17:16], and program the highest value
+ /// advertised between PCIe root port and device.to L1 Sub-States Extended Capability Offset + 0x08 [7:0] on
+ /// both Pcie root port and device.
+ /// c. Program L1 Sub-States Extended Capability Offset + 0x08[31:29] to 010b for both Pcie root port and device
+ /// d. Program L1 Sub-States Extended Capability Offset + 0x08[25:16] to 0010100000b for both Pcie root port and device
+ /// e. Program the L1 PM Sub-States Control 1 Register bits 3:0 to the smallest common subset supported by both sides.
+ ///
+ if ((((UINT8) EndPointL1Substates & EndPointL1SubStateCapMask) == EndPointL1SubStateCapMask)) {
+
+ //
+ // Check if current device is a downstream port
+ //
+ DownstreamPort = FALSE;
+ PcieEndCapOffset = PcieFindCapId (EndPointBus, DeviceIndex, FunctionIndex, EFI_PCI_CAPABILITY_ID_PCIEXP);
+ if ((MmioRead8 (EndPointBase + R_PCI_BCC_OFFSET) == PCI_CLASS_BRIDGE) && (PcieEndCapOffset != 0)) {
+ PcieEndDeviceType = (MmioRead16 (EndPointBase + PcieEndCapOffset + R_PCIE_XCAP_OFFSET) & B_PCIE_XCAP_DT) >> N_PCIE_XCAP_DT;
+ if (PcieEndDeviceType == 0x06) {
+ DownstreamPort = TRUE;
+ }
+ }
+ ConfigureL1s (
+ DownstreamPort,
+ EndPointBase,
+ EndPointL1SubStateCapOffset,
+ *PortL1SubstateCapSupport,
+ *PortCommonModeRestoreTime,
+ *PortTpowerOnValue,
+ *PortTpowerOnScale
+ );
+ }
+ }
+ ///
+ /// Write it to the Link Control register
+ ///
+ DEBUG ((DEBUG_INFO, "Program Endpoint Device %0x Aspm Value: %0x\n", DeviceIndex, *LinkAspmVal));
+ MmioAndThenOr16 (EndPointBase + EndPointPcieCapOffset + R_PCIE_LCTL_OFFSET, (UINT16) ~B_PCIE_LCTL_ASPM, *LinkAspmVal);
+ ///
+ /// PCH BIOS Spec Section 8.14.1 Power Optimizer Configuration
+ /// Step 3
+ ///
+ ConfigureLtr (
+ RootPortConfig,
+ EndPointBus,
+ DeviceIndex,
+ FunctionIndex,
+ EndPointBase,
+ EndPointPcieCapOffset,
+ DeviceCapabilities2,
+ PchSeries,
+ LtrOverrideVal
+ );
+ }
+ ///
+ /// Check if this device is a bridge
+ ///
+ ClassCode = MmioRead8 (EndPointBase + R_PCI_BCC_OFFSET);
+
+ if (ClassCode == PCI_CLASS_BRIDGE) {
+ ///
+ /// Get the downstream Bus number
+ ///
+ DownStreamBusMin = MmioRead8 (EndPointBase + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET);
+ ///
+ /// If the Secondary Bus Number of endpoint device is not assigned
+ ///
+ if (DownStreamBusMin == 0) {
+ RootDevSubBusNum = MmioRead8 (RootDeviceBase + PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET);
+ ///
+ /// If the endpoint device is a bridge, the Subordinate Bus Number of the root port will need to be greater
+ /// than the Secondary Bus Number of the root port (the Bus Number of endpoint device).
+ ///
+ if (RootDevSubBusNum > EndPointBus) {
+ ///
+ /// Assign the Primary, Secondary and Subordinate Bus Number to endpoint device
+ ///
+ MmioAndThenOr32 (
+ EndPointBase + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET,
+ 0xFF000000,
+ EndPointBus | (((UINT32) (EndPointBus + 1) << 8)) | ((UINT32) (RootDevSubBusNum << 16))
+ );
+ DownStreamBusMin = EndPointBus + 1;
+ } else {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ BusAssign = FALSE;
+ } else {
+ BusAssign = TRUE;
+ }
+
+ if (DownStreamBusMin > EndPointBus) {
+ Status = PcieEndPointPm (
+ RootDeviceBase,
+ RootPcieCapOffset,
+ DownStreamBusMin,
+ NumOfDevAspmOverride,
+ DevAspmOverride,
+ LinkAspmVal,
+ Operation,
+ LtrOverrideVal,
+ RootL1SubstateExtCapOffset,
+ L1SubstatesSupported,
+ PortL1SubstateCapSupport,
+ PortCommonModeRestoreTime,
+ PortTpowerOnValue,
+ PortTpowerOnScale,
+ RootPortConfig,
+ AspmOverride,
+ ClkreqPerPortSupported,
+ RpAndEndPointsLtrSupported,
+ ForceLtrOverride
+ );
+ if (Status == EFI_NOT_FOUND) {
+ DEBUG ((DEBUG_INFO, "Check DownStreamBus:%d and no device found!\n", DownStreamBusMin));
+ }
+
+ if (BusAssign == FALSE) {
+ ///
+ /// Clear Bus Numbers.
+ ///
+ MmioAnd32 (EndPointBase + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET, 0xFF000000);
+ }
+ }
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Initializes the root port and its down stream devices
+
+ @param[in] RootPortBus Pci Bus Number of the root port
+ @param[in] RootPortDevice Pci Device Number of the root port
+ @param[in] RootPortFunc Pci Function Number of the root port
+ @param[in] CurrentPortBus Pci Bus Number of the current port. Can be a root port or Switch Upstream/Downstream port
+ @param[in] CurrentPortDevice Pci Device Number of the current port. Can be a root port or Switch Upstream/Downstream port
+ @param[in] CurrentPortFunc Pci Function Number of the current port. Can be a root port or Switch Upstream/Downstream port
+ @param[in] TempBusNumberMin Minimal temp bus number that can be assigned to the root port (as secondary
+ bus number) and its down stream switches
+ @param[in] TempBusNumberMax Maximal temp bus number that can be assigned to the root port (as subordinate
+ bus number) and its down stream switches
+ @param[in, out] MaxPayload The Max Payolad Size of the root port
+ @param[in] SetConfig FALSE to Get information or TRUE to set configuration
+ @param[in] EnableCpm Enables Clock Power Management; even if disabled, CLKREQ# can still be used by L1 PM substates mechanism
+
+ @retval EFI_SUCCESS Successfully completed
+ @retval EFI_NOT_FOUND Can not find device.
+**/
+EFI_STATUS
+PchPcieInitDownstreamDevices (
+ IN UINT8 RootPortBus,
+ IN UINT8 RootPortDevice,
+ IN UINT8 RootPortFunc,
+ IN UINT8 CurrentPortBus,
+ IN UINT8 CurrentPortDevice,
+ IN UINT8 CurrentPortFunc,
+ IN UINT8 TempBusNumberMin,
+ IN UINT8 TempBusNumberMax,
+ IN OUT UINT16 *MaxPayload,
+ IN BOOLEAN SetConfig,
+ IN BOOLEAN EnableCpm
+ )
+{
+ UINT32 Index;
+ UINTN CurrentDeviceBase;
+ UINTN EndPointBase;
+ UINT8 EndPointBus;
+ UINT8 PcieCapOffset;
+ UINT8 PcieDeviceType;
+ UINT8 PcieEndCapOffset;
+ UINT8 PcieEndDeviceType;
+ UINT16 SlotStatus;
+ DEBUG ((DEBUG_INFO,"PchPcieInitDownstreamDevices RootBDF %0x : %0x :%0x\n",RootPortBus, RootPortDevice, RootPortFunc));
+ DEBUG ((DEBUG_INFO,"PchPcieInitDownstreamDevices CurrentBDF %0x : %0x :%0x\n",CurrentPortBus, CurrentPortDevice, CurrentPortFunc));
+ DEBUG ((DEBUG_INFO,"PchPcieInitDownstreamDevices TempBusMin %0x , TempBusMax %0x\n",TempBusNumberMin, TempBusNumberMax));
+ DEBUG ((DEBUG_INFO,"PchPcieInitDownstreamDevices MaxPayLoad %0x\n", *MaxPayload));
+ CurrentDeviceBase = MmPciBase (CurrentPortBus, CurrentPortDevice, CurrentPortFunc);
+ ///
+ /// Get the downstream Bus number
+ ///
+ EndPointBus = MmioRead8 (CurrentDeviceBase + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET);
+ ///
+ /// If the Secondary Bus Number of the root port is not assigned,
+ /// then temporarily Hardcode the Root Port Bridge Number to TempBusNumberMin,
+ /// otherwise use the assigned Bus Number
+ ///
+ if (EndPointBus == 0) {
+ MmioAndThenOr32 (
+ CurrentDeviceBase + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET,
+ 0xFF000000,
+ CurrentPortBus | ((UINT32) (TempBusNumberMin << 8)) | ((UINT32) (TempBusNumberMax << 16))
+ );
+ } else {
+ TempBusNumberMin = EndPointBus;
+ TempBusNumberMax = MmioRead8 (CurrentDeviceBase + PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET);
+ }
+ PcieCapOffset = PcieFindCapId (
+ CurrentPortBus,
+ CurrentPortDevice,
+ CurrentPortFunc,
+ EFI_PCI_CAPABILITY_ID_PCIEXP
+ );
+ PcieDeviceType = (UINT8) ((MmioRead16 (CurrentDeviceBase + PcieCapOffset + R_PCIE_XCAP_OFFSET) & B_PCIE_XCAP_DT) >> N_PCIE_XCAP_DT);
+
+ ///
+ /// Skip this section if Upstream device
+ ///
+ if ((PcieDeviceType != 0x05) ||
+ ((MmioRead8 (CurrentDeviceBase + PCI_HEADER_TYPE_OFFSET) & HEADER_LAYOUT_CODE) == HEADER_TYPE_DEVICE)) {
+ ///
+ /// This Endpoint check should immediately pass.
+ /// Completion Retry Status Replay Enable is set in PchRootPorts.c PchInitRootPorts ()
+ /// to bypass the timing requirements of the PCI Express Base
+ /// Specification, Revision 1.0A, Section 6.6 ("...software must allow 1.0s
+ /// after a reset of a device, before it may determine that a device which
+ /// fails to return a Successful Completion status for a valid Configuration
+ /// Request is a broken device").
+ ///
+ EndPointBase = MmPciBase (TempBusNumberMin, 0, 0);
+ ///
+ /// A config write is required in order for the device to re-capture the Bus number,
+ /// according to PCI Express Base Specification, 2.2.6.2 ("Note that the Bus Number
+ /// and Device Number may be changed at run time, and so it is necessary to re-capture
+ /// this information with each and every Configuration Write Request")
+ ///
+ MmioWrite8 (EndPointBase + 0x0, 0);
+
+ if (MmioRead16 (EndPointBase + PCI_VENDOR_ID_OFFSET) == MAX_UINT16) {
+ ///
+ /// Clear Bus Numbers.
+ ///
+ if (EndPointBus == 0) {
+ MmioAnd32 (CurrentDeviceBase + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET, 0xFF000000);
+ }
+ return EFI_NOT_FOUND;
+ }
+ }
+ for (Index = 0; Index <= PCI_MAX_DEVICE; Index++) {
+ EndPointBase = MmPciBase (TempBusNumberMin, Index, 0);
+ if (MmioRead16 (EndPointBase + PCI_VENDOR_ID_OFFSET) == MAX_UINT16) {
+ continue;
+ }
+
+ if (!SetConfig) {
+ ///
+ /// Get the Max Payload Size on all the end point functions
+ ///
+ PcieMaxPayloadSize (TempBusNumberMin, (UINT8) Index, MaxPayload, FALSE);
+ }
+
+ PcieEndCapOffset = PcieFindCapId (
+ TempBusNumberMin,
+ (UINT8) Index,
+ 0,
+ EFI_PCI_CAPABILITY_ID_PCIEXP
+ );
+
+ ///
+ /// Check if this device is a bridge
+ /// Pcie to Pci/PciX bridges are skipped
+ ///
+ if ((MmioRead8 (EndPointBase + R_PCI_BCC_OFFSET) == PCI_CLASS_BRIDGE) && (PcieEndCapOffset != 0)) {
+ DEBUG ((DEBUG_INFO,"PchPcieInitDownstreamDevices Bridge Detected\n"));
+ PcieEndDeviceType = (UINT8) ((MmioRead16 (EndPointBase + PcieEndCapOffset + R_PCIE_XCAP_OFFSET) & B_PCIE_XCAP_DT) >> N_PCIE_XCAP_DT);
+ SlotStatus = MmioRead16 (EndPointBase + PcieEndCapOffset + R_PCIE_SLSTS_OFFSET);
+
+ ///
+ /// Initialize the downstream device in following conditions:
+ /// PcieDeviceType is 5 (endpoint is an upstream device).
+ /// PcieDeviceType is 6 (endpoint is a downstream device). And the slot has a device.
+ ///
+ if ((PcieEndDeviceType == 0x05) || ((PcieEndDeviceType == 0x06) && ((SlotStatus & B_PCIE_SLSTS_PDS) != 0))) {
+ ///
+ /// Initialize downstream devices
+ ///
+ if (TempBusNumberMax > TempBusNumberMin) {
+ PchPcieInitDownstreamDevices (
+ RootPortBus,
+ RootPortDevice,
+ RootPortFunc,
+ TempBusNumberMin,
+ (UINT8) Index,
+ 0,
+ TempBusNumberMin + 1,
+ TempBusNumberMax,
+ MaxPayload,
+ SetConfig,
+ EnableCpm
+ );
+ } else {
+ ASSERT (FALSE);
+ }
+ }
+ }
+
+ if (SetConfig) {
+ ///
+ /// Disable the forwarding of EOI messages unless it discovers an IOAPIC behind this root port
+ ///
+ if (CurrentPortBus == DEFAULT_PCI_BUS_NUMBER_PCH) {
+ PcieSetEoiFwdDisable (CurrentPortBus, CurrentPortDevice, CurrentPortFunc, TempBusNumberMin, (UINT8) Index);
+ }
+
+ ///
+ /// Set Common Clock for inserted cards
+ ///
+ ///
+ /// PCH BIOS Spec Section 8.3 ASPM on DMI and the PCI Express* Root Ports
+ /// Before determining whether ASPM can be enabled or not,
+ /// the System BIOS must perform the following steps:
+ ///
+ /// For PCH H
+ /// 1. Update the Link Capabilities of the DMI link to indicate L0s/L1 is
+ /// supported by programming the LCAP Register,
+ /// PCR[DMI] + 21A4h[11:10] = 11b. (for PCH with DMI ONLY)
+ /// (Done in PchDmiPei.c)
+ ///
+ /// 2. Enable L0s on DMI for Desktop platforms by setting the APMC field,
+ /// PCR[DMI] + 21A8h[1:0] to 01b.
+ /// Enable L0s/L1 on DMI by setting PCR[DMI] + 21A8h[1:0] to 11b. (for PCH with DMI ONLY)
+ /// (Done in PchDmiPei.c)
+ ///
+ /// 3. For each root port, read the Slot Clock Configuration bit, Dxx:Fn:52h[12],
+ /// of the root port and the endpoint device connected to the port (i.e., D0:F0 on the
+ /// secondary bus behind the root port). If both components have this bit set, then the
+ /// System BIOS should set the Common Clock Configuration (CCC) bit, Dxx:Fn:50h[6],
+ /// for both components at both sides of the link to indicate that components at both ends
+ /// of the link use a common clock source.
+ ///
+ /// 4. If the CCC bit was changed by the System BIOS in step 3, System BIOS should initiate
+ /// a link training by setting the Retrain Link (RL) bit, Dxx:Fn:50h[5], and then poll the Link
+ /// Training (LT) bit, Dxx:Fn:52h[11], until it is clear.
+ /// Note that System BIOS should save and restore CCC bit on S3.
+ ///
+ PcieSetCommonClock (CurrentPortBus, CurrentPortDevice, CurrentPortFunc, TempBusNumberMin, (UINT8) Index);
+
+ ///
+ /// Enable the PCIe CLKREQ#
+ ///
+ if (EnableCpm) {
+ PcieSetClkreq (TempBusNumberMin, (UINT8) Index, RootPortDevice, RootPortFunc);
+ }
+
+ ///
+ /// Set the Max Payload Size on all the end point functions
+ ///
+ PcieMaxPayloadSize (TempBusNumberMin, (UINT8) Index, MaxPayload, TRUE);
+ }
+ }
+
+ ///
+ /// Clear Bus Numbers if it's not assigned yet
+ ///
+ if (EndPointBus == 0) {
+ MmioAnd32 (CurrentDeviceBase + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET, 0xFF000000);
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Initializes the root port and its down stream devices
+
+ @param[in] RootPortBus Pci Bus Number of the root port
+ @param[in] RootPortDevice Pci Device Number of the root port
+ @param[in] RootPortFunc Pci Function Number of the root port
+ @param[in] TempBusNumberMin Minimal temp bus number that can be assigned to the root port (as secondary
+ bus number) and its down stream switches
+ @param[in] TempBusNumberMax Maximal temp bus number that can be assigned to the root port (as subordinate
+ bus number) and its down stream switches
+ @param[in] EnableCpm Enables Clock Power Management; even if disabled, CLKREQ# can still be used by L1 PM substates mechanism
+
+ @retval EFI_SUCCESS Successfully completed
+ @retval EFI_NOT_FOUND Can not find device.
+**/
+EFI_STATUS
+PchPcieInitRootPortDownstreamDevices (
+ IN UINT8 RootPortBus,
+ IN UINT8 RootPortDevice,
+ IN UINT8 RootPortFunc,
+ IN UINT8 TempBusNumberMin,
+ IN UINT8 TempBusNumberMax,
+ IN BOOLEAN EnableCpm
+ )
+{
+ UINT16 SlotStatus;
+ UINTN RpBase;
+ UINT16 MaxPayload;
+ UINT8 PcieCapOffset;
+ EFI_STATUS Status;
+ UINT8 CurrentPortBus;
+ UINT8 CurrentPortDevice;
+ UINT8 CurrentPortFunc;
+ UINT32 Timeout;
+
+
+ RpBase = MmPciBase (RootPortBus, RootPortDevice, RootPortFunc);
+ ///
+ /// Check for a Presence Detect Change.
+ ///
+ SlotStatus = MmioRead16 (RpBase + R_PCH_PCIE_SLSTS);
+
+ ///
+ /// Check whether the slot has a device connected
+ ///
+ if ((SlotStatus & B_PCIE_SLSTS_PDS) == 0) {
+ return EFI_NOT_FOUND;
+ }
+ ///
+ /// Make sure the link is active before trying to talk to device behind it
+ /// Wait up to 100ms, according to PCIE spec chapter 6.7.3.3
+ ///
+ Timeout = 100 * 1000;
+ while ((MmioRead16 (RpBase + R_PCH_PCIE_LSTS) & B_PCIE_LSTS_LA) == 0 ) {
+ MicroSecondDelay (10);
+ Timeout-=10;
+ if (Timeout == 0) {
+ return EFI_NOT_FOUND;
+ }
+ }
+ ///
+ /// Get the pointer to the Endpoint PCI Express Capability Structure.
+ ///
+ PcieCapOffset = PcieFindCapId (
+ RootPortBus,
+ RootPortDevice,
+ RootPortFunc,
+ EFI_PCI_CAPABILITY_ID_PCIEXP
+ );
+ if (PcieCapOffset == 0) {
+ DEBUG ((DEBUG_INFO,"PcieCapOffset Not Found"));
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Get the root port Max Payload Size support
+ //
+ MaxPayload = MmioRead16 (RpBase + PcieCapOffset + R_PCIE_DCAP_OFFSET) & B_PCIE_DCAP_MPS;
+
+ ///
+ /// Initialize downstream devices
+ ///
+ CurrentPortBus = RootPortBus;
+ CurrentPortDevice = RootPortDevice;
+ CurrentPortFunc = RootPortFunc;
+
+ //
+ // Get configuration from all downstreams
+ //
+ // In current implementation, only the MaxPayloadSize need to be calculated.
+ // Therefore, for performance, skip the calculation if the MaxPayloadSize is already minimum.
+ //
+ if (MaxPayload != 0) {
+ Status = PchPcieInitDownstreamDevices (
+ RootPortBus,
+ RootPortDevice,
+ RootPortFunc,
+ CurrentPortBus,
+ CurrentPortDevice,
+ CurrentPortFunc,
+ TempBusNumberMin,
+ TempBusNumberMax,
+ &MaxPayload,
+ FALSE,
+ EnableCpm
+ );
+ }
+ //
+ // Set configuration to all downstreams
+ //
+ Status = PchPcieInitDownstreamDevices (
+ RootPortBus,
+ RootPortDevice,
+ RootPortFunc,
+ CurrentPortBus,
+ CurrentPortDevice,
+ CurrentPortFunc,
+ TempBusNumberMin,
+ TempBusNumberMax,
+ &MaxPayload,
+ TRUE,
+ EnableCpm
+ );
+ return Status;
+}
+
+/**
+ Get current PCIe link speed.
+
+ @param[in] RpBase Root Port base address
+ @return Link speed
+**/
+UINT32
+GetLinkSpeed (
+ UINTN RpBase
+ )
+{
+ return MmioRead16 (RpBase + R_PCH_PCIE_LSTS) & B_PCIE_LSTS_CLS;
+}
+
+/**
+ Get max PCIe link speed supported by the root port.
+
+ @param[in] RpBase Root Port base address
+ @return Max link speed
+**/
+UINT32
+GetMaxLinkSpeed (
+ UINTN RpBase
+ )
+{
+ return MmioRead32 (RpBase + R_PCH_PCIE_LCAP) & B_PCIE_LCAP_MLS;
+}
+
+/**
+ Get Pch Maximum Pcie Controller Number
+
+ @retval Pch Maximum Pcie Controller Number
+**/
+UINT8
+EFIAPI
+GetPchMaxPcieControllerNum (
+ VOID
+ )
+{
+ if (GetPchSeries () == PchLp) {
+ return PCH_LP_PCIE_MAX_CONTROLLERS;
+ } else {
+ if (GetPchGeneration () == KblPch) {
+ return KBL_PCH_H_PCIE_MAX_CONTROLLERS;
+ } else {
+ return SKL_PCH_H_PCIE_MAX_CONTROLLERS;
+ }
+ }
+}
+
+/**
+ PCIe controller configuration strings.
+**/
+GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8* mPcieControllerConfigName[] = {
+ "4x1",
+ "1x2-2x1",
+ "2x2",
+ "1x4"
+};
+
+/**
+ Returns the PCIe controller configuration (4x1, 1x2-2x1, 2x2, 1x4)
+
+ @param[in] ControllerIndex Number of PCIe controller (0 based)
+
+ @retval PCIe controller configuration
+**/
+PCIE_CONTROLLER_CONFIG
+GetPcieControllerConfig (
+ IN UINT32 ControllerIndex
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Data32;
+ PCIE_CONTROLLER_CONFIG Config;
+ UINT32 FirstRp;
+
+ FirstRp = ControllerIndex * PCH_PCIE_CONTROLLER_PORTS;
+
+ Status = PchSbiRpPciRead32 (FirstRp, R_PCH_PCIE_STRPFUSECFG, &Data32);
+ ASSERT_EFI_ERROR (Status);
+
+ Config = ((Data32 & B_PCH_PCIE_STRPFUSECFG_RPC) >> N_PCH_PCIE_STRPFUSECFG_RPC);
+ DEBUG ((DEBUG_INFO, "PCIe SP%c is %a\n", (UINTN) ('A' + ControllerIndex), mPcieControllerConfigName[Config]));
+ return Config;
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchPciExpressHelpersLib/PchPciExpressHelpersLibrary.h b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchPciExpressHelpersLib/PchPciExpressHelpersLibrary.h
new file mode 100644
index 0000000000..bd59b5346e
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchPciExpressHelpersLib/PchPciExpressHelpersLibrary.h
@@ -0,0 +1,45 @@
+/** @file
+ Header file for PCH Pci Express helps library implementation.
+
+Copyright (c) 2017, 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_PCI_EXPRESS_HELPERS_LIBRARY_H_
+#define _PCH_PCI_EXPRESS_HELPERS_LIBRARY_H_
+
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <IndustryStandard/Pci30.h>
+#include <PchPolicyCommon.h>
+#include <PchAccess.h>
+#include <Library/PchPcieRpLib.h>
+#include <Library/PchPcrLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/MmPciLib.h>
+#include <Library/GpioNativeLib.h>
+#include <Library/TimerLib.h>
+#include <Library/PchPciExpressHelpersLib.h>
+#include <Library/PchPsfPrivateLib.h>
+#include <Library/PchInitCommonLib.h>
+
+#define LTR_VALUE_MASK (BIT0 + BIT1 + BIT2 + BIT3 + BIT4 + BIT5 + BIT6 + BIT7 + BIT8 + BIT9)
+#define LTR_SCALE_MASK (BIT10 + BIT11 + BIT12)
+
+ #define CONFIG_WRITE_LOOP_COUNT 100000
+
+//
+// LTR related macros
+//
+#define LTR_LATENCY_VALUE(x) ((x) & LTR_VALUE_MASK)
+#define LTR_SCALE_VALUE(x) (((x) & LTR_SCALE_MASK) >> 10)
+#define LTR_LATENCY_NS(x) (LTR_LATENCY_VALUE(x) * (1 << (5 * LTR_SCALE_VALUE(x))))
+
+#endif
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchPciExpressHelpersLib/PeiDxeSmmPchPciExpressHelpersLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchPciExpressHelpersLib/PeiDxeSmmPchPciExpressHelpersLib.inf
new file mode 100644
index 0000000000..b02f311f02
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchPciExpressHelpersLib/PeiDxeSmmPchPciExpressHelpersLib.inf
@@ -0,0 +1,52 @@
+## @file
+# Component description file for the PeiDxeSmmPchPciExpressHelpersLib
+#
+# Copyright (c) 2017, 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 = PeiDxeSmmPchPciExpressHelpersLib
+FILE_GUID = 07E3F76D-6D26-419d-9053-58696A15B519
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = PchPciExpressHelpersLib
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+
+
+[LibraryClasses]
+IoLib
+DebugLib
+PchPcieRpLib
+PchPcrLib
+PchInfoLib
+GpioLib
+TimerLib
+PchPsfPrivateLib
+PchInitCommonLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+KabylakeSiliconPkg/KabylakeSiliconPrivate.dec
+
+
+[Sources]
+PchPciExpressHelpersLibrary.c
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchPsfPrivateLib/PchPsfPrivateLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchPsfPrivateLib/PchPsfPrivateLib.c
new file mode 100644
index 0000000000..ef579c825d
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchPsfPrivateLib/PchPsfPrivateLib.c
@@ -0,0 +1,1169 @@
+/** @file
+ This file contains PSF routines for RC usage
+
+Copyright (c) 2017, 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/BaseMemoryLib.h>
+#include <PchAccess.h>
+#include <Library/PchPcrLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/PchPsfPrivateLib.h>
+#include <Library/PchPciExpressHelpersLib.h>
+#include <Library/S3BootScriptLib.h>
+
+/**
+ This procedure will disable CIO2 device at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfDisableCio2Device (
+ VOID
+ )
+{
+ PchPcrAndThenOr32 (
+ PID_PSF1,
+ R_PCH_LP_PCR_PSF1_T0_SHDW_CAM_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_PCIEN,
+ 0xFFFFFFFF,
+ B_PCH_PCR_PSFX_T0_SHDW_PCIEN_FUNDIS
+ );
+}
+
+/**
+ Hide CIO2 devices PciCfgSpace at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfHideCio2Device (
+ VOID
+ )
+{
+ PchPcrAndThenOr32 (
+ PID_PSF1,
+ R_PCH_LP_PCR_PSF1_T0_SHDW_CAM_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_CFG_DIS,
+ (UINT32) ~0,
+ B_PCH_PCR_PSFX_T0_SHDW_CFG_DIS_CFGDIS
+ );
+}
+
+/**
+ Disable HDAudio device at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfDisableHdaDevice (
+ VOID
+ )
+{
+ PchPcrAndThenOr32 (
+ PID_PSF3,
+ R_PCH_PCR_PSF3_T0_SHDW_AUD_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_PCIEN,
+ (UINT32) ~0,
+ B_PCH_PCR_PSFX_T0_SHDW_PCIEN_FUNDIS
+ );
+}
+
+/**
+ Disable xDCI device at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfDisableXdciDevice (
+ VOID
+ )
+{
+ UINT16 RegOffset;
+
+ if (GetPchSeries () == PchLp) {
+ RegOffset = R_PCH_LP_PCR_PSF2_T0_SHDW_OTG_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_PCIEN;
+ } else {
+ RegOffset = R_PCH_H_PCR_PSF2_T0_SHDW_OTG_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_PCIEN;
+ }
+
+ PchPcrAndThenOr32 (
+ PID_PSF2,
+ RegOffset,
+ ~0u,
+ B_PCH_PCR_PSFX_T0_SHDW_PCIEN_FUNDIS
+ );
+}
+
+/**
+ Disable xHCI device at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfDisableXhciDevice (
+ VOID
+ )
+{
+ UINT16 RegOffset;
+
+ if (GetPchSeries () == PchLp) {
+ RegOffset = R_PCH_LP_PCR_PSF2_T0_SHDW_XHCI_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_PCIEN;
+ } else {
+ RegOffset = R_PCH_H_PCR_PSF2_T0_SHDW_XHCI_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_PCIEN;
+ }
+
+ PchPcrAndThenOr32 (
+ PID_PSF2,
+ RegOffset,
+ ~0u,
+ B_PCH_PCR_PSFX_T0_SHDW_PCIEN_FUNDIS
+ );
+}
+
+/**
+ Disable SATA device at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfDisableSataDevice (
+ VOID
+ )
+{
+ UINT16 RegOffset;
+
+ if (GetPchSeries () == PchLp) {
+ RegOffset = R_PCH_LP_PCR_PSF1_T0_SHDW_SATA_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_PCIEN;
+ } else {
+ RegOffset = R_PCH_H_PCR_PSF1_T0_SHDW_SATA_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_PCIEN;
+ }
+
+ PchPcrAndThenOr32 (
+ PID_PSF1,
+ RegOffset,
+ ~0u,
+ B_PCH_PCR_PSFX_T0_SHDW_PCIEN_FUNDIS
+ );
+}
+
+/**
+ Disable ISH device at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfDisableIshDevice (
+ VOID
+ )
+{
+ PchPcrAndThenOr32 (
+ PID_PSF3,
+ R_PCH_PCR_PSF3_T0_SHDW_ISH_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_PCIEN,
+ ~0u,
+ B_PCH_PCR_PSFX_T0_SHDW_PCIEN_FUNDIS
+ );
+}
+
+/**
+ Disable ISH BAR1 at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfDisableIshBar1 (
+ VOID
+ )
+{
+ //
+ // Set AGNT_T0_SHDW_PCIEN[19:18] = 11b
+ // ISH device BAR is 64bit wide so to disable BAR1
+ // at PSF both BAR2 (32bit wide) and BAR3 (32bit wide) need to be disabled
+ //
+ PchPcrAndThenOr32 (
+ PID_PSF3,
+ R_PCH_PCR_PSF3_T0_SHDW_ISH_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_PCIEN,
+ (UINT32) ~0,
+ (B_PCH_PCR_PSFX_T0_SHDW_PCIEN_BAR2DIS | B_PCH_PCR_PSFX_T0_SHDW_PCIEN_BAR3DIS)
+ );
+}
+
+/**
+ Disable GbE device at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfDisableGbeDevice (
+ VOID
+ )
+{
+ UINT16 RegOffset;
+ PCH_SBI_PID PortId;
+
+ if (GetPchSeries () == PchLp) {
+ PortId = PID_PSF1;
+ RegOffset = R_PCH_LP_PCR_PSF1_T0_SHDW_GBE_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_PCIEN;
+ } else {
+ PortId = PID_PSF3;
+ RegOffset = R_PCH_H_PCR_PSF3_T0_SHDW_GBE_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_PCIEN;
+ }
+
+ PchPcrAndThenOr32 (
+ PortId,
+ RegOffset,
+ ~0u,
+ B_PCH_PCR_PSFX_T0_SHDW_PCIEN_FUNDIS
+ );
+}
+
+/**
+ Disable SMBUS device at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfDisableSmbusDevice (
+ VOID
+ )
+{
+ ///
+ /// Hide SMBUS device
+ /// Set PCR[PSF_3] + "AGNT_T0_SHDW_CFG_DIS"[SMBUS][0]
+ ///
+ PchPcrAndThenOr32 (
+ PID_PSF3,
+ R_PCH_PCR_PSF3_T0_SHDW_SMBUS_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_CFG_DIS,
+ (UINT32) ~0,
+ B_PCH_PCR_PSFX_T0_SHDW_CFG_DIS_CFGDIS
+ );
+
+ ///
+ /// Function disable SMBUS device
+ /// Set PCR[PSF_3] + "AGNT_T0_SHDW_PCIEN"[SMBUS][8]
+ ///
+ PchPcrAndThenOr32 (
+ PID_PSF3,
+ R_PCH_PCR_PSF3_T0_SHDW_SMBUS_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_PCIEN,
+ (UINT32) ~0,
+ B_PCH_PCR_PSFX_T0_SHDW_PCIEN_FUNDIS
+ );
+}
+
+/**
+ Disable Thermal device at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfDisableThermalDevice (
+ VOID
+ )
+{
+ ///
+ /// Set PCR[PSF2] TRH PCIEN[8] to 1
+ ///
+ PchPcrAndThenOr32 (
+ PID_PSF2, R_PCH_PCR_PSF2_T0_SHDW_TRH_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_PCIEN,
+ (UINT32) ~0,
+ B_PCH_PCR_PSFX_T0_SHDW_PCIEN_FUNDIS
+ );
+}
+
+/**
+ Hide Thermal device PciCfgSpace at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfHideThermalDevice (
+ VOID
+ )
+{
+ PchPcrAndThenOr32 (
+ PID_PSF2, R_PCH_PCR_PSF2_T0_SHDW_TRH_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_CFG_DIS,
+ (UINT32) ~0,
+ B_PCH_PCR_PSFX_T0_SHDW_CFG_DIS_CFGDIS
+ );
+}
+
+GLOBAL_REMOVE_IF_UNREFERENCED UINT16 mPchLpScsDevicePsfRegBase[] =
+{
+ R_PCH_LP_PCR_PSF2_T0_SHDW_EMMC_REG_BASE,
+ R_PCH_LP_PCR_PSF2_T0_SHDW_SDIO_REG_BASE,
+ R_PCH_LP_PCR_PSF2_T0_SHDW_SDCARD_REG_BASE,
+ R_PCH_LP_PCR_PSF2_T0_SHDW_UFS_REG_BASE
+};
+
+/**
+ Disable SCS device at PSF level
+
+ @param[in] ScsDevNum SCS Device
+
+ @retval None
+**/
+VOID
+PsfDisableScsDevice (
+ IN PCH_PSF_SCS_DEV_NUM ScsDevNum
+ )
+{
+ if (ScsDevNum >= PchPsfMaxScsDevNum) {
+ ASSERT (FALSE);
+ }
+
+ PchPcrAndThenOr32 (
+ PID_PSF2,
+ mPchLpScsDevicePsfRegBase[ScsDevNum] + R_PCH_PCR_PSFX_T0_SHDW_PCIEN,
+ (UINT32) ~0,
+ B_PCH_PCR_PSFX_T0_SHDW_PCIEN_FUNDIS
+ );
+}
+
+/**
+ Disable SCS devices BAR1 PSF level
+
+ @param[in] ScsDevNum SCS Device
+
+ @retval None
+**/
+VOID
+PsfDisableScsBar1 (
+ IN PCH_PSF_SCS_DEV_NUM ScsDevNum
+ )
+{
+ if (ScsDevNum >= PchPsfMaxScsDevNum) {
+ ASSERT (FALSE);
+ }
+
+ //
+ // Set AGNT_T0_SHDW_PCIEN[19:18] = 11b
+ // SCS device BAR is 64bit wide so to disable BAR1
+ // at PSF both BAR2 (32bit wide) and BAR3 (32bit wide) need to be disabled
+ //
+ PchPcrAndThenOr32 (
+ PID_PSF2,
+ mPchLpScsDevicePsfRegBase[ScsDevNum] + R_PCH_PCR_PSFX_T0_SHDW_PCIEN,
+ (UINT32) ~0,
+ (B_PCH_PCR_PSFX_T0_SHDW_PCIEN_BAR2DIS | B_PCH_PCR_PSFX_T0_SHDW_PCIEN_BAR3DIS)
+ );
+}
+
+/**
+ Hide TraceHub ACPI devices PciCfgSpace at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfHideTraceHubAcpiDevice (
+ VOID
+ )
+{
+ PchPcrAndThenOr32 (
+ PID_PSF3,
+ R_PCH_PCR_PSF3_T0_SHDW_TRACE_HUB_ACPI_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_CFG_DIS,
+ (UINT32) ~0,
+ B_PCH_PCR_PSFX_T0_SHDW_CFG_DIS_CFGDIS
+ );
+}
+
+/**
+ This procedure will hide TraceHub PciCfgSpace at PSF level
+
+ @retval None
+**/
+VOID
+PsfHideTraceHubDevice (
+ VOID
+ )
+{
+ PchPcrAndThenOr32 (
+ PID_PSF3,
+ R_PCH_PCR_PSF3_T0_SHDW_TRACE_HUB_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_CFG_DIS,
+ ~0u,
+ B_PCH_PCR_PSFX_T0_SHDW_CFG_DIS_CFGDIS
+ );
+}
+
+/**
+ This procedure will reveal TraceHub PciCfgSpace at PSF level
+
+ @retval None
+**/
+VOID
+PsfRevealTraceHubDevice (
+ VOID
+ )
+{
+ PchPcrAndThenOr32 (
+ PID_PSF3,
+ R_PCH_PCR_PSF3_T0_SHDW_TRACE_HUB_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_CFG_DIS,
+ (UINT32) ~(B_PCH_PCR_PSFX_T0_SHDW_CFG_DIS_CFGDIS),
+ 0
+ );
+}
+
+/**
+ This procedure will disable and hide TraceHub device at PSF level
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfDisableTraceHubDevice (
+ VOID
+ )
+{
+ PsfHideTraceHubDevice ();
+
+ PchPcrAndThenOr32 (
+ PID_PSF3,
+ R_PCH_PCR_PSF3_T0_SHDW_TRACE_HUB_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_PCIEN,
+ 0xFFFFFFFF,
+ B_PCH_PCR_PSFX_T0_SHDW_PCIEN_FUNDIS
+ );
+}
+
+/**
+ Calculates offset of PCR register where given rootport can be enabled/disabled
+
+ @param[in] RpIndex PCIe Root Port Index (0 based)
+
+ @retval Offset
+**/
+static UINT16
+GetPsfPcieRootPortOffset (
+ IN UINT32 RpIndex
+ )
+{
+ UINT16 RootPortReg;
+
+ if (GetPchSeries () == PchLp) {
+ RootPortReg = R_PCH_LP_PCR_PSF1_T1_SHDW_PCIE01_REG_BASE;
+ } else {
+ if (GetPchGeneration () == KblPch) {
+ RootPortReg = R_KBL_PCH_H_PCR_PSF1_T1_SHDW_PCIE01_REG_BASE;
+ } else {
+ RootPortReg = R_SKL_PCH_H_PCR_PSF1_T1_SHDW_PCIE01_REG_BASE;
+ }
+ }
+ return (RootPortReg - ((UINT16)RpIndex * 0x100) + R_PCH_PCR_PSFX_T1_SHDW_PCIEN);
+}
+
+/**
+ Re-enable PCIe Root Port at PSF level after it was disabled
+
+ @param[in] RpIndex PCIe Root Port Index (0 based)
+
+ @retval None
+**/
+VOID
+PsfEnablePcieRootPort (
+ IN UINT32 RpIndex
+ )
+{
+ ASSERT (RpIndex < GetPchMaxPciePortNum ());
+
+ PchPcrAndThenOr32 (PID_PSF1, GetPsfPcieRootPortOffset (RpIndex), (UINT32)(~B_PCH_PCR_PSFX_T1_SHDW_PCIEN_FUNDIS), 0);
+}
+
+/**
+ Disable PCIe Root Port at PSF level
+
+ @param[in] RpIndex PCIe Root Port Index (0 based)
+
+ @retval None
+**/
+VOID
+PsfDisablePcieRootPort (
+ IN UINT32 RpIndex
+ )
+{
+ ASSERT (RpIndex < GetPchMaxPciePortNum ());
+
+ PchPcrAndThenOr32 (PID_PSF1, GetPsfPcieRootPortOffset (RpIndex), ~0u, B_PCH_PCR_PSFX_T1_SHDW_PCIEN_FUNDIS);
+}
+
+/**
+ Disable PCIe Root Port at PSF level.
+ This function will also perform S3 boot script programming
+
+ @param[in] RpIndex PCIe Root Port Index (0 based)
+
+ @retval None
+**/
+VOID
+PsfDisablePcieRootPortWithS3BootScript (
+ IN UINT32 RpIndex
+ )
+{
+ UINT16 RootPortReg;
+ UINT32 Data32And;
+ UINT32 Data32Or;
+
+ if (GetPchSeries () == PchLp) {
+ if (RpIndex >= PCH_LP_PCIE_MAX_ROOT_PORTS) {
+ ASSERT (FALSE);
+ return;
+ }
+ RootPortReg = R_PCH_LP_PCR_PSF1_T1_SHDW_PCIE01_REG_BASE;
+ } else {
+ if (GetPchGeneration () == KblPch) {
+ if (RpIndex >= KBL_PCH_H_PCIE_MAX_ROOT_PORTS) {
+ ASSERT (FALSE);
+ return;
+ }
+ RootPortReg = R_KBL_PCH_H_PCR_PSF1_T1_SHDW_PCIE01_REG_BASE;
+ } else {
+ if (RpIndex >= SKL_PCH_H_PCIE_MAX_ROOT_PORTS) {
+ ASSERT (FALSE);
+ return;
+ }
+ RootPortReg = R_SKL_PCH_H_PCR_PSF1_T1_SHDW_PCIE01_REG_BASE;
+ }
+ }
+
+ Data32And = ~0u;
+ Data32Or = B_PCH_PCR_PSFX_T1_SHDW_PCIEN_FUNDIS;
+
+ PchPcrAndThenOr32 (
+ PID_PSF1,
+ RootPortReg - ((UINT16)RpIndex * 0x100) + R_PCH_PCR_PSFX_T1_SHDW_PCIEN,
+ Data32And,
+ Data32Or
+ );
+
+ PCH_PCR_BOOT_SCRIPT_READ_WRITE (
+ S3BootScriptWidthUint32,
+ PID_PSF1, (RootPortReg - ((UINT16)RpIndex * 0x100) + R_PCH_PCR_PSFX_T1_SHDW_PCIEN),
+ &Data32Or,
+ &Data32And
+ );
+}
+
+/**
+ Program PSF grant counts for PCI express depending on controllers configuration
+
+ @param[in] Controller PCIe controller index
+ @param[in] ControllerConfig Port configuration of controller
+
+ @retval Status
+**/
+EFI_STATUS
+PsfConfigurePcieGrantCounts (
+ UINT8 Controller,
+ UINT8 ControllerConfig
+ )
+{
+ static CONST UINT8 DgcrPairsLp [PCH_LP_PCIE_MAX_CONTROLLERS][PCH_PCIE_CONTROLLER_PORTS][2] = {
+ { { 5, 6 }, { 8, 9 }, { 11, 12 }, { 14, 15 } }, //SPA
+ { { 19, 20 }, { 22, 23 }, { 25, 26 }, { 28, 29 } }, //SPB
+ { { 33, 34 }, { 36, 37 }, { 39, 40 }, { 42, 43 } }, //SPC
+ };
+
+ static CONST UINT8 PgTgtLp [PCH_LP_PCIE_MAX_CONTROLLERS][PCH_PCIE_CONTROLLER_PORTS] = {
+ { 4, 5, 6, 7 }, //SPA
+ { 12, 13, 14, 15 }, //SPB
+ { 20, 21, 22, 23 } //SPC
+ };
+
+ static CONST UINT8 DgcrPairsH [KBL_PCH_H_PCIE_MAX_CONTROLLERS][PCH_PCIE_CONTROLLER_PORTS][2] = {
+ { { 11, 12 }, { 14, 15 }, { 17, 18 }, { 20, 21 } }, //SPA
+ { { 24, 25 }, { 27, 28 }, { 30, 31 }, { 33, 34 } }, //SPB
+ { { 37, 38 }, { 40, 41 }, { 43, 44 }, { 46, 47 } }, //SPC
+ { { 50, 51 }, { 53, 54 }, { 56, 57 }, { 59, 60 } }, //SPD
+ { { 63, 64 }, { 66, 67 }, { 69, 70 }, { 72, 73 } }, //SPE
+ { {182,183 }, {185,186 }, {188,189 }, {191,192 } } //SPF, only for KBL-H
+ };
+
+ static CONST UINT8 PgTgtH [KBL_PCH_H_PCIE_MAX_CONTROLLERS][PCH_PCIE_CONTROLLER_PORTS] = {
+ { 0, 1, 2, 3 }, //SPA
+ { 4, 5, 6, 7 }, //SPB
+ { 12, 13, 14, 15 }, //SPC
+ { 20, 21, 22, 23 }, //SPD
+ { 28, 29, 30, 31 }, //SPE
+ { 32, 33, 34, 35 } //SPF, only for KBL-H
+ };
+
+ static CONST UINT8 DefaultGrantCount = 4;
+
+ PCH_SERIES PchSeries;
+ UINT32 Dgcr0Addr;
+ UINT32 PgTgt0Addr;
+ UINT32 DgcrNo0;
+ UINT32 DgcrNo1;
+ UINT32 PgTgtNo;
+ UINT32 Channel;
+ UINT32 ChannelGrant[PCH_PCIE_CONTROLLER_PORTS];
+
+ DEBUG ((DEBUG_INFO, "PsfConfigurePcieGrantCounts(%d) Start\n", Controller));
+
+ PchSeries = GetPchSeries ();
+ if (PchSeries == PchLp) {
+ Dgcr0Addr = R_PCH_LP_PSF1_DEV_GNTCNT_RELOAD_DGCR0;
+ PgTgt0Addr = R_PCH_LP_PSF1_TARGET_GNTCNT_RELOAD_PG1_TGT0;
+ } else {
+ if (GetPchGeneration () == KblPch) {
+ Dgcr0Addr = R_KBL_PCH_H_PSF1_DEV_GNTCNT_RELOAD_DGCR0;
+ PgTgt0Addr = R_KBL_PCH_H_PSF1_TARGET_GNTCNT_RELOAD_PG1_TGT0;
+ } else {
+ Dgcr0Addr = R_SKL_PCH_H_PSF1_DEV_GNTCNT_RELOAD_DGCR0;
+ PgTgt0Addr = R_SKL_PCH_H_PSF1_TARGET_GNTCNT_RELOAD_PG1_TGT0;
+ }
+ }
+
+
+ switch (ControllerConfig) {
+ case V_PCH_PCIE_STRPFUSECFG_RPC_1_1_1_1: //Pcie4x1
+ ChannelGrant[0] = 1;
+ ChannelGrant[1] = 1;
+ ChannelGrant[2] = 1;
+ ChannelGrant[3] = 1;
+ break;
+ case V_PCH_PCIE_STRPFUSECFG_RPC_2_1_1: //Pcie1x2_2x1
+ ChannelGrant[0] = 2;
+ ChannelGrant[1] = DefaultGrantCount;
+ ChannelGrant[2] = 1;
+ ChannelGrant[3] = 1;
+ break;
+ case V_PCH_PCIE_STRPFUSECFG_RPC_2_2: //Pcie2x2
+ ChannelGrant[0] = 2;
+ ChannelGrant[1] = DefaultGrantCount;
+ ChannelGrant[2] = 2;
+ ChannelGrant[3] = DefaultGrantCount;
+ break;
+ case V_PCH_PCIE_STRPFUSECFG_RPC_4: //Pcie1x4
+ ChannelGrant[0] = 4;
+ ChannelGrant[1] = DefaultGrantCount;
+ ChannelGrant[2] = DefaultGrantCount;
+ ChannelGrant[3] = DefaultGrantCount;
+ break;
+ default:
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ for (Channel = 0; Channel < PCH_PCIE_CONTROLLER_PORTS; ++Channel) {
+ if (PchSeries == PchLp) {
+ DgcrNo0 = DgcrPairsLp[Controller][Channel][0];
+ DgcrNo1 = DgcrPairsLp[Controller][Channel][1];
+ PgTgtNo = PgTgtLp[Controller][Channel];
+ } else {
+ DgcrNo0 = DgcrPairsH[Controller][Channel][0];
+ DgcrNo1 = DgcrPairsH[Controller][Channel][1];
+ PgTgtNo = PgTgtH[Controller][Channel];
+ }
+
+ DEBUG ((DEBUG_INFO, "DGCR%d = %d\n", DgcrNo0, ChannelGrant[Channel]));
+ PchPcrAndThenOr32 (
+ PID_PSF1,
+ (UINT16) (Dgcr0Addr + (DgcrNo0 * S_PCH_PSF_DEV_GNTCNT_RELOAD_DGCR)),
+ (UINT32) ~B_PCH_PSF_DEV_GNTCNT_RELOAD_DGCR_GNT_CNT_RELOAD,
+ ChannelGrant[Channel]
+ );
+ DEBUG ((DEBUG_INFO, "DGCR%d = %d\n", DgcrNo1, ChannelGrant[Channel]));
+ PchPcrAndThenOr32 (
+ PID_PSF1,
+ (UINT16) (Dgcr0Addr + (DgcrNo1 * S_PCH_PSF_DEV_GNTCNT_RELOAD_DGCR)),
+ (UINT32) ~B_PCH_PSF_DEV_GNTCNT_RELOAD_DGCR_GNT_CNT_RELOAD,
+ ChannelGrant[Channel]
+ );
+ DEBUG ((DEBUG_INFO, "PG1_TGT%d = %d\n", PgTgtNo, ChannelGrant[Channel]));
+ PchPcrAndThenOr32 (
+ PID_PSF1,
+ (UINT16) (PgTgt0Addr + (PgTgtNo * S_PCH_PSF_TARGET_GNTCNT_RELOAD)),
+ (UINT32) ~B_PCH_PSF_TARGET_GNTCNT_RELOAD_GNT_CNT_RELOAD,
+ ChannelGrant[Channel]
+ );
+ }
+
+ DEBUG ((DEBUG_INFO, "PsfConfigurePcieGrantCounts() End\n"));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Disable ISM NP Completion Tracking for GbE PSF port
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfDisableIsmNpCompletionTrackForGbe (
+ VOID
+ )
+{
+ UINT16 RegOffset;
+ PCH_SBI_PID PortId;
+
+ if (GetPchSeries () == PchLp) {
+ PortId = PID_PSF1;
+ RegOffset = R_PCH_LP_PCR_PSF1_PSF_PORT_CONFIG_PG1_PORT7;
+ } else {
+ PortId = PID_PSF3;
+ RegOffset = R_PCH_H_PCR_PSF3_PSF_PORT_CONFIG_PG1_PORT1;
+ }
+ ///
+ /// Clear PCR PSF_x_PSF_PORT_CONFIG_PGx_PORTx[5] = 0b
+ ///
+ PchPcrAndThenOr8 (
+ PortId,
+ RegOffset,
+ (UINT8) ~(BIT5),
+ 0
+ );
+}
+
+/**
+ Program PSF EOI Multicast configuration
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfSetEoiMulticastConfiguration (
+ VOID
+ )
+{
+ UINT32 McastTarget;
+
+ ///
+ /// Program PSF Multicast registers accordingly to SKL PCH BWG 5.14.4 PSF EOI Multicast Configuration
+ ///
+ if (GetPchSeries () == PchLp) {
+ McastTarget = V_PCH_LP_PCR_PSFX_PSF_MC_AGENT_MCAST_TGT_P2SB;
+ ///
+ /// Set PCR[PSF1] + 4060h = 38A00h
+ ///
+ PchPcrWrite32 (
+ PID_PSF1, R_PCH_LP_PCR_PSF1_PSF_MC_AGENT_MCAST0_TGT0_EOI,
+ McastTarget
+ );
+ ///
+ /// Set PCR[PSF1] + 4050h[7:0] = 11b
+ ///
+ PchPcrWrite32 (
+ PID_PSF1, R_PCH_LP_PCR_PSF1_PSF_MC_CONTROL_MCAST0_EOI,
+ 0x3
+ );
+ } else {
+ McastTarget = V_PCH_H_PCR_PSFX_PSF_MC_AGENT_MCAST_TGT_P2SB;
+ if (GetPchGeneration () == KblPch) {
+ ///
+ /// Set PCR[PSF1] + 405Ch = 38B00h
+ ///
+ PchPcrWrite32 (
+ PID_PSF1, R_KBL_PCH_H_PCR_PSF1_PSF_MC_AGENT_MCAST0_TGT0_EOI,
+ McastTarget
+ );
+ ///
+ /// Set PCR[PSF1] + 404Ch[7:0] = 11b
+ ///
+ PchPcrWrite32 (
+ PID_PSF1, R_KBL_PCH_H_PCR_PSF1_PSF_MC_CONTROL_MCAST0_EOI,
+ 0x3
+ );
+ } else {
+ ///
+ /// Set PCR[PSF1] + 4058h = 38B00h
+ ///
+ PchPcrWrite32 (
+ PID_PSF1, R_SKL_PCH_H_PCR_PSF1_PSF_MC_AGENT_MCAST0_TGT0_EOI,
+ McastTarget
+ );
+ ///
+ /// Set PCR[PSF1] + 4048h[7:0] = 11b
+ ///
+ PchPcrWrite32 (
+ PID_PSF1, R_SKL_PCH_H_PCR_PSF1_PSF_MC_CONTROL_MCAST0_EOI,
+ 0x3
+ );
+ }
+ }
+ ///
+ /// Set PCR[PSF1] + 4054h to P2SB target
+ ///
+ PchPcrWrite32 (
+ PID_PSF3, R_PCH_PCR_PSF3_PSF_MC_AGENT_MCAST0_TGT0_EOI,
+ McastTarget
+ );
+ ///
+ /// Set PCR[PSF3] + 404Ch[7:0] = 11b
+ ///
+ PchPcrWrite32 (
+ PID_PSF3, R_PCH_PCR_PSF3_PSF_MC_CONTROL_MCAST0_EOI,
+ 0x3
+ );
+}
+
+/**
+ This function enables EOI message forwarding in PSF for PCIe ports
+ for cases where IOAPIC is present behind this root port.
+
+ @param[in] RpIndex Root port index (0 based)
+
+ @retval Status
+**/
+EFI_STATUS
+PsfConfigurEoiForPciePort (
+ IN UINT32 RpIndex
+ )
+{
+
+ UINT32 Data32;
+ UINT8 NumMcVal;
+ UINT32 RpDestId;
+ ///
+ /// PCH-LP:
+ /// RP Destination ID RP Destination ID
+ /// 1 0x18100 7 0x18302
+ /// 2 0x18101 8 0x18303
+ /// 3 0x18102 9 0x18500
+ /// 4 0x18103 10 0x18501
+ /// 5 0x18300 11 0x18502
+ /// 6 0x18301 12 0x18503
+ ///
+ static UINT32 PchSklLpRpDestId[PCH_LP_PCIE_MAX_ROOT_PORTS] =
+ {
+ 0x18100, 0x18101, 0x18102, 0x18103, 0x18300,
+ 0x18301, 0x18302, 0x18303, 0x18500, 0x18501,
+ 0x18502, 0x18503
+ };
+ ///
+ /// PCH-H:
+ /// RP Destination ID RP Destination ID
+ /// 1 0x18000 11 0x18302
+ /// 2 0x18001 12 0x18303
+ /// 3 0x18002 13 0x18500
+ /// 4 0x18003 14 0x18501
+ /// 5 0x18100 15 0x18502
+ /// 6 0x18101 16 0x18503
+ /// 7 0x18102 17 0x18700
+ /// 8 0x18103 18 0x18701
+ /// 9 0x18300 19 0x18702
+ /// 10 0x18301 20 0x18703
+ ///
+ /// KBL-H: same as SKL-H plus the following 4 ports
+ /// 21 0x18800 23 0x18802
+ /// 22 0x18801 24 0x18803
+ ///
+ static UINT32 PchHRpDestId[KBL_PCH_H_PCIE_MAX_ROOT_PORTS] =
+ {
+ 0x18000, 0x18001, 0x18002, 0x18003,
+ 0x18100, 0x18101, 0x18102, 0x18103,
+ 0x18300, 0x18301, 0x18302, 0x18303,
+ 0x18500, 0x18501, 0x18502, 0x18503,
+ 0x18700, 0x18701, 0x18702, 0x18703,
+ 0x18800, 0x18801, 0x18802, 0x18803
+ };
+ PCH_SERIES PchSeries;
+ PCH_GENERATION PchGen;
+ UINT16 PsfReg;
+
+ ASSERT (RpIndex < GetPchMaxPciePortNum ());
+
+ PchSeries = GetPchSeries ();
+ PchGen = GetPchGeneration ();
+
+ ///
+ /// If there is an IOAPIC discovered behind root port program PSF Multicast registers
+ /// accordingly to SKL PCH BWG 5.14.4 PSF EOI Multicast Configuration
+ ///
+ ///
+ ///
+ ///
+ /// Read PSF_1_PSF_MC_CONTROL_MCAST0_RS0_EOI bit [7:1], increase it by 1, write back
+ ///
+ if (PchSeries == PchLp) {
+ PsfReg = R_PCH_LP_PCR_PSF1_PSF_MC_CONTROL_MCAST0_EOI;
+ } else {
+ if (PchGen == KblPch) {
+ PsfReg = R_KBL_PCH_H_PCR_PSF1_PSF_MC_CONTROL_MCAST0_EOI;
+ } else {
+ PsfReg = R_SKL_PCH_H_PCR_PSF1_PSF_MC_CONTROL_MCAST0_EOI;
+ }
+ }
+ PchPcrRead32 (PID_PSF1, PsfReg, &Data32);
+ NumMcVal = (UINT8) (Data32 >> 1);
+ Data32 += 0x2;
+ PchPcrWrite32 (PID_PSF1, PsfReg, Data32);
+
+ ///
+ /// Program PSF_1_PSF_MC_AGENT_MCAST0_RS0_TGT<x>_EOI, the next empty register,
+ /// where x is the same as the value read in step 1 before the increment.
+ /// Program this register according to the RP# and the table below
+ ///
+ if (PchSeries == PchLp) {
+ PsfReg = R_PCH_LP_PCR_PSF1_PSF_MC_AGENT_MCAST0_TGT0_EOI;
+ RpDestId = PchSklLpRpDestId[RpIndex];
+ } else {
+ if (PchGen == KblPch) {
+ PsfReg = R_KBL_PCH_H_PCR_PSF1_PSF_MC_AGENT_MCAST0_TGT0_EOI;
+ } else {
+ PsfReg = R_SKL_PCH_H_PCR_PSF1_PSF_MC_AGENT_MCAST0_TGT0_EOI;
+ }
+ RpDestId = PchHRpDestId[RpIndex];
+ }
+
+ PchPcrAndThenOr32 (
+ PID_PSF1, PsfReg + (NumMcVal * 4),
+ (UINT32) ~0,
+ RpDestId
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Reload default RP PSF device number and function number.
+ The PSF register doesn't got reset after system reset, which will result in mismatch between
+ PSF register setting and PCIE PCR PCD register setting. Reset PSF register in early phase
+ to avoid cycle decoding confusing.
+
+ @param[in] None
+
+ @retval Status
+**/
+VOID
+PsfReloadDefaultPcieRpDevFunc (
+ VOID
+ )
+{
+ UINT16 Psf1RpFuncCfgBase;
+ UINTN PortIndex;
+ UINTN MaxPciePorts;
+
+ PortIndex = 0;
+ MaxPciePorts = GetPchMaxPciePortNum ();
+
+ if (GetPchSeries () == PchLp) {
+ Psf1RpFuncCfgBase = R_PCH_LP_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPA_D28_F0;
+ } else {
+ if (GetPchGeneration () == KblPch) {
+ Psf1RpFuncCfgBase = R_KBL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPA_D28_F0;
+ } else {
+ Psf1RpFuncCfgBase = R_SKL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPA_D28_F0;
+ }
+ }
+ //
+ // Reload D28 registers
+ //
+ for (; PortIndex < 8; PortIndex++) {
+ PchPcrWrite32 (
+ PID_PSF1,
+ Psf1RpFuncCfgBase + 4 * (UINT16) PortIndex,
+ (PCI_DEVICE_NUMBER_PCH_PCIE_DEVICE_1 << N_PCH_PCR_PSFX_TX_AGENT_FUNCTION_CONFIG_DEVICE) +
+ ((PortIndex % 8) << N_PCH_PCR_PSFX_TX_AGENT_FUNCTION_CONFIG_FUNCTION)
+ );
+ }
+ //
+ // Reload D29 registers
+ //
+ for (; PortIndex < 16 && PortIndex < MaxPciePorts; PortIndex++) {
+ PchPcrWrite32 (
+ PID_PSF1,
+ Psf1RpFuncCfgBase + 4 * (UINT16) PortIndex,
+ (PCI_DEVICE_NUMBER_PCH_PCIE_DEVICE_2 << N_PCH_PCR_PSFX_TX_AGENT_FUNCTION_CONFIG_DEVICE) +
+ ((PortIndex % 8) << N_PCH_PCR_PSFX_TX_AGENT_FUNCTION_CONFIG_FUNCTION)
+ );
+ }
+ //
+ // Reload D27 registers
+ //
+ for (; PortIndex < MaxPciePorts; PortIndex++) {
+ PchPcrWrite32 (
+ PID_PSF1,
+ Psf1RpFuncCfgBase + 4 * (UINT16) PortIndex,
+ (PCI_DEVICE_NUMBER_PCH_PCIE_DEVICE_3 << N_PCH_PCR_PSFX_TX_AGENT_FUNCTION_CONFIG_DEVICE) +
+ ((PortIndex % 8) << N_PCH_PCR_PSFX_TX_AGENT_FUNCTION_CONFIG_FUNCTION)
+ );
+ }
+}
+
+
+/**
+ Assign new function number for PCIe Port Number.
+ This function will also perform S3 boot script programming
+
+ @param[in] RpIndex PCIe Root Port Index (0 based)
+ @param[in] NewFunction New Function number
+
+ @retval None
+**/
+VOID
+PsfSetPcieFunctionWithS3BootScript (
+ IN UINT32 RpIndex,
+ IN UINT32 NewFunction
+ )
+{
+ UINT16 PsfRpFuncCfgBase;
+ UINT16 PsfD28F0FuncCfgBase;
+ UINT32 Data32;
+
+ if (GetPchSeries () == PchLp) {
+ PsfD28F0FuncCfgBase = R_PCH_LP_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPA_D28_F0;
+ } else {
+ if (GetPchGeneration () == KblPch) {
+ PsfD28F0FuncCfgBase = R_KBL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPA_D28_F0;
+ } else {
+ PsfD28F0FuncCfgBase = R_SKL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPA_D28_F0;
+ }
+ }
+
+ PsfRpFuncCfgBase = PsfD28F0FuncCfgBase + 4 * (UINT16)RpIndex;
+
+ //
+ // Program PSF1 RP function config register.
+ //
+ PchPcrAndThenOr32 (
+ PID_PSF1,
+ PsfRpFuncCfgBase,
+ (UINT32) ~B_PCH_PCR_PSFX_TX_AGENT_FUNCTION_CONFIG_FUNCTION,
+ (UINT32) (NewFunction << N_PCH_PCR_PSFX_TX_AGENT_FUNCTION_CONFIG_FUNCTION)
+ );
+
+ PchPcrRead32 (PID_PSF1, PsfRpFuncCfgBase, &Data32);
+ PCH_PCR_BOOT_SCRIPT_WRITE (
+ S3BootScriptWidthUint32,
+ PID_PSF1,
+ PsfRpFuncCfgBase,
+ 1,
+ &Data32
+ );
+}
+
+/**
+ This function enables PCIe Relaxed Order in PSF
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfEnablePcieRelaxedOrder (
+ VOID
+ )
+{
+ ///
+ /// PCH BIOS Spec Section 8.2.9
+ ///
+ PchPcrAndThenOr32 (
+ PID_PSF1,
+ R_PCH_PCR_PSF_PORT_CONFIG_PG0_PORT0,
+ ~0u,
+ BIT1
+ );
+}
+
+/**
+ Configure PSF power management.
+ Must be called after all PSF configuration is completed.
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PsfConfigurePowerManagement (
+ VOID
+ )
+{
+ PchPcrAndThenOr32 (PID_PSF1, R_PCH_PCR_PSF_GLOBAL_CONFIG, ~0u, B_PCH_PCR_PSF_GLOBAL_CONFIG_ENTCG);
+ PchPcrAndThenOr32 (PID_PSF2, R_PCH_PCR_PSF_GLOBAL_CONFIG, ~0u, B_PCH_PCR_PSF_GLOBAL_CONFIG_ENTCG);
+ PchPcrAndThenOr32 (PID_PSF3, R_PCH_PCR_PSF_GLOBAL_CONFIG, ~0u, B_PCH_PCR_PSF_GLOBAL_CONFIG_ENTCG);
+ PchPcrAndThenOr32 (PID_PSF4, R_PCH_PCR_PSF_GLOBAL_CONFIG, ~0u, B_PCH_PCR_PSF_GLOBAL_CONFIG_ENTCG);
+ PchPcrAndThenOr32 (PID_CSME_PSF, R_PCH_PCR_PSF_GLOBAL_CONFIG, ~0u, B_PCH_PCR_PSF_GLOBAL_CONFIG_ENTCG);
+ PchPcrAndThenOr32 (PID_PSF2, R_PCH_PCR_PSF_GLOBAL_CONFIG, ~0u, B_PCH_PCR_PSF_GLOBAL_CONFIG_ENLCG);
+ PchPcrAndThenOr32 (PID_PSF3, R_PCH_PCR_PSF_GLOBAL_CONFIG, ~0u, B_PCH_PCR_PSF_GLOBAL_CONFIG_ENLCG);
+ PchPcrAndThenOr32 (PID_PSF4, R_PCH_PCR_PSF_GLOBAL_CONFIG, ~0u, B_PCH_PCR_PSF_GLOBAL_CONFIG_ENLCG);
+ PchPcrAndThenOr32 (PID_CSME_PSF, R_PCH_PCR_PSF_GLOBAL_CONFIG, ~0u, B_PCH_PCR_PSF_GLOBAL_CONFIG_ENLCG);
+}
+
+/**
+ Enable VTd support in PSF.
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PchPsfEnableVtd (
+ VOID
+ )
+{
+ STATIC PCH_SBI_PID PsfPidTable[] = {PID_PSF1, PID_PSF2, PID_PSF3, PID_PSF4};
+ UINTN PsfPidIndex;
+
+ for (PsfPidIndex = 0; PsfPidIndex < (sizeof (PsfPidTable) / sizeof (PsfPidTable[0])); PsfPidIndex++) {
+ PchPcrAndThenOr32 (
+ PsfPidTable[PsfPidIndex],
+ R_PCH_PCR_PSF_ROOTSPACE_CONFIG_RS0,
+ ~0u,
+ B_PCH_PCR_PSF_ROOTSPACE_CONFIG_RSX_VTDEN
+ );
+ }
+}
+
+/**
+ Disable PSF address-based peer-to-peer decoding.
+**/
+VOID
+PchPsfDisableP2pDecoding (
+ VOID
+ )
+{
+ STATIC PCH_SBI_PID PsfPidTable[] = {PID_PSF1, PID_PSF2, PID_PSF3, PID_PSF4};
+ UINTN PsfPidIndex;
+
+ for (PsfPidIndex = 0; PsfPidIndex < (sizeof (PsfPidTable) / sizeof (PsfPidTable[0])); PsfPidIndex++) {
+ PchPcrAndThenOr32 (
+ PsfPidTable[PsfPidIndex],
+ R_PCH_PCR_PSF_ROOTSPACE_CONFIG_RS0,
+ (UINT32)~B_PCH_PCR_PSF_ROOTSPACE_CONFIG_RSX_ENADDRP2P,
+ 0
+ );
+
+ PchPcrAndThenOr32 (
+ PsfPidTable[PsfPidIndex],
+ R_PCH_PCR_PSF_ROOTSPACE_CONFIG_RS1,
+ (UINT32)~B_PCH_PCR_PSF_ROOTSPACE_CONFIG_RSX_ENADDRP2P,
+ 0
+ );
+ }
+}
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchPsfPrivateLib/PeiDxeSmmPchPsfPrivateLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchPsfPrivateLib/PeiDxeSmmPchPsfPrivateLib.inf
new file mode 100644
index 0000000000..6995171b10
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchPsfPrivateLib/PeiDxeSmmPchPsfPrivateLib.inf
@@ -0,0 +1,47 @@
+## @file
+# Component description file for the PeiDxeSmmPchPsfPrivateLib
+#
+# Copyright (c) 2017, 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 = PeiDxeSmmPchPsfPrivateLib
+FILE_GUID = 7A6C18CA-0353-433E-885D-DD68BFAD38BE
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = PchPsfPrivateLib
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[LibraryClasses]
+ BaseLib
+ IoLib
+ DebugLib
+ MmPciLib
+ PchInfoLib
+ PchPcrLib
+ PchPcieRpLib
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ KabylakeSiliconPkg/SiPkg.dec
+ KabylakeSiliconPkg/KabylakeSiliconPrivate.dec
+
+
+[Sources]
+ PchPsfPrivateLib.c
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchSmbusCommonLib/PchSmbusExec.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchSmbusCommonLib/PchSmbusExec.c
new file mode 100644
index 0000000000..ad5c784bff
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchSmbusCommonLib/PchSmbusExec.c
@@ -0,0 +1,652 @@
+/** @file
+ PCH Smbus Executive Code (common PEI/DXE/SMM code)
+
+Copyright (c) 2017, 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 <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/TimerLib.h>
+#include <IndustryStandard/SmBus.h>
+#include <IndustryStandard/Pci30.h>
+#include <PchAccess.h>
+#include <Library/MmPciLib.h>
+#include <Library/PchSmbusCommonLib.h>
+
+/**
+ Get SMBUS IO Base address
+
+
+ @retval UINT32 The SMBUS IO Base Address
+**/
+UINT32
+SmbusGetIoBase (
+ VOID
+ )
+{
+ UINT32 SmbusIoBase;
+
+ SmbusIoBase = MmioRead32 (
+ MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_SMBUS,
+ PCI_FUNCTION_NUMBER_PCH_SMBUS)
+ + R_PCH_SMBUS_BASE) & B_PCH_SMBUS_BASE_BAR;
+
+ ASSERT (SmbusIoBase != B_PCH_SMBUS_BASE_BAR && SmbusIoBase != 0);
+
+ return SmbusIoBase;
+}
+
+/**
+ This function provides a standard way to read PCH Smbus IO registers.
+
+ @param[in] Offset Register offset from Smbus base IO address.
+
+ @retval UINT8 Returns data read from IO.
+**/
+UINT8
+EFIAPI
+SmbusIoRead (
+ IN UINT8 Offset
+ )
+{
+ return IoRead8 (SmbusGetIoBase () + Offset);
+}
+
+/**
+ This function provides a standard way to write PCH Smbus IO registers.
+
+ @param[in] Offset Register offset from Smbus base IO address.
+ @param[in] Data Data to write to register.
+
+**/
+VOID
+EFIAPI
+SmbusIoWrite (
+ IN UINT8 Offset,
+ IN UINT8 Data
+ )
+{
+ ///
+ /// Write New Value
+ ///
+ IoWrite8 (SmbusGetIoBase () + Offset, Data);
+ return;
+}
+
+/**
+ This function provides a standard way to check if an SMBus transaction has
+ completed.
+
+ @param[in] StsReg Not used for input. On return, contains the
+ value of the SMBus status register.
+
+ @retval TRUE Transaction is complete
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+IoDone (
+ IN UINT8 *StsReg
+ )
+{
+ ///
+ /// Wait for IO to complete
+ ///
+ UINTN StallIndex;
+ UINTN StallTries;
+
+ StallTries = STALL_TIME / STALL_PERIOD;
+
+ for (StallIndex = 0; StallIndex < StallTries; StallIndex++) {
+ *StsReg = SmbusIoRead (R_PCH_SMBUS_HSTS);
+ if (*StsReg & (B_PCH_SMBUS_INTR | B_PCH_SMBUS_BYTE_DONE_STS | B_PCH_SMBUS_DERR | B_PCH_SMBUS_BERR)) {
+ return TRUE;
+ } else {
+ MicroSecondDelay (STALL_PERIOD);
+ }
+ }
+
+ return FALSE;
+}
+
+/**
+ Check if it's ok to use the bus.
+
+
+ @retval EFI_SUCCESS SmBus is acquired and it's safe to send commands.
+ @retval EFI_TIMEOUT SmBus is busy, it's not safe to send commands.
+**/
+EFI_STATUS
+AcquireBus (
+ VOID
+ )
+{
+ UINT8 StsReg;
+
+ StsReg = 0;
+ StsReg = SmbusIoRead (R_PCH_SMBUS_HSTS);
+ if (StsReg & B_PCH_SMBUS_IUS) {
+ return EFI_TIMEOUT;
+ } else if (StsReg & B_PCH_SMBUS_HBSY) {
+ ///
+ /// Clear Status Register and exit
+ ///
+ SmbusIoWrite (R_PCH_SMBUS_HSTS, B_PCH_SMBUS_HSTS_ALL);
+ return EFI_TIMEOUT;
+ } else {
+ ///
+ /// Clear out any odd status information (Will Not Clear In Use)
+ ///
+ SmbusIoWrite (R_PCH_SMBUS_HSTS, StsReg);
+ return EFI_SUCCESS;
+ }
+}
+
+/**
+ This function provides a standard way to execute Smbus protocols
+ as defined in the SMBus Specification. The data can either be of
+ the Length byte, word, or a block of data. The resulting transaction will be
+ either the SMBus Slave Device accepts this transaction or this function
+ returns with an error
+
+ @param[in] SlaveAddress Smbus Slave device the command is directed at
+ @param[in] Command Slave Device dependent
+ @param[in] Operation Which SMBus protocol will be used
+ @param[in] PecCheck Defines if Packet Error Code Checking is to be used
+ @param[in, out] Length How many bytes to read. Must be 0 <= Length <= 32 depending on Operation
+ It will contain the actual number of bytes read/written.
+ @param[in, out] Buffer Contain the data read/written.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @exception EFI_UNSUPPORTED The operation is unsupported.
+
+ @retval EFI_INVALID_PARAMETER Length or Buffer is NULL for any operation besides
+ quick read or quick write.
+ @retval EFI_TIMEOUT The transaction did not complete within an internally
+ specified timeout period, or the controller is not
+ available for use.
+ @retval EFI_DEVICE_ERROR There was an Smbus error (NACK) during the operation.
+ This could indicate the slave device is not present
+ or is in a hung condition.
+**/
+EFI_STATUS
+SmbusExec (
+ IN EFI_SMBUS_DEVICE_ADDRESS SlaveAddress,
+ IN EFI_SMBUS_DEVICE_COMMAND Command,
+ IN EFI_SMBUS_OPERATION Operation,
+ IN BOOLEAN PecCheck,
+ IN OUT UINTN *Length,
+ IN OUT VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINT8 AuxcReg;
+ UINT8 AuxStsReg;
+ UINT8 SmbusOperation;
+ UINT8 StsReg;
+ UINT8 SlvAddrReg;
+ UINT8 HostCmdReg;
+ UINT8 BlockCount;
+ BOOLEAN BufferTooSmall;
+ UINTN Index;
+ UINTN BusIndex;
+ UINT8 *CallBuffer;
+ UINT8 SmbusHctl;
+ UINT32 Timeout;
+
+ CallBuffer = Buffer;
+ BlockCount = 0;
+
+ ///
+ /// For any operations besides quick read & write, the pointers to
+ /// Length and Buffer must not be NULL.
+ ///
+ if ((Operation != EfiSmbusQuickRead) && (Operation != EfiSmbusQuickWrite)) {
+ if ((Length == NULL) || (Buffer == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+ ///
+ /// See if its ok to use the bus based upon INUSE_STS bit.
+ ///
+ Status = AcquireBus ();
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ ///
+ /// This is the main operation loop. If the operation results in a Smbus
+ /// collision with another master on the bus, it attempts the requested
+ /// transaction again at least BUS_TRIES attempts.
+ ///
+ for (BusIndex = 0; BusIndex < BUS_TRIES; BusIndex++) {
+ ///
+ /// Operation Specifics (pre-execution)
+ ///
+ Status = EFI_SUCCESS;
+ SmbusOperation = V_PCH_SMBUS_SMB_CMD_QUICK;
+ SlvAddrReg = (UINT8) ((SlaveAddress.SmbusDeviceAddress << 1) | 1);
+ HostCmdReg = (UINT8) Command;
+ AuxcReg = 0;
+
+ switch (Operation) {
+
+ case EfiSmbusQuickWrite:
+ SlvAddrReg--;
+
+ ///
+ /// The "break;" command is not present here to allow code execution
+ /// do drop into the next case, which contains common code to this case.
+ ///
+ case EfiSmbusQuickRead:
+ if (PecCheck == TRUE) {
+ Status = EFI_UNSUPPORTED;
+ }
+ break;
+
+ case EfiSmbusSendByte:
+ HostCmdReg = CallBuffer[0];
+ SlvAddrReg--;
+
+ ///
+ /// The "break;" command is not present here to allow code execution
+ /// do drop into the next case, which contains common code to this case.
+ ///
+ case EfiSmbusReceiveByte:
+ SmbusOperation = V_PCH_SMBUS_SMB_CMD_BYTE;
+ if (*Length < 1) {
+ Status = EFI_BUFFER_TOO_SMALL;
+ }
+
+ *Length = 1;
+ break;
+
+ case EfiSmbusWriteByte:
+ SmbusIoWrite (R_PCH_SMBUS_HD0, CallBuffer[0]);
+ SlvAddrReg--;
+ *Length = 1;
+
+ ///
+ /// The "break;" command is not present here to allow code execution
+ /// do drop into the next case, which contains common code to this case.
+ ///
+ case EfiSmbusReadByte:
+ if (*Length < 1) {
+ Status = EFI_BUFFER_TOO_SMALL;
+ } else if (*Length == 1) {
+ SmbusOperation = V_PCH_SMBUS_SMB_CMD_BYTE_DATA;
+ } else if (*Length <= 256) {
+ if (PecCheck == TRUE) {
+ ///
+ /// The I2C Read command with either PEC_EN or AAC bit set
+ /// produces undefined results.
+ ///
+ Status = EFI_UNSUPPORTED;
+ }
+
+ SmbusOperation = V_PCH_SMBUS_SMB_CMD_IIC_READ;
+ } else {
+ Status = EFI_INVALID_PARAMETER;
+ }
+
+ break;
+
+ case EfiSmbusReadWord:
+ SmbusOperation = V_PCH_SMBUS_SMB_CMD_WORD_DATA;
+ if (*Length < 2) {
+ Status = EFI_BUFFER_TOO_SMALL;
+ }
+
+ *Length = 2;
+ break;
+
+ case EfiSmbusWriteWord:
+ SmbusOperation = V_PCH_SMBUS_SMB_CMD_WORD_DATA;
+ SlvAddrReg--;
+ SmbusIoWrite (R_PCH_SMBUS_HD1, CallBuffer[1]);
+ SmbusIoWrite (R_PCH_SMBUS_HD0, CallBuffer[0]);
+ if (*Length < 2) {
+ Status = EFI_BUFFER_TOO_SMALL;
+ }
+
+ *Length = 2;
+ break;
+
+ case EfiSmbusWriteBlock:
+ SmbusIoWrite (R_PCH_SMBUS_HD0, *(UINT8 *) Length);
+ SlvAddrReg--;
+ BlockCount = (UINT8) (*Length);
+
+ ///
+ /// The "break;" command is not present here to allow code execution
+ /// do drop into the next case, which contains common code to this case.
+ ///
+ case EfiSmbusReadBlock:
+ SmbusOperation = V_PCH_SMBUS_SMB_CMD_BLOCK;
+ if ((*Length < 1) || (*Length > 32)) {
+ Status = EFI_INVALID_PARAMETER;
+ break;
+ }
+
+ AuxcReg |= B_PCH_SMBUS_E32B;
+ break;
+
+ case EfiSmbusProcessCall:
+ SmbusOperation = V_PCH_SMBUS_SMB_CMD_PROCESS_CALL;
+ SmbusIoWrite (R_PCH_SMBUS_HD1, CallBuffer[1]);
+ SmbusIoWrite (R_PCH_SMBUS_HD0, CallBuffer[0]);
+ if (*Length < 2) {
+ Status = EFI_BUFFER_TOO_SMALL;
+ }
+
+ *Length = 2;
+ break;
+
+ case EfiSmbusBWBRProcessCall:
+ ///
+ /// The write byte count cannot be zero or more than
+ /// 32 bytes.
+ ///
+ if ((*Length < 1) || (*Length > 32)) {
+ Status = EFI_INVALID_PARAMETER;
+ break;
+ }
+
+ SmbusIoWrite (R_PCH_SMBUS_HD0, *(UINT8 *) Length);
+ BlockCount = (UINT8) (*Length);
+ SmbusOperation = V_PCH_SMBUS_SMB_CMD_BLOCK_PROCESS;
+
+ AuxcReg |= B_PCH_SMBUS_E32B;
+ break;
+
+ default:
+ Status = EFI_INVALID_PARAMETER;
+ break;
+ }
+
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+
+ if (PecCheck == TRUE) {
+ AuxcReg |= B_PCH_SMBUS_AAC;
+ }
+ ///
+ /// Set Auxiliary Control register
+ ///
+ SmbusIoWrite (R_PCH_SMBUS_AUXC, AuxcReg);
+
+ ///
+ /// Reset the pointer of the internal buffer
+ ///
+ SmbusIoRead (R_PCH_SMBUS_HCTL);
+
+ ///
+ /// Now that the 32 byte buffer is turned on, we can write th block data
+ /// into it
+ ///
+ if ((Operation == EfiSmbusWriteBlock) || (Operation == EfiSmbusBWBRProcessCall)) {
+ for (Index = 0; Index < BlockCount; Index++) {
+ ///
+ /// Write next byte
+ ///
+ SmbusIoWrite (R_PCH_SMBUS_HBD, CallBuffer[Index]);
+ }
+ }
+ ///
+ /// Set SMBus slave address for the device to send/receive from
+ ///
+ SmbusIoWrite (R_PCH_SMBUS_TSA, SlvAddrReg);
+
+ ///
+ /// For I2C read, send DATA1 register for the offset (address)
+ /// within the serial memory chips
+ ///
+ if ((Operation == EfiSmbusReadByte) && (*Length > 1)) {
+ SmbusIoWrite (R_PCH_SMBUS_HD1, HostCmdReg);
+ } else {
+ ///
+ /// Set Command register
+ ///
+ SmbusIoWrite (R_PCH_SMBUS_HCMD, HostCmdReg);
+ }
+ ///
+ /// Set Control Register (Initiate Operation, Interrupt disabled)
+ ///
+ SmbusIoWrite (R_PCH_SMBUS_HCTL, (UINT8) (SmbusOperation + B_PCH_SMBUS_START));
+
+ ///
+ /// Wait for IO to complete
+ ///
+ if (!IoDone (&StsReg)) {
+ Status = EFI_TIMEOUT;
+ break;
+ } else if (StsReg & B_PCH_SMBUS_DERR) {
+ AuxStsReg = SmbusIoRead (R_PCH_SMBUS_AUXS);
+ if (AuxStsReg & B_PCH_SMBUS_CRCE) {
+ Status = EFI_CRC_ERROR;
+ } else {
+ Status = EFI_DEVICE_ERROR;
+ }
+ break;
+ } else if (StsReg & B_PCH_SMBUS_BERR) {
+ ///
+ /// Clear the Bus Error for another try
+ ///
+ Status = EFI_DEVICE_ERROR;
+ SmbusIoWrite (R_PCH_SMBUS_HSTS, B_PCH_SMBUS_BERR);
+ ///
+ /// Clear Status Registers
+ ///
+ SmbusIoWrite (R_PCH_SMBUS_HSTS, B_PCH_SMBUS_HSTS_ALL);
+ SmbusIoWrite (R_PCH_SMBUS_AUXS, B_PCH_SMBUS_CRCE);
+ ///
+ /// If bus collision happens, stall some time, then try again
+ /// Here we choose 10 milliseconds to avoid MTCP transfer.
+ ///
+ MicroSecondDelay (STALL_PERIOD);
+ continue;
+ }
+ ///
+ /// successfull completion
+ /// Operation Specifics (post-execution)
+ ///
+ switch (Operation) {
+
+ case EfiSmbusReadWord:
+ ///
+ /// The "break;" command is not present here to allow code execution
+ /// do drop into the next case, which contains common code to this case.
+ ///
+ case EfiSmbusProcessCall:
+ CallBuffer[1] = SmbusIoRead (R_PCH_SMBUS_HD1);
+ CallBuffer[0] = SmbusIoRead (R_PCH_SMBUS_HD0);
+ break;
+
+ case EfiSmbusReadByte:
+ if (*Length > 1) {
+ for (Index = 0; Index < *Length; Index++) {
+ ///
+ /// Read the byte
+ ///
+ CallBuffer[Index] = SmbusIoRead (R_PCH_SMBUS_HBD);
+ ///
+ /// After receiving byte n-1 (1-base) of the message, the
+ /// software will then set the LAST BYTE bit. The software
+ /// will then clear the BYTE_DONE_STS bit.
+ ///
+ if (Index == ((*Length - 1) - 1)) {
+ SmbusHctl = SmbusIoRead (R_PCH_SMBUS_HCTL) | (UINT8) B_PCH_SMBUS_LAST_BYTE;
+ SmbusIoWrite (R_PCH_SMBUS_HCTL, SmbusHctl);
+ } else if (Index == (*Length - 1)) {
+ ///
+ /// Clear the LAST BYTE bit after receiving byte n (1-base) of the message
+ ///
+ SmbusHctl = SmbusIoRead (R_PCH_SMBUS_HCTL) & (UINT8) ~B_PCH_SMBUS_LAST_BYTE;
+ SmbusIoWrite (R_PCH_SMBUS_HCTL, SmbusHctl);
+ }
+ ///
+ /// Clear the BYTE_DONE_STS bit
+ ///
+ SmbusIoWrite (R_PCH_SMBUS_HSTS, B_PCH_SMBUS_BYTE_DONE_STS);
+ ///
+ /// Check BYTE_DONE_STS bit to know if it has completed transmission
+ /// of a byte. No need to check it for the last byte.
+ ///
+ if (Index < (*Length - 1)) {
+ ///
+ /// If somehow board operates at 10Khz, it will take 0.9 ms (9/10Khz) for another byte.
+ /// Add 10 us delay for a loop of 100 that the total timeout is 1 ms to take care of
+ /// the slowest case.
+ ///
+ for (Timeout = 0; Timeout < 100; Timeout++) {
+ if ((SmbusIoRead (R_PCH_SMBUS_HSTS) & (UINT8) B_PCH_SMBUS_BYTE_DONE_STS) != 0) {
+ break;
+ }
+ ///
+ /// Delay 10 us
+ ///
+ MicroSecondDelay (STALL_PERIOD);
+ }
+
+ if (Timeout >= 100) {
+ Status = EFI_TIMEOUT;
+ break;
+ }
+ }
+ }
+ break;
+ }
+
+ case EfiSmbusReceiveByte:
+ CallBuffer[0] = SmbusIoRead (R_PCH_SMBUS_HD0);
+ break;
+
+ case EfiSmbusWriteBlock:
+ SmbusIoWrite (R_PCH_SMBUS_HSTS, B_PCH_SMBUS_BYTE_DONE_STS);
+ break;
+
+ case EfiSmbusReadBlock:
+ BufferTooSmall = FALSE;
+ ///
+ /// Find out how many bytes will be in the block
+ ///
+ BlockCount = SmbusIoRead (R_PCH_SMBUS_HD0);
+ if (*Length < BlockCount) {
+ BufferTooSmall = TRUE;
+ } else {
+ for (Index = 0; Index < BlockCount; Index++) {
+ ///
+ /// Read the byte
+ ///
+ CallBuffer[Index] = SmbusIoRead (R_PCH_SMBUS_HBD);
+ }
+ }
+
+ *Length = BlockCount;
+ if (BufferTooSmall) {
+ Status = EFI_BUFFER_TOO_SMALL;
+ }
+ break;
+
+ case EfiSmbusBWBRProcessCall:
+ ///
+ /// Find out how many bytes will be in the block
+ ///
+ BlockCount = SmbusIoRead (R_PCH_SMBUS_HD0);
+ ///
+ /// The read byte count cannot be zero.
+ ///
+ if (BlockCount < 1) {
+ Status = EFI_BUFFER_TOO_SMALL;
+ break;
+ }
+ ///
+ /// The combined data payload (the write byte count + the read byte count)
+ /// must not exceed 32 bytes
+ ///
+ if (((UINT8) (*Length) + BlockCount) > 32) {
+ Status = EFI_DEVICE_ERROR;
+ break;
+ }
+
+ for (Index = 0; Index < BlockCount; Index++) {
+ ///
+ /// Read the byte
+ ///
+ CallBuffer[Index] = SmbusIoRead (R_PCH_SMBUS_HBD);
+ }
+
+ *Length = BlockCount;
+ break;
+
+ default:
+ break;
+ };
+
+ if ((StsReg & B_PCH_SMBUS_BERR) && (Status != EFI_BUFFER_TOO_SMALL)) {
+ ///
+ /// Clear the Bus Error for another try
+ ///
+ Status = EFI_DEVICE_ERROR;
+ SmbusIoWrite (R_PCH_SMBUS_HSTS, B_PCH_SMBUS_BERR);
+ ///
+ /// If bus collision happens, stall some time, then try again
+ /// Here we choose 10 milliseconds to avoid MTCP transfer.
+ ///
+ MicroSecondDelay (STALL_PERIOD);
+ continue;
+ } else {
+ break;
+ }
+ }
+ ///
+ /// Clear Status Registers and exit
+ ///
+ SmbusIoWrite (R_PCH_SMBUS_HSTS, B_PCH_SMBUS_HSTS_ALL);
+ SmbusIoWrite (R_PCH_SMBUS_AUXS, B_PCH_SMBUS_CRCE);
+ SmbusIoWrite (R_PCH_SMBUS_AUXC, 0);
+ return Status;
+}
+
+/**
+ This function initializes the Smbus Registers.
+
+**/
+VOID
+InitializeSmbusRegisters (
+ VOID
+ )
+{
+ UINTN SmbusRegBase;
+
+ SmbusRegBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_SMBUS,
+ PCI_FUNCTION_NUMBER_PCH_SMBUS
+ );
+ ///
+ /// Enable the Smbus I/O Enable
+ ///
+ MmioOr8 (SmbusRegBase + PCI_COMMAND_OFFSET, (UINT8) EFI_PCI_COMMAND_IO_SPACE);
+
+ ///
+ /// Enable the Smbus host controller
+ ///
+ MmioAndThenOr8 (
+ SmbusRegBase + R_PCH_SMBUS_HOSTC,
+ (UINT8) (~(B_PCH_SMBUS_HOSTC_SMI_EN | B_PCH_SMBUS_HOSTC_I2C_EN)),
+ B_PCH_SMBUS_HOSTC_HST_EN
+ );
+
+ SmbusIoWrite (R_PCH_SMBUS_HSTS, B_PCH_SMBUS_HSTS_ALL);
+} \ No newline at end of file
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchSmbusCommonLib/PeiDxeSmmPchSmbusCommonLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchSmbusCommonLib/PeiDxeSmmPchSmbusCommonLib.inf
new file mode 100644
index 0000000000..54a67614af
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmPchSmbusCommonLib/PeiDxeSmmPchSmbusCommonLib.inf
@@ -0,0 +1,35 @@
+## @file
+# Component description file for the PchSmbusCommonLib
+#
+# Copyright (c) 2017, 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 = 0x00010005
+ BASE_NAME = PeiDxeSmmPchSmbusCommonLib
+ FILE_GUID = 490CEB45-F3A8-41CD-89CB-C47BF7F7A4B4
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PchSmbusCommonLib
+
+[Sources]
+ PchSmbusExec.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ KabylakeSiliconPkg/SiPkg.dec
+ KabylakeSiliconPkg/KabylakeSiliconPrivate.dec
+
+[LibraryClasses]
+ IoLib
+ DebugLib
+ MmPciLib
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmRstPrivateLib/PeiDxeSmmRstPrivateLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmRstPrivateLib/PeiDxeSmmRstPrivateLib.c
new file mode 100644
index 0000000000..7436a76ec1
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmRstPrivateLib/PeiDxeSmmRstPrivateLib.c
@@ -0,0 +1,216 @@
+/** @file
+ Routines for Rst remapping
+
+Copyright (c) 2017, 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/RstPrivateLib.h>
+#include <PchPcieStorageDetectHob.h>
+
+/**
+ Checks whether device on given Root Port is remap capable
+
+ @param[in] RpNumber Root Port Number
+ @param[in] TempPciBus Temporary Pci Bus
+
+ @retval UINT8 Device Programming Interface
+**/
+UINT8
+RstGetProgInterfaceForRemapDevice (
+ IN UINT32 RpNumber,
+ IN UINT32 TempPciBus
+)
+{
+ UINTN RpDevice;
+ UINTN RpFunction;
+ UINT8 BusNumber;
+ UINTN EpBase;
+ UINT8 PiInterface;
+ UINTN RpBase;
+ UINT8 ClassCode;
+ UINT8 SubClassCode;
+
+
+ DEBUG ((DEBUG_INFO, "Detect storage device on Rp: %d\n", RpNumber));
+
+ GetPchPcieRpDevFun (RpNumber, &RpDevice, &RpFunction);
+ BusNumber = DEFAULT_PCI_BUS_NUMBER_PCH;
+ PiInterface = RST_PCIE_STORAGE_INTERFACE_NONE;
+ RpBase = MmPciBase (BusNumber, (UINT32) RpDevice, (UINT32) RpFunction);
+
+ if (MmioRead16 (RpBase + PCI_VENDOR_ID_OFFSET) == 0xFFFF) {
+ DEBUG((DEBUG_INFO, "RstGetProgInterfaceForRemapDevices: RootPort does not exists Rp = %d\n", RpNumber));
+
+ return PiInterface;
+ }
+
+ //
+ // Assign Temporary Bus Number
+ //
+ MmioAndThenOr32 (
+ RpBase + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET,
+ (UINT32) ~B_PCI_BRIDGE_BNUM_SBBN_SCBN,
+ ((UINT32) (TempPciBus << 8)) | ((UINT32) (TempPciBus << 16))
+ );
+
+ //
+ // A config write is required in order for the device to re-capture the Bus number,
+ // according to PCI Express Base Specification, 2.2.6.2
+ // Write to a read-only register VendorID to not cause any side effects.
+ //
+ EpBase = MmPciBase (TempPciBus, 0, 0);
+ MmioWrite16 (EpBase + PCI_VENDOR_ID_OFFSET, 0);
+
+ //
+ // Read Vendor Id to check if device exists
+ // if not clear bus number and return RST_PCIE_STORAGE_INTERFACE_NONE
+ //
+ if (MmioRead16 (EpBase + PCI_VENDOR_ID_OFFSET) == 0xFFFF) {
+ MmioAnd32 (RpBase + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET, (UINT32) ~B_PCI_BRIDGE_BNUM_SBBN_SCBN);
+ return PiInterface;
+ }
+
+ ClassCode = MmioRead8 (EpBase + R_PCI_BCC_OFFSET);
+ SubClassCode = MmioRead8 (EpBase + R_PCI_SCC_OFFSET);
+ PiInterface = MmioRead8 (EpBase + R_PCI_PI_OFFSET);
+
+ if ( ClassCode == PCI_CLASS_MASS_STORAGE) {
+ DEBUG ((DEBUG_INFO, "RstGetProgInterfaceForRemapDevice: ClassCode = %X, SubClassCode = %X, PiInterface = %X\n", ClassCode, SubClassCode, PiInterface));
+
+ if (SubClassCode == PCI_CLASS_MASS_STORAGE_AHCI) {
+ if (PiInterface == RST_PCIE_STORAGE_INTERFACE_AHCI) {
+ DEBUG ((DEBUG_INFO, "RstGetProgInterfaceForRemapDevice: AHCI Card found on Rp: %d\n", RpNumber));
+
+ }
+ } else if (SubClassCode == PCI_CLASS_MASS_STORAGE_NVME) {
+ if (PiInterface == RST_PCIE_STORAGE_INTERFACE_NVME) {
+ DEBUG ((DEBUG_INFO, "RstGetProgInterfaceForRemapDevice: NVMe Card found on Rp: %d\n", RpNumber));
+
+ }
+ } else if (SubClassCode == PCI_CLASS_MASS_STORAGE_RAID) {
+ DEBUG ((DEBUG_INFO, "RstGetProgInterfaceForRemapDevice: RAID Card found on Rp: %d\n", RpNumber));
+
+ PiInterface = RST_PCIE_STORAGE_INTERFACE_NVME;
+ }
+ }
+ //
+ // Clear temporary bus number
+ //
+ MmioAnd32 (RpBase + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET, (UINT32) ~B_PCI_BRIDGE_BNUM_SBBN_SCBN);
+
+ return PiInterface;
+
+}
+
+/**
+ Check the lane occupied by certain root port according to the root port number and configuration strap
+ Return 8-bit bitmap where each bit represents the lane number (e.g.: return 00000011b means the root port owns 2 lane)
+
+ @param[in] RootPortNum Root Port Number
+
+ @retval UINT8 Lane Occupied by the Root Port (bitmap)
+**/
+UINT8
+RstGetRpLaneOccupyMask (
+ IN UINT32 RootPortNum
+ )
+{
+ EFI_STATUS Status;
+ UINT32 CtrlNum;
+ UINT32 CtrlFirstRpNum;
+ UINT32 Data32;
+ UINT8 LaneOccupied;
+
+ LaneOccupied = 0;
+
+ CtrlNum = RootPortNum / PCH_PCIE_CONTROLLER_PORTS;
+ CtrlFirstRpNum = CtrlNum * PCH_PCIE_CONTROLLER_PORTS;
+
+ //
+ // Read the Root Port Configuration Straps for the link width, and return LaneOccupied by the Root Port accordingly
+ //
+ Status = PchSbiRpPciRead32 (CtrlFirstRpNum, R_PCH_PCIE_STRPFUSECFG, &Data32);
+ ASSERT_EFI_ERROR (Status);
+
+ switch ((Data32 & B_PCH_PCIE_STRPFUSECFG_RPC) >> N_PCH_PCIE_STRPFUSECFG_RPC) {
+ case V_PCH_PCIE_STRPFUSECFG_RPC_4:
+ if (RootPortNum % 4 == 0) {
+ LaneOccupied = (BIT3|BIT2|BIT1|BIT0);
+ }
+ break;
+ case V_PCH_PCIE_STRPFUSECFG_RPC_2_2:
+ if ((RootPortNum % 2 == 0)) {
+ LaneOccupied = (BIT1|BIT0);
+ }
+ break;
+ case V_PCH_PCIE_STRPFUSECFG_RPC_2_1_1:
+ if (RootPortNum % 4 == 0) {
+ LaneOccupied = (BIT1|BIT0);
+ } else if (RootPortNum % 4 != 1) {
+ LaneOccupied = BIT0;
+ }
+ break;
+ case V_PCH_PCIE_STRPFUSECFG_RPC_1_1_1_1:
+ LaneOccupied = BIT0;
+ break;
+ default:
+ break;
+ }
+
+ return LaneOccupied;
+}
+
+/**
+ Checks PCH generation and returns SATA's GCR.PLS bit number according to root port number with a PCIe storage device
+ connected to.
+
+ @param[in] RootPortNum Root port number which PCIe storage device is connected to
+
+ @retval UINT32 Number of GCR.PLS bit representing root port
+**/
+UINT32
+RstPlsBitNumber (
+ IN UINT32 RootPortNum
+ )
+{
+ if ((GetPchGeneration () == KblPch) && (RstGetCycleRouterNumber (RootPortNum) == RST_PCIE_STORAGE_CR_2)) {
+ return RootPortNum - 2 * PCH_PCIE_CONTROLLER_PORTS;
+ } else {
+ return RootPortNum;
+ }
+}
+
+/**
+ Checks if device with given PCI config space address is Intel's Stony Beach.
+
+ @param[in] EndPointPciBase Address of device's PCI config space
+
+ @retval BOOLEAN TRUE if device is Intel's Stony Beach, FALSE othrwise
+**/
+BOOLEAN
+RstIsStonyBeach (
+ IN UINTN EndPointPciBase
+ )
+{
+ UINT16 DeviceVendorId;
+ UINT16 DeviceDeviceId;
+
+ DeviceVendorId = MmioRead16 (EndPointPciBase + PCI_VENDOR_ID_OFFSET);
+ DeviceDeviceId = MmioRead16 (EndPointPciBase + PCI_DEVICE_ID_OFFSET);
+
+ if (DeviceVendorId == RST_STONY_BEACH_VENDOR_ID && DeviceDeviceId == RST_STONY_BEACH_DEVICE_ID) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmRstPrivateLib/PeiDxeSmmRstPrivateLib.inf b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmRstPrivateLib/PeiDxeSmmRstPrivateLib.inf
new file mode 100644
index 0000000000..1bbcc7eda7
--- /dev/null
+++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/LibraryPrivate/PeiDxeSmmRstPrivateLib/PeiDxeSmmRstPrivateLib.inf
@@ -0,0 +1,42 @@
+## @file
+# PCH Rst Library.
+#
+# All function in this library is available for PEI, DXE, and SMM,
+# But do not support UEFI RUNTIME environment call.
+#
+# Copyright (c) 2017, 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 = PeiDxeSmmRstPrivateLib
+FILE_GUID = FD2B63E7-FBBF-4D77-8A52-6702112EFDC1
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = RstPrivateLib
+
+[LibraryClasses]
+BaseLib
+IoLib
+DebugLib
+MmPciLib
+PchInfoLib
+PchPcieRpLib
+PchInitCommonLib
+
+[Packages]
+MdePkg/MdePkg.dec
+KabylakeSiliconPkg/SiPkg.dec
+KabylakeSiliconPkg/KabylakeSiliconPrivate.dec
+
+[Sources]
+PeiDxeSmmRstPrivateLib.c