summaryrefslogtreecommitdiff
path: root/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library
diff options
context:
space:
mode:
authorGuo Mang <mang.guo@intel.com>2016-12-23 12:57:11 +0800
committerGuo Mang <mang.guo@intel.com>2017-05-09 13:02:55 +0800
commitf204d37aca86f4f321a3a8301e847b125005c6de (patch)
treeea783d9bb0e5f83a7bdc89437c8ff9af50ad32d2 /Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library
parent70ba44c1dada5be3847b50b78bd07e45979fd33b (diff)
downloadedk2-platforms-f204d37aca86f4f321a3a8301e847b125005c6de.tar.xz
BroxtonSiPkg: Add Include and Library
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Guo Mang <mang.guo@intel.com>
Diffstat (limited to 'Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library')
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/DxeRuntimePciLibPciExpress/DxeRuntimePciLibPciExpress.c2284
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/DxeRuntimePciLibPciExpress/DxeRuntimePciLibPciExpress.h30
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/DxeRuntimePciLibPciExpress/DxeRuntimePciLibPciExpress.inf47
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/DxeVtdLib/DxeVtdLib.c683
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/DxeVtdLib/DxeVtdLib.inf62
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/PeiDxeSmmPchSerialIoLib/PeiDxeSmmPchSerialIoLib.c293
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/PeiDxeSmmPchSerialIoLib/PeiDxeSmmPchSerialIoLib.inf41
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/PeiDxeSmmPchSerialIoUartLib/PeiDxeSmmPchSerialIoUartLib.c348
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/PeiDxeSmmPchSerialIoUartLib/PeiDxeSmmPchSerialIoUartLib.inf40
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/PeiScPolicyLib/PeiScPolicyLib.c862
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/PeiScPolicyLib/PeiScPolicyLib.inf77
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/PeiScPolicyLib/PeiScPolicyLibrary.h51
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/PeiScPolicyLib/PeiScPreMemPolicyLib.c201
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/PeiScPolicyLib/ScPrintPolicy.c699
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/PeiScPolicyLib/ScPrintPolicyPreMem.c75
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/Private/DxeScHdaLib/DxeScHdaLib.inf46
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/Private/DxeScHdaLib/ScHdaEndpoints.c497
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/Private/DxeScHdaLib/ScHdaLib.c807
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/Private/PeiDxeSmmScPciExpressHelpersLib/PeiDxeSmmScPciExpressHelpersLib.inf45
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/Private/PeiDxeSmmScPciExpressHelpersLib/ScPciExpressHelpersLibrary.c2096
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/Private/PeiDxeSmmScPciExpressHelpersLib/ScPciExpressHelpersLibrary.h48
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/Private/PeiDxeUsbCommonLib/PeiDxeUsbCommonLib.inf53
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/Private/PeiDxeUsbCommonLib/UsbCommonLib.c1172
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/ScPlatformLib/ScCycleDecoding.c739
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/ScPlatformLib/ScPlatformLib.inf46
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/ScPlatformLib/ScPlatformLibrary.c843
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/ScPlatformLib/ScPlatformLibrary.h32
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/ScPlatformLib/ScSbiAccess.c297
28 files changed, 12514 insertions, 0 deletions
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/DxeRuntimePciLibPciExpress/DxeRuntimePciLibPciExpress.c b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/DxeRuntimePciLibPciExpress/DxeRuntimePciLibPciExpress.c
new file mode 100644
index 0000000000..fda7b86fdd
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/DxeRuntimePciLibPciExpress/DxeRuntimePciLibPciExpress.c
@@ -0,0 +1,2284 @@
+/** @file
+ PCI Library using PC Express access.
+
+ Copyright (c) 2005 - 2016, 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.
+
+**/
+
+#include <PiDxe.h>
+#include <Guid/EventGroup.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include "DxeRuntimePciLibPciExpress.h"
+
+#define ASSERT_INVALID_PCI_ADDRESS(A) ASSERT (((A) &~0xfffffff) == 0)
+
+STATIC UINTN mPciExpressBaseAddress;
+
+typedef struct _REGISTERED_ADDRESS_MAP {
+ UINTN PciAddress;
+ UINTN Length;
+ UINTN RuntimeAddress;
+} REGISTERED_ADDRESS_MAP;
+
+#define PCI_LIB_ADDRESS_MAP_MAX_ITEM 64
+
+STATIC REGISTERED_ADDRESS_MAP mPciLibAddressMap[PCI_LIB_ADDRESS_MAP_MAX_ITEM];
+
+STATIC UINTN mPciLibAddressMapIndex = 0;
+
+STATIC EFI_EVENT mVirtualAddressChangeEvent;
+
+#ifndef __GNUC__
+
+//
+// Code not used
+//
+/**
+ Get the base address of PCI Express memory space.
+
+ @retval VOID* Return the pointer which points to base address of PCI Express.
+
+**/
+static
+VOID *
+EFIAPI
+GetPciExpressBaseAddress (
+ VOID
+ )
+{
+ return (VOID *) (mPciExpressBaseAddress);
+}
+#endif
+
+
+/**
+ Generate Pci Express address.
+ If Address > 0x0FFFFFFF or can't get the match Pci address, then ASSERT().
+
+ @param[in] Address Pci address.
+
+ @retval UINTN Pci Express address.
+
+**/
+static
+UINTN
+EFIAPI
+PreparePciExpressAddress (
+ IN UINTN Address
+ )
+{
+ UINTN Index;
+
+ ASSERT_INVALID_PCI_ADDRESS (Address);
+
+ if (EfiAtRuntime () == FALSE) {
+ return mPciExpressBaseAddress + Address;
+ }
+
+ for (Index = 0; Index < PCI_LIB_ADDRESS_MAP_MAX_ITEM; Index++) {
+ if ((Address >= mPciLibAddressMap[Index].PciAddress) &&
+ (Address < mPciLibAddressMap[Index].PciAddress + mPciLibAddressMap[Index].Length)
+ ) {
+ return mPciLibAddressMap[Index].RuntimeAddress + (Address - mPciLibAddressMap[Index].PciAddress);
+ }
+ }
+
+ ASSERT (FALSE);
+ CpuDeadLoop ();
+ return 0;
+}
+
+
+/**
+ Reads and returns the 8-bit PCI configuration register specified by Address.
+ This function must guarantee that all PCI read and write operations are
+ serialized.
+ If Address > 0x0FFFFFFF, then ASSERT().
+
+ @param[in] Address Address that encodes the PCI Bus, Device, Function and Register.
+
+ @retval UINT8 return The read value from the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciExpressRead8 (
+ IN UINTN Address
+ )
+{
+ return MmioRead8 (PreparePciExpressAddress (Address));
+}
+
+
+/**
+ Writes the 8-bit PCI configuration register specified by Address with the
+ value specified by Value. Value is returned. This function must guarantee
+ that all PCI read and write operations are serialized.
+ If Address > 0x0FFFFFFF, then ASSERT().
+
+ @param[in] Address Address that encodes the PCI Bus, Device, Function and Register.
+ @param[in] Value The value to write
+
+ @retval UINT8 The value to write to the MMIO register.
+
+**/
+UINT8
+EFIAPI
+PciExpressWrite8 (
+ IN UINTN Address,
+ IN UINT8 Value
+ )
+{
+ return MmioWrite8 (PreparePciExpressAddress (Address), Value);
+}
+
+
+/**
+ Reads the 8-bit PCI configuration register specified by Address, performs a
+ bitwise inclusive OR between the read result and the value specified by
+ OrData, and writes the result to the 8-bit PCI configuration register
+ specified by Address. The value written to the PCI configuration register is
+ returned. This function must guarantee that all PCI read and write operations
+ are serialized.
+ If Address > 0x0FFFFFFF, then ASSERT().
+
+ @param[in] Address Address that encodes the PCI Bus, Device, Function and Register.
+ @param[in] OrData The value to OR with the PCI configuration register.
+
+ @retval UINT8 The value written back to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciExpressOr8 (
+ IN UINTN Address,
+ IN UINT8 OrData
+ )
+{
+ return MmioOr8 (PreparePciExpressAddress (Address), OrData);
+}
+
+
+/**
+ Reads the 8-bit PCI configuration register specified by Address, performs a
+ bitwise AND between the read result and the value specified by AndData, and
+ writes the result to the 8-bit PCI configuration register specified by
+ Address. The value written to the PCI configuration register is returned.
+ This function must guarantee that all PCI read and write operations are
+ serialized.
+ If Address > 0x0FFFFFFF, then ASSERT().
+
+ @param[in] Address Address that encodes the PCI Bus, Device, Function and Register.
+ @param[in] AndData The value to AND with the PCI configuration register.
+
+ @retval UINT8 The value written back to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciExpressAnd8 (
+ IN UINTN Address,
+ IN UINT8 AndData
+ )
+{
+ return MmioAnd8 (PreparePciExpressAddress (Address), AndData);
+}
+
+
+/**
+ Reads the 8-bit PCI configuration register specified by Address, performs a
+ bitwise AND between the read result and the value specified by AndData,
+ performs a bitwise inclusive OR between the result of the AND operation and
+ the value specified by OrData, and writes the result to the 8-bit PCI
+ configuration register specified by Address. The value written to the PCI
+ configuration register is returned. This function must guarantee that all PCI
+ read and write operations are serialized.
+ If Address > 0x0FFFFFFF, then ASSERT().
+
+ @param[in] Address Address that encodes the PCI Bus, Device, Function and Register.
+ @param[in] AndData The value to AND with the PCI configuration register.
+ @param[in] OrData The value to OR with the result of the AND operation.
+
+ @retval UINT8 The value written back to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciExpressAndThenOr8 (
+ IN UINTN Address,
+ IN UINT8 AndData,
+ IN UINT8 OrData
+ )
+{
+ return MmioAndThenOr8 (
+ PreparePciExpressAddress (Address),
+ AndData,
+ OrData
+ );
+}
+
+
+/**
+ Reads the bit field in an 8-bit PCI configuration register. The bit field is
+ specified by the StartBit and the EndBit. The value of the bit field is
+ returned.
+ If Address > 0x0FFFFFFF, then ASSERT().
+ If StartBit is greater than 7, then ASSERT().
+ If EndBit is greater than 7, then ASSERT().
+ If EndBit is less than StartBit, then ASSERT().
+
+ @param[in] Address PCI configuration register to read.
+ @param[in] StartBit The original of the least significant bit in the bit field. Range 0..7.
+ @param[in] EndBit The original of the most significant bit in the bit field. Range 0..7.
+
+ @retval UINT8 The value of the bit field read from the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciExpressBitFieldRead8 (
+ IN UINTN Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit
+ )
+{
+ return MmioBitFieldRead8 (
+ PreparePciExpressAddress (Address),
+ StartBit,
+ EndBit
+ );
+}
+
+
+/**
+ Writes Value to the bit field of the PCI configuration register. The bit
+ field is specified by the StartBit and the EndBit. All other bits in the
+ destination PCI configuration register are preserved. The new value of the
+ 8-bit register is returned.
+ If Address > 0x0FFFFFFF, then ASSERT().
+ If StartBit is greater than 7, then ASSERT().
+ If EndBit is greater than 7, then ASSERT().
+ If EndBit is less than StartBit, then ASSERT().
+
+ @param[in] Address PCI configuration register to write.
+ @param[in] StartBit The original of the least significant bit in the bit field. Range 0..7.
+ @param[in] EndBit The original of the most significant bit in the bit field. Range 0..7.
+ @param[in] Value New value of the bit field.
+
+ @retval UINT8 The value written back to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciExpressBitFieldWrite8 (
+ IN UINTN Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit,
+ IN UINT8 Value
+ )
+{
+ return MmioBitFieldWrite8 (
+ PreparePciExpressAddress (Address),
+ StartBit,
+ EndBit,
+ Value
+ );
+}
+
+
+/**
+ Reads the 8-bit PCI configuration register specified by Address, performs a
+ bitwise inclusive OR between the read result and the value specified by
+ OrData, and writes the result to the 8-bit PCI configuration register
+ specified by Address. The value written to the PCI configuration register is
+ returned. This function must guarantee that all PCI read and write operations
+ are serialized. Extra left bits in OrData are stripped.
+ If Address > 0x0FFFFFFF, then ASSERT().
+ If StartBit is greater than 7, then ASSERT().
+ If EndBit is greater than 7, then ASSERT().
+ If EndBit is less than StartBit, then ASSERT().
+
+ @param[in] Address PCI configuration register to write.
+ @param[in] StartBit The original of the least significant bit in the bit field. Range 0..7.
+ @param[in] EndBit The original of the most significant bit in the bit field. Range 0..7.
+ @param[in] OrData The value to OR with the PCI configuration register.
+
+ @retval UINT8 The value written back to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciExpressBitFieldOr8 (
+ IN UINTN Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit,
+ IN UINT8 OrData
+ )
+{
+ return MmioBitFieldOr8 (
+ PreparePciExpressAddress (Address),
+ StartBit,
+ EndBit,
+ OrData
+ );
+}
+
+
+/**
+ Reads the 8-bit PCI configuration register specified by Address, performs a
+ bitwise AND between the read result and the value specified by AndData, and
+ writes the result to the 8-bit PCI configuration register specified by
+ Address. The value written to the PCI configuration register is returned.
+ This function must guarantee that all PCI read and write operations are
+ serialized. Extra left bits in AndData are stripped.
+ If Address > 0x0FFFFFFF, then ASSERT().
+ If StartBit is greater than 7, then ASSERT().
+ If EndBit is greater than 7, then ASSERT().
+ If EndBit is less than StartBit, then ASSERT().
+
+ @param[in] Address PCI configuration register to write.
+ @param[in] StartBit The original of the least significant bit in the bit field. Range 0..7.
+ @param[in] EndBit The original of the most significant bit in the bit field. Range 0..7.
+ @param[in] AndData The value to AND with the PCI configuration register.
+
+ @retval UINT8 The value written back to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciExpressBitFieldAnd8 (
+ IN UINTN Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit,
+ IN UINT8 AndData
+ )
+{
+ return MmioBitFieldAnd8 (
+ PreparePciExpressAddress (Address),
+ StartBit,
+ EndBit,
+ AndData
+ );
+}
+
+
+/**
+ Reads the 8-bit PCI configuration register specified by Address, performs a
+ bitwise AND followed by a bitwise inclusive OR between the read result and
+ the value specified by AndData, and writes the result to the 8-bit PCI
+ configuration register specified by Address. The value written to the PCI
+ configuration register is returned. This function must guarantee that all PCI
+ read and write operations are serialized. Extra left bits in both AndData and
+ OrData are stripped.
+ If Address > 0x0FFFFFFF, then ASSERT().
+ If StartBit is greater than 7, then ASSERT().
+ If EndBit is greater than 7, then ASSERT().
+ If EndBit is less than StartBit, then ASSERT().
+
+ @param[in] Address PCI configuration register to write.
+ @param[in] StartBit The original of the least significant bit in the bit field. Range 0..7.
+ @param[in] EndBit The original of the most significant bit in the bit field. Range 0..7.
+ @param[in] AndData The value to AND with the PCI configuration register.
+ @param[in] OrData The value to OR with the result of the AND operation.
+
+ @retval UINT8 The value written back to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciExpressBitFieldAndThenOr8 (
+ IN UINTN Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit,
+ IN UINT8 AndData,
+ IN UINT8 OrData
+ )
+{
+ return MmioBitFieldAndThenOr8 (
+ PreparePciExpressAddress (Address),
+ StartBit,
+ EndBit,
+ AndData,
+ OrData
+ );
+}
+
+
+/**
+ Reads and returns the 16-bit PCI configuration register specified by Address.
+ This function must guarantee that all PCI read and write operations are
+ serialized.
+ If Address > 0x0FFFFFFF, then ASSERT().
+ If Address is not aligned on a 16-bit boundary, then ASSERT().
+
+ @param[in] Address Address that encodes the PCI Bus, Device, Function and Register.
+
+ @retval UINT16 The read value from the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciExpressRead16 (
+ IN UINTN Address
+ )
+{
+ return MmioRead16 (PreparePciExpressAddress (Address));
+}
+
+
+/**
+ Writes the 16-bit PCI configuration register specified by Address with the
+ value specified by Value. Value is returned. This function must guarantee
+ that all PCI read and write operations are serialized.
+ If Address > 0x0FFFFFFF, then ASSERT().
+ If Address is not aligned on a 16-bit boundary, then ASSERT().
+
+ @param[in] Address Address that encodes the PCI Bus, Device, Function and Register.
+ @param[in] Value The value to write.
+
+ @retval UINT16 The value written to the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciExpressWrite16 (
+ IN UINTN Address,
+ IN UINT16 Value
+ )
+{
+ return MmioWrite16 (PreparePciExpressAddress (Address), Value);
+}
+
+
+/**
+ Reads the 16-bit PCI configuration register specified by Address, performs a
+ bitwise inclusive OR between the read result and the value specified by
+ OrData, and writes the result to the 16-bit PCI configuration register
+ specified by Address. The value written to the PCI configuration register is
+ returned. This function must guarantee that all PCI read and write operations
+ are serialized.
+ If Address > 0x0FFFFFFF, then ASSERT().
+ If Address is not aligned on a 16-bit boundary, then ASSERT().
+
+ @param[in] Address Address that encodes the PCI Bus, Device, Function and Register.
+ @param[in] OrData The value to OR with the PCI configuration register.
+
+ @retval UINT16 The value written back to the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciExpressOr16 (
+ IN UINTN Address,
+ IN UINT16 OrData
+ )
+{
+ return MmioOr16 (PreparePciExpressAddress (Address), OrData);
+}
+
+
+/**
+ Reads the 16-bit PCI configuration register specified by Address, performs a
+ bitwise AND between the read result and the value specified by AndData, and
+ writes the result to the 16-bit PCI configuration register specified by
+ Address. The value written to the PCI configuration register is returned.
+ This function must guarantee that all PCI read and write operations are
+ serialized.
+ If Address > 0x0FFFFFFF, then ASSERT().
+ If Address is not aligned on a 16-bit boundary, then ASSERT().
+
+ @param[in] Address Address that encodes the PCI Bus, Device, Function and Register.
+ @param[in] AndData The value to AND with the PCI configuration register.
+
+ @retval UINT16 The value written back to the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciExpressAnd16 (
+ IN UINTN Address,
+ IN UINT16 AndData
+ )
+{
+ return MmioAnd16 (PreparePciExpressAddress (Address), AndData);
+}
+
+
+/**
+ Reads the 16-bit PCI configuration register specified by Address, performs a
+ bitwise AND between the read result and the value specified by AndData,
+ performs a bitwise inclusive OR between the result of the AND operation and
+ the value specified by OrData, and writes the result to the 16-bit PCI
+ configuration register specified by Address. The value written to the PCI
+ configuration register is returned. This function must guarantee that all PCI
+ read and write operations are serialized.
+ If Address > 0x0FFFFFFF, then ASSERT().
+ If Address is not aligned on a 16-bit boundary, then ASSERT().
+
+ @param[in] Address Address that encodes the PCI Bus, Device, Function and Register.
+ @param[in] AndData The value to AND with the PCI configuration register.
+ @param[in] OrData The value to OR with the result of the AND operation.
+
+ @retval UINT16 The value written back to the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciExpressAndThenOr16 (
+ IN UINTN Address,
+ IN UINT16 AndData,
+ IN UINT16 OrData
+ )
+{
+ return MmioAndThenOr16 (
+ PreparePciExpressAddress (Address),
+ AndData,
+ OrData
+ );
+}
+
+
+/**
+ Reads the bit field in a 16-bit PCI configuration register. The bit field is
+ specified by the StartBit and the EndBit. The value of the bit field is
+ returned.
+ If Address > 0x0FFFFFFF, then ASSERT().
+ If Address is not aligned on a 16-bit boundary, then ASSERT().
+ If StartBit is greater than 15, then ASSERT().
+ If EndBit is greater than 15, then ASSERT().
+ If EndBit is less than StartBit, then ASSERT().
+
+ @param[in] Address PCI configuration register to read.
+ @param[in] StartBit The original of the least significant bit in the bit field. Range 0..15.
+ @param[in] EndBit The original of the most significant bit in the bit field. Range 0..15.
+
+ @retval UINT16 The value of the bit field read from the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciExpressBitFieldRead16 (
+ IN UINTN Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit
+ )
+{
+ return MmioBitFieldRead16 (
+ PreparePciExpressAddress (Address),
+ StartBit,
+ EndBit
+ );
+}
+
+
+/**
+ Writes Value to the bit field of the PCI configuration register. The bit
+ field is specified by the StartBit and the EndBit. All other bits in the
+ destination PCI configuration register are preserved. The new value of the
+ 16-bit register is returned.
+ If Address > 0x0FFFFFFF, then ASSERT().
+ If Address is not aligned on a 16-bit boundary, then ASSERT().
+ If StartBit is greater than 15, then ASSERT().
+ If EndBit is greater than 15, then ASSERT().
+ If EndBit is less than StartBit, then ASSERT().
+
+ @param[in] Address PCI configuration register to write.
+ @param[in] StartBit The original of the least significant bit in the bit field. Range 0..15.
+ @param[in] EndBit The original of the most significant bit in the bit field. Range 0..15.
+ @param[in] Value New value of the bit field.
+
+ @retval UINT16 The value written back to the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciExpressBitFieldWrite16 (
+ IN UINTN Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit,
+ IN UINT16 Value
+ )
+{
+ return MmioBitFieldWrite16 (
+ PreparePciExpressAddress (Address),
+ StartBit,
+ EndBit,
+ Value
+ );
+}
+
+
+/**
+ Reads the 16-bit PCI configuration register specified by Address, performs a
+ bitwise inclusive OR between the read result and the value specified by
+ OrData, and writes the result to the 16-bit PCI configuration register
+ specified by Address. The value written to the PCI configuration register is
+ returned. This function must guarantee that all PCI read and write operations
+ are serialized. Extra left bits in OrData are stripped.
+ If Address > 0x0FFFFFFF, then ASSERT().
+ If Address is not aligned on a 16-bit boundary, then ASSERT().
+ If StartBit is greater than 15, then ASSERT().
+ If EndBit is greater than 15, then ASSERT().
+ If EndBit is less than StartBit, then ASSERT().
+
+ @param[in] Address PCI configuration register to write.
+ @param[in] StartBit The original of the least significant bit in the bit field. Range 0..15.
+ @param[in] EndBit The original of the most significant bit in the bit field. Range 0..15.
+ @param[in] OrData The value to OR with the PCI configuration register.
+
+ @retval UINT16 The value written back to the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciExpressBitFieldOr16 (
+ IN UINTN Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit,
+ IN UINT16 OrData
+ )
+{
+ return MmioBitFieldOr16 (
+ PreparePciExpressAddress (Address),
+ StartBit,
+ EndBit,
+ OrData
+ );
+}
+
+
+/**
+ Reads the 16-bit PCI configuration register specified by Address, performs a
+ bitwise AND between the read result and the value specified by AndData, and
+ writes the result to the 16-bit PCI configuration register specified by
+ Address. The value written to the PCI configuration register is returned.
+ This function must guarantee that all PCI read and write operations are
+ serialized. Extra left bits in AndData are stripped.
+ If Address > 0x0FFFFFFF, then ASSERT().
+ If Address is not aligned on a 16-bit boundary, then ASSERT().
+ If StartBit is greater than 15, then ASSERT().
+ If EndBit is greater than 15, then ASSERT().
+ If EndBit is less than StartBit, then ASSERT().
+
+ @param[in] Address PCI configuration register to write.
+ @param[in] StartBit The original of the least significant bit in the bit field. Range 0..15.
+ @param[in] EndBit The original of the most significant bit in the bit field. Range 0..15.
+ @param[in] AndData The value to AND with the PCI configuration register.
+
+ @retval UINT16 The value written back to the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciExpressBitFieldAnd16 (
+ IN UINTN Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit,
+ IN UINT16 AndData
+ )
+{
+ return MmioBitFieldAnd16 (
+ PreparePciExpressAddress (Address),
+ StartBit,
+ EndBit,
+ AndData
+ );
+}
+
+
+/**
+ Reads the 16-bit PCI configuration register specified by Address, performs a
+ bitwise AND followed by a bitwise inclusive OR between the read result and
+ the value specified by AndData, and writes the result to the 16-bit PCI
+ configuration register specified by Address. The value written to the PCI
+ configuration register is returned. This function must guarantee that all PCI
+ read and write operations are serialized. Extra left bits in both AndData and
+ OrData are stripped.
+ If Address > 0x0FFFFFFF, then ASSERT().
+ If Address is not aligned on a 16-bit boundary, then ASSERT().
+ If StartBit is greater than 15, then ASSERT().
+ If EndBit is greater than 15, then ASSERT().
+ If EndBit is less than StartBit, then ASSERT().
+
+ @param[in] Address PCI configuration register to write.
+ @param[in] StartBit The original of the least significant bit in the bit field. Range 0..15.
+ @param[in] EndBit The original of the most significant bit in the bit field. Range 0..15.
+ @param[in] AndData The value to AND with the PCI configuration register.
+ @param[in] OrData The value to OR with the result of the AND operation.
+
+ @retval UINT16 The value written back to the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciExpressBitFieldAndThenOr16 (
+ IN UINTN Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit,
+ IN UINT16 AndData,
+ IN UINT16 OrData
+ )
+{
+ return MmioBitFieldAndThenOr16 (
+ PreparePciExpressAddress (Address),
+ StartBit,
+ EndBit,
+ AndData,
+ OrData
+ );
+}
+
+
+/**
+ Reads and returns the 32-bit PCI configuration register specified by Address.
+ This function must guarantee that all PCI read and write operations are
+ serialized.
+ If Address > 0x0FFFFFFF, then ASSERT().
+ If Address is not aligned on a 32-bit boundary, then ASSERT().
+
+ @param[in] Address Address that encodes the PCI Bus, Device, Function and Register.
+
+ @retval UINT32 The read value from the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciExpressRead32 (
+ IN UINTN Address
+ )
+{
+ return MmioRead32 (PreparePciExpressAddress (Address));
+}
+
+
+/**
+ Writes the 32-bit PCI configuration register specified by Address with the
+ value specified by Value. Value is returned. This function must guarantee
+ that all PCI read and write operations are serialized.
+ If Address > 0x0FFFFFFF, then ASSERT().
+ If Address is not aligned on a 32-bit boundary, then ASSERT().
+
+ @param[in] Address Address that encodes the PCI Bus, Device, Function and Register.
+ @param[in] Value The value to write.
+
+ @retval UINT32 The value written to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciExpressWrite32 (
+ IN UINTN Address,
+ IN UINT32 Value
+ )
+{
+ return MmioWrite32 (PreparePciExpressAddress (Address), Value);
+}
+
+
+/**
+ Reads the 32-bit PCI configuration register specified by Address, performs a
+ bitwise inclusive OR between the read result and the value specified by
+ OrData, and writes the result to the 32-bit PCI configuration register
+ specified by Address. The value written to the PCI configuration register is
+ returned. This function must guarantee that all PCI read and write operations
+ are serialized.
+ If Address > 0x0FFFFFFF, then ASSERT().
+ If Address is not aligned on a 32-bit boundary, then ASSERT().
+
+ @param[in] Address Address that encodes the PCI Bus, Device, Function and Register.
+ @param[in] OrData The value to OR with the PCI configuration register.
+
+ @retval UINT32 The value written back to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciExpressOr32 (
+ IN UINTN Address,
+ IN UINT32 OrData
+ )
+{
+ return MmioOr32 (PreparePciExpressAddress (Address), OrData);
+}
+
+
+/**
+ Reads the 32-bit PCI configuration register specified by Address, performs a
+ bitwise AND between the read result and the value specified by AndData, and
+ writes the result to the 32-bit PCI configuration register specified by
+ Address. The value written to the PCI configuration register is returned.
+ This function must guarantee that all PCI read and write operations are
+ serialized.
+ If Address > 0x0FFFFFFF, then ASSERT().
+ If Address is not aligned on a 32-bit boundary, then ASSERT().
+
+ @param[in] Address Address that encodes the PCI Bus, Device, Function and Register.
+ @param[in] AndData The value to AND with the PCI configuration register.
+
+ @retval UINT32 The value written back to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciExpressAnd32 (
+ IN UINTN Address,
+ IN UINT32 AndData
+ )
+{
+ return MmioAnd32 (PreparePciExpressAddress (Address), AndData);
+}
+
+
+/**
+ Reads the 32-bit PCI configuration register specified by Address, performs a
+ bitwise AND between the read result and the value specified by AndData,
+ performs a bitwise inclusive OR between the result of the AND operation and
+ the value specified by OrData, and writes the result to the 32-bit PCI
+ configuration register specified by Address. The value written to the PCI
+ configuration register is returned. This function must guarantee that all PCI
+ read and write operations are serialized.
+ If Address > 0x0FFFFFFF, then ASSERT().
+ If Address is not aligned on a 32-bit boundary, then ASSERT().
+
+ @param[in] Address Address that encodes the PCI Bus, Device, Function and Register.
+ @param[in] AndData The value to AND with the PCI configuration register.
+ @param[in] OrData The value to OR with the result of the AND operation.
+
+ @retval UINT32 The value written back to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciExpressAndThenOr32 (
+ IN UINTN Address,
+ IN UINT32 AndData,
+ IN UINT32 OrData
+ )
+{
+ return MmioAndThenOr32 (
+ PreparePciExpressAddress (Address),
+ AndData,
+ OrData
+ );
+}
+
+
+/**
+ Reads the bit field in a 32-bit PCI configuration register. The bit field is
+ specified by the StartBit and the EndBit. The value of the bit field is
+ returned.
+ If Address > 0x0FFFFFFF, then ASSERT().
+ If Address is not aligned on a 32-bit boundary, then ASSERT().
+ If StartBit is greater than 31, then ASSERT().
+ If EndBit is greater than 31, then ASSERT().
+ If EndBit is less than StartBit, then ASSERT().
+
+ @param[in] Address PCI configuration register to read.
+ @param[in] StartBit The original of the least significant bit in the bit field. Range 0..31.
+ @param[in] EndBit The original of the most significant bit in the bit field. Range 0..31.
+
+ @retval UNT32 The value of the bit field read from the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciExpressBitFieldRead32 (
+ IN UINTN Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit
+ )
+{
+ return MmioBitFieldRead32 (
+ PreparePciExpressAddress (Address),
+ StartBit,
+ EndBit
+ );
+}
+
+
+/**
+ Writes Value to the bit field of the PCI configuration register. The bit
+ field is specified by the StartBit and the EndBit. All other bits in the
+ destination PCI configuration register are preserved. The new value of the
+ 32-bit register is returned.
+ If Address > 0x0FFFFFFF, then ASSERT().
+ If Address is not aligned on a 32-bit boundary, then ASSERT().
+ If StartBit is greater than 31, then ASSERT().
+ If EndBit is greater than 31, then ASSERT().
+ If EndBit is less than StartBit, then ASSERT().
+
+ @param[in] Address PCI configuration register to write.
+ @param[in] StartBit The original of the least significant bit in the bit field. Range 0..31.
+ @param[in] EndBit The original of the most significant bit in the bit field. Range 0..31.
+ @param[in] Value New value of the bit field.
+
+ @retval UINT32 The value written back to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciExpressBitFieldWrite32 (
+ IN UINTN Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit,
+ IN UINT32 Value
+ )
+{
+ return MmioBitFieldWrite32 (
+ PreparePciExpressAddress (Address),
+ StartBit,
+ EndBit,
+ Value
+ );
+}
+
+
+/**
+ Reads the 32-bit PCI configuration register specified by Address, performs a
+ bitwise inclusive OR between the read result and the value specified by
+ OrData, and writes the result to the 32-bit PCI configuration register
+ specified by Address. The value written to the PCI configuration register is
+ returned. This function must guarantee that all PCI read and write operations
+ are serialized. Extra left bits in OrData are stripped.
+ If Address > 0x0FFFFFFF, then ASSERT().
+ If Address is not aligned on a 32-bit boundary, then ASSERT().
+ If StartBit is greater than 31, then ASSERT().
+ If EndBit is greater than 31, then ASSERT().
+ If EndBit is less than StartBit, then ASSERT().
+
+ @param[in] Address PCI configuration register to write.
+ @param[in] StartBit The original of the least significant bit in the bit field. Range 0..31.
+ @param[in] EndBit The original of the most significant bit in the bit field. Range 0..31.
+ @param[in] OrData The value to OR with the PCI configuration register.
+
+ @retval UINT32 The value written back to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciExpressBitFieldOr32 (
+ IN UINTN Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit,
+ IN UINT32 OrData
+ )
+{
+ return MmioBitFieldOr32 (
+ PreparePciExpressAddress (Address),
+ StartBit,
+ EndBit,
+ OrData
+ );
+}
+
+
+/**
+ Reads the 32-bit PCI configuration register specified by Address, performs a
+ bitwise AND between the read result and the value specified by AndData, and
+ writes the result to the 32-bit PCI configuration register specified by
+ Address. The value written to the PCI configuration register is returned.
+ This function must guarantee that all PCI read and write operations are
+ serialized. Extra left bits in AndData are stripped.
+ If Address > 0x0FFFFFFF, then ASSERT().
+ If Address is not aligned on a 32-bit boundary, then ASSERT().
+ If StartBit is greater than 31, then ASSERT().
+ If EndBit is greater than 31, then ASSERT().
+ If EndBit is less than StartBit, then ASSERT().
+
+ @param[in] Address PCI configuration register to write.
+ @param[in] StartBit The original of the least significant bit in the bit field. Range 0..31.
+ @param[in] EndBit The original of the most significant bit in the bit field. Range 0..31.
+ @param[in] AndData The value to AND with the PCI configuration register.
+
+ @retval UINT32 The value written back to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciExpressBitFieldAnd32 (
+ IN UINTN Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit,
+ IN UINT32 AndData
+ )
+{
+ return MmioBitFieldAnd32 (
+ PreparePciExpressAddress (Address),
+ StartBit,
+ EndBit,
+ AndData
+ );
+}
+
+
+/**
+ Reads the 32-bit PCI configuration register specified by Address, performs a
+ bitwise AND followed by a bitwise inclusive OR between the read result and
+ the value specified by AndData, and writes the result to the 32-bit PCI
+ configuration register specified by Address. The value written to the PCI
+ configuration register is returned. This function must guarantee that all PCI
+ read and write operations are serialized. Extra left bits in both AndData and
+ OrData are stripped.
+ If Address > 0x0FFFFFFF, then ASSERT().
+ If Address is not aligned on a 32-bit boundary, then ASSERT().
+ If StartBit is greater than 31, then ASSERT().
+ If EndBit is greater than 31, then ASSERT().
+ If EndBit is less than StartBit, then ASSERT().
+
+ @param[in] Address PCI configuration register to write.
+ @param[in] StartBit The original of the least significant bit in the bit field. Range 0..31.
+ @param[in] EndBit The original of the most significant bit in the bit field. Range 0..31.
+ @param[in] AndData The value to AND with the PCI configuration register.
+ @param[in] OrData The value to OR with the result of the AND operation.
+
+ @retval UINT32 The value written back to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciExpressBitFieldAndThenOr32 (
+ IN UINTN Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit,
+ IN UINT32 AndData,
+ IN UINT32 OrData
+ )
+{
+ return MmioBitFieldAndThenOr32 (
+ PreparePciExpressAddress (Address),
+ StartBit,
+ EndBit,
+ AndData,
+ OrData
+ );
+}
+
+
+/**
+ Reads the range of PCI configuration registers specified by StartAddress and
+ Size into the buffer specified by Buffer. This function only allows the PCI
+ configuration registers from a single PCI function to be read. Size is
+ returned. When possible 32-bit PCI configuration read cycles are used to read
+ from StartAdress to StartAddress + Size. Due to alignment restrictions, 8-bit
+ and 16-bit PCI configuration read cycles may be used at the beginning and the
+ end of the range.
+ If StartAddress > 0x0FFFFFFF, then ASSERT().
+ If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT().
+ If Size > 0 and Buffer is NULL, then ASSERT().
+
+ @param[in] StartAddress Starting address that encodes the PCI Bus, Device, Function and Register.
+ @param[in] Size Size in bytes of the transfer.
+ @param[out] Buffer Pointer to a buffer receiving the data read.
+
+ @retval UINTN Size in bytes of the transfer.
+
+**/
+UINTN
+EFIAPI
+PciExpressReadBuffer (
+ IN UINTN StartAddress,
+ IN UINTN Size,
+ OUT VOID *Buffer
+ )
+{
+ UINTN ReturnValue;
+
+ ASSERT (((StartAddress & 0xFFF) + Size) <= 0x1000);
+
+ if (Size == 0) {
+ return Size;
+ }
+
+ if (Buffer == NULL) {
+ ASSERT (Buffer != NULL);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Save Size for return
+ //
+ ReturnValue = Size;
+
+ if ((StartAddress & 1) != 0) {
+ //
+ // Read a byte if StartAddress is byte aligned
+ //
+ *(volatile UINT8 *) Buffer = PciExpressRead8 (StartAddress);
+ StartAddress += sizeof (UINT8);
+ Size -= sizeof (UINT8);
+ Buffer = (UINT8 *) Buffer + 1;
+ }
+
+ if (Size >= sizeof (UINT16) && (StartAddress & 2) != 0) {
+ //
+ // Read a word if StartAddress is word aligned
+ //
+ *(volatile UINT16 *) Buffer = PciExpressRead16 (StartAddress);
+ StartAddress += sizeof (UINT16);
+ Size -= sizeof (UINT16);
+ Buffer = (UINT16 *) Buffer + 1;
+ }
+
+ while (Size >= sizeof (UINT32)) {
+ //
+ // Read as many double words as possible
+ //
+ *(volatile UINT32 *) Buffer = PciExpressRead32 (StartAddress);
+ StartAddress += sizeof (UINT32);
+ Size -= sizeof (UINT32);
+ Buffer = (UINT32 *) Buffer + 1;
+ }
+
+ if (Size >= sizeof (UINT16)) {
+ //
+ // Read the last remaining word if exist
+ //
+ *(volatile UINT16 *) Buffer = PciExpressRead16 (StartAddress);
+ StartAddress += sizeof (UINT16);
+ Size -= sizeof (UINT16);
+ Buffer = (UINT16 *) Buffer + 1;
+ }
+
+ if (Size >= sizeof (UINT8)) {
+ //
+ // Read the last remaining byte if exist
+ //
+ *(volatile UINT8 *) Buffer = PciExpressRead8 (StartAddress);
+ }
+
+ return ReturnValue;
+}
+
+
+/**
+ Writes the range of PCI configuration registers specified by StartAddress and
+ Size from the buffer specified by Buffer. This function only allows the PCI
+ configuration registers from a single PCI function to be written. Size is
+ returned. When possible 32-bit PCI configuration write cycles are used to
+ write from StartAdress to StartAddress + Size. Due to alignment restrictions,
+ 8-bit and 16-bit PCI configuration write cycles may be used at the beginning
+ and the end of the range.
+ If StartAddress > 0x0FFFFFFF, then ASSERT().
+ If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT().
+ If Size > 0 and Buffer is NULL, then ASSERT().
+
+ @param[in] StartAddress Starting address that encodes the PCI Bus, Device, Function and Register.
+ @param[in] Size Size in bytes of the transfer.
+ @param[in] Buffer Pointer to a buffer containing the data to write.
+
+ @retval UINTN Size in bytes of the transfer.
+
+**/
+UINTN
+EFIAPI
+PciExpressWriteBuffer (
+ IN UINTN StartAddress,
+ IN UINTN Size,
+ IN VOID *Buffer
+ )
+{
+ UINTN ReturnValue;
+
+ ASSERT (((StartAddress & 0xFFF) + Size) <= 0x1000);
+
+ if (Size == 0) {
+ return 0;
+ }
+
+ if (Buffer == NULL) {
+ ASSERT (Buffer != NULL);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Save Size for return
+ //
+ ReturnValue = Size;
+
+ if ((StartAddress & 1) != 0) {
+ //
+ // Write a byte if StartAddress is byte aligned
+ //
+ PciExpressWrite8 (StartAddress, *(UINT8 *) Buffer);
+ StartAddress += sizeof (UINT8);
+ Size -= sizeof (UINT8);
+ Buffer = (UINT8 *) Buffer + 1;
+ }
+
+ if (Size >= sizeof (UINT16) && (StartAddress & 2) != 0) {
+ //
+ // Write a word if StartAddress is word aligned
+ //
+ PciExpressWrite16 (StartAddress, *(UINT16 *) Buffer);
+ StartAddress += sizeof (UINT16);
+ Size -= sizeof (UINT16);
+ Buffer = (UINT16 *) Buffer + 1;
+ }
+
+ while (Size >= sizeof (UINT32)) {
+ //
+ // Write as many double words as possible
+ //
+ PciExpressWrite32 (StartAddress, *(UINT32 *) Buffer);
+ StartAddress += sizeof (UINT32);
+ Size -= sizeof (UINT32);
+ Buffer = (UINT32 *) Buffer + 1;
+ }
+
+ if (Size >= sizeof (UINT16)) {
+ //
+ // Write the last remaining word if exist
+ //
+ PciExpressWrite16 (StartAddress, *(UINT16 *) Buffer);
+ StartAddress += sizeof (UINT16);
+ Size -= sizeof (UINT16);
+ Buffer = (UINT16 *) Buffer + 1;
+ }
+
+ if (Size >= sizeof (UINT8)) {
+ //
+ // Write the last remaining byte if exist
+ //
+ PciExpressWrite8 (StartAddress, *(UINT8 *) Buffer);
+ }
+
+ return ReturnValue;
+}
+
+
+/**
+ Reads and returns the 8-bit PCI configuration register specified by Address.
+ This function must guarantee that all PCI read and write operations are
+ serialized.
+ If Address > 0x0FFFFFFF, then ASSERT().
+
+ @param[in] Address Address that encodes the PCI Bus, Device, Function and Register.
+
+ @retval UINT8 The read value from the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciRead8 (
+ IN UINTN Address
+ )
+{
+ return PciExpressRead8 (Address);
+}
+
+
+/**
+ Writes the 8-bit PCI configuration register specified by Address with the
+ value specified by Value. Value is returned. This function must guarantee
+ that all PCI read and write operations are serialized.
+ If Address > 0x0FFFFFFF, then ASSERT().
+
+ @param[in] Address Address that encodes the PCI Bus, Device, Function and Register.
+ @param[in] Data The value to write.
+
+ @retval UINT8 The value written to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciWrite8 (
+ IN UINTN Address,
+ IN UINT8 Data
+ )
+{
+ return PciExpressWrite8 (Address, Data);
+}
+
+
+/**
+ Reads the 8-bit PCI configuration register specified by Address, performs a
+ bitwise inclusive OR between the read result and the value specified by
+ OrData, and writes the result to the 8-bit PCI configuration register
+ specified by Address. The value written to the PCI configuration register is
+ returned. This function must guarantee that all PCI read and write operations
+ are serialized.
+ If Address > 0x0FFFFFFF, then ASSERT().
+
+ @param[in] Address Address that encodes the PCI Bus, Device, Function and Register.
+ @param[in] OrData The value to OR with the PCI configuration register.
+
+ @retval UINT8 The value written back to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciOr8 (
+ IN UINTN Address,
+ IN UINT8 OrData
+ )
+{
+ return PciExpressOr8 (Address, OrData);
+}
+
+
+/**
+ Reads the 8-bit PCI configuration register specified by Address, performs a
+ bitwise AND between the read result and the value specified by AndData, and
+ writes the result to the 8-bit PCI configuration register specified by
+ Address. The value written to the PCI configuration register is returned.
+ This function must guarantee that all PCI read and write operations are
+ serialized.
+ If Address > 0x0FFFFFFF, then ASSERT().
+
+ @param[in] Address Address that encodes the PCI Bus, Device, Function and Register.
+ @param[in] AndData The value to AND with the PCI configuration register.
+
+ @retval UINT8 The value written back to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciAnd8 (
+ IN UINTN Address,
+ IN UINT8 AndData
+ )
+{
+ return PciExpressAnd8 (Address, AndData);
+}
+
+
+/**
+ Reads the 8-bit PCI configuration register specified by Address, performs a
+ bitwise AND between the read result and the value specified by AndData,
+ performs a bitwise inclusive OR between the result of the AND operation and
+ the value specified by OrData, and writes the result to the 8-bit PCI
+ configuration register specified by Address. The value written to the PCI
+ configuration register is returned. This function must guarantee that all PCI
+ read and write operations are serialized.
+ If Address > 0x0FFFFFFF, then ASSERT().
+
+ @param[in] Address Address that encodes the PCI Bus, Device, Function and Register.
+ @param[in] AndData The value to AND with the PCI configuration register.
+ @param[in] OrData The value to OR with the result of the AND operation.
+
+ @retval UINT8 The value written back to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciAndThenOr8 (
+ IN UINTN Address,
+ IN UINT8 AndData,
+ IN UINT8 OrData
+ )
+{
+ return PciExpressAndThenOr8 (Address, AndData, OrData);
+}
+
+
+/**
+ Reads the bit field in an 8-bit PCI configuration register. The bit field is
+ specified by the StartBit and the EndBit. The value of the bit field is
+ returned.
+ If Address > 0x0FFFFFFF, then ASSERT().
+ If StartBit is greater than 7, then ASSERT().
+ If EndBit is greater than 7, then ASSERT().
+ If EndBit is less than StartBit, then ASSERT().
+
+ @param[in] Address PCI configuration register to read.
+ @param[in] StartBit The original of the least significant bit in the bit field. Range 0..7.
+ @param[in] EndBit The original of the most significant bit in the bit field. Range 0..7.
+
+ @retval UINT8 The value of the bit field read from the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciBitFieldRead8 (
+ IN UINTN Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit
+ )
+{
+ return PciExpressBitFieldRead8 (Address, StartBit, EndBit);
+}
+
+
+/**
+ Writes Value to the bit field of the PCI configuration register. The bit
+ field is specified by the StartBit and the EndBit. All other bits in the
+ destination PCI configuration register are preserved. The new value of the
+ 8-bit register is returned.
+ If Address > 0x0FFFFFFF, then ASSERT().
+ If StartBit is greater than 7, then ASSERT().
+ If EndBit is greater than 7, then ASSERT().
+ If EndBit is less than StartBit, then ASSERT().
+
+ @param[in] Address PCI configuration register to write.
+ @param[in] StartBit The original of the least significant bit in the bit field. Range 0..7.
+ @param[in] EndBit The original of the most significant bit in the bit field. Range 0..7.
+ @param[in] Value New value of the bit field.
+
+ @retval UINT8 The value written back to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciBitFieldWrite8 (
+ IN UINTN Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit,
+ IN UINT8 Value
+ )
+{
+ return PciExpressBitFieldWrite8 (Address, StartBit, EndBit, Value);
+}
+
+
+/**
+ Reads the 8-bit PCI configuration register specified by Address, performs a
+ bitwise inclusive OR between the read result and the value specified by
+ OrData, and writes the result to the 8-bit PCI configuration register
+ specified by Address. The value written to the PCI configuration register is
+ returned. This function must guarantee that all PCI read and write operations
+ are serialized. Extra left bits in OrData are stripped.
+ If Address > 0x0FFFFFFF, then ASSERT().
+ If StartBit is greater than 7, then ASSERT().
+ If EndBit is greater than 7, then ASSERT().
+ If EndBit is less than StartBit, then ASSERT().
+
+ @param[in] Address PCI configuration register to write.
+ @param[in] StartBit The original of the least significant bit in the bit field. Range 0..7.
+ @param[in] EndBit The original of the most significant bit in the bit field. Range 0..7.
+ @param[in] OrData The value to OR with the PCI configuration register.
+
+ @retval UINT8 The value written back to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciBitFieldOr8 (
+ IN UINTN Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit,
+ IN UINT8 OrData
+ )
+{
+ return PciExpressBitFieldOr8 (Address, StartBit, EndBit, OrData);
+}
+
+
+/**
+ Reads the 8-bit PCI configuration register specified by Address, performs a
+ bitwise AND between the read result and the value specified by AndData, and
+ writes the result to the 8-bit PCI configuration register specified by
+ Address. The value written to the PCI configuration register is returned.
+ This function must guarantee that all PCI read and write operations are
+ serialized. Extra left bits in AndData are stripped.
+ If Address > 0x0FFFFFFF, then ASSERT().
+ If StartBit is greater than 7, then ASSERT().
+ If EndBit is greater than 7, then ASSERT().
+ If EndBit is less than StartBit, then ASSERT().
+
+ @param[in] Address PCI configuration register to write.
+ @param[in] StartBit The original of the least significant bit in the bit field. Range 0..7.
+ @param[in] EndBit The original of the most significant bit in the bit field. Range 0..7.
+ @param[in] AndData The value to AND with the PCI configuration register.
+
+ @retval UINT8 The value written back to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciBitFieldAnd8 (
+ IN UINTN Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit,
+ IN UINT8 AndData
+ )
+{
+ return PciExpressBitFieldAnd8 (Address, StartBit, EndBit, AndData);
+}
+
+
+/**
+ Reads the 8-bit PCI configuration register specified by Address, performs a
+ bitwise AND followed by a bitwise inclusive OR between the read result and
+ the value specified by AndData, and writes the result to the 8-bit PCI
+ configuration register specified by Address. The value written to the PCI
+ configuration register is returned. This function must guarantee that all PCI
+ read and write operations are serialized. Extra left bits in both AndData and
+ OrData are stripped.
+ If Address > 0x0FFFFFFF, then ASSERT().
+ If StartBit is greater than 7, then ASSERT().
+ If EndBit is greater than 7, then ASSERT().
+ If EndBit is less than StartBit, then ASSERT().
+
+ @param[in] Address PCI configuration register to write.
+ @param[in] StartBit The original of the least significant bit in the bit field. Range 0..7.
+ @param[in] EndBit The original of the most significant bit in the bit field. Range 0..7.
+ @param[in] AndData The value to AND with the PCI configuration register.
+ @param[in] OrData The value to OR with the result of the AND operation.
+
+ @retval UINT8 The value written back to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciBitFieldAndThenOr8 (
+ IN UINTN Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit,
+ IN UINT8 AndData,
+ IN UINT8 OrData
+ )
+{
+ return PciExpressBitFieldAndThenOr8 (Address, StartBit, EndBit, AndData, OrData);
+}
+
+
+/**
+ Reads and returns the 16-bit PCI configuration register specified by Address.
+ This function must guarantee that all PCI read and write operations are
+ serialized.
+ If Address > 0x0FFFFFFF, then ASSERT().
+
+ @param[in] Address Address that encodes the PCI Bus, Device, Function and Register.
+
+ @retval UINT16 The read value from the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciRead16 (
+ IN UINTN Address
+ )
+{
+ return PciExpressRead16 (Address);
+}
+
+
+/**
+ Writes the 16-bit PCI configuration register specified by Address with the
+ value specified by Value. Value is returned. This function must guarantee
+ that all PCI read and write operations are serialized.
+ If Address > 0x0FFFFFFF, then ASSERT().
+
+ @param[in] Address Address that encodes the PCI Bus, Device, Function and Register.
+ @param[in] Data The value to write.
+
+ @retval UINT16 The value written to the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciWrite16 (
+ IN UINTN Address,
+ IN UINT16 Data
+ )
+{
+ return PciExpressWrite16 (Address, Data);
+}
+
+
+/**
+ Reads the 16-bit PCI configuration register specified by Address, performs a
+ bitwise inclusive OR between the read result and the value specified by
+ OrData, and writes the result to the 16-bit PCI configuration register
+ specified by Address. The value written to the PCI configuration register is
+ returned. This function must guarantee that all PCI read and write operations
+ are serialized.
+ If Address > 0x0FFFFFFF, then ASSERT().
+
+ @param[in] Address Address that encodes the PCI Bus, Device, Function and Register.
+ @param[in] OrData The value to OR with the PCI configuration register.
+
+ @retval UINT16 The value written back to the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciOr16 (
+ IN UINTN Address,
+ IN UINT16 OrData
+ )
+{
+ return PciExpressOr16 (Address, OrData);
+}
+
+
+/**
+ Reads the 16-bit PCI configuration register specified by Address, performs a
+ bitwise AND between the read result and the value specified by AndData, and
+ writes the result to the 16-bit PCI configuration register specified by
+ Address. The value written to the PCI configuration register is returned.
+ This function must guarantee that all PCI read and write operations are
+ serialized.
+ If Address > 0x0FFFFFFF, then ASSERT().
+
+ @param[in] Address Address that encodes the PCI Bus, Device, Function and Register.
+ @param[in] AndData The value to AND with the PCI configuration register.
+
+ @retval UINT16 The value written back to the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciAnd16 (
+ IN UINTN Address,
+ IN UINT16 AndData
+ )
+{
+ return PciExpressAnd16 (Address, AndData);
+}
+
+
+/**
+ Reads the 16-bit PCI configuration register specified by Address, performs a
+ bitwise AND between the read result and the value specified by AndData,
+ performs a bitwise inclusive OR between the result of the AND operation and
+ the value specified by OrData, and writes the result to the 16-bit PCI
+ configuration register specified by Address. The value written to the PCI
+ configuration register is returned. This function must guarantee that all PCI
+ read and write operations are serialized.
+ If Address > 0x0FFFFFFF, then ASSERT().
+
+ @param[in] Address Address that encodes the PCI Bus, Device, Function and Register.
+ @param[in] AndData The value to AND with the PCI configuration register.
+ @param[in] OrData The value to OR with the result of the AND operation.
+
+ @retval UINT16 The value written back to the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciAndThenOr16 (
+ IN UINTN Address,
+ IN UINT16 AndData,
+ IN UINT16 OrData
+ )
+{
+ return PciExpressAndThenOr16 (Address, AndData, OrData);
+}
+
+
+/**
+ Reads the bit field in a 16-bit PCI configuration register. The bit field is
+ specified by the StartBit and the EndBit. The value of the bit field is
+ returned.
+ If Address > 0x0FFFFFFF, then ASSERT().
+ If StartBit is greater than 15, then ASSERT().
+ If EndBit is greater than 15, then ASSERT().
+ If EndBit is less than StartBit, then ASSERT().
+
+ @param[in] Address PCI configuration register to read.
+ @param[in] StartBit The original of the least significant bit in the bit field. Range 0..15.
+ @param[in] EndBit The original of the most significant bit in the bit field. Range 0..15.
+
+ @retval UINT16 The value of the bit field read from the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciBitFieldRead16 (
+ IN UINTN Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit
+ )
+{
+ return PciExpressBitFieldRead16 (Address, StartBit, EndBit);
+}
+
+
+/**
+ Writes Value to the bit field of the PCI configuration register. The bit
+ field is specified by the StartBit and the EndBit. All other bits in the
+ destination PCI configuration register are preserved. The new value of the
+ 16-bit register is returned.
+ If Address > 0x0FFFFFFF, then ASSERT().
+ If StartBit is greater than 15, then ASSERT().
+ If EndBit is greater than 15, then ASSERT().
+ If EndBit is less than StartBit, then ASSERT().
+
+ @param[in] Address PCI configuration register to write.
+ @param[in] StartBit The original of the least significant bit in the bit field. Range 0..15.
+ @param[in] EndBit The original of the most significant bit in the bit field. Range 0..15.
+ @param[in] Value New value of the bit field.
+
+ @retval UINT16 The value written back to the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciBitFieldWrite16 (
+ IN UINTN Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit,
+ IN UINT16 Value
+ )
+{
+ return PciExpressBitFieldWrite16 (Address, StartBit, EndBit, Value);
+}
+
+
+/**
+ Reads the 16-bit PCI configuration register specified by Address, performs a
+ bitwise inclusive OR between the read result and the value specified by
+ OrData, and writes the result to the 16-bit PCI configuration register
+ specified by Address. The value written to the PCI configuration register is
+ returned. This function must guarantee that all PCI read and write operations
+ are serialized. Extra left bits in OrData are stripped.
+ If Address > 0x0FFFFFFF, then ASSERT().
+ If StartBit is greater than 15, then ASSERT().
+ If EndBit is greater than 15, then ASSERT().
+ If EndBit is less than StartBit, then ASSERT().
+
+ @param[in] Address PCI configuration register to write.
+ @param[in] StartBit The original of the least significant bit in the bit field. Range 0..15.
+ @param[in] EndBit The original of the most significant bit in the bit field. Range 0..15.
+ @param[in] OrData The value to OR with the PCI configuration register.
+
+ @retval UINT16 The value written back to the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciBitFieldOr16 (
+ IN UINTN Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit,
+ IN UINT16 OrData
+ )
+{
+ return PciExpressBitFieldOr16 (Address, StartBit, EndBit, OrData);
+}
+
+
+/**
+ Reads the 16-bit PCI configuration register specified by Address, performs a
+ bitwise AND between the read result and the value specified by AndData, and
+ writes the result to the 16-bit PCI configuration register specified by
+ Address. The value written to the PCI configuration register is returned.
+ This function must guarantee that all PCI read and write operations are
+ serialized. Extra left bits in AndData are stripped.
+ If Address > 0x0FFFFFFF, then ASSERT().
+ If StartBit is greater than 15, then ASSERT().
+ If EndBit is greater than 15, then ASSERT().
+ If EndBit is less than StartBit, then ASSERT().
+
+ @param[in] Address PCI configuration register to write.
+ @param[in] StartBit The original of the least significant bit in the bit field. Range 0..15.
+ @param[in] EndBit The original of the most significant bit in the bit field. Range 0..15.
+ @param[in] AndData The value to AND with the PCI configuration register.
+
+ @retval UINT16 The value written back to the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciBitFieldAnd16 (
+ IN UINTN Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit,
+ IN UINT16 AndData
+ )
+{
+ return PciExpressBitFieldAnd16 (Address, StartBit, EndBit, AndData);
+}
+
+
+/**
+ Reads the 16-bit PCI configuration register specified by Address, performs a
+ bitwise AND followed by a bitwise inclusive OR between the read result and
+ the value specified by AndData, and writes the result to the 16-bit PCI
+ configuration register specified by Address. The value written to the PCI
+ configuration register is returned. This function must guarantee that all PCI
+ read and write operations are serialized. Extra left bits in both AndData and
+ OrData are stripped.
+ If Address > 0x0FFFFFFF, then ASSERT().
+ If StartBit is greater than 15, then ASSERT().
+ If EndBit is greater than 15, then ASSERT().
+ If EndBit is less than StartBit, then ASSERT().
+
+ @param[in] Address PCI configuration register to write.
+ @param[in] StartBit The original of the least significant bit in the bit field. Range 0..15.
+ @param[in] EndBit The original of the most significant bit in the bit field. Range 0..15.
+ @param[in] AndData The value to AND with the PCI configuration register.
+ @param[in] OrData The value to OR with the result of the AND operation.
+
+ @retval UINT16 The value written back to the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciBitFieldAndThenOr16 (
+ IN UINTN Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit,
+ IN UINT16 AndData,
+ IN UINT16 OrData
+ )
+{
+ return PciExpressBitFieldAndThenOr16 (Address, StartBit, EndBit, AndData, OrData);
+}
+
+
+/**
+ Reads and returns the 32-bit PCI configuration register specified by Address.
+ This function must guarantee that all PCI read and write operations are
+ serialized.
+ If Address > 0x0FFFFFFF, then ASSERT().
+
+ @param[in] Address Address that encodes the PCI Bus, Device, Function and Register.
+
+ @retval UINT32 The read value from the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciRead32 (
+ IN UINTN Address
+ )
+{
+ return PciExpressRead32 (Address);
+}
+
+
+/**
+ Writes the 32-bit PCI configuration register specified by Address with the
+ value specified by Value. Value is returned. This function must guarantee
+ that all PCI read and write operations are serialized.
+ If Address > 0x0FFFFFFF, then ASSERT().
+
+ @param[in] Address Address that encodes the PCI Bus, Device, Function and Register.
+ @param[in] Data The value to write.
+
+ @retval UINT32 The value written to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciWrite32 (
+ IN UINTN Address,
+ IN UINT32 Data
+ )
+{
+ return PciExpressWrite32 (Address, Data);
+}
+
+
+/**
+ Reads the 32-bit PCI configuration register specified by Address, performs a
+ bitwise inclusive OR between the read result and the value specified by
+ OrData, and writes the result to the 32-bit PCI configuration register
+ specified by Address. The value written to the PCI configuration register is
+ returned. This function must guarantee that all PCI read and write operations
+ are serialized.
+ If Address > 0x0FFFFFFF, then ASSERT().
+
+ @param[in] Address Address that encodes the PCI Bus, Device, Function and Register.
+ @param[in] OrData The value to OR with the PCI configuration register.
+
+ @retval UINT32 The value written back to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciOr32 (
+ IN UINTN Address,
+ IN UINT32 OrData
+ )
+{
+ return PciExpressOr32 (Address, OrData);
+}
+
+
+/**
+ Reads the 32-bit PCI configuration register specified by Address, performs a
+ bitwise AND between the read result and the value specified by AndData, and
+ writes the result to the 32-bit PCI configuration register specified by
+ Address. The value written to the PCI configuration register is returned.
+ This function must guarantee that all PCI read and write operations are
+ serialized.
+ If Address > 0x0FFFFFFF, then ASSERT().
+
+ @param[in] Address Address that encodes the PCI Bus, Device, Function and Register.
+ @param[in] AndData The value to AND with the PCI configuration register.
+
+ @retval UINT32 The value written back to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciAnd32 (
+ IN UINTN Address,
+ IN UINT32 AndData
+ )
+{
+ return PciExpressAnd32 (Address, AndData);
+}
+
+
+/**
+ Reads the 32-bit PCI configuration register specified by Address, performs a
+ bitwise AND between the read result and the value specified by AndData,
+ performs a bitwise inclusive OR between the result of the AND operation and
+ the value specified by OrData, and writes the result to the 32-bit PCI
+ configuration register specified by Address. The value written to the PCI
+ configuration register is returned. This function must guarantee that all PCI
+ read and write operations are serialized.
+ If Address > 0x0FFFFFFF, then ASSERT().
+
+ @param[in] Address Address that encodes the PCI Bus, Device, Function and Register.
+ @param[in] AndData The value to AND with the PCI configuration register.
+ @param[in] OrData The value to OR with the result of the AND operation.
+
+ @retval UINT32 The value written back to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciAndThenOr32 (
+ IN UINTN Address,
+ IN UINT32 AndData,
+ IN UINT32 OrData
+ )
+{
+ return PciExpressAndThenOr32 (Address, AndData, OrData);
+}
+
+
+/**
+ Reads the bit field in a 32-bit PCI configuration register. The bit field is
+ specified by the StartBit and the EndBit. The value of the bit field is
+ returned.
+ If Address > 0x0FFFFFFF, then ASSERT().
+ If StartBit is greater than 31, then ASSERT().
+ If EndBit is greater than 31, then ASSERT().
+ If EndBit is less than StartBit, then ASSERT().
+
+ @param[in] Address PCI configuration register to read.
+ @param[in] StartBit The original of the least significant bit in the bit field. Range 0..31.
+ @param[in] EndBit The original of the most significant bit in the bit field. Range 0..31.
+
+ @retval UINT32 The value of the bit field read from the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciBitFieldRead32 (
+ IN UINTN Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit
+ )
+{
+ return PciExpressBitFieldRead32 (Address, StartBit, EndBit);
+}
+
+
+/**
+ Writes Value to the bit field of the PCI configuration register. The bit
+ field is specified by the StartBit and the EndBit. All other bits in the
+ destination PCI configuration register are preserved. The new value of the
+ 32-bit register is returned.
+ If Address > 0x0FFFFFFF, then ASSERT().
+ If StartBit is greater than 31, then ASSERT().
+ If EndBit is greater than 31, then ASSERT().
+ If EndBit is less than StartBit, then ASSERT().
+
+ @param[in] Address PCI configuration register to write.
+ @param[in] StartBit The original of the least significant bit in the bit field. Range 0..31.
+ @param[in] EndBit The original of the most significant bit in the bit field. Range 0..31.
+ @param[in] Value New value of the bit field.
+
+ @retval UINT32 The value written back to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciBitFieldWrite32 (
+ IN UINTN Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit,
+ IN UINT32 Value
+ )
+{
+ return PciExpressBitFieldWrite32 (Address, StartBit, EndBit, Value);
+}
+
+
+/**
+ Reads the 32-bit PCI configuration register specified by Address, performs a
+ bitwise inclusive OR between the read result and the value specified by
+ OrData, and writes the result to the 32-bit PCI configuration register
+ specified by Address. The value written to the PCI configuration register is
+ returned. This function must guarantee that all PCI read and write operations
+ are serialized. Extra left bits in OrData are stripped.
+ If Address > 0x0FFFFFFF, then ASSERT().
+ If StartBit is greater than 31, then ASSERT().
+ If EndBit is greater than 31, then ASSERT().
+ If EndBit is less than StartBit, then ASSERT().
+
+ @param[in] Address PCI configuration register to write.
+ @param[in] StartBit The original of the least significant bit in the bit field. Range 0..31.
+ @param[in] EndBit The original of the most significant bit in the bit field. Range 0..31.
+ @param[in] OrData The value to OR with the PCI configuration register.
+
+ @retval UINT32 The value written back to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciBitFieldOr32 (
+ IN UINTN Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit,
+ IN UINT32 OrData
+ )
+{
+ return PciExpressBitFieldOr32 (Address, StartBit, EndBit, OrData);
+}
+
+
+/**
+ Reads the 32-bit PCI configuration register specified by Address, performs a
+ bitwise AND between the read result and the value specified by AndData, and
+ writes the result to the 32-bit PCI configuration register specified by
+ Address. The value written to the PCI configuration register is returned.
+ This function must guarantee that all PCI read and write operations are
+ serialized. Extra left bits in AndData are stripped.
+ If Address > 0x0FFFFFFF, then ASSERT().
+ If StartBit is greater than 31, then ASSERT().
+ If EndBit is greater than 31, then ASSERT().
+ If EndBit is less than StartBit, then ASSERT().
+
+ @param[in] Address PCI configuration register to write.
+ @param[in] StartBit The original of the least significant bit in the bit field. Range 0..31.
+ @param[in] EndBit The original of the most significant bit in the bit field. Range 0..31.
+ @param[in] AndData The value to AND with the PCI configuration register.
+
+ @retval UINT32 The value written back to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciBitFieldAnd32 (
+ IN UINTN Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit,
+ IN UINT32 AndData
+ )
+{
+ return PciExpressBitFieldAnd32 (Address, StartBit, EndBit, AndData);
+}
+
+
+/**
+ Reads the 32-bit PCI configuration register specified by Address, performs a
+ bitwise AND followed by a bitwise inclusive OR between the read result and
+ the value specified by AndData, and writes the result to the 32-bit PCI
+ configuration register specified by Address. The value written to the PCI
+ configuration register is returned. This function must guarantee that all PCI
+ read and write operations are serialized. Extra left bits in both AndData and
+ OrData are stripped.
+ If Address > 0x0FFFFFFF, then ASSERT().
+ If StartBit is greater than 31, then ASSERT().
+ If EndBit is greater than 31, then ASSERT().
+ If EndBit is less than StartBit, then ASSERT().
+
+ @param[in] Address PCI configuration register to write.
+ @param[in] StartBit The original of the least significant bit in the bit field. Range 0..31.
+ @param[in] EndBit The original of the most significant bit in the bit field. Range 0..31.
+ @param[in] AndData The value to AND with the PCI configuration register.
+ @param[in] OrData The value to OR with the result of the AND operation.
+
+ @retval UINT32 The value written back to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciBitFieldAndThenOr32 (
+ IN UINTN Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit,
+ IN UINT32 AndData,
+ IN UINT32 OrData
+ )
+{
+ return PciExpressBitFieldAndThenOr32 (Address, StartBit, EndBit, AndData, OrData);
+}
+
+
+/**
+ Reads the range of PCI configuration registers specified by StartAddress and
+ Size into the buffer specified by Buffer. This function only allows the PCI
+ configuration registers from a single PCI function to be read. Size is
+ returned. When possible 32-bit PCI configuration read cycles are used to read
+ from StartAdress to StartAddress + Size. Due to alignment restrictions, 8-bit
+ and 16-bit PCI configuration read cycles may be used at the beginning and the
+ end of the range.
+ If StartAddress > 0x0FFFFFFF, then ASSERT().
+ If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT().
+ If Size > 0 and Buffer is NULL, then ASSERT().
+
+ @param[in] StartAddress Starting address that encodes the PCI Bus, Device, Function and Register.
+ @param[in] Size Size in bytes of the transfer.
+
+ @param[out] Buffer Pointer to a buffer receiving the data read.
+
+ @retval UINTN Size in bytes of the transfer.
+
+**/
+UINTN
+EFIAPI
+PciReadBuffer (
+ IN UINTN StartAddress,
+ IN UINTN Size,
+ OUT VOID *Buffer
+ )
+{
+ return PciExpressReadBuffer (StartAddress, Size, Buffer);
+}
+
+
+/**
+ Writes the range of PCI configuration registers specified by StartAddress and
+ Size from the buffer specified by Buffer. This function only allows the PCI
+ configuration registers from a single PCI function to be written. Size is
+ returned. When possible 32-bit PCI configuration write cycles are used to
+ write from StartAdress to StartAddress + Size. Due to alignment restrictions,
+ 8-bit and 16-bit PCI configuration write cycles may be used at the beginning
+ and the end of the range.
+ If StartAddress > 0x0FFFFFFF, then ASSERT().
+ If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT().
+ If Size > 0 and Buffer is NULL, then ASSERT().
+
+ @param[in] StartAddress Starting address that encodes the PCI Bus, Device, Function and Register.
+ @param[in] Size Size in bytes of the transfer.
+ @param[in] Buffer Pointer to a buffer containing the data to write.
+
+ @retval UINTN The value written back to the PCI configuration register.
+
+**/
+UINTN
+EFIAPI
+PciWriteBuffer (
+ IN UINTN StartAddress,
+ IN UINTN Size,
+ IN VOID *Buffer
+ )
+{
+ return PciExpressWriteBuffer (StartAddress, Size, Buffer);
+}
+
+/**
+ Register memory space
+ If StartAddress > 0x0FFFFFFF, then ASSERT().
+ If SmPciLibAddressMapIndex) > PCI_LIB_ADDRESS_MAP_MAX_ITEM, then ASSERT().
+
+ @param[in] Address Starting address of the memory space
+ @param[in] Length Length of the memory space
+
+ @retval EFI_SUCCESS The function completed successfully
+
+**/
+EFI_STATUS
+EFIAPI
+PciLibRegisterMemory (
+ IN UINTN Address,
+ IN UINTN Length
+ )
+{
+ UINTN Index;
+
+ ASSERT_INVALID_PCI_ADDRESS (Address);
+ ASSERT (mPciLibAddressMapIndex < PCI_LIB_ADDRESS_MAP_MAX_ITEM);
+
+ //
+ // If already registered
+ //
+ for (Index = 0; Index < mPciLibAddressMapIndex; Index++) {
+ if (mPciLibAddressMap[Index].PciAddress == Address) {
+ return EFI_SUCCESS;
+ }
+ }
+
+ mPciLibAddressMap[mPciLibAddressMapIndex].PciAddress = Address;
+ mPciLibAddressMap[mPciLibAddressMapIndex].Length = Length;
+ mPciLibAddressMap[mPciLibAddressMapIndex].RuntimeAddress = mPciExpressBaseAddress + Address;
+ mPciLibAddressMapIndex++;
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Virtual address notify.
+ The event handler changes PCIE base address to an virtual address.
+ Starting address of registered memory scope is converted as well.
+
+ @param[in] Event The event that be siganlled when virtual address changed
+ @param[in] Context The pointer of the ESAL procedure instance
+
+**/
+VOID
+EFIAPI
+VirtualAddressNotifyEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ UINTN Index;
+
+ for (Index = 0; Index < PCI_LIB_ADDRESS_MAP_MAX_ITEM; Index++) {
+ if (mPciLibAddressMap[Index].PciAddress != 0) {
+ EfiConvertPointer (0x0, (VOID **) &(mPciLibAddressMap[Index].RuntimeAddress));
+ }
+ }
+
+ EfiConvertPointer (0x0, (VOID **) &mPciExpressBaseAddress);
+}
+
+
+/**
+ Constructor for Pci library. Register VirtualAddressNotifyEvent() notify function
+ It will ASSERT() if that operation fails
+
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.
+ @param[in] SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The function completed successfully
+
+**/
+EFI_STATUS
+EFIAPI
+PciLibConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ mPciExpressBaseAddress = (UINTN) PcdGet64 (PcdPciExpressBaseAddress);
+
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ VirtualAddressNotifyEvent,
+ NULL,
+ &gEfiEventVirtualAddressChangeGuid,
+ &mVirtualAddressChangeEvent
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ ZeroMem (mPciLibAddressMap, sizeof (mPciLibAddressMap));
+
+ return EFI_SUCCESS;
+}
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/DxeRuntimePciLibPciExpress/DxeRuntimePciLibPciExpress.h b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/DxeRuntimePciLibPciExpress/DxeRuntimePciLibPciExpress.h
new file mode 100644
index 0000000000..c55e89ce95
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/DxeRuntimePciLibPciExpress/DxeRuntimePciLibPciExpress.h
@@ -0,0 +1,30 @@
+/** @file
+ Header file for SC Pci Express helps library implementation.
+
+ Copyright (c) 2008 - 2016, 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.
+
+**/
+
+#ifndef _SC_DXE_RUNTIME_PCI_EXPRESS_LIBRARY_H_
+#define _SC_DXE_RUNTIME_PCI_EXPRESS_LIBRARY_H_
+
+#include "ScAccess.h"
+#include "Library/PciLib.h"
+#include "Library/IoLib.h"
+#include "Library/DebugLib.h"
+#include "Library/PcdLib.h"
+
+#include <Uefi.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/UefiRuntimeLib.h>
+
+#endif
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/DxeRuntimePciLibPciExpress/DxeRuntimePciLibPciExpress.inf b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/DxeRuntimePciLibPciExpress/DxeRuntimePciLibPciExpress.inf
new file mode 100644
index 0000000000..4aab494cb6
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/DxeRuntimePciLibPciExpress/DxeRuntimePciLibPciExpress.inf
@@ -0,0 +1,47 @@
+## @file
+# ScDxeRuntimePciLibPciExpress Driver.
+#
+# Copyright (c) 2012 - 2016, 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 = ScDxeRuntimePciLibPciExpress
+ FILE_GUID = D048C113-CAE2-4107-AD0C-F78693EB6EBA
+ MODULE_TYPE = DXE_RUNTIME_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = ScDxeRuntimePciLibPciExpress|DXE_RUNTIME_DRIVER
+ CONSTRUCTOR = PciLibConstructor
+
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ DxeRuntimePciLibPciExpress.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ BroxtonSiPkg/BroxtonSiPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ IoLib
+ DebugLib
+ UefiBootServicesTableLib
+ DxeServicesTableLib
+
+[Pcd]
+ gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress ## CONSUMES
+
+[Guids]
+ gEfiEventVirtualAddressChangeGuid ## PRODUCES ## Event
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/DxeVtdLib/DxeVtdLib.c b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/DxeVtdLib/DxeVtdLib.c
new file mode 100644
index 0000000000..a21816ec38
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/DxeVtdLib/DxeVtdLib.c
@@ -0,0 +1,683 @@
+/** @file
+ This code provides a initialization of Intel VT-d (Virtualization Technology for Directed I/O).
+
+ Copyright (c) 1999 - 2016, 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.
+
+**/
+
+#include <Library/DxeVtdLib.h>
+#include <Private/Guid/ScPolicyHobGuid.h>
+#include <Library/HobLib.h>
+#include <Library/SteppingLib.h>
+#include <Library/ConfigBlockLib.h>
+
+/**
+ For device that specified by Device Num and Function Num,
+ mDevEnMap is used to check device presence.
+ 0x80 means use Device ID to determine presence
+
+ The structure is used to check if device scope is valid when update DMAR table
+**/
+UINT16 mDevEnMap[][2] = {{0x0200, 0x80}, {0x1500, 0x80}, {0x1501, 0x80}};
+
+/**
+ Get the corresponding device Enable/Disable bit according DevNum and FunNum
+
+ @param[in] DevNum Device Number
+ @param[in] FunNum Function Number
+
+ @retval Bit If the device is found, return Disable/Enable bit in FD/DevEn register
+ @retval 0xFF When device not found
+
+**/
+UINT16
+GetFunDisableBit (
+ IN UINT8 DevNum,
+ IN UINT8 FunNum
+ )
+{
+ UINTN Index;
+
+ for (Index = 0; Index < sizeof (mDevEnMap) / 4; Index++) {
+ if (mDevEnMap[Index][0] == ((DevNum << 0x08) | FunNum)) {
+ return mDevEnMap[Index][1];
+ }
+ }
+
+ return 0xFF;
+}
+
+
+/**
+ Update the DRHD structure
+
+ @param[in, out] DrhdEnginePtr A pointer to DRHD structure
+
+**/
+VOID
+UpdateDrhd (
+ IN OUT VOID *DrhdEnginePtr
+ )
+{
+ UINT16 Length;
+ UINT16 DisableBit;
+ UINTN DeviceScopeNum;
+ BOOLEAN NeedRemove;
+ EFI_ACPI_DRHD_ENGINE1_STRUCT *DrhdEngine;
+
+ //
+ // Convert DrhdEnginePtr to EFI_ACPI_DRHD_ENGINE1_STRUCT Pointer
+ //
+ DrhdEngine = (EFI_ACPI_DRHD_ENGINE1_STRUCT *) DrhdEnginePtr;
+ Length = DrhdEngine->Length;
+ DeviceScopeNum = (DrhdEngine->Length - EFI_ACPI_DRHD_ENGINE_HEADER_LENGTH) / sizeof (EFI_ACPI_DEV_SCOPE_STRUCTURE);
+
+ DisableBit = GetFunDisableBit (
+ DrhdEngine->DeviceScope[0].PciPath[0],
+ DrhdEngine->DeviceScope[0].PciPath[1]
+ );
+
+ NeedRemove = FALSE;
+
+ if ((DisableBit == 0xFF) ||
+ (DrhdEngine->RegisterBaseAddress == 0) ||
+ ((DisableBit == 0x80) &&
+ (MmioRead32 (MmPciBase (0, DrhdEngine->DeviceScope[0].PciPath[0], DrhdEngine->DeviceScope[0].PciPath[1]) + 0x00) == 0xFFFFFFFF))) {
+ NeedRemove = TRUE;
+ }
+
+ if (NeedRemove) {
+ Length -= sizeof (EFI_ACPI_DEV_SCOPE_STRUCTURE);
+ }
+
+ //
+ // If no device scope is left, we set the structure length as 0x00
+ //
+ if ((Length > EFI_ACPI_DRHD_ENGINE_HEADER_LENGTH) || (DrhdEngine->Flags == 0x01)) {
+ DrhdEngine->Length = Length;
+ } else {
+ DrhdEngine->Length = 0;
+ }
+
+ return;
+}
+
+
+/**
+ Get IOAPIC ID from LPC.
+
+ @retval UINT8 IO APIC ID
+
+**/
+UINT8
+GetIoApicId (
+ VOID
+ )
+{
+ UINT32 IoApicId;
+ UINTN P2sbMmbase;
+
+ P2sbMmbase = MmPciAddress(
+ 0,
+ DEFAULT_PCI_BUS_NUMBER_SC,
+ PCI_DEVICE_NUMBER_P2SB,
+ PCI_FUNCTION_NUMBER_P2SB,
+ 0
+ );
+
+
+ MmioOr16 (P2sbMmbase + R_P2SB_IOAC, (UINT16) (B_P2SB_IOAC_AE));
+ //
+ // Reads back for posted write to take effect and make sure it is set properly.
+ //
+ if ((MmioRead16 (P2sbMmbase + R_P2SB_IOAC) & (UINT16) B_P2SB_IOAC_AE) == (UINT16) 0x00) {
+ DEBUG ((EFI_D_INFO, " IoApicId B_P2SB_IOAC_AE:0 Skip \n"));
+ return 0;
+ }
+
+ //
+ // Get current IO APIC ID
+ //
+ MmioWrite8 ((UINTN) IO_APIC_INDEX_REGISTER, R_IO_APIC_ID);
+ IoApicId = MmioRead32 ((UINTN) IO_APIC_DATA_REGISTER) >> 24;
+
+ return (UINT8) IoApicId;
+}
+
+
+/**
+ Update the second DRHD structure
+
+ @param[in, out] DrhdEnginePtr A pointer to DRHD structure
+
+**/
+VOID
+UpdateDrhd2 (
+ IN OUT VOID *DrhdEnginePtr
+ )
+{
+ UINT16 Length;
+ UINTN DeviceScopeNum;
+ UINTN ValidDeviceScopeNum;
+ UINT16 Data16;
+ UINT16 Index;
+ UINT8 Bus;
+ UINT8 Path[2] = { 0, 0 };
+ BOOLEAN NeedRemove;
+ EFI_ACPI_DRHD_ENGINE2_STRUCT *DrhdEngine;
+ UINTN P2sbMmbase;
+
+ P2sbMmbase = MmPciAddress(
+ 0,
+ DEFAULT_PCI_BUS_NUMBER_SC,
+ PCI_DEVICE_NUMBER_P2SB,
+ PCI_FUNCTION_NUMBER_P2SB,
+ 0
+ );
+
+ //
+ // Convert DrhdEnginePtr to EFI_ACPI_DRHD_ENGINE2_STRUCT Pointer
+ //
+ DrhdEngine = (EFI_ACPI_DRHD_ENGINE2_STRUCT *) DrhdEnginePtr;
+
+ Length = DrhdEngine->Length;
+ DeviceScopeNum = (DrhdEngine->Length - EFI_ACPI_DRHD_ENGINE_HEADER_LENGTH) / sizeof (EFI_ACPI_DEV_SCOPE_STRUCTURE);
+ Data16 = 0;
+ Bus = 0;
+ ValidDeviceScopeNum = 0;
+
+ for (Index = 0; Index < DeviceScopeNum; Index++) {
+ NeedRemove = FALSE;
+ //
+ // For HPET and APIC, update device scope if Interrupt remapping is supported. remove device scope
+ // if interrupt remapping is not supported.
+ // - Index = 0 - IOAPIC
+ // - Index = 1 - HPET
+ //
+ if ((MmioRead32 (PcdGet32 (PcdVtdGfxBaseAddress) + VTD_ECAP_REG) & IR)
+ && (MmioRead32 (DEF_VTD_BASE_ADDRESS + VTD_ECAP_REG) & IR)
+ && ((GetBxtSeries() == BxtP && BxtStepping() > BxtPA0) || GetBxtSeries() == Bxt1)) {
+ if (Index == 0) {
+ //
+ // Update source id for IoApic's device scope entry
+ //
+ Data16 = MmioRead16 (P2sbMmbase + R_PCH_P2SB_IBDF);
+ Bus = (UINT8) (Data16 >> 8);
+
+ if (Bus != 0x00) {
+ Path[0] = (UINT8) ((Data16 & 0xff) >> 3);
+ Path[1] = (UINT8) (Data16 & 0x7);
+ } else {
+ Bus = 0xF0;
+ Path[0] = 0x1F;
+ Path[1] = 0x0;
+ }
+
+ DrhdEngine->DeviceScope[Index].StartBusNumber = Bus;
+ DrhdEngine->DeviceScope[Index].PciPath[0] = Path[0];
+ DrhdEngine->DeviceScope[Index].PciPath[1] = Path[1];
+
+ //
+ // Update APIC ID
+ //
+ DrhdEngine->DeviceScope[Index].EnumId = GetIoApicId();
+ DEBUG ((EFI_D_INFO, " VTd check IoApicId : 0x%x\n", GetIoApicId()));
+ }
+
+ if (Index == 1) {
+ //
+ // Update source id for HPET's device scope entry
+ //
+ Data16 = MmioRead16 (P2sbMmbase + R_PCH_P2SB_HBDF);
+ Bus = (UINT8) (Data16 >> 8);
+ Path[0] = (UINT8) ((Data16 & 0xFF) >> 3);
+ Path[1] = (UINT8) (Data16 & 0x7);
+
+ DrhdEngine->DeviceScope[Index].StartBusNumber = Bus;
+ DrhdEngine->DeviceScope[Index].PciPath[0] = Path[0];
+ DrhdEngine->DeviceScope[Index].PciPath[1] = Path[1];
+ }
+ } else {
+ if ((Index == 0) || (Index == 1)) {
+ NeedRemove = TRUE;
+ }
+ }
+
+ CopyMem (
+ &DrhdEngine->DeviceScope[ValidDeviceScopeNum],
+ &DrhdEngine->DeviceScope[Index],
+ sizeof (EFI_ACPI_DEV_SCOPE_STRUCTURE)
+ );
+
+ if (NeedRemove) {
+ Length -= sizeof (EFI_ACPI_DEV_SCOPE_STRUCTURE);
+ } else {
+ ValidDeviceScopeNum++;
+ }
+ }
+
+ //
+ // If no device scope is left, we set the structure length as 0x00
+ //
+ if ((Length > EFI_ACPI_DRHD_ENGINE_HEADER_LENGTH) || (DrhdEngine->Flags == 0x01)) {
+ DrhdEngine->Length = Length;
+ } else {
+ DrhdEngine->Length = 0;
+ }
+}
+
+
+/**
+ Update the RMRR structure
+
+ @param[in, out] RmrrPtr A pointer to RMRR structure
+
+**/
+VOID
+UpdateRmrr (
+ IN OUT VOID *RmrrPtr
+ )
+{
+ UINT16 Length;
+ UINT16 DisableBit;
+ UINTN DeviceScopeNum;
+ UINTN ValidDeviceScopeNum;
+ UINTN Index;
+ BOOLEAN NeedRemove;
+ EFI_ACPI_RMRR_USB_STRUC *Rmrr;
+
+ //
+ // To make sure all device scope can be checked,
+ // we convert the RmrrPtr to EFI_ACPI_RMRR_USB_STRUC pointer
+ //
+ Rmrr = (EFI_ACPI_RMRR_USB_STRUC *) RmrrPtr;
+ Length = Rmrr->Length;
+ ValidDeviceScopeNum = 0;
+ DeviceScopeNum = (Rmrr->Length - EFI_ACPI_RMRR_HEADER_LENGTH) / sizeof (EFI_ACPI_DEV_SCOPE_STRUCTURE);
+
+ for (Index = 0; Index < DeviceScopeNum; Index++) {
+ DisableBit = GetFunDisableBit (
+ Rmrr->DeviceScope[Index].PciPath[0],
+ Rmrr->DeviceScope[Index].PciPath[1]
+ );
+ NeedRemove = FALSE;
+
+ if ((DisableBit == 0xFF) ||
+ ((DisableBit == 0x80) &&
+ (MmioRead32 (MmPciBase (0, Rmrr->DeviceScope[Index].PciPath[0], Rmrr->DeviceScope[Index].PciPath[1]) + 0x00) == 0xFFFFFFFF))) {
+ NeedRemove = TRUE;
+ }
+
+ CopyMem (
+ &Rmrr->DeviceScope[ValidDeviceScopeNum],
+ &Rmrr->DeviceScope[Index],
+ sizeof (EFI_ACPI_DEV_SCOPE_STRUCTURE)
+ );
+
+ if (NeedRemove) {
+ Length -= sizeof (EFI_ACPI_DEV_SCOPE_STRUCTURE);
+ } else {
+ ValidDeviceScopeNum++;
+ }
+ }
+
+ //
+ // If No deviceScope is left, set length as 0x00
+ //
+ if (Length > EFI_ACPI_RMRR_HEADER_LENGTH) {
+ Rmrr->Length = Length;
+ } else {
+ Rmrr->Length = 0;
+ }
+}
+
+
+/**
+ Update the DMAR table
+
+ @param[in, out] TableHeader The table to be set
+ @param[in, out] Version Version to publish
+
+**/
+VOID
+DmarTableUpdate (
+ IN OUT EFI_ACPI_DESCRIPTION_HEADER *TableHeader,
+ IN OUT EFI_ACPI_TABLE_VERSION *Version
+ )
+{
+ EFI_ACPI_DMAR_TABLE *DmarTable;
+ EFI_ACPI_DMAR_TABLE TempDmarTable;
+ UINTN Offset;
+ UINTN StructureLen;
+ UINTN McD0BaseAddress;
+ UINTN MchBar;
+ UINT16 IgdMode;
+ UINT16 GttMode;
+ UINT32 IgdMemSize;
+ UINT32 GttMemSize;
+ SC_POLICY_HOB *ScPolicy;
+ EFI_PEI_HOB_POINTERS HobPtr;
+ SC_VTD_CONFIG *VtdConfig;
+ EFI_STATUS Status;
+
+ //
+ // Get SC VT-d config block
+ //
+ HobPtr.Guid = GetFirstGuidHob (&gScPolicyHobGuid);
+ ASSERT (HobPtr.Guid != NULL);
+ ScPolicy = (SC_POLICY_HOB *) GET_GUID_HOB_DATA (HobPtr.Guid);
+ Status = GetConfigBlock ((VOID *) ScPolicy, &gVtdConfigGuid, (VOID *) &VtdConfig);
+ ASSERT_EFI_ERROR (Status);
+ DEBUG ((DEBUG_INFO, "ScPolicy VtdEnable = %x\n", VtdConfig->VtdEnable));
+
+ IgdMemSize = 0;
+ GttMemSize = 0;
+ DmarTable = (EFI_ACPI_DMAR_TABLE *) TableHeader;
+
+ DEBUG ((DEBUG_INFO, "DmarTableUpdate() - start\n"));
+
+ //
+ // Set INTR_REMAP bit (BIT 0) if interrupt remapping is supported
+ //
+ if ((MmioRead32 (PcdGet32 (PcdVtdGfxBaseAddress) + VTD_ECAP_REG) & IR)
+ && (MmioRead32 (DEF_VTD_BASE_ADDRESS + VTD_ECAP_REG) & IR)
+ && ((GetBxtSeries() == BxtP && BxtStepping() > BxtPA0) || GetBxtSeries() == Bxt1)) {
+ DmarTable->Flags |= BIT0;
+ }
+
+ if (VtdConfig->x2ApicEnabled == 1) {
+ DmarTable->Flags |= BIT1;
+ } else {
+ DmarTable->Flags &= 0xFD;
+ }
+
+ //
+ // Calculate IGD mem size
+ //
+ McD0BaseAddress = MmPciBase (SA_MC_BUS, 0, 0);
+ MchBar = MmioRead32 (McD0BaseAddress + R_SA_MCHBAR) & ~BIT0;
+ IgdMode = (MmioRead16 (McD0BaseAddress + R_SA_GGC) & B_SA_GGC_GMS_MASK) >> N_SA_GGC_GMS_OFFSET;
+
+ if (IgdMode < V_SA_GGC_GMS_2016MB) {
+ IgdMemSize = IgdMode * 32 * (1024) * (1024);
+ } else {
+ IgdMemSize = 0;
+ }
+
+ //
+ // Calculate GTT mem size
+ //
+ GttMemSize = 0;
+ GttMode = (MmioRead16 (McD0BaseAddress + R_SA_GGC) & B_SA_GGC_GGMS_MASK) >> N_SA_GGC_GGMS_OFFSET;
+
+ if (GttMode <= V_SA_GGC_GGMS_8MB) {
+ GttMemSize = (1 << GttMode) * (1024) * (1024);
+ }
+
+ DmarTable->RmrrIgd.RmrBaseAddress = (MmioRead32 (McD0BaseAddress + R_SA_TOLUD) & ~(0x01)) - IgdMemSize - GttMemSize;
+ DmarTable->RmrrIgd.RmrLimitAddress = DmarTable->RmrrIgd.RmrBaseAddress + IgdMemSize + GttMemSize - 1;
+
+ DEBUG ((DEBUG_INFO, "RMRR Base address IGD %016lX\n", DmarTable->RmrrIgd.RmrBaseAddress));
+ DEBUG ((DEBUG_INFO, "RMRR Limit address IGD %016lX\n", DmarTable->RmrrIgd.RmrLimitAddress));
+
+ DmarTable->RmrrUsb.RmrBaseAddress = VtdConfig->RmrrUsbBaseAddr;
+ DmarTable->RmrrUsb.RmrLimitAddress = VtdConfig->RmrrUsbLimit;
+
+ //
+ // Convert to 4KB alignment.
+ //
+ DmarTable->RmrrUsb.RmrBaseAddress &= (EFI_PHYSICAL_ADDRESS) ~0xFFF;
+ DmarTable->RmrrUsb.RmrLimitAddress &= (EFI_PHYSICAL_ADDRESS) ~0xFFF;
+ DmarTable->RmrrUsb.RmrLimitAddress += 0x1000 - 1;
+
+ DEBUG ((DEBUG_INFO, "RMRR Base address USB %016lX\n", DmarTable->RmrrUsb.RmrBaseAddress));
+ DEBUG ((DEBUG_INFO, "RMRR Limit address USB %016lX\n", DmarTable->RmrrUsb.RmrLimitAddress));
+
+
+ //
+ // Update DRHD structures of DmarTable
+ //
+ DmarTable->DrhdEngine1.RegisterBaseAddress = (MmioRead32 (MchBar + R_SA_MCHBAR_VTD1_OFFSET) &~3);
+ DmarTable->DrhdEngine2.RegisterBaseAddress = (MmioRead32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET) &~3);
+
+ DEBUG ((DEBUG_INFO, "VTD base address1 %x\n", DmarTable->DrhdEngine1.RegisterBaseAddress));
+ DEBUG ((DEBUG_INFO, "VTD base address2 %x\n", DmarTable->DrhdEngine2.RegisterBaseAddress));
+
+ //
+ // Copy DmarTable to TempDmarTable to be processed
+ //
+ CopyMem (&TempDmarTable, DmarTable, sizeof (EFI_ACPI_DMAR_TABLE));
+
+ //
+ // Update DRHD structures of temp DMAR table
+ //
+ UpdateDrhd (&TempDmarTable.DrhdEngine1);
+ UpdateDrhd2 (&TempDmarTable.DrhdEngine2);
+
+ //
+ // Update RMRR structures of temp DMAR table
+ //
+ UpdateRmrr ((VOID *) &TempDmarTable.RmrrUsb);
+ UpdateRmrr ((VOID *) &TempDmarTable.RmrrIgd);
+
+ //
+ // Remove unused device scope or entire DRHD structures
+ //
+ Offset = (UINTN) (&TempDmarTable.DrhdEngine1);
+ if (TempDmarTable.DrhdEngine1.Length != 0) {
+ Offset += TempDmarTable.DrhdEngine1.Length;
+ }
+
+ if (TempDmarTable.DrhdEngine2.Length != 0) {
+ StructureLen = TempDmarTable.DrhdEngine2.Length;
+ CopyMem ((VOID *) Offset, (VOID *) &TempDmarTable.DrhdEngine2, TempDmarTable.DrhdEngine2.Length);
+ Offset += StructureLen;
+ }
+
+ //
+ // Remove unused device scope or entire RMRR structures
+ //
+ if (TempDmarTable.RmrrUsb.Length != 0) {
+ StructureLen = TempDmarTable.RmrrUsb.Length;
+ CopyMem ((VOID *) Offset, (VOID *) &TempDmarTable.RmrrUsb, TempDmarTable.RmrrUsb.Length);
+ Offset += StructureLen;
+ }
+
+ if (TempDmarTable.RmrrIgd.Length != 0) {
+ StructureLen = TempDmarTable.RmrrIgd.Length;
+ CopyMem ((VOID *) Offset, (VOID *) &TempDmarTable.RmrrIgd, TempDmarTable.RmrrIgd.Length);
+ Offset += StructureLen;
+ }
+
+ Offset = Offset - (UINTN) &TempDmarTable;
+
+ //
+ // Re-calculate DMAR table check sum
+ //
+ TempDmarTable.Header.Checksum = (UINT8) (TempDmarTable.Header.Checksum + TempDmarTable.Header.Length - Offset);
+
+ //
+ // Set DMAR table length
+ //
+ TempDmarTable.Header.Length = (UINT32) Offset;
+
+ //
+ // Replace DMAR table with rebuilt table TempDmarTable
+ //
+ CopyMem ((VOID *) DmarTable, (VOID *) &TempDmarTable, TempDmarTable.Header.Length);
+
+ DEBUG ((DEBUG_INFO, "DmarTableUpdate() - end\n"));
+}
+
+
+/**
+ ReadyToBoot callback routine to update DMAR
+
+**/
+VOID
+UpdateDmarOnReadyToBoot (
+ BOOLEAN VtEnable
+ )
+{
+ EFI_ACPI_DESCRIPTION_HEADER *Table;
+ EFI_ACPI_SUPPORT_PROTOCOL *AcpiSupport;
+ EFI_ACPI_TABLE_VERSION Version;
+ EFI_STATUS Status;
+ UINT8 Index;
+ UINTN Handle;
+
+ AcpiSupport = NULL;
+ Index = 0;
+
+ //
+ // Locate ACPI support protocol
+ //
+ Status = gBS->LocateProtocol (&gEfiAcpiSupportProtocolGuid, NULL, (VOID **) &AcpiSupport);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Find the DMAR ACPI table
+ //
+ do {
+ Status = AcpiSupport->GetAcpiTable(AcpiSupport, Index, (VOID **) &Table, &Version, &Handle);
+ if (Status == EFI_NOT_FOUND) {
+ break;
+ }
+ ASSERT_EFI_ERROR(Status);
+ Index++;
+ } while (Table->Signature != EFI_ACPI_VTD_DMAR_TABLE_SIGNATURE);
+
+ DEBUG ((DEBUG_INFO, "DMAR ACPI Table: Address = 0x%x, Version = %u, Handle = %u\n", Table, Version, Handle));
+
+ if (VtEnable) {
+ //
+ // Update the DMAR table structure
+ //
+ DEBUG ((DEBUG_INFO, "DMAR ACPI table to be Installed \n"));
+ DmarTableUpdate (Table, &Version);
+ } else {
+ //
+ // Uninstall DMAR table
+ //
+ DEBUG ((DEBUG_INFO, "DMAR ACPI table to be Uninstalled \n"));
+ Table = NULL;
+ }
+
+ //
+ // Update the DMAR ACPI table
+ //
+ Status = AcpiSupport->SetAcpiTable (
+ AcpiSupport,
+ Table,
+ TRUE,
+ Version,
+ &Handle
+ );
+
+ if (!EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_INFO, "DMAR ACPI table was successfully updated\n"));
+ } else {
+ DEBUG ((DEBUG_ERROR, "Error updating the DMAR ACPI table\n"));
+ }
+}
+
+
+/**
+ Update RMRR Base and Limit Address for USB.
+
+**/
+VOID
+UpdateRmrrUsbAddress (
+ IN SC_VTD_CONFIG *VtdConfig
+ )
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS Address;
+ UINTN Size;
+
+ if (VtdConfig->RmrrUsbBaseAddr != 0) {
+ //
+ // The buffer did assign.
+ //
+ return;
+ }
+
+ Size = EFI_SIZE_TO_PAGES(VTD_RMRR_USB_LENGTH);
+ Address = 0xFFFFFFFF;
+
+ Status = gBS->AllocatePages (
+ AllocateMaxAddress,
+ EfiReservedMemoryType,
+ Size,
+ &Address
+ );
+ ASSERT_EFI_ERROR (Status);
+
+
+ VtdConfig->RmrrUsbBaseAddr = Address;
+ VtdConfig->RmrrUsbLimit = Address + VTD_RMRR_USB_LENGTH - 1;
+
+ return;
+}
+
+
+/**
+ Locate the VT-d ACPI tables data file and update it based on current configuration and capabilities.
+
+ @retval EFI_SUCCESS VT-d initialization complete
+ @retval EFI_UNSUPPORTED VT-d is disabled by policy or not supported
+
+**/
+EFI_STATUS
+VtdInit (
+ VOID
+ )
+{
+ UINTN McD0BaseAddress;
+ SC_POLICY_HOB *ScPolicy;
+ EFI_PEI_HOB_POINTERS HobPtr;
+ SC_VTD_CONFIG *VtdConfig;
+ EFI_STATUS Status;
+
+ DEBUG ((DEBUG_INFO, "VtdInit () - Start\n"));
+ McD0BaseAddress = MmPciBase (SA_MC_BUS, 0, 0);
+
+ //
+ // Get SC VT-d config block
+ //
+ HobPtr.Guid = GetFirstGuidHob (&gScPolicyHobGuid);
+ ASSERT (HobPtr.Guid != NULL);
+ ScPolicy = (SC_POLICY_HOB*) GET_GUID_HOB_DATA (HobPtr.Guid);
+ Status = GetConfigBlock ((VOID *) ScPolicy, &gVtdConfigGuid, (VOID *) &VtdConfig);
+ ASSERT_EFI_ERROR (Status);
+ DEBUG ((DEBUG_INFO, "ScPolicy VtdEnable = %x\n", VtdConfig->VtdEnable));
+
+ if ((VtdConfig->VtdEnable == 0) || (MmioRead32 (McD0BaseAddress + R_SA_MC_CAPID0_A) & BIT23)) {
+ DEBUG ((DEBUG_INFO, "VT-d Disabled or not supported on this platform, skip DMAR Table update\n"));
+ return EFI_UNSUPPORTED;
+ }
+
+ if (((AsmReadMsr64 (EFI_MSR_XAPIC_BASE)) & (BIT11 + BIT10)) == BIT11 + BIT10) {
+ VtdConfig->x2ApicEnabled = 1;
+ } else {
+ VtdConfig->x2ApicEnabled = 0;
+ }
+
+ //
+ // Update RMRR USB address
+ //
+ UpdateRmrrUsbAddress (VtdConfig);
+
+ DEBUG ((DEBUG_INFO, "VtdInit () - End\n"));
+
+ return EFI_SUCCESS;
+}
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/DxeVtdLib/DxeVtdLib.inf b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/DxeVtdLib/DxeVtdLib.inf
new file mode 100644
index 0000000000..4f22249ac7
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/DxeVtdLib/DxeVtdLib.inf
@@ -0,0 +1,62 @@
+## @file
+# Library for Intel VT-d.
+#
+# Copyright (c) 1999 - 2016, 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 = DxeVtdLib
+ FILE_GUID = A5525CF4-88CD-4c7b-8C9F-4E3343CED768
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = DxeVtdLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources.common]
+ DxeVtdLib.c
+
+[Guids]
+ gVtdConfigGuid
+ gScPolicyHobGuid
+
+[Protocols]
+ gEfiAcpiSupportProtocolGuid ## CONSUMES
+
+[Packages]
+ MdePkg/MdePkg.dec
+ BroxtonSiPkg/BroxtonSiPkg.dec
+ BroxtonSiPkg/BroxtonSiPrivate.dec
+
+[LibraryClasses]
+ DebugLib
+ IoLib
+ BaseLib
+ PcdLib
+ UefiLib
+ HobLib
+ ScPlatformLib
+ MmPciLib
+ BaseMemoryLib
+ UefiBootServicesTableLib
+ MemoryAllocationLib
+ SteppingLib
+ ConfigBlockLib
+
+[Pcd]
+ gEfiBxtTokenSpaceGuid.PcdVtdGfxBaseAddress ## ALWAYS_CONSUMES
+ gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress ## SOMETIMES_CONSUMES
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/PeiDxeSmmPchSerialIoLib/PeiDxeSmmPchSerialIoLib.c b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/PeiDxeSmmPchSerialIoLib/PeiDxeSmmPchSerialIoLib.c
new file mode 100644
index 0000000000..36dcf53d1c
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/PeiDxeSmmPchSerialIoLib/PeiDxeSmmPchSerialIoLib.c
@@ -0,0 +1,293 @@
+/** @file
+ PCH Serial IO Lib implementation.
+ All function in this library is available for PEI, DXE, and SMM,
+ But do not support UEFI RUNTIME environment call.
+
+ Copyright (c) 2014 - 2016, 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.
+
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/BaseLib.h>
+#include <IndustryStandard/Pci30.h>
+#include <ScAccess.h>
+#include <ScRegs/RegsLpss.h>
+#include <Library/ScPcrLib.h>
+#include <Library/ScInfoLib.h>
+#include <Library/MmPciLib.h>
+#include <Library/ScSerialIoLib.h>
+
+typedef struct {
+ UINT32 Bar0;
+ UINT32 Bar1;
+} SERIAL_IO_CONTROLLER_DESCRIPTOR;
+
+typedef struct {
+ UINT8 DevNum;
+ UINT8 FuncNum;
+} SERIAL_IO_BDF_NUMBERS;
+
+typedef struct {
+ UINT16 PciDevIdLp;
+ CHAR8 AcpiHid[SERIALIO_HID_LENGTH];
+} SERIAL_IO_ID;
+
+GLOBAL_REMOVE_IF_UNREFERENCED SERIAL_IO_BDF_NUMBERS mSerialIoBdf [4] =
+{
+ {PCI_DEVICE_NUMBER_LPSS_HSUART, PCI_FUNCTION_NUMBER_LPSS_HSUART0},
+ {PCI_DEVICE_NUMBER_LPSS_HSUART, PCI_FUNCTION_NUMBER_LPSS_HSUART1},
+ {PCI_DEVICE_NUMBER_LPSS_HSUART, PCI_FUNCTION_NUMBER_LPSS_HSUART2},
+ {PCI_DEVICE_NUMBER_LPSS_HSUART, PCI_FUNCTION_NUMBER_LPSS_HSUART3},
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED SERIAL_IO_CONTROLLER_DESCRIPTOR mSerialIoAcpiAddress [4] =
+{
+
+ {LPSS_I2C0_TMP_BAR0 + 0x80000,LPSS_I2C0_TMP_BAR0 + 0x81000},
+ {LPSS_I2C0_TMP_BAR0 + 0x90000,LPSS_I2C0_TMP_BAR0 + 0x91000},
+ {LPSS_I2C0_TMP_BAR0 + 0x100000,LPSS_I2C0_TMP_BAR0 + 0x101000},
+ {LPSS_I2C0_TMP_BAR0 + 0x110000,LPSS_I2C0_TMP_BAR0 + 0x111000},
+};
+
+typedef struct {
+ UINT16 PciCfgCtrAddr;
+ UINT16 Psf3BaseAddress;
+} SERIAL_IO_CONTROLLER_PSF3_OFFSETS;
+
+GLOBAL_REMOVE_IF_UNREFERENCED SERIAL_IO_CONTROLLER_PSF3_OFFSETS mPchLpSerialIoPsf3Offsets [4] =
+{
+ { 0x220, 0x1100},
+ { 0x224, 0x1000},
+ { 0x228, 0x0F00},
+ { 0x22C, 0x0E00},
+};
+
+
+/**
+ Finds PCI Device Number of SerialIo devices.
+ SerialIo devices' BDF is configurable
+
+ @param[in] SerialIoDevice 0=I2C0, ..., 11=UART2
+
+ @retval UINT8 SerialIo device number
+
+**/
+UINT8
+GetSerialIoDeviceNumber (
+ IN PCH_SERIAL_IO_CONTROLLER SerialIoNumber
+ )
+{
+ return mSerialIoBdf[SerialIoNumber].DevNum;
+}
+
+
+/**
+ Finds PCI Function Number of SerialIo devices.
+ SerialIo devices' BDF is configurable
+
+ @param[in] SerialIoDevice 0=I2C0, ..., 11=UART2
+
+ @retval UINT8 SerialIo funciton number
+
+**/
+UINT8
+GetSerialIoFunctionNumber (
+ IN PCH_SERIAL_IO_CONTROLLER SerialIoNumber
+ )
+{
+ return mSerialIoBdf[SerialIoNumber].FuncNum;
+}
+
+
+/**
+ Finds BAR value of SerialIo devices.
+
+ SerialIo devices can be configured to not appear on PCI so traditional method of reading BAR might not work.
+ If the SerialIo device is in PCI mode, a request for BAR1 will return its PCI CFG space instead
+
+ @param[in] SerialIoDevice 0=I2C0, ..., 11=UART2
+ @param[in] BarNumber 0=BAR0, 1=BAR1
+
+ @retval UINTN SerialIo Bar value
+
+**/
+UINTN
+FindSerialIoBar (
+ IN PCH_SERIAL_IO_CONTROLLER SerialIoDevice,
+ IN UINT8 BarNumber
+ )
+{
+ UINT32 Bar;
+ UINTN PcieBase;
+ UINT32 VenId;
+
+ PcieBase = MmPciBase (DEFAULT_PCI_BUS_NUMBER_SC, GetSerialIoDeviceNumber (SerialIoDevice), GetSerialIoFunctionNumber (SerialIoDevice));
+
+ VenId = MmioRead32 (PcieBase + PCI_VENDOR_ID_OFFSET) & 0xFFFF;
+
+ if (VenId == V_INTEL_VENDOR_ID) {
+ if (BarNumber == 1) {
+ return PcieBase;
+ }
+ Bar = (MmioRead32 (PcieBase + PCI_BASE_ADDRESSREG_OFFSET + 8*BarNumber) & 0xFFFFF000);
+ return Bar;
+ }
+
+ return 0xFFFFFFFF;
+}
+
+
+/**
+ Configures Serial IO Controller.
+
+ @param[in] Controller 0=I2C0, ..., 11=UART2
+ @param[in] DeviceMode Different type of serial io mode defined in PCH_SERIAL_IO_MODE
+ @param[in] SerialIoSafeRegister D0i3 Max Power On Latency and Device PG config
+
+**/
+VOID
+ConfigureSerialIoController (
+ IN PCH_SERIAL_IO_CONTROLLER Controller,
+ IN PCH_SERIAL_IO_MODE DeviceMode
+#ifdef PCH_PO_FLAG
+ , IN UINT32 SerialIoSafeRegister
+#endif
+ )
+{
+ UINTN PciCfgBase;
+ UINTN Bar;
+ UINT32 Data32;
+ SERIAL_IO_CONTROLLER_PSF3_OFFSETS *SerialIoPsf3Offsets;
+
+ PciCfgBase = MmPciBase (0, GetSerialIoDeviceNumber (Controller), GetSerialIoFunctionNumber (Controller));
+
+ //
+ // Do not modify a device that has already been initialized
+ //
+ if (MmioRead16(PciCfgBase + PCI_VENDOR_ID_OFFSET) != V_INTEL_VENDOR_ID) {
+ return;
+ }
+
+#ifdef PCH_PO_FLAG
+ if (!SerialIoSafeRegister) {
+#endif
+ //
+ // Step 1. Set Bit 16,17,18.
+ //
+ MmioOr32 (PciCfgBase + R_LPSS_IO_D0I3MAXDEVPG, BIT18 | BIT17 | BIT16);
+#ifdef PCH_PO_FLAG
+ }
+#endif
+
+ SerialIoPsf3Offsets = mPchLpSerialIoPsf3Offsets;
+
+ Bar = MmioRead32(PciCfgBase + R_LPSS_IO_BAR) & 0xFFFFF000;
+
+ switch (DeviceMode) {
+ case PchSerialIoDisabled:
+ MmioOr32 (PciCfgBase + R_LPSS_IO_PCS, BIT1 | BIT0);
+ PchPcrAndThenOr32 (0xC6, SerialIoPsf3Offsets[Controller].Psf3BaseAddress+0x001C, 0xFFFFFFFF, BIT8);
+ break;
+
+ case PchSerialIoAcpi:
+ case PchSerialIoAcpiHidden:
+ case PchSerialIoLegacyUart:
+ //
+ // Assign BAR0
+ // Assign BAR1
+ //
+ if (Bar == 0) {
+ MmioWrite32 (PciCfgBase + R_LPSS_IO_BAR, mSerialIoAcpiAddress[Controller].Bar0);
+ MmioWrite32 (PciCfgBase + R_LPSS_IO_BAR_HIGH, 0x0);
+ MmioWrite32 (PciCfgBase + R_LPSS_IO_BAR1, mSerialIoAcpiAddress[Controller].Bar1);
+ MmioWrite32 (PciCfgBase + R_LPSS_IO_BAR1_HIGH, 0x0);
+ Bar = MmioRead32 (PciCfgBase + R_LPSS_IO_BAR) & 0xFFFFF000;
+ }
+
+ MmioWrite32 (Bar + R_LPSS_IO_REMAP_ADDRESS_LOW, Bar);
+
+ //
+ // Set Memory space Enable
+ //
+ MmioOr32 (PciCfgBase + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_MEMORY_SPACE | EFI_PCI_COMMAND_BUS_MASTER);
+
+ //
+ // Get controller out of reset
+ //
+ MmioWrite32 (Bar + R_LPSS_IO_MEM_RESETS, 0);
+ MmioWrite32 (Bar + R_LPSS_IO_MEM_RESETS, B_LPSS_IO_MEM_HC_RESET_REL | B_LPSS_IO_MEM_iDMA_RESET_REL);
+ break;
+
+ case PchSerialIoPci:
+ if (Bar == 0) {
+
+ PchPcrAndThenOr32 (0x90, SerialIoPsf3Offsets[Controller].PciCfgCtrAddr, 0xFFFFFFFF, BIT7);
+ PchPcrAndThenOr32 (0xC6, SerialIoPsf3Offsets[Controller].Psf3BaseAddress + 0x001C, 0xFFFFFFFF, BIT18);
+
+ do {
+ PchPcrRead32(0xC6, SerialIoPsf3Offsets[Controller].Psf3BaseAddress + 0x001C, &Data32);
+ } while (Data32 & BIT18 != BIT18);
+
+ //
+ // Assign BAR0 and Set Memory space Enable
+ //
+ MmioWrite32 (PciCfgBase + R_LPSS_IO_BAR, mSerialIoAcpiAddress[Controller].Bar0);
+ MmioWrite32 (PciCfgBase + R_LPSS_IO_BAR_HIGH, 0x0);
+ MmioOr32 (PciCfgBase + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_MEMORY_SPACE | EFI_PCI_COMMAND_BUS_MASTER);
+
+ //
+ // Read Newly Assigned BAR
+ //
+ Bar = MmioRead32(PciCfgBase + R_LPSS_IO_BAR) & 0xFFFFF000;
+ }
+
+ //
+ // Update Address Remap Register with Current BAR
+ //
+ MmioWrite32 (Bar + R_LPSS_IO_REMAP_ADDRESS_LOW, Bar);
+
+ ///
+ /// Get controller out of reset
+ ///
+ MmioWrite32 (Bar + R_LPSS_IO_MEM_RESETS, 0);
+
+ MmioOr32 (Bar + R_LPSS_IO_MEM_RESETS, B_LPSS_IO_MEM_HC_RESET_REL | B_LPSS_IO_MEM_iDMA_RESET_REL);
+ break;
+
+ default:
+ return;
+ }
+
+ //
+ // Program clock dividers for UARTs in legacy mode
+ // Enable Byte addressing for UARTs in legacy mode
+ //
+ if (Controller >= PchSerialIoIndexUart0 && Controller <= PchSerialIoIndexUart3) {
+ Data32 = B_LPSS_IO_MEM_PCP_CLK_UPDATE | (V_LPSS_IO_PPR_CLK_N_DIV << 16) | (V_LPSS_IO_PPR_CLK_M_DIV << 1) | B_LPSS_IO_MEM_PCP_CLK_EN;
+ MmioWrite32 (Bar + R_LPSS_IO_MEM_PCP, Data32);
+
+ if (DeviceMode == PchSerialIoLegacyUart) {
+ //
+ // Set UART Byte Address Control - Control bit for 16550 8-Bit Addressing Mode.
+ //
+ PchPcrAndThenOr32(0x90, 0x618, 0xFFFFFFFF, (BIT0 << (Controller - PchSerialIoIndexUart0)));
+
+ //
+ // An MMIO Read Must Immediately Be Issued to UART2 BAR0 + 0xF8 for 8-bit Legacy Mode to Activate
+ //
+ MmioRead32(Bar + R_LPSS_IO_MANID);
+ }
+ }
+}
+
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/PeiDxeSmmPchSerialIoLib/PeiDxeSmmPchSerialIoLib.inf b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/PeiDxeSmmPchSerialIoLib/PeiDxeSmmPchSerialIoLib.inf
new file mode 100644
index 0000000000..2e8b9b5bf0
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/PeiDxeSmmPchSerialIoLib/PeiDxeSmmPchSerialIoLib.inf
@@ -0,0 +1,41 @@
+## @file
+# Library for Pch Serial Io.
+#
+# Copyright (c) 2014 - 2016, 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 = PeiDxeSmmPchSerialIoLib
+ FILE_GUID = 613A22A2-5736-40f8-909B-DF10EA389C72
+ VERSION_STRING = 1.0
+ MODULE_TYPE = BASE
+ LIBRARY_CLASS = PchSerialIoLib
+
+[Sources]
+ PeiDxeSmmPchSerialIoLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ BroxtonSiPkg/BroxtonSiPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ IoLib
+ DebugLib
+ MmPciLib
+ ScPlatformLib
+
+[BuildOptions]
+ *_*_IA32_ASM_FLAGS = /w /Od /GL-
+ *_*_IA32_CC_FLAGS = /w /Od /GL-
+ *_*_X64_CC_FLAGS = /w /Od /GL-
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/PeiDxeSmmPchSerialIoUartLib/PeiDxeSmmPchSerialIoUartLib.c b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/PeiDxeSmmPchSerialIoUartLib/PeiDxeSmmPchSerialIoUartLib.c
new file mode 100644
index 0000000000..ed34140562
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/PeiDxeSmmPchSerialIoUartLib/PeiDxeSmmPchSerialIoUartLib.c
@@ -0,0 +1,348 @@
+/** @file
+ PCH Serial IO UART Lib implementation.
+ All function in this library is available for PEI, DXE, and SMM,
+ But do not support UEFI RUNTIME environment call.
+
+ Copyright (c) 2014 - 2016, 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.
+
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/BaseLib.h>
+#include <Library/TimerLib.h>
+#include <ScAccess.h>
+#include <Library/ScPcrLib.h>
+#include <Library/ScSerialIoLib.h>
+
+#define MAX_BAUD_RATE 460800 // Maximum Baud per SoC spec
+
+#define R_PCH_SERIAL_IO_8BIT_UART_RXBUF 0x00
+#define R_PCH_SERIAL_IO_8BIT_UART_TXBUF 0x00
+#define R_PCH_SERIAL_IO_8BIT_UART_BAUD_LOW 0x00
+#define R_PCH_SERIAL_IO_8BIT_UART_BAUD_HIGH 0x01
+#define R_PCH_SERIAL_IO_8BIT_UART_FCR 0x02
+#define R_PCH_SERIAL_IO_8BIT_UART_IIR 0x02
+#define R_PCH_SERIAL_IO_8BIT_UART_LCR 0x03
+#define R_PCH_SERIAL_IO_8BIT_UART_MCR 0x04
+#define R_PCH_SERIAL_IO_8BIT_UART_LSR 0x05
+#define R_PCH_SERIAL_IO_8BIT_UART_USR 0x1F
+
+#define R_PCH_SERIAL_IO_NATIVE_UART_RXBUF 0x00
+#define R_PCH_SERIAL_IO_NATIVE_UART_TXBUF 0x00
+#define R_PCH_SERIAL_IO_NATIVE_UART_BAUD_LOW 0x00
+#define R_PCH_SERIAL_IO_NATIVE_UART_BAUD_HIGH 0x04
+#define R_PCH_SERIAL_IO_NATIVE_UART_FCR 0x08
+#define R_PCH_SERIAL_IO_NATIVE_UART_IIR 0x08
+#define R_PCH_SERIAL_IO_NATIVE_UART_LCR 0x0C
+#define R_PCH_SERIAL_IO_NATIVE_UART_MCR 0x10
+#define R_PCH_SERIAL_IO_NATIVE_UART_LSR 0x14
+#define R_PCH_SERIAL_IO_NATIVE_UART_USR 0x7C
+
+#define B_PCH_SERIAL_IO_UART_IIR_FIFOSE BIT7|BIT6
+#define B_PCH_SERIAL_IO_UART_LSR_TXRDY BIT5
+#define B_PCH_SERIAL_IO_UART_LSR_RXDA BIT0
+#define B_PCH_SERIAL_IO_UART_LCR_DLAB BIT7
+#define B_PCH_SERIAL_IO_UART_FCR_FCR BIT0
+#define B_PCH_SERIAL_IO_UART_MCR_RTS BIT1
+#define B_PCH_SERIAL_IO_UART_MCR_AFCE BIT5
+#define B_PCH_SERIAL_IO_UART_USR_TFNF BIT1
+
+/**
+ Initialize selected SerialIo UART.
+
+ @param[in] UartNumber Selects Serial IO UART device (0-2)
+ @param[in] FifoEnable When TRUE, enables 64-byte FIFOs.
+ @param[in] BaudRate Baud rate.
+ @param[in] LineControl Data length, parity, stop bits.
+ @param[in] HardwareFlowControl Automated hardware flow control. If TRUE, hardware automatically checks CTS when sending data, and sets RTS when receiving data.
+
+**/
+VOID
+SerialIo16550Init (
+ IN UINTN Base,
+ IN BOOLEAN FifoEnable,
+ IN UINT32 BaudRate,
+ IN UINT8 LineControl,
+ IN BOOLEAN HardwareFlowControl,
+ IN UINT8 ShiftOffset
+ )
+{
+ UINTN Divisor;
+
+ Divisor = MAX_BAUD_RATE / BaudRate;
+ //
+ // Configure baud rate
+ //
+ MmioWrite8 (Base + (R_PCH_SERIAL_IO_NATIVE_UART_LCR >> ShiftOffset), B_PCH_SERIAL_IO_UART_LCR_DLAB);
+ MmioWrite8 (Base + (R_PCH_SERIAL_IO_NATIVE_UART_BAUD_HIGH >> ShiftOffset), (UINT8) (Divisor >> 8));
+ MmioWrite8 (Base + (R_PCH_SERIAL_IO_NATIVE_UART_BAUD_LOW >> ShiftOffset), (UINT8) (Divisor & 0xff));
+ //
+ // Configure Line control and switch back to bank 0
+ //
+ MmioWrite8 (Base + (R_PCH_SERIAL_IO_NATIVE_UART_LCR >> ShiftOffset), LineControl & 0x1F);
+ //
+ // Enable and reset FIFOs
+ //
+ MmioWrite8 (Base + (R_PCH_SERIAL_IO_NATIVE_UART_FCR >> ShiftOffset), FifoEnable ? B_PCH_SERIAL_IO_UART_FCR_FCR : 0);
+ //
+ // Put Modem Control Register(MCR) into its reset state of 0x00.
+ //
+ MmioWrite8 (Base + (R_PCH_SERIAL_IO_NATIVE_UART_MCR >> ShiftOffset), B_PCH_SERIAL_IO_UART_MCR_RTS | (HardwareFlowControl ? B_PCH_SERIAL_IO_UART_MCR_AFCE : 0) );
+
+ return;
+}
+
+
+/**
+ Initialize selected SerialIo UART.
+ This init function MUST be used prior any SerialIo UART functions to init serial io controller
+ if platform is going use serialio UART as debug output.
+
+ @param[in] UartNumber Selects Serial IO UART device (0-2)
+ @param[in] FifoEnable When TRUE, enables 64-byte FIFOs.
+ @param[in] BaudRate Baud rate.
+ @param[in] LineControl Data length, parity, stop bits.
+ @param[in] HardwareFlowControl Automated hardware flow control. If TRUE, hardware automatically checks CTS when sending data,
+ and sets RTS when receiving data.
+ @retval BOOLEAN Initilization succeeded.
+
+**/
+BOOLEAN
+EFIAPI
+PchSerialIoUartInit (
+ IN UINT8 UartNumber,
+ IN BOOLEAN FifoEnable,
+ IN UINT32 BaudRate,
+ IN UINT8 LineControl,
+ IN BOOLEAN HardwareFlowControl
+ )
+{
+ UINT32 UartMode = 0;
+ UINTN Bar = 0;
+ UINT8 ShiftOffset = 0;
+
+ if (UartNumber > 3) {
+ return FALSE; // In case of invalid UART device
+ }
+
+#ifdef PCH_PO_FLAG
+ ConfigureSerialIoController (UartNumber + PchSerialIoIndexUart0, PchSerialIoPci, 0);
+#else
+ ConfigureSerialIoController (UartNumber + PchSerialIoIndexUart0, PchSerialIoPci);
+#endif
+
+ //
+ // Find UART Mode (Checking for 16550 Mode)
+ //
+ PchPcrRead32 (0x90, 0x618, &UartMode);
+
+ if (UartMode == BIT2) {
+ ShiftOffset = 2;
+ }
+
+ Bar = FindSerialIoBar (UartNumber + PchSerialIoIndexUart0, 0);
+
+ if (Bar == 0xFFFFFFFF) {
+ return FALSE;
+ }
+
+ SerialIo16550Init (Bar, FifoEnable, BaudRate, LineControl, HardwareFlowControl, ShiftOffset);
+ return TRUE;
+}
+
+
+/**
+ Write data to serial device.
+
+ If the buffer is NULL, then return 0;
+ if NumberOfBytes is zero, then return 0.
+
+ @param[in] UartNumber Selects Serial IO UART device (0-2)
+ @param[in] Buffer Point of data buffer which need to be writed.
+ @param[in] NumberOfBytes Number of output bytes which are cached in Buffer.
+
+ @retval UINTN Actual number of bytes writed to serial device.
+**/
+UINTN
+EFIAPI
+PchSerialIoUartOut (
+ IN UINT8 UartNumber,
+ IN UINT8 *Buffer,
+ IN UINTN NumberOfBytes
+ )
+{
+ UINTN BytesLeft;
+ volatile UINTN Base;
+ UINT32 UartMode = 0;
+ UINT8 ShiftOffset = 0;
+ UINT32 TxAttemptCount = 0;
+
+ if (UartNumber > 3) {
+ return 0; // In case of invalid UART device
+ }
+
+ Base = FindSerialIoBar (UartNumber + PchSerialIoIndexUart0, 0);
+
+ //
+ // Sanity checks to avoid infinite loop when trying to print through uninitialized UART
+ //
+ // If BAR is unavailable, write 0 bytes to the device
+ //
+ if (Base == 0xFFFFFFFF ||
+ (Base & 0xFFFFFF00) == 0x0 ||
+ MmioRead8 (Base + (R_PCH_SERIAL_IO_NATIVE_UART_USR >> ShiftOffset)) == 0xFF ||
+ Buffer == NULL) {
+ return 0;
+ }
+
+ PchPcrRead32(0x90, 0x618, &UartMode);
+
+ if (UartMode == BIT2)
+ {
+ ShiftOffset = 2;
+ }
+
+ BytesLeft = NumberOfBytes;
+
+ while (BytesLeft != 0 && TxAttemptCount < 200) {
+ //
+ // Write data while there's room in TXFIFO. If HW Flow Control was enabled, it happens automatically on hardware level.
+ //
+ while ((MmioRead8(Base + (R_PCH_SERIAL_IO_NATIVE_UART_IIR >> ShiftOffset)) & 0xF) == 0x10);
+
+ if (MmioRead8 (Base + (R_PCH_SERIAL_IO_NATIVE_UART_USR >> ShiftOffset)) & B_PCH_SERIAL_IO_UART_USR_TFNF) {
+ MmioWrite8 (Base + R_PCH_SERIAL_IO_NATIVE_UART_TXBUF, *Buffer);
+
+ TxAttemptCount = 0;
+ Buffer++;
+ BytesLeft--;
+ }
+ TxAttemptCount++;
+ }
+
+ return NumberOfBytes;
+}
+
+
+/**
+ Read data from serial device and save the datas in buffer.
+
+ If the buffer is NULL, then return 0;
+ if NumberOfBytes is zero, then return 0.
+
+ @param[in] UartNumber Selects Serial IO UART device (0-2)
+ @param[out] Buffer Point of data buffer which need to be writed.
+ @param[in] NumberOfBytes Number of output bytes which are cached in Buffer.
+ @param[in] WaitUntilBufferFull When TRUE, function waits until whole buffer is filled. When FALSE,
+ function returns as soon as no new characters are available.
+
+ @retval UINTN Actual number of bytes read to the serial device.
+
+**/
+UINTN
+EFIAPI
+PchSerialIoUartIn (
+ IN UINT8 UartNumber,
+ OUT UINT8 *Buffer,
+ IN UINTN NumberOfBytes,
+ IN BOOLEAN WaitUntilBufferFull
+ )
+{
+ UINTN BytesReceived;
+ UINTN Base;
+ UINT32 UartMode = 0;
+ UINT8 ShiftOffset = 0;
+
+ if (UartNumber > 3) {
+ return 0; // In case of invalid UART device
+ }
+
+ Base = FindSerialIoBar (UartNumber + PchSerialIoIndexUart0, 0);
+
+ //
+ // If BAR is unavailable, receive 0 bytes
+ //
+ if (Base == 0xFFFFFFFF) {
+ return 0;
+ }
+
+ PchPcrRead32 (0x90, 0x618, &UartMode);
+ if (UartMode == 4) {
+ ShiftOffset = 2;
+ }
+
+ if (NULL == Buffer) {
+ return 0;
+ }
+
+ BytesReceived = 0;
+
+ while (BytesReceived != NumberOfBytes) {
+ //
+ // check if there's data in RX buffer
+ //
+ if (MmioRead8 (Base + (R_PCH_SERIAL_IO_NATIVE_UART_LSR >> ShiftOffset)) & B_PCH_SERIAL_IO_UART_LSR_RXDA) {
+ //
+ // Receive data
+ //
+ *Buffer = MmioRead8 (Base + R_PCH_SERIAL_IO_NATIVE_UART_RXBUF);
+ Buffer++;
+ BytesReceived++;
+ } else {
+ if (!WaitUntilBufferFull && ((MmioRead8(Base + (R_PCH_SERIAL_IO_NATIVE_UART_LSR >> ShiftOffset)) & BIT0) == 0)) {
+ //
+ // If there's no data and function shouldn't wait, exit early
+ //
+ return BytesReceived;
+ }
+ }
+ }
+
+ return BytesReceived;
+}
+
+
+/**
+ Polls a serial device to see if there is any data waiting to be read.
+
+ If there is data waiting to be read from the serial device, then TRUE is returned.
+ If there is no data waiting to be read from the serial device, then FALSE is returned.
+
+ @param[in] UartNumber Selects Serial IO UART device (0-2)
+
+ @retval TRUE Data is waiting to be read from the serial device.
+ @retval FALSE There is no data waiting to be read from the serial device.
+
+**/
+BOOLEAN
+EFIAPI
+PchSerialIoUartPoll (
+ IN UINT8 UartNumber
+ )
+{
+ UINTN Base;
+
+ if (UartNumber > 3) {
+ return FALSE; // In case of invalid UART device
+ }
+
+ Base = FindSerialIoBar (UartNumber + PchSerialIoIndexUart0, 0);
+ //
+ // Read the serial port status
+ //
+ if ((MmioRead8 (Base + R_PCH_SERIAL_IO_NATIVE_UART_LSR) & B_PCH_SERIAL_IO_UART_LSR_RXDA) != 0) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/PeiDxeSmmPchSerialIoUartLib/PeiDxeSmmPchSerialIoUartLib.inf b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/PeiDxeSmmPchSerialIoUartLib/PeiDxeSmmPchSerialIoUartLib.inf
new file mode 100644
index 0000000000..18ae567999
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/PeiDxeSmmPchSerialIoUartLib/PeiDxeSmmPchSerialIoUartLib.inf
@@ -0,0 +1,40 @@
+## @file
+# Library for Pch Serial Io Uart.
+#
+# Copyright (c) 2014 - 2016, 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 = PeiDxeSmmPchSerialIoUartLib
+ FILE_GUID = 55463A54-FD0D-4e8e-8D57-D54FAAEFDC2F
+ VERSION_STRING = 1.0
+ MODULE_TYPE = BASE
+ LIBRARY_CLASS = PchSerialIoUartLib
+
+[Sources]
+ PeiDxeSmmPchSerialIoUartLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ BroxtonSiPkg/BroxtonSiPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ IoLib
+ DebugLib
+ MmPciLib
+ PchSerialIoLib
+ TimerLib
+
+[Pcd]
+ gBxtRefCodePkgTokenSpaceGuid.PcdSerialIoUartNumber
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/PeiScPolicyLib/PeiScPolicyLib.c b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/PeiScPolicyLib/PeiScPolicyLib.c
new file mode 100644
index 0000000000..bfdb6d0a1f
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/PeiScPolicyLib/PeiScPolicyLib.c
@@ -0,0 +1,862 @@
+/** @file
+ This file is PeiScPolicy library.
+
+ Copyright (c) 2014 - 2016, 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.
+
+**/
+
+#include "PeiScPolicyLibrary.h"
+#include <Library/SteppingLib.h>
+
+GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mSmbusRsvdAddresses[] = {
+ 0xA0,
+ 0xA2,
+ 0xA4,
+ 0xA6
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED PRIVATE_PCICFGCTRL mDirectIrqTable[] = {
+ { 0x90, 0x200, 27, V_PCICFG_CTRL_INTA },
+ { 0x90, 0x204, 28, V_PCICFG_CTRL_INTB },
+ { 0x90, 0x208, 29, V_PCICFG_CTRL_INTC },
+ { 0x90, 0x20C, 30, V_PCICFG_CTRL_INTD },
+ { 0x90, 0x210, 31, V_PCICFG_CTRL_INTA },
+ { 0x90, 0x214, 32, V_PCICFG_CTRL_INTB },
+ { 0x90, 0x218, 33, V_PCICFG_CTRL_INTC },
+ { 0x90, 0x21C, 34, V_PCICFG_CTRL_INTD },
+ { 0x90, 0x220, 4, V_PCICFG_CTRL_INTA },
+ { 0x90, 0x224, 5, V_PCICFG_CTRL_INTB },
+ { 0x90, 0x228, 6, V_PCICFG_CTRL_INTC },
+ { 0x90, 0x22C, 7, V_PCICFG_CTRL_INTD },
+ { 0x90, 0x230, 35, V_PCICFG_CTRL_INTA },
+ { 0x90, 0x234, 36, V_PCICFG_CTRL_INTB },
+ { 0x90, 0x238, 37, V_PCICFG_CTRL_INTC },
+ { 0xD6, 0x208, 3, V_PCICFG_CTRL_INTA },
+ { 0xD6, 0x200, 39, V_PCICFG_CTRL_INTA },
+ { 0xD6, 0x20C, 38, V_PCICFG_CTRL_INTA },
+ { 0xD6, 0x204, 42, V_PCICFG_CTRL_INTA },
+ { 0x98, 0x200, 26, V_PCICFG_CTRL_INTA },
+ { 0xA4, 0x200, 13, V_PCICFG_CTRL_INTB },
+};
+
+/**
+ mDevIntConfig[] table contains data on INTx and IRQ for each device.
+
+
+ PCI Express Root Ports mapping should be programmed only with values as in below table (D19/20)
+ otherwise _PRT methods in ACPI for RootPorts would require additional patching as
+ PCIe Endpoint Device Interrupt is further subjected to INTx to PIRQy Mapping
+
+ Configured IRQ values are not used if an OS chooses to be in PIC instead of APIC mode
+**/
+GLOBAL_REMOVE_IF_UNREFERENCED SC_DEVICE_INTERRUPT_CONFIG mDevIntConfig[] = {
+ {19, 0, ScIntA, 16}, // PCI Express Port 3, INT is default, programmed in PciCfgSpace + FCh
+ {19, 1, ScIntB, 17}, // PCI Express Port 4, INT is default, programmed in PciCfgSpace + FCh
+ {19, 2, ScIntC, 18}, // PCI Express Port 5, INT is default, programmed in PciCfgSpace + FCh
+ {19, 3, ScIntD, 19}, // PCI Express Port 6, INT is default, programmed in PciCfgSpace + FCh
+ {20, 0, ScIntA, 16}, // PCI Express Port 1 (APL Only), INT is default, programmed in PciCfgSpace + FCh
+ {20, 1, ScIntB, 17}, // PCI Express Port 2 (APL Only), INT is default, programmed in PciCfgSpace + FCh
+};
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+
+**/
+VOID
+LoadScGeneralConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ SC_GENERAL_CONFIG *ScGeneralConfig;
+
+ ScGeneralConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "ScGeneralConfig->Header.Guid = %g\n", &ScGeneralConfig->Header.Guid));
+ DEBUG ((DEBUG_INFO, "ScGeneralConfig->Header.Size = 0x%x\n", ScGeneralConfig->Header.Size));
+
+ ScGeneralConfig->SubSystemVendorId = V_INTEL_VENDOR_ID;
+ ScGeneralConfig->SubSystemId = V_SC_DEFAULT_SID;
+
+ ScGeneralConfig->AcpiBase = (UINT16) PcdGet16 (PcdScAcpiIoPortBaseAddress);
+ ScGeneralConfig->PmcBase = (UINT32) PcdGet32 (PcdPmcGcrBaseAddress);
+ ScGeneralConfig->P2sbBase = (UINT32) PcdGet32 (PcdP2SBBaseAddress);
+}
+
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+
+**/
+VOID
+LoadSataConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ SC_SATA_CONFIG *SataConfig;
+ UINT8 PortIndex;
+
+ SataConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "SataConfig->Header.Guid = %g\n", &SataConfig->Header.Guid));
+ DEBUG ((DEBUG_INFO, "SataConfig->Header.Size = 0x%x\n", SataConfig->Header.Size));
+
+ SataConfig->Enable = TRUE;
+ SataConfig->SalpSupport = TRUE;
+ SataConfig->SataMode = ScSataModeAhci;
+ SataConfig->SpeedLimit = ScSataSpeedDefault;
+
+ for (PortIndex = 0; PortIndex < SC_MAX_SATA_PORTS; PortIndex++) {
+ SataConfig->PortSettings[PortIndex].Enable = TRUE;
+ SataConfig->PortSettings[PortIndex].DmVal = 15;
+ SataConfig->PortSettings[PortIndex].DitoVal = 625;
+ }
+}
+
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+
+**/
+VOID
+LoadPcieConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ SC_PCIE_CONFIG *PcieConfig;
+ UINT8 PortIndex;
+
+ PcieConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "PcieConfig->Header.Guid = %g\n", &PcieConfig->Header.Guid));
+ DEBUG ((DEBUG_INFO, "PcieConfig->Header.Size = 0x%x\n", PcieConfig->Header.Size));
+
+ for (PortIndex = 0; PortIndex < GetScMaxPciePortNum (); PortIndex++) {
+ PcieConfig->RootPort[PortIndex].Aspm = ScPcieAspmAutoConfig;
+ PcieConfig->RootPort[PortIndex].Enable = TRUE;
+ PcieConfig->RootPort[PortIndex].SlotImplemented = TRUE;
+ PcieConfig->RootPort[PortIndex].PmSci = TRUE;
+ PcieConfig->RootPort[PortIndex].AcsEnabled = TRUE;
+ PcieConfig->RootPort[PortIndex].PhysicalSlotNumber = PortIndex;
+ PcieConfig->RootPort[PortIndex].L1Substates = ScPcieL1SubstatesL1_1_2;
+ PcieConfig->RootPort[PortIndex].SelectableDeemphasis = TRUE;
+ //
+ // PCIe LTR Configuration.
+ //
+ PcieConfig->RootPort[PortIndex].LtrEnable = TRUE;
+ PcieConfig->RootPort[PortIndex].LtrMaxSnoopLatency = 0x1003;
+ PcieConfig->RootPort[PortIndex].LtrMaxNoSnoopLatency = 0x1003;
+ PcieConfig->RootPort[PortIndex].SnoopLatencyOverrideMode = 2;
+ PcieConfig->RootPort[PortIndex].SnoopLatencyOverrideMultiplier = 2;
+ PcieConfig->RootPort[PortIndex].SnoopLatencyOverrideValue = 60;
+ PcieConfig->RootPort[PortIndex].NonSnoopLatencyOverrideMode = 2;
+ PcieConfig->RootPort[PortIndex].NonSnoopLatencyOverrideMultiplier = 2;
+ PcieConfig->RootPort[PortIndex].NonSnoopLatencyOverrideValue = 60;
+ }
+ PcieConfig->AspmSwSmiNumber = SW_SMI_PCIE_ASPM_OVERRIDE;
+}
+
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+
+**/
+VOID
+LoadUsbConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ SC_USB_CONFIG *UsbConfig;
+ UINT32 PortIndex;
+
+ UsbConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "UsbConfig->Header.Guid = %g\n", &UsbConfig->Header.Guid));
+ DEBUG ((DEBUG_INFO, "UsbConfig->Header.Size = 0x%x\n", UsbConfig->Header.Size));
+
+ UsbConfig->Usb30Settings.Mode = XHCI_MODE_ON;
+ for (PortIndex = 0; PortIndex < GetScXhciMaxUsb2PortNum (); PortIndex++) {
+ UsbConfig->PortUsb20[PortIndex].Enable = TRUE;
+ }
+ for (PortIndex = 0; PortIndex < GetScXhciMaxUsb3PortNum (); PortIndex++) {
+ UsbConfig->PortUsb30[PortIndex].Enable = TRUE;
+ }
+ UsbConfig->XdciConfig.Enable = ScPciMode;
+ UsbConfig->SsicConfig.SsicPort[0].Enable = FALSE;
+ UsbConfig->SsicConfig.SsicPort[1].Enable = FALSE;
+ UsbConfig->SsicConfig.SsicPort[0].Rate = XhciSsicRateA;
+ UsbConfig->SsicConfig.SsicPort[1].Rate = XhciSsicRateA;
+ UsbConfig->SsicConfig.DlanePwrGating = TRUE;
+}
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+
+**/
+VOID
+LoadHpetConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ SC_HPET_CONFIG *HpetConfig;
+
+ HpetConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "HpetConfig->Header.Guid = %g\n", &HpetConfig->Header.Guid));
+ DEBUG ((DEBUG_INFO, "HpetConfig->Header.Size = 0x%x\n", HpetConfig->Header.Size));
+
+ HpetConfig->Enable = TRUE;
+ HpetConfig->Base = SC_HPET_BASE_ADDRESS;
+}
+
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+
+**/
+VOID
+LoadSmbusConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ SC_SMBUS_CONFIG *SmbusConfig;
+
+ SmbusConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "SmbusConfig->Header.Guid = %g\n", &SmbusConfig->Header.Guid));
+ DEBUG ((DEBUG_INFO, "SmbusConfig->Header.Size = 0x%x\n", SmbusConfig->Header.Size));
+
+ SmbusConfig->Enable = TRUE;
+ SmbusConfig->SmbusIoBase = PcdGet16(PcdSmbusBaseAddress);
+ ASSERT (sizeof (mSmbusRsvdAddresses) <= SC_MAX_SMBUS_RESERVED_ADDRESS);
+ SmbusConfig->NumRsvdSmbusAddresses = sizeof (mSmbusRsvdAddresses);
+ CopyMem (
+ SmbusConfig->RsvdSmbusAddressTable,
+ mSmbusRsvdAddresses,
+ sizeof (mSmbusRsvdAddresses)
+ );
+}
+
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+
+**/
+VOID
+LoadIoApicConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ SC_IOAPIC_CONFIG *IoApicConfig;
+
+ IoApicConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "IoApicConfig->Header.Guid = %g\n", &IoApicConfig->Header.Guid));
+ DEBUG ((DEBUG_INFO, "IoApicConfig->Header.Size = 0x%x\n", IoApicConfig->Header.Size));
+}
+
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+
+**/
+VOID
+LoadHdaConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ SC_HDAUDIO_CONFIG *HdaConfig;
+
+ HdaConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "HdaConfig->Header.Guid = %g\n", &HdaConfig->Header.Guid));
+ DEBUG ((DEBUG_INFO, "HdaConfig->Header.Size = 0x%x\n", HdaConfig->Header.Size));
+
+ HdaConfig->Enable = TRUE;
+ HdaConfig->DspEnable = TRUE;
+ HdaConfig->Mmt = ScHdaVc0;
+ HdaConfig->Hmt = ScHdaVc0;
+ HdaConfig->BiosCfgLockDown = TRUE;
+ HdaConfig->PwrGate = TRUE;
+ HdaConfig->ClkGate = TRUE;
+ HdaConfig->Pme = TRUE;
+ HdaConfig->IoBufferOwnership = ScHdaIoBufOwnerI2sPort;
+ HdaConfig->VcType = ScHdaVc0;
+ HdaConfig->HdAudioLinkFrequency = ScHdaLinkFreq24MHz;
+ HdaConfig->IDispLinkFrequency = ScHdaLinkFreq96MHz;
+ HdaConfig->IDispLinkTmode = ScHdaIDispMode2T;
+ HdaConfig->ResetWaitTimer = 300;
+ HdaConfig->RsvdBits3 = 0;
+}
+
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+
+**/
+VOID
+LoadGmmConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ SC_GMM_CONFIG *GmmConfig;
+
+ GmmConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "GmmConfig->Header.Guid = %g\n", &GmmConfig->Header.Guid));
+ DEBUG ((DEBUG_INFO, "GmmConfig->Header.Size = 0x%x\n", GmmConfig->Header.Size));
+
+ GmmConfig->ClkGatingPgcbClkTrunk = TRUE;
+ GmmConfig->ClkGatingSb = TRUE;
+ GmmConfig->ClkGatingSbClkTrunk = TRUE;
+ GmmConfig->ClkGatingSbClkPartition = TRUE;
+ GmmConfig->ClkGatingCore = TRUE;
+ GmmConfig->ClkGatingDma = TRUE;
+ GmmConfig->ClkGatingRegAccess = TRUE;
+ GmmConfig->ClkGatingHost = TRUE;
+ GmmConfig->ClkGatingPartition = TRUE;
+ GmmConfig->ClkGatingTrunk = TRUE;
+ GmmConfig->SvPwrGatingHwAutoEnable = TRUE;
+}
+
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+
+**/
+VOID
+LoadPmConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ SC_PM_CONFIG *PmConfig;
+
+ PmConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "PmConfig->Header.Guid = %g\n", &PmConfig->Header.Guid));
+ DEBUG ((DEBUG_INFO, "PmConfig->Header.Size = 0x%x\n", PmConfig->Header.Size));
+
+ PmConfig->PciClockRun = TRUE;
+ PmConfig->Timer8254ClkGateEn = TRUE;
+}
+
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+
+**/
+VOID
+LoadLockDownConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ SC_LOCK_DOWN_CONFIG *LockDownConfig;
+
+ LockDownConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "LockDownConfig->Header.Guid = %g\n", &LockDownConfig->Header.Guid));
+ DEBUG ((DEBUG_INFO, "LockDownConfig->Header.Size = 0x%x\n", LockDownConfig->Header.Size));
+
+ LockDownConfig->GlobalSmi = TRUE;
+ //
+ // Flash Security Recommendations,
+ // Intel strongly recommends that BIOS sets the BIOS Interface Lock Down bit. Enabling this bit
+ // will mitigate malicious software attempts to replace the system BIOS option ROM with its own code.
+ // Here we always enable this as a Policy.
+ //
+ LockDownConfig->BiosInterface = TRUE;
+ LockDownConfig->RtcLock = TRUE;
+ LockDownConfig->BiosLockSwSmiNumber = SW_SMI_BIOS_LOCK;
+}
+
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+
+**/
+VOID
+LoadSerialIrqConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ SC_LPC_SIRQ_CONFIG *SerialIrqConfig;
+
+ SerialIrqConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "SerialIrqConfig->Header.Guid = %g\n", &SerialIrqConfig->Header.Guid));
+ DEBUG ((DEBUG_INFO, "SerialIrqConfig->Header.Size = 0x%x\n", SerialIrqConfig->Header.Size));
+
+ SerialIrqConfig->SirqEnable = TRUE;
+ SerialIrqConfig->SirqMode = ScQuietMode;
+ SerialIrqConfig->StartFramePulse = ScSfpw4Clk;
+}
+
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+
+**/
+VOID
+LoadLpssConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ SC_LPSS_CONFIG *LpssConfig;
+ UINT8 Index;
+
+ LpssConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "LpssConfig->Header.Guid = %g\n", &LpssConfig->Header.Guid));
+ DEBUG ((DEBUG_INFO, "LpssConfig->Header.Size = 0x%x\n", LpssConfig->Header.Size));
+
+ LpssConfig->I2c0Enable = ScPciMode;
+ LpssConfig->I2c1Enable = ScPciMode;
+ LpssConfig->I2c2Enable = ScPciMode;
+ LpssConfig->I2c3Enable = ScPciMode;
+ LpssConfig->I2c4Enable = ScPciMode;
+ LpssConfig->I2c5Enable = ScPciMode;
+ LpssConfig->I2c6Enable = ScPciMode;
+ LpssConfig->I2c7Enable = ScPciMode;
+ LpssConfig->Hsuart0Enable = ScPciMode;
+ LpssConfig->Hsuart1Enable = ScPciMode;
+ LpssConfig->Hsuart2Enable = ScPciMode;
+ LpssConfig->Hsuart3Enable = ScPciMode;
+ LpssConfig->Spi0Enable = ScPciMode;
+ LpssConfig->Spi1Enable = ScPciMode;
+ LpssConfig->Spi2Enable = ScPciMode;
+
+ for (Index = 0; Index < LPSS_I2C_DEVICE_NUM; Index++) {
+ LpssConfig->I2cClkGateCfg[Index] = TRUE;
+ }
+
+ for (Index = 0; Index < LPSS_HSUART_DEVICE_NUM; Index++) {
+ LpssConfig->HsuartClkGateCfg[Index] = TRUE;
+ }
+
+ for (Index = 0; Index < LPSS_SPI_DEVICE_NUM; Index++) {
+ LpssConfig->SpiClkGateCfg[Index] = TRUE;
+ }
+}
+
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+
+**/
+VOID
+LoadScsConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ SC_SCS_CONFIG *ScsConfig;
+
+ ScsConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "ScsConfig->Header.Guid = %g\n", &ScsConfig->Header.Guid));
+ DEBUG ((DEBUG_INFO, "ScsConfig->Header.Size = 0x%x\n", ScsConfig->Header.Size));
+
+ ScsConfig->SdcardEnable = ScPciMode;
+ ScsConfig->SdioEnable = ScPciMode;
+ ScsConfig->EmmcEnable = ScPciMode;
+ ScsConfig->EmmcHostMaxSpeed = SccEmmcHs400;
+ ScsConfig->GppLock = 0;
+ ScsConfig->SccEmmcTraceLength = SCC_EMMC_LONG_TRACE_LEN;
+ ScsConfig->SdioRegDllConfig.TxCmdCntl = 0x505;
+ ScsConfig->SdioRegDllConfig.TxDataCntl1 = 0xE;
+ ScsConfig->SdioRegDllConfig.TxDataCntl2 = 0x22272828;
+ ScsConfig->SdioRegDllConfig.RxCmdDataCntl1 = 0x16161616;
+ ScsConfig->SdioRegDllConfig.RxCmdDataCntl2 = 0x10000;
+ ScsConfig->SdcardRegDllConfig.TxCmdCntl = 0x505;
+ if (GetBxtSeries () == Bxt) {
+ ScsConfig->SdcardRegDllConfig.TxDataCntl1 = 0xA12;
+ ScsConfig->SdcardRegDllConfig.TxDataCntl2 = 0x26272727;
+ ScsConfig->SdcardRegDllConfig.RxCmdDataCntl1 = 0x0B483B3B;
+ } else {
+ ScsConfig->SdcardRegDllConfig.TxDataCntl1 = 0xA13;
+ ScsConfig->SdcardRegDllConfig.TxDataCntl2 = 0x24242828;
+ ScsConfig->SdcardRegDllConfig.RxCmdDataCntl1 = 0x73A3637;
+ }
+ ScsConfig->SdcardRegDllConfig.RxStrobeCntl = 0x0;
+ ScsConfig->SdcardRegDllConfig.RxCmdDataCntl2 = 0x10000;
+
+ if (ScsConfig->SccEmmcTraceLength == SCC_EMMC_SHORT_TRACE_LEN) {
+ //
+ // Configure DLL settings for short trace length
+ //
+ ScsConfig->EmmcRegDllConfig.TxCmdCntl = 0x505;
+ ScsConfig->EmmcRegDllConfig.TxDataCntl1 = 0xC15;
+ ScsConfig->EmmcRegDllConfig.TxDataCntl2 = 0x1C1C1C00;
+ ScsConfig->EmmcRegDllConfig.RxCmdDataCntl1 = 0x1C1C1C00;
+ ScsConfig->EmmcRegDllConfig.RxStrobeCntl = 0x0a0a;
+ ScsConfig->EmmcRegDllConfig.RxCmdDataCntl2 = 0x1001C;
+ ScsConfig->EmmcRegDllConfig.MasterSwCntl = 0x001;
+ } else {
+ //
+ // Configure DLL settings for long trace length
+ //
+ ScsConfig->EmmcRegDllConfig.TxCmdCntl = 0x505;
+ ScsConfig->EmmcRegDllConfig.TxDataCntl1 = 0xC11;
+ ScsConfig->EmmcRegDllConfig.TxDataCntl2 = 0x1C2A2927;
+ ScsConfig->EmmcRegDllConfig.RxCmdDataCntl1 = 0x000D162F;
+ ScsConfig->EmmcRegDllConfig.RxStrobeCntl = 0x0a0a;
+ ScsConfig->EmmcRegDllConfig.RxCmdDataCntl2 = 0x1003b;
+ ScsConfig->EmmcRegDllConfig.MasterSwCntl = 0x001;
+ }
+}
+
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+
+**/
+VOID
+LoadVtdConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ SC_VTD_CONFIG *VtdConfig;
+
+ VtdConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "VtdConfig->Header.Guid = %g\n", &VtdConfig->Header.Guid));
+ DEBUG ((DEBUG_INFO, "VtdConfig->Header.Size = 0x%x\n", VtdConfig->Header.Size));
+
+ VtdConfig->RmrrUsbBaseAddr = 0;
+ VtdConfig->RmrrUsbLimit = 0;
+}
+
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+
+**/
+VOID
+LoadIshConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ SC_ISH_CONFIG *IshConfig;
+
+ IshConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "IshConfig->Header.Guid = %g\n", &IshConfig->Header.Guid));
+ DEBUG ((DEBUG_INFO, "IshConfig->Header.Size = 0x%x\n", IshConfig->Header.Size));
+
+ IshConfig->Enable = TRUE;
+}
+
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+
+**/
+VOID
+LoadFlashProtectionConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ SC_FLASH_PROTECTION_CONFIG *FlashProtectionConfig;
+
+ FlashProtectionConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "FlashProtectionConfig->Header.Guid = %g\n", &FlashProtectionConfig->Header.Guid));
+ DEBUG ((DEBUG_INFO, "FlashProtectionConfig->Header.Size = 0x%x\n", FlashProtectionConfig->Header.Size));
+}
+
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+
+**/
+VOID
+LoadDciConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ SC_DCI_CONFIG *DciConfig;
+
+ DciConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "DciConfig->Header.Guid = %g\n", &DciConfig->Header.Guid));
+ DEBUG ((DEBUG_INFO, "DciConfig->Header.Size = 0x%x\n", DciConfig->Header.Size));
+
+ DciConfig->DciAutoDetect = TRUE;
+}
+
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+
+**/
+VOID
+LoadP2sbConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ SC_P2SB_CONFIG *P2sbConfig;
+
+ P2sbConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "P2sbConfig->Header.Guid = %g\n", &P2sbConfig->Header.Guid));
+ DEBUG ((DEBUG_INFO, "P2sbConfig->Header.Size = 0x%x\n", P2sbConfig->Header.Size));
+
+ P2sbConfig->P2sbUnhide = 0;
+}
+
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+
+**/
+VOID
+LoadInterruptConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ UINT8 IntConfigTableEntries;
+ UINT8 DirectIrqTableEntries;
+ SC_INTERRUPT_CONFIG *InterruptConfig;
+
+ InterruptConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "InterruptConfig->Header.Guid = %g\n", &InterruptConfig->Header.Guid));
+ DEBUG ((DEBUG_INFO, "InterruptConfig->Header.Size = 0x%x\n", InterruptConfig->Header.Size));
+
+ DirectIrqTableEntries = sizeof (mDirectIrqTable) / sizeof (PRIVATE_PCICFGCTRL);
+ ASSERT (DirectIrqTableEntries <= SC_MAX_DIRECT_IRQ_CONFIG);
+ InterruptConfig->NumOfDirectIrqTable = DirectIrqTableEntries;
+ CopyMem (
+ InterruptConfig->DirectIrqTable,
+ mDirectIrqTable,
+ sizeof (mDirectIrqTable)
+ );
+
+ IntConfigTableEntries = sizeof (mDevIntConfig) / sizeof (SC_DEVICE_INTERRUPT_CONFIG);
+ ASSERT (IntConfigTableEntries <= SC_MAX_DEVICE_INTERRUPT_CONFIG);
+ InterruptConfig->NumOfDevIntConfig = IntConfigTableEntries;
+ CopyMem (
+ InterruptConfig->DevIntConfig,
+ mDevIntConfig,
+ sizeof (mDevIntConfig)
+ );
+
+ InterruptConfig->PxRcRouting[0] = V_ITSS_SB_REN_ENABLE + V_ITSS_SB_IR_IRQ3; // R_ITSS_SB_PARC PIRQA->IRQx Routing Control
+ InterruptConfig->PxRcRouting[1] = V_ITSS_SB_REN_ENABLE + V_ITSS_SB_IR_IRQ4; // R_ITSS_SB_PBRC PIRQB->IRQx Routing Control
+ InterruptConfig->PxRcRouting[2] = V_ITSS_SB_REN_ENABLE + V_ITSS_SB_IR_IRQ5; // R_ITSS_SB_PCRC PIRQC->IRQx Routing Control
+ InterruptConfig->PxRcRouting[3] = V_ITSS_SB_REN_ENABLE + V_ITSS_SB_IR_IRQ6; // R_ITSS_SB_PDRC PIRQD->IRQx Routing Control
+ InterruptConfig->PxRcRouting[4] = V_ITSS_SB_REN_ENABLE + V_ITSS_SB_IR_IRQ7; // R_ITSS_SB_PERC PIRQE->IRQx Routing Control
+ InterruptConfig->PxRcRouting[5] = V_ITSS_SB_REN_ENABLE + V_ITSS_SB_IR_IRQ9; // R_ITSS_SB_PFRC PIRQF->IRQx Routing Control
+ InterruptConfig->PxRcRouting[6] = V_ITSS_SB_REN_ENABLE + V_ITSS_SB_IR_IRQ10; // R_ITSS_SB_PGRC PIRQG->IRQx Routing Control
+ InterruptConfig->PxRcRouting[7] = V_ITSS_SB_REN_ENABLE + V_ITSS_SB_IR_IRQ11; // R_ITSS_SB_PHRC PIRQH->IRQx Routing Control
+}
+
+static IP_BLOCK_ENTRY mScIpBlocks [] = {
+ {&gScGeneralConfigGuid, sizeof (SC_GENERAL_CONFIG), SC_GENERAL_CONFIG_REVISION, LoadScGeneralConfigDefault},
+ {&gSataConfigGuid, sizeof (SC_SATA_CONFIG), SATA_CONFIG_REVISION, LoadSataConfigDefault},
+ {&gPcieRpConfigGuid, sizeof (SC_PCIE_CONFIG), PCIE_RP_CONFIG_REVISION, LoadPcieConfigDefault},
+ {&gUsbConfigGuid, sizeof (SC_USB_CONFIG), USB_CONFIG_REVISION, LoadUsbConfigDefault},
+ {&gHpetConfigGuid, sizeof (SC_HPET_CONFIG), HPET_CONFIG_REVISION, LoadHpetConfigDefault},
+ {&gSmbusConfigGuid, sizeof (SC_SMBUS_CONFIG), SMBUS_CONFIG_REVISION, LoadSmbusConfigDefault},
+ {&gIoApicConfigGuid, sizeof (SC_IOAPIC_CONFIG), IOAPIC_CONFIG_REVISION, LoadIoApicConfigDefault},
+ {&gHdAudioConfigGuid, sizeof (SC_HDAUDIO_CONFIG), HDAUDIO_CONFIG_REVISION, LoadHdaConfigDefault},
+ {&gGmmConfigGuid, sizeof (SC_GMM_CONFIG), GMM_CONFIG_REVISION, LoadGmmConfigDefault},
+ {&gPmConfigGuid, sizeof (SC_PM_CONFIG), PM_CONFIG_REVISION, LoadPmConfigDefault},
+ {&gLockDownConfigGuid, sizeof (SC_LOCK_DOWN_CONFIG), LOCK_DOWN_CONFIG_REVISION, LoadLockDownConfigDefault},
+ {&gSerialIrqConfigGuid, sizeof (SC_LPC_SIRQ_CONFIG), SERIAL_IRQ_CONFIG_REVISION, LoadSerialIrqConfigDefault},
+ {&gLpssConfigGuid, sizeof (SC_LPSS_CONFIG), LPSS_CONFIG_REVISION, LoadLpssConfigDefault},
+ {&gScsConfigGuid, sizeof (SC_SCS_CONFIG), SCS_CONFIG_REVISION, LoadScsConfigDefault},
+ {&gVtdConfigGuid, sizeof (SC_VTD_CONFIG), VTD_CONFIG_REVISION, LoadVtdConfigDefault},
+ {&gIshConfigGuid, sizeof (SC_ISH_CONFIG), ISH_CONFIG_REVISION, LoadIshConfigDefault},
+ {&gFlashProtectionConfigGuid, sizeof (SC_FLASH_PROTECTION_CONFIG), FLASH_PROTECTION_CONFIG_REVISION, LoadFlashProtectionConfigDefault},
+ {&gDciConfigGuid, sizeof (SC_DCI_CONFIG), DCI_CONFIG_REVISION, LoadDciConfigDefault},
+ {&gP2sbConfigGuid, sizeof (SC_P2SB_CONFIG), P2SB_CONFIG_REVISION, LoadP2sbConfigDefault},
+ {&gInterruptConfigGuid, sizeof (SC_INTERRUPT_CONFIG), INTERRUPT_CONFIG_REVISION, LoadInterruptConfigDefault},
+};
+
+
+/**
+ Get SC config block table total size.
+
+ @retval Size of SC config block table
+
+**/
+UINT32
+EFIAPI
+ScGetConfigBlockTotalSize (
+ VOID
+ )
+{
+ UINT32 TotalBlockCount;
+ UINT32 TotalBlockSize;
+ UINT32 ConfigBlockHdrSize;
+ UINT32 BlockCount;
+
+ TotalBlockCount = sizeof (mScIpBlocks) / sizeof (IP_BLOCK_ENTRY);
+ TotalBlockSize = 0;
+ for (BlockCount = 0 ; BlockCount < TotalBlockCount; BlockCount++) {
+ TotalBlockSize += (UINT32)mScIpBlocks[BlockCount].Size;
+ DEBUG ((DEBUG_INFO, "TotalBlockSize after adding Block[0x%x]= 0x%x\n", BlockCount, TotalBlockSize));
+ }
+ ConfigBlockHdrSize = GetSizeOfConfigBlockTableHeaders ((UINT16) TotalBlockCount);
+
+ //
+ // Because CreateConfigBlockTable has the padding for each config block,
+ // we need extra size, which is TotalBlockCount * 3, to create the table
+ //
+ return ConfigBlockHdrSize + TotalBlockSize + (TotalBlockCount * 3);
+}
+
+
+/**
+ CreateConfigBlocks generates the config blocks of SC Policy.
+ It allocates and zero out buffer, and fills in the Intel default settings.
+
+ @param[out] ScPolicyPpi The pointer to get SC Policy PPI instance
+
+ @retval EFI_SUCCESS The policy default is initialized.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create buffer
+
+**/
+EFI_STATUS
+EFIAPI
+ScCreateConfigBlocks (
+ OUT SC_POLICY_PPI **ScPolicyPpi
+ )
+{
+ UINT16 TotalBlockCount;
+ UINT16 BlockCount;
+ VOID *ConfigBlockPointer;
+ CONFIG_BLOCK ConfigBlockBuf;
+ EFI_STATUS Status;
+ SC_POLICY_PPI *InitPolicy;
+ UINT32 RequiredSize;
+
+ DEBUG ((DEBUG_INFO, "SC CreateConfigBlocks\n"));
+
+ InitPolicy = NULL;
+ TotalBlockCount = sizeof (mScIpBlocks) / sizeof (IP_BLOCK_ENTRY);
+ DEBUG ((DEBUG_INFO, "TotalBlockCount = 0x%x\n", TotalBlockCount));
+
+ RequiredSize = ScGetConfigBlockTotalSize ();
+
+ Status = CreateConfigBlockTable ((VOID *) &InitPolicy, TotalBlockCount, RequiredSize);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Initialize Policy Revision
+ //
+ InitPolicy->TableHeader.Header.Revision = SC_POLICY_REVISION;
+ //
+ // Initialize ConfigBlockPointer to NULL
+ //
+ ConfigBlockPointer = NULL;
+ //
+ // Loop to identify each config block from mScIpBlocks[] Table and add each of them
+ //
+ for (BlockCount = 0 ; BlockCount < TotalBlockCount; BlockCount++) {
+ CopyMem (&(ConfigBlockBuf.Header.Guid), mScIpBlocks[BlockCount].Guid, sizeof (EFI_GUID));
+ ConfigBlockBuf.Header.Size = mScIpBlocks[BlockCount].Size;
+ ConfigBlockBuf.Header.Revision = mScIpBlocks[BlockCount].Revision;
+ ConfigBlockPointer = (VOID *) &ConfigBlockBuf;
+ Status = AddConfigBlock ((VOID *) InitPolicy, (VOID *) &ConfigBlockPointer);
+ ASSERT_EFI_ERROR (Status);
+ mScIpBlocks[BlockCount].LoadDefault (ConfigBlockPointer);
+ }
+ //
+ // Assignment for returning Policy config block base address
+ //
+ *ScPolicyPpi = InitPolicy;
+ return EFI_SUCCESS;
+}
+
+
+/**
+ ScInstallPolicyPpi installs ScPolicyPpi.
+ While installed, RC assumes the Policy is ready and finalized. So please update and override
+ any setting before calling this function.
+
+ @param[in] ScPolicyPpi The pointer to SC Policy PPI instance
+
+ @retval EFI_SUCCESS The policy is installed.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create buffer
+
+**/
+EFI_STATUS
+EFIAPI
+ScInstallPolicyPpi (
+ IN SC_POLICY_PPI *ScPolicyPpi
+ )
+{
+ EFI_STATUS Status;
+ EFI_PEI_PPI_DESCRIPTOR *ScPolicyPpiDesc;
+
+ ScPolicyPpiDesc = (EFI_PEI_PPI_DESCRIPTOR *) AllocateZeroPool (sizeof (EFI_PEI_PPI_DESCRIPTOR));
+ if (ScPolicyPpiDesc == NULL) {
+ ASSERT (FALSE);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ ScPolicyPpiDesc->Flags = EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST;
+ ScPolicyPpiDesc->Guid = &gScPolicyPpiGuid;
+ ScPolicyPpiDesc->Ppi = ScPolicyPpi;
+
+ //
+ // Print whole SC_POLICY_PPI and serial out.
+ //
+ ScPrintPolicyPpi (ScPolicyPpi);
+
+ //
+ // Install SC Policy PPI
+ //
+ Status = PeiServicesInstallPpi (ScPolicyPpiDesc);
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/PeiScPolicyLib/PeiScPolicyLib.inf b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/PeiScPolicyLib/PeiScPolicyLib.inf
new file mode 100644
index 0000000000..a81fe726a2
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/PeiScPolicyLib/PeiScPolicyLib.inf
@@ -0,0 +1,77 @@
+## @file
+# Library for the PeiScPolicy.
+#
+# Copyright (c) 2014 - 2016, 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 = PeiScPolicyLib
+ FILE_GUID = BB1AC992-B2CA-4744-84B7-915C185576C5
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PeiScPolicyLib
+
+[Sources]
+ PeiScPolicyLib.c
+ PeiScPreMemPolicyLib.c
+ PeiScPolicyLibrary.h
+ ScPrintPolicy.c
+ ScPrintPolicyPreMem.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ BroxtonSiPkg/BroxtonSiPkg.dec
+
+[LibraryClasses]
+ DebugLib
+ IoLib
+ PeiServicesLib
+ BaseMemoryLib
+ MemoryAllocationLib
+ ScPlatformLib
+ ConfigBlockLib
+ PcdLib
+
+[Guids]
+ gLpcPreMemConfigGuid ## CONSUMES
+ gPcieRpPreMemConfigGuid ## CONSUMES
+ gScGeneralConfigGuid ## CONSUMES
+ gPcieRpConfigGuid ## CONSUMES
+ gSataConfigGuid ## CONSUMES
+ gHpetConfigGuid
+ gSmbusConfigGuid
+ gUsbConfigGuid
+ gIoApicConfigGuid
+ gHdAudioConfigGuid
+ gGmmConfigGuid
+ gPmConfigGuid
+ gLockDownConfigGuid
+ gSerialIrqConfigGuid
+ gLpssConfigGuid
+ gScsConfigGuid
+ gVtdConfigGuid
+ gIshConfigGuid
+ gFlashProtectionConfigGuid
+ gDciConfigGuid
+ gP2sbConfigGuid
+ gInterruptConfigGuid
+
+[Ppis]
+ gScPolicyPpiGuid ## PRODUCES
+ gScPreMemPolicyPpiGuid ## PRODUCES
+
+[Pcd]
+ gSiPkgTokenSpaceGuid.PcdSmbusBaseAddress
+ gEfiBxtTokenSpaceGuid.PcdScAcpiIoPortBaseAddress
+ gEfiBxtTokenSpaceGuid.PcdP2SBBaseAddress
+ gEfiBxtTokenSpaceGuid.PcdPmcGcrBaseAddress
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/PeiScPolicyLib/PeiScPolicyLibrary.h b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/PeiScPolicyLib/PeiScPolicyLibrary.h
new file mode 100644
index 0000000000..2802528e28
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/PeiScPolicyLib/PeiScPolicyLibrary.h
@@ -0,0 +1,51 @@
+/** @file
+ Header file for the PeiScPolicy library.
+
+ Copyright (c) 2014 - 2016, 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.
+
+**/
+
+#ifndef _PEI_SC_POLICY_LIB_H_
+#define _PEI_SC_POLICY_LIB_H_
+
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PeiScPolicyLib.h>
+#include <Library/ScPlatformLib.h>
+#include <Ppi/ScPolicy.h>
+#include <ScAccess.h>
+#include <SaAccess.h>
+#include <Library/SideBandLib.h>
+#include <ConfigBlock.h>
+#include <Library/ConfigBlockLib.h>
+
+#define SC_SMBUS_BASE_ADDRESS 0xEFA0
+#define SC_HPET_BASE_ADDRESS 0xFED00000
+#define SW_SMI_BIOS_LOCK 0xA9
+
+typedef
+VOID
+(*LOAD_DEFAULT_FUNCTION) (
+ IN VOID *ConfigBlockPointer
+ );
+
+typedef struct {
+ EFI_GUID *Guid;
+ UINT16 Size;
+ UINT8 Revision;
+ LOAD_DEFAULT_FUNCTION LoadDefault;
+} IP_BLOCK_ENTRY;
+
+#endif // _PEI_SC_POLICY_LIB_H_
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/PeiScPolicyLib/PeiScPreMemPolicyLib.c b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/PeiScPolicyLib/PeiScPreMemPolicyLib.c
new file mode 100644
index 0000000000..8566a4f70f
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/PeiScPolicyLib/PeiScPreMemPolicyLib.c
@@ -0,0 +1,201 @@
+/** @file
+ This file is PeiScPreMemPolicy library.
+
+ Copyright (c) 2016, 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.
+
+**/
+
+#include "PeiScPolicyLibrary.h"
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+
+**/
+VOID
+LoadLpcPreMemConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ SC_LPC_PREMEM_CONFIG *LpcPreMemConfig;
+
+ LpcPreMemConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "LpcPreMemConfig->Header.Guid = %g\n", &LpcPreMemConfig->Header.Guid));
+ DEBUG ((DEBUG_INFO, "LpcPreMemConfig->Header.Size = 0x%x\n", LpcPreMemConfig->Header.Size));
+
+ LpcPreMemConfig->EnhancePort8xhDecoding = TRUE;
+}
+
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+
+**/
+VOID
+LoadPciePreMemConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ SC_PCIE_PREMEM_CONFIG *PciePreMemConfig;
+ PciePreMemConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "PciePreMemConfig->Header.Guid = %g\n", &PciePreMemConfig->Header.Guid));
+ DEBUG ((DEBUG_INFO, "PciePreMemConfig->Header.Size = 0x%x\n", PciePreMemConfig->Header.Size));
+}
+
+static IP_BLOCK_ENTRY mScIpBlocks [] = {
+ {&gPcieRpPreMemConfigGuid, sizeof (SC_PCIE_PREMEM_CONFIG), PCIE_RP_PREMEM_CONFIG_REVISION, LoadPciePreMemConfigDefault},
+ {&gLpcPreMemConfigGuid, sizeof (SC_LPC_PREMEM_CONFIG), LPC_PREMEM_CONFIG_REVISION, LoadLpcPreMemConfigDefault},
+};
+
+/**
+ Get SC PREMEM config block table total size.
+
+ @retval Size of SC PREMEM config block table
+
+**/
+UINT32
+EFIAPI
+ScGetPreMemConfigBlockTotalSize (
+ VOID
+ )
+{
+ UINT32 TotalBlockCount;
+ UINT32 TotalBlockSize;
+ UINT32 ConfigBlockHdrSize;
+ UINT32 BlockCount;
+
+ TotalBlockCount = sizeof (mScIpBlocks) / sizeof (IP_BLOCK_ENTRY);
+ TotalBlockSize = 0;
+ for (BlockCount = 0 ; BlockCount < TotalBlockCount; BlockCount++) {
+ TotalBlockSize += (UINT32) mScIpBlocks[BlockCount].Size;
+ DEBUG ((DEBUG_INFO, "TotalBlockSize after adding Block[0x%x]= 0x%x\n", BlockCount, TotalBlockSize));
+ }
+ ConfigBlockHdrSize = GetSizeOfConfigBlockTableHeaders ((UINT16) TotalBlockCount);
+
+ //
+ // Because CreateConfigBlockTable has the padding for each config block,
+ // we need extra size, which is TotalBlockCount * 3, to create the table
+ //
+ return ConfigBlockHdrSize + TotalBlockSize + (TotalBlockCount * 3);
+}
+
+
+/**
+ CreatePreMemConfigBlocks generates the config blocks of SC Policy.
+ It allocates and zero out buffer, and fills in the Intel default settings.
+
+ @param[out] ScPreMemPolicyPpi The pointer to get SC PREMEM Policy PPI instance
+
+ @retval EFI_SUCCESS The policy default is initialized.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create buffer
+
+**/
+EFI_STATUS
+EFIAPI
+ScCreatePreMemConfigBlocks (
+ OUT SC_PREMEM_POLICY_PPI **ScPreMemPolicyPpi
+ )
+{
+ UINT16 TotalBlockCount;
+ UINT16 BlockCount;
+ VOID *ConfigBlockPointer;
+ CONFIG_BLOCK ConfigBlockBuf;
+ EFI_STATUS Status;
+ SC_PREMEM_POLICY_PPI *InitPolicy;
+ UINT32 RequiredSize;
+
+ DEBUG ((DEBUG_INFO, "SC CreateConfigBlocks\n"));
+
+ InitPolicy = NULL;
+ TotalBlockCount = sizeof (mScIpBlocks) / sizeof (IP_BLOCK_ENTRY);
+ DEBUG ((DEBUG_INFO, "TotalBlockCount = 0x%x\n", TotalBlockCount));
+
+ RequiredSize = ScGetPreMemConfigBlockTotalSize ();
+
+ Status = CreateConfigBlockTable ((VOID *) &InitPolicy, TotalBlockCount, RequiredSize);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Initialize Policy Revision
+ //
+ InitPolicy->TableHeader.Header.Revision = SC_PREMEM_POLICY_REVISION;
+ //
+ // Initialize ConfigBlockPointer to NULL
+ //
+ ConfigBlockPointer = NULL;
+ //
+ // Loop to identify each config block from mScIpBlocks[] Table and add each of them
+ //
+ for (BlockCount = 0 ; BlockCount < TotalBlockCount; BlockCount++) {
+ CopyMem (&(ConfigBlockBuf.Header.Guid), mScIpBlocks[BlockCount].Guid, sizeof (EFI_GUID));
+ ConfigBlockBuf.Header.Size = mScIpBlocks[BlockCount].Size;
+ ConfigBlockBuf.Header.Revision = mScIpBlocks[BlockCount].Revision;
+ ConfigBlockPointer = (VOID *) &ConfigBlockBuf;
+ Status = AddConfigBlock ((VOID *) InitPolicy, (VOID *) &ConfigBlockPointer);
+ ASSERT_EFI_ERROR (Status);
+ mScIpBlocks[BlockCount].LoadDefault (ConfigBlockPointer);
+ }
+ //
+ // Assignment for returning Policy config block base address
+ //
+ *ScPreMemPolicyPpi = InitPolicy;
+ return EFI_SUCCESS;
+}
+
+
+/**
+ ScInstallPreMemPolicyPpi installs PchPolicyPpi.
+ While installed, RC assumes the Policy is ready and finalized. So please update and override
+ any setting before calling this function.
+
+ @param[in] ScPreMemPolicyPpi The pointer to SC PREMEM Policy PPI instance
+
+ @retval EFI_SUCCESS The policy is installed.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create buffer
+
+**/
+EFI_STATUS
+EFIAPI
+ScInstallPreMemPolicyPpi (
+ IN SC_PREMEM_POLICY_PPI *ScPreMemPolicyPpi
+ )
+{
+ EFI_STATUS Status;
+ EFI_PEI_PPI_DESCRIPTOR *ScPreMemPolicyPpiDesc;
+
+ ScPreMemPolicyPpiDesc = (EFI_PEI_PPI_DESCRIPTOR *) AllocateZeroPool (sizeof (EFI_PEI_PPI_DESCRIPTOR));
+ if (ScPreMemPolicyPpiDesc == NULL) {
+ ASSERT (FALSE);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ ScPreMemPolicyPpiDesc->Flags = EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST;
+ ScPreMemPolicyPpiDesc->Guid = &gScPreMemPolicyPpiGuid;
+ ScPreMemPolicyPpiDesc->Ppi = ScPreMemPolicyPpi;
+
+ //
+ // Print whole SC_PREMEM_POLICY_PPI and serial out.
+ //
+ ScPreMemPrintPolicyPpi (ScPreMemPolicyPpi);
+
+ //
+ // Install PREMEM Policy PPI
+ //
+ Status = PeiServicesInstallPpi (ScPreMemPolicyPpiDesc);
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/PeiScPolicyLib/ScPrintPolicy.c b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/PeiScPolicyLib/ScPrintPolicy.c
new file mode 100644
index 0000000000..7ccf1d2495
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/PeiScPolicyLib/ScPrintPolicy.c
@@ -0,0 +1,699 @@
+/** @file
+ Print whole SC_POLICY_PPI and serial out.
+
+ Copyright (c) 2014 - 2016, 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.
+
+**/
+
+#include "PeiScPolicyLibrary.h"
+
+/**
+ Print SC_INTERRUPT_CONFIG and serial out
+
+ @param[in] InterruptConfig Pointer to Interrupt Configuration structure
+
+**/
+VOID
+PrintInterruptConfig (
+ IN CONST SC_INTERRUPT_CONFIG *InterruptConfig
+ )
+{
+ UINTN Index;
+ //
+ // Print interrupt information
+ //
+ DEBUG ((DEBUG_INFO, "------------------ Interrupt Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, " Interrupt assignment:\n"));
+ DEBUG ((DEBUG_INFO, " Dxx:Fx INTx IRQ\n"));
+ for (Index = 0; Index < InterruptConfig->NumOfDevIntConfig; Index++) {
+ DEBUG ((DEBUG_INFO, " D%02d:F%d %d %03d\n",
+ InterruptConfig->DevIntConfig[Index].Device,
+ InterruptConfig->DevIntConfig[Index].Function,
+ InterruptConfig->DevIntConfig[Index].IntX,
+ InterruptConfig->DevIntConfig[Index].Irq));
+ }
+ DEBUG ((DEBUG_INFO, " Direct Irq Table:\n"));
+ for (Index = 0; Index < InterruptConfig->NumOfDirectIrqTable; Index++) {
+ DEBUG ((DEBUG_INFO, " D%02d:F%d %d %03d\n",
+ InterruptConfig->DirectIrqTable[Index].Port,
+ InterruptConfig->DirectIrqTable[Index].PciCfgOffset,
+ InterruptConfig->DirectIrqTable[Index].PciIrqNumber,
+ InterruptConfig->DirectIrqTable[Index].IrqPin));
+ }
+
+ DEBUG ((DEBUG_INFO, " Legacy Interrupt Routing:\n"));
+ for (Index = 0; Index < SC_MAX_PXRC_CONFIG; Index++) {
+ DEBUG ((DEBUG_INFO, "PxRcRouting[%x] = %x \n", Index ,InterruptConfig->PxRcRouting[Index]));
+ }
+}
+
+
+/**
+ Print SC_USB_CONFIG and serial out.
+
+ @param[in] UsbConfig Pointer to a SC_USB_CONFIG that provides the platform setting
+
+**/
+
+VOID
+PrintUsbConfig (
+ IN CONST SC_USB_CONFIG *UsbConfig
+ )
+{
+ UINT32 Index;
+
+ DEBUG ((DEBUG_INFO, "------------------ USB Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, " DisableComplianceMode= %x\n", UsbConfig->DisableComplianceMode));
+ DEBUG ((DEBUG_INFO, " UsbPerPortCtl = %x\n", UsbConfig->UsbPerPortCtl));
+ DEBUG ((DEBUG_INFO, " Mode = %x\n", UsbConfig->Usb30Settings.Mode));
+
+ for (Index = 0; Index < GetScXhciMaxUsb2PortNum (); Index++) {
+ DEBUG ((DEBUG_INFO, " PortUsb20[%d].Enabled= %x\n", Index, UsbConfig->PortUsb20[Index].Enable));
+ DEBUG ((DEBUG_INFO, " PortUsb20[%d].OverCurrentPin= OC%x\n", Index, UsbConfig->PortUsb20[Index].OverCurrentPin));
+ }
+ for (Index = 0; Index < GetScXhciMaxUsb3PortNum (); Index++) {
+ DEBUG ((DEBUG_INFO, " PortUsb30[%d] Enabled= %x\n", Index, UsbConfig->PortUsb30[Index].Enable));
+ DEBUG ((DEBUG_INFO, " PortUsb30[%d].OverCurrentPin= OC%x\n", Index, UsbConfig->PortUsb30[Index].OverCurrentPin));
+ }
+ DEBUG ((DEBUG_INFO, " xDCI Enable = %x\n", UsbConfig->XdciConfig.Enable));
+
+ for (Index = 0; Index < XHCI_MAX_HSIC_PORTS; Index++) {
+ DEBUG ((DEBUG_INFO, " HsicPort[%d].Enable = %x\n", Index, UsbConfig->HsicConfig.HsicPort[Index].Enable));
+ }
+ for (Index = 0; Index < XHCI_MAX_SSIC_PORTS; Index++) {
+ DEBUG ((DEBUG_INFO, " SsicPort[%d].Enable = %x\n", Index, UsbConfig->SsicConfig.SsicPort[Index].Enable));
+ DEBUG ((DEBUG_INFO, " SsicPort[%d].Rate = %x\n", Index, UsbConfig->SsicConfig.SsicPort[Index].Rate));
+ }
+ DEBUG ((DEBUG_INFO, " SSIC DlanePwrGating = %x\n", UsbConfig->SsicConfig.DlanePwrGating));
+
+ return;
+}
+
+
+/**
+ Print SC_PCIE_CONFIG and serial out.
+
+ @param[in] PcieConfig Pointer to a SC_PCIE_CONFIG that provides the platform setting
+
+**/
+VOID
+PrintPcieConfig (
+ IN CONST SC_PCIE_CONFIG *PcieConfig
+ )
+{
+ UINT32 i;
+
+ DEBUG ((DEBUG_INFO, "------------------ PCIe Config ------------------\n"));
+ for (i = 0; i < GetScMaxPciePortNum (); i++) {
+ DEBUG ((DEBUG_INFO, " RootPort[%d] Enabled = %x\n", i, PcieConfig->RootPort[i].Enable));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] Hide = %x\n", i, PcieConfig->RootPort[i].Hide));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] SlotImplemented = %x\n", i, PcieConfig->RootPort[i].SlotImplemented));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] HotPlug = %x\n", i, PcieConfig->RootPort[i].HotPlug));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] PmSci = %x\n", i, PcieConfig->RootPort[i].PmSci));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] ExtSync = %x\n", i, PcieConfig->RootPort[i].ExtSync));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] ClkReqSupported = %x\n", i, PcieConfig->RootPort[i].ClkReqSupported));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] ClkReqNumber = %x\n", i, PcieConfig->RootPort[i].ClkReqNumber));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] UnsupportedRequestReport = %x\n", i, PcieConfig->RootPort[i].UnsupportedRequestReport));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] FatalErrorReport = %x\n", i, PcieConfig->RootPort[i].FatalErrorReport));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] NoFatalErrorReport = %x\n", i, PcieConfig->RootPort[i].NoFatalErrorReport));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] CorrectableErrorReport = %x\n", i, PcieConfig->RootPort[i].CorrectableErrorReport));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] PmeInterrupt = %x\n", i, PcieConfig->RootPort[i].PmeInterrupt));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] SystemErrorOnFatalError = %x\n", i, PcieConfig->RootPort[i].SystemErrorOnFatalError));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] SystemErrorOnNonFatalError = %x\n", i, PcieConfig->RootPort[i].SystemErrorOnNonFatalError));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] SystemErrorOnCorrectableError = %x\n", i, PcieConfig->RootPort[i].SystemErrorOnCorrectableError));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] AcsEnabled = %x\n", i, PcieConfig->RootPort[i].AcsEnabled));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] AdvancedErrorReporting = %x\n", i, PcieConfig->RootPort[i].AdvancedErrorReporting));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] TransmitterHalfSwing = %x\n", i, PcieConfig->RootPort[i].TransmitterHalfSwing));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] PcieSpeed = %x\n", i, PcieConfig->RootPort[i].PcieSpeed));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] PhysicalSlotNumber = %x\n", i, PcieConfig->RootPort[i].PhysicalSlotNumber));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] CompletionTimeout = %x\n", i, PcieConfig->RootPort[i].CompletionTimeout));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] SelectableDeemphasis = %x\n", i, PcieConfig->RootPort[i].SelectableDeemphasis));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] Aspm = %x\n", i, PcieConfig->RootPort[i].Aspm));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] L1Substates = %x\n", i, PcieConfig->RootPort[i].L1Substates));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] LtrEnable = %x\n", i, PcieConfig->RootPort[i].LtrEnable));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] LtrConfigLock = %x\n", i, PcieConfig->RootPort[i].LtrConfigLock));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] LtrMaxSnoopLatency = %x\n", i, PcieConfig->RootPort[i].LtrMaxSnoopLatency));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] LtrMaxNoSnoopLatency = %x\n", i, PcieConfig->RootPort[i].LtrMaxNoSnoopLatency));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] SnoopLatencyOverrideMode = %x\n", i, PcieConfig->RootPort[i].SnoopLatencyOverrideMode));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] SnoopLatencyOverrideMultiplier = %x\n", i, PcieConfig->RootPort[i].SnoopLatencyOverrideMultiplier));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] SnoopLatencyOverrideValue = %x\n", i, PcieConfig->RootPort[i].SnoopLatencyOverrideValue));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] NonSnoopLatencyOverrideMode = %x\n", i, PcieConfig->RootPort[i].NonSnoopLatencyOverrideMode));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] NonSnoopLatencyOverrideMultiplier = %x\n", i, PcieConfig->RootPort[i].NonSnoopLatencyOverrideMultiplier));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] NonSnoopLatencyOverrideValue = %x\n", i, PcieConfig->RootPort[i].NonSnoopLatencyOverrideValue));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] SlotPowerLimitScale = %x\n", i, PcieConfig->RootPort[i].SlotPowerLimitScale));
+ DEBUG ((DEBUG_INFO, " RootPort[%d] SlotPowerLimitValue = %x\n", i, PcieConfig->RootPort[i].SlotPowerLimitValue));
+ }
+ DEBUG ((DEBUG_INFO, " EnablePort8xhDecode = %x\n", PcieConfig->EnablePort8xhDecode));
+ DEBUG ((DEBUG_INFO, " ScPciePort8xhDecodePortIndex = %x\n", PcieConfig->ScPciePort8xhDecodePortIndex));
+ DEBUG ((DEBUG_INFO, " DisableRootPortClockGating = %x\n", PcieConfig->DisableRootPortClockGating));
+ DEBUG ((DEBUG_INFO, " EnablePeerMemoryWrite = %x\n", PcieConfig->EnablePeerMemoryWrite));
+ DEBUG ((DEBUG_INFO, " AspmSwSmiNumber = %x\n", PcieConfig->AspmSwSmiNumber));
+ DEBUG ((DEBUG_INFO, " ComplianceTestMode = %x\n", PcieConfig->ComplianceTestMode));
+}
+
+
+/**
+ Print SC_SATA_CONFIG and serial out.
+
+ @param[in] SataConfig Pointer to a SC_SATA_CONFIG that provides the platform setting
+
+**/
+VOID
+PrintSataConfig (
+ IN CONST SC_SATA_CONFIG *SataConfig
+ )
+{
+ UINT32 i;
+
+ DEBUG ((DEBUG_INFO, "------------------ SATA Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, " Enable = %x\n", SataConfig->Enable));
+ DEBUG ((DEBUG_INFO, " SataMode = %x\n", SataConfig->SataMode));
+
+ for (i = 0; i < SC_MAX_SATA_PORTS; i++) {
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] Enabled = %x\n", i, SataConfig->PortSettings[i].Enable));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] HotPlug = %x\n", i, SataConfig->PortSettings[i].HotPlug));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] InterlockSw = %x\n", i, SataConfig->PortSettings[i].InterlockSw));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] External = %x\n", i, SataConfig->PortSettings[i].External));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] SpinUp = %x\n", i, SataConfig->PortSettings[i].SpinUp));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] SolidStateDrive = %x\n", i, SataConfig->PortSettings[i].SolidStateDrive));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] DevSlp = %x\n", i, SataConfig->PortSettings[i].DevSlp));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] EnableDitoConfig = %x\n", i, SataConfig->PortSettings[i].EnableDitoConfig));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] DmVal = %x\n", i, SataConfig->PortSettings[i].DmVal));
+ DEBUG ((DEBUG_INFO, " PortSettings[%d] DitoVal = %x\n", i, SataConfig->PortSettings[i].DitoVal));
+ }
+ DEBUG ((DEBUG_INFO, " SpeedSupport = %x\n", SataConfig->SpeedLimit));
+ DEBUG ((DEBUG_INFO, " eSATASpeedLimit = %x\n", SataConfig->eSATASpeedLimit));
+ DEBUG ((DEBUG_INFO, " TestMode = %x\n", SataConfig->TestMode));
+ DEBUG ((DEBUG_INFO, " SalpSupport = %x\n", SataConfig->SalpSupport));
+ DEBUG ((DEBUG_INFO, " PwrOptEnable = %x\n", SataConfig->PwrOptEnable));
+}
+
+
+/**
+ Print SC_IOAPIC_CONFIG and serial out.
+
+ @param[in] IoApicConfig Pointer to a SC_IOAPIC_CONFIG that provides the platform setting
+
+**/
+VOID
+PrintIoApicConfig (
+ IN CONST SC_IOAPIC_CONFIG *IoApicConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ IOAPIC Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, " BdfValid = %x\n", IoApicConfig->BdfValid));
+ DEBUG ((DEBUG_INFO, " BusNumber = %x\n", IoApicConfig->BusNumber));
+ DEBUG ((DEBUG_INFO, " DeviceNumber = %x\n", IoApicConfig->DeviceNumber));
+ DEBUG ((DEBUG_INFO, " FunctionNumber = %x\n", IoApicConfig->FunctionNumber));
+ DEBUG ((DEBUG_INFO, " IoApicId = %x\n", IoApicConfig->IoApicId));
+ DEBUG ((DEBUG_INFO, " ApicRangeSelect = %x\n", IoApicConfig->ApicRangeSelect));
+ DEBUG ((DEBUG_INFO, " IoApicEntry24_119 = %x\n", IoApicConfig->IoApicEntry24_119));
+}
+
+
+/**
+ Print SC_HPET_CONFIG and serial out.
+
+ @param[in] HpetConfig Pointer to a SC_HPET_CONFIG that provides the platform setting
+
+**/
+VOID
+PrintHpetConfig (
+ IN CONST SC_HPET_CONFIG *HpetConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ HPET Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, " Enable = %x\n", HpetConfig->Enable));
+ DEBUG ((DEBUG_INFO, " BdfValid = %x\n", HpetConfig->BdfValid));
+ DEBUG ((DEBUG_INFO, " BusNumber = %x\n", HpetConfig->BusNumber));
+ DEBUG ((DEBUG_INFO, " DeviceNumber = %x\n", HpetConfig->DeviceNumber));
+ DEBUG ((DEBUG_INFO, " FunctionNumber = %x\n", HpetConfig->FunctionNumber));
+ DEBUG ((DEBUG_INFO, " Base = %x\n", HpetConfig->Base));
+}
+
+
+/**
+ Print PCH_LOCK_DOWN_CONFIG and serial out.
+
+ @param[in] LockDownConfig Pointer to a PCH_LOCK_DOWN_CONFIG that provides the platform setting
+
+**/
+VOID
+PrintLockDownConfig (
+ IN CONST SC_LOCK_DOWN_CONFIG *LockDownConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ Lock Down Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, " GlobalSmi = %x\n", LockDownConfig->GlobalSmi));
+ DEBUG ((DEBUG_INFO, " BiosInterface = %x\n", LockDownConfig->BiosInterface));
+ DEBUG ((DEBUG_INFO, " RtcLock = %x\n", LockDownConfig->RtcLock));
+ DEBUG ((DEBUG_INFO, " BiosLock = %x\n", LockDownConfig->BiosLock));
+ DEBUG ((DEBUG_INFO, " SpiEiss = %x\n", LockDownConfig->SpiEiss));
+ DEBUG ((DEBUG_INFO, " BiosLockSwSmiNumbe = %x\n", LockDownConfig->BiosLockSwSmiNumber));
+ DEBUG ((DEBUG_INFO, " TcoTimerLock = %x\n", LockDownConfig->TcoLock));
+}
+
+/**
+ Print SC_SMBUS_CONFIG and serial out.
+
+ @param[in] SmbusConfig Pointer to a SC_SMBUS_CONFIG that provides the platform setting
+
+**/
+VOID
+PrintSmbusConfig (
+ IN CONST SC_SMBUS_CONFIG *SmbusConfig
+ )
+{
+ UINT32 i;
+
+ DEBUG ((DEBUG_INFO, "------------------ SMBus Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, " Enable = %x\n", SmbusConfig->Enable));
+ DEBUG ((DEBUG_INFO, " ArpEnable = %x\n", SmbusConfig->ArpEnable));
+ DEBUG ((DEBUG_INFO, " DynamicPowerGating = %x\n", SmbusConfig->DynamicPowerGating));
+ DEBUG ((DEBUG_INFO, " SmbusIoBase = %x\n", SmbusConfig->SmbusIoBase));
+ DEBUG ((DEBUG_INFO, " NumRsvdSmbusAddresses = %x\n", SmbusConfig->NumRsvdSmbusAddresses));
+ DEBUG ((DEBUG_INFO, " RsvdSmbusAddressTable = {"));
+ for (i = 0; i < SmbusConfig->NumRsvdSmbusAddresses; ++i) {
+ DEBUG ((DEBUG_INFO, " %02xh", SmbusConfig->RsvdSmbusAddressTable[i]));
+ }
+ DEBUG ((DEBUG_INFO, " }\n"));
+}
+
+
+/**
+ Print SC_HDAUDIO_CONFIG and serial out.
+
+ @param[in] HdaConfig Pointer to a SC_HDAUDIO_CONFIG that provides the platform setting
+
+**/
+VOID
+PrintHdAudioConfig (
+ IN CONST SC_HDAUDIO_CONFIG *HdaConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ HD-Audio Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, " HDA Enable = %x\n", HdaConfig->Enable));
+ DEBUG ((DEBUG_INFO, " DSP Enable = %x\n", HdaConfig->DspEnable));
+ DEBUG ((DEBUG_INFO, " Pme = %x\n", HdaConfig->Pme));
+ DEBUG ((DEBUG_INFO, " I/O Buffer Ownership = %x\n", HdaConfig->IoBufferOwnership));
+ DEBUG ((DEBUG_INFO, " I/O Buffer Voltage = %x\n", HdaConfig->IoBufferVoltage));
+ DEBUG ((DEBUG_INFO, " VC Type = %x\n", HdaConfig->VcType));
+ DEBUG ((DEBUG_INFO, " DSP Feature Mask = %x\n", HdaConfig->DspFeatureMask));
+ DEBUG ((DEBUG_INFO, " DSP PP Module Mask = %x\n", HdaConfig->DspPpModuleMask));
+ DEBUG ((DEBUG_INFO, " ResetWaitTimer = %x\n", HdaConfig->ResetWaitTimer));
+ DEBUG ((DEBUG_INFO, " VcType = %x\n", HdaConfig->VcType));
+ DEBUG ((DEBUG_INFO, " HD-A Link Frequency = %x\n", HdaConfig->HdAudioLinkFrequency));
+ DEBUG ((DEBUG_INFO, " iDisp Link Frequency = %x\n", HdaConfig->IDispLinkFrequency));
+ DEBUG ((DEBUG_INFO, " iDisp Link T-Mode = %x\n", HdaConfig->IDispLinkTmode));
+ DEBUG ((DEBUG_INFO, " DSP Endpoint DMIC = %x\n", HdaConfig->DspEndpointDmic));
+ DEBUG ((DEBUG_INFO, " DSP Endpoint I2S SKP = %x\n", HdaConfig->DspEndpointI2sSkp));
+ DEBUG ((DEBUG_INFO, " DSP Endpoint I2S HP = %x\n", HdaConfig->DspEndpointI2sHp));
+ DEBUG ((DEBUG_INFO, " DSP Endpoint BT = %x\n", HdaConfig->DspEndpointBluetooth));
+ DEBUG ((DEBUG_INFO, " DSP Feature Mask = %x\n", HdaConfig->DspFeatureMask));
+ DEBUG ((DEBUG_INFO, " DSP PP Module Mask = %x\n", HdaConfig->DspPpModuleMask));
+ DEBUG ((DEBUG_INFO, " CSME Memory Transfers = %x\n", HdaConfig->Mmt));
+ DEBUG ((DEBUG_INFO, " Host Memory Transfers = %x\n", HdaConfig->Hmt));
+ DEBUG ((DEBUG_INFO, " BIOS Configuration Lock Down = %x\n", HdaConfig->BiosCfgLockDown));
+ DEBUG ((DEBUG_INFO, " Power Gating = %x\n", HdaConfig->PwrGate));
+ DEBUG ((DEBUG_INFO, " Clock Gating = %x\n", HdaConfig->ClkGate));
+}
+
+
+/**
+ Print SC_PM_CONFIG and serial out.
+
+ @param[in] PmConfig Pointer to a SC_PM_CONFIG that provides the platform setting
+
+**/
+VOID
+PrintPmConfig (
+ IN CONST SC_PM_CONFIG *PmConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ PM Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, " WakeConfig PmeB0S5Dis = %x\n", PmConfig->WakeConfig.PmeB0S5Dis));
+ DEBUG ((DEBUG_INFO, " PciClockRun = %x\n", PmConfig->PciClockRun));
+ DEBUG ((DEBUG_INFO, " Timer8254ClkGateEn = %x\n", PmConfig->Timer8254ClkGateEn));
+ DEBUG ((DEBUG_INFO, " PwrBtnOverridePeriod = %x\n", PmConfig->PwrBtnOverridePeriod));
+ DEBUG ((DEBUG_INFO, " DisableNativePowerButton = %x\n", PmConfig->DisableNativePowerButton));
+ DEBUG ((DEBUG_INFO, " PowerButterDebounceMode = %x\n", PmConfig->PowerButterDebounceMode));
+}
+
+/**
+ Print SC_LPC_SIRQ_CONFIG and serial out.
+
+ @param[in] SerialIrqConfig Pointer to a SC_LPC_SIRQ_CONFIG that provides the platform setting
+
+**/
+VOID
+PrintSerialIrqConfig (
+ IN CONST SC_LPC_SIRQ_CONFIG *SerialIrqConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ Serial IRQ Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, " SirqEnable = %x\n", SerialIrqConfig->SirqEnable));
+ DEBUG ((DEBUG_INFO, " SirqMode = %x\n", SerialIrqConfig->SirqMode));
+ DEBUG ((DEBUG_INFO, " StartFramePulse = %x\n", SerialIrqConfig->StartFramePulse));
+}
+
+
+/**
+ Print SC_GMM_CONFIG and serial out.
+
+ @param[in] GmmConfig Pointer to a SC_GMM_CONFIG that provides the platform setting
+
+**/
+VOID
+PrintGmmConfig (
+ IN CONST SC_GMM_CONFIG *GmmConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ GMM Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, " Enable = %x\n", GmmConfig->Enable));
+ DEBUG ((DEBUG_INFO, " ClkGatingPgcbClkTrunk = %x\n", GmmConfig->ClkGatingPgcbClkTrunk));
+ DEBUG ((DEBUG_INFO, " ClkGatingSb = %x\n", GmmConfig->ClkGatingSb));
+ DEBUG ((DEBUG_INFO, " ClkGatingSbClkTrunk = %x\n", GmmConfig->ClkGatingSbClkTrunk));
+ DEBUG ((DEBUG_INFO, " ClkGatingSbClkPartition = %x\n", GmmConfig->ClkGatingSbClkPartition));
+ DEBUG ((DEBUG_INFO, " ClkGatingCore = %x\n", GmmConfig->ClkGatingCore));
+ DEBUG ((DEBUG_INFO, " ClkGatingDma = %x\n", GmmConfig->ClkGatingDma));
+ DEBUG ((DEBUG_INFO, " ClkGatingRegAccess = %x\n", GmmConfig->ClkGatingRegAccess));
+ DEBUG ((DEBUG_INFO, " ClkGatingHost = %x\n", GmmConfig->ClkGatingHost));
+ DEBUG ((DEBUG_INFO, " ClkGatingPartition = %x\n", GmmConfig->ClkGatingPartition));
+ DEBUG ((DEBUG_INFO, " ClkGatingTrunk = %x\n", GmmConfig->ClkGatingTrunk));
+ DEBUG ((DEBUG_INFO, " SvPwrGatingHwAutoEnable = %x\n", GmmConfig->SvPwrGatingHwAutoEnable));
+ DEBUG ((DEBUG_INFO, " SvPwrGatingD3HotEnable = %x\n", GmmConfig->SvPwrGatingD3HotEnable));
+ DEBUG ((DEBUG_INFO, " SvPwrGatingI3Enable = %x\n", GmmConfig->SvPwrGatingI3Enable));
+ DEBUG ((DEBUG_INFO, " SvPwrGatingPmcReqEnable = %x\n", GmmConfig->SvPwrGatingPmcReqEnable));
+
+ return;
+}
+
+
+/**
+ Print SC_LPSS_CONFIG and serial out.
+
+ @param[in] LpssConfig Pointer to a SC_LPSS_CONFIG that provides the platform setting
+
+**/
+
+VOID
+PrintLpssConfig (
+ IN CONST SC_LPSS_CONFIG *LpssConfig
+ )
+{
+ UINT32 Index;
+
+ DEBUG ((DEBUG_INFO, "------------------ LPSS Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, " I2c0Enable = %x\n", LpssConfig->I2c0Enable));
+ DEBUG ((DEBUG_INFO, " I2c1Enable = %x\n", LpssConfig->I2c1Enable));
+ DEBUG ((DEBUG_INFO, " I2c2Enable = %x\n", LpssConfig->I2c2Enable));
+ DEBUG ((DEBUG_INFO, " I2c3Enable = %x\n", LpssConfig->I2c3Enable));
+ DEBUG ((DEBUG_INFO, " I2c4Enable = %x\n", LpssConfig->I2c4Enable));
+ DEBUG ((DEBUG_INFO, " I2c5Enable = %x\n", LpssConfig->I2c5Enable));
+ DEBUG ((DEBUG_INFO, " I2c6Enable = %x\n", LpssConfig->I2c6Enable));
+ DEBUG ((DEBUG_INFO, " I2c7Enable = %x\n", LpssConfig->I2c7Enable));
+ DEBUG ((DEBUG_INFO, " Hsuart0Enable = %x\n", LpssConfig->Hsuart0Enable));
+ DEBUG ((DEBUG_INFO, " Hsuart1Enable = %x\n", LpssConfig->Hsuart1Enable));
+ DEBUG ((DEBUG_INFO, " Hsuart2Enable = %x\n", LpssConfig->Hsuart2Enable));
+ DEBUG ((DEBUG_INFO, " Hsuart3Enable = %x\n", LpssConfig->Hsuart3Enable));
+ DEBUG ((DEBUG_INFO, " Spi0Enable = %x\n", LpssConfig->Spi0Enable));
+ DEBUG ((DEBUG_INFO, " Spi1Enable = %x\n", LpssConfig->Spi1Enable));
+ DEBUG ((DEBUG_INFO, " Spi2Enable = %x\n", LpssConfig->Spi2Enable));
+ DEBUG ((DEBUG_INFO, " Uart2KernelDebugBaseAddress = %x\n", LpssConfig->Uart2KernelDebugBaseAddress));
+
+ for (Index = 0; Index < LPSS_I2C_DEVICE_NUM; Index++) {
+ DEBUG ((DEBUG_INFO, " I2cClkGateCfg[%d] = %x\n", Index, LpssConfig->I2cClkGateCfg[Index]));
+ }
+
+ for (Index = 0; Index < LPSS_HSUART_DEVICE_NUM; Index++) {
+ DEBUG ((DEBUG_INFO, " HsuartClkGateCfg[%d] = %x\n", Index, LpssConfig->HsuartClkGateCfg[Index]));
+ }
+
+ for (Index = 0; Index < LPSS_SPI_DEVICE_NUM; Index++) {
+ DEBUG ((DEBUG_INFO, " SpiClkGateCfg[%d] = %x\n", Index, LpssConfig->SpiClkGateCfg[Index]));
+ }
+
+ DEBUG ((DEBUG_INFO, " S0ixEnable = %x\n", LpssConfig->S0ixEnable));
+ DEBUG ((DEBUG_INFO, " OsDbgEnable = %x\n", LpssConfig->OsDbgEnable));
+}
+
+
+/**
+ Print SC_SCS_CONFIG and serial out.
+
+ @param[in] ScsConfig Pointer to a SC_SCS_CONFIG that provides the platform setting
+
+**/
+VOID
+PrintScsConfig (
+ IN CONST SC_SCS_CONFIG *ScsConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ SCS Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, " SdcardEnable = %x\n", ScsConfig->SdcardEnable));
+ DEBUG ((DEBUG_INFO, " EmmcEnable = %x\n", ScsConfig->EmmcEnable));
+ DEBUG ((DEBUG_INFO, " UfsEnable = %x\n", ScsConfig->UfsEnable));
+ DEBUG ((DEBUG_INFO, " SdioEnable = %x\n", ScsConfig->SdioEnable));
+ DEBUG ((DEBUG_INFO, " EmmcHostMaxSpeed = %x\n", ScsConfig->EmmcHostMaxSpeed));
+ DEBUG ((DEBUG_INFO, " GppLock = %x\n", ScsConfig->GppLock));
+ DEBUG ((DEBUG_INFO, " SccEmmcTraceLength = %x\n", ScsConfig->SccEmmcTraceLength));
+ DEBUG ((DEBUG_INFO, " SdioTxCmdCntl = %x\n", ScsConfig->SdioRegDllConfig.TxCmdCntl));
+ DEBUG ((DEBUG_INFO, " SdioTxDataCntl1 = %x\n", ScsConfig->SdioRegDllConfig.TxDataCntl1));
+ DEBUG ((DEBUG_INFO, " SdioTxDataCntl2 = %x\n", ScsConfig->SdioRegDllConfig.TxDataCntl2));
+ DEBUG ((DEBUG_INFO, " SdioRxCmdDataCntl1 = %x\n", ScsConfig->SdioRegDllConfig.RxCmdDataCntl1));
+ DEBUG ((DEBUG_INFO, " SdioRxStrobeCntl = %x\n", ScsConfig->SdioRegDllConfig.RxCmdDataCntl2));
+ DEBUG ((DEBUG_INFO, " SdcardTxCmdCntl = %x\n", ScsConfig->SdcardRegDllConfig.TxCmdCntl));
+ DEBUG ((DEBUG_INFO, " SdcardTxDataCntl1 = %x\n", ScsConfig->SdcardRegDllConfig.TxDataCntl1));
+ DEBUG ((DEBUG_INFO, " SdcardTxDataCntl2 = %x\n", ScsConfig->SdcardRegDllConfig.TxDataCntl2));
+ DEBUG ((DEBUG_INFO, " SdcardRxCmdDataCntl1 = %x\n", ScsConfig->SdcardRegDllConfig.RxCmdDataCntl1));
+ DEBUG ((DEBUG_INFO, " SdcardRxStrobeCntl = %x\n", ScsConfig->SdcardRegDllConfig.RxStrobeCntl));
+ DEBUG ((DEBUG_INFO, " SdcardRxCmdDataCntl1 = %x\n", ScsConfig->SdcardRegDllConfig.RxCmdDataCntl2));
+ DEBUG ((DEBUG_INFO, " EmmcTxCmdCntl = %x\n", ScsConfig->EmmcRegDllConfig.TxCmdCntl));
+ DEBUG ((DEBUG_INFO, " EmmcTxDataCntl1 = %x\n", ScsConfig->EmmcRegDllConfig.TxDataCntl1));
+ DEBUG ((DEBUG_INFO, " EmmcTxDataCntl2 = %x\n", ScsConfig->EmmcRegDllConfig.TxDataCntl2));
+ DEBUG ((DEBUG_INFO, " EmmcRxCmdDataCntl1 = %x\n", ScsConfig->EmmcRegDllConfig.RxCmdDataCntl1));
+ DEBUG ((DEBUG_INFO, " EmmcRxStrobeCntl = %x\n", ScsConfig->EmmcRegDllConfig.RxStrobeCntl));
+ DEBUG ((DEBUG_INFO, " EmmcRxCmdDataCntl2 = %x\n", ScsConfig->EmmcRegDllConfig.RxCmdDataCntl2));
+ DEBUG ((DEBUG_INFO, " EmmcMasterSwCntl = %x\n", ScsConfig->EmmcRegDllConfig.MasterSwCntl));
+}
+
+
+/**
+ Print SC_VTD_CONFIG and serial out.
+
+ @param[in] VtdConfig Pointer to a SC_VTD_CONFIG that provides the platform setting
+
+**/
+
+VOID
+PrintVtdConfig (
+ IN CONST SC_VTD_CONFIG *VtdConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ Vtd Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, " VtdEnable = %x\n", VtdConfig->VtdEnable));
+
+ return;
+}
+
+
+/**
+ Print SC_GENERAL_CONFIG and serial out.
+
+ @param[in] ScConfig Pointer to a SC_GENERAL_CONFIG that provides the platform setting
+**/
+VOID
+PrintGeneralConfig (
+ IN CONST SC_GENERAL_CONFIG *ScGeneralConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ General Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, " SubSystemVendorId = %x\n", ScGeneralConfig->SubSystemVendorId));
+ DEBUG ((DEBUG_INFO, " SubSystemId = %x\n", ScGeneralConfig->SubSystemId));
+ DEBUG ((DEBUG_INFO, " AcpiBase = %x\n", ScGeneralConfig->AcpiBase));
+ DEBUG ((DEBUG_INFO, " PmcBase = %x\n", ScGeneralConfig->PmcBase));
+ DEBUG ((DEBUG_INFO, " P2sbBase = %x\n", ScGeneralConfig->P2sbBase));
+ DEBUG ((DEBUG_INFO, " Crid = %x\n", ScGeneralConfig->Crid));
+ DEBUG ((DEBUG_INFO, " ResetSelect = %x\n", ScGeneralConfig->ResetSelect));
+}
+
+
+/**
+ Print SC_ISH_CONFIG and serial out.
+
+ @param[in] IshConfig Pointer to a SC_ISH_CONFIG that provides the platform setting
+
+**/
+VOID
+PrintIshConfig (
+ IN CONST SC_ISH_CONFIG *IshConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ ISH Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, "Enable = %x\n", IshConfig->Enable));
+}
+
+
+/**
+ Print SC_FLASH_PROTECTION_CONFIG and serial out.
+
+ @param[in] FlashProtectConfig Pointer to a SC_FLASH_PROTECTION_CONFIG that provides the platform setting
+
+**/
+VOID
+PrintFlashProtectionConfig (
+ IN CONST SC_FLASH_PROTECTION_CONFIG *FlashProtectConfig
+ )
+{
+ UINT32 Index;
+
+ DEBUG ((DEBUG_INFO, "------------------ SC Flash Protection Config ------------------\n"));
+ for (Index = 0; Index < SC_FLASH_PROTECTED_RANGES; ++Index) {
+ DEBUG ((DEBUG_INFO, " WriteProtectionEnable[%d] = %x\n", Index, FlashProtectConfig->ProtectRange[Index].WriteProtectionEnable));
+ DEBUG ((DEBUG_INFO, " ReadProtectionEnable[%d] = %x\n", Index, FlashProtectConfig->ProtectRange[Index].ReadProtectionEnable));
+ DEBUG ((DEBUG_INFO, " ProtectedRangeLimit[%d] = %x\n", Index, FlashProtectConfig->ProtectRange[Index].ProtectedRangeLimit));
+ DEBUG ((DEBUG_INFO, " ProtectedRangeBase[%d] = %x\n", Index, FlashProtectConfig->ProtectRange[Index].ProtectedRangeBase));
+ }
+}
+
+
+/**
+ Print SC_DCI_CONFIG and serial out.
+
+ @param[in] IshConfig Pointer to a SC_DCI_CONFIG that provides the platform setting
+
+**/
+VOID
+PrintDciConfig (
+ IN CONST SC_DCI_CONFIG *DciConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ DCI Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, "DciEn = %x\n", DciConfig->DciEn));
+ DEBUG ((DEBUG_INFO, "DciAutoDetect = %x\n", DciConfig->DciAutoDetect));
+}
+
+
+/**
+ Print SC_P2SB_CONFIG and serial out.
+
+ @param[in] IshConfig Pointer to a SC_DCI_CONFIG that provides the platform setting
+
+**/
+VOID
+PrintP2sbConfig (
+ IN CONST SC_P2SB_CONFIG *P2sbConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ P2SB Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, " P2sbUnhide = %x\n", P2sbConfig->P2sbUnhide));
+}
+
+
+/**
+ Print whole SC config blocks and serial out.
+
+ @param[in] ScPolicyPpi The RC Policy PPI instance
+
+**/
+VOID
+ScPrintPolicyPpi (
+ IN SC_POLICY_PPI *ScPolicyPpi
+ )
+{
+ EFI_STATUS Status;
+ SC_GENERAL_CONFIG *ScGeneralConfig;
+ SC_SATA_CONFIG *SataConfig;
+ SC_PCIE_CONFIG *PcieRpConfig;
+ SC_SMBUS_CONFIG *SmbusConfig;
+ SC_HPET_CONFIG *HpetConfig;
+ SC_IOAPIC_CONFIG *IoApicConfig;
+ SC_USB_CONFIG *UsbConfig;
+ SC_HDAUDIO_CONFIG *HdaConfig;
+ SC_GMM_CONFIG *GmmConfig;
+ SC_PM_CONFIG *PmConfig;
+ SC_LOCK_DOWN_CONFIG *LockDownConfig;
+ SC_LPC_SIRQ_CONFIG *SerialIrqConfig;
+ SC_LPSS_CONFIG *LpssConfig;
+ SC_SCS_CONFIG *ScsConfig;
+ SC_VTD_CONFIG *VtdConfig;
+ SC_ISH_CONFIG *IshConfig;
+ SC_FLASH_PROTECTION_CONFIG *FlashProtectionConfig;
+ SC_DCI_CONFIG *DciConfig;
+ SC_P2SB_CONFIG *P2sbConfig;
+ SC_INTERRUPT_CONFIG *InterruptConfig;
+
+ Status = GetConfigBlock ((VOID *) ScPolicyPpi, &gScGeneralConfigGuid, (VOID *) &ScGeneralConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) ScPolicyPpi, &gSataConfigGuid, (VOID *) &SataConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) ScPolicyPpi, &gPcieRpConfigGuid, (VOID *) &PcieRpConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) ScPolicyPpi, &gHpetConfigGuid, (VOID *) &HpetConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) ScPolicyPpi, &gSmbusConfigGuid, (VOID *) &SmbusConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) ScPolicyPpi, &gIoApicConfigGuid, (VOID *) &IoApicConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) ScPolicyPpi, &gUsbConfigGuid, (VOID *) &UsbConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) ScPolicyPpi, &gHdAudioConfigGuid, (VOID *) &HdaConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) ScPolicyPpi, &gGmmConfigGuid, (VOID *) &GmmConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) ScPolicyPpi, &gPmConfigGuid, (VOID *) &PmConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) ScPolicyPpi, &gLockDownConfigGuid, (VOID *) &LockDownConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) ScPolicyPpi, &gSerialIrqConfigGuid, (VOID *) &SerialIrqConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) ScPolicyPpi, &gLpssConfigGuid, (VOID *) &LpssConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) ScPolicyPpi, &gScsConfigGuid, (VOID *) &ScsConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) ScPolicyPpi, &gVtdConfigGuid, (VOID *) &VtdConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) ScPolicyPpi, &gIshConfigGuid, (VOID *) &IshConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) ScPolicyPpi, &gFlashProtectionConfigGuid, (VOID *) &FlashProtectionConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) ScPolicyPpi, &gDciConfigGuid, (VOID *) &DciConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) ScPolicyPpi, &gP2sbConfigGuid, (VOID *) &P2sbConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) ScPolicyPpi, &gInterruptConfigGuid, (VOID *) &InterruptConfig);
+ ASSERT_EFI_ERROR (Status);
+
+ DEBUG ((DEBUG_INFO, "------------------------ SC Print Policy Start ------------------------\n"));
+ PrintGeneralConfig (ScGeneralConfig);
+ PrintSataConfig (SataConfig);
+ PrintPcieConfig (PcieRpConfig);
+ PrintHpetConfig (HpetConfig);
+ PrintSmbusConfig (SmbusConfig);
+ PrintIoApicConfig (IoApicConfig);
+ PrintUsbConfig (UsbConfig);
+ PrintHdAudioConfig (HdaConfig);
+ PrintGmmConfig (GmmConfig);
+ PrintPmConfig (PmConfig);
+ PrintLockDownConfig (LockDownConfig);
+ PrintSerialIrqConfig (SerialIrqConfig);
+ PrintLpssConfig (LpssConfig);
+ PrintScsConfig (ScsConfig);
+ PrintVtdConfig (VtdConfig);
+ PrintIshConfig (IshConfig);
+ PrintFlashProtectionConfig (FlashProtectionConfig);
+ PrintDciConfig (DciConfig);
+ PrintP2sbConfig (P2sbConfig);
+ PrintInterruptConfig (InterruptConfig);
+
+ DEBUG ((DEBUG_INFO, "------------------------ SC Print Policy End ------------------------\n"));
+}
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/PeiScPolicyLib/ScPrintPolicyPreMem.c b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/PeiScPolicyLib/ScPrintPolicyPreMem.c
new file mode 100644
index 0000000000..44d71202f1
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/PeiScPolicyLib/ScPrintPolicyPreMem.c
@@ -0,0 +1,75 @@
+/** @file
+ This file is PeiScPolicyLib library for printing PREMEM Policy settings.
+
+ Copyright (c) 2016, 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.
+
+**/
+
+#include "PeiScPolicyLibrary.h"
+
+VOID
+PrintPciePreMemConfig (
+ IN CONST SC_PCIE_PREMEM_CONFIG *PciePreMemConfig
+ )
+{
+ UINT8 i;
+
+ DEBUG ((DEBUG_INFO, "--- PCIe Config ---\n"));
+ for (i = 0; i < GetScMaxPciePortNum (); i++) {
+ DEBUG ((DEBUG_INFO, " RootPort[%d] PERST = %x\n", i, PciePreMemConfig->RootPort[i].Perst));
+ }
+ DEBUG ((DEBUG_INFO, " StartTimerTickerOfPerstAssert = %x\n", i, PciePreMemConfig->StartTimerTickerOfPfetAssert));
+}
+
+
+/**
+ Print SC_LPC_PREMEM_CONFIG and serial out.
+
+ @param[in] LpcConfig Pointer to a SC_LPC_CONFIG that provides the platform setting
+
+**/
+VOID
+PrintLpcPreMemConfig (
+ IN CONST SC_LPC_PREMEM_CONFIG *LpcConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "--- LPC Config ---\n"));
+ DEBUG ((DEBUG_INFO, " EnhancePort8xhDecoding = %x\n", LpcConfig->EnhancePort8xhDecoding));
+}
+
+
+/**
+ Print whole SC_PREMEM_POLICY_PPI and serial out.
+
+ @param[in] ScPreMemPolicyPpi The RC Policy PPI instance
+
+**/
+VOID
+EFIAPI
+ScPreMemPrintPolicyPpi (
+ IN SC_PREMEM_POLICY_PPI *ScPreMemPolicyPpi
+ )
+{
+ SC_PCIE_PREMEM_CONFIG *PciePreMemConfig;
+ SC_LPC_PREMEM_CONFIG *LpcPreMemConfig;
+ EFI_STATUS Status;
+
+ Status = GetConfigBlock ((VOID *) ScPreMemPolicyPpi, &gPcieRpPreMemConfigGuid, (VOID *) &PciePreMemConfig);
+ ASSERT_EFI_ERROR (Status);
+ Status = GetConfigBlock ((VOID *) ScPreMemPolicyPpi, &gLpcPreMemConfigGuid, (VOID *) &LpcPreMemConfig);
+ ASSERT_EFI_ERROR (Status);
+
+ DEBUG ((DEBUG_INFO, "--- SC Print PreMem Policy Start ---\n"));
+ PrintPciePreMemConfig (PciePreMemConfig);
+ PrintLpcPreMemConfig (LpcPreMemConfig);
+ DEBUG ((DEBUG_INFO, "--- SC Print PreMem Policy End ---\n"));
+}
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/Private/DxeScHdaLib/DxeScHdaLib.inf b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/Private/DxeScHdaLib/DxeScHdaLib.inf
new file mode 100644
index 0000000000..2013054fdb
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/Private/DxeScHdaLib/DxeScHdaLib.inf
@@ -0,0 +1,46 @@
+## @file
+# Component information file for SC HD Audio Library.
+#
+# Copyright (c) 2014 - 2016, 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 = DxeScHdaLib
+ FILE_GUID = DA915B7F-EE08-4C1D-B3D0-DE7C52AB155A
+ VERSION_STRING = 1.0
+ MODULE_TYPE = BASE
+ LIBRARY_CLASS = ScHdaLib
+
+[LibraryClasses]
+ BaseLib
+ DebugLib
+ MemoryAllocationLib
+ BaseMemoryLib
+ ScPlatformLib
+ SteppingLib
+
+[Packages]
+ MdePkg/MdePkg.dec
+ BroxtonSiPkg/BroxtonSiPkg.dec
+ BroxtonSiPkg/BroxtonSiPrivate.dec
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemId ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemTableId ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemRevision ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorId ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorRevision ## CONSUMES
+
+[Sources]
+ ScHdaLib.c
+ ScHdaEndpoints.c
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/Private/DxeScHdaLib/ScHdaEndpoints.c b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/Private/DxeScHdaLib/ScHdaEndpoints.c
new file mode 100644
index 0000000000..59add2d2fc
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/Private/DxeScHdaLib/ScHdaEndpoints.c
@@ -0,0 +1,497 @@
+/** @file
+ This file contains HD Audio NHLT Endpoints definitions.
+
+ Copyright (c) 2014 - 2016, 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.
+
+**/
+
+#include <Private/ScHdaEndpoints.h>
+
+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
+CONST UINT32 DmicStereo16BitFormatConfig[] =
+{
+ 0x00000001,
+ 0xFFFF3210,
+ 0xFFFFFF10,
+ 0xFFFFFF32,
+ 0xFFFFFFFF,
+ 0x00000003,
+ 0x00000003,
+ 0x00300003,
+ 0x00300003
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST UINT32 DmicStereo32BitFormatConfig[] =
+{
+ 0x00000001,
+ 0xFFFF3210,
+ 0xFFFFFF10,
+ 0xFFFFFF32,
+ 0xFFFFFFFF,
+ 0x00000003,
+ 0x00000003,
+ 0x00380003,
+ 0x00380003
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST UINT32 DmicQuad16BitFormatConfig[] =
+{
+ 0x00000001,
+ 0xFFFF3210,
+ 0xFFFFFF10,
+ 0xFFFFFF32,
+ 0xFFFFFFFF,
+ 0x00000003,
+ 0x00000003,
+ 0x00320003,
+ 0x00320003
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST UINT32 DmicQuad32BitFormatConfig[] =
+{
+ 0x00000001,
+ 0xFFFF3210,
+ 0xFFFFFF10,
+ 0xFFFFFF32,
+ 0xFFFFFFFF,
+ 0x00000003,
+ 0x00000003,
+ 0x003A0003,
+ 0x003A0003
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 DmicFormatConfigSize = sizeof (DmicStereo16BitFormatConfig);
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST UINT32 DmicCommonFormatConfig[] =
+{
+ 0x00000003,
+ //
+ // PDM_SETTINGS
+ //
+ 0x0001, 0x08000F00, 0x0, 0x0303, 0, 0, 0, 0,
+ 0x11, 0x401a0, 0, 0, 0, 0, 0, 0,
+ 0x11, 0xe03b1, 0, 0, 0, 0, 0, 0,
+ //
+ // FIR A coefficients
+ //
+ 0x00006, 0xfffc2, 0xfff4a, 0xffe76, 0xffd3d, 0xffbb1, 0xffa06, 0xff891, 0xff7b5, 0xff7d0, 0xff91a, 0xffb89, 0xffec7, 0x00232, 0x00501, 0x00674, 0x0060f, 0x003c8, 0x0001f, 0xffc0e,
+ 0xff8c8, 0xff76b, 0xff89b, 0xffc48, 0x00192, 0x006fd, 0x00ad0, 0x00ba2, 0x008d3, 0x002db, 0xffb45, 0xff451, 0xff04f, 0xff0de, 0xff654, 0xfff79, 0x009c4, 0x01204, 0x01559, 0x0122f,
+ 0x008e0, 0xffbcc, 0xfeec8, 0xfe607, 0xfe4c4, 0xfec1d, 0xffa84, 0x00bfe, 0x01b34, 0x0230f, 0x02062, 0x0131d, 0xffe9a, 0xfe8d0, 0xfd8a1, 0xfd3b3, 0xfdc86, 0xff162, 0x00c8d, 0x025d6,
+ 0x03504, 0x03479, 0x02332, 0x00574, 0xfe3d0, 0xfc8b1, 0xfbd30, 0xfc60d, 0xfe1e3, 0x0092c, 0x0303b, 0x04ab2, 0x04f5b, 0x03b53, 0x01350, 0xfe2a8, 0xfb81f, 0xfa174, 0xfa6ff, 0xfc8be,
+ 0xffdd5, 0x036d4, 0x0622f, 0x07195, 0x05e9d, 0x02d32, 0xfeae9, 0xfab52, 0xf8238, 0xf7d85, 0xfa0ad, 0xfe310, 0x03207, 0x0761d, 0x099fa, 0x09101, 0x05b91, 0x00783, 0xfaca0, 0xf65ea,
+ 0xf499f, 0xf6261, 0xfab80, 0x011b3, 0x0782e, 0x0c0b9, 0x0d485, 0x0ab24, 0x04d99, 0xfd470, 0xf6145, 0xf157b, 0xf08ad, 0xf419d, 0xfb3aa, 0x041a3, 0x0c550, 0x119b3, 0x1253d, 0x0e125,
+ 0x05bdc, 0xfb5dc, 0xf1998, 0xeb0a6, 0xe98ed, 0xedca7, 0xf6f50, 0x0303a, 0x0f22e, 0x18623, 0x1c671, 0x19fbb, 0x1158d, 0x041b8, 0xf4ea6, 0xe6e38, 0xdcf55, 0xd9485, 0xdcd8e, 0xe7549,
+ 0xf73b4, 0x0a398, 0x1da21, 0x2eec7, 0x3c1e2, 0x440c0, 0x466ea, 0x43ca0, 0x3d36f, 0x341bc, 0x29e6b, 0x1fd4d, 0x16cef, 0x0f5cd, 0x09ac4, 0x05a55, 0x03040, 0x0171e, 0x00999, 0x0033a,
+ 0x000be,
+ //
+ // FIR B coefficients
+ //
+ 0xffff5, 0x007c7, 0x00726, 0x00a22, 0x00db5, 0x011d6, 0x01676, 0x01b80, 0x020d4, 0x02648, 0x02baa, 0x030c4, 0x03557, 0x03924, 0x03be9, 0x03d69, 0x03d6c, 0x03bc5, 0x03854, 0x03309,
+ 0x02be4, 0x022fe, 0x01882, 0x00cb5, 0xfffec, 0xff294, 0xfe526, 0xfd82b, 0xfcc2f, 0xfc1c0, 0xfb967, 0xfb3a1, 0xfb0d7, 0xfb158, 0xfb556, 0xfbcdd, 0xfc7d4, 0xfd5f7, 0xfe6dc, 0xff9f0,
+ 0x00e7f, 0x023b7, 0x038af, 0x04c77, 0x05e19, 0x06ca8, 0x07750, 0x07d58, 0x07e34, 0x0798a, 0x06f3a, 0x05f66, 0x04a6d, 0x030f5, 0x013db, 0xff438, 0xfd34d, 0xfb280, 0xf9346, 0xf771b,
+ 0xf5f64, 0xf4d73, 0xf425a, 0xf3efb, 0xf43de, 0xf513f, 0xf66f2, 0xf8476, 0xfa8dd, 0xfd2ef, 0x00113, 0x03183, 0x06234, 0x09112, 0x0bbf5, 0x0e0d9, 0x0fdd1, 0x11149, 0x119ee, 0x116eb,
+ 0x107cf, 0x0ecbd, 0x0c64d, 0x095a8, 0x05c67, 0x01c9d, 0xfd8b2, 0xf935b, 0xf4f70, 0xf0fe0, 0xed781, 0xea8fe, 0xe86ae, 0xe7280, 0xe6de0, 0xe799f, 0xe95f0, 0xec252, 0xefda0, 0xf4606,
+ 0xf9922, 0xff404, 0x0535e, 0x0b38a, 0x110c8, 0x16749, 0x1b36d, 0x1f1d1, 0x21f8e, 0x23a37, 0x24019, 0x2302a, 0x20a3e, 0x1cee6, 0x17f93, 0x11e6e, 0x0ae61, 0x032e8, 0xfb00a, 0xf2a20,
+ 0xea5c4, 0xe2795, 0xdb421, 0xd4faa, 0xcfe13, 0xcc2ad, 0xca02a, 0xc9877, 0xcacbc, 0xcdd42, 0xd2982, 0xd901f, 0xe0efb, 0xea344, 0xf4996, 0xffe0c, 0x0bc6f, 0x1804f, 0x24528, 0x3068b,
+ 0x3c039, 0x46e45, 0x50d2f, 0x599f7, 0x61231, 0x67412, 0x6be71, 0x6f0ca, 0x70b3a, 0x70e72, 0x6fbac, 0x6d497, 0x69b45, 0x65213, 0x5fb93, 0x59a75, 0x53172, 0x4c336, 0x4524e, 0x3e116,
+ 0x371b3, 0x305ff, 0x29f8c, 0x23f9b, 0x1e71b, 0x196b1, 0x14eb4, 0x10f3e, 0x0d828, 0x0a91e, 0x081a1, 0x06117, 0x046cd, 0x03207, 0x02204, 0x01605, 0x00d56, 0x009c9,
+ //
+ // PDM_SETTINGS
+ //
+ 0x0001, 0x08000F00, 0x0, 0x0303, 0, 0, 0, 0,
+ 0x11, 0x401a0, 0, 0, 0, 0, 0, 0,
+ 0x11, 0xe03b1, 0, 0, 0, 0, 0, 0,
+ //
+ // FIR A coefficients
+ //
+ 0x00006, 0xfffc2, 0xfff4a, 0xffe76, 0xffd3d, 0xffbb1, 0xffa06, 0xff891, 0xff7b5, 0xff7d0, 0xff91a, 0xffb89, 0xffec7, 0x00232, 0x00501, 0x00674, 0x0060f, 0x003c8, 0x0001f, 0xffc0e,
+ 0xff8c8, 0xff76b, 0xff89b, 0xffc48, 0x00192, 0x006fd, 0x00ad0, 0x00ba2, 0x008d3, 0x002db, 0xffb45, 0xff451, 0xff04f, 0xff0de, 0xff654, 0xfff79, 0x009c4, 0x01204, 0x01559, 0x0122f,
+ 0x008e0, 0xffbcc, 0xfeec8, 0xfe607, 0xfe4c4, 0xfec1d, 0xffa84, 0x00bfe, 0x01b34, 0x0230f, 0x02062, 0x0131d, 0xffe9a, 0xfe8d0, 0xfd8a1, 0xfd3b3, 0xfdc86, 0xff162, 0x00c8d, 0x025d6,
+ 0x03504, 0x03479, 0x02332, 0x00574, 0xfe3d0, 0xfc8b1, 0xfbd30, 0xfc60d, 0xfe1e3, 0x0092c, 0x0303b, 0x04ab2, 0x04f5b, 0x03b53, 0x01350, 0xfe2a8, 0xfb81f, 0xfa174, 0xfa6ff, 0xfc8be,
+ 0xffdd5, 0x036d4, 0x0622f, 0x07195, 0x05e9d, 0x02d32, 0xfeae9, 0xfab52, 0xf8238, 0xf7d85, 0xfa0ad, 0xfe310, 0x03207, 0x0761d, 0x099fa, 0x09101, 0x05b91, 0x00783, 0xfaca0, 0xf65ea,
+ 0xf499f, 0xf6261, 0xfab80, 0x011b3, 0x0782e, 0x0c0b9, 0x0d485, 0x0ab24, 0x04d99, 0xfd470, 0xf6145, 0xf157b, 0xf08ad, 0xf419d, 0xfb3aa, 0x041a3, 0x0c550, 0x119b3, 0x1253d, 0x0e125,
+ 0x05bdc, 0xfb5dc, 0xf1998, 0xeb0a6, 0xe98ed, 0xedca7, 0xf6f50, 0x0303a, 0x0f22e, 0x18623, 0x1c671, 0x19fbb, 0x1158d, 0x041b8, 0xf4ea6, 0xe6e38, 0xdcf55, 0xd9485, 0xdcd8e, 0xe7549,
+ 0xf73b4, 0x0a398, 0x1da21, 0x2eec7, 0x3c1e2, 0x440c0, 0x466ea, 0x43ca0, 0x3d36f, 0x341bc, 0x29e6b, 0x1fd4d, 0x16cef, 0x0f5cd, 0x09ac4, 0x05a55, 0x03040, 0x0171e, 0x00999, 0x0033a,
+ 0x000be,
+ //
+ // FIR B coefficients
+ //
+ 0xffff5, 0x007c7, 0x00726, 0x00a22, 0x00db5, 0x011d6, 0x01676, 0x01b80, 0x020d4, 0x02648, 0x02baa, 0x030c4, 0x03557, 0x03924, 0x03be9, 0x03d69, 0x03d6c, 0x03bc5, 0x03854, 0x03309,
+ 0x02be4, 0x022fe, 0x01882, 0x00cb5, 0xfffec, 0xff294, 0xfe526, 0xfd82b, 0xfcc2f, 0xfc1c0, 0xfb967, 0xfb3a1, 0xfb0d7, 0xfb158, 0xfb556, 0xfbcdd, 0xfc7d4, 0xfd5f7, 0xfe6dc, 0xff9f0,
+ 0x00e7f, 0x023b7, 0x038af, 0x04c77, 0x05e19, 0x06ca8, 0x07750, 0x07d58, 0x07e34, 0x0798a, 0x06f3a, 0x05f66, 0x04a6d, 0x030f5, 0x013db, 0xff438, 0xfd34d, 0xfb280, 0xf9346, 0xf771b,
+ 0xf5f64, 0xf4d73, 0xf425a, 0xf3efb, 0xf43de, 0xf513f, 0xf66f2, 0xf8476, 0xfa8dd, 0xfd2ef, 0x00113, 0x03183, 0x06234, 0x09112, 0x0bbf5, 0x0e0d9, 0x0fdd1, 0x11149, 0x119ee, 0x116eb,
+ 0x107cf, 0x0ecbd, 0x0c64d, 0x095a8, 0x05c67, 0x01c9d, 0xfd8b2, 0xf935b, 0xf4f70, 0xf0fe0, 0xed781, 0xea8fe, 0xe86ae, 0xe7280, 0xe6de0, 0xe799f, 0xe95f0, 0xec252, 0xefda0, 0xf4606,
+ 0xf9922, 0xff404, 0x0535e, 0x0b38a, 0x110c8, 0x16749, 0x1b36d, 0x1f1d1, 0x21f8e, 0x23a37, 0x24019, 0x2302a, 0x20a3e, 0x1cee6, 0x17f93, 0x11e6e, 0x0ae61, 0x032e8, 0xfb00a, 0xf2a20,
+ 0xea5c4, 0xe2795, 0xdb421, 0xd4faa, 0xcfe13, 0xcc2ad, 0xca02a, 0xc9877, 0xcacbc, 0xcdd42, 0xd2982, 0xd901f, 0xe0efb, 0xea344, 0xf4996, 0xffe0c, 0x0bc6f, 0x1804f, 0x24528, 0x3068b,
+ 0x3c039, 0x46e45, 0x50d2f, 0x599f7, 0x61231, 0x67412, 0x6be71, 0x6f0ca, 0x70b3a, 0x70e72, 0x6fbac, 0x6d497, 0x69b45, 0x65213, 0x5fb93, 0x59a75, 0x53172, 0x4c336, 0x4524e, 0x3e116,
+ 0x371b3, 0x305ff, 0x29f8c, 0x23f9b, 0x1e71b, 0x196b1, 0x14eb4, 0x10f3e, 0x0d828, 0x0a91e, 0x081a1, 0x06117, 0x046cd, 0x03207, 0x02204, 0x01605, 0x00d56, 0x009c9
+};
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 DmicCommonFormatConfigSize = sizeof (DmicCommonFormatConfig);
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST UINT32 I2sFormatConfigRender[] = {0x0, 0xFFFFFF10, 0xFFFFFF32, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x83d00337, 0xc0700000, 0x0, 0x2010005, 0xf, 0xf, 0x4002, 0x4, 0x7070f00, 0x20, 0x1, 0x0 }; ///<config_Master TDM 24bit 48Khz 4 slot;
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 I2sFormatConfigRenderSize = sizeof (I2sFormatConfigRender);
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST UINT32 I2sFormatConfigCapture[] = {0x0, 0xFFFFFF10, 0x0,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x83d00337, 0xc0700000, 0x0, 0x2010005, 0xf, 0xf, 0x4002, 0x4, 0x7070f00, 0x20, 0x1, 0x0 }; ///<config_Master TDM 24bit 48Khz 4 slot;
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 I2sFormatConfigCaptureSize = sizeof (I2sFormatConfigCapture);
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST UINT32 I2sFormatConfigRender_Bxtp[] = { 0x0, 0xffffff10, 0xffffff32, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x83d00337, 0xc0700000, 0x0, 0x2010004, 0xf, 0xf, 0x4002, 0x4, 0x7070f00, 0x20, 0x220002, 0x2 }; ///<config_Master TDM 24bit 48Khz 4 slot;
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 I2sFormatConfigRenderSize_Bxtp = sizeof (I2sFormatConfigRender_Bxtp);
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST UINT32 I2sFormatConfigCapture_Bxtp[] = { 0x0, 0xffffff10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x83d00337, 0xc0700000, 0x0, 0x2010004, 0xf, 0xf, 0x4002, 0x4, 0x7070f00, 0x20, 0x220002, 0x2 }; ///<config_Master TDM 24bit 48Khz 4 slot;
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 I2sFormatConfigCaptureSize_Bxtp = sizeof (I2sFormatConfigCapture_Bxtp);
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+CONST UINT32 BtFormatConfig[] = {0xfffffff0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x80c095bf, 0xc0401dc0, 0x00000000, 0x02010005, 0x00000001, 0x00000001, 0x00004002, 0x00000000, 0x07020000, 0x00000030, 0x00000001, 0x00000000};
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 BtFormatConfigSize = sizeof (BtFormatConfig);
+
+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
+ 1, ///< 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
+ 1, ///< VirtualBusId
+ { 0 }, ///< EndpointConfig
+ { 0 } ///< FormatsConfig
+};
+
+ENDPOINT_DESCRIPTOR HdaEndpointI2sRenderSKP = {
+ 0, ///< EndpointDescriptorLength
+ HdaNhltLinkSsp, ///< LinkType
+ 1, ///< InstanceId
+ 0x8086, ///< HwVendorId
+ 0xae34, ///< HwDeviceId
+ 1, ///< HwRevisionId
+ 1, ///< HwSubsystemId
+ HdaNhltDeviceI2s, ///< DeviceType
+ 0, ///< Direction
+ 0, ///< VirtualBusId
+ { 0 }, ///< EndpointConfig
+ { 0 } ///< FormatsConfig
+};
+
+ENDPOINT_DESCRIPTOR HdaEndpointI2sRenderHP = {
+ 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
+ENDPOINT_DESCRIPTOR HdaEndpointModem1Render = {
+ 0, ///< EndpointDescriptorLength
+ HdaNhltLinkSsp, ///< LinkType
+ 1, ///< InstanceId
+ 0x8086, ///< HwVendorId
+ 0x7260, ///< HwDeviceId
+ 1, ///< HwRevisionId
+ 1, ///< HwSubsystemId
+ HdaNhltDeviceI2s, ///< DeviceType
+ 0, ///< Direction
+ 0, ///< VirtualBusId
+ { 0 }, ///< EndpointConfig
+ { 0 } ///< FormatsConfig
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+ENDPOINT_DESCRIPTOR HdaEndpointModem1Capture = {
+ 0, ///< EndpointDescriptorLength
+ HdaNhltLinkSsp, ///< LinkType
+ 1, ///< InstanceId
+ 0x8086, ///< HwVendorId
+ 0x7360, ///< HwDeviceId
+ 1, ///< HwRevisionId
+ 1, ///< HwSubsystemId
+ HdaNhltDeviceI2s, ///< DeviceType
+ 1, ///< Direction
+ 0, ///< VirtualBusId
+ { 0 }, ///< EndpointConfig
+ { 0 } ///< FormatsConfig
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+ENDPOINT_DESCRIPTOR HdaEndpointModem2Render = {
+ 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 HdaEndpointModem2Capture = {
+ 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 DmicX2Config[] = { 0x00, 0x01, 0x0A };
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 DmicX2ConfigSize = sizeof (DmicX2Config);
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 DmicX4Config[] = { 0x00, 0x01, 0x0D };
+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 I2sConfig[] = {0};
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 I2sConfigSize = 0;
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 I2sConfigSKP[] = {1};
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 I2sConfigSKPSize = 1;
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 Modem1Config[] = {0};
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 Modem1ConfigSize = 0;
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 Modem2Config[] = {0};
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 Modem2ConfigSize = 0;
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 NhltConfiguration[] = { 0xEFBEADDE };
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 NhltConfigurationSize = sizeof (NhltConfiguration);
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/Private/DxeScHdaLib/ScHdaLib.c b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/Private/DxeScHdaLib/ScHdaLib.c
new file mode 100644
index 0000000000..e27b38ddab
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/Private/DxeScHdaLib/ScHdaLib.c
@@ -0,0 +1,807 @@
+/** @file
+ SC HD Audio Library implementation.
+
+ Copyright (c) 2014 - 2016, 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.
+
+**/
+
+#include <Uefi/UefiBaseType.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PcdLib.h>
+#include <Private/Library/ScHdaLib.h>
+#include <Library/ScPlatformLib.h>
+#include <Library/SteppingLib.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_INFO, " Format->FormatConfiguration.Capabilities:"));
+ for (i = 0; i < ( Format->FormatConfiguration.CapabilitiesSize ) ; i++) {
+ if(i % 16 == 0) DEBUG ((DEBUG_INFO, "\n"));
+ DEBUG ((DEBUG_INFO, "0x%02x, ", Format->FormatConfiguration.Capabilities[i]));
+ }
+ DEBUG ((DEBUG_INFO, "\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_INFO, " Endpoint->EndpointConfig.Capabilities:"));
+ for (i = 0; i < (Endpoint->EndpointConfig.CapabilitiesSize ) ; i++) {
+ if (i % 16 == 0) DEBUG ((DEBUG_INFO, "\n"));
+ DEBUG ((DEBUG_INFO, "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);
+ NhltFormatDump (Format);
+ }
+
+ DEBUG ((DEBUG_INFO, "\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_INFO, " OedConfig->Capabilities:"));
+ for (i = 0; i < (OedConfig->CapabilitiesSize) ; i++) {
+ if(i % 16 == 0) DEBUG ((DEBUG_INFO, "\n"));
+ DEBUG ((DEBUG_INFO, "0x%02x, ", OedConfig->Capabilities[i]));
+ }
+
+ DEBUG ((DEBUG_INFO, "\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
+ )
+{
+
+ 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"));
+}
+
+
+/**
+ 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,
+ IN NHLT_ENDPOINT EndpointType
+ )
+{
+ 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_2CH_48KHZ_16BIT_FORMAT) {
+ DEBUG ((DEBUG_INFO, "Format: B_HDA_2CH_48KHZ_16BIT_FORMAT\n"));
+
+ Format = GetNhltEndpointFormat (Endpoint, FormatIndex++);
+ if (Format != NULL){
+ CopyMem (&(Format->Format), &Ch2_48kHz16bitFormat, sizeof (WAVEFORMATEXTENSIBLE));
+
+ Format->FormatConfiguration.CapabilitiesSize = DmicFormatConfigSize + DmicCommonFormatConfigSize;
+ CopyMem (Format->FormatConfiguration.Capabilities, DmicStereo16BitFormatConfig, DmicFormatConfigSize);
+ CopyMem ((Format->FormatConfiguration.Capabilities + DmicFormatConfigSize), DmicCommonFormatConfig, DmicCommonFormatConfigSize);
+
+ FormatsConfigLength += sizeof (*Format)
+ - sizeof (Format->FormatConfiguration.Capabilities)
+ + Format->FormatConfiguration.CapabilitiesSize;
+ FormatsConfig->FormatsCount++;
+ }
+ }
+
+ if (FormatsBitmask & B_HDA_2CH_48KHZ_24BIT_FORMAT) {
+ DEBUG ((DEBUG_INFO, "Format: B_HDA_2CH_48KHZ_24BIT_FORMAT\n"));
+
+ Format = GetNhltEndpointFormat (Endpoint, FormatIndex++);
+ if (Format != NULL){
+ CopyMem (&(Format->Format), &Ch2_48kHz24bitFormat, sizeof (WAVEFORMATEXTENSIBLE));
+ if ((EndpointType == HdaI2sRenderHP) || (EndpointType == HdaI2sRenderSKP)){
+ //
+ // For BXT-P, [HSD 1206654234]: Audio: BIOS I2S blobs need to change for proper I2S render and capture
+ //
+ if (GetBxtSeries() == BxtP) {
+ Format->FormatConfiguration.CapabilitiesSize = I2sFormatConfigRenderSize_Bxtp;
+ CopyMem(Format->FormatConfiguration.Capabilities, I2sFormatConfigRender_Bxtp, I2sFormatConfigRenderSize_Bxtp);
+ DEBUG ((DEBUG_INFO, "For BXT-P, Audio: BIOS I2S blobs need to change for proper I2S render and capture.\n"));
+ } else {
+ Format->FormatConfiguration.CapabilitiesSize = I2sFormatConfigRenderSize;
+ CopyMem(Format->FormatConfiguration.Capabilities, I2sFormatConfigRender, I2sFormatConfigRenderSize);
+ }
+ } else if ((EndpointType == HdaI2sCaptureHP) || (EndpointType == HdaI2sCaptureSKP) ){
+ //
+ // For BXT-P, [HSD 1206654234]: Audio: BIOS I2S blobs need to change for proper I2S render and capture
+ //
+ if (GetBxtSeries() == BxtP) {
+ Format->FormatConfiguration.CapabilitiesSize = I2sFormatConfigCaptureSize_Bxtp;
+ CopyMem(Format->FormatConfiguration.Capabilities, I2sFormatConfigCapture_Bxtp, I2sFormatConfigCaptureSize_Bxtp);
+ DEBUG ((DEBUG_INFO, "For BXT-P, Audio: BIOS I2S blobs need to change for proper I2S render and capture.\n"));
+ } else {
+ Format->FormatConfiguration.CapabilitiesSize = I2sFormatConfigCaptureSize;
+ CopyMem(Format->FormatConfiguration.Capabilities, I2sFormatConfigCapture, I2sFormatConfigCaptureSize);
+ }
+ }
+ FormatsConfigLength += sizeof (*Format)
+ - sizeof (Format->FormatConfiguration.Capabilities)
+ + Format->FormatConfiguration.CapabilitiesSize;
+ FormatsConfig->FormatsCount++;
+ }
+ }
+
+ if (FormatsBitmask & B_HDA_2CH_48KHZ_32BIT_FORMAT) {
+ DEBUG ((DEBUG_INFO, "Format: B_HDA_2CH_48KHZ_32BIT_FORMAT\n"));
+
+ Format = GetNhltEndpointFormat (Endpoint, FormatIndex++);
+ if (Format != NULL) {
+ CopyMem (&(Format->Format), &Ch2_48kHz32bitFormat, sizeof (WAVEFORMATEXTENSIBLE));
+
+ Format->FormatConfiguration.CapabilitiesSize = DmicFormatConfigSize + DmicCommonFormatConfigSize;
+ CopyMem (Format->FormatConfiguration.Capabilities, DmicStereo32BitFormatConfig, DmicFormatConfigSize);
+ CopyMem ((Format->FormatConfiguration.Capabilities + DmicFormatConfigSize), DmicCommonFormatConfig, DmicCommonFormatConfigSize);
+
+ FormatsConfigLength += sizeof (*Format)
+ - sizeof (Format->FormatConfiguration.Capabilities)
+ + Format->FormatConfiguration.CapabilitiesSize;
+ FormatsConfig->FormatsCount++;
+ }
+ }
+
+ if (FormatsBitmask & B_HDA_4CH_48KHZ_16BIT_FORMAT) {
+ DEBUG ((DEBUG_INFO, "Format: B_HDA_4CH_48KHZ_16BIT_FORMAT\n"));
+
+ Format = GetNhltEndpointFormat (Endpoint, FormatIndex++);
+ if (Format != NULL){
+ CopyMem (&(Format->Format), &Ch4_48kHz16bitFormat, sizeof (WAVEFORMATEXTENSIBLE));
+
+ Format->FormatConfiguration.CapabilitiesSize = DmicFormatConfigSize + DmicCommonFormatConfigSize;
+ CopyMem (Format->FormatConfiguration.Capabilities, DmicQuad16BitFormatConfig, DmicFormatConfigSize);
+ CopyMem ((Format->FormatConfiguration.Capabilities + DmicFormatConfigSize), DmicCommonFormatConfig, DmicCommonFormatConfigSize);
+
+ FormatsConfigLength += sizeof (*Format)
+ - sizeof (Format->FormatConfiguration.Capabilities)
+ + Format->FormatConfiguration.CapabilitiesSize;
+ FormatsConfig->FormatsCount++;
+ }
+ }
+
+ if (FormatsBitmask & B_HDA_4CH_48KHZ_32BIT_FORMAT) {
+ DEBUG ((DEBUG_INFO, "Format: B_HDA_4CH_48KHZ_32BIT_FORMAT\n"));
+
+ Format = GetNhltEndpointFormat (Endpoint, FormatIndex++);
+ if (Format != NULL){
+ CopyMem (&(Format->Format), &Ch4_48kHz32bitFormat, sizeof (WAVEFORMATEXTENSIBLE));
+
+ Format->FormatConfiguration.CapabilitiesSize = DmicFormatConfigSize + DmicCommonFormatConfigSize;
+ CopyMem (Format->FormatConfiguration.Capabilities, DmicQuad32BitFormatConfig, DmicFormatConfigSize);
+ CopyMem ((Format->FormatConfiguration.Capabilities + DmicFormatConfigSize), DmicCommonFormatConfig, DmicCommonFormatConfigSize);
+
+ FormatsConfigLength += sizeof (*Format)
+ - sizeof (Format->FormatConfiguration.Capabilities)
+ + Format->FormatConfiguration.CapabilitiesSize;
+ FormatsConfig->FormatsCount++;
+ }
+ }
+
+ if (FormatsBitmask & B_HDA_NARROWBAND_FORMAT) {
+ DEBUG ((DEBUG_INFO, "Format: B_HDA_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_WIDEBAND_FORMAT) {
+ DEBUG ((DEBUG_INFO, "Format: B_HDA_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_A2DP_FORMAT) {
+ DEBUG ((DEBUG_INFO, "Format: B_HDA_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++;
+ }
+ }
+
+ 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] 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 UINT8 EndpointIndex
+ )
+{
+
+ ENDPOINT_DESCRIPTOR *Endpoint;
+ SPECIFIC_CONFIG *EndpointConfig;
+ CONST UINT8 *EndpointConfigBuffer;
+ UINT32 EndpointConfigBufferSize;
+ UINT32 EndpointFormatsBitmask;
+ UINT32 EndpointDescriptorLength;
+
+ DEBUG ((DEBUG_INFO, "NhltEndpointConstructor() Start, EndpointIndex = %d\n", EndpointIndex));
+
+ EndpointDescriptorLength = 0;
+ Endpoint = GetNhltEndpoint (NhltTable, EndpointIndex);
+ EndpointDescriptorLength = sizeof (ENDPOINT_DESCRIPTOR)
+ - sizeof (SPECIFIC_CONFIG)
+ - sizeof (FORMAT_CONFIG);
+
+ switch (EndpointType) {
+ case HdaDmicX2:
+ DEBUG ((DEBUG_INFO, "Endpoint: HdaDmicX2\n"));
+ CopyMem (Endpoint, &HdaEndpointDmicX2, sizeof (ENDPOINT_DESCRIPTOR));
+ EndpointConfigBuffer = DmicX2Config;
+ EndpointConfigBufferSize = DmicX2ConfigSize;
+ EndpointFormatsBitmask = B_HDA_2CH_48KHZ_16BIT_FORMAT | B_HDA_2CH_48KHZ_32BIT_FORMAT;
+ break;
+ case HdaDmicX4:
+ DEBUG ((DEBUG_INFO, "Endpoint: HdaDmicX4\n"));
+ CopyMem (Endpoint, &HdaEndpointDmicX4, sizeof (ENDPOINT_DESCRIPTOR));
+ EndpointConfigBuffer = DmicX4Config;
+ EndpointConfigBufferSize = DmicX4ConfigSize;
+ EndpointFormatsBitmask = B_HDA_4CH_48KHZ_16BIT_FORMAT | B_HDA_4CH_48KHZ_32BIT_FORMAT;
+ break;
+ case HdaBtRender:
+ DEBUG ((DEBUG_INFO, "Endpoint: HdaBtRender\n"));
+ if (GetBxtSeries() == BxtP) {
+ HdaEndpointBtRender.VirtualBusId = 2;
+ DEBUG ((DEBUG_INFO, "For BXT-P, HdaEndpointBtRender.VirtualBusId Change to 0x%02x.\n", HdaEndpointBtRender.VirtualBusId));
+ }
+ CopyMem (Endpoint, &HdaEndpointBtRender, sizeof (ENDPOINT_DESCRIPTOR));
+ EndpointConfigBuffer = BtConfig;
+ EndpointConfigBufferSize = BtConfigSize;
+ EndpointFormatsBitmask = B_HDA_NARROWBAND_FORMAT | B_HDA_WIDEBAND_FORMAT | B_HDA_A2DP_FORMAT;
+ break;
+ case HdaBtCapture:
+ DEBUG ((DEBUG_INFO, "Endpoint: HdaBtCapture\n"));
+ if (GetBxtSeries() == BxtP) {
+ HdaEndpointBtCapture.VirtualBusId = 2;
+ DEBUG ((DEBUG_INFO, "For BXT-P, HdaEndpointBtCapture.VirtualBusId Change to 0x%02x.\n", HdaEndpointBtCapture.VirtualBusId));
+ }
+ CopyMem (Endpoint, &HdaEndpointBtCapture, sizeof (ENDPOINT_DESCRIPTOR));
+ EndpointConfigBuffer = BtConfig;
+ EndpointConfigBufferSize = BtConfigSize;
+ EndpointFormatsBitmask = B_HDA_NARROWBAND_FORMAT | B_HDA_WIDEBAND_FORMAT;
+ break;
+ case HdaI2sRenderSKP:
+ DEBUG ((DEBUG_INFO, "Endpoint: HdaI2sRenderSKP\n"));
+ //
+ // For BXT-P, Virtual Bus ID is 5, while it is 0 for BXTM
+ //
+ if (GetBxtSeries() == BxtP) {
+ HdaEndpointI2sRenderSKP.VirtualBusId = 5;
+ DEBUG ((DEBUG_INFO, "For BXT-P, Endpoint: HdaI2sRenderSKP virtual bus ID is 5.\n"));
+ }
+ CopyMem (Endpoint, &HdaEndpointI2sRenderSKP, sizeof (ENDPOINT_DESCRIPTOR));
+ EndpointConfigBuffer = I2sConfigSKP;
+ EndpointConfigBufferSize = I2sConfigSKPSize;
+ EndpointFormatsBitmask = B_HDA_2CH_48KHZ_24BIT_FORMAT;
+ break;
+ case HdaI2sCaptureSKP:
+ DEBUG ((DEBUG_INFO, "Endpoint: HdaI2sCaptureSKP\n"));
+ CopyMem (Endpoint, &HdaEndpointI2sCapture, sizeof (ENDPOINT_DESCRIPTOR));
+ EndpointConfigBuffer = I2sConfig;
+ EndpointConfigBufferSize = I2sConfigSize;
+ EndpointFormatsBitmask = B_HDA_2CH_48KHZ_24BIT_FORMAT;
+ break;
+ case HdaI2sRenderHP:
+ DEBUG ((DEBUG_INFO, "Endpoint: HdaI2sRenderHP\n"));
+ //
+ // For BXT-P, Virtual Bus ID is 5, while it is 0 for BXTM
+ //
+ if (GetBxtSeries() == BxtP) {
+ HdaEndpointI2sRenderHP.VirtualBusId = 5;
+ DEBUG ((DEBUG_INFO, "For BXT-P, Endpoint: HdaI2sRenderHP virtual bus ID is 5.\n"));
+ }
+ CopyMem (Endpoint, &HdaEndpointI2sRenderHP, sizeof (ENDPOINT_DESCRIPTOR));
+ EndpointConfigBuffer = I2sConfig;
+ EndpointConfigBufferSize = I2sConfigSize;
+ EndpointFormatsBitmask = B_HDA_2CH_48KHZ_24BIT_FORMAT;
+ break;
+ case HdaI2sCaptureHP:
+ DEBUG ((DEBUG_INFO, "Endpoint: HdaI2sCaptureHP\n"));
+ //
+ // For BXT-P, Virtual Bus ID is 5, while it is 0 for BXTM
+ //
+ if (GetBxtSeries() == BxtP) {
+ HdaEndpointI2sCapture.VirtualBusId = 5;
+ DEBUG ((DEBUG_INFO, "For BXT-P, Endpoint: HdaI2sCaptureHP virtual bus ID is 5.\n"));
+ }
+ CopyMem (Endpoint, &HdaEndpointI2sCapture, sizeof (ENDPOINT_DESCRIPTOR));
+ EndpointConfigBuffer = I2sConfig;
+ EndpointConfigBufferSize = I2sConfigSize;
+ EndpointFormatsBitmask = B_HDA_2CH_48KHZ_24BIT_FORMAT;
+ break;
+ case HdaModem1Render:
+ DEBUG ((DEBUG_INFO, "Endpoint: HdaModem1Render\n"));
+ CopyMem (Endpoint, &HdaEndpointModem1Render, sizeof (ENDPOINT_DESCRIPTOR));
+ EndpointConfigBuffer = Modem1Config;
+ EndpointConfigBufferSize = Modem1ConfigSize;
+ EndpointFormatsBitmask = B_HDA_2CH_48KHZ_24BIT_FORMAT;
+ break;
+ case HdaModem1Capture:
+ DEBUG ((DEBUG_INFO, "Endpoint: HdaModem1Capture\n"));
+ CopyMem (Endpoint, &HdaEndpointModem1Capture, sizeof (ENDPOINT_DESCRIPTOR));
+ EndpointConfigBuffer = Modem1Config;
+ EndpointConfigBufferSize = Modem1ConfigSize;
+ EndpointFormatsBitmask = B_HDA_2CH_48KHZ_24BIT_FORMAT;
+ break;
+ case HdaModem2Render:
+ DEBUG ((DEBUG_INFO, "Endpoint: HdaModem2Render\n"));
+ CopyMem (Endpoint, &HdaEndpointModem2Render, sizeof (ENDPOINT_DESCRIPTOR));
+ EndpointConfigBuffer = Modem2Config;
+ EndpointConfigBufferSize = Modem2ConfigSize;
+ EndpointFormatsBitmask = B_HDA_2CH_48KHZ_24BIT_FORMAT;
+ break;
+ case HdaModem2Capture:
+ DEBUG ((DEBUG_INFO, "Endpoint: HdaModem2Capture\n"));
+ CopyMem (Endpoint, &HdaEndpointModem2Capture, sizeof (ENDPOINT_DESCRIPTOR));
+ EndpointConfigBuffer = Modem2Config;
+ EndpointConfigBufferSize = Modem2ConfigSize;
+ EndpointFormatsBitmask = B_HDA_2CH_48KHZ_24BIT_FORMAT;
+ 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,EndpointType);
+ 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 SC_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 = SC_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, 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/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/Private/PeiDxeSmmScPciExpressHelpersLib/PeiDxeSmmScPciExpressHelpersLib.inf b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/Private/PeiDxeSmmScPciExpressHelpersLib/PeiDxeSmmScPciExpressHelpersLib.inf
new file mode 100644
index 0000000000..e22dc3abbc
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/Private/PeiDxeSmmScPciExpressHelpersLib/PeiDxeSmmScPciExpressHelpersLib.inf
@@ -0,0 +1,45 @@
+## @file
+# PeiDxeSmmPchPciExpressHelpersLib.
+#
+# Copyright (c) 2008 - 2016, 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 = PeiDxeSmmPchPciExpressHelpersLib
+ FILE_GUID = 07E3F76D-6D26-419d-9053-58696A15B519
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PeiDxeSmmScPciExpressHelpersLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ ScPciExpressHelpersLibrary.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ BroxtonSiPkg/BroxtonSiPrivate.dec
+ BroxtonSiPkg/BroxtonSiPkg.dec
+
+[LibraryClasses]
+ IoLib
+ DebugLib
+ ScPlatformLib
+ SideBandLib
+ SteppingLib
+
+ [Pcd]
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/Private/PeiDxeSmmScPciExpressHelpersLib/ScPciExpressHelpersLibrary.c b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/Private/PeiDxeSmmScPciExpressHelpersLib/ScPciExpressHelpersLibrary.c
new file mode 100644
index 0000000000..44b62db3ff
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/Private/PeiDxeSmmScPciExpressHelpersLib/ScPciExpressHelpersLibrary.c
@@ -0,0 +1,2096 @@
+/** @file
+ This file contains routines that support PCI Express initialization.
+
+ Copyright (c) 1999 - 2016, 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.
+
+**/
+
+#include "ScPciExpressHelpersLibrary.h"
+
+//
+// Tpower-on Scale
+//
+GLOBAL_REMOVE_IF_UNREFERENCED const UINT8 mPcieL1sTposMultiplier[] = {2, 10, 100};
+GLOBAL_REMOVE_IF_UNREFERENCED const UINT8 mPclkdL1trefCfg[] = {0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 60, 70, 80, 90, 100};
+
+/**
+ 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);
+#ifdef EFI_DEBUG
+ DEBUG ((DEBUG_INFO,"PcieFindCapId () BDF %0x: %0x :%0x, CapId = %0x \n", Bus, Device, Function, CapId));
+#endif
+ 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
+ @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 != DEVICE_ID_NOCARE) {
+ 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 function returns PID according to Root Port Number
+
+ @param[in] RpPort Root Port Number
+
+ @retval SC_SBI_PID Returns PID for SBI Access
+
+**/
+SC_SBI_PID
+GetRpSbiPid (
+ IN UINTN RpPort
+ )
+{
+ if (RpPort < 2) {
+ return 0xB3;
+ } else {
+ return 0xB4;
+ }
+}
+
+
+/**
+ This function reads Pci Config register via SBI Access
+
+ @param[in] RpDevice Root Port Device Number
+ @param[in] RpPort Root Port Number
+ @param[in] Offset Offset of Config register
+ @param[out] Data32 Value of Config register
+
+ @retval EFI_SUCCESS SBI Read successful.
+
+**/
+EFI_STATUS
+PchSbiRpPciRead32 (
+ IN UINTN RpDevice,
+ IN UINTN RpPort,
+ IN UINTN Offset,
+ OUT UINT32 *Data32
+ )
+{
+ EFI_STATUS Status;
+ UINT8 Response;
+ UINT16 Fid;
+
+ if (RpPort < 2) {
+ Fid = (UINT16) ((RpDevice << 3) | RpPort);
+ } else {
+ Fid = (UINT16) ((RpDevice << 3) | (RpPort - 2 ));
+ }
+ Status = PchSbiExecutionEx (
+ GetRpSbiPid (RpPort),
+ Offset,
+ PciConfigRead,
+ FALSE,
+ 0xF,
+ 0,
+ Fid,
+ Data32,
+ &Response
+ );
+ if (Status != EFI_SUCCESS) {
+ DEBUG ((DEBUG_ERROR,"Side band Read Failed\n"));
+ }
+ return Status;
+}
+
+
+/**
+ This function And then Or Pci Config register via SBI Access
+
+ @param[in] RpDevice Root Port Device Number
+ @param[in] RpPort Root Port Number
+ @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 UINTN RpDevice,
+ IN UINTN RpPort,
+ IN UINTN Offset,
+ IN UINT32 Data32And,
+ IN UINT32 Data32Or
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Data32;
+ UINT8 Response;
+ UINT16 Fid;
+
+ Status = PchSbiRpPciRead32 (RpDevice, RpPort, Offset, &Data32);
+ if (Status == EFI_SUCCESS) {
+ Data32 &= Data32And;
+ Data32 |= Data32Or;
+ if (RpPort < 2) {
+ Fid = (UINT16) ((RpDevice << 3) | RpPort);
+ } else {
+ Fid = (UINT16) ((RpDevice << 3) | (RpPort - 2 ));
+ }
+ Status = PchSbiExecutionEx (
+ GetRpSbiPid (RpPort),
+ Offset,
+ PciConfigWrite,
+ FALSE,
+ 0xF,
+ 0,
+ Fid,
+ &Data32,
+ &Response
+ );
+ if (Status != EFI_SUCCESS) {
+ DEBUG ((DEBUG_ERROR, "Side band Write Failed\n"));
+ }
+ }
+
+ return Status;
+}
+
+
+/**
+ This function returns the maximum number of ClkReq signals available
+
+ @retval UINT8 Returns maximum number of ClkReq signals
+
+**/
+UINT8
+GetClkReqMax ()
+{
+ return SC_PCIE_MAX_CLK_REQ;
+}
+
+
+/**
+ 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;
+
+ if (GetBxtSeries () == BxtP) {
+ if (PortIndex < 2) {
+ PortIndex += 4;
+ } else {
+ PortIndex -= 2;
+ }
+ }
+ PchPcrRead8 (0xB0, 0x100 + (PortIndex / 2), &ClkReqNum);
+ if (PortIndex % 2 == 0) {
+ ClkReqNum &= 0x0F;
+ } else {
+ ClkReqNum = ClkReqNum >> 4;
+ }
+
+ return ClkReqNum;
+}
+
+
+/**
+ This function assigns a ClkReq signal to Pcie ports and returns updated ClkReq Number
+
+ @param[in] PcieConfig PCH Pcie Configuration
+ @param[in] PortIndex PCIe Port Number (Zero Base)
+
+ @retval EFI_SUCCESS Successfully set ClkReq Number to Root Port
+
+**/
+EFI_STATUS
+SetPortClkReqNumber (
+ IN SC_PCIE_CONFIG *PcieConfig,
+ IN UINT8 PortIndex
+ )
+{
+#ifdef EFI_DEBUG
+ UINT32 Drcrm1;
+#endif
+ EFI_STATUS Status;
+ UINT8 ClkReqNum;
+
+ Status = EFI_SUCCESS;
+
+ ClkReqNum = (UINT8) PcieConfig->RootPort[PortIndex].ClkReqNumber;
+ //
+ // CLKREQ to Root Port Mapping
+ // The mapping of the PCIeExpress Ports to the CLKREQ# pins can be
+ // specified through the DRCRM{x} registers
+ //
+ if (GetBxtSeries () == BxtP) {
+ if (PortIndex < 2) {
+ PortIndex += 4;
+ } else {
+ PortIndex -= 2;
+ }
+ }
+ if (PortIndex % 2 == 0) {
+ PchPcrAndThenOr8 (0xB0, 0x100 + (PortIndex / 2), 0xF0, ClkReqNum);
+ } else {
+ PchPcrAndThenOr8 (0xB0, 0x100 + (PortIndex / 2), 0x0F, (ClkReqNum) << 4);
+ }
+#ifdef EFI_DEBUG
+ PchPcrRead32 (0xB0, 0x100, &Drcrm1);
+ DEBUG ((DEBUG_INFO, "AssignClkReq = %0x\n", Drcrm1));
+#endif
+
+ return Status;
+}
+
+
+/**
+ 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
+
+ @retval 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;
+ EFI_STATUS Status;
+ 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) {
+ Status = EFI_UNSUPPORTED;
+ } else {
+ Status = EFI_SUCCESS;
+ }
+ //
+ // 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 Status;
+}
+
+
+/**
+ This function checks whether PHY lane power gating is enable on the port.
+
+ @param[in] RpBase Root Port base address
+
+ @retval TRUE PHY power gating is enabled
+ @retval FALSE PHY power gating disabled
+
+**/
+STATIC
+BOOLEAN
+PcieIsPhyLanePgEnabled (
+ IN UINTN RpBase
+ )
+{
+ UINT32 Data32;
+
+ Data32 = MmioRead32 (RpBase + 0x420);
+ return (Data32 & BIT30) != 0;
+}
+
+
+/**
+ 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 (offset 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 (offset 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) != DEVICE_ID_NOCARE) {
+ //
+ // 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)~(BIT7 | BIT6 | BIT5),
+ *MaxPayload << 5
+ );
+ } 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
+
+ @retval 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
+ )
+{
+ return 0;
+}
+
+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 SC_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 & ScPcieL1L2Override) == ScPcieL1L2Override) &&
+ ((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))) {
+ *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[in, out] EndPointL1SubStateCapOffset Pointer to L1 Substate Capability Structure
+ @param[in, out] EndPointL1SubStateCapMask L1 Substate Capability Mask
+
+ @retval None
+
+**/
+
+VOID GetOverrideL1sCapOffset (
+ IN UINTN EndPointBase,
+ IN UINT32 NumOfDevAspmOverride,
+ IN CONST SC_PCIE_DEVICE_OVERRIDE *DevAspmOverride,
+ IN UINT16 EndPointVendorId,
+ IN UINT16 EndPointDeviceId,
+ IN UINT8 EndPointRevId,
+ IN OUT UINT16* EndPointL1SubStateCapOffset,
+ IN OUT UINT32* EndPointL1SubStateCapMask
+ )
+{
+ UINT8 PcieDeviceIndex;
+
+ //
+ // Get the endpoint supports L1 Substates Capabilities from Override Table
+ //
+ for (PcieDeviceIndex = 0; PcieDeviceIndex < NumOfDevAspmOverride; PcieDeviceIndex++) {
+ if (((DevAspmOverride[PcieDeviceIndex].OverrideConfig & ScPcieL1SubstatesOverride) == ScPcieL1SubstatesOverride) &&
+ (EndPointVendorId == DevAspmOverride[PcieDeviceIndex].VendorId) &&
+ (EndPointDeviceId == DevAspmOverride[PcieDeviceIndex].DeviceId) &&
+ ((EndPointRevId == DevAspmOverride[PcieDeviceIndex].RevId) ||
+ (DevAspmOverride[PcieDeviceIndex].RevId == 0xFF))) {
+
+ if ((EndPointVendorId == V_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;
+ break;
+ }
+ }
+}
+
+
+/**
+ This function configures the L1 Substates.
+ It can be used for Rootport and endpoint devices.
+
+ @param[in] RootPortConfig Rootport PCI Express Configuration
+ @param[in] Bus Rootport/Endpoint Bus Number
+ @param[in] Device Rootport/Endpoint Device Number
+ @param[in] Function Rootport/Endpoint Function Number
+ @param[in] EndPointL1SubStateCapOffset Pointer to L1 Substate Capability Structure
+ @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 const SC_PCIE_ROOT_PORT_CONFIG* RootPortConfig,
+ IN UINT8 Bus,
+ IN UINT8 Device,
+ IN UINT8 Function,
+ IN UINTN DeviceBase,
+ IN UINT16 L1SubstateExtCapOffset,
+ IN UINT32 PortCommonModeRestoreTime,
+ IN UINT32 PortTpowerOnValue,
+ IN UINT32 PortTpowerOnScale
+ )
+{
+ UINT32 Data32Or;
+ UINT32 Data32;
+ UINT32 Tpoweron;
+ UINT8 ClkReqNum;
+ UINTN PortIndex;
+
+ //
+ // Step 6
+ // a. Set L1 Sub-States Extended Capability Offset + 0x08[4:0] to 01111b for both Pcie root port and device
+ //
+ Data32Or = (BIT3 | BIT2 | BIT1 | BIT0);
+ if (RootPortConfig->L1Substates == ScPcieL1SubstatesL1_1) {
+ Data32Or &= (UINT32) ~(BIT0);
+ }
+ if (RootPortConfig->L1Substates == ScPcieL1SubstatesL1_2) {
+ Data32Or &= (UINT32) ~(BIT1);
+ }
+ MmioAndThenOr32 (
+ DeviceBase + L1SubstateExtCapOffset + R_PCIE_EX_L1SCTL1_OFFSET,
+ (UINT32) ~(BIT4 | BIT3 | BIT2 | BIT1 | BIT0),
+ Data32Or
+ );
+ //
+ // 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
+ );
+ //
+ // 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)
+ );
+
+ //
+ // If Root port,
+ //
+ if (Bus == DEFAULT_PCI_BUS_NUMBER_SC) {
+ GetScPcieRpNumber (Device, Function, &PortIndex);
+ ClkReqNum = GetPortClkReqNumber ((UINT8) PortIndex);
+ //
+ // f. Set Dxx:Fn:420h[0] to 1b prior to L1 enabling
+ //
+ MmioOr32 (DeviceBase + 0x420, BIT0);
+ //
+ // g. Set PCR[PCLKD] +1010h[23:0] to a value (in time unit) bigger than Tpoweron from step c.
+ // For the hotplug port but empty, set it to 45us just in case SMI is not enabled to handle this.
+ //
+ Tpoweron = PortTpowerOnValue * mPcieL1sTposMultiplier[PortTpowerOnScale];
+ Data32 = 0;
+ if ((MmioRead16 (DeviceBase + R_PCH_PCIE_SLSTS) & B_PCIE_SLSTS_PDS) != 0) {
+ while ((Tpoweron > mPclkdL1trefCfg[Data32]) && (Data32 < 15)) {
+ Data32++;
+ }
+ } else {
+ Data32 = 9;
+ }
+ Data32 = (Data32 << (4 * ClkReqNum));
+ SideBandAndThenOr32 (0xB6, 0x1010, ~0u, Data32);
+ }
+}
+
+
+/**
+ 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
+
+ @retval None
+
+**/
+VOID GetLtrOverride (
+ IN UINT32 NumOfDevAspmOverride,
+ IN CONST SC_PCIE_DEVICE_OVERRIDE *DevAspmOverride,
+ IN UINT16 EndPointVendorId,
+ IN UINT16 EndPointDeviceId,
+ IN UINT8 EndPointRevId,
+ IN OUT UINT32 *LtrOverrideVal
+ )
+{
+ 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 & ScPcieLtrOverride) == ScPcieLtrOverride) &&
+ (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;
+ 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 SC_PCIE_ROOT_PORT_CONFIG* RootPortConfig,
+ IN UINT8 EndPointBus,
+ IN UINT8 EndPointDevice,
+ IN UINT8 EndPointFunction,
+ IN UINTN EndPointBase,
+ IN UINT8 EndPointPcieCapOffset,
+ IN UINT32 DeviceCapabilities2,
+ IN UINT32* LtrOverrideVal
+ )
+{
+ UINT32 Data32;
+ UINT16 Data16;
+ UINT16 LtrExtendedCapOffset;
+ UINT16 DefaultMaxLatency;
+
+ DefaultMaxLatency = 0;
+
+ //
+ // Step 3
+ // If Endpoint device supports LTR, Device Capabilities 2 Register Offset 24h [11] = 1b,
+ //
+ if ((DeviceCapabilities2 & B_PCIE_DCAP2_LTRMS) && (RootPortConfig->LtrEnable == TRUE)) {
+ //
+ // 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;
+ //
+ // 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);
+ //
+ // 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] 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[in] PolicyRevision Policy revision for codes compatibility
+
+ @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 SC_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 *PortCommonModeRestoreTime,
+ IN OUT UINT32 *PortTpowerOnValue,
+ IN OUT UINT32 *PortTpowerOnScale,
+ IN CONST SC_PCIE_ROOT_PORT_CONFIG *RootPortConfig,
+ IN OUT BOOLEAN *AspmOverride,
+ IN BOOLEAN *ClkreqPerPortSupported,
+ IN OUT BOOLEAN *RpAndEndPointsLtrSupported,
+ IN UINT8 PolicyRevision
+ )
+{
+ 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 RootDeviceL1Substates;
+ UINT32 EndPointL1Substates;
+ UINT8 EndPointPortCommonModeRestoreTime;
+ UINT8 EndPointTpowerOnScale;
+ UINT8 EndPointTpowerOnValue;
+ UINT32 Multiplier[4] = {2, 10, 100, 0};
+ UINT32 EndPointL1SubStateCapMask;
+
+ 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) == DEVICE_ID_NOCARE) {
+ 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) == DEVICE_ID_NOCARE) {
+ 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 = 0x0000001F;
+ RootDeviceL1Substates = 0;
+ EndPointL1Substates = 0;
+ //
+ // Get the endpoint supports L1 Substates Capabilities
+ //
+ GetOverrideL1sCapOffset (
+ EndPointBase,
+ NumOfDevAspmOverride,
+ DevAspmOverride,
+ EndPointVendorId,
+ EndPointDeviceId,
+ EndPointRevId,
+ &EndPointL1SubStateCapOffset,
+ &EndPointL1SubStateCapMask
+ );
+ if (EndPointL1SubStateCapOffset == 0) {
+ EndPointL1SubStateCapOffset = PcieFindExtendedCapId (
+ EndPointBus,
+ DeviceIndex,
+ FunctionIndex,
+ V_PCIE_EX_L1S_CID
+ );
+ }
+ if (EndPointL1SubStateCapOffset != 0) {
+ RootDeviceL1Substates = MmioRead32 (RootDeviceBase + RootL1SubstateExtCapOffset + R_PCIE_EX_L1SCAP_OFFSET);
+ 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)) {
+ //
+ // If both Root and endpoint's L1 Sub-States Extended Capability Offset + 0x04[4:0] are 11111b,
+ // 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 L1 Sub-States Extended Capability Offset + 0x08[4:0] to 01111b for both Pcie root port and device
+ //
+ if (((RootDeviceL1Substates & 0x1F) == 0x1F) &&
+ ((EndPointL1Substates & EndPointL1SubStateCapMask) == EndPointL1SubStateCapMask) &&
+ (RootPortConfig->L1Substates != ScPcieL1SubstatesDisabled))
+ {
+ *L1SubstatesSupported = TRUE;
+ EndPointPortCommonModeRestoreTime = (EndPointL1Substates >> 8) & 0xFF;
+ EndPointTpowerOnScale = (EndPointL1Substates >> 16) & 0x3;
+ EndPointTpowerOnValue = (EndPointL1Substates >> 19) & 0x1F;
+
+ if (EndPointPortCommonModeRestoreTime > *PortCommonModeRestoreTime) {
+ *PortCommonModeRestoreTime = EndPointPortCommonModeRestoreTime;
+ }
+
+ if ((EndPointTpowerOnValue * Multiplier[EndPointTpowerOnScale]) >
+ (*PortTpowerOnValue * Multiplier[*PortTpowerOnScale])) {
+ *PortTpowerOnValue = EndPointTpowerOnValue;
+ *PortTpowerOnScale = EndPointTpowerOnScale;
+ }
+ }
+ }
+ //
+ // 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
+ );
+ } else if (Operation == SetAspm) {
+ if ((EndPointL1SubStateCapOffset != 0) && (*L1SubstatesSupported)) {
+ if (((RootDeviceL1Substates & 0x1F) == 0x1F) &&
+ ((EndPointL1Substates & EndPointL1SubStateCapMask) == EndPointL1SubStateCapMask)) {
+ ConfigureL1s (
+ RootPortConfig,
+ EndPointBus,
+ DeviceIndex,
+ FunctionIndex,
+ EndPointBase,
+ EndPointL1SubStateCapOffset,
+ *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);
+ //
+ // Step 3
+ //
+ ConfigureLtr (
+ RootPortConfig,
+ EndPointBus,
+ DeviceIndex,
+ FunctionIndex,
+ EndPointBase,
+ EndPointPcieCapOffset,
+ DeviceCapabilities2,
+ 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,
+ PortCommonModeRestoreTime,
+ PortTpowerOnValue,
+ PortTpowerOnScale,
+ RootPortConfig,
+ AspmOverride,
+ ClkreqPerPortSupported,
+ RpAndEndPointsLtrSupported,
+ PolicyRevision
+ );
+ 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;
+}
+
+
+/**
+ This function checks if the root port and downstream device support Clkreq per port, ASPM L1 and L1 substates
+
+ @param[in] RootBus Pci Bus Number of the root port
+ @param[in] RootDevice Pci Device Number of the root port
+ @param[in] RootFunction Pci Function Number of the root port
+ @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] 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] RootPortConfig Pcie Power Optimizer Configuration
+ @param[in, out] L1SubstatesSupported Flag to indicate if L1 Substates are supported
+ @param[in] PolicyRevision Revision of the policy
+ @param[in, out] AspmVal Aspm value for both rootport and end point devices
+ @param[in, out] ClkreqPerPortSupported Clkreq support for both rootport and endpoint devices
+ @param[out] LtrSupported Check and return if all endpoints support LTR
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_UNSUPPORTED The pointer to the Port PCI Express Capability Structure is not found
+
+**/
+EFI_STATUS
+PcieCheckPmConfig (
+ IN UINT8 RootBus,
+ IN UINT8 RootDevice,
+ IN UINT8 RootFunction,
+ IN UINT32 NumOfDevAspmOverride,
+ IN SC_PCIE_DEVICE_OVERRIDE *DevAspmOverride,
+ IN UINT8 TempBusNumberMin,
+ IN UINT8 TempBusNumberMax,
+ IN CONST SC_PCIE_ROOT_PORT_CONFIG *RootPortConfig,
+ IN OUT BOOLEAN *L1SubstatesSupported,
+ IN UINT8 PolicyRevision,
+ IN OUT UINT16 *AspmVal,
+ IN OUT BOOLEAN *ClkreqPerPortSupported,
+ OUT BOOLEAN *LtrSupported
+ )
+{
+ EFI_STATUS Status;
+ UINTN RootDeviceBase;
+ UINT32 RootPcieCapOffset;
+ UINT8 EndPointBus;
+ OPERATION Operation;
+ UINT16 SlotStatus;
+ BOOLEAN BusAssign;
+ UINT32 LtrOvrVal;
+ UINT16 RootL1SubstateExtCapOffset;
+ UINT32 PortCommonModeRestoreTime;
+ UINT32 PortTpowerOnValue;
+ UINT32 PortTpowerOnScale;
+ BOOLEAN AspmOverride;
+
+ DEBUG ((DEBUG_INFO, "PcieCheckPmConfig () Start BDF: %0x : %0x : %0x\n", RootBus, RootDevice, RootFunction));
+ Status = EFI_SUCCESS;
+ RootDeviceBase = MmPciBase (RootBus, RootDevice, RootFunction);
+ PortCommonModeRestoreTime = 0;
+ PortTpowerOnValue = 0;
+ PortTpowerOnScale = 0;
+ *L1SubstatesSupported = FALSE;
+ AspmOverride = FALSE;
+ *ClkreqPerPortSupported = FALSE;
+
+ if (MmioRead16 (RootDeviceBase + PCI_VENDOR_ID_OFFSET) == DEVICE_ID_NOCARE) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Assume CLKREQ# is supported on the port if PHY lane power gating is already enabled.
+ //
+ *ClkreqPerPortSupported = PcieIsPhyLanePgEnabled (RootDeviceBase);
+
+ //
+ // Get the pointer to the Port PCI Express Capability Structure.
+ //
+ RootPcieCapOffset = PcieFindCapId (RootBus, RootDevice, RootFunction, EFI_PCI_CAPABILITY_ID_PCIEXP);
+ if (RootPcieCapOffset == 0) {
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ *AspmVal = (MmioRead16 (RootDeviceBase + RootPcieCapOffset + R_PCIE_LCAP_OFFSET) >> N_PCIE_LCAP_APMS) & 3;
+ if (RootPortConfig->Aspm == ScPcieAspmAutoConfig) {
+ Operation = CalculateAspm;
+ } else {
+ Operation = ManualAspm;
+ *AspmVal &= RootPortConfig->Aspm;
+ }
+
+ //
+ // Get the downstream Bus number
+ //
+ EndPointBus = MmioRead8 (RootDeviceBase + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET);
+
+ //
+ // If the Secondary Bus Number of the root port is not assigned
+ // Note:
+ // It will be better that PCI emulation has been done before PcieSetPm(). Or, you will need to assign
+ // a larger number to TempRootPortBusNumMax to support the specific card which has many bridges behind.
+ // If it is not, the Policy settings of "TempRootPortBusNumMax" and "TempRootPortBusNumMin"
+ // will be assigned to the Subordinate and Secondary Bus Number of the root ports.
+ // The assigned bus number will be cleared in the end of PcieSetPm().
+ //
+ if (EndPointBus == 0) {
+ MmioAndThenOr32 (
+ RootDeviceBase + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET,
+ 0xFF0000FF,
+ ((UINT32) (TempBusNumberMin << 8)) | ((UINT32) (TempBusNumberMax << 16))
+ );
+ EndPointBus = TempBusNumberMin;
+ BusAssign = FALSE;
+ } else {
+ BusAssign = TRUE;
+ }
+
+ //
+ // Check whether the slot has a device connected
+ //
+ SlotStatus = MmioRead16 (RootDeviceBase + RootPcieCapOffset + R_PCIE_SLSTS_OFFSET);
+ LtrOvrVal = 0;
+
+ RootL1SubstateExtCapOffset = 0;
+ RootL1SubstateExtCapOffset = PcieFindExtendedCapId (RootBus, RootDevice, RootFunction, V_PCIE_EX_L1S_CID);
+ if (RootL1SubstateExtCapOffset != 0) {
+ PortCommonModeRestoreTime = (MmioRead32 (RootDeviceBase + RootL1SubstateExtCapOffset + R_PCIE_EX_L1SCAP_OFFSET) >> 8) & 0xFF;
+ PortTpowerOnScale = (MmioRead32 (RootDeviceBase + RootL1SubstateExtCapOffset + R_PCIE_EX_L1SCAP_OFFSET) >> 16) & 0x3;
+ PortTpowerOnValue = (MmioRead32 (RootDeviceBase + RootL1SubstateExtCapOffset + R_PCIE_EX_L1SCAP_OFFSET) >> 19) & 0x1F;
+ }
+
+ //
+ // Obtain initial ASPM settings from respective port capability registers.
+ // Scan LTR override table for device match and calculate the lowest override
+ // value to be programmed into PCIE RP PCI offset 400h
+ //
+ if (EndPointBus != 0 && (SlotStatus & BIT6) != 0) {
+ Status = PcieEndPointPm (
+ RootDeviceBase,
+ RootPcieCapOffset,
+ EndPointBus,
+ NumOfDevAspmOverride,
+ DevAspmOverride,
+ AspmVal,
+ Operation,
+ &LtrOvrVal,
+ RootL1SubstateExtCapOffset,
+ L1SubstatesSupported,
+ &PortCommonModeRestoreTime,
+ &PortTpowerOnValue,
+ &PortTpowerOnScale,
+ RootPortConfig,
+ &AspmOverride,
+ ClkreqPerPortSupported,
+ LtrSupported,
+ PolicyRevision
+ );
+ }
+
+ if (BusAssign == FALSE) {
+ //
+ // Clear Bus Numbers.
+ //
+ MmioAnd32 (RootDeviceBase + 0x018, 0xFF0000FF);
+ }
+ return Status;
+}
+
+
+/**
+ This function performs the Power Management settings for root port and downstream device
+
+ @param[in] RootBus Pci Bus Number of the root port
+ @param[in] RootDevice Pci Device Number of the root port
+ @param[in] RootFunction Pci Function Number of the root port
+ @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] 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] RootPortConfig Pcie Power Optimizer Configuration
+ @param[in, out] L1SubstatesSupported Flag to indicate if L1 Substates are supported
+ @param[in] PolicyRevision Policy revision for codes compatibility
+ @param[in] FirstRpToSetPm Indicates if this is the first root port to be set
+ @param[in] L1SupportedInAllEnabledPorts Check if L1 is supported in all enabled ports
+ @param[in] ClkreqSupportedInAllEnabledPorts Check if clkreq is supported in all enabled ports
+ @param[out] LtrSupported Check and return if all endpoints support LTR
+ @param[in] AllowRpAspmProgramming Allow fine grain control on when the RP ASPM programming is to be done,
+ particularly used by the RST PCIe storage remapping feature
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_UNSUPPORTED The pointer to the Port PCI Express Capability Structure is not found
+
+**/
+EFI_STATUS
+PcieSetPm (
+ IN UINT8 RootBus,
+ IN UINT8 RootDevice,
+ IN UINT8 RootFunction,
+ IN UINT32 NumOfDevAspmOverride,
+ IN CONST SC_PCIE_DEVICE_OVERRIDE *DevAspmOverride,
+ IN UINT8 TempBusNumberMin,
+ IN UINT8 TempBusNumberMax,
+ IN CONST SC_PCIE_ROOT_PORT_CONFIG *RootPortConfig,
+ IN OUT BOOLEAN *L1SubstatesSupported,
+ IN UINT8 PolicyRevision,
+ IN BOOLEAN FirstRPToSetPm,
+ IN BOOLEAN L1SupportedInAllEnabledPorts,
+ IN BOOLEAN ClkreqSupportedInAllEnabledPorts,
+ OUT BOOLEAN *LtrSupported,
+ IN BOOLEAN AllowRpAspmProgramming
+ )
+{
+ UINT16 AspmVal;
+ EFI_STATUS Status;
+ UINTN RootDeviceBase;
+ UINT32 RootPcieCapOffset;
+ UINT8 EndPointBus;
+ OPERATION Operation;
+ UINT16 SlotStatus;
+ BOOLEAN BusAssign;
+ UINT32 DeviceCapabilities2;
+ UINT32 LtrOvrVal;
+ UINT32 Data32And;
+ UINT32 Data32Or;
+ BOOLEAN ClkreqPerPortSupported;
+ UINT16 RootL1SubstateExtCapOffset;
+ UINT32 PortCommonModeRestoreTime;
+ UINT32 PortTpowerOnValue;
+ UINT32 PortTpowerOnScale;
+ BOOLEAN AspmOverride;
+ UINTN PortIndex;
+ UINT8 FirstRpIndex;
+
+ DEBUG ((DEBUG_INFO, "PcieSetPm () Start BDF: %0x : %0x : %0x\n", RootBus, RootDevice, RootFunction));
+ Status = EFI_SUCCESS;
+ RootDeviceBase = MmPciBase (RootBus, RootDevice, RootFunction);
+ PortCommonModeRestoreTime = 0;
+ PortTpowerOnValue = 0;
+ PortTpowerOnScale = 0;
+ *L1SubstatesSupported = FALSE;
+ AspmOverride = FALSE;
+ ClkreqPerPortSupported = FALSE;
+
+ if (MmioRead16 (RootDeviceBase + PCI_VENDOR_ID_OFFSET) == DEVICE_ID_NOCARE) {
+ ASSERT (FALSE);
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Assume CLKREQ# is supported on the port if PHY lane power gating is already enabled.
+ //
+ ClkreqPerPortSupported = PcieIsPhyLanePgEnabled (RootDeviceBase);
+
+ //
+ // Get the pointer to the Port PCI Express Capability Structure.
+ //
+ RootPcieCapOffset = PcieFindCapId (RootBus, RootDevice, RootFunction, EFI_PCI_CAPABILITY_ID_PCIEXP);
+ if (RootPcieCapOffset == 0) {
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+ DeviceCapabilities2 = MmioRead32 (RootDeviceBase + RootPcieCapOffset + R_PCIE_DCAP2_OFFSET);
+
+ //
+ // Enable LTR mechanism for this root port if it is capable
+ //
+ if ((DeviceCapabilities2 & B_PCIE_DCAP2_LTRMS) && (RootPortConfig->LtrEnable == TRUE)) {
+ MmioOr16 (RootDeviceBase + RootPcieCapOffset + R_PCIE_DCTL2_OFFSET, B_PCIE_DCTL2_LTREN);
+ }
+
+ AspmVal = (MmioRead16 (RootDeviceBase + RootPcieCapOffset + R_PCIE_LCAP_OFFSET) & B_PCIE_LCAP_APMS) >> N_PCIE_LCAP_APMS;
+ if (RootPortConfig->Aspm == ScPcieAspmAutoConfig) {
+ Operation = CalculateAspm;
+ } else {
+ Operation = ManualAspm;
+ AspmVal &= RootPortConfig->Aspm;
+ }
+
+ //
+ // Get the downstream Bus number
+ //
+ EndPointBus = MmioRead8 (RootDeviceBase + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET);
+
+ //
+ // If the Secondary Bus Number of the root port is not assigned
+ // Note:
+ // It will be better that PCI enumeration has been done before PcieSetPm(). Or, you will need to assign
+ // a larger number to TempRootPortBusNumMax to support the specific card which has many bridges behind.
+ // If it is not, the Policy settings of "TempRootPortBusNumMax" and "TempRootPortBusNumMin"
+ // will be assigned to the Subordinate and Secondary Bus Number of the root ports.
+ // The assigned bus number will be cleared in the end of PcieSetPm().
+ //
+ if (EndPointBus == 0) {
+ MmioAndThenOr32 (
+ RootDeviceBase + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET,
+ 0xFF0000FF,
+ ((UINT32) (TempBusNumberMin << 8)) | ((UINT32) (TempBusNumberMax << 16))
+ );
+ EndPointBus = TempBusNumberMin;
+ BusAssign = FALSE;
+ } else {
+ BusAssign = TRUE;
+ }
+
+ //
+ // Check whether the slot has a device connected
+ //
+ SlotStatus = MmioRead16 (RootDeviceBase + RootPcieCapOffset + R_PCIE_SLSTS_OFFSET);
+ LtrOvrVal = 0;
+
+ RootL1SubstateExtCapOffset = 0;
+ RootL1SubstateExtCapOffset = PcieFindExtendedCapId (RootBus, RootDevice, RootFunction, V_PCIE_EX_L1S_CID);
+ if (RootL1SubstateExtCapOffset != 0) {
+ PortCommonModeRestoreTime = (MmioRead32 (RootDeviceBase + RootL1SubstateExtCapOffset + R_PCIE_EX_L1SCAP_OFFSET) >> 8) & 0xFF;
+ PortTpowerOnScale = (MmioRead32 (RootDeviceBase + RootL1SubstateExtCapOffset + R_PCIE_EX_L1SCAP_OFFSET) >> 16) & 0x3;
+ PortTpowerOnValue = (MmioRead32 (RootDeviceBase + RootL1SubstateExtCapOffset + R_PCIE_EX_L1SCAP_OFFSET) >> 19) & 0x1F;
+ }
+
+ //
+ // Obtain initial ASPM settings from respective port capability registers.
+ // Scan LTR override table for device match and calculate the lowest override
+ // value to be programmed into PCIE RP PCI offset 400h
+ //
+ if (EndPointBus != 0 && (SlotStatus & BIT6) != 0) {
+ Status = PcieEndPointPm (
+ RootDeviceBase,
+ RootPcieCapOffset,
+ EndPointBus,
+ NumOfDevAspmOverride,
+ DevAspmOverride,
+ &AspmVal,
+ Operation,
+ &LtrOvrVal,
+ RootL1SubstateExtCapOffset,
+ L1SubstatesSupported,
+ &PortCommonModeRestoreTime,
+ &PortTpowerOnValue,
+ &PortTpowerOnScale,
+ RootPortConfig,
+ &AspmOverride,
+ &ClkreqPerPortSupported,
+ LtrSupported,
+ PolicyRevision
+ );
+ if (RootPortConfig->LtrEnable == TRUE) {
+ if (RootPortConfig->SnoopLatencyOverrideMode == 1) {
+ LtrOvrVal &= 0xFFFF0000;
+ LtrOvrVal |= (UINT32) BIT15 |
+ (UINT32) (RootPortConfig->SnoopLatencyOverrideMultiplier << 10) |
+ (UINT32) (RootPortConfig->SnoopLatencyOverrideValue);
+ }
+
+ if (RootPortConfig->NonSnoopLatencyOverrideMode == 1) {
+ LtrOvrVal &= 0x0000FFFF;
+ LtrOvrVal |= (UINT32) BIT31 |
+ (UINT32) (RootPortConfig->NonSnoopLatencyOverrideMultiplier << 26) |
+ (UINT32) (RootPortConfig->NonSnoopLatencyOverrideValue << 16);
+ }
+ if (LtrOvrVal != 0) {
+ //
+ // Program PCIE RP PCI offset 400h only if we find a device in the LTR override table
+ //
+ MmioWrite32 (RootDeviceBase + 0x400, LtrOvrVal);
+ //
+ // Step 1.1
+ // If B0:Dxx:Fn + 400h is programmed, BIOS will also program B0:Dxx:Fn + 404h [1:0] = 11b,
+ // to enable these override values.
+ // - Fn refers to the function number of the root port that has a device attached to it.
+ // - Default override value for B0:Dxx:Fn + 400h should be 880F880Fh
+ // - Also set 404h[2] to lock down the configuration
+ //
+ Data32Or = BIT1 | BIT0;
+ if (RootPortConfig->SnoopLatencyOverrideMode == 0) {
+ Data32Or &= (UINT32) ~BIT0;
+ }
+ if (RootPortConfig->NonSnoopLatencyOverrideMode == 0) {
+ Data32Or &= (UINT32) ~BIT1;
+ }
+
+ if (RootPortConfig->LtrConfigLock == TRUE) {
+ //
+ // Set the lock bit
+ //
+ Data32Or |= BIT2;
+ }
+ MmioWrite32 (RootDeviceBase + 0x404, Data32Or);
+ }
+ }
+ }
+ //
+ // Step 6
+ // If both Root and endpoint's L1 Sub-States Extended Capability Offset + 0x04[4:0] are 11111b,
+ //
+ if (*L1SubstatesSupported) {
+ ConfigureL1s (
+ RootPortConfig,
+ RootBus,
+ RootDevice,
+ RootFunction,
+ RootDeviceBase,
+ RootL1SubstateExtCapOffset,
+ PortCommonModeRestoreTime,
+ PortTpowerOnValue,
+ PortTpowerOnScale
+ );
+ }
+ //
+ // Step 7
+ // If L1.SNOOZ and L1.OFF (L1 Sub-States) are not supported,
+ // and per-port CLKREQ# is supported, and LTR is supported:
+ //
+ if ((!(*L1SubstatesSupported)) && ClkreqPerPortSupported) {
+ if ((DeviceCapabilities2 & BIT11) && (RootPortConfig->LtrEnable == TRUE)) {
+ //
+ // Set Dxx:Fn:420[13:4] = 32h
+ //
+ MmioAndThenOr32 (
+ RootDeviceBase + 0x420,
+ (UINT32) ~(BIT13 | BIT12 | BIT11 | BIT10 | BIT9 | BIT8 | BIT7 | BIT6 | BIT5 | BIT4),
+ (0x32 << 4)
+ );
+ //
+ // Enable L1.LOW by setting Dxx:Fn:420[17] = 1b
+ //
+ MmioOr32 (RootDeviceBase + 0x420, (UINT32)BIT17);
+ //
+ // Set Dxx:Fn:420h[0] to 1b
+ //
+ if ((AspmVal & V_PCIE_LCTL_ASPM_L1) == V_PCIE_LCTL_ASPM_L1) {
+ MmioOr32 (RootDeviceBase + 0x420, BIT0);
+ }
+ }
+ }
+
+ if ((AspmVal & V_PCIE_LCTL_ASPM_L1) == V_PCIE_LCTL_ASPM_L1) {
+
+ Data32Or = (BIT4 << 16);
+ //
+ // If dedicated CLKREQ# per-port is supported on all enabled ports,
+ // set Dxx:F0:E1h[6] = 1b prior to enabling ASPM L1.
+ //
+ if (ClkreqSupportedInAllEnabledPorts) {
+ Data32Or |= (B_PCH_PCIE_RPDCGEN_PTOCGE << 8);
+ }
+ //
+ // Note: for each PCIe controller, only its first root port register field E2h[4] and E1h[6] value are used,
+ // thus program them using sideband access
+ //
+ GetScPcieRpNumber (RootDevice, RootFunction, &PortIndex);
+ if (PortIndex < 2) {
+ FirstRpIndex = 0;
+ } else {
+ FirstRpIndex = 2;
+ }
+ Status = PchSbiRpPciAndThenOr32 (RootDevice, FirstRpIndex, 0xE0, (UINT32)(~(0)),Data32Or);
+ Data32Or = 0;
+ Data32And = (UINT32)~0;
+ if (ClkreqPerPortSupported) {
+ //
+ // If L1.SNOOZ and L1.OFF (L1 Sub-States) are supported , set Dxx:F0:420[30, 29] = [1b, 1b],
+ //
+ if (*L1SubstatesSupported) {
+ //
+ // If L1.SNOOZ and L1.OFF (L1 Sub-States) are supported, then disable L1.LOW by setting Dxx:Fn:420h[17] = 0b
+ //
+ Data32And = (UINT32)~BIT17;
+ Data32Or = BIT30 | BIT29;
+ }
+ MmioAndThenOr32 (RootDeviceBase + 0x420, Data32And, Data32Or);
+ }
+ }
+ //
+ // Set Root Port Aspm and enable LTR capability of the device if the Root Port's ASPM programming is allowed
+ //
+ if (AllowRpAspmProgramming == TRUE) {
+ MmioAndThenOr16 (RootDeviceBase + RootPcieCapOffset + R_PCIE_LCTL_OFFSET, (UINT16)~B_PCIE_LCTL_ASPM, AspmVal);
+ }
+
+ //
+ // Based on the Role based Error Reporting Capability bit, for pre-1.1 devices,
+ // program root port 0xD4[4] to 1 and 0xD4[3:2] to 10.
+ //
+ if (AspmOverride) {
+ MmioAndThenOr8 (RootDeviceBase + R_PCH_PCIE_MPC2,
+ (UINT8)~(B_PCH_PCIE_MPC2_ASPMCOEN | B_PCH_PCIE_MPC2_ASPMCO),
+ (B_PCH_PCIE_MPC2_ASPMCOEN | V_PCH_PCIE_MPC2_ASPMCO_L1)
+ );
+ } else {
+ MmioAnd8 (RootDeviceBase + R_PCH_PCIE_MPC2, (UINT8)~(B_PCH_PCIE_MPC2_ASPMCOEN | B_PCH_PCIE_MPC2_ASPMCO));
+ }
+ //
+ // Step 1
+ // Enable support Latency Tolerance Reporting (LTR)
+ //
+ if (EndPointBus != 0 && (SlotStatus & BIT6) != 0) {
+ //
+ // Set Endpoint Aspm and LTR capabilities
+ //
+ Status = PcieEndPointPm (
+ RootDeviceBase,
+ RootPcieCapOffset,
+ EndPointBus,
+ NumOfDevAspmOverride,
+ DevAspmOverride,
+ &AspmVal,
+ SetAspm,
+ &LtrOvrVal,
+ RootL1SubstateExtCapOffset,
+ L1SubstatesSupported,
+ &PortCommonModeRestoreTime,
+ &PortTpowerOnValue,
+ &PortTpowerOnScale,
+ RootPortConfig,
+ &AspmOverride,
+ &ClkreqPerPortSupported,
+ LtrSupported,
+ PolicyRevision
+ );
+ }
+
+ if (BusAssign == FALSE) {
+ //
+ // Clear Bus Numbers.
+ //
+ MmioAnd32 (RootDeviceBase + 0x018, 0xFF0000FF);
+ }
+
+ return Status;
+}
+
+
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/Private/PeiDxeSmmScPciExpressHelpersLib/ScPciExpressHelpersLibrary.h b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/Private/PeiDxeSmmScPciExpressHelpersLib/ScPciExpressHelpersLibrary.h
new file mode 100644
index 0000000000..9d20fb6797
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/Private/PeiDxeSmmScPciExpressHelpersLib/ScPciExpressHelpersLibrary.h
@@ -0,0 +1,48 @@
+/** @file
+ Header file for PCI Express helps library implementation.
+
+ Copyright (c) 2008 - 2016, 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.
+
+**/
+
+#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 <Ppi/ScPolicy.h>
+#include <ScAccess.h>
+#include <Library/ScPlatformLib.h>
+#include <Library/MmPciLib.h>
+#include <Library/SideBandLib.h>
+#include <Library/SteppingLib.h>
+#include <Private/Library/PeiDxeSmmScPciExpressHelpersLib.h>
+
+#define LTR_VALUE_MASK (BIT0 + BIT1 + BIT2 + BIT3 + BIT4 + BIT5 + BIT6 + BIT7 + BIT8 + BIT9)
+#define LTR_SCALE_MASK (BIT10 + BIT11 + BIT12)
+
+#ifndef SLE_FLAG
+ #define CONFIG_WRITE_LOOP_COUNT 100000
+#else // SLE_FLAG
+ #define CONFIG_WRITE_LOOP_COUNT 10
+#endif // SLE_FLAG
+
+//
+// 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/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/Private/PeiDxeUsbCommonLib/PeiDxeUsbCommonLib.inf b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/Private/PeiDxeUsbCommonLib/PeiDxeUsbCommonLib.inf
new file mode 100644
index 0000000000..1df68e706a
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/Private/PeiDxeUsbCommonLib/PeiDxeUsbCommonLib.inf
@@ -0,0 +1,53 @@
+## @file
+# USB common lib.
+#
+# Copyright (c) 2015 - 2016, 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 = PeiDxeUsbCommonLib
+ FILE_GUID = 7A06ED7D-8E15-40a4-8539-22E86992DBE1
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = UsbCommonLib | PEIM DXE_DRIVER
+
+[Sources]
+ UsbCommonLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ BroxtonSiPkg/BroxtonSiPkg.dec
+ BroxtonSiPkg/BroxtonSiPrivate.dec
+
+[LibraryClasses]
+ S3BootScriptLib # Link this S3BootScriptLib to a NULL library for PEI usage.
+ BaseLib
+ IoLib
+ DebugLib
+ TimerLib
+ MmPciLib
+ SteppingLib
+ TimerLib
+ ConfigBlockLib
+ ScPlatformLib
+
+[Guids]
+ gUsbConfigGuid
+ gSiPolicyHobGuid
+
+[Ppis]
+
+[Pcd]
+ gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress ## SOMETIMES_CONSUMES
+ gEfiBxtTokenSpaceGuid.PcdScAcpiIoPortBaseAddress ## SOMETIMES_CONSUMES
+ gEfiBxtTokenSpaceGuid.PcdPmcGcrBaseAddress ## SOMETIMES_CONSUMES
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/Private/PeiDxeUsbCommonLib/UsbCommonLib.c b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/Private/PeiDxeUsbCommonLib/UsbCommonLib.c
new file mode 100644
index 0000000000..f7a2a4af0b
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/Private/PeiDxeUsbCommonLib/UsbCommonLib.c
@@ -0,0 +1,1172 @@
+/** @file
+ Initializes USB Controllers.
+
+ Copyright (c) 2012 - 2016, 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.
+
+**/
+
+#include <Private/Library/UsbCommonLib.h>
+#include <Library/SteppingLib.h>
+#include <Library/PmcIpcLib.h>
+#include <Library/TimerLib.h>
+#include <Library/ConfigBlockLib.h>
+#include <Library/ScPlatformLib.h>
+
+EFI_BOOT_MODE mBootMode = BOOT_WITH_FULL_CONFIGURATION;
+
+
+/**
+ Set UNUSED bit to "1" if the port has no physical SSIC Device connected.
+
+ @param[in] UsbConfig The SC Policy for USB configuration
+ @param[in] XhciMmioBase Memory base address of XHCI Controller
+
+ @retval EFI_INVALID_PARAMETER The parameter of ScPolicy is invalid
+ @retval EFI_SUCCESS The function completed successfully
+
+**/
+VOID
+XhciSsicInit (
+ IN SC_USB_CONFIG *UsbConfig,
+ IN UINT32 XhciMmioBase,
+ IN EFI_BOOT_MODE BootMode
+ );
+
+/**
+ Program Xhci Port Disable Override
+
+ @param[in] UsbConfig The SC Policy for USB configuration
+ @param[in] XhciMmioBase XHCI Memory Space Address
+
+ @retval None
+
+**/
+VOID
+XhciPortDisableOverride (
+ IN SC_USB_CONFIG *UsbConfig,
+ IN UINTN XhciMmioBase
+ );
+
+/**
+ Setup XHCI Over-Current Mapping
+
+ @param[in] UsbConfig The SC Policy for USB configuration
+ @param[in] XhciPciMmBase XHCI PCI Base Address
+
+ @retval None
+
+**/
+VOID
+XhciOverCurrentMapping (
+ IN SC_USB_CONFIG *UsbConfig,
+ IN UINTN XhciPciMmBase
+ );
+
+/**
+ Configures SC USB controller
+
+ @param[in] UsbConfig The SC Policy for USB configuration
+ @param[in] XhciMmioBase Memory base address of XHCI Controller
+ @param[in] BusNumber PCI Bus Number of the SC device
+ @param[in] FuncDisableReg Function Disable Register
+ @param[in] BootMode current boot mode
+
+ @retval EFI_INVALID_PARAMETER The parameter of ScPolicy is invalid
+ @retval EFI_SUCCESS The function completed successfully
+
+**/
+EFI_STATUS
+EFIAPI
+CommonUsbInit (
+ IN SC_USB_CONFIG *UsbConfig,
+ IN UINT32 XhciMmioBase,
+ IN UINT8 BusNumber,
+ IN OUT UINT32 *FuncDisableReg,
+ IN EFI_BOOT_MODE BootMode
+ )
+{
+ UINTN XhciPciMmBase;
+
+ DEBUG ((DEBUG_INFO, "CommonUsbInit() - Start\n"));
+ mBootMode = BootMode;
+
+ XhciPciMmBase = MmPciBase (
+ BusNumber,
+ PCI_DEVICE_NUMBER_XHCI,
+ PCI_FUNCTION_NUMBER_XHCI
+ );
+ //
+ // If xHCI is disabled by fuse or soft-strap,
+ // set the function disable bit and then return.
+ //
+ if (MmioRead32 ((UINTN) (XhciPciMmBase)) == 0xFFFFFFFF) {
+ DEBUG ((EFI_D_INFO , "xHCI not present, skipping.\n"));
+ UsbConfig->Usb30Settings.Mode = XHCI_MODE_OFF;
+ *FuncDisableReg |= B_PMC_FUNC_DIS_USB_XHCI;
+ return EFI_SUCCESS;
+ }
+
+ //
+ // To disable a host controller, the System BIOS must first place the
+ // xHCI controller in RTD3Hot state by program PM_CS.PS, D21:F0:0x74 [1:0] = 11b
+ // and then set the Function Disable register to disable the xHCI controller.
+ //
+ if (UsbConfig->Usb30Settings.Mode == XHCI_MODE_OFF) {
+
+ //
+ // Putting xHCI into D3 Hot State
+ //
+ DEBUG ((EFI_D_INFO , "Putting xHCI into D3 Hot State.\n"));
+ MmioOr32 ((UINTN) (XhciPciMmBase + R_XHCI_PWR_CNTL_STS), B_XHCI_PWR_CNTL_STS_PWR_STS);
+
+ SideBandAndThenOr32 (
+ 0xA9,
+ (0x0600 + 0x001C),
+ 0xFFFFFFFF,
+ BIT8
+ );
+ *FuncDisableReg |= B_PMC_FUNC_DIS_USB_XHCI;
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Assign memory resources
+ //
+ XhciMemorySpaceOpen (
+ UsbConfig,
+ XhciMmioBase,
+ XhciPciMmBase
+ );
+
+ CommonXhciHcInit (
+ UsbConfig,
+ XhciMmioBase,
+ XhciPciMmBase,
+ BootMode
+ );
+
+ XhciSsicInit (
+ UsbConfig,
+ XhciMmioBase,
+ BootMode
+ );
+
+ //
+ // Setup USB Over-Current Mapping.
+ //
+ XhciOverCurrentMapping (
+ UsbConfig,
+ XhciPciMmBase
+ );
+
+ //
+ // Program USB Port Disable Override Capability
+ //
+ XhciPortDisableOverride (
+ UsbConfig,
+ XhciMmioBase
+ );
+
+ //
+ // Clear memory resources
+ //
+ XhciMemorySpaceClose (
+ UsbConfig,
+ XhciMmioBase,
+ XhciPciMmBase
+ );
+
+ DEBUG ((EFI_D_INFO, "CommonUsbInit() - End\n"));
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Set UNUSED bit to "1" if the port has no physical SSIC Device connected.
+
+ @param[in] UsbConfig The SC Policy for USB configuration
+ @param[in] XhciMmioBase Memory base address of XHCI Controller
+
+ @retval EFI_INVALID_PARAMETER The parameter of ScPolicy is invalid
+ @retval EFI_SUCCESS The function completed successfully
+
+**/
+VOID
+XhciSsicInit (
+ IN SC_USB_CONFIG *UsbConfig,
+ IN UINT32 XhciMmioBase,
+ IN EFI_BOOT_MODE BootMode
+ )
+{
+ UINT32 Data32;
+ UINT32 Iteration;
+
+ DEBUG ((DEBUG_INFO, "XhciSsicInit() - Start\n"));
+
+ if (UsbConfig->SsicConfig.SsicPort[0].Enable == TRUE) {
+ Data32 = B_XHCI_PROG_DONE;
+ } else {
+ //
+ // Set UNUSED bit to "1" if the port has no physical SSIC Device connected.
+ //
+ Data32 = B_XHCI_SSIC_PORT_UNUSED | B_XHCI_PROG_DONE;
+ }
+ MmioOr32 (
+ XhciMmioBase + R_XHCI_SSIC_CFG_2_PORT1,
+ Data32
+ );
+
+ if (UsbConfig->SsicConfig.SsicPort[1].Enable == TRUE) {
+ Data32 = B_XHCI_PROG_DONE;
+ } else {
+ //
+ // Set UNUSED bit to "1" if the port has no physical SSIC Device connected.
+ //
+ Data32 = B_XHCI_SSIC_PORT_UNUSED | B_XHCI_PROG_DONE;
+ }
+ MmioOr32 (
+ XhciMmioBase + R_XHCI_SSIC_CFG_2_PORT2,
+ Data32
+ );
+
+ DEBUG ((DEBUG_INFO, "XhciSsicInit:base:0x%x\n",XhciMmioBase));
+ Data32 = MmioRead32(XhciMmioBase+R_XHCI_SSIC_CFG_2_PORT1);
+ DEBUG ((DEBUG_INFO, "0x%x:0x%x\n", (XhciMmioBase+R_XHCI_SSIC_CFG_2_PORT1), Data32));
+
+ Data32 = MmioRead32(XhciMmioBase+R_XHCI_SSIC_CFG_2_PORT2);
+ DEBUG ((DEBUG_INFO, "0x%x:0x%x\n", (XhciMmioBase+R_XHCI_SSIC_CFG_2_PORT2), Data32));
+
+ if ((UsbConfig->SsicConfig.SsicPort[0].Enable == TRUE) ||
+ (UsbConfig->SsicConfig.SsicPort[1].Enable == TRUE)) {
+ if (BootMode == BOOT_ON_S5_RESUME) {
+ DEBUG ((DEBUG_INFO, "Boot on S5 resume...\n"));
+ MicroSecondDelay (100); // 100us
+ //
+ // Clear SSIC ports PP bits
+ //
+ if (GetBxtSeries () == BxtP) {
+ //
+ // Clear SSIC ports PP bits
+ //
+ MmioAnd32 (
+ XhciMmioBase + R_BXTP_XHCI_PORTSC2USB3,
+ (UINT32) ~(B_XHCI_PORTSCXUSB3_PP)
+ );
+ MmioAnd32 (
+ XhciMmioBase + R_BXTP_XHCI_PORTSC3USB3,
+ (UINT32) ~(B_XHCI_PORTSCXUSB3_PP)
+ );
+ //
+ // Wait for 150ms for Host to complete the DSP Disconnect protocol
+ //
+ MicroSecondDelay (150 * 1000);
+
+ MmioOr32 (
+ XhciMmioBase + R_BXTP_XHCI_PORTSC2USB3,
+ (UINT32) B_XHCI_PORTSCXUSB3_PP
+ );
+
+ MmioOr32 (
+ XhciMmioBase + R_BXTP_XHCI_PORTSC3USB3,
+ (UINT32) B_XHCI_PORTSCXUSB3_PP
+ );
+ } else {
+ MmioAnd32 (
+ XhciMmioBase + R_BXT_XHCI_PORTSC2USB3,
+ (UINT32) ~(B_XHCI_PORTSCXUSB3_PP)
+ );
+ MmioAnd32 (
+ XhciMmioBase + R_BXT_XHCI_PORTSC3USB3,
+ (UINT32) ~(B_XHCI_PORTSCXUSB3_PP)
+ );
+ //
+ // Wait for 150ms for Host to complete the DSP Disconnect protocol
+ //
+ MicroSecondDelay (150 * 1000);
+
+ MmioOr32 (
+ XhciMmioBase + R_BXT_XHCI_PORTSC2USB3,
+ (UINT32) B_XHCI_PORTSCXUSB3_PP
+ );
+ MmioOr32 (
+ XhciMmioBase + R_BXT_XHCI_PORTSC3USB3,
+ (UINT32) B_XHCI_PORTSCXUSB3_PP
+ );
+ }
+ //
+ // Set HCRST after S5, HCRST is cleared by HW when reset process is complete
+ //
+ MmioOr32 (
+ XhciMmioBase + R_XHCI_USBCMD,
+ (UINT32) B_XHCI_USBCMD_HCRST
+ );
+ //
+ // Waiting for reset complete
+ // The controller requires that its MMIO space not be accessed for a minimum of 1 ms after
+ // an HCRST is triggered which includes reading the HCRST bit
+ //
+ MicroSecondDelay (1000); // 1ms
+ for (Iteration = 0; Iteration < 8000; Iteration++) {
+ if ((MmioRead32 (XhciMmioBase + R_XHCI_USBCMD) & B_XHCI_USBCMD_HCRST) == 0) {
+ break;
+ }
+ MicroSecondDelay (100); // 100us
+ }
+ }
+ }
+
+ DEBUG ((DEBUG_INFO, "XhciSsicInit() - End\n"));
+
+ return;
+}
+
+
+/**
+ Performs basic configuration of SC USB3 (xHCI) controller.
+
+ @param[in] UsbConfig The SC Policy for USB configuration
+ @param[in] XhciMmioBase Memory base address of xHCI Controller
+ @param[in] XhciPciMmBase XHCI PCI Base Address
+
+ @retval None
+
+**/
+VOID
+CommonXhciHcInit (
+ IN SC_USB_CONFIG *UsbConfig,
+ IN UINT32 XhciMmioBase,
+ IN UINTN XhciPciMmBase,
+ IN EFI_BOOT_MODE BootMode
+ )
+{
+ EFI_STATUS Status;
+ UINT32 BitMask;
+ UINT32 BitValue;
+ BXT_STEPPING BxtStep;
+ UINT32 Data32And;
+ UINT32 Data32Or;
+
+ Status = EFI_TIMEOUT;
+ BitMask = 0;
+ BitValue = 0;
+ BxtStep = BxtStepping ();
+
+ //
+ // Set xHCI MSI_NEXT to 0x90 to point to the DevIdle capability structure
+ //
+ MmioAndThenOr32(XhciPciMmBase + R_XHCI_MSI_CAPID, 0xFFFF00FF, V_XHCI_MSI_NEXT << 8);
+
+ //
+ // HCSPARAMS1 - Structural Parameters 1
+ // Address Offset: 0x04 - 0x07
+ //
+ BitValue = MmioRead32 (XhciMmioBase + R_XHCI_XECP_SUPP_USB3_2);
+ BitValue = ((BitValue >> 8) & 0xff) + ((BitValue & 0xff) - 1);
+ MmioAndThenOr32 (
+ (XhciMmioBase + R_XHCI_HCSPARAMS1),
+ (UINT32) 0x00FFFFFF,
+ (UINT32) (BitValue << 24)
+ );
+ BitValue = 0;
+ //
+ // HCSPARAMS3 - Structural Parameters 3
+ // Address Offset: 0x0C - 0x0F
+ // Set xHCIBAR + 0Ch[7:0] = 0Ah and [31:16] = 200h
+ //
+ MmioAndThenOr32 (
+ (XhciMmioBase + R_XHCI_HCSPARAMS3),
+ (UINT32) 0x0000FF00,
+ (UINT32) 0x0200000A
+ );
+
+ //
+ // XHCC2 - XHC System Bus Configuration 2
+ // Address Offset: 44-47h
+ // Value: [25] 1b, [24:22] 111b, [19:14] 3fh, [11] 0b, [10] 1b, [9:8] 10b, [7:6] 10b, [5:3] 001b, [2:0] 111b
+ //
+ Data32And = 0xFC303000;
+ Data32Or = 0x03CFC68F;
+ if (BxtStep == BxtPA0 && BootMode == BOOT_ON_S3_RESUME) {
+
+ Data32Or = 0x000FC688;
+ }
+ MmioAndThenOr32 (
+ XhciPciMmBase + R_XHCI_XHCC2,
+ Data32And,
+ Data32Or
+ );
+
+
+ if (GetBxtSeries() == BxtP) {
+ //
+ // PCE - Power Control Enables
+ // Address Offset: A2h - A3h
+ // Value: [5] 0b, [3] 1b, [2] 1b, [1] 1b, [0] 0b
+ MmioAndThenOr16 (
+ XhciPciMmBase + R_XHCI_PCE,
+ (UINT16)~(B_XHCI_PCE_SPE | B_XHCI_PCE_HAE),
+ (UINT16)(B_XHCI_PCE_SE | B_XHCI_PCE_D3HE | B_XHCI_PCE_I3E)
+ );
+ } else {
+ //
+ // PCE - Power Control Enables
+ // Address Offset: A2h - A3h
+ // Value: [5] 1b, [3] 1b, [2] 1b, [1] 1b, [0] 0b
+ //
+ MmioAndThenOr16 (
+ XhciPciMmBase + R_XHCI_PCE,
+ (UINT16) ~(B_XHCI_PCE_SPE),
+ (UINT16) (B_XHCI_PCE_SE | B_XHCI_PCE_D3HE | B_XHCI_PCE_I3E | B_XHCI_PCE_HAE)
+ );
+ }
+
+ //
+ // HSCFG2 - High Speed Configuration 2
+ // Address Offset: A4h - A5h
+ // Value: [15] 0b, [14] 0b, [13] 0b, [12:11] 11b
+ //
+ MmioAndThenOr16 (
+ XhciPciMmBase + R_XHCI_HSCFG2,
+ (UINT16) ~(B_XHCI_HSCFG2_HSAAIM | B_XHCI_HSCFG2_HSOAAPEPM | B_XHCI_HSCFG2_HSIAAPEPM),
+ (UINT16) (B_XHCI_HSCFG2_HSIIPAPC)
+ );
+
+ //
+ // SSCFG1 - SuperSpeed Configuration 1
+ // Address Offset: A8h - ABh
+ // Value: [17] 1b, [14] 1b
+ //
+ MmioAndThenOr32 (
+ XhciPciMmBase + R_XHCI_SSCFG1,
+ 0xFFFFFFFF,
+ (UINT32) (B_XHCI_SSCFG1_LFPS | B_XHCI_SSCFG1_PHY_U3)
+ );
+
+ //
+ // XECP_CMDM_CTRL_REG1 - Command Manager Control 1
+ // Address Offset: 818C-818Fh
+ // Value: [20] 0b, [16] 1b, [8] 0b
+ //
+ MmioAndThenOr32 (
+ (XhciMmioBase+R_XHCI_XECP_CMDM_CTRL_REG1),
+ (UINT32) ~(B_XHCI_XECP_MAX_EP | B_XHCI_XECP_CLR_CTX_ENSLOT),
+ (UINT32) (B_XHCI_XECP_TSP)
+ );
+
+ //
+ // XECP_CMDM_CTRL_REG3 - Command Manager Control 3
+ // Address Offset: 8194-8197h
+ // Value: [25] 1b
+ //
+ MmioAndThenOr32 (
+ (XhciMmioBase+R_XHCI_XECP_CMDM_CTRL_REG3),
+ 0xFFFFFFFF,
+ (UINT32) (B_XHCI_XECP_STOP_EP)
+ );
+
+ MmioAndThenOr32 (
+ (XhciMmioBase + R_XHCI_HOST_CTRL_BW_MAX_REG + 4),
+ 0xFFFF000F,
+ (UINT32) (V_XHCI_HOST_CTRL_BW_MAX_REG_TT << 4)
+ );
+
+ //
+ // PMCTRL - Power Management Control
+ // Address Offset: 80A4-80A7h
+ // Value: [31] 0b, [30] 1b, [29] 0b, [25:22] 1111b, [16] 1b, [7:4] 9h, [3] 1 for BXTA0, 0 for all BXT [2] 1b
+ //
+ Data32And = 0x143EFF03;
+ if (BxtStep <= BxtA1) {
+ Data32Or = 0x4BC1009C;
+ } else {
+ Data32Or = 0x4BC10094;
+ }
+ MmioAndThenOr32 (
+ (XhciMmioBase + R_XHCI_PMCTRL),
+ Data32And,
+ Data32Or
+ );
+
+ //
+ // PGCBCTRL - PGCB Control
+ // Address Offset: 80A8-80ABh
+ // Value: [24] 1b
+ //
+ MmioAndThenOr32 (
+ (XhciMmioBase + R_XHCI_PGCBCTRL),
+ ~0u,
+ (UINT32) (B_XHCI_PGCBCTRL_RESET_PREP_DIS)
+ );
+
+ //
+ // SSPE - Super Speed Port Enables
+ // Address Offset: 0x80B8 - 0x80BC
+ // Value: [30] 1b
+ //
+ MmioAndThenOr32 (
+ (XhciMmioBase + R_XHCI_HOST_CONTROLLER_SSPE),
+ ~0u,
+ (UINT32) (B_XHCI_ENCLCCS)
+ );
+
+ //
+ // AUX_CTRL_REG1 - AUX Power Management Control
+ // Address Offset: 80E0-80E3h
+ // Value: [22] 0b, [16] 0b, [9] 0b, [6] 1b
+ //
+ MmioAndThenOr32 (
+ (XhciMmioBase+R_XHCI_AUX_CTRL_REG1),
+ (UINT32) ~(B_XHCI_AUX_ISOLATION | B_XHCI_AUX_PORT_CG | B_XHCI_AUX_CG),
+ (UINT32) (B_XHCI_AUX_P2)
+ );
+
+ //
+ // HOST_CTRL_SCH_REG - Host Control Scheduler
+ // Address Offset: 8094-8097h
+ // Value: [23] 1b, [22] 1b, [21] 0b, [14] 0b, [6] 1b
+ //
+ MmioAndThenOr32 (
+ (XhciMmioBase + R_XHCI_HOST_CTRL_SCH_REG),
+ (UINT32) ~(B_XHCI_HOST_CTRL_DIS_SCH_PKT | B_XHCI_HOST_CTRL_DIS_PKT_CHK),
+ (UINT32) (B_XHCI_HOST_CTRL_DIS_ASYNC | B_XHCI_HOST_CTRL_EN_EP_PPL | B_XHCI_HOST_CTRL_EN_1P_EP_PPL)
+ );
+
+ //
+ // HOST_CTRL_PORT_LINK_REG - SuperSpeed Port Link Control
+ // Address Offset: 0x80EC - 0x80EF
+ // Value: [19] 1b, [17] 1b
+ //
+ Data32And = ~0u;
+ Data32Or = (UINT32) (B_XHCI_HOST_CTRL_EN_TS_EXIT | B_XHCI_HOST_CTRL_PORT_INIT_TIMEOUT);
+ if (UsbConfig->DisableComplianceMode == TRUE) {
+ Data32Or |= B_XHCI_DIS_LINK_CM;
+ }
+ MmioAndThenOr32 (
+ (XhciMmioBase + R_XHCI_HOST_CTRL_PORT_LINK_REG),
+ Data32And,
+ Data32Or
+ );
+ //
+ // USB2_LINK_MGR_CTRL_REG1 - USB2 Port Link Control 1, 2, 3, 4
+ // Address Offset: 0x80F0 - 0x80FF [121] 1b, [20] 0b
+ // [127:96] is mapped to DW4 at offset 80FCh-80FFh [25] 1b
+ // [31:0] is mapped to DW1 at offset 80F0h-80F3h [20] 0b
+ //
+ MmioAndThenOr32 (
+ (XhciMmioBase + R_XHCI_USB2_LINK_MGR_CTRL_REG1),
+ (UINT32) ~(B_XHCI_USB2_LINK_L1_EXIT),
+ 0x0
+ );
+
+ MmioAndThenOr32 (
+ (XhciMmioBase + R_XHCI_USB2_LINK_MGR_CTRL_REG1_CONTROL4),
+ 0xFFFFFFFF,
+ (UINT32)(B_XHCI_USB2_LINK_PRV_L1_ENTRY)
+ );
+
+ //
+ // HOST_CTRL_TRM_REG2 - Host Controller Transfer Manager Control 2
+ // Address Offset: 8110-8113h
+ // Value: [2] 0b, [20] 1b, [11] 1b
+ //
+ MmioAndThenOr32 (
+ (XhciMmioBase + R_XHCI_HOST_CTRL_TRM_REG2),
+ (UINT32) ~(B_XHCI_HOST_CTRL_REDEEM),
+ (UINT32) (B_XHCI_HOST_CTRL_MAX_BURST_CHK | B_XHCI_HOST_CTRL_TRF_PIPE)
+ );
+
+ //
+ // Set xHCIBAR + 8154h[31, 21,13] to 1b, 0b, 1b
+ //
+ MmioAndThenOr32(
+ (XhciMmioBase + R_XHCI_AUX_CTRL_REG2),
+ (UINT32)~(B_XHCI_AUX2_P2_D3HOT),
+ (UINT32) (B_XHCI_AUX2_L1P2_EXIT|B_XHCI_AUX2_PHY_P3)
+ );
+
+ //
+ // xHCI Aux Clock Control Register
+ // Address Offset: 0x816C - 0x816F
+ // [13:12] 00b, [11:8] 0h
+ // [19] 1b, [18] 1b, [17] 1b, [14] 1b, [5] 0b, [4] 1b, [3] 1b, [2] 1b,
+ //
+
+ Data32And = 0xFFF180C3;
+ Data32Or = 0x0002401C;
+ MmioAndThenOr32 (
+ (XhciMmioBase + R_XHCI_AUX_CLOCK_CTRL_REG),
+ Data32And,
+ Data32Or
+ );
+
+ //
+ // HOST_IF_PWR_CTRL_REG0 - Power Scheduler Control 0
+ // Address Offset: 8140-8143h
+ // Value: [31:24] 0xFF, [11:0] 0x03C
+ // [23:12] 0x080 for BXT A step
+ // [23:12] 0x00F for all others steppings
+ //
+ Data32And = 0;
+ Data32Or = 0xFF00F03C;
+ if (BxtStep <= BxtA1) {
+ Data32Or = 0xFF08003C;
+ }
+ MmioAndThenOr32 (
+ (XhciMmioBase + R_XHCI_HOST_IF_PWR_CTRL_REG0),
+ Data32And,
+ Data32Or
+ );
+ //
+ // HOST_IF_PWR_CTRL_REG1 - Power Scheduler Control 1
+ // Address Offset: 8144-8147h
+ // Value: [8] 1b
+ //
+ MmioAndThenOr32 (
+ (XhciMmioBase + R_XHCI_HOST_IF_PWR_CTRL_REG1),
+ ~0u,
+ (UINT32) (B_XHCI_HSII)
+ );
+
+ //
+ // xHC Latency Tolerance Parameters - LTV Control
+ // Address Offset: 0x8174 - 0x8177
+ // Value: [24] 1b, 0b for BXTPA0 [11:0] 0xC0A
+ //
+ Data32And = (UINT32) ~(B_XHCI_USB2_PORT_L0_LTV | B_XHCI_XLTRE);
+ Data32Or = 0x01000C0A;
+ if (BxtStep <= BxtPA0){
+ Data32Or = 0x00000C0A;
+ }
+ MmioAndThenOr32 (
+ (XhciMmioBase + R_XHCI_LATENCY_TOLERANCE_PARAMETERS_LTV_CONTROL),
+ Data32And,
+ Data32Or
+ );
+ //
+ // xHC Latency Tolerance Parameters - High Idle Time Control
+ // Address Offset: 0x817C - 0x817F
+ // Value: [28:16] 0x0332, [12:0] 0x00A3
+ //
+ MmioAndThenOr32 (
+ (XhciMmioBase + R_XHCI_LATENCY_TOLERANCE_PARAMETERS_HIGH_IDLE_TIME_CONTROL),
+ 0xE000E000,
+ 0x033200A3
+ );
+
+ //
+ // xHC Latency Tolerance Parameters - Medium Idle Time Control
+ // Address Offset: 0x8180 - 0x8183
+ // Value: [28:16] 0x00CB, [12:0] 0x0028
+ //
+ MmioAndThenOr32 (
+ (XhciMmioBase + R_XHCI_LATENCY_TOLERANCE_PARAMETERS_MEDIUM_IDLE_TIME_CONTROL),
+ 0xE000E000,
+ 0x00CB0028
+ );
+
+ //
+ // xHC Latency Tolerance Parameters - Low Idle Time Control
+ // Address Offset: 0x8184 - 0x8187
+ // Value: [28:16] 0x0064, [12:0] 0x001E
+ //
+ MmioAndThenOr32 (
+ (XhciMmioBase + R_XHCI_LATENCY_TOLERANCE_PARAMETERS_LOW_IDLE_TIME_CONTROL),
+ 0xE000E000,
+ 0x0064001E
+ );
+
+ //
+ // USB2 PHY Power Management Control
+ // Address Offset: 8164-8167h
+ // Value: [7:0] 11111100b
+ //
+ MmioAndThenOr32 (
+ (XhciMmioBase + R_XHCI_USB2_PHY_POWER_MANAGEMENT_CONTROL),
+ (UINT32) ~(B_XHCI_RX_BIAS_CHT_DIS | B_XHCI_TX_BIAS_CHT_DIS),
+ (UINT32) (B_XHCI_CMAI | B_XHCI_TTEAI | B_XHCI_IDMAAI | B_XHCI_ODMAAI | B_XHCI_TMAI | B_XHCI_SAI)
+ );
+
+ //
+ // Host Controller Misc Reg
+ // Address Offset: 0x80B0 - 0x80B3
+ // Value: [24:23] 01b, [18:16] 000b
+ //
+ MmioAndThenOr32 (
+ (XhciMmioBase + R_XHCI_HOST_CONTROLLER_MISC_REG),
+ (UINT32) ~(B_XHCI_EXTRA_UFRAME | B_XHCI_LATE_FID_CHK_DIS),
+ (UINT32) (B_XHCI_LATE_FID_TTE_DIS)
+ );
+
+ //
+ // Host Controller Misc Reg 2
+ // Address Offset: 0x80B4 - 0x80B7
+ // Value: [2] 1b
+ // 0b for BXT-P B0 and above
+ // [5] 1b for BXT A0 step
+ // [5] 0b for all others steppings
+ //
+ if (BxtStep == BxtA0) {
+ MmioOr32 (
+ (XhciMmioBase + R_XHCI_HOST_CONTROLLER_MISC2REG),
+ (UINT32) (B_XHCI_FRAME_TIM_SEL | B_XHCI_WARM_PORT_RESET_ON_DISC_PORT_DIS)
+ );
+ } else if (BxtStep >= BxtPB0) {
+ MmioAnd32 (
+ (XhciMmioBase + R_XHCI_HOST_CONTROLLER_MISC2REG),
+ (UINT32) ~(B_XHCI_FRAME_TIM_SEL | B_XHCI_WARM_PORT_RESET_ON_DISC_PORT_DIS)
+ );
+ } else {
+ MmioAndThenOr32 (
+ (XhciMmioBase + R_XHCI_HOST_CONTROLLER_MISC2REG),
+ (UINT32) ~(B_XHCI_FRAME_TIM_SEL),
+ (UINT32) (B_XHCI_WARM_PORT_RESET_ON_DISC_PORT_DIS)
+ );
+ }
+ //
+ // LFPSONCOUNT - LFPS On Count
+ // Address Offset: 0x81B8 - 0x81BB
+ // Value: [15:10] 02h, [9:0] 02h
+ //
+ MmioAndThenOr32 (
+ (XhciMmioBase + R_XHCI_LFPS_ON_COUNT),
+ (UINT32) ~(B_XHCI_XLFPSONCNTSSIC | B_XHCI_XLFPSONCNTSS),
+ (UINT32) (0x0802)
+ );
+
+ //
+ // D0I2CTRL - D0I2 Control Register
+ // Address Offset: 81BC-81BFh
+ // Value: [31] 1b, [29:26] 04h, [25:22] 04h, [21] 0b, [20:16] 04h, [15:4] 20h, [3:0] 0h
+ //
+
+ MmioAndThenOr32 (
+ (XhciMmioBase + R_XHCI_D0I2_CONTROL),
+ 0x40000000,
+ 0x91040200
+ );
+
+ //
+ // D0I2SchAlarmCtrl - D0i2 Scheduler Alram Control Reg
+ // Address Offset: 81C0-81C3h
+ // Value: [28:16] 0Fh, [12:0] 05h
+ //
+ MmioAndThenOr32 (
+ (XhciMmioBase + R_XHCI_D0I2_SCH_ALARM_CTRL),
+ 0xE000E000,
+ 0x000F0005
+ );
+
+ //
+ // USB2PMCTRL - USB2 Power Management Control
+ // Address Offset: 0x81C4 - 0x81C7
+ // Value: [11] 1b, [10:8] 001b, [3:2] 00b, [1:0] 11b
+ //
+ MmioAndThenOr32 (
+ (XhciMmioBase + R_XHCI_USB2_PM_CTRL),
+ (UINT32) ~(B_XHCI_U2PSPGEHC | B_XHCI_U2PSUSPGP),
+ (UINT32) (B_XHCI_U2PSPGPSCBP | BIT8 | B_XHCI_U2PSUSPGP_Shadow)
+ );
+
+ //
+ // Set xHCIBAR + 8178h[12:0] to 0h
+ //
+ MmioAndThenOr32 (
+ (XhciMmioBase + 0x8178),
+ (UINT32)~(0xFFFFE000),
+ (UINT32) (0x00)
+ );
+
+ if (UsbConfig->XdciConfig.Enable != ScDisabled) {
+ MmioAndThenOr32 (
+ (XhciMmioBase + R_XHCI_MEM_DUAL_ROLE_CFG0),
+ 0,
+ (UINT32) BIT24
+ );
+
+ MmioAndThenOr32 (
+ (XhciMmioBase + R_XHCI_MEM_DUAL_ROLE_CFG0),
+ 0,
+ (UINT32) (BIT21 | BIT20)
+ );
+ //
+ // Step 2
+ // Poll xHCI BAR + DUAL_ROLE_CFG1 [29] until it reads 0b or else 5ms timeout.
+ //
+ BitMask = (UINT32) (BIT29);
+ BitValue = 0;
+ Status = ScMmioPoll32 (
+ (UINTN) (XhciMmioBase + R_XHCI_MEM_DUAL_ROLE_CFG1),
+ BitMask,
+ BitValue,
+ 50
+ );
+ if (Status == EFI_TIMEOUT) {
+ DEBUG ((DEBUG_ERROR | DEBUG_INFO, "USBCommonlib.c Timeout while polling on xHCI BAR + R_XHCI_MEM_DUAL_ROLE_CFG1 [29] for 0b\n"));
+ }
+ }
+ DEBUG ((DEBUG_INFO, "R_XHCI_MEM_DUAL_ROLE_CFG0=%x\n", MmioRead32(XhciMmioBase + R_XHCI_MEM_DUAL_ROLE_CFG0)));
+}
+
+
+/**
+ Initialization XHCI Clock Gating registers
+
+ @retval None
+
+**/
+VOID
+ConfigureXhciClockGating (
+ VOID
+ )
+{
+ UINTN XhciPciMmBase;
+ UINT32 Data32And;
+ UINT32 Data32Or;
+ BXT_STEPPING BxtStep;
+
+ XhciPciMmBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_SC,
+ PCI_DEVICE_NUMBER_XHCI,
+ PCI_FUNCTION_NUMBER_XHCI
+ );
+
+ if (XhciPciMmBase == 0xFFFFFFFF) { // controller absence or function disable
+ DEBUG ((DEBUG_INFO , "XHCI controller absence or function disable, skip setting clock gating.\n"));
+ return;
+ }
+
+ BxtStep = BxtStepping ();
+
+ //
+ // XHCC1 - XHC System Bus Configuration 1
+ // Address Offset: 40-43h
+ // Value: [21:19] 110b, [18] 1b, [8] 1b
+ // Writes to this registers needs to be performed per bytes to avoid touching bit 31
+ // Bit 31 is used to lock RW/L bits and can be writen once.
+ //
+ MmioOr8 (
+ XhciPciMmBase + R_XHCI_XHCC1 + 1,
+ BIT0
+ );
+ MmioOr8 (
+ XhciPciMmBase + R_XHCI_XHCC1 + 2,
+ (BIT5 | BIT4 | BIT2)
+ );
+
+ //
+ // HSCFG1 - High Speed Configuration 1
+ // Address Offset: AC-AFh
+ // Value: [19] 0b, [18] 1b
+ //
+ MmioAndThenOr32 (
+ (UINTN) (XhciPciMmBase + R_XHCI_HSCFG1),
+ (UINT32) ~(B_XHCI_HSCFG1_UTMI_SUSPEND_CG),
+ (UINT32) (B_XHCI_HSCFG1_UTMI_SPEED_CG)
+ );
+
+ //
+ // XHCLKGTEN - Clock Gating
+ // Address Offset: 50-53h
+ // Value: [28] 0b, [27:24] 1111b, [23:20] 1100b, [19:16] 1110b, [15:8] 01101110b, [7:0] 01011111b
+ //
+ Data32And = 0xE0000000;
+ if (BxtStep == BxtPA0 && mBootMode == BOOT_ON_S3_RESUME) {
+
+ Data32Or = 0x0FDF6D3F;
+ MmioAndThenOr32 (
+ (UINTN) (XhciPciMmBase + R_XHCI_XHCLKGTEN),
+ Data32And,
+ Data32Or
+ );
+ DEBUG ((DEBUG_INFO , "Putting xHCI into D3 Hot State.\n"));
+ MmioOr32 ((UINT32) (XhciPciMmBase + R_XHCI_PWR_CNTL_STS), B_XHCI_PWR_CNTL_STS_PWR_STS);
+ MicroSecondDelay (20);
+ DEBUG ((DEBUG_INFO , "Putting xHCI into D0 State.\n"));
+ MmioAnd32 ((UINT32) (XhciPciMmBase + R_XHCI_PWR_CNTL_STS), (UINT32) ~ (B_XHCI_PWR_CNTL_STS_PWR_STS));
+ } else {
+ Data32Or = 0x0FCE6E5F;
+ MmioAndThenOr32 (
+ (UINTN) (XhciPciMmBase + R_XHCI_XHCLKGTEN),
+ Data32And,
+ Data32Or
+ );
+ }
+}
+
+
+/**
+ Lock USB registers before boot
+
+ @param[in] ScPolicy The SC Policy
+
+ @retval None
+
+**/
+VOID
+UsbInitBeforeBoot (
+ IN SI_POLICY_HOB *SiPolicyHob,
+ IN SC_POLICY_HOB *ScPolicyHob
+ )
+{
+ UINTN XhciPciMmBase;
+ SC_USB_CONFIG *UsbConfig;
+ EFI_STATUS Status;
+
+ XhciPciMmBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_SC,
+ PCI_DEVICE_NUMBER_XHCI,
+ PCI_FUNCTION_NUMBER_XHCI
+ );
+ Status = GetConfigBlock ((VOID *) ScPolicyHob, &gUsbConfigGuid, (VOID *) &UsbConfig);
+ ASSERT_EFI_ERROR (Status);
+
+ if (UsbConfig->Usb30Settings.Mode != XHCI_MODE_OFF) {
+ //
+ // Set xHCI MSI_MCTL According to OS:
+ // Windows: D3 Supported - Set to 1h to enable MSI
+ // Android: D0i3/DevIdle Supported (legacy interrupts used in D0i3 flows) - Set to 0h to disable MSI
+ //
+ if (MmioRead32((UINTN)(XhciPciMmBase)) != 0xFFFFFFFF) {
+ if (SiPolicyHob->OsSelection == SiAndroid) {
+ //
+ // MSI capability structure must not be reported for Android to use line based interrupts.
+ // Linux driver will use MSI if reported and wake flows require line based interrupts.
+ //
+ MmioAnd16(XhciPciMmBase + R_XHCI_MSI_MCTL, (UINT16)~(B_XHCI_MSI_MCTL_MSIENABLE));
+ } else {
+ MmioOr16(XhciPciMmBase + R_XHCI_MSI_MCTL, B_XHCI_MSI_MCTL_MSIENABLE);
+ }
+ } else {
+ DEBUG ((EFI_D_ERROR, "xHCI not present, cannot disable the xHCI MSI capability structure for Android.\n"));
+ }
+
+ MmioOr32 (XhciPciMmBase + R_XHCI_XHCC2, B_XHCI_XHCC2_OCCFDONE);
+ INIT_COMMON_SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (XhciPciMmBase + R_XHCI_XHCC2),
+ 1,
+ (VOID *) (UINTN) (XhciPciMmBase + R_XHCI_XHCC2)
+ );
+
+ MmioOr32 (XhciPciMmBase + R_XHCI_XHCC1, B_XHCI_XHCC1_ACCTRL | B_XHCI_XHCC1_URD);
+ INIT_COMMON_SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (XhciPciMmBase + R_XHCI_XHCC1),
+ 1,
+ (VOID *) (UINTN) (XhciPciMmBase + R_XHCI_XHCC1)
+ );
+ }
+}
+
+
+/**
+ Setup XHCI Over-Current Mapping
+
+ @param[in] UsbConfig The SC Policy for USB configuration
+ @param[in] XhciPciMmBase XHCI PCI Base Address
+
+ @retval None
+
+**/
+VOID
+XhciOverCurrentMapping (
+ IN SC_USB_CONFIG *UsbConfig,
+ IN UINTN XhciPciMmBase
+ )
+{
+ //
+ // BIOS responsibility on Overcurrent protection.
+ // ----------------------------------------------
+ // The max can be total 8 overcurrent pins
+ // OC0: Used for the OTG port (port 0)
+ // OC1: Used for the 2 host walk-up ports (ports 1 to 5)
+ // It is ok to map multiple ports to a single pin.
+ // It is not ok to map a single ports to a multiple pins.
+ // All USB ports routed out of the package must have Overcurrent protection.
+ // USB Ports not routed out from the package should not be assigned OC pins.
+ //
+ UINT32 Index;
+ UINT32 U2OCMBuf[V_XHCI_NUMBER_OF_OC_PINS] = {0};
+ UINT32 U3OCMBuf[V_XHCI_NUMBER_OF_OC_PINS] = {0};
+ UINT32 OCPin;
+
+ for (Index = 0; Index < GetScXhciMaxUsb3PortNum (); Index++) {
+ if (UsbConfig->PortUsb30[Index].OverCurrentPin == ScUsbOverCurrentPinSkip) {
+ //
+ // No OC pin assigned, skip this port
+ //
+ } else {
+ OCPin = UsbConfig->PortUsb30[Index].OverCurrentPin;
+ ASSERT (OCPin < V_XHCI_NUMBER_OF_OC_PINS);
+ U3OCMBuf[OCPin] |= (UINT32) (BIT0 << Index);
+ }
+ }
+ for (Index = 0; Index < V_XHCI_NUMBER_OF_OC_PINS; Index++) {
+ MmioWrite32 (XhciPciMmBase + R_XHCI_U3OCM + (Index * 4), U3OCMBuf[Index]);
+ }
+
+ for (Index = 0; Index < GetScXhciMaxUsb2PortNum (); Index++) {
+ if (UsbConfig->PortUsb20[Index].OverCurrentPin == ScUsbOverCurrentPinSkip) {
+ //
+ // No OC pin assigned, skip this port
+ //
+ } else {
+ OCPin = UsbConfig->PortUsb20[Index].OverCurrentPin;
+ ASSERT (OCPin < V_XHCI_NUMBER_OF_OC_PINS);
+ U2OCMBuf[OCPin] |= (UINT32) (BIT0 << Index);
+ }
+ }
+
+ for (Index = 0; Index < V_XHCI_NUMBER_OF_OC_PINS; Index++) {
+ MmioWrite32 (XhciPciMmBase + R_XHCI_U2OCM + (Index * 4), U2OCMBuf[Index]);
+ }
+
+}
+
+
+/**
+ Program Xhci Port Disable Override
+
+ @param[in] UsbConfig The SC Policy for USB configuration
+ @param[in] XhciPciMmBase XHCI PCI Base Address
+
+ @retval None
+**/
+VOID
+XhciPortDisableOverride (
+ IN SC_USB_CONFIG *UsbConfig,
+ IN UINTN XhciMmioBase
+ )
+{
+ UINT32 Index;
+ UINT32 XhciUsb2Pdo = 0;
+ UINT32 XhciUsb3Pdo = 0;
+ BXT_SERIES BxtSeries;
+
+ BxtSeries = GetBxtSeries ();
+ switch (BxtSeries) {
+ case Bxt:
+ XhciUsb2Pdo = MmioRead32 (XhciMmioBase + R_XHCI_USB2PDO) & B_XHCI_BXT_USB2PDO_MASK;
+ XhciUsb3Pdo = MmioRead32 (XhciMmioBase + R_XHCI_USB3PDO) & B_XHCI_BXT_USB3PDO_MASK;
+ break;
+ case BxtP:
+ XhciUsb2Pdo = MmioRead32 (XhciMmioBase + R_XHCI_USB2PDO) & B_XHCI_BXTP_USB2PDO_MASK;
+ XhciUsb3Pdo = MmioRead32 (XhciMmioBase + R_XHCI_USB3PDO) & B_XHCI_BXTP_USB3PDO_MASK;
+ break;
+ default:
+ break;
+ }
+ //
+ // XHCI PDO for HS
+ //
+ for (Index = 0; Index < GetScXhciMaxUsb2PortNum(); Index++) {
+ if (UsbConfig->PortUsb20[Index].Enable == FALSE) {
+ XhciUsb2Pdo |= (UINT32) (B_XHCI_USB2PDO_DIS_PORT0 << Index);
+ } else {
+ XhciUsb2Pdo &= (UINT32)~(B_XHCI_USB2PDO_DIS_PORT0 << Index);
+ }
+ }
+ //
+ // XHCI PDO for SS
+ //
+ for (Index = 0; Index < GetScXhciMaxUsb3PortNum(); Index++) {
+ if (UsbConfig->PortUsb30[Index].Enable == FALSE) {
+ XhciUsb3Pdo |= (UINT32) (B_XHCI_USB3PDO_DIS_PORT0 << Index);
+ } else {
+ XhciUsb3Pdo &= (UINT32)~(B_XHCI_USB3PDO_DIS_PORT0 << Index);
+ }
+ }
+ //
+ // USB2PDO and USB3PDO are Write-Once registers and bits in them are in the SUS Well.
+ //
+ MmioWrite32 (XhciMmioBase + R_XHCI_USB2PDO, XhciUsb2Pdo);
+ MmioWrite32 (XhciMmioBase + R_XHCI_USB3PDO, XhciUsb3Pdo);
+}
+
+
+/**
+ Program and enable XHCI Memory Space
+
+ @param[in] UsbConfig The SC Policy for USB configuration
+ @param[in] XhciMmioBase Memory base address of XHCI Controller
+ @param[in] XhciPciMmBase XHCI PCI Base Address
+
+ @retval None
+
+**/
+VOID
+XhciMemorySpaceOpen (
+ IN SC_USB_CONFIG *UsbConfig,
+ IN UINT32 XhciMmioBase,
+ IN UINTN XhciPciMmBase
+ )
+{
+ //
+ // Assign memory resources
+ //
+ MmioAnd16 (
+ XhciPciMmBase + R_XHCI_COMMAND_REGISTER,
+ (UINT16)~(B_XHCI_COMMAND_MSE | B_XHCI_COMMAND_BME)
+ );
+ MmioWrite32 (XhciPciMmBase + R_XHCI_MEM_BASE, XhciMmioBase);
+ MmioOr16 (
+ XhciPciMmBase + R_XHCI_COMMAND_REGISTER,
+ (UINT16) (B_XHCI_COMMAND_MSE | B_XHCI_COMMAND_BME)
+ );
+}
+
+
+/**
+ Clear and disable XHCI Memory Space
+
+ @param[in] UsbConfig The SC Policy for USB configuration
+ @param[in] XhciMmioBase Memory base address of XHCI Controller
+ @param[in] XhciPciMmBase XHCI PCI Base Address
+
+ @retval None
+
+**/
+VOID
+XhciMemorySpaceClose (
+ IN SC_USB_CONFIG *UsbConfig,
+ IN UINT32 XhciMmioBase,
+ IN UINTN XhciPciMmBase
+ )
+{
+ //
+ // Clear memory resources
+ //
+ MmioAnd16 (
+ XhciPciMmBase + R_XHCI_COMMAND_REGISTER,
+ (UINT16)~(B_XHCI_COMMAND_MSE | B_XHCI_COMMAND_BME)
+ );
+
+ MmioWrite32 ((XhciPciMmBase + R_XHCI_MEM_BASE), 0);
+
+}
+
+/**
+ Initialization USB Clock Gating registers
+
+ @retval None
+
+**/
+VOID
+ConfigureUsbClockGating (
+ VOID
+ )
+{
+ ConfigureXhciClockGating ();
+}
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/ScPlatformLib/ScCycleDecoding.c b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/ScPlatformLib/ScCycleDecoding.c
new file mode 100644
index 0000000000..65ee993a9c
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/ScPlatformLib/ScCycleDecoding.c
@@ -0,0 +1,739 @@
+/** @file
+ Access to SC relevant IP base addresses.
+
+ Copyright (c) 2013 - 2016, 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.
+
+**/
+
+#include "ScPlatformLibrary.h"
+
+EFI_STATUS
+EFIAPI
+PchAcpiBaseSet (
+ IN UINT16 Address
+ )
+{
+ return EFI_SUCCESS;
+}
+
+/**
+ Get PCH ACPI base address.
+
+ @param[in] Address Address of ACPI base address.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid pointer passed.
+
+**/
+EFI_STATUS
+EFIAPI
+PchAcpiBaseGet (
+ IN UINT16 *Address
+ )
+{
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+PchPwrmBaseSet (
+ IN UINT32 Address
+ )
+{
+ return EFI_SUCCESS;
+}
+
+/**
+ Get PCH PWRM base address.
+
+ @param[in] Address Address of PWRM base address.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid pointer passed.
+
+**/
+EFI_STATUS
+EFIAPI
+PchPwrmBaseGet (
+ IN UINT32 *Address
+ )
+{
+ return EFI_SUCCESS;
+}
+
+/**
+ Set TCO base address for legacy Smbus
+
+ @param[in] Address Address for TCO base address.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid base address passed.
+ @retval EFI_UNSUPPORTED DMIC.SRL is set.
+
+**/
+EFI_STATUS
+EFIAPI
+SetTcoBase (
+ IN UINT16 Address
+ )
+{
+ UINTN SmbusBase;
+
+ if ((Address & B_SMBUS_TCOBASE_BAR) == 0) {
+ DEBUG ((DEBUG_ERROR, "SetTcoBase Error. Invalid Address: %x.\n", Address));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ SmbusBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_SC,
+ PCI_DEVICE_NUMBER_SMBUS,
+ PCI_FUNCTION_NUMBER_SMBUS
+ );
+ if (MmioRead16 (SmbusBase) == 0xFFFF) {
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+ //
+ // Verify TCO base is not locked.
+ //
+ if ((MmioRead8 (SmbusBase + R_SMBUS_TCOCTL) & R_SMBUS_TCOCTL_TCO_BASE_LOCK) != 0) {
+ ASSERT (FALSE);
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Disable TCO in SMBUS Device first before changing base address.
+ //
+ MmioAnd16 (
+ SmbusBase + R_SMBUS_TCOCTL,
+ (UINT16) ~B_SMBUS_TCOCTL_TCO_BASE_EN
+ );
+ //
+ // Program TCO in SMBUS Device
+ //
+ MmioAndThenOr16 (
+ SmbusBase + R_SMBUS_TCOBASE,
+ (UINT16) (~B_SMBUS_TCOBASE_BAR),
+ Address
+ );
+ //
+ // Enable TCO in SMBUS Device
+ //
+ MmioOr16 (
+ SmbusBase + R_SMBUS_TCOCTL,
+ B_SMBUS_TCOCTL_TCO_BASE_EN
+ );
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Get TCO base address.
+
+ @param[in] Address Address of TCO base address.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid pointer passed.
+
+**/
+EFI_STATUS
+EFIAPI
+GetTcoBase (
+ IN UINT16 *Address
+ )
+{
+ UINTN SmbusBase;
+
+ if (Address == NULL) {
+ DEBUG((DEBUG_ERROR, "GetTcoBase Error. Invalid pointer.\n"));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ SmbusBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_SC,
+ PCI_DEVICE_NUMBER_SMBUS,
+ PCI_FUNCTION_NUMBER_SMBUS
+ );
+ if (MmioRead16 (SmbusBase) == 0xFFFF) {
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+ *Address = MmioRead16 (SmbusBase + R_SMBUS_TCOBASE) & B_SMBUS_TCOBASE_BAR;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+PchLpcGenIoRangeSet (
+ IN UINT16 Address,
+ IN UINTN Length
+ )
+{
+ EFI_STATUS Status;
+ PCH_LPC_GEN_IO_RANGE_LIST LpcGenIoRangeList;
+ UINTN LpcBase;
+ UINTN Index;
+ UINTN BaseAddr;
+ UINTN MaskLength;
+ UINTN TempMaxAddr;
+ UINT32 Data32;
+ UINTN ArraySize;
+ static struct EXCEPT_RANGE {
+ UINT8 Start;
+ UINT8 Length;
+ } ExceptRanges[] = { {0x00, 0x20}, {0x44, 0x08}, {0x54, 0x0C}, {0x68, 0x08}, {0x80, 0x10}, {0x90, 0x10}, {0xC0, 0x40} };
+
+ if (((Length & (Length - 1)) != 0) ||
+ ((Address & (UINT16)~B_PCH_LPC_GENX_DEC_IOBAR) != 0) ||
+ (Length > 256))
+ {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+ if (Address < 0x100) {
+ ArraySize = sizeof (ExceptRanges) / sizeof (struct EXCEPT_RANGE);
+ for (Index = 0; Index < ArraySize; Index++) {
+ if ((Address >= ExceptRanges[Index].Start) &&
+ ((Address + Length) <= ((UINTN) ExceptRanges[Index].Start + (UINTN) ExceptRanges[Index].Length))) {
+ break;
+ }
+ }
+ if (Index >= ArraySize) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ //
+ // check if range overlap
+ //
+ Status = PchLpcGenIoRangeGet (&LpcGenIoRangeList);
+ if (EFI_ERROR (Status)) {
+ ASSERT (FALSE);
+ return Status;
+ }
+
+ for (Index = 0; Index < PCH_LPC_GEN_IO_RANGE_MAX; Index++) {
+ BaseAddr = LpcGenIoRangeList.Range[Index].BaseAddr;
+ MaskLength = LpcGenIoRangeList.Range[Index].Length;
+ if (BaseAddr == 0) {
+ continue;
+ }
+ if (((Address >= BaseAddr) && (Address < (BaseAddr + MaskLength))) ||
+ (((Address + Length) > BaseAddr) && ((Address + Length) <= (BaseAddr + MaskLength)))) {
+ if ((Address >= BaseAddr) && (Length <= MaskLength)) {
+ //
+ // return SUCCESS while range is covered.
+ //
+ return EFI_SUCCESS;
+ }
+
+ if ((Address + Length) > (BaseAddr + MaskLength)) {
+ TempMaxAddr = Address + Length;
+ } else {
+ TempMaxAddr = BaseAddr + MaskLength;
+ }
+ if (Address > BaseAddr) {
+ Address = (UINT16) BaseAddr;
+ }
+ Length = TempMaxAddr - Address;
+ break;
+ }
+ }
+ //
+ // If no range overlap
+ //
+ if (Index >= PCH_LPC_GEN_IO_RANGE_MAX) {
+ //
+ // Find a empty register
+ //
+ for (Index = 0; Index < PCH_LPC_GEN_IO_RANGE_MAX; Index++) {
+ BaseAddr = LpcGenIoRangeList.Range[Index].BaseAddr;
+ if (BaseAddr == 0) {
+ break;
+ }
+ }
+ if (Index >= PCH_LPC_GEN_IO_RANGE_MAX) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ }
+ //
+ // Program LPC/eSPI generic IO range register accordingly.
+ //
+ LpcBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_SC,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC
+ );
+ Data32 = (UINT32) (((Length - 1) << 16) & B_PCH_LPC_GENX_DEC_IODRA);
+ Data32 |= (UINT32) Address;
+ Data32 |= B_PCH_LPC_GENX_DEC_EN;
+ //
+ // Program LPC/eSPI PCI Offset 84h ~ 93h of Mask, Address, and Enable.
+ //
+ MmioWrite32 (
+ LpcBase + R_PCH_LPC_GEN1_DEC + Index * 4,
+ Data32
+ );
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Get PCH LPC/eSPI generic IO range list.
+ This function returns a list of base address, length, and enable for all LPC/eSPI generic IO range regsiters.
+
+ @param[out] LpcGenIoRangeList Return all LPC/eSPI generic IO range register status.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid base address passed.
+
+**/
+EFI_STATUS
+EFIAPI
+PchLpcGenIoRangeGet (
+ OUT PCH_LPC_GEN_IO_RANGE_LIST *LpcGenIoRangeList
+ )
+{
+ UINTN Index;
+ UINTN LpcBase;
+ UINT32 Data32;
+
+ if (LpcGenIoRangeList == NULL) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ LpcBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_SC,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC
+ );
+
+ for (Index = 0; Index < PCH_LPC_GEN_IO_RANGE_MAX; Index++) {
+ Data32 = MmioRead32 (LpcBase + R_PCH_LPC_GEN1_DEC + Index * 4);
+ LpcGenIoRangeList->Range[Index].BaseAddr = Data32 & B_PCH_LPC_GENX_DEC_IOBAR;
+ LpcGenIoRangeList->Range[Index].Length = ((Data32 & B_PCH_LPC_GENX_DEC_IODRA) >> 16) + 4;
+ LpcGenIoRangeList->Range[Index].Enable = Data32 & B_PCH_LPC_GENX_DEC_EN;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+PchLpcMemRangeSet (
+ IN UINT32 Address
+ )
+{
+ UINTN LpcBase;
+
+ if ((Address & (~B_PCH_LPC_LGMR_MA)) != 0) {
+ DEBUG ((DEBUG_ERROR, "PchLpcMemRangeSet Error. Invalid Address: %x.\n", Address));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ LpcBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_SC,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC
+ );
+
+ //
+ // Program LPC/eSPI PCI Offset 98h [0] to [0] to disable memory decoding first before changing base address.
+ //
+ MmioAnd32 (
+ LpcBase + R_PCH_LPC_LGMR,
+ (UINT32) ~B_PCH_LPC_LGMR_LMRD_EN
+ );
+
+ //
+ // Program LPC/eSPI PCI Offset 98h [31:16, 0] to [Address, 1].
+ //
+ MmioWrite32 (
+ LpcBase + R_PCH_LPC_LGMR,
+ (Address | B_PCH_LPC_LGMR_LMRD_EN)
+ );
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Get PCH LPC/eSPI memory range decoding address.
+
+ @param[in] Address Address of LPC/eSPI memory decoding base address.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid base address passed.
+
+**/
+EFI_STATUS
+EFIAPI
+PchLpcMemRangeGet (
+ IN UINT32 *Address
+ )
+{
+ UINTN LpcBase;
+
+ if (Address == NULL) {
+ DEBUG ((DEBUG_ERROR, "PchLpcMemRangeGet Error. Invalid pointer.\n"));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ LpcBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_SC,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC
+ );
+ *Address = MmioRead32 (LpcBase + R_PCH_LPC_LGMR) & B_PCH_LPC_LGMR_MA;
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Set PCH BIOS range deocding.
+ This will check General Control and Status bit 10 (GCS.BBS) to identify SPI or LPC/eSPI and program BDE register accordingly.
+ Please check EDS for detail of BiosDecodeEnable bit definition.
+ bit 15: F8-FF Enable
+ bit 14: F0-F8 Enable
+ bit 13: E8-EF Enable
+ bit 12: E0-E8 Enable
+ bit 11: D8-DF Enable
+ bit 10: D0-D7 Enable
+ bit 9: C8-CF Enable
+ bit 8: C0-C7 Enable
+ bit 7: Legacy F Segment Enable
+ bit 6: Legacy E Segment Enable
+ bit 5: Reserved
+ bit 4: Reserved
+ bit 3: 70-7F Enable
+ bit 2: 60-6F Enable
+ bit 1: 50-5F Enable
+ bit 0: 40-4F Enable
+ This cycle decoding is allowed to set when DMIC.SRL is 0.
+ Programming steps:
+ 1. if GCS.BBS is 0 (SPI), program SPI offset D8h to BiosDecodeEnable.
+ if GCS.BBS is 1 (LPC/eSPi), program LPC offset D8h to BiosDecodeEnable.
+ 2. program LPC BIOS Decode Enable, PCR[DMI] + 2744h to the same value programmed in LPC or SPI Offset D8h.
+
+ @param[in] BiosDecodeEnable Bios decode enable setting.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_UNSUPPORTED DMIC.SRL is set.
+
+**/
+EFI_STATUS
+EFIAPI
+PchBiosDecodeEnableSet (
+ IN UINT16 BiosDecodeEnable
+ )
+{
+ UINTN BaseAddr;
+ UINT8 Bbs;
+
+ BaseAddr = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_SC,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC
+ );
+ Bbs = MmioRead8(BaseAddr + R_PCH_LPC_BC) & B_PCH_LPC_BC_BBS;
+ //
+ // Check General Control and Status (GCS) [10]
+ // '0': SPI
+ // '1': LPC/eSPI
+ //
+ if (Bbs == 0) {
+ BaseAddr = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_SC,
+ PCI_DEVICE_NUMBER_SPI,
+ PCI_FUNCTION_NUMBER_SPI
+ );
+ //
+ // if GCS.BBS is 0 (SPI), program SPI offset D8h to BiosDecodeEnable.
+ //
+ MmioWrite16 (BaseAddr + R_SPI_BDE, BiosDecodeEnable);
+ } else {
+ BaseAddr = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_SC,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC
+ );
+ //
+ // if GCS.BBS is 1 (LPC/eSPI), program LPC offset D8h to BiosDecodeEnable.
+ //
+ MmioWrite16 (BaseAddr + R_PCH_LPC_BDE, BiosDecodeEnable);
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Set PCH LPC/eSPI IO decode ranges.
+ Program LPC/eSPI I/O Decode Ranges, PCR[DMI] + 2770h[15:0] to the same value programmed in LPC/eSPI PCI offset 80h.
+ Please check EDS for detail of LPC/eSPI IO decode ranges bit definition.
+ Bit 12: FDD range
+ Bit 9:8: LPT range
+ Bit 6:4: ComB range
+ Bit 2:0: ComA range
+
+ @param[in] LpcIoDecodeRanges LPC/eSPI IO decode ranges bit settings.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_UNSUPPORTED DMIC.SRL is set.
+
+**/
+EFI_STATUS
+EFIAPI
+PchLpcIoDecodeRangesSet (
+ IN UINT16 LpcIoDecodeRanges
+ )
+{
+ UINTN LpcBaseAddr;
+
+ //
+ // Note: Inside this function, don't use debug print since it's could used before debug print ready.
+ //
+ LpcBaseAddr = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_SC,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC
+ );
+ //
+ // check if setting is identical
+ //
+ if (LpcIoDecodeRanges == MmioRead16 (LpcBaseAddr + R_PCH_LPC_IOD)) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // program LPC/eSPI PCI offset 80h.
+ //
+ MmioWrite16 (LpcBaseAddr + R_PCH_LPC_IOD, LpcIoDecodeRanges);
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Set PCH LPC/eSPI IO enable decoding.
+ Setup LPC/eSPI I/O Enables, PCR[DMI] + 2774h[15:0] to the same value program in LPC/eSPI PCI offset 82h.
+ Note: Bit[15:10] of the source decode register is Read-Only. The IO range indicated by the Enables field
+ in LPC/eSPI PCI offset 82h[13:10] is always forwarded by DMI to subtractive agent for handling.
+ Please check EDS for detail of Lpc/eSPI IO decode ranges bit definition.
+
+ @param[in] LpcIoEnableDecoding LPC/eSPI IO enable decoding bit settings.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_UNSUPPORTED DMIC.SRL is set.
+
+**/
+EFI_STATUS
+EFIAPI
+PchLpcIoEnableDecodingSet (
+ IN UINT16 LpcIoEnableDecoding
+ )
+{
+ UINTN LpcBaseAddr;
+
+ //
+ // Note: Inside this function, don't use debug print since it's could used before debug print ready.
+ //
+ LpcBaseAddr = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_SC,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC
+ );
+
+ if (LpcIoEnableDecoding == MmioRead16 (LpcBaseAddr + R_PCH_LPC_IOE)) {
+ return EFI_SUCCESS;
+ }
+ //
+ // program LPC/eSPI PCI offset 82h.
+ //
+ MmioWrite16 (LpcBaseAddr + R_PCH_LPC_IOE, LpcIoEnableDecoding);
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Set PCH TraceHub base address.
+ This cycle decoding is allowed to set when DMIC.SRL is 0.
+ Programming steps:
+ 1. Program TraceHub PCI Offset 0x70~0x77 to the 64-bit base address.
+ 2. Program PCR[PSF3] + TraceHub RS0 offset 0x000 and 0x004 to TraceHub 64-bit base address.
+ 3. Manually write 1 to MSEN, PCR[PSF3] + TraceHub RS0 offset 0x01C[1] to activate the shadow.
+
+ @param[in] AddressHi High 32-bits for TraceHub base address.
+ @param[in] AddressLo Low 32-bits for TraceHub base address.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_UNSUPPORTED DMIC.SRL is set.
+
+**/
+EFI_STATUS
+EFIAPI
+PchTraceHubBaseSet (
+ IN UINT32 AddressHi,
+ IN UINT32 AddressLo
+ )
+{
+ return EFI_SUCCESS;
+}
+
+//
+// PCH-LP RPR destination ID table
+//
+UINT16 PchLpRprDidTable[] = {
+ 0x2188, ///< Dest ID of RP1
+ 0x2189, ///< Dest ID of RP2
+ 0x218A, ///< Dest ID of RP3
+ 0x218B, ///< Dest ID of RP4
+ 0x2198, ///< Dest ID of RP5
+ 0x2199, ///< Dest ID of RP6
+ 0x219A, ///< Dest ID of RP7
+ 0x219B, ///< Dest ID of RP8
+ 0x21A8, ///< Dest ID of RP9
+ 0x21A9, ///< Dest ID of RP10
+ 0x21AA, ///< Dest ID of RP11
+ 0x21AB ///< Dest ID of RP12
+};
+
+//
+// PCH-H RPR destination ID table
+//
+UINT16 PchHRprDidTable[] = {
+ 0x2180, ///< Dest ID of RP1
+ 0x2181, ///< Dest ID of RP2
+ 0x2182, ///< Dest ID of RP3
+ 0x2183, ///< Dest ID of RP4
+ 0x2188, ///< Dest ID of RP5
+ 0x2189, ///< Dest ID of RP6
+ 0x218A, ///< Dest ID of RP7
+ 0x218B, ///< Dest ID of RP8
+ 0x2198, ///< Dest ID of RP9
+ 0x2199, ///< Dest ID of RP10
+ 0x219A, ///< Dest ID of RP11
+ 0x219B, ///< Dest ID of RP12
+ 0x21A8, ///< Dest ID of RP13
+ 0x21A9, ///< Dest ID of RP14
+ 0x21AA, ///< Dest ID of RP15
+ 0x21AB, ///< Dest ID of RP16
+ 0x21B8, ///< Dest ID of RP17
+ 0x21B9, ///< Dest ID of RP18
+ 0x21BA, ///< Dest ID of RP19
+ 0x21BB, ///< Dest ID of RP20
+};
+
+/**
+ Set PCH IO port 80h cycle decoding to PCIE root port.
+ System BIOS is likely to do this very soon after reset before PCI bus enumeration.
+ This cycle decoding is allowed to set when DMIC.SRL is 0.
+ Programming steps:
+ 1. Program "RPR Destination ID", PCR[DMI] + 274Ch[31:16] to the Dest ID of RP.
+ 2. Program "Reserved Page Route", PCR[DMI] + 274Ch[11] to '1'. Use byte write on GCS+1 and leave the BILD bit which is RWO.
+
+ @param[in] RpPhyNumber PCIE root port physical number.
+
+ @retval EFI_SUCCESS Successfully completed.
+
+**/
+EFI_STATUS
+EFIAPI
+PchIoPort80DecodeSet (
+ IN UINTN RpPhyNumber
+ )
+{
+ return EFI_SUCCESS;
+}
+
+/**
+ return SPI linear Base address of descriptor region section
+
+ @param[in] RegNum FLREG number of region section defined in the descriptor
+
+ @retval UINT32 Base address of the FLREG
+**/
+UINT32
+GetSpiFlashRegionBase (
+ IN UINTN RegNum
+ )
+{
+ UINTN SpiPciBase;
+ UINT32 SpiBar0;
+ UINT32 FlashRegBase;
+ UINT16 TempCmd;
+
+ SpiPciBase = MmPciBase ( DEFAULT_PCI_BUS_NUMBER_SC, PCI_DEVICE_NUMBER_SPI, PCI_FUNCTION_NUMBER_SPI);
+ SpiBar0 = MmioRead32 (SpiPciBase + R_SPI_BASE) & B_SPI_BASE_BAR;
+ TempCmd = MmioRead16 (SpiPciBase + PCI_COMMAND_OFFSET);
+ MmioOr16 (SpiPciBase + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_MEMORY_SPACE);
+
+ FlashRegBase = MmioRead32 (SpiBar0 + R_SPI_FREG0_FLASHD + RegNum * 4) & B_SPI_FREG0_BASE_MASK;
+ if (FlashRegBase == V_SPI_FLREG_DISABLED) {
+ FlashRegBase = 0;
+ DEBUG((DEBUG_ERROR, "SPI FLREG%d is disabled!!!\n", RegNum));
+ }
+ FlashRegBase <<= N_SPI_FREG0_BASE;
+
+ DEBUG ((DEBUG_INFO, "SPI FLREG%d base = 0x%x\n", RegNum, FlashRegBase));
+ MmioWrite16 (SpiPciBase + PCI_COMMAND_OFFSET, TempCmd);
+
+ return FlashRegBase;
+}
+
+
+/**
+ return SPI linear Base address of descriptor region section
+
+ @param[in] RegNum FLREG number of region section defined in the descriptor
+
+ @retval UINTN Base address of the FLREG
+
+**/
+UINT32
+GetSpiFlashRegionLimit (
+ UINTN RegNum
+ )
+{
+ UINTN SpiPciBase;
+ UINT32 SpiBar0;
+ UINT32 FlashRegLimit;
+ UINT16 TempCmd;
+
+ SpiPciBase = MmPciBase ( DEFAULT_PCI_BUS_NUMBER_SC, PCI_DEVICE_NUMBER_SPI, PCI_FUNCTION_NUMBER_SPI);
+ SpiBar0 = MmioRead32 (SpiPciBase + R_SPI_BASE) & B_SPI_BASE_BAR;
+ TempCmd = MmioRead16 (SpiPciBase + PCI_COMMAND_OFFSET);
+ MmioOr16 (SpiPciBase + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_MEMORY_SPACE);
+
+ FlashRegLimit = MmioRead32 (SpiBar0 + R_SPI_FREG0_FLASHD + RegNum * 4) & B_SPI_FREG0_LIMIT_MASK;
+ FlashRegLimit >>= N_SPI_FREG1_LIMIT;
+
+ if (FlashRegLimit == V_SPI_FLREG_DISABLED) {
+ FlashRegLimit = 0;
+ DEBUG((DEBUG_ERROR, "SPI FLREG%d is disabled!!!\n", RegNum));
+ }
+
+ DEBUG ((DEBUG_INFO, "SPI FLREG%d limit = 0x%x\n", RegNum, FlashRegLimit));
+ MmioWrite16 (SpiPciBase + PCI_COMMAND_OFFSET, TempCmd);
+
+ return FlashRegLimit;
+}
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/ScPlatformLib/ScPlatformLib.inf b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/ScPlatformLib/ScPlatformLib.inf
new file mode 100644
index 0000000000..83a2c4bcaf
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/ScPlatformLib/ScPlatformLib.inf
@@ -0,0 +1,46 @@
+## @file
+# Library for ScPlatform.
+#
+# Copyright (c) 2012 - 2016, 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 = ScPlatformLib
+ FILE_GUID = 32F89CBC-305D-4bdd-8B2C-9C65592E66AC
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = ScPlatformLib
+
+[sources.common]
+ ScPlatformLibrary.h
+ ScPlatformLibrary.c
+ ScCycleDecoding.c
+ ScSbiAccess.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ BroxtonSiPkg/BroxtonSiPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ PciLib
+ PcdLib
+ IoLib
+ DebugLib
+ SideBandLib
+ MmPciLib
+ SteppingLib
+
+[Pcd]
+ gEfiBxtTokenSpaceGuid.PcdScAcpiIoPortBaseAddress ## SOMETIMES_CONSUMES
+ gEfiBxtTokenSpaceGuid.PcdPmcGcrBaseAddress ## SOMETIMES_CONSUMES
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/ScPlatformLib/ScPlatformLibrary.c b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/ScPlatformLib/ScPlatformLibrary.c
new file mode 100644
index 0000000000..afc744ac39
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/ScPlatformLib/ScPlatformLibrary.c
@@ -0,0 +1,843 @@
+/** @file
+ SC Platform Lib implementation.
+
+ Copyright (c) 2014 - 2016, 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.
+
+**/
+
+#include "ScPlatformLibrary.h"
+#include <Library/SteppingLib.h>
+
+//
+// For BXT-P, it supports two express port controllers:
+// Controller 1:
+// Port 1-2, Device 20, function 0-1
+// Controller 2:
+// Port 3-6, Device 19, function 0-3
+// For BXT-X, it supports one express port controllers:
+// Controller 1:
+// Port 1-4, Device 19, function 0-3
+// For BXT-0/1, it supports one express port controllers:
+// Controller 1:
+// Port 1-2, Device 20, function 0-1
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCIE_CONTROLLER_INFO mPcieControllerInfo[] = {
+ { PCI_DEVICE_NUMBER_SC_PCIE_DEVICE_1, 0xB3, 0 },
+ { PCI_DEVICE_NUMBER_SC_PCIE_DEVICE_2, 0xB4, 2 }
+};
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 mPcieControllerInfoSize = sizeof (mPcieControllerInfo) / sizeof (mPcieControllerInfo[0]);
+
+
+/**
+ Get Sc Maximum Pcie Root Port Number
+
+ @retval UINT8 Sc Maximum Pcie Root Port Number
+**/
+UINT8
+EFIAPI
+GetScMaxPciePortNum (
+ VOID
+ )
+{
+ BXT_SERIES BxtSeries;
+
+ BxtSeries = GetBxtSeries ();
+ switch (BxtSeries) {
+ case BxtX:
+ return SC_BXTX_PCIE_MAX_ROOT_PORTS;
+ case BxtP:
+ return SC_BXTP_PCIE_MAX_ROOT_PORTS;
+ case Bxt1:
+ return SC_BXT_PCIE_MAX_ROOT_PORTS;
+ default:
+ return 0;
+ }
+}
+
+
+/**
+ Delay for at least the request number of microseconds.
+ This function would be called by runtime driver, please do not use any MMIO marco here.
+
+ @param[in] Microseconds Number of microseconds to delay.
+
+**/
+VOID
+EFIAPI
+ScPmTimerStall (
+ IN UINTN Microseconds
+ )
+{
+ UINTN Ticks;
+ UINTN Counts;
+ UINTN CurrentTick;
+ UINTN OriginalTick;
+ UINTN RemainingTick;
+ UINT16 AcpiBaseAddr;
+
+ if (Microseconds == 0) {
+ return;
+ }
+
+ //
+ // Read ACPI Base Address
+ //
+ AcpiBaseAddr = (UINT16)PcdGet16(PcdScAcpiIoPortBaseAddress);
+
+ OriginalTick = IoRead32 ((UINTN) (AcpiBaseAddr + R_ACPI_PM1_TMR)) & B_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_ACPI_PM1_TMR_MAX_VAL;
+
+ //
+ // Remaining clocks within one loop
+ //
+ RemainingTick = Ticks % V_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) (AcpiBaseAddr + R_ACPI_PM1_TMR)) & B_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;
+ }
+}
+
+
+/**
+ Check whether SPI is in descriptor mode
+
+ @param[in] SpiBase The SC SPI Base Address
+
+ @retval TRUE SPI is in descriptor mode
+ @retval FALSE SPI is not in descriptor mode
+
+**/
+BOOLEAN
+EFIAPI
+ScIsSpiDescriptorMode (
+ IN UINTN SpiBase
+ )
+{
+ if ((MmioRead16 (SpiBase + R_SPI_HSFS) & B_SPI_HSFS_FDV) == B_SPI_HSFS_FDV) {
+ MmioAndThenOr32 (
+ SpiBase + R_SPI_FDOC,
+ (UINT32) (~(B_SPI_FDOC_FDSS_MASK | B_SPI_FDOC_FDSI_MASK)),
+ (UINT32) (V_SPI_FDOC_FDSS_FSDM | R_SPI_FDBAR_FLVALSIG)
+ );
+ if ((MmioRead32 (SpiBase + R_SPI_FDOD)) == V_SPI_FDBAR_FLVALSIG) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+ } else {
+ return FALSE;
+ }
+}
+
+
+/**
+ This function can be called to poll for certain value within a time given.
+
+ @param[in] MmioAddress The Mmio Address.
+ @param[in] BitMask Bits to be masked.
+ @param[in] BitValue Value to be polled.
+ @param[in] DelayTime Delay time in terms of 100 micro seconds.
+
+ @retval EFI_SUCCESS Successfully polled the value.
+ @retval EFI_TIMEOUT Timeout while polling the value.
+
+**/
+EFI_STATUS
+EFIAPI
+ScMmioPoll32 (
+ IN UINTN MmioAddress,
+ IN UINT32 BitMask,
+ IN UINT32 BitValue,
+ IN UINT16 DelayTime
+ )
+{
+ UINT32 LoopTime;
+ UINT8 PollSuccess;
+
+ LoopTime = 0;
+ PollSuccess = 0;
+
+ for (LoopTime = 0; LoopTime < DelayTime; LoopTime++) {
+ if ((MmioRead32 (MmioAddress) & BitMask) == BitValue) {
+ PollSuccess = 1;
+ break;
+ } else {
+ ScPmTimerStall (100);
+ }
+ }
+
+ if (PollSuccess) {
+ return EFI_SUCCESS;
+ } else {
+ return EFI_TIMEOUT;
+ }
+}
+
+
+/**
+ Determine if the specificed device is available
+
+ @param[in] RpDev Device number
+
+ @retval FALSE Device is not available.
+ TRUE Device is available.
+
+**/
+BOOLEAN
+IsPcieControllerAvailable (
+ IN UINTN *RpDev
+)
+{
+ UINT32 FuncDisableReg;
+ UINT32 FuncDisableMask;
+
+ if (*RpDev == PCI_DEVICE_NUMBER_SC_PCIE_DEVICE_1) {
+ FuncDisableReg = MmioRead32 (PMC_BASE_ADDRESS + R_PMC_FUNC_DIS);
+ FuncDisableMask = (B_PMC_FUNC_DIS_PCIE0_P1 | B_PMC_FUNC_DIS_PCIE0_P0);
+ } else {
+ FuncDisableReg = MmioRead32 (PMC_BASE_ADDRESS + R_PMC_FUNC_DIS_1);
+ FuncDisableMask = (B_PMC_FUNC_DIS_1_PCIE1_P3 | B_PMC_FUNC_DIS_1_PCIE1_P2 | B_PMC_FUNC_DIS_1_PCIE1_P1 | B_PMC_FUNC_DIS_1_PCIE1_P0);
+ }
+
+ if ((FuncDisableReg & FuncDisableMask) == FuncDisableMask) {
+ return FALSE;
+ } else {
+ return TRUE;
+ }
+}
+
+
+/**
+ Get Sc Pcie Root Port Device and Function Number by Root Port physical Number
+
+ @param[in] RpNumber Root port physical number. (0-based)
+ @param[out] RpDev Return corresponding root port device number.
+ @param[out] RpFun Return corresponding root port function number.
+
+ @retval EFI_SUCCESS Root port device and function is retrieved
+ @retval EFI_INVALID_PARAMETER RpNumber is invalid
+
+**/
+EFI_STATUS
+EFIAPI
+GetScPcieRpDevFun (
+ IN UINTN RpNumber,
+ OUT UINTN *RpDev,
+ OUT UINTN *RpFun
+ )
+{
+ UINTN Index;
+ UINTN FuncIndex;
+ UINT32 PciePcd;
+
+ //
+ // if BXT SC , RpNumber must be < 6.
+ //
+ if (RpNumber >= GetScMaxPciePortNum ()) {
+ DEBUG ((DEBUG_ERROR, "GetScPcieRpDevFun invalid RpNumber %x\n", RpNumber));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+ if (RpNumber >= 2) {
+ Index = 1;
+ }else {
+ Index = 0;
+ }
+ FuncIndex = RpNumber - mPcieControllerInfo[Index].RpNumBase;
+ *RpDev = mPcieControllerInfo[Index].DevNum;
+
+ //
+ // Before doing the actual PCD read, ensure the device is available
+ //
+ if (IsPcieControllerAvailable (RpDev) == TRUE) {
+ PchPcrRead32 (mPcieControllerInfo[Index].Pid, 0x0000, &PciePcd);
+ *RpFun = (PciePcd >> (FuncIndex * 4)) & (BIT2 | BIT1 | BIT0);
+ } else {
+ *RpFun = FuncIndex;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Get Root Port physical Number by Sc Pcie Root Port Device and Function Number
+
+ @param[in] RpDev Root port device number.
+ @param[in] RpFun Root port function number.
+ @param[out] RpNumber Return corresponding Root port physical number.
+
+ @retval EFI_SUCCESS Physical root port is retrieved
+ @retval EFI_INVALID_PARAMETER RpDev and/or RpFun are invalid
+ @retval EFI_UNSUPPORTED Root port device and function is not assigned to any physical root port
+
+**/
+EFI_STATUS
+EFIAPI
+GetScPcieRpNumber (
+ IN UINTN RpDev,
+ IN UINTN RpFun,
+ OUT UINTN *RpNumber
+ )
+{
+ UINTN Index;
+ UINTN FuncIndex;
+ UINT32 PciePcd;
+
+ //
+ // if BXT SC, must be Dev == 19 and Fun < 4, or Dev == 20 and Fun < 2.
+ //
+ if (!((RpDev == PCI_DEVICE_NUMBER_SC_PCIE_DEVICE_1) && (RpFun < 2)) &&
+ !((RpDev == PCI_DEVICE_NUMBER_SC_PCIE_DEVICE_2) && (RpFun < 4))) {
+ DEBUG ((DEBUG_ERROR, "GetPchPcieRpNumber invalid RpDev %x RpFun %x", RpDev, RpFun));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ for (Index = 0; Index < mPcieControllerInfoSize; Index++) {
+ if (mPcieControllerInfo[Index].DevNum == RpDev) {
+ PchPcrRead32 (mPcieControllerInfo[Index].Pid, 0x0000, &PciePcd);
+ for (FuncIndex = 0; FuncIndex < 4; FuncIndex ++) {
+ if (RpFun == ((PciePcd >> (FuncIndex * 4)) & (BIT2 | BIT1 | BIT0))) {
+ break;
+ }
+ }
+ if (FuncIndex < 4) {
+ *RpNumber = mPcieControllerInfo[Index].RpNumBase + FuncIndex;
+ break;
+ }
+ }
+ }
+ if (Index >= mPcieControllerInfoSize) {
+ return EFI_UNSUPPORTED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Read PCR register. (This is internal function)
+ It returns PCR register and size in 1byte/2bytes/4bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of this Port ID
+ @param[in] Size Size for read. Must be 1 or 2 or 4.
+ @param[out] OutData Buffer of Output Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+
+**/
+STATIC
+EFI_STATUS
+PchPcrRead (
+ IN SC_SBI_PID Pid,
+ IN UINT16 Offset,
+ IN UINTN Size,
+ OUT UINT32 *OutData
+ )
+{
+ if ((Offset & (Size - 1)) != 0) {
+ DEBUG ((DEBUG_ERROR, "PchPcrRead error. Invalid Offset: %x Size: %x", Offset, Size));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+ switch (Size) {
+ case 4:
+ *(UINT32 *) OutData = MmioRead32 (SC_PCR_ADDRESS (Pid, Offset));
+ break;
+ case 2:
+ *(UINT16 *) OutData = MmioRead16 (SC_PCR_ADDRESS (Pid, Offset));
+ break;
+ case 1:
+ *(UINT8 *) OutData = MmioRead8 (SC_PCR_ADDRESS (Pid, Offset));
+ break;
+ default:
+ break;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Read PCR register.
+ It returns PCR register and size in 4bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of this Port ID
+ @param[out] OutData Buffer of Output Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+
+**/
+EFI_STATUS
+PchPcrRead32 (
+ IN SC_SBI_PID Pid,
+ IN UINT16 Offset,
+ OUT UINT32 *OutData
+ )
+{
+ return PchPcrRead (Pid, Offset, 4, (UINT32*) OutData);
+}
+
+
+/**
+ Read PCR register.
+ It returns PCR register and size in 2bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of this Port ID
+ @param[out] OutData Buffer of Output Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+
+**/
+EFI_STATUS
+PchPcrRead16 (
+ IN SC_SBI_PID Pid,
+ IN UINT16 Offset,
+ OUT UINT16 *OutData
+ )
+{
+ return PchPcrRead (Pid, Offset, 2, (UINT32*) OutData);
+}
+
+
+/**
+ Read PCR register.
+ It returns PCR register and size in 1bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of this Port ID
+ @param[out] OutData Buffer of Output Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+
+**/
+EFI_STATUS
+PchPcrRead8 (
+ IN SC_SBI_PID Pid,
+ IN UINT16 Offset,
+ OUT UINT8 *OutData
+ )
+{
+ return PchPcrRead (Pid, Offset, 1, (UINT32*) OutData);
+}
+
+
+#ifdef EFI_DEBUG
+/**
+ Check if the port ID is available for sideband mmio read/write
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of this Port ID
+
+ @retval TRUE available for sideband Mmio read/write method
+ @retval FALSE inavailable for sideband Mmio read/write method
+
+**/
+BOOLEAN
+PchPcrWriteMmioCheck (
+ IN SC_SBI_PID Pid,
+ IN UINT16 Offset
+ )
+{
+ return TRUE;
+}
+#endif
+
+
+/**
+ Write PCR register. (This is internal function)
+ It programs PCR register and size in 1byte/2bytes/4bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of Port ID.
+ @param[in] Size Size for read. Must be 1 or 2 or 4.
+ @param[in] InData Input Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+
+**/
+STATIC
+EFI_STATUS
+PchPcrWrite (
+ IN SC_SBI_PID Pid,
+ IN UINT16 Offset,
+ IN UINTN Size,
+ IN UINT32 InData
+ )
+{
+ if ((Offset & (Size - 1)) != 0) {
+ DEBUG ((DEBUG_ERROR, "PchPcrWrite error. Invalid Offset: %x Size: %x", Offset, Size));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+#ifdef EFI_DEBUG
+ if (!PchPcrWriteMmioCheck (Pid, Offset)) {
+ DEBUG ((DEBUG_ERROR, "PchPcrWrite error. Pid: %x Offset: %x should access through SBI interface", Pid, Offset));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+#endif
+
+ //
+ // Write the PCR register with provided data
+ // Then read back PCR register to prevent from back to back write.
+ //
+ switch (Size) {
+ case 4:
+ MmioWrite32 (SC_PCR_ADDRESS (Pid, Offset), (UINT32)InData);
+ break;
+ case 2:
+ MmioWrite16 (SC_PCR_ADDRESS (Pid, Offset), (UINT16)InData);
+ break;
+ case 1:
+ MmioWrite8 (SC_PCR_ADDRESS (Pid, Offset), (UINT8) InData);
+ break;
+ default:
+ break;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Write PCR register.
+ It programs PCR register and size in 4bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of Port ID.
+ @param[in] InData Input Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+
+**/
+EFI_STATUS
+PchPcrWrite32 (
+ IN SC_SBI_PID Pid,
+ IN UINT16 Offset,
+ IN UINT32 InData
+ )
+{
+ return PchPcrWrite (Pid, Offset, 4, InData);
+}
+
+
+/**
+ Write PCR register.
+ It programs PCR register and size in 2bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of Port ID.
+ @param[in] InData Input Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+
+**/
+EFI_STATUS
+PchPcrWrite16 (
+ IN SC_SBI_PID Pid,
+ IN UINT16 Offset,
+ IN UINT16 InData
+ )
+{
+ return PchPcrWrite (Pid, Offset, 2, InData);
+}
+
+
+/**
+ Write PCR register.
+ It programs PCR register and size in 1bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of Port ID.
+ @param[in] InData Input Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+
+**/
+EFI_STATUS
+PchPcrWrite8 (
+ IN SC_SBI_PID Pid,
+ IN UINT16 Offset,
+ IN UINT8 InData
+ )
+{
+ return PchPcrWrite (Pid, Offset, 1, InData);
+}
+
+
+/**
+ Reads an 4-byte Pcr register, performs a bitwise AND followed by a bitwise
+ inclusive OR, and writes the result back to the 4-byte Pcr register.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of Port ID.
+ @param[in] AndData AND Data. Must be the same size as Size parameter.
+ @param[in] OrData OR Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+
+**/
+EFI_STATUS
+PchPcrAndThenOr32 (
+ IN SC_SBI_PID Pid,
+ IN UINT16 Offset,
+ IN UINT32 AndData,
+ IN UINT32 OrData
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Data32;
+
+ Status = PchPcrRead (Pid, Offset, 4, &Data32);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Data32 &= AndData;
+ Data32 |= OrData;
+ Status = PchPcrWrite (Pid, Offset, 4, Data32);
+
+ return Status;
+}
+
+
+/**
+ Reads an 2-byte Pcr register, performs a bitwise AND followed by a bitwise
+ inclusive OR, and writes the result back to the 2-byte Pcr register.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of Port ID.
+ @param[in] AndData AND Data. Must be the same size as Size parameter.
+ @param[in] OrData OR Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+
+**/
+EFI_STATUS
+PchPcrAndThenOr16 (
+ IN SC_SBI_PID Pid,
+ IN UINT16 Offset,
+ IN UINT16 AndData,
+ IN UINT16 OrData
+ )
+{
+ EFI_STATUS Status;
+ UINT16 Data16;
+
+ Status = PchPcrRead (Pid, Offset, 2, (UINT32*) &Data16);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Data16 &= AndData;
+ Data16 |= OrData;
+ Status = PchPcrWrite (Pid, Offset, 2, Data16);
+
+ return Status;
+}
+
+
+/**
+ Reads an 1-byte Pcr register, performs a bitwise AND followed by a bitwise
+ inclusive OR, and writes the result back to the 1-byte Pcr register.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of Port ID.
+ @param[in] AndData AND Data. Must be the same size as Size parameter.
+ @param[in] OrData OR Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+
+**/
+EFI_STATUS
+PchPcrAndThenOr8 (
+ IN SC_SBI_PID Pid,
+ IN UINT16 Offset,
+ IN UINT8 AndData,
+ IN UINT8 OrData
+ )
+{
+ EFI_STATUS Status;
+ UINT8 Data8;
+
+ Status = PchPcrRead (Pid, Offset, 1, (UINT32 *) &Data8);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Data8 &= AndData;
+ Data8 |= OrData;
+ Status = PchPcrWrite (Pid, Offset, 1, Data8);
+
+ return Status;
+}
+
+
+/**
+ Hide P2SB device.
+
+ @param[in] P2sbBase Pci base address of P2SB controller.
+
+ @retval EFI_SUCCESS Always return success.
+
+**/
+EFI_STATUS
+PchHideP2sb (
+ IN UINTN P2sbBase
+ )
+{
+ MmioWrite8 (P2sbBase + R_PCH_P2SB_E0 + 1, BIT0);
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Reveal P2SB device.
+ Also return the original P2SB status which is for Hidding P2SB or not after.
+ If OrgStatus is not NULL, then TRUE means P2SB is unhidden,
+ and FALSE means P2SB is hidden originally.
+
+ @param[in] P2sbBase Pci base address of P2SB controller.
+ @param[out] OrgStatus Original P2SB hidding/unhidden status
+
+ @retval EFI_SUCCESS Always return success.
+
+**/
+EFI_STATUS
+PchRevealP2sb (
+ IN UINTN P2sbBase,
+ OUT BOOLEAN *OrgStatus
+ )
+{
+ BOOLEAN DevicePresent;
+
+ DevicePresent = (MmioRead16 (P2sbBase + PCI_VENDOR_ID_OFFSET) != 0xFFFF);
+ if (OrgStatus != NULL) {
+ *OrgStatus = DevicePresent;
+ }
+ if (!DevicePresent) {
+ MmioWrite8 (P2sbBase + R_PCH_P2SB_E0 + 1, 0);
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Get Sc Maximum Usb3 Port Number of XHCI Controller
+
+ @retval UINT8 Sc Maximum Usb3 Port Number of XHCI Controller
+
+**/
+UINT8
+EFIAPI
+GetScXhciMaxUsb3PortNum (
+ VOID
+ )
+{
+ BXT_SERIES BxtSeries;
+
+ BxtSeries = GetBxtSeries ();
+ switch (BxtSeries) {
+ case Bxt:
+ case Bxt1:
+ return SC_BXT_MAX_USB3_PORTS;
+
+ case BxtP:
+ return SC_BXTP_MAX_USB3_PORTS;
+
+ default:
+ return 0;
+ }
+}
+
+
+/**
+ Get Sc Maximum Usb2 Port Number of XHCI Controller
+
+ @retval UINT8 Sc Maximum Usb2 Port Number of XHCI Controller
+
+**/
+UINT8
+EFIAPI
+GetScXhciMaxUsb2PortNum (
+ VOID
+ )
+{
+ BXT_SERIES BxtSeries;
+
+ BxtSeries = GetBxtSeries ();
+ switch (BxtSeries) {
+ case Bxt:
+ case Bxt1:
+ return SC_BXT_MAX_USB2_PORTS;
+
+ case BxtP:
+ return SC_BXTP_MAX_USB2_PORTS;
+
+ default:
+ return 0;
+ }
+}
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/ScPlatformLib/ScPlatformLibrary.h b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/ScPlatformLib/ScPlatformLibrary.h
new file mode 100644
index 0000000000..9015afd312
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/ScPlatformLib/ScPlatformLibrary.h
@@ -0,0 +1,32 @@
+/** @file
+ Header file for SC Platform Lib implementation.
+
+ Copyright (c) 2008 - 2016, 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.
+
+**/
+
+#ifndef _SC_PLATFORM_LIBRARY_IMPLEMENTATION_H_
+#define _SC_PLATFORM_LIBRARY_IMPLEMENTATION_H_
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <IndustryStandard/Pci30.h>
+#include <ScAccess.h>
+#include <Library/ScPlatformLib.h>
+#include <Library/SideBandLib.h>
+#include <Library/MmPciLib.h>
+#include <Library/PcdLib.h>
+
+#endif
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/ScPlatformLib/ScSbiAccess.c b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/ScPlatformLib/ScSbiAccess.c
new file mode 100644
index 0000000000..9741479d08
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/ScPlatformLib/ScSbiAccess.c
@@ -0,0 +1,297 @@
+/** @file
+ Program SC SBI register.
+
+ Copyright (c) 2013 - 2016, 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.
+
+**/
+
+#include "ScPlatformLibrary.h"
+
+EFI_STATUS
+EFIAPI
+PchSbiExecution (
+ IN SC_SBI_PID Pid,
+ IN UINT64 Offset,
+ IN PCH_SBI_OPCODE Opcode,
+ IN BOOLEAN Posted,
+ IN OUT UINT32 *Data32,
+ OUT UINT8 *Response
+ )
+{
+ //
+ // Check address valid
+ //
+ if (((UINT32) Offset & 0x3) != 0) {
+ //
+ // Warning message for the address not DWORD alignment.
+ //
+ DEBUG ((DEBUG_INFO, "PchSbiExecution: Be careful that the address is not DWORD alignment.\n"));
+ }
+
+ return PchSbiExecutionEx (
+ Pid,
+ Offset,
+ Opcode,
+ Posted,
+ 0x000F,
+ 0x0000,
+ 0x0000,
+ Data32,
+ Response
+ );
+}
+
+EFI_STATUS
+EFIAPI
+PchSbiExecutionEx (
+ IN SC_SBI_PID Pid,
+ IN UINT64 Offset,
+ IN PCH_SBI_OPCODE Opcode,
+ IN BOOLEAN Posted,
+ IN UINT16 Fbe,
+ IN UINT16 Bar,
+ IN UINT16 Fid,
+ IN OUT UINT32 *Data32,
+ OUT UINT8 *Response
+ )
+{
+ EFI_STATUS Status;
+ UINTN P2sbBase;
+ BOOLEAN P2sbOrgStatus;
+ UINTN Timeout;
+ UINT16 SbiStat;
+
+ //
+ // Check opcode valid
+ //
+ switch (Opcode) {
+ case PciConfigRead:
+ case PciConfigWrite:
+ case PrivateControlRead:
+ case PrivateControlWrite:
+ case GpioLockUnlock:
+ break;
+ default:
+ return EFI_INVALID_PARAMETER;
+ break;
+ }
+
+ P2sbOrgStatus = FALSE;
+ P2sbBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_SC,
+ PCI_DEVICE_NUMBER_PCH_P2SB,
+ PCI_FUNCTION_NUMBER_PCH_P2SB
+ );
+ PchRevealP2sb (P2sbBase, &P2sbOrgStatus);
+
+ Timeout = 0xFFFFFFF;
+ while (Timeout > 0){
+ SbiStat = MmioRead16 (P2sbBase + R_PCH_P2SB_SBISTAT);
+ if ((SbiStat & B_PCH_P2SB_SBISTAT_INITRDY) == 0) {
+ break;
+ }
+ Timeout--;
+ }
+ if (Timeout == 0) {
+ Status = EFI_DEVICE_ERROR;
+ goto ExitPchSbiExecutionEx;
+ }
+ //
+ // Initial Response status
+ //
+ *Response = SBI_INVALID_RESPONSE;
+ Status = EFI_SUCCESS;
+ SbiStat = 0;
+
+ MmioWrite32 (P2sbBase + R_PCH_P2SB_SBIADDR, (UINT32) ((Pid << 24) | (UINT16)Offset));
+
+ MmioWrite32 (P2sbBase + R_PCH_P2SB_SBIEXTADDR, (UINT32) RShiftU64 (Offset, 16));
+
+ MmioAndThenOr16 (
+ (P2sbBase + R_PCH_P2SB_SBISTAT),
+ (UINT16) ~(B_PCH_P2SB_SBISTAT_OPCODE | B_PCH_P2SB_SBISTAT_POSTED),
+ (UINT16) ((Opcode << 8) | (Posted << 7))
+ );
+
+ MmioWrite16 (
+ (P2sbBase + R_PCH_P2SB_SBIRID),
+ (((Fbe & 0x000F) << 12) | ((Bar & 0x0007) << 8) | (Fid & 0x00FF))
+ );
+
+ switch (Opcode) {
+ case PciConfigWrite:
+ case PrivateControlWrite:
+ case GpioLockUnlock:
+
+ MmioWrite32 ((P2sbBase + R_PCH_P2SB_SBIDATA), *Data32);
+ break;
+ default:
+
+ MmioWrite32 ((P2sbBase + R_PCH_P2SB_SBIDATA), 0);
+ break;
+ }
+
+ MmioOr16 (P2sbBase + R_PCH_P2SB_SBISTAT, (UINT16) B_PCH_P2SB_SBISTAT_INITRDY);
+ //
+ // Poll SBISTAT[0] = 0b, Polling for Busy bit
+ //
+ Timeout = 0xFFFFFFF;
+ while (Timeout > 0){
+ SbiStat = MmioRead16 (P2sbBase + R_PCH_P2SB_SBISTAT);
+ if ((SbiStat & B_PCH_P2SB_SBISTAT_INITRDY) == 0) {
+ break;
+ }
+ Timeout--;
+ }
+ if (Timeout == 0) {
+ //
+ // If timeout, it's fatal error.
+ //
+ Status = EFI_DEVICE_ERROR;
+ } else {
+ *Response = (UINT8) ((SbiStat & B_PCH_P2SB_SBISTAT_RESPONSE) >> N_PCH_P2SB_SBISTAT_RESPONSE);
+ if (*Response == SBI_SUCCESSFUL) {
+ switch (Opcode) {
+ case PciConfigRead:
+ case PrivateControlRead:
+ *Data32 = MmioRead32 (P2sbBase + R_PCH_P2SB_SBIDATA);
+ break;
+ default:
+ break;
+ }
+ Status = EFI_SUCCESS;
+ } else {
+ Status = EFI_DEVICE_ERROR;
+ }
+ }
+
+ExitPchSbiExecutionEx:
+ if (!P2sbOrgStatus) {
+ PchHideP2sb (P2sbBase);
+ }
+
+ return Status;
+}
+
+
+/**
+ This function saves all PCH SBI registers.
+ The save and restore operations must be done while using the PchSbiExecution inside SMM.
+ It prevents the racing condition of PchSbiExecution re-entry between POST and SMI.
+ Before using this function, make sure the P2SB is not hidden.
+
+ @param[in, out] PchSbiRegister Structure for saving the registers
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_DEVICE_ERROR Device is hidden.
+
+**/
+EFI_STATUS
+EFIAPI
+PchSbiRegisterSave (
+ IN OUT PCH_SBI_REGISTER_STRUCT *PchSbiRegister
+ )
+{
+ UINTN P2sbBase;
+ UINTN Timeout;
+ UINT16 SbiStat;
+
+ P2sbBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_SC,
+ PCI_DEVICE_NUMBER_PCH_P2SB,
+ PCI_FUNCTION_NUMBER_PCH_P2SB
+ );
+ if (MmioRead16 (P2sbBase + PCI_VENDOR_ID_OFFSET) == 0xFFFF) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Make sure it's not busy.
+ // Poll SBISTAT[0] = 0b
+ //
+ Timeout = 0xFFFFFFF;
+ while ((Timeout--) > 0){
+ SbiStat = MmioRead16 (P2sbBase + R_PCH_P2SB_SBISTAT);
+ if ((SbiStat & B_PCH_P2SB_SBISTAT_INITRDY) == 0) {
+ break;
+ }
+ }
+ if (Timeout == 0) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Save original SBI registers
+ //
+ PchSbiRegister->SbiAddr = MmioRead32 (P2sbBase + R_PCH_P2SB_SBIADDR);
+ PchSbiRegister->SbiExtAddr = MmioRead32 (P2sbBase + R_PCH_P2SB_SBIEXTADDR);
+ PchSbiRegister->SbiData = MmioRead32 (P2sbBase + R_PCH_P2SB_SBIDATA);
+ PchSbiRegister->SbiStat = MmioRead16 (P2sbBase + R_PCH_P2SB_SBISTAT);
+ PchSbiRegister->SbiRid = MmioRead16 (P2sbBase + R_PCH_P2SB_SBIRID);
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This function restores all PCH SBI registers
+ The save and restore operations must be done while using the PchSbiExecution inside SMM.
+ It prevents the racing condition of PchSbiExecution re-entry between POST and SMI.
+ Before using this function, make sure the P2SB is not hidden.
+
+ @param[in] PchSbiRegister Structure for restoring the registers
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_DEVICE_ERROR Device is hidden.
+
+**/
+EFI_STATUS
+EFIAPI
+PchSbiRegisterRestore (
+ IN PCH_SBI_REGISTER_STRUCT *PchSbiRegister
+ )
+{
+ UINTN P2sbBase;
+ UINTN Timeout;
+ UINT16 SbiStat;
+
+ P2sbBase = MmPciBase (
+ DEFAULT_PCI_BUS_NUMBER_SC,
+ PCI_DEVICE_NUMBER_PCH_P2SB,
+ PCI_FUNCTION_NUMBER_PCH_P2SB
+ );
+ if (MmioRead16 (P2sbBase + PCI_VENDOR_ID_OFFSET) == 0xFFFF) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Make sure it's not busy.
+ // Poll SBISTAT[0] = 0b
+ //
+ Timeout = 0xFFFFFFF;
+ while ((Timeout--) > 0){
+ SbiStat = MmioRead16 (P2sbBase + R_PCH_P2SB_SBISTAT);
+ if ((SbiStat & B_PCH_P2SB_SBISTAT_INITRDY) == 0) {
+ break;
+ }
+ }
+ if (Timeout == 0) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Restore original SBI registers
+ //
+ MmioWrite32 (P2sbBase + R_PCH_P2SB_SBIADDR , PchSbiRegister->SbiAddr);
+ MmioWrite32 (P2sbBase + R_PCH_P2SB_SBIEXTADDR, PchSbiRegister->SbiExtAddr);
+ MmioWrite32 (P2sbBase + R_PCH_P2SB_SBIDATA , PchSbiRegister->SbiData);
+ MmioWrite16 (P2sbBase + R_PCH_P2SB_SBISTAT , PchSbiRegister->SbiStat);
+ MmioWrite16 (P2sbBase + R_PCH_P2SB_SBIRID , PchSbiRegister->SbiRid);
+
+ return EFI_SUCCESS;
+}
+