* [Patch V3 02/40] TigerlakeSiliconPkg/Include: Add Library, PPI and Protocol include headers
2021-02-05 7:40 [Patch V3 01/40] TigerlakeSiliconPkg: Add package and Include/ConfigBlock headers Heng Luo
@ 2021-02-05 7:40 ` Heng Luo
2021-02-05 7:40 ` [Patch V3 03/40] TigerlakeSiliconPkg/Include: Add Pins, Register and other " Heng Luo
` (37 subsequent siblings)
38 siblings, 0 replies; 42+ messages in thread
From: Heng Luo @ 2021-02-05 7:40 UTC (permalink / raw)
To: devel; +Cc: Sai Chaganty, Nate DeSimone
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3171
Adds the following header files:
* Include/Library
* Include/Ppi
* Include/Protocol
Cc: Sai Chaganty <rangasai.v.chaganty@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Signed-off-by: Heng Luo <heng.luo@intel.com>
---
Silicon/Intel/TigerlakeSiliconPkg/Include/Library/ConfigBlockLib.h | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Include/Library/CpuRegbarAccessLib.h | 332 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Include/Library/DxeHdaNhltLib.h | 153 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Include/Library/EspiLib.h | 140 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Include/Library/GbeLib.h | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Include/Library/GpioConfig.h | 342 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Include/Library/GpioLib.h | 720 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Include/Library/GpioNativeLib.h | 149 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Include/Library/MmPciLib.h | 27 +++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Include/Library/PchPcieRpLib.h | 123 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Include/Library/PchPcrLib.h | 256 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Include/Library/PcieHelperLib.h | 173 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Include/Library/PmcLib.h | 355 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Include/Library/ResetSystemLib.h | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Include/Library/SataLib.h | 112 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Include/Library/SerialIoAccessLib.h | 113 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Include/Library/SiConfigBlockLib.h | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Include/Library/SpiAccessLib.h | 290 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Include/Library/VtdInfoLib.h | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Include/Ppi/PeiPreMemSiDefaultPolicy.h | 34 ++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Include/Ppi/PeiSiDefaultPolicy.h | 33 +++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Include/Ppi/SiPolicy.h | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Include/Protocol/GopComponentName2.h | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Include/Protocol/GopPolicy.h | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Include/Protocol/IgdOpRegion.h | 22 ++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Include/Protocol/Spi.h | 301 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
26 files changed, 4199 insertions(+)
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Include/Library/ConfigBlockLib.h b/Silicon/Intel/TigerlakeSiliconPkg/Include/Library/ConfigBlockLib.h
new file mode 100644
index 0000000000..dbf786ec9a
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Include/Library/ConfigBlockLib.h
@@ -0,0 +1,64 @@
+/** @file
+ Header file for Config Block Lib implementation
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _CONFIG_BLOCK_LIB_H_
+#define _CONFIG_BLOCK_LIB_H_
+
+/**
+ Create config block table
+
+ @param[in] TotalSize - Max size to be allocated for the Config Block Table
+ @param[out] ConfigBlockTableAddress - On return, points to a pointer to the beginning of Config Block Table Address
+
+ @retval EFI_INVALID_PARAMETER - Invalid Parameter
+ @retval EFI_OUT_OF_RESOURCES - Out of resources
+ @retval EFI_SUCCESS - Successfully created Config Block Table at ConfigBlockTableAddress
+**/
+EFI_STATUS
+EFIAPI
+CreateConfigBlockTable (
+ IN UINT16 TotalSize,
+ OUT VOID **ConfigBlockTableAddress
+ );
+
+/**
+ Add config block into config block table structure
+
+ @param[in] ConfigBlockTableAddress - A pointer to the beginning of Config Block Table Address
+ @param[out] ConfigBlockAddress - On return, points to a pointer to the beginning of Config Block Address
+
+ @retval EFI_OUT_OF_RESOURCES - Config Block Table is full and cannot add new Config Block or
+ Config Block Offset Table is full and cannot add new Config Block.
+ @retval EFI_SUCCESS - Successfully added Config Block
+**/
+EFI_STATUS
+EFIAPI
+AddConfigBlock (
+ IN VOID *ConfigBlockTableAddress,
+ OUT VOID **ConfigBlockAddress
+ );
+
+/**
+ Retrieve a specific Config Block data by GUID
+
+ @param[in] ConfigBlockTableAddress - A pointer to the beginning of Config Block Table Address
+ @param[in] ConfigBlockGuid - A pointer to the GUID uses to search specific Config Block
+ @param[out] ConfigBlockAddress - On return, points to a pointer to the beginning of Config Block Address
+
+ @retval EFI_NOT_FOUND - Could not find the Config Block
+ @retval EFI_SUCCESS - Config Block found and return
+**/
+EFI_STATUS
+EFIAPI
+GetConfigBlock (
+ IN VOID *ConfigBlockTableAddress,
+ IN EFI_GUID *ConfigBlockGuid,
+ OUT VOID **ConfigBlockAddress
+ );
+
+#endif // _CONFIG_BLOCK_LIB_H_
+
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Include/Library/CpuRegbarAccessLib.h b/Silicon/Intel/TigerlakeSiliconPkg/Include/Library/CpuRegbarAccessLib.h
new file mode 100644
index 0000000000..564fcccb43
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Include/Library/CpuRegbarAccessLib.h
@@ -0,0 +1,332 @@
+/** @file
+ Header file for CPU REGBAR ACCESS library.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _CPU_REGBAR_ACCESS_LIB_H_
+#define _CPU_REGBAR_ACCESS_LIB_H_
+
+#define INVALID_DATA_64 0xFFFFFFFFFFFFFFFF
+#define INVALID_DATA_32 0xFFFFFFFF
+#define INVALID_DATA_16 0xFFFF
+#define INVALID_DATA_8 0xFF
+#define INVALID_PID 0xFF
+
+typedef UINT8 CPU_SB_DEVICE_PID;
+
+/**
+ Read REGBAR register.
+ It returns REGBAR register and size in 8bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] CpuSbDevicePid CPU SB Device Port ID
+ @param[in] Offset Register offset of this Port ID
+
+ @retval UINT64 REGBAR register value.
+**/
+UINT64
+CpuRegbarRead64 (
+ IN CPU_SB_DEVICE_PID CpuSbDevicePid,
+ IN UINT16 Offset
+ );
+
+
+/**
+ Read REGBAR register.
+ It returns REGBAR register and size in 4bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] CpuSbDevicePid CPU SB Device Port ID
+ @param[in] Offset Register offset of this Port ID
+
+ @retval UINT32 REGBAR register value.
+**/
+UINT32
+CpuRegbarRead32 (
+ IN CPU_SB_DEVICE_PID CpuSbDevicePid,
+ IN UINT16 Offset
+ );
+
+/**
+ Read REGBAR register.
+ It returns REGBAR register and size in 2bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] CpuSbDevicePid CPU SB Device Port ID
+ @param[in] Offset Register offset of this Port ID
+
+ @retval UINT16 REGBAR register value.
+**/
+UINT16
+CpuRegbarRead16 (
+ IN CPU_SB_DEVICE_PID CpuSbDevicePid,
+ IN UINT16 Offset
+ );
+
+/**
+ Read REGBAR register.
+ It returns REGBAR register and size in 1bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] CpuSbDevicePid CPU SB Device Port ID
+ @param[in] Offset Register offset of this Port ID
+
+ @retval UINT8 REGBAR regsiter value
+**/
+UINT8
+CpuRegbarRead8 (
+ IN CPU_SB_DEVICE_PID CpuSbDevicePid,
+ IN UINT16 Offset
+ );
+
+/**
+ Write REGBAR register.
+ It programs REGBAR register and size in 8bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] CpuSbDevicePid CPU SB Device Port ID
+ @param[in] Offset Register offset of Port ID.
+ @param[in] Data Input Data. Must be the same size as Size parameter.
+
+ @retval UINT64 Value written to register
+**/
+UINT64
+CpuRegbarWrite64 (
+ IN CPU_SB_DEVICE_PID CpuSbDevicePid,
+ IN UINT16 Offset,
+ IN UINT64 Data
+ );
+
+
+/**
+ Write REGBAR register.
+ It programs REGBAR register and size in 4bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] CpuSbDevicePid CPU SB Device Port ID
+ @param[in] Offset Register offset of Port ID.
+ @param[in] Data Input Data. Must be the same size as Size parameter.
+
+ @retval UINT32 Value written to register
+**/
+UINT32
+CpuRegbarWrite32 (
+ IN CPU_SB_DEVICE_PID CpuSbDevicePid,
+ IN UINT16 Offset,
+ IN UINT32 Data
+ );
+
+/**
+ Write REGBAR register.
+ It programs REGBAR register and size in 2bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] CpuSbDevicePid CPU SB Device Port ID
+ @param[in] Offset Register offset of Port ID.
+ @param[in] Data Input Data. Must be the same size as Size parameter.
+
+ @retval UINT16 Value written to register
+**/
+UINT16
+CpuRegbarWrite16 (
+ IN CPU_SB_DEVICE_PID CpuSbDevicePid,
+ IN UINT16 Offset,
+ IN UINT16 Data
+ );
+
+/**
+ Write REGBAR register.
+ It programs REGBAR register and size in 1bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] CpuSbDevicePid CPU SB Device Port ID
+ @param[in] Offset Register offset of Port ID.
+ @param[in] Data Input Data. Must be the same size as Size parameter.
+
+ @retval UINT8 Value written to register
+**/
+UINT8
+CpuRegbarWrite8 (
+ IN CPU_SB_DEVICE_PID CpuSbDevicePid,
+ IN UINT16 Offset,
+ IN UINT8 Data
+ );
+
+/**
+ Write REGBAR register.
+ It programs REGBAR register and size in 4bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] CpuSbDevicePid CPU SB Device Port ID
+ @param[in] Offset Register offset of Port ID.
+ @param[in] OrData OR Data. Must be the same size as Size parameter.
+
+ @retval UINT32 Value written to register
+
+**/
+UINT32
+CpuRegbarOr32 (
+ IN CPU_SB_DEVICE_PID CpuSbDevicePid,
+ IN UINT16 Offset,
+ IN UINT32 OrData
+ );
+
+/**
+ Write REGBAR register.
+ It programs REGBAR register and size in 2bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] CpuSbDevicePid CPU SB Device Port ID
+ @param[in] Offset Register offset of Port ID.
+ @param[in] OrData OR Data. Must be the same size as Size parameter.
+
+ @retval UINT16 Value written to register
+
+**/
+UINT16
+CpuRegbarOr16 (
+ IN CPU_SB_DEVICE_PID CpuSbDevicePid,
+ IN UINT16 Offset,
+ IN UINT16 OrData
+ );
+
+/**
+ Write REGBAR register.
+ It programs REGBAR register and size in 1bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] CpuSbDevicePid CPU SB Device Port ID
+ @param[in] Offset Register offset of Port ID.
+ @param[in] OrData OR Data. Must be the same size as Size parameter.
+
+ @retval UINT8 Value written to register
+
+**/
+UINT8
+CpuRegbarOr8 (
+ IN CPU_SB_DEVICE_PID CpuSbDevicePid,
+ IN UINT16 Offset,
+ IN UINT8 OrData
+ );
+
+/**
+ Performs a bitwise AND of a 32-bit data.
+ It programs REGBAR register and size in 4bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] CpuSbDevice CPU SB Device
+ @param[in] Offset Register offset of Port ID.
+ @param[in] AndData And Data. Must be the same size as Size parameter.
+
+ @retval UINT32 Value written to register
+
+**/
+UINT32
+CpuRegbarAnd32 (
+ IN CPU_SB_DEVICE_PID CpuSbDevicePid,
+ IN UINT16 Offset,
+ IN UINT32 AndData
+ );
+
+/**
+ Performs a bitwise AND of a 16-bit data.
+ It programs REGBAR register and size in 2bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] CpuSbDevice CPU SB Device
+ @param[in] Offset Register offset of Port ID.
+ @param[in] AndData And Data. Must be the same size as Size parameter.
+
+ @retval UINT16 Value written to register
+
+**/
+UINT16
+CpuRegbarAnd16 (
+ IN CPU_SB_DEVICE_PID CpuSbDevicePid,
+ IN UINT16 Offset,
+ IN UINT16 AndData
+ );
+
+/**
+ Performs a bitwise AND of a 8-bit data.
+ It programs REGBAR register and size in 1byte.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] CpuSbDevice CPU SB Device
+ @param[in] Offset Register offset of Port ID.
+ @param[in] AndData And Data. Must be the same size as Size parameter.
+
+ @retval UINT8 Value written to register
+
+**/
+UINT8
+CpuRegbarAnd8 (
+ IN CPU_SB_DEVICE_PID CpuSbDevicePid,
+ IN UINT16 Offset,
+ IN UINT8 AndData
+ );
+/**
+ Write REGBAR register.
+ It programs REGBAR register and size in 4bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] CpuSbDevicePid CPU SB Device 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 UINT32 Value written to register
+
+**/
+UINT32
+CpuRegbarAndThenOr32 (
+ IN CPU_SB_DEVICE_PID CpuSbDevicePid,
+ IN UINT16 Offset,
+ IN UINT32 AndData,
+ IN UINT32 OrData
+ );
+
+/**
+ Write REGBAR register.
+ It programs REGBAR register and size in 2bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] CpuSbDevicePid CPU SB Device 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 UINT16 Value written to register
+
+**/
+UINT16
+CpuRegbarAndThenOr16 (
+ IN CPU_SB_DEVICE_PID CpuSbDevicePid,
+ IN UINT16 Offset,
+ IN UINT16 AndData,
+ IN UINT16 OrData
+ );
+
+/**
+ Write REGBAR register.
+ It programs REGBAR register and size in 1bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] CpuSbDevicePid CPU SB Device 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 UINT8 Value written to register
+
+**/
+UINT8
+CpuRegbarAndThenOr8 (
+ IN CPU_SB_DEVICE_PID CpuSbDevicePid,
+ IN UINT16 Offset,
+ IN UINT8 AndData,
+ IN UINT8 OrData
+ );
+
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Include/Library/DxeHdaNhltLib.h b/Silicon/Intel/TigerlakeSiliconPkg/Include/Library/DxeHdaNhltLib.h
new file mode 100644
index 0000000000..c48ea3667f
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Include/Library/DxeHdaNhltLib.h
@@ -0,0 +1,153 @@
+/** @file
+ Prototype of the DxePchHdaNhltLib library.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _DXE_HDA_NHLT_LIB_H_
+#define _DXE_HDA_NHLT_LIB_H_
+
+#include <DxeHdaNhlt.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
+ );
+
+/**
+ 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
+ );
+
+/**
+ 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
+ );
+
+/**
+ 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
+ );
+
+/**
+ Returns pointer to all Device Information DEVICES_INFO structure.
+
+ @param[in] *Endpoint Endpoint for which DevicesInfo address is retrieved
+
+ @retval Pointer to DEVICES_INFO structure
+**/
+DEVICES_INFO *
+GetNhltEndpointDevicesInfo (
+ IN CONST ENDPOINT_DESCRIPTOR *Endpoint
+ );
+
+/**
+ Returns pointer to Device Information DEVICES_INFO structure.
+
+ @param[in] *Endpoint Endpoint for which Device Info address is retrieved
+ @param[in] DeviceInfoIndex Index of Device Info to be retrieved
+
+ @retval Pointer to DEVICE_INFO structure with given index
+**/
+DEVICE_INFO *
+GetNhltEndpointDeviceInfo (
+ IN CONST ENDPOINT_DESCRIPTOR *Endpoint,
+ IN CONST UINT8 DeviceInfoIndex
+ );
+
+
+/**
+ 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
+ );
+
+/**
+ Prints Format configuration.
+
+ @param[in] *Format Format to be printed
+
+ @retval None
+**/
+VOID
+NhltFormatDump (
+ IN CONST FORMAT_CONFIG *Format
+ );
+
+
+/**
+ Prints Endpoint configuration.
+
+ @param[in] *Endpoint Endpoint to be printed
+
+ @retval None
+**/
+VOID
+NhltEndpointDump (
+ IN CONST ENDPOINT_DESCRIPTOR *Endpoint
+ );
+
+/**
+ Prints OED (Offload Engine Driver) configuration.
+
+ @param[in] *OedConfig OED to be printed
+
+ @retval None
+**/
+VOID
+NhltOedConfigDump (
+ IN CONST SPECIFIC_CONFIG *OedConfig
+ );
+
+/**
+ 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
+ );
+
+#endif // _DXE_HDA_NHLT_LIB_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Include/Library/EspiLib.h b/Silicon/Intel/TigerlakeSiliconPkg/Include/Library/EspiLib.h
new file mode 100644
index 0000000000..6d8466ab7a
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Include/Library/EspiLib.h
@@ -0,0 +1,140 @@
+/** @file
+ Header file for PchEspiLib.
+ All function in this library is available for PEI, DXE, and SMM,
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _ESPI_LIB_H_
+#define _ESPI_LIB_H_
+
+/**
+ Checks if there's second slave connected under CS#1
+
+ @retval TRUE There's second slave
+ @retval FALSE There's no second slave
+**/
+BOOLEAN
+IsEspiSecondSlaveSupported (
+ VOID
+ );
+
+/**
+ Checks in slave General Capabilities register if it supports channel with requested number
+
+ @param[in] SlaveId Id of slave to check
+ @param[in] ChannelNumber Number of channel of which to check
+
+ @retval TRUE Channel with requested number is supported by slave device
+ @retval FALSE Channel with requested number is not supported by slave device
+**/
+BOOLEAN
+IsEspiSlaveChannelSupported (
+ UINT8 SlaveId,
+ UINT8 ChannelNumber
+ );
+
+/**
+ Is eSPI enabled in strap.
+
+ @retval TRUE Espi is enabled in strap
+ @retval FALSE Espi is disabled in strap
+**/
+BOOLEAN
+IsEspiEnabled (
+ VOID
+ );
+
+/**
+ Get configuration from eSPI slave
+
+ @param[in] SlaveId eSPI slave ID
+ @param[in] SlaveAddress Slave Configuration Register Address
+ @param[out] OutData Configuration data read
+
+ @retval EFI_SUCCESS Operation succeed
+ @retval EFI_INVALID_PARAMETER Slave ID is not supported
+ @retval EFI_INVALID_PARAMETER Slave ID is not supported or SlaveId 1 is used in PchLp
+ @retval EFI_INVALID_PARAMETER Slave configuration register address exceed maximum allowed
+ @retval EFI_INVALID_PARAMETER Slave configuration register address is not DWord aligned
+ @retval EFI_DEVICE_ERROR Error in SCRS during polling stage of operation
+**/
+EFI_STATUS
+PchEspiSlaveGetConfig (
+ IN UINT32 SlaveId,
+ IN UINT32 SlaveAddress,
+ OUT UINT32 *OutData
+ );
+
+/**
+ Set eSPI slave configuration
+
+ Note: A Set_Configuration must always be followed by a Get_Configuration in order to ensure
+ that the internal state of the eSPI-MC is consistent with the Slave's register settings.
+
+ @param[in] SlaveId eSPI slave ID
+ @param[in] SlaveAddress Slave Configuration Register Address
+ @param[in] InData Configuration data to write
+
+ @retval EFI_SUCCESS Operation succeed
+ @retval EFI_INVALID_PARAMETER Slave ID is not supported or SlaveId 1 is used in PchLp
+ @retval EFI_INVALID_PARAMETER Slave configuration register address exceed maximum allowed
+ @retval EFI_INVALID_PARAMETER Slave configuration register address is not DWord aligned
+ @retval EFI_ACCESS_DENIED eSPI Slave write to address range 0 to 0x7FF has been locked
+ @retval EFI_DEVICE_ERROR Error in SCRS during polling stage of operation
+**/
+EFI_STATUS
+PchEspiSlaveSetConfig (
+ IN UINT32 SlaveId,
+ IN UINT32 SlaveAddress,
+ IN UINT32 InData
+ );
+
+/**
+ Get status from eSPI slave
+
+ @param[in] SlaveId eSPI slave ID
+ @param[out] OutData Configuration data read
+
+ @retval EFI_SUCCESS Operation succeed
+ @retval EFI_INVALID_PARAMETER Slave ID is not supported or SlaveId 1 is used in PchLp
+ @retval EFI_DEVICE_ERROR Error in SCRS during polling stage of operation
+**/
+EFI_STATUS
+PchEspiSlaveGetStatus (
+ IN UINT32 SlaveId,
+ OUT UINT16 *OutData
+ );
+
+/**
+ eSPI slave in-band reset
+
+ @param[in] SlaveId eSPI slave ID
+
+ @retval EFI_SUCCESS Operation succeed
+ @retval EFI_INVALID_PARAMETER Slave ID is not supported or SlaveId 1 is used in PchLp
+ @retval EFI_DEVICE_ERROR Error in SCRS during polling stage of operation
+**/
+EFI_STATUS
+PchEspiSlaveInBandReset (
+ IN UINT32 SlaveId
+ );
+
+/**
+ eSPI Slave channel reset helper function
+
+ @param[in] SlaveId eSPI slave ID
+ @param[in] ChannelNumber Number of channel to reset
+
+ @retval EFI_SUCCESS Operation succeeded
+ @retval EFI_UNSUPPORTED Slave doesn't support that channel or invalid number specified
+ @retval EFI_TIMEOUT Operation has timeouted
+**/
+EFI_STATUS
+PchEspiSlaveChannelReset (
+ IN UINT8 SlaveId,
+ IN UINT8 ChannelNumber
+ );
+
+#endif // _ESPI_LIB_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Include/Library/GbeLib.h b/Silicon/Intel/TigerlakeSiliconPkg/Include/Library/GbeLib.h
new file mode 100644
index 0000000000..9d72b9ac7c
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Include/Library/GbeLib.h
@@ -0,0 +1,63 @@
+/** @file
+ Header file for GbeLib.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _GBE_LIB_H_
+#define _GBE_LIB_H_
+
+/**
+ Check whether GbE region is valid
+ Check SPI region directly since GbE might be disabled in SW.
+
+ @retval TRUE Gbe Region is valid
+ @retval FALSE Gbe Region is invalid
+**/
+BOOLEAN
+IsGbeRegionValid (
+ VOID
+ );
+
+/**
+ Check whether GBE controller is enabled in the platform.
+
+ @retval TRUE GbE is enabled
+ @retval FALSE GbE is disabled
+**/
+BOOLEAN
+IsGbePresent (
+ VOID
+ );
+
+/**
+ Checks if Gbe is Enabled or Disabled
+
+ @retval BOOLEAN TRUE if device is enabled, FALSE otherwise.
+**/
+BOOLEAN
+IsGbeEnabled (
+ VOID
+ );
+
+/**
+ Returns Gigabit Ethernet PCI Device Number
+
+ @retval GbE device number
+**/
+UINT8
+GbeDevNumber (
+ VOID
+ );
+
+/**
+ Returns Gigabit Ethernet PCI Function Number
+
+ @retval GbE function number
+**/
+UINT8
+GbeFuncNumber (
+ VOID
+ );
+
+#endif // _GBE_LIB_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Include/Library/GpioConfig.h b/Silicon/Intel/TigerlakeSiliconPkg/Include/Library/GpioConfig.h
new file mode 100644
index 0000000000..88a21efb32
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Include/Library/GpioConfig.h
@@ -0,0 +1,342 @@
+/** @file
+ Header file for GpioConfig structure used by GPIO library.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _GPIO_CONFIG_H_
+#define _GPIO_CONFIG_H_
+
+#pragma pack(push, 1)
+
+///
+/// For any GpioPad usage in code use GPIO_PAD type
+///
+typedef UINT32 GPIO_PAD;
+
+///
+/// GpioPad with additional native function information.
+/// This type is used to represent signal muxing alternatives. Platform will provide such value to
+/// identify muxing selection for given signal on a specific SOC.
+/// Please refer to the board layout
+///
+typedef UINT32 GPIO_NATIVE_PAD;
+
+
+///
+/// For any GpioGroup usage in code use GPIO_GROUP type
+///
+typedef UINT32 GPIO_GROUP;
+
+/**
+ GPIO configuration structure used for pin programming.
+ Structure contains fields that can be used to configure pad.
+**/
+typedef struct {
+ /**
+ Pad Mode
+ Pad can be set as GPIO or one of its native functions.
+ When in native mode setting Direction (except Inversion), OutputState,
+ InterruptConfig, Host Software Pad Ownership and OutputStateLock are unnecessary.
+ Refer to definition of GPIO_PAD_MODE.
+ Refer to EDS for each native mode according to the pad.
+ **/
+ UINT32 PadMode : 5;
+ /**
+ Host Software Pad Ownership
+ Set pad to ACPI mode or GPIO Driver Mode.
+ Refer to definition of GPIO_HOSTSW_OWN.
+ **/
+ UINT32 HostSoftPadOwn : 2;
+ /**
+ GPIO Direction
+ Can choose between In, In with inversion, Out, both In and Out, both In with inversion and out or disabling both.
+ Refer to definition of GPIO_DIRECTION for supported settings.
+ **/
+ UINT32 Direction : 6;
+ /**
+ Output State
+ Set Pad output value.
+ Refer to definition of GPIO_OUTPUT_STATE for supported settings.
+ This setting takes place when output is enabled.
+ **/
+ UINT32 OutputState : 2;
+ /**
+ GPIO Interrupt Configuration
+ Set Pad to cause one of interrupts (IOxAPIC/SCI/SMI/NMI).
+ This setting is applicable only if GPIO is in GpioMode with input enabled.
+ Refer to definition of GPIO_INT_CONFIG for supported settings.
+ **/
+ UINT32 InterruptConfig : 9;
+ /**
+ GPIO Power Configuration.
+ This setting controls Pad Reset Configuration.
+ Refer to definition of GPIO_RESET_CONFIG for supported settings.
+ **/
+ UINT32 PowerConfig : 8;
+ /**
+ GPIO Electrical Configuration
+ This setting controls pads termination.
+ Refer to definition of GPIO_ELECTRICAL_CONFIG for supported settings.
+ **/
+ UINT32 ElectricalConfig : 9;
+ /**
+ GPIO Lock Configuration
+ This setting controls pads lock.
+ Refer to definition of GPIO_LOCK_CONFIG for supported settings.
+ **/
+ UINT32 LockConfig : 4;
+ /**
+ Additional GPIO configuration
+ Refer to definition of GPIO_OTHER_CONFIG for supported settings.
+ **/
+ UINT32 OtherSettings : 9;
+
+ UINT32 RsvdBits : 10; ///< Reserved bits for future extension
+} GPIO_CONFIG;
+
+
+typedef enum {
+ GpioHardwareDefault = 0x0 ///< Leave setting unmodified
+} GPIO_HARDWARE_DEFAULT;
+
+/**
+ GPIO Pad Mode
+ Refer to GPIO documentation on native functions available for certain pad.
+ If GPIO is set to one of NativeX modes then following settings are not applicable
+ and can be skipped:
+ - Interrupt related settings
+ - Host Software Ownership
+ - Output/Input enabling/disabling
+ - Output lock
+**/
+typedef enum {
+ GpioPadModeHwDefault = 0x0,
+ GpioPadModeGpio = 0x1,
+ GpioPadModeNative1 = 0x3,
+ GpioPadModeNative2 = 0x5,
+ GpioPadModeNative3 = 0x7,
+ GpioPadModeNative4 = 0x9,
+ GpioPadModeNative5 = 0xB,
+ GpioPadModeNative6 = 0xD,
+ GpioPadModeNative7 = 0xF
+} GPIO_PAD_MODE;
+
+/**
+ Host Software Pad Ownership modes
+ This setting affects GPIO interrupt status registers. Depending on chosen ownership
+ some GPIO Interrupt status register get updated and other masked.
+ Please refer to EDS for HOSTSW_OWN register description.
+**/
+typedef enum {
+ GpioHostOwnDefault = 0x0, ///< Leave ownership value unmodified
+ /**
+ Set HOST ownership to ACPI.
+ Use this setting if pad is not going to be used by GPIO OS driver.
+ If GPIO is configured to generate SCI/SMI/NMI then this setting must be
+ used for interrupts to work
+ **/
+ GpioHostOwnAcpi = 0x1,
+ /**
+ Set HOST ownership to GPIO Driver mode.
+ Use this setting only if GPIO pad should be controlled by GPIO OS Driver.
+ GPIO OS Driver will be able to control the pad if appropriate entry in
+ ACPI exists (refer to ACPI specification for GpioIo and GpioInt descriptors)
+ **/
+ GpioHostOwnGpio = 0x3
+} GPIO_HOSTSW_OWN;
+
+///
+/// GPIO Direction
+///
+typedef enum {
+ GpioDirDefault = 0x0, ///< Leave pad direction setting unmodified
+ GpioDirInOut = (0x1 | (0x1 << 3)), ///< Set pad for both output and input
+ GpioDirInInvOut = (0x1 | (0x3 << 3)), ///< Set pad for both output and input with inversion
+ GpioDirIn = (0x3 | (0x1 << 3)), ///< Set pad for input only
+ GpioDirInInv = (0x3 | (0x3 << 3)), ///< Set pad for input with inversion
+ GpioDirOut = 0x5, ///< Set pad for output only
+ GpioDirNone = 0x7 ///< Disable both output and input
+} GPIO_DIRECTION;
+
+/**
+ GPIO Output State
+ This field is relevant only if output is enabled
+**/
+typedef enum {
+ GpioOutDefault = 0x0, ///< Leave output value unmodified
+ GpioOutLow = 0x1, ///< Set output to low
+ GpioOutHigh = 0x3 ///< Set output to high
+} GPIO_OUTPUT_STATE;
+
+/**
+ GPIO interrupt configuration
+ This setting is applicable only if pad is in GPIO mode and has input enabled.
+ GPIO_INT_CONFIG allows to choose which interrupt is generated (IOxAPIC/SCI/SMI/NMI)
+ and how it is triggered (edge or level). Refer to PADCFG_DW0 register description in
+ EDS for details on this settings.
+ Field from GpioIntNmi to GpioIntApic can be OR'ed with GpioIntLevel to GpioIntBothEdge
+ to describe an interrupt e.g. GpioIntApic | GpioIntLevel
+ If GPIO is set to cause an SCI then also GPI_GPE_EN is enabled for this pad.
+ If GPIO is set to cause an NMI then also GPI_NMI_EN is enabled for this pad.
+ Not all GPIO are capable of generating an SMI or NMI interrupt.
+ When routing GPIO to cause an IOxAPIC interrupt care must be taken, as this
+ interrupt cannot be shared and its IRQn number is not configurable.
+ Refer to EDS for GPIO pads IRQ numbers (PADCFG_DW1.IntSel)
+ If GPIO is under GPIO OS driver control and appropriate ACPI GpioInt descriptor
+ exist then use only trigger type setting (from GpioIntLevel to GpioIntBothEdge).
+ This type of GPIO Driver interrupt doesn't have any additional routing setting
+ required to be set by BIOS. Interrupt is handled by GPIO OS Driver.
+**/
+
+typedef enum {
+ GpioIntDefault = 0x0, ///< Leave value of interrupt routing unmodified
+ GpioIntDis = 0x1, ///< Disable IOxAPIC/SCI/SMI/NMI interrupt generation
+ GpioIntNmi = 0x3, ///< Enable NMI interrupt only
+ GpioIntSmi = 0x5, ///< Enable SMI interrupt only
+ GpioIntSci = 0x9, ///< Enable SCI interrupt only
+ GpioIntApic = 0x11, ///< Enable IOxAPIC interrupt only
+ GpioIntLevel = (0x1 << 5), ///< Set interrupt as level triggered
+ GpioIntEdge = (0x3 << 5), ///< Set interrupt as edge triggered (type of edge depends on input inversion)
+ GpioIntLvlEdgDis = (0x5 << 5), ///< Disable interrupt trigger
+ GpioIntBothEdge = (0x7 << 5) ///< Set interrupt as both edge triggered
+} GPIO_INT_CONFIG;
+
+#define B_GPIO_INT_CONFIG_INT_SOURCE_MASK 0x1F ///< Mask for GPIO_INT_CONFIG for interrupt source
+#define B_GPIO_INT_CONFIG_INT_TYPE_MASK 0xE0 ///< Mask for GPIO_INT_CONFIG for interrupt type
+
+/**
+ GPIO Power Configuration
+ GPIO_RESET_CONFIG allows to set GPIO Reset type (PADCFG_DW0.PadRstCfg) which will
+ be used to reset certain GPIO settings.
+ Refer to EDS for settings that are controllable by PadRstCfg.
+**/
+typedef enum {
+ GpioResetDefault = 0x00, ///< Leave value of pad reset unmodified
+ /**
+ Resume Reset (RSMRST)
+ GPP: PadRstCfg = 00b = "Powergood"
+ GPD: PadRstCfg = 11b = "Resume Reset"
+ Pad setting will reset on:
+ - DeepSx transition
+ - G3
+ Pad settings will not reset on:
+ - S3/S4/S5 transition
+ - Warm/Cold/Global reset
+ **/
+ GpioResumeReset = 0x01,
+ /**
+ Host Deep Reset
+ PadRstCfg = 01b = "Deep GPIO Reset"
+ Pad settings will reset on:
+ - Warm/Cold/Global reset
+ - DeepSx transition
+ - G3
+ Pad settings will not reset on:
+ - S3/S4/S5 transition
+ **/
+ GpioHostDeepReset = 0x03,
+ /**
+ Platform Reset (PLTRST)
+ PadRstCfg = 10b = "GPIO Reset"
+ Pad settings will reset on:
+ - S3/S4/S5 transition
+ - Warm/Cold/Global reset
+ - DeepSx transition
+ - G3
+ **/
+ GpioPlatformReset = 0x05,
+ /**
+ Deep Sleep Well Reset (DSW_PWROK)
+ GPP: not applicable
+ GPD: PadRstCfg = 00b = "Powergood"
+ Pad settings will reset on:
+ - G3
+ Pad settings will not reset on:
+ - S3/S4/S5 transition
+ - Warm/Cold/Global reset
+ - DeepSx transition
+ **/
+ GpioDswReset = 0x07
+} GPIO_RESET_CONFIG;
+
+/**
+ GPIO Electrical Configuration
+ Configuration options for GPIO termination setting
+**/
+typedef enum {
+ GpioTermDefault = 0x0, ///< Leave termination setting unmodified
+ GpioTermNone = 0x1, ///< none
+ GpioTermWpd5K = 0x5, ///< 5kOhm weak pull-down
+ GpioTermWpd20K = 0x9, ///< 20kOhm weak pull-down
+ GpioTermWpu1K = 0x13, ///< 1kOhm weak pull-up
+ GpioTermWpu2K = 0x17, ///< 2kOhm weak pull-up
+ GpioTermWpu5K = 0x15, ///< 5kOhm weak pull-up
+ GpioTermWpu20K = 0x19, ///< 20kOhm weak pull-up
+ GpioTermWpu1K2K = 0x1B, ///< 1kOhm & 2kOhm weak pull-up
+ /**
+ Native function controls pads termination
+ This setting is applicable only to some native modes.
+ Please check EDS to determine which native functionality
+ can control pads termination
+ **/
+ GpioTermNative = 0x1F
+} GPIO_ELECTRICAL_CONFIG;
+
+#define B_GPIO_ELECTRICAL_CONFIG_TERMINATION_MASK 0x1F ///< Mask for GPIO_ELECTRICAL_CONFIG for termination value
+
+/**
+ GPIO LockConfiguration
+ Set GPIO configuration lock and output state lock.
+ GpioPadConfigUnlock/Lock and GpioOutputStateUnlock can be OR'ed.
+ By default GPIO pads will be locked unless GPIO lib is explicitly
+ informed that certain pad is to be left unlocked.
+ Lock settings reset is in Powergood domain. Care must be taken when using this setting
+ as fields it locks may be reset by a different signal and can be controlled
+ by what is in GPIO_RESET_CONFIG (PADCFG_DW0.PadRstCfg). GPIO library provides
+ functions which allow to unlock a GPIO pad. If possible each GPIO lib function will try to unlock
+ an already locked pad upon request for reconfiguration
+**/
+typedef enum {
+ /**
+ Perform default action
+ - if pad is an GPO, lock configuration but leave output unlocked
+ - if pad is an GPI, lock everything
+ - if pad is in native, lock everything
+**/
+ GpioLockDefault = 0x0,
+ GpioPadConfigUnlock = 0x3, ///< Leave Pad configuration unlocked
+ GpioPadConfigLock = 0x1, ///< Lock Pad configuration
+ GpioOutputStateUnlock = 0xC, ///< Leave Pad output control unlocked
+ GpioPadUnlock = 0xF, ///< Leave both Pad configuration and output control unlocked
+ GpioPadLock = 0x5, ///< Lock both Pad configuration and output control
+ /**
+ Below statuses are used for
+ return from GpioGetPadConfig function
+ **/
+ GpioLockTxLockCfgUnLock = 0x7, ///< Tx State locked, Pad Configuration unlocked
+ GpioLockTxUnLockCfgLock = 0xD ///< Tx State unlocked, Pad Configuration locked
+} GPIO_LOCK_CONFIG;
+
+#define B_GPIO_LOCK_CONFIG_PAD_CONF_LOCK_MASK 0x3 ///< Mask for GPIO_LOCK_CONFIG for Pad Configuration Lock
+#define B_GPIO_LOCK_CONFIG_OUTPUT_LOCK_MASK 0xC ///< Mask for GPIO_LOCK_CONFIG for Pad Output Lock
+
+/**
+ Other GPIO Configuration
+ GPIO_OTHER_CONFIG is used for less often settings and for future extensions
+ Supported settings:
+ - RX raw override to '1' - allows to override input value to '1'
+ This setting is applicable only if in input mode (both in GPIO and native usage).
+ The override takes place at the internal pad state directly from buffer and before the RXINV.
+**/
+typedef enum {
+ GpioRxRaw1Default = 0x0, ///< Use default input override value
+ GpioRxRaw1Dis = 0x1, ///< Don't override input
+ GpioRxRaw1En = 0x3 ///< Override input to '1'
+} GPIO_OTHER_CONFIG;
+
+#define B_GPIO_OTHER_CONFIG_RXRAW_MASK 0x3 ///< Mask for GPIO_OTHER_CONFIG for RxRaw1 setting
+
+#pragma pack(pop)
+
+#endif //_GPIO_CONFIG_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Include/Library/GpioLib.h b/Silicon/Intel/TigerlakeSiliconPkg/Include/Library/GpioLib.h
new file mode 100644
index 0000000000..5b3cf502a0
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Include/Library/GpioLib.h
@@ -0,0 +1,720 @@
+/** @file
+ Header file for GpioLib.
+ All function in this library is available for PEI, DXE, and SMM
+
+ @note: When GPIO pads are owned by ME Firmware, BIOS/host should not
+ attempt to access these GPIO Pads registers, registers value
+ returned in this case will be 0xFF.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _GPIO_LIB_H_
+#define _GPIO_LIB_H_
+
+#include <Library/GpioConfig.h>
+
+#define GPIO_NAME_LENGTH_MAX 32
+
+typedef struct {
+ GPIO_PAD GpioPad;
+ GPIO_CONFIG GpioConfig;
+} GPIO_INIT_CONFIG;
+
+/**
+ This procedure will initialize multiple GPIO pins. Use GPIO_INIT_CONFIG structure.
+ Structure contains fields that can be used to configure each pad.
+ Pad not configured using GPIO_INIT_CONFIG will be left with hardware default values.
+ Separate fields could be set to hardware default if it does not matter, except
+ GpioPad and PadMode.
+ Function will work in most efficient way if pads which belong to the same group are
+ placed in adjacent records of the table.
+ Although function can enable pads for Native mode, such programming is done
+ by reference code when enabling related silicon feature.
+
+ @param[in] NumberofItem Number of GPIO pads to be updated
+ @param[in] GpioInitTableAddress GPIO initialization table
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioConfigurePads (
+ IN UINT32 NumberOfItems,
+ IN GPIO_INIT_CONFIG *GpioInitTableAddress
+ );
+
+//
+// Functions for setting/getting multiple GpioPad settings
+//
+
+/**
+ This procedure will read multiple GPIO settings
+
+ @param[in] GpioPad GPIO Pad
+ @param[out] GpioData GPIO data structure
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetPadConfig (
+ IN GPIO_PAD GpioPad,
+ OUT GPIO_CONFIG *GpioData
+ );
+
+/**
+ This procedure will configure multiple GPIO settings
+
+ @param[in] GpioPad GPIO Pad
+ @param[in] GpioData GPIO data structure
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioSetPadConfig (
+ IN GPIO_PAD GpioPad,
+ IN GPIO_CONFIG *GpioData
+ );
+
+//
+// Functions for setting/getting single GpioPad properties
+//
+
+/**
+ This procedure will set GPIO output level
+
+ @param[in] GpioPad GPIO pad
+ @param[in] Value Output value
+ 0: OutputLow, 1: OutputHigh
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioSetOutputValue (
+ IN GPIO_PAD GpioPad,
+ IN UINT32 Value
+ );
+
+/**
+ This procedure will get GPIO output level
+
+ @param[in] GpioPad GPIO pad
+ @param[out] OutputVal GPIO Output value
+ 0: OutputLow, 1: OutputHigh
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetOutputValue (
+ IN GPIO_PAD GpioPad,
+ OUT UINT32 *OutputVal
+ );
+
+/**
+ This procedure will get GPIO input level
+
+ @param[in] GpioPad GPIO pad
+ @param[out] InputVal GPIO Input value
+ 0: InputLow, 1: InputHigh
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetInputValue (
+ IN GPIO_PAD GpioPad,
+ OUT UINT32 *InputVal
+ );
+
+/**
+ This procedure will get GPIO IOxAPIC interrupt number
+
+ @param[in] GpioPad GPIO pad
+ @param[out] IrqNum IRQ number
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetPadIoApicIrqNumber (
+ IN GPIO_PAD GpioPad,
+ OUT UINT32 *IrqNum
+ );
+
+/**
+ This procedure will configure GPIO input inversion
+
+ @param[in] GpioPad GPIO pad
+ @param[in] Value Value for GPIO input inversion
+ 0: No input inversion, 1: Invert input
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioSetInputInversion (
+ IN GPIO_PAD GpioPad,
+ IN UINT32 Value
+ );
+
+/**
+ This procedure will get GPIO pad input inversion value
+
+ @param[in] GpioPad GPIO pad
+ @param[out] InvertState GPIO inversion state
+ 0: No input inversion, 1: Inverted input
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetInputInversion (
+ IN GPIO_PAD GpioPad,
+ OUT UINT32 *InvertState
+ );
+
+/**
+ This procedure will set GPIO interrupt settings
+
+ @param[in] GpioPad GPIO pad
+ @param[in] Value Value of Level/Edge
+ use GPIO_INT_CONFIG as argument
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioSetPadInterruptConfig (
+ IN GPIO_PAD GpioPad,
+ IN GPIO_INT_CONFIG Value
+ );
+
+/**
+ This procedure will set GPIO electrical settings
+
+ @param[in] GpioPad GPIO pad
+ @param[in] Value Value of termination
+ use GPIO_ELECTRICAL_CONFIG as argument
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioSetPadElectricalConfig (
+ IN GPIO_PAD GpioPad,
+ IN GPIO_ELECTRICAL_CONFIG Value
+ );
+
+/**
+ This procedure will set GPIO Reset settings
+
+ @param[in] GpioPad GPIO pad
+ @param[in] Value Value for Pad Reset Configuration
+ use GPIO_RESET_CONFIG as argument
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioSetPadResetConfig (
+ IN GPIO_PAD GpioPad,
+ IN GPIO_RESET_CONFIG Value
+ );
+
+/**
+ This procedure will get GPIO Reset settings
+
+ @param[in] GpioPad GPIO pad
+ @param[in] Value Value of Pad Reset Configuration
+ based on GPIO_RESET_CONFIG
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetPadResetConfig (
+ IN GPIO_PAD GpioPad,
+ IN GPIO_RESET_CONFIG *Value
+ );
+
+/**
+ This procedure will get Gpio Pad Host Software Ownership
+
+ @param[in] GpioPad GPIO pad
+ @param[out] PadHostSwOwn Value of Host Software Pad Owner
+ 0: ACPI Mode, 1: GPIO Driver mode
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetHostSwOwnershipForPad (
+ IN GPIO_PAD GpioPad,
+ OUT UINT32 *PadHostSwOwn
+ );
+
+/**
+ This procedure will set Gpio Pad Host Software Ownership
+
+ @param[in] GpioPad GPIO pad
+ @param[in] PadHostSwOwn Pad Host Software Owner
+ 0: ACPI Mode, 1: GPIO Driver mode
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioSetHostSwOwnershipForPad (
+ IN GPIO_PAD GpioPad,
+ IN UINT32 PadHostSwOwn
+ );
+
+///
+/// Possible values of Pad Ownership
+/// If Pad is not under Host ownership then GPIO registers
+/// are not accessible by host (e.g. BIOS) and reading them
+/// will return 0xFFs.
+///
+typedef enum {
+ GpioPadOwnHost = 0x0,
+ GpioPadOwnCsme = 0x1,
+ GpioPadOwnIsh = 0x2,
+} GPIO_PAD_OWN;
+
+/**
+ This procedure will get Gpio Pad Ownership
+
+ @param[in] GpioPad GPIO pad
+ @param[out] PadOwnVal Value of Pad Ownership
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetPadOwnership (
+ IN GPIO_PAD GpioPad,
+ OUT GPIO_PAD_OWN *PadOwnVal
+ );
+
+/**
+ This procedure will check state of Pad Config Lock for pads within one group
+
+ @param[in] Group GPIO group
+ @param[in] DwNum PadCfgLock register number for current group.
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[out] PadCfgLockRegVal Value of PadCfgLock register
+ Bit position - PadNumber
+ Bit value - 0: NotLocked, 1: Locked
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or DwNum parameter number
+**/
+EFI_STATUS
+GpioGetPadCfgLockForGroupDw (
+ IN GPIO_GROUP Group,
+ IN UINT32 DwNum,
+ OUT UINT32 *PadCfgLockRegVal
+ );
+
+/**
+ This procedure will check state of Pad Config Lock for selected pad
+
+ @param[in] GpioPad GPIO pad
+ @param[out] PadCfgLock PadCfgLock for selected pad
+ 0: NotLocked, 1: Locked
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetPadCfgLock (
+ IN GPIO_PAD GpioPad,
+ OUT UINT32 *PadCfgLock
+ );
+
+/**
+ This procedure will check state of Pad Config Tx Lock for pads within one group
+
+ @param[in] Group GPIO group
+ @param[in] DwNum PadCfgLockTx register number for current group.
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[out] PadCfgLockTxRegVal Value of PadCfgLockTx register
+ Bit position - PadNumber
+ Bit value - 0: NotLockedTx, 1: LockedTx
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or DwNum parameter number
+**/
+EFI_STATUS
+GpioGetPadCfgLockTxForGroupDw (
+ IN GPIO_GROUP Group,
+ IN UINT32 DwNum,
+ OUT UINT32 *PadCfgLockTxRegVal
+ );
+
+/**
+ This procedure will check state of Pad Config Tx Lock for selected pad
+
+ @param[in] GpioPad GPIO pad
+ @param[out] PadCfgLock PadCfgLockTx for selected pad
+ 0: NotLockedTx, 1: LockedTx
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetPadCfgLockTx (
+ IN GPIO_PAD GpioPad,
+ OUT UINT32 *PadCfgLockTx
+ );
+
+/**
+ This procedure will clear PadCfgLock for selected pads within one group.
+ Unlocking a pad will cause an SMI (if enabled)
+
+ @param[in] Group GPIO group
+ @param[in] DwNum PadCfgLock register number for current group.
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[in] PadsToUnlock Bitmask for pads which are going to be unlocked,
+ Bit position - PadNumber
+ Bit value - 0: DoNotUnlock, 1: Unlock
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioUnlockPadCfgForGroupDw (
+ IN GPIO_GROUP Group,
+ IN UINT32 DwNum,
+ IN UINT32 PadsToUnlock
+ );
+
+/**
+ This procedure will clear PadCfgLock for selected pad.
+ Unlocking a pad will cause an SMI (if enabled)
+
+ @param[in] GpioPad GPIO pad
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioUnlockPadCfg (
+ IN GPIO_PAD GpioPad
+ );
+
+/**
+ This procedure will set PadCfgLock for selected pads within one group
+
+ @param[in] Group GPIO group
+ @param[in] DwNum PadCfgLock register number for current group.
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[in] PadsToLock Bitmask for pads which are going to be locked,
+ Bit position - PadNumber
+ Bit value - 0: DoNotLock, 1: Lock
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or DwNum parameter number
+**/
+EFI_STATUS
+GpioLockPadCfgForGroupDw (
+ IN GPIO_GROUP Group,
+ IN UINT32 DwNum,
+ IN UINT32 PadsToLock
+ );
+
+/**
+ This procedure will set PadCfgLock for selected pad
+
+ @param[in] GpioPad GPIO pad
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioLockPadCfg (
+ IN GPIO_PAD GpioPad
+ );
+
+/**
+ This procedure will clear PadCfgLockTx for selected pads within one group.
+ Unlocking a pad will cause an SMI (if enabled)
+
+ @param[in] Group GPIO group
+ @param[in] DwNum PadCfgLockTx register number for current group.
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[in] PadsToUnlockTx Bitmask for pads which are going to be unlocked,
+ Bit position - PadNumber
+ Bit value - 0: DoNotUnLockTx, 1: LockTx
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioUnlockPadCfgTxForGroupDw (
+ IN GPIO_GROUP Group,
+ IN UINT32 DwNum,
+ IN UINT32 PadsToUnlockTx
+ );
+
+/**
+ This procedure will clear PadCfgLockTx for selected pad.
+ Unlocking a pad will cause an SMI (if enabled)
+
+ @param[in] GpioPad GPIO pad
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioUnlockPadCfgTx (
+ IN GPIO_PAD GpioPad
+ );
+
+/**
+ This procedure will set PadCfgLockTx for selected pads within one group
+
+ @param[in] Group GPIO group
+ @param[in] DwNum PadCfgLock register number for current group.
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[in] PadsToLockTx Bitmask for pads which are going to be locked,
+ Bit position - PadNumber
+ Bit value - 0: DoNotLockTx, 1: LockTx
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or DwNum parameter number
+**/
+EFI_STATUS
+GpioLockPadCfgTxForGroupDw (
+ IN GPIO_GROUP Group,
+ IN UINT32 DwNum,
+ IN UINT32 PadsToLockTx
+ );
+
+/**
+ This procedure will set PadCfgLockTx for selected pad
+
+ @param[in] GpioPad GPIO pad
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioLockPadCfgTx (
+ IN GPIO_PAD GpioPad
+ );
+
+/**
+ This procedure will get Group to GPE mapping.
+ It will assume that only first 32 pads can be mapped to GPE.
+ To handle cases where groups have more than 32 pads and higher part of group
+ can be mapped please refer to GpioGetGroupDwToGpeDwX()
+
+ @param[out] GroupToGpeDw0 GPIO group to be mapped to GPE_DW0
+ @param[out] GroupToGpeDw1 GPIO group to be mapped to GPE_DW1
+ @param[out] GroupToGpeDw2 GPIO group to be mapped to GPE_DW2
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioGetGroupToGpeDwX (
+ IN GPIO_GROUP *GroupToGpeDw0,
+ IN GPIO_GROUP *GroupToGpeDw1,
+ IN GPIO_GROUP *GroupToGpeDw2
+ );
+
+/**
+ This procedure will get Group to GPE mapping. If group has more than 32 bits
+ it is possible to map only single DW of pins (e.g. 0-31, 32-63) because
+ ACPI GPE_DWx register is 32 bits large.
+
+ @param[out] GroupToGpeDw0 GPIO group mapped to GPE_DW0
+ @param[out] GroupDwForGpeDw0 DW of pins mapped to GPE_DW0
+ @param[out] GroupToGpeDw1 GPIO group mapped to GPE_DW1
+ @param[out] GroupDwForGpeDw1 DW of pins mapped to GPE_DW1
+ @param[out] GroupToGpeDw2 GPIO group mapped to GPE_DW2
+ @param[out] GroupDwForGpeDw2 DW of pins mapped to GPE_DW2
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioGetGroupDwToGpeDwX (
+ OUT GPIO_GROUP *GroupToGpeDw0,
+ OUT UINT32 *GroupDwForGpeDw0,
+ OUT GPIO_GROUP *GroupToGpeDw1,
+ OUT UINT32 *GroupDwForGpeDw1,
+ OUT GPIO_GROUP *GroupToGpeDw2,
+ OUT UINT32 *GroupDwForGpeDw2
+ );
+
+/**
+ This procedure will get GPE number for provided GpioPad.
+ PCH allows to configure mapping between GPIO groups and related GPE (GpioSetGroupToGpeDwX())
+ what results in the fact that certain Pad can cause different General Purpose Event. Only three
+ GPIO groups can be mapped to cause unique GPE (1-tier), all others groups will be under one common
+ event (GPE_111 for 2-tier).
+
+ 1-tier:
+ Returned GpeNumber is in range <0,95>. GpioGetGpeNumber() can be used
+ to determine what _LXX ACPI method would be called on event on selected GPIO pad
+
+ 2-tier:
+ Returned GpeNumber is 0x6F (111). All GPIO pads which are not mapped to 1-tier GPE
+ will be under one master GPE_111 which is linked to _L6F ACPI method. If it is needed to determine
+ what Pad from 2-tier has caused the event, _L6F method should check GPI_GPE_STS and GPI_GPE_EN
+ registers for all GPIO groups not mapped to 1-tier GPE.
+
+ @param[in] GpioPad GPIO pad
+ @param[out] GpeNumber GPE number
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetGpeNumber (
+ IN GPIO_PAD GpioPad,
+ OUT UINT32 *GpeNumber
+ );
+
+/**
+ This procedure is used to clear SMI STS for a specified Pad
+
+ @param[in] GpioPad GPIO pad
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioClearGpiSmiSts (
+ IN GPIO_PAD GpioPad
+ );
+
+/**
+ This procedure is used by Smi Dispatcher and will clear
+ all GPI SMI Status bits
+
+ @retval EFI_SUCCESS The function completed successfully
+**/
+EFI_STATUS
+GpioClearAllGpiSmiSts (
+ VOID
+ );
+
+/**
+ This procedure is used to disable all GPI SMI
+
+ @retval EFI_SUCCESS The function completed successfully
+**/
+EFI_STATUS
+GpioDisableAllGpiSmi (
+ VOID
+ );
+
+/**
+ This procedure is used to register GPI SMI dispatch function.
+
+ @param[in] GpioPad GPIO pad
+ @param[out] GpiNum GPI number
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetGpiSmiNum (
+ IN GPIO_PAD GpioPad,
+ OUT UINTN *GpiNum
+ );
+
+/**
+ This procedure is used to check GPIO inputs belongs to 2 tier or 1 tier architecture
+
+ @param[in] GpioPad GPIO pad
+
+ @retval Data 0 means 1-tier, 1 means 2-tier
+**/
+BOOLEAN
+GpioCheckFor2Tier (
+ IN GPIO_PAD GpioPad
+ );
+
+/**
+ This procedure is used to clear GPE STS for a specified GpioPad
+
+ @param[in] GpioPad GPIO pad
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioClearGpiGpeSts (
+ IN GPIO_PAD GpioPad
+ );
+
+/**
+ This procedure is used to read GPE STS for a specified Pad
+
+ @param[in] GpioPad GPIO pad
+ @param[out] GpeSts Gpe status for given pad
+ The GpeSts is true if the status register is set for given Pad number
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetGpiGpeSts (
+ IN GPIO_PAD GpioPad,
+ OUT BOOLEAN *GpeSts
+ );
+
+/**
+ This procedure is used to get SMI STS for a specified Pad
+
+ @param[in] GpioPad GPIO pad
+ @param[out] SmiSts Smi status for given pad
+ The SmiSts is true if the status register is set for given Pad number
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetGpiSmiSts (
+ IN GPIO_PAD GpioPad,
+ OUT BOOLEAN *SmiSts
+ );
+
+/**
+ Generates GPIO name from GpioPad
+
+ @param[in] GpioPad GpioPad
+ @param[out] GpioNameBuffer Caller allocated buffer for GPIO name of GPIO_NAME_LENGTH_MAX size
+ @param[in] GpioNameBufferSize Size of the buffer
+
+ @retval CHAR8* Pointer to the GPIO name
+**/
+CHAR8*
+GpioGetPadName (
+ IN GPIO_PAD GpioPad,
+ OUT CHAR8* GpioNameBuffer,
+ IN UINT32 GpioNameBufferSize
+ );
+
+/**
+ Generates GPIO group name from GroupIndex
+
+ @param[in] GroupIndex Gpio GroupIndex
+
+ @retval CHAR8* Pointer to the GPIO group name
+**/
+CONST
+CHAR8*
+GpioGetGroupName (
+ IN UINT32 GroupIndex
+ );
+
+#endif // _GPIO_LIB_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Include/Library/GpioNativeLib.h b/Silicon/Intel/TigerlakeSiliconPkg/Include/Library/GpioNativeLib.h
new file mode 100644
index 0000000000..b09600dd30
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Include/Library/GpioNativeLib.h
@@ -0,0 +1,149 @@
+/** @file
+ Header file for GpioLib for native and Si specific usage.
+ All function in this library is available for PEI, DXE, and SMM,
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _GPIO_NATIVE_LIB_H_
+#define _GPIO_NATIVE_LIB_H_
+
+#include <Library/GpioConfig.h>
+
+/**
+ This procedure will get number of pads for certain GPIO group
+
+ @param[in] Group GPIO group number
+
+ @retval Value Pad number for group
+ If illegal group number then return 0
+**/
+UINT32
+GpioGetPadPerGroup (
+ IN GPIO_GROUP Group
+ );
+
+/**
+ This procedure will get number of groups
+
+ @param[in] none
+
+ @retval Value Group number
+**/
+UINT32
+GpioGetNumberOfGroups (
+ VOID
+ );
+/**
+ This procedure will get lowest group
+
+ @param[in] none
+
+ @retval Value Lowest Group
+**/
+GPIO_GROUP
+GpioGetLowestGroup (
+ VOID
+ );
+
+/**
+ This procedure will get highest group
+
+ @param[in] none
+
+ @retval Value Highest Group
+**/
+GPIO_GROUP
+GpioGetHighestGroup (
+ VOID
+ );
+
+/**
+ This procedure will get group
+
+ @param[in] GpioPad Gpio Pad
+
+ @retval Value Group
+**/
+GPIO_GROUP
+GpioGetGroupFromGpioPad (
+ IN GPIO_PAD GpioPad
+ );
+
+/**
+ This procedure will get group index (0 based) from GpioPad
+
+ @param[in] GpioPad Gpio Pad
+
+ @retval Value Group Index
+**/
+UINT32
+GpioGetGroupIndexFromGpioPad (
+ IN GPIO_PAD GpioPad
+ );
+
+/**
+ This procedure will get group index (0 based) from group
+
+ @param[in] GpioGroup Gpio Group
+
+ @retval Value Group Index
+**/
+UINT32
+GpioGetGroupIndexFromGroup (
+ IN GPIO_GROUP GpioGroup
+ );
+
+/**
+ This procedure will get group from group index (0 based)
+
+ @param[in] GroupIndex Group Index
+
+ @retval GpioGroup Gpio Group
+**/
+GPIO_GROUP
+GpioGetGroupFromGroupIndex (
+ IN UINT32 GroupIndex
+ );
+
+/**
+ This procedure will get pad number (0 based) from Gpio Pad
+
+ @param[in] GpioPad Gpio Pad
+
+ @retval Value Pad Number
+**/
+UINT32
+GpioGetPadNumberFromGpioPad (
+ IN GPIO_PAD GpioPad
+ );
+
+/**
+ This procedure will return GpioPad from Group and PadNumber
+
+ @param[in] Group GPIO group
+ @param[in] PadNumber GPIO PadNumber
+
+ @retval GpioPad GpioPad
+**/
+GPIO_PAD
+GpioGetGpioPadFromGroupAndPadNumber (
+ IN GPIO_GROUP Group,
+ IN UINT32 PadNumber
+ );
+
+/**
+ This procedure will return GpioPad from GroupIndex and PadNumber
+
+ @param[in] GroupIndex GPIO GroupIndex
+ @param[in] PadNumber GPIO PadNumber
+
+ @retval GpioPad GpioPad
+**/
+GPIO_PAD
+GpioGetGpioPadFromGroupIndexAndPadNumber (
+ IN UINT32 GroupIndex,
+ IN UINT32 PadNumber
+ );
+
+#endif // _GPIO_NATIVE_LIB_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Include/Library/MmPciLib.h b/Silicon/Intel/TigerlakeSiliconPkg/Include/Library/MmPciLib.h
new file mode 100644
index 0000000000..a53887ffcb
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Include/Library/MmPciLib.h
@@ -0,0 +1,27 @@
+/** @file
+ Get Pci Express address library implementation.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _MM_PCI_LIB_H_
+#define _MM_PCI_LIB_H_
+
+/**
+ This procedure will get PCIE address
+
+ @param[in] Bus Pci Bus Number
+ @param[in] Device Pci Device Number
+ @param[in] Function Pci Function Number
+
+ @retval PCIE address
+**/
+UINTN
+EFIAPI
+MmPciBase (
+ IN UINT32 Bus,
+ IN UINT32 Device,
+ IN UINT32 Function
+);
+
+#endif // _PEI_DXE_SMM_MM_PCI_LIB_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Include/Library/PchPcieRpLib.h b/Silicon/Intel/TigerlakeSiliconPkg/Include/Library/PchPcieRpLib.h
new file mode 100644
index 0000000000..3c46029b7f
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Include/Library/PchPcieRpLib.h
@@ -0,0 +1,123 @@
+/** @file
+ Header file for PchPcieRpLib.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PCH_PCIERP_LIB_H_
+#define _PCH_PCIERP_LIB_H_
+
+#include <Library/PchPcrLib.h>
+
+/**
+ PCIe controller bifurcation configuration.
+**/
+typedef enum {
+ PcieBifurcationDefault = 0,
+ PcieBifurcation4x1,
+ PcieBifurcation1x2_2x1,
+ PcieBifurcation2x2,
+ PcieBifurcation1x4,
+ PcieBifurcation4x2,
+ PcieBifurcation1x4_2x2,
+ PcieBifurcation2x2_1x4,
+ PcieBifurcation2x4,
+ PcieBifurcation1x8,
+ PcieBifurcationUnknown,
+ PcieBifurcationMax
+} PCIE_BIFURCATION_CONFIG;
+
+/**
+ This function returns PID according to PCIe controller index
+
+ @param[in] ControllerIndex PCIe controller index
+
+ @retval PCH_SBI_PID Returns PID for SBI Access
+**/
+PCH_SBI_PID
+PchGetPcieControllerSbiPid (
+ IN UINT32 ControllerIndex
+ );
+
+/**
+ This function returns PID according to Root Port Number
+
+ @param[in] RpIndex Root Port Index (0-based)
+
+ @retval PCH_SBI_PID Returns PID for SBI Access
+**/
+PCH_SBI_PID
+GetRpSbiPid (
+ IN UINTN RpIndex
+ );
+
+/**
+ Get Pch 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
+**/
+EFI_STATUS
+EFIAPI
+GetPchPcieRpDevFun (
+ IN UINTN RpNumber,
+ OUT UINTN *RpDev,
+ OUT UINTN *RpFun
+ );
+
+/**
+ Get Root Port physical Number by Pch 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 physical Root Port index (0-based)
+
+ @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
+GetPchPcieRpNumber (
+ IN UINTN RpDev,
+ IN UINTN RpFun,
+ OUT UINTN *RpNumber
+ );
+
+/**
+ Gets pci segment base address of PCIe root port.
+
+ @param RpIndex Root Port Index (0 based)
+ @return PCIe port base address.
+**/
+UINT64
+PchPcieBase (
+ IN UINT32 RpIndex
+ );
+
+/**
+ Determines whether L0s is supported on current stepping.
+
+ @return TRUE if L0s is supported, FALSE otherwise
+**/
+BOOLEAN
+PchIsPcieL0sSupported (
+ VOID
+ );
+
+/**
+ Some early PCH steppings require Native ASPM to be disabled due to hardware issues:
+ - RxL0s exit causes recovery
+ - Disabling PCIe L0s capability disables L1
+ Use this function to determine affected steppings.
+
+ @return TRUE if Native ASPM is supported, FALSE otherwise
+**/
+BOOLEAN
+PchIsPcieNativeAspmSupported (
+ VOID
+ );
+#endif // _PCH_PCIERP_LIB_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Include/Library/PchPcrLib.h b/Silicon/Intel/TigerlakeSiliconPkg/Include/Library/PchPcrLib.h
new file mode 100644
index 0000000000..f46c3da0e1
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Include/Library/PchPcrLib.h
@@ -0,0 +1,256 @@
+/** @file
+ Header file for PchPcrLib.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PCH_PCR_LIB_H_
+#define _PCH_PCR_LIB_H_
+
+#include <PchReservedResources.h>
+
+/**
+ Definition for PCR address
+ The PCR address is used to the PCR MMIO programming
+
+ SBREG_BAR_20BITADDRESS is configured by SoC
+
+ SBREG_BAR_20BITADDRESS=1, the format has included 16b addressing.
+ +---------------------------------------------------------------------------------------------+
+ | Addr[63:28] | Addr[27:24] | Addr[23:16] | Addr[15:2] | Addr[1:0] |
+ +----------------+-----------------------+-----------------+----------------------------------+
+ | REG_BAR[63:28] | TargetRegister[19:16] | TargetPort[7:0] | TargetRegister[15:2] |
+ +---------------------------------------------------------------------------------------------+
+
+ SBREG_BAR_20BITADDRESS=0
+ +---------------------------------------------------------------------------------------------+
+ | Addr[63:24] | Addr[27:24] | Addr[23:16] | Addr[15:2] | Addr[1:0] |
+ +----------------+-----------------------+-----------------+----------------------------------+
+ | REG_BAR[63:24] | REG_BAR[27:24] | TargetPort[7:0] | TargetRegister[15:2] |
+ +---------------------------------------------------------------------------------------------+
+**/
+#define PCH_PCR_ADDRESS(Pid, Offset) (PCH_PCR_BASE_ADDRESS | (UINT32) (((Offset) & 0x0F0000) << 8) | ((UINT8)(Pid) << 16) | (UINT16) ((Offset) & 0xFFFF))
+
+/**
+ PCH PCR boot script accessing macro
+ Those macros are only available for DXE phase.
+**/
+#define PCH_PCR_BOOT_SCRIPT_WRITE(Width, Pid, Offset, Count, Buffer) \
+ S3BootScriptSaveMemWrite (Width, PCH_PCR_ADDRESS (Pid, Offset), Count, Buffer); \
+
+#define PCH_PCR_BOOT_SCRIPT_READ_WRITE(Width, Pid, Offset, DataOr, DataAnd) \
+ S3BootScriptSaveMemReadWrite (Width, PCH_PCR_ADDRESS (Pid, Offset), DataOr, DataAnd); \
+
+#define PCH_PCR_BOOT_SCRIPT_READ(Width, Pid, Offset, BitMask, BitValue) \
+ S3BootScriptSaveMemPoll (Width, PCH_PCR_ADDRESS (Pid, Offset), BitMask, BitValue, 1, 1);
+
+typedef UINT8 PCH_SBI_PID;
+
+/**
+ 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
+
+ @retval UINT32 PCR register value.
+**/
+UINT32
+PchPcrRead32 (
+ IN PCH_SBI_PID Pid,
+ IN UINT32 Offset
+ );
+
+/**
+ 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
+
+ @retval UINT16 PCR register value.
+**/
+UINT16
+PchPcrRead16 (
+ IN PCH_SBI_PID Pid,
+ IN UINT32 Offset
+ );
+
+/**
+ 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
+
+ @retval UINT8 PCR register value
+**/
+UINT8
+PchPcrRead8 (
+ IN PCH_SBI_PID Pid,
+ IN UINT32 Offset
+ );
+
+/**
+ 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] Data Input Data. Must be the same size as Size parameter.
+
+ @retval UINT32 Value written to register
+**/
+UINT32
+PchPcrWrite32 (
+ IN PCH_SBI_PID Pid,
+ IN UINT32 Offset,
+ IN UINT32 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] Data Input Data. Must be the same size as Size parameter.
+
+ @retval UINT16 Value written to register
+**/
+UINT16
+PchPcrWrite16 (
+ IN PCH_SBI_PID Pid,
+ IN UINT32 Offset,
+ IN UINT16 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] Data Input Data. Must be the same size as Size parameter.
+
+ @retval UINT8 Value written to register
+**/
+UINT8
+PchPcrWrite8 (
+ IN PCH_SBI_PID Pid,
+ IN UINT32 Offset,
+ IN UINT8 InData
+ );
+
+/**
+ Write PCR register.
+ It programs PCR register and size in 4bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of Port ID.
+ @param[in] AndData AND Data. Must be the same size as Size parameter.
+ @param[in] OrData OR Data. Must be the same size as Size parameter.
+
+ @retval UINT32 Value written to register
+
+**/
+UINT32
+PchPcrAndThenOr32 (
+ IN PCH_SBI_PID Pid,
+ IN UINT32 Offset,
+ IN UINT32 AndData,
+ IN UINT32 OrData
+ );
+
+/**
+ Write PCR register and read back.
+ The read back ensures the PCR cycle is completed before next operation.
+ It programs PCR register and size in 4bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of Port ID.
+ @param[in] AndData AND Data. Must be the same size as Size parameter.
+ @param[in] OrData OR Data. Must be the same size as Size parameter.
+
+ @retval UINT32 Value read back from the register
+**/
+UINT32
+PchPcrAndThenOr32WithReadback (
+ IN PCH_SBI_PID Pid,
+ IN UINT32 Offset,
+ IN UINT32 AndData,
+ IN UINT32 OrData
+ );
+
+/**
+ Write PCR register.
+ It programs PCR register and size in 2bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of Port ID.
+ @param[in] AndData AND Data. Must be the same size as Size parameter.
+ @param[in] OrData OR Data. Must be the same size as Size parameter.
+
+ @retval UINT16 Value written to register
+
+**/
+UINT16
+PchPcrAndThenOr16 (
+ IN PCH_SBI_PID Pid,
+ IN UINT32 Offset,
+ IN UINT16 AndData,
+ IN UINT16 OrData
+ );
+
+/**
+ Write PCR register.
+ It programs PCR register and size in 1bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of Port ID.
+ @param[in] AndData AND Data. Must be the same size as Size parameter.
+ @param[in] OrData OR Data. Must be the same size as Size parameter.
+
+ @retval UINT8 Value written to register
+
+**/
+UINT8
+PchPcrAndThenOr8 (
+ IN PCH_SBI_PID Pid,
+ IN UINT32 Offset,
+ IN UINT8 AndData,
+ IN UINT8 OrData
+ );
+
+
+typedef enum {
+ PchIpDmi = 1,
+ PchIpIclk,
+} PCH_IP_PID_ENUM;
+
+#define PCH_INVALID_PID 0
+
+/**
+ Get PCH IP PID number
+
+ @param[in] IpEnum PCH IP in PCH_IP_PID_ENUM
+
+ @retval 0 PID of this IP is not supported
+ !0 PID of the IP.
+**/
+PCH_SBI_PID
+PchPcrGetPid (
+ PCH_IP_PID_ENUM IpEnum
+ );
+
+#endif // _PCH_PCR_LIB_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Include/Library/PcieHelperLib.h b/Silicon/Intel/TigerlakeSiliconPkg/Include/Library/PcieHelperLib.h
new file mode 100644
index 0000000000..8ab20f0db7
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Include/Library/PcieHelperLib.h
@@ -0,0 +1,173 @@
+/** @file
+ Header file for PCI Express helpers base library
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PCIE_HELPER_LIB_H_
+#define _PCIE_HELPER_LIB_H_
+
+#include <PcieRegs.h>
+#include <Library/PciSegmentLib.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <IndustryStandard/Pci.h>
+
+/**
+ 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] DeviceBase device's base address
+ @param[in] CapId CAPID to search for
+
+ @retval 0 CAPID not found
+ @retval Other CAPID found, Offset of desired CAPID
+**/
+UINT8
+PcieBaseFindCapId (
+ IN UINT64 DeviceBase,
+ IN UINT8 CapId
+ );
+
+/**
+ 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] Segment Pci Segment Number
+ @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 Segment,
+ IN UINT8 Bus,
+ IN UINT8 Device,
+ IN UINT8 Function,
+ IN UINT8 CapId
+ );
+
+/**
+ 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] DeviceBase device base address
+ @param[in] CapId Extended CAPID to search for
+
+ @retval 0 CAPID not found, this includes situation where device doesn't exist
+ @retval Other CAPID found, Offset of desired CAPID
+**/
+UINT16
+PcieBaseFindExtendedCapId (
+ IN UINT64 DeviceBase,
+ IN UINT16 CapId
+ );
+
+/**
+ Search and return the offset of desired Pci Express Capability ID
+ CAPID list:
+ 0x0001 = Advanced Error Rreporting Capability
+ 0x0002 = Virtual Channel Capability
+ 0x0003 = Device Serial Number Capability
+ 0x0004 = Power Budgeting Capability
+
+ @param[in] Segment Pci Segment Number
+ @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 Segment,
+ IN UINT8 Bus,
+ IN UINT8 Device,
+ IN UINT8 Function,
+ IN UINT16 CapId
+ );
+
+/*
+ Checks device's Slot Clock Configuration
+
+ @param[in] Base device's base address
+ @param[in] PcieCapOffset devices Pci express capability list register offset
+
+ @retval TRUE when device device uses slot clock, FALSE otherwise
+*/
+BOOLEAN
+GetScc (
+ UINT64 Base,
+ UINT8 PcieCapOffset
+ );
+
+/*
+ Sets Common Clock Configuration bit for given device.
+ @param[in] PcieCapOffset devices Pci express capability list register offset
+ @param[in] Base device's base address
+*/
+VOID
+EnableCcc (
+ UINT64 Base,
+ UINT8 PcieCapOffset
+ );
+
+/*
+ Retrains link behind given device.
+ It only makes sense to call it for downstream ports.
+ If called for upstream port nothing will happen, it won't enter infinite loop.
+
+ @param[in] Base device's base address
+ @param[in] PcieCapOffset devices Pci express capability list register offset
+ @param[boolean] WaitUnitlDone when TRUE, function waits until link has retrained
+*/
+VOID
+RetrainLink (
+ UINT64 Base,
+ UINT8 PcieCapOffset,
+ BOOLEAN WaitUntilDone
+ );
+
+/*
+ Checks if device at given address exists
+
+ @param[in] Base device's base address
+
+ @retval TRUE when device exists; FALSE otherwise
+*/
+BOOLEAN
+IsDevicePresent (
+ UINT64 Base
+ );
+
+/*
+ Checks if device is a multifunction device
+
+ @param[in] Base device's base address
+
+ @retval TRUE if multifunction; FALSE otherwise
+*/
+BOOLEAN
+IsMultifunctionDevice (
+ UINT64 Base
+ );
+#endif // _PCIE_HELPER_LIB_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Include/Library/PmcLib.h b/Silicon/Intel/TigerlakeSiliconPkg/Include/Library/PmcLib.h
new file mode 100644
index 0000000000..0b8ad7a182
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Include/Library/PmcLib.h
@@ -0,0 +1,355 @@
+/** @file
+ Header file for PmcLib.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PMC_LIB_H_
+#define _PMC_LIB_H_
+
+#pragma pack(1)
+
+typedef enum {
+ PmcTPch25_10us = 0,
+ PmcTPch25_100us,
+ PmcTPch25_1ms,
+ PmcTPch25_10ms,
+} PMC_TPCH25_TIMING;
+
+typedef enum {
+ PmcNotASleepState,
+ PmcInS0State,
+ PmcS1SleepState,
+ PmcS2SleepState,
+ PmcS3SleepState,
+ PmcS4SleepState,
+ PmcS5SleepState,
+ PmcUndefinedState,
+} PMC_SLEEP_STATE;
+
+typedef struct {
+ UINT32 Buf0;
+ UINT32 Buf1;
+ UINT32 Buf2;
+ UINT32 Buf3;
+} PMC_IPC_COMMAND_BUFFER;
+
+//
+// Structure to Check different attributes for CrashLog supported by PMC.
+//
+typedef union {
+ struct {
+ UINT32 Avail : 1; ///< CrashLog feature availability bit
+ UINT32 Dis : 1; ///< CrasLog Disable bit
+ UINT32 Rsvd : 2; ///< Reserved
+ UINT32 Size : 12; ///< CrasLog data size. (If it is zero, use default size 0xC00)
+ UINT32 BaseOffset : 16; ///< Start offset of CrashLog in PMC SSRAM
+ } Bits;
+ struct {
+ UINT32 Avail : 1; ///< CrashLog feature availability bit
+ UINT32 Dis : 1; ///< CrasLog Disable bit
+ UINT32 Mech : 2; ///< CrashLog mechanism
+ UINT32 ManuTri : 1; ///< Manul trigger command.
+ UINT32 Clr : 1; ///< Clear Command
+ UINT32 AllReset : 1; ///< Trigger on all reset command
+ UINT32 ReArm : 1; ///< Re-arm command
+ UINT32 Rsvd : 20; ///< Pch Specific reserved
+ UINT32 CrashLogReq: 1; ///< Crash log requestor flow
+ UINT32 TriArmedSts: 1; ///< Trigger armed status, re-arm indication bit.
+ UINT32 TriAllReset: 1; ///< Trigger on all resets status
+ UINT32 CrashDisSts: 1; ///< Crash log disabled status
+ UINT32 PchRsvd : 16; ///< Pch Specific reserved
+ UINT32 DesTableOffset: 16; ///< Descriptor Table offset
+ } Bits64;
+ UINT32 Uint32;
+ UINT64 Uint64;
+} PMC_IPC_DISCOVERY_BUF;
+
+typedef union {
+ struct {
+ UINT32 Offset : 16;
+ UINT32 Size : 16;
+ } Info;
+ UINT32 Uint32;
+} PMC_CRASHLOG_RECORDS;
+
+typedef struct PmcCrashLogLink {
+ PMC_CRASHLOG_RECORDS Record;
+ UINT64 AllocateAddress;
+ struct PmcCrashLogLink *Next;
+} PMC_CRASHLOG_LINK;
+
+#pragma pack()
+
+/**
+ Get PCH ACPI base address.
+
+ @retval Address Address of PWRM base address.
+**/
+UINT16
+PmcGetAcpiBase (
+ VOID
+ );
+
+/**
+ Get PCH PWRM base address.
+
+ @retval Address Address of PWRM base address.
+**/
+UINT32
+PmcGetPwrmBase (
+ VOID
+ );
+
+/**
+ This function sets tPCH25 timing
+
+ @param[in] TimingValue tPCH25 timing value (10us, 100us, 1ms, 10ms)
+**/
+VOID
+PmcSetTPch25Timing (
+ IN PMC_TPCH25_TIMING TimingValue
+ );
+
+/**
+ This function checks if RTC Power Failure occurred by
+ reading RTC_PWR_FLR bit
+
+ @retval RTC Power Failure state: TRUE - Battery is always present.
+ FALSE - CMOS is cleared.
+**/
+BOOLEAN
+PmcIsRtcBatteryGood (
+ VOID
+ );
+
+/**
+ This function checks if Power Failure occurred by
+ reading PWR_FLR bit
+
+ @retval Power Failure state
+**/
+BOOLEAN
+PmcIsPowerFailureDetected (
+ VOID
+ );
+
+/**
+ This function checks if Power Failure occurred by
+ reading SUS_PWR_FLR bit
+
+ @retval SUS Power Failure state
+**/
+BOOLEAN
+PmcIsSusPowerFailureDetected (
+ VOID
+ );
+
+/**
+ This function clears Power Failure status (PWR_FLR)
+**/
+VOID
+PmcClearPowerFailureStatus (
+ VOID
+ );
+
+/**
+ This function clears Global Reset status (GBL_RST_STS)
+**/
+VOID
+PmcClearGlobalResetStatus (
+ VOID
+ );
+
+/**
+ This function clears Host Reset status (HOST_RST_STS)
+**/
+VOID
+PmcClearHostResetStatus (
+ VOID
+ );
+
+/**
+ This function clears SUS Power Failure status (SUS_PWR_FLR)
+**/
+VOID
+PmcClearSusPowerFailureStatus (
+ VOID
+ );
+
+/**
+ This function sets state to which platform will get after power is reapplied
+
+ @param[in] PowerStateAfterG3 0: S0 state (boot)
+ 1: S5/S4 State
+**/
+VOID
+PmcSetPlatformStateAfterPowerFailure (
+ IN UINT8 PowerStateAfterG3
+ );
+
+/**
+ This function enables Power Button SMI
+**/
+VOID
+PmcEnablePowerButtonSmi (
+ VOID
+ );
+
+/**
+ This function disables Power Button SMI
+**/
+VOID
+PmcDisablePowerButtonSmi (
+ VOID
+ );
+
+/**
+ This function reads PM Timer Count driven by 3.579545 MHz clock
+
+ @retval PM Timer Count
+**/
+UINT32
+PmcGetTimerCount (
+ VOID
+ );
+
+/**
+ Get Sleep Type that platform has waken from
+
+ @retval SleepType Sleep Type
+**/
+PMC_SLEEP_STATE
+PmcGetSleepTypeAfterWake (
+ VOID
+ );
+
+/**
+ Clear PMC Wake Status
+**/
+VOID
+PmcClearWakeStatus (
+ VOID
+ );
+
+/**
+ Configure sleep state
+
+ @param[in] SleepState S0/S1/S3/S4/S5, refer to PMC_SLEEP_STATE
+**/
+VOID
+PmcSetSleepState (
+ PMC_SLEEP_STATE SleepState
+ );
+
+/**
+ Check if platform boots after shutdown caused by power button override event
+
+ @retval TRUE Power Button Override occurred in last system boot
+ @retval FALSE Power Button Override didn't occur
+**/
+BOOLEAN
+PmcIsPowerButtonOverrideDetected (
+ VOID
+ );
+
+/**
+ This function will set the DISB - DRAM Initialization Scratchpad Bit.
+**/
+VOID
+PmcSetDramInitScratchpad (
+ VOID
+ );
+
+/**
+ Check global SMI enable is set
+
+ @retval TRUE Global SMI enable is set
+ FALSE Global SMI enable is not set
+**/
+BOOLEAN
+PmcIsGblSmiEn (
+ VOID
+ );
+
+/**
+ This function checks if SMI Lock is set
+
+ @retval SMI Lock state
+**/
+BOOLEAN
+PmcIsSmiLockSet (
+ VOID
+ );
+
+/**
+ This function checks if Debug Mode is locked
+
+ @retval Debug Mode Lock state
+**/
+BOOLEAN
+PmcIsDebugModeLocked (
+ VOID
+ );
+
+/**
+ Check TCO second timeout status.
+
+ @retval TRUE TCO reboot happened.
+ @retval FALSE TCO reboot didn't happen.
+**/
+BOOLEAN
+TcoSecondToHappened (
+ VOID
+ );
+
+/**
+ This function clears the Second TO status bit
+**/
+VOID
+TcoClearSecondToStatus (
+ VOID
+ );
+
+/**
+ Check TCO SMI ENABLE is locked
+
+ @retval TRUE TCO SMI ENABLE is locked
+ FALSE TCO SMI ENABLE is not locked
+**/
+BOOLEAN
+TcoIsSmiLock (
+ VOID
+ );
+
+/**
+ Check if user wants to turn off in PEI phase
+
+**/
+VOID
+CheckPowerOffNow(
+ VOID
+ );
+
+
+/**
+ Clear any SMI status or wake status left from boot.
+**/
+VOID
+ClearSmiAndWake (
+ VOID
+ );
+
+/**
+ Function to check if Dirty Warm Reset occurs
+ (Global Reset has been converted to Host Reset)
+
+ @reval TRUE DWR occurs
+ @reval FALSE Normal boot flow
+**/
+BOOLEAN
+PmcIsDwrBootMode (
+ VOID
+ );
+
+#endif // _PMC_LIB_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Include/Library/ResetSystemLib.h b/Silicon/Intel/TigerlakeSiliconPkg/Include/Library/ResetSystemLib.h
new file mode 100644
index 0000000000..9ab55ad9d0
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Include/Library/ResetSystemLib.h
@@ -0,0 +1,79 @@
+/** @file
+ System reset Library Services. This library class defines a set of
+ methods that reset the whole system.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef __RESET_SYSTEM_LIB_H__
+#define __RESET_SYSTEM_LIB_H__
+
+/**
+ This function causes a system-wide reset (cold reset), in which
+ all circuitry within the system returns to its initial state. This type of reset
+ is asynchronous to system operation and operates without regard to
+ cycle boundaries.
+
+ If this function returns, it means that the system does not support cold reset.
+**/
+VOID
+EFIAPI
+ResetCold (
+ VOID
+ );
+
+/**
+ This function causes a system-wide initialization (warm reset), in which all processors
+ are set to their initial state. Pending cycles are not corrupted.
+
+ If this function returns, it means that the system does not support warm reset.
+**/
+VOID
+EFIAPI
+ResetWarm (
+ VOID
+ );
+
+/**
+ This function causes the system to enter a power state equivalent
+ to the ACPI G2/S5 or G3 states.
+
+ If this function returns, it means that the system does not support shutdown reset.
+**/
+VOID
+EFIAPI
+ResetShutdown (
+ VOID
+ );
+
+/**
+ This function causes the system to enter S3 and then wake up immediately.
+
+ If this function returns, it means that the system does not support S3 feature.
+**/
+VOID
+EFIAPI
+EnterS3WithImmediateWake (
+ VOID
+ );
+
+/**
+ This function causes a systemwide reset. The exact type of the reset is
+ defined by the EFI_GUID that follows the Null-terminated Unicode string passed
+ into ResetData. If the platform does not recognize the EFI_GUID in ResetData
+ the platform must pick a supported reset type to perform.The platform may
+ optionally log the parameters from any non-normal reset that occurs.
+
+ @param[in] DataSize The size, in bytes, of ResetData.
+ @param[in] ResetData The data buffer starts with a Null-terminated string,
+ followed by the EFI_GUID.
+**/
+VOID
+EFIAPI
+ResetPlatformSpecific (
+ IN UINTN DataSize,
+ IN VOID *ResetData
+ );
+
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Include/Library/SataLib.h b/Silicon/Intel/TigerlakeSiliconPkg/Include/Library/SataLib.h
new file mode 100644
index 0000000000..bc1555ed19
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Include/Library/SataLib.h
@@ -0,0 +1,112 @@
+/** @file
+ Header file for SataLib.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _SATA_LIB_H_
+#define _SATA_LIB_H_
+
+#define SATA_1_CONTROLLER_INDEX 0
+#define SATA_2_CONTROLLER_INDEX 1
+#define SATA_3_CONTROLLER_INDEX 2
+
+/**
+ Get Maximum Sata Port Number
+
+ @param[in] SataCtrlIndex SATA controller index
+
+ @retval Maximum Sata Port Number
+**/
+UINT8
+MaxSataPortNum (
+ IN UINT32 SataCtrlIndex
+ );
+
+/**
+ Gets Maximum Sata Controller Number
+
+ @retval Maximum Sata Controller Number
+**/
+UINT8
+MaxSataControllerNum (
+ VOID
+ );
+
+/**
+ Get SATA controller's Port Present Status
+
+ @param[in] SataCtrlIndex SATA controller index
+
+ @retval Port Present Status
+**/
+UINT8
+GetSataPortPresentStatus (
+ IN UINT32 SataCtrlIndex
+ );
+
+/**
+ Get SATA controller Function Disable Status
+
+ @param[in] SataCtrlIndex SATA controller index
+
+ @retval 0 SATA Controller is not Function Disabled
+ @retval 1 SATA Controller is Function Disabled
+**/
+BOOLEAN
+SataControllerFunctionDisableStatus (
+ IN UINT32 SataCtrlIndex
+ );
+
+/**
+ Get SATA controller ABAR size
+
+ @param[in] SataCtrlIndex SATA controller index
+
+ @retval SATA controller ABAR size
+**/
+UINT32
+GetSataAbarSize (
+ IN UINT32 SataCtrlIndex
+ );
+
+/**
+ Get SATA controller AHCI base address
+
+ @param[in] SataCtrlIndex SATA controller index
+
+ @retval SATA controller AHCI base address
+**/
+UINT32
+GetSataAhciBase (
+ IN UINT32 SataCtrlIndex
+ );
+
+/**
+ Check if SATA controller supports RST remapping
+
+ @param[in] SataCtrlIndex SATA controller index
+
+ @retval TRUE Controller supports remapping
+ @retval FALSE Controller does not support remapping
+**/
+BOOLEAN
+IsRemappingSupportedOnSata (
+ IN UINT32 SataCtrlIndex
+ );
+
+/**
+ Checks if SoC supports the SATA PGD power down on given
+ SATA controller.
+
+ @param[in] SataCtrlIndex SATA controller index
+
+ @retval TRUE SATA PGD power down supported
+ @retval FALSE SATA PGD power down not supported
+**/
+BOOLEAN
+IsSataPowerGatingSupported (
+ IN UINT32 SataCtrlIndex
+ );
+
+#endif // _SATA_LIB_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Include/Library/SerialIoAccessLib.h b/Silicon/Intel/TigerlakeSiliconPkg/Include/Library/SerialIoAccessLib.h
new file mode 100644
index 0000000000..3c8aae6ac2
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Include/Library/SerialIoAccessLib.h
@@ -0,0 +1,113 @@
+/** @file
+ Header file for Serial Io Common Lib
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _SERIAL_IO_ACCESS_LIB_H_
+#define _SERIAL_IO_ACCESS_LIB_H_
+
+/**
+ Returns BAR0
+
+ @param[in] PciCfgBase Pci Config Base
+
+ @retval 64bit MMIO BAR Address
+**/
+UINT64
+GetSerialIoBar (
+ IN UINT64 PciCfgBase
+ );
+
+/**
+ Returns I2C Pci Config Space
+
+ @param[in] I2cNumber I2C Number
+
+ @retval I2C Pci Config Space Address
+**/
+UINT64
+GetSerialIoI2cPciCfg (
+ IN UINT8 I2cNumber
+ );
+
+/**
+ Returns SPI Pci Config Space
+
+ @param[in] SpiNumber SPI Number
+
+ @retval SPI Pci Config Space Address
+**/
+UINT64
+GetSerialIoSpiPciCfg (
+ IN UINT8 SpiNumber
+ );
+
+/**
+ Returns UART Pci Config Space
+
+ @param[in] UartNumber UART Number
+
+ @retval UART Pci Config Space Address
+**/
+UINT64
+GetSerialIoUartPciCfg (
+ IN UINT8 UartNumber
+ );
+
+/**
+ Checks if Device with given PciDeviceId is one of SerialIo I2C controllers
+ If yes, its number is returned through I2cIndex parameter, otherwise I2cIndex is not updated
+
+ @param[in] PciDevId Device ID
+ @param[out] I2cNumber Number of SerialIo I2C controller
+
+ @retval TRUE yes it is a SerialIo I2C controller
+ @retval FALSE no it isn't a SerialIo I2C controller
+**/
+BOOLEAN
+IsSerialIoI2cDeviceId (
+ IN UINT16 PciDevId,
+ OUT UINT8 *I2cNumber
+ );
+
+/**
+ Checks if I2c is Function 0 Enabled
+
+ @param[in] I2cIndex Number of the SerialIo I2C controller
+
+ @retval TRUE Enabled
+ @retval FALSE Disabled
+**/
+BOOLEAN
+IsSerialIoI2cFunction0Enabled (
+ IN UINT8 I2cIndex
+ );
+
+/**
+ Checks if Uart is Function 0 Enabled
+
+ @param[in] UartIndex Number of the SerialIo Uart controller
+
+ @retval TRUE Enabled
+ @retval FALSE Disabled
+**/
+BOOLEAN
+IsSerialIoUartFunction0Enabled (
+ IN UINT8 UartIndex
+ );
+
+/**
+ Checks if Spi is Function 0 Enabled
+
+ @param[in] SpiIndex Number of the SerialIo Spi controller
+
+ @retval TRUE Enabled
+ @retval FALSE Disabled
+**/
+BOOLEAN
+IsSerialIoSpiFunction0Enabled (
+ IN UINT8 SpiIndex
+ );
+
+#endif // _SERIAL_IO_ACCESS_LIB_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Include/Library/SiConfigBlockLib.h b/Silicon/Intel/TigerlakeSiliconPkg/Include/Library/SiConfigBlockLib.h
new file mode 100644
index 0000000000..7732ccf59e
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Include/Library/SiConfigBlockLib.h
@@ -0,0 +1,56 @@
+/** @file
+ Prototype of the SiConfigBlockLib library.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _SI_CONFIG_BLOCK_LIB_H_
+#define _SI_CONFIG_BLOCK_LIB_H_
+
+
+typedef
+VOID
+(*LOAD_DEFAULT_FUNCTION) (
+ IN VOID *ConfigBlockPointer
+ );
+
+typedef struct {
+ EFI_GUID *Guid;
+ UINT16 Size;
+ UINT8 Revision;
+ LOAD_DEFAULT_FUNCTION LoadDefault;
+} COMPONENT_BLOCK_ENTRY;
+
+/**
+ GetComponentConfigBlockTotalSize get config block table total size.
+
+ @param[in] ComponentBlocks Component blocks array
+ @param[in] TotalBlockCount Number of blocks
+
+ @retval Size of config block table
+**/
+UINT16
+EFIAPI
+GetComponentConfigBlockTotalSize (
+ IN COMPONENT_BLOCK_ENTRY *ComponentBlocks,
+ IN UINT16 TotalBlockCount
+ );
+
+/**
+ AddComponentConfigBlocks add all config blocks.
+
+ @param[in] ConfigBlockTableAddress The pointer to add config blocks
+ @param[in] ComponentBlocks Config blocks array
+ @param[in] TotalBlockCount Number of blocks
+
+ @retval EFI_SUCCESS The policy default is initialized.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create buffer
+**/
+EFI_STATUS
+EFIAPI
+AddComponentConfigBlocks (
+ IN VOID *ConfigBlockTableAddress,
+ IN COMPONENT_BLOCK_ENTRY *ComponentBlocks,
+ IN UINT16 TotalBlockCount
+ );
+#endif // _SI_CONFIG_BLOCK_LIB_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Include/Library/SpiAccessLib.h b/Silicon/Intel/TigerlakeSiliconPkg/Include/Library/SpiAccessLib.h
new file mode 100644
index 0000000000..50f9e048b3
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Include/Library/SpiAccessLib.h
@@ -0,0 +1,290 @@
+/** @file
+ SPI library header for abstraction of SPI HW registers accesses
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _SPI_ACCESS_LIB_H_
+#define _SPI_ACCESS_LIB_H_
+
+/**
+ Returns SPI PCI Config Space base address
+
+ @retval UINT64 SPI Config Space base address
+**/
+UINT64
+SpiGetPciCfgAddress (
+ VOID
+ );
+
+/**
+ Returns SPI BAR0 value
+
+ @retval UINT32 PCH SPI BAR0 value
+**/
+UINT32
+SpiGetBar0 (
+ VOID
+ );
+
+/**
+ Returns SPI Device number
+
+ @retval UINT8 PCH SPI Device number
+**/
+UINT8
+SpiDeviceNumber (
+ VOID
+ );
+
+/**
+ Returns SPI Function number
+
+ @retval UINT8 PCH SPI Function number
+**/
+UINT8
+SpiFunctionNumber (
+ VOID
+ );
+
+/**
+ Returns descriptor signature
+
+ @retval UINT32 Descriptor signature
+**/
+UINT32
+SpiGetDescriptorSignature (
+ VOID
+ );
+
+/**
+ Returns supported features and R/W frequencies of Flash Component
+
+ @retval UINT32 Flash Component features descriptor
+**/
+UINT32
+SpiGetFlashComponentDescription (
+ VOID
+ );
+
+/**
+ Returns number of Flash Components
+
+ @retval UINT32 Flash components number
+**/
+UINT32
+SpiGetFlashComponentsNumber (
+ VOID
+ );
+
+/**
+ Returns total Flash size with regards to number of flash components
+
+ @retval UINT32 Total Flash Memory size
+**/
+UINT32
+SpiGetTotalFlashSize (
+ VOID
+ );
+
+/**
+ Checks if PCH SPI Controler is present and available
+
+ @retval TRUE PCH SPI controller is avaialable
+ @retval FALSE PCH SPI controller is not available
+**/
+BOOLEAN
+SpiIsControllerAvailable (
+ VOID
+ );
+
+/**
+ Checks BIOS lock bits for proper value and checks if write protection is enabled
+ Expected vales are: LE bit set, EISS bit set and WPD bit cleared
+
+ @retval TRUE All protection bits are set correctly
+ @retval FALSE Not all protection bits had exepcted values
+**/
+BOOLEAN
+SpiIsWriteProtectionEnabled (
+ VOID
+ );
+
+/**
+ Returns Flash Descriptor Override Pin Strap status
+
+ @retval TRUE Flash Descriptor override is enabled
+ @retval FALSE Flash Descriptor override is disabled
+**/
+BOOLEAN
+SpiIsFlashDescriptorOverrideEnabled (
+ VOID
+ );
+
+/**
+ Returns Flash Configuration Lock Down bit status
+
+ @retval TRUE Flash Configuration Lock Down bit is set
+ @retval FALSE Flash Configuration Lock Down bit is not set
+**/
+BOOLEAN
+SpiIsFlashConfigurationLockDownEnabled (
+ VOID
+ );
+
+/**
+ Returns Top Swap functionality enable state
+
+ @retval TRUE Top Swap is enabled
+ @retval FALSE Top Swap is disabled
+**/
+BOOLEAN
+SpiIsTopSwapEnabled (
+ VOID
+ );
+
+/**
+ Return Component Property Parameter Table for a given component number
+
+ @param[in] ComponentNumber SPI Component number
+ @param[out] CppTable Component Poperty Parameter Table value
+
+ @retval TRUE Vendor Specific Component Capabilities Register value was read
+ @reval FALSE Vendor Specific Component Capabilities Register value was not present
+**/
+BOOLEAN
+SpiGetComponentPropertyParameterTable (
+ IN UINT8 ComponentNumber,
+ OUT UINT32 *CppTable
+ );
+
+/**
+ Returns valid bit status in given Component Property Parameter Table
+
+ @param[in] CppTable Component Poperty Parameter Table value
+
+ @retval TRUE Valid bit is set
+ @reval FALSE Valid bit is not set
+**/
+BOOLEAN
+SpiIsCppValidBitSet (
+ IN UINT32 CppTable
+ );
+
+/**
+ Checks if Flash Descriptor is valid
+
+ @retval TRUE Flash Descriptor is valid
+ @retval FALSE Flash Descriptor is invalid
+**/
+BOOLEAN
+SpiIsFlashDescriptorValid (
+ VOID
+ );
+
+/**
+ Returns masked BIOS Master Read Access
+
+ @retval UINT32 Already masked BIOS Master Read Access
+**/
+UINT32
+SpiGetMasterReadAccess (
+ VOID
+ );
+
+/**
+ Returns masked BIOS Master Write Access
+
+ @retval UINT32 Already masked BIOS Master Write Access
+**/
+UINT32
+SpiGetMasterWriteAccess (
+ VOID
+ );
+
+/**
+ Returns GbE Region Access rights
+
+ @retval UINT32 GbE Region access rights
+**/
+UINT32
+SpiGetGbeRegionAccess (
+ VOID
+ );
+
+/**
+ Returns CSME region access rights
+
+ @retval UINT32 CSME Region Access rights
+**/
+UINT32
+SpiGetCsmeRegionAccess (
+ VOID
+ );
+
+/**
+ Returns EC region access right
+
+ @retval UINT32 EC Region access rights
+**/
+UINT32
+SpiGetEcRegionAccess (
+ VOID
+ );
+
+/**
+ Checks if Slave Attached Flash (SAF) mode is active
+
+ @retval TRUE SAF mode is active
+ @retval FALSE SAF mode is not active
+**/
+BOOLEAN
+SpiIsSafModeActive (
+ VOID
+ );
+
+/**
+ Checks validity of GbE region
+
+ @retval TRUE GbE region is valid
+ @retval FALSE GbE regios in invalid
+**/
+BOOLEAN
+SpiIsGbeRegionValid (
+ VOID
+ );
+
+/**
+ Returns status of BIOS Interface Lockdown
+
+ @retval TRUE BIOS Interface Lockdown is enabled
+ @retval FALSE BIOS Interface Lockdown is disabled
+**/
+BOOLEAN
+SpiIsBiosInterfaceLockdownEnabled (
+ VOID
+ );
+
+/**
+ Returns TRUE if BIOS Boot Strap is set to SPI
+
+ @retval TRUE BIOS Boot strap is set to SPI
+ @retval FALSE BIOS Boot strap is set to LPC/eSPI
+**/
+BOOLEAN
+SpiIsBiosBootFromSpi (
+ VOID
+ );
+
+/**
+ Check SPI write status disable is set
+
+ @retval TRUE Write status disable is set
+ @retval FALSE Write status disable is not set
+**/
+BOOLEAN
+SpiIsWriteStatusDisable (
+ VOID
+ );
+
+#endif // _SPI_ACCESS_LIB_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Include/Library/VtdInfoLib.h b/Silicon/Intel/TigerlakeSiliconPkg/Include/Library/VtdInfoLib.h
new file mode 100644
index 0000000000..69eed8d32d
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Include/Library/VtdInfoLib.h
@@ -0,0 +1,53 @@
+/** @file
+ Header file for VtdInfoLib.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _VTD_INFO_LIB_H_
+#define _VTD_INFO_LIB_H_
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/HobLib.h>
+
+#define VTD_ENGINE_NUMBER 7
+
+#pragma pack(1)
+
+/**
+ Get VTD Engine Base Address from PCD values.
+
+ @param[in] VtdEngineNumber - Engine number for which VTD Base Adderess is required.
+
+ @retval VTD Engine Base Address
+**/
+UINT32
+GetVtdBaseAddress (
+ IN UINT8 VtdEngineNumber
+ );
+
+/**
+ Read VTD Engine Base Address from VTD BAR Offsets.
+
+ @param[in] VtdEngineNumber - Engine number for which VTD Base Adderess is required.
+
+ @retval VTD Engine Base Address
+**/
+UINT32
+ReadVtdBaseAddress (
+ IN UINT8 VtdEngineNumber
+ );
+
+/**
+ GetMaxVtdEngineNumber: Get Maximum Vtd Engine Number
+
+ @retval Vtd Engine Number
+**/
+UINT8
+GetMaxVtdEngineNumber(
+ VOID
+);
+
+#pragma pack()
+#endif // _VTD_INFO_LIB_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Include/Ppi/PeiPreMemSiDefaultPolicy.h b/Silicon/Intel/TigerlakeSiliconPkg/Include/Ppi/PeiPreMemSiDefaultPolicy.h
new file mode 100644
index 0000000000..3fd917c2b9
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Include/Ppi/PeiPreMemSiDefaultPolicy.h
@@ -0,0 +1,34 @@
+/** @file
+ This file defines the function to initialize default silicon policy PPI.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _PEI_PREMEM_SI_DEFAULT_POLICY_INIT_PPI_H_
+#define _PEI_PREMEM_SI_DEFAULT_POLICY_INIT_PPI_H_
+
+//
+// Forward declaration for the PEI_PREMEM_SI_DEFAULT_POLICY_INIT_PPI.
+//
+typedef struct _PEI_PREMEM_SI_DEFAULT_POLICY_INIT_PPI PEI_PREMEM_SI_DEFAULT_POLICY_INIT_PPI;
+
+/**
+ Initialize and install default silicon policy PPI
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PEI_PREMEM_POLICY_INIT) (
+ VOID
+ );
+
+///
+/// This PPI provides function to install default silicon policy
+///
+struct _PEI_PREMEM_SI_DEFAULT_POLICY_INIT_PPI {
+ PEI_PREMEM_POLICY_INIT PeiPreMemPolicyInit; ///< PeiPreMemPolicyInit()
+};
+
+extern EFI_GUID gSiPreMemDefaultPolicyInitPpiGuid;
+
+#endif // _PEI_PREMEM_SI_DEFAULT_POLICY_INIT_PPI_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Include/Ppi/PeiSiDefaultPolicy.h b/Silicon/Intel/TigerlakeSiliconPkg/Include/Ppi/PeiSiDefaultPolicy.h
new file mode 100644
index 0000000000..9cb34728cc
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Include/Ppi/PeiSiDefaultPolicy.h
@@ -0,0 +1,33 @@
+/** @file
+ This file defines the function to initialize default silicon policy PPI.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PEI_SI_DEFAULT_POLICY_INIT_PPI_H_
+#define _PEI_SI_DEFAULT_POLICY_INIT_PPI_H_
+
+//
+// Forward declaration for the PEI_SI_DEFAULT_POLICY_INIT_PPI.
+//
+typedef struct _PEI_SI_DEFAULT_POLICY_INIT_PPI PEI_SI_DEFAULT_POLICY_INIT_PPI;
+
+/**
+ Initialize and install default silicon policy PPI
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PEI_POLICY_INIT) (
+ VOID
+ );
+
+///
+/// This PPI provides function to install default silicon policy
+///
+struct _PEI_SI_DEFAULT_POLICY_INIT_PPI {
+ PEI_POLICY_INIT PeiPolicyInit; ///< PeiPolicyInit()
+};
+
+extern EFI_GUID gSiDefaultPolicyInitPpiGuid;
+
+#endif // _PEI_SI_DEFAULT_POLICY_INIT_PPI_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Include/Ppi/SiPolicy.h b/Silicon/Intel/TigerlakeSiliconPkg/Include/Ppi/SiPolicy.h
new file mode 100644
index 0000000000..5f4d467439
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Include/Ppi/SiPolicy.h
@@ -0,0 +1,75 @@
+/** @file
+ Silicon Policy PPI is used for specifying platform
+ related Intel silicon information and policy setting.
+ This PPI is consumed by the silicon PEI modules and carried
+ over to silicon DXE modules.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _SI_POLICY_PPI_H_
+#define _SI_POLICY_PPI_H_
+
+#include <SiPolicyStruct.h>
+#include <PchPolicyCommon.h>
+#include <PchPreMemPolicyCommon.h>
+#include <MePolicyCommon.h>
+#include <CpuPolicyCommon.h>
+#include <Uefi.h>
+#include <Library/ConfigBlockLib.h>
+
+#ifndef DISABLED
+#define DISABLED 0
+#endif
+#ifndef ENABLED
+#define ENABLED 1
+#endif
+
+extern EFI_GUID gSiPreMemPolicyPpiGuid;
+extern EFI_GUID gSiPolicyPpiGuid;
+
+
+#include <GraphicsConfig.h>
+extern EFI_GUID gGraphicsPeiPreMemConfigGuid;
+extern EFI_GUID gGraphicsPeiConfigGuid;
+
+#include <VtdConfig.h>
+extern EFI_GUID gVtdConfigGuid;
+
+#include <GnaConfig.h>
+extern EFI_GUID gGnaConfigGuid;
+
+#include <CpuPcieConfig.h>
+extern EFI_GUID gCpuPciePeiPreMemConfigGuid;
+extern EFI_GUID gCpuPcieRpConfigGuid;
+
+#include <HybridGraphicsConfig.h>
+extern EFI_GUID gHybridGraphicsConfigGuid;
+
+#include <ConfigBlock/PramPreMemConfig.h>
+#include <MemoryConfig.h>
+extern EFI_GUID gMemoryConfigGuid;
+extern EFI_GUID gMemoryConfigNoCrcGuid;
+
+#include <ConfigBlock/SaMiscPeiPreMemConfig.h>
+extern EFI_GUID gSaMiscPeiPreMemConfigGuid;
+
+#include <ConfigBlock/SaMiscPeiConfig.h>
+extern EFI_GUID gSaMiscPeiConfigGuid;
+
+
+#include <TraceHubConfig.h>
+extern EFI_GUID gCpuTraceHubConfigGuid;
+
+#include <HostBridgeConfig.h>
+extern EFI_GUID gHostBridgePeiPreMemConfigGuid;
+extern EFI_GUID gHostBridgePeiConfigGuid;
+
+#include <CpuDmiPreMemConfig.h>
+extern EFI_GUID gCpuDmiPreMemConfigGuid;
+
+typedef struct _SI_PREMEM_POLICY_STRUCT SI_PREMEM_POLICY_PPI;
+typedef struct _SI_POLICY_STRUCT SI_POLICY_PPI;
+
+#endif // _SI_POLICY_PPI_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Include/Protocol/GopComponentName2.h b/Silicon/Intel/TigerlakeSiliconPkg/Include/Protocol/GopComponentName2.h
new file mode 100644
index 0000000000..1d69ee0e8d
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Include/Protocol/GopComponentName2.h
@@ -0,0 +1,61 @@
+/** @file
+ Protocol to retrieve the GOP driver version
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _GOP_COMPONENT_NAME2_H_
+#define _GOP_COMPONENT_NAME2_H_
+
+
+typedef struct _GOP_COMPONENT_NAME2_PROTOCOL GOP_COMPONENT_NAME2_PROTOCOL;
+
+///
+/// GOP Component protocol for retrieving driver name
+///
+typedef
+EFI_STATUS
+(EFIAPI *GOP_COMPONENT_NAME2_GET_DRIVER_NAME) (
+ IN GOP_COMPONENT_NAME2_PROTOCOL * This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ );
+
+///
+/// GOP Component protocol for retrieving controller name
+///
+typedef
+EFI_STATUS
+(EFIAPI *GOP_COMPONENT_NAME2_GET_CONTROLLER_NAME) (
+ IN GOP_COMPONENT_NAME2_PROTOCOL * This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ );
+
+///
+/// GOP Component protocol for retrieving driver version
+///
+typedef
+EFI_STATUS
+(EFIAPI *GOP_COMPONENT_NAME2_GET_DRIVER_VERSION) (
+ IN GOP_COMPONENT_NAME2_PROTOCOL * This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverVersion
+ );
+
+/**
+ GOP Component protocol\n
+ This protocol will be installed by GOP driver and can be used to retrieve GOP information.
+**/
+struct _GOP_COMPONENT_NAME2_PROTOCOL {
+ GOP_COMPONENT_NAME2_GET_DRIVER_NAME GetDriverName; ///< Protocol function to get driver name
+ GOP_COMPONENT_NAME2_GET_DRIVER_VERSION GetDriverVersion; ///< Protocol function to get driver version
+ GOP_COMPONENT_NAME2_GET_CONTROLLER_NAME GetControllerName; ///< Protocol function to get controller name
+ CHAR8 *SupportedLanguages; ///< Number of Supported languages.
+};
+
+extern EFI_GUID gGopComponentName2ProtocolGuid;
+
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Include/Protocol/GopPolicy.h b/Silicon/Intel/TigerlakeSiliconPkg/Include/Protocol/GopPolicy.h
new file mode 100644
index 0000000000..c8dc17008e
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Include/Protocol/GopPolicy.h
@@ -0,0 +1,73 @@
+/** @file
+ Interface definition for GopPolicy Protocol.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _GOP_POLICY_PROTOCOL_H_
+#define _GOP_POLICY_PROTOCOL_H_
+
+
+#define GOP_POLICY_PROTOCOL_REVISION_01 0x01
+#define GOP_POLICY_PROTOCOL_REVISION_03 0x03
+
+typedef enum {
+ LidClosed,
+ LidOpen,
+ LidStatusMax
+} LID_STATUS;
+
+typedef enum {
+ Docked,
+ UnDocked,
+ DockStatusMax
+} DOCK_STATUS;
+
+///
+/// Function to retrieve LID status
+///
+typedef
+EFI_STATUS
+(EFIAPI *GET_PLATFORM_LID_STATUS) (
+ OUT LID_STATUS * CurrentLidStatus
+ );
+
+///
+/// Function to retrieve Dock status
+///
+typedef
+EFI_STATUS
+(EFIAPI *GET_PLATFORM_DOCK_STATUS) (
+ OUT DOCK_STATUS CurrentDockStatus
+);
+
+///
+/// Function to retrieve VBT table address and size
+///
+typedef
+EFI_STATUS
+(EFIAPI *GET_VBT_DATA) (
+ OUT EFI_PHYSICAL_ADDRESS * VbtAddress,
+ OUT UINT32 *VbtSize
+ );
+
+/**
+ System Agent Graphics Output Protocol (GOP) - Policy Protocol\n
+ Graphics Output Protocol (GOP) is a UEFI API replacing legacy Video ROMs for EFI boot\n
+ When GOP Driver is used this protocol can be consumed by GOP driver or platform code for GOP relevant initialization\n
+ All functions in this protocol should be initialized by platform code basing on platform implementation\n
+**/
+typedef struct {
+ UINT32 Revision; ///< Protocol revision
+ GET_PLATFORM_LID_STATUS GetPlatformLidStatus; ///< Protocol function to get Lid Status. Platform code should provide this function basing on design.
+ GET_VBT_DATA GetVbtData; ///< Protocol function to get Vbt Data address and size. Platform code should provide this function basing on design.
+ GET_PLATFORM_DOCK_STATUS GetPlatformDockStatus; ///< Function pointer for get platform dock status.
+ EFI_GUID GopOverrideGuid; ///< A GUID provided by BIOS in case GOP is to be overridden.
+} GOP_POLICY_PROTOCOL;
+
+extern EFI_GUID gGopPolicyProtocolGuid;
+extern EFI_GUID gGen12PolicyProtocolGuid;
+extern EFI_GUID gGen9PolicyProtocolGuid;
+extern EFI_GUID gIntelGraphicsVbtGuid;
+
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Include/Protocol/IgdOpRegion.h b/Silicon/Intel/TigerlakeSiliconPkg/Include/Protocol/IgdOpRegion.h
new file mode 100644
index 0000000000..c030f771e3
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Include/Protocol/IgdOpRegion.h
@@ -0,0 +1,22 @@
+/** @file
+ This file is part of the IGD OpRegion Implementation. The IGD OpRegion is
+ an interface between system BIOS, ASL code, and Graphics drivers.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _IGD_OPREGION_PROTOCOL_H_
+#define _IGD_OPREGION_PROTOCOL_H_
+
+#include <IndustryStandard/IgdOpRegion.h>
+
+extern EFI_GUID gIgdOpRegionProtocolGuid;
+
+///
+/// IGD OpRegion Protocol
+///
+typedef struct {
+ IGD_OPREGION_STRUCTURE *OpRegion; ///< IGD Operation Region Structure
+} IGD_OPREGION_PROTOCOL;
+
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Include/Protocol/Spi.h b/Silicon/Intel/TigerlakeSiliconPkg/Include/Protocol/Spi.h
new file mode 100644
index 0000000000..c13dc5a5f5
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Include/Protocol/Spi.h
@@ -0,0 +1,301 @@
+/** @file
+ This file defines the PCH SPI Protocol which implements the
+ Intel(R) PCH SPI Host Controller Compatibility Interface.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PCH_SPI_PROTOCOL_H_
+#define _PCH_SPI_PROTOCOL_H_
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID gPchSpiProtocolGuid;
+extern EFI_GUID gPchSmmSpiProtocolGuid;
+
+//
+// Forward reference for ANSI C compatibility
+//
+typedef struct _PCH_SPI_PROTOCOL PCH_SPI_PROTOCOL;
+
+//
+// SPI protocol data structures and definitions
+//
+
+/**
+ Flash Region Type
+**/
+typedef enum {
+ FlashRegionDescriptor,
+ FlashRegionBios,
+ FlashRegionMe,
+ FlashRegionGbE,
+ FlashRegionPlatformData,
+ FlashRegionDer,
+ FlashRegionSecondaryBios,
+ FlashRegionuCodePatch,
+ FlashRegionEC,
+ FlashRegionDeviceExpansion2,
+ FlashRegionIE,
+ FlashRegion10Gbe_A,
+ FlashRegion10Gbe_B,
+ FlashRegion13,
+ FlashRegion14,
+ FlashRegion15,
+ FlashRegionAll,
+ FlashRegionMax
+} FLASH_REGION_TYPE;
+//
+// Protocol member functions
+//
+
+/**
+ Read data from the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] FlashRegionType The Flash Region type for flash cycle which is listed in the Descriptor.
+ @param[in] Address The Flash Linear Address must fall within a region for which BIOS has access permissions.
+ @param[in] ByteCount Number of bytes in the data portion of the SPI cycle.
+ @param[out] Buffer The Pointer to caller-allocated buffer containing the dada received.
+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SPI_FLASH_READ) (
+ IN PCH_SPI_PROTOCOL *This,
+ IN FLASH_REGION_TYPE FlashRegionType,
+ IN UINT32 Address,
+ IN UINT32 ByteCount,
+ OUT UINT8 *Buffer
+ );
+
+/**
+ Write data to the flash part. Remark: Erase may be needed before write to the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] FlashRegionType The Flash Region type for flash cycle which is listed in the Descriptor.
+ @param[in] Address The Flash Linear Address must fall within a region for which BIOS has access permissions.
+ @param[in] ByteCount Number of bytes in the data portion of the SPI cycle.
+ @param[in] Buffer Pointer to caller-allocated buffer containing the data sent during the SPI cycle.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SPI_FLASH_WRITE) (
+ IN PCH_SPI_PROTOCOL *This,
+ IN FLASH_REGION_TYPE FlashRegionType,
+ IN UINT32 Address,
+ IN UINT32 ByteCount,
+ IN UINT8 *Buffer
+ );
+
+/**
+ Erase some area on the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] FlashRegionType The Flash Region type for flash cycle which is listed in the Descriptor.
+ @param[in] Address The Flash Linear Address must fall within a region for which BIOS has access permissions.
+ @param[in] ByteCount Number of bytes in the data portion of the SPI cycle.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SPI_FLASH_ERASE) (
+ IN PCH_SPI_PROTOCOL *This,
+ IN FLASH_REGION_TYPE FlashRegionType,
+ IN UINT32 Address,
+ IN UINT32 ByteCount
+ );
+
+/**
+ Read SFDP data from the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] ComponentNumber The Componen Number for chip select
+ @param[in] Address The starting byte address for SFDP data read.
+ @param[in] ByteCount Number of bytes in SFDP data portion of the SPI cycle
+ @param[out] SfdpData The Pointer to caller-allocated buffer containing the SFDP data received
+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SPI_FLASH_READ_SFDP) (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT8 ComponentNumber,
+ IN UINT32 Address,
+ IN UINT32 ByteCount,
+ OUT UINT8 *SfdpData
+ );
+
+/**
+ Read Jedec Id from the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] ComponentNumber The Componen Number for chip select
+ @param[in] ByteCount Number of bytes in JedecId data portion of the SPI cycle, the data size is 3 typically
+ @param[out] JedecId The Pointer to caller-allocated buffer containing JEDEC ID received
+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SPI_FLASH_READ_JEDEC_ID) (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT8 ComponentNumber,
+ IN UINT32 ByteCount,
+ OUT UINT8 *JedecId
+ );
+
+/**
+ Write the status register in the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] ByteCount Number of bytes in Status data portion of the SPI cycle, the data size is 1 typically
+ @param[in] StatusValue The Pointer to caller-allocated buffer containing the value of Status register writing
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SPI_FLASH_WRITE_STATUS) (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT32 ByteCount,
+ IN UINT8 *StatusValue
+ );
+
+/**
+ Read status register in the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] ByteCount Number of bytes in Status data portion of the SPI cycle, the data size is 1 typically
+ @param[out] StatusValue The Pointer to caller-allocated buffer containing the value of Status register received.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SPI_FLASH_READ_STATUS) (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT32 ByteCount,
+ OUT UINT8 *StatusValue
+ );
+
+/**
+ Get the SPI region base and size, based on the enum type
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] FlashRegionType The Flash Region type for for the base address which is listed in the Descriptor.
+ @param[out] BaseAddress The Flash Linear Address for the Region 'n' Base
+ @param[out] RegionSize The size for the Region 'n'
+
+ @retval EFI_SUCCESS Read success
+ @retval EFI_INVALID_PARAMETER Invalid region type given
+ @retval EFI_DEVICE_ERROR The region is not used
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SPI_GET_REGION_ADDRESS) (
+ IN PCH_SPI_PROTOCOL *This,
+ IN FLASH_REGION_TYPE FlashRegionType,
+ OUT UINT32 *BaseAddress,
+ OUT UINT32 *RegionSize
+ );
+
+/**
+ Read PCH Soft Strap Values
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] SoftStrapAddr PCH Soft Strap address offset from FPSBA.
+ @param[in] ByteCount Number of bytes in SoftStrap data portion of the SPI cycle
+ @param[out] SoftStrapValue The Pointer to caller-allocated buffer containing PCH Soft Strap Value.
+ If the value of ByteCount is 0, the data type of SoftStrapValue should be UINT16 and SoftStrapValue will be PCH Soft Strap Length
+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SPI_READ_PCH_SOFTSTRAP) (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT32 SoftStrapAddr,
+ IN UINT32 ByteCount,
+ OUT VOID *SoftStrapValue
+ );
+
+/**
+ Read CPU Soft Strap Values
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] SoftStrapAddr CPU Soft Strap address offset from FCPUSBA.
+ @param[in] ByteCount Number of bytes in SoftStrap data portion of the SPI cycle.
+ @param[out] SoftStrapValue The Pointer to caller-allocated buffer containing CPU Soft Strap Value.
+ If the value of ByteCount is 0, the data type of SoftStrapValue should be UINT16 and SoftStrapValue will be PCH Soft Strap Length
+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SPI_READ_CPU_SOFTSTRAP) (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT32 SoftStrapAddr,
+ IN UINT32 ByteCount,
+ OUT VOID *SoftStrapValue
+ );
+
+/**
+ These protocols/PPI allows a platform module to perform SPI operations through the
+ Intel PCH SPI Host Controller Interface.
+**/
+struct _PCH_SPI_PROTOCOL {
+ /**
+ This member specifies the revision of this structure. This field is used to
+ indicate backwards compatible changes to the protocol.
+ **/
+ UINT8 Revision;
+ PCH_SPI_FLASH_READ FlashRead; ///< Read data from the flash part.
+ PCH_SPI_FLASH_WRITE FlashWrite; ///< Write data to the flash part. Remark: Erase may be needed before write to the flash part.
+ PCH_SPI_FLASH_ERASE FlashErase; ///< Erase some area on the flash part.
+ PCH_SPI_FLASH_READ_SFDP FlashReadSfdp; ///< Read SFDP data from the flash part.
+ PCH_SPI_FLASH_READ_JEDEC_ID FlashReadJedecId; ///< Read Jedec Id from the flash part.
+ PCH_SPI_FLASH_WRITE_STATUS FlashWriteStatus; ///< Write the status register in the flash part.
+ PCH_SPI_FLASH_READ_STATUS FlashReadStatus; ///< Read status register in the flash part.
+ PCH_SPI_GET_REGION_ADDRESS GetRegionAddress; ///< Get the SPI region base and size
+ PCH_SPI_READ_PCH_SOFTSTRAP ReadPchSoftStrap; ///< Read PCH Soft Strap Values
+ PCH_SPI_READ_CPU_SOFTSTRAP ReadCpuSoftStrap; ///< Read CPU Soft Strap Values
+};
+
+/**
+ PCH SPI PPI/PROTOCOL revision number
+
+ Revision 1: Initial version
+**/
+#define PCH_SPI_SERVICES_REVISION 1
+
+#endif
--
2.24.0.windows.2
^ permalink raw reply related [flat|nested] 42+ messages in thread
* [Patch V3 03/40] TigerlakeSiliconPkg/Include: Add Pins, Register and other include headers
2021-02-05 7:40 [Patch V3 01/40] TigerlakeSiliconPkg: Add package and Include/ConfigBlock headers Heng Luo
2021-02-05 7:40 ` [Patch V3 02/40] TigerlakeSiliconPkg/Include: Add Library, PPI and Protocol include headers Heng Luo
@ 2021-02-05 7:40 ` Heng Luo
2021-02-05 7:40 ` [Patch V3 04/40] TigerlakeSiliconPkg/Cpu: Add Include headers Heng Luo
` (36 subsequent siblings)
38 siblings, 0 replies; 42+ messages in thread
From: Heng Luo @ 2021-02-05 7:40 UTC (permalink / raw)
To: devel; +Cc: Sai Chaganty, Nate DeSimone
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3171
Adds the following header files:
* Include/Pins
* Include/Register
* Include/*.h
Cc: Sai Chaganty <rangasai.v.chaganty@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Signed-off-by: Heng Luo <heng.luo@intel.com>
---
Silicon/Intel/TigerlakeSiliconPkg/Include/ConfigBlock.h | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Include/CpuPcieHob.h | 38 ++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Include/DmaRemappingTable.h | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Include/DxeHdaNhlt.h | 138 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Include/Hda.h | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Include/MePolicyCommon.h | 24 ++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Include/PcieRegs.h | 155 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Include/Pins/GpioPinsVer2Lp.h | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Include/Register/FlashRegs.h | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Include/Register/GpioRegs.h | 121 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Include/Register/GpioRegsVer2.h | 226 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Include/Register/PchDmi14Regs.h | 16 ++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Include/Register/PchDmiRegs.h | 36 ++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Include/Register/PchPcieRpRegs.h | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Include/Register/PmcRegs.h | 258 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Include/Register/RtcRegs.h | 45 +++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Include/Register/SataRegs.h | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Include/Register/SerialIoRegs.h | 47 +++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Include/Register/UsbRegs.h | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Include/SerialIoDevices.h | 213 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Include/SiConfigHob.h | 17 +++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Include/SiPolicyStruct.h | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
22 files changed, 1965 insertions(+)
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Include/ConfigBlock.h b/Silicon/Intel/TigerlakeSiliconPkg/Include/ConfigBlock.h
new file mode 100644
index 0000000000..ad34e4ea42
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Include/ConfigBlock.h
@@ -0,0 +1,53 @@
+/** @file
+ Header file for Config Block Lib implementation
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _CONFIG_BLOCK_H_
+#define _CONFIG_BLOCK_H_
+
+#include <Uefi/UefiBaseType.h>
+#include <Uefi/UefiMultiPhase.h>
+#include <Pi/PiBootMode.h>
+#include <Pi/PiHob.h>
+
+#pragma pack (push,1)
+
+///
+/// Config Block Header
+///
+typedef struct _CONFIG_BLOCK_HEADER {
+ EFI_HOB_GUID_TYPE GuidHob; ///< Offset 0-23 GUID extension HOB header
+ UINT8 Revision; ///< Offset 24 Revision of this config block
+ UINT8 Attributes; ///< Offset 25 The main revision for config block
+ UINT8 Reserved[2]; ///< Offset 26-27 Reserved for future use
+} CONFIG_BLOCK_HEADER;
+
+///
+/// Config Block
+///
+typedef struct _CONFIG_BLOCK {
+ CONFIG_BLOCK_HEADER Header; ///< Offset 0-27 Header of config block
+ //
+ // Config Block Data
+ //
+} CONFIG_BLOCK;
+
+///
+/// Config Block Table Header
+///
+typedef struct _CONFIG_BLOCK_TABLE_STRUCT {
+ CONFIG_BLOCK_HEADER Header; ///< Offset 0-27 GUID number for main entry of config block
+ UINT8 Rsvd0[2]; ///< Offset 28-29 Reserved for future use
+ UINT16 NumberOfBlocks; ///< Offset 30-31 Number of config blocks (N)
+ UINT32 AvailableSize; ///< Offset 32-35 Current config block table size
+///
+/// Individual Config Block Structures are added here in memory as part of AddConfigBlock()
+///
+} CONFIG_BLOCK_TABLE_HEADER;
+#pragma pack (pop)
+
+#endif // _CONFIG_BLOCK_H_
+
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Include/CpuPcieHob.h b/Silicon/Intel/TigerlakeSiliconPkg/Include/CpuPcieHob.h
new file mode 100644
index 0000000000..23a408e8dc
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Include/CpuPcieHob.h
@@ -0,0 +1,38 @@
+/** @file
+ The GUID definition for CpuPcieHob
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _CPU_PCIE_HOB_H_
+#define _CPU_PCIE_HOB_H_
+
+#include <Base.h>
+#include <CpuPcieInfo.h>
+#include <CpuPcieConfig.h>
+
+extern EFI_GUID gCpuPcieHobGuid;
+#pragma pack (push,1)
+
+/**
+ The CPU_PCIE_HOB block describes the expected configuration of the CpuPcie controllers
+**/
+typedef struct {
+ ///
+ /// These members describe the configuration of each CPU PCIe root port.
+ ///
+ EFI_HOB_GUID_TYPE EfiHobGuidType; ///< Offset 0 - 23: GUID Hob type structure for gCpuPcieHobGuid
+ CPU_PCIE_ROOT_PORT_CONFIG RootPort[CPU_PCIE_MAX_ROOT_PORTS];
+ UINT8 L1SubStates[CPU_PCIE_MAX_ROOT_PORTS]; ///< The L1 Substates configuration of the root port
+
+ UINT32 DekelFwVersionMinor; ///< Dekel Firmware Minor Version
+ UINT32 DekelFwVersionMajor; ///< Dekel Firmware Major Version
+ BOOLEAN InitPcieAspmAfterOprom; ///< 1=initialize PCIe ASPM after Oprom; 0=before (This will be set basing on policy)
+ UINT32 RpEnabledMask; ///< Rootport enabled mask based on DEVEN register
+ UINT32 RpEnMaskFromDevEn; ///< Rootport enabled mask based on Device Id
+ UINT8 DisableClkReqMsg[CPU_PCIE_MAX_ROOT_PORTS]; ///< 1=ClkReqMsg disabled, 0=ClkReqMsg enabled
+ UINT8 SlotSelection; ///< 1=M2 slot, 0=CEMx4 slot
+ BOOLEAN ComplianceTest; ///< Compliance Test based on policy
+} CPU_PCIE_HOB;
+#pragma pack (pop)
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Include/DmaRemappingTable.h b/Silicon/Intel/TigerlakeSiliconPkg/Include/DmaRemappingTable.h
new file mode 100644
index 0000000000..5b058c7a45
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Include/DmaRemappingTable.h
@@ -0,0 +1,75 @@
+/** @file
+ This code defines ACPI DMA Remapping table related definitions.
+ See the System Agent BIOS specification for definition of the table.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _DMA_REMAPPING_TABLE_H_
+#define _DMA_REMAPPING_TABLE_H_
+
+#include <Uefi.h>
+#include <Base.h>
+#include <IndustryStandard/DmaRemappingReportingTable.h>
+#include <IndustryStandard/Acpi.h>
+#include <TcssInfo.h>
+
+#pragma pack(1)
+///
+/// DMAR table signature
+///
+#define EFI_ACPI_VTD_DMAR_TABLE_SIGNATURE 0x52414D44 ///< "DMAR"
+#define EFI_ACPI_DMAR_TABLE_REVISION 2
+#define EFI_ACPI_DRHD_ENGINE_HEADER_LENGTH 0x10
+#define EFI_ACPI_RMRR_HEADER_LENGTH 0x18
+#define MAX_PCI_DEPTH 5
+
+typedef struct {
+ EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER DeviceScopeStructureHeader;
+ EFI_ACPI_DMAR_PCI_PATH PciPath; // device, function
+} EFI_ACPI_DEV_SCOPE_STRUCTURE;
+
+typedef struct {
+ EFI_ACPI_DMAR_DRHD_HEADER DrhdHeader;
+ EFI_ACPI_DEV_SCOPE_STRUCTURE DeviceScope[1];
+} EFI_ACPI_DRHD_ENGINE1_STRUCT;
+
+typedef struct {
+ EFI_ACPI_DMAR_DRHD_HEADER DrhdHeader;
+ //
+ // @todo use PCD
+ //
+ EFI_ACPI_DEV_SCOPE_STRUCTURE DeviceScope[2];
+} EFI_ACPI_DRHD_ENGINE3_STRUCT;
+
+typedef struct {
+ EFI_ACPI_DMAR_RMRR_HEADER RmrrHeader;
+ EFI_ACPI_DEV_SCOPE_STRUCTURE DeviceScope[2];
+} EFI_ACPI_RMRR_USB_STRUC;
+
+typedef struct {
+ EFI_ACPI_DMAR_RMRR_HEADER RmrrHeader;
+ EFI_ACPI_DEV_SCOPE_STRUCTURE DeviceScope[1]; // IGD
+} EFI_ACPI_RMRR_IGD_STRUC;
+
+typedef struct {
+ EFI_ACPI_DMAR_RMRR_HEADER RmrrHeader;
+ EFI_ACPI_DEV_SCOPE_STRUCTURE DeviceScope[1]; // IGD - DiSM
+} EFI_ACPI_RMRR_IGD_DISM_STRUC;
+
+typedef struct {
+ EFI_ACPI_DMAR_ANDD_HEADER AnddHeader;
+ UINT8 AcpiObjectName[20];
+} EFI_ACPI_ANDD_STRUC;
+
+typedef struct {
+ EFI_ACPI_DMAR_HEADER DmarHeader;
+ EFI_ACPI_DRHD_ENGINE1_STRUCT DrhdEngine1;
+ EFI_ACPI_DRHD_ENGINE3_STRUCT DrhdEngine3;
+ EFI_ACPI_RMRR_IGD_STRUC RmrrIgd;
+ EFI_ACPI_RMRR_IGD_DISM_STRUC RmrrIgdDism;
+} EFI_ACPI_DMAR_TABLE;
+
+#pragma pack()
+
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Include/DxeHdaNhlt.h b/Silicon/Intel/TigerlakeSiliconPkg/Include/DxeHdaNhlt.h
new file mode 100644
index 0000000000..edb3855b68
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Include/DxeHdaNhlt.h
@@ -0,0 +1,138 @@
+/** @file
+ Header file for DxePchHdaNhltLib - NHLT structure definitions.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _DXE_HDA_NHLT_H_
+#define _DXE_HDA_NHLT_H_
+
+#include <IndustryStandard/Acpi.h>
+
+//
+// ACPI support protocol instance signature definition.
+//
+#define NHLT_ACPI_TABLE_SIGNATURE SIGNATURE_32 ('N', 'H', 'L', 'T')
+
+// MSFT defined structures
+#define SPEAKER_FRONT_LEFT 0x1
+#define SPEAKER_FRONT_RIGHT 0x2
+#define SPEAKER_FRONT_CENTER 0x4
+#define SPEAKER_BACK_LEFT 0x10
+#define SPEAKER_BACK_RIGHT 0x20
+
+#define KSAUDIO_SPEAKER_MONO (SPEAKER_FRONT_CENTER)
+#define KSAUDIO_SPEAKER_STEREO (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT)
+#define KSAUDIO_SPEAKER_QUAD (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT)
+
+#define WAVE_FORMAT_EXTENSIBLE 0xFFFE /* Microsoft */
+#define KSDATAFORMAT_SUBTYPE_PCM \
+ {0x00000001, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}}
+
+#pragma pack (push, 1)
+
+typedef struct {
+ UINT16 wFormatTag;
+ UINT16 nChannels;
+ UINT32 nSamplesPerSec;
+ UINT32 nAvgBytesPerSec;
+ UINT16 nBlockAlign;
+ UINT16 wBitsPerSample;
+ UINT16 cbSize;
+} WAVEFORMATEX;
+
+typedef struct {
+ WAVEFORMATEX Format;
+ union {
+ UINT16 wValidBitsPerSample;
+ UINT16 wSamplesPerBlock;
+ UINT16 wReserved;
+ } Samples;
+ UINT32 dwChannelMask;
+ GUID SubFormat;
+} WAVEFORMATEXTENSIBLE;
+
+//
+// List of supported link type.
+//
+enum NHLT_LINK_TYPE
+{
+ HdaNhltLinkHd = 0,
+ HdaNhltLinkDsp = 1,
+ HdaNhltLinkDmic = 2,
+ HdaNhltLinkSsp = 3,
+ HdaNhltLinkInvalid
+};
+
+//
+// List of supported device type.
+//
+enum NHLT_SSP_DEVICE_TYPE
+{
+ HdaNhltSspDeviceBt = 0,
+ HdaNhltSspDeviceI2s = 4,
+ HdaNhltSspDeviceInvalid
+};
+
+enum NHLT_PDM_DEVICE_TYPE
+{
+ HdaNhltPdmDeviceDmic = 0,
+ HdaNhltPdmDeviceInvalid
+};
+
+typedef struct {
+ UINT32 CapabilitiesSize;
+ UINT8 Capabilities[1];
+} SPECIFIC_CONFIG;
+
+typedef struct {
+ WAVEFORMATEXTENSIBLE Format;
+ SPECIFIC_CONFIG FormatConfiguration;
+} FORMAT_CONFIG;
+
+typedef struct {
+ UINT8 FormatsCount;
+ FORMAT_CONFIG FormatsConfiguration[1];
+} FORMATS_CONFIG;
+
+typedef struct {
+ UINT8 DeviceId[16];
+ UINT8 DeviceInstanceId;
+ UINT8 DevicePortId;
+} DEVICE_INFO;
+
+typedef struct {
+ UINT8 DeviceInfoCount;
+ DEVICE_INFO DeviceInformation[1];
+} DEVICES_INFO;
+
+typedef struct {
+ UINT32 EndpointDescriptorLength;
+ UINT8 LinkType;
+ UINT8 InstanceId;
+ UINT16 HwVendorId;
+ UINT16 HwDeviceId;
+ UINT16 HwRevisionId;
+ UINT32 HwSubsystemId;
+ UINT8 DeviceType;
+ UINT8 Direction;
+ UINT8 VirtualBusId;
+ SPECIFIC_CONFIG EndpointConfig;
+ FORMATS_CONFIG FormatsConfig;
+ DEVICES_INFO DevicesInformation;
+} ENDPOINT_DESCRIPTOR;
+
+//
+// High Level Table structure
+//
+typedef struct {
+ EFI_ACPI_DESCRIPTION_HEADER Header; //{'N', 'H', 'L', 'T'}
+ UINT8 EndpointCount; // Actual number of endpoints
+ ENDPOINT_DESCRIPTOR EndpointDescriptors[1];
+ SPECIFIC_CONFIG OedConfiguration;
+} NHLT_ACPI_TABLE;
+
+#pragma pack (pop)
+
+#endif // _DXE_PCH_HDA_NHLT_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Include/Hda.h b/Silicon/Intel/TigerlakeSiliconPkg/Include/Hda.h
new file mode 100644
index 0000000000..ab3f2c9cd0
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Include/Hda.h
@@ -0,0 +1,57 @@
+/** @file
+ Header file for HD Audio configuration.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _HDA_H_
+#define _HDA_H_
+
+typedef enum {
+ HdaVc0 = 0,
+ HdaVc1 = 1
+} HDAUDIO_VC_TYPE;
+
+typedef enum {
+ HdaDmicDisabled = 0,
+ HdaDmic2chArray = 1,
+ HdaDmic4chArray = 2,
+ HdaDmic1chArray = 3
+} HDAUDIO_DMIC_TYPE;
+
+typedef enum {
+ HdaLinkFreq6MHz = 0,
+ HdaLinkFreq12MHz = 1,
+ HdaLinkFreq24MHz = 2,
+ HdaLinkFreq48MHz = 3,
+ HdaLinkFreq96MHz = 4,
+ HdaLinkFreqInvalid
+} HDAUDIO_LINK_FREQUENCY;
+
+typedef enum {
+ HdaIDispMode2T = 0,
+ HdaIDispMode1T = 1,
+ HdaIDispMode4T = 2,
+ HdaIDispMode8T = 3,
+ HdaIDispMode16T = 4,
+ HdaIDispTModeInvalid
+} HDAUDIO_IDISP_TMODE;
+
+typedef enum {
+ HdaLink = 0,
+ HdaIDispLink = 1,
+ HdaDmic = 2,
+ HdaSsp = 3,
+ HdaSndw = 4,
+ HdaLinkUnsupported
+} HDAUDIO_LINK_TYPE;
+
+typedef enum {
+ HdaDmicClockSelectBoth = 0,
+ HdaDmicClockSelectClkA = 1,
+ HdaDmicClockSelectClkB = 2,
+ HdaDmicClockSelectInvalid
+} HDAUDIO_DMIC_CLOCK_SELECT;
+
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Include/MePolicyCommon.h b/Silicon/Intel/TigerlakeSiliconPkg/Include/MePolicyCommon.h
new file mode 100644
index 0000000000..023ba12daa
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Include/MePolicyCommon.h
@@ -0,0 +1,24 @@
+/** @file
+ Definition for ME common policy
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _ME_POLICY_COMMON_H_
+#define _ME_POLICY_COMMON_H_
+
+#include <ConfigBlock.h>
+
+#include <MePeiConfig.h>
+
+#ifndef PLATFORM_POR
+#define PLATFORM_POR 0
+#endif
+#ifndef FORCE_ENABLE
+#define FORCE_ENABLE 1
+#endif
+#ifndef FORCE_DISABLE
+#define FORCE_DISABLE 2
+#endif
+
+#endif // _ME_POLICY_COMMON_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Include/PcieRegs.h b/Silicon/Intel/TigerlakeSiliconPkg/Include/PcieRegs.h
new file mode 100644
index 0000000000..d98019d1b4
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Include/PcieRegs.h
@@ -0,0 +1,155 @@
+/** @file
+ Register names for PCIE standard register
+
+ Conventions:
+
+ - Prefixes:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register sizes
+ Definitions beginning with "N_" are the bit position
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PCIE_REGS_H_
+#define _PCIE_REGS_H_
+
+#include <IndustryStandard/Pci30.h>
+
+//
+// PCI type 0 Header
+//
+#define R_PCI_BCC_OFFSET 0x0B
+
+//
+// PCI type 1 Header
+//
+#define R_PCI_BRIDGE_BNUM 0x18 ///< Bus Number Register
+#define B_PCI_BRIDGE_BNUM_SBBN 0x00FF0000 ///< Subordinate Bus Number
+#define B_PCI_BRIDGE_BNUM_SCBN 0x0000FF00 ///< Secondary Bus Number
+
+//
+// PCI Express Capability List Register (CAPID:10h)
+//
+#define R_PCIE_XCAP_OFFSET 0x02 ///< PCI Express Capabilities Register (Offset 02h)
+#define B_PCIE_XCAP_DT (BIT7 | BIT6 | BIT5 | BIT4) ///< Device/Port Type
+#define N_PCIE_XCAP_DT 4
+
+#define R_PCIE_DCAP_OFFSET 0x04 ///< Device Capabilities Register (Offset 04h)
+#define B_PCIE_DCAP_RBER BIT15 ///< Role-Based Error Reporting
+#define B_PCIE_DCAP_E1AL (BIT11 | BIT10 | BIT9) ///< Endpoint L1 Acceptable Latency
+#define N_PCIE_DCAP_E1AL 9
+#define B_PCIE_DCAP_E0AL (BIT8 | BIT7 | BIT6) ///< Endpoint L0s Acceptable Latency
+#define N_PCIE_DCAP_E0AL 6
+#define B_PCIE_DCAP_MPS (BIT2 | BIT1 | BIT0) ///< Max_Payload_Size Supported
+
+#define R_PCIE_DCTL_OFFSET 0x08 ///< Device Control Register (Offset 08h)
+#define B_PCIE_DCTL_MPS (BIT7 | BIT6 | BIT5) ///< Max_Payload_Size
+#define N_PCIE_DCTL_MPS 5
+
+#define R_PCIE_LCAP_OFFSET 0x0C ///< Link Capabilities Register (Offset 0Ch)
+#define B_PCIE_LCAP_CPM BIT18 ///< Clock Power Management
+#define B_PCIE_LCAP_EL1 (BIT17 | BIT16 | BIT15) ///< L1 Exit Latency
+#define N_PCIE_LCAP_EL1 15
+#define B_PCIE_LCAP_EL0 (BIT14 | BIT13 | BIT12) ///< L0s Exit Latency
+#define N_PCIE_LCAP_EL0 12
+#define B_PCIE_LCAP_APMS_L0S BIT10
+#define B_PCIE_LCAP_APMS_L1 BIT11
+#define B_PCIE_LCAP_MLS (BIT3 | BIT2 | BIT1 | BIT0) ///< Max Link Speed
+#define V_PCIE_LCAP_MLS_GEN3 3
+#define V_PCIE_LCAP_MLS_GEN4 4
+
+#define R_PCIE_LCTL_OFFSET 0x10 ///< Link Control Register (Offset 10h)
+#define B_PCIE_LCTL_ECPM BIT8 ///< Enable Clock Power Management
+#define B_PCIE_LCTL_CCC BIT6 ///< Common Clock Configuration
+#define B_PCIE_LCTL_RL BIT5 ///< Retrain Link
+#define B_PCIE_LCTL_ASPM (BIT1 | BIT0) ///< Active State Power Management (ASPM) Control
+#define V_PCIE_LCTL_ASPM_L0S 1
+#define V_PCIE_LCTL_ASPM_L1 2
+#define V_PCIE_LCTL_ASPM_L0S_L1 3
+
+#define R_PCIE_LSTS_OFFSET 0x12 ///< Link Status Register (Offset 12h)
+#define B_PCIE_LSTS_LA BIT13 ///< Data Link Layer Link Active
+#define B_PCIE_LSTS_SCC BIT12 ///< Slot Clock Configuration
+#define B_PCIE_LSTS_LT BIT11 ///< Link Training
+#define B_PCIE_LSTS_NLW 0x03F0 ///< Negotiated Link Width
+#define N_PCIE_LSTS_NLW 4
+#define B_PCIE_LSTS_CLS 0x000F ///< Current Link Speed
+
+#define R_PCIE_SLCAP_OFFSET 0x14 ///< Slot Capabilities Register (Offset 14h)
+#define B_PCIE_SLCAP_HPC BIT6 ///< Hot-Plug Capable
+
+#define R_PCIE_SLSTS_OFFSET 0x1A ///< Slot Status Register (Offset 1Ah)
+#define B_PCIE_SLSTS_PDS BIT6 ///< Presence Detect State
+
+#define R_PCIE_DCAP2_OFFSET 0x24 ///< Device Capabilities 2 Register (Offset 24h)
+#define B_PCIE_DCAP2_LTRMS BIT11 ///< LTR Mechanism Supported
+
+#define R_PCIE_DCTL2_OFFSET 0x28 ///< Device Control 2 Register (Offset 28h)
+#define B_PCIE_DCTL2_LTREN BIT10 ///< LTR Mechanism Enable
+
+#define B_PCIE_LCTL2_TLS (BIT3 | BIT2 | BIT1 | BIT0) ///< Target Link Speed
+
+//
+// Latency Tolerance Reporting Extended Capability Registers (CAPID:0018h)
+//
+#define R_PCIE_LTRECH_CID 0x0018
+
+#define R_PCIE_LTRECH_MSLR_OFFSET 0x04
+#define N_PCIE_LTRECH_MSLR_VALUE 0
+#define N_PCIE_LTRECH_MSLR_SCALE 10
+
+#define R_PCIE_LTRECH_MNSLR_OFFSET 0x06
+#define N_PCIE_LTRECH_MNSLR_VALUE 0
+#define N_PCIE_LTRECH_MNSLR_SCALE 10
+
+//
+// Secondary PCI Express Extended Capability Header (CAPID:0019h)
+//
+#define R_PCIE_EX_LCTL3_OFFSET 0x04 ///< Link Control 3 Register
+#define B_PCIE_EX_LCTL3_PE BIT0 ///< Perform Equalization
+
+//
+// L1 Sub-States Extended Capability Register (CAPID:001Eh)
+//
+#define V_PCIE_EX_L1S_CID 0x001E ///< Capability ID
+#define R_PCIE_EX_L1SCAP_OFFSET 0x04 ///< L1 Sub-States Capabilities
+#define B_PCIE_EX_L1SCAP_PTV 0x00F80000 //< Port Tpower_on value
+#define N_PCIE_EX_L1SCAP_PTV 19
+#define B_PCIE_EX_L1SCAP_PTPOS 0x00030000 //< Port Tpower_on scale
+#define N_PCIE_EX_L1SCAP_PTPOS 16
+#define B_PCIE_EX_L1SCAP_CMRT 0x0000FF00 //< Common Mode Restore time
+#define N_PCIE_EX_L1SCAP_CMRT 8
+#define B_PCIE_EX_L1SCAP_L1PSS BIT4 ///< L1 PM substates supported
+#define B_PCIE_EX_L1SCAP_AL1SS BIT3 ///< ASPM L1.1 supported
+#define B_PCIE_EX_L1SCAP_AL12S BIT2 ///< ASPM L1.2 supported
+#define B_PCIE_EX_L1SCAP_PPL11S BIT1 ///< PCI-PM L1.1 supported
+#define B_PCIE_EX_L1SCAP_PPL12S BIT0 ///< PCI-PM L1.2 supported
+#define R_PCIE_EX_L1SCTL1_OFFSET 0x08 ///< L1 Sub-States Control 1
+#define B_PCIE_EX_L1SCTL1_L1SSEIE BIT4
+#define N_PCIE_EX_L1SCTL1_L12LTRTLSV 29
+#define N_PCIE_EX_L1SCTL1_L12LTRTLV 16
+#define R_PCIE_EX_L1SCTL2_OFFSET 0x0C ///< L1 Sub-States Control 2
+#define N_PCIE_EX_L1SCTL2_POWT 3
+
+//
+// PTM Extended Capability Register (CAPID:001Fh)
+//
+#define V_PCIE_EX_PTM_CID 0x001F ///< Capability ID
+#define R_PCIE_EX_PTMCAP_OFFSET 0x04 ///< PTM Capabilities
+#define R_PCIE_EX_PTMCTL_OFFSET 0x08 ///< PTM Control Register
+
+//
+// Base Address Offset
+//
+#define B_PCI_BAR_MEMORY_TYPE_MASK (BIT1 | BIT2)
+#define B_PCI_BAR_MEMORY_TYPE_64 BIT2
+
+//
+// PCI Express Extended Capability Header
+//
+#define R_PCIE_CFG_EXCAP_OFFSET 0x100
+
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Include/Pins/GpioPinsVer2Lp.h b/Silicon/Intel/TigerlakeSiliconPkg/Include/Pins/GpioPinsVer2Lp.h
new file mode 100644
index 0000000000..ef94790985
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Include/Pins/GpioPinsVer2Lp.h
@@ -0,0 +1,110 @@
+/** @file
+ GPIO pins for TGL-PCH-LP,
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _GPIO_PINS_VER2_LP_H_
+#define _GPIO_PINS_VER2_LP_H_
+///
+/// This header file should be used together with
+/// PCH GPIO lib in C and ASL. All defines used
+/// must match both ASL/C syntax
+///
+
+///
+/// Unique ID used in GpioPad defines
+///
+#define GPIO_VER2_LP_CHIPSET_ID 0x9
+
+///
+/// TGL LP GPIO Groups
+/// Use below for functions from PCH GPIO Lib which
+/// require GpioGroup as argument
+///
+#define GPIO_VER2_LP_GROUP_GPP_B 0x0900
+#define GPIO_VER2_LP_GROUP_GPP_A 0x0902
+#define GPIO_VER2_LP_GROUP_GPP_R 0x0903
+#define GPIO_VER2_LP_GROUP_GPD 0x0905
+#define GPIO_VER2_LP_GROUP_GPP_S 0x0906
+#define GPIO_VER2_LP_GROUP_GPP_H 0x0907
+#define GPIO_VER2_LP_GROUP_GPP_D 0x0908
+#define GPIO_VER2_LP_GROUP_GPP_C 0x090B
+#define GPIO_VER2_LP_GROUP_GPP_F 0x090C
+#define GPIO_VER2_LP_GROUP_GPP_E 0x090E
+
+
+///
+/// TGL LP GPIO pins
+/// Use below for functions from PCH GPIO Lib which
+/// require GpioPad as argument. Encoding used here
+/// has all information required by library functions
+///
+#define GPIO_VER2_LP_GPP_B2 0x09000002
+#define GPIO_VER2_LP_GPP_B4 0x09000004
+#define GPIO_VER2_LP_GPP_B14 0x0900000E
+#define GPIO_VER2_LP_GPP_B15 0x0900000F
+#define GPIO_VER2_LP_GPP_B16 0x09000010
+#define GPIO_VER2_LP_GPP_B18 0x09000012
+#define GPIO_VER2_LP_GPP_B23 0x09000017
+#define GPIO_VER2_LP_GSPI0_CLK_LOOPBK 0x09000018
+
+#define GPIO_VER2_LP_GPP_A10 0x0902000A
+#define GPIO_VER2_LP_GPP_A11 0x0902000B
+#define GPIO_VER2_LP_GPP_A13 0x0902000D
+#define GPIO_VER2_LP_GPP_A14 0x0902000E
+#define GPIO_VER2_LP_GPP_A23 0x09020017
+#define GPIO_VER2_LP_ESPI_CLK_LOOPBK 0x09020018
+
+#define GPIO_VER2_LP_GPP_R5 0x09030005
+#define GPIO_VER2_LP_GPP_R6 0x09030006
+
+#define GPIO_VER2_LP_GPD7 0x09050007
+
+#define GPIO_VER2_LP_INPUT3VSEL 0x0905000C
+
+#define GPIO_VER2_LP_GPP_H0 0x09070000
+#define GPIO_VER2_LP_GPP_H1 0x09070001
+#define GPIO_VER2_LP_GPP_H12 0x0907000C
+#define GPIO_VER2_LP_GPP_H13 0x0907000D
+#define GPIO_VER2_LP_GPP_H15 0x0907000F
+#define GPIO_VER2_LP_GPP_H19 0x09070013
+
+#define GPIO_VER2_LP_GPP_D16 0x09080010
+#define GPIO_VER2_LP_GSPI2_CLK_LOOPBK 0x09080014
+
+#define GPIO_VER2_LP_GPP_C2 0x090B0002
+#define GPIO_VER2_LP_GPP_C5 0x090B0005
+#define GPIO_VER2_LP_GPP_C8 0x090B0008
+#define GPIO_VER2_LP_GPP_C12 0x090B000C
+#define GPIO_VER2_LP_GPP_C13 0x090B000D
+#define GPIO_VER2_LP_GPP_C14 0x090B000E
+#define GPIO_VER2_LP_GPP_C15 0x090B000F
+#define GPIO_VER2_LP_GPP_C22 0x090B0016
+#define GPIO_VER2_LP_GPP_C23 0x090B0017
+
+#define GPIO_VER2_LP_GPP_F4 0x090C0004
+#define GPIO_VER2_LP_GPP_F5 0x090C0005
+#define GPIO_VER2_LP_GPP_F9 0x090C0009
+#define GPIO_VER2_LP_GPP_F10 0x090C000A
+#define GPIO_VER2_LP_GPP_F20 0x090C0014
+#define GPIO_VER2_LP_GPP_F21 0x090C0015
+#define GPIO_VER2_LP_GPPF_CLK_LOOPBK 0x090C0018
+
+#define GPIO_VER2_LP_GPP_E3 0x090E0003
+#define GPIO_VER2_LP_GPP_E7 0x090E0007
+#define GPIO_VER2_LP_GPP_E8 0x090E0008
+#define GPIO_VER2_LP_GPP_E22 0x090E0016
+#define GPIO_VER2_LP_GPP_E23 0x090E0017
+#define GPIO_VER2_LP_GPPE_CLK_LOOPBK 0x090E0018
+
+//
+// GPIO Pin Muxing
+// Determines a selection of physical pad for a given signal.
+// Please refer to GPIO_NATIVE_PAD type.
+// If certain signal is not listed below it means that it can be enabled
+// only on a single pad and muxing setting is not needed.
+//
+#define GPIO_VER2_LP_MUXING_SERIALIO_I2C4_SDA_GPP_H8 0x1947CC08
+#define GPIO_VER2_LP_MUXING_SERIALIO_I2C4_SCL_GPP_H9 0x1947AC09
+#endif // _GPIO_PINS_VER2_LP_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Include/Register/FlashRegs.h b/Silicon/Intel/TigerlakeSiliconPkg/Include/Register/FlashRegs.h
new file mode 100644
index 0000000000..215fd0407e
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Include/Register/FlashRegs.h
@@ -0,0 +1,72 @@
+/** @file
+ Register names for Flash registers
+
+ Conventions:
+
+ - Register definition format:
+ Prefix_[GenerationName]_[ComponentName]_SubsystemName_RegisterSpace_RegisterName
+ - Prefix:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register size
+ Definitions beginning with "N_" are the bit position
+ - [GenerationName]:
+ Three letter acronym of the generation is used (e.g. SKL,KBL,CNL etc.).
+ Register name without GenerationName applies to all generations.
+ - [ComponentName]:
+ This field indicates the component name that the register belongs to (e.g. PCH, SA etc.)
+ Register name without ComponentName applies to all components.
+ Register that is specific to -LP denoted by "_PCH_LP_" in component name.
+ - SubsystemName:
+ This field indicates the subsystem name of the component that the register belongs to
+ (e.g. PCIE, USB, SATA, GPIO, PMC etc.).
+ - RegisterSpace:
+ MEM - MMIO space register of subsystem.
+ IO - IO space register of subsystem.
+ PCR - Private configuration register of subsystem.
+ CFG - PCI configuration space register of subsystem.
+ - RegisterName:
+ Full register name.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _FLASH_REGS_H_
+#define _FLASH_REGS_H_
+
+//
+// Flash Descriptor Base Address Region (FDBAR) from Flash Region 0
+//
+#define R_FLASH_FDBAR_FLASH_MAP0 0x04
+#define B_FLASH_FDBAR_NC 0x00000300 ///< Number Of Components
+#define N_FLASH_FDBAR_NC 8 ///< Number Of Components
+#define R_FLASH_FDBAR_FLASH_MAP1 0x08
+#define B_FLASH_FDBAR_FPSBA 0x00FF0000 ///< PCH Strap Base Address, [23:16] represents [11:4]
+#define N_FLASH_FDBAR_FPSBA 16 ///< PCH Strap base Address bit position
+#define N_FLASH_FDBAR_FPSBA_REPR 4 ///< PCH Strap base Address bit represents position
+#define B_FLASH_FDBAR_PCHSL 0xFF000000 ///< PCH Strap Length, [31:24] represents number of Dwords
+#define N_FLASH_FDBAR_PCHSL 24 ///< PCH Strap Length bit position
+#define R_FLASH_FDBAR_FLASH_MAP2 0x0C
+#define B_FLASH_FDBAR_FCPUSBA 0x00000FFC ///< CPU Strap Base Address [11:2]
+#define N_FLASH_FDBAR_FCPUSBA 2 ///< CPU Strap Base Address bit position
+#define B_FLASH_FDBAR_CPUSL 0x00FF0000 ///< CPU Strap Length, [23:16] represents number of Dwords
+#define N_FLASH_FDBAR_CPUSL 16 ///< CPU Strap Length bit position
+
+//
+// Flash Component Base Address (FCBA) from Flash Region 0
+//
+#define R_FLASH_FCBA_FLCOMP 0x00 ///< Flash Components Register
+#define B_FLASH_FLCOMP_COMP1_MASK 0xF0 ///< Flash Component 1 Size MASK
+#define N_FLASH_FLCOMP_COMP1 4 ///< Flash Component 1 Size bit position
+#define B_FLASH_FLCOMP_COMP0_MASK 0x0F ///< Flash Component 0 Size MASK
+#define V_FLASH_FLCOMP_COMP_512KB 0x80000
+//
+// Descriptor Upper Map Section from Flash Region 0
+//
+#define R_FLASH_UMAP1 0xEFC ///< Flash Upper Map 1
+#define B_FLASH_UMAP1_MDTBA 0xFF000000 ///< MIP Descriptor Table Base Address
+#define N_FLASH_UMAP1_MDTBA 24 ///< MDTBA bits position
+#define N_FLASH_UMAP1_MDTBA_REPR 4 ///< MDTBA address representation position
+
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Include/Register/GpioRegs.h b/Silicon/Intel/TigerlakeSiliconPkg/Include/Register/GpioRegs.h
new file mode 100644
index 0000000000..e4bf2018b7
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Include/Register/GpioRegs.h
@@ -0,0 +1,121 @@
+/** @file
+ Register names for PCH GPIO
+
+Conventions:
+
+ - Register definition format:
+ Prefix_[GenerationName]_[ComponentName]_SubsystemName_RegisterSpace_RegisterName
+ - Prefix:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register size
+ Definitions beginning with "N_" are the bit position
+ - [GenerationName]:
+ Three letter acronym of the generation is used (e.g. SKL,KBL,CNL etc.).
+ Register name without GenerationName applies to all generations.
+ - [ComponentName]:
+ This field indicates the component name that the register belongs to (e.g. PCH, SA etc.)
+ Register name without ComponentName applies to all components.
+ Register that is specific to -LP denoted by "_PCH_LP_" in component name.
+ - SubsystemName:
+ This field indicates the subsystem name of the component that the register belongs to
+ (e.g. PCIE, USB, SATA, GPIO, PMC etc.).
+ - RegisterSpace:
+ MEM - MMIO space register of subsystem.
+ IO - IO space register of subsystem.
+ PCR - Private configuration register of subsystem.
+ CFG - PCI configuration space register of subsystem.
+ - RegisterName:
+ Full register name.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _GPIO_REGS_H_
+#define _GPIO_REGS_H_
+
+//
+// PADCFG register is split into multiple DW registers
+// S_GPIO_PCR_PADCFG refers to number of bytes used by all those registers for one pad
+//
+#define S_GPIO_PCR_PADCFG 0x10
+
+//
+// Pad Configuration Register DW0
+//
+
+//Pad Reset Config
+#define B_GPIO_PCR_RST_CONF (BIT31 | BIT30)
+#define N_GPIO_PCR_RST_CONF 30
+#define V_GPIO_PCR_RST_CONF_POW_GOOD 0x00
+#define V_GPIO_PCR_RST_CONF_DEEP_RST 0x01
+#define V_GPIO_PCR_RST_CONF_GPIO_RST 0x02
+#define V_GPIO_PCR_RST_CONF_RESUME_RST 0x03 // Only for GPD Group
+
+//RX Raw Override to 1
+#define B_GPIO_PCR_RX_RAW1 BIT28
+#define N_GPIO_PCR_RX_RAW1 28
+
+//RX Level/Edge Configuration
+#define B_GPIO_PCR_RX_LVL_EDG (BIT26 | BIT25)
+#define N_GPIO_PCR_RX_LVL_EDG 25
+
+//RX Invert
+#define B_GPIO_PCR_RXINV BIT23
+#define N_GPIO_PCR_RXINV 23
+
+//GPIO Input Route IOxAPIC
+#define B_GPIO_PCR_RX_APIC_ROUTE BIT20
+
+//GPIO Input Route SCI
+#define B_GPIO_PCR_RX_SCI_ROUTE BIT19
+
+//GPIO Input Route SMI
+#define B_GPIO_PCR_RX_SMI_ROUTE BIT18
+
+//GPIO Input Route NMI
+#define B_GPIO_PCR_RX_NMI_ROUTE BIT17
+#define N_GPIO_PCR_RX_NMI_ROUTE 17
+
+//GPIO Pad Mode
+#define B_GPIO_PCR_PAD_MODE (BIT12 | BIT11 | BIT10)
+#define N_GPIO_PCR_PAD_MODE 10
+
+//GPIO RX Disable
+#define B_GPIO_PCR_RXDIS BIT9
+
+//GPIO TX Disable
+#define B_GPIO_PCR_TXDIS BIT8
+#define N_GPIO_PCR_TXDIS 8
+
+//GPIO RX State
+#define B_GPIO_PCR_RX_STATE BIT1
+#define N_GPIO_PCR_RX_STATE 1
+
+//GPIO TX State
+#define B_GPIO_PCR_TX_STATE BIT0
+#define N_GPIO_PCR_TX_STATE 0
+
+//Termination
+#define B_GPIO_PCR_TERM (BIT13 | BIT12 | BIT11 | BIT10)
+#define N_GPIO_PCR_TERM 10
+
+//Interrupt number
+#define B_GPIO_PCR_INTSEL 0x7F
+#define N_GPIO_PCR_INTSEL 0
+
+///
+/// GPIO SMI data used for EFI_SMM_GPI_DISPATCH2_PROTOCOL
+/// Below defines are to be used internally by PCH SMI dispatcher only
+///
+#define PCH_GPIO_NUM_SUPPORTED_GPIS 512
+#define S_GPIO_PCR_GP_SMI_STS 4
+
+///
+/// Groups mapped to 2-tier General Purpose Event will all be under
+/// one master GPE_111 (0x6F)
+///
+#define PCH_GPIO_2_TIER_MASTER_GPE_NUMBER 0x6F
+
+#endif // _GPIO_REGS_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Include/Register/GpioRegsVer2.h b/Silicon/Intel/TigerlakeSiliconPkg/Include/Register/GpioRegsVer2.h
new file mode 100644
index 0000000000..1dc05869dd
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Include/Register/GpioRegsVer2.h
@@ -0,0 +1,226 @@
+/** @file
+ Register names for VER2 GPIO
+
+Conventions:
+
+ - Register definition format:
+ Prefix_[GenerationName]_[ComponentName]_SubsystemName_RegisterSpace_RegisterName
+ - Prefix:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register size
+ Definitions beginning with "N_" are the bit position
+ - [GenerationName]:
+ Three letter acronym of the generation is used (e.g. SKL,KBL,CNL etc.).
+ Register name without GenerationName applies to all generations.
+ - [ComponentName]:
+ This field indicates the component name that the register belongs to (e.g. PCH, SA etc.)
+ Register name without ComponentName applies to all components.
+ Register that is specific to -LP denoted by "_PCH_LP_" in component name.
+ - SubsystemName:
+ This field indicates the subsystem name of the component that the register belongs to
+ (e.g. PCIE, USB, SATA, GPIO, PMC etc.).
+ - RegisterSpace:
+ MEM - MMIO space register of subsystem.
+ IO - IO space register of subsystem.
+ PCR - Private configuration register of subsystem.
+ CFG - PCI configuration space register of subsystem.
+ - RegisterName:
+ Full register name.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _GPIO_REGS_VER2_H_
+#define _GPIO_REGS_VER2_H_
+
+//
+// PCH-LP GPIO
+//
+#define GPIO_VER2_PCH_LP_GPIO_GPP_B_PAD_MAX 26
+#define GPIO_VER2_PCH_LP_GPIO_GPP_A_PAD_MAX 25
+#define GPIO_VER2_PCH_LP_GPIO_GPP_R_PAD_MAX 8
+#define GPIO_VER2_PCH_LP_GPIO_GPD_PAD_MAX 17
+#define GPIO_VER2_PCH_LP_GPIO_GPP_S_PAD_MAX 8
+#define GPIO_VER2_PCH_LP_GPIO_GPP_H_PAD_MAX 24
+#define GPIO_VER2_PCH_LP_GPIO_GPP_D_PAD_MAX 21
+#define GPIO_VER2_PCH_LP_GPIO_GPP_F_PAD_MAX 25
+#define GPIO_VER2_PCH_LP_GPIO_GPP_C_PAD_MAX 24
+#define GPIO_VER2_PCH_LP_GPIO_GPP_E_PAD_MAX 25
+#define GPIO_VER2_PCH_LP_GPIO_CPU_PAD_MAX 15
+
+//
+// PCH-LP GPIO registers
+//
+
+//
+// GPIO Community 0 Private Configuration Registers
+//
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_B_PAD_OWN 0x20
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_A_PAD_OWN 0x38
+
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_B_PADCFGLOCK 0x80
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_B_PADCFGLOCKTX 0x84
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_A_PADCFGLOCK 0x90
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_A_PADCFGLOCKTX 0x94
+
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_B_HOSTSW_OWN 0xB0
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_A_HOSTSW_OWN 0xB8
+
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_B_GPI_IS 0x0100
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_A_GPI_IS 0x0108
+
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_B_GPI_IE 0x0120
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_A_GPI_IE 0x0128
+
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_B_GPI_GPE_STS 0x0140
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_A_GPI_GPE_STS 0x0148
+
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_B_GPI_GPE_EN 0x0160
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_A_GPI_GPE_EN 0x0168
+
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_B_SMI_STS 0x0180
+
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_B_SMI_EN 0x01A0
+
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_B_NMI_STS 0x01C0
+
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_B_NMI_EN 0x01E0
+
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_B_PADCFG_OFFSET 0x700
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_A_PADCFG_OFFSET 0x9A0
+
+//
+// GPIO Community 1 Private Configuration Registers
+//
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_S_PAD_OWN 0x20
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_H_PAD_OWN 0x24
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_D_PAD_OWN 0x30
+
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_S_PADCFGLOCK 0x80
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_S_PADCFGLOCKTX 0x84
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_H_PADCFGLOCK 0x88
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_H_PADCFGLOCKTX 0x8C
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_D_PADCFGLOCK 0x90
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_D_PADCFGLOCKTX 0x94
+
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_S_HOSTSW_OWN 0xB0
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_H_HOSTSW_OWN 0xB4
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_D_HOSTSW_OWN 0xB8
+
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_S_GPI_IS 0x0100
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_H_GPI_IS 0x0104
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_D_GPI_IS 0x0108
+
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_S_GPI_IE 0x0120
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_H_GPI_IE 0x0124
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_D_GPI_IE 0x0128
+
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_S_GPI_GPE_STS 0x0140
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_H_GPI_GPE_STS 0x0144
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_D_GPI_GPE_STS 0x0148
+
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_S_GPI_GPE_EN 0x0160
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_H_GPI_GPE_EN 0x0164
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_D_GPI_GPE_EN 0x0168
+
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_D_SMI_STS 0x0188
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_D_SMI_EN 0x01A8
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_D_NMI_STS 0x01C8
+
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_D_NMI_EN 0x01E8
+
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_S_PADCFG_OFFSET 0x700
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_H_PADCFG_OFFSET 0x780
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_D_PADCFG_OFFSET 0x900
+
+//
+// GPIO Community 2 Private Configuration Registers
+//
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPD_PAD_OWN 0x20
+
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPD_PADCFGLOCK 0x80
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPD_PADCFGLOCKTX 0x84
+
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPD_HOSTSW_OWN 0xB0
+
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPD_GPI_IS 0x0100
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPD_GPI_IE 0x0120
+
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPD_GPI_GPE_STS 0x0140
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPD_GPI_GPE_EN 0x0160
+
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPD_PADCFG_OFFSET 0x700
+
+//
+// GPIO Community 4 Private Configuration Registers
+//
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_C_PAD_OWN 0x20
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_F_PAD_OWN 0x2C
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_E_PAD_OWN 0x40
+
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_C_PADCFGLOCK 0x80
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_C_PADCFGLOCKTX 0x84
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_F_PADCFGLOCK 0x88
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_F_PADCFGLOCKTX 0x8C
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_E_PADCFGLOCK 0x98
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_E_PADCFGLOCKTX 0x9C
+
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_C_HOSTSW_OWN 0xB0
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_F_HOSTSW_OWN 0xB4
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_E_HOSTSW_OWN 0xBC
+
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_C_GPI_IS 0x0100
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_F_GPI_IS 0x0104
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_E_GPI_IS 0x010C
+
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_C_GPI_IE 0x0120
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_F_GPI_IE 0x0124
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_E_GPI_IE 0x012C
+
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_C_GPI_GPE_STS 0x0140
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_F_GPI_GPE_STS 0x0144
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_E_GPI_GPE_STS 0x014C
+
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_C_GPI_GPE_EN 0x0160
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_F_GPI_GPE_EN 0x0164
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_E_GPI_GPE_EN 0x016C
+
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_C_SMI_STS 0x0180
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_E_SMI_STS 0x018C
+
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_C_SMI_EN 0x01A0
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_E_SMI_EN 0x01AC
+
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_C_NMI_STS 0x01C0
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_E_NMI_STS 0x01CC
+
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_C_NMI_EN 0x01E0
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_E_NMI_EN 0x01EC
+
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_C_PADCFG_OFFSET 0x700
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_F_PADCFG_OFFSET 0x880
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_E_PADCFG_OFFSET 0xA70
+
+//
+// GPIO Community 5 Private Configuration Registers
+//
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_R_PAD_OWN 0x20
+
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_R_PADCFGLOCK 0x80
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_R_PADCFGLOCKTX 0x84
+
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_R_HOSTSW_OWN 0xB0
+
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_R_GPI_IS 0x0100
+
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_R_GPI_IE 0x0120
+
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_R_GPI_GPE_STS 0x0140
+
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_R_GPI_GPE_EN 0x0160
+
+#define R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_R_PADCFG_OFFSET 0x700
+
+#endif // _GPIO_REGS_VER2_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Include/Register/PchDmi14Regs.h b/Silicon/Intel/TigerlakeSiliconPkg/Include/Register/PchDmi14Regs.h
new file mode 100644
index 0000000000..5447fabccf
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Include/Register/PchDmi14Regs.h
@@ -0,0 +1,16 @@
+/** @file
+ Register names for PCH DMI SIP14
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PCH_DMI14_REGS_H_
+#define _PCH_DMI14_REGS_H_
+
+//
+// DMI Control
+//
+#define R_PCH_DMI14_PCR_DMIC 0x2234 ///< DMI Control
+#define B_PCH_DMI14_PCR_DMIC_SRL BIT31 ///< Secured register lock
+
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Include/Register/PchDmiRegs.h b/Silicon/Intel/TigerlakeSiliconPkg/Include/Register/PchDmiRegs.h
new file mode 100644
index 0000000000..e9e6f80327
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Include/Register/PchDmiRegs.h
@@ -0,0 +1,36 @@
+/** @file
+ Register names for PCH DMI and OP-DMI
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PCH_DMI_REGS_H_
+#define _PCH_DMI_REGS_H_
+
+//
+// PCH DMI Chipset Configuration Registers (PID:DMI)
+//
+
+//
+// PCH DMI Source Decode PCRs (Common)
+//
+#define R_PCH_DMI_PCR_LPCLGIR1 0x2730 ///< LPC Generic I/O Range 1
+#define R_PCH_DMI_PCR_LPCGMR 0x2740 ///< LPC Generic Memory Range
+#define R_PCH_DMI_PCR_SEGIR 0x27BC ///< Second ESPI Generic I/O Range
+#define R_PCH_DMI_PCR_SEGMR 0x27C0 ///< Second ESPI Generic Memory Range
+#define R_PCH_DMI_PCR_LPCBDE 0x2744 ///< LPC BIOS Decode Enable
+#define R_PCH_DMI_PCR_UCPR 0x2748 ///< uCode Patch Region
+#define B_PCH_DMI_PCR_UCPR_UPRE BIT0 ///< uCode Patch Region Enable
+#define R_PCH_DMI_PCR_GCS 0x274C ///< Generic Control and Status
+#define B_PCH_DMI_PCR_BBS BIT10 ///< Boot BIOS Strap
+#define B_PCH_DMI_PCR_RPR BIT11 ///< Reserved Page Route
+#define B_PCH_DMI_PCR_BILD BIT0 ///< BIOS Interface Lock-Down
+#define R_PCH_DMI_PCR_IOT1 0x2750 ///< I/O Trap Register 1
+#define R_PCH_DMI_PCR_LPCIOD 0x2770 ///< LPC I/O Decode Ranges
+#define R_PCH_DMI_PCR_LPCIOE 0x2774 ///< LPC I/O Enables
+#define R_PCH_DMI_PCR_TCOBASE 0x2778 ///< TCO Base Address
+#define B_PCH_DMI_PCR_TCOBASE_TCOBA 0xFFE0 ///< TCO Base Address Mask
+#define R_PCH_DMI_PCR_GPMR1 0x277C ///< General Purpose Memory Range 1
+#define R_PCH_DMI_PCR_GPMR1DID 0x2780 ///< General Purpose Memory Range 1 Destination ID
+
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Include/Register/PchPcieRpRegs.h b/Silicon/Intel/TigerlakeSiliconPkg/Include/Register/PchPcieRpRegs.h
new file mode 100644
index 0000000000..c3497b1013
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Include/Register/PchPcieRpRegs.h
@@ -0,0 +1,93 @@
+/** @file
+ Register names for PCH PCI-E root port devices
+
+ Conventions:
+
+ - Register definition format:
+ Prefix_[GenerationName]_[ComponentName]_SubsystemName_RegisterSpace_RegisterName
+ - Prefix:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register size
+ Definitions beginning with "N_" are the bit position
+ - [GenerationName]:
+ Three letter acronym of the generation is used (e.g. SKL,KBL,CNL etc.).
+ Register name without GenerationName applies to all generations.
+ - [ComponentName]:
+ This field indicates the component name that the register belongs to (e.g. PCH, SA etc.)
+ Register name without ComponentName applies to all components.
+ Register that is specific to -LP denoted by "_PCH_LP_" in component name.
+ - SubsystemName:
+ This field indicates the subsystem name of the component that the register belongs to
+ (e.g. PCIE, USB, SATA, GPIO, PMC etc.).
+ - RegisterSpace:
+ MEM - MMIO space register of subsystem.
+ IO - IO space register of subsystem.
+ PCR - Private configuration register of subsystem.
+ CFG - PCI configuration space register of subsystem.
+ - RegisterName:
+ Full register name.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PCH_REGS_PCIE_H_
+#define _PCH_REGS_PCIE_H_
+
+#define R_PCH_PCIE_CFG_CLIST 0x40
+#define R_PCH_PCIE_CFG_LCAP (R_PCH_PCIE_CFG_CLIST + R_PCIE_LCAP_OFFSET)
+#define N_PCH_PCIE_CFG_LCAP_PN 24
+#define R_PCH_PCIE_CFG_LCTL (R_PCH_PCIE_CFG_CLIST + R_PCIE_LCTL_OFFSET)
+#define R_PCH_PCIE_CFG_LSTS (R_PCH_PCIE_CFG_CLIST + R_PCIE_LSTS_OFFSET)
+#define R_PCH_PCIE_CFG_SLCAP (R_PCH_PCIE_CFG_CLIST + R_PCIE_SLCAP_OFFSET)
+#define R_PCH_PCIE_CFG_SLSTS (R_PCH_PCIE_CFG_CLIST + R_PCIE_SLSTS_OFFSET)
+
+#define R_PCH_PCIE_CFG_MPC2 0xD4
+#define B_PCH_PCIE_CFG_MPC2_EOIFD BIT1
+
+#define R_PCH_PCIE_CFG_MPC 0xD8
+#define S_PCH_PCIE_CFG_MPC 4
+#define B_PCH_PCIE_CFG_MPC_PMCE BIT31
+#define B_PCH_PCIE_CFG_MPC_HPME BIT1
+#define N_PCH_PCIE_CFG_MPC_HPME 1
+
+#define R_PCH_PCIE_CFG_SMSCS 0xDC
+#define S_PCH_PCIE_CFG_SMSCS 4
+#define B_PCH_PCIE_CFG_SMSCS_PMCS BIT31
+#define N_PCH_PCIE_CFG_SMSCS_LERSMIS 5
+#define N_PCH_PCIE_CFG_SMSCS_HPLAS 4
+#define N_PCH_PCIE_CFG_SMSCS_HPPDM 1
+
+//CES.RE, CES.BT, CES.BD
+
+#define R_PCH_PCIE_CFG_EX_SPEECH 0xA30 ///< Secondary PCI Express Extended Capability Header
+#define R_PCH_PCIE_CFG_EX_LCTL3 (R_PCH_PCIE_CFG_EX_SPEECH + R_PCIE_EX_LCTL3_OFFSET)
+
+#define R_PCH_PCIE_CFG_LTROVR 0x400
+#define B_PCH_PCIE_CFG_LTROVR_LTRNSROVR BIT31 ///< LTR Non-Snoop Requirement Bit Override
+#define B_PCH_PCIE_CFG_LTROVR_LTRSROVR BIT15 ///< LTR Snoop Requirement Bit Override
+
+#define R_PCH_PCIE_CFG_LTROVR2 0x404
+#define B_PCH_PCIE_CFG_LTROVR2_FORCE_OVERRIDE BIT3 ///< LTR Force Override Enable
+#define B_PCH_PCIE_CFG_LTROVR2_LOCK BIT2 ///< LTR Override Lock
+#define B_PCH_PCIE_CFG_LTROVR2_LTRNSOVREN BIT1 ///< LTR Non-Snoop Override Enable
+#define B_PCH_PCIE_CFG_LTROVR2_LTRSOVREN BIT0 ///< LTR Snoop Override Enable
+
+#define R_PCH_PCIE_CFG_PCIEPMECTL 0x420
+#define B_PCH_PCIE_CFG_PCIEPMECTL_DLSULPPGE BIT30
+#define B_PCH_PCIE_CFG_PCIEPMECTL_L1LE BIT17
+#define B_PCH_PCIE_CFG_PCIEPMECTL_L1FSOE BIT0
+
+#define R_PCH_PCIE_CFG_EQCFG1 0x450
+#define S_PCH_PCIE_CFG_EQCFG1 4
+#define N_PCH_PCIE_CFG_EQCFG1_LERSMIE 21
+
+//
+// PCIE PCRs (PID:SPA SPB SPC SPD SPE SPF)
+//
+#define R_SPX_PCR_PCD 0 ///< Port configuration and disable
+#define B_SPX_PCR_PCD_RP1FN (BIT2 | BIT1 | BIT0) ///< Port 1 Function Number
+#define S_SPX_PCR_PCD_RP_FIELD 4 ///< 4 bits for each RP FN
+
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Include/Register/PmcRegs.h b/Silicon/Intel/TigerlakeSiliconPkg/Include/Register/PmcRegs.h
new file mode 100644
index 0000000000..fac1497773
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Include/Register/PmcRegs.h
@@ -0,0 +1,258 @@
+/** @file
+ Register names for PCH PMC device
+
+ Conventions:
+
+ - Register definition format:
+ Prefix_[GenerationName]_[ComponentName]_SubsystemName_RegisterSpace_RegisterName
+ - Prefix:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register size
+ Definitions beginning with "N_" are the bit position
+ - [GenerationName]:
+ Three letter acronym of the generation is used (e.g. SKL,KBL,CNL etc.).
+ Register name without GenerationName applies to all generations.
+ - [ComponentName]:
+ This field indicates the component name that the register belongs to (e.g. PCH, SA etc.)
+ Register name without ComponentName applies to all components.
+ Register that is specific to -LP denoted by "_PCH_LP_" in component name.
+ - SubsystemName:
+ This field indicates the subsystem name of the component that the register belongs to
+ (e.g. PCIE, USB, SATA, GPIO, PMC etc.).
+ - RegisterSpace:
+ MEM - MMIO space register of subsystem.
+ IO - IO space register of subsystem.
+ PCR - Private configuration register of subsystem.
+ CFG - PCI configuration space register of subsystem.
+ - RegisterName:
+ Full register name.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PCH_REGS_PMC_H_
+#define _PCH_REGS_PMC_H_
+
+//
+// ACPI and legacy I/O register offsets from ACPIBASE
+//
+#define R_ACPI_IO_PM1_STS 0x00
+#define S_ACPI_IO_PM1_STS 2
+#define B_ACPI_IO_PM1_STS_WAK BIT15
+#define B_ACPI_IO_PM1_STS_PCIEXP_WAKE_STS BIT14
+#define B_ACPI_IO_PM1_STS_PRBTNOR BIT11
+#define B_ACPI_IO_PM1_STS_RTC BIT10
+#define B_ACPI_IO_PM1_STS_PWRBTN BIT8
+#define B_ACPI_IO_PM1_STS_GBL BIT5
+#define B_ACPI_IO_PM1_STS_TMROF BIT0
+#define N_ACPI_IO_PM1_STS_RTC 10
+#define N_ACPI_IO_PM1_STS_PWRBTN 8
+#define N_ACPI_IO_PM1_STS_TMROF 0
+
+#define R_ACPI_IO_PM1_EN 0x02
+#define S_ACPI_IO_PM1_EN 2
+#define B_ACPI_IO_PM1_EN_PWRBTN BIT8
+#define N_ACPI_IO_PM1_EN_RTC 10
+#define N_ACPI_IO_PM1_EN_PWRBTN 8
+#define N_ACPI_IO_PM1_EN_TMROF 0
+
+#define R_ACPI_IO_PM1_CNT 0x04
+#define B_ACPI_IO_PM1_CNT_SLP_EN BIT13
+#define B_ACPI_IO_PM1_CNT_SLP_TYP (BIT12 | BIT11 | BIT10)
+#define V_ACPI_IO_PM1_CNT_S0 0
+#define V_ACPI_IO_PM1_CNT_S1 BIT10
+#define V_ACPI_IO_PM1_CNT_S3 (BIT12 | BIT10)
+#define V_ACPI_IO_PM1_CNT_S4 (BIT12 | BIT11)
+#define V_ACPI_IO_PM1_CNT_S5 (BIT12 | BIT11 | BIT10)
+#define B_ACPI_IO_PM1_CNT_SCI_EN BIT0
+
+#define R_ACPI_IO_PM1_TMR 0x08
+#define B_ACPI_IO_PM1_TMR_VAL 0xFFFFFF
+#define V_ACPI_IO_PM1_TMR_MAX_VAL 0x1000000 ///< The timer is 24 bit overflow
+
+#define R_ACPI_IO_SMI_EN 0x30
+#define S_ACPI_IO_SMI_EN 4
+#define B_ACPI_IO_SMI_EN_LEGACY_USB2 BIT17
+#define B_ACPI_IO_SMI_EN_TCO BIT13
+#define B_ACPI_IO_SMI_EN_BIOS_RLS BIT7
+#define B_ACPI_IO_SMI_EN_SWSMI_TMR BIT6
+#define B_ACPI_IO_SMI_EN_APMC BIT5
+#define B_ACPI_IO_SMI_EN_LEGACY_USB BIT3
+#define B_ACPI_IO_SMI_EN_BIOS BIT2
+#define B_ACPI_IO_SMI_EN_EOS BIT1
+#define B_ACPI_IO_SMI_EN_GBL_SMI BIT0
+#define N_ACPI_IO_SMI_EN_LEGACY_USB3 31
+#define N_ACPI_IO_SMI_EN_ESPI 28
+#define N_ACPI_IO_SMI_EN_PERIODIC 14
+#define N_ACPI_IO_SMI_EN_TCO 13
+#define N_ACPI_IO_SMI_EN_MCSMI 11
+#define N_ACPI_IO_SMI_EN_SWSMI_TMR 6
+#define N_ACPI_IO_SMI_EN_APMC 5
+#define N_ACPI_IO_SMI_EN_ON_SLP_EN 4
+#define N_ACPI_IO_SMI_EN_LEGACY_USB 3
+
+#define R_ACPI_IO_SMI_STS 0x34
+#define S_ACPI_IO_SMI_STS 4
+#define B_ACPI_IO_SMI_STS_GPIO_UNLOCK BIT27
+#define B_ACPI_IO_SMI_STS_SMBUS BIT16
+#define B_ACPI_IO_SMI_STS_PERIODIC BIT14
+#define B_ACPI_IO_SMI_STS_TCO BIT13
+#define B_ACPI_IO_SMI_STS_MCSMI BIT11
+#define B_ACPI_IO_SMI_STS_SWSMI_TMR BIT6
+#define B_ACPI_IO_SMI_STS_APM BIT5
+#define B_ACPI_IO_SMI_STS_ON_SLP_EN BIT4
+#define B_ACPI_IO_SMI_STS_BIOS BIT2
+#define N_ACPI_IO_SMI_STS_LEGACY_USB3 31
+#define N_ACPI_IO_SMI_STS_ESPI 28
+#define N_ACPI_IO_SMI_STS_SPI 26
+#define N_ACPI_IO_SMI_STS_MONITOR 21
+#define N_ACPI_IO_SMI_STS_PCI_EXP 20
+#define N_ACPI_IO_SMI_STS_SMBUS 16
+#define N_ACPI_IO_SMI_STS_SERIRQ 15
+#define N_ACPI_IO_SMI_STS_PERIODIC 14
+#define N_ACPI_IO_SMI_STS_TCO 13
+#define N_ACPI_IO_SMI_STS_MCSMI 11
+#define N_ACPI_IO_SMI_STS_GPIO_SMI 10
+#define N_ACPI_IO_SMI_STS_GPE0 9
+#define N_ACPI_IO_SMI_STS_PM1_STS_REG 8
+#define N_ACPI_IO_SMI_STS_SWSMI_TMR 6
+#define N_ACPI_IO_SMI_STS_APM 5
+#define N_ACPI_IO_SMI_STS_ON_SLP_EN 4
+#define N_ACPI_IO_SMI_STS_LEGACY_USB 3
+
+#define R_ACPI_IO_DEVACT_STS 0x44
+#define B_ACPI_IO_DEVACT_STS_KBC BIT12
+#define B_ACPI_IO_DEVACT_STS_PIRQDH BIT9
+#define B_ACPI_IO_DEVACT_STS_PIRQCG BIT8
+#define B_ACPI_IO_DEVACT_STS_PIRQBF BIT7
+#define B_ACPI_IO_DEVACT_STS_PIRQAE BIT6
+
+#define R_ACPI_IO_GPE0_STS_127_96 0x6C
+#define S_ACPI_IO_GPE0_STS_127_96 4
+#define B_ACPI_IO_GPE0_STS_127_96_WADT BIT18
+#define B_ACPI_IO_GPE0_STS_127_96_USB_CON_DSX_STS BIT17
+#define B_ACPI_IO_GPE0_STS_127_96_LAN_WAKE BIT16
+#define B_ACPI_IO_GPE0_STS_127_96_PME_B0 BIT13
+#define B_ACPI_IO_GPE0_STS_127_96_PME BIT11
+#define B_ACPI_IO_GPE0_STS_127_96_BATLOW BIT10
+#define B_ACPI_IO_GPE0_STS_127_96_RI BIT8
+#define B_ACPI_IO_GPE0_STS_127_96_SMB_WAK BIT7
+#define B_ACPI_IO_GPE0_STS_127_96_SWGPE BIT2
+#define N_ACPI_IO_GPE0_STS_127_96_PME_B0 13
+#define N_ACPI_IO_GPE0_STS_127_96_PME 11
+
+#define R_ACPI_IO_GPE0_EN_127_96 0x7C
+#define S_ACPI_IO_GPE0_EN_127_96 4
+#define B_ACPI_IO_GPE0_EN_127_96_WADT BIT18
+#define B_ACPI_IO_GPE0_EN_127_96_LAN_WAKE BIT16
+#define B_ACPI_IO_GPE0_EN_127_96_PME_B0 BIT13
+#define B_ACPI_IO_GPE0_EN_127_96_ME_SCI BIT12
+#define B_ACPI_IO_GPE0_EN_127_96_PME BIT11
+#define B_ACPI_IO_GPE0_EN_127_96_BATLOW BIT10
+#define B_ACPI_IO_GPE0_EN_127_96_RI BIT8
+#define B_ACPI_IO_GPE0_EN_127_96_SWGPE BIT2
+#define N_ACPI_IO_GPE0_EN_127_96_PME_B0 13
+#define N_ACPI_IO_GPE0_EN_127_96_PME 11
+
+//
+// TCO register I/O map
+//
+#define R_TCO_IO_TCO1_STS 0x04
+#define S_TCO_IO_TCO1_STS 2
+#define B_TCO_IO_TCO1_STS_DMISERR BIT12
+#define B_TCO_IO_TCO1_STS_DMISMI BIT10
+#define B_TCO_IO_TCO1_STS_DMISCI BIT9
+#define B_TCO_IO_TCO1_STS_BIOSWR BIT8
+#define B_TCO_IO_TCO1_STS_NEWCENTURY BIT7
+#define B_TCO_IO_TCO1_STS_TIMEOUT BIT3
+#define B_TCO_IO_TCO1_STS_TCO_INT BIT2
+#define B_TCO_IO_TCO1_STS_SW_TCO_SMI BIT1
+#define N_TCO_IO_TCO1_STS_DMISMI 10
+#define N_TCO_IO_TCO1_STS_BIOSWR 8
+#define N_TCO_IO_TCO1_STS_NEWCENTURY 7
+#define N_TCO_IO_TCO1_STS_TIMEOUT 3
+#define N_TCO_IO_TCO1_STS_SW_TCO_SMI 1
+#define N_TCO_IO_TCO1_STS_NMI2SMI 0
+
+#define R_TCO_IO_TCO2_STS 0x06
+#define S_TCO_IO_TCO2_STS 2
+#define B_TCO_IO_TCO2_STS_SECOND_TO BIT1
+#define B_TCO_IO_TCO2_STS_INTRD_DET BIT0
+#define N_TCO_IO_TCO2_STS_INTRD_DET 0
+
+#define R_TCO_IO_TCO1_CNT 0x08
+#define S_TCO_IO_TCO1_CNT 2
+#define B_TCO_IO_TCO1_CNT_LOCK BIT12
+#define N_TCO_IO_TCO1_CNT_NMI2SMI_EN 9
+
+#define R_TCO_IO_TCO2_CNT 0x0A
+#define S_TCO_IO_TCO2_CNT 2
+#define N_TCO_IO_TCO2_CNT_INTRD_SEL 2
+
+//
+// PWRM Registers
+//
+#define R_PMC_PWRM_GEN_PMCON_A 0x1020 ///< in CNL located in PWRM
+#define B_PMC_PWRM_GEN_PMCON_A_GBL_RST_STS BIT24
+#define B_PMC_PWRM_GEN_PMCON_A_DISB BIT23
+#define B_PMC_PWRM_GEN_PMCON_A_ALLOW_L1LOW_C0 BIT19
+#define B_PMC_PWRM_GEN_PMCON_A_MS4V BIT18
+#define B_PMC_PWRM_GEN_PMCON_A_SUS_PWR_FLR BIT16
+#define B_PMC_PWRM_GEN_PMCON_A_PWR_FLR BIT14
+#define B_PMC_PWRM_GEN_PMCON_A_HOST_RST_STS BIT9
+#define B_PMC_PWRM_GEN_PMCON_A_ESPI_SMI_LOCK BIT8
+#define B_PMC_PWRM_GEN_PMCON_A_AFTERG3_EN BIT0
+#define B_PMC_PWRM_GEN_PMCON_A_SWSMI_RTSL 0xC0
+#define V_PMC_PWRM_GEN_PMCON_A_SWSMI_RTSL_64MS 0xC0
+#define V_PMC_PWRM_GEN_PMCON_A_SWSMI_RTSL_32MS 0x80
+#define V_PMC_PWRM_GEN_PMCON_A_SWSMI_RTSL_16MS 0x40
+#define V_PMC_PWRM_GEN_PMCON_A_SWSMI_RTSL_1_5MS 0x00
+#define B_PMC_PWRM_GEN_PMCON_A_PER_SMI_SEL 0x6
+#define V_PMC_PWRM_GEN_PMCON_A_PER_SMI_64S 0x0000
+#define V_PMC_PWRM_GEN_PMCON_A_PER_SMI_32S 0x0002
+#define V_PMC_PWRM_GEN_PMCON_A_PER_SMI_16S 0x0004
+#define V_PMC_PWRM_GEN_PMCON_A_PER_SMI_8S 0x0006
+
+#define R_PMC_PWRM_GEN_PMCON_B 0x1024
+#define B_PMC_PWRM_GEN_PMCON_B_SLPSX_STR_POL_LOCK BIT18 ///< Lock down SLP_S3/SLP_S4 Minimum Assertion width
+#define B_PMC_PWRM_GEN_PMCON_B_PWRBTN_LVL BIT9
+#define B_PMC_PWRM_GEN_PMCON_B_SMI_LOCK BIT4
+#define B_PMC_PWRM_GEN_PMCON_B_RTC_PWR_STS BIT2
+
+#define R_PMC_PWRM_CRID 0x1030 ///< Configured Revision ID
+#define V_PMC_PWRM_CRID_RID_SEL_CRID0 1
+#define B_PMC_PWRM_CRID_CRID_LK BIT31 ///< CRID Lock
+
+#define R_PMC_PWRM_ETR3 0x1048 ///< in CNL this is PWRM register
+#define B_PMC_PWRM_ETR3_CF9LOCK BIT31 ///< CF9h Lockdown
+#define B_PMC_PWRM_ETR3_CF9GR BIT20 ///< CF9h Global Reset
+#define B_PMC_PWRM_ETR3_CWORWRE BIT18
+
+#define R_PMC_PWRM_CFG 0x1818 ///< Power Management Configuration
+#define B_PMC_PWRM_CFG_DBG_MODE_LOCK BIT27 ///< Debug Mode Lock
+#define B_PMC_PWRM_CFG_PMCREAD_DISABLE BIT22 ///< Disable Reads to PMC
+#define B_PMC_PWRM_CFG_TIMING_TPCH25 (BIT1 | BIT0) ///< tPCH25 timing
+
+#define R_PMC_PWRM_DSX_CFG 0x1834 ///< Deep SX Configuration
+#define B_PMC_PWRM_DSX_CFG_LAN_WAKE_EN BIT0 ///< LAN_WAKE Pin DeepSx Enable
+
+#define R_PMC_PWRM_GPIO_CFG 0x1920
+#define B_PMC_PWRM_GPIO_CFG_GPE0_DW2 (BIT11 | BIT10 | BIT9 | BIT8)
+#define N_PMC_PWRM_GPIO_CFG_GPE0_DW2 8
+#define B_PMC_PWRM_GPIO_CFG_GPE0_DW1 (BIT7 | BIT6 | BIT5 | BIT4)
+#define N_PMC_PWRM_GPIO_CFG_GPE0_DW1 4
+#define B_PMC_PWRM_GPIO_CFG_GPE0_DW0 (BIT3 | BIT2 | BIT1 | BIT0)
+#define N_PMC_PWRM_GPIO_CFG_GPE0_DW0 0
+
+#define R_PMC_PWRM_HPR_CAUSE0 0x192C ///< Host partition reset causes
+#define B_PMC_PWRM_HPR_CAUSE0_GBL_TO_HOST BIT15 ///< Global reset converted to Host reset
+
+#define R_PMC_PWRM_ST_PG_FDIS_PMC_1 0x1E20 ///< Static PG Related Function Disable Register 1
+#define B_PMC_PWRM_ST_PG_FDIS_PMC_1_ST_FDIS_LK BIT31 ///< Static Function Disable Lock (ST_FDIS_LK)
+
+#define R_PMC_PWRM_FUSE_DIS_RD_2 0x1E44 ///< Fuse Disable Read 2 Register
+#define B_PMC_PWRM_FUSE_DIS_RD_2_GBE_FUSE_SS_DIS BIT0 ///< GBE Fuse or Soft Strap Disable
+
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Include/Register/RtcRegs.h b/Silicon/Intel/TigerlakeSiliconPkg/Include/Register/RtcRegs.h
new file mode 100644
index 0000000000..5824663d22
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Include/Register/RtcRegs.h
@@ -0,0 +1,45 @@
+/** @file
+ Register names for RTC device
+
+Conventions:
+
+ - Register definition format:
+ Prefix_[GenerationName]_[ComponentName]_SubsystemName_RegisterSpace_RegisterName
+ - Prefix:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register size
+ Definitions beginning with "N_" are the bit position
+ - [GenerationName]:
+ Three letter acronym of the generation is used (e.g. SKL,KBL,CNL etc.).
+ Register name without GenerationName applies to all generations.
+ - [ComponentName]:
+ This field indicates the component name that the register belongs to (e.g. PCH, SA etc.)
+ Register name without ComponentName applies to all components.
+ Register that is specific to -LP denoted by "_PCH_LP_" in component name.
+ - SubsystemName:
+ This field indicates the subsystem name of the component that the register belongs to
+ (e.g. PCIE, USB, SATA, GPIO, PMC etc.).
+ - RegisterSpace:
+ MEM - MMIO space register of subsystem.
+ IO - IO space register of subsystem.
+ PCR - Private configuration register of subsystem.
+ CFG - PCI configuration space register of subsystem.
+ - RegisterName:
+ Full register name.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _REGS_RTC_H_
+#define _REGS_RTC_H_
+
+#define R_RTC_IO_INDEX 0x70
+#define R_RTC_IO_TARGET 0x71
+#define R_RTC_IO_INDEX_ALT 0x74
+#define R_RTC_IO_TARGET_ALT 0x75
+#define R_RTC_IO_EXT_INDEX_ALT 0x76
+#define R_RTC_IO_REGD 0x0D
+
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Include/Register/SataRegs.h b/Silicon/Intel/TigerlakeSiliconPkg/Include/Register/SataRegs.h
new file mode 100644
index 0000000000..2037bb003d
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Include/Register/SataRegs.h
@@ -0,0 +1,56 @@
+/** @file
+ Register names for SATA controllers
+
+ Conventions:
+
+ - Register definition format:
+ Prefix_[GenerationName]_[ComponentName]_SubsystemName_RegisterSpace_RegisterName
+ - Prefix:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register size
+ Definitions beginning with "N_" are the bit position
+ - [GenerationName]:
+ Three letter acronym of the generation is used (e.g. SKL,KBL,CNL etc.).
+ Register name without GenerationName applies to all generations.
+ - [ComponentName]:
+ This field indicates the component name that the register belongs to (e.g. PCH, SA etc.)
+ Register name without ComponentName applies to all components.
+ Register that is specific to -LP denoted by "_PCH_LP_" in component name.
+ - SubsystemName:
+ This field indicates the subsystem name of the component that the register belongs to
+ (e.g. PCIE, USB, SATA, GPIO, PMC etc.).
+ - RegisterSpace:
+ MEM - MMIO space register of subsystem.
+ IO - IO space register of subsystem.
+ PCR - Private configuration register of subsystem.
+ CFG - PCI configuration space register of subsystem.
+ - RegisterName:
+ Full register name.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _SATA_REGS_H_
+#define _SATA_REGS_H_
+
+//
+// SATA Controller Common Registers
+//
+#define R_SATA_CFG_AHCI_BAR 0x24
+#define R_SATA_CFG_MAP 0x90
+#define N_SATA_CFG_MAP_SPD 16
+#define R_SATA_CFG_PCS 0x94
+#define B_SATA_CFG_PCS_P0P BIT16
+#define R_SATA_CFG_SATAGC 0x9C
+#define B_SATA_CFG_SATAGC_ASSEL (BIT2 | BIT1 | BIT0)
+#define V_SATA_CFG_SATAGC_ASSEL_2K 0x0
+#define V_SATA_CFG_SATAGC_ASSEL_16K 0x1
+#define V_SATA_CFG_SATAGC_ASSEL_32K 0x2
+#define V_SATA_CFG_SATAGC_ASSEL_64K 0x3
+#define V_SATA_CFG_SATAGC_ASSEL_128K 0x4
+#define V_SATA_CFG_SATAGC_ASSEL_256K 0x5
+#define V_SATA_CFG_SATAGC_ASSEL_512K 0x6
+
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Include/Register/SerialIoRegs.h b/Silicon/Intel/TigerlakeSiliconPkg/Include/Register/SerialIoRegs.h
new file mode 100644
index 0000000000..9864dd872d
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Include/Register/SerialIoRegs.h
@@ -0,0 +1,47 @@
+/** @file
+ Register names for Serial IO Controllers
+
+ Conventions:
+
+ - Register definition format:
+ Prefix_[GenerationName]_[ComponentName]_SubsystemName_RegisterSpace_RegisterName
+ - Prefix:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register size
+ Definitions beginning with "N_" are the bit position
+ - [GenerationName]:
+ Three letter acronym of the generation is used (e.g. SKL,KBL,CNL etc.).
+ Register name without GenerationName applies to all generations.
+ - [ComponentName]:
+ This field indicates the component name that the register belongs to (e.g. PCH, SA etc.)
+ Register name without ComponentName applies to all components.
+ Register that is specific to -LP denoted by "_PCH_LP_" in component name.
+ - SubsystemName:
+ This field indicates the subsystem name of the component that the register belongs to
+ (e.g. PCIE, USB, SATA, GPIO, PMC etc.).
+ - RegisterSpace:
+ MEM - MMIO space register of subsystem.
+ IO - IO space register of subsystem.
+ PCR - Private configuration register of subsystem.
+ CFG - PCI configuration space register of subsystem.
+ - RegisterName:
+ Full register name.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _SERIAL_IO_REGS_H_
+#define _SERIAL_IO_REGS_H_
+
+//
+// Serial IO Controllers PCI Configuration Registers
+// registers accessed using PciD21FxRegBase + offset
+//
+#define R_SERIAL_IO_CFG_BAR0_LOW 0x10
+#define R_SERIAL_IO_CFG_BAR0_HIGH 0x14
+
+#define R_SERIAL_IO_CFG_PME_CTRL_STS 0x84
+
+#endif //_SERIAL_IO_REGS_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Include/Register/UsbRegs.h b/Silicon/Intel/TigerlakeSiliconPkg/Include/Register/UsbRegs.h
new file mode 100644
index 0000000000..ea832873bf
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Include/Register/UsbRegs.h
@@ -0,0 +1,51 @@
+/** @file
+ Register names for USB Host and device controller
+
+ Conventions:
+
+ - Register definition format:
+ Prefix_[GenerationName]_[ComponentName]_SubsystemName_RegisterSpace_RegisterName
+ - Prefix:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register size
+ Definitions beginning with "N_" are the bit position
+ - [GenerationName]:
+ Three letter acronym of the generation is used (e.g. SKL,KBL,CNL etc.).
+ Register name without GenerationName applies to all generations.
+ - [ComponentName]:
+ This field indicates the component name that the register belongs to (e.g. PCH, SA etc.)
+ Register name without ComponentName applies to all components.
+ Register that is specific to -LP denoted by "_PCH_LP_" in component name.
+ - SubsystemName:
+ This field indicates the subsystem name of the component that the register belongs to
+ (e.g. PCIE, USB, SATA, GPIO, PMC etc.).
+ - RegisterSpace:
+ MEM - MMIO space register of subsystem.
+ IO - IO space register of subsystem.
+ PCR - Private configuration register of subsystem.
+ CFG - PCI configuration space register of subsystem.
+ - RegisterName:
+ Full register name.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _USB_REGS_H_
+#define _USB_REGS_H_
+
+//
+// XHCI PCI Config Space registers
+//
+#define R_XHCI_CFG_PWR_CNTL_STS 0x74
+#define B_XHCI_CFG_PWR_CNTL_STS_PWR_STS (BIT1 | BIT0)
+#define V_XHCI_CFG_PWR_CNTL_STS_PWR_STS_D3 (BIT1 | BIT0)
+
+//
+// xDCI (OTG) MMIO registers
+//
+#define R_XDCI_MEM_GCTL 0xC110 ///< Xdci Global Ctrl
+
+#endif // _USB_REGS_H_
+
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Include/SerialIoDevices.h b/Silicon/Intel/TigerlakeSiliconPkg/Include/SerialIoDevices.h
new file mode 100644
index 0000000000..e2e1cf2ad2
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Include/SerialIoDevices.h
@@ -0,0 +1,213 @@
+/** @file
+ Serial IO policy
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _SERIAL_IO_DEVICES_H_
+#define _SERIAL_IO_DEVICES_H_
+
+#include <Protocol/SerialIo.h>
+#include <PchLimits.h>
+
+#pragma pack (push,1)
+
+/**
+ Available working modes for SerialIo SPI Host Controller
+
+ 0: SerialIoSpiDisabled;
+ - Device is placed in D3
+ - Gpio configuration is skipped
+ - PSF:
+ !important! If given device is Function 0 and other higher functions on given device
+ are enabled, PSF disabling is skipped. PSF default will remain and device PCI CFG Space will still be visible.
+ This is needed to allow PCI enumerator access functions above 0 in a multifunction device.
+ <b>1: SerialIoSpiPci;</b>
+ - Gpio pin configuration in native mode for each assigned pin
+ - Device will be enabled in PSF
+ - Only BAR0 will be enabled
+ 2: SerialIoSpiHidden;
+ - Gpio pin configuration in native mode for each assigned pin
+ - Device disabled in the PSF
+ - Both BARs are enabled, BAR1 becomes devices Pci Config Space
+ - BAR0 assigned from the global PCH reserved memory range, reported as motherboard resource by SIRC
+ @note
+ If this controller is located at function 0 and it's mode is set to hidden it will not be visible in the PCI space.
+**/
+typedef enum {
+ SerialIoSpiDisabled,
+ SerialIoSpiPci,
+ SerialIoSpiHidden
+} SERIAL_IO_SPI_MODE;
+
+/**
+ Used to set Inactive/Idle polarity of Spi Chip Select
+**/
+typedef enum {
+ SerialIoSpiCsActiveLow = 0,
+ SerialIoSpiCsActiveHigh = 1
+} SERIAL_IO_CS_POLARITY;
+
+/**
+ The SERIAL_IO_SPI_CONFIG provides the configurations to set the Serial IO SPI controller
+**/
+typedef struct {
+ UINT8 Mode; ///< <b>SerialIoSpiPci </b> see SERIAL_IO_SPI_MODE
+ UINT8 DefaultCsOutput; ///< <b>0 = CS0</b> CS1, CS2, CS3. Default CS used by the SPI HC
+ UINT8 CsPolarity[PCH_MAX_SERIALIO_SPI_CHIP_SELECTS]; ///< Selects SPI ChipSelect signal polarity, 0 = low <b>1 = High</b>
+ UINT8 CsEnable[PCH_MAX_SERIALIO_SPI_CHIP_SELECTS]; ///< <b>0 = Enable</b> 1 = Disable. Based on this setting GPIO for given SPIx CSx will be configured in Native mode
+ UINT8 CsMode; ///< <b>0 = HW Control</b> 1 = SW Control. Sets Chip Select Control mode Hardware or Software.
+ UINT8 CsState; ///< <b>0 = CS is set to low</b> 1 = CS is set to high
+} SERIAL_IO_SPI_CONFIG;
+
+/**
+ Available working modes for SerialIo UART Host Controller
+
+ 0: SerialIoUartDisabled;
+ - Device is placed in D3
+ - Gpio configuration is skipped
+ - PSF:
+ !important! If given device is Function 0 and other higher functions on given device
+ are enabled, PSF disabling is skipped. PSF default will remain and device PCI CFG Space will still be visible.
+ This is needed to allow PCI enumerator access functions above 0 in a multifunction device.
+ <b>1: SerialIoUartPci;</b>
+ - Designated for Serial IO UART OS driver usage
+ - Gpio pin configuration in native mode for each assigned pin
+ - Device will be enabled in PSF
+ - Only BAR0 will be enabled
+ 2: SerialIoUartHidden;
+ - Designated for BIOS and/or DBG2 OS kernel debug
+ - Gpio pin configuration in native mode for each assigned pin
+ - Device disabled in the PSF
+ - Both BARs are enabled, BAR1 becomes devices Pci Config Space
+ - BAR0 assigned from the global PCH reserved memory range, reported as motherboard resource by SIRC
+ @note
+ If this controller is located at function 0 and it's mode is set to hidden it will not be visible in the PCI space.
+ 3: SerialIoUartCom;
+ - Designated for 16550/PNP0501 compatible COM device
+ - Gpio pin configuration in native mode for each assigned pin
+ - Device disabled in the PSF
+ - Both BARs are enabled, BAR1 becomes devices Pci Config Space
+ - BAR0 assigned from the global PCH reserved memory range, reported as motherboard resource by SIRC
+ 4: SerialIoUartSkipInit;
+ - Gpio configuration is skipped
+ - PSF configuration is skipped
+ - BAR assignemnt is skipped
+ - D-satate setting is skipped
+
+**/
+typedef enum {
+ SerialIoUartDisabled,
+ SerialIoUartPci,
+ SerialIoUartHidden,
+ SerialIoUartCom,
+ SerialIoUartSkipInit
+} SERIAL_IO_UART_MODE;
+
+/**
+ UART Settings
+**/
+typedef struct {
+ UINT32 BaudRate; ///< <b> 115200 </b> Max 6000000 MdePkg.dec PcdUartDefaultBaudRate
+ UINT8 Parity; ///< <b> 1 - No Parity</b> see EFI_PARITY_TYPE MdePkg.dec PcdUartDefaultParity
+ UINT8 DataBits; ///< <b>8</b> MdePkg.dec PcdUartDefaultDataBits
+ UINT8 StopBits; ///< <b>1 - One Stop Bit</b> see EFI_STOP_BITS_TYPE MdePkg.dec PcdUartDefaultStopBits
+ UINT8 AutoFlow; ///< <b>FALSE</b> IntelFrameworkModulePkg.dsc PcdIsaBusSerialUseHalfHandshake
+} SERIAL_IO_UART_ATTRIBUTES;
+
+/**
+ UART signals pin muxing settings. If signal can be enable only on a single pin
+ then this parameter is ignored by RC. Refer to GPIO_*_MUXING_SERIALIO_UARTx_* in GpioPins*.h
+ for supported settings on a given platform
+**/
+typedef struct {
+ UINT32 Rx; ///< RXD Pin mux configuration. Refer to GPIO_*_MUXING_SERIALIO_UARTx_RXD_*
+ UINT32 Tx; ///< TXD Pin mux configuration. Refer to GPIO_*_MUXING_SERIALIO_UARTx_TXD_*
+ UINT32 Rts; ///< RTS Pin mux configuration. Refer to GPIO_*_MUXING_SERIALIO_UARTx_RTS_*
+ UINT32 Cts; ///< CTS Pin mux configuration. Refer to GPIO_*_MUXING_SERIALIO_UARTx_CTS_*
+} UART_PIN_MUX;
+
+/**
+ Serial IO UART Controller Configuration
+**/
+typedef struct {
+ SERIAL_IO_UART_ATTRIBUTES Attributes; ///< see SERIAL_IO_UART_ATTRIBUTES
+ UART_PIN_MUX PinMux; ///< UART pin mux configuration
+ UINT8 Mode; ///< <b> SerialIoUartPci </b> see SERIAL_IO_UART_MODE
+ UINT8 DBG2; ///< <b> FALSE </b> If TRUE adds UART to DBG2 table and overrides UartPg to SerialIoUartPgDisabled
+ UINT8 PowerGating; ///< <b> SerialIoUartPgAuto </b> Applies to Hidden/COM/SkipInit see SERIAL_IO_UART_PG
+ UINT8 DmaEnable; ///< <b> TRUE </b> Applies to SerialIoUartPci only. Informs OS driver to use DMA, if false it will run in PIO mode
+} SERIAL_IO_UART_CONFIG;
+
+typedef enum {
+ SerialIoUartPgDisabled, ///< No _PS0/_PS3 support, device left in D0, after initialization
+/**
+ In mode: SerialIoUartCom;
+ _PS0/_PS3 that supports getting device out of reset
+ In mode: SerialIoUartPci
+ Keeps UART in D0 and assigns Fixed MMIO for SEC/PEI usage only
+**/
+ SerialIoUartPgEnabled,
+ SerialIoUartPgAuto ///< _PS0 and _PS3, detection through ACPI if device was initialized prior to first PG. If it was used (DBG2) PG is disabled,
+} SERIAL_IO_UART_PG;
+
+/**
+ Available working modes for SerialIo I2C Host Controller
+
+ 0: SerialIoI2cDisabled;
+ - Device is placed in D3
+ - Gpio configuration is skipped
+ - PSF:
+ !important! If given device is Function 0 and other higher functions on given device
+ are enabled, PSF disabling is skipped. PSF default will remain and device PCI CFG Space will still be visible.
+ This is needed to allow PCI enumerator access functions above 0 in a multifunction device.
+ <b>1: SerialIoI2cPci;</b>
+ - Gpio pin configuration in native mode for each assigned pin
+ - Device will be enabled in PSF
+ - Only BAR0 will be enabled
+ 2: SerialIoI2cHidden;
+ - Gpio pin configuration in native mode for each assigned pin
+ - Device disabled in the PSF
+ - Both BARs are enabled, BAR1 becomes devices Pci Config Space
+ - BAR0 assigned from the global PCH reserved memory range, reported as motherboard resource by SIRC
+ @note
+ If this controller is located at function 0 and it's mode is set to hidden it will not be visible in the PCI space.
+**/
+typedef enum {
+ SerialIoI2cDisabled,
+ SerialIoI2cPci,
+ SerialIoI2cHidden
+} SERIAL_IO_I2C_MODE;
+
+/**
+ I2C signals pin muxing settings. If signal can be enable only on a single pin
+ then this parameter is ignored by RC. Refer to GPIO_*_MUXING_SERIALIO_I2Cx_* in GpioPins*.h
+ for supported settings on a given platform
+**/
+typedef struct {
+ UINT32 Sda; ///< SDA Pin mux configuration. Refer to GPIO_*_MUXING_SERIALIO_I2Cx_SDA_*
+ UINT32 Scl; ///< SCL Pin mux configuration. Refer to GPIO_*_MUXING_SERIALIO_I2Cx_SCL_*
+} I2C_PIN_MUX;
+
+/**
+ Serial IO I2C Controller Configuration
+**/
+typedef struct {
+ UINT8 Mode; /// <b>SerialIoI2cPci <b> see SERIAL_IO_I2C_MODE
+ /**
+ I2C Pads Internal Termination.
+ For more information please see Platform Design Guide.
+ Supported values (check GPIO_ELECTRICAL_CONFIG for reference):
+ <b>GpioTermNone: No termination</b>,
+ GpioTermWpu1K: 1kOhm weak pull-up,
+ GpioTermWpu5K: 5kOhm weak pull-up,
+ GpioTermWpu20K: 20kOhm weak pull-up
+ **/
+ UINT8 PadTermination;
+ UINT8 Reserved[2];
+ I2C_PIN_MUX PinMux; ///< I2C pin mux configuration
+} SERIAL_IO_I2C_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _SERIAL_IO_DEVICES_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Include/SiConfigHob.h b/Silicon/Intel/TigerlakeSiliconPkg/Include/SiConfigHob.h
new file mode 100644
index 0000000000..191bd815a1
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Include/SiConfigHob.h
@@ -0,0 +1,17 @@
+/** @file
+ Silicon Config HOB is used for gathering platform
+ related Intel silicon information and config setting.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _SI_CONFIG_HOB_H_
+#define _SI_CONFIG_HOB_H_
+
+#include <SiPolicyStruct.h>
+
+extern EFI_GUID gSiConfigHobGuid;
+
+// Rename SI_CONFIG_HOB into SI_CONFIG_HOB_DATA for it does not follow HOB structure.
+typedef CONST SI_CONFIG SI_CONFIG_HOB_DATA;
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Include/SiPolicyStruct.h b/Silicon/Intel/TigerlakeSiliconPkg/Include/SiPolicyStruct.h
new file mode 100644
index 0000000000..7b646d8972
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Include/SiPolicyStruct.h
@@ -0,0 +1,64 @@
+/** @file
+ Intel reference code configuration policies.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _SI_POLICY_STRUCT_H_
+#define _SI_POLICY_STRUCT_H_
+
+#include <ConfigBlock.h>
+#include <ConfigBlock/SiPreMemConfig.h>
+#include <ConfigBlock/SiConfig.h>
+
+/**
+ Silicon Policy revision number
+ Any change to this structure will result in an update in the revision number
+
+ This member specifies the revision of the Silicon Policy. This field is used to indicate change
+ to the policy structure.
+
+ <b>Revision 1</b>:
+ - Initial version.
+**/
+#define SI_POLICY_REVISION 1
+
+/**
+ Silicon pre-memory Policy revision number
+ Any change to this structure will result in an update in the revision number
+
+ <b>Revision 1</b>:
+ - Initial version.
+**/
+#define SI_PREMEM_POLICY_REVISION 1
+
+
+/**
+ SI Policy PPI in Pre-Mem\n
+ All SI config block change history will be listed here\n\n
+
+ - <b>Revision 1</b>:
+ - Initial version.\n
+**/
+struct _SI_PREMEM_POLICY_STRUCT {
+ CONFIG_BLOCK_TABLE_HEADER TableHeader; ///< Config Block Table Header
+/*
+ Individual Config Block Structures are added here in memory as part of AddConfigBlock()
+*/
+};
+
+/**
+ SI Policy PPI\n
+ All SI config block change history will be listed here\n\n
+
+ - <b>Revision 1</b>:
+ - Initial version.\n
+**/
+struct _SI_POLICY_STRUCT {
+ CONFIG_BLOCK_TABLE_HEADER TableHeader; ///< Config Block Table Header
+/*
+ Individual Config Block Structures are added here in memory as part of AddConfigBlock()
+*/
+};
+
+#endif
--
2.24.0.windows.2
^ permalink raw reply related [flat|nested] 42+ messages in thread
* [Patch V3 04/40] TigerlakeSiliconPkg/Cpu: Add Include headers
2021-02-05 7:40 [Patch V3 01/40] TigerlakeSiliconPkg: Add package and Include/ConfigBlock headers Heng Luo
2021-02-05 7:40 ` [Patch V3 02/40] TigerlakeSiliconPkg/Include: Add Library, PPI and Protocol include headers Heng Luo
2021-02-05 7:40 ` [Patch V3 03/40] TigerlakeSiliconPkg/Include: Add Pins, Register and other " Heng Luo
@ 2021-02-05 7:40 ` Heng Luo
2021-02-05 7:40 ` [Patch V3 05/40] TigerlakeSiliconPkg/Pch: Add include headers Heng Luo
` (35 subsequent siblings)
38 siblings, 0 replies; 42+ messages in thread
From: Heng Luo @ 2021-02-05 7:40 UTC (permalink / raw)
To: devel; +Cc: Sai Chaganty, Nate DeSimone
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3171
Adds header files common to CPU modules.
Cc: Sai Chaganty <rangasai.v.chaganty@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Signed-off-by: Heng Luo <heng.luo@intel.com>
---
Silicon/Intel/TigerlakeSiliconPkg/Cpu/Include/ConfigBlock/CpuConfig.h | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Cpu/Include/ConfigBlock/CpuConfigLibPreMemConfig.h | 148 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Cpu/Include/ConfigBlock/CpuPidTestConfig.h | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Cpu/Include/ConfigBlock/CpuPowerMgmtBasicConfig.h | 226 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Cpu/Include/ConfigBlock/CpuPowerMgmtCustomConfig.h | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Cpu/Include/ConfigBlock/CpuPowerMgmtPsysConfig.h | 36 ++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Cpu/Include/ConfigBlock/CpuPowerMgmtTestConfig.h | 150 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Cpu/Include/ConfigBlock/CpuSecurityPreMemConfig.h | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Cpu/Include/ConfigBlock/CpuTestConfig.h | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Cpu/Include/CpuAccess.h | 12 ++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Cpu/Include/CpuDataStruct.h | 21 +++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Cpu/Include/CpuPolicyCommon.h | 23 +++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Cpu/Include/Register/CommonMsr.h | 18 ++++++++++++++++++
13 files changed, 959 insertions(+)
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Cpu/Include/ConfigBlock/CpuConfig.h b/Silicon/Intel/TigerlakeSiliconPkg/Cpu/Include/ConfigBlock/CpuConfig.h
new file mode 100644
index 0000000000..d837500a38
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Cpu/Include/ConfigBlock/CpuConfig.h
@@ -0,0 +1,83 @@
+/** @file
+ CPU Config Block.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _CPU_CONFIG_H_
+#define _CPU_CONFIG_H_
+
+#define CPU_CONFIG_REVISION 3
+
+extern EFI_GUID gCpuConfigGuid;
+
+#pragma pack (push,1)
+
+/**
+ CPU Configuration Structure.
+
+ <b>Revision 1</b>:
+ - Initial version.
+ <b>Revision 2</b>:
+ - Add SmbiosType4MaxSpeedOverride.
+ <b>Revision 3</b>:
+ - Add AvxDisable & Avx3Disable.
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ UINT32 MicrocodePatchRegionSize;
+ EFI_PHYSICAL_ADDRESS MicrocodePatchAddress; ///< Pointer to microcode patch that is suitable for this processor.
+ /**
+ Enable or Disable Advanced Encryption Standard (AES) feature.
+ For some countries, this should be disabled for legal reasons.
+ - 0: Disable
+ - <b>1: Enable</b>
+ **/
+ UINT32 AesEnable : 1;
+ /**
+ Enable or Disable Trusted Execution Technology (TXT) feature.
+ - 0: Disable
+ - <b>1: Enable</b>
+ **/
+ UINT32 TxtEnable : 1;
+ UINT32 SkipMpInit : 1; ///< For Fsp only, Silicon Initialization will skip MP Initialization (including BSP) if enabled. For non-FSP, this should always be 0.
+ /**
+ Enable or Disable or Auto for PPIN Support to view Protected Processor Inventory Number.
+ - <b>0: Disable</b>
+ - 1: Enable
+ - 2: Auto : Feature is based on End Of Manufacturing (EOM) flag. If EOM is set, it is disabled.
+ **/
+ UINT32 PpinSupport : 2;
+ /**
+ Enable or Disable #AC machine check on split lock.
+ - <b>0: Disable</b>
+ - 1: Enable
+ **/
+ UINT32 AcSplitLock : 1;
+ /**
+ Enable or Disable Avx.
+ - 1: Disable
+ - <b> 0: Enable</b>
+ **/
+ UINT32 AvxDisable : 1;
+ /**
+ Enable or Disable Avx3.
+ - 1: Disable
+ - <b> 0: Enable</b>
+ **/
+ UINT32 Avx3Disable : 1;
+ UINT32 RsvdBits : 24; ///< Reserved for future use
+ /**
+ Provide the option for platform to override the MaxSpeed field of Smbios Type 4.
+ Value 4000 means 4000MHz.
+ If this value is not zero, it dominates the field.
+ If this value is zero, CPU RC will update the field according to the max radio.
+ <b>default is 0.</b>
+ **/
+ UINT16 SmbiosType4MaxSpeedOverride;
+ UINT8 Reserved0[2]; ///< Reserved for future use
+} CPU_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _CPU_CONFIG_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Cpu/Include/ConfigBlock/CpuConfigLibPreMemConfig.h b/Silicon/Intel/TigerlakeSiliconPkg/Cpu/Include/ConfigBlock/CpuConfigLibPreMemConfig.h
new file mode 100644
index 0000000000..bf3f436ddd
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Cpu/Include/ConfigBlock/CpuConfigLibPreMemConfig.h
@@ -0,0 +1,148 @@
+/** @file
+ CPU Security PreMemory Config Block.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _CPU_CONFIG_LIB_PREMEM_CONFIG_H_
+#define _CPU_CONFIG_LIB_PREMEM_CONFIG_H_
+
+#define CPU_CONFIG_LIB_PREMEM_CONFIG_REVISION 6
+
+extern EFI_GUID gCpuConfigLibPreMemConfigGuid;
+
+#define BOOT_FREQUENCY_MAX_BATTERY_PERF 0
+#define BOOT_FREQUENCY_MAX_NON_TURBO_PERF 1
+#define BOOT_FREQUENCY_TURBO_PERF 2
+
+#pragma pack (push,1)
+
+/**
+ CPU Config Library PreMemory Configuration Structure.
+
+ <b>Revision 1</b>:
+ - Initial version.
+ <b>Revision 2</b>:
+ - Expand the supported number of processor cores (ActiveCoreCount1).
+ <b>Revision 3</b>:
+ - Added PECI Sx and C10 Reset.
+ <b>Revision 4</b>:
+ - Added ActiveSmallCoreCount.
+ <b>Revision 5</b>:
+ - Added CrashLogGprs
+ <b>Revision 6</b>:
+ - Added ConfigTdpLevel
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ UINT32 HyperThreading : 1; ///< Enable or Disable Hyper Threading; 0: Disable; <b>1: Enable</b>.
+ /**
+ Sets the boot frequency starting from reset vector.
+ - 0: Maximum battery performance.
+ - 1: Maximum non-turbo performance
+ -<b>2: Turbo performance</b>.
+ @note If Turbo is selected BIOS will start in max non-turbo mode and switch to Turbo mode.
+ **/
+ UINT32 BootFrequency : 2;
+ /**
+ Number of processor cores to enable.
+ - <b> 0: All cores</b>
+ - 1: 1 core
+ - 2: 2 cores
+ - 3: 3 cores
+ **/
+ UINT32 ActiveCoreCount : 3; ///< @deprecated due to core active number limitaion.
+ UINT32 JtagC10PowerGateDisable : 1; ///< False: JTAG is power gated in C10 state. True: keeps the JTAG power up during C10 and deeper power states for debug purpose. <b>0: False<\b>; 1: True.
+ UINT32 BistOnReset : 1; ///< <b>(Test)</b> Enable or Disable BIST on Reset; <b>0: Disable</b>; 1: Enable.
+ /**
+ Enable or Disable Virtual Machine Extensions (VMX) feature.
+ - 0: Disable
+ - <b>1: Enable</b>
+ **/
+ UINT32 VmxEnable : 1;
+ /**
+ Processor Early Power On Configuration FCLK setting.
+ - <b>0: 800 MHz (ULT/ULX)</b>.
+ - <b>1: 1 GHz (DT/Halo)</b>. Not supported on ULT/ULX.
+ - 2: 400 MHz.
+ - 3: Reserved.
+ **/
+ UINT32 FClkFrequency : 2;
+ /**
+ Enable or Disable CrashLog feature
+ - 0: Disable
+ - <b>1: Enable</b>
+ **/
+ UINT32 CrashLogEnable : 1;
+
+ /**
+ Enable or Disable Total Memory Encryption (TME) feature.
+ - <b>0: Disable</b>
+ - 1: Enable
+ **/
+ UINT32 TmeEnable : 1;
+
+ UINT32 DebugInterfaceEnable : 2; ///< Enable or Disable processor debug features; 0: Disable; 1: Enable; <b>2: No Change</b>.
+ UINT32 DebugInterfaceLockEnable : 1; ///< Lock or Unlock debug interface features; 0: Disable; <b>1: Enable</b>.
+
+ /**
+ Number of big cores in processor to enable. And support up to 16 cores.
+ - <b> 0: All cores</b>
+ - 1: 1 core
+ - 2: 2 cores
+ - 3: 3 cores
+ **/
+ UINT32 ActiveCoreCount1 : 4;
+
+ /**
+ Enables a mailbox command to resolve rare PECI related Sx issues.
+ @note This should only be used on systems that observe PECI Sx issues.
+ - <b>0: Disable</b>
+ - 1: Enable
+ **/
+ UINT32 PeciSxReset : 1;
+
+ /**
+ Enables the mailbox command to resolve PECI reset issues during Pkg-C10 exit.
+ If Enabled, BIOS will send the CPU message to disable peci reset on C10 exit.
+ The default value is <b>1: Enable</b> for CML, and <b>0: Disable</b> for all other CPU's
+ - 0: Disable
+ - 1: Enable
+ **/
+ UINT32 PeciC10Reset : 1;
+
+ /**
+ Number of small cores in processor to enable. And support the enabling of up to 63 cores.
+ - <b> 0: All cores</b>
+ - 1: 1 core
+ - 2: 2 cores
+ - 3: 3 cores
+ **/
+ UINT32 ActiveSmallCoreCount : 6;
+
+ /**
+ Enable or Disable CrashLog GPRs dump
+ - <b>0: Disable</b>
+ - 1: Gprs Enabled, Smm Gprs Enabled
+ 2: Gprs Enabled, Smm Gprs Disabled
+ **/
+ UINT32 CrashLogGprs : 2;
+
+ UINT32 RsvdBits : 2;
+
+ /**
+ CpuRatio - Max non-turbo ratio (Flexible Ratio Boot) is set to CpuRatio. <b>0: Disabled</b> If disabled, doesn't override max-non turbo ratio.
+ **/
+ UINT8 CpuRatio;
+ /**
+ Configuration for boot TDP selection; <b>0: TDP Nominal</b>; 1: TDP Down; 2: TDP Up.
+ **/
+ UINT8 ConfigTdpLevel;
+ UINT8 Reserved[2]; ///< Reserved for alignment
+ UINT32 ElixirSpringsPatchAddr; ///< Address of Elixir Springs Patch(es)
+ UINT32 ElixirSpringsPatchSize; ///< Elixir Springs Patch(es) Size.
+} CPU_CONFIG_LIB_PREMEM_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _CPU_CONFIG_LIB_PREMEM_CONFIG_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Cpu/Include/ConfigBlock/CpuPidTestConfig.h b/Silicon/Intel/TigerlakeSiliconPkg/Cpu/Include/ConfigBlock/CpuPidTestConfig.h
new file mode 100644
index 0000000000..4fcb92cb27
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Cpu/Include/ConfigBlock/CpuPidTestConfig.h
@@ -0,0 +1,52 @@
+/** @file
+ CPU PID Config Block.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _CPU_PID_TEST_CONFIG_H_
+#define _CPU_PID_TEST_CONFIG_H_
+
+#define CPU_PID_TEST_CONFIG_REVISION 1
+
+extern EFI_GUID gCpuPidTestConfigGuid;
+
+#pragma pack (push,1)
+
+/**
+ PID Tuning Configuration Structure.
+ Domain is mapped to Kp = 0, Ki = 1, Kd = 2.
+
+ <b>Revision 1</b>:
+ - Initial version.
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ UINT16 Ratl[3]; ///< RATL setting, in 1/256 units. Range is 0 - 65280
+ UINT16 VrTdcVr0[3]; ///< VR Thermal Design Current for VR0. In 1/256 units. Range is 0 - 65280
+ UINT16 VrTdcVr1[3]; ///< VR Thermal Design Current for VR1. In 1/256 units. Range is 0 - 65280
+ UINT16 VrTdcVr2[3]; ///< VR Thermal Design Current for VR2. In 1/256 units. Range is 0 - 65280
+ UINT16 VrTdcVr3[3]; ///< VR Thermal Design Current for VR3. In 1/256 units. Range is 0 - 65280
+ UINT16 PbmPsysPl1Msr[3]; ///< Power Budget Management Psys PL1 MSR. In 1/256 units. Range is 0 - 65280
+ UINT16 PbmPsysPl1MmioPcs[3]; ///< Power Budget Management Psys PL1 MMIO/PCS. In 1/256 units. Range is 0 - 65280
+ UINT16 PbmPsysPl2Msr[3]; ///< Power Budget Management Psys PL2 MSR. In 1/256 units. Range is 0 - 65280
+ UINT16 PbmPsysPl2MmioPcs[3]; ///< Power Budget Management Psys PL2 MMIO/PCS. In 1/256 units. Range is 0 - 65280
+ UINT16 PbmPkgPl1Msr[3]; ///< Power Budget Management Package PL1 MSR. In 1/256 units. Range is 0 - 65280
+ UINT16 PbmPkgPl1MmioPcs[3]; ///< Power Budget Management Package PL1 MMIO/PCS. In 1/256 units. Range is 0 - 65280
+ UINT16 PbmPkgPl2Msr[3]; ///< Power Budget Management Package PL2 MSR. In 1/256 units. Range is 0 - 65280
+ UINT16 PbmPkgPl2MmioPcs[3]; ///< Power Budget Management Package PL2 MMIO/PCS. In 1/256 units. Range is 0 - 65280
+ UINT16 DdrPl1Msr[3]; ///< DDR PL1 MSR. In 1/256 units. Range is 0 - 65280
+ UINT16 DdrPl1MmioPcs[3]; ///< DDR PL1 MMIO/PCS. In 1/256 units. Range is 0 - 65280
+ UINT16 DdrPl2Msr[3]; ///< DDR PL2 MSR. In 1/256 units. Range is 0 - 65280
+ UINT16 DdrPl2MmioPcs[3]; ///< DDR PL2 MMIO/PCS. In 1/256 units. Range is 0 - 65280
+ /**
+ Enable or Disable PID Tuning programming flow.
+ If disabled, all other policies in this config block are ignored.
+ **/
+ UINT8 PidTuning;
+ UINT8 Rsvd; ///< Reserved for DWORD alignment.
+} CPU_PID_TEST_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _CPU_PID_TEST_CONFIG_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Cpu/Include/ConfigBlock/CpuPowerMgmtBasicConfig.h b/Silicon/Intel/TigerlakeSiliconPkg/Cpu/Include/ConfigBlock/CpuPowerMgmtBasicConfig.h
new file mode 100644
index 0000000000..0255d49bdf
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Cpu/Include/ConfigBlock/CpuPowerMgmtBasicConfig.h
@@ -0,0 +1,226 @@
+/** @file
+ CPU Power Management Basic Config Block.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _CPU_POWER_MGMT_BASIC_CONFIG_H_
+#define _CPU_POWER_MGMT_BASIC_CONFIG_H_
+
+#define CPU_POWER_MGMT_BASIC_CONFIG_REVISION 5
+
+extern EFI_GUID gCpuPowerMgmtBasicConfigGuid;
+
+#pragma pack (push,1)
+
+/**
+ CPU Power Management Basic Configuration Structure.
+
+ <b>Revision 1</b>:
+ - Initial version.
+ <b>Revision 2</b>:
+ - Changed EnableItbm default to be disable
+ - Deprecated EnableItbmDriver due to Platform doesn't have ITBMT OS driver
+ <b>Revision 3</b>:
+ - Add ApplyConfigTdp for TDP initialization settings based on non-cTDP or cTDP
+ <b>Revision 4</b>:
+ - Add Hwp Lock support
+ <b>Revision 5</b>:
+ - Add VccInDemotionOverride and VccInDemotionMs
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ /**
+ Sets the boot frequency starting from reset vector.
+ - 0: Maximum battery performance.
+ - 1: Maximum non-turbo performance.
+ - <b>2: Turbo performance.</b>
+ @note If Turbo is selected BIOS will start in max non-turbo mode and switch to Turbo mode.
+ **/
+ UINT32 BootFrequency : 2; //@deprecated
+ UINT32 SkipSetBootPState : 1; ///< Choose whether to skip SetBootPState function for all APs; <b>0: Do not skip</b>; 1: Skip.
+ /**
+ Enable or Disable Intel Speed Shift Technology.
+ Enabling allows for processor control of P-state transitions.
+ 0: Disable; <b>1: Enable;</b> Bit 1 is ignored.
+ @note Currently this feature is recommended to be enabled only on win10
+ **/
+ UINT32 Hwp : 2;
+ /**
+ Hardware Duty Cycle Control configuration. 0: Disabled; <b>1: Enabled</b> 2-3:Reserved
+ HDC enables the processor to autonomously force components to enter into an idle state to lower effective frequency.
+ This allows for increased package level C6 residency.
+ @note Currently this feature is recommended to be enabled only on win10
+ **/
+ UINT32 HdcControl : 2;
+ UINT32 PowerLimit2 : 1; ///< Enable or Disable short duration Power Limit (PL2). 0: Disable; <b>1: Enable</b>
+ UINT32 TurboPowerLimitLock : 1; ///< MSR 0x610[63] and 0x618[63]: Locks all Turbo power limit settings to read-only; <b>0: Disable</b>; 1: Enable (Lock).
+ UINT32 PowerLimit3DutyCycle : 8; ///< Package PL3 Duty Cycle. Specifies the PL3 duty cycle percentage, Range 0-100. <b>Default: 0</b>.
+ UINT32 PowerLimit3Lock : 1; ///< Package PL3 MSR 615h lock; <b>0: Disable</b>; 1: Enable (Lock).
+ UINT32 PowerLimit4Lock : 1; ///< Package PL4 MSR 601h lock; <b>0: Disable</b>; 1: Enable (Lock).
+ /**
+ Tcc Offset Clamp for Runtime Average Temperature Limit (RATL) allows CPU to throttle below P1.
+ For Y SKU, the recommended default for this policy is <b>1: Enabled</b>, which indicates throttling below P1 is allowed.
+ For all other SKUs the recommended default are <b>0: Disabled</b>.
+ **/
+ UINT32 TccOffsetClamp : 1;
+ UINT32 TccOffsetLock : 1; ///< Tcc Offset Lock for Runtime Average Temperature Limit (RATL) to lock temperature target MSR 1A2h; 0: Disabled; <b>1: Enabled (Lock)</b>.
+ UINT32 TurboMode : 1; ///< Enable or Disable Turbo Mode. Disable; <b>1: Enable</b>
+ UINT32 HwpInterruptControl : 1; ///< Set HW P-State Interrupts Enabled for MISC_PWR_MGMT MSR 0x1AA[7]; <b>0: Disable</b>; 1: Enable.
+ UINT32 ApplyConfigTdp : 1; ///< Switch TDP applied setting based on non-cTDP or TDP; 0: non-cTDP; <b>1: cTDP</b>.
+ UINT32 HwpLock : 1; ///< HWP Lock in MISC PWR MGMT MSR 1AAh; <b>0: Disable</b>; 1: Enable (Lock).
+ UINT32 VccInDemotionOverride : 1; ///< Enable VccIn Demotion Override configuration. <b>0: Disable</b>; 1: Enable.
+ UINT32 RsvdBits : 6; ///< Reserved for future use.
+
+ /**
+ 1-Core Ratio Limit: LFM to Fused 1-Core Ratio Limit. For overclocking parts: LFM to Fused 1-Core Ratio Limit + OC Bins.
+ Note: OC Bins = 7 means fully unlocked, so range is LFM to 83.
+ - This 1-Core Ratio Limit Must be greater than or equal to 2-Core Ratio Limit, 3-Core Ratio Limit, 4-Core Ratio Limit.
+ **/
+ UINT8 OneCoreRatioLimit;
+ /**
+ 2-Core Ratio Limit: LFM to Fused 2-Core Ratio Limit, For overclocking part: LFM to Fused 2-Core Ratio Limit + OC Bins.
+ Note: OC Bins = 7 means fully unlocked, so range is LFM to 83.
+ - This 2-Core Ratio Limit Must be Less than or equal to 1-Core Ratio Limit.
+ **/
+ UINT8 TwoCoreRatioLimit;
+ /**
+ 3-Core Ratio Limit: LFM to Fused 3-Core Ratio Limit, For overclocking part: LFM to Fused 3-Core Ratio Limit + OC Bins.
+ Note: OC Bins = 7 means fully unlocked, so range is LFM to 83.
+ - This 3-Core Ratio Limit Must be Less than or equal to 1-Core Ratio Limit.
+ **/
+ UINT8 ThreeCoreRatioLimit;
+ /**
+ 4-Core Ratio Limit: LFM to Fused 4-Core Ratio Limit, For overclocking part: LFM to Fused 4-Core Ratio Limit + OC Bins.
+ Note: OC Bins = 7 means fully unlocked, so range is LFM to 83.
+ - This 4-Core Ratio Limit Must be Less than or equal to 1-Core Ratio Limit.
+ **/
+ UINT8 FourCoreRatioLimit;
+ /**
+ 5-Core Ratio Limit: LFM to Fused 5-Core Ratio Limit, For overclocking part: LFM to Fused 5-Core Ratio Limit + OC Bins.
+ Note: OC Bins = 7 means fully unlocked, so range is LFM to 83.
+ - This 5-Core Ratio Limit Must be Less than or equal to 1-Core Ratio Limit.
+ **/
+ UINT8 FiveCoreRatioLimit;
+ /**
+ 6-Core Ratio Limit: LFM to Fused 6-Core Ratio Limit, For overclocking part: LFM to Fused 6-Core Ratio Limit + OC Bins.
+ Note: OC Bins = 7 means fully unlocked, so range is LFM to 83.
+ - This 6-Core Ratio Limit Must be Less than or equal to 1-Core Ratio Limit.
+ **/
+ UINT8 SixCoreRatioLimit;
+ /**
+ 7-Core Ratio Limit: LFM to Fused 7-Core Ratio Limit, For overclocking part: LFM to Fused 7-Core Ratio Limit + OC Bins.
+ Note: OC Bins = 7 means fully unlocked, so range is LFM to 83.
+ - This 7-Core Ratio Limit Must be Less than or equal to 1-Core Ratio Limit.
+ **/
+ UINT8 SevenCoreRatioLimit;
+ /**
+ 8-Core Ratio Limit: LFM to Fused 8-Core Ratio Limit, For overclocking part: LFM to Fused 8-Core Ratio Limit + OC Bins.
+ Note: OC Bins = 7 means fully unlocked, so range is LFM to 83.
+ - This 8-Core Ratio Limit Must be Less than or equal to 1-Core Ratio Limit.
+ **/
+ UINT8 EightCoreRatioLimit;
+ /**
+ TCC Activation Offset. Offset from factory set TCC activation temperature at which the Thermal Control Circuit must be activated.
+ TCC will be activated at (TCC Activation Temperature - TCC Activation Offset), in degrees Celcius.
+ For Y SKU, the recommended default for this policy is <b>10</b>
+ For all other SKUs the recommended default are <b>0</b>, causing TCC to activate at TCC Activation temperature.
+ @note The policy is recommended for validation purpose only.
+ **/
+ UINT8 TccActivationOffset;
+ /**
+ Intel Turbo Boost Max Technology 3.0
+ Enabling it on processors with OS support will allow OS to exploit the diversity in max turbo frequency of the cores.
+ <b>0: Disable</b>; 1: Enable;
+ **/
+ UINT8 EnableItbm : 1;
+ /**
+ @deprecated: Platform doesn't have Intel Turbo Boost Max Technology 3.0 Driver
+ Enabling it will load the driver upon ACPI device with HID = INT3510.
+ <b> 0: Disable;</b> 1: Enable;
+ **/
+ UINT8 EnableItbmDriver : 1;
+ /**
+ Per Core P State OS control mode
+ Disabling will set PCU_MISC_CONFIG (Command 0x06) Bit 31 = 1. When set, the highest core request is used for all other core requests.
+ 0: Disable;<b> 1: Enable;</b>
+ **/
+ UINT8 EnablePerCorePState : 1;
+ /**
+ HwP Autonomous Per Core P State
+ Disabling will set Bit 30 = 1, command 0x11. When set, autonomous will request the same value
+ for all cores all the time.
+ 0: Disable;<b> 1: Enable;</b>
+ **/
+ UINT8 EnableHwpAutoPerCorePstate : 1;
+ /**
+ HwP Autonomous EPP grouping.
+ Disabling will set Bit 29 = 1, command 0x11. When set, autonomous will not necesarrily request the same value
+ for all cores with same EPP.
+ Enabling will clean Bit 29 = 0, command 0x11. Autonomous will request same values for all cores with same EPP.
+ 0: Disable;<b> 1: Enable;</b>
+ **/
+ UINT8 EnableHwpAutoEppGrouping : 1;
+ /**
+ EPB override over PECI
+ Enable by sending pcode command 0x2b , subcommand 0x3 to 1.
+ This will allow OOB EPB PECI override control.
+ <b>0: Disable;</b> 1: Enable;
+ **/
+ UINT8 EnableEpbPeciOverride : 1;
+ /**
+ Support for Fast MSR for IA32_HWP_REQUEST.
+ On systems with HwP enabled, if this feature is available as indicated by MSR 0x65F[0] = 1,
+ set MSR 0x657[0] = 1.
+ 0: Disable; <b> 1: Enable;</b>
+ **/
+ UINT8 EnableFastMsrHwpReq : 1;
+ UINT8 ReservedBits1 : 1; ///< Reserved for future use.
+ UINT8 MinRingRatioLimit; ///< Minimum Ring Ratio Limit. Range from 0 to Max Turbo Ratio. 0 = AUTO/HW Default
+ UINT8 MaxRingRatioLimit; ///< Maximum Ring Ratio Limit. Range from 0 to Max Turbo Ratio. 0 = AUTO/HW Default
+ /**
+ Package Long duration turbo mode power limit (PL1).
+ Default is the TDP power limit of processor. Units are based on POWER_MGMT_CONFIG.CustomPowerUnit.
+ **/
+ UINT16 PowerLimit1;
+ /**
+ Package Short duration turbo mode power limit (PL2). Allows for short excursions above TDP power limit.
+ Default = 1.25 * TDP Power Limit. Units are based on POWER_MGMT_CONFIG.CustomPowerUnit.
+ **/
+ UINT16 PowerLimit2Power;
+ /**
+ Package PL3 power limit. PL3 is the CPU Peak Power Occurences Limit.
+ <b>Default: 0</b>. Range 0-65535. Units are based on POWER_MGMT_CONFIG.CustomPowerUnit.
+ **/
+ UINT16 PowerLimit3;
+ /**
+ Package PL4 power limit. PL4 is a Preemptive CPU Package Peak Power Limit, it will never be exceeded.
+ Power is premptively lowered before limit is reached. <b>Default: 0</b>. Range 0-65535.
+ Units are based on POWER_MGMT_CONFIG.CustomPowerUnit.
+ **/
+ UINT16 PowerLimit4;
+ /**
+ Package Long duration turbo mode power limit (PL1) time window in seconds.
+ Used in calculating the average power over time.
+ Mobile: <b> 28s</b>
+ Desktop: <b> 8s</b>
+ Range: 0 - 128s
+ **/
+ UINT32 PowerLimit1Time;
+ UINT32 PowerLimit3Time; ///< Package PL3 time window. Range from 3ms to 64ms.
+ /**
+ Tcc Offset Time Window can range from 5ms to 448000ms for Runtime Average Temperature Limit (RATL).
+ For Y SKU, the recommended default for this policy is <b>5000: 5 seconds</b>, For all other SKUs the recommended default are <b>0: Disabled</b>
+ **/
+ UINT32 TccOffsetTimeWindowForRatl;
+ /**
+ Customize the VccIn Demotion in ms accordingly. Values used by OEM expected to be in lower end of 1-30 ms range.
+ Value 1 means 1ms, value 2 means 2ms, and so on. Value 0 will disable VccIn Demotion knob.
+ <b> It's 30ms by silicon default</b>.
+ **/
+ UINT32 VccInDemotionMs;
+} CPU_POWER_MGMT_BASIC_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _CPU_POWER_MGMT_BASIC_CONFIG_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Cpu/Include/ConfigBlock/CpuPowerMgmtCustomConfig.h b/Silicon/Intel/TigerlakeSiliconPkg/Cpu/Include/ConfigBlock/CpuPowerMgmtCustomConfig.h
new file mode 100644
index 0000000000..e1a5bcc684
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Cpu/Include/ConfigBlock/CpuPowerMgmtCustomConfig.h
@@ -0,0 +1,76 @@
+/** @file
+ CPU Power Managment Custom Config Block.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _CPU_POWER_MGMT_CUSTOM_CONFIG_H_
+#define _CPU_POWER_MGMT_CUSTOM_CONFIG_H_
+
+#define CPU_POWER_MGMT_CUSTOM_CONFIG_REVISION 1
+
+extern EFI_GUID gCpuPowerMgmtCustomConfigGuid;
+
+#pragma pack (push,1)
+
+///
+/// Defines the maximum number of custom ratio states supported.
+///
+#define MAX_CUSTOM_RATIO_TABLE_ENTRIES 40
+#define MAX_16_CUSTOM_RATIO_TABLE_ENTRIES 16
+
+///
+/// Defines the maximum number of custom ConfigTdp entries supported.
+/// @warning: Changing this define would cause DWORD alignment issues in policy structures.
+///
+#define MAX_CUSTOM_CTDP_ENTRIES 3
+
+///
+/// This structure is used to describe the custom processor ratio table desired by the platform.
+///
+typedef struct {
+ UINT8 MaxRatio; ///< The maximum ratio of the custom ratio table.
+ UINT8 NumberOfEntries; ///< The number of custom ratio state entries, ranges from 2 to 40 for a valid custom ratio table.
+ UINT8 Rsvd0[2]; ///< Reserved for DWORD alignment.
+ UINT32 Cpuid; ///< The CPU ID for which this custom ratio table applies.
+ UINT8 StateRatio[MAX_CUSTOM_RATIO_TABLE_ENTRIES]; ///< The processor ratios in the custom ratio table.
+ ///
+ /// If there are more than 16 total entries in the StateRatio table, then use these 16 entries to fill max 16 table.
+ /// @note If NumberOfEntries is 16 or less, or the first entry of this table is 0, then this table is ignored,
+ /// and up to the top 16 values from the StateRatio table is used instead.
+ ///
+ UINT8 StateRatioMax16[MAX_16_CUSTOM_RATIO_TABLE_ENTRIES];
+#if ((MAX_CUSTOM_RATIO_TABLE_ENTRIES + MAX_16_CUSTOM_RATIO_TABLE_ENTRIES) % 4)
+ UINT8 Rsvd1[4 - ((MAX_CUSTOM_RATIO_TABLE_ENTRIES + MAX_16_CUSTOM_RATIO_TABLE_ENTRIES) % 4)]; ///< If needed, add padding for dword alignment.
+#endif
+} PPM_CUSTOM_RATIO_TABLE;
+
+///
+/// PPM Custom ConfigTdp Settings
+///
+typedef struct _PPM_CUSTOM_CTDP_TABLE {
+ UINT32 CustomPowerLimit1Time : 8; ///< Short term Power Limit time window value for custom cTDP level.
+ UINT32 CustomTurboActivationRatio : 8; ///< Turbo Activation Ratio for custom cTDP level.
+ UINT32 RsvdBits : 16; ///< Bits reserved for DWORD alignment.
+ UINT16 CustomPowerLimit1; ///< Short term Power Limit value for custom cTDP level. Units are based on POWER_MGMT_CONFIG.CustomPowerUnit.
+ UINT16 CustomPowerLimit2; ///< Long term Power Limit value for custom cTDP level. Units are based on POWER_MGMT_CONFIG.CustomPowerUnit.
+} PPM_CUSTOM_CTDP_TABLE;
+
+/**
+ CPU Power Management Custom Configuration Structure.
+
+ <b>Revision 1</b>:
+ - Initial version.
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ PPM_CUSTOM_RATIO_TABLE CustomRatioTable; ///< Custom Processor Ratio Table Instance
+ PPM_CUSTOM_CTDP_TABLE CustomConfigTdpTable[MAX_CUSTOM_CTDP_ENTRIES]; ///< Custom ConfigTdp Settings Instance
+ UINT32 ConfigTdpLock : 1; ///< Lock the ConfigTdp mode settings from runtime changes; <b>0: Disable</b>; 1: Enable.
+ UINT32 ConfigTdpBios : 1; ///< Configure whether to load Configurable TDP SSDT; <b>0: Disable</b>; 1: Enable.
+ UINT32 RsvdBits : 30; ///< Reserved for future use
+} CPU_POWER_MGMT_CUSTOM_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _CPU_POWER_MGMT_CUSTOM_CONFIG_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Cpu/Include/ConfigBlock/CpuPowerMgmtPsysConfig.h b/Silicon/Intel/TigerlakeSiliconPkg/Cpu/Include/ConfigBlock/CpuPowerMgmtPsysConfig.h
new file mode 100644
index 0000000000..f1ceb8f43b
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Cpu/Include/ConfigBlock/CpuPowerMgmtPsysConfig.h
@@ -0,0 +1,36 @@
+/** @file
+ CPU Power Management Psys(Platform) Config Block.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _CPU_POWER_MGMT_PSYS_CONFIG_H_
+#define _CPU_POWER_MGMT_PSYS_CONFIG_H_
+
+#define CPU_POWER_MGMT_PSYS_CONFIG_REVISION 1
+
+extern EFI_GUID gCpuPowerMgmtPsysConfigGuid;
+
+#pragma pack (push,1)
+
+/**
+ CPU Power Management Psys(Platform) Configuration Structure.
+
+ <b>Revision 1</b>:
+ - Initial version.
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ UINT32 PsysPowerLimit1 : 1; ///< MSR 0x65C[15]: PL1 Enable activates the PL1 value to limit average platform power
+ UINT32 PsysPowerLimit1Time : 8; ///< MSR 0x65C[23:17]: PL1 timewindow in seconds.
+ UINT32 PsysPowerLimit2 : 1; ///< MSR 0x65C[47]: PL2 Enable activates the PL2 value to limit average platform power
+ UINT32 RsvdBits : 22; ///< Reserved for future use.
+ UINT16 PsysPowerLimit1Power; ///< MSR 0x65C[14:0]: Platform PL1 power. Units are based on POWER_MGMT_CONFIG.CustomPowerUnit.
+ UINT16 PsysPowerLimit2Power; ///< MSR 0x65C[46:32]]: Platform PL2 power. Units are based on POWER_MGMT_CONFIG.CustomPowerUnit.
+ UINT16 PsysPmax; ///< PCODE MMIO Mailbox: Platform Power Pmax. <b>0 - Auto</b> Specified in 1/8 Watt increments. 0-1024 Watts. Value of 800 = 100W.
+ UINT8 Rsvd[2]; ///< Reserved for future use and config block alignment
+} CPU_POWER_MGMT_PSYS_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _CPU_POWER_MGMT_PSYS_CONFIG_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Cpu/Include/ConfigBlock/CpuPowerMgmtTestConfig.h b/Silicon/Intel/TigerlakeSiliconPkg/Cpu/Include/ConfigBlock/CpuPowerMgmtTestConfig.h
new file mode 100644
index 0000000000..bd641f27c5
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Cpu/Include/ConfigBlock/CpuPowerMgmtTestConfig.h
@@ -0,0 +1,150 @@
+/** @file
+ CPU Power Management Test Config Block.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _CPU_POWER_MGMT_TEST_CONFIG_H_
+#define _CPU_POWER_MGMT_TEST_CONFIG_H_
+
+#define CPU_POWER_MGMT_TEST_CONFIG_REVISION 4
+
+extern EFI_GUID gCpuPowerMgmtTestConfigGuid;
+
+#pragma pack (push,1)
+
+///
+/// PPM Package C State Limit
+///
+typedef enum {
+ PkgC0C1 = 0,
+ PkgC2,
+ PkgC3,
+ PkgC6,
+ PkgC7,
+ PkgC7s,
+ PkgC8,
+ PkgC9,
+ PkgC10,
+ PkgCMax,
+ PkgCpuDefault = 254,
+ PkgAuto = 255
+} MAX_PKG_C_STATE;
+
+///
+/// PPM Package C State Time Limit
+///
+typedef enum {
+ TimeUnit1ns = 0,
+ TimeUnit32ns,
+ TimeUnit1024ns,
+ TimeUnit32768ns,
+ TimeUnit1048576ns,
+ TimeUnit33554432ns,
+ TimeUnitMax
+} C_STATE_TIME_UNIT;
+
+///
+/// Custom Power Units. User can choose to enter in watts or 125 milliwatt increments.
+///
+typedef enum {
+ PowerUnitWatts = 0, ///< in Watts.
+ PowerUnit125MilliWatts, ///< in 125 milliwatt increments. Example: 90 power units times 125 mW equals 11.250 W.
+ PowerUnitMax
+} CUSTOM_POWER_UNIT;
+
+///
+/// PPM Interrupt Redirection Mode Selection
+///
+typedef enum {
+ PpmIrmFixedPriority = 0,
+ PpmIrmRoundRobin,
+ PpmIrmHashVector,
+ PpmIrmReserved1,
+ PpmIrmReserved2,
+ PpmIrmReserved3,
+ PpmIrmReserved4,
+ PpmIrmNoChange
+} PPM_IRM_SETTING;
+
+/**
+ CPU Power Management Test Configuration Structure.
+
+ <b>Revision 1</b>:
+ - Initial version.
+ <b>Revision 2</b>:
+ - Add CstateLatencyControl0TimeUnit for WHL only
+ - Add CstateLatencyControl0Irtl for WHL only
+ <b>Revision 3</b>:
+ - Change C State LatencyContol to Auto as default.
+ <b>Revision 4</b>:
+ - Deprecate ConfigTdpLevel. Move to premem.
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Offset 0-27 Config Block Header
+ UINT32 Eist : 1; ///< Offset 28-31 Enable or Disable Intel SpeedStep Technology. 0: Disable; <b>1: Enable</b>
+ UINT32 EnergyEfficientPState : 1; ///< Enable or Disable Energy Efficient P-state will be applied in Turbo mode. Disable; <b>1: Enable</b>
+ UINT32 EnergyEfficientTurbo : 1; ///< Enable or Disable Energy Efficient Turbo, will be applied in Turbo mode. Disable; <b>1: Enable</b>
+ UINT32 TStates : 1; ///< Enable or Disable T states; <b>0: Disable</b>; 1: Enable.
+ UINT32 BiProcHot : 1; ///< Enable or Disable Bi-Directional PROCHOT#; 0: Disable; <b>1: Enable</b>.
+ UINT32 DisableProcHotOut : 1; ///< Enable or Disable PROCHOT# signal being driven externally; 0: Disable; <b>1: Enable</b>.
+ UINT32 ProcHotResponse : 1; ///< Enable or Disable PROCHOT# Response; <b>0: Disable</b>; 1: Enable.
+ UINT32 DisableVrThermalAlert : 1; ///< Enable or Disable VR Thermal Alert; <b>0: Disable</b>; 1: Enable.
+ UINT32 EnableAllThermalFunctions : 1; ///< Enable or Disable Thermal Reporting through ACPI tables; 0: Disable; <b>1: Enable</b>.
+ UINT32 ThermalMonitor : 1; ///< Enable or Disable Thermal Monitor; 0: Disable; <b>1: Enable</b>.
+ UINT32 Cx : 1; ///< Enable or Disable CPU power states (C-states). 0: Disable; <b>1: Enable</b>
+ UINT32 PmgCstCfgCtrlLock : 1; ///< If enabled, sets MSR 0xE2[15]; 0: Disable; <b>1: Enable</b>.
+ UINT32 C1e : 1; ///< Enable or Disable Enhanced C-states. 0: Disable; <b>1: Enable</b>
+ UINT32 C1AutoDemotion : 1; ///< Enable or Disable C6/C7 auto demotion to C1. 0: Disabled; <b>1: C1 Auto demotion</b>
+ UINT32 C1UnDemotion : 1; ///< Enable or Disable C1UnDemotion. 0: Disabled; <b>1: C1 Auto undemotion</b>
+ UINT32 C3AutoDemotion : 1; ///< [CoffeeLake Only] Enable or Disable C6/C7 auto demotion to C3 0: Disabled; <b>1: C3 Auto demotion</b>
+ UINT32 C3UnDemotion : 1; ///< [CoffeeLake Only] Enable or Disable C3UnDemotion. 0: Disabled; <b>1: C3 Auto undemotion</b>
+ UINT32 PkgCStateDemotion : 1; ///< Enable or Disable Package Cstate Demotion. Disable; <b>1: Enable</b> [WhiskeyLake] <b>Disable</b>; 1: Enable
+ UINT32 PkgCStateUnDemotion : 1; ///< Enable or Disable Package Cstate UnDemotion. Disable; <b>1: Enable</b> [WhiskeyLake] <b>Disable</b>; 1: Enable
+ UINT32 CStatePreWake : 1; ///< Enable or Disable CState-Pre wake. Disable; <b>1: Enable</b>
+ UINT32 TimedMwait : 1; ///< Enable or Disable TimedMwait Support. <b>Disable</b>; 1: Enable
+ UINT32 CstCfgCtrIoMwaitRedirection : 1; ///< Enable or Disable IO to MWAIT redirection; <b>0: Disable</b>; 1: Enable.
+ UINT32 ProcHotLock : 1; ///< If enabled, sets MSR 0x1FC[23]; <b>0: Disable</b>; 1: Enable.
+ UINT32 RaceToHalt : 1; ///< Enable or Disable Race To Halt feature; 0: Disable; <b>1: Enable </b>. RTH will dynamically increase CPU frequency in order to enter pkg C-State faster to reduce overall power. (RTH is controlled through MSR 1FC bit 20)
+ UINT32 ConfigTdpLevel : 8; ///< @deprecated. Move to premem phase.
+ UINT16 CstateLatencyControl1Irtl; ///< Offset 32-33 Interrupt Response Time Limit of LatencyContol1 MSR 0x60B[9:0].<b>0 is Auto</b>.
+ UINT16 CstateLatencyControl2Irtl; ///< Offset 34-35 Interrupt Response Time Limit of LatencyContol2 MSR 0x60C[9:0].<b>0 is Auto</b>.
+ UINT16 CstateLatencyControl3Irtl; ///< Offset 36-37 Interrupt Response Time Limit of LatencyContol3 MSR 0x633[9:0].<b>0 is Auto</b>.
+ UINT16 CstateLatencyControl4Irtl; ///< Offset 38-39 Interrupt Response Time Limit of LatencyContol4 MSR 0x634[9:0].<b>0 is Auto</b>.
+ UINT16 CstateLatencyControl5Irtl; ///< Offset 40-41 Interrupt Response Time Limit of LatencyContol5 MSR 0x635[9:0].<b>0 is Auto</b>.
+ // Due to the removal of CstateLatencyControl0Irtl, PkgCStateLimit is not aligned to 32-bit address.
+ UINT8 Rsvd1[2]; ///< Offset 42-43 Reserved for config block alignment.
+ MAX_PKG_C_STATE PkgCStateLimit; ///< Offset 44 This field is used to set the Max Pkg Cstate. Default set to Auto which limits the Max Pkg Cstate to deep C-state.
+ /**
+ @todo: The following enums have to be replaced with policies.
+ **/
+ C_STATE_TIME_UNIT Reserved; ///< Offset 45 Reserved for config block alignment.
+ C_STATE_TIME_UNIT CstateLatencyControl1TimeUnit; ///< Offset 46 TimeUnit for Latency Control1 MSR 0x60B[12:10]; <b>2: 1024ns</b>.
+ C_STATE_TIME_UNIT CstateLatencyControl2TimeUnit; ///< Offset 47 TimeUnit for Latency Control2 MSR 0x60C[12:10]; <b>2: 1024ns</b>.
+ C_STATE_TIME_UNIT CstateLatencyControl3TimeUnit; ///< Offset 48 TimeUnit for Latency Control3 MSR 0x633[12:10]; <b>2: 1024ns</b>.
+ C_STATE_TIME_UNIT CstateLatencyControl4TimeUnit; ///< Offset 49 TimeUnit for Latency Control4 MSR 0x634[12:10]; <b>2: 1024ns</b>.
+ C_STATE_TIME_UNIT CstateLatencyControl5TimeUnit; ///< Offset 50 TimeUnit for Latency Control5 MSR 0x635[12:10]; <b>2: 1024ns</b>.
+ /**
+ Offset 51 Default power unit in watts or in 125 milliwatt increments.
+ - 0: PowerUnitWatts.
+ - <b>1: PowerUnit125MilliWatts</b>.
+ **/
+ CUSTOM_POWER_UNIT CustomPowerUnit;
+ /**
+ Offset 52 Interrupt Redirection Mode Select.
+ - 0: Fixed priority. //Default under CNL.
+ - 1: Round robin.
+ - 2: Hash vector.
+ - 4: PAIR with fixed priority. //Default under KBL, not available under CNL.
+ - 5: PAIR with round robin. //Not available under CNL.
+ - 6: PAIR with hash vector. //Not available under CNL.
+ - 7: No change.
+ **/
+ PPM_IRM_SETTING PpmIrmSetting;
+ // Move the padding to previous offset to align the structure at 32-bit address.
+ UINT8 Rsvd[4]; ///< Offset 53-56 Reserved for future use and config block alignment
+} CPU_POWER_MGMT_TEST_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _CPU_POWER_MGMT_TEST_CONFIG_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Cpu/Include/ConfigBlock/CpuSecurityPreMemConfig.h b/Silicon/Intel/TigerlakeSiliconPkg/Cpu/Include/ConfigBlock/CpuSecurityPreMemConfig.h
new file mode 100644
index 0000000000..24614fe497
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Cpu/Include/ConfigBlock/CpuSecurityPreMemConfig.h
@@ -0,0 +1,63 @@
+/** @file
+ CPU Security PreMemory Config Block.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _CPU_SECURITY_PREMEM_CONFIG_H_
+#define _CPU_SECURITY_PREMEM_CONFIG_H_
+
+#define CPU_SECURITY_PREMEM_CONFIG_REVISION 1
+
+extern EFI_GUID gCpuSecurityPreMemConfigGuid;
+
+#pragma pack (push,1)
+
+/**
+ CPU Security PreMemory Configuration Structure.
+
+ <b>Revision 1</b>:
+ - Initial version.
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ UINT32 PrmrrSize; ///< PRMRR Size.<b>Software Control: 0x0</b> 32MB: 0x2000000, 64MB: 0x4000000, 128 MB: 0x8000000, 256 MB: 0x10000000, 512 MB: 0x20000000
+ UINT16 BiosSize; ///< Flash information for BIOS Guard: BIOS Size in KB.
+ UINT8 Reserved[2]; ///< Reserved for future use
+/**
+ Enable or Disable BIOS Guard; 0: Disable; <b>1: Enable</b>.
+ - This is an optional feature and can be opted out.
+ - If this policy is set to Disabled, the policies in the BIOS_GUARD_CONFIG will be ignored.
+ - If PeiBiosGuardLibNull is used, this policy will have no effect.
+**/
+ UINT32 BiosGuard : 1;
+ UINT32 BiosGuardToolsInterface : 1; ///< BIOS Guard Tools Interface; <b>0: Disable</b>, 1:Enable
+/**
+ Enable or Disable Software Guard Extensions; <b>0: Disable</b>; 1: Enable.
+ - This is an optional feature and can be opted out.
+ - If this policy is set to Disabled, the policies in the CPU_SGX_CONFIG will be ignored.
+ - If BaseSoftwareGuardLibNull is used, this policy will have no effect.
+**/
+ UINT32 EnableSgx : 1;
+/**
+ Enable or Disable Trusted Execution Technology; <b>0: Disable</b>; 1: Enable.
+ - This is an optional feature and can be opted out.
+ - If this policy is set to Disabled, the policies in the CPU_TXT_PREMEM_CONFIG will be ignored.
+ - If PeiTxtLibNull is used, this policy will have no effect.
+**/
+ UINT32 Txt : 1;
+ UINT32 SkipStopPbet : 1; ///< <b>(Test)</b> Skip Stop PBET Timer; <b>0: Disable</b>; 1: Enable.
+ ///
+ /// <b>(Test)</b> This policy indicates whether or not BIOS should allocate PRMRR memory for C6DRAM power gating feature.
+ /// - 0: Don't allocate any PRMRR memory for C6DRAM power gating feature.
+ /// - <b>1: Allocate PRMRR memory for C6DRAM power gating feature</b>.
+ ///
+ UINT32 EnableC6Dram : 1;
+ UINT32 ResetAux : 1; ///< <b>(Test)</b> Reset Auxiliary content, <b>0: Disabled</b>, 1: Enabled
+ UINT32 TxtAcheckRequest : 1; ///< <b>(Test)</b> AcheckRequest <b>0: Disabled</b>, 1: Enabled. When Enabled, it will call Acheck regardless of crashcode value
+ UINT32 RsvdBits : 24; ///< Reserved for future use
+} CPU_SECURITY_PREMEM_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _CPU_SECURITY_CONFIG_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Cpu/Include/ConfigBlock/CpuTestConfig.h b/Silicon/Intel/TigerlakeSiliconPkg/Cpu/Include/ConfigBlock/CpuTestConfig.h
new file mode 100644
index 0000000000..ee946290e0
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Cpu/Include/ConfigBlock/CpuTestConfig.h
@@ -0,0 +1,51 @@
+/** @file
+ CPU Test Config Block.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _CPU_TEST_CONFIG_H_
+#define _CPU_TEST_CONFIG_H_
+
+#define CPU_TEST_CONFIG_REVISION 2
+
+extern EFI_GUID gCpuTestConfigGuid;
+
+#pragma pack (push,1)
+
+/**
+ CPU Test Configuration Structure.
+
+ <b>Revision 1</b>:
+ - Initial version.
+ <b>Revision 2</b>:
+ - Removed Voltage Optimization feature.
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ UINT32 MlcStreamerPrefetcher : 1; ///< Enable or Disable MLC Streamer Prefetcher; 0: Disable; <b>1: Enable</b>.
+ UINT32 MlcSpatialPrefetcher : 1; ///< Enable or Disable MLC Spatial Prefetcher; 0: Disable; <b>1: Enable</b>.
+ UINT32 MonitorMwaitEnable : 1; ///< Enable or Disable Monitor /MWAIT instructions; 0: Disable; <b>1: Enable</b>.
+ UINT32 MachineCheckEnable : 1; ///< Enable or Disable initialization of machine check registers; 0: Disable; <b>1: Enable</b>.
+ UINT32 ProcessorTraceOutputScheme : 1; ///< Control on Processor Trace output scheme; <b>0: Single Range Output</b>; 1: ToPA Output.
+ UINT32 ProcessorTraceEnable : 1; ///< Enable or Disable Processor Trace feature; <b>0: Disable</b>; 1: Enable.
+ UINT32 ThreeStrikeCounterDisable : 1; ///< Disable Three strike counter; <b>0: FALSE</b>; 1: TRUE.
+ UINT32 RsvdBits : 25; ///< Reserved for future use
+ /**
+ Base address of memory region allocated for Processor Trace.
+ Processor Trace requires 2^N alignment and size in bytes per thread, from 4KB to 128MB.
+ - <b>NULL: Disable</b>
+ **/
+ EFI_PHYSICAL_ADDRESS ProcessorTraceMemBase;
+ /**
+ Length in bytes of memory region allocated for Processor Trace.
+ Processor Trace requires 2^N alignment and size in bytes per thread, from 4KB to 128MB.
+ - <b>0: Disable</b>
+ **/
+ UINT32 ProcessorTraceMemLength;
+ UINT8 Reserved0[4];
+} CPU_TEST_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _CPU_TEST_CONFIG_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Cpu/Include/CpuAccess.h b/Silicon/Intel/TigerlakeSiliconPkg/Cpu/Include/CpuAccess.h
new file mode 100644
index 0000000000..5d5e4df071
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Cpu/Include/CpuAccess.h
@@ -0,0 +1,12 @@
+/** @file
+ Macros to simplify and abstract the interface to CPU configuration.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _CPUACCESS_H_
+#define _CPUACCESS_H_
+
+#include "CpuDataStruct.h"
+
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Cpu/Include/CpuDataStruct.h b/Silicon/Intel/TigerlakeSiliconPkg/Cpu/Include/CpuDataStruct.h
new file mode 100644
index 0000000000..ba9a840e54
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Cpu/Include/CpuDataStruct.h
@@ -0,0 +1,21 @@
+/** @file
+ This file declares various data structures used in CPU reference code.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _CPU_DATA_STRUCT_H
+#define _CPU_DATA_STRUCT_H
+
+///
+/// Structure to hold the return value of AsmCpuid instruction
+///
+typedef struct {
+ UINT32 RegEax; ///< Value of EAX.
+ UINT32 RegEbx; ///< Value of EBX.
+ UINT32 RegEcx; ///< Value of ECX.
+ UINT32 RegEdx; ///< Value of EDX.
+} EFI_CPUID_REGISTER;
+
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Cpu/Include/CpuPolicyCommon.h b/Silicon/Intel/TigerlakeSiliconPkg/Cpu/Include/CpuPolicyCommon.h
new file mode 100644
index 0000000000..1178f68d0c
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Cpu/Include/CpuPolicyCommon.h
@@ -0,0 +1,23 @@
+/** @file
+ CPU Policy Structure definition which will contain several config blocks during runtime.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _CPU_POLICY_COMMON_H_
+#define _CPU_POLICY_COMMON_H_
+
+#include <ConfigBlock.h>
+#include <ConfigBlock/CpuConfig.h>
+#include <ConfigBlock/CpuPidTestConfig.h>
+#include <ConfigBlock/CpuPowerMgmtBasicConfig.h>
+#include <ConfigBlock/CpuPowerMgmtCustomConfig.h>
+#include <ConfigBlock/CpuPowerMgmtPsysConfig.h>
+#include <ConfigBlock/CpuPowerMgmtTestConfig.h>
+#include <ConfigBlock/VoltageRegulator/CpuPowerMgmtVrConfig.h>
+#include <ConfigBlock/CpuTestConfig.h>
+#include <ConfigBlock/CpuSecurityPreMemConfig.h>
+#include <ConfigBlock/CpuConfigLibPreMemConfig.h>
+#include <OverclockingConfig.h>
+
+#endif // _CPU_POLICY_COMMON_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Cpu/Include/Register/CommonMsr.h b/Silicon/Intel/TigerlakeSiliconPkg/Cpu/Include/Register/CommonMsr.h
new file mode 100644
index 0000000000..a2cd1db1d6
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Cpu/Include/Register/CommonMsr.h
@@ -0,0 +1,18 @@
+
+/** @file
+ CommonMsr.h
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _COMMONMSR_h
+#define _COMMONMSR_h
+#include <Base.h>
+
+/**
+ Special Chipset Usage MSR
+**/
+#define MSR_SPCL_CHIPSET_USAGE 0x000001FE
+
+#endif /* _COMMONMSR_h */
--
2.24.0.windows.2
^ permalink raw reply related [flat|nested] 42+ messages in thread
* [Patch V3 05/40] TigerlakeSiliconPkg/Pch: Add include headers
2021-02-05 7:40 [Patch V3 01/40] TigerlakeSiliconPkg: Add package and Include/ConfigBlock headers Heng Luo
` (2 preceding siblings ...)
2021-02-05 7:40 ` [Patch V3 04/40] TigerlakeSiliconPkg/Cpu: Add Include headers Heng Luo
@ 2021-02-05 7:40 ` Heng Luo
2021-02-05 7:40 ` [Patch V3 06/40] TigerlakeSiliconPkg/Pch: Add IncludePrivate headers Heng Luo
` (34 subsequent siblings)
38 siblings, 0 replies; 42+ messages in thread
From: Heng Luo @ 2021-02-05 7:40 UTC (permalink / raw)
To: devel; +Cc: Sai Chaganty, Nate DeSimone
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3171
Adds the following header files:
* Pch/Include
Cc: Sai Chaganty <rangasai.v.chaganty@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Signed-off-by: Heng Luo <heng.luo@intel.com>
---
Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/ConfigBlock/FlashProtectionConfig.h | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/ConfigBlock/HsioConfig.h | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/ConfigBlock/HsioPcieConfig.h | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/ConfigBlock/HsioSataConfig.h | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/ConfigBlock/LockDownConfig.h | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/ConfigBlock/LpcConfig.h | 38 ++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/ConfigBlock/PchGeneralConfig.h | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/Library/PchCycleDecodingLib.h | 258 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/Library/PchInfoLib.h | 590 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/Library/PchPciBdfLib.h | 552 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/PchInfoHob.h | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/PchLimits.h | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/PchPolicyCommon.h | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/PchPreMemPolicyCommon.h | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/PchResetPlatformSpecific.h | 21 +++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/Protocol/IoTrapExDispatch.h | 184 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/Protocol/PchAcpiSmiDispatch.h | 134 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/Protocol/PchEspiSmiDispatch.h | 144 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/Protocol/PchPcieSmiDispatch.h | 166 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/Protocol/PchPolicy.h | 40 ++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/Protocol/PchSmiDispatch.h | 132 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/Protocol/PchSmmIoTrapControl.h | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/Protocol/PchSmmPeriodicTimerControl.h | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/Protocol/PchTcoSmiDispatch.h | 150 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/Register/PchRegs.h | 16 ++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/Register/PchRegsLpc.h | 145 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/Register/PchRegsPsf.h | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/Register/PchRegsPsth.h | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
28 files changed, 3431 insertions(+)
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/ConfigBlock/FlashProtectionConfig.h b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/ConfigBlock/FlashProtectionConfig.h
new file mode 100644
index 0000000000..d1e10c3422
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/ConfigBlock/FlashProtectionConfig.h
@@ -0,0 +1,55 @@
+/** @file
+ FlashProtection policy
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _FLASH_PROTECTION_CONFIG_H_
+#define _FLASH_PROTECTION_CONFIG_H_
+
+#define FLASH_PROTECTION_CONFIG_REVISION 1
+extern EFI_GUID gFlashProtectionConfigGuid;
+
+#pragma pack (push,1)
+
+//
+// Flash Protection Range Register
+//
+#define PCH_FLASH_PROTECTED_RANGES 5
+
+/**
+ Protected Flash Range
+**/
+typedef struct {
+ UINT32 WriteProtectionEnable : 1; ///< Write or erase is blocked by hardware. <b>0: Disable</b>; 1: Enable.
+ UINT32 ReadProtectionEnable : 1; ///< Read is blocked by hardware. <b>0: Disable</b>; 1: Enable.
+ UINT32 RsvdBits : 30; ///< Reserved
+ /**
+ The address of the upper limit of protection
+ This is a left shifted address by 12 bits with address bits 11:0 are assumed to be FFFh for limit comparison
+ **/
+ UINT16 ProtectedRangeLimit;
+ /**
+ The address of the upper limit of protection
+ This is a left shifted address by 12 bits with address bits 11:0 are assumed to be 0
+ **/
+ UINT16 ProtectedRangeBase;
+} PROTECTED_RANGE;
+
+/**
+ The PCH provides a method for blocking writes and reads to specific ranges
+ in the SPI flash when the Protected Ranges are enabled.
+ PROTECTED_RANGE is used to specify if flash protection are enabled,
+ the write protection enable bit and the read protection enable bit,
+ and to specify the upper limit and lower base for each register
+ Platform code is responsible to get the range base by PchGetSpiRegionAddresses routine,
+ and set the limit and base accordingly.
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ PROTECTED_RANGE ProtectRange[PCH_FLASH_PROTECTED_RANGES]; ///< Protected Flash Ranges
+} PCH_FLASH_PROTECTION_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _FLASH_PROTECTION_CONFIG_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/ConfigBlock/HsioConfig.h b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/ConfigBlock/HsioConfig.h
new file mode 100644
index 0000000000..ec27845a48
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/ConfigBlock/HsioConfig.h
@@ -0,0 +1,57 @@
+/** @file
+ HSIO policy
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _HSIO_CONFIG_H_
+#define _HSIO_CONFIG_H_
+#define HSIO_PREMEM_CONFIG_REVISION 1 //@deprecated
+extern EFI_GUID gHsioPreMemConfigGuid; //@deprecated
+
+#define HSIO_CONFIG_REVISION 1
+extern EFI_GUID gHsioConfigGuid;
+
+#pragma pack (push,1)
+
+/**
+ The PCH_HSIO_PREMEM_CONFIG block provides HSIO message related settings.
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+
+ /**
+ <b>(Test)</b>
+ 0- Disable, disable will prevent the HSIO version check and ChipsetInit HECI message from being sent
+ <b>1- Enable</b> ChipsetInit HECI message
+ **/
+ UINT8 ChipsetInitMessage;
+ /**
+ <b>(Test)</b>
+ <b>0- Disable</b>
+ 1- Enable When enabled, this is used to bypass the reset after ChipsetInit HECI message.
+ **/
+ UINT8 BypassPhySyncReset;
+ UINT8 RsvdBytes[2];
+
+} PCH_HSIO_PREMEM_CONFIG;
+
+
+/**
+ The PCH_HSIO_CONFIG block provides HSIO message related settings.
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ /**
+ Policy used to point to the Base (+ OEM) ChipsetInit binary used to sync between BIOS and CSME
+ **/
+ UINT32 ChipsetInitBinPtr;
+ /**
+ Policy used to indicate the size of the Base (+ OEM) ChipsetInit binary used to sync between BIOS and CSME
+ **/
+ UINT32 ChipsetInitBinLen;
+} PCH_HSIO_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _HSIO_CONFIG_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/ConfigBlock/HsioPcieConfig.h b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/ConfigBlock/HsioPcieConfig.h
new file mode 100644
index 0000000000..bc23f3e1a6
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/ConfigBlock/HsioPcieConfig.h
@@ -0,0 +1,58 @@
+/** @file
+ HSIO pcie policy
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _HSIO_PCIE_CONFIG_H_
+#define _HSIO_PCIE_CONFIG_H_
+
+#include <PchLimits.h>
+
+#define HSIO_PCIE_PREMEM_CONFIG_REVISION 1
+extern EFI_GUID gHsioPciePreMemConfigGuid;
+
+#pragma pack (push,1)
+
+/**
+ The PCH_HSIO_PCIE_LANE_CONFIG describes HSIO settings for PCIe lane
+**/
+typedef struct {
+ //
+ // HSIO Rx Eq
+ // Refer to the EDS for recommended values.
+ // Note that these setting are per-lane and not per-port
+ //
+ UINT32 HsioRxSetCtleEnable : 1; ///< <b>0: Disable</b>; 1: Enable PCH PCIe Gen 3 Set CTLE Value
+ UINT32 HsioRxSetCtle : 6; ///< PCH PCIe Gen 3 Set CTLE Value
+ UINT32 HsioTxGen1DownscaleAmpEnable : 1; ///< <b>0: Disable</b>; 1: Enable PCH PCIe Gen 1 TX Output Downscale Amplitude Adjustment value override
+ UINT32 HsioTxGen1DownscaleAmp : 6; ///< PCH PCIe Gen 1 TX Output Downscale Amplitude Adjustment value
+ UINT32 HsioTxGen2DownscaleAmpEnable : 1; ///< <b>0: Disable</b>; 1: Enable PCH PCIe Gen 2 TX Output Downscale Amplitude Adjustment value override
+ UINT32 HsioTxGen2DownscaleAmp : 6; ///< PCH PCIe Gen 2 TX Output Downscale Amplitude Adjustment value
+ UINT32 HsioTxGen3DownscaleAmpEnable : 1; ///< <b>0: Disable</b>; 1: Enable PCH PCIe Gen 3 TX Output Downscale Amplitude Adjustment value override
+ UINT32 HsioTxGen3DownscaleAmp : 6; ///< PCH PCIe Gen 3 TX Output Downscale Amplitude Adjustment value
+ UINT32 RsvdBits0 : 4; ///< Reserved Bits
+
+ UINT32 HsioTxGen1DeEmphEnable : 1; ///< <b>0: Disable</b>; 1: Enable PCH PCIe Gen 1 TX Output De-Emphasis Adjustment Setting value override
+ UINT32 HsioTxGen1DeEmph : 6; ///< PCH PCIe Gen 1 TX Output De-Emphasis Adjustment Setting
+ UINT32 HsioTxGen2DeEmph3p5Enable : 1; ///< <b>0: Disable</b>; 1: Enable PCH PCIe Gen 2 TX Output -3.5dB Mode De-Emphasis Adjustment Setting value override
+ UINT32 HsioTxGen2DeEmph3p5 : 6; ///< PCH PCIe Gen 2 TX Output -3.5dB Mode De-Emphasis Adjustment Setting
+ UINT32 HsioTxGen2DeEmph6p0Enable : 1; ///< <b>0: Disable</b>; 1: Enable PCH PCIe Gen 2 TX Output -6.0dB Mode De-Emphasis Adjustment Setting value override
+ UINT32 HsioTxGen2DeEmph6p0 : 6; ///< PCH PCIe Gen 2 TX Output -6.0dB Mode De-Emphasis Adjustment Setting
+ UINT32 RsvdBits1 : 11; ///< Reserved Bits
+} PCH_HSIO_PCIE_LANE_CONFIG;
+
+///
+/// The PCH_HSIO_PCIE_CONFIG block describes the configuration of the HSIO for PCIe lanes
+///
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ ///
+ /// These members describe the configuration of HSIO for PCIe lanes.
+ ///
+ PCH_HSIO_PCIE_LANE_CONFIG Lane[PCH_MAX_PCIE_ROOT_PORTS];
+} PCH_HSIO_PCIE_PREMEM_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _HSIO_PCIE_LANE_CONFIG_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/ConfigBlock/HsioSataConfig.h b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/ConfigBlock/HsioSataConfig.h
new file mode 100644
index 0000000000..21b0d7ff63
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/ConfigBlock/HsioSataConfig.h
@@ -0,0 +1,64 @@
+/** @file
+ Hsio Sata policy
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _HSIO_SATA_CONFIG_H_
+#define _HSIO_SATA_CONFIG_H_
+
+#define HSIO_SATA_PREMEM_CONFIG_REVISION 1
+extern EFI_GUID gHsioSataPreMemConfigGuid;
+
+#pragma pack (push,1)
+
+/**
+ The PCH_HSIO_SATA_PORT_LANE describes HSIO settings for SATA Port lane
+**/
+typedef struct {
+ //
+ // HSIO Rx Eq
+ //
+ UINT32 HsioRxGen1EqBoostMagEnable : 1; ///< <b>0: Disable</b>; 1: Enable Receiver Equalization Boost Magnitude Adjustment Value override
+ UINT32 HsioRxGen1EqBoostMag : 6; ///< SATA 1.5 Gb/sReceiver Equalization Boost Magnitude Adjustment value
+ UINT32 HsioRxGen2EqBoostMagEnable : 1; ///< <b>0: Disable</b>; 1: Enable Receiver Equalization Boost Magnitude Adjustment Value override
+ UINT32 HsioRxGen2EqBoostMag : 6; ///< SATA 3.0 Gb/sReceiver Equalization Boost Magnitude Adjustment value
+ UINT32 HsioRxGen3EqBoostMagEnable : 1; ///< <b>0: Disable</b>; 1: Enable Receiver Equalization Boost Magnitude Adjustment Value override
+ UINT32 HsioRxGen3EqBoostMag : 6; ///< SATA 6.0 Gb/sReceiver Equalization Boost Magnitude Adjustment value
+ //
+ // HSIO Tx Eq
+ //
+ UINT32 HsioTxGen1DownscaleAmpEnable : 1; ///< <b>0: Disable</b>; 1: Enable SATA 1.5 Gb/s TX Output Downscale Amplitude Adjustment value override
+ UINT32 HsioTxGen1DownscaleAmp : 6; ///< SATA 1.5 Gb/s TX Output Downscale Amplitude Adjustment value
+ UINT32 RsvdBits0 : 4; ///< Reserved bits
+
+ UINT32 HsioTxGen2DownscaleAmpEnable : 1; ///< <b>0: Disable</b>; 1: Enable SATA 3.0 Gb/s TX Output Downscale Amplitude Adjustment value override
+ UINT32 HsioTxGen2DownscaleAmp : 6; ///< SATA 3.0 Gb/s TX Output Downscale Amplitude Adjustment
+ UINT32 HsioTxGen3DownscaleAmpEnable : 1; ///< <b>0: Disable</b>; 1: Enable SATA 6.0 Gb/s TX Output Downscale Amplitude Adjustment value override
+ UINT32 HsioTxGen3DownscaleAmp : 6; ///< SATA 6.0 Gb/s TX Output Downscale Amplitude Adjustment
+ UINT32 HsioTxGen1DeEmphEnable : 1; ///< <b>0: Disable</b>; 1: Enable SATA 1.5 Gb/s TX Output De-Emphasis Adjustment Setting value override
+ UINT32 HsioTxGen1DeEmph : 6; ///< SATA 1.5 Gb/s TX Output De-Emphasis Adjustment Setting
+
+ UINT32 HsioTxGen2DeEmphEnable : 1; ///< <b>0: Disable</b>; 1: Enable SATA 3.0 Gb/s TX Output De-Emphasis Adjustment Setting value override
+ UINT32 HsioTxGen2DeEmph : 6; ///< SATA 3.0 Gb/s TX Output De-Emphasis Adjustment Setting
+ UINT32 RsvdBits1 : 4; ///< Reserved bits
+
+ UINT32 HsioTxGen3DeEmphEnable : 1; ///< <b>0: Disable</b>; 1: Enable SATA 6.0 Gb/s TX Output De-Emphasis Adjustment Setting value override
+ UINT32 HsioTxGen3DeEmph : 6; ///< SATA 6.0 Gb/s TX Output De-Emphasis Adjustment Setting value override
+ UINT32 RsvdBits2 : 25; ///< Reserved bits
+} PCH_HSIO_SATA_PORT_LANE;
+
+///
+/// The PCH_HSIO_SATA_CONFIG block describes the HSIO configuration of the SATA controller.
+///
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ ///
+ /// These members describe the configuration of HSIO for SATA lanes.
+ ///
+ PCH_HSIO_SATA_PORT_LANE PortLane[PCH_MAX_SATA_PORTS];
+} PCH_HSIO_SATA_PREMEM_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _HSIO_SATA_CONFIG_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/ConfigBlock/LockDownConfig.h b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/ConfigBlock/LockDownConfig.h
new file mode 100644
index 0000000000..23f116cf3d
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/ConfigBlock/LockDownConfig.h
@@ -0,0 +1,61 @@
+/** @file
+ Lock down policy
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _LOCK_DOWN_CONFIG_H_
+#define _LOCK_DOWN_CONFIG_H_
+
+#define LOCK_DOWN_CONFIG_REVISION 1
+extern EFI_GUID gLockDownConfigGuid;
+
+#pragma pack (push,1)
+
+/**
+ The PCH_LOCK_DOWN_CONFIG block describes the expected configuration of the PCH
+ for security requirement.
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ /**
+ <b>(Test)</b> Enable SMI_LOCK bit to prevent writes to the Global SMI Enable bit. 0: Disable; <b>1: Enable</b>.
+ **/
+ UINT32 GlobalSmi : 1;
+ /**
+ <b>(Test)</b> Enable BIOS Interface Lock Down bit to prevent writes to the Backup Control Register
+ Top Swap bit and the General Control and Status Registers Boot BIOS Straps.
+ 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 with its own code.
+ 0: Disable; <b>1: Enable</b>.
+ **/
+ UINT32 BiosInterface : 1;
+ /**
+ Enable the BIOS Lock Enable (BLE) feature and set EISS bit (D31:F5:RegDCh[5])
+ for the BIOS region protection. When it is enabled, the BIOS Region can only be
+ modified from SMM.
+ If this EISS bit is set, then WPD must be a '1' and InSMM.STS must be '1' also
+ in order to write to BIOS regions of SPI Flash. If this EISS bit is clear,
+ then the InSMM.STS is a don't care.
+ The BIOS must set the EISS bit while BIOS Guard support is enabled.
+ In recovery path, platform can temporary disable EISS for SPI programming in
+ PEI phase or early DXE phase.
+ When PcdSmmVariableEnable is FALSE, to support BIOS regions update outside of SMM,
+ the BiosLock must be set to Disabled by platform.
+ 0: Disable; <b>1: Enable.</b>
+ **/
+ UINT32 BiosLock : 1;
+ /**
+ <b>(Test)</b> This test option when set will force all GPIO pads to be unlocked
+ before BIOS transitions to POSTBOOT_SAI. This option should not be enabled in production
+ configuration and used only for debug purpose when free runtime reconfiguration of
+ GPIO pads is needed.
+ <b>0: Disable</b>; 1: Enable.
+ **/
+ UINT32 UnlockGpioPads : 1;
+ UINT32 RsvdBits0 : 28; ///< Reserved bits
+} PCH_LOCK_DOWN_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _LOCK_DOWN_CONFIG_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/ConfigBlock/LpcConfig.h b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/ConfigBlock/LpcConfig.h
new file mode 100644
index 0000000000..3fc64aa056
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/ConfigBlock/LpcConfig.h
@@ -0,0 +1,38 @@
+/** @file
+ Lpc policy
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _LPC_CONFIG_H_
+#define _LPC_CONFIG_H_
+
+#define LPC_PREMEM_CONFIG_REVISION 1
+extern EFI_GUID gLpcPreMemConfigGuid;
+
+#pragma pack (push,1)
+
+/**
+ This structure contains the policies which are related to LPC.
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ /**
+ Enhance the port 8xh decoding.
+ Original LPC only decodes one byte of port 80h, with this enhancement LPC can decode word or dword of port 80h-83h.
+ @note: this will occupy one LPC generic IO range register. While this is enabled, read from port 80h always return 0x00.
+ 0: Disable, <b>1: Enable</b>
+ **/
+ UINT32 EnhancePort8xhDecoding : 1;
+ /**
+ Hardware Autonomous Enable.
+ When enabled, LPC will automatically engage power gating when it has reached its idle condition.
+ 0: Disable, <b>1: Enable</b>
+ **/
+ UINT32 LpcPmHAE : 1;
+ UINT32 RsvdBits : 30; ///< Reserved bits
+} PCH_LPC_PREMEM_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _LPC_CONFIG_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/ConfigBlock/PchGeneralConfig.h b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/ConfigBlock/PchGeneralConfig.h
new file mode 100644
index 0000000000..da77abc1b3
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/ConfigBlock/PchGeneralConfig.h
@@ -0,0 +1,72 @@
+/** @file
+ PCH General policy
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PCH_GENERAL_CONFIG_H_
+#define _PCH_GENERAL_CONFIG_H_
+
+#define PCH_GENERAL_CONFIG_REVISION 1
+#define PCH_GENERAL_PREMEM_CONFIG_REVISION 2
+
+extern EFI_GUID gPchGeneralConfigGuid;
+extern EFI_GUID gPchGeneralPreMemConfigGuid;
+
+#pragma pack (push,1)
+
+enum PCH_RESERVED_PAGE_ROUTE {
+ PchReservedPageToLpc, ///< Port 80h cycles are sent to LPC.
+ PchReservedPageToPcie ///< Port 80h cycles are sent to PCIe.
+};
+
+/**
+ PCH General Configuration
+ <b>Revision 1</b>: - Initial version.
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ /**
+ This member describes whether or not the Compatibility Revision ID (CRID) feature
+ of PCH should be enabled. <b>0: Disable</b>; 1: Enable
+ **/
+ UINT32 Crid : 1;
+ /**
+ Set to enable low latency of legacy IO.
+ Some systems require lower IO latency irrespective of power.
+ This is a tradeoff between power and IO latency.
+ @note: Once this is enabled, DmiAspm, Pcie DmiAspm in SystemAgent
+ and ITSS Clock Gating are forced to disabled.
+ <b>0: Disable</b>, 1: Enable
+ **/
+ UINT32 LegacyIoLowLatency : 1;
+ UINT32 RsvdBits0 : 30; ///< Reserved bits
+} PCH_GENERAL_CONFIG;
+
+/**
+ PCH General Pre-Memory Configuration
+ <b>Revision 1</b>: - Initial version.
+ <b>Revision 2</b>: - Added GpioOverride.
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Config Block Header
+ /**
+ Control where the Port 80h cycles are sent, <b>0: LPC</b>; 1: PCI.
+ **/
+ UINT32 Port80Route : 1;
+ UINT32 IotgPllSscEn : 1; ///< Need to disable CPU Side SSC for A0 PO
+ /**
+ Gpio override Level
+ -- <b>0: Disable</b>;
+ - 1: Override Level 1 - only skips GpioSetNativePadByFunction
+ - 2: Override Level 2 - skips GpioSetNativePadByFunction and GpioSetPadMode
+ Additional policy that allows GPIO configuration to be done by external means.
+ If equal to 1 PCH will skip every Pad configuration.
+ **/
+ UINT32 GpioOverride : 3;
+ UINT32 RsvdBits0 : 27; ///< Reserved bits
+} PCH_GENERAL_PREMEM_CONFIG;
+
+#pragma pack (pop)
+
+#endif // _PCH_GENERAL_CONFIG_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/Library/PchCycleDecodingLib.h b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/Library/PchCycleDecodingLib.h
new file mode 100644
index 0000000000..94509a80fe
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/Library/PchCycleDecodingLib.h
@@ -0,0 +1,258 @@
+/** @file
+ Header file for PchCycleDecodingLib.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PCH_CYCLE_DECODING_LIB_H_
+#define _PCH_CYCLE_DECODING_LIB_H_
+
+
+/**
+ Get PCH TCO base address.
+
+ @param[out] Address Address of TCO base address.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid pointer passed.
+**/
+EFI_STATUS
+PchTcoBaseGet (
+ OUT UINT16 *Address
+ );
+
+///
+/// structure of LPC general IO range register
+/// It contains base address, address mask, and enable status.
+///
+typedef struct {
+ UINT32 BaseAddr :16;
+ UINT32 Length :15;
+ UINT32 Enable : 1;
+} PCH_LPC_GEN_IO_RANGE;
+
+#define PCH_LPC_GEN_IO_RANGE_MAX 4
+#define ESPI_CS1_GEN_IO_RANGE_MAX 1
+
+///
+/// structure of LPC general IO range register list
+/// It lists all LPC general IO ran registers supported by PCH.
+///
+typedef struct {
+ PCH_LPC_GEN_IO_RANGE Range[PCH_LPC_GEN_IO_RANGE_MAX];
+} PCH_LPC_GEN_IO_RANGE_LIST;
+
+/**
+ Set PCH LPC/eSPI generic IO range.
+ For generic IO range, the base address must align to 4 and less than 0xFFFF, and the length must be power of 2
+ and less than or equal to 256. Moreover, the address must be length aligned.
+ This function basically checks the address and length, which should not overlap with all other generic ranges.
+ If no more generic range register available, it returns out of resource error.
+ This cycle decoding is also required on DMI side.
+ Some IO ranges below 0x100 have fixed target. The target might be ITSS,RTC,LPC,PMC or terminated inside P2SB
+ but all predefined and can't be changed. IO range below 0x100 will be rejected in this function except below ranges:
+ 0x00-0x1F,
+ 0x44-0x4B,
+ 0x54-0x5F,
+ 0x68-0x6F,
+ 0x80-0x8F,
+ 0xC0-0xFF
+ Steps of programming generic IO range:
+ 1. Program LPC/eSPI PCI Offset 84h ~ 93h of Mask, Address, and Enable.
+ 2. Program LPC/eSPI Generic IO Range in DMI
+
+ @param[in] Address Address for generic IO range base address.
+ @param[in] Length Length of generic IO range.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid base address or length passed.
+ @retval EFI_OUT_OF_RESOURCES No more generic range available.
+ @retval EFI_UNSUPPORTED DMIC.SRL is set.
+**/
+EFI_STATUS
+PchLpcGenIoRangeSet (
+ IN UINT16 Address,
+ IN UINTN Length
+ );
+
+/**
+ Set PCH LPC/eSPI memory range decoding.
+ This cycle decoding is required to be set on DMI side
+ Programming steps:
+ 1. Program LPC PCI Offset 98h [0] to [0] to disable memory decoding first before changing base address.
+ 2. Program LPC PCI Offset 98h [31:16, 0] to [Address, 1].
+ 3. Program LPC Memory Range in DMI
+
+ @param[in] Address Address for memory base address.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid base address or length passed.
+ @retval EFI_OUT_OF_RESOURCES No more generic range available.
+ @retval EFI_UNSUPPORTED DMIC.SRL is set.
+**/
+EFI_STATUS
+PchLpcMemRangeSet (
+ IN UINT32 Address
+ );
+
+/**
+ Set PCH eSPI CS1# memory range decoding.
+ This cycle decoding is required to be set on DMI side
+ Programming steps:
+ 1. Program eSPI PCI Offset A8h (eSPI CS1#) [0] to [0] to disable memory decoding first before changing base address.
+ 2. Program eSPI PCI Offset A8h (eSPI CS1#) [31:16, 0] to [Address, 1].
+ 3. Program eSPI Memory Range in DMI
+
+ @param[in] Address Address for memory for decoding.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid base address or length passed.
+ @retval EFI_UNSUPPORTED eSPI secondary slave not supported
+**/
+EFI_STATUS
+PchEspiCs1MemRangeSet (
+ IN UINT32 Address
+ );
+
+/**
+ Get PCH LPC/eSPI memory range decoding address.
+
+ @param[out] Address Address of LPC/eSPI memory decoding base address.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid base address passed.
+**/
+EFI_STATUS
+PchLpcMemRangeGet (
+ OUT UINT32 *Address
+ );
+
+/**
+ Get PCH eSPI CS1# memory range decoding address.
+
+ @param[out] Address Address of eSPI CS1# memory decoding base address.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid base address passed.
+ @retval EFI_UNSUPPORTED eSPI secondary slave not supported
+**/
+EFI_STATUS
+PchEspiCs1MemRangeGet (
+ OUT UINT32 *Address
+ );
+
+/**
+ 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 PCI offset D8h to BiosDecodeEnable.
+ if GCS.BBS is 1 (LPC/eSPi), program LPC/eSPI PCI offset D8h to BiosDecodeEnable.
+ 2. program LPC/eSPI/SPI BIOS Decode Enable, PCR[DMI] + 2744h to the same value programmed in LPC/eSPI or SPI PCI Offset D8h.
+
+ @param[in] BiosDecodeEnable Bios decode enable setting.
+
+ @retval EFI_SUCCESS Successfully completed.
+**/
+EFI_STATUS
+PchBiosDecodeEnableSet (
+ IN UINT16 BiosDecodeEnable
+ );
+
+/**
+ Set PCH LPC IO decode ranges.
+ Program LPC I/O Decode Ranges, PCR[DMI] + 2770h[15:0] to the same value programmed in LPC offset 80h.
+ Please check EDS for detail of Lpc 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 IO decode ranges bit settings.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_UNSUPPORTED DMIC.SRL is set.
+**/
+EFI_STATUS
+PchLpcIoDecodeRangesSet (
+ IN UINT16 LpcIoDecodeRanges
+ );
+
+/**
+ Set PCH LPC and eSPI CS0# IO enable decoding.
+ Setup I/O Enables in DMI 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 IO enable decoding bit settings.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_UNSUPPORTED DMIC.SRL is set.
+**/
+EFI_STATUS
+PchLpcIoEnableDecodingSet (
+ IN UINT16 LpcIoEnableDecoding
+ );
+
+/**
+ Set PCH eSPI CS1# IO enable decoding.
+ Setup I/O Enables in DMI to the same value program in eSPI PCI offset A0h (eSPI CS1#).
+ Note: Bit[15:10] of the source decode register is Read-Only. The IO range indicated by the Enables field
+ in eSPI PCI offset A0h[13:10] is always forwarded by DMI to subtractive agent for handling.
+ Please check EDS for detail of eSPI IO decode ranges bit definition.
+
+ @param[in] IoEnableDecoding eSPI IO enable decoding bit settings.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_UNSUPPORTED DMI configuration is locked
+**/
+EFI_STATUS
+PchEspiCs1IoEnableDecodingSet (
+ IN UINT16 IoEnableDecoding
+ );
+
+/**
+ Get IO APIC regsiters base address.
+
+ @param[out] IoApicBase Buffer of IO APIC regsiter address
+
+ @retval EFI_SUCCESS Successfully completed.
+**/
+EFI_STATUS
+PchIoApicBaseGet (
+ OUT UINT32 *IoApicBase
+ );
+
+/**
+ Get HPET base address.
+ This function will be unavailable after P2SB is hidden by PSF.
+
+ @param[out] HpetBase Buffer of HPET base address
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchHpetBaseGet (
+ OUT UINT32 *HpetBase
+ );
+
+#endif // _PCH_CYCLE_DECODING_LIB_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/Library/PchInfoLib.h b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/Library/PchInfoLib.h
new file mode 100644
index 0000000000..c8aee81a8b
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/Library/PchInfoLib.h
@@ -0,0 +1,590 @@
+/** @file
+ Header file for PchInfoLib.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PCH_INFO_LIB_H_
+#define _PCH_INFO_LIB_H_
+
+#include <Hda.h>
+#include <Uefi/UefiBaseType.h>
+
+typedef UINT8 PCH_STEPPING;
+
+typedef UINT8 PCH_SERIES;
+#define PCH_LP 2
+
+typedef UINT8 PCH_GENERATION;
+#define TGL_PCH 5
+
+typedef enum {
+ RstUnsupported = 0,
+ RstPremium,
+ RstOptane,
+ RstMaxMode
+} RST_MODE;
+
+/**
+ Return Pch stepping type
+
+ @retval PCH_STEPPING Pch stepping type
+**/
+PCH_STEPPING
+PchStepping (
+ VOID
+ );
+
+/**
+ Return Pch Series
+
+ @retval PCH_SERIES Pch Series
+**/
+PCH_SERIES
+PchSeries (
+ VOID
+ );
+
+/**
+ Return Pch Generation
+
+ @retval PCH_GENERATION Pch Generation
+**/
+PCH_GENERATION
+PchGeneration (
+ VOID
+ );
+
+/**
+ Check if this is TGL PCH generation
+
+ @retval TRUE It's TGL PCH
+ @retval FALSE It's not TGL PCH
+**/
+BOOLEAN
+IsTglPch (
+ VOID
+ );
+
+/**
+ Get Pch Maximum Pcie Root Port Number
+
+ @retval PcieMaxRootPort Pch Maximum Pcie Root Port Number
+**/
+UINT8
+GetPchMaxPciePortNum (
+ VOID
+ );
+
+/**
+ Get Pch Maximum Pcie Controller Number
+
+ @retval Pch Maximum Pcie Controller Number
+**/
+UINT8
+GetPchMaxPcieControllerNum (
+ VOID
+ );
+
+/**
+ Get Pch Maximum Pcie Clock Number
+
+ @retval Pch Maximum Pcie Clock Number
+**/
+UINT8
+GetPchMaxPcieClockNum (
+ VOID
+ );
+
+/**
+ Get Pch Maximum Pcie ClockReq Number
+
+ @retval Pch Maximum Pcie ClockReq Number
+**/
+UINT8
+GetPchMaxPcieClockReqNum (
+ VOID
+ );
+
+/**
+ Get Pch Usb2 Maximum Physical Port Number
+
+ @retval Pch Usb2 Maximum Physical Port Number
+**/
+UINT8
+GetPchUsb2MaxPhysicalPortNum (
+ VOID
+ );
+
+/**
+ Get Pch Maximum Usb2 Port Number of XHCI Controller
+
+ @retval Pch Maximum Usb2 Port Number of XHCI Controller
+**/
+UINT8
+GetPchXhciMaxUsb2PortNum (
+ VOID
+ );
+
+/**
+ Get Pch Usb3 Maximum Physical Port Number
+
+ @retval Pch Usb3 Maximum Physical Port Number
+**/
+UINT8
+GetPchUsb3MaxPhysicalPortNum (
+ VOID
+ );
+
+/**
+ Get Pch Maximum Usb3 Port Number of XHCI Controller
+
+ @retval Pch Maximum Usb3 Port Number of XHCI Controller
+**/
+UINT8
+GetPchXhciMaxUsb3PortNum (
+ VOID
+ );
+
+/**
+ Get Pch Maximum Serial IO I2C controllers number
+
+ @retval Pch Maximum Serial IO I2C controllers number
+**/
+UINT8
+GetPchMaxSerialIoI2cControllersNum (
+ VOID
+ );
+
+/**
+ Get Pch Maximum Serial IO SPI controllers number
+
+ @retval Pch Maximum Serial IO SPI controllers number
+**/
+UINT8
+GetPchMaxSerialIoSpiControllersNum (
+ VOID
+ );
+
+/**
+ Get Pch Maximum Serial IO UART controllers number
+
+ @retval Pch Maximum Serial IO UART controllers number
+**/
+UINT8
+GetPchMaxSerialIoUartControllersNum (
+ VOID
+ );
+
+/**
+ Get Pch Maximum Serial IO SPI Chip Selects count
+
+ @retval Pch Maximum Serial IO SPI Chip Selects nu,ber
+**/
+UINT8
+GetPchMaxSerialIoSpiChipSelectsNum (
+ VOID
+ );
+
+/**
+ Get Pch Maximum ISH UART Controller number
+
+ @retval Pch Maximum ISH UART controllers number
+**/
+UINT8
+GetPchMaxIshUartControllersNum (
+ VOID
+ );
+
+/**
+ Get Pch Maximum ISH I2C Controller number
+
+ @retval Pch Maximum ISH I2C controllers number
+**/
+UINT8
+GetPchMaxIshI2cControllersNum (
+ VOID
+ );
+
+/**
+ Get Pch Maximum ISH I3C Controller number
+
+ @retval Pch Maximum ISH I3C controllers number
+**/
+UINT8
+GetPchMaxIshI3cControllersNum (
+ VOID
+ );
+
+/**
+ Get Pch Maximum ISH SPI Controller number
+
+ @retval Pch Maximum ISH SPI controllers number
+**/
+UINT8
+GetPchMaxIshSpiControllersNum (
+ VOID
+ );
+
+/**
+ Get Pch Maximum ISH SPI Controller Cs pins number
+
+ @retval Pch Maximum ISH SPI controller Cs pins number
+**/
+UINT8
+GetPchMaxIshSpiControllerCsPinsNum (
+ VOID
+ );
+
+/**
+ Get Pch Maximum ISH GP number
+
+ @retval Pch Maximum ISH GP number
+**/
+UINT8
+GetPchMaxIshGpNum (
+ VOID
+ );
+
+/**
+ Get Pch Maximum ME Applet count
+
+ @retval Pch Maximum ME Applet number
+**/
+UINT8
+GetPchMaxMeAppletCount (
+ VOID
+ );
+
+/**
+Get Pch Maximum ME Session count
+
+@retval Pch Maximum ME Sesion number
+**/
+UINT8
+GetPchMaxMeSessionCount(
+ VOID
+);
+
+/**
+ Get Pch Maximum Type C Port Number
+
+ @retval Pch Maximum Type C Port Number
+**/
+UINT8
+GetPchMaxTypeCPortNum (
+ VOID
+ );
+
+#define PCH_STEPPING_STR_LENGTH_MAX 3
+
+/**
+ Get PCH stepping ASCII string.
+ Function determines major and minor stepping versions and writes them into a buffer.
+ The return string is zero terminated
+
+ @param [out] Buffer Output buffer of string
+ @param [in] BufferSize Buffer size.
+ Must not be less then PCH_STEPPING_STR_LENGTH_MAX
+
+ @retval EFI_SUCCESS String copied successfully
+ @retval EFI_INVALID_PARAMETER The stepping is not supported, or parameters are NULL
+ @retval EFI_BUFFER_TOO_SMALL Input buffer size is too small
+**/
+EFI_STATUS
+PchGetSteppingStr (
+ OUT CHAR8 *Buffer,
+ IN UINT32 BufferSize
+ );
+
+/**
+ Get PCH series ASCII string.
+ The return string is zero terminated.
+
+ @retval Static ASCII string of PCH Series
+**/
+CHAR8*
+PchGetSeriesStr (
+ );
+
+/**
+ Check if this chipset supports eMMC controller
+
+ @retval BOOLEAN TRUE if supported, FALSE otherwise
+**/
+BOOLEAN
+IsPchEmmcSupported (
+ VOID
+ );
+
+/**
+ Check if this chipset supports SD controller
+
+ @retval BOOLEAN TRUE if supported, FALSE otherwise
+**/
+BOOLEAN
+IsPchSdCardSupported (
+ VOID
+ );
+
+/**
+ Check if this chipset supports THC controller
+
+ @retval BOOLEAN TRUE if supported, FALSE otherwise
+**/
+BOOLEAN
+IsPchThcSupported (
+ VOID
+ );
+
+/**
+ Check if this chipset supports HSIO BIOS Sync
+
+ @retval BOOLEAN TRUE if supported, FALSE otherwise
+**/
+BOOLEAN
+IsPchChipsetInitSyncSupported (
+ VOID
+ );
+
+/**
+ Gets the maximum number of UFS controller supported by this chipset.
+
+ @return Number of supported UFS controllers
+**/
+UINT8
+PchGetMaxUfsNum (
+ VOID
+ );
+
+/**
+ Check whether integrated LAN controller is supported.
+
+ @retval TRUE GbE is supported in PCH
+ @retval FALSE GbE is not supported by PCH
+**/
+BOOLEAN
+PchIsGbeSupported (
+ VOID
+ );
+
+/**
+ Check whether integrated TSN is supported.
+
+ @retval TRUE TSN is supported in current PCH
+ @retval FALSE TSN is not supported on current PCH
+**/
+BOOLEAN
+PchIsTsnSupported (
+ VOID
+ );
+
+/**
+ Check whether ISH is supported.
+
+ @retval TRUE ISH is supported in PCH
+ @retval FALSE ISH is not supported by PCH
+**/
+BOOLEAN
+PchIsIshSupported (
+ VOID
+ );
+
+/**
+ Check whether ATX Shutdown (PS_ON) is supported.
+
+ @retval TRUE ATX Shutdown (PS_ON) is supported in PCH
+ @retval FALSE ATX Shutdown (PS_ON) is not supported by PCH
+**/
+BOOLEAN
+IsPchPSOnSupported (
+ VOID
+ );
+
+/**
+ Get Pch Maximum Hda Sndw Link
+
+ @retval Pch Maximum Hda Sndw Link
+**/
+UINT8
+GetPchHdaMaxSndwLinkNum (
+ VOID
+ );
+
+/**
+ Get Pch Maximum Hda Ssp Link
+
+ @retval Pch Maximum Hda Ssp Link
+**/
+UINT8
+GetPchHdaMaxSspLinkNum (
+ VOID
+ );
+
+/**
+ Get Pch Maximum Hda Dmic Link
+
+ @retval Pch Maximum Hda Dmic Link
+**/
+UINT8
+GetPchHdaMaxDmicLinkNum (
+ VOID
+ );
+
+/**
+ Check if given Audio Interface is supported
+
+ @param[in] AudioLinkType Link type support to be checked
+ @param[in] AudioLinkIndex Link number
+
+ @retval TRUE Link supported
+ @retval FALSE Link not supported
+**/
+BOOLEAN
+IsAudioInterfaceSupported (
+ IN HDAUDIO_LINK_TYPE AudioLinkType,
+ IN UINT32 AudioLinkIndex
+ );
+
+/**
+ Check if given Display Audio Link T-Mode is supported
+
+ @param[in] Tmode T-mode support to be checked
+
+ @retval TRUE T-mode supported
+ @retval FALSE T-mode not supported
+**/
+BOOLEAN
+IsAudioIDispTmodeSupported (
+ IN HDAUDIO_IDISP_TMODE Tmode
+ );
+
+/**
+ Check if link between PCH and CPU is an P-DMI
+
+ @retval TRUE P-DMI link
+ @retval FALSE Not an P-DMI link
+**/
+BOOLEAN
+IsPchWithPdmi (
+ VOID
+ );
+
+/**
+ Check if link between PCH and CPU is an OP-DMI
+
+ @retval TRUE OP-DMI link
+ @retval FALSE Not an OP-DMI link
+**/
+BOOLEAN
+IsPchWithOpdmi (
+ VOID
+ );
+
+/**
+ Check if link between PCH and CPU is an F-DMI
+
+ @retval TRUE F-DMI link
+ @retval FALSE Not an F-DMI link
+**/
+BOOLEAN
+IsPchWithFdmi (
+ VOID
+ );
+
+/**
+ Get Pch Maximum THC count
+
+ @retval Pch Maximum THC count number
+**/
+UINT8
+GetPchMaxThcCount (
+ VOID
+ );
+
+typedef enum {
+ SataSosc125Mhz = 0,
+ SataSosc120Mhz,
+ SataSosc100Mhz,
+ SataSosc25Mhz,
+ SataSosc19p2Mhz,
+ SataSoscUnsupported
+} SATA_SOSC_CLK_FREQ;
+
+/**
+ Returns a frequency of the sosc_clk signal.
+ All SATA controllers on the system are assumed to
+ work on the same sosc_clk frequency.
+
+ @retval Frequency of the sosc_clk signal.
+**/
+SATA_SOSC_CLK_FREQ
+GetSataSoscClkFreq (
+ VOID
+ );
+
+/**
+ Check if SATA support should be awake after function disable
+
+ @retval TRUE
+ @retval FALSE
+**/
+BOOLEAN
+IsSataSupportWakeAfterFunctionDisable (
+ VOID
+ );
+
+
+//
+// USB2 PHY reference frequencies values (MHz)
+//
+typedef enum {
+ FREQ_19_2 = 0u,
+ FREQ_24_0,
+ FREQ_96_0,
+ FREQ_MAX
+} USB2_PHY_REF_FREQ;
+
+/**
+ Returns USB2 PHY Reference Clock frequency value used by PCH
+ This defines what electrical tuning parameters shall be used
+ during USB2 PHY initialization programming
+
+ @retval Frequency reference clock for USB2 PHY
+**/
+USB2_PHY_REF_FREQ
+GetUsb2PhyRefFreq (
+ VOID
+ );
+
+/**
+ return support status for P2SB PCR 20-bit addressing
+
+ @retval TRUE
+ @retval FALSE
+**/
+BOOLEAN
+IsP2sb20bPcrSupported (
+ VOID
+ );
+
+/**
+ Check if SPI in a given PCH generation supports an Extended BIOS Range Decode
+
+ @retval TRUE or FALSE if PCH supports Extended BIOS Range Decode
+**/
+BOOLEAN
+IsExtendedBiosRangeDecodeSupported (
+ VOID
+ );
+
+/**
+ Returns DMI target for current PCH SPI
+
+ @retval PCH SPI DMI target
+**/
+UINT16
+GetPchSpiDmiTarget (
+ VOID
+ );
+#endif // _PCH_INFO_LIB_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/Library/PchPciBdfLib.h b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/Library/PchPciBdfLib.h
new file mode 100644
index 0000000000..85456653de
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/Library/PchPciBdfLib.h
@@ -0,0 +1,552 @@
+/** @file
+ Header file for PchPciBdfLib.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PCH_PCI_BDF_LIB_H_
+#define _PCH_PCI_BDF_LIB_H_
+
+
+/**
+ Get eSPI controller address that can be passed to the PCI Segment Library functions.
+
+ @retval eSPI controller address in PCI Segment Library representation
+**/
+UINT64
+EspiPciCfgBase (
+ VOID
+ );
+
+/**
+ Get GbE controller address that can be passed to the PCI Segment Library functions.
+
+ @retval GbE controller address in PCI Segment Library representation
+**/
+UINT64
+GbePciCfgBase (
+ VOID
+ );
+
+/**
+ Returns Gigabit Ethernet PCI Device Number
+
+ @retval GbE device number
+**/
+UINT8
+GbeDevNumber (
+ VOID
+ );
+
+/**
+ Returns Gigabit Ethernet PCI Function Number
+
+ @retval GbE function number
+**/
+UINT8
+GbeFuncNumber (
+ VOID
+ );
+
+/**
+ Get HDA controller address that can be passed to the PCI Segment Library functions.
+
+ @retval HDA controller address in PCI Segment Library representation
+**/
+UINT64
+HdaPciCfgBase (
+ VOID
+ );
+
+/**
+ Get HDA PCI device number
+
+ @retval PCI dev number
+**/
+UINT8
+HdaDevNumber (
+ VOID
+ );
+
+/**
+ Get HDA PCI function number
+
+ @retval PCI fun number
+**/
+UINT8
+HdaFuncNumber (
+ VOID
+ );
+
+
+/**
+ Get P2SB controller address that can be passed to the PCI Segment Library functions.
+
+ @retval P2SB controller address in PCI Segment Library representation
+**/
+UINT64
+P2sbPciCfgBase (
+ VOID
+ );
+
+/**
+ Get P2SB PCI device number
+
+ @retval PCI dev number
+**/
+UINT8
+P2sbDevNumber (
+ VOID
+ );
+
+/**
+ Returns SPI PCI Config Space base address
+
+ @retval UINT64 SPI Config Space base address
+**/
+UINT64
+SpiPciCfgBase (
+ VOID
+ );
+
+/**
+ Returns SPI Device number
+
+ @retval UINT8 PCH SPI Device number
+**/
+UINT8
+SpiDevNumber (
+ VOID
+ );
+
+/**
+ Returns SPI Function number
+
+ @retval UINT8 PCH SPI Function number
+**/
+UINT8
+SpiFuncNumber (
+ VOID
+ );
+
+/**
+ Get XHCI controller address that can be passed to the PCI Segment Library functions.
+
+ @retval XHCI controller address in PCI Segment Library representation
+**/
+UINT64
+PchXhciPciCfgBase (
+ VOID
+ );
+
+/**
+ Get XHCI controller PCIe Device Number
+
+ @retval XHCI controller PCIe Device Number
+**/
+UINT8
+PchXhciDevNumber (
+ VOID
+ );
+
+/**
+ Get XHCI controller PCIe Function Number
+
+ @retval XHCI controller PCIe Function Number
+**/
+UINT8
+PchXhciFuncNumber (
+ VOID
+ );
+
+/**
+ Get XDCI controller address that can be passed to the PCI Segment Library functions.
+
+ @retval XDCI controller address in PCI Segment Library representation
+**/
+UINT64
+PchXdciPciCfgBase (
+ VOID
+ );
+
+/**
+ Get XDCI controller PCIe Device Number
+
+ @retval XDCI controller PCIe Device Number
+**/
+UINT8
+PchXdciDevNumber (
+ VOID
+ );
+
+/**
+ Get XDCI controller PCIe Function Number
+
+ @retval XDCI controller PCIe Function Number
+**/
+UINT8
+PchXdciFuncNumber (
+ VOID
+ );
+
+/**
+ Get SMBUS controller address that can be passed to the PCI Segment Library functions.
+
+ @retval SMBUS controller address in PCI Segment Library representation
+**/
+UINT64
+SmbusPciCfgBase (
+ VOID
+ );
+
+/**
+ Return DMA Smbus Device Number
+
+ @retval DMA Smbus Device Number
+**/
+UINT8
+SmbusDmaDevNumber (
+ VOID
+ );
+
+/**
+ Return DMA Smbus Function Number
+
+ @retval DMA Smbus Function Number
+**/
+UINT8
+SmbusDmaFuncNumber (
+ VOID
+ );
+
+/**
+ Get DMA SMBUS controller address that can be passed to the PCI Segment Library functions.
+
+ @retval DMA SMBUS controller address in PCI Segment Library representation
+**/
+UINT64
+SmbusDmaPciCfgBase (
+ VOID
+ );
+
+/**
+ Return Smbus Device Number
+
+ @retval Smbus Device Number
+**/
+UINT8
+SmbusDevNumber (
+ VOID
+ );
+
+/**
+ Return Smbus Function Number
+
+ @retval Smbus Function Number
+**/
+UINT8
+SmbusFuncNumber (
+ VOID
+ );
+
+/**
+ Gets SATA controller PCIe config space base address
+
+ @param[in] SataCtrlIndex SATA controller index
+
+ @retval SATA controller PCIe config space base address
+**/
+UINT64
+SataPciCfgBase (
+ IN UINT32 SataCtrlIndex
+ );
+
+/**
+ Gets SATA controller PCIe Device Number
+
+ @param[in] SataCtrlIndex SATA controller index
+
+ @retval SATA controller PCIe Device Number
+**/
+UINT8
+SataDevNumber (
+ IN UINT32 SataCtrlIndex
+ );
+
+/**
+ Gets SATA controller PCIe Function Number
+
+ @param[in] SataCtrlIndex SATA controller index
+
+ @retval SATA controller PCIe Function Number
+**/
+UINT8
+SataFuncNumber (
+ IN UINT32 SataCtrlIndex
+ );
+
+/**
+ Returns PCH LPC device PCI base address.
+
+ @retval PCH LPC PCI base address.
+**/
+UINT64
+LpcPciCfgBase (
+ VOID
+ );
+
+/**
+ Get LPC controller PCIe Device Number
+
+ @retval LPC controller PCIe Device Number
+**/
+UINT8
+LpcDevNumber (
+ VOID
+ );
+
+/**
+ Get Thermal Device PCIe Device Number
+
+ @retval Thermal Device PCIe Device Number
+**/
+UINT8
+ThermalDevNumber (
+ VOID
+ );
+
+/**
+ Get Thermal Device PCIe Function Number
+
+ @retval Thermal Device PCIe Function Number
+**/
+UINT8
+ThermalFuncNumber (
+ VOID
+ );
+
+/**
+ Returns Thermal Device PCI base address.
+
+ @retval Thermal Device PCI base address.
+**/
+UINT64
+ThermalPciCfgBase (
+ VOID
+ );
+
+/**
+ Get LPC controller PCIe Function Number
+
+ @retval LPC controller PCIe Function Number
+**/
+UINT8
+LpcFuncNumber (
+ VOID
+ );
+
+/**
+ Get Serial IO I2C controller PCIe Device Number
+
+ @param[in] I2cNumber Serial IO I2C controller index
+
+ @retval Serial IO I2C controller PCIe Device Number
+**/
+UINT8
+SerialIoI2cDevNumber (
+ IN UINT8 I2cNumber
+ );
+
+/**
+ Get Serial IO I2C controller PCIe Function Number
+
+ @param[in] I2cNumber Serial IO I2C controller index
+
+ @retval Serial IO I2C controller PCIe Function Number
+**/
+UINT8
+SerialIoI2cFuncNumber (
+ IN UINT8 I2cNumber
+ );
+
+/**
+ Get Serial IO I2C controller address that can be passed to the PCI Segment Library functions.
+
+ @param[in] I2cNumber Serial IO I2C controller index
+
+ @retval Serial IO I2C controller address in PCI Segment Library representation
+**/
+UINT64
+SerialIoI2cPciCfgBase (
+ IN UINT8 I2cNumber
+ );
+
+/**
+ Get Serial IO SPI controller PCIe Device Number
+
+ @param[in] I2cNumber Serial IO SPI controller index
+
+ @retval Serial IO SPI controller PCIe Device Number
+**/
+UINT8
+SerialIoSpiDevNumber (
+ IN UINT8 SpiNumber
+ );
+
+/**
+ Get Serial IO SPI controller PCIe Function Number
+
+ @param[in] SpiNumber Serial IO SPI controller index
+
+ @retval Serial IO SPI controller PCIe Function Number
+**/
+UINT8
+SerialIoSpiFuncNumber (
+ IN UINT8 SpiNumber
+ );
+
+/**
+ Get Serial IO SPI controller address that can be passed to the PCI Segment Library functions.
+
+ @param[in] SpiNumber Serial IO SPI controller index
+
+ @retval Serial IO SPI controller address in PCI Segment Library representation
+**/
+UINT64
+SerialIoSpiPciCfgBase (
+ IN UINT8 SpiNumber
+ );
+
+/**
+ Get Serial IO UART controller PCIe Device Number
+
+ @param[in] UartNumber Serial IO UART controller index
+
+ @retval Serial IO UART controller PCIe Device Number
+**/
+UINT8
+SerialIoUartDevNumber (
+ IN UINT8 UartNumber
+ );
+
+/**
+ Get Serial IO UART controller PCIe Function Number
+
+ @param[in] UartNumber Serial IO UART controller index
+
+ @retval Serial IO UART controller PCIe Function Number
+**/
+UINT8
+SerialIoUartFuncNumber (
+ IN UINT8 UartNumber
+ );
+
+/**
+ Get Serial IO UART controller address that can be passed to the PCI Segment Library functions.
+
+ @param[in] UartNumber Serial IO UART controller index
+
+ @retval Serial IO UART controller address in PCI Segment Library representation
+**/
+UINT64
+SerialIoUartPciCfgBase (
+ IN UINT8 UartNumber
+ );
+
+/**
+ Get PCH PCIe controller PCIe Device Number
+
+ @param[in] RpIndex Root port physical number. (0-based)
+
+ @retval PCH PCIe controller PCIe Device Number
+**/
+UINT8
+PchPcieRpDevNumber (
+ IN UINTN RpIndex
+ );
+
+/**
+ Get PCH PCIe controller PCIe Function Number
+
+ @param[in] RpIndex Root port physical number. (0-based)
+
+ @retval PCH PCIe controller PCIe Function Number
+**/
+UINT8
+PchPcieRpFuncNumber (
+ IN UINTN RpIndex
+ );
+
+/**
+ Get PCH PCIe controller address that can be passed to the PCI Segment Library functions.
+
+ @param[in] RpIndex PCH PCIe Root Port physical number. (0-based)
+
+ @retval PCH PCIe controller address in PCI Segment Library representation
+**/
+UINT64
+PchPcieRpPciCfgBase (
+ IN UINT32 RpIndex
+ );
+
+/**
+ Get HECI1 PCI device number
+
+ @retval PCI dev number
+**/
+UINT8
+PchHeci1DevNumber (
+ VOID
+ );
+
+/**
+ Get HECI1 PCI function number
+
+ @retval PCI fun number
+**/
+UINT8
+PchHeci1FuncNumber (
+ VOID
+ );
+
+/**
+ Get HECI1 controller address that can be passed to the PCI Segment Library functions.
+
+ @retval HECI1 controller address in PCI Segment Library representation
+**/
+UINT64
+PchHeci1PciCfgBase (
+ VOID
+ );
+
+/**
+ Get HECI3 PCI device number
+
+ @retval PCI dev number
+**/
+UINT8
+PchHeci3DevNumber (
+ VOID
+ );
+
+/**
+ Get HECI3 PCI function number
+
+ @retval PCI fun number
+**/
+UINT8
+PchHeci3FuncNumber (
+ VOID
+ );
+
+/**
+ Get HECI3 controller address that can be passed to the PCI Segment Library functions.
+
+ @retval HECI3 controller address in PCI Segment Library representation
+**/
+UINT64
+PchHeci3PciCfgBase (
+ VOID
+ );
+
+#endif //_PCH_PCI_BDF_LIB_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/PchInfoHob.h b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/PchInfoHob.h
new file mode 100644
index 0000000000..845bb19a65
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/PchInfoHob.h
@@ -0,0 +1,70 @@
+/** @file
+ This file contains definitions of PCH Info HOB.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PCH_INFO_HOB_H_
+#define _PCH_INFO_HOB_H_
+
+extern EFI_GUID gPchInfoHobGuid;
+
+#define PCH_INFO_HOB_REVISION 4
+
+#pragma pack (push,1)
+/**
+ This structure is used to provide the information of PCH controller.
+
+ <b>Revision 1</b>:
+ - Initial version.
+ <b>Revision 2</b>:
+ - Add CridSupport, CridOrgRid, and CridNewRid.
+ <b>Revision 3</b>:
+ - Add Thc0Strap.
+ <b>Revision 4</b>
+ - Removed GbePciePortNumber
+**/
+typedef struct {
+ /**
+ This member specifies the revision of the PCH Info HOB. This field is used
+ to indicate backwards compatible changes to the protocol. Platform code that
+ consumes this protocol must read the correct revision value to correctly interpret
+ the content of the protocol fields.
+ **/
+ UINT8 Revision;
+ UINT8 PcieControllerCfg[6];
+ /**
+ THC strap disable/enable status
+ **/
+ UINT8 Thc0Strap;
+ UINT32 PciePortFuses;
+ /**
+ Bit map for PCIe Root Port Lane setting. If bit is set it means that
+ corresponding Root Port has its lane enabled.
+ BIT0 - RP0, BIT1 - RP1, ...
+ This information needs to be passed through HOB as FIA registers
+ are not accessible with POSTBOOT_SAI
+ **/
+ UINT32 PciePortLaneEnabled;
+ /**
+ Publish Hpet BDF and IoApic BDF information for VTD.
+ **/
+ UINT32 HpetBusNum : 8;
+ UINT32 HpetDevNum : 5;
+ UINT32 HpetFuncNum : 3;
+ UINT32 IoApicBusNum : 8;
+ UINT32 IoApicDevNum : 5;
+ UINT32 IoApicFuncNum : 3;
+ /**
+ Publish the CRID information.
+ **/
+ UINT32 CridOrgRid : 8;
+ UINT32 CridNewRid : 8;
+ UINT32 CridSupport : 1;
+ UINT32 Rsvdbits : 15;
+} PCH_INFO_HOB;
+
+#pragma pack (pop)
+
+#endif // _PCH_INFO_HOB_H_
+
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/PchLimits.h b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/PchLimits.h
new file mode 100644
index 0000000000..04ad17c8bd
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/PchLimits.h
@@ -0,0 +1,67 @@
+/** @file
+ Build time limits of PCH resources.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PCH_LIMITS_H_
+#define _PCH_LIMITS_H_
+/*
+ * Defines povided in this file are indended to be used only where static value
+ * is needed. They are set to values which allow to accomodate multiple projects
+ * needs. Where runtime usage is possible please used dedicated functions from
+ * PchInfoLib to retrieve accurate values
+ */
+
+//
+// PCIe limits
+//
+#define PCH_MAX_PCIE_ROOT_PORTS 24
+#define PCH_MAX_PCIE_CONTROLLERS 6
+
+//
+// PCIe clocks limits
+//
+#define PCH_MAX_PCIE_CLOCKS 16
+
+//
+// RST PCIe Storage Cycle Router limits
+//
+#define PCH_MAX_RST_PCIE_STORAGE_CR 3
+
+//
+// SATA limits
+//
+#define PCH_MAX_SATA_CONTROLLERS 3
+#define PCH_MAX_SATA_PORTS 8
+
+//
+// SerialIo limits
+//
+#define PCH_MAX_SERIALIO_I2C_CONTROLLERS 8
+#define PCH_MAX_SERIALIO_SPI_CONTROLLERS 7
+#define PCH_MAX_SERIALIO_SPI_CHIP_SELECTS 2
+#define PCH_MAX_SERIALIO_UART_CONTROLLERS 7
+
+//
+// ISH limits
+//
+#define PCH_MAX_ISH_GP_PINS 8
+#define PCH_MAX_ISH_UART_CONTROLLERS 2
+#define PCH_MAX_ISH_I2C_CONTROLLERS 3
+#define PCH_MAX_ISH_SPI_CONTROLLERS 1
+#define PCH_MAX_ISH_SPI_CS_PINS 1
+//
+// HDA limits
+//
+#define PCH_MAX_HDA_SDI 2
+#define PCH_MAX_HDA_SSP_LINK_NUM 6
+#define PCH_MAX_HDA_SNDW_LINK_NUM 4
+
+//
+// Number of eSPI slaves
+//
+#define PCH_MAX_ESPI_SLAVES 2
+
+#endif // _PCH_LIMITS_H_
+
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/PchPolicyCommon.h b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/PchPolicyCommon.h
new file mode 100644
index 0000000000..7b749818fa
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/PchPolicyCommon.h
@@ -0,0 +1,55 @@
+/** @file
+ PCH configuration based on PCH policy
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PCH_POLICY_COMMON_H_
+#define _PCH_POLICY_COMMON_H_
+
+#include <ConfigBlock.h>
+#include <UsbConfig.h>
+#include <Usb2PhyConfig.h>
+#include <Usb3HsioConfig.h>
+
+#include "PchLimits.h"
+#include "ConfigBlock/PchGeneralConfig.h"
+#include <PchPcieRpConfig.h>
+#include <IoApicConfig.h>
+#include <SataConfig.h>
+#include <RstConfig.h>
+#include <PchDmiConfig.h>
+#include "ConfigBlock/FlashProtectionConfig.h"
+#include <InterruptConfig.h>
+#include <HdAudioConfig.h>
+#include <IshConfig.h>
+#include <GbeConfig.h>
+#include "ConfigBlock/LockDownConfig.h"
+#include "P2sbConfig.h"
+#include <PmConfig.h>
+#include <ScsConfig.h>
+#include <SerialIoConfig.h>
+#include <ThcConfig.h>
+#include <ThermalConfig.h>
+#include <EspiConfig.h>
+#include <CnviConfig.h>
+#include <IehConfig.h>
+#include <PsfConfig.h>
+#include <FivrConfig.h>
+#include <AdrConfig.h>
+#include <RtcConfig.h>
+#include <HybridStorageConfig.h>
+#include <SpiConfig.h>
+
+#ifndef FORCE_ENABLE
+#define FORCE_ENABLE 1
+#endif
+#ifndef FORCE_DISABLE
+#define FORCE_DISABLE 2
+#endif
+#ifndef PLATFORM_POR
+#define PLATFORM_POR 0
+#endif
+
+
+#endif // _PCH_POLICY_COMMON_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/PchPreMemPolicyCommon.h b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/PchPreMemPolicyCommon.h
new file mode 100644
index 0000000000..25e99d3a68
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/PchPreMemPolicyCommon.h
@@ -0,0 +1,56 @@
+/** @file
+ PCH configuration based on PCH policy
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PCH_PREMEM_POLICY_COMMON_H_
+#define _PCH_PREMEM_POLICY_COMMON_H_
+
+#include <ConfigBlock.h>
+
+#include "PchLimits.h"
+#include "ConfigBlock/PchGeneralConfig.h"
+#include <DciConfig.h>
+#include <WatchDogConfig.h>
+#include <SmbusConfig.h>
+#include "ConfigBlock/LpcConfig.h"
+#include "ConfigBlock/HsioPcieConfig.h"
+#include "ConfigBlock/HsioSataConfig.h"
+#include "ConfigBlock/HsioConfig.h"
+
+#pragma pack (push,1)
+
+#ifndef FORCE_ENABLE
+#define FORCE_ENABLE 1
+#endif
+#ifndef FORCE_DISABLE
+#define FORCE_DISABLE 2
+#endif
+#ifndef PLATFORM_POR
+#define PLATFORM_POR 0
+#endif
+
+/**
+ PCH Policy revision number
+ Any backwards compatible changes to this structure will result in an update in the revision number
+**/
+#define PCH_PREMEM_POLICY_REVISION 1
+
+/**
+ PCH Policy PPI\n
+ All PCH config block change history will be listed here\n\n
+
+ - <b>Revision 1</b>:
+ - Initial version.\n
+**/
+typedef struct _PCH_PREMEM_POLICY {
+ CONFIG_BLOCK_TABLE_HEADER TableHeader;
+/*
+ Individual Config Block Structures are added here in memory as part of AddConfigBlock()
+*/
+} PCH_PREMEM_POLICY;
+
+#pragma pack (pop)
+
+#endif // _PCH_PREMEM_POLICY_COMMON_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/PchResetPlatformSpecific.h b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/PchResetPlatformSpecific.h
new file mode 100644
index 0000000000..4573a11520
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/PchResetPlatformSpecific.h
@@ -0,0 +1,21 @@
+/** @file
+ PCH Reset Platform Specific definitions.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PCH_RESET_PLATFORM_SPECIFIC_H_
+#define _PCH_RESET_PLATFORM_SPECIFIC_H_
+
+#define PCH_PLATFORM_SPECIFIC_RESET_STRING L"PCH_RESET"
+#define PCH_RESET_DATA_STRING_MAX_LENGTH (sizeof (PCH_PLATFORM_SPECIFIC_RESET_STRING) / sizeof (UINT16))
+
+extern EFI_GUID gPchGlobalResetGuid;
+
+typedef struct _RESET_DATA {
+ CHAR16 Description[PCH_RESET_DATA_STRING_MAX_LENGTH];
+ EFI_GUID Guid;
+} PCH_RESET_DATA;
+
+#endif // _PCH_RESET_PLATFORM_SPECIFIC_H_
+
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/Protocol/IoTrapExDispatch.h b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/Protocol/IoTrapExDispatch.h
new file mode 100644
index 0000000000..4d6241c32b
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/Protocol/IoTrapExDispatch.h
@@ -0,0 +1,184 @@
+/** @file
+ PCH IO TrapEx Dispatch Protocol
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _IO_TRAP_EX_DISPATCH_H_
+#define _IO_TRAP_EX_DISPATCH_H_
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID gIoTrapExDispatchProtocolGuid;
+
+typedef struct _IO_TRAP_EX_DISPATCH_PROTOCOL IO_TRAP_EX_DISPATCH_PROTOCOL;
+
+/**
+ IO Trap Ex valid types
+**/
+typedef enum {
+ IoTrapExTypeWrite,
+ IoTrapExTypeRead,
+ IoTrapExTypeReadWrite,
+ IoTrapExTypeMaximum
+} IO_TRAP_EX_DISPATCH_TYPE;
+
+/**
+ IO Trap Ex context structure containing information about the
+ IO trap Ex event that should invoke the handler.
+ ByteEnableMask bitwise to ignore the ByteEnable setting. E.g. 1111b for any byte access.
+
+ Here are some examples for the usage.
+ 1. To trigger the TRAP for the IO address from 0x2000 to 0x20FF with BYTE/WORD/DWORD read/write access:
+ Address = 0x2000
+ Length = 0x100
+ Type = IoTrapExTypeReadWrite
+ ByteEnable = 0x00 (BE is not matter)
+ ByteEnableMask = 0x0F (BEM 0xF for any BYTE/WORD/DWORD access)
+ 2. To trigger the TRAP for port 0x61 with BYTE read access:
+ Address = 0x60
+ Length = 4
+ Type = IoTrapExTypeRead
+ ByteEnable = 0x02 (BE is 0010b to trap only second byte of every DWORD)
+ ByteEnableMask = 0x00 (BEM doesn't mask any BE bit)
+ 3. To trigger the TRAP for port 0x60 and 0x64 with BYTE write access:
+ Address = 0x60
+ Length = 8
+ Type = IoTrapExTypeWrite
+ ByteEnable = 0x01 (BE is 0001b to trap only first byte of every DWORD)
+ ByteEnableMask = 0x00 (BEM doesn't mask any BE bit)
+**/
+typedef struct {
+ /**
+ The Address must be dword alignment.
+ **/
+ UINT16 Address;
+ UINT16 Length;
+ IO_TRAP_EX_DISPATCH_TYPE Type;
+ /**
+ Bitmap to enable trap for each byte of every dword alignment address.
+ The Io Trap Address must be dword alignment for ByteEnable.
+ E.g. 0001b for first byte, 0010b for second byte, 1100b for third and fourth byte.
+ **/
+ UINT8 ByteEnable;
+ /**
+ ByteEnableMask bitwise to ignore the ByteEnable setting. E.g. 1111b for any byte access.
+ The Io Trap Address must be dword alignment for ByteEnableMask.
+ **/
+ UINT8 ByteEnableMask;
+} IO_TRAP_EX_REGISTER_CONTEXT;
+
+/**
+ Callback function for an PCH IO TRAP EX handler dispatch.
+
+ @param[in] Address DWord-aligned address of the trapped cycle.
+ @param[in] ByteEnable This is the DWord-aligned byte enables associated with the trapped cycle.
+ A 1 in any bit location indicates that the corresponding byte is enabled in the cycle.
+ @param[in] WriteCycle TRUE = Write cycle; FALSE = Read cycle
+ @param[in] WriteData DWord of I/O write data. This field is undefined after trapping a read cycle.
+ The byte of WriteData is only valid if the corresponding bits in ByteEnable is 1.
+ E.g.
+ If ByteEnable is 0001b, then only first byte of WriteData is valid.
+ If ByteEnable is 0010b, then only second byte of WriteData is valid.
+**/
+typedef
+VOID
+(EFIAPI *IO_TRAP_EX_DISPATCH_CALLBACK) (
+ IN UINT16 Address,
+ IN UINT8 ByteEnable,
+ IN BOOLEAN WriteCycle,
+ IN UINT32 WriteData
+ );
+
+/**
+ Register a new IO Trap Ex SMI dispatch function.
+ The caller will provide information of IO trap setting via the context.
+ Please consider to use EfiSmmIoTrapDispatch2Protocol as possible.
+ This is the function to extend the IoTrap capability, and it's expected
+ to handle the special ByteEnable and ByteEnableMask setting.
+ This register function will occupy one IoTrap register if possible.
+ And it only support one handler for one IoTrap event.
+ The Address of context MUST NOT be 0, and MUST be dword alignment.
+ The Length of context MUST not less than 4, and MUST be power of 2.
+ The ByteEnable and ByteEnableMask MUST not be zero at the same time.
+ if the IO Trap handler is not used. It also enable the IO Trap Range to generate
+ SMI.
+ Caller must take care of reserving the IO addresses in ACPI.
+
+ @param[in] This Pointer to the IO_TRAP_EX_DISPATCH_PROTOCOL instance.
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for
+ this SMI source.
+ @param[in] RegisterContext Pointer to the dispatch function's context.
+ The caller fills this context in before calling
+ the register function to indicate to the register
+ function the IO trap Ex SMI source for which the dispatch
+ function should be invoked. This MUST not be NULL.
+ @param[out] DispatchHandle Handle of dispatch function.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ registered and the SMI source has been enabled.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources are available
+ @retval EFI_INVALID_PARAMETER Address requested is already in use.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+typedef
+EFI_STATUS
+(EFIAPI *IO_TRAP_EX_DISPATCH_REGISTER) (
+ IN IO_TRAP_EX_DISPATCH_PROTOCOL *This,
+ IN IO_TRAP_EX_DISPATCH_CALLBACK DispatchFunction,
+ IN IO_TRAP_EX_REGISTER_CONTEXT *RegisterContext,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+
+/**
+ Unregister a SMI source dispatch function.
+ This function is unsupported.
+
+ @param[in] This Pointer to the IO_TRAP_EX_DISPATCH_PROTOCOL instance.
+ @param[in] DispatchHandle Handle of dispatch function to deregister.
+
+ @retval EFI_UNSUPPORTED The function is unsupported.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *IO_TRAP_EX_DISPATCH_UNREGISTER) (
+ IN IO_TRAP_EX_DISPATCH_PROTOCOL *This,
+ IN EFI_HANDLE DispatchHandle
+ );
+
+/**
+ Interface structure for the IO trap Extention protocol.
+ This protocol exposes full IO TRAP capability for ByteEnable and ByteEnableMask setting.
+ Platform code should fully control the ByteEnable and ByteEnableMake while using this protocol.
+
+ Please consider to use EfiSmmIoTrapDispatch2Protocol as possible.
+ This is the function to extend the IoTrap capability, and it's expected
+ to handle the special ByteEnable and ByteEnableMask setting.
+
+ The protocol is low level, It returns PSTH trapped cycle. This might not be safe for multithread
+ if more than one thread triggers the same IOTRAP at the same time.
+**/
+struct _IO_TRAP_EX_DISPATCH_PROTOCOL {
+ /**
+ Register function for PCH IO TRAP EX DISPATCH PROTOCOL.
+ The caller will provide information of IO trap setting via the context.
+ Please consider to use EfiSmmIoTrapDispatch2Protocol as possible.
+ This is the function to extend the IoTrap capability, and it's expected
+ to handle the special ByteEnable and ByteEnableMask setting.
+ This register function will occupy one IoTrap register if possible.
+ And it only support one handler for one IoTrap event.
+ The Address of context MUST NOT be 0, and MUST be dword alignment.
+ The Length of context MUST not less than 4, and MUST be power of 2.
+ The ByteEnable and ByteEnableMask MUST not be zero at the same time.
+ if the IO Trap handler is not used. It also enable the IO Trap Range to
+ generate SMI.
+ **/
+ IO_TRAP_EX_DISPATCH_REGISTER Register;
+ /**
+ Unregister function for PCH IO TRAP EX DISPATCH PROTOCOL.
+ **/
+ IO_TRAP_EX_DISPATCH_UNREGISTER UnRegister;
+};
+
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/Protocol/PchAcpiSmiDispatch.h b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/Protocol/PchAcpiSmiDispatch.h
new file mode 100644
index 0000000000..136734d9ff
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/Protocol/PchAcpiSmiDispatch.h
@@ -0,0 +1,134 @@
+/** @file
+ APIs of PCH ACPI SMI Dispatch Protocol.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PCH_ACPI_SMI_DISPATCH_PROTOCOL_H_
+#define _PCH_ACPI_SMI_DISPATCH_PROTOCOL_H_
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID gPchAcpiSmiDispatchProtocolGuid;
+
+//
+// Forward reference for ANSI C compatibility
+//
+typedef struct _PCH_ACPI_SMI_DISPATCH_PROTOCOL PCH_ACPI_SMI_DISPATCH_PROTOCOL;
+
+//
+// Member functions
+//
+
+/**
+ Callback function for an PCH ACPI SMI handler dispatch.
+
+ @param[in] DispatchHandle The unique handle assigned to this handler by register function.
+
+**/
+typedef
+VOID
+(EFIAPI *PCH_ACPI_SMI_DISPATCH_CALLBACK) (
+ IN EFI_HANDLE DispatchHandle
+ );
+
+/**
+ Register a child SMI source dispatch function for PCH ACPI SMI events.
+
+ @param[in] This Protocol instance pointer.
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for
+ this SMI source
+ @param[out] DispatchHandle Handle of dispatch function, for when interfacing
+ with the parent SMM driver.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ registered and the SMI source has been enabled.
+ @retval EFI_DEVICE_ERROR The driver was unable to enable the SMI source.
+ @retval EFI_OUT_OF_RESOURCES Not enough memory (system or SMM) to manage this child.
+ @retval EFI_ACCESS_DENIED Return access denied if the EndOfDxe event has been triggered
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_ACPI_SMI_DISPATCH_REGISTER) (
+ IN PCH_ACPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ACPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+
+/**
+ Unregister a child SMI source dispatch function with a parent ACPI SMM driver
+
+ @param[in] This Protocol instance pointer.
+ @param[in] DispatchHandle Handle of dispatch function to deregister.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ unregistered and the SMI source has been disabled
+ if there are no other registered child dispatch
+ functions for this SMI source.
+ @retval EFI_INVALID_PARAMETER Handle is invalid.
+ @retval EFI_ACCESS_DENIED Return access denied if the EndOfDxe event has been triggered
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_ACPI_SMI_DISPATCH_UNREGISTER) (
+ IN PCH_ACPI_SMI_DISPATCH_PROTOCOL *This,
+ IN EFI_HANDLE DispatchHandle
+ );
+
+/**
+ Interface structure for PCH ACPI SMIs Dispatch Protocol
+ The PCH ACPI SMI DISPATCH PROTOCOL provides the ability to dispatch function for PCH ACPI related SMIs.
+ It contains SMI types of Pme, RtcAlarm, PmeB0, and Time overflow.
+**/
+struct _PCH_ACPI_SMI_DISPATCH_PROTOCOL {
+ /**
+ This member specifies the revision of this structure. This field is used to
+ indicate backwards compatible changes to the protocol.
+ **/
+ UINT8 Revision;
+ /**
+ Smi unregister function for PCH ACPI SMI DISPATCH PROTOCOL.
+ **/
+ PCH_ACPI_SMI_DISPATCH_UNREGISTER UnRegister;
+ /**
+ Pme
+ The event is triggered by hardware when the PME# signal goes active.
+ Additionally, the event is only triggered when SCI_EN is not set.
+ **/
+ PCH_ACPI_SMI_DISPATCH_REGISTER PmeRegister;
+ /**
+ PmeB0
+ The event is triggered PCH when any internal device with PCI Power Management
+ capabilities on bus 0 asserts the equivalent of the PME# signal.
+ Additionally, the event is only triggered when SCI_EN is not set.
+ The following are internal devices which can set this bit:
+ Intel HD Audio, Intel Management Engine "maskable" wake events, Integrated LAN,
+ SATA, xHCI, Intel SST
+ **/
+ PCH_ACPI_SMI_DISPATCH_REGISTER PmeB0Register;
+ /**
+ RtcAlarm
+ The event is triggered by hardware when the RTC generates an alarm
+ (assertion of the IRQ8# signal).
+ **/
+ PCH_ACPI_SMI_DISPATCH_REGISTER RtcAlarmRegister;
+ /**
+ TmrOverflow
+ The event is triggered any time bit 22 of the 24-bit timer goes high
+ (bits are numbered from 0 to 23).
+ This will occur every 2.3435 seconds. When the TMROF_EN bit (ABASE + 02h, bit 0) is set,
+ then the setting of the TMROF_STS bit will additionally generate an SMI#
+ Additionally, the event is only triggered when SCI_EN is not set.
+ **/
+ PCH_ACPI_SMI_DISPATCH_REGISTER TmrOverflowRegister;
+};
+
+/**
+ PCH ACPI SMI dispatch revision number
+
+ Revision 1: Initial version
+**/
+#define PCH_ACPI_SMI_DISPATCH_REVISION 1
+
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/Protocol/PchEspiSmiDispatch.h b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/Protocol/PchEspiSmiDispatch.h
new file mode 100644
index 0000000000..4ea48c3fcd
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/Protocol/PchEspiSmiDispatch.h
@@ -0,0 +1,144 @@
+/** @file
+ SmmEspiDispatch Protocol
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PCH_ESPI_SMI_DISPATCH_PROTOCOL_H_
+#define _PCH_ESPI_SMI_DISPATCH_PROTOCOL_H_
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID gPchEspiSmiDispatchProtocolGuid;
+
+//
+// Forward reference for ANSI C compatibility
+//
+typedef struct _PCH_ESPI_SMI_DISPATCH_PROTOCOL PCH_ESPI_SMI_DISPATCH_PROTOCOL;
+
+//
+// Member functions
+//
+
+/**
+ Callback function for an PCH eSPI SMI handler dispatch.
+
+ @param[in] DispatchHandle The unique handle assigned to this handler by register function.
+**/
+typedef
+VOID
+(EFIAPI *PCH_ESPI_SMI_DISPATCH_CALLBACK) (
+ IN EFI_HANDLE DispatchHandle
+ );
+
+/**
+ Generic function to register different types of eSPI SMI types
+
+ @param[in] This Not used
+ @param[in] DispatchFunction The callback to execute
+ @param[out] DispatchHandle The handle for this callback registration
+
+ @retval EFI_SUCCESS Registration successful
+ @retval EFI_ACCESS_DENIED Return access denied if the EndOfDxe event has been triggered
+ @retval others Registration failed
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_ESPI_SMI_REGISTER) (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ESPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+
+/**
+ eSPI SMI Dispatch Protocol instance to unregister a callback based on handle
+
+ @param[in] This Not used
+ @param[in] DispatchHandle Handle acquired during registration
+
+ @retval EFI_SUCCESS Unregister successful
+ @retval EFI_INVALID_PARAMETER DispatchHandle is null
+ @retval EFI_INVALID_PARAMETER DispatchHandle's forward link has bad pointer
+ @retval EFI_INVALID_PARAMETER DispatchHandle does not exist in database
+ @retval EFI_ACCESS_DENIED Unregistration is done after end of DXE
+**/
+
+typedef
+EFI_STATUS
+(EFIAPI *PCH_ESPI_SMI_UNREGISTER) (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN EFI_HANDLE DispatchHandle
+ );
+
+/**
+ Interface structure for PCH eSPI SMIs Dispatch Protocol
+ The PCH ESPI SMI DISPATCH PROTOCOL provides the ability to dispatch function for PCH eSPI related SMIs.
+ It contains SMI types of BiosWr, EcAssertedVw, and eSPI Master asserted SMIs
+**/
+struct _PCH_ESPI_SMI_DISPATCH_PROTOCOL {
+ /**
+ This member specifies the revision of this structure. This field is used to
+ indicate backwards compatible changes to the protocol.
+ **/
+ UINT8 Revision;
+ /**
+ Unregister eSPI SMI events
+ **/
+ PCH_ESPI_SMI_UNREGISTER UnRegister;
+ /**
+ Register a BIOS Write Protect event
+ **/
+ PCH_ESPI_SMI_REGISTER BiosWrProtectRegister;
+ /**
+ Register a BIOS Write Report event
+ **/
+ PCH_ESPI_SMI_REGISTER BiosWrReportRegister;
+ /**
+ Register a Peripheral Channel Non Fatal Error event
+ **/
+ PCH_ESPI_SMI_REGISTER PcErrNonFatalRegister;
+ /**
+ Register a Peripheral Channel Fatal Error event
+ **/
+ PCH_ESPI_SMI_REGISTER PcErrFatalRegister;
+ /**
+ Register a Virtual Wire Non Fatal Error event
+ **/
+ PCH_ESPI_SMI_REGISTER VwErrNonFatalRegister;
+ /**
+ Register a Virtual Wire Fatal Error event
+ **/
+ PCH_ESPI_SMI_REGISTER VwErrFatalRegister;
+ /**
+ Register a Flash Channel Non Fatal Error event
+ **/
+ PCH_ESPI_SMI_REGISTER FlashErrNonFatalRegister;
+ /**
+ Register a Flash Channel Fatal Error event
+ **/
+ PCH_ESPI_SMI_REGISTER FlashErrFatalRegister;
+ /**
+ Register a Link Error event
+ **/
+ PCH_ESPI_SMI_REGISTER LnkErrType1Register;
+ /**
+ Register a SMI handler for Espi slaver
+ This routine will also lock down ESPI_SMI_LOCK bit after registration and prevent
+ this handler from unregistration.
+ On platform that supports more than 1 device through another chip select (SPT-H),
+ the SMI handler itself needs to inspect both the eSPI devices' interrupt status registers
+ (implementation specific for each Slave) in order to identify and service the cause.
+ After servicing it, it has to clear the Slaves' internal SMI# status registers
+ **/
+ PCH_ESPI_SMI_REGISTER EspiSlaveSmiRegister;
+};
+
+/**
+ PCH ESPI SMI dispatch revision number
+
+ Revision 1: Initial version
+**/
+#define PCH_ESPI_SMI_DISPATCH_REVISION 1
+
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/Protocol/PchPcieSmiDispatch.h b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/Protocol/PchPcieSmiDispatch.h
new file mode 100644
index 0000000000..b75b9ab45d
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/Protocol/PchPcieSmiDispatch.h
@@ -0,0 +1,166 @@
+/** @file
+ APIs of PCH PCIE SMI Dispatch Protocol.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PCH_PCIE_SMI_DISPATCH_PROTOCOL_H_
+#define _PCH_PCIE_SMI_DISPATCH_PROTOCOL_H_
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID gPchPcieSmiDispatchProtocolGuid;
+
+//
+// Forward reference for ANSI C compatibility
+//
+typedef struct _PCH_PCIE_SMI_DISPATCH_PROTOCOL PCH_PCIE_SMI_DISPATCH_PROTOCOL;
+
+typedef enum {
+ PchRpIndex0 = 0,
+ PchRpIndex1 = 1,
+ PchRpIndex2 = 2,
+ PchRpIndex3 = 3,
+ PchRpIndex4 = 4,
+ PchRpIndex5 = 5,
+ PchRpIndex6 = 6,
+ PchRpIndex7 = 7,
+ PchRpIndex8 = 8,
+ PchRpIndex9 = 9,
+ PchRpIndex10 = 10,
+ PchRpIndex11 = 11,
+ PchRpIndex12 = 12,
+ PchRpIndex13 = 13,
+ PchRpIndex14 = 14,
+ PchRpIndex15 = 15,
+ PchRpIndex16 = 16,
+ PchRpIndex17 = 17,
+ PchRpIndex18 = 18,
+ PchRpIndex19 = 19,
+ PchRpIndex20 = 20,
+ PchRpIndex21 = 21,
+ PchRpIndex22 = 22,
+ PchRpIndex23 = 23,
+ /**
+ Quantity of PCH and CPU PCIe ports, as well as their encoding in this enum, may change between
+ silicon generations and series. Do not assume that PCH port 0 will be always encoded by 0.
+ Instead, it is recommended to use (PchRpIndex0 + PchPortIndex) style to be forward-compatible
+ **/
+ CpuRpIndex0 = 0x40,
+ CpuRpIndex1 = 0x41,
+ CpuRpIndex2 = 0x42,
+ CpuRpIndex3 = 0x43
+} PCIE_COMBINED_RPINDEX;
+
+//
+// Member functions
+//
+
+typedef struct {
+ UINT8 RpIndex; ///< Root port index (0-based), 0: RP1, 1: RP2, n: RP(N+1)
+ UINT8 BusNum; ///< Root port pci bus number
+ UINT8 DevNum; ///< Root port pci device number
+ UINT8 FuncNum; ///< Root port pci function number
+} PCH_PCIE_SMI_RP_CONTEXT;
+
+/**
+ Callback function for an PCH PCIE RP SMI handler dispatch.
+
+ @param[in] DispatchHandle The unique handle assigned to this handler by register function.
+ @param[in] RpContext Pointer of PCH PCIE Root Port context.
+
+**/
+typedef
+VOID
+(EFIAPI *PCH_PCIE_SMI_RP_DISPATCH_CALLBACK) (
+ IN EFI_HANDLE DispatchHandle,
+ IN PCH_PCIE_SMI_RP_CONTEXT *RpContext
+ );
+
+/**
+ Register a child SMI source dispatch function for PCH PCIERP SMI events.
+
+ @param[in] This Protocol instance pointer.
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for
+ this SMI source
+ @param[in] RpIndex Refer PCIE_COMBINED_RPINDEX for PCH RP index and CPU RP index.
+ 0: RP1, 1: RP2, n: RP(N+1)
+ @param[out] DispatchHandle Handle of dispatch function, for when interfacing
+ with the parent SMM driver.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ registered and the SMI source has been enabled.
+ @retval EFI_DEVICE_ERROR The driver was unable to enable the SMI source.
+ @retval EFI_OUT_OF_RESOURCES Not enough memory (system or SMM) to manage this child.
+ @retval EFI_ACCESS_DENIED Return access denied if the EndOfDxe event has been triggered
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_PCIE_SMI_RP_DISPATCH_REGISTER) (
+ IN PCH_PCIE_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_PCIE_SMI_RP_DISPATCH_CALLBACK DispatchFunction,
+ IN UINTN RpIndex,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+
+/**
+ Unregister a child SMI source dispatch function with a parent PCIE SMM driver
+
+ @param[in] This Protocol instance pointer.
+ @param[in] DispatchHandle Handle of dispatch function to deregister.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ unregistered and the SMI source has been disabled
+ if there are no other registered child dispatch
+ functions for this SMI source.
+ @retval EFI_INVALID_PARAMETER Handle is invalid.
+ @retval EFI_ACCESS_DENIED Return access denied if the EndOfDxe event has been triggered
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_PCIE_SMI_DISPATCH_UNREGISTER) (
+ IN PCH_PCIE_SMI_DISPATCH_PROTOCOL *This,
+ IN EFI_HANDLE DispatchHandle
+ );
+
+/**
+ Interface structure for PCH PCIE SMIs Dispatch Protocol
+ The PCH PCIE SMI DISPATCH PROTOCOL provides the ability to dispatch function for PCH PCIE related SMIs.
+ It contains SMI types of HotPlug, LinkActive, and Link EQ.
+**/
+struct _PCH_PCIE_SMI_DISPATCH_PROTOCOL {
+ /**
+ This member specifies the revision of this structure. This field is used to
+ indicate backwards compatible changes to the protocol.
+ **/
+ UINT8 Revision;
+ /**
+ Smi unregister function for PCH PCIE SMI DISPATCH PROTOCOL.
+ **/
+ PCH_PCIE_SMI_DISPATCH_UNREGISTER UnRegister;
+ /**
+ PcieRpXHotPlug
+ The event is triggered when PCIE root port Hot-Plug Presence Detect.
+ **/
+ PCH_PCIE_SMI_RP_DISPATCH_REGISTER HotPlugRegister;
+ /**
+ PcieRpXLinkActive
+ The event is triggered when Hot-Plug Link Active State Changed.
+ **/
+ PCH_PCIE_SMI_RP_DISPATCH_REGISTER LinkActiveRegister;
+ /**
+ PcieRpXLinkEq
+ The event is triggered when Device Requests Software Link Equalization.
+ **/
+ PCH_PCIE_SMI_RP_DISPATCH_REGISTER LinkEqRegister;
+};
+
+/**
+ PCH PCIE SMI dispatch revision number
+
+ Revision 1: Initial version
+**/
+#define PCH_PCIE_SMI_DISPATCH_REVISION 1
+
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/Protocol/PchPolicy.h b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/Protocol/PchPolicy.h
new file mode 100644
index 0000000000..ba7cbdb23e
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/Protocol/PchPolicy.h
@@ -0,0 +1,40 @@
+/** @file
+ Interface definition details between Pch and platform drivers during DXE phase.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PCH_POLICY_H_
+#define _PCH_POLICY_H_
+
+#include <ConfigBlock.h>
+#include <Library/ConfigBlockLib.h>
+#include "../IncludePrivate/PchConfigHob.h" // To Be corrected
+#include <Library/HobLib.h>
+
+extern EFI_GUID gPchPolicyProtocolGuid;
+
+#define PCH_POLICY_PROTOCOL_REVISION 1
+
+
+/**
+ PCH DXE Policy
+
+ The PCH_POLICY_PROTOCOL producer drvier is recommended to
+ set all the PCH_POLICY_PROTOCOL size buffer zero before init any member parameter,
+ this clear step can make sure no random value for those unknown new version parameters.
+
+ Make sure to update the Revision if any change to the protocol, including the existing
+ internal structure definations.\n
+ Note: Here revision will be bumped up when adding/removing any config block under this structure.\n
+ <b>Revision 1</b>:
+ - Initial version.
+**/
+typedef struct {
+ CONFIG_BLOCK_TABLE_HEADER TableHeader;
+/*
+ Individual Config Block Structures are added here in memory as part of AddConfigBlock()
+*/
+} PCH_POLICY_PROTOCOL;
+
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/Protocol/PchSmiDispatch.h b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/Protocol/PchSmiDispatch.h
new file mode 100644
index 0000000000..12b5f8117b
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/Protocol/PchSmiDispatch.h
@@ -0,0 +1,132 @@
+/** @file
+ APIs of PCH SMI Dispatch Protocol.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PCH_SMI_DISPATCH_PROTOCOL_H_
+#define _PCH_SMI_DISPATCH_PROTOCOL_H_
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID gPchSmiDispatchProtocolGuid;
+
+//
+// Forward reference for ANSI C compatibility
+//
+typedef struct _PCH_SMI_DISPATCH_PROTOCOL PCH_SMI_DISPATCH_PROTOCOL;
+
+//
+// Member functions
+//
+
+/**
+ Callback function for an PCH SMI handler dispatch.
+
+ @param[in] DispatchHandle The unique handle assigned to this handler by register function.
+
+**/
+typedef
+VOID
+(EFIAPI *PCH_SMI_DISPATCH_CALLBACK) (
+ IN EFI_HANDLE DispatchHandle
+ );
+
+/**
+ Register a child SMI source dispatch function for specific PCH SMI dispatch event.
+
+ @param[in] This Protocol instance pointer.
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for
+ this SMI source
+ @param[out] DispatchHandle Handle of dispatch function, for when interfacing
+ with the parent SMM driver.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ registered and the SMI source has been enabled.
+ @retval EFI_DEVICE_ERROR The driver was unable to enable the SMI source.
+ @retval EFI_OUT_OF_RESOURCES Not enough memory (system or SMM) to manage this child.
+ @retval EFI_ACCESS_DENIED Return access denied if the EndOfDxe event has been triggered
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SMI_DISPATCH_REGISTER) (
+ IN PCH_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+
+/**
+ Unregister a child SMI source dispatch function with a parent SMM driver
+
+ @param[in] This Protocol instance pointer.
+ @param[in] DispatchHandle Handle of dispatch function to deregister.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ unregistered and the SMI source has been disabled
+ if there are no other registered child dispatch
+ functions for this SMI source.
+ @retval EFI_INVALID_PARAMETER Handle is invalid.
+ @retval EFI_ACCESS_DENIED Return access denied if the EndOfDxe event has been triggered
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SMI_DISPATCH_UNREGISTER) (
+ IN PCH_SMI_DISPATCH_PROTOCOL *This,
+ IN EFI_HANDLE DispatchHandle
+ );
+
+/**
+ Interface structure for PCH specific SMIs Dispatch Protocol
+ The PCH SMI DISPATCH PROTOCOL provides the ability to dispatch function for PCH misc SMIs.
+ It contains legacy SMIs and new PCH SMI types like:
+ SerialIrq, McSmi, Smbus, ...
+**/
+struct _PCH_SMI_DISPATCH_PROTOCOL {
+ /**
+ This member specifies the revision of this structure. This field is used to
+ indicate backwards compatible changes to the protocol.
+ **/
+ UINT8 Revision;
+ /**
+ Smi unregister function for PCH SMI DISPATCH PROTOCOL.
+ **/
+ PCH_SMI_DISPATCH_UNREGISTER UnRegister;
+ /**
+ SerialIrq
+ The event is triggered while the SMI# was caused by the SERIRQ decoder.
+ **/
+ PCH_SMI_DISPATCH_REGISTER SerialIrqRegister;
+ /**
+ McSmi
+ The event is triggered if there has been an access to the power management
+ microcontroller range (62h or 66h) and the Microcontroller Decode Enable #1 bit
+ in the LPC Bridge I/O Enables configuration register is 1 .
+ **/
+ PCH_SMI_DISPATCH_REGISTER McSmiRegister;
+ /**
+ SmBus
+ The event is triggered while the SMI# was caused by:
+ 1. The SMBus Slave receiving a message that an SMI# should be caused, or
+ 2. The SMBALERT# signal goes active and the SMB_SMI_EN bit is set and the
+ SMBALERT_DIS bit is cleared, or
+ 3. The SMBus Slave receiving a Host Notify message and the HOST_NOTIFY_INTREN and
+ the SMB_SMI_EN bits are set, or
+ 4. The PCH detecting the SMLINK_SLAVE_SMI command while in the S0 state.
+ **/
+ PCH_SMI_DISPATCH_REGISTER SmbusRegister;
+ /**
+ SPI Asynchronous
+ When registered, the flash controller will generate an SMI when it blocks a BIOS write or erase.
+ **/
+ PCH_SMI_DISPATCH_REGISTER SpiAsyncRegister;
+};
+
+/**
+ PCH SMI dispatch revision number
+
+ Revision 1: Initial version
+**/
+#define PCH_SMI_DISPATCH_REVISION 1
+
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/Protocol/PchSmmIoTrapControl.h b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/Protocol/PchSmmIoTrapControl.h
new file mode 100644
index 0000000000..9f2793634e
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/Protocol/PchSmmIoTrapControl.h
@@ -0,0 +1,65 @@
+/** @file
+ PCH SMM IO Trap Control Protocol
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PCH_SMM_IO_TRAP_CONTROL_H_
+#define _PCH_SMM_IO_TRAP_CONTROL_H_
+
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID gPchSmmIoTrapControlGuid;
+
+//
+// Forward reference for ANSI C compatibility
+//
+typedef struct _PCH_SMM_IO_TRAP_CONTROL_PROTOCOL PCH_SMM_IO_TRAP_CONTROL_PROTOCOL;
+
+//
+// Related Definitions
+//
+
+//
+// Member functions
+//
+
+/**
+ The Prototype of Pause and Resume IoTrap callback function.
+
+ @param[in] This Pointer to the PCH_SMM_IO_TRAP_CONTROL_PROTOCOL instance.
+ @param[in] DispatchHandle Handle of the child service to change state.
+
+ @retval EFI_SUCCESS This operation is complete.
+ @retval EFI_INVALID_PARAMETER The DispatchHandle is invalid.
+ @retval EFI_ACCESS_DENIED The SMI status is alrady PAUSED/RESUMED.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SMM_IO_TRAP_CONTROL_FUNCTION) (
+ IN PCH_SMM_IO_TRAP_CONTROL_PROTOCOL * This,
+ IN EFI_HANDLE DispatchHandle
+ );
+
+/**
+ Interface structure for the SMM IO trap pause and resume protocol
+ This protocol provides the functions to runtime control the IoTrap SMI enabled/disable.
+ This applys the capability to the DispatchHandle which returned by IoTrap callback
+ registration, and the DispatchHandle which must be MergeDisable = TRUE and Address != 0.
+ Besides, when S3 resuem, it only restores the state of IoTrap callback registration.
+ The Paused/Resume state won't be restored after S3 resume.
+**/
+struct _PCH_SMM_IO_TRAP_CONTROL_PROTOCOL {
+ /**
+ This runtime pauses a registered IoTrap handler.
+ **/
+ PCH_SMM_IO_TRAP_CONTROL_FUNCTION Pause;
+ /**
+ This runtime resumes a registered IoTrap handler.
+ **/
+ PCH_SMM_IO_TRAP_CONTROL_FUNCTION Resume;
+};
+
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/Protocol/PchSmmPeriodicTimerControl.h b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/Protocol/PchSmmPeriodicTimerControl.h
new file mode 100644
index 0000000000..a7b44c5f7e
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/Protocol/PchSmmPeriodicTimerControl.h
@@ -0,0 +1,65 @@
+/** @file
+ PCH SMM Periodic Timer Control Protocol
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PCH_SMM_PERIODIC_TIMER_CONTROL_H_
+#define _PCH_SMM_PERIODIC_TIMER_CONTROL_H_
+
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID gPchSmmPeriodicTimerControlGuid;
+
+//
+// Forward reference for ANSI C compatibility
+//
+typedef struct _PCH_SMM_PERIODIC_TIMER_CONTROL_PROTOCOL PCH_SMM_PERIODIC_TIMER_CONTROL_PROTOCOL;
+
+//
+// Related Definitions
+//
+
+//
+// Member functions
+//
+
+/**
+ The Prototype of Pause and Resume SMM PERIODIC TIMER function.
+
+ @param[in] This Pointer to the PCH_SMM_PERIODIC_TIMER_CONTROL_PROTOCOL instance.
+ @param[in] DispatchHandle Handle of the child service to change state.
+
+ @retval EFI_SUCCESS This operation is complete.
+ @retval EFI_INVALID_PARAMETER The DispatchHandle is invalid.
+ @retval EFI_ACCESS_DENIED The SMI status is alrady PAUSED/RESUMED.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SMM_PERIODIC_TIMER_CONTROL_FUNCTION) (
+ IN PCH_SMM_PERIODIC_TIMER_CONTROL_PROTOCOL *This,
+ IN EFI_HANDLE DispatchHandle
+ );
+
+/**
+ Interface structure for the SMM PERIODIC TIMER pause and resume protocol
+ This protocol provides the functions to runtime control the SM periodic timer enabled/disable.
+ This applies the capability to the DispatchHandle which returned by SMM periodic timer callback
+ registration.
+ Besides, when S3 resume, it only restores the state of callback registration.
+ The Paused/Resume state won't be restored after S3 resume.
+**/
+struct _PCH_SMM_PERIODIC_TIMER_CONTROL_PROTOCOL {
+ /**
+ This runtime pauses the registered periodic timer handler.
+ **/
+ PCH_SMM_PERIODIC_TIMER_CONTROL_FUNCTION Pause;
+ /**
+ This runtime resumes the registered periodic timer handler.
+ **/
+ PCH_SMM_PERIODIC_TIMER_CONTROL_FUNCTION Resume;
+};
+
+#endif // _PCH_SMM_PERIODIC_TIMER_CONTROL_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/Protocol/PchTcoSmiDispatch.h b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/Protocol/PchTcoSmiDispatch.h
new file mode 100644
index 0000000000..b443484f39
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/Protocol/PchTcoSmiDispatch.h
@@ -0,0 +1,150 @@
+/** @file
+ APIs of PCH TCO SMI Dispatch Protocol.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PCH_TCO_SMI_DISPATCH_PROTOCOL_H_
+#define _PCH_TCO_SMI_DISPATCH_PROTOCOL_H_
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID gPchTcoSmiDispatchProtocolGuid;
+
+//
+// Forward reference for ANSI C compatibility
+//
+typedef struct _PCH_TCO_SMI_DISPATCH_PROTOCOL PCH_TCO_SMI_DISPATCH_PROTOCOL;
+
+//
+// Member functions
+//
+
+/**
+ Callback function for an PCH TCO SMI handler dispatch.
+
+ @param[in] DispatchHandle The unique handle assigned to this handler by register function.
+
+**/
+typedef
+VOID
+(EFIAPI *PCH_TCO_SMI_DISPATCH_CALLBACK) (
+ IN EFI_HANDLE DispatchHandle
+ );
+
+/**
+ Register a child SMI source dispatch function for PCH TCO SMI events.
+
+ @param[in] This Protocol instance pointer.
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for
+ this SMI source
+ @param[out] DispatchHandle Handle of dispatch function, for when interfacing
+ with the parent SMM driver.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ registered and the SMI source has been enabled.
+ @retval EFI_DEVICE_ERROR The driver was unable to enable the SMI source.
+ @retval EFI_OUT_OF_RESOURCES Not enough memory (system or SMM) to manage this child.
+ @retval EFI_ACCESS_DENIED Return access denied if the EndOfDxe event has been triggered
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_TCO_SMI_DISPATCH_REGISTER) (
+ IN PCH_TCO_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_TCO_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+
+/**
+ Unregister a child SMI source dispatch function with a parent TCO SMM driver
+
+ @param[in] This Protocol instance pointer.
+ @param[in] DispatchHandle Handle of dispatch function to deregister.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ unregistered and the SMI source has been disabled
+ if there are no other registered child dispatch
+ functions for this SMI source.
+ @retval EFI_INVALID_PARAMETER Handle is invalid.
+ @retval EFI_ACCESS_DENIED Return access denied if the EndOfDxe event has been triggered
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PCH_TCO_SMI_DISPATCH_UNREGISTER) (
+ IN PCH_TCO_SMI_DISPATCH_PROTOCOL *This,
+ IN EFI_HANDLE DispatchHandle
+ );
+
+/**
+ Interface structure for PCH TCO SMIs Dispatch Protocol
+ The PCH TCO SMI DISPATCH PROTOCOL provides the ability to dispatch function for PCH TCO related SMIs.
+ It contains SMI types of Mch, TcoTimeout, OsTco, Nmi, IntruderDectect, and BiowWp.
+**/
+struct _PCH_TCO_SMI_DISPATCH_PROTOCOL {
+ /**
+ This member specifies the revision of this structure. This field is used to
+ indicate backwards compatible changes to the protocol.
+ **/
+ UINT8 Revision;
+ /**
+ Smi unregister function for PCH TCO SMI DISPATCH PROTOCOL.
+ **/
+ PCH_TCO_SMI_DISPATCH_UNREGISTER UnRegister;
+ /**
+ Mch
+ The event is triggered when PCH received a DMI special cycle message using DMI indicating that
+ it wants to cause an SMI.
+ The software must read the processor to determine the reason for the SMI.
+ **/
+ PCH_TCO_SMI_DISPATCH_REGISTER MchRegister;
+ /**
+ TcoTimeout
+ The event is triggered by PCH to indicate that the SMI was caused by the TCO timer reaching 0.
+ **/
+ PCH_TCO_SMI_DISPATCH_REGISTER TcoTimeoutRegister;
+ /**
+ OsTco
+ The event is triggered when software caused an SMI# by writing to the TCO_DAT_IN register (TCOBASE + 02h).
+ **/
+ PCH_TCO_SMI_DISPATCH_REGISTER OsTcoRegister;
+ /**
+ Nmi
+ The event is triggered by the PCH when an SMI# occurs because an event occurred that would otherwise have
+ caused an NMI (because NMI2SMI_EN is set)
+ **/
+ PCH_TCO_SMI_DISPATCH_REGISTER NmiRegister;
+ /**
+ IntruderDectect
+ The event is triggered by PCH to indicate that an intrusion was detected.
+ **/
+ PCH_TCO_SMI_DISPATCH_REGISTER IntruderDetRegister;
+ /**
+ SpiBiosWp
+ This event is triggered when SMI# was caused by the TCO logic and
+ SPI flash controller asserted Synchronous SMI by BIOS lock enable set.
+ **/
+ PCH_TCO_SMI_DISPATCH_REGISTER SpiBiosWpRegister;
+ /**
+ LpcBiosWp
+ This event is triggered when SMI# was caused by the TCO logic and
+ LPC/eSPI BIOS lock enable set.
+ **/
+ PCH_TCO_SMI_DISPATCH_REGISTER LpcBiosWpRegister;
+ /**
+ NewCentury
+ This event is triggered when SMI# was caused by the TCO logic and
+ year of RTC date rolls over a century (99 to 00).
+ **/
+ PCH_TCO_SMI_DISPATCH_REGISTER NewCenturyRegister;
+};
+
+/**
+ PCH TCO SMI dispatch revision number
+
+ Revision 1: Initial version
+ Revision 2: Add NEWCENTURY support
+**/
+#define PCH_TCO_SMI_DISPATCH_REVISION 2
+
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/Register/PchRegs.h b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/Register/PchRegs.h
new file mode 100644
index 0000000000..679cb17f6c
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/Register/PchRegs.h
@@ -0,0 +1,16 @@
+/** @file
+ Generic register definitions for PCH.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PCH_REGS_H_
+#define _PCH_REGS_H_
+
+///
+/// The default PCH PCI segment and bus number
+///
+#define DEFAULT_PCI_SEGMENT_NUMBER_PCH 0
+#define DEFAULT_PCI_BUS_NUMBER_PCH 0
+
+#endif //_PCH_REGS_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/Register/PchRegsLpc.h b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/Register/PchRegsLpc.h
new file mode 100644
index 0000000000..32dd88be0e
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/Register/PchRegsLpc.h
@@ -0,0 +1,145 @@
+/** @file
+ Register names for PCH LPC/eSPI device
+
+Conventions:
+
+ - Register definition format:
+ Prefix_[GenerationName]_[ComponentName]_SubsystemName_RegisterSpace_RegisterName
+ - Prefix:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register size
+ Definitions beginning with "N_" are the bit position
+ - [GenerationName]:
+ Three letter acronym of the generation is used (e.g. SKL,KBL,CNL etc.).
+ Register name without GenerationName applies to all generations.
+ - [ComponentName]:
+ This field indicates the component name that the register belongs to (e.g. PCH, SA etc.)
+ Register name without ComponentName applies to all components.
+ Register that is specific to -LP denoted by "_PCH_LP_" in component name.
+ - SubsystemName:
+ This field indicates the subsystem name of the component that the register belongs to
+ (e.g. PCIE, USB, SATA, GPIO, PMC etc.).
+ - RegisterSpace:
+ MEM - MMIO space register of subsystem.
+ IO - IO space register of subsystem.
+ PCR - Private configuration register of subsystem.
+ CFG - PCI configuration space register of subsystem.
+ - RegisterName:
+ Full register name.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PCH_REGS_LPC_H_
+#define _PCH_REGS_LPC_H_
+
+#define B_LPC_CFG_DID 0xFFE0
+
+//
+// PCI to LPC Bridge Registers
+//
+
+#define R_LPC_CFG_IOD 0x80
+#define V_LPC_CFG_IOD_COMB_2F8 1
+#define V_LPC_CFG_IOD_COMA_3F8 0
+#define V_LPC_CFG_IOD_COMA_2F8 1
+#define R_LPC_CFG_IOE 0x82
+#define B_LPC_CFG_IOE_SE BIT12 ///< Super I/O Enable, Enables decoding of I/O locations 2Eh and 2Fh to LPC.
+#define B_LPC_CFG_IOE_KE BIT10 ///< Keyboard Enable, Enables decoding of the keyboard I/O locations 60h and 64h to LPC.
+#define B_LPC_CFG_IOE_PPE BIT2 ///< Parallel Port Enable, Enables decoding of the LPT range to LPC. Range is selected by LIOD.LPT.
+#define B_LPC_CFG_IOE_CBE BIT1 ///< Com Port B Enable, Enables decoding of the COMB range to LPC. Range is selected LIOD.CB.
+#define B_LPC_CFG_IOE_CAE BIT0 ///< Com Port A Enable, Enables decoding of the COMA range to LPC. Range is selected LIOD.CA.
+#define R_LPC_CFG_ULKMC 0x94
+#define B_LPC_CFG_ULKMC_A20PASSEN BIT5
+#define B_LPC_CFG_ULKMC_64WEN BIT3
+#define B_LPC_CFG_ULKMC_64REN BIT2
+#define B_LPC_CFG_ULKMC_60WEN BIT1
+#define B_LPC_CFG_ULKMC_60REN BIT0
+#define R_LPC_CFG_LGMR 0x98
+#define B_LPC_CFG_LGMR_MA 0xFFFF0000
+#define B_LPC_CFG_LGMR_LMRD_EN BIT0
+#define R_ESPI_CFG_CS1IORE 0xA0
+#define R_ESPI_CFG_CS1GMR1 0xA8
+
+#define R_LPC_CFG_BDE 0xD8 ///< BIOS decode enable
+
+//
+// APM Registers
+//
+#define R_PCH_IO_APM_CNT 0xB2
+#define R_PCH_IO_APM_STS 0xB3
+
+#define R_LPC_CFG_BC 0xDC ///< Bios Control
+#define S_LPC_CFG_BC 1
+#define N_LPC_CFG_BC_LE 1
+#define B_LPC_CFG_BC_WPD BIT0 ///< Write Protect Disable
+
+#define R_ESPI_CFG_PCBC 0xDC ///< Peripheral Channel BIOS Control
+#define S_ESPI_CFG_PCBC 4 ///< Peripheral Channel BIOS Control register size
+#define B_ESPI_CFG_PCBC_BWRE BIT11 ///< BIOS Write Report Enable
+#define B_ESPI_CFG_PCBC_BWRS BIT10 ///< BIOS Write Report Status
+#define B_ESPI_CFG_PCBC_BWPDS BIT8 ///< BIOS Write Protect Disable Status
+#define N_ESPI_CFG_PCBC_BWPDS 8 ///< BIOS Write Protect Disable Status bit position
+#define B_ESPI_CFG_PCBC_ESPI_EN BIT2 ///< eSPI Enable Pin Strap
+#define B_ESPI_CFG_PCBC_LE BIT1 ///< Lock Enable
+#define N_ESPI_CFG_PCBC_LE 1
+
+//
+// eSPI slave registers
+//
+#define B_ESPI_SLAVE_BME BIT2 ///< Bus Master Enable
+
+//
+// Reset Generator I/O Port
+//
+#define R_PCH_IO_RST_CNT 0xCF9
+#define V_PCH_IO_RST_CNT_FULLRESET 0x0E
+#define V_PCH_IO_RST_CNT_HARDRESET 0x06
+
+//
+// eSPI PCR Registers
+//
+#define R_ESPI_PCR_SLV_CFG_REG_CTL 0x4000 ///< Slave Configuration Register and Link Control
+#define B_ESPI_PCR_SLV_CFG_REG_CTL_SCRE BIT31 ///< Slave Configuration Register Access Enable
+#define B_ESPI_PCR_SLV_CFG_REG_CTL_SCRS (BIT30 | BIT29 | BIT28) ///< Slave Configuration Register Access Status
+#define N_ESPI_PCR_SLV_CFG_REG_CTL_SCRS 28 ///< Slave Configuration Register Access Status bit position
+#define B_ESPI_PCR_SLV_CFG_REG_CTL_SBLCL BIT27 ///< IOSF-SB eSPI Link Configuration Lock
+#define V_ESPI_PCR_SLV_CFG_REG_CTL_SCRS_NOERR 7 ///< No errors (transaction completed successfully)
+#define B_ESPI_PCR_SLV_CFG_REG_CTL_SID (BIT20 | BIT19) ///< Slave ID
+#define N_ESPI_PCR_SLV_CFG_REG_CTL_SID 19 ///< Slave ID bit position
+#define B_ESPI_PCR_SLV_CFG_REG_CTL_SCRT (BIT17 | BIT16) ///< Slave Configuration Register Access Type
+#define N_ESPI_PCR_SLV_CFG_REG_CTL_SCRT 16 ///< Slave Configuration Register Access Type bit position
+#define B_ESPI_PCR_SLV_CFG_REG_CTL_SCRA 0x00000FFF ///< Slave Configuration Register Address
+#define R_ESPI_PCR_SLV_CFG_REG_DATA 0x4004 ///< Slave Configuration Register Data
+
+#define R_ESPI_PCR_PCERR_SLV0 0x4020 ///< Peripheral Channel Error for Slave 0
+#define B_ESPI_PCR_PCERR_PCURD BIT24 ///< Peripheral Channel Unsupported Request Detected
+#define R_ESPI_PCR_VWERR_SLV0 0x4030 ///< Virtual Wire Channel Error for Slave 0
+#define R_ESPI_PCR_FCERR_SLV0 0x4040 ///< Flash Access Channel Error for Slave 0
+#define B_ESPI_PCR_FCERR_SAFBLK BIT17 ///< SAF Blocked (SAFBLK)
+#define B_ESPI_PCR_XERR_XNFEE (BIT14 | BIT13) ///< Non-Fatal Error Reporting Enable bits
+#define N_ESPI_PCR_XERR_XNFEE 13 ///< Non-Fatal Error Reporting Enable bit position
+#define V_ESPI_PCR_XERR_XNFEE_SMI 3 ///< Enable Non-Fatal Error Reporting as SMI
+#define B_ESPI_PCR_XERR_XNFES BIT12 ///< Fatal Error Status
+#define B_ESPI_PCR_XERR_XFEE (BIT6 | BIT5) ///< Fatal Error Reporting Enable bits
+#define N_ESPI_PCR_XERR_XFEE 5 ///< Fatal Error Reporting Enable bit position
+#define V_ESPI_PCR_XERR_XFEE_SMI 3 ///< Enable Fatal Error Reporting as SMI
+#define B_ESPI_PCR_XERR_XFES BIT4 ///< Fatal Error Status
+#define S_ESPI_PCR_XERR 4 ///< Channel register sizes
+#define B_ESPI_PCR_PCERR_SLV0_PCURD BIT24 ///< Peripheral Channel Unsupported Request Detected
+#define R_ESPI_PCR_LNKERR_SLV0 0x4050 ///< Link Error for Slave 0
+#define S_ESPI_PCR_LNKERR_SLV0 4 ///< Link Error for Slave 0 register size
+#define B_ESPI_PCR_LNKERR_SLV0_SLCRR BIT31 ///< eSPI Link and Slave Channel Recovery Required
+#define B_ESPI_PCR_LNKERR_SLV0_LFET1E (BIT22 | BIT21) ///< Fatal Error Type 1 Reporting Enable
+#define N_ESPI_PCR_LNKERR_SLV0_LFET1E 21 ///< Fatal Error Type 1 Reporting Enable bit position
+#define V_ESPI_PCR_LNKERR_SLV0_LFET1E_SMI 3 ///< Enable Fatal Error Type 1 Reporting as SMI
+#define B_ESPI_PCR_LNKERR_SLV0_LFET1S BIT20 ///< Link Fatal Error Type 1 Status
+#define R_ESPI_PCR_LNKERR_SLV1 0x4054 ///< Link Error for Slave 1
+#define R_ESPI_PCR_CFG_VAL 0xC00C ///< ESPI Enabled Strap
+#define B_ESPI_PCR_CFG_VAL_ESPI_EN BIT0 ///< ESPI Enabled Strap bit position
+#define R_ESPI_PCR_SOFTSTRAPS 0xC210 ///< eSPI Sofstraps Register 0
+#define B_ESPI_PCR_SOFTSTRAPS_CS1_EN BIT12 ///< CS1# Enable
+
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/Register/PchRegsPsf.h b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/Register/PchRegsPsf.h
new file mode 100644
index 0000000000..dc32f1e5b3
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/Register/PchRegsPsf.h
@@ -0,0 +1,50 @@
+/** @file
+ Register definition for PSF component
+
+ Conventions:
+
+ - Register definition format:
+ Prefix_[GenerationName]_[ComponentName]_SubsystemName_RegisterSpace_RegisterName
+ - Prefix:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register size
+ Definitions beginning with "N_" are the bit position
+ - [GenerationName]:
+ Three letter acronym of the generation is used (e.g. SKL,KBL,CNL etc.).
+ Register name without GenerationName applies to all generations.
+ - [ComponentName]:
+ This field indicates the component name that the register belongs to (e.g. PCH, SA etc.)
+ Register name without ComponentName applies to all components.
+ Register that is specific to -LP denoted by "_PCH_LP_" in component name.
+ - SubsystemName:
+ This field indicates the subsystem name of the component that the register belongs to
+ (e.g. PCIE, USB, SATA, GPIO, PMC etc.).
+ - RegisterSpace:
+ MEM - MMIO space register of subsystem.
+ IO - IO space register of subsystem.
+ PCR - Private configuration register of subsystem.
+ CFG - PCI configuration space register of subsystem.
+ - RegisterName:
+ Full register name.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PCH_REGS_PSF_H_
+#define _PCH_REGS_PSF_H_
+//
+// PSFx segment registers
+//
+
+#define N_PCH_PSFX_PCR_MC_CONTROL_MCASTX_NUMMC 1
+#define B_PCH_PSFX_PCR_MC_CONTROL_MCASTX_MULTCEN BIT0
+
+//
+// PSFx PCRs definitions
+//
+#define B_PCH_PSFX_PCR_TARGET_PSFID 0xFF0000
+#define N_PCH_PSFX_PCR_TARGET_PSFID 16
+
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/Register/PchRegsPsth.h b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/Register/PchRegsPsth.h
new file mode 100644
index 0000000000..2007eae44f
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Include/Register/PchRegsPsth.h
@@ -0,0 +1,66 @@
+/** @file
+ Register definition for PSTH component
+
+ Conventions:
+
+ - Register definition format:
+ Prefix_[GenerationName]_[ComponentName]_SubsystemName_RegisterSpace_RegisterName
+ - Prefix:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register size
+ Definitions beginning with "N_" are the bit position
+ - [GenerationName]:
+ Three letter acronym of the generation is used (e.g. SKL,KBL,CNL etc.).
+ Register name without GenerationName applies to all generations.
+ - [ComponentName]:
+ This field indicates the component name that the register belongs to (e.g. PCH, SA etc.)
+ Register name without ComponentName applies to all components.
+ Register that is specific to -LP denoted by "_PCH_LP_" in component name.
+ - SubsystemName:
+ This field indicates the subsystem name of the component that the register belongs to
+ (e.g. PCIE, USB, SATA, GPIO, PMC etc.).
+ - RegisterSpace:
+ MEM - MMIO space register of subsystem.
+ IO - IO space register of subsystem.
+ PCR - Private configuration register of subsystem.
+ CFG - PCI configuration space register of subsystem.
+ - RegisterName:
+ Full register name.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PCH_REGS_PSTH_H_
+#define _PCH_REGS_PSTH_H_
+
+//
+// Private chipset regsiter (Memory space) offset definition
+// The PCR register defines is used for PCR MMIO programming and PCH SBI programming as well.
+//
+
+//
+// PSTH and IO Trap PCRs (PID:PSTH)
+//
+#define R_PSTH_PCR_PSTHCTL 0x1D00 ///< PSTH control register
+#define B_PSTH_PCR_PSTHIOSFPTCGE BIT2 ///< PSTH IOSF primary trunk clock gating enable
+#define R_PSTH_PCR_TRPST 0x1E00 ///< Trap status regsiter
+#define R_PSTH_PCR_TRPC 0x1E10 ///< Trapped cycle
+#define B_PSTH_PCR_TRPC_RW BIT24 ///< Read/Write#: 1=Read, 0=Write
+#define B_PSTH_PCR_TRPC_AHBE 0x00000000000F0000 ///< Active high byte enables
+#define B_PSTH_PCR_TRPC_IOA 0x000000000000FFFC ///< Trap cycle I/O address
+#define R_PSTH_PCR_TRPD 0x1E18 ///< Trapped write data
+#define R_PSTH_PCR_TRPREG0 0x1E80 ///< IO Tarp 0 register
+#define R_PSTH_PCR_TRPREG1 0x1E88 ///< IO Tarp 1 register
+#define R_PSTH_PCR_TRPREG2 0x1E90 ///< IO Tarp 2 register
+#define R_PSTH_PCR_TRPREG3 0x1E98 ///< IO Tarp 3 register
+#define B_PSTH_PCR_TRPREG_RWM BIT17 ///< 49 - 32 for 32 bit access, Read/Write mask
+#define B_PSTH_PCR_TRPREG_RWIO BIT16 ///< 48 - 32 for 32 bit access, Read/Write#, 1=Read, 0=Write
+#define N_PSTH_PCR_TRPREG_RWIO 16 ///< 48 - 32 for 32 bit access, 16bit shift for Read/Write field
+#define N_PSTH_PCR_TRPREG_BEM 36
+#define N_PSTH_PCR_TRPREG_BE 32
+#define B_PSTH_PCR_TRPREG_AD 0x000000000000FFFC ///< IO Address
+#define B_PSTH_PCR_TRPREG_TSE BIT0 ///< Trap and SMI# Enable
+
+#endif
--
2.24.0.windows.2
^ permalink raw reply related [flat|nested] 42+ messages in thread
* [Patch V3 06/40] TigerlakeSiliconPkg/Pch: Add IncludePrivate headers
2021-02-05 7:40 [Patch V3 01/40] TigerlakeSiliconPkg: Add package and Include/ConfigBlock headers Heng Luo
` (3 preceding siblings ...)
2021-02-05 7:40 ` [Patch V3 05/40] TigerlakeSiliconPkg/Pch: Add include headers Heng Luo
@ 2021-02-05 7:40 ` Heng Luo
2021-02-05 7:40 ` [Patch V3 07/40] TigerlakeSiliconPkg/SystemAgent: Add include headers Heng Luo
` (33 subsequent siblings)
38 siblings, 0 replies; 42+ messages in thread
From: Heng Luo @ 2021-02-05 7:40 UTC (permalink / raw)
To: devel; +Cc: Sai Chaganty, Nate DeSimone
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3171
Adds the following header files:
* Pch/IncludePrivate
Cc: Sai Chaganty <rangasai.v.chaganty@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Signed-off-by: Heng Luo <heng.luo@intel.com>
---
Silicon/Intel/TigerlakeSiliconPkg/Pch/IncludePrivate/Library/SiScheduleResetLib.h | 47 +++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/IncludePrivate/Library/SmmPchPrivateLib.h | 26 ++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/IncludePrivate/PchConfigHob.h | 269 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/IncludePrivate/PchHybridStorageHob.h | 21 +++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/IncludePrivate/PchNvsAreaDef.h | 319 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/IncludePrivate/PchRstHob.h | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/IncludePrivate/Protocol/PchNvsArea.h | 30 ++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/IncludePrivate/Protocol/PcieIoTrap.h | 35 +++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/IncludePrivate/SiScheduleResetHob.h | 21 +++++++++++++++++++++
9 files changed, 826 insertions(+)
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/IncludePrivate/Library/SiScheduleResetLib.h b/Silicon/Intel/TigerlakeSiliconPkg/Pch/IncludePrivate/Library/SiScheduleResetLib.h
new file mode 100644
index 0000000000..2ad80a0269
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/IncludePrivate/Library/SiScheduleResetLib.h
@@ -0,0 +1,47 @@
+/** @file
+ Reset scheduling library services
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _SI_SCHEDULE_RESET_LIB_H_
+#define _SI_SCHEDULE_RESET_LIB_H_
+
+#include <Uefi/UefiMultiPhase.h>
+#include <PchResetPlatformSpecific.h>
+
+/**
+ This function updates the reset information in SiScheduleResetHob
+ @param[in] ResetType UEFI defined reset type.
+ @param[in] ResetData Optional element used to introduce a platform specific reset.
+ The exact type of the reset is defined by the EFI_GUID that follows
+ the Null-terminated Unicode string.
+**/
+VOID
+SiScheduleResetSetType (
+ IN EFI_RESET_TYPE ResetType,
+ IN PCH_RESET_DATA *ResetData OPTIONAL
+ );
+
+/**
+ This function returns TRUE or FALSE depending on whether a reset is required based on SiScheduleResetHob
+
+ @retval BOOLEAN The function returns FALSE if no reset is required
+**/
+BOOLEAN
+SiScheduleResetIsRequired (
+ VOID
+ );
+
+/**
+ This function performs reset based on SiScheduleResetHob
+
+ @retval BOOLEAN The function returns FALSE if no reset is required
+**/
+BOOLEAN
+SiScheduleResetPerformReset (
+ VOID
+ );
+
+#endif //_SI_SCHEDULE_RESET_LIB_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/IncludePrivate/Library/SmmPchPrivateLib.h b/Silicon/Intel/TigerlakeSiliconPkg/Pch/IncludePrivate/Library/SmmPchPrivateLib.h
new file mode 100644
index 0000000000..955dac5a82
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/IncludePrivate/Library/SmmPchPrivateLib.h
@@ -0,0 +1,26 @@
+/** @file
+ Header file for private PCH SMM Lib.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _SMM_PCH_PRIVATE_LIB_H_
+#define _SMM_PCH_PRIVATE_LIB_H_
+
+/**
+ Set InSmm.Sts bit
+**/
+VOID
+PchSetInSmmSts (
+ VOID
+ );
+
+/**
+ Clear InSmm.Sts bit
+**/
+VOID
+PchClearInSmmSts (
+ VOID
+ );
+
+#endif // _SMM_PCH_PRIVATE_LIB_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/IncludePrivate/PchConfigHob.h b/Silicon/Intel/TigerlakeSiliconPkg/Pch/IncludePrivate/PchConfigHob.h
new file mode 100644
index 0000000000..13a41f8d04
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/IncludePrivate/PchConfigHob.h
@@ -0,0 +1,269 @@
+/** @file
+ The GUID definition for PchConfigHob
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PCH_CONFIG_HOB_H_
+#define _PCH_CONFIG_HOB_H_
+
+#include <ConfigBlock.h>
+#include <SmbusConfig.h>
+#include <InterruptConfig.h>
+#include <PchPcieRpConfig.h>
+#include <SataConfig.h>
+#include <RstConfig.h>
+#include <ConfigBlock/FlashProtectionConfig.h>
+#include <FivrConfig.h>
+#include <ThcConfig.h>
+#include <SerialIoConfig.h>
+
+
+extern EFI_GUID gPchConfigHobGuid;
+
+#pragma pack (push,1)
+
+/**
+ This structure contains the HOB which are related to PCH general config.
+**/
+typedef struct {
+ /**
+ This member describes whether or not the Compatibility Revision ID (CRID) feature
+ of PCH should be enabled. <b>0: Disable</b>; 1: Enable
+ **/
+ UINT32 Crid : 1;
+ UINT32 RsvdBits0 : 31; ///< Reserved bits
+} GENERAL_HOB;
+
+/**
+ The SMBUS_CONFIG block lists the reserved addresses for non-ARP capable devices in the platform.
+**/
+typedef struct {
+ UINT8 RsvdBytes[3]; ///< Reserved bytes
+ UINT8 NumRsvdSmbusAddresses; ///< The number of elements in the RsvdSmbusAddressTable.
+ /**
+ Array of addresses reserved for non-ARP-capable SMBus devices.
+ **/
+ UINT8 RsvdSmbusAddressTable[PCH_MAX_SMBUS_RESERVED_ADDRESS];
+} SMBUS_HOB;
+
+/**
+ The INTERRUPT_HOB describes interrupt settings for PCH.
+**/
+typedef struct {
+ UINT8 NumOfDevIntConfig; ///< Number of entries in DevIntConfig table
+ UINT8 GpioIrqRoute; ///< Interrupt routing for GPIO. Default is <b>14</b>.
+ UINT8 Rsvd0[2]; ///< Reserved bytes, align to multiple 4.
+ PCH_DEVICE_INTERRUPT_CONFIG DevIntConfig[PCH_MAX_DEVICE_INTERRUPT_CONFIG]; ///< Array which stores PCH devices interrupts settings
+} INTERRUPT_HOB;
+
+/**
+ The SERIAL_IO block provides the configurations to set the Serial IO controllers
+**/
+typedef struct {
+ SERIAL_IO_SPI_CONFIG SpiDeviceConfig[PCH_MAX_SERIALIO_SPI_CONTROLLERS]; ///< SPI Configuration
+ SERIAL_IO_I2C_CONFIG I2cDeviceConfig[PCH_MAX_SERIALIO_I2C_CONTROLLERS]; ///< I2C Configuration
+ SERIAL_IO_UART_CONFIG UartDeviceConfig[PCH_MAX_SERIALIO_UART_CONTROLLERS]; ///< UART Configuration
+} SERIAL_IO_HOB;
+
+/**
+ The PCIERP_HOB block describes the expected configuration of the PCH PCI Express controllers
+**/
+typedef struct {
+ ///
+ /// These members describe the configuration of each PCH PCIe root port.
+ ///
+ PCH_PCIE_ROOT_PORT_CONFIG RootPort[PCH_MAX_PCIE_ROOT_PORTS];
+ PCH_PCIE_CLOCK PcieClock[PCH_MAX_PCIE_CLOCKS];
+ /**
+ This member allows BIOS to control ICC PLL Shutdown by determining PCIe devices are LTR capable
+ or leaving untouched.
+ - <b>0: Disable, ICC PLL Shutdown is determined by PCIe device LTR capablility.</b>
+ - To allow ICC PLL shutdown if all present PCIe devices are LTR capable or if no PCIe devices are
+ presented for maximum power savings where possible.
+ - To disable ICC PLL shutdown when BIOS detects any non-LTR capable PCIe device for ensuring device
+ functionality.
+ - 1: Enable, To allow ICC PLL shutdown even if some devices do not support LTR capability.
+ **/
+ UINT32 AllowNoLtrIccPllShutdown : 1;
+ UINT32 RsvdBits0 : 31; ///< Reserved bits
+} PCIERP_HOB;
+
+/**
+ The HDAUDIO_HOB block describes the configuration of the PCH cAVS controller
+**/
+typedef struct {
+ UINT32 DspEnable : 1; ///< DSP enablement: 0: Disable; <b>1: Enable</b>
+ UINT32 DspUaaCompliance : 1; ///< UAA-mode Select: <b>0: Non-Uaa</b>; 1: UAA
+ UINT32 CodecSxWakeCapability : 1; ///< Capability to detect wake initiated by a codec in Sx, <b>0: Disable</b>; 1: Enable
+ UINT32 AudioLinkSndw1 : 1; ///< SoundWire1 link enablement: <b>0: Disable</b>; 1: Enable. Muxed with HDA
+ UINT32 AudioLinkSndw2 : 1; ///< SoundWire2 link enablement: <b>0: Disable</b>; 1: Enable. Muxed with SSP1
+ UINT32 AudioLinkSndw3 : 1; ///< SoundWire3 link enablement: <b>0: Disable</b>; 1: Enable. Muxed with DMIC1
+ UINT32 AudioLinkSndw4 : 1; ///< SoundWire4 link enablement: <b>0: Disable</b>; 1: Enable. Muxed with DMIC0
+ UINT32 Pme : 1; ///< Azalia wake-on-ring, <b>0: Disable</b>; 1: Enable
+ UINT32 RsvdBits0 : 24; ///< Reserved bits
+} HDAUDIO_HOB;
+
+/**
+ The SATA_HOB block describes the configuration of the PCH SATA controllers
+**/
+typedef struct {
+ /**
+ This member describes whether or not the SATA controllers should be enabled. 0: Disable; <b>1: Enable</b>.
+ **/
+ UINT32 Enable : 1;
+ UINT32 TestMode : 1; ///< <b>(Test)</b> <b>0: Disable</b>; 1: Allow entrance to the PCH SATA test modes
+ UINT32 RsvdBits0 : 30; ///< Reserved bits
+ /**
+ This member configures the features, property, and capability for each SATA port.
+ **/
+ PCH_SATA_PORT_CONFIG PortSettings[PCH_MAX_SATA_PORTS];
+} SATA_HOB;
+
+/**
+ The RST block describes the configuration of the RST PCIE Cycle Routers
+**/
+typedef struct {
+ /**
+ This member describes the details of implementation of Intel RST for PCIe Storage remapping (Intel RST Driver is required)
+ **/
+ RST_HARDWARE_REMAPPED_STORAGE_CONFIG RstHardwareRemappedStorageConfig[PCH_MAX_RST_PCIE_STORAGE_CR];
+} RST_HOB;
+
+typedef struct {
+ UINT32 Enabled : 1; ///< Indicates that SD card has been enabled
+ UINT32 Reserved : 31;
+} SD_CARD_HOB;
+
+/**
+ The EMMC_HOB block describes integrated eMMC settings for PCH.
+**/
+typedef struct {
+ UINT32 Enabled : 1; ///< Determine if eMMC is enabled - 0: Disabled, <b>1: Enabled</b>.
+ UINT32 Hs400Enabled : 1; ///< Determine eMMC HS400 Mode if EmmcEnabled - <b>0: Disabled</b>, 1: Enabled
+ /**
+ Determine if HS400 Training is required, set to FALSE if Hs400 Data is valid. <b>0: Disabled</b>, 1: Enabled.
+ First Boot or CMOS clear, system boot with Default settings, set tuning required.
+ Subsequent Boots, Get Variable 'Hs400TuningData'
+ - if failed to get variable, set tuning required
+ - if passed, retrieve Hs400DataValid, Hs400RxStrobe1Dll and Hs400TxDataDll from variable. Set tuning not required.
+ **/
+ UINT32 Hs400DllDataValid : 1; ///< Set if HS400 Tuning Data Valid
+ UINT32 RsvdBits : 29;
+} EMMC_HOB;
+
+/**
+ The PCH_LOCK_DOWN_CONFIG block describes the expected configuration of the PCH
+ for security requirement.
+**/
+typedef struct {
+ UINT32 GlobalSmi : 1;
+ /**
+ <b>(Test)</b> Enable BIOS Interface Lock Down bit to prevent writes to the Backup Control Register
+ Top Swap bit and the General Control and Status Registers Boot BIOS Straps. 0: Disable; <b>1: Enable</b>.
+ **/
+ UINT32 BiosInterface : 1;
+ /**
+ Enable the BIOS Lock Enable (BLE) feature and set EISS bit (D31:F5:RegDCh[5])
+ for the BIOS region protection. When it is enabled, the BIOS Region can only be
+ modified from SMM after EndOfDxe protocol is installed.
+ Note: When BiosLock is enabled, platform code also needs to update to take care
+ of BIOS modification (including SetVariable) in DXE or runtime phase after
+ EndOfDxe protocol is installed.
+ Enable InSMM.STS (EISS) in SPI
+ If this EISS bit is set, then WPD must be a '1' and InSMM.STS must be '1' also
+ in order to write to BIOS regions of SPI Flash. If this EISS bit is clear,
+ then the InSMM.STS is a don't care.
+ The BIOS must set the EISS bit while BIOS Guard support is enabled.
+ In recovery path, platform can temporary disable EISS for SPI programming in
+ PEI phase or early DXE phase.
+ 0: Disable; <b>1: Enable.</b>
+ **/
+ UINT32 BiosLock : 1;
+ UINT32 RsvdBits : 29;
+} LOCK_DOWN_HOB;
+
+/**
+ The PM_HOB block describes expected miscellaneous power management settings.
+ The PowerResetStatusClear field would clear the Power/Reset status bits, please
+ set the bits if you want PCH Init driver to clear it, if you want to check the
+ status later then clear the bits.
+**/
+typedef struct {
+ UINT32 PsOnEnable : 1; ///< Indicates if PS_ON support has been enabled, <b>0: Disable</b>; 1: Enable.
+ UINT32 EnableTimedGpio0 : 1; ///< Enable Bit for Timed GPIO 0 <b>0 = disable</b>; 1 = enable
+ UINT32 EnableTimedGpio1 : 1; ///< Enable Bit for Timed GPIO 1 <b>0 = disable</b>; 1 = enable
+ UINT32 RsvdBits1 : 29;
+} PM_HOB;
+
+/**
+ FIVR_HOB block
+**/
+typedef struct {
+ /**
+ Additional External Vnn VR rail configuration dedicated for Sx.
+ Required only if External Vnn VR needs different settings for Sx than
+ those specified in ExtVnnRail (refer to PCH_FIVR_CONFIG.ExtVnnRail)
+ **/
+ FIVR_EXT_RAIL_CONFIG ExtVnnRailSx;
+} FIVR_HOB;
+
+/**
+ PCH Trace Hub HOB settings.
+**/
+typedef struct {
+ UINT32 PchTraceHubMode : 2; ///< <b>0 = Disable</b>; 1 = Target Debugger mode; 2 = Host Debugger mode
+ UINT32 Rsvd1 : 30; ///< Reserved bits
+ /**
+ Trace hub memory buffer region size policy.
+ The avaliable memory size options are: 0:0MB (none), 1:1MB, <b>2:8MB</b>, 3:64MB, 4:128MB, 5:256MB, 6:512MB.
+ Note : Limitation of total buffer size (CPU + PCH) is 512MB. If iTbt is enabled, the total size limits to 256 MB.
+ Refer to TRACE_BUFFER_SIZE
+ **/
+ UINT32 MemReg0Size;
+ UINT32 MemReg1Size;
+} PCH_TRACEHUB_HOB;
+
+/**
+ PCH eSPI HOB settings.
+**/
+typedef struct {
+ UINT32 BmeMasterSlaveEnabled : 1; ///< <b>0 = BME disable</b>; 1 = BME enable
+ UINT32 RsvdBits : 31; ///< Reserved bits
+} PCH_ESPI_HOB;
+
+/**
+ THC HOB settings.
+**/
+typedef struct {
+ THC_PORT ThcPort[2]; ///< Port Configuration
+} THC_HOB;
+
+
+/**
+ This structure contains the HOBs which are related to PCH controllers
+**/
+typedef struct {
+ EFI_HOB_GUID_TYPE EfiHobGuidType; ///< GUID HOB type structure for gPchConfigHobGuid
+ GENERAL_HOB General; ///< Pch general HOB definition
+ INTERRUPT_HOB Interrupt; ///< Interrupt HOB definition
+ SERIAL_IO_HOB SerialIo; ///< Serial io HOB definition
+ PCIERP_HOB PcieRp; ///< PCIE root port HOB definition
+ SD_CARD_HOB SdCard; ///< SD card HOB definition
+ EMMC_HOB Emmc; ///< eMMC HOB definition
+ LOCK_DOWN_HOB LockDown; ///< Lock down HOB definition
+ PM_HOB Pm; ///< PM HOB definition
+ HDAUDIO_HOB HdAudio; ///< HD audio definition
+ SATA_HOB Sata[PCH_MAX_SATA_CONTROLLERS]; ///< SATA definition
+ RST_HOB Rst; ///< RST definition
+ PROTECTED_RANGE ProtectRange[PCH_FLASH_PROTECTED_RANGES];
+ SMBUS_HOB Smbus;
+ PCH_TRACEHUB_HOB PchTraceHub; ///< PCH Trace Hub definition
+ PCH_ESPI_HOB Espi; ///< PCH eSPI definition
+ THC_HOB Thc; ///< PCH Tocuh Host Controller definition
+ FIVR_HOB Fivr; ///< PCH FIVR HOB definition
+
+
+} PCH_CONFIG_HOB;
+#pragma pack (pop)
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/IncludePrivate/PchHybridStorageHob.h b/Silicon/Intel/TigerlakeSiliconPkg/Pch/IncludePrivate/PchHybridStorageHob.h
new file mode 100644
index 0000000000..040bc270e6
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/IncludePrivate/PchHybridStorageHob.h
@@ -0,0 +1,21 @@
+/** @file
+
+ Definitions required to create HybridStorageHob
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _PCH_HYBRIDSTORAGE_HOB_
+#define _PCH_HYBRIDSTORAGE_HOB_
+
+extern EFI_GUID gHybridStorageHobGuid;
+
+//
+// Passes to DXE Hybrid Storage location
+//
+typedef struct {
+ UINT32 HybridStorageLocation;
+} PCH_HYBRIDSTORAGE_HOB;
+
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/IncludePrivate/PchNvsAreaDef.h b/Silicon/Intel/TigerlakeSiliconPkg/Pch/IncludePrivate/PchNvsAreaDef.h
new file mode 100644
index 0000000000..200f3ca8fa
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/IncludePrivate/PchNvsAreaDef.h
@@ -0,0 +1,319 @@
+//
+// Automatically generated by GenNvs ver 2.4.6
+// Please DO NOT modify !!!
+//
+
+/** @file
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+ //
+ // Define PCH NVS Area operatino region.
+ //
+#ifndef _PCH_NVS_AREA_DEF_H_
+#define _PCH_NVS_AREA_DEF_H_
+
+#pragma pack (push,1)
+typedef struct {
+ UINT16 PchSeries; ///< Offset 0 PCH Series
+ UINT16 PchGeneration; ///< Offset 2 PCH Generation
+ UINT16 PchStepping; ///< Offset 4 PCH Stepping
+ UINT32 RpAddress[28]; ///< Offset 6 Root Port address 1
+ ///< Offset 10 Root Port address 2
+ ///< Offset 14 Root Port address 3
+ ///< Offset 18 Root Port address 4
+ ///< Offset 22 Root Port address 5
+ ///< Offset 26 Root Port address 6
+ ///< Offset 30 Root Port address 7
+ ///< Offset 34 Root Port address 8
+ ///< Offset 38 Root Port address 9
+ ///< Offset 42 Root Port address 10
+ ///< Offset 46 Root Port address 11
+ ///< Offset 50 Root Port address 12
+ ///< Offset 54 Root Port address 13
+ ///< Offset 58 Root Port address 14
+ ///< Offset 62 Root Port address 15
+ ///< Offset 66 Root Port address 16
+ ///< Offset 70 Root Port address 17
+ ///< Offset 74 Root Port address 18
+ ///< Offset 78 Root Port address 19
+ ///< Offset 82 Root Port address 20
+ ///< Offset 86 Root Port address 21
+ ///< Offset 90 Root Port address 22
+ ///< Offset 94 Root Port address 23
+ ///< Offset 98 Root Port address 24
+ ///< Offset 102 Root Port address 25
+ ///< Offset 106 Root Port address 26
+ ///< Offset 110 Root Port address 27
+ ///< Offset 114 Root Port address 28
+ UINT64 NHLA; ///< Offset 118 HD-Audio NHLT ACPI address
+ UINT32 NHLL; ///< Offset 126 HD-Audio NHLT ACPI length
+ UINT32 ADFM; ///< Offset 130 HD-Audio DSP Feature Mask
+ UINT8 SWQ0; ///< Offset 134 HD-Audio SoundWire Link #1 quirk mask
+ UINT8 SWQ1; ///< Offset 135 HD-Audio SoundWire Link #2 quirk mask
+ UINT8 SWQ2; ///< Offset 136 HD-Audio SoundWire Link #3 quirk mask
+ UINT8 SWQ3; ///< Offset 137 HD-Audio SoundWire Link #4 quirk mask
+ UINT8 ACS0; ///< Offset 138 HD-Audio SoundWire Link #1 Autonomous Clock Stop
+ UINT8 ACS1; ///< Offset 139 HD-Audio SoundWire Link #2 Autonomous Clock Stop
+ UINT8 ACS2; ///< Offset 140 HD-Audio SoundWire Link #3 Autonomous Clock Stop
+ UINT8 ACS3; ///< Offset 141 HD-Audio SoundWire Link #4 Autonomous Clock Stop
+ UINT8 DAI0; ///< Offset 142 HD-Audio SoundWire Link #1 Data On Active Interval Select
+ UINT8 DAI1; ///< Offset 143 HD-Audio SoundWire Link #2 Data On Active Interval Select
+ UINT8 DAI2; ///< Offset 144 HD-Audio SoundWire Link #3 Data On Active Interval Select
+ UINT8 DAI3; ///< Offset 145 HD-Audio SoundWire Link #4 Data On Active Interval Select
+ UINT8 DOD0; ///< Offset 146 HD-Audio SoundWire Link #1 Data On Delay Select
+ UINT8 DOD1; ///< Offset 147 HD-Audio SoundWire Link #2 Data On Delay Select
+ UINT8 DOD2; ///< Offset 148 HD-Audio SoundWire Link #3 Data On Delay Select
+ UINT8 DOD3; ///< Offset 149 HD-Audio SoundWire Link #4 Data On Delay Select
+ UINT8 SWMC; ///< Offset 150 HD-Audio SoundWire Master Count
+ UINT8 XTAL; ///< Offset 151 XTAL frequency: 0: 24MHz; 1: 38.4MHz; 2: Unsupported
+ UINT32 DSPM; ///< Offset 152 HD-Audio DSP Stolen Memory Base Address (@todo: Remove after CNL-LP B0)
+ UINT32 SBRG; ///< Offset 156 SBREG_BAR
+ UINT8 GEI0; ///< Offset 160 GPIO GroupIndex mapped to GPE_DW0
+ UINT8 GEI1; ///< Offset 161 GPIO GroupIndex mapped to GPE_DW1
+ UINT8 GEI2; ///< Offset 162 GPIO GroupIndex mapped to GPE_DW2
+ UINT8 GED0; ///< Offset 163 GPIO DW part of group mapped to GPE_DW0
+ UINT8 GED1; ///< Offset 164 GPIO DW part of group mapped to GPE_DW1
+ UINT8 GED2; ///< Offset 165 GPIO DW part of group mapped to GPE_DW2
+ UINT16 PcieLtrMaxSnoopLatency[28]; ///< Offset 166 PCIE LTR max snoop Latency 1
+ ///< Offset 168 PCIE LTR max snoop Latency 2
+ ///< Offset 170 PCIE LTR max snoop Latency 3
+ ///< Offset 172 PCIE LTR max snoop Latency 4
+ ///< Offset 174 PCIE LTR max snoop Latency 5
+ ///< Offset 176 PCIE LTR max snoop Latency 6
+ ///< Offset 178 PCIE LTR max snoop Latency 7
+ ///< Offset 180 PCIE LTR max snoop Latency 8
+ ///< Offset 182 PCIE LTR max snoop Latency 9
+ ///< Offset 184 PCIE LTR max snoop Latency 10
+ ///< Offset 186 PCIE LTR max snoop Latency 11
+ ///< Offset 188 PCIE LTR max snoop Latency 12
+ ///< Offset 190 PCIE LTR max snoop Latency 13
+ ///< Offset 192 PCIE LTR max snoop Latency 14
+ ///< Offset 194 PCIE LTR max snoop Latency 15
+ ///< Offset 196 PCIE LTR max snoop Latency 16
+ ///< Offset 198 PCIE LTR max snoop Latency 17
+ ///< Offset 200 PCIE LTR max snoop Latency 18
+ ///< Offset 202 PCIE LTR max snoop Latency 19
+ ///< Offset 204 PCIE LTR max snoop Latency 20
+ ///< Offset 206 PCIE LTR max snoop Latency 21
+ ///< Offset 208 PCIE LTR max snoop Latency 22
+ ///< Offset 210 PCIE LTR max snoop Latency 23
+ ///< Offset 212 PCIE LTR max snoop Latency 24
+ ///< Offset 214 PCIE LTR max snoop Latency 25
+ ///< Offset 216 PCIE LTR max snoop Latency 26
+ ///< Offset 218 PCIE LTR max snoop Latency 27
+ ///< Offset 220 PCIE LTR max snoop Latency 28
+ UINT16 PcieLtrMaxNoSnoopLatency[28]; ///< Offset 222 PCIE LTR max no snoop Latency 1
+ ///< Offset 224 PCIE LTR max no snoop Latency 2
+ ///< Offset 226 PCIE LTR max no snoop Latency 3
+ ///< Offset 228 PCIE LTR max no snoop Latency 4
+ ///< Offset 230 PCIE LTR max no snoop Latency 5
+ ///< Offset 232 PCIE LTR max no snoop Latency 6
+ ///< Offset 234 PCIE LTR max no snoop Latency 7
+ ///< Offset 236 PCIE LTR max no snoop Latency 8
+ ///< Offset 238 PCIE LTR max no snoop Latency 9
+ ///< Offset 240 PCIE LTR max no snoop Latency 10
+ ///< Offset 242 PCIE LTR max no snoop Latency 11
+ ///< Offset 244 PCIE LTR max no snoop Latency 12
+ ///< Offset 246 PCIE LTR max no snoop Latency 13
+ ///< Offset 248 PCIE LTR max no snoop Latency 14
+ ///< Offset 250 PCIE LTR max no snoop Latency 15
+ ///< Offset 252 PCIE LTR max no snoop Latency 16
+ ///< Offset 254 PCIE LTR max no snoop Latency 17
+ ///< Offset 256 PCIE LTR max no snoop Latency 18
+ ///< Offset 258 PCIE LTR max no snoop Latency 19
+ ///< Offset 260 PCIE LTR max no snoop Latency 20
+ ///< Offset 262 PCIE LTR max no snoop Latency 21
+ ///< Offset 264 PCIE LTR max no snoop Latency 22
+ ///< Offset 266 PCIE LTR max no snoop Latency 23
+ ///< Offset 268 PCIE LTR max no snoop Latency 24
+ ///< Offset 270 PCIE LTR max no snoop Latency 25
+ ///< Offset 272 PCIE LTR max no snoop Latency 26
+ ///< Offset 274 PCIE LTR max no snoop Latency 27
+ ///< Offset 276 PCIE LTR max no snoop Latency 28
+ UINT8 XHPC; ///< Offset 278 Number of HighSpeed ports implemented in XHCI controller
+ UINT8 XRPC; ///< Offset 279 Number of USBR ports implemented in XHCI controller
+ UINT8 XSPC; ///< Offset 280 Number of SuperSpeed ports implemented in XHCI controller
+ UINT8 XSPA; ///< Offset 281 Address of 1st SuperSpeed port
+ UINT32 HPTB; ///< Offset 282 HPET base address
+ UINT8 HPTE; ///< Offset 286 HPET enable
+ //SerialIo block
+ UINT8 SM0[7]; ///< Offset 287 SerialIo SPI Controller 0 Mode
+ ///< Offset 288 SerialIo SPI Controller 1 Mode
+ ///< Offset 289 SerialIo SPI Controller 2 Mode
+ ///< Offset 290 SerialIo SPI Controller 3 Mode
+ ///< Offset 291 SerialIo SPI Controller 4 Mode
+ ///< Offset 292 SerialIo SPI Controller 5 Mode
+ ///< Offset 293 SerialIo SPI Controller 6 Mode
+ UINT64 SC0[7]; ///< Offset 294 SerialIo SPI Controller 0 Pci Config
+ ///< Offset 302 SerialIo SPI Controller 1 Pci Config
+ ///< Offset 310 SerialIo SPI Controller 2 Pci Config
+ ///< Offset 318 SerialIo SPI Controller 3 Pci Config
+ ///< Offset 326 SerialIo SPI Controller 4 Pci Config
+ ///< Offset 334 SerialIo SPI Controller 5 Pci Config
+ ///< Offset 342 SerialIo SPI Controller 6 Pci Config
+ UINT8 IM0[8]; ///< Offset 350 SerialIo I2C Controller 0 Mode
+ ///< Offset 351 SerialIo I2C Controller 1 Mode
+ ///< Offset 352 SerialIo I2C Controller 2 Mode
+ ///< Offset 353 SerialIo I2C Controller 3 Mode
+ ///< Offset 354 SerialIo I2C Controller 4 Mode
+ ///< Offset 355 SerialIo I2C Controller 5 Mode
+ ///< Offset 356 SerialIo I2C Controller 6 Mode
+ ///< Offset 357 SerialIo I2C Controller 7 Mode
+ UINT64 IC0[8]; ///< Offset 358 SerialIo I2C Controller 0 Pci Config
+ ///< Offset 366 SerialIo I2C Controller 1 Pci Config
+ ///< Offset 374 SerialIo I2C Controller 2 Pci Config
+ ///< Offset 382 SerialIo I2C Controller 3 Pci Config
+ ///< Offset 390 SerialIo I2C Controller 4 Pci Config
+ ///< Offset 398 SerialIo I2C Controller 5 Pci Config
+ ///< Offset 406 SerialIo I2C Controller 6 Pci Config
+ ///< Offset 414 SerialIo I2C Controller 7 Pci Config
+ UINT8 UM0[7]; ///< Offset 422 SerialIo UART Controller 0 Mode
+ ///< Offset 423 SerialIo UART Controller 1 Mode
+ ///< Offset 424 SerialIo UART Controller 2 Mode
+ ///< Offset 425 SerialIo UART Controller 3 Mode
+ ///< Offset 426 SerialIo UART Controller 4 Mode
+ ///< Offset 427 SerialIo UART Controller 5 Mode
+ ///< Offset 428 SerialIo UART Controller 6 Mode
+ UINT64 UC0[7]; ///< Offset 429 SerialIo UART Controller 0 Pci Config
+ ///< Offset 437 SerialIo UART Controller 1 Pci Config
+ ///< Offset 445 SerialIo UART Controller 2 Pci Config
+ ///< Offset 453 SerialIo UART Controller 3 Pci Config
+ ///< Offset 461 SerialIo UART Controller 4 Pci Config
+ ///< Offset 469 SerialIo UART Controller 5 Pci Config
+ ///< Offset 477 SerialIo UART Controller 6 Pci Config
+ UINT8 UD0[7]; ///< Offset 485 SerialIo UART Controller 0 DmaEnable
+ ///< Offset 486 SerialIo UART Controller 1 DmaEnable
+ ///< Offset 487 SerialIo UART Controller 2 DmaEnable
+ ///< Offset 488 SerialIo UART Controller 3 DmaEnable
+ ///< Offset 489 SerialIo UART Controller 4 DmaEnable
+ ///< Offset 490 SerialIo UART Controller 5 DmaEnable
+ ///< Offset 491 SerialIo UART Controller 6 DmaEnable
+ UINT8 UP0[7]; ///< Offset 492 SerialIo UART Controller 0 Power Gating
+ ///< Offset 493 SerialIo UART Controller 1 Power Gating
+ ///< Offset 494 SerialIo UART Controller 2 Power Gating
+ ///< Offset 495 SerialIo UART Controller 3 Power Gating
+ ///< Offset 496 SerialIo UART Controller 4 Power Gating
+ ///< Offset 497 SerialIo UART Controller 5 Power Gating
+ ///< Offset 498 SerialIo UART Controller 6 Power Gating
+ UINT8 UI0[7]; ///< Offset 499 SerialIo UART Controller 0 Irq
+ ///< Offset 500 SerialIo UART Controller 1 Irq
+ ///< Offset 501 SerialIo UART Controller 2 Irq
+ ///< Offset 502 SerialIo UART Controller 3 Irq
+ ///< Offset 503 SerialIo UART Controller 4 Irq
+ ///< Offset 504 SerialIo UART Controller 5 Irq
+ ///< Offset 505 SerialIo UART Controller 6 Irq
+ //end of SerialIo block
+ UINT8 SGIR; ///< Offset 506 GPIO IRQ
+ UINT8 GPHD; ///< Offset 507 Hide GPIO ACPI device
+ UINT8 RstPcieStorageInterfaceType[3]; ///< Offset 508 RST PCIe Storage Cycle Router#1 Interface Type
+ ///< Offset 509 RST PCIe Storage Cycle Router#2 Interface Type
+ ///< Offset 510 RST PCIe Storage Cycle Router#3 Interface Type
+ UINT8 RstPcieStoragePmCapPtr[3]; ///< Offset 511 RST PCIe Storage Cycle Router#1 Power Management Capability Pointer
+ ///< Offset 512 RST PCIe Storage Cycle Router#2 Power Management Capability Pointer
+ ///< Offset 513 RST PCIe Storage Cycle Router#3 Power Management Capability Pointer
+ UINT8 RstPcieStoragePcieCapPtr[3]; ///< Offset 514 RST PCIe Storage Cycle Router#1 PCIe Capabilities Pointer
+ ///< Offset 515 RST PCIe Storage Cycle Router#2 PCIe Capabilities Pointer
+ ///< Offset 516 RST PCIe Storage Cycle Router#3 PCIe Capabilities Pointer
+ UINT16 RstPcieStorageL1ssCapPtr[3]; ///< Offset 517 RST PCIe Storage Cycle Router#1 L1SS Capability Pointer
+ ///< Offset 519 RST PCIe Storage Cycle Router#2 L1SS Capability Pointer
+ ///< Offset 521 RST PCIe Storage Cycle Router#3 L1SS Capability Pointer
+ UINT8 RstPcieStorageEpL1ssControl2[3]; ///< Offset 523 RST PCIe Storage Cycle Router#1 Endpoint L1SS Control Data2
+ ///< Offset 524 RST PCIe Storage Cycle Router#2 Endpoint L1SS Control Data2
+ ///< Offset 525 RST PCIe Storage Cycle Router#3 Endpoint L1SS Control Data2
+ UINT32 RstPcieStorageEpL1ssControl1[3]; ///< Offset 526 RST PCIe Storage Cycle Router#1 Endpoint L1SS Control Data1
+ ///< Offset 530 RST PCIe Storage Cycle Router#2 Endpoint L1SS Control Data1
+ ///< Offset 534 RST PCIe Storage Cycle Router#3 Endpoint L1SS Control Data1
+ UINT16 RstPcieStorageLtrCapPtr[3]; ///< Offset 538 RST PCIe Storage Cycle Router#1 LTR Capability Pointer
+ ///< Offset 540 RST PCIe Storage Cycle Router#2 LTR Capability Pointer
+ ///< Offset 542 RST PCIe Storage Cycle Router#3 LTR Capability Pointer
+ UINT32 RstPcieStorageEpLtrData[3]; ///< Offset 544 RST PCIe Storage Cycle Router#1 Endpoint LTR Data
+ ///< Offset 548 RST PCIe Storage Cycle Router#2 Endpoint LTR Data
+ ///< Offset 552 RST PCIe Storage Cycle Router#3 Endpoint LTR Data
+ UINT16 RstPcieStorageEpLctlData16[3]; ///< Offset 556 RST PCIe Storage Cycle Router#1 Endpoint LCTL Data
+ ///< Offset 558 RST PCIe Storage Cycle Router#2 Endpoint LCTL Data
+ ///< Offset 560 RST PCIe Storage Cycle Router#3 Endpoint LCTL Data
+ UINT16 RstPcieStorageEpDctlData16[3]; ///< Offset 562 RST PCIe Storage Cycle Router#1 Endpoint DCTL Data
+ ///< Offset 564 RST PCIe Storage Cycle Router#2 Endpoint DCTL Data
+ ///< Offset 566 RST PCIe Storage Cycle Router#3 Endpoint DCTL Data
+ UINT16 RstPcieStorageEpDctl2Data16[3]; ///< Offset 568 RST PCIe Storage Cycle Router#1 Endpoint DCTL2 Data
+ ///< Offset 570 RST PCIe Storage Cycle Router#2 Endpoint DCTL2 Data
+ ///< Offset 572 RST PCIe Storage Cycle Router#3 Endpoint DCTL2 Data
+ UINT16 RstPcieStorageRpDctl2Data16[3]; ///< Offset 574 RST PCIe Storage Cycle Router#1 RootPort DCTL2 Data
+ ///< Offset 576 RST PCIe Storage Cycle Router#2 RootPort DCTL2 Data
+ ///< Offset 578 RST PCIe Storage Cycle Router#3 RootPort DCTL2 Data
+ UINT32 RstPcieStorageUniqueTableBar[3]; ///< Offset 580 RST PCIe Storage Cycle Router#1 Endpoint unique MSI-X Table BAR
+ ///< Offset 584 RST PCIe Storage Cycle Router#2 Endpoint unique MSI-X Table BAR
+ ///< Offset 588 RST PCIe Storage Cycle Router#3 Endpoint unique MSI-X Table BAR
+ UINT32 RstPcieStorageUniqueTableBarValue[3]; ///< Offset 592 RST PCIe Storage Cycle Router#1 Endpoint unique MSI-X Table BAR value
+ ///< Offset 596 RST PCIe Storage Cycle Router#2 Endpoint unique MSI-X Table BAR value
+ ///< Offset 600 RST PCIe Storage Cycle Router#3 Endpoint unique MSI-X Table BAR value
+ UINT32 RstPcieStorageUniquePbaBar[3]; ///< Offset 604 RST PCIe Storage Cycle Router#1 Endpoint unique MSI-X PBA BAR
+ ///< Offset 608 RST PCIe Storage Cycle Router#2 Endpoint unique MSI-X PBA BAR
+ ///< Offset 612 RST PCIe Storage Cycle Router#3 Endpoint unique MSI-X PBA BAR
+ UINT32 RstPcieStorageUniquePbaBarValue[3]; ///< Offset 616 RST PCIe Storage Cycle Router#1 Endpoint unique MSI-X PBA BAR value
+ ///< Offset 620 RST PCIe Storage Cycle Router#2 Endpoint unique MSI-X PBA BAR value
+ ///< Offset 624 RST PCIe Storage Cycle Router#3 Endpoint unique MSI-X PBA BAR value
+ UINT32 RstPcieStorageRootPortNum[3]; ///< Offset 628 RST PCIe Storage Cycle Router#1 Root Port number
+ ///< Offset 632 RST PCIe Storage Cycle Router#2 Root Port number
+ ///< Offset 636 RST PCIe Storage Cycle Router#3 Root Port number
+ UINT8 EMH4; ///< Offset 640 eMMC HS400 mode enabled
+ UINT8 EMDS; ///< Offset 641 eMMC Driver Strength
+ UINT8 CpuSku; ///< Offset 642 CPU SKU
+ UINT16 IoTrapAddress[4]; ///< Offset 643
+ UINT8 IoTrapStatus[4]; ///< Offset 651
+ UINT16 PMBS; ///< Offset 655 ACPI IO BASE address
+ UINT32 PWRM; ///< Offset 657 PWRM MEM BASE address
+ // CNVi specific
+ UINT8 CnviMode; ///< Offset 661 CNVi mode
+ UINT8 CnviBtCore; ///< Offset 662 CNVi BT Core
+ UINT8 CnviBtAudioOffload; ///< Offset 663 CNVi BT Audio Offload
+ // PCH Trace Hub
+ UINT8 PchTraceHubMode; ///< Offset 664 PCH Trace Hub Mode
+ // PCH PS_ON support
+ UINT8 PsOnEnable; ///< Offset 665 PCH PS_ON enable
+ //
+ // These are for PchApciTablesSelfTest use
+ //
+ UINT8 LtrEnable[24]; ///< Offset 666 Latency Tolerance Reporting Enable
+ ///< Offset 667 Latency Tolerance Reporting Enable
+ ///< Offset 668 Latency Tolerance Reporting Enable
+ ///< Offset 669 Latency Tolerance Reporting Enable
+ ///< Offset 670 Latency Tolerance Reporting Enable
+ ///< Offset 671 Latency Tolerance Reporting Enable
+ ///< Offset 672 Latency Tolerance Reporting Enable
+ ///< Offset 673 Latency Tolerance Reporting Enable
+ ///< Offset 674 Latency Tolerance Reporting Enable
+ ///< Offset 675 Latency Tolerance Reporting Enable
+ ///< Offset 676 Latency Tolerance Reporting Enable
+ ///< Offset 677 Latency Tolerance Reporting Enable
+ ///< Offset 678 Latency Tolerance Reporting Enable
+ ///< Offset 679 Latency Tolerance Reporting Enable
+ ///< Offset 680 Latency Tolerance Reporting Enable
+ ///< Offset 681 Latency Tolerance Reporting Enable
+ ///< Offset 682 Latency Tolerance Reporting Enable
+ ///< Offset 683 Latency Tolerance Reporting Enable
+ ///< Offset 684 Latency Tolerance Reporting Enable
+ ///< Offset 685 Latency Tolerance Reporting Enable
+ ///< Offset 686 Latency Tolerance Reporting Enable
+ ///< Offset 687 Latency Tolerance Reporting Enable
+ ///< Offset 688 Latency Tolerance Reporting Enable
+ ///< Offset 689 Latency Tolerance Reporting Enable
+ UINT8 GBES; ///< Offset 690 GbE Support
+ UINT32 PchxDCIPwrDnScale; ///< Offset 691 PCH xDCI Power Down Scale Value, DWC_USB3_GCTL_INIT[31:19]
+ UINT8 EmmcEnabled; ///< Offset 695 Set to indicate that eMMC is enabled
+ UINT8 SdCardEnabled; ///< Offset 696 Set to indicate that SD card is enabled
+ UINT8 EnableTimedGpio0; ///< Offset 697 Set to indicate that Timed GPIO 0 is enabled
+ UINT8 EnableTimedGpio1; ///< Offset 698 Set to indicate that Timed GPIO 1 is enabled
+ UINT8 ClockToRootPortMap[18]; ///< Offset 699 CLOCK index to root port index map. Used during PCIe D3Cold flows
+ UINT16 TcoBase; ///< Offset 717 TCO base address
+ UINT16 IclkPid; ///< Offset 719 Iclk PID number
+ UINT16 CnviPortId; ///< Offset 721 CNVi sideband port id
+ UINT32 HybridStorageLocation; ///< Offset 723
+ UINT8 SataPortPresence; ///< Offset 727 Holds information from SATA PCS register about SATA ports which recieved COMINIT from connected devices.
+} PCH_NVS_AREA;
+
+#pragma pack(pop)
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/IncludePrivate/PchRstHob.h b/Silicon/Intel/TigerlakeSiliconPkg/Pch/IncludePrivate/PchRstHob.h
new file mode 100644
index 0000000000..428858afcf
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/IncludePrivate/PchRstHob.h
@@ -0,0 +1,58 @@
+/** @file
+
+ Definitions required to create RstHob
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _PCH_RST_HOB_
+#define _PCH_RST_HOB_
+
+extern EFI_GUID gPchRstHobGuid;
+
+//
+// This struct is used to record the fields that should be restored during device wake up
+//
+typedef struct {
+ UINT8 PmCapPtr;
+ UINT8 PcieCapPtr;
+ UINT16 L1ssCapPtr;
+ UINT8 EndpointL1ssControl2;
+ UINT32 EndpointL1ssControl1;
+ UINT16 LtrCapPtr;
+ UINT32 EndpointLtrData;
+ UINT16 EndpointLctlData16;
+ UINT16 EndpointDctlData16;
+ UINT16 EndpointDctl2Data16;
+ UINT16 RootPortDctl2Data16;
+} SAVED_DEVICE_CONFIG_SPACE;
+
+//
+// This structure is used to record the result of PCIe storageremapping for each cycle router
+//
+typedef struct {
+ UINT8 RootPortNum; // Indicates the root port number with RST PCIe Storage Remapping remapping supported and PCIe storage device plugged on, numbering is 0-based
+ UINT8 DeviceInterface; // Indicates the interface of the PCIe storage device (AHCI or NVMe)
+ UINT32 EndPointUniqueMsixTableBar; // Records the PCIe storage device's MSI-X Table BAR if it supports unique MSI-X Table BAR
+ UINT32 EndPointUniqueMsixTableBarValue; // Records the PCIe storage device's MSI-X Table BAR value if it supports unique MSI-X Table BAR
+ UINT32 EndPointUniqueMsixPbaBar; // Records the PCIe storage device's MSI-X PBA BAR if it supports unique MSI-X PBA BAR
+ UINT32 EndPointUniqueMsixPbaBarValue; // Records the PCIe storage device's MSI-X PBA BAR value if it supports unique MSI-X PBA BAR
+} RST_CR_CONFIGURATION;
+
+//
+// Passes to DXE results of PCIe storage remapping
+//
+typedef struct {
+ //
+ // Stores configuration information about cycle router
+ //
+ RST_CR_CONFIGURATION RstCrConfiguration[PCH_MAX_RST_PCIE_STORAGE_CR];
+
+ //
+ // Saved fields from hidden device config space to be used later by RST driver
+ //
+ SAVED_DEVICE_CONFIG_SPACE SavedRemapedDeviceConfigSpace[PCH_MAX_RST_PCIE_STORAGE_CR];
+} PCH_RST_HOB;
+
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/IncludePrivate/Protocol/PchNvsArea.h b/Silicon/Intel/TigerlakeSiliconPkg/Pch/IncludePrivate/Protocol/PchNvsArea.h
new file mode 100644
index 0000000000..1c45d89225
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/IncludePrivate/Protocol/PchNvsArea.h
@@ -0,0 +1,30 @@
+/** @file
+ This file defines the PCH NVS Area Protocol.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _PCH_NVS_AREA_H_
+#define _PCH_NVS_AREA_H_
+
+//
+// PCH NVS Area definition
+//
+#include <Pch/IncludePrivate/PchNvsAreaDef.h>
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID gPchNvsAreaProtocolGuid;
+
+/**
+ This protocol is used to sync PCH information from POST to runtime ASL.
+ This protocol exposes the pointer of PCH NVS Area only. Please refer to
+ ASL definition for PCH NVS AREA.
+**/
+typedef struct {
+ PCH_NVS_AREA *Area;
+} PCH_NVS_AREA_PROTOCOL;
+
+#endif // _PCH_NVS_AREA_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/IncludePrivate/Protocol/PcieIoTrap.h b/Silicon/Intel/TigerlakeSiliconPkg/Pch/IncludePrivate/Protocol/PcieIoTrap.h
new file mode 100644
index 0000000000..ecea5db4fc
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/IncludePrivate/Protocol/PcieIoTrap.h
@@ -0,0 +1,35 @@
+/** @file
+ This file defines the PCH PCIE IoTrap Protocol.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PCH_PCIE_IOTRAP_H_
+#define _PCH_PCIE_IOTRAP_H_
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID gPchPcieIoTrapProtocolGuid;
+
+//
+// Forward reference for ANSI C compatibility
+//
+typedef struct _PCH_PCIE_IOTRAP_PROTOCOL PCH_PCIE_IOTRAP_PROTOCOL;
+
+///
+/// Pcie Trap valid types
+///
+typedef enum {
+ PchPciePmTrap,
+ PcieTrapTypeMaximum
+} PCH_PCIE_TRAP_TYPE;
+
+/**
+ This protocol is used to provide the IoTrap address to trigger PCH PCIE call back events
+**/
+struct _PCH_PCIE_IOTRAP_PROTOCOL {
+ UINT16 PcieTrapAddress;
+};
+
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/IncludePrivate/SiScheduleResetHob.h b/Silicon/Intel/TigerlakeSiliconPkg/Pch/IncludePrivate/SiScheduleResetHob.h
new file mode 100644
index 0000000000..0d9b167588
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/IncludePrivate/SiScheduleResetHob.h
@@ -0,0 +1,21 @@
+/** @file
+ This file contains definitions of Si Schedule Reset HOB.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _SI_SCHEDULE_RESET_HOB_H_
+#define _SI_SCHEDULE_RESET_HOB_H_
+
+/**
+ This structure is used to provide information about PCH Resets
+**/
+typedef struct {
+ EFI_RESET_TYPE ResetType;
+ PCH_RESET_DATA ResetData;
+} SI_SCHEDULE_RESET_HOB;
+
+extern EFI_GUID gSiScheduleResetHobGuid;
+
+#endif // _SI_SCHEDULE_RESET_HOB_H_
+
--
2.24.0.windows.2
^ permalink raw reply related [flat|nested] 42+ messages in thread
* [Patch V3 07/40] TigerlakeSiliconPkg/SystemAgent: Add include headers
2021-02-05 7:40 [Patch V3 01/40] TigerlakeSiliconPkg: Add package and Include/ConfigBlock headers Heng Luo
` (4 preceding siblings ...)
2021-02-05 7:40 ` [Patch V3 06/40] TigerlakeSiliconPkg/Pch: Add IncludePrivate headers Heng Luo
@ 2021-02-05 7:40 ` Heng Luo
2021-02-05 7:40 ` [Patch V3 08/40] TigerlakeSiliconPkg/SystemAgent: Add IncludePrivate headers Heng Luo
` (32 subsequent siblings)
38 siblings, 0 replies; 42+ messages in thread
From: Heng Luo @ 2021-02-05 7:40 UTC (permalink / raw)
To: devel; +Cc: Sai Chaganty, Nate DeSimone
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3171
Adds the following header files:
* SystemAgent/Include
Cc: Sai Chaganty <rangasai.v.chaganty@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Signed-off-by: Heng Luo <heng.luo@intel.com>
---
Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/Include/ConfigBlock/MemoryDxeConfig.h | 123 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/Include/ConfigBlock/PcieDxeConfig.h | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/Include/ConfigBlock/PramPreMemConfig.h | 34 ++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/Include/ConfigBlock/SaMiscPeiConfig.h | 24 ++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/Include/ConfigBlock/SaMiscPeiPreMemConfig.h | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/Include/Library/SaPlatformLib.h | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/Include/MemInfoHob.h | 245 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/Include/Protocol/SaPolicy.h | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
8 files changed, 753 insertions(+)
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/Include/ConfigBlock/MemoryDxeConfig.h b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/Include/ConfigBlock/MemoryDxeConfig.h
new file mode 100644
index 0000000000..451e295b49
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/Include/ConfigBlock/MemoryDxeConfig.h
@@ -0,0 +1,123 @@
+/** @file
+ Memory DXE Policy definitions
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _MEMORY_DXE_CONFIG_H_
+#define _MEMORY_DXE_CONFIG_H_
+
+#pragma pack(push, 1)
+
+#define MEMORY_DXE_CONFIG_REVISION 1
+
+typedef struct _MEMORY_DXE_CONFIG MEMORY_DXE_CONFIG;
+
+/**
+ Retrieves the OEM custom string for the SMBIOS Type 17 Table DeviceLocator field.
+ Implementation of this function is optional, if this function pointer is NULL then
+ the reference implementation of DeviceLocator will be used.
+
+ @param[in] This A pointer to this instance of MEMORY_DXE_CONFIG.
+ @param[in] Controller Desired Controller to get a DeviceLocator string for.
+ @param[in] Dimm Desired DIMM to get a DeviceLocator string for.
+ @param[in] MdSocket 0 = Memory Down, 1 = Socketed.
+
+ @retval The DeviceLocator string
+ @retval NULL If the return value is NULL, the default value will be used.
+**/
+typedef
+CHAR8*
+(EFIAPI *MEMORY_DXE_CONFIG_GET_DEVICE_LOCATOR_STRING)(
+ IN CONST MEMORY_DXE_CONFIG *This,
+ IN UINT8 Controller,
+ IN UINT8 Dimm,
+ IN UINT8 MdSocket
+ );
+
+/**
+ Retrieves the OEM custom string for the SMBIOS Type 17 Table BankLocator field.
+ Implementation of this function is optional, if this function pointer is NULL then
+ the reference implementation of DeviceLocator will be used.
+
+ @param[in] This A pointer to this instance of MEMORY_DXE_CONFIG.
+ @param[in] Controller Desired Controller to get a BankLocator string for.
+ @param[in] Dimm Desired DIMM to get a BankLocator string for.
+ @param[in] MdSocket 0 = Memory Down, 1 = Socketed.
+
+ @retval The BankLocator string
+ @retval NULL If the return value is NULL, the default value will be used.
+**/
+typedef
+CHAR8*
+(EFIAPI *MEMORY_DXE_CONFIG_GET_BANK_LOCATOR_STRING)(
+ IN CONST MEMORY_DXE_CONFIG *This,
+ IN UINT8 Controller,
+ IN UINT8 Dimm,
+ IN UINT8 MdSocket
+ );
+
+/**
+ The Memory Configuration includes DIMM SPD address Map and DIMM Slot Mechanical present bit map.
+ The data elements should be initialized by a Platform Module.\n
+ <b>Revision 1</b>:
+ - Initial version.
+**/
+struct _MEMORY_DXE_CONFIG {
+ CONFIG_BLOCK_HEADER Header; ///< Offset 0-27: Config Block Header
+/**
+ Offset 28:
+ Dimm SPD address
+ Only Server support 2 channels * 3 slots per channel = 6 sockets totally
+ The Desktop and mobile only support 2 channels * 2 slots per channel = 4 sockets totally
+ So there is mapping rule here for Desktop and mobile that there are no more 4 DIMMS totally in a system:
+ Channel A/ Slot 0 --> Dimm 0 --> SpdAddressTable[0]
+ Channel A/ Slot 1 --> Dimm 1 --> SpdAddressTable[1]
+ Channel B/ Slot 0 --> Dimm 2 --> SpdAddressTable[2]
+ Channel B/ Slot 1 --> Dimm 3 --> SpdAddressTable[3]
+ Refer to SmbiosMemory.c for use
+ If change the mapping rule, please update the Revision number.
+**/
+ UINT8 *SpdAddressTable;
+/**
+ Offset 36:
+ Channel A DIMM Slot Mechanical present bit map, bit 0 -> DIMM 0, bit 1 -> DIMM1, ...
+ if the bit is 1, the related DIMM slot is present.
+ E.g. if channel A has 2 DIMMs, ChannelASlotMap = 0x03;
+ E.g. if channel A has only 1 DIMMs, ChannelASlotMap = 0x01;
+ Refer to SmbiosMemory.c
+**/
+ UINT8 ChannelASlotMap;
+/**
+ Offset 37:
+ Channel B DIMM Slot Mechanical present bit map, bit 0 -> DIMM 0, bit 1 -> DIMM1, ...
+ if the bit is 1, the related DIMM slot is present.
+ E.g. if channel B has 2 DIMMs, ChannelBSlotMap = 0x03;
+ E.g. if channel B has only 1 DIMMs, ChannelBSlotMap = 0x01;
+ Refer to SmbiosMemory.c
+**/
+ UINT8 ChannelBSlotMap;
+/**
+ Offset 38:
+ MRC execution time measurement: <b>0=Disable</b>, 1=Enable
+**/
+ UINT8 MrcTimeMeasure;
+/**
+ Offset 39:
+ Fast boot: 0=Disable, <b>1=Enable</b>
+**/
+ UINT8 MrcFastBoot;
+/**
+ Offset 40:
+ Retrieves the OEM custom string for the SMBIOS Type 17 Table DeviceLocator field.
+**/
+ MEMORY_DXE_CONFIG_GET_DEVICE_LOCATOR_STRING GetDeviceLocatorString;
+/**
+ Offset 48:
+ Retrieves the OEM custom string for the SMBIOS Type 17 Table BankLocator field.
+**/
+ MEMORY_DXE_CONFIG_GET_BANK_LOCATOR_STRING GetBankLocatorString;
+};
+#pragma pack(pop)
+
+#endif // _MEMORY_DXE_CONFIG_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/Include/ConfigBlock/PcieDxeConfig.h b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/Include/ConfigBlock/PcieDxeConfig.h
new file mode 100644
index 0000000000..799121f1ab
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/Include/ConfigBlock/PcieDxeConfig.h
@@ -0,0 +1,114 @@
+/** @file
+ PCIE DXE policy definitions
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PCIE_DXE_CONFIG_H_
+#define _PCIE_DXE_CONFIG_H_
+
+#include "CpuPcieInfo.h"
+
+#pragma pack(push, 1)
+
+#define PCIE_DXE_CONFIG_REVISION 2
+
+typedef struct {
+ UINT16 VendorId; ///< Offset 0 PCI Config space offset 0
+ UINT16 DeviceId; ///< Offset 2 PCI Config space offset 2
+/**
+ Offset 4:
+ SnoopLatency bit definition
+ Note: All Reserved bits must be set to 0
+
+ BIT[15] - When set to 1b, indicates that the values in bits 9:0 are valid
+ When clear values in bits 9:0 will be ignored
+ BIT[14] - Should be set to 0b
+ BIT[13] - Reserved
+ BITS[12:10] - Value in bits 9:0 will be multiplied with the scale in these bits
+ 000b - 1 ns
+ 001b - 32 ns
+ 010b - 1024 ns
+ 011b - 32,768 ns
+ 100b - 1,048,576 ns
+ 101b - 33,554,432 ns
+ 110b - Reserved
+ 111b - Reserved
+ BITS[9:0] - Snoop Latency Value. The value in these bits will be multiplied with
+ the scale in bits 12:10
+**/
+ UINT16 SnoopLatency;
+/**
+ Offset 6:
+ NonSnoopLatency bit definition
+ Note: All Reserved bits must be set to 0
+
+ BIT[15] - When set to 1b, indicates that the values in bits 9:0 are valid
+ When clear values in bits 9:0 will be ignored
+ BIT[14] - Should be set to 0b
+ BIT[13] - Reserved
+ BITS[12:10] - Value in bits 9:0 will be multiplied with the scale in these bits
+ 000b - 1 ns
+ 001b - 32 ns
+ 010b - 1024 ns
+ 011b - 32,768 ns
+ 100b - 1,048,576 ns
+ 101b - 33,554,432 ns
+ 110b - Reserved
+ 111b - Reserved
+ BITS[9:0] - Non Snoop Latency Value. The value in these bits will be multiplied with
+ the scale in bits 12:10
+**/
+ UINT16 NonSnoopLatency;
+ UINT8 RevId; ///< Offset 8 PCI Config space offset 8; 0xFF means all steppings
+ UINT8 Rsvd0[3]; ///< Offset 9
+} PCIE_LTR_DEV_INFO;
+
+///
+/// PCIE Power Optimizer config
+///
+typedef struct {
+ UINT16 LtrMaxSnoopLatency; ///< Offset 0 LTR Maximum Snoop Latency: <b>0x0846=70us</b>
+ UINT16 LtrMaxNoSnoopLatency; ///< Offset 2 LTR Maximum Non-Snoop Latency: <b>0x0846=70us</b>
+ UINT8 ObffEnable; ///< Offset 4 LTR enable/disable: 0=Disable, <b>1=Enable</b>
+ UINT8 LtrEnable; ///< Offset 5 LTR enable/disable: 0=Disable, <b>1=Enable</b>
+ UINT8 Rsvd0[2]; ///< Offset 6 Reserved
+} CPU_PCIE_PWR_OPT;
+
+
+/**
+ The PCI Express Configuration info includes PCI Resources Range Base and Limits and the control
+ for PEG ASPM.
+ The data elements should be initialized by a Platform Module.\n
+ @note <b>Optional.</b> These policies will be ignored if there is no PEG port present on board.
+ <b>Revision 1</b>:
+ - Initial version.
+ <b>Revision 2</b>:
+ - Adding PEG RTD3 Support Setup Variable
+ <b>Revision 3</b>:
+ - Adding CPU PCIE RTD3 Support Setup Variable
+ - Deprecating PEG RTD3 Support Setup Variable
+ <b>Revision 4</b>:
+ - Deprecating CPU PCIE RTD3 Support Setup Variable
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Offset 0-27 Config Block Header
+/**
+ Offset 28: This field is used to describe the ASPM control for PEG Ports\n
+ 0=ASPM Disabled, 1=ASPM L0s Enabled, 2=ASPM L1 Enabled, 3=ASPM L0sL1 Enabled, <b>4=ASPM AUTO</b>
+**/
+ UINT8 PegAspm[SA_PEG_MAX_FUN];
+/**
+ Offset 32: PCIe Hot Plug Enable/Disable. It has 2 policies.
+ - <b>Disabled (0x0)</b> : No hotplug.
+ - Enabled (0x1) : Bios assist hotplug.
+**/
+ UINT8 PegRootPortHPE[SA_PEG_MAX_FUN];
+ CPU_PCIE_PWR_OPT PegPwrOpt[SA_PEG_MAX_FUN]; ///< Offset 36: This field is used to describe the PCIe LTR/OBFF relevant settings
+ UINT32 PegRtd3; /// Deprecated Policy
+ UINT8 CpuPcieRtd3; ///< Enable/Disable RTD3 Support for CPU PCIE. 0=Disable and 1=Enable (default) // Deprecated Policy
+ UINT8 Rsvd3[3];
+} PCIE_DXE_CONFIG;
+#pragma pack(pop)
+
+#endif // _PCIE_DXE_CONFIG_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/Include/ConfigBlock/PramPreMemConfig.h b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/Include/ConfigBlock/PramPreMemConfig.h
new file mode 100644
index 0000000000..8947e80b22
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/Include/ConfigBlock/PramPreMemConfig.h
@@ -0,0 +1,34 @@
+/** @file
+ Policy definition for Persisted Ram (Pram) Config Block
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PRAM_PREMEM_CONFIG__H_
+#define _PRAM_PREMEM_CONFIG__H_
+#pragma pack(push, 1)
+
+#define PRAM_PREMEM_CONFIG_REVISION 1
+
+/**
+ Defines Pram configuration parameters.\n
+ <b>Revision 1</b>:
+ - Initial version.
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Offset 0-27 Config Block Header
+ /**
+ Offset 28:
+ Size of Pram
+ If disabled, or if PcdSaOcEnable is disabled, all other policies in this config block are ignored.
+ <b>0=Disable</b>,
+ 1=4MB,
+ 2=16MB,
+ 3=64MB
+ **/
+ UINT8 Pram;
+ UINT8 Rsvd[3]; ///< Offset 29 Reserved for DWORD alignment
+} PRAM_PREMEM_CONFIG;
+#pragma pack(pop)
+
+#endif // _PRAM_CONFIG_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/Include/ConfigBlock/SaMiscPeiConfig.h b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/Include/ConfigBlock/SaMiscPeiConfig.h
new file mode 100644
index 0000000000..203d894df9
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/Include/ConfigBlock/SaMiscPeiConfig.h
@@ -0,0 +1,24 @@
+/** @file
+ Policy details for miscellaneous configuration in System Agent
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _SA_MISC_PEI_CONFIG_H_
+#define _SA_MISC_PEI_CONFIG_H_
+
+#pragma pack(push, 1)
+
+#define SA_MISC_PEI_CONFIG_REVISION 1
+
+/**
+ This configuration block is to configure SA Miscellaneous variables during PEI Post-Mem.\n
+ <b>Revision 1</b>:
+ - Initial version.
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Offset 0-27 Config Block Header
+} SA_MISC_PEI_CONFIG;
+#pragma pack(pop)
+
+#endif // _SA_MISC_PEI_CONFIG_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/Include/ConfigBlock/SaMiscPeiPreMemConfig.h b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/Include/ConfigBlock/SaMiscPeiPreMemConfig.h
new file mode 100644
index 0000000000..8c660b31a9
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/Include/ConfigBlock/SaMiscPeiPreMemConfig.h
@@ -0,0 +1,104 @@
+/** @file
+ Policy details for miscellaneous configuration in System Agent
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _SA_MISC_PEI_PREMEM_CONFIG_H_
+#define _SA_MISC_PEI_PREMEM_CONFIG_H_
+
+#pragma pack(push, 1)
+
+#ifndef MEM_CFG_MAX_SOCKETS
+#define MEM_CFG_MAX_SOCKETS 16
+#endif
+
+#define SA_MISC_PEI_PREMEM_CONFIG_REVISION 2
+
+/**
+ This configuration block is to configure SA Miscellaneous variables during PEI Pre-Mem phase like programming
+ different System Agent BARs, TsegSize, MmioSize required etc.
+ <b>Revision 1</b>:
+ - Initial version.
+ <b>Revision 2</b>:
+ - Deprecate IedSize.
+**/
+typedef struct {
+ CONFIG_BLOCK_HEADER Header; ///< Offset 0-27 Config Block Header
+ /**
+ Offset 28 Memory DIMMs' SPD address for reading SPD data.
+ TGL Mapping
+ 0 - Controller 0 Channel 0 Dimm 0 - DDR4 - DDR5 - LPDDR4 - LPDDR5
+ 1 - Controller 0 Channel 0 Dimm 1 - DDR4
+ 2 - Controller 0 Channel 1 Dimm 0 -------- DDR5 - LPDDR4 - LPDDR5
+ 3 - Controller 0 Channel 1 Dimm 1 -------- DDR5 2DPC
+ 4 - Controller 0 Channel 2 Dimm 0 --------------- LPDDR4 - LPDDR5
+ 6 - Controller 0 Channel 3 Dimm 0 --------------- LPDDR4 - LPDDR5
+ 8 - Controller 1 Channel 0 Dimm 0 - DDR4 - DDR5 - LPDDR4 - LPDDR5
+ 9 - Controller 1 Channel 0 Dimm 1 - DDR4
+ 10 - Controller 1 Channel 1 Dimm 0 -------- DDR5 - LPDDR4 - LPDDR5
+ 11 - Controller 1 Channel 1 Dimm 1 -------- DDR5 2DPC
+ 12 - Controller 1 Channel 2 Dimm 0 --------------- LPDDR4 - LPDDR5
+ 14 - Controller 1 Channel 3 Dimm 0 --------------- LPDDR4 - LPDDR5
+ **/
+ UINT8 SpdAddressTable[MEM_CFG_MAX_SOCKETS];
+ VOID *S3DataPtr; ///< Offset 44 Memory data save pointer for S3 resume. The memory space should be allocated and filled with proper S3 resume data on a resume path
+ UINT32 SmbusBar; ///< Offset 48 Address of System Agent SMBUS BAR: <b>0xEFA0</b>
+ /**
+ Offset 52 Size of TSEG in bytes. (Must be power of 2)
+ <b>0x400000</b>: 4MB for Release build (When IED enabled, it will be 8MB)
+ 0x1000000 : 16MB for Debug build (Regardless IED enabled or disabled)
+ **/
+ UINT32 TsegSize;
+ /**
+ Offset 56
+ <b>(Test)</b> Size of IED region in bytes.
+ <b>0</b> : IED Disabled (no memory occupied)
+ 0x400000 : 4MB SMM memory occupied by IED (Part of TSEG)
+ <b>Note: Enabling IED may also enlarge TsegSize together.</b>
+ @deprecated
+ **/
+ UINT32 IedSize;
+ UINT32 SkipExtGfxScan:1; ///< <b>(Test)</b> OFfset 60:0 :1=Skip External Gfx Device Scan; <b>0=Scan for external graphics devices</b>. Set this policy to skip External Graphics card scanning if the platform uses Internal Graphics only.
+ UINT32 BdatEnable:1; ///< Offset 60:1 :This field enables the generation of the BIOS DATA ACPI Tables: <b>0=FALSE</b>, 1=TRUE.
+ UINT32 TxtImplemented:1; ///< OFfset 60:2 :This field currently is used to tell MRC if it should run after TXT initializatoin completed: <b>0=Run without waiting for TXT</b>, 1=Run after TXT initialization by callback
+ /**
+ Offset 60:3 :
+ <b>(Test)</b> Scan External Discrete Graphics Devices for Legacy Only VGA OpROMs
+
+ When enabled, if the primary graphics device is an external discrete graphics device, Si will scan the
+ graphics device for legacy only VGA OpROMs.
+
+ This is intended to ease the implementation of a BIOS feature to automatically enable CSM if the Primary Gfx device
+ only supports Legacy VBIOS (No UEFI GOP Present). Otherwise disabling CSM won't result in no video being displayed.
+ This is useful for platforms that implement PCIe slots that allow the end user to install an arbitrary Gfx device.
+
+ This setting will only take effect if SkipExtGfxScan == 0. It is ignored otherwise.
+
+ - Disabled (0x0) : Don't Scan for Legacy Only VGA OpROMs (Default)
+ - <b>Enabled</b> (0x1) : Scan External Gfx for Legacy Only VGA OpROM
+ **/
+ UINT32 ScanExtGfxForLegacyOpRom:1;
+ UINT32 RsvdBits0 :28; ///< Offset 60:4 :Reserved for future use
+ UINT8 UserBd; ///< Offset 64 <b>0=Mobile/Mobile Halo</b>, 1=Desktop/DT Halo, 5=ULT/ULX/Mobile Halo, 7=UP Server
+ UINT8 LockPTMregs; ///< <b>(Test)</b> Offset 65 Lock PCU Thermal Management registers: 0=FALSE, <b>1=TRUE</b>
+ UINT8 BdatTestType; ///< Offset 66 When BdatEnable is set to TRUE, this option selects the type of data which will be populated in the BIOS Data ACPI Tables: <b>0=RMT</b>, 1=RMT Per Bit, 2=Margin 2D.
+ UINT8 CridEnable; ///< Offset 67 For Platforms supporting Intel(R) SIPP, this policy is use control enable/disable Compatibility Revision ID (CRID) feature: <b>0=FALSE</b>, 1=TRUE
+ UINT32 AcpiReservedMemorySize; ///< Offset 68 The Size of a Reserved memory buffer allocated in previous boot for S3 resume used. Originally it is retrieved from AcpiVariableCompatibility variable.
+ UINT32 OpRomScanTempMmioBar; ///< <b>(Test)</b> Offset 72 Temporary address to MMIO map OpROMs during VGA scanning. Used for ScanExtGfxForLegacyOpRom feature. MUST BE 16MB ALIGNED!
+ UINT32 OpRomScanTempMmioLimit; ///< <b>(Test)</b> Offset 76 Limit address for OpROM MMIO range. Used for ScanExtGfxForLegacyOpRom feature. (OpROMScanTempMmioLimit - OpRomScanTempMmioBar) MUST BE >= 16MB!
+ UINT64 AcpiReservedMemoryBase; ///< Offset 80 The Base address of a Reserved memory buffer allocated in previous boot for S3 resume used. Originally it is retrieved from AcpiVariableCompatibility variable.
+ UINT64 SystemMemoryLength; ///< Offset 88 Total system memory length from previous boot, this is required for S3 resume. Originally it is retrieved from AcpiVariableCompatibility variable.
+
+ UINT8 WrcFeatureEnable; ///< Offset 96: Enable/Disable WRC (Write Cache) feature of IOP. When enabled, supports IO devices allocating onto the ring and into LLC.
+ UINT8 Reserved1[3]; ///< Reserved for config block alignment.
+
+
+ // Since the biggest element is UINT64, this structure should be aligned with 64 bits.
+ UINT8 Rsvd[4]; ///< Reserved for config block alignment.
+
+
+} SA_MISC_PEI_PREMEM_CONFIG;
+#pragma pack(pop)
+
+#endif // _SA_MISC_PEI_PREMEM_CONFIG_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/Include/Library/SaPlatformLib.h b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/Include/Library/SaPlatformLib.h
new file mode 100644
index 0000000000..daf3746605
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/Include/Library/SaPlatformLib.h
@@ -0,0 +1,48 @@
+/** @file
+ Header file for SaPlatformLib.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _SA_PLATFORM_LIB_H_
+#define _SA_PLATFORM_LIB_H_
+
+
+/**
+ Checks if SKU is Mobile
+
+ @retval FALSE SKU is not Mobile
+ @retval TRUE SKU is Mobile
+**/
+BOOLEAN
+EFIAPI
+IsMobileSku (
+ VOID
+ );
+
+/**
+ Checks if SKU is Desktop
+
+ @retval FALSE SKU is not Desktop
+ @retval TRUE SKU is Desktop
+**/
+BOOLEAN
+EFIAPI
+IsDesktopSku (
+ VOID
+ );
+
+/**
+ Checks if SKU is Server
+
+ @retval FALSE SKU is not Server
+ @retval TRUE SKU is Server
+**/
+BOOLEAN
+EFIAPI
+IsServerSku (
+ VOID
+ );
+
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/Include/MemInfoHob.h b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/Include/MemInfoHob.h
new file mode 100644
index 0000000000..f280a3d379
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/Include/MemInfoHob.h
@@ -0,0 +1,245 @@
+/** @file
+ This file contains definitions required for creation of
+ Memory S3 Save data, Memory Info data and Memory Platform
+ data hobs.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _MEM_INFO_HOB_H_
+#define _MEM_INFO_HOB_H_
+
+#pragma pack (push, 1)
+
+extern EFI_GUID gSiMemoryS3DataGuid;
+extern EFI_GUID gSiMemoryInfoDataGuid;
+extern EFI_GUID gSiMemoryPlatformDataGuid;
+
+#define MAX_TRACE_CACHE_TYPE 3
+
+#define MAX_NODE 2
+#define MAX_CH 4
+#define MAX_DIMM 2
+
+///
+/// Host reset states from MRC.
+///
+#define WARM_BOOT 2
+
+#define R_MC_CHNL_RANK_PRESENT 0x7C
+#define B_RANK0_PRS BIT0
+#define B_RANK1_PRS BIT1
+#define B_RANK2_PRS BIT4
+#define B_RANK3_PRS BIT5
+
+///
+/// Defines taken from MRC so avoid having to include MrcInterface.h
+///
+
+//
+// Matches MAX_SPD_SAVE define in MRC
+//
+#ifndef MAX_SPD_SAVE
+#define MAX_SPD_SAVE 29
+#endif
+
+//
+// MRC version description.
+//
+typedef struct {
+ UINT8 Major; ///< Major version number
+ UINT8 Minor; ///< Minor version number
+ UINT8 Rev; ///< Revision number
+ UINT8 Build; ///< Build number
+} SiMrcVersion;
+
+//
+// Matches MrcDimmSts enum in MRC
+//
+#ifndef DIMM_ENABLED
+#define DIMM_ENABLED 0 // DIMM/rank Pair is enabled, presence will be detected.
+#endif
+#ifndef DIMM_DISABLED
+#define DIMM_DISABLED 1 // DIMM/rank Pair is disabled, regardless of presence.
+#endif
+#ifndef DIMM_PRESENT
+#define DIMM_PRESENT 2 // There is a DIMM present in the slot/rank pair and it will be used.
+#endif
+#ifndef DIMM_NOT_PRESENT
+#define DIMM_NOT_PRESENT 3 // There is no DIMM present in the slot/rank pair.
+#endif
+
+//
+// Matches MrcBootMode enum in MRC
+//
+#ifndef __MRC_BOOT_MODE__
+#define __MRC_BOOT_MODE__ //The below values are originated from MrcCommonTypes.h
+ #ifndef INT32_MAX
+ #define INT32_MAX (0x7FFFFFFF)
+ #endif //INT32_MAX
+typedef enum {
+ bmCold, ///< Cold boot
+ bmWarm, ///< Warm boot
+ bmS3, ///< S3 resume
+ bmFast, ///< Fast boot
+ MrcBootModeMax, ///< MRC_BOOT_MODE enumeration maximum value.
+ MrcBootModeDelim = INT32_MAX ///< This value ensures the enum size is consistent on both sides of the PPI.
+} MRC_BOOT_MODE;
+#endif //__MRC_BOOT_MODE__
+
+//
+// Matches MrcDdrType enum in MRC
+//
+#ifndef MRC_DDR_TYPE_DDR4
+#define MRC_DDR_TYPE_DDR4 0
+#endif
+#ifndef MRC_DDR_TYPE_DDR3
+#define MRC_DDR_TYPE_DDR3 1
+#endif
+#ifndef MRC_DDR_TYPE_LPDDR3
+#define MRC_DDR_TYPE_LPDDR3 2
+#endif
+#ifndef MRC_DDR_TYPE_LPDDR4
+#define MRC_DDR_TYPE_LPDDR4 3
+#endif
+#ifndef MRC_DDR_TYPE_WIO2
+#define MRC_DDR_TYPE_WIO2 4
+#endif
+#ifndef MRC_DDR_TYPE_UNKNOWN
+#define MRC_DDR_TYPE_UNKNOWN 5
+#endif
+
+#define MAX_PROFILE_NUM 4 // number of memory profiles supported
+#define MAX_XMP_PROFILE_NUM 2 // number of XMP profiles supported
+
+//
+// DIMM timings
+//
+typedef struct {
+ UINT32 tCK; ///< Memory cycle time, in femtoseconds.
+ UINT16 NMode; ///< Number of tCK cycles for the channel DIMM's command rate mode.
+ UINT16 tCL; ///< Number of tCK cycles for the channel DIMM's CAS latency.
+ UINT16 tCWL; ///< Number of tCK cycles for the channel DIMM's minimum CAS write latency time.
+ UINT16 tFAW; ///< Number of tCK cycles for the channel DIMM's minimum four activate window delay time.
+ UINT16 tRAS; ///< Number of tCK cycles for the channel DIMM's minimum active to precharge delay time.
+ UINT16 tRCDtRP; ///< Number of tCK cycles for the channel DIMM's minimum RAS# to CAS# delay time and Row Precharge delay time.
+ UINT16 tREFI; ///< Number of tCK cycles for the channel DIMM's minimum Average Periodic Refresh Interval.
+ UINT16 tRFC; ///< Number of tCK cycles for the channel DIMM's minimum refresh recovery delay time.
+ UINT16 tRFCpb; ///< Number of tCK cycles for the channel DIMM's minimum per bank refresh recovery delay time.
+ UINT16 tRFC2; ///< Number of tCK cycles for the channel DIMM's minimum refresh recovery delay time.
+ UINT16 tRFC4; ///< Number of tCK cycles for the channel DIMM's minimum refresh recovery delay time.
+ UINT16 tRPab; ///< Number of tCK cycles for the channel DIMM's minimum row precharge delay time for all banks.
+ UINT16 tRRD; ///< Number of tCK cycles for the channel DIMM's minimum row active to row active delay time.
+ UINT16 tRRD_L; ///< Number of tCK cycles for the channel DIMM's minimum row active to row active delay time for same bank groups.
+ UINT16 tRRD_S; ///< Number of tCK cycles for the channel DIMM's minimum row active to row active delay time for different bank groups.
+ UINT16 tRTP; ///< Number of tCK cycles for the channel DIMM's minimum internal read to precharge command delay time.
+ UINT16 tWR; ///< Number of tCK cycles for the channel DIMM's minimum write recovery time.
+ UINT16 tWTR; ///< Number of tCK cycles for the channel DIMM's minimum internal write to read command delay time.
+ UINT16 tWTR_L; ///< Number of tCK cycles for the channel DIMM's minimum internal write to read command delay time for same bank groups.
+ UINT16 tWTR_S; ///< Number of tCK cycles for the channel DIMM's minimum internal write to read command delay time for different bank groups.
+ UINT16 tCCD_L; ///< Number of tCK cycles for the channel DIMM's minimum CAS-to-CAS delay for same bank group.
+} MRC_CH_TIMING;
+
+///
+/// Memory SMBIOS & OC Memory Data Hob
+///
+typedef struct {
+ UINT8 Status; ///< See MrcDimmStatus for the definition of this field.
+ UINT8 DimmId;
+ UINT32 DimmCapacity; ///< DIMM size in MBytes.
+ UINT16 MfgId;
+ UINT8 ModulePartNum[20]; ///< Module part number for DDR3 is 18 bytes however for DRR4 20 bytes as per JEDEC Spec, so reserving 20 bytes
+ UINT8 RankInDimm; ///< The number of ranks in this DIMM.
+ UINT8 SpdDramDeviceType; ///< Save SPD DramDeviceType information needed for SMBIOS structure creation.
+ UINT8 SpdModuleType; ///< Save SPD ModuleType information needed for SMBIOS structure creation.
+ UINT8 SpdModuleMemoryBusWidth; ///< Save SPD ModuleMemoryBusWidth information needed for SMBIOS structure creation.
+ UINT8 SpdSave[MAX_SPD_SAVE]; ///< Save SPD Manufacturing information needed for SMBIOS structure creation.
+ UINT16 Speed; ///< The maximum capable speed of the device, in MHz
+ UINT8 MdSocket; ///< MdSocket: 0 = Memory Down, 1 = Socketed. Needed for SMBIOS structure creation.
+} DIMM_INFO;
+
+typedef struct {
+ UINT8 Status; ///< Indicates whether this channel should be used.
+ UINT8 ChannelId;
+ UINT8 DimmCount; ///< Number of valid DIMMs that exist in the channel.
+ MRC_CH_TIMING Timing[MAX_PROFILE_NUM]; ///< The channel timing values.
+ DIMM_INFO DimmInfo[MAX_DIMM]; ///< Save the DIMM output characteristics.
+} CHANNEL_INFO;
+
+typedef struct {
+ UINT8 Status; ///< Indicates whether this controller should be used.
+ UINT16 DeviceId; ///< The PCI device id of this memory controller.
+ UINT8 RevisionId; ///< The PCI revision id of this memory controller.
+ UINT8 ChannelCount; ///< Number of valid channels that exist on the controller.
+ CHANNEL_INFO ChannelInfo[MAX_CH]; ///< The following are channel level definitions.
+} CONTROLLER_INFO;
+
+typedef struct {
+ UINT64 BaseAddress; ///< Trace Base Address
+ UINT64 TotalSize; ///< Total Trace Region of Same Cache type
+ UINT8 CacheType; ///< Trace Cache Type
+ UINT8 ErrorCode; ///< Trace Region Allocation Fail Error code
+ UINT8 Rsvd[2];
+} PSMI_MEM_INFO;
+
+typedef struct {
+ UINT8 Revision;
+ UINT16 DataWidth; ///< Data width, in bits, of this memory device
+ /** As defined in SMBIOS 3.0 spec
+ Section 7.18.2 and Table 75
+ **/
+ UINT8 MemoryType; ///< DDR type: DDR3, DDR4, or LPDDR3
+ UINT16 MaximumMemoryClockSpeed;///< The maximum capable speed of the device, in megahertz (MHz)
+ UINT16 ConfiguredMemoryClockSpeed; ///< The configured clock speed to the memory device, in megahertz (MHz)
+ /** As defined in SMBIOS 3.0 spec
+ Section 7.17.3 and Table 72
+ **/
+ UINT8 ErrorCorrectionType;
+
+ SiMrcVersion Version;
+ BOOLEAN EccSupport;
+ UINT8 MemoryProfile;
+ UINT32 TotalPhysicalMemorySize;
+ UINT32 DefaultXmptCK[MAX_XMP_PROFILE_NUM];///< Stores the tCK value read from SPD XMP profiles if they exist.
+ UINT8 XmpProfileEnable; ///< If XMP capable DIMMs are detected, this will indicate which XMP Profiles are common among all DIMMs.
+ UINT8 Ratio;
+ UINT8 RefClk;
+ UINT32 VddVoltage[MAX_PROFILE_NUM];
+ CONTROLLER_INFO Controller[MAX_NODE];
+} MEMORY_INFO_DATA_HOB;
+
+/**
+ Memory Platform Data Hob
+
+ <b>Revision 1:</b>
+ - Initial version.
+ <b>Revision 2:</b>
+ - Added TsegBase, PrmrrSize, PrmrrBase, Gttbase, MmioSize, PciEBaseAddress fields
+**/
+typedef struct {
+ UINT8 Revision;
+ UINT8 Reserved[3];
+ UINT32 BootMode;
+ UINT32 TsegSize;
+ UINT32 TsegBase;
+ UINT32 PrmrrSize;
+ UINT64 PrmrrBase;
+ UINT32 PramSize;
+ UINT64 PramBase;
+ UINT64 DismLimit;
+ UINT64 DismBase;
+ UINT32 GttBase;
+ UINT32 MmioSize;
+ UINT32 PciEBaseAddress;
+ PSMI_MEM_INFO PsmiInfo[MAX_TRACE_CACHE_TYPE];
+} MEMORY_PLATFORM_DATA;
+
+typedef struct {
+ EFI_HOB_GUID_TYPE EfiHobGuidType;
+ MEMORY_PLATFORM_DATA Data;
+ UINT8 *Buffer;
+} MEMORY_PLATFORM_DATA_HOB;
+
+#pragma pack (pop)
+
+#endif // _MEM_INFO_HOB_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/Include/Protocol/SaPolicy.h b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/Include/Protocol/SaPolicy.h
new file mode 100644
index 0000000000..4ff2578038
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/Include/Protocol/SaPolicy.h
@@ -0,0 +1,61 @@
+/** @file
+ Interface definition details between System Agent and platform drivers during DXE phase.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _SA_POLICY_H_
+#define _SA_POLICY_H_
+
+#include <ConfigBlock.h>
+#include <Library/ConfigBlockLib.h>
+#include <GraphicsConfig.h>
+#include <ConfigBlock/MemoryDxeConfig.h>
+#include <ConfigBlock/PcieDxeConfig.h>
+#include <VtdConfig.h>
+
+///
+/// Extern the GUID for protocol users.
+///
+extern EFI_GUID gSaPolicyProtocolGuid;
+extern EFI_GUID gGraphicsDxeConfigGuid;
+extern EFI_GUID gPcieDxeConfigGuid;
+extern EFI_GUID gMemoryDxeConfigGuid;
+extern EFI_GUID gVtdDxeConfigGuid;
+
+/**
+ Don't change the original SA_POLICY_PROTOCOL_REVISION macro, external
+ modules maybe have consumed this macro in their source code. Directly
+ update the SA_POLICY_PROTOCOL_REVISION version number may cause those
+ external modules to auto mark themselves wrong version info.
+ Always create new version macro for new Policy protocol interface.
+**/
+#define SA_POLICY_PROTOCOL_REVISION 1
+
+#define CPU_PCIE_DEV_END_OF_TABLE 0xFFFF
+
+#define LTR_MAX_SNOOP_LATENCY_VALUE 0x0846 ///< Intel recommended maximum value for Snoop Latency
+#define LTR_MAX_NON_SNOOP_LATENCY_VALUE 0x0846 ///< Intel recommended maximum value for Non-Snoop Latency
+
+
+/**
+ SA DXE Policy
+
+ The SA_POLICY_PROTOCOL producer drvier is recommended to
+ set all the SA_POLICY_PROTOCOL size buffer zero before init any member parameter,
+ this clear step can make sure no random value for those unknow new version parameters.
+
+ Make sure to update the Revision if any change to the protocol, including the existing
+ internal structure definations.\n
+ Note: Here revision will be bumped up when adding/removing any config block under this structure.\n
+ <b>Revision 1</b>:
+ - Initial version.
+**/
+typedef struct {
+ CONFIG_BLOCK_TABLE_HEADER TableHeader; ///< Offset 0-31
+/*
+ Individual Config Block Structures are added here in memory as part of AddConfigBlock()
+*/
+} SA_POLICY_PROTOCOL;
+
+#endif
--
2.24.0.windows.2
^ permalink raw reply related [flat|nested] 42+ messages in thread
* [Patch V3 08/40] TigerlakeSiliconPkg/SystemAgent: Add IncludePrivate headers
2021-02-05 7:40 [Patch V3 01/40] TigerlakeSiliconPkg: Add package and Include/ConfigBlock headers Heng Luo
` (5 preceding siblings ...)
2021-02-05 7:40 ` [Patch V3 07/40] TigerlakeSiliconPkg/SystemAgent: Add include headers Heng Luo
@ 2021-02-05 7:40 ` Heng Luo
2021-02-05 7:40 ` [Patch V3 09/40] TigerlakeSiliconPkg/Fru: Add TglCpu/Include headers Heng Luo
` (31 subsequent siblings)
38 siblings, 0 replies; 42+ messages in thread
From: Heng Luo @ 2021-02-05 7:40 UTC (permalink / raw)
To: devel; +Cc: Sai Chaganty, Nate DeSimone
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3171
Adds the following header files:
* SystemAgent/IncludePrivate
Cc: Sai Chaganty <rangasai.v.chaganty@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Signed-off-by: Heng Luo <heng.luo@intel.com>
---
Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/IncludePrivate/Protocol/SaIotrapSmi.h | 42 ++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/IncludePrivate/Protocol/SaNvsArea.h | 30 ++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/IncludePrivate/SaConfigHob.h | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/IncludePrivate/SaNvsAreaDef.h | 222 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 344 insertions(+)
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/IncludePrivate/Protocol/SaIotrapSmi.h b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/IncludePrivate/Protocol/SaIotrapSmi.h
new file mode 100644
index 0000000000..2e86d497f9
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/IncludePrivate/Protocol/SaIotrapSmi.h
@@ -0,0 +1,42 @@
+/** @file
+ This file defines the SA Iotrap SMI Protocol to provide the
+ I/O address for registered Iotrap SMI.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _SA_IOTRAP_SMI_PROTOCOL_H_
+#define _SA_IOTRAP_SMI_PROTOCOL_H_
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID gSaIotrapSmiProtocolGuid;
+
+#define SA_IOTRAP_SMI_PROTOCOL_REVISION_1 1
+
+//
+// SA IO Trap SMI Protocol definition (Private protocol for RC internal use only)
+//
+typedef struct {
+/*
+ Protocol revision number
+ Any backwards compatible changes to this protocol will result in an update in the revision number
+ Major changes will require publication of a new protocol
+
+ <b>Revision 1</b>:
+ - First version
+*/
+ UINT8 Revision;
+ UINT16 SaIotrapSmiAddress;
+} SA_IOTRAP_SMI_PROTOCOL;
+
+///
+/// Pcie Trap valid types
+///
+typedef enum {
+ CpuPciePmTrap,
+ CpuPcieTrapTypeMaximum
+} CPU_PCIE_TRAP_TYPE;
+
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/IncludePrivate/Protocol/SaNvsArea.h b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/IncludePrivate/Protocol/SaNvsArea.h
new file mode 100644
index 0000000000..785a808cf4
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/IncludePrivate/Protocol/SaNvsArea.h
@@ -0,0 +1,30 @@
+/** @file
+ Definition of the System Agent global NVS area protocol.
+ This protocol publishes the address and format of a global ACPI NVS buffer
+ used as a communications buffer between SMM/DXE/PEI code and ASL code.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _SYSTEM_AGENT_NVS_AREA_H_
+#define _SYSTEM_AGENT_NVS_AREA_H_
+
+//
+// SA NVS Area definition
+//
+#include <SaNvsAreaDef.h>
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID gSaNvsAreaProtocolGuid;
+
+///
+/// System Agent Global NVS Area Protocol
+///
+typedef struct {
+ SYSTEM_AGENT_NVS_AREA *Area; ///< System Agent Global NVS Area Structure
+} SYSTEM_AGENT_NVS_AREA_PROTOCOL;
+
+#endif // _SYSTEM_AGENT_NVS_AREA_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/IncludePrivate/SaConfigHob.h b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/IncludePrivate/SaConfigHob.h
new file mode 100644
index 0000000000..65622069e6
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/IncludePrivate/SaConfigHob.h
@@ -0,0 +1,50 @@
+/** @file
+ The GUID definition for SaConfigHob
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _SA_CONFIG_HOB_H_
+#define _SA_CONFIG_HOB_H_
+
+#include <Register/SaRegsHostBridge.h>
+#include <Base.h>
+#include "CpuPcieInfo.h"
+#include <Library/PcdLib.h>
+
+extern EFI_GUID gSaConfigHobGuid;
+#define SA_VTD_ENGINE_NUMBER 3
+
+#pragma pack (push,1)
+///
+/// DPR Directory Types
+///
+typedef enum {
+ EnumDprDirectoryTxt = 0,
+} DPR_DIRECTORY_ELEMENT;
+
+#define DPR_DIRECTORY_TYPE_TXT 0x01 ///< DPR directory type - TXT
+#define DPR_DIRECTORY_TYPE_BIOSGUARD 0x02 ///< DPR directory type - BIOS Guard
+#define DPR_DIRECTORY_MAX 1 ///< DPR Maximum Size
+
+///
+/// DPR directory entry definition
+///
+typedef struct {
+ UINT8 Type; ///< DPR Directory Type
+ UINT8 Size; ///< DPR Size in MB
+ UINT32 PhysBase; ///< Must be 4K aligned (bits 11..0 must be clear)
+ UINT16 Reserved; ///< Must be 0
+} DPR_DIRECTORY_ENTRY;
+
+///
+/// System Agent Config Hob
+///
+typedef struct {
+ EFI_HOB_GUID_TYPE EfiHobGuidType; ///< GUID Hob type structure for gSaConfigHobGuid
+ DPR_DIRECTORY_ENTRY DprDirectory[DPR_DIRECTORY_MAX]; ///< DPR directory entry definition
+ UINT8 ApertureSize; ///< Aperture size value
+ BOOLEAN CridEnable; ///< This field inidicates if CRID is enabled or disabled (to support Intel(R) SIPP)
+} SA_CONFIG_HOB;
+#pragma pack (pop)
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/IncludePrivate/SaNvsAreaDef.h b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/IncludePrivate/SaNvsAreaDef.h
new file mode 100644
index 0000000000..6ee2343363
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/IncludePrivate/SaNvsAreaDef.h
@@ -0,0 +1,222 @@
+//
+// Automatically generated by GenNvs ver 2.4.6
+// Please DO NOT modify !!!
+//
+
+/** @file
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+ //
+ // Define SA NVS Area operation region.
+ //
+#ifndef _SA_NVS_AREA_DEF_H_
+#define _SA_NVS_AREA_DEF_H_
+
+#pragma pack (push,1)
+typedef struct {
+ UINT32 IgdOpRegionAddress; ///< Offset 0 IGD OpRegion base address
+ UINT8 GfxTurboIMON; ///< Offset 4 IMON Current Value
+ UINT8 IgdState; ///< Offset 5 IGD State (Primary Display = 1)
+ UINT8 IgdBootType; ///< Offset 6 IGD Boot Display Device
+ UINT8 IgdPanelType; ///< Offset 7 IGD Panel Type CMOS option
+ UINT8 IgdPanelScaling; ///< Offset 8 IGD Panel Scaling
+ UINT8 IgdBiaConfig; ///< Offset 9 IGD BIA Configuration
+ UINT8 IgdSscConfig; ///< Offset 10 IGD SSC Configuration
+ UINT8 IgdDvmtMemSize; ///< Offset 11 IGD DVMT Memory Size
+ UINT8 IgdFunc1Enable; ///< Offset 12 IGD Function 1 Enable
+ UINT8 IgdHpllVco; ///< Offset 13 HPLL VCO
+ UINT8 IgdSciSmiMode; ///< Offset 14 GMCH SMI/SCI mode (0=SCI)
+ UINT8 IgdPAVP; ///< Offset 15 IGD PAVP data
+ UINT8 CurrentDeviceList; ///< Offset 16 Current Attached Device List
+ UINT16 CurrentDisplayState; ///< Offset 17 Current Display State
+ UINT16 NextDisplayState; ///< Offset 19 Next Display State
+ UINT8 NumberOfValidDeviceId; ///< Offset 21 Number of Valid Device IDs
+ UINT32 DeviceId1; ///< Offset 22 Device ID 1
+ UINT32 DeviceId2; ///< Offset 26 Device ID 2
+ UINT32 DeviceId3; ///< Offset 30 Device ID 3
+ UINT32 DeviceId4; ///< Offset 34 Device ID 4
+ UINT32 DeviceId5; ///< Offset 38 Device ID 5
+ UINT32 DeviceId6; ///< Offset 42 Device ID 6
+ UINT32 DeviceId7; ///< Offset 46 Device ID 7
+ UINT32 DeviceId8; ///< Offset 50 Device ID 8
+ UINT32 DeviceId9; ///< Offset 54 Device ID 9
+ UINT32 DeviceId10; ///< Offset 58 Device ID 10
+ UINT32 DeviceId11; ///< Offset 62 Device ID 11
+ UINT32 DeviceId12; ///< Offset 66 Device ID 12
+ UINT32 DeviceId13; ///< Offset 70 Device ID 13
+ UINT32 DeviceId14; ///< Offset 74 Device ID 14
+ UINT32 DeviceId15; ///< Offset 78 Device ID 15
+ UINT32 DeviceIdX; ///< Offset 82 Device ID for eDP device
+ UINT32 NextStateDid1; ///< Offset 86 Next state DID1 for _DGS
+ UINT32 NextStateDid2; ///< Offset 90 Next state DID2 for _DGS
+ UINT32 NextStateDid3; ///< Offset 94 Next state DID3 for _DGS
+ UINT32 NextStateDid4; ///< Offset 98 Next state DID4 for _DGS
+ UINT32 NextStateDid5; ///< Offset 102 Next state DID5 for _DGS
+ UINT32 NextStateDid6; ///< Offset 106 Next state DID6 for _DGS
+ UINT32 NextStateDid7; ///< Offset 110 Next state DID7 for _DGS
+ UINT32 NextStateDid8; ///< Offset 114 Next state DID8 for _DGS
+ UINT32 NextStateDidEdp; ///< Offset 118 Next state DID for eDP
+ UINT8 LidState; ///< Offset 122 Lid State (Lid Open = 1)
+ UINT32 AKsv0; ///< Offset 123 First four bytes of AKSV (manufacturing mode)
+ UINT8 AKsv1; ///< Offset 127 Fifth byte of AKSV (manufacturing mode)
+ UINT8 BrightnessPercentage; ///< Offset 128 Brightness Level Percentage
+ UINT8 AlsEnable; ///< Offset 129 Ambient Light Sensor Enable
+ UINT8 AlsAdjustmentFactor; ///< Offset 130 Ambient Light Adjusment Factor
+ UINT8 LuxLowValue; ///< Offset 131 LUX Low Value
+ UINT8 LuxHighValue; ///< Offset 132 LUX High Value
+ UINT8 ActiveLFP; ///< Offset 133 Active LFP
+ UINT8 IpuAcpiMode; ///< Offset 134 IPU ACPI device type (0=Disabled, 1=AVStream virtual device as child of GFX)
+ UINT8 EdpValid; ///< Offset 135 Check for eDP display device
+ UINT8 HgMode; ///< Offset 136 SG Mode (0=Disabled, 1=HG Muxed, 2=HG Muxless, 3=DGPU Only)
+ UINT8 HgFeatureList; ///< Offset 137 HG Feature List
+ UINT8 Pcie0GpioSupport; ///< Offset 138 PCIe0 GPIO Support (0=Disabled, 1=PCH Based, 2=I2C Based)
+ UINT8 Pcie0HoldRstExpanderNo; ///< Offset 139 PCIe0 HLD RST IO Expander Number
+ UINT32 Pcie0HoldRstGpioNo; ///< Offset 140 PCIe0 HLD RST GPIO Number
+ UINT8 Pcie0HoldRstActiveInfo; ///< Offset 144 PCIe0 HLD RST GPIO Active Information
+ UINT8 Pcie0PwrEnExpanderNo; ///< Offset 145 PCIe0 PWR Enable IO Expander Number
+ UINT32 Pcie0PwrEnGpioNo; ///< Offset 146 PCIe0 PWR Enable GPIO Number
+ UINT8 Pcie0PwrEnActiveInfo; ///< Offset 150 PCIe0 PWR Enable GPIO Active Information
+ UINT8 Pcie1GpioSupport; ///< Offset 151 PCIe1 GPIO Support (0=Disabled, 1=PCH Based, 2=I2C Based)
+ UINT8 Pcie1HoldRstExpanderNo; ///< Offset 152 PCIe1 HLD RST IO Expander Number
+ UINT32 Pcie1HoldRstGpioNo; ///< Offset 153 PCIe1 HLD RST GPIO Number
+ UINT8 Pcie1HoldRstActiveInfo; ///< Offset 157 PCIe1 HLD RST GPIO Active Information
+ UINT8 Pcie1PwrEnExpanderNo; ///< Offset 158 PCIe1 PWR Enable IO Expander Number
+ UINT32 Pcie1PwrEnGpioNo; ///< Offset 159 PCIe1 PWR Enable GPIO Number
+ UINT8 Pcie1PwrEnActiveInfo; ///< Offset 163 PCIe1 PWR Enable GPIO Active Information
+ UINT8 Pcie2GpioSupport; ///< Offset 164 PCIe2 GPIO Support (0=Disabled, 1=PCH Based, 2=I2C Based)
+ UINT8 Pcie2HoldRstExpanderNo; ///< Offset 165 PCIe2 HLD RST IO Expander Number
+ UINT32 Pcie2HoldRstGpioNo; ///< Offset 166 PCIe2 HLD RST GPIO Number
+ UINT8 Pcie2HoldRstActiveInfo; ///< Offset 170 PCIe2 HLD RST GPIO Active Information
+ UINT8 Pcie2PwrEnExpanderNo; ///< Offset 171 PCIe2 PWR Enable IO Expander Number
+ UINT32 Pcie2PwrEnGpioNo; ///< Offset 172 PCIe2 PWR Enable GPIO Number
+ UINT8 Pcie2PwrEnActiveInfo; ///< Offset 176 PCIe2 PWR Enable GPIO Active Information
+ UINT8 Pcie3GpioSupport; ///< Offset 177 PCIe3 GPIO Support (0=Disabled, 1=PCH Based, 2=I2C Based)
+ UINT8 Pcie3HoldRstExpanderNo; ///< Offset 178 PCIe3 HLD RST IO Expander Number
+ UINT32 Pcie3HoldRstGpioNo; ///< Offset 179 PCIe3 HLD RST GPIO Number
+ UINT8 Pcie3HoldRstActiveInfo; ///< Offset 183 PCIe3 HLD RST GPIO Active Information
+ UINT8 Pcie3PwrEnExpanderNo; ///< Offset 184 PCIe3 PWR Enable IO Expander Number
+ UINT32 Pcie3PwrEnGpioNo; ///< Offset 185 PCIe3 PWR Enable GPIO Number
+ UINT8 Pcie3PwrEnActiveInfo; ///< Offset 189 PCIe3 PWR Enable GPIO Active Information
+ UINT32 Pcie3WakeGpioNo; ///< Offset 190 PCIe3 RTD3 Device Wake GPIO Number
+ UINT16 DelayAfterPwrEn; ///< Offset 194 Delay after power enable for PCIe
+ UINT16 DelayAfterHoldReset; ///< Offset 196 Delay after Hold Reset for PCIe
+ UINT8 Pcie0EpCapOffset; ///< Offset 198 PCIe0 Endpoint Capability Structure Offset
+ UINT32 XPcieCfgBaseAddress; ///< Offset 199 Any Device's PCIe Config Space Base Address
+ UINT16 GpioBaseAddress; ///< Offset 203 GPIO Base Address
+ UINT32 NvIgOpRegionAddress; ///< Offset 205 NVIG opregion address
+ UINT32 NvHmOpRegionAddress; ///< Offset 209 NVHM opregion address
+ UINT32 ApXmOpRegionAddress; ///< Offset 213 AMDA opregion address
+ UINT8 Peg0LtrEnable; ///< Offset 217 Latency Tolerance Reporting Enable
+ UINT8 Peg0ObffEnable; ///< Offset 218 Optimized Buffer Flush and Fill
+ UINT8 Peg1LtrEnable; ///< Offset 219 Latency Tolerance Reporting Enable
+ UINT8 Peg1ObffEnable; ///< Offset 220 Optimized Buffer Flush and Fill
+ UINT8 Peg2LtrEnable; ///< Offset 221 Latency Tolerance Reporting Enable
+ UINT8 Peg2ObffEnable; ///< Offset 222 Optimized Buffer Flush and Fill
+ UINT8 Peg3LtrEnable; ///< Offset 223 Latency Tolerance Reporting Enable
+ UINT8 Peg3ObffEnable; ///< Offset 224 Optimized Buffer Flush and Fill
+ UINT16 PegLtrMaxSnoopLatency; ///< Offset 225 SA Peg Latency Tolerance Reporting Max Snoop Latency
+ UINT16 PegLtrMaxNoSnoopLatency; ///< Offset 227 SA Peg Latency Tolerance Reporting Max No Snoop Latency
+ UINT64 Mmio64Base; ///< Offset 229 Base of above 4GB MMIO resource
+ UINT64 Mmio64Length; ///< Offset 237 Length of above 4GB MMIO resource
+ UINT32 CpuIdInfo; ///< Offset 245 CPU ID info to get Family Id or Stepping
+ UINT32 Mmio32Base; ///< Offset 249 Base of below 4GB MMIO resource
+ UINT32 Mmio32Length; ///< Offset 253 Length of below 4GB MMIO resource
+ UINT32 Pcie0WakeGpioNo; ///< Offset 257 PCIe0 RTD3 Device Wake GPIO Number
+ UINT32 Pcie1WakeGpioNo; ///< Offset 261 PCIe1 RTD3 Device Wake GPIO Number
+ UINT32 Pcie2WakeGpioNo; ///< Offset 265 PCIe2 RTD3 Device Wake GPIO Number
+ UINT8 VtdDisable; ///< Offset 269 VT-d Enable/Disable
+ UINT32 VtdBaseAddress[7]; ///< Offset 270 VT-d Base Address 1
+ ///< Offset 274 VT-d Base Address 2
+ ///< Offset 278 VT-d Base Address 3
+ ///< Offset 282 VT-d Base Address 4 (iTBT PCIE0)
+ ///< Offset 286 VT-d Base Address 5 (iTBT PCIE1)
+ ///< Offset 290 VT-d Base Address 6 (iTBT PCIE2)
+ ///< Offset 294 VT-d Base Address 7 (iTBT PCIE3)
+ UINT16 VtdEngine1Vid; ///< Offset 298 VT-d Engine#1 Vendor ID
+ UINT16 VtdEngine2Vid; ///< Offset 300 VT-d Engine#2 Vendor ID
+ UINT8 RootPortIndex; ///< Offset 302 RootPort Number
+ UINT32 RootPortAddress; ///< Offset 303 RootPortAddress
+ UINT8 CpuTraceHubMode; ///< Offset 307 CPU Trace Hub Mode
+ UINT8 SimicsEnvironment; ///< Offset 308 Simics Environment information
+ UINT8 ItbtXhciEn; ///< Offset 309 TCSS XHCI Device Enable
+ UINT8 ItbtXdciEn; ///< Offset 310 TCSS XDCI Device Enable
+ UINT8 ItbtDmaEn[2]; ///< Offset 311 TCSS DMA 0 Device Enable
+ ///< Offset 312 TCSS DMA 1 Device Enable
+ UINT8 ItbtPcieRpEn[4]; ///< Offset 313 TCSS ItbtPcieRp PCIE RP 0 Device Enable
+ ///< Offset 314 TCSS ItbtPcieRp PCIE RP 1 Device Enable
+ ///< Offset 315 TCSS ItbtPcieRp PCIE RP 2 Device Enable
+ ///< Offset 316 TCSS ItbtPcieRp PCIE RP 3 Device Enable
+ UINT32 ItbtPcieRpAddress[4]; ///< Offset 317 TCSS ItbtPcie Root Port address 0
+ ///< Offset 321 TCSS ItbtPcie Root Port address 1
+ ///< Offset 325 TCSS ItbtPcie Root Port address 2
+ ///< Offset 329 TCSS ItbtPcie Root Port address 3
+ UINT32 TcssxDCIPwrDnScale; ///< Offset 333 TCSS xDCI Power Down Scale Value, DWC_USB3_GCTL_INIT[31:19]
+ UINT8 TcssxDCIInt; ///< Offset 337 TCSS xDCI Int Pin
+ UINT8 TcssxDCIIrq; ///< Offset 338 TCSS xDCI Irq Number
+ UINT8 TcssRtd3; ///< Offset 339 TCSS RTD3
+ UINT32 TcssDma0RmrrAddr; ///< Offset 340 TCSS DMA0 RMRR address
+ UINT32 TcssDma1RmrrAddr; ///< Offset 344 TCSS DMA1 RMRR address
+ UINT8 LtrEnable[4]; ///< Offset 348 Latency Tolerance Reporting Mechanism. <b>0: Disable</b>; 1: Enable.
+ ///< Offset 349 Latency Tolerance Reporting Mechanism. <b>0: Disable</b>; 1: Enable.
+ ///< Offset 350 Latency Tolerance Reporting Mechanism. <b>0: Disable</b>; 1: Enable.
+ ///< Offset 351 Latency Tolerance Reporting Mechanism. <b>0: Disable</b>; 1: Enable.
+ UINT16 PcieLtrMaxSnoopLatency[4]; ///< Offset 352 PCIE LTR max snoop Latency 0
+ ///< Offset 354 PCIE LTR max snoop Latency 1
+ ///< Offset 356 PCIE LTR max snoop Latency 2
+ ///< Offset 358 PCIE LTR max snoop Latency 3
+ UINT16 PcieLtrMaxNoSnoopLatency[4]; ///< Offset 360 PCIE LTR max no snoop Latency 0
+ ///< Offset 362 PCIE LTR max no snoop Latency 1
+ ///< Offset 364 PCIE LTR max no snoop Latency 2
+ ///< Offset 366 PCIE LTR max no snoop Latency 3
+ UINT8 IomReady; ///< Offset 368 IOM Ready
+ UINT8 TcssIomVccSt; ///< Offset 369 TCSS IOM VccSt
+ UINT8 CpuPcieRp0Enable; ///< Offset 370 <0:Disabled, 1:Enabled>
+ UINT8 CpuPcieRp1Enable; ///< Offset 371 <0:Disabled, 1:Enabled>
+ UINT8 CpuPcieRp2Enable; ///< Offset 372 <0:Disabled, 1:Enabled>
+ UINT8 CpuPcieRp3Enable; ///< Offset 373 <0:Disabled, 1:Enabled>
+ UINT8 VmdEnable; ///< Offset 374 VMD Device Enable
+ UINT32 DeviceIdY; ///< Offset 375 Device ID for second LFP device
+ UINT32 NextStateDidEdp2; ///< Offset 379 Next state DID for Second Display
+ UINT8 SlotSelection; ///< Offset 383 PCIe slot selection
+ UINT8 VmdRp1to8; ///< Offset 384 VMD PCH RP 1 to 8 <0:Disabled, 1:Enabled>
+ UINT8 VmdRp9to16; ///< Offset 385 VMD PCH RP 9 to 16 <0:Disabled, 1:Enabled>
+ UINT8 VmdRp17to24; ///< Offset 386 VMD PCH RP 17 to 24 <0:Disabled, 1:Enabled>
+ UINT8 VmdSataPort[8]; ///< Offset 387 VMD SATA PORT 0 <0:Disabled, 1:Enabled>
+ ///< Offset 388 VMD SATA PORT 1 <0:Disabled, 1:Enabled>
+ ///< Offset 389 VMD SATA PORT 2 <0:Disabled, 1:Enabled>
+ ///< Offset 390 VMD SATA PORT 3 <0:Disabled, 1:Enabled>
+ ///< Offset 391 VMD SATA PORT 4 <0:Disabled, 1:Enabled>
+ ///< Offset 392 VMD SATA PORT 5 <0:Disabled, 1:Enabled>
+ ///< Offset 393 VMD SATA PORT 6 <0:Disabled, 1:Enabled>
+ ///< Offset 394 VMD SATA PORT 7 <0:Disabled, 1:Enabled>
+ UINT8 VmdCpuRp; ///< Offset 395 VMD CPU RP <0:Disabled, 1:Enabled>
+ UINT8 CpuPcieRtd3; ///< Offset 396 RTD3 Support for CPU PCIE.
+ UINT32 LaneUsed; ///< Offset 397 Lane Used of each CSI Port <0:Not Configured, 1:x1, 2:x2, 3:x3 4:x4>
+ UINT32 CsiSpeed; ///< Offset 401 Speed of each CSI Port <0:Not configured, 1:<416GMbps, 2:<1.5Gbps, 3:<2.0Gbps, 4:<2.5Gbps, 5:<4Gbps, 6:>4Gbps>
+ UINT8 MaxPegPortNumber; ///< Offset 405 Max PEG port number
+ UINT8 MemBootMode; ///< Offset 406 Current Memory Boot Mode <0: BOOT_MODE_1LM(Default), 1: BOOT_MODE_2LM, 2: BOOT_MODE_PROVISION>
+ UINT8 DpmemSupport; ///< Offset 407 Dynamic PMem Support <0: Disabled, 1:Enabled>
+ UINT64 PmemStartingAddress; ///< Offset 408 Private Pmem Starting address
+ UINT64 PmemRangeLength; ///< Offset 416 Private Pmem Range Length
+ UINT8 Pcie3EpCapOffset; ///< Offset 424 PCIe3 Endpoint Capability Structure Offset
+ UINT8 Pcie0SrcClkNo; ///< Offset 425 PCIe0 RTD3 Device Source Clock Number
+ UINT8 Pcie1SrcClkNo; ///< Offset 426 PCIe1 RTD3 Device Source Clock Number
+ UINT8 Pcie2SrcClkNo; ///< Offset 427 PCIe2 RTD3 Device Source Clock Number
+ UINT8 Pcie3SrcClkNo; ///< Offset 428 PCIe2 RTD3 Device Source Clock Number
+ UINT8 Pcie0SecBusNum; ///< Offset 429 PCIe0 Secondary Bus Number (PCIe0 Endpoint Bus Number)
+ UINT8 Pcie1SecBusNum; ///< Offset 430 PCIe1 Secondary Bus Number (PCIe0 Endpoint Bus Number)
+ UINT8 Pcie2SecBusNum; ///< Offset 431 PCIe2 Secondary Bus Number (PCIe0 Endpoint Bus Number)
+ UINT8 Pcie3SecBusNum; ///< Offset 432 PCIe2 Secondary Bus Number (PCIe0 Endpoint Bus Number)
+ UINT8 Pcie1EpCapOffset; ///< Offset 433 PCIe1 Endpoint Capability Structure Offset
+ UINT8 Pcie2EpCapOffset; ///< Offset 434 PCIe2 Endpoint Capability Structure Offset
+ UINT8 IsBridgeDeviceBehindPeg1; ///< Offset 435 Is bridge device behind PEG1
+ UINT8 IsBridgeDeviceBehindPeg2; ///< Offset 436 Is bridge device behind PEG2
+ UINT8 IsBridgeDeviceBehindPeg3; ///< Offset 437 Is bridge device behind PEG3
+ UINT8 HgSlot; ///< Offset 438 Slot selection between PCH/PEG
+} SYSTEM_AGENT_NVS_AREA;
+
+#pragma pack(pop)
+#endif
--
2.24.0.windows.2
^ permalink raw reply related [flat|nested] 42+ messages in thread
* [Patch V3 09/40] TigerlakeSiliconPkg/Fru: Add TglCpu/Include headers
2021-02-05 7:40 [Patch V3 01/40] TigerlakeSiliconPkg: Add package and Include/ConfigBlock headers Heng Luo
` (6 preceding siblings ...)
2021-02-05 7:40 ` [Patch V3 08/40] TigerlakeSiliconPkg/SystemAgent: Add IncludePrivate headers Heng Luo
@ 2021-02-05 7:40 ` Heng Luo
2021-02-05 7:40 ` [Patch V3 10/40] TigerlakeSiliconPkg/Fru: Add TglCpu/IncludePrivate headers Heng Luo
` (30 subsequent siblings)
38 siblings, 0 replies; 42+ messages in thread
From: Heng Luo @ 2021-02-05 7:40 UTC (permalink / raw)
To: devel; +Cc: Sai Chaganty, Nate DeSimone
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3171
Adds the following header files:
* Fru/TglCpu/Include
Cc: Sai Chaganty <rangasai.v.chaganty@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Signed-off-by: Heng Luo <heng.luo@intel.com>
---
Silicon/Intel/TigerlakeSiliconPkg/Fru/TglCpu/Include/Library/CpuPcieInfoFruLib.h | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Fru/TglCpu/Include/Register/SaRegsHostBridge.h | 145 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Fru/TglCpu/Include/TcssInfo.h | 12 ++++++++++++
3 files changed, 214 insertions(+)
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglCpu/Include/Library/CpuPcieInfoFruLib.h b/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglCpu/Include/Library/CpuPcieInfoFruLib.h
new file mode 100644
index 0000000000..89cf952717
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglCpu/Include/Library/CpuPcieInfoFruLib.h
@@ -0,0 +1,57 @@
+/** @file
+ Header file for CpuPcieInfoFruLib.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _CPU_PCIE_INFO_FRU_LIB_H_
+#define _CPU_PCIE_INFO_FRU_LIB_H_
+
+#include <CpuPcieInfo.h>
+
+#define CPU_PCIE_MAX_ROOT_PORTS 4
+
+#define CPU_PCIE_ULT_ULX_MAX_ROOT_PORT 1
+
+#include <Library/CpuRegbarAccessLib.h>
+
+/**
+ Get CPU Maximum Pcie Root Port Number
+
+ @retval PcieMaxRootPort Pch Maximum Pcie Root Port Number
+**/
+UINT8
+GetMaxCpuPciePortNum (
+ VOID
+ );
+
+/**
+ Get CPU 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
+GetCpuPcieRpDevFun (
+ IN UINTN RpNumber,
+ OUT UINTN *RpDev,
+ OUT UINTN *RpFun
+ );
+
+/**
+ Gets pci segment base address of PCIe root port.
+
+ @param RpIndex Root Port Index (0 based)
+ @return PCIe port base address.
+**/
+UINT64
+CpuPcieBase (
+ IN UINT32 RpIndex
+ );
+
+#endif // _CPU_PCIE_INFO_FRU_LIB_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglCpu/Include/Register/SaRegsHostBridge.h b/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglCpu/Include/Register/SaRegsHostBridge.h
new file mode 100644
index 0000000000..32e38fa072
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglCpu/Include/Register/SaRegsHostBridge.h
@@ -0,0 +1,145 @@
+/** @file
+ Register names for Host Bridge block
+ <b>Conventions</b>:
+ - Prefixes:
+ - Definitions beginning with "R_" are registers
+ - Definitions beginning with "B_" are bits within registers
+ - Definitions beginning with "V_" are meaningful values of bits within the registers
+ - Definitions beginning with "S_" are register sizes
+ - Definitions beginning with "N_" are the bit position
+ - In general, SA registers are denoted by "_SA_" in register names
+ - Registers / bits that are different between SA generations are denoted by
+ "_SA_[generation_name]_" in register/bit names. e.g., "_SA_HSW_"
+ - Registers / bits that are different between SKUs are denoted by "_[SKU_name]"
+ at the end of the register/bit names
+ - Registers / bits of new devices introduced in a SA generation will be just named
+ as "_SA_" without [generation_name] inserted.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _SA_REGS_HOST_BRIDGE_H_
+#define _SA_REGS_HOST_BRIDGE_H_
+
+#define SA_SEG_NUM 0x00
+#define V_SA_DEVICE_ID_INVALID 0xFFFF
+//
+// DEVICE 0 (Memory Controller Hub)
+//
+#define SA_MC_BUS 0x00
+#define SA_MC_DEV 0x00
+#define SA_MC_FUN 0x00
+#define V_SA_MC_VID 0x8086
+#define R_SA_MC_DEVICE_ID 0x02
+#define R_SA_MC_CAPID0_B 0xE8
+
+//
+// SA DMI configuration
+//
+
+//
+// Maximum DMI lanes and bundles supported (x8 and 4 lanes)
+//
+#define SA_DMI_MAX_LANE 0x08
+#define SA_DMI_MAX_BUNDLE 0x04
+#define SA_DMI_MAX_LANE_VER1 0x04
+#define SA_DMI_MAX_BUNDLE_VER1 0x02
+
+
+//
+// TigerLake Mobile SA Device IDs B0:D0:F0
+//
+#define V_SA_DEVICE_ID_MB_ULT_1 0x9A14 ///< TigerLake Ult (TGL-U 4+2)
+#define V_SA_DEVICE_ID_MB_ULT_2 0x9A04 ///< TigerLake Ult (TGL-U 2+2)
+
+#define V_SA_DEVICE_ID_MB_ULX_1 0x9A12 ///< TigerLake Ulx (TGL-Y 4+2)
+#define V_SA_DEVICE_ID_MB_ULX_2 0x9A02 ///< TigerLake Ulx (TGL-Y 2+2)
+
+/**
+ <b>Description</b>:
+ - This is the base address for the Host Memory Mapped Configuration space. There is no physical memory within this 32KB window that can be addressed. The 32KB reserved by this register does not alias to any PCI 2.3 compliant memory mapped space. On reset, the Host MMIO Memory Mapped Configuation space is disabled and must be enabled by writing a 1 to MCHBAREN [Dev 0, offset48h, bit 0].
+ - All the bits in this register are locked in LT mode.
+ - The register space contains memory control, initialization, timing, and buffer strength registers; clocking registers; and power and thermal management registers.
+**/
+#define R_SA_MCHBAR (0x48)
+
+/**
+ <b>Description</b>:
+ - All the bits in this register are LT lockable.
+**/
+#define R_SA_GGC (0x50)
+
+/**
+ Description of GMS (8:15)
+ - This field is used to select the amount of Main Memory that is pre-allocated to support the Internal Graphics device in VGA (non-linear) and Native (linear) modes. The BIOS ensures that memory is pre-allocated only when Internal graphics is enabled.
+ - This register is also LT lockable.
+ - Valid options are 0 (0x0) to 2048MB (0x40) in multiples of 32 MB
+ - All other values are reserved
+ - Hardware does not clear or set any of these bits automatically based on IGD being disabled/enabled.
+ - BIOS Requirement: BIOS must not set this field to 0h if IVD (bit 1 of this register) is 0.
+**/
+#define N_SA_GGC_GMS_OFFSET (0x8)
+#define B_SA_GGC_GMS_MASK (0xff00)
+
+/**
+ Description of GGMS (6:7)
+ - This field is used to select the amount of Main Memory that is pre-allocated to support the Internal Graphics Translation Table. The BIOS ensures that memory is pre-allocated only when Internal graphics is enabled.
+ - GSM is assumed to be a contiguous physical DRAM space with DSM, and BIOS needs to allocate a contiguous memory chunk. Hardware will derive the base of GSM from DSM only using the GSM size programmed in the register.
+ - Valid options:
+ - 0h: 0 MB of memory pre-allocated for GTT.
+ - 1h: 2 MB of memory pre-allocated for GTT.
+ - 2h: 4 MB of memory pre-allocated for GTT.
+ - 3h: 8 MB of memory pre-allocated for GTT.
+ - Others: Reserved
+ - Hardware functionality in case of programming this value to Reserved is not guaranteed.
+**/
+#define N_SA_GGC_GGMS_OFFSET (0x6)
+#define B_SA_GGC_GGMS_MASK (0xc0)
+#define V_SA_GGC_GGMS_8MB 3
+
+/**
+ Description:
+ - Allows for enabling/disabling of PCI devices and functions that are within the CPU package. The table below the bit definitions describes the behavior of all combinations of transactions to devices controlled by this register.
+ All the bits in this register are LT Lockable.
+**/
+#define R_SA_DEVEN (0x54)
+
+/**
+ Description of D2EN (4:4)
+ - 0: Bus 0 Device 2 is disabled and hidden
+ - 1: Bus 0 Device 2 is enabled and visible
+ - This bit will remain 0 if Device 2 capability is disabled.
+**/
+#define B_SA_DEVEN_D2EN_MASK (0x10)
+
+
+///
+/// Description:
+/// The SMRAMC register controls how accesses to Compatible SMRAM spaces are treated. The Open, Close and Lock bits function only when G_SMRAME bit is set to 1. Also, the Open bit must be reset before the Lock bit is set.
+///
+#define R_SA_SMRAMC (0x88)
+
+///
+/// Description:
+/// This register contains the base address of stolen DRAM memory for the GTT. BIOS determines the base of GTT stolen memory by subtracting the GTT graphics stolen memory size (PCI Device 0 offset 52 bits 9:8) from the Graphics Base of Data Stolen Memory (PCI Device 0 offset B0 bits 31:20).
+///
+#define R_SA_BGSM (0xb4)
+
+
+///
+/// Description:
+/// This register contains the Top of low memory address.
+///
+#define R_SA_TOLUD (0xbc)
+
+///
+/// Description of TOLUD (20:31)
+/// This register contains bits 31 to 20 of an address one byte above the maximum DRAM memory below 4G that is usable by the operating system. Address bits 31 down to 20 programmed to 01h implies a minimum memory size of 1MB. Configuration software must set this value to the smaller of the following 2 choices: maximum amount memory in the system minus ME stolen memory plus one byte or the minimum address allocated for PCI memory. Address bits 19:0 are assumed to be 0_0000h for the purposes of address comparison. The Host interface positively decodes an address towards DRAM if the incoming address is less than the value programmed in this register.
+/// The Top of Low Usable DRAM is the lowest address above both Graphics Stolen memory and Tseg. BIOS determines the base of Graphics Stolen Memory by subtracting the Graphics Stolen Memory Size from TOLUD and further decrements by Tseg size to determine base of Tseg. All the Bits in this register are locked in LT mode.
+/// This register must be 1MB aligned when reclaim is enabled.
+///
+#define B_SA_TOLUD_TOLUD_MASK (0xfff00000)
+#define R_SA_MC_CAPID0_A_OFFSET 0xE4
+#define V_SA_LTR_MAX_SNOOP_LATENCY_VALUE 0x0846 ///< Intel recommended maximum value for Snoop Latency (70us)
+#define V_SA_LTR_MAX_NON_SNOOP_LATENCY_VALUE 0x0846 ///< Intel recommended maximum value for Non-Snoop Latency (70us)
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglCpu/Include/TcssInfo.h b/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglCpu/Include/TcssInfo.h
new file mode 100644
index 0000000000..cd8d57d948
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglCpu/Include/TcssInfo.h
@@ -0,0 +1,12 @@
+/** @file
+ Register names for TCSS USB devices
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _TCSS_INFO_H_
+#define _TCSS_INFO_H_
+
+#define MAX_ITBT_PCIE_PORT 4
+
+#endif
--
2.24.0.windows.2
^ permalink raw reply related [flat|nested] 42+ messages in thread
* [Patch V3 10/40] TigerlakeSiliconPkg/Fru: Add TglCpu/IncludePrivate headers
2021-02-05 7:40 [Patch V3 01/40] TigerlakeSiliconPkg: Add package and Include/ConfigBlock headers Heng Luo
` (7 preceding siblings ...)
2021-02-05 7:40 ` [Patch V3 09/40] TigerlakeSiliconPkg/Fru: Add TglCpu/Include headers Heng Luo
@ 2021-02-05 7:40 ` Heng Luo
2021-02-05 7:40 ` [Patch V3 11/40] TigerlakeSiliconPkg/Fru: Add TglPch/Include headers Heng Luo
` (29 subsequent siblings)
38 siblings, 0 replies; 42+ messages in thread
From: Heng Luo @ 2021-02-05 7:40 UTC (permalink / raw)
To: devel; +Cc: Sai Chaganty, Nate DeSimone
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3171
Adds the following header files:
* Fru/TglCpu/IncludePrivate
Cc: Sai Chaganty <rangasai.v.chaganty@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Signed-off-by: Heng Luo <heng.luo@intel.com>
---
Silicon/Intel/TigerlakeSiliconPkg/Fru/TglCpu/IncludePrivate/Library/VtdInitFruLib.h | 18 ++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Fru/TglCpu/IncludePrivate/Register/CpuPcieRegs.h | 24 ++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Fru/TglCpu/IncludePrivate/Register/IgdRegs.h | 42 ++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Fru/TglCpu/IncludePrivate/Register/IpuRegs.h | 31 +++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Fru/TglCpu/IncludePrivate/Register/VtdRegs.h | 22 ++++++++++++++++++++++
5 files changed, 137 insertions(+)
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglCpu/IncludePrivate/Library/VtdInitFruLib.h b/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglCpu/IncludePrivate/Library/VtdInitFruLib.h
new file mode 100644
index 0000000000..a46b29cbbe
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglCpu/IncludePrivate/Library/VtdInitFruLib.h
@@ -0,0 +1,18 @@
+/** @file
+ Vtd Initialization Fru Library header file
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _VTD_INIT_FRU_LIB_H_
+#define _VTD_INIT_FRU_LIB_H_
+
+///
+/// TCSS DMA controller RMRR buffer 4MB for each DMA controller
+///
+#define RMRR_TCSS_DMA_SIZE 0x400000
+
+extern UINT16 mDevEnMap[][2];
+extern UINTN mDevEnMapSize;
+
+#endif // _VTD_INIT_FRU_LIB_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglCpu/IncludePrivate/Register/CpuPcieRegs.h b/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglCpu/IncludePrivate/Register/CpuPcieRegs.h
new file mode 100644
index 0000000000..a571381202
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglCpu/IncludePrivate/Register/CpuPcieRegs.h
@@ -0,0 +1,24 @@
+/** @file
+ This file contains definitions of PCIe Configuration
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _CPU_PCIE_REGS_H_
+#define _CPU_PCIE_REGS_H_
+
+#define R_PCIE_LCAP 0x4C
+#define R_PCIE_LCTL 0x50
+#define R_PCIE_LSTS 0x52
+#define R_PCIE_SLCAP 0x54
+#define R_PCIE_SLSTS 0x5A
+#define R_PCIE_LCTL2 0x70
+#define R_PCIE_MPC 0xD8
+#define B_PCIE_MPC_HPME BIT1
+#define R_PCIE_PGTHRES 0x5C0
+#define B_PCIE_PGTHRES_L1PGLTREN BIT0
+#define R_PCIE_LCTL3 0xA34
+#define B_PCIE_LCTL3_PE BIT0
+
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglCpu/IncludePrivate/Register/IgdRegs.h b/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglCpu/IncludePrivate/Register/IgdRegs.h
new file mode 100644
index 0000000000..f0b30107f4
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglCpu/IncludePrivate/Register/IgdRegs.h
@@ -0,0 +1,42 @@
+/** @file
+ Register names for IGD block
+ <b>Conventions</b>:
+ - Prefixes:
+ - Definitions beginning with "R_" are registers
+ - Definitions beginning with "B_" are bits within registers
+ - Definitions beginning with "V_" are meaningful values of bits within the registers
+ - Definitions beginning with "S_" are register sizes
+ - Definitions beginning with "N_" are the bit position
+ - In general, SA registers are denoted by "_SA_" in register names
+ - Registers / bits that are different between SA generations are denoted by
+ "_SA_[generation_name]_" in register/bit names. e.g., "_SA_HSW_"
+ - Registers / bits that are different between SKUs are denoted by "_[SKU_name]"
+ at the end of the register/bit names
+ - Registers / bits of new devices introduced in a SA generation will be just named
+ as "_SA_" without [generation_name] inserted.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _IGD_REGS_H_
+#define _IGD_REGS_H_
+
+///
+/// Device 2 Register Equates
+///
+//
+// The following equates must be reviewed and revised when the specification is ready.
+//
+#define IGD_BUS_NUM 0x00
+#define IGD_DEV_NUM 0x02
+#define IGD_FUN_NUM 0x00
+
+///
+/// GTTMMADR aligned to 16MB (Base address = [38:24])
+///
+#define R_SA_IGD_GTTMMADR 0x10
+
+#define R_SA_IGD_SWSCI_OFFSET 0x00E8
+#define R_SA_IGD_ASLS_OFFSET 0x00FC ///< ASL Storage
+
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglCpu/IncludePrivate/Register/IpuRegs.h b/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglCpu/IncludePrivate/Register/IpuRegs.h
new file mode 100644
index 0000000000..afc72e8db0
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglCpu/IncludePrivate/Register/IpuRegs.h
@@ -0,0 +1,31 @@
+/** @file
+ Register names for IPU block
+ <b>Conventions</b>:
+ - Prefixes:
+ - Definitions beginning with "R_" are registers
+ - Definitions beginning with "B_" are bits within registers
+ - Definitions beginning with "V_" are meaningful values of bits within the registers
+ - Definitions beginning with "S_" are register sizes
+ - Definitions beginning with "N_" are the bit position
+ - IPU registers are denoted by "_IPU_" in register names
+ - Registers / bits that are different between IPU generations are denoted by
+ "_IPU_[generation_name]_" in register/bit names. e.g., "_IPU_TGL_"
+ - Registers / bits that are different between SKUs are denoted by "_[SKU_name]"
+ at the end of the register/bit names
+ - Registers / bits of new devices introduced in a IPU generation will be just named
+ as "_IPU_" without [generation_name] inserted.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _IPU_REGS_H_
+#define _IPU_REGS_H_
+
+//
+// Device 5 Equates
+//
+#define IPU_BUS_NUM 0x00
+#define IPU_DEV_NUM 0x05
+#define IPU_FUN_NUM 0x00
+
+#endif // _IPU_REGS_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglCpu/IncludePrivate/Register/VtdRegs.h b/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglCpu/IncludePrivate/Register/VtdRegs.h
new file mode 100644
index 0000000000..d796a44afc
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglCpu/IncludePrivate/Register/VtdRegs.h
@@ -0,0 +1,22 @@
+/** @file
+ Register names for VTD block
+ <b>Conventions</b>:
+ - Prefixes:
+ - Definitions beginning with "R_" are registers
+ - Definitions beginning with "B_" are bits within registers
+ - Definitions beginning with "V_" are meaningful values of bits within the registers
+ - Definitions beginning with "S_" are register sizes
+ - Definitions beginning with "N_" are the bit position
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _VTD_REGS_H_
+#define _VTD_REGS_H_
+
+///
+/// Vt-d Engine base address.
+///
+#define R_MCHBAR_VTD1_OFFSET 0x5400 ///< HW UNIT1 for IGD
+#define R_MCHBAR_VTD3_OFFSET 0x5410 ///< HW UNIT3 for all other - PEG, USB, SATA etc
+
+#endif
--
2.24.0.windows.2
^ permalink raw reply related [flat|nested] 42+ messages in thread
* [Patch V3 11/40] TigerlakeSiliconPkg/Fru: Add TglPch/Include headers
2021-02-05 7:40 [Patch V3 01/40] TigerlakeSiliconPkg: Add package and Include/ConfigBlock headers Heng Luo
` (8 preceding siblings ...)
2021-02-05 7:40 ` [Patch V3 10/40] TigerlakeSiliconPkg/Fru: Add TglCpu/IncludePrivate headers Heng Luo
@ 2021-02-05 7:40 ` Heng Luo
2021-02-05 7:40 ` [Patch V3 12/40] TigerlakeSiliconPkg/Fru: Add TglPch/IncludePrivate headers Heng Luo
` (28 subsequent siblings)
38 siblings, 0 replies; 42+ messages in thread
From: Heng Luo @ 2021-02-05 7:40 UTC (permalink / raw)
To: devel; +Cc: Sai Chaganty, Nate DeSimone
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3171
Adds the following header files:
* Fru/TglPch/Include
Cc: Sai Chaganty <rangasai.v.chaganty@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Signed-off-by: Heng Luo <heng.luo@intel.com>
---
Silicon/Intel/TigerlakeSiliconPkg/Fru/TglPch/Include/PchBdfAssignment.h | 326 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Fru/TglPch/Include/PchPcieRpInfo.h | 16 ++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Fru/TglPch/Include/PchReservedResources.h | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 397 insertions(+)
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglPch/Include/PchBdfAssignment.h b/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglPch/Include/PchBdfAssignment.h
new file mode 100644
index 0000000000..0d00f25d5e
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglPch/Include/PchBdfAssignment.h
@@ -0,0 +1,326 @@
+/** @file
+ Header file for TigerLake PCH devices PCI Bus Device Function map.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PCH_BDF_ASSIGNMENT_H_
+#define _PCH_BDF_ASSIGNMENT_H_
+
+#define NOT_PRESENT 0xFF
+
+#define MAX_SATA_CONTROLLER 1
+
+//
+// PCH PCIe Controllers
+//
+#define PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_1 28
+#define PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_2 28
+#define PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_3 28
+#define PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_4 28
+#define PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_5 28
+#define PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_6 28
+#define PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_7 28
+#define PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_8 28
+#define PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_9 29
+#define PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_10 29
+#define PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_11 29
+#define PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_12 29
+#define PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_13 29
+#define PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_14 29
+#define PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_15 29
+#define PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_16 29
+#define PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_17 27
+#define PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_18 27
+#define PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_19 27
+#define PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_20 27
+#define PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_21 27
+#define PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_22 27
+#define PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_23 27
+#define PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_24 27
+#define PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_25 NOT_PRESENT
+#define PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_26 NOT_PRESENT
+#define PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_27 NOT_PRESENT
+#define PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_28 NOT_PRESENT
+
+//
+// USB3 (XHCI) Controller PCI config
+//
+#define PCI_DEVICE_NUMBER_PCH_XHCI 20
+#define PCI_FUNCTION_NUMBER_PCH_XHCI 0
+
+//
+// xDCI (OTG) USB Device Controller
+//
+#define PCI_DEVICE_NUMBER_PCH_XDCI 20
+#define PCI_FUNCTION_NUMBER_PCH_XDCI 1
+
+//
+// Thermal Device
+//
+#define PCI_DEVICE_NUMBER_PCH_THERMAL NOT_PRESENT
+#define PCI_FUNCTION_NUMBER_PCH_THERMAL NOT_PRESENT
+
+//
+// CSME HECI #1
+//
+#define PCI_DEVICE_NUMBER_PCH_HECI1 22
+#define PCI_FUNCTION_NUMBER_PCH_HECI1 0
+
+//
+// CSME HECI #2
+//
+#define PCI_DEVICE_NUMBER_PCH_HECI2 22
+#define PCI_FUNCTION_NUMBER_PCH_HECI2 1
+
+//
+// CSME IDE-Redirection (IDE-R)
+//
+#define PCI_DEVICE_NUMBER_PCH_IDER 22
+#define PCI_FUNCTION_NUMBER_PCH_IDER 2
+
+//
+// CSME Keyboard and Text (KT) Redirection
+//
+#define PCI_DEVICE_NUMBER_PCH_KTR 22
+#define PCI_FUNCTION_NUMBER_PCH_KTR 3
+
+//
+// CSME HECI #3
+//
+#define PCI_DEVICE_NUMBER_PCH_HECI3 22
+#define PCI_FUNCTION_NUMBER_PCH_HECI3 4
+
+//
+// CSME HECI #4
+//
+#define PCI_DEVICE_NUMBER_PCH_HECI4 22
+#define PCI_FUNCTION_NUMBER_PCH_HECI4 5
+
+//
+// CSME MROM
+//
+#define PCI_DEVICE_NUMBER_PCH_MROM NOT_PRESENT
+#define PCI_FUNCTION_NUMBER_PCH_MROM NOT_PRESENT
+
+//
+// CSME WLAN
+//
+#define PCI_DEVICE_NUMBER_PCH_WLAN 22
+#define PCI_FUNCTION_NUMBER_PCH_WLAN 7
+
+//
+// SATA Controllers
+//
+#define PCI_DEVICE_NUMBER_PCH_SATA_1 23
+#define PCI_FUNCTION_NUMBER_PCH_SATA_1 0
+#define PCI_DEVICE_NUMBER_PCH_SATA_2 NOT_PRESENT
+#define PCI_FUNCTION_NUMBER_PCH_SATA_2 NOT_PRESENT
+#define PCI_DEVICE_NUMBER_PCH_SATA_3 NOT_PRESENT
+#define PCI_FUNCTION_NUMBER_PCH_SATA_3 NOT_PRESENT
+
+//
+// PCH LP Serial IO I2C #0 Controller
+//
+#define PCI_DEVICE_NUMBER_PCH_SERIAL_IO_I2C0 21
+#define PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_I2C0 0
+
+//
+// PCH LP Serial IO I2C #1 Controller
+//
+#define PCI_DEVICE_NUMBER_PCH_SERIAL_IO_I2C1 21
+#define PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_I2C1 1
+
+//
+// PCH LP Serial IO I2C #2 Controller
+//
+#define PCI_DEVICE_NUMBER_PCH_SERIAL_IO_I2C2 21
+#define PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_I2C2 2
+
+//
+// PCH LP Serial IO I2C #3 Controller
+//
+#define PCI_DEVICE_NUMBER_PCH_SERIAL_IO_I2C3 21
+#define PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_I2C3 3
+
+//
+// PCH LP Serial IO I2C #4 Controller
+//
+#define PCI_DEVICE_NUMBER_PCH_SERIAL_IO_I2C4 25
+#define PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_I2C4 0
+
+//
+// PCH LP Serial IO I2C #5 Controller
+//
+#define PCI_DEVICE_NUMBER_PCH_SERIAL_IO_I2C5 25
+#define PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_I2C5 1
+
+//
+// PCH LP Serial IO I2C #6 Controller
+//
+#define PCI_DEVICE_NUMBER_PCH_SERIAL_IO_I2C6 16
+#define PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_I2C6 0
+
+//
+// PCH LP Serial IO I2C #7 Controller
+//
+#define PCI_DEVICE_NUMBER_PCH_SERIAL_IO_I2C7 16
+#define PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_I2C7 1
+
+//
+// PCH LP Serial IO SPI #0 Controller
+//
+#define PCI_DEVICE_NUMBER_PCH_SERIAL_IO_SPI0 30
+#define PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_SPI0 2
+
+//
+// PCH LP Serial IO SPI #1 Controller
+//
+#define PCI_DEVICE_NUMBER_PCH_SERIAL_IO_SPI1 30
+#define PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_SPI1 3
+
+//
+// PCH LP Serial IO SPI #2 Controller
+//
+#define PCI_DEVICE_NUMBER_PCH_SERIAL_IO_SPI2 18
+#define PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_SPI2 6
+
+//
+// PCH LP Serial IO SPI #3 Controller
+//
+#define PCI_DEVICE_NUMBER_PCH_SERIAL_IO_SPI3 19
+#define PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_SPI3 0
+
+//
+// PCH LP Serial IO SPI #4 Controller
+//
+#define PCI_DEVICE_NUMBER_PCH_SERIAL_IO_SPI4 19
+#define PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_SPI4 1
+
+//
+// PCH LP Serial IO SPI #5 Controller
+//
+#define PCI_DEVICE_NUMBER_PCH_SERIAL_IO_SPI5 19
+#define PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_SPI5 2
+
+//
+// PCH LP Serial IO SPI #6 Controller
+//
+#define PCI_DEVICE_NUMBER_PCH_SERIAL_IO_SPI6 19
+#define PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_SPI6 3
+
+//
+// PCH LP Serial IO UART #0 Controller
+//
+#define PCI_DEVICE_NUMBER_PCH_SERIAL_IO_UART0 30
+#define PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_UART0 0
+
+//
+// PCH LP Serial IO UART #1 Controller
+//
+#define PCI_DEVICE_NUMBER_PCH_SERIAL_IO_UART1 30
+#define PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_UART1 1
+
+//
+// PCH LP Serial IO UART #2 Controller
+//
+#define PCI_DEVICE_NUMBER_PCH_SERIAL_IO_UART2 25
+#define PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_UART2 2
+
+//
+// PCH LP Serial IO UART #3 Controller
+//
+#define PCI_DEVICE_NUMBER_PCH_SERIAL_IO_UART3 17
+#define PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_UART3 0
+
+//
+// PCH LP Serial IO UART #4 Controller
+//
+#define PCI_DEVICE_NUMBER_PCH_SERIAL_IO_UART4 17
+#define PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_UART4 1
+
+//
+// PCH LP Serial IO UART #5 Controller
+//
+#define PCI_DEVICE_NUMBER_PCH_SERIAL_IO_UART5 17
+#define PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_UART5 2
+
+//
+// PCH LP Serial IO UART #6 Controller
+//
+#define PCI_DEVICE_NUMBER_PCH_SERIAL_IO_UART6 17
+#define PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_UART6 3
+
+//
+// DMA-SMBus Controller
+//
+#define PCI_DEVICE_NUMBER_PCH_DMA_SMBUS 30
+#define PCI_FUNCTION_NUMBER_PCH_DMA_SMBUS 4
+
+//
+// TSN GbE Controller #1
+//
+#define PCI_DEVICE_NUMBER_PCH_TSN0 30
+#define PCI_FUNCTION_NUMBER_PCH_TSN0 4
+
+//
+// TSN GbE Controller #2
+//
+#define PCI_DEVICE_NUMBER_PCH_TSN1 30
+#define PCI_FUNCTION_NUMBER_PCH_TSN1 5
+
+//
+// LPC Controller
+//
+#define PCI_DEVICE_NUMBER_PCH_LPC 31
+#define PCI_FUNCTION_NUMBER_PCH_LPC 0
+
+//
+// eSPI Controller
+//
+#define PCI_DEVICE_NUMBER_PCH_ESPI 31
+#define PCI_FUNCTION_NUMBER_PCH_ESPI 0
+
+//
+// Primary to Sideband (P2SB) Bridge
+//
+#define PCI_DEVICE_NUMBER_PCH_P2SB 31
+#define PCI_FUNCTION_NUMBER_PCH_P2SB 1
+
+//
+// PMC (D31:F2)
+//
+#define PCI_DEVICE_NUMBER_PCH_PMC 31
+#define PCI_FUNCTION_NUMBER_PCH_PMC 2
+
+//
+// PMC SSRAM Registers
+//
+#define PCI_DEVICE_NUMBER_PCH_PMC_SSRAM 20
+#define PCI_FUNCTION_NUMBER_PCH_PMC_SSRAM 2
+
+//
+// HD-A Controller
+//
+#define PCI_DEVICE_NUMBER_PCH_HDA 31
+#define PCI_FUNCTION_NUMBER_PCH_HDA 3
+
+//
+// SMBus Controller
+//
+#define PCI_DEVICE_NUMBER_PCH_SMBUS 31
+#define PCI_FUNCTION_NUMBER_PCH_SMBUS 4
+
+//
+// SPI Controller (D31:F5)
+//
+#define PCI_DEVICE_NUMBER_PCH_SPI 31
+#define PCI_FUNCTION_NUMBER_PCH_SPI 5
+
+//
+// Gigabit Ethernet LAN Controller (D31:F6)
+//
+#define PCI_DEVICE_NUMBER_GBE 31
+#define PCI_FUNCTION_NUMBER_GBE 6
+
+#endif // _PCH_BDF_ASSIGNMENT_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglPch/Include/PchPcieRpInfo.h b/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglPch/Include/PchPcieRpInfo.h
new file mode 100644
index 0000000000..d3548796a3
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglPch/Include/PchPcieRpInfo.h
@@ -0,0 +1,16 @@
+/** @file
+ Pcie Root Port info header
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _PCH_PCIERP_INFO_H_
+#define _PCH_PCIERP_INFO_H_
+
+//
+// Number of PCIe ports per PCIe controller
+//
+#define PCH_PCIE_CONTROLLER_PORTS 4u
+
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglPch/Include/PchReservedResources.h b/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglPch/Include/PchReservedResources.h
new file mode 100644
index 0000000000..283246692f
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglPch/Include/PchReservedResources.h
@@ -0,0 +1,55 @@
+/** @file
+ PCH preserved MMIO resource definitions.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PCH_PRESERVED_RESOURCES_H_
+#define _PCH_PRESERVED_RESOURCES_H_
+
+/**
+ Detailed recommended static allocation
+ +-------------------------------------------------------------------------+
+ | PCH preserved MMIO range, 32 MB, from 0xFC800000 to 0xFE7FFFFF |
+ +-------------------------------------------------------------------------+
+ | Size | Start | End | Usage |
+ | 8 MB | 0xFC800000 | 0xFCFFFFFF | TraceHub SW BAR |
+ | 16 MB | 0xFD000000 | 0xFDFFFFFF | SBREG |
+ | 64 KB | 0xFE000000 | 0xFE00FFFF | PMC MBAR |
+ | 4 KB | 0xFE010000 | 0xFE010FFF | SPI BAR0 |
+ | 176 KB | 0xFE020000 | 0xFE04BFFF | SerialIo BAR in ACPI mode |
+ | 400 KB | 0xFE04C000 | 0xFE0AFFFF | Unused |
+ | 64 KB | 0xFE0B0000 | 0xFE0BFFFF | eSPI LGMR BAR |
+ | 64 KB | 0xFE0C0000 | 0xFE0CFFFF | eSPI2 SEGMR BAR |
+ | 192 KB | 0xFE0D0000 | 0xFE0FFFFF | Unused |
+ | 1 MB | 0xFE100000 | 0xFE1FFFFF | TraceHub MTB BAR |
+ | 2 MB | 0xFE200000 | 0xFE3FFFFF | TraceHub FW BAR |
+ | 2 MB | 0xFE400000 | 0xFE5FFFFF | Unused |
+ | 2 MB | 0xFE600000 | 0xFE7FFFFF | Temp address |
+ +-------------------------------------------------------------------------+
+**/
+#define PCH_PRESERVED_BASE_ADDRESS 0xFC800000 ///< Pch preserved MMIO base address
+#define PCH_PRESERVED_MMIO_SIZE 0x02000000 ///< 32MB
+#define PCH_TRACE_HUB_SW_BASE_ADDRESS 0xFC800000 ///< TraceHub SW MMIO base address
+#define PCH_TRACE_HUB_SW_MMIO_SIZE 0x00800000 ///< 8MB
+#define PCH_PCR_BASE_ADDRESS 0xFD000000 ///< SBREG MMIO base address
+#define PCH_PCR_MMIO_SIZE 0x01000000 ///< 16MB
+#define PCH_PWRM_BASE_ADDRESS 0xFE000000 ///< PMC MBAR MMIO base address
+#define PCH_PWRM_MMIO_SIZE 0x00010000 ///< 64KB
+#define PCH_SPI_BASE_ADDRESS 0xFE010000 ///< SPI BAR0 MMIO base address
+#define PCH_SPI_MMIO_SIZE 0x00001000 ///< 4KB
+#define PCH_SERIAL_IO_BASE_ADDRESS 0xFE020000 ///< SerialIo MMIO base address
+#define PCH_SERIAL_IO_MMIO_SIZE 0x0002C000 ///< 176KB
+#define PCH_ESPI_LGMR_BASE_ADDRESS 0xFE0B0000 ///< eSPI LGMR MMIO base address
+#define PCH_ESPI_LGMR_MMIO_SIZE 0x00010000 ///< 64KB
+#define PCH_ESPI_SEGMR_BASE_ADDRESS 0xFE0C0000 ///< Second eSPI GMR MMIO base address
+#define PCH_ESPI_SEGMR_MMIO_SIZE 0x00010000 ///< 64KB
+#define PCH_TRACE_HUB_MTB_BASE_ADDRESS 0xFE100000 ///< TraceHub MTB MMIO base address
+#define PCH_TRACE_HUB_MTB_MMIO_SIZE 0x00100000 ///< 1MB
+#define PCH_TRACE_HUB_FW_BASE_ADDRESS 0xFE200000 ///< TraceHub FW MMIO base address
+#define PCH_TRACE_HUB_FW_MMIO_SIZE 0x00200000 ///< 2MB
+#define PCH_TEMP_BASE_ADDRESS 0xFE600000 ///< preserved temp address for misc usage,
+#define PCH_TEMP_MMIO_SIZE 0x00200000 ///< 2MB
+
+#endif // _PCH_PRESERVED_RESOURCES_H_
+
--
2.24.0.windows.2
^ permalink raw reply related [flat|nested] 42+ messages in thread
* [Patch V3 12/40] TigerlakeSiliconPkg/Fru: Add TglPch/IncludePrivate headers
2021-02-05 7:40 [Patch V3 01/40] TigerlakeSiliconPkg: Add package and Include/ConfigBlock headers Heng Luo
` (9 preceding siblings ...)
2021-02-05 7:40 ` [Patch V3 11/40] TigerlakeSiliconPkg/Fru: Add TglPch/Include headers Heng Luo
@ 2021-02-05 7:40 ` Heng Luo
2021-02-05 7:40 ` [Patch V3 13/40] TigerlakeSiliconPkg/IpBlock: Add Cnvi component Heng Luo
` (27 subsequent siblings)
38 siblings, 0 replies; 42+ messages in thread
From: Heng Luo @ 2021-02-05 7:40 UTC (permalink / raw)
To: devel; +Cc: Sai Chaganty, Nate DeSimone
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3171
Adds the following header files:
* Fru/TglPch/IncludePrivate
Cc: Sai Chaganty <rangasai.v.chaganty@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Signed-off-by: Heng Luo <heng.luo@intel.com>
---
Silicon/Intel/TigerlakeSiliconPkg/Fru/TglPch/IncludePrivate/Register/PchPcrRegs.h | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 66 insertions(+)
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglPch/IncludePrivate/Register/PchPcrRegs.h b/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglPch/IncludePrivate/Register/PchPcrRegs.h
new file mode 100644
index 0000000000..4987d21f09
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglPch/IncludePrivate/Register/PchPcrRegs.h
@@ -0,0 +1,66 @@
+/** @file
+ Register names for PCH private chipset register
+
+Conventions:
+
+ - Register definition format:
+ Prefix_[GenerationName]_[ComponentName]_SubsystemName_RegisterSpace_RegisterName
+ - Prefix:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register size
+ Definitions beginning with "N_" are the bit position
+ - [GenerationName]:
+ Three letter acronym of the generation is used (e.g. SKL,KBL,CNL etc.).
+ Register name without GenerationName applies to all generations.
+ - [ComponentName]:
+ This field indicates the component name that the register belongs to (e.g. PCH, SA etc.)
+ Register name without ComponentName applies to all components.
+ Register that is specific to -LP denoted by "_PCH_LP_" in component name.
+ - SubsystemName:
+ This field indicates the subsystem name of the component that the register belongs to
+ (e.g. PCIE, USB, SATA, GPIO, PMC etc.).
+ - RegisterSpace:
+ MEM - MMIO space register of subsystem.
+ IO - IO space register of subsystem.
+ PCR - Private configuration register of subsystem.
+ CFG - PCI configuration space register of subsystem.
+ - RegisterName:
+ Full register name.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PCH_REGS_PCR_H_
+#define _PCH_REGS_PCR_H_
+
+/**
+ Definition for SBI PID
+ The PCH_SBI_PID defines the PID for PCR MMIO programming and PCH SBI programming as well.
+**/
+#define PID_CNVI 0x73
+#define PID_ICLK 0xAD
+#define PID_DMI 0x88
+#define PID_PSTH 0x89
+#define PID_ESPISPI 0x72
+#define PID_SPF 0x85
+#define PID_SPE 0x84
+#define PID_SPD 0x83
+#define PID_SPC 0x82
+#define PID_SPB 0x81
+#define PID_SPA 0x80
+#define PID_PSF6 0x7F
+#define PID_PSF4 0xBD
+#define PID_PSF3 0xBC
+#define PID_PSF2 0xBB
+#define PID_PSF1 0xBA
+#define PID_GPIOCOM0 0x6E
+#define PID_GPIOCOM1 0x6D
+#define PID_GPIOCOM2 0x6C
+#define PID_GPIOCOM3 0x6B
+#define PID_GPIOCOM4 0x6A
+#define PID_GPIOCOM5 0x69
+#define PID_CSME_PSF 0x8F
+
+#endif
--
2.24.0.windows.2
^ permalink raw reply related [flat|nested] 42+ messages in thread
* [Patch V3 13/40] TigerlakeSiliconPkg/IpBlock: Add Cnvi component
2021-02-05 7:40 [Patch V3 01/40] TigerlakeSiliconPkg: Add package and Include/ConfigBlock headers Heng Luo
` (10 preceding siblings ...)
2021-02-05 7:40 ` [Patch V3 12/40] TigerlakeSiliconPkg/Fru: Add TglPch/IncludePrivate headers Heng Luo
@ 2021-02-05 7:40 ` Heng Luo
2021-02-05 7:40 ` [Patch V3 14/40] TigerlakeSiliconPkg/IpBlock: Add CpuPcieRp component Heng Luo
` (26 subsequent siblings)
38 siblings, 0 replies; 42+ messages in thread
From: Heng Luo @ 2021-02-05 7:40 UTC (permalink / raw)
To: devel; +Cc: Sai Chaganty, Nate DeSimone
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3171
Adds the following files:
* IpBlock/Cnvi/IncludePrivate
Cc: Sai Chaganty <rangasai.v.chaganty@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Signed-off-by: Heng Luo <heng.luo@intel.com>
---
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Cnvi/IncludePrivate/CnviConfigHob.h | 27 +++++++++++++++++++++++++++
1 file changed, 27 insertions(+)
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Cnvi/IncludePrivate/CnviConfigHob.h b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Cnvi/IncludePrivate/CnviConfigHob.h
new file mode 100644
index 0000000000..e881e49d62
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Cnvi/IncludePrivate/CnviConfigHob.h
@@ -0,0 +1,27 @@
+/** @file
+ This file defines the CNVi CONFIG HOB
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _CNVI_CONFIG_HOB_H_
+#define _CNVI_CONFIG_HOB_H_
+
+#include <Base.h>
+
+extern EFI_GUID gCnviConfigHobGuid;
+#pragma pack (push,1)
+
+/**
+ This HOB is used to pass CNVi related private information to DXE phase
+**/
+typedef struct {
+ EFI_HOB_GUID_TYPE EfiHobGuidType; ///< GUID HOB type structure for gCnviConfigHobGuid
+ UINT32 Mode : 1; ///< 0: Disabled, <b>1: Auto</b>
+ UINT32 BtCore : 1; ///< 0: Disabled, <b>1: Enabled</b>
+ UINT32 BtAudioOffload : 1; ///< <b>0: Disabled</b>, 1: Enabled
+ UINT32 RsvdBits0 : 29; ///< Reserved bits
+} CNVI_CONFIG_HOB;
+#pragma pack (pop)
+
+#endif // _CNVI_CONFIG_HOB_H_
--
2.24.0.windows.2
^ permalink raw reply related [flat|nested] 42+ messages in thread
* [Patch V3 14/40] TigerlakeSiliconPkg/IpBlock: Add CpuPcieRp component
2021-02-05 7:40 [Patch V3 01/40] TigerlakeSiliconPkg: Add package and Include/ConfigBlock headers Heng Luo
` (11 preceding siblings ...)
2021-02-05 7:40 ` [Patch V3 13/40] TigerlakeSiliconPkg/IpBlock: Add Cnvi component Heng Luo
@ 2021-02-05 7:40 ` Heng Luo
2021-02-05 7:40 ` [Patch V3 15/40] TigerlakeSiliconPkg/IpBlock: Add Espi component Heng Luo
` (25 subsequent siblings)
38 siblings, 0 replies; 42+ messages in thread
From: Heng Luo @ 2021-02-05 7:40 UTC (permalink / raw)
To: devel; +Cc: Sai Chaganty, Nate DeSimone
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3171
Adds the following files:
* IpBlock/CpuPcieRp/Include
* IpBlock/CpuPcieRp/IncludePrivate
* IpBlock/CpuPcieRp/Library
* IpBlock/CpuPcieRp/LibraryPrivate
Cc: Sai Chaganty <rangasai.v.chaganty@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Signed-off-by: Heng Luo <heng.luo@intel.com>
---
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/CpuPcieRp/Include/CpuPcieInfo.h | 31 +++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/CpuPcieRp/Include/Library/CpuPcieInitCommon.h | 353 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/CpuPcieRp/Include/Library/CpuPcieRpLib.h | 47 +++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/CpuPcieRp/IncludePrivate/Library/DxeCpuPcieRpLib.h | 18 ++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/CpuPcieRp/Library/PeiDxeSmmCpuPcieInitCommonLib/CpuPcieInitCommon.c | 445 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/CpuPcieRp/Library/PeiDxeSmmCpuPcieInitCommonLib/PeiDxeSmmCpuPcieInitCommonLib.inf | 33 +++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/CpuPcieRp/Library/PeiDxeSmmCpuPcieRpLib/CpuPcieRpLib.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/CpuPcieRp/Library/PeiDxeSmmCpuPcieRpLib/PeiDxeSmmCpuPcieRpLib.inf | 32 ++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/CpuPcieRp/LibraryPrivate/DxeCpuPcieRpLib/DxeCpuPcieRpLib.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/CpuPcieRp/LibraryPrivate/DxeCpuPcieRpLib/DxeCpuPcieRpLib.inf | 40 ++++++++++++++++++++++++++++++++++++++++
10 files changed, 1109 insertions(+)
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/CpuPcieRp/Include/CpuPcieInfo.h b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/CpuPcieRp/Include/CpuPcieInfo.h
new file mode 100644
index 0000000000..15eeab0ecf
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/CpuPcieRp/Include/CpuPcieInfo.h
@@ -0,0 +1,31 @@
+/** @file
+ This file contains definitions of PCIe controller information
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _CPU_PCIE_INFO_H_
+#define _CPU_PCIE_INFO_H_
+
+#define PCIE_HWEQ_COEFFS_MAX 5
+
+//
+// Device 1 Memory Mapped IO Register Offset Equates
+//
+#define SA_PEG_DEV_NUM 0x01
+#define SA_PEG0_DEV_NUM SA_PEG_DEV_NUM
+#define SA_PEG3_DEV_NUM 0x06
+
+//
+// SA PCI Express* Port configuration
+//
+
+#define CPU_PCIE_MAX_ROOT_PORTS 4
+
+#define SA_PEG_MAX_FUN 0x04
+#define SA_PEG_MAX_LANE 0x14
+#define SA_PEG_MAX_FUN_GEN3 0x03
+#define SA_PEG_MAX_LANE_GEN3 0x10
+#define SA_PEG_MAX_BUNDLE_GEN3 0x08
+
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/CpuPcieRp/Include/Library/CpuPcieInitCommon.h b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/CpuPcieRp/Include/Library/CpuPcieInitCommon.h
new file mode 100644
index 0000000000..79b255c273
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/CpuPcieRp/Include/Library/CpuPcieInitCommon.h
@@ -0,0 +1,353 @@
+/** @file
+Header file for CpuPcieInitCommonLib.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _CPU_PCIE_INIT_COMMON_H_
+#define _CPU_PCIE_INIT_COMMON_H_
+
+#include <Library/CpuRegbarAccessLib.h>
+
+/**
+ Print registers value
+
+ @param[in] PrintMmioBase Mmio base address
+ @param[in] PrintSize Number of registers
+ @param[in] OffsetFromBase Offset from mmio base address
+
+ @retval None
+**/
+VOID
+SaPrintRegisters (
+ IN UINTN PrintMmioBase,
+ IN UINT32 PrintSize,
+ IN UINT32 OffsetFromBase
+ );
+
+/**
+ Print registers value
+
+ @param[in] PrintPciSegmentBase Pci segment base address
+ @param[in] PrintSize Number of registers
+ @param[in] OffsetFromBase Offset from mmio base address
+
+ @retval None
+**/
+VOID
+SaPrintPciRegisters (
+ IN UINT64 PrintPciSegmentBase,
+ IN UINT32 PrintSize,
+ IN UINT32 OffsetFromBase
+ );
+
+//
+// 2LM: PegPcie APIs for Sideband Access Mechanism in 2LM mode
+//
+/**
+Reads an 8-bit PCI configuration register.
+
+Its a wrapper library function. This function uses side band access for PEG60 when 2LM mode is enabled.
+Other calls to this function will be routed to core PciSegmentRead8 function.
+
+@param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register.
+
+@return The 8-bit PCI configuration register specified by Address.
+
+**/
+UINT8
+EFIAPI
+PegPciSegmentRead8 (
+ IN UINT64 Address
+ );
+
+/**
+Writes an 8-bit PCI configuration register.
+
+Its a wrapper library function. This function uses side band access for PEG60 when 2LM mode is enabled.
+Other calls to this function will be routed to core PciSegmentWrite8 function.
+
+@param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register.
+@param Value The value to write.
+
+@return The value written to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PegPciSegmentWrite8 (
+ IN UINT64 Address,
+ IN UINT8 Value
+ );
+
+/**
+Reads a 16-bit PCI configuration register.
+
+Its a wrapper library function. This function uses side band access for PEG60 when 2LM mode is enabled.
+Other calls to this function will be routed to core PciSegmentRead16 function.
+
+@param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register.
+
+@return The 16-bit PCI configuration register specified by Address.
+
+**/
+UINT16
+EFIAPI
+PegPciSegmentRead16 (
+ IN UINT64 Address
+ );
+
+/**
+Writes a 16-bit PCI configuration register.
+
+Its a wrapper library function. This function uses side band access for PEG60 when 2LM mode is enabled.
+Other calls to this function will be routed to core PciSegmentWrite16 function.
+
+@param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register.
+@param Value The value to write.
+
+@return The parameter of Value.
+
+**/
+UINT16
+EFIAPI
+PegPciSegmentWrite16 (
+ IN UINT64 Address,
+ IN UINT16 Value
+ );
+
+/**
+Reads a 32-bit PCI configuration register.
+
+Its a wrapper library function. This function uses side band access for PEG60 when 2LM mode is enabled.
+Other calls to this function will be routed to core PciSegmentRead32 function.
+
+@param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register.
+
+@return The 32-bit PCI configuration register specified by Address.
+
+**/
+UINT32
+EFIAPI
+PegPciSegmentRead32 (
+ IN UINT64 Address
+ );
+
+/**
+Writes a 32-bit PCI configuration register.
+
+Its a wrapper library function. This function uses side band access for PEG60 when 2LM mode is enabled.
+Other calls to this function will be routed to core PciSegmentWrite32 function.
+
+@param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register.
+@param Value The value to write.
+
+@return The parameter of Value.
+
+**/
+UINT32
+EFIAPI
+PegPciSegmentWrite32 (
+ IN UINT64 Address,
+ IN UINT32 Value
+ );
+
+/**
+Performs a bitwise OR of a 16-bit PCI configuration register with a 16-bit value.
+
+Its a wrapper library function. This function uses side band access for PEG60 when 2LM mode is enabled.
+Other calls to this function will be routed to core PciSegmentOr16 function.
+
+@param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register.
+@param OrData The value to OR with the PCI configuration register.
+
+@return The value written to the PCI configuration register.
+**/
+UINT16
+EFIAPI
+PegPciSegmentOr16 (
+ IN UINT64 Address,
+ IN UINT16 OrData
+ );
+
+/**
+Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit value.
+
+Its a wrapper library function. This function uses side band access for PEG60 when 2LM mode is enabled.
+Other calls to this function will be routed to core PciSegmentAnd32 function.
+
+@param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register.
+@param AndData The value to AND with the PCI configuration register.
+
+@return The value written to the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PegPciSegmentAnd16 (
+ IN UINT64 Address,
+ IN UINT16 AndData
+ );
+
+/**
+Performs a bitwise AND of a 8-bit PCI configuration register with a 8-bit value.
+
+Its a wrapper library function. This function uses side band access for PEG60 when 2LM mode is enabled.
+Other calls to this function will be routed to core PciSegmentAnd8 function.
+
+@param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register.
+@param AndData The value to AND with the PCI configuration register.
+
+@return The value written to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PegPciSegmentAnd8 (
+ IN UINT64 Address,
+ IN UINT8 AndData
+ );
+
+/**
+Performs a bitwise OR of a 32-bit PCI configuration register with a 32-bit value.
+
+Its a wrapper library function. This function uses side band access for PEG60 when 2LM mode is enabled.
+Other calls to this function will be routed to core PciSegmentOr32 function.
+
+@param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register.
+@param OrData The value to OR with the PCI configuration register.
+
+@return The value written to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PegPciSegmentOr32 (
+ IN UINT64 Address,
+ IN UINT32 OrData
+ );
+
+/**
+Performs a bitwise OR of a 8-bit PCI configuration register with a 8-bit value.
+
+Its a wrapper library function. This function uses side band access for PEG60 when 2LM mode is enabled.
+Other calls to this function will be routed to core PciSegmentOr8 function.
+
+@param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register.
+@param OrData The value to OR with the PCI configuration register.
+
+@return The value written to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PegPciSegmentOr8 (
+ IN UINT64 Address,
+ IN UINT8 OrData
+ );
+
+/**
+Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit value.
+
+Its a wrapper library function. This function uses side band access for PEG60 when 2LM mode is enabled.
+Other calls to this function will be routed to core PciSegmentAnd32 function.
+
+@param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register.
+@param AndData The value to AND with the PCI configuration register.
+
+@return The value written to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PegPciSegmentAnd32 (
+ IN UINT64 Address,
+ IN UINT32 AndData
+ );
+
+/**
+Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit value,
+followed a bitwise OR with another 32-bit value.
+
+Its a wrapper library function. This function uses side band access for PEG60 when 2LM mode is enabled.
+Other calls to this function will be routed to core PciSegmentAndThenOr32 function.
+
+@param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register.
+@param AndData The value to AND with the PCI configuration register.
+@param OrData The value to OR with the PCI configuration register.
+
+@return The value written to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PegPciSegmentAndThenOr32 (
+ IN UINT64 Address,
+ IN UINT32 AndData,
+ IN UINT32 OrData
+ );
+
+/**
+Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit value,
+followed a bitwise OR with another 16-bit value.
+
+Its a wrapper library function. This function uses side band access for PEG60 when 2LM mode is enabled.
+Other calls to this function will be routed to core PciSegmentAndThenOr16 function.
+
+@param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register.
+@param AndData The value to AND with the PCI configuration register.
+@param OrData The value to OR with the PCI configuration register.
+
+@return The value written to the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PegPciSegmentAndThenOr16 (
+ IN UINT64 Address,
+ IN UINT16 AndData,
+ IN UINT16 OrData
+ );
+
+/**
+Performs a bitwise AND of a 8-bit PCI configuration register with a 8-bit value,
+followed a bitwise OR with another 8-bit value.
+
+Its a wrapper library function. This function uses side band access for PEG60 when 2LM mode is enabled.
+Other calls to this function will be routed to core PciSegmentAndThenOr8 function.
+
+@param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register.
+@param AndData The value to AND with the PCI configuration register.
+@param OrData The value to OR with the PCI configuration register.
+
+@return The value written to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PegPciSegmentAndThenOr8 (
+ IN UINT64 Address,
+ IN UINT8 AndData,
+ IN UINT8 OrData
+ );
+
+/**
+Find the Offset to a Capabilities ID
+@param[in] Segment Pci Segment Number
+@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
+PegPcieFindCapId (
+ IN UINT8 Segment,
+ IN UINT8 Bus,
+ IN UINT8 Device,
+ IN UINT8 Function,
+ IN UINT8 CapId
+ );
+#endif // _CPU_PCIE_INIT_COMMON_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/CpuPcieRp/Include/Library/CpuPcieRpLib.h b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/CpuPcieRp/Include/Library/CpuPcieRpLib.h
new file mode 100644
index 0000000000..ebb568193a
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/CpuPcieRp/Include/Library/CpuPcieRpLib.h
@@ -0,0 +1,47 @@
+/** @file
+ Header file for CpuPcieRpLib.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _CPU_PCIERP_LIB_H_
+#define _CPU_PCIERP_LIB_H_
+
+#include <Ppi/SiPolicy.h>
+#include <Library/HobLib.h>
+
+#pragma pack(1)
+
+typedef struct {
+ UINT8 Segment;
+ UINT8 Bus;
+ UINT8 Device;
+ UINT8 Function;
+ BOOLEAN Enable;
+} CPU_PCIE_RP_INFO;
+
+#pragma pack()
+
+/**
+ Determines whether PCIe link is active
+
+ @param[in] RpBase Root Port base address
+ @retval Link Active state
+**/
+BOOLEAN
+CpuPcieIsLinkActive (
+ UINT64 RpBase
+ );
+
+/**
+ Get max PCIe link speed supported by the root port.
+
+ @param[in] RpBase Root Port pci segment base address
+ @return Max link speed
+**/
+UINT32
+CpuPcieGetMaxLinkSpeed (
+ UINT64 RpBase
+ );
+
+#endif // _CPU_PCIERP_LIB_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/CpuPcieRp/IncludePrivate/Library/DxeCpuPcieRpLib.h b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/CpuPcieRp/IncludePrivate/Library/DxeCpuPcieRpLib.h
new file mode 100644
index 0000000000..593e1893bb
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/CpuPcieRp/IncludePrivate/Library/DxeCpuPcieRpLib.h
@@ -0,0 +1,18 @@
+/** @file
+ Header file for private DxeCpuPcieRpLib.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _DXE_PCIE_RP_INIT_LIB_H_
+#define _DXE_PCIE_RP_INIT_LIB_H_
+
+/**
+ Update CPU PCIE RP NVS AREA tables
+
+**/
+VOID
+UpdateCpuPcieNVS (
+ VOID
+ );
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/CpuPcieRp/Library/PeiDxeSmmCpuPcieInitCommonLib/CpuPcieInitCommon.c b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/CpuPcieRp/Library/PeiDxeSmmCpuPcieInitCommonLib/CpuPcieInitCommon.c
new file mode 100644
index 0000000000..28032e5b24
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/CpuPcieRp/Library/PeiDxeSmmCpuPcieInitCommonLib/CpuPcieInitCommon.c
@@ -0,0 +1,445 @@
+/** @file
+ common library for CPU PCIe INIT PEI/DXE/SMM modules
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Uefi/UefiBaseType.h>
+#include <Library/PcieHelperLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/IoLib.h>
+#include <Library/PciSegmentLib.h>
+#include <Library/CpuPcieRpLib.h>
+#include <Register/CpuPcieRegs.h>
+#include <Library/CpuPcieInitCommon.h>
+#include <Library/CpuRegbarAccessLib.h>
+
+/**
+ Print registers value
+
+ @param[in] PrintMmioBase Mmio base address
+ @param[in] PrintSize Number of registers
+ @param[in] OffsetFromBase Offset from mmio base address
+
+ @retval None
+**/
+VOID
+SaPrintRegisters (
+ IN UINTN PrintMmioBase,
+ IN UINT32 PrintSize,
+ IN UINT32 OffsetFromBase
+ )
+{
+ UINT32 Offset;
+ DEBUG ((DEBUG_VERBOSE, " 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F"));
+ for (Offset = 0; Offset < PrintSize; Offset++) {
+ if ((Offset % 16) == 0) {
+ DEBUG ((DEBUG_VERBOSE, "\n %04X: ", (Offset + OffsetFromBase) & 0xFFF0));
+ }
+ DEBUG ((DEBUG_VERBOSE, "%02X ", MmioRead8 (PrintMmioBase + Offset)));
+ }
+ DEBUG ((DEBUG_VERBOSE, "\n"));
+}
+
+/**
+ Print registers value
+
+ @param[in] PrintPciSegmentBase Pci segment base address
+ @param[in] PrintSize Number of registers
+ @param[in] OffsetFromBase Offset from mmio base address
+
+ @retval None
+**/
+VOID
+SaPrintPciRegisters (
+ IN UINT64 PrintPciSegmentBase,
+ IN UINT32 PrintSize,
+ IN UINT32 OffsetFromBase
+ )
+{
+ UINT32 Offset;
+ DEBUG ((DEBUG_VERBOSE, " 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F"));
+ for (Offset = 0; Offset < PrintSize; Offset++) {
+ if ((Offset % 16) == 0) {
+ DEBUG ((DEBUG_VERBOSE, "\n %04X: ", (Offset + OffsetFromBase) & 0xFFF0));
+ }
+ DEBUG ((DEBUG_VERBOSE, "%02X ", PciSegmentRead8 (PrintPciSegmentBase + Offset)));
+ }
+ DEBUG ((DEBUG_VERBOSE, "\n"));
+}
+
+//
+// 2LM: PegPcie APIs using the Sideband Access Mechanism
+//
+/**
+ Reads an 8-bit PCI configuration register.
+
+ Its a wrapper library function. This function uses side band access for PEG60 when 2LM mode is enabled.
+ Other calls to this function will be routed to core PciSegmentRead8 function.
+
+ @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register.
+
+ @return The 8-bit PCI configuration register specified by Address.
+**/
+UINT8
+EFIAPI
+PegPciSegmentRead8 (
+ IN UINT64 Address
+ )
+{
+ return PciSegmentRead8 (Address);
+}
+
+/**
+ Writes an 8-bit PCI configuration register.
+
+ Its a wrapper library function. This function uses side band access for PEG60 when 2LM mode is enabled.
+ Other calls to this function will be routed to core PciSegmentWrite8 function.
+
+ @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register.
+ @param Value The value to write.
+
+ @return The value written to the PCI configuration register.
+**/
+UINT8
+EFIAPI
+PegPciSegmentWrite8 (
+ IN UINT64 Address,
+ IN UINT8 Value
+ )
+{
+ return PciSegmentWrite8 (Address, Value);
+}
+
+/**
+ Reads a 16-bit PCI configuration register.
+
+ Its a wrapper library function. This function uses side band access for PEG60 when 2LM mode is enabled.
+ Other calls to this function will be routed to core PciSegmentRead16 function.
+
+ @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register.
+
+ @return The 16-bit PCI configuration register specified by Address.
+**/
+UINT16
+EFIAPI
+PegPciSegmentRead16 (
+ IN UINT64 Address
+ )
+{
+ return PciSegmentRead16 (Address);
+}
+
+/**
+ Writes a 16-bit PCI configuration register.
+
+ Its a wrapper library function. This function uses side band access for PEG60 when 2LM mode is enabled.
+ Other calls to this function will be routed to core PciSegmentWrite16 function.
+
+ @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register.
+ @param Value The value to write.
+
+ @return The parameter of Value.
+**/
+UINT16
+EFIAPI
+PegPciSegmentWrite16 (
+ IN UINT64 Address,
+ IN UINT16 Value
+ )
+{
+ return PciSegmentWrite16 (Address, Value);
+}
+
+/**
+ Reads a 32-bit PCI configuration register.
+
+ Its a wrapper library function. This function uses side band access for PEG60 when 2LM mode is enabled.
+ Other calls to this function will be routed to core PciSegmentRead32 function.
+
+ @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register.
+
+ @return The 32-bit PCI configuration register specified by Address.
+**/
+UINT32
+EFIAPI
+PegPciSegmentRead32 (
+ IN UINT64 Address
+ )
+{
+ return PciSegmentRead32 (Address);
+}
+
+/**
+ Writes a 32-bit PCI configuration register.
+
+ Its a wrapper library function. This function uses side band access for PEG60 when 2LM mode is enabled.
+ Other calls to this function will be routed to core PciSegmentWrite32 function.
+
+ @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register.
+ @param Value The value to write.
+
+ @return The parameter of Value.
+**/
+UINT32
+EFIAPI
+PegPciSegmentWrite32 (
+ IN UINT64 Address,
+ IN UINT32 Value
+ )
+{
+ return PciSegmentWrite32 (Address, Value);
+}
+
+/**
+ Performs a bitwise OR of a 16-bit PCI configuration register with a 16-bit value.
+
+ Its a wrapper library function. This function uses side band access for PEG60 when 2LM mode is enabled.
+ Other calls to this function will be routed to core PciSegmentOr16 function.
+
+ @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register.
+ @param OrData The value to OR with the PCI configuration register.
+
+ @return The value written to the PCI configuration register.
+**/
+UINT16
+EFIAPI
+PegPciSegmentOr16 (
+ IN UINT64 Address,
+ IN UINT16 OrData
+ )
+{
+ return PciSegmentOr16 (Address, OrData);
+}
+
+/**
+ Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit value.
+
+ Its a wrapper library function. This function uses side band access for PEG60 when 2LM mode is enabled.
+ Other calls to this function will be routed to core PciSegmentAnd32 function.
+
+ @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register.
+ @param AndData The value to AND with the PCI configuration register.
+
+ @return The value written to the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PegPciSegmentAnd16 (
+ IN UINT64 Address,
+ IN UINT16 AndData
+ )
+{
+ return PciSegmentAnd16 (Address, AndData);
+}
+
+/**
+ Performs a bitwise AND of a 8-bit PCI configuration register with a 8-bit value.
+
+ Its a wrapper library function. This function uses side band access for PEG60 when 2LM mode is enabled.
+ Other calls to this function will be routed to core PciSegmentAnd8 function.
+
+ @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register.
+ @param AndData The value to AND with the PCI configuration register.
+
+ @return The value written to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PegPciSegmentAnd8 (
+ IN UINT64 Address,
+ IN UINT8 AndData
+ )
+{
+ return PciSegmentAnd8 (Address, AndData);
+}
+
+/**
+ Performs a bitwise OR of a 32-bit PCI configuration register with a 32-bit value.
+
+ Its a wrapper library function. This function uses side band access for PEG60 when 2LM mode is enabled.
+ Other calls to this function will be routed to core PciSegmentOr32 function.
+
+ @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register.
+ @param OrData The value to OR with the PCI configuration register.
+
+ @return The value written to the PCI configuration register.
+**/
+UINT32
+EFIAPI
+PegPciSegmentOr32 (
+ IN UINT64 Address,
+ IN UINT32 OrData
+ )
+{
+ return PciSegmentOr32 (Address, OrData);
+}
+
+/**
+ Performs a bitwise OR of a 8-bit PCI configuration register with a 8-bit value.
+
+ Its a wrapper library function. This function uses side band access for PEG60 when 2LM mode is enabled.
+ Other calls to this function will be routed to core PciSegmentOr8 function.
+
+ @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register.
+ @param OrData The value to OR with the PCI configuration register.
+
+ @return The value written to the PCI configuration register.
+**/
+UINT8
+EFIAPI
+PegPciSegmentOr8 (
+ IN UINT64 Address,
+ IN UINT8 OrData
+ )
+{
+ return PciSegmentOr8 (Address, OrData);
+}
+
+/**
+ Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit value.
+
+ Its a wrapper library function. This function uses side band access for PEG60 when 2LM mode is enabled.
+ Other calls to this function will be routed to core PciSegmentAnd32 function.
+
+ @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register.
+ @param AndData The value to AND with the PCI configuration register.
+
+ @return The value written to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PegPciSegmentAnd32 (
+ IN UINT64 Address,
+ IN UINT32 AndData
+ )
+{
+ return PciSegmentAnd32 (Address, AndData);
+}
+
+/**
+ Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit value,
+ followed a bitwise OR with another 32-bit value.
+
+ Its a wrapper library function. This function uses side band access for PEG60 when 2LM mode is enabled.
+ Other calls to this function will be routed to core PciSegmentAndThenOr32 function.
+
+ @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register.
+ @param AndData The value to AND with the PCI configuration register.
+ @param OrData The value to OR with the PCI configuration register.
+
+ @return The value written to the PCI configuration register.
+**/
+UINT32
+EFIAPI
+PegPciSegmentAndThenOr32 (
+ IN UINT64 Address,
+ IN UINT32 AndData,
+ IN UINT32 OrData
+ )
+{
+ return PciSegmentAndThenOr32 (Address, AndData, OrData);
+}
+
+
+/**
+ Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit value,
+ followed a bitwise OR with another 16-bit value.
+
+ Its a wrapper library function. This function uses side band access for PEG60 when 2LM mode is enabled.
+ Other calls to this function will be routed to core PciSegmentAndThenOr16 function.
+
+ @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register.
+ @param AndData The value to AND with the PCI configuration register.
+ @param OrData The value to OR with the PCI configuration register.
+
+ @return The value written to the PCI configuration register.
+**/
+UINT16
+EFIAPI
+PegPciSegmentAndThenOr16 (
+ IN UINT64 Address,
+ IN UINT16 AndData,
+ IN UINT16 OrData
+ )
+{
+ return PciSegmentAndThenOr16 (Address, AndData, OrData);
+}
+
+
+/**
+ Performs a bitwise AND of a 8-bit PCI configuration register with a 8-bit value,
+ followed a bitwise OR with another 8-bit value.
+
+ Its a wrapper library function. This function uses side band access for PEG60 when 2LM mode is enabled.
+ Other calls to this function will be routed to core PciSegmentAndThenOr8 function.
+
+ @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register.
+ @param AndData The value to AND with the PCI configuration register.
+ @param OrData The value to OR with the PCI configuration register.
+
+ @return The value written to the PCI configuration register.
+**/
+UINT8
+EFIAPI
+PegPciSegmentAndThenOr8 (
+ IN UINT64 Address,
+ IN UINT8 AndData,
+ IN UINT8 OrData
+ )
+{
+ return PciSegmentAndThenOr8 (Address, AndData, OrData);
+}
+
+
+/**
+ Find the Offset to a Capabilities ID
+ @param[in] Segment Pci Segment Number
+ @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
+PegPcieFindCapId (
+ IN UINT8 Segment,
+ IN UINT8 Bus,
+ IN UINT8 Device,
+ IN UINT8 Function,
+ IN UINT8 CapId
+ )
+{
+ return PcieFindCapId (Segment, Bus, Device, Function, CapId);
+}
+
+
+/**
+ Search and return the offset of desired Pci Express extended Capability ID
+ @param[in] Segment Pci Segment Number
+ @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
+PegPcieFindExtendedCapId (
+ IN UINT8 Segment,
+ IN UINT8 Bus,
+ IN UINT8 Device,
+ IN UINT8 Function,
+ IN UINT16 CapId
+ )
+{
+ return PcieFindExtendedCapId (Segment, Bus, Device, Function, CapId);
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/CpuPcieRp/Library/PeiDxeSmmCpuPcieInitCommonLib/PeiDxeSmmCpuPcieInitCommonLib.inf b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/CpuPcieRp/Library/PeiDxeSmmCpuPcieInitCommonLib/PeiDxeSmmCpuPcieInitCommonLib.inf
new file mode 100644
index 0000000000..2ad30ab7c9
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/CpuPcieRp/Library/PeiDxeSmmCpuPcieInitCommonLib/PeiDxeSmmCpuPcieInitCommonLib.inf
@@ -0,0 +1,33 @@
+## @file
+# Component description file for the CpuPcieInitCommonLib
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010017
+ BASE_NAME = PeiDxeSmmCpuPcieInitCommonLib
+ FILE_GUID = 68992CB0-A3A5-4f73-9370-93A3559F84C8
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = CpuPcieInitCommonLib
+
+[Sources]
+ CpuPcieInitCommon.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ TigerlakeSiliconPkg/SiPkg.dec
+
+[LibraryClasses]
+ IoLib
+ DebugLib
+ PciSegmentLib
+ CpuPcieRpLib
+ CpuRegbarAccessLib
+ BasePcieHelperLib
+
+[Pcd]
+ gSiPkgTokenSpaceGuid.PcdCpuPcieEnable ## CONSUMES
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/CpuPcieRp/Library/PeiDxeSmmCpuPcieRpLib/CpuPcieRpLib.c b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/CpuPcieRp/Library/PeiDxeSmmCpuPcieRpLib/CpuPcieRpLib.c
new file mode 100644
index 0000000000..02cd482b55
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/CpuPcieRp/Library/PeiDxeSmmCpuPcieRpLib/CpuPcieRpLib.c
@@ -0,0 +1,48 @@
+/** @file
+ CPU PCIe root port library.
+ All function in this library is available for PEI, DXE, and SMM,
+ But do not support UEFI RUNTIME environment call.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <PcieRegs.h>
+#include <Register/CpuPcieRegs.h>
+#include "CpuPcieInfo.h"
+#include <Library/CpuPcieInitCommon.h>
+#include <Library/PciLib.h>
+#include <IndustryStandard/Pci22.h>
+
+/**
+ Determines whether PCIe link is active
+
+ @param[in] RpBase Root Port base address
+ @retval Link Active state
+**/
+BOOLEAN
+CpuPcieIsLinkActive (
+ UINT64 RpBase
+ )
+{
+ return !! (PegPciSegmentRead16 (RpBase + R_PCIE_LSTS) & B_PCIE_LSTS_LA);
+}
+
+/**
+ Get max PCIe link speed supported by the root port.
+
+ @param[in] RpBase Root Port base address
+ @return Max link speed
+**/
+UINT32
+CpuPcieGetMaxLinkSpeed (
+ UINT64 RpBase
+ )
+{
+ return PegPciSegmentRead32 (RpBase + R_PCIE_LCAP) & B_PCIE_LCAP_MLS;
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/CpuPcieRp/Library/PeiDxeSmmCpuPcieRpLib/PeiDxeSmmCpuPcieRpLib.inf b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/CpuPcieRp/Library/PeiDxeSmmCpuPcieRpLib/PeiDxeSmmCpuPcieRpLib.inf
new file mode 100644
index 0000000000..cea8bcbecd
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/CpuPcieRp/Library/PeiDxeSmmCpuPcieRpLib/PeiDxeSmmCpuPcieRpLib.inf
@@ -0,0 +1,32 @@
+## @file
+# CPU PCIE root port Library.
+#
+# All function in this library is available for PEI, DXE, and SMM,
+# But do not support UEFI RUNTIME environment call.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiDxeSmmCpuPcieRpLib
+FILE_GUID = 00199A03-41F4-43c7-B6D5-5A3AA1EE78D0
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = CpuPcieRpLib
+
+[LibraryClasses]
+BaseLib
+IoLib
+DebugLib
+PciLib
+
+[Packages]
+MdePkg/MdePkg.dec
+TigerlakeSiliconPkg/SiPkg.dec
+
+[Sources]
+CpuPcieRpLib.c
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/CpuPcieRp/LibraryPrivate/DxeCpuPcieRpLib/DxeCpuPcieRpLib.c b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/CpuPcieRp/LibraryPrivate/DxeCpuPcieRpLib/DxeCpuPcieRpLib.c
new file mode 100644
index 0000000000..48ef8165de
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/CpuPcieRp/LibraryPrivate/DxeCpuPcieRpLib/DxeCpuPcieRpLib.c
@@ -0,0 +1,62 @@
+/** @file
+ The DXE CPU PCIE RP Library Implements After Memory PEIM
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include <Base.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Ppi/SiPolicy.h>
+#include <Library/HobLib.h>
+#include <Library/PciSegmentLib.h>
+#include <IndustryStandard/Pci22.h>
+#include <Protocol/SaPolicy.h>
+#include <Protocol/SaNvsArea.h>
+#include <Library/PcdLib.h>
+#include <Library/PciExpressHelpersLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <ConfigBlock/PcieDxeConfig.h>
+#include <Register/SaRegsHostBridge.h>
+
+/**
+Update CPU PCIE RP NVS AREA tables
+
+**/
+VOID
+UpdateCpuPcieNVS (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ PCIE_DXE_CONFIG *PcieDxeConfig;
+ SA_POLICY_PROTOCOL *SaPolicy;
+ SYSTEM_AGENT_NVS_AREA_PROTOCOL *SaNvsAreaProtocol;
+
+ DEBUG ((DEBUG_INFO, "Update Cpu Pcie NVS Area.\n"));
+
+ Status = gBS->LocateProtocol (&gSaPolicyProtocolGuid, NULL, (VOID **) &SaPolicy);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = GetConfigBlock ((VOID *)SaPolicy, &gPcieDxeConfigGuid, (VOID *)&PcieDxeConfig);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = gBS->LocateProtocol (&gSaNvsAreaProtocolGuid, NULL, (VOID **) &SaNvsAreaProtocol);
+ if (Status != EFI_SUCCESS) {
+ DEBUG ((DEBUG_ERROR, "Locate SA NVS Area failed.\n"));
+ return;
+ }
+
+ SaNvsAreaProtocol->Area->Peg0LtrEnable = PcieDxeConfig->PegPwrOpt[0].LtrEnable;
+ SaNvsAreaProtocol->Area->Peg0ObffEnable = PcieDxeConfig->PegPwrOpt[0].ObffEnable;
+ SaNvsAreaProtocol->Area->Peg1LtrEnable = PcieDxeConfig->PegPwrOpt[1].LtrEnable;
+ SaNvsAreaProtocol->Area->Peg1ObffEnable = PcieDxeConfig->PegPwrOpt[1].ObffEnable;
+ SaNvsAreaProtocol->Area->Peg2LtrEnable = PcieDxeConfig->PegPwrOpt[2].LtrEnable;
+ SaNvsAreaProtocol->Area->Peg2ObffEnable = PcieDxeConfig->PegPwrOpt[2].ObffEnable;
+ SaNvsAreaProtocol->Area->Peg3LtrEnable = PcieDxeConfig->PegPwrOpt[3].LtrEnable;
+ SaNvsAreaProtocol->Area->Peg3ObffEnable = PcieDxeConfig->PegPwrOpt[3].ObffEnable;
+ SaNvsAreaProtocol->Area->PegLtrMaxSnoopLatency = V_SA_LTR_MAX_SNOOP_LATENCY_VALUE;
+ SaNvsAreaProtocol->Area->PegLtrMaxNoSnoopLatency = V_SA_LTR_MAX_NON_SNOOP_LATENCY_VALUE;
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/CpuPcieRp/LibraryPrivate/DxeCpuPcieRpLib/DxeCpuPcieRpLib.inf b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/CpuPcieRp/LibraryPrivate/DxeCpuPcieRpLib/DxeCpuPcieRpLib.inf
new file mode 100644
index 0000000000..dc9b893be3
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/CpuPcieRp/LibraryPrivate/DxeCpuPcieRpLib/DxeCpuPcieRpLib.inf
@@ -0,0 +1,40 @@
+## @file
+# The DXE CPU PCIE RP Library Implements After Memory PEIM
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = DxeCpuPcieRpLib
+FILE_GUID = D563A22E-6A01-4EF7-84D1-78B6717E3402
+VERSION_STRING = 1.0
+MODULE_TYPE = DXE_DRIVER
+UEFI_SPECIFICATION_VERSION = 2.00
+LIBRARY_CLASS = DxeCpuPcieRpLib
+
+[LibraryClasses]
+IoLib
+BaseLib
+DebugLib
+BaseMemoryLib
+UefiBootServicesTableLib
+UefiLib
+HobLib
+
+[Packages]
+MdePkg/MdePkg.dec
+TigerlakeSiliconPkg/SiPkg.dec
+
+[Sources]
+DxeCpuPcieRpLib.c
+
+[Guids]
+gPcieDxeConfigGuid
+
+[Protocols]
+gSaPolicyProtocolGuid ## CONSUMES
+gSaNvsAreaProtocolGuid ## CONSUMES
--
2.24.0.windows.2
^ permalink raw reply related [flat|nested] 42+ messages in thread
* [Patch V3 15/40] TigerlakeSiliconPkg/IpBlock: Add Espi component
2021-02-05 7:40 [Patch V3 01/40] TigerlakeSiliconPkg: Add package and Include/ConfigBlock headers Heng Luo
` (12 preceding siblings ...)
2021-02-05 7:40 ` [Patch V3 14/40] TigerlakeSiliconPkg/IpBlock: Add CpuPcieRp component Heng Luo
@ 2021-02-05 7:40 ` Heng Luo
2021-02-05 7:40 ` [Patch V3 16/40] TigerlakeSiliconPkg/IpBlock: Add Gbe component Heng Luo
` (24 subsequent siblings)
38 siblings, 0 replies; 42+ messages in thread
From: Heng Luo @ 2021-02-05 7:40 UTC (permalink / raw)
To: devel; +Cc: Sai Chaganty, Nate DeSimone
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3171
Adds the following files:
* IpBlock/Espi/Library
Cc: Sai Chaganty <rangasai.v.chaganty@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Signed-off-by: Heng Luo <heng.luo@intel.com>
---
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Espi/Library/PeiDxeSmmEspiLib/EspiLib.c | 469 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Espi/Library/PeiDxeSmmEspiLib/PeiDxeSmmEspiLib.inf | 38 ++++++++++++++++++++++++++++++++++++++
2 files changed, 507 insertions(+)
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Espi/Library/PeiDxeSmmEspiLib/EspiLib.c b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Espi/Library/PeiDxeSmmEspiLib/EspiLib.c
new file mode 100644
index 0000000000..2d1928ce18
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Espi/Library/PeiDxeSmmEspiLib/EspiLib.c
@@ -0,0 +1,469 @@
+/** @file
+ This file contains routines for eSPI
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/EspiLib.h>
+#include <Library/PchPcrLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/TimerLib.h>
+#include <PchLimits.h>
+#include <Register/PchPcrRegs.h>
+#include <Register/PchRegsLpc.h>
+
+#define CHANNEL_RESET_TIMEOUT 100 ///< Channel reset timeout in us after which to report error
+#define SLAVE_CHANNELS_MAX 7 ///< Max number of channels
+
+//
+// eSPI Slave registers
+//
+#define R_ESPI_SLAVE_GENCAP 0x08 ///< General Capabilities and Configurations
+#define B_ESPI_SLAVE_GENCAP_SUPPCHAN 0xFF ///< Channels supported bit mask
+#define R_ESPI_SLAVE_CHACAP_BASE 0x10 ///< Base address from which channel Cap and Conf registers start on slave
+#define S_ESPI_SLAVE_CHACAP_OFFSET 0x10 ///< Offset for each channel from base
+#define B_ESPI_SLAVE_CHACAP_CHEN BIT0 ///< Slave Channel enable bit
+#define B_ESPI_SLAVE_CHACAP_CHRDY BIT1 ///< Slave Channel ready bit
+
+/**
+ Checks if second slave capability is enabled
+
+ @retval TRUE There's second slave
+ @retval FALSE There's no second slave
+**/
+BOOLEAN
+IsEspiSecondSlaveSupported (
+ VOID
+ )
+{
+ return FALSE;
+}
+
+/**
+ Checks in slave General Capabilities register if it supports channel with requested number
+
+ @param[in] SlaveId Id of slave to check
+ @param[in] ChannelNumber Number of channel of which to check
+
+ @retval TRUE Channel with requested number is supported by slave device
+ @retval FALSE Channel with requested number is not supported by slave device
+**/
+BOOLEAN
+IsEspiSlaveChannelSupported (
+ UINT8 SlaveId,
+ UINT8 ChannelNumber
+ )
+{
+ UINT32 Data32;
+ UINT8 SupportedChannels;
+
+ PchEspiSlaveGetConfig (SlaveId, R_ESPI_SLAVE_GENCAP, &Data32);
+ SupportedChannels = (UINT8) (Data32 & B_ESPI_SLAVE_GENCAP_SUPPCHAN);
+
+ DEBUG ((DEBUG_INFO, "Slave %d supported channels 0x%4X\n", SlaveId, SupportedChannels));
+
+ if (ChannelNumber > SLAVE_CHANNELS_MAX || !(SupportedChannels & (BIT0 << ChannelNumber))) {
+ // Incorrect channel number was specified. Either exceeded max or Slave doesn't support that channel.
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/**
+ Is eSPI enabled in strap.
+
+ @retval TRUE Espi is enabled in strap
+ @retval FALSE Espi is disabled in strap
+**/
+BOOLEAN
+IsEspiEnabled (
+ VOID
+ )
+{
+ return (PchPcrRead32 (PID_ESPISPI, R_ESPI_PCR_CFG_VAL) & B_ESPI_PCR_CFG_VAL_ESPI_EN) != 0;
+}
+
+/**
+ eSPI helper function to clear slave configuration register status
+
+ @retval EFI_SUCCESS Write to private config space succeed
+ @retval others Read / Write failed
+**/
+STATIC
+VOID
+EspiClearScrs (
+ VOID
+ )
+{
+ PchPcrAndThenOr32 (
+ PID_ESPISPI,
+ R_ESPI_PCR_SLV_CFG_REG_CTL,
+ (UINT32) ~0,
+ B_ESPI_PCR_SLV_CFG_REG_CTL_SCRS
+ );
+}
+
+/**
+ eSPI helper function to poll slave configuration register enable for 0
+ and to check for slave configuration register status
+
+ @retval EFI_SUCCESS Enable bit is zero and no error in status bits
+ @retval EFI_DEVICE_ERROR Error in SCRS
+ @retval others Read / Write to private config space failed
+**/
+STATIC
+EFI_STATUS
+EspiPollScreAndCheckScrs (
+ VOID
+ )
+{
+ UINT32 ScrStat;
+
+ do {
+ ScrStat = PchPcrRead32 (PID_ESPISPI, R_ESPI_PCR_SLV_CFG_REG_CTL);
+ } while ((ScrStat & B_ESPI_PCR_SLV_CFG_REG_CTL_SCRE) != 0);
+
+ ScrStat = (ScrStat & B_ESPI_PCR_SLV_CFG_REG_CTL_SCRS) >> N_ESPI_PCR_SLV_CFG_REG_CTL_SCRS;
+ if (ScrStat != V_ESPI_PCR_SLV_CFG_REG_CTL_SCRS_NOERR) {
+ DEBUG ((DEBUG_ERROR, "eSPI slave config register status (error) is %x \n", ScrStat));
+ return EFI_DEVICE_ERROR;
+ }
+ return EFI_SUCCESS;
+}
+
+typedef enum {
+ EspiSlaveOperationConfigRead,
+ EspiSlaveOperationConfigWrite,
+ EspiSlaveOperationStatusRead,
+ EspiSlaveOperationInBandReset
+} ESPI_SLAVE_OPERATION;
+
+/**
+ Helper library to do all the operations regards to eSPI slave
+
+ @param[in] SlaveId eSPI Slave ID
+ @param[in] SlaveAddress Slave address to be put in R_ESPI_PCR_SLV_CFG_REG_CTL[11:0]
+ @param[in] SlaveOperation Based on ESPI_SLAVE_OPERATION
+ @param[in,out] Data
+
+ @retval EFI_SUCCESS Operation succeed
+ @retval EFI_INVALID_PARAMETER Slave ID is not supported or SlaveId 1 is used in PCH_LP
+ @retval EFI_INVALID_PARAMETER Slave configuration register address exceed maximum allowed
+ @retval EFI_INVALID_PARAMETER Slave configuration register address is not DWord aligned
+ @retval EFI_ACCESS_DENIED eSPI Slave write to address range 0 to 0x7FF has been locked
+ @retval EFI_DEVICE_ERROR Error in SCRS during polling stage of operation
+**/
+STATIC
+EFI_STATUS
+EspiSlaveOperationHelper (
+ IN UINT32 SlaveId,
+ IN UINT32 SlaveAddress,
+ IN ESPI_SLAVE_OPERATION SlaveOperation,
+ IN OUT UINT32 *Data
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Data32;
+
+ //
+ // Check the SlaveId is 0 or 1
+ //
+ if (SlaveId >= PCH_MAX_ESPI_SLAVES) {
+ DEBUG ((DEBUG_ERROR, "eSPI Slave ID of %d or more is not accepted \n", PCH_MAX_ESPI_SLAVES));
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Check if SlaveId 1 is used, it is not a PCH_LP
+ //
+ if (SlaveId == 1) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Check the address is not more then 0xFFF
+ //
+ if (SlaveAddress > B_ESPI_PCR_SLV_CFG_REG_CTL_SCRA) {
+ DEBUG ((DEBUG_ERROR, "eSPI Slave address must be less than 0x%x \n", (B_ESPI_PCR_SLV_CFG_REG_CTL_SCRA + 1)));
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Check the address is DWord aligned
+ //
+ if ((SlaveAddress & 0x3) != 0) {
+ DEBUG ((DEBUG_ERROR, "eSPI Slave address must be DWord aligned \n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check if write is allowed
+ //
+ if ((SlaveOperation == EspiSlaveOperationConfigWrite) &&
+ (SlaveAddress <= 0x7FF)) {
+
+ //
+ // If the SLCRR is not set in corresponding slave, we will check the lock bit
+ //
+ Data32 = PchPcrRead32 (PID_ESPISPI, (UINT16) (R_ESPI_PCR_LNKERR_SLV0 + (SlaveId * S_ESPI_PCR_LNKERR_SLV0)));
+ if ((Data32 & B_ESPI_PCR_LNKERR_SLV0_SLCRR) == 0) {
+
+ Data32 = PchPcrRead32 (PID_ESPISPI, (UINT16) R_ESPI_PCR_SLV_CFG_REG_CTL);
+ if ((Data32 & B_ESPI_PCR_SLV_CFG_REG_CTL_SBLCL) != 0) {
+ DEBUG ((DEBUG_ERROR, "eSPI Slave write to address range 0 to 0x7FF has been locked \n"));
+ return EFI_ACCESS_DENIED;
+ }
+ }
+ }
+
+ //
+ // Input check done, now go through all the processes
+ //
+ EspiClearScrs ();
+
+ if (SlaveOperation == EspiSlaveOperationConfigWrite) {
+ PchPcrWrite32 (
+ PID_ESPISPI,
+ (UINT16) R_ESPI_PCR_SLV_CFG_REG_DATA,
+ *Data
+ );
+ }
+
+ PchPcrAndThenOr32 (
+ PID_ESPISPI,
+ (UINT16) R_ESPI_PCR_SLV_CFG_REG_CTL,
+ (UINT32) ~(B_ESPI_PCR_SLV_CFG_REG_CTL_SID | B_ESPI_PCR_SLV_CFG_REG_CTL_SCRT | B_ESPI_PCR_SLV_CFG_REG_CTL_SCRA),
+ (B_ESPI_PCR_SLV_CFG_REG_CTL_SCRE |
+ (SlaveId << N_ESPI_PCR_SLV_CFG_REG_CTL_SID) |
+ (((UINT32) SlaveOperation) << N_ESPI_PCR_SLV_CFG_REG_CTL_SCRT) |
+ SlaveAddress
+ )
+ );
+
+ Status = EspiPollScreAndCheckScrs ();
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if ((SlaveOperation == EspiSlaveOperationConfigRead) || (SlaveOperation == EspiSlaveOperationStatusRead)) {
+ Data32 = PchPcrRead32 (
+ PID_ESPISPI,
+ (UINT16) R_ESPI_PCR_SLV_CFG_REG_DATA
+ );
+ if (SlaveOperation == EspiSlaveOperationStatusRead) {
+ *Data = Data32 & 0xFFFF;
+ } else {
+ *Data = Data32;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Get configuration from eSPI slave
+
+ @param[in] SlaveId eSPI slave ID
+ @param[in] SlaveAddress Slave Configuration Register Address
+ @param[out] OutData Configuration data read
+
+ @retval EFI_SUCCESS Operation succeed
+ @retval EFI_INVALID_PARAMETER Slave ID is not supported
+ @retval EFI_INVALID_PARAMETER Slave ID is not supported or SlaveId 1 is used in PCH_LP
+ @retval EFI_INVALID_PARAMETER Slave configuration register address exceed maximum allowed
+ @retval EFI_INVALID_PARAMETER Slave configuration register address is not DWord aligned
+ @retval EFI_DEVICE_ERROR Error in SCRS during polling stage of operation
+**/
+EFI_STATUS
+PchEspiSlaveGetConfig (
+ IN UINT32 SlaveId,
+ IN UINT32 SlaveAddress,
+ OUT UINT32 *OutData
+ )
+{
+ //
+ // 1. Clear status from previous transaction by writing 111b to status in SCRS, PCR[eSPI] + 4000h [30:28]
+ // 2. Program SLV_CFG_REG_CTL with the right value (Bit[31]=01, Bit [20:19]=<SlvID>, Bit [17:16] = 00b, Bit[11:0] = <addr_xxx>.
+ // 3. Poll the SCRE (PCR[eSPI] +4000h [31]) to be set back to 0
+ // 4. Check the transaction status in SCRS (bits [30:28])
+ // 5. Read SLV_CFG_REG_DATA.
+ //
+ return EspiSlaveOperationHelper (SlaveId, SlaveAddress, EspiSlaveOperationConfigRead, OutData);
+}
+
+/**
+ Set eSPI slave configuration
+
+ Note: A Set_Configuration must always be followed by a Get_Configuration in order to ensure
+ that the internal state of the eSPI-MC is consistent with the Slave's register settings.
+
+ @param[in] SlaveId eSPI slave ID
+ @param[in] SlaveAddress Slave Configuration Register Address
+ @param[in] InData Configuration data to write
+
+ @retval EFI_SUCCESS Operation succeed
+ @retval EFI_INVALID_PARAMETER Slave ID is not supported or SlaveId 1 is used in PCH_LP
+ @retval EFI_INVALID_PARAMETER Slave configuration register address exceed maximum allowed
+ @retval EFI_INVALID_PARAMETER Slave configuration register address is not DWord aligned
+ @retval EFI_ACCESS_DENIED eSPI Slave write to address range 0 to 0x7FF has been locked
+ @retval EFI_DEVICE_ERROR Error in SCRS during polling stage of operation
+**/
+EFI_STATUS
+PchEspiSlaveSetConfig (
+ IN UINT32 SlaveId,
+ IN UINT32 SlaveAddress,
+ IN UINT32 InData
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Data32;
+
+ //
+ // 1. Clear status from previous transaction by writing 111b to status in SCRS, PCR[eSPI] + 4000h [30:28]
+ // 2. Program SLV_CFG_REG_DATA with the write value.
+ // 3. Program SLV_CFG_REG_CTL with the right value (Bit[31]=01, Bit [20:19]=<SlvID>, Bit [17:16] = 01b, Bit[11:0] = <addr_xxx>.
+ // 4. Poll the SCRE (PCR[eSPI] +4000h [31]) to be set back to 0
+ // 5. Check the transaction status in SCRS (bits [30:28])
+ //
+ Status = EspiSlaveOperationHelper (SlaveId, SlaveAddress, EspiSlaveOperationConfigWrite, &InData);
+ PchEspiSlaveGetConfig (SlaveId, SlaveAddress, &Data32);
+ return Status;
+}
+
+/**
+ Get status from eSPI slave
+
+ @param[in] SlaveId eSPI slave ID
+ @param[out] OutData Configuration data read
+
+ @retval EFI_SUCCESS Operation succeed
+ @retval EFI_INVALID_PARAMETER Slave ID is not supported or SlaveId 1 is used in PCH_LP
+ @retval EFI_DEVICE_ERROR Error in SCRS during polling stage of operation
+**/
+EFI_STATUS
+PchEspiSlaveGetStatus (
+ IN UINT32 SlaveId,
+ OUT UINT16 *OutData
+ )
+{
+ EFI_STATUS Status;
+ UINT32 TempOutData;
+
+ TempOutData = 0;
+
+ //
+ // 1. Clear status from previous transaction by writing 111b to status in SCRS, PCR[eSPI] + 4000h [30:28]
+ // 2. Program SLV_CFG_REG_CTL with the right value (Bit[31]=01, Bit [20:19]=<SlvID>, Bit [17:16] = 10b, Bit[11:0] = <addr_xxx>.
+ // 3. Poll the SCRE (PCR[eSPI] +4000h [31]) to be set back to 0
+ // 4. Check the transaction status in SCRS (bits [30:28])
+ // 5. Read SLV_CFG_REG_DATA [15:0].
+ //
+ Status = EspiSlaveOperationHelper (SlaveId, 0, EspiSlaveOperationStatusRead, &TempOutData);
+ *OutData = (UINT16) TempOutData;
+
+ return Status;
+}
+
+/**
+ eSPI slave in-band reset
+
+ @param[in] SlaveId eSPI slave ID
+
+ @retval EFI_SUCCESS Operation succeed
+ @retval EFI_INVALID_PARAMETER Slave ID is not supported or SlaveId 1 is used in PCH_LP
+ @retval EFI_DEVICE_ERROR Error in SCRS during polling stage of operation
+**/
+EFI_STATUS
+PchEspiSlaveInBandReset (
+ IN UINT32 SlaveId
+ )
+{
+ //
+ // 1. Clear status from previous transaction by writing 111b to status in SCRS, PCR[eSPI] + 4000h [30:28]
+ // 2. Program SLV_CFG_REG_CTL with the right value (Bit[31]=01, Bit [20:19]=<SlvID>, Bit [17:16] = 11b).
+ // 3. Poll the SCRE (PCR[eSPI] +4000h [31]) to be set back to 0
+ // 4. Check the transaction status in SCRS (bits [30:28])
+ //
+ return EspiSlaveOperationHelper (SlaveId, 0, EspiSlaveOperationInBandReset, NULL);
+}
+
+/**
+ eSPI Slave channel reset helper function
+
+ @param[in] SlaveId eSPI slave ID
+ @param[in] ChannelNumber Number of channel to reset
+
+ @retval EFI_SUCCESS Operation succeeded
+ @retval EFI_UNSUPPORTED Slave doesn't support that channel or invalid number specified
+ @retval EFI_TIMEOUT Operation has timeouted
+**/
+EFI_STATUS
+PchEspiSlaveChannelReset (
+ IN UINT8 SlaveId,
+ IN UINT8 ChannelNumber
+ )
+{
+ UINT8 Timeout;
+ UINT32 Data32;
+ UINT32 SlaveChannelAddress;
+ BOOLEAN SlaveBmeSet;
+
+ DEBUG ((DEBUG_INFO, "eSPI slave %d channel %d reset\n", SlaveId, ChannelNumber));
+
+ Timeout = CHANNEL_RESET_TIMEOUT;
+ SlaveBmeSet = FALSE;
+
+ if (!IsEspiSlaveChannelSupported (SlaveId, ChannelNumber)) {
+ // Incorrect channel number was specified. Either exceeded max or Slave doesn't support that channel.
+ DEBUG ((DEBUG_ERROR, "Channel %d is not valid channel number for slave %d!\n", ChannelNumber, SlaveId));
+ return EFI_UNSUPPORTED;
+ }
+
+ // Calculating slave channel address
+ SlaveChannelAddress = R_ESPI_SLAVE_CHACAP_BASE + (S_ESPI_SLAVE_CHACAP_OFFSET * ChannelNumber);
+
+ // If we're resetting Peripheral Channel then we need to disable Bus Mastering first and reenable after reset
+ if (ChannelNumber == 0) {
+ PchEspiSlaveGetConfig (SlaveId, SlaveChannelAddress, &Data32);
+ if ((Data32 & B_ESPI_SLAVE_BME) != 0) {
+ Data32 &= ~(B_ESPI_SLAVE_BME);
+ PchEspiSlaveSetConfig (SlaveId, SlaveChannelAddress, Data32);
+ SlaveBmeSet = TRUE;
+ }
+ }
+
+ // Disable channel
+ PchEspiSlaveGetConfig (SlaveId, SlaveChannelAddress, &Data32);
+ Data32 &= ~(B_ESPI_SLAVE_CHACAP_CHEN);
+ PchEspiSlaveSetConfig (SlaveId, SlaveChannelAddress, Data32);
+
+ // Enable channel
+ PchEspiSlaveGetConfig (SlaveId, SlaveChannelAddress, &Data32);
+ Data32 |= B_ESPI_SLAVE_CHACAP_CHEN;
+ PchEspiSlaveSetConfig (SlaveId, SlaveChannelAddress, Data32);
+
+ DEBUG ((DEBUG_INFO, "Waiting for Channel Ready bit\n"));
+ // Wait until channel is ready by polling Channel Ready bit
+ while (((Data32 & B_ESPI_SLAVE_CHACAP_CHRDY) == 0) && (Timeout > 0)) {
+ PchEspiSlaveGetConfig (SlaveId, SlaveChannelAddress, &Data32);
+ MicroSecondDelay (1);
+ --Timeout;
+ }
+
+ if (Timeout == 0) {
+ // The waiting for channel to be ready has timed out
+ DEBUG ((DEBUG_ERROR, "The operation of channel %d reset for slave %d has timed out!\n", ChannelNumber, SlaveId));
+ return EFI_TIMEOUT;
+ }
+
+ if (ChannelNumber == 0 && SlaveBmeSet) {
+ PchEspiSlaveGetConfig (SlaveId, SlaveChannelAddress, &Data32);
+ Data32 |= B_ESPI_SLAVE_BME;
+ PchEspiSlaveSetConfig (SlaveId, SlaveChannelAddress, Data32);
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Espi/Library/PeiDxeSmmEspiLib/PeiDxeSmmEspiLib.inf b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Espi/Library/PeiDxeSmmEspiLib/PeiDxeSmmEspiLib.inf
new file mode 100644
index 0000000000..440051432f
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Espi/Library/PeiDxeSmmEspiLib/PeiDxeSmmEspiLib.inf
@@ -0,0 +1,38 @@
+## @file
+# Component description file for the PeiDxeSmmPchEspiLib
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiDxeSmmEspiLib
+FILE_GUID = 7F25F990-7989-4413-B414-1EDE557E9389
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = EspiLib
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+
+
+[LibraryClasses]
+BaseLib
+IoLib
+DebugLib
+PchPcrLib
+TimerLib
+
+[Packages]
+MdePkg/MdePkg.dec
+TigerlakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+EspiLib.c
--
2.24.0.windows.2
^ permalink raw reply related [flat|nested] 42+ messages in thread
* [Patch V3 16/40] TigerlakeSiliconPkg/IpBlock: Add Gbe component
2021-02-05 7:40 [Patch V3 01/40] TigerlakeSiliconPkg: Add package and Include/ConfigBlock headers Heng Luo
` (13 preceding siblings ...)
2021-02-05 7:40 ` [Patch V3 15/40] TigerlakeSiliconPkg/IpBlock: Add Espi component Heng Luo
@ 2021-02-05 7:40 ` Heng Luo
2021-02-05 7:40 ` [Patch V3 17/40] TigerlakeSiliconPkg/IpBlock: Add Gpio component Heng Luo
` (23 subsequent siblings)
38 siblings, 0 replies; 42+ messages in thread
From: Heng Luo @ 2021-02-05 7:40 UTC (permalink / raw)
To: devel; +Cc: Sai Chaganty, Nate DeSimone
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3171
Adds the following files:
* IpBlock/Gbe/IncludePrivate
* IpBlock/Gbe/Library
* IpBlock/Gbe/LibraryPrivate
Cc: Sai Chaganty <rangasai.v.chaganty@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Signed-off-by: Heng Luo <heng.luo@intel.com>
---
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gbe/IncludePrivate/Library/GbeMdiLib.h | 324 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gbe/IncludePrivate/Register/GbeRegs.h | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gbe/Library/PeiDxeSmmGbeLib/GbeLib.c | 121 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gbe/Library/PeiDxeSmmGbeLib/PeiDxeSmmGbeLib.inf | 43 +++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gbe/LibraryPrivate/PeiDxeSmmGbeMdiLib/GbeMdiLib.c | 388 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gbe/LibraryPrivate/PeiDxeSmmGbeMdiLib/PeiDxeSmmGbeMdiLib.inf | 34 ++++++++++++++++++++++++++++++++++
6 files changed, 978 insertions(+)
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gbe/IncludePrivate/Library/GbeMdiLib.h b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gbe/IncludePrivate/Library/GbeMdiLib.h
new file mode 100644
index 0000000000..b8274ed3dc
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gbe/IncludePrivate/Library/GbeMdiLib.h
@@ -0,0 +1,324 @@
+/** @file
+ Header file for GbeMdiLib.
+
+ Conventions:
+
+ - Prefixes:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register sizes
+ Definitions beginning with "N_" are the bit position
+ - In general, PCH registers are denoted by "_PCH_" in register names
+ - Registers / bits that are different between PCH generations are denoted by
+ "_PCH_[generation_name]_" in register/bit names.
+ - Registers / bits that are specific to PCH-H denoted by "_H_" in register/bit names.
+ Registers / bits that are specific to PCH-LP denoted by "_LP_" in register/bit names.
+ e.g., "_PCH_LP_"
+ Registers / bits names without or _LP_ apply for LP.
+ - Registers / bits that are different between SKUs are denoted by "_[SKU_name]"
+ at the end of the register/bit names
+ - Registers / bits of new devices introduced in a PCH generation will be just named
+ as "_PCH_" without [generation_name] inserted.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _GBE_MDI_LIB_H_
+#define _GBE_MDI_LIB_H_
+
+//
+// Maximum loop time for GbE status check
+// 4000 * 50 = 200 mSec in total
+//
+#define GBE_MAX_LOOP_TIME 4000
+#define GBE_ACQUIRE_MDIO_DELAY 50
+#define GBE_MDI_SET_PAGE_DELAY 4000 // 4 mSec delay after setting page
+
+//
+// LAN PHY MDI settings
+//
+// MDI Control Register Bits
+// 31:30 Reserved
+// This field is reserved and returns 0.
+// 29 Interrupt Enable.
+// When this bit is set to 1 by software, it causes the device to assert
+// an interrupt indicating the end of an MDI cycle.
+// 28 Ready.
+// Set to 1 by the device at the end of MDI transaction (i.e., indicates a Read or
+// Write has been completed. It should be reset to 0 by software at the same time the
+// command is written.
+// 27:26 Opcode
+// For an MDI write, the opcode equals 01b, and for MDI read, 10b. 00b and
+// 11b are reserved and should not be used.
+// 25:21 PHYAdd
+// PHY Address
+// 20:16 RegAdd
+// PHY Register Address
+// 15:0 Data
+
+#define B_PHY_MDI_READY BIT28
+#define B_PHY_MDI_READ BIT27
+#define B_PHY_MDI_WRITE BIT26
+//
+// PHY SPECIFIC registers
+//
+#define B_PHY_MDI_PHY_ADDRESS_02 BIT22
+//
+// PHY GENERAL registers
+// Registers 0 to 15 are defined by the specification
+// Registers 16 to 31 are left available to the vendor
+//
+#define B_PHY_MDI_PHY_ADDRESS_01 BIT21
+#define B_PHY_MDI_PHY_ADDRESS_MASK (BIT25 | BIT24 | BIT23 | BIT22 | BIT21)
+//
+// PHY Identifier Register 2
+// Bits [15:10] - PHY ID Number - The PHY identifier composed of bits 3 through 18
+// of the Organizationally Unique Identifier (OUI)
+// Bits [9:4] - Device Model Number
+// Bits [3:0] - Device Revision Number
+//
+#define R_PHY_MDI_GENEREAL_REGISTER_03_PHY_IDENTIFIER_2 0x00030000
+
+#define MDI_REG_SHIFT(x) (x << 16)
+#define B_PHY_MDI_PHY_REGISTER_MASK (BIT20 | BIT19 | BIT18 | BIT17 | BIT16)
+#define R_PHY_MDI_PHY_REG_SET_ADDRESS 0x00110000 // Used after new page setting
+#define R_PHY_MDI_PHY_REG_DATA_READ_WRITE 0x00120000
+#define R_PHY_MDI_PHY_REG_SET_PAGE 0x001F0000
+
+//
+// LAN PHY MDI registers and bits
+//
+
+//
+// Page 769 Port Control Registers
+// 6020h (769 * 32)
+//
+#define PHY_MDI_PAGE_769_PORT_CONTROL_REGISTERS 769
+//
+// Custom Mode Control PHY Address 01, Page 769, Register 16
+//
+#define R_PHY_MDI_PAGE_769_REGISETER_16_CMC 0x0010
+//
+// Custom Mode Control
+// Page 769, Register 16, BIT 10
+// 0 - normal MDIO frequency access
+// 1 - reduced MDIO frequency access (slow mdio)
+// required for read during cable disconnect
+//
+#define B_PHY_MDI_PAGE_769_REGISETER_16_CMC_MDIO_FREQ_ACCESS BIT10
+//
+// Port General Configuration PHY Address 01, Page 769, Register 17
+//
+#define R_PHY_MDI_PAGE_769_REGISETER_17_PGC 0x0011
+//
+// Page 769, Register 17, BIT 4
+// Enables host wake up
+//
+#define B_PHY_MDI_PAGE_769_REGISETER_17_PGC_HOST_WAKE_UP BIT4
+//
+// Page 769, Register 17, BIT 2
+// Globally enable the MAC power down feature while the
+// GbE supports WoL. When set to 1b,
+// pages 800 and 801 are enabled for
+// configuration and Host_WU_Active is not blocked for writes.
+//
+#define B_PHY_MDI_PAGE_769_REGISETER_17_PGC_MACPD_ENABLE BIT2
+
+//
+// Page 800 Wake Up Registers
+// 6400h (800 * 32)
+//
+#define PHY_MDI_PAGE_800_WAKE_UP_REGISTERS 800
+//
+// Wake Up Control - WUC PHY Address 01, Page 800, Register 1
+// 1h (Register 1)
+//
+#define R_PHY_MDI_PAGE_800_REGISETER_1_WUC 0x0001
+//
+// Wake Up Control - (WUC)
+// Page 800, Register 1, BIT 0
+// Advance Power Management Enable (APME)
+// If set to 1b, APM wake up is enabled.
+//
+#define B_PHY_MDI_PAGE_800_REGISETER_1_WUC_APME BIT0
+//
+// Receive Address Low - RAL PHY Address 01, Page 800, Register 16
+// 10h (Register 16)
+//
+#define R_PHY_MDI_PAGE_800_REGISETER_16_RAL0 0x0010
+//
+// Receive Address Low - RAL PHY Address 01, Page 800, Register 17
+// 11h (Register 17)
+//
+#define R_PHY_MDI_PAGE_800_REGISETER_17_RAL1 0x0011
+//
+// Receive Address High - RAH PHY Address 01, Page 800, Register 18
+// 12h (Register 18)
+//
+#define R_PHY_MDI_PAGE_800_REGISETER_18_RAH0 0x0012
+//
+// Receive Address High - RAH PHY Address 01, Page 800, Register 19
+// 13h (Register 19)
+//
+#define R_PHY_MDI_PAGE_800_REGISETER_19_RAH1 0x0013
+//
+// Setting AV (BIT15 RAH is divided on two registers)
+// RAH Register 19, Page 800, BIT 31
+//
+// Address valid (AV)
+// When this bit is set, the relevant RAL and RAH are valid
+//
+#define B_PHY_MDI_PAGE_800_REGISETER_19_RAH1_ADDRESS_VALID BIT15
+//
+// Page 803 Host WoL Packet
+// 6460h (803 * 32)
+//
+#define PHY_MDI_PAGE_803_HOST_WOL_PACKET 803
+//
+// Host WoL Packet Clear - HWPC PHY Address 01, Page 803, Register 66
+//
+#define R_PHY_MDI_PAGE_803_REGISETER_66_HWPC 0x0042
+
+
+/**
+ Change Extended Device Control Register BIT 11 to 1 which
+ forces the interface between the MAC and the Phy to be on SMBus.
+ Cleared on the assertion of PCI reset.
+
+ @param [in] GbeBar GbE MMIO space
+
+**/
+VOID
+GbeMdiForceMACtoSMB (
+ IN UINT32 GbeBar
+ );
+
+/**
+ Test for MDIO operation complete.
+
+ @param [in] GbeBar GbE MMIO space
+
+ @retval EFI_SUCCESS
+ @retval EFI_TIMEOUT
+**/
+EFI_STATUS
+GbeMdiWaitReady (
+ IN UINT32 GbeBar
+ );
+
+/**
+ Acquire MDIO software semaphore.
+
+ 1. Ensure that MBARA offset F00h [5] = 1b
+ 2. Poll MBARA offset F00h [5] up to 200ms
+
+ @param [in] GbeBar GbE MMIO space
+
+ @retval EFI_SUCCESS
+ @retval EFI_TIMEOUT
+**/
+EFI_STATUS
+GbeMdiAcquireMdio (
+ IN UINT32 GbeBar
+ );
+
+/**
+ Release MDIO software semaphore by clearing MBARA offset F00h [5]
+
+ @param [in] GbeBar GbE MMIO space
+**/
+VOID
+GbeMdiReleaseMdio (
+ IN UINT32 GbeBar
+ );
+
+/**
+ Sets page on MDI
+ Page setting is attempted twice.
+ If first attempt failes MAC and the Phy are force to be on SMBus
+
+ @param [in] GbeBar GbE MMIO space
+ @param [in] Data Value to write in lower 16bits.
+
+ @retval EFI_SUCCESS Page setting was successfull
+ @retval EFI_DEVICE_ERROR Returned if both attermps of setting page failed
+**/
+EFI_STATUS
+GbeMdiSetPage (
+ IN UINT32 GbeBar,
+ IN UINT32 Page
+ );
+
+/**
+ Sets Register in current page.
+
+ @param [in] GbeBar GbE MMIO space
+ @param [in] register Register number
+
+ @return EFI_STATUS
+**/
+EFI_STATUS
+GbeMdiSetRegister (
+ IN UINT32 GbeBar,
+ IN UINT32 Register
+ );
+
+
+/**
+ Perform MDI read.
+
+ @param [in] GbeBar GbE MMIO space
+ @param [in] PhyAddress Phy Address General - 02 or Specific - 01
+ @param [in] PhyRegister Phy Register
+ @param [out] ReadData Return Value
+
+ @retval EFI_SUCCESS Based on response from GbeMdiWaitReady
+ @retval EFI_TIMEOUT Based on response from GbeMdiWaitReady
+ @retval EFI_INVALID_PARAMETER If Phy Address or Register validaton failed
+**/
+EFI_STATUS
+GbeMdiRead (
+ IN UINT32 GbeBar,
+ IN UINT32 PhyAddress,
+ IN UINT32 PhyRegister,
+ OUT UINT16 *ReadData
+ );
+
+/**
+ Perform MDI write.
+
+ @param [in] GbeBar GbE MMIO space
+ @param [in] PhyAddress Phy Address General - 02 or Specific - 01
+ @param [in] PhyRegister Phy Register
+ @param [in] WriteData Value to write in lower 16bits.
+
+ @retval EFI_SUCCESS Based on response from GbeMdiWaitReady
+ @retval EFI_TIMEOUT Based on response from GbeMdiWaitReady
+ @retval EFI_INVALID_PARAMETER If Phy Address or Register validaton failed
+**/
+EFI_STATUS
+GbeMdiWrite (
+ IN UINT32 GbeBar,
+ IN UINT32 PhyAddress,
+ IN UINT32 PhyRegister,
+ IN UINT32 WriteData
+ );
+
+/**
+ Gets Phy Revision and Model Number
+ from PHY IDENTIFIER register 2 (offset 3)
+
+ @param [in] GbeBar GbE MMIO space
+ @param [out] LanPhyRevision Return Value
+
+ @return EFI_STATUS
+ @return EFI_INVALID_PARAMETER When GbeBar is incorrect
+**/
+EFI_STATUS
+GbeMdiGetLanPhyRevision (
+ IN UINT32 GbeBar,
+ OUT UINT16 *LanPhyRevision
+ );
+
+#endif // _GBE_MDI_LIB_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gbe/IncludePrivate/Register/GbeRegs.h b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gbe/IncludePrivate/Register/GbeRegs.h
new file mode 100644
index 0000000000..307f1e159e
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gbe/IncludePrivate/Register/GbeRegs.h
@@ -0,0 +1,68 @@
+/** @file
+ Register names for GbE device
+
+ Conventions:
+
+ - Register definition format:
+ Prefix_[GenerationName]_[ComponentName]_SubsystemName_RegisterSpace_RegisterName
+ - Prefix:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register size
+ Definitions beginning with "N_" are the bit position
+ - [GenerationName]:
+ Three letter acronym of the generation is used (e.g. SKL,KBL,CNL etc.).
+ Register name without GenerationName applies to all generations.
+ - [ComponentName]:
+ This field indicates the component name that the register belongs to (e.g. PCH, SA etc.)
+ Register name without ComponentName applies to all components.
+ Register that is specific to -LP denoted by "_PCH_LP_" in component name.
+ - SubsystemName:
+ This field indicates the subsystem name of the component that the register belongs to
+ (e.g. PCIE, USB, SATA, GPIO, PMC etc.).
+ - RegisterSpace:
+ MEM - MMIO space register of subsystem.
+ IO - IO space register of subsystem.
+ PCR - Private configuration register of subsystem.
+ CFG - PCI configuration space register of subsystem.
+ - RegisterName:
+ Full register name.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _GBE_REGS_H_
+#define _GBE_REGS_H_
+
+#define R_GBE_CFG_MBARA 0x10
+#define N_GBE_CFG_MBARA_ALIGN 17
+#define R_GBE_CFG_PMCS 0xCC
+#define B_GBE_CFG_PMCS_PS (BIT1 | BIT0)
+#define V_GBE_CFG_PMCS_PS0 0x00
+//
+// Gigabit Ethernet LAN Capabilities and Status Registers (Memory space)
+//
+#define R_GBE_MEM_CSR_CTRL 0
+//
+// LANPHYPC:
+// Connects to the LCD DEVICE_OFF# signal in the
+// LAN Connected Device
+//
+#define B_GBE_MEM_CSR_CTRL_LANPHYPC_OVERRIDE BIT16 // When set to 1 SW driver has the ability to control the LANPHYPC pin value.
+#define B_GBE_MEM_CSR_CTRL_LANPHYPC_VAL BIT17 // When set to 1 this bit will define the value of the LANPHYPC pin.
+#define R_GBE_MEM_CSR_CTRL_EXT 0x0018
+#define B_GBE_MEM_CSR_CTRL_EXT_LPCD BIT2 //LCD Power Cycle Done (LPCD). This bit indicates whether LCD power cycle is done
+ //- the bit is set 50/100mSec after LANPHYPC pin assertion.
+#define B_GBE_MEM_CSR_CTRL_EXT_FORCE_SMB BIT11
+#define R_GBE_MEM_CSR_MDIC 0x0020
+#define B_GBE_MEM_CSR_MDIC_RB BIT28
+#define R_GBE_MEM_CSR_EXTCNF_CTRL 0x0F00
+#define B_GBE_MEM_CSR_EXTCNF_CTRL_SWFLAG BIT5
+#define R_GBE_MEM_CSR_RAL 0x5400
+#define R_GBE_MEM_CSR_RAH 0x5404
+#define B_GBE_MEM_CSR_RAH_RAH 0x0000FFFF
+#define R_GBE_MEM_CSR_WUC 0x5800
+#define B_GBE_MEM_CSR_WUC_APME BIT0
+
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gbe/Library/PeiDxeSmmGbeLib/GbeLib.c b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gbe/Library/PeiDxeSmmGbeLib/GbeLib.c
new file mode 100644
index 0000000000..3b51b9eb62
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gbe/Library/PeiDxeSmmGbeLib/GbeLib.c
@@ -0,0 +1,121 @@
+/** @file
+ Gbe Library.
+ All function in this library is available for PEI, DXE, and SMM,
+ But do not support UEFI RUNTIME environment call.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/PciSegmentLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/PchPcrLib.h>
+#include <Library/PchCycleDecodingLib.h>
+#include <Library/PmcPrivateLib.h>
+#include <Library/SpiAccessLib.h>
+#include <Library/GbeMdiLib.h>
+#include <IndustryStandard/Pci30.h>
+#include <Register/PchRegs.h>
+#include <Register/GbeRegs.h>
+#include <Library/PchPciBdfLib.h>
+
+/**
+ Check whether GbE region is valid
+ Check SPI region directly since GbE might be disabled in SW.
+
+ @retval TRUE Gbe Region is valid
+ @retval FALSE Gbe Region is invalid
+**/
+BOOLEAN
+IsGbeRegionValid (
+ VOID
+ )
+{
+ return SpiIsGbeRegionValid ();
+}
+
+/**
+ Check whether GBE controller is enabled in the platform.
+
+ @retval TRUE GbE is enabled
+ @retval FALSE GbE is disabled
+**/
+BOOLEAN
+IsGbePresent (
+ VOID
+ )
+{
+ //
+ // Check PCH Support
+ //
+ if (!PchIsGbeSupported ()) {
+ return FALSE;
+ }
+ //
+ // Check PMC strap/fuse
+ //
+ if (!PmcIsGbeSupported ()) {
+ return FALSE;
+ }
+ //
+ // Check GbE NVM
+ //
+ if (IsGbeRegionValid () == FALSE) {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**
+ Verifies Gigabit Ethernet PCI Class Code
+
+ @param [in] GbePciCfgBase GbE PCI Config Space Address
+
+ @retval TRUE GbE Class Code match
+ @retval FALSE GbE Class Code does not match
+**/
+BOOLEAN
+STATIC
+GbeCheckClassCode (
+ UINT64 GbePciCfgBase
+ )
+{
+ UINT8 BaseCode;
+ UINT8 SubClassCode;
+
+ SubClassCode = PciSegmentRead8 (GbePciCfgBase + PCI_CLASSCODE_OFFSET + 1);
+ BaseCode = PciSegmentRead8 (GbePciCfgBase + PCI_CLASSCODE_OFFSET + 2);
+
+ if ((BaseCode != PCI_CLASS_NETWORK) || (SubClassCode != PCI_CLASS_NETWORK_ETHERNET)) {
+ DEBUG ((DEBUG_ERROR, "GbeCheckClassCode : BaseCode(0x%x) or ClassCode(0x%x) is not supported\n", BaseCode, SubClassCode));
+ ASSERT (FALSE);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**
+ Checks if Gbe is Enabled or Disabled
+
+ @retval BOOLEAN TRUE if device is enabled, FALSE otherwise.
+**/
+BOOLEAN
+IsGbeEnabled (
+ VOID
+ )
+{
+ UINT64 GbePciBase;
+
+ GbePciBase = GbePciCfgBase ();
+
+ if (PciSegmentRead32 (GbePciBase) != 0xFFFFFFFF) {
+ return GbeCheckClassCode (GbePciBase);
+ }
+
+ return FALSE;
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gbe/Library/PeiDxeSmmGbeLib/PeiDxeSmmGbeLib.inf b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gbe/Library/PeiDxeSmmGbeLib/PeiDxeSmmGbeLib.inf
new file mode 100644
index 0000000000..4fef1288af
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gbe/Library/PeiDxeSmmGbeLib/PeiDxeSmmGbeLib.inf
@@ -0,0 +1,43 @@
+## @file
+# Gbe Library.
+#
+# All function in this library is available for PEI, DXE, and SMM,
+# But do not support UEFI RUNTIME environment call.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiDxeSmmGbeLib
+FILE_GUID = FC022ED0-6EB3-43E1-A740-0BA27CBBD010
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = GbeLib
+
+
+[LibraryClasses]
+BaseLib
+IoLib
+DebugLib
+PciSegmentLib
+PchInfoLib
+PchPcrLib
+PchCycleDecodingLib
+PmcPrivateLib
+SpiAccessLib
+GbeMdiLib
+PchPciBdfLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+TigerlakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+GbeLib.c
+
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gbe/LibraryPrivate/PeiDxeSmmGbeMdiLib/GbeMdiLib.c b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gbe/LibraryPrivate/PeiDxeSmmGbeMdiLib/GbeMdiLib.c
new file mode 100644
index 0000000000..7917474406
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gbe/LibraryPrivate/PeiDxeSmmGbeMdiLib/GbeMdiLib.c
@@ -0,0 +1,388 @@
+/** @file
+ Gbe MDI Library.
+ All function in this library is available for PEI, DXE, and SMM,
+ But do not support UEFI RUNTIME environment call.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/TimerLib.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/GbeMdiLib.h>
+#include <Register/GbeRegs.h>
+
+
+/**
+ Validates both Phy Address and Regster.
+
+ @param [in] PhyAddress
+ @param [in] PhyRegister
+
+ @retval BOOLEAN TRUE Validation passed
+ FALSE If the data is not within its range
+
+**/
+BOOLEAN
+IsPhyAddressRegisterValid (
+ IN UINT32 PhyAddress,
+ IN UINT32 PhyRegister
+ )
+{
+ if (((PhyAddress & (~B_PHY_MDI_PHY_ADDRESS_MASK)) != 0) || ((PhyRegister & (~B_PHY_MDI_PHY_REGISTER_MASK)) != 0)) {
+ DEBUG ((DEBUG_ERROR, "IsPhyAddressRegisterValid validation failed! PhyAddress: 0x%08X PhyRegister: 0x%08X \n", PhyAddress, PhyRegister));
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**
+ Change Extended Device Control Register BIT 11 to 1 which
+ forces the interface between the MAC and the Phy to be on SMBus.
+ Cleared on the assertion of PCI reset.
+
+ @param [in] GbeBar GbE MMIO space
+
+**/
+VOID
+GbeMdiForceMacToSmb (
+ IN UINT32 GbeBar
+ )
+{
+ MmioOr32 (GbeBar + R_GBE_MEM_CSR_CTRL_EXT, B_GBE_MEM_CSR_CTRL_EXT_FORCE_SMB);
+}
+
+/**
+ Test for MDIO operation complete.
+
+ @param [in] GbeBar GbE MMIO space
+
+ @retval EFI_SUCCESS
+ @retval EFI_TIMEOUT
+**/
+EFI_STATUS
+GbeMdiWaitReady (
+ IN UINT32 GbeBar
+ )
+{
+ UINT32 Count;
+
+ for (Count = 0; Count < GBE_MAX_LOOP_TIME; ++Count) {
+ if (MmioRead32 (GbeBar + R_GBE_MEM_CSR_MDIC) & B_GBE_MEM_CSR_MDIC_RB) {
+ return EFI_SUCCESS;
+ }
+ MicroSecondDelay (GBE_ACQUIRE_MDIO_DELAY);
+ }
+ DEBUG ((DEBUG_ERROR, "GbeMdiWaitReady Timeout reached. MDIO operation failed to complete in %d micro seconds\n", GBE_MAX_LOOP_TIME * GBE_ACQUIRE_MDIO_DELAY));
+ return EFI_TIMEOUT;
+}
+
+/**
+ Acquire MDIO software semaphore.
+
+ 1. Ensure that MBARA offset F00h [5] = 1b
+ 2. Poll MBARA offset F00h [5] up to 200ms
+
+ @param [in] GbeBar GbE MMIO space
+
+ @retval EFI_SUCCESS
+ @retval EFI_TIMEOUT
+**/
+EFI_STATUS
+GbeMdiAcquireMdio (
+ IN UINT32 GbeBar
+ )
+{
+ UINT32 ExtCnfCtrl;
+ UINT32 Count;
+
+ MmioOr32 (GbeBar + R_GBE_MEM_CSR_EXTCNF_CTRL, B_GBE_MEM_CSR_EXTCNF_CTRL_SWFLAG);
+ for (Count = 0; Count < GBE_MAX_LOOP_TIME; ++Count) {
+ ExtCnfCtrl = MmioRead32 (GbeBar + R_GBE_MEM_CSR_EXTCNF_CTRL);
+ if (ExtCnfCtrl & B_GBE_MEM_CSR_EXTCNF_CTRL_SWFLAG) {
+ return EFI_SUCCESS;
+ }
+ MicroSecondDelay (GBE_ACQUIRE_MDIO_DELAY);
+ }
+ DEBUG ((DEBUG_ERROR, "GbeMdiAcquireMdio Timeout. Unable to acquire MDIO Semaphore in %d micro seconds\n", GBE_MAX_LOOP_TIME * GBE_ACQUIRE_MDIO_DELAY));
+ return EFI_TIMEOUT;
+}
+
+/**
+ Release MDIO software semaphore by clearing MBARA offset F00h [5]
+
+ @param [in] GbeBar GbE MMIO space
+**/
+VOID
+GbeMdiReleaseMdio (
+ IN UINT32 GbeBar
+ )
+{
+ ASSERT (MmioRead32 (GbeBar + R_GBE_MEM_CSR_EXTCNF_CTRL) & B_GBE_MEM_CSR_EXTCNF_CTRL_SWFLAG);
+ MmioAnd32 (GbeBar + R_GBE_MEM_CSR_EXTCNF_CTRL, (UINT32) ~B_GBE_MEM_CSR_EXTCNF_CTRL_SWFLAG);
+ ASSERT ((MmioRead32 (GbeBar + R_GBE_MEM_CSR_EXTCNF_CTRL) & B_GBE_MEM_CSR_EXTCNF_CTRL_SWFLAG) == 0);
+}
+
+/**
+ Sets page on MDI
+ Page setting is attempted twice.
+ If first attempt failes MAC and the Phy are force to be on SMBus.
+
+ Waits 4 mSec after page setting
+
+ @param [in] GbeBar GbE MMIO space
+ @param [in] Data Value to write in lower 16bits.
+
+ @retval EFI_SUCCESS Page setting was successfull
+ @retval EFI_DEVICE_ERROR Returned if both attermps of setting page failed
+**/
+EFI_STATUS
+GbeMdiSetPage (
+ IN UINT32 GbeBar,
+ IN UINT32 Page
+ )
+{
+ EFI_STATUS Status;
+
+ MmioWrite32 (GbeBar + R_GBE_MEM_CSR_MDIC, (~B_PHY_MDI_READY) & (B_PHY_MDI_WRITE | B_PHY_MDI_PHY_ADDRESS_01 | R_PHY_MDI_PHY_REG_SET_PAGE | ((Page * 32) & 0xFFFF)));
+
+ Status = GbeMdiWaitReady (GbeBar);
+
+ if (Status == EFI_TIMEOUT) {
+ DEBUG ((DEBUG_INFO, "GbeMdiSetPage Timeout reached. Forcing the interface between the MAC and the Phy to be on SMBus\n"));
+ GbeMdiForceMacToSmb (GbeBar);
+ //
+ // Retry page setting
+ //
+ MmioWrite32 (GbeBar + R_GBE_MEM_CSR_MDIC, (~B_PHY_MDI_READY) & (B_PHY_MDI_WRITE | B_PHY_MDI_PHY_ADDRESS_01 | R_PHY_MDI_PHY_REG_SET_PAGE | ((Page * 32) & 0xFFFF)));
+ Status = GbeMdiWaitReady (GbeBar);
+ if (Status == EFI_TIMEOUT) {
+ DEBUG ((DEBUG_ERROR, "GbeMdiSetPage retry page setting failed!\n"));
+ return EFI_DEVICE_ERROR;
+ }
+ }
+
+ //
+ // Delay required for page to set properly
+ //
+ MicroSecondDelay (GBE_MDI_SET_PAGE_DELAY);
+
+ return Status;
+}
+
+/**
+ Sets Register in current page.
+
+ @param [in] GbeBar GbE MMIO space
+ @param [in] register Register number valid only in lower 16 Bits
+
+ @return EFI_STATUS
+**/
+EFI_STATUS
+GbeMdiSetRegister (
+ IN UINT32 GbeBar,
+ IN UINT32 Register
+ )
+{
+ MmioWrite32 (GbeBar + R_GBE_MEM_CSR_MDIC, (~B_PHY_MDI_READY) & (B_PHY_MDI_WRITE | B_PHY_MDI_PHY_ADDRESS_01 | R_PHY_MDI_PHY_REG_SET_ADDRESS | (Register & 0xFFFF)));
+ return GbeMdiWaitReady (GbeBar);
+}
+
+/**
+ Perform MDI write.
+
+ @param [in] GbeBar GbE MMIO space
+ @param [in] PhyAddress Phy Address General - 02 or Specific - 01
+ @param [in] PhyRegister Phy Register
+ @param [in] WriteData Value to write in lower 16bits.
+
+ @retval EFI_SUCCESS Based on response from GbeMdiWaitReady
+ @retval EFI_TIMEOUT Based on response from GbeMdiWaitReady
+ @retval EFI_INVALID_PARAMETER If Phy Address or Register validaton failed
+**/
+EFI_STATUS
+GbeMdiWrite (
+ IN UINT32 GbeBar,
+ IN UINT32 PhyAddress,
+ IN UINT32 PhyRegister,
+ IN UINT32 WriteData
+ )
+{
+ if(!IsPhyAddressRegisterValid (PhyAddress, PhyRegister)) {
+ DEBUG ((DEBUG_ERROR, "GbeMdiWrite PhyAddressRegister validaton failed!\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ MmioWrite32 (GbeBar + R_GBE_MEM_CSR_MDIC, (~B_PHY_MDI_READY) & (B_PHY_MDI_WRITE | PhyAddress | PhyRegister | (WriteData & 0xFFFF)));
+ return GbeMdiWaitReady (GbeBar);
+}
+
+/**
+ Perform MDI read.
+
+ @param [in] GbeBar GbE MMIO space
+ @param [in] PhyAddress Phy Address General - 02 or Specific - 01
+ @param [in] PhyRegister Phy Register
+ @param [out] ReadData Return Value
+
+ @retval EFI_SUCCESS Based on response from GbeMdiWaitReady
+ @retval EFI_TIMEOUT Based on response from GbeMdiWaitReady
+ @retval EFI_INVALID_PARAMETER If Phy Address or Register validaton failed
+**/
+EFI_STATUS
+GbeMdiRead (
+ IN UINT32 GbeBar,
+ IN UINT32 PhyAddress,
+ IN UINT32 PhyRegister,
+ OUT UINT16 *ReadData
+ )
+{
+ EFI_STATUS Status;
+
+ if(!IsPhyAddressRegisterValid (PhyAddress, PhyRegister)) {
+ DEBUG ((DEBUG_ERROR, "GbeMdiRead PhyAddressRegister validaton failed!\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ MmioWrite32 (GbeBar + R_GBE_MEM_CSR_MDIC, (~B_PHY_MDI_READY) & (B_PHY_MDI_READ | PhyAddress | PhyRegister));
+ Status = GbeMdiWaitReady (GbeBar);
+ if (EFI_SUCCESS == Status) {
+ *ReadData = (UINT16) MmioRead32 (GbeBar + R_GBE_MEM_CSR_MDIC);
+ }
+ return Status;
+}
+
+/**
+ Gets Phy Revision and Model Number
+ from PHY IDENTIFIER register 2 (offset 3)
+
+ @param [in] GbeBar GbE MMIO space
+ @param [out] LanPhyRevision Return Value
+
+ @return EFI_STATUS
+ @return EFI_INVALID_PARAMETER When GbeBar is incorrect
+ When Phy register or address is out of bounds
+**/
+EFI_STATUS
+GbeMdiGetLanPhyRevision (
+ IN UINT32 GbeBar,
+ OUT UINT16 *LanPhyRevision
+ )
+{
+ EFI_STATUS Status;
+ UINT8 LpcdLoop;
+ UINT8 Delay;
+
+ if (!((GbeBar & 0xFFFFF000) > 0)) {
+ DEBUG ((DEBUG_ERROR, "GbeMdiGetLanPhyRevision GbeBar validation failed! Bar: 0x%08X \n", GbeBar));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = GbeMdiAcquireMdio (GbeBar);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "GbeMdiGetLanPhyRevision failed to aquire MDIO semaphore. Status: %r\n", Status));
+ return Status;
+ }
+
+ Status = GbeMdiSetPage (GbeBar, PHY_MDI_PAGE_769_PORT_CONTROL_REGISTERS);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "GbeMdiGetLanPhyRevision failed to Set Page 769. Status: %r\n", Status));
+ GbeMdiReleaseMdio (GbeBar);
+ return Status;
+ }
+
+ //
+ // Set register to: Custom Mode Control
+ // Reduced MDIO frequency access (slow mdio)
+ // BIT 10 set to 1
+ //
+ Status = GbeMdiWrite (GbeBar, B_PHY_MDI_PHY_ADDRESS_01, MDI_REG_SHIFT (R_PHY_MDI_PAGE_769_REGISETER_16_CMC), BIT13 | B_PHY_MDI_PAGE_769_REGISETER_16_CMC_MDIO_FREQ_ACCESS | BIT8 | BIT7);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "GbeMdiGetLanPhyRevision failed to enable slow MDIO mode. Status: %r\n", Status));
+ GbeMdiReleaseMdio (GbeBar);
+ return Status;
+ }
+
+ //
+ // Read register PHY Version from PHY IDENTIFIER 2 (offset 0x3)
+ // Bits [9:4] - Device Model Number
+ // Bits [3:0] - Device Revision Number
+ //
+ Status = GbeMdiRead (GbeBar, B_PHY_MDI_PHY_ADDRESS_02, R_PHY_MDI_GENEREAL_REGISTER_03_PHY_IDENTIFIER_2, LanPhyRevision);
+
+ //
+ // Failed to obtain PHY REV
+ //
+ if (*LanPhyRevision == 0x0) {
+ if ((MmioRead32 (GbeBar + R_GBE_MEM_CSR_CTRL) & (B_GBE_MEM_CSR_CTRL_LANPHYPC_OVERRIDE | B_GBE_MEM_CSR_CTRL_LANPHYPC_VAL))) {
+ DEBUG ((DEBUG_ERROR, "GbeMdiGetLanPhyRevision failed to read Phy Revision. Other component tried to initialize GbE and failed.\n"));
+ Status = EFI_DEVICE_ERROR;
+ goto phy_exit;
+ }
+ DEBUG ((DEBUG_INFO, "GbeMdiGetLanPhyRevision failed to read Revision. Overriding LANPHYPC\n", Status));
+ //
+ // Taking over LANPHYPC
+ // 1. SW signal override - 1st cycle.
+ // 2. Turn LCD on - 2nd cycle.
+ //
+ MmioOr32 (GbeBar + R_GBE_MEM_CSR_CTRL, B_GBE_MEM_CSR_CTRL_LANPHYPC_OVERRIDE);
+ MmioOr32 (GbeBar + R_GBE_MEM_CSR_CTRL, B_GBE_MEM_CSR_CTRL_LANPHYPC_VAL);
+
+ //
+ // Poll on LPCD for 100mSec
+ //
+ LpcdLoop = 101;
+ while (LpcdLoop > 0) {
+ if (MmioRead32 (GbeBar + R_GBE_MEM_CSR_CTRL_EXT) & B_GBE_MEM_CSR_CTRL_EXT_LPCD) {
+ break;
+ } else {
+ LpcdLoop--;
+ MicroSecondDelay (1000);
+ }
+ }
+
+ if (LpcdLoop > 0) {
+ Delay = 100;
+ Status = GbeMdiRead (GbeBar, B_PHY_MDI_PHY_ADDRESS_02, R_PHY_MDI_GENEREAL_REGISTER_03_PHY_IDENTIFIER_2, LanPhyRevision);
+ while (*LanPhyRevision == 0 && Delay > 0) {
+ Status = GbeMdiRead (GbeBar, B_PHY_MDI_PHY_ADDRESS_02, R_PHY_MDI_GENEREAL_REGISTER_03_PHY_IDENTIFIER_2, LanPhyRevision);
+ if (EFI_ERROR(Status)) {
+ break;
+ }
+ MicroSecondDelay (1000);
+ Delay --;
+ }
+ }
+ //
+ // Restore LANPHYPC
+ // 1. Turn LCD off - 1st cycle.
+ // 2. Remove SW signal override - 2nd cycle.
+ //
+ MmioAnd32 (GbeBar + R_GBE_MEM_CSR_CTRL, (UINT32) ~B_GBE_MEM_CSR_CTRL_LANPHYPC_VAL);
+ MmioAnd32 (GbeBar + R_GBE_MEM_CSR_CTRL, (UINT32) ~B_GBE_MEM_CSR_CTRL_LANPHYPC_OVERRIDE);
+ }
+
+phy_exit:
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "GbeMdiGetLanPhyRevision failed to read Revision and Model Number from PHY Identifier 2. Status: %r\n", Status));
+ GbeMdiReleaseMdio (GbeBar);
+ return Status;
+ }
+
+ //
+ // Switch back to normal MDIO frequency access
+ //
+ Status = GbeMdiWrite (GbeBar, B_PHY_MDI_PHY_ADDRESS_01, MDI_REG_SHIFT (R_PHY_MDI_PAGE_769_REGISETER_16_CMC), (~B_PHY_MDI_PAGE_769_REGISETER_16_CMC_MDIO_FREQ_ACCESS) & (BIT13 | BIT8 | BIT7));
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "GbeMdiGetLanPhyRevision failed to disable slow MDIO mode. Status: %r\n", Status));
+ }
+
+ GbeMdiReleaseMdio (GbeBar);
+
+ return Status;
+}
+
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gbe/LibraryPrivate/PeiDxeSmmGbeMdiLib/PeiDxeSmmGbeMdiLib.inf b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gbe/LibraryPrivate/PeiDxeSmmGbeMdiLib/PeiDxeSmmGbeMdiLib.inf
new file mode 100644
index 0000000000..99a01177f6
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gbe/LibraryPrivate/PeiDxeSmmGbeMdiLib/PeiDxeSmmGbeMdiLib.inf
@@ -0,0 +1,34 @@
+## @file
+# Gbe MDI Library.
+#
+# All function in this library is available for PEI, DXE, and SMM,
+# But do not support UEFI RUNTIME environment call.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiDxeSmmGbeMdiLib
+FILE_GUID = 0360E6F6-892A-4852-BF98-15C0D30D8A48
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = GbeMdiLib
+
+
+[LibraryClasses]
+BaseLib
+IoLib
+DebugLib
+TimerLib
+
+[Packages]
+MdePkg/MdePkg.dec
+TigerlakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+GbeMdiLib.c
--
2.24.0.windows.2
^ permalink raw reply related [flat|nested] 42+ messages in thread
* [Patch V3 17/40] TigerlakeSiliconPkg/IpBlock: Add Gpio component
2021-02-05 7:40 [Patch V3 01/40] TigerlakeSiliconPkg: Add package and Include/ConfigBlock headers Heng Luo
` (14 preceding siblings ...)
2021-02-05 7:40 ` [Patch V3 16/40] TigerlakeSiliconPkg/IpBlock: Add Gbe component Heng Luo
@ 2021-02-05 7:40 ` Heng Luo
2021-02-05 7:40 ` [Patch V3 18/40] TigerlakeSiliconPkg/IpBlock: Add Graphics component Heng Luo
` (22 subsequent siblings)
38 siblings, 0 replies; 42+ messages in thread
From: Heng Luo @ 2021-02-05 7:40 UTC (permalink / raw)
To: devel; +Cc: Sai Chaganty, Nate DeSimone
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3171
Adds the following files:
* IpBlock/Gpio/Include
* IpBlock/Gpio/IncludePrivate
* IpBlock/Gpio/Library
* IpBlock/Gpio/LibraryPrivate
Cc: Sai Chaganty <rangasai.v.chaganty@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Signed-off-by: Heng Luo <heng.luo@intel.com>
---
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/Include/Library/GpioCheckConflictLib.h | 43 ++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/IncludePrivate/Library/DxeGpioPolicyLib.h | 55 +++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/IncludePrivate/Library/GpioHelpersLib.h | 105 +++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/IncludePrivate/Library/GpioNameBufferLib.h | 23 +++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/IncludePrivate/Library/GpioPrivateLib.h | 1197 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/Library/BaseGpioCheckConflictLib/BaseGpioCheckConflictLib.c | 140 ++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/Library/BaseGpioCheckConflictLib/BaseGpioCheckConflictLib.inf | 29 +++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/Library/BaseGpioCheckConflictLibNull/BaseGpioCheckConflictLibNull.c | 35 +++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/Library/BaseGpioCheckConflictLibNull/BaseGpioCheckConflictLibNull.inf | 26 ++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/Library/PeiDxeSmmGpioLib/GpioInit.c | 558 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/Library/PeiDxeSmmGpioLib/GpioLib.c | 2387 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/Library/PeiDxeSmmGpioLib/GpioLibrary.h | 82 ++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/Library/PeiDxeSmmGpioLib/GpioNames.c | 86 ++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/Library/PeiDxeSmmGpioLib/GpioNativeLib.c | 193 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/Library/PeiDxeSmmGpioLib/PeiDxeSmmGpioLib.inf | 49 ++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/BaseGpioHelpersLibNull/BaseGpioHelpersLibNull.c | 119 ++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/BaseGpioHelpersLibNull/BaseGpioHelpersLibNull.inf | 26 ++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/DxeGpioNameBufferLib/DxeGpioNameBufferLib.inf | 32 ++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/DxeGpioNameBufferLib/GpioNameBufferDxe.c | 19 +++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/DxeGpioPolicyLib/DxeGpioPolicyLib.c | 87 ++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/DxeGpioPolicyLib/DxeGpioPolicyLib.inf | 31 ++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/PeiDxeSmmGpioPrivateLib/GpioNamesVer2.c | 88 +++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/PeiDxeSmmGpioPrivateLib/GpioPrivateLib.c | 395 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/PeiDxeSmmGpioPrivateLib/GpioPrivateLibVer2.c | 131 ++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/PeiDxeSmmGpioPrivateLib/PeiDxeSmmGpioPrivateLibVer2.inf | 46 +++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/PeiGpioHelpersLib/PeiGpioHelpersLib.c | 413 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/PeiGpioHelpersLib/PeiGpioHelpersLib.inf | 48 ++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/PeiGpioNameBufferLib/GpioNameBufferPei.c | 67 +++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/PeiGpioNameBufferLib/PeiGpioNameBufferLib.inf | 35 +++++++++++++
29 files changed, 6545 insertions(+)
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/Include/Library/GpioCheckConflictLib.h b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/Include/Library/GpioCheckConflictLib.h
new file mode 100644
index 0000000000..5e3dd90ae6
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/Include/Library/GpioCheckConflictLib.h
@@ -0,0 +1,43 @@
+/** @file
+ Header file for checking Gpio PadMode conflict.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _GPIO_CHECK_CONFLICT_LIB_H_
+#define _GPIO_CHECK_CONFLICT_LIB_H_
+
+#include <Uefi/UefiBaseType.h>
+#include <Library/GpioConfig.h>
+#include <Library/GpioLib.h>
+
+extern EFI_GUID gGpioCheckConflictHobGuid;
+
+typedef struct {
+ GPIO_PAD GpioPad;
+ UINT32 GpioPadMode:5;
+ UINT32 Reserved:27;
+} GPIO_PAD_MODE_INFO;
+
+/**
+ Check Gpio PadMode conflict and report it.
+**/
+VOID
+GpioCheckConflict (
+ VOID
+ );
+
+/**
+ This library will create one Hob for each Gpio config table
+ without PadMode is GpioHardwareDefault
+
+ @param[in] GpioDefinition Point to Platform Gpio table
+ @param[in] GpioTableCount Number of Gpio table entries
+**/
+VOID
+CreateGpioCheckConflictHob (
+ IN GPIO_INIT_CONFIG *GpioDefinition,
+ IN UINT32 GpioTableCount
+ );
+
+#endif // _GPIO_CHECK_CONFLICT_LIB_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/IncludePrivate/Library/DxeGpioPolicyLib.h b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/IncludePrivate/Library/DxeGpioPolicyLib.h
new file mode 100644
index 0000000000..d86e6624b7
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/IncludePrivate/Library/DxeGpioPolicyLib.h
@@ -0,0 +1,55 @@
+/** @file
+ DXE Gpio policy library.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _DXE_GPIO_POLICY_LIB_H_
+#define _DXE_GPIO_POLICY_LIB_H_
+
+#include <Protocol/PchPolicy.h>
+
+/**
+ Print GPIO_DXE_CONFIG and serial out.
+
+ @param[in] PchPolicy Pointer to a PCH_POLICY_PROTOCOL
+**/
+VOID
+GpioDxePrintConfig (
+ IN PCH_POLICY_PROTOCOL *PchPolicy
+ );
+
+/**
+ Load DXE Config block default for GPIO
+
+ @param[in] ConfigBlockPointer Pointer to config block
+**/
+VOID
+GpioDxeLoadConfigDefault (
+ IN VOID *ConfigBlockPointer
+ );
+
+/**
+ Get Gpio config block table size.
+
+ @retval Size of config block
+**/
+UINT16
+GpioDxeGetConfigBlockTotalSize (
+ VOID
+ );
+
+/**
+ Add Gpio ConfigBlock.
+
+ @param[in] ConfigBlockTableAddress The pointer to config block table
+
+ @retval EFI_SUCCESS The policy default is initialized.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create buffer
+**/
+EFI_STATUS
+GpioDxeAddConfigBlock (
+ IN VOID *ConfigBlockTableAddress
+ );
+
+#endif // _DXE_GPIO_POLICY_LIB_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/IncludePrivate/Library/GpioHelpersLib.h b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/IncludePrivate/Library/GpioHelpersLib.h
new file mode 100644
index 0000000000..d2a8d24c8a
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/IncludePrivate/Library/GpioHelpersLib.h
@@ -0,0 +1,105 @@
+/** @file
+ Header file for GPIO Helpers Lib implementation.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _GPIO_HELPERS_LIB_H_
+#define _GPIO_HELPERS_LIB_H_
+
+#include <Library/GpioConfig.h>
+
+/**
+ This procedure stores GPIO pad unlock information
+
+ @param[in] GpioPad GPIO pad
+ @param[in] GpioLockConfig GPIO Lock Configuration
+
+ @retval Status
+**/
+EFI_STATUS
+GpioStoreUnlockData (
+ IN GPIO_PAD GpioPad,
+ IN GPIO_LOCK_CONFIG GpioLockConfig
+ );
+
+/**
+ This procedure stores GPIO group data about pads which PadConfig needs to be unlocked.
+
+ @param[in] GroupIndex GPIO group index
+ @param[in] DwNum DWORD index for a group.
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[in] PadsToLock DWORD bitmask for pads which are going to be left unlocked
+ Bit position - PadNumber
+ Bit value - 0: Skip, 1: Leave unlocked
+
+ @retval Status
+**/
+EFI_STATUS
+GpioStoreGroupDwUnlockPadConfigData (
+ IN UINT32 GroupIndex,
+ IN UINT32 DwNum,
+ IN UINT32 UnlockedPads
+ );
+
+/**
+ This procedure stores GPIO group data about pads which Output state needs to be unlocked.
+
+ @param[in] GroupIndex GPIO group index
+ @param[in] DwNum DWORD index for a group.
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[in] PadsToLock DWORD bitmask for pads which are going to be left unlocked
+ Bit position - PadNumber
+ Bit value - 0: Skip, 1: Leave unlocked
+
+ @retval Status
+**/
+EFI_STATUS
+GpioStoreGroupDwUnlockOutputData (
+ IN UINT32 GroupIndex,
+ IN UINT32 DwNum,
+ IN UINT32 UnlockedPads
+ );
+
+/**
+ This procedure will get GPIO group data with pads, which PadConfig is supposed to be left unlock
+
+ @param[in] GroupIndex GPIO group index
+ @param[in] DwNum DWORD index for a group.
+ For group which has less then 32 pads per group DwNum must be 0.
+ @retval UnlockedPads DWORD bitmask for pads which are going to be left unlocked
+ Bit position - PadNumber
+ Bit value - 0: to be locked, 1: Leave unlocked
+**/
+UINT32
+GpioGetGroupDwUnlockPadConfigMask (
+ IN UINT32 GroupIndex,
+ IN UINT32 DwNum
+ );
+
+/**
+ This procedure will get GPIO group data with pads, which Output is supposed to be left unlock
+
+ @param[in] GroupIndex GPIO group index
+ @param[in] DwNum DWORD index for a group.
+ For group which has less then 32 pads per group DwNum must be 0.
+ @retval UnlockedPads DWORD bitmask for pads which are going to be left unlocked
+ Bit position - PadNumber
+ Bit value - 0: to be locked, 1: Leave unlocked
+**/
+UINT32
+GpioGetGroupDwUnlockOutputMask (
+ IN UINT32 GroupIndex,
+ IN UINT32 DwNum
+ );
+
+/**
+ Returns Gpio Override Level1 Information
+
+ @retval TRUE/FALSE GPIO Override Level 1 Enabled/Disabled
+**/
+BOOLEAN
+GpioOverrideLevel1Enabled (
+ VOID
+ );
+#endif // _GPIO_HELPERS_LIB_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/IncludePrivate/Library/GpioNameBufferLib.h b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/IncludePrivate/Library/GpioNameBufferLib.h
new file mode 100644
index 0000000000..c60709c637
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/IncludePrivate/Library/GpioNameBufferLib.h
@@ -0,0 +1,23 @@
+/** @file
+ Header file for GpioMemLib. This library provides GpioLib with static memory to hold GpioName.
+ Static memory is handled differently in PEI and DXE phase. For PEI pre mem we use private HOB to store
+ gpio name since .data section is read only. For PEI post mem and DXE simple static buffer is used.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _GPIO_NAME_BUFFER_LIB_H_
+#define _GPIO_NAME_BUFFER_LIB_H_
+
+#define GPIO_NAME_LENGTH_MAX 32
+
+/**
+ Returns pointer to the global buffer to be used by GpioNamesLib
+
+ @retval CHAR8* Pointer to the buffer
+**/
+CHAR8*
+GpioGetStaticNameBuffer (
+ VOID
+ );
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/IncludePrivate/Library/GpioPrivateLib.h b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/IncludePrivate/Library/GpioPrivateLib.h
new file mode 100644
index 0000000000..be41f80c24
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/IncludePrivate/Library/GpioPrivateLib.h
@@ -0,0 +1,1197 @@
+/** @file
+ Header file for GpioPrivateLib.
+ All function in this library is available for PEI, DXE, and SMM,
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _GPIO_PRIVATE_LIB_H_
+#define _GPIO_PRIVATE_LIB_H_
+
+#include <Uefi/UefiBaseType.h>
+#include <Library/GpioConfig.h>
+#include <Library/PchPcrLib.h>
+#include <TcssPeiConfig.h>
+
+/**
+ GPIO Standby State configuration
+ Standby State options for GPIO Pads
+**/
+typedef enum {
+ GpioIosStateDefault = 0x0,
+ GpioIosStateLatchLastValue = (0x0 << 1) | 0x01, ///< Latch last value driven on TX, TX Enable and RX Enable
+ GpioIosStateTx0Rx0RxDis = (0x1 << 1) | 0x01, ///< TX: 0, RX: 0 (internally), RX disabled
+ GpioIosStateTx0Rx1RxDis = (0x2 << 1) | 0x01, ///< TX: 0, RX: 1 (internally), RX disabled
+ GpioIosStateTx1Rx0RxDis = (0x3 << 1) | 0x01, ///< TX: 1, RX: 0 (internally), RX disabled
+ GpioIosStateTx1Rx1RxDis = (0x4 << 1) | 0x01, ///< TX: 1, RX: 1 (internally), RX disabled
+ GpioIosStateTx0RxEn = (0x5 << 1) | 0x01, ///< TX: 0, RX enabled
+ GpioIosStateTx1RxEn = (0x6 << 1) | 0x01, ///< TX: 1, RX enabled
+ GpioIosStateHizRx0 = (0x7 << 1) | 0x01, ///< Hi-Z, RX: 0 (internally)
+ GpioIosStateHizRx1 = (0x8 << 1) | 0x01, ///< Hi-Z, RX: 1 (internally)
+ GpioIosStateTxDisRxEn = (0x9 << 1) | 0x01, ///< TX Disabled and RX Enabled (i.e. wake or interrupt)
+ GpioIosStateMasked = (0xF << 1) | 0x01 ///< IO Standby signal is masked for this pad. In this mode, a pad operates as if IOStandby has not been asserted.
+} GPIO_IOSTANDBY_STATE;
+
+/**
+ GPIO Standby Term configuration
+ Standby Termination options for GPIO Pads
+**/
+typedef enum {
+ GpioIosTermDefault = 0x00,
+ GpioIosTermSame = (0x00 << 1) | 0x01, ///< Same as state specified in Term
+ GpioIosTermPuDisPdDis = (0x01 << 1) | 0x01, ///< Disable Pullup and Pulldown
+ GpioIosTermPuDisPdEn = (0x02 << 1) | 0x01, ///< Enable Pulldown
+ GpioIosTermPuEnPdDis = (0x03 << 1) | 0x01 ///< Enable Pullup
+} GPIO_IOSTANDBY_TERM;
+
+//
+// Structure for native pin data
+//
+typedef struct {
+ GPIO_PAD Pad;
+ GPIO_PAD_MODE Mode;
+ GPIO_IOSTANDBY_STATE IosState;
+ GPIO_IOSTANDBY_TERM IosTerm;
+} GPIO_PAD_NATIVE_FUNCTION;
+
+//
+// Structure for Serial GPIO pin definition
+//
+typedef struct {
+ GPIO_PAD_NATIVE_FUNCTION Sclock;
+ GPIO_PAD_NATIVE_FUNCTION Sload;
+ GPIO_PAD_NATIVE_FUNCTION Sdataout;
+} SGPIO_PINS;
+
+//
+// Structure for USB Virtual Wire OverCurrent Pad Mode group
+//
+typedef struct {
+ GPIO_PAD OcRxPad;
+ GPIO_PAD OcTxPad;
+} GPIO_VWOC_FUNCTION;
+
+//
+// Below defines are based on GPIO_CONFIG structure fields
+//
+#define B_GPIO_PAD_MODE_MASK 0xF
+#define N_GPIO_PAD_MODE_BIT_POS 0
+#define B_GPIO_HOSTSW_OWN_MASK 0x3
+#define N_GPIO_HOSTSW_OWN_BIT_POS 0
+#define B_GPIO_DIRECTION_MASK 0x1F
+#define B_GPIO_DIRECTION_DIR_MASK 0x7
+#define N_GPIO_DIRECTION_DIR_BIT_POS 0
+#define B_GPIO_DIRECTION_INV_MASK 0x18
+#define N_GPIO_DIRECTION_INV_BIT_POS 3
+#define B_GPIO_OUTPUT_MASK 0x3
+#define N_GPIO_OUTPUT_BIT_POS 0
+#define N_GPIO_INT_CONFIG_INT_SOURCE_BIT_POS 0
+#define N_GPIO_INT_CONFIG_INT_TYPE_BIT_POS 5
+#define B_GPIO_RESET_CONFIG_RESET_MASK 0x3F
+#define N_GPIO_RESET_CONFIG_OLD_RESET_TYPE BIT1
+#define B_GPIO_RESET_CONFIG_OLD_RESET_MASK 0xF
+#define N_GPIO_RESET_CONFIG_RESET_BIT_POS 0
+#define B_GPIO_RESET_CONFIG_GPD_RESET_MASK (BIT5 | BIT4)
+#define B_GPIO_RESET_CONFIG_GPP_RESET_MASK (BIT3 | BIT2)
+#define N_GPIO_ELECTRICAL_CONFIG_TERMINATION_BIT_POS 0
+#define N_GPIO_OTHER_CONFIG_RXRAW_BIT_POS 0
+#define B_GPIO_GPIO_IOSTANDBY_STATE_MASK ((0xF << 1) | 0x01)
+#define B_GPIO_GPIO_IOSTANDBY_STATE_POS 0
+#define B_GPIO_GPIO_IOSTANDBY_TERM_MASK ((0x2 << 1) | 0x01)
+#define B_GPIO_GPIO_IOSTANDBY_TERM_POS 0
+
+//
+// Structure for storing information about registers offset, community,
+// maximal pad number for available groups
+//
+typedef struct {
+ PCH_SBI_PID Community;
+ UINT16 PadOwnOffset;
+ UINT16 HostOwnOffset;
+ UINT16 GpiIsOffset;
+ UINT16 GpiIeOffset;
+ UINT16 GpiGpeStsOffset;
+ UINT16 GpiGpeEnOffset;
+ UINT16 SmiStsOffset;
+ UINT16 SmiEnOffset;
+ UINT16 NmiStsOffset;
+ UINT16 NmiEnOffset;
+ UINT16 PadCfgLockOffset;
+ UINT16 PadCfgLockTxOffset;
+ UINT16 PadCfgOffset;
+ UINT16 PadPerGroup;
+} GPIO_GROUP_INFO;
+
+//
+// If in GPIO_GROUP_INFO structure certain register doesn't exist
+// it will have value equal to NO_REGISTER_FOR_PROPERTY
+//
+#define NO_REGISTER_FOR_PROPERTY 0xFFFF
+
+#define GPIO_PAD_DEF(Group,Pad) (UINT32)(((Group) << 16) + (Pad))
+#define GPIO_GROUP_DEF(GroupIndex,ChipsetId) ((GroupIndex) | ((ChipsetId) << 8))
+#define GPIO_GET_GROUP_INDEX(Group) ((Group) & 0x1F)
+#define GPIO_GET_GROUP_FROM_PAD(GpioPad) (((GpioPad) & 0x0F1F0000) >> 16)
+#define GPIO_GET_GROUP_INDEX_FROM_PAD(GpioPad) GPIO_GET_GROUP_INDEX (GPIO_GET_GROUP_FROM_PAD(GpioPad))
+#define GPIO_GET_PAD_NUMBER(GpioPad) ((GpioPad) & 0x1FF)
+#define GPIO_GET_CHIPSET_ID(GpioPad) (((GpioPad) >> 24) & 0xF)
+
+#define GPIO_GET_PAD_POSITION(PadNumber) ((PadNumber) % 32)
+#define GPIO_GET_DW_NUM(PadNumber) ((PadNumber) / 32u)
+
+/**
+ This procedure will retrieve address and length of GPIO info table
+
+ @param[out] GpioGroupInfoTableLength Length of GPIO group table
+
+ @retval Pointer to GPIO group table
+**/
+CONST GPIO_GROUP_INFO*
+GpioGetGroupInfoTable (
+ OUT UINT32 *GpioGroupInfoTableLength
+ );
+
+typedef struct {
+ CONST CHAR8* GpioGroupPrefix;
+ CONST GPIO_PAD FirstUniqueGpio;
+ CONST CHAR8** GroupUniqueNames;
+ CONST UINT32 UniqueNamesTableSize;
+} GPIO_GROUP_NAME_INFO;
+
+//
+// Helper macros for initializing GPIO_GROUP_NAME_INFO structures
+//
+#define GPIO_GROUP_NAME(GroupName,FirstUniqueGpio,GroupUniqueNamesTable) \
+ {GroupName, FirstUniqueGpio, GroupUniqueNamesTable, ARRAY_SIZE (GroupUniqueNamesTable)}
+
+#define GPIO_GROUP_NAME_BASIC(GroupName) \
+ {GroupName, 0, NULL, 0}
+
+/**
+ Returns GPIO_GROUP_NAME_INFO corresponding to the give GpioPad
+
+ @param[in] GroupIndex Group index
+
+ @retval GPIO_GROUP_NAME_INFO* Pointer to the GPIO_GROUP_NAME_INFO
+ @retval NULL If no group descriptor was found
+**/
+CONST
+GPIO_GROUP_NAME_INFO*
+GpioGetGroupNameInfo (
+ IN UINT32 GroupIndex
+ );
+
+/**
+ Get GPIO Chipset ID specific to PCH generation and series
+**/
+UINT32
+GpioGetThisChipsetId (
+ VOID
+ );
+
+/**
+ This procedure is used to check if GpioPad is valid for certain chipset
+
+ @param[in] GpioPad GPIO pad
+
+ @retval TRUE This pin is valid on this chipset
+ FALSE Incorrect pin
+**/
+BOOLEAN
+GpioIsCorrectPadForThisChipset (
+ IN GPIO_PAD GpioPad
+ );
+
+/**
+ Generates GPIO name from GpioPad
+ This function returns pointer to the static buffer.
+
+ @param[in] GpioPad GpioPad
+
+ @retval CHAR8* Pointer to the GPIO name
+**/
+CHAR8*
+GpioName (
+ IN GPIO_PAD GpioPad
+ );
+
+/**
+ Generates GPIO name from GpioNativePad
+ This function returns pointer to the static buffer.
+
+ @param[in] GpioNativePad GpioNativePad
+
+ @retval CHAR8* Pointer to the GPIO name
+**/
+CHAR8*
+GpioPinMuxName (
+ IN GPIO_NATIVE_PAD GpioNativePad
+ );
+
+/**
+ Generates GPIO Pad Termination string
+ This function returns pointer to the static buffer.
+
+ @param[in] GpioPadTermination GPIO Pad Termination
+
+ @retval CHAR8* Painter to the pad termianation string
+**/
+CHAR8*
+GpioGetPadTerminationString (
+ IN GPIO_ELECTRICAL_CONFIG PadTermination
+ );
+
+/**
+ This procedure will get value of selected gpio register
+
+ @param[in] Group GPIO group number
+ @param[in] Offset GPIO register offset
+ @param[out] RegVal Value of gpio register
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioGetReg (
+ IN GPIO_GROUP Group,
+ IN UINT32 Offset,
+ OUT UINT32 *RegVal
+ );
+
+/**
+ This procedure will set value of selected gpio register
+
+ @param[in] Group GPIO group number
+ @param[in] Offset GPIO register offset
+ @param[in] RegVal Value of gpio register
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioSetReg (
+ IN GPIO_GROUP Group,
+ IN UINT32 Offset,
+ IN UINT32 RegVal
+ );
+
+/**
+ This procedure is used by PchSmiDispatcher and will return information
+ needed to register GPI SMI.
+
+ @param[in] Index GPI SMI number
+ @param[out] GpioPin GPIO pin
+ @param[out] GpiSmiBitOffset GPI SMI bit position within GpiSmi Registers
+ @param[out] GpiHostSwOwnRegAddress Address of HOSTSW_OWN register
+ @param[out] GpiSmiStsRegAddress Address of GPI SMI status register
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioGetPadAndSmiRegs (
+ IN UINT32 Index,
+ OUT GPIO_PAD *GpioPin,
+ OUT UINT8 *GpiSmiBitOffset,
+ OUT UINT32 *GpiHostSwOwnRegAddress,
+ OUT UINT32 *GpiSmiStsRegAddress
+ );
+
+/**
+ This procedure will set GPIO Driver IRQ number
+
+ @param[in] Irq Irq number
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid IRQ number
+**/
+EFI_STATUS
+GpioSetIrq (
+ IN UINT8 Irq
+ );
+
+/**
+ This function provides GPIO Community PortIDs
+
+ @param[out] NativePinsTable Table with GPIO COMMx SBI PortIDs
+
+ @retval Number of communities
+**/
+UINT32
+GpioGetComSbiPortIds (
+ OUT PCH_SBI_PID **GpioComSbiIds
+ );
+
+/**
+ This function provides list of GPIO for which IO Standby State configuration
+ has to be set as 'Masked'
+
+ @param[out] GpioPadsList Table with pads
+
+ @retval Number of pads
+**/
+UINT32
+GpioGetIoStandbyStateConfigurationPadsList (
+ OUT GPIO_PAD_NATIVE_FUNCTION **GpioPadsList
+ );
+
+
+/**
+ This procedure will perform special handling of GPP_A_12.
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+GpioA12SpecialHandling (
+ VOID
+ );
+
+//
+// Structure which stores information needed to map GPIO Group
+// to 1-Tier GPE. Configuration is needed both in PMC and GPIO IP.
+// Because GPE_DWx can handle only 32 pins only single double word can
+// be mapped at a time. Each DW for a group has different configuration in PMC and GPIO
+//
+typedef struct {
+ GPIO_GROUP Group;
+ UINT8 GroupDw;
+ UINT8 PmcGpeDwxVal;
+} GPIO_GROUP_TO_GPE_MAPPING;
+
+/**
+ Get information for GPIO Group required to program GPIO and PMC for desired 1-Tier GPE mapping
+
+ @param[out] GpioGroupToGpeMapping Table with GPIO Group to GPE mapping
+ @param[out] GpioGroupToGpeMappingLength GPIO Group to GPE mapping table length
+**/
+VOID
+GpioGetGroupToGpeMapping (
+ OUT GPIO_GROUP_TO_GPE_MAPPING **GpioGroupToGpeMapping,
+ OUT UINT32 *GpioGroupToGpeMappingLength
+ );
+
+/**
+ This procedure will return Port ID of GPIO Community from GpioPad
+
+ @param[in] GpioPad GpioPad
+
+ @retval GpioCommunityPortId Port ID of GPIO Community
+**/
+UINT8
+GpioGetGpioCommunityPortIdFromGpioPad (
+ IN GPIO_PAD GpioPad
+ );
+
+/**
+ This procedure will return PadCfg address from GpioPad
+
+ @param[in] GpioPad GpioPad
+
+ @retval GpioPadCfgAddress PadCfg Address of GpioPad
+**/
+UINT32
+GpioGetGpioPadCfgAddressFromGpioPad (
+ IN GPIO_PAD GpioPad
+ );
+
+/**
+ This procedure is used to unlock all GPIO pads.
+ This function can only be called when platform is still in HOSTIA_BOOT_SAI.
+**/
+VOID
+GpioUnlockAllPads (
+ VOID
+ );
+
+/**
+ This procedure will check if GpioPad is owned by host.
+
+ @param[in] GpioPad GPIO pad
+
+ @retval TRUE GPIO pad is owned by host
+ @retval FALSE GPIO pad is not owned by host and should not be used with GPIO lib API
+**/
+BOOLEAN
+GpioIsPadHostOwned (
+ IN GPIO_PAD GpioPad
+ );
+
+
+/**
+ This procedure will check if GpioPad argument is valid.
+ Function will check below conditions:
+ - GpioPad represents a pad for current PCH
+ - GpioPad belongs to valid GpioGroup
+ - GPIO PadNumber is not greater than number of pads for this group
+
+ @param[in] GpioPad GPIO pad
+
+ @retval TRUE GPIO pad is valid and can be used with GPIO lib API
+ @retval FALSE GPIO pad is invalid and cannot be used with GPIO lib API
+**/
+BOOLEAN
+GpioIsPadValid (
+ IN GPIO_PAD GpioPad
+ );
+
+/**
+ This procedure will read GPIO Pad Configuration register
+
+ @param[in] GpioPad GPIO pad
+ @param[in] DwReg Choose PADCFG register: 0:DW0, 1:DW1
+
+ @retval PadCfgRegValue PADCFG_DWx value
+**/
+UINT32
+GpioReadPadCfgReg (
+ IN GPIO_PAD GpioPad,
+ IN UINT8 DwReg
+ );
+
+/**
+ This procedure will write or read GPIO Pad Configuration register
+
+ @param[in] GpioPad GPIO pad
+ @param[in] DwReg Choose PADCFG register: 0:DW0, 1:DW1
+ @param[in] PadCfgAndMask Mask to be AND'ed with PADCFG reg value
+ @param[in] PadCfgOrMask Mask to be OR'ed with PADCFG reg value
+
+ @retval none
+**/
+VOID
+GpioWritePadCfgReg (
+ IN GPIO_PAD GpioPad,
+ IN UINT8 DwReg,
+ IN UINT32 PadCfgAndMask,
+ IN UINT32 PadCfgOrMask
+ );
+
+/**
+ This procedure will Enable USB Virtual Wire Overcurrent pin
+
+ @param[in] GpioPad GPIO Pad
+
+ @retval EFI_SUCCESS
+**/
+EFI_STATUS
+GpioSetVwOverCurrentPin (
+ IN GPIO_VWOC_FUNCTION GpioPad
+ );
+
+/**
+ This procedure will set Native Function IOSF-SB Virtual Wire Message Generation bit
+ in DW0 of requested GPIO Pad
+
+ @param[in] GPIO_PAD GpioPad
+**/
+VOID
+GpioSetNafVweBit (
+ IN CONST GPIO_PAD PadCfg
+ );
+
+/**
+ This procedure will set GPIO mode
+
+ @param[in] GpioPad GPIO pad
+ @param[in] PadModeValue GPIO pad mode value
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioSetPadMode (
+ IN GPIO_PAD GpioPad,
+ IN GPIO_PAD_MODE PadModeValue
+ );
+
+/**
+ This procedure will set GPIO pad to native mode.
+ To be used if no other settings are to be configured when enabling native mode.
+
+ @param[in] GpioNativePad GPIO Pad with native mode information
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioSetNativePad (
+ IN GPIO_NATIVE_PAD GpioNativePad
+ );
+
+/**
+ This procedure will set GPIO pad to native function based on provided native function
+ and platform muxing selection (if needed).
+
+ @param[in] PadFunction PadMode for a specific native signal. Please refer to GpioNativePads.h
+ @param[in] PinMux GPIO Native pin mux platform config.
+ This argument is optional and needs to be
+ provided only if feature can be enabled
+ on multiple pads
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioSetNativePadByFunction (
+ IN UINT32 PadFunction,
+ IN UINT32 PinMux
+ );
+
+/**
+ This procedure will get GPIO mode
+
+ @param[in] GpioPad GPIO pad
+ @param[out] PadModeValue GPIO pad mode value
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioGetPadMode (
+ IN GPIO_PAD GpioPad,
+ OUT GPIO_PAD_MODE *PadModeValue
+ );
+
+/**
+ This procedure will check if group is within DeepSleepWell.
+
+ @param[in] Group GPIO Group
+
+ @retval GroupWell TRUE: This is DSW Group
+ FALSE: This is not DSW Group
+**/
+BOOLEAN
+GpioIsDswGroup (
+ IN GPIO_GROUP Group
+ );
+
+/**
+ The function performs GPIO Power Management programming.
+**/
+VOID
+GpioConfigurePm (
+ VOID
+ );
+
+/**
+ This function performs initial IO Standby State related configurations
+**/
+VOID
+GpioConfigureIoStandbyState (
+ VOID
+ );
+
+/**
+ This function enables SCS SD Card controller card detect pin
+
+ @param[in] none
+
+ @retval Status
+**/
+EFI_STATUS
+GpioEnableScsSdCardDetect (
+ VOID
+ );
+
+/**
+ This function sets HDA SSP interface pins into native mode
+
+ @param[in] SspInterfaceNumber SSPx interface number
+
+ @retval Status
+**/
+EFI_STATUS
+GpioEnableHdaSsp (
+ IN UINT32 SspInterfaceNumber
+ );
+
+/**
+ This function sets HDA SSP Master Clock into native mode
+
+ @param[in] MclkIndex MCLK index
+
+ @retval Status
+**/
+EFI_STATUS
+GpioEnableHdaSspMasterClock (
+ IN UINT32 MclkIndex
+ );
+
+/**
+ This function sets HDA SoundWire interface pins into native mode
+
+ @param[in] SndwInterfaceNumber SNDWx interface number
+
+ @retval Status
+**/
+EFI_STATUS
+GpioEnableHdaSndw (
+ IN UINT32 SndwInterfaceNumber
+ );
+
+/**
+ This function provides SPI IO pin for Touch Host Controller
+
+ @param[in] SpiIndex SPI1 or SPI2 - 0 or 1
+ @param[in] IoIndex IoIndex Valid from 0 (SPI_IO_0) to 3 (SPI_IO_3)
+
+ @retval NativePin Native Pin Configuration, 0 if SpiIndex or IoIndex is invalid
+**/
+GPIO_PAD_NATIVE_FUNCTION
+GpioGetThcSpiIo (
+ IN UINT32 SpiIndex,
+ IN UINT32 IoIndex
+ );
+
+/**
+ This function provides SPI ChipSelect pin for Touch Host Controller
+
+ @param[in] SpiIndex SPI1 or SPI2 - 0 or 1
+
+ @retval NativePin Native Pin Configuration, 0 if SpiIndex is invalid
+**/
+GPIO_PAD_NATIVE_FUNCTION
+GpioGetThcSpiCs (
+ IN UINT32 SpiIndex
+ );
+
+/**
+ This function provides SPI Clock pin for Touch Host Controller
+
+ @param[in] SpiIndex SPI1 or SPI2 - 0 or 1
+
+ @retval NativePin Native Pin Configuration, 0 if SpiIndex is invalid
+**/
+GPIO_PAD_NATIVE_FUNCTION
+GpioGetThcSpiClk (
+ IN UINT32 SpiIndex
+ );
+
+/**
+ This function provides SPI Reset pin for Touch Host Controller
+
+ @param[in] SpiIndex SPI1 or SPI2 - 0 or 1
+
+ @retval NativePin Native Pin Configuration, 0 if SpiIndex is invalid
+**/
+GPIO_PAD_NATIVE_FUNCTION
+GpioGetThcSpiReset (
+ IN UINT32 SpiIndex
+ );
+
+/**
+ This function sets SMBUS controller pins into native mode
+
+ @param[in] none
+
+ @retval Status
+**/
+EFI_STATUS
+GpioEnableSmbus (
+ VOID
+ );
+
+/**
+ This function sets SMBUS ALERT pins into native mode
+
+ @param[in] none
+
+ @retval Status
+**/
+EFI_STATUS
+GpioEnableSmbusAlert (
+ VOID
+ );
+
+/**
+ This function provides Serial GPIO pins
+
+ @param[in] SataCtrlIndex SATA controller index
+ @param[out] SgpioPins SATA Serial GPIO pins
+**/
+VOID
+GpioGetSataSgpioPins (
+ IN UINT32 SataCtrlIndex,
+ OUT SGPIO_PINS *SgpioPins
+ );
+
+/**
+ This function sets Serial GPIO pins into native mode
+
+ @param[in] SataCtrlIndex SATA controller index
+ @param[in] SataPort SATA port number
+
+ @retval Status
+**/
+EFI_STATUS
+GpioEnableSataSgpio (
+ IN UINT32 SataCtrlIndex
+ );
+
+/**
+ This function enables USB OverCurrent pins by setting
+ USB2 OCB pins into native mode
+
+ @param[in] OcPinNumber USB OC pin number
+
+ @retval Status
+**/
+EFI_STATUS
+GpioEnableUsbOverCurrent (
+ IN UINTN OcPinNumber
+ );
+
+/**
+ This function enables USB Virtual Wire OverCurrent pins by OcPinNumber.
+
+ @param[in] OcPinNumber USB OC pin number
+
+ @retval Status
+**/
+EFI_STATUS
+GpioEnableUsbVwOverCurrent (
+ IN UINTN OcPinNumber
+ );
+
+/**
+ This function sets SATA DevSlp pins into native mode
+
+ @param[in] SataCtrlIndex SATA controller index
+ @param[in] SataPort SATA port number
+ @param[in] ResetType GPIO reset type (see GPIO_RESET_CONFIG in GpioConfig.h)
+
+ @retval Status
+**/
+EFI_STATUS
+GpioEnableSataDevSlpPin (
+ IN UINT32 SataCtrlIndex,
+ IN UINTN SataPort,
+ IN UINT32 ResetType
+ );
+
+/**
+ This function checks if SataDevSlp pin is in native mode
+
+ @param[in] SataCtrlIndex SATA controller index
+ @param[in] SataPort SATA port
+ @param[out] DevSlpPad DevSlpPad
+ This is an optional parameter and may be NULL.
+
+ @retval TRUE DevSlp is in native mode
+ FALSE DevSlp is not in native mode
+**/
+BOOLEAN
+GpioIsSataDevSlpPinEnabled (
+ IN UINT32 SataCtrlIndex,
+ IN UINTN SataPort,
+ OUT GPIO_PAD *DevSlpPad OPTIONAL
+ );
+
+/**
+ This function sets SATAGPx pin into native mode
+
+ @param[in] SataCtrlIndex SATA controller index
+ @param[in] SataPort SATA port number
+
+ @retval Status
+**/
+EFI_STATUS
+GpioEnableSataGpPin (
+ IN UINT32 SataCtrlIndex,
+ IN UINTN SataPort
+ );
+
+/**
+ This function provides SATA GP pin data
+
+ @param[in] SataCtrlIndex SATA controller index
+ @param[in] SataPort SATA port number
+ @param[out] NativePin SATA GP pin
+**/
+VOID
+GpioGetSataGpPin (
+ IN UINT32 SataCtrlIndex,
+ IN UINTN SataPort,
+ OUT GPIO_PAD_NATIVE_FUNCTION *NativePin
+ );
+
+/**
+ This function sets SATA LED pin into native mode. SATA LED indicates
+ SATA controller activity
+
+ @param[in] SataCtrlIndex SATA controller index
+ @retval Status
+**/
+EFI_STATUS
+GpioEnableSataLed (
+ IN UINT32 SataCtrlIndex
+ );
+
+/**
+ Returns pad for given CLKREQ# index.
+
+ @param[in] ClkreqIndex CLKREQ# number
+
+ @return CLKREQ# pad.
+**/
+GPIO_PAD
+GpioGetClkreqPad (
+ IN UINT32 ClkreqIndex
+ );
+
+/**
+ Enables CLKREQ# pad in native mode.
+
+ @param[in] ClkreqIndex CLKREQ# number
+
+ @return none
+**/
+VOID
+GpioEnableClkreq (
+ IN UINT32 ClkreqIndex
+ );
+
+/**
+ This function sets PCHHOT pin into native mode
+
+ @param[in] none
+
+ @retval Status
+**/
+EFI_STATUS
+GpioEnablePchHot (
+ VOID
+ );
+
+/**
+ This function sets VRALERTB pin into native mode
+
+ @param[in] none
+
+ @retval Status
+**/
+EFI_STATUS
+GpioEnableVrAlert (
+ VOID
+ );
+
+/**
+ This function sets CPU GP pins into native mode
+
+ @param[in] CpuGpPinNum CPU GP pin number
+
+ @retval Status
+**/
+EFI_STATUS
+GpioEnableCpuGpPin (
+ IN UINT32 CpuGpPinNum
+ );
+
+/**
+This function sets CPU C10 Gate pins into native mode
+
+@retval Status
+**/
+EFI_STATUS
+GpioEnableCpuC10GatePin (
+ VOID
+ );
+
+//
+// DDPx pins
+//
+typedef enum {
+ GpioDdp1 = 0x01,
+ GpioDdp2 = 0x02,
+ GpioDdp3 = 0x03,
+ GpioDdp4 = 0x04,
+ GpioDdpA = 0x10,
+ GpioDdpB = 0x11,
+ GpioDdpC = 0x12,
+ GpioDdpD = 0x13,
+ GpioDdpF = 0x15,
+} GPIO_DDP;
+
+/**
+ This function sets DDP pins into native mode
+
+ @param[in] DdpInterface DDPx interface
+
+ @retval Status
+**/
+EFI_STATUS
+GpioEnableDpInterface (
+ IN GPIO_DDP DdpInterface
+ );
+
+//
+// DDI Port TBT_LSX interface
+//
+typedef enum {
+ GpioTbtLsxDdi1,
+ GpioTbtLsxDdi2,
+ GpioTbtLsxDdi3,
+ GpioTbtLsxDdi4,
+ GpioTbtLsxDdi5,
+ GpioTbtLsxDdi6
+} GPIO_TBT_LSX;
+
+/**
+ This function sets TBT_LSx pin into native mode
+
+ @param[in] TbtLsxDdiPort TBT_LSx DDI Port Number
+
+ @retval Status
+**/
+EFI_STATUS
+GpioEnableTbtLsxInterface (
+ IN GPIO_TBT_LSX TbtLsxDdiPort
+ );
+
+/**
+ This function configures GPIO connection between CNVi and CRF
+
+ @retval Status
+**/
+EFI_STATUS
+GpioConfigureCnviCrfConnection (
+ VOID
+ );
+
+/**
+ This function sets CNVi Bluetooth Enable value
+
+ @param[in] Value CNVi BT enable value
+ 0: Disable, 1: Enable
+ @retval Status
+**/
+EFI_STATUS
+GpioSetCnviBtEnState (
+ IN UINT32 Value
+ );
+
+/**
+ This function sets CNVi Bluetooth Wireless Charging support
+
+ @param[in] BtWirelessCharging CNVi BT Wireless Charging support
+ 0: Normal BT operation (no Wireless Charging support)
+ 1: Enable BT Wireless Charging
+ @retval Status
+**/
+EFI_STATUS
+GpioSetCnviBtWirelessCharging (
+ IN UINT32 BtWirelessCharging
+ );
+
+/**
+ This function enables and configures CNVi Bluetooth Host wake-up interrupt
+
+ @param[in] None
+
+ @retval Status
+**/
+EFI_STATUS
+GpioConfigureCnviBtHostWakeInt (
+ VOID
+ );
+
+/**
+ This function enables IMGU CLKOUT native pin
+
+ @param[in] ImguClkOutPinIndex The index of IMGU CLKOUT natine pin
+
+ @retval Status
+**/
+EFI_STATUS
+GpioEnableImguClkOut (
+ IN UINT8 ImguClkOutPinIndex
+ );
+
+/**
+ Power button debounce configuration
+ Debounce time can be specified in microseconds. Only certain values according
+ to below formula are supported:
+ DebounceTime = (2 ^ PADCFG_DW2.DEBOUNCE)*(glitch filter clock period).
+ RTC clock with f = 32 KHz is used for glitch filter.
+ DebounceTime = (2 ^ PADCFG_DW2.DEBOUNCE)*(31.25 us).
+ Supported DebounceTime values are following:
+ DebounceTime = 0 -> Debounce feature disabled
+ DebounceTime > 0 && < 250us -> Not supported
+ DebounceTime = 250us - 1024000us -> Supported range (DebounceTime = 250us * 2^n)
+ For values not supported by HW, they will be rounded down to closest supported one
+
+ @param[in] DebounceTime Debounce Time in microseconds
+ If Debounce Time = 0, Debouncer feature will be disabled
+ Function will set DebounceTime argument to rounded supported value
+**/
+VOID
+GpioSetPwrBtnDebounceTimer (
+ IN UINT32 DebounceTime
+ );
+
+
+/**
+ VCCIO level selection
+**/
+typedef enum {
+ GpioVcc3v3,
+ GpioVcc1v8,
+ MaxVccioSel
+} GPIO_VCCIO_SEL;
+/**
+ The function sets VCCIOSEL
+
+ @param[in] GpioPad GPIO pad
+ @param[in] VccioSel Pad voltage
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_UNSUPPORTED The Pin is owned by others
+ @retval EFI_INVALID_PARAMETER Invalid group or parameter
+**/
+EFI_STATUS
+GpioSetVccLevel (
+ IN GPIO_PAD GpioPad,
+ IN GPIO_VCCIO_SEL VccioSel
+ );
+
+/**
+ SBU (Sideband use) pins are used as auxiliary signals for Type C connector,
+ which are hard-wired to BSSB_LS natively for debug function.
+ when USB-C is enablde and debug not needed, disable pins (BSSB) used for debug through TypeC connector,
+ program SBU pins to high-Z/open circuit per USB-C spec.
+
+ @param[in] UsbTcPortEnBitmap USB Type C port enabled bitmap
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_UNSUPPORTED SBU pads are not supported
+ @retval EFI_INVALID_PARAMETER Invalid input parameter
+**/
+EFI_STATUS
+GpioDisableTypeCSbuDebug (
+ IN UINT32 UsbTcPortEnBitmap
+ );
+
+/**
+ When 2-wire DCI OOB is connected via SBU from Type C port, need set IO Standby state to masked (to operate as if no standby signal asserted)
+ to remain connection in low power state.
+
+ @param[in] DciPortId DCI connection port ID
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_UNSUPPORTED SBU pads are not supported
+ @retval EFI_INVALID_PARAMETER Invalid input parameter
+**/
+EFI_STATUS
+Gpio2WireDciOobSetting (
+ IN UINT8 DciPortId
+ );
+
+/**
+ This function enables the virtual wire msg bus from GPIO controller
+ to FIA. The virtual wire is used to transfer CLKREQ assert/de-assert
+ msg for CPU PCIe ports. Each of the PCIe ports has its dedicated VW
+ msg.
+
+ @param[in] PortIndex Index of the CPU PCIe port for which VW
+ should be enabled.
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_UNSUPPORTED Failed to set native mode.
+**/
+EFI_STATUS
+GpioEnableCpuPcieVwClkReqMsgBus (
+ IN UINT32 PortIndex
+ );
+
+/**
+ This function sets Time Sync Gpio into native mode
+
+ @param[in] Index index
+
+ @retval Status
+**/
+EFI_STATUS
+GpioEnableTimeSync (
+ IN UINT32 Index
+ );
+
+/**
+ This function sets Tsn into native mode
+
+ @retval Status
+**/
+EFI_STATUS
+GpioEnableTsn (
+ VOID
+ );
+
+/**
+ This function is to be used In GpioLockPads() to override a lock request by SOC code.
+
+ @param[in] Group GPIO group
+ @param[in] DwNum Register number for current group (parameter applicable in accessing whole register).
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[out] *UnlockCfgPad DWORD bitmask for pads which are going to be left unlocked
+ Bit position - PadNumber
+ Bit value - 0: to be locked, 1: Leave unlocked
+ @param[out] *UnlockTxPad DWORD bitmask for pads which are going to be left unlocked
+ Bit position - PadNumber
+ Bit value - 0: to be locked, 1: Leave unlocked
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid input parameter
+**/
+EFI_STATUS
+GpioUnlockOverride (
+ IN GPIO_GROUP Group,
+ IN UINT32 DwNum,
+ OUT UINT32 *UnlockCfgPad,
+ OUT UINT32 *UnlockTxPad
+ );
+
+/**
+ Check if 0x13 opcode supported for writing to GPIO lock unlock register
+
+ @retval TRUE It's supported
+ @retval FALSE It's not supported
+**/
+BOOLEAN
+IsGpioLockOpcodeSupported (
+ VOID
+ );
+
+/**
+ Configures IO standby related settings for the GPIO pad.
+
+ @param[in] GpioPad GPIO pad
+ @param[in] IoStandbyState GPIO pad IO Standby state
+ @param[in] IoStandbyTerm GPIO pad IO Standby termination
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioConfigurePadIoStandby (
+ IN GPIO_PAD GpioPad,
+ IN GPIO_IOSTANDBY_STATE IoStandbyState,
+ IN GPIO_IOSTANDBY_TERM IoStandbyTerm
+ );
+
+/**
+ Checks if GPIO PinMux corresponds to I2C4 B
+
+ @param[in] SdaPinMux GPIO pad pinmux for SDA
+ @param[in] SclPinMux GPIO pad pinmux for SCL
+
+ @retval TRUE PinMux corresponds to I2C4 B
+ FALSE PinMux equals to I2C4 A
+**/
+EFI_STATUS
+GpioIsSerialIoI2c4bMuxed (
+ IN UINT32 SdaPinMux,
+ IN UINT32 SclPinMux
+ );
+
+#endif // _GPIO_PRIVATE_LIB_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/Library/BaseGpioCheckConflictLib/BaseGpioCheckConflictLib.c b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/Library/BaseGpioCheckConflictLib/BaseGpioCheckConflictLib.c
new file mode 100644
index 0000000000..5a6360931b
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/Library/BaseGpioCheckConflictLib/BaseGpioCheckConflictLib.c
@@ -0,0 +1,140 @@
+/** @file
+ Implementation of BaseGpioCheckConflictLib.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/GpioCheckConflictLib.h>
+#include <Uefi/UefiMultiPhase.h>
+#include <Pi/PiBootMode.h>
+#include <Pi/PiHob.h>
+#include <Library/HobLib.h>
+#include <Library/DebugLib.h>
+#include <Library/GpioPrivateLib.h>
+
+/**
+ Check Gpio PadMode conflict and report it.
+
+ @retval none.
+**/
+VOID
+GpioCheckConflict (
+ VOID
+ )
+{
+ EFI_HOB_GUID_TYPE *GpioCheckConflictHob;
+ GPIO_PAD_MODE_INFO *GpioCheckConflictHobData;
+ UINT32 HobDataSize;
+ UINT32 GpioCount;
+ UINT32 GpioIndex;
+ GPIO_CONFIG GpioActualConfig;
+
+ GpioCheckConflictHob = NULL;
+ GpioCheckConflictHobData = NULL;
+
+ DEBUG ((DEBUG_INFO, "GpioCheckConflict Start..\n"));
+
+ //
+ // Use Guid to find HOB.
+ //
+ GpioCheckConflictHob = (EFI_HOB_GUID_TYPE *) GetFirstGuidHob (&gGpioCheckConflictHobGuid);
+ if (GpioCheckConflictHob == NULL) {
+ DEBUG ((DEBUG_INFO, "[GPIO Conflict Check] No GPIO HOB found.\n"));
+ } else {
+ while (GpioCheckConflictHob != NULL) {
+ //
+ // Find the Data area pointer and Data size from the Hob
+ //
+ GpioCheckConflictHobData = (GPIO_PAD_MODE_INFO *) GET_GUID_HOB_DATA (GpioCheckConflictHob);
+ HobDataSize = GET_GUID_HOB_DATA_SIZE (GpioCheckConflictHob);
+
+ GpioCount = HobDataSize / sizeof (GPIO_PAD_MODE_INFO);
+ DEBUG ((DEBUG_INFO, "[GPIO Conflict Check] Hob : GpioCount = %d\n", GpioCount));
+
+ //
+ // Probe Gpio entries in Hob and compare which are conflicted
+ //
+ for (GpioIndex = 0; GpioIndex < GpioCount ; GpioIndex++) {
+ GpioGetPadConfig (GpioCheckConflictHobData[GpioIndex].GpioPad, &GpioActualConfig);
+ if (GpioCheckConflictHobData[GpioIndex].GpioPadMode != GpioActualConfig.PadMode) {
+ DEBUG ((DEBUG_ERROR, "[GPIO Conflict Check] Identified conflict on pad %a (actual: 0x%X, expected: 0x%X)\n",
+ GpioName (GpioCheckConflictHobData[GpioIndex].GpioPad),
+ GpioActualConfig.PadMode,
+ GpioCheckConflictHobData[GpioIndex].GpioPadMode));
+ }
+ }
+ //
+ // Find next Hob and return the Hob pointer by the specific Hob Guid
+ //
+ GpioCheckConflictHob = GET_NEXT_HOB (GpioCheckConflictHob);
+ GpioCheckConflictHob = GetNextGuidHob (&gGpioCheckConflictHobGuid, GpioCheckConflictHob);
+ }
+
+ DEBUG ((DEBUG_INFO, "GpioCheckConflict End.\n"));
+ }
+
+ return;
+}
+
+/**
+ This libaray will create one Hob for each Gpio config table
+ without PadMode is GpioHardwareDefault
+
+ @param[in] GpioDefinition Point to Platform Gpio table
+ @param[in] GpioTableCount Number of Gpio table entries
+
+ @retval none.
+**/
+VOID
+CreateGpioCheckConflictHob (
+ IN GPIO_INIT_CONFIG *GpioDefinition,
+ IN UINT32 GpioTableCount
+ )
+{
+
+ UINT32 Index;
+ UINT32 GpioIndex;
+ GPIO_PAD_MODE_INFO *GpioCheckConflictHobData;
+ UINT16 GpioCount;
+
+ GpioCount = 0;
+ GpioIndex = 0;
+
+ DEBUG ((DEBUG_INFO, "CreateGpioCheckConflictHob Start \n"));
+
+ for (Index = 0; Index < GpioTableCount ; Index++) {
+ if (GpioDefinition[Index].GpioConfig.PadMode == GpioHardwareDefault) {
+ continue;
+ } else {
+ //
+ // Calculate non-default GPIO number
+ //
+ GpioCount++;
+ }
+ }
+
+ //
+ // Build a HOB tagged with a GUID for identification and returns
+ // the start address of GUID HOB data.
+ //
+ GpioCheckConflictHobData = (GPIO_PAD_MODE_INFO *) BuildGuidHob (&gGpioCheckConflictHobGuid , GpioCount * sizeof (GPIO_PAD_MODE_INFO));
+
+ //
+ // Record Non Default Gpio entries to the Hob
+ //
+ for (Index = 0; Index < GpioTableCount; Index++) {
+ if (GpioDefinition[Index].GpioConfig.PadMode == GpioHardwareDefault) {
+ continue;
+ } else {
+ if (GpioCheckConflictHobData != NULL) {
+ GpioCheckConflictHobData[GpioIndex].GpioPad = GpioDefinition[Index].GpioPad;
+ GpioCheckConflictHobData[GpioIndex].GpioPadMode = GpioDefinition[Index].GpioConfig.PadMode;
+ GpioIndex++;
+ }
+ }
+ }
+
+ DEBUG ((DEBUG_INFO, "CreateGpioCheckConflictHob End \n"));
+ return;
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/Library/BaseGpioCheckConflictLib/BaseGpioCheckConflictLib.inf b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/Library/BaseGpioCheckConflictLib/BaseGpioCheckConflictLib.inf
new file mode 100644
index 0000000000..f7e1de774d
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/Library/BaseGpioCheckConflictLib/BaseGpioCheckConflictLib.inf
@@ -0,0 +1,29 @@
+## @file
+# Component information file for BaseGpioCheckConflictLib.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+[Defines]
+ INF_VERSION = 0x00010017
+ BASE_NAME = BaseGpioCheckConflictLib
+ FILE_GUID = C19A848A-F013-4DBF-9C23-F0F74DEA6F14
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = GpioCheckConflictLib
+
+[LibraryClasses]
+ DebugLib
+ HobLib
+ GpioLib
+
+[Packages]
+ MdePkg/MdePkg.dec
+ TigerlakeSiliconPkg/SiPkg.dec
+
+[Sources]
+ BaseGpioCheckConflictLib.c
+
+[Guids]
+ gGpioCheckConflictHobGuid
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/Library/BaseGpioCheckConflictLibNull/BaseGpioCheckConflictLibNull.c b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/Library/BaseGpioCheckConflictLibNull/BaseGpioCheckConflictLibNull.c
new file mode 100644
index 0000000000..2f83f95b27
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/Library/BaseGpioCheckConflictLibNull/BaseGpioCheckConflictLibNull.c
@@ -0,0 +1,35 @@
+/** @file
+ Implementation of BaseGpioCheckConflicLibNull.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/GpioCheckConflictLib.h>
+
+/**
+ Check Gpio PadMode conflict and report it.
+**/
+VOID
+GpioCheckConflict (
+ VOID
+ )
+{
+ return;
+}
+
+/**
+ This libaray will create one Hob for each Gpio config table
+ without PadMode is GpioHardwareDefault
+
+ @param[in] GpioDefinition Point to Platform Gpio table
+ @param[in] GpioTableCount Number of Gpio table entries
+**/
+VOID
+CreateGpioCheckConflictHob (
+ IN GPIO_INIT_CONFIG *GpioDefinition,
+ IN UINT32 GpioTableCount
+ )
+{
+ return;
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/Library/BaseGpioCheckConflictLibNull/BaseGpioCheckConflictLibNull.inf b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/Library/BaseGpioCheckConflictLibNull/BaseGpioCheckConflictLibNull.inf
new file mode 100644
index 0000000000..1c226d7c16
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/Library/BaseGpioCheckConflictLibNull/BaseGpioCheckConflictLibNull.inf
@@ -0,0 +1,26 @@
+## @file
+# Component information file for BaseGpioCheckConflictLib.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+[Defines]
+ INF_VERSION = 0x00010017
+ BASE_NAME = BaseGpioCheckConflictLibNull
+ FILE_GUID = C19A848A-F013-4DBF-9C23-F0F74DEA6F14
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = GpioCheckConflictLib
+
+[LibraryClasses]
+ DebugLib
+ HobLib
+ GpioLib
+
+[Packages]
+ MdePkg/MdePkg.dec
+ TigerlakeSiliconPkg/SiPkg.dec
+
+[Sources]
+ BaseGpioCheckConflictLibNull.c
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/Library/PeiDxeSmmGpioLib/GpioInit.c b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/Library/PeiDxeSmmGpioLib/GpioInit.c
new file mode 100644
index 0000000000..99dbbf0ca6
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/Library/PeiDxeSmmGpioLib/GpioInit.c
@@ -0,0 +1,558 @@
+/** @file
+ This file contains routines for GPIO initialization
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include "GpioLibrary.h"
+#include <Register/PchPcrRegs.h>
+#include <Library/GpioCheckConflictLib.h>
+
+//
+// GPIO_GROUP_DW_DATA structure is used by GpioConfigurePch function
+// to cache values which will be programmed into respective GPIO registers
+// after all GpioPads are processed. This way MMIO accesses are decreased
+// and instead of doing one programming for one GpioPad there is only
+// one access for whole register.
+//
+typedef struct {
+ UINT32 HostSoftOwnReg;
+ UINT32 HostSoftOwnRegMask;
+ UINT32 GpiGpeEnReg;
+ UINT32 GpiGpeEnRegMask;
+ UINT32 GpiNmiEnReg;
+ UINT32 GpiNmiEnRegMask;
+ UINT32 GpiSmiEnReg;
+ UINT32 GpiSmiEnRegMask;
+ UINT32 ConfigUnlockMask;
+ UINT32 OutputUnlockMask;
+} GPIO_GROUP_DW_DATA;
+
+//
+// GPIO_GROUP_DW_NUMBER contains number of DWords required to
+// store Pad data for all groups. Each pad uses one bit.
+//
+#define GPIO_GROUP_DW_NUMBER 1
+
+/**
+ Get GPIO DW Register values (HOSTSW_OWN, GPE_EN, NMI_EN, Lock).
+
+ @param[in] PadNumber GPIO pad number
+ @param[in] GpioConfig GPIO Config data
+ @param[in out] DwRegsValues Values for GPIO DW Registers
+
+ @retval None
+**/
+STATIC
+VOID
+GpioDwRegValueFromGpioConfig (
+ IN UINT32 PadNumber,
+ IN CONST GPIO_CONFIG *GpioConfig,
+ IN OUT GPIO_GROUP_DW_DATA *GroupDwData
+ )
+{
+ UINT32 PadBitPosition;
+ UINT32 DwNum;
+
+ PadBitPosition = GPIO_GET_PAD_POSITION (PadNumber);
+ DwNum = GPIO_GET_DW_NUM (PadNumber);
+
+ if (DwNum >= GPIO_GROUP_DW_NUMBER) {
+ ASSERT (FALSE);
+ return;
+ }
+ //
+ // Update value to be programmed in HOSTSW_OWN register
+ //
+ GroupDwData[DwNum].HostSoftOwnRegMask |= (GpioConfig->HostSoftPadOwn & 0x1) << PadBitPosition;
+ GroupDwData[DwNum].HostSoftOwnReg |= (GpioConfig->HostSoftPadOwn >> 0x1) << PadBitPosition;
+
+ //
+ // Update value to be programmed in GPI_GPE_EN register
+ //
+ GroupDwData[DwNum].GpiGpeEnRegMask |= (GpioConfig->InterruptConfig & 0x1) << PadBitPosition;
+ GroupDwData[DwNum].GpiGpeEnReg |= ((GpioConfig->InterruptConfig & GpioIntSci) >> 3) << PadBitPosition;
+
+ //
+ // Update value to be programmed in GPI_NMI_EN register
+ //
+ GroupDwData[DwNum].GpiNmiEnRegMask |= (GpioConfig->InterruptConfig & 0x1) << PadBitPosition;
+ GroupDwData[DwNum].GpiNmiEnReg |= ((GpioConfig->InterruptConfig & GpioIntNmi) >> 1) << PadBitPosition;
+
+ //
+ // Update value to be programmed in GPI_SMI_EN register
+ GroupDwData[DwNum].GpiSmiEnRegMask |= (GpioConfig->InterruptConfig & 0x1) << PadBitPosition;
+ GroupDwData[DwNum].GpiSmiEnReg |= ((GpioConfig->InterruptConfig & GpioIntSmi) >> 2) << PadBitPosition;
+ if ((GpioConfig->InterruptConfig & GpioIntSmi) == GpioIntSmi) {
+ GroupDwData[DwNum].HostSoftOwnRegMask |= 1 << PadBitPosition;
+ GroupDwData[DwNum].HostSoftOwnReg |= 1 << PadBitPosition;
+ }
+
+ //
+ // Update information on Pad Configuration Lock
+ //
+ GroupDwData[DwNum].ConfigUnlockMask |= ((GpioConfig->LockConfig >> 1) & 0x1) << PadBitPosition;
+
+ //
+ // Update information on Pad Configuration Lock Tx
+ //
+ GroupDwData[DwNum].OutputUnlockMask |= ((GpioConfig->LockConfig >> 3) & 0x1) << PadBitPosition;
+
+ //
+ // if pad in GpioMode is an output default action should be to leave output unlocked
+ //
+ if ((GpioConfig->PadMode == GpioPadModeGpio) &&
+ (GpioConfig->Direction == GpioDirOut) &&
+ ((GpioConfig->LockConfig & B_GPIO_LOCK_CONFIG_OUTPUT_LOCK_MASK) == GpioLockDefault)) {
+ GroupDwData[DwNum].OutputUnlockMask |= 0x1 << PadBitPosition;
+ }
+}
+
+/**
+ This internal procedure will scan GPIO initialization table and unlock
+ all pads present in it
+
+ @param[in] NumberOfItem Number of GPIO pad records in table
+ @param[in] GpioInitTableAddress GPIO initialization table
+ @param[in] Index Index of GPIO Initialization table record
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+STATIC
+EFI_STATUS
+GpioUnlockPadsForAGroup (
+ IN UINT32 NumberOfItems,
+ IN GPIO_INIT_CONFIG *GpioInitTableAddress,
+ IN UINT32 Index
+ )
+{
+ UINT32 PadsToUnlock[GPIO_GROUP_DW_NUMBER];
+ UINT32 DwNum;
+ UINT32 PadBitPosition;
+ CONST GPIO_GROUP_INFO *GpioGroupInfo;
+ UINT32 GpioGroupInfoLength;
+ CONST GPIO_INIT_CONFIG *GpioData;
+ GPIO_GROUP Group;
+ UINT32 GroupIndex;
+ UINT32 PadNumber;
+
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+
+ GpioData = &GpioInitTableAddress[Index];
+ Group = GpioGetGroupFromGpioPad (GpioData->GpioPad);
+ GroupIndex = GpioGetGroupIndexFromGpioPad (GpioData->GpioPad);
+
+ ZeroMem (PadsToUnlock, sizeof (PadsToUnlock));
+ //
+ // Loop through pads for one group. If pad belongs to a different group then
+ // break and move to register programming.
+ //
+ while (Index < NumberOfItems) {
+
+ GpioData = &GpioInitTableAddress[Index];
+ if (GroupIndex != GpioGetGroupIndexFromGpioPad (GpioData->GpioPad)) {
+ //if next pad is from different group then break loop
+ break;
+ }
+
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioData->GpioPad);
+ //
+ // Check if legal pin number
+ //
+ if (PadNumber >= GpioGroupInfo[GroupIndex].PadPerGroup) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Pin number (%d) exceeds possible range for group %d\n", PadNumber, GroupIndex));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PadBitPosition = GPIO_GET_PAD_POSITION (PadNumber);
+ DwNum = GPIO_GET_DW_NUM (PadNumber);
+
+ if (DwNum >= GPIO_GROUP_DW_NUMBER) {
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+ //
+ // Update pads which need to be unlocked
+ //
+ PadsToUnlock[DwNum] |= 0x1 << PadBitPosition;
+
+ //Move to next item
+ Index++;
+ }
+
+ for (DwNum = 0; DwNum <= GPIO_GET_DW_NUM (GpioGroupInfo[GroupIndex].PadPerGroup); DwNum++) {
+ //
+ // Unlock pads
+ //
+ if (PadsToUnlock[DwNum] != 0) {
+ GpioUnlockPadCfgForGroupDw (Group, DwNum, PadsToUnlock[DwNum]);
+ GpioUnlockPadCfgTxForGroupDw (Group, DwNum, PadsToUnlock[DwNum]);
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will initialize multiple PCH GPIO pins
+
+ @param[in] NumberofItem Number of GPIO pads to be updated
+ @param[in] GpioInitTableAddress GPIO initialization table
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+STATIC
+EFI_STATUS
+GpioConfigurePch (
+ IN UINT32 NumberOfItems,
+ IN GPIO_INIT_CONFIG *GpioInitTableAddress
+ )
+{
+ UINT32 Index;
+ UINT32 PadCfgDwReg[GPIO_PADCFG_DW_REG_NUMBER];
+ UINT32 PadCfgDwRegMask[GPIO_PADCFG_DW_REG_NUMBER];
+ UINT32 PadCfgReg;
+ GPIO_GROUP_DW_DATA GroupDwData[GPIO_GROUP_DW_NUMBER];
+ UINT32 DwNum;
+ CONST GPIO_GROUP_INFO *GpioGroupInfo;
+ UINT32 GpioGroupInfoLength;
+ GPIO_PAD_OWN PadOwnVal;
+ CONST GPIO_INIT_CONFIG *GpioData;
+ UINT32 GroupIndex;
+ UINT32 PadNumber;
+ PCH_SBI_PID GpioCom;
+
+ PadOwnVal = GpioPadOwnHost;
+
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+
+ Index = 0;
+ while (Index < NumberOfItems) {
+
+ GpioData = &GpioInitTableAddress[Index];
+ GroupIndex = GpioGetGroupIndexFromGpioPad (GpioData->GpioPad);
+ GpioCom = GpioGroupInfo[GroupIndex].Community;
+
+ DEBUG_CODE_BEGIN();
+ if (!GpioIsCorrectPadForThisChipset (GpioData->GpioPad)) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Incorrect GpioPad (0x%08x) used on this chipset!\n", GpioData->GpioPad));
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+ DEBUG_CODE_END ();
+
+ //
+ // Unlock pads for a given group which are going to be reconfigured
+ //
+ //
+ // Because PADCFGLOCK/LOCKTX register reset domain is Powergood, lock settings
+ // will get back to default only after G3 or DeepSx transition. On the other hand GpioPads
+ // configuration is controlled by a configurable type of reset - PadRstCfg. This means that if
+ // PadRstCfg != Powergood GpioPad will have its configuration locked despite it being not the
+ // one desired by BIOS. Before reconfiguring all pads they will get unlocked.
+ //
+ GpioUnlockPadsForAGroup (NumberOfItems, GpioInitTableAddress, Index);
+
+ ZeroMem (GroupDwData, sizeof (GroupDwData));
+ //
+ // Loop through pads for one group. If pad belongs to a different group then
+ // break and move to register programming.
+ //
+ while (Index < NumberOfItems) {
+
+ GpioData = &GpioInitTableAddress[Index];
+ if (GroupIndex != GpioGetGroupIndexFromGpioPad (GpioData->GpioPad)) {
+ //if next pad is from different group then break loop
+ break;
+ }
+
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioData->GpioPad);
+
+ DEBUG_CODE_BEGIN ();
+ //
+ // Check if legal pin number
+ //
+ if (PadNumber >= GpioGroupInfo[GroupIndex].PadPerGroup) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Pin number (%d) exceeds possible range for group %d\n", PadNumber, GroupIndex));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check if selected GPIO Pad is not owned by CSME/ISH
+ //
+ GpioGetPadOwnership (GpioData->GpioPad, &PadOwnVal);
+
+ if (PadOwnVal != GpioPadOwnHost) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Accessing pad not owned by host (Group=%d, Pad=%d)!\n", GroupIndex, PadNumber));
+ DEBUG ((DEBUG_ERROR, "** Please make sure the GPIO usage in sync between CSME and BIOS configuration. \n"));
+ DEBUG ((DEBUG_ERROR, "** All the GPIO occupied by CSME should not do any configuration by BIOS.\n"));
+ //Move to next item
+ Index++;
+ continue;
+ }
+
+ //
+ // Check if Pad enabled for SCI is to be in unlocked state
+ //
+ if (((GpioData->GpioConfig.InterruptConfig & GpioIntSci) == GpioIntSci) &&
+ ((GpioData->GpioConfig.LockConfig & B_GPIO_LOCK_CONFIG_PAD_CONF_LOCK_MASK) != GpioPadConfigUnlock)){
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: %a used for SCI is not unlocked!\n", GpioName (GpioData->GpioPad)));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+ DEBUG_CODE_END ();
+
+ ZeroMem (PadCfgDwReg, sizeof (PadCfgDwReg));
+ ZeroMem (PadCfgDwRegMask, sizeof (PadCfgDwRegMask));
+ //
+ // Get GPIO PADCFG register value from GPIO config data
+ //
+ GpioPadCfgRegValueFromGpioConfig (
+ GpioData->GpioPad,
+ &GpioData->GpioConfig,
+ PadCfgDwReg,
+ PadCfgDwRegMask
+ );
+
+ //
+ // Create PADCFG register offset using group and pad number
+ //
+ PadCfgReg = S_GPIO_PCR_PADCFG * PadNumber + GpioGroupInfo[GroupIndex].PadCfgOffset;
+
+ //
+ // Write PADCFG DW0 register
+ //
+ MmioAndThenOr32 (
+ PCH_PCR_ADDRESS (GpioCom, PadCfgReg),
+ ~PadCfgDwRegMask[0],
+ PadCfgDwReg[0]
+ );
+ //
+ // Write PADCFG DW1 register
+ //
+ MmioAndThenOr32 (
+ PCH_PCR_ADDRESS (GpioCom, PadCfgReg + 0x4),
+ ~PadCfgDwRegMask[1],
+ PadCfgDwReg[1]
+ );
+
+ //
+ // Write PADCFG DW2 register
+ //
+ MmioAndThenOr32 (
+ PCH_PCR_ADDRESS (GpioCom, PadCfgReg + 0x8),
+ ~PadCfgDwRegMask[2],
+ PadCfgDwReg[2]
+ );
+
+ //
+ // Get GPIO DW register values from GPIO config data
+ //
+ GpioDwRegValueFromGpioConfig (
+ PadNumber,
+ &GpioData->GpioConfig,
+ GroupDwData
+ );
+
+ //Move to next item
+ Index++;
+ }
+
+ for (DwNum = 0; DwNum <= GPIO_GET_DW_NUM (GpioGroupInfo[GroupIndex].PadPerGroup); DwNum++) {
+ //
+ // Write HOSTSW_OWN registers
+ //
+ if (GpioGroupInfo[GroupIndex].HostOwnOffset != NO_REGISTER_FOR_PROPERTY) {
+ MmioAndThenOr32 (
+ PCH_PCR_ADDRESS (GpioCom, GpioGroupInfo[GroupIndex].HostOwnOffset + DwNum * 0x4),
+ ~GroupDwData[DwNum].HostSoftOwnRegMask,
+ GroupDwData[DwNum].HostSoftOwnReg
+ );
+ }
+
+ //
+ // Write GPI_GPE_EN registers
+ //
+ if (GpioGroupInfo[GroupIndex].GpiGpeEnOffset != NO_REGISTER_FOR_PROPERTY) {
+ MmioAndThenOr32 (
+ PCH_PCR_ADDRESS (GpioCom, GpioGroupInfo[GroupIndex].GpiGpeEnOffset + DwNum * 0x4),
+ ~GroupDwData[DwNum].GpiGpeEnRegMask,
+ GroupDwData[DwNum].GpiGpeEnReg
+ );
+ }
+
+ //
+ // Write GPI_NMI_EN registers
+ //
+ if (GpioGroupInfo[GroupIndex].NmiEnOffset != NO_REGISTER_FOR_PROPERTY) {
+ MmioAndThenOr32 (
+ PCH_PCR_ADDRESS (GpioCom, GpioGroupInfo[GroupIndex].NmiEnOffset + DwNum * 0x4),
+ ~GroupDwData[DwNum].GpiNmiEnRegMask,
+ GroupDwData[DwNum].GpiNmiEnReg
+ );
+ } else if (GroupDwData[DwNum].GpiNmiEnReg != 0x0) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Group %d has no pads supporting NMI\n", GroupIndex));
+ ASSERT_EFI_ERROR (EFI_UNSUPPORTED);
+ }
+
+ //
+ // Write GPI_SMI_EN registers
+ //
+ if (GpioGroupInfo[GroupIndex].SmiEnOffset != NO_REGISTER_FOR_PROPERTY) {
+ MmioAndThenOr32 (
+ PCH_PCR_ADDRESS (GpioCom, GpioGroupInfo[GroupIndex].SmiEnOffset + DwNum * 0x4),
+ ~GroupDwData[DwNum].GpiSmiEnRegMask,
+ GroupDwData[DwNum].GpiSmiEnReg
+ );
+ } else if (GroupDwData[DwNum].GpiSmiEnReg != 0x0) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Group %d has no pads supporting SMI\n", GroupIndex));
+ ASSERT_EFI_ERROR (EFI_UNSUPPORTED);
+ }
+
+ //
+ // Update Pad Configuration unlock data
+ //
+ if (GroupDwData[DwNum].ConfigUnlockMask) {
+ GpioStoreGroupDwUnlockPadConfigData (GroupIndex, DwNum, GroupDwData[DwNum].ConfigUnlockMask);
+ }
+
+ //
+ // Update Pad Output unlock data
+ //
+ if (GroupDwData[DwNum].OutputUnlockMask) {
+ GpioStoreGroupDwUnlockOutputData (GroupIndex, DwNum, GroupDwData[DwNum].OutputUnlockMask);
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will clear all status bits of any GPIO interrupts.
+
+ @param[in] none
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+STATIC
+EFI_STATUS
+GpioClearAllGpioInterrupts (
+ VOID
+ )
+{
+ GPIO_GROUP Group;
+ CONST GPIO_GROUP_INFO *GpioGroupInfo;
+ GPIO_GROUP GpioGroupLowest;
+ GPIO_GROUP GpioGroupHighest;
+ UINT32 GroupIndex;
+ UINT32 GpioGroupInfoLength;
+ UINT32 DwNum;
+
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+
+ GpioGroupLowest = GpioGetLowestGroup ();
+ GpioGroupHighest = GpioGetHighestGroup ();
+
+ for (Group = GpioGroupLowest; Group <= GpioGroupHighest; Group++) {
+ GroupIndex = GpioGetGroupIndexFromGroup (Group);
+ //
+ // Check if group has GPI IS register
+ //
+ if (GpioGroupInfo[GroupIndex].GpiIsOffset != NO_REGISTER_FOR_PROPERTY) {
+ //
+ // Clear all GPI_IS Status bits by writing '1'
+ //
+ for (DwNum = 0; DwNum <= GPIO_GET_DW_NUM (GpioGroupInfo[GroupIndex].PadPerGroup); DwNum++) {
+ MmioWrite32 (
+ PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, GpioGroupInfo[GroupIndex].GpiIsOffset + DwNum * 0x4),
+ 0xFFFFFFFF
+ );
+ }
+ }
+
+ //
+ // Check if group has GPI_GPE_STS register
+ //
+ if (GpioGroupInfo[GroupIndex].GpiGpeStsOffset != NO_REGISTER_FOR_PROPERTY) {
+ //
+ // Clear all GPI_GPE_STS Status bits by writing '1'
+ //
+ for (DwNum = 0; DwNum <= GPIO_GET_DW_NUM (GpioGroupInfo[GroupIndex].PadPerGroup); DwNum++) {
+ MmioWrite32 (
+ PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, GpioGroupInfo[GroupIndex].GpiGpeStsOffset + DwNum * 0x4),
+ 0xFFFFFFFF
+ );
+ }
+ }
+
+ //
+ // Check if group has SMI_STS register
+ //
+ if (GpioGroupInfo[GroupIndex].SmiStsOffset != NO_REGISTER_FOR_PROPERTY) {
+ //
+ // Clear all SMI_STS Status bits by writing '1'
+ //
+ for (DwNum = 0; DwNum <= GPIO_GET_DW_NUM (GpioGroupInfo[GroupIndex].PadPerGroup); DwNum++) {
+ MmioWrite32 (
+ PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, GpioGroupInfo[GroupIndex].SmiStsOffset + DwNum * 4),
+ 0xFFFFFFFF
+ );
+ }
+ }
+
+ //
+ // Check if group has NMI_STS register
+ //
+ if (GpioGroupInfo[GroupIndex].NmiStsOffset != NO_REGISTER_FOR_PROPERTY) {
+ //
+ // Clear all NMI_STS Status bits by writing '1'
+ //
+ for (DwNum = 0; DwNum <= GPIO_GET_DW_NUM (GpioGroupInfo[GroupIndex].PadPerGroup); DwNum++) {
+ MmioWrite32 (
+ PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, GpioGroupInfo[GroupIndex].NmiStsOffset + DwNum * 4),
+ 0xFFFFFFFF
+ );
+ }
+ }
+
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will initialize multiple GPIO pins. Use GPIO_INIT_CONFIG structure.
+ Structure contains fields that can be used to configure each pad.
+ Pad not configured using GPIO_INIT_CONFIG will be left with hardware default values.
+ Separate fields could be set to hardware default if it does not matter, except
+ GpioPad and PadMode.
+ Function will work in most efficient way if pads which belong to the same group are
+ placed in adjacent records of the table.
+ Although function can enable pads for Native mode, such programming is done
+ by reference code when enabling related silicon feature.
+
+ @param[in] NumberofItem Number of GPIO pads to be updated
+ @param[in] GpioInitTableAddress GPIO initialization table
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioConfigurePads (
+ IN UINT32 NumberOfItems,
+ IN GPIO_INIT_CONFIG *GpioInitTableAddress
+ )
+{
+ EFI_STATUS Status;
+
+ Status = GpioConfigurePch (NumberOfItems, GpioInitTableAddress);
+
+ CreateGpioCheckConflictHob (GpioInitTableAddress, NumberOfItems);
+
+ GpioClearAllGpioInterrupts ();
+ return Status;
+}
+
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/Library/PeiDxeSmmGpioLib/GpioLib.c b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/Library/PeiDxeSmmGpioLib/GpioLib.c
new file mode 100644
index 0000000000..d6c13fe581
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/Library/PeiDxeSmmGpioLib/GpioLib.c
@@ -0,0 +1,2387 @@
+/** @file
+ This file contains routines for GPIO
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include "GpioLibrary.h"
+#include <Register/PchPcrRegs.h>
+
+/**
+ This procedure will check if GpioGroup argument is correct and
+ supplied DW reg number can be used for this group to access DW registers.
+ Function will check below conditions:
+ - Valid GpioGroup
+ - DwNum is has valid value for this group
+
+ @param[in] Group GPIO group
+ @param[in] DwNum Register number for current group (parameter applicable in accessing whole register).
+ For group which has less then 32 pads per group DwNum must be 0.
+
+ @retval TRUE DW Reg number and GpioGroup is valid
+ @retval FALSE DW Reg number and GpioGroup is invalid
+**/
+STATIC
+BOOLEAN
+GpioIsGroupAndDwNumValid (
+ IN GPIO_GROUP Group,
+ IN UINT32 DwNum
+ )
+{
+ UINT32 GroupIndex;
+ CONST GPIO_GROUP_INFO *GpioGroupInfo;
+ UINT32 GpioGroupInfoLength;
+
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+
+ GroupIndex = GpioGetGroupIndexFromGroup (Group);
+
+ if ((Group < GpioGetLowestGroup ()) || (Group > GpioGetHighestGroup ()) || (GroupIndex >= GpioGroupInfoLength)) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Group argument (%d) is not within range of possible groups for this PCH\n", GroupIndex));
+ goto Error;
+ }
+
+ //
+ // Check if DwNum argument does not exceed number of DWord registers
+ // resulting from available pads for certain group
+ //
+ if (DwNum > GPIO_GET_DW_NUM (GpioGroupInfo[GroupIndex].PadPerGroup - 1)){
+ goto Error;
+ }
+
+ return TRUE;
+Error:
+ ASSERT (FALSE);
+ return FALSE;
+}
+
+//
+// Possible registers to be accessed using GpioReadReg()/GpioWriteReg() functions
+//
+typedef enum {
+ GpioHostOwnershipRegister = 0,
+ GpioGpeEnableRegister,
+ GpioGpeStatusRegister,
+ GpioSmiEnableRegister,
+ GpioSmiStatusRegister,
+ GpioNmiEnableRegister,
+ GpioPadConfigLockRegister,
+ GpioPadLockOutputRegister
+} GPIO_REG;
+
+/**
+ This procedure will read GPIO register
+
+ @param[in] RegType GPIO register type
+ @param[in] Group GPIO group
+ @param[in] DwNum Register number for current group (parameter applicable in accessing whole register).
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[out] ReadVal Read data
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_UNSUPPORTED Feature is not supported for this group or pad
+**/
+STATIC
+EFI_STATUS
+GpioReadReg (
+ IN GPIO_REG RegType,
+ IN GPIO_GROUP Group,
+ IN UINT32 DwNum,
+ OUT UINT32 *ReadVal
+ )
+{
+ UINT32 RegOffset;
+ UINT32 GroupIndex;
+ CONST GPIO_GROUP_INFO *GpioGroupInfo;
+ UINT32 GpioGroupInfoLength;
+
+ RegOffset = NO_REGISTER_FOR_PROPERTY;
+ GroupIndex = GpioGetGroupIndexFromGroup (Group);
+
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+
+ switch (RegType) {
+ case GpioHostOwnershipRegister:
+ RegOffset = GpioGroupInfo[GroupIndex].HostOwnOffset;
+ break;
+ case GpioGpeEnableRegister:
+ RegOffset = GpioGroupInfo[GroupIndex].GpiGpeEnOffset;
+ break;
+ case GpioGpeStatusRegister:
+ RegOffset = GpioGroupInfo[GroupIndex].GpiGpeStsOffset;
+ break;
+ case GpioSmiEnableRegister:
+ RegOffset = GpioGroupInfo[GroupIndex].SmiEnOffset;
+ break;
+ case GpioSmiStatusRegister:
+ RegOffset = GpioGroupInfo[GroupIndex].SmiStsOffset;
+ break;
+ case GpioNmiEnableRegister:
+ RegOffset = GpioGroupInfo[GroupIndex].NmiEnOffset;
+ break;
+ case GpioPadConfigLockRegister:
+ RegOffset = GpioGroupInfo[GroupIndex].PadCfgLockOffset;
+ break;
+ case GpioPadLockOutputRegister:
+ RegOffset = GpioGroupInfo[GroupIndex].PadCfgLockTxOffset;
+ break;
+ default:
+ break;
+ }
+
+ //
+ // Check if selected register exists
+ //
+ if (RegOffset == NO_REGISTER_FOR_PROPERTY) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // If there are more then 32 pads per group then certain
+ // group information would be split into more then one DWord register.
+ //
+ if ((RegType == GpioPadConfigLockRegister) || (RegType == GpioPadLockOutputRegister)) {
+ //
+ // PadConfigLock and OutputLock registers when used for group containing more than 32 pads
+ // are not placed in a continuous way, e.g:
+ // 0x0 - PadConfigLock_DW0
+ // 0x4 - OutputLock_DW0
+ // 0x8 - PadConfigLock_DW1
+ // 0xC - OutputLock_DW1
+ //
+ RegOffset += DwNum * 0x8;
+ } else {
+ RegOffset += DwNum * 0x4;
+ }
+
+ *ReadVal = MmioRead32 (PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, RegOffset));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will write GPIO register
+
+ @param[in] RegType GPIO register type
+ @param[in] Group GPIO group
+ @param[in] DwNum Register number for current group (parameter applicable in accessing whole register).
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[in] RegAndMask Mask which will be AND'ed with register value
+ @param[in] RegOrMask Mask which will be OR'ed with register value
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_UNSUPPORTED Feature is not supported for this group or pad
+**/
+STATIC
+EFI_STATUS
+GpioWriteReg (
+ IN GPIO_REG RegType,
+ IN GPIO_GROUP Group,
+ IN UINT32 DwNum,
+ IN UINT32 RegAndMask,
+ IN UINT32 RegOrMask
+ )
+{
+ UINT32 RegOffset;
+ UINT32 GroupIndex;
+ CONST GPIO_GROUP_INFO *GpioGroupInfo;
+ UINT32 GpioGroupInfoLength;
+ UINT32 PadCfgLock;
+ BOOLEAN Lockable;
+
+ Lockable = FALSE;
+ PadCfgLock = 0;
+ RegOffset = NO_REGISTER_FOR_PROPERTY;
+ GroupIndex = GpioGetGroupIndexFromGroup (Group);
+
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+
+ switch (RegType) {
+ case GpioHostOwnershipRegister:
+ RegOffset = GpioGroupInfo[GroupIndex].HostOwnOffset;
+ break;
+ case GpioGpeEnableRegister:
+ RegOffset = GpioGroupInfo[GroupIndex].GpiGpeEnOffset;
+ Lockable = TRUE;
+ break;
+ case GpioGpeStatusRegister:
+ RegOffset = GpioGroupInfo[GroupIndex].GpiGpeStsOffset;
+ break;
+ case GpioSmiEnableRegister:
+ RegOffset = GpioGroupInfo[GroupIndex].SmiEnOffset;
+ Lockable = TRUE;
+ break;
+ case GpioSmiStatusRegister:
+ RegOffset = GpioGroupInfo[GroupIndex].SmiStsOffset;
+ break;
+ case GpioNmiEnableRegister:
+ RegOffset = GpioGroupInfo[GroupIndex].NmiEnOffset;
+ Lockable = TRUE;
+ break;
+ case GpioPadConfigLockRegister:
+ case GpioPadLockOutputRegister:
+ default:
+ break;
+ }
+
+ //
+ // Check if selected register exists
+ //
+ if (RegOffset == NO_REGISTER_FOR_PROPERTY) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if (Lockable) {
+ GpioGetPadCfgLockForGroupDw (Group, DwNum, &PadCfgLock);
+ if (PadCfgLock) {
+ //
+ // Check if for pads which are going to be reconfigured lock is set.
+ //
+ if ((~RegAndMask | RegOrMask) & PadCfgLock) {
+ //
+ // Unlock all pads for this Group DW reg for simplicity
+ // even if not all of those pads will have their settings reprogrammed
+ //
+ GpioUnlockPadCfgForGroupDw (Group, DwNum, PadCfgLock);
+ } else {
+ //
+ // No need to perform an unlock as pads which are going to be reconfigured
+ // are not in locked state
+ //
+ PadCfgLock = 0;
+ }
+ }
+ }
+
+ //
+ // If there are more then 32 pads per group then certain
+ // group information would be split into more then one DWord register.
+ //
+ RegOffset += DwNum * 0x4;
+
+ MmioAndThenOr32 (
+ PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, RegOffset),
+ RegAndMask,
+ RegOrMask
+ );
+
+ if (Lockable && PadCfgLock) {
+ //
+ // Lock previously unlocked pads
+ //
+ GpioLockPadCfgForGroupDw (Group, DwNum, PadCfgLock);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will write GPIO Lock/LockTx register using SBI.
+
+ @param[in] RegType GPIO register (Lock or LockTx)
+ @param[in] Group GPIO group number
+ @param[in] DwNum Register number for current group.
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[in] LockRegAndMask Mask which will be AND'ed with Lock register value
+ @param[in] LockRegOrMask Mask which will be Or'ed with Lock register value
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_UNSUPPORTED Feature is not supported for this group or pad
+**/
+STATIC
+EFI_STATUS
+GpioWriteLockReg (
+ IN GPIO_REG RegType,
+ IN GPIO_GROUP Group,
+ IN UINT32 DwNum,
+ IN UINT32 LockRegAndMask,
+ IN UINT32 LockRegOrMask
+ )
+{
+ UINT8 Response;
+ CONST GPIO_GROUP_INFO *GpioGroupInfo;
+ UINT32 GpioGroupInfoLength;
+ UINT32 RegOffset;
+ UINT32 OldLockVal;
+ UINT32 NewLockVal;
+ UINT32 GroupIndex;
+ EFI_STATUS Status;
+ PCH_SBI_OPCODE Opcode;
+
+ OldLockVal = 0;
+ NewLockVal = 0;
+
+ RegOffset = NO_REGISTER_FOR_PROPERTY;
+ GroupIndex = GpioGetGroupIndexFromGroup (Group);
+
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+
+ switch (RegType) {
+ case GpioPadConfigLockRegister:
+ RegOffset = GpioGroupInfo[GroupIndex].PadCfgLockOffset;
+ GpioGetPadCfgLockForGroupDw (Group, DwNum, &OldLockVal);
+ break;
+ case GpioPadLockOutputRegister:
+ RegOffset = GpioGroupInfo[GroupIndex].PadCfgLockTxOffset;
+ GpioGetPadCfgLockTxForGroupDw (Group, DwNum, &OldLockVal);
+ break;
+ default:
+ break;
+ }
+
+ //
+ // Check if selected register exists
+ //
+ if (RegOffset == NO_REGISTER_FOR_PROPERTY) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // If there are more then 32 pads per group then certain
+ // group information would be split into more then one DWord register.
+ // PadConfigLock and OutputLock registers when used for group containing more than 32 pads
+ // are not placed in a continuous way, e.g:
+ // 0x0 - PadConfigLock_DW0
+ // 0x4 - OutputLock_DW0
+ // 0x8 - PadConfigLock_DW1
+ // 0xC - OutputLock_DW1
+ //
+ RegOffset += DwNum *0x8;
+
+ NewLockVal = (OldLockVal & LockRegAndMask) | LockRegOrMask;
+
+ if (IsGpioLockOpcodeSupported ()) {
+ Opcode = GpioLockUnlock;
+ } else {
+ Opcode = PrivateControlWrite;
+ }
+
+ Status = PchSbiExecutionEx (
+ GpioGroupInfo[GroupIndex].Community,
+ RegOffset,
+ Opcode,
+ FALSE,
+ 0x000F,
+ 0x0000,
+ 0x0000,
+ &NewLockVal,
+ &Response
+ );
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+/**
+ This internal procedure will calculate GPIO_RESET_CONFIG value (new type)
+ based on provided PadRstCfg for a specific GPIO Pad.
+
+ @param[in] GpioPad GPIO Pad
+ @param[in] PadRstCfg GPIO PadRstCfg value
+
+ @retval GpioResetConfig GPIO Reset configuration (new type)
+**/
+GPIO_RESET_CONFIG
+GpioResetConfigFromPadRstCfg (
+ IN GPIO_PAD GpioPad,
+ IN UINT32 PadRstCfg
+ )
+{
+ GPIO_GROUP Group;
+
+ static GPIO_RESET_CONFIG PadRstCfgToGpioResetConfigMap[] = {
+ GpioDswReset,
+ GpioHostDeepReset,
+ GpioPlatformReset,
+ GpioResumeReset};
+
+ Group = GpioGetGroupFromGpioPad (GpioPad);
+
+ if (PadRstCfg < 4) {
+ if (!GpioIsDswGroup(Group) && PadRstCfg == 3) {
+ DEBUG ((DEBUG_ERROR, "ERROR: Pad %a is configured to be reset by Global Reset without being part of DSW group\n", GpioName (GpioPad)));
+ }
+ return PadRstCfgToGpioResetConfigMap[PadRstCfg];
+ }
+ return GpioResetDefault;
+}
+
+/**
+ This internal procedure will calculate PadRstCfg register value based
+ on provided GPIO Reset configuration for a certain pad.
+
+ @param[in] GpioPad GPIO Pad
+ @param[in] GpioResetConfig GPIO Reset configuration
+ @param[out] PadRstCfg GPIO PadRstCfg value
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid configuration
+**/
+EFI_STATUS
+GpioPadRstCfgFromResetConfig (
+ IN GPIO_PAD GpioPad,
+ IN GPIO_RESET_CONFIG GpioResetConfig,
+ OUT UINT32 *PadRstCfg
+ )
+{
+ GPIO_GROUP Group;
+
+ Group = GpioGetGroupFromGpioPad (GpioPad);
+
+ switch (GpioResetConfig) {
+ case GpioResetDefault:
+ *PadRstCfg = 0x0;
+ break;
+ case GpioHostDeepReset:
+ *PadRstCfg = V_GPIO_PCR_RST_CONF_DEEP_RST;
+ break;
+ case GpioPlatformReset:
+ *PadRstCfg = V_GPIO_PCR_RST_CONF_GPIO_RST;
+ break;
+ case GpioResumeReset:
+ if (GpioIsDswGroup (Group)) {
+ *PadRstCfg = V_GPIO_PCR_RST_CONF_RESUME_RST;
+ } else {
+ *PadRstCfg = V_GPIO_PCR_RST_CONF_POW_GOOD;
+ }
+ break;
+ case GpioDswReset:
+ if (GpioIsDswGroup (Group)) {
+ *PadRstCfg = V_GPIO_PCR_RST_CONF_POW_GOOD;
+ } else {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Only GPD group pads can use GpioDswReset: %a\n", GpioName (GpioPad)));
+ goto Error;
+ }
+ break;
+ default:
+ goto Error;
+ }
+
+ return EFI_SUCCESS;
+Error:
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+}
+
+/**
+ This internal procedure will get GPIO_CONFIG data from PADCFG registers value
+
+ @param[in] GpioPad GPIO Pad
+ @param[in] PadCfgDwReg PADCFG DWx register values
+ @param[out] GpioData GPIO Configuration data
+
+ @retval Status
+**/
+STATIC
+VOID
+GpioConfigFromPadCfgRegValue (
+ IN GPIO_PAD GpioPad,
+ IN CONST UINT32 *PadCfgDwReg,
+ OUT GPIO_CONFIG *GpioConfig
+ )
+{
+ UINT32 PadRstCfg;
+
+ //
+ // Get Reset Type (PadRstCfg)
+ //
+ PadRstCfg = (PadCfgDwReg[0] & B_GPIO_PCR_RST_CONF) >> N_GPIO_PCR_RST_CONF;
+
+ GpioConfig->PowerConfig = GpioResetConfigFromPadRstCfg (
+ GpioPad,
+ PadRstCfg
+ );
+
+ //
+ // Get how interrupt is triggered (RxEvCfg)
+ //
+ GpioConfig->InterruptConfig = ((PadCfgDwReg[0] & B_GPIO_PCR_RX_LVL_EDG) >> (N_GPIO_PCR_RX_LVL_EDG - (N_GPIO_INT_CONFIG_INT_TYPE_BIT_POS + 1))) | (0x1 << N_GPIO_INT_CONFIG_INT_TYPE_BIT_POS);
+
+ //
+ // Get interrupt generation (GPIRoutIOxAPIC/SCI/SMI/NMI)
+ //
+ GpioConfig->InterruptConfig |= ((PadCfgDwReg[0] & (B_GPIO_PCR_RX_NMI_ROUTE | B_GPIO_PCR_RX_SCI_ROUTE | B_GPIO_PCR_RX_SMI_ROUTE | B_GPIO_PCR_RX_APIC_ROUTE)) >> (N_GPIO_PCR_RX_NMI_ROUTE - (N_GPIO_INT_CONFIG_INT_SOURCE_BIT_POS + 1))) | (0x1 << N_GPIO_INT_CONFIG_INT_SOURCE_BIT_POS);
+
+ //
+ // Get GPIO direction (GPIORxDis and GPIOTxDis)
+ //
+ GpioConfig->Direction = ((PadCfgDwReg[0] & (B_GPIO_PCR_RXDIS | B_GPIO_PCR_TXDIS)) >> (N_GPIO_PCR_TXDIS - (N_GPIO_DIRECTION_DIR_BIT_POS + 1))) | (0x1 << N_GPIO_DIRECTION_DIR_BIT_POS);
+
+ //
+ // Get GPIO input inversion (RXINV)
+ // (Only meaningful if input enabled)
+ //
+ if((PadCfgDwReg[0] & B_GPIO_PCR_RXDIS) == 0) {
+ GpioConfig->Direction |= ((PadCfgDwReg[0] & B_GPIO_PCR_RXINV) >> (N_GPIO_PCR_RXINV - (N_GPIO_DIRECTION_INV_BIT_POS + 1))) | (0x1 << N_GPIO_DIRECTION_INV_BIT_POS);
+ }
+
+ //
+ // Get GPIO output state (GPIOTxState)
+ //
+ GpioConfig->OutputState = ((PadCfgDwReg[0] & B_GPIO_PCR_TX_STATE) << (N_GPIO_PCR_TX_STATE + (N_GPIO_OUTPUT_BIT_POS + 1))) | (0x1 << N_GPIO_OUTPUT_BIT_POS);
+
+ //
+ // Configure GPIO RX raw override to '1' (RXRAW1)
+ //
+ GpioConfig->OtherSettings = ((PadCfgDwReg[0] & B_GPIO_PCR_RX_RAW1) >> (N_GPIO_PCR_RX_RAW1 - (N_GPIO_OTHER_CONFIG_RXRAW_BIT_POS + 1))) | (0x1 << N_GPIO_OTHER_CONFIG_RXRAW_BIT_POS);
+
+ //
+ // Get GPIO Pad Mode (PMode)
+ //
+ GpioConfig->PadMode = ((PadCfgDwReg[0] & B_GPIO_PCR_PAD_MODE) >> (N_GPIO_PCR_PAD_MODE - (N_GPIO_PAD_MODE_BIT_POS + 1))) | (0x1 << N_GPIO_PAD_MODE_BIT_POS);
+
+ //
+ // Get GPIO termination (Term)
+ //
+ GpioConfig->ElectricalConfig = ((PadCfgDwReg[1] & B_GPIO_PCR_TERM) >> (N_GPIO_PCR_TERM - (N_GPIO_ELECTRICAL_CONFIG_TERMINATION_BIT_POS + 1))) | (0x1 << N_GPIO_ELECTRICAL_CONFIG_TERMINATION_BIT_POS);
+}
+
+/**
+ This procedure will read multiple GPIO settings
+
+ @param[in] GpioPad GPIO Pad
+ @param[out] GpioData GPIO data structure
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioGetPadConfig (
+ IN GPIO_PAD GpioPad,
+ OUT GPIO_CONFIG *GpioData
+ )
+{
+ UINT32 PadCfgDwReg[GPIO_PADCFG_DW_REG_NUMBER];
+ UINT32 RegVal;
+ GPIO_GROUP Group;
+ UINT32 PadNumber;
+ UINT32 PadBitPosition;
+
+ Group = GpioGetGroupFromGpioPad (GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+ PadBitPosition = GPIO_GET_PAD_POSITION (PadNumber);
+
+ if (!GpioIsPadValid (GpioPad)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if (!GpioIsPadHostOwned (GpioPad)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Read PADCFG DW0 register
+ //
+ PadCfgDwReg[0] = GpioReadPadCfgReg (GpioPad, 0);
+
+ //
+ // Read PADCFG DW1 register
+ //
+ PadCfgDwReg[1] = GpioReadPadCfgReg (GpioPad, 1);
+
+ //
+ // Read PADCFG DW2 register
+ //
+ PadCfgDwReg[2] = GpioReadPadCfgReg (GpioPad, 2);
+
+ GpioConfigFromPadCfgRegValue (
+ GpioPad,
+ PadCfgDwReg,
+ GpioData
+ );
+
+ //
+ // Read HOSTSW_OWN registers
+ //
+ GpioReadReg (
+ GpioHostOwnershipRegister,
+ Group,
+ GPIO_GET_DW_NUM (PadNumber),
+ &RegVal
+ );
+
+ //
+ // Get Host Software Ownership
+ //
+ GpioData->HostSoftPadOwn = (((RegVal >> PadBitPosition) & 0x1) << (N_GPIO_HOSTSW_OWN_BIT_POS + 1)) | (0x1 << N_GPIO_HOSTSW_OWN_BIT_POS);
+
+ //
+ // Read PADCFGLOCK register
+ //
+ GpioReadReg (
+ GpioPadConfigLockRegister,
+ Group,
+ GPIO_GET_DW_NUM (PadNumber),
+ &RegVal
+ );
+
+ //
+ // Get Pad Configuration Lock state
+ //
+ GpioData->LockConfig = ((!((RegVal >> PadBitPosition) & 0x1)) << 1) | BIT0;
+
+ //
+ // Read PADCFGLOCKTX register
+ //
+ GpioReadReg (
+ GpioPadLockOutputRegister,
+ Group,
+ GPIO_GET_DW_NUM (PadNumber),
+ &RegVal
+ );
+
+ //
+ // Get Pad Configuration Lock Tx state
+ //
+ GpioData->LockConfig |= ((!((RegVal >> PadBitPosition) & 0x1)) << 3) | BIT2;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will calculate PADCFG register value based on GpioConfig data
+
+ @param[in] GpioPad GPIO Pad
+ @param[in] GpioConfig GPIO Configuration data
+ @param[out] PadCfgDwReg PADCFG DWx register value
+ @param[out] PadCfgDwRegMask Mask with PADCFG DWx register bits to be modified
+
+ @retval Status
+**/
+EFI_STATUS
+GpioPadCfgRegValueFromGpioConfig (
+ IN GPIO_PAD GpioPad,
+ IN CONST GPIO_CONFIG *GpioConfig,
+ OUT UINT32 *PadCfgDwReg,
+ OUT UINT32 *PadCfgDwRegMask
+ )
+{
+ UINT32 PadRstCfg;
+
+ //
+ // Configure Reset Type (PadRstCfg)
+ // Reset configuration depends on group type.
+ // This field requires support for new and deprecated settings.
+ //
+ GpioPadRstCfgFromResetConfig (
+ GpioPad,
+ GpioConfig->PowerConfig,
+ &PadRstCfg
+ );
+
+ PadCfgDwRegMask[0] |= ((((GpioConfig->PowerConfig & B_GPIO_RESET_CONFIG_RESET_MASK) >> N_GPIO_RESET_CONFIG_RESET_BIT_POS) == GpioHardwareDefault) ? 0x0 : B_GPIO_PCR_RST_CONF);
+ PadCfgDwReg[0] |= PadRstCfg << N_GPIO_PCR_RST_CONF;
+
+ //
+ // Configure how interrupt is triggered (RxEvCfg)
+ //
+ PadCfgDwRegMask[0] |= ((((GpioConfig->InterruptConfig & B_GPIO_INT_CONFIG_INT_TYPE_MASK) >> N_GPIO_INT_CONFIG_INT_TYPE_BIT_POS) == GpioHardwareDefault) ? 0x0 : B_GPIO_PCR_RX_LVL_EDG);
+ PadCfgDwReg[0] |= (((GpioConfig->InterruptConfig & B_GPIO_INT_CONFIG_INT_TYPE_MASK) >> (N_GPIO_INT_CONFIG_INT_TYPE_BIT_POS + 1)) << N_GPIO_PCR_RX_LVL_EDG);
+
+ //
+ // Configure interrupt generation (GPIRoutIOxAPIC/SCI/SMI/NMI)
+ //
+ PadCfgDwRegMask[0] |= ((((GpioConfig->InterruptConfig & B_GPIO_INT_CONFIG_INT_SOURCE_MASK) >> N_GPIO_INT_CONFIG_INT_SOURCE_BIT_POS) == GpioHardwareDefault) ? 0x0 : (B_GPIO_PCR_RX_NMI_ROUTE | B_GPIO_PCR_RX_SCI_ROUTE | B_GPIO_PCR_RX_SMI_ROUTE | B_GPIO_PCR_RX_APIC_ROUTE));
+ PadCfgDwReg[0] |= (((GpioConfig->InterruptConfig & B_GPIO_INT_CONFIG_INT_SOURCE_MASK) >> (N_GPIO_INT_CONFIG_INT_SOURCE_BIT_POS + 1)) << N_GPIO_PCR_RX_NMI_ROUTE);
+
+ //
+ // Configure GPIO direction (GPIORxDis and GPIOTxDis)
+ //
+ PadCfgDwRegMask[0] |= ((((GpioConfig->Direction & B_GPIO_DIRECTION_DIR_MASK) >> N_GPIO_DIRECTION_DIR_BIT_POS) == GpioHardwareDefault) ? 0x0 : (B_GPIO_PCR_RXDIS | B_GPIO_PCR_TXDIS));
+ PadCfgDwReg[0] |= (((GpioConfig->Direction & B_GPIO_DIRECTION_DIR_MASK) >> (N_GPIO_DIRECTION_DIR_BIT_POS + 1)) << N_GPIO_PCR_TXDIS);
+
+ //
+ // Configure GPIO input inversion (RXINV)
+ //
+ PadCfgDwRegMask[0] |= ((((GpioConfig->Direction & B_GPIO_DIRECTION_INV_MASK) >> N_GPIO_DIRECTION_INV_BIT_POS) == GpioHardwareDefault) ? 0x0 : B_GPIO_PCR_RXINV);
+ PadCfgDwReg[0] |= (((GpioConfig->Direction & B_GPIO_DIRECTION_INV_MASK) >> (N_GPIO_DIRECTION_INV_BIT_POS + 1)) << N_GPIO_PCR_RXINV);
+
+ //
+ // Configure GPIO output state (GPIOTxState)
+ //
+ PadCfgDwRegMask[0] |= ((((GpioConfig->OutputState & B_GPIO_OUTPUT_MASK) >> N_GPIO_OUTPUT_BIT_POS) == GpioHardwareDefault) ? 0x0 : B_GPIO_PCR_TX_STATE);
+ PadCfgDwReg[0] |= (((GpioConfig->OutputState & B_GPIO_OUTPUT_MASK) >> (N_GPIO_OUTPUT_BIT_POS + 1)) << N_GPIO_PCR_TX_STATE);
+
+ //
+ // Configure GPIO RX raw override to '1' (RXRAW1)
+ //
+ PadCfgDwRegMask[0] |= ((((GpioConfig->OtherSettings & B_GPIO_OTHER_CONFIG_RXRAW_MASK) >> N_GPIO_OTHER_CONFIG_RXRAW_BIT_POS) == GpioHardwareDefault) ? 0x0 : B_GPIO_PCR_RX_RAW1);
+ PadCfgDwReg[0] |= (((GpioConfig->OtherSettings & B_GPIO_OTHER_CONFIG_RXRAW_MASK) >> (N_GPIO_OTHER_CONFIG_RXRAW_BIT_POS + 1)) << N_GPIO_PCR_RX_RAW1);
+
+ //
+ // Configure GPIO Pad Mode (PMode)
+ //
+ PadCfgDwRegMask[0] |= ((((GpioConfig->PadMode & B_GPIO_PAD_MODE_MASK) >> N_GPIO_PAD_MODE_BIT_POS) == GpioHardwareDefault) ? 0x0 : B_GPIO_PCR_PAD_MODE);
+ PadCfgDwReg[0] |= (((GpioConfig->PadMode & B_GPIO_PAD_MODE_MASK) >> (N_GPIO_PAD_MODE_BIT_POS + 1)) << N_GPIO_PCR_PAD_MODE);
+
+ //
+ // Configure GPIO termination (Term)
+ //
+ PadCfgDwRegMask[1] |= ((((GpioConfig->ElectricalConfig & B_GPIO_ELECTRICAL_CONFIG_TERMINATION_MASK) >> N_GPIO_ELECTRICAL_CONFIG_TERMINATION_BIT_POS) == GpioHardwareDefault) ? 0x0 : B_GPIO_PCR_TERM);
+ PadCfgDwReg[1] |= (((GpioConfig->ElectricalConfig & B_GPIO_ELECTRICAL_CONFIG_TERMINATION_MASK) >> (N_GPIO_ELECTRICAL_CONFIG_TERMINATION_BIT_POS + 1)) << N_GPIO_PCR_TERM);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will configure multiple GPIO settings
+
+ @param[in] GpioPad GPIO Pad
+ @param[in] GpioData GPIO data structure
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioSetPadConfig (
+ IN GPIO_PAD GpioPad,
+ IN GPIO_CONFIG *GpioData
+ )
+{
+ EFI_STATUS Status;
+ UINT32 PadCfgDwReg[GPIO_PADCFG_DW_REG_NUMBER];
+ UINT32 PadCfgDwRegMask[GPIO_PADCFG_DW_REG_NUMBER];
+ UINT32 HostSoftOwnReg;
+ UINT32 HostSoftOwnRegMask;
+ UINT32 GpiGpeEnReg;
+ UINT32 GpiGpeEnRegMask;
+ UINT32 GpiNmiEnReg;
+ UINT32 GpiNmiEnRegMask;
+ UINT32 GpiSmiEnReg;
+ UINT32 GpiSmiEnRegMask;
+ GPIO_GROUP Group;
+ UINT32 GroupIndex;
+ UINT32 PadNumber;
+ UINT32 PadBitPosition;
+ UINT32 DwNum;
+ GPIO_LOCK_CONFIG LockConfig;
+
+ ZeroMem (PadCfgDwReg, sizeof (PadCfgDwReg));
+ ZeroMem (PadCfgDwRegMask, sizeof (PadCfgDwRegMask));
+
+ Group = GpioGetGroupFromGpioPad (GpioPad);
+ GroupIndex = GpioGetGroupIndexFromGpioPad (GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+ PadBitPosition = GPIO_GET_PAD_POSITION (PadNumber);
+ DwNum = GPIO_GET_DW_NUM (PadNumber);
+
+ if (!GpioIsPadValid (GpioPad)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if (!GpioIsPadHostOwned (GpioPad)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Check if Pad enabled for SCI is to be in unlocked state
+ //
+ if (((GpioData->InterruptConfig & GpioIntSci) == GpioIntSci) &&
+ ((GpioData->LockConfig & B_GPIO_LOCK_CONFIG_PAD_CONF_LOCK_MASK) != GpioPadConfigUnlock)){
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: %a for SCI is not unlocked!\n", GpioName (GpioPad)));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Get GPIO PADCFG register value from GPIO config data
+ //
+ GpioPadCfgRegValueFromGpioConfig (
+ GpioPad,
+ GpioData,
+ PadCfgDwReg,
+ PadCfgDwRegMask
+ );
+
+ //
+ // Write PADCFG DW0 register
+ //
+ GpioWritePadCfgReg (
+ GpioPad,
+ 0,
+ ~PadCfgDwRegMask[0],
+ PadCfgDwReg[0]
+ );
+
+ //
+ // Write PADCFG DW1 register
+ //
+ GpioWritePadCfgReg (
+ GpioPad,
+ 1,
+ ~PadCfgDwRegMask[1],
+ PadCfgDwReg[1]
+ );
+
+ //
+ // Write PADCFG DW2 register
+ //
+ GpioWritePadCfgReg (
+ GpioPad,
+ 2,
+ ~PadCfgDwRegMask[2],
+ PadCfgDwReg[2]
+ );
+
+ //
+ // Update value to be programmed in HOSTSW_OWN register
+ //
+ if ((GpioData->InterruptConfig & GpioIntSmi) == GpioIntSmi) {
+ HostSoftOwnRegMask = 1 << PadBitPosition;
+ HostSoftOwnReg = 1 << PadBitPosition;
+ } else {
+ HostSoftOwnRegMask = (GpioData->HostSoftPadOwn & 0x1) << PadBitPosition;
+ HostSoftOwnReg = (GpioData->HostSoftPadOwn >> 0x1) << PadBitPosition;
+ }
+
+ //
+ // Write HOSTSW_OWN registers
+ //
+ GpioWriteReg (
+ GpioHostOwnershipRegister,
+ Group,
+ DwNum,
+ ~HostSoftOwnRegMask,
+ HostSoftOwnReg
+ );
+
+ //
+ // Update value to be programmed in GPI_GPE_EN register
+ //
+ GpiGpeEnRegMask = (GpioData->InterruptConfig & 0x1) << PadBitPosition;
+ GpiGpeEnReg = ((GpioData->InterruptConfig & GpioIntSci) >> 3) << PadBitPosition;
+
+ //
+ // Write GPI_GPE_EN registers
+ //
+ GpioWriteReg (
+ GpioGpeEnableRegister,
+ Group,
+ DwNum,
+ ~GpiGpeEnRegMask,
+ GpiGpeEnReg
+ );
+
+ //
+ // Update value to be programmed in GPI_NMI_EN register
+ //
+ GpiNmiEnRegMask = (GpioData->InterruptConfig & 0x1) << PadBitPosition;
+ GpiNmiEnReg = ((GpioData->InterruptConfig & GpioIntNmi) >> 1) << PadBitPosition;
+
+ Status = GpioWriteReg (
+ GpioNmiEnableRegister,
+ Group,
+ DwNum,
+ ~GpiNmiEnRegMask,
+ GpiNmiEnReg
+ );
+ if (Status == EFI_UNSUPPORTED) {
+ if (GpiNmiEnReg == 0) {
+ //
+ // Not all GPIO have NMI capabilities. Since we always try to program this register,
+ // even when not enabling NMI for a pad so do not report such access as an error
+ //
+ Status = EFI_SUCCESS;
+ } else {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Group %a has no pads supporting NMI\n", GpioGetGroupName (GroupIndex)));
+ ASSERT (FALSE);
+ return Status;
+ }
+ }
+
+ //
+ // Update value to be programmed in GPI_SMI_EN register
+ //
+ GpiSmiEnRegMask = (GpioData->InterruptConfig & 0x1) << PadBitPosition;
+ GpiSmiEnReg = ((GpioData->InterruptConfig & GpioIntSmi) >> 2) << PadBitPosition;
+
+ Status = GpioWriteReg (
+ GpioSmiEnableRegister,
+ Group,
+ DwNum,
+ ~GpiSmiEnRegMask,
+ GpiSmiEnReg
+ );
+ if (Status == EFI_UNSUPPORTED) {
+ if (GpiSmiEnReg == 0) {
+ //
+ // Not all GPIO have SMI capabilities. Since we always try to program this register,
+ // even when not enabling SMI for a pad so do not report such access as an error
+ //
+ Status = EFI_SUCCESS;
+ } else {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Group %a has no pads supporting SMI\n", GpioGetGroupName (GroupIndex)));
+ ASSERT (FALSE);
+ return Status;
+ }
+ }
+
+ //
+ // Store unlock data
+ //
+ if (GpioData->LockConfig != GpioLockDefault) {
+ LockConfig = GpioData->LockConfig & B_GPIO_LOCK_CONFIG_PAD_CONF_LOCK_MASK;
+ //
+ // If pad in GpioMode is an output default action should be to leave output unlocked
+ //
+ if ((GpioData->PadMode == GpioPadModeGpio) &&
+ (GpioData->Direction == GpioDirOut) &&
+ ((GpioData->LockConfig & B_GPIO_LOCK_CONFIG_OUTPUT_LOCK_MASK) == GpioLockDefault)) {
+ LockConfig |= GpioOutputStateUnlock;
+ } else {
+ LockConfig |= GpioData->LockConfig & B_GPIO_LOCK_CONFIG_OUTPUT_LOCK_MASK;
+ }
+ Status = GpioStoreUnlockData (GpioPad, LockConfig);
+ }
+
+ return Status;
+}
+
+/**
+ This procedure will set GPIO output level
+
+ @param[in] GpioPad GPIO pad
+ @param[in] Value Output value
+ 0: OutputLow, 1: OutputHigh
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioSetOutputValue (
+ IN GPIO_PAD GpioPad,
+ IN UINT32 Value
+ )
+{
+ if (Value > 1) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!GpioIsPadValid (GpioPad)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!GpioIsPadHostOwned (GpioPad)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ GpioWritePadCfgReg (
+ GpioPad,
+ 0,
+ (UINT32)~B_GPIO_PCR_TX_STATE,
+ Value << N_GPIO_PCR_TX_STATE
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will get GPIO output level
+
+ @param[in] GpioPad GPIO pad
+ @param[out] OutputVal GPIO Output value
+ 0: OutputLow, 1: OutputHigh
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetOutputValue (
+ IN GPIO_PAD GpioPad,
+ OUT UINT32 *OutputVal
+ )
+{
+ UINT32 PadCfgReg;
+
+ if (!GpioIsPadValid (GpioPad)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!GpioIsPadHostOwned (GpioPad)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ PadCfgReg = GpioReadPadCfgReg (GpioPad, 0);
+
+ *OutputVal = (PadCfgReg & B_GPIO_PCR_TX_STATE) >> N_GPIO_PCR_TX_STATE;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will get GPIO input level
+
+ @param[in] GpioPad GPIO pad
+ @param[out] InputVal GPIO Input value
+ 0: InputLow, 1: InpuHigh
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetInputValue (
+ IN GPIO_PAD GpioPad,
+ OUT UINT32 *InputVal
+ )
+{
+ UINT32 PadCfgReg;
+
+ if (!GpioIsPadValid (GpioPad)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!GpioIsPadHostOwned (GpioPad)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ PadCfgReg = GpioReadPadCfgReg (GpioPad, 0);
+
+ *InputVal = (PadCfgReg & B_GPIO_PCR_RX_STATE) >> N_GPIO_PCR_RX_STATE;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will get GPIO IOxAPIC interrupt number
+
+ @param[in] GpioPad GPIO pad
+ @param[out] IrqNum IRQ number
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetPadIoApicIrqNumber (
+ IN GPIO_PAD GpioPad,
+ OUT UINT32 *IrqNum
+ )
+{
+ UINT32 PadCfgReg;
+
+ if (!GpioIsPadValid (GpioPad)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!GpioIsPadHostOwned (GpioPad)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ PadCfgReg = GpioReadPadCfgReg (GpioPad, 1);
+
+ *IrqNum = (PadCfgReg & B_GPIO_PCR_INTSEL) >> N_GPIO_PCR_INTSEL;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will configure GPIO input inversion
+
+ @param[in] GpioPad GPIO pad
+ @param[in] Value Value for GPIO input inversion
+ 0: No input inversion, 1: Invert input
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioSetInputInversion (
+ IN GPIO_PAD GpioPad,
+ IN UINT32 Value
+ )
+{
+ if (Value > 1) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!GpioIsPadValid (GpioPad)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!GpioIsPadHostOwned (GpioPad)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ GpioWritePadCfgReg (
+ GpioPad,
+ 0,
+ (UINT32)~B_GPIO_PCR_RXINV,
+ Value << N_GPIO_PCR_RXINV
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will get GPIO pad input inversion value
+
+ @param[in] GpioPad GPIO pad
+ @param[out] InvertState GPIO inversion state
+ 0: No input inversion, 1: Inverted input
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetInputInversion (
+ IN GPIO_PAD GpioPad,
+ OUT UINT32 *InvertState
+ )
+{
+ UINT32 PadCfgReg;
+
+ if (!GpioIsPadValid (GpioPad)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!GpioIsPadHostOwned (GpioPad)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ PadCfgReg = GpioReadPadCfgReg (GpioPad, 0);
+
+ *InvertState = (PadCfgReg & B_GPIO_PCR_RXINV) >> N_GPIO_PCR_RXINV;
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will set GPIO interrupt settings
+
+ @param[in] GpioPad GPIO pad
+ @param[in] Value Value of Level/Edge
+ use GPIO_INT_CONFIG as argument
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioSetPadInterruptConfig (
+ IN GPIO_PAD GpioPad,
+ IN GPIO_INT_CONFIG Value
+ )
+{
+ EFI_STATUS Status;
+ UINT32 RxLvlEdgeValue;
+ UINT32 IntRouteValue;
+ UINT32 PadNumber;
+ UINT32 GpeEnable;
+ UINT32 NmiEnable;
+
+ if (!GpioIsPadValid (GpioPad)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!GpioIsPadHostOwned (GpioPad)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Status = EFI_SUCCESS;
+
+ if (((Value & B_GPIO_INT_CONFIG_INT_TYPE_MASK) >> N_GPIO_INT_CONFIG_INT_TYPE_BIT_POS) != GpioHardwareDefault) {
+ RxLvlEdgeValue = ((Value & B_GPIO_INT_CONFIG_INT_TYPE_MASK) >> (N_GPIO_INT_CONFIG_INT_TYPE_BIT_POS + 1)) << N_GPIO_PCR_RX_LVL_EDG;
+
+ GpioWritePadCfgReg (
+ GpioPad,
+ 0,
+ (UINT32)~B_GPIO_PCR_RX_LVL_EDG,
+ RxLvlEdgeValue
+ );
+ }
+
+ if (((Value & B_GPIO_INT_CONFIG_INT_SOURCE_MASK) >> N_GPIO_INT_CONFIG_INT_SOURCE_BIT_POS) != GpioHardwareDefault) {
+
+ IntRouteValue = ((Value & B_GPIO_INT_CONFIG_INT_SOURCE_MASK) >> (N_GPIO_INT_CONFIG_INT_SOURCE_BIT_POS + 1)) << N_GPIO_PCR_RX_NMI_ROUTE;
+
+ GpioWritePadCfgReg (
+ GpioPad,
+ 0,
+ (UINT32)~(B_GPIO_PCR_RX_NMI_ROUTE | B_GPIO_PCR_RX_SCI_ROUTE | B_GPIO_PCR_RX_SMI_ROUTE | B_GPIO_PCR_RX_APIC_ROUTE),
+ IntRouteValue
+ );
+
+ if ((Value & GpioIntSci) == GpioIntSci) {
+ GpeEnable = 0x1;
+ } else {
+ GpeEnable = 0x0;
+ }
+
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+
+ GpioWriteReg (
+ GpioGpeEnableRegister,
+ GpioGetGroupFromGpioPad (GpioPad),
+ GPIO_GET_DW_NUM (PadNumber),
+ ~(1 << GPIO_GET_PAD_POSITION (PadNumber)),
+ GpeEnable << GPIO_GET_PAD_POSITION (PadNumber)
+ );
+
+ if ((Value & GpioIntNmi) == GpioIntNmi) {
+ NmiEnable = 0x1;
+ } else {
+ NmiEnable = 0x0;
+ }
+
+ Status = GpioWriteReg (
+ GpioNmiEnableRegister,
+ GpioGetGroupFromGpioPad (GpioPad),
+ GPIO_GET_DW_NUM (PadNumber),
+ ~(1 << GPIO_GET_PAD_POSITION (PadNumber)),
+ NmiEnable << GPIO_GET_PAD_POSITION (PadNumber)
+ );
+ if (Status == EFI_UNSUPPORTED) {
+ if (NmiEnable == 0) {
+ //
+ // Not all GPIO have NMI capabilities. Since we always try to program this register,
+ // even when not enabling NMI for a pad so do not report such access as an error
+ //
+ return EFI_SUCCESS;
+ } else {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Group %a has no pads supporting NMI\n", GpioGetGroupName (GpioGetGroupIndexFromGpioPad (GpioPad))));
+ }
+ }
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ return Status;
+}
+
+/**
+ This procedure will set GPIO electrical settings
+
+ @param[in] GpioPad GPIO pad
+ @param[in] Value Value of termination
+ use GPIO_ELECTRICAL_CONFIG as argument
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioSetPadElectricalConfig (
+ IN GPIO_PAD GpioPad,
+ IN GPIO_ELECTRICAL_CONFIG Value
+ )
+{
+ UINT32 TermValue;
+
+ if (!GpioIsPadValid (GpioPad)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!GpioIsPadHostOwned (GpioPad)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if (((Value & B_GPIO_ELECTRICAL_CONFIG_TERMINATION_MASK) >> N_GPIO_ELECTRICAL_CONFIG_TERMINATION_BIT_POS) != GpioHardwareDefault) {
+ TermValue = ((Value & B_GPIO_ELECTRICAL_CONFIG_TERMINATION_MASK) >> (N_GPIO_ELECTRICAL_CONFIG_TERMINATION_BIT_POS + 1)) << N_GPIO_PCR_TERM;
+
+ GpioWritePadCfgReg (
+ GpioPad,
+ 1,
+ (UINT32)~B_GPIO_PCR_TERM,
+ TermValue
+ );
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will set GPIO Reset settings
+
+ @param[in] GpioPad GPIO pad
+ @param[in] Value Value for Pad Reset Configuration
+ use GPIO_RESET_CONFIG as argument
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioSetPadResetConfig (
+ IN GPIO_PAD GpioPad,
+ IN GPIO_RESET_CONFIG Value
+ )
+{
+ UINT32 PadRstCfg;
+
+ if (!GpioIsPadValid (GpioPad)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!GpioIsPadHostOwned (GpioPad)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if (((Value & B_GPIO_RESET_CONFIG_RESET_MASK) >> N_GPIO_RESET_CONFIG_RESET_BIT_POS) != GpioHardwareDefault) {
+
+ //
+ // Reset configuration depends on group type.
+ // This field requires support for new and deprecated settings.
+ //
+ GpioPadRstCfgFromResetConfig (
+ GpioPad,
+ Value,
+ &PadRstCfg
+ );
+
+ GpioWritePadCfgReg (
+ GpioPad,
+ 0,
+ (UINT32)~B_GPIO_PCR_RST_CONF,
+ PadRstCfg << N_GPIO_PCR_RST_CONF
+ );
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will get GPIO Reset settings
+
+ @param[in] GpioPad GPIO pad
+ @param[in] Value Value of Pad Reset Configuration
+ based on GPIO_RESET_CONFIG
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetPadResetConfig (
+ IN GPIO_PAD GpioPad,
+ IN GPIO_RESET_CONFIG *Value
+ )
+{
+ UINT32 PadRstCfg;
+ UINT32 PadCfgDw0Reg;
+
+ if (!GpioIsPadValid (GpioPad)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!GpioIsPadHostOwned (GpioPad)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ PadCfgDw0Reg = GpioReadPadCfgReg (GpioPad, 0);
+
+ //
+ // Get Reset Type (PadRstCfg)
+ //
+ PadRstCfg = (PadCfgDw0Reg & B_GPIO_PCR_RST_CONF) >> N_GPIO_PCR_RST_CONF;
+
+ *Value = GpioResetConfigFromPadRstCfg (
+ GpioPad,
+ PadRstCfg
+ );
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This procedure will get Gpio Pad Host Software Ownership
+
+ @param[in] GpioPad GPIO pad
+ @param[out] PadHostSwOwn Value of Host Software Pad Owner
+ 0: ACPI Mode, 1: GPIO Driver mode
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetHostSwOwnershipForPad (
+ IN GPIO_PAD GpioPad,
+ OUT UINT32 *PadHostSwOwn
+ )
+{
+ UINT32 PadNumber;
+ UINT32 HostSwRegVal;
+
+ if (!GpioIsPadValid (GpioPad)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+
+ GpioReadReg (
+ GpioHostOwnershipRegister,
+ GpioGetGroupFromGpioPad (GpioPad),
+ GPIO_GET_DW_NUM (PadNumber),
+ &HostSwRegVal
+ );
+
+ *PadHostSwOwn = (HostSwRegVal >> GPIO_GET_PAD_POSITION (PadNumber)) & 0x1;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will set Gpio Pad Host Software Ownership
+
+ @param[in] GpioPad GPIO pad
+ @param[in] PadHostSwOwn Pad Host Software Owner
+ 0: ACPI Mode, 1: GPIO Driver mode
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioSetHostSwOwnershipForPad (
+ IN GPIO_PAD GpioPad,
+ IN UINT32 PadHostSwOwn
+ )
+{
+ UINT32 PadNumber;
+
+ if (!GpioIsPadValid (GpioPad) || (PadHostSwOwn > 1)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+
+ return GpioWriteReg (
+ GpioHostOwnershipRegister,
+ GpioGetGroupFromGpioPad (GpioPad),
+ GPIO_GET_DW_NUM (PadNumber),
+ (UINT32)~(1 << GPIO_GET_PAD_POSITION (PadNumber)),
+ PadHostSwOwn << GPIO_GET_PAD_POSITION (PadNumber)
+ );
+}
+
+/**
+ This procedure will get Gpio Pad Ownership
+
+ @param[in] GpioPad GPIO pad
+ @param[out] PadOwnVal Value of Pad Ownership
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioGetPadOwnership (
+ IN GPIO_PAD GpioPad,
+ OUT GPIO_PAD_OWN *PadOwnVal
+ )
+{
+ UINT32 Mask;
+ UINT32 RegOffset;
+ UINT32 GroupIndex;
+ UINT32 PadNumber;
+ CONST GPIO_GROUP_INFO *GpioGroupInfo;
+ UINT32 GpioGroupInfoLength;
+ UINT32 PadOwnRegValue;
+
+ if (!GpioIsPadValid (GpioPad)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ GroupIndex = GpioGetGroupIndexFromGpioPad (GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+
+ //
+ // Calculate RegOffset using Pad Ownership offset and GPIO Pad number.
+ // One DWord register contains information for 8 pads.
+ //
+ RegOffset = GpioGroupInfo[GroupIndex].PadOwnOffset + (PadNumber >> 3) * 0x4;
+
+ //
+ // Calculate pad bit position within DWord register
+ //
+ PadNumber %= 8;
+ Mask = (BIT1 | BIT0) << (PadNumber * 4);
+
+ PadOwnRegValue = MmioRead32 (PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, RegOffset));
+
+ *PadOwnVal = (GPIO_PAD_OWN) ((PadOwnRegValue & Mask) >> (PadNumber * 4));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will check state of Pad Config Lock for pads within one group
+
+ @param[in] Group GPIO group
+ @param[in] DwNum PadCfgLock register number for current group.
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[out] PadCfgLockRegVal Value of PadCfgLock register
+ Bit position - PadNumber
+ Bit value - 0: NotLocked, 1: Locked
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or DwNum parameter number
+**/
+EFI_STATUS
+GpioGetPadCfgLockForGroupDw (
+ IN GPIO_GROUP Group,
+ IN UINT32 DwNum,
+ OUT UINT32 *PadCfgLockRegVal
+ )
+{
+ if (!GpioIsGroupAndDwNumValid (Group, DwNum)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return GpioReadReg (
+ GpioPadConfigLockRegister,
+ Group,
+ DwNum,
+ PadCfgLockRegVal
+ );
+}
+
+/**
+ This procedure will check state of Pad Config Lock for selected pad
+
+ @param[in] GpioPad GPIO pad
+ @param[out] PadCfgLock PadCfgLock for selected pad
+ 0: NotLocked, 1: Locked
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetPadCfgLock (
+ IN GPIO_PAD GpioPad,
+ OUT UINT32 *PadCfgLock
+ )
+{
+ UINT32 PadNumber;
+ UINT32 PadCfgLockRegVal;
+
+ if (!GpioIsPadValid (GpioPad)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+
+ GpioReadReg (
+ GpioPadConfigLockRegister,
+ GpioGetGroupFromGpioPad (GpioPad),
+ GPIO_GET_DW_NUM (PadNumber),
+ &PadCfgLockRegVal
+ );
+
+ *PadCfgLock = (PadCfgLockRegVal >> GPIO_GET_PAD_POSITION (PadNumber)) & 0x1;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will check state of Pad Config Tx Lock for pads within one group
+
+ @param[in] Group GPIO group
+ @param[in] DwNum PadCfgLockTx register number for current group.
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[out] PadCfgLockTxRegVal Value of PadCfgLockTx register
+ Bit position - PadNumber
+ Bit value - 0: NotLockedTx, 1: LockedTx
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or DwNum parameter number
+**/
+EFI_STATUS
+GpioGetPadCfgLockTxForGroupDw (
+ IN GPIO_GROUP Group,
+ IN UINT32 DwNum,
+ OUT UINT32 *PadCfgLockTxRegVal
+ )
+{
+ if (!GpioIsGroupAndDwNumValid (Group, DwNum)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return GpioReadReg (
+ GpioPadLockOutputRegister,
+ Group,
+ DwNum,
+ PadCfgLockTxRegVal
+ );
+}
+
+/**
+ This procedure will check state of Pad Config Tx Lock for selected pad
+
+ @param[in] GpioPad GPIO pad
+ @param[out] PadCfgLock PadCfgLockTx for selected pad
+ 0: NotLockedTx, 1: LockedTx
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetPadCfgLockTx (
+ IN GPIO_PAD GpioPad,
+ OUT UINT32 *PadCfgLockTx
+ )
+{
+ UINT32 PadNumber;
+ UINT32 PadCfgLockTxRegVal;
+
+ if (!GpioIsPadValid (GpioPad)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+
+ GpioReadReg (
+ GpioPadLockOutputRegister,
+ GpioGetGroupFromGpioPad (GpioPad),
+ GPIO_GET_DW_NUM (PadNumber),
+ &PadCfgLockTxRegVal
+ );
+
+ *PadCfgLockTx = (PadCfgLockTxRegVal >> GPIO_GET_PAD_POSITION (PadNumber)) & 0x1;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will clear PadCfgLock for selected pads within one group.
+ This function should be used only inside SMI.
+
+ @param[in] Group GPIO group
+ @param[in] DwNum PadCfgLock register number for current group.
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[in] PadsToUnlock Bitmask for pads which are going to be unlocked,
+ Bit position - PadNumber
+ Bit value - 0: DoNotUnlock, 1: Unlock
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioUnlockPadCfgForGroupDw (
+ IN GPIO_GROUP Group,
+ IN UINT32 DwNum,
+ IN UINT32 PadsToUnlock
+ )
+{
+ if (!GpioIsGroupAndDwNumValid (Group, DwNum)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return GpioWriteLockReg (
+ GpioPadConfigLockRegister,
+ Group,
+ DwNum,
+ ~PadsToUnlock,
+ 0
+ );
+}
+
+/**
+ This procedure will clear PadCfgLock for selected pad.
+ This function should be used only inside SMI.
+
+ @param[in] GpioPad GPIO pad
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioUnlockPadCfg (
+ IN GPIO_PAD GpioPad
+ )
+{
+ GPIO_GROUP Group;
+ UINT32 PadNumber;
+
+ Group = GpioGetGroupFromGpioPad (GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+
+ return GpioUnlockPadCfgForGroupDw (
+ Group,
+ GPIO_GET_DW_NUM (PadNumber),
+ 1 << GPIO_GET_PAD_POSITION (PadNumber)
+ );
+}
+
+/**
+ This procedure will set PadCfgLock for selected pads within one group
+
+ @param[in] Group GPIO group
+ @param[in] DwNum PadCfgLock register number for current group.
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[in] PadsToLock Bitmask for pads which are going to be locked
+ Bit position - PadNumber
+ Bit value - 0: DoNotLock, 1: Lock
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or DwNum parameter number
+**/
+EFI_STATUS
+GpioLockPadCfgForGroupDw (
+ IN GPIO_GROUP Group,
+ IN UINT32 DwNum,
+ IN UINT32 PadsToLock
+ )
+{
+ if (!GpioIsGroupAndDwNumValid (Group, DwNum)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return GpioWriteLockReg (
+ GpioPadConfigLockRegister,
+ Group,
+ DwNum,
+ ~0u,
+ PadsToLock
+ );
+}
+
+/**
+ This procedure will set PadCfgLock for selected pad
+
+ @param[in] GpioPad GPIO pad
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioLockPadCfg (
+ IN GPIO_PAD GpioPad
+ )
+{
+ GPIO_GROUP Group;
+ UINT32 PadNumber;
+
+ Group = GpioGetGroupFromGpioPad (GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+
+ return GpioLockPadCfgForGroupDw (
+ Group,
+ GPIO_GET_DW_NUM (PadNumber),
+ 1 << GPIO_GET_PAD_POSITION (PadNumber)
+ );
+}
+
+/**
+ This procedure will clear PadCfgLockTx for selected pads within one group.
+ This function should be used only inside SMI.
+
+ @param[in] Group GPIO group
+ @param[in] DwNum PadCfgLockTx register number for current group.
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[in] PadsToUnlockTx Bitmask for pads which are going to be unlocked,
+ Bit position - PadNumber
+ Bit value - 0: DoNotUnLockTx, 1: LockTx
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioUnlockPadCfgTxForGroupDw (
+ IN GPIO_GROUP Group,
+ IN UINT32 DwNum,
+ IN UINT32 PadsToUnlockTx
+ )
+{
+ if (!GpioIsGroupAndDwNumValid (Group, DwNum)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return GpioWriteLockReg (
+ GpioPadLockOutputRegister,
+ Group,
+ DwNum,
+ ~PadsToUnlockTx,
+ 0
+ );
+}
+
+/**
+ This procedure will clear PadCfgLockTx for selected pad.
+ This function should be used only inside SMI.
+
+ @param[in] GpioPad GPIO pad
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioUnlockPadCfgTx (
+ IN GPIO_PAD GpioPad
+ )
+{
+ GPIO_GROUP Group;
+ UINT32 PadNumber;
+
+ Group = GpioGetGroupFromGpioPad (GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+
+ return GpioUnlockPadCfgTxForGroupDw (
+ Group,
+ GPIO_GET_DW_NUM (PadNumber),
+ 1 << GPIO_GET_PAD_POSITION (PadNumber)
+ );
+}
+
+/**
+ This procedure will set PadCfgLockTx for selected pads within one group
+
+ @param[in] Group GPIO group
+ @param[in] DwNum PadCfgLock register number for current group.
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[in] PadsToLockTx Bitmask for pads which are going to be locked,
+ Bit position - PadNumber
+ Bit value - 0: DoNotLockTx, 1: LockTx
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or DwNum parameter number
+**/
+EFI_STATUS
+GpioLockPadCfgTxForGroupDw (
+ IN GPIO_GROUP Group,
+ IN UINT32 DwNum,
+ IN UINT32 PadsToLockTx
+ )
+{
+ if (!GpioIsGroupAndDwNumValid (Group, DwNum)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return GpioWriteLockReg (
+ GpioPadLockOutputRegister,
+ Group,
+ DwNum,
+ ~0u,
+ PadsToLockTx
+ );
+}
+
+/**
+ This procedure will set PadCfgLockTx for selected pad
+
+ @param[in] GpioPad GPIO pad
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioLockPadCfgTx (
+ IN GPIO_PAD GpioPad
+ )
+{
+ GPIO_GROUP Group;
+ UINT32 PadNumber;
+
+ Group = GpioGetGroupFromGpioPad (GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+
+ return GpioLockPadCfgTxForGroupDw (
+ Group,
+ GPIO_GET_DW_NUM (PadNumber),
+ 1 << GPIO_GET_PAD_POSITION (PadNumber)
+ );
+}
+
+/**
+ This procedure will get Group to GPE mapping.
+ It will assume that only first 32 pads can be mapped to GPE.
+ To handle cases where groups have more than 32 pads and higher part of group
+ can be mapped please refer to GpioGetGroupDwToGpeDwX()
+
+ @param[out] GroupToGpeDw0 GPIO group to be mapped to GPE_DW0
+ @param[out] GroupToGpeDw1 GPIO group to be mapped to GPE_DW1
+ @param[out] GroupToGpeDw2 GPIO group to be mapped to GPE_DW2
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioGetGroupToGpeDwX (
+ IN GPIO_GROUP *GroupToGpeDw0,
+ IN GPIO_GROUP *GroupToGpeDw1,
+ IN GPIO_GROUP *GroupToGpeDw2
+ )
+{
+ UINT32 GroupDw[3];
+ UINT32 Index;
+ EFI_STATUS Status;
+
+ Status = GpioGetGroupDwToGpeDwX (
+ GroupToGpeDw0,
+ &GroupDw[0],
+ GroupToGpeDw1,
+ &GroupDw[1],
+ GroupToGpeDw2,
+ &GroupDw[2]
+ );
+
+ for (Index = 0; Index < ARRAY_SIZE (GroupDw); Index++) {
+ if (GroupDw[Index] != 0) {
+ Status = EFI_UNSUPPORTED;
+ ASSERT (FALSE);
+ }
+ }
+ return Status;
+}
+
+/**
+ This procedure will get Group to GPE mapping. If group has more than 32 bits
+ it is possible to map only single DW of pins (e.g. 0-31, 32-63) because
+ ACPI GPE_DWx register is 32 bits large.
+
+ @param[out] GroupToGpeDw0 GPIO group mapped to GPE_DW0
+ @param[out] GroupDwForGpeDw0 DW of pins mapped to GPE_DW0
+ @param[out] GroupToGpeDw1 GPIO group mapped to GPE_DW1
+ @param[out] GroupDwForGpeDw1 DW of pins mapped to GPE_DW1
+ @param[out] GroupToGpeDw2 GPIO group mapped to GPE_DW2
+ @param[out] GroupDwForGpeDw2 DW of pins mapped to GPE_DW2
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioGetGroupDwToGpeDwX (
+ OUT GPIO_GROUP *GroupToGpeDw0,
+ OUT UINT32 *GroupDwForGpeDw0,
+ OUT GPIO_GROUP *GroupToGpeDw1,
+ OUT UINT32 *GroupDwForGpeDw1,
+ OUT GPIO_GROUP *GroupToGpeDw2,
+ OUT UINT32 *GroupDwForGpeDw2
+ )
+{
+ UINT32 PmcGpeDwXValue[3];
+ GPIO_GROUP GroupToGpeDwX[3];
+ UINT32 GroupDwForGpeDwX[3];
+ UINT8 GpeDwXIndex;
+ UINT32 Index;
+ GPIO_GROUP_TO_GPE_MAPPING *GpioGpeMap;
+ UINT32 GpioGpeMapLength;
+
+ ZeroMem (GroupToGpeDwX, sizeof (GroupToGpeDwX));
+ ZeroMem (GroupDwForGpeDwX, sizeof (GroupDwForGpeDwX));
+
+ PmcGetGpioGpe (&PmcGpeDwXValue[0], &PmcGpeDwXValue[1], &PmcGpeDwXValue[2]);
+ GpioGetGroupToGpeMapping (&GpioGpeMap, &GpioGpeMapLength);
+ for (GpeDwXIndex = 0; GpeDwXIndex < 3; GpeDwXIndex++) {
+ for (Index = 0; Index < GpioGpeMapLength; Index++) {
+
+ if (GpioGpeMap[Index].PmcGpeDwxVal == PmcGpeDwXValue[GpeDwXIndex]) {
+ GroupToGpeDwX[GpeDwXIndex] = GpioGpeMap[Index].Group;
+ GroupDwForGpeDwX[GpeDwXIndex] = GpioGpeMap[Index].GroupDw;
+ break;
+ }
+ }
+ }
+
+ if ((GroupToGpeDwX[0] == 0) ||
+ (GroupToGpeDwX[1] == 0) ||
+ (GroupToGpeDwX[2] == 0)) {
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ *GroupToGpeDw0 = GroupToGpeDwX[0];
+ *GroupDwForGpeDw0 = GroupDwForGpeDwX[0];
+ *GroupToGpeDw1 = GroupToGpeDwX[1];
+ *GroupDwForGpeDw1 = GroupDwForGpeDwX[1];
+ *GroupToGpeDw2 = GroupToGpeDwX[2];
+ *GroupDwForGpeDw2 = GroupDwForGpeDwX[2];
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will get GPE number for provided GpioPad.
+ PCH allows to configure mapping between GPIO groups and related GPE (GpioSetGroupToGpeDwX())
+ what results in the fact that certain Pad can cause different General Purpose Event. Only three
+ GPIO groups can be mapped to cause unique GPE (1-tier), all others groups will be under one common
+ event (GPE_111 for 2-tier).
+
+ 1-tier:
+ Returned GpeNumber is in range <0,95>. GpioGetGpeNumber() can be used
+ to determine what _LXX ACPI method would be called on event on selected GPIO pad
+
+ 2-tier:
+ Returned GpeNumber is 0x6F (111). All GPIO pads which are not mapped to 1-tier GPE
+ will be under one master GPE_111 which is linked to _L6F ACPI method. If it is needed to determine
+ what Pad from 2-tier has caused the event, _L6F method should check GPI_GPE_STS and GPI_GPE_EN
+ registers for all GPIO groups not mapped to 1-tier GPE.
+
+ @param[in] GpioPad GPIO pad
+ @param[out] GpeNumber GPE number
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetGpeNumber (
+ IN GPIO_PAD GpioPad,
+ OUT UINT32 *GpeNumber
+ )
+{
+ GPIO_GROUP GroupToGpeDwX[3];
+ UINT32 GroupDw[3];
+ GPIO_GROUP Group;
+ UINT32 PadNumber;
+ UINT32 Index;
+
+ Group = GpioGetGroupFromGpioPad (GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+
+ if (!GpioIsPadValid (GpioPad)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Get GPIO groups mapping to 1-tier GPE
+ // This mapping is dependent on GPIO IP implementation
+ // and may change between chipset generations
+ //
+ GpioGetGroupDwToGpeDwX (
+ &GroupToGpeDwX[0], &GroupDw[0],
+ &GroupToGpeDwX[1], &GroupDw[1],
+ &GroupToGpeDwX[2], &GroupDw[2]
+ );
+
+ //
+ // Check if pad is routed to 1-Tier GPE
+ //
+ for (Index = 0; Index < 3; Index++) {
+ if ((Group == GroupToGpeDwX[Index]) && (PadNumber >= (32 * GroupDw[Index])) && (PadNumber < (32 * (GroupDw[Index] + 1)))) {
+ *GpeNumber = PadNumber + (32 * Index) - (32 * GroupDw[Index]);
+ return EFI_SUCCESS;
+ }
+ }
+
+ //
+ // If Group number doesn't match any of above then
+ // it means that the pad is routed to 2-tier GPE
+ // which corresponds to GPE_111 (0x6F)
+ //
+ *GpeNumber = PCH_GPIO_2_TIER_MASTER_GPE_NUMBER;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure is used to clear SMI STS for a specified Pad
+
+ @param[in] GpioPad GPIO pad
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioClearGpiSmiSts (
+ IN GPIO_PAD GpioPad
+ )
+{
+ GPIO_GROUP Group;
+ UINT32 PadNumber;
+ UINT32 DwNum;
+ UINT32 PadBitPosition;
+
+ if (!GpioIsPadValid (GpioPad)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Group = GpioGetGroupFromGpioPad (GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+ DwNum = GPIO_GET_DW_NUM (PadNumber);
+ PadBitPosition = GPIO_GET_PAD_POSITION (PadNumber);
+
+ //
+ // Clear GPI SMI Status bit by writing '1'
+ //
+ return GpioWriteReg (
+ GpioSmiStatusRegister,
+ Group,
+ DwNum,
+ 0u,
+ (UINT32) (BIT0 << PadBitPosition)
+ );
+}
+
+/**
+ This procedure is used by PchSmiDispatcher and will clear
+ all GPI SMI Status bits
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioClearAllGpiSmiSts (
+ VOID
+ )
+{
+ UINT32 DwNum;
+ GPIO_GROUP Group;
+ GPIO_GROUP GroupMin;
+ GPIO_GROUP GroupMax;
+
+ GroupMin = GpioGetLowestGroup ();
+ GroupMax = GpioGetHighestGroup ();
+
+ for (Group = GroupMin; Group <= GroupMax; Group++) {
+ //
+ // Clear all GPI SMI STS
+ //
+ for (DwNum = 0; DwNum <= GPIO_GET_DW_NUM (GpioGetPadPerGroup (Group)); DwNum++) {
+ GpioWriteReg (
+ GpioSmiStatusRegister,
+ Group,
+ DwNum,
+ 0u,
+ 0xFFFFFFFF
+ );
+ }
+ }
+ return EFI_SUCCESS;
+
+}
+
+/**
+ This procedure is used to disable all GPI SMI
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioDisableAllGpiSmi (
+ VOID
+ )
+{
+ UINT32 DwNum;
+ GPIO_GROUP Group;
+ GPIO_GROUP GroupMin;
+ GPIO_GROUP GroupMax;
+ UINT32 SmiEnRegVal;
+
+ GroupMin = GpioGetLowestGroup ();
+ GroupMax = GpioGetHighestGroup ();
+
+ for (Group = GroupMin; Group <= GroupMax; Group++) {
+ //
+ // Disable all GPI SMI
+ //
+ for (DwNum = 0; DwNum <= GPIO_GET_DW_NUM (GpioGetPadPerGroup (Group)); DwNum++) {
+ //
+ // Check which pins have SMI_EN set
+ //
+ GpioReadReg (
+ GpioSmiEnableRegister,
+ Group,
+ DwNum,
+ &SmiEnRegVal
+ );
+ //
+ // Set HOSTSW_OWN to GPIO mode (1) for those pins to disable SMI capability
+ //
+ GpioWriteReg (
+ GpioHostOwnershipRegister,
+ Group,
+ DwNum,
+ ~0u,
+ SmiEnRegVal
+ );
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure is used to register GPI SMI dispatch function.
+
+ @param[in] GpioPad GPIO pad
+ @param[out] GpiNum GPI number
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetGpiSmiNum (
+ IN GPIO_PAD GpioPad,
+ OUT UINTN *GpiNum
+ )
+{
+ UINT32 GroupIndex;
+ UINT32 Index;
+ UINT32 PadNumber;
+ CONST GPIO_GROUP_INFO *GpioGroupInfo;
+ UINT32 GpioGroupInfoLength;
+
+ GroupIndex = GpioGetGroupIndexFromGpioPad (GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+
+ if (!GpioIsPadValid (GpioPad)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+
+ *GpiNum = 0;
+
+ for (Index = 0; Index < GroupIndex; Index++) {
+ *GpiNum += (UINTN) (GpioGroupInfo[Index].PadPerGroup);
+ }
+ *GpiNum += (UINTN) PadNumber;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure is used to check GPIO inputs belongs to 2 tier or 1 tier architecture
+
+ @param[in] GpioPad GPIO pad
+
+ @retval Data 0 means 1-tier, 1 means 2-tier
+**/
+BOOLEAN
+GpioCheckFor2Tier (
+ IN GPIO_PAD GpioPad
+ )
+{
+ UINT32 Data32;
+
+ GpioGetGpeNumber (GpioPad, &Data32);
+ if (Data32 == PCH_GPIO_2_TIER_MASTER_GPE_NUMBER) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ This procedure is used to clear GPE STS for a specified GpioPad
+
+ @param[in] GpioPad GPIO pad
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioClearGpiGpeSts (
+ IN GPIO_PAD GpioPad
+ )
+{
+ GPIO_GROUP Group;
+ UINT32 PadNumber;
+ UINT32 DwNum;
+ UINT32 PadBitPosition;
+
+ if (!GpioIsPadValid (GpioPad)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Check for 2-tier
+ //
+ if (!(GpioCheckFor2Tier (GpioPad))) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Group = GpioGetGroupFromGpioPad (GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+ DwNum = GPIO_GET_DW_NUM (PadNumber);
+ PadBitPosition = GPIO_GET_PAD_POSITION (PadNumber);
+
+ //
+ // Clear GPI GPE Status bit by writing '1'
+ //
+ return GpioWriteReg (
+ GpioGpeStatusRegister,
+ Group,
+ DwNum,
+ 0u,
+ (UINT32) (BIT0 << PadBitPosition)
+ );
+}
+
+/**
+ This procedure is used to read GPE STS for a specified Pad
+
+ @param[in] GpioPad GPIO pad
+ @param[out] GpeSts Gpe status for given pad
+ The GpeSts is true if the status register is set for given Pad number
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetGpiGpeSts (
+ IN GPIO_PAD GpioPad,
+ OUT BOOLEAN *GpeSts
+ )
+{
+ UINT32 GpeStsRegVal;
+ GPIO_GROUP Group;
+ UINT32 PadNumber;
+ UINT32 DwNum;
+ UINT32 PadBitPosition;
+
+ if (!GpioIsPadValid (GpioPad)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Check for 2-tier
+ //
+ if (!(GpioCheckFor2Tier (GpioPad))) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Group = GpioGetGroupFromGpioPad (GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+ DwNum = GPIO_GET_DW_NUM (PadNumber);
+ PadBitPosition = GPIO_GET_PAD_POSITION (PadNumber);
+
+ //
+ // Read GPI GPE Status bits
+ //
+ GpioReadReg (
+ GpioGpeStatusRegister,
+ Group,
+ DwNum,
+ &GpeStsRegVal
+ );
+
+ *GpeSts = ((GpeStsRegVal >> PadBitPosition) & 0x1) != 0;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure is used to get SMI STS for a specified Pad
+
+ @param[in] GpioPad GPIO pad
+ @param[out] SmiSts Smi status for given pad
+ The SmiSts is true if the status register is set for given Pad number
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetGpiSmiSts (
+ IN GPIO_PAD GpioPad,
+ OUT BOOLEAN *SmiSts
+ )
+{
+ GPIO_GROUP Group;
+ UINT32 PadNumber;
+ UINT32 DwNum;
+ UINT32 PadBitPosition;
+ UINT32 SmiStsRegister;
+
+ if (!GpioIsPadValid (GpioPad)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Group = GpioGetGroupFromGpioPad (GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+ DwNum = GPIO_GET_DW_NUM (PadNumber);
+ PadBitPosition = GPIO_GET_PAD_POSITION (PadNumber);
+
+ //
+ // Read the SMI Register
+ //
+ GpioReadReg (
+ GpioSmiStatusRegister,
+ Group,
+ DwNum,
+ &SmiStsRegister
+ );
+
+ *SmiSts = (SmiStsRegister & (BIT0 << PadBitPosition)) != 0;
+
+ return EFI_SUCCESS;
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/Library/PeiDxeSmmGpioLib/GpioLibrary.h b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/Library/PeiDxeSmmGpioLib/GpioLibrary.h
new file mode 100644
index 0000000000..d197ee4898
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/Library/PeiDxeSmmGpioLib/GpioLibrary.h
@@ -0,0 +1,82 @@
+/** @file
+ Header file for GPIO Lib implementation.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _GPIO_LIBRARY_H_
+#define _GPIO_LIBRARY_H_
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/GpioLib.h>
+#include <Library/GpioNativeLib.h>
+#include <Library/GpioPrivateLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/SataLib.h>
+#include <Library/PchCycleDecodingLib.h>
+#include <Library/PchSbiAccessLib.h>
+#include <Library/PmcPrivateLib.h>
+#include <Library/GpioHelpersLib.h>
+#include <Register/GpioRegs.h>
+
+//
+// Number of PADCFG_DW registers
+//
+#define GPIO_PADCFG_DW_REG_NUMBER 4
+
+/**
+ This internal procedure will calculate GPIO_RESET_CONFIG value (new type)
+ based on provided PadRstCfg for a specific GPIO Pad.
+
+ @param[in] GpioPad GPIO Pad
+ @param[in] PadRstCfg GPIO PadRstCfg value
+
+ @retval GpioResetConfig GPIO Reset configuration (new type)
+**/
+GPIO_RESET_CONFIG
+GpioResetConfigFromPadRstCfg (
+ IN GPIO_PAD GpioPad,
+ IN UINT32 PadRstCfg
+ );
+
+/**
+ This internal procedure will calculate PadRstCfg register value based
+ on provided GPIO Reset configuration for a certain pad.
+
+ @param[in] GpioPad GPIO Pad
+ @param[in] GpioResetConfig GPIO Reset configuration
+ @param[out] PadRstCfg GPIO PadRstCfg value
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid configuration
+**/
+EFI_STATUS
+GpioPadRstCfgFromResetConfig (
+ IN GPIO_PAD GpioPad,
+ IN GPIO_RESET_CONFIG GpioResetConfig,
+ OUT UINT32 *PadRstCfg
+ );
+
+/**
+ This procedure will calculate PADCFG register value based on GpioConfig data
+
+ @param[in] GpioPad GPIO Pad
+ @param[in] GpioConfig GPIO Configuration data
+ @param[out] PadCfgDwReg PADCFG DWx register value
+ @param[out] PadCfgDwRegMask Mask with PADCFG DWx register bits to be modified
+
+ @retval Status
+**/
+EFI_STATUS
+GpioPadCfgRegValueFromGpioConfig (
+ IN GPIO_PAD GpioPad,
+ IN CONST GPIO_CONFIG *GpioConfig,
+ OUT UINT32 *PadCfgDwReg,
+ OUT UINT32 *PadCfgDwRegMask
+ );
+
+#endif // _GPIO_LIBRARY_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/Library/PeiDxeSmmGpioLib/GpioNames.c b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/Library/PeiDxeSmmGpioLib/GpioNames.c
new file mode 100644
index 0000000000..d21e77ba60
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/Library/PeiDxeSmmGpioLib/GpioNames.c
@@ -0,0 +1,86 @@
+/** @file
+ This file contains GPIO name library implementation
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "GpioLibrary.h"
+#include <Library/PrintLib.h>
+
+/**
+ Generates GPIO group name from GpioPad
+
+ @param[in] GpioPad GpioPad
+
+ @retval CHAR8* Pointer to the GPIO group name
+**/
+CONST
+CHAR8*
+GpioGetGroupName (
+ IN UINT32 GroupIndex
+ )
+{
+ CONST GPIO_GROUP_NAME_INFO* GroupNameInfo;
+
+ GroupNameInfo = GpioGetGroupNameInfo (GroupIndex);
+ if (GroupNameInfo == NULL) {
+ return NULL;
+ } else {
+ return GroupNameInfo->GpioGroupPrefix;
+ }
+}
+
+/**
+ Generates GPIO name from GpioPad
+
+ @param[in] GpioPad GpioPad
+ @param[out] GpioNameBuffer Caller allocated buffer of GPIO_NAME_LENGTH_MAX size
+ @param[in] GpioNameBufferSize Size of the buffer
+
+ @retval CHAR8* Pointer to the GPIO name
+**/
+CHAR8*
+GpioGetPadName (
+ IN GPIO_PAD GpioPad,
+ OUT CHAR8* GpioNameBuffer,
+ IN UINT32 GpioNameBufferSize
+ )
+{
+ UINT32 GroupIndex;
+ UINT32 PadNumber;
+ UINT32 FirstUniquePadNumber;
+ CONST GPIO_GROUP_NAME_INFO* GroupNameInfo;
+
+ if (GpioNameBuffer == NULL) {
+ ASSERT (FALSE);
+ return NULL;
+ }
+ if ((GpioNameBufferSize < GPIO_NAME_LENGTH_MAX) || !GpioIsPadValid (GpioPad)) {
+ ASSERT (FALSE);
+ *GpioNameBuffer = 0;
+ return NULL;
+ }
+
+ GroupIndex = GpioGetGroupIndexFromGpioPad (GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+ GroupNameInfo = GpioGetGroupNameInfo (GroupIndex);
+ if (GroupNameInfo == NULL) {
+ return NULL;
+ }
+
+ FirstUniquePadNumber = GpioGetPadNumberFromGpioPad (GroupNameInfo->FirstUniqueGpio);
+ if ((PadNumber < FirstUniquePadNumber) || (GroupNameInfo->GroupUniqueNames == NULL)) {
+ AsciiSPrint (GpioNameBuffer, GPIO_NAME_LENGTH_MAX, "GPIO_%a%d", GpioGetGroupName (GroupIndex), PadNumber);
+ } else {
+ if ((PadNumber - FirstUniquePadNumber) < GroupNameInfo->UniqueNamesTableSize) {
+ AsciiSPrint (GpioNameBuffer, GPIO_NAME_LENGTH_MAX, "GPIO_%a", GroupNameInfo->GroupUniqueNames[PadNumber - FirstUniquePadNumber]);
+ } else {
+ AsciiSPrint (GpioNameBuffer, GPIO_NAME_LENGTH_MAX, "GPIO_%08X", GpioPad);
+ ASSERT (FALSE);
+ }
+ }
+
+ return GpioNameBuffer;
+}
+
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/Library/PeiDxeSmmGpioLib/GpioNativeLib.c b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/Library/PeiDxeSmmGpioLib/GpioNativeLib.c
new file mode 100644
index 0000000000..97244c665b
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/Library/PeiDxeSmmGpioLib/GpioNativeLib.c
@@ -0,0 +1,193 @@
+/** @file
+ This file contains routines for GPIO native and chipset specific usage
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include "GpioLibrary.h"
+
+/**
+ This procedure will get number of pads for certain GPIO group
+
+ @param[in] Group GPIO group number
+
+ @retval Value Pad number for group
+ If illegal group number then return 0
+**/
+UINT32
+GpioGetPadPerGroup (
+ IN GPIO_GROUP Group
+ )
+{
+ CONST GPIO_GROUP_INFO *GpioGroupInfo;
+ UINT32 GpioGroupInfoLength;
+ UINT32 GroupIndex;
+ //
+ // Check if group argument exceeds GPIO GROUP INFO array
+ //
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+ GroupIndex = GpioGetGroupIndexFromGroup (Group);
+
+ if ((UINTN) GroupIndex >= GpioGroupInfoLength) {
+ return 0;
+ } else {
+ return GpioGroupInfo[GroupIndex].PadPerGroup;
+ }
+}
+
+/**
+ This procedure will get number of groups
+
+ @param[in] none
+
+ @retval Value Group number
+**/
+UINT32
+GpioGetNumberOfGroups (
+ VOID
+ )
+{
+ UINT32 GpioGroupInfoLength;
+
+ GpioGetGroupInfoTable (&GpioGroupInfoLength);
+ return GpioGroupInfoLength;
+}
+/**
+ This procedure will get lowest group
+
+ @param[in] none
+
+ @retval Value Lowest Group
+**/
+GPIO_GROUP
+GpioGetLowestGroup (
+ VOID
+ )
+{
+ return GpioGetGroupFromGroupIndex (0);
+}
+/**
+ This procedure will get highest group
+
+ @param[in] none
+
+ @retval Value Highest Group
+**/
+GPIO_GROUP
+GpioGetHighestGroup (
+ VOID
+ )
+{
+ return GpioGetGroupFromGroupIndex (GpioGetNumberOfGroups () - 1);
+}
+
+/**
+ This procedure will get group number
+
+ @param[in] GpioPad Gpio Pad
+
+ @retval Value Group number
+**/
+GPIO_GROUP
+GpioGetGroupFromGpioPad (
+ IN GPIO_PAD GpioPad
+ )
+{
+ return GPIO_GET_GROUP_FROM_PAD (GpioPad);
+}
+
+/**
+ This procedure will get group index (0 based)
+
+ @param[in] GpioPad Gpio Pad
+
+ @retval Value Group Index
+**/
+UINT32
+GpioGetGroupIndexFromGpioPad (
+ IN GPIO_PAD GpioPad
+ )
+{
+ return (UINT32) GPIO_GET_GROUP_INDEX_FROM_PAD (GpioPad);
+}
+
+/**
+ This procedure will get group index (0 based) from group
+
+ @param[in] GpioGroup Gpio Group
+
+ @retval Value Group Index
+**/
+UINT32
+GpioGetGroupIndexFromGroup (
+ IN GPIO_GROUP GpioGroup
+ )
+{
+ return (UINT32) GPIO_GET_GROUP_INDEX (GpioGroup);
+}
+
+/**
+ This procedure will get group from group index (0 based)
+
+ @param[in] GroupIndex Group Index
+
+ @retval GpioGroup Gpio Group
+**/
+GPIO_GROUP
+GpioGetGroupFromGroupIndex (
+ IN UINT32 GroupIndex
+ )
+{
+ return GPIO_GROUP_DEF (GroupIndex, GpioGetThisChipsetId ());
+}
+
+/**
+ This procedure will get pad number (0 based) from Gpio Pad
+
+ @param[in] GpioPad Gpio Pad
+
+ @retval Value Pad Number
+**/
+UINT32
+GpioGetPadNumberFromGpioPad (
+ IN GPIO_PAD GpioPad
+ )
+{
+ return (UINT32) GPIO_GET_PAD_NUMBER (GpioPad);
+}
+/**
+ This procedure will return GpioPad from Group and PadNumber
+
+ @param[in] Group GPIO group
+ @param[in] PadNumber GPIO PadNumber
+
+ @retval GpioPad GpioPad
+**/
+GPIO_PAD
+GpioGetGpioPadFromGroupAndPadNumber (
+ IN GPIO_GROUP Group,
+ IN UINT32 PadNumber
+ )
+{
+ return GPIO_PAD_DEF (Group,PadNumber);
+}
+
+/**
+ This procedure will return GpioPad from GroupIndex and PadNumber
+
+ @param[in] GroupIndex GPIO GroupIndex
+ @param[in] PadNumber GPIO PadNumber
+
+ @retval GpioPad GpioPad
+**/
+GPIO_PAD
+GpioGetGpioPadFromGroupIndexAndPadNumber (
+ IN UINT32 GroupIndex,
+ IN UINT32 PadNumber
+ )
+{
+ GPIO_GROUP Group;
+
+ Group = GPIO_GROUP_DEF (GroupIndex, GpioGetThisChipsetId ());
+ return GPIO_PAD_DEF (Group, PadNumber);
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/Library/PeiDxeSmmGpioLib/PeiDxeSmmGpioLib.inf b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/Library/PeiDxeSmmGpioLib/PeiDxeSmmGpioLib.inf
new file mode 100644
index 0000000000..0a888a38ba
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/Library/PeiDxeSmmGpioLib/PeiDxeSmmGpioLib.inf
@@ -0,0 +1,49 @@
+## @file
+# Component description file for the PeiDxeSmmGpioLib
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiDxeSmmGpioLib
+FILE_GUID = 16EC5CA8-8195-4847-B6CB-662BD7B763F2
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = GpioLib
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+
+
+[LibraryClasses]
+BaseLib
+IoLib
+DebugLib
+PrintLib
+PchCycleDecodingLib
+PchSbiAccessLib
+PmcPrivateLib
+GpioPrivateLib
+SataLib
+GpioHelpersLib
+GpioCheckConflictLib
+
+[Packages]
+MdePkg/MdePkg.dec
+TigerlakeSiliconPkg/SiPkg.dec
+
+[Pcd]
+
+[Sources]
+GpioLib.c
+GpioNativeLib.c
+GpioInit.c
+GpioNames.c
+GpioLibrary.h
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/BaseGpioHelpersLibNull/BaseGpioHelpersLibNull.c b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/BaseGpioHelpersLibNull/BaseGpioHelpersLibNull.c
new file mode 100644
index 0000000000..2c7a1987d9
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/BaseGpioHelpersLibNull/BaseGpioHelpersLibNull.c
@@ -0,0 +1,119 @@
+/** @file
+ This file contains NULL implementation for GPIO Helpers Lib
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include <Uefi/UefiBaseType.h>
+#include <Library/GpioConfig.h>
+
+/**
+ This procedure stores GPIO pad unlock information
+
+ @param[in] GpioPad GPIO pad
+ @param[in] GpioLockConfig GPIO Lock Configuration
+
+ @retval Status
+**/
+EFI_STATUS
+GpioStoreUnlockData (
+ IN GPIO_PAD GpioPad,
+ IN GPIO_LOCK_CONFIG GpioLockConfig
+ )
+{
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure stores GPIO group data about pads which PadConfig needs to be unlocked.
+
+ @param[in] GroupIndex GPIO group index
+ @param[in] DwNum DWORD index for a group.
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[in] UnlockedPads DWORD bitmask for pads which are going to be left unlocked
+ Bit position - PadNumber
+ Bit value - 0: Skip, 1: Leave unlocked
+
+ @retval Status
+**/
+EFI_STATUS
+GpioStoreGroupDwUnlockPadConfigData (
+ IN UINT32 GroupIndex,
+ IN UINT32 DwNum,
+ IN UINT32 UnlockedPads
+ )
+{
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure stores GPIO group data about pads which Output state needs to be unlocked.
+
+ @param[in] GroupIndex GPIO group index
+ @param[in] DwNum DWORD index for a group.
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[in] UnlockedPads DWORD bitmask for pads which are going to be left unlocked
+ Bit position - PadNumber
+ Bit value - 0: Skip, 1: Leave unlocked
+ @retval Status
+**/
+EFI_STATUS
+GpioStoreGroupDwUnlockOutputData (
+ IN UINT32 GroupIndex,
+ IN UINT32 DwNum,
+ IN UINT32 UnlockedPads
+ )
+{
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will get GPIO group data with pads, which PadConfig is supposed to be left unlock
+
+ @param[in] GroupIndex GPIO group index
+ @param[in] DwNum DWORD index for a group.
+ For group which has less then 32 pads per group DwNum must be 0.
+ @retval UnlockedPads DWORD bitmask for pads which are going to be left unlocked
+ Bit position - PadNumber
+ Bit value - 0: to be locked, 1: Leave unlocked
+**/
+UINT32
+GpioGetGroupDwUnlockPadConfigMask (
+ IN UINT32 GroupIndex,
+ IN UINT32 DwNum
+ )
+{
+ return 0;
+}
+
+/**
+ This procedure will get GPIO group data with pads, which Output is supposed to be left unlock
+
+ @param[in] GroupIndex GPIO group index
+ @param[in] DwNum DWORD index for a group.
+ For group which has less then 32 pads per group DwNum must be 0.
+ @retval UnlockedPads DWORD bitmask for pads which are going to be left unlocked
+ Bit position - PadNumber
+ Bit value - 0: to be locked, 1: Leave unlocked
+**/
+UINT32
+GpioGetGroupDwUnlockOutputMask (
+ IN UINT32 GroupIndex,
+ IN UINT32 DwNum
+ )
+{
+ return 0;
+}
+
+/**
+ Returns Gpio Override Level1 Information
+
+ @retval TRUE/FALSE GPIO Override Level 1 Enabled/Disabled
+**/
+BOOLEAN
+GpioOverrideLevel1Enabled (
+ VOID
+ )
+{
+ return FALSE;
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/BaseGpioHelpersLibNull/BaseGpioHelpersLibNull.inf b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/BaseGpioHelpersLibNull/BaseGpioHelpersLibNull.inf
new file mode 100644
index 0000000000..756359d1e3
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/BaseGpioHelpersLibNull/BaseGpioHelpersLibNull.inf
@@ -0,0 +1,26 @@
+## @file
+# Component description file for the NULL GpioHelpersLib
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = BaseGpioHelpersLib
+FILE_GUID = AB282608-2A50-4AE3-9242-64064ECF40D4
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = GpioHelpersLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+TigerlakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+BaseGpioHelpersLibNull.c
+
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/DxeGpioNameBufferLib/DxeGpioNameBufferLib.inf b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/DxeGpioNameBufferLib/DxeGpioNameBufferLib.inf
new file mode 100644
index 0000000000..43860b7d20
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/DxeGpioNameBufferLib/DxeGpioNameBufferLib.inf
@@ -0,0 +1,32 @@
+## @file
+# Component description file for the DxeGpioMemLib
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = DxeGpioNameBufferLib
+FILE_GUID = 16EC6AA8-81D5-4847-B6CB-662CDAB863F2
+VERSION_STRING = 1.0
+MODULE_TYPE = DXE_DRIVER
+LIBRARY_CLASS = GpioNameBufferLib
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[LibraryClasses]
+BaseLib
+
+[Packages]
+MdePkg/MdePkg.dec
+TigerlakeSiliconPkg/SiPkg.dec
+
+[Sources]
+GpioNameBufferDxe.c
+
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/DxeGpioNameBufferLib/GpioNameBufferDxe.c b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/DxeGpioNameBufferLib/GpioNameBufferDxe.c
new file mode 100644
index 0000000000..87dc9a2cd5
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/DxeGpioNameBufferLib/GpioNameBufferDxe.c
@@ -0,0 +1,19 @@
+/** @file
+ This file contains implementation of the GpioMemLib for DXE phase
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/GpioNameBufferLib.h>
+
+STATIC CHAR8 mGpioNameBuffer[GPIO_NAME_LENGTH_MAX];
+
+CHAR8*
+GpioGetStaticNameBuffer (
+ VOID
+ )
+{
+ return mGpioNameBuffer;
+}
+
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/DxeGpioPolicyLib/DxeGpioPolicyLib.c b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/DxeGpioPolicyLib/DxeGpioPolicyLib.c
new file mode 100644
index 0000000000..e9fe6f04e0
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/DxeGpioPolicyLib/DxeGpioPolicyLib.c
@@ -0,0 +1,87 @@
+/** @file
+ This file provides services for Gpio policy function
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include <Uefi.h>
+#include <Library/DebugLib.h>
+#include <Library/SiConfigBlockLib.h>
+#include <Library/ConfigBlockLib.h>
+#include <Protocol/PchPolicy.h>
+#include <ConfigBlock/Gpio/GpioDevConfig.h>
+
+/**
+ Print GPIO_DXE_CONFIG and serial out.
+
+ @param[in] PchPolicy Pointer to a PCH_POLICY_PROTOCOL
+**/
+VOID
+GpioDxePrintConfig (
+ IN PCH_POLICY_PROTOCOL *PchPolicy
+ )
+{
+ EFI_STATUS Status;
+ GPIO_DXE_CONFIG *GpioDxeConfig;
+
+ Status = GetConfigBlock ((VOID *) PchPolicy, &gGpioDxeConfigGuid, (VOID *) &GpioDxeConfig);
+ ASSERT_EFI_ERROR (Status);
+
+ DEBUG ((DEBUG_INFO, "------------------ GPIO DXE Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, " HideGpioAcpiDevice : %d\n", GpioDxeConfig->HideGpioAcpiDevice));
+}
+
+/**
+ Load DXE Config block default for GPIO
+
+ @param[in] ConfigBlockPointer Pointer to config block
+**/
+VOID
+GpioDxeLoadConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ GPIO_DXE_CONFIG *GpioDxeConfig;
+ GpioDxeConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "GpioDxeConfig->Header.GuidHob.Name = %g\n", &GpioDxeConfig->Header.GuidHob.Name));
+ DEBUG ((DEBUG_INFO, "GpioDxeConfig->Header.GuidHob.Header.HobLength = 0x%x\n", GpioDxeConfig->Header.GuidHob.Header.HobLength));
+
+ GpioDxeConfig->HideGpioAcpiDevice = 0;
+}
+
+STATIC COMPONENT_BLOCK_ENTRY mGpioBlocks = {
+ &gGpioDxeConfigGuid,
+ sizeof (GPIO_DXE_CONFIG),
+ GPIO_DXE_CONFIG_REVISION,
+ GpioDxeLoadConfigDefault
+};
+
+/**
+ Get Gpio config block table size.
+
+ @retval Size of config block
+**/
+UINT16
+GpioDxeGetConfigBlockTotalSize (
+ VOID
+ )
+{
+ return mGpioBlocks.Size;
+}
+
+/**
+ Add Gpio ConfigBlock.
+
+ @param[in] ConfigBlockTableAddress The pointer to config block table
+
+ @retval EFI_SUCCESS The policy default is initialized.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create buffer
+**/
+EFI_STATUS
+GpioDxeAddConfigBlock (
+ IN VOID *ConfigBlockTableAddress
+ )
+{
+ return AddComponentConfigBlocks (ConfigBlockTableAddress, &mGpioBlocks, 1);
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/DxeGpioPolicyLib/DxeGpioPolicyLib.inf b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/DxeGpioPolicyLib/DxeGpioPolicyLib.inf
new file mode 100644
index 0000000000..1b9d53f40c
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/DxeGpioPolicyLib/DxeGpioPolicyLib.inf
@@ -0,0 +1,31 @@
+## @file
+# Component description file for the Gpio policy library
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = DxeGpioPolicyLib
+FILE_GUID = 2D2B8ECA-E343-4036-A289-3F39545AEA06
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = DxeGpioPolicyLib
+
+[LibraryClasses]
+DebugLib
+ConfigBlockLib
+SiConfigBlockLib
+
+[Packages]
+MdePkg/MdePkg.dec
+TigerlakeSiliconPkg/SiPkg.dec
+
+[Sources]
+DxeGpioPolicyLib.c
+
+[Guids]
+gGpioDxeConfigGuid ## CONSUMES
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/PeiDxeSmmGpioPrivateLib/GpioNamesVer2.c b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/PeiDxeSmmGpioPrivateLib/GpioNamesVer2.c
new file mode 100644
index 0000000000..4084583122
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/PeiDxeSmmGpioPrivateLib/GpioNamesVer2.c
@@ -0,0 +1,88 @@
+/** @file
+ This file contains GPIO name library implementation specific to Ver2
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include <Base.h>
+#include <Library/BaseLib.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/DebugLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/GpioPrivateLib.h>
+#include <Pins/GpioPinsVer2Lp.h>
+
+STATIC CONST CHAR8* mGpioGppbNames[] = {
+ "GSPI0_CLK_LOOPBK",
+ "GSPI1_CLK_LOOPBK"
+};
+
+STATIC CONST CHAR8* mGpioGppaNames[] = {
+ "SPI0_CLK_LOOPBK",
+ "ESPI_CLK_LOOPBK"
+};
+
+STATIC CONST CHAR8* mPchLpGpioGpdNames[] = {
+ "INPUT3VSEL",
+ "SLP_LANB",
+ "SLP_SUSB",
+ "SLP_WAKEB",
+ "SLP_DRAM_RESETB"
+};
+
+STATIC CONST CHAR8* mPchLpGpioGppdNames[] = {
+ "GSPI2_CLK_LOOPBK"
+};
+
+STATIC CONST CHAR8* mGpioGppfNames[] = {
+ "GPPF_CLK_LOOPBK"
+};
+
+STATIC CONST CHAR8* mGpioGppeNames[] = {
+ "GPPE_CLK_LOOPBK"
+};
+
+
+STATIC CONST GPIO_GROUP_NAME_INFO mPchLpGroupDescriptors[] = {
+ GPIO_GROUP_NAME("GPP_B", GPIO_VER2_LP_GSPI0_CLK_LOOPBK, mGpioGppbNames),
+ GPIO_GROUP_NAME_BASIC(""),
+ GPIO_GROUP_NAME("GPP_A", GPIO_VER2_LP_ESPI_CLK_LOOPBK, mGpioGppaNames),
+ GPIO_GROUP_NAME_BASIC("GPP_R"),
+ GPIO_GROUP_NAME_BASIC(""),
+ GPIO_GROUP_NAME("GPD", GPIO_VER2_LP_INPUT3VSEL, mPchLpGpioGpdNames),
+ GPIO_GROUP_NAME_BASIC("GPP_S"),
+ GPIO_GROUP_NAME_BASIC("GPP_H"),
+ GPIO_GROUP_NAME("GPP_D", GPIO_VER2_LP_GSPI2_CLK_LOOPBK, mPchLpGpioGppdNames),
+ GPIO_GROUP_NAME_BASIC(""),
+ GPIO_GROUP_NAME_BASIC(""),
+ GPIO_GROUP_NAME_BASIC("GPP_C"),
+ GPIO_GROUP_NAME("GPP_F", GPIO_VER2_LP_GPPF_CLK_LOOPBK, mGpioGppfNames),
+ GPIO_GROUP_NAME_BASIC(""),
+ GPIO_GROUP_NAME("GPP_E", GPIO_VER2_LP_GPPE_CLK_LOOPBK, mGpioGppeNames),
+ GPIO_GROUP_NAME_BASIC(""),
+ GPIO_GROUP_NAME_BASIC(""),
+ GPIO_GROUP_NAME_BASIC("")
+};
+
+/**
+ Returns GPIO_GROUP_NAME_INFO corresponding to the given GpioPad
+
+ @param[in] GroupIndex Group index
+
+ @retval GPIO_GROUP_NAME_INFO* Pointer to the GPIO_GROUP_NAME_INFO
+ @reval NULL If no group descriptor was found
+**/
+CONST
+GPIO_GROUP_NAME_INFO*
+GpioGetGroupNameInfo (
+ IN UINT32 GroupIndex
+ )
+{
+ if (GroupIndex < ARRAY_SIZE (mPchLpGroupDescriptors)) {
+ return &mPchLpGroupDescriptors[GroupIndex];
+ }
+
+ ASSERT (FALSE);
+ return NULL;
+}
+
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/PeiDxeSmmGpioPrivateLib/GpioPrivateLib.c b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/PeiDxeSmmGpioPrivateLib/GpioPrivateLib.c
new file mode 100644
index 0000000000..f750d77e9a
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/PeiDxeSmmGpioPrivateLib/GpioPrivateLib.c
@@ -0,0 +1,395 @@
+/** @file
+ This file contains GPIO routines for RC usage
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/GpioLib.h>
+#include <Library/GpioNativeLib.h>
+#include <Library/GpioPrivateLib.h>
+#include <Library/GpioNameBufferLib.h>
+#include <Register/PchPcrRegs.h>
+#include <Register/GpioRegs.h>
+
+/**
+ This procedure is used to check if GpioPad is valid for certain chipset
+
+ @param[in] GpioPad GPIO pad
+
+ @retval TRUE This pin is valid on this chipset
+ FALSE Incorrect pin
+**/
+BOOLEAN
+GpioIsCorrectPadForThisChipset (
+ IN GPIO_PAD GpioPad
+ )
+{
+ return ((GPIO_GET_CHIPSET_ID (GpioPad) == GpioGetThisChipsetId ()) &&
+ (GpioGetGroupIndexFromGpioPad (GpioPad) < GpioGetNumberOfGroups ()));
+}
+
+/**
+ This procedure is used by PchSmiDispatcher and will return information
+ needed to register GPI SMI.
+
+ @param[in] Index GPI SMI number
+ @param[out] GpioPin GPIO pin
+ @param[out] GpiSmiBitOffset GPI SMI bit position within GpiSmi Registers
+ @param[out] GpiHostSwOwnRegAddress Address of HOSTSW_OWN register
+ @param[out] GpiSmiStsRegAddress Address of GPI SMI status register
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioGetPadAndSmiRegs (
+ IN UINT32 Index,
+ OUT GPIO_PAD *GpioPin,
+ OUT UINT8 *GpiSmiBitOffset,
+ OUT UINT32 *GpiHostSwOwnRegAddress,
+ OUT UINT32 *GpiSmiStsRegAddress
+ )
+{
+ UINT32 GroupIndex;
+ UINT32 PadNumber;
+ CONST GPIO_GROUP_INFO *GpioGroupInfo;
+ GPIO_GROUP GpioGroup;
+ UINT32 GpioGroupInfoLength;
+ UINT32 SmiStsRegOffset;
+ UINT32 HostSwOwnRegOffset;
+ GPIO_PAD_OWN PadOwnVal;
+
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+
+ PadNumber = 0;
+ GroupIndex = 0;
+ for (GroupIndex = 0; GroupIndex < GpioGroupInfoLength; GroupIndex++) {
+ PadNumber = Index;
+ if (PadNumber < GpioGroupInfo[GroupIndex].PadPerGroup) {
+ //
+ // Found group and pad number
+ //
+ break;
+ }
+ Index = Index - GpioGroupInfo[GroupIndex].PadPerGroup;
+ }
+
+ //
+ // Check if legal pad number
+ //
+ if (PadNumber >= GpioGroupInfo[GroupIndex].PadPerGroup){
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check if selected group has GPI SMI Enable and Status registers
+ //
+ if (GpioGroupInfo[GroupIndex].SmiEnOffset == NO_REGISTER_FOR_PROPERTY) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ GpioGroup = GpioGetGroupFromGroupIndex (GroupIndex);
+ *GpioPin = GpioGetGpioPadFromGroupAndPadNumber (GpioGroup, PadNumber);
+
+ DEBUG_CODE_BEGIN ();
+ //
+ // Check if selected GPIO Pad is not owned by CSME/ISH/IE
+ //
+ GpioGetPadOwnership (*GpioPin, &PadOwnVal);
+ if (PadOwnVal != GpioPadOwnHost) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: %a not owned by host!\n", GpioName (*GpioPin)));
+ return EFI_INVALID_PARAMETER;
+ }
+ DEBUG_CODE_END ();
+
+ *GpiSmiBitOffset = (UINT8)(PadNumber % 32);
+
+ HostSwOwnRegOffset = GpioGroupInfo[GroupIndex].HostOwnOffset + (PadNumber / 32) * 0x4;
+ *GpiHostSwOwnRegAddress = PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, HostSwOwnRegOffset);
+
+ SmiStsRegOffset = GpioGroupInfo[GroupIndex].SmiStsOffset + (PadNumber / 32) * 0x4;
+ *GpiSmiStsRegAddress = PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, SmiStsRegOffset);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will check if GpioPad is owned by host.
+
+ @param[in] GpioPad GPIO pad
+
+ @retval TRUE GPIO pad is owned by host
+ @retval FALSE GPIO pad is not owned by host and should not be used with GPIO lib API
+**/
+BOOLEAN
+GpioIsPadHostOwned (
+ IN GPIO_PAD GpioPad
+ )
+{
+ GPIO_PAD_OWN PadOwnVal;
+
+ //
+ // Check if selected GPIO Pad is not owned by CSME/ISH
+ // If GPIO is not owned by Host all access to PadCfg will be dropped
+ //
+ GpioGetPadOwnership (GpioPad, &PadOwnVal);
+ if (PadOwnVal != GpioPadOwnHost) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: %a is not owned by host!\n", GpioName (GpioPad)));
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/**
+ This procedure will check if GpioPad argument is valid.
+ Function will check below conditions:
+ - GpioPad represents a pad for current PCH
+ - GpioPad belongs to valid GpioGroup
+ - GPIO PadNumber is not greater than number of pads for this group
+
+ @param[in] GpioPad GPIO pad
+
+ @retval TRUE GPIO pad is valid and can be used with GPIO lib API
+ @retval FALSE GPIO pad is invalid and cannot be used with GPIO lib API
+**/
+BOOLEAN
+GpioIsPadValid (
+ IN GPIO_PAD GpioPad
+ )
+{
+ CONST GPIO_GROUP_INFO *GpioGroupInfo;
+ UINT32 GpioGroupInfoLength;
+ UINT32 PadNumber;
+ UINT32 GroupIndex;
+
+ if (!GpioIsCorrectPadForThisChipset (GpioPad)) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Incorrect GpioPad (0x%08x) used on this chipset!\n", GpioPad));
+ goto Error;
+ }
+
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+
+ //
+ // Check if legal pin number
+ //
+ GroupIndex = GpioGetGroupIndexFromGpioPad (GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+ if (PadNumber >= GpioGroupInfo[GroupIndex].PadPerGroup) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Pin number (%d) exceeds range of %a group (max: %d)\n",
+ PadNumber,
+ GpioGetGroupName (GroupIndex),
+ GpioGroupInfo[GroupIndex].PadPerGroup));
+ goto Error;
+ }
+
+ return TRUE;
+Error:
+ ASSERT (FALSE);
+ return FALSE;
+}
+
+/**
+ This procedure will read GPIO Pad Configuration register
+
+ @param[in] GpioPad GPIO pad
+ @param[in] DwReg Choose PADCFG register: 0:DW0, 1:DW1
+
+ @retval PadCfgRegValue PADCFG_DWx value
+**/
+UINT32
+GpioReadPadCfgReg (
+ IN GPIO_PAD GpioPad,
+ IN UINT8 DwReg
+ )
+{
+ UINT32 PadCfgReg;
+ CONST GPIO_GROUP_INFO *GpioGroupInfo;
+ UINT32 GpioGroupInfoLength;
+ UINT32 GroupIndex;
+ UINT32 PadNumber;
+
+ GroupIndex = GpioGetGroupIndexFromGpioPad (GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+
+ //
+ // Create Pad Configuration register offset
+ //
+ PadCfgReg = GpioGroupInfo[GroupIndex].PadCfgOffset + S_GPIO_PCR_PADCFG * PadNumber + 0x4 * DwReg;
+
+ return MmioRead32 (PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, PadCfgReg));
+}
+
+/**
+ This procedure will write or read GPIO Pad Configuration register
+
+ @param[in] GpioPad GPIO pad
+ @param[in] DwReg Choose PADCFG register: 0:DW0, 1:DW1
+ @param[in] PadCfgAndMask Mask to be AND'ed with PADCFG reg value
+ @param[in] PadCfgOrMask Mask to be OR'ed with PADCFG reg value
+
+ @retval none
+**/
+VOID
+GpioWritePadCfgReg (
+ IN GPIO_PAD GpioPad,
+ IN UINT8 DwReg,
+ IN UINT32 PadCfgAndMask,
+ IN UINT32 PadCfgOrMask
+ )
+{
+ UINT32 PadCfgReg;
+ CONST GPIO_GROUP_INFO *GpioGroupInfo;
+ UINT32 GpioGroupInfoLength;
+ UINT32 GroupIndex;
+ UINT32 PadNumber;
+ UINT32 PadCfgLock;
+ UINT32 PadCfgLockTx;
+
+ PadCfgLock = 0;
+ PadCfgLockTx = 0;
+
+ //
+ // Check if Pad Configuration (except output state) is to be changed.
+ // If AND and OR masks will indicate that configuration fields (other than output control)
+ // are to be modified it means that there is a need to perform an unlock (if set)
+ //
+ if ((~PadCfgAndMask | PadCfgOrMask) & (UINT32)~B_GPIO_PCR_TX_STATE) {
+ GpioGetPadCfgLock (GpioPad, &PadCfgLock);
+ if (PadCfgLock) {
+ GpioUnlockPadCfg (GpioPad);
+ }
+ }
+
+ //
+ // Check if Pad Output state is to be changed
+ // If AND and OR masks will indicate that output control
+ // is to be modified it means that there is a need to perform an unlock (if set)
+ //
+ if ((~PadCfgAndMask | PadCfgOrMask) & B_GPIO_PCR_TX_STATE) {
+ GpioGetPadCfgLockTx (GpioPad, &PadCfgLockTx);
+ if (PadCfgLockTx) {
+ GpioUnlockPadCfgTx (GpioPad);
+ }
+ }
+
+ GroupIndex = GpioGetGroupIndexFromGpioPad (GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+
+ //
+ // Create Pad Configuration register offset
+ //
+ PadCfgReg = GpioGroupInfo[GroupIndex].PadCfgOffset + S_GPIO_PCR_PADCFG * PadNumber + 0x4 * DwReg;
+
+ MmioAndThenOr32 (
+ PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, PadCfgReg),
+ PadCfgAndMask,
+ PadCfgOrMask
+ );
+
+ if (PadCfgLock) {
+ GpioLockPadCfg (GpioPad);
+ }
+ if (PadCfgLockTx) {
+ GpioLockPadCfgTx (GpioPad);
+ }
+}
+
+/**
+ This procedure will set GPIO mode
+
+ @param[in] GpioPad GPIO pad
+ @param[in] PadModeValue GPIO pad mode value
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GpioSetPadMode (
+ IN GPIO_PAD GpioPad,
+ IN GPIO_PAD_MODE PadModeValue
+ )
+{
+ UINT32 PadCfgOrMask;
+
+ PadCfgOrMask = 0;
+
+ if (!GpioIsPadValid (GpioPad)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!GpioIsPadHostOwned (GpioPad)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if (PadModeValue != (GPIO_PAD_MODE)GpioHardwareDefault) {
+
+ PadCfgOrMask = (((PadModeValue & B_GPIO_PAD_MODE_MASK) >> (N_GPIO_PAD_MODE_BIT_POS + 1)) << N_GPIO_PCR_PAD_MODE);
+
+ GpioWritePadCfgReg (
+ GpioPad,
+ 0,
+ (UINT32)~B_GPIO_PCR_PAD_MODE,
+ PadCfgOrMask
+ );
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will get GPIO mode
+
+ @param[in] GpioPad GPIO pad
+ @param[out] PadModeValue GPIO pad mode value
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid GpioPad
+**/
+EFI_STATUS
+GpioGetPadMode (
+ IN GPIO_PAD GpioPad,
+ OUT GPIO_PAD_MODE *PadModeValue
+ )
+{
+ UINT32 PadCfgRegValue;
+
+ if (!GpioIsPadValid (GpioPad)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!GpioIsPadHostOwned (GpioPad)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ PadCfgRegValue = GpioReadPadCfgReg (GpioPad, 0);
+
+ *PadModeValue = (GPIO_PAD_MODE)(((PadCfgRegValue & B_GPIO_PCR_PAD_MODE) >> (N_GPIO_PCR_PAD_MODE - (N_GPIO_PAD_MODE_BIT_POS + 1))) | (0x1 << N_GPIO_PAD_MODE_BIT_POS));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Generates GPIO name from GpioPad
+ This function returns pointer to the static buffer
+
+ @param[in] GpioPad GpioPad
+
+ @retval CHAR8* Pointer to the gpio name string
+**/
+CHAR8*
+GpioName (
+ IN GPIO_PAD GpioPad
+ )
+{
+ return GpioGetPadName (GpioPad, GpioGetStaticNameBuffer (), GPIO_NAME_LENGTH_MAX);
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/PeiDxeSmmGpioPrivateLib/GpioPrivateLibVer2.c b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/PeiDxeSmmGpioPrivateLib/GpioPrivateLibVer2.c
new file mode 100644
index 0000000000..9fea5daa28
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/PeiDxeSmmGpioPrivateLib/GpioPrivateLibVer2.c
@@ -0,0 +1,131 @@
+/** @file
+ This file contains VER2 specific GPIO information
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include <Uefi/UefiBaseType.h>
+#include <Library/DebugLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/GpioLib.h>
+#include <Library/GpioNativeLib.h>
+#include <Library/GpioPrivateLib.h>
+#include <Library/GpioHelpersLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/CpuRegbarAccessLib.h>
+#include <Register/GpioRegsVer2.h>
+#include <Register/PmcRegsVer2.h>
+#include <Register/PchPcrRegs.h>
+#include <Pins/GpioPinsVer2Lp.h>
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_GROUP_INFO mPchLpGpioGroupInfo[] = {
+ {PID_GPIOCOM0, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_B_PAD_OWN, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_B_HOSTSW_OWN, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_B_GPI_IS, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_B_GPI_IE, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_B_GPI_GPE_STS, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_B_GPI_GPE_EN, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_B_SMI_STS, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_B_SMI_EN, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_B_NMI_STS, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_B_NMI_EN, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_B_PADCFGLOCK, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_B_PADCFGLOCKTX, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_B_PADCFG_OFFSET, GPIO_VER2_PCH_LP_GPIO_GPP_B_PAD_MAX}, //TGL PCH-LP GPP_B
+ {PID_GPIOCOM0, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, 0},
+ {PID_GPIOCOM0, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_A_PAD_OWN, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_A_HOSTSW_OWN, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_A_GPI_IS, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_A_GPI_IE, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_A_GPI_GPE_STS, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_A_GPI_GPE_EN, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_A_PADCFGLOCK, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_A_PADCFGLOCKTX, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_A_PADCFG_OFFSET, GPIO_VER2_PCH_LP_GPIO_GPP_A_PAD_MAX}, //TGL PCH-LP GPP_A
+ {PID_GPIOCOM5, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_R_PAD_OWN, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_R_HOSTSW_OWN, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_R_GPI_IS, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_R_GPI_IE, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_R_GPI_GPE_STS, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_R_GPI_GPE_EN, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_R_PADCFGLOCK, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_R_PADCFGLOCKTX, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_R_PADCFG_OFFSET, GPIO_VER2_PCH_LP_GPIO_GPP_R_PAD_MAX}, //TGL PCH-LP GPP_R
+ {PID_GPIOCOM5, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, 0},
+ {PID_GPIOCOM2, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPD_PAD_OWN, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPD_HOSTSW_OWN, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPD_GPI_IS, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPD_GPI_IE, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPD_GPI_GPE_STS, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPD_GPI_GPE_EN, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPD_PADCFGLOCK, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPD_PADCFGLOCKTX, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPD_PADCFG_OFFSET, GPIO_VER2_PCH_LP_GPIO_GPD_PAD_MAX}, //TGL PCH-LP GPD
+ {PID_GPIOCOM1, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_S_PAD_OWN, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_S_HOSTSW_OWN, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_S_GPI_IS, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_S_GPI_IE, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_S_GPI_GPE_STS, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_S_GPI_GPE_EN, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_S_PADCFGLOCK, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_S_PADCFGLOCKTX, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_S_PADCFG_OFFSET, GPIO_VER2_PCH_LP_GPIO_GPP_S_PAD_MAX}, //TGL PCH-LP GPP_S
+ {PID_GPIOCOM1, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_H_PAD_OWN, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_H_HOSTSW_OWN, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_H_GPI_IS, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_H_GPI_IE, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_H_GPI_GPE_STS, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_H_GPI_GPE_EN, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_H_PADCFGLOCK, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_H_PADCFGLOCKTX, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_H_PADCFG_OFFSET, GPIO_VER2_PCH_LP_GPIO_GPP_H_PAD_MAX}, //TGL PCH-LP GPP_H
+ {PID_GPIOCOM1, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_D_PAD_OWN, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_D_HOSTSW_OWN, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_D_GPI_IS, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_D_GPI_IE, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_D_GPI_GPE_STS, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_D_GPI_GPE_EN, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_D_SMI_STS, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_D_SMI_EN, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_D_NMI_STS, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_D_NMI_EN, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_D_PADCFGLOCK, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_D_PADCFGLOCKTX, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_D_PADCFG_OFFSET, GPIO_VER2_PCH_LP_GPIO_GPP_D_PAD_MAX}, //TGL PCH-LP GPP_D
+ {PID_GPIOCOM1, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, 0},
+ {PID_GPIOCOM1, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, 0},
+ {PID_GPIOCOM4, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_C_PAD_OWN, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_C_HOSTSW_OWN, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_C_GPI_IS, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_C_GPI_IE, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_C_GPI_GPE_STS, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_C_GPI_GPE_EN, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_C_SMI_STS, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_C_SMI_EN, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_C_NMI_STS, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_C_NMI_EN, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_C_PADCFGLOCK, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_C_PADCFGLOCKTX, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_C_PADCFG_OFFSET, GPIO_VER2_PCH_LP_GPIO_GPP_C_PAD_MAX}, //TGL PCH-LP GPP_C
+ {PID_GPIOCOM4, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_F_PAD_OWN, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_F_HOSTSW_OWN, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_F_GPI_IS, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_F_GPI_IE, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_F_GPI_GPE_STS, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_F_GPI_GPE_EN, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_F_PADCFGLOCK, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_F_PADCFGLOCKTX, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_F_PADCFG_OFFSET, GPIO_VER2_PCH_LP_GPIO_GPP_F_PAD_MAX}, //TGL PCH-LP GPP_F
+ {PID_GPIOCOM4, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, 0},
+ {PID_GPIOCOM4, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_E_PAD_OWN, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_E_HOSTSW_OWN, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_E_GPI_IS, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_E_GPI_IE, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_E_GPI_GPE_STS, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_E_GPI_GPE_EN, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_E_SMI_STS, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_E_SMI_EN, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_E_NMI_STS, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_E_NMI_EN, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_E_PADCFGLOCK, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_E_PADCFGLOCKTX, R_GPIO_VER2_PCH_LP_GPIO_PCR_GPP_E_PADCFG_OFFSET, GPIO_VER2_PCH_LP_GPIO_GPP_E_PAD_MAX}, //TGL PCH-LP GPP_E
+ {PID_GPIOCOM4, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, 0},
+ {PID_GPIOCOM3, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, 0},
+ {PID_GPIOCOM3, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, NO_REGISTER_FOR_PROPERTY, 0}
+};
+
+/**
+ This procedure will retrieve address and length of GPIO info table
+
+ @param[out] GpioGroupInfoTableLength Length of GPIO group table
+
+ @retval Pointer to GPIO group table
+
+**/
+CONST GPIO_GROUP_INFO*
+GpioGetGroupInfoTable (
+ OUT UINT32 *GpioGroupInfoTableLength
+ )
+{
+ *GpioGroupInfoTableLength = ARRAY_SIZE (mPchLpGpioGroupInfo);
+ return mPchLpGpioGroupInfo;
+}
+
+/**
+ Get GPIO Chipset ID specific to PCH generation and series
+**/
+UINT32
+GpioGetThisChipsetId (
+ VOID
+ )
+{
+ return GPIO_VER2_LP_CHIPSET_ID;
+}
+
+/**
+ This internal procedure will check if group is within DeepSleepWell.
+
+ @param[in] Group GPIO Group
+
+ @retval GroupWell TRUE: This is DSW Group
+ FALSE: This is not DSW Group
+**/
+BOOLEAN
+GpioIsDswGroup (
+ IN GPIO_GROUP Group
+ )
+{
+ if (Group == GPIO_VER2_LP_GROUP_GPD) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+GLOBAL_REMOVE_IF_UNREFERENCED GPIO_GROUP_TO_GPE_MAPPING mPchLpGpioGroupToGpeMapping[] = {
+ {GPIO_VER2_LP_GROUP_GPP_B, 0, V_TGL_PCH_LP_PMC_PWRM_GPIO_CFG_GPP_B},
+ {GPIO_VER2_LP_GROUP_GPP_A, 0, V_TGL_PCH_LP_PMC_PWRM_GPIO_CFG_GPP_A},
+ {GPIO_VER2_LP_GROUP_GPP_R, 0, V_TGL_PCH_LP_PMC_PWRM_GPIO_CFG_GPP_R},
+ {GPIO_VER2_LP_GROUP_GPD, 0, V_TGL_PCH_LP_PMC_PWRM_GPIO_CFG_GPD },
+ {GPIO_VER2_LP_GROUP_GPP_S, 0, V_TGL_PCH_LP_PMC_PWRM_GPIO_CFG_GPP_S},
+ {GPIO_VER2_LP_GROUP_GPP_H, 0, V_TGL_PCH_LP_PMC_PWRM_GPIO_CFG_GPP_H},
+ {GPIO_VER2_LP_GROUP_GPP_D, 0, V_TGL_PCH_LP_PMC_PWRM_GPIO_CFG_GPP_D},
+ {GPIO_VER2_LP_GROUP_GPP_C, 0, V_TGL_PCH_LP_PMC_PWRM_GPIO_CFG_GPP_C},
+ {GPIO_VER2_LP_GROUP_GPP_F, 0, V_TGL_PCH_LP_PMC_PWRM_GPIO_CFG_GPP_F},
+ {GPIO_VER2_LP_GROUP_GPP_E, 0, V_TGL_PCH_LP_PMC_PWRM_GPIO_CFG_GPP_E}
+};
+
+/**
+ Get information for GPIO Group required to program GPIO and PMC for desired 1-Tier GPE mapping
+
+ @param[out] GpioGroupToGpeMapping Table with GPIO Group to GPE mapping
+ @param[out] GpioGroupToGpeMappingLength GPIO Group to GPE mapping table length
+**/
+VOID
+GpioGetGroupToGpeMapping (
+ OUT GPIO_GROUP_TO_GPE_MAPPING **GpioGroupToGpeMapping,
+ OUT UINT32 *GpioGroupToGpeMappingLength
+ )
+{
+ *GpioGroupToGpeMapping = mPchLpGpioGroupToGpeMapping;
+ *GpioGroupToGpeMappingLength = ARRAY_SIZE (mPchLpGpioGroupToGpeMapping);
+}
+
+/**
+ Check if 0x13 opcode supported for writing to GPIO lock unlock register
+
+ @retval TRUE It's supported
+ @retval FALSE It's not supported
+**/
+BOOLEAN
+IsGpioLockOpcodeSupported (
+ VOID
+ )
+{
+ return TRUE;
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/PeiDxeSmmGpioPrivateLib/PeiDxeSmmGpioPrivateLibVer2.inf b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/PeiDxeSmmGpioPrivateLib/PeiDxeSmmGpioPrivateLibVer2.inf
new file mode 100644
index 0000000000..a355f407f8
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/PeiDxeSmmGpioPrivateLib/PeiDxeSmmGpioPrivateLibVer2.inf
@@ -0,0 +1,46 @@
+## @file
+# Component description file for the PeiDxeSmmGpioPrivateLib
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiDxeSmmGpioPrivateLibVer2
+FILE_GUID = 680A81B0-A087-4687-B5B4-146DA30042D6
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = GpioPrivateLib
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+
+[LibraryClasses]
+ BaseLib
+ IoLib
+ DebugLib
+ PmcLib
+ PchInfoLib
+ GpioLib
+ GpioNameBufferLib
+ SataLib
+ GpioHelpersLib
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ TigerlakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+ GpioPrivateLib.c
+ GpioPrivateLibVer2.c
+ GpioNamesVer2.c
+
+[Pcd]
+gSiPkgTokenSpaceGuid.PcdEmbeddedEnable ## CONSUMES
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/PeiGpioHelpersLib/PeiGpioHelpersLib.c b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/PeiGpioHelpersLib/PeiGpioHelpersLib.c
new file mode 100644
index 0000000000..84bf655ab9
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/PeiGpioHelpersLib/PeiGpioHelpersLib.c
@@ -0,0 +1,413 @@
+/** @file
+ This file contains routines for PEI GPIO Helpers Lib
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include <Library/HobLib.h>
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/GpioNativeLib.h>
+#include <Library/GpioPrivateLib.h>
+#include <Library/GpioHelpersLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/ConfigBlockLib.h>
+#include <ConfigBlock/PchGeneralConfig.h>
+#include <Ppi/SiPolicy.h>
+
+extern EFI_GUID gGpioLibUnlockHobGuid;
+
+//
+// GPIO Lock HOB
+// Stores information on GPIO pads that should be left unlocked
+//
+typedef struct {
+ //
+ // GPIO PadConfig unlock data
+ //
+ UINT32 PadConfig;
+ //
+ // GPIO Output unlock data
+ //
+ UINT32 OutputState;
+} GPIO_UNLOCK_HOB_DATA;
+
+/**
+ This procedure will get index of GPIO Unlock HOB structure for selected GroupIndex and DwNum.
+
+ @param[in] GroupIndex GPIO group index
+ @param[in] DwNum DWORD index for a group.
+ For group which has less then 32 pads per group DwNum must be 0.
+
+ @retval GpioUnlockHobIndex
+**/
+STATIC
+UINT32
+GpioUnlockDataIndex (
+ IN UINT32 GroupIndex,
+ IN UINT32 DwNum
+ )
+{
+ UINT32 GpioUnlockDataIndex;
+ UINT32 Index;
+
+ GpioUnlockDataIndex = 0;
+
+ for (Index = 0; Index < GroupIndex; Index++) {
+ GpioUnlockDataIndex += GPIO_GET_DW_NUM (GpioGetPadPerGroup (GpioGetGroupFromGroupIndex (Index))) + 1;
+ }
+
+ GpioUnlockDataIndex += DwNum;
+ return GpioUnlockDataIndex;
+}
+
+/**
+ This procedure will create GPIO HOB for storing unlock data
+
+ @retval Pointer to GPIO Unlock data structure
+**/
+STATIC
+GPIO_UNLOCK_HOB_DATA*
+GpioCreateUnlockData (
+ VOID
+ )
+{
+ VOID *HobData;
+ GPIO_GROUP Group;
+ GPIO_GROUP GroupMin;
+ GPIO_GROUP GroupMax;
+ UINT32 GpioUnlockDataRecords;
+
+ GroupMin = GpioGetLowestGroup ();
+ GroupMax = GpioGetHighestGroup ();
+ GpioUnlockDataRecords = 0;
+
+ for (Group = GroupMin; Group <= GroupMax; Group++) {
+ GpioUnlockDataRecords += GPIO_GET_DW_NUM (GpioGetPadPerGroup (Group)) + 1;
+ }
+
+ HobData = BuildGuidHob (&gGpioLibUnlockHobGuid, GpioUnlockDataRecords * sizeof (GPIO_UNLOCK_HOB_DATA));
+ if (HobData == NULL) {
+ return NULL;
+ }
+
+ ZeroMem (HobData, GpioUnlockDataRecords * sizeof (GPIO_UNLOCK_HOB_DATA));
+
+ return (GPIO_UNLOCK_HOB_DATA*)HobData;
+}
+
+/**
+ This procedure will Get GPIO Unlock data structure for storing unlock data.
+ If HOB doesn't exist it will be created.
+
+ @param[out] GpioUnlockData pointer to GPIO Unlock data structure
+
+ @retval Length number of GPIO unlock data records
+**/
+STATIC
+UINT32
+GpioGetUnlockData (
+ GPIO_UNLOCK_HOB_DATA **GpioUnlockData
+ )
+{
+ VOID *Hob;
+
+ Hob = GetFirstGuidHob (&gGpioLibUnlockHobGuid);
+ if (Hob == NULL) {
+ //
+ // It is the first time this function is used so create the HOB
+ //
+ *GpioUnlockData = GpioCreateUnlockData ();
+ if (*GpioUnlockData == NULL) {
+ return 0;
+ }
+ Hob = GetFirstGuidHob (&gGpioLibUnlockHobGuid);
+ } else {
+ *GpioUnlockData = (GPIO_UNLOCK_HOB_DATA*) GET_GUID_HOB_DATA (Hob);
+ }
+ return GET_GUID_HOB_DATA_SIZE (Hob) / sizeof (GPIO_UNLOCK_HOB_DATA);
+}
+
+/**
+ This procedure will get pointer to GPIO Unlock data structure.
+
+ @param[out] GpioUnlockData pointer to GPIO Unlock data structure
+
+ @retval Length number of GPIO unlock data records
+**/
+STATIC
+UINT32
+GpioLocateUnlockData (
+ GPIO_UNLOCK_HOB_DATA **GpioUnlockData
+ )
+{
+ VOID *Hob;
+
+ Hob = GetFirstGuidHob (&gGpioLibUnlockHobGuid);
+ if (Hob == NULL) {
+ *GpioUnlockData = NULL;
+ return 0;
+ }
+
+ *GpioUnlockData = (GPIO_UNLOCK_HOB_DATA*) GET_GUID_HOB_DATA (Hob);
+ return GET_GUID_HOB_DATA_SIZE (Hob) / sizeof (GPIO_UNLOCK_HOB_DATA);
+}
+
+/**
+ This procedure stores GPIO pad unlock information
+
+ @param[in] GpioPad GPIO pad
+ @param[in] GpioLockConfig GPIO Lock Configuration
+
+ @retval Status
+**/
+EFI_STATUS
+GpioStoreUnlockData (
+ IN GPIO_PAD GpioPad,
+ IN GPIO_LOCK_CONFIG GpioLockConfig
+ )
+{
+ GPIO_UNLOCK_HOB_DATA *GpioUnlockData;
+ UINT32 Length;
+ UINT32 GroupIndex;
+ UINT32 PadNumber;
+ UINT32 Index;
+
+ if (GpioLockConfig == GpioLockDefault) {
+ return EFI_SUCCESS;
+ }
+
+ Length = GpioGetUnlockData (&GpioUnlockData);
+ if (Length == 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ GroupIndex = GpioGetGroupIndexFromGpioPad (GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+ Index = GpioUnlockDataIndex (GroupIndex, GPIO_GET_DW_NUM (PadNumber));
+
+ if (Index >= Length) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((GpioLockConfig & B_GPIO_LOCK_CONFIG_PAD_CONF_LOCK_MASK) == GpioPadConfigUnlock) {
+ GpioUnlockData[Index].PadConfig |= 1 << (GpioGetPadNumberFromGpioPad (GpioPad) % 32);
+ }
+
+ if ((GpioLockConfig & B_GPIO_LOCK_CONFIG_OUTPUT_LOCK_MASK) == GpioOutputStateUnlock) {
+ GpioUnlockData[Index].OutputState |= 1 << (GpioGetPadNumberFromGpioPad (GpioPad) % 32);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure stores GPIO group data about pads which PadConfig needs to be unlocked.
+
+ @param[in] GroupIndex GPIO group index
+ @param[in] DwNum DWORD index for a group.
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[in] UnlockedPads DWORD bitmask for pads which are going to be left unlocked
+ Bit position - PadNumber
+ Bit value - 0: Skip, 1: Leave unlocked
+
+ @retval Status
+**/
+EFI_STATUS
+GpioStoreGroupDwUnlockPadConfigData (
+ IN UINT32 GroupIndex,
+ IN UINT32 DwNum,
+ IN UINT32 UnlockedPads
+ )
+{
+ GPIO_UNLOCK_HOB_DATA *GpioUnlockData;
+ UINT32 Length;
+ UINT32 Index;
+
+ if (UnlockedPads == 0) {
+ //
+ // No pads to be left unlocked
+ //
+ return EFI_SUCCESS;
+ }
+
+ Length = GpioGetUnlockData (&GpioUnlockData);
+ if (Length == 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ Index = GpioUnlockDataIndex (GroupIndex, DwNum);
+ if (Index >= Length) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ GpioUnlockData[Index].PadConfig |= UnlockedPads;
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure stores GPIO group data about pads which Output state needs to be unlocked.
+
+ @param[in] GroupIndex GPIO group index
+ @param[in] DwNum DWORD index for a group.
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[in] UnlockedPads DWORD bitmask for pads which are going to be left unlocked
+ Bit position - PadNumber
+ Bit value - 0: Skip, 1: Leave unlocked
+ @retval Status
+**/
+EFI_STATUS
+GpioStoreGroupDwUnlockOutputData (
+ IN UINT32 GroupIndex,
+ IN UINT32 DwNum,
+ IN UINT32 UnlockedPads
+ )
+{
+ GPIO_UNLOCK_HOB_DATA *GpioUnlockData;
+ UINT32 Length;
+ UINT32 Index;
+
+ if (UnlockedPads == 0) {
+ //
+ // No pads to be left unlocked
+ //
+ return EFI_SUCCESS;
+ }
+
+ Length = GpioGetUnlockData (&GpioUnlockData);
+ if (Length == 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ Index = GpioUnlockDataIndex (GroupIndex, DwNum);
+ if (Index >= Length) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ GpioUnlockData[Index].OutputState |= UnlockedPads;
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will get GPIO group data with pads, which PadConfig is supposed to be left unlock
+
+ @param[in] GroupIndex GPIO group index
+ @param[in] DwNum DWORD index for a group.
+ For group which has less then 32 pads per group DwNum must be 0.
+ @retval UnlockedPads DWORD bitmask for pads which are going to be left unlocked
+ Bit position - PadNumber
+ Bit value - 0: to be locked, 1: Leave unlocked
+**/
+UINT32
+GpioGetGroupDwUnlockPadConfigMask (
+ IN UINT32 GroupIndex,
+ IN UINT32 DwNum
+ )
+{
+ GPIO_UNLOCK_HOB_DATA *GpioUnlockData;
+ UINT32 Length;
+ UINT32 Index;
+
+ Length = GpioLocateUnlockData (&GpioUnlockData);
+ if (Length == 0) {
+ return 0;
+ }
+
+ Index = GpioUnlockDataIndex (GroupIndex, DwNum);
+ if (Index >= Length) {
+ return 0;
+ }
+
+ return GpioUnlockData[Index].PadConfig;
+}
+
+/**
+ This procedure will get GPIO group data with pads, which Output is supposed to be left unlock
+
+ @param[in] GroupIndex GPIO group index
+ @param[in] DwNum DWORD index for a group.
+ For group which has less then 32 pads per group DwNum must be 0.
+ @retval UnlockedPads DWORD bitmask for pads which are going to be left unlocked
+ Bit position - PadNumber
+ Bit value - 0: to be locked, 1: Leave unlocked
+**/
+UINT32
+GpioGetGroupDwUnlockOutputMask (
+ IN UINT32 GroupIndex,
+ IN UINT32 DwNum
+ )
+{
+ GPIO_UNLOCK_HOB_DATA *GpioUnlockData;
+ UINT32 Length;
+ UINT32 Index;
+
+ Length = GpioLocateUnlockData (&GpioUnlockData);
+ if (Length == 0) {
+ return 0;
+ }
+
+ Index = GpioUnlockDataIndex (GroupIndex, DwNum);
+ if (Index >= Length) {
+ return 0;
+ }
+
+ return GpioUnlockData[Index].OutputState;
+}
+
+/**
+ Obtains GpioOverride Information from PreMem config
+
+ @retval TRUE GPIO Override obtained successfully
+ FALSE Unable to obtain GPIO Override data
+**/
+BOOLEAN
+STATIC
+GetGpioOverrideFromConfigBlock (
+ IN OUT UINT8 *GpioOverride
+ )
+{
+ EFI_STATUS Status;
+ SI_PREMEM_POLICY_PPI *SiPreMemPolicyPpi;
+ PCH_GENERAL_PREMEM_CONFIG *PchGeneralPreMemConfig;
+
+ Status = PeiServicesLocatePpi (
+ &gSiPreMemPolicyPpiGuid,
+ 0,
+ NULL,
+ (VOID **) &SiPreMemPolicyPpi
+ );
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+ Status = GetConfigBlock ((VOID *) SiPreMemPolicyPpi, &gPchGeneralPreMemConfigGuid, (VOID *) &PchGeneralPreMemConfig);
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+ *GpioOverride = (UINT8) PchGeneralPreMemConfig->GpioOverride;
+
+ return TRUE;
+}
+
+/**
+ Returns Gpio Override Level1 Information
+
+ @retval TRUE/FALSE GPIO Override Level 1 Enabled/Disabled
+**/
+BOOLEAN
+GpioOverrideLevel1Enabled (
+ VOID
+ )
+{
+ UINT8 GpioOverride;
+
+ GpioOverride = 0;
+
+ if (GetGpioOverrideFromConfigBlock (&GpioOverride)) {
+ if (GpioOverride == 1) { return TRUE; }
+ }
+
+ return FALSE;
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/PeiGpioHelpersLib/PeiGpioHelpersLib.inf b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/PeiGpioHelpersLib/PeiGpioHelpersLib.inf
new file mode 100644
index 0000000000..d70c2a1352
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/PeiGpioHelpersLib/PeiGpioHelpersLib.inf
@@ -0,0 +1,48 @@
+## @file
+# Component description file for the PeiGpioHelpersLib
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiGpioHelpersLib
+FILE_GUID = 1838E1E7-3CC4-4A74-90D9-B421EF2A579F
+VERSION_STRING = 1.0
+MODULE_TYPE = PEIM
+LIBRARY_CLASS = GpioHelpersLib
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+
+[LibraryClasses]
+BaseLib
+IoLib
+DebugLib
+HobLib
+GpioLib
+PeiServicesLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+TigerlakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+PeiGpioHelpersLib.c
+
+
+[Guids]
+gGpioLibUnlockHobGuid
+gPchGeneralPreMemConfigGuid ## CONSUMES
+
+[Ppis]
+gSiPreMemPolicyPpiGuid
+
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/PeiGpioNameBufferLib/GpioNameBufferPei.c b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/PeiGpioNameBufferLib/GpioNameBufferPei.c
new file mode 100644
index 0000000000..920d9a2cbc
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/PeiGpioNameBufferLib/GpioNameBufferPei.c
@@ -0,0 +1,67 @@
+/** @file
+ This file contains GpioMemLib implementation for PEI phase
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/HobLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/GpioNameBufferLib.h>
+
+STATIC CONST EFI_GUID mGpioNamesPrivateHobGuid = {0x9AE3138D, 0x4EBF, 0x4E90, {0x87, 0x96, 0x11, 0xD3, 0x10, 0x04, 0x60, 0x0A}};
+
+STATIC volatile BOOLEAN mGlobalMemoryWorking = FALSE;
+
+STATIC CHAR8 mGpioNameBuffer[GPIO_NAME_LENGTH_MAX];
+
+/**
+ Returns pointer to the buffer taken from GpioLib private HOB
+
+ @retval CHAR8* Pointer to the buffer
+**/
+STATIC
+CHAR8*
+GetBufferFromHob (
+ VOID
+ )
+{
+ VOID *Hob;
+ CHAR8 *GpioNameBuffer;
+
+ Hob = NULL;
+ GpioNameBuffer = NULL;
+
+ Hob = GetFirstGuidHob (&mGpioNamesPrivateHobGuid);
+ if (Hob != NULL){
+ GpioNameBuffer = (CHAR8*) GET_GUID_HOB_DATA (Hob);
+ } else {
+ GpioNameBuffer = (CHAR8*) BuildGuidHob (&mGpioNamesPrivateHobGuid, GPIO_NAME_LENGTH_MAX);
+ if (GpioNameBuffer == NULL){
+ DEBUG ((DEBUG_ERROR, "Failed to setup HOB for GPIO names lib\n"));
+ ASSERT (FALSE);
+ }
+ }
+ return GpioNameBuffer;
+}
+
+/**
+ Returns pointer to the global buffer to be used by GpioNamesLib
+
+ @retval CHAR8* Pointer to the buffer
+**/
+CHAR8*
+GpioGetStaticNameBuffer (
+ VOID
+ )
+{
+ mGlobalMemoryWorking = TRUE;
+
+ if (mGlobalMemoryWorking) {
+ return mGpioNameBuffer;
+ } else {
+ return GetBufferFromHob ();
+ }
+}
+
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/PeiGpioNameBufferLib/PeiGpioNameBufferLib.inf b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/PeiGpioNameBufferLib/PeiGpioNameBufferLib.inf
new file mode 100644
index 0000000000..0525a42a8d
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/PeiGpioNameBufferLib/PeiGpioNameBufferLib.inf
@@ -0,0 +1,35 @@
+## @file
+# Component description file for the PeiGpioMemLib
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiGpioNameBufferLib
+FILE_GUID = 16EC5CA8-8195-4847-B6CB-662CDAB863F2
+VERSION_STRING = 1.0
+MODULE_TYPE = PEIM
+LIBRARY_CLASS = GpioNameBufferLib
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32
+#
+
+[LibraryClasses]
+HobLib
+BaseLib
+IoLib
+DebugLib
+
+[Packages]
+MdePkg/MdePkg.dec
+TigerlakeSiliconPkg/SiPkg.dec
+
+[Sources]
+GpioNameBufferPei.c
+
--
2.24.0.windows.2
^ permalink raw reply related [flat|nested] 42+ messages in thread
* [Patch V3 18/40] TigerlakeSiliconPkg/IpBlock: Add Graphics component
2021-02-05 7:40 [Patch V3 01/40] TigerlakeSiliconPkg: Add package and Include/ConfigBlock headers Heng Luo
` (15 preceding siblings ...)
2021-02-05 7:40 ` [Patch V3 17/40] TigerlakeSiliconPkg/IpBlock: Add Gpio component Heng Luo
@ 2021-02-05 7:40 ` Heng Luo
2021-02-05 7:40 ` [Patch V3 19/40] TigerlakeSiliconPkg/IpBlock: Add Hda component Heng Luo
` (21 subsequent siblings)
38 siblings, 0 replies; 42+ messages in thread
From: Heng Luo @ 2021-02-05 7:40 UTC (permalink / raw)
To: devel; +Cc: Sai Chaganty, Nate DeSimone
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3171
Adds the following files:
* IpBlock/Graphics/AcpiTables
* IpBlock/Graphics/IncludePrivate
* IpBlock/Graphics/LibraryPrivate
Cc: Sai Chaganty <rangasai.v.chaganty@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Signed-off-by: Heng Luo <heng.luo@intel.com>
---
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Graphics/AcpiTables/Igfx.asl | 1955 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Graphics/AcpiTables/IgfxCommon.asl | 480 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Graphics/AcpiTables/IgfxDsm.asl | 398 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Graphics/AcpiTables/IgfxOpGbda.asl | 127 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Graphics/AcpiTables/IgfxOpRn.asl | 314 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Graphics/AcpiTables/IgfxOpSbcb.asl | 261 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Graphics/AcpiTables/IgfxSsdt.asl | 73 +++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Graphics/AcpiTables/IgfxSsdt.inf | 23 +++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Graphics/IncludePrivate/Library/DxeGraphicsInitLib.h | 53 ++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Graphics/IncludePrivate/Library/DxeGraphicsPolicyLib.h | 71 ++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Graphics/IncludePrivate/Library/DxeIgdOpRegionInitLib.h | 177 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Graphics/LibraryPrivate/DxeGraphicsInitLib/DxeGraphicsInitLib.c | 135 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Graphics/LibraryPrivate/DxeGraphicsInitLib/DxeGraphicsInitLib.inf | 45 +++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Graphics/LibraryPrivate/DxeGraphicsPolicyLib/DxeGraphicsPolicyLib.c | 118 +++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Graphics/LibraryPrivate/DxeGraphicsPolicyLib/DxeGraphicsPolicyLib.inf | 37 +++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Graphics/LibraryPrivate/DxeIgdOpRegionInitLib/DxeIgdOpRegionInit.c | 541 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Graphics/LibraryPrivate/DxeIgdOpRegionInitLib/DxeIgdOpRegionInitLib.inf | 49 ++++++++++++++++++++++
17 files changed, 4857 insertions(+)
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Graphics/AcpiTables/Igfx.asl b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Graphics/AcpiTables/Igfx.asl
new file mode 100644
index 0000000000..d00a1d8f58
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Graphics/AcpiTables/Igfx.asl
@@ -0,0 +1,1955 @@
+/** @file
+ This file contains the IGD OpRegion/Software ACPI Reference
+ Code.
+ It defines the methods to enable/disable output switching,
+ store display switching and LCD brightness BIOS control
+ and return valid addresses for all display device encoders
+ present in the system, etc.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+External(\PLD1, MethodObj)
+External(\PLD2, MethodObj)
+External(\ECST, MethodObj)
+External(\PBCL, MethodObj)
+External(HDOS, MethodObj)
+External(\ECON, IntObj)
+External(\PNHM, IntObj)
+External(OSYS, IntObj)
+External(CPSC)
+External(\GUAM, MethodObj)
+External(DSEN)
+External(S0ID)
+
+//
+// Default Physical Location of Device
+//
+Name (DPLD, Package (0x1) {
+ ToPLD (
+ PLD_Revision = 0x2,
+ PLD_IgnoreColor = 0x1,
+ PLD_Red = 0x0,
+ PLD_Green = 0x0,
+ PLD_Blue = 0x0,
+ PLD_Width = 0x320, //800 mm
+ PLD_Height = 0x7D0, //2000 mm
+ PLD_UserVisible = 0x1, //Set if the device connection point can be seen by the user without disassembly.
+ PLD_Dock = 0x0, // Set if the device connection point resides in a docking station or port replicator.
+ PLD_Lid = 0x0, // Set if this device connection point resides on the lid of laptop system.
+ PLD_Panel = "TOP", // Describes which panel surface of the systems housing the device connection point resides on.
+ PLD_VerticalPosition = "CENTER", // Vertical Position on the panel where the device connection point resides.
+ PLD_HorizontalPosition = "RIGHT", // Horizontal Position on the panel where the device connection point resides.
+ PLD_Shape = "VERTICALRECTANGLE",
+ PLD_GroupOrientation = 0x0, // if Set, indicates vertical grouping, otherwise horizontal is assumed.
+ PLD_GroupToken = 0x0, // Unique numerical value identifying a group.
+ PLD_GroupPosition = 0x0, // Identifies this device connection points position in the group (i.e. 1st, 2nd)
+ PLD_Bay = 0x0, // Set if describing a device in a bay or if device connection point is a bay.
+ PLD_Ejectable = 0x0, // Set if the device is ejectable. Indicates ejectability in the absence of _EJx objects
+ PLD_EjectRequired = 0x0, // OSPM Ejection required: Set if OSPM needs to be involved with ejection process. User-operated physical hardware ejection is not possible.
+ PLD_CabinetNumber = 0x0, // For single cabinet system, this field is always 0.
+ PLD_CardCageNumber = 0x0, // For single card cage system, this field is always 0.
+ PLD_Reference = 0x0, // if Set, this _PLD defines a reference shape that is used to help orient the user with respect to the other shapes when rendering _PLDs.
+ PLD_Rotation = 0x0, // 0 - 0deg, 1 - 45deg, 2 - 90deg, 3 - 135deg, 4 - 180deg, 5 - 225deg, 6 - 270deg, 7 - 315deg
+ PLD_Order = 0x3, // Identifies the drawing order of the connection point described by a _PLD
+ PLD_VerticalOffset = 0x0,
+ PLD_HorizontalOffset = 0x0
+ )
+ } // Package
+) //DPLD
+
+// Enable/Disable Output Switching. In WIN2K/WINXP, _DOS = 0 will
+// get called during initialization to prepare for an ACPI Display
+// Switch Event. During an ACPI Display Switch, the OS will call
+// _DOS = 2 immediately after a Notify=0x80 to temporarily disable
+// all Display Switching. After ACPI Display Switching is complete,
+// the OS will call _DOS = 0 to re-enable ACPI Display Switching.
+Method(_DOS,1)
+{
+ //
+ // Store Display Switching and LCD brightness BIOS control bit
+ //
+ Store(And(Arg0,7),DSEN)
+
+ If(LEqual(And(Arg0, 0x3), 0)) // If _DOS[1:0]=0
+ {
+ If(CondRefOf(HDOS))
+ {
+ HDOS()
+ }
+ }
+}
+
+//
+// Enumerate the Display Environment. This method will return
+// valid addresses for all display device encoders present in the
+// system. The Miniport Driver will reject the addresses for every
+// encoder that does not have an attached display device. After
+// enumeration is complete, the OS will call the _DGS methods
+// during a display switch only for the addresses accepted by the
+// Miniport Driver. For hot-insertion and removal of display
+// devices, a re-enumeration notification will be required so the
+// address of the newly present display device will be accepted by
+// the Miniport Driver.
+//
+Method(_DOD,0)
+{
+ //
+ // Two LFP devices are supporte by default
+ //
+ Store(2, NDID)
+ If(LNotEqual(DIDL, Zero))
+ {
+ Store(SDDL(DIDL),DID1)
+ }
+ If(LNotEqual(DDL2, Zero))
+ {
+ Store(SDDL(DDL2),DID2)
+ }
+ If(LNotEqual(DDL3, Zero))
+ {
+ Store(SDDL(DDL3),DID3)
+ }
+ If(LNotEqual(DDL4, Zero))
+ {
+ Store(SDDL(DDL4),DID4)
+ }
+ If(LNotEqual(DDL5, Zero))
+ {
+ Store(SDDL(DDL5),DID5)
+ }
+ If(LNotEqual(DDL6, Zero))
+ {
+ Store(SDDL(DDL6),DID6)
+ }
+ If(LNotEqual(DDL7, Zero))
+ {
+ Store(SDDL(DDL7),DID7)
+ }
+ If(LNotEqual(DDL8, Zero))
+ {
+ Store(SDDL(DDL8),DID8)
+ }
+ If(LNotEqual(DDL9, Zero))
+ {
+ Store(SDDL(DDL9),DID9)
+ }
+ If(LNotEqual(DD10, Zero))
+ {
+ Store(SDDL(DD10),DIDA)
+ }
+ If(LNotEqual(DD11, Zero))
+ {
+ Store(SDDL(DD11),DIDB)
+ }
+ If(LNotEqual(DD12, Zero))
+ {
+ Store(SDDL(DD12),DIDC)
+ }
+ If(LNotEqual(DD13, Zero))
+ {
+ Store(SDDL(DD13),DIDD)
+ }
+ If(LNotEqual(DD14, Zero))
+ {
+ Store(SDDL(DD14),DIDE)
+ }
+ If(LNotEqual(DD15, Zero))
+ {
+ Store(SDDL(DD15),DIDF)
+ }
+
+ //
+ // Enumerate the encoders. Note that for
+ // current silicon, the maximum number of encoders
+ // possible is 15.
+ //
+ If(LEqual(NDID,1))
+ {
+ Name(TMP1,Package() {
+ 0xFFFFFFFF})
+ If (LEqual(IPTP,1)) {
+ //
+ // IGFX need report IPUA as GFX0 child
+ //
+ Store(0x00023480,Index(TMP1,0))
+ } Else {
+ Store(Or(0x10000,DID1),Index(TMP1,0))
+ }
+ Return(TMP1)
+ }
+
+ If(LEqual(NDID,2))
+ {
+ Name(TMP2,Package() {
+ 0xFFFFFFFF,
+ 0xFFFFFFFF})
+ Store(Or(0x10000,DID1),Index(TMP2,0))
+ If (LEqual(IPTP,1)) {
+ //
+ // IGFX need report IPUA as GFX0 child
+ //
+ Store(0x00023480,Index(TMP2,1))
+ } Else {
+ Store(Or(0x10000,DID2),Index(TMP2,1))
+ }
+ Return(TMP2)
+ }
+
+ If(LEqual(NDID,3))
+ {
+ Name(TMP3,Package() {
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF})
+ Store(Or(0x10000,DID1),Index(TMP3,0))
+ Store(Or(0x10000,DID2),Index(TMP3,1))
+ If (LEqual(IPTP,1)) {
+ //
+ // IGFX need report IPUA as GFX0 child
+ //
+ Store(0x00023480,Index(TMP3,2))
+ } Else {
+ Store(Or(0x10000,DID3),Index(TMP3,2))
+ }
+ Return(TMP3)
+ }
+
+ If(LEqual(NDID,4))
+ {
+ Name(TMP4,Package() {
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF})
+ Store(Or(0x10000,DID1),Index(TMP4,0))
+ Store(Or(0x10000,DID2),Index(TMP4,1))
+ Store(Or(0x10000,DID3),Index(TMP4,2))
+ If (LEqual(IPTP,1)) {
+ //
+ // IGFX need report IPUA as GFX0 child
+ //
+ Store(0x00023480,Index(TMP4,3))
+ } Else {
+ Store(Or(0x10000,DID4),Index(TMP4,3))
+ }
+ Return(TMP4)
+ }
+
+ If(LEqual(NDID,5))
+ {
+ Name(TMP5,Package() {
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF})
+ Store(Or(0x10000,DID1),Index(TMP5,0))
+ Store(Or(0x10000,DID2),Index(TMP5,1))
+ Store(Or(0x10000,DID3),Index(TMP5,2))
+ Store(Or(0x10000,DID4),Index(TMP5,3))
+ If (LEqual(IPTP,1)) {
+ //
+ // IGFX need report IPUA as GFX0 child
+ //
+ Store(0x00023480,Index(TMP5,4))
+ } Else {
+ Store(Or(0x10000,DID5),Index(TMP5,4))
+ }
+ Return(TMP5)
+ }
+
+ If(LEqual(NDID,6))
+ {
+ Name(TMP6,Package() {
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF})
+ Store(Or(0x10000,DID1),Index(TMP6,0))
+ Store(Or(0x10000,DID2),Index(TMP6,1))
+ Store(Or(0x10000,DID3),Index(TMP6,2))
+ Store(Or(0x10000,DID4),Index(TMP6,3))
+ Store(Or(0x10000,DID5),Index(TMP6,4))
+ If (LEqual(IPTP,1)) {
+ //
+ // IGFX need report IPUA as GFX0 child
+ //
+ Store(0x00023480,Index(TMP6,5))
+ } Else {
+ Store(Or(0x10000,DID6),Index(TMP6,5))
+ }
+ Return(TMP6)
+ }
+
+ If(LEqual(NDID,7))
+ {
+ Name(TMP7,Package() {
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF})
+ Store(Or(0x10000,DID1),Index(TMP7,0))
+ Store(Or(0x10000,DID2),Index(TMP7,1))
+ Store(Or(0x10000,DID3),Index(TMP7,2))
+ Store(Or(0x10000,DID4),Index(TMP7,3))
+ Store(Or(0x10000,DID5),Index(TMP7,4))
+ Store(Or(0x10000,DID6),Index(TMP7,5))
+ If (LEqual(IPTP,1)) {
+ //
+ // IGFX need report IPUA as GFX0 child
+ //
+ Store(0x00023480,Index(TMP7,6))
+ } Else {
+ Store(Or(0x10000,DID7),Index(TMP7,6))
+ }
+ Return(TMP7)
+ }
+
+ If(LEqual(NDID,8))
+ {
+ Name(TMP8,Package() {
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF})
+ Store(Or(0x10000,DID1),Index(TMP8,0))
+ Store(Or(0x10000,DID2),Index(TMP8,1))
+ Store(Or(0x10000,DID3),Index(TMP8,2))
+ Store(Or(0x10000,DID4),Index(TMP8,3))
+ Store(Or(0x10000,DID5),Index(TMP8,4))
+ Store(Or(0x10000,DID6),Index(TMP8,5))
+ Store(Or(0x10000,DID7),Index(TMP8,6))
+ If (LEqual(IPTP,1)) {
+ //
+ // IGFX need report IPUA as GFX0 child
+ //
+ Store(0x00023480,Index(TMP8,7))
+ } Else {
+ Store(Or(0x10000,DID8),Index(TMP8,7))
+ }
+ Return(TMP8)
+ }
+
+ If(LEqual(NDID,9))
+ {
+ Name(TMP9,Package() {
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF})
+ Store(Or(0x10000,DID1),Index(TMP9,0))
+ Store(Or(0x10000,DID2),Index(TMP9,1))
+ Store(Or(0x10000,DID3),Index(TMP9,2))
+ Store(Or(0x10000,DID4),Index(TMP9,3))
+ Store(Or(0x10000,DID5),Index(TMP9,4))
+ Store(Or(0x10000,DID6),Index(TMP9,5))
+ Store(Or(0x10000,DID7),Index(TMP9,6))
+ Store(Or(0x10000,DID8),Index(TMP9,7))
+ If (LEqual(IPTP,1)) {
+ //
+ // IGFX need report IPUA as GFX0 child
+ //
+ Store(0x00023480,Index(TMP9,8))
+ } Else {
+ Store(Or(0x10000,DID9),Index(TMP9,8))
+ }
+ Return(TMP9)
+ }
+
+ If(LEqual(NDID,0x0A))
+ {
+ Name(TMPA,Package() {
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF})
+ Store(Or(0x10000,DID1),Index(TMPA,0))
+ Store(Or(0x10000,DID2),Index(TMPA,1))
+ Store(Or(0x10000,DID3),Index(TMPA,2))
+ Store(Or(0x10000,DID4),Index(TMPA,3))
+ Store(Or(0x10000,DID5),Index(TMPA,4))
+ Store(Or(0x10000,DID6),Index(TMPA,5))
+ Store(Or(0x10000,DID7),Index(TMPA,6))
+ Store(Or(0x10000,DID8),Index(TMPA,7))
+ Store(Or(0x10000,DID9),Index(TMPA,8))
+ If (LEqual(IPTP,1)) {
+ //
+ // IGFX need report IPUA as GFX0 child
+ //
+ Store(0x00023480,Index(TMPA,9))
+ } Else {
+ Store(Or(0x10000,DIDA),Index(TMPA,9))
+ }
+ Return(TMPA)
+ }
+
+ If(LEqual(NDID,0x0B))
+ {
+ Name(TMPB,Package() {
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF})
+ Store(Or(0x10000,DID1),Index(TMPB,0))
+ Store(Or(0x10000,DID2),Index(TMPB,1))
+ Store(Or(0x10000,DID3),Index(TMPB,2))
+ Store(Or(0x10000,DID4),Index(TMPB,3))
+ Store(Or(0x10000,DID5),Index(TMPB,4))
+ Store(Or(0x10000,DID6),Index(TMPB,5))
+ Store(Or(0x10000,DID7),Index(TMPB,6))
+ Store(Or(0x10000,DID8),Index(TMPB,7))
+ Store(Or(0x10000,DID9),Index(TMPB,8))
+ Store(Or(0x10000,DIDA),Index(TMPB,9))
+ If (LEqual(IPTP,1)) {
+ //
+ // IGFX need report IPUA as GFX0 child
+ //
+ Store(0x00023480,Index(TMPB,10))
+ } Else {
+ Store(Or(0x10000,DIDB),Index(TMPB,10))
+ }
+ Return(TMPB)
+ }
+
+ If(LEqual(NDID,0x0C))
+ {
+ Name(TMPC,Package() {
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF})
+ Store(Or(0x10000,DID1),Index(TMPC,0))
+ Store(Or(0x10000,DID2),Index(TMPC,1))
+ Store(Or(0x10000,DID3),Index(TMPC,2))
+ Store(Or(0x10000,DID4),Index(TMPC,3))
+ Store(Or(0x10000,DID5),Index(TMPC,4))
+ Store(Or(0x10000,DID6),Index(TMPC,5))
+ Store(Or(0x10000,DID7),Index(TMPC,6))
+ Store(Or(0x10000,DID8),Index(TMPC,7))
+ Store(Or(0x10000,DID9),Index(TMPC,8))
+ Store(Or(0x10000,DIDA),Index(TMPC,9))
+ Store(Or(0x10000,DIDB),Index(TMPC,10))
+ If (LEqual(IPTP,1)) {
+ //
+ // IGFX need report IPUA as GFX0 child
+ //
+ Store(0x00023480,Index(TMPC,11))
+ } Else {
+ Store(Or(0x10000,DIDC),Index(TMPC,11))
+ }
+ Return(TMPC)
+ }
+
+ If(LEqual(NDID,0x0D))
+ {
+ Name(TMPD,Package() {
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF})
+ Store(Or(0x10000,DID1),Index(TMPD,0))
+ Store(Or(0x10000,DID2),Index(TMPD,1))
+ Store(Or(0x10000,DID3),Index(TMPD,2))
+ Store(Or(0x10000,DID4),Index(TMPD,3))
+ Store(Or(0x10000,DID5),Index(TMPD,4))
+ Store(Or(0x10000,DID6),Index(TMPD,5))
+ Store(Or(0x10000,DID7),Index(TMPD,6))
+ Store(Or(0x10000,DID8),Index(TMPD,7))
+ Store(Or(0x10000,DID9),Index(TMPD,8))
+ Store(Or(0x10000,DIDA),Index(TMPD,9))
+ Store(Or(0x10000,DIDB),Index(TMPD,10))
+ Store(Or(0x10000,DIDC),Index(TMPD,11))
+ If (LEqual(IPTP,1)) {
+ //
+ // IGFX need report IPUA as GFX0 child
+ //
+ Store(0x00023480,Index(TMPD,12))
+ } Else {
+ Store(Or(0x10000,DIDD),Index(TMPD,12))
+ }
+ Return(TMPD)
+ }
+
+ If(LEqual(NDID,0x0E))
+ {
+ Name(TMPE,Package() {
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF})
+ Store(Or(0x10000,DID1),Index(TMPE,0))
+ Store(Or(0x10000,DID2),Index(TMPE,1))
+ Store(Or(0x10000,DID3),Index(TMPE,2))
+ Store(Or(0x10000,DID4),Index(TMPE,3))
+ Store(Or(0x10000,DID5),Index(TMPE,4))
+ Store(Or(0x10000,DID6),Index(TMPE,5))
+ Store(Or(0x10000,DID7),Index(TMPE,6))
+ Store(Or(0x10000,DID8),Index(TMPE,7))
+ Store(Or(0x10000,DID9),Index(TMPE,8))
+ Store(Or(0x10000,DIDA),Index(TMPE,9))
+ Store(Or(0x10000,DIDB),Index(TMPE,10))
+ Store(Or(0x10000,DIDC),Index(TMPE,11))
+ Store(Or(0x10000,DIDD),Index(TMPE,12))
+ If (LEqual(IPTP,1)) {
+ //
+ // IGFX need report IPUA as GFX0 child
+ //
+ Store(0x00023480,Index(TMPE,13))
+ } Else {
+ Store(Or(0x10000,DIDE),Index(TMPE,13))
+ }
+ Return(TMPE)
+ }
+
+ If(LEqual(NDID,0x0F))
+ {
+ Name(TMPF,Package() {
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF})
+ Store(Or(0x10000,DID1),Index(TMPF,0))
+ Store(Or(0x10000,DID2),Index(TMPF,1))
+ Store(Or(0x10000,DID3),Index(TMPF,2))
+ Store(Or(0x10000,DID4),Index(TMPF,3))
+ Store(Or(0x10000,DID5),Index(TMPF,4))
+ Store(Or(0x10000,DID6),Index(TMPF,5))
+ Store(Or(0x10000,DID7),Index(TMPF,6))
+ Store(Or(0x10000,DID8),Index(TMPF,7))
+ Store(Or(0x10000,DID9),Index(TMPF,8))
+ Store(Or(0x10000,DIDA),Index(TMPF,9))
+ Store(Or(0x10000,DIDB),Index(TMPF,10))
+ Store(Or(0x10000,DIDC),Index(TMPF,11))
+ Store(Or(0x10000,DIDD),Index(TMPF,12))
+ Store(Or(0x10000,DIDE),Index(TMPF,13))
+ If (LEqual(IPTP,1)) {
+ //
+ // IGFX need report IPUA as GFX0 child
+ //
+ Store(0x00023480,Index(TMPF,14))
+ } Else {
+ Store(Or(0x10000,DIDF),Index(TMPF,14))
+ }
+ Return(TMPF)
+ }
+
+ If(LEqual(NDID,0x10))
+ {
+ Name(TMPG,Package() {
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF})
+ Store(Or(0x10000,DID1),Index(TMPG,0))
+ Store(Or(0x10000,DID2),Index(TMPG,1))
+ Store(Or(0x10000,DID3),Index(TMPG,2))
+ Store(Or(0x10000,DID4),Index(TMPG,3))
+ Store(Or(0x10000,DID5),Index(TMPG,4))
+ Store(Or(0x10000,DID6),Index(TMPG,5))
+ Store(Or(0x10000,DID7),Index(TMPG,6))
+ Store(Or(0x10000,DID8),Index(TMPG,7))
+ Store(Or(0x10000,DID9),Index(TMPG,8))
+ Store(Or(0x10000,DIDA),Index(TMPG,9))
+ Store(Or(0x10000,DIDB),Index(TMPG,10))
+ Store(Or(0x10000,DIDC),Index(TMPG,11))
+ Store(Or(0x10000,DIDD),Index(TMPG,12))
+ Store(Or(0x10000,DIDE),Index(TMPG,13))
+ Store(Or(0x10000,DIDF),Index(TMPG,14))
+ //
+ // IGFX need report IPUA as GFX0 child
+ // NDID can only be 0x10 if IPU is enabled
+ //
+ Store(0x00023480,Index(TMPG,15))
+ Return(TMPG)
+ }
+
+ //
+ // If nothing else, return Unknown LFP.
+ // (Prevents compiler warning.)
+ //
+ Return(Package() {0x00000400})
+}
+
+Device(DD01)
+{
+ //
+ // Return Unique ID.
+ //
+ Method(_ADR,0,Serialized)
+ {
+ If(LEqual(And(0x0F00,DID1),0x400))
+ {
+ Store(0x1, EDPV)
+ Store(NXD1, NXDX)
+ Store(DID1, DIDX)
+ Return(1)
+ }
+ If(LEqual(DID1,0))
+ {
+ Return(1)
+ }
+ Else
+ {
+ Return(And(0xFFFF,DID1))
+ }
+ }
+
+ //
+ // Return the Current Status.
+ //
+ Method(_DCS,0)
+ {
+ Return(CDDS(DID1))
+ }
+
+ //
+ // Query Graphics State (active or inactive).
+ //
+ Method(_DGS,0)
+ {
+ If(LAnd(LEqual(And(HGMD,0x7F),0x01),CondRefOf(SNXD)))
+ {
+ Return (NXD1)
+ }
+ Return(NDDS(DID1))
+ }
+
+ //
+ // Device Set State.
+ //
+ Method(_DSS,1)
+ {
+ DSST(Arg0)
+ }
+}
+
+Device(DD02)
+{
+ //
+ // Return Unique ID.
+ //
+ Method(_ADR,0,Serialized)
+ {
+ If(LEqual(And(0x0F00,DID2),0x400))
+ {
+ If(LEqual(And(0xF,DID2),0x1))
+ {
+ Store(0x2, EDPV)
+ Store(NXD2, NXDY)
+ Store(DID2, DIDY)
+ Return(2)
+ }
+ Store(0x2, EDPV)
+ Store(NXD2, NXDX)
+ Store(DID2, DIDX)
+ Return(2)
+ }
+ If(LEqual(DID2,0))
+ {
+ Return(2)
+ }
+ Else
+ {
+ Return(And(0xFFFF,DID2))
+ }
+ }
+
+ //
+ // Return the Current Status.
+ //
+ Method(_DCS,0)
+ {
+ If(LEqual(LIDS,0))
+ {
+ Return(0x0)
+ }
+ Return(CDDS(DID2))
+ }
+
+ //
+ // Query Graphics State (active or inactive).
+ //
+ Method(_DGS,0)
+ {
+ //
+ // Return the Next State.
+ //
+ If(LAnd(LEqual(And(HGMD,0x7F),0x01),CondRefOf(SNXD)))
+ {
+ Return (NXD2)
+ }
+ Return(NDDS(DID2))
+ }
+
+ //
+ // Device Set State.
+ //
+ Method(_DSS,1)
+ {
+ DSST(Arg0)
+ }
+}
+
+Device(DD03)
+{
+ //
+ // Return Unique ID.
+ //
+ Method(_ADR,0,Serialized)
+ {
+ If(LEqual(And(0x0F00,DID3),0x400))
+ {
+ Store(0x3, EDPV)
+ Store(NXD3, NXDX)
+ Store(DID3, DIDX)
+ Return(3)
+ }
+ If(LEqual(DID3,0))
+ {
+ Return(3)
+ }
+ Else
+ {
+ Return(And(0xFFFF,DID3))
+ }
+ }
+
+ //
+ // Return the Current Status.
+ //
+ Method(_DCS,0)
+ {
+ If(LEqual(DID3,0))
+ {
+ Return(0x0B)
+ }
+ Else
+ {
+ Return(CDDS(DID3))
+ }
+ }
+
+ //
+ // Query Graphics State (active or inactive).
+ //
+ Method(_DGS,0)
+ {
+ If(LAnd(LEqual(And(HGMD,0x7F),0x01),CondRefOf(SNXD)))
+ {
+ Return (NXD3)
+ }
+ Return(NDDS(DID3))
+ }
+
+ //
+ // Device Set State.
+ //
+ Method(_DSS,1)
+ {
+ DSST(Arg0)
+ }
+}
+
+Device(DD04)
+{
+ //
+ // Return Unique ID.
+ //
+ Method(_ADR,0,Serialized)
+ {
+ If(LEqual(And(0x0F00,DID4),0x400))
+ {
+ Store(0x4, EDPV)
+ Store(NXD4, NXDX)
+ Store(DID4, DIDX)
+ Return(4)
+ }
+ If(LEqual(DID4,0))
+ {
+ Return(4)
+ }
+ Else
+ {
+ Return(And(0xFFFF,DID4))
+ }
+ }
+
+ //
+ // Return the Current Status.
+ //
+ Method(_DCS,0)
+ {
+ If(LEqual(DID4,0))
+ {
+ Return(0x0B)
+ }
+ Else
+ {
+ Return(CDDS(DID4))
+ }
+ }
+
+ //
+ // Query Graphics State (active or inactive).
+ //
+ Method(_DGS,0)
+ {
+ If(LAnd(LEqual(And(HGMD,0x7F),0x01),CondRefOf(SNXD)))
+ {
+ Return (NXD4)
+ }
+ Return(NDDS(DID4))
+ }
+
+ //
+ // Device Set State. (See table above.)
+ //
+ Method(_DSS,1)
+ {
+ DSST(Arg0)
+ }
+}
+
+Device(DD05)
+{
+ //
+ // Return Unique ID.
+ //
+ Method(_ADR,0,Serialized)
+ {
+ If(LEqual(And(0x0F00,DID5),0x400))
+ {
+ Store(0x5, EDPV)
+ Store(NXD5, NXDX)
+ Store(DID5, DIDX)
+ Return(5)
+ }
+ If(LEqual(DID5,0))
+ {
+ Return(5)
+ }
+ Else
+ {
+ Return(And(0xFFFF,DID5))
+ }
+ }
+
+ //
+ // Return the Current Status.
+ //
+ Method(_DCS,0)
+ {
+ If(LEqual(DID5,0))
+ {
+ Return(0x0B)
+ }
+ Else
+ {
+ Return(CDDS(DID5))
+ }
+ }
+
+ //
+ // Query Graphics State (active or inactive).
+ //
+ Method(_DGS,0)
+ {
+ If(LAnd(LEqual(And(HGMD,0x7F),0x01),CondRefOf(SNXD)))
+ {
+ Return (NXD5)
+ }
+ Return(NDDS(DID5))
+ }
+
+ //
+ // Device Set State.
+ //
+ Method(_DSS,1)
+ {
+ DSST(Arg0)
+ }
+}
+
+Device(DD06)
+{
+ //
+ // Return Unique ID.
+ //
+ Method(_ADR,0,Serialized)
+ {
+ If(LEqual(And(0x0F00,DID6),0x400))
+ {
+ Store(0x6, EDPV)
+ Store(NXD6, NXDX)
+ Store(DID6, DIDX)
+ Return(6)
+ }
+ If(LEqual(DID6,0))
+ {
+ Return(6)
+ }
+ Else
+ {
+ Return(And(0xFFFF,DID6))
+ }
+ }
+
+ //
+ // Return the Current Status.
+ //
+ Method(_DCS,0)
+ {
+ If(LEqual(DID6,0))
+ {
+ Return(0x0B)
+ }
+ Else
+ {
+ Return(CDDS(DID6))
+ }
+ }
+
+ //
+ // Query Graphics State (active or inactive).
+ //
+ Method(_DGS,0)
+ {
+ If(LAnd(LEqual(And(HGMD,0x7F),0x01),CondRefOf(SNXD)))
+ {
+ Return (NXD6)
+ }
+ Return(NDDS(DID6))
+ }
+
+ //
+ // Device Set State.
+ //
+ Method(_DSS,1)
+ {
+ DSST(Arg0)
+ }
+}
+
+Device(DD07)
+{
+ //
+ // Return Unique ID.
+ //
+ Method(_ADR,0,Serialized)
+ {
+ If(LEqual(And(0x0F00,DID7),0x400))
+ {
+ Store(0x7, EDPV)
+ Store(NXD7, NXDX)
+ Store(DID7, DIDX)
+ Return(7)
+ }
+ If(LEqual(DID7,0))
+ {
+ Return(7)
+ }
+ Else
+ {
+ Return(And(0xFFFF,DID7))
+ }
+ }
+
+ //
+ // Return the Current Status.
+ //
+ Method(_DCS,0)
+ {
+ If(LEqual(DID7,0))
+ {
+ Return(0x0B)
+ }
+ Else
+ {
+ Return(CDDS(DID7))
+ }
+ }
+
+ //
+ // Query Graphics State (active or inactive).
+ //
+ Method(_DGS,0)
+ {
+ If(LAnd(LEqual(And(HGMD,0x7F),0x01),CondRefOf(SNXD)))
+ {
+ Return (NXD7)
+ }
+ Return(NDDS(DID7))
+ }
+
+ //
+ // Device Set State.
+ //
+ Method(_DSS,1)
+ {
+ DSST(Arg0)
+ }
+}
+
+Device(DD08)
+{
+ //
+ // Return Unique ID.
+ //
+ Method(_ADR,0,Serialized)
+ {
+ If(LEqual(And(0x0F00,DID8),0x400))
+ {
+ Store(0x8, EDPV)
+ Store(NXD8, NXDX)
+ Store(DID8, DIDX)
+ Return(8)
+ }
+ If(LEqual(DID8,0))
+ {
+ Return(8)
+ }
+ Else
+ {
+ Return(And(0xFFFF,DID8))
+ }
+ }
+
+ //
+ // Return the Current Status.
+ //
+ Method(_DCS,0)
+ {
+ If(LEqual(DID8,0))
+ {
+ Return(0x0B)
+ }
+ Else
+ {
+ Return(CDDS(DID8))
+ }
+ }
+
+ //
+ // Query Graphics State (active or inactive).
+ //
+ Method(_DGS,0)
+ {
+ If(LAnd(LEqual(And(HGMD,0x7F),0x01),CondRefOf(SNXD)))
+ {
+ Return (NXD8)
+ }
+ Return(NDDS(DID8))
+ }
+
+ //
+ // Device Set State.
+ //
+ Method(_DSS,1)
+ {
+ DSST(Arg0)
+ }
+}
+
+Device(DD09)
+{
+ //
+ // Return Unique ID.
+ //
+ Method(_ADR,0,Serialized)
+ {
+ If(LEqual(And(0x0F00,DID9),0x400))
+ {
+ Store(0x9, EDPV)
+ Store(NXD8, NXDX)
+ Store(DID9, DIDX)
+ Return(9)
+ }
+ If(LEqual(DID9,0))
+ {
+ Return(9)
+ }
+ Else
+ {
+ Return(And(0xFFFF,DID9))
+ }
+ }
+
+ //
+ // Return the Current Status.
+ //
+ Method(_DCS,0)
+ {
+ If(LEqual(DID9,0))
+ {
+ Return(0x0B)
+ }
+ Else
+ {
+ Return(CDDS(DID9))
+ }
+ }
+
+ //
+ // Query Graphics State (active or inactive).
+ //
+ Method(_DGS,0)
+ {
+ If(LAnd(LEqual(And(HGMD,0x7F),0x01),CondRefOf(SNXD)))
+ {
+ Return (NXD8)
+ }
+ Return(NDDS(DID9))
+ }
+
+ //
+ // Device Set State.
+ //
+ Method(_DSS,1)
+ {
+ DSST(Arg0)
+ }
+}
+
+Device(DD0A)
+{
+ //
+ // Return Unique ID.
+ //
+ Method(_ADR,0,Serialized)
+ {
+ If(LEqual(And(0x0F00,DIDA),0x400))
+ {
+ Store(0xA, EDPV)
+ Store(NXD8, NXDX)
+ Store(DIDA, DIDX)
+ Return(0x0A)
+ }
+ If(LEqual(DIDA,0))
+ {
+ Return(0x0A)
+ }
+ Else
+ {
+ Return(And(0xFFFF,DIDA))
+ }
+ }
+
+ //
+ // Return the Current Status.
+ //
+ Method(_DCS,0)
+ {
+ If(LEqual(DIDA,0))
+ {
+ Return(0x0B)
+ }
+ Else
+ {
+ Return(CDDS(DIDA))
+ }
+ }
+
+ //
+ // Query Graphics State (active or inactive).
+ //
+ Method(_DGS,0)
+ {
+ If(LAnd(LEqual(And(HGMD,0x7F),0x01),CondRefOf(SNXD)))
+ {
+ Return (NXD8)
+ }
+ Return(NDDS(DIDA))
+ }
+
+ //
+ // Device Set State.
+ //
+ Method(_DSS,1)
+ {
+ DSST(Arg0)
+ }
+}
+
+Device(DD0B)
+{
+ //
+ // Return Unique ID.
+ //
+ Method(_ADR,0,Serialized)
+ {
+ If(LEqual(And(0x0F00,DIDB),0x400))
+ {
+ Store(0xB, EDPV)
+ Store(NXD8, NXDX)
+ Store(DIDB, DIDX)
+ Return(0X0B)
+ }
+ If(LEqual(DIDB,0))
+ {
+ Return(0x0B)
+ }
+ Else
+ {
+ Return(And(0xFFFF,DIDB))
+ }
+ }
+
+ //
+ // Return the Current Status.
+ //
+ Method(_DCS,0)
+ {
+ If(LEqual(DIDB,0))
+ {
+ Return(0x0B)
+ }
+ Else
+ {
+ Return(CDDS(DIDB))
+ }
+ }
+
+ //
+ // Query Graphics State (active or inactive).
+ //
+ Method(_DGS,0)
+ {
+ If(LAnd(LEqual(And(HGMD,0x7F),0x01),CondRefOf(SNXD)))
+ {
+ Return (NXD8)
+ }
+ Return(NDDS(DIDB))
+ }
+
+ //
+ // Device Set State.
+ //
+ Method(_DSS,1)
+ {
+ DSST(Arg0)
+ }
+}
+
+Device(DD0C)
+{
+ //
+ // Return Unique ID.
+ //
+ Method(_ADR,0,Serialized)
+ {
+ If(LEqual(And(0x0F00,DIDC),0x400))
+ {
+ Store(0xC, EDPV)
+ Store(NXD8, NXDX)
+ Store(DIDC, DIDX)
+ Return(0X0C)
+ }
+ If(LEqual(DIDC,0))
+ {
+ Return(0x0C)
+ }
+ Else
+ {
+ Return(And(0xFFFF,DIDC))
+ }
+ }
+
+ //
+ // Return the Current Status.
+ //
+ Method(_DCS,0)
+ {
+ If(LEqual(DIDC,0))
+ {
+ Return(0x0C)
+ }
+ Else
+ {
+ Return(CDDS(DIDC))
+ }
+ }
+
+ //
+ // Query Graphics State (active or inactive).
+ //
+ Method(_DGS,0)
+ {
+ If(LAnd(LEqual(And(HGMD,0x7F),0x01),CondRefOf(SNXD)))
+ {
+ Return (NXD8)
+ }
+ Return(NDDS(DIDC))
+ }
+
+ //
+ // Device Set State.
+ //
+ Method(_DSS,1)
+ {
+ DSST(Arg0)
+ }
+}
+
+Device(DD0D)
+{
+ //
+ // Return Unique ID.
+ //
+ Method(_ADR,0,Serialized)
+ {
+ If(LEqual(And(0x0F00,DIDD),0x400))
+ {
+ Store(0xD, EDPV)
+ Store(NXD8, NXDX)
+ Store(DIDD, DIDX)
+ Return(0X0D)
+ }
+ If(LEqual(DIDD,0))
+ {
+ Return(0x0D)
+ }
+ Else
+ {
+ Return(And(0xFFFF,DIDD))
+ }
+ }
+
+ //
+ // Return the Current Status.
+ //
+ Method(_DCS,0)
+ {
+ If(LEqual(DIDD,0))
+ {
+ Return(0x0D)
+ }
+ Else
+ {
+ Return(CDDS(DIDD))
+ }
+ }
+
+ //
+ // Query Graphics State (active or inactive).
+ //
+ Method(_DGS,0)
+ {
+ If(LAnd(LEqual(And(HGMD,0x7F),0x01),CondRefOf(SNXD)))
+ {
+ Return (NXD8)
+ }
+ Return(NDDS(DIDD))
+ }
+
+ //
+ // Device Set State.
+ //
+ Method(_DSS,1)
+ {
+ DSST(Arg0)
+ }
+}
+
+Device(DD0E)
+{
+ //
+ // Return Unique ID.
+ //
+ Method(_ADR,0,Serialized)
+ {
+ If(LEqual(And(0x0F00,DIDE),0x400))
+ {
+ Store(0xE, EDPV)
+ Store(NXD8, NXDX)
+ Store(DIDE, DIDX)
+ Return(0X0E)
+ }
+ If(LEqual(DIDE,0))
+ {
+ Return(0x0E)
+ }
+ Else
+ {
+ Return(And(0xFFFF,DIDE))
+ }
+ }
+
+ //
+ // Return the Current Status.
+ //
+ Method(_DCS,0)
+ {
+ If(LEqual(DIDE,0))
+ {
+ Return(0x0E)
+ }
+ Else
+ {
+ Return(CDDS(DIDE))
+ }
+ }
+
+ //
+ // Query Graphics State (active or inactive).
+ //
+ Method(_DGS,0)
+ {
+ If(LAnd(LEqual(And(HGMD,0x7F),0x01),CondRefOf(SNXD)))
+ {
+ Return (NXD8)
+ }
+ Return(NDDS(DIDE))
+ }
+
+ //
+ // Device Set State.
+ //
+ Method(_DSS,1)
+ {
+ DSST(Arg0)
+ }
+}
+
+Device(DD0F)
+{
+ //
+ // Return Unique ID.
+ //
+ Method(_ADR,0,Serialized)
+ {
+ If(LEqual(And(0x0F00,DIDF),0x400))
+ {
+ Store(0xF, EDPV)
+ Store(NXD8, NXDX)
+ Store(DIDF, DIDX)
+ Return(0X0F)
+ }
+ If(LEqual(DIDF,0))
+ {
+ Return(0x0F)
+ }
+ Else
+ {
+ Return(And(0xFFFF,DIDF))
+ }
+ }
+
+ //
+ // Return the Current Status.
+ //
+ Method(_DCS,0)
+ {
+ If(LEqual(DIDC,0))
+ {
+ Return(0x0F)
+ }
+ Else
+ {
+ Return(CDDS(DIDF))
+ }
+ }
+
+ //
+ // Query Graphics State (active or inactive).
+ //
+ Method(_DGS,0)
+ {
+ If(LAnd(LEqual(And(HGMD,0x7F),0x01),CondRefOf(SNXD)))
+ {
+ Return (NXD8)
+ }
+ Return(NDDS(DIDF))
+ }
+
+ //
+ // Device Set State.
+ //
+ Method(_DSS,1)
+ {
+ DSST(Arg0)
+ }
+}
+
+//
+//Device for eDP
+//
+Device(DD1F)
+{
+ //
+ // Return Unique ID.
+ //
+ Method(_ADR,0,Serialized)
+ {
+ If(LEqual(EDPV, 0x0))
+ {
+ Return(0x1F)
+ }
+ Else
+ {
+ Return(And(0xFFFF,DIDX))
+ }
+ }
+
+ //
+ // Return the Current Status.
+ //
+ Method(_DCS,0)
+ {
+ If(LEqual(EDPV, 0x0))
+ {
+ Return(0x00)
+ }
+ Else
+ {
+ Return(CDDS(DIDX))
+ }
+ }
+
+ //
+ // Query Graphics State (active or inactive).
+ //
+ Method(_DGS,0)
+ {
+ If(LAnd(LEqual(And(HGMD,0x7F),0x01),CondRefOf(SNXD)))
+ {
+ Return (NXDX)
+ }
+ Return(NDDS(DIDX))
+ }
+
+ //
+ // Device Set State.
+ //
+ Method(_DSS,1)
+ {
+ DSST(Arg0)
+ }
+
+ //
+ // Query List of Brightness Control Levels Supported.
+ //
+ Method(_BCL,0)
+ {
+ //
+ // List of supported brightness levels in the following sequence.
+ // Level when machine has full power.
+ // Level when machine is on batteries.
+ // Other supported levels.
+ //
+ If(CondRefOf(\PBCL)) {
+ Return (PBCL())
+ } Else {
+ Return(Package(){80, 50, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100})
+ }
+ }
+
+ //
+ // Set the Brightness Level.
+ //
+ Method (_BCM,1)
+ {
+ //
+ // Set the requested level if it is between 0 and 100%.
+ //
+ If(LAnd(LGreaterEqual(Arg0,0),LLessEqual(Arg0,100)))
+ {
+ \_SB.PC00.GFX0.AINT(1, Arg0)
+ Store(Arg0,BRTL) // Store Brightness Level.
+ }
+ }
+
+ //
+ // Brightness Query Current level.
+ //
+ Method (_BQC,0)
+ {
+ Return(BRTL)
+ }
+
+ //
+ // Physical Location of Device
+ //
+ Method (_PLD,0)
+ {
+ If(CondRefOf(\PLD1)) {
+ Return (PLD1())
+ } Else {
+ Return (DPLD)
+ }
+ }
+}
+
+//
+// Second Display
+//
+Device(DD2F)
+{
+ //
+ // Return Unique ID.
+ //
+ Method(_ADR,0,Serialized)
+ {
+ If(LEqual(EDPV, 0x0))
+ {
+ Return(0x1F)
+ }
+ If(LEqual(EDPV, 0x1))
+ {
+ Return(0x1F)
+ }
+ Else
+ {
+ Return(And(0xFFFF,DIDY))
+ }
+ }
+
+ //
+ // Return the Current Status.
+ //
+ Method(_DCS,0)
+ {
+ If(LEqual(EDPV, 0x0))
+ {
+ Return(0x00)
+ }
+ If(LEqual(EDPV, 0x1))
+ {
+ Return(0x0)
+ }
+ Else
+ {
+ Return(CDDS(DIDY))
+ }
+ }
+
+ //
+ // Query Graphics State (active or inactive).
+ //
+ Method(_DGS,0)
+ {
+ If(LAnd(LEqual(And(HGMD,0x7F),0x01),CondRefOf(SNXD)))
+ {
+ Return (NXDY)
+ }
+ Return(NDDS(DIDY))
+ }
+
+ //
+ // Device Set State.
+ //
+ Method(_DSS,1)
+ {
+ DSST(Arg0)
+ }
+
+ //
+ // Query List of Brightness Control Levels Supported.
+ //
+ Method(_BCL,0)
+ {
+ //
+ // List of supported brightness levels in the following sequence.
+ // Level when machine has full power.
+ // Level when machine is on batteries.
+ // Other supported levels.
+ //
+ If(CondRefOf(\PBCL)) {
+ Return (PBCL())
+ } Else {
+ Return(Package(){80, 50, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100})
+ }
+ }
+
+ //
+ // Set the Brightness Level.
+ //
+ Method (_BCM,1)
+ {
+ //
+ // Set the requested level if it is between 0 and 100%.
+ //
+ If(LAnd(LGreaterEqual(Arg0,0),LLessEqual(Arg0,100)))
+ {
+ \_SB.PC00.GFX0.AINT(1, Arg0)
+ Store(Arg0,BRTL) // Store Brightness Level.
+ }
+ }
+
+ //
+ // Brightness Query Current level.
+ //
+ Method (_BQC,0)
+ {
+ Return(BRTL)
+ }
+
+ Method (_PLD,0)
+ {
+ If(CondRefOf(\PLD2)) {
+ Return (PLD2())
+ } Else {
+ Return (DPLD)
+ }
+ }
+}
+
+Method(SDDL,1)
+{
+ Increment(NDID)
+ Store(And(Arg0,0xF0F),Local0)
+ Or(0x80000000,Local0, Local1)
+ If(LEqual(DIDL,Local0))
+ {
+ Return(Local1)
+ }
+ If(LEqual(DDL2,Local0))
+ {
+ Return(Local1)
+ }
+ If(LEqual(DDL3,Local0))
+ {
+ Return(Local1)
+ }
+ If(LEqual(DDL4,Local0))
+ {
+ Return(Local1)
+ }
+ If(LEqual(DDL5,Local0))
+ {
+ Return(Local1)
+ }
+ If(LEqual(DDL6,Local0))
+ {
+ Return(Local1)
+ }
+ If(LEqual(DDL7,Local0))
+ {
+ Return(Local1)
+ }
+ If(LEqual(DDL8,Local0))
+ {
+ Return(Local1)
+ }
+ If(LEqual(DDL9,Local0))
+ {
+ Return(Local1)
+ }
+ If(LEqual(DD10,Local0))
+ {
+ Return(Local1)
+ }
+ If(LEqual(DD11,Local0))
+ {
+ Return(Local1)
+ }
+ If(LEqual(DD12,Local0))
+ {
+ Return(Local1)
+ }
+ If(LEqual(DD13,Local0))
+ {
+ Return(Local1)
+ }
+ If(LEqual(DD14,Local0))
+ {
+ Return(Local1)
+ }
+ If(LEqual(DD15,Local0))
+ {
+ Return(Local1)
+ }
+ Return(0)
+}
+
+Method(CDDS,1)
+{
+ Store(And(Arg0,0xF0F),Local0)
+
+ If(LEqual(0, Local0))
+ {
+ Return(0x1D)
+ }
+ If(LEqual(CADL, Local0))
+ {
+ Return(0x1F)
+ }
+ If(LEqual(CAL2, Local0))
+ {
+ Return(0x1F)
+ }
+ If(LEqual(CAL3, Local0))
+ {
+ Return(0x1F)
+ }
+ If(LEqual(CAL4, Local0))
+ {
+ Return(0x1F)
+ }
+ If(LEqual(CAL5, Local0))
+ {
+ Return(0x1F)
+ }
+ If(LEqual(CAL6, Local0))
+ {
+ Return(0x1F)
+ }
+ If(LEqual(CAL7, Local0))
+ {
+ Return(0x1F)
+ }
+ If(LEqual(CAL8, Local0))
+ {
+ Return(0x1F)
+ }
+ Return(0x1D)
+}
+
+Method(NDDS,1)
+{
+ Store(And(Arg0,0xF0F),Local0)
+
+ If(LEqual(0, Local0))
+ {
+ Return(0)
+ }
+ If(LEqual(NADL, Local0))
+ {
+ Return(1)
+ }
+ If(LEqual(NDL2, Local0))
+ {
+ Return(1)
+ }
+ If(LEqual(NDL3, Local0))
+ {
+ Return(1)
+ }
+ If(LEqual(NDL4, Local0))
+ {
+ Return(1)
+ }
+ If(LEqual(NDL5, Local0))
+ {
+ Return(1)
+ }
+ If(LEqual(NDL6, Local0))
+ {
+ Return(1)
+ }
+ If(LEqual(NDL7, Local0))
+ {
+ Return(1)
+ }
+ If(LEqual(NDL8, Local0))
+ {
+ Return(1)
+ }
+ Return(0)
+}
+
+//
+// Device Set State Table
+// BIT31 BIT30 Execution
+// 0 0 Don't implement.
+// 0 1 Cache change. Nothing to Implement.
+// 1 0 Don't Implement.
+// 1 1 Display Switch Complete. Implement.
+//
+Method(DSST,1)
+{
+ If(LEqual(And(Arg0,0xC0000000),0xC0000000))
+ {
+ //
+ // State change was performed by the
+ // Video Drivers. Simply update the
+ // New State.
+ //
+ Store(NSTE,CSTE)
+ }
+}
+
+//
+// Include IGD OpRegion/Software SCI interrupt handler/DSM which is used by
+// the graphics drivers to request data from system BIOS.
+//
+include ("IgfxOpRn.asl")
+include ("IgfxDsm.asl")
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Graphics/AcpiTables/IgfxCommon.asl b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Graphics/AcpiTables/IgfxCommon.asl
new file mode 100644
index 0000000000..7325b9fdea
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Graphics/AcpiTables/IgfxCommon.asl
@@ -0,0 +1,480 @@
+/** @file
+ IGD OpRegion/Software SCI Reference Code.
+ This file contains ASL code with the purpose of handling events
+ i.e. hotkeys and other system interrupts.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+//
+// Notes:
+// 1. The following routines are to be called from the appropriate event
+// handlers.
+// 2. This code cannot comprehend the exact implementation in the OEM's BIOS.
+// Therefore, an OEM must call these methods from the existing event
+// handler infrastructure. Details on when/why to call each method is
+// included in the method header under the "usage" section.
+//
+
+/************************************************************************;
+;* ACPI Notification Methods
+;************************************************************************/
+
+
+/************************************************************************;
+;*
+;* Name: PDRD
+;*
+;* Description: Check if the graphics driver is ready to process
+;* notifications and video extensions.
+;*
+;* Usage: This method is to be called prior to performing any
+;* notifications or handling video extensions.
+;* Ex: If (PDRD()) {Return (FAIL)}
+;*
+;* Input: None
+;*
+;* Output: None
+;*
+;* References: DRDY (Driver ready status), ASLP (Driver recommended
+;* sleep timeout value).
+;*
+;************************************************************************/
+
+External(HNOT, MethodObj)
+
+Method(PDRD)
+{
+ //
+ // If DRDY is clear, the driver is not ready. If the return value is
+ // !=0, do not perform any notifications or video extension handling.
+ //
+ Return(LNot(DRDY))
+}
+
+/************************************************************************;
+;*
+;* Name: PSTS
+;*
+;* Description: Check if the graphics driver has completed the previous
+;* "notify" command.
+;*
+;* Usage: This method is called before every "notify" command. A
+;* "notify" should only be set if the driver has completed the
+;* previous command. Else, ignore the event and exit the parent
+;* method.
+;* Ex: If (PSTS()) {Return (FAIL)}
+;*
+;* Input: None
+;*
+;* Output: None
+;*
+;* References: CSTS (Notification status), ASLP (Driver recommended sleep
+;* timeout value).
+;*
+;************************************************************************/
+
+Method(PSTS)
+{
+ If(LGreater(CSTS, 2))
+ {
+ //
+ // Sleep for ASLP milliseconds if the status is not "success,
+ // failure, or pending"
+ //
+ Sleep(ASLP)
+ }
+
+ Return(LEqual(CSTS, 3)) // Return True if still Dispatched
+}
+
+/************************************************************************;
+;*
+;* Name: GNOT
+;*
+;* Description: Call the appropriate methods to query the graphics driver
+;* status. If all methods return success, do a notification of
+;* the graphics device.
+;*
+;* Usage: This method is to be called when a graphics device
+;* notification is required (display switch hotkey, etc).
+;*
+;* Input: Arg0 = Current event type:
+;* 1 = display switch
+;* 2 = lid
+;* 3 = dock
+;* Arg1 = Notification type:
+;* 0 = Re-enumeration
+;* 0x80 = Display switch
+;*
+;* Output: Returns 0 = success, 1 = failure
+;*
+;* References: PDRD and PSTS methods. OSYS (OS version)
+;*
+;************************************************************************/
+
+Method(GNOT, 2)
+{
+ //
+ // Check for 1. Driver loaded, 2. Driver ready.
+ // If any of these cases is not met, skip this event and return failure.
+ //
+ If(PDRD())
+ {
+ Return(0x1) // Return failure if driver not loaded.
+ }
+
+ Store(Arg0, CEVT) // Set up the current event value
+ Store(3, CSTS) // CSTS=BIOS dispatched an event
+
+ If(LAnd(LEqual(CHPD, 0), LEqual(Arg1, 0))) // Do not re-enum if driver supports hotplug
+ {
+ //
+ // Re-enumerate the Graphics Device for non-XP operating systems.
+ //
+ Notify(\_SB.PC00.GFX0, Arg1)
+ }
+
+ If(CondRefOf(HNOT))
+ {
+ HNOT(Arg0) //Notification handler for Hybrid graphics
+ }
+ Else
+ {
+ Notify(\_SB.PC00.GFX0,0x80)
+ }
+
+ Return(0x0) // Return success
+}
+
+/************************************************************************;
+;*
+;* Name: GHDS
+;*
+;* Description: Handle a hotkey display switching event (performs a
+;* Notify(GFX0, 0).
+;*
+;* Usage: This method must be called when a hotkey event occurs and the
+;* purpose of that hotkey is to do a display switch.
+;*
+;* Input: Arg0 = Toggle table number.
+;*
+;* Output: Returns 0 = success, 1 = failure.
+;* CEVT and TIDX are indirect outputs.
+;*
+;* References: TIDX, GNOT
+;*
+;************************************************************************/
+
+Method(GHDS, 1)
+{
+ Store(Arg0, TIDX) // Store the table number
+ //
+ // Call GNOT for CEVT = 1 = hotkey, notify value = 0
+ //
+ Return(GNOT(1, 0)) // Return stats from GNOT
+}
+
+/************************************************************************;
+;*
+;* Name: GLID
+;*
+;* Description: Handle a lid event (performs the Notify(GFX0, 0), but not the
+;* lid notify).
+;*
+;* Usage: This method must be called when a lid event occurs. A
+;* Notify(LID0, 0x80) must follow the call to this method.
+;*
+;* Input: Arg0 = Lid state:
+;* 0 = All closed
+;* 1 = internal LFP lid open
+;* 2 = external lid open
+;* 3 = both external and internal open
+;*
+;* Output: Returns 0=success, 1=failure.
+;* CLID and CEVT are indirect outputs.
+;*
+;* References: CLID, GNOT
+;*
+;************************************************************************/
+
+Method(GLID, 1)
+{
+
+ If (LEqual(Arg0,1))
+ {
+ Store(3,CLID)
+ }
+ Else
+ {
+ Store(Arg0, CLID)
+ }
+ //
+ //Store(Arg0, CLID) // Store the current lid state
+ // Call GNOT for CEVT=2=Lid, notify value = 0
+ //
+ if (GNOT(2, 0)) {
+ Or (CLID, 0x80000000, CLID)
+ Return (1) // Return Fail
+ }
+
+ Return (0) // Return Pass
+}
+
+/************************************************************************;
+;*
+;* Name: GDCK
+;*
+;* Description: Handle a docking event by updating the current docking status
+;* and doing a notification.
+;*
+;* Usage: This method must be called when a docking event occurs.
+;*
+;* Input: Arg0 = Docking state:
+;* 0 = Undocked
+;* 1 = Docked
+;*
+;* Output: Returns 0=success, 1=failure.
+;* CDCK and CEVT are indirect outputs.
+;*
+;* References: CDCK, GNOT
+;*
+;************************************************************************/
+
+Method(GDCK, 1)
+{
+ Store(Arg0, CDCK) // Store the current dock state
+ //
+ // Call GNOT for CEVT=4=Dock, notify value = 0
+ //
+ Return(GNOT(4, 0)) // Return stats from GNOT
+}
+
+/************************************************************************;
+;* ASLE Interrupt Methods
+;************************************************************************/
+
+/************************************************************************;
+;*
+;* Name: PARD
+;*
+;* Description: Check if the driver is ready to handle ASLE interrupts
+;* generate by the system BIOS.
+;*
+;* Usage: This method must be called before generating each ASLE
+;* interrupt.
+;*
+;* Input: None
+;*
+;* Output: Returns 0 = success, 1 = failure.
+;*
+;* References: ARDY (Driver readiness), ASLP (Driver recommended sleep
+;* timeout value)
+;*
+;************************************************************************/
+
+Method(PARD)
+{
+ If(LNot(ARDY))
+ {
+ //
+ // Sleep for ASLP milliseconds if the driver is not ready.
+ //
+ Sleep(ASLP)
+ }
+ //
+ // If ARDY is clear, the driver is not ready. If the return value is
+ // !=0, do not generate the ASLE interrupt.
+ //
+ Return(LNot(ARDY))
+}
+
+//
+// Intel Ultrabook Event Handler. Arg0 represents the Ultrabook Event Bit # to pass
+// to the Intel Graphics Driver. Note that this is a serialized method, meaning
+// sumultaneous events are not allowed.
+//
+Method(IUEH,1,Serialized)
+{
+ And(IUER,0xC0,IUER) // Clear all button events on entry.
+ XOr(IUER,Shiftleft(1,Arg0),IUER) // Toggle status.
+
+ If(LLessEqual(Arg0,4)) // Button Event?
+ {
+ Return(AINT(5,0)) // Generate event and return status.
+
+ }
+ Else // Indicator Event.
+ {
+ Return(AINT(Arg0,0)) // Generate event and return status.
+ }
+}
+
+/************************************************************************;
+;*
+;* Name: AINT
+;*
+;* Description: Call the appropriate methods to generate an ASLE interrupt.
+;* This process includes ensuring the graphics driver is ready
+;* to process the interrupt, ensuring the driver supports the
+;* interrupt of interest, and passing information about the event
+;* to the graphics driver.
+;*
+;* Usage: This method must called to generate an ASLE interrupt.
+;*
+;* Input: Arg0 = ASLE command function code:
+;* 0 = Set ALS illuminance
+;* 1 = Set backlight brightness
+;* 2 = Do Panel Fitting
+;* 4 = Reserved
+;* 5 = Button Indicator Event
+;* 6 = Convertible Indicator Event
+;* 7 = Docking Indicator Event
+;* Arg1 = If Arg0 = 0, current ALS reading:
+;* 0 = Reading below sensor range
+;* 1-0xFFFE = Current sensor reading
+;* 0xFFFF = Reading above sensor range
+;* Arg1 = If Arg0 = 1, requested backlight percentage
+;*
+;* Output: Returns 0 = success, 1 = failure
+;*
+;* References: PARD method.
+;*
+;************************************************************************/
+
+Method(AINT, 2)
+{
+ //
+ // Return failure if the requested feature is not supported by the
+ // driver.
+ //
+ If(LNot(And(TCHE, ShiftLeft(1, Arg0))))
+ {
+ Return(0x1)
+ }
+ //
+ // Return failure if the driver is not ready to handle an ASLE
+ // interrupt.
+ //
+ If(PARD())
+ {
+ Return(0x1)
+ }
+ //
+ // Handle Intel Ultrabook Events.
+ //
+ If(LAnd(LGreaterEqual(Arg0,5),LLessEqual(Arg0,7)))
+ {
+ Store(ShiftLeft(1,Arg0), ASLC) // Set Ultrbook Event [6:4].
+ Store(0x01, ASLE) // Generate ASLE interrupt
+
+ Store(0,Local2) // Use Local2 as a timeout counter. Intialize to zero.
+
+ While(LAnd(LLess(Local2,250),LNotEqual(ASLC,0))) // Wait 1 second or until Driver ACKs a success.
+ {
+ Sleep(4) // Delay 4 ms.
+ Increment(Local2) // Increment Timeout.
+ }
+
+ Return(0) // Return success
+ }
+ //
+ // Evaluate the first argument (Panel fitting, backlight brightness, or ALS).
+ //
+ If(LEqual(Arg0, 2)) // Arg0 = 2, so request a panel fitting mode change.
+ {
+ If(CPFM) // If current mode field is non-zero use it.
+ {
+ And(CPFM, 0x0F, Local0) // Create variables without reserved
+ And(EPFM, 0x0F, Local1) // or valid bits.
+
+ If(LEqual(Local0, 1)) // If current mode is centered,
+ {
+ If(And(Local1, 6)) // and if stretched is enabled,
+ {
+ Store(6, PFIT) // request stretched.
+ }
+ Else // Otherwise,
+ {
+ If(And(Local1, 8)) // if aspect ratio is enabled,
+ {
+ Store(8, PFIT) // request aspect ratio.
+ }
+ Else // Only centered mode is enabled
+ {
+ Store(1, PFIT) // so request centered. (No change.)
+ }
+ }
+ }
+ If(LEqual(Local0, 6)) // If current mode is stretched,
+ {
+ If(And(Local1, 8)) // and if aspect ratio is enabled,
+ {
+ Store(8, PFIT) // request aspect ratio.
+ }
+ Else // Otherwise,
+ {
+ If(And(Local1, 1)) // if centered is enabled,
+ {
+ Store(1, PFIT) // request centered.
+ }
+ Else // Only stretched mode is enabled
+ {
+ Store(6, PFIT) // so request stretched. (No change.)
+ }
+ }
+ }
+ If(LEqual(Local0, 8)) // If current mode is aspect ratio,
+ {
+ If(And(Local1, 1)) // and if centered is enabled,
+ {
+ Store(1, PFIT) // request centered.
+ }
+ Else // Otherwise,
+ {
+ If(And(Local1, 6)) // if stretched is enabled,
+ {
+ Store(6, PFIT) // request stretched.
+ }
+ Else // Only aspect ratio mode is enabled
+ {
+ Store(8, PFIT) // so request aspect ratio. (No change.)
+ }
+ }
+ }
+ }
+ //
+ // The following code for panel fitting (within the Else condition) is retained for backward compatiblity.
+ //
+ Else // If CFPM field is zero use PFIT and toggle the
+ {
+ Xor(PFIT,7,PFIT) // mode setting between stretched and centered only.
+ }
+ Or(PFIT,0x80000000,PFIT) // Set the valid bit for all cases.
+ Store(4, ASLC) // Store "Panel fitting event" to ASLC[31:1]
+ }
+ Else
+ {
+ If(LEqual(Arg0, 1)) // Arg0=1, so set the backlight brightness.
+ {
+ Store(Divide(Multiply(Arg1, 255), 100), BCLP) // Convert from percent to 0-255.
+ Or(BCLP, 0x80000000, BCLP) // Set the valid bit.
+ Store(2, ASLC) // Store "Backlight control event" to ASLC[31:1]
+ }
+ Else
+ {
+ If(LEqual(Arg0, 0)) // Arg0=0, so set the ALS illuminace
+ {
+ Store(Arg1, ALSI)
+ Store(1, ASLC) // Store "ALS event" to ASLC[31:1]
+ }
+ Else
+ {
+ Return(0x1) // Unsupported function
+ }
+ }
+ }
+
+ Store(0x01, ASLE) // Generate ASLE interrupt
+ Return(0x0) // Return success
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Graphics/AcpiTables/IgfxDsm.asl b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Graphics/AcpiTables/IgfxDsm.asl
new file mode 100644
index 0000000000..ecd87e8c1f
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Graphics/AcpiTables/IgfxDsm.asl
@@ -0,0 +1,398 @@
+/** @file
+ IGD OpRegion/_DSM Reference Code.
+ This file contains Get BIOS Data and Callback functions for
+ the Integrated Graphics Device (IGD) OpRegion/DSM mechanism
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+External(\_SB.PC00.IMMC, MethodObj)
+External(\_SB.PC00.IMMD, MethodObj)
+
+//
+// _DSM Device Specific Method
+//
+// Arg0: UUID Unique function identifier
+// Arg1: Integer Revision Level
+// Arg2: Integer Function Index (1 = Return Supported Functions)
+// Arg3: Additional Inputs/Package Parameters Bits [31:0] input as {Byte0, Byte1, Byte2, Byte3} to BIOS which is passed as 32 bit DWORD by Driver
+//
+Method (_DSM, 4, Serialized, 0, UnknownObj, {BuffObj, IntObj, IntObj, PkgObj}) {
+
+ If (LEqual(Arg0, ToUUID ("3E5B41C6-EB1D-4260-9D15-C71FBADAE414"))) {
+ //
+ // _DSM Definition for Igd functions
+ // Arguments:
+ // Arg0: UUID: 3E5B41C6-EB1D-4260-9D15-C71FBADAE414
+ // Arg1: Revision ID: 1
+ // Arg2: Function Index: 16
+ // Arg3: Additional Inputs Bits[31:0] Arg3 {Byte0, Byte1, Byte2, Byte3}
+ //
+ // Return:
+ // Success for simple notification, Opregion update for some routines and a Package for AKSV
+ //
+ If (Lor(LEqual(Arg2,18),LEqual(Arg2,19))) {
+ CreateDwordField(Arg3, 0x0, DDIN)
+ CreateDwordField(Arg3, 0x4, BUF1)
+ //
+ // OPTS is return buffer from IOM mailbox -
+ // Byte[0] is Status field.
+ // BYTE[1] is HDP Count.
+ //
+ Name(OPTS, Buffer(4){0,0,0,0})
+ CreateByteField(OPTS, 0x00, CMST) // Command Status field
+ // Success - 0
+ // Fail - 1
+ CreateByteField(OPTS, 0x01, RTB1) // Return Buffer 1
+
+ //
+ // Gfx Empty Dongle Buffer is data for return DSM fun#
+ // with below buffer format
+ // Byte[0-3] is Data field.
+ // Byte[4] is Status field.
+ //
+ Name(GEDB, Buffer(5){0,0,0,0,0})
+ CreateDwordField(GEDB, 0x00, GEDF) // Gfx Empty Dongle Data Field
+ CreateByteField(GEDB, 0x04, GESF) // Gfx Empty Dongle Status Field
+ // Success - 0
+ // Fail - None 0
+ }
+
+ //
+ // Switch by function index
+ //
+ Switch(ToInteger(Arg2)) {
+ //
+ // Function Index: 0
+ // Standard query - A bitmask of functions supported
+ //
+ // Return: A bitmask of functions supported
+ //
+ Case (0)
+ {
+ If (LEqual(Arg1, 1)) { // test Arg1 for Revision ID: 1
+ Store("iGfx Supported Functions Bitmap ", Debug)
+
+ Return(0xDE7FF)
+ }
+ }
+
+ //
+ // Function Index: 1
+ // Adapter Power State Notification
+ // Arg3 Bits [7:0]: Adapter Power State bits [7:0] from Driver 00h = D0; 01h = D1; 02h = D2; 04h = D3 (Cold/Hot); 08h = D4 (Hibernate Notification)
+ // Return: Success
+ //
+ Case(1) {
+ If (LEqual(Arg1, 1)) { // test Arg1 for Revision ID: 1
+ Store(" Adapter Power State Notification ", Debug)
+
+ //
+ // Handle Low Power S0 Idle Capability if enabled
+ //
+ If(LAnd(LEqual(S0ID, 1),LLess(OSYS, 2015))) {
+ //
+ // Call GUAM to trigger CS Entry
+ // If Adapter Power State Notification = D1 (Arg3[0]=0x01)
+ //
+ If (LEqual (And(DerefOf (Index (Arg3,0)), 0xFF), 0x01)) {
+ // GUAM - Global User Absent Mode Notification Method
+ \GUAM(One) // 0x01 - Power State Standby (CS Entry)
+ }
+ Store(And(DerefOf (Index (Arg3,1)), 0xFF), Local0)
+ //
+ // Call GUAM
+ // If Display Turn ON Notification (Arg3 [1] == 0) for CS Exit
+ //
+ If (LEqual (Local0, 0)) {
+ // GUAM - Global User Absent Mode Notification Method
+ \GUAM(0)
+ }
+ }
+
+ // Upon notification from driver that the Adapter Power State = D0,
+ // check if previous lid event failed. If it did, retry the lid
+ // event here.
+ If(LEqual(DerefOf (Index (Arg3,0)), 0)) {
+ Store(CLID, Local0)
+ If(And(0x80000000,Local0)) {
+ And(CLID, 0x0000000F, CLID)
+ GLID(CLID)
+ }
+ }
+ Return(0x01)
+ }
+ }
+ //
+ // Function Index: 2
+ // Display Power State Notification
+ // Arg3: Display Power State Bits [15:8]
+ // 00h = On
+ // 01h = Standby
+ // 02h = Suspend
+ // 04h = Off
+ // 08h = Reduced On
+ // Return: Success
+ //
+ Case(2) {
+ if (LEqual(Arg1, 1)) { // test Arg1 for Revision ID: 1
+
+ Store("Display Power State Notification ", Debug)
+ Return(0x01)
+ }
+ }
+
+ //
+ // Function Index: 3
+ // BIOS POST Completion Notification
+ // Return: Success
+ //
+ Case(3) {
+ if (LEqual(Arg1, 1)) { // test Arg1 for Revision ID: 1
+ Store("BIOS POST Completion Notification ", Debug)
+ Return(0x01) // Not supported, but no failure
+ }
+ }
+
+ //
+ // Function Index: 4
+ // Pre-Hires Set Mode
+ // Return: Success
+ //
+ Case(4) {
+ if (LEqual(Arg1, 1)){ // test Arg1 for Revision ID: 1
+ Store("Pre-Hires Set Mode ", Debug)
+ Return(0x01) // Not supported, but no failure
+ }
+ }
+
+ //
+ // Function Index: 5
+ // Post-Hires Set Mode
+ // Return: Success
+ //
+ Case(5) {
+ if (LEqual(Arg1, 1)){ // test Arg1 for Revision ID: 1
+ Store("Post-Hires Set Mode ", Debug)
+ Return(0x01) // Not supported, but no failure
+ }
+ }
+
+ //
+ // Function Index: 6
+ // SetDisplayDeviceNotification (Display Switch)
+ // Return: Success
+ //
+ Case(6) {
+ if (LEqual(Arg1, 1)){ // test Arg1 for Revision ID: 1
+ Store("SetDisplayDeviceNotification", Debug)
+ Return(0x01) // Not supported, but no failure
+ }
+ }
+
+ //
+ // Function Index: 7
+ // SetBootDevicePreference
+ // Return: Success
+ //
+ Case(7) {
+ if (LEqual(Arg1, 1)){ // test Arg1 for Revision ID: 1
+ //<TODO> An OEM may elect to implement this method. In that case,
+ // the input values must be saved into non-volatile storage for
+ // parsing during the next boot. The following Sample code is Intel
+ // validated implementation.
+
+ Store("SetBootDevicePreference ", Debug)
+ And(DerefOf (Index (Arg3,0)), 0xFF, IBTT) // Save the boot display to NVS
+ Return(0x01)
+ }
+ }
+
+ //
+ // Function Index: 8
+ // SetPanelPreference
+ // Return: Success
+ //
+ Case(8) {
+ if (LEqual(Arg1, 1)){ // test Arg1 for Revision ID: 1
+ // An OEM may elect to implement this method. In that case,
+ // the input values must be saved into non-volatile storage for
+ // parsing during the next boot. The following Sample code is Intel
+ // validated implementation.
+
+ Store("SetPanelPreference ", Debug)
+
+ // Set the panel-related NVRAM variables based the input from the driver.
+ And(DerefOf (Index (Arg3,0)), 0xFF, IPSC)
+
+ // Change panel type if a change is requested by the driver (Change if
+ // panel type input is non-zero). Zero=No change requested.
+ If(And(DerefOf (Index (Arg3,1)), 0xFF)) {
+ And(DerefOf (Index (Arg3,1)), 0xFF, IPAT)
+ Decrement(IPAT) // 0 = no change, so fit to CMOS map
+ }
+ And(ShiftRight(DerefOf (Index (Arg3,2)), 4), 0x7, IBIA)
+ Return(0x01) // Success
+ }
+ }
+
+ //
+ // Function Index: 9
+ // FullScreenDOS
+ // Return: Success
+ //
+ Case(9) {
+ if (LEqual(Arg1, 1)){ // test Arg1 for Revision ID: 1
+ Store("FullScreenDOS ", Debug)
+ Return(0x01) // Not supported, but no failure
+ }
+ }
+
+ //
+ // Function Index: 10
+ // APM Complete
+ // Return: Adjusted Lid State
+ //
+ Case(10) {
+ if (LEqual(Arg1, 1)) { // test Arg1 for Revision ID: 1
+
+ Store("APM Complete ", Debug)
+ Store(ShiftLeft(LIDS, 8), Local0) // Report the lid state
+ Add(Local0, 0x100, Local0) // Adjust the lid state, 0 = Unknown
+ Return(Local0)
+ }
+ }
+
+ //
+ //
+ // Function Index: 13
+ // GetBootDisplayPreference
+ // Arg3 Bits [30:16] : Boot Device Ports
+ // Arg3 Bits [7:0] : Boot Device Type
+ // Return: Boot device port and Boot device type from saved configuration
+ //
+ Case(13) {
+ if (LEqual(Arg1, 1)){ // test Arg1 for Revision ID: 1
+
+ Store("GetBootDisplayPreference ", Debug)
+ Or(ShiftLeft(DerefOf (Index (Arg3,3)), 24), ShiftLeft(DerefOf (Index (Arg3,2)), 16), Local0) // Combine Arg3 Bits [31:16]
+ And(Local0, 0xEFFF0000, Local0)
+ And(Local0, ShiftLeft(DeRefOf(Index(DBTB, IBTT)), 16), Local0)
+ Or(IBTT, Local0, Local0) // Arg3 Bits [7:0] = Boot device type
+ Return(Local0)
+ }
+ }
+
+ //
+ // Function Index: 14
+ // GetPanelDetails
+ // Return: Different Panel Settings
+ //
+ Case(14) {
+ if (LEqual(Arg1, 1)){ // test Arg1 for Revision ID: 1
+ Store("GetPanelDetails ", Debug)
+
+ // Report the scaling setting
+ // Bits [7:0] - Panel Scaling
+ // Bits contain the panel scaling user setting from CMOS
+ // 00h = On: Auto
+ // 01h = On: Force Scaling
+ // 02h = Off
+ // 03h = Maintain Aspect Ratio
+
+ Store(IPSC, Local0)
+ Or(Local0, ShiftLeft(IPAT, 8), Local0)
+
+ // Adjust panel type, 0 = VBT default
+ // Bits [15:8] - Panel Type
+ // Bits contain the panel type user setting from CMOS
+ // 00h = Not Valid, use default Panel Type & Timings from VBT
+ // 01h - 0Fh = Panel Number
+
+ Add(Local0, 0x100, Local0)
+
+ // Report the lid state and Adjust it
+ // Bits [16] - Lid State
+ // Bits contain the current panel lid state
+ // 0 = Lid Open
+ // 1 = Lid Closed
+
+ Or(Local0, ShiftLeft(LIDS, 16), Local0)
+ Add(Local0, 0x10000, Local0)
+
+ // Report the BIA setting
+ // Bits [22:20] - Backlight Image Adaptation (BIA) Control
+ // Bits contain the backlight image adaptation control user setting from CMOS
+ // 000 = VBT Default
+ // 001 = BIA Disabled (BLC may still be enabled)
+ // 010 - 110 = BIA Enabled at Aggressiveness Level [1 - 5]
+
+ Or(Local0, ShiftLeft(IBIA, 20), Local0)
+ Return(Local0)
+ }
+ }
+
+ //
+ // Function Index: 15
+ // GetInternalGraphics
+ // Return: Different Internal Grahics Settings
+ //
+
+ Case(15) {
+ if (LEqual(Arg1, 1)){ // test Arg1 for Revision ID: 1
+ Store("GetInternalGraphics ", Debug)
+
+ Store(GIVD, Local0) // Local0[0] - VGA mode(1=VGA)
+ Xor(Local0, 1, Local0) // Invert the VGA mode polarity
+
+ Or(Local0, ShiftLeft(GMFN, 1), Local0) // Local0[1] - # IGD PCI functions-1
+ // Local0[3:2] - Reserved
+ // Local0[4] - IGD D3 support(0=cold)
+ // Local0[10:5] - Reserved
+ Or(Local0, ShiftLeft(3, 11), Local0) // Local0[12:11] - DVMT version (11b = 5.0)
+
+ //
+ // Report DVMT 5.0 Total Graphics memory size.
+ //
+ Or(Local0, ShiftLeft(IDMS, 17), Local0) // Bits 20:17 are for Gfx total memory size
+
+ // If the "Set Internal Graphics" call is supported, the modified
+ // settings flag must be programmed per the specification. This means
+ // that the flag must be set to indicate that system BIOS requests
+ // these settings. Once "Set Internal Graphics" is called, the
+ // modified settings flag must be cleared on all subsequent calls to
+ // this function.
+
+ // Report the graphics frequency based on B0:D2:F0:RF0h[12]. Must
+ // take into account the current VCO.
+
+ Or(ShiftLeft(DeRefOf(Index(DeRefOf(Index(CDCT, HVCO)), CDVL)), 21),Local0, Local0)
+ Return(Local0)
+ }
+ }
+
+ //
+ // Function Index: 16
+ // GetAKSV
+ // Retrun: 5 bytes of AKSV
+ //
+ Case(16) {
+ if (LEqual(Arg1, 1)) { // test Arg1 for Revision ID: 1
+
+ Store("GetAKSV ", Debug)
+ Name (KSVP, Package()
+ {
+ 0x80000000,
+ 0x8000
+ })
+ Store(KSV0, Index(KSVP,0)) // First four bytes of AKSV
+ Store(KSV1, Index(KSVP,1)) // Fifth byte of AKSV
+ Return(KSVP) // Success
+ }
+ }
+ } // End of switch(Arg2)
+ } // End of if (ToUUID("3E5B41C6-EB1D-4260-9D15-C71FBADAE414D"))
+
+ Return (Buffer () {0x00})
+} // End of _DSM
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Graphics/AcpiTables/IgfxOpGbda.asl b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Graphics/AcpiTables/IgfxOpGbda.asl
new file mode 100644
index 0000000000..2b5f2393b0
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Graphics/AcpiTables/IgfxOpGbda.asl
@@ -0,0 +1,127 @@
+/** @file
+ IGD OpRegion/Software SCI Reference Code.
+ This file contains Get BIOS Data Area funciton support for
+ the Integrated Graphics Device (IGD) OpRegion/Software SCI mechanism
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+Method (GBDA, 0, Serialized)
+{
+ //
+ // Supported calls: Sub-function 0
+ //
+ If (LEqual(GESF, 0))
+ {
+ //
+ //<NOTE> Reference code is set to Intel's validated implementation.
+ //
+ Store(0x0000659, PARM)
+ Store(Zero, GESF) // Clear the exit parameter
+ Return(SUCC) // Success
+ }
+ //
+ // Requested callbacks: Sub-function 1
+ //
+ If (LEqual(GESF, 1))
+ {
+ //
+ //<NOTE> Call back functions are where the driver calls the
+ // system BIOS at function indicated event.
+ //
+ Store(0x300482, PARM)
+ If(LEqual(S0ID, One)){
+ Or(PARM, 0x100, PARM) //Request Fn 8 callback in CS systems
+ }
+ Store(Zero, GESF) // Clear the exit parameter
+ Return(SUCC) // Success
+ }
+ //
+ // Get Boot display Preferences: Sub-function 4
+ //
+ If (LEqual(GESF, 4))
+ {
+ //
+ //<NOTE> Get Boot Display Preferences function.
+ //
+ And(PARM, 0xEFFF0000, PARM) // PARM[30:16] = Boot device ports
+ And(PARM, ShiftLeft(DeRefOf(Index(DBTB, IBTT)), 16), PARM)
+ Or(IBTT, PARM, PARM) // PARM[7:0] = Boot device type
+ Store(Zero, GESF) // Clear the exit parameter
+ Return(SUCC) // Success
+ }
+ //
+ // Panel details: Sub-function 5
+ //
+ If (LEqual(GESF, 5))
+ {
+ //
+ //<NOTE> Get Panel Details function.
+ //
+ Store(IPSC, PARM) // Report the scaling setting
+ Or(PARM, ShiftLeft(IPAT, 8), PARM)
+ Add(PARM, 0x100, PARM) // Adjust panel type, 0 = VBT default
+ Or(PARM, ShiftLeft(LIDS, 16), PARM) // Report the lid state
+ Add(PARM, 0x10000, PARM) // Adjust the lid state, 0 = Unknown
+ Or(PARM, ShiftLeft(IBIA, 20), PARM) // Report the BIA setting
+ Store(Zero, GESF)
+ Return(SUCC)
+ }
+ //
+ // Internal graphics: Sub-function 7
+ //
+ If (LEqual(GESF, 7))
+ {
+ Store(GIVD, PARM) // PARM[0] - VGA mode(1=VGA)
+ Xor(PARM, 1, PARM) // Invert the VGA mode polarity
+ Or(PARM, ShiftLeft(GMFN, 1), PARM) // PARM[1] - # IGD PCI functions-1
+ // PARM[3:2] - Reserved
+ // PARM[4] - IGD D3 support(0=cold)
+ // PARM[10:5] - Reserved
+ Or(PARM, ShiftLeft(3, 11), PARM) // PARM[12:11] - DVMT mode(11b = 5.0)
+
+ //
+ // Report DVMT 5.0 Total Graphics memory size.
+ //
+ Or(PARM, ShiftLeft(IDMS, 17), PARM) // Bits 20:17 are for Gfx total memory size
+ //
+ // If the "Set Internal Graphics" call is supported, the modified
+ // settings flag must be programmed per the specification. This means
+ // that the flag must be set to indicate that system BIOS requests
+ // these settings. Once "Set Internal Graphics" is called, the
+ // modified settings flag must be cleared on all subsequent calls to
+ // this function.
+ // Report the graphics frequency based on B0:D2:F0:RF0h[12]. Must
+ // take into account the current VCO.
+ //
+ Or(ShiftLeft(Derefof(Index(Derefof(Index(CDCT, HVCO)), CDVL)), 21),PARM, PARM)
+ Store(1, GESF) // Set the modified settings flag
+ Return(SUCC)
+ }
+ //
+ // Spread spectrum clocks: Sub-function 10
+ //
+ If (LEqual(GESF, 10))
+ {
+ Store(0, PARM) // Assume SSC is disabled
+ If(ISSC)
+ {
+ Or(PARM, 3, PARM) // If SSC enabled, return SSC1+Enabled
+ }
+ Store(0, GESF) // Set the modified settings flag
+ Return(SUCC) // Success
+ }
+
+ If (LEqual(GESF, 11))
+ {
+ Store(KSV0, PARM) // First four bytes of AKSV
+ Store(KSV1, GESF) // Fifth byte of AKSV
+
+ Return(SUCC) // Success
+ }
+ //
+ // A call to a reserved "Get BIOS data" function was received.
+ //
+ Store(Zero, GESF) // Clear the exit parameter
+ Return(CRIT) // Reserved, "Critical failure"
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Graphics/AcpiTables/IgfxOpRn.asl b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Graphics/AcpiTables/IgfxOpRn.asl
new file mode 100644
index 0000000000..410524b324
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Graphics/AcpiTables/IgfxOpRn.asl
@@ -0,0 +1,314 @@
+/** @file
+ IGD OpRegion/Software SCI Reference Code.
+ This file contains the interrupt handler code for the Integrated
+ Graphics Device (IGD) OpRegion/Software SCI mechanism.
+ It defines OperationRegions to cover the IGD PCI configuration space
+ as described in the IGD OpRegion specification.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+//
+//NOTES:
+//
+// (1) The code contained in this file inherits the scope in which it
+// was included. So BIOS developers must be sure to include this
+// file in the scope associated with the graphics device
+// (ex. \_SB.PC00.GFX0).
+// (2) Create a _L06 method under the GPE scope to handle the event
+// generated by the graphics driver. The _L06 method must call
+// the GSCI method in this file.
+// (3) The MCHP operation region assumes that _ADR and _BBN names
+// corresponding to bus 0, device0, function 0 have been declared
+// under the PC00 scope.
+// (4) Before the first execution of the GSCI method, the base address
+// of the GMCH SCI OpRegion must be programmed where the driver can
+// access it. A 32bit scratch register at 0xFC in the IGD PCI
+// configuration space (B0/D2/F0/R0FCh) is used for this purpose.
+
+// Define an OperationRegion to cover the GMCH PCI configuration space as
+// described in the IGD OpRegion specificiation.
+//
+Scope(\_SB.PC00)
+{
+ OperationRegion(MCHP, PCI_Config, 0x40, 0xC0)
+ Field(MCHP, AnyAcc, NoLock, Preserve)
+ {
+ Offset(0x14),
+ AUDE, 8,
+
+ Offset(0x60), // Top of Memory register
+ TASM, 10, // Total system memory (64MB gran)
+ , 6,
+ }
+}
+
+//
+// Define an OperationRegion to cover the IGD PCI configuration space as
+// described in the IGD OpRegion specificiation.
+//
+OperationRegion(IGDP, PCI_Config, 0x40, 0xC0)
+Field(IGDP, AnyAcc, NoLock, Preserve)
+{
+ Offset(0x10), // Mirror of gfx control reg
+ , 1,
+ GIVD, 1, // IGD VGA disable bit
+ , 2,
+ GUMA, 3, // Stolen memory size
+ , 9,
+ Offset(0x14),
+ , 4,
+ GMFN, 1, // Gfx function 1 enable
+ , 27,
+ Offset(0xA4),
+ ASLE, 8, // Reg 0xE4, ASLE interrupt register
+ , 24, // Only use first byte of ASLE reg
+ Offset(0xA8), // Reg 0xE8, SWSCI control register
+ GSSE, 1, // Graphics SCI event (1=event pending)
+ GSSB, 14, // Graphics SCI scratchpad bits
+ GSES, 1, // Graphics event select (1=SCI)
+ Offset(0xB0), // Gfx Clk Frequency and Gating Control
+ , 12,
+ CDVL, 1, // Core display clock value
+ , 3, // Graphics Core Display Clock Select
+ Offset(0xB5),
+ LBPC, 8, // Legacy brightness control
+ Offset(0xBC),
+ ASLS, 32, // Reg 0xFC, Address of the IGD OpRegion
+}
+
+//
+// Define an OperationRegion to cover the IGD OpRegion layout.
+//
+OperationRegion(IGDM, SystemMemory, ASLB, 0x2000)
+Field(IGDM, AnyAcc, NoLock, Preserve)
+{
+ //
+ // OpRegion Header
+ //
+ SIGN, 128, // Signature-"IntelGraphicsMem"
+ SIZE, 32, // OpRegion Size
+ OVER, 32, // OpRegion Version
+ SVER, 256, // System BIOS Version
+ VVER, 128, // VBIOS Version
+ GVER, 128, // Driver version
+ MBOX, 32, // Mailboxes supported
+ DMOD, 32, // Driver Model
+ PCON, 32, // Platform Configuration
+ DVER, 64, // GOP Version
+ //
+ // OpRegion Mailbox 1 (Public ACPI Methods)
+ // Note: Mailbox 1 is normally reserved for desktop platforms.
+ //
+ Offset(0x100),
+ DRDY, 32, // Driver readiness (ACPI notification)
+ CSTS, 32, // Notification status
+ CEVT, 32, // Current event
+ Offset(0x120),
+ DIDL, 32, // Supported display device ID list
+ DDL2, 32, // Allows for 8 devices
+ DDL3, 32,
+ DDL4, 32,
+ DDL5, 32,
+ DDL6, 32,
+ DDL7, 32,
+ DDL8, 32,
+ CPDL, 32, // Currently present display list
+ CPL2, 32, // Allows for 8 devices
+ CPL3, 32,
+ CPL4, 32,
+ CPL5, 32,
+ CPL6, 32,
+ CPL7, 32,
+ CPL8, 32,
+ CADL, 32, // Currently active display list
+ CAL2, 32, // Allows for 8 devices
+ CAL3, 32,
+ CAL4, 32,
+ CAL5, 32,
+ CAL6, 32,
+ CAL7, 32,
+ CAL8, 32,
+ NADL, 32, // Next active display list
+ NDL2, 32, // Allows for 8 devices
+ NDL3, 32,
+ NDL4, 32,
+ NDL5, 32,
+ NDL6, 32,
+ NDL7, 32,
+ NDL8, 32,
+ ASLP, 32, // ASL sleep timeout
+ TIDX, 32, // Toggle table index
+ CHPD, 32, // Current hot plug enable indicator
+ CLID, 32, // Current lid state indicator
+ CDCK, 32, // Current docking state indicator
+ SXSW, 32, // Display switch notify on resume
+ EVTS, 32, // Events supported by ASL (diag only)
+ CNOT, 32, // Current OS notifications (diag only)
+ NRDY, 32,
+ //
+ //Extended DIDL list
+ //
+ DDL9, 32,
+ DD10, 32,
+ DD11, 32,
+ DD12, 32,
+ DD13, 32,
+ DD14, 32,
+ DD15, 32,
+ //
+ //Extended Currently attached Display Device List CPD2
+ //
+ CPL9, 32,
+ CP10, 32,
+ CP11, 32,
+ CP12, 32,
+ CP13, 32,
+ CP14, 32,
+ CP15, 32,
+ //
+ // OpRegion Mailbox 2 (Software SCI Interface)
+ //
+ Offset(0x200), // SCIC
+ SCIE, 1, // SCI entry bit (1=call unserviced)
+ GEFC, 4, // Entry function code
+ GXFC, 3, // Exit result
+ GESF, 8, // Entry/exit sub-function/parameter
+ , 16, // SCIC[31:16] reserved
+ Offset(0x204), // PARM
+ PARM, 32, // PARM register (extra parameters)
+ DSLP, 32, // Driver sleep time out
+ //
+ // OpRegion Mailbox 3 (BIOS to Driver Notification)
+ // Note: Mailbox 3 is normally reserved for desktop platforms.
+ //
+ Offset(0x300),
+ ARDY, 32, // Driver readiness (power conservation)
+ ASLC, 32, // ASLE interrupt command/status
+ TCHE, 32, // Technology enabled indicator
+ ALSI, 32, // Current ALS illuminance reading
+ BCLP, 32, // Backlight brightness
+ PFIT, 32, // Panel fitting state or request
+ CBLV, 32, // Current brightness level
+ BCLM, 320, // Backlight brightness level duty cycle mapping table
+ CPFM, 32, // Current panel fitting mode
+ EPFM, 32, // Enabled panel fitting modes
+ PLUT, 592, // Optional. 74-byte Panel LUT Table
+ PFMB, 32, // Optional. PWM Frequency and Minimum Brightness
+ CCDV, 32, // Optional. Gamma, Brightness, Contrast values.
+ PCFT, 32, // Optional. Power Conservation Features
+ SROT, 32, // Supported rotation angle.
+ IUER, 32, // Optional. Intel Ultrabook Event Register.
+ FDSS, 64, // Optional. FFS Display Physical address
+ FDSP, 32, // Optional. FFS Display Size
+ STAT, 32, // State Indicator
+ RVDA, 64, // Physical address of Raw VBT data
+ RVDS, 32, // Size of Raw VBT data
+ //
+ // OpRegion Mailbox 4 (VBT)
+ //
+ Offset(0x400),
+ RVBT, 0xC000, // 6K bytes maximum VBT image
+ //
+ // OpRegion Mailbox 5 (BIOS to Driver Notification Extension)
+ //
+ Offset(0x1C00),
+ PHED, 32, // Panel Header
+ BDDC, 2048, // Panel EDID (Max 256 bytes)
+
+}
+
+//
+// Convert boot display type into a port mask.
+//
+Name (DBTB, Package()
+{
+ 0x0000, // Automatic
+ 0x0007, // Port-0 : Integrated CRT
+ 0x0038, // Port-1 : DVO-A, or Integrated LVDS
+ 0x01C0, // Port-2 : SDVO-B, or SDVO-B/C
+ 0x0E00, // Port-3 : SDVO-C
+ 0x003F, // [CRT + DVO-A / Integrated LVDS]
+ 0x01C7, // [CRT + SDVO-B] or [CRT + SDVO-B/C]
+ 0x0E07, // [CRT + SDVO-C]
+ 0x01F8, // [DVO-A / Integrated LVDS + SDVO-B]
+ 0x0E38, // [DVO-A / Integrated LVDS + SDVO-C]
+ 0x0FC0, // [SDVO-B + SDVO-C]
+ 0x0000, // Reserved
+ 0x0000, // Reserved
+ 0x0000, // Reserved
+ 0x0000, // Reserved
+ 0x0000, // Reserved
+ 0x7000, // Port-4: Integrated TV
+ 0x7007, // [Integrated TV + CRT]
+ 0x7038, // [Integrated TV + LVDS]
+ 0x71C0, // [Integrated TV + DVOB]
+ 0x7E00 // [Integrated TV + DVOC]
+})
+
+//
+// Core display clock value table.
+//
+Name (CDCT, Package()
+{
+ Package() {228, 320},
+ Package() {222, 333},
+ Package() {222, 333},
+ Package() { 0, 0},
+ Package() {222, 333},
+})
+
+//
+// Defined exit result values:
+//
+Name (SUCC, 1) // Exit result: Success
+Name (NVLD, 2) // Exit result: Invalid parameter
+Name (CRIT, 4) // Exit result: Critical failure
+Name (NCRT, 6) // Exit result: Non-critical failure
+
+/************************************************************************;
+;*
+;* Name: GSCI
+;*
+;* Description: Handles an SCI generated by the graphics driver. The
+;* PARM and SCIC input fields are parsed to determine the
+;* functionality requested by the driver. GBDA or SBCB
+;* is called based on the input data in SCIC.
+;*
+;* Usage: The method must be called in response to a GPE 06 event
+;* which will be generated by the graphics driver.
+;* Ex: Method(\_GPE._L06) {Return(\_SB.PC00.GFX0.GSCI())}
+;*
+;* Input: PARM and SCIC are indirect inputs
+;*
+;* Output: PARM and SIC are indirect outputs
+;*
+;* References: GBDA (Get BIOS Data method), SBCB (System BIOS Callback
+;* method)
+;*
+;************************************************************************/
+
+Method (GSCI, 0, Serialized)
+{
+ Include("IgfxOpGbda.asl") // "Get BIOS Data" Functions
+ Include("IgfxOpSbcb.asl") // "System BIOS CallBacks"
+
+ If (LEqual(GEFC, 4))
+ {
+ Store(GBDA(), GXFC) // Process Get BIOS Data functions
+ }
+
+ If (LEqual(GEFC, 6))
+ {
+ Store(SBCB(), GXFC) // Process BIOS Callback functions
+ }
+
+ Store(0, GEFC) // Wipe out the entry function code
+ Store(1, CPSC) // Clear CPUSCI_STS to clear the PCH TCO SCI status
+ Store(0, GSSE) // Clear the SCI generation bit in PCI space.
+ Store(0, SCIE) // Clr SCI serviced bit to signal completion
+
+ Return(Zero)
+}
+
+Include("IgfxCommon.asl") // IGD SCI mobile features
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Graphics/AcpiTables/IgfxOpSbcb.asl b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Graphics/AcpiTables/IgfxOpSbcb.asl
new file mode 100644
index 0000000000..3c5d4d9862
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Graphics/AcpiTables/IgfxOpSbcb.asl
@@ -0,0 +1,261 @@
+/** @file
+ This file contains the system BIOS call back functionality for the
+ OpRegion/Software SCI mechanism.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+Method (SBCB, 0, Serialized)
+{
+ //
+ // Supported Callbacks: Sub-function 0
+ //
+ If (LEqual(GESF, 0x0))
+ {
+ //
+ //<NOTE> An OEM may support the driver->SBIOS status callbacks, but
+ // the supported callbacks value must be modified. The code that is
+ // executed upon reception of the callbacks must be also be updated
+ // to perform the desired functionality.
+ //
+ Store(0x00000000, PARM) // No callbacks supported
+ //Store(0x000787FD, PARM) // Used for Intel test implementaion
+ Store(0x000F87DD, PARM)
+ Store(Zero, GESF) // Clear the exit parameter
+ Return(SUCC) // "Success"
+ }
+ //
+ // BIOS POST Completion: Sub-function 1
+ //
+ If (LEqual(GESF, 1))
+ {
+ Store(Zero, GESF) // Clear the exit parameter
+ Store(Zero, PARM)
+ Return(SUCC) // Not supported, but no failure
+ }
+ //
+ // Pre-Hires Set Mode: Sub-function 3
+ //
+ If (LEqual(GESF, 3))
+ {
+ Store(Zero, GESF) // Clear the exit parameter
+ Store(Zero, PARM)
+ Return(SUCC) // Not supported, but no failure
+ }
+ //
+ // Post-Hires Set Mode: Sub-function 4
+ //
+ If (LEqual(GESF, 4))
+ {
+ Store(Zero, GESF) // Clear the exit parameter
+ Store(Zero, PARM)
+ Return(SUCC) // Not supported, but no failure
+ }
+ //
+ // Display Switch: Sub-function 5
+ //
+ If (LEqual(GESF, 5))
+ {
+ Store(Zero, GESF) // Clear the exit parameter
+ Store(Zero, PARM)
+ Return(SUCC) // Not supported, but no failure
+ }
+ //
+ // Adapter Power State: Sub-function 7
+ //
+ If (LEqual(GESF, 7))
+ {
+ //
+ // Handle Low Power S0 Idle Capability if enabled
+ //
+ If(LAnd(LEqual(S0ID, 1),LLess(OSYS, 2015))) {
+ //
+ // Call GUAM to trigger CS Entry
+ // If Adapter Power State Notification = D1 (PARM[7:0]=0x01)
+ //
+ If (LEqual (And(PARM,0xFF), 0x01)) {
+ // GUAM - Global User Absent Mode Notification Method
+ \GUAM(One) // 0x01 - Power State Standby (CS Entry)
+ }
+ If (LEqual (And(PARM,0xFF), 0x00)) {
+ // GUAM - Global User Absent Mode Notification Method
+ \GUAM(0)
+ }
+ }
+ //
+ // Upon notification from driver that the Adapter Power State = D0,
+ // check if previous lid event failed. If it did, retry the lid
+ // event here.
+ //
+ If(LEqual(PARM, 0))
+ {
+ Store(CLID, Local0)
+ If(And(0x80000000,Local0))
+ {
+ And(CLID, 0x0000000F, CLID)
+ GLID(CLID)
+ }
+ }
+ Store(Zero, GESF) // Clear the exit parameter
+ Store(Zero, PARM)
+ Return(SUCC) // Not supported, but no failure
+ }
+ //
+ // Display Power State: Sub-function 8
+ //
+ If (LEqual(GESF, 8))
+ {
+ Store(Zero, GESF) // Clear the exit parameter
+ Store(Zero, PARM)
+ Return(SUCC) // Not supported, but no failure
+ }
+ //
+ // Set Boot Display: Sub-function 9
+ //
+ If (LEqual(GESF, 9))
+ {
+ //
+ //<NOTE> An OEM may elect to implement this method. In that case,
+ // the input values must be saved into non-volatile storage for
+ // parsing during the next boot. The following Sample code is Intel
+ // validated implementation.
+ //
+ And(PARM, 0xFF, IBTT) // Save the boot display to NVS
+ Store(Zero, GESF) // Clear the exit parameter
+ Store(Zero, PARM)
+ Return(SUCC) // Reserved, "Critical failure"
+ }
+ //
+ // Set Panel Details: Sub-function 10 (0Ah)
+ //
+ If (LEqual(GESF, 10))
+ {
+ //
+ //<NOTE> An OEM may elect to implement this method. In that case,
+ // the input values must be saved into non-volatile storage for
+ // parsing during the next boot. The following Sample code is Intel
+ // validated implementation.
+ // Set the panel-related NVRAM variables based the input from the driver.
+ //
+ And(PARM, 0xFF, IPSC)
+ //
+ // Change panel type if a change is requested by the driver (Change if
+ // panel type input is non-zero). Zero=No change requested.
+ //
+ If(And(ShiftRight(PARM, 8), 0xFF))
+ {
+ And(ShiftRight(PARM, 8), 0xFF, IPAT)
+ Decrement(IPAT) // 0 = no change, so fit to CMOS map
+ }
+ And(ShiftRight(PARM, 20), 0x7, IBIA)
+ Store(Zero, GESF) // Clear the exit parameter
+ Store(Zero, PARM)
+ Return(SUCC) // Success
+ }
+ //
+ // Set Internal Graphics: Sub-function 11 (0Bh)
+ //
+ If (LEqual(GESF, 11))
+ {
+ //
+ //<NOTE> An OEM may elect to implement this method. In that case,
+ // the input values must be saved into non-volatile storage for
+ // parsing during the next boot. The following Sample code is Intel
+ // validated implementation.
+ //
+ And(ShiftRight(PARM, 1), 1, IF1E) // Program the function 1 option
+ If(And(PARM, ShiftLeft(0xF, 13))) // Use fixed memory if fixed size != 0
+ {
+ //
+ // Fixed memory
+ //
+ And(ShiftRight(PARM, 13), 0xF, IDMS) // Program fixed memory size
+ }
+ Else
+ {
+ //
+ // DVMT memory
+ //
+ And(ShiftRight(PARM, 17), 0xF, IDMS) // Program fixed memory size
+ }
+ Store(Zero, GESF) // Clear the exit parameter
+ Store(Zero, PARM)
+ Return(SUCC) // Success
+ }
+ //
+ // Post-Hires to DOS FS: Sub-function 16 (10h)
+ //
+ If (LEqual(GESF, 16))
+ {
+ Store(Zero, GESF) // Clear the exit parameter
+ Store(Zero, PARM)
+ Return(SUCC) // Not supported, but no failure
+ }
+ //
+ // APM Complete: Sub-function 17 (11h)
+ //
+ If (LEqual(GESF, 17))
+ {
+ Store(ShiftLeft(LIDS, 8), PARM) // Report the lid state
+ Add(PARM, 0x100, PARM) // Adjust the lid state, 0 = Unknown
+ Store(Zero, GESF) // Clear the exit parameter
+ Return(SUCC) // Not supported, but no failure
+ }
+ //
+ // Set Spread Spectrum Clocks: Sub-function 18 (12h)
+ //
+ If (LEqual(GESF, 18))
+ {
+ //
+ //<NOTE> An OEM may elect to implement this method. In that case,
+ // the input values must be saved into non-volatile storage for
+ // parsing during the next boot. The following Sample code is Intel
+ // validated implementation.
+ //
+ If(And(PARM, 1))
+ {
+ If(LEqual(ShiftRight(PARM, 1), 1))
+ {
+ Store(1, ISSC) // Enable HW SSC, only for clock 1
+ }
+ Else
+ {
+ Store(Zero, GESF)
+ Return(CRIT) // Failure, as the SSC clock must be 1
+ }
+ }
+ Else
+ {
+ Store(0, ISSC) // Disable SSC
+ }
+ Store(Zero, GESF) // Clear the exit parameter
+ Store(Zero, PARM)
+ Return(SUCC) // Success
+ }
+ //
+ // Post VBE/PM Callback: Sub-function 19 (13h)
+ //
+ If (LEqual(GESF, 19))
+ {
+ Store(Zero, GESF) // Clear the exit parameter
+ Store(Zero, PARM)
+ Return(SUCC) // Not supported, but no failure
+ }
+ //
+ // Set PAVP Data: Sub-function 20 (14h)
+ //
+ If (LEqual(GESF, 20))
+ {
+ And(PARM, 0xF, PAVP) // Store PAVP info
+ Store(Zero, GESF) // Clear the exit parameter
+ Store(Zero, PARM)
+ Return(SUCC) // Success
+ }
+
+ //
+ // A call to a reserved "System BIOS callbacks" function was received
+ //
+ Store(Zero, GESF) // Clear the exit parameter
+ Return(SUCC) // Reserved, "Critical failure"
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Graphics/AcpiTables/IgfxSsdt.asl b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Graphics/AcpiTables/IgfxSsdt.asl
new file mode 100644
index 0000000000..99130a853d
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Graphics/AcpiTables/IgfxSsdt.asl
@@ -0,0 +1,73 @@
+/** @file
+ This file contains the Intel Graphics SSDT Table ASL code.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+DefinitionBlock (
+ "IgfxSsdt.aml",
+ "SSDT",
+ 2,
+ "INTEL ",
+ "IgfxSsdt",
+ 0x3000
+ )
+{
+ External(\_SB.PC00, DeviceObj)
+ External(\_SB.PC00.GFX0, DeviceObj)
+ External(\NDID)
+ External(\DID1)
+ External(\DID2)
+ External(\DID3)
+ External(\DID4)
+ External(\DID5)
+ External(\DID6)
+ External(\DID7)
+ External(\DID8)
+ External(\DID9)
+ External(\DIDA)
+ External(\DIDB)
+ External(\DIDC)
+ External(\DIDD)
+ External(\DIDE)
+ External(\DIDF)
+ External(\DIDX)
+ External(\DIDY)
+
+ External(\NXD1)
+ External(\NXD2)
+ External(\NXD3)
+ External(\NXD4)
+ External(\NXD5)
+ External(\NXD6)
+ External(\NXD7)
+ External(\NXD8)
+ External(\NXDY)
+
+ External(\IPTP)
+ External(\EDPV)
+ External(\NXDX)
+ External(\HGMD)
+ External(\LIDS)
+ External(\BRTL)
+ External(\NSTE)
+ External(\CSTE)
+ External(\ASLB)
+ External(\IBTT)
+ External(\IPSC)
+ External(\IPAT)
+ External(\IBIA)
+ External(\IDMS)
+ External(\HVCO)
+ External(\ISSC)
+ External(\KSV0)
+ External(\KSV1)
+ External(\IF1E)
+ External(\PAVP)
+
+ Scope (\_SB.PC00.GFX0)
+ {
+ include("Igfx.asl")
+ }
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Graphics/AcpiTables/IgfxSsdt.inf b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Graphics/AcpiTables/IgfxSsdt.inf
new file mode 100644
index 0000000000..be28157cef
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Graphics/AcpiTables/IgfxSsdt.inf
@@ -0,0 +1,23 @@
+## @file
+# Component description file for the Igfx ACPI tables
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+INF_VERSION = 0x00010005
+BASE_NAME = IgfxSsdt
+FILE_GUID = CE9CAA0E-8248-442C-9E57-50F212E2BAED
+MODULE_TYPE = USER_DEFINED
+VERSION_STRING = 1.0
+
+[Sources]
+ IgfxSsdt.asl
+
+[Packages]
+ MdePkg/MdePkg.dec
+ TigerlakeSiliconPkg/SiPkg.dec
+
+[FixedPcd]
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Graphics/IncludePrivate/Library/DxeGraphicsInitLib.h b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Graphics/IncludePrivate/Library/DxeGraphicsInitLib.h
new file mode 100644
index 0000000000..0e9f119763
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Graphics/IncludePrivate/Library/DxeGraphicsInitLib.h
@@ -0,0 +1,53 @@
+/** @file
+ Header file for DXE Graphics Init Lib.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _DXE_GRAPHICS_INIT_LIB_H_
+#define _DXE_GRAPHICS_INIT_LIB_H_
+
+#include <Uefi.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/IoLib.h>
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/Pci.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/UefiLib.h>
+#include <Library/PciSegmentLib.h>
+#include <Protocol/SaPolicy.h>
+#include <Protocol/SaNvsArea.h>
+#include <Protocol/GopComponentName2.h>
+#include <SiConfigHob.h>
+#include <Register/SaRegsHostBridge.h>
+
+/**
+ Initialize GT ACPI tables
+
+ @param[in] ImageHandle - Handle for the image of this driver
+ @param[in] SaPolicy - SA DXE Policy protocol
+
+ @retval EFI_SUCCESS - GT ACPI initialization complete
+ @retval EFI_NOT_FOUND - Dxe System Table not found.
+ @retval EFI_OUT_OF_RESOURCES - Mmio not allocated successfully.
+**/
+EFI_STATUS
+GraphicsInit (
+ IN EFI_HANDLE ImageHandle,
+ IN SA_POLICY_PROTOCOL *SaPolicy
+ );
+
+/**
+ Do Post GT PM Init Steps after VBIOS Initialization.
+
+ @retval EFI_SUCCESS Succeed.
+**/
+EFI_STATUS
+PostPmInitEndOfDxe (
+ VOID
+ );
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Graphics/IncludePrivate/Library/DxeGraphicsPolicyLib.h b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Graphics/IncludePrivate/Library/DxeGraphicsPolicyLib.h
new file mode 100644
index 0000000000..abb5dffc45
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Graphics/IncludePrivate/Library/DxeGraphicsPolicyLib.h
@@ -0,0 +1,71 @@
+/** @file
+ Header file for the DXE Graphics Policy Init library.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _DXE_GRAPHICS_POLICY_LIB_H_
+#define _DXE_GRAPHICS_POLICY_LIB_H_
+
+#include <Uefi.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Protocol/SaPolicy.h>
+#include <ConfigBlock.h>
+#include <GraphicsConfig.h>
+#include <Library/SiConfigBlockLib.h>
+
+#define WORD_FIELD_VALID_BIT BIT15
+
+extern EFI_GUID gGraphicsDxeConfigGuid;
+
+/**
+ This function prints the Graphics DXE phase policy.
+
+ @param[in] SaPolicy - SA DXE Policy protocol
+**/
+VOID
+GraphicsDxePolicyPrint (
+ IN SA_POLICY_PROTOCOL *SaPolicy
+ );
+
+/**
+ This function Load default Graphics DXE policy.
+
+ @param[in] ConfigBlockPointer The pointer to add Graphics config block
+**/
+VOID
+LoadIgdDxeDefault (
+ IN VOID *ConfigBlockPointer
+ );
+
+
+/**
+ Get DXE Graphics config block table total size.
+
+ @retval Size of DXE Graphics config block table
+**/
+UINT16
+EFIAPI
+GraphicsGetConfigBlockTotalSizeDxe (
+ VOID
+ );
+
+/**
+ GraphicsAddConfigBlocksDxe add all DXE Graphics config block.
+
+ @param[in] ConfigBlockTableAddress The pointer to add SA config blocks
+
+ @retval EFI_SUCCESS The policy default is initialized.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create buffer
+**/
+EFI_STATUS
+EFIAPI
+GraphicsAddConfigBlocksDxe (
+ IN VOID *ConfigBlockTableAddress
+ );
+
+#endif // _DXE_GRAPHICs_POLICY_LIBRARY_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Graphics/IncludePrivate/Library/DxeIgdOpRegionInitLib.h b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Graphics/IncludePrivate/Library/DxeIgdOpRegionInitLib.h
new file mode 100644
index 0000000000..683893f940
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Graphics/IncludePrivate/Library/DxeIgdOpRegionInitLib.h
@@ -0,0 +1,177 @@
+/** @file
+ This is part of the implementation of an Intel Graphics drivers OpRegion /
+ Software SCI interface between system BIOS, ASL code, and Graphics drivers.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _DXE_IGD_OPREGION_INIT_LIB_H_
+#define _DXE_IGD_OPREGION_INIT_LIB_H_
+
+///
+/// Statements that include other header files.
+///
+#include <Uefi.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <IndustryStandard/Pci.h>
+#include <Library/ConfigBlockLib.h>
+#include <Library/PciSegmentLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/UefiLib.h>
+#include <Library/S3BootScriptLib.h>
+#include <Register/IgdRegs.h>
+#include <SiConfigHob.h>
+#include <Register/SaRegsHostBridge.h>
+///
+/// Driver Consumed Protocol Prototypes
+///
+#include <Protocol/PciIo.h>
+#include <Protocol/PciRootBridgeIo.h>
+#include <Protocol/SaPolicy.h>
+#include <Protocol/SaNvsArea.h>
+///
+/// Driver Produced Protocol Prototypes
+///
+#include <Protocol/IgdOpRegion.h>
+
+#pragma pack(push, 1)
+///
+///
+/// OpRegion (Miscellaneous) defines.
+///
+/// OpRegion Header defines.
+///
+typedef UINT16 STRING_REF;
+#define HEADER_SIGNATURE "IntelGraphicsMem"
+#define HEADER_SIZE 0x2000
+#define HEADER_OPREGION_REV 0x00
+#define HEADER_MBOX_SUPPORT (HD_MBOX5 + HD_MBOX4 + HD_MBOX3 + HD_MBOX2 + HD_MBOX1)
+#define HD_MBOX1 BIT0
+#define HD_MBOX2 BIT1
+#define HD_MBOX3 BIT2
+#define HD_MBOX4 BIT3
+#define HD_MBOX5 BIT4
+#define SVER_SIZE 32
+
+///
+/// OpRegion Mailbox 1 EQUates.
+///
+/// OpRegion Mailbox 3 EQUates.
+///
+#define ALS_ENABLE BIT0
+#define BACKLIGHT_BRIGHTNESS 0xFF
+#define FIELD_VALID_BIT BIT31
+#define PFIT_ENABLE BIT2
+#define PFIT_OPRN_AUTO 0x00000000
+#define PFIT_OPRN_SCALING 0x00000007
+#define PFIT_OPRN_OFF 0x00000000
+#define PFIT_SETUP_AUTO 0
+#define PFIT_SETUP_SCALING 1
+#define PFIT_SETUP_OFF 2
+#define INIT_BRIGHT_LEVEL 0x64
+#define PFIT_STRETCH 6
+
+///
+/// Video BIOS / VBT defines
+///
+#define OPTION_ROM_SIGNATURE 0xAA55
+#define VBIOS_LOCATION_PRIMARY 0xC0000
+
+#define VBT_SIGNATURE SIGNATURE_32 ('$', 'V', 'B', 'T')
+///
+/// Typedef stuctures
+///
+typedef struct {
+ UINT16 Signature; /// 0xAA55
+ UINT8 Size512;
+ UINT8 Reserved[21];
+ UINT16 PcirOffset;
+ UINT16 VbtOffset;
+} INTEL_VBIOS_OPTION_ROM_HEADER;
+
+typedef struct {
+ UINT32 Signature; /// "PCIR"
+ UINT16 VendorId; /// 0x8086
+ UINT16 DeviceId;
+ UINT16 Reserved0;
+ UINT16 Length;
+ UINT8 Revision;
+ UINT8 ClassCode[3];
+ UINT16 ImageLength;
+ UINT16 CodeRevision;
+ UINT8 CodeType;
+ UINT8 Indicator;
+ UINT16 Reserved1;
+} INTEL_VBIOS_PCIR_STRUCTURE;
+
+typedef struct {
+ UINT8 HeaderSignature[20];
+ UINT16 HeaderVersion;
+ UINT16 HeaderSize;
+ UINT16 HeaderVbtSize;
+ UINT8 HeaderVbtCheckSum;
+ UINT8 HeaderReserved;
+ UINT32 HeaderOffsetVbtDataBlock;
+ UINT32 HeaderOffsetAim1;
+ UINT32 HeaderOffsetAim2;
+ UINT32 HeaderOffsetAim3;
+ UINT32 HeaderOffsetAim4;
+ UINT8 DataHeaderSignature[16];
+ UINT16 DataHeaderVersion;
+ UINT16 DataHeaderSize;
+ UINT16 DataHeaderDataBlockSize;
+ UINT8 CoreBlockId;
+ UINT16 CoreBlockSize;
+ UINT16 CoreBlockBiosSize;
+ UINT8 CoreBlockBiosType;
+ UINT8 CoreBlockReleaseStatus;
+ UINT8 CoreBlockHWSupported;
+ UINT8 CoreBlockIntegratedHW;
+ UINT8 CoreBlockBiosBuild[4];
+ UINT8 CoreBlockBiosSignOn[155];
+} VBIOS_VBT_STRUCTURE;
+#pragma pack(pop)
+///
+/// Driver Private Function definitions
+///
+
+/**
+ Graphics OpRegion / Software SCI driver installation function.
+
+ @retval EFI_SUCCESS - The driver installed without error.
+ @retval EFI_ABORTED - The driver encountered an error and could not complete
+ installation of the ACPI tables.
+**/
+EFI_STATUS
+IgdOpRegionInit (
+ VOID
+ );
+
+/**
+ Get Intel video BIOS VBT information (i.e. Pointer to VBT and VBT size).
+ The VBT (Video BIOS Table) is a block of customizable data that is built
+ within the video BIOS and edited by customers.
+
+ @retval EFI_SUCCESS - Video BIOS VBT information returned.
+ @exception EFI_UNSUPPORTED - Could not find VBT information (*VBiosVbtPtr = NULL).
+**/
+EFI_STATUS
+GetVBiosVbtEndOfDxe (
+ VOID
+ );
+
+/**
+ Update Graphics OpRegion after PCI enumeration.
+
+ @retval EFI_SUCCESS - The function completed successfully.
+**/
+EFI_STATUS
+UpdateIgdOpRegionEndOfDxe (
+ VOID
+ );
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Graphics/LibraryPrivate/DxeGraphicsInitLib/DxeGraphicsInitLib.c b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Graphics/LibraryPrivate/DxeGraphicsInitLib/DxeGraphicsInitLib.c
new file mode 100644
index 0000000000..8769f34021
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Graphics/LibraryPrivate/DxeGraphicsInitLib/DxeGraphicsInitLib.c
@@ -0,0 +1,135 @@
+/** @file
+ DXE Library for Initializing SystemAgent Graphics ACPI table initialization.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include <Library/DxeGraphicsInitLib.h>
+
+
+typedef union {
+ struct {
+ UINT32 Low;
+ UINT32 High;
+ } Data32;
+ UINT64 Data;
+} UINT64_STRUCT;
+
+GLOBAL_REMOVE_IF_UNREFERENCED UINT64_STRUCT mMchBarBase;
+GLOBAL_REMOVE_IF_UNREFERENCED GOP_COMPONENT_NAME2_PROTOCOL *GopComponentName2Protocol = NULL;
+
+/**
+ Do Post GT PM Init Steps after VBIOS Initialization.
+
+ @retval EFI_SUCCESS Succeed.
+**/
+EFI_STATUS
+PostPmInitEndOfDxe (
+ VOID
+ )
+{
+ CHAR16 *DriverVersion;
+ UINTN Index;
+ EFI_STATUS Status;
+ GRAPHICS_DXE_CONFIG *GraphicsDxeConfig;
+ SA_POLICY_PROTOCOL *SaPolicy;
+
+ ///
+ /// Get the platform setup policy.
+ ///
+ DriverVersion = NULL;
+ Status = gBS->LocateProtocol (&gSaPolicyProtocolGuid, NULL, (VOID **) &SaPolicy);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = GetConfigBlock ((VOID *) SaPolicy, &gGraphicsDxeConfigGuid, (VOID *)&GraphicsDxeConfig);
+ ASSERT_EFI_ERROR (Status);
+
+
+ Status = gBS->LocateProtocol (&gGopComponentName2ProtocolGuid, NULL, (VOID **)&GopComponentName2Protocol);
+ if (!EFI_ERROR (Status)) {
+ Status = GopComponentName2Protocol->GetDriverVersion (
+ GopComponentName2Protocol,
+ "en-US",
+ &DriverVersion
+ );
+ if (!EFI_ERROR (Status)) {
+ for (Index = 0; (DriverVersion[Index] != '\0'); Index++) {
+ }
+ Index = (Index+1)*2;
+ CopyMem (GraphicsDxeConfig->GopVersion, DriverVersion, Index);
+ }
+ }
+
+ ///
+ /// Return final status
+ ///
+ return EFI_SUCCESS;
+}
+
+
+/**
+Initialize GT ACPI tables
+
+ @param[in] ImageHandle - Handle for the image of this driver
+ @param[in] SaPolicy - SA DXE Policy protocol
+
+ @retval EFI_SUCCESS - GT ACPI initialization complete
+ @retval EFI_NOT_FOUND - Dxe System Table not found.
+ @retval EFI_OUT_OF_RESOURCES - Mmio not allocated successfully.
+**/
+EFI_STATUS
+GraphicsInit (
+ IN EFI_HANDLE ImageHandle,
+ IN SA_POLICY_PROTOCOL *SaPolicy
+ )
+{
+ EFI_STATUS Status;
+ GRAPHICS_DXE_CONFIG *GraphicsDxeConfig;
+ SYSTEM_AGENT_NVS_AREA_PROTOCOL *SaNvsAreaProtocol;
+
+ Status = EFI_SUCCESS;
+ mMchBarBase.Data32.High = PciSegmentRead32 (PCI_SEGMENT_LIB_ADDRESS (SA_SEG_NUM, SA_MC_BUS, 0, 0, R_SA_MCHBAR + 4));
+ mMchBarBase.Data32.Low = PciSegmentRead32 (PCI_SEGMENT_LIB_ADDRESS (SA_SEG_NUM, SA_MC_BUS, 0, 0, R_SA_MCHBAR));
+ mMchBarBase.Data &= (UINT64) ~BIT0;
+
+ Status = GetConfigBlock ((VOID *) SaPolicy, &gGraphicsDxeConfigGuid, (VOID *)&GraphicsDxeConfig);
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Locate the SA Global NVS Protocol.
+ ///
+ Status = gBS->LocateProtocol (&gSaNvsAreaProtocolGuid, NULL, (VOID **) &SaNvsAreaProtocol);
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Update IGD SA Global NVS
+ ///
+ DEBUG ((DEBUG_INFO, " Update Igd SA Global NVS Area.\n"));
+
+ SaNvsAreaProtocol->Area->AlsEnable = GraphicsDxeConfig->AlsEnable;
+ ///
+ /// Initialize IGD state by checking if IGD Device 2 Function 0 is enabled in the chipset
+ ///
+ if (PciSegmentRead16 (PCI_SEGMENT_LIB_ADDRESS (SA_SEG_NUM, SA_MC_BUS, 0, 0, R_SA_DEVEN)) & B_SA_DEVEN_D2EN_MASK) {
+ SaNvsAreaProtocol->Area->IgdState = 1;
+ } else {
+ SaNvsAreaProtocol->Area->IgdState = 0;
+ }
+
+ SaNvsAreaProtocol->Area->BrightnessPercentage = 100;
+ SaNvsAreaProtocol->Area->IgdBootType = GraphicsDxeConfig->IgdBootType;
+ SaNvsAreaProtocol->Area->IgdPanelType = GraphicsDxeConfig->IgdPanelType;
+ SaNvsAreaProtocol->Area->IgdPanelScaling = GraphicsDxeConfig->IgdPanelScaling;
+ ///
+ /// Get SFF power mode platform data for the IGD driver. Flip the bit (bitwise xor)
+ /// since Setup value is opposite of NVS and IGD OpRegion value.
+ ///
+ SaNvsAreaProtocol->Area->IgdDvmtMemSize = GraphicsDxeConfig->IgdDvmtMemSize;
+ SaNvsAreaProtocol->Area->IgdFunc1Enable = 0;
+ SaNvsAreaProtocol->Area->IgdHpllVco = MmioRead8 (mMchBarBase.Data + 0xC0F) & 0x07;
+ SaNvsAreaProtocol->Area->IgdSciSmiMode = 0;
+ SaNvsAreaProtocol->Area->GfxTurboIMON = GraphicsDxeConfig->GfxTurboIMON;
+ SaNvsAreaProtocol->Area->EdpValid = 0;
+
+ return EFI_SUCCESS;
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Graphics/LibraryPrivate/DxeGraphicsInitLib/DxeGraphicsInitLib.inf b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Graphics/LibraryPrivate/DxeGraphicsInitLib/DxeGraphicsInitLib.inf
new file mode 100644
index 0000000000..78c115eb3c
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Graphics/LibraryPrivate/DxeGraphicsInitLib/DxeGraphicsInitLib.inf
@@ -0,0 +1,45 @@
+## @file
+# Component description file for the Dxe Graphics Init library.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = DxeGraphicsInitLib
+FILE_GUID = 2E889319-7361-4F6C-B181-EBD7AEF1DE6A
+VERSION_STRING = 1.0
+MODULE_TYPE = DXE_DRIVER
+LIBRARY_CLASS = DxeGraphicsInitLib
+
+[LibraryClasses]
+UefiLib
+UefiRuntimeServicesTableLib
+UefiBootServicesTableLib
+DebugLib
+PostCodeLib
+ConfigBlockLib
+IoLib
+PciSegmentLib
+BaseMemoryLib
+MemoryAllocationLib
+MmPciLib
+
+[Packages]
+MdePkg/MdePkg.dec
+TigerlakeSiliconPkg/SiPkg.dec
+
+[Sources]
+DxeGraphicsInitLib.c
+
+[Guids]
+gGraphicsDxeConfigGuid ## CONSUMES
+
+[Pcd]
+
+[Protocols]
+gSaPolicyProtocolGuid ## CONSUMES
+gSaNvsAreaProtocolGuid ## CONSUMES
+gGopComponentName2ProtocolGuid ## CONSUMES
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Graphics/LibraryPrivate/DxeGraphicsPolicyLib/DxeGraphicsPolicyLib.c b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Graphics/LibraryPrivate/DxeGraphicsPolicyLib/DxeGraphicsPolicyLib.c
new file mode 100644
index 0000000000..fd284d5f42
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Graphics/LibraryPrivate/DxeGraphicsPolicyLib/DxeGraphicsPolicyLib.c
@@ -0,0 +1,118 @@
+/** @file
+ This file provide services for DXE phase Graphics policy default initialization.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/DxeGraphicsPolicyLib.h>
+
+/**
+ This function prints the Graphics DXE phase policy.
+
+ @param[in] SaPolicy - SA DXE Policy protocol
+**/
+VOID
+GraphicsDxePolicyPrint (
+ IN SA_POLICY_PROTOCOL *SaPolicy
+ )
+{
+ EFI_STATUS Status;
+ GRAPHICS_DXE_CONFIG *GraphicsDxeConfig;
+
+ //
+ // Get requisite IP Config Blocks which needs to be used here
+ //
+ Status = GetConfigBlock ((VOID *) SaPolicy, &gGraphicsDxeConfigGuid, (VOID *)&GraphicsDxeConfig);
+ ASSERT_EFI_ERROR (Status);
+
+
+ DEBUG_CODE_BEGIN ();
+ DEBUG ((DEBUG_INFO, "\n------------------------ Graphics Policy (DXE) print BEGIN -----------------\n"));
+ DEBUG ((DEBUG_INFO, " Revision : %d\n", GraphicsDxeConfig->Header.Revision));
+ ASSERT (GraphicsDxeConfig->Header.Revision == GRAPHICS_DXE_CONFIG_REVISION);
+ DEBUG ((DEBUG_INFO, "\n------------------------ Graphics Policy (DXE) print END -----------------\n"));
+ DEBUG_CODE_END ();
+
+ return;
+}
+
+
+/**
+ This function Load default Graphics DXE policy.
+
+ @param[in] ConfigBlockPointer The pointer to add Graphics config block
+**/
+VOID
+LoadIgdDxeDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ GRAPHICS_DXE_CONFIG *GraphicsDxeConfig;
+
+ GraphicsDxeConfig = ConfigBlockPointer;
+ DEBUG ((DEBUG_INFO, "GraphicsDxeConfig->Header.GuidHob.Name = %g\n", &GraphicsDxeConfig->Header.GuidHob.Name));
+ DEBUG ((DEBUG_INFO, "GraphicsDxeConfig->Header.GuidHob.Header.HobLength = 0x%x\n", GraphicsDxeConfig->Header.GuidHob.Header.HobLength));
+ ///
+ /// Initialize the Graphics configuration
+ ///
+ GraphicsDxeConfig->PlatformConfig = 1;
+ GraphicsDxeConfig->AlsEnable = 2;
+ GraphicsDxeConfig->BacklightControlSupport = 2;
+ GraphicsDxeConfig->IgdBlcConfig = 2;
+ GraphicsDxeConfig->IgdDvmtMemSize = 1;
+ GraphicsDxeConfig->GfxTurboIMON = 31;
+ ///
+ /// <EXAMPLE> Create a static Backlight Brightness Level Duty cycle Mapping Table
+ /// Possible 20 entries (example used 11), each 16 bits as follows:
+ /// [15] = Field Valid bit, [14:08] = Level in Percentage (0-64h), [07:00] = Desired duty cycle (0 - FFh).
+ ///
+ GraphicsDxeConfig->BCLM[0] = (0x0000 + WORD_FIELD_VALID_BIT); ///< 0%
+ GraphicsDxeConfig->BCLM[1] = (0x0A19 + WORD_FIELD_VALID_BIT); ///< 10%
+ GraphicsDxeConfig->BCLM[2] = (0x1433 + WORD_FIELD_VALID_BIT); ///< 20%
+ GraphicsDxeConfig->BCLM[3] = (0x1E4C + WORD_FIELD_VALID_BIT); ///< 30%
+ GraphicsDxeConfig->BCLM[4] = (0x2866 + WORD_FIELD_VALID_BIT); ///< 40%
+ GraphicsDxeConfig->BCLM[5] = (0x327F + WORD_FIELD_VALID_BIT); ///< 50%
+ GraphicsDxeConfig->BCLM[6] = (0x3C99 + WORD_FIELD_VALID_BIT); ///< 60%
+ GraphicsDxeConfig->BCLM[7] = (0x46B2 + WORD_FIELD_VALID_BIT); ///< 70%
+ GraphicsDxeConfig->BCLM[8] = (0x50CC + WORD_FIELD_VALID_BIT); ///< 80%
+ GraphicsDxeConfig->BCLM[9] = (0x5AE5 + WORD_FIELD_VALID_BIT); ///< 90%
+ GraphicsDxeConfig->BCLM[10] = (0x64FF + WORD_FIELD_VALID_BIT); ///< 100%
+}
+
+static COMPONENT_BLOCK_ENTRY mGraphicsDxeIpBlocks = {
+ &gGraphicsDxeConfigGuid, sizeof (GRAPHICS_DXE_CONFIG), GRAPHICS_DXE_CONFIG_REVISION, LoadIgdDxeDefault};
+
+
+/**
+ Get DXE Graphics config block table total size.
+
+ @retval Size of DXE Graphics config block table
+**/
+UINT16
+EFIAPI
+GraphicsGetConfigBlockTotalSizeDxe (
+ VOID
+ )
+{
+ return mGraphicsDxeIpBlocks.Size;
+}
+
+/**
+ GraphicsAddConfigBlocksDxe add all DXE Graphics config block.
+
+ @param[in] ConfigBlockTableAddress The pointer to add SA config blocks
+
+ @retval EFI_SUCCESS The policy default is initialized.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create buffer
+**/
+EFI_STATUS
+EFIAPI
+GraphicsAddConfigBlocksDxe (
+ IN VOID *ConfigBlockTableAddress
+ )
+{
+ EFI_STATUS Status;
+ Status = AddComponentConfigBlocks (ConfigBlockTableAddress, &mGraphicsDxeIpBlocks, 1);
+ return Status;
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Graphics/LibraryPrivate/DxeGraphicsPolicyLib/DxeGraphicsPolicyLib.inf b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Graphics/LibraryPrivate/DxeGraphicsPolicyLib/DxeGraphicsPolicyLib.inf
new file mode 100644
index 0000000000..d3ac3c24a1
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Graphics/LibraryPrivate/DxeGraphicsPolicyLib/DxeGraphicsPolicyLib.inf
@@ -0,0 +1,37 @@
+## @file
+# Component description file for the DXE Graphics Policy Init library.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = DxeGraphicsPolicyLib
+FILE_GUID = C6190599-287E-40F9-9B46-EE112A322EBF
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = DxeGraphicsPolicyLib
+
+[LibraryClasses]
+BaseMemoryLib
+UefiRuntimeServicesTableLib
+UefiBootServicesTableLib
+DebugLib
+PostCodeLib
+ConfigBlockLib
+HobLib
+SiConfigBlockLib
+
+[Packages]
+MdePkg/MdePkg.dec
+TigerlakeSiliconPkg/SiPkg.dec
+
+[Sources]
+DxeGraphicsPolicyLib.c
+
+[Guids]
+gGraphicsDxeConfigGuid
+
+[Pcd]
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Graphics/LibraryPrivate/DxeIgdOpRegionInitLib/DxeIgdOpRegionInit.c b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Graphics/LibraryPrivate/DxeIgdOpRegionInitLib/DxeIgdOpRegionInit.c
new file mode 100644
index 0000000000..0e12f62f4e
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Graphics/LibraryPrivate/DxeIgdOpRegionInitLib/DxeIgdOpRegionInit.c
@@ -0,0 +1,541 @@
+/** @file
+ This is part of the implementation of an Intel Graphics drivers OpRegion /
+ Software SCI interface between system BIOS, ASL code, and Graphics drivers.
+ The code in this file will load the driver and initialize the interface
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/DxeIgdOpRegionInitLib.h>
+
+#define HEADER_OPREGION_VER_GEN9 0x0200
+#define HEADER_OPREGION_VER_GEN12 0x0201
+
+
+GLOBAL_REMOVE_IF_UNREFERENCED IGD_OPREGION_PROTOCOL mIgdOpRegion;
+
+/**
+ Get VBT data using SaPlaformPolicy
+
+ @param[out] VbtFileBuffer Pointer to VBT data buffer.
+
+ @retval EFI_SUCCESS VBT data was returned.
+ @retval EFI_NOT_FOUND VBT data not found.
+ @exception EFI_UNSUPPORTED Invalid signature in VBT data.
+**/
+EFI_STATUS
+GetIntegratedIntelVbtPtr (
+ OUT VBIOS_VBT_STRUCTURE **VbtFileBuffer
+ )
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS VbtAddress;
+ UINT32 Size;
+ GRAPHICS_DXE_CONFIG *GraphicsDxeConfig;
+ SA_POLICY_PROTOCOL *SaPolicy;
+
+ ///
+ /// Get the SA policy.
+ ///
+ Status = gBS->LocateProtocol (
+ &gSaPolicyProtocolGuid,
+ NULL,
+ (VOID **) &SaPolicy
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = GetConfigBlock ((VOID *) SaPolicy, &gGraphicsDxeConfigGuid, (VOID *)&GraphicsDxeConfig);
+ ASSERT_EFI_ERROR (Status);
+
+ VbtAddress = GraphicsDxeConfig->VbtAddress;
+ Size = GraphicsDxeConfig->Size;
+
+ if (VbtAddress == 0x00000000) {
+ return EFI_NOT_FOUND;
+ } else {
+ ///
+ /// Check VBT signature
+ ///
+ *VbtFileBuffer = NULL;
+ *VbtFileBuffer = (VBIOS_VBT_STRUCTURE *) (UINTN) VbtAddress;
+ if ((*((UINT32 *) ((*VbtFileBuffer)->HeaderSignature))) != VBT_SIGNATURE) {
+ FreePool (*VbtFileBuffer);
+ *VbtFileBuffer = NULL;
+ return EFI_UNSUPPORTED;
+ }
+ }
+ if (Size == 0) {
+ return EFI_NOT_FOUND;
+ } else {
+ ///
+ /// Check VBT size
+ ///
+ if ((*VbtFileBuffer)->HeaderVbtSize > Size) {
+ (*VbtFileBuffer)->HeaderVbtSize = (UINT16) Size;
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Get a pointer to an uncompressed image of the Intel video BIOS.
+
+ @Note: This function would only be called if the video BIOS at 0xC000 is
+ missing or not an Intel video BIOS. It may not be an Intel video BIOS
+ if the Intel graphic contoller is considered a secondary adapter.
+
+ @param[out] VBiosImage - Pointer to an uncompressed Intel video BIOS. This pointer must
+ be set to NULL if an uncompressed image of the Intel Video BIOS
+ is not obtainable.
+
+ @retval EFI_SUCCESS - VBiosPtr is updated.
+ @exception EFI_UNSUPPORTED - No Intel video BIOS found.
+**/
+EFI_STATUS
+GetIntegratedIntelVBiosPtr (
+ OUT INTEL_VBIOS_OPTION_ROM_HEADER **VBiosImage
+ )
+{
+ EFI_HANDLE *HandleBuffer;
+ UINTN HandleCount;
+ UINTN Index;
+ INTEL_VBIOS_PCIR_STRUCTURE *PcirBlockPtr;
+ EFI_STATUS Status;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ INTEL_VBIOS_OPTION_ROM_HEADER *VBiosRomImage;
+
+ ///
+ /// Set as if an umcompressed Intel video BIOS image was not obtainable.
+ ///
+ VBiosRomImage = NULL;
+
+ ///
+ /// Get all PCI IO protocols
+ ///
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiPciIoProtocolGuid,
+ NULL,
+ &HandleCount,
+ &HandleBuffer
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Find the video BIOS by checking each PCI IO handle for an Intel video
+ /// BIOS OPROM.
+ ///
+ for (Index = 0; Index < HandleCount; Index++) {
+ Status = gBS->HandleProtocol (
+ HandleBuffer[Index],
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ VBiosRomImage = PciIo->RomImage;
+
+ ///
+ /// If this PCI device doesn't have a ROM image, skip to the next device.
+ ///
+ if (!VBiosRomImage) {
+ continue;
+ }
+ ///
+ /// Get pointer to PCIR structure
+ ///
+ PcirBlockPtr = (INTEL_VBIOS_PCIR_STRUCTURE *) ((UINT8 *) VBiosRomImage + VBiosRomImage->PcirOffset);
+
+ ///
+ /// Check if we have an Intel video BIOS OPROM.
+ ///
+ if ((VBiosRomImage->Signature == OPTION_ROM_SIGNATURE) &&
+ (PcirBlockPtr->VendorId == V_SA_MC_VID) &&
+ (PcirBlockPtr->ClassCode[0] == 0x00) &&
+ (PcirBlockPtr->ClassCode[1] == 0x00) &&
+ (PcirBlockPtr->ClassCode[2] == 0x03)
+ ) {
+ ///
+ /// Found Intel video BIOS.
+ ///
+ *VBiosImage = VBiosRomImage;
+ return EFI_SUCCESS;
+ }
+ }
+ ///
+ /// No Intel video BIOS found.
+ ///
+ ///
+ /// Free any allocated buffers
+ ///
+ FreePool (HandleBuffer);
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Get Intel video BIOS VBT information (i.e. Pointer to VBT and VBT size).
+ The VBT (Video BIOS Table) is a block of customizable data that is built
+ within the video BIOS and edited by customers.
+
+ @retval EFI_SUCCESS - Video BIOS VBT information returned.
+ @exception EFI_UNSUPPORTED - Could not find VBT information (*VBiosVbtPtr = NULL).
+**/
+EFI_STATUS
+GetVBiosVbtEndOfDxe (
+ VOID
+ )
+{
+ INTEL_VBIOS_OPTION_ROM_HEADER *VBiosPtr;
+ VBIOS_VBT_STRUCTURE *VBiosVbtPtr;
+ EFI_STATUS Status;
+ VBIOS_VBT_STRUCTURE *VbtFileBuffer;
+ GRAPHICS_DXE_CONFIG *GraphicsDxeConfig;
+ SA_POLICY_PROTOCOL *SaPolicy;
+
+ VbtFileBuffer = NULL;
+
+ ///
+ /// Get the SA policy.
+ ///
+ Status = gBS->LocateProtocol (
+ &gSaPolicyProtocolGuid,
+ NULL,
+ (VOID **) &SaPolicy
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = GetConfigBlock ((VOID *) SaPolicy, &gGraphicsDxeConfigGuid, (VOID *)&GraphicsDxeConfig);
+ ASSERT_EFI_ERROR (Status);
+
+ VBiosPtr = NULL;
+ ///
+ /// Try to get VBT from FV.
+ ///
+ GetIntegratedIntelVbtPtr (&VbtFileBuffer);
+ if (VbtFileBuffer != NULL) {
+ ///
+ /// Video BIOS not found, use VBT from SaPolicy
+ ///
+ DEBUG ((DEBUG_INFO, "VBT data found\n"));
+ CopyMem (mIgdOpRegion.OpRegion->Header.DVER, GraphicsDxeConfig->GopVersion, sizeof(GraphicsDxeConfig->GopVersion));
+ mIgdOpRegion.OpRegion->MBox3.RVDA = 0;
+ mIgdOpRegion.OpRegion->MBox3.RVDS = 0;
+ if ((VbtFileBuffer->HeaderVbtSize > 0x1800)) { // VBT > 6KB
+ DEBUG ((DEBUG_INFO, "Extended VBT supported\n"));
+ mIgdOpRegion.OpRegion->MBox3.RVDA = sizeof (IGD_OPREGION_STRUCTURE); // Relative offset at the end of Op-region.
+ mIgdOpRegion.OpRegion->MBox3.RVDS = ((VbtFileBuffer->HeaderVbtSize) & (UINT32)~(0x1FF)) + 0x200; // Aligned VBT Data Size to 512 bytes.
+ CopyMem ((CHAR8 *)(UINTN)(mIgdOpRegion.OpRegion) + sizeof (IGD_OPREGION_STRUCTURE), VbtFileBuffer, mIgdOpRegion.OpRegion->MBox3.RVDS);
+ } else {
+ CopyMem (mIgdOpRegion.OpRegion->MBox4.RVBT, VbtFileBuffer, VbtFileBuffer->HeaderVbtSize);
+ }
+ return EFI_SUCCESS;
+ }
+
+ if (VBiosPtr == NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ DEBUG ((DEBUG_INFO, "VBIOS found at 0x%X\n", VBiosPtr));
+ VBiosVbtPtr = (VBIOS_VBT_STRUCTURE *) ((UINT8 *) VBiosPtr + VBiosPtr->VbtOffset);
+
+ if ((*((UINT32 *) (VBiosVbtPtr->HeaderSignature))) != VBT_SIGNATURE) {
+ return EFI_UNSUPPORTED;
+ }
+
+ ///
+ /// Initialize Video BIOS version with its build number.
+ ///
+ mIgdOpRegion.OpRegion->Header.VVER[0] = VBiosVbtPtr->CoreBlockBiosBuild[0];
+ mIgdOpRegion.OpRegion->Header.VVER[1] = VBiosVbtPtr->CoreBlockBiosBuild[1];
+ mIgdOpRegion.OpRegion->Header.VVER[2] = VBiosVbtPtr->CoreBlockBiosBuild[2];
+ mIgdOpRegion.OpRegion->Header.VVER[3] = VBiosVbtPtr->CoreBlockBiosBuild[3];
+ CopyMem (mIgdOpRegion.OpRegion->MBox4.RVBT, VBiosVbtPtr, VBiosVbtPtr->HeaderVbtSize);
+
+ ///
+ /// Return final status
+ ///
+ return EFI_SUCCESS;
+}
+
+/**
+ Graphics OpRegion / Software SCI driver installation function.
+
+ @param[in] void - None
+ @retval EFI_SUCCESS - The driver installed without error.
+ @retval EFI_ABORTED - The driver encountered an error and could not complete
+ installation of the ACPI tables.
+**/
+EFI_STATUS
+IgdOpRegionInit (
+ VOID
+ )
+{
+ EFI_HANDLE Handle;
+ EFI_STATUS Status;
+ UINT32 DwordData;
+ UINT64 IgdBaseAddress;
+ SA_POLICY_PROTOCOL *SaPolicy;
+ GRAPHICS_DXE_CONFIG *GraphicsDxeConfig;
+ UINT8 Index;
+ SYSTEM_AGENT_NVS_AREA_PROTOCOL *SaNvsAreaProtocol;
+ VBIOS_VBT_STRUCTURE *VbtFileBuffer;
+ UINT16 ExtendedVbtSize;
+
+ ///
+ /// Get the SA policy.
+ ///
+ Status = gBS->LocateProtocol (&gSaPolicyProtocolGuid, NULL, (VOID **)&SaPolicy);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = GetConfigBlock ((VOID *) SaPolicy, &gGraphicsDxeConfigGuid, (VOID *)&GraphicsDxeConfig);
+ ASSERT_EFI_ERROR (Status);
+
+ VbtFileBuffer = NULL;
+ ExtendedVbtSize = 0;
+
+ GetIntegratedIntelVbtPtr (&VbtFileBuffer);
+ ///
+ /// Locate the SA Global NVS Protocol.
+ ///
+ Status = gBS->LocateProtocol (
+ &gSaNvsAreaProtocolGuid,
+ NULL,
+ (VOID **) &SaNvsAreaProtocol
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Check if VBT size is >6KB then allocate an ACPI NVS memory buffer as the IGD OpRegion + extended VBT size,
+ /// zero initialize it, and set the IGD OpRegion pointer in the Global NVS area structure.
+ ///
+ if ((VbtFileBuffer != NULL) && (VbtFileBuffer->HeaderVbtSize > 0x1800)) {
+ ExtendedVbtSize = ((VbtFileBuffer->HeaderVbtSize) & (UINT32)~(0x1FF)) + 0x200;
+ }
+
+ Status = (gBS->AllocatePool) (EfiACPIMemoryNVS, sizeof (IGD_OPREGION_STRUCTURE) + ExtendedVbtSize, (VOID **) &mIgdOpRegion.OpRegion);
+ ASSERT_EFI_ERROR (Status);
+ SetMem (mIgdOpRegion.OpRegion, sizeof (IGD_OPREGION_STRUCTURE) + ExtendedVbtSize, 0);
+ SaNvsAreaProtocol->Area->IgdOpRegionAddress = (UINT32) (UINTN) (mIgdOpRegion.OpRegion);
+
+ ///
+ /// If IGD is disabled return
+ ///
+ IgdBaseAddress = PCI_SEGMENT_LIB_ADDRESS (SA_SEG_NUM, IGD_BUS_NUM, IGD_DEV_NUM, IGD_FUN_NUM, 0);
+ if (PciSegmentRead32 (IgdBaseAddress + 0) == 0xFFFFFFFF) {
+ return EFI_SUCCESS;
+ }
+ ///
+ /// Initialize OpRegion Header
+ ///
+ CopyMem (mIgdOpRegion.OpRegion->Header.SIGN, HEADER_SIGNATURE, sizeof (HEADER_SIGNATURE));
+ ///
+ /// Set OpRegion Size in KBs
+ ///
+ mIgdOpRegion.OpRegion->Header.SIZE = HEADER_SIZE / 1024;
+ mIgdOpRegion.OpRegion->Header.OVER = (UINT32) (LShiftU64 (HEADER_OPREGION_VER_GEN12, 16) + LShiftU64 (HEADER_OPREGION_REV, 8));
+
+ ///
+ /// All Mailboxes are supported.
+ ///
+ mIgdOpRegion.OpRegion->Header.MBOX = HEADER_MBOX_SUPPORT;
+
+ ///
+ /// Initialize OpRegion Mailbox 1 (Public ACPI Methods).
+ ///
+ /// Note - The initial setting of mailbox 1 fields is implementation specific.
+ /// Adjust them as needed many even coming from user setting in setup.
+ ///
+ ///
+ /// Initialize OpRegion Mailbox 3 (ASLE Interrupt and Power Conservation).
+ ///
+ /// Note - The initial setting of mailbox 3 fields is implementation specific.
+ /// Adjust them as needed many even coming from user setting in setup.
+ ///
+ ///
+ /// Do not initialize TCHE. This field is written by the graphics driver only.
+ ///
+ ///
+ /// The ALSI field is generally initialized by ASL code by reading the embedded controller.
+ ///
+ mIgdOpRegion.OpRegion->Header.PCON = GraphicsDxeConfig->PlatformConfig;
+ mIgdOpRegion.OpRegion->Header.PCON = mIgdOpRegion.OpRegion->Header.PCON | 0x2;
+
+ mIgdOpRegion.OpRegion->MBox3.BCLP = BACKLIGHT_BRIGHTNESS;
+
+ mIgdOpRegion.OpRegion->MBox3.PFIT = (FIELD_VALID_BIT | PFIT_STRETCH);
+
+ ///
+ /// Reporting to driver for VR IMON Calibration. Bits [5-1] values supported 14A to 31A.
+ ///
+ mIgdOpRegion.OpRegion->MBox3.PCFT = (SaNvsAreaProtocol->Area->GfxTurboIMON << 1) & 0x003E;
+
+ ///
+ /// Set Initial current Brightness
+ ///
+ mIgdOpRegion.OpRegion->MBox3.CBLV = (INIT_BRIGHT_LEVEL | FIELD_VALID_BIT);
+
+ ///
+ /// Static Backlight Brightness Level Duty cycle Mapping Table
+ ///
+ for (Index = 0; Index < MAX_BCLM_ENTRIES; Index++) {
+ mIgdOpRegion.OpRegion->MBox3.BCLM[Index] = GraphicsDxeConfig->BCLM[Index];
+ }
+
+ mIgdOpRegion.OpRegion->MBox3.IUER = 0x00;
+
+ if (!EFI_ERROR (Status)) {
+ mIgdOpRegion.OpRegion->MBox3.IUER = GraphicsDxeConfig->IuerStatusVal;
+ }
+
+ ///
+ /// Initialize hardware state:
+ /// Set ASLS Register to the OpRegion physical memory address.
+ /// Set SWSCI register bit 15 to a "1" to activate SCI interrupts.
+ ///
+ PciSegmentWrite32 (IgdBaseAddress + R_SA_IGD_ASLS_OFFSET, (UINT32) (UINTN) (mIgdOpRegion.OpRegion));
+ PciSegmentAndThenOr16 (IgdBaseAddress + R_SA_IGD_SWSCI_OFFSET, (UINT16) ~(BIT0), BIT15);
+
+ DwordData = PciSegmentRead32 (IgdBaseAddress + R_SA_IGD_ASLS_OFFSET);
+ S3BootScriptSaveMemWrite (
+ S3BootScriptWidthUint32,
+ (UINTN) PcdGet64 (PcdPciExpressBaseAddress) + (IgdBaseAddress + R_SA_IGD_ASLS_OFFSET),
+ 1,
+ &DwordData
+ );
+ DwordData = PciSegmentRead32 (IgdBaseAddress + R_SA_IGD_SWSCI_OFFSET);
+ S3BootScriptSaveMemWrite (
+ S3BootScriptWidthUint32,
+ (UINTN) PcdGet64 (PcdPciExpressBaseAddress) + (IgdBaseAddress + R_SA_IGD_SWSCI_OFFSET),
+ 1,
+ &DwordData
+ );
+
+ ///
+ /// Install OpRegion / Software SCI protocol
+ ///
+ Handle = NULL;
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Handle,
+ &gIgdOpRegionProtocolGuid,
+ &mIgdOpRegion,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Return final status
+ ///
+ return EFI_SUCCESS;
+}
+
+/**
+ Update Graphics OpRegion after PCI enumeration.
+
+ @param[in] void - None
+ @retval EFI_SUCCESS - The function completed successfully.
+**/
+EFI_STATUS
+UpdateIgdOpRegionEndOfDxe (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINTN HandleCount;
+ EFI_HANDLE *HandleBuffer;
+ UINTN Index;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ PCI_TYPE00 Pci;
+ UINTN Segment;
+ UINTN Bus;
+ UINTN Device;
+ UINTN Function;
+
+ Bus = 0;
+ Device = 0;
+ Function = 0;
+
+ DEBUG ((DEBUG_INFO, "UpdateIgdOpRegionEndOfDxe\n"));
+
+ mIgdOpRegion.OpRegion->Header.PCON |= BIT8; //Set External Gfx Adapter field is valid
+ mIgdOpRegion.OpRegion->Header.PCON &= (UINT32) (~BIT7); //Assume No External Gfx Adapter
+
+ ///
+ /// Get all PCI IO protocols handles
+ ///
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiPciIoProtocolGuid,
+ NULL,
+ &HandleCount,
+ &HandleBuffer
+ );
+
+ if (!EFI_ERROR (Status)) {
+ for (Index = 0; Index < HandleCount; Index++) {
+ ///
+ /// Get the PCI IO Protocol Interface corresponding to each handle
+ ///
+ Status = gBS->HandleProtocol (
+ HandleBuffer[Index],
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo
+ );
+
+ if (!EFI_ERROR (Status)) {
+ ///
+ /// Read the PCI configuration space
+ ///
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint32,
+ 0,
+ sizeof (Pci) / sizeof (UINT32),
+ &Pci
+ );
+
+ ///
+ /// Find the display controllers devices
+ ///
+ if (!EFI_ERROR (Status) && IS_PCI_DISPLAY (&Pci)) {
+ Status = PciIo->GetLocation (
+ PciIo,
+ &Segment,
+ &Bus,
+ &Device,
+ &Function
+ );
+
+ //
+ // Assumption: Onboard devices will be sits on Bus no 0, while external devices will be sits on Bus no > 0
+ //
+ if (!EFI_ERROR (Status) && (Bus > 0)) {
+ //External Gfx Adapter Detected and Available
+ DEBUG ((DEBUG_INFO, "PCON - External Gfx Adapter Detected and Available\n"));
+ mIgdOpRegion.OpRegion->Header.PCON |= BIT7;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ ///
+ /// Free any allocated buffers
+ ///
+ if (HandleBuffer != NULL) {
+ FreePool (HandleBuffer);
+ }
+
+ ///
+ /// Return final status
+ ///
+ return Status;
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Graphics/LibraryPrivate/DxeIgdOpRegionInitLib/DxeIgdOpRegionInitLib.inf b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Graphics/LibraryPrivate/DxeIgdOpRegionInitLib/DxeIgdOpRegionInitLib.inf
new file mode 100644
index 0000000000..20c6265d8f
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Graphics/LibraryPrivate/DxeIgdOpRegionInitLib/DxeIgdOpRegionInitLib.inf
@@ -0,0 +1,49 @@
+## @file
+# Component description file for the Dxe IGD OpRegion library.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = DxeIgdOpRegionInitLib
+FILE_GUID = 18D47D72-555E-475B-A4E4-AD20C3BD8B15
+VERSION_STRING = 1.0
+MODULE_TYPE = DXE_DRIVER
+UEFI_SPECIFICATION_VERSION = 2.00
+LIBRARY_CLASS = DxeIgdOpRegionInitLib
+
+[LibraryClasses]
+UefiLib
+UefiRuntimeServicesTableLib
+UefiBootServicesTableLib
+DebugLib
+PostCodeLib
+ConfigBlockLib
+PciSegmentLib
+BaseMemoryLib
+MemoryAllocationLib
+IoLib
+S3BootScriptLib
+
+[Packages]
+MdePkg/MdePkg.dec
+TigerlakeSiliconPkg/SiPkg.dec
+IntelSiliconPkg/IntelSiliconPkg.dec
+
+[Pcd]
+gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
+
+[Sources]
+DxeIgdOpRegionInit.c
+
+[Guids]
+gGraphicsDxeConfigGuid ## CONSUMES
+
+[Protocols]
+gIgdOpRegionProtocolGuid ## PRODUCES
+gSaPolicyProtocolGuid ## CONSUMES
+gEfiPciIoProtocolGuid ## CONSUMES
+gSaNvsAreaProtocolGuid ## CONSUMES
--
2.24.0.windows.2
^ permalink raw reply related [flat|nested] 42+ messages in thread
* [Patch V3 19/40] TigerlakeSiliconPkg/IpBlock: Add Hda component
2021-02-05 7:40 [Patch V3 01/40] TigerlakeSiliconPkg: Add package and Include/ConfigBlock headers Heng Luo
` (16 preceding siblings ...)
2021-02-05 7:40 ` [Patch V3 18/40] TigerlakeSiliconPkg/IpBlock: Add Graphics component Heng Luo
@ 2021-02-05 7:40 ` Heng Luo
2021-02-05 7:40 ` [Patch V3 20/40] TigerlakeSiliconPkg/IpBlock: Add HostBridge component Heng Luo
` (20 subsequent siblings)
38 siblings, 0 replies; 42+ messages in thread
From: Heng Luo @ 2021-02-05 7:40 UTC (permalink / raw)
To: devel; +Cc: Sai Chaganty, Nate DeSimone
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3171
Adds the following files:
* IpBlock/Hda/IncludePrivate
* IpBlock/Hda/Library
* IpBlock/Hda/LibraryPrivate
Cc: Sai Chaganty <rangasai.v.chaganty@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Signed-off-by: Heng Luo <heng.luo@intel.com>
---
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Hda/IncludePrivate/Library/DxeHdaPolicyLib.h | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Hda/IncludePrivate/Register/HdaRegs.h | 46 ++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Hda/Library/DxeHdaNhltLib/DxeHdaNhltLib.c | 383 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Hda/Library/DxeHdaNhltLib/DxeHdaNhltLib.inf | 31 +++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Hda/LibraryPrivate/DxeHdaPolicyLib/DxeHdaPolicyLib.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Hda/LibraryPrivate/DxeHdaPolicyLib/DxeHdaPolicyLib.inf | 31 +++++++++++++++++++++++++++++++
6 files changed, 638 insertions(+)
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Hda/IncludePrivate/Library/DxeHdaPolicyLib.h b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Hda/IncludePrivate/Library/DxeHdaPolicyLib.h
new file mode 100644
index 0000000000..9c42bf5611
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Hda/IncludePrivate/Library/DxeHdaPolicyLib.h
@@ -0,0 +1,55 @@
+/** @file
+ DXE Hda policy library.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _DXE_HDA_POLICY_LIB_H_
+#define _DXE_HDA_POLICY_LIB_H_
+
+#include <Protocol/PchPolicy.h>
+
+/**
+ Print HDAUDIO_DXE_CONFIG and serial out.
+
+ @param[in] PchPolicy Pointer to a PCH_POLICY_PROTOCOL
+**/
+VOID
+HdaDxePrintConfig (
+ IN PCH_POLICY_PROTOCOL *PchPolicy
+ );
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+**/
+VOID
+HdaDxeLoadConfigDefault (
+ IN VOID *ConfigBlockPointer
+ );
+
+/**
+ Get Hda config block table size.
+
+ @retval Size of config block
+**/
+UINT16
+HdaDxeGetConfigBlockTotalSize (
+ VOID
+ );
+
+/**
+ Add Hda ConfigBlock.
+
+ @param[in] ConfigBlockTableAddress The pointer to config block table
+
+ @retval EFI_SUCCESS The policy default is initialized.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create buffer
+**/
+EFI_STATUS
+HdaDxeAddConfigBlock (
+ IN VOID *ConfigBlockTableAddress
+ );
+
+#endif // _DXE_HDA_POLICY_LIB_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Hda/IncludePrivate/Register/HdaRegs.h b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Hda/IncludePrivate/Register/HdaRegs.h
new file mode 100644
index 0000000000..b165e7bb22
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Hda/IncludePrivate/Register/HdaRegs.h
@@ -0,0 +1,46 @@
+/** @file
+ Register names for High Definition Audio device.
+
+ Conventions:
+
+ - Register definition format:
+ Prefix_[GenerationName]_[ComponentName]_SubsystemName_RegisterSpace_RegisterName
+ - Prefix:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register size
+ Definitions beginning with "N_" are the bit position
+ - [GenerationName]:
+ Three letter acronym of the generation is used (e.g. SKL,KBL,CNL etc.).
+ Register name without GenerationName applies to all generations.
+ - [ComponentName]:
+ This field indicates the component name that the register belongs to (e.g. PCH, SA etc.)
+ Register name without ComponentName applies to all components.
+ Register that is specific to -LP denoted by "_PCH_LP_" in component name.
+ - SubsystemName:
+ This field indicates the subsystem name of the component that the register belongs to
+ (e.g. PCIE, USB, SATA, GPIO, PMC etc.).
+ - RegisterSpace:
+ MEM - MMIO space register of subsystem.
+ IO - IO space register of subsystem.
+ PCR - Private configuration register of subsystem.
+ CFG - PCI configuration space register of subsystem.
+ - RegisterName:
+ Full register name.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _HDA_REGS_H_
+#define _HDA_REGS_H_
+
+//
+// HD-A Controller Registers
+//
+// PCI Configuration Space Registers
+//
+#define R_HDA_CFG_PCS 0x54
+#define B_HDA_CFG_PCS_PMEE BIT8
+
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Hda/Library/DxeHdaNhltLib/DxeHdaNhltLib.c b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Hda/Library/DxeHdaNhltLib/DxeHdaNhltLib.c
new file mode 100644
index 0000000000..71388934e6
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Hda/Library/DxeHdaNhltLib/DxeHdaNhltLib.c
@@ -0,0 +1,383 @@
+/** @file
+ HD Audio NHLT Library implementation.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Uefi/UefiBaseType.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PcdLib.h>
+#include <ConfigBlock.h>
+#include <Library/ConfigBlockLib.h>
+#include <Library/PchInfoLib.h>
+#include <DxeHdaNhlt.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 Index;
+ ENDPOINT_DESCRIPTOR *Endpoint;
+ Endpoint = (ENDPOINT_DESCRIPTOR*) (NhltTable->EndpointDescriptors);
+
+ if (EndpointIndex > NhltTable->EndpointCount) {
+ return NULL;
+ }
+
+ for (Index = 0; Index < EndpointIndex; Index++) {
+ 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 Index;
+ UINT32 Length;
+ FORMATS_CONFIG *FormatsConfig;
+ FORMAT_CONFIG *Format;
+
+ Length = 0;
+ FormatsConfig = GetNhltEndpointFormatsConfig (Endpoint);
+ Format = FormatsConfig->FormatsConfiguration;
+
+ if (FormatIndex > FormatsConfig->FormatsCount) {
+ return NULL;
+ }
+
+ for (Index = 0; Index < FormatIndex; Index++) {
+ Length = sizeof (Format->Format) + Format->FormatConfiguration.CapabilitiesSize
+ + sizeof (Format->FormatConfiguration.CapabilitiesSize);
+ Format = (FORMAT_CONFIG*) ((UINT8*) (Format) + Length);
+ }
+
+ return Format;
+}
+
+/**
+ Returns pointer to all Device Information DEVICES_INFO structure.
+
+ @param[in] *Endpoint Endpoint for which DevicesInfo address is retrieved
+
+ @retval Pointer to DEVICES_INFO structure
+**/
+DEVICES_INFO *
+GetNhltEndpointDevicesInfo (
+ IN CONST ENDPOINT_DESCRIPTOR *Endpoint
+ )
+{
+ DEVICES_INFO *DevicesInfo;
+ FORMATS_CONFIG *FormatsConfig;
+ FORMAT_CONFIG *Format;
+
+ FormatsConfig = GetNhltEndpointFormatsConfig (Endpoint);
+ Format = GetNhltEndpointFormat (Endpoint, FormatsConfig->FormatsCount);
+ DevicesInfo = (DEVICES_INFO*) ((UINT8*) Format);
+
+ return DevicesInfo;
+}
+
+/**
+ Returns pointer to Device Information DEVICES_INFO structure.
+
+ @param[in] *Endpoint Endpoint for which Device Info address is retrieved
+ @param[in] DeviceInfoIndex Index of Device Info to be retrieved
+
+ @retval Pointer to DEVICE_INFO structure with given index
+**/
+DEVICE_INFO *
+GetNhltEndpointDeviceInfo (
+ IN CONST ENDPOINT_DESCRIPTOR *Endpoint,
+ IN CONST UINT8 DeviceInfoIndex
+ )
+{
+ DEVICES_INFO *DevicesInfo;
+ DEVICE_INFO *DeviceInfo;
+
+ DevicesInfo = GetNhltEndpointDevicesInfo (Endpoint);
+ DeviceInfo = DevicesInfo->DeviceInformation;
+
+ if (DevicesInfo == NULL || DeviceInfoIndex >= DevicesInfo->DeviceInfoCount) {
+ return NULL;
+ }
+
+ DeviceInfo = (DEVICE_INFO*) ((UINT8*) (DeviceInfo) + sizeof (*DeviceInfo) * DeviceInfoIndex);
+
+ return DeviceInfo;
+}
+
+/**
+ 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 Index;
+
+ DEBUG ((DEBUG_INFO, "------------------------------- FORMAT -------------------------------\n"));
+ DEBUG ((DEBUG_INFO, " Format->Format.Format.wFormatTag = 0x%x\n", Format->Format.Format.wFormatTag));
+ DEBUG ((DEBUG_INFO, " Format->Format.Format.nChannels = %d\n", Format->Format.Format.nChannels));
+ DEBUG ((DEBUG_INFO, " Format->Format.Format.nSamplesPerSec = %d\n", Format->Format.Format.nSamplesPerSec));
+ DEBUG ((DEBUG_INFO, " Format->Format.Format.nAvgBytesPerSec = %d\n", Format->Format.Format.nAvgBytesPerSec));
+ DEBUG ((DEBUG_INFO, " Format->Format.Format.nBlockAlign = %d\n", Format->Format.Format.nBlockAlign));
+ DEBUG ((DEBUG_INFO, " Format->Format.Format.wBitsPerSample = %d\n", Format->Format.Format.wBitsPerSample));
+ DEBUG ((DEBUG_INFO, " Format->Format.Format.cbSize = %d\n", Format->Format.Format.cbSize));
+ DEBUG ((DEBUG_INFO, " Format->Format.Samples = %d\n", Format->Format.Samples));
+ DEBUG ((DEBUG_INFO, " Format->Format.dwChannelMask = 0x%x\n", Format->Format.dwChannelMask));
+ DEBUG ((DEBUG_INFO, " Format->Format.SubFormat = %g\n", Format->Format.SubFormat));
+
+
+ DEBUG ((DEBUG_INFO, " Format->FormatConfiguration.CapabilitiesSize = %d B\n", Format->FormatConfiguration.CapabilitiesSize));
+ DEBUG ((DEBUG_VERBOSE, " Format->FormatConfiguration.Capabilities:"));
+ for (Index = 0; Index < ( Format->FormatConfiguration.CapabilitiesSize ) ; Index++) {
+ if (Index % 16 == 0) {
+ DEBUG ((DEBUG_VERBOSE, "\n"));
+ }
+ DEBUG ((DEBUG_VERBOSE, "0x%02x, ", Format->FormatConfiguration.Capabilities[Index]));
+ }
+ DEBUG ((DEBUG_VERBOSE, "\n"));
+}
+
+/**
+ Prints Device Information.
+
+ @param[in] *DeviceInfo DeviceInfo to be printed
+
+ @retval None
+**/
+VOID
+NhltDeviceInfoDump (
+ IN CONST DEVICE_INFO *DeviceInfo
+ )
+{
+ DEBUG ((DEBUG_INFO, "----------------------------- DEVICE INFO ----------------------------\n"));
+ DEBUG ((DEBUG_INFO, " DeviceInfo->DeviceId = %a\n", DeviceInfo->DeviceId));
+ DEBUG ((DEBUG_INFO, " DeviceInfo->DeviceInstanceId = 0x%x\n", DeviceInfo->DeviceInstanceId));
+ DEBUG ((DEBUG_INFO, " DeviceInfo->DevicePortId = 0x%x\n", DeviceInfo->DevicePortId));
+}
+
+/**
+ Prints Endpoint configuration.
+
+ @param[in] *Endpoint Endpoint to be printed
+
+ @retval None
+**/
+VOID
+NhltEndpointDump (
+ IN CONST ENDPOINT_DESCRIPTOR *Endpoint
+ )
+{
+ UINT8 Index;
+ FORMATS_CONFIG *FormatsConfigs;
+ FORMAT_CONFIG *Format;
+ DEVICES_INFO *DevicesInfo;
+ DEVICE_INFO *DeviceInfo;
+
+ DEBUG ((DEBUG_INFO, "------------------------------ ENDPOINT ------------------------------\n"));
+ DEBUG ((DEBUG_INFO, " Endpoint->DeviceDescriptorLength = %d B\n", Endpoint->EndpointDescriptorLength));
+ DEBUG ((DEBUG_INFO, " Endpoint->LinkType = 0x%x\n", Endpoint->LinkType));
+ DEBUG ((DEBUG_INFO, " Endpoint->InstanceId = 0x%x\n", Endpoint->InstanceId));
+ DEBUG ((DEBUG_INFO, " Endpoint->HwVendorId = 0x%x\n", Endpoint->HwVendorId));
+ DEBUG ((DEBUG_INFO, " Endpoint->HwDeviceId = 0x%x\n", Endpoint->HwDeviceId));
+ DEBUG ((DEBUG_INFO, " Endpoint->HwRevisionId = 0x%x\n", Endpoint->HwRevisionId));
+ DEBUG ((DEBUG_INFO, " Endpoint->HwSubsystemId = 0x%x\n", Endpoint->HwSubsystemId));
+ DEBUG ((DEBUG_INFO, " Endpoint->DeviceType = 0x%x\n", Endpoint->DeviceType));
+ DEBUG ((DEBUG_INFO, " Endpoint->Direction = 0x%x\n", Endpoint->Direction));
+ DEBUG ((DEBUG_INFO, " Endpoint->VirtualBusId = 0x%x\n", Endpoint->VirtualBusId));
+
+ DEBUG ((DEBUG_INFO, " Endpoint->EndpointConfig.CapabilitiesSize = %d B\n", Endpoint->EndpointConfig.CapabilitiesSize));
+ DEBUG ((DEBUG_VERBOSE, " Endpoint->EndpointConfig.Capabilities:"));
+ for (Index = 0; Index < (Endpoint->EndpointConfig.CapabilitiesSize ) ; Index++) {
+ if (Index % 16 == 0) DEBUG ((DEBUG_VERBOSE, "\n"));
+ DEBUG ((DEBUG_VERBOSE, "0x%02x, ", Endpoint->EndpointConfig.Capabilities[Index]));
+ }
+
+ FormatsConfigs = GetNhltEndpointFormatsConfig (Endpoint);
+
+ DEBUG ((DEBUG_INFO, "\n"));
+ DEBUG ((DEBUG_INFO, " Endpoint->FormatsConfig.FormatsCount = %d\n", FormatsConfigs->FormatsCount));
+ for (Index = 0; Index < FormatsConfigs->FormatsCount; Index++) {
+ Format = GetNhltEndpointFormat (Endpoint, Index);
+ if (Format != NULL) {
+ NhltFormatDump (Format);
+ }
+ }
+
+ DevicesInfo = GetNhltEndpointDevicesInfo (Endpoint);
+ if (DevicesInfo != NULL) {
+ DEBUG ((DEBUG_INFO, "\n"));
+ DEBUG ((DEBUG_INFO, " Endpoint->DevicesInfo.DeviceInfoCount = %d\n", DevicesInfo->DeviceInfoCount));
+ for (Index = 0; Index < DevicesInfo->DeviceInfoCount; Index++) {
+ DeviceInfo = GetNhltEndpointDeviceInfo (Endpoint, Index);
+ if (DeviceInfo != NULL) {
+ NhltDeviceInfoDump (DeviceInfo);
+ }
+ }
+ }
+ DEBUG ((DEBUG_VERBOSE, "\n"));
+}
+
+/**
+ Prints OED (Offload Engine Driver) configuration.
+
+ @param[in] *OedConfig OED to be printed
+
+ @retval None
+**/
+VOID
+NhltOedConfigDump (
+ IN CONST SPECIFIC_CONFIG *OedConfig
+ )
+{
+ UINT8 Index;
+
+ DEBUG ((DEBUG_INFO, "-------------------------- OED CONFIGURATION -------------------------\n"));
+ DEBUG ((DEBUG_INFO, " OedConfig->CapabilitiesSize = %d B\n", OedConfig->CapabilitiesSize));
+ DEBUG ((DEBUG_VERBOSE, " OedConfig->Capabilities:"));
+ for (Index = 0; Index < (OedConfig->CapabilitiesSize) ; Index++) {
+ if (Index % 16 == 0) DEBUG ((DEBUG_VERBOSE, "\n"));
+ DEBUG ((DEBUG_VERBOSE, "0x%02x, ", OedConfig->Capabilities[Index]));
+ }
+
+ DEBUG ((DEBUG_VERBOSE, "\n"));
+}
+
+/**
+ Prints NHLT (Non HDA-Link Table) to be exposed via ACPI (aka. OED (Offload Engine Driver) Configuration Table).
+
+ @param[in] *NhltTable The NHLT table to print
+
+ @retval None
+**/
+VOID
+NhltAcpiTableDump (
+ IN NHLT_ACPI_TABLE *NhltTable
+ )
+{
+ DEBUG_CODE_BEGIN ();
+ UINT8 Index;
+
+ 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, "sizeof DEVICES_INFO = %d B\n", sizeof (DEVICES_INFO)));
+ DEBUG ((DEBUG_INFO, "sizeof DEVICE_INFO = %d B\n", sizeof (DEVICE_INFO)));
+
+ 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 (Index = 0; Index < NhltTable->EndpointCount; Index++) {
+ NhltEndpointDump (GetNhltEndpoint (NhltTable, Index));
+ }
+
+ NhltOedConfigDump (GetNhltOedConfig (NhltTable));
+ DEBUG ((DEBUG_INFO, "----------------------------------------------------------------------\n"));
+
+ DEBUG_CODE_END ();
+}
+
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Hda/Library/DxeHdaNhltLib/DxeHdaNhltLib.inf b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Hda/Library/DxeHdaNhltLib/DxeHdaNhltLib.inf
new file mode 100644
index 0000000000..a1574c3ab1
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Hda/Library/DxeHdaNhltLib/DxeHdaNhltLib.inf
@@ -0,0 +1,31 @@
+## @file
+# Component information file for HD Audio NHLT Library
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = DxeHdaNhltLib
+FILE_GUID = DA915B7F-EE08-4C1D-B3D0-DE7C52AB155A
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = DxeHdaNhltLib
+
+[LibraryClasses]
+BaseLib
+DebugLib
+MemoryAllocationLib
+BaseMemoryLib
+PchInfoLib
+ConfigBlockLib
+
+[Packages]
+MdePkg/MdePkg.dec
+TigerlakeSiliconPkg/SiPkg.dec
+
+[Sources]
+DxeHdaNhltLib.c
+
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Hda/LibraryPrivate/DxeHdaPolicyLib/DxeHdaPolicyLib.c b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Hda/LibraryPrivate/DxeHdaPolicyLib/DxeHdaPolicyLib.c
new file mode 100644
index 0000000000..30843fab39
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Hda/LibraryPrivate/DxeHdaPolicyLib/DxeHdaPolicyLib.c
@@ -0,0 +1,92 @@
+/** @file
+ This file provides services for Hda policy function
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include <Uefi.h>
+#include <Library/DebugLib.h>
+#include <Library/SiConfigBlockLib.h>
+#include <Library/ConfigBlockLib.h>
+#include <Protocol/PchPolicy.h>
+#include <HdAudioConfig.h>
+
+/**
+ Print HDAUDIO_DXE_CONFIG and serial out.
+
+ @param[in] PchPolicy Pointer to a PCH_POLICY_PROTOCOL
+**/
+VOID
+HdaDxePrintConfig (
+ IN PCH_POLICY_PROTOCOL *PchPolicy
+ )
+{
+ EFI_STATUS Status;
+ HDAUDIO_DXE_CONFIG *HdaDxeConfig;
+ UINT32 Index;
+
+ Status = GetConfigBlock ((VOID *) PchPolicy, &gHdAudioDxeConfigGuid, (VOID *) &HdaDxeConfig);
+ ASSERT_EFI_ERROR (Status);
+
+ DEBUG ((DEBUG_INFO, "------------------ HD-Audio DXE Config ------------------\n"));
+
+ for (Index = 0; Index < PCH_MAX_HDA_SNDW_LINK_NUM; Index++) {
+ DEBUG ((DEBUG_INFO, " SNDW%d AutonomousClockStop : %d\n", Index, HdaDxeConfig->SndwConfig[Index].AutonomousClockStop));
+ DEBUG ((DEBUG_INFO, " SNDW%d DODS : %d\n", Index, HdaDxeConfig->SndwConfig[Index].DataOnDelaySelect));
+ DEBUG ((DEBUG_INFO, " SNDW%d DOAS : %d\n", Index, HdaDxeConfig->SndwConfig[Index].DataOnActiveIntervalSelect));
+ }
+ DEBUG ((DEBUG_INFO, " DSP Feature Mask : 0x%x\n", HdaDxeConfig->DspFeatureMask));
+}
+
+/**
+ Load Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+**/
+VOID
+HdaDxeLoadConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ HDAUDIO_DXE_CONFIG *HdAudioDxeConfig;
+ HdAudioDxeConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "HdaDxeConfig->Header.GuidHob.Name = %g\n", &HdAudioDxeConfig->Header.GuidHob.Name));
+ DEBUG ((DEBUG_INFO, "HdaDxeConfig->Header.GuidHob.Header.HobLength = 0x%x\n", HdAudioDxeConfig->Header.GuidHob.Header.HobLength));
+}
+
+STATIC COMPONENT_BLOCK_ENTRY mHdaBlocks = {
+ &gHdAudioDxeConfigGuid,
+ sizeof (HDAUDIO_DXE_CONFIG),
+ HDAUDIO_DXE_CONFIG_REVISION,
+ HdaDxeLoadConfigDefault
+};
+
+/**
+ Get Hda config block table size.
+
+ @retval Size of config block
+**/
+UINT16
+HdaDxeGetConfigBlockTotalSize (
+ VOID
+ )
+{
+ return mHdaBlocks.Size;
+}
+
+/**
+ Add Hda ConfigBlock.
+
+ @param[in] ConfigBlockTableAddress The pointer to config block table
+
+ @retval EFI_SUCCESS The policy default is initialized.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create buffer
+**/
+EFI_STATUS
+HdaDxeAddConfigBlock (
+ IN VOID *ConfigBlockTableAddress
+ )
+{
+ return AddComponentConfigBlocks (ConfigBlockTableAddress, &mHdaBlocks, 1);
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Hda/LibraryPrivate/DxeHdaPolicyLib/DxeHdaPolicyLib.inf b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Hda/LibraryPrivate/DxeHdaPolicyLib/DxeHdaPolicyLib.inf
new file mode 100644
index 0000000000..758499b95e
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Hda/LibraryPrivate/DxeHdaPolicyLib/DxeHdaPolicyLib.inf
@@ -0,0 +1,31 @@
+## @file
+# Component description file for the Hda policy library
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = DxeHdaPolicyLib
+FILE_GUID = B053EFE4-0868-4510-A71D-96A85CD16C77
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = DxeHdaPolicyLib
+
+[LibraryClasses]
+DebugLib
+ConfigBlockLib
+SiConfigBlockLib
+
+[Packages]
+MdePkg/MdePkg.dec
+TigerlakeSiliconPkg/SiPkg.dec
+
+[Sources]
+DxeHdaPolicyLib.c
+
+[Guids]
+gHdAudioDxeConfigGuid ## CONSUMES
--
2.24.0.windows.2
^ permalink raw reply related [flat|nested] 42+ messages in thread
* [Patch V3 20/40] TigerlakeSiliconPkg/IpBlock: Add HostBridge component
2021-02-05 7:40 [Patch V3 01/40] TigerlakeSiliconPkg: Add package and Include/ConfigBlock headers Heng Luo
` (17 preceding siblings ...)
2021-02-05 7:40 ` [Patch V3 19/40] TigerlakeSiliconPkg/IpBlock: Add Hda component Heng Luo
@ 2021-02-05 7:40 ` Heng Luo
2021-02-05 7:40 ` [Patch V3 21/40] TigerlakeSiliconPkg/IpBlock: Add P2sb component Heng Luo
` (19 subsequent siblings)
38 siblings, 0 replies; 42+ messages in thread
From: Heng Luo @ 2021-02-05 7:40 UTC (permalink / raw)
To: devel; +Cc: Sai Chaganty, Nate DeSimone
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3171
Adds the following files:
* IpBlock/HostBridge/IncludePrivate
Cc: Sai Chaganty <rangasai.v.chaganty@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Signed-off-by: Heng Luo <heng.luo@intel.com>
---
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/HostBridge/IncludePrivate/HostBridgeDataHob.h | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/HostBridge/IncludePrivate/HostBridgeDataHob.h b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/HostBridge/IncludePrivate/HostBridgeDataHob.h
new file mode 100644
index 0000000000..41e92da4df
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/HostBridge/IncludePrivate/HostBridgeDataHob.h
@@ -0,0 +1,25 @@
+/** @file
+ The GUID definition for Host Bridge Data Hob
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _HOST_BRIDGE_DATA_HOB_H_
+#define _HOST_BRIDGE_DATA_HOB_H_
+
+#include <Base.h>
+
+extern EFI_GUID gHostBridgeDataHobGuid;
+#pragma pack (push,1)
+
+///
+/// Host Bridge Data Hob
+///
+typedef struct {
+ EFI_HOB_GUID_TYPE EfiHobGuidType; ///< GUID Hob type structure for gSaDataHobGuid
+ UINT8 EnableAbove4GBMmio; ///< 0=Disable above 4GB MMIO resource support, 1=Enable above 4GB MMIO resource support
+ BOOLEAN SkipPamLock; ///< 0=All PAM registers will be locked in System Agent code, 1=Do not lock PAM registers in System Agent code.
+ UINT8 Rsvd1[2]; ///< Reserved for future use
+} HOST_BRIDGE_DATA_HOB;
+#pragma pack (pop)
+#endif
--
2.24.0.windows.2
^ permalink raw reply related [flat|nested] 42+ messages in thread
* [Patch V3 21/40] TigerlakeSiliconPkg/IpBlock: Add P2sb component
2021-02-05 7:40 [Patch V3 01/40] TigerlakeSiliconPkg: Add package and Include/ConfigBlock headers Heng Luo
` (18 preceding siblings ...)
2021-02-05 7:40 ` [Patch V3 20/40] TigerlakeSiliconPkg/IpBlock: Add HostBridge component Heng Luo
@ 2021-02-05 7:40 ` Heng Luo
2021-02-05 7:40 ` [Patch V3 22/40] TigerlakeSiliconPkg/IpBlock: Add PchDmi component Heng Luo
` (18 subsequent siblings)
38 siblings, 0 replies; 42+ messages in thread
From: Heng Luo @ 2021-02-05 7:40 UTC (permalink / raw)
To: devel; +Cc: Sai Chaganty, Nate DeSimone
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3171
Adds the following files:
* IpBlock/P2sb/IncludePrivate
* IpBlock/P2sb/Library
* IpBlock/P2sb/LibraryPrivate
Cc: Sai Chaganty <rangasai.v.chaganty@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Signed-off-by: Heng Luo <heng.luo@intel.com>
---
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/P2sb/IncludePrivate/Library/PchSbiAccessLib.h | 112 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/P2sb/IncludePrivate/Register/P2sbRegs.h | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/P2sb/Library/PeiDxeSmmCpuRegbarAccessLib/CpuRegbarAccessLib.c | 494 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/P2sb/Library/PeiDxeSmmCpuRegbarAccessLib/PeiDxeSmmCpuRegbarAccessLib.inf | 35 +++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/P2sb/Library/PeiDxeSmmPchPcrLib/PchPcrLib.c | 313 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/P2sb/Library/PeiDxeSmmPchPcrLib/PeiDxeSmmPchPcrLib.inf | 35 +++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/P2sb/LibraryPrivate/PeiDxeSmmPchSbiAccessLib/PchSbiAccessLib.c | 253 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/P2sb/LibraryPrivate/PeiDxeSmmPchSbiAccessLib/PeiDxeSmmPchSbiAccessLib.inf | 36 ++++++++++++++++++++++++++++++++++++
8 files changed, 1343 insertions(+)
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/P2sb/IncludePrivate/Library/PchSbiAccessLib.h b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/P2sb/IncludePrivate/Library/PchSbiAccessLib.h
new file mode 100644
index 0000000000..3fab933bbd
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/P2sb/IncludePrivate/Library/PchSbiAccessLib.h
@@ -0,0 +1,112 @@
+/** @file
+ Header file for PchSbiAccessLib.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PCH_SBI_ACCESS_LIB_H_
+#define _PCH_SBI_ACCESS_LIB_H_
+
+#include <Library/PchPcrLib.h>
+
+/**
+ PCH SBI opcode definitions
+**/
+typedef enum {
+ MemoryRead = 0x0,
+ MemoryWrite = 0x1,
+ PciConfigRead = 0x4,
+ PciConfigWrite = 0x5,
+ PrivateControlRead = 0x6,
+ PrivateControlWrite = 0x7,
+ GpioLockUnlock = 0x13
+} PCH_SBI_OPCODE;
+
+/**
+ PCH SBI response status definitions
+**/
+typedef enum {
+ SBI_SUCCESSFUL = 0,
+ SBI_UNSUCCESSFUL = 1,
+ SBI_POWERDOWN = 2,
+ SBI_MIXED = 3,
+ SBI_INVALID_RESPONSE
+} PCH_SBI_RESPONSE;
+
+/**
+ Execute PCH SBI message
+ Take care of that there is no lock protection when using SBI programming in both POST time and SMI.
+ It will clash with POST time SBI programming when SMI happen.
+ Programmer MUST do the save and restore opration while using the PchSbiExecution inside SMI
+ to prevent from racing condition.
+ This function will reveal P2SB and hide P2SB if it's originally hidden. If more than one SBI access
+ needed, it's better to unhide the P2SB before calling and hide it back after done.
+
+ When the return value is "EFI_SUCCESS", the "Response" do not need to be checked as it would have been
+ SBI_SUCCESS. If the return value is "EFI_DEVICE_ERROR", then this would provide additional information
+ when needed.
+
+ @param[in] Pid Port ID of the SBI message
+ @param[in] Offset Offset of the SBI message
+ @param[in] Opcode Opcode
+ @param[in] Posted Posted message
+ @param[in, out] Data32 Read/Write data
+ @param[out] Response Response
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_DEVICE_ERROR Transaction fail
+ @retval EFI_INVALID_PARAMETER Invalid parameter
+ @retval EFI_TIMEOUT Timeout while waiting for response
+**/
+EFI_STATUS
+PchSbiExecution (
+ IN PCH_SBI_PID Pid,
+ IN UINT64 Offset,
+ IN PCH_SBI_OPCODE Opcode,
+ IN BOOLEAN Posted,
+ IN OUT UINT32 *Data32,
+ OUT UINT8 *Response
+ );
+
+/**
+ Full function for executing PCH SBI message
+ Take care of that there is no lock protection when using SBI programming in both POST time and SMI.
+ It will clash with POST time SBI programming when SMI happen.
+ Programmer MUST do the save and restore opration while using the PchSbiExecution inside SMI
+ to prevent from racing condition.
+ This function will reveal P2SB and hide P2SB if it's originally hidden. If more than one SBI access
+ needed, it's better to unhide the P2SB before calling and hide it back after done.
+
+ When the return value is "EFI_SUCCESS", the "Response" do not need to be checked as it would have been
+ SBI_SUCCESS. If the return value is "EFI_DEVICE_ERROR", then this would provide additional information
+ when needed.
+
+ @param[in] Pid Port ID of the SBI message
+ @param[in] Offset Offset of the SBI message
+ @param[in] Opcode Opcode
+ @param[in] Posted Posted message
+ @param[in] Fbe First byte enable
+ @param[in] Bar Bar
+ @param[in] Fid Function ID
+ @param[in, out] Data32 Read/Write data
+ @param[out] Response Response
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_DEVICE_ERROR Transaction fail
+ @retval EFI_INVALID_PARAMETER Invalid parameter
+ @retval EFI_TIMEOUT Timeout while waiting for response
+**/
+EFI_STATUS
+PchSbiExecutionEx (
+ IN PCH_SBI_PID Pid,
+ IN UINT64 Offset,
+ IN PCH_SBI_OPCODE Opcode,
+ IN BOOLEAN Posted,
+ IN UINT16 Fbe,
+ IN UINT16 Bar,
+ IN UINT16 Fid,
+ IN OUT UINT32 *Data32,
+ OUT UINT8 *Response
+ );
+
+#endif // _PCH_SBI_ACCESS_LIB_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/P2sb/IncludePrivate/Register/P2sbRegs.h b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/P2sb/IncludePrivate/Register/P2sbRegs.h
new file mode 100644
index 0000000000..44c71af719
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/P2sb/IncludePrivate/Register/P2sbRegs.h
@@ -0,0 +1,65 @@
+/** @file
+ Register names for PCH P2SB device
+
+ Conventions:
+
+ - Register definition format:
+ Prefix_[GenerationName]_[ComponentName]_SubsystemName_RegisterSpace_RegisterName
+ - Prefix:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register size
+ Definitions beginning with "N_" are the bit position
+ - [GenerationName]:
+ Three letter acronym of the generation is used (e.g. SKL,KBL,CNL etc.).
+ Register name without GenerationName applies to all generations.
+ - [ComponentName]:
+ This field indicates the component name that the register belongs to (e.g. PCH, SA etc.)
+ Register name without ComponentName applies to all components.
+ Register that is specific to -LP denoted by "_PCH_LP_" in component name.
+ - SubsystemName:
+ This field indicates the subsystem name of the component that the register belongs to
+ (e.g. PCIE, USB, SATA, GPIO, PMC etc.).
+ - RegisterSpace:
+ MEM - MMIO space register of subsystem.
+ IO - IO space register of subsystem.
+ PCR - Private configuration register of subsystem.
+ CFG - PCI configuration space register of subsystem.
+ - RegisterName:
+ Full register name.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _P2SB_REGS_H_
+#define _P2SB_REGS_H_
+
+//
+// PCI to P2SB Bridge Registers
+//
+
+#define R_IO_APIC_MEM_INDEX_OFFSET 0x00
+#define R_IO_APIC_MEM_DATA_OFFSET 0x10
+#define V_P2SB_CFG_IBDF_BUS 0
+#define V_P2SB_CFG_IBDF_DEV 30
+#define V_P2SB_CFG_IBDF_FUNC 7
+#define V_P2SB_CFG_HBDF_BUS 0
+#define V_P2SB_CFG_HBDF_DEV 30
+#define V_P2SB_CFG_HBDF_FUNC 6
+
+//
+// Definition for SBI
+//
+#define R_P2SB_CFG_SBIADDR 0xD0
+#define R_P2SB_CFG_SBIDATA 0xD4
+#define R_P2SB_CFG_SBISTAT 0xD8
+#define B_P2SB_CFG_SBISTAT_OPCODE 0xFF00
+#define B_P2SB_CFG_SBISTAT_POSTED BIT7
+#define B_P2SB_CFG_SBISTAT_RESPONSE 0x0006
+#define N_P2SB_CFG_SBISTAT_RESPONSE 1
+#define B_P2SB_CFG_SBISTAT_INITRDY BIT0
+#define R_P2SB_CFG_SBIRID 0xDA
+#define R_P2SB_CFG_SBIEXTADDR 0xDC
+
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/P2sb/Library/PeiDxeSmmCpuRegbarAccessLib/CpuRegbarAccessLib.c b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/P2sb/Library/PeiDxeSmmCpuRegbarAccessLib/CpuRegbarAccessLib.c
new file mode 100644
index 0000000000..9d8851ac37
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/P2sb/Library/PeiDxeSmmCpuRegbarAccessLib/CpuRegbarAccessLib.c
@@ -0,0 +1,494 @@
+/** @file
+ CPU REGBAR ACCESS library.
+ All function in this library is available for PEI, DXE, and SMM,
+ But do not support UEFI RUNTIME environment call.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/CpuRegbarAccessLib.h>
+
+/**
+ Definition for REGBAR address
+ The REGBAR address is used for the CPU IP's SB register access
+**/
+#define CPU_REGBAR_ADDRESS(Pid, Offset) (PcdGet32(PcdRegBarBaseAddress) | ((UINT8)(Pid) << 16) | (UINT16)(Offset))
+
+/**
+ Read REGBAR register.
+ It returns REGBAR register and size in 8bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] CpuSbDevicePid CPU SB Device Port ID
+ @param[in] Offset Register offset of this Port ID
+
+ @retval UINT64 REGBAR register value.
+**/
+UINT64
+CpuRegbarRead64 (
+ IN CPU_SB_DEVICE_PID CpuSbDevicePid,
+ IN UINT16 Offset
+ )
+{
+ UINT8 Pid;
+
+ Pid = CpuSbDevicePid;
+ if (Pid != INVALID_PID)
+ return ((UINT64) MmioRead32 (CPU_REGBAR_ADDRESS (Pid, Offset)) + LShiftU64 ((UINT64) MmioRead32 (CPU_REGBAR_ADDRESS (Pid, Offset+4)), 32));
+ else
+ return INVALID_DATA_64;
+}
+
+
+/**
+ Read REGBAR register.
+ It returns REGBAR register and size in 4bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] CpuSbDevicePid CPU SB Device Port ID
+ @param[in] Offset Register offset of this Port ID
+
+ @retval UINT32 REGBAR register value.
+**/
+UINT32
+CpuRegbarRead32 (
+ IN CPU_SB_DEVICE_PID CpuSbDevicePid,
+ IN UINT16 Offset
+ )
+{
+ UINT8 Pid;
+
+ Pid = CpuSbDevicePid;
+ if (Pid != INVALID_PID)
+ return MmioRead32 (CPU_REGBAR_ADDRESS (Pid, Offset));
+ else
+ return INVALID_DATA_32;
+}
+
+/**
+ Read REGBAR register.
+ It returns REGBAR register and size in 2bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] CpuSbDevicePid CPU SB Device Port ID
+ @param[in] Offset Register offset of this Port ID
+
+ @retval UINT16 REGBAR register value.
+**/
+UINT16
+CpuRegbarRead16 (
+ IN CPU_SB_DEVICE_PID CpuSbDevicePid,
+ IN UINT16 Offset
+ )
+{
+ UINT16 DwOffset;
+ UINT32 Data32;
+ UINT16 Data16;
+
+ Data16 = 0;
+ Data32 = 0;
+ DwOffset = 0;
+
+ if (CpuSbDevicePid == INVALID_PID) {
+ return INVALID_DATA_16;
+ }
+ switch (Offset & 0x0003) {
+ case 0:
+ DwOffset = Offset;
+ break;
+ case 2:
+ DwOffset = Offset - 0x2;
+ break;
+ }
+ Data32 = MmioRead32 (CPU_REGBAR_ADDRESS (CpuSbDevicePid, DwOffset));
+ switch (Offset & 0x0003) {
+ case 0:
+ Data16 = (UINT16) Data32;
+ break;
+ case 2:
+ Data16 = (UINT16) (Data32 >> 16);
+ break;
+ }
+ return Data16;
+}
+
+/**
+ Read REGBAR register.
+ It returns REGBAR register and size in 1bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] CpuSbDevicePid CPU SB Device Port ID
+ @param[in] Offset Register offset of this Port ID
+
+ @retval UINT8 REGBAR regsiter value
+**/
+UINT8
+CpuRegbarRead8 (
+ IN CPU_SB_DEVICE_PID CpuSbDevicePid,
+ IN UINT16 Offset
+ )
+{
+ UINT16 DwOffset;
+ UINT32 Data32;
+ UINT8 Data8;
+
+ DwOffset = 0;
+ Data32 = 0;
+ Data8 = 0;
+
+ if (CpuSbDevicePid == INVALID_PID)
+ return INVALID_DATA_8;
+ switch (Offset & 0x0003) {
+ case 0:
+ DwOffset = Offset;
+ break;
+ case 1:
+ DwOffset = Offset - 0x1;
+ break;
+ case 2:
+ DwOffset = Offset - 0x2;
+ break;
+ case 3:
+ DwOffset = Offset - 0x3;
+ break;
+ }
+ Data32 = MmioRead32 (CPU_REGBAR_ADDRESS (CpuSbDevicePid, DwOffset));
+ switch (Offset & 0x0003) {
+ case 0:
+ Data8 = (UINT8) Data32;
+ break;
+ case 1:
+ Data8 = (UINT8) (Data32 >> 8);
+ break;
+ case 2:
+ Data8 = (UINT8) (Data32 >> 16);
+ break;
+ case 3:
+ Data8 = (UINT8) (Data32 >> 24);
+ break;
+ }
+ return Data8;
+}
+
+
+/**
+ Write REGBAR register.
+ It programs REGBAR register and size in 8bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] CpuSbDevicePid CPU SB Device Port ID
+ @param[in] Offset Register offset of Port ID.
+ @param[in] Data Input Data. Must be the same size as Size parameter.
+
+ @retval UINT64 Value written to register
+**/
+UINT64
+CpuRegbarWrite64 (
+ IN CPU_SB_DEVICE_PID CpuSbDevicePid,
+ IN UINT16 Offset,
+ IN UINT64 Data
+ )
+{
+ UINT8 Pid;
+
+ Pid = CpuSbDevicePid;
+ if (Pid != INVALID_PID) {
+ MmioWrite32 (CPU_REGBAR_ADDRESS (Pid, Offset) + 4, (UINT32) RShiftU64 (Data, 32));
+ MmioWrite32 (CPU_REGBAR_ADDRESS (Pid, Offset), (UINT32) Data);
+ return Data;
+ }
+ else
+ return INVALID_DATA_64;
+}
+
+
+/**
+ Write REGBAR register.
+ It programs REGBAR register and size in 4bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] CpuSbDevicePid CPU SB Device Port ID
+ @param[in] Offset Register offset of Port ID.
+ @param[in] Data Input Data. Must be the same size as Size parameter.
+
+ @retval UINT32 Value written to register
+**/
+UINT32
+CpuRegbarWrite32 (
+ IN CPU_SB_DEVICE_PID CpuSbDevicePid,
+ IN UINT16 Offset,
+ IN UINT32 Data
+ )
+{
+ UINT8 Pid;
+
+ Pid = CpuSbDevicePid;
+ if (Pid != INVALID_PID)
+ return MmioWrite32 (CPU_REGBAR_ADDRESS (Pid, Offset), Data);
+ else
+ return INVALID_DATA_32;
+}
+
+/**
+ Write REGBAR register.
+ It programs REGBAR register and size in 2bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] CpuSbDevicePid CPU SB Device Port ID
+ @param[in] Offset Register offset of Port ID.
+ @param[in] Data Input Data. Must be the same size as Size parameter.
+
+ @retval UINT16 Value written to register
+**/
+UINT16
+CpuRegbarWrite16 (
+ IN CPU_SB_DEVICE_PID CpuSbDevicePid,
+ IN UINT16 Offset,
+ IN UINT16 Data
+ )
+{
+ UINT8 Pid;
+
+ Pid = CpuSbDevicePid;
+ if (Pid != INVALID_PID)
+ return MmioWrite16 (CPU_REGBAR_ADDRESS (Pid, Offset), Data);
+ else
+ return INVALID_DATA_16;
+}
+
+/**
+ Write REGBAR register.
+ It programs REGBAR register and size in 1bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] CpuSbDevicePid CPU SB Device Port ID
+ @param[in] Offset Register offset of Port ID.
+ @param[in] Data Input Data. Must be the same size as Size parameter.
+
+ @retval UINT8 Value written to register
+**/
+UINT8
+CpuRegbarWrite8 (
+ IN CPU_SB_DEVICE_PID CpuSbDevicePid,
+ IN UINT16 Offset,
+ IN UINT8 Data
+ )
+{
+ UINT8 Pid;
+
+ Pid = CpuSbDevicePid;
+ if (Pid != INVALID_PID)
+ return MmioWrite8 (CPU_REGBAR_ADDRESS (Pid, Offset), Data);
+ else
+ return INVALID_DATA_8;
+}
+
+/**
+ Write REGBAR register.
+ It programs REGBAR register and size in 4bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] CpuSbDevicePid CPU SB Device Port ID
+ @param[in] Offset Register offset of Port ID.
+ @param[in] OrData OR Data. Must be the same size as Size parameter.
+
+ @retval UINT32 Value written to register
+
+**/
+UINT32
+CpuRegbarOr32 (
+ IN CPU_SB_DEVICE_PID CpuSbDevicePid,
+ IN UINT16 Offset,
+ IN UINT32 OrData
+ )
+{
+ return CpuRegbarWrite32 (CpuSbDevicePid, Offset, CpuRegbarRead32(CpuSbDevicePid, Offset) | OrData);
+}
+
+/**
+ Write REGBAR register.
+ It programs REGBAR register and size in 2bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] CpuSbDevicePid CPU SB Device Port ID
+ @param[in] Offset Register offset of Port ID.
+ @param[in] OrData OR Data. Must be the same size as Size parameter.
+
+ @retval UINT16 Value written to register
+
+**/
+UINT16
+CpuRegbarOr16 (
+ IN CPU_SB_DEVICE_PID CpuSbDevicePid,
+ IN UINT16 Offset,
+ IN UINT16 OrData
+ )
+{
+ return CpuRegbarWrite16 (CpuSbDevicePid, Offset, CpuRegbarRead16(CpuSbDevicePid, Offset) | OrData);
+}
+
+/**
+ Write REGBAR register.
+ It programs REGBAR register and size in 1bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] CpuSbDevicePid CPU SB Device Port ID
+ @param[in] Offset Register offset of Port ID.
+ @param[in] OrData OR Data. Must be the same size as Size parameter.
+
+ @retval UINT8 Value written to register
+
+**/
+UINT8
+CpuRegbarOr8(
+ IN CPU_SB_DEVICE_PID CpuSbDevicePid,
+ IN UINT16 Offset,
+ IN UINT8 OrData
+ )
+{
+ return CpuRegbarWrite8 (CpuSbDevicePid, Offset, CpuRegbarRead8(CpuSbDevicePid, Offset) | OrData);
+}
+
+/**
+ Performs a bitwise AND of a 32-bit data.
+ It programs REGBAR register and size in 4bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] CpuSbDevice CPU SB Device
+ @param[in] Offset Register offset of Port ID.
+ @param[in] AndData And Data. Must be the same size as Size parameter.
+
+ @retval UINT32 Value written to register
+
+**/
+UINT32
+CpuRegbarAnd32 (
+ IN CPU_SB_DEVICE_PID CpuSbDevicePid,
+ IN UINT16 Offset,
+ IN UINT32 AndData
+ )
+{
+ return CpuRegbarWrite32 (CpuSbDevicePid, Offset, CpuRegbarRead32 (CpuSbDevicePid, Offset) & AndData);
+}
+
+/**
+ Performs a bitwise AND of a 16-bit data.
+ It programs REGBAR register and size in 2bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] CpuSbDevice CPU SB Device
+ @param[in] Offset Register offset of Port ID.
+ @param[in] AndData And Data. Must be the same size as Size parameter.
+
+ @retval UINT16 Value written to register
+
+**/
+UINT16
+CpuRegbarAnd16 (
+ IN CPU_SB_DEVICE_PID CpuSbDevicePid,
+ IN UINT16 Offset,
+ IN UINT16 AndData
+ )
+{
+ return CpuRegbarWrite16 (CpuSbDevicePid, Offset, CpuRegbarRead16 (CpuSbDevicePid, Offset) & AndData);
+}
+
+/**
+Performs a bitwise AND of a 8-bit data.
+It programs REGBAR register and size in 1byte.
+The Offset should not exceed 0xFFFF and must be aligned with size.
+
+@param[in] CpuSbDevice CPU SB Device
+@param[in] Offset Register offset of Port ID.
+@param[in] AndData And Data. Must be the same size as Size parameter.
+
+@retval UINT8 Value written to register
+
+**/
+UINT8
+CpuRegbarAnd8 (
+ IN CPU_SB_DEVICE_PID CpuSbDevicePid,
+ IN UINT16 Offset,
+ IN UINT8 AndData
+ )
+{
+ return CpuRegbarWrite8 (CpuSbDevicePid, Offset, CpuRegbarRead8 (CpuSbDevicePid, Offset) & AndData);
+}
+
+/**
+ Write REGBAR register.
+ It programs REGBAR register and size in 4bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] CpuSbDevicePid CPU SB Device 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 UINT32 Value written to register
+
+**/
+UINT32
+CpuRegbarAndThenOr32 (
+ IN CPU_SB_DEVICE_PID CpuSbDevicePid,
+ IN UINT16 Offset,
+ IN UINT32 AndData,
+ IN UINT32 OrData
+ )
+{
+ return CpuRegbarWrite32 (CpuSbDevicePid, Offset, (CpuRegbarRead32 (CpuSbDevicePid, Offset) & AndData) | OrData);
+}
+
+/**
+ Write REGBAR register.
+ It programs REGBAR register and size in 2bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] CpuSbDevicePid CPU SB Device 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 UINT16 Value written to register
+
+**/
+UINT16
+CpuRegbarAndThenOr16 (
+ IN CPU_SB_DEVICE_PID CpuSbDevicePid,
+ IN UINT16 Offset,
+ IN UINT16 AndData,
+ IN UINT16 OrData
+ )
+{
+ return CpuRegbarWrite16 (CpuSbDevicePid, Offset, (CpuRegbarRead16 (CpuSbDevicePid, Offset) & AndData) | OrData);
+}
+
+/**
+ Write REGBAR register.
+ It programs REGBAR register and size in 1bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] CpuSbDevicePid CPU SB Device 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 UINT8 Value written to register
+
+**/
+UINT8
+CpuRegbarAndThenOr8 (
+ IN CPU_SB_DEVICE_PID CpuSbDevicePid,
+ IN UINT16 Offset,
+ IN UINT8 AndData,
+ IN UINT8 OrData
+ )
+{
+ return CpuRegbarWrite8 (CpuSbDevicePid, Offset, (CpuRegbarRead8 (CpuSbDevicePid, Offset) & AndData) | OrData);
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/P2sb/Library/PeiDxeSmmCpuRegbarAccessLib/PeiDxeSmmCpuRegbarAccessLib.inf b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/P2sb/Library/PeiDxeSmmCpuRegbarAccessLib/PeiDxeSmmCpuRegbarAccessLib.inf
new file mode 100644
index 0000000000..596543f34f
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/P2sb/Library/PeiDxeSmmCpuRegbarAccessLib/PeiDxeSmmCpuRegbarAccessLib.inf
@@ -0,0 +1,35 @@
+## @file
+# CPU REGBAR ACCESS Library.
+#
+# All function in this library is available for PEI, DXE, and SMM,
+# But do not support UEFI RUNTIME environment call.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiDxeSmmCpuRegbarAccessLib
+FILE_GUID = CA92B911-528D-4FBB-9A5A-7BC22AA1A6D0
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = CpuRegbarAccessLib
+
+
+[LibraryClasses]
+BaseLib
+IoLib
+DebugLib
+
+[Packages]
+MdePkg/MdePkg.dec
+TigerlakeSiliconPkg/SiPkg.dec
+
+[Pcd]
+gSiPkgTokenSpaceGuid.PcdRegBarBaseAddress
+
+[Sources]
+CpuRegbarAccessLib.c
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/P2sb/Library/PeiDxeSmmPchPcrLib/PchPcrLib.c b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/P2sb/Library/PeiDxeSmmPchPcrLib/PchPcrLib.c
new file mode 100644
index 0000000000..c4f3740c86
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/P2sb/Library/PeiDxeSmmPchPcrLib/PchPcrLib.c
@@ -0,0 +1,313 @@
+/** @file
+ PCH PCR library.
+ All function in this library is available for PEI, DXE, and SMM,
+ But do not support UEFI RUNTIME environment call.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/PchPcrLib.h>
+#include <Register/PchPcrRegs.h>
+
+#ifndef MDEPKG_NDEBUG
+/**
+ Checks if the offset is valid for a given memory access width. Offset must align to width size.
+
+ @param[in] Offset Offset of a register
+ @param[in] Size Size of memory access in bytes
+
+ @retval FALSE Offset is not valid for a given memory access
+ @retval TRUE Offset is valid
+**/
+STATIC
+BOOLEAN
+PchIsPcrOffsetValid (
+ IN UINT32 Offset,
+ IN UINTN Size
+ )
+{
+ if (!IsP2sb20bPcrSupported ()) {
+ if (((Offset & (Size - 1)) != 0) || (Offset > 0xFFFF)) {
+ DEBUG ((DEBUG_ERROR, "PCR offset error. Invalid Offset: %x Size: %x", Offset, Size));
+ return FALSE;
+ } else {
+ return TRUE;
+ }
+ } else {
+ if (((Offset & (Size - 1)) != 0) || (Offset > 0xFFFFF)) {
+ DEBUG ((DEBUG_ERROR, "PCR offset error. Invalid Offset: %x Size: %x", Offset, Size));
+ return FALSE;
+ } else {
+ return TRUE;
+ }
+ }
+}
+#endif
+
+/**
+ 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
+
+ @retval UINT32 PCR register value.
+**/
+UINT32
+PchPcrRead32 (
+ IN PCH_SBI_PID Pid,
+ IN UINT32 Offset
+ )
+{
+#ifndef MDEPKG_NDEBUG
+ ASSERT (PchIsPcrOffsetValid (Offset, 4));
+#endif
+ return MmioRead32 (PCH_PCR_ADDRESS (Pid, Offset));
+}
+
+/**
+ 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
+
+ @retval UINT16 PCR register value.
+**/
+UINT16
+PchPcrRead16 (
+ IN PCH_SBI_PID Pid,
+ IN UINT32 Offset
+ )
+{
+#ifndef MDEPKG_NDEBUG
+ ASSERT (PchIsPcrOffsetValid (Offset, 2));
+#endif
+ return MmioRead16 (PCH_PCR_ADDRESS (Pid, Offset));
+}
+
+/**
+ 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
+
+ @retval UINT8 PCR register value
+**/
+UINT8
+PchPcrRead8 (
+ IN PCH_SBI_PID Pid,
+ IN UINT32 Offset
+ )
+{
+ return MmioRead8 (PCH_PCR_ADDRESS (Pid, Offset));
+}
+
+/**
+ 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] Data Input Data. Must be the same size as Size parameter.
+
+ @retval UINT32 Value written to register
+**/
+UINT32
+PchPcrWrite32 (
+ IN PCH_SBI_PID Pid,
+ IN UINT32 Offset,
+ IN UINT32 Data
+ )
+{
+#ifndef MDEPKG_NDEBUG
+ ASSERT (PchIsPcrOffsetValid (Offset, 4));
+#endif
+ MmioWrite32 (PCH_PCR_ADDRESS (Pid, Offset), Data);
+
+ return Data;
+
+}
+
+/**
+ 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] Data Input Data. Must be the same size as Size parameter.
+
+ @retval UINT16 Value written to register
+**/
+UINT16
+PchPcrWrite16 (
+ IN PCH_SBI_PID Pid,
+ IN UINT32 Offset,
+ IN UINT16 Data
+ )
+{
+#ifndef MDEPKG_NDEBUG
+ ASSERT (PchIsPcrOffsetValid (Offset, 2));
+#endif
+ MmioWrite16 (PCH_PCR_ADDRESS (Pid, Offset), Data);
+
+ return Data;
+}
+
+/**
+ 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] Data Input Data. Must be the same size as Size parameter.
+
+ @retval UINT8 Value written to register
+**/
+UINT8
+PchPcrWrite8 (
+ IN PCH_SBI_PID Pid,
+ IN UINT32 Offset,
+ IN UINT8 Data
+ )
+{
+
+ MmioWrite8 (PCH_PCR_ADDRESS (Pid, Offset), Data);
+
+ return Data;
+}
+
+/**
+ Write PCR register.
+ It programs PCR register and size in 4bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of Port ID.
+ @param[in] AndData AND Data. Must be the same size as Size parameter.
+ @param[in] OrData OR Data. Must be the same size as Size parameter.
+
+ @retval UINT32 Value written to register
+
+**/
+UINT32
+PchPcrAndThenOr32 (
+ IN PCH_SBI_PID Pid,
+ IN UINT32 Offset,
+ IN UINT32 AndData,
+ IN UINT32 OrData
+ )
+{
+ return PchPcrWrite32 (Pid, Offset, (PchPcrRead32 (Pid, Offset) & AndData) | OrData);
+}
+
+/**
+ Write PCR register and read back.
+ The read back ensures the PCR cycle is completed before next operation.
+ It programs PCR register and size in 4bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of Port ID.
+ @param[in] AndData AND Data. Must be the same size as Size parameter.
+ @param[in] OrData OR Data. Must be the same size as Size parameter.
+
+ @retval UINT32 Value read back from the register
+**/
+UINT32
+PchPcrAndThenOr32WithReadback (
+ IN PCH_SBI_PID Pid,
+ IN UINT32 Offset,
+ IN UINT32 AndData,
+ IN UINT32 OrData
+ )
+{
+ PchPcrWrite32 (Pid, Offset, (PchPcrRead32 (Pid, Offset) & AndData) | OrData);
+ return PchPcrRead32 (Pid, Offset);
+}
+
+/**
+ Write PCR register.
+ It programs PCR register and size in 2bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of Port ID.
+ @param[in] AndData AND Data. Must be the same size as Size parameter.
+ @param[in] OrData OR Data. Must be the same size as Size parameter.
+
+ @retval UINT16 Value written to register
+
+**/
+UINT16
+PchPcrAndThenOr16 (
+ IN PCH_SBI_PID Pid,
+ IN UINT32 Offset,
+ IN UINT16 AndData,
+ IN UINT16 OrData
+ )
+{
+ return PchPcrWrite16 (Pid, Offset, (PchPcrRead16 (Pid, Offset) & AndData) | OrData);
+}
+
+/**
+ Write PCR register.
+ It programs PCR register and size in 1bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of Port ID.
+ @param[in] AndData AND Data. Must be the same size as Size parameter.
+ @param[in] OrData OR Data. Must be the same size as Size parameter.
+
+ @retval UINT8 Value written to register
+
+**/
+UINT8
+PchPcrAndThenOr8 (
+ IN PCH_SBI_PID Pid,
+ IN UINT32 Offset,
+ IN UINT8 AndData,
+ IN UINT8 OrData
+ )
+{
+ return PchPcrWrite8 (Pid, Offset, (PchPcrRead8 (Pid, Offset) & AndData) | OrData);
+}
+
+/**
+ Get PCH IP PID number
+
+ @param[in] IpEnum PCH IP in PCH_IP_PID_ENUM
+
+ @retval 0 PID of this IP is not supported
+ !0 PID of the IP.
+**/
+PCH_SBI_PID
+PchPcrGetPid (
+ PCH_IP_PID_ENUM IpEnum
+ )
+{
+ switch (IpEnum) {
+ case PchIpDmi:
+ return PID_DMI;
+ case PchIpIclk:
+ return PID_ICLK;
+ default:
+ ASSERT (FALSE);
+ return PCH_INVALID_PID;
+ }
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/P2sb/Library/PeiDxeSmmPchPcrLib/PeiDxeSmmPchPcrLib.inf b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/P2sb/Library/PeiDxeSmmPchPcrLib/PeiDxeSmmPchPcrLib.inf
new file mode 100644
index 0000000000..2efeba374f
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/P2sb/Library/PeiDxeSmmPchPcrLib/PeiDxeSmmPchPcrLib.inf
@@ -0,0 +1,35 @@
+## @file
+# PCH PCR Library.
+#
+# All function in this library is available for PEI, DXE, and SMM,
+# But do not support UEFI RUNTIME environment call.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiDxeSmmPchPcrLib
+FILE_GUID = 117C8D19-445B-46BF-B624-109F63709375
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = PchPcrLib
+
+
+[LibraryClasses]
+BaseLib
+IoLib
+DebugLib
+PchInfoLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+TigerlakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+PchPcrLib.c
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/P2sb/LibraryPrivate/PeiDxeSmmPchSbiAccessLib/PchSbiAccessLib.c b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/P2sb/LibraryPrivate/PeiDxeSmmPchSbiAccessLib/PchSbiAccessLib.c
new file mode 100644
index 0000000000..8017dee3aa
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/P2sb/LibraryPrivate/PeiDxeSmmPchSbiAccessLib/PchSbiAccessLib.c
@@ -0,0 +1,253 @@
+/** @file
+ PCH SBI access library.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <IndustryStandard/Pci30.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/PciSegmentLib.h>
+#include <Library/PchSbiAccessLib.h>
+#include <Library/PchPciBdfLib.h>
+#include <Register/PchRegs.h>
+#include <Register/P2sbRegs.h>
+
+/**
+ Execute PCH SBI message
+ Take care of that there is no lock protection when using SBI programming in both POST time and SMI.
+ It will clash with POST time SBI programming when SMI happen.
+ Programmer MUST do the save and restore opration while using the PchSbiExecution inside SMI
+ to prevent from racing condition.
+ This function will reveal P2SB and hide P2SB if it's originally hidden. If more than one SBI access
+ needed, it's better to unhide the P2SB before calling and hide it back after done.
+
+ When the return value is "EFI_SUCCESS", the "Response" do not need to be checked as it would have been
+ SBI_SUCCESS. If the return value is "EFI_DEVICE_ERROR", then this would provide additional information
+ when needed.
+
+ @param[in] Pid Port ID of the SBI message
+ @param[in] Offset Offset of the SBI message
+ @param[in] Opcode Opcode
+ @param[in] Posted Posted message
+ @param[in, out] Data32 Read/Write data
+ @param[out] Response Response
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_DEVICE_ERROR Transaction fail
+ @retval EFI_INVALID_PARAMETER Invalid parameter
+ @retval EFI_TIMEOUT Timeout while waiting for response
+**/
+EFI_STATUS
+PchSbiExecution (
+ IN PCH_SBI_PID Pid,
+ IN UINT64 Offset,
+ IN PCH_SBI_OPCODE Opcode,
+ IN BOOLEAN Posted,
+ IN OUT UINT32 *Data32,
+ OUT UINT8 *Response
+ )
+{
+ return PchSbiExecutionEx ( Pid,
+ Offset,
+ Opcode,
+ Posted,
+ 0x000F,
+ 0x0000,
+ 0x0000,
+ Data32,
+ Response
+ );
+}
+
+/**
+ Full function for executing PCH SBI message
+ Take care of that there is no lock protection when using SBI programming in both POST time and SMI.
+ It will clash with POST time SBI programming when SMI happen.
+ Programmer MUST do the save and restore opration while using the PchSbiExecution inside SMI
+ to prevent from racing condition.
+ This function will reveal P2SB and hide P2SB if it's originally hidden. If more than one SBI access
+ needed, it's better to unhide the P2SB before calling and hide it back after done.
+
+ When the return value is "EFI_SUCCESS", the "Response" do not need to be checked as it would have been
+ SBI_SUCCESS. If the return value is "EFI_DEVICE_ERROR", then this would provide additional information
+ when needed.
+
+ @param[in] Pid Port ID of the SBI message
+ @param[in] Offset Offset of the SBI message
+ @param[in] Opcode Opcode
+ @param[in] Posted Posted message
+ @param[in] Fbe First byte enable
+ @param[in] Bar Bar
+ @param[in] Fid Function ID
+ @param[in, out] Data32 Read/Write data
+ @param[out] Response Response
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_DEVICE_ERROR Transaction fail
+ @retval EFI_INVALID_PARAMETER Invalid parameter
+ @retval EFI_TIMEOUT Timeout while waiting for response
+**/
+EFI_STATUS
+PchSbiExecutionEx (
+ IN PCH_SBI_PID Pid,
+ IN UINT64 Offset,
+ IN PCH_SBI_OPCODE Opcode,
+ IN BOOLEAN Posted,
+ IN UINT16 Fbe,
+ IN UINT16 Bar,
+ IN UINT16 Fid,
+ IN OUT UINT32 *Data32,
+ OUT UINT8 *Response
+ )
+{
+ UINT64 P2sbBase;
+ UINTN Timeout;
+ UINT16 SbiStat;
+
+ //
+ // Check opcode valid
+ //
+ switch (Opcode) {
+ case MemoryRead:
+ case MemoryWrite:
+ case PciConfigRead:
+ case PciConfigWrite:
+ case PrivateControlRead:
+ case PrivateControlWrite:
+ case GpioLockUnlock:
+ break;
+ default:
+ return EFI_INVALID_PARAMETER;
+ break;
+ }
+
+ P2sbBase = P2sbPciCfgBase ();
+ if (PciSegmentRead16 (P2sbBase + PCI_VENDOR_ID_OFFSET) == 0xFFFF) {
+ ASSERT (FALSE);
+ return EFI_DEVICE_ERROR;
+ }
+ ///
+ /// BWG Section 2.2.1
+ /// 1. Poll P2SB PCI offset D8h[0] = 0b
+ /// Make sure the previous opeartion is completed.
+ ///
+ Timeout = 0xFFFFFFF;
+ while (Timeout > 0) {
+ SbiStat = PciSegmentRead16 (P2sbBase + R_P2SB_CFG_SBISTAT);
+ if ((SbiStat & B_P2SB_CFG_SBISTAT_INITRDY) == 0) {
+ break;
+ }
+ Timeout--;
+ }
+ if (Timeout == 0) {
+ return EFI_TIMEOUT;
+ }
+ //
+ // Initial Response status
+ //
+ *Response = SBI_INVALID_RESPONSE;
+ SbiStat = 0;
+ ///
+ /// 2. Write P2SB PCI offset D0h[31:0] with Address and Destination Port ID
+ ///
+ PciSegmentWrite32 (P2sbBase + R_P2SB_CFG_SBIADDR, (UINT32) ((Pid << 24) | (UINT16) Offset));
+ ///
+ /// 3. Write P2SB PCI offset DCh[31:0] with extended address, which is expected to be 0 in CNL PCH.
+ ///
+ PciSegmentWrite32 (P2sbBase + R_P2SB_CFG_SBIEXTADDR, (UINT32) RShiftU64 (Offset, 16));
+ ///
+ /// 5. Set P2SB PCI offset D8h[15:8] = 00000110b for read
+ /// Set P2SB PCI offset D8h[15:8] = 00000111b for write
+ //
+ // Set SBISTAT[15:8] to the opcode passed in
+ // Set SBISTAT[7] to the posted passed in
+ //
+ PciSegmentAndThenOr16 (
+ (P2sbBase + R_P2SB_CFG_SBISTAT),
+ (UINT16) ~(B_P2SB_CFG_SBISTAT_OPCODE | B_P2SB_CFG_SBISTAT_POSTED),
+ (UINT16) ((Opcode << 8) | (Posted << 7))
+ );
+ ///
+ /// 6. Write P2SB PCI offset DAh[15:0] = F000h
+ ///
+ //
+ // Set RID[15:0] = Fbe << 12 | Bar << 8 | Fid
+ //
+ PciSegmentWrite16 (
+ (P2sbBase + R_P2SB_CFG_SBIRID),
+ (((Fbe & 0x000F) << 12) | ((Bar & 0x0007) << 8) | (Fid & 0x00FF))
+ );
+
+ switch (Opcode) {
+ case MemoryWrite:
+ case PciConfigWrite:
+ case PrivateControlWrite:
+ case GpioLockUnlock:
+ ///
+ /// 4. Write P2SB PCI offset D4h[31:0] with the intended data accordingly
+ ///
+ PciSegmentWrite32 ((P2sbBase + R_P2SB_CFG_SBIDATA), *Data32);
+ break;
+ default:
+ ///
+ /// 4. Write P2SB PCI offset D4h[31:0] with dummy data such as 0,
+ /// because all D0-DFh register range must be touched in CNL PCH
+ /// for a successful SBI transaction.
+ ///
+ PciSegmentWrite32 ((P2sbBase + R_P2SB_CFG_SBIDATA), 0);
+ break;
+ }
+ ///
+ /// 7. Set P2SB PCI offset D8h[0] = 1b, Poll P2SB PCI offset D8h[0] = 0b
+ ///
+ //
+ // Set SBISTAT[0] = 1b, trigger the SBI operation
+ //
+ PciSegmentOr16 (P2sbBase + R_P2SB_CFG_SBISTAT, (UINT16) B_P2SB_CFG_SBISTAT_INITRDY);
+ //
+ // Poll SBISTAT[0] = 0b, Polling for Busy bit
+ //
+ Timeout = 0xFFFFFFF;
+ while (Timeout > 0) {
+ SbiStat = PciSegmentRead16 (P2sbBase + R_P2SB_CFG_SBISTAT);
+ if ((SbiStat & B_P2SB_CFG_SBISTAT_INITRDY) == 0) {
+ break;
+ }
+ Timeout--;
+ }
+ if (Timeout == 0) {
+ //
+ // If timeout, it's fatal error.
+ //
+ return EFI_TIMEOUT;
+ } else {
+ ///
+ /// 8. Check if P2SB PCI offset D8h[2:1] = 00b for successful transaction
+ ///
+ *Response = (UINT8) ((SbiStat & B_P2SB_CFG_SBISTAT_RESPONSE) >> N_P2SB_CFG_SBISTAT_RESPONSE);
+ if (*Response == SBI_SUCCESSFUL) {
+ switch (Opcode) {
+ case MemoryRead:
+ case PciConfigRead:
+ case PrivateControlRead:
+ ///
+ /// 9. Read P2SB PCI offset D4h[31:0] for SBI data
+ ///
+ *Data32 = PciSegmentRead32 (P2sbBase + R_P2SB_CFG_SBIDATA);
+ break;
+ default:
+ break;
+ }
+ return EFI_SUCCESS;
+ } else if (*Response == SBI_POWERDOWN) {
+ return EFI_NO_RESPONSE;
+ } else {
+ return EFI_DEVICE_ERROR;
+ }
+ }
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/P2sb/LibraryPrivate/PeiDxeSmmPchSbiAccessLib/PeiDxeSmmPchSbiAccessLib.inf b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/P2sb/LibraryPrivate/PeiDxeSmmPchSbiAccessLib/PeiDxeSmmPchSbiAccessLib.inf
new file mode 100644
index 0000000000..4199a0a6c7
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/P2sb/LibraryPrivate/PeiDxeSmmPchSbiAccessLib/PeiDxeSmmPchSbiAccessLib.inf
@@ -0,0 +1,36 @@
+## @file
+# PCH SBI access library.
+#
+# All function in this library is available for PEI, DXE, and SMM,
+# But do not support UEFI RUNTIME environment call.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiDxeSmmPchSbiAccessLib
+FILE_GUID = 96ECB0FB-A975-4DC8-B88A-D90C3378CE87
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = PchSbiAccessLib
+
+
+[LibraryClasses]
+BaseLib
+IoLib
+DebugLib
+PciSegmentLib
+PchPciBdfLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+TigerlakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+PchSbiAccessLib.c
--
2.24.0.windows.2
^ permalink raw reply related [flat|nested] 42+ messages in thread
* [Patch V3 22/40] TigerlakeSiliconPkg/IpBlock: Add PchDmi component
2021-02-05 7:40 [Patch V3 01/40] TigerlakeSiliconPkg: Add package and Include/ConfigBlock headers Heng Luo
` (19 preceding siblings ...)
2021-02-05 7:40 ` [Patch V3 21/40] TigerlakeSiliconPkg/IpBlock: Add P2sb component Heng Luo
@ 2021-02-05 7:40 ` Heng Luo
2021-02-05 7:40 ` [Patch V3 23/40] TigerlakeSiliconPkg/IpBlock: Add PcieRp component Heng Luo
` (17 subsequent siblings)
38 siblings, 0 replies; 42+ messages in thread
From: Heng Luo @ 2021-02-05 7:40 UTC (permalink / raw)
To: devel; +Cc: Sai Chaganty, Nate DeSimone
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3171
Adds the following files:
* IpBlock/PchDmi/IncludePrivate
* IpBlock/PchDmi/LibraryPrivate
Cc: Sai Chaganty <rangasai.v.chaganty@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Signed-off-by: Heng Luo <heng.luo@intel.com>
---
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PchDmi/IncludePrivate/Library/PchDmiLib.h | 175 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PchDmi/LibraryPrivate/PeiDxeSmmPchDmiLib/PchDmi14.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PchDmi/LibraryPrivate/PeiDxeSmmPchDmiLib/PchDmi14.h | 34 ++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PchDmi/LibraryPrivate/PeiDxeSmmPchDmiLib/PchDmiLib.c | 269 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PchDmi/LibraryPrivate/PeiDxeSmmPchDmiLib/PchDmiWithS3Lib.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PchDmi/LibraryPrivate/PeiDxeSmmPchDmiLib/PeiDxeSmmPchDmiLib.inf | 42 ++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PchDmi/LibraryPrivate/PeiDxeSmmPchDmiLib/PeiDxeSmmPchDmiWithS3Lib.inf | 41 +++++++++++++++++++++++++++++++++++++++++
7 files changed, 684 insertions(+)
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PchDmi/IncludePrivate/Library/PchDmiLib.h b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PchDmi/IncludePrivate/Library/PchDmiLib.h
new file mode 100644
index 0000000000..77db69c75a
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PchDmi/IncludePrivate/Library/PchDmiLib.h
@@ -0,0 +1,175 @@
+/** @file
+ Header file for PchDmiLib.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PCH_DMI_LIB_H_
+#define _PCH_DMI_LIB_H_
+
+/**
+ This function checks if DMI Secured Register Lock (SRL) is set
+
+ @retval SRL state
+**/
+BOOLEAN
+IsPchDmiLocked (
+ VOID
+ );
+
+/**
+ Get PCH TCO base address.
+
+ @retval Address Address of TCO base address.
+**/
+UINT16
+PchDmiGetTcoBase (
+ VOID
+ );
+
+/**
+ Set PCH LPC/eSPI generic IO range decoding in DMI
+
+ @param[in] Address Address for generic IO range base address.
+ @param[in] Length Length of generic IO range.
+ @param[in] RangeIndex Index of choosen range
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_UNSUPPORTED DMIC.SRL is set.
+**/
+EFI_STATUS
+PchDmiSetLpcGenIoRange (
+ IN UINT32 Address,
+ IN UINT32 Length,
+ IN UINT32 RangeIndex
+ );
+
+/**
+ Set PCH eSPI eSPI CS1# generic IO range decoding in DMI
+
+ @param[in] Address Address for generic IO range base address.
+ @param[in] Length Length of generic IO range.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_UNSUPPORTED DMIC.SRL is set.
+**/
+EFI_STATUS
+PchDmiSetEspiCs1GenIoRange (
+ IN UINT32 Address,
+ IN UINT32 Length
+ );
+
+/**
+ Set PCH LPC/eSPI memory range decoding in DMI
+
+ @param[in] Address Address for memory base address.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_UNSUPPORTED DMIC.SRL is set.
+**/
+EFI_STATUS
+PchDmiSetLpcMemRange (
+ IN UINT32 Address
+ );
+
+/**
+ Set PCH eSPI CS1# memory range decoding in DMI
+
+ @param[in] Address Address for memory base address.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_UNSUPPORTED DMIC.SRL is set.
+**/
+EFI_STATUS
+PchDmiSetEspiCs1MemRange (
+ IN UINT32 Address
+ );
+
+/**
+ Check if Boot BIOS Strap is set for SPI.
+
+ @retval TRUE Boot BIOS Strap set for SPI
+ @retval FALSE Boot BIOS Strap set for LPC/eSPI
+**/
+BOOLEAN
+PchDmiIsBootBiosStrapSetForSpi (
+ VOID
+ );
+
+/**
+ Set PCH BIOS range decoding in DMI
+ 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
+
+ @param[in] BiosDecodeEnable Bios decode enable setting.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_UNSUPPORTED DMIC.SRL is set.
+**/
+EFI_STATUS
+PchDmiSetBiosDecodeEnable (
+ IN UINT16 BiosDecodeEnable
+ );
+
+/**
+ Set PCH LPC/eSPI IO decode ranges in DMI
+ 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
+PchDmiSetLpcIoDecodeRanges (
+ IN UINT16 LpcIoDecodeRanges
+ );
+
+/**
+ Set PCH LPC/eSPI IO enable decoding in DMI
+
+ @param[in] LpcIoEnableDecoding LPC/eSPI IO enable decoding bit settings.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_UNSUPPORTED DMIC.SRL is set.
+**/
+EFI_STATUS
+PchDmiSetLpcIoEnable (
+ IN UINT16 LpcIoEnableDecoding
+ );
+
+/**
+ Configure PCH DMI Lock
+**/
+VOID
+PchDmiSetLockWithS3BootScript (
+ VOID
+ );
+
+/**
+ Set BIOS interface Lock-Down
+**/
+VOID
+PchDmiSetBiosLockDownWithS3BootScript (
+ VOID
+ );
+#endif // _PCH_DMI_LIB_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PchDmi/LibraryPrivate/PeiDxeSmmPchDmiLib/PchDmi14.c b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PchDmi/LibraryPrivate/PeiDxeSmmPchDmiLib/PchDmi14.c
new file mode 100644
index 0000000000..60bc29c431
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PchDmi/LibraryPrivate/PeiDxeSmmPchDmiLib/PchDmi14.c
@@ -0,0 +1,50 @@
+/** @file
+ This file contains functions for PCH DMI SIP14
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/PchPcrLib.h>
+#include <Library/PchDmiLib.h>
+#include <Library/PchCycleDecodingLib.h>
+#include <Library/PchPcrLib.h>
+#include <Library/PchInfoLib.h>
+#include <Register/PchDmiRegs.h>
+#include <Register/PchDmi14Regs.h>
+#include <Register/PchPcrRegs.h>
+
+/**
+ This function checks if DMI SIP14 Secured Register Lock (SRL) is set
+
+ @retval SRL state
+**/
+BOOLEAN
+IsPchDmi14Locked (
+ VOID
+ )
+{
+ return ((PchPcrRead32 (PID_DMI, R_PCH_DMI14_PCR_DMIC) & B_PCH_DMI14_PCR_DMIC_SRL) != 0);
+}
+
+/**
+ Secure Register Lock data
+
+ @param[out] SrlRegOffset Register offset holding Secure Register Lock setting
+ @param[out] SrlRegMask Mask for Secure Register Lock setting
+**/
+VOID
+PchDmi14SrlRegData (
+ OUT UINT16 *SrlRegOffset,
+ OUT UINT32 *SrlRegMask
+ )
+{
+ *SrlRegMask = B_PCH_DMI14_PCR_DMIC_SRL;
+ *SrlRegOffset = R_PCH_DMI14_PCR_DMIC;
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PchDmi/LibraryPrivate/PeiDxeSmmPchDmiLib/PchDmi14.h b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PchDmi/LibraryPrivate/PeiDxeSmmPchDmiLib/PchDmi14.h
new file mode 100644
index 0000000000..4c19ad82d7
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PchDmi/LibraryPrivate/PeiDxeSmmPchDmiLib/PchDmi14.h
@@ -0,0 +1,34 @@
+/** @file
+ Internal header file for PCH DMI library for SIP14
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef __PCH_DMI_14_H__
+#define __PCH_DMI_14_H__
+
+#include <Library/PchDmiLib.h>
+
+/**
+ This function checks if DMI SIP14 Secured Register Lock (SRL) is set
+
+ @retval SRL state
+**/
+BOOLEAN
+IsPchDmi14Locked (
+ VOID
+ );
+
+/**
+ Secure Register Lock data
+
+ @param[out] SrlRegOffset Register offset holding Secure Register Lock setting
+ @param[out] SrlRegMask Mask for Secure Register Lock setting
+**/
+VOID
+PchDmi14SrlRegData (
+ OUT UINT16 *SrlRegOffset,
+ OUT UINT32 *SrlRegMask
+ );
+
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PchDmi/LibraryPrivate/PeiDxeSmmPchDmiLib/PchDmiLib.c b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PchDmi/LibraryPrivate/PeiDxeSmmPchDmiLib/PchDmiLib.c
new file mode 100644
index 0000000000..972e5145aa
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PchDmi/LibraryPrivate/PeiDxeSmmPchDmiLib/PchDmiLib.c
@@ -0,0 +1,269 @@
+/** @file
+ PCH DMI library.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/PchPcrLib.h>
+#include <Library/PchDmiLib.h>
+#include <Library/PchCycleDecodingLib.h>
+#include <Register/PchPcrRegs.h>
+#include <Register/PchDmiRegs.h>
+#include <Register/PchRegsLpc.h>
+
+#include "PchDmi14.h"
+
+/**
+ This function checks if DMI Secured Register Lock (SRL) is set
+
+ @retval SRL state
+**/
+BOOLEAN
+IsPchDmiLocked (
+ VOID
+ )
+{
+ return IsPchDmi14Locked ();
+}
+
+/**
+ Get PCH TCO base address.
+
+ @retval Address Address of TCO base address.
+**/
+UINT16
+PchDmiGetTcoBase (
+ VOID
+ )
+{
+ //
+ // Read "TCO Base Address" PCR[DMI] + 2778h[15:5]
+ //
+ return (PchPcrRead16 (PID_DMI, R_PCH_DMI_PCR_TCOBASE) & B_PCH_DMI_PCR_TCOBASE_TCOBA);
+}
+
+/**
+ Set PCH LPC/eSPI generic IO range decoding in DMI
+
+ @param[in] Address Address for generic IO range base address.
+ @param[in] Length Length of generic IO range.
+ @param[in] RangeIndex Index of choosen range
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_UNSUPPORTED DMIC.SRL is set.
+**/
+EFI_STATUS
+PchDmiSetLpcGenIoRange (
+ IN UINT32 Address,
+ IN UINT32 Length,
+ IN UINT32 RangeIndex
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Set PCH eSPI eSPI CS1# generic IO range decoding in DMI
+
+ @param[in] Address Address for generic IO range base address.
+ @param[in] Length Length of generic IO range.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_UNSUPPORTED DMIC.SRL is set.
+**/
+EFI_STATUS
+PchDmiSetEspiCs1GenIoRange (
+ IN UINT32 Address,
+ IN UINT32 Length
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Set PCH LPC/eSPI memory range decoding in DMI
+
+ @param[in] Address Address for memory base address.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_UNSUPPORTED DMIC.SRL is set.
+**/
+EFI_STATUS
+PchDmiSetLpcMemRange (
+ IN UINT32 Address
+ )
+{
+ if (IsPchDmiLocked ()) {
+ DEBUG ((DEBUG_ERROR, "%a Error. DMI is locked.\n", __FUNCTION__));
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Program LPC Memory Range, PCR[DMI] + 2740h to the same value programmed in LPC/eSPI PCI Offset 98h.
+ //
+ PchPcrWrite32 (
+ PID_DMI, R_PCH_DMI_PCR_LPCGMR,
+ (Address | B_LPC_CFG_LGMR_LMRD_EN)
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Set PCH eSPI CS1# memory range decoding in DMI
+
+ @param[in] Address Address for memory base address.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_UNSUPPORTED DMIC.SRL is set.
+**/
+EFI_STATUS
+PchDmiSetEspiCs1MemRange (
+ IN UINT32 Address
+ )
+{
+ if (IsPchDmiLocked ()) {
+ DEBUG ((DEBUG_ERROR, "%a Error. DMI is locked.\n", __FUNCTION__));
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Program LPC Memory Range, PCR[DMI] + 27C0h to the same value programmed in eSPI PCI Offset A8h.
+ //
+ PchPcrWrite32 (
+ PID_DMI, R_PCH_DMI_PCR_SEGMR,
+ (Address | B_LPC_CFG_LGMR_LMRD_EN)
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Check if Boot BIOS Strap is set for SPI.
+
+ @retval TRUE Boot BIOS Strap set for SPI
+ @retval FALSE Boot BIOS Strap set for LPC/eSPI
+**/
+BOOLEAN
+PchDmiIsBootBiosStrapSetForSpi (
+ VOID
+ )
+{
+ //
+ // Check General Control and Status (GCS) [10]
+ // '0': SPI
+ // '1': LPC/eSPI
+ //
+ return ((PchPcrRead32 (PID_DMI, R_PCH_DMI_PCR_GCS) & B_PCH_DMI_PCR_BBS) != B_PCH_DMI_PCR_BBS);
+}
+
+/**
+ Set PCH BIOS range decoding in DMI
+ 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
+
+ @param[in] BiosDecodeEnable Bios decode enable setting.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_UNSUPPORTED DMIC.SRL is set.
+**/
+EFI_STATUS
+PchDmiSetBiosDecodeEnable (
+ IN UINT16 BiosDecodeEnable
+ )
+{
+ if (IsPchDmiLocked ()) {
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // program LPC BIOS Decode Enable, PCR[DMI] + 2744h to the same value programmed in LPC or SPI Offset D8h.
+ //
+ PchPcrWrite16 (PID_DMI, R_PCH_DMI_PCR_LPCBDE, BiosDecodeEnable);
+ return EFI_SUCCESS;
+}
+
+/**
+ Set PCH LPC/eSPI IO decode ranges in DMI
+ 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
+PchDmiSetLpcIoDecodeRanges (
+ IN UINT16 LpcIoDecodeRanges
+ )
+{
+ //
+ // This cycle decoding is only allowed to set when DMI is not locked.
+ //
+ if (IsPchDmiLocked ()) {
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // program LPC I/O Decode Ranges, PCR[DMI] + 2770h[15:0] to the same value programmed in LPC/eSPI PCI offset 80h.
+ //
+ PchPcrWrite16 (PID_DMI, R_PCH_DMI_PCR_LPCIOD, LpcIoDecodeRanges);
+ return EFI_SUCCESS;
+}
+
+/**
+ Set PCH LPC/eSPI IO enable decoding in DMI
+
+ @param[in] LpcIoEnableDecoding LPC/eSPI IO enable decoding bit settings.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_UNSUPPORTED DMIC.SRL is set.
+**/
+EFI_STATUS
+PchDmiSetLpcIoEnable (
+ IN UINT16 LpcIoEnableDecoding
+ )
+{
+ //
+ // This cycle decoding is only allowed to set when DMI is not locked.
+ //
+ if (IsPchDmiLocked ()) {
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // program LPC I/O Decode Ranges, PCR[DMI] + 2774h[15:0] to the same value programmed in LPC/eSPI PCI offset 82h.
+ //
+ PchPcrWrite16 (PID_DMI, R_PCH_DMI_PCR_LPCIOE, LpcIoEnableDecoding);
+ return EFI_SUCCESS;
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PchDmi/LibraryPrivate/PeiDxeSmmPchDmiLib/PchDmiWithS3Lib.c b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PchDmi/LibraryPrivate/PeiDxeSmmPchDmiLib/PchDmiWithS3Lib.c
new file mode 100644
index 0000000000..7d6801ee57
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PchDmi/LibraryPrivate/PeiDxeSmmPchDmiLib/PchDmiWithS3Lib.c
@@ -0,0 +1,73 @@
+/** @file
+ PCH DMI library with S3 boot script support.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/PchPcrLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/S3BootScriptLib.h>
+#include <Register/PchPcrRegs.h>
+#include <Register/PchDmiRegs.h>
+
+#include "PchDmi14.h"
+
+/**
+ Configure DMI Lock
+**/
+VOID
+PchDmiSetLockWithS3BootScript (
+ VOID
+ )
+{
+ UINT32 Data32Or;
+ UINT32 Data32And;
+ UINT16 Address;
+
+ Data32And = 0xFFFFFFFF;
+
+ PchDmi14SrlRegData (&Address, &Data32Or);
+
+ PchPcrAndThenOr32 (
+ PID_DMI, Address,
+ Data32And,
+ Data32Or
+ );
+ PCH_PCR_BOOT_SCRIPT_READ_WRITE (
+ S3BootScriptWidthUint32,
+ PID_DMI, Address,
+ &Data32Or,
+ &Data32And
+ );
+}
+
+/**
+ Set BIOS interface Lock-Down
+**/
+VOID
+PchDmiSetBiosLockDownWithS3BootScript (
+ VOID
+ )
+{
+ UINT32 Data32Or;
+ UINT32 Data32And;
+
+ //
+ // Set BIOS Lock-Down (BILD)
+ // When set, prevents GCS.BBS from being changed
+ //
+ Data32And = 0xFFFFFFFF;
+ Data32Or = B_PCH_DMI_PCR_BILD;
+ PchPcrAndThenOr32 (PID_DMI, R_PCH_DMI_PCR_GCS, Data32And, Data32Or);
+ PCH_PCR_BOOT_SCRIPT_READ_WRITE (
+ S3BootScriptWidthUint32,
+ PID_DMI, R_PCH_DMI_PCR_GCS,
+ &Data32Or,
+ &Data32And
+ );
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PchDmi/LibraryPrivate/PeiDxeSmmPchDmiLib/PeiDxeSmmPchDmiLib.inf b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PchDmi/LibraryPrivate/PeiDxeSmmPchDmiLib/PeiDxeSmmPchDmiLib.inf
new file mode 100644
index 0000000000..d33310dd76
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PchDmi/LibraryPrivate/PeiDxeSmmPchDmiLib/PeiDxeSmmPchDmiLib.inf
@@ -0,0 +1,42 @@
+## @file
+# Component description file for the PeiDxeSmmPchDmiLib
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiDxeSmmPchDmiLib
+FILE_GUID = 067DC1C4-2668-4F06-9921-307514B66B34
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = PchDmiLib
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[LibraryClasses]
+ BaseLib
+ IoLib
+ DebugLib
+ PchInfoLib
+ PchPcrLib
+
+[Packages]
+ MdePkg/MdePkg.dec
+ TigerlakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+ PchDmiLib.c
+ PchDmi14.c
+ PchDmi14.h
+
+[Guids]
+ gPchDmiConfigGuid ## CONSUMES
+
+[Pcd]
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PchDmi/LibraryPrivate/PeiDxeSmmPchDmiLib/PeiDxeSmmPchDmiWithS3Lib.inf b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PchDmi/LibraryPrivate/PeiDxeSmmPchDmiLib/PeiDxeSmmPchDmiWithS3Lib.inf
new file mode 100644
index 0000000000..9381a7b5fd
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PchDmi/LibraryPrivate/PeiDxeSmmPchDmiLib/PeiDxeSmmPchDmiWithS3Lib.inf
@@ -0,0 +1,41 @@
+## @file
+# Component description file for the PeiDxeSmmPchDmiWithS3Lib
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiDxeSmmPchDmiWithS3Lib
+FILE_GUID = 32CCA047-6AF0-46FF-83DA-32BA62484075
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = PchDmiWithS3Lib
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[LibraryClasses]
+ BaseLib
+ IoLib
+ DebugLib
+ PchPcrLib
+ PchInfoLib
+ S3BootScriptLib
+ PchDmiLib
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ TigerlakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+ PchDmiWithS3Lib.c
+ PchDmi14.h
+
+[pcd]
--
2.24.0.windows.2
^ permalink raw reply related [flat|nested] 42+ messages in thread
* [Patch V3 23/40] TigerlakeSiliconPkg/IpBlock: Add PcieRp component
2021-02-05 7:40 [Patch V3 01/40] TigerlakeSiliconPkg: Add package and Include/ConfigBlock headers Heng Luo
` (20 preceding siblings ...)
2021-02-05 7:40 ` [Patch V3 22/40] TigerlakeSiliconPkg/IpBlock: Add PchDmi component Heng Luo
@ 2021-02-05 7:40 ` Heng Luo
2021-02-05 7:40 ` [Patch V3 24/40] TigerlakeSiliconPkg/IpBlock: Add Pmc component Heng Luo
` (16 subsequent siblings)
38 siblings, 0 replies; 42+ messages in thread
From: Heng Luo @ 2021-02-05 7:40 UTC (permalink / raw)
To: devel; +Cc: Sai Chaganty, Nate DeSimone
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3171
Adds the following files:
* IpBlock/PcieRp/IncludePrivate
* IpBlock/PcieRp/Library
* IpBlock/PcieRp/LibraryPrivate
Cc: Sai Chaganty <rangasai.v.chaganty@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Signed-off-by: Heng Luo <heng.luo@intel.com>
---
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PcieRp/IncludePrivate/Library/DxePchPcieRpPolicyLib.h | 55 ++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PcieRp/IncludePrivate/Library/PciExpressHelpersLib.h | 173 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PcieRp/IncludePrivate/Library/PcieRpLib.h | 109 ++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PcieRp/IncludePrivate/Register/PcieSipRegs.h | 45 ++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PcieRp/Library/BasePcieHelperLib/BasePcieHelperLib.c | 315 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PcieRp/Library/BasePcieHelperLib/BasePcieHelperLib.inf | 37 +++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PcieRp/Library/PeiDxeSmmPchPcieRpLib/PchPcieRpLib.c | 69 ++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PcieRp/Library/PeiDxeSmmPchPcieRpLib/PchPcieRpLibInternal.h | 20 +++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PcieRp/Library/PeiDxeSmmPchPcieRpLib/PchPcieRpLibVer2.c | 128 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PcieRp/Library/PeiDxeSmmPchPcieRpLib/PeiDxeSmmPchPcieRpLibVer2.inf | 39 +++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PcieRp/LibraryPrivate/DxePchPcieRpPolicyLib/DxePchPcieRpPolicyLib.c | 179 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PcieRp/LibraryPrivate/DxePchPcieRpPolicyLib/DxePchPcieRpPolicyLib.inf | 30 ++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PcieRp/LibraryPrivate/PciExpressHelpersLibrary/PciExpressHelpersLibrary.c | 1997 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PcieRp/LibraryPrivate/PciExpressHelpersLibrary/PciExpressHelpersLibrary.h | 40 ++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PcieRp/LibraryPrivate/PciExpressHelpersLibrary/PeiDxeSmmPciExpressHelpersLib.inf | 49 ++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PcieRp/LibraryPrivate/PcieClientRpLib/PcieClientRpLib.c | 247 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PcieRp/LibraryPrivate/PcieClientRpLib/PcieClientRpLib.inf | 43 +++++++++++++++++++
17 files changed, 3575 insertions(+)
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PcieRp/IncludePrivate/Library/DxePchPcieRpPolicyLib.h b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PcieRp/IncludePrivate/Library/DxePchPcieRpPolicyLib.h
new file mode 100644
index 0000000000..1dea61388e
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PcieRp/IncludePrivate/Library/DxePchPcieRpPolicyLib.h
@@ -0,0 +1,55 @@
+/** @file
+ DXE PcieRp policy library.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _DXE_PCH_PCIERP_POLICY_LIB_H_
+#define _DXE_PCH_PCIERP_POLICY_LIB_H_
+
+#include <Protocol/PchPolicy.h>
+
+/**
+ Load DXE Config block default for Pch PCIE RP
+
+ @param[in] ConfigBlockPointer Pointer to config block
+**/
+VOID
+LoadPchPcieRpDxeConfigDefault (
+ IN VOID *ConfigBlockPointer
+ );
+
+/**
+ Print PCIE_RP_DXE_CONFIG.
+
+ @param[in] PchPolicy Pointer to a PCH_POLICY_PROTOCOL
+**/
+VOID
+PchPcieRpDxePrintConfig (
+ IN PCH_POLICY_PROTOCOL *PchPolicy
+ );
+
+/**
+ Get PchPcieRp config block table size.
+
+ @retval Size of config block
+**/
+UINT16
+PchPcieRpDxeGetConfigBlockTotalSize (
+ VOID
+ );
+
+/**
+ Add PchPcieRp ConfigBlock.
+
+ @param[in] ConfigBlockTableAddress The pointer to config block table
+
+ @retval EFI_SUCCESS The policy default is initialized.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create buffer
+**/
+EFI_STATUS
+PchPcieRpDxeAddConfigBlock (
+ IN VOID *ConfigBlockTableAddress
+ );
+
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PcieRp/IncludePrivate/Library/PciExpressHelpersLib.h b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PcieRp/IncludePrivate/Library/PciExpressHelpersLib.h
new file mode 100644
index 0000000000..d7ca34dc38
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PcieRp/IncludePrivate/Library/PciExpressHelpersLib.h
@@ -0,0 +1,173 @@
+/** @file
+ Header file for PCI Express helpers library
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PCI_EXPRESS_HELPERS_LIB_H_
+#define _PCI_EXPRESS_HELPERS_LIB_H_
+
+#include <PchPolicyCommon.h>
+#include <Library/PcieRpLib.h>
+
+typedef enum {
+ TpoScale2us,
+ TpoScale10us,
+ TpoScale100us,
+ TpoScaleMax
+} T_PO_SCALE;
+//
+// This structure keeps segment:bus:device:function coordinates of a PCIe device
+// in a single variable. PcieCap is offset to PCI Express capabilities.
+//
+typedef struct {
+ UINT32 Seg : 8;
+ UINT32 Bus : 8;
+ UINT32 Dev : 5;
+ UINT32 Func : 3;
+ UINT32 PcieCap : 8;
+} SBDF;
+
+/*
+ Converts Tpower_on from value:scale notation to microseconds
+
+ @param[in] TpoScale T power on scale
+ @param[in] TpoValue T power on value
+
+ @retval number of microseconds
+*/
+UINT32
+TpoToUs (
+ UINT32 TpoScale,
+ UINT32 TpoValue
+ );
+
+/**
+PCIe controller Sku.
+**/
+
+typedef enum {
+ EnumPchPcie = 0,
+ EnumiTbtPcie = 1,
+ EnumCpuPcie = 2,
+ EnumPciSkuMax = 3
+} PCI_SKU;
+
+/*
+ Initializes the following features in rootport and devices behind it:
+ Maximum Payload Size (generic)
+ Rootport packet split (proprietary)
+ EonOfInterrupt forwarding (proprietary)
+ Common Clock Configuration (generic)
+
+ Generic: any code written according to PCIE Express base specification can do that.
+ Proprietary: code uses registers and features that are specific to Intel silicon
+ and probably only this Reference Code knows how to handle that.
+
+ If OEM implemented generic feature enabling in his platform code or trusts Operating System
+ to do it, then those features can be deleted from here.
+
+ CCC requires link retrain, which takes a while. CCC must happen before L0s/L1 programming.
+ If there was guarantee no code would access PCI while links retrain, it would be possible to skip this waiting
+
+ @param[in] RpSegment address of rootport on PCIe
+ @param[in] RpBus address of rootport on PCIe
+ @param[in] RpDevice address of rootport on PCIe
+ @param[in] RpFunction address of rootport on PCIe
+ @param[in] BusMin minimum Bus number that can be assigned below this rootport
+ @param[in] BusMax maximum Bus number that can be assigned below this rootport
+*/
+VOID
+RootportDownstreamConfiguration (
+ UINT8 RpSegment,
+ UINT8 RpBus,
+ UINT8 RpDevice,
+ UINT8 RpFunction,
+ UINT8 BusMin,
+ UINT8 BusMax,
+ PCI_SKU PciSku
+ );
+
+/*
+ Configures the following power-management related features in rootport and devices behind it:
+ LTR limit (generic)
+ LTR override (proprietary)
+ Clock Power Management (generic)
+ L1 substates (generic except for the override table)
+ L1.LOW substate (proprietary)
+ L0s and L1 (generic)
+
+ Generic: any code written according to PCIE Express base specification can do that.
+ Proprietary: code uses registers and features that are specific to Intel silicon
+ and probably only this Reference Code knows how to handle that.
+
+ If OEM implemented generic feature enabling in his platform code or trusts Operating System
+ to do it, then those features can be deleted from here.
+
+ @param[in] RpSegment address of rootport on PCIe
+ @param[in] RpBus address of rootport on PCIe
+ @param[in] RpDevice address of rootport on PCIe
+ @param[in] RpFunction address of rootport on PCIe
+ @param[in] BusMin minimal Bus number that can be assigned below this rootport
+ @param[in] BusMax maximum Bus number that can be assigned below this rootport
+ @param[in] PcieRpCommonConfig a pointer to Pcie Root Port Common Config
+ @param[in] AspmOverrideTableSize size of override array
+ @param[in] AspmOverrideTable array of device that need exceptions in configuration
+*/
+VOID
+RootportDownstreamPmConfiguration (
+ UINT8 RpSegment,
+ UINT8 RpBus,
+ UINT8 RpDevice,
+ UINT8 RpFunction,
+ UINT8 BusMin,
+ UINT8 BusMax,
+ PCIE_ROOT_PORT_COMMON_CONFIG *PcieRpCommonConfig,
+ UINT32 AspmOverrideTableSize,
+ PCH_PCIE_DEVICE_OVERRIDE *AspmOverrideTable
+ );
+
+typedef struct {
+ UINT32 MaxSnoopLatencyValue : 10;
+ UINT32 MaxSnoopLatencyScale : 3;
+ UINT32 MaxNoSnoopLatencyValue : 10;
+ UINT32 MaxNoSnoopLatencyScale : 3;
+ UINT32 Reserved : 6;
+} LTR_LIMIT;
+
+/**
+ Checks if given PCI device is capable of Latency Tolerance Reporting
+
+ @param[in] Sbdf device's segment:bus:device:function coordinates
+
+ @retval TRUE if yes
+**/
+BOOLEAN
+IsLtrCapable (
+ SBDF Sbdf
+ );
+
+/**
+ Returns combination of two LTR override values
+ The resulting LTR override separately chooses stricter limits for snoop and nosnoop
+
+ @param[in] LtrA LTR override values to be combined
+ @param[in] LtrB LTR override values to be combined
+
+ @retval LTR override value
+**/
+LTR_OVERRIDE
+CombineLtr (
+ LTR_OVERRIDE LtrA,
+ LTR_OVERRIDE LtrB
+ );
+
+/**
+ Extended Virtual Channel Configuration
+**/
+typedef struct {
+ UINT16 CapOffset;
+ UINT8 ExtVcCount;
+} MULTI_VC_SUPPORT;
+
+#endif // _PCI_EXPRESS_HELPERS_LIB_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PcieRp/IncludePrivate/Library/PcieRpLib.h b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PcieRp/IncludePrivate/Library/PcieRpLib.h
new file mode 100644
index 0000000000..ed75e438c7
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PcieRp/IncludePrivate/Library/PcieRpLib.h
@@ -0,0 +1,109 @@
+/** @file
+ Header file for PCH PCI Express helpers library
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PCIE_RP_LIB_
+#define _PCIE_RP_LIB_
+
+#include <PchPolicyCommon.h>
+
+typedef struct {
+ UINT32 MaxSnoopLatencyValue : 10;
+ UINT32 MaxSnoopLatencyScale : 3;
+ UINT32 MaxSnoopLatencyRequirement : 1;
+ UINT32 MaxNoSnoopLatencyValue : 10;
+ UINT32 MaxNoSnoopLatencyScale : 3;
+ UINT32 MaxNoSnoopLatencyRequirement : 1;
+ UINT32 ForceOverride : 1;
+} LTR_OVERRIDE;
+
+/**
+ Get PCIe port number for enabled Root Port.
+
+ @param[in] RpBase Root Port pci segment base address
+
+ @retval Root Port number (1 based)
+**/
+UINT32
+PciePortNum (
+ IN UINT64 RpBase
+ );
+
+/**
+ Get PCIe root port index
+ @param[in] RpBase Root Port pci segment base address
+ @return Root Port index (0 based)
+**/
+UINT32
+PciePortIndex (
+ IN UINT64 RpBase
+ );
+
+/**
+ This function checks whether PHY lane power gating is enabled on the port.
+
+ @param[in] RpBase Root Port base address
+
+ @retval TRUE PHY power gating is enabled
+ @retval FALSE PHY power gating disabled
+**/
+BOOLEAN
+PcieIsPhyLanePgEnabled (
+ IN UINT64 RpBase
+ );
+
+/**
+ Configures Root Port packet split.
+
+ @param[in] Segment,Bus,Device,Function address of currently visited PCIe device
+ @param[in] Mps maximum packet size
+**/
+VOID
+ConfigureRpPacketSplit (
+ UINT64 RpBase,
+ UINT8 Mps
+ );
+
+/**
+ Configures LTR override in Root Port's proprietary registers.
+
+ @param[in] Segment,Bus,Device,Function address of currently visited PCIe device
+ @param[in] LtrConfig Root Port LTR configuration
+ @param[in] AspmOverride combination of LTR override values from all devices under this Root Port
+**/
+VOID
+ConfigureRpLtrOverride (
+ UINT64 RpBase,
+ UINT32 DevNum,
+ LTR_OVERRIDE *TreeLtr,
+ PCIE_LTR_CONFIG *LtrConfig
+ );
+
+/**
+ This function configures EOI message forwarding for PCIe port.
+ If there's an IoAPIC behind this port, forwarding will be enabled
+ Otherwise it will be disabled to minimize bus traffic
+
+ @param[in] Segment,Bus,Device,Function address of currently visited PCIe device
+ @param[in] IoApicPresent TRUE if there's IoAPIC behind this Root Port
+**/
+VOID
+ConfigureEoiForwarding (
+ UINT64 RpBase,
+ BOOLEAN IoApicPresent
+ );
+
+/**
+ Configures proprietary parts of L1 substates configuration in Root Port
+
+ @param[in] RpSbdf segment:bus:device:function coordinates of Root Port
+ @param[in] LtrCapable TRUE if Root Port is LTR capable
+**/
+VOID
+L1ssProprietaryConfiguration (
+ UINT64 RpBase,
+ BOOLEAN LtrCapable
+ );
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PcieRp/IncludePrivate/Register/PcieSipRegs.h b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PcieRp/IncludePrivate/Register/PcieSipRegs.h
new file mode 100644
index 0000000000..1fc470b8ba
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PcieRp/IncludePrivate/Register/PcieSipRegs.h
@@ -0,0 +1,45 @@
+/** @file
+ Register names for PCIe SIP specific registers
+
+ Conventions:
+
+ - Register definition format:
+ Prefix_[GenerationName]_[ComponentName]_SubsystemName_RegisterSpace_RegisterName
+ - Prefix:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register size
+ Definitions beginning with "N_" are the bit position
+ - [GenerationName]:
+ Three letter acronym of the generation is used (e.g. SKL,KBL,CNL etc.).
+ Register name without GenerationName applies to all generations.
+ - [ComponentName]:
+ This field indicates the component name that the register belongs to (e.g. PCH, SA etc.)
+ Register name without ComponentName applies to all components.
+ Register that is specific to -LP denoted by "_PCH_LP_" in component name.
+ - SubsystemName:
+ This field indicates the subsystem name of the component that the register belongs to
+ (e.g. PCIE, USB, SATA, GPIO, PMC etc.).
+ - RegisterSpace:
+ MEM - MMIO space register of subsystem.
+ IO - IO space register of subsystem.
+ PCR - Private configuration register of subsystem.
+ CFG - PCI configuration space register of subsystem.
+ - RegisterName:
+ Full register name.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _PCIE_SIP_RP_REGS_H_
+#define _PCIE_SIP_RP_REGS_H_
+
+#include <PcieRegs.h>
+
+#define R_PCIE_CFG_CCFG 0xD0
+#define B_PCIE_CFG_CCFG_UNRS (BIT6 | BIT5 | BIT4)
+#define N_PCIE_CFG_CCFG_UNRS 4
+
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PcieRp/Library/BasePcieHelperLib/BasePcieHelperLib.c b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PcieRp/Library/BasePcieHelperLib/BasePcieHelperLib.c
new file mode 100644
index 0000000000..1b3e629431
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PcieRp/Library/BasePcieHelperLib/BasePcieHelperLib.c
@@ -0,0 +1,315 @@
+/** @file
+ This file contains routines that support PCI Express initialization
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include <Library/PcieHelperLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <PcieRegs.h>
+
+#define ASPM_L1_NO_LIMIT 0xFF
+#define LINK_RETRAIN_WAIT_TIME 1000 // microseconds
+
+/**
+ Finds the Offset to a given Capabilities ID
+ Each capability has an ID and a pointer to next Capability, so they form a linked list.
+ This function walks the list of Capabilities present in device's pci cfg. If requested capability
+ can be found, its offset is returned.
+ If the capability can't be found or if device doesn't exist, function returns 0
+ CAPID list:
+ 0x01 = PCI Power Management Interface
+ 0x04 = Slot Identification
+ 0x05 = MSI Capability
+ 0x10 = PCI Express Capability
+
+ @param[in] DeviceBase device's base address
+ @param[in] CapId CAPID to search for
+
+ @retval 0 CAPID not found (this includes situation where device doesn't exit)
+ @retval Other CAPID found, Offset of desired CAPID
+**/
+UINT8
+PcieBaseFindCapId (
+ IN UINT64 DeviceBase,
+ IN UINT8 CapId
+ )
+{
+ UINT8 CapHeaderOffset;
+ UINT8 CapHeaderId;
+ UINT16 Data16;
+ //
+ // We do not explicitly check if device exists to save time and avoid unnecessary PCI access
+ // If the device doesn't exist, check for CapHeaderId != 0xFF will fail and function will return offset 0
+ //
+ if ((PciSegmentRead8 (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 ((PciSegmentRead8 (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 = PciSegmentRead8 (DeviceBase + CapHeaderOffset) & ((UINT8) ~(BIT0 | BIT1));
+ while (CapHeaderOffset != 0 && CapHeaderId != 0xFF) {
+ Data16 = PciSegmentRead16 (DeviceBase + CapHeaderOffset);
+ CapHeaderId = (UINT8)(Data16 & 0xFF);
+ 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 = (UINT8)(Data16 >> 8);
+ }
+ return 0;
+ }
+}
+
+/**
+ 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] Segment Pci Segment Number
+ @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 Segment,
+ IN UINT8 Bus,
+ IN UINT8 Device,
+ IN UINT8 Function,
+ IN UINT8 CapId
+ )
+{
+ UINT64 DeviceBase;
+
+ DeviceBase = PCI_SEGMENT_LIB_ADDRESS (Segment, Bus, Device, Function, 0);
+ return PcieBaseFindCapId (DeviceBase, CapId);
+}
+
+/**
+ 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] DeviceBase device base address
+ @param[in] CapId Extended CAPID to search for
+
+ @retval 0 CAPID not found, this includes situation where device doesn't exist
+ @retval Other CAPID found, Offset of desired CAPID
+**/
+UINT16
+PcieBaseFindExtendedCapId (
+ IN UINT64 DeviceBase,
+ IN UINT16 CapId
+ )
+{
+ UINT16 CapHeaderOffset;
+ UINT16 CapHeaderId;
+ ///
+ /// 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_PCIE_CFG_EXCAP_OFFSET;
+ while (CapHeaderOffset != 0 && CapHeaderId != MAX_UINT16) {
+ CapHeaderId = PciSegmentRead16 (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 = (PciSegmentRead16 (DeviceBase + CapHeaderOffset + 2) >> 4) & ((UINT16) ~(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] Segment Pci Segment Number
+ @param[in] Bus Pci Bus Number
+ @param[in] Device Pci Device Number
+ @param[in] Function Pci Function Number
+ @param[in] CapId Extended CAPID to search for
+
+ @retval 0 CAPID not found, this includes situation where device doesn't exist
+ @retval Other CAPID found, Offset of desired CAPID
+**/
+UINT16
+PcieFindExtendedCapId (
+ IN UINT8 Segment,
+ IN UINT8 Bus,
+ IN UINT8 Device,
+ IN UINT8 Function,
+ IN UINT16 CapId
+ )
+{
+ UINT64 DeviceBase;
+
+ DeviceBase = PCI_SEGMENT_LIB_ADDRESS (Segment, Bus, Device, Function, 0);
+ return PcieBaseFindExtendedCapId (DeviceBase, CapId);
+}
+
+/**
+ Checks if PCI device at given address exists
+
+ @param[in] Base device's base address
+
+ @retval TRUE if exists
+**/
+BOOLEAN
+IsDevicePresent (
+ UINT64 Base
+ )
+{
+ if (PciSegmentRead16 (Base) == 0xFFFF) {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**
+ Checks if device is a multifunction device
+ Besides comparing Multifunction bit (BIT7) it checks if contents of HEADER_TYPE register
+ make sense (header != 0xFF) to prevent false positives when called on devices which do not exist
+
+ @param[in] Base device's base address
+
+ @retval TRUE if multifunction; FALSE otherwise
+**/
+BOOLEAN
+IsMultifunctionDevice (
+ UINT64 Base
+ )
+{
+ UINT8 HeaderType;
+ HeaderType = PciSegmentRead8(Base + PCI_HEADER_TYPE_OFFSET);
+ if ((HeaderType == 0xFF) || ((HeaderType & HEADER_TYPE_MULTI_FUNCTION) == 0)) {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**
+ Checks device's Slot Clock Configuration
+
+ @param[in] Base device's base address
+ @param[in] PcieCapOffset devices Pci express capability list register offset
+
+ @retval TRUE when device uses slot clock, FALSE otherwise
+**/
+BOOLEAN
+GetScc (
+ UINT64 Base,
+ UINT8 PcieCapOffset
+ )
+{
+ return !!(PciSegmentRead16 (Base + PcieCapOffset + R_PCIE_LSTS_OFFSET) & B_PCIE_LSTS_SCC);
+}
+
+/**
+ Sets Common Clock Configuration bit for given device.
+
+ @param[in] PcieCapOffset devices Pci express capability list register offset
+ @param[in] Base device's base address
+**/
+VOID
+EnableCcc (
+ UINT64 Base,
+ UINT8 PcieCapOffset
+ )
+{
+ PciSegmentOr8 (Base + PcieCapOffset + R_PCIE_LCTL_OFFSET, B_PCIE_LCTL_CCC);
+}
+
+/**
+ Retrains link behind given device.
+ It only makes sense to call it for downstream ports. If called for upstream port nothing will happen.
+ If WaitUntilDone is TRUE function will wait until link retrain had finished, otherwise it will return immediately.
+ Link must finish retrain before software can access the device on the other side. If it's not going to access it
+ then considerable time can be saved by not waiting here.
+
+ @param[in] Base device's base address
+ @param[in] PcieCapOffset devices Pci express capability list register offset
+ @param[in] WaitUntilDone when TRUE, function waits until link has retrained
+**/
+VOID
+RetrainLink (
+ UINT64 Base,
+ UINT8 PcieCapOffset,
+ BOOLEAN WaitUntilDone
+ )
+{
+ UINT16 LinkTraining;
+ UINT32 TimeoutUs;
+
+ TimeoutUs = LINK_RETRAIN_WAIT_TIME;
+ //
+ // Before triggering link retrain make sure it's not already retraining. Otherwise
+ // settings recently entered in LCTL register might go unnoticed
+ //
+ do {
+ LinkTraining = (PciSegmentRead16 (Base + PcieCapOffset + R_PCIE_LSTS_OFFSET) & B_PCIE_LSTS_LT);
+ TimeoutUs--;
+ } while (LinkTraining && (TimeoutUs != 0));
+
+ PciSegmentOr8 (Base + PcieCapOffset + R_PCIE_LCTL_OFFSET, B_PCIE_LCTL_RL);
+
+ TimeoutUs = LINK_RETRAIN_WAIT_TIME;
+ if (WaitUntilDone) {
+ do {
+ LinkTraining = (PciSegmentRead16 (Base + PcieCapOffset + R_PCIE_LSTS_OFFSET) & B_PCIE_LSTS_LT);
+ TimeoutUs--;
+ } while (LinkTraining && (TimeoutUs != 0));
+ }
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PcieRp/Library/BasePcieHelperLib/BasePcieHelperLib.inf b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PcieRp/Library/BasePcieHelperLib/BasePcieHelperLib.inf
new file mode 100644
index 0000000000..458a540859
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PcieRp/Library/BasePcieHelperLib/BasePcieHelperLib.inf
@@ -0,0 +1,37 @@
+## @file
+# Component description file for the BasePcieHelperLib
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = BasePcieHelperLib
+FILE_GUID = 568F5812-A9A8-4A4A-AD4D-471DD5F0BC11
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = BasePcieHelperLib
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+
+
+[LibraryClasses]
+DebugLib
+PciSegmentLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+TigerlakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+BasePcieHelperLib.c
+
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PcieRp/Library/PeiDxeSmmPchPcieRpLib/PchPcieRpLib.c b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PcieRp/Library/PeiDxeSmmPchPcieRpLib/PchPcieRpLib.c
new file mode 100644
index 0000000000..153c073093
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PcieRp/Library/PeiDxeSmmPchPcieRpLib/PchPcieRpLib.c
@@ -0,0 +1,69 @@
+/** @file
+ PCIE root port library.
+ All function in this library is available for PEI, DXE, and SMM,
+ But do not support UEFI RUNTIME environment call.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/PciSegmentLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/PchPcrLib.h>
+#include <Library/PchPcieRpLib.h>
+#include <PcieRegs.h>
+#include <Register/PchRegs.h>
+#include <PchPcieRpInfo.h>
+#include <Register/PchPcieRpRegs.h>
+#include <Register/PchPcrRegs.h>
+#include <Library/PchPciBdfLib.h>
+
+#include "PchPcieRpLibInternal.h"
+
+/**
+ Gets pci segment base address of PCIe root port.
+
+ @param RpIndex Root Port Index (0 based)
+ @return PCIe port base address.
+**/
+UINT64
+PchPcieBase (
+ IN UINT32 RpIndex
+ )
+{
+ return PchPcieRpPciCfgBase (RpIndex);
+}
+
+/**
+ Determines whether L0s is supported on current stepping.
+
+ @return TRUE if L0s is supported, FALSE otherwise
+**/
+BOOLEAN
+PchIsPcieL0sSupported (
+ VOID
+ )
+{
+ return TRUE;
+}
+
+/**
+ Some early PCH steppings require Native ASPM to be disabled due to hardware issues:
+ - RxL0s exit causes recovery
+ - Disabling PCIe L0s capability disables L1
+ Use this function to determine affected steppings.
+
+ @return TRUE if Native ASPM is supported, FALSE otherwise
+**/
+BOOLEAN
+PchIsPcieNativeAspmSupported (
+ VOID
+ )
+{
+ return PchIsPcieL0sSupported ();
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PcieRp/Library/PeiDxeSmmPchPcieRpLib/PchPcieRpLibInternal.h b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PcieRp/Library/PeiDxeSmmPchPcieRpLib/PchPcieRpLibInternal.h
new file mode 100644
index 0000000000..1766cff618
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PcieRp/Library/PeiDxeSmmPchPcieRpLib/PchPcieRpLibInternal.h
@@ -0,0 +1,20 @@
+/** @file
+ PCIE root port library.
+ All function in this library is available for PEI, DXE, and SMM,
+ But do not support UEFI RUNTIME environment call.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _PCH_PCIE_RP_LIB_INTERNAL_H_
+#define _PCH_PCIE_RP_LIB_INTERNAL_H_
+
+typedef struct {
+ UINT8 DevNum;
+ UINT8 Pid;
+ UINT8 RpNumBase;
+} PCH_PCIE_CONTROLLER_INFO;
+
+#endif
+
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PcieRp/Library/PeiDxeSmmPchPcieRpLib/PchPcieRpLibVer2.c b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PcieRp/Library/PeiDxeSmmPchPcieRpLib/PchPcieRpLibVer2.c
new file mode 100644
index 0000000000..df90a87df7
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PcieRp/Library/PeiDxeSmmPchPcieRpLib/PchPcieRpLibVer2.c
@@ -0,0 +1,128 @@
+/** @file
+ PCIE root port library.
+ All function in this library is available for PEI, DXE, and SMM,
+ But do not support UEFI RUNTIME environment call.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/PciSegmentLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/PchPcrLib.h>
+#include <Library/PchPcieRpLib.h>
+#include <PcieRegs.h>
+#include <Register/PchRegs.h>
+#include <PchBdfAssignment.h>
+#include <PchPcieRpInfo.h>
+#include <Register/PchPcieRpRegs.h>
+#include <Register/PchPcrRegs.h>
+
+#include "PchPcieRpLibInternal.h"
+
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_PCIE_CONTROLLER_INFO mPchPcieControllerInfo[] = {
+ { PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_1, PID_SPA, 0 },
+ { PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_5, PID_SPB, 4 },
+ { PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_9, PID_SPC, 8 },
+ { PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_13, PID_SPD, 12 },
+ { PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_17, PID_SPE, 16 }, // PCH-H only
+ { PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_21, PID_SPF, 20 } // PCH-H only
+};
+
+/**
+ Get Pch 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
+GetPchPcieRpDevFun (
+ IN UINTN RpNumber,
+ OUT UINTN *RpDev,
+ OUT UINTN *RpFun
+ )
+{
+ UINTN Index;
+ UINTN FuncIndex;
+ UINT32 PciePcd;
+
+ if (RpNumber >= GetPchMaxPciePortNum ()) {
+ DEBUG ((DEBUG_ERROR, "GetPchPcieRpDevFun invalid RpNumber %x", RpNumber));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Index = RpNumber / PCH_PCIE_CONTROLLER_PORTS;
+ FuncIndex = RpNumber - mPchPcieControllerInfo[Index].RpNumBase;
+ *RpDev = mPchPcieControllerInfo[Index].DevNum;
+ PciePcd = PchPcrRead32 (mPchPcieControllerInfo[Index].Pid, R_SPX_PCR_PCD);
+ *RpFun = (PciePcd >> (FuncIndex * S_SPX_PCR_PCD_RP_FIELD)) & B_SPX_PCR_PCD_RP1FN;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Get Root Port physical Number by Pch 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 physical Root Port index (0-based)
+
+ @retval EFI_SUCCESS Physical root port is retrieved
+**/
+EFI_STATUS
+EFIAPI
+GetPchPcieRpNumber (
+ IN UINTN RpDev,
+ IN UINTN RpFun,
+ OUT UINTN *RpNumber
+ )
+{
+ UINT64 RpBase;
+
+ RpBase = PCI_SEGMENT_LIB_ADDRESS (DEFAULT_PCI_SEGMENT_NUMBER_PCH, DEFAULT_PCI_BUS_NUMBER_PCH, RpDev, RpFun, 0);
+ *RpNumber = (PciSegmentRead32 (RpBase + R_PCH_PCIE_CFG_LCAP) >> N_PCH_PCIE_CFG_LCAP_PN) -1;
+ return EFI_SUCCESS;
+}
+
+/**
+ This function returns PID according to PCIe controller index
+
+ @param[in] ControllerIndex PCIe controller index
+
+ @retval PCH_SBI_PID Returns PID for SBI Access
+**/
+PCH_SBI_PID
+PchGetPcieControllerSbiPid (
+ IN UINT32 ControllerIndex
+ )
+{
+ ASSERT (ControllerIndex < ARRAY_SIZE (mPchPcieControllerInfo));
+ return mPchPcieControllerInfo[ControllerIndex].Pid;
+}
+
+/**
+ This function returns PID according to Root Port Number
+
+ @param[in] RpIndex Root Port Index (0-based)
+
+ @retval PCH_SBI_PID Returns PID for SBI Access
+**/
+PCH_SBI_PID
+GetRpSbiPid (
+ IN UINTN RpIndex
+ )
+{
+ return PchGetPcieControllerSbiPid ((UINT32) (RpIndex / PCH_PCIE_CONTROLLER_PORTS));
+}
+
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PcieRp/Library/PeiDxeSmmPchPcieRpLib/PeiDxeSmmPchPcieRpLibVer2.inf b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PcieRp/Library/PeiDxeSmmPchPcieRpLib/PeiDxeSmmPchPcieRpLibVer2.inf
new file mode 100644
index 0000000000..4fc217581b
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PcieRp/Library/PeiDxeSmmPchPcieRpLib/PeiDxeSmmPchPcieRpLibVer2.inf
@@ -0,0 +1,39 @@
+## @file
+# PCIE root port Library.
+#
+# All function in this library is available for PEI, DXE, and SMM,
+# But do not support UEFI RUNTIME environment call.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiDxeSmmPchPcieRpLib
+FILE_GUID = B522981C-E0C5-4E04-A82A-C61D4F0B2C75
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = PchPcieRpLib
+
+
+[LibraryClasses]
+BaseLib
+IoLib
+DebugLib
+PciSegmentLib
+PchInfoLib
+PchPcrLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+TigerlakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+PchPcieRpLib.c
+PchPcieRpLibVer2.c
+
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PcieRp/LibraryPrivate/DxePchPcieRpPolicyLib/DxePchPcieRpPolicyLib.c b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PcieRp/LibraryPrivate/DxePchPcieRpPolicyLib/DxePchPcieRpPolicyLib.c
new file mode 100644
index 0000000000..577e436e32
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PcieRp/LibraryPrivate/DxePchPcieRpPolicyLib/DxePchPcieRpPolicyLib.c
@@ -0,0 +1,179 @@
+/** @file
+ This file provides services for PcieRp policy function
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include <Uefi.h>
+#include <Library/DebugLib.h>
+#include <Library/SiConfigBlockLib.h>
+#include <Library/ConfigBlockLib.h>
+#include <Protocol/PchPolicy.h>
+#include <PchPcieRpConfig.h>
+
+#define PCI_CLASS_NETWORK 0x02
+#define PCI_CLASS_NETWORK_ETHERNET 0x00
+#define PCI_CLASS_NETWORK_OTHER 0x80
+
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_PCIE_DEVICE_OVERRIDE mPcieDeviceTable[] = {
+ //
+ // Intel PRO/Wireless
+ //
+ { 0x8086, 0x422b, 0xff, 0xff, 0xff, PchPcieAspmL1, PchPcieL1L2Override, 0, 0, 0, 0, 0, 0, 0 },
+ { 0x8086, 0x422c, 0xff, 0xff, 0xff, PchPcieAspmL1, PchPcieL1L2Override, 0, 0, 0, 0, 0, 0, 0 },
+ { 0x8086, 0x4238, 0xff, 0xff, 0xff, PchPcieAspmL1, PchPcieL1L2Override, 0, 0, 0, 0, 0, 0, 0 },
+ { 0x8086, 0x4239, 0xff, 0xff, 0xff, PchPcieAspmL1, PchPcieL1L2Override, 0, 0, 0, 0, 0, 0, 0 },
+ //
+ // Intel WiMAX/WiFi Link
+ //
+ { 0x8086, 0x0082, 0xff, 0xff, 0xff, PchPcieAspmL1, PchPcieL1L2Override, 0, 0, 0, 0, 0, 0, 0 },
+ { 0x8086, 0x0085, 0xff, 0xff, 0xff, PchPcieAspmL1, PchPcieL1L2Override, 0, 0, 0, 0, 0, 0, 0 },
+ { 0x8086, 0x0083, 0xff, 0xff, 0xff, PchPcieAspmL1, PchPcieL1L2Override, 0, 0, 0, 0, 0, 0, 0 },
+ { 0x8086, 0x0084, 0xff, 0xff, 0xff, PchPcieAspmL1, PchPcieL1L2Override, 0, 0, 0, 0, 0, 0, 0 },
+ { 0x8086, 0x0086, 0xff, 0xff, 0xff, PchPcieAspmL1, PchPcieL1L2Override, 0, 0, 0, 0, 0, 0, 0 },
+ { 0x8086, 0x0087, 0xff, 0xff, 0xff, PchPcieAspmL1, PchPcieL1L2Override, 0, 0, 0, 0, 0, 0, 0 },
+ { 0x8086, 0x0088, 0xff, 0xff, 0xff, PchPcieAspmL1, PchPcieL1L2Override, 0, 0, 0, 0, 0, 0, 0 },
+ { 0x8086, 0x0089, 0xff, 0xff, 0xff, PchPcieAspmL1, PchPcieL1L2Override, 0, 0, 0, 0, 0, 0, 0 },
+ { 0x8086, 0x008F, 0xff, 0xff, 0xff, PchPcieAspmL1, PchPcieL1L2Override, 0, 0, 0, 0, 0, 0, 0 },
+ { 0x8086, 0x0090, 0xff, 0xff, 0xff, PchPcieAspmL1, PchPcieL1L2Override, 0, 0, 0, 0, 0, 0, 0 },
+ //
+ // Intel Crane Peak WLAN NIC
+ //
+ { 0x8086, 0x08AE, 0xff, PCI_CLASS_NETWORK, PCI_CLASS_NETWORK_OTHER, PchPcieAspmL1, PchPcieL1L2Override, 0, 0, 0, 0, 0, 0, 0 },
+ { 0x8086, 0x08AF, 0xff, PCI_CLASS_NETWORK, PCI_CLASS_NETWORK_OTHER, PchPcieAspmL1, PchPcieL1L2Override, 0, 0, 0, 0, 0, 0, 0 },
+ //
+ // Intel Crane Peak w/BT WLAN NIC
+ //
+ { 0x8086, 0x0896, 0xff, PCI_CLASS_NETWORK, PCI_CLASS_NETWORK_OTHER, PchPcieAspmL1, PchPcieL1L2Override, 0, 0, 0, 0, 0, 0, 0 },
+ { 0x8086, 0x0897, 0xff, PCI_CLASS_NETWORK, PCI_CLASS_NETWORK_OTHER, PchPcieAspmL1, PchPcieL1L2Override, 0, 0, 0, 0, 0, 0, 0 },
+ //
+ // Intel Kelsey Peak WiFi, WiMax
+ //
+ { 0x8086, 0x0885, 0xff, PCI_CLASS_NETWORK, PCI_CLASS_NETWORK_OTHER, PchPcieAspmL1, PchPcieL1L2Override, 0, 0, 0, 0, 0, 0, 0 },
+ { 0x8086, 0x0886, 0xff, PCI_CLASS_NETWORK, PCI_CLASS_NETWORK_OTHER, PchPcieAspmL1, PchPcieL1L2Override, 0, 0, 0, 0, 0, 0, 0 },
+ //
+ // Intel Centrino Wireless-N 105
+ //
+ { 0x8086, 0x0894, 0xff, PCI_CLASS_NETWORK, PCI_CLASS_NETWORK_OTHER, PchPcieAspmL1, PchPcieL1L2Override, 0, 0, 0, 0, 0, 0, 0 },
+ { 0x8086, 0x0895, 0xff, PCI_CLASS_NETWORK, PCI_CLASS_NETWORK_OTHER, PchPcieAspmL1, PchPcieL1L2Override, 0, 0, 0, 0, 0, 0, 0 },
+ //
+ // Intel Centrino Wireless-N 135
+ //
+ { 0x8086, 0x0892, 0xff, PCI_CLASS_NETWORK, PCI_CLASS_NETWORK_OTHER, PchPcieAspmL1, PchPcieL1L2Override, 0, 0, 0, 0, 0, 0, 0 },
+ { 0x8086, 0x0893, 0xff, PCI_CLASS_NETWORK, PCI_CLASS_NETWORK_OTHER, PchPcieAspmL1, PchPcieL1L2Override, 0, 0, 0, 0, 0, 0, 0 },
+ //
+ // Intel Centrino Wireless-N 2200
+ //
+ { 0x8086, 0x0890, 0xff, PCI_CLASS_NETWORK, PCI_CLASS_NETWORK_OTHER, PchPcieAspmL1, PchPcieL1L2Override, 0, 0, 0, 0, 0, 0, 0 },
+ { 0x8086, 0x0891, 0xff, PCI_CLASS_NETWORK, PCI_CLASS_NETWORK_OTHER, PchPcieAspmL1, PchPcieL1L2Override, 0, 0, 0, 0, 0, 0, 0 },
+ //
+ // Intel Centrino Wireless-N 2230
+ //
+ { 0x8086, 0x0887, 0xff, PCI_CLASS_NETWORK, PCI_CLASS_NETWORK_OTHER, PchPcieAspmL1, PchPcieL1L2Override, 0, 0, 0, 0, 0, 0, 0 },
+ { 0x8086, 0x0888, 0xff, PCI_CLASS_NETWORK, PCI_CLASS_NETWORK_OTHER, PchPcieAspmL1, PchPcieL1L2Override, 0, 0, 0, 0, 0, 0, 0 },
+ //
+ // Intel Centrino Wireless-N 6235
+ //
+ { 0x8086, 0x088E, 0xff, PCI_CLASS_NETWORK, PCI_CLASS_NETWORK_OTHER, PchPcieAspmL1, PchPcieL1L2Override, 0, 0, 0, 0, 0, 0, 0 },
+ { 0x8086, 0x088F, 0xff, PCI_CLASS_NETWORK, PCI_CLASS_NETWORK_OTHER, PchPcieAspmL1, PchPcieL1L2Override, 0, 0, 0, 0, 0, 0, 0 },
+ //
+ // Intel CampPeak 2 Wifi
+ //
+ { 0x8086, 0x08B5, 0xff, PCI_CLASS_NETWORK, PCI_CLASS_NETWORK_OTHER, PchPcieAspmL1, PchPcieL1L2Override, 0, 0, 0, 0, 0, 0, 0 },
+ { 0x8086, 0x08B6, 0xff, PCI_CLASS_NETWORK, PCI_CLASS_NETWORK_OTHER, PchPcieAspmL1, PchPcieL1L2Override, 0, 0, 0, 0, 0, 0, 0 },
+ //
+ // Intel WilkinsPeak 1 Wifi
+ //
+ { 0x8086, 0x08B3, 0xff, PCI_CLASS_NETWORK, PCI_CLASS_NETWORK_OTHER, PchPcieAspmL1, PchPcieL1L2AndL1SubstatesOverride, 0x0158, 0x0000000F, 0, 0, 0, 0, 0 },
+ { 0x8086, 0x08B4, 0xff, PCI_CLASS_NETWORK, PCI_CLASS_NETWORK_OTHER, PchPcieAspmL1, PchPcieL1L2AndL1SubstatesOverride, 0x0158, 0x0000000F, 0, 0, 0, 0, 0 },
+ //
+ // Intel Wilkins Peak 2 Wifi
+ //
+ { 0x8086, 0x08B1, 0xff, PCI_CLASS_NETWORK, PCI_CLASS_NETWORK_OTHER, PchPcieAspmL1, PchPcieL1L2AndL1SubstatesOverride, 0x0158, 0x0000000F, 0, 0, 0, 0, 0 },
+ { 0x8086, 0x08B2, 0xff, PCI_CLASS_NETWORK, PCI_CLASS_NETWORK_OTHER, PchPcieAspmL1, PchPcieL1L2AndL1SubstatesOverride, 0x0158, 0x0000000F, 0, 0, 0, 0, 0 },
+ //
+ // Intel Wilkins Peak PF Wifi
+ //
+ { 0x8086, 0x08B0, 0xff, PCI_CLASS_NETWORK, PCI_CLASS_NETWORK_OTHER, PchPcieAspmL1, PchPcieL1L2Override, 0, 0, 0, 0, 0, 0, 0 },
+ //
+ // Teton Glacier Endpoint
+ //
+ { 0x8086, 0x0975, 0xff, 0, 0, 0, PchPcieL1SubstatesOverride, 0, 0xff, 0x3C, 0, 5, 0, 0, 0, 0 },
+
+ //
+ // End of Table
+ //
+ { 0 }
+};
+
+/**
+ Print PCIE_RP_DXE_CONFIG.
+
+ @param[in] PchPolicy Pointer to a PCH_POLICY_PROTOCOL
+**/
+VOID
+PchPcieRpDxePrintConfig (
+ IN PCH_POLICY_PROTOCOL *PchPolicy
+ )
+{
+ EFI_STATUS Status;
+ PCIE_RP_DXE_CONFIG *PchPcieRpDxeConfig;
+
+ Status = GetConfigBlock ((VOID *) PchPolicy, &gPchPcieRpDxeConfigGuid, (VOID *) &PchPcieRpDxeConfig);
+ ASSERT_EFI_ERROR (Status);
+
+ DEBUG ((DEBUG_INFO, "------------------ PCH PCIE DXE CONFIG ------------------\n"));
+ DEBUG ((DEBUG_INFO, " PcieDeviceOverrideTablePtr : 0x%x\n",PchPcieRpDxeConfig->PcieDeviceOverrideTablePtr));
+}
+
+/**
+ Load DXE Config block default for Pch PCIE RP
+
+ @param[in] ConfigBlockPointer Pointer to config block
+**/
+VOID
+LoadPchPcieRpDxeConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ PCIE_RP_DXE_CONFIG *PchPcieRpDxeConfig;
+
+ PchPcieRpDxeConfig = ConfigBlockPointer;
+ PchPcieRpDxeConfig->PcieDeviceOverrideTablePtr = mPcieDeviceTable;
+}
+
+STATIC COMPONENT_BLOCK_ENTRY mPchPcieRpBlocks = {
+ &gPchPcieRpDxeConfigGuid,
+ sizeof (PCIE_RP_DXE_CONFIG),
+ PCIE_RP_DXE_CONFIG_REVISION,
+ LoadPchPcieRpDxeConfigDefault
+};
+
+/**
+ Get PchPcieRp config block table size.
+
+ @retval Size of config block
+**/
+UINT16
+PchPcieRpDxeGetConfigBlockTotalSize (
+ VOID
+ )
+{
+ return mPchPcieRpBlocks.Size;
+}
+
+/**
+ Add PchPcieRp ConfigBlock.
+
+ @param[in] ConfigBlockTableAddress The pointer to config block table
+
+ @retval EFI_SUCCESS The policy default is initialized.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create buffer
+**/
+EFI_STATUS
+PchPcieRpDxeAddConfigBlock (
+ IN VOID *ConfigBlockTableAddress
+ )
+{
+ return AddComponentConfigBlocks (ConfigBlockTableAddress, &mPchPcieRpBlocks, 1);
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PcieRp/LibraryPrivate/DxePchPcieRpPolicyLib/DxePchPcieRpPolicyLib.inf b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PcieRp/LibraryPrivate/DxePchPcieRpPolicyLib/DxePchPcieRpPolicyLib.inf
new file mode 100644
index 0000000000..6158e77a35
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PcieRp/LibraryPrivate/DxePchPcieRpPolicyLib/DxePchPcieRpPolicyLib.inf
@@ -0,0 +1,30 @@
+## @file
+# Component description file for the PchPcieRp policy library
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = DxePchPcieRpPolicyLib
+FILE_GUID = 328B0DE5-189A-4DB0-BFE1-557F4F89010B
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = DxePchPcieRpPolicyLib
+
+[LibraryClasses]
+DebugLib
+ConfigBlockLib
+SiConfigBlockLib
+
+[Packages]
+MdePkg/MdePkg.dec
+TigerlakeSiliconPkg/SiPkg.dec
+
+[Sources]
+DxePchPcieRpPolicyLib.c
+
+[Guids]
+gPchPcieRpDxeConfigGuid ## CONSUMES
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PcieRp/LibraryPrivate/PciExpressHelpersLibrary/PciExpressHelpersLibrary.c b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PcieRp/LibraryPrivate/PciExpressHelpersLibrary/PciExpressHelpersLibrary.c
new file mode 100644
index 0000000000..401a9fbe7b
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PcieRp/LibraryPrivate/PciExpressHelpersLibrary/PciExpressHelpersLibrary.c
@@ -0,0 +1,1997 @@
+/** @file
+ This file contains routines that support PCI Express initialization
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include "PciExpressHelpersLibrary.h"
+#include <Library/BaseMemoryLib.h>
+#include <Library/PcieHelperLib.h>
+#include <Library/PchPciBdfLib.h>
+#include <Library/PcieRpLib.h>
+#include <PchPcieRpInfo.h>
+#include <CpuPcieInfo.h>
+#include <CpuPcieHob.h>
+#include <Library/HobLib.h>
+#include <Register/PchPcieRpRegs.h>
+
+#define ASPM_L1_NO_LIMIT 0xFF
+#define ASPM_L0s_NO_LIMIT 0x7
+#define LINK_RETRAIN_WAIT_TIME 1000 // microseconds
+
+typedef union {
+ struct {
+ UINT32 RequesterCapable : 1;
+ UINT32 ResponderCapable : 1;
+ UINT32 RootCapable : 1;
+ UINT32 Reserved : 5;
+ UINT32 LocalClockGranularity : 8;
+ UINT32 Reserved2 : 16;
+ } Bits;
+ UINT32 Uint32;
+} PTM_CAPS;
+
+typedef union {
+ struct {
+ UINT32 Enable : 1;
+ UINT32 RootSelect : 1;
+ UINT32 Reserved : 6;
+ UINT32 EffectiveGranularity : 8;
+ UINT32 Reserved2 : 16;
+ } Bits;
+ UINT32 Uint32;
+} PTM_CTRL;
+
+typedef struct {
+ UINT32 Size;
+ const PCH_PCIE_DEVICE_OVERRIDE* Table;
+} OVERRIDE_TABLE;
+
+typedef enum {
+ DevTypePci,
+ DevTypePcieEndpoint,
+ DevTypePcieUpstream,
+ DevTypePcieDownstream,
+ DevTypeMax
+} PCI_DEV_TYPE;
+
+//
+// This structure keeps in one place all data relevant to enabling L0s and L1.
+// L0s latencies are encoded in the same way as in hardware registers. The only operation
+// that will be performed on them is comparison
+// L1 latencies are decoded to microseconds, because they will be used in subtractions and additions
+//
+typedef struct {
+ UINT32 L0sSupported : 1;
+ UINT32 L1Supported : 1;
+ UINT32 L0sAcceptableLatency : 3; // encoded as in hardware register
+ UINT32 L1AcceptableLatencyUs : 8; // decoded to microseconds
+ UINT32 LinkL0sExitLatency : 3; // encoded as in hardware register
+ UINT32 LinkL1ExitLatencyUs : 8; // decoded to microseconds
+} ASPM_CAPS;
+
+typedef struct {
+ UINT32 AspmL11 : 1;
+ UINT32 AspmL12 : 1;
+ UINT32 PmL11 : 1;
+ UINT32 PmL12 : 1;
+ UINT32 Cmrt : 8; // Common Mode Restore Time
+ UINT32 TpoScale : 2; // T power_on scale
+ UINT32 TpoValue : 6; // T power_on value
+} L1SS_CAPS;
+
+#define MAX_SBDF_TABLE_SIZE 50 //arbitrary table size; big enough to accomodate even full length TBT chain.
+
+typedef struct {
+ UINT32 Count;
+ SBDF Entry [MAX_SBDF_TABLE_SIZE];
+} SBDF_TABLE;
+
+/**
+ Converts device's segment:bus:device:function coordinates to flat address
+
+ @param[in] Sbdf device's segment:bus:device:function coordinates
+
+ @retval address of device's PCI cfg space
+**/
+STATIC
+UINT64
+SbdfToBase (
+ SBDF Sbdf
+ )
+{
+ return PCI_SEGMENT_LIB_ADDRESS (Sbdf.Seg, Sbdf.Bus, Sbdf.Dev, Sbdf.Func, 0);
+}
+
+/*
+ Converts Tpower_on from value:scale notation to microseconds
+
+ @param[in] TpoScale T power on scale
+ @param[in] TpoValue T power on value
+
+ @retval number of microseconds
+*/
+UINT32
+TpoToUs (
+ UINT32 TpoScale,
+ UINT32 TpoValue
+ )
+{
+ static const UINT8 TpoScaleMultiplier[] = {2, 10, 100};
+
+ ASSERT (TpoScale < TpoScaleMax);
+ if (TpoScale >= TpoScaleMax) {
+ return 0;
+ }
+ return (TpoScaleMultiplier[TpoScale] * TpoValue);
+}
+
+/**
+ Get max payload size supported by device.
+
+ @param[in] Sbdf device's segment:bus:device:function coordinates
+
+ @retval Max payload size, encoded in the same way as in register (0=128b, 1=256b, etc)
+**/
+STATIC
+UINT8
+GetMps (
+ SBDF Sbdf
+ )
+{
+ return (PciSegmentRead16 (SbdfToBase (Sbdf) + Sbdf.PcieCap + R_PCIE_DCAP_OFFSET) & B_PCIE_DCAP_MPS);
+}
+
+/**
+ Sets Maximum Payload Size to be used by device
+
+ @param[in] Sbdf device's segment:bus:device:function coordinates
+ @param[in] Mps Max payload size, encoded in the same way as in register (0=128b, 1=256b, etc)
+**/
+STATIC
+VOID
+SetMps (
+ SBDF Sbdf,
+ UINT8 Mps
+ )
+{
+ PciSegmentAndThenOr16 (SbdfToBase (Sbdf) + Sbdf.PcieCap + R_PCIE_DCTL_OFFSET, (UINT16) ~B_PCIE_DCTL_MPS, Mps << N_PCIE_DCTL_MPS);
+}
+
+/**
+ Enables LTR feature in given device
+
+ @param[in] Sbdf device's segment:bus:device:function coordinates
+**/
+STATIC
+VOID
+EnableLtr (
+ SBDF Sbdf
+ )
+{
+ if (Sbdf.PcieCap == 0) {
+ return;
+ }
+ PciSegmentOr32 (SbdfToBase (Sbdf) + Sbdf.PcieCap + R_PCIE_DCTL2_OFFSET, B_PCIE_DCTL2_LTREN);
+}
+
+/**
+ Returns information about type of device.
+
+ @param[out] Sbdf device's segment:bus:device:function coordinates
+
+ @retval one of: not a PCIe device (legacy PCI), PCIe endpoint, PCIe upstream port or PCIe downstream port (including rootport)
+**/
+STATIC
+PCI_DEV_TYPE
+GetDeviceType (
+ SBDF Sbdf
+ )
+{
+ UINT8 DeviceType;
+
+ if (Sbdf.PcieCap == 0) {
+ return DevTypePci;
+ }
+ DeviceType = (UINT8) ((PciSegmentRead16 (SbdfToBase (Sbdf) + Sbdf.PcieCap + R_PCIE_XCAP_OFFSET) & B_PCIE_XCAP_DT) >> N_PCIE_XCAP_DT);
+ if (DeviceType == PCIE_DEVICE_PORT_TYPE_UPSTREAM_PORT) {
+ return DevTypePcieUpstream;
+ } else if (DeviceType == PCIE_DEVICE_PORT_TYPE_DOWNSTREAM_PORT || DeviceType == PCIE_DEVICE_PORT_TYPE_ROOT_PORT) {
+ return DevTypePcieDownstream;
+ } else {
+ return DevTypePcieEndpoint;
+ }
+}
+
+/**
+ Initializes Dev:Func numbers for use in FindNextPcieChild or FindNextLegalSbdf functions.
+
+ @param[out] Sbdf device's segment:bus:device:function coordinates
+**/
+STATIC
+VOID
+InitChildFinder (
+ OUT SBDF *Sbdf
+ )
+{
+ //
+ // Initialize Dev/Func to maximum values, so that when FindNextLegalSbdf ()
+ // is called on those input parameters, it will return 1st legal address (Dev 0 Func 0).
+ //
+ Sbdf->Dev = PCI_MAX_DEVICE;
+ Sbdf->Func = PCI_MAX_FUNC;
+}
+
+/**
+ Checks the device is a bridge and has non-zero secondary bus number assigned.
+ If so, it returns TRUE and initializes ChildSbdf with such values that
+ allow searching for devices on the secondary bus.
+ ChildSbdf will be mangled even if this function returns FALSE.
+
+ Legal bus assignment is assumed. This function doesn't check subordinate bus numbers of
+ the the device it was called on or any bridges between it and root complex
+
+ @param[in] Sbdf device's segment:bus:device:function coordinates
+ @param[out] ChildSbdf SBDF initialized in such way that calling FindNextPcieChild( ) on it will find all children devices
+
+ @retval TRUE if device is a bridge and has a bus behind it; FALSE otherwise
+**/
+STATIC
+BOOLEAN
+HasChildBus (
+ SBDF Sbdf,
+ SBDF *ChildSbdf
+ )
+{
+ UINT32 Data32;
+ UINT64 Base;
+ UINT8 SecondaryBus;
+
+ ChildSbdf->Seg = Sbdf.Seg;
+ InitChildFinder (ChildSbdf);
+
+ Base = SbdfToBase (Sbdf);
+
+ if (PciSegmentRead8 (Base + R_PCI_BCC_OFFSET) != PCI_CLASS_BRIDGE) {
+ DEBUG ((DEBUG_INFO, "HasChildBus%02:%02:%02: no\n", Sbdf.Bus, Sbdf.Dev, Sbdf.Func));
+ return FALSE;
+ }
+ Data32 = PciSegmentRead32 (Base + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET);
+ SecondaryBus = (UINT8)((Data32 & B_PCI_BRIDGE_BNUM_SCBN) >> 8);
+ ChildSbdf->Bus = SecondaryBus;
+ if (SecondaryBus == 0) {
+ DEBUG ((DEBUG_INFO, "HasChildBus%02x:%02x:%02x: no\n", Sbdf.Bus, Sbdf.Dev, Sbdf.Func));
+ return FALSE;
+ } else {
+ DEBUG ((DEBUG_INFO, "HasChildBus%02x:%02x:%02x: yes, %x\n", Sbdf.Bus, Sbdf.Dev, Sbdf.Func, SecondaryBus));
+ return TRUE;
+ }
+}
+
+/**
+ Sets LTR limit in a device.
+
+ @param[in] Base device's base address
+ @param[in] Ltr LTR limit
+**/
+STATIC
+VOID
+SetLtrLimit (
+ UINT64 Base,
+ LTR_LIMIT Ltr
+ )
+{
+ UINT16 LtrCapOffset;
+ UINT16 Data16;
+
+ LtrCapOffset = PcieBaseFindExtendedCapId (Base, R_PCIE_LTRECH_CID);
+ if (LtrCapOffset == 0) {
+ return;
+ }
+ Data16 = (UINT16)((Ltr.MaxSnoopLatencyValue << N_PCIE_LTRECH_MSLR_VALUE) | (Ltr.MaxSnoopLatencyScale << N_PCIE_LTRECH_MSLR_SCALE));
+ PciSegmentWrite16(Base + LtrCapOffset + R_PCIE_LTRECH_MSLR_OFFSET, Data16);
+
+ Data16 = (UINT16)((Ltr.MaxNoSnoopLatencyValue << N_PCIE_LTRECH_MNSLR_VALUE) | (Ltr.MaxNoSnoopLatencyScale << N_PCIE_LTRECH_MNSLR_SCALE));
+ PciSegmentWrite16(Base + LtrCapOffset + R_PCIE_LTRECH_MNSLR_OFFSET, Data16);
+}
+
+/**
+ Checks if device at given address exists and is a PCI Express device.
+ PCI express devices are distinguished from PCI by having Capability ID 0x10
+ If the device is PCI express then its SDBF structure gets updated with pointer to
+ the PCIe Capability. This is an optimization feature. It greatly decreases the number
+ of bus accesses, since most features configured by this library depend on registers
+ whose location is relative to PCIe capability.
+
+ @param[in,out] Sbdf on entry, segment:bus:device:function coordinates
+ on exit, PcieCap offset is updated
+
+ @retval TRUE when PCIe device exists; FALSE if it's not PCIe or there's no device at all
+**/
+STATIC
+BOOLEAN
+IsPcieDevice (
+ SBDF *Sbdf
+ )
+{
+ UINT8 PcieCapOffset;
+ UINT64 Base;
+
+ Base = SbdfToBase(*Sbdf);
+
+ if (PciSegmentRead16 (Base) == 0xFFFF) {
+ return FALSE;
+ }
+
+
+ PcieCapOffset = PcieBaseFindCapId (Base, EFI_PCI_CAPABILITY_ID_PCIEXP);
+ if (PcieCapOffset == 0) {
+ DEBUG ((DEBUG_INFO, "IsPcieDevice %02x:%02x:%02x - legacy\n", Sbdf->Bus, Sbdf->Dev, Sbdf->Func));
+ return FALSE;
+ } else {
+ Sbdf->PcieCap = PcieCapOffset;
+ DEBUG ((DEBUG_INFO, "IsPcieDevice %02x:%02x:%02x - yes\n", Sbdf->Bus, Sbdf->Dev, Sbdf->Func));
+ return TRUE;
+ }
+}
+
+/**
+ Returns TRUE and Dev:Func numbers where a PCIe device could legally be located, or FALSE if there
+ no such coordinates left.
+
+ Segment and Bus fields of SBDF structure are input only and determine which bus will be scanned.
+ This function should be called in a while() loop. It replaces the less efficient method of
+ using nested FOR loops that iterate over all device and function numbers. It is optimized for
+ the amount of bus access. If function0 doesn't exist or doesn't have Multifunction bit set,
+ then higher function numbers are skipped. If parent of this bus is a downstream port, then
+ Device numbers 1-31 get skipped too (there can be only Dev0 behind downstream ports)
+ If device/function number == 0x1F/0x7, this function returns first possible address, that is 0:0
+ Any other device number means Dev:Func contain address of last found child device
+ and this function should search for next one
+
+ @param[in] ParentDevType type of bridge who's partent of this bus
+ @param[in,out] Sbdf On entry: location returned previously from this function
+ Dev:Func value of 1F:07 means search should start from the beginning
+ On exit: if legal Dev:Func combination was found, that Dev:Func is returned
+ otherwise, Dev:Func are initialized to 1F:07 for convenience
+
+ @retval TRUE when next legal Dev:Func address was found; FALSE otherwise
+**/
+STATIC
+BOOLEAN
+FindNextLegalSbdf (
+ IN PCI_DEV_TYPE ParentDevType,
+ IN OUT SBDF *Sbdf
+ )
+{
+ UINT8 MaxDev;
+ UINT64 Func0Base;
+
+ if (ParentDevType == DevTypePcieEndpoint) {
+ return FALSE;
+ }
+ if (ParentDevType == DevTypePcieUpstream) {
+ MaxDev = PCI_MAX_DEVICE;
+ } else {
+ MaxDev = 0;
+ }
+ Func0Base = PCI_SEGMENT_LIB_ADDRESS (Sbdf->Seg, Sbdf->Bus, Sbdf->Dev, 0, 0);
+ if ((Sbdf->Dev == PCI_MAX_DEVICE) && Sbdf->Func == PCI_MAX_FUNC) {
+ Sbdf->Dev = 0;
+ Sbdf->Func = 0;
+ return TRUE;
+ } else if ((Sbdf->Func == PCI_MAX_FUNC) || (Sbdf->Func == 0 && !IsMultifunctionDevice (Func0Base))) {
+ //
+ // if it's the last function of a device, then return Func0 of new device or FALSE in case there are no more devices
+ //
+ if (Sbdf->Dev == MaxDev) {
+ InitChildFinder (Sbdf);
+ return FALSE;
+ }
+ (Sbdf->Dev)++;
+ Sbdf->Func = 0;
+ return TRUE;
+ } else {
+ (Sbdf->Func)++;
+ return TRUE;
+ }
+}
+
+/**
+ Finds next PCIe (not legacy PCI) device behind given device
+ If device/function number == 0x1F/0x7, this function searches for children from scratch
+ Any other device number means Dev:Func contain address of last found child device
+ and this function should search for next one
+
+ @param[in] ParentDevType type of bridge who's partent of this bus
+ @param[in,out] Sbdf On entry: location returned previously from this function
+ Dev:Func value of 0x1F:0x07 means search should start from the beginning
+ On exit: if PCIe device was found, its SBDF coordinates are returned
+ otherwise, Dev:Func are initialized to 0x1F:0x07 for convenience
+ @retval TRUE when next PCIe device was found; FALSE otherwise
+**/
+BOOLEAN
+FindNextPcieChild (
+ IN PCI_DEV_TYPE ParentDevType,
+ IN OUT SBDF *Sbdf
+ )
+{
+ while ( FindNextLegalSbdf (ParentDevType, Sbdf)) {
+ if (IsPcieDevice (Sbdf)) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/**
+ Checks if given device supports Clock Power Management
+
+ @param[in] Sbdf segment:bus:device:function coordinates of a device
+
+ @retval TRUE when device supports it, FALSE otherwise
+**/
+STATIC
+BOOLEAN
+IsCpmSupported (
+ SBDF Sbdf
+ )
+{
+ return !!(PciSegmentRead32 (SbdfToBase (Sbdf) + Sbdf.PcieCap + R_PCIE_LCAP_OFFSET) & B_PCIE_LCAP_CPM);
+}
+
+/**
+ Sets Enable Clock Power Management bit for given device
+
+ @param[in] Sbdf segment:bus:device:function coordinates of a device
+**/
+STATIC
+VOID
+EnableCpm (
+ SBDF Sbdf
+ )
+{
+ PciSegmentOr16 (SbdfToBase (Sbdf) + Sbdf.PcieCap + R_PCIE_LCTL_OFFSET, B_PCIE_LCTL_ECPM);
+}
+
+/**
+ Checks if given device is an IoAPIC
+
+ @param[in] Base device's base address
+
+ @retval TRUE if it's an IoAPIC
+**/
+BOOLEAN
+IsIoApicDevice (
+ UINT64 Base
+ )
+{
+ UINT8 BaseClassCode;
+ UINT8 SubClassCode;
+ UINT8 ProgInterface;
+
+ BaseClassCode = PciSegmentRead8 (Base + PCI_CLASSCODE_OFFSET + 2);
+ SubClassCode = PciSegmentRead8 (Base + PCI_CLASSCODE_OFFSET + 1);
+ ProgInterface = PciSegmentRead8 (Base + PCI_CLASSCODE_OFFSET);
+ if ((BaseClassCode == PCI_CLASS_SYSTEM_PERIPHERAL) &&
+ (SubClassCode == PCI_SUBCLASS_PIC) &&
+ ((ProgInterface == PCI_IF_APIC_CONTROLLER) ||
+ (ProgInterface == PCI_IF_APIC_CONTROLLER2))) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ There are some devices which support L1 substates, but due to silicon bugs the corresponding register
+ cannot be found by scanning PCIe capabilities. This function checks list of such devices and if one
+ is found, returns its L1ss capability register offset
+
+ @param[in] Base base address of device
+ @param[in] Override table of devices that need override
+
+ @retval offset to L1ss capability register
+**/
+UINT16
+GetOverrideL1ssCapsOffset (
+ UINT64 Base,
+ OVERRIDE_TABLE *Override
+ )
+{
+ UINT16 DeviceId;
+ UINT16 VendorId;
+ UINT8 Revision;
+ UINT32 Index;
+
+ VendorId = PciSegmentRead16 (Base + PCI_VENDOR_ID_OFFSET);
+ DeviceId = PciSegmentRead16 (Base + PCI_DEVICE_ID_OFFSET);
+ Revision = PciSegmentRead8 (Base + PCI_REVISION_ID_OFFSET);
+
+ for (Index = 0; Index < Override->Size; Index++) {
+ if (((Override->Table[Index].OverrideConfig & PchPcieL1SubstatesOverride) == PchPcieL1SubstatesOverride) &&
+ (Override->Table[Index].VendorId == VendorId) &&
+ (Override->Table[Index].DeviceId == DeviceId) &&
+ (Override->Table[Index].RevId == Revision || Override->Table[Index].RevId == 0xFFFF)) {
+ return Override->Table[Index].L1SubstatesCapOffset;
+ }
+ }
+ return 0;
+}
+
+/**
+ There are some devices whose implementation of L1 substates is partially broken. This function checks
+ list of such devices and if one is found, overrides their L1ss-related capabilities
+
+ @param[in] Base base address of device
+ @param[in] Override table of devices that need override
+ @param[in,out] L1ss on entry, capabilities read from register; on exit, capabilities modified according ot override table
+**/
+STATIC
+VOID
+OverrideL1ssCaps (
+ UINT64 Base,
+ OVERRIDE_TABLE *Override,
+ L1SS_CAPS *L1ss
+ )
+{
+ UINT16 DeviceId;
+ UINT16 VendorId;
+ UINT8 Revision;
+ UINT32 Index;
+
+ VendorId = PciSegmentRead16 (Base + PCI_VENDOR_ID_OFFSET);
+ DeviceId = PciSegmentRead16 (Base + PCI_DEVICE_ID_OFFSET);
+ Revision = PciSegmentRead8 (Base + PCI_REVISION_ID_OFFSET);
+
+ for (Index = 0; Index < Override->Size; Index++) {
+ if (((Override->Table[Index].OverrideConfig & PchPcieL1SubstatesOverride) == PchPcieL1SubstatesOverride) &&
+ (Override->Table[Index].VendorId == VendorId) &&
+ (Override->Table[Index].DeviceId == DeviceId) &&
+ (Override->Table[Index].RevId == Revision || Override->Table[Index].RevId == 0xFF)) {
+
+ L1ss->PmL12 &= !!(Override->Table[Index].L1SubstatesCapMask & B_PCIE_EX_L1SCAP_PPL12S);
+ L1ss->PmL11 &= !!(Override->Table[Index].L1SubstatesCapMask & B_PCIE_EX_L1SCAP_PPL11S);
+ L1ss->AspmL12 &= !!(Override->Table[Index].L1SubstatesCapMask & B_PCIE_EX_L1SCAP_AL12S);
+ L1ss->AspmL11 &= !!(Override->Table[Index].L1SubstatesCapMask & B_PCIE_EX_L1SCAP_AL1SS);
+ if (Override->Table[Index].L1sTpowerOnValue != 0) {
+ L1ss->Cmrt = Override->Table[Index].L1sCommonModeRestoreTime;
+ L1ss->TpoScale = Override->Table[Index].L1sTpowerOnScale;
+ L1ss->TpoValue = Override->Table[Index].L1sTpowerOnValue;
+ }
+ return;
+ }
+ }
+}
+
+/**
+ Returns L1 sub states capabilities of a device
+
+ @param[in] Base base address of a device
+
+ @retval L1SS_CAPS structure filled with device's capabilities
+**/
+STATIC
+L1SS_CAPS
+GetL1ssCaps (
+ UINT64 Base,
+ OVERRIDE_TABLE *Override
+ )
+{
+ L1SS_CAPS Capabilities = {0};
+ UINT16 PcieCapOffset;
+ UINT32 CapsRegister;
+
+ PcieCapOffset = GetOverrideL1ssCapsOffset (Base, Override);
+ if (PcieCapOffset == 0) {
+ PcieCapOffset = PcieBaseFindExtendedCapId (Base, V_PCIE_EX_L1S_CID);
+ }
+ if (PcieCapOffset == 0) {
+ return Capabilities;
+ }
+ CapsRegister = PciSegmentRead32 (Base + PcieCapOffset + R_PCIE_EX_L1SCAP_OFFSET);
+ if (CapsRegister & B_PCIE_EX_L1SCAP_L1PSS) {
+ //
+ // Skip L1.1 checking since some device only indecate L1.2 support.
+ // [1604452805]
+ //
+ Capabilities.PmL11 = !!(CapsRegister & B_PCIE_EX_L1SCAP_PPL11S);
+ Capabilities.PmL12 = !!(CapsRegister & B_PCIE_EX_L1SCAP_PPL12S);
+ Capabilities.AspmL12 = !!(CapsRegister & B_PCIE_EX_L1SCAP_AL12S);
+ Capabilities.AspmL11 = !!(CapsRegister & B_PCIE_EX_L1SCAP_AL1SS);
+ Capabilities.Cmrt = (CapsRegister & B_PCIE_EX_L1SCAP_CMRT) >> N_PCIE_EX_L1SCAP_CMRT;
+ Capabilities.TpoValue = (CapsRegister & B_PCIE_EX_L1SCAP_PTV) >> N_PCIE_EX_L1SCAP_PTV;
+ Capabilities.TpoScale = (CapsRegister & B_PCIE_EX_L1SCAP_PTPOS) >> N_PCIE_EX_L1SCAP_PTPOS;
+ }
+ OverrideL1ssCaps (Base, Override, &Capabilities);
+ return Capabilities;
+}
+
+/**
+ Returns combination of two sets of L1 substate capabilities
+ Given feature is supported by the link only if both sides support it
+ Time parameters for link (Cmrt and Tpo) depend on the bigger value between two sides
+
+ @param[in] L1ssA L1 substate capabilities of first device
+ @param[in] L1ssB L1 substate capabilities of second device
+
+ @retval Link's L1 substate capabilities
+**/
+STATIC
+L1SS_CAPS
+CombineL1ss (
+ L1SS_CAPS L1ssA,
+ L1SS_CAPS L1ssB
+ )
+{
+ L1SS_CAPS Combined;
+
+ Combined.PmL12 = L1ssA.PmL12 && L1ssB.PmL12;
+ Combined.PmL11 = L1ssA.PmL11 && L1ssB.PmL11;
+ Combined.AspmL12 = L1ssA.AspmL12 && L1ssB.AspmL12;
+ Combined.AspmL11 = L1ssA.AspmL11 && L1ssB.AspmL11;
+ Combined.Cmrt = MAX (L1ssA.Cmrt, L1ssB.Cmrt);
+ if (TpoToUs (L1ssA.TpoScale, L1ssA.TpoValue) > TpoToUs (L1ssB.TpoScale, L1ssB.TpoValue)) {
+ Combined.TpoScale = L1ssA.TpoScale;
+ Combined.TpoValue = L1ssA.TpoValue;
+ } else {
+ Combined.TpoScale = L1ssB.TpoScale;
+ Combined.TpoValue = L1ssB.TpoValue;
+ }
+ return Combined;
+}
+
+/**
+ Configures L1 substate feature in a device
+
+ @param[in] Sbdf segment:bus:device:function coordinates of a device
+ @param[in] L1ss configuration to be programmed
+ @param[in] Override table of devices that require special handling
+**/
+STATIC
+VOID
+SetL1ss (
+ SBDF Sbdf,
+ L1SS_CAPS L1ss,
+ OVERRIDE_TABLE *Override,
+ BOOLEAN IsCpuPcie
+
+ )
+{
+ UINT16 PcieCapOffset;
+ UINT32 Ctrl1Register;
+ UINT32 Ctrl2Register;
+ UINT64 Base;
+
+ Base = SbdfToBase(Sbdf);
+ Ctrl1Register = 0;
+ Ctrl2Register = 0;
+
+ PcieCapOffset = GetOverrideL1ssCapsOffset (Base, Override);
+ if (PcieCapOffset == 0) {
+ PcieCapOffset = PcieBaseFindExtendedCapId (Base, V_PCIE_EX_L1S_CID);
+ }
+ if (PcieCapOffset == 0) {
+ return;
+ }
+
+ Ctrl1Register |= (L1ss.PmL12 ? B_PCIE_EX_L1SCAP_PPL12S : 0);
+ Ctrl1Register |= (L1ss.PmL11 ? B_PCIE_EX_L1SCAP_PPL11S : 0);
+ Ctrl1Register |= (L1ss.AspmL12 ? B_PCIE_EX_L1SCAP_AL12S : 0);
+ Ctrl1Register |= (L1ss.AspmL11 ? B_PCIE_EX_L1SCAP_AL1SS : 0);
+ if ((GetDeviceType (Sbdf) == DevTypePcieDownstream)) {
+ Ctrl1Register |= (L1ss.Cmrt << N_PCIE_EX_L1SCAP_CMRT);
+ }
+ ///
+ /// BWG 1.3 Section 5.5.7.6 LTR Threshold Latency
+ /// Set L1.2 LTR threshold using formula (TpoToUs (L1ss.TpoScale, L1ss.TpoValue) + L1ss.Cmrt + 10)
+ ///
+ Ctrl1Register |= ((TpoToUs (L1ss.TpoScale, L1ss.TpoValue) + L1ss.Cmrt + 10) << N_PCIE_EX_L1SCTL1_L12LTRTLV);
+ Ctrl1Register |= (2 << N_PCIE_EX_L1SCTL1_L12LTRTLSV);
+
+ Ctrl2Register |= (L1ss.TpoScale);
+ Ctrl2Register |= (L1ss.TpoValue << N_PCIE_EX_L1SCTL2_POWT);
+ //
+ // Set CLKREQ Acceleration Interrupt Enable
+ //
+ Ctrl1Register |= B_PCIE_EX_L1SCTL1_L1SSEIE;
+ PciSegmentWrite32 (Base + PcieCapOffset + R_PCIE_EX_L1SCTL1_OFFSET, 0);
+ PciSegmentWrite32 (Base + PcieCapOffset + R_PCIE_EX_L1SCTL2_OFFSET, Ctrl2Register);
+ PciSegmentWrite32 (Base + PcieCapOffset + R_PCIE_EX_L1SCTL1_OFFSET, Ctrl1Register);
+}
+
+/**
+ Converts L1 latency from enumerated register value to microseconds
+
+ @param[in] L1Latency latency value retrieved from register; see PCIE specification for encoding
+
+ @retval L1 latency converted to microseconds
+**/
+UINT32
+L1LatencyToUs (
+ UINT32 L1Latency
+ )
+{
+ if (L1Latency < 7) {
+ return 1 * (BIT0 << L1Latency);
+ } else {
+ return ASPM_L1_NO_LIMIT;
+ }
+}
+
+/**
+ Modifies L1 latency by provided value
+
+ @param[in] Aspm Structure that contains ASPM capabilities of a link, including L1 acceptable latency
+ @param[in] Value Value, in microseconds, to be added to L1 acceptable latency. Can be negative.
+
+ @retval Aspm structure with modified L1 acceptable latency
+**/
+STATIC
+ASPM_CAPS
+PatchL1AcceptableLatency (
+ ASPM_CAPS Aspm,
+ INT8 Value
+ )
+{
+ if (Aspm.L1AcceptableLatencyUs != ASPM_L1_NO_LIMIT) {
+ if (Value > 0) {
+ Aspm.L1AcceptableLatencyUs += Value;
+ } else {
+ if (Aspm.L1AcceptableLatencyUs > (UINT32)(-1*Value)) {
+ Aspm.L1AcceptableLatencyUs = Aspm.L1AcceptableLatencyUs + Value;
+ } else {
+ Aspm.L1AcceptableLatencyUs = 0;
+ }
+ }
+ }
+ return Aspm;
+}
+
+/**
+ Reads ASPM capabilities of a device
+
+ @param[in] Sbdf segment:bus:device:function coordinates of a device
+
+ @retval structure containing device's ASPM capabilities
+**/
+STATIC
+ASPM_CAPS
+GetAspmCaps (
+ SBDF Sbdf
+ )
+{
+
+ UINT32 LinkCapRegister;
+ UINT32 DevCapRegister;
+ UINT64 Base;
+ ASPM_CAPS Aspm = {0};
+
+ Base = SbdfToBase (Sbdf);
+
+ LinkCapRegister = PciSegmentRead32 (Base + Sbdf.PcieCap + R_PCIE_LCAP_OFFSET);
+ DevCapRegister = PciSegmentRead32 (Base + Sbdf.PcieCap + R_PCIE_DCAP_OFFSET);
+
+ ///
+ /// Check endpoint for pre-1.1 devices based on the Role based Error Reporting Capability bit. Don't report L0s support for old devices
+ ///
+ if (DevCapRegister & B_PCIE_DCAP_RBER) {
+ Aspm.L0sSupported = !!(LinkCapRegister & B_PCIE_LCAP_APMS_L0S);
+ }
+ Aspm.L1Supported = !!(LinkCapRegister & B_PCIE_LCAP_APMS_L1);
+
+ Aspm.LinkL0sExitLatency = (LinkCapRegister & B_PCIE_LCAP_EL0) >> N_PCIE_LCAP_EL0;
+ Aspm.LinkL1ExitLatencyUs = L1LatencyToUs( (LinkCapRegister & B_PCIE_LCAP_EL1) >> N_PCIE_LCAP_EL1);
+
+ if (GetDeviceType (Sbdf) == DevTypePcieEndpoint) {
+ Aspm.L0sAcceptableLatency = (DevCapRegister & B_PCIE_DCAP_E0AL) >> N_PCIE_DCAP_E0AL;
+ Aspm.L1AcceptableLatencyUs = L1LatencyToUs( (DevCapRegister & B_PCIE_DCAP_E1AL) >> N_PCIE_DCAP_E1AL);
+ DEBUG ((DEBUG_INFO, "GetAspmCaps %02x:%02x:%02x L0s%c %d:%d L1%c %d:%d\n", Sbdf.Bus, Sbdf.Dev, Sbdf.Func,
+ Aspm.L0sSupported?'+':'-', Aspm.LinkL0sExitLatency, Aspm.L0sAcceptableLatency,
+ Aspm.L1Supported?'+':'-', Aspm.LinkL1ExitLatencyUs, Aspm.L1AcceptableLatencyUs));
+ } else {
+ Aspm.L0sAcceptableLatency = ASPM_L0s_NO_LIMIT;
+ Aspm.L1AcceptableLatencyUs = ASPM_L1_NO_LIMIT;
+ DEBUG ((DEBUG_INFO, "GetAspmCaps %02x:%02x:%02x L0s%c %d:x L1%c %d:x\n", Sbdf.Bus, Sbdf.Dev, Sbdf.Func,
+ Aspm.L0sSupported?'+':'-', Aspm.LinkL0sExitLatency,
+ Aspm.L1Supported?'+':'-', Aspm.LinkL1ExitLatencyUs));
+ }
+ return Aspm;
+}
+
+/**
+ Get ASPM L0s and L1 override of given device.
+
+ @param[in] Sbdf Segment,Bus,Device,Function address of currently visited PCIe device
+ @param[in,out] MyAspm Current device's ASPM capabilities structure
+ @param[in] Override Pch Pcie devices OverrideTable
+**/
+STATIC
+VOID
+GetOverrideAspm (
+ SBDF Sbdf,
+ ASPM_CAPS *MyAspm,
+ OVERRIDE_TABLE *Override
+ )
+{
+ UINT16 DeviceId;
+ UINT16 VendorId;
+ UINT8 Revision;
+ UINT32 Index;
+ UINT64 Base;
+
+ Base = SbdfToBase (Sbdf);
+
+ VendorId = PciSegmentRead16 (Base + PCI_VENDOR_ID_OFFSET);
+ DeviceId = PciSegmentRead16 (Base + PCI_DEVICE_ID_OFFSET);
+ Revision = PciSegmentRead8 (Base + PCI_REVISION_ID_OFFSET);
+
+ for (Index = 0; Index < Override->Size; Index++) {
+ if (((Override->Table[Index].OverrideConfig & PchPcieL1L2Override) == PchPcieL1L2Override) &&
+ (Override->Table[Index].VendorId == VendorId) &&
+ (Override->Table[Index].DeviceId == DeviceId) &&
+ (Override->Table[Index].RevId == Revision || Override->Table[Index].RevId == 0xFF)) {
+ DEBUG ((DEBUG_INFO, "GetOverrideAspm %02x:%02x:%02x, original L0sSupported = 0x%x, L1Supported = 0x%x\n",
+ Sbdf.Bus, Sbdf.Dev, Sbdf.Func, MyAspm->L0sSupported, MyAspm->L1Supported));
+ if (MyAspm->L0sSupported) {
+ //
+ // If L0s is supported in capability, apply platform override.
+ //
+ MyAspm->L0sSupported = Override->Table[Index].EndPointAspm & BIT0;
+ }
+ if (MyAspm->L1Supported) {
+ //
+ // If L1 is supported in capability, apply platform override.
+ //
+ MyAspm->L1Supported = (Override->Table[Index].EndPointAspm & BIT1) >> 1;
+ }
+ DEBUG ((DEBUG_INFO, "GetOverrideAspm %02x:%02x:%02x, override L0sSupported = 0x%x, L1Supported = 0x%x\n",
+ Sbdf.Bus, Sbdf.Dev, Sbdf.Func, MyAspm->L0sSupported, MyAspm->L1Supported));
+ }
+ }
+}
+
+/**
+ Combines ASPM capabilities of two devices on both ends of a link to determine link's ASPM capabilities
+
+ @param[in] AspmA, AspmB ASPM capabilities of two devices
+
+ @retval ASPM_CAPS structure containing combined ASPM capabilities
+**/
+STATIC
+ASPM_CAPS
+CombineAspm (
+ ASPM_CAPS AspmA,
+ ASPM_CAPS AspmB,
+ BOOLEAN DownstreamPort
+ )
+{
+ ASPM_CAPS Combined;
+
+ if (DownstreamPort) {
+ //
+ // When combining ASPM in downstream ports, combination must reflect state of link just below
+ // and consider all acceptable latencies of all endpoints anywhere down below that port
+ //
+ Combined.L0sSupported = AspmA.L0sSupported & AspmB.L0sSupported;
+ Combined.L1Supported = AspmA.L1Supported & AspmB.L1Supported;
+ Combined.LinkL0sExitLatency = MAX (AspmA.LinkL0sExitLatency, AspmB.LinkL0sExitLatency);
+ Combined.LinkL1ExitLatencyUs = MAX (AspmA.LinkL1ExitLatencyUs, AspmB.LinkL1ExitLatencyUs);
+ Combined.L0sAcceptableLatency = MIN (AspmA.L0sAcceptableLatency, AspmB.L0sAcceptableLatency);
+ Combined.L1AcceptableLatencyUs = MIN (AspmA.L1AcceptableLatencyUs, AspmB.L1AcceptableLatencyUs);
+ } else {
+ //
+ // When combining ASPM in switch upstream ports,
+ // Supported and ExitLatency must only reflect capabilities of upstream port itself
+ // But acceptable latencies must consider all endpoints anywhere below
+ //
+ Combined.L0sSupported = AspmA.L0sSupported;
+ Combined.L1Supported = AspmA.L1Supported;
+ Combined.LinkL0sExitLatency = AspmA.LinkL0sExitLatency;
+ Combined.LinkL1ExitLatencyUs = AspmA.LinkL1ExitLatencyUs;
+ Combined.L0sAcceptableLatency = MIN (AspmA.L0sAcceptableLatency, AspmB.L0sAcceptableLatency);
+ Combined.L1AcceptableLatencyUs = MIN (AspmA.L1AcceptableLatencyUs, AspmB.L1AcceptableLatencyUs);
+ }
+ DEBUG ((DEBUG_INFO, "CombineAspm %x:%x -> %x\n", AspmA.L1AcceptableLatencyUs, AspmB.L1AcceptableLatencyUs, Combined.L1AcceptableLatencyUs));
+ return Combined;
+}
+
+/**
+ Checks if L1 can be enabled on given link, according to ASPM parameters of that link
+
+ @param[in] Aspm set of parameters describing this link and endpoint devices below it
+
+ @retval TRUE if L1 can be enabled
+**/
+STATIC
+BOOLEAN
+IsL1Allowed (
+ ASPM_CAPS Aspm
+ )
+{
+ return (Aspm.L1Supported && (Aspm.L1AcceptableLatencyUs >= Aspm.LinkL1ExitLatencyUs));
+}
+
+/**
+ Checks if L0s can be enabled on given link, according to ASPM parameters of that link
+
+ @param[in] Aspm set of parameters describing this link and endpoint devices below it
+
+ @retval TRUE if L0s can be enabled
+**/
+STATIC
+BOOLEAN
+IsL0sAllowed (
+ ASPM_CAPS Aspm
+ )
+{
+ return (Aspm.L0sSupported && (Aspm.L0sAcceptableLatency >= Aspm.LinkL0sExitLatency));
+}
+
+/**
+ Enables L0s and L1 for given port, if possible.
+ L0s/L1 can be enabled if it's supported on both sides of a link and if link's latency doesn't exceed
+ acceptable latency of any endpoint below this link
+
+ @param[in] Base device's base address
+ @param[in] Aspm set of parameters describing this link and endpoint devices below it
+**/
+STATIC
+VOID
+SetAspm (
+ SBDF Sbdf,
+ ASPM_CAPS Aspm
+ )
+{
+ UINT16 DataOr;
+
+ DataOr = 0;
+ if (IsL0sAllowed (Aspm)) {
+ DataOr |= V_PCIE_LCTL_ASPM_L0S;
+ }
+ if (IsL1Allowed (Aspm)) {
+ DataOr |= V_PCIE_LCTL_ASPM_L1;
+ }
+ DEBUG ((DEBUG_INFO, "SetAspm on %02x:%02x:%02x to %d\n", Sbdf.Bus,Sbdf.Dev,Sbdf.Func, DataOr));
+ PciSegmentAndThenOr16 (SbdfToBase (Sbdf) + Sbdf.PcieCap + R_PCIE_LCTL_OFFSET, (UINT16)~B_PCIE_LCTL_ASPM, DataOr);
+}
+
+/**
+ Adds device entry to a list of devices.
+
+ @param[in,out] Table array of devices
+ @param[in] Sbdf segment:bus:device:function coordinates of device to be added to table
+**/
+STATIC
+VOID
+AddToDeviceTable (
+ SBDF_TABLE *Table,
+ SBDF Sbdf
+ )
+{
+ if (Table->Count < MAX_SBDF_TABLE_SIZE) {
+ Table->Entry[Table->Count++] = Sbdf;
+ } else {
+ ASSERT (FALSE);
+ }
+}
+
+/**
+ Remove device entry from a list and clear its bus assignment
+
+ @param[in,out] Table array of devices
+**/
+STATIC
+VOID
+ClearBusFromTable (
+ SBDF_TABLE *Table
+ )
+{
+ while (Table->Count > 0) {
+ PciSegmentWrite32 (SbdfToBase (Table->Entry[Table->Count - 1]) + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET, 0);
+ Table->Count--;
+ }
+}
+
+/**
+ Attempts to assign secondary and subordinate bus numbers to uninitialized bridges in PCIe tree
+ If the device is a bridge and already has bus numbers assigned, they won't be changed
+ Otherwise new bus number will be assigned below this bridge.
+ This function can be called from SMM, where BIOS must not modify bus numbers to prevent
+ conflict with OS enumerator. To prevent this, this function returns list of bridges whose
+ bus numbers were changed. All devices from that list must have buses cleared afterwards.
+
+ @param[in] Sbdf segment:bus:device:function coordinates of device to be added to table
+ @param[in] MinBus minimum Bus number that can be assigned below this port
+ @param[in] MaxBus maximum Bus number that can be assigned below this port
+ @param[in] BridgeCleanupList list of bridges where bus numbers were modified
+
+ @retval maximum bus number assigned anywhere below this device
+**/
+STATIC
+UINT8
+RecursiveBusAssignment (
+ SBDF Sbdf,
+ UINT8 MinBus,
+ UINT8 MaxBus,
+ SBDF_TABLE *BridgeCleanupList
+ )
+{
+ UINT64 Base;
+ SBDF ChildSbdf;
+ PCI_DEV_TYPE DevType;
+ UINT32 Data32;
+ UINT8 BelowBus;
+ UINT8 SecondaryBus;
+ UINT8 SubordinateBus;
+
+ ChildSbdf.Seg = Sbdf.Seg;
+ InitChildFinder (&ChildSbdf);
+ Base = SbdfToBase (Sbdf);
+
+ //
+ // On way down:
+ // assign secondary bus, then increase it by one before stepping down; temporarily assign max subordinate bus
+ // On way up:
+ // fix subordinate bus assignment to equal max bus number assigned anywhere below; return that number
+ //
+ DevType = GetDeviceType (Sbdf);
+ if ((Sbdf.Bus >= MaxBus) || (DevType == DevTypePcieEndpoint) || (DevType == DevTypePci)) {
+ return (UINT8) Sbdf.Bus;
+ } else {
+ Data32 = PciSegmentRead32 (Base + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET);
+ SecondaryBus = (UINT8)((Data32 & B_PCI_BRIDGE_BNUM_SCBN) >> 8);
+ SubordinateBus = (UINT8)((Data32 & B_PCI_BRIDGE_BNUM_SBBN) >> 16);
+ if (SecondaryBus != 0) {
+ ChildSbdf.Bus = SecondaryBus;
+ MinBus = SecondaryBus + 1;
+ DEBUG ((DEBUG_INFO, "RecursiveBusAssignmentP %x:%x:%x -> %x,%x,%x \n", Sbdf.Bus, Sbdf.Dev, Sbdf.Func, Sbdf.Bus, MinBus, SubordinateBus));
+ while (FindNextPcieChild (DevType, &ChildSbdf)) {
+ BelowBus = RecursiveBusAssignment (ChildSbdf, MinBus, SubordinateBus, BridgeCleanupList);
+ MinBus = BelowBus + 1;
+ }
+ return SubordinateBus;
+ } else {
+ Data32 = Sbdf.Bus + (MinBus << 8) + (MaxBus << 16);
+ PciSegmentWrite32(Base + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET, Data32);
+ AddToDeviceTable (BridgeCleanupList, Sbdf);
+ DEBUG ((DEBUG_INFO, "RecursiveBusAssignmentE %x:%x:%x -> %x,%x,%x \n", Sbdf.Bus, Sbdf.Dev, Sbdf.Func, Sbdf.Bus, MinBus, MaxBus));
+ BelowBus = MinBus;
+ ChildSbdf.Bus = MinBus;
+ MinBus++;
+ while (FindNextPcieChild (DevType, &ChildSbdf)) {
+ BelowBus = RecursiveBusAssignment (ChildSbdf, MinBus, MaxBus, BridgeCleanupList);
+ MinBus = BelowBus + 1;
+ }
+ Data32 &= ~B_PCI_BRIDGE_BNUM_SBBN;
+ Data32 |= (BelowBus << 16);
+ PciSegmentWrite32 (Base + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET, Data32);
+ DEBUG ((DEBUG_INFO, "RecursiveBusAssignmentL %x:%x:%x -> %x,%x,%x \n", Sbdf.Bus, Sbdf.Dev, Sbdf.Func, Sbdf.Bus, (Data32&0xFF00)>>8, BelowBus));
+ return BelowBus;
+ }
+ }
+}
+
+/**
+ Enables L0s and/or L1 for PCIE links in the hierarchy below
+ L0s/L1 can be enabled when both sides of a link support it and link latency is smaller than acceptable latency
+ ASPM of a given link is independend from any other link (except 1ms L1 adjustment, read below), so it's possible to
+ have a hierarchy when RP link has no ASPM but links below do.
+
+ @param[in] Segment,Bus,Device,Function address of currently visited PCIe device
+ @param[in] Depth How many links there are between this port and root complex
+ @param[in] Override Pch Pcie devices OverrideTable
+
+ @retval structure that describes acceptable latencies of all endpoints below plus ASPM parameters of last link
+**/
+STATIC
+ASPM_CAPS
+RecursiveAspmConfiguration (
+ SBDF Sbdf,
+ UINT8 Depth,
+ OVERRIDE_TABLE *Override
+ )
+{
+ SBDF ChildSbdf;
+ ASPM_CAPS MyAspm;
+ ASPM_CAPS ChildAspm;
+ PCI_DEV_TYPE DevType;
+
+ DEBUG ((DEBUG_INFO, "RecursiveAspmConfiguration %x:%x:%x\n", Sbdf.Bus, Sbdf.Dev, Sbdf.Func));
+
+ //
+ // On way down:
+ // pass number of links traversed; increase it per upstream port visited (not endpoint)
+ // On way up:
+ // EndPoint: read Acceptable Latencies; subtract Depth From L1AcceptableLat to account for "1us per switch additional delay"
+ // Downstreamport: AND L0s/L1 caps; calculate LinkLatency; enable L0s/L1 if supported and if acceptable latency is bigger than link latency;
+ // if L1 not enabled, add back 1us to Acceptable Latency to cancel earlier Depth subtraction
+ // UpstreamPort: calculate minimum of below Acceptable Latencies; return that, with upper link's Latency and L0s/L1 support
+ //
+ DevType = GetDeviceType(Sbdf);
+ if (DevType == DevTypePcieUpstream) {
+ Depth++;
+ }
+ MyAspm = GetAspmCaps (Sbdf);
+ //
+ // Get ASPM L0s and L1 override
+ //
+ if (Override != NULL) {
+ GetOverrideAspm (Sbdf, &MyAspm, Override);
+ }
+ if (DevType == DevTypePcieEndpoint) {
+ //
+ // Every switch between endpoint and CPU introduces 1us additional latency on L1 exit. This is reflected by
+ // subtracting 1us per switch from endpoint's acceptable L1 latency.
+ // In case L1 doesn't get enabled in one of switches, that 1us will be added back.
+ // This calculation is not precise. It ignores that some switches' added delay may be shadowed by
+ // other links' exit latency. But it guarantees that acceptable latency won't be exceeded and is simple
+ // enough to perform in a single iteration without backtracking.
+ //
+ return PatchL1AcceptableLatency (MyAspm, (-1 * Depth));
+ }
+ if (HasChildBus (Sbdf, &ChildSbdf)) {
+ while (FindNextPcieChild (DevType, &ChildSbdf)) {
+ ChildAspm = RecursiveAspmConfiguration (ChildSbdf, Depth, Override);
+ MyAspm = CombineAspm (MyAspm, ChildAspm, (DevType == DevTypePcieDownstream));
+ }
+ if (DevType == DevTypePcieDownstream) {
+ SetAspm (Sbdf, MyAspm);
+ //
+ // ASPM config must be consistent across all functions of a device. That's why there's while loop.
+ //
+ while (FindNextPcieChild (DevType, &ChildSbdf)) {
+ SetAspm (ChildSbdf, MyAspm);
+ }
+ if (!IsL1Allowed (MyAspm)) {
+ MyAspm = PatchL1AcceptableLatency (MyAspm, 1);
+ }
+ }
+ }
+ return MyAspm;
+}
+
+/**
+ Enables L1 substates for PCIE links in the hierarchy below
+ L1.1 / L1.2 can be enabled if both sides of a link support it.
+
+ @param[in] Segment,Bus,Device,Function address of currently visited PCIe device
+
+ @retval structure that describes L1ss capabilities of the device
+**/
+STATIC
+L1SS_CAPS
+RecursiveL1ssConfiguration (
+ SBDF Sbdf,
+ OVERRIDE_TABLE *Override
+ )
+{
+ UINT64 Base;
+ SBDF ChildSbdf;
+ L1SS_CAPS CombinedCaps;
+ L1SS_CAPS ChildCaps;
+ PCI_DEV_TYPE DevType;
+ BOOLEAN IsCpuPcie;
+ UINT32 DevNum;
+
+ IsCpuPcie = FALSE;
+
+ DEBUG ((DEBUG_INFO, "RecursiveL1ssConfiguration %x:%x:%x\n", Sbdf.Bus, Sbdf.Dev, Sbdf.Func));
+
+ Base = SbdfToBase (Sbdf);
+ DevNum = Sbdf.Dev;
+ if (DevNum == SA_PEG0_DEV_NUM || DevNum == SA_PEG3_DEV_NUM) {
+ IsCpuPcie = TRUE;
+ }
+ //
+ // On way down:
+ // do nothing
+ // On way up:
+ // In downstream ports, combine L1ss capabilities of that port and device behind it, then enable L1.1 and/or L1.2 if possible
+ // Return L1ss capabilities
+ //
+ if (HasChildBus (Sbdf, &ChildSbdf)) {
+ DevType = GetDeviceType (Sbdf);
+ while (FindNextPcieChild (DevType, &ChildSbdf)) {
+ ChildCaps = RecursiveL1ssConfiguration (ChildSbdf, Override);
+ if (DevType == DevTypePcieDownstream && ChildSbdf.Func == 0) {
+ CombinedCaps = CombineL1ss (GetL1ssCaps (Base, Override), ChildCaps);
+ SetL1ss (Sbdf, CombinedCaps, Override, IsCpuPcie);
+ SetL1ss (ChildSbdf, CombinedCaps, Override, IsCpuPcie);
+ }
+ }
+ }
+ return GetL1ssCaps (Base, Override);
+}
+
+/**
+ Checks if there is an IoAPIC device in the PCIe hierarchy.
+ If one is found, this function doesn't check for more and returns
+
+ @param[in] BusLimit maximum Bus number that can be assigned below this port
+ @param[in] Segment,Bus,Device,Function address of currently visited PCIe device
+
+ @retval TRUE if IoAPIC device was found
+**/
+STATIC
+BOOLEAN
+RecursiveIoApicCheck (
+ SBDF Sbdf
+ )
+{
+ SBDF ChildSbdf;
+ UINT8 IoApicPresent;
+ PCI_DEV_TYPE DevType;
+
+ DEBUG ((DEBUG_INFO, "RecursiveIoApicCheck %x:%x:%x\n", Sbdf.Bus, Sbdf.Dev, Sbdf.Func));
+
+ IoApicPresent = FALSE;
+
+ if (IsIoApicDevice (SbdfToBase (Sbdf))) {
+ DEBUG ((DEBUG_INFO, "IoApicFound @%x:%x:%x:%x\n", Sbdf.Bus, Sbdf.Dev, Sbdf.Func));
+ return TRUE;
+ }
+ if (HasChildBus (Sbdf, &ChildSbdf)) {
+ DevType = GetDeviceType (Sbdf);
+ while (FindNextPcieChild (DevType, &ChildSbdf)) {
+ IoApicPresent = RecursiveIoApicCheck (ChildSbdf);
+ if (IoApicPresent) {
+ break;
+ }
+ }
+ }
+ DEBUG ((DEBUG_INFO, "IoApic status %d @%x:%x:%x:%x\n", IoApicPresent, Sbdf.Seg, Sbdf.Bus, Sbdf.Dev, Sbdf.Func));
+ return IoApicPresent;
+}
+
+/**
+ Calculates Maximum Payload Size supported by PCIe hierarchy.
+ Starting from a device, it finds the minimum MPS supported by devices below it.
+ There are many valid strategies for setting MPS. This implementation chooses
+ one that is safest, but doesn't guarantee maximum performance:
+ Find minimum MPS under given rootport, then program that minimum value everywhere below that rootport
+
+ @param[in] BusLimit maximum Bus number that can be assigned below this port
+ @param[in] Segment,Bus,Device,Function address of currently visited PCIe device
+
+ @retval MPS supported by PCIe hierarchy, calculated as MIN(MPS of all devices below)
+**/
+STATIC
+UINT8
+RecursiveMpsCheck (
+ SBDF Sbdf
+ )
+{
+ SBDF ChildSbdf;
+ UINT8 MyMps;
+ UINT8 SubtreeMps;
+ PCI_DEV_TYPE DevType;
+
+ DEBUG ((DEBUG_INFO, "RecursiveMpsCheck %x:%x:%x\n", Sbdf.Bus, Sbdf.Dev, Sbdf.Func));
+
+ MyMps = GetMps (Sbdf);
+ if (MyMps == 0) {
+ return MyMps;
+ }
+ if (HasChildBus (Sbdf, &ChildSbdf)) {
+ DevType = GetDeviceType (Sbdf);
+ while (FindNextPcieChild (DevType, &ChildSbdf)) {
+ SubtreeMps = RecursiveMpsCheck (ChildSbdf);
+ MyMps = MIN(MyMps, SubtreeMps);
+ }
+ }
+ return MyMps;
+}
+
+/**
+ Sets Maximum Payload Size in PCIe hierarchy.
+ Starting from a device, it programs the same MPS value to it and all devices below it.
+ There are many valid strategies for setting MPS. This implementation chooses
+ one that is safest, but doesn't guarantee maximum performance:
+ Find minimum MPS under given rootport, then program that minimum value everywhere below that rootport
+
+ @param[in] BusLimit maximum Bus number that can be assigned below this port
+ @param[in] Segment,Bus,Device,Function address of currently visited PCIe device
+ @param[in] Mps Maximum Payload Size to be programmed
+**/
+STATIC
+VOID
+RecursiveMpsConfiguration (
+ SBDF Sbdf,
+ UINT8 Mps
+ )
+{
+ SBDF ChildSbdf;
+ PCI_DEV_TYPE DevType;
+
+ DEBUG ((DEBUG_INFO, "RecursiveMpsConfiguration %x:%x:%x\n", Sbdf.Bus, Sbdf.Dev, Sbdf.Func));
+
+ if (HasChildBus (Sbdf, &ChildSbdf)) {
+ DevType = GetDeviceType (Sbdf);
+ while (FindNextPcieChild (DevType, &ChildSbdf)) {
+ RecursiveMpsConfiguration (ChildSbdf, Mps);
+ }
+ }
+ SetMps (Sbdf, Mps);
+}
+
+/**
+ Sets Enable Clock Power Management bit for devices that support it.
+ A device supports CPM only if all function of this device report CPM support.
+ Downstream ports never report CPM capability, so it's only relevant for upstream ports.
+ When this function executes on upstream component, it will check CPM & set ECPM of downstream component
+ When this function executes on downstream component, all devices below it are guaranteed to
+ return CPM=0 so it will do nothing
+
+ @param[in] Segment,Bus,Device,Function address of currently visited PCIe device
+
+ @retval TRUE = this device supports CPM, FALSE = it doesn't
+**/
+STATIC
+BOOLEAN
+RecursiveCpmConfiguration (
+ SBDF Sbdf
+ )
+{
+ SBDF ChildSbdf;
+ BOOLEAN ChildCpm;
+ PCI_DEV_TYPE DevType;
+
+ DEBUG ((DEBUG_INFO, "RecursiveCpmConfiguration %x:%x:%x\n", Sbdf.Bus, Sbdf.Dev, Sbdf.Func));
+
+ ChildCpm = FALSE;
+
+ if (HasChildBus (Sbdf, &ChildSbdf)) {
+ ChildCpm = TRUE;
+ DevType = GetDeviceType (Sbdf);
+ while (FindNextPcieChild (DevType, &ChildSbdf)) {
+ ChildCpm &= RecursiveCpmConfiguration (ChildSbdf);
+ }
+ if (ChildCpm) {
+ while (FindNextPcieChild (DevType, &ChildSbdf)) {
+ EnableCpm (ChildSbdf);
+ }
+ }
+ }
+ return IsCpmSupported (Sbdf);
+}
+
+/**
+ Sets Common Clock Configuration bit for devices that share common clock across link
+ Devices on both sides of a PCIE link share common clock if both upstream component
+ and function 0 of downstream component report Slot Clock Configuration bit = 1.
+ When this function executes on upstream component, it checks SCC of both sides of the link
+ If they both support it, sets CCC for both sides (this means all functions of downstream component)
+ When this function executes on downstream component, it only returns SCC capability
+
+ @param[in] Segment,Bus,Device,Function address of currently visited PCIe device
+ @param[in] WaitForRetrain decides if this function should busy-wait for link retrain
+
+ @retval TRUE = this device supports SCC, FALSE = it doesn't
+**/
+STATIC
+BOOLEAN
+RecursiveCccConfiguration (
+ SBDF Sbdf,
+ BOOLEAN WaitForRetrain
+ )
+{
+ UINT64 Base;
+ SBDF ChildSbdf;
+ BOOLEAN MyScc;
+ BOOLEAN ChildScc;
+ BOOLEAN LinkScc;
+ PCI_DEV_TYPE DevType;
+
+ DEBUG ((DEBUG_INFO, "RecursiveCccConfiguration %x:%x:%x\n", Sbdf.Bus, Sbdf.Dev, Sbdf.Func));
+
+ ChildScc = 0;
+ Base = SbdfToBase(Sbdf);
+ MyScc = GetScc (SbdfToBase(Sbdf), (UINT8)Sbdf.PcieCap);
+ if (HasChildBus (Sbdf, &ChildSbdf)) {
+ DevType = GetDeviceType (Sbdf);
+ while (FindNextPcieChild (DevType, &ChildSbdf)) {
+ ChildScc |= RecursiveCccConfiguration (ChildSbdf, WaitForRetrain);
+ }
+ if (DevType == DevTypePcieDownstream) {
+ LinkScc = MyScc & ChildScc;
+ if (LinkScc) {
+ EnableCcc (SbdfToBase(Sbdf), (UINT8)Sbdf.PcieCap);
+ while (FindNextPcieChild (DevType, &ChildSbdf)) {
+ EnableCcc (SbdfToBase(ChildSbdf), (UINT8)ChildSbdf.PcieCap);
+ }
+ RetrainLink(Base, (UINT8)Sbdf.PcieCap, WaitForRetrain);
+ }
+ }
+ }
+ return MyScc;
+}
+
+/**
+ Configures Latency Tolerance Reporting in given device and in PCIe tree below it.
+ This function configures Maximum LTR and enables LTR mechanism. It visits devices using depth-first search
+ and skips branches behind devices which do not support LTR.
+ Maximum LTR:
+ This function will set LTR's upper bound for every visited device. Max LTR value is provided as a parameter
+ Enable LTR:
+ LTR should be enabled top-to-bottom in every visited device that supports LTR. This function does not
+ iterate down behind devices with no LTR support. In effect, LTR will be enabled in given device if that device
+ and all devices above it on the way to RootComplex do support LTR.
+
+ This function expects that bridges have bus numbers already configured
+
+ @param[in] Segment,Bus,Device,Function address of currently visited PCIe device
+ @param[in] LtrLimit Ltr to be programmed to every endpoint
+
+ @retval MaxLTR programmed in this device
+**/
+STATIC
+VOID
+RecursiveLtrConfiguration (
+ SBDF Sbdf,
+ LTR_LIMIT LtrLimit
+ )
+{
+ UINT64 Base;
+ SBDF ChildSbdf;
+ PCI_DEV_TYPE DevType;
+
+ DEBUG ((DEBUG_INFO, "RecursiveLtrConfiguration %x:%x:%x\n", Sbdf.Bus, Sbdf.Dev, Sbdf.Func));
+
+ Base = SbdfToBase(Sbdf);
+
+ if (!IsLtrCapable (Sbdf)) {
+ DEBUG ((DEBUG_INFO, "Not LtrCapable %02x:%02x:%02x\n", Sbdf.Bus, Sbdf.Dev, Sbdf.Func));
+ return;
+ }
+ EnableLtr (Sbdf);
+ if (HasChildBus (Sbdf, &ChildSbdf)) {
+ DevType = GetDeviceType (Sbdf);
+ while (FindNextPcieChild (DevType, &ChildSbdf)) {
+ RecursiveLtrConfiguration (ChildSbdf, LtrLimit);
+ }
+ }
+ SetLtrLimit (Base, LtrLimit);
+}
+
+/**
+ Checks to see device is PTM Capable
+
+ @param[in] Sbdf device's segment:bus:device:function coordinates
+
+ @retval TRUE = PTM Capability found, FALSE = Not PTM capable
+**/
+STATIC
+BOOLEAN
+IsPtmCapable (
+ SBDF Sbdf
+ )
+{
+ UINT16 CapHeaderOffset;
+
+ CapHeaderOffset = PcieFindExtendedCapId ((UINT8) Sbdf.Seg, (UINT8) Sbdf.Bus, (UINT8) Sbdf.Dev, (UINT8) Sbdf.Func, V_PCIE_EX_PTM_CID);
+
+ return (CapHeaderOffset != 0);
+}
+
+/**
+ Get PTM Capability register from PCIe Extended Capability Space.
+
+ @param[in] Sbdf device's segment:bus:device:function coordinates
+ @param[in] PtmCapHeaderOffset PTM Capability Header Offset
+
+ @retval LocalPtm Returns PTM Capability.
+ If Device is not PTM capable then PTM Capability is zeroed out.
+**/
+STATIC
+PTM_CAPS
+GetPtmCapability (
+ SBDF Sbdf,
+ UINT16 PtmCapHeaderOffset
+ )
+{
+ PTM_CAPS PtmCaps;
+
+ PtmCaps.Uint32 = 0;
+
+ if (PtmCapHeaderOffset != 0) {
+ PtmCaps.Uint32 = PciSegmentRead32 (SbdfToBase (Sbdf) + PtmCapHeaderOffset + R_PCIE_EX_PTMCAP_OFFSET);
+ }
+
+ return PtmCaps;
+}
+
+/**
+ Get PTM Control register from PCIe Extended Capability Space.
+
+ @param[in] Sbdf device's segment:bus:device:function coordinates
+ @param[in] PtmCapHeaderOffset PTM Capability Header Offset
+
+ @retval LocalPtm Returns PTM Control.
+ If Device is not PTM capable then PTM Control is zeroed out.
+**/
+STATIC
+PTM_CTRL
+GetPtmControl (
+ SBDF Sbdf,
+ UINT16 PtmCapHeaderOffset
+ )
+{
+ PTM_CTRL PtmCtrl;
+
+ PtmCtrl.Uint32 = 0;
+
+ if (PtmCapHeaderOffset != 0) {
+ PtmCtrl.Uint32 = PciSegmentRead32 (SbdfToBase (Sbdf) + PtmCapHeaderOffset + R_PCIE_EX_PTMCTL_OFFSET);
+ }
+
+ return PtmCtrl;
+}
+
+/**
+ Set PTM Control register in the PCIe Extended Capability Space.
+
+ @param[in] Sbdf device's segment:bus:device:function coordinates
+ @param[in] PtmCapHeaderOffset PTM Capability Header Offset
+ @param[in] PtmCtrl PTM Control Register
+**/
+STATIC
+VOID
+SetPtmControl (
+ SBDF Sbdf,
+ UINT16 PtmCapHeaderOffset,
+ PTM_CTRL PtmCtrl
+ )
+{
+ if (PtmCapHeaderOffset != 0) {
+ PciSegmentWrite32 (SbdfToBase (Sbdf) + PtmCapHeaderOffset + R_PCIE_EX_PTMCTL_OFFSET, PtmCtrl.Uint32);
+ }
+}
+
+/**
+ Enable PTM on device's control register. Set the Effective Clock Granularity.
+
+ @param[in] Sbdf device's segment:bus:device:function coordinates
+ @param[in out] EffectiveGranularity Effective Clock Granularity of the PTM hierarchy
+ @param[in out] PtmHierarchy Indicates if the current device is within a PTM hierarchy
+**/
+STATIC
+VOID
+SetPtm (
+ IN SBDF Sbdf,
+ IN OUT UINT8 *EffectiveGranularity,
+ IN OUT BOOLEAN *PtmHierarchy
+ )
+{
+ PTM_CTRL CurrentPtmCtrl;
+ PTM_CAPS CurrentPtmCaps;
+ PTM_CTRL OrigPtmCtrl;
+ UINT16 PtmCapHeaderOffset;
+
+ PtmCapHeaderOffset = PcieFindExtendedCapId ((UINT8) Sbdf.Seg, (UINT8) Sbdf.Bus, (UINT8) Sbdf.Dev, (UINT8) Sbdf.Func, V_PCIE_EX_PTM_CID);
+ CurrentPtmCtrl = GetPtmControl (Sbdf, PtmCapHeaderOffset);
+ CurrentPtmCaps = GetPtmCapability (Sbdf, PtmCapHeaderOffset);
+
+ OrigPtmCtrl.Uint32 = CurrentPtmCtrl.Uint32;
+
+ if ( (*PtmHierarchy == FALSE) && CurrentPtmCaps.Bits.RootCapable) {
+ // Select device as PTM Root if PTM Root is not selected.
+ CurrentPtmCtrl.Bits.RootSelect = TRUE;
+ *EffectiveGranularity = (UINT8) CurrentPtmCaps.Bits.LocalClockGranularity;
+ *PtmHierarchy = TRUE;
+ }
+
+ if (*PtmHierarchy == TRUE) {
+ // Enable PTM if device is part of a ptm hierarchy
+ CurrentPtmCtrl.Bits.Enable = TRUE;
+
+ if (CurrentPtmCaps.Bits.RequesterCapable) {
+ // Set Effective Granularity if PTM device is Requester roles.
+ CurrentPtmCtrl.Bits.EffectiveGranularity = *EffectiveGranularity;
+ }
+ }
+
+ if (OrigPtmCtrl.Uint32 != CurrentPtmCtrl.Uint32) {
+ SetPtmControl (Sbdf, PtmCapHeaderOffset, CurrentPtmCtrl);
+ }
+
+ // Update EffectiveGranularity.
+ // Set to zero if 1 or more switches between the root and endpoint report local granularity = 0.
+ // Otherwise set to the max local granularity of the hierarchy.
+ if ( ((CurrentPtmCaps.Bits.LocalClockGranularity == 0) && CurrentPtmCaps.Bits.RequesterCapable) ||
+ (*EffectiveGranularity == 0) ) {
+ *EffectiveGranularity = 0;
+ } else {
+ *EffectiveGranularity = MAX (*EffectiveGranularity, (UINT8) CurrentPtmCaps.Bits.LocalClockGranularity);
+ }
+}
+
+/**
+ Configures PTM hierarchies by searching for Endpoints and Upstream Switches
+ that are PTM capable. Each PTM device role is identified and configured accordingly.
+ PTM root capable devices are selected as PTM root if the device is not already in a
+ PTM hierarchy.
+ PTM capable Root Ports must be configured before calling this function.
+ @note: This function has not been tested with switches.
+
+ @param[in] Sbdf Address of curretly visited Pcie device
+ @param[in] EffectiveGranularity The largest Clock Granularity from Upstream Devices
+ @param[in] PtmHierarchy TRUE = Device in a PTM Hierarchy, FALSE = Not in PTM Hierarchy
+**/
+STATIC
+VOID
+RecursivePtmConfiguration (
+ SBDF Sbdf,
+ UINT8 EffectiveGranularity,
+ BOOLEAN PtmHierarchy
+ )
+{
+ SBDF ChildSbdf;
+ PCI_DEV_TYPE DevType;
+
+ DEBUG ((DEBUG_INFO, "RecursivePtmConfiguration %x:%x:%x\n", Sbdf.Bus, Sbdf.Dev, Sbdf.Func));
+
+ DevType = GetDeviceType (Sbdf);
+
+ if (IsPtmCapable (Sbdf)) {
+ //
+ // Enable PTM for PTM Capable devices (Endpoints, Upstream Switch, and Root Ports).
+ // @Note: Switches have not been tested.
+ //
+ SetPtm (Sbdf, &EffectiveGranularity, &PtmHierarchy);
+ } else if (!IsPtmCapable (Sbdf) && (DevType == DevTypePcieUpstream) ) {
+ //
+ // Non-PTM UpStream Switch Ports breaks the PTM Hierarchy.
+ // No other downstream PTM devices should be PTM enabled until a PTM Root capable device is selected.
+ //
+ PtmHierarchy = FALSE;
+ EffectiveGranularity = 0;
+ }
+
+ if (HasChildBus (Sbdf, &ChildSbdf)) {
+ while (FindNextPcieChild (DevType, &ChildSbdf)) {
+ RecursivePtmConfiguration (ChildSbdf, EffectiveGranularity, PtmHierarchy);
+ }
+ }
+}
+
+/**
+ Initializes the following features in rootport and devices behind it:
+ Maximum Payload Size (generic)
+ Rootport packet split (proprietary)
+ EonOfInterrupt forwarding (proprietary)
+ Common Clock Configuration (generic)
+
+ Generic: any code written according to PCIE Express base specification can do that.
+ Proprietary: code uses registers and features that are specific to Intel silicon
+ and probably only this Reference Code knows how to handle that.
+
+ If OEM implemented generic feature enabling in his platform code or trusts Operating System
+ to do it, then those features can be deleted from here.
+
+ CCC requires link retrain, which takes a while. CCC must happen before L0s/L1 programming.
+ If there was guarantee no code would access PCI while links retrain, it would be possible to skip this waiting
+
+ @param[in] RpSegment address of rootport on PCIe
+ @param[in] RpBus address of rootport on PCIe
+ @param[in] RpDevice address of rootport on PCIe
+ @param[in] RpFunction address of rootport on PCIe
+ @param[in] BusMin minimum Bus number that can be assigned below this rootport
+ @param[in] BusMax maximum Bus number that can be assigned below this rootport
+**/
+VOID
+RootportDownstreamConfiguration (
+ UINT8 RpSegment,
+ UINT8 RpBus,
+ UINT8 RpDevice,
+ UINT8 RpFunction,
+ UINT8 BusMin,
+ UINT8 BusMax,
+ PCI_SKU PciSku
+ )
+{
+ UINT8 Mps;
+ BOOLEAN IoApicPresent;
+ UINT64 RpBase;
+ SBDF RpSbdf;
+ SBDF_TABLE BridgeCleanupList;
+
+ IoApicPresent = FALSE;
+ RpBase = PCI_SEGMENT_LIB_ADDRESS (RpSegment, RpBus, RpDevice, RpFunction, 0);
+ if (!(IsDevicePresent (RpBase))) {
+ return;
+ }
+ RpSbdf.Seg = RpSegment;
+ RpSbdf.Bus = RpBus;
+ RpSbdf.Dev = RpDevice;
+ RpSbdf.Func = RpFunction;
+ RpSbdf.PcieCap = PcieBaseFindCapId (RpBase, EFI_PCI_CAPABILITY_ID_PCIEXP);
+
+ DEBUG ((DEBUG_INFO, "RootportDownstreamConfiguration %x:%x\n", RpDevice, RpFunction));
+ BridgeCleanupList.Count = 0;
+ RecursiveBusAssignment (RpSbdf, BusMin, BusMax, &BridgeCleanupList);
+
+ Mps = RecursiveMpsCheck (RpSbdf);
+ RecursiveMpsConfiguration (RpSbdf, Mps);
+ if (PciSku == EnumPchPcie) {
+ RpBase = SbdfToBase (RpSbdf);
+ ConfigureRpPacketSplit(RpBase, Mps);
+ IoApicPresent = RecursiveIoApicCheck(RpSbdf);
+ }
+ if ((PciSku == EnumPchPcie) || (PciSku == EnumCpuPcie)) {
+ ConfigureEoiForwarding (RpBase, IoApicPresent);
+ }
+ RecursiveCccConfiguration (RpSbdf, TRUE);
+
+ if (IsPtmCapable (RpSbdf)) {
+ RecursivePtmConfiguration (RpSbdf, 0, FALSE);
+ }
+
+ ClearBusFromTable (&BridgeCleanupList);
+}
+
+/**
+ Checks if given PCI device is capable of Latency Tolerance Reporting
+
+ @param[in] Sbdf device's segment:bus:device:function coordinates
+
+ @retval TRUE if yes
+**/
+BOOLEAN
+IsLtrCapable (
+ SBDF Sbdf
+ )
+{
+ if (Sbdf.PcieCap == 0) {
+ return FALSE;
+ }
+ return !!(PciSegmentRead32 (SbdfToBase (Sbdf) + Sbdf.PcieCap + R_PCIE_DCAP2_OFFSET) & B_PCIE_DCAP2_LTRMS);
+}
+
+/**
+ Returns combination of two LTR override values
+ The resulting LTR override separately chooses stricter limits for snoop and nosnoop
+
+ @param[in] LtrA LTR override values to be combined
+ @param[in] LtrB LTR override values to be combined
+
+ @retval LTR override value
+**/
+LTR_OVERRIDE
+CombineLtr (
+ LTR_OVERRIDE LtrA,
+ LTR_OVERRIDE LtrB
+ )
+{
+ UINT64 DecodedLatencyA;
+ UINT64 DecodedLatencyB;
+ LTR_OVERRIDE Result;
+ static UINT32 ScaleEncoding [8] = {1, 32, 1024, 32768, 1048576, 33554432, 0, 0};
+
+ ZeroMem (&Result, sizeof (LTR_OVERRIDE));
+ DecodedLatencyA = ScaleEncoding[LtrA.MaxSnoopLatencyScale] * LtrA.MaxSnoopLatencyValue;
+ DecodedLatencyB = ScaleEncoding[LtrB.MaxSnoopLatencyScale] * LtrB.MaxSnoopLatencyValue;
+ if ((!LtrB.MaxSnoopLatencyRequirement) || ((DecodedLatencyA < DecodedLatencyB) && LtrA.MaxSnoopLatencyRequirement)) {
+ Result.MaxSnoopLatencyValue = LtrA.MaxSnoopLatencyValue;
+ Result.MaxSnoopLatencyScale = LtrA.MaxSnoopLatencyScale;
+ Result.MaxSnoopLatencyRequirement = LtrA.MaxSnoopLatencyRequirement;
+ } else {
+ Result.MaxSnoopLatencyValue = LtrB.MaxSnoopLatencyValue;
+ Result.MaxSnoopLatencyScale = LtrB.MaxSnoopLatencyScale;
+ Result.MaxSnoopLatencyRequirement = LtrB.MaxSnoopLatencyRequirement;
+ }
+ DecodedLatencyA = ScaleEncoding[LtrA.MaxNoSnoopLatencyScale] * LtrA.MaxNoSnoopLatencyValue;
+ DecodedLatencyB = ScaleEncoding[LtrB.MaxNoSnoopLatencyScale] * LtrB.MaxNoSnoopLatencyValue;
+ if ((!LtrB.MaxNoSnoopLatencyRequirement) || ((DecodedLatencyA < DecodedLatencyB) && LtrA.MaxNoSnoopLatencyRequirement)) {
+ Result.MaxNoSnoopLatencyValue = LtrA.MaxNoSnoopLatencyValue;
+ Result.MaxNoSnoopLatencyScale = LtrA.MaxNoSnoopLatencyScale;
+ Result.MaxNoSnoopLatencyRequirement = LtrA.MaxNoSnoopLatencyRequirement;
+ } else {
+ Result.MaxNoSnoopLatencyValue = LtrB.MaxNoSnoopLatencyValue;
+ Result.MaxNoSnoopLatencyScale = LtrB.MaxNoSnoopLatencyScale;
+ Result.MaxNoSnoopLatencyRequirement = LtrB.MaxNoSnoopLatencyRequirement;
+ }
+ if (LtrA.ForceOverride || LtrB.ForceOverride) {
+ Result.ForceOverride = TRUE;
+ }
+ DEBUG ((DEBUG_INFO, "CombineLtr: A(V%d S%d E%d : V%d S%d E%d, F%d)\n",
+ LtrA.MaxSnoopLatencyValue, LtrA.MaxSnoopLatencyScale, LtrA.MaxSnoopLatencyRequirement,
+ LtrA.MaxNoSnoopLatencyValue, LtrA.MaxNoSnoopLatencyScale, LtrA.MaxNoSnoopLatencyRequirement,
+ LtrA.ForceOverride
+ ));
+ DEBUG ((DEBUG_INFO, " : B(V%d S%d E%d : V%d S%d E%d, F%d)\n",
+ LtrB.MaxSnoopLatencyValue, LtrB.MaxSnoopLatencyScale, LtrB.MaxSnoopLatencyRequirement,
+ LtrB.MaxNoSnoopLatencyValue, LtrB.MaxNoSnoopLatencyScale, LtrB.MaxNoSnoopLatencyRequirement,
+ LtrB.ForceOverride
+ ));
+ DEBUG ((DEBUG_INFO, " : R(V%d S%d E%d : V%d S%d E%d, F%d)\n",
+ Result.MaxSnoopLatencyValue, Result.MaxSnoopLatencyScale, Result.MaxSnoopLatencyRequirement,
+ Result.MaxNoSnoopLatencyValue, Result.MaxNoSnoopLatencyScale, Result.MaxNoSnoopLatencyRequirement,
+ Result.ForceOverride
+ ));
+ return Result;
+}
+
+/**
+ Returns LTR override value for given device
+ The value is extracted from Device Override table. If the device is not found,
+ the returned value will have Requirement bits clear
+
+ @param[in] Base device's base address
+ @param[in] Override device override table
+
+ @retval LTR override value
+**/
+LTR_OVERRIDE
+GetOverrideLtr (
+ UINT64 Base,
+ OVERRIDE_TABLE *Override
+ )
+{
+ UINT16 DevId;
+ UINT16 VenId;
+ UINT16 RevId;
+ UINT32 Index;
+ LTR_OVERRIDE ReturnValue = {0};
+
+ VenId = PciSegmentRead16 (Base + PCI_VENDOR_ID_OFFSET);
+ DevId = PciSegmentRead16 (Base + PCI_DEVICE_ID_OFFSET);
+ RevId = PciSegmentRead16 (Base + PCI_REVISION_ID_OFFSET);
+
+ for (Index = 0; Index < Override->Size; Index++) {
+ if (((Override->Table[Index].OverrideConfig & PchPcieLtrOverride) == PchPcieLtrOverride) &&
+ (Override->Table[Index].VendorId == VenId) &&
+ ((Override->Table[Index].DeviceId == DevId) || (Override->Table[Index].DeviceId == 0xFFFF)) &&
+ ((Override->Table[Index].RevId == RevId) || (Override->Table[Index].RevId == 0xFF))) {
+ if (Override->Table[Index].SnoopLatency & 0x8000) {
+ ReturnValue.MaxSnoopLatencyRequirement = 1;
+ ReturnValue.MaxSnoopLatencyValue = Override->Table[Index].SnoopLatency & 0x3FF;
+ ReturnValue.MaxSnoopLatencyScale = (Override->Table[Index].SnoopLatency & 0x1C00) >> 10;
+ }
+ if (Override->Table[Index].NonSnoopLatency & 0x8000) {
+ ReturnValue.MaxNoSnoopLatencyRequirement = 1;
+ ReturnValue.MaxNoSnoopLatencyValue = Override->Table[Index].NonSnoopLatency & 0x3FF;
+ ReturnValue.MaxNoSnoopLatencyScale = (Override->Table[Index].NonSnoopLatency & 0x1C00) >> 10;
+ }
+ ReturnValue.ForceOverride = Override->Table[Index].ForceLtrOverride;
+ break;
+ }
+ }
+ return ReturnValue;
+}
+
+/**
+ In accordance with PCIe spec, devices with no LTR support are considered to have no LTR requirements
+ which means infinite latency tolerance. This was found to cause problems with HID and Audio devices without LTR
+ support placed behind PCIe switches with LTR support, as Switch's upstream link would be allowed to enter L1.2
+ and cause large latency downstream. To work around such issues and to fix some devices with broken
+ LTR reporting, Device Override table was introduced.
+ This function scans PCIe tree for devices mentioned in override table and calculates the strictest
+ LTR requirement between them. That value will be programmed into rootport's LTR override register
+
+ This function expects that bridges have bus numbers already configured
+
+ @param[in] BusLimit maximum Bus number that can be assigned below this port
+ @param[in] Segment,Bus,Device,Function address of currently visited PCIe device
+ @param[in] AspmOverride Device specific ASPM policy override items
+
+ @retval MaxLTR programmed in this device
+**/
+LTR_OVERRIDE
+RecursiveLtrOverrideCheck (
+ SBDF Sbdf,
+ OVERRIDE_TABLE *AspmOverride
+ )
+{
+ UINT64 Base;
+ SBDF ChildSbdf;
+ LTR_OVERRIDE MyLtrOverride;
+ LTR_OVERRIDE ChildLtr;
+ PCI_DEV_TYPE DevType;
+
+ DEBUG ((DEBUG_INFO, "RecursiveLtrOverrideCheck %x:%x:%x\n", Sbdf.Bus, Sbdf.Dev, Sbdf.Func));
+
+ Base = SbdfToBase(Sbdf);
+
+ MyLtrOverride = GetOverrideLtr (Base, AspmOverride);
+ if (HasChildBus (Sbdf, &ChildSbdf)) {
+ DevType = GetDeviceType (Sbdf);
+ while (FindNextPcieChild (DevType, &ChildSbdf)) {
+ ChildLtr = RecursiveLtrOverrideCheck (ChildSbdf, AspmOverride);
+ MyLtrOverride = CombineLtr (MyLtrOverride, ChildLtr);
+ }
+ }
+ return MyLtrOverride;
+}
+
+/**
+ Configures the following power-management related features in rootport and devices behind it:
+ LTR limit (generic)
+ LTR override (proprietary)
+ Clock Power Management (generic)
+ L1 substates (generic except for the override table)
+ L1.LOW substate (proprietary)
+ L0s and L1 (generic)
+
+ Generic: any code written according to PCIE Express base specification can do that.
+ Proprietary: code uses registers and features that are specific to Intel silicon
+ and probably only this Reference Code knows how to handle that.
+
+ If OEM implemented generic feature enabling in his platform code or trusts Operating System
+ to do it, then those features can be deleted from here.
+
+ @param[in] RpSegment address of rootport on PCIe
+ @param[in] RpBus address of rootport on PCIe
+ @param[in] RpDevice address of rootport on PCIe
+ @param[in] RpFunction address of rootport on PCIe
+ @param[in] BusLimit maximum Bus number that can be assigned below this rootport
+ @param[in] PcieRpLtrConfig address of LTR Policy struct
+ @param[in] PcieRpCommonConfig address of Common PCIe Policy struct
+ @param[in] AspmOverrideTableSize size of override array
+ @param[in] AspmOverrideTable array of device that need exceptions in configuration
+**/
+VOID
+RootportDownstreamPmConfiguration (
+ UINT8 RpSegment,
+ UINT8 RpBus,
+ UINT8 RpDevice,
+ UINT8 RpFunction,
+ UINT8 BusMin,
+ UINT8 BusMax,
+ PCIE_ROOT_PORT_COMMON_CONFIG *PcieRpCommonConfig,
+ UINT32 AspmOverrideTableSize,
+ PCH_PCIE_DEVICE_OVERRIDE *AspmOverrideTable
+ )
+{
+ LTR_LIMIT PolicyLtr;
+ LTR_OVERRIDE TreeLtr;
+ OVERRIDE_TABLE PmOverrideTable;
+ UINT64 RpBase;
+ SBDF RpSbdf;
+ SBDF_TABLE BridgeCleanupList;
+
+ RpBase = PCI_SEGMENT_LIB_ADDRESS (RpSegment, RpBus, RpDevice, RpFunction, 0);
+ if (!(IsDevicePresent (RpBase))) {
+ return;
+ }
+ PmOverrideTable.Size = AspmOverrideTableSize;
+ PmOverrideTable.Table = AspmOverrideTable;
+
+ DEBUG ((DEBUG_INFO, "RootportDownstreamPmConfiguration %x:%x\n", RpDevice, RpFunction));
+ PolicyLtr.MaxNoSnoopLatencyScale = (PcieRpCommonConfig->PcieRpLtrConfig.LtrMaxNoSnoopLatency & 0x1c00) >> 10;
+ PolicyLtr.MaxNoSnoopLatencyValue = PcieRpCommonConfig->PcieRpLtrConfig.LtrMaxNoSnoopLatency & 0x3FF;
+ PolicyLtr.MaxSnoopLatencyScale = (PcieRpCommonConfig->PcieRpLtrConfig.LtrMaxSnoopLatency & 0x1c00) >> 10;
+ PolicyLtr.MaxSnoopLatencyValue = PcieRpCommonConfig->PcieRpLtrConfig.LtrMaxSnoopLatency & 0x3FF;
+
+ RpSbdf.Seg = RpSegment;
+ RpSbdf.Bus = RpBus;
+ RpSbdf.Dev = RpDevice;
+ RpSbdf.Func = RpFunction;
+ RpSbdf.PcieCap = PcieBaseFindCapId (RpBase, EFI_PCI_CAPABILITY_ID_PCIEXP);
+ //
+ // This code could execute either before or after enumeration. If before, then buses would not yet be assigned to bridges,
+ // making devices deeper in the hierarchy inaccessible.
+ // RecursiveBusAssignment will scan whole PCie tree and assign bus numbers to uninitialized bridges, if there are any
+ // List of such bridges will be kept in CleanupList, so that after PM programming is done, bus numbers can brought to original state
+ //
+ BridgeCleanupList.Count = 0;
+ RecursiveBusAssignment(RpSbdf, BusMin, BusMax, &BridgeCleanupList);
+ //
+ // The 'Recursive...' functions below expect bus numbers to be already assigned
+ //
+ RecursiveLtrConfiguration (RpSbdf, PolicyLtr);
+ TreeLtr = RecursiveLtrOverrideCheck (RpSbdf, &PmOverrideTable);
+ ConfigureRpLtrOverride (RpBase, RpSbdf.Dev, &TreeLtr, &(PcieRpCommonConfig->PcieRpLtrConfig));
+ DEBUG ((DEBUG_INFO, "ConfigureRpLtrOverride %x:%x\n", RpSbdf.Dev, RpSbdf.Func));
+ if (PcieRpCommonConfig->EnableCpm) {
+ RecursiveCpmConfiguration (RpSbdf);
+ }
+ //
+ // L1 substates can be modified only when L1 is disabled, so this function must execute
+ // before Aspm configuration which enables L1
+ //
+ RecursiveL1ssConfiguration (RpSbdf, &PmOverrideTable);
+ L1ssProprietaryConfiguration (RpBase, IsLtrCapable (RpSbdf));
+ RecursiveAspmConfiguration (RpSbdf, 0, &PmOverrideTable);
+
+ ClearBusFromTable (&BridgeCleanupList);
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PcieRp/LibraryPrivate/PciExpressHelpersLibrary/PciExpressHelpersLibrary.h b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PcieRp/LibraryPrivate/PciExpressHelpersLibrary/PciExpressHelpersLibrary.h
new file mode 100644
index 0000000000..19c1051771
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PcieRp/LibraryPrivate/PciExpressHelpersLibrary/PciExpressHelpersLibrary.h
@@ -0,0 +1,40 @@
+/** @file
+ Header file for Pci Express helps library implementation.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PCI_EXPRESS_HELPERS_LIBRARY_H_
+#define _PCI_EXPRESS_HELPERS_LIBRARY_H_
+
+#include <Uefi/UefiBaseType.h>
+#include <Library/BaseLib.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <IndustryStandard/Pci.h>
+#include <PchPolicyCommon.h>
+#include <Library/PchPcieRpLib.h>
+#include <Library/PchPcrLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/PciSegmentLib.h>
+#include <Library/GpioNativeLib.h>
+#include <Library/TimerLib.h>
+#include <Library/PciExpressHelpersLib.h>
+#include <Library/PcieRpLib.h>
+#include <PcieRegs.h>
+#include <Register/CpuPcieRegs.h>
+#include <Register/PchPcieRpRegs.h>
+
+#define LTR_VALUE_MASK (BIT0 + BIT1 + BIT2 + BIT3 + BIT4 + BIT5 + BIT6 + BIT7 + BIT8 + BIT9)
+#define LTR_SCALE_MASK (BIT10 + BIT11 + BIT12)
+
+ #define CONFIG_WRITE_LOOP_COUNT 100000
+
+//
+// LTR related macros
+//
+#define LTR_LATENCY_VALUE(x) ((x) & LTR_VALUE_MASK)
+#define LTR_SCALE_VALUE(x) (((x) & LTR_SCALE_MASK) >> 10)
+#define LTR_LATENCY_NS(x) (LTR_LATENCY_VALUE(x) * (1 << (5 * LTR_SCALE_VALUE(x))))
+
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PcieRp/LibraryPrivate/PciExpressHelpersLibrary/PeiDxeSmmPciExpressHelpersLib.inf b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PcieRp/LibraryPrivate/PciExpressHelpersLibrary/PeiDxeSmmPciExpressHelpersLib.inf
new file mode 100644
index 0000000000..8f673d14c2
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PcieRp/LibraryPrivate/PciExpressHelpersLibrary/PeiDxeSmmPciExpressHelpersLib.inf
@@ -0,0 +1,49 @@
+## @file
+# Component description file for the PeiDxeSmmPciExpressHelpersLib
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+
+[Defines]
+ INF_VERSION = 0x00010017
+ BASE_NAME = PeiDxeSmmPciExpressHelpersLib
+ FILE_GUID = 07E3F76D-6D26-419d-9053-58696A15B519
+ VERSION_STRING = 1.0
+ MODULE_TYPE = BASE
+LIBRARY_CLASS = PciExpressHelpersLib
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+
+
+
+[LibraryClasses]
+ IoLib
+ DebugLib
+ PchPcieRpLib
+ PchPcrLib
+ PchInfoLib
+ GpioLib
+ TimerLib
+ BasePcieHelperLib
+ PchPciBdfLib
+ HobLib
+ PcieRpLib
+
+[Packages]
+ MdePkg/MdePkg.dec
+ TigerlakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+ PciExpressHelpersLibrary.c
+ PciExpressHelpersLibrary.h
+
+[Guids]
+ gCpuPcieHobGuid
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PcieRp/LibraryPrivate/PcieClientRpLib/PcieClientRpLib.c b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PcieRp/LibraryPrivate/PcieClientRpLib/PcieClientRpLib.c
new file mode 100644
index 0000000000..15d295a573
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PcieRp/LibraryPrivate/PcieClientRpLib/PcieClientRpLib.c
@@ -0,0 +1,247 @@
+/** @file
+ This file contains routines that support PCI Express initialization
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include <Uefi/UefiBaseType.h>
+#include <IndustryStandard/Pci.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PcieHelperLib.h>
+#include <Library/PchSbiAccessLib.h>
+#include <Library/PchPciBdfLib.h>
+#include <Library/PcieRpLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/PchPcieRpLib.h>
+#include <Library/PsfLib.h>
+#include <Library/HobLib.h>
+#include <Register/PchPcieRpRegs.h>
+#include <Register/PcieSipRegs.h>
+#include <PcieRegs.h>
+#include <PchPcieRpInfo.h>
+#include <CpuPcieInfo.h>
+#include <CpuPcieHob.h>
+
+/**
+ Get PCIe port number for enabled port.
+ @param[in] RpBase Root Port pci segment base address
+
+ @retval Root Port number (1 based)
+**/
+UINT32
+PciePortNum (
+ IN UINT64 RpBase
+ )
+{
+ return PciSegmentRead32 (RpBase + R_PCH_PCIE_CFG_LCAP) >> N_PCH_PCIE_CFG_LCAP_PN;
+}
+
+/**
+ Get PCIe root port index
+
+ @param[in] RpBase Root Port pci segment base address
+
+ @retval Root Port index (0 based)
+**/
+UINT32
+PciePortIndex (
+ IN UINT64 RpBase
+ )
+{
+ return PciePortNum (RpBase) - 1;
+}
+
+/**
+ This function checks whether PHY lane power gating is enabled on the port.
+
+ @param[in] RpBase Root Port base address
+
+ @retval TRUE PHY power gating is enabled
+ @retval FALSE PHY power gating disabled
+**/
+BOOLEAN
+PcieIsPhyLanePgEnabled (
+ IN UINT64 RpBase
+ )
+{
+ UINT32 Data32;
+
+ Data32 = PciSegmentRead32 (RpBase + R_PCH_PCIE_CFG_PCIEPMECTL);
+ return (Data32 & B_PCH_PCIE_CFG_PCIEPMECTL_DLSULPPGE) != 0;
+}
+
+/**
+ Configures Root Port packet split.
+
+ @param[in] Segment,Bus,Device,Function address of currently visited PCIe device
+ @param[in] Mps maximum packet size
+**/
+VOID
+ConfigureRpPacketSplit (
+ UINT64 RpBase,
+ UINT8 Mps
+ )
+{
+ PciSegmentAndThenOr32 (RpBase + R_PCIE_CFG_CCFG, (UINT32) ~(B_PCIE_CFG_CCFG_UNRS), Mps << N_PCIE_CFG_CCFG_UNRS);
+}
+
+/**
+ Configures LTR override in Root Port's proprietary registers.
+
+ @param[in] Segment,Bus,Device,Function address of currently visited PCIe device
+ @param[in] DevNum currently visited device number
+ @param[in] RpConfig Root Port LTR configuration
+ @param[in] AspmOverride combination of LTR override values from all devices under this Root Port
+**/
+VOID
+ConfigureRpLtrOverride (
+ UINT64 RpBase,
+ UINT32 DevNum,
+ LTR_OVERRIDE *TreeLtr,
+ PCIE_LTR_CONFIG *LtrConfig
+ )
+{
+ UINT32 OvrEn;
+ UINT32 OvrVal;
+ BOOLEAN IsCpuPcie;
+ UINT32 LtrCfgLock;
+
+ IsCpuPcie = FALSE;
+ OvrEn = 0;
+ OvrVal = 0;
+ LtrCfgLock = 0;
+
+ if (DevNum == SA_PEG0_DEV_NUM || DevNum == SA_PEG3_DEV_NUM) {
+ IsCpuPcie = TRUE;
+ }
+
+ //
+ // LTR settings from LTROVR register only get acknowledged on rising edge of LTROVR2[1:0]
+ // If those bits were already set (that can happen on a plug-hotUnplug-hotPlug scenario),
+ // they need to be toggled
+ //
+ if (PciSegmentRead32 (RpBase + R_PCH_PCIE_CFG_LTROVR2) != 0) {
+ PciSegmentWrite32 (RpBase + R_PCH_PCIE_CFG_LTROVR2, 0);
+ }
+ //
+ // (*)LatencyOverrideMode = 0 -> no override
+ // 1 -> override with RP policy values
+ // 2 -> override with endpoint's override values
+ //
+
+ if (LtrConfig->ForceLtrOverride || TreeLtr->ForceOverride) {
+ OvrEn |= B_PCH_PCIE_CFG_LTROVR2_FORCE_OVERRIDE;
+ }
+ if (LtrConfig->LtrConfigLock == TRUE) {
+ OvrEn |= B_PCH_PCIE_CFG_LTROVR2_LOCK;
+ }
+
+ if (LtrConfig->SnoopLatencyOverrideMode == 1) {
+ OvrEn |= B_PCH_PCIE_CFG_LTROVR2_LTRSOVREN;
+ OvrVal |= LtrConfig->SnoopLatencyOverrideValue;
+ OvrVal |= LtrConfig->SnoopLatencyOverrideMultiplier << 10;
+ OvrVal |= B_PCH_PCIE_CFG_LTROVR_LTRSROVR;
+ } else if (LtrConfig->SnoopLatencyOverrideMode == 2) {
+ if (TreeLtr->MaxSnoopLatencyRequirement) {
+ OvrEn |= B_PCH_PCIE_CFG_LTROVR2_LTRSOVREN;
+ OvrVal |= TreeLtr->MaxSnoopLatencyValue;
+ OvrVal |= TreeLtr->MaxSnoopLatencyScale << 10;
+ OvrVal |= B_PCH_PCIE_CFG_LTROVR_LTRSROVR;
+ }
+ }
+ if (LtrConfig->NonSnoopLatencyOverrideMode == 1) {
+ OvrEn |= B_PCH_PCIE_CFG_LTROVR2_LTRNSOVREN;
+ OvrVal |= LtrConfig->NonSnoopLatencyOverrideValue << 16;
+ OvrVal |= LtrConfig->NonSnoopLatencyOverrideMultiplier << 26;
+ OvrVal |= B_PCH_PCIE_CFG_LTROVR_LTRNSROVR;
+ } else if (LtrConfig->NonSnoopLatencyOverrideMode == 2) {
+ if (TreeLtr->MaxNoSnoopLatencyRequirement) {
+ OvrEn |= B_PCH_PCIE_CFG_LTROVR2_LTRNSOVREN;
+ OvrVal |= TreeLtr->MaxNoSnoopLatencyValue << 16;
+ OvrVal |= TreeLtr->MaxNoSnoopLatencyScale << 26;
+ OvrVal |= B_PCH_PCIE_CFG_LTROVR_LTRNSROVR;
+ }
+ }
+ PciSegmentWrite32 (RpBase + R_PCH_PCIE_CFG_LTROVR, OvrVal);
+ PciSegmentWrite32 (RpBase + R_PCH_PCIE_CFG_LTROVR2, OvrEn);
+
+ DEBUG ((DEBUG_INFO, "ConfigureRpLtrOverride IsCpuPcie=%d\n", IsCpuPcie));
+ DEBUG ((DEBUG_INFO, "ConfigureRpLtrOverride %x Val %x En %x\n", RpBase, OvrVal, OvrEn));
+}
+
+/**
+ This function configures EOI message forwarding for PCIe port.
+ If there's an IoAPIC behind this port, forwarding will be enabled
+ Otherwise it will be disabled to minimize bus traffic
+
+ @param[in] Segment,Bus,Device,Function address of currently visited PCIe device
+ @param[in] IoApicPresent TRUE if there's IoAPIC behind this Root Port
+**/
+VOID
+ConfigureEoiForwarding (
+ UINT64 RpBase,
+ BOOLEAN IoApicPresent
+ )
+{
+ UINT32 RpIndex;
+
+ RpIndex = PciePortIndex (RpBase);
+
+ if (IoApicPresent == FALSE) {
+ PciSegmentOr32 (RpBase + R_PCH_PCIE_CFG_MPC2, B_PCH_PCIE_CFG_MPC2_EOIFD);
+ } else {
+ ///
+ /// If there is an IOAPIC discovered behind Root Port, program PSF Multicast registers
+ /// in accordance with PCH PCIe BWG PSF EOI Multicast Configuration
+ ///
+ PciSegmentAnd32 (RpBase + R_PCH_PCIE_CFG_MPC2, (UINT32)~B_PCH_PCIE_CFG_MPC2_EOIFD);
+ PsfConfigurEoiForPciePort (RpIndex);
+ }
+}
+
+/**
+ Configures proprietary parts of L1 substates configuration in Root Port
+
+ @param[in] RpSbdf segment:bus:device:function coordinates of Root Port
+ @param[in] LtrCapable TRUE if Root Port is LTR capable
+**/
+VOID
+L1ssProprietaryConfiguration (
+ UINT64 RpBase,
+ BOOLEAN LtrCapable
+ )
+{
+ BOOLEAN ClkreqSupported;
+ BOOLEAN L1ssEnabled;
+ UINT16 PcieCapOffset;
+ UINT32 Data32;
+ BOOLEAN L1LowSupported;
+
+ ClkreqSupported = PcieIsPhyLanePgEnabled (RpBase);
+
+ PcieCapOffset = PcieBaseFindExtendedCapId (RpBase, V_PCIE_EX_L1S_CID);
+ if (PcieCapOffset == 0) {
+ L1ssEnabled = FALSE;
+ } else {
+ Data32 = PciSegmentRead32 (RpBase + PcieCapOffset + R_PCIE_EX_L1SCTL1_OFFSET);
+ L1ssEnabled = Data32 & (B_PCIE_EX_L1SCAP_AL1SS | B_PCIE_EX_L1SCAP_AL12S | B_PCIE_EX_L1SCAP_PPL11S |B_PCIE_EX_L1SCAP_PPL12S);
+ }
+ L1LowSupported = ClkreqSupported && LtrCapable && !L1ssEnabled;
+
+ ///
+ /// If L1.SNOOZ and L1.OFF (L1 Sub-States) are not supported and per-port CLKREQ# is supported, and LTR is supported:
+ /// Enable L1.LOW by setting Dxx:Fn:420[17] = 1b
+ ///
+ if (L1LowSupported) {
+ PciSegmentOr32 (RpBase + R_PCH_PCIE_CFG_PCIEPMECTL, (UINT32) B_PCH_PCIE_CFG_PCIEPMECTL_L1LE);
+ } else {
+ PciSegmentAnd32 (RpBase + R_PCH_PCIE_CFG_PCIEPMECTL, (UINT32) ~B_PCH_PCIE_CFG_PCIEPMECTL_L1LE);
+ }
+
+ if (L1LowSupported || L1ssEnabled) {
+ ///
+ /// f. Set Dxx:Fn:420h[0] to 1b prior to L1 enabling if any L1substate is enabled (including L1.LOW)
+ ///
+ PciSegmentOr32 (RpBase + R_PCH_PCIE_CFG_PCIEPMECTL, B_PCH_PCIE_CFG_PCIEPMECTL_L1FSOE);
+ }
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PcieRp/LibraryPrivate/PcieClientRpLib/PcieClientRpLib.inf b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PcieRp/LibraryPrivate/PcieClientRpLib/PcieClientRpLib.inf
new file mode 100644
index 0000000000..86dceb14ee
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/PcieRp/LibraryPrivate/PcieClientRpLib/PcieClientRpLib.inf
@@ -0,0 +1,43 @@
+## @file
+# Component description file for the PcieClientRpLib
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+
+[Defines]
+ INF_VERSION = 0x00010017
+ BASE_NAME = PcieClientRpLib
+ FILE_GUID = 77EB467D-674C-4C20-A13E-381600E182C4
+ VERSION_STRING = 1.0
+ MODULE_TYPE = BASE
+ LIBRARY_CLASS = PcieRpLib
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+
+
+[LibraryClasses]
+ IoLib
+ DebugLib
+ PchPcieRpLib
+ PchPcrLib
+ PchInfoLib
+ GpioLib
+ TimerLib
+ PsfLib
+ BasePcieHelperLib
+ PchPciBdfLib
+
+[Packages]
+ MdePkg/MdePkg.dec
+ TigerlakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+ PcieClientRpLib.c
--
2.24.0.windows.2
^ permalink raw reply related [flat|nested] 42+ messages in thread
* [Patch V3 24/40] TigerlakeSiliconPkg/IpBlock: Add Pmc component
2021-02-05 7:40 [Patch V3 01/40] TigerlakeSiliconPkg: Add package and Include/ConfigBlock headers Heng Luo
` (21 preceding siblings ...)
2021-02-05 7:40 ` [Patch V3 23/40] TigerlakeSiliconPkg/IpBlock: Add PcieRp component Heng Luo
@ 2021-02-05 7:40 ` Heng Luo
2021-02-05 7:40 ` [Patch V3 25/40] TigerlakeSiliconPkg/IpBlock: Add Psf component Heng Luo
` (15 subsequent siblings)
38 siblings, 0 replies; 42+ messages in thread
From: Heng Luo @ 2021-02-05 7:40 UTC (permalink / raw)
To: devel; +Cc: Sai Chaganty, Nate DeSimone
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3171
Adds the following files:
* IpBlock/Pmc/IncludePrivate
* IpBlock/Pmc/Library
* IpBlock/Pmc/LibraryPrivate
Cc: Sai Chaganty <rangasai.v.chaganty@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Signed-off-by: Heng Luo <heng.luo@intel.com>
---
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Pmc/IncludePrivate/Library/PmcPrivateLib.h | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Pmc/IncludePrivate/Register/PmcRegsVer2.h | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Pmc/Library/PeiDxeSmmPmcLib/PeiDxeSmmPmcLib.inf | 42 ++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Pmc/Library/PeiDxeSmmPmcLib/PmcLib.c | 545 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Pmc/LibraryPrivate/PeiDxeSmmPmcPrivateLib/PeiDxeSmmPmcPrivateLibVer2.inf | 39 +++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Pmc/LibraryPrivate/PeiDxeSmmPmcPrivateLib/PeiDxeSmmPmcPrivateLibWithS3.inf | 40 ++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Pmc/LibraryPrivate/PeiDxeSmmPmcPrivateLib/PmcPrivateLib.c | 166 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Pmc/LibraryPrivate/PeiDxeSmmPmcPrivateLib/PmcPrivateLibWithS3.c | 122 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
8 files changed, 1126 insertions(+)
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Pmc/IncludePrivate/Library/PmcPrivateLib.h b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Pmc/IncludePrivate/Library/PmcPrivateLib.h
new file mode 100644
index 0000000000..0f2f251d57
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Pmc/IncludePrivate/Library/PmcPrivateLib.h
@@ -0,0 +1,120 @@
+/** @file
+ Header file for private PmcLib.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PMC_PRIVATE_LIB_H_
+#define _PMC_PRIVATE_LIB_H_
+
+#include <Library/PmcLib.h>
+#include "Register/PmcRegs.h"
+
+/**
+ This function checks if GbE device is supported (not disabled by fuse)
+
+ @retval GbE support state
+**/
+BOOLEAN
+PmcIsGbeSupported (
+ VOID
+ );
+
+/**
+ This function checks if LAN wake from DeepSx is enabled
+
+ @retval Lan Wake state
+**/
+BOOLEAN
+PmcIsLanDeepSxWakeEnabled (
+ VOID
+ );
+
+/**
+ This function sets SMI Lock with S3 Boot Script programming
+**/
+VOID
+PmcLockSmiWithS3BootScript (
+ VOID
+ );
+
+/**
+ This function sets eSPI SMI Lock
+ @attention This function must be called after eSPI SMI generation has been enabled.
+ This setting is required in all boot modes and before EndOfDxe.
+ If set value will be restored upon S3 resume by bootscript.
+**/
+VOID
+PmcLockEspiSmiWithS3BootScript (
+ VOID
+ );
+
+/**
+ This function checks if eSPI SMI Lock is set
+
+ @retval eSPI SMI Lock state
+**/
+BOOLEAN
+PmcIsEspiSmiLockSet (
+ VOID
+ );
+
+typedef enum {
+ PmcSwSmiRate1p5ms = 0,
+ PmcSwSmiRate16ms,
+ PmcSwSmiRate32ms,
+ PmcSwSmiRate64ms
+} PMC_SWSMI_RATE;
+
+/**
+ This function sets SW SMI Rate.
+
+ @param[in] SwSmiRate Refer to PMC_SWSMI_RATE for possible values
+**/
+VOID
+PmcSetSwSmiRate (
+ IN PMC_SWSMI_RATE SwSmiRate
+ );
+
+typedef enum {
+ PmcPeriodicSmiRate8s = 0,
+ PmcPeriodicSmiRate16s,
+ PmcPeriodicSmiRate32s,
+ PmcPeriodicSmiRate64s
+} PMC_PERIODIC_SMI_RATE;
+
+/**
+ This function sets Periodic SMI Rate.
+
+ @param[in] PeriodicSmiRate Refer to PMC_PERIODIC_SMI_RATE for possible values
+**/
+VOID
+PmcSetPeriodicSmiRate (
+ IN PMC_PERIODIC_SMI_RATE PeriodicSmiRate
+ );
+
+/**
+ This function reads Power Button Level
+
+ @retval State of PWRBTN# signal (0: Low, 1: High)
+**/
+UINT8
+PmcGetPwrBtnLevel (
+ VOID
+ );
+
+/**
+ This function gets Group to GPE0 configuration
+
+ @param[out] GpeDw0Value GPIO Group to GPE_DW0 assignment
+ @param[out] GpeDw1Value GPIO Group to GPE_DW1 assignment
+ @param[out] GpeDw2Value GPIO Group to GPE_DW2 assignment
+**/
+VOID
+PmcGetGpioGpe (
+ OUT UINT32 *GpeDw0Value,
+ OUT UINT32 *GpeDw1Value,
+ OUT UINT32 *GpeDw2Value
+ );
+
+#endif // _PMC_PRIVATE_LIB_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Pmc/IncludePrivate/Register/PmcRegsVer2.h b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Pmc/IncludePrivate/Register/PmcRegsVer2.h
new file mode 100644
index 0000000000..986173dd7d
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Pmc/IncludePrivate/Register/PmcRegsVer2.h
@@ -0,0 +1,52 @@
+/** @file
+ Register names for Ver2 PCH PMC device
+
+ Conventions:
+
+ - Register definition format:
+ Prefix_[GenerationName]_[ComponentName]_SubsystemName_RegisterSpace_RegisterName
+ - Prefix:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register size
+ Definitions beginning with "N_" are the bit position
+ - [GenerationName]:
+ Three letter acronym of the generation is used (e.g. SKL,KBL,CNL etc.).
+ Register name without GenerationName applies to all generations.
+ - [ComponentName]:
+ This field indicates the component name that the register belongs to (e.g. PCH, SA etc.)
+ Register name without ComponentName applies to all components.
+ Register that is specific to -LP denoted by "_PCH_LP_" in component name.
+ - SubsystemName:
+ This field indicates the subsystem name of the component that the register belongs to
+ (e.g. PCIE, USB, SATA, GPIO, PMC etc.).
+ - RegisterSpace:
+ MEM - MMIO space register of subsystem.
+ IO - IO space register of subsystem.
+ PCR - Private configuration register of subsystem.
+ CFG - PCI configuration space register of subsystem.
+ - RegisterName:
+ Full register name.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PCH_REGS_PMC_TGL_H_
+#define _PCH_REGS_PMC_TGL_H_
+
+//
+// PWRM Registers
+//
+#define V_TGL_PCH_LP_PMC_PWRM_GPIO_CFG_GPP_B 0x0
+#define V_TGL_PCH_LP_PMC_PWRM_GPIO_CFG_GPP_A 0x2
+#define V_TGL_PCH_LP_PMC_PWRM_GPIO_CFG_GPP_R 0x3
+#define V_TGL_PCH_LP_PMC_PWRM_GPIO_CFG_GPD 0x4
+#define V_TGL_PCH_LP_PMC_PWRM_GPIO_CFG_GPP_S 0x5
+#define V_TGL_PCH_LP_PMC_PWRM_GPIO_CFG_GPP_H 0x6
+#define V_TGL_PCH_LP_PMC_PWRM_GPIO_CFG_GPP_D 0x7
+#define V_TGL_PCH_LP_PMC_PWRM_GPIO_CFG_GPP_F 0xA
+#define V_TGL_PCH_LP_PMC_PWRM_GPIO_CFG_GPP_C 0xB
+#define V_TGL_PCH_LP_PMC_PWRM_GPIO_CFG_GPP_E 0xC
+
+#endif // _PCH_REGS_PMC_TGL_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Pmc/Library/PeiDxeSmmPmcLib/PeiDxeSmmPmcLib.inf b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Pmc/Library/PeiDxeSmmPmcLib/PeiDxeSmmPmcLib.inf
new file mode 100644
index 0000000000..eba6db767c
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Pmc/Library/PeiDxeSmmPmcLib/PeiDxeSmmPmcLib.inf
@@ -0,0 +1,42 @@
+## @file
+# PEI/DXE/SMM PCH PMC Lib.
+#
+# All function in this library is available for PEI, DXE, and SMM,
+# But do not support UEFI RUNTIME environment call.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiDxeSmmPmcLib
+FILE_GUID = 9D60C364-5086-41E3-BC9D-C62AB7233DBF
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = PmcLib
+
+
+[LibraryClasses]
+BaseLib
+IoLib
+DebugLib
+PciSegmentLib
+PchCycleDecodingLib
+PchPcrLib
+PchInfoLib
+BaseMemoryLib
+
+[Packages]
+MdePkg/MdePkg.dec
+TigerlakeSiliconPkg/SiPkg.dec
+
+
+[Pcd]
+gSiPkgTokenSpaceGuid.PcdAcpiBaseAddress
+gSiPkgTokenSpaceGuid.PcdTcoBaseAddress
+
+[Sources]
+PmcLib.c
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Pmc/Library/PeiDxeSmmPmcLib/PmcLib.c b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Pmc/Library/PeiDxeSmmPmcLib/PmcLib.c
new file mode 100644
index 0000000000..78e596b268
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Pmc/Library/PeiDxeSmmPmcLib/PmcLib.c
@@ -0,0 +1,545 @@
+/** @file
+ PCH PMC Library.
+ All function in this library is available for PEI, DXE, and SMM,
+ But do not support UEFI RUNTIME environment call.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PciSegmentLib.h>
+#include <Library/PchCycleDecodingLib.h>
+#include <Library/PmcLib.h>
+#include <Library/PchPcrLib.h>
+#include <Library/PchInfoLib.h>
+#include <PchReservedResources.h>
+#include <Register/PmcRegs.h>
+#include <Register/PchRegs.h>
+
+/**
+ Get PCH ACPI base address.
+
+ @retval Address Address of PWRM base address.
+**/
+UINT16
+PmcGetAcpiBase (
+ VOID
+ )
+{
+ return PcdGet16 (PcdAcpiBaseAddress);
+}
+
+/**
+ Get PCH PWRM base address.
+
+ @retval Address Address of PWRM base address.
+**/
+UINT32
+PmcGetPwrmBase (
+ VOID
+ )
+{
+ return PCH_PWRM_BASE_ADDRESS;
+}
+
+/**
+ This function enables Power Button SMI
+**/
+VOID
+PmcEnablePowerButtonSmi (
+ VOID
+ )
+{
+ IoOr16 (PmcGetAcpiBase () + R_ACPI_IO_PM1_EN, B_ACPI_IO_PM1_EN_PWRBTN);
+}
+
+/**
+ This function disables Power Button SMI
+**/
+VOID
+PmcDisablePowerButtonSmi (
+ VOID
+ )
+{
+ IoAnd16 (PmcGetAcpiBase () + R_ACPI_IO_PM1_EN, (UINT16)~B_ACPI_IO_PM1_EN_PWRBTN);
+}
+
+/**
+ This function reads PM Timer Count driven by 3.579545 MHz clock
+
+ @retval PM Timer Count
+**/
+UINT32
+PmcGetTimerCount (
+ VOID
+ )
+{
+ return IoRead32 (PmcGetAcpiBase () + R_ACPI_IO_PM1_TMR) & B_ACPI_IO_PM1_TMR_VAL;
+}
+
+/**
+ Get Sleep Type that platform has waken from
+
+ @retval SleepType Sleep Type
+**/
+PMC_SLEEP_STATE
+PmcGetSleepTypeAfterWake (
+ VOID
+ )
+{
+ UINT16 AcpiBase;
+ UINT32 PmconA;
+
+ AcpiBase = PmcGetAcpiBase ();
+ PmconA = MmioRead32 (PmcGetPwrmBase () + R_PMC_PWRM_GEN_PMCON_A);
+
+ DEBUG ((DEBUG_INFO, "PWRM_PMCON_A = 0x%x\n", PmconA));
+
+ //
+ // If Global Reset Status, Power Failure. Host Reset Status bits are set, return S5 State
+ //
+ if ((PmconA & (B_PMC_PWRM_GEN_PMCON_A_GBL_RST_STS | B_PMC_PWRM_GEN_PMCON_A_PWR_FLR | B_PMC_PWRM_GEN_PMCON_A_HOST_RST_STS)) != 0) {
+ return PmcNotASleepState;
+ }
+
+ if (IoRead16 (AcpiBase + R_ACPI_IO_PM1_STS) & B_ACPI_IO_PM1_STS_WAK) {
+ switch (IoRead16 (AcpiBase + R_ACPI_IO_PM1_CNT) & B_ACPI_IO_PM1_CNT_SLP_TYP) {
+ case V_ACPI_IO_PM1_CNT_S0:
+ return PmcInS0State;
+
+ case V_ACPI_IO_PM1_CNT_S1:
+ return PmcS1SleepState;
+
+ case V_ACPI_IO_PM1_CNT_S3:
+ return PmcS3SleepState;
+
+ case V_ACPI_IO_PM1_CNT_S4:
+ return PmcS4SleepState;
+
+ case V_ACPI_IO_PM1_CNT_S5:
+ return PmcS5SleepState;
+
+ default:
+ ASSERT (FALSE);
+ return PmcUndefinedState;
+ }
+ } else {
+ return PmcNotASleepState;
+ }
+}
+
+/**
+ Clear PMC Wake Status
+**/
+VOID
+PmcClearWakeStatus (
+ VOID
+ )
+{
+ IoWrite16 (PmcGetAcpiBase () + R_ACPI_IO_PM1_STS, B_ACPI_IO_PM1_STS_WAK);
+}
+
+/**
+ Configure sleep state
+
+ @param[in] SleepState S0/S1/S3/S4/S5, refer to PMC_SLEEP_STATE
+**/
+VOID
+PmcSetSleepState (
+ PMC_SLEEP_STATE SleepState
+ )
+{
+ UINT16 Data16;
+
+ switch (SleepState) {
+ case PmcInS0State:
+ Data16 = V_ACPI_IO_PM1_CNT_S0;
+ break;
+
+ case PmcS1SleepState:
+ Data16 = V_ACPI_IO_PM1_CNT_S1;
+ break;
+
+ case PmcS3SleepState:
+ Data16 = V_ACPI_IO_PM1_CNT_S3;
+ break;
+
+ case PmcS4SleepState:
+ Data16 = V_ACPI_IO_PM1_CNT_S4;
+ break;
+
+ case PmcS5SleepState:
+ Data16 = V_ACPI_IO_PM1_CNT_S5;
+ break;
+
+ default:
+ ASSERT (FALSE);
+ return;
+
+ }
+ IoAndThenOr16 (PmcGetAcpiBase () + R_ACPI_IO_PM1_CNT, (UINT16) ~B_ACPI_IO_PM1_CNT_SLP_TYP, Data16);
+}
+
+/**
+ Check if platform boots after shutdown caused by power button override event
+
+ @retval TRUE Power Button Override occurred in last system boot
+ @retval FALSE Power Button Override didn't occur
+**/
+BOOLEAN
+PmcIsPowerButtonOverrideDetected (
+ VOID
+ )
+{
+ return ((IoRead16 (PmcGetAcpiBase () + R_ACPI_IO_PM1_STS) & B_ACPI_IO_PM1_STS_PRBTNOR) != 0);
+}
+
+/**
+ This function sets tPCH25 timing
+
+ @param[in] TimingValue tPCH25 timing value (10us, 100us, 1ms, 10ms)
+**/
+VOID
+PmcSetTPch25Timing (
+ IN PMC_TPCH25_TIMING TimingValue
+ )
+{
+ ASSERT (TimingValue <= PmcTPch25_10ms);
+
+ MmioAndThenOr32 (
+ (UINTN) (PmcGetPwrmBase () + R_PMC_PWRM_CFG),
+ (UINT32)~(B_PMC_PWRM_CFG_TIMING_TPCH25),
+ TimingValue
+ );
+}
+
+/**
+ This function checks if RTC Power Failure occurred by
+ reading RTC_PWR_FLR bit
+
+ @retval RTC Power Failure state: TRUE - Battery is always present.
+ FALSE - CMOS is cleared.
+**/
+BOOLEAN
+PmcIsRtcBatteryGood (
+ VOID
+ )
+{
+ return ((MmioRead8 (PmcGetPwrmBase () + R_PMC_PWRM_GEN_PMCON_B) & B_PMC_PWRM_GEN_PMCON_B_RTC_PWR_STS) == 0);
+}
+
+/**
+ This function checks if Power Failure occurred by
+ reading PWR_FLR bit
+
+ @retval Power Failure state
+**/
+BOOLEAN
+PmcIsPowerFailureDetected (
+ VOID
+ )
+{
+ return ((MmioRead16 (PmcGetPwrmBase () + R_PMC_PWRM_GEN_PMCON_A) & B_PMC_PWRM_GEN_PMCON_A_PWR_FLR) != 0);
+}
+
+/**
+ This function checks if Power Failure occurred by
+ reading SUS_PWR_FLR bit
+
+ @retval SUS Power Failure state
+**/
+BOOLEAN
+PmcIsSusPowerFailureDetected (
+ VOID
+ )
+{
+ return ((MmioRead32 (PmcGetPwrmBase () + R_PMC_PWRM_GEN_PMCON_A) & B_PMC_PWRM_GEN_PMCON_A_SUS_PWR_FLR) != 0);
+}
+
+/**
+ This function clears Power Failure status (PWR_FLR)
+**/
+VOID
+PmcClearPowerFailureStatus (
+ VOID
+ )
+{
+ //
+ // Write 1 to clear PWR_FLR
+ // Avoid clearing other W1C bits
+ //
+ MmioAndThenOr8 (
+ PmcGetPwrmBase () + R_PMC_PWRM_GEN_PMCON_A + 1,
+ (UINT8) ~(B_PMC_PWRM_GEN_PMCON_A_HOST_RST_STS >> 8),
+ B_PMC_PWRM_GEN_PMCON_A_PWR_FLR >> 8
+ );
+}
+
+/**
+ This function clears Global Reset status (GBL_RST_STS)
+**/
+VOID
+PmcClearGlobalResetStatus (
+ VOID
+ )
+{
+ //
+ // Write 1 to clear GBL_RST_STS
+ // Avoid clearing other W1C bits
+ //
+ MmioAndThenOr8 (
+ PmcGetPwrmBase () + R_PMC_PWRM_GEN_PMCON_A + 3,
+ (UINT8) ~0,
+ B_PMC_PWRM_GEN_PMCON_A_GBL_RST_STS >> 24
+ );
+}
+
+/**
+ This function clears Host Reset status (HOST_RST_STS)
+**/
+VOID
+PmcClearHostResetStatus (
+ VOID
+ )
+{
+ //
+ // Write 1 to clear HOST_RST_STS
+ // Avoid clearing other W1C bits
+ //
+ MmioAndThenOr8 (
+ PmcGetPwrmBase () + R_PMC_PWRM_GEN_PMCON_A + 1,
+ (UINT8) ~(B_PMC_PWRM_GEN_PMCON_A_PWR_FLR >> 8),
+ B_PMC_PWRM_GEN_PMCON_A_HOST_RST_STS >> 8
+ );
+}
+
+/**
+ This function clears SUS Power Failure status (SUS_PWR_FLR)
+**/
+VOID
+PmcClearSusPowerFailureStatus (
+ VOID
+ )
+{
+ //
+ // BIOS clears this bit by writing a '1' to it.
+ // Take care of other fields, so we don't clear them accidentally.
+ //
+ MmioAndThenOr8 (
+ PmcGetPwrmBase () + R_PMC_PWRM_GEN_PMCON_A + 2,
+ (UINT8) ~(B_PMC_PWRM_GEN_PMCON_A_MS4V >> 16),
+ B_PMC_PWRM_GEN_PMCON_A_SUS_PWR_FLR >> 16
+ );
+}
+
+/**
+ This function sets state to which platform will get after power is reapplied
+
+ @param[in] PowerStateAfterG3 0: S0 state (boot)
+ 1: S5/S4 State
+**/
+VOID
+PmcSetPlatformStateAfterPowerFailure (
+ IN UINT8 PowerStateAfterG3
+ )
+{
+ UINT32 PchPwrmBase;
+
+ PchPwrmBase = PmcGetPwrmBase ();
+
+ if (PowerStateAfterG3) {
+ MmioOr8 (PchPwrmBase + R_PMC_PWRM_GEN_PMCON_A, B_PMC_PWRM_GEN_PMCON_A_AFTERG3_EN);
+ } else {
+ MmioAnd8 (PchPwrmBase + R_PMC_PWRM_GEN_PMCON_A, (UINT8)~B_PMC_PWRM_GEN_PMCON_A_AFTERG3_EN);
+ }
+}
+
+/**
+ This function will set the DISB - DRAM Initialization Scratchpad Bit.
+**/
+VOID
+PmcSetDramInitScratchpad (
+ VOID
+ )
+{
+ //
+ // Set B_CNL_PCH_PWRM_GEN_PMCON_A_DISB.
+ // NOTE: Byte access and not clear BIT18 and BIT16 (W1C bits)
+ //
+ MmioAndThenOr8 (
+ PmcGetPwrmBase () + R_PMC_PWRM_GEN_PMCON_A + 2,
+ (UINT8) ~((B_PMC_PWRM_GEN_PMCON_A_MS4V | B_PMC_PWRM_GEN_PMCON_A_SUS_PWR_FLR) >> 16),
+ B_PMC_PWRM_GEN_PMCON_A_DISB >> 16
+ );
+}
+
+/**
+ Check global SMI enable is set
+
+ @retval TRUE Global SMI enable is set
+ FALSE Global SMI enable is not set
+**/
+BOOLEAN
+PmcIsGblSmiEn (
+ VOID
+ )
+{
+ return !!(IoRead32 (PmcGetAcpiBase () + R_ACPI_IO_SMI_EN) & B_ACPI_IO_SMI_EN_GBL_SMI);
+}
+
+/**
+ This function checks if SMI Lock is set
+
+ @retval SMI Lock state
+**/
+BOOLEAN
+PmcIsSmiLockSet (
+ VOID
+ )
+{
+ return ((MmioRead8 ((UINTN) (PmcGetPwrmBase () + R_PMC_PWRM_GEN_PMCON_B)) & B_PMC_PWRM_GEN_PMCON_B_SMI_LOCK) != 0);
+}
+
+/**
+ This function checks if Debug Mode is locked
+
+ @retval Debug Mode Lock state
+**/
+BOOLEAN
+PmcIsDebugModeLocked (
+ VOID
+ )
+{
+ //
+ // Get lock info from PWRMBASE + PM_CFG
+ //
+ return ((MmioRead32 (PmcGetPwrmBase () + R_PMC_PWRM_CFG) & B_PMC_PWRM_CFG_DBG_MODE_LOCK) != 0);
+}
+
+/**
+ Check TCO second timeout status.
+
+ @retval TRUE TCO reboot happened.
+ @retval FALSE TCO reboot didn't happen.
+**/
+BOOLEAN
+TcoSecondToHappened (
+ VOID
+ )
+{
+ ///
+ /// Read the Second TO status bit
+ ///
+ if ((IoRead8 (PcdGet16 (PcdTcoBaseAddress) + R_TCO_IO_TCO2_STS) & R_TCO_IO_TCO2_STS) != 0) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+/**
+ This function clears the Second TO status bit
+**/
+VOID
+TcoClearSecondToStatus (
+ VOID
+ )
+{
+ IoWrite8 (PcdGet16 (PcdTcoBaseAddress) + R_TCO_IO_TCO2_STS, B_TCO_IO_TCO2_STS_SECOND_TO);
+}
+
+/**
+ Check TCO SMI ENABLE is locked
+
+ @retval TRUE TCO SMI ENABLE is locked
+ FALSE TCO SMI ENABLE is not locked
+**/
+BOOLEAN
+TcoIsSmiLock (
+ VOID
+ )
+{
+ return !!(IoRead16 (PcdGet16 (PcdTcoBaseAddress) + R_TCO_IO_TCO1_CNT) & B_TCO_IO_TCO1_CNT_LOCK);
+}
+
+/**
+ Check if user wants to turn off in PEI phase and power it off
+ CAUTION: this function will potentially turn off your system
+**/
+VOID
+CheckPowerOffNow (
+ VOID
+ )
+{
+ UINT16 ABase;
+ UINT16 Pm1Sts;
+
+ ABase = PmcGetAcpiBase ();
+
+ //
+ // Read and check the ACPI registers
+ //
+ Pm1Sts = IoRead16 (ABase + R_ACPI_IO_PM1_STS);
+
+ DEBUG ((DEBUG_ERROR, "CheckPowerOffNow ()- Pm1Sts= 0x%04x\n", Pm1Sts));
+
+ if ((Pm1Sts & B_ACPI_IO_PM1_STS_PWRBTN) != 0) {
+ IoWrite16 (ABase + R_ACPI_IO_PM1_STS, B_ACPI_IO_PM1_STS_PWRBTN);
+ IoWrite16 (ABase + R_ACPI_IO_PM1_CNT, V_ACPI_IO_PM1_CNT_S5);
+ IoWrite16 (ABase + R_ACPI_IO_PM1_CNT, V_ACPI_IO_PM1_CNT_S5 | B_ACPI_IO_PM1_CNT_SLP_EN);
+ }
+}
+
+/**
+ Clear any SMI status or wake status.
+**/
+VOID
+ClearSmiAndWake (
+ VOID
+ )
+{
+ UINT16 ABase;
+ UINT16 Pm1Sts;
+
+ ABase = PmcGetAcpiBase ();
+
+ //
+ // Clear any SMI or wake state from the boot
+ //
+ Pm1Sts = B_ACPI_IO_PM1_STS_PWRBTN;
+
+ IoWrite16 (ABase + R_ACPI_IO_PM1_STS, Pm1Sts);
+
+ //
+ // Clear the GPE and PM enable
+ //
+ IoWrite16 (ABase + R_ACPI_IO_PM1_EN, 0);
+ IoWrite32 (ABase + R_ACPI_IO_GPE0_EN_127_96, 0);
+}
+
+
+/**
+ Function to check if Dirty Warm Reset occurs
+ (Global Reset has been converted to Host Reset)
+
+ @reval TRUE DWR occurs
+ @reval FALSE Normal boot flow
+**/
+BOOLEAN
+PmcIsDwrBootMode (
+ VOID
+ )
+{
+ UINT32 PchPwrmBase;
+
+ PchPwrmBase = PmcGetPwrmBase ();
+ ASSERT (PchPwrmBase != 0);
+
+ return !!(MmioRead32 (PchPwrmBase + R_PMC_PWRM_HPR_CAUSE0) & B_PMC_PWRM_HPR_CAUSE0_GBL_TO_HOST);
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Pmc/LibraryPrivate/PeiDxeSmmPmcPrivateLib/PeiDxeSmmPmcPrivateLibVer2.inf b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Pmc/LibraryPrivate/PeiDxeSmmPmcPrivateLib/PeiDxeSmmPmcPrivateLibVer2.inf
new file mode 100644
index 0000000000..2bd57b79f0
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Pmc/LibraryPrivate/PeiDxeSmmPmcPrivateLib/PeiDxeSmmPmcPrivateLibVer2.inf
@@ -0,0 +1,39 @@
+## @file
+# PEI/DXE/SMM PCH PMC Private Lib Ver2.
+#
+# All function in this library is available for PEI, DXE, and SMM,
+# But do not support UEFI RUNTIME environment call.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiDxeSmmPmcPrivateLibVer2
+FILE_GUID = EB69B12B-6D4C-4B12-BB31-66CBCC4C1DC7
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = PmcPrivateLib
+
+
+[LibraryClasses]
+BaseLib
+IoLib
+DebugLib
+PmcLib
+
+[Packages]
+MdePkg/MdePkg.dec
+TigerlakeSiliconPkg/SiPkg.dec
+
+
+[Pcd]
+gSiPkgTokenSpaceGuid.PcdAcpiBaseAddress
+
+[FixedPcd]
+
+[Sources]
+PmcPrivateLib.c
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Pmc/LibraryPrivate/PeiDxeSmmPmcPrivateLib/PeiDxeSmmPmcPrivateLibWithS3.inf b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Pmc/LibraryPrivate/PeiDxeSmmPmcPrivateLib/PeiDxeSmmPmcPrivateLibWithS3.inf
new file mode 100644
index 0000000000..72a21cfe14
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Pmc/LibraryPrivate/PeiDxeSmmPmcPrivateLib/PeiDxeSmmPmcPrivateLibWithS3.inf
@@ -0,0 +1,40 @@
+## @file
+# PEI/DXE/SMM PCH private PMC Lib.
+# This part of PMC lib includes S3BootScript support
+#
+# All function in this library is available for PEI, DXE, and SMM,
+# But do not support UEFI RUNTIME environment call.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiDxeSmmPmcPrivateLibWithS3
+FILE_GUID = 5890CA5A-1955-4A02-A09C-01E4150606CC
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = PmcPrivateLibWithS3
+
+
+[LibraryClasses]
+BaseLib
+IoLib
+DebugLib
+PciSegmentLib
+PmcLib
+PcdLib
+S3BootScriptLib
+PchPciBdfLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+TigerlakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+PmcPrivateLibWithS3.c
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Pmc/LibraryPrivate/PeiDxeSmmPmcPrivateLib/PmcPrivateLib.c b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Pmc/LibraryPrivate/PeiDxeSmmPmcPrivateLib/PmcPrivateLib.c
new file mode 100644
index 0000000000..4f04765886
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Pmc/LibraryPrivate/PeiDxeSmmPmcPrivateLib/PmcPrivateLib.c
@@ -0,0 +1,166 @@
+/** @file
+ PCH private PMC Library for all PCH generations.
+ All function in this library is available for PEI, DXE, and SMM,
+ But do not support UEFI RUNTIME environment call.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PmcLib.h>
+#include <Library/PciSegmentLib.h>
+#include <Library/PchPcrLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/PmcPrivateLib.h>
+
+/**
+ This function checks if GbE device is supported (not disabled by fuse)
+
+ @retval GbE support state
+**/
+BOOLEAN
+PmcIsGbeSupported (
+ VOID
+ )
+{
+ //
+ // Get fuse info from PWRMBASE + FUSE_SS_DIS_RD_2
+ //
+ return ((MmioRead32 (PmcGetPwrmBase () + R_PMC_PWRM_FUSE_DIS_RD_2) & B_PMC_PWRM_FUSE_DIS_RD_2_GBE_FUSE_SS_DIS) == 0);
+}
+
+/**
+ This function checks if LAN wake from DeepSx is enabled
+
+ @retval Lan Wake state
+**/
+BOOLEAN
+PmcIsLanDeepSxWakeEnabled (
+ VOID
+ )
+{
+ //
+ // Get wake info from PWRMBASE + DSX_CFG
+ //
+ return ((MmioRead32 (PmcGetPwrmBase () + R_PMC_PWRM_DSX_CFG) & (UINT32) B_PMC_PWRM_DSX_CFG_LAN_WAKE_EN) != 0);
+}
+
+/**
+ This function checks if eSPI SMI Lock is set
+
+ @retval eSPI SMI Lock state
+**/
+BOOLEAN
+PmcIsEspiSmiLockSet (
+ VOID
+ )
+{
+ return ((MmioRead32 ((UINTN) (PmcGetPwrmBase () + R_PMC_PWRM_GEN_PMCON_A)) & B_PMC_PWRM_GEN_PMCON_A_ESPI_SMI_LOCK) != 0);
+}
+
+/**
+ This function sets SW SMI Rate.
+
+ @param[in] SwSmiRate Refer to PMC_SWSMI_RATE for possible values
+**/
+VOID
+PmcSetSwSmiRate (
+ IN PMC_SWSMI_RATE SwSmiRate
+ )
+{
+ UINT32 PchPwrmBase;
+ STATIC UINT8 SwSmiRateRegVal[4] = {
+ V_PMC_PWRM_GEN_PMCON_A_SWSMI_RTSL_1_5MS,
+ V_PMC_PWRM_GEN_PMCON_A_SWSMI_RTSL_16MS,
+ V_PMC_PWRM_GEN_PMCON_A_SWSMI_RTSL_32MS,
+ V_PMC_PWRM_GEN_PMCON_A_SWSMI_RTSL_64MS
+ };
+
+ ASSERT (SwSmiRate <= PmcSwSmiRate64ms);
+
+ PchPwrmBase = PmcGetPwrmBase ();
+
+ //
+ // SWSMI_RATE_SEL BIT (PWRMBASE offset 1020h[7:6]) bits are in RTC well
+ //
+ MmioAndThenOr8 (
+ PchPwrmBase + R_PMC_PWRM_GEN_PMCON_A,
+ (UINT8)~B_PMC_PWRM_GEN_PMCON_A_SWSMI_RTSL,
+ SwSmiRateRegVal[SwSmiRate]
+ );
+}
+
+/**
+ This function sets Periodic SMI Rate.
+
+ @param[in] PeriodicSmiRate Refer to PMC_PERIODIC_SMI_RATE for possible values
+**/
+VOID
+PmcSetPeriodicSmiRate (
+ IN PMC_PERIODIC_SMI_RATE PeriodicSmiRate
+ )
+{
+ UINT32 PchPwrmBase;
+ STATIC UINT8 PeriodicSmiRateRegVal[4] = {
+ V_PMC_PWRM_GEN_PMCON_A_PER_SMI_8S,
+ V_PMC_PWRM_GEN_PMCON_A_PER_SMI_16S,
+ V_PMC_PWRM_GEN_PMCON_A_PER_SMI_32S,
+ V_PMC_PWRM_GEN_PMCON_A_PER_SMI_64S
+ };
+
+ ASSERT (PeriodicSmiRate <= PmcPeriodicSmiRate64s);
+
+ PchPwrmBase = PmcGetPwrmBase ();
+
+ MmioAndThenOr8 (
+ PchPwrmBase + R_PMC_PWRM_GEN_PMCON_A,
+ (UINT8)~B_PMC_PWRM_GEN_PMCON_A_PER_SMI_SEL,
+ PeriodicSmiRateRegVal[PeriodicSmiRate]
+ );
+}
+
+/**
+ This function reads Power Button Level
+
+ @retval State of PWRBTN# signal (0: Low, 1: High)
+**/
+UINT8
+PmcGetPwrBtnLevel (
+ VOID
+ )
+{
+ if (MmioRead32 (PmcGetPwrmBase () + R_PMC_PWRM_GEN_PMCON_B) & B_PMC_PWRM_GEN_PMCON_B_PWRBTN_LVL) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+/**
+ This function gets Group to GPE0 configuration
+
+ @param[out] GpeDw0Value GPIO Group to GPE_DW0 assignment
+ @param[out] GpeDw1Value GPIO Group to GPE_DW1 assignment
+ @param[out] GpeDw2Value GPIO Group to GPE_DW2 assignment
+**/
+VOID
+PmcGetGpioGpe (
+ OUT UINT32 *GpeDw0Value,
+ OUT UINT32 *GpeDw1Value,
+ OUT UINT32 *GpeDw2Value
+ )
+{
+ UINT32 Data32;
+
+ Data32 = MmioRead32 ((UINTN) (PmcGetPwrmBase () + R_PMC_PWRM_GPIO_CFG));
+
+ *GpeDw0Value = ((Data32 & B_PMC_PWRM_GPIO_CFG_GPE0_DW0) >> N_PMC_PWRM_GPIO_CFG_GPE0_DW0);
+ *GpeDw1Value = ((Data32 & B_PMC_PWRM_GPIO_CFG_GPE0_DW1) >> N_PMC_PWRM_GPIO_CFG_GPE0_DW1);
+ *GpeDw2Value = ((Data32 & B_PMC_PWRM_GPIO_CFG_GPE0_DW2) >> N_PMC_PWRM_GPIO_CFG_GPE0_DW2);
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Pmc/LibraryPrivate/PeiDxeSmmPmcPrivateLib/PmcPrivateLibWithS3.c b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Pmc/LibraryPrivate/PeiDxeSmmPmcPrivateLib/PmcPrivateLibWithS3.c
new file mode 100644
index 0000000000..02acd0d688
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Pmc/LibraryPrivate/PeiDxeSmmPmcPrivateLib/PmcPrivateLibWithS3.c
@@ -0,0 +1,122 @@
+/** @file
+ PCH private PMC Library.
+ All function in this library is available for PEI, DXE, and SMM,
+ But do not support UEFI RUNTIME environment call.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/PchCycleDecodingLib.h>
+#include <Library/S3BootScriptLib.h>
+#include <Library/PmcLib.h>
+#include <Library/PmcPrivateLib.h>
+
+/**
+ This S3 BootScript only function disables triggering Global Reset of both
+ the Host and the ME partitions after CF9h write of 6h or Eh.
+**/
+VOID
+PmcDisableCf9GlobalResetInS3BootScript (
+ VOID
+ )
+{
+ UINT32 Data;
+
+ UINT32 PchPwrmBase;
+ PchPwrmBase = PmcGetPwrmBase ();
+
+ Data = MmioRead32 (PchPwrmBase + R_PMC_PWRM_ETR3);
+
+ Data &= (UINT32) ~B_PMC_PWRM_ETR3_CF9GR;
+
+ S3BootScriptSaveMemWrite (
+ S3BootScriptWidthUint32,
+ (UINTN) PchPwrmBase +
+ R_PMC_PWRM_ETR3,
+ 1,
+ &Data
+ );
+}
+
+/**
+ This S3 BootScript only function disables triggering Global Reset of both
+ the Host and the ME partitions after CF9h write of 6h or Eh.
+ Global Reset configuration is locked after programming
+**/
+VOID
+PmcDisableCf9GlobalResetWithLockInS3BootScript (
+ VOID
+ )
+{
+ UINT32 Data;
+
+ UINT32 PchPwrmBase;
+ PchPwrmBase = PmcGetPwrmBase ();
+
+ Data = MmioRead32 (PchPwrmBase + R_PMC_PWRM_ETR3);
+
+ Data &= (UINT32) ~B_PMC_PWRM_ETR3_CF9GR;
+ Data |= (UINT32) B_PMC_PWRM_ETR3_CF9LOCK;
+
+ S3BootScriptSaveMemWrite (
+ S3BootScriptWidthUint32,
+ (UINTN) PchPwrmBase +
+ R_PMC_PWRM_ETR3,
+ 1,
+ &Data
+ );
+}
+
+/**
+ This function sets SMI Lock with S3 Boot Script programming
+**/
+VOID
+PmcLockSmiWithS3BootScript (
+ VOID
+ )
+{
+ UINT32 PchPwrmBase;
+
+ PchPwrmBase = PmcGetPwrmBase ();
+
+ MmioOr8 ((UINTN) (PchPwrmBase + R_PMC_PWRM_GEN_PMCON_B), B_PMC_PWRM_GEN_PMCON_B_SMI_LOCK);
+
+ S3BootScriptSaveMemWrite (
+ S3BootScriptWidthUint8,
+ (UINTN) (PchPwrmBase + R_PMC_PWRM_GEN_PMCON_B),
+ 1,
+ (VOID *) (UINTN) (PchPwrmBase + R_PMC_PWRM_GEN_PMCON_B)
+ );
+}
+
+/**
+ This function sets eSPI SMI Lock
+ @attention This function must be called after eSPI SMI generation has been enabled.
+ This setting is required in all boot modes and before EndOfDxe.
+ If set value will be restored upon S3 resume by bootscript.
+**/
+VOID
+PmcLockEspiSmiWithS3BootScript (
+ VOID
+ )
+{
+ UINT8 Data8Or;
+ UINT8 Data8And;
+
+ Data8Or = (UINT8) (B_PMC_PWRM_GEN_PMCON_A_ESPI_SMI_LOCK >> 8);
+ Data8And = (UINT8)~((B_PMC_PWRM_GEN_PMCON_A_PWR_FLR | B_PMC_PWRM_GEN_PMCON_A_HOST_RST_STS) >> 8);
+
+ MmioAndThenOr8 (PmcGetPwrmBase () + R_PMC_PWRM_GEN_PMCON_A + 1, Data8And, Data8Or);
+ S3BootScriptSaveMemReadWrite (
+ S3BootScriptWidthUint8,
+ PmcGetPwrmBase () + R_PMC_PWRM_GEN_PMCON_A + 1,
+ &Data8Or,
+ &Data8And
+ );
+}
--
2.24.0.windows.2
^ permalink raw reply related [flat|nested] 42+ messages in thread
* [Patch V3 25/40] TigerlakeSiliconPkg/IpBlock: Add Psf component
2021-02-05 7:40 [Patch V3 01/40] TigerlakeSiliconPkg: Add package and Include/ConfigBlock headers Heng Luo
` (22 preceding siblings ...)
2021-02-05 7:40 ` [Patch V3 24/40] TigerlakeSiliconPkg/IpBlock: Add Pmc component Heng Luo
@ 2021-02-05 7:40 ` Heng Luo
2021-02-05 7:40 ` [Patch V3 26/40] TigerlakeSiliconPkg/IpBlock: Add Sata component Heng Luo
` (14 subsequent siblings)
38 siblings, 0 replies; 42+ messages in thread
From: Heng Luo @ 2021-02-05 7:40 UTC (permalink / raw)
To: devel; +Cc: Sai Chaganty, Nate DeSimone
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3171
Adds the following files:
* IpBlock/Psf/IncludePrivate
* IpBlock/Psf/LibraryPrivate
Cc: Sai Chaganty <rangasai.v.chaganty@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Signed-off-by: Heng Luo <heng.luo@intel.com>
---
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Psf/IncludePrivate/Library/PsfLib.h | 520 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Psf/LibraryPrivate/PsfLib/PeiDxeSmmPsfLibVer2.inf | 40 ++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Psf/LibraryPrivate/PsfLib/PsfLib.c | 203 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Psf/LibraryPrivate/PsfLib/PsfLibInternal.h | 470 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Psf/LibraryPrivate/PsfLib/PsfLibVer2.c | 115 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 1348 insertions(+)
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Psf/IncludePrivate/Library/PsfLib.h b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Psf/IncludePrivate/Library/PsfLib.h
new file mode 100644
index 0000000000..f333be48d2
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Psf/IncludePrivate/Library/PsfLib.h
@@ -0,0 +1,520 @@
+/** @file
+ Header file for PchPsfPrivateLib.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PCH_PSF_PRIVATE_LIB_H_
+#define _PCH_PSF_PRIVATE_LIB_H_
+
+#include <Library/PchPcrLib.h>
+#include <Register/PchPcrRegs.h>
+
+typedef struct {
+ UINT32 Id;
+ PCH_SBI_PID SbPid;
+} PSF_SEGMENT;
+
+/**
+ Get list of supported PSF segments.
+
+ @param[out] PsfTable Array of supported PSF segments
+ @param[out] PsfTableLength Length of PsfTable
+**/
+VOID
+PsfSegments (
+ OUT PSF_SEGMENT **PsfTable,
+ OUT UINT32 *PsfTableLength
+ );
+
+//
+// Structure for storing data on both PSF SideBand Port ID and
+// PSF port register offset for specific device
+//
+typedef struct {
+ PCH_SBI_PID PsfPid;
+ UINT16 RegBase;
+} PSF_PORT;
+
+/**
+ Disable device at PSF level
+ Method not for bridges (e.g. PCIe Root Port)
+
+ @param[in] PsfPort PSF PORT data structure
+**/
+VOID
+PsfDisableDevice (
+ IN PSF_PORT PsfPort
+ );
+
+/**
+ Enable device at PSF level
+ Method not for bridges (e.g. PCIe Root Port)
+
+ @param[in] PsfPort PSF PORT data structure
+**/
+VOID
+PsfEnableDevice (
+ IN PSF_PORT PsfPort
+ );
+
+/**
+ Hide PciCfgSpace of device at PSF level
+ Method not for bridges (e.g. PCIe Root Port)
+
+ @param[in] PsfPort PSF PORT data structure
+**/
+VOID
+PsfHideDevice (
+ IN PSF_PORT PsfPort
+ );
+
+/**
+ Unhide PciCfgSpace of device at PSF level
+ Method not for bridges (e.g. PCIe Root Port)
+
+ @param[in] PsfPort PSF PORT data structure
+**/
+VOID
+PsfUnhideDevice (
+ IN PSF_PORT PsfPort
+ );
+
+/**
+ Disable device BARs at PSF level
+ Method not for bridges (e.g. PCIe Root Port)
+
+ @param[in] PsfPort PSF PORT data structure
+ @param[in] BarDisMask BIT0-BAR0, BIT1-BAR1,...
+ Mask corresponds to 32bit wide BARs
+**/
+VOID
+PsfDisableDeviceBar (
+ IN PSF_PORT PsfPort,
+ IN UINT32 BarDisMask
+ );
+
+/**
+ Enable device BARs at PSF level
+ Method not for bridges (e.g. PCIe Root Port)
+
+ @param[in] PsfPort PSF PORT data structure
+ @param[in] BarEnMask BIT0-BAR0, BIT1-BAR1,...
+ Mask corresponds to 32bit wide BARs
+**/
+VOID
+PsfEnableDeviceBar (
+ IN PSF_PORT PsfPort,
+ IN UINT32 BarEnMask
+ );
+
+/**
+ Disable IDER device at PSF level
+**/
+VOID
+PsfDisableIderDevice (
+ VOID
+ );
+
+/**
+ Enable SOL device at PSF level
+**/
+VOID
+PsfEnableSolDevice (
+ VOID
+ );
+
+/**
+ Disable SOL device at PSF level
+**/
+VOID
+PsfDisableSolDevice (
+ VOID
+ );
+
+/**
+ Set PMC ABASE value in PSF
+
+ @param[in] Address Address for ACPI base.
+**/
+VOID
+PsfSetPmcAbase (
+ IN UINT16 Address
+ );
+
+/**
+ Get PMC ABASE value from PSF
+
+ @retval Address Address for ACPI base.
+**/
+UINT16
+PsfGetPmcAbase (
+ VOID
+ );
+
+/**
+ Get PMC PWRMBASE value from PSF
+
+ @retval Address Address for PWRM base.
+**/
+UINT32
+PsfGetPmcPwrmBase (
+ VOID
+ );
+
+/**
+ Hide Cnvi WiFi device's PciCfgSpace at PSF level
+**/
+VOID
+PsfHideCnviWifiDevice (
+ VOID
+ );
+
+/**
+ Disable Cnvi Wifi device at PSF level
+**/
+VOID
+PsfDisableCnviWifiDevice (
+ VOID
+ );
+
+/**
+ Disable HDAudio device at PSF level
+**/
+VOID
+PsfDisableHdaDevice (
+ VOID
+ );
+
+/**
+ Disable Dsp bar at PSF level
+**/
+VOID
+PsfDisableDspBar (
+ VOID
+ );
+
+/**
+ Disable THC device at PSF level
+
+ @param[in] ThcNumber Touch Host Controller Number THC0 or THC1
+**/
+VOID
+PsfDisableThcDevice (
+ IN UINT32 ThcNumber
+ );
+
+/**
+ Disable xDCI device at PSF level
+**/
+VOID
+PsfDisableXdciDevice (
+ VOID
+ );
+
+/**
+ Disable xHCI device at PSF level
+**/
+VOID
+PsfDisableXhciDevice (
+ VOID
+ );
+
+/**
+ Disable xHCI VTIO Phantom device at PSF level
+**/
+VOID
+PsfDisableXhciVtioDevice (
+ VOID
+ );
+
+/**
+ Disable SATA device at PSF level
+
+ @param[in] SataCtrlIndex SATA controller index
+**/
+VOID
+PsfDisableSataDevice (
+ IN UINT32 SataCtrlIndex
+ );
+
+/**
+ Return PSF_PORT for SCS eMMC device
+
+ @retval PsfPort PSF PORT structure for SCS eMMC device
+**/
+PSF_PORT
+PsfScsEmmcPort (
+ VOID
+ );
+
+/**
+ Return PSF_PORT for SCS SD Card device
+
+ @retval PsfPort PSF PORT structure for SCS SD Card device
+**/
+PSF_PORT
+PsfScsSdCardPort (
+ VOID
+ );
+
+/**
+ Return PSF_PORT for SCS UFS device
+
+ @param[in] UfsNum UFS Device
+
+ @retval PsfPort PSF PORT structure for SCS UFS device
+**/
+PSF_PORT
+PsfScsUfsPort (
+ IN UINT32 UfsNum
+ );
+
+/**
+ Disable ISH device at PSF level
+**/
+VOID
+PsfDisableIshDevice (
+ VOID
+ );
+
+/**
+ Disable FPAK device at PSF level
+**/
+VOID
+PsfDisableFpakDevice (
+ VOID
+ );
+
+/**
+ Disable ISH BAR1 at PSF level
+**/
+VOID
+PsfDisableIshBar1 (
+ VOID
+ );
+
+/**
+ Disable GbE device at PSF level
+**/
+VOID
+PsfDisableGbeDevice (
+ VOID
+ );
+
+/**
+ Disable SMBUS device at PSF level
+**/
+VOID
+PsfDisableSmbusDevice (
+ VOID
+ );
+
+/**
+ Disable TraceHub ACPI devices at PSF level
+**/
+VOID
+PsfDisableTraceHubAcpiDevice (
+ VOID
+ );
+
+/**
+ Hide TraceHub ACPI devices PciCfgSpace at PSF level
+**/
+VOID
+PsfHideTraceHubAcpiDevice (
+ VOID
+ );
+
+/**
+ This procedure will hide TraceHub PciCfgSpace at PSF level
+**/
+VOID
+PsfHideTraceHubDevice (
+ VOID
+ );
+
+/**
+ This procedure will unhide TraceHub PciCfgSpace at PSF level
+**/
+VOID
+PsfUnhideTraceHubDevice (
+ VOID
+ );
+
+/**
+ This procedure will disable TraceHub device at PSF level
+**/
+VOID
+PsfDisableTraceHubDevice (
+ VOID
+ );
+
+/**
+ Configures rootspace 3 bus number for PCIe IMR use
+
+ @param[in] Rs3Bus bus number
+**/
+VOID
+PsfSetRs3Bus (
+ UINT8 Rs3Bus
+ );
+
+/**
+ Disable PCIe Root Port at PSF level
+
+ @param[in] RpIndex PCIe Root Port Index (0 based)
+**/
+VOID
+PsfDisablePcieRootPort (
+ IN UINT32 RpIndex
+ );
+
+/**
+ Program PSF grant counts for SATA
+ Call this before SATA ports are accessed for enumeration
+**/
+VOID
+PsfConfigureSataGrantCounts (
+ VOID
+ );
+
+/**
+ Specifies the root port configuration of the
+ PCIe controller. The number on the left of x
+ signifies the number of root ports in the controller
+ while value on the right is link width. N stands for
+ the number of PCIe lanes per root port instance.
+**/
+typedef enum {
+ PsfPcieCtrl4xn,
+ PsfPcieCtrl1x2n_2xn,
+ PsfPcieCtrl2xn_1x2n,
+ PsfPcieCtrl2x2n,
+ PsfPcieCtrl1x4n,
+ PsfPcieCtrlUndefined
+} PSF_PCIE_CTRL_CONFIG;
+
+/**
+ Program PSF grant counts for PCI express depending on controllers configuration
+
+ @param[in] PsfPcieCtrlConfigTable Table with PCIe controllers configuration
+ @param[in] NumberOfPcieControllers Number of PCIe controllers. This is also the size of PsfPcieCtrlConfig table
+**/
+VOID
+PsfConfigurePcieGrantCounts (
+ IN PSF_PCIE_CTRL_CONFIG *PsfPcieCtrlConfigTable,
+ IN UINT32 NumberOfPcieControllers
+ );
+
+
+/**
+ This function enables EOI message forwarding in PSF for PCIe ports
+ for cases where IOAPIC is present behind this root port.
+
+ @param[in] RpIndex Root port index (0 based)
+
+ @retval Status
+**/
+EFI_STATUS
+PsfConfigurEoiForPciePort (
+ IN UINT32 RpIndex
+ );
+
+//
+// Structure for PSF Port Destination ID
+//
+typedef union {
+ UINT32 RegVal;
+ struct {
+ UINT32 ChannelId : 8; // Channel ID
+ UINT32 PortId : 7; // Port ID
+ UINT32 PortGroupId : 1; // Port Group ID
+ UINT32 PsfId : 8; // PSF ID
+ UINT32 Rsvd : 7; // Reserved
+ UINT32 ChanMap : 1; // Channel map
+ } Fields;
+} PSF_PORT_DEST_ID;
+
+/**
+ PCIe PSF port destination ID (psf_id:port_group_id:port_id:channel_id)
+
+ @param[in] RpIndex PCIe Root Port Index (0 based)
+
+ @retval Destination ID
+**/
+PSF_PORT_DEST_ID
+PsfPcieDestinationId (
+ IN UINT32 RpIndex
+ );
+
+/**
+ PSF early initialization.
+**/
+VOID
+PsfEarlyInit (
+ VOID
+ );
+
+/**
+ Assign new function number for PCIe Port Number.
+
+ @param[in] RpIndex PCIe Root Port Index (0 based)
+ @param[in] NewFunction New Function number
+**/
+VOID
+PsfSetPcieFunction (
+ IN UINT32 RpIndex,
+ IN UINT32 NewFunction
+ );
+
+/**
+ This function enables PCIe Relaxed Order in PSF
+**/
+VOID
+PsfEnablePcieRelaxedOrder (
+ VOID
+ );
+
+
+/**
+ Enable VTd support in PSF.
+**/
+VOID
+PchPsfEnableVtd (
+ VOID
+ );
+
+/**
+ Disable PSF address-based peer-to-peer decoding.
+**/
+VOID
+PchPsfDisableP2pDecoding (
+ VOID
+ );
+
+/**
+ This procedure will hide PMC device at PSF level
+**/
+VOID
+PsfHidePmcDevice (
+ VOID
+ );
+
+/**
+ This procedure will disable D3:F0 device at PSF level for PCH-LP
+**/
+VOID
+PsfDisableD3F0 (
+ VOID
+ );
+
+/**
+ This procedure will disable PSF upstream completion tracking for HDAudio on PCH-LP
+**/
+VOID
+PsfDisableUpstreamCompletionTrackingForHda (
+ VOID
+ );
+
+#endif // _PCH_PSF_PRIVATE_LIB_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Psf/LibraryPrivate/PsfLib/PeiDxeSmmPsfLibVer2.inf b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Psf/LibraryPrivate/PsfLib/PeiDxeSmmPsfLibVer2.inf
new file mode 100644
index 0000000000..d8fc52444a
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Psf/LibraryPrivate/PsfLib/PeiDxeSmmPsfLibVer2.inf
@@ -0,0 +1,40 @@
+## @file
+# PEI/DXE/SMM PCH PSF Private Lib for TigerLake PCH
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiDxeSmmPsfLibTgl
+FILE_GUID = 28B03D2C-6FD5-4061-96B8-39E3F0402DE5
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = PsfLib
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[LibraryClasses]
+ BaseLib
+ IoLib
+ DebugLib
+ PciSegmentLib
+ PchInfoLib
+ PchPcrLib
+ SataLib
+ CpuPcieInfoFruLib
+ PchPciBdfLib
+
+[Packages]
+ MdePkg/MdePkg.dec
+ TigerlakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+ PsfLib.c
+ PsfLibVer2.c
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Psf/LibraryPrivate/PsfLib/PsfLib.c b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Psf/LibraryPrivate/PsfLib/PsfLib.c
new file mode 100644
index 0000000000..1f0b11c11a
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Psf/LibraryPrivate/PsfLib/PsfLib.c
@@ -0,0 +1,203 @@
+/** @file
+ This file contains PSF routines for RC usage
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PchPcrLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/SataLib.h>
+#include <Library/CpuPcieInfoFruLib.h>
+#include <Library/PsfLib.h>
+#include <PchLimits.h>
+#include <Register/PchRegsPsf.h>
+#include <PchPcieRpInfo.h>
+#include "PsfLibInternal.h"
+#include <Library/PchPciBdfLib.h>
+
+/**
+ Get PSF SideBand Port ID from PSF ID (1 - PSF1, 2 - PSF2, ...)
+
+ @param[in] PsfId PSF ID (1 - PSF1, 2 - PSF2, ...)
+
+ @retval PSF SideBand Port ID
+**/
+PCH_SBI_PID
+PsfSbPortId (
+ UINT32 PsfId
+ )
+{
+ UINT32 PsfTableIndex;
+ PSF_SEGMENT *PsfTable;
+ UINT32 PsfTableSize;
+
+ PsfSegments (&PsfTable, &PsfTableSize);
+
+ for (PsfTableIndex = 0; PsfTableIndex < PsfTableSize; PsfTableIndex++) {
+ if (PsfTable[PsfTableIndex].Id == PsfId) {
+ return PsfTable[PsfTableIndex].SbPid;
+ }
+ }
+
+ ASSERT (FALSE);
+ return 0;
+}
+
+
+/**
+ Get PCH Root PSF ID. This is the PSF segment to which OPDMI/DMI is connected.
+
+ @retval PsfId Root PSF ID
+**/
+UINT32
+PsfRootId (
+ VOID
+ )
+{
+ PSF_SEGMENT *PsfTable;
+ UINT32 PsfTableSize;
+
+ PsfSegments (&PsfTable, &PsfTableSize);
+
+ return PsfTable[0].Id;
+}
+
+/**
+ Add EOI Target in a given PSF
+
+ @param[in] PsfId PSF ID (1 - PSF1, 2 - PSF2, ...)
+ @param[in] TargetId EOI Target ID
+**/
+STATIC
+VOID
+PsfAddEoiTarget (
+ UINT32 PsfId,
+ PSF_PORT_DEST_ID TargetId
+ )
+{
+ UINT16 EoiTargetBase;
+ UINT16 EoiControlBase;
+ UINT8 NumOfEnabledTargets;
+ UINT8 MaximalNumberOfTargets;
+ PCH_SBI_PID PsfSbiPortId;
+ UINT32 Data32;
+ UINT8 TargetIndex;
+
+ MaximalNumberOfTargets = PsfEoiRegData (PsfId, &EoiTargetBase, &EoiControlBase);
+ PsfSbiPortId = PsfSbPortId (PsfId);
+
+ //
+ // Get number of enabled agents from PSF_x_PSF_MC_CONTROL_MCAST0_RS0_EOI register
+ //
+ Data32 = PchPcrRead32 (PsfSbiPortId, EoiControlBase);
+ NumOfEnabledTargets = (UINT8) (Data32 >> N_PCH_PSFX_PCR_MC_CONTROL_MCASTX_NUMMC);
+
+ //
+ // Check if target was not already enabled
+ // Targets from a different PSF segment are aggregated into single destination on
+ // current PSF segment.
+ //
+ for (TargetIndex = 0; TargetIndex < NumOfEnabledTargets; TargetIndex++) {
+ Data32 = PchPcrRead32 (PsfSbiPortId, EoiTargetBase + TargetIndex * 4);
+ //
+ // If target already added don't add it again
+ //
+ if (Data32 == TargetId.RegVal) {
+ ASSERT (FALSE);
+ return;
+ }
+ //
+ // If target is from different PSF segment than currently being analyzed
+ // it is enough that its PsfID is matching
+ //
+ if ((Data32 & B_PCH_PSFX_PCR_TARGET_PSFID) >> N_PCH_PSFX_PCR_TARGET_PSFID == TargetId.Fields.PsfId) {
+ return;
+ }
+ }
+
+ //
+ // Check if next one can be added
+ //
+ if (NumOfEnabledTargets >= MaximalNumberOfTargets) {
+ ASSERT (FALSE);
+ return;
+ }
+
+ //
+ // Add next target
+ // Configure Multicast Destination ID register with target device on PSF.
+ // Configuration must be done in next available PSF_MC_AGENT_MCAST0_RS0_TGT<x>_EOI register
+ // so that other targets are not overridden. <x> is known from the number of multicast agents
+ // in Multicast Control Register. Value programmed is based on
+ // PsfID, PortGroupID, PortID and ChannelID of the target
+ //
+ PchPcrWrite32 (PsfSbiPortId, EoiTargetBase + NumOfEnabledTargets * 4, TargetId.RegVal);
+
+ //
+ // Enable new target
+ // Configure PSF_x_PSF_MC_CONTROL_MCAST0_RS0_EOI, increase NumMc and set MultCEn
+ //
+ NumOfEnabledTargets++;
+ Data32 = (NumOfEnabledTargets << N_PCH_PSFX_PCR_MC_CONTROL_MCASTX_NUMMC) | B_PCH_PSFX_PCR_MC_CONTROL_MCASTX_MULTCEN;
+ PchPcrWrite32 (PsfSbiPortId, EoiControlBase, Data32);
+}
+
+/**
+ Enable EOI Target
+
+ @param[in] TargetId Target ID
+**/
+STATIC
+VOID
+PsfEnableEoiTarget (
+ PSF_PORT_DEST_ID TargetId
+ )
+{
+ UINT32 RootLevelPsf;
+
+ RootLevelPsf = PsfRootId ();
+
+ //
+ // Enable EOI target in root PSF
+ //
+ PsfAddEoiTarget (RootLevelPsf, TargetId);
+
+ //
+ // Enable EOI target on other PSF segment if target
+ // is not located on root PSF
+ //
+ if (TargetId.Fields.PsfId != RootLevelPsf) {
+ PsfAddEoiTarget (TargetId.Fields.PsfId, TargetId);
+ }
+}
+
+/**
+ This function enables EOI message forwarding in PSF for PCIe ports
+ for cases where IOAPIC is present behind this root port.
+
+ @param[in] RpIndex Root port index (0 based)
+
+ @retval Status
+**/
+EFI_STATUS
+PsfConfigurEoiForPciePort (
+ IN UINT32 RpIndex
+ )
+{
+ ASSERT (RpIndex < GetPchMaxPciePortNum ());
+
+ //
+ // If there is an IOAPIC discovered behind root port program PSF Multicast registers
+ // accordingly to CNL PCH BWG PSF EOI Multicast Configuration
+ // Since there is a device behind RootPort to which EOI needs to be forwarded
+ // enable multicast (MULTCEN) and increase the number of multicast agents (NUMMC)
+ // in Multicast Control Register.
+ //
+ PsfEnableEoiTarget (PsfPcieDestinationId (RpIndex));
+
+ return EFI_SUCCESS;
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Psf/LibraryPrivate/PsfLib/PsfLibInternal.h b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Psf/LibraryPrivate/PsfLib/PsfLibInternal.h
new file mode 100644
index 0000000000..9d636b5298
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Psf/LibraryPrivate/PsfLib/PsfLibInternal.h
@@ -0,0 +1,470 @@
+/** @file
+ This file contains internal header for PSF lib usage
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PCH_PSF_PRIVATE_LIB_INTERNAL_H_
+#define _PCH_PSF_PRIVATE_LIB_INTERNAL_H_
+
+#include <Library/PsfLib.h>
+#include <Register/PchPcrRegs.h>
+
+#define PSF_PORT_NULL ((PSF_PORT){0,0})
+#define PSF_IS_PORT_NULL(PsfPort) ((PsfPort.PsfPid == 0) && (PsfPort.RegBase == 0))
+
+typedef struct {
+ PCH_SBI_PID PsfPid;
+ UINT32 RegisterAddress;
+ UINT8 Fro;
+} PSF_PORT_RELAXED_ORDERING_CONFIG_REG;
+/**
+ Disable bridge (e.g. PCIe Root Port) at PSF level
+
+ @param[in] PsfPort PSF PORT data structure
+**/
+VOID
+PsfDisableBridge (
+ IN PSF_PORT PsfPort
+ );
+
+/**
+ Disable bridge (e.g. PCIe Root Port) at PSF level in RS3
+
+ @param[in] PsfPort PSF PORT data structure
+**/
+VOID
+PsfRs3DisableBridge (
+ IN PSF_PORT PsfPort
+ );
+
+/**
+ Check if bridge (e.g. PCIe Root Port) is enabled at PSF level
+
+ @param[in] PsfPort PSF PORT data structure
+
+ @retval TRUE Bridge behind PSF Port is enabled
+ FALSE Bridge behind PSF Port is disabled
+**/
+BOOLEAN
+PsfIsBridgeEnabled (
+ IN PSF_PORT PsfPort
+ );
+
+/**
+ Disable device IOSpace at PSF level
+ Method not for bridges (e.g. PCIe Root Port)
+
+ @param[in] PsfPort PSF PORT data structure
+**/
+VOID
+PsfDisableDeviceIoSpace (
+ IN PSF_PORT PsfPort
+ );
+
+/**
+ Enable device IOSpace at PSF level
+ Method not for bridges (e.g. PCIe Root Port)
+
+ @param[in] PsfPort PSF PORT data structure
+**/
+VOID
+PsfEnableDeviceIoSpace (
+ IN PSF_PORT PsfPort
+ );
+
+/**
+ Disable device Memory Space at PSF level
+ Method not for bridges (e.g. PCIe Root Port)
+
+ @param[in] PsfPort PSF PORT data structure
+**/
+VOID
+PsfDisableDeviceMemSpace (
+ IN PSF_PORT PsfPort
+ );
+
+/**
+ Enable device Memory Space at PSF level
+ Method not for bridges (e.g. PCIe Root Port)
+
+ @param[in] PsfPort PSF PORT data structure
+**/
+VOID
+PsfEnableDeviceMemSpace (
+ IN PSF_PORT PsfPort
+ );
+
+/**
+ Set device BARx address at PSF level
+ Method not for bridges (e.g. PCIe Root Port)
+
+ @param[in] PsfPort PSF PORT data structure
+ @param[in] BarNum BAR Number (0:BAR0, 1:BAR1, ...)
+ @param[in] BarValue 32bit BAR value
+**/
+VOID
+PsfSetDeviceBarValue (
+ IN PSF_PORT PsfPort,
+ IN UINT8 BarNum,
+ IN UINT32 BarValue
+ );
+
+/**
+ Return PSF_PORT for TraceHub device
+
+ @retval PsfPort PSF PORT structure for TraceHub device
+**/
+PSF_PORT
+PsfTraceHubPort (
+ VOID
+ );
+
+/**
+ This procedure will return PSF_PORT for TraceHub ACPI device
+
+ @retval PsfPort PSF PORT structure for TraceHub ACPI device
+**/
+PSF_PORT
+PsfTraceHubAcpiDevPort (
+ VOID
+ );
+
+/**
+ This procedure will return PSF_PORT for SOL device
+
+ @retval PsfPort PSF PORT structure for SOL device
+**/
+PSF_PORT
+PsfSolPort (
+ VOID
+ );
+
+/**
+ Return PSF_PORT for ISH device
+
+ @retval PsfPort PSF PORT structure for ISH device
+**/
+PSF_PORT
+PsfIshPort (
+ VOID
+ );
+
+/**
+ Return PSF_PORT for FPAK device
+
+ @retval PsfPort PSF PORT structure for FPAK device
+**/
+PSF_PORT
+PsfFpakPort (
+ VOID
+ );
+
+/**
+ Return PSF_PORT for CNVi device
+
+ @retval PsfPort PSF PORT structure for CNVi device
+**/
+PSF_PORT
+PsfCnviPort (
+ VOID
+ );
+
+/**
+ Return PSF_PORT for PMC device
+
+ @retval PsfPort PSF PORT structure for PMC device
+**/
+PSF_PORT
+PsfPmcPort (
+ VOID
+ );
+
+/**
+ Return second level PSF_PORT to which PCIE Root Port device is connected (directly)
+
+ @param[in] RpIndex PCIe Root Port Index (0 based)
+
+ @retval PsfPort PSF PORT structure for PCIe
+**/
+PSF_PORT
+PsfPcieSecondLevelPort (
+ IN UINT32 RpIndex
+ );
+
+/**
+ Return PSF_PORT at root PSF level to which PCIe Root Port device is connected
+
+ @param[in] RpIndex PCIe Root Port Index (0 based)
+
+ @retval PsfPort PSF PORT structure for PCIe
+
+**/
+PSF_PORT
+PsfRootPciePort (
+ IN UINT32 RpIndex
+ );
+
+/**
+ Return RS3 PSF_PORT at root PSF level to which PCIe Root Port device is connected
+
+ @param[in] RpIndex PCIe Root Port Index (0 based)
+
+ @retval PsfPort PSF PORT structure for PCIe
+**/
+PSF_PORT
+PsfRootRs3PciePort (
+ IN UINT32 RpIndex
+ );
+
+/**
+ Check if PCIe Root Port is enabled
+
+ @param[in] RpIndex PCIe Root Port Index (0 based)
+
+ @retval TRUE PCIe Root Port is enabled
+ FALSE PCIe Root Port is disabled
+**/
+BOOLEAN
+PsfIsPcieRootPortEnabled (
+ IN UINT32 RpIndex
+ );
+
+//
+// Type of enpoint connected to PSF port.
+// PsfNullPort is used for ports which do not exist
+//
+typedef enum {
+ PsfNullPort,
+ PsfToPsfPort,
+ PsfPcieCtrlPort
+} PSF_TOPO_PORT_TYPE;
+
+//
+// Structure for storing information on location in PSF topology
+// Every PSF node is identified by PsfID and PsfPortId
+//
+typedef struct {
+ UINT8 PsfId;
+ UINT8 PortId;
+} PSF_TOPO_PORT;
+
+#define PSF_TOPO_PORT_NULL ((PSF_TOPO_PORT){0, 0})
+#define PSF_IS_TOPO_PORT_NULL(PsfTopoPort) (((PsfTopoPort).PsfId == 0) && ((PsfTopoPort).PortId == 0))
+
+//
+// This is optional field containing PSF port specific data
+//
+typedef union {
+ UINT32 PcieCtrlIndex;
+} PSF_TOPO_PORT_DATA;
+
+//
+// Structure representing PSF port in PSF topology
+// If port is of PsfToPsfPort type Child will point to the first
+// port of sub PSF segment.
+//
+typedef struct PSF_TOPOLOGY {
+ PSF_TOPO_PORT PsfPort;
+ PSF_TOPO_PORT_TYPE PortType;
+ CONST struct PSF_TOPOLOGY *Child;
+ PSF_TOPO_PORT_DATA PortData;
+} PSF_TOPOLOGY;
+
+//
+// Tag for identifying last element of PSF_TOPOLOGY type array
+//
+#define PSF_TOPOLOGY_END {{0, 0}, PsfNullPort, NULL}
+
+/**
+ Get PSF Pcie Tree topology
+
+ @param[in] PsfTopology PSF Port from PSF PCIe tree topology
+
+ @retval PsfTopology PSF PCIe tree topology
+**/
+CONST PSF_TOPOLOGY*
+PsfGetRootPciePsfTopology (
+ VOID
+ );
+
+//
+// Structure for storing data on PCIe controller to PSF assignment and GrantCount register offsets
+//
+typedef struct {
+ PCH_SBI_PID PsfPid;
+ UINT16 DevGntCnt0Base;
+ UINT16 TargetGntCntPg1Tgt0Base;
+} PSF_GRANT_COUNT_REG;
+
+/**
+ Grant count regs data for PSF that is directly connected to PCIe Root Ports
+
+ @param[in] Controller PCIe Root Port Controller index (0 based)
+ @param[out] GrantCountReg Structure with PSF Grant Count register data
+**/
+VOID
+PsfPcieGrantCountBaseReg (
+ IN UINT8 Controller,
+ OUT PSF_GRANT_COUNT_REG *GrantCountReg
+ );
+
+/**
+ Get Grant Count number (Device Grant Count and Target Grant Count)
+ for PSF that is directly connected to PCIe Root Ports
+
+ @param[in] Controller PCIe Root Port Controller index
+ @param[in] Channel PCIe Root Port Channel index
+ @param[out] DgcrNo Device Grant Count number
+ @param[out] PgTgtNo Target Grant Count number
+**/
+VOID
+PsfPcieGrantCountNumber (
+ IN UINT8 Controller,
+ IN UINT8 Channel,
+ OUT UINT8 *DgcrNo,
+ OUT UINT8 *PgTgtNo
+ );
+
+/**
+ Grant count regs data for a given PSF-to-PSF port.
+
+ @param[in] PsfTopoPort PSF-to-PSF port
+
+ @param[out] GrantCountReg Structure with PSF Grant Count register data
+**/
+VOID
+PsfSegmentGrantCountBaseReg (
+ IN PSF_TOPO_PORT PsfTopoPort,
+ OUT PSF_GRANT_COUNT_REG *GrantCountReg
+ );
+
+/**
+ Grant Count number (Device Grant Count and Target Grant Count) for a given PSF-to-PSF port.
+
+ @param[in] PsfTopoPort PSF-to-PSF port
+ @param[out] DgcrNo Device Grant Count number
+ @param[out] PgTgtNo Target Grant Count number
+**/
+VOID
+PsfSegmentGrantCountNumber (
+ IN PSF_TOPO_PORT PsfTopoPort,
+ OUT UINT8 *DgcrNo,
+ OUT UINT8 *PgTgtNo
+ );
+
+//
+// Do not override PSF Grant Count value and leave HW default setting
+//
+#define DEFAULT_PCIE_GRANT_COUNT 0xFF
+
+/**
+ Get PSF SideBand Port ID from PSF ID (1 - PSF1, 2 - PSF2, ...)
+
+ @param[in] PsfId PSF ID (1 - PSF1, 2 - PSF2, ...)
+
+ @retval PSF SideBand Port ID
+**/
+PCH_SBI_PID
+PsfSbPortId (
+ UINT32 PsfId
+ );
+
+/**
+ Get EOI register data for given PSF ID
+
+ @param[in] PsfId PSF ID (1 - PSF1, 2 - PSF2, ...)
+ @param[out] EoiTargetBase EOI Target register
+ @param[out] EoiControlBase EOI Control register
+
+ @retval MaxTargets Number of supported targets
+
+**/
+UINT8
+PsfEoiRegData (
+ UINT32 PsfId,
+ UINT16 *EoiTargetBase,
+ UINT16 *EoiControlBase
+ );
+
+/**
+ Get MCTP register data for given PSF ID
+
+ @param[in] PsfId PSF ID (1 - PSF1, 2 - PSF2, ...)
+ @param[out] MctpTargetBase MCTP Target register
+ @param[out] MctpControlBase MCTP Control register
+
+ @retval MaxTargets Number of supported targets
+
+**/
+UINT8
+PsfMctpRegData (
+ UINT32 PsfId,
+ UINT16 *MctpTargetBase,
+ UINT16 *MctpControlBase
+ );
+
+/**
+ Check if MCTP is supported
+
+ @retval TRUE MCTP is supported
+ FALSE MCTP is not supported
+**/
+BOOLEAN
+PsfIsMctpSupported (
+ VOID
+ );
+
+/**
+ Return the PSF (Root level) Function Config PSF_PORT for PCIe Root Port
+
+ @param[in] RpIndex PCIe Root Port Index (0 based)
+
+ @retval PsfPort PSF PORT structure for PCIe Function Config
+**/
+PSF_PORT
+PsfRootPcieFunctionConfigPort (
+ IN UINT32 RpIndex
+ );
+
+/**
+ Return the PSF (Root level) RS3 Function Config PSF_PORT for PCIe Root Port
+
+ @param[in] RpIndex PCIe Root Port Index (0 based)
+
+ @retval PsfPort PSF PORT structure for PCIe Function Config
+**/
+PSF_PORT
+PsfRootRs3PcieFunctionConfigPort (
+ IN UINT32 RpIndex
+ );
+
+/**
+ Return the PSF Function Config Second Level PSF_PORT for PCIe Root Port
+
+ @param[in] RpIndex PCIe Root Port Index (0 based)
+
+ @retval PsfPort PSF PORT structure for PCIe Function Config
+**/
+PSF_PORT
+PsfPcieFunctionConfigSecondLevelPort (
+ IN UINT32 RpIndex
+ );
+
+/**
+ This function returns Psf Port Relaxed Ordering Configs
+
+ @param[out] PsfPortRelaxedOrderingConfigRegs PCH Series specific table
+ @param[out] PsfPortRelaxedOrderingConfigRegsTableSize PCH Series specific table size
+ @param[out] PsfPortRelaxedOrderingConfigRegsPchTypeSpecific PCH type specific table
+ @param[out] PsfPortRelaxedOrderingConfigRegsPchTypeSpecificTableSize PCH type specific table size
+**/
+VOID
+GetPsfPortRelaxedOrderingTables (
+ PSF_PORT_RELAXED_ORDERING_CONFIG_REG** PsfPortRelaxedOrderingConfigRegs,
+ UINT32* PsfPortRelaxedOrderingConfigRegsTableSize,
+ PSF_PORT_RELAXED_ORDERING_CONFIG_REG** PsfPortRelaxedOrderingConfigRegsPchTypeSpecific,
+ UINT32* PsfPortRelaxedOrderingConfigRegsPchTypeSpecificTableSize
+ );
+
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Psf/LibraryPrivate/PsfLib/PsfLibVer2.c b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Psf/LibraryPrivate/PsfLib/PsfLibVer2.c
new file mode 100644
index 0000000000..fd21e5bed4
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Psf/LibraryPrivate/PsfLib/PsfLibVer2.c
@@ -0,0 +1,115 @@
+/** @file
+ This file contains internal PSF routines for PCH PSF VER2 lib usage
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PchPcrLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/SataLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Register/PchRegsPsf.h>
+#include "PsfLibInternal.h"
+#include <PchPcieRpInfo.h>
+
+
+/**
+ Get EOI register data for given PSF ID
+
+ @param[in] PsfId PSF ID (1 - PSF1, 2 - PSF2, ...)
+ @param[out] EoiTargetBase EOI Target register
+ @param[out] EoiControlBase EOI Control register
+
+ @retval MaxTargets Number of supported targets
+
+**/
+UINT8
+PsfEoiRegData (
+ UINT32 PsfId,
+ UINT16 *EoiTargetBase,
+ UINT16 *EoiControlBase
+ )
+{
+ UINT8 MaxTargets;
+
+ MaxTargets = 0;
+ *EoiTargetBase = 0;
+ *EoiControlBase = 0;
+
+ switch (PsfId) {
+ case 1:
+ break;
+
+ case 3:
+ break;
+
+ case 7:
+ break;
+
+ case 8:
+ break;
+
+ case 9:
+ break;
+
+ default:
+ break;
+
+ }
+ return MaxTargets;
+}
+
+GLOBAL_REMOVE_IF_UNREFERENCED PSF_PORT_DEST_ID PchLpRpDestId[] =
+{
+ {0x18000}, {0x18001}, {0x18002}, {0x18003}, // SPA: PSF1, PortID = 0
+ {0x18100}, {0x18101}, {0x18102}, {0x18103}, // SPB: PSF1, PortID = 1
+ {0x18200}, {0x18201}, {0x18202}, {0x18203}, // SPC: PSF1, PortID = 2
+};
+
+/**
+ PCIe PSF port destination ID (psf_id:port_group_id:port_id:channel_id)
+
+ @param[in] RpIndex PCIe Root Port Index (0 based)
+
+ @retval Destination ID
+**/
+PSF_PORT_DEST_ID
+PsfPcieDestinationId (
+ IN UINT32 RpIndex
+ )
+{
+ if (RpIndex < ARRAY_SIZE (PchLpRpDestId)) {
+ return PchLpRpDestId[RpIndex];
+ }
+ ASSERT (FALSE);
+ return (PSF_PORT_DEST_ID){0};
+}
+
+GLOBAL_REMOVE_IF_UNREFERENCED PSF_SEGMENT mPchLpPsfTable[] =
+{
+ {1, PID_PSF1},
+ {2, PID_PSF2},
+ {3, PID_PSF3},
+ {4, PID_PSF4},
+ {5, PID_CSME_PSF},
+ {6, PID_PSF6}
+};
+
+/**
+ Get list of supported PSF segments.
+
+ @param[out] PsfTable Array of supported PSF segments
+ @param[out] PsfTableLength Length of PsfTable
+**/
+VOID
+PsfSegments (
+ OUT PSF_SEGMENT **PsfTable,
+ OUT UINT32 *PsfTableLength
+ )
+{
+*PsfTable = mPchLpPsfTable;
+ *PsfTableLength = ARRAY_SIZE (mPchLpPsfTable);
+}
--
2.24.0.windows.2
^ permalink raw reply related [flat|nested] 42+ messages in thread
* [Patch V3 26/40] TigerlakeSiliconPkg/IpBlock: Add Sata component
2021-02-05 7:40 [Patch V3 01/40] TigerlakeSiliconPkg: Add package and Include/ConfigBlock headers Heng Luo
` (23 preceding siblings ...)
2021-02-05 7:40 ` [Patch V3 25/40] TigerlakeSiliconPkg/IpBlock: Add Psf component Heng Luo
@ 2021-02-05 7:40 ` Heng Luo
2021-02-05 7:40 ` [Patch V3 27/40] TigerlakeSiliconPkg/IpBlock: Add SerialIo component Heng Luo
` (13 subsequent siblings)
38 siblings, 0 replies; 42+ messages in thread
From: Heng Luo @ 2021-02-05 7:40 UTC (permalink / raw)
To: devel; +Cc: Sai Chaganty, Nate DeSimone
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3171
Adds the following files:
* IpBlock/Sata/Library
Cc: Sai Chaganty <rangasai.v.chaganty@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Signed-off-by: Heng Luo <heng.luo@intel.com>
---
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Sata/Library/PeiDxeSmmSataLib/PeiDxeSmmSataLibVer2.inf | 32 ++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Sata/Library/PeiDxeSmmSataLib/SataLib.c | 138 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Sata/Library/PeiDxeSmmSataLib/SataLibVer2.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 253 insertions(+)
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Sata/Library/PeiDxeSmmSataLib/PeiDxeSmmSataLibVer2.inf b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Sata/Library/PeiDxeSmmSataLib/PeiDxeSmmSataLibVer2.inf
new file mode 100644
index 0000000000..1c304fed59
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Sata/Library/PeiDxeSmmSataLib/PeiDxeSmmSataLibVer2.inf
@@ -0,0 +1,32 @@
+## @file
+# PEI/DXE/SMM PCH SATA library Ver2
+#
+# All function in this library is available for PEI, DXE, and SMM,
+# But do not support UEFI RUNTIME environment call.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiDxeSmmPchSataLibVer2
+FILE_GUID = 2519ADE8-D971-4551-8A8E-2EB55DFC555B
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = SataLib
+
+[LibraryClasses]
+BaseLib
+PciSegmentLib
+PchInfoLib
+PchPciBdfLib
+
+[Packages]
+MdePkg/MdePkg.dec
+TigerlakeSiliconPkg/SiPkg.dec
+
+[Sources]
+SataLib.c
+SataLibVer2.c
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Sata/Library/PeiDxeSmmSataLib/SataLib.c b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Sata/Library/PeiDxeSmmSataLib/SataLib.c
new file mode 100644
index 0000000000..49cba49910
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Sata/Library/PeiDxeSmmSataLib/SataLib.c
@@ -0,0 +1,138 @@
+/** @file
+ Pch SATA library.
+ All function in this library is available for PEI, DXE, and SMM,
+ But do not support UEFI RUNTIME environment call.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/PciSegmentLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/SataLib.h>
+#include <Register/PchRegs.h>
+#include <Register/SataRegs.h>
+#include <Library/PchPciBdfLib.h>
+
+/**
+ Get SATA controller address that can be passed to the PCI Segment Library functions.
+
+ @param[in] SataCtrlIndex SATA controller index
+
+ @retval SATA controller address in PCI Segment Library representation
+**/
+UINT64
+SataRegBase (
+ IN UINT32 SataCtrlIndex
+ )
+{
+ ASSERT (SataCtrlIndex < MaxSataControllerNum ());
+
+ return SataPciCfgBase (SataCtrlIndex);
+}
+
+/**
+ Get SATA controller's Port Present Status
+
+ @param[in] SataCtrlIndex SATA controller index
+
+ @retval Port Present Status
+**/
+UINT8
+GetSataPortPresentStatus (
+ IN UINT32 SataCtrlIndex
+ )
+{
+ ASSERT (SataCtrlIndex < MaxSataControllerNum ());
+
+ return PciSegmentRead8 (SataPciCfgBase (SataCtrlIndex) + R_SATA_CFG_PCS + 2);
+}
+
+/**
+ Get SATA controller Function Disable Status
+
+ @param[in] SataCtrlIndex SATA controller index
+
+ @retval 0 SATA Controller is not Function Disabled
+ @retval 1 SATA Controller is Function Disabled
+**/
+BOOLEAN
+SataControllerFunctionDisableStatus (
+ IN UINT32 SataCtrlIndex
+ )
+{
+ UINT32 SataGc;
+ ASSERT (SataCtrlIndex < MaxSataControllerNum ());
+ SataGc = PciSegmentRead32 (SataPciCfgBase (SataCtrlIndex) + R_SATA_CFG_SATAGC);
+ return !!(SataGc & BIT10);
+}
+
+/**
+ Get SATA controller ABAR size
+
+ @param[in] SataCtrlIndex SATA controller index
+
+ @retval SATA controller ABAR size
+**/
+UINT32
+GetSataAbarSize (
+ IN UINT32 SataCtrlIndex
+ )
+{
+ UINT32 SataGc;
+ ASSERT (SataCtrlIndex < MaxSataControllerNum ());
+ SataGc = PciSegmentRead32 (SataPciCfgBase (SataCtrlIndex) + R_SATA_CFG_SATAGC);
+
+ switch (SataGc & B_SATA_CFG_SATAGC_ASSEL) {
+ case V_SATA_CFG_SATAGC_ASSEL_2K:
+ return SIZE_2KB;
+ break;
+
+ case V_SATA_CFG_SATAGC_ASSEL_16K:
+ return SIZE_16KB;
+ break;
+
+ case V_SATA_CFG_SATAGC_ASSEL_32K:
+ return SIZE_32KB;
+ break;
+
+ case V_SATA_CFG_SATAGC_ASSEL_64K:
+ return SIZE_64KB;
+ break;
+
+ case V_SATA_CFG_SATAGC_ASSEL_128K:
+ return SIZE_128KB;
+ break;
+
+ case V_SATA_CFG_SATAGC_ASSEL_512K:
+ return SIZE_256KB;
+ break;
+
+ default:
+ return SIZE_2KB;
+ break;
+ }
+}
+
+/**
+ Get SATA controller AHCI base address
+
+ @param[in] SataCtrlIndex SATA controller index
+
+ @retval SATA controller AHCI base address
+**/
+UINT32
+GetSataAhciBase (
+ IN UINT32 SataCtrlIndex
+ )
+{
+ ASSERT (SataCtrlIndex < MaxSataControllerNum ());
+
+ return PciSegmentRead32 (SataPciCfgBase (SataCtrlIndex) + R_SATA_CFG_AHCI_BAR) & 0xFFFFF800;
+}
+
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Sata/Library/PeiDxeSmmSataLib/SataLibVer2.c b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Sata/Library/PeiDxeSmmSataLib/SataLibVer2.c
new file mode 100644
index 0000000000..cde74e4e76
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Sata/Library/PeiDxeSmmSataLib/SataLibVer2.c
@@ -0,0 +1,83 @@
+/** @file
+ Pch SATA library.
+ All function in this library is available for PEI, DXE, and SMM,
+ But do not support UEFI RUNTIME environment call.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/DebugLib.h>
+#include <Library/PchInfoLib.h>
+#include <PchLimits.h>
+#include <Register/SataRegs.h>
+#include <Library/SataLib.h>
+
+/**
+ Get Maximum Sata Controller Number
+
+ @retval Maximum Sata Controller Number
+**/
+UINT8
+MaxSataControllerNum (
+ VOID
+ )
+{
+ return 1;
+}
+
+/**
+ Get Maximum Sata Port Number
+
+ @param[in] SataCtrlIndex SATA controller index
+
+ @retval Maximum Sata Port Number
+**/
+UINT8
+MaxSataPortNum (
+ IN UINT32 SataCtrlIndex
+ )
+{
+ ASSERT (SataCtrlIndex < MaxSataControllerNum ());
+
+ return 2;
+}
+
+/**
+ Check if SATA controller supports RST remapping
+
+ @param[in] SataCtrlIndex SATA controller index
+
+ @retval TRUE Controller supports remapping
+ @retval FALSE Controller does not support remapping
+
+**/
+BOOLEAN
+IsRemappingSupportedOnSata (
+ IN UINT32 SataCtrlIndex
+ )
+{
+ ASSERT (SataCtrlIndex < MaxSataControllerNum ());
+
+ return FALSE;
+}
+
+/**
+ Checks if SoC supports the SATA PGD power down on given
+ SATA controller.
+
+ @param[in] SataCtrlIndex SATA controller index
+
+ @retval TRUE SATA PGD power down supported
+ @retval FALSE SATA PGD power down not supported
+**/
+BOOLEAN
+IsSataPowerGatingSupported (
+ IN UINT32 SataCtrlIndex
+ )
+{
+ return TRUE;
+}
+
--
2.24.0.windows.2
^ permalink raw reply related [flat|nested] 42+ messages in thread
* [Patch V3 27/40] TigerlakeSiliconPkg/IpBlock: Add SerialIo component
2021-02-05 7:40 [Patch V3 01/40] TigerlakeSiliconPkg: Add package and Include/ConfigBlock headers Heng Luo
` (24 preceding siblings ...)
2021-02-05 7:40 ` [Patch V3 26/40] TigerlakeSiliconPkg/IpBlock: Add Sata component Heng Luo
@ 2021-02-05 7:40 ` Heng Luo
2021-02-05 7:40 ` [Patch V3 28/40] TigerlakeSiliconPkg/IpBlock: Add Smbus component Heng Luo
` (12 subsequent siblings)
38 siblings, 0 replies; 42+ messages in thread
From: Heng Luo @ 2021-02-05 7:40 UTC (permalink / raw)
To: devel; +Cc: Sai Chaganty, Nate DeSimone
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3171
Adds the following files:
* IpBlock/SerialIo/IncludePrivate
* IpBlock/SerialIo/Library
* IpBlock/SerialIo/LibraryPrivate
Cc: Sai Chaganty <rangasai.v.chaganty@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Signed-off-by: Heng Luo <heng.luo@intel.com>
---
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/SerialIo/IncludePrivate/Library/SerialIoPrivateLib.h | 377 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/SerialIo/IncludePrivate/Register/SerialIoRegsVer2.h | 108 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/SerialIo/Library/PeiDxeSmmSerialIoAccessLib/PeiDxeSmmSerialIoAccessLib.inf | 35 +++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/SerialIo/Library/PeiDxeSmmSerialIoAccessLib/SerialIoAccessLib.c | 266 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/SerialIo/LibraryPrivate/PeiDxeSmmSerialIoPrivateLib/PeiDxeSmmSerialIoPrivateLibVer2.inf | 34 ++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/SerialIo/LibraryPrivate/PeiDxeSmmSerialIoPrivateLib/SerialIoPrivateLib.c | 156 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/SerialIo/LibraryPrivate/PeiDxeSmmSerialIoPrivateLib/SerialIoPrivateLibI2c.c | 122 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/SerialIo/LibraryPrivate/PeiDxeSmmSerialIoPrivateLib/SerialIoPrivateLibI2cVer2.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/SerialIo/LibraryPrivate/PeiDxeSmmSerialIoPrivateLib/SerialIoPrivateLibInternal.h | 20 ++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/SerialIo/LibraryPrivate/PeiDxeSmmSerialIoPrivateLib/SerialIoPrivateLibSpi.c | 122 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/SerialIo/LibraryPrivate/PeiDxeSmmSerialIoPrivateLib/SerialIoPrivateLibSpiVer2.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/SerialIo/LibraryPrivate/PeiDxeSmmSerialIoPrivateLib/SerialIoPrivateLibUart.c | 136 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/SerialIo/LibraryPrivate/PeiDxeSmmSerialIoPrivateLib/SerialIoPrivateLibUartVer2.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
13 files changed, 1610 insertions(+)
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/SerialIo/IncludePrivate/Library/SerialIoPrivateLib.h b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/SerialIo/IncludePrivate/Library/SerialIoPrivateLib.h
new file mode 100644
index 0000000000..47057cd2ef
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/SerialIo/IncludePrivate/Library/SerialIoPrivateLib.h
@@ -0,0 +1,377 @@
+/** @file
+ Header file for Serial IO Private Lib implementation.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _SERIAL_IO_PRIVATE_LIB_H_
+#define _SERIAL_IO_PRIVATE_LIB_H_
+
+#include <SerialIoDevices.h>
+#include <Library/SerialIoAccessLib.h>
+
+/**
+ Serial Io Pci Device State structure.
+ Used to preserve current information about the device when it is configured in Pci mode prior to Pch Initialization.
+**/
+typedef struct {
+ UINT64 PciCfgBar0; ///< Pci Config Space Base Address Register
+ UINT8 PciCfgCommand; ///< Pci Config Space Command Register
+ UINT8 PciCfgPmeCtrlSts; ///< Pci Config Space Pme Control Status
+ UINT8 PprReset; ///< MMIO Proprietary Reset Register
+} SERIAL_IO_PCI_DEVICE_STATE;
+
+/**
+ Checks if higher functions are enabled.
+ Used for Function 0 Serial Io Device disabling
+
+ @param[in] DeviceNum Device Number
+
+ @retval TRUE At least one higher function device is enabled
+ FALSE Higher functions are disabled
+**/
+BOOLEAN
+SerialIoHigherFunctionsEnabled (
+ IN UINT8 DeviceNum
+ );
+
+/**
+ Places SerialIo device in D3
+
+ @param[in] PciCfgBase Pci Config Offset
+
+**/
+VOID
+SerialIoSetD3 (
+ IN UINT64 PciCfgBase
+ );
+
+/**
+ Places SerialIo device in D0
+
+ @param[in] PciCfgBase Pci Config Offset
+
+**/
+VOID
+SerialIoSetD0 (
+ IN UINT64 PciCfgBase
+ );
+
+/**
+ Allows Memory Access
+
+ @param[in] PciCfgBase Pci Config Offset
+ @param[in] Hidden Mode that determines access type
+
+**/
+VOID
+SerialIoEnableMse (
+ IN UINT64 PciCfgBase,
+ IN BOOLEAN Hidden
+ );
+
+/**
+ Disable SerialIo memory access
+
+ @param[in] PciCfgBase Pci Config Offset
+
+**/
+VOID
+SerialIoDisableMse (
+ IN UINT64 PciCfgBase
+ );
+
+/**
+ Disable SerialIo memory encoding
+ Designated for Pci modes
+
+ @param[in] PciCfgBase Pci Config Offset
+ @param[in] RemoveTempBar Remove temporary mem base address or not
+
+**/
+VOID
+SerialIoMmioDisable (
+ IN UINT64 PciCfgBase,
+ IN BOOLEAN RemoveBar
+ );
+
+/**
+ Gets Fixed Base Address used for BAR0
+
+ @param[in] SpiNumber Serial IO device SPI number
+
+ @retval Config control offset
+**/
+UINT32
+GetSerialIoSpiFixedMmioAddress (
+ IN UINT8 SpiNumber
+ );
+
+/**
+ Gets Fixed Address used for Pci Config Space manipulation
+
+ @param[in] SpiNumber Serial IO device SPI number
+
+ @retval Pci Config Address
+**/
+UINT32
+GetSerialIoSpiFixedPciCfgAddress (
+ IN UINT8 SpiNumber
+ );
+
+/**
+ Gets Spi Device Id
+
+ @param[in] SpiNumber Serial IO device SPI number
+
+ @retval Device Id
+**/
+UINT16
+GetSerialIoSpiDeviceId (
+ IN UINT8 SpiNumber
+ );
+
+/**
+ Checks if SPI is Hidden, and it's Pci Config space available
+
+ @param[in] SpiNumber Selects Serial IO SPI device
+
+ @retval TRUE SPI is in hidden mode
+ @retval FALSE SPI is not in hidden mode
+**/
+BOOLEAN
+IsSerialIoSpiHidden (
+ IN UINT8 SpiNumber
+ );
+
+/**
+ Configures Serial IO Controller before control is passd to the OS
+
+ @param[in] SpiNumber SPI Number
+ @param[in] SpiDeviceConfig SerialIo SPI Config
+
+**/
+VOID
+SerialIoSpiBootHandler (
+ IN UINT8 SpiNumber,
+ IN SERIAL_IO_SPI_CONFIG *SpiDeviceConfig
+ );
+
+/**
+ Sets Pme Control Status and Command register values required for S3 Boot Script
+
+ @param[in] SpiNumber SPI Number
+ @param[in] SpiDeviceConfig SerialIo SPI Config
+ @param[in/out] S3PciCfgBase S3 Boot Script Pci Config Base
+ @param[in/out] Command Pci Command register data to save
+ @param[in/out] Pme Pci Pme Control register data to save
+
+**/
+VOID
+SerialIoSpiS3Handler (
+ IN UINT8 SpiNumber,
+ IN SERIAL_IO_SPI_CONFIG *SpiDeviceConfig,
+ IN OUT UINT64 *S3PciCfgBase,
+ IN OUT UINT32 *Command,
+ IN OUT UINT32 *Pme
+ );
+
+/**
+ Gets Pci Config control offset
+
+ @param[in] UartNumber Serial IO device UART number
+
+ @retval Config control offset
+**/
+UINT16
+GetSerialIoUartConfigControlOffset (
+ IN UINT8 UartNumber
+ );
+
+/**
+ Gets Fixed Base Address used for BAR0
+
+ @param[in] UartNumber Serial IO device UART number
+
+ @retval Config control offset
+**/
+UINT32
+GetSerialIoUartFixedMmioAddress (
+ IN UINT8 UartNumber
+ );
+
+/**
+ Gets Fixed Address used for Pci Config Space manipulation
+
+ @param[in] UartNumber Serial IO device UART number
+
+ @retval Pci Config Address
+**/
+UINT32
+GetSerialIoUartFixedPciCfgAddress (
+ IN UINT8 UartNumber
+ );
+
+/**
+ Returns UART S3 boot script PCI address
+
+ @param[in] UartNumber UART Number
+
+ @retval UART S3 boot script PCI address
+**/
+UINT64
+GetSerialIoUartS3PciBase (
+ IN UINT8 UartNumber
+ );
+
+/**
+ Returns SPI S3 boot script PCI address
+
+ @param[in] UartNumber UART Number
+
+ @retval SPI S3 boot script PCI address
+**/
+UINT64
+GetSerialIoSpiS3PciBase (
+ IN UINT8 SpiNumber
+ );
+
+/**
+ Returns I2C S3 boot script PCI address
+
+ @param[in] I2cNumber I2C Number
+
+ @retval I2C S3 boot script PCI address
+**/
+UINT64
+GetSerialIoI2cS3PciBase (
+ IN UINT8 I2cNumber
+ );
+
+/**
+ Gets Uarts Device Id
+
+ @param[in] UartNumbe Serial IO device UART number
+
+ @retval Device Id
+**/
+UINT16
+GetSerialIoUartDeviceId (
+ IN UINT8 UartNumber
+ );
+
+/**
+ Checks if UART is Hidden, and it's Pci Config space available
+
+ @param[in] UartNumber Selects Serial IO UART device
+
+ @retval TRUE UART is in hidden mode
+ @retval FALSE UART is not in hidden mode
+**/
+BOOLEAN
+IsSerialIoUartHidden (
+ IN UINT8 UartNumber
+ );
+
+/**
+ Configures Serial IO Controller before control is passd to the OS
+
+ @param[in] UartNumber UART Number
+ @param[in] UartDeviceConfig SerialIo UART Config
+
+**/
+VOID
+SerialIoUartBootHandler (
+ IN UINT8 UartNumber,
+ IN SERIAL_IO_UART_CONFIG *UartDeviceConfig
+ );
+
+/**
+ Sets Pme Control Status and Command register values required for S3 Boot Script
+
+ @param[in] UartNumber UART Number
+ @param[in] UartDeviceConfig SerialIo UART Config
+ @param[in/out] S3PciCfgBase S3 Boot Script Pci Config Base
+ @param[in/out] Command Pci Command register data to save
+ @param[in/out] Pme Pci Pme Control register data to save
+
+**/
+VOID
+SerialIoUartS3Handler (
+ IN UINT8 UartNumber,
+ IN SERIAL_IO_UART_CONFIG *UartDeviceConfig,
+ IN OUT UINT64 *S3PciCfgBase,
+ IN OUT UINT32 *Command,
+ IN OUT UINT32 *Pme
+ );
+
+/**
+ Gets Fixed Address used for Pci Config Space manipulation
+
+ @param[in] I2cNumber Serial IO device I2C number
+
+ @retval Pci Config Address
+**/
+UINT32
+GetSerialIoI2cFixedPciCfgAddress (
+ IN UINT8 I2cNumber
+ );
+
+/**
+ Gets I2C Device Id
+
+ @param[in] I2cNumber Serial IO device I2C number
+
+ @retval Device Id
+**/
+UINT16
+GetSerialIoI2cDeviceId (
+ IN UINT8 I2cNumber
+ );
+
+/**
+ Checks if I2C is Hidden, and it's Pci Config space available
+
+ @param[in] 2cNumber Selects Serial IO I2C device
+
+ @retval TRUE I2C is in hidden mode
+ @retval FALSE I2C is not in hidden mode
+**/
+BOOLEAN
+IsSerialIoI2cHidden (
+ IN UINT8 I2cNumber
+ );
+
+/**
+ Configures Serial IO Controller before control is passd to the OS
+
+ @param[in] I2cNumber I2C Number
+ @param[in] I2cDeviceConfig SerialIo I2C Config
+
+**/
+VOID
+SerialIoI2cBootHandler (
+ IN UINT8 I2cNumber,
+ IN SERIAL_IO_I2C_CONFIG *I2cDeviceConfig
+ );
+
+/**
+ Sets Pme Control Status and Command register values required for S3 Boot Script
+
+ @param[in] I2cNumber I2C Number
+ @param[in] I2cDeviceConfig SerialIo I2C Config
+ @param[in/out] S3PciCfgBase S3 Boot Script Pci Config Base
+ @param[in/out] Command Pci Command register data to save
+ @param[in/out] Pme Pci Pme Control register data to save
+
+**/
+VOID
+SerialIoI2cS3Handler (
+ IN UINT8 I2cNumber,
+ IN SERIAL_IO_I2C_CONFIG *I2cDeviceConfig,
+ IN OUT UINT64 *S3PciCfgBase,
+ IN OUT UINT32 *Command,
+ IN OUT UINT32 *Pme
+ );
+
+#endif // _SERIAL_IO_PRIVATE_LIB_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/SerialIo/IncludePrivate/Register/SerialIoRegsVer2.h b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/SerialIo/IncludePrivate/Register/SerialIoRegsVer2.h
new file mode 100644
index 0000000000..01840b14c9
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/SerialIo/IncludePrivate/Register/SerialIoRegsVer2.h
@@ -0,0 +1,108 @@
+/** @file
+ Device IDs for Serial IO Controllers for TGL PCH
+
+ Conventions:
+
+ - Register definition format:
+ Prefix_[GenerationName]_[ComponentName]_SubsystemName_RegisterSpace_RegisterName
+ - Prefix:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register size
+ Definitions beginning with "N_" are the bit position
+ - [GenerationName]:
+ Three letter acronym of the generation is used (e.g. SKL,KBL,CNL etc.).
+ Register name without GenerationName applies to all generations.
+ - [ComponentName]:
+ This field indicates the component name that the register belongs to (e.g. PCH, SA etc.)
+ Register name without ComponentName applies to all components.
+
+ Register that is specific to -LP denoted by "_PCH_LP_" in component name.
+ - SubsystemName:
+ This field indicates the subsystem name of the component that the register belongs to
+ (e.g. PCIE, USB, SATA, GPIO, PMC etc.).
+ - RegisterSpace:
+ MEM - MMIO space register of subsystem.
+ IO - IO space register of subsystem.
+ PCR - Private configuration register of subsystem.
+ CFG - PCI configuration space register of subsystem.
+ - RegisterName:
+ Full register name.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _SERIAL_IO_REGS_VER2_H_
+#define _SERIAL_IO_REGS_VER2_H_
+//
+// Serial IO I2C0 Controller Registers
+//
+#define V_VER2_PCH_LP_SERIAL_IO_CFG_I2C0_DEVICE_ID 0xA0E8
+
+//
+// Serial IO I2C1 Controller Registers
+//
+#define V_VER2_PCH_LP_SERIAL_IO_CFG_I2C1_DEVICE_ID 0xA0E9
+
+//
+// Serial IO I2C2 Controller Registers
+//
+#define V_VER2_PCH_LP_SERIAL_IO_CFG_I2C2_DEVICE_ID 0xA0EA
+
+//
+// Serial IO I2C3 Controller Registers
+//
+#define V_VER2_PCH_LP_SERIAL_IO_CFG_I2C3_DEVICE_ID 0xA0EB
+
+//
+// Serial IO I2C4 Controller Registers
+//
+#define V_VER2_PCH_LP_SERIAL_IO_CFG_I2C4_DEVICE_ID 0xA0C5
+
+//
+// Serial IO I2C5 Controller Registers
+//
+#define V_VER2_PCH_LP_SERIAL_IO_CFG_I2C5_DEVICE_ID 0xA0C6
+
+//
+// Serial IO SPI0 Controller Registers
+//
+#define V_VER2_PCH_LP_SERIAL_IO_CFG_SPI0_DEVICE_ID 0xA0AA
+
+//
+// Serial IO SPI1 Controller Registers
+//
+#define V_VER2_PCH_LP_SERIAL_IO_CFG_SPI1_DEVICE_ID 0xA0AB
+
+//
+// Serial IO SPI2 Controller Registers
+//
+#define V_VER2_PCH_LP_SERIAL_IO_CFG_SPI2_DEVICE_ID 0xA0FB
+
+//
+// Serial IO SPI3 Controller Registers
+//
+#define V_VER2_PCH_LP_SERIAL_IO_CFG_SPI3_DEVICE_ID 0xA0FD
+
+//
+// Serial IO UART0 Controller Registers
+//
+#define V_VER2_PCH_LP_SERIAL_IO_CFG_UART0_DEVICE_ID 0xA0A8
+
+//
+// Serial IO UART1 Controller Registers
+//
+#define V_VER2_PCH_LP_SERIAL_IO_CFG_UART1_DEVICE_ID 0xA0A9
+
+//
+// Serial IO UART2 Controller Registers
+//
+#define V_VER2_PCH_LP_SERIAL_IO_CFG_UART2_DEVICE_ID 0xA0C7
+
+//
+// Serial IO UART3 Controller Registers
+//
+#define V_VER2_PCH_LP_SERIAL_IO_CFG_UART3_DEVICE_ID 0xA0DA
+
+#endif //_SERIAL_IO_REGS_VER2_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/SerialIo/Library/PeiDxeSmmSerialIoAccessLib/PeiDxeSmmSerialIoAccessLib.inf b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/SerialIo/Library/PeiDxeSmmSerialIoAccessLib/PeiDxeSmmSerialIoAccessLib.inf
new file mode 100644
index 0000000000..9178840ca8
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/SerialIo/Library/PeiDxeSmmSerialIoAccessLib/PeiDxeSmmSerialIoAccessLib.inf
@@ -0,0 +1,35 @@
+## @file
+# Component description file for PEI/DXE/SMM Serial Io Access Lib.
+#
+# All function in this library is available for PEI, DXE, and SMM,
+# But do not support UEFI RUNTIME environment call.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+
+[Defines]
+ INF_VERSION = 0x00010017
+ BASE_NAME = PeiDxeSmmSerialIoAccessLib
+ FILE_GUID = F1A20692-26CA-4CA4-A775-695BBD6D3EC7
+ VERSION_STRING = 1.0
+ MODULE_TYPE = BASE
+ LIBRARY_CLASS = SerialIoAccessLib
+
+[LibraryClasses]
+ BaseLib
+ IoLib
+ DebugLib
+ PcdLib
+ PciSegmentLib
+ PchPcrLib
+ SerialIoPrivateLib
+
+[Packages]
+ MdePkg/MdePkg.dec
+ TigerlakeSiliconPkg/SiPkg.dec
+
+[Sources]
+ SerialIoAccessLib.c
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/SerialIo/Library/PeiDxeSmmSerialIoAccessLib/SerialIoAccessLib.c b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/SerialIo/Library/PeiDxeSmmSerialIoAccessLib/SerialIoAccessLib.c
new file mode 100644
index 0000000000..2b3a3dca5a
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/SerialIo/Library/PeiDxeSmmSerialIoAccessLib/SerialIoAccessLib.c
@@ -0,0 +1,266 @@
+/** @file
+ Serial Io Common Lib implementation.
+ All function in this library is available for PEI, DXE, and SMM,
+ But do not support UEFI RUNTIME environment call.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Include/PcieRegs.h>
+#include <IndustryStandard/Pci30.h>
+#include <Register/PchRegs.h>
+#include <Library/IoLib.h>
+#include <Library/BaseLib.h>
+#include <Library/SerialIoAccessLib.h>
+#include <Library/SerialIoPrivateLib.h>
+#include <Library/PciSegmentLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/S3BootScriptLib.h>
+#include <Library/DebugLib.h>
+#include <PchLimits.h>
+#include <PchReservedResources.h>
+#include <Library/PchPciBdfLib.h>
+
+/**
+ Returns BAR0
+
+ @param[in] PciCfgBase Pci Config Base
+
+ @retval 64bit MMIO BAR Address
+**/
+UINT64
+GetSerialIoBar (
+ IN UINT64 PciCfgBase
+ )
+{
+ if (PciCfgBase < PCH_SERIAL_IO_BASE_ADDRESS) {
+ return (UINT64) ((PciSegmentRead32 ((UINTN) (PciCfgBase + PCI_BASE_ADDRESSREG_OFFSET)) & 0xFFFFF000) + LShiftU64 (PciSegmentRead32 ((UINTN) (PciCfgBase + PCI_BASE_ADDRESSREG_OFFSET + 4)), 32));
+ }
+ return (UINT64) ((MmioRead32 ((UINTN) (PciCfgBase + PCI_BASE_ADDRESSREG_OFFSET)) & 0xFFFFF000) + LShiftU64 (MmioRead32 ((UINTN) (PciCfgBase + PCI_BASE_ADDRESSREG_OFFSET + 4)), 32));
+}
+
+/**
+ Returns I2C Pci Config Space
+
+ @param[in] I2cNumber I2C Number
+
+ @retval I2C Pci Config Space Address
+**/
+UINT64
+GetSerialIoI2cPciCfg (
+ IN UINT8 I2cNumber
+ )
+{
+ if (IsSerialIoI2cHidden (I2cNumber)) {
+ return (UINTN) GetSerialIoI2cFixedPciCfgAddress (I2cNumber);
+ }
+ return SerialIoI2cPciCfgBase (I2cNumber);
+}
+
+/**
+ Returns SPI Pci Config Space
+
+ @param[in] SpiNumber SPI Number
+
+ @retval SPI Pci Config Space Address
+**/
+UINT64
+GetSerialIoSpiPciCfg (
+ IN UINT8 SpiNumber
+ )
+{
+ if (IsSerialIoSpiHidden (SpiNumber)) {
+ return (UINTN) GetSerialIoSpiFixedPciCfgAddress (SpiNumber);
+ }
+ return SerialIoSpiPciCfgBase (SpiNumber);
+}
+
+/**
+ Returns UART Pci Config Space
+
+ @param[in] UartNumber UART Number
+
+ @retval UART Pci Config Space Address
+**/
+UINT64
+GetSerialIoUartPciCfg (
+ IN UINT8 UartNumber
+ )
+{
+ if (IsSerialIoUartHidden (UartNumber)) {
+ return GetSerialIoUartFixedPciCfgAddress (UartNumber);
+ }
+ return SerialIoUartPciCfgBase (UartNumber);
+}
+
+/**
+ Returns SPI S3 boot script PCI address
+
+ @param[in] UartNumber UART Number
+
+ @retval SPI S3 boot script PCI address
+**/
+UINT64
+GetSerialIoSpiS3PciBase (
+ IN UINT8 SpiNumber
+ )
+{
+ if (IsSerialIoSpiHidden (SpiNumber)) {
+ //
+ // It's not expected to return Spi S3 Boot Script PCI address for non PCI mode.
+ //
+ ASSERT (TRUE);
+ }
+ return S3_BOOT_SCRIPT_LIB_PCI_ADDRESS (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ SerialIoSpiDevNumber (SpiNumber),
+ SerialIoSpiFuncNumber (SpiNumber),
+ 0
+ );
+}
+
+/**
+ Returns UART S3 boot script PCI address
+
+ @param[in] UartNumber UART Number
+
+ @retval UART S3 boot script PCI address
+**/
+UINT64
+GetSerialIoUartS3PciBase (
+ IN UINT8 UartNumber
+ )
+{
+ if (IsSerialIoUartHidden (UartNumber)) {
+ //
+ // It's not expected to return Uart S3 Boot Script PCI address for non PCI mode.
+ //
+ ASSERT (TRUE);
+ }
+ return S3_BOOT_SCRIPT_LIB_PCI_ADDRESS (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ SerialIoUartDevNumber (UartNumber),
+ SerialIoUartFuncNumber (UartNumber),
+ 0
+ );
+}
+
+/**
+ Returns I2C S3 boot script PCI address
+
+ @param[in] I2cNumber I2C Number
+
+ @retval I2C S3 boot script PCI address
+**/
+UINT64
+GetSerialIoI2cS3PciBase (
+ IN UINT8 I2cNumber
+ )
+{
+ if (IsSerialIoI2cHidden (I2cNumber)) {
+ //
+ // It's not expected to return I2c S3 Boot Script PCI address for non PCI mode.
+ //
+ ASSERT (TRUE);
+ }
+ return S3_BOOT_SCRIPT_LIB_PCI_ADDRESS (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ SerialIoI2cDevNumber (I2cNumber),
+ SerialIoI2cFuncNumber (I2cNumber),
+ 0
+ );
+}
+
+/**
+ Checks if Device with given PciDeviceId is one of SerialIo I2C controllers
+ If yes, its number is returned through I2cIndex parameter, otherwise I2cIndex is not updated
+
+ @param[in] PciDevId Device ID
+ @param[out] I2cNumber Number of SerialIo I2C controller
+
+ @retval TRUE yes it is a SerialIo I2C controller
+ @retval FALSE no it isn't a SerialIo I2C controller
+**/
+BOOLEAN
+IsSerialIoI2cDeviceId (
+ IN UINT16 PciDevId,
+ OUT UINT8 *I2cNumber
+ )
+{
+ UINT8 Index;
+
+ for (Index = 0; Index < GetPchMaxSerialIoI2cControllersNum (); Index++) {
+ if (PciDevId == GetSerialIoI2cDeviceId (Index)) {
+ *I2cNumber = Index;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/**
+ Checks if I2c is Function 0 Enabled
+
+ @param[in] I2cIndex Number of the SerialIo I2C controller
+
+ @retval TRUE Enabled
+ @retval FALSE Disabled
+**/
+BOOLEAN
+IsSerialIoI2cFunction0Enabled (
+ IN UINT8 I2cIndex
+ )
+{
+ if (SerialIoI2cFuncNumber (I2cIndex) == 0) {
+ if (SerialIoHigherFunctionsEnabled (SerialIoI2cDevNumber (I2cIndex))) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/**
+ Checks if Uart is Function 0 Enabled
+
+ @param[in] UartIndex Number of the SerialIo Uart controller
+
+ @retval TRUE Enabled
+ @retval FALSE Disabled
+**/
+BOOLEAN
+IsSerialIoUartFunction0Enabled (
+ IN UINT8 UartIndex
+ )
+{
+ if (SerialIoUartFuncNumber (UartIndex) == 0) {
+ if (SerialIoHigherFunctionsEnabled (SerialIoUartDevNumber (UartIndex))) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/**
+ Checks if Spi is Function 0 Enabled
+
+ @param[in] SpiIndex Number of the SerialIo Spi controller
+
+ @retval TRUE Enabled
+ @retval FALSE Disabled
+**/
+BOOLEAN
+IsSerialIoSpiFunction0Enabled (
+ IN UINT8 SpiIndex
+ )
+{
+ if (SerialIoSpiFuncNumber (SpiIndex) == 0) {
+ if (SerialIoHigherFunctionsEnabled (SerialIoSpiDevNumber (SpiIndex))) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/SerialIo/LibraryPrivate/PeiDxeSmmSerialIoPrivateLib/PeiDxeSmmSerialIoPrivateLibVer2.inf b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/SerialIo/LibraryPrivate/PeiDxeSmmSerialIoPrivateLib/PeiDxeSmmSerialIoPrivateLibVer2.inf
new file mode 100644
index 0000000000..8981be2496
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/SerialIo/LibraryPrivate/PeiDxeSmmSerialIoPrivateLib/PeiDxeSmmSerialIoPrivateLibVer2.inf
@@ -0,0 +1,34 @@
+## @file
+# Serial Io Private Lib Ver 2
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010017
+ BASE_NAME = PeiDxeSmmSerialIoLibVer2
+ FILE_GUID = 9D9F99CD-C072-48C2-BF78-ABA3D664C0FA
+ VERSION_STRING = 1.0
+ MODULE_TYPE = BASE
+ LIBRARY_CLASS = SerialIoPrivateLib
+
+[LibraryClasses]
+ BaseLib
+ IoLib
+ PciSegmentLib
+ SerialIoAccessLib
+
+[Packages]
+ MdePkg/MdePkg.dec
+ TigerlakeSiliconPkg/SiPkg.dec
+
+[Sources]
+ SerialIoPrivateLib.c
+ SerialIoPrivateLibI2c.c
+ SerialIoPrivateLibI2cVer2.c
+ SerialIoPrivateLibSpi.c
+ SerialIoPrivateLibSpiVer2.c
+ SerialIoPrivateLibUart.c
+ SerialIoPrivateLibUartVer2.c
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/SerialIo/LibraryPrivate/PeiDxeSmmSerialIoPrivateLib/SerialIoPrivateLib.c b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/SerialIo/LibraryPrivate/PeiDxeSmmSerialIoPrivateLib/SerialIoPrivateLib.c
new file mode 100644
index 0000000000..9b84c2dda6
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/SerialIo/LibraryPrivate/PeiDxeSmmSerialIoPrivateLib/SerialIoPrivateLib.c
@@ -0,0 +1,156 @@
+/** @file
+ Serial IO Private Lib implementation.
+ All function in this library is available for PEI, DXE, and SMM,
+ But do not support UEFI RUNTIME environment call.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/BaseLib.h>
+#include <Library/SerialIoAccessLib.h>
+#include <Library/SerialIoPrivateLib.h>
+#include <Library/PciSegmentLib.h>
+#include <Register/PchRegs.h>
+#include <Register/SerialIoRegs.h>
+#include <Include/PcieRegs.h>
+#include <IndustryStandard/Pci30.h>
+#include <PchReservedResources.h>
+
+/**
+ Checks if higher functions are enabled.
+ Used for Function 0 Serial Io Device disabling
+
+ @param[in] DeviceNum Device Number
+
+ @retval TRUE At least one higher function device is enabled
+ FALSE Higher functions are disabled
+**/
+BOOLEAN
+SerialIoHigherFunctionsEnabled (
+ IN UINT8 DeviceNum
+ )
+{
+ UINT8 FuncNum;
+ //
+ // Check all other func devs(1 to 7) status except func 0.
+ //
+ for (FuncNum = 1; FuncNum <= PCI_MAX_FUNC; FuncNum++) {
+ if (PciSegmentRead16 (PCI_SEGMENT_LIB_ADDRESS (DEFAULT_PCI_SEGMENT_NUMBER_PCH,
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ DeviceNum,
+ FuncNum,
+ PCI_DEVICE_ID_OFFSET)
+ ) != 0xFFFF) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/**
+ Places SerialIo device in D3
+
+ @param[in] PciCfgBase Pci Config Offset
+
+**/
+VOID
+SerialIoSetD3 (
+ IN UINT64 PciCfgBase
+ )
+{
+ if (PciCfgBase < PCH_SERIAL_IO_BASE_ADDRESS) {
+ PciSegmentOr32 (PciCfgBase + R_SERIAL_IO_CFG_PME_CTRL_STS, BIT1 | BIT0);
+ } else {
+ MmioOr8 ((UINTN) PciCfgBase + R_SERIAL_IO_CFG_PME_CTRL_STS, BIT1 | BIT0);
+ //
+ // Reading back value after write to ensure bridge observes the BAR1 write access
+ //
+ MmioRead8 ((UINTN) PciCfgBase + R_SERIAL_IO_CFG_PME_CTRL_STS);
+ }
+}
+
+/**
+ Places SerialIo device in D0
+
+ @param[in] PciCfgBase Pci Config Offset
+
+**/
+VOID
+SerialIoSetD0 (
+ IN UINT64 PciCfgBase
+ )
+{
+ if (PciCfgBase < PCH_SERIAL_IO_BASE_ADDRESS) {
+ PciSegmentAnd32 ((UINTN) PciCfgBase + R_SERIAL_IO_CFG_PME_CTRL_STS, (UINT32) ~(BIT1 | BIT0));
+ } else {
+ MmioAnd32 ((UINTN) PciCfgBase + R_SERIAL_IO_CFG_PME_CTRL_STS, (UINT32) ~(BIT1 | BIT0));
+ //
+ // Reading back value after write to ensure bridge observes the BAR1 write access
+ //
+ MmioRead32 ((UINTN) PciCfgBase + R_SERIAL_IO_CFG_PME_CTRL_STS);
+ }
+}
+
+/**
+ Allows memory access
+
+ @param[in] PciCfgBase Pci Config Offset
+ @param[in] Hidden Mode that determines access type
+
+**/
+VOID
+SerialIoEnableMse (
+ IN UINT64 PciCfgBase,
+ IN BOOLEAN Hidden
+ )
+{
+ if (Hidden) {
+ MmioOr16 ((UINTN) PciCfgBase + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_MEMORY_SPACE);
+ //
+ // Reading back value after write to ensure bridge observes the BAR1 write access
+ //
+ MmioRead16 ((UINTN) PciCfgBase + PCI_COMMAND_OFFSET);
+ } else {
+ PciSegmentOr16 ((UINTN) PciCfgBase + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_MEMORY_SPACE);
+ }
+}
+
+/**
+ Disable SerialIo memory access
+
+ @param[in] PciCfgBase Pci Config Offset
+
+**/
+VOID
+SerialIoDisableMse (
+ IN UINT64 PciCfgBase
+ )
+{
+ PciSegmentAnd16 ((UINTN) PciCfgBase + PCI_COMMAND_OFFSET, (UINT16) ~EFI_PCI_COMMAND_MEMORY_SPACE);
+}
+
+/**
+ Disable SerialIo memory encoding
+ Designated for Pci modes
+
+ @param[in] PciCfgBase Pci Config Offset
+ @param[in] RemoveTempBar Remove temporary mem base address or not
+
+**/
+VOID
+SerialIoMmioDisable (
+ IN UINT64 PciCfgBase,
+ IN BOOLEAN RemoveBar
+ )
+{
+ SerialIoDisableMse (PciCfgBase);
+
+ if (RemoveBar == TRUE) {
+ PciSegmentWrite32 ((UINTN) PciCfgBase + R_SERIAL_IO_CFG_BAR0_LOW, 0x0);
+ PciSegmentWrite32 ((UINTN) PciCfgBase + R_SERIAL_IO_CFG_BAR0_HIGH, 0x0);
+ }
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/SerialIo/LibraryPrivate/PeiDxeSmmSerialIoPrivateLib/SerialIoPrivateLibI2c.c b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/SerialIo/LibraryPrivate/PeiDxeSmmSerialIoPrivateLib/SerialIoPrivateLibI2c.c
new file mode 100644
index 0000000000..7601081cfa
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/SerialIo/LibraryPrivate/PeiDxeSmmSerialIoPrivateLib/SerialIoPrivateLibI2c.c
@@ -0,0 +1,122 @@
+/** @file
+ Common Serial IO Private Lib implementation - I2C part
+ All function in this library is available for PEI, DXE, and SMM,
+ But do not support UEFI RUNTIME environment call.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/BaseLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/PciSegmentLib.h>
+#include <Library/SerialIoAccessLib.h>
+#include <Library/SerialIoPrivateLib.h>
+#include <IndustryStandard/Pci30.h>
+#include <Register/PchRegs.h>
+#include <Register/SerialIoRegs.h>
+#include <SerialIoPrivateLibInternal.h>
+#include <PchLimits.h>
+#include <Library/PchPciBdfLib.h>
+
+/**
+ Checks if I2C is Hidden, and it's Pci Config space available
+
+ @param[in] I2cNumber Selects Serial IO I2C device
+
+ @retval TRUE I2C is in hidden mode
+ @retval FALSE I2C is not in hidden mode
+**/
+BOOLEAN
+IsSerialIoI2cHidden (
+ IN UINT8 I2cNumber
+ )
+{
+ if (MmioRead16 (GetSerialIoI2cFixedPciCfgAddress (I2cNumber) + PCI_DEVICE_ID_OFFSET) == GetSerialIoI2cDeviceId (I2cNumber)) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ Configures Serial IO Controller before control is passd to the OS
+
+ @param[in] I2cNumber I2C Number
+ @param[in] I2cDeviceConfig SerialIo I2C Config
+
+**/
+VOID
+SerialIoI2cBootHandler (
+ IN UINT8 I2cNumber,
+ IN SERIAL_IO_I2C_CONFIG *I2cDeviceConfig
+ )
+{
+ UINT64 PciCfgBase;
+ BOOLEAN TurnOff;
+
+ TurnOff = FALSE;
+
+ if (I2cDeviceConfig->Mode == SerialIoI2cPci) {
+ TurnOff = TRUE;
+ }
+
+ if ((I2cDeviceConfig->Mode == SerialIoI2cDisabled) && (SerialIoI2cFuncNumber (I2cNumber) == 0x0)) {
+ if (SerialIoHigherFunctionsEnabled (SerialIoI2cDevNumber (I2cNumber))) {
+ TurnOff = TRUE;
+ }
+ }
+
+ if (TurnOff) {
+ PciCfgBase = GetSerialIoI2cPciCfg (I2cNumber);
+ SerialIoSetD3 (PciCfgBase);
+ SerialIoMmioDisable (PciCfgBase, TRUE);
+ }
+}
+
+/**
+ Sets Pme Control Status and Command register values required for S3 Boot Script
+
+ @param[in] I2cNumber I2C Number
+ @param[in] I2cDeviceConfig SerialIo I2C Config
+ @param[in/out] S3PciCfgBase S3 Boot Script Pci Config Base
+ @param[in/out] Command Pci Command register data to save
+ @param[in/out] Pme Pci Pme Control register data to save
+
+**/
+VOID
+SerialIoI2cS3Handler (
+ IN UINT8 I2cNumber,
+ IN SERIAL_IO_I2C_CONFIG *I2cDeviceConfig,
+ IN OUT UINT64 *S3PciCfgBase,
+ IN OUT UINT32 *Command,
+ IN OUT UINT32 *Pme
+ )
+{
+ BOOLEAN TurnOff;
+ UINT64 PciCfgBase;
+
+ *S3PciCfgBase = 0;
+ TurnOff = FALSE;
+
+ if (I2cDeviceConfig->Mode == SerialIoI2cPci) {
+ TurnOff = TRUE;
+ }
+
+ if ((I2cDeviceConfig->Mode == SerialIoI2cDisabled) && (SerialIoI2cFuncNumber (I2cNumber) == 0x0)) {
+ if (SerialIoHigherFunctionsEnabled (SerialIoI2cDevNumber (I2cNumber))) {
+ TurnOff = TRUE;
+ }
+ }
+
+ if (TurnOff) {
+ *S3PciCfgBase = GetSerialIoI2cS3PciBase (I2cNumber);
+ PciCfgBase = GetSerialIoI2cPciCfg (I2cNumber);
+ *Pme = PciSegmentRead32 ((UINTN) PciCfgBase + R_SERIAL_IO_CFG_PME_CTRL_STS);
+ *Pme = *Pme | BIT0 | BIT1;
+ *Command = PciSegmentRead32 ((UINTN) PciCfgBase + PCI_COMMAND_OFFSET);
+ *Command = *Command & (UINT32)~(EFI_PCI_COMMAND_MEMORY_SPACE | EFI_PCI_COMMAND_BUS_MASTER);
+ }
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/SerialIo/LibraryPrivate/PeiDxeSmmSerialIoPrivateLib/SerialIoPrivateLibI2cVer2.c b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/SerialIo/LibraryPrivate/PeiDxeSmmSerialIoPrivateLib/SerialIoPrivateLibI2cVer2.c
new file mode 100644
index 0000000000..fd684ca2a9
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/SerialIo/LibraryPrivate/PeiDxeSmmSerialIoPrivateLib/SerialIoPrivateLibI2cVer2.c
@@ -0,0 +1,70 @@
+/** @file
+ Serial IO I2C Private Lib implementation TigerLake specific.
+ All function in this library is available for PEI, DXE, and SMM,
+ But do not support UEFI RUNTIME environment call.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/BaseLib.h>
+#include <Library/PchInfoLib.h>
+#include <Register/SerialIoRegsVer2.h>
+#include <IndustryStandard/Pci30.h>
+#include <SerialIoPrivateLibInternal.h>
+#include <PchReservedResources.h>
+#include <PchLimits.h>
+
+GLOBAL_REMOVE_IF_UNREFERENCED UINT16 mPchLpSerialIoI2cDevId [] = {
+ V_VER2_PCH_LP_SERIAL_IO_CFG_I2C0_DEVICE_ID,
+ V_VER2_PCH_LP_SERIAL_IO_CFG_I2C1_DEVICE_ID,
+ V_VER2_PCH_LP_SERIAL_IO_CFG_I2C2_DEVICE_ID,
+ V_VER2_PCH_LP_SERIAL_IO_CFG_I2C3_DEVICE_ID,
+ V_VER2_PCH_LP_SERIAL_IO_CFG_I2C4_DEVICE_ID,
+ V_VER2_PCH_LP_SERIAL_IO_CFG_I2C5_DEVICE_ID
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED SERIAL_IO_CONTROLLER_DESCRIPTOR mSerialIoI2cFixedAddress [] = {
+ {PCH_SERIAL_IO_BASE_ADDRESS + 0x0000, PCH_SERIAL_IO_BASE_ADDRESS + 0x1000},
+ {PCH_SERIAL_IO_BASE_ADDRESS + 0x2000, PCH_SERIAL_IO_BASE_ADDRESS + 0x3000},
+ {PCH_SERIAL_IO_BASE_ADDRESS + 0x4000, PCH_SERIAL_IO_BASE_ADDRESS + 0x5000},
+ {PCH_SERIAL_IO_BASE_ADDRESS + 0x6000, PCH_SERIAL_IO_BASE_ADDRESS + 0x7000},
+ {PCH_SERIAL_IO_BASE_ADDRESS + 0x8000, PCH_SERIAL_IO_BASE_ADDRESS + 0x9000},
+ {PCH_SERIAL_IO_BASE_ADDRESS + 0xA000, PCH_SERIAL_IO_BASE_ADDRESS + 0xB000},
+ {PCH_SERIAL_IO_BASE_ADDRESS + 0xC000, PCH_SERIAL_IO_BASE_ADDRESS + 0xD000},
+ {PCH_SERIAL_IO_BASE_ADDRESS + 0xE000, PCH_SERIAL_IO_BASE_ADDRESS + 0xF000}
+};
+
+/**
+ Gets Fixed Address used for Pci Config Space manipulation
+
+ @param[in] I2cNumber Serial IO device I2C number
+
+ @retval Pci Config Address
+**/
+UINT32
+GetSerialIoI2cFixedPciCfgAddress (
+ IN UINT8 I2cNumber
+ )
+{
+ return mSerialIoI2cFixedAddress[I2cNumber].Bar1;
+}
+
+
+/**
+ Gets I2C Device Id
+
+ @param[in] I2cNumber Serial IO device I2C number
+
+ @retval Device Id
+**/
+UINT16
+GetSerialIoI2cDeviceId (
+ IN UINT8 I2cNumber
+ )
+{
+ return mPchLpSerialIoI2cDevId[I2cNumber];
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/SerialIo/LibraryPrivate/PeiDxeSmmSerialIoPrivateLib/SerialIoPrivateLibInternal.h b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/SerialIo/LibraryPrivate/PeiDxeSmmSerialIoPrivateLib/SerialIoPrivateLibInternal.h
new file mode 100644
index 0000000000..b5e8aba9ac
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/SerialIo/LibraryPrivate/PeiDxeSmmSerialIoPrivateLib/SerialIoPrivateLibInternal.h
@@ -0,0 +1,20 @@
+/** @file
+ Header file for SerialIoPrivateLibInternal.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _SERIAL_IO_PRIVATE_LIB_INTERNAL_H_
+#define _SERIAL_IO_PRIVATE_LIB_INTERNAL_H_
+
+typedef struct {
+ UINT32 Bar0;
+ UINT32 Bar1;
+} SERIAL_IO_CONTROLLER_DESCRIPTOR;
+
+typedef struct {
+ UINT8 DevNum;
+ UINT8 FuncNum;
+} SERIAL_IO_BDF_NUMBERS;
+
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/SerialIo/LibraryPrivate/PeiDxeSmmSerialIoPrivateLib/SerialIoPrivateLibSpi.c b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/SerialIo/LibraryPrivate/PeiDxeSmmSerialIoPrivateLib/SerialIoPrivateLibSpi.c
new file mode 100644
index 0000000000..a926941baf
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/SerialIo/LibraryPrivate/PeiDxeSmmSerialIoPrivateLib/SerialIoPrivateLibSpi.c
@@ -0,0 +1,122 @@
+/** @file
+ Common Serial IO Private Lib implementation - SPI part
+ All function in this library is available for PEI, DXE, and SMM,
+ But do not support UEFI RUNTIME environment call.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/BaseLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/PciSegmentLib.h>
+#include <Library/SerialIoAccessLib.h>
+#include <Library/SerialIoPrivateLib.h>
+#include <IndustryStandard/Pci30.h>
+#include <Register/PchRegs.h>
+#include <Register/SerialIoRegs.h>
+#include <SerialIoPrivateLibInternal.h>
+#include <PchLimits.h>
+#include <Library/PchPciBdfLib.h>
+
+/**
+ Checks if SPI is Hidden, and it's Pci Config space available
+
+ @param[in] SpiNumber Selects Serial IO SPI device
+
+ @retval TRUE SPI is in hidden mode
+ @retval FALSE SPI is not in hidden mode
+**/
+BOOLEAN
+IsSerialIoSpiHidden (
+ IN UINT8 SpiNumber
+ )
+{
+ if (MmioRead16 (GetSerialIoSpiFixedPciCfgAddress (SpiNumber) + PCI_DEVICE_ID_OFFSET) == GetSerialIoSpiDeviceId (SpiNumber)) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ Configures Serial IO Controller before control is passd to the OS
+
+ @param[in] SpiNumber SPI Number
+ @param[in] SpiDeviceConfig SerialIo SPI Config
+
+**/
+VOID
+SerialIoSpiBootHandler (
+ IN UINT8 SpiNumber,
+ IN SERIAL_IO_SPI_CONFIG *SpiDeviceConfig
+ )
+{
+ UINT64 PciCfgBase;
+ BOOLEAN TurnOff;
+
+ TurnOff = FALSE;
+
+ if (SpiDeviceConfig->Mode == SerialIoSpiPci) {
+ TurnOff = TRUE;
+ }
+
+ if ((SpiDeviceConfig->Mode == SerialIoSpiDisabled) && (SerialIoSpiFuncNumber (SpiNumber) == 0x0)) {
+ if (SerialIoHigherFunctionsEnabled (SerialIoSpiDevNumber (SpiNumber))) {
+ TurnOff = TRUE;
+ }
+ }
+
+ if (TurnOff) {
+ PciCfgBase = GetSerialIoSpiPciCfg (SpiNumber);
+ SerialIoSetD3 (PciCfgBase);
+ SerialIoMmioDisable (PciCfgBase, TRUE);
+ }
+}
+
+/**
+ Sets Pme Control Status and Command register values required for S3 Boot Script
+
+ @param[in] SpiNumber SPI Number
+ @param[in] SpiDeviceConfig SerialIo SPI Config
+ @param[in/out] S3PciCfgBase S3 Boot Script Pci Config Base
+ @param[in/out] Command Pci Command register data to save
+ @param[in/out] Pme Pci Pme Control register data to save
+
+**/
+VOID
+SerialIoSpiS3Handler (
+ IN UINT8 SpiNumber,
+ IN SERIAL_IO_SPI_CONFIG *SpiDeviceConfig,
+ IN OUT UINT64 *S3PciCfgBase,
+ IN OUT UINT32 *Command,
+ IN OUT UINT32 *Pme
+ )
+{
+ BOOLEAN TurnOff;
+ UINT64 PciCfgBase;
+
+ *S3PciCfgBase = 0;
+ TurnOff = FALSE;
+
+ if (SpiDeviceConfig->Mode == SerialIoSpiPci) {
+ TurnOff = TRUE;
+ }
+
+ if ((SpiDeviceConfig->Mode == SerialIoSpiDisabled) && (SerialIoSpiFuncNumber (SpiNumber) == 0x0)) {
+ if (SerialIoHigherFunctionsEnabled (SerialIoSpiDevNumber (SpiNumber))) {
+ TurnOff = TRUE;
+ }
+ }
+
+ if (TurnOff) {
+ *S3PciCfgBase = GetSerialIoSpiS3PciBase (SpiNumber);
+ PciCfgBase = GetSerialIoSpiPciCfg (SpiNumber);
+ *Pme = PciSegmentRead32 ((UINTN) PciCfgBase + R_SERIAL_IO_CFG_PME_CTRL_STS);
+ *Pme = *Pme | BIT0 | BIT1;
+ *Command = PciSegmentRead32 ((UINTN) PciCfgBase + PCI_COMMAND_OFFSET);
+ *Command = *Command & (UINT32)~(EFI_PCI_COMMAND_MEMORY_SPACE | EFI_PCI_COMMAND_BUS_MASTER);
+ }
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/SerialIo/LibraryPrivate/PeiDxeSmmSerialIoPrivateLib/SerialIoPrivateLibSpiVer2.c b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/SerialIo/LibraryPrivate/PeiDxeSmmSerialIoPrivateLib/SerialIoPrivateLibSpiVer2.c
new file mode 100644
index 0000000000..abda359202
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/SerialIo/LibraryPrivate/PeiDxeSmmSerialIoPrivateLib/SerialIoPrivateLibSpiVer2.c
@@ -0,0 +1,82 @@
+/** @file
+ Serial IO Spi Private Lib implementation TigerLake specific.
+ All function in this library is available for PEI, DXE, and SMM,
+ But do not support UEFI RUNTIME environment call.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/BaseLib.h>
+#include <Library/PchInfoLib.h>
+#include <Register/SerialIoRegsVer2.h>
+#include <IndustryStandard/Pci30.h>
+#include <SerialIoPrivateLibInternal.h>
+#include <PchReservedResources.h>
+#include <PchLimits.h>
+
+GLOBAL_REMOVE_IF_UNREFERENCED UINT16 mPchLpSerialIoSpiDevId [] = {
+ V_VER2_PCH_LP_SERIAL_IO_CFG_SPI0_DEVICE_ID,
+ V_VER2_PCH_LP_SERIAL_IO_CFG_SPI1_DEVICE_ID,
+ V_VER2_PCH_LP_SERIAL_IO_CFG_SPI2_DEVICE_ID,
+ V_VER2_PCH_LP_SERIAL_IO_CFG_SPI3_DEVICE_ID
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED SERIAL_IO_CONTROLLER_DESCRIPTOR mSerialIoSpiFixedAddress [] = {
+ {PCH_SERIAL_IO_BASE_ADDRESS + 0x10000, PCH_SERIAL_IO_BASE_ADDRESS + 0x11000},
+ {PCH_SERIAL_IO_BASE_ADDRESS + 0x12000, PCH_SERIAL_IO_BASE_ADDRESS + 0x13000},
+ {PCH_SERIAL_IO_BASE_ADDRESS + 0x14000, PCH_SERIAL_IO_BASE_ADDRESS + 0x15000},
+ {PCH_SERIAL_IO_BASE_ADDRESS + 0x16000, PCH_SERIAL_IO_BASE_ADDRESS + 0x17000},
+ {PCH_SERIAL_IO_BASE_ADDRESS + 0x18000, PCH_SERIAL_IO_BASE_ADDRESS + 0x19000},
+ {PCH_SERIAL_IO_BASE_ADDRESS + 0x1A000, PCH_SERIAL_IO_BASE_ADDRESS + 0x1B000},
+ {PCH_SERIAL_IO_BASE_ADDRESS + 0x1C000, PCH_SERIAL_IO_BASE_ADDRESS + 0x1D000}
+};
+
+/**
+ Gets Fixed Base Address used for BAR0
+
+ @param[in] SpiNumber Serial IO device SPI number
+
+ @retval Config control offset
+**/
+UINT32
+GetSerialIoSpiFixedMmioAddress (
+ IN UINT8 SpiNumber
+ )
+{
+ return mSerialIoSpiFixedAddress[SpiNumber].Bar0;
+}
+
+/**
+ Gets Fixed Address used for Pci Config Space manipulation
+
+ @param[in] SpiNumber Serial IO device SPI number
+
+ @retval Pci Config Address
+**/
+UINT32
+GetSerialIoSpiFixedPciCfgAddress (
+ IN UINT8 SpiNumber
+ )
+{
+ return mSerialIoSpiFixedAddress[SpiNumber].Bar1;
+}
+
+/**
+ Gets Spi Device Id
+
+ @param[in] SpiNumber Serial IO device SPI number
+
+ @retval Device Id
+**/
+UINT16
+GetSerialIoSpiDeviceId (
+ IN UINT8 SpiNumber
+ )
+{
+ return mPchLpSerialIoSpiDevId[SpiNumber];
+}
+
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/SerialIo/LibraryPrivate/PeiDxeSmmSerialIoPrivateLib/SerialIoPrivateLibUart.c b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/SerialIo/LibraryPrivate/PeiDxeSmmSerialIoPrivateLib/SerialIoPrivateLibUart.c
new file mode 100644
index 0000000000..0f7d6513ce
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/SerialIo/LibraryPrivate/PeiDxeSmmSerialIoPrivateLib/SerialIoPrivateLibUart.c
@@ -0,0 +1,136 @@
+/** @file
+ Serial IO Private Lib implementation - UART part
+ All function in this library is available for PEI, DXE, and SMM,
+ But do not support UEFI RUNTIME environment call.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/BaseLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/PciSegmentLib.h>
+#include <Library/SerialIoAccessLib.h>
+#include <Library/SerialIoPrivateLib.h>
+#include <IndustryStandard/Pci30.h>
+#include <Register/PchRegs.h>
+#include <Register/SerialIoRegs.h>
+#include <SerialIoPrivateLibInternal.h>
+#include <PchLimits.h>
+#include <Library/PchPciBdfLib.h>
+
+/**
+ Checks if UART is Hidden, and it's Pci Config space available
+
+ @param[in] UartNumber Selects Serial IO UART device
+
+ @retval TRUE UART is in hidden mode
+ @retval FALSE UART is not in hidden mode
+**/
+BOOLEAN
+IsSerialIoUartHidden (
+ IN UINT8 UartNumber
+ )
+{
+ if (MmioRead16 (GetSerialIoUartFixedPciCfgAddress (UartNumber) + PCI_DEVICE_ID_OFFSET) == GetSerialIoUartDeviceId (UartNumber)) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ Configures Serial IO Controller before control is passd to the OS
+
+ @param[in] UartNumber UART Number
+ @param[in] UartDeviceConfig SerialIo UART Config
+
+**/
+VOID
+SerialIoUartBootHandler (
+ IN UINT8 UartNumber,
+ IN SERIAL_IO_UART_CONFIG *UartDeviceConfig
+ )
+{
+ UINT64 PciCfgBase;
+ BOOLEAN TurnOff;
+
+ TurnOff = FALSE;
+
+ //
+ // Even if Uart is Hidden and in D3 SerialIoUartLib is capable of setting D0 during each write/read.
+ // In case it is required for Os Debug DBG2 must be set to TRUE.
+ //
+ if (UartDeviceConfig->Mode == SerialIoUartPci || UartDeviceConfig->Mode == SerialIoUartHidden) {
+ TurnOff = TRUE;
+ }
+
+ //
+ // Uart in Com mode will be placed in D3 depending on PG configuration through ACPI _PS3
+ //
+
+ if ((UartDeviceConfig->Mode == SerialIoUartDisabled) && (SerialIoUartFuncNumber (UartNumber) == 0x0)) {
+ if (SerialIoHigherFunctionsEnabled (SerialIoUartDevNumber (UartNumber))) {
+ TurnOff = TRUE;
+ }
+ }
+
+ if (UartDeviceConfig->DBG2 == TRUE) {
+ TurnOff = FALSE;
+ }
+
+ if (TurnOff) {
+ PciCfgBase = GetSerialIoUartPciCfg (UartNumber);
+ SerialIoSetD3 (PciCfgBase);
+ if ((UartDeviceConfig->Mode == SerialIoUartPci) || (UartDeviceConfig->Mode == SerialIoUartDisabled)) {
+ SerialIoMmioDisable (PciCfgBase, TRUE);
+ }
+ }
+}
+
+/**
+ Sets Pme Control Status and Command register values required for S3 Boot Script
+
+ @param[in] UartNumber UART Number
+ @param[in] UartDeviceConfig SerialIo UART Config
+ @param[in/out] S3PciCfgBase S3 Boot Script Pci Config Base
+ @param[in/out] Command Pci Command register data to save
+ @param[in/out] Pme Pci Pme Control register data to save
+
+**/
+VOID
+SerialIoUartS3Handler (
+ IN UINT8 UartNumber,
+ IN SERIAL_IO_UART_CONFIG *UartDeviceConfig,
+ IN OUT UINT64 *S3PciCfgBase,
+ IN OUT UINT32 *Command,
+ IN OUT UINT32 *Pme
+ )
+{
+ BOOLEAN TurnOff;
+ UINT64 PciCfgBase;
+
+ *S3PciCfgBase = 0;
+ TurnOff = FALSE;
+
+ if (UartDeviceConfig->Mode == SerialIoUartPci) {
+ TurnOff = TRUE;
+ }
+
+ if ((UartDeviceConfig->Mode == SerialIoUartDisabled) && (SerialIoUartFuncNumber (UartNumber) == 0x0)) {
+ if (SerialIoHigherFunctionsEnabled (SerialIoUartDevNumber (UartNumber))) {
+ TurnOff = TRUE;
+ }
+ }
+
+ if (TurnOff) {
+ *S3PciCfgBase = GetSerialIoUartS3PciBase (UartNumber);
+ PciCfgBase = GetSerialIoUartPciCfg (UartNumber);
+ *Pme = PciSegmentRead32 ((UINTN) PciCfgBase + R_SERIAL_IO_CFG_PME_CTRL_STS);
+ *Pme = *Pme | BIT0 | BIT1;
+ *Command = PciSegmentRead32 ((UINTN) PciCfgBase + PCI_COMMAND_OFFSET);
+ *Command = *Command & (UINT32)~(EFI_PCI_COMMAND_MEMORY_SPACE | EFI_PCI_COMMAND_BUS_MASTER);
+ }
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/SerialIo/LibraryPrivate/PeiDxeSmmSerialIoPrivateLib/SerialIoPrivateLibUartVer2.c b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/SerialIo/LibraryPrivate/PeiDxeSmmSerialIoPrivateLib/SerialIoPrivateLibUartVer2.c
new file mode 100644
index 0000000000..91280f8e90
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/SerialIo/LibraryPrivate/PeiDxeSmmSerialIoPrivateLib/SerialIoPrivateLibUartVer2.c
@@ -0,0 +1,82 @@
+/** @file
+ Serial IO Private Uart Lib implementation TigerLake specific.
+ All function in this library is available for PEI, DXE, and SMM,
+ But do not support UEFI RUNTIME environment call.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/BaseLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/SerialIoAccessLib.h>
+#include <Register/SerialIoRegsVer2.h>
+#include <IndustryStandard/Pci30.h>
+#include <SerialIoPrivateLibInternal.h>
+#include <PchReservedResources.h>
+#include <PchLimits.h>
+
+GLOBAL_REMOVE_IF_UNREFERENCED UINT16 mPchLpSerialIoUartDevId [] = {
+ V_VER2_PCH_LP_SERIAL_IO_CFG_UART0_DEVICE_ID,
+ V_VER2_PCH_LP_SERIAL_IO_CFG_UART1_DEVICE_ID,
+ V_VER2_PCH_LP_SERIAL_IO_CFG_UART2_DEVICE_ID,
+ V_VER2_PCH_LP_SERIAL_IO_CFG_UART3_DEVICE_ID
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED SERIAL_IO_CONTROLLER_DESCRIPTOR mSerialIoUartFixedAddress [] = {
+ {PCH_SERIAL_IO_BASE_ADDRESS + 0x1E000, PCH_SERIAL_IO_BASE_ADDRESS + 0x1F000},
+ {PCH_SERIAL_IO_BASE_ADDRESS + 0x20000, PCH_SERIAL_IO_BASE_ADDRESS + 0x21000},
+ {PCH_SERIAL_IO_BASE_ADDRESS + 0x22000, PCH_SERIAL_IO_BASE_ADDRESS + 0x23000},
+ {PCH_SERIAL_IO_BASE_ADDRESS + 0x24000, PCH_SERIAL_IO_BASE_ADDRESS + 0x25000},
+ {PCH_SERIAL_IO_BASE_ADDRESS + 0x26000, PCH_SERIAL_IO_BASE_ADDRESS + 0x27000},
+ {PCH_SERIAL_IO_BASE_ADDRESS + 0x28000, PCH_SERIAL_IO_BASE_ADDRESS + 0x29000},
+ {PCH_SERIAL_IO_BASE_ADDRESS + 0x2A000, PCH_SERIAL_IO_BASE_ADDRESS + 0x2B000}
+};
+
+/**
+ Gets Fixed Base Address used for BAR0
+
+ @param[in] UartNumber Serial IO device UART number
+
+ @retval Config control offset
+**/
+UINT32
+GetSerialIoUartFixedMmioAddress (
+ IN UINT8 UartNumber
+ )
+{
+ return mSerialIoUartFixedAddress[UartNumber].Bar0;
+}
+
+/**
+ Gets Fixed Address used for Pci Config Space manipulation
+
+ @param[in] UartNumber Serial IO device UART number
+
+ @retval Pci Config Address
+**/
+UINT32
+GetSerialIoUartFixedPciCfgAddress (
+ IN UINT8 UartNumber
+ )
+{
+ return mSerialIoUartFixedAddress[UartNumber].Bar1;
+}
+
+/**
+ Gets Uarts Device Id
+
+ @param[in] UartNumbe Serial IO device UART number
+
+ @retval Device Id
+**/
+UINT16
+GetSerialIoUartDeviceId (
+ IN UINT8 UartNumber
+ )
+{
+ return mPchLpSerialIoUartDevId[UartNumber];
+}
--
2.24.0.windows.2
^ permalink raw reply related [flat|nested] 42+ messages in thread
* [Patch V3 28/40] TigerlakeSiliconPkg/IpBlock: Add Smbus component
2021-02-05 7:40 [Patch V3 01/40] TigerlakeSiliconPkg: Add package and Include/ConfigBlock headers Heng Luo
` (25 preceding siblings ...)
2021-02-05 7:40 ` [Patch V3 27/40] TigerlakeSiliconPkg/IpBlock: Add SerialIo component Heng Luo
@ 2021-02-05 7:40 ` Heng Luo
2021-02-05 7:40 ` [Patch V3 29/40] TigerlakeSiliconPkg/IpBlock: Add Spi component Heng Luo
` (11 subsequent siblings)
38 siblings, 0 replies; 42+ messages in thread
From: Heng Luo @ 2021-02-05 7:40 UTC (permalink / raw)
To: devel; +Cc: Sai Chaganty, Nate DeSimone
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3171
Adds the following files:
* IpBlock/Smbus/IncludePrivate
Cc: Sai Chaganty <rangasai.v.chaganty@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Signed-off-by: Heng Luo <heng.luo@intel.com>
---
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Smbus/IncludePrivate/Register/SmbusRegs.h | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 50 insertions(+)
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Smbus/IncludePrivate/Register/SmbusRegs.h b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Smbus/IncludePrivate/Register/SmbusRegs.h
new file mode 100644
index 0000000000..c863615583
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Smbus/IncludePrivate/Register/SmbusRegs.h
@@ -0,0 +1,50 @@
+/** @file
+ Register names for PCH Smbus Device.
+
+ Conventions:
+
+ - Register definition format:
+ Prefix_[GenerationName]_[ComponentName]_SubsystemName_RegisterSpace_RegisterName
+ - Prefix:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register size
+ Definitions beginning with "N_" are the bit position
+ - [GenerationName]:
+ Three letter acronym of the generation is used (e.g. SKL,KBL,CNL etc.).
+ Register name without GenerationName applies to all generations.
+ - [ComponentName]:
+ This field indicates the component name that the register belongs to (e.g. PCH, SA etc.)
+ Register name without ComponentName applies to all components.
+ Register that is specific to -LP denoted by "_PCH_LP_" in component name.
+ - SubsystemName:
+ This field indicates the subsystem name of the component that the register belongs to
+ (e.g. PCIE, USB, SATA, GPIO, PMC etc.).
+ - RegisterSpace:
+ MEM - MMIO space register of subsystem.
+ IO - IO space register of subsystem.
+ PCR - Private configuration register of subsystem.
+ CFG - PCI configuration space register of subsystem.
+ - RegisterName:
+ Full register name.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PCH_REGS_SMBUS_H_
+#define _PCH_REGS_SMBUS_H_
+
+//
+// SMBus Controller Registers
+//
+#define R_SMBUS_CFG_BASE 0x20
+#define B_SMBUS_CFG_BASE_BAR 0x0000FFE0
+
+//
+// SMBus I/O Registers
+//
+#define R_SMBUS_IO_HSTS 0x00 ///< Host Status Register R/W
+#define B_SMBUS_IO_SMBALERT_STS 0x20
+
+#endif
--
2.24.0.windows.2
^ permalink raw reply related [flat|nested] 42+ messages in thread
* [Patch V3 29/40] TigerlakeSiliconPkg/IpBlock: Add Spi component
2021-02-05 7:40 [Patch V3 01/40] TigerlakeSiliconPkg: Add package and Include/ConfigBlock headers Heng Luo
` (26 preceding siblings ...)
2021-02-05 7:40 ` [Patch V3 28/40] TigerlakeSiliconPkg/IpBlock: Add Smbus component Heng Luo
@ 2021-02-05 7:40 ` Heng Luo
2021-02-05 7:40 ` [Patch V3 30/40] TigerlakeSiliconPkg/IpBlock: Add Vtd component Heng Luo
` (10 subsequent siblings)
38 siblings, 0 replies; 42+ messages in thread
From: Heng Luo @ 2021-02-05 7:40 UTC (permalink / raw)
To: devel; +Cc: Sai Chaganty, Nate DeSimone
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3171
Adds the following files:
* IpBlock/Spi/IncludePrivate
* IpBlock/Spi/Library
* IpBlock/Spi/LibraryPrivate
* IpBlock/Spi/Smm
Cc: Sai Chaganty <rangasai.v.chaganty@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Signed-off-by: Heng Luo <heng.luo@intel.com>
---
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/IncludePrivate/Library/SpiAccessPrivateLib.h | 40 ++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/IncludePrivate/Library/SpiCommonLib.h | 364 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/IncludePrivate/Register/SpiRegs.h | 136 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/Library/PeiDxeSmmSpiAccessLib/PeiDxeSmmSpiAccessLib.inf | 33 ++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/Library/PeiDxeSmmSpiAccessLib/SpiAccessLib.c | 477 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/LibraryPrivate/BaseSpiCommonLib/BaseSpiCommonLib.inf | 31 +++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/LibraryPrivate/BaseSpiCommonLib/SpiCommon.c | 1115 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/LibraryPrivate/PeiDxeSmmSpiAccessPrivateLib/PeiDxeSmmSpiAccessPrivateLib.inf | 40 ++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/LibraryPrivate/PeiDxeSmmSpiAccessPrivateLib/SpiAccessPrivateLib.c | 133 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/Smm/Spi.c | 296 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/Smm/SpiSmm.inf | 47 +++++++++++++++++++++++++++++++++++++
11 files changed, 2712 insertions(+)
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/IncludePrivate/Library/SpiAccessPrivateLib.h b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/IncludePrivate/Library/SpiAccessPrivateLib.h
new file mode 100644
index 0000000000..6da88a9047
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/IncludePrivate/Library/SpiAccessPrivateLib.h
@@ -0,0 +1,40 @@
+/** @file
+ SPI library header for abstraction of SPI HW registers accesses
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _SPI_ACCESS_PRIVATE_LIB_H_
+#define _SPI_ACCESS_PRIVATE_LIB_H_
+
+/**
+ Disable EISS (Enable InSMM.STS)
+**/
+VOID
+SpiDisableEiss (
+ VOID
+ );
+
+/**
+ Configure BiosLockEnable bit and BiosInterfaceLock bit according to policy setting.
+
+ @param[in] BiosLockEnable Policy for BiosLockEnable bit programming
+ @param[in] BiosInterfaceLock Policy for BiosInterfaceLock bit programming
+
+**/
+VOID
+SpiBiosLockEnableAndBiosInterfaceLockWithS3BootScript (
+ IN BOOLEAN BiosLockEnable,
+ IN BOOLEAN BiosInterfaceLock
+ );
+
+/**
+ Clears BIOS Write Protect Disable bit
+**/
+VOID
+SpiClearBiosWriteProtectDisable (
+ VOID
+ );
+
+#endif // _SPI_ACCESS_PRIVATE_LIB_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/IncludePrivate/Library/SpiCommonLib.h b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/IncludePrivate/Library/SpiCommonLib.h
new file mode 100644
index 0000000000..3290f77122
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/IncludePrivate/Library/SpiCommonLib.h
@@ -0,0 +1,364 @@
+/** @file
+ Header file for the PCH SPI Common Driver.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _SPI_COMMON_LIB_H_
+#define _SPI_COMMON_LIB_H_
+
+#include <Protocol/Spi.h>
+
+//
+// Maximum time allowed while waiting the SPI cycle to complete
+// Wait Time = 6 seconds = 6000000 microseconds
+// Wait Period = 10 microseconds
+//
+#define SPI_WAIT_TIME 6000000 ///< Wait Time = 6 seconds = 6000000 microseconds
+#define SPI_WAIT_PERIOD 10 ///< Wait Period = 10 microseconds
+
+///
+/// Flash cycle Type
+///
+typedef enum {
+ FlashCycleRead,
+ FlashCycleWrite,
+ FlashCycleErase,
+ FlashCycleReadSfdp,
+ FlashCycleReadJedecId,
+ FlashCycleWriteStatus,
+ FlashCycleReadStatus,
+ FlashCycleMax
+} FLASH_CYCLE_TYPE;
+
+///
+/// Flash Component Number
+///
+typedef enum {
+ FlashComponent0,
+ FlashComponent1,
+ FlashComponentMax
+} FLASH_COMPONENT_NUM;
+
+///
+/// Private data structure definitions for the driver
+///
+#define PCH_SPI_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('P', 'S', 'P', 'I')
+
+typedef struct {
+ UINT32 Signature;
+ EFI_HANDLE Handle;
+ PCH_SPI_PROTOCOL SpiProtocol;
+ UINT16 PchAcpiBase;
+ UINT64 PchSpiBase;
+ UINT8 ReadPermission;
+ UINT8 WritePermission;
+ UINT32 SfdpVscc0Value;
+ UINT32 SfdpVscc1Value;
+ UINT16 PchStrapBaseAddr;
+ UINT16 PchStrapSize;
+ UINT16 CpuStrapBaseAddr;
+ UINT16 CpuStrapSize;
+ UINT8 NumberOfComponents;
+ UINT32 Component1StartAddr;
+ UINT32 TotalFlashSize;
+} SPI_INSTANCE;
+
+#define SPI_INSTANCE_FROM_SPIPROTOCOL(a) CR (a, SPI_INSTANCE, SpiProtocol, PCH_SPI_PRIVATE_DATA_SIGNATURE)
+
+//
+// Function prototypes used by the SPI protocol.
+//
+
+/**
+ Initialize an SPI protocol instance.
+
+ @param[in] SpiInstance Pointer to SpiInstance to initialize
+
+ @retval EFI_SUCCESS The protocol instance was properly initialized
+ @exception EFI_UNSUPPORTED The PCH is not supported by this module
+**/
+EFI_STATUS
+SpiProtocolConstructor (
+ IN SPI_INSTANCE *SpiInstance
+ );
+
+/**
+ This function is a hook for Spi to disable BIOS Write Protect
+
+ @retval EFI_SUCCESS The protocol instance was properly initialized
+ @retval EFI_ACCESS_DENIED The BIOS Region can only be updated in SMM phase
+
+**/
+EFI_STATUS
+EFIAPI
+DisableBiosWriteProtect (
+ VOID
+ );
+
+/**
+ This function is a hook for Spi to enable BIOS Write Protect
+
+
+**/
+VOID
+EFIAPI
+EnableBiosWriteProtect (
+ VOID
+ );
+
+/**
+ Acquire pch spi mmio address.
+
+ @param[in] SpiInstance Pointer to SpiInstance to initialize
+
+ @retval PchSpiBar0 return SPI MMIO address
+**/
+UINTN
+AcquireSpiBar0 (
+ IN SPI_INSTANCE *SpiInstance
+ );
+
+/**
+ Release pch spi mmio address.
+
+ @param[in] SpiInstance Pointer to SpiInstance to initialize
+
+ @retval None
+**/
+VOID
+ReleaseSpiBar0 (
+ IN SPI_INSTANCE *SpiInstance
+ );
+
+/**
+ Check if it's granted to do flash write.
+
+ @retval TRUE It's secure to do flash write.
+ @retval FALSE It's not secure to do flash write.
+**/
+BOOLEAN
+IsSpiFlashWriteGranted (
+ VOID
+ );
+
+/**
+ Read data from the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] FlashRegionType The Flash Region type for flash cycle which is listed in the Descriptor.
+ @param[in] Address The Flash Linear Address must fall within a region for which BIOS has access permissions.
+ @param[in] ByteCount Number of bytes in the data portion of the SPI cycle.
+ @param[out] Buffer The Pointer to caller-allocated buffer containing the dada received.
+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashRead (
+ IN PCH_SPI_PROTOCOL *This,
+ IN FLASH_REGION_TYPE FlashRegionType,
+ IN UINT32 Address,
+ IN UINT32 ByteCount,
+ OUT UINT8 *Buffer
+ );
+
+/**
+ Write data to the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] FlashRegionType The Flash Region type for flash cycle which is listed in the Descriptor.
+ @param[in] Address The Flash Linear Address must fall within a region for which BIOS has access permissions.
+ @param[in] ByteCount Number of bytes in the data portion of the SPI cycle.
+ @param[in] Buffer Pointer to caller-allocated buffer containing the data sent during the SPI cycle.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashWrite (
+ IN PCH_SPI_PROTOCOL *This,
+ IN FLASH_REGION_TYPE FlashRegionType,
+ IN UINT32 Address,
+ IN UINT32 ByteCount,
+ IN UINT8 *Buffer
+ );
+
+/**
+ Erase some area on the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] FlashRegionType The Flash Region type for flash cycle which is listed in the Descriptor.
+ @param[in] Address The Flash Linear Address must fall within a region for which BIOS has access permissions.
+ @param[in] ByteCount Number of bytes in the data portion of the SPI cycle.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashErase (
+ IN PCH_SPI_PROTOCOL *This,
+ IN FLASH_REGION_TYPE FlashRegionType,
+ IN UINT32 Address,
+ IN UINT32 ByteCount
+ );
+
+/**
+ Read SFDP data from the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] ComponentNumber The Componen Number for chip select
+ @param[in] Address The starting byte address for SFDP data read.
+ @param[in] ByteCount Number of bytes in SFDP data portion of the SPI cycle
+ @param[out] SfdpData The Pointer to caller-allocated buffer containing the SFDP data received
+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashReadSfdp (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT8 ComponentNumber,
+ IN UINT32 Address,
+ IN UINT32 ByteCount,
+ OUT UINT8 *SfdpData
+ );
+
+/**
+ Read Jedec Id from the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] ComponentNumber The Componen Number for chip select
+ @param[in] ByteCount Number of bytes in JedecId data portion of the SPI cycle, the data size is 3 typically
+ @param[out] JedecId The Pointer to caller-allocated buffer containing JEDEC ID received
+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashReadJedecId (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT8 ComponentNumber,
+ IN UINT32 ByteCount,
+ OUT UINT8 *JedecId
+ );
+
+/**
+ Write the status register in the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] ByteCount Number of bytes in Status data portion of the SPI cycle, the data size is 1 typically
+ @param[in] StatusValue The Pointer to caller-allocated buffer containing the value of Status register writing
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashWriteStatus (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT32 ByteCount,
+ IN UINT8 *StatusValue
+ );
+
+/**
+ Read status register in the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] ByteCount Number of bytes in Status data portion of the SPI cycle, the data size is 1 typically
+ @param[out] StatusValue The Pointer to caller-allocated buffer containing the value of Status register received.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashReadStatus (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT32 ByteCount,
+ OUT UINT8 *StatusValue
+ );
+
+/**
+ Get the SPI region base and size, based on the enum type
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] FlashRegionType The Flash Region type for for the base address which is listed in the Descriptor.
+ @param[out] BaseAddress The Flash Linear Address for the Region 'n' Base
+ @param[out] RegionSize The size for the Region 'n'
+
+ @retval EFI_SUCCESS Read success
+ @retval EFI_INVALID_PARAMETER Invalid region type given
+ @retval EFI_DEVICE_ERROR The region is not used
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolGetRegionAddress (
+ IN PCH_SPI_PROTOCOL *This,
+ IN FLASH_REGION_TYPE FlashRegionType,
+ OUT UINT32 *BaseAddress,
+ OUT UINT32 *RegionSize
+ );
+
+/**
+ Read PCH Soft Strap Values
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] SoftStrapAddr PCH Soft Strap address offset from FPSBA.
+ @param[in] ByteCount Number of bytes in SoftStrap data portion of the SPI cycle
+ @param[out] SoftStrapValue The Pointer to caller-allocated buffer containing PCH Soft Strap Value.
+ If the value of ByteCount is 0, the data type of SoftStrapValue should be UINT16 and SoftStrapValue will be PCH Soft Strap Length
+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolReadPchSoftStrap (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT32 SoftStrapAddr,
+ IN UINT32 ByteCount,
+ OUT VOID *SoftStrapValue
+ );
+
+/**
+ Read CPU Soft Strap Values
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] SoftStrapAddr CPU Soft Strap address offset from FCPUSBA.
+ @param[in] ByteCount Number of bytes in SoftStrap data portion of the SPI cycle.
+ @param[out] SoftStrapValue The Pointer to caller-allocated buffer containing CPU Soft Strap Value.
+ If the value of ByteCount is 0, the data type of SoftStrapValue should be UINT16 and SoftStrapValue will be PCH Soft Strap Length
+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolReadCpuSoftStrap (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT32 SoftStrapAddr,
+ IN UINT32 ByteCount,
+ OUT VOID *SoftStrapValue
+ );
+
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/IncludePrivate/Register/SpiRegs.h b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/IncludePrivate/Register/SpiRegs.h
new file mode 100644
index 0000000000..8e2029500c
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/IncludePrivate/Register/SpiRegs.h
@@ -0,0 +1,136 @@
+/** @file
+ Register names for PCH SPI device.
+
+ Conventions:
+
+ - Register definition format:
+ Prefix_[GenerationName]_[ComponentName]_SubsystemName_RegisterSpace_RegisterName
+ - Prefix:
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values within the bits
+ Definitions beginning with "S_" are register size
+ Definitions beginning with "N_" are the bit position
+ - [GenerationName]:
+ Three letter acronym of the generation is used (e.g. SKL,KBL,CNL etc.).
+ Register name without GenerationName applies to all generations.
+ - [ComponentName]:
+ This field indicates the component name that the register belongs to (e.g. PCH, SA etc.)
+ Register name without ComponentName applies to all components.
+ Register that is specific to -LP denoted by "_PCH_LP_" in component name.
+ - SubsystemName:
+ This field indicates the subsystem name of the component that the register belongs to
+ (e.g. PCIE, USB, SATA, GPIO, PMC etc.).
+ - RegisterSpace:
+ MEM - MMIO space register of subsystem.
+ IO - IO space register of subsystem.
+ PCR - Private configuration register of subsystem.
+ CFG - PCI configuration space register of subsystem.
+ - RegisterName:
+ Full register name.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _SPI_REGS_H_
+#define _SPI_REGS_H_
+
+//
+// SPI Registers
+//
+#define R_SPI_CFG_BAR0 0x10
+#define B_SPI_CFG_BAR0_MASK 0x0FFF
+
+#define R_SPI_CFG_BDE 0xD8
+
+#define R_SPI_CFG_BC 0xDC
+#define S_SPI_CFG_BC 4
+#define N_SPI_CFG_BC_ASE_BWP 11
+#define B_SPI_CFG_BC_ASE_BWP BIT11
+#define N_SPI_CFG_BC_ASYNC_SS 10
+#define B_SPI_CFG_BC_ASYNC_SS BIT10
+#define N_SPI_CFG_BC_SYNC_SS 8
+#define B_SPI_CFG_BC_SYNC_SS BIT8
+#define B_SPI_CFG_BC_BILD BIT7
+#define B_SPI_CFG_BC_BBS BIT6 ///< Boot BIOS strap
+#define N_SPI_CFG_BC_BBS 6
+#define V_SPI_CFG_BC_BBS_SPI 0 ///< Boot BIOS strapped to SPI
+#define B_SPI_CFG_BC_EISS BIT5 ///< Enable InSMM.STS
+#define B_SPI_CFG_BC_TSS BIT4
+#define B_SPI_CFG_BC_SRC (BIT3 | BIT2)
+#define N_SPI_CFG_BC_SRC 2
+#define V_SPI_CFG_BC_SRC_PREF_DIS_CACHE_DIS 0x01 ///< No prefetching and no caching
+#define B_SPI_CFG_BC_LE BIT1 ///< Lock Enable
+#define N_SPI_CFG_BC_BLE 1
+#define B_SPI_CFG_BC_WPD BIT0 ///< Write Protect Disable
+
+//
+// BIOS Flash Program Registers (based on SPI_BAR0)
+//
+#define R_SPI_MEM_HSFSC 0x04 ///< Hardware Sequencing Flash Status and Control Register(32bits)
+#define B_SPI_MEM_HSFSC_FDBC_MASK 0x3F000000 ///< Flash Data Byte Count ( <= 64), Count = (Value in this field) + 1.
+#define N_SPI_MEM_HSFSC_FDBC 24
+#define B_SPI_MEM_HSFSC_CYCLE_MASK 0x001E0000 ///< Flash Cycle.
+#define N_SPI_MEM_HSFSC_CYCLE 17
+#define V_SPI_MEM_HSFSC_CYCLE_READ 0 ///< Flash Cycle Read
+#define V_SPI_MEM_HSFSC_CYCLE_WRITE 2 ///< Flash Cycle Write
+#define V_SPI_MEM_HSFSC_CYCLE_4K_ERASE 3 ///< Flash Cycle 4K Block Erase
+#define V_SPI_MEM_HSFSC_CYCLE_64K_ERASE 4 ///< Flash Cycle 64K Sector Erase
+#define V_SPI_MEM_HSFSC_CYCLE_READ_SFDP 5 ///< Flash Cycle Read SFDP
+#define V_SPI_MEM_HSFSC_CYCLE_READ_JEDEC_ID 6 ///< Flash Cycle Read JEDEC ID
+#define V_SPI_MEM_HSFSC_CYCLE_WRITE_STATUS 7 ///< Flash Cycle Write Status
+#define V_SPI_MEM_HSFSC_CYCLE_READ_STATUS 8 ///< Flash Cycle Read Status
+#define B_SPI_MEM_HSFSC_CYCLE_FGO BIT16 ///< Flash Cycle Go.
+#define B_SPI_MEM_HSFSC_FLOCKDN BIT15 ///< Flash Configuration Lock-Down
+#define B_SPI_MEM_HSFSC_FDV BIT14 ///< Flash Descriptor Valid, once valid software can use hareware sequencing regs
+#define B_SPI_MEM_HSFSC_FDOPSS BIT13 ///< Flash Descriptor Override Pin-Strap Status
+#define B_SPI_MEM_HSFSC_WRSDIS BIT11 ///< Write Status Disable
+#define B_SPI_MEM_HSFSC_SAF_MODE_ACTIVE BIT7 ///< Indicates flash is attached either directly to the PCH via the SPI bus or EC/BMC
+#define B_SPI_MEM_HSFSC_SCIP BIT5 ///< SPI cycle in progress
+#define B_SPI_MEM_HSFSC_SAF_DLE BIT4 ///< SAF Data length error
+#define B_SPI_MEM_HSFSC_SAF_ERROR BIT3 ///< SAF Error
+#define B_SPI_MEM_HSFSC_AEL BIT2 ///< Access Error Log
+#define B_SPI_MEM_HSFSC_FCERR BIT1 ///< Flash Cycle Error
+#define B_SPI_MEM_HSFSC_FDONE BIT0 ///< Flash Cycle Done
+#define R_SPI_MEM_FADDR 0x08 ///< SPI Flash Address
+#define B_SPI_MEM_FADDR_MASK 0x07FFFFFF ///< SPI Flash Address Mask (0~26bit)
+#define R_SPI_MEM_DLOCK 0x0C ///< Discrete Lock Bits
+#define B_SPI_MEM_DLOCK_PR0LOCKDN BIT8 ///< PR0LOCKDN
+#define R_SPI_MEM_FDATA00 0x10 ///< SPI Data 00 (32 bits)
+#define R_SPI_MEM_FRAP 0x50 ///< Flash Region Access Permissions Register
+#define B_SPI_MEM_FRAP_BRWA_MASK 0x0000FF00 ///< BIOS Region Write Access MASK, Region0~7 - 0: Flash Descriptor; 1: BIOS; 2: ME; 3: GbE; 4: PlatformData
+#define N_SPI_MEM_FRAP_BRWA 8 ///< BIOS Region Write Access bit position
+#define B_SPI_MEM_FRAP_BRRA_MASK 0x000000FF ///< BIOS Region Read Access MASK, Region0~7 - 0: Flash Descriptor; 1: BIOS; 2: ME; 3: GbE; 4: PlatformData
+#define B_SPI_MEM_FRAP_BMRAG_MASK 0x00FF0000 ///< BIOS Master Read Access Grant
+#define B_SPI_MEM_FRAP_BMWAG_MASK 0xFF000000 ///< BIOS Master Write Access Grant
+#define R_SPI_MEM_FREG0_FLASHD 0x54 ///< Flash Region 0(Flash Descriptor)(32bits)
+#define R_SPI_MEM_FREG3_GBE 0x60 ///< Flash Region 3(GbE)(32bits)
+#define S_SPI_MEM_FREGX 4 ///< Size of Flash Region register
+#define B_SPI_MEM_FREGX_LIMIT_MASK 0x7FFF0000 ///< Flash Region Limit [30:16] represents [26:12], [11:0] are assumed to be FFFh
+#define N_SPI_MEM_FREGX_LIMIT 16 ///< Region limit bit position
+#define N_SPI_MEM_FREGX_LIMIT_REPR 12 ///< Region limit bit represents position
+#define B_SPI_MEM_FREGX_BASE_MASK 0x00007FFF ///< Flash Region Base, [14:0] represents [26:12]
+#define N_SPI_MEM_FREGX_BASE 0 ///< Region base bit position
+#define N_SPI_MEM_FREGX_BASE_REPR 12 ///< Region base bit represents position
+#define R_SPI_MEM_PR0 0x84 ///< Protected Region 0 Register
+#define S_SPI_MEM_PRX 4 ///< Protected Region X Register size
+#define B_SPI_MEM_PRX_WPE BIT31 ///< Write Protection Enable
+#define B_SPI_MEM_PRX_PRL_MASK 0x7FFF0000 ///< Protected Range Limit Mask, [30:16] here represents upper limit of address [26:12]
+#define N_SPI_MEM_PRX_PRL 16 ///< Protected Range Limit bit position
+#define B_SPI_MEM_PRX_RPE BIT15 ///< Read Protection Enable
+#define B_SPI_MEM_PRX_PRB_MASK 0x00007FFF ///< Protected Range Base Mask, [14:0] here represents base limit of address [26:12]
+#define N_SPI_MEM_PRX_PRB 0 ///< Protected Range Base bit position
+#define R_SPI_MEM_FDOC 0xB4 ///< Flash Descriptor Observability Control Register(32 bits)
+#define B_SPI_MEM_FDOC_FDSS_MASK (BIT14 | BIT13 | BIT12) ///< Flash Descritor Section Select
+#define V_SPI_MEM_FDOC_FDSS_FSDM 0x0000 ///< Flash Signature and Descriptor Map
+#define V_SPI_MEM_FDOC_FDSS_COMP 0x1000 ///< Component
+#define V_SPI_MEM_FDOC_FDSS_MSTR 0x3000 ///< Master
+#define B_SPI_MEM_FDOC_FDSI_MASK 0x0FFC ///< Flash Descriptor Section Index
+#define R_SPI_MEM_FDOD 0xB8 ///< Flash Descriptor Observability Data Register(32 bits)
+#define R_SPI_MEM_SFDP0_VSCC0 0xC4 ///< Vendor Specific Component Capabilities Register(32 bits)
+#define B_SPI_MEM_SFDPX_VSCCX_CPPTV BIT31 ///< Component Property Parameter Table Valid
+#define B_SPI_MEM_SFDP0_VSCC0_VCL BIT30 ///< Vendor Component Lock
+#define B_SPI_MEM_SFDPX_VSCCX_EO_64K BIT29 ///< 64k Erase valid (EO_64k_valid)
+#define R_SPI_MEM_SFDP1_VSCC1 0xC8 ///< Vendor Specific Component Capabilities Register(32 bits)
+
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/Library/PeiDxeSmmSpiAccessLib/PeiDxeSmmSpiAccessLib.inf b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/Library/PeiDxeSmmSpiAccessLib/PeiDxeSmmSpiAccessLib.inf
new file mode 100644
index 0000000000..bba0b1fef3
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/Library/PeiDxeSmmSpiAccessLib/PeiDxeSmmSpiAccessLib.inf
@@ -0,0 +1,33 @@
+## @file
+# Component description file for PCH SPI access library
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiDxeSmmSpiAccessLib
+FILE_GUID = A6D4C05A-F6CB-46D5-4BA1-8C47B139DCA6
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = SpiAccessLib
+
+
+[LibraryClasses]
+BaseLib
+IoLib
+DebugLib
+PciSegmentLib
+PchPciBdfLib
+PchPcrLib
+
+[Packages]
+MdePkg/MdePkg.dec
+TigerlakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+SpiAccessLib.c
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/Library/PeiDxeSmmSpiAccessLib/SpiAccessLib.c b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/Library/PeiDxeSmmSpiAccessLib/SpiAccessLib.c
new file mode 100644
index 0000000000..c91b9aaf4d
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/Library/PeiDxeSmmSpiAccessLib/SpiAccessLib.c
@@ -0,0 +1,477 @@
+/** @file
+ SPI library for abstraction of SPI HW registers accesses
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <IndustryStandard/Pci22.h>
+#include <Library/BaseLib.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PciSegmentLib.h>
+#include <Library/SpiAccessLib.h>
+#include <Library/PchPciBdfLib.h>
+#include <Library/PchPcrLib.h>
+#include <Register/SpiRegs.h>
+#include <Register/FlashRegs.h>
+#include <Register/PchRegs.h>
+#include <Register/PchPcrRegs.h>
+#include <Register/PchDmiRegs.h>
+
+/**
+ Checks if PCH SPI Controler is present and available
+
+ @retval TRUE PCH SPI controller is avaialable
+ @retval FALSE PCH SPI controller is not available
+**/
+BOOLEAN
+SpiIsControllerAvailable (
+ VOID
+ )
+{
+ //
+ // Checks for SPI controller
+ //
+ return (PciSegmentRead16 (SpiPciCfgBase () + PCI_VENDOR_ID_OFFSET) != 0xFFFF);
+}
+
+/**
+ Returns PCH SPI BAR0 value
+
+ @retval UINT32 PCH SPI BAR0 value
+**/
+UINT32
+SpiGetBar0 (
+ VOID
+ )
+{
+ UINT32 SpiBar0;
+
+ ASSERT (SpiIsControllerAvailable ());
+ SpiBar0 = PciSegmentRead32 (SpiPciCfgBase () + R_SPI_CFG_BAR0) & ~B_SPI_CFG_BAR0_MASK;
+ ASSERT (SpiBar0 != 0);
+
+ return SpiBar0;
+}
+
+/**
+ Reads given descriptor section and returns value
+
+ @param[in] UINT16 Descriptor section
+ @param[in] UINT16 Offset
+
+ @retval UINT32 Read value from a section under given offset
+**/
+STATIC
+UINT32
+SpiReadDescriptor (
+ IN UINT16 DescriptorSection,
+ IN UINT16 Offset
+ )
+{
+ UINT32 SpiBar0;
+ SpiBar0 = SpiGetBar0 ();
+
+ MmioWrite32 (SpiBar0 + R_SPI_MEM_FDOC, (DescriptorSection | Offset));
+ return MmioRead32 (SpiBar0 + R_SPI_MEM_FDOD);
+}
+
+/**
+ Returns descriptor signature
+
+ @retval UINT32 Descriptor signature
+**/
+UINT32
+SpiGetDescriptorSignature (
+ VOID
+ )
+{
+ //
+ // Read Descriptor offset 0x10 - To get Descriptor Signature
+ // Signature section 0x0000 + offset 0x0 which points to Descriptor offset 0x10
+ //
+ return SpiReadDescriptor (V_SPI_MEM_FDOC_FDSS_FSDM, 0x0);
+}
+
+/**
+ Returns supported features and R/W frequencies of Flash Component
+
+ @retval UINT32 Flash Component features descriptor
+**/
+UINT32
+SpiGetFlashComponentDescription (
+ VOID
+ )
+{
+ //
+ // Read Descriptor offset 0x30 - To get supported features and R/W frequencies
+ // Component section 0x1000 + offset 0x0 which points to Descriptor offset 0x30
+ //
+ return SpiReadDescriptor (V_SPI_MEM_FDOC_FDSS_COMP, 0x0);
+}
+
+/**
+ Returns number of Flash Components
+
+ @retval UINT32 Flash components number
+**/
+UINT32
+SpiGetFlashComponentsNumber (
+ VOID
+ )
+{
+ //
+ // Read Descriptor offset 0x14 - To get number of components
+ // Signature section 0x0000 + offset 0x4 which points to Descriptor offset 0x14
+ //
+ return ((SpiReadDescriptor (V_SPI_MEM_FDOC_FDSS_FSDM, R_FLASH_FDBAR_FLASH_MAP0) & B_FLASH_FDBAR_NC) >> N_FLASH_FDBAR_NC);
+}
+
+/**
+ Returns total Flash size with regards to number of flash components
+
+ @retval UINT32 Total Flash Memory size
+**/
+UINT32
+SpiGetTotalFlashSize (
+ VOID
+ )
+{
+ UINT32 Data32;
+ UINT32 ComponentsNumber;
+ UINT32 TotalFlashSize;
+
+ Data32 = SpiGetFlashComponentDescription ();
+ ComponentsNumber = SpiGetFlashComponentsNumber ();
+
+ TotalFlashSize = (V_FLASH_FLCOMP_COMP_512KB << ((UINT8) (Data32 & B_FLASH_FLCOMP_COMP0_MASK)));
+ if (ComponentsNumber == 1) {
+ TotalFlashSize += (V_FLASH_FLCOMP_COMP_512KB << ((UINT8) ((Data32 & B_FLASH_FLCOMP_COMP1_MASK) >> 4)));
+ }
+
+ return TotalFlashSize;
+}
+
+/**
+ Checks BIOS lock bits for proper value and checks if write protection is enabled
+ Expected vales are: LE bit set, EISS bit set and WPD bit cleared
+
+ @retval TRUE All protection bits are set correctly
+ @retval FALSE Not all protection bits had exepcted values
+**/
+BOOLEAN
+SpiIsWriteProtectionEnabled (
+ VOID
+ )
+{
+ UINT32 BiosControl;
+ BiosControl = PciSegmentRead32 (SpiPciCfgBase () + R_SPI_CFG_BC);
+
+ DEBUG ((DEBUG_INFO, "SPI BIOS CONTROL LE: %x\n", (BiosControl & B_SPI_CFG_BC_LE) != 0 ));
+ DEBUG ((DEBUG_INFO, "SPI BIOS CONTROL WPD: %x\n", (BiosControl & B_SPI_CFG_BC_WPD) != 0 ));
+ DEBUG ((DEBUG_INFO, "SPI BIOS CONTROL EISS: %x\n", (BiosControl & B_SPI_CFG_BC_EISS) != 0 ));
+
+ return (((BiosControl & B_SPI_CFG_BC_LE) != 0) &&
+ ((BiosControl & B_SPI_CFG_BC_WPD) == 0) &&
+ ((BiosControl & B_SPI_CFG_BC_EISS) != 0));
+}
+
+/**
+ Returns status of BIOS Interface Lockdown
+
+ @retval TRUE BIOS Interface Lockdown is enabled
+ @retval FALSE BIOS Interface Lockdown is disabled
+**/
+BOOLEAN
+SpiIsBiosInterfaceLockdownEnabled (
+ VOID
+ )
+{
+ return !!(PciSegmentRead32 (SpiPciCfgBase () + R_SPI_CFG_BC) & B_SPI_CFG_BC_BILD);
+}
+
+/**
+ Returns Flash Descriptor Override Pin Strap status
+
+ @retval TRUE Flash Descriptor override is enabled
+ @retval FALSE Flash Descriptor override is disabled
+**/
+BOOLEAN
+SpiIsFlashDescriptorOverrideEnabled (
+ VOID
+ )
+{
+ UINT32 SpiBar0;
+ SpiBar0 = SpiGetBar0 ();
+
+ return !!(MmioRead16 (SpiBar0 + R_SPI_MEM_HSFSC) & B_SPI_MEM_HSFSC_FDOPSS);
+}
+
+/**
+ Returns Flash Configuration Lock Down bit status
+
+ @retval TRUE Flash Configuration Lock Down bit is set
+ @retval FALSE Flash Configuration Lock Down bit is not set
+**/
+BOOLEAN
+SpiIsFlashConfigurationLockDownEnabled (
+ VOID
+ )
+{
+ UINT32 SpiBar0;
+ SpiBar0 = SpiGetBar0 ();
+
+ return !!(MmioRead16 (SpiBar0 + R_SPI_MEM_HSFSC) & B_SPI_MEM_HSFSC_FLOCKDN);
+}
+
+/**
+ Returns Top Swap functionality enable state
+
+ @retval TRUE Top Swap is enabled
+ @retval FALSE Top Swap is disabled
+**/
+BOOLEAN
+SpiIsTopSwapEnabled (
+ VOID
+ )
+{
+ return !!(PciSegmentRead32 (SpiPciCfgBase () + R_SPI_CFG_BC) & B_SPI_CFG_BC_TSS);
+}
+
+/**
+ Return Component Property Parameter Table for a given component number
+
+ @param[in] ComponentNumber SPI Component number
+ @param[out] CppTable Component Poperty Parameter Table value
+
+ @retval TRUE Vendor Specific Component Capabilities Register value was read
+ @reval FALSE Vendor Specific Component Capabilities Register value was not present
+**/
+BOOLEAN
+SpiGetComponentPropertyParameterTable (
+ IN UINT8 ComponentNumber,
+ OUT UINT32 *CppTable
+ )
+{
+ UINT32 SpiBar0;
+ UINT32 Data32;
+ SpiBar0 = SpiGetBar0 ();
+
+ //
+ // More than 2 components not supported
+ //
+ switch (ComponentNumber) {
+ case 0:
+ *CppTable = MmioRead32 (SpiBar0 + R_SPI_MEM_SFDP0_VSCC0);
+ return TRUE;
+ case 1:
+ Data32 = SpiReadDescriptor (V_SPI_MEM_FDOC_FDSS_FSDM, R_FLASH_FDBAR_FLASH_MAP0);
+ *CppTable = MmioRead32 (SpiBar0 + R_SPI_MEM_SFDP1_VSCC1);
+ return !!(Data32 & BIT8);
+ default:
+ return FALSE;
+ }
+}
+
+/**
+ Returns valid bit status in given Component Property Parameter Table
+
+ @param[in] CppTable Component Poperty Parameter Table value
+
+ @retval TRUE Valid bit is set
+ @reval FALSE Valid bit is not set
+**/
+BOOLEAN
+SpiIsCppValidBitSet (
+ IN UINT32 CppTable
+ )
+{
+ return !!(CppTable & B_SPI_MEM_SFDPX_VSCCX_CPPTV);
+}
+
+/**
+ Checks if Flash Descriptor is valid
+
+ @retval TRUE Flash Descriptor is valid
+ @retval FALSE Flash Descriptor is invalid
+**/
+BOOLEAN
+SpiIsFlashDescriptorValid (
+ VOID
+ )
+{
+ UINT32 SpiBar0;
+ SpiBar0 = SpiGetBar0 ();
+
+ return !!(MmioRead32 (SpiBar0 + R_SPI_MEM_HSFSC) & B_SPI_MEM_HSFSC_FDV);
+}
+
+/**
+ Reads and returns value from Flash Region Access Permissions Register (FRAP)
+
+ @retval UINT32 Flash Region Access Permissions Register value
+**/
+STATIC
+UINT32
+SpiGetFlashRegionAccessPermissions (
+ VOID
+ )
+{
+ return MmioRead32 (SpiGetBar0 () + R_SPI_MEM_FRAP);
+}
+
+/**
+ Returns masked BIOS Master Read Access
+
+ @retval UINT32 Already masked BIOS Master Read Access
+**/
+UINT32
+SpiGetMasterReadAccess (
+ VOID
+ )
+{
+ UINT32 Data32;
+ Data32 = SpiGetFlashRegionAccessPermissions () & B_SPI_MEM_FRAP_BMRAG_MASK;
+ DEBUG ((DEBUG_INFO, "BMRAG 0x%x\n", Data32));
+
+ return Data32;
+}
+
+/**
+ Returns masked BIOS Master Write Access
+
+ @retval UINT32 Already masked BIOS Master Write Access
+**/
+UINT32
+SpiGetMasterWriteAccess (
+ VOID
+ )
+{
+ UINT32 Data32;
+ Data32 = SpiGetFlashRegionAccessPermissions () & B_SPI_MEM_FRAP_BMWAG_MASK;
+ DEBUG ((DEBUG_INFO, "BMWAG 0x%x\n", Data32));
+
+ return Data32;
+}
+
+/**
+ Returns GbE Region Access rights
+
+ @retval UINT32 GbE Region access rights
+**/
+UINT32
+SpiGetGbeRegionAccess (
+ VOID
+ )
+{
+ UINT32 Data32;
+
+ Data32 = SpiReadDescriptor (V_SPI_MEM_FDOC_FDSS_MSTR, 0x8);
+ DEBUG ((DEBUG_INFO, "GbE Region Access 0x%x\n", Data32));
+
+ return Data32;
+}
+
+/**
+ Returns CSME region access rights
+
+ @retval UINT32 CSME Region Access rights
+**/
+UINT32
+SpiGetCsmeRegionAccess (
+ VOID
+ )
+{
+ UINT32 Data32;
+
+ Data32 = SpiReadDescriptor (V_SPI_MEM_FDOC_FDSS_MSTR, 0x4);
+ DEBUG ((DEBUG_INFO, "CSME Region Access 0x%x\n", Data32));
+
+ return Data32;
+}
+
+/**
+ Returns EC region access right
+
+ @retval UINT32 EC Region access rights
+**/
+UINT32
+SpiGetEcRegionAccess (
+ VOID
+ )
+{
+ UINT32 Data32;
+
+ Data32 = SpiReadDescriptor (V_SPI_MEM_FDOC_FDSS_MSTR, 0x10);
+ DEBUG ((DEBUG_INFO, "EC Region Access 0x%x\n", Data32));
+
+ return Data32;
+}
+
+/**
+ Checks if Slave Attached Flash (SAF) mode is active
+
+ @retval TRUE SAF mode is active
+ @retval FALSE SAF mode is not active
+**/
+BOOLEAN
+SpiIsSafModeActive (
+ VOID
+ )
+{
+ UINT32 SpiBar0;
+ SpiBar0 = SpiGetBar0 ();
+
+ return !!(MmioRead32 (SpiBar0 + R_SPI_MEM_HSFSC) & B_SPI_MEM_HSFSC_SAF_MODE_ACTIVE);
+}
+
+/**
+ Checks validity of GbE region
+
+ @retval TRUE GbE region is valid
+ @retval FALSE GbE regios in invalid
+**/
+BOOLEAN
+SpiIsGbeRegionValid (
+ VOID
+ )
+{
+ UINT32 SpiBar0;
+ SpiBar0 = SpiGetBar0 ();
+
+ if (MmioRead32 (SpiBar0 + R_SPI_MEM_FREG3_GBE) != B_SPI_MEM_FREGX_BASE_MASK) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ Returns TRUE if BIOS Boot Strap is set to SPI
+
+ @retval TRUE BIOS Boot strap is set to SPI
+ @retval FALSE BIOS Boot strap is set to LPC/eSPI
+**/
+BOOLEAN
+SpiIsBiosBootFromSpi (
+ VOID
+ )
+{
+ return !!(((PciSegmentRead8 (SpiPciCfgBase () + R_SPI_CFG_BC) & B_SPI_CFG_BC_BBS) >> N_SPI_CFG_BC_BBS) == V_SPI_CFG_BC_BBS_SPI);
+}
+
+/**
+ Check SPI write status disable is set
+
+ @retval TRUE Write status disable is set
+ @retval FALSE Write status disable is not set
+**/
+BOOLEAN
+SpiIsWriteStatusDisable (
+ VOID
+ )
+{
+ return !!(MmioRead32 (SpiGetBar0 () + R_SPI_MEM_HSFSC) & B_SPI_MEM_HSFSC_WRSDIS);
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/LibraryPrivate/BaseSpiCommonLib/BaseSpiCommonLib.inf b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/LibraryPrivate/BaseSpiCommonLib/BaseSpiCommonLib.inf
new file mode 100644
index 0000000000..a1a5467745
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/LibraryPrivate/BaseSpiCommonLib/BaseSpiCommonLib.inf
@@ -0,0 +1,31 @@
+## @file
+# Component description file for the PchSpiCommonLib
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = BaseSpiCommonLib
+ FILE_GUID = A37CB67E-7D85-45B3-B07E-BF65BDB603E8
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = SpiCommonLib
+
+[Sources]
+ SpiCommon.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ TigerlakeSiliconPkg/SiPkg.dec
+
+[LibraryClasses]
+ IoLib
+ DebugLib
+ PmcLib
+ PchPciBdfLib
+ SpiAccessLib
+
+[Pcd]
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/LibraryPrivate/BaseSpiCommonLib/SpiCommon.c b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/LibraryPrivate/BaseSpiCommonLib/SpiCommon.c
new file mode 100644
index 0000000000..954b349e7c
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/LibraryPrivate/BaseSpiCommonLib/SpiCommon.c
@@ -0,0 +1,1115 @@
+/** @file
+ PCH SPI Common Driver implements the SPI Host Controller Compatibility Interface.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include <Uefi/UefiBaseType.h>
+#include <Library/BaseLib.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <IndustryStandard/Pci30.h>
+#include <Library/PmcLib.h>
+#include <Library/PciSegmentLib.h>
+#include <Protocol/Spi.h>
+#include <Library/SpiCommonLib.h>
+#include <Register/PchRegs.h>
+#include <Register/SpiRegs.h>
+#include <Register/FlashRegs.h>
+#include <Register/PmcRegs.h>
+#include <Library/PchPciBdfLib.h>
+#include <Library/SpiAccessLib.h>
+
+/**
+ Initialize an SPI protocol instance.
+
+ @param[in] SpiInstance Pointer to SpiInstance to initialize
+
+ @retval EFI_SUCCESS The protocol instance was properly initialized
+ @exception EFI_UNSUPPORTED The PCH is not supported by this module
+**/
+EFI_STATUS
+SpiProtocolConstructor (
+ IN SPI_INSTANCE *SpiInstance
+ )
+{
+ UINTN PchSpiBar0;
+ UINT32 Data32;
+ UINT16 Mdtba;
+ EFI_STATUS Status;
+
+ //
+ // Initialize the SPI protocol instance
+ //
+ SpiInstance->Signature = PCH_SPI_PRIVATE_DATA_SIGNATURE;
+ SpiInstance->Handle = NULL;
+ SpiInstance->SpiProtocol.Revision = PCH_SPI_SERVICES_REVISION;
+ SpiInstance->SpiProtocol.FlashRead = SpiProtocolFlashRead;
+ SpiInstance->SpiProtocol.FlashWrite = SpiProtocolFlashWrite;
+ SpiInstance->SpiProtocol.FlashErase = SpiProtocolFlashErase;
+ SpiInstance->SpiProtocol.FlashReadSfdp = SpiProtocolFlashReadSfdp;
+ SpiInstance->SpiProtocol.FlashReadJedecId = SpiProtocolFlashReadJedecId;
+ SpiInstance->SpiProtocol.FlashWriteStatus = SpiProtocolFlashWriteStatus;
+ SpiInstance->SpiProtocol.FlashReadStatus = SpiProtocolFlashReadStatus;
+ SpiInstance->SpiProtocol.GetRegionAddress = SpiProtocolGetRegionAddress;
+ SpiInstance->SpiProtocol.ReadPchSoftStrap = SpiProtocolReadPchSoftStrap;
+ SpiInstance->SpiProtocol.ReadCpuSoftStrap = SpiProtocolReadCpuSoftStrap;
+
+ SpiInstance->PchSpiBase = SpiPciCfgBase ();
+
+ SpiInstance->PchAcpiBase = PmcGetAcpiBase ();
+ ASSERT (SpiInstance->PchAcpiBase != 0);
+
+ PchSpiBar0 = PciSegmentRead32 (SpiInstance->PchSpiBase + R_SPI_CFG_BAR0) & ~(B_SPI_CFG_BAR0_MASK);
+ if (PchSpiBar0 == 0) {
+ DEBUG ((DEBUG_ERROR, "ERROR : PchSpiBar0 is invalid!\n"));
+ ASSERT (FALSE);
+ }
+
+ if ((MmioRead32 (PchSpiBar0 + R_SPI_MEM_HSFSC) & B_SPI_MEM_HSFSC_FDV) == 0) {
+ DEBUG ((DEBUG_ERROR, "ERROR : SPI Flash Signature invalid, cannot use the Hardware Sequencing registers!\n"));
+ ASSERT (FALSE);
+ }
+
+ //
+ // Get Region 0 - 7 read Permission bits, region 8 and above are not permitted.
+ //
+ SpiInstance->ReadPermission = MmioRead8 (PchSpiBar0 + R_SPI_MEM_FRAP) & B_SPI_MEM_FRAP_BRRA_MASK;
+ DEBUG ((DEBUG_INFO, "Flash Region read Permission : %0x\n", SpiInstance->ReadPermission));
+ //
+ // Get Region 0 - 7 write Permission bits, region 8 and above are not permitted.
+ //
+ SpiInstance->WritePermission = (UINT8) ((MmioRead16 (PchSpiBar0 + R_SPI_MEM_FRAP) &
+ B_SPI_MEM_FRAP_BRWA_MASK) >> N_SPI_MEM_FRAP_BRWA);
+ DEBUG ((DEBUG_INFO, "Flash Region write Permission : %0x\n", SpiInstance->WritePermission));
+
+ SpiInstance->SfdpVscc0Value = MmioRead32 (PchSpiBar0 + R_SPI_MEM_SFDP0_VSCC0);
+ DEBUG ((DEBUG_INFO, "Component 0 SFDP VSCC value : %0x\n", SpiInstance->SfdpVscc0Value));
+ SpiInstance->SfdpVscc1Value = MmioRead32 (PchSpiBar0 + R_SPI_MEM_SFDP1_VSCC1);
+ DEBUG ((DEBUG_INFO, "Component 1 SFDP VSCC value : %0x\n", SpiInstance->SfdpVscc1Value));
+
+ //
+ // Select to Flash Map 0 Register to get the number of flash Component
+ //
+ MmioAndThenOr32 (
+ PchSpiBar0 + R_SPI_MEM_FDOC,
+ (UINT32) (~(B_SPI_MEM_FDOC_FDSS_MASK | B_SPI_MEM_FDOC_FDSI_MASK)),
+ (UINT32) (V_SPI_MEM_FDOC_FDSS_FSDM | R_FLASH_FDBAR_FLASH_MAP0)
+ );
+
+ //
+ // Copy Zero based Number Of Components
+ //
+ SpiInstance->NumberOfComponents = (UINT8) ((MmioRead16 (PchSpiBar0 + R_SPI_MEM_FDOD) & B_FLASH_FDBAR_NC) >> N_FLASH_FDBAR_NC);
+ DEBUG ((DEBUG_INFO, "Component Number : %0x\n", SpiInstance->NumberOfComponents + 1));
+
+ MmioAndThenOr32 (
+ PchSpiBar0 + R_SPI_MEM_FDOC,
+ (UINT32) (~(B_SPI_MEM_FDOC_FDSS_MASK | B_SPI_MEM_FDOC_FDSI_MASK)),
+ (UINT32) (V_SPI_MEM_FDOC_FDSS_COMP | R_FLASH_FCBA_FLCOMP)
+ );
+
+ //
+ // Copy Component 0 Density
+ //
+ Data32 = MmioRead32 (PchSpiBar0 + R_SPI_MEM_FDOD);
+ if (SpiInstance->NumberOfComponents > 0) {
+ SpiInstance->Component1StartAddr = V_FLASH_FLCOMP_COMP_512KB <<
+ (Data32 & B_FLASH_FLCOMP_COMP0_MASK);
+ DEBUG ((DEBUG_INFO, "Component 1 StartAddr : %0x\n", SpiInstance->Component1StartAddr));
+ SpiInstance->TotalFlashSize = SpiInstance->Component1StartAddr +
+ (V_FLASH_FLCOMP_COMP_512KB <<
+ ((Data32 & B_FLASH_FLCOMP_COMP1_MASK) >>
+ N_FLASH_FLCOMP_COMP1));
+ } else {
+ SpiInstance->TotalFlashSize = V_FLASH_FLCOMP_COMP_512KB <<
+ (Data32 & B_FLASH_FLCOMP_COMP0_MASK);
+ }
+ DEBUG ((DEBUG_INFO, "Total Flash Size : %0x\n", SpiInstance->TotalFlashSize));
+
+ //
+ // Select FLASH_MAP1 to get Flash PCH Strap Base Address
+ //
+ MmioAndThenOr32 (
+ (PchSpiBar0 + R_SPI_MEM_FDOC),
+ (UINT32) (~(B_SPI_MEM_FDOC_FDSS_MASK | B_SPI_MEM_FDOC_FDSI_MASK)),
+ (UINT32) (V_SPI_MEM_FDOC_FDSS_FSDM | R_FLASH_FDBAR_FLASH_MAP1)
+ );
+ //
+ // Align FPSBA with address bits for the PCH Strap portion of flash descriptor
+ //
+ Data32 = MmioRead32 (PchSpiBar0 + R_SPI_MEM_FDOD);
+ SpiInstance->PchStrapBaseAddr = (UINT16) (((Data32 & B_FLASH_FDBAR_FPSBA)
+ >> N_FLASH_FDBAR_FPSBA)
+ << N_FLASH_FDBAR_FPSBA_REPR);
+ DEBUG ((DEBUG_INFO, "PchStrapBaseAddr : %0x\n", SpiInstance->PchStrapBaseAddr));
+ ASSERT (SpiInstance->PchStrapBaseAddr != 0);
+ //
+ // PCH Strap Length, [31:24] represents number of Dwords
+ //
+ SpiInstance->PchStrapSize = (UINT16) (((Data32 & B_FLASH_FDBAR_PCHSL)
+ >> N_FLASH_FDBAR_PCHSL)
+ * sizeof (UINT32));
+ DEBUG ((DEBUG_INFO, "PchStrapSize : %0x\n", SpiInstance->PchStrapSize));
+
+ //
+ // Select FLASH_MAP2 to get Flash CPU Strap Base Address
+ //
+ MmioAndThenOr32 (
+ (PchSpiBar0 + R_SPI_MEM_FDOC),
+ (UINT32) (~(B_SPI_MEM_FDOC_FDSS_MASK | B_SPI_MEM_FDOC_FDSI_MASK)),
+ (UINT32) (V_SPI_MEM_FDOC_FDSS_FSDM | R_FLASH_FDBAR_FLASH_MAP2)
+ );
+ //
+ // Align FPSBA with address bits for the CPU Strap portion of flash descriptor
+ //
+ Data32 = MmioRead32 (PchSpiBar0 + R_SPI_MEM_FDOD);
+ //
+ // CPU Strap Length, [23:16] represents number of Dwords
+ //
+ SpiInstance->CpuStrapSize = (UINT16) (((Data32 & B_FLASH_FDBAR_CPUSL)
+ >> N_FLASH_FDBAR_CPUSL)
+ * sizeof (UINT32));
+
+ //
+ // CPU Strap Address [11:2] represent offset from MDTBA
+ //
+ SpiInstance->CpuStrapBaseAddr = (UINT16) ((Data32 & B_FLASH_FDBAR_FCPUSBA) >> N_FLASH_FDBAR_FCPUSBA);
+ ASSERT (SpiInstance->CpuStrapBaseAddr != 0);
+
+ if (SpiInstance->CpuStrapBaseAddr != 0x300) {
+ Status = SpiProtocolFlashRead (&(SpiInstance->SpiProtocol), FlashRegionAll, R_FLASH_UMAP1, sizeof (Data32), (UINT8 *) (&Data32));
+ ASSERT_EFI_ERROR (Status);
+ Mdtba = (UINT16)(((Data32 & B_FLASH_UMAP1_MDTBA) >> N_FLASH_UMAP1_MDTBA) << N_FLASH_UMAP1_MDTBA_REPR);
+ DEBUG ((DEBUG_INFO, "Mdtba : %0x\n", Mdtba));
+ // Add MDTBA offset for final address of CPU Straps
+ SpiInstance->CpuStrapBaseAddr += Mdtba;
+ }
+
+ DEBUG ((DEBUG_INFO, "CpuStrapBaseAddr : %0x\n", SpiInstance->CpuStrapBaseAddr));
+ DEBUG ((DEBUG_INFO, "CpuStrapSize : %0x\n", SpiInstance->CpuStrapSize));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Delay for at least the request number of microseconds for Runtime usage.
+
+ @param[in] ABase Acpi base address
+ @param[in] Microseconds Number of microseconds to delay.
+
+**/
+VOID
+EFIAPI
+PchPmTimerStallRuntimeSafe (
+ IN UINT16 ABase,
+ IN UINTN Microseconds
+ )
+{
+ UINTN Ticks;
+ UINTN Counts;
+ UINTN CurrentTick;
+ UINTN OriginalTick;
+ UINTN RemainingTick;
+
+ if (Microseconds == 0) {
+ return;
+ }
+
+ OriginalTick = IoRead32 ((UINTN) (ABase + R_ACPI_IO_PM1_TMR)) & B_ACPI_IO_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_IO_PM1_TMR_MAX_VAL;
+
+ //
+ // Remaining clocks within one loop
+ //
+ RemainingTick = Ticks % V_ACPI_IO_PM1_TMR_MAX_VAL;
+
+ //
+ // not intend to use TMROF_STS bit of register PM1_STS, because this adds extra
+ // one I/O operation, and maybe generate SMI
+ //
+ while ((Counts != 0) || (RemainingTick > CurrentTick)) {
+ CurrentTick = IoRead32 ((UINTN) (ABase + R_ACPI_IO_PM1_TMR)) & B_ACPI_IO_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;
+ }
+}
+
+/**
+ Wait execution cycle to complete on the SPI interface.
+
+ @param[in] This The SPI protocol instance
+ @param[in] PchSpiBar0 Spi MMIO base address
+ @param[in] ErrorCheck TRUE if the SpiCycle needs to do the error check
+
+ @retval TRUE SPI cycle completed on the interface.
+ @retval FALSE Time out while waiting the SPI cycle to complete.
+ It's not safe to program the next command on the SPI interface.
+**/
+STATIC
+BOOLEAN
+WaitForSpiCycleComplete (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINTN PchSpiBar0,
+ IN BOOLEAN ErrorCheck
+ )
+{
+ UINT64 WaitTicks;
+ UINT64 WaitCount;
+ UINT32 Data32;
+ SPI_INSTANCE *SpiInstance;
+
+ SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
+
+ //
+ // Convert the wait period allowed into to tick count
+ //
+ WaitCount = SPI_WAIT_TIME / SPI_WAIT_PERIOD;
+ //
+ // Wait for the SPI cycle to complete.
+ //
+ for (WaitTicks = 0; WaitTicks < WaitCount; WaitTicks++) {
+ Data32 = MmioRead32 (PchSpiBar0 + R_SPI_MEM_HSFSC);
+ if ((Data32 & B_SPI_MEM_HSFSC_SCIP) == 0) {
+ MmioWrite32 (PchSpiBar0 + R_SPI_MEM_HSFSC, B_SPI_MEM_HSFSC_FCERR | B_SPI_MEM_HSFSC_FDONE);
+ if (((Data32 & B_SPI_MEM_HSFSC_FCERR) != 0) && (ErrorCheck == TRUE)) {
+ return FALSE;
+ } else {
+ return TRUE;
+ }
+ }
+ PchPmTimerStallRuntimeSafe (SpiInstance->PchAcpiBase, SPI_WAIT_PERIOD);
+ }
+ return FALSE;
+}
+
+/**
+ This function sends the programmed SPI command to the slave device.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] SpiRegionType The SPI Region type for flash cycle which is listed in the Descriptor
+ @param[in] FlashCycleType The Flash SPI cycle type list in HSFC (Hardware Sequencing Flash Control Register) register
+ @param[in] Address The Flash Linear Address must fall within a region for which BIOS has access permissions.
+ @param[in] ByteCount Number of bytes in the data portion of the SPI cycle.
+ @param[in,out] Buffer Pointer to caller-allocated buffer containing the dada received or sent during the SPI cycle.
+
+ @retval EFI_SUCCESS SPI command completes successfully.
+ @retval EFI_DEVICE_ERROR Device error, the command aborts abnormally.
+ @retval EFI_ACCESS_DENIED Some unrecognized or blocked command encountered in hardware sequencing mode
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+**/
+STATIC
+EFI_STATUS
+SendSpiCmd (
+ IN PCH_SPI_PROTOCOL *This,
+ IN FLASH_REGION_TYPE FlashRegionType,
+ IN FLASH_CYCLE_TYPE FlashCycleType,
+ IN UINT32 Address,
+ IN UINT32 ByteCount,
+ IN OUT UINT8 *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Index;
+ SPI_INSTANCE *SpiInstance;
+ UINT64 SpiBaseAddress;
+ UINTN PchSpiBar0;
+ UINT32 HardwareSpiAddr;
+ UINT32 FlashRegionSize;
+ UINT32 SpiDataCount;
+ UINT32 FlashCycle;
+ UINT8 BiosCtlSave;
+ UINT32 SmiEnSave;
+ UINT16 ABase;
+ UINT32 HsfstsCtl;
+
+ //
+ // For flash write, there is a requirement that all CPU threads are in SMM
+ // before the flash protection is disabled.
+ //
+ if ((FlashCycleType == FlashCycleWrite) || (FlashCycleType == FlashCycleErase)) {
+ if (!IsSpiFlashWriteGranted ()) {
+ return EFI_ACCESS_DENIED;
+ }
+ }
+
+ Status = EFI_SUCCESS;
+ SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
+ SpiBaseAddress = SpiInstance->PchSpiBase;
+ PchSpiBar0 = AcquireSpiBar0 (SpiInstance);
+ ABase = SpiInstance->PchAcpiBase;
+
+ //
+ // Disable SMIs to make sure normal mode flash access is not interrupted by an SMI
+ // whose SMI handler accesses flash (e.g. for error logging)
+ //
+ // *** NOTE: if the SMI_LOCK bit is set (i.e., PMC PCI Offset A0h [4]='1'),
+ // clearing B_GBL_SMI_EN will not have effect. In this situation, some other
+ // synchronization methods must be applied here or in the consumer of the
+ // SendSpiCmd. An example method is disabling the specific SMI sources
+ // whose SMI handlers access flash before flash cycle and re-enabling the SMI
+ // sources after the flash cycle .
+ //
+ SmiEnSave = IoRead32 ((UINTN) (ABase + R_ACPI_IO_SMI_EN));
+ IoWrite32 ((UINTN) (ABase + R_ACPI_IO_SMI_EN), SmiEnSave & (UINT32) (~B_ACPI_IO_SMI_EN_GBL_SMI));
+ BiosCtlSave = PciSegmentRead8 (SpiBaseAddress + R_SPI_CFG_BC) & B_SPI_CFG_BC_SRC;
+
+ //
+ // If it's write cycle, disable Prefetching, Caching and disable BIOS Write Protect
+ //
+ if ((FlashCycleType == FlashCycleWrite) ||
+ (FlashCycleType == FlashCycleErase)) {
+ Status = DisableBiosWriteProtect ();
+ if (EFI_ERROR (Status)) {
+ goto SendSpiCmdEnd;
+ }
+ PciSegmentAndThenOr8 (
+ SpiBaseAddress + R_SPI_CFG_BC,
+ (UINT8) (~B_SPI_CFG_BC_SRC),
+ (UINT8) (V_SPI_CFG_BC_SRC_PREF_DIS_CACHE_DIS << N_SPI_CFG_BC_SRC)
+ );
+ }
+ //
+ // Make sure it's safe to program the command.
+ //
+ if (!WaitForSpiCycleComplete (This, PchSpiBar0, FALSE)) {
+ Status = EFI_DEVICE_ERROR;
+ goto SendSpiCmdEnd;
+ }
+
+ //
+ // Check if Write Status isn't disabled in HW Sequencing
+ //
+ if (FlashCycleType == FlashCycleWriteStatus) {
+ HsfstsCtl = MmioRead32 (PchSpiBar0 + R_SPI_MEM_HSFSC);
+ if ((HsfstsCtl & B_SPI_MEM_HSFSC_WRSDIS) != 0) {
+ Status = EFI_ACCESS_DENIED;
+ goto SendSpiCmdEnd;
+ }
+ }
+
+ Status = SpiProtocolGetRegionAddress (This, FlashRegionType, &HardwareSpiAddr, &FlashRegionSize);
+ if (EFI_ERROR (Status)) {
+ goto SendSpiCmdEnd;
+ }
+ HardwareSpiAddr += Address;
+ if ((Address + ByteCount) > FlashRegionSize) {
+ Status = EFI_INVALID_PARAMETER;
+ goto SendSpiCmdEnd;
+ }
+
+ //
+ // Check for PCH SPI hardware sequencing required commands
+ //
+ FlashCycle = 0;
+ switch (FlashCycleType) {
+ case FlashCycleRead:
+ FlashCycle = (UINT32) (V_SPI_MEM_HSFSC_CYCLE_READ << N_SPI_MEM_HSFSC_CYCLE);
+ break;
+ case FlashCycleWrite:
+ FlashCycle = (UINT32) (V_SPI_MEM_HSFSC_CYCLE_WRITE << N_SPI_MEM_HSFSC_CYCLE);
+ break;
+ case FlashCycleErase:
+ if (((ByteCount % SIZE_4KB) != 0) ||
+ ((HardwareSpiAddr % SIZE_4KB) != 0)) {
+ ASSERT (FALSE);
+ Status = EFI_INVALID_PARAMETER;
+ goto SendSpiCmdEnd;
+ }
+ break;
+ case FlashCycleReadSfdp:
+ FlashCycle = (UINT32) (V_SPI_MEM_HSFSC_CYCLE_READ_SFDP << N_SPI_MEM_HSFSC_CYCLE);
+ break;
+ case FlashCycleReadJedecId:
+ FlashCycle = (UINT32) (V_SPI_MEM_HSFSC_CYCLE_READ_JEDEC_ID << N_SPI_MEM_HSFSC_CYCLE);
+ break;
+ case FlashCycleWriteStatus:
+ FlashCycle = (UINT32) (V_SPI_MEM_HSFSC_CYCLE_WRITE_STATUS << N_SPI_MEM_HSFSC_CYCLE);
+ break;
+ case FlashCycleReadStatus:
+ FlashCycle = (UINT32) (V_SPI_MEM_HSFSC_CYCLE_READ_STATUS << N_SPI_MEM_HSFSC_CYCLE);
+ break;
+ default:
+ //
+ // Unrecognized Operation
+ //
+ ASSERT (FALSE);
+ Status = EFI_INVALID_PARAMETER;
+ goto SendSpiCmdEnd;
+ break;
+ }
+
+ do {
+ SpiDataCount = ByteCount;
+ if ((FlashCycleType == FlashCycleRead) ||
+ (FlashCycleType == FlashCycleWrite) ||
+ (FlashCycleType == FlashCycleReadSfdp)) {
+ //
+ // Trim at 256 byte boundary per operation,
+ // - PCH SPI controller requires trimming at 4KB boundary
+ // - Some SPI chips require trimming at 256 byte boundary for write operation
+ // - Trimming has limited performance impact as we can read / write atmost 64 byte
+ // per operation
+ //
+ if (HardwareSpiAddr + ByteCount > ((HardwareSpiAddr + BIT8) &~(BIT8 - 1))) {
+ SpiDataCount = (((UINT32) (HardwareSpiAddr) + BIT8) &~(BIT8 - 1)) - (UINT32) (HardwareSpiAddr);
+ }
+ //
+ // Calculate the number of bytes to shift in/out during the SPI data cycle.
+ // Valid settings for the number of bytes duing each data portion of the
+ // PCH SPI cycles are: 0, 1, 2, 3, 4, 5, 6, 7, 8, 16, 24, 32, 40, 48, 56, 64
+ //
+ if (SpiDataCount >= 64) {
+ SpiDataCount = 64;
+ } else if ((SpiDataCount &~0x07) != 0) {
+ SpiDataCount = SpiDataCount &~0x07;
+ }
+ }
+ if (FlashCycleType == FlashCycleErase) {
+ if (((ByteCount / SIZE_64KB) != 0) &&
+ ((ByteCount % SIZE_64KB) == 0) &&
+ ((HardwareSpiAddr % SIZE_64KB) == 0)) {
+ if ((SpiInstance->NumberOfComponents == 0) ||
+ (HardwareSpiAddr < SpiInstance->Component1StartAddr)) {
+ //
+ // Check whether Component0 support 64k Erase
+ //
+ if ((SpiInstance->SfdpVscc0Value & B_SPI_MEM_SFDPX_VSCCX_EO_64K) != 0) {
+ SpiDataCount = SIZE_64KB;
+ } else {
+ SpiDataCount = SIZE_4KB;
+ }
+ } else {
+ //
+ // Check whether Component1 support 64k Erase
+ //
+ if ((SpiInstance->SfdpVscc1Value & B_SPI_MEM_SFDPX_VSCCX_EO_64K) != 0) {
+ SpiDataCount = SIZE_64KB;
+ } else {
+ SpiDataCount = SIZE_4KB;
+ }
+ }
+ } else {
+ SpiDataCount = SIZE_4KB;
+ }
+ if (SpiDataCount == SIZE_4KB) {
+ FlashCycle = (UINT32) (V_SPI_MEM_HSFSC_CYCLE_4K_ERASE << N_SPI_MEM_HSFSC_CYCLE);
+ } else {
+ FlashCycle = (UINT32) (V_SPI_MEM_HSFSC_CYCLE_64K_ERASE << N_SPI_MEM_HSFSC_CYCLE);
+ }
+ }
+ //
+ // If it's write cycle, load data into the SPI data buffer.
+ //
+ if ((FlashCycleType == FlashCycleWrite) || (FlashCycleType == FlashCycleWriteStatus)) {
+ if ((SpiDataCount & 0x07) != 0) {
+ //
+ // Use Byte write if Data Count is 0, 1, 2, 3, 4, 5, 6, 7
+ //
+ for (Index = 0; Index < SpiDataCount; Index++) {
+ MmioWrite8 (PchSpiBar0 + R_SPI_MEM_FDATA00 + Index, Buffer[Index]);
+ }
+ } else {
+ //
+ // Use Dword write if Data Count is 8, 16, 24, 32, 40, 48, 56, 64
+ //
+ for (Index = 0; Index < SpiDataCount; Index += sizeof (UINT32)) {
+ MmioWrite32 (PchSpiBar0 + R_SPI_MEM_FDATA00 + Index, *(UINT32 *) (Buffer + Index));
+ }
+ }
+ }
+
+ //
+ // Set the Flash Address
+ //
+ MmioWrite32 (
+ (PchSpiBar0 + R_SPI_MEM_FADDR),
+ (UINT32) (HardwareSpiAddr & B_SPI_MEM_FADDR_MASK)
+ );
+
+ //
+ // Set Data count, Flash cycle, and Set Go bit to start a cycle
+ //
+ MmioAndThenOr32 (
+ PchSpiBar0 + R_SPI_MEM_HSFSC,
+ (UINT32) (~(B_SPI_MEM_HSFSC_FDBC_MASK | B_SPI_MEM_HSFSC_CYCLE_MASK)),
+ (UINT32) ((((SpiDataCount - 1) << N_SPI_MEM_HSFSC_FDBC) & B_SPI_MEM_HSFSC_FDBC_MASK) | FlashCycle | B_SPI_MEM_HSFSC_CYCLE_FGO)
+ );
+ //
+ // end of command execution
+ //
+ // Wait the SPI cycle to complete.
+ //
+ if (!WaitForSpiCycleComplete (This, PchSpiBar0, TRUE)) {
+ ASSERT (FALSE);
+ Status = EFI_DEVICE_ERROR;
+ goto SendSpiCmdEnd;
+ }
+ //
+ // If it's read cycle, load data into the call's buffer.
+ //
+ if ((FlashCycleType == FlashCycleRead) ||
+ (FlashCycleType == FlashCycleReadSfdp) ||
+ (FlashCycleType == FlashCycleReadJedecId) ||
+ (FlashCycleType == FlashCycleReadStatus)) {
+ if ((SpiDataCount & 0x07) != 0) {
+ //
+ // Use Byte read if Data Count is 0, 1, 2, 3, 4, 5, 6, 7
+ //
+ for (Index = 0; Index < SpiDataCount; Index++) {
+ Buffer[Index] = MmioRead8 (PchSpiBar0 + R_SPI_MEM_FDATA00 + Index);
+ }
+ } else {
+ //
+ // Use Dword read if Data Count is 8, 16, 24, 32, 40, 48, 56, 64
+ //
+ for (Index = 0; Index < SpiDataCount; Index += sizeof (UINT32)) {
+ *(UINT32 *) (Buffer + Index) = MmioRead32 (PchSpiBar0 + R_SPI_MEM_FDATA00 + Index);
+ }
+ }
+ }
+
+ HardwareSpiAddr += SpiDataCount;
+ Buffer += SpiDataCount;
+ ByteCount -= SpiDataCount;
+ } while (ByteCount > 0);
+
+SendSpiCmdEnd:
+ //
+ // Restore the settings for SPI Prefetching and Caching and enable BIOS Write Protect
+ //
+ if ((FlashCycleType == FlashCycleWrite) ||
+ (FlashCycleType == FlashCycleErase)) {
+ EnableBiosWriteProtect ();
+ PciSegmentAndThenOr8 (
+ SpiBaseAddress + R_SPI_CFG_BC,
+ (UINT8) ~B_SPI_CFG_BC_SRC,
+ BiosCtlSave
+ );
+ }
+ //
+ // Restore SMIs.
+ //
+ IoWrite32 ((UINTN) (ABase + R_ACPI_IO_SMI_EN), SmiEnSave);
+
+ ReleaseSpiBar0 (SpiInstance);
+
+ return Status;
+}
+
+/**
+ Read data from the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] FlashRegionType The Flash Region type for flash cycle which is listed in the Descriptor.
+ @param[in] Address The Flash Linear Address must fall within a region for which BIOS has access permissions.
+ @param[in] ByteCount Number of bytes in the data portion of the SPI cycle.
+ @param[out] Buffer The Pointer to caller-allocated buffer containing the dada received.
+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashRead (
+ IN PCH_SPI_PROTOCOL *This,
+ IN FLASH_REGION_TYPE FlashRegionType,
+ IN UINT32 Address,
+ IN UINT32 ByteCount,
+ OUT UINT8 *Buffer
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Sends the command to the SPI interface to execute.
+ //
+ Status = SendSpiCmd (
+ This,
+ FlashRegionType,
+ FlashCycleRead,
+ Address,
+ ByteCount,
+ Buffer
+ );
+ return Status;
+}
+
+/**
+ Write data to the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] FlashRegionType The Flash Region type for flash cycle which is listed in the Descriptor.
+ @param[in] Address The Flash Linear Address must fall within a region for which BIOS has access permissions.
+ @param[in] ByteCount Number of bytes in the data portion of the SPI cycle.
+ @param[in] Buffer Pointer to caller-allocated buffer containing the data sent during the SPI cycle.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashWrite (
+ IN PCH_SPI_PROTOCOL *This,
+ IN FLASH_REGION_TYPE FlashRegionType,
+ IN UINT32 Address,
+ IN UINT32 ByteCount,
+ IN UINT8 *Buffer
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Sends the command to the SPI interface to execute.
+ //
+ Status = SendSpiCmd (
+ This,
+ FlashRegionType,
+ FlashCycleWrite,
+ Address,
+ ByteCount,
+ Buffer
+ );
+ return Status;
+}
+
+/**
+ Erase some area on the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] FlashRegionType The Flash Region type for flash cycle which is listed in the Descriptor.
+ @param[in] Address The Flash Linear Address must fall within a region for which BIOS has access permissions.
+ @param[in] ByteCount Number of bytes in the data portion of the SPI cycle.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashErase (
+ IN PCH_SPI_PROTOCOL *This,
+ IN FLASH_REGION_TYPE FlashRegionType,
+ IN UINT32 Address,
+ IN UINT32 ByteCount
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Sends the command to the SPI interface to execute.
+ //
+ Status = SendSpiCmd (
+ This,
+ FlashRegionType,
+ FlashCycleErase,
+ Address,
+ ByteCount,
+ NULL
+ );
+ return Status;
+}
+
+/**
+ Read SFDP data from the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] ComponentNumber The Componen Number for chip select
+ @param[in] Address The starting byte address for SFDP data read.
+ @param[in] ByteCount Number of bytes in SFDP data portion of the SPI cycle
+ @param[out] SfdpData The Pointer to caller-allocated buffer containing the SFDP data received
+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+ @retval EFI_UNSUPPORTED Unsupported operation with SAF Mode enabled
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashReadSfdp (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT8 ComponentNumber,
+ IN UINT32 Address,
+ IN UINT32 ByteCount,
+ OUT UINT8 *SfdpData
+ )
+{
+ SPI_INSTANCE *SpiInstance;
+ EFI_STATUS Status;
+ UINT32 FlashAddress;
+
+ if (SpiIsSafModeActive ()) {
+ DEBUG ((DEBUG_ERROR, "Unallowed call to %a while SAF Mode is active.\n", __FUNCTION__));
+ return EFI_UNSUPPORTED;
+ }
+
+ SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
+ Status = EFI_SUCCESS;
+
+ if (ComponentNumber > SpiInstance->NumberOfComponents) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ FlashAddress = 0;
+ if (ComponentNumber == FlashComponent1) {
+ FlashAddress = SpiInstance->Component1StartAddr;
+ }
+ FlashAddress += Address;
+ //
+ // Sends the command to the SPI interface to execute.
+ //
+ Status = SendSpiCmd (
+ This,
+ FlashRegionAll,
+ FlashCycleReadSfdp,
+ FlashAddress,
+ ByteCount,
+ SfdpData
+ );
+ return Status;
+}
+
+/**
+ Read Jedec Id from the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] ComponentNumber The Componen Number for chip select
+ @param[in] ByteCount Number of bytes in JedecId data portion of the SPI cycle, the data size is 3 typically
+ @param[out] JedecId The Pointer to caller-allocated buffer containing JEDEC ID received
+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+ @retval EFI_UNSUPPORTED Unsupported operation with SAF Mode enabled
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashReadJedecId (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT8 ComponentNumber,
+ IN UINT32 ByteCount,
+ OUT UINT8 *JedecId
+ )
+{
+ SPI_INSTANCE *SpiInstance;
+ EFI_STATUS Status;
+ UINT32 Address;
+
+ if (SpiIsSafModeActive ()) {
+ DEBUG ((DEBUG_ERROR, "Unallowed call to %a while SAF Mode is active.\n", __FUNCTION__));
+ return EFI_UNSUPPORTED;
+ }
+
+ SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
+ Status = EFI_SUCCESS;
+
+ if (ComponentNumber > SpiInstance->NumberOfComponents) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Address = 0;
+ if (ComponentNumber == FlashComponent1) {
+ Address = SpiInstance->Component1StartAddr;
+ }
+
+ //
+ // Sends the command to the SPI interface to execute.
+ //
+ Status = SendSpiCmd (
+ This,
+ FlashRegionAll,
+ FlashCycleReadJedecId,
+ Address,
+ ByteCount,
+ JedecId
+ );
+ return Status;
+}
+
+/**
+ Write the status register in the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] ByteCount Number of bytes in Status data portion of the SPI cycle, the data size is 1 typically
+ @param[in] StatusValue The Pointer to caller-allocated buffer containing the value of Status register writing
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+ @retval EFI_UNSUPPORTED Unsupported operation with SAF Mode enabled
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashWriteStatus (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT32 ByteCount,
+ IN UINT8 *StatusValue
+ )
+{
+ EFI_STATUS Status;
+
+ if (SpiIsSafModeActive ()) {
+ DEBUG ((DEBUG_ERROR, "Unallowed call to %a while SAF Mode is active.\n", __FUNCTION__));
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Sends the command to the SPI interface to execute.
+ //
+ Status = SendSpiCmd (
+ This,
+ FlashRegionAll,
+ FlashCycleWriteStatus,
+ 0,
+ ByteCount,
+ StatusValue
+ );
+ return Status;
+}
+
+/**
+ Read status register in the flash part.
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] ByteCount Number of bytes in Status data portion of the SPI cycle, the data size is 1 typically
+ @param[out] StatusValue The Pointer to caller-allocated buffer containing the value of Status register received.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+ @retval EFI_UNSUPPORTED Unsupported operation with SAF Mode enabled
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolFlashReadStatus (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT32 ByteCount,
+ OUT UINT8 *StatusValue
+ )
+{
+ EFI_STATUS Status;
+
+ if (SpiIsSafModeActive ()) {
+ DEBUG ((DEBUG_ERROR, "Unallowed call to %a while SAF Mode is active.\n", __FUNCTION__));
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Sends the command to the SPI interface to execute.
+ //
+ Status = SendSpiCmd (
+ This,
+ FlashRegionAll,
+ FlashCycleReadStatus,
+ 0,
+ ByteCount,
+ StatusValue
+ );
+ return Status;
+}
+
+/**
+ Get the SPI region base and size, based on the enum type
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] FlashRegionType The Flash Region type for for the base address which is listed in the Descriptor.
+ @param[out] BaseAddress The Flash Linear Address for the Region 'n' Base
+ @param[out] RegionSize The size for the Region 'n'
+
+ @retval EFI_SUCCESS Read success
+ @retval EFI_INVALID_PARAMETER Invalid region type given
+ @retval EFI_DEVICE_ERROR The region is not used
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolGetRegionAddress (
+ IN PCH_SPI_PROTOCOL *This,
+ IN FLASH_REGION_TYPE FlashRegionType,
+ OUT UINT32 *BaseAddress,
+ OUT UINT32 *RegionSize
+ )
+{
+ SPI_INSTANCE *SpiInstance;
+ UINTN PchSpiBar0;
+ UINT32 ReadValue;
+
+ SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
+
+ if (FlashRegionType >= FlashRegionMax) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (FlashRegionType == FlashRegionAll) {
+ *BaseAddress = 0;
+ *RegionSize = SpiInstance->TotalFlashSize;
+ return EFI_SUCCESS;
+ }
+
+ PchSpiBar0 = AcquireSpiBar0 (SpiInstance);
+ ReadValue = MmioRead32 (PchSpiBar0 + (R_SPI_MEM_FREG0_FLASHD + (S_SPI_MEM_FREGX * ((UINT32) FlashRegionType))));
+ ReleaseSpiBar0 (SpiInstance);
+
+ //
+ // If the region is not used, the Region Base is 7FFFh and Region Limit is 0000h
+ //
+ if (ReadValue == B_SPI_MEM_FREGX_BASE_MASK) {
+ return EFI_DEVICE_ERROR;
+ }
+ *BaseAddress = ((ReadValue & B_SPI_MEM_FREGX_BASE_MASK) >> N_SPI_MEM_FREGX_BASE) <<
+ N_SPI_MEM_FREGX_BASE_REPR;
+ //
+ // Region limit address Bits[11:0] are assumed to be FFFh
+ //
+ *RegionSize = ((((ReadValue & B_SPI_MEM_FREGX_LIMIT_MASK) >> N_SPI_MEM_FREGX_LIMIT) + 1) <<
+ N_SPI_MEM_FREGX_LIMIT_REPR) - *BaseAddress;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Read PCH Soft Strap Values
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] SoftStrapAddr PCH Soft Strap address offset from FPSBA.
+ @param[in] ByteCount Number of bytes in SoftStrap data portion of the SPI cycle
+ @param[out] SoftStrapValue The Pointer to caller-allocated buffer containing PCH Soft Strap Value.
+ If the value of ByteCount is 0, the data type of SoftStrapValue should be UINT16 and SoftStrapValue will be PCH Soft Strap Length
+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolReadPchSoftStrap (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT32 SoftStrapAddr,
+ IN UINT32 ByteCount,
+ OUT VOID *SoftStrapValue
+ )
+{
+ SPI_INSTANCE *SpiInstance;
+ UINT32 StrapFlashAddr;
+ EFI_STATUS Status;
+
+ SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
+
+ if (ByteCount == 0) {
+ *(UINT16 *) SoftStrapValue = SpiInstance->PchStrapSize;
+ return EFI_SUCCESS;
+ }
+
+ if ((SoftStrapAddr + ByteCount) > (UINT32) SpiInstance->PchStrapSize) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // PCH Strap Flash Address = FPSBA + RamAddr
+ //
+ StrapFlashAddr = SpiInstance->PchStrapBaseAddr + SoftStrapAddr;
+
+ //
+ // Read PCH Soft straps from using execute command
+ //
+ Status = SendSpiCmd (
+ This,
+ FlashRegionDescriptor,
+ FlashCycleRead,
+ StrapFlashAddr,
+ ByteCount,
+ SoftStrapValue
+ );
+ return Status;
+}
+
+/**
+ Read CPU Soft Strap Values
+
+ @param[in] This Pointer to the PCH_SPI_PROTOCOL instance.
+ @param[in] SoftStrapAddr CPU Soft Strap address offset from FCPUSBA.
+ @param[in] ByteCount Number of bytes in SoftStrap data portion of the SPI cycle.
+ @param[out] SoftStrapValue The Pointer to caller-allocated buffer containing CPU Soft Strap Value.
+ If the value of ByteCount is 0, the data type of SoftStrapValue should be UINT16 and SoftStrapValue will be PCH Soft Strap Length
+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
+
+ @retval EFI_SUCCESS Command succeed.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolReadCpuSoftStrap (
+ IN PCH_SPI_PROTOCOL *This,
+ IN UINT32 SoftStrapAddr,
+ IN UINT32 ByteCount,
+ OUT VOID *SoftStrapValue
+ )
+{
+ SPI_INSTANCE *SpiInstance;
+ UINT32 StrapFlashAddr;
+ EFI_STATUS Status;
+
+ SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
+
+ if (ByteCount == 0) {
+ *(UINT16 *) SoftStrapValue = SpiInstance->CpuStrapSize;
+ return EFI_SUCCESS;
+ }
+
+ if ((SoftStrapAddr + ByteCount) > (UINT32) SpiInstance->CpuStrapSize) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // CPU Strap Flash Address = FCPUSBA + RamAddr
+ //
+ StrapFlashAddr = SpiInstance->CpuStrapBaseAddr + SoftStrapAddr;
+
+ //
+ // Read Cpu Soft straps from using execute command
+ //
+ Status = SendSpiCmd (
+ This,
+ FlashRegionDescriptor,
+ FlashCycleRead,
+ StrapFlashAddr,
+ ByteCount,
+ SoftStrapValue
+ );
+ return Status;
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/LibraryPrivate/PeiDxeSmmSpiAccessPrivateLib/PeiDxeSmmSpiAccessPrivateLib.inf b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/LibraryPrivate/PeiDxeSmmSpiAccessPrivateLib/PeiDxeSmmSpiAccessPrivateLib.inf
new file mode 100644
index 0000000000..4e059494d8
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/LibraryPrivate/PeiDxeSmmSpiAccessPrivateLib/PeiDxeSmmSpiAccessPrivateLib.inf
@@ -0,0 +1,40 @@
+## @file
+# Component description file for PCH SPI access private library
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiDxeSmmSpiAccessPrivateLib
+FILE_GUID = 2CD382D7-9928-C32A-601D-69797C618A6D
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = SpiAccessPrivateLib
+
+
+[LibraryClasses]
+BaseLib
+IoLib
+DebugLib
+PciSegmentLib
+SpiAccessLib
+PcdLib
+S3BootScriptLib
+PchPciBdfLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+TigerlakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+SpiAccessPrivateLib.c
+
+
+[Pcd]
+gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/LibraryPrivate/PeiDxeSmmSpiAccessPrivateLib/SpiAccessPrivateLib.c b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/LibraryPrivate/PeiDxeSmmSpiAccessPrivateLib/SpiAccessPrivateLib.c
new file mode 100644
index 0000000000..de1f3d3f86
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/LibraryPrivate/PeiDxeSmmSpiAccessPrivateLib/SpiAccessPrivateLib.c
@@ -0,0 +1,133 @@
+/** @file
+ SPI library for abstraction of SPI HW registers accesses
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/SpiAccessLib.h>
+#include <Library/PciSegmentLib.h>
+#include <Library/DebugLib.h>
+#include <Library/S3BootScriptLib.h>
+#include <Register/SpiRegs.h>
+#include <Register/PchRegs.h>
+#include <Register/PchPcrRegs.h>
+#include <Library/PchPciBdfLib.h>
+
+/**
+ Disable EISS (Enable InSMM.STS)
+**/
+VOID
+SpiDisableEiss (
+ VOID
+ )
+{
+ UINT64 SpiBaseAddress;
+ SpiBaseAddress = SpiPciCfgBase ();
+
+ ASSERT ((PciSegmentRead8 (SpiBaseAddress + R_SPI_CFG_BC) & B_SPI_CFG_BC_LE) == 0);
+
+ PciSegmentAnd8 (SpiBaseAddress + R_SPI_CFG_BC, (UINT8) ~(B_SPI_CFG_BC_EISS));
+}
+
+/**
+ Configure BiosLockEnable bit and BiosInterfaceLock bit according to policy setting.
+
+ @param[in] BiosLockEnable Policy for BiosLockEnable bit programming
+ @param[in] BiosInterfaceLock Policy for BiosInterfaceLock bit programming
+
+**/
+VOID
+SpiBiosLockEnableAndBiosInterfaceLockWithS3BootScript (
+ IN BOOLEAN BiosLockEnable,
+ IN BOOLEAN BiosInterfaceLock
+ )
+{
+ UINT64 SpiBaseAddress;
+ UINT8 SpiData8;
+
+ if (!BiosLockEnable && !BiosInterfaceLock) {
+ return;
+ }
+
+ SpiBaseAddress = SpiPciCfgBase ();
+
+ ///
+ /// PCH BIOS Spec Flash Security Recommendation
+ ///
+ /// BIOS needs to enable the BIOS Lock Enable (BLE) feature of the PCH by setting
+ /// SPI/eSPI/LPC PCI offset DCh[1] = 1b.
+ /// When this bit is set, attempts to write the Write Protect Disable (WPD) bit
+ /// in PCH will cause a SMI which will allow the BIOS to verify that the write is
+ /// from a valid source.
+ /// Remember that BIOS needs to set SPI/LPC/eSPI PCI Offset DC [0] = 0b to enable
+ /// BIOS region protection before exiting the SMI handler.
+ /// Also, TCO_EN bit needs to be set (SMI_EN Register, ABASE + 30h[13] = 1b) to keep
+ /// BLE feature enabled after booting to the OS.
+ /// Intel requires that BIOS enables the Lock Enable (LE) feature of the PCH to
+ /// ensure SMM protection of flash.
+ /// RC installs a default SMI handler that clears WPD.
+ /// There could be additional SMI handler to log such attempt if desired.
+ ///
+ /// BIOS needs to enable the "Enable in SMM.STS" (EISS) feature of the PCH by setting
+ /// SPI PCI offset DCh[5] = 1b for SPI or setting eSPI PCI offset DCh[5] = 1b for eSPI.
+ /// When this bit is set, the BIOS region is not writable until SMM sets the InSMM.STS bit,
+ /// to ensure BIOS can only be modified from SMM. Please refer to CPU BWG for more details
+ /// on InSMM.STS bit.
+ /// Intel requires that BIOS enables the Lock Enable (LE) feature of the PCH to ensure
+ /// SMM protection of flash.
+ /// SPI PCI offset DCh[1] = 1b for SPI or setting eSPI PCI offset DCh[1] = 1b for eSPI.
+ /// When this bit is set, EISS is locked down.
+ ///
+ SpiData8 = 0;
+ if (BiosLockEnable) {
+ SpiData8 |= B_SPI_CFG_BC_EISS | B_SPI_CFG_BC_LE;
+ }
+ ///
+ /// BIOS also needs to set the BIOS Interface Lock Down bit in multiple locations
+ /// (PCR[DMI] + 274Ch[0], LPC/eSPI PCI offset DCh[7] and SPI PCI offset DCh[7]).
+ /// (done in PchInit/Dxe/PchInit.c by PchDmiSetBiosLockDownWithS3BootScript ()) for PCR[DMI] 274Ch)
+ /// Setting these bits will prevent writes to the Top Swap bit (under their respective locations)
+ /// and the Boot BIOS Straps. Enabling this bit will mitigate malicious software
+ /// attempts to replace the system BIOS option ROM with its own code.
+ ///
+ if (BiosInterfaceLock) {
+ SpiData8 |= B_SPI_CFG_BC_BILD;
+ }
+
+ PciSegmentOr8 (SpiBaseAddress + R_SPI_CFG_BC, SpiData8);
+ S3BootScriptSaveMemWrite (
+ S3BootScriptWidthUint8,
+ PcdGet64 (PcdPciExpressBaseAddress) + SpiBaseAddress + R_SPI_CFG_BC,
+ 1,
+ (VOID *) (UINTN) (PcdGet64 (PcdPciExpressBaseAddress) + SpiBaseAddress + R_SPI_CFG_BC)
+ );
+ //
+ // Reads back for posted write to take effect
+ //
+ SpiData8 = PciSegmentRead8 (SpiBaseAddress + R_SPI_CFG_BC);
+ S3BootScriptSaveMemPoll (
+ S3BootScriptWidthUint8,
+ PcdGet64 (PcdPciExpressBaseAddress) + SpiBaseAddress + R_SPI_CFG_BC,
+ &SpiData8,
+ &SpiData8,
+ 1,
+ 1
+ );
+}
+
+/**
+ Clears BIOS Write Protect Disable bit
+**/
+VOID
+SpiClearBiosWriteProtectDisable (
+ VOID
+ )
+{
+ //
+ // Disable BIOSWE bit to protect BIOS
+ //
+ PciSegmentAnd8 (SpiPciCfgBase () + R_SPI_CFG_BC, (UINT8) ~B_SPI_CFG_BC_WPD);
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/Smm/Spi.c b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/Smm/Spi.c
new file mode 100644
index 0000000000..419eddaff3
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/Smm/Spi.c
@@ -0,0 +1,296 @@
+/** @file
+ PCH SPI SMM Driver implements the SPI Host Controller Compatibility Interface.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/SmmServicesTableLib.h>
+#include <Library/PciSegmentLib.h>
+#include <Protocol/Spi.h>
+#include <Protocol/SmmCpu.h>
+#include <Library/SpiCommonLib.h>
+#include <PchReservedResources.h>
+#include <Library/SmmPchPrivateLib.h>
+#include <Library/PchPciBdfLib.h>
+#include <IndustryStandard/Pci30.h>
+#include <Register/PchRegs.h>
+#include <Register/SpiRegs.h>
+
+//
+// Global variables
+//
+GLOBAL_REMOVE_IF_UNREFERENCED SPI_INSTANCE *mSpiInstance;
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_SMM_CPU_PROTOCOL *mSmmCpuProtocol;
+//
+// mPchSpiResvMmioAddr keeps the reserved MMIO range assiged to SPI.
+// In SMM it always set back the reserved MMIO address to SPI BAR0 to ensure the MMIO range
+// won't overlap with SMRAM range, and trusted.
+//
+GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mSpiResvMmioAddr;
+
+/**
+ <b>SPI Runtime SMM Module Entry Point</b>\n
+ - <b>Introduction</b>\n
+ The SPI SMM module provide a standard way for other modules to use the PCH SPI Interface in SMM.
+
+ - @pre
+ - EFI_SMM_BASE2_PROTOCOL
+ - Documented in System Management Mode Core Interface Specification .
+
+ - @result
+ The SPI SMM driver produces @link _PCH_SPI_PROTOCOL PCH_SPI_PROTOCOL @endlink with GUID
+ gPchSmmSpiProtocolGuid which is different from SPI RUNTIME driver.
+
+ - <b>Integration Check List</b>\n
+ - This driver supports Descriptor Mode only.
+ - This driver supports Hardware Sequence only.
+ - When using SMM SPI Protocol to perform flash access in an SMI handler,
+ and the SMI occurrence is asynchronous to normal mode code execution,
+ proper synchronization mechanism must be applied, e.g. disable SMI before
+ the normal mode SendSpiCmd() starts and re-enable SMI after
+ the normal mode SendSpiCmd() completes.
+ @note The implementation of SendSpiCmd() uses GBL_SMI_EN in
+ SMI_EN register (ABase + 30h) to disable and enable SMIs. But this may
+ not be effective as platform may well set the SMI_LOCK bit (i.e., PMC PCI Offset A0h [4]).
+ So the synchronization at caller level is likely needed.
+
+ @param[in] ImageHandle Image handle of this driver.
+ @param[in] SystemTable Global system service table.
+
+ @retval EFI_SUCCESS Initialization complete.
+ @exception EFI_UNSUPPORTED The chipset is unsupported by this driver.
+ @retval EFI_OUT_OF_RESOURCES Do not have enough resources to initialize the driver.
+ @retval EFI_DEVICE_ERROR Device error, driver exits abnormally.
+**/
+EFI_STATUS
+EFIAPI
+InstallPchSpi (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Init PCH spi reserved MMIO address.
+ //
+ mSpiResvMmioAddr = PCH_SPI_BASE_ADDRESS;
+
+ ///
+ /// Allocate pool for SPI protocol instance
+ ///
+ Status = gSmst->SmmAllocatePool (
+ EfiRuntimeServicesData, /// MemoryType don't care
+ sizeof (SPI_INSTANCE),
+ (VOID **) &mSpiInstance
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (mSpiInstance == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ ZeroMem ((VOID *) mSpiInstance, sizeof (SPI_INSTANCE));
+ ///
+ /// Initialize the SPI protocol instance
+ ///
+ Status = SpiProtocolConstructor (mSpiInstance);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ ///
+ /// Install the SMM PCH_SPI_PROTOCOL interface
+ ///
+ Status = gSmst->SmmInstallProtocolInterface (
+ &(mSpiInstance->Handle),
+ &gPchSmmSpiProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &(mSpiInstance->SpiProtocol)
+ );
+ if (EFI_ERROR (Status)) {
+ gSmst->SmmFreePool (mSpiInstance);
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Acquire PCH spi mmio address.
+ If it is ever different from the preallocated address, reassign it back.
+ In SMM, it always override the BAR0 and returns the reserved MMIO range for SPI.
+
+ @param[in] SpiInstance Pointer to SpiInstance to initialize
+
+ @retval PchSpiBar0 return SPI MMIO address
+**/
+UINTN
+AcquireSpiBar0 (
+ IN SPI_INSTANCE *SpiInstance
+ )
+{
+ UINT32 SpiBar0;
+ //
+ // Save original SPI physical MMIO address
+ //
+ SpiBar0 = PciSegmentRead32 (SpiInstance->PchSpiBase + R_SPI_CFG_BAR0) & ~(B_SPI_CFG_BAR0_MASK);
+
+ if (SpiBar0 != mSpiResvMmioAddr) {
+ //
+ // Temporary disable MSE, and override with SPI reserved MMIO address, then enable MSE.
+ //
+ PciSegmentAnd8 (SpiInstance->PchSpiBase + PCI_COMMAND_OFFSET, (UINT8) ~EFI_PCI_COMMAND_MEMORY_SPACE);
+ PciSegmentWrite32 (SpiInstance->PchSpiBase + R_SPI_CFG_BAR0, mSpiResvMmioAddr);
+ PciSegmentOr8 (SpiInstance->PchSpiBase + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_MEMORY_SPACE);
+ }
+ //
+ // SPIBAR0 will be different before and after PCI enum so need to get it from SPI BAR0 reg.
+ //
+ return mSpiResvMmioAddr;
+}
+
+/**
+ Release pch spi mmio address. Do nothing.
+
+ @param[in] SpiInstance Pointer to SpiInstance to initialize
+
+ @retval None
+**/
+VOID
+ReleaseSpiBar0 (
+ IN SPI_INSTANCE *SpiInstance
+ )
+{
+}
+
+/**
+ This function is a hook for Spi to disable BIOS Write Protect
+
+ @retval EFI_SUCCESS The protocol instance was properly initialized
+ @retval EFI_ACCESS_DENIED The BIOS Region can only be updated in SMM phase
+
+**/
+EFI_STATUS
+EFIAPI
+DisableBiosWriteProtect (
+ VOID
+ )
+{
+ UINT64 SpiBaseAddress;
+
+ SpiBaseAddress = SpiPciCfgBase ();
+ // Write clear BC_SYNC_SS prior to change WPD from 0 to 1.
+ //
+ PciSegmentOr8 (
+ SpiBaseAddress + R_SPI_CFG_BC + 1,
+ (B_SPI_CFG_BC_SYNC_SS >> 8)
+ );
+ ///
+ /// Set BIOSWE bit (SPI PCI Offset DCh [0]) = 1b
+ /// Enable the access to the BIOS space for both read and write cycles
+ ///
+ PciSegmentOr8 (
+ SpiBaseAddress + R_SPI_CFG_BC,
+ B_SPI_CFG_BC_WPD
+ );
+
+ ///
+ /// PCH BIOS Spec Section 3.7 BIOS Region SMM Protection Enabling
+ /// If the following steps are implemented:
+ /// - Set the EISS bit (SPI PCI Offset DCh [5]) = 1b
+ /// - Follow the 1st recommendation in section 3.6
+ /// the BIOS Region can only be updated by following the steps bellow:
+ /// - Once all threads enter SMM
+ /// - Read memory location FED30880h OR with 00000001h, place the result in EAX,
+ /// and write data to lower 32 bits of MSR 1FEh (sample code available)
+ /// - Set BIOSWE bit (SPI PCI Offset DCh [0]) = 1b
+ /// - Modify BIOS Region
+ /// - Clear BIOSWE bit (SPI PCI Offset DCh [0]) = 0b
+ ///
+ if ((PciSegmentRead8 (SpiBaseAddress + R_SPI_CFG_BC) & B_SPI_CFG_BC_EISS) != 0) {
+ PchSetInSmmSts ();
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function is a hook for Spi to enable BIOS Write Protect
+**/
+VOID
+EFIAPI
+EnableBiosWriteProtect (
+ VOID
+ )
+{
+ UINT64 SpiBaseAddress;
+
+ SpiBaseAddress = SpiPciCfgBase ();
+ ///
+ /// Clear BIOSWE bit (SPI PCI Offset DCh [0]) = 0b
+ /// Disable the access to the BIOS space for write cycles
+ ///
+ PciSegmentAnd8 (
+ SpiBaseAddress + R_SPI_CFG_BC,
+ (UINT8) (~B_SPI_CFG_BC_WPD)
+ );
+
+ ///
+ /// Check if EISS bit is set
+ ///
+ if (((PciSegmentRead8 (SpiBaseAddress + R_SPI_CFG_BC)) & B_SPI_CFG_BC_EISS) == B_SPI_CFG_BC_EISS) {
+ PchClearInSmmSts ();
+ }
+}
+
+/**
+ Check if it's granted to do flash write.
+
+ @retval TRUE It's secure to do flash write.
+ @retval FALSE It's not secure to do flash write.
+**/
+BOOLEAN
+IsSpiFlashWriteGranted (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINT32 CpuIndex;
+ UINT64 ProcessorId;
+
+ if (mSmmCpuProtocol == NULL) {
+ Status = gSmst->SmmLocateProtocol (&gEfiSmmCpuProtocolGuid, NULL, (VOID **)&mSmmCpuProtocol);
+ ASSERT_EFI_ERROR (Status);
+ if (mSmmCpuProtocol == NULL) {
+ return TRUE;
+ }
+ }
+
+ for (CpuIndex = 0; CpuIndex < gSmst->NumberOfCpus; CpuIndex++) {
+ Status = mSmmCpuProtocol->ReadSaveState (
+ mSmmCpuProtocol,
+ sizeof (ProcessorId),
+ EFI_SMM_SAVE_STATE_REGISTER_PROCESSOR_ID,
+ CpuIndex,
+ &ProcessorId
+ );
+ //
+ // If the processor is in SMM at the time the SMI occurred,
+ // it will return success. Otherwise, EFI_NOT_FOUND is returned.
+ //
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/Smm/SpiSmm.inf b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/Smm/SpiSmm.inf
new file mode 100644
index 0000000000..033134cea1
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Spi/Smm/SpiSmm.inf
@@ -0,0 +1,47 @@
+## @file
+# Component description file for the SPI SMM driver.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = SpiSmm
+FILE_GUID = 27F4917B-A707-4aad-9676-26DF168CBF0D
+VERSION_STRING = 1.0
+MODULE_TYPE = DXE_SMM_DRIVER
+PI_SPECIFICATION_VERSION = 1.10
+ENTRY_POINT = InstallPchSpi
+
+
+[LibraryClasses]
+DebugLib
+IoLib
+UefiDriverEntryPoint
+UefiBootServicesTableLib
+BaseLib
+SmmServicesTableLib
+SpiCommonLib
+SmmPchPrivateLib
+PchPciBdfLib
+
+[Packages]
+MdePkg/MdePkg.dec
+TigerlakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+Spi.c
+
+
+[Protocols]
+gPchSmmSpiProtocolGuid ## PRODUCES
+gEfiSmmCpuProtocolGuid ## CONSUMES
+
+
+[Depex]
+gEfiSmmBase2ProtocolGuid AND # This is for SmmServicesTableLib
+gEfiSmmCpuProtocolGuid # This is for CpuSmmDisableBiosWriteProtect()
--
2.24.0.windows.2
^ permalink raw reply related [flat|nested] 42+ messages in thread
* [Patch V3 30/40] TigerlakeSiliconPkg/IpBlock: Add Vtd component
2021-02-05 7:40 [Patch V3 01/40] TigerlakeSiliconPkg: Add package and Include/ConfigBlock headers Heng Luo
` (27 preceding siblings ...)
2021-02-05 7:40 ` [Patch V3 29/40] TigerlakeSiliconPkg/IpBlock: Add Spi component Heng Luo
@ 2021-02-05 7:40 ` Heng Luo
2021-02-05 7:40 ` [Patch V3 31/40] TigerlakeSiliconPkg/Library: Add package common library instances Heng Luo
` (9 subsequent siblings)
38 siblings, 0 replies; 42+ messages in thread
From: Heng Luo @ 2021-02-05 7:40 UTC (permalink / raw)
To: devel; +Cc: Sai Chaganty, Nate DeSimone
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3171
Adds the following files:
* IpBlock/Vtd/IncludePrivate
* IpBlock/Vtd/Library
* IpBlock/Vtd/LibraryPrivate
Cc: Sai Chaganty <rangasai.v.chaganty@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Signed-off-by: Heng Luo <heng.luo@intel.com>
---
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Vtd/IncludePrivate/Library/DxeVtdInitLib.h | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Vtd/IncludePrivate/Library/DxeVtdPolicyLib.h | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Vtd/IncludePrivate/VtdDataHob.h | 32 ++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Vtd/Library/PeiDxeSmmVtdInfoLib/PeiDxeSmmVtdInfoLib.inf | 45 +++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Vtd/Library/PeiDxeSmmVtdInfoLib/VtdInfoLib.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Vtd/LibraryPrivate/DxeVtdInitLib/DxeVtdInitLib.c | 684 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Vtd/LibraryPrivate/DxeVtdInitLib/DxeVtdInitLib.inf | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Vtd/LibraryPrivate/DxeVtdPolicyLib/DxeVtdPolicyLib.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Vtd/LibraryPrivate/DxeVtdPolicyLib/DxeVtdPolicyLib.inf | 35 +++++++++++++++++++++++++++++++++++
9 files changed, 1172 insertions(+)
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Vtd/IncludePrivate/Library/DxeVtdInitLib.h b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Vtd/IncludePrivate/Library/DxeVtdInitLib.h
new file mode 100644
index 0000000000..e439cfbac2
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Vtd/IncludePrivate/Library/DxeVtdInitLib.h
@@ -0,0 +1,62 @@
+/** @file
+ Header file for DXE VTD Init Lib.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _DXE_VTD_INIT_LIB_H_
+#define _DXE_VTD_INIT_LIB_H_
+
+#include <Uefi.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/UefiLib.h>
+#include <Library/ConfigBlockLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/PchCycleDecodingLib.h>
+#include <Library/PciSegmentLib.h>
+#include <Library/VtdInfoLib.h>
+#include <Library/SaPlatformLib.h>
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/Pci.h>
+#include <VtdDataHob.h>
+#include <PchConfigHob.h>
+#include <PchInfoHob.h>
+#include <Register/P2sbRegs.h>
+#include <Register/IpuRegs.h>
+#include <Register/IgdRegs.h>
+#include <Register/VtdRegs.h>
+#include <DmaRemappingTable.h>
+#include <Protocol/AcpiSystemDescriptionTable.h>
+#include <Protocol/AcpiTable.h>
+#include <Protocol/SaPolicy.h>
+#include <Protocol/SaNvsArea.h>
+#include <Protocol/FirmwareVolume2.h>
+
+/**
+ Locate the VT-d ACPI tables data file and read ACPI SSDT tables.
+ Publish the appropriate SSDT based on current configuration and capabilities.
+
+ @param[in] SaPolicy SA DXE Policy protocol
+
+ @retval EFI_SUCCESS - Vtd initialization complete
+ @retval Other - No Vtd function initiated
+**/
+EFI_STATUS
+VtdInit (
+ IN SA_POLICY_PROTOCOL *SaPolicy
+ );
+
+/**
+ EndOfPcieEnum routine for update DMAR
+**/
+VOID
+UpdateDmarEndOfPcieEnum (
+ VOID
+ );
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Vtd/IncludePrivate/Library/DxeVtdPolicyLib.h b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Vtd/IncludePrivate/Library/DxeVtdPolicyLib.h
new file mode 100644
index 0000000000..d55cf6bc34
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Vtd/IncludePrivate/Library/DxeVtdPolicyLib.h
@@ -0,0 +1,67 @@
+/** @file
+ Prototype of the DXE VTD Policy Init library.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _DXE_VTD_POLICY_INIT_LIB_H_
+#define _DXE_VTD_POLICY_INIT_LIB_H_
+
+#include <Uefi.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Protocol/SaPolicy.h>
+#include <ConfigBlock.h>
+#include <VtdConfig.h>
+#include <Library/SiConfigBlockLib.h>
+
+extern EFI_GUID gVtdDxeConfigGuid;
+
+/**
+ This function Load default Vtd DXE policy.
+
+ @param[in] ConfigBlockPointer The pointer to add VTD config block
+**/
+VOID
+VtdLoadDefaultDxe (
+ IN VOID *ConfigBlockPointer
+ );
+
+/**
+ This function prints the DXE phase VTD policy.
+
+ @param[in] SaPolicy - Instance of SA_POLICY_PROTOCOL
+**/
+VOID
+VtdPrintPolicyDxe (
+ IN SA_POLICY_PROTOCOL *SaPolicy
+ );
+
+/**
+ This function is used to add VTD Config Block.
+
+ @param[in] ConfigBlockTableAddress The pointer to add VTD config blocks
+
+ @retval EFI_SUCCESS The policy default is initialized.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create buffer
+**/
+EFI_STATUS
+EFIAPI
+VtdAddConfigBlocksDxe (
+ IN VOID *ConfigBlockTableAddress
+ );
+
+/**
+ Get VTD DXE config block table total size.
+
+ @retval Size of VTD DXE config block table
+**/
+UINT16
+EFIAPI
+VtdGetConfigBlockTotalSizeDxe (
+ VOID
+ );
+#endif // _DXE_VTD_POLICY_INIT_LIB_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Vtd/IncludePrivate/VtdDataHob.h b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Vtd/IncludePrivate/VtdDataHob.h
new file mode 100644
index 0000000000..0f9d500af9
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Vtd/IncludePrivate/VtdDataHob.h
@@ -0,0 +1,32 @@
+/** @file
+ The GUID definition for Vtd Data Hob
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _VTD_DATA_HOB_H_
+#define _VTD_DATA_HOB_H_
+
+#include <Library/VtdInfoLib.h>
+#include <Base.h>
+
+extern EFI_GUID gVtdDataHobGuid;
+
+#pragma pack (push,1)
+
+///
+/// The data elements should be initialized by a Platform Module.
+/// The data structure is for VT-d driver initialization
+///
+typedef struct {
+ EFI_HOB_GUID_TYPE EfiHobGuidType; ///< GUID Hob type structure for gVtdDataHobGuid
+ BOOLEAN VtdDisable; ///< 1 = Avoids programming Vtd bars, Vtd overrides and DMAR table
+ UINT32 BaseAddress[VTD_ENGINE_NUMBER]; ///< This field is used to describe the base addresses for VT-d function
+ BOOLEAN X2ApicOptOut; ///< This field is used to enable the X2APIC_OPT_OUT bit in the DMAR table. <b>1=Enable/Set</b> and 0=Disable/Clear
+ BOOLEAN DmaControlGuarantee; ///< This field is used to enable the DMA_CONTROL_GUARANTEE bit in the DMAR table. <b>1=Enable/Set</b> and 0=Disable/Clear
+ BOOLEAN InterruptRemappingSupport; ///< This field is used to indicate Interrupt Remapping supported or not
+ UINT32 DmaBufferBase; ///< Iommu PEI DMA buffer base in low memory region, in Mbytes units
+} VTD_DATA_HOB;
+
+#pragma pack (pop)
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Vtd/Library/PeiDxeSmmVtdInfoLib/PeiDxeSmmVtdInfoLib.inf b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Vtd/Library/PeiDxeSmmVtdInfoLib/PeiDxeSmmVtdInfoLib.inf
new file mode 100644
index 0000000000..c7c5e56b84
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Vtd/Library/PeiDxeSmmVtdInfoLib/PeiDxeSmmVtdInfoLib.inf
@@ -0,0 +1,45 @@
+## @file
+# VTD Common Library.
+#
+# All function in this library is available for PEI, DXE, and SMM,
+# But do not support UEFI RUNTIME environment call.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiDxeSmmVtdInfoLib
+FILE_GUID = A1480873-3FDA-4E90-B450-743D8031F9DE
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = VtdInfoLib
+
+[LibraryClasses]
+BaseLib
+IoLib
+DebugLib
+PciSegmentLib
+HobLib
+VtdInfoLib
+
+[Packages]
+MdePkg/MdePkg.dec
+TigerlakeSiliconPkg/SiPkg.dec
+
+[Sources]
+VtdInfoLib.c
+
+[Pcd]
+gSiPkgTokenSpaceGuid.VtdEngine1BaseAddeess
+gSiPkgTokenSpaceGuid.VtdEngine2BaseAddeess
+gSiPkgTokenSpaceGuid.VtdEngine3BaseAddeess
+gSiPkgTokenSpaceGuid.VtdEngine4BaseAddeess
+gSiPkgTokenSpaceGuid.VtdEngine5BaseAddeess
+gSiPkgTokenSpaceGuid.VtdEngine6BaseAddeess
+gSiPkgTokenSpaceGuid.VtdEngine7BaseAddeess
+
+[FixedPcd]
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Vtd/Library/PeiDxeSmmVtdInfoLib/VtdInfoLib.c b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Vtd/Library/PeiDxeSmmVtdInfoLib/VtdInfoLib.c
new file mode 100644
index 0000000000..e4f08592cc
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Vtd/Library/PeiDxeSmmVtdInfoLib/VtdInfoLib.c
@@ -0,0 +1,86 @@
+/** @file
+ VTD Info library.
+ All function in this library is available for PEI, DXE, and SMM,
+ But do not support UEFI RUNTIME environment call.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Ppi/SiPolicy.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/PciSegmentLib.h>
+#include <Library/VtdInfoLib.h>
+#include <Register/VtdRegs.h>
+
+/**
+ Get VTD Engine Base Address from PCD value
+
+ @param[in] VtdEngineNumber - Engine number for which VTD Base Adderess is required.
+
+ @retval VTD Engine Base Address
+**/
+UINT32
+GetVtdBaseAddress (
+ IN UINT8 VtdEngineNumber
+ )
+{
+ switch (VtdEngineNumber) {
+ case 0:
+ return PcdGet32(VtdEngine1BaseAddeess);
+ break;
+ case 2:
+ return PcdGet32(VtdEngine3BaseAddeess);
+ break;
+ default:
+ return 0x0;
+ break;
+ }
+}
+
+
+/**
+ Read VTD Engine Base Address from VTD BAR Offsets.
+
+ @param[in] VtdEngineNumber - Engine number for which VTD Base Adderess is required.
+
+ @retval VTD Engine Base Address
+**/
+UINT32
+ReadVtdBaseAddress (
+ IN UINT8 VtdEngineNumber
+ )
+{
+ UINT64 McD0BaseAddress;
+ UINTN MchBar;
+
+ McD0BaseAddress = PCI_SEGMENT_LIB_ADDRESS (SA_SEG_NUM, SA_MC_BUS, 0, 0, 0);
+ MchBar = PciSegmentRead32 (McD0BaseAddress + R_SA_MCHBAR) & (~BIT0);
+
+ switch (VtdEngineNumber) {
+ case 0:
+ return (MmioRead32 (MchBar + R_MCHBAR_VTD1_OFFSET) & (~BIT0));
+ break;
+ case 2:
+ return (MmioRead32 (MchBar + R_MCHBAR_VTD3_OFFSET) & (~BIT0));
+ break;
+ default:
+ return 0x0;
+ break;
+ }
+}
+
+/**
+ GetMaxVtdEngineNumber: Get Maximum Vtd Engine Number
+
+ @retval Vtd Engine Number
+**/
+UINT8
+GetMaxVtdEngineNumber(
+ VOID
+)
+{
+ return (UINT8)VTD_ENGINE_NUMBER;
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Vtd/LibraryPrivate/DxeVtdInitLib/DxeVtdInitLib.c b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Vtd/LibraryPrivate/DxeVtdInitLib/DxeVtdInitLib.c
new file mode 100644
index 0000000000..faac07c45d
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Vtd/LibraryPrivate/DxeVtdInitLib/DxeVtdInitLib.c
@@ -0,0 +1,684 @@
+/** @file
+ DXE Library for VTD ACPI table initialization.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include <Library/DxeVtdInitLib.h>
+#include <Library/DxeVtdPolicyLib.h>
+#include <Library/VtdInitFruLib.h>
+#include <Register/SaRegsHostBridge.h>
+
+///
+/// Global Variables
+///
+GLOBAL_REMOVE_IF_UNREFERENCED VTD_DATA_HOB *mVtdDataHob;
+
+BOOLEAN mInterruptRemappingSupport;
+
+/**
+ Get the corresponding device Enable/Disable bit according DevNum and FunNum
+
+ @param[in] DevNum - Device Number
+ @param[in] FunNum - Function Number
+
+ @retval If the device is found, return disable/Enable bit in FD/Deven reigster
+ @retval If not found return 0xFF
+**/
+UINT16
+GetFunDisableBit (
+ UINT8 DevNum,
+ UINT8 FunNum
+ )
+{
+ UINTN Index;
+
+ for (Index = 0; Index < mDevEnMapSize; 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;
+ 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->DrhdHeader.Header.Length;
+ DisableBit = GetFunDisableBit (
+ DrhdEngine->DeviceScope[0].PciPath.Device,
+ DrhdEngine->DeviceScope[0].PciPath.Function
+ );
+ NeedRemove = FALSE;
+
+ if ((DisableBit == 0xFF) ||
+ (DrhdEngine->DrhdHeader.RegisterBaseAddress == 0) ||
+ ((DisableBit == 0x80) &&
+ (PciSegmentRead32 (PCI_SEGMENT_LIB_ADDRESS (SA_SEG_NUM, 0, DrhdEngine->DeviceScope[0].PciPath.Device, DrhdEngine->DeviceScope[0].PciPath.Function, 0x00)) == 0xFFFFFFFF))
+ ) {
+ NeedRemove = TRUE;
+ }
+ if ((DrhdEngine->DeviceScope[0].PciPath.Device == IGD_DEV_NUM) && (DrhdEngine->DeviceScope[0].PciPath.Function == IGD_FUN_NUM) &&
+ (PciSegmentRead32 (PCI_SEGMENT_LIB_ADDRESS (SA_SEG_NUM, 0, DrhdEngine->DeviceScope[0].PciPath.Device, DrhdEngine->DeviceScope[0].PciPath.Function, 0x00)) != 0xFFFFFFFF)) {
+ NeedRemove = FALSE;
+ }
+ if (NeedRemove) {
+ Length -= sizeof (EFI_ACPI_DEV_SCOPE_STRUCTURE);
+ }
+ ///
+ /// If no devicescope is left, we set the structure length as 0x00
+ ///
+ if ((Length > EFI_ACPI_DRHD_ENGINE_HEADER_LENGTH) || (DrhdEngine->DrhdHeader.Flags == 0x01)) {
+ DrhdEngine->DrhdHeader.Header.Length = Length;
+ } else {
+ DrhdEngine->DrhdHeader.Header.Length = 0;
+ }
+}
+
+/**
+ Get IOAPIC ID from LPC
+
+ @retval APIC ID
+**/
+UINT8
+GetIoApicId (
+ VOID
+ )
+{
+ UINT32 IoApicAddress;
+ UINT32 IoApicId;
+
+ IoApicAddress = PcdGet32 (PcdSiIoApicBaseAddress);
+ ///
+ /// Get current IO APIC ID
+ ///
+ MmioWrite8 ((UINTN) (IoApicAddress + R_IO_APIC_MEM_INDEX_OFFSET), 0);
+ IoApicId = MmioRead32 ((UINTN) (IoApicAddress + R_IO_APIC_MEM_DATA_OFFSET)) >> 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 Index;
+ UINT8 Bus;
+ UINT8 Path[2];
+ BOOLEAN NeedRemove;
+ EFI_ACPI_DRHD_ENGINE3_STRUCT *DrhdEngine;
+ VOID *HobPtr;
+ PCH_INFO_HOB *PchInfoHob;
+
+ ///
+ /// Convert DrhdEnginePtr to EFI_ACPI_DRHD_ENGINE3_STRUCT Pointer
+ ///
+ DrhdEngine = (EFI_ACPI_DRHD_ENGINE3_STRUCT *) DrhdEnginePtr;
+
+ Length = DrhdEngine->DrhdHeader.Header.Length;
+ DeviceScopeNum = (DrhdEngine->DrhdHeader.Header.Length - EFI_ACPI_DRHD_ENGINE_HEADER_LENGTH) / sizeof (EFI_ACPI_DEV_SCOPE_STRUCTURE);
+ Bus = 0;
+ ValidDeviceScopeNum = 0;
+ Path[0] = 0;
+ Path[1] = 0;
+
+ HobPtr = GetFirstGuidHob (&gPchInfoHobGuid);
+ ASSERT (HobPtr != NULL);
+ if (HobPtr == NULL) {
+ return;
+ }
+ PchInfoHob = (PCH_INFO_HOB *) GET_GUID_HOB_DATA (HobPtr);
+ ASSERT (PchInfoHob != NULL);
+ if (PchInfoHob == NULL) {
+ return;
+ }
+
+ 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 (mInterruptRemappingSupport) {
+ if (Index == 0) {
+ ///
+ /// Update source id for IoApic's device scope entry
+ ///
+ Bus = (UINT8) PchInfoHob->IoApicBusNum;
+ Path[0] = (UINT8) PchInfoHob->IoApicDevNum;
+ Path[1] = (UINT8) PchInfoHob->IoApicFuncNum;
+ DrhdEngine->DeviceScope[Index].DeviceScopeStructureHeader.StartBusNumber = Bus;
+ DrhdEngine->DeviceScope[Index].PciPath.Device = Path[0];
+ DrhdEngine->DeviceScope[Index].PciPath.Function = Path[1];
+ //
+ // Update APIC ID
+ //
+ DrhdEngine->DeviceScope[Index].DeviceScopeStructureHeader.EnumerationId = GetIoApicId ();
+ }
+ if (Index == 1) {
+ ///
+ /// Update source id for HPET's device scope entry
+ ///
+ Bus = (UINT8) PchInfoHob->HpetBusNum;
+ Path[0] = (UINT8) PchInfoHob->HpetDevNum;
+ Path[1] = (UINT8) PchInfoHob->HpetFuncNum;
+ DrhdEngine->DeviceScope[Index].DeviceScopeStructureHeader.StartBusNumber = Bus;
+ DrhdEngine->DeviceScope[Index].PciPath.Device = Path[0];
+ DrhdEngine->DeviceScope[Index].PciPath.Function = 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 devicescope is left, we set the structure length as 0x00
+ ///
+ if ((Length > EFI_ACPI_DRHD_ENGINE_HEADER_LENGTH) || (DrhdEngine->DrhdHeader.Flags == 0x01)) {
+ DrhdEngine->DrhdHeader.Header.Length = Length;
+ } else {
+ DrhdEngine->DrhdHeader.Header.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 devicescope can be checked,
+ /// we convert the RmrrPtr to EFI_ACPI_RMRR_USB_STRUC pointer
+ ///
+ Rmrr = (EFI_ACPI_RMRR_USB_STRUC *) RmrrPtr;
+
+ Length = Rmrr->RmrrHeader.Header.Length;
+ ValidDeviceScopeNum = 0;
+ DeviceScopeNum = (Rmrr->RmrrHeader.Header.Length - EFI_ACPI_RMRR_HEADER_LENGTH) / sizeof (EFI_ACPI_DEV_SCOPE_STRUCTURE);
+ for (Index = 0; Index < DeviceScopeNum; Index++) {
+ DisableBit = GetFunDisableBit (
+ Rmrr->DeviceScope[Index].PciPath.Device,
+ Rmrr->DeviceScope[Index].PciPath.Function
+ );
+ NeedRemove = FALSE;
+ if ((DisableBit == 0xFF) ||
+ ((DisableBit == 0x80) &&
+ (PciSegmentRead32 (PCI_SEGMENT_LIB_ADDRESS (SA_SEG_NUM, 0, Rmrr->DeviceScope[Index].PciPath.Device, Rmrr->DeviceScope[Index].PciPath.Function, 0x00)) == 0xFFFFFFFF))
+ ) {
+ NeedRemove = TRUE;
+ } else if (DisableBit == 0x8F) {
+ DEBUG ((DEBUG_ERROR, "Rmrr->RmrrHeader.ReservedMemoryRegionBaseAddress %x\n", Rmrr->RmrrHeader.ReservedMemoryRegionBaseAddress));
+
+ if (Rmrr->RmrrHeader.ReservedMemoryRegionBaseAddress != 0) {
+ DEBUG ((DEBUG_ERROR, "NeedRemove = FALSE\n"));
+ NeedRemove = FALSE;
+ } else {
+ DEBUG ((DEBUG_ERROR, "NeedRemove = TRUE\n"));
+ NeedRemove = TRUE;
+ }
+ }
+ CopyMem (
+ &Rmrr->DeviceScope[ValidDeviceScopeNum],
+ &Rmrr->DeviceScope[Index],
+ sizeof (EFI_ACPI_DEV_SCOPE_STRUCTURE)
+ );
+
+ if (Rmrr->RmrrHeader.ReservedMemoryRegionLimitAddress == 0x0) {
+ NeedRemove = TRUE;
+ }
+
+ 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->RmrrHeader.Header.Length = Length;
+ } else {
+ Rmrr->RmrrHeader.Header.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;
+ UINT64 McD0BaseAddress;
+ UINT32 GttMmAdr;
+ UINT64 McD2BaseAddress;
+ UINT16 IgdMode;
+ UINT16 GttMode;
+ UINT32 IgdMemSize;
+ UINT32 GttMemSize;
+ EFI_STATUS Status;
+ VTD_DXE_CONFIG *VtdDxeConfig;
+ SA_POLICY_PROTOCOL *SaPolicy;
+
+
+ IgdMemSize = 0;
+ GttMemSize = 0;
+ DmarTable = (EFI_ACPI_DMAR_TABLE *) TableHeader;
+
+ Status = gBS->LocateProtocol (&gSaPolicyProtocolGuid, NULL, (VOID **) &SaPolicy);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = GetConfigBlock ((VOID *) SaPolicy, &gVtdDxeConfigGuid, (VOID *)&VtdDxeConfig);
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Set INTR_REMAP bit (BIT 0) if interrupt remapping is supported
+ ///
+ if (mInterruptRemappingSupport) {
+ DmarTable->DmarHeader.Flags |= BIT0;
+ }
+
+ if (mVtdDataHob->X2ApicOptOut == 1) {
+ DmarTable->DmarHeader.Flags |= BIT1;
+ } else {
+ DmarTable->DmarHeader.Flags &= 0xFD;
+ }
+
+ ///
+ /// Set DMA_CONTROL_GUARANTEE bit (BIT 2) if Dma Control Guarantee is supported
+ ///
+ if (mVtdDataHob->DmaControlGuarantee == 1) {
+ DmarTable->DmarHeader.Flags |= BIT2;
+ }
+ ///
+ /// Get OemId
+ ///
+ CopyMem (DmarTable->DmarHeader.Header.OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (DmarTable->DmarHeader.Header.OemId));
+ DmarTable->DmarHeader.Header.OemTableId = PcdGet64 (PcdAcpiDefaultOemTableId);
+ DmarTable->DmarHeader.Header.OemRevision = PcdGet32 (PcdAcpiDefaultOemRevision);
+ DmarTable->DmarHeader.Header.CreatorId = PcdGet32 (PcdAcpiDefaultCreatorId);
+ DmarTable->DmarHeader.Header.CreatorRevision = PcdGet32 (PcdAcpiDefaultCreatorRevision);
+
+ ///
+ /// Calculate IGD memsize
+ ///
+ McD0BaseAddress = PCI_SEGMENT_LIB_ADDRESS (SA_SEG_NUM, SA_MC_BUS, 0, 0, 0);
+ IgdMode = ((PciSegmentRead16 (McD0BaseAddress + R_SA_GGC) & B_SA_GGC_GMS_MASK) >> N_SA_GGC_GMS_OFFSET) & 0xFF;
+ if (IgdMode < 0xF0) {
+ IgdMemSize = IgdMode * 32 * (1024) * (1024);
+ } else {
+ IgdMemSize = 4 * (IgdMode - 0xF0 + 1) * (1024) * (1024);
+ }
+ ///
+ /// Calculate GTT mem size
+ ///
+ GttMemSize = 0;
+ GttMode = (PciSegmentRead16 (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);
+ }
+
+ McD2BaseAddress = PCI_SEGMENT_LIB_ADDRESS (SA_SEG_NUM, IGD_BUS_NUM, IGD_DEV_NUM, IGD_FUN_NUM, 0);
+ GttMmAdr = (PciSegmentRead32 (McD2BaseAddress + R_SA_IGD_GTTMMADR)) & 0xFFFFFFF0;
+
+ DmarTable->RmrrIgd.RmrrHeader.ReservedMemoryRegionBaseAddress = (PciSegmentRead32 (McD0BaseAddress + R_SA_BGSM) & ~(0x01));
+ DmarTable->RmrrIgd.RmrrHeader.ReservedMemoryRegionLimitAddress = DmarTable->RmrrIgd.RmrrHeader.ReservedMemoryRegionBaseAddress + IgdMemSize + GttMemSize - 1;
+ DEBUG ((DEBUG_INFO, "RMRR Base address IGD %016lX\n", DmarTable->RmrrIgd.RmrrHeader.ReservedMemoryRegionBaseAddress));
+ DEBUG ((DEBUG_INFO, "RMRR Limit address IGD %016lX\n", DmarTable->RmrrIgd.RmrrHeader.ReservedMemoryRegionLimitAddress));
+
+ ///
+ /// Update DRHD structures of DmarTable
+ ///
+ DmarTable->DrhdEngine1.DrhdHeader.RegisterBaseAddress = ReadVtdBaseAddress(0);
+ DmarTable->DrhdEngine3.DrhdHeader.RegisterBaseAddress = ReadVtdBaseAddress (2);
+
+ DEBUG ((DEBUG_INFO, "VTD base address 1 = %x\n", DmarTable->DrhdEngine1.DrhdHeader.RegisterBaseAddress));
+ DEBUG ((DEBUG_INFO, "VTD base address 3 = %x\n", DmarTable->DrhdEngine3.DrhdHeader.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.DrhdEngine3);
+
+ ///
+ /// Remove unused device scope or entire DRHD structures
+ ///
+ Offset = (UINTN) (&TempDmarTable.DrhdEngine1);
+ if (TempDmarTable.DrhdEngine1.DrhdHeader.Header.Length != 0) {
+ Offset += TempDmarTable.DrhdEngine1.DrhdHeader.Header.Length;
+ }
+ if (TempDmarTable.DrhdEngine3.DrhdHeader.Header.Length != 0) {
+ StructureLen = TempDmarTable.DrhdEngine3.DrhdHeader.Header.Length;
+ CopyMem ((VOID *) Offset, (VOID *) &TempDmarTable.DrhdEngine3, TempDmarTable.DrhdEngine3.DrhdHeader.Header.Length);
+ Offset += StructureLen;
+ }
+ ///
+ /// Remove unused device scope or entire RMRR structures
+ ///
+ if (TempDmarTable.RmrrIgd.RmrrHeader.Header.Length != 0) {
+ StructureLen = TempDmarTable.RmrrIgd.RmrrHeader.Header.Length;
+ CopyMem ((VOID *) Offset, (VOID *) &TempDmarTable.RmrrIgd, TempDmarTable.RmrrIgd.RmrrHeader.Header.Length);
+ Offset += StructureLen;
+ }
+ Offset = Offset - (UINTN) &TempDmarTable;
+ ///
+ /// Re-calculate DMAR table check sum
+ ///
+ TempDmarTable.DmarHeader.Header.Checksum = (UINT8) (TempDmarTable.DmarHeader.Header.Checksum + TempDmarTable.DmarHeader.Header.Length - Offset);
+ ///
+ /// Set DMAR table length
+ ///
+ TempDmarTable.DmarHeader.Header.Length = (UINT32) Offset;
+ ///
+ /// Replace DMAR table with rebuilt table TempDmarTable
+ ///
+ CopyMem ((VOID *) DmarTable, (VOID *) &TempDmarTable, TempDmarTable.DmarHeader.Header.Length);
+}
+
+/**
+ EndOfPcieEnumration routine for update DMAR
+**/
+VOID
+UpdateDmarEndOfPcieEnum (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE *HandleBuffer;
+ UINTN NumberOfHandles;
+ EFI_FV_FILETYPE FileType;
+ UINT32 FvStatus;
+ EFI_FV_FILE_ATTRIBUTES Attributes;
+ UINTN Size;
+ UINTN i;
+ INTN Instance;
+ EFI_ACPI_TABLE_VERSION Version;
+ EFI_ACPI_COMMON_HEADER *CurrentTable;
+ UINTN AcpiTableHandle;
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVol;
+ EFI_ACPI_TABLE_PROTOCOL *AcpiTable;
+ EFI_ACPI_DESCRIPTION_HEADER *VtdAcpiTable;
+ STATIC BOOLEAN Triggered = FALSE;
+
+
+ if (Triggered) {
+ return;
+ }
+
+ Triggered = TRUE;
+
+ FwVol = NULL;
+ AcpiTable = NULL;
+ VtdAcpiTable = NULL;
+
+ DEBUG ((DEBUG_INFO, "UpdateDmarEndOfPcieEnum \n"));
+
+
+ ///
+ /// Fix DMAR Table always created, skip install when disabled
+ ///
+ if ((mVtdDataHob->VtdDisable == TRUE) || (PciSegmentRead32 (PCI_SEGMENT_LIB_ADDRESS (SA_SEG_NUM, SA_MC_BUS, 0, 0, R_SA_MC_CAPID0_A_OFFSET)) & BIT23)) {
+ DEBUG ((DEBUG_INFO, "Vtd Disabled, skip DMAR Table install\n"));
+ return;
+ }
+
+
+ ///
+ /// Locate ACPI support protocol
+ ///
+ Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTable);
+
+ ///
+ /// Locate protocol.
+ /// There is little chance we can't find an FV protocol
+ ///
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiFirmwareVolume2ProtocolGuid,
+ NULL,
+ &NumberOfHandles,
+ &HandleBuffer
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Looking for FV with ACPI storage file
+ ///
+ for (i = 0; i < NumberOfHandles; i++) {
+ ///
+ /// Get the protocol on this handle
+ /// This should not fail because of LocateHandleBuffer
+ ///
+ Status = gBS->HandleProtocol (
+ HandleBuffer[i],
+ &gEfiFirmwareVolume2ProtocolGuid,
+ (VOID **) &FwVol
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// See if it has the ACPI storage file
+ ///
+ Size = 0;
+ FvStatus = 0;
+ Status = FwVol->ReadFile (
+ FwVol,
+ &gSaAcpiTableStorageGuid,
+ NULL,
+ &Size,
+ &FileType,
+ &Attributes,
+ &FvStatus
+ );
+
+ ///
+ /// If we found it, then we are done
+ ///
+ if (Status == EFI_SUCCESS) {
+ break;
+ }
+ }
+ ///
+ /// Our exit status is determined by the success of the previous operations
+ /// If the protocol was found, Instance already points to it.
+ ///
+ ///
+ /// Free any allocated buffers
+ ///
+ FreePool (HandleBuffer);
+
+ ///
+ /// Sanity check that we found our data file
+ ///
+ ASSERT (FwVol);
+ if (FwVol == NULL) {
+ return;
+ }
+ ///
+ /// By default, a table belongs in all ACPI table versions published.
+ ///
+ Version = EFI_ACPI_TABLE_VERSION_1_0B | EFI_ACPI_TABLE_VERSION_2_0 | EFI_ACPI_TABLE_VERSION_3_0;
+
+ ///
+ /// Read tables from the storage file.
+ ///
+ Instance = 0;
+ CurrentTable = NULL;
+
+ while (Status == EFI_SUCCESS) {
+ Status = FwVol->ReadSection (
+ FwVol,
+ &gSaAcpiTableStorageGuid,
+ EFI_SECTION_RAW,
+ Instance,
+ (VOID **) &CurrentTable,
+ &Size,
+ &FvStatus
+ );
+
+ if (!EFI_ERROR (Status)) {
+ ///
+ /// Check the Signature ID to modify the table
+ ///
+ if ((CurrentTable != NULL) && ((EFI_ACPI_DESCRIPTION_HEADER *) CurrentTable)->Signature == EFI_ACPI_VTD_DMAR_TABLE_SIGNATURE) {
+ VtdAcpiTable = (EFI_ACPI_DESCRIPTION_HEADER *) CurrentTable;
+ DmarTableUpdate (VtdAcpiTable, &Version);
+ break;
+ }
+ ///
+ /// Increment the instance
+ ///
+ Instance++;
+ if (CurrentTable != NULL) {
+ gBS->FreePool (CurrentTable);
+ CurrentTable = NULL;
+ }
+ }
+ }
+ ///
+ /// Update the VTD table in the ACPI tables.
+ ///
+ AcpiTableHandle = 0;
+ if (VtdAcpiTable != NULL) {
+ Status = AcpiTable->InstallAcpiTable (
+ AcpiTable,
+ VtdAcpiTable,
+ VtdAcpiTable->Length,
+ &AcpiTableHandle
+ );
+ FreePool (VtdAcpiTable);
+ }
+}
+
+/**
+ Locate the VT-d ACPI tables data file and read ACPI SSDT tables.
+ Publish the appropriate SSDT based on current configuration and capabilities.
+
+ @param[in] SaPolicy - SA DXE Policy protocol
+
+ @retval EFI_SUCCESS - Vtd initialization complete
+ @exception EFI_UNSUPPORTED - Vtd is not enabled by policy
+**/
+EFI_STATUS
+VtdInit (
+ IN SA_POLICY_PROTOCOL *SaPolicy
+ )
+{
+ EFI_STATUS Status;
+ UINT64 McD0BaseAddress;
+ UINT64 McD2BaseAddress;
+ SYSTEM_AGENT_NVS_AREA_PROTOCOL *SaNvsAreaProtocol;
+ UINT8 Index;
+
+ mInterruptRemappingSupport = FALSE;
+ mVtdDataHob = NULL;
+ mVtdDataHob = GetFirstGuidHob(&gVtdDataHobGuid);
+ if (mVtdDataHob != NULL) {
+ mInterruptRemappingSupport = mVtdDataHob->InterruptRemappingSupport;
+ }
+
+ ///
+ /// Locate the SA Global NVS Protocol.
+ ///
+ Status = gBS->LocateProtocol (
+ &gSaNvsAreaProtocolGuid,
+ NULL,
+ (VOID **) &SaNvsAreaProtocol
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ McD0BaseAddress = PCI_SEGMENT_LIB_ADDRESS (SA_SEG_NUM, SA_MC_BUS, 0, 0, 0);
+ McD2BaseAddress = PCI_SEGMENT_LIB_ADDRESS (SA_SEG_NUM, IGD_BUS_NUM, IGD_DEV_NUM, IGD_FUN_NUM, 0);
+
+ if (mVtdDataHob != NULL) {
+ SaNvsAreaProtocol->Area->VtdDisable = mVtdDataHob->VtdDisable;
+ }
+
+ for (Index = 0; Index < VTD_ENGINE_NUMBER; Index++) {
+ SaNvsAreaProtocol->Area->VtdBaseAddress[Index] = ReadVtdBaseAddress (Index);
+ }
+ SaNvsAreaProtocol->Area->VtdEngine1Vid = PciSegmentRead16(McD2BaseAddress + PCI_VENDOR_ID_OFFSET);
+
+ if (mVtdDataHob != NULL) {
+ if ((mVtdDataHob->VtdDisable) || (PciSegmentRead32 (McD0BaseAddress + R_SA_MC_CAPID0_A_OFFSET) & BIT23)) {
+ DEBUG ((DEBUG_WARN, "VTd disabled or no capability!\n"));
+ return EFI_UNSUPPORTED;
+ }
+ }
+ ///
+ /// Check SA supports VTD and VTD is enabled in setup menu
+ ///
+ DEBUG ((DEBUG_INFO, "VTd enabled\n"));
+
+ return EFI_SUCCESS;
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Vtd/LibraryPrivate/DxeVtdInitLib/DxeVtdInitLib.inf b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Vtd/LibraryPrivate/DxeVtdInitLib/DxeVtdInitLib.inf
new file mode 100644
index 0000000000..9797c31cc6
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Vtd/LibraryPrivate/DxeVtdInitLib/DxeVtdInitLib.inf
@@ -0,0 +1,71 @@
+## @file
+# Component description file for the Dxe VTD Init library.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = DxeVtdInitLib
+FILE_GUID = 9BD11E68-923C-424C-A278-716084B4C931
+VERSION_STRING = 1.0
+MODULE_TYPE = DXE_DRIVER
+LIBRARY_CLASS = DxeVtdInitLib
+
+[LibraryClasses]
+UefiLib
+UefiRuntimeServicesTableLib
+UefiBootServicesTableLib
+DebugLib
+PostCodeLib
+ConfigBlockLib
+HobLib
+IoLib
+PciSegmentLib
+BaseMemoryLib
+MemoryAllocationLib
+MmPciLib
+VtdInfoLib
+PchInfoLib
+PchCycleDecodingLib
+SaPlatformLib
+DxeVtdInitFruLib
+
+[Packages]
+MdePkg/MdePkg.dec
+TigerlakeSiliconPkg/SiPkg.dec
+
+[Sources]
+DxeVtdInitLib.c
+
+[Pcd]
+gSiPkgTokenSpaceGuid.PcdSiIoApicBaseAddress
+gSiPkgTokenSpaceGuid.PcdAcpiDefaultOemId
+gSiPkgTokenSpaceGuid.PcdAcpiDefaultOemTableId
+gSiPkgTokenSpaceGuid.PcdAcpiDefaultOemRevision
+gSiPkgTokenSpaceGuid.PcdAcpiDefaultCreatorId
+gSiPkgTokenSpaceGuid.PcdAcpiDefaultCreatorRevision
+
+[FixedPcd]
+
+[Guids]
+gPchInfoHobGuid ## CONSUMES
+gSaAcpiTableStorageGuid
+gVtdDataHobGuid
+gVtdDxeConfigGuid
+
+[Protocols]
+gSaPolicyProtocolGuid ## CONSUMES
+gSaNvsAreaProtocolGuid ## CONSUMES
+gEfiFirmwareVolume2ProtocolGuid
+gEfiAcpiTableProtocolGuid
+
+[Depex]
+gEfiAcpiTableProtocolGuid AND
+gEfiFirmwareVolume2ProtocolGuid AND
+gSaPolicyProtocolGuid AND
+gEfiPciRootBridgeIoProtocolGuid AND
+gEfiPciHostBridgeResourceAllocationProtocolGuid AND # This is to ensure that PCI MMIO resource has been prepared and available for this driver to allocate.
+gEfiHiiDatabaseProtocolGuid
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Vtd/LibraryPrivate/DxeVtdPolicyLib/DxeVtdPolicyLib.c b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Vtd/LibraryPrivate/DxeVtdPolicyLib/DxeVtdPolicyLib.c
new file mode 100644
index 0000000000..168de0c0a9
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Vtd/LibraryPrivate/DxeVtdPolicyLib/DxeVtdPolicyLib.c
@@ -0,0 +1,90 @@
+/** @file
+ This file provides services for DXE VTD policy default initialization
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/DxeVtdPolicyLib.h>
+
+/**
+ This function prints the DXE phase VTD policy.
+
+ @param[in] SaPolicy - Instance of SA_POLICY_PROTOCOL
+**/
+VOID
+VtdPrintPolicyDxe (
+ IN SA_POLICY_PROTOCOL *SaPolicy
+ )
+{
+ EFI_STATUS Status;
+ VTD_DXE_CONFIG *VtdDxeConfig;
+
+ //
+ // Get requisite IP Config Blocks which needs to be used here
+ //
+ Status = GetConfigBlock ((VOID *) SaPolicy, &gVtdDxeConfigGuid, (VOID *)&VtdDxeConfig);
+ ASSERT_EFI_ERROR (Status);
+
+ DEBUG_CODE_BEGIN ();
+ DEBUG ((DEBUG_INFO, "\n------------------------ Vtd Policy (DXE) print BEGIN -----------------\n"));
+ DEBUG ((DEBUG_INFO, " Revision : %d\n", VtdDxeConfig->Header.Revision));
+ ASSERT (VtdDxeConfig->Header.Revision == VTD_DXE_CONFIG_REVISION);
+ DEBUG ((DEBUG_INFO, "\n------------------------ Vtd Policy (DXE) print END -----------------\n"));
+ DEBUG_CODE_END ();
+ return;
+}
+
+/**
+ This function Load default Vtd DXE policy.
+
+ @param[in] ConfigBlockPointer The pointer to add VTD config block
+**/
+VOID
+VtdLoadDefaultDxe (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ VTD_DXE_CONFIG *VtdDxeConfig;
+
+ VtdDxeConfig = ConfigBlockPointer;
+ DEBUG ((DEBUG_INFO, "VtdDxeConfig->Header.GuidHob.Name = %g\n", &VtdDxeConfig->Header.GuidHob.Name));
+ DEBUG ((DEBUG_INFO, "VtdDxeConfig->Header.GuidHob.Header.HobLength = 0x%x\n", VtdDxeConfig->Header.GuidHob.Header.HobLength));
+}
+
+static COMPONENT_BLOCK_ENTRY mVtdDxeIpBlock = {
+ &gVtdDxeConfigGuid, sizeof (VTD_DXE_CONFIG), VTD_DXE_CONFIG_REVISION, VtdLoadDefaultDxe
+};
+
+/**
+ Get VTD DXE config block table total size.
+
+ @retval Size of VTD DXE config block table
+**/
+UINT16
+EFIAPI
+VtdGetConfigBlockTotalSizeDxe (
+ VOID
+ )
+{
+ return mVtdDxeIpBlock.Size;
+}
+
+/**
+ VtdAddConfigBlocks add VTD DXE config block.
+
+ @param[in] ConfigBlockTableAddress The pointer to add VTD config blocks
+
+ @retval EFI_SUCCESS The policy default is initialized.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create buffer
+**/
+EFI_STATUS
+EFIAPI
+VtdAddConfigBlocksDxe (
+ IN VOID *ConfigBlockTableAddress
+ )
+{
+ EFI_STATUS Status;
+ Status = AddComponentConfigBlocks (ConfigBlockTableAddress, &mVtdDxeIpBlock, 1);
+ return Status;
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Vtd/LibraryPrivate/DxeVtdPolicyLib/DxeVtdPolicyLib.inf b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Vtd/LibraryPrivate/DxeVtdPolicyLib/DxeVtdPolicyLib.inf
new file mode 100644
index 0000000000..1fe288416a
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Vtd/LibraryPrivate/DxeVtdPolicyLib/DxeVtdPolicyLib.inf
@@ -0,0 +1,35 @@
+## @file
+# Component description file for the DxeVtdPolicy library.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = DxeVtdPolicyLib
+FILE_GUID = 54754C6D-4883-4B67-BBBA-49D241539BE7
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = DxeVtdPolicyLib
+
+[LibraryClasses]
+BaseMemoryLib
+UefiRuntimeServicesTableLib
+UefiBootServicesTableLib
+DebugLib
+PostCodeLib
+ConfigBlockLib
+HobLib
+SiConfigBlockLib
+
+[Packages]
+MdePkg/MdePkg.dec
+TigerlakeSiliconPkg/SiPkg.dec
+
+[Sources]
+DxeVtdPolicyLib.c
+
+[Guids]
+gVtdDxeConfigGuid
--
2.24.0.windows.2
^ permalink raw reply related [flat|nested] 42+ messages in thread
* [Patch V3 31/40] TigerlakeSiliconPkg/Library: Add package common library instances
2021-02-05 7:40 [Patch V3 01/40] TigerlakeSiliconPkg: Add package and Include/ConfigBlock headers Heng Luo
` (28 preceding siblings ...)
2021-02-05 7:40 ` [Patch V3 30/40] TigerlakeSiliconPkg/IpBlock: Add Vtd component Heng Luo
@ 2021-02-05 7:40 ` Heng Luo
2021-02-05 7:40 ` [Patch V3 32/40] TigerlakeSiliconPkg/Pch: Add Pch " Heng Luo
` (8 subsequent siblings)
38 siblings, 0 replies; 42+ messages in thread
From: Heng Luo @ 2021-02-05 7:40 UTC (permalink / raw)
To: devel; +Cc: Sai Chaganty, Nate DeSimone
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3171
Adds the following files:
* Library/BasePciSegmentMultiSegLibPci
* Library/BaseSiConfigBlockLib
* Library/PeiDxeSmmMmPciLib
Cc: Sai Chaganty <rangasai.v.chaganty@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Signed-off-by: Heng Luo <heng.luo@intel.com>
---
Silicon/Intel/TigerlakeSiliconPkg/Library/BasePciSegmentMultiSegLibPci/BasePciSegmentMultiSegLibPci.inf | 38 +++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Library/BasePciSegmentMultiSegLibPci/BasePciSegmentMultiSegLibPci.uni | 14 ++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Library/BasePciSegmentMultiSegLibPci/PciSegmentLib.c | 1280 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Library/BaseSiConfigBlockLib/BaseSiConfigBlockLib.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Library/BaseSiConfigBlockLib/BaseSiConfigBlockLib.inf | 33 +++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Library/PeiDxeSmmMmPciLib/PeiDxeSmmMmPciLib.c | 35 +++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Library/PeiDxeSmmMmPciLib/PeiDxeSmmMmPciLib.inf | 43 ++++++++++++++++++++++++++++++
7 files changed, 1529 insertions(+)
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Library/BasePciSegmentMultiSegLibPci/BasePciSegmentMultiSegLibPci.inf b/Silicon/Intel/TigerlakeSiliconPkg/Library/BasePciSegmentMultiSegLibPci/BasePciSegmentMultiSegLibPci.inf
new file mode 100644
index 0000000000..b04bce9cf0
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Library/BasePciSegmentMultiSegLibPci/BasePciSegmentMultiSegLibPci.inf
@@ -0,0 +1,38 @@
+## @file
+# Instance of PCI Segment Library based on PCI Library.
+#
+# PCI Segment Library that layers on top of the PCI Library which only
+# supports segment 0 and segment 1 PCI configuration access.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = BasePciSegmentMultiSegLibPci
+ MODULE_UNI_FILE = BasePciSegmentMultiSegLibPci.uni
+ FILE_GUID = AC65B409-DF03-466e-8D2B-6FCE1079F0B2
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PciSegmentLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ PciSegmentLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ TigerlakeSiliconPkg/SiPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ PciLib
+ DebugLib
+ PcdLib
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Library/BasePciSegmentMultiSegLibPci/BasePciSegmentMultiSegLibPci.uni b/Silicon/Intel/TigerlakeSiliconPkg/Library/BasePciSegmentMultiSegLibPci/BasePciSegmentMultiSegLibPci.uni
new file mode 100644
index 0000000000..09bd0f5cfc
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Library/BasePciSegmentMultiSegLibPci/BasePciSegmentMultiSegLibPci.uni
@@ -0,0 +1,14 @@
+/** @file
+ Instance of PCI Segment Library based on PCI Library.
+
+ PCI Segment Library that layers on top of the PCI Library which only
+ supports segment 0 and segment 1 PCI configuration access.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+
+#string STR_MODULE_ABSTRACT #language en-US "Instance of PCI Segment Library based on PCI Library."
+
+#string STR_MODULE_DESCRIPTION #language en-US "PCI Segment Library that layers on top of the PCI Library which only supports segment 0 and segment 1 PCI configuration access."
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Library/BasePciSegmentMultiSegLibPci/PciSegmentLib.c b/Silicon/Intel/TigerlakeSiliconPkg/Library/BasePciSegmentMultiSegLibPci/PciSegmentLib.c
new file mode 100644
index 0000000000..0d0c64be3f
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Library/BasePciSegmentMultiSegLibPci/PciSegmentLib.c
@@ -0,0 +1,1280 @@
+/** @file
+ PCI Segment Library that layers on top of the PCI Library which only
+ supports segment 0 and segment 1 PCI configuration access.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Base.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PciLib.h>
+#include <Library/PciSegmentLib.h>
+
+/**
+ Assert the validity of a PCI Segment address.
+ A valid PCI Segment address should not contain 1's in bits 28..31 and 33..63
+ and the segment should be 0 or 1.
+
+ @param A The address to validate.
+ @param M Additional bits to assert to be zero.
+
+**/
+#define ASSERT_INVALID_PCI_SEGMENT_ADDRESS(A,M) \
+ ASSERT (((A) & (0xfffffffef0000000ULL | (M))) == 0)
+
+/**
+ Convert the PCI Segment library address to PCI library address.
+ From ICL generation support the multiple segment, and the segment number start from BIT28,
+ So we convert the Segment Number offset from BIT32 to BIT28
+
+ @param A The address to convert.
+**/
+#define PCI_SEGMENT_TO_PCI_ADDRESS(A) ((UINTN) (UINT32) ((A) | ((RShiftU64 ((A) & BIT32, 4)))))
+
+/**
+ Register a PCI device so PCI configuration registers may be accessed after
+ SetVirtualAddressMap().
+
+ If any reserved bits in Address are set, then ASSERT().
+
+ @param Address The address that encodes the PCI Bus, Device, Function and
+ Register.
+
+ @retval RETURN_SUCCESS The PCI device was registered for runtime access.
+ @retval RETURN_UNSUPPORTED An attempt was made to call this function
+ after ExitBootServices().
+ @retval RETURN_UNSUPPORTED The resources required to access the PCI device
+ at runtime could not be mapped.
+ @retval RETURN_OUT_OF_RESOURCES There are not enough resources available to
+ complete the registration.
+
+**/
+RETURN_STATUS
+EFIAPI
+PciSegmentRegisterForRuntimeAccess (
+ IN UINTN Address
+ )
+{
+ ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 0);
+ return PciRegisterForRuntimeAccess (PCI_SEGMENT_TO_PCI_ADDRESS (Address));
+}
+
+/**
+ Reads an 8-bit PCI configuration register.
+
+ 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 any reserved bits in Address are set, then ASSERT().
+
+ @param Address The address that encodes the PCI Segment, Bus, Device, Function, and Register.
+
+ @return The 8-bit PCI configuration register specified by Address.
+
+**/
+UINT8
+EFIAPI
+PciSegmentRead8 (
+ IN UINT64 Address
+ )
+{
+ ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 0);
+
+ return PciRead8 (PCI_SEGMENT_TO_PCI_ADDRESS (Address));
+}
+
+/**
+ Writes an 8-bit PCI configuration register.
+
+ 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 any reserved bits in Address are set, then ASSERT().
+
+ @param Address The address that encodes the PCI Segment, Bus, Device, Function, and Register.
+ @param Value The value to write.
+
+ @return The value written to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciSegmentWrite8 (
+ IN UINT64 Address,
+ IN UINT8 Value
+ )
+{
+ ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 0);
+
+ return PciWrite8 (PCI_SEGMENT_TO_PCI_ADDRESS (Address), Value);
+}
+
+/**
+ Performs a bitwise OR of an 8-bit PCI configuration register with an 8-bit value.
+
+ Reads the 8-bit PCI configuration register specified by Address,
+ performs a bitwise 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 any reserved bits in Address are set, then ASSERT().
+
+ @param Address The address that encodes the PCI Segment, Bus, Device, Function, and Register.
+ @param OrData The value to OR with the PCI configuration register.
+
+ @return The value written to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciSegmentOr8 (
+ IN UINT64 Address,
+ IN UINT8 OrData
+ )
+{
+ return PciWrite8 (PCI_SEGMENT_TO_PCI_ADDRESS (Address), (UINT8) (PciSegmentRead8 (Address) | OrData));
+}
+
+/**
+ Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit value.
+
+ 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 any reserved bits in Address are set, then ASSERT().
+
+ @param Address The address that encodes the PCI Segment, Bus, Device, Function, and Register.
+ @param AndData The value to AND with the PCI configuration register.
+
+ @return The value written to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciSegmentAnd8 (
+ IN UINT64 Address,
+ IN UINT8 AndData
+ )
+{
+ return PciSegmentWrite8 (Address, (UINT8) (PciSegmentRead8 (Address) & AndData));
+}
+
+/**
+ Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit value,
+ followed a bitwise OR with another 8-bit value.
+
+ 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 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 any reserved bits in Address are set, then ASSERT().
+
+ @param Address The address that encodes the PCI Segment, Bus, Device, Function, and Register.
+ @param AndData The value to AND with the PCI configuration register.
+ @param OrData The value to OR with the PCI configuration register.
+
+ @return The value written to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciSegmentAndThenOr8 (
+ IN UINT64 Address,
+ IN UINT8 AndData,
+ IN UINT8 OrData
+ )
+{
+ return PciSegmentWrite8 (Address, (UINT8) ((PciSegmentRead8 (Address) & AndData) | OrData));
+}
+
+/**
+ Reads a bit field of a PCI configuration register.
+
+ 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 any reserved bits in Address are set, 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 Address The PCI configuration register to read.
+ @param StartBit The ordinal of the least significant bit in the bit field.
+ Range 0..7.
+ @param EndBit The ordinal of the most significant bit in the bit field.
+ Range 0..7.
+
+ @return The value of the bit field read from the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciSegmentBitFieldRead8 (
+ IN UINT64 Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit
+ )
+{
+ return BitFieldRead8 (PciSegmentRead8 (Address), StartBit, EndBit);
+}
+
+/**
+ Writes a bit field to a PCI configuration register.
+
+ 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 any reserved bits in Address are set, 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().
+ If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
+
+ @param Address The PCI configuration register to write.
+ @param StartBit The ordinal of the least significant bit in the bit field.
+ Range 0..7.
+ @param EndBit The ordinal of the most significant bit in the bit field.
+ Range 0..7.
+ @param Value The new value of the bit field.
+
+ @return The value written back to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciSegmentBitFieldWrite8 (
+ IN UINT64 Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit,
+ IN UINT8 Value
+ )
+{
+ return PciSegmentWrite8 (
+ Address,
+ BitFieldWrite8 (PciSegmentRead8 (Address), StartBit, EndBit, Value)
+ );
+}
+
+/**
+ Reads a bit field in an 8-bit PCI configuration, performs a bitwise OR, and
+ writes the result back to the bit field in the 8-bit port.
+
+ Reads the 8-bit PCI configuration register specified by Address, performs a
+ bitwise 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 any reserved bits in Address are set, 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().
+ If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
+
+ @param Address The PCI configuration register to write.
+ @param StartBit The ordinal of the least significant bit in the bit field.
+ Range 0..7.
+ @param EndBit The ordinal of the most significant bit in the bit field.
+ Range 0..7.
+ @param OrData The value to OR with the PCI configuration register.
+
+ @return The value written back to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciSegmentBitFieldOr8 (
+ IN UINT64 Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit,
+ IN UINT8 OrData
+ )
+{
+ return PciSegmentWrite8 (
+ Address,
+ BitFieldOr8 (PciSegmentRead8 (Address), StartBit, EndBit, OrData)
+ );
+}
+
+/**
+ Reads a bit field in an 8-bit PCI configuration register, performs a bitwise
+ AND, and writes the result back to the bit field in the 8-bit register.
+
+ 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 any reserved bits in Address are set, 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().
+ If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
+
+ @param Address The PCI configuration register to write.
+ @param StartBit The ordinal of the least significant bit in the bit field.
+ Range 0..7.
+ @param EndBit The ordinal of the most significant bit in the bit field.
+ Range 0..7.
+ @param AndData The value to AND with the PCI configuration register.
+
+ @return The value written back to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciSegmentBitFieldAnd8 (
+ IN UINT64 Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit,
+ IN UINT8 AndData
+ )
+{
+ return PciSegmentWrite8 (
+ Address,
+ BitFieldAnd8 (PciSegmentRead8 (Address), StartBit, EndBit, AndData)
+ );
+}
+
+/**
+ Reads a bit field in an 8-bit port, performs a bitwise AND followed by a
+ bitwise OR, and writes the result back to the bit field in the
+ 8-bit port.
+
+ Reads the 8-bit PCI configuration register specified by Address, performs a
+ bitwise AND followed by a bitwise 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 any reserved bits in Address are set, 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().
+ If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
+ If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
+
+ @param Address The PCI configuration register to write.
+ @param StartBit The ordinal of the least significant bit in the bit field.
+ Range 0..7.
+ @param EndBit The ordinal of the most significant bit in the bit field.
+ Range 0..7.
+ @param AndData The value to AND with the PCI configuration register.
+ @param OrData The value to OR with the result of the AND operation.
+
+ @return The value written back to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciSegmentBitFieldAndThenOr8 (
+ IN UINT64 Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit,
+ IN UINT8 AndData,
+ IN UINT8 OrData
+ )
+{
+ return PciSegmentWrite8 (
+ Address,
+ BitFieldAndThenOr8 (PciSegmentRead8 (Address), StartBit, EndBit, AndData, OrData)
+ );
+}
+
+/**
+ Reads a 16-bit PCI configuration register.
+
+ 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 any reserved bits in Address are set, then ASSERT().
+ If Address is not aligned on a 16-bit boundary, then ASSERT().
+
+ @param Address The address that encodes the PCI Segment, Bus, Device, Function, and Register.
+
+ @return The 16-bit PCI configuration register specified by Address.
+
+**/
+UINT16
+EFIAPI
+PciSegmentRead16 (
+ IN UINT64 Address
+ )
+{
+ ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 1);
+
+ return PciRead16 (PCI_SEGMENT_TO_PCI_ADDRESS (Address));
+}
+
+/**
+ Writes a 16-bit PCI configuration register.
+
+ 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 any reserved bits in Address are set, then ASSERT().
+ If Address is not aligned on a 16-bit boundary, then ASSERT().
+
+ @param Address The address that encodes the PCI Segment, Bus, Device, Function, and Register.
+ @param Value The value to write.
+
+ @return The parameter of Value.
+
+**/
+UINT16
+EFIAPI
+PciSegmentWrite16 (
+ IN UINT64 Address,
+ IN UINT16 Value
+ )
+{
+ ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 1);
+
+ return PciWrite16 (PCI_SEGMENT_TO_PCI_ADDRESS (Address), Value);
+}
+
+/**
+ Performs a bitwise OR of a 16-bit PCI configuration register with
+ a 16-bit value.
+
+ Reads the 16-bit PCI configuration register specified by Address, performs a
+ bitwise 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 any reserved bits in Address are set, then ASSERT().
+ If Address is not aligned on a 16-bit boundary, then ASSERT().
+
+ @param Address The address that encodes the PCI Segment, Bus, Device, Function and
+ Register.
+ @param OrData The value to OR with the PCI configuration register.
+
+ @return The value written back to the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciSegmentOr16 (
+ IN UINT64 Address,
+ IN UINT16 OrData
+ )
+{
+ return PciSegmentWrite16 (Address, (UINT16) (PciSegmentRead16 (Address) | OrData));
+}
+
+/**
+ Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit value.
+
+ 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 any reserved bits in Address are set, then ASSERT().
+ If Address is not aligned on a 16-bit boundary, then ASSERT().
+
+ @param Address The address that encodes the PCI Segment, Bus, Device, Function, and Register.
+ @param AndData The value to AND with the PCI configuration register.
+
+ @return The value written to the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciSegmentAnd16 (
+ IN UINT64 Address,
+ IN UINT16 AndData
+ )
+{
+ return PciSegmentWrite16 (Address, (UINT16) (PciSegmentRead16 (Address) & AndData));
+}
+
+/**
+ Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit value,
+ followed a bitwise OR with another 16-bit value.
+
+ 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 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 any reserved bits in Address are set, then ASSERT().
+ If Address is not aligned on a 16-bit boundary, then ASSERT().
+
+ @param Address The address that encodes the PCI Segment, Bus, Device, Function, and Register.
+ @param AndData The value to AND with the PCI configuration register.
+ @param OrData The value to OR with the PCI configuration register.
+
+ @return The value written to the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciSegmentAndThenOr16 (
+ IN UINT64 Address,
+ IN UINT16 AndData,
+ IN UINT16 OrData
+ )
+{
+ return PciSegmentWrite16 (Address, (UINT16) ((PciSegmentRead16 (Address) & AndData) | OrData));
+}
+
+/**
+ Reads a bit field of a PCI configuration register.
+
+ 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 any reserved bits in Address are set, 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 Address The PCI configuration register to read.
+ @param StartBit The ordinal of the least significant bit in the bit field.
+ Range 0..15.
+ @param EndBit The ordinal of the most significant bit in the bit field.
+ Range 0..15.
+
+ @return The value of the bit field read from the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciSegmentBitFieldRead16 (
+ IN UINT64 Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit
+ )
+{
+ return BitFieldRead16 (PciSegmentRead16 (Address), StartBit, EndBit);
+}
+
+/**
+ Writes a bit field to a PCI configuration register.
+
+ 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 any reserved bits in Address are set, 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().
+ If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
+
+ @param Address The PCI configuration register to write.
+ @param StartBit The ordinal of the least significant bit in the bit field.
+ Range 0..15.
+ @param EndBit The ordinal of the most significant bit in the bit field.
+ Range 0..15.
+ @param Value The new value of the bit field.
+
+ @return The value written back to the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciSegmentBitFieldWrite16 (
+ IN UINT64 Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit,
+ IN UINT16 Value
+ )
+{
+ return PciSegmentWrite16 (
+ Address,
+ BitFieldWrite16 (PciSegmentRead16 (Address), StartBit, EndBit, Value)
+ );
+}
+
+/**
+ Reads the 16-bit PCI configuration register specified by Address,
+ performs a bitwise 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.
+
+ If any reserved bits in Address are set, 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().
+ If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
+
+ @param Address The PCI configuration register to write.
+ @param StartBit The ordinal of the least significant bit in the bit field.
+ Range 0..15.
+ @param EndBit The ordinal of the most significant bit in the bit field.
+ Range 0..15.
+ @param OrData The value to OR with the PCI configuration register.
+
+ @return The value written back to the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciSegmentBitFieldOr16 (
+ IN UINT64 Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit,
+ IN UINT16 OrData
+ )
+{
+ return PciSegmentWrite16 (
+ Address,
+ BitFieldOr16 (PciSegmentRead16 (Address), StartBit, EndBit, OrData)
+ );
+}
+
+/**
+ Reads a bit field in a 16-bit PCI configuration, performs a bitwise OR,
+ and writes the result back to the bit field in the 16-bit port.
+
+ Reads the 16-bit PCI configuration register specified by Address,
+ performs a bitwise 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 any reserved bits in Address are set, then ASSERT().
+ If Address is not aligned on a 16-bit boundary, 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().
+ If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
+
+ @param Address The address that encodes the PCI Segment, Bus, Device, Function, and Register.
+ @param StartBit The ordinal of the least significant bit in the bit field.
+ The ordinal of the least significant bit in a byte is bit 0.
+ @param EndBit The ordinal of the most significant bit in the bit field.
+ The ordinal of the most significant bit in a byte is bit 7.
+ @param AndData The value to AND with the read value from the PCI configuration register.
+
+ @return The value written to the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciSegmentBitFieldAnd16 (
+ IN UINT64 Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit,
+ IN UINT16 AndData
+ )
+{
+ return PciSegmentWrite16 (
+ Address,
+ BitFieldAnd16 (PciSegmentRead16 (Address), StartBit, EndBit, AndData)
+ );
+}
+
+/**
+ Reads a bit field in a 16-bit port, performs a bitwise AND followed by a
+ bitwise OR, and writes the result back to the bit field in the
+ 16-bit port.
+
+ Reads the 16-bit PCI configuration register specified by Address, performs a
+ bitwise AND followed by a bitwise 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 any reserved bits in Address are set, 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().
+ If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
+ If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
+
+ @param Address The PCI configuration register to write.
+ @param StartBit The ordinal of the least significant bit in the bit field.
+ Range 0..15.
+ @param EndBit The ordinal of the most significant bit in the bit field.
+ Range 0..15.
+ @param AndData The value to AND with the PCI configuration register.
+ @param OrData The value to OR with the result of the AND operation.
+
+ @return The value written back to the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciSegmentBitFieldAndThenOr16 (
+ IN UINT64 Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit,
+ IN UINT16 AndData,
+ IN UINT16 OrData
+ )
+{
+ return PciSegmentWrite16 (
+ Address,
+ BitFieldAndThenOr16 (PciSegmentRead16 (Address), StartBit, EndBit, AndData, OrData)
+ );
+}
+
+/**
+ Reads a 32-bit PCI configuration register.
+
+ 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 any reserved bits in Address are set, then ASSERT().
+ If Address is not aligned on a 32-bit boundary, then ASSERT().
+
+ @param Address The address that encodes the PCI Segment, Bus, Device, Function, and Register.
+
+ @return The 32-bit PCI configuration register specified by Address.
+
+**/
+UINT32
+EFIAPI
+PciSegmentRead32 (
+ IN UINT64 Address
+ )
+{
+ ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 3);
+
+ return PciRead32 (PCI_SEGMENT_TO_PCI_ADDRESS (Address));
+}
+
+/**
+ Writes a 32-bit PCI configuration register.
+
+ 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 any reserved bits in Address are set, then ASSERT().
+ If Address is not aligned on a 32-bit boundary, then ASSERT().
+
+ @param Address The address that encodes the PCI Segment, Bus, Device, Function, and Register.
+ @param Value The value to write.
+
+ @return The parameter of Value.
+
+**/
+UINT32
+EFIAPI
+PciSegmentWrite32 (
+ IN UINT64 Address,
+ IN UINT32 Value
+ )
+{
+ ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 3);
+
+ return PciWrite32 (PCI_SEGMENT_TO_PCI_ADDRESS (Address), Value);
+}
+
+/**
+ Performs a bitwise OR of a 32-bit PCI configuration register with a 32-bit value.
+
+ Reads the 32-bit PCI configuration register specified by Address,
+ performs a bitwise 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 any reserved bits in Address are set, then ASSERT().
+ If Address is not aligned on a 32-bit boundary, then ASSERT().
+
+ @param Address The address that encodes the PCI Segment, Bus, Device, Function, and Register.
+ @param OrData The value to OR with the PCI configuration register.
+
+ @return The value written to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciSegmentOr32 (
+ IN UINT64 Address,
+ IN UINT32 OrData
+ )
+{
+ return PciSegmentWrite32 (Address, PciSegmentRead32 (Address) | OrData);
+}
+
+/**
+ Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit value.
+
+ 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 any reserved bits in Address are set, then ASSERT().
+ If Address is not aligned on a 32-bit boundary, then ASSERT().
+
+ @param Address The address that encodes the PCI Segment, Bus, Device, Function, and Register.
+ @param AndData The value to AND with the PCI configuration register.
+
+ @return The value written to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciSegmentAnd32 (
+ IN UINT64 Address,
+ IN UINT32 AndData
+ )
+{
+ return PciSegmentWrite32 (Address, PciSegmentRead32 (Address) & AndData);
+}
+
+/**
+ Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit value,
+ followed a bitwise OR with another 32-bit value.
+
+ 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 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 any reserved bits in Address are set, then ASSERT().
+ If Address is not aligned on a 32-bit boundary, then ASSERT().
+
+ @param Address The address that encodes the PCI Segment, Bus, Device, Function, and Register.
+ @param AndData The value to AND with the PCI configuration register.
+ @param OrData The value to OR with the PCI configuration register.
+
+ @return The value written to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciSegmentAndThenOr32 (
+ IN UINT64 Address,
+ IN UINT32 AndData,
+ IN UINT32 OrData
+ )
+{
+ return PciSegmentWrite32 (Address, (PciSegmentRead32 (Address) & AndData) | OrData);
+}
+
+/**
+ Reads a bit field of a PCI configuration register.
+
+ 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 any reserved bits in Address are set, 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 Address The PCI configuration register to read.
+ @param StartBit The ordinal of the least significant bit in the bit field.
+ Range 0..31.
+ @param EndBit The ordinal of the most significant bit in the bit field.
+ Range 0..31.
+
+ @return The value of the bit field read from the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciSegmentBitFieldRead32 (
+ IN UINT64 Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit
+ )
+{
+ return BitFieldRead32 (PciSegmentRead32 (Address), StartBit, EndBit);
+}
+
+/**
+ Writes a bit field to a PCI configuration register.
+
+ 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 any reserved bits in Address are set, 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().
+ If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
+
+ @param Address The PCI configuration register to write.
+ @param StartBit The ordinal of the least significant bit in the bit field.
+ Range 0..31.
+ @param EndBit The ordinal of the most significant bit in the bit field.
+ Range 0..31.
+ @param Value The new value of the bit field.
+
+ @return The value written back to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciSegmentBitFieldWrite32 (
+ IN UINT64 Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit,
+ IN UINT32 Value
+ )
+{
+ return PciSegmentWrite32 (
+ Address,
+ BitFieldWrite32 (PciSegmentRead32 (Address), StartBit, EndBit, Value)
+ );
+}
+
+/**
+ Reads a bit field in a 32-bit PCI configuration, performs a bitwise OR, and
+ writes the result back to the bit field in the 32-bit port.
+
+ Reads the 32-bit PCI configuration register specified by Address, performs a
+ bitwise 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 any reserved bits in Address are set, 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().
+ If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
+
+ @param Address The PCI configuration register to write.
+ @param StartBit The ordinal of the least significant bit in the bit field.
+ Range 0..31.
+ @param EndBit The ordinal of the most significant bit in the bit field.
+ Range 0..31.
+ @param OrData The value to OR with the PCI configuration register.
+
+ @return The value written back to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciSegmentBitFieldOr32 (
+ IN UINT64 Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit,
+ IN UINT32 OrData
+ )
+{
+ return PciSegmentWrite32 (
+ Address,
+ BitFieldOr32 (PciSegmentRead32 (Address), StartBit, EndBit, OrData)
+ );
+}
+
+/**
+ Reads a bit field in a 32-bit PCI configuration register, performs a bitwise
+ AND, and writes the result back to the bit field in the 32-bit register.
+
+
+ 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 any reserved bits in Address are set, 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().
+ If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
+
+ @param Address The PCI configuration register to write.
+ @param StartBit The ordinal of the least significant bit in the bit field.
+ Range 0..31.
+ @param EndBit The ordinal of the most significant bit in the bit field.
+ Range 0..31.
+ @param AndData The value to AND with the PCI configuration register.
+
+ @return The value written back to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciSegmentBitFieldAnd32 (
+ IN UINT64 Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit,
+ IN UINT32 AndData
+ )
+{
+ return PciSegmentWrite32 (
+ Address,
+ BitFieldAnd32 (PciSegmentRead32 (Address), StartBit, EndBit, AndData)
+ );
+}
+
+/**
+ Reads a bit field in a 32-bit port, performs a bitwise AND followed by a
+ bitwise OR, and writes the result back to the bit field in the
+ 32-bit port.
+
+ Reads the 32-bit PCI configuration register specified by Address, performs a
+ bitwise AND followed by a bitwise 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 any reserved bits in Address are set, 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().
+ If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
+ If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
+
+ @param Address The PCI configuration register to write.
+ @param StartBit The ordinal of the least significant bit in the bit field.
+ Range 0..31.
+ @param EndBit The ordinal of the most significant bit in the bit field.
+ Range 0..31.
+ @param AndData The value to AND with the PCI configuration register.
+ @param OrData The value to OR with the result of the AND operation.
+
+ @return The value written back to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciSegmentBitFieldAndThenOr32 (
+ IN UINT64 Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit,
+ IN UINT32 AndData,
+ IN UINT32 OrData
+ )
+{
+ return PciSegmentWrite32 (
+ Address,
+ BitFieldAndThenOr32 (PciSegmentRead32 (Address), StartBit, EndBit, AndData, OrData)
+ );
+}
+
+/**
+ Reads a range of PCI configuration registers into a caller supplied buffer.
+
+ 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 any reserved bits in StartAddress are set, then ASSERT().
+ If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT().
+ If Size > 0 and Buffer is NULL, then ASSERT().
+
+ @param StartAddress The starting address that encodes the PCI Segment, Bus, Device,
+ Function and Register.
+ @param Size The size in bytes of the transfer.
+ @param Buffer The pointer to a buffer receiving the data read.
+
+ @return Size
+
+**/
+UINTN
+EFIAPI
+PciSegmentReadBuffer (
+ IN UINT64 StartAddress,
+ IN UINTN Size,
+ OUT VOID *Buffer
+ )
+{
+ UINTN ReturnValue;
+
+ ASSERT_INVALID_PCI_SEGMENT_ADDRESS (StartAddress, 0);
+ ASSERT (((StartAddress & 0xFFF) + Size) <= 0x1000);
+
+ if (Size == 0) {
+ return Size;
+ }
+
+ ASSERT (Buffer != NULL);
+
+ //
+ // Save Size for return
+ //
+ ReturnValue = Size;
+
+ if ((StartAddress & BIT0) != 0) {
+ //
+ // Read a byte if StartAddress is byte aligned
+ //
+ *(volatile UINT8 *)Buffer = PciSegmentRead8 (StartAddress);
+ StartAddress += sizeof (UINT8);
+ Size -= sizeof (UINT8);
+ Buffer = (UINT8*)Buffer + 1;
+ }
+
+ if (Size >= sizeof (UINT16) && (StartAddress & BIT1) != 0) {
+ //
+ // Read a word if StartAddress is word aligned
+ //
+ WriteUnaligned16 (Buffer, PciSegmentRead16 (StartAddress));
+ StartAddress += sizeof (UINT16);
+ Size -= sizeof (UINT16);
+ Buffer = (UINT16*)Buffer + 1;
+ }
+
+ while (Size >= sizeof (UINT32)) {
+ //
+ // Read as many double words as possible
+ //
+ WriteUnaligned32 (Buffer, PciSegmentRead32 (StartAddress));
+ StartAddress += sizeof (UINT32);
+ Size -= sizeof (UINT32);
+ Buffer = (UINT32*)Buffer + 1;
+ }
+
+ if (Size >= sizeof (UINT16)) {
+ //
+ // Read the last remaining word if exist
+ //
+ WriteUnaligned16 (Buffer, PciSegmentRead16 (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 = PciSegmentRead8 (StartAddress);
+ }
+
+ return ReturnValue;
+}
+
+/**
+ Copies the data in a caller supplied buffer to a specified range of PCI
+ configuration space.
+
+ 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 any reserved bits in StartAddress are set, then ASSERT().
+ If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT().
+ If Size > 0 and Buffer is NULL, then ASSERT().
+
+ @param StartAddress The starting address that encodes the PCI Segment, Bus, Device,
+ Function and Register.
+ @param Size The size in bytes of the transfer.
+ @param Buffer The pointer to a buffer containing the data to write.
+
+ @return The parameter of Size.
+
+**/
+UINTN
+EFIAPI
+PciSegmentWriteBuffer (
+ IN UINT64 StartAddress,
+ IN UINTN Size,
+ IN VOID *Buffer
+ )
+{
+ UINTN ReturnValue;
+
+ ASSERT_INVALID_PCI_SEGMENT_ADDRESS (StartAddress, 0);
+ ASSERT (((StartAddress & 0xFFF) + Size) <= 0x1000);
+
+ if (Size == 0) {
+ return 0;
+ }
+
+ ASSERT (Buffer != NULL);
+
+ //
+ // Save Size for return
+ //
+ ReturnValue = Size;
+
+ if ((StartAddress & BIT0) != 0) {
+ //
+ // Write a byte if StartAddress is byte aligned
+ //
+ PciSegmentWrite8 (StartAddress, *(UINT8*) Buffer);
+ StartAddress += sizeof (UINT8);
+ Size -= sizeof (UINT8);
+ Buffer = (UINT8*) Buffer + 1;
+ }
+
+ if (Size >= sizeof (UINT16) && (StartAddress & BIT1) != 0) {
+ //
+ // Write a word if StartAddress is word aligned
+ //
+ PciSegmentWrite16 (StartAddress, ReadUnaligned16 (Buffer));
+ StartAddress += sizeof (UINT16);
+ Size -= sizeof (UINT16);
+ Buffer = (UINT16*) Buffer + 1;
+ }
+
+ while (Size >= sizeof (UINT32)) {
+ //
+ // Write as many double words as possible
+ //
+ PciSegmentWrite32 (StartAddress, ReadUnaligned32 (Buffer));
+ StartAddress += sizeof (UINT32);
+ Size -= sizeof (UINT32);
+ Buffer = (UINT32*) Buffer + 1;
+ }
+
+ if (Size >= sizeof (UINT16)) {
+ //
+ // Write the last remaining word if exist
+ //
+ PciSegmentWrite16 (StartAddress, ReadUnaligned16 (Buffer));
+ StartAddress += sizeof (UINT16);
+ Size -= sizeof (UINT16);
+ Buffer = (UINT16*) Buffer + 1;
+ }
+
+ if (Size >= sizeof (UINT8)) {
+ //
+ // Write the last remaining byte if exist
+ //
+ PciSegmentWrite8 (StartAddress, *(UINT8*) Buffer);
+ }
+
+ return ReturnValue;
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Library/BaseSiConfigBlockLib/BaseSiConfigBlockLib.c b/Silicon/Intel/TigerlakeSiliconPkg/Library/BaseSiConfigBlockLib/BaseSiConfigBlockLib.c
new file mode 100644
index 0000000000..4644de9b74
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Library/BaseSiConfigBlockLib/BaseSiConfigBlockLib.c
@@ -0,0 +1,86 @@
+/** @file
+ This file is BaseSiConfigBlockLib library is used to add config blocks
+ to config block header.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include <ConfigBlock.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/ConfigBlockLib.h>
+#include <Library/SiConfigBlockLib.h>
+
+
+/**
+ GetComponentConfigBlockTotalSize get config block table total size.
+
+ @param[in] ComponentBlocks Component blocks array
+ @param[in] TotalBlockCount Number of blocks
+
+ @retval Size of config block table
+**/
+UINT16
+EFIAPI
+GetComponentConfigBlockTotalSize (
+ IN COMPONENT_BLOCK_ENTRY *ComponentBlocks,
+ IN UINT16 TotalBlockCount
+ )
+{
+ UINT16 TotalBlockSize;
+ UINT16 BlockCount;
+
+ TotalBlockSize = 0;
+ for (BlockCount = 0 ; BlockCount < TotalBlockCount; BlockCount++) {
+ TotalBlockSize += (UINT32) ComponentBlocks[BlockCount].Size;
+ DEBUG ((DEBUG_INFO, "TotalBlockSize after adding Block[0x%x]= 0x%x\n", BlockCount, TotalBlockSize));
+ }
+
+ return TotalBlockSize;
+}
+
+/**
+ AddComponentConfigBlocks add all config blocks.
+
+ @param[in] ConfigBlockTableAddress The pointer to add config blocks
+ @param[in] ComponentBlocks Config blocks array
+ @param[in] TotalBlockCount Number of blocks
+
+ @retval EFI_SUCCESS The policy default is initialized.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create buffer
+**/
+EFI_STATUS
+EFIAPI
+AddComponentConfigBlocks (
+ IN VOID *ConfigBlockTableAddress,
+ IN COMPONENT_BLOCK_ENTRY *ComponentBlocks,
+ IN UINT16 TotalBlockCount
+ )
+{
+ UINT16 BlockCount;
+ VOID *ConfigBlockPointer;
+ CONFIG_BLOCK ConfigBlockBuf;
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+
+ //
+ // Initialize ConfigBlockPointer to NULL
+ //
+ ConfigBlockPointer = NULL;
+ //
+ // Loop to identify each config block from ComponentBlocks[] Table and add each of them
+ //
+ for (BlockCount = 0; BlockCount < TotalBlockCount; BlockCount++) {
+ ZeroMem (&ConfigBlockBuf, sizeof (CONFIG_BLOCK));
+ CopyMem (&(ConfigBlockBuf.Header.GuidHob.Name), ComponentBlocks[BlockCount].Guid, sizeof (EFI_GUID));
+ ConfigBlockBuf.Header.GuidHob.Header.HobLength = ComponentBlocks[BlockCount].Size;
+ ConfigBlockBuf.Header.Revision = ComponentBlocks[BlockCount].Revision;
+ ConfigBlockPointer = (VOID *)&ConfigBlockBuf;
+ Status = AddConfigBlock ((VOID *)ConfigBlockTableAddress, (VOID *)&ConfigBlockPointer);
+ ASSERT_EFI_ERROR (Status);
+ ComponentBlocks[BlockCount].LoadDefault (ConfigBlockPointer);
+ }
+ return Status;
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Library/BaseSiConfigBlockLib/BaseSiConfigBlockLib.inf b/Silicon/Intel/TigerlakeSiliconPkg/Library/BaseSiConfigBlockLib/BaseSiConfigBlockLib.inf
new file mode 100644
index 0000000000..e23b2d342f
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Library/BaseSiConfigBlockLib/BaseSiConfigBlockLib.inf
@@ -0,0 +1,33 @@
+## @file
+# Component description file for the BaseSiConfigBlockLib library.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = BaseSiConfigBlockLib
+FILE_GUID = 6C068D0F-F48E-48CB-B369-433E507AF4A2
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = SiConfigBlockLib
+
+
+[LibraryClasses]
+DebugLib
+IoLib
+ConfigBlockLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+TigerlakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+BaseSiConfigBlockLib.c
+
+
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Library/PeiDxeSmmMmPciLib/PeiDxeSmmMmPciLib.c b/Silicon/Intel/TigerlakeSiliconPkg/Library/PeiDxeSmmMmPciLib/PeiDxeSmmMmPciLib.c
new file mode 100644
index 0000000000..48e14dc9ee
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Library/PeiDxeSmmMmPciLib/PeiDxeSmmMmPciLib.c
@@ -0,0 +1,35 @@
+/** @file
+ This file contains routines that get PCI Express Address
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include <Library/BaseLib.h>
+#include <Library/PcdLib.h>
+#include <Library/DebugLib.h>
+
+/**
+ This procedure will get PCIE address
+
+ @param[in] Bus Pci Bus Number
+ @param[in] Device Pci Device Number
+ @param[in] Function Pci Function Number
+
+ @retval PCIE address
+**/
+UINTN
+EFIAPI
+MmPciBase (
+ IN UINT32 Bus,
+ IN UINT32 Device,
+ IN UINT32 Function
+ )
+{
+ ASSERT ((Bus <= 0xFF) && (Device <= 0x1F) && (Function <= 0x7));
+
+#ifdef FSP_FLAG
+ return ((UINTN) PcdGet64 (PcdSiPciExpressBaseAddress) + (UINTN) (Bus << 20) + (UINTN) (Device << 15) + (UINTN) (Function << 12));
+#else
+ return ((UINTN) PcdGet64 (PcdPciExpressBaseAddress) + (UINTN) (Bus << 20) + (UINTN) (Device << 15) + (UINTN) (Function << 12));
+#endif
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Library/PeiDxeSmmMmPciLib/PeiDxeSmmMmPciLib.inf b/Silicon/Intel/TigerlakeSiliconPkg/Library/PeiDxeSmmMmPciLib/PeiDxeSmmMmPciLib.inf
new file mode 100644
index 0000000000..353b97f3f6
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Library/PeiDxeSmmMmPciLib/PeiDxeSmmMmPciLib.inf
@@ -0,0 +1,43 @@
+## @file
+# Component description file for the PeiDxeSmmMmPciLib
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiDxeSmmMmPciLib
+FILE_GUID = D03D6670-A032-11E2-9E96-0800200C9A66
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = MmPciLib
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+
+
+[LibraryClasses]
+BaseLib
+PcdLib
+DebugLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+TigerlakeSiliconPkg/SiPkg.dec
+
+
+[Pcd]
+gSiPkgTokenSpaceGuid.PcdSiPciExpressBaseAddress
+
+[FixedPcd]
+gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
+
+[Sources]
+PeiDxeSmmMmPciLib.c
--
2.24.0.windows.2
^ permalink raw reply related [flat|nested] 42+ messages in thread
* [Patch V3 32/40] TigerlakeSiliconPkg/Pch: Add Pch common library instances
2021-02-05 7:40 [Patch V3 01/40] TigerlakeSiliconPkg: Add package and Include/ConfigBlock headers Heng Luo
` (29 preceding siblings ...)
2021-02-05 7:40 ` [Patch V3 31/40] TigerlakeSiliconPkg/Library: Add package common library instances Heng Luo
@ 2021-02-05 7:40 ` Heng Luo
2021-02-05 7:40 ` [Patch V3 33/40] TigerlakeSiliconPkg/Pch: Add Pch private " Heng Luo
` (7 subsequent siblings)
38 siblings, 0 replies; 42+ messages in thread
From: Heng Luo @ 2021-02-05 7:40 UTC (permalink / raw)
To: devel; +Cc: Sai Chaganty, Nate DeSimone
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3171
Adds the following files:
* Pch/Library/BasePchPciBdfLib
* Pch/Library/BaseResetSystemLib
* Pch/Library/DxePchPolicyLib
* Pch/Library/PeiDxeSmmPchCycleDecodingLib
* Pch/Library/PeiDxeSmmPchInfoLib
Cc: Sai Chaganty <rangasai.v.chaganty@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Signed-off-by: Heng Luo <heng.luo@intel.com>
---
Silicon/Intel/TigerlakeSiliconPkg/Pch/Library/BasePchPciBdfLib/BasePchPciBdfLib.inf | 33 +++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/Library/BasePchPciBdfLib/PchPciBdfLib.c | 1092 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/Library/BaseResetSystemLib/BaseResetSystemLib.c | 158 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/Library/BaseResetSystemLib/BaseResetSystemLib.inf | 38 +++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/Library/DxePchPolicyLib/DxePchPolicyLib.c | 198 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/Library/DxePchPolicyLib/DxePchPolicyLib.inf | 43 +++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/Library/PeiDxeSmmPchCycleDecodingLib/PchCycleDecodingLib.c | 587 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/Library/PeiDxeSmmPchCycleDecodingLib/PeiDxeSmmPchCycleDecodingLib.inf | 42 ++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PchInfoLib.c | 127 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PchInfoLibPrivate.h | 58 +++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PchInfoLibTgl.c | 715 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PeiDxeSmmPchInfoLibTgl.inf | 43 +++++++++++++++++++++++++++++++++++
12 files changed, 3134 insertions(+)
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/Library/BasePchPciBdfLib/BasePchPciBdfLib.inf b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Library/BasePchPciBdfLib/BasePchPciBdfLib.inf
new file mode 100644
index 0000000000..4f4096a409
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Library/BasePchPciBdfLib/BasePchPciBdfLib.inf
@@ -0,0 +1,33 @@
+## @file
+# PCH PCIe Bus Device Function Library.
+#
+# All functions from this library are available in PEI, DXE, and SMM,
+# But do not support UEFI RUNTIME environment call.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiDxeSmmPchPciBdfLib
+FILE_GUID = ED0C4241-40FA-4A74-B061-2E45E7AAD7BA
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = PchPciBdfLib
+
+[LibraryClasses]
+BaseLib
+IoLib
+DebugLib
+PciSegmentLib
+PchInfoLib
+PchPcieRpLib
+
+[Packages]
+MdePkg/MdePkg.dec
+TigerlakeSiliconPkg/SiPkg.dec
+
+[Sources]
+PchPciBdfLib.c
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/Library/BasePchPciBdfLib/PchPciBdfLib.c b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Library/BasePchPciBdfLib/PchPciBdfLib.c
new file mode 100644
index 0000000000..0db8cea4bb
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Library/BasePchPciBdfLib/PchPciBdfLib.c
@@ -0,0 +1,1092 @@
+/** @file
+ PCH PCIe Bus Device Function Library.
+ All functions from this library are available in PEI, DXE, and SMM,
+ But do not support UEFI RUNTIME environment call.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Base.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PciSegmentLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/PchPcieRpLib.h>
+#include <Register/PchRegs.h>
+#include <PchBdfAssignment.h>
+
+/**
+ Check if a Device is present for PCH FRU
+ If the data is defined for PCH RFU return it
+ If the data is not defined (Device is NOT present) assert.
+
+ @param[in] DataToCheck Device or Function number to check
+
+ @retval Device or Function number value if defined for PCH FRU
+ 0xFF if not present in PCH FRU
+**/
+UINT8
+CheckAndReturn (
+ UINT8 DataToCheck
+ )
+{
+ if (DataToCheck == NOT_PRESENT) {
+ ASSERT (FALSE);
+ }
+ return DataToCheck;
+}
+
+/**
+ Get eSPI controller address that can be passed to the PCI Segment Library functions.
+
+ @retval eSPI controller address in PCI Segment Library representation
+**/
+UINT64
+EspiPciCfgBase (
+ VOID
+ )
+{
+ ASSERT (PCI_DEVICE_NUMBER_PCH_ESPI != NOT_PRESENT);
+
+ return PCI_SEGMENT_LIB_ADDRESS (
+ DEFAULT_PCI_SEGMENT_NUMBER_PCH,
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_ESPI,
+ PCI_FUNCTION_NUMBER_PCH_ESPI,
+ 0
+ );
+}
+
+/**
+ Returns Gigabit Ethernet PCI Device Number
+
+ @retval GbE device number
+**/
+UINT8
+GbeDevNumber (
+ VOID
+ )
+{
+ return CheckAndReturn (PCI_DEVICE_NUMBER_GBE);
+}
+
+/**
+ Returns Gigabit Ethernet PCI Function Number
+
+ @retval GbE function number
+**/
+UINT8
+GbeFuncNumber (
+ VOID
+ )
+{
+ return CheckAndReturn (PCI_FUNCTION_NUMBER_GBE);
+}
+
+/**
+ Get GbE controller address that can be passed to the PCI Segment Library functions.
+
+ @retval GbE controller address in PCI Segment Library representation
+**/
+UINT64
+GbePciCfgBase (
+ VOID
+ )
+{
+ return PCI_SEGMENT_LIB_ADDRESS (
+ DEFAULT_PCI_SEGMENT_NUMBER_PCH,
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ GbeDevNumber (),
+ GbeFuncNumber (),
+ 0
+ );
+}
+
+/**
+ Get HDA PCI device number
+
+ @retval PCI dev number
+**/
+UINT8
+HdaDevNumber (
+ VOID
+ )
+{
+ return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_HDA);
+}
+
+/**
+ Get HDA PCI function number
+
+ @retval PCI fun number
+**/
+UINT8
+HdaFuncNumber (
+ VOID
+ )
+{
+ return CheckAndReturn (PCI_FUNCTION_NUMBER_PCH_HDA);
+}
+
+/**
+ Get HDA controller address that can be passed to the PCI Segment Library functions.
+
+ @retval HDA controller address in PCI Segment Library representation
+**/
+UINT64
+HdaPciCfgBase (
+ VOID
+ )
+{
+ return PCI_SEGMENT_LIB_ADDRESS (
+ DEFAULT_PCI_SEGMENT_NUMBER_PCH,
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ HdaDevNumber (),
+ HdaFuncNumber (),
+ 0
+ );
+}
+
+/**
+ Get P2SB PCI device number
+
+ @retval PCI dev number
+**/
+UINT8
+P2sbDevNumber (
+ VOID
+ )
+{
+ return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_P2SB);
+}
+
+/**
+ Get P2SB PCI function number
+
+ @retval PCI fun number
+**/
+UINT8
+P2sbFuncNumber (
+ VOID
+ )
+{
+ return CheckAndReturn (PCI_FUNCTION_NUMBER_PCH_P2SB);
+}
+
+/**
+ Get P2SB controller address that can be passed to the PCI Segment Library functions.
+
+ @retval P2SB controller address in PCI Segment Library representation
+**/
+UINT64
+P2sbPciCfgBase (
+ VOID
+ )
+{
+ return PCI_SEGMENT_LIB_ADDRESS (
+ DEFAULT_PCI_SEGMENT_NUMBER_PCH,
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ P2sbDevNumber (),
+ P2sbFuncNumber (),
+ 0
+ );
+}
+
+/**
+ Returns PCH SPI Device number
+
+ @retval UINT8 PCH SPI Device number
+**/
+UINT8
+SpiDevNumber (
+ VOID
+ )
+{
+ return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_SPI);
+}
+
+/**
+ Returns PCH SPI Function number
+
+ @retval UINT8 PCH SPI Function number
+**/
+UINT8
+SpiFuncNumber (
+ VOID
+ )
+{
+ return CheckAndReturn (PCI_FUNCTION_NUMBER_PCH_SPI);
+}
+
+/**
+ Returns PCH SPI PCI Config Space base address
+
+ @retval UINT64 PCH SPI Config Space base address
+**/
+UINT64
+SpiPciCfgBase (
+ VOID
+ )
+{
+ return PCI_SEGMENT_LIB_ADDRESS (
+ DEFAULT_PCI_SEGMENT_NUMBER_PCH,
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ SpiDevNumber (),
+ SpiFuncNumber (),
+ 0
+ );
+}
+
+/**
+ Get XHCI controller PCIe Device Number
+
+ @retval XHCI controller PCIe Device Number
+**/
+UINT8
+PchXhciDevNumber (
+ VOID
+ )
+{
+ return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_XHCI);
+}
+
+/**
+ Get XHCI controller PCIe Function Number
+
+ @retval XHCI controller PCIe Function Number
+**/
+UINT8
+PchXhciFuncNumber (
+ VOID
+ )
+{
+ return CheckAndReturn (PCI_FUNCTION_NUMBER_PCH_XHCI);
+}
+
+/**
+ Get XHCI controller address that can be passed to the PCI Segment Library functions.
+
+ @retval XHCI controller address in PCI Segment Library representation
+**/
+UINT64
+PchXhciPciCfgBase (
+ VOID
+ )
+{
+ return PCI_SEGMENT_LIB_ADDRESS (
+ DEFAULT_PCI_SEGMENT_NUMBER_PCH,
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PchXhciDevNumber (),
+ PchXhciFuncNumber (),
+ 0
+ );
+}
+
+/**
+ Get XDCI controller PCIe Device Number
+
+ @retval XDCI controller PCIe Device Number
+**/
+UINT8
+PchXdciDevNumber (
+ VOID
+ )
+{
+ return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_XDCI);
+}
+
+/**
+ Get XDCI controller PCIe Function Number
+
+ @retval XDCI controller PCIe Function Number
+**/
+UINT8
+PchXdciFuncNumber (
+ VOID
+ )
+{
+ return CheckAndReturn (PCI_FUNCTION_NUMBER_PCH_XDCI);
+}
+
+/**
+ Get XDCI controller address that can be passed to the PCI Segment Library functions.
+
+ @retval XDCI controller address in PCI Segment Library representation
+**/
+UINT64
+PchXdciPciCfgBase (
+ VOID
+ )
+{
+ return PCI_SEGMENT_LIB_ADDRESS (
+ DEFAULT_PCI_SEGMENT_NUMBER_PCH,
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PchXdciDevNumber (),
+ PchXdciFuncNumber (),
+ 0
+ );
+}
+
+/**
+ Return Smbus Device Number
+
+ @retval Smbus Device Number
+**/
+UINT8
+SmbusDevNumber (
+ VOID
+ )
+{
+ return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_SMBUS);
+}
+
+/**
+ Return Smbus Function Number
+
+ @retval Smbus Function Number
+**/
+UINT8
+SmbusFuncNumber (
+ VOID
+ )
+{
+ return CheckAndReturn (PCI_FUNCTION_NUMBER_PCH_SMBUS);
+}
+
+/**
+ Get SMBUS controller address that can be passed to the PCI Segment Library functions.
+
+ @retval SMBUS controller address in PCI Segment Library representation
+**/
+UINT64
+SmbusPciCfgBase (
+ VOID
+ )
+{
+ return PCI_SEGMENT_LIB_ADDRESS (
+ DEFAULT_PCI_SEGMENT_NUMBER_PCH,
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ SmbusDevNumber (),
+ SmbusFuncNumber (),
+ 0
+ );
+}
+
+/**
+ Return DMA Smbus Device Number
+
+ @retval DMA Smbus Device Number
+**/
+UINT8
+SmbusDmaDevNumber (
+ VOID
+ )
+{
+ return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_DMA_SMBUS);
+}
+
+/**
+ Return DMA Smbus Function Number
+
+ @retval DMA Smbus Function Number
+**/
+UINT8
+SmbusDmaFuncNumber (
+ VOID
+ )
+{
+ return CheckAndReturn (PCI_FUNCTION_NUMBER_PCH_DMA_SMBUS);
+}
+
+/**
+ Get DMA SMBUS controller address that can be passed to the PCI Segment Library functions.
+
+ @retval DMA SMBUS controller address in PCI Segment Library representation
+**/
+UINT64
+SmbusDmaPciCfgBase (
+ VOID
+ )
+{
+ return PCI_SEGMENT_LIB_ADDRESS (
+ DEFAULT_PCI_SEGMENT_NUMBER_PCH,
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ SmbusDmaDevNumber (),
+ SmbusDmaFuncNumber (),
+ 0
+ );
+}
+
+/**
+ Get SATA controller PCIe Device Number
+
+ @param[in] SataCtrlIndex SATA controller index
+
+ @retval SATA controller PCIe Device Number
+**/
+UINT8
+SataDevNumber (
+ IN UINT32 SataCtrlIndex
+ )
+{
+ ASSERT (SataCtrlIndex < MAX_SATA_CONTROLLER);
+
+ if (SataCtrlIndex == 0) {
+ return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_SATA_1);
+ } else if (SataCtrlIndex == 1) {
+ return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_SATA_2);
+ } else if (SataCtrlIndex == 2) {
+ return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_SATA_3);
+ } else {
+ ASSERT (FALSE);
+ return 0xFF;
+ }
+}
+
+/**
+ Get SATA controller PCIe Function Number
+
+ @param[in] SataCtrlIndex SATA controller index
+
+ @retval SATA controller PCIe Function Number
+**/
+UINT8
+SataFuncNumber (
+ IN UINT32 SataCtrlIndex
+ )
+{
+ ASSERT (SataCtrlIndex < MAX_SATA_CONTROLLER);
+
+ if (SataCtrlIndex == 0) {
+ return CheckAndReturn (PCI_FUNCTION_NUMBER_PCH_SATA_1);
+ } else if (SataCtrlIndex == 1) {
+ return CheckAndReturn (PCI_FUNCTION_NUMBER_PCH_SATA_2);
+ } else if (SataCtrlIndex == 2) {
+ return CheckAndReturn (PCI_FUNCTION_NUMBER_PCH_SATA_3);
+ } else {
+ ASSERT (FALSE);
+ return 0xFF;
+ }
+}
+
+/**
+ Get SATA controller address that can be passed to the PCI Segment Library functions.
+
+ @param[in] SataCtrlIndex SATA controller index
+
+ @retval SATA controller address in PCI Segment Library representation
+**/
+UINT64
+SataPciCfgBase (
+ IN UINT32 SataCtrlIndex
+ )
+{
+ return PCI_SEGMENT_LIB_ADDRESS (
+ DEFAULT_PCI_SEGMENT_NUMBER_PCH,
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ SataDevNumber (SataCtrlIndex),
+ SataFuncNumber (SataCtrlIndex),
+ 0
+ );
+}
+
+/**
+ Get LPC controller PCIe Device Number
+
+ @retval LPC controller PCIe Device Number
+**/
+UINT8
+LpcDevNumber (
+ VOID
+ )
+{
+ return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_LPC);
+}
+
+/**
+ Get LPC controller PCIe Function Number
+
+ @retval LPC controller PCIe Function Number
+**/
+UINT8
+LpcFuncNumber (
+ VOID
+ )
+{
+ return CheckAndReturn (PCI_FUNCTION_NUMBER_PCH_LPC);
+}
+
+/**
+ Returns PCH LPC device PCI base address.
+
+ @retval PCH LPC PCI base address.
+**/
+UINT64
+LpcPciCfgBase (
+ VOID
+ )
+{
+ return PCI_SEGMENT_LIB_ADDRESS (
+ DEFAULT_PCI_SEGMENT_NUMBER_PCH,
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ LpcDevNumber (),
+ LpcFuncNumber (),
+ 0
+ );
+}
+
+/**
+ Get Thermal Device PCIe Device Number
+
+ @retval Thermal Device PCIe Device Number
+**/
+UINT8
+ThermalDevNumber (
+ VOID
+ )
+{
+ return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_THERMAL);
+}
+
+/**
+ Get Thermal Device PCIe Function Number
+
+ @retval Thermal Device PCIe Function Number
+**/
+UINT8
+ThermalFuncNumber (
+ VOID
+ )
+{
+ return CheckAndReturn (PCI_FUNCTION_NUMBER_PCH_THERMAL);
+}
+
+/**
+ Returns Thermal Device PCI base address.
+
+ @retval Thermal Device PCI base address.
+**/
+UINT64
+ThermalPciCfgBase (
+ VOID
+ )
+{
+ return PCI_SEGMENT_LIB_ADDRESS (
+ DEFAULT_PCI_SEGMENT_NUMBER_PCH,
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ ThermalDevNumber (),
+ ThermalFuncNumber (),
+ 0
+ );
+}
+
+/**
+ Get Serial IO I2C controller PCIe Device Number
+
+ @param[in] I2cNumber Serial IO I2C controller index
+
+ @retval Serial IO I2C controller PCIe Device Number
+**/
+UINT8
+SerialIoI2cDevNumber (
+ IN UINT8 I2cNumber
+ )
+{
+ if (GetPchMaxSerialIoI2cControllersNum () <= I2cNumber) {
+ ASSERT (FALSE);
+ return 0xFF;
+ }
+ switch (I2cNumber) {
+ case 0:
+ return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_SERIAL_IO_I2C0);
+ case 1:
+ return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_SERIAL_IO_I2C1);
+ case 2:
+ return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_SERIAL_IO_I2C2);
+ case 3:
+ return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_SERIAL_IO_I2C3);
+ case 4:
+ return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_SERIAL_IO_I2C4);
+ case 5:
+ return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_SERIAL_IO_I2C5);
+ case 6:
+ return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_SERIAL_IO_I2C6);
+ case 7:
+ return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_SERIAL_IO_I2C7);
+ default:
+ ASSERT (FALSE);
+ return 0xFF;
+ }
+}
+
+/**
+ Get Serial IO I2C controller PCIe Function Number
+
+ @param[in] I2cNumber Serial IO I2C controller index
+
+ @retval Serial IO I2C controller PCIe Function Number
+**/
+UINT8
+SerialIoI2cFuncNumber (
+ IN UINT8 I2cNumber
+ )
+{
+ if (GetPchMaxSerialIoI2cControllersNum () <= I2cNumber) {
+ ASSERT (FALSE);
+ return 0xFF;
+ }
+ switch (I2cNumber) {
+ case 0:
+ return CheckAndReturn (PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_I2C0);
+ case 1:
+ return CheckAndReturn (PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_I2C1);
+ case 2:
+ return CheckAndReturn (PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_I2C2);
+ case 3:
+ return CheckAndReturn (PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_I2C3);
+ case 4:
+ return CheckAndReturn (PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_I2C4);
+ case 5:
+ return CheckAndReturn (PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_I2C5);
+ case 6:
+ return CheckAndReturn (PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_I2C6);
+ case 7:
+ return CheckAndReturn (PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_I2C7);
+ default:
+ ASSERT (FALSE);
+ return 0xFF;
+ }
+}
+
+/**
+ Get Serial IO I2C controller address that can be passed to the PCI Segment Library functions.
+
+ @param[in] I2cNumber Serial IO I2C controller index
+
+ @retval Serial IO I2C controller address in PCI Segment Library representation
+**/
+UINT64
+SerialIoI2cPciCfgBase (
+ IN UINT8 I2cNumber
+ )
+{
+ return PCI_SEGMENT_LIB_ADDRESS (
+ DEFAULT_PCI_SEGMENT_NUMBER_PCH,
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ SerialIoI2cDevNumber (I2cNumber),
+ SerialIoI2cFuncNumber (I2cNumber),
+ 0
+ );
+}
+
+/**
+ Get Serial IO SPI controller PCIe Device Number
+
+ @param[in] I2cNumber Serial IO SPI controller index
+
+ @retval Serial IO SPI controller PCIe Device Number
+**/
+UINT8
+SerialIoSpiDevNumber (
+ IN UINT8 SpiNumber
+ )
+{
+ if (GetPchMaxSerialIoSpiControllersNum () <= SpiNumber) {
+ ASSERT (FALSE);
+ return 0xFF;
+ }
+
+ switch (SpiNumber) {
+ case 0:
+ return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_SERIAL_IO_SPI0);
+ case 1:
+ return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_SERIAL_IO_SPI1);
+ case 2:
+ return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_SERIAL_IO_SPI2);
+ case 3:
+ return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_SERIAL_IO_SPI3);
+ case 4:
+ return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_SERIAL_IO_SPI4);
+ case 5:
+ return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_SERIAL_IO_SPI5);
+ case 6:
+ return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_SERIAL_IO_SPI6);
+ default:
+ ASSERT (FALSE);
+ return 0xFF;
+ }
+}
+
+/**
+ Get Serial IO SPI controller PCIe Function Number
+
+ @param[in] SpiNumber Serial IO SPI controller index
+
+ @retval Serial IO SPI controller PCIe Function Number
+**/
+UINT8
+SerialIoSpiFuncNumber (
+ IN UINT8 SpiNumber
+ )
+{
+ if (GetPchMaxSerialIoSpiControllersNum () <= SpiNumber) {
+ ASSERT (FALSE);
+ return 0xFF;
+ }
+
+ switch (SpiNumber) {
+ case 0:
+ return CheckAndReturn (PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_SPI0);
+ case 1:
+ return CheckAndReturn (PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_SPI1);
+ case 2:
+ return CheckAndReturn (PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_SPI2);
+ case 3:
+ return CheckAndReturn (PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_SPI3);
+ case 4:
+ return CheckAndReturn (PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_SPI4);
+ case 5:
+ return CheckAndReturn (PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_SPI5);
+ case 6:
+ return CheckAndReturn (PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_SPI6);
+ default:
+ ASSERT (FALSE);
+ return 0xFF;
+ }
+}
+
+/**
+ Get Serial IO SPI controller address that can be passed to the PCI Segment Library functions.
+
+ @param[in] SpiNumber Serial IO SPI controller index
+
+ @retval Serial IO SPI controller address in PCI Segment Library representation
+**/
+UINT64
+SerialIoSpiPciCfgBase (
+ IN UINT8 SpiNumber
+ )
+{
+ return PCI_SEGMENT_LIB_ADDRESS (
+ DEFAULT_PCI_SEGMENT_NUMBER_PCH,
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ SerialIoSpiDevNumber (SpiNumber),
+ SerialIoSpiFuncNumber (SpiNumber),
+ 0
+ );
+}
+
+/**
+ Get Serial IO UART controller PCIe Device Number
+
+ @param[in] UartNumber Serial IO UART controller index
+
+ @retval Serial IO UART controller PCIe Device Number
+**/
+UINT8
+SerialIoUartDevNumber (
+ IN UINT8 UartNumber
+ )
+{
+ if (GetPchMaxSerialIoUartControllersNum () <= UartNumber) {
+ ASSERT (FALSE);
+ return 0xFF;
+ }
+ switch (UartNumber) {
+ case 0:
+ return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_SERIAL_IO_UART0);
+ case 1:
+ return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_SERIAL_IO_UART1);
+ case 2:
+ return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_SERIAL_IO_UART2);
+ case 3:
+ return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_SERIAL_IO_UART3);
+ case 4:
+ return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_SERIAL_IO_UART4);
+ case 5:
+ return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_SERIAL_IO_UART5);
+ case 6:
+ return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_SERIAL_IO_UART6);
+ default:
+ ASSERT (FALSE);
+ return 0xFF;
+ }
+}
+
+/**
+ Get Serial IO UART controller PCIe Function Number
+
+ @param[in] UartNumber Serial IO UART controller index
+
+ @retval Serial IO UART controller PCIe Function Number
+**/
+UINT8
+SerialIoUartFuncNumber (
+ IN UINT8 UartNumber
+ )
+{
+ if (GetPchMaxSerialIoUartControllersNum () <= UartNumber) {
+ ASSERT (FALSE);
+ return 0xFF;
+ }
+ switch (UartNumber) {
+ case 0:
+ return CheckAndReturn (PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_UART0);
+ case 1:
+ return CheckAndReturn (PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_UART1);
+ case 2:
+ return CheckAndReturn (PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_UART2);
+ case 3:
+ return CheckAndReturn (PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_UART3);
+ case 4:
+ return CheckAndReturn (PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_UART4);
+ case 5:
+ return CheckAndReturn (PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_UART5);
+ case 6:
+ return CheckAndReturn (PCI_FUNCTION_NUMBER_PCH_SERIAL_IO_UART6);
+ default:
+ ASSERT (FALSE);
+ return 0xFF;
+ }
+}
+
+/**
+ Get Serial IO UART controller address that can be passed to the PCI Segment Library functions.
+
+ @param[in] UartNumber Serial IO UART controller index
+
+ @retval Serial IO UART controller address in PCI Segment Library representation
+**/
+UINT64
+SerialIoUartPciCfgBase (
+ IN UINT8 UartNumber
+ )
+{
+ return PCI_SEGMENT_LIB_ADDRESS (
+ DEFAULT_PCI_SEGMENT_NUMBER_PCH,
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ SerialIoUartDevNumber (UartNumber),
+ SerialIoUartFuncNumber (UartNumber),
+ 0
+ );
+}
+
+/**
+ Get PCH PCIe controller PCIe Device Number
+
+ @param[in] RpIndex Root port physical number. (0-based)
+
+ @retval PCH PCIe controller PCIe Device Number
+**/
+UINT8
+PchPcieRpDevNumber (
+ IN UINTN RpIndex
+ )
+{
+ if (RpIndex >= GetPchMaxPciePortNum ()) {
+ ASSERT (FALSE);
+ return 0xFF;
+ }
+ switch (RpIndex) {
+ case 0:
+ return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_1);
+ case 1:
+ return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_2);
+ case 2:
+ return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_3);
+ case 3:
+ return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_4);
+ case 4:
+ return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_5);
+ case 5:
+ return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_6);
+ case 6:
+ return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_7);
+ case 7:
+ return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_8);
+ case 8:
+ return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_9);
+ case 9:
+ return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_10);
+ case 10:
+ return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_11);
+ case 11:
+ return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_12);
+ case 12:
+ return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_13);
+ case 13:
+ return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_14);
+ case 14:
+ return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_15);
+ case 15:
+ return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_16);
+ case 16:
+ return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_17);
+ case 17:
+ return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_18);
+ case 18:
+ return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_19);
+ case 19:
+ return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_20);
+ case 20:
+ return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_21);
+ case 21:
+ return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_22);
+ case 22:
+ return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_23);
+ case 23:
+ return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_24);
+ case 24:
+ return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_25);
+ case 25:
+ return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_26);
+ case 26:
+ return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_27);
+ case 27:
+ return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_PCIE_ROOT_PORT_28);
+
+ default:
+ ASSERT (FALSE);
+ return 0xFF;
+ }
+}
+
+/**
+ Get PCH PCIe controller PCIe Function Number
+ Note:
+ For Client PCH generations Function Number can be various
+ depending on "Root Port Function Swapping". For such cases
+ Function Number MUST be obtain from proper register.
+ For Server PCHs we have no "Root Port Function Swapping"
+ and we can return fixed Function Number.
+ To address this difference in this, PCH generation independent,
+ library we should call specific function in PchPcieRpLib.
+
+ @param[in] RpIndex Root port physical number. (0-based)
+
+ @retval PCH PCIe controller PCIe Function Number
+**/
+UINT8
+PchPcieRpFuncNumber (
+ IN UINTN RpIndex
+ )
+{
+ UINTN Device;
+ UINTN Function;
+
+ GetPchPcieRpDevFun (RpIndex, &Device, &Function);
+
+ return (UINT8)Function;
+}
+
+/**
+ Get PCH PCIe controller address that can be passed to the PCI Segment Library functions.
+
+ @param[in] RpIndex PCH PCIe Root Port physical number. (0-based)
+
+ @retval PCH PCIe controller address in PCI Segment Library representation
+**/
+UINT64
+PchPcieRpPciCfgBase (
+ IN UINT32 RpIndex
+ )
+{
+ return PCI_SEGMENT_LIB_ADDRESS (
+ DEFAULT_PCI_SEGMENT_NUMBER_PCH,
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PchPcieRpDevNumber (RpIndex),
+ PchPcieRpFuncNumber (RpIndex),
+ 0
+ );
+}
+
+/**
+ Get HECI1 PCI device number
+
+ @retval PCI dev number
+**/
+UINT8
+PchHeci1DevNumber (
+ VOID
+ )
+{
+ return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_HECI1);
+}
+
+/**
+ Get HECI1 PCI function number
+
+ @retval PCI fun number
+**/
+UINT8
+PchHeci1FuncNumber (
+ VOID
+ )
+{
+ return CheckAndReturn (PCI_FUNCTION_NUMBER_PCH_HECI1);
+}
+
+/**
+ Get HECI1 controller address that can be passed to the PCI Segment Library functions.
+
+ @retval HECI1 controller address in PCI Segment Library representation
+**/
+UINT64
+PchHeci1PciCfgBase (
+ VOID
+ )
+{
+ return PCI_SEGMENT_LIB_ADDRESS (
+ DEFAULT_PCI_SEGMENT_NUMBER_PCH,
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PchHeci1DevNumber (),
+ PchHeci1FuncNumber (),
+ 0
+ );
+}
+
+/**
+ Get HECI3 PCI device number
+
+ @retval PCI dev number
+**/
+UINT8
+PchHeci3DevNumber (
+ VOID
+ )
+{
+ return CheckAndReturn (PCI_DEVICE_NUMBER_PCH_HECI3);
+}
+
+/**
+ Get HECI3 PCI function number
+
+ @retval PCI fun number
+**/
+UINT8
+PchHeci3FuncNumber (
+ VOID
+ )
+{
+ return CheckAndReturn (PCI_FUNCTION_NUMBER_PCH_HECI3);
+}
+
+/**
+ Get HECI3 controller address that can be passed to the PCI Segment Library functions.
+
+ @retval HECI3 controller address in PCI Segment Library representation
+**/
+UINT64
+PchHeci3PciCfgBase (
+ VOID
+ )
+{
+ return PCI_SEGMENT_LIB_ADDRESS (
+ DEFAULT_PCI_SEGMENT_NUMBER_PCH,
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PchHeci3DevNumber (),
+ PchHeci3FuncNumber (),
+ 0
+ );
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/Library/BaseResetSystemLib/BaseResetSystemLib.c b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Library/BaseResetSystemLib/BaseResetSystemLib.c
new file mode 100644
index 0000000000..2ede8e0021
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Library/BaseResetSystemLib/BaseResetSystemLib.c
@@ -0,0 +1,158 @@
+/** @file
+ System reset library services.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include <Uefi.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/ResetSystemLib.h>
+#include <Library/PmcLib.h>
+#include <Library/BaseLib.h>
+#include <Register/PchRegsLpc.h>
+#include <Register/PmcRegs.h>
+
+GLOBAL_REMOVE_IF_UNREFERENCED UINT16 mBaseResetSystemABase;
+
+/**
+ Calling this function causes a system-wide reset. This sets
+ all circuitry within the system to its initial state. This type of reset
+ is asynchronous to system operation and operates without regard to
+ cycle boundaries.
+
+ System reset should not return, if it returns, it means the system does
+ not support cold reset.
+**/
+VOID
+EFIAPI
+ResetCold (
+ VOID
+ )
+{
+ IoWrite8 (R_PCH_IO_RST_CNT, V_PCH_IO_RST_CNT_FULLRESET);
+}
+
+/**
+ Calling this function causes a system-wide initialization. The processors
+ are set to their initial state, and pending cycles are not corrupted.
+
+ System reset should not return, if it returns, it means the system does
+ not support warm reset.
+**/
+VOID
+EFIAPI
+ResetWarm (
+ VOID
+ )
+{
+ IoWrite8 (R_PCH_IO_RST_CNT, V_PCH_IO_RST_CNT_HARDRESET);
+}
+
+/**
+ Calling this function causes the system to enter a power state equivalent
+ to the ACPI G2/S5 or G3 states.
+
+ System shutdown should not return, if it returns, it means the system does
+ not support shut down reset.
+**/
+VOID
+EFIAPI
+ResetShutdown (
+ VOID
+ )
+{
+ UINT16 ABase;
+ UINT32 Data32;
+
+ ABase = mBaseResetSystemABase;
+ if (ABase == 0) {
+ ABase = PmcGetAcpiBase ();
+ }
+ ///
+ /// Firstly, GPE0_EN should be disabled to avoid any GPI waking up the system from S5
+ ///
+ IoWrite32 (ABase + R_ACPI_IO_GPE0_EN_127_96, 0);
+
+ ///
+ /// Secondly, PwrSts register must be cleared
+ ///
+ /// Write a "1" to bit[8] of power button status register at
+ /// (PM_BASE + PM1_STS_OFFSET) to clear this bit
+ ///
+ IoWrite16 (ABase + R_ACPI_IO_PM1_STS, B_ACPI_IO_PM1_STS_PWRBTN);
+
+ ///
+ /// Finally, transform system into S5 sleep state
+ ///
+ Data32 = IoRead32 (ABase + R_ACPI_IO_PM1_CNT);
+
+ Data32 = (UINT32) ((Data32 &~(B_ACPI_IO_PM1_CNT_SLP_TYP + B_ACPI_IO_PM1_CNT_SLP_EN)) | V_ACPI_IO_PM1_CNT_S5);
+
+ IoWrite32 (ABase + R_ACPI_IO_PM1_CNT, Data32);
+
+ Data32 = Data32 | B_ACPI_IO_PM1_CNT_SLP_EN;
+
+ IoWrite32 (ABase + R_ACPI_IO_PM1_CNT, Data32);
+
+ return;
+}
+
+/**
+ Calling this function causes the system to enter a power state for platform specific.
+
+ @param[in] DataSize The size of ResetData in bytes.
+ @param[in] ResetData Optional element used to introduce a platform specific reset.
+ The exact type of the reset is defined by the EFI_GUID that follows
+ the Null-terminated Unicode string.
+
+**/
+VOID
+EFIAPI
+ResetPlatformSpecific (
+ IN UINTN DataSize,
+ IN VOID *ResetData OPTIONAL
+ )
+{
+ IoWrite8 (R_PCH_IO_RST_CNT, V_PCH_IO_RST_CNT_FULLRESET);
+}
+
+/**
+ Calling this function causes the system to enter a power state for capsule update.
+
+ Reset update should not return, if it returns, it means the system does
+ not support capsule update.
+
+**/
+VOID
+EFIAPI
+EnterS3WithImmediateWake (
+ VOID
+ )
+{
+ //
+ // In case there are pending capsules to process, need to flush the cache.
+ //
+ AsmWbinvd ();
+
+ ResetWarm ();
+ ASSERT (FALSE);
+}
+
+/**
+ The library constructuor.
+
+ The function does the necessary initialization work for this library instance.
+
+ @retval EFI_SUCCESS The function always return EFI_SUCCESS for now.
+**/
+EFI_STATUS
+EFIAPI
+BaseResetSystemLibConstructor (
+ VOID
+ )
+{
+ mBaseResetSystemABase = PmcGetAcpiBase ();
+
+ return EFI_SUCCESS;
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/Library/BaseResetSystemLib/BaseResetSystemLib.inf b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Library/BaseResetSystemLib/BaseResetSystemLib.inf
new file mode 100644
index 0000000000..a4f805035a
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Library/BaseResetSystemLib/BaseResetSystemLib.inf
@@ -0,0 +1,38 @@
+## @file
+# Component description file for Intel Ich7 Reset System Library.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = BaseResetSystemLib
+FILE_GUID = D4FF05AA-3C7D-4B8A-A1EE-AA5EFA0B1732
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+UEFI_SPECIFICATION_VERSION = 2.00
+LIBRARY_CLASS = ResetSystemLib
+CONSTRUCTOR = BaseResetSystemLibConstructor
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF
+#
+
+[LibraryClasses]
+IoLib
+BaseLib
+DebugLib
+PmcLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+TigerlakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+BaseResetSystemLib.c
+
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/Library/DxePchPolicyLib/DxePchPolicyLib.c b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Library/DxePchPolicyLib/DxePchPolicyLib.c
new file mode 100644
index 0000000000..90aea8f420
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Library/DxePchPolicyLib/DxePchPolicyLib.c
@@ -0,0 +1,198 @@
+/** @file
+ This file provide services for DXE phase policy default initialization
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Uefi.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <ConfigBlock.h>
+#include <Library/ConfigBlockLib.h>
+#include <Library/SiConfigBlockLib.h>
+#include <Protocol/PchPolicy.h>
+#include <ScsConfig.h>
+#include <Library/DxeGpioPolicyLib.h>
+#include <Library/DxeHdaPolicyLib.h>
+#include <Library/DxePchPcieRpPolicyLib.h>
+
+/**
+ Load DXE Config block default for eMMC
+
+ @param[in] ConfigBlockPointer Pointer to config block
+**/
+VOID
+LoadEmmcDxeConfigDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ SCS_EMMC_DXE_CONFIG *EmmcDxeConfig;
+ EmmcDxeConfig = ConfigBlockPointer;
+
+ DEBUG ((DEBUG_INFO, "EmmcDxeConfig->Header.GuidHob.Name = %g\n", &EmmcDxeConfig->Header.GuidHob.Name));
+ DEBUG ((DEBUG_INFO, "EmmcDxeConfig->Header.GuidHob.Header.HobLength = 0x%x\n", EmmcDxeConfig->Header.GuidHob.Header.HobLength));
+
+ EmmcDxeConfig->DriverStrength = DriverStrength40Ohm;
+}
+
+GLOBAL_REMOVE_IF_UNREFERENCED COMPONENT_BLOCK_ENTRY mPchDxeIpBlocks [] = {
+ {&gEmmcDxeConfigGuid, sizeof (SCS_EMMC_DXE_CONFIG), SCS_EMMC_DXE_CONFIG_REVISION, LoadEmmcDxeConfigDefault}
+};
+
+/**
+ Print SCS_EMMC_DXE_CONFIG.
+
+ @param[in] EmmcDxeConfig Pointer to a SCS_EMMC_DXE_CONFIG that provides the eMMC settings
+**/
+VOID
+PchPrintEmmcDxeConfig (
+ IN CONST SCS_EMMC_DXE_CONFIG *EmmcDxeConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "------------------ PCH eMMC DXE Config ------------------\n"));
+ DEBUG ((DEBUG_INFO, " DriverStrength : %d\n", EmmcDxeConfig->DriverStrength));
+ DEBUG ((DEBUG_INFO, " EnableSoftwareHs400Tuning: %d\n", EmmcDxeConfig->EnableSoftwareHs400Tuning));
+ DEBUG ((DEBUG_INFO, " TuningLba : %X\n", EmmcDxeConfig->TuningLba));
+ DEBUG ((DEBUG_INFO, " Previous tuning success : %d\n", EmmcDxeConfig->PreviousTuningResults.TuningSuccessful));
+ if (EmmcDxeConfig->PreviousTuningResults.TuningSuccessful) {
+ DEBUG ((DEBUG_INFO, " Hs400 Rx DLL value : %X\n", EmmcDxeConfig->PreviousTuningResults.Hs400RxValue));
+ DEBUG ((DEBUG_INFO, " Hs400 Tx DLL value : %X\n", EmmcDxeConfig->PreviousTuningResults.Hs400TxValue));
+ }
+}
+
+/**
+ This function prints the PCH DXE phase policy.
+
+ @param[in] PchPolicy - PCH DXE Policy protocol
+**/
+VOID
+PchPrintPolicyProtocol (
+ IN PCH_POLICY_PROTOCOL *PchPolicy
+ )
+{
+ DEBUG_CODE_BEGIN();
+ EFI_STATUS Status;
+ SCS_EMMC_DXE_CONFIG *EmmcDxeConfig;
+
+ //
+ // Get requisite IP Config Blocks which needs to be used here
+ //
+ Status = GetConfigBlock ((VOID *) PchPolicy, &gEmmcDxeConfigGuid, (VOID *)&EmmcDxeConfig);
+ ASSERT_EFI_ERROR (Status);
+
+ DEBUG ((DEBUG_INFO, "------------------------ PCH Policy (DXE) Print Start ------------------------\n"));
+ DEBUG ((DEBUG_INFO, " Revision : %x\n", PchPolicy->TableHeader.Header.Revision));
+
+ PchPrintEmmcDxeConfig (EmmcDxeConfig);
+ GpioDxePrintConfig (PchPolicy);
+ HdaDxePrintConfig (PchPolicy);
+ PchPcieRpDxePrintConfig (PchPolicy);
+
+ DEBUG ((DEBUG_INFO, "------------------------ PCH Policy (DXE) Print End --------------------------\n"));
+ DEBUG_CODE_END();
+}
+
+/**
+ CreatePchDxeConfigBlocks generates the config blocksg of PCH DXE Policy.
+ It allocates and zero out buffer, and fills in the Intel default settings.
+
+ @param[out] PchPolicy The pointer to get PCH DXE Protocol instance
+
+ @retval EFI_SUCCESS The policy default is initialized.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create buffer
+**/
+EFI_STATUS
+EFIAPI
+CreatePchDxeConfigBlocks (
+ IN OUT PCH_POLICY_PROTOCOL **DxePchPolicy
+ )
+{
+ UINT16 TotalBlockSize;
+ EFI_STATUS Status;
+ PCH_POLICY_PROTOCOL *PchPolicyInit;
+ UINT16 RequiredSize;
+
+
+ DEBUG ((DEBUG_INFO, "PCH Create Dxe Config Blocks\n"));
+
+ PchPolicyInit = NULL;
+
+ TotalBlockSize = GetComponentConfigBlockTotalSize (&mPchDxeIpBlocks[0], sizeof (mPchDxeIpBlocks) / sizeof (COMPONENT_BLOCK_ENTRY));
+ TotalBlockSize += GpioDxeGetConfigBlockTotalSize();
+ TotalBlockSize += HdaDxeGetConfigBlockTotalSize();
+ TotalBlockSize += PchPcieRpDxeGetConfigBlockTotalSize();
+
+ DEBUG ((DEBUG_INFO, "TotalBlockSize = 0x%x\n", TotalBlockSize));
+
+ RequiredSize = sizeof (CONFIG_BLOCK_TABLE_HEADER) + TotalBlockSize;
+
+ Status = CreateConfigBlockTable (RequiredSize, (VOID *) &PchPolicyInit);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // General initialization
+ //
+ PchPolicyInit->TableHeader.Header.Revision = PCH_POLICY_PROTOCOL_REVISION;
+ //
+ // Add config blocks.
+ //
+ Status = AddComponentConfigBlocks ((VOID *) PchPolicyInit, &mPchDxeIpBlocks[0], sizeof (mPchDxeIpBlocks) / sizeof (COMPONENT_BLOCK_ENTRY));
+ ASSERT_EFI_ERROR (Status);
+
+ Status = GpioDxeAddConfigBlock ((VOID *) PchPolicyInit);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = HdaDxeAddConfigBlock ((VOID *) PchPolicyInit);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = PchPcieRpDxeAddConfigBlock ((VOID *) PchPolicyInit);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Assignment for returning SaInitPolicy config block base address
+ //
+ *DxePchPolicy = PchPolicyInit;
+ return Status;
+}
+
+/**
+ PchInstallPolicyProtocol installs PCH Policy.
+ While installed, RC assumes the Policy is ready and finalized. So please update and override
+ any setting before calling this function.
+
+ @param[in] ImageHandle Image handle of this driver.
+ @param[in] SaPolicy The pointer to SA Policy Protocol instance
+
+ @retval EFI_SUCCESS The policy is installed.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create buffer
+
+**/
+EFI_STATUS
+EFIAPI
+PchInstallPolicyProtocol (
+ IN EFI_HANDLE ImageHandle,
+ IN PCH_POLICY_PROTOCOL *PchPolicy
+ )
+{
+
+ EFI_STATUS Status;
+
+ ///
+ /// Print PCH DXE Policy
+ ///
+ PchPrintPolicyProtocol (PchPolicy);
+
+ ///
+ /// Install protocol to to allow access to this Policy.
+ ///
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &ImageHandle,
+ &gPchPolicyProtocolGuid,
+ PchPolicy,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/Library/DxePchPolicyLib/DxePchPolicyLib.inf b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Library/DxePchPolicyLib/DxePchPolicyLib.inf
new file mode 100644
index 0000000000..50e5cdacfd
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Library/DxePchPolicyLib/DxePchPolicyLib.inf
@@ -0,0 +1,43 @@
+## @file
+# Component description file for the PeiPchPolicy library.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = DxePchPolicyLib
+FILE_GUID = E2179D04-7026-48A5-9475-309CEA2F21A3
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = DxePchPolicyLib
+
+
+[LibraryClasses]
+BaseMemoryLib
+UefiBootServicesTableLib
+DebugLib
+ConfigBlockLib
+SiConfigBlockLib
+PchInfoLib
+DxeGpioPolicyLib
+DxeHdaPolicyLib
+DxePchPcieRpPolicyLib
+
+[Packages]
+MdePkg/MdePkg.dec
+TigerlakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+DxePchPolicyLib.c
+
+
+[Guids]
+gEmmcDxeConfigGuid
+
+[Protocols]
+gPchPolicyProtocolGuid ## PRODUCES
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/Library/PeiDxeSmmPchCycleDecodingLib/PchCycleDecodingLib.c b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Library/PeiDxeSmmPchCycleDecodingLib/PchCycleDecodingLib.c
new file mode 100644
index 0000000000..0927cd1ced
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Library/PeiDxeSmmPchCycleDecodingLib/PchCycleDecodingLib.c
@@ -0,0 +1,587 @@
+/** @file
+ PCH cycle decoding configuration and query library.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/PciSegmentLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/PchPcrLib.h>
+#include <Library/PchCycleDecodingLib.h>
+#include <Library/PchDmiLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Register/PchRegs.h>
+#include <Register/PchRegsLpc.h>
+#include <Register/SpiRegs.h>
+#include <Register/SmbusRegs.h>
+#include <Library/EspiLib.h>
+#include <Library/PchPciBdfLib.h>
+
+typedef enum {
+ SlaveLpcEspiCS0,
+ SlaveEspiCS1,
+ SlaveId_Max
+} SLAVE_ID_INDEX;
+
+/**
+ Get PCH TCO base address.
+
+ @param[out] Address Address of TCO base address.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid pointer passed.
+**/
+EFI_STATUS
+PchTcoBaseGet (
+ OUT UINT16 *Address
+ )
+{
+ if (Address == NULL) {
+ DEBUG ((DEBUG_ERROR, "PchTcoBaseGet Error. Invalid pointer.\n"));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Read "TCO Base Address" from DMI
+ // Don't read TCO base address from SMBUS PCI register since SMBUS might be disabled.
+ //
+ *Address = PchDmiGetTcoBase ();
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Set PCH LPC/eSPI and eSPI CS1# generic IO range decoding.
+
+ Steps of programming generic IO range:
+ 1. Program LPC/eSPI PCI Offset 84h ~ 93h (LPC, eSPI CS0#) or A4h (eSPI CS1#) of Mask, Address, and Enable.
+ 2. Program LPC/eSPI Generic IO Range in DMI
+
+ @param[in] Address Address for generic IO range decoding.
+ @param[in] Length Length of generic IO range.
+ @param[in] SlaveId Slave ID (refer to SLAVE_ID_INDEX)
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid base address or length passed.
+ @retval EFI_OUT_OF_RESOURCES No more generic range available.
+ @retval EFI_UNSUPPORTED DMI configuration is locked,
+ GenIO range conflicting with other eSPI CS
+**/
+STATIC
+EFI_STATUS
+LpcEspiGenIoRangeSetHelper (
+ IN UINT32 Address,
+ IN UINT32 Length,
+ IN SLAVE_ID_INDEX SlaveId
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Set PCH LPC/eSPI generic IO range.
+ For generic IO range, the base address must align to 4 and less than 0xFFFF, and the length must be power of 2
+ and less than or equal to 256. Moreover, the address must be length aligned.
+ This function basically checks the address and length, which should not overlap with all other generic ranges.
+ If no more generic range register available, it returns out of resource error.
+ This cycle decoding is also required on DMI side
+ Some IO ranges below 0x100 have fixed target. The target might be ITSS,RTC,LPC,PMC or terminated inside P2SB
+ but all predefined and can't be changed. IO range below 0x100 will be rejected in this function except below ranges:
+ 0x00-0x1F,
+ 0x44-0x4B,
+ 0x54-0x5F,
+ 0x68-0x6F,
+ 0x80-0x8F,
+ 0xC0-0xFF
+ Steps of programming generic IO range:
+ 1. Program LPC/eSPI PCI Offset 84h ~ 93h of Mask, Address, and Enable.
+ 2. Program LPC/eSPI Generic IO Range in DMI
+
+ @param[in] Address Address for generic IO range base address.
+ @param[in] Length Length of generic IO range.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid base address or length passed.
+ @retval EFI_OUT_OF_RESOURCES No more generic range available.
+ @retval EFI_UNSUPPORTED DMIC.SRL is set.
+**/
+EFI_STATUS
+PchLpcGenIoRangeSet (
+ IN UINT16 Address,
+ IN UINTN Length
+ )
+{
+ return LpcEspiGenIoRangeSetHelper ((UINT32)Address, (UINT32)Length, SlaveLpcEspiCS0);
+}
+
+
+/**
+ Set PCH LPC/eSPI and eSPI CS1# memory range decoding.
+ This cycle decoding is required to be set on DMI side
+ Programming steps:
+ 1. Program LPC/eSPI PCI Offset 98h (LPC, eSPI CS0#) or A8h (eSPI CS1#) [0] to [0] to disable memory decoding first before changing base address.
+ 2. Program LPC/eSPI PCI Offset 98h (LPC, eSPI CS0#) or A8h (eSPI CS1#) [31:16, 0] to [Address, 1].
+ 3. Program LPC/eSPI Memory Range in DMI
+
+ @param[in] Address Address for memory for decoding.
+ @param[in] RangeIndex Slave ID (refer to SLAVE_ID_INDEX)
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid base address or length passed.
+**/
+STATIC
+EFI_STATUS
+LpcEspiMemRangeSetHelper (
+ IN UINT32 Address,
+ IN SLAVE_ID_INDEX SlaveId
+ )
+{
+ UINT64 LpcBase;
+ EFI_STATUS Status;
+ UINT32 GenMemReg;
+ UINT32 MemRangeAddr;
+
+ if (((Address & (~B_LPC_CFG_LGMR_MA)) != 0) || (SlaveId >= SlaveId_Max)) {
+ DEBUG ((DEBUG_ERROR, "%a Error. Invalid Address: %x or invalid SlaveId\n", __FUNCTION__, Address));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ LpcBase = LpcPciCfgBase ();
+
+ MemRangeAddr = ~Address;
+ if (SlaveId == SlaveEspiCS1) {
+ GenMemReg = R_ESPI_CFG_CS1GMR1;
+ // Memory Range already decoded for LPC/eSPI?
+ Status = PchLpcMemRangeGet (&MemRangeAddr);
+ if (MemRangeAddr != Address) {
+ Status = PchDmiSetEspiCs1MemRange (Address);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+ }
+ } else {
+ GenMemReg = R_LPC_CFG_LGMR;
+ // Memory Range already decoded for eSPI CS1?
+ Status = PchEspiCs1MemRangeGet (&MemRangeAddr);
+ if (MemRangeAddr != Address) {
+ Status = PchDmiSetLpcMemRange (Address);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+ }
+ }
+
+ //
+ // Program LPC/eSPI PCI Offset 98h (LPC, eSPI CS0#) or A8h (eSPI CS1#) [0] to [0] to disable memory decoding first before changing base address.
+ //
+ PciSegmentAnd32 (
+ LpcBase + GenMemReg,
+ (UINT32) ~B_LPC_CFG_LGMR_LMRD_EN
+ );
+ //
+ // Program LPC/eSPI PCI Offset 98h (LPC, eSPI CS0#) or A8h (eSPI CS1#) [31:16, 0] to [Address, 1].
+ //
+ PciSegmentWrite32 (
+ LpcBase + GenMemReg,
+ (Address | B_LPC_CFG_LGMR_LMRD_EN)
+ );
+
+ return Status;
+}
+
+/**
+ Set PCH LPC/eSPI memory range decoding.
+ This cycle decoding is required to be set on DMI side
+ Programming steps:
+ 1. Program LPC PCI Offset 98h [0] to [0] to disable memory decoding first before changing base address.
+ 2. Program LPC PCI Offset 98h [31:16, 0] to [Address, 1].
+ 3. Program LPC Memory Range in DMI
+
+ @param[in] Address Address for memory base address.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid base address or length passed.
+ @retval EFI_OUT_OF_RESOURCES No more generic range available.
+ @retval EFI_UNSUPPORTED DMIC.SRL is set.
+**/
+EFI_STATUS
+PchLpcMemRangeSet (
+ IN UINT32 Address
+ )
+{
+ return LpcEspiMemRangeSetHelper (Address, SlaveLpcEspiCS0);
+}
+
+/**
+ Set PCH eSPI CS1# memory range decoding.
+ This cycle decoding is required to be set on DMI side
+ Programming steps:
+ 1. Program eSPI PCI Offset A8h (eSPI CS1#) [0] to [0] to disable memory decoding first before changing base address.
+ 2. Program eSPI PCI Offset A8h (eSPI CS1#) [31:16, 0] to [Address, 1].
+ 3. Program eSPI Memory Range in DMI
+
+ @param[in] Address Address for memory for decoding.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid base address or length passed.
+ @retval EFI_UNSUPPORTED eSPI secondary slave not supported
+**/
+EFI_STATUS
+PchEspiCs1MemRangeSet (
+ IN UINT32 Address
+ )
+{
+ if (!IsEspiSecondSlaveSupported ()) {
+ return EFI_UNSUPPORTED;
+ }
+
+ return LpcEspiMemRangeSetHelper (Address, SlaveEspiCS1);
+}
+
+/**
+ Get PCH LPC/eSPI and eSPI CS1# memory range decoding address.
+
+ @param[in] SlaveId Slave ID (refer to SLAVE_ID_INDEX)
+ @param[out] Address Address of LPC/eSPI or eSPI CS1# memory decoding base address.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid base address passed.
+ @retval EFI_UNSUPPORTED eSPI secondary slave not supported
+**/
+STATIC
+EFI_STATUS
+LpcEspiMemRangeGetHelper (
+ IN SLAVE_ID_INDEX SlaveId,
+ OUT UINT32 *Address
+ )
+{
+ UINT32 GenMemReg;
+
+ if ((Address == NULL) || (SlaveId >= SlaveId_Max)) {
+ DEBUG ((DEBUG_ERROR, "%a Error. Invalid pointer or SlaveId.\n", __FUNCTION__));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (SlaveId == SlaveEspiCS1) {
+ GenMemReg = R_ESPI_CFG_CS1GMR1;
+ } else {
+ GenMemReg = R_LPC_CFG_LGMR;
+ }
+ *Address = PciSegmentRead32 (LpcPciCfgBase () + GenMemReg) & B_LPC_CFG_LGMR_MA;
+ return EFI_SUCCESS;
+}
+
+/**
+ Get PCH LPC/eSPI memory range decoding address.
+
+ @param[out] Address Address of LPC/eSPI memory decoding base address.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid base address passed.
+**/
+EFI_STATUS
+PchLpcMemRangeGet (
+ OUT UINT32 *Address
+ )
+{
+ return LpcEspiMemRangeGetHelper (SlaveLpcEspiCS0, Address);
+}
+
+/**
+ Get PCH eSPI CS1# memory range decoding address.
+
+ @param[out] Address Address of eSPI CS1# memory decoding base address.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid base address passed.
+ @retval EFI_UNSUPPORTED eSPI secondary slave not supported
+**/
+EFI_STATUS
+PchEspiCs1MemRangeGet (
+ OUT UINT32 *Address
+ )
+{
+ if (!IsEspiSecondSlaveSupported ()) {
+ return EFI_UNSUPPORTED;
+ }
+
+ return LpcEspiMemRangeGetHelper (SlaveEspiCS1, Address);
+}
+
+/**
+ 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 also required in DMI
+ 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 in DMI
+
+ @param[in] BiosDecodeEnable Bios decode enable setting.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_UNSUPPORTED DMIC.SRL is set.
+**/
+EFI_STATUS
+PchBiosDecodeEnableSet (
+ IN UINT16 BiosDecodeEnable
+ )
+{
+ UINT64 BaseAddr;
+ EFI_STATUS Status;
+
+ Status = PchDmiSetBiosDecodeEnable (BiosDecodeEnable);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ //
+ // Check Boot BIOS Strap in DMI
+ //
+ if (PchDmiIsBootBiosStrapSetForSpi ()) {
+ BaseAddr = SpiPciCfgBase ();
+ //
+ // If SPI, Program SPI offset D8h to BiosDecodeEnable.
+ //
+ PciSegmentWrite16 (BaseAddr + R_SPI_CFG_BDE, BiosDecodeEnable);
+ } else {
+ BaseAddr = LpcPciCfgBase ();
+ //
+ // If LPC/eSPi, program LPC offset D8h to BiosDecodeEnable.
+ //
+ PciSegmentWrite16 (BaseAddr + R_LPC_CFG_BDE, BiosDecodeEnable);
+ }
+
+ return Status;
+}
+
+/**
+ Set PCH LPC/eSPI IO decode ranges.
+ Program LPC/eSPI I/O Decode Ranges in DMI 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
+PchLpcIoDecodeRangesSet (
+ IN UINT16 LpcIoDecodeRanges
+ )
+{
+ UINT64 LpcBaseAddr;
+ EFI_STATUS Status;
+
+ //
+ // Note: Inside this function, don't use debug print since it's could used before debug print ready.
+ //
+
+ LpcBaseAddr = LpcPciCfgBase ();
+
+ //
+ // check if setting is identical
+ //
+ if (LpcIoDecodeRanges == PciSegmentRead16 (LpcBaseAddr + R_LPC_CFG_IOD)) {
+ return EFI_SUCCESS;
+ }
+
+ Status = PchDmiSetLpcIoDecodeRanges (LpcIoDecodeRanges);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ //
+ // program LPC/eSPI PCI offset 80h.
+ //
+ PciSegmentWrite16 (LpcBaseAddr + R_LPC_CFG_IOD, LpcIoDecodeRanges);
+
+ return Status;
+}
+
+/**
+ Set PCH LPC/eSPI and eSPI CS1# IO enable decoding.
+ Setup I/O Enables in DMI to the same value program in LPC/eSPI PCI offset 82h (LPC, eSPI CS0#) or A0h (eSPI CS1#).
+ 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] or A0h[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] IoEnableDecoding LPC/eSPI IO enable decoding bit settings.
+ @param[in] SlaveId Slave ID (refer to SLAVE_ID_INDEX)
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_UNSUPPORTED DMI configuration is locked
+**/
+EFI_STATUS
+LpcEspiIoEnableDecodingSetHelper (
+ IN UINT16 IoEnableDecoding,
+ IN SLAVE_ID_INDEX SlaveId
+ )
+{
+ UINT64 LpcBaseAddr;
+ EFI_STATUS Status;
+ UINT16 Cs1IoEnableDecodingOrg;
+ UINT16 Cs0IoEnableDecodingOrg;
+ UINT16 IoEnableDecodingMerged;
+
+ LpcBaseAddr = LpcPciCfgBase ();
+
+ Cs0IoEnableDecodingOrg = PciSegmentRead16 (LpcBaseAddr + R_LPC_CFG_IOE);
+
+ if (IsEspiSecondSlaveSupported ()) {
+ Cs1IoEnableDecodingOrg = PciSegmentRead16 (LpcBaseAddr + R_ESPI_CFG_CS1IORE);
+ } else {
+ Cs1IoEnableDecodingOrg = 0;
+ }
+
+ if (SlaveId == SlaveEspiCS1) {
+ if (IoEnableDecoding == Cs1IoEnableDecodingOrg) {
+ return EFI_SUCCESS;
+ } else {
+ IoEnableDecodingMerged = (Cs0IoEnableDecodingOrg | IoEnableDecoding);
+ }
+ } else {
+ if ((IoEnableDecoding | Cs1IoEnableDecodingOrg) == Cs0IoEnableDecodingOrg) {
+ return EFI_SUCCESS;
+ } else {
+ IoEnableDecodingMerged = (Cs1IoEnableDecodingOrg | IoEnableDecoding);
+ }
+ }
+
+ Status = PchDmiSetLpcIoEnable (IoEnableDecodingMerged);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ //
+ // program PCI offset 82h for LPC/eSPI.
+ //
+ PciSegmentWrite16 (LpcBaseAddr + R_LPC_CFG_IOE, IoEnableDecodingMerged);
+
+ if (SlaveId == SlaveEspiCS1) {
+ //
+ // For eSPI CS1# device program eSPI PCI offset A0h.
+ //
+ PciSegmentWrite16 (LpcBaseAddr + R_ESPI_CFG_CS1IORE, IoEnableDecoding);
+ }
+
+ return Status;
+}
+
+/**
+ Set PCH LPC and eSPI CS0# IO enable decoding.
+ Setup I/O Enables in DMI 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 IO enable decoding bit settings.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_UNSUPPORTED DMIC.SRL is set.
+**/
+EFI_STATUS
+PchLpcIoEnableDecodingSet (
+ IN UINT16 LpcIoEnableDecoding
+ )
+{
+ return LpcEspiIoEnableDecodingSetHelper (LpcIoEnableDecoding, SlaveLpcEspiCS0);
+}
+
+/**
+ Set PCH eSPI CS1# IO enable decoding.
+ Setup I/O Enables in DMI to the same value program in eSPI PCI offset A0h (eSPI CS1#).
+ Note: Bit[15:10] of the source decode register is Read-Only. The IO range indicated by the Enables field
+ in eSPI PCI offset A0h[13:10] is always forwarded by DMI to subtractive agent for handling.
+ Please check EDS for detail of eSPI IO decode ranges bit definition.
+
+ @param[in] IoEnableDecoding eSPI IO enable decoding bit settings.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_UNSUPPORTED DMI configuration is locked
+**/
+EFI_STATUS
+PchEspiCs1IoEnableDecodingSet (
+ IN UINT16 IoEnableDecoding
+ )
+{
+ if (!IsEspiSecondSlaveSupported ()) {
+ return EFI_UNSUPPORTED;
+ }
+
+ return LpcEspiIoEnableDecodingSetHelper (IoEnableDecoding, SlaveEspiCS1);
+}
+
+
+/**
+ Get IO APIC regsiters base address.
+
+ @param[out] IoApicBase Buffer of IO APIC regsiter address
+
+ @retval EFI_SUCCESS Successfully completed.
+**/
+EFI_STATUS
+PchIoApicBaseGet (
+ OUT UINT32 *IoApicBase
+ )
+{
+ *IoApicBase = PcdGet32 (PcdSiIoApicBaseAddress);
+ return EFI_SUCCESS;
+}
+
+/**
+ Get HPET base address.
+
+ @param[out] HpetBase Buffer of HPET base address
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchHpetBaseGet (
+ OUT UINT32 *HpetBase
+ )
+{
+ if (HpetBase == NULL) {
+ DEBUG ((DEBUG_ERROR, "PchHpetBaseGet Error. Invalid pointer.\n"));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *HpetBase = PcdGet32 (PcdSiHpetBaseAddress);
+ return EFI_SUCCESS;
+}
+
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/Library/PeiDxeSmmPchCycleDecodingLib/PeiDxeSmmPchCycleDecodingLib.inf b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Library/PeiDxeSmmPchCycleDecodingLib/PeiDxeSmmPchCycleDecodingLib.inf
new file mode 100644
index 0000000000..ea6b434f29
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Library/PeiDxeSmmPchCycleDecodingLib/PeiDxeSmmPchCycleDecodingLib.inf
@@ -0,0 +1,42 @@
+## @file
+# PCH cycle decoding Lib.
+#
+# All function in this library is available for PEI, DXE, and SMM,
+# But do not support UEFI RUNTIME environment call.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiDxeSmmPchCycleDecodingLib
+FILE_GUID = 676C749F-9CD1-46B7-BAFD-4B1BC36B4C8E
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = PchCycleDecodingLib
+
+
+[LibraryClasses]
+BaseLib
+IoLib
+DebugLib
+PciSegmentLib
+PchInfoLib
+PchPcrLib
+PchDmiLib
+EspiLib
+PchPciBdfLib
+
+[Packages]
+MdePkg/MdePkg.dec
+TigerlakeSiliconPkg/SiPkg.dec
+
+[Sources]
+PchCycleDecodingLib.c
+
+[Pcd]
+gSiPkgTokenSpaceGuid.PcdSiHpetBaseAddress ## CONSUMES
+gSiPkgTokenSpaceGuid.PcdSiIoApicBaseAddress ## CONSUMES
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PchInfoLib.c b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PchInfoLib.c
new file mode 100644
index 0000000000..df8a23d5a3
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PchInfoLib.c
@@ -0,0 +1,127 @@
+/** @file
+ Pch information library.
+
+ All function in this library is available for PEI, DXE, and SMM,
+ But do not support UEFI RUNTIME environment call.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/PciSegmentLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/PchPcrLib.h>
+#include <Library/PrintLib.h>
+#include <Library/PcdLib.h>
+#include "PchInfoLibPrivate.h"
+#include <Register/PchRegs.h>
+#include <Register/PchRegsLpc.h>
+#include <PchPcieRpInfo.h>
+#include <IndustryStandard/Pci30.h>
+#include <Library/PchPciBdfLib.h>
+
+/**
+ Return Pch Series
+
+ @retval PCH_SERIES Pch Series
+**/
+PCH_SERIES
+PchSeries (
+ VOID
+ )
+{
+ return PCH_LP;
+}
+
+/**
+ Return Pch stepping type
+
+ @retval PCH_STEPPING Pch stepping type
+**/
+PCH_STEPPING
+PchStepping (
+ VOID
+ )
+{
+ return 0;
+}
+
+/**
+ Check if this is TGL PCH generation
+
+ @retval TRUE It's TGL PCH
+ @retval FALSE It's not TGL PCH
+**/
+BOOLEAN
+IsTglPch (
+ VOID
+ )
+{
+ return (PchGeneration () == TGL_PCH);
+}
+
+/**
+ Get PCH stepping ASCII string.
+ Function determines major and minor stepping versions and writes them into a buffer.
+ The return string is zero terminated
+
+ @param [out] Buffer Output buffer of string
+ @param [in] BufferSize Buffer size.
+ Must not be less then PCH_STEPPING_STR_LENGTH_MAX
+
+ @retval EFI_SUCCESS String copied successfully
+ @retval EFI_INVALID_PARAMETER The stepping is not supported, or parameters are NULL
+ @retval EFI_BUFFER_TOO_SMALL Input buffer size is too small
+**/
+EFI_STATUS
+PchGetSteppingStr (
+ OUT CHAR8 *Buffer,
+ IN UINT32 BufferSize
+ )
+{
+ PCH_STEPPING PchStep;
+
+ PchStep = PchStepping ();
+
+ if ((Buffer == NULL) || (BufferSize == 0)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (BufferSize < PCH_STEPPING_STR_LENGTH_MAX) {
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ PchPrintSteppingStr (Buffer, BufferSize, PchStep);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Get Pch Maximum Pcie Controller Number
+
+ @retval Pch Maximum Pcie Root Port Number
+**/
+UINT8
+GetPchMaxPcieControllerNum (
+ VOID
+ )
+{
+ return GetPchMaxPciePortNum () / PCH_PCIE_CONTROLLER_PORTS;
+}
+
+/**
+ return support status for P2SB PCR 20-bit addressing
+
+ @retval TRUE
+ @retval FALSE
+**/
+BOOLEAN
+IsP2sb20bPcrSupported (
+ VOID
+ )
+{
+ return FALSE;
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PchInfoLibPrivate.h b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PchInfoLibPrivate.h
new file mode 100644
index 0000000000..a93c3dbafd
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PchInfoLibPrivate.h
@@ -0,0 +1,58 @@
+/** @file
+ Private header for PCH Info Lib.
+
+ All function in this library is available for PEI, DXE, and SMM,
+ But do not support UEFI RUNTIME environment call.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+/**
+ Structure for PCH SKU string mapping
+**/
+struct PCH_SKU_STRING {
+ UINT16 Id;
+ CHAR8 *String;
+};
+
+/**
+ Determine Pch Series based on Device Id
+
+ @param[in] LpcDeviceId Lpc Device Id
+
+ @retval PCH_SERIES Pch Series
+**/
+PCH_SERIES
+PchSeriesFromLpcDid (
+ IN UINT16 LpcDeviceId
+ );
+
+/**
+Determine Pch Generation based on Device Id
+
+@param[in] LpcDeviceId Lpc Device Id
+
+@retval PCH_GENERATION Pch Generation
+**/
+PCH_GENERATION
+PchGenerationFromDid (
+ IN UINT16 LpcDeviceId
+ );
+
+/**
+ Print Pch Stepping String
+
+ @param[out] Buffer Output buffer of string
+ @param[in] BufferSize Buffer Size
+ @param[in] PchStep Pch Stepping Type
+
+ @retval VOID
+**/
+VOID
+PchPrintSteppingStr (
+ OUT CHAR8 *Buffer,
+ IN UINT32 BufferSize,
+ IN PCH_STEPPING PchStep
+ );
+
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PchInfoLibTgl.c b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PchInfoLibTgl.c
new file mode 100644
index 0000000000..bb3c7975e8
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PchInfoLibTgl.c
@@ -0,0 +1,715 @@
+/** @file
+ Pch information library for TGL.
+
+ All function in this library is available for PEI, DXE, and SMM,
+ But do not support UEFI RUNTIME environment call.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Uefi/UefiBaseType.h>
+#include <Library/PchInfoLib.h>
+#include "PchInfoLibPrivate.h"
+#include <Library/PrintLib.h>
+#include <Register/PchRegsLpc.h>
+
+/**
+ Print Pch Stepping String
+
+ @param[out] Buffer Output buffer of string
+ @param[in] BufferSize Buffer Size
+ @param[in] PchStep Pch Stepping Type
+
+ @retval VOID
+**/
+VOID
+PchPrintSteppingStr (
+ OUT CHAR8 *Buffer,
+ IN UINT32 BufferSize,
+ IN PCH_STEPPING PchStep
+ )
+{
+ AsciiSPrint (Buffer, BufferSize, "%c%c", 'A' + (PchStep >> 4), '0' + (PchStep & 0xF));
+}
+
+/**
+ Return Pch Generation
+
+ @retval PCH_GENERATION Pch Generation
+**/
+PCH_GENERATION
+PchGeneration (
+ VOID
+ )
+{
+ return TGL_PCH;
+}
+
+
+/**
+ Get PCH series ASCII string.
+
+ @retval PCH Series string
+**/
+CHAR8*
+PchGetSeriesStr (
+ VOID
+ )
+{
+ switch (PchSeries ()) {
+
+ case PCH_LP:
+ return "TGL PCH-LP";
+
+ default:
+ return NULL;
+ }
+}
+
+/**
+ Get Pch Maximum Pcie Clock Number
+
+ @retval Pch Maximum Pcie Clock Number
+**/
+UINT8
+GetPchMaxPcieClockNum (
+ VOID
+ )
+{
+ return 7;
+}
+
+/**
+ Get Pch Maximum Pcie ClockReq Number
+
+ @retval Pch Maximum Pcie ClockReq Number
+**/
+UINT8
+GetPchMaxPcieClockReqNum (
+ VOID
+ )
+{
+ return GetPchMaxPcieClockNum ();
+}
+
+/**
+ Get Pch Maximum Type C Port Number
+
+ @retval Pch Maximum Type C Port Number
+**/
+UINT8
+GetPchMaxTypeCPortNum (
+ VOID
+ )
+{
+ switch (PchSeries ()) {
+ case PCH_LP:
+ return 4;
+ default:
+ return 0;
+ }
+}
+
+/**
+ Check whether integrated LAN controller is supported by PCH Series.
+
+ @retval TRUE GbE is supported in current PCH
+ @retval FALSE GbE is not supported on current PCH
+**/
+BOOLEAN
+PchIsGbeSupported (
+ VOID
+ )
+{
+ return TRUE;
+}
+
+/**
+ Check whether integrated TSN is supported by PCH Series.
+
+ @retval TRUE TSN is supported in current PCH
+ @retval FALSE TSN is not supported on current PCH
+**/
+BOOLEAN
+PchIsTsnSupported (
+ VOID
+ )
+{
+#if FixedPcdGet8(PcdEmbeddedEnable) == 0x1
+ return TRUE;
+#else
+ return FALSE;
+#endif
+}
+
+/**
+ Check whether ISH is supported by PCH Series.
+
+ @retval TRUE ISH is supported in current PCH
+ @retval FALSE ISH is not supported on current PCH
+**/
+BOOLEAN
+PchIsIshSupported (
+ VOID
+ )
+{
+ return TRUE;
+}
+
+/**
+ Get Pch Maximum Pcie Root Port Number
+
+ @retval Pch Maximum Pcie Root Port Number
+**/
+UINT8
+GetPchMaxPciePortNum (
+ VOID
+ )
+{
+ switch (PchSeries ()) {
+ case PCH_LP:
+ return 12;
+ default:
+ return 0;
+ }
+}
+
+/**
+ Get Pch Maximum Hda Dmic Link
+
+ @retval Pch Maximum Hda Dmic Link
+**/
+UINT8
+GetPchHdaMaxDmicLinkNum (
+ VOID
+ )
+{
+ return 2;
+}
+
+/**
+ Get Pch Maximum Hda Sndw Link
+
+ @retval Pch Maximum Hda Sndw Link
+**/
+UINT8
+GetPchHdaMaxSndwLinkNum (
+ VOID
+ )
+{
+ return 4;
+}
+
+/**
+ Get Pch Maximum Hda Ssp Link
+
+ @retval Pch Maximum Hda Ssp Link
+**/
+UINT8
+GetPchHdaMaxSspLinkNum (
+ VOID
+ )
+{
+ return 3;
+}
+
+/**
+ Check if given Audio Interface is supported
+
+ @param[in] AudioLinkType Link type support to be checked
+ @param[in] AudioLinkIndex Link number
+
+ @retval TRUE Link supported
+ @retval FALSE Link not supported
+**/
+BOOLEAN
+IsAudioInterfaceSupported (
+ IN HDAUDIO_LINK_TYPE AudioLinkType,
+ IN UINT32 AudioLinkIndex
+ )
+{
+ //
+ // Interfaces supported:
+ // 1. HDA Link (SDI0/SDI1)
+ // 2. Display Audio Link (SDI2)
+ // 3. SSP[0-5]
+ // 4. SNDW[1-4]
+ //
+ switch (AudioLinkType) {
+ case HdaLink:
+ case HdaIDispLink:
+ return TRUE;
+ case HdaDmic:
+ if (AudioLinkIndex < 2) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+ case HdaSsp:
+ if (AudioLinkIndex < 6) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+ case HdaSndw:
+ if (AudioLinkIndex < 1) {
+ return TRUE;
+ } else if (AudioLinkIndex < 4) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+ default:
+ return FALSE;
+ }
+}
+
+/**
+ Check if given Display Audio Link T-Mode is supported
+
+ @param[in] Tmode T-mode support to be checked
+
+ @retval TRUE T-mode supported
+ @retval FALSE T-mode not supported
+**/
+BOOLEAN
+IsAudioIDispTmodeSupported (
+ IN HDAUDIO_IDISP_TMODE Tmode
+ )
+{
+ //
+ // iDisplay Audio Link T-mode support per PCH Generation/Series:
+ // 1. 2T - TGL-LP/H/N
+ // 2. 4T - TGL-LP (default), TGL-H, TGL-N
+ // 3. 8T - TGL-H, TGL-N (default)
+ // 4. 16T - TGL-H, TGL-N (not-POR)
+ //
+ switch (Tmode) {
+ case HdaIDispMode1T:
+ return FALSE;
+ case HdaIDispMode2T:
+ case HdaIDispMode4T:
+ case HdaIDispMode8T:
+ return TRUE;
+ case HdaIDispMode16T:
+ return FALSE;
+ default:
+ return FALSE;
+ }
+}
+
+/**
+Get Pch Usb2 Maximum Physical Port Number
+
+@retval Pch Usb2 Maximum Physical Port Number
+**/
+UINT8
+GetPchUsb2MaxPhysicalPortNum(
+ VOID
+ )
+{
+ switch (PchSeries()) {
+ case PCH_LP:
+ return 10;
+ default:
+ return 0;
+ }
+}
+
+/**
+Get Pch Maximum Usb2 Port Number of XHCI Controller
+
+@retval Pch Maximum Usb2 Port Number of XHCI Controller
+**/
+UINT8
+GetPchXhciMaxUsb2PortNum(
+ VOID
+ )
+{
+ switch (PchSeries()) {
+ case PCH_LP:
+ return 12;
+ default:
+ return 0;
+ }
+}
+
+/**
+Get Pch Maximum Usb3 Port Number of XHCI Controller
+
+@retval Pch Maximum Usb3 Port Number of XHCI Controller
+**/
+UINT8
+GetPchXhciMaxUsb3PortNum(
+ VOID
+ )
+{
+ switch (PchSeries()) {
+ case PCH_LP:
+ return 4;
+ default:
+ return 0;
+ }
+}
+
+/**
+ Gets the maximum number of UFS controller supported by this chipset.
+
+ @return Number of supported UFS controllers
+**/
+UINT8
+PchGetMaxUfsNum (
+ VOID
+ )
+{
+ return 2;
+}
+
+/**
+ Check if this chipset supports eMMC controller
+
+ @retval BOOLEAN TRUE if supported, FALSE otherwise
+**/
+BOOLEAN
+IsPchEmmcSupported (
+ VOID
+ )
+{
+ return FALSE;
+}
+
+/**
+ Check if this chipset supports SD controller
+
+ @retval BOOLEAN TRUE if supported, FALSE otherwise
+**/
+BOOLEAN
+IsPchSdCardSupported (
+ VOID
+ )
+{
+ return FALSE;
+}
+
+/**
+ Check if this chipset supports THC controller
+
+ @retval BOOLEAN TRUE if supported, FALSE otherwise
+**/
+BOOLEAN
+IsPchThcSupported (
+ VOID
+ )
+{
+ return TRUE;
+}
+
+/**
+ Check if this chipset supports HSIO BIOS Sync
+
+ @retval BOOLEAN TRUE if supported, FALSE otherwise
+**/
+BOOLEAN
+IsPchChipsetInitSyncSupported (
+ VOID
+ )
+{
+ return TRUE;
+}
+
+/**
+ Check if link between PCH and CPU is an P-DMI
+
+ @retval TRUE P-DMI link
+ @retval FALSE Not an P-DMI link
+**/
+BOOLEAN
+IsPchWithPdmi (
+ VOID
+ )
+{
+ return FALSE;
+}
+
+/**
+ Check whether ATX Shutdown (PS_ON) is supported.
+
+ @retval TRUE ATX Shutdown (PS_ON) is supported in PCH
+ @retval FALSE ATX Shutdown (PS_ON) is not supported by PCH
+**/
+BOOLEAN
+IsPchPSOnSupported (
+ VOID
+ )
+{
+ return FALSE;
+}
+
+/**
+ Check if link between PCH and CPU is an OP-DMI
+
+ @retval TRUE OP-DMI link
+ @retval FALSE Not an OP-DMI link
+**/
+BOOLEAN
+IsPchWithOpdmi (
+ VOID
+ )
+{
+ return TRUE;
+}
+
+/**
+ Check if link between PCH and CPU is an F-DMI
+
+ @retval TRUE F-DMI link
+ @retval FALSE Not an F-DMI link
+**/
+BOOLEAN
+IsPchWithFdmi (
+ VOID
+ )
+{
+ return FALSE;
+}
+/**
+ Get Pch Maximum ISH UART Controller number
+
+ @retval Pch Maximum ISH UART controllers number
+**/
+UINT8
+GetPchMaxIshUartControllersNum (
+ VOID
+ )
+{
+ return 2;
+}
+
+/**
+ Get Pch Maximum ISH I2C Controller number
+
+ @retval Pch Maximum ISH I2C controllers number
+**/
+UINT8
+GetPchMaxIshI2cControllersNum (
+ VOID
+ )
+{
+ return 3;
+}
+
+/**
+ Get Pch Maximum ISH I3C Controller number
+
+ @retval Pch Maximum ISH I3C controllers number
+**/
+UINT8
+GetPchMaxIshI3cControllersNum (
+ VOID
+ )
+{
+ return 0;
+}
+
+/**
+ Get Pch Maximum ISH SPI Controller number
+
+ @retval Pch Maximum ISH SPI controllers number
+**/
+UINT8
+GetPchMaxIshSpiControllersNum (
+ VOID
+ )
+{
+ return 1;
+}
+
+/**
+ Get Pch Maximum ISH SPI Controller Cs pins number
+
+ @retval Pch Maximum ISH SPI controller Cs pins number
+**/
+UINT8
+GetPchMaxIshSpiControllerCsPinsNum (
+ VOID
+ )
+{
+ return 1;
+}
+
+/**
+ Get Pch Maximum ISH GP number
+
+ @retval Pch Maximum ISH GP number
+**/
+UINT8
+GetPchMaxIshGpNum (
+ VOID
+ )
+{
+ return 8;
+}
+
+/**
+ Get Pch Maximum Serial IO I2C controllers number
+
+ @retval Pch Maximum Serial IO I2C controllers number
+**/
+UINT8
+GetPchMaxSerialIoI2cControllersNum (
+ VOID
+ )
+{
+ return 6;
+}
+
+/**
+ Get Pch Maximum Serial IO SPI controllers number
+
+ @retval Pch Maximum Serial IO SPI controllers number
+**/
+UINT8
+GetPchMaxSerialIoSpiControllersNum (
+ VOID
+ )
+{
+ return 4;
+}
+
+/**
+ Get Pch Maximum Serial IO UART controllers number
+
+ @retval Pch Maximum Serial IO UART controllers number
+**/
+UINT8
+GetPchMaxSerialIoUartControllersNum (
+ VOID
+ )
+{
+ return 4;
+}
+
+/**
+ Get Pch Maximum Serial IO SPI Chip Selects count
+
+ @retval Pch Maximum Serial IO SPI Chip Selects number
+**/
+UINT8
+GetPchMaxSerialIoSpiChipSelectsNum (
+ VOID
+ )
+{
+ return 2;
+}
+
+/**
+ Get Pch Maximum ME Applet count
+
+ @retval Pch Maximum ME Applet number
+**/
+UINT8
+GetPchMaxMeAppletCount (
+ VOID
+ )
+{
+ return 31;
+}
+
+/**
+ Get Pch Maximum ME Session count
+
+ @retval Pch Maximum ME Sesion number
+**/
+UINT8
+GetPchMaxMeSessionCount (
+ VOID
+ )
+{
+ return 16;
+}
+
+/**
+ Get Pch Maximum THC count
+
+ @retval Pch Maximum THC count number
+**/
+UINT8
+GetPchMaxThcCount (
+ VOID
+ )
+{
+ return 2;
+}
+
+/**
+ Returns a frequency of the sosc_clk signal.
+ All SATA controllers on the system are assumed to
+ work on the same sosc_clk frequency.
+
+ @retval Frequency of the sosc_clk signal.
+**/
+SATA_SOSC_CLK_FREQ
+GetSataSoscClkFreq (
+ VOID
+ )
+{
+ return SataSosc100Mhz;
+}
+
+/**
+ Check if SATA support should be awake after function disable
+
+ @retval TRUE
+ @retval FALSE
+**/
+BOOLEAN
+IsSataSupportWakeAfterFunctionDisable (
+ VOID
+ )
+{
+ return TRUE;
+}
+
+/**
+ Returns USB2 PHY Reference Clock frequency value used by PCH
+ This defines what electrical tuning parameters shall be used
+ during USB2 PHY initialization programming
+
+ @retval Frequency reference clock for USB2 PHY
+**/
+USB2_PHY_REF_FREQ
+GetUsb2PhyRefFreq (
+ VOID
+ )
+{
+ return FREQ_19_2;
+}
+
+/**
+ Check if SPI in a given PCH generation supports an Extended BIOS Range Decode
+
+ @retval TRUE or FALSE if PCH supports Extended BIOS Range Decode
+**/
+BOOLEAN
+IsExtendedBiosRangeDecodeSupported (
+ VOID
+ )
+{
+ return TRUE;
+}
+
+#define SPI_PCH_LP_DMI_TARGET 0x23A8
+
+/**
+ Returns DMI target for current PCH SPI
+
+ @retval PCH SPI DMI target value
+**/
+UINT16
+GetPchSpiDmiTarget (
+ VOID
+ )
+{
+ return SPI_PCH_LP_DMI_TARGET;
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PeiDxeSmmPchInfoLibTgl.inf b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PeiDxeSmmPchInfoLibTgl.inf
new file mode 100644
index 0000000000..4b3fb988d2
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/Library/PeiDxeSmmPchInfoLib/PeiDxeSmmPchInfoLibTgl.inf
@@ -0,0 +1,43 @@
+## @file
+# PCH information library for TigerLake PCH.
+#
+# All function in this library is available for PEI, DXE, and SMM,
+# But do not support UEFI RUNTIME environment call.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiDxeSmmPchInfoLibTgl
+FILE_GUID = 253B9BFC-026F-4BB4-AC2C-AC167BC0F43C
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = PchInfoLib
+
+
+[LibraryClasses]
+BaseLib
+IoLib
+DebugLib
+PrintLib
+PciSegmentLib
+PchPcrLib
+PcdLib
+PchPciBdfLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+TigerlakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+PchInfoLib.c
+PchInfoLibTgl.c
+
+[Pcd]
+gSiPkgTokenSpaceGuid.PcdEmbeddedEnable ## CONSUMES
--
2.24.0.windows.2
^ permalink raw reply related [flat|nested] 42+ messages in thread
* [Patch V3 33/40] TigerlakeSiliconPkg/Pch: Add Pch private library instances
2021-02-05 7:40 [Patch V3 01/40] TigerlakeSiliconPkg: Add package and Include/ConfigBlock headers Heng Luo
` (30 preceding siblings ...)
2021-02-05 7:40 ` [Patch V3 32/40] TigerlakeSiliconPkg/Pch: Add Pch " Heng Luo
@ 2021-02-05 7:40 ` Heng Luo
2021-02-05 7:40 ` [Patch V3 34/40] TigerlakeSiliconPkg/SystemAgent: Add Acpi Tables and " Heng Luo
` (6 subsequent siblings)
38 siblings, 0 replies; 42+ messages in thread
From: Heng Luo @ 2021-02-05 7:40 UTC (permalink / raw)
To: devel; +Cc: Sai Chaganty, Nate DeSimone
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3171
Adds the following files:
* Pch/LibraryPrivate/BaseSiScheduleResetLib
* Pch/LibraryPrivate/SmmPchPrivateLib
Cc: Sai Chaganty <rangasai.v.chaganty@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Signed-off-by: Heng Luo <heng.luo@intel.com>
---
Silicon/Intel/TigerlakeSiliconPkg/Pch/LibraryPrivate/BaseSiScheduleResetLib/BaseSiScheduleResetLib.c | 171 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/LibraryPrivate/BaseSiScheduleResetLib/BaseSiScheduleResetLib.inf | 37 +++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/LibraryPrivate/SmmPchPrivateLib/SmmPchPrivateLib.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/LibraryPrivate/SmmPchPrivateLib/SmmPchPrivateLib.inf | 31 +++++++++++++++++++++++++++++++
4 files changed, 296 insertions(+)
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/LibraryPrivate/BaseSiScheduleResetLib/BaseSiScheduleResetLib.c b/Silicon/Intel/TigerlakeSiliconPkg/Pch/LibraryPrivate/BaseSiScheduleResetLib/BaseSiScheduleResetLib.c
new file mode 100644
index 0000000000..1880244a01
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/LibraryPrivate/BaseSiScheduleResetLib/BaseSiScheduleResetLib.c
@@ -0,0 +1,171 @@
+/** @file
+ Reset scheduling library services
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include <Library/DebugLib.h>
+#include <Library/ResetSystemLib.h>
+#include <Uefi/UefiBaseType.h>
+#include <Uefi.h>
+#include <Pi/PiMultiPhase.h>
+#include <Library/HobLib.h>
+#include <PchResetPlatformSpecific.h>
+#include <Library/SiScheduleResetLib.h>
+#include <SiScheduleResetHob.h>
+
+/**
+ This function returns SiScheduleResetHob for library use
+**/
+STATIC
+SI_SCHEDULE_RESET_HOB *
+SiScheduleGetResetData (
+ VOID
+ )
+{
+ STATIC SI_SCHEDULE_RESET_HOB *SiScheduleResetHob = NULL;
+ SI_SCHEDULE_RESET_HOB *SiScheduleResetHobTemp;
+ VOID *HobPtr;
+
+ if (SiScheduleResetHob != NULL) {
+ return SiScheduleResetHob;
+ }
+
+ HobPtr = GetFirstGuidHob (&gSiScheduleResetHobGuid);
+ if (HobPtr == NULL) {
+ SiScheduleResetHobTemp = BuildGuidHob (&gSiScheduleResetHobGuid, sizeof (SI_SCHEDULE_RESET_HOB));
+ if (SiScheduleResetHobTemp == NULL) {
+ ASSERT (FALSE);
+ return SiScheduleResetHobTemp;
+ }
+ SiScheduleResetHobTemp->ResetType = 0xFF;
+ DEBUG ((DEBUG_INFO, "SiScheduleResetSetType : Init SiScheduleResetHob\n"));
+ } else {
+ SiScheduleResetHobTemp = (SI_SCHEDULE_RESET_HOB*) GET_GUID_HOB_DATA (HobPtr);
+ }
+ SiScheduleResetHob = SiScheduleResetHobTemp;
+ return SiScheduleResetHobTemp;
+}
+
+/**
+ This function updates the reset information in SiScheduleResetHob
+ @param[in] ResetType UEFI defined reset type.
+ @param[in] ResetData Optional element used to introduce a platform specific reset.
+ The exact type of the reset is defined by the EFI_GUID that follows
+ the Null-terminated Unicode string.
+**/
+VOID
+SiScheduleResetSetType (
+ IN EFI_RESET_TYPE ResetType,
+ IN PCH_RESET_DATA *ResetData OPTIONAL
+ )
+{
+ SI_SCHEDULE_RESET_HOB *SiScheduleResetHob;
+ if (ResetType > EfiResetPlatformSpecific) {
+ DEBUG ((DEBUG_INFO, "Unsupported Reset Type Requested\n"));
+ return;
+ }
+ SiScheduleResetHob = SiScheduleGetResetData ();
+ if (SiScheduleResetHob == NULL) {
+ return;
+ }
+ DEBUG ((DEBUG_INFO, "SiScheduleResetSetType : Current Reset Type = 0x%x\n", SiScheduleResetHob->ResetType));
+ if (SiScheduleResetHob->ResetType == ResetType) {
+ DEBUG ((DEBUG_INFO, "Current Reset Type is same as requested Reset Type\n"));
+ return;
+ }
+ if (SiScheduleResetHob->ResetType == 0xFF) {
+ // Init Reset Type to lowest ResetType
+ SiScheduleResetHob->ResetType = EfiResetWarm;
+ }
+ //
+ // ResetType Priority set as : ResetPlatformSpecific(3) > ResetShutdown(2) > ResetCold(0) > ResetWarm(1)
+ //
+ switch (ResetType) {
+ case EfiResetWarm:
+ break;
+
+ case EfiResetCold:
+ if (SiScheduleResetHob->ResetType == EfiResetWarm) {
+ SiScheduleResetHob->ResetType = ResetType;
+ }
+ break;
+
+ case EfiResetShutdown:
+ if (SiScheduleResetHob->ResetType < ResetType)
+ SiScheduleResetHob->ResetType = ResetType;
+ break;
+
+ case EfiResetPlatformSpecific:
+ SiScheduleResetHob->ResetType = ResetType;
+ SiScheduleResetHob->ResetData = *ResetData;
+ break;
+ }
+ DEBUG ((DEBUG_INFO, "SiScheduleResetSetType : New Reset Type = 0x%x\n", SiScheduleResetHob->ResetType));
+}
+
+/**
+ This function returns TRUE or FALSE depending on whether a reset is required based on SiScheduleResetHob
+
+ @retval BOOLEAN The function returns FALSE if no reset is required
+**/
+BOOLEAN
+SiScheduleResetIsRequired (
+ VOID
+ )
+{
+ VOID *HobPtr;
+
+ HobPtr = NULL;
+ HobPtr = GetFirstGuidHob (&gSiScheduleResetHobGuid);
+ if (HobPtr == NULL) {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**
+ This function performs reset based on SiScheduleResetHob
+
+ @retval BOOLEAN The function returns FALSE if no reset is required
+**/
+BOOLEAN
+SiScheduleResetPerformReset (
+ VOID
+ )
+{
+ UINTN DataSize;
+ SI_SCHEDULE_RESET_HOB *SiScheduleResetHob;
+
+ if (!SiScheduleResetIsRequired ()) {
+ return FALSE;
+ }
+ SiScheduleResetHob = SiScheduleGetResetData ();
+
+ if (SiScheduleResetHob == NULL) {
+ return TRUE;
+ }
+
+ DEBUG ((DEBUG_INFO, "SiScheduleResetPerformReset : Reset Type = 0x%x\n", SiScheduleResetHob->ResetType));
+ switch (SiScheduleResetHob->ResetType) {
+ case EfiResetWarm:
+ ResetWarm ();
+ break;
+
+ case EfiResetCold:
+ ResetCold ();
+ break;
+
+ case EfiResetShutdown:
+ ResetShutdown ();
+ break;
+
+ case EfiResetPlatformSpecific:
+ DataSize = sizeof (PCH_RESET_DATA);
+ ResetPlatformSpecific (DataSize, &SiScheduleResetHob->ResetData);
+ break;
+ }
+ // Code should never reach here
+ ASSERT (FALSE);
+ return TRUE;
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/LibraryPrivate/BaseSiScheduleResetLib/BaseSiScheduleResetLib.inf b/Silicon/Intel/TigerlakeSiliconPkg/Pch/LibraryPrivate/BaseSiScheduleResetLib/BaseSiScheduleResetLib.inf
new file mode 100644
index 0000000000..4363a752a9
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/LibraryPrivate/BaseSiScheduleResetLib/BaseSiScheduleResetLib.inf
@@ -0,0 +1,37 @@
+## @file
+# Component description file for Si Reset Schedule Library.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = BaseSiScheduleResetLib
+FILE_GUID = E6F3D551-36C0-4737-80C7-47FC57593163
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = SiScheduleResetLib
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF
+#
+
+[LibraryClasses]
+BaseLib
+IoLib
+DebugLib
+HobLib
+ResetSystemLib
+
+[Packages]
+MdePkg/MdePkg.dec
+TigerlakeSiliconPkg/SiPkg.dec
+
+[Guids]
+gSiScheduleResetHobGuid
+
+[Sources]
+BaseSiScheduleResetLib.c
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/LibraryPrivate/SmmPchPrivateLib/SmmPchPrivateLib.c b/Silicon/Intel/TigerlakeSiliconPkg/Pch/LibraryPrivate/SmmPchPrivateLib/SmmPchPrivateLib.c
new file mode 100644
index 0000000000..46cf735860
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/LibraryPrivate/SmmPchPrivateLib/SmmPchPrivateLib.c
@@ -0,0 +1,57 @@
+/** @file
+ PCH SMM private lib.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Uefi/UefiBaseType.h>
+#include <Library/BaseLib.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Register/CommonMsr.h>
+
+/**
+ Set InSmm.Sts bit
+**/
+VOID
+PchSetInSmmSts (
+ VOID
+ )
+{
+ UINT32 Data32;
+
+
+ ///
+ /// Read memory location FED30880h OR with 00000001h, place the result in EAX,
+ /// and write data to lower 32 bits of MSR 1FEh (sample code available)
+ ///
+ Data32 = MmioRead32 (0xFED30880);
+ AsmWriteMsr32 (MSR_SPCL_CHIPSET_USAGE, Data32 | BIT0);
+ ///
+ /// Read FED30880h back to ensure the setting went through.
+ ///
+ Data32 = MmioRead32 (0xFED30880);
+}
+
+/**
+ Clear InSmm.Sts bit
+**/
+VOID
+PchClearInSmmSts (
+ VOID
+ )
+{
+ UINT32 Data32;
+
+ ///
+ /// Read memory location FED30880h AND with FFFFFFFEh, place the result in EAX,
+ /// and write data to lower 32 bits of MSR 1FEh (sample code available)
+ ///
+ Data32 = MmioRead32 (0xFED30880);
+ AsmWriteMsr32 (MSR_SPCL_CHIPSET_USAGE, Data32 & (UINT32) (~BIT0));
+ ///
+ /// Read FED30880h back to ensure the setting went through.
+ ///
+ Data32 = MmioRead32 (0xFED30880);
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/LibraryPrivate/SmmPchPrivateLib/SmmPchPrivateLib.inf b/Silicon/Intel/TigerlakeSiliconPkg/Pch/LibraryPrivate/SmmPchPrivateLib/SmmPchPrivateLib.inf
new file mode 100644
index 0000000000..6d4c3a5729
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/LibraryPrivate/SmmPchPrivateLib/SmmPchPrivateLib.inf
@@ -0,0 +1,31 @@
+## @file
+# PCH SMM private lib.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = SmmPchPrivateLib
+FILE_GUID = FE6495FB-7AA9-4A24-BF3E-4698F7BCE0EE
+VERSION_STRING = 1.0
+MODULE_TYPE = DXE_SMM_DRIVER
+LIBRARY_CLASS = SmmPchPrivateLib
+
+
+[LibraryClasses]
+BaseLib
+IoLib
+DebugLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+TigerlakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+SmmPchPrivateLib.c
--
2.24.0.windows.2
^ permalink raw reply related [flat|nested] 42+ messages in thread
* [Patch V3 34/40] TigerlakeSiliconPkg/SystemAgent: Add Acpi Tables and library instances
2021-02-05 7:40 [Patch V3 01/40] TigerlakeSiliconPkg: Add package and Include/ConfigBlock headers Heng Luo
` (31 preceding siblings ...)
2021-02-05 7:40 ` [Patch V3 33/40] TigerlakeSiliconPkg/Pch: Add Pch private " Heng Luo
@ 2021-02-05 7:40 ` Heng Luo
2021-02-05 7:40 ` [Patch V3 35/40] TigerlakeSiliconPkg/Fru/TglCpu: Add CpuPcieRp and Vtd " Heng Luo
` (5 subsequent siblings)
38 siblings, 0 replies; 42+ messages in thread
From: Heng Luo @ 2021-02-05 7:40 UTC (permalink / raw)
To: devel; +Cc: Sai Chaganty, Nate DeSimone
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3171
Adds the following files:
* SystemAgent/AcpiTables
* SystemAgent/Library/DxeSaPolicyLib
* SystemAgent/Library/PeiDxeSmmSaPlatformLib
Cc: Sai Chaganty <rangasai.v.chaganty@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Signed-off-by: Heng Luo <heng.luo@intel.com>
---
Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/CpuPcieRp.asl | 252 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/CpuPcieRpCommon.asl | 289 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/PegCommon.asl | 1344 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/PegRtd3.asl | 124 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/Sa.asl | 26 ++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/SaSsdt.asl | 20 ++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/SaSsdt.inf | 22 +++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/Library/DxeSaPolicyLib/DxeSaPolicyLib.c | 254 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/Library/DxeSaPolicyLib/DxeSaPolicyLib.inf | 48 ++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/Library/DxeSaPolicyLib/DxeSaPolicyLibrary.h | 33 ++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/Library/PeiDxeSmmSaPlatformLib/PeiDxeSmmSaPlatformLib.inf | 32 ++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/Library/PeiDxeSmmSaPlatformLib/SaPlatformLibrary.c | 68 +++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/Library/PeiDxeSmmSaPlatformLib/SaPlatformLibrary.h | 21 ++++++++++++++
13 files changed, 2533 insertions(+)
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/CpuPcieRp.asl b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/CpuPcieRp.asl
new file mode 100644
index 0000000000..0babf047ed
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/CpuPcieRp.asl
@@ -0,0 +1,252 @@
+/** @file
+ This file contains the CPU PCIe Root Port configuration
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+External(LTRX) // CPU PCIe Root Port 0 Latency Tolerance Reporting Enable
+External(LTRY) // CPU PCIe Root Port 1 Latency Tolerance Reporting Enable
+External(LTRZ) // CPU PCIe Root Port 2 Latency Tolerance Reporting Enable
+External(LTRW) // CPU PCIe Root Port 3 Latency Tolerance Reporting Enable
+External(SMSL) // CPU PCIe Root Port Latency Tolerance Reporting Max Snoop Latency
+External(SNSL) // CPU PCIe Root Port Latency Tolerance Reporting Max No Snoop Latency
+External(PG0E) // CpuPcieRp0Enable <b>0: Disable</b>; 1: Enable
+External(PG1E) // CpuPcieRp1Enable <b>0: Disable</b>; 1: Enable
+External(PG2E) // CpuPcieRp2Enable <b>0: Disable</b>; 1: Enable
+External(PG3E) // CpuPcieRp3Enable <b>0: Disable</b>; 1: Enable
+External(\_SB.PC00.PEG0, DeviceObj)
+External(\_SB.PC00.PEG1, DeviceObj)
+External(\_SB.PC00.PEG2, DeviceObj)
+External(\_SB.PC00.PEG3, DeviceObj)
+External(\_SB.PC00.PEG0.PEGP, DeviceObj)
+External(\_SB.PC00.PEG1.PEGP, DeviceObj)
+External(\_SB.PC00.PEG2.PEGP, DeviceObj)
+External(\_SB.PC00.PEG3.PEGP, DeviceObj)
+External(\AR02)
+External(\PD02)
+External(\AR0A)
+External(\PD0A)
+External(\AR0B)
+External(\PD0B)
+External(\AR0C)
+External(\PD0C)
+External(VMDE)
+External(VMCP)
+External(MPGN)
+External(PBR1)
+External(PBR2)
+External(PBR3)
+
+Scope (\_SB.PC00.PEG0) {
+
+ Name(SLOT, 0) // CPU PCIe root port index 0 corresponds to PEG60 (0/6/0)
+
+ Method (_STA, 0x0, NotSerialized) {
+ if(PG0E == 1) { // If CPU PCIe RP0 enabled?
+ Return(0x0F)
+ }
+ Return(0x00)
+ }
+
+ Name(LTEN, 0)
+ Name(LMSL, 0)
+ Name(LNSL, 0)
+
+ Method(_INI)
+ {
+ Store (LTRX, LTEN)
+ Store (SMSL, LMSL)
+ Store (SNSL, LNSL)
+ If(LAnd(CondRefOf(VMCP),CondRefOf(VMDE))) {
+ If(LAnd(LEqual(VMDE,1),LNotEqual(And(VMCP,0x8),0))) {
+ Store (1, CPMV)
+ }
+ }
+ }
+
+ Method(_PRT,0) {
+ If(PICM) {
+ Return(AR02)
+ } // APIC mode
+ Return (PD02) // PIC Mode
+ } // end _PRT
+
+ Include("CpuPcieRpCommon.asl")
+} // PEG0 scope end
+
+Scope (\_SB.PC00.PEG1) {
+
+ Name(SLOT, 1) // CPU PCIe root port index 1 corresponds to PEG10 (0/1/0)
+
+ Method (_STA, 0x0, NotSerialized) {
+ if(PG1E == 1) { // If CPU PCIe RP1 enabled?
+ Return(0x0F)
+ }
+ Return(0x00)
+ }
+
+ Name(LTEN, 0)
+ Name(LMSL, 0)
+ Name(LNSL, 0)
+
+ Method(_INI)
+ {
+ Store (LTRY, LTEN)
+ Store (SMSL, LMSL)
+ Store (SNSL, LNSL)
+ If(LAnd(CondRefOf(VMCP),CondRefOf(VMDE))) {
+ If(LAnd(LEqual(VMDE,1),LNotEqual(And(VMCP,0x1),0))) {
+ Store (1, CPMV)
+ }
+ }
+ }
+
+ Method(_PRT,0) {
+ If(PICM) {
+ Return(AR0A)
+ } // APIC mode
+ Return (PD0A) // PIC Mode
+ } // end _PRT
+
+ Include("CpuPcieRpCommon.asl")
+} // PEG1 scope end
+
+Scope (\_SB.PC00.PEG2) {
+
+ Name(SLOT, 2) // CPU PCIe root port index 2 corresponds to PEG11 (0/1/1)
+
+ Method (_STA, 0x0, NotSerialized) {
+ if(PG2E == 1) { // If CPU PCIe RP2 enabled?
+ Return(0x0F)
+ }
+ Return(0x00)
+ }
+
+ Name(LTEN, 0)
+ Name(LMSL, 0)
+ Name(LNSL, 0)
+
+ Method(_INI)
+ {
+ Store (LTRZ, LTEN)
+ Store (SMSL, LMSL)
+ Store (SNSL, LNSL)
+ If(LAnd(CondRefOf(VMCP),CondRefOf(VMDE))) {
+ If(LAnd(LEqual(VMDE,1),LNotEqual(And(VMCP,0x2),0))) {
+ Store (1, CPMV)
+ }
+ }
+ }
+
+ Method(_PRT,0) {
+ If(PICM) {
+ Return(AR0B)
+ } // APIC mode
+ Return (PD0B) // PIC Mode
+ } // end _PRT
+
+ Include("CpuPcieRpCommon.asl")
+} // PEG2 scope end
+
+If (CondRefOf(\_SB.PC00.PEG3)) {
+ Scope (\_SB.PC00.PEG3) {
+
+ Name(SLOT, 3) // CPU PCIe root port index 3 corresponds to PEG12 (0/1/2)
+
+ Method (_STA, 0x0, NotSerialized) {
+ if(PG3E == 1) { // If CPU PCIe RP3 enabled?
+ Return(0x0F)
+ }
+ Return(0x00)
+ }
+
+ Name(LTEN, 0)
+ Name(LMSL, 0)
+ Name(LNSL, 0)
+
+ Method(_INI)
+ {
+ Store (LTRW, LTEN)
+ Store (SMSL, LMSL)
+ Store (SNSL, LNSL)
+ If(LAnd(CondRefOf(VMCP),CondRefOf(VMDE))) {
+ If(LAnd(LEqual(VMDE,1),LNotEqual(And(VMCP,0x4),0))) {
+ Store (1, CPMV)
+ }
+ }
+ }
+
+ Method(_PRT,0) {
+ If(PICM) {
+ Return(AR0C)
+ } // APIC mode
+ Return (PD0C) // PIC Mode
+ } // end _PRT
+
+ Include("CpuPcieRpCommon.asl")
+ } // PEG3 scope end
+}
+
+Scope(\_SB.PC00.PEG0.PEGP) {
+ Method(_PRW, 0) {
+ Return(GPRW(0x69, 4)) // can wakeup from S4 state
+ }
+}
+
+
+If (PBR1) {
+ Scope(\_SB.PC00.PEG1.PEGP) {
+ Method(_S0W, 0) { Return(4)} //D3cold is supported
+
+ Device (PEGD) {
+ Method(_S0W, 0) { Return(4)} //D3cold is supported
+ Name(_ADR, 0x00000000)
+ Method(_PRW, 0) { Return(GPRW(0x69, 4)) } // can wakeup from S4 state
+ }
+ } // end "P.E.G. Port Slot x16"
+}
+
+Scope(\_SB.PC00.PEG1.PEGP) {
+ Method(_PRW, 0) {
+ Return(GPRW(0x69, 4)) // can wakeup from S4 state
+ }
+}
+
+
+If (PBR2) {
+ Scope(\_SB.PC00.PEG2.PEGP) {
+ Method(_S0W, 0) { Return(4)} //D3cold is supported
+
+ Device (PEGD) {
+ Method(_S0W, 0) { Return(4)} //D3cold is supported
+ Name(_ADR, 0x00000000)
+ Method(_PRW, 0) { Return(GPRW(0x69, 4)) } // can wakeup from S4 state
+ }
+ } // end "P.E.G. Port Slot 2x8"
+}
+
+Scope(\_SB.PC00.PEG2.PEGP) {
+ Method(_PRW, 0) {
+ Return(GPRW(0x69, 4)) // can wakeup from S4 state
+ }
+}
+
+If (PBR3) {
+ Scope(\_SB.PC00.PEG3.PEGP) {
+ Method(_S0W, 0) { Return(4)} //D3cold is supported
+
+ Device (PEGD) {
+ Method(_S0W, 0) { Return(4)} //D3cold is supported
+ Name(_ADR, 0x00000000)
+ Method(_PRW, 0) { Return(GPRW(0x69, 4)) } // can wakeup from S4 state
+ }
+ } // end "P.E.G. Port Slot 1x8 - 2x4"
+}
+
+If (CondRefOf(\_SB.PC00.PEG3)) {
+ Scope(\_SB.PC00.PEG3.PEGP) {
+ Method(_PRW, 0) {
+ Return(GPRW(0x69, 4)) // can wakeup from S4 state
+ }
+ }
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/CpuPcieRpCommon.asl b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/CpuPcieRpCommon.asl
new file mode 100644
index 0000000000..81f785dfc5
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/CpuPcieRpCommon.asl
@@ -0,0 +1,289 @@
+/** @file
+ This file contains the CPU PCIe Root Port configuration
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+ External(ECR1)
+ External(GPRW, MethodObj)
+ External(PICM)
+ External(\_SB.PC00.PC2M, MethodObj)
+ External(_ADR, IntObj)
+
+
+ OperationRegion(PXCS,SystemMemory,\_SB.PC00.PC2M(_ADR),0x480)
+ Field(PXCS, AnyAcc, NoLock, Preserve)
+ {
+ Offset(0),
+ VDID, 32,
+ Offset(0x50), // LCTL - Link Control Register
+ L0SE, 1, // 0, L0s Entry Enabled
+ , 3,
+ LDIS, 1,
+ , 3,
+ Offset(0x52), // LSTS - Link Status Register
+ , 13,
+ LASX, 1, // 0, Link Active Status
+ Offset(0x5A), // SLSTS[7:0] - Slot Status Register
+ ABPX, 1, // 0, Attention Button Pressed
+ , 2,
+ PDCX, 1, // 3, Presence Detect Changed
+ , 2,
+ PDSX, 1, // 6, Presence Detect State
+ , 1,
+ Offset(0x60), // RSTS - Root Status Register
+ , 16,
+ PSPX, 1, // 16, PME Status
+ Offset(0xA4),
+ D3HT, 2, // Power State
+ Offset(0xD8), // 0xD8, MPC - Miscellaneous Port Configuration Register
+ , 30,
+ HPEX, 1, // 30, Hot Plug SCI Enable
+ PMEX, 1, // 31, Power Management SCI Enable
+ Offset(0xE0), // 0xE0, SPR - Scratch Pad Register
+ , 0,
+ SCB0, 1, // Sticky Scratch Pad Bit SCB0
+ Offset(0xE2), // 0xE2, RPPGEN - Root Port Power Gating Enable
+ , 2,
+ L23E, 1, // 2, L23_Rdy Entry Request (L23ER)
+ L23R, 1, // 3, L23_Rdy to Detect Transition (L23R2DT)
+ Offset(0x324), // 0x324 - PCIEDBG
+ , 3,
+ LEDM, 1, // PCIEDBG.DMIL1EDM
+ Offset(0x328), // 0x328 - PCIESTS1
+ , 24,
+ LTSM, 8,
+ }
+ Field(PXCS,AnyAcc, NoLock, WriteAsZeros)
+ {
+ Offset(0xDC), // 0xDC, SMSCS - SMI/SCI Status Register
+ , 30,
+ HPSX, 1, // 30, Hot Plug SCI Status
+ PMSX, 1 // 31, Power Management SCI Status
+ }
+
+ //
+ // L23D method recovers link from L2 or L3 state. Used for RTD3 flows, right after endpoint is powered up and exits reset.
+ // This flow is implemented in ASL because rootport registers used for L2/L3 entry/exit
+ // are proprietary and OS drivers don't know about them.
+ //
+ Method (L23D, 0, Serialized) {
+ If(LNotEqual(SCB0,0x1)) {
+ Return()
+ }
+
+ /// Set L23_Rdy to Detect Transition (L23R2DT)
+ Store(1, L23R)
+ Store(0, Local0)
+ /// Wait for transition to Detect
+ While(L23R) {
+ If(Lgreater(Local0, 4))
+ {
+ Break
+ }
+ Sleep(16)
+ Increment(Local0)
+ }
+ Store(0,SCB0)
+
+ /// Once in Detect, wait up to 124 ms for Link Active (typically happens in under 70ms)
+ /// Worst case per PCIe spec from Detect to Link Active is:
+ /// 24ms in Detect (12+12), 72ms in Polling (24+48), 28ms in Config (24+2+2+2+2)
+ Store(0, Local0)
+ While(LEqual(LASX,0)) {
+ If(Lgreater(Local0, 8))
+ {
+ Break
+ }
+ Sleep(16)
+ Increment(Local0)
+ }
+ }
+
+ //
+ // DL23 method puts link to L2 or L3 state. Used for RTD3 flows, before endpoint is powered down.
+ // This flow is implemented in ASL because rootport registers used for L2/L3 entry/exit
+ // are proprietary and OS drivers don't know about them.
+ //
+ Method (DL23, 0, Serialized) {
+ Store(1, L23E)
+ Sleep(16)
+ Store(0, Local0)
+ While(L23E) {
+ If(Lgreater(Local0, 4))
+ {
+ Break
+ }
+ Sleep(16)
+ Increment(Local0)
+ }
+ Store(1,SCB0)
+ }
+
+ Name(LTRV, Package(){0,0,0,0})
+ Name(CPMV, 0) // CPU Rp Mapped under VMD
+
+ //
+ // _DSM Device Specific Method
+ //
+ // Arg0: UUID Unique function identifier
+ // Arg1: Integer Revision Level
+ // Arg2: Integer Function Index (0 = Return Supported Functions)
+ // Arg3: Package Parameters
+ Method(_DSM, 4, Serialized) {
+ //
+ // Switch based on which unique function identifier was passed in
+ //
+ If (LEqual(Arg0, ToUUID ("E5C937D0-3553-4d7a-9117-EA4D19C3434D"))) {
+ //
+ // _DSM Definitions for Latency Tolerance Reporting
+ //
+ // Arguments:
+ // Arg0: UUID: E5C937D0-3553-4d7a-9117-EA4D19C3434D
+ // Arg1: Revision ID: 3
+ // Arg2: Function Index: 0, 6, 8, 9
+ // Arg3: Empty Package
+ //
+ // Switch by function index
+ //
+ Switch(ToInteger(Arg2)) {
+ //
+ // Function Index:0
+ // Standard query - A bitmask of functions supported
+ //
+ Case (0) {
+ Name(OPTS,Buffer(2){0,0})
+ CreateBitField(OPTS,0,FUN0)
+ CreateBitField(OPTS,6,FUN6)
+ CreateBitField(OPTS,8,FUN8)
+ CreateBitField(OPTS,9,FUN9)
+
+ Store(1,FUN0)
+ if(LEqual(LTEN,1)) {
+ Store(1,Fun6)
+ }
+
+ If (LGreaterEqual(Arg1, 2)){ // test Arg1 for Revision ID: 2
+ If(CondRefOf(ECR1)) {
+ if(LEqual(ECR1,1)){
+ if (LGreaterEqual(Arg1, 3)){ // test Arg1 for Revision ID: 3
+ Store(1,Fun8)
+ Store(1,Fun9)
+ }
+ }
+ }
+ }
+ Return (OPTS)
+ }
+
+ //
+ // Function Index: 6
+ // LTR Extended Capability Structure
+ //
+ Case(6) {
+ if (LGreaterEqual(Arg1, 2)){ // test Arg1 for Revision ID: 2
+ Store(And(ShiftRight(LMSL,10),7), Index(LTRV, 0))
+ Store(And(LMSL,0x3FF), Index(LTRV, 1))
+ Store(And(ShiftRight(LNSL,10),7), Index(LTRV, 2))
+ Store(And(LNSL,0x3FF), Index(LTRV, 3))
+ Return (LTRV)
+ }
+ }
+ Case(8) { //ECR ACPI additions for FW latency optimizations, DSM for Avoiding Power-On Reset Delay Duplication on Sx Resume
+ If(CondRefOf(ECR1)) {
+ if(LEqual(ECR1,1)){
+ if (LGreaterEqual(Arg1, 3)) { // test Arg1 for Revision ID: 3
+ return (1)
+ }
+ }
+ }
+ }
+ Case(9) { //ECR ACPI additions for FW latency optimizations, DSM for Specifying Device Readiness Durations
+ If(CondRefOf(ECR1)) {
+ if(LEqual(ECR1,1)){
+ if (LGreaterEqual(Arg1, 3)) { // test Arg1 for Revision ID: 3
+ return(Package(5){50000,Ones,Ones,50000,Ones})
+ }
+ }
+ }
+ }
+ } // End of switch(Arg2)
+ } // End of if
+ return (Buffer() {0x00})
+ } // End of _DSM
+
+ Method(_PRW, 0) {
+ Return(GPRW(0x69, 4)) // can wakeup from S4 state
+ }
+
+ Method(_PS0,0,Serialized)
+ {
+ If (LEqual(HPEX, 1)) {
+ Store(0, HPEX) // Disable Hot Plug SCI
+ Store(1, HPSX) // Clear Hot Plug SCI status
+ }
+ If (LEqual (PMEX, 1)) {
+ Store(0, PMEX) // Disable Power Management SCI
+ Store(1, PMSX) // Clear Power Management SCI status
+ }
+ }
+ Method(_PS3,0,Serialized)
+ {
+ If (LEqual (HPEX, 0)) {
+ Store(1, HPEX) // Enable Hot Plug SCI
+ Store(1, HPSX) // Clear Hot Plug SCI status
+ }
+ If (LEqual(PMEX, 0)) {
+ Store(1, PMEX) // Enable Power Management SCI
+ Store(1, PMSX) // Clear Power Management SCI status
+ }
+ }
+
+ Method (_DSD, 0) {
+ Return (
+ Package () {
+ ToUUID("FDF06FAD-F744-4451-BB64-ECD792215B10"),
+ Package () {
+ Package (2) {"FundamentalDeviceResetTriggeredOnD3ToD0", 1},
+ }
+ }
+ ) // End of Return ()
+ }
+
+ //
+ // PCI_EXP_STS Handler for PCIE Root Port
+ //
+ Method(HPME,0,Serialized) {
+ If(LAnd(LNotEqual(VDID,0xFFFFFFFF), LEqual(PMSX,1))) { //if port exists and has PME SCI Status set...
+ Store(1,PMSX) // clear rootport's PME SCI status
+ Store(1,PSPX) // consume one pending PME status to prevent it from blocking the queue
+ Return(0x01)
+ }
+ Return(0x00)
+ }
+
+ //
+ // Sub-Method of _L61 Hot-Plug event
+ // _L61 event handler should invoke this method to support HotPlug wake event from PEG RP
+ //
+ Method(HPEV,0,Serialized) {
+ If(LAnd(LNotEqual(VDID,0xFFFFFFFF), HPSX)) {
+ // Clear HotPlug SCI event status
+ Store(1, HPSX)
+
+ If(LEqual(PDCX, 1)) {
+ // Clear Presence Detect Changed
+ Store(1,PDCX)
+
+ If(LEqual(PDSX, 0)) {
+ // The PCI Express slot is empty, so disable L0s on hot unplug
+ //
+ Store(0,L0SE)
+ }
+ // Perform proper notification
+ // to the OS.
+ Notify(^,0)
+ }
+ }
+ }
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/PegCommon.asl b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/PegCommon.asl
new file mode 100644
index 0000000000..68b10309d4
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/PegCommon.asl
@@ -0,0 +1,1344 @@
+/** @file
+ This file contains the device definitions of the SystemAgent
+ PCIE ACPI Reference Code.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+External(\_SB.ISME, MethodObj)
+External(\_SB.SHPO, MethodObj)
+External(\_SB.CAGS, MethodObj)
+External(\_SB.GGOV, MethodObj)
+External(\_SB.SGOV, MethodObj)
+External(\_SB.PC00.PEG0, DeviceObj)
+External(\_SB.PC00.PEG1, DeviceObj)
+External(\_SB.PC00.PEG2, DeviceObj)
+External(\_SB.PC00.PEG3, DeviceObj)
+External(\_SB.PC00.PEG0.PPRW, MethodObj)
+External(\_SB.PC00.PEG1.PPRW, MethodObj)
+External(\_SB.PC00.PEG2.PPRW, MethodObj)
+External(\_SB.PC00.PEG3.PPRW, MethodObj)
+External(\_SB.PC00.PC2M, MethodObj)
+External(P8XH, MethodObj)
+External(SPCO, MethodObj)
+External(PINI, MethodObj) // Platform specific PCIe root port initialization
+External(PRES, MethodObj)
+External(GPRW, MethodObj)
+External(\SLOT)
+External(\P0WK)
+External(\P1WK)
+External(\P2WK)
+External(\P3WK)
+External(\XBAS)
+External(\SBN0)
+External(\SBN1)
+External(\SBN2)
+External(\SBN3)
+External(\EECP)
+External(\EEC1)
+External(\EEC2)
+External(\EEC3)
+External(\SGGP)
+External(\HRE0)
+External(\HRG0)
+External(\HRA0)
+External(\PWE0)
+External(\PWG0)
+External(\PWA0)
+External(\P1GP)
+External(\HRE1)
+External(\HRG1)
+External(\HRA1)
+External(\PWE1)
+External(\PWG1)
+External(\PWA1)
+External(\P2GP)
+External(\HRE2)
+External(\HRG2)
+External(\HRA2)
+External(\PWE2)
+External(\PWG2)
+External(\PWA2)
+External(\P3GP)
+External(\HRE3)
+External(\HRG3)
+External(\HRA3)
+External(\PWE3)
+External(\PWG3)
+External(\PWA3)
+External(\P0SC)
+External(\P1SC)
+External(\P2SC)
+External(\P3SC)
+External(\DLPW)
+External(\DLHR)
+External(\OBFX)
+External(\OBFY)
+External(\OBFZ)
+External(\OBFA)
+External(\OSYS)
+
+//GPE Event handling - Start
+Scope(\_GPE) {
+ //
+ // _L6F Method call for PEG0/1/2/3 ports to handle 2-tier RTD3 GPE events
+ //
+ Method(P0L6,0)
+ {
+ // PEG0 Device Wake Event
+ If (\_SB.ISME(P0WK))
+ {
+ \_SB.SHPO(P0WK, 1) // set gpio ownership to driver(0=ACPI mode, 1=GPIO mode)
+ Notify(\_SB.PC00.PEG0, 0x02) // device wake
+ \_SB.CAGS(P0WK) // Clear GPE status bit for PEG0 WAKE
+ }
+ }
+
+ Method(P1L6,0)
+ {
+ // PEG1 Device Wake Event
+ If (\_SB.ISME(P1WK))
+ {
+ \_SB.SHPO(P1WK, 1) // set gpio ownership to driver(0=ACPI mode, 1=GPIO mode)
+ Notify(\_SB.PC00.PEG1, 0x02) // device wake
+ \_SB.CAGS(P1WK) // Clear GPE status bit for PEG1 WAKE
+ }
+ }
+
+ Method(P2L6,0)
+ {
+ // PEG2 Device Wake Event
+ If (\_SB.ISME(P2WK))
+ {
+ \_SB.SHPO(P2WK, 1) // set gpio ownership to driver(0=ACPI mode, 1=GPIO mode)
+ Notify(\_SB.PC00.PEG2, 0x02) // device wake
+ \_SB.CAGS(P2WK) // Clear GPE status bit for PEG2 WAKE
+ }
+ }
+
+ If (CondRefOf(\_SB.PC00.PEG3)) {
+ Method(P3L6,0)
+ {
+ // PEG2 Device Wake Event
+ If (\_SB.ISME(P3WK))
+ {
+ \_SB.SHPO(P3WK, 1) // set gpio ownership to driver(0=ACPI mode, 1=GPIO mode)
+ Notify(\_SB.PC00.PEG3, 0x02) // device wake
+ \_SB.CAGS(P3WK) // Clear GPE status bit for PEG2 WAKE
+ }
+ }
+ }
+} //Scope(\_GPE)
+
+If(LAnd((LEqual(HGMD,2)), (LEqual(HGST,1)))) {
+///
+/// P.E.G. Root Port D6F0
+///
+Scope(\_SB.PC00.PEG0) {
+ Name(WKEN, 0)
+
+ PowerResource(PG00, 0, 0) {
+ Name(_STA, One)
+ Method(_ON, 0, Serialized) {
+ If(LGreater(OSYS,2009)) {
+ PGON(0)
+ Store(One, _STA)
+ }
+ }
+ Method(_OFF, 0, Serialized) {
+ If(LGreater(OSYS,2009)) {
+ PGOF(0)
+ Store(Zero, _STA)
+ }
+ }
+ } //End of PowerResource(PG00, 0, 0)
+
+ Name(_PR0,Package(){PG00})
+ Name(_PR3,Package(){PG00})
+
+ ///
+ /// This method is used to enable/disable wake from PEG60 (WKEN)
+ ///
+ Method(_DSW, 3)
+ {
+ If(Arg1)
+ {
+ Store(0, WKEN) /// If entering Sx, need to disable WAKE# from generating runtime PME
+ }
+ Else
+ { /// If Staying in S0
+ If(LAnd(Arg0, Arg2)) ///- Check if Exiting D0 and arming for wake
+ {
+ Store(1, WKEN) ///- Set PME
+ } Else {
+ Store(0, WKEN) ///- Disable runtime PME, either because staying in D0 or disabling wake
+ }
+ }
+ } // End _DSW
+
+ ///
+ /// This method is used to change the GPIO ownership back to ACPI and will be called in PEG OFF Method
+ ///
+ Method(P0EW, 0)
+ {
+ If(WKEN)
+ {
+ If(LNotEqual(SGGP, 0x0))
+ {
+ If(LEqual(SGGP, 0x1)) // GPIO mode
+ {
+ \_SB.SGOV(P0WK, 0x1)
+ \_SB.SHPO(P0WK, 0x0) // set gpio ownership to ACPI(0=ACPI mode, 1=GPIO mode)
+ }
+ }
+ }
+ } // End P0EW
+
+ Method(_S0W, 0) {
+ Return(4) //D3cold is supported
+ }
+}// end "P.E.G. Root Port D6F0"
+
+///
+/// P.E.G. Root Port D1F0
+///
+Scope(\_SB.PC00.PEG1) {
+ Name(WKEN, 0)
+
+ PowerResource(PG01, 0, 0) {
+ Name(_STA, One)
+ Method(_ON, 0, Serialized) {
+ If(LGreater(OSYS,2009)) {
+ PGON(1)
+ Store(One, _STA)
+ }
+ }
+ Method(_OFF, 0, Serialized) {
+ If(LGreater(OSYS,2009)) {
+ PGOF(1)
+ Store(Zero, _STA)
+ }
+ }
+ } //End of PowerResource(PG01, 0, 0)
+
+ Name(_PR0,Package(){PG01})
+ Name(_PR3,Package(){PG01})
+
+ ///
+ /// This method is used to enable/disable wake from PEG10 (WKEN)
+ ///
+ Method(_DSW, 3)
+ {
+ If(Arg1)
+ {
+ Store(0, WKEN) /// If entering Sx, need to disable WAKE# from generating runtime PME
+ }
+ Else
+ { /// If Staying in S0
+ If(LAnd(Arg0, Arg2)) ///- Check if Exiting D0 and arming for wake
+ {
+ Store(1, WKEN) ///- Set PME
+ } Else {
+ Store(0, WKEN) ///- Disable runtime PME, either because staying in D0 or disabling wake
+ }
+ }
+ } // End _DSW
+
+ ///
+ /// This method is used to change the GPIO ownership back to ACPI and will be called in PEG OFF Method
+ ///
+ Method(P1EW, 0)
+ {
+ If(WKEN)
+ {
+ If(LNotEqual(P1GP, 0x0))
+ {
+ If(LEqual(P1GP, 0x1)) // GPIO mode
+ {
+ \_SB.SGOV(P1WK, 0x1)
+ \_SB.SHPO(P1WK, 0x0) // set gpio ownership to ACPI(0=ACPI mode, 1=GPIO mode)
+ }
+ }
+ }
+ } // End P1EW
+}// end "P.E.G. Root Port D1F0"
+
+///
+/// P.E.G. Root Port D1F1
+///
+Scope(\_SB.PC00.PEG2) {
+ Name(WKEN, 0)
+
+ PowerResource(PG02, 0, 0) {
+ Name(_STA, One)
+ Method(_ON, 0, Serialized) {
+ If(LGreater(OSYS,2009)) {
+ PGON(2)
+ Store(One, _STA)
+ }
+ }
+ Method(_OFF, 0, Serialized) {
+ If(LGreater(OSYS,2009)) {
+ PGOF(2)
+ Store(Zero, _STA)
+ }
+ }
+ } //End of PowerResource(PG02, 0, 0)
+
+ Name(_PR0,Package(){PG02})
+
+ Name(_PR3,Package(){PG02})
+
+ ///
+ /// This method is used to enable/disable wake from PEG11 (WKEN)
+ ///
+ Method(_DSW, 3)
+ {
+ If(Arg1)
+ {
+ Store(0, WKEN) /// If entering Sx, need to disable WAKE# from generating runtime PME
+ }
+ Else
+ { /// If Staying in S0
+ If(LAnd(Arg0, Arg2)) ///- Check if Exiting D0 and arming for wake
+ {
+ Store(1, WKEN) ///- Set PME
+ } Else {
+ Store(0, WKEN) ///- Disable runtime PME, either because staying in D0 or disabling wake
+ }
+ }
+ } // End _DSW
+
+ ///
+ /// This method is used to change the GPIO ownership back to ACPI and will be called in PEG OFF Method
+ ///
+ Method(P2EW, 0)
+ {
+ If(WKEN)
+ {
+ If(LNotEqual(P2GP, 0x0))
+ {
+ If(LEqual(P2GP, 0x1)) // GPIO mode
+ {
+ \_SB.SGOV(P2WK, 0x1)
+ \_SB.SHPO(P2WK, 0x0) // set gpio ownership to ACPI(0=ACPI mode, 1=GPIO mode)
+ }
+ }
+ }
+ } // End P2EW
+}// end "P.E.G. Root Port D1F1"
+
+///
+/// P.E.G. Root Port D1F2
+///
+Scope(\_SB.PC00.PEG3) {
+ Name(WKEN, 0)
+
+ PowerResource(PG03, 0, 0) {
+ Name(_STA, One)
+ Method(_ON, 0, Serialized) {
+ If(LGreater(OSYS,2009)) {
+ PGON(3)
+ Store(One, _STA)
+ }
+ }
+ Method(_OFF, 0, Serialized) {
+ If(LGreater(OSYS,2009)) {
+ PGOF(3)
+ Store(Zero, _STA)
+ }
+ }
+ } //End of PowerResource(PG03, 0, 0)
+
+ Name(_PR0,Package(){PG03})
+ Name(_PR3,Package(){PG03})
+
+ ///
+ /// This method is used to enable/disable wake from PEG12 (WKEN)
+ ///
+ Method(_DSW, 3)
+ {
+ If(Arg1)
+ {
+ Store(0, WKEN) /// If entering Sx, need to disable WAKE# from generating runtime PME
+ }
+ Else
+ { /// If Staying in S0
+ If(LAnd(Arg0, Arg2)) ///- Check if Exiting D0 and arming for wake
+ {
+ Store(1, WKEN) ///- Set PME
+ } Else {
+ Store(0, WKEN) ///- Disable runtime PME, either because staying in D0 or disabling wake
+ }
+ }
+ } // End _DSW
+
+ ///
+ /// This method is used to change the GPIO ownership back to ACPI and will be called in PEG OFF Method
+ ///
+ Method(P3EW, 0)
+ {
+ If(WKEN)
+ {
+ If(LNotEqual(P3GP, 0x0))
+ {
+ If(LEqual(P3GP, 0x1)) // GPIO mode
+ {
+ \_SB.SGOV(P3WK, 0x1)
+ \_SB.SHPO(P3WK, 0x0) // set gpio ownership to ACPI(0=ACPI mode, 1=GPIO mode)
+ }
+ }
+ }
+ } // End P3EW
+}// end "P.E.G. Root Port D1F2"
+
+Scope (\_SB.PC00) {
+
+ Name(IVID, 0xFFFF) //Invalid Vendor ID
+
+ Name(PEBA, 0) //PCIE base address
+
+ Name(PION, 0) //PEG index for ON Method
+ Name(PIOF, 0) //PEG index for OFF Method
+
+ Name(PBUS, 0) //PEG Rootport bus no
+ Name(PDEV, 0) //PEG Rootport device no
+ Name(PFUN, 0) //PEG Rootport function no
+
+ Name(EBUS, 0) //Endpoint bus no
+ Name(EDEV, 0) //Endpoint device no
+ Name(EFN0, 0) //Endpoint function no 0
+ Name(EFN1, 1) //Endpoint function no 1
+
+ Name(LTRS, 0)
+ Name(OBFS, 0)
+
+ Name(DSOF, 0x06) //Device status PCI offset
+ Name(CPOF, 0x34) //Capabilities pointer PCI offset
+ Name(SBOF, 0x19) //PCI-2-PCI Secondary Bus number
+
+ // PEG0 Endpoint variable to save/restore Link Capability, Link control, Subsytem VendorId and Device Id
+ Name (ELC0, 0x00000000)
+ Name (ECP0, 0xffffffff)
+ Name (H0VI, 0x0000)
+ Name (H0DI, 0x0000)
+
+ // PEG1 Endpoint variable to save/restore Link Capability, Link control, Subsytem VendorId and Device Id
+ Name (ELC1, 0x00000000)
+ Name (ECP1, 0xffffffff)
+ Name (H1VI, 0x0000)
+ Name (H1DI, 0x0000)
+
+ // PEG2 Endpoint variable to save/restore Link Capability, Link control, Subsytem VendorId and Device Id
+ Name (ELC2, 0x00000000)
+ Name (ECP2, 0xffffffff)
+ Name (H2VI, 0x0000)
+ Name (H2DI, 0x0000)
+
+ // PEG3 Endpoint variable to save/restore Link Capability, Link control, Subsytem VendorId and Device Id
+ Name (ELC3, 0x00000000)
+ Name (ECP3, 0xffffffff)
+ Name (H3VI, 0x0000)
+ Name (H3DI, 0x0000)
+
+ // PEG_AFELN[15:0]VMTX2_OFFSET variables
+ Name(AFL0, 0)
+ Name(AFL1, 0)
+ Name(AFL2, 0)
+ Name(AFL3, 0)
+ Name(AFL4, 0)
+ Name(AFL5, 0)
+ Name(AFL6, 0)
+ Name(AFL7, 0)
+ Name(AFL8, 0)
+ Name(AFL9, 0)
+ Name(AFLA, 0)
+ Name(AFLB, 0)
+ Name(AFLC, 0)
+ Name(AFLD, 0)
+ Name(AFLE, 0)
+ Name(AFLF, 0)
+
+ //
+ // Define a Memory Region for PEG60 root port that will allow access to its
+ // Register Block.
+ //
+ OperationRegion(OPG0, SystemMemory, Add(XBAS,0x30000), 0x1000)
+ Field(OPG0, AnyAcc,NoLock,Preserve)
+ {
+ Offset(0),
+ P0VI, 16, //Vendor ID PCI offset
+ P0DI, 16, //Device ID PCI offset
+ Offset(0x06),
+ DSO0, 16, //Device status PCI offset
+ Offset(0x34),
+ CPO0, 8, //Capabilities pointer PCI offset
+ Offset(0x0B0),
+ , 4,
+ P0LD, 1, //Link Disable
+ Offset(0x11A),
+ , 1,
+ P0VC, 1, //VC0RSTS.VC0NP
+ Offset(0x214),
+ , 16,
+ P0LS, 4, //PEGSTS.LKS
+ Offset(0x248),
+ , 7,
+ Q0L2, 1, //L23_Rdy Entry Request for RTD3
+ Q0L0, 1, //L23 to Detect Transition for RTD3
+ Offset(0x504),
+ HST0, 32,
+ Offset(0x508),
+ P0TR, 1, //TRNEN.TREN
+ Offset(0xC74),
+ P0LT, 4, //LTSSM_FSM_RESTORE.LTSSM_FSM_PS
+ Offset(0xD0C),
+ LRV0, 32,
+ }
+
+ //
+ // Define a Memory Region for Endpoint on PEG60 root port
+ //
+ OperationRegion (PCS0, SystemMemory, Add(XBAS,ShiftLeft(SBN0,20)), 0xF0)
+ Field(PCS0, DWordAcc, Lock, Preserve)
+ {
+ Offset(0x0),
+ D0VI, 16,
+ Offset(0x2C),
+ S0VI, 16,
+ S0DI, 16,
+ }
+
+ OperationRegion(CAP0, SystemMemory, Add(Add(XBAS,ShiftLeft(SBN0,20)),EECP),0x14)
+ Field(CAP0,DWordAcc, NoLock,Preserve)
+ {
+ Offset(0x0C), // Link Capabilities Register
+ LCP0, 32, // Link Capabilities Register Data
+ Offset(0x10),
+ LCT0, 16, // Link Control register
+ }
+
+ //
+ // Define a Memory Region for PEG10 root port that will allow access to its
+ // Register Block.
+ //
+ OperationRegion(OPG1, SystemMemory, Add(XBAS,0x8000), 0x1000)
+ Field(OPG1, AnyAcc,NoLock,Preserve)
+ {
+ Offset(0),
+ P1VI, 16, //Vendor ID PCI offset
+ P1DI, 16, //Device ID PCI offset
+ Offset(0x06),
+ DSO1, 16, //Device status PCI offset
+ Offset(0x34),
+ CPO1, 8, //Capabilities pointer PCI offset
+ Offset(0x0B0),
+ , 4,
+ P1LD, 1, //Link Disable
+ Offset(0x11A),
+ , 1,
+ P1VC, 1, //VC0RSTS.VC0NP
+ Offset(0x214),
+ , 16,
+ P1LS, 4, //PEGSTS.LKS
+ Offset(0x248),
+ , 7,
+ Q1L2, 1, //L23_Rdy Entry Request for RTD3
+ Q1L0, 1, //L23 to Detect Transition for RTD3
+ Offset(0x504),
+ HST1, 32,
+ Offset(0x508),
+ P1TR, 1, //TRNEN.TREN
+ Offset(0x70C),
+ PA0V, 32, //PEG_AFELN0VMTX2_OFFSET
+ Offset(0x71C),
+ PA1V, 32, //PEG_AFELN1VMTX2_OFFSET
+ Offset(0x72C),
+ PA2V, 32, //PEG_AFELN2VMTX2_OFFSET
+ Offset(0x73C),
+ PA3V, 32, //PEG_AFELN3VMTX2_OFFSET
+ Offset(0x74C),
+ PA4V, 32, //PEG_AFELN4VMTX2_OFFSET
+ Offset(0x75C),
+ PA5V, 32, //PEG_AFELN5VMTX2_OFFSET
+ Offset(0x76C),
+ PA6V, 32, //PEG_AFELN6VMTX2_OFFSET
+ Offset(0x77C),
+ PA7V, 32, //PEG_AFELN7VMTX2_OFFSET
+ Offset(0x78C),
+ PA8V, 32, //PEG_AFELN8VMTX2_OFFSET
+ Offset(0x79C),
+ PA9V, 32, //PEG_AFELN9VMTX2_OFFSET
+ Offset(0x7AC),
+ PAAV, 32, //PEG_AFELNAVMTX2_OFFSET
+ Offset(0x7BC),
+ PABV, 32, //PEG_AFELNBVMTX2_OFFSET
+ Offset(0x7CC),
+ PACV, 32, //PEG_AFELNCVMTX2_OFFSET
+ Offset(0x7DC),
+ PADV, 32, //PEG_AFELNDVMTX2_OFFSET
+ Offset(0x7EC),
+ PAEV, 32, //PEG_AFELNEVMTX2_OFFSET
+ Offset(0x7FC),
+ PAFV, 32, //PEG_AFELNFVMTX2_OFFSET
+ Offset(0x91C),
+ , 31,
+ BSP1, 1,
+ Offset(0x93C),
+ , 31,
+ BSP2, 1,
+ Offset(0x95C),
+ , 31,
+ BSP3, 1,
+ Offset(0x97C),
+ , 31,
+ BSP4, 1,
+ Offset(0x99C),
+ , 31,
+ BSP5, 1,
+ Offset(0x9BC),
+ , 31,
+ BSP6, 1,
+ Offset(0x9DC),
+ , 31,
+ BSP7, 1,
+ Offset(0x9FC),
+ , 31,
+ BSP8, 1,
+ Offset(0xC20),
+ , 4,
+ P1AP, 2, //AFEOVR.RXSQDETOVR
+ Offset(0xC38),
+ , 3,
+ P1RM, 1, //CMNSPARE.PCUNOTL1
+ Offset(0xC3C),
+ , 31,
+ PRST, 1,
+ Offset(0xC74),
+ P1LT, 4, //LTSSM_FSM_RESTORE.LTSSM_FSM_PS
+ Offset(0xD0C),
+ LRV1, 32,
+ }
+
+ //
+ // Define a Memory Region for Endpoint on PEG10 root port
+ //
+ OperationRegion (PCS1, SystemMemory, Add(XBAS,ShiftLeft(SBN1,20)), 0xF0)
+ Field(PCS0, DWordAcc, Lock, Preserve)
+ {
+ Offset(0x0),
+ D1VI, 16,
+ Offset(0x2C),
+ S1VI, 16,
+ S1DI, 16,
+ }
+
+ OperationRegion(CAP1, SystemMemory, Add(Add(XBAS,ShiftLeft(SBN1,20)),EEC1),0x14)
+ Field(CAP0,DWordAcc, NoLock,Preserve)
+ {
+ Offset(0x0C), // Link Capabilities Register
+ LCP1, 32, // Link Capabilities Register Data
+ Offset(0x10),
+ LCT1, 16, // Link Control register
+ }
+
+ //
+ // Define a Memory Region for PEG11 root port that will allow access to its
+ // Register Block.
+ //
+ OperationRegion(OPG2, SystemMemory, Add(XBAS,0x9000), 0x1000)
+ Field(OPG2, AnyAcc,NoLock,Preserve)
+ {
+ Offset(0),
+ P2VI, 16, //Vendor ID PCI offset
+ P2DI, 16, //Device ID PCI offset
+ Offset(0x06),
+ DSO2, 16, //Device status PCI offset
+ Offset(0x34),
+ CPO2, 8, //Capabilities pointer PCI offset
+ Offset(0x0B0),
+ , 4,
+ P2LD, 1, //Link Disable
+ Offset(0x11A),
+ , 1,
+ P2VC, 1, //VC0RSTS.VC0NP
+ Offset(0x214),
+ , 16,
+ P2LS, 4, //PEGSTS.LKS
+ Offset(0x248),
+ , 7,
+ Q2L2, 1, //L23_Rdy Entry Request for RTD3
+ Q2L0, 1, //L23 to Detect Transition for RTD3
+ Offset(0x504),
+ HST2, 32,
+ Offset(0x508),
+ P2TR, 1, //TRNEN.TREN
+ Offset(0xC20),
+ , 4,
+ P2AP, 2, //AFEOVR.RXSQDETOVR
+ Offset(0xC38),
+ , 3,
+ P2RM, 1, //CMNSPARE.PCUNOTL1
+ Offset(0xC74),
+ P2LT, 4, //LTSSM_FSM_RESTORE.LTSSM_FSM_PS
+ Offset(0xD0C),
+ LRV2, 32,
+ }
+
+ //
+ // Define a Memory Region for Endpoint on PEG11 root port
+ //
+ OperationRegion (PCS2, SystemMemory, Add(XBAS,ShiftLeft(SBN2,20)), 0xF0)
+ Field(PCS2, DWordAcc, Lock, Preserve)
+ {
+ Offset(0x0),
+ D2VI, 16,
+ Offset(0x2C),
+ S2VI, 16,
+ S2DI, 16,
+ }
+
+ OperationRegion(CAP2, SystemMemory, Add(Add(XBAS,ShiftLeft(SBN2,20)),EEC2),0x14)
+ Field(CAP2,DWordAcc, NoLock,Preserve)
+ {
+ Offset(0x0C), // Link Capabilities Register
+ LCP2, 32, // Link Capabilities Register Data
+ Offset(0x10),
+ LCT2, 16, // Link Control register
+ }
+
+
+ //
+ // Define a Memory Region for PEG12 root port that will allow access to its
+ // Register Block.
+ //
+ OperationRegion(OPG3, SystemMemory, Add(XBAS,0xA000), 0x1000)
+ Field(OPG3, AnyAcc,NoLock,Preserve)
+ {
+ Offset(0),
+ P3VI, 16, //Vendor ID PCI offset
+ P3DI, 16, //Device ID PCI offset
+ Offset(0x06),
+ DSO3, 16, //Device status PCI offset
+ Offset(0x34),
+ CPO3, 8, //Capabilities pointer PCI offset
+ Offset(0x0B0),
+ , 4,
+ P3LD, 1, //Link Disable
+ Offset(0x11A),
+ , 1,
+ P3VC, 1, //VC0RSTS.VC0NP
+ Offset(0x214),
+ , 16,
+ P3LS, 4, //PEGSTS.LKS
+ Offset(0x248),
+ , 7,
+ Q3L2, 1, //L23_Rdy Entry Request for RTD3
+ Q3L0, 1, //L23 to Detect Transition for RTD3
+ Offset(0x504),
+ HST3, 32,
+ Offset(0x508),
+ P3TR, 1, //TRNEN.TREN
+ Offset(0xC20),
+ , 4,
+ P3AP, 2, //AFEOVR.RXSQDETOVR
+ Offset(0xC38),
+ , 3,
+ P3RM, 1, //CMNSPARE.PCUNOTL1
+ Offset(0xC74),
+ P3LT, 4, //LTSSM_FSM_RESTORE.LTSSM_FSM_PS
+ Offset(0xD0C),
+ LRV3, 32,
+ }
+
+ //
+ // Define a Memory Region for Endpoint on PEG2 root port
+ //
+ OperationRegion (PCS3, SystemMemory, Add(XBAS,ShiftLeft(SBN3,20)), 0xF0)
+ Field(PCS2, DWordAcc, Lock, Preserve)
+ {
+ Offset(0x0),
+ D3VI, 16,
+ Offset(0x2C),
+ S3VI, 16,
+ S3DI, 16,
+ }
+
+ OperationRegion(CAP3, SystemMemory, Add(Add(XBAS,ShiftLeft(SBN3,20)),EEC3),0x14)
+ Field(CAP3,DWordAcc, NoLock,Preserve)
+ {
+ Offset(0x0C), // Link Capabilities Register
+ LCP3, 32, // Link Capabilities Register Data
+ Offset(0x10),
+ LCT3, 16, // Link Control register
+ }
+
+ //
+ // Name: PGON
+ // Description: Function to put the Pcie Endpoint in ON state
+ // Input: Arg0 -> PEG index
+ // Return: Nothing
+ //
+ Method(PGON,1,Serialized)
+ {
+ Store(Arg0, PION)
+
+ //
+ // Check for the GPIO support on PEG0/1/2/3 Configuration and Return if it is not supported.
+ //
+ If (LEqual(PION, 0))
+ {
+ If (LEqual(SGGP, 0x0))
+ {
+ Return ()
+ }
+ }
+ ElseIf (LEqual(PION, 1))
+ {
+ If (LEqual(P1GP, 0x0))
+ {
+ Return ()
+ }
+ }
+ ElseIf (LEqual(PION, 2))
+ {
+ If (LEqual(P2GP, 0x0))
+ {
+ Return ()
+ }
+ }
+ ElseIf (LEqual(PION, 3))
+ {
+ If (LEqual(P3GP, 0x0))
+ {
+ Return ()
+ }
+ }
+ Store(\XBAS, PEBA)
+ Store(GDEV(PIOF), PDEV)
+ Store(GFUN(PIOF), PFUN)
+
+ /// de-assert CLK_REQ MSK
+ PGSC(Arg0, 1)
+
+ If (LEqual(CCHK(PION, 1), 0))
+ {
+ Return ()
+ }
+
+ //Power on the Endpoint
+ GPPR(PION, 1)
+
+ // Restore PEG Recipe before program L23R2DT
+ //\_SB.PC00.PEG1.RAVR()
+
+ // Enable link for RTD3
+ RTEN()
+
+ // Re-store the DGPU Subsystem VendorID, DeviceID & Link control register data
+ If (LEqual(PION, 0))
+ {
+ Store(H0VI, S0VI)
+ Store(H0DI, S0DI)
+ Or(And(ELC0,0x0043),And(LCT0,0xFFBC),LCT0)
+ }
+ ElseIf (LEqual(PION, 1))
+ {
+ Store(H1VI, S1VI)
+ Store(H1DI, S1DI)
+ Or(And(ELC1,0x0043),And(LCT1,0xFFBC),LCT1)
+ }
+ ElseIf (LEqual(PION, 2))
+ {
+ Store(H2VI, S2VI)
+ Store(H2DI, S2DI)
+ Or(And(ELC2,0x0043),And(LCT2,0xFFBC),LCT2)
+ }
+ ElseIf (LEqual(PION, 3))
+ {
+ Store(H3VI, S3VI)
+ Store(H3DI, S3DI)
+ Or(And(ELC3,0x0043),And(LCT3,0xFFBC),LCT3)
+ }
+ Return ()
+ } // End of Method(PGON,1,Serialized)
+
+ //
+ // Name: PGOF
+ // Description: Function to put the Pcie Endpoint in OFF state
+ // Input: Arg0 -> PEG index
+ // Return: Nothing
+ //
+ Method(PGOF,1,Serialized)
+ {
+
+ Store(Arg0, PIOF)
+ //
+ // Check for the GPIO support on PEG0/1/2 Configuration and Return if it is not supported.
+ //
+ If (LEqual(PIOF, 0))
+ {
+ If (LEqual(SGGP, 0x0))
+ {
+ Return ()
+ }
+ }
+ ElseIf (LEqual(PIOF, 1))
+ {
+ If (LEqual(P1GP, 0x0))
+ {
+ Return ()
+ }
+ }
+ ElseIf (LEqual(PIOF, 2))
+ {
+ If (LEqual(P2GP, 0x0))
+ {
+ Return ()
+ }
+ }
+ ElseIf (LEqual(PIOF, 3))
+ {
+ If (LEqual(P3GP, 0x0))
+ {
+ Return ()
+ }
+ }
+
+ Store(\XBAS, PEBA)
+ Store(GDEV(PIOF), PDEV)
+ Store(GFUN(PIOF), PFUN)
+
+ If (LEqual(CCHK(PIOF, 0), 0))
+ {
+ Return ()
+ }
+
+ // Save Endpoint Link Control register, Subsystem VendorID & Device ID, Link capability Data
+ If (LEqual(Arg0, 0)) //PEG60
+ {
+ Store(LCT0, ELC0)
+ Store(S0VI, H0VI)
+ Store(S0DI, H0DI)
+ Store(LCP0, ECP0)
+ }
+ ElseIf (LEqual(Arg0, 1)) //PEG10
+ {
+ Store(LCT1, ELC1)
+ Store(S1VI, H1VI)
+ Store(S1DI, H1DI)
+ Store(LCP1, ECP1)
+ }
+ ElseIf (LEqual(Arg0, 2)) //PEG11
+ {
+ Store(LCT2, ELC2)
+ Store(S2VI, H2VI)
+ Store(S2DI, H2DI)
+ Store(LCP2, ECP2)
+ }
+ ElseIf (LEqual(Arg0, 3)) //PEG12
+ {
+ Store(LCT3, ELC3)
+ Store(S3VI, H3VI)
+ Store(S3DI, H3DI)
+ Store(LCP3, ECP3)
+ }
+
+ //\_SB.PC00.PEG0.SAVR()
+
+ // Put link in L2
+ RTDS()
+
+ /// assert CLK_REQ MSK
+ ///
+ /// On RTD3 entry, BIOS will instruct the PMC to disable source clocks.
+ /// This is done through sending a PMC IPC command.
+ ///
+ PGSC(Arg0, 0)
+
+ //Power-off the Endpoint
+ GPPR(PIOF, 0)
+ //Method to set Wake GPIO ownership from GPIO to ACPI for Device Initiated RTD3
+ DIWK(PIOF)
+
+ Return ()
+ } // End of Method(PGOF,1,Serialized)
+
+
+ //
+ // Name: GDEV
+ // Description: Function to return the PEG device no for the given PEG index
+ // Input: Arg0 -> PEG index
+ // Return: PEG device no for the given PEG index
+ //
+ Method(GDEV,1)
+ {
+ If(LEqual(Arg0, 0))
+ {
+ Store(0x6, Local0) //Device6-Function0 = 00110.000
+ }
+ ElseIf(LEqual(Arg0, 1))
+ {
+ Store(0x1, Local0) //Device1-Function0 = 00001.000
+ }
+ ElseIf(LEqual(Arg0, 2))
+ {
+ Store(0x1, Local0) //Device1-Function2 = 00001.001
+ }
+ ElseIf(LEqual(Arg0, 3))
+ {
+ Store(0x1, Local0) //Device1-Function3 = 00001.010
+ }
+
+ Return(Local0)
+ } // End of Method(GDEV,1)
+
+ //
+ // Name: GFUN
+ // Description: Function to return the PEG function no for the given PEG index
+ // Input: Arg0 -> PEG index
+ // Return: PEG function no for the given PEG index
+ //
+ Method(GFUN,1)
+ {
+ If(LEqual(Arg0, 0))
+ {
+ Store(0x0, Local0) //Device6-Function0 = 00110.000
+ }
+ ElseIf(LEqual(Arg0, 1))
+ {
+ Store(0x0, Local0) //Device1-Function0 = 00001.000
+ }
+ ElseIf(LEqual(Arg0, 2))
+ {
+ Store(0x1, Local0) //Device1-Function1 = 00001.001
+ }
+ ElseIf(LEqual(Arg0, 2))
+ {
+ Store(0x2, Local0) //Device1-Function2 = 00001.010
+ }
+
+ Return(Local0)
+ } // End of Method(GFUN,1)
+
+ //
+ // Name: CCHK
+ // Description: Function to check whether _ON/_OFF sequence is allowed to execute for the given PEG controller or not
+ // Input: Arg0 -> PEG index
+ // Arg1 -> 0 means _OFF sequence, 1 means _ON sequence
+ // Return: 0 - Don't execute the flow, 1 - Execute the flow
+ //
+ Method(CCHK,2)
+ {
+
+ //Check for Referenced PEG controller is present or not
+ If(LEqual(Arg0, 0))
+ {
+ Store(P0VI, Local7)
+ }
+ ElseIf(LEqual(Arg0, 1))
+ {
+ Store(P1VI, Local7)
+ }
+ ElseIf(LEqual(Arg0, 2))
+ {
+ Store(P2VI, Local7)
+ }
+ ElseIf(LEqual(Arg0, 3))
+ {
+ Store(P3VI, Local7)
+ }
+
+ If(LEqual(Local7, IVID))
+ {
+ Return(0)
+ }
+
+ If(LNotEqual(Arg0, 1))
+ {
+ //Check for PEG10 controller presence
+ Store(P1VI, Local7)
+ If(LEqual(Local7, IVID))
+ {
+ Return(0)
+ }
+ }
+
+ //If Endpoint is not present[already disabled] before executing PGOF then don't call the PGOF method
+ //If Endpoint is present[already enabled] before executing PGON then don't call the PGON method
+ If(LEqual(Arg1, 0))
+ {
+ //_OFF sequence condition check
+ If(LEqual(Arg0, 0))
+ {
+ If(LEqual(SGPI(SGGP, PWE0, PWG0, PWA0), 0))
+ {
+ Return(0)
+ }
+ }
+ If(LEqual(Arg0, 1))
+ {
+ If(LEqual(SGPI(P1GP, PWE1, PWG1, PWA1), 0))
+ {
+ Return(0)
+ }
+ }
+ If(LEqual(Arg0, 2))
+ {
+ If(LEqual(SGPI(P2GP, PWE2, PWG2, PWA2), 0))
+ {
+ Return(0)
+ }
+ }
+ If(LEqual(Arg0, 3))
+ {
+ If(LEqual(SGPI(P3GP, PWE3, PWG3, PWA3), 0))
+ {
+ Return(0)
+ }
+ }
+ }
+ ElseIf(LEqual(Arg1, 1))
+ {
+ //_ON sequence condition check
+ If(LEqual(Arg0, 0))
+ {
+ If(LEqual(SGPI(SGGP, PWE0, PWG0, PWA0), 1))
+ {
+ Return(0)
+ }
+ }
+ If(LEqual(Arg0, 1))
+ {
+ If(LEqual(SGPI(P1GP, PWE1, PWG1, PWA1), 1))
+ {
+ Return(0)
+ }
+ }
+ If(LEqual(Arg0, 2))
+ {
+ If(LEqual(SGPI(P2GP, PWE2, PWG2, PWA2), 1))
+ {
+ Return(0)
+ }
+ }
+ If(LEqual(Arg0, 3))
+ {
+ If(LEqual(SGPI(P3GP, PWE3, PWG3, PWA3), 1))
+ {
+ Return(0)
+ }
+ }
+ }
+
+ Return(1)
+ }
+
+
+ //
+ // Name: SGPI [PCIe GPIO Read]
+ // Description: Function to Read from PCIe GPIO
+ // Input: Arg0 -> Gpio Support
+ // Arg1 -> Expander Number
+ // Arg2 -> Gpio Number
+ // Arg3 -> Active Information
+ // Return: GPIO value
+ //
+ Method(SGPI, 4, Serialized)
+ {
+ If (LEqual(Arg0, 0x01))
+ {
+ //
+ // PCH based GPIO
+ //
+ If (CondRefOf(\_SB.GGOV))
+ {
+ Store(\_SB.GGOV(Arg2), Local0)
+ }
+ }
+ //
+ // Invert if Active Low
+ //
+ If (LEqual(Arg3,0))
+ {
+ Not(Local0, Local0)
+ And (Local0, 0x01, Local0)
+ }
+
+ Return(Local0)
+ }// End of Method(SGPI)
+
+ // Name: PGSC [PEG port source clock control]
+ // Description: Function to enable/disable PEG port source clocks
+ // Input: Arg0 -> PEG index
+ // Arg1 -> Enable/Disable Clock (0 = Disable, 1 = Enable)
+ // Return: Nothing
+ //
+
+ Method(PGSC, 2, Serialized)
+ {
+ If(LEqual(Arg0, 0)) { // PEG0
+ Store (P0SC, Local0)
+ } ElseIf(LEqual(Arg0, 1)) { // PEG1
+ Store (P1SC, Local0)
+ } ElseIf(LEqual(Arg0, 2)) { // PEG2
+ Store (P2SC, Local0)
+ } ElseIf(LEqual(Arg0, 3)) {// PEG3
+ Store (P3SC, Local0)
+ } Else {
+ Return()
+ }
+
+ SPCO (Local0, Arg1)
+ }// End of Method(PGSC)
+
+ //
+ // Name: GPPR
+ // Description: Function to do Endpoint ON/OFF using GPIOs
+ // There are two GPIOs currently used to control Third Party Vendor[TPV] DGPU Endpoint devices:
+ // (1) DGPU_PWR_EN [used for Power control]
+ // (2) DGPU_HOLD_RST[used for Reset control]
+ // Input: Arg0 -> PEG index
+ // Arg1 -> 0 means _OFF sequence, 1 means _ON sequence
+ // Return: Nothing
+ //
+ Method(GPPR,2)
+ {
+
+ If(LEqual(Arg1, 0))
+ {
+ //_OFF sequence GPIO programming
+ If(LEqual(Arg0, 0))
+ {
+ SGPO(SGGP, HRE0, HRG0, HRA0, 1) // Assert PCIe0/dGPU_HOLD_RST# (PERST#)
+ //Sleep(DLHR) // As per the PCIe spec, Wait for 'given'ms after Assert the Reset
+ SGPO(SGGP, PWE0, PWG0, PWA0, 0) // Deassert PCIe0/dGPU_PWR_EN#
+ }
+
+ If(LEqual(Arg0, 1))
+ {
+ SGPO(P1GP, HRE1, HRG1, HRA1, 1) // Assert PCIe1_HOLD_RST# (PERST#)
+ //Sleep(DLHR) // As per the PCIe spec, Wait for 'given'ms after Assert the Reset
+ SGPO(P1GP, PWE1, PWG1, PWA1, 0) // Deassert PCIe1_PWR_EN#
+ }
+
+ If(LEqual(Arg0, 2))
+ {
+ SGPO(P2GP, HRE2, HRG2, HRA2, 1) // Assert PCIe2_HOLD_RST# (PERST#)
+ //Sleep(DLHR) // As per the PCIe spec, Wait for 'given'ms after Assert the Reset
+ SGPO(P2GP, PWE2, PWG2, PWA2, 0) // Deassert PCIe2_PWR_EN#
+ }
+
+ If(LEqual(Arg0, 3))
+ {
+ SGPO(P3GP, HRE3, HRG3, HRA3, 1) // Assert PCIe3_HOLD_RST# (PERST#)
+ //Sleep(DLHR) // As per the PCIe spec, Wait for 'given'ms after Assert the Reset
+ SGPO(P3GP, PWE3, PWG3, PWA3, 0) // Deassert PCIe2_PWR_EN#
+ }
+ }
+ ElseIf(LEqual(Arg1, 1))
+ {
+ //_ON sequence GPIO programming
+ If(LEqual(Arg0, 0))
+ {
+ SGPO(SGGP, PWE0, PWG0, PWA0, 1) //Assert dGPU_PWR_EN#
+
+ //Sleep(DLPW) // Wait for 'given'ms for power to get stable
+ SGPO(SGGP, HRE0, HRG0, HRA0, 0) //Deassert dGPU_HOLD_RST# as per the PCIe spec
+
+ //Sleep(DLHR) // Wait for 'given'ms after Deassert
+ }
+
+ If(LEqual(Arg0, 1))
+ {
+ SGPO(P1GP, PWE1, PWG1, PWA1, 1) //Assert dGPU_PWR_EN#
+
+ //Sleep(DLPW) // Wait for 'given'ms for power to get stable
+ SGPO(P1GP, HRE1, HRG1, HRA1, 0) //Deassert dGPU_HOLD_RST# as per the PCIe spec
+
+ //Sleep(DLHR) // Wait for 'given'ms after Deassert
+ }
+
+ If(LEqual(Arg0, 2))
+ {
+ SGPO(P2GP, PWE2, PWG2, PWA2, 1) //Assert dGPU_PWR_EN#
+
+ //Sleep(DLPW) // Wait for 'given'ms for power to get stable
+ SGPO(P2GP, HRE2, HRG2, HRA2, 0) //Deassert dGPU_HOLD_RST# as per the PCIe spec
+
+ //Sleep(DLHR) // Wait for 'given'ms after Deassert
+ }
+
+ If(LEqual(Arg0, 3))
+ {
+ SGPO(P3GP, PWE3, PWG3, PWA3, 1) //Assert dGPU_PWR_EN#
+
+ //Sleep(DLPW) // Wait for 'given'ms for power to get stable
+ SGPO(P3GP, HRE3, HRG3, HRA3, 0) //Deassert dGPU_HOLD_RST# as per the PCIe spec
+
+ //Sleep(DLHR) // Wait for 'given'ms after Deassert
+ }
+ }
+ } // End of Method(GPPR,2)
+
+ //
+ // Name: SGPO [PCIe GPIO Write]
+ // Description: Function to write into PCIe GPIO
+ // Input: Arg0 -> Gpio Support
+ // Arg1 -> Expander Number
+ // Arg2 -> Gpio Number
+ // Arg3 -> Active Information
+ // Arg4 -> Value to write
+ // Return: Nothing
+ //
+
+ Method(SGPO, 5, Serialized)
+ {
+ //
+ // Invert if Active Low
+ //
+ If (LEqual(Arg3,0))
+ {
+ Not(Arg4, Arg4)
+ And(Arg4, 0x01, Arg4)
+ }
+ If (LEqual(Arg0, 0x01))
+ {
+ //
+ // PCH based GPIO
+ //
+ If (CondRefOf(\_SB.SGOV))
+ {
+ \_SB.SGOV(Arg2, Arg4)
+ }
+ }
+ } // End of Method(SGPO)
+
+ //
+ // Name: DIWK
+ // Description: Function which set the GPIO ownership to ACPI for device initiated RTD3
+ // Input: PEG Index
+ // Return: Nothing
+ //
+ Method(DIWK,1)
+ {
+ If (LEqual(Arg0, 0))
+ {
+ \_SB.PC00.PEG0.P0EW()
+ }
+ ElseIf (LEqual(Arg0, 1))
+ {
+ \_SB.PC00.PEG1.P1EW()
+ }
+ ElseIf (LEqual(Arg0, 2))
+ {
+ \_SB.PC00.PEG2.P2EW()
+ }
+ ElseIf (LEqual(Arg0, 3))
+ {
+ \_SB.PC00.PEG3.P3EW()
+ }
+ }
+ }// End of Scope (\_SB.PC00)
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/PegRtd3.asl b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/PegRtd3.asl
new file mode 100644
index 0000000000..b5d1a4e35e
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/PegRtd3.asl
@@ -0,0 +1,124 @@
+/** @file
+ This file contains the device definitions of the SystemAgent
+ PCIE ACPI Reference Code.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+Scope (\_SB.PC00) {
+
+ OperationRegion(PXCS,PCI_Config,0x00,0x480)
+ Field(PXCS,AnyAcc, NoLock, Preserve)
+ {
+ Offset(0),
+ VDID, 32,
+ Offset(0x50), // LCTL - Link Control Register
+ L0SE, 1, // 0, L0s Entry Enabled
+ , 3,
+ LDIS, 1,
+ , 3,
+ Offset(0x52), // LSTS - Link Status Register
+ , 13,
+ LASX, 1, // 0, Link Active Status
+ Offset(0x5A), // SLSTS[7:0] - Slot Status Register
+ ABPX, 1, // 0, Attention Button Pressed
+ , 2,
+ PDCX, 1, // 3, Presence Detect Changed
+ , 2,
+ PDSX, 1, // 6, Presence Detect State
+ , 1,
+ Offset(0x60), // RSTS - Root Status Register
+ , 16,
+ PSPX, 1, // 16, PME Status
+ Offset(0xA4),
+ D3HT, 2, // Power State
+ Offset(0xD8), // 0xD8, MPC - Miscellaneous Port Configuration Register
+ , 30,
+ HPEX, 1, // 30, Hot Plug SCI Enable
+ PMEX, 1, // 31, Power Management SCI Enable
+ Offset(0xE0), // 0xE0, SPR - Scratch Pad Register
+ , 0,
+ SCB0, 1, // Sticky Scratch Pad Bit SCB0
+ Offset(0xE2), // 0xE2, RPPGEN - Root Port Power Gating Enable
+ , 2,
+ L23E, 1, // 2, L23_Rdy Entry Request (L23ER)
+ L23R, 1, // 3, L23_Rdy to Detect Transition (L23R2DT)
+ Offset(0x324), // 0x324 - PCIEDBG
+ , 3,
+ LEDM, 1, // PCIEDBG.DMIL1EDM
+ Offset(0x328), // 0x328 - PCIESTS1
+ , 24,
+ LTSM, 8,
+ }
+ Field(PXCS,AnyAcc, NoLock, WriteAsZeros)
+ {
+ Offset(0xDC), // 0xDC, SMSCS - SMI/SCI Status Register
+ , 30,
+ HPSX, 1, // 30, Hot Plug SCI Status
+ PMSX, 1 // 31, Power Management SCI Status
+ }
+
+ //
+ // Name: RTEN
+ // Description: Function to Enable the link for RTD3 [RCTL.L22DT]
+ // Input: PEG Index
+ // Return: Nothing
+ //
+ Method(RTEN, 0, Serialized)
+ {
+ If (LNotEqual (SCB0,0x1)) {
+ Return ()
+ }
+
+ /// Set L23_Rdy to Detect Transition (L23R2DT)
+ Store(1, L23R)
+ Store(0, Local0)
+ /// Wait for transition to Detect
+ While(L23R) {
+ If(Lgreater(Local0, 4))
+ {
+ Break
+ }
+ Sleep(16)
+ Increment(Local0)
+ }
+ Store(0,SCB0)
+
+ /// Once in Detect, wait up to 124 ms for Link Active (typically happens in under 70ms)
+ /// Worst case per PCIe spec from Detect to Link Active is:
+ /// 24ms in Detect (12+12), 72ms in Polling (24+48), 28ms in Config (24+2+2+2+2)
+ Store(0, Local0)
+ While(LEqual(LASX,0)) {
+ If(Lgreater(Local0, 8))
+ {
+ Break
+ }
+ Sleep(16)
+ Increment(Local0)
+ }
+ }
+
+ //
+ // Name: RTDS
+ // Description: Function to Disable link for RTD3 [RCTL.L23ER]
+ // Input: PEG Index
+ // Return: Nothing
+ //
+ Method(RTDS, 0, Serialized)
+ {
+ Store(1, L23E)
+ Sleep(16)
+ Store(0, Local0)
+ While(L23E) {
+ If(Lgreater(Local0, 4))
+ {
+ Break
+ }
+ Sleep(16)
+ Increment(Local0)
+ }
+ Store(1,SCB0)
+ }
+
+} // End of Scope (\_SB.PC00)
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/Sa.asl b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/Sa.asl
new file mode 100644
index 0000000000..5228d9d753
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/Sa.asl
@@ -0,0 +1,26 @@
+/** @file
+ This file contains the device definition of the System Agent
+ ACPI reference code.
+ Currently defines the device objects for the
+ System Agent PCI Express* ports (PEG), iGfx and other devices.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+External(\HGMD)
+External(\HGST)
+External(\_SB.PC00, DeviceObj)
+External(\_SB.PC00.GFX0, DeviceObj)
+External(\_SB.PC00.IPU0, DeviceObj)
+External(\_SB.PC00.B0D3, DeviceObj)
+External(\_SB.PC00.PCIC, MethodObj)
+External(\_SB.PC00.PCID, MethodObj)
+///
+/// CPU PCIe Root Port
+///
+include("CpuPcieRp.asl")
+include("PegCommon.asl")
+If(LAnd((LEqual(HGMD,2)), (LEqual(HGST,1)))) {
+ include("PegRtd3.asl")
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/SaSsdt.asl b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/SaSsdt.asl
new file mode 100644
index 0000000000..0494c659e0
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/SaSsdt.asl
@@ -0,0 +1,20 @@
+/** @file
+ This file contains the SystemAgent SSDT Table ASL code.
+ It defines a Global NVS table which exchanges datas between OS
+ and BIOS.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+DefinitionBlock (
+ "SaSsdt.aml",
+ "SSDT",
+ 0x02,
+ "SaSsdt",
+ "SaSsdt ",
+ 0x3000
+ )
+{
+ Include ("Sa.asl")
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/SaSsdt.inf b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/SaSsdt.inf
new file mode 100644
index 0000000000..d0d1494b99
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/AcpiTables/SaSsdt/SaSsdt.inf
@@ -0,0 +1,22 @@
+## @file
+# Component description file for the ACPI tables
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+INF_VERSION = 0x00010005
+BASE_NAME = SaSsdt
+FILE_GUID = ca89914d-2317-452e-b245-36c6fb77a9c6
+MODULE_TYPE = USER_DEFINED
+VERSION_STRING = 1.0
+
+[Sources]
+ SaSsdt.asl
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ TigerlakeSiliconPkg/SiPkg.dec
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/Library/DxeSaPolicyLib/DxeSaPolicyLib.c b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/Library/DxeSaPolicyLib/DxeSaPolicyLib.c
new file mode 100644
index 0000000000..e1569e7f32
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/Library/DxeSaPolicyLib/DxeSaPolicyLib.c
@@ -0,0 +1,254 @@
+/** @file
+ This file provide services for DXE phase policy default initialization
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "DxeSaPolicyLibrary.h"
+#include <Library/DxeGraphicsPolicyLib.h>
+#include <Library/DxeVtdPolicyLib.h>
+#include <Register/SaRegsHostBridge.h>
+
+extern EFI_GUID gMemoryDxeConfigGuid;
+extern EFI_GUID gPcieDxeConfigGuid;
+
+/**
+ This function prints the SA DXE phase policy.
+
+ @param[in] SaPolicy - SA DXE Policy protocol
+**/
+VOID
+SaPrintPolicyProtocol (
+ IN SA_POLICY_PROTOCOL *SaPolicy
+ )
+{
+ EFI_STATUS Status;
+ PCIE_DXE_CONFIG *PcieDxeConfig;
+ MEMORY_DXE_CONFIG *MemoryDxeConfig;
+
+ //
+ // Get requisite IP Config Blocks which needs to be used here
+ //
+ Status = GetConfigBlock ((VOID *) SaPolicy, &gPcieDxeConfigGuid, (VOID *)&PcieDxeConfig);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = GetConfigBlock ((VOID *) SaPolicy, &gMemoryDxeConfigGuid, (VOID *)&MemoryDxeConfig);
+ ASSERT_EFI_ERROR (Status);
+
+
+ DEBUG_CODE_BEGIN ();
+ INTN i;
+
+ DEBUG ((DEBUG_INFO, "\n------------------------ SA Policy (DXE) print BEGIN -----------------\n"));
+ DEBUG ((DEBUG_INFO, "Revision : %x\n", SaPolicy->TableHeader.Header.Revision));
+ ASSERT (SaPolicy->TableHeader.Header.Revision == SA_POLICY_PROTOCOL_REVISION);
+
+ DEBUG ((DEBUG_INFO, "------------------------ SA_MEMORY_CONFIGURATION -----------------\n"));
+
+ DEBUG ((DEBUG_INFO, " SpdAddressTable[%d] :", 4));
+ for (i = 0; i < 4; i++) {
+ DEBUG ((DEBUG_INFO, " %x", MemoryDxeConfig->SpdAddressTable[i]));
+ }
+ DEBUG ((DEBUG_INFO, "\n"));
+
+ DEBUG ((DEBUG_INFO, " ChannelASlotMap : %x\n", MemoryDxeConfig->ChannelASlotMap));
+ DEBUG ((DEBUG_INFO, " ChannelBSlotMap : %x\n", MemoryDxeConfig->ChannelBSlotMap));
+ DEBUG ((DEBUG_INFO, " MrcTimeMeasure : %x\n", MemoryDxeConfig->MrcTimeMeasure));
+ DEBUG ((DEBUG_INFO, " MrcFastBoot : %x\n", MemoryDxeConfig->MrcFastBoot));
+
+ DEBUG ((DEBUG_INFO, "------------------------ CPU_PCIE_CONFIGURATION -----------------\n"));
+ DEBUG ((DEBUG_INFO, " PegAspm[%d] :", SA_PEG_MAX_FUN));
+ for (i = 0; i < SA_PEG_MAX_FUN; i++) {
+ DEBUG ((DEBUG_INFO, " %x", PcieDxeConfig->PegAspm[i]));
+ }
+ DEBUG ((DEBUG_INFO, "\n"));
+
+ DEBUG ((DEBUG_INFO, " PegRootPortHPE[%d] :", SA_PEG_MAX_FUN));
+ for (i = 0; i < SA_PEG_MAX_FUN; i++) {
+ DEBUG ((DEBUG_INFO, " %x", PcieDxeConfig->PegRootPortHPE[i]));
+ }
+ DEBUG ((DEBUG_INFO, "\n"));
+
+
+ DEBUG ((DEBUG_INFO, "\n------------------------ SA Policy (DXE) print END -----------------\n"));
+ DEBUG_CODE_END ();
+
+ return;
+}
+
+/**
+ Load DXE Config block default for PCIe
+
+ @param[in] ConfigBlockPointer Pointer to config block
+**/
+VOID
+LoadPcieDxeDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ UINT8 Index;
+ PCIE_DXE_CONFIG *PcieDxeConfig;
+
+ PcieDxeConfig = ConfigBlockPointer;
+ DEBUG ((DEBUG_INFO, "PcieDxeConfig->Header.GuidHob.Name = %g\n", &PcieDxeConfig->Header.GuidHob.Name));
+ DEBUG ((DEBUG_INFO, "PcieDxeConfig->Header.GuidHob.Header.HobLength = 0x%x\n", PcieDxeConfig->Header.GuidHob.Header.HobLength));
+ ///
+ /// Initialize the PCIE Configuration
+ /// PEG ASPM per port configuration. 4 PEG controllers i.e. 0,1,2,3
+ ///
+ for (Index = 0; Index < SA_PEG_MAX_FUN; Index++) {
+ PcieDxeConfig->PegAspm[Index] = CpuPcieAspmAutoConfig;
+ }
+
+ for (Index = 0; Index < SA_PEG_MAX_FUN; Index++) {
+ PcieDxeConfig->PegPwrOpt[Index].LtrEnable = 1;
+ PcieDxeConfig->PegPwrOpt[Index].LtrMaxSnoopLatency = V_SA_LTR_MAX_SNOOP_LATENCY_VALUE;
+ PcieDxeConfig->PegPwrOpt[Index].LtrMaxNoSnoopLatency = V_SA_LTR_MAX_NON_SNOOP_LATENCY_VALUE;
+ PcieDxeConfig->PegPwrOpt[Index].ObffEnable = 1;
+ }
+}
+
+
+/**
+ Load DXE Config block default
+
+ @param[in] ConfigBlockPointer Pointer to config block
+**/
+VOID
+LoadMemoryDxeDefault (
+ IN VOID *ConfigBlockPointer
+ )
+{
+ MEMORY_DXE_CONFIG *MemoryDxeConfig;
+
+ MemoryDxeConfig = ConfigBlockPointer;
+ DEBUG ((DEBUG_INFO, "MemoryDxeConfig->Header.GuidHob.Name = %g\n", &MemoryDxeConfig->Header.GuidHob.Name));
+ DEBUG ((DEBUG_INFO, "MemoryDxeConfig->Header.GuidHob.Header.HobLength = 0x%x\n", MemoryDxeConfig->Header.GuidHob.Header.HobLength));
+ ///
+ /// Initialize the Memory Configuration
+ ///
+ ///
+ /// DIMM SMBus addresses info
+ /// Refer to the SpdAddressTable[] mapping rule in DxeSaPolicyLibrary.h
+ ///
+ MemoryDxeConfig->SpdAddressTable = AllocateZeroPool (sizeof (UINT8) * 4);
+ ASSERT (MemoryDxeConfig->SpdAddressTable != NULL);
+ if (MemoryDxeConfig->SpdAddressTable != NULL) {
+ MemoryDxeConfig->SpdAddressTable[0] = DIMM_SMB_SPD_P0C0D0;
+ MemoryDxeConfig->SpdAddressTable[1] = DIMM_SMB_SPD_P0C0D1;
+ MemoryDxeConfig->SpdAddressTable[2] = DIMM_SMB_SPD_P0C1D0;
+ MemoryDxeConfig->SpdAddressTable[3] = DIMM_SMB_SPD_P0C1D1;
+ }
+ MemoryDxeConfig->ChannelASlotMap = 0x01;
+ MemoryDxeConfig->ChannelBSlotMap = 0x01;
+}
+
+GLOBAL_REMOVE_IF_UNREFERENCED COMPONENT_BLOCK_ENTRY mSaDxeIpBlocks [] = {
+ {&gPcieDxeConfigGuid, sizeof (PCIE_DXE_CONFIG), PCIE_DXE_CONFIG_REVISION, LoadPcieDxeDefault},
+ {&gMemoryDxeConfigGuid, sizeof (MEMORY_DXE_CONFIG), MEMORY_DXE_CONFIG_REVISION, LoadMemoryDxeDefault}
+};
+
+
+/**
+ CreateSaDxeConfigBlocks generates the config blocks of SA DXE Policy.
+ It allocates and zero out buffer, and fills in the Intel default settings.
+
+ @param[out] SaPolicy The pointer to get SA DXE Protocol instance
+
+ @retval EFI_SUCCESS The policy default is initialized.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create buffer
+**/
+EFI_STATUS
+EFIAPI
+CreateSaDxeConfigBlocks (
+ IN OUT SA_POLICY_PROTOCOL **SaPolicy
+ )
+{
+ UINT16 TotalBlockSize;
+ EFI_STATUS Status;
+ SA_POLICY_PROTOCOL *SaInitPolicy;
+ UINT16 RequiredSize;
+
+ DEBUG ((DEBUG_INFO, "SA Create Dxe Config Blocks\n"));
+
+ SaInitPolicy = NULL;
+
+ TotalBlockSize = GetComponentConfigBlockTotalSize (&mSaDxeIpBlocks[0], sizeof (mSaDxeIpBlocks) / sizeof (COMPONENT_BLOCK_ENTRY));
+ TotalBlockSize += VtdGetConfigBlockTotalSizeDxe ();
+ TotalBlockSize += GraphicsGetConfigBlockTotalSizeDxe ();
+ DEBUG ((DEBUG_INFO, "TotalBlockSize = 0x%x\n", TotalBlockSize));
+
+ RequiredSize = sizeof (CONFIG_BLOCK_TABLE_HEADER) + TotalBlockSize;
+
+ Status = CreateConfigBlockTable (RequiredSize, (VOID *) &SaInitPolicy);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Initialize Policy Revision
+ //
+ SaInitPolicy->TableHeader.Header.Revision = SA_POLICY_PROTOCOL_REVISION;
+ //
+ // Add config blocks.
+ //
+ Status = AddComponentConfigBlocks ((VOID *) SaInitPolicy, &mSaDxeIpBlocks[0], sizeof (mSaDxeIpBlocks) / sizeof (COMPONENT_BLOCK_ENTRY));
+ ASSERT_EFI_ERROR (Status);
+
+ // Vtd
+ Status = VtdAddConfigBlocksDxe((VOID *) SaInitPolicy);
+ ASSERT_EFI_ERROR (Status);
+
+ // Gfx
+ Status = GraphicsAddConfigBlocksDxe ((VOID *) SaInitPolicy);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Assignment for returning SaInitPolicy config block base address
+ //
+ *SaPolicy = SaInitPolicy;
+ return Status;
+}
+
+
+/**
+ SaInstallPolicyProtocol installs SA Policy.
+ While installed, RC assumes the Policy is ready and finalized. So please update and override
+ any setting before calling this function.
+
+ @param[in] ImageHandle Image handle of this driver.
+ @param[in] SaPolicy The pointer to SA Policy Protocol instance
+
+ @retval EFI_SUCCESS The policy is installed.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create buffer
+
+**/
+EFI_STATUS
+EFIAPI
+SaInstallPolicyProtocol (
+ IN EFI_HANDLE ImageHandle,
+ IN SA_POLICY_PROTOCOL *SaPolicy
+ )
+{
+ EFI_STATUS Status;
+
+ ///
+ /// Print SA DXE Policy
+ ///
+ SaPrintPolicyProtocol (SaPolicy);
+ GraphicsDxePolicyPrint (SaPolicy);
+ VtdPrintPolicyDxe (SaPolicy);
+
+ ///
+ /// Install protocol to to allow access to this Policy.
+ ///
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &ImageHandle,
+ &gSaPolicyProtocolGuid,
+ SaPolicy,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/Library/DxeSaPolicyLib/DxeSaPolicyLib.inf b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/Library/DxeSaPolicyLib/DxeSaPolicyLib.inf
new file mode 100644
index 0000000000..8af3d09b80
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/Library/DxeSaPolicyLib/DxeSaPolicyLib.inf
@@ -0,0 +1,48 @@
+## @file
+# Component description file for the PeiSaPolicy library.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = DxeSaPolicyLib
+FILE_GUID = B402A3A4-4B82-410E-B79C-5914880A05E7
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = DxeSaPolicyLib
+
+
+[LibraryClasses]
+BaseMemoryLib
+UefiRuntimeServicesTableLib
+UefiBootServicesTableLib
+DebugLib
+PostCodeLib
+ConfigBlockLib
+HobLib
+DxeGraphicsPolicyLib
+DxeVtdPolicyLib
+
+[Packages]
+MdePkg/MdePkg.dec
+TigerlakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+DxeSaPolicyLib.c
+DxeSaPolicyLibrary.h
+
+
+[Guids]
+gPcieDxeConfigGuid
+gMemoryDxeConfigGuid
+
+
+[Protocols]
+gSaPolicyProtocolGuid ## PRODUCES
+
+[Pcd]
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/Library/DxeSaPolicyLib/DxeSaPolicyLibrary.h b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/Library/DxeSaPolicyLib/DxeSaPolicyLibrary.h
new file mode 100644
index 0000000000..2f64e6eb0d
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/Library/DxeSaPolicyLib/DxeSaPolicyLibrary.h
@@ -0,0 +1,33 @@
+/** @file
+ Header file for the DxeSaPolicy library.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _DXE_SA_POLICY_LIBRARY_H_
+#define _DXE_SA_POLICY_LIBRARY_H_
+
+#include <Uefi.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/ConfigBlockLib.h>
+#include <CpuPcieConfig.h>
+#include <Protocol/SaPolicy.h>
+
+#define WORD_FIELD_VALID_BIT BIT15
+#define MAX_PCIE_ASPM_OVERRIDE 500
+#define MAX_PCIE_LTR_OVERRIDE 500
+///
+/// DIMM SMBus addresses
+///
+#define DIMM_SMB_SPD_P0C0D0 0xA0
+#define DIMM_SMB_SPD_P0C0D1 0xA2
+#define DIMM_SMB_SPD_P0C1D0 0xA4
+#define DIMM_SMB_SPD_P0C1D1 0xA6
+#define DIMM_SMB_SPD_P0C0D2 0xA8
+#define DIMM_SMB_SPD_P0C1D2 0xAA
+
+#endif // _DXE_SA_POLICY_LIBRARY_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/Library/PeiDxeSmmSaPlatformLib/PeiDxeSmmSaPlatformLib.inf b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/Library/PeiDxeSmmSaPlatformLib/PeiDxeSmmSaPlatformLib.inf
new file mode 100644
index 0000000000..0a632fc81a
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/Library/PeiDxeSmmSaPlatformLib/PeiDxeSmmSaPlatformLib.inf
@@ -0,0 +1,32 @@
+## @file
+# Component description file for SA Platform Lib
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiDxeSmmSaPlatformLib
+FILE_GUID = 9DB5ACB4-DB23-43AE-A283-2ABEF365CBE0
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = SaPlatformLib
+
+
+[LibraryClasses]
+BaseLib
+BaseMemoryLib
+DebugLib
+IoLib
+
+[Packages]
+MdePkg/MdePkg.dec
+TigerlakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+SaPlatformLibrary.h
+SaPlatformLibrary.c
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/Library/PeiDxeSmmSaPlatformLib/SaPlatformLibrary.c b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/Library/PeiDxeSmmSaPlatformLib/SaPlatformLibrary.c
new file mode 100644
index 0000000000..42902d795c
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/Library/PeiDxeSmmSaPlatformLib/SaPlatformLibrary.c
@@ -0,0 +1,68 @@
+/** @file
+ SA Platform Lib implementation.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include "SaPlatformLibrary.h"
+#include <Library/PciSegmentLib.h>
+#include <IndustryStandard/Pci22.h>
+#include <CpuPcieInfo.h>
+
+
+/**
+ Checks if SKU is Mobile
+
+ @retval FALSE SKU is not Mobile
+ @retval TRUE SKU is Mobile
+**/
+BOOLEAN
+EFIAPI
+IsMobileSku (
+ VOID
+ )
+{
+ UINT16 DeviceId;
+
+ DeviceId = PciSegmentRead16 (PCI_SEGMENT_LIB_ADDRESS (SA_SEG_NUM, SA_MC_BUS, SA_MC_DEV, SA_MC_FUN, R_SA_MC_DEVICE_ID));
+ if (
+ (DeviceId == V_SA_DEVICE_ID_MB_ULT_1) || \
+ (DeviceId == V_SA_DEVICE_ID_MB_ULT_2) || \
+ (DeviceId == V_SA_DEVICE_ID_MB_ULX_1) || \
+ (DeviceId == V_SA_DEVICE_ID_MB_ULX_2) \
+ ) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ Checks if SKU is Desktop
+
+ @retval FALSE SKU is not Desktop
+ @retval TRUE SKU is Desktop
+**/
+BOOLEAN
+EFIAPI
+IsDesktopSku (
+ VOID
+ )
+{
+ return FALSE;
+}
+
+/**
+ Checks if SKU is Server
+
+ @retval FALSE SKU is not Server
+ @retval TRUE SKU is Server
+**/
+BOOLEAN
+EFIAPI
+IsServerSku (
+ VOID
+ )
+{
+ return FALSE;
+}
+
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/Library/PeiDxeSmmSaPlatformLib/SaPlatformLibrary.h b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/Library/PeiDxeSmmSaPlatformLib/SaPlatformLibrary.h
new file mode 100644
index 0000000000..10513d0ea0
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/Library/PeiDxeSmmSaPlatformLib/SaPlatformLibrary.h
@@ -0,0 +1,21 @@
+/** @file
+ Header file for SA Platform Lib implementation.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _SA_PLATFORM_LIBRARY_IMPLEMENTATION_H_
+#define _SA_PLATFORM_LIBRARY_IMPLEMENTATION_H_
+
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Register/SaRegsHostBridge.h>
+#include <CpuAccess.h>
+#include <Library/SaPlatformLib.h>
+#include <Register/IgdRegs.h>
+
+#endif
--
2.24.0.windows.2
^ permalink raw reply related [flat|nested] 42+ messages in thread
* [Patch V3 35/40] TigerlakeSiliconPkg/Fru/TglCpu: Add CpuPcieRp and Vtd library instances
2021-02-05 7:40 [Patch V3 01/40] TigerlakeSiliconPkg: Add package and Include/ConfigBlock headers Heng Luo
` (32 preceding siblings ...)
2021-02-05 7:40 ` [Patch V3 34/40] TigerlakeSiliconPkg/SystemAgent: Add Acpi Tables and " Heng Luo
@ 2021-02-05 7:40 ` Heng Luo
2021-02-05 7:40 ` [Patch V3 36/40] TigerlakeSiliconPkg/Pch: Add Pch modules Heng Luo
` (4 subsequent siblings)
38 siblings, 0 replies; 42+ messages in thread
From: Heng Luo @ 2021-02-05 7:40 UTC (permalink / raw)
To: devel; +Cc: Sai Chaganty, Nate DeSimone
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3171
Adds the following files:
* Fru/TglCpu/CpuPcieRp/Library/PeiDxeSmmCpuPcieInfoFruLib
* Fru/TglCpu/Vtd/LibraryPrivate/DxeVtdInitLib
Cc: Sai Chaganty <rangasai.v.chaganty@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Signed-off-by: Heng Luo <heng.luo@intel.com>
---
Silicon/Intel/TigerlakeSiliconPkg/Fru/TglCpu/CpuPcieRp/Library/PeiDxeSmmCpuPcieInfoFruLib/CpuPcieInfoFruLib.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Fru/TglCpu/CpuPcieRp/Library/PeiDxeSmmCpuPcieInfoFruLib/PeiDxeSmmCpuPcieInfoFruLib.inf | 36 ++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Fru/TglCpu/Vtd/LibraryPrivate/DxeVtdInitLib/DxeVtdInitFruLib.c | 18 ++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Fru/TglCpu/Vtd/LibraryPrivate/DxeVtdInitLib/DxeVtdInitFruLib.inf | 39 +++++++++++++++++++++++++++++++++++++++
4 files changed, 174 insertions(+)
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglCpu/CpuPcieRp/Library/PeiDxeSmmCpuPcieInfoFruLib/CpuPcieInfoFruLib.c b/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglCpu/CpuPcieRp/Library/PeiDxeSmmCpuPcieInfoFruLib/CpuPcieInfoFruLib.c
new file mode 100644
index 0000000000..6a9bc89ecf
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglCpu/CpuPcieRp/Library/PeiDxeSmmCpuPcieInfoFruLib/CpuPcieInfoFruLib.c
@@ -0,0 +1,81 @@
+/** @file
+ CPU PCIe information library.
+
+ All function in this library is available for PEI, DXE, and SMM,
+ But do not support UEFI RUNTIME environment call.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include <Uefi/UefiBaseType.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/PciSegmentLib.h>
+#include <Register/CpuPcieRegs.h>
+#include <Library/CpuPcieInfoFruLib.h>
+#include <Library/CpuPcieInitCommon.h>
+#include <CpuPcieInfo.h>
+#include <Register/SaRegsHostBridge.h>
+#include <PcieRegs.h>
+
+/**
+ Get Maximum CPU Pcie Root Port Number
+
+ @retval Maximum CPU Pcie Root Port Number
+**/
+UINT8
+GetMaxCpuPciePortNum (
+ VOID
+ )
+{
+ return CPU_PCIE_ULT_ULX_MAX_ROOT_PORT;
+}
+
+/**
+ Get CPU 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
+GetCpuPcieRpDevFun (
+ IN UINTN RpNumber,
+ OUT UINTN *RpDev,
+ OUT UINTN *RpFun
+ )
+{
+ if (RpNumber > GetMaxCpuPciePortNum ()) {
+ DEBUG ((DEBUG_ERROR, "GetCpuPcieRpDevFun invalid RpNumber %x", RpNumber));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // For TGL - U/Y only one CPU PCIE Root port is present
+ //
+ *RpDev = 6;
+ *RpFun = 0;
+ return EFI_SUCCESS;
+}
+/**
+
+ Gets pci segment base address of PCIe root port.
+
+ @param RpIndex Root Port Index (0 based)
+
+ @return PCIe port base address.
+**/
+UINT64
+CpuPcieBase (
+ IN UINT32 RpIndex
+ )
+{
+ UINTN RpDevice;
+ UINTN RpFunction;
+ GetCpuPcieRpDevFun (RpIndex, &RpDevice, &RpFunction);
+ return PCI_SEGMENT_LIB_ADDRESS (SA_SEG_NUM, SA_MC_BUS, (UINT32) RpDevice, (UINT32) RpFunction, 0);
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglCpu/CpuPcieRp/Library/PeiDxeSmmCpuPcieInfoFruLib/PeiDxeSmmCpuPcieInfoFruLib.inf b/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglCpu/CpuPcieRp/Library/PeiDxeSmmCpuPcieInfoFruLib/PeiDxeSmmCpuPcieInfoFruLib.inf
new file mode 100644
index 0000000000..b6a40b2f7c
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglCpu/CpuPcieRp/Library/PeiDxeSmmCpuPcieInfoFruLib/PeiDxeSmmCpuPcieInfoFruLib.inf
@@ -0,0 +1,36 @@
+## @file
+# CPU PCIe information library for TigerLake PCH.
+#
+# All function in this library is available for PEI, DXE, and SMM,
+# But do not support UEFI RUNTIME environment call.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiDxeSmmCpuPcieInfoFruLib
+FILE_GUID = 59CA5352-ED46-4449-BF1C-0D0074C4D5B1
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = CpuPcieInfoFruLib
+
+
+[LibraryClasses]
+IoLib
+BaseLib
+DebugLib
+PrintLib
+PcdLib
+ConfigBlockLib
+CpuPcieInitCommonLib
+
+[Packages]
+MdePkg/MdePkg.dec
+TigerlakeSiliconPkg/SiPkg.dec
+
+[Sources]
+CpuPcieInfoFruLib.c
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglCpu/Vtd/LibraryPrivate/DxeVtdInitLib/DxeVtdInitFruLib.c b/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglCpu/Vtd/LibraryPrivate/DxeVtdInitLib/DxeVtdInitFruLib.c
new file mode 100644
index 0000000000..d6e8096da6
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglCpu/Vtd/LibraryPrivate/DxeVtdInitLib/DxeVtdInitFruLib.c
@@ -0,0 +1,18 @@
+/** @file
+ DXE FRU Library to initialize Vtd
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include <Base.h>
+
+/**
+ For device that specified by Device Num and Function Num,
+ mDevEnMap is used to check device presence.
+ 0x80 means use Device ID to detemine presence
+ 0x8F means force to update
+
+ The structure is used to check if device scope is valid when update DMAR table
+**/
+UINT16 mDevEnMap[][2] = {{0x0200, 0x80}, {0x0500, 0x80}, {0x1400, 0x80}, {0x1401, 0x80}, {0x0700, 0x80}, {0x0701, 0x80}, {0x0702, 0x80}, {0x0703, 0x80}, {0x1302, 0x8F}, {0x1303, 0x8F}};
+UINTN mDevEnMapSize = sizeof (mDevEnMap) / (sizeof (UINT16) * 2);
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglCpu/Vtd/LibraryPrivate/DxeVtdInitLib/DxeVtdInitFruLib.inf b/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglCpu/Vtd/LibraryPrivate/DxeVtdInitLib/DxeVtdInitFruLib.inf
new file mode 100644
index 0000000000..e0aa88f68a
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglCpu/Vtd/LibraryPrivate/DxeVtdInitLib/DxeVtdInitFruLib.inf
@@ -0,0 +1,39 @@
+## @file
+# Library description file for DXE Phase Vtd Init
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = DxeVtdInitFruLib
+FILE_GUID = 18690D67-08A9-4DCE-B62D-CBE3AF7CFEE7
+VERSION_STRING = 1.0
+MODULE_TYPE = DXE_DRIVER
+LIBRARY_CLASS = DxeVtdFruLib
+
+
+[LibraryClasses]
+UefiLib
+UefiRuntimeServicesTableLib
+UefiBootServicesTableLib
+DebugLib
+DxeSaPolicyLib
+
+[Packages]
+MdePkg/MdePkg.dec
+TigerlakeSiliconPkg/SiPkg.dec
+
+[Protocols]
+gSaNvsAreaProtocolGuid ## CONSUMES
+
+[Sources]
+DxeVtdInitFruLib.c
+
+[FixedPcd]
+
+[Guids]
+gTcssHobGuid ## CONSUMES
--
2.24.0.windows.2
^ permalink raw reply related [flat|nested] 42+ messages in thread
* [Patch V3 36/40] TigerlakeSiliconPkg/Pch: Add Pch modules
2021-02-05 7:40 [Patch V3 01/40] TigerlakeSiliconPkg: Add package and Include/ConfigBlock headers Heng Luo
` (33 preceding siblings ...)
2021-02-05 7:40 ` [Patch V3 35/40] TigerlakeSiliconPkg/Fru/TglCpu: Add CpuPcieRp and Vtd " Heng Luo
@ 2021-02-05 7:40 ` Heng Luo
2021-02-05 7:40 ` [Patch V3 37/40] TigerlakeSiliconPkg/SystemAgent: Add SystemAgent modules Heng Luo
` (3 subsequent siblings)
38 siblings, 0 replies; 42+ messages in thread
From: Heng Luo @ 2021-02-05 7:40 UTC (permalink / raw)
To: devel; +Cc: Sai Chaganty, Nate DeSimone
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3171
Adds the following files:
* Pch/PchInit/Dxe
* Pch/PchInit/Smm
* Pch/PchSmiDispatcher/Smm
* Pch/SmmControl/RuntimeDxe
Cc: Sai Chaganty <rangasai.v.chaganty@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Signed-off-by: Heng Luo <heng.luo@intel.com>
---
Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Dxe/PchAcpi.c | 494 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Dxe/PchCnviAcpi.c | 41 ++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Dxe/PchHdaAcpi.c | 201 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Dxe/PchInit.c | 314 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Dxe/PchInit.h | 122 ++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Dxe/PchInitDxe.c | 354 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Dxe/PchInitDxeTgl.inf | 96 ++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Dxe/PchSata.c | 89 ++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Dxe/PchSerialIo.c | 33 +++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Dxe/PchSerialIoDxe.c | 134 ++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Smm/GbeSxSmm.c | 266 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Smm/PchBiosWriteProtect.c | 137 +++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Smm/PchHdaSxSmm.c | 33 +++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Smm/PchInitSmm.c | 285 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Smm/PchInitSmm.h | 254 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Smm/PchInitSmm.inf | 110 +++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Smm/PchPcieSmm.c | 451 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Smm/PchSpiAsync.c | 67 +++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/IoTrap.c | 1284 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/IoTrap.h | 226 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmiDispatch.c | 2442 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmiDispatcher.inf | 116 ++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmiHelper.h | 40 +++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmiHelperClient.c | 57 ++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmm.h | 1043 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmCore.c | 926 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmEspi.c | 1588 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmEspi.h | 341 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmGpi.c | 263 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmHelpers.c | 332 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmHelpers.h | 155 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmPeriodicTimer.c | 667 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmPowerButton.c | 81 +++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmSw.c | 381 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmSx.c | 224 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmUsb.c | 230 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchxSmmHelpers.c | 778 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchxSmmHelpers.h | 107 ++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControl.inf | 54 +++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControlDriver.c | 394 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControlDriver.h | 130 +++++++++++++++++++++++++++++++++++++++++++++++++
41 files changed, 15340 insertions(+)
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Dxe/PchAcpi.c b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Dxe/PchAcpi.c
new file mode 100644
index 0000000000..e88afa5ded
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Dxe/PchAcpi.c
@@ -0,0 +1,494 @@
+/** @file
+ This is the driver that initializes the Intel PCH.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/HobLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#include "PchInit.h"
+#include <Protocol/PchPolicy.h>
+#include <GpioDevConfig.h>
+#include <ScsConfig.h>
+#include <Library/PchInfoLib.h>
+#include <Library/GpioLib.h>
+#include <Library/GpioNativeLib.h>
+#include <Library/PchCycleDecodingLib.h>
+#include <Library/PmcLib.h>
+#include <Library/SerialIoAccessLib.h>
+#include <Library/GbeLib.h>
+#include <PchRstHob.h>
+#include <Library/PchPcieRpLib.h>
+#include <TraceHubConfig.h>
+#include <PchReservedResources.h>
+#include <Library/PciSegmentLib.h>
+#include <Register/PchRegs.h>
+#include <Library/BaseLib.h>
+#include <Register/UsbRegs.h>
+#include <Library/PcdLib.h>
+#include <IndustryStandard/Pci22.h>
+#include <PcieRegs.h>
+#include <Library/PchPcrLib.h>
+#include <Library/PchPciBdfLib.h>
+#include <PchHybridStorageHob.h>
+#include <Library/SataLib.h>
+
+//
+// Module variables
+//
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_NVS_AREA_PROTOCOL mPchNvsAreaProtocol;
+
+/**
+ Retrieve interrupt information about a PCH device from policy
+
+ @param[in] UartNumber Uart number
+
+ @retval PCH_DEVICE_INTERRUPT_CONFIG structure with device's interrupt information
+**/
+PCH_DEVICE_INTERRUPT_CONFIG
+GetUartInterrupt (
+ IN UINT8 UartNumber
+ )
+{
+ PCH_DEVICE_INTERRUPT_CONFIG EmptyRecord;
+ UINT8 DevNum;
+ UINT8 FuncNum;
+ UINT8 Index;
+
+ ZeroMem (&EmptyRecord, sizeof (PCH_DEVICE_INTERRUPT_CONFIG));
+ DevNum = SerialIoUartDevNumber (UartNumber);
+ FuncNum = SerialIoUartFuncNumber (UartNumber);
+
+ for (Index = 0; Index < mPchConfigHob->Interrupt.NumOfDevIntConfig; Index++) {
+ if ((mPchConfigHob->Interrupt.DevIntConfig[Index].Device == DevNum) &&
+ (mPchConfigHob->Interrupt.DevIntConfig[Index].Function == FuncNum)) {
+ return mPchConfigHob->Interrupt.DevIntConfig[Index];
+ }
+ }
+ return EmptyRecord;
+}
+
+/**
+ Update ASL definitions for SerialIo devices.
+
+**/
+VOID
+UpdateSerialIoAcpiData (
+ VOID
+ )
+{
+ UINT8 Index;
+
+ for (Index = 0; Index < GetPchMaxSerialIoSpiControllersNum (); Index++) {
+ mPchNvsAreaProtocol.Area->SM0[Index] = mPchConfigHob->SerialIo.SpiDeviceConfig[Index].Mode;
+ mPchNvsAreaProtocol.Area->SC0[Index] = GetSerialIoSpiPciCfg (Index);
+ }
+ for (Index = 0; Index < GetPchMaxSerialIoI2cControllersNum (); Index++) {
+ mPchNvsAreaProtocol.Area->IM0[Index] = mPchConfigHob->SerialIo.I2cDeviceConfig[Index].Mode;
+ mPchNvsAreaProtocol.Area->IC0[Index] = GetSerialIoI2cPciCfg (Index);
+ }
+ for (Index = 0; Index < GetPchMaxSerialIoUartControllersNum (); Index++) {
+ mPchNvsAreaProtocol.Area->UM0[Index] = mPchConfigHob->SerialIo.UartDeviceConfig[Index].Mode;
+ mPchNvsAreaProtocol.Area->UC0[Index] = GetSerialIoUartPciCfg (Index);
+ mPchNvsAreaProtocol.Area->UD0[Index] = mPchConfigHob->SerialIo.UartDeviceConfig[Index].DmaEnable;
+ mPchNvsAreaProtocol.Area->UP0[Index] = mPchConfigHob->SerialIo.UartDeviceConfig[Index].PowerGating;
+ mPchNvsAreaProtocol.Area->UI0[Index] = (GetUartInterrupt (Index)).Irq;
+ }
+}
+
+#if FixedPcdGet8(PcdEmbeddedEnable) == 0x1
+/**
+ Update NVS Area for Timed GPIO devices.
+**/
+VOID
+UpdateTimedGpioSetup (
+ VOID
+ )
+{
+ mPchNvsAreaProtocol.Area->EnableTimedGpio0 = (UINT8)mPchConfigHob->Pm.EnableTimedGpio0;
+ mPchNvsAreaProtocol.Area->EnableTimedGpio1 = (UINT8)mPchConfigHob->Pm.EnableTimedGpio1;
+}
+#endif
+
+/**
+ Update NVS Area after RST PCIe Storage Remapping and before Boot
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_NOT_FOUND Couldn't fetch RstHob
+**/
+EFI_STATUS
+PchUpdateNvsAreaAfterRemapping (
+ VOID
+ )
+{
+ UINTN Index;
+ VOID *Hob;
+ PCH_RST_HOB *RstHob;
+
+ Hob = GetFirstGuidHob (&gPchRstHobGuid);
+ if (Hob == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ RstHob = (PCH_RST_HOB *) GET_GUID_HOB_DATA (Hob);
+
+ for (Index = 0; Index < PCH_MAX_RST_PCIE_STORAGE_CR; Index++) {
+ mPchNvsAreaProtocol.Area->RstPcieStorageInterfaceType[Index] = RstHob->RstCrConfiguration[Index].DeviceInterface;
+ mPchNvsAreaProtocol.Area->RstPcieStoragePmCapPtr[Index] = RstHob->SavedRemapedDeviceConfigSpace[Index].PmCapPtr;
+ mPchNvsAreaProtocol.Area->RstPcieStoragePcieCapPtr[Index] = RstHob->SavedRemapedDeviceConfigSpace[Index].PcieCapPtr;
+ mPchNvsAreaProtocol.Area->RstPcieStorageL1ssCapPtr[Index] = RstHob->SavedRemapedDeviceConfigSpace[Index].L1ssCapPtr;
+ mPchNvsAreaProtocol.Area->RstPcieStorageEpL1ssControl2[Index] = RstHob->SavedRemapedDeviceConfigSpace[Index].EndpointL1ssControl2;
+ mPchNvsAreaProtocol.Area->RstPcieStorageEpL1ssControl1[Index] = RstHob->SavedRemapedDeviceConfigSpace[Index].EndpointL1ssControl1;
+ mPchNvsAreaProtocol.Area->RstPcieStorageLtrCapPtr[Index] = RstHob->SavedRemapedDeviceConfigSpace[Index].LtrCapPtr;
+ mPchNvsAreaProtocol.Area->RstPcieStorageEpLtrData[Index] = RstHob->SavedRemapedDeviceConfigSpace[Index].EndpointLtrData;
+ mPchNvsAreaProtocol.Area->RstPcieStorageEpLctlData16[Index] = RstHob->SavedRemapedDeviceConfigSpace[Index].EndpointLctlData16;
+ mPchNvsAreaProtocol.Area->RstPcieStorageEpDctlData16[Index] = RstHob->SavedRemapedDeviceConfigSpace[Index].EndpointDctlData16;
+ mPchNvsAreaProtocol.Area->RstPcieStorageEpDctl2Data16[Index] = RstHob->SavedRemapedDeviceConfigSpace[Index].EndpointDctl2Data16;
+ mPchNvsAreaProtocol.Area->RstPcieStorageRpDctl2Data16[Index] = RstHob->SavedRemapedDeviceConfigSpace[Index].RootPortDctl2Data16;
+ mPchNvsAreaProtocol.Area->RstPcieStorageUniqueTableBar[Index] = RstHob->RstCrConfiguration[Index].EndPointUniqueMsixTableBar;
+ mPchNvsAreaProtocol.Area->RstPcieStorageUniqueTableBarValue[Index] = RstHob->RstCrConfiguration[Index].EndPointUniqueMsixTableBarValue;
+ mPchNvsAreaProtocol.Area->RstPcieStorageUniquePbaBar[Index] = RstHob->RstCrConfiguration[Index].EndPointUniqueMsixPbaBar;
+ mPchNvsAreaProtocol.Area->RstPcieStorageUniquePbaBarValue[Index] = RstHob->RstCrConfiguration[Index].EndPointUniqueMsixPbaBarValue;
+ mPchNvsAreaProtocol.Area->RstPcieStorageRootPortNum[Index] = RstHob->RstCrConfiguration[Index].RootPortNum;
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Update the Hybrid storage location NVS Area if Hybrid Storage device is present
+**/
+EFI_STATUS
+UpdateHybridStorageLocation (
+ VOID
+ )
+{
+ VOID *Hob;
+ PCH_HYBRIDSTORAGE_HOB *HybridStorageHob;
+
+ Hob = GetFirstGuidHob (&gHybridStorageHobGuid);
+ if (Hob == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ HybridStorageHob = (PCH_HYBRIDSTORAGE_HOB *) GET_GUID_HOB_DATA (Hob);
+ mPchNvsAreaProtocol.Area->HybridStorageLocation = HybridStorageHob->HybridStorageLocation;
+ return EFI_SUCCESS;
+}
+
+/**
+ PCH ACPI initialization before Boot Sript Table is closed
+ It update ACPI table and ACPI NVS area.
+
+ @param[in] Event A pointer to the Event that triggered the callback.
+ @param[in] Context A pointer to private data registered with the callback function.
+**/
+VOID
+EFIAPI
+PchAcpiOnEndOfDxe (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ DEBUG ((DEBUG_INFO, "PchAcpiOnEndOfDxe() Start\n"));
+
+ ///
+ /// Closed the event to avoid call twice when launch shell
+ ///
+ gBS->CloseEvent (Event);
+
+ //
+ // Init HDA Audio ACPI tables
+ //
+ PchHdAudioAcpiInit ();
+ //
+ // Update ASL definitions for SerialIo devices.
+ //
+ UpdateSerialIoAcpiData ();
+ UpdateCnviAcpiData ();
+#if FixedPcdGet8(PcdEmbeddedEnable) == 0x1
+ UpdateTimedGpioSetup();
+#endif
+
+ //
+ // Update Pch Nvs Area
+ //
+ PchUpdateNvsArea ();
+
+ DEBUG ((DEBUG_INFO, "PchAcpiOnEndOfDxe() End\n"));
+
+ return;
+}
+
+/**
+ Initialize Pch acpi
+ @param[in] ImageHandle Handle for the image of this driver
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_OUT_OF_RESOURCES Do not have enough resources to initialize the driver
+**/
+EFI_STATUS
+EFIAPI
+PchAcpiInit (
+ IN EFI_HANDLE ImageHandle
+ )
+{
+ EFI_STATUS Status;
+ EFI_EVENT EndOfDxeEvent;
+
+ DEBUG ((DEBUG_INFO, "Install PCH NVS protocol\n"));
+
+ Status = (gBS->AllocatePool) (EfiACPIMemoryNVS, sizeof (PCH_NVS_AREA), (VOID **) &mPchNvsAreaProtocol.Area);
+ ASSERT_EFI_ERROR (Status);
+
+ ZeroMem ((VOID *) mPchNvsAreaProtocol.Area, sizeof (PCH_NVS_AREA));
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &ImageHandle,
+ &gPchNvsAreaProtocolGuid,
+ &mPchNvsAreaProtocol,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Update the NVS Area after RST PCIe Storage Remapping
+ ///
+ PchUpdateNvsAreaAfterRemapping ();
+
+ UpdateHybridStorageLocation ();
+ //
+ // Register an end of DXE event for PCH ACPI to do tasks before invoking any UEFI drivers,
+ // applications, or connecting consoles,...
+ //
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ PchAcpiOnEndOfDxe,
+ NULL,
+ &gEfiEndOfDxeEventGroupGuid,
+ &EndOfDxeEvent
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
+
+/**
+ Update NVS area for PCIe root ports.
+**/
+STATIC
+VOID
+PcieRpUpdateNvsArea (
+ VOID
+ )
+{
+ UINT32 Index;
+
+ for (Index = 0; Index < PCH_MAX_PCIE_CLOCKS; Index++) {
+ mPchNvsAreaProtocol.Area->ClockToRootPortMap[Index] = mPchConfigHob->PcieRp.PcieClock[Index].Usage;
+ }
+}
+
+/**
+ Update ASL object before Boot
+
+ @retval EFI_STATUS
+ @retval EFI_NOT_READY The Acpi protocols are not ready.
+**/
+EFI_STATUS
+PchUpdateNvsArea (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ UINT32 HpetBaseAdress;
+ GPIO_GROUP GroupToGpeDwX[3];
+ UINT32 GroupDw[3];
+ UINTN RpDev;
+ UINTN RpFun;
+ UINT32 Data32;
+ PCH_POLICY_PROTOCOL *PchPolicy;
+ GPIO_DXE_CONFIG *GpioDxeConfig;
+ UINT64 XdciPciBase;
+ UINT64 XdciBar;
+ UINT16 PciMemConfig;
+ UINT16 TcoBase;
+ UINT8 ClearXdciBar = FALSE;
+
+ ///
+ /// Get PCH Policy Protocol
+ ///
+ Status = gBS->LocateProtocol (&gPchPolicyProtocolGuid, NULL, (VOID **)&PchPolicy);
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Get GPIO DXE Config Block
+ ///
+ Status = GetConfigBlock ((VOID *)PchPolicy, &gGpioDxeConfigGuid, (VOID *)&GpioDxeConfig);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Update ASL PCIE port address according to root port device and function
+ //
+ for (Index = 0; Index < GetPchMaxPciePortNum (); Index++) {
+ RpDev = PchPcieRpDevNumber (Index);
+ RpFun = PchPcieRpFuncNumber (Index);
+ Data32 = ((UINT8) RpDev << 16) | (UINT8) RpFun;
+ mPchNvsAreaProtocol.Area->RpAddress[Index] = Data32;
+
+ //
+ // Update Maximum Snoop Latency and Maximum No-Snoop Latency values for PCIE
+ //
+ mPchNvsAreaProtocol.Area->PcieLtrMaxSnoopLatency[Index] = mPchConfigHob->PcieRp.RootPort[Index].PcieRpCommonConfig.PcieRpLtrConfig.LtrMaxSnoopLatency;
+ mPchNvsAreaProtocol.Area->PcieLtrMaxNoSnoopLatency[Index] = mPchConfigHob->PcieRp.RootPort[Index].PcieRpCommonConfig.PcieRpLtrConfig.LtrMaxNoSnoopLatency;
+ }
+
+ //
+ // Update PCHS.
+ //
+ mPchNvsAreaProtocol.Area->PchSeries = PchSeries ();
+ //
+ // Update PCHG.
+ //
+ mPchNvsAreaProtocol.Area->PchGeneration = (UINT16) PchGeneration ();
+ //
+ // Update PSTP.
+ //
+ mPchNvsAreaProtocol.Area->PchStepping = (UINT16) PchStepping ();
+ //
+ // Update HPET base address.
+ //
+ PchHpetBaseGet (&HpetBaseAdress);
+ mPchNvsAreaProtocol.Area->HPTE = TRUE; // @todo remove the NVS, since it's always enabled.
+ mPchNvsAreaProtocol.Area->HPTB = HpetBaseAdress;
+ //
+ // Update SBREG_BAR.
+ //
+ mPchNvsAreaProtocol.Area->SBRG = PCH_PCR_BASE_ADDRESS;
+
+ //
+ // Update base address
+ //
+ mPchNvsAreaProtocol.Area->PMBS = PmcGetAcpiBase ();
+ mPchNvsAreaProtocol.Area->PWRM = PmcGetPwrmBase ();
+ PchTcoBaseGet (&TcoBase);
+ mPchNvsAreaProtocol.Area->TcoBase = TcoBase;
+
+ //
+ // Update PCH PID info
+ //
+ mPchNvsAreaProtocol.Area->IclkPid = PchPcrGetPid (PchIpIclk);
+
+ //
+ // Update GPIO device ACPI variables
+ //
+ mPchNvsAreaProtocol.Area->SGIR = mPchConfigHob->Interrupt.GpioIrqRoute;
+ mPchNvsAreaProtocol.Area->GPHD = (UINT8)GpioDxeConfig->HideGpioAcpiDevice;
+
+ //
+ // Update GPP_X to GPE_DWX mapping.
+ //
+ GpioGetGroupDwToGpeDwX (
+ &GroupToGpeDwX[0], &GroupDw[0],
+ &GroupToGpeDwX[1], &GroupDw[1],
+ &GroupToGpeDwX[2], &GroupDw[2]
+ );
+
+ //
+ // GEI0/1/2 and GED0/1/2 are objects for informing how GPIO groups are mapped to GPE0.
+ // If Group is mapped to 1-Tier GPE information is also stored on what Group DW
+ // is mapped to GPE_DWx. Because GPE_DWx register is 32 bits large if groups have more than
+ // 32 pads only part of it can be mapped.
+ //
+ // GEIx - GroupIndex mapped to GPE0_DWx
+ // GEDx - DoubleWorld part of Group: 0 - pins 31-0, 1 - pins 63-32, ...
+ //
+ mPchNvsAreaProtocol.Area->GEI0 = (UINT8) GpioGetGroupIndexFromGroup (GroupToGpeDwX[0]);
+ mPchNvsAreaProtocol.Area->GEI1 = (UINT8) GpioGetGroupIndexFromGroup (GroupToGpeDwX[1]);
+ mPchNvsAreaProtocol.Area->GEI2 = (UINT8) GpioGetGroupIndexFromGroup (GroupToGpeDwX[2]);
+ mPchNvsAreaProtocol.Area->GED0 = (UINT8) GroupDw[0];
+ mPchNvsAreaProtocol.Area->GED1 = (UINT8) GroupDw[1];
+ mPchNvsAreaProtocol.Area->GED2 = (UINT8) GroupDw[2];
+
+ //
+ // SCS Configuration
+ //
+
+ PcieRpUpdateNvsArea ();
+
+ //
+ // SATA configuration.
+ //
+ mPchNvsAreaProtocol.Area->SataPortPresence = GetSataPortPresentStatus (0);
+ DEBUG ((DEBUG_INFO, "SataPortPresence: 0x%x\n", mPchNvsAreaProtocol.Area->SataPortPresence));
+
+ //
+ // CPU SKU
+ //
+ mPchNvsAreaProtocol.Area->CpuSku = 0;
+ mPchNvsAreaProtocol.Area->PsOnEnable = (UINT8)mPchConfigHob->Pm.PsOnEnable;
+
+ for (Index = 0; Index < GetPchMaxPciePortNum (); Index++) {
+ mPchNvsAreaProtocol.Area->LtrEnable[Index] = (UINT8)mPchConfigHob->PcieRp.RootPort[Index].PcieRpCommonConfig.LtrEnable;
+ }
+
+ mPchNvsAreaProtocol.Area->GBES = IsGbePresent ();
+
+ //
+ // Update PCH Trace Hub Mode
+ //
+ mPchNvsAreaProtocol.Area->PchTraceHubMode = (UINT8) mPchConfigHob->PchTraceHub.PchTraceHubMode;
+
+ //
+ // Saving GCTL value into PCH NVS area
+ //
+
+ XdciPciBase = PchXdciPciCfgBase ();
+
+ //
+ // Determine Base address for Base address register (Offset 0x10)
+ //
+ if (PciSegmentRead32 (XdciPciBase) != 0xFFFFFFFF) {
+
+ XdciBar = PciSegmentRead32 (XdciPciBase + PCI_BASE_ADDRESSREG_OFFSET) & 0xFFFFFFF0;
+
+ if ((PciSegmentRead32 (XdciPciBase + PCI_BASE_ADDRESSREG_OFFSET) & B_PCI_BAR_MEMORY_TYPE_MASK) == B_PCI_BAR_MEMORY_TYPE_64) {
+ XdciBar += (UINT64)PciSegmentRead32 (XdciPciBase + (PCI_BASE_ADDRESSREG_OFFSET + 4)) << 32;
+ }
+
+ if (XdciBar == 0x0) {
+ ClearXdciBar = TRUE;
+ PciSegmentWrite32 ((XdciPciBase + PCI_BASE_ADDRESSREG_OFFSET), PcdGet32 (PcdSiliconInitTempMemBaseAddr));
+ XdciBar = PciSegmentRead32 (XdciPciBase + PCI_BASE_ADDRESSREG_OFFSET) & 0xFFFFFFF0;
+
+ if ((PciSegmentRead32 (XdciPciBase + PCI_BASE_ADDRESSREG_OFFSET) & B_PCI_BAR_MEMORY_TYPE_MASK) == B_PCI_BAR_MEMORY_TYPE_64) {
+ XdciBar += (UINT64)PciSegmentRead32 (XdciPciBase + (PCI_BASE_ADDRESSREG_OFFSET + 4)) << 32;
+ }
+ }
+
+ //
+ // Enable Pci Memconfig to read the correct value for GCTL register
+ //
+ PciMemConfig = PciSegmentRead16 (XdciPciBase + PCI_COMMAND_OFFSET);
+ PciSegmentWrite16 (XdciPciBase + PCI_COMMAND_OFFSET, PciMemConfig | (EFI_PCI_COMMAND_BUS_MASTER | EFI_PCI_COMMAND_MEMORY_SPACE));
+
+ mPchNvsAreaProtocol.Area->PchxDCIPwrDnScale = MmioRead32(XdciBar + R_XDCI_MEM_GCTL);
+ DEBUG ((DEBUG_INFO, "PchxDCIPwrDnScale 0x%x\n", (UINT64)mPchNvsAreaProtocol.Area->PchxDCIPwrDnScale));
+ //
+ // Disable Pci Memconfig & clear Base address
+ //
+ PciSegmentWrite16(XdciPciBase + PCI_COMMAND_OFFSET, PciMemConfig);
+
+ if (ClearXdciBar == TRUE) {
+ PciSegmentWrite32 ((XdciPciBase + PCI_BASE_ADDRESSREG_OFFSET), 0x0);
+ PciSegmentWrite32 ((XdciPciBase + (PCI_BASE_ADDRESSREG_OFFSET + 4)), 0x0);
+ }
+ }
+
+ return Status;
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Dxe/PchCnviAcpi.c b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Dxe/PchCnviAcpi.c
new file mode 100644
index 0000000000..5c8e1ce5b4
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Dxe/PchCnviAcpi.c
@@ -0,0 +1,41 @@
+/** @file
+ Initializes PCH CNVi device ACPI data.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <CnviConfigHob.h>
+#include "PchInit.h"
+#include <Register/PchPcrRegs.h>
+
+/**
+ Update ASL definitions for CNVi device.
+
+ @retval EFI_SUCCESS The function completed successfully
+**/
+EFI_STATUS
+UpdateCnviAcpiData (
+ VOID
+ )
+{
+ EFI_PEI_HOB_POINTERS HobPtr;
+ CNVI_CONFIG_HOB *CnviConfigHob;
+
+ DEBUG ((DEBUG_INFO, "UpdateCnviAcpiData() Start\n"));
+
+ // Get CNVi Config HOB.
+ HobPtr.Guid = GetFirstGuidHob (&gCnviConfigHobGuid);
+ if (HobPtr.Guid != NULL) {
+ CnviConfigHob = (CNVI_CONFIG_HOB *) GET_GUID_HOB_DATA (HobPtr.Guid);
+ mPchNvsAreaProtocol.Area->CnviMode = (UINT8)CnviConfigHob->Mode;
+ mPchNvsAreaProtocol.Area->CnviBtCore = (UINT8)CnviConfigHob->BtCore;
+ mPchNvsAreaProtocol.Area->CnviBtAudioOffload = (UINT8)CnviConfigHob->BtAudioOffload;
+ }
+ mPchNvsAreaProtocol.Area->CnviPortId = PID_CNVI;
+ DEBUG ((DEBUG_INFO, "UpdateCnviAcpiData() End\n"));
+
+ return EFI_SUCCESS;
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Dxe/PchHdaAcpi.c b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Dxe/PchHdaAcpi.c
new file mode 100644
index 0000000000..dbdb028483
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Dxe/PchHdaAcpi.c
@@ -0,0 +1,201 @@
+
+/** @file
+ Initializes the PCH HD Audio ACPI Tables.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PciSegmentLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Protocol/AcpiTable.h>
+#include <DxeHdaNhlt.h>
+#include <Library/DxeHdaNhltLib.h>
+#include "PchInit.h"
+#include <HdAudioConfig.h>
+#include <PchConfigHob.h>
+#include <Library/PcdLib.h>
+#include <Protocol/PchPolicy.h>
+#include <HdAudioConfig.h>
+#include <IndustryStandard/Pci30.h>
+#include <Register/PchRegs.h>
+#include <Library/PchPciBdfLib.h>
+#include <Library/PchInfoLib.h>
+
+#define XTAL_FREQ_38P4MHZ 1
+
+/**
+ Retrieves address of NHLT table from XSDT/RSDT.
+
+ @retval NHLT_ACPI_TABLE* Pointer to NHLT table if found
+ @retval NULL NHLT could not be found
+**/
+NHLT_ACPI_TABLE *
+LocateNhltAcpiTable (
+ VOID
+ )
+{
+ EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp;
+ EFI_ACPI_DESCRIPTION_HEADER *Xsdt;
+ NHLT_ACPI_TABLE *Nhlt;
+ UINTN Index;
+ UINT64 Data64;
+ EFI_STATUS Status;
+ Rsdp = NULL;
+ Xsdt = NULL;
+ Nhlt = NULL;
+
+ ///
+ /// Find the AcpiSupport protocol returns RSDP (or RSD PTR) address.
+ ///
+ DEBUG ((DEBUG_INFO, "LocateNhltAcpiTable() Start\n"));
+
+ Status = EfiGetSystemConfigurationTable (&gEfiAcpiTableGuid, (VOID *) &Rsdp);
+ if (EFI_ERROR (Status) || (Rsdp == NULL)) {
+ DEBUG ((DEBUG_ERROR, "EFI_ERROR or Rsdp == NULL\n"));
+ return NULL;
+ }
+
+ Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN) Rsdp->XsdtAddress;
+ if (Xsdt == NULL || Xsdt->Signature != EFI_ACPI_5_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) {
+ // If XSDT has not been found, check RSDT
+ Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN) Rsdp->RsdtAddress;
+ if (Xsdt == NULL || Xsdt->Signature != EFI_ACPI_5_0_ROOT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) {
+ DEBUG ((DEBUG_ERROR, "XSDT/RSDT == NULL or wrong signature\n"));
+ return NULL;
+ }
+ }
+
+ for (Index = sizeof (EFI_ACPI_DESCRIPTION_HEADER); Index < Xsdt->Length; Index = Index + sizeof (UINT64)) {
+ Data64 = *(UINT64 *) ((UINT8 *) Xsdt + Index);
+ Nhlt = (NHLT_ACPI_TABLE *) (UINTN) Data64;
+ if (Nhlt != NULL && Nhlt->Header.Signature == NHLT_ACPI_TABLE_SIGNATURE) {
+ break;
+ }
+ Nhlt = NULL;
+ }
+
+ if (Nhlt == NULL || Nhlt->Header.Signature != NHLT_ACPI_TABLE_SIGNATURE) {
+ DEBUG ((DEBUG_ERROR, "Nhlt == NULL or wrong signature\n"));
+ return NULL;
+ }
+
+ DEBUG ((DEBUG_INFO, "Found NhltTable, Address = 0x%016x\n", Nhlt));
+
+ return Nhlt;
+}
+
+/**
+ Sets NVS ACPI variables for HDAS._DSM and SNDW._DSD accordingly to policy.
+
+ @param[in] NhltAcpiTableAddress
+ @param[in] NhltAcpiTableLength
+ @param[in] *HdAudioConfigHob
+ @param[in] *HdAudioDxeConfig
+**/
+VOID
+UpdateHdaAcpiData (
+ IN UINT64 NhltAcpiTableAddress,
+ IN UINT32 NhltAcpiTableLength,
+ IN CONST HDAUDIO_HOB *HdAudioConfigHob,
+ IN CONST HDAUDIO_DXE_CONFIG *HdAudioDxeConfig
+ )
+{
+ DEBUG ((DEBUG_INFO, "UpdateHdaAcpiData():\n NHLT Address = 0x%016x, Length = 0x%08x\n", NhltAcpiTableAddress, NhltAcpiTableLength));
+ DEBUG ((DEBUG_INFO, " FeatureMask = 0x%08x\n", HdAudioDxeConfig->DspFeatureMask));
+
+ mPchNvsAreaProtocol.Area->XTAL = XTAL_FREQ_38P4MHZ;
+ mPchNvsAreaProtocol.Area->NHLA = NhltAcpiTableAddress;
+ mPchNvsAreaProtocol.Area->NHLL = NhltAcpiTableLength;
+ mPchNvsAreaProtocol.Area->ADFM = HdAudioDxeConfig->DspFeatureMask;
+
+ if (HdAudioConfigHob->DspEnable || HdAudioConfigHob->DspUaaCompliance == FALSE) {
+ mPchNvsAreaProtocol.Area->SWQ0 = HdAudioConfigHob->AudioLinkSndw1 ? 0 : BIT1;
+ mPchNvsAreaProtocol.Area->SWQ1 = HdAudioConfigHob->AudioLinkSndw2 ? 0 : BIT1;
+ mPchNvsAreaProtocol.Area->SWQ2 = HdAudioConfigHob->AudioLinkSndw3 ? 0 : BIT1;
+ mPchNvsAreaProtocol.Area->SWQ3 = HdAudioConfigHob->AudioLinkSndw4 ? 0 : BIT1;
+ } else {
+ mPchNvsAreaProtocol.Area->SWQ0 = BIT1;
+ mPchNvsAreaProtocol.Area->SWQ1 = BIT1;
+ mPchNvsAreaProtocol.Area->SWQ2 = BIT1;
+ mPchNvsAreaProtocol.Area->SWQ3 = BIT1;
+ }
+
+ mPchNvsAreaProtocol.Area->SWMC = GetPchHdaMaxSndwLinkNum ();
+
+ mPchNvsAreaProtocol.Area->ACS0 = (UINT8)HdAudioDxeConfig->SndwConfig[0].AutonomousClockStop;
+ mPchNvsAreaProtocol.Area->ACS1 = (UINT8)HdAudioDxeConfig->SndwConfig[1].AutonomousClockStop;
+ mPchNvsAreaProtocol.Area->ACS2 = (UINT8)HdAudioDxeConfig->SndwConfig[2].AutonomousClockStop;
+ mPchNvsAreaProtocol.Area->ACS3 = (UINT8)HdAudioDxeConfig->SndwConfig[3].AutonomousClockStop;
+
+ mPchNvsAreaProtocol.Area->DAI0 = (UINT8)HdAudioDxeConfig->SndwConfig[0].DataOnActiveIntervalSelect;
+ mPchNvsAreaProtocol.Area->DAI1 = (UINT8)HdAudioDxeConfig->SndwConfig[1].DataOnActiveIntervalSelect;
+ mPchNvsAreaProtocol.Area->DAI2 = (UINT8)HdAudioDxeConfig->SndwConfig[2].DataOnActiveIntervalSelect;
+ mPchNvsAreaProtocol.Area->DAI3 = (UINT8)HdAudioDxeConfig->SndwConfig[3].DataOnActiveIntervalSelect;
+
+ mPchNvsAreaProtocol.Area->DOD0 = (UINT8)HdAudioDxeConfig->SndwConfig[0].DataOnDelaySelect;
+ mPchNvsAreaProtocol.Area->DOD1 = (UINT8)HdAudioDxeConfig->SndwConfig[1].DataOnDelaySelect;
+ mPchNvsAreaProtocol.Area->DOD2 = (UINT8)HdAudioDxeConfig->SndwConfig[2].DataOnDelaySelect;
+ mPchNvsAreaProtocol.Area->DOD3 = (UINT8)HdAudioDxeConfig->SndwConfig[3].DataOnDelaySelect;
+}
+
+/**
+ Initialize Intel High Definition Audio ACPI Tables
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_LOAD_ERROR ACPI table cannot be installed
+ @retval EFI_UNSUPPORTED ACPI table not set because DSP is disabled
+**/
+EFI_STATUS
+PchHdAudioAcpiInit (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINT64 HdaPciBase;
+ CONST HDAUDIO_HOB *HdAudioConfigHob;
+ PCH_POLICY_PROTOCOL *PchPolicy;
+ HDAUDIO_DXE_CONFIG *HdAudioDxeConfig;
+ NHLT_ACPI_TABLE *NhltTable;
+
+
+ DEBUG ((DEBUG_INFO, "PchHdAudioAcpiInit() Start\n"));
+
+ HdAudioConfigHob = &mPchConfigHob->HdAudio;
+
+ ///
+ /// Get PCH Policy Protocol
+ ///
+ Status = gBS->LocateProtocol (&gPchPolicyProtocolGuid, NULL, (VOID **)&PchPolicy);
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Get HD Audio DXE Config Block
+ ///
+ Status = GetConfigBlock ((VOID *)PchPolicy, &gHdAudioDxeConfigGuid, (VOID *)&HdAudioDxeConfig);
+ ASSERT_EFI_ERROR (Status);
+
+ HdaPciBase = HdaPciCfgBase ();
+
+ if ((PciSegmentRead16 (HdaPciBase + PCI_VENDOR_ID_OFFSET) == 0xFFFF) || (HdAudioConfigHob->DspEnable == FALSE)) {
+ // Do not set ACPI tables if HDAudio is Function disabled or DSP is disabled
+ DEBUG ((DEBUG_INFO, "AudioDSP: Non-HDAudio ACPI Table (NHLT) not set!\n"));
+ return EFI_UNSUPPORTED;
+ }
+
+ NhltTable = LocateNhltAcpiTable ();
+ if (NhltTable == NULL) {
+ return EFI_LOAD_ERROR;
+ }
+
+ UpdateHdaAcpiData ((UINT64) (UINTN) NhltTable, (UINT32) (NhltTable->Header.Length), HdAudioConfigHob, HdAudioDxeConfig);
+ DEBUG_CODE ( NhltAcpiTableDump (NhltTable); );
+
+ DEBUG ((DEBUG_INFO, "PchHdAudioAcpiInit() End - Status = %r\n", Status));
+ return Status;
+}
+
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Dxe/PchInit.c b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Dxe/PchInit.c
new file mode 100644
index 0000000000..734d4e295a
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Dxe/PchInit.c
@@ -0,0 +1,314 @@
+/** @file
+ This is the Common driver that initializes the Intel PCH.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/PciSegmentLib.h>
+#include <Library/TimerLib.h>
+#include <Library/S3BootScriptLib.h>
+#include <Library/HobLib.h>
+
+#include "PchInit.h"
+#include <PchPolicyCommon.h>
+#include <Library/SpiCommonLib.h>
+#include <Library/PmcPrivateLib.h>
+#include <Library/PchDmiLib.h>
+#include <Library/SiScheduleResetLib.h>
+#include <Library/PchCycleDecodingLib.h>
+#include <Library/PchPcrLib.h>
+#include <IndustryStandard/Pci30.h>
+#include <Library/SpiAccessPrivateLib.h>
+#include <Register/PchRegs.h>
+#include <Register/PchPcrRegs.h>
+#include <Register/PchRegsLpc.h>
+#include <Register/SpiRegs.h>
+#include <Register/PchRegsPsth.h>
+#include <Register/PmcRegs.h>
+#include <Register/HdaRegs.h>
+#include <Library/GpioCheckConflictLib.h>
+#include <Library/PchPciBdfLib.h>
+#include <Library/PchInfoLib.h>
+
+//
+// Module variables
+//
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_CONFIG_HOB *mPchConfigHob;
+
+//
+// EFI_EVENT
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_EVENT mHeciEvent;
+
+/**
+ Common PchInit Module Entry Point
+**/
+VOID
+PchInitEntryPointCommon (
+ VOID
+ )
+{
+ EFI_PEI_HOB_POINTERS HobPtr;
+
+ DEBUG ((DEBUG_INFO, "PchInitEntryPointCommon() Start\n"));
+
+ //
+ // Get PCH Config HOB.
+ //
+ HobPtr.Guid = GetFirstGuidHob (&gPchConfigHobGuid);
+ ASSERT (HobPtr.Guid != NULL);
+ mPchConfigHob = (PCH_CONFIG_HOB *) GET_GUID_HOB_DATA (HobPtr.Guid);
+
+ DEBUG ((DEBUG_INFO, "PchInitEntryPointCommon() End\n"));
+
+ return;
+}
+
+/**
+ Lock SPI register before boot
+**/
+VOID
+LockSpiConfiguration (
+ VOID
+ )
+{
+ UINTN Index;
+ UINT16 Data16;
+ UINT16 Data16And;
+ UINT16 Data16Or;
+ UINT32 Data32;
+ UINT32 DlockValue;
+ UINT64 PciSpiRegBase;
+ UINT32 PchSpiBar0;
+ UINT32 Timer;
+
+ PciSpiRegBase = SpiPciCfgBase ();
+
+ //
+ // Check for SPI controller presence before programming
+ //
+ if (PciSegmentRead16 (PciSpiRegBase + PCI_VENDOR_ID_OFFSET) == 0xFFFF) {
+ return;
+ }
+
+ //
+ // Make sure SPI BAR0 has fixed address before writing to boot script.
+ // The same base address is set in PEI and will be used during resume.
+ //
+ PchSpiBar0 = PCH_SPI_BASE_ADDRESS;
+
+ PciSegmentAnd8 (PciSpiRegBase + PCI_COMMAND_OFFSET, (UINT8) ~EFI_PCI_COMMAND_MEMORY_SPACE);
+ PciSegmentWrite32 (PciSpiRegBase + R_SPI_CFG_BAR0, PchSpiBar0);
+ PciSegmentOr8 (PciSpiRegBase + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_MEMORY_SPACE);
+
+ //
+ // Locking for security reasons only if Extended BIOS Range Decode is supported
+ //
+ if (IsExtendedBiosRangeDecodeSupported ()) {
+ //
+ // Before setting FLOCKDN lock Extended BIOS Range configuration
+ // All configuration of this feature shall be done already at this moment
+ //
+ PciSegmentOr32 (PciSpiRegBase + R_SPI_CFG_BC, BIT28);
+ S3BootScriptSavePciCfgWrite (
+ S3BootScriptWidthUint32,
+ (UINTN) PciSpiRegBase + R_SPI_CFG_BC,
+ 1,
+ (VOID *) (UINTN) (PciSpiRegBase + R_SPI_CFG_BC)
+ );
+ }
+
+ //
+ // Program the Flash Protection Range Register based on policy
+ //
+ DlockValue = MmioRead32 (PchSpiBar0 + R_SPI_MEM_DLOCK);
+ for (Index = 0; Index < PCH_FLASH_PROTECTED_RANGES; ++Index) {
+ if ((mPchConfigHob->ProtectRange[Index].WriteProtectionEnable ||
+ mPchConfigHob->ProtectRange[Index].ReadProtectionEnable) != TRUE) {
+ continue;
+ }
+
+ //
+ // Proceed to program the register after ensure it is enabled
+ //
+ Data32 = 0;
+ Data32 |= (mPchConfigHob->ProtectRange[Index].WriteProtectionEnable == TRUE) ? B_SPI_MEM_PRX_WPE : 0;
+ Data32 |= (mPchConfigHob->ProtectRange[Index].ReadProtectionEnable == TRUE) ? B_SPI_MEM_PRX_RPE : 0;
+ Data32 |= ((UINT32) mPchConfigHob->ProtectRange[Index].ProtectedRangeLimit << N_SPI_MEM_PRX_PRL) & B_SPI_MEM_PRX_PRL_MASK;
+ Data32 |= ((UINT32) mPchConfigHob->ProtectRange[Index].ProtectedRangeBase << N_SPI_MEM_PRX_PRB) & B_SPI_MEM_PRX_PRB_MASK;
+ DEBUG ((DEBUG_INFO, "Protected range %d: 0x%08x \n", Index, Data32));
+
+ DlockValue |= (UINT32) (B_SPI_MEM_DLOCK_PR0LOCKDN << Index);
+ MmioWrite32 ((UINTN) (PchSpiBar0 + (R_SPI_MEM_PR0 + (Index * S_SPI_MEM_PRX))), Data32);
+ S3BootScriptSaveMemWrite (
+ S3BootScriptWidthUint32,
+ (UINTN) (PchSpiBar0 + (R_SPI_MEM_PR0 + (Index * S_SPI_MEM_PRX))),
+ 1,
+ (VOID *) (UINTN) (PchSpiBar0 + (R_SPI_MEM_PR0 + (Index * S_SPI_MEM_PRX)))
+ );
+ }
+ //
+ // Program DLOCK register
+ //
+ MmioWrite32 ((UINTN) (PchSpiBar0 + R_SPI_MEM_DLOCK), DlockValue);
+ S3BootScriptSaveMemWrite (
+ S3BootScriptWidthUint32,
+ (UINTN) (PchSpiBar0 + R_SPI_MEM_DLOCK),
+ 1,
+ (VOID *) (UINTN) (PchSpiBar0 + R_SPI_MEM_DLOCK)
+ );
+
+ ///
+ /// PCH BIOS Spec Section 3.6 Flash Security Recommendation
+ /// In PCH SPI controller the BIOS should set the Flash Configuration Lock-Down bit
+ /// (SPI_BAR0 + 04[15]) at end of post. When set to 1, those Flash Program Registers
+ /// that are locked down by this FLOCKDN bit cannot be written.
+ /// Please refer to the EDS for which program registers are impacted.
+ /// Additionally BIOS must program SPI_BAR0 + 0x04 BIT11 (WRSDIS) to disable Write Status in HW sequencing
+ ///
+
+ //
+ // Ensure there is no pending SPI trasaction before setting lock bits
+ //
+ Timer = 0;
+ while (MmioRead16 (PchSpiBar0 + R_SPI_MEM_HSFSC) & B_SPI_MEM_HSFSC_SCIP) {
+ if (Timer > SPI_WAIT_TIME) {
+ //
+ // SPI transaction is pending too long at this point, exit with error.
+ //
+ DEBUG ((DEBUG_ERROR, "SPI Cycle timeout\n"));
+ ASSERT (FALSE);
+ break;
+ }
+ MicroSecondDelay (SPI_WAIT_PERIOD);
+ Timer += SPI_WAIT_PERIOD;
+ }
+
+ Data16And = B_SPI_MEM_HSFSC_SCIP;
+ Data16 = 0;
+ S3BootScriptSaveMemPoll (
+ S3BootScriptWidthUint16,
+ PchSpiBar0 + R_SPI_MEM_HSFSC,
+ &Data16And,
+ &Data16,
+ SPI_WAIT_PERIOD,
+ SPI_WAIT_TIME / SPI_WAIT_PERIOD
+ );
+
+ //
+ // Clear any outstanding status
+ //
+ Data16Or = B_SPI_MEM_HSFSC_SAF_DLE
+ | B_SPI_MEM_HSFSC_SAF_ERROR
+ | B_SPI_MEM_HSFSC_AEL
+ | B_SPI_MEM_HSFSC_FCERR
+ | B_SPI_MEM_HSFSC_FDONE;
+ Data16And = 0xFFFF;
+ MmioAndThenOr16 (PchSpiBar0 + R_SPI_MEM_HSFSC, Data16And, Data16Or);
+ S3BootScriptSaveMemReadWrite (
+ S3BootScriptWidthUint16,
+ PchSpiBar0 + R_SPI_MEM_HSFSC,
+ &Data16Or,
+ &Data16And
+ );
+
+ //
+ // Set WRSDIS
+ //
+ Data16Or = B_SPI_MEM_HSFSC_WRSDIS;
+ Data16And = 0xFFFF;
+ MmioAndThenOr16 (PchSpiBar0 + R_SPI_MEM_HSFSC, Data16And, Data16Or);
+ S3BootScriptSaveMemReadWrite (
+ S3BootScriptWidthUint16,
+ PchSpiBar0 + R_SPI_MEM_HSFSC,
+ &Data16Or,
+ &Data16And
+ );
+
+ //
+ // Set FLOCKDN
+ //
+ Data16Or = B_SPI_MEM_HSFSC_FLOCKDN;
+ Data16And = 0xFFFF;
+ MmioAndThenOr16 (PchSpiBar0 + R_SPI_MEM_HSFSC, Data16And, Data16Or);
+ S3BootScriptSaveMemReadWrite (
+ S3BootScriptWidthUint16,
+ PchSpiBar0 + R_SPI_MEM_HSFSC,
+ &Data16Or,
+ &Data16And
+ );
+
+ ///
+ /// SPI Flash Programming Guide Section 5.5.2 Vendor Component Lock
+ /// It is strongly recommended that BIOS sets the Vendor Component Lock (VCL) bits. VCL applies
+ /// the lock to both VSCC0 and VSCC1 even if VSCC0 is not used. Without the VCL bits set, it is
+ /// possible to make Host/GbE VSCC register(s) changes in that can cause undesired host and
+ /// integrated GbE Serial Flash functionality.
+ ///
+ MmioOr32 ((UINTN) (PchSpiBar0 + R_SPI_MEM_SFDP0_VSCC0), B_SPI_MEM_SFDP0_VSCC0_VCL);
+ S3BootScriptSaveMemWrite (
+ S3BootScriptWidthUint32,
+ (UINTN) (PchSpiBar0 + R_SPI_MEM_SFDP0_VSCC0),
+ 1,
+ (VOID *) (UINTN) (PchSpiBar0 + R_SPI_MEM_SFDP0_VSCC0)
+ );
+}
+
+/**
+ Set HD Audio PME bit
+**/
+VOID
+ConfigureHdAudioPme (
+ VOID
+ )
+{
+ UINT64 HdaPciBase;
+
+ HdaPciBase = HdaPciCfgBase ();
+
+ if (PciSegmentRead16 (HdaPciBase + PCI_VENDOR_ID_OFFSET) == 0xFFFF) {
+ return;
+ }
+
+ ///
+ /// PME Enable for Audio controller
+ ///
+ if (mPchConfigHob->HdAudio.Pme == TRUE) {
+ PciSegmentOr32 (HdaPciBase + R_HDA_CFG_PCS, (UINT32) B_HDA_CFG_PCS_PMEE);
+ }
+}
+
+/**
+ Set eSPI BME bit
+**/
+VOID
+ConfigureEspiBme (
+ VOID
+ )
+{
+ UINT64 EspiPciBase;
+
+ EspiPciBase = EspiPciCfgBase ();
+
+ if (PciSegmentRead16 (EspiPciBase + PCI_VENDOR_ID_OFFSET) == 0xFFFF) {
+ return;
+ }
+ if ((PciSegmentRead32 (EspiPciBase + R_ESPI_CFG_PCBC) & B_ESPI_CFG_PCBC_ESPI_EN) == 0) {
+ return;
+ }
+
+ //
+ // Refer to PCH BWG.
+ // To enable eSPI bus mastering BIOS must enable BME in eSPI controller
+ // and also set BME bit in the respective slave devices through Configuration
+ // and Capabilities register of each slave using Get_Configuration and Set_Configuration functionality.
+ //
+ // NOTE: The setting is also done in PEI, but might be cleared by PCI bus during PCI enumeration.
+ // Therefore, reeable it after PCI enumeration done.
+ //
+ if (mPchConfigHob->Espi.BmeMasterSlaveEnabled == TRUE) {
+ PciSegmentOr8 (EspiPciBase + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_BUS_MASTER);
+ }
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Dxe/PchInit.h b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Dxe/PchInit.h
new file mode 100644
index 0000000000..0d6647e3f3
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Dxe/PchInit.h
@@ -0,0 +1,122 @@
+/** @file
+ Header file for PCH Initialization Driver.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PCH_INIT_DXE_H_
+#define _PCH_INIT_DXE_H_
+
+#include <SiConfigHob.h>
+#include <PchConfigHob.h>
+#include <Protocol/PchNvsArea.h>
+
+//
+// Data definitions
+//
+extern EFI_HANDLE mImageHandle;
+
+//
+// Pch NVS area definition
+//
+extern PCH_NVS_AREA_PROTOCOL mPchNvsAreaProtocol;
+
+extern PCH_CONFIG_HOB *mPchConfigHob;
+extern SI_CONFIG_HOB_DATA *mSiConfigHobData;
+
+//
+// Function Prototype
+//
+
+//
+// Local function prototypes
+//
+/**
+ Common PchInit Module Entry Point
+**/
+VOID
+PchInitEntryPointCommon (
+ VOID
+ );
+
+/**
+ Calls Boot Os Hand off routine for each Serial IO Controller
+**/
+VOID
+ConfigureSerialIoAtBoot (
+ VOID
+ );
+
+/**
+ Puts all SerialIo controllers (except UARTs in debug mode) in D3.
+ Clears MemoryEnable for all PCI-mode controllers on S3 resume
+**/
+VOID
+ConfigureSerialIoAtS3Resume (
+ VOID
+ );
+
+/**
+ Add Serial Io UART Hidden Handles
+**/
+VOID
+CreateSerialIoUartHiddenHandle (
+ VOID
+ );
+
+/**
+ Initialize Intel High Definition Audio ACPI Tables
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_LOAD_ERROR ACPI table cannot be installed
+ @retval EFI_UNSUPPORTED ACPI table not set because DSP is disabled
+**/
+EFI_STATUS
+PchHdAudioAcpiInit (
+ VOID
+ );
+
+/**
+ Perform the remaining configuration on SATA to perform device detection,
+ then set the SATA SPD and PxE corresponding, and set the Register Lock on PCH SATA
+**/
+VOID
+ConfigureSataOnEndOfDxe (
+ VOID
+ );
+
+/**
+ Update ASL data for CNVI Device.
+
+ @retval EFI_SUCCESS The function completed successfully
+**/
+EFI_STATUS
+UpdateCnviAcpiData (
+ VOID
+ );
+
+/**
+ Initialize Pch acpi
+ @param[in] ImageHandle Handle for the image of this driver
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_OUT_OF_RESOURCES Do not have enough resources to initialize the driver
+**/
+EFI_STATUS
+EFIAPI
+PchAcpiInit (
+ IN EFI_HANDLE ImageHandle
+ );
+
+/**
+ Update ASL object before Boot
+
+ @retval EFI_STATUS
+ @retval EFI_NOT_READY The Acpi protocols are not ready.
+**/
+EFI_STATUS
+PchUpdateNvsArea (
+ VOID
+ );
+
+#endif // _PCH_INIT_DXE_H_
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Dxe/PchInitDxe.c b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Dxe/PchInitDxe.c
new file mode 100644
index 0000000000..1d4f08a86c
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Dxe/PchInitDxe.c
@@ -0,0 +1,354 @@
+/** @file
+ This is the Uefi driver that initializes the Intel PCH.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/PciSegmentLib.h>
+#include <Library/S3BootScriptLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+
+#include "PchInit.h"
+#include <PchPolicyCommon.h>
+#include <Protocol/PcieIoTrap.h>
+#include <Library/PchInfoLib.h>
+#include <Library/PmcLib.h>
+#include <Library/PchPcieRpLib.h>
+#include <Library/PmcPrivateLib.h>
+#include <Library/PciExpressHelpersLib.h>
+#include <PcieRegs.h>
+#include <Register/PchPcieRpRegs.h>
+#include <Register/PmcRegs.h>
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_HANDLE mImageHandle;
+GLOBAL_REMOVE_IF_UNREFERENCED UINT16 mPcieIoTrapAddress;
+
+VOID
+EFIAPI
+PchOnBootToOs (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+
+VOID
+EFIAPI
+PchOnExitBootServices (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+
+VOID
+EFIAPI
+PchOnReadyToBoot (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+/**
+ Process all the lock downs
+**/
+VOID
+ProcessSmiLocks (
+ VOID
+ )
+{
+ UINT32 Data32And;
+ UINT32 Data32Or;
+ UINT16 ABase;
+
+ ///
+ /// PCH BIOS Spec Section 3.6 Flash Security Recommendation
+ /// BIOS needs to enables SMI_LOCK (PMC PCI offset A0h[4] = 1b) which prevent writes
+ /// to the Global SMI Enable bit (GLB_SMI_EN ABASE + 30h[0]). Enabling this bit will
+ /// mitigate malicious software attempts to gain system management mode privileges.
+ ///
+ if (mPchConfigHob->LockDown.GlobalSmi == TRUE) {
+ ///
+ /// Save Global SMI Enable bit setting before BIOS enables SMI_LOCK during S3 resume
+ ///
+ ABase = PmcGetAcpiBase ();
+ Data32Or = IoRead32 ((UINTN) (ABase + R_ACPI_IO_SMI_EN));
+ if ((Data32Or & B_ACPI_IO_SMI_EN_GBL_SMI) != 0) {
+ Data32And = 0xFFFFFFFF;
+ Data32Or |= B_ACPI_IO_SMI_EN_GBL_SMI;
+ S3BootScriptSaveIoReadWrite (
+ S3BootScriptWidthUint32,
+ (UINTN) (ABase + R_ACPI_IO_SMI_EN),
+ &Data32Or, // Data to be ORed
+ &Data32And // Data to be ANDed
+ );
+ }
+ PmcLockSmiWithS3BootScript ();
+ }
+}
+
+/**
+ Do PCIE power management while resume from S3
+**/
+VOID
+ReconfigurePciePowerManagementForS3 (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Data32;
+ PCH_PCIE_IOTRAP_PROTOCOL *PchPcieIoTrapProtocol;
+
+ Status = gBS->LocateProtocol (&gPchPcieIoTrapProtocolGuid, NULL, (VOID **) &PchPcieIoTrapProtocol);
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+ mPcieIoTrapAddress = PchPcieIoTrapProtocol->PcieTrapAddress;
+ DEBUG ((DEBUG_INFO, "PcieIoTrapAddress: %0x\n", mPcieIoTrapAddress));
+
+ if (mPcieIoTrapAddress != 0) {
+ //
+ // Save PCH PCIE IoTrap address to re-config PCIE power management setting after resume from S3
+ //
+ Data32 = PchPciePmTrap;
+ S3BootScriptSaveIoWrite (
+ S3BootScriptWidthUint32,
+ (UINTN) (mPcieIoTrapAddress),
+ 1,
+ &Data32
+ );
+ } else {
+ ASSERT (FALSE);
+ }
+}
+
+/**
+ This is the callback function for PCI ENUMERATION COMPLETE.
+**/
+VOID
+EFIAPI
+PchOnPciEnumComplete (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ VOID *ProtocolPointer;
+
+ ///
+ /// Check if this is first time called by EfiCreateProtocolNotifyEvent() or not,
+ /// if it is, we will skip it until real event is triggered
+ ///
+ Status = gBS->LocateProtocol (&gEfiPciEnumerationCompleteProtocolGuid, NULL, (VOID **) &ProtocolPointer);
+ if (EFI_SUCCESS != Status) {
+ return;
+ }
+ gBS->CloseEvent (Event);
+
+ ReconfigurePciePowerManagementForS3 ();
+ ProcessSmiLocks ();
+ ConfigureSerialIoAtS3Resume ();
+}
+
+/**
+ Register callback functions for PCH DXE.
+**/
+VOID
+PchRegisterNotifications (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_EVENT ReadyToBoot;
+ EFI_EVENT LegacyBootEvent;
+ EFI_EVENT ExitBootServicesEvent;
+ VOID *Registration;
+
+ ///
+ /// Create PCI Enumeration Completed callback for PCH
+ ///
+ EfiCreateProtocolNotifyEvent (
+ &gEfiPciEnumerationCompleteProtocolGuid,
+ TPL_CALLBACK,
+ PchOnPciEnumComplete,
+ NULL,
+ &Registration
+ );
+
+ //
+ // Register a Ready to boot event to config PCIE power management setting after OPROM executed
+ //
+ Status = EfiCreateEventReadyToBootEx (
+ TPL_CALLBACK,
+ PchOnReadyToBoot,
+ NULL,
+ &ReadyToBoot
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Create events for PCH to do the task before ExitBootServices/LegacyBoot.
+ // It is guaranteed that only one of two events below will be signalled
+ //
+ Status = gBS->CreateEvent (
+ EVT_SIGNAL_EXIT_BOOT_SERVICES,
+ TPL_CALLBACK,
+ PchOnExitBootServices,
+ NULL,
+ &ExitBootServicesEvent
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = EfiCreateEventLegacyBootEx (
+ TPL_CALLBACK,
+ PchOnBootToOs,
+ NULL,
+ &LegacyBootEvent
+ );
+ ASSERT_EFI_ERROR (Status);
+}
+
+/**
+ <b>PchInit DXE Module Entry Point</b>\n
+ - <b>Introduction</b>\n
+ The PchInit module is a DXE driver that initializes the Intel Platform Controller Hub
+ following the PCH BIOS specification and EDS requirements and recommendations. It consumes
+ the PCH_POLICY_HOB SI_POLICY_HOB for expected configurations per policy.
+ This is the standard EFI driver point that detects whether there is an supported PCH in
+ the system and if so, initializes the chipset.
+
+ - <b>Details</b>\n
+ This module is required for initializing the Intel Platform Controller Hub to
+ follow the PCH BIOS specification and EDS.
+ This includes some initialization sequences, enabling and disabling PCH devices,
+ configuring clock gating, RST PCIe Storage Remapping, SATA controller, ASPM of PCIE devices. Right before end of DXE,
+ it's responsible to lock down registers for security requirement.
+
+ - @pre
+ - PCH PCR base address configured
+ - EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
+ - This is to ensure that PCI MMIO and IO resource has been prepared and available for this driver to allocate.
+
+ - @result
+ - Publishes the @link _PCH_INFO_PROTOCOL PCH_INFO_PROTOCOL @endlink
+ - Publishes the @link _PCH_EMMC_TUNING_PROTOCOL PCH_EMMC_TUNING_PROTOCOL @endlink
+
+ - <b>References</b>\n
+ - @link _PCH_POLICY PCH_POLICY_HOB @endlink.
+ - @link _SI_POLICY_STRUCT SI_POLICY_HOB @endlink.
+
+ - <b>Integration Checklists</b>\n
+ - Verify prerequisites are met. Porting Recommendations.
+ - No modification of this module should be necessary
+ - Any modification of this module should follow the PCH BIOS Specification and EDS
+
+ @param[in] ImageHandle Handle for the image of this driver
+ @param[in] SystemTable Pointer to the EFI System Table
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_OUT_OF_RESOURCES Do not have enough resources to initialize the driver
+**/
+EFI_STATUS
+EFIAPI
+PchInitEntryPointDxe (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ DEBUG ((DEBUG_INFO, "PchInitEntryPointDxe() Start\n"));
+
+ mImageHandle = ImageHandle;
+
+ PchInitEntryPointCommon ();
+
+ Status = PchAcpiInit (ImageHandle);
+
+ PchRegisterNotifications ();
+
+ CreateSerialIoUartHiddenHandle ();
+
+ DEBUG ((DEBUG_INFO, "PchInitEntryPointDxe() End\n"));
+
+ return Status;
+}
+
+/**
+ PCH initialization before ExitBootServices / LegacyBoot events
+ Useful for operations which must happen later than at EndOfPost event
+
+ @param[in] Event A pointer to the Event that triggered the callback.
+ @param[in] Context A pointer to private data registered with the callback function.
+**/
+VOID
+EFIAPI
+PchOnBootToOs (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ ///
+ /// Closed the event to avoid call twice
+ ///
+ if (Event != NULL) {
+ gBS->CloseEvent (Event);
+ }
+
+ ConfigureSerialIoAtBoot ();
+
+ return;
+}
+
+/**
+ PCH initialization on ExitBootService. This event is used if only ExitBootService is used
+ and not in legacy boot
+
+ @param[in] Event A pointer to the Event that triggered the callback.
+ @param[in] Context A pointer to private data registered with the callback function.
+
+ @retval None
+**/
+VOID
+EFIAPI
+PchOnExitBootServices (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ PchOnBootToOs (NULL, NULL);
+
+ return;
+}
+
+/**
+ PCH initialization before boot to OS
+
+ @param[in] Event A pointer to the Event that triggered the callback.
+ @param[in] Context A pointer to private data registered with the callback function.
+**/
+VOID
+EFIAPI
+PchOnReadyToBoot (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ DEBUG ((DEBUG_INFO, "Uefi PchOnReadyToBoot() Start\n"));
+
+ if (Event != NULL) {
+ gBS->CloseEvent (Event);
+ }
+
+ //
+ // Trigger an Iotrap SMI to config PCIE power management setting after PCI enumrate is done
+ //
+ if (mPcieIoTrapAddress != 0) {
+ IoWrite32 ((UINTN) mPcieIoTrapAddress, PchPciePmTrap);
+ } else {
+ ASSERT (FALSE);
+ }
+
+ DEBUG ((DEBUG_INFO, "Uefi PchOnReadyToBoot() End\n"));
+}
+
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Dxe/PchInitDxeTgl.inf b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Dxe/PchInitDxeTgl.inf
new file mode 100644
index 0000000000..4941ff0f49
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Dxe/PchInitDxeTgl.inf
@@ -0,0 +1,96 @@
+## @file
+# Component description file for Pch Initialization driver
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PchInitDxeTgl
+FILE_GUID = 4BD0EB2F-3A2D-442E-822D-753516F75424
+VERSION_STRING = 1.0
+MODULE_TYPE = DXE_DRIVER
+ENTRY_POINT = PchInitEntryPointDxe
+
+
+[LibraryClasses]
+S3BootScriptLib
+PchCycleDecodingLib
+PchPcieRpLib
+PchPcrLib
+PchInfoLib
+PciExpressHelpersLib
+UefiBootServicesTableLib
+DebugLib
+IoLib
+TimerLib
+HobLib
+BaseMemoryLib
+MemoryAllocationLib
+UefiLib
+DxeServicesTableLib
+UefiDriverEntryPoint
+UefiRuntimeServicesTableLib
+GpioLib
+SerialIoAccessLib
+ConfigBlockLib
+PmcLib
+PmcPrivateLibWithS3
+SataLib
+PchDmiWithS3Lib
+GbeLib
+SiScheduleResetLib
+DxeHdaNhltLib
+SpiAccessPrivateLib
+PchPciBdfLib
+
+[Packages]
+MdePkg/MdePkg.dec
+TigerlakeSiliconPkg/SiPkg.dec
+
+
+[Pcd]
+gSiPkgTokenSpaceGuid.PcdSiPciExpressBaseAddress
+gSiPkgTokenSpaceGuid.PcdSiliconInitTempMemBaseAddr ## CONSUMES
+gSiPkgTokenSpaceGuid.PcdEmbeddedEnable ## CONSUMES
+
+[Sources]
+PchInitDxe.c
+PchInit.h
+PchInit.c
+PchSata.c
+PchSerialIo.c
+PchSerialIoDxe.c
+PchHdaAcpi.c
+PchCnviAcpi.c
+PchAcpi.c
+
+
+[Protocols]
+gPchNvsAreaProtocolGuid ## PRODUCES
+gEfiPciIoProtocolGuid ## CONSUMES
+gEfiAcpiTableProtocolGuid ## CONSUMES
+gEfiBlockIoProtocolGuid ## CONSUMES
+gHeciProtocolGuid
+gEfiPciEnumerationCompleteProtocolGuid ## CONSUMES
+gPchPcieIoTrapProtocolGuid ## CONSUMES
+gPchPolicyProtocolGuid ## CONSUMES
+
+
+[Guids]
+gEfiEndOfDxeEventGroupGuid
+gEfiAcpiTableGuid
+gEmmcDxeConfigGuid ## CONSUMES
+gSiConfigHobGuid ## CONSUMES
+gPchConfigHobGuid ## CONSUMES
+gPchRstHobGuid ## CONSUMES
+gHdAudioDxeConfigGuid ## CONSUMES
+gGpioDxeConfigGuid ## CONSUMES
+gCnviConfigHobGuid ## CONSUMES
+gHybridStorageHobGuid ## CONSUMES
+
+[Depex]
+gEfiPciHostBridgeResourceAllocationProtocolGuid ## This is to ensure that PCI MMIO and IO resource has been prepared and available for this driver to allocate.
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Dxe/PchSata.c b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Dxe/PchSata.c
new file mode 100644
index 0000000000..886f3b4bc0
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Dxe/PchSata.c
@@ -0,0 +1,89 @@
+/** @file
+ Perform related functions for PCH Sata in DXE phase
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/DebugLib.h>
+#include <Library/PciSegmentLib.h>
+#include <Library/S3BootScriptLib.h>
+
+#include "PchInit.h"
+#include <Library/SataLib.h>
+#include <Library/PchPciBdfLib.h>
+#include <Register/SataRegs.h>
+
+/**
+ Perform the remaining configuration on SATA to perform device detection,
+ then set the SATA SPD and PxE corresponding, and set the Register Lock on PCH SATA
+
+ @retval None
+**/
+VOID
+ConfigureSataOnEndOfDxe (
+ VOID
+ )
+{
+ UINT64 PciSataRegBase;
+ UINT16 SataPortsEnabled;
+ UINT32 DwordReg;
+ UINTN Index;
+ UINT32 SataCtrlIndex;
+
+ for (SataCtrlIndex = 0; SataCtrlIndex < MaxSataControllerNum (); SataCtrlIndex++) {
+ ///
+ /// SATA PCS: Enable the port in any of below condition:
+ /// i.) Hot plug is enabled
+ /// ii.) A device is attached
+ /// iii.) Test mode is enabled
+ /// iv.) Configured as eSATA port
+ ///
+ PciSataRegBase = SataPciCfgBase (SataCtrlIndex);
+ SataPortsEnabled = 0;
+
+ DwordReg = PciSegmentRead32 (PciSataRegBase + R_SATA_CFG_PCS);
+ for (Index = 0; Index < MaxSataPortNum (SataCtrlIndex); Index++) {
+ if ((mPchConfigHob->Sata[SataCtrlIndex].PortSettings[Index].HotPlug == TRUE) ||
+ (DwordReg & (B_SATA_CFG_PCS_P0P << Index)) ||
+ (mPchConfigHob->Sata[SataCtrlIndex].TestMode == TRUE) ||
+ (mPchConfigHob->Sata[SataCtrlIndex].PortSettings[Index].External == TRUE)) {
+ SataPortsEnabled |= (mPchConfigHob->Sata[SataCtrlIndex].PortSettings[Index].Enable << Index);
+ }
+ }
+
+ ///
+ /// Set MAP."Sata PortX Disable", SATA PCI offset 90h[23:16] to 1b if SATA Port 0/1/2/3/4/5/6/7 is disabled
+ ///
+ PciSegmentOr32 (PciSataRegBase + R_SATA_CFG_MAP, (~SataPortsEnabled << N_SATA_CFG_MAP_SPD));
+ S3BootScriptSaveMemWrite (
+ S3BootScriptWidthUint32,
+ PcdGet64 (PcdSiPciExpressBaseAddress) + PciSataRegBase + R_SATA_CFG_MAP,
+ 1,
+ (VOID *) (UINTN) (PcdGet64 (PcdSiPciExpressBaseAddress) + PciSataRegBase + R_SATA_CFG_MAP)
+ );
+
+ ///
+ /// Program PCS "Port X Enabled", SATA PCI offset 94h[7:0] = Port 0~7 Enabled bit as per SataPortsEnabled value.
+ ///
+ PciSegmentOr16 (PciSataRegBase + R_SATA_CFG_PCS, SataPortsEnabled);
+ S3BootScriptSaveMemWrite (
+ S3BootScriptWidthUint16,
+ PcdGet64 (PcdSiPciExpressBaseAddress) + PciSataRegBase + R_SATA_CFG_PCS,
+ 1,
+ (VOID *) (UINTN) (PcdGet64 (PcdSiPciExpressBaseAddress) + PciSataRegBase + R_SATA_CFG_PCS)
+ );
+
+ ///
+ /// Step 14
+ /// Program SATA PCI offset 9Ch [31] to 1b
+ ///
+ PciSegmentOr32 ((UINTN) (PciSataRegBase + R_SATA_CFG_SATAGC), BIT31);
+ S3BootScriptSaveMemWrite (
+ S3BootScriptWidthUint32,
+ PcdGet64 (PcdSiPciExpressBaseAddress) + PciSataRegBase + R_SATA_CFG_SATAGC,
+ 1,
+ (VOID *) (UINTN) (PcdGet64 (PcdSiPciExpressBaseAddress) + PciSataRegBase + R_SATA_CFG_SATAGC)
+ );
+ }
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Dxe/PchSerialIo.c b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Dxe/PchSerialIo.c
new file mode 100644
index 0000000000..9409a9a387
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Dxe/PchSerialIo.c
@@ -0,0 +1,33 @@
+/** @file
+ Initializes Serial IO Controllers.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include "PchInit.h"
+#include <Library/SerialIoPrivateLib.h>
+#include <Library/PchInfoLib.h>
+
+/**
+ Calls Boot Os Hand off routine for each Serial IO Controller
+**/
+VOID
+ConfigureSerialIoAtBoot (
+ VOID
+ )
+{
+ UINT8 Index;
+
+ for (Index = 0; Index < GetPchMaxSerialIoSpiControllersNum (); Index++) {
+ SerialIoSpiBootHandler (Index, &mPchConfigHob->SerialIo.SpiDeviceConfig[Index]);
+ }
+
+ for (Index = 0; Index < GetPchMaxSerialIoI2cControllersNum (); Index++) {
+ SerialIoI2cBootHandler (Index, &mPchConfigHob->SerialIo.I2cDeviceConfig[Index]);
+ }
+
+ for (Index = 0; Index < GetPchMaxSerialIoUartControllersNum (); Index++) {
+ SerialIoUartBootHandler (Index, &mPchConfigHob->SerialIo.UartDeviceConfig[Index]);
+ }
+}
+
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Dxe/PchSerialIoDxe.c b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Dxe/PchSerialIoDxe.c
new file mode 100644
index 0000000000..fde7da6b96
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Dxe/PchSerialIoDxe.c
@@ -0,0 +1,134 @@
+/** @file
+ Initializes Serial IO Controllers.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/S3BootScriptLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/SerialIoPrivateLib.h>
+#include <Library/PchInfoLib.h>
+#include <IndustryStandard/Pci30.h>
+#include <Register/SerialIoRegs.h>
+#include <PchInit.h>
+
+typedef struct {
+ ACPI_HID_DEVICE_PATH RootPort;
+ ACPI_EXTENDED_HID_DEVICE_PATH AcpiDev;
+ CHAR8 HidString[8];
+ UINT16 DeviceId;
+ UINT8 UartIndex;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} SERIALIO_UART_DEVICE_PATH;
+
+#define mPciRootBridge {{ACPI_DEVICE_PATH, ACPI_DP, {(UINT8)(sizeof (ACPI_HID_DEVICE_PATH)), 0}}, EISA_PNP_ID (0x0A03), 0}
+#define mAcpiDev {{ACPI_DEVICE_PATH, ACPI_EXTENDED_DP, {(UINT8)(sizeof (ACPI_EXTENDED_HID_DEVICE_PATH) + (sizeof(CHAR8) * 8) + sizeof (UINT16) + sizeof (UINT8)), 0}},0,0,0}
+#define mEndEntire {END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, {END_DEVICE_PATH_LENGTH, 0}}
+
+GLOBAL_REMOVE_IF_UNREFERENCED SERIALIO_UART_DEVICE_PATH mSerialIoUartPath = {
+ mPciRootBridge,
+ mAcpiDev,
+ "UART\0\0\0",
+ 0xFFFF,
+ 0xFF,
+ mEndEntire
+};
+
+/**
+ Add Serial Io UART Hidden Handles
+**/
+VOID
+CreateSerialIoUartHiddenHandle (
+ VOID
+ )
+{
+ EFI_HANDLE NewHandle;
+ EFI_DEVICE_PATH_PROTOCOL *NewPath;
+ EFI_STATUS Status;
+ UINT8 Index;
+ UINT16 DeviceId;
+
+ DEBUG ((DEBUG_INFO, "CreateSerialIoUartHandle\n"));
+
+ for (Index = 0; Index < GetPchMaxSerialIoUartControllersNum (); Index++) {
+ DEBUG ((DEBUG_INFO, "UART Index: %d Mode: %d\n", Index, mPchConfigHob->SerialIo.UartDeviceConfig[Index].Mode));
+ if (mPchConfigHob->SerialIo.UartDeviceConfig[Index].Mode == SerialIoUartHidden) {
+ NewHandle = NULL;
+ DeviceId = MmioRead16 (GetSerialIoUartFixedPciCfgAddress (Index) + PCI_DEVICE_ID_OFFSET);
+ DEBUG ((DEBUG_INFO, "Creating Handle for UART DEVICE_ID: 0x%X \n", DeviceId));
+ mSerialIoUartPath.AcpiDev.HID = 0x5432 + (Index << 16); //UAR
+ mSerialIoUartPath.HidString[4] = (CHAR8)('0' + Index);
+ mSerialIoUartPath.DeviceId = DeviceId;
+ mSerialIoUartPath.UartIndex = Index;
+ NewPath = DuplicateDevicePath ((EFI_DEVICE_PATH_PROTOCOL*) &mSerialIoUartPath);
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &NewHandle,
+ &gEfiDevicePathProtocolGuid,
+ NewPath,
+ NULL
+ );
+ DEBUG ((DEBUG_INFO, "CreateSerialIoUartHandle Status: %r\n", Status));
+ }
+ }
+}
+
+/**
+ Stores Pme Control Status and Command register values in S3 Boot Script
+
+ @param[in] S3PciCfgBase S3 Boot Script Pci Config Base
+ @param[in] Command Pci Command register data to save
+ @param[in] Pme Pci Pme Control register data to save
+
+**/
+VOID
+STATIC
+SerialIoS3Save (
+ IN UINTN S3PciCfgBase,
+ IN UINTN Command,
+ IN UINTN Pme
+ )
+{
+ if (S3PciCfgBase != 0) {
+ S3BootScriptSavePciCfgWrite (S3BootScriptWidthUint32, S3PciCfgBase + R_SERIAL_IO_CFG_PME_CTRL_STS, 1, &Pme);
+ S3BootScriptSavePciCfgWrite (S3BootScriptWidthUint32, S3PciCfgBase + PCI_COMMAND_OFFSET, 1, &Command);
+ }
+}
+
+/**
+ Puts all SerialIo controllers (except UARTs in debug mode) in D3.
+ Clears MemoryEnable for all PCI-mode controllers on S3 resume
+**/
+VOID
+ConfigureSerialIoAtS3Resume (
+ VOID
+ )
+{
+ UINT8 Index;
+ UINTN S3PciCfgBase;
+ UINT32 Command;
+ UINT32 Pme;
+
+ S3PciCfgBase = 0;
+ for (Index = 0; Index < GetPchMaxSerialIoSpiControllersNum (); Index++) {
+ SerialIoSpiS3Handler (Index, &mPchConfigHob->SerialIo.SpiDeviceConfig[Index], &S3PciCfgBase, &Command, &Pme);
+ SerialIoS3Save (S3PciCfgBase, Command, Pme);
+ }
+
+ S3PciCfgBase = 0;
+ for (Index = 0; Index < GetPchMaxSerialIoI2cControllersNum (); Index++) {
+ SerialIoI2cS3Handler (Index, &mPchConfigHob->SerialIo.I2cDeviceConfig[Index], &S3PciCfgBase, &Command, &Pme);
+ SerialIoS3Save (S3PciCfgBase, Command, Pme);
+ }
+
+ S3PciCfgBase = 0;
+ for (Index = 0; Index < GetPchMaxSerialIoUartControllersNum (); Index++) {
+ SerialIoUartS3Handler (Index, &mPchConfigHob->SerialIo.UartDeviceConfig[Index], &S3PciCfgBase, &Command, &Pme);
+ SerialIoS3Save (S3PciCfgBase, Command, Pme);
+ }
+}
+
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Smm/GbeSxSmm.c b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Smm/GbeSxSmm.c
new file mode 100644
index 0000000000..786ce13915
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Smm/GbeSxSmm.c
@@ -0,0 +1,266 @@
+/** @file
+ Gbe Sx handler implementation.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/TimerLib.h>
+#include "PchInitSmm.h"
+#include <Library/PmcPrivateLib.h>
+#include <Library/GbeMdiLib.h>
+#include <Library/GbeLib.h>
+#include <Register/PchRegs.h>
+#include <Register/GbeRegs.h>
+#include <Library/PchPciBdfLib.h>
+
+
+/**
+ Configure WOL during Sx entry.
+
+ @param [in] GbeBar GbE MMIO space
+**/
+VOID
+GbeWolWorkaround (
+ IN UINT32 GbeBar
+ )
+{
+ UINT32 RAL0;
+ UINT32 RAH0;
+ UINT16 WUC;
+ EFI_STATUS Status;
+ UINT16 Data16;
+
+ //
+ // 1. Set page to 769 Port Control Registers
+ // 2. Wait 4 mSec
+ //
+ Status = GbeMdiSetPage (GbeBar, PHY_MDI_PAGE_769_PORT_CONTROL_REGISTERS);
+ if (EFI_ERROR (Status)) return;
+
+ //
+ // 3. Set registry to 17 Port General Configuration
+ // 4. Copy all settings from Port General Configuration
+ //
+ Status = GbeMdiRead (GbeBar, B_PHY_MDI_PHY_ADDRESS_01, MDI_REG_SHIFT (R_PHY_MDI_PAGE_769_REGISETER_17_PGC), &Data16);
+ if (EFI_ERROR (Status)) return;
+
+ //
+ // 5. Modify BIT 4 and BIT 2 to disable host wake up and set MACPD
+ //
+ Status = GbeMdiWrite (GbeBar, B_PHY_MDI_PHY_ADDRESS_01, MDI_REG_SHIFT (R_PHY_MDI_PAGE_769_REGISETER_17_PGC), (Data16 | B_PHY_MDI_PAGE_769_REGISETER_17_PGC_MACPD_ENABLE) & (~B_PHY_MDI_PAGE_769_REGISETER_17_PGC_HOST_WAKE_UP));
+ if (EFI_ERROR (Status)) return;
+
+ //
+ // 6. Read Receive Address Low and Receive Address High from MMIO
+ //
+ RAL0 = MmioRead32 (GbeBar + R_GBE_MEM_CSR_RAL);
+ RAH0 = MmioRead32 (GbeBar + R_GBE_MEM_CSR_RAH);
+
+ //
+ // 7. Set page to 800 Wake Up Registers
+ // 8. Wait 4 mSec
+ //
+ Status = GbeMdiSetPage (GbeBar, PHY_MDI_PAGE_800_WAKE_UP_REGISTERS);
+ if (EFI_ERROR (Status)) return;
+
+ //
+ // 9. Set registry to 16 Receive Address Low 1/2
+ //
+ Status = GbeMdiSetRegister (GbeBar, R_PHY_MDI_PAGE_800_REGISETER_16_RAL0);
+ if (EFI_ERROR (Status)) return;
+
+ //
+ // 10. Program first 16 bits [0:15] out of 48 in Receive Address Low 1/2
+ //
+ Status = GbeMdiWrite (GbeBar, B_PHY_MDI_PHY_ADDRESS_01, R_PHY_MDI_PHY_REG_DATA_READ_WRITE, (RAL0 & 0xFFFF));
+ if (EFI_ERROR (Status)) return;
+
+ //
+ // 11. Set registry to 17 Receive Address Low 2/2
+ //
+ Status = GbeMdiSetRegister (GbeBar, R_PHY_MDI_PAGE_800_REGISETER_17_RAL1);
+ if (EFI_ERROR (Status)) return;
+
+ //
+ // 12. Program second 16 bits [16:31] out of 48 in Receive Address Low 2/2
+ //
+ Status = GbeMdiWrite (GbeBar, B_PHY_MDI_PHY_ADDRESS_01, R_PHY_MDI_PHY_REG_DATA_READ_WRITE, (RAL0 >> 16));
+ if (EFI_ERROR (Status)) return;
+
+ //
+ // 13. Set registry to 18 Receive Address High 1/2
+ //
+ Status = GbeMdiSetRegister (GbeBar, R_PHY_MDI_PAGE_800_REGISETER_18_RAH0);
+ if (EFI_ERROR (Status)) return;
+
+ //
+ // 14. Program last 16 bits [32:47] out of 48
+ //
+ Status = GbeMdiWrite (GbeBar, B_PHY_MDI_PHY_ADDRESS_01, R_PHY_MDI_PHY_REG_DATA_READ_WRITE, (RAH0 & B_GBE_MEM_CSR_RAH_RAH));
+ if (EFI_ERROR (Status)) return;
+
+ //
+ // 15. Set registry to 19 Receive Address High 2/2
+ //
+ Status = GbeMdiSetRegister (GbeBar, R_PHY_MDI_PAGE_800_REGISETER_19_RAH1);
+ if (EFI_ERROR (Status)) return;
+
+ //
+ // 16. Set Address Valid
+ //
+ Status = GbeMdiWrite (GbeBar, B_PHY_MDI_PHY_ADDRESS_01, R_PHY_MDI_PHY_REG_DATA_READ_WRITE, B_PHY_MDI_PAGE_800_REGISETER_19_RAH1_ADDRESS_VALID);
+ if (EFI_ERROR (Status)) return;
+
+ //
+ // 17. Set Wake Up Control Register 1
+ //
+ Status = GbeMdiSetRegister (GbeBar, R_PHY_MDI_PAGE_800_REGISETER_1_WUC);
+ if (EFI_ERROR (Status)) return;
+
+ //
+ // 18. Copy WakeUp Control from MAC MMIO
+ //
+ WUC = (UINT16) MmioRead32 (GbeBar + R_GBE_MEM_CSR_WUC);
+
+ //
+ // 19. Store WakeUp Contorl into LCD
+ // Modify APME bit to enable APM wake up
+ //
+ Status = GbeMdiWrite (GbeBar, B_PHY_MDI_PHY_ADDRESS_01, R_PHY_MDI_PHY_REG_DATA_READ_WRITE, (WUC & 0xFFFF));
+ if (EFI_ERROR (Status)) return;
+
+ //
+ // 20. Set page to 803 Host Wol Packet
+ // 21. Wait 4 mSec
+ //
+ Status = GbeMdiSetPage (GbeBar, PHY_MDI_PAGE_803_HOST_WOL_PACKET);
+ if (EFI_ERROR (Status)) return;
+
+ //
+ // 22. Set registry to 66 Host WoL Packet Clear
+ //
+ Status = GbeMdiSetRegister (GbeBar, R_PHY_MDI_PAGE_803_REGISETER_66_HWPC);
+ if (EFI_ERROR (Status)) return;
+
+ //
+ // 23. Clear WOL Packet
+ //
+ Status = GbeMdiWrite (GbeBar, B_PHY_MDI_PHY_ADDRESS_01, R_PHY_MDI_PHY_REG_DATA_READ_WRITE, 0);
+ if (EFI_ERROR (Status)) return;
+ //
+ // 24. Set page to 769 Port Control Registers
+ // 25. Wait 4 mSec
+ //
+ Status = GbeMdiSetPage (GbeBar, PHY_MDI_PAGE_769_PORT_CONTROL_REGISTERS);
+ if (EFI_ERROR (Status)) return;
+
+ //
+ // 26. Set registry to 17 Port General Configuration
+ //
+ Status = GbeMdiSetRegister (GbeBar, R_PHY_MDI_PAGE_769_REGISETER_17_PGC);
+ if (EFI_ERROR (Status)) return;
+
+ //
+ // 27. Copy all settings from Port General Configuration
+ //
+ Status = GbeMdiRead (GbeBar, B_PHY_MDI_PHY_ADDRESS_01, MDI_REG_SHIFT (R_PHY_MDI_PAGE_769_REGISETER_17_PGC), &Data16);
+ if (EFI_ERROR (Status)) return;
+
+ //
+ // 28. Modify BIT 4 and BIT 2 to enable host wake up and clear MACPD
+ //
+ Status = GbeMdiWrite (GbeBar, B_PHY_MDI_PHY_ADDRESS_01, MDI_REG_SHIFT (R_PHY_MDI_PAGE_769_REGISETER_17_PGC), (Data16 | B_PHY_MDI_PAGE_769_REGISETER_17_PGC_HOST_WAKE_UP) & (~B_PHY_MDI_PAGE_769_REGISETER_17_PGC_MACPD_ENABLE));
+ if (EFI_ERROR (Status)) return;
+}
+
+/**
+ Additional Internal GbE Controller special cases WOL Support.
+
+ System BIOS is required perform additional steps upon S0 to S3,4,5 transition
+ when ME is off and GbE device in D0. This is needed to enable LAN wake
+ in particular when platform is shut-down from EFI.
+**/
+VOID
+GbeSxWorkaround (
+ VOID
+ )
+{
+ UINT64 LanRegBase;
+ UINT32 GbeBar;
+ EFI_STATUS Status;
+
+ LanRegBase = GbePciCfgBase ();
+
+ if (PciSegmentRead16 (LanRegBase + PCI_VENDOR_ID_OFFSET) == 0xFFFF) {
+ return;
+ }
+
+ //
+ // Check if GbE device is in D0
+ //
+ if ((PciSegmentRead16 (LanRegBase + R_GBE_CFG_PMCS) & B_GBE_CFG_PMCS_PS) != V_GBE_CFG_PMCS_PS0) {
+ return;
+ }
+
+ ASSERT (mResvMmioSize >= (1 << N_GBE_CFG_MBARA_ALIGN));
+ GbeBar = (UINT32) mResvMmioBaseAddr;
+ if (GbeBar == 0) {
+ ASSERT (FALSE);
+ return;
+ }
+
+ //
+ // Enable MMIO decode using reserved range.
+ //
+ PciSegmentAnd16 (LanRegBase + PCI_COMMAND_OFFSET, (UINT16) ~EFI_PCI_COMMAND_MEMORY_SPACE);
+ PciSegmentWrite32 (LanRegBase + R_GBE_CFG_MBARA, GbeBar);
+ PciSegmentOr16 (LanRegBase + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_MEMORY_SPACE);
+
+ //
+ // If MBARA offset 5800h [0] = 1b then proceed with the w/a
+ //
+ if (MmioRead32 (GbeBar + R_GBE_MEM_CSR_WUC) & B_GBE_MEM_CSR_WUC_APME) {
+ Status = GbeMdiAcquireMdio (GbeBar);
+ ASSERT_EFI_ERROR (Status);
+ if (!EFI_ERROR (Status)) {
+ GbeWolWorkaround (GbeBar);
+ GbeMdiReleaseMdio (GbeBar);
+ }
+ }
+
+ //
+ // Disable MMIO decode.
+ //
+ PciSegmentAnd16 (LanRegBase + PCI_COMMAND_OFFSET, (UINT16) ~EFI_PCI_COMMAND_MEMORY_SPACE);
+ PciSegmentWrite32 (LanRegBase + R_GBE_CFG_MBARA, 0);
+}
+
+/**
+ Enable platform wake from LAN when in DeepSx if platform supports it.
+ Called upon Sx entry.
+**/
+VOID
+GbeConfigureDeepSxWake (
+ VOID
+ )
+{
+ if (PmcIsLanDeepSxWakeEnabled ()) {
+ IoOr32 ((UINTN) (mAcpiBaseAddr + R_ACPI_IO_GPE0_EN_127_96), (UINT32) B_ACPI_IO_GPE0_EN_127_96_LAN_WAKE);
+ }
+}
+
+/**
+ GbE Sx entry handler
+**/
+VOID
+PchLanSxCallback (
+ VOID
+ )
+{
+ if (IsGbeEnabled ()) {
+ GbeSxWorkaround ();
+ GbeConfigureDeepSxWake ();
+
+ }
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Smm/PchBiosWriteProtect.c b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Smm/PchBiosWriteProtect.c
new file mode 100644
index 0000000000..f435af434a
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Smm/PchBiosWriteProtect.c
@@ -0,0 +1,137 @@
+/** @file
+ PCH BIOS Write Protect Driver.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include "PchInitSmm.h"
+#include <Register/PchRegs.h>
+#include <Register/PchRegsLpc.h>
+#include <Register/SpiRegs.h>
+#include <Library/SpiAccessPrivateLib.h>
+#include <Library/PchPciBdfLib.h>
+
+//
+// Global variables
+//
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_TCO_SMI_DISPATCH_PROTOCOL *mPchTcoSmiDispatchProtocol;
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_ESPI_SMI_DISPATCH_PROTOCOL *mEspiSmmDispatchProtocol;
+GLOBAL_REMOVE_IF_UNREFERENCED UINT64 mLpcRegBase;
+
+/**
+ This hardware SMI handler will be run every time the BIOS Write Enable bit is set.
+
+ @param[in] DispatchHandle Not used
+**/
+VOID
+EFIAPI
+PchSpiBiosWpCallback (
+ IN EFI_HANDLE DispatchHandle
+ )
+{
+ SpiClearBiosWriteProtectDisable ();
+}
+
+/**
+ This hardware SMI handler will be run every time the BIOS Write Enable bit is set.
+
+ @param[in] DispatchHandle Not used
+
+**/
+VOID
+EFIAPI
+PchLpcBiosWpCallback (
+ IN EFI_HANDLE DispatchHandle
+ )
+{
+ //
+ // Disable BIOSWE bit to protect BIOS
+ //
+ PciSegmentAnd8 ((UINTN) (mLpcRegBase + R_LPC_CFG_BC), (UINT8) ~B_LPC_CFG_BC_WPD);
+}
+
+/**
+ Entry point for Pch Bios Write Protect driver.
+
+ @param[in] ImageHandle Image handle of this driver.
+ @param[in] SystemTable Global system service table.
+
+ @retval EFI_SUCCESS Initialization complete.
+**/
+EFI_STATUS
+EFIAPI
+InstallPchBiosWriteProtect (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE Handle;
+
+ DEBUG ((DEBUG_INFO, "InstallPchBiosWriteProtect()\n"));
+
+ if (mPchConfigHob->LockDown.BiosLock != TRUE) {
+ return EFI_SUCCESS;
+ }
+
+ mLpcRegBase = LpcPciCfgBase ();
+
+ DEBUG ((DEBUG_INFO, "Installing BIOS Write Protect SMI handler\n"));
+ //
+ // Get the PCH TCO SMM dispatch protocol
+ //
+ mPchTcoSmiDispatchProtocol = NULL;
+ Status = gSmst->SmmLocateProtocol (&gPchTcoSmiDispatchProtocolGuid, NULL, (VOID **) &mPchTcoSmiDispatchProtocol);
+ ASSERT_EFI_ERROR (Status);
+ //
+ // Always register an SPI BiosWp callback function to handle TCO BIOSWR SMI
+ // NOTE: No matter the BIOS resides behind SPI or not, it needs to handle the SPI BIOS WP SMI
+ // to avoid SMI deadloop on SPI WPD write.
+ //
+ Handle = NULL;
+ Status = mPchTcoSmiDispatchProtocol->SpiBiosWpRegister (
+ mPchTcoSmiDispatchProtocol,
+ PchSpiBiosWpCallback,
+ &Handle
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Always register an LPC/eSPI BiosWp callback function to handle TCO BIOSWR SMI
+ // NOTE: No matter the BIOS resides behind LPC/eSPI or not, it needs to handle the BIOS WP SMI
+ // to avoid SMI deadloop on LPC/eSPI WPD write.
+ //
+ if (IsEspiEnabled ()) {
+ //
+ // Get the PCH ESPI SMM dispatch protocol
+ //
+ mEspiSmmDispatchProtocol = NULL;
+ Status = gSmst->SmmLocateProtocol (&gPchEspiSmiDispatchProtocolGuid, NULL, (VOID **) &mEspiSmmDispatchProtocol);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Register an ESpiBiosWp callback function to handle BIOSWR SMI
+ //
+ Handle = NULL;
+ Status = mEspiSmmDispatchProtocol->BiosWrProtectRegister (
+ mEspiSmmDispatchProtocol,
+ PchLpcBiosWpCallback,
+ &Handle
+ );
+ ASSERT_EFI_ERROR (Status);
+ } else {
+ //
+ // Register an LPC BiosWp callback function to handle TCO BIOSWR SMI
+ //
+ Handle = NULL;
+ Status = mPchTcoSmiDispatchProtocol->LpcBiosWpRegister (
+ mPchTcoSmiDispatchProtocol,
+ PchLpcBiosWpCallback,
+ &Handle
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ return EFI_SUCCESS;
+}
+
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Smm/PchHdaSxSmm.c b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Smm/PchHdaSxSmm.c
new file mode 100644
index 0000000000..f3d11ab204
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Smm/PchHdaSxSmm.c
@@ -0,0 +1,33 @@
+/** @file
+ PCH HD Audio Sx handler implementation.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "PchInitSmm.h"
+#include <Register/PchRegs.h>
+#include <Register/HdaRegs.h>
+#include <Library/PchPciBdfLib.h>
+
+GLOBAL_REMOVE_IF_UNREFERENCED UINT64 mHdaPciBase;
+GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN mHdaCodecSxWakeCapability = FALSE;
+
+/**
+ Updates Codec Sx Wake Capability setting: disabled/enabled
+**/
+VOID
+UpdateHdaCodecSxWakeCapabilitySetting (
+ VOID
+ )
+{
+ mHdaPciBase = HdaPciCfgBase ();
+
+ if ((mPchConfigHob->HdAudio.CodecSxWakeCapability == FALSE) ||
+ (PciSegmentRead16 (mHdaPciBase + PCI_VENDOR_ID_OFFSET) == 0xFFFF)) {
+ mHdaCodecSxWakeCapability = FALSE;
+ } else {
+ mHdaCodecSxWakeCapability = TRUE;
+ }
+}
+
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Smm/PchInitSmm.c b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Smm/PchInitSmm.c
new file mode 100644
index 0000000000..9c2475e3a1
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Smm/PchInitSmm.c
@@ -0,0 +1,285 @@
+/** @file
+ PCH Init Smm module for PCH specific SMI handlers.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include "PchInitSmm.h"
+#include <Register/PchRegs.h>
+#include <Register/UsbRegs.h>
+#include <Register/SmbusRegs.h>
+#include <Library/PchPciBdfLib.h>
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_SMM_IO_TRAP_DISPATCH2_PROTOCOL *mPchIoTrap;
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_SMM_SX_DISPATCH2_PROTOCOL *mSxDispatch;
+
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_NVS_AREA *mPchNvsArea;
+GLOBAL_REMOVE_IF_UNREFERENCED UINT16 mAcpiBaseAddr;
+
+GLOBAL_REMOVE_IF_UNREFERENCED FIVR_EXT_RAIL_CONFIG mFivrExtVnnRailSxConfig;
+
+//
+// NOTE: The module variables of policy here are only valid in post time, but not runtime time.
+//
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_CONFIG_HOB *mPchConfigHob;
+
+//
+// The reserved MMIO range to be used in Sx handler
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_PHYSICAL_ADDRESS mResvMmioBaseAddr;
+GLOBAL_REMOVE_IF_UNREFERENCED UINTN mResvMmioSize;
+
+/**
+ SMBUS Sx entry SMI handler.
+**/
+VOID
+SmbusSxCallback (
+ VOID
+ )
+{
+ UINT64 SmbusRegBase;
+ UINT16 SmbusIoBase;
+
+ SmbusRegBase = SmbusPciCfgBase ();
+
+ if (PciSegmentRead32 (SmbusRegBase) == 0xFFFFFFFF) {
+ return;
+ }
+
+ SmbusIoBase = PciSegmentRead16 (SmbusRegBase + R_SMBUS_CFG_BASE) & B_SMBUS_CFG_BASE_BAR;
+ if (SmbusIoBase == 0) {
+ return;
+ }
+
+ PciSegmentOr8 (SmbusRegBase + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_IO_SPACE);
+ //
+ // Clear SMBUS status and SMB_WAK_STS of GPE0
+ //
+ IoWrite8 (SmbusIoBase + R_SMBUS_IO_HSTS, B_SMBUS_IO_SMBALERT_STS);
+ IoWrite32 (mAcpiBaseAddr + R_ACPI_IO_GPE0_STS_127_96, B_ACPI_IO_GPE0_STS_127_96_SMB_WAK);
+}
+
+/*
+ PCH xHCI Sx entry SMI handler
+*/
+VOID
+PchXhciSxCallback (
+ VOID
+ )
+{
+ UINTN XhciPciBase;
+
+ XhciPciBase = PchXhciPciCfgBase ();
+
+ //
+ // Safety check for xHCI existense
+ //
+ if (PciSegmentRead32 (XhciPciBase) == 0xFFFFFFFF) {
+ return;
+ }
+
+ //
+ // If xHCI is in D0 that means OS didn't put it to D3 during Sx entry i.e. USB kernel debug is enabled.
+ // Unless it is put manually to D3, USB wake functionality will not work.
+ //
+ if ((PciSegmentRead8 (XhciPciBase + R_XHCI_CFG_PWR_CNTL_STS) & V_XHCI_CFG_PWR_CNTL_STS_PWR_STS_D3) == 0) {
+ //
+ // Put device to D3 to enable wake functionality for USB devices
+ //
+ PciSegmentOr8 (XhciPciBase + R_XHCI_CFG_PWR_CNTL_STS, (UINT8)(B_XHCI_CFG_PWR_CNTL_STS_PWR_STS));
+ }
+}
+
+/**
+ Cache PCH FIVR policy.
+**/
+VOID
+UpdatePchFivrSettings (
+ VOID
+ )
+{
+ CopyMem (
+ &mFivrExtVnnRailSxConfig,
+ &mPchConfigHob->Fivr.ExtVnnRailSx,
+ sizeof (mFivrExtVnnRailSxConfig)
+ );
+}
+
+/**
+ PCH Sx entry SMI handler.
+
+ @param[in] Handle Handle of the callback
+ @param[in] Context The dispatch context
+ @param[in,out] CommBuffer A pointer to a collection of data in memory that will
+ be conveyed from a non-SMM environment into an SMM environment.
+ @param[in,out] CommBufferSize The size of the CommBuffer.
+
+ @retval EFI_SUCCESS
+**/
+EFI_STATUS
+EFIAPI
+PchSxHandler (
+ IN EFI_HANDLE Handle,
+ IN CONST VOID *Context OPTIONAL,
+ IN OUT VOID *CommBuffer OPTIONAL,
+ IN OUT UINTN *CommBufferSize OPTIONAL
+ )
+{
+ PchLanSxCallback ();
+ PchXhciSxCallback ();
+
+ SmbusSxCallback ();
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Initialize PCH Sx entry SMI handler.
+
+ @param[in] ImageHandle - Handle for the image of this driver
+**/
+VOID
+InitializeSxHandler (
+ IN EFI_HANDLE ImageHandle
+ )
+{
+ EFI_SMM_SX_REGISTER_CONTEXT SxDispatchContext;
+ EFI_HANDLE SxDispatchHandle;
+ EFI_SLEEP_TYPE SxType;
+ EFI_STATUS Status;
+
+ DEBUG ((DEBUG_INFO, "InitializeSxHandler() Start\n"));
+
+ //
+ // Register the callback for S3/S4/S5 entry
+ //
+ SxDispatchContext.Phase = SxEntry;
+ for (SxType = SxS3; SxType <= SxS5; SxType++) {
+ SxDispatchContext.Type = SxType;
+ Status = mSxDispatch->Register (
+ mSxDispatch,
+ PchSxHandler,
+ &SxDispatchContext,
+ &SxDispatchHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ DEBUG ((DEBUG_INFO, "InitializeSxHandler() End\n"));
+}
+
+/**
+ Allocates reserved MMIO for Sx SMI handler use.
+**/
+VOID
+AllocateReservedMmio (
+ VOID
+ )
+{
+ mResvMmioBaseAddr = PcdGet32 (PcdSiliconInitTempMemBaseAddr);
+ mResvMmioSize = PcdGet32 (PcdSiliconInitTempMemSize);
+ DEBUG ((DEBUG_INFO, "mResvMmioBaseAddr %x, mResvMmioSize %x\n", mResvMmioBaseAddr, mResvMmioSize));
+}
+
+/**
+ Initializes the PCH SMM handler for for PCIE hot plug support
+ <b>PchInit SMM Module Entry Point</b>\n
+ - <b>Introduction</b>\n
+ The PchInitSmm module is a SMM driver that initializes the Intel Platform Controller Hub
+ SMM requirements and services. It consumes the PCH_POLICY_HOB and SI_POLICY_HOB for expected
+ configurations per policy.
+
+ - <b>Details</b>\n
+ This module provides SMI handlers to services PCIE HotPlug SMI, LinkActive SMI, and LinkEq SMI.
+ And also provides port 0x61 emulation support, registers BIOS WP handler to process BIOSWP status,
+ and registers SPI Async SMI handler to handler SPI Async SMI.
+ This module also registers Sx SMI callback function to detail with GPIO Sx Isolation and LAN requirement.
+
+ - @pre
+ - PCH PCR base address configured
+ - EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
+ - This is to ensure that PCI MMIO and IO resource has been prepared and available for this driver to allocate.
+ - EFI_SMM_BASE2_PROTOCOL
+ - EFI_SMM_IO_TRAP_DISPATCH2_PROTOCOL
+ - EFI_SMM_SX_DISPATCH2_PROTOCOL
+ - EFI_SMM_CPU_PROTOCOL
+ - @link _PCH_SMM_IO_TRAP_CONTROL_PROTOCOL PCH_SMM_IO_TRAP_CONTROL_PROTOCOL @endlink
+ - @link _PCH_SMI_DISPATCH_PROTOCOL PCH_SMI_DISPATCH_PROTOCOL @endlink
+ - @link _PCH_PCIE_SMI_DISPATCH_PROTOCOL PCH_PCIE_SMI_DISPATCH_PROTOCOL @endlink
+ - @link _PCH_TCO_SMI_DISPATCH_PROTOCOL PCH_TCO_SMI_DISPATCH_PROTOCOL @endlink
+ - @link _PCH_ESPI_SMI_DISPATCH_PROTOCOL PCH_ESPI_SMI_DISPATCH_PROTOCOL @endlink
+
+ - <b>References</b>\n
+ - @link _PCH_POLICY PCH_POLICY_HOB @endlink.
+ - @link _SI_POLICY_STRUCT SI_POLICY_HOB @endlink.
+
+ - <b>Integration Checklists</b>\n
+ - Verify prerequisites are met. Porting Recommendations.
+ - No modification of this module should be necessary
+ - Any modification of this module should follow the PCH BIOS Specification and EDS
+
+ @param[in] ImageHandle - Handle for the image of this driver
+ @param[in] SystemTable - Pointer to the EFI System Table
+
+ @retval EFI_SUCCESS - PCH SMM handler was installed
+**/
+EFI_STATUS
+EFIAPI
+PchInitSmmEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ PCH_NVS_AREA_PROTOCOL *PchNvsAreaProtocol;
+ EFI_PEI_HOB_POINTERS HobPtr;
+
+ DEBUG ((DEBUG_INFO, "PchInitSmmEntryPoint()\n"));
+
+ Status = gSmst->SmmLocateProtocol (
+ &gEfiSmmIoTrapDispatch2ProtocolGuid,
+ NULL,
+ (VOID **) &mPchIoTrap
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = gSmst->SmmLocateProtocol (
+ &gEfiSmmSxDispatch2ProtocolGuid,
+ NULL,
+ (VOID**) &mSxDispatch
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = gBS->LocateProtocol (&gPchNvsAreaProtocolGuid, NULL, (VOID **) &PchNvsAreaProtocol);
+ ASSERT_EFI_ERROR (Status);
+ mPchNvsArea = PchNvsAreaProtocol->Area;
+
+ //
+ // Get PCH Data HOB.
+ //
+ HobPtr.Guid = GetFirstGuidHob (&gPchConfigHobGuid);
+ ASSERT (HobPtr.Guid != NULL);
+ mPchConfigHob = (PCH_CONFIG_HOB *) GET_GUID_HOB_DATA (HobPtr.Guid);
+
+ mAcpiBaseAddr = PmcGetAcpiBase ();
+
+ AllocateReservedMmio ();
+
+ InitializeSxHandler (ImageHandle);
+
+ Status = InitializePchPcieSmm (ImageHandle, SystemTable);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = InstallPchBiosWriteProtect (ImageHandle, SystemTable);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = InstallPchSpiAsyncSmiHandler ();
+ ASSERT_EFI_ERROR (Status);
+
+ UpdateHdaCodecSxWakeCapabilitySetting ();
+
+ UpdatePchFivrSettings ();
+
+
+ return EFI_SUCCESS;
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Smm/PchInitSmm.h b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Smm/PchInitSmm.h
new file mode 100644
index 0000000000..c2a09acd11
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Smm/PchInitSmm.h
@@ -0,0 +1,254 @@
+/** @file
+ Header file for PCH Init SMM Handler
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _PCH_INIT_SMM_H_
+#define _PCH_INIT_SMM_H_
+
+#include <PiDxe.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/SmmServicesTableLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Protocol/SmmSxDispatch2.h>
+#include <Protocol/SmmIoTrapDispatch2.h>
+#include <Library/S3BootScriptLib.h>
+#include <Library/HobLib.h>
+#include <Protocol/SmmCpu.h>
+#include <Library/TimerLib.h>
+
+#include <IndustryStandard/Pci30.h>
+#include <Library/PmcLib.h>
+#include <Library/PchPcieRpLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/SataLib.h>
+#include <Library/GpioLib.h>
+#include <Library/GpioNativeLib.h>
+#include <Library/EspiLib.h>
+#include <Library/PciSegmentLib.h>
+#include <Library/ConfigBlockLib.h>
+#include <Library/PciExpressHelpersLib.h>
+#include <Protocol/PchPcieSmiDispatch.h>
+#include <Protocol/PchTcoSmiDispatch.h>
+#include <Protocol/PchSmiDispatch.h>
+#include <Protocol/PchEspiSmiDispatch.h>
+#include <Protocol/PchSmmIoTrapControl.h>
+#include <Protocol/PchNvsArea.h>
+#include <Protocol/PcieIoTrap.h>
+#include <SiConfigHob.h>
+#include <PchConfigHob.h>
+#include <Library/PmcPrivateLib.h>
+
+extern EFI_SMM_IO_TRAP_DISPATCH2_PROTOCOL *mPchIoTrap;
+extern EFI_SMM_SX_DISPATCH2_PROTOCOL *mSxDispatch;
+
+extern PCH_NVS_AREA *mPchNvsArea;
+extern UINT16 mAcpiBaseAddr;
+
+extern EFI_PHYSICAL_ADDRESS mResvMmioBaseAddr;
+extern UINTN mResvMmioSize;
+
+//
+// NOTE: The module variables of policy here are only valid in post time, but not runtime time.
+//
+extern PCH_CONFIG_HOB *mPchConfigHob;
+extern SI_CONFIG_HOB_DATA *mSiConfigHobData;
+
+/**
+ Register PCIE Hotplug SMI dispatch function to handle Hotplug enabling
+
+ @param[in] ImageHandle The image handle of this module
+ @param[in] SystemTable The EFI System Table
+
+ @retval EFI_SUCCESS The function completes successfully
+**/
+EFI_STATUS
+EFIAPI
+InitializePchPcieSmm (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Program Common Clock and ASPM of Downstream Devices
+
+ @param[in] PortIndex Pcie Root Port Number
+ @param[in] RpDevice Pcie Root Pci Device Number
+ @param[in] RpFunction Pcie Root Pci Function Number
+
+ @retval EFI_SUCCESS Root port complete successfully
+ @retval EFI_UNSUPPORTED PMC has invalid vendor ID
+**/
+EFI_STATUS
+PchPcieSmi (
+ IN UINT8 PortIndex,
+ IN UINT8 RpDevice,
+ IN UINT8 RpFunction
+ );
+
+/**
+ PCIE Hotplug SMI call back function for each Root port
+
+ @param[in] DispatchHandle Handle of this dispatch function
+ @param[in] RpContext Rootport context, which contains RootPort Index,
+ and RootPort PCI BDF.
+**/
+VOID
+EFIAPI
+PchPcieSmiRpHandlerFunction (
+ IN EFI_HANDLE DispatchHandle,
+ IN PCH_PCIE_SMI_RP_CONTEXT *RpContext
+ );
+
+/**
+ PCIE Link Active State Change Hotplug SMI call back function for all Root ports
+
+ @param[in] DispatchHandle Handle of this dispatch function
+ @param[in] RpContext Rootport context, which contains RootPort Index,
+ and RootPort PCI BDF.
+**/
+VOID
+EFIAPI
+PchPcieLinkActiveStateChange (
+ IN EFI_HANDLE DispatchHandle,
+ IN PCH_PCIE_SMI_RP_CONTEXT *RpContext
+ );
+
+/**
+ PCIE Link Equalization Request SMI call back function for all Root ports
+
+ @param[in] DispatchHandle Handle of this dispatch function
+ @param[in] RpContext Rootport context, which contains RootPort Index,
+ and RootPort PCI BDF.
+**/
+VOID
+EFIAPI
+PchPcieLinkEqHandlerFunction (
+ IN EFI_HANDLE DispatchHandle,
+ IN PCH_PCIE_SMI_RP_CONTEXT *RpContext
+ );
+
+/**
+ An IoTrap callback to config PCIE power management settings
+
+ @param[in] DispatchHandle - The handle of this callback, obtained when registering
+ @param[in] DispatchContext - Pointer to the EFI_SMM_IO_TRAP_DISPATCH_CALLBACK_CONTEXT
+
+**/
+VOID
+EFIAPI
+PchPcieIoTrapSmiCallback (
+ IN EFI_HANDLE DispatchHandle,
+ IN EFI_SMM_IO_TRAP_CONTEXT *CallbackContext,
+ IN OUT VOID *CommBuffer,
+ IN OUT UINTN *CommBufferSize
+ );
+
+/**
+ Initializes the PCH SMM handler for PCH save and restore
+
+ @param[in] ImageHandle - Handle for the image of this driver
+ @param[in] SystemTable - Pointer to the EFI System Table
+
+ @retval EFI_SUCCESS - PCH SMM handler was installed
+**/
+EFI_STATUS
+EFIAPI
+PchInitLateSmm (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Initialize PCH Sx entry SMI handler.
+
+ @param[in] ImageHandle - Handle for the image of this driver
+**/
+VOID
+InitializeSxHandler (
+ IN EFI_HANDLE ImageHandle
+ );
+
+/**
+ PCH Sx entry SMI handler.
+
+ @param[in] Handle Handle of the callback
+ @param[in] Context The dispatch context
+ @param[in,out] CommBuffer A pointer to a collection of data in memory that will
+ be conveyed from a non-SMM environment into an SMM environment.
+ @param[in,out] CommBufferSize The size of the CommBuffer.
+
+ @retval EFI_SUCCESS
+**/
+
+EFI_STATUS
+EFIAPI
+PchSxHandler (
+ IN EFI_HANDLE Handle,
+ IN CONST VOID *Context OPTIONAL,
+ IN OUT VOID *CommBuffer OPTIONAL,
+ IN OUT UINTN *CommBufferSize OPTIONAL
+ );
+
+/**
+ GbE Sx entry handler
+**/
+VOID
+PchLanSxCallback (
+ VOID
+ );
+
+/**
+ Updates Codec Sx Wake Capability setting: disabled/enabled
+**/
+VOID
+UpdateHdaCodecSxWakeCapabilitySetting (
+ VOID
+ );
+
+/**
+ Register dispatch function to handle GPIO pads Sx isolation
+**/
+VOID
+InitializeGpioSxIsolationSmm (
+ VOID
+ );
+
+/**
+ Entry point for Pch Bios Write Protect driver.
+
+ @param[in] ImageHandle Image handle of this driver.
+ @param[in] SystemTable Global system service table.
+
+ @retval EFI_SUCCESS Initialization complete.
+**/
+EFI_STATUS
+EFIAPI
+InstallPchBiosWriteProtect (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ This fuction install SPI ASYNC SMI handler.
+
+ @retval EFI_SUCCESS Initialization complete.
+**/
+EFI_STATUS
+EFIAPI
+InstallPchSpiAsyncSmiHandler (
+ VOID
+ );
+
+
+
+
+
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Smm/PchInitSmm.inf b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Smm/PchInitSmm.inf
new file mode 100644
index 0000000000..aaf36a7b2a
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Smm/PchInitSmm.inf
@@ -0,0 +1,110 @@
+## @file
+# Component description file for PchInitSmm driver
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PchInitSmm
+FILE_GUID = D7B10D4E-67E6-4C74-83E9-F9AF0ACC33CC
+VERSION_STRING = 1.0
+MODULE_TYPE = DXE_SMM_DRIVER
+PI_SPECIFICATION_VERSION = 1.10
+ENTRY_POINT = PchInitSmmEntryPoint
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+
+[LibraryClasses]
+UefiBootServicesTableLib
+UefiDriverEntryPoint
+DxeServicesTableLib
+IoLib
+DebugLib
+BaseLib
+BaseMemoryLib
+S3BootScriptLib
+PciExpressHelpersLib
+SmmServicesTableLib
+PciSegmentLib
+HobLib
+GpioLib
+GpioPrivateLib
+ReportStatusCodeLib
+DevicePathLib
+PmcLib
+PchPcieRpLib
+PchInfoLib
+EspiLib
+TimerLib
+ConfigBlockLib
+PmcPrivateLib
+SataLib
+GbeLib
+GbeMdiLib
+SpiAccessPrivateLib
+PchPciBdfLib
+
+[Packages]
+MdePkg/MdePkg.dec
+TigerlakeSiliconPkg/SiPkg.dec
+
+
+[Pcd]
+gSiPkgTokenSpaceGuid.PcdSiPciExpressBaseAddress
+gSiPkgTokenSpaceGuid.PcdSiliconInitTempPciBusMin
+gSiPkgTokenSpaceGuid.PcdSiliconInitTempPciBusMax
+gSiPkgTokenSpaceGuid.PcdSiliconInitTempMemBaseAddr
+gSiPkgTokenSpaceGuid.PcdSiliconInitTempMemSize
+
+
+[Sources]
+PchInitSmm.c
+PchPcieSmm.c
+GbeSxSmm.c
+PchInitSmm.h
+PchBiosWriteProtect.c
+PchSpiAsync.c
+PchHdaSxSmm.c
+
+
+[Protocols]
+gEfiSmmIoTrapDispatch2ProtocolGuid ## CONSUMES
+gEfiSmmSxDispatch2ProtocolGuid ## CONSUMES
+gPchSmmIoTrapControlGuid ## CONSUMES
+gEfiSmmCpuProtocolGuid ## CONSUMES
+gPchNvsAreaProtocolGuid ## CONSUMES
+gPchPcieSmiDispatchProtocolGuid ## CONSUMES
+gPchTcoSmiDispatchProtocolGuid ## CONSUMES
+gPchSmiDispatchProtocolGuid ## CONSUMES
+gPchEspiSmiDispatchProtocolGuid ## CONSUMES
+gPchPcieIoTrapProtocolGuid ## PRODUCES
+gPchPolicyProtocolGuid ##CONSUMES
+
+
+[Guids]
+gSiConfigHobGuid ## CONSUMES
+gPchConfigHobGuid ## CONSUMES
+gPchDeviceTableHobGuid
+gPchPcieRpDxeConfigGuid ## CONSUMES
+
+
+[Depex]
+gEfiSmmIoTrapDispatch2ProtocolGuid AND
+gEfiSmmSxDispatch2ProtocolGuid AND
+gPchSmmIoTrapControlGuid AND
+gPchPcieSmiDispatchProtocolGuid AND
+gPchTcoSmiDispatchProtocolGuid AND
+gEfiSmmCpuProtocolGuid AND
+gPchNvsAreaProtocolGuid AND
+gEfiPciHostBridgeResourceAllocationProtocolGuid AND # This is to ensure that PCI MMIO resource has been prepared and available for this driver to allocate.
+gEfiSmmBase2ProtocolGuid AND # This is for SmmServicesTableLib
+gPchPolicyProtocolGuid
+
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Smm/PchPcieSmm.c b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Smm/PchPcieSmm.c
new file mode 100644
index 0000000000..e885a342a7
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Smm/PchPcieSmm.c
@@ -0,0 +1,451 @@
+/** @file
+ PCH Pcie SMM Driver Entry
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include "PchInitSmm.h"
+#include <PcieRegs.h>
+#include <Register/PchRegs.h>
+#include <Register/PchPcieRpRegs.h>
+#include <Library/PcieHelperLib.h>
+#include <Library/PchPciBdfLib.h>
+#include <Protocol/PchPolicy.h>
+
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_PCIE_DEVICE_OVERRIDE *mDevAspmOverride;
+GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mNumOfDevAspmOverride;
+GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mPchBusNumber;
+//
+// @note:
+// These temp bus numbers cannot be used in runtime (hot-plug).
+// These can be used only during boot.
+//
+GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mTempRootPortBusNumMin;
+GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mTempRootPortBusNumMax;
+
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_PCIE_ROOT_PORT_CONFIG mPcieRootPortConfig[PCH_MAX_PCIE_ROOT_PORTS];
+
+GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN mPchPciePmTrapExecuted = FALSE;
+
+extern EFI_GUID gPchDeviceTableHobGuid;
+
+/**
+ Program Common Clock and ASPM of Downstream Devices
+
+ @param[in] PortIndex Pcie Root Port Number
+ @param[in] RpDevice Pcie Root Pci Device Number
+ @param[in] RpFunction Pcie Root Pci Function Number
+
+ @retval EFI_SUCCESS Root port complete successfully
+ @retval EFI_UNSUPPORTED PMC has invalid vendor ID
+**/
+EFI_STATUS
+PchPcieSmi (
+ IN UINT8 PortIndex,
+ IN UINT8 RpDevice,
+ IN UINT8 RpFunction
+ )
+{
+ UINT8 SecBus;
+ UINT8 SubBus;
+ UINT64 RpBase;
+ UINT64 EpBase;
+ UINT8 EpPcieCapPtr;
+ UINT8 EpMaxSpeed;
+ BOOLEAN DownstreamDevicePresent;
+ UINT32 Timeout;
+
+ RpBase = PCI_SEGMENT_LIB_ADDRESS (
+ DEFAULT_PCI_SEGMENT_NUMBER_PCH,
+ mPchBusNumber,
+ (UINT32) RpDevice,
+ (UINT32) RpFunction,
+ 0
+ );
+
+ if (PciSegmentRead16 (RpBase + PCI_VENDOR_ID_OFFSET) == 0xFFFF) {
+ return EFI_SUCCESS;
+ }
+ //
+ // Check presence detect state. Here the endpoint must be detected using PDS rather than
+ // the usual LinkActive check, because PDS changes immediately and LA takes a few milliseconds to stabilize
+ //
+ DownstreamDevicePresent = !!(PciSegmentRead16 (RpBase + R_PCH_PCIE_CFG_SLSTS) & B_PCIE_SLSTS_PDS);
+
+ if (DownstreamDevicePresent) {
+ ///
+ /// Make sure the link is active before trying to talk to device behind it
+ /// Wait up to 100ms, according to PCIE spec chapter 6.7.3.3
+ ///
+ Timeout = 100 * 1000;
+ while ((PciSegmentRead16 (RpBase + R_PCH_PCIE_CFG_LSTS) & B_PCIE_LSTS_LA) == 0 ) {
+ MicroSecondDelay (10);
+ Timeout-=10;
+ if (Timeout == 0) {
+ return EFI_NOT_FOUND;
+ }
+ }
+ SecBus = PciSegmentRead8 (RpBase + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET);
+ SubBus = PciSegmentRead8 (RpBase + PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET);
+ ASSERT (SecBus != 0 && SubBus != 0);
+ RootportDownstreamConfiguration (
+ DEFAULT_PCI_SEGMENT_NUMBER_PCH,
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ RpDevice,
+ RpFunction,
+ mTempRootPortBusNumMin,
+ mTempRootPortBusNumMax,
+ EnumPchPcie
+ );
+ RootportDownstreamPmConfiguration (
+ DEFAULT_PCI_SEGMENT_NUMBER_PCH,
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ RpDevice,
+ RpFunction,
+ mTempRootPortBusNumMin,
+ mTempRootPortBusNumMax,
+ &mPcieRootPortConfig[PortIndex].PcieRpCommonConfig,
+ mNumOfDevAspmOverride,
+ mDevAspmOverride
+ );
+ //
+ // Perform Equalization
+ //
+ EpBase = PCI_SEGMENT_LIB_ADDRESS (DEFAULT_PCI_SEGMENT_NUMBER_PCH, SecBus, 0, 0, 0);
+ EpPcieCapPtr = PcieFindCapId (DEFAULT_PCI_SEGMENT_NUMBER_PCH, SecBus, 0, 0, EFI_PCI_CAPABILITY_ID_PCIEXP);
+ EpMaxSpeed = PciSegmentRead8 (EpBase + EpPcieCapPtr + R_PCIE_LCAP_OFFSET) & B_PCIE_LCAP_MLS;
+ if (EpMaxSpeed >= 3) {
+ PciSegmentOr32 (RpBase + R_PCH_PCIE_CFG_EX_LCTL3, B_PCIE_EX_LCTL3_PE);
+ PciSegmentOr32 (RpBase + R_PCH_PCIE_CFG_LCTL, B_PCIE_LCTL_RL);
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ PCIE Hotplug SMI call back function for each Root port
+
+ @param[in] DispatchHandle Handle of this dispatch function
+ @param[in] RpContext Rootport context, which contains RootPort Index,
+ and RootPort PCI BDF.
+**/
+VOID
+EFIAPI
+PchPcieSmiRpHandlerFunction (
+ IN EFI_HANDLE DispatchHandle,
+ IN PCH_PCIE_SMI_RP_CONTEXT *RpContext
+ )
+{
+ PchPcieSmi (RpContext->RpIndex, RpContext->DevNum, RpContext->FuncNum);
+}
+
+/**
+ PCIE Link Active State Change Hotplug SMI call back function for all Root ports
+
+ @param[in] DispatchHandle Handle of this dispatch function
+ @param[in] RpContext Rootport context, which contains RootPort Index,
+ and RootPort PCI BDF.
+**/
+VOID
+EFIAPI
+PchPcieLinkActiveStateChange (
+ IN EFI_HANDLE DispatchHandle,
+ IN PCH_PCIE_SMI_RP_CONTEXT *RpContext
+ )
+{
+ return;
+}
+
+/**
+ PCIE Link Equalization Request SMI call back function for all Root ports
+
+ @param[in] DispatchHandle Handle of this dispatch function
+ @param[in] RpContext Rootport context, which contains RootPort Index,
+ and RootPort PCI BDF.
+**/
+VOID
+EFIAPI
+PchPcieLinkEqHandlerFunction (
+ IN EFI_HANDLE DispatchHandle,
+ IN PCH_PCIE_SMI_RP_CONTEXT *RpContext
+ )
+{
+ ///
+ /// From PCI Express specification, the PCIe device can request for Link Equalization. When the
+ /// Link Equalization is requested by the device, an SMI will be generated by PCIe RP when
+ /// enabled and the SMI subroutine would invoke the Software Preset/Coefficient Search
+ /// software to re-equalize the link.
+ ///
+
+ return;
+
+}
+
+/**
+ An IoTrap callback to config PCIE power management settings
+**/
+VOID
+PchPciePmIoTrapSmiCallback (
+ VOID
+ )
+{
+ UINT32 PortIndex;
+ UINT64 RpBase;
+ UINT8 MaxPciePortNum;
+
+ MaxPciePortNum = GetPchMaxPciePortNum ();
+
+ for (PortIndex = 0; PortIndex < MaxPciePortNum; PortIndex++) {
+ RpBase = PchPcieRpPciCfgBase (PortIndex);
+
+ if (PciSegmentRead16 (RpBase) != 0xFFFF) {
+ RootportDownstreamPmConfiguration (
+ DEFAULT_PCI_SEGMENT_NUMBER_PCH,
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PchPcieRpDevNumber (PortIndex),
+ PchPcieRpFuncNumber (PortIndex),
+ mTempRootPortBusNumMin,
+ mTempRootPortBusNumMax,
+ &mPcieRootPortConfig[PortIndex].PcieRpCommonConfig,
+ mNumOfDevAspmOverride,
+ mDevAspmOverride
+ );
+
+ }
+ }
+}
+
+/**
+ An IoTrap callback to config PCIE power management settings
+
+ @param[in] DispatchHandle - The handle of this callback, obtained when registering
+ @param[in] DispatchContext - Pointer to the EFI_SMM_IO_TRAP_DISPATCH_CALLBACK_CONTEXT
+
+**/
+VOID
+EFIAPI
+PchPcieIoTrapSmiCallback (
+ IN EFI_HANDLE DispatchHandle,
+ IN EFI_SMM_IO_TRAP_CONTEXT *CallbackContext,
+ IN OUT VOID *CommBuffer,
+ IN OUT UINTN *CommBufferSize
+ )
+{
+ if (CallbackContext->WriteData == PchPciePmTrap) {
+ if (mPchPciePmTrapExecuted == FALSE) {
+ PchPciePmIoTrapSmiCallback ();
+ mPchPciePmTrapExecuted = TRUE;
+ }
+ } else {
+ ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
+ }
+}
+
+/**
+ This function clear the Io trap executed flag before enter S3
+
+ @param[in] Handle Handle of the callback
+ @param[in] Context The dispatch context
+
+ @retval EFI_SUCCESS PCH register saved
+**/
+EFI_STATUS
+EFIAPI
+PchPcieS3EntryCallBack (
+ IN EFI_HANDLE Handle,
+ IN CONST VOID *Context OPTIONAL,
+ IN OUT VOID *CommBuffer OPTIONAL,
+ IN OUT UINTN *CommBufferSize OPTIONAL
+ )
+{
+ mPchPciePmTrapExecuted = FALSE;
+ return EFI_SUCCESS;
+}
+/**
+ Register PCIE Hotplug SMI dispatch function to handle Hotplug enabling
+
+ @param[in] ImageHandle The image handle of this module
+ @param[in] SystemTable The EFI System Table
+
+ @retval EFI_SUCCESS The function completes successfully
+**/
+EFI_STATUS
+EFIAPI
+InitializePchPcieSmm (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ UINT8 PortIndex;
+ UINT8 Data8;
+ UINT32 Data32Or;
+ UINT32 Data32And;
+ UINT64 RpBase;
+ EFI_HANDLE PcieHandle;
+ PCH_PCIE_SMI_DISPATCH_PROTOCOL *PchPcieSmiDispatchProtocol;
+ EFI_HANDLE PchIoTrapHandle;
+ EFI_SMM_IO_TRAP_REGISTER_CONTEXT PchIoTrapContext;
+ EFI_SMM_SX_REGISTER_CONTEXT SxDispatchContext;
+ PCH_PCIE_IOTRAP_PROTOCOL *PchPcieIoTrapProtocol;
+ EFI_HANDLE SxDispatchHandle;
+ UINT8 MaxPciePortNum;
+ PCH_POLICY_PROTOCOL *PchPolicy;
+ PCIE_RP_DXE_CONFIG *PchPcieRpDxeConfig;
+ UINTN PcieDeviceTableSize;
+ PCH_PCIE_DEVICE_OVERRIDE *DevAspmOverride;
+ UINTN Count;
+
+ DEBUG ((DEBUG_INFO, "InitializePchPcieSmm () Start\n"));
+
+ MaxPciePortNum = GetPchMaxPciePortNum ();
+
+ //
+ // Locate Pch Pcie Smi Dispatch Protocol
+ //
+ Status = gSmst->SmmLocateProtocol (&gPchPcieSmiDispatchProtocolGuid, NULL, (VOID**) &PchPcieSmiDispatchProtocol);
+ ASSERT_EFI_ERROR (Status);
+
+ mPchBusNumber = DEFAULT_PCI_BUS_NUMBER_PCH;
+ mTempRootPortBusNumMin = PcdGet8 (PcdSiliconInitTempPciBusMin);
+ mTempRootPortBusNumMax = PcdGet8 (PcdSiliconInitTempPciBusMax);
+
+ ASSERT (sizeof mPcieRootPortConfig == sizeof mPchConfigHob->PcieRp.RootPort);
+ CopyMem (
+ mPcieRootPortConfig,
+ &(mPchConfigHob->PcieRp.RootPort),
+ sizeof (mPcieRootPortConfig)
+ );
+
+ DevAspmOverride = NULL;
+ mDevAspmOverride = NULL;
+ mNumOfDevAspmOverride = 0;
+
+ Status = gBS->LocateProtocol (&gPchPolicyProtocolGuid, NULL, (VOID **) &PchPolicy);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = GetConfigBlock ((VOID*) PchPolicy, &gPchPcieRpDxeConfigGuid, (VOID*) &PchPcieRpDxeConfig);
+ ASSERT_EFI_ERROR (Status);
+
+ DevAspmOverride = PchPcieRpDxeConfig->PcieDeviceOverrideTablePtr;
+
+ Count = 0;
+ if (DevAspmOverride != NULL) {
+ for (Count = 0; DevAspmOverride[Count].DeviceId != 0; Count++) {}
+ }
+
+ if (Count !=0) {
+ PcieDeviceTableSize = Count * sizeof (PCH_PCIE_DEVICE_OVERRIDE);
+ Status = gSmst->SmmAllocatePool (
+ EfiRuntimeServicesData,
+ PcieDeviceTableSize,
+ (VOID **) &mDevAspmOverride
+ );
+ ASSERT_EFI_ERROR (Status);
+ CopyMem (mDevAspmOverride, DevAspmOverride, PcieDeviceTableSize);
+ mNumOfDevAspmOverride = (UINT32) Count;
+ }
+ //
+ // Throught all PCIE root port function and register the SMI Handler for enabled ports.
+ //
+ for (PortIndex = 0; PortIndex < MaxPciePortNum; PortIndex++) {
+ RpBase = PchPcieRpPciCfgBase (PortIndex);
+ //
+ // Skip the root port function which is not enabled
+ //
+ if (PciSegmentRead32 (RpBase) == 0xFFFFFFFF) {
+ continue;
+ }
+
+ //
+ // Register SMI Handlers for Hot Plug and Link Active State Change
+ //
+ Data8 = PciSegmentRead8 (RpBase + R_PCH_PCIE_CFG_SLCAP);
+ if (Data8 & B_PCIE_SLCAP_HPC) {
+ PcieHandle = NULL;
+ Status = PchPcieSmiDispatchProtocol->HotPlugRegister (
+ PchPcieSmiDispatchProtocol,
+ PchPcieSmiRpHandlerFunction,
+ PortIndex,
+ &PcieHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = PchPcieSmiDispatchProtocol->LinkActiveRegister (
+ PchPcieSmiDispatchProtocol,
+ PchPcieLinkActiveStateChange,
+ PortIndex,
+ &PcieHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Data32Or = B_PCH_PCIE_CFG_MPC_HPME;
+ Data32And = (UINT32) ~B_PCH_PCIE_CFG_MPC_HPME;
+ PciSegmentOr32 (RpBase + R_PCH_PCIE_CFG_MPC, Data32Or);
+ S3BootScriptSaveMemReadWrite (
+ S3BootScriptWidthUint32,
+ PcdGet64 (PcdSiPciExpressBaseAddress) + RpBase + R_PCH_PCIE_CFG_MPC,
+ &Data32Or, /// Data to be ORed
+ &Data32And /// Data to be ANDed
+ );
+ }
+
+ //
+ // Register SMI Handler for Link Equalization Request from Gen 3 Devices.
+ //
+ Data8 = PciSegmentRead8 (RpBase + R_PCH_PCIE_CFG_LCAP);
+ if ((Data8 & B_PCIE_LCAP_MLS) == V_PCIE_LCAP_MLS_GEN3) {
+ Status = PchPcieSmiDispatchProtocol->LinkEqRegister (
+ PchPcieSmiDispatchProtocol,
+ PchPcieLinkEqHandlerFunction,
+ PortIndex,
+ &PcieHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+ }
+
+ ASSERT_EFI_ERROR (Status);
+
+ PchIoTrapContext.Type = WriteTrap;
+ PchIoTrapContext.Length = 4;
+ PchIoTrapContext.Address = 0;
+ Status = mPchIoTrap->Register (
+ mPchIoTrap,
+ (EFI_SMM_HANDLER_ENTRY_POINT2) PchPcieIoTrapSmiCallback,
+ &PchIoTrapContext,
+ &PchIoTrapHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Install the PCH Pcie IoTrap protocol
+ //
+ (gBS->AllocatePool) (EfiBootServicesData, sizeof (PCH_PCIE_IOTRAP_PROTOCOL), (VOID **)&PchPcieIoTrapProtocol);
+ PchPcieIoTrapProtocol->PcieTrapAddress = PchIoTrapContext.Address;
+
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &ImageHandle,
+ &gPchPcieIoTrapProtocolGuid,
+ PchPcieIoTrapProtocol,
+ NULL
+ );
+
+ //
+ // Register the callback for S3 entry
+ //
+ SxDispatchContext.Type = SxS3;
+ SxDispatchContext.Phase = SxEntry;
+ Status = mSxDispatch->Register (
+ mSxDispatch,
+ PchPcieS3EntryCallBack,
+ &SxDispatchContext,
+ &SxDispatchHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ DEBUG ((DEBUG_INFO, "InitializePchPcieSmm, IoTrap @ %x () End\n", PchIoTrapContext.Address));
+
+ return EFI_SUCCESS;
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Smm/PchSpiAsync.c b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Smm/PchSpiAsync.c
new file mode 100644
index 0000000000..bdae6fe918
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchInit/Smm/PchSpiAsync.c
@@ -0,0 +1,67 @@
+/** @file
+ PCH SPI Async SMI handler.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include "PchInitSmm.h"
+
+///
+/// Global variables
+///
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_SMI_DISPATCH_PROTOCOL *mPchSmiDispatchProtocol;
+
+/**
+ This hardware SMI handler will be run every time the flash write/earse happens.
+
+ @param[in] DispatchHandle Not used
+
+**/
+VOID
+EFIAPI
+PchSpiAsyncCallback (
+ IN EFI_HANDLE DispatchHandle
+ )
+{
+ //
+ // Dummy SMI handler
+ //
+}
+
+/**
+ This fuction install SPI ASYNC SMI handler.
+
+ @retval EFI_SUCCESS Initialization complete.
+**/
+EFI_STATUS
+EFIAPI
+InstallPchSpiAsyncSmiHandler (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE Handle;
+
+ DEBUG ((DEBUG_INFO, "InstallPchSpiAsyncSmiHandler()\n"));
+
+ ///
+ /// Get the PCH SMM dispatch protocol
+ ///
+ mPchSmiDispatchProtocol = NULL;
+ Status = gSmst->SmmLocateProtocol (&gPchSmiDispatchProtocolGuid, NULL, (VOID **) &mPchSmiDispatchProtocol);
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Register an SpiAsync callback function
+ ///
+ Handle = NULL;
+ Status = mPchSmiDispatchProtocol->SpiAsyncRegister (
+ mPchSmiDispatchProtocol,
+ PchSpiAsyncCallback,
+ &Handle
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
+
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/IoTrap.c b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/IoTrap.c
new file mode 100644
index 0000000000..54a1575f2c
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/IoTrap.c
@@ -0,0 +1,1284 @@
+/** @file
+ Main implementation source file for the Io Trap SMM driver
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include "PchSmmHelpers.h"
+#include <Protocol/PchNvsArea.h>
+#include <Library/SmiHandlerProfileLib.h>
+#include <Register/PchPcrRegs.h>
+#include <Register/PchRegsPsth.h>
+#include <Register/PchDmiRegs.h>
+
+#define GENERIC_IOTRAP_SIZE 0x100
+
+//
+// Module global variables
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_HANDLE mDriverImageHandle;
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_HANDLE mIoTrapHandle;
+
+GLOBAL_REMOVE_IF_UNREFERENCED IO_TRAP_INSTANCE mIoTrapData;
+GLOBAL_REMOVE_IF_UNREFERENCED IO_TRAP_RECORD *mIoTrapRecord;
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_NVS_AREA *mPchNvsArea;
+
+
+static CONST UINT16 mLengthTable[10] = { 1, 2, 3, 4, 8, 16, 32, 64, 128, 256 };
+
+/**
+ Helper function that encapsulates IoTrap register access.
+ IO trap related register updates must be made in 2 registers, IOTRAP and DMI source decode.
+
+ @param[in] TrapHandlerNum trap number (0-3)
+ @param[in] Value value to be written in both registers
+ @param[in] SaveToBootscript if true, this register write will be saved to bootscript
+
+**/
+VOID
+SetIoTrapLowDword (
+ IN UINT8 TrapHandlerNum,
+ IN UINT32 Value,
+ IN BOOLEAN SaveToBootscript
+ )
+{
+ UINT32 BitMask;
+ UINT32 BitValue;
+ //
+ // To provide sequentially consistent programming model for IO trap
+ // all pending IO cycles must be flushed before enabling and before disabling a trap.
+ // Without this the trap may trigger due to IO cycle issued before the trap is enabled or a cycle issued before the trap is disabled might be missed.
+ // a. Issues a MemRd to PSTH IO Trap Enable bit -> This serves to flush all previous IO cycles.
+ // b. Then only issues a MemWr to PSTH IO Trap Enable == Value
+ // c. Issues another MemRd to PSTH IO Trap Enable bit -> This serves to push the MemWr to PSTH and confirmed that IO Trap is in fact enabled
+ //
+ PchPcrRead32 (PID_PSTH, R_PSTH_PCR_TRPREG0 + TrapHandlerNum * 8);
+ PchPcrWrite32 (PID_PSTH, R_PSTH_PCR_TRPREG0 + TrapHandlerNum * 8, Value);
+ PchPcrRead32 (PID_PSTH, R_PSTH_PCR_TRPREG0 + TrapHandlerNum * 8);
+
+ PchPcrWrite32 (PID_DMI, R_PCH_DMI_PCR_IOT1 + TrapHandlerNum * 8, Value);
+ //
+ // Read back DMI IOTRAP register to enforce ordering so DMI write is completed before any IO reads
+ // from other threads which may occur after this point (after SMI exit).
+ //
+ PchPcrRead32 (PID_DMI, R_PCH_DMI_PCR_IOT1 + TrapHandlerNum * 8);
+ if (SaveToBootscript) {
+ //
+ // Ignore the value check of PCH_PCR_BOOT_SCRIPT_READ
+ //
+ BitMask = 0;
+ BitValue = 0;
+
+ PCH_PCR_BOOT_SCRIPT_READ (S3BootScriptWidthUint32, PID_PSTH, R_PSTH_PCR_TRPREG0 + TrapHandlerNum * 8, &BitMask, &BitValue);
+ PCH_PCR_BOOT_SCRIPT_WRITE (S3BootScriptWidthUint32, PID_PSTH, R_PSTH_PCR_TRPREG0 + TrapHandlerNum * 8, 1, &Value);
+ PCH_PCR_BOOT_SCRIPT_READ (S3BootScriptWidthUint32, PID_PSTH, R_PSTH_PCR_TRPREG0 + TrapHandlerNum * 8, &BitMask, &BitValue);
+ PCH_PCR_BOOT_SCRIPT_WRITE (S3BootScriptWidthUint32, PID_DMI, R_PCH_DMI_PCR_IOT1 + TrapHandlerNum * 8, 1, &Value);
+ }
+}
+
+/**
+ Helper function that encapsulates IoTrap register access.
+ IO trap related register updates must be made in 2 registers, IOTRAP and DMI source decode.
+
+ @param[in] TrapHandlerNum trap number (0-3)
+ @param[in] Value value to be written in both registers
+ @param[in] SaveToBootscript if true, this register write will be saved to bootscript
+
+**/
+VOID
+SetIoTrapHighDword (
+ IN UINT8 TrapHandlerNum,
+ IN UINT32 Value,
+ IN BOOLEAN SaveToBootscript
+ )
+{
+ PchPcrWrite32 (PID_PSTH, R_PSTH_PCR_TRPREG0 + TrapHandlerNum * 8 + 4, Value);
+ PchPcrWrite32 (PID_DMI, R_PCH_DMI_PCR_IOT1 + TrapHandlerNum * 8 + 4, Value);
+ if (SaveToBootscript) {
+ PCH_PCR_BOOT_SCRIPT_WRITE (S3BootScriptWidthUint32, PID_PSTH, R_PSTH_PCR_TRPREG0 + TrapHandlerNum * 8 + 4, 1, &Value);
+ PCH_PCR_BOOT_SCRIPT_WRITE (S3BootScriptWidthUint32, PID_DMI, R_PCH_DMI_PCR_IOT1 + TrapHandlerNum * 8 + 4, 1, &Value);
+ }
+}
+
+/**
+ Clear pending IOTRAP status.
+ If IOTRAP status is pending and IOTRAP is disabled, then BIOS will not find a match SMI source
+ and will not dispatch any SMI handler for it. The pending status will lead to SMI storm.
+ This prevents that IOTRAP gets triggered by pending IO cycles even after it's disabled.
+
+ @param[in] TrapHandlerNum trap number (0-3)
+
+**/
+VOID
+ClearPendingIoTrapStatus (
+ IN UINT8 TrapHandlerNum
+ )
+{
+ PchPcrWrite32 (PID_PSTH, R_PSTH_PCR_TRPST, (UINT32)(1 << TrapHandlerNum));
+}
+
+/**
+ IO resources allocated to IO traps need to be reported to OS so that they don't get reused.
+ This function makes IO trap allocation data available to ACPI
+
+ @param[in] TrapHandlerNum trap number (0-3)
+ @param[in] BaseAddress address of allocated IO resource
+ @param[in] Track TRUE = resource allocated, FALSE = resource freed
+
+**/
+VOID
+UpdateIoTrapAcpiResources (
+ IN UINT8 TrapHandlerNum,
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN BOOLEAN Track
+ )
+{
+
+ if (Track == TRUE) {
+ mPchNvsArea->IoTrapAddress[TrapHandlerNum] = (UINT16) BaseAddress;
+ mPchNvsArea->IoTrapStatus[TrapHandlerNum] = 1;
+ } else {
+ mPchNvsArea->IoTrapStatus[TrapHandlerNum] = 0;
+ }
+}
+
+/**
+ Get address from IOTRAP low dword.
+
+ @param[in] IoTrapRegLowDword IOTRAP register low dword
+
+ @retval Address of IOTRAP setting.
+**/
+STATIC
+UINT16
+AddressFromLowDword (
+ UINT32 IoTrapRegLowDword
+ )
+{
+ return (UINT16) (IoTrapRegLowDword & B_PSTH_PCR_TRPREG_AD);
+}
+
+/**
+ Get length from IOTRAP low dword.
+
+ @param[in] IoTrapRegLowDword IOTRAP register low dword
+
+ @retval Length of IOTRAP setting.
+**/
+STATIC
+UINT16
+LengthFromLowDword (
+ UINT32 IoTrapRegLowDword
+ )
+{
+ return (UINT16) (((IoTrapRegLowDword >> 16) & 0xFC) + 4);
+}
+
+/**
+ Get ByteEnable from IOTRAP high dword.
+
+ @param[in] IoTrapRegHighDword IOTRAP register high dword
+
+ @retval ByteEnable of IOTRAP setting.
+**/
+STATIC
+UINT8
+ByteEnableFromHighDword (
+ UINT32 IoTrapRegHighDword
+ )
+{
+ return (UINT8) (IoTrapRegHighDword & 0x0F);
+}
+
+/**
+ Get ByteEnableMask from IOTRAP high dword.
+
+ @param[in] IoTrapRegHighDword IOTRAP register high dword
+
+ @retval ByteEnableMask of IOTRAP setting.
+**/
+STATIC
+UINT8
+ByteEnableMaskFromHighDword (
+ UINT32 IoTrapRegHighDword
+ )
+{
+ return (UINT8) ((IoTrapRegHighDword & 0xF0) >> 4);
+}
+
+/**
+ Check the IoTrap register matches the IOTRAP EX content.
+
+ @param[in] IoTrapRecord IOTRAP registration record structure
+ @param[in] IoTrapRegLowDword IOTRAP register low dword
+ @param[in] IoTrapRegHighDword IOTRAP register high dword
+
+ @retval TRUE Content matched
+ FALSE Content mismatched
+**/
+STATIC
+BOOLEAN
+IsIoTrapExContentMatched (
+ IO_TRAP_RECORD *IoTrapRecord,
+ UINT32 IoTrapRegLowDword,
+ UINT32 IoTrapRegHighDword
+ )
+{
+ if ((IoTrapRecord->Context.Address == AddressFromLowDword (IoTrapRegLowDword)) &&
+ (IoTrapRecord->Context.Length == LengthFromLowDword (IoTrapRegLowDword)) &&
+ (IoTrapRecord->Context.ByteEnable == ByteEnableFromHighDword (IoTrapRegHighDword)) &&
+ (IoTrapRecord->Context.ByteEnableMask == ByteEnableMaskFromHighDword (IoTrapRegHighDword)))
+ {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+/**
+ The helper function for IoTrap callback dispacther
+
+ @param[in] TrapHandlerNum trap number (0-3)
+**/
+VOID
+IoTrapDispatcherHelper (
+ UINTN TrapHandlerNum
+ )
+{
+ IO_TRAP_RECORD *RecordInDb;
+ LIST_ENTRY *LinkInDb;
+ EFI_SMM_IO_TRAP_REGISTER_CONTEXT CurrentIoTrapRegisterData;
+ EFI_SMM_IO_TRAP_CONTEXT CurrentIoTrapContextData;
+ UINT16 BaseAddress;
+ UINT16 StartAddress;
+ UINT16 EndAddress;
+ UINT32 Data32;
+ UINT8 ActiveHighByteEnable;
+ BOOLEAN ReadCycle;
+ UINT32 WriteData;
+
+ if (!IsListEmpty (&(mIoTrapData.Entry[TrapHandlerNum].CallbackDataBase))) {
+ Data32 = PchPcrRead32 (PID_PSTH, R_PSTH_PCR_TRPC);
+ WriteData = PchPcrRead32 (PID_PSTH, R_PSTH_PCR_TRPD);
+
+ BaseAddress = (UINT16) (Data32 & B_PSTH_PCR_TRPC_IOA);
+ ActiveHighByteEnable = (UINT8)((Data32 & B_PSTH_PCR_TRPC_AHBE) >> 16);
+ ReadCycle = (BOOLEAN) ((Data32 & B_PSTH_PCR_TRPC_RW) == B_PSTH_PCR_TRPC_RW);
+ //
+ // StartAddress and EndAddress will be equal if it's byte access
+ //
+ EndAddress = (UINT16) (HighBitSet32 ((UINT32) (ActiveHighByteEnable))) + BaseAddress;
+ StartAddress = (UINT16) (LowBitSet32 ((UINT32) (ActiveHighByteEnable))) + BaseAddress;
+
+ CurrentIoTrapRegisterData.Type = (EFI_SMM_IO_TRAP_DISPATCH_TYPE)ReadCycle;
+ CurrentIoTrapContextData.WriteData = WriteData;
+
+ LinkInDb = GetFirstNode (&(mIoTrapData.Entry[TrapHandlerNum].CallbackDataBase));
+
+ while (!IsNull (&(mIoTrapData.Entry[TrapHandlerNum].CallbackDataBase), LinkInDb)) {
+ RecordInDb = IO_TRAP_RECORD_FROM_LINK (LinkInDb);
+
+ //
+ // If MergeDisable is TRUE, no need to check the address range, dispatch the callback function directly.
+ //
+ if (mIoTrapData.Entry[TrapHandlerNum].MergeDisable) {
+ if (RecordInDb->IoTrapCallback != NULL) {
+ RecordInDb->IoTrapCallback (&RecordInDb->Link, &CurrentIoTrapContextData, NULL, NULL);
+ }
+ if (RecordInDb->IoTrapExCallback != NULL) {
+ RecordInDb->IoTrapExCallback (BaseAddress, ActiveHighByteEnable, !ReadCycle, WriteData);
+ }
+ //
+ // Expect only one callback available. So break immediately.
+ //
+ break;
+ //
+ // If MergeDisable is FALSE, check the address range and trap type.
+ //
+ } else {
+ if ((RecordInDb->Context.Address <= StartAddress) &&
+ (RecordInDb->Context.Address + RecordInDb->Context.Length > EndAddress)) {
+ if ((RecordInDb->Context.Type == IoTrapExTypeReadWrite) || (RecordInDb->Context.Type == (IO_TRAP_EX_DISPATCH_TYPE) CurrentIoTrapRegisterData.Type)) {
+ //
+ // Pass the IO trap context information
+ //
+ RecordInDb->IoTrapCallback (&RecordInDb->Link, &CurrentIoTrapContextData, NULL, NULL);
+ }
+ //
+ // Break if the address is match
+ //
+ break;
+ } else {
+ LinkInDb = GetNextNode (&(mIoTrapData.Entry[TrapHandlerNum].CallbackDataBase), &RecordInDb->Link);
+ if (IsNull (&(mIoTrapData.Entry[TrapHandlerNum].CallbackDataBase), LinkInDb)) {
+ //
+ // An IO access was trapped that does not have a handler registered.
+ // This indicates an error condition.
+ //
+ ASSERT (FALSE);
+ }
+ }
+ } // end of if else block
+ } // end of while loop
+ } // end of if else block
+}
+
+/**
+ IoTrap dispatcher for IoTrap register 0.
+
+ @param[in] DispatchHandle Handle of dispatch function
+**/
+VOID
+EFIAPI
+IoTrapDispatcher0 (
+ IN EFI_HANDLE DispatchHandle
+ )
+{
+ IoTrapDispatcherHelper (0);
+}
+
+/**
+ IoTrap dispatcher for IoTrap register 1.
+
+ @param[in] DispatchHandle Handle of dispatch function
+**/
+VOID
+EFIAPI
+IoTrapDispatcher1 (
+ IN EFI_HANDLE DispatchHandle
+ )
+{
+ IoTrapDispatcherHelper (1);
+}
+
+/**
+ IoTrap dispatcher for IoTrap register 2.
+
+ @param[in] DispatchHandle Handle of dispatch function
+**/
+VOID
+EFIAPI
+IoTrapDispatcher2 (
+ IN EFI_HANDLE DispatchHandle
+ )
+{
+ IoTrapDispatcherHelper (2);
+}
+
+/**
+ IoTrap dispatcher for IoTrap register 3.
+
+ @param[in] DispatchHandle Handle of dispatch function
+**/
+VOID
+EFIAPI
+IoTrapDispatcher3 (
+ IN EFI_HANDLE DispatchHandle
+ )
+{
+ IoTrapDispatcherHelper (3);
+}
+
+/**
+ IoTrap registratrion helper fucntion.
+
+ @param[in] DispatchHandle Handle of dispatch function
+ @param[in] IoTrapDispatchFunction Dispatch function of IoTrapDispatch2Protocol.
+ This could be NULL if it's not from IoTrapDispatch2Protocol.
+ @param[in] IoTrapExDispatchFunction Dispatch function of IoTrapExDispatchProtocol.
+ This could be NULL if it's not from IoTrapExDispatchProtocol.
+ @param[in out] Address The pointer of IO Address.
+ If the input Addres is 0, it will return the address assigned
+ by registration to this caller.
+ @param[in] Length Length of IO address range.
+ @param[in] Type Read/Write type of IO trap.
+ @param[in] ByteEnable Bitmap to enable trap for each byte of every dword alignment address.
+ @param[in] ByteEnableMask ByteEnableMask bitwise to ignore the ByteEnable setting.
+
+ @retval EFI_INVALID_PARAMETER If Type is invalid,
+ If Length is invalid,
+ If Address is invalid,
+ EFI_ACCESS_DENIED If the SmmReadyToLock event has been triggered,
+ EFI_OUT_OF_RESOURCES If run out of IoTrap register resource,
+ If run out of SMM memory pool,
+ EFI_SUCCESS IoTrap register successfully.
+**/
+EFI_STATUS
+IoTrapRegisterHelper (
+ OUT EFI_HANDLE *DispatchHandle,
+ IN EFI_SMM_HANDLER_ENTRY_POINT2 IoTrapDispatchFunction,
+ IN IO_TRAP_EX_DISPATCH_CALLBACK IoTrapExDispatchFunction,
+ IN OUT UINT16 *Address,
+ IN UINT16 Length,
+ IN IO_TRAP_EX_DISPATCH_TYPE Type,
+ IN UINT8 ByteEnable,
+ IN UINT8 ByteEnableMask
+ )
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+ UINT32 UsedLength;
+ UINT8 TrapHandlerNum;
+ UINT32 IoTrapRegLowDword;
+ UINT32 IoTrapRegHighDword;
+ BOOLEAN TempMergeDisable;
+
+ DEBUG ((DEBUG_INFO, "IoTrapRegisterHelper\n"));
+ DEBUG ((DEBUG_INFO, "Address:%x \n", *Address));
+ DEBUG ((DEBUG_INFO, "Length:%x \n", Length));
+ DEBUG ((DEBUG_INFO, "Type:%x \n", Type));
+ DEBUG ((DEBUG_INFO, "ByteEnable:%x \n", ByteEnable));
+ DEBUG ((DEBUG_INFO, "ByteEnableMask:%x \n", ByteEnableMask));
+
+ //
+ // Return error if the type is invalid
+ //
+ if (Type >= IoTrapExTypeMaximum) {
+ DEBUG ((DEBUG_ERROR, "The Dispatch Type %0X is invalid! \n", Type));
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Return error if the Length is invalid
+ //
+ if (Length < 1 || Length > GENERIC_IOTRAP_SIZE) {
+ DEBUG ((DEBUG_ERROR, "The Dispatch Length %0X is invalid! \n", Length));
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Return error if the address is invalid
+ // PCH supports non-aligned address but (Address % 4 + Length) must not be more than 4
+ //
+ if (((Length & (Length - 1)) != 0) && (Length != 3)) {
+ DEBUG ((DEBUG_ERROR, "The Dispatch Length is not power of 2 \n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (((Length >= 4) && (*Address & 0x3)) ||
+ ((Length < 4) && (((*Address & 0x3) + Length) > 4))) {
+ DEBUG ((DEBUG_ERROR, "PCH does not support Dispatch Address %0X and Length %0X combination \n", *Address, Length));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((Length >= 4) && ((*Address & (Length - 1)) != 0)) {
+ DEBUG ((DEBUG_ERROR, "Dispatch Address %0X is not aligned to the Length %0X \n", *Address, Length));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ if (*Address) {
+ TempMergeDisable = TRUE;
+ }else {
+ TempMergeDisable = FALSE;
+ }
+ //
+ // Loop through the first IO Trap handler, looking for the suitable handler
+ //
+ for (TrapHandlerNum = 0; TrapHandlerNum < IO_TRAP_HANDLER_NUM; TrapHandlerNum++) {
+ //
+ // Get information from Io Trap handler register
+ //
+ IoTrapRegLowDword = PchPcrRead32 (PID_PSTH, R_PSTH_PCR_TRPREG0 + TrapHandlerNum * 8);
+
+ //
+ // Check if the IO Trap handler is not used
+ //
+ if (AddressFromLowDword (IoTrapRegLowDword) == 0) {
+ //
+ // Search available IO address and allocate it if the IO address is 0
+ //
+ BaseAddress = *Address;
+ if (BaseAddress == 0) {
+ //
+ // Allocate 256 byte range from GCD for common pool usage
+ //
+ if ((PcdGet8 (PcdEfiGcdAllocateType) == EfiGcdAllocateMaxAddressSearchBottomUp) || (PcdGet8 (PcdEfiGcdAllocateType) == EfiGcdAllocateMaxAddressSearchTopDown)) {
+ BaseAddress = 0xFFFF;
+ }
+ Status = gDS->AllocateIoSpace (
+ PcdGet8 (PcdEfiGcdAllocateType),
+ EfiGcdIoTypeIo,
+ 8,
+ GENERIC_IOTRAP_SIZE,
+ &BaseAddress,
+ mDriverImageHandle,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Can't find any available IO address! \n"));
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ *Address = (UINT16) BaseAddress;
+ UsedLength = GENERIC_IOTRAP_SIZE;
+ mIoTrapData.Entry[TrapHandlerNum].TrapUsedLength = Length;
+ mIoTrapData.Entry[TrapHandlerNum].ReservedAcpiIoResource = TRUE;
+ UpdateIoTrapAcpiResources (TrapHandlerNum, BaseAddress, TRUE);
+ } else {
+ BaseAddress &= B_PSTH_PCR_TRPREG_AD;
+ UsedLength = Length;
+ }
+
+ Status = PchInternalIoTrapSmiRegister (
+ mIoTrapData.Entry[TrapHandlerNum].CallbackDispatcher,
+ TrapHandlerNum,
+ &mIoTrapHandle
+ );
+
+ ASSERT_EFI_ERROR (Status);
+ mIoTrapData.Entry[TrapHandlerNum].IoTrapHandle = mIoTrapHandle;
+
+ //
+ // Fill in the Length, address and Enable the IO Trap SMI
+ //
+ IoTrapRegLowDword = (UINT32) (((UsedLength - 1) & ~(BIT1 + BIT0)) << 16) |
+ (UINT16) BaseAddress |
+ B_PSTH_PCR_TRPREG_TSE;
+
+ if (UsedLength < 4) {
+ //
+ // The 4 bits is the Byte Enable Mask bits to indicate which byte that are trapped.
+ // The input ByteEnable and ByteEnableMask are ignored in this case.
+ //
+ IoTrapRegHighDword = (((1 << UsedLength) - 1) << ((*Address & 0x3) + (N_PSTH_PCR_TRPREG_BEM - 32))) |
+ (UINT32) (Type << N_PSTH_PCR_TRPREG_RWIO);
+ } else {
+ //
+ // Fill in the ByteEnable, ByteEnableMask, and Type of Io Trap register
+ //
+ IoTrapRegHighDword = ((ByteEnableMask & 0xF) << (N_PSTH_PCR_TRPREG_BEM - 32)) |
+ ((ByteEnable & 0xF) << (N_PSTH_PCR_TRPREG_BE - 32)) |
+ (UINT32) (Type << N_PSTH_PCR_TRPREG_RWIO);
+ }
+ SetIoTrapHighDword (TrapHandlerNum, IoTrapRegHighDword, TRUE);
+ SetIoTrapLowDword (TrapHandlerNum, IoTrapRegLowDword, TRUE);
+ //
+ // Set MergeDisable flag of the registered IoTrap
+ //
+ mIoTrapData.Entry[TrapHandlerNum].MergeDisable = TempMergeDisable;
+ } else {
+ //
+ // Check next handler if MergeDisable is TRUE or the registered IoTrap if MergeDisable is TRUE
+ // If the Io Trap register is used by IoTrapEx protocol, then the MergeDisable will be FALSE.
+ //
+ if ((TempMergeDisable == TRUE) || (mIoTrapData.Entry[TrapHandlerNum].MergeDisable == TRUE)) {
+ continue;
+ }
+ //
+ // The IO Trap handler is used, calculate the Length
+ //
+ UsedLength = LengthFromLowDword (IoTrapRegLowDword);
+ BaseAddress = AddressFromLowDword (IoTrapRegLowDword);
+ //
+ // Assign an addfress from common pool if the caller's address is 0
+ //
+ if (*Address == 0) {
+ //
+ // Check next handler if it's fully used
+ //
+ if (mIoTrapData.Entry[TrapHandlerNum].TrapUsedLength >= GENERIC_IOTRAP_SIZE) {
+ continue;
+ }
+ //
+ // Check next handler if it's not for a common pool
+ //
+ if (UsedLength < GENERIC_IOTRAP_SIZE) {
+ continue;
+ }
+ //
+ // Check next handler if the size is too big
+ //
+ if (Length >= (UINT16) GENERIC_IOTRAP_SIZE - mIoTrapData.Entry[TrapHandlerNum].TrapUsedLength) {
+ continue;
+ }
+ //
+ // For common pool, we don't need to change the BaseAddress and UsedLength
+ //
+ *Address = (UINT16) (BaseAddress + mIoTrapData.Entry[TrapHandlerNum].TrapUsedLength);
+ mIoTrapData.Entry[TrapHandlerNum].TrapUsedLength += Length;
+ }
+ //
+ // Only set RWM bit when we need both read and write cycles.
+ //
+ IoTrapRegHighDword = PchPcrRead32 (PID_PSTH, R_PSTH_PCR_TRPREG0 + TrapHandlerNum * 8 + 4);
+ if ((IoTrapRegHighDword & B_PSTH_PCR_TRPREG_RWM) == 0 &&
+ (UINT32) ((IoTrapRegHighDword & B_PSTH_PCR_TRPREG_RWIO) >> N_PSTH_PCR_TRPREG_RWIO) !=
+ (UINT32) Type) {
+ IoTrapRegHighDword = ((IoTrapRegHighDword | B_PSTH_PCR_TRPREG_RWM) & ~B_PSTH_PCR_TRPREG_RWIO);
+ SetIoTrapHighDword (TrapHandlerNum, IoTrapRegHighDword, TRUE);
+ }
+ }
+ break;
+ }
+
+ if (TrapHandlerNum >= IO_TRAP_HANDLER_NUM) {
+ DEBUG ((DEBUG_ERROR, "All IO Trap handler is used, no available IO Trap handler! \n"));
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Create database record and add to database
+ //
+ Status = gSmst->SmmAllocatePool (
+ EfiRuntimeServicesData,
+ sizeof (IO_TRAP_RECORD),
+ (VOID **) &mIoTrapRecord
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed to allocate memory for mIoTrapRecord! \n"));
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Gather information about the registration request
+ //
+ mIoTrapRecord->Signature = IO_TRAP_RECORD_SIGNATURE;
+ mIoTrapRecord->Context.Address = *Address;
+ mIoTrapRecord->Context.Length = Length;
+ mIoTrapRecord->Context.Type = Type;
+ mIoTrapRecord->Context.ByteEnable = ByteEnable;
+ mIoTrapRecord->Context.ByteEnableMask = ByteEnableMask;
+ mIoTrapRecord->IoTrapCallback = IoTrapDispatchFunction;
+ mIoTrapRecord->IoTrapExCallback = IoTrapExDispatchFunction;
+ mIoTrapRecord->IoTrapNumber = TrapHandlerNum;
+
+ InsertTailList (&(mIoTrapData.Entry[TrapHandlerNum].CallbackDataBase), &mIoTrapRecord->Link);
+
+ //
+ // Child's handle will be the address linked list link in the record
+ //
+ *DispatchHandle = (EFI_HANDLE) (&mIoTrapRecord->Link);
+
+ DEBUG ((DEBUG_INFO, "Result Address:%x \n", *Address));
+ DEBUG ((DEBUG_INFO, "Result Length:%x \n", Length));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ IoTrap unregistratrion helper fucntion.
+
+ @param[in] DispatchHandle Handle of dispatch function
+
+ @retval EFI_INVALID_PARAMETER If DispatchHandle is invalid,
+ EFI_ACCESS_DENIED If the SmmReadyToLock event has been triggered,
+ EFI_SUCCESS IoTrap unregister successfully.
+**/
+EFI_STATUS
+IoTrapUnRegisterHelper (
+ IN EFI_HANDLE DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+ IO_TRAP_RECORD *RecordToDelete;
+ UINT32 IoTrapRegLowDword;
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+ UINT32 UsedLength;
+ UINT8 TrapHandlerNum;
+ UINT8 LengthIndex;
+ BOOLEAN RequireToDisableIoTrapHandler;
+
+ if (DispatchHandle == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "UnRegister is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ RecordToDelete = IO_TRAP_RECORD_FROM_LINK (DispatchHandle);
+ //
+ // Take the entry out of the linked list
+ //
+ if (RecordToDelete->Link.ForwardLink == (LIST_ENTRY *) EFI_BAD_POINTER) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ RequireToDisableIoTrapHandler = FALSE;
+ //
+ // Loop through the first IO Trap handler, looking for the suitable handler
+ //
+ TrapHandlerNum = RecordToDelete->IoTrapNumber;
+
+ if (mIoTrapData.Entry[TrapHandlerNum].MergeDisable) {
+ //
+ // Disable the IO Trap handler if it's the only child of the Trap handler
+ //
+ RequireToDisableIoTrapHandler = TRUE;
+ } else {
+ //
+ // Get information from Io Trap handler register
+ //
+ IoTrapRegLowDword = PchPcrRead32 (PID_PSTH, R_PSTH_PCR_TRPREG0 + TrapHandlerNum * 8);
+
+ //
+ // Check next Io Trap handler if the IO Trap handler is not used
+ //
+ if (AddressFromLowDword (IoTrapRegLowDword) != 0) {
+
+ UsedLength = LengthFromLowDword (IoTrapRegLowDword);
+ BaseAddress = AddressFromLowDword (IoTrapRegLowDword);
+
+ //
+ // Check if it's the maximum address of the Io Trap handler
+ //
+ if ((UINTN)(BaseAddress + UsedLength) == (UINTN)(RecordToDelete->Context.Address + RecordToDelete->Context.Length)) {
+
+ if (BaseAddress == RecordToDelete->Context.Address) {
+ //
+ // Disable the IO Trap handler if it's the only child of the Trap handler
+ //
+ RequireToDisableIoTrapHandler = TRUE;
+ } else {
+ //
+ // Calculate the new IO Trap handler Length
+ //
+ UsedLength = UsedLength - RecordToDelete->Context.Length;
+ //
+ // Check the alignment is dword * power of 2 or not
+ //
+ for (LengthIndex = 0; LengthIndex < sizeof (mLengthTable) / sizeof (UINT16); LengthIndex++) {
+ if (UsedLength == mLengthTable[LengthIndex]) {
+ break;
+ }
+ }
+ //
+ // Do not decrease the length if the alignment is not dword * power of 2
+ //
+ if (LengthIndex < sizeof (mLengthTable) / sizeof (UINT16)) {
+ //
+ // Decrease the length to prevent the IO trap SMI
+ //
+ IoTrapRegLowDword = (UINT32) ((((UsedLength - 1) &~(BIT1 + BIT0)) << 16) | BaseAddress | B_PSTH_PCR_TRPREG_TSE);
+ }
+ SetIoTrapLowDword (TrapHandlerNum, IoTrapRegLowDword, TRUE);
+ }
+ }
+ }
+ }
+
+ if (RequireToDisableIoTrapHandler) {
+ mIoTrapHandle = mIoTrapData.Entry[TrapHandlerNum].IoTrapHandle;
+ Status = PchInternalIoTrapSmiUnRegister (mIoTrapHandle);
+ ASSERT_EFI_ERROR (Status);
+
+ SetIoTrapLowDword (TrapHandlerNum, 0, TRUE);
+ SetIoTrapHighDword (TrapHandlerNum, 0, TRUE);
+ //
+ // Also clear pending IOTRAP status.
+ //
+ ClearPendingIoTrapStatus (TrapHandlerNum);
+
+ mIoTrapData.Entry[TrapHandlerNum].IoTrapHandle = 0;
+ mIoTrapData.Entry[TrapHandlerNum].MergeDisable = FALSE;
+ if (mIoTrapData.Entry[TrapHandlerNum].ReservedAcpiIoResource == TRUE) {
+ mIoTrapData.Entry[TrapHandlerNum].ReservedAcpiIoResource = FALSE;
+ UpdateIoTrapAcpiResources (TrapHandlerNum, 0, FALSE);
+ }
+ }
+
+ RemoveEntryList (&RecordToDelete->Link);
+ Status = gSmst->SmmFreePool (RecordToDelete);
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Register a new IO Trap SMI dispatch function with a parent SMM driver.
+ The caller will provide information about the IO trap characteristics via
+ the context. This includes base address, length, read vs. r/w, etc.
+ This function will autoallocate IO base address from a common pool if the base address is 0,
+ and the RegisterContext Address field will be updated.
+ The service will not perform GCD allocation if the base address is non-zero.
+ In this case, the caller is responsible for the existence and allocation of the
+ specific IO range.
+ This function looks for the suitable handler and Register a new IoTrap handler
+ if the IO Trap handler is not used. It also enable the IO Trap Range to generate
+ SMI.
+
+ @param[in] This Pointer to the EFI_SMM_IO_TRAP_DISPATCH2_PROTOCOL instance.
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for
+ this SMI source.
+ @param[in, out] RegisterContext Pointer to the dispatch function's context.
+ The caller fills this context in before calling
+ the register function to indicate to the register
+ function the IO trap SMI source for which the dispatch
+ function should be invoked. This may not be NULL.
+ If the registration address is not 0, it's caller's responsibility
+ to reserve the IO resource in ACPI.
+ @param[out] DispatchHandle Handle of dispatch function, for when interfacing
+ with the parent SMM driver, will be the address of linked
+ list link in the call back record. This may not be NULL.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ registered and the SMI source has been enabled.
+ @retval EFI_DEVICE_ERROR The driver was unable to enable the SMI source.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources are available
+ @retval EFI_INVALID_PARAMETER Address requested is already in use.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+IoTrapRegister (
+ IN CONST EFI_SMM_IO_TRAP_DISPATCH2_PROTOCOL *This,
+ IN EFI_SMM_HANDLER_ENTRY_POINT2 DispatchFunction,
+ IN OUT EFI_SMM_IO_TRAP_REGISTER_CONTEXT *RegisterContext,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+
+ DEBUG ((DEBUG_INFO, "IoTrapRegister\n"));
+ Status = IoTrapRegisterHelper (
+ DispatchHandle,
+ DispatchFunction,
+ NULL,
+ &(RegisterContext->Address),
+ RegisterContext->Length,
+ (IO_TRAP_EX_DISPATCH_TYPE) RegisterContext->Type,
+ 0x00,
+ 0x0F);
+
+ if (!EFI_ERROR (Status)) {
+ SmiHandlerProfileRegisterHandler (
+ &gEfiSmmIoTrapDispatch2ProtocolGuid,
+ DispatchFunction,
+ (UINTN)RETURN_ADDRESS (0),
+ RegisterContext,
+ sizeof (EFI_SMM_IO_TRAP_REGISTER_CONTEXT)
+ );
+ }
+ return Status;
+}
+
+/**
+ Unregister a child SMI source dispatch function with a parent SMM driver.
+
+ @param[in] This Pointer to the EFI_SMM_IO_TRAP_DISPATCH2_PROTOCOL instance.
+ @param[in] DispatchHandle Handle of dispatch function to deregister.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ unregistered and the SMI source has been disabled
+ if there are no other registered child dispatch
+ functions for this SMI source.
+ @retval EFI_INVALID_PARAMETER Handle is invalid.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+IoTrapUnRegister (
+ IN CONST EFI_SMM_IO_TRAP_DISPATCH2_PROTOCOL *This,
+ IN EFI_HANDLE DispatchHandle
+ )
+{
+ IO_TRAP_RECORD *RecordToDelete;
+
+ RecordToDelete = IO_TRAP_RECORD_FROM_LINK (DispatchHandle);
+ SmiHandlerProfileUnregisterHandler (
+ &gIoTrapExDispatchProtocolGuid,
+ RecordToDelete->IoTrapCallback,
+ &RecordToDelete->Context,
+ sizeof (EFI_SMM_IO_TRAP_REGISTER_CONTEXT)
+ );
+ return IoTrapUnRegisterHelper (DispatchHandle);
+}
+
+/**
+ Register a new IO Trap Ex SMI dispatch function.
+
+ @param[in] This Pointer to the IO_TRAP_EX_DISPATCH_PROTOCOL instance.
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for
+ this SMI source.
+ @param[in] RegisterContext Pointer to the dispatch function's context.
+ The caller fills this context in before calling
+ the register function to indicate to the register
+ function the IO trap Ex SMI source for which the dispatch
+ function should be invoked. This MUST not be NULL.
+ @param[out] DispatchHandle Handle of dispatch function.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ registered and the SMI source has been enabled.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources are available
+ @retval EFI_INVALID_PARAMETER Address requested is already in use.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+IoTrapExRegister (
+ IN IO_TRAP_EX_DISPATCH_PROTOCOL *This,
+ IN IO_TRAP_EX_DISPATCH_CALLBACK DispatchFunction,
+ IN IO_TRAP_EX_REGISTER_CONTEXT *RegisterContext,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+
+ DEBUG ((DEBUG_INFO, "PchSmmIoTrapExRegister\n"));
+ //
+ // Return error if length is less than 4 and not power of 2.
+ //
+ if ((RegisterContext->Length < 4) || ((RegisterContext->Length & (RegisterContext->Length - 1)) != 0)) {
+ DEBUG ((DEBUG_ERROR, "The Dispatch Length is not power of 2 \n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = IoTrapRegisterHelper (
+ DispatchHandle,
+ NULL,
+ DispatchFunction,
+ &(RegisterContext->Address),
+ RegisterContext->Length,
+ RegisterContext->Type,
+ RegisterContext->ByteEnable,
+ RegisterContext->ByteEnableMask);
+
+ if (!EFI_ERROR (Status)) {
+ SmiHandlerProfileRegisterHandler (
+ &gIoTrapExDispatchProtocolGuid,
+ (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction,
+ (UINTN)RETURN_ADDRESS (0),
+ RegisterContext,
+ sizeof (*RegisterContext)
+ );
+ }
+ return Status;
+}
+
+/**
+ Unregister a SMI source dispatch function.
+ This function is unsupported.
+
+ @param[in] This Pointer to the IO_TRAP_EX_DISPATCH_PROTOCOL instance.
+ @param[in] DispatchHandle Handle of dispatch function to deregister.
+
+ @retval EFI_UNSUPPORTED The function is unsupported.
+**/
+EFI_STATUS
+EFIAPI
+IoTrapExUnRegister (
+ IN IO_TRAP_EX_DISPATCH_PROTOCOL *This,
+ IN EFI_HANDLE DispatchHandle
+ )
+{
+ IO_TRAP_RECORD *RecordToDelete;
+
+ RecordToDelete = IO_TRAP_RECORD_FROM_LINK (DispatchHandle);
+ SmiHandlerProfileUnregisterHandler (
+ &gIoTrapExDispatchProtocolGuid,
+ RecordToDelete->IoTrapCallback,
+ &RecordToDelete->Context,
+ sizeof (RecordToDelete->Context)
+ );
+ return IoTrapUnRegisterHelper (DispatchHandle);
+}
+
+/**
+ Pause IoTrap callback function.
+
+ This function disables the SMI enable of IoTrap according to the DispatchHandle,
+ which is returned by IoTrap callback registration. It only supports the DispatchHandle
+ with MergeDisable TRUE and address not zero.
+
+ NOTE: This call does not guarantee all pending IO cycles to be synchronized
+ and pending IO cycles issued before this call might not be trapped.
+
+ @param[in] This Pointer to the PCH_SMM_IO_TRAP_CONTROL_PROTOCOL instance.
+ @param[in] DispatchHandle Handle of the child service to change state.
+
+ @retval EFI_SUCCESS This operation is complete.
+ @retval EFI_INVALID_PARAMETER The DispatchHandle is invalid.
+ @retval EFI_ACCESS_DENIED The SMI status is alrady PAUSED.
+**/
+EFI_STATUS
+EFIAPI
+IoTrapControlPause (
+ IN PCH_SMM_IO_TRAP_CONTROL_PROTOCOL *This,
+ IN EFI_HANDLE DispatchHandle
+ )
+{
+ IO_TRAP_RECORD *IoTrapRecord;
+ UINT32 IoTrapRegLowDword;
+ UINT32 IoTrapRegHighDword;
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+ UINT32 UsedLength;
+ UINT8 TrapHandlerNum;
+ BOOLEAN TempMergeDisable;
+ BOOLEAN DisableIoTrap;
+
+ if (DispatchHandle == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ IoTrapRecord = IO_TRAP_RECORD_FROM_LINK (DispatchHandle);
+
+ if (IoTrapRecord->Context.Address) {
+ TempMergeDisable =TRUE;
+ }else {
+ TempMergeDisable = FALSE;
+ }
+
+ if ((IoTrapRecord->Signature != IO_TRAP_RECORD_SIGNATURE) ||
+ (TempMergeDisable != TRUE) ||
+ (IoTrapRecord->Context.Address == 0) ||
+ (IoTrapRecord->Context.Length == 0)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ for (TrapHandlerNum = 0; TrapHandlerNum < IO_TRAP_HANDLER_NUM; TrapHandlerNum++) {
+ //
+ // This IoTrap register should be merge disabled.
+ //
+ if (mIoTrapData.Entry[TrapHandlerNum].MergeDisable != TRUE) {
+ continue;
+ }
+ IoTrapRegLowDword = PchPcrRead32 (PID_PSTH, R_PSTH_PCR_TRPREG0 + TrapHandlerNum * 8);
+ IoTrapRegHighDword = PchPcrRead32 (PID_PSTH, R_PSTH_PCR_TRPREG0 + TrapHandlerNum * 8 + 4);
+ //
+ // Depending on the usage, we will obtain the UsedLength and BaseAddress differently
+ // If the registered trap length is less than 4, we obtain the length from Byte Enable Mask
+ // In the other hand, we obtain the length from Address Mask
+ //
+ if (ByteEnableMaskFromHighDword (IoTrapRegHighDword) != 0xF) {
+ UsedLength = (UINT32) (HighBitSet32 (IoTrapRegHighDword & 0xF0) - LowBitSet32 (IoTrapRegHighDword & 0xF0) + 1);
+ BaseAddress = AddressFromLowDword (IoTrapRegLowDword) + LowBitSet32 (ByteEnableMaskFromHighDword (IoTrapRegHighDword));
+ } else {
+ UsedLength = LengthFromLowDword (IoTrapRegLowDword);
+ BaseAddress = AddressFromLowDword (IoTrapRegLowDword);
+ }
+
+ //
+ // The address and length of record matches the IoTrap register's.
+ //
+ DisableIoTrap = FALSE;
+ if ((IoTrapRecord->IoTrapExCallback != NULL) &&
+ IsIoTrapExContentMatched (IoTrapRecord, IoTrapRegLowDword, IoTrapRegHighDword)) {
+ DisableIoTrap = TRUE;
+ } else if ((BaseAddress == IoTrapRecord->Context.Address) &&
+ (UsedLength == IoTrapRecord->Context.Length )) {
+ DisableIoTrap = TRUE;
+ }
+
+ if (DisableIoTrap) {
+ //
+ // Check if status matched.
+ // If this is already Paused, return warning status.
+ //
+ if ((IoTrapRegLowDword & B_PSTH_PCR_TRPREG_TSE) == 0) {
+ return EFI_ACCESS_DENIED;
+ }
+ //
+ // Clear IoTrap register SMI enable bit
+ //
+ IoTrapRegLowDword &= (~B_PSTH_PCR_TRPREG_TSE);
+ SetIoTrapLowDword (TrapHandlerNum, IoTrapRegLowDword, FALSE);
+ //
+ // Also clear pending IOTRAP status.
+ //
+ ClearPendingIoTrapStatus (TrapHandlerNum);
+ return EFI_SUCCESS;
+ }
+ }
+ return EFI_INVALID_PARAMETER;
+}
+
+/**
+ Resume IoTrap callback function.
+
+ This function enables the SMI enable of IoTrap according to the DispatchHandle,
+ which is returned by IoTrap callback registration. It only supports the DispatchHandle
+ with MergeDisable TRUE and address not zero.
+
+ @param[in] This Pointer to the PCH_SMM_IO_TRAP_CONTROL_PROTOCOL instance.
+ @param[in] DispatchHandle Handle of the child service to change state.
+
+ @retval EFI_SUCCESS This operation is complete.
+ @retval EFI_INVALID_PARAMETER The DispatchHandle is invalid.
+ @retval EFI_ACCESS_DENIED The SMI status is alrady RESUMED.
+**/
+EFI_STATUS
+EFIAPI
+IoTrapControlResume (
+ IN PCH_SMM_IO_TRAP_CONTROL_PROTOCOL *This,
+ IN EFI_HANDLE DispatchHandle
+ )
+{
+ IO_TRAP_RECORD *IoTrapRecord;
+ UINT32 IoTrapRegLowDword;
+ UINT32 IoTrapRegHighDword;
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+ UINT32 UsedLength;
+ UINT8 TrapHandlerNum;
+ BOOLEAN TempMergeDisable;
+ BOOLEAN EnableIoTrap;
+
+ if (DispatchHandle == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+ IoTrapRecord = IO_TRAP_RECORD_FROM_LINK (DispatchHandle);
+
+ if (IoTrapRecord->Context.Address) {
+ TempMergeDisable = TRUE;
+ }else {
+ TempMergeDisable = FALSE;
+ }
+
+ if ((IoTrapRecord->Signature != IO_TRAP_RECORD_SIGNATURE) ||
+ (TempMergeDisable != TRUE) ||
+ (IoTrapRecord->Context.Address == 0) ||
+ (IoTrapRecord->Context.Length == 0)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ for (TrapHandlerNum = 0; TrapHandlerNum < IO_TRAP_HANDLER_NUM; TrapHandlerNum++) {
+ //
+ // This IoTrap register should be merge disabled.
+ //
+ if (mIoTrapData.Entry[TrapHandlerNum].MergeDisable != TRUE) {
+ continue;
+ }
+ IoTrapRegLowDword = PchPcrRead32 (PID_PSTH, R_PSTH_PCR_TRPREG0 + TrapHandlerNum * 8);
+ IoTrapRegHighDword = PchPcrRead32 (PID_PSTH, R_PSTH_PCR_TRPREG0 + TrapHandlerNum * 8 + 4);
+ //
+ // Depending on the usage, we will obtain the UsedLength and BaseAddress differently
+ // If the registered trap length is less than 4, we obtain the length from Byte Enable Mask
+ // In the other hand, we obtain the length from Address Mask
+ //
+ if (ByteEnableMaskFromHighDword (IoTrapRegHighDword) != 0xF) {
+ UsedLength = (UINT32) (HighBitSet32 (IoTrapRegHighDword & 0xF0) - LowBitSet32 (IoTrapRegHighDword & 0xF0) + 1);
+ BaseAddress = AddressFromLowDword (IoTrapRegLowDword) + LowBitSet32 (ByteEnableMaskFromHighDword (IoTrapRegHighDword));
+ } else {
+ UsedLength = LengthFromLowDword (IoTrapRegLowDword);
+ BaseAddress = AddressFromLowDword (IoTrapRegLowDword);
+ }
+
+ //
+ // The address and length of record matches the IoTrap register's.
+ //
+ EnableIoTrap = FALSE;
+ if ((IoTrapRecord->IoTrapExCallback != NULL) &&
+ IsIoTrapExContentMatched (IoTrapRecord, IoTrapRegLowDword, IoTrapRegHighDword)) {
+ EnableIoTrap = TRUE;
+ } else if ((BaseAddress == IoTrapRecord->Context.Address) &&
+ (UsedLength == IoTrapRecord->Context.Length )) {
+ EnableIoTrap = TRUE;
+ }
+
+ if (EnableIoTrap) {
+ //
+ // Check if status matched.
+ // If this is already Resume, return warning status.
+ //
+ if ((IoTrapRegLowDword & B_PSTH_PCR_TRPREG_TSE) != 0) {
+ return EFI_ACCESS_DENIED;
+ }
+ //
+ // Set IoTrap register SMI enable bit
+ //
+ IoTrapRegLowDword |= (B_PSTH_PCR_TRPREG_TSE);
+ SetIoTrapLowDword (TrapHandlerNum, IoTrapRegLowDword, FALSE);
+ return EFI_SUCCESS;
+ }
+ }
+ return EFI_INVALID_PARAMETER;
+}
+
+/**
+ The IoTrap module abstracts PCH I/O trapping capabilities for other drivers.
+ This driver manages the limited I/O trap resources.
+
+ @param[in] ImageHandle Image handle for this driver image
+
+ @retval EFI_SUCCESS Driver initialization completed successfully
+**/
+EFI_STATUS
+EFIAPI
+InstallIoTrap (
+ IN EFI_HANDLE ImageHandle
+ )
+{
+ EFI_STATUS Status;
+ PCH_NVS_AREA_PROTOCOL *PchNvsAreaProtocol;
+ UINTN TrapHandlerNum;
+
+ //
+ // Initialize the EFI SMM driver library
+ //
+ mDriverImageHandle = ImageHandle;
+
+ //
+ // Initialize the IO TRAP protocol we produce
+ //
+ mIoTrapData.Signature = IO_TRAP_INSTANCE_SIGNATURE;
+ mIoTrapData.EfiSmmIoTrapDispatchProtocol.Register = IoTrapRegister;
+ mIoTrapData.EfiSmmIoTrapDispatchProtocol.UnRegister = IoTrapUnRegister;
+
+ //
+ // Initialize the IO TRAP EX protocol
+ //
+ mIoTrapData.IoTrapExDispatchProtocol.Register = IoTrapExRegister;
+ mIoTrapData.IoTrapExDispatchProtocol.UnRegister = IoTrapExUnRegister;
+
+ //
+ // Initialize the IO TRAP control protocol.
+ //
+ mIoTrapData.PchSmmIoTrapControlProtocol.Pause = IoTrapControlPause;
+ mIoTrapData.PchSmmIoTrapControlProtocol.Resume = IoTrapControlResume;
+
+ for (TrapHandlerNum = 0; TrapHandlerNum < IO_TRAP_HANDLER_NUM; TrapHandlerNum++) {
+ //
+ // Initialize IO TRAP Callback DataBase
+ //
+ InitializeListHead (&(mIoTrapData.Entry[TrapHandlerNum].CallbackDataBase));
+ }
+ mIoTrapData.Entry[0].CallbackDispatcher = IoTrapDispatcher0;
+ mIoTrapData.Entry[1].CallbackDispatcher = IoTrapDispatcher1;
+ mIoTrapData.Entry[2].CallbackDispatcher = IoTrapDispatcher2;
+ mIoTrapData.Entry[3].CallbackDispatcher = IoTrapDispatcher3;
+
+ //
+ // Get address of PchNvs structure for later use
+ //
+ Status = gBS->LocateProtocol (&gPchNvsAreaProtocolGuid, NULL, (VOID **) &PchNvsAreaProtocol);
+ ASSERT_EFI_ERROR (Status);
+ mPchNvsArea = PchNvsAreaProtocol->Area;
+
+ //
+ // Install protocol interface
+ //
+ mIoTrapData.Handle = NULL;
+ Status = gSmst->SmmInstallProtocolInterface (
+ &mIoTrapData.Handle,
+ &gEfiSmmIoTrapDispatch2ProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &mIoTrapData.EfiSmmIoTrapDispatchProtocol
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = gSmst->SmmInstallProtocolInterface (
+ &mIoTrapData.Handle,
+ &gIoTrapExDispatchProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &mIoTrapData.IoTrapExDispatchProtocol
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = gSmst->SmmInstallProtocolInterface (
+ &mIoTrapData.Handle,
+ &gPchSmmIoTrapControlGuid,
+ EFI_NATIVE_INTERFACE,
+ &mIoTrapData.PchSmmIoTrapControlProtocol
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/IoTrap.h b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/IoTrap.h
new file mode 100644
index 0000000000..e69d2e2d4d
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/IoTrap.h
@@ -0,0 +1,226 @@
+/** @file
+ Defines and prototypes for the IoTrap SMM driver
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _IO_TRAP_H_
+#define _IO_TRAP_H_
+
+//
+// Include files
+//
+#include <Library/S3BootScriptLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Protocol/SmmIoTrapDispatch2.h>
+#include <Protocol/PchSmmIoTrapControl.h>
+#include <Protocol/IoTrapExDispatch.h>
+
+#define IO_TRAP_HANDLER_NUM 4
+
+//
+// Driver private data
+//
+#define IO_TRAP_INSTANCE_SIGNATURE SIGNATURE_32 ('I', 'O', 'T', 'P')
+
+typedef struct {
+ EFI_HANDLE IoTrapHandle;
+ /**
+ The callback linked list for all "merged" IoTrap callbacks.
+ **/
+ LIST_ENTRY CallbackDataBase;
+ /**
+ The IoTrap IO range used length tracking for "merged" IoTrap register.
+ **/
+ UINT32 TrapUsedLength;
+ /**
+ Determine if IoTrap can be merged with other IoTrap callbacks.
+ If MergeDisable is TRUE, then there is only one callback function for one IoTrap register.
+ If MergeDisable is FALSE, then there are multiple callbacks in the "CallbackDataBase" for one IoTrap register.
+ **/
+ BOOLEAN MergeDisable;
+ /**
+ Indicator of the resource tracking in ACPI.
+ If the registration address is not 0, it's caller's responsibility to reserve the IO resource in ACPI.
+ **/
+ BOOLEAN ReservedAcpiIoResource;
+ /**
+ Dispatcher for each IoTrap register.
+ **/
+ PCH_SMI_DISPATCH_CALLBACK CallbackDispatcher;
+} IO_TRAP_ENTRY_ATTRIBUTES;
+
+typedef struct {
+ UINT32 Signature;
+ EFI_HANDLE Handle;
+ EFI_SMM_IO_TRAP_DISPATCH2_PROTOCOL EfiSmmIoTrapDispatchProtocol;
+ PCH_SMM_IO_TRAP_CONTROL_PROTOCOL PchSmmIoTrapControlProtocol; ///< Protocol for runtime control the IoTrap state
+ IO_TRAP_EX_DISPATCH_PROTOCOL IoTrapExDispatchProtocol; ///< Protocol for IoTrap Extension
+ IO_TRAP_ENTRY_ATTRIBUTES Entry[IO_TRAP_HANDLER_NUM];
+} IO_TRAP_INSTANCE;
+
+#define IO_TRAP_INSTANCE_FROM_THIS(a) CR (a, IO_TRAP_INSTANCE, EfiSmmIoTrapDispatchProtocol, IO_TRAP_INSTANCE_SIGNATURE)
+
+///
+/// "IOTRAP" RECORD
+/// Linked list data structures
+///
+#define IO_TRAP_RECORD_SIGNATURE SIGNATURE_32 ('I', 'T', 'R', 'C')
+
+typedef struct _IO_TRAP_RECORD {
+ UINT32 Signature;
+ LIST_ENTRY Link;
+ IO_TRAP_EX_REGISTER_CONTEXT Context;
+ /**
+ The callback function of IoTrap protocol.
+ This also indicate it's the record for IoTrapProtocol.
+ Only one of IoTrapCallback or IoTrapExCallback is valid at a time.
+ **/
+ EFI_SMM_HANDLER_ENTRY_POINT2 IoTrapCallback;
+ /**
+ The callback function of IoTrapEx protocol
+ This also indicate it's the record for IoTrapExProtocol.
+ Only one of IoTrapCallback or IoTrapExCallback is valid at a time.
+ **/
+ IO_TRAP_EX_DISPATCH_CALLBACK IoTrapExCallback;
+ UINT8 IoTrapNumber;
+} IO_TRAP_RECORD;
+
+#define IO_TRAP_RECORD_FROM_LINK(_record) CR (_record, IO_TRAP_RECORD, Link, IO_TRAP_RECORD_SIGNATURE)
+
+//
+// Prototypes
+//
+/**
+ The IoTrap module abstracts PCH I/O trapping capabilities for other drivers.
+ This driver manages the limited I/O trap resources.
+
+ @param[in] ImageHandle Image handle for this driver image
+
+ @retval EFI_SUCCESS Driver initialization completed successfully
+**/
+EFI_STATUS
+EFIAPI
+InstallIoTrap (
+ IN EFI_HANDLE ImageHandle
+ );
+
+/**
+ Register a new IO Trap SMI dispatch function with a parent SMM driver.
+ The caller will provide information about the IO trap characteristics via
+ the context. This includes base address, length, read vs. r/w, etc.
+ This function will autoallocate IO base address from a common pool if the base address is 0,
+ and the RegisterContext Address field will be updated.
+ The service will not perform GCD allocation if the base address is non-zero.
+ In this case, the caller is responsible for the existence and allocation of the
+ specific IO range.
+ This function looks for the suitable handler and Register a new IoTrap handler
+ if the IO Trap handler is not used. It also enable the IO Trap Range to generate
+ SMI.
+
+ @param[in] This Pointer to the EFI_SMM_IO_TRAP_DISPATCH2_PROTOCOL instance.
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for
+ this SMI source.
+ @param[in, out] RegisterContext Pointer to the dispatch function's context.
+ The caller fills this context in before calling
+ the register function to indicate to the register
+ function the IO trap SMI source for which the dispatch
+ function should be invoked. This may not be NULL.
+ If the registration address is not 0, it's caller's responsibility
+ to reserve the IO resource in ACPI.
+ @param[out] DispatchHandle Handle of dispatch function, for when interfacing
+ with the parent SMM driver, will be the address of linked
+ list link in the call back record. This may not be NULL.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ registered and the SMI source has been enabled.
+ @retval EFI_DEVICE_ERROR The driver was unable to enable the SMI source.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources are available
+ @retval EFI_INVALID_PARAMETER Address requested is already in use.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+IoTrapRegister (
+ IN CONST EFI_SMM_IO_TRAP_DISPATCH2_PROTOCOL *This,
+ IN EFI_SMM_HANDLER_ENTRY_POINT2 DispatchFunction,
+ IN OUT EFI_SMM_IO_TRAP_REGISTER_CONTEXT *RegisterContext,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+
+/**
+ Unregister a child SMI source dispatch function with a parent SMM driver.
+
+ @param[in] This Pointer to the EFI_SMM_IO_TRAP_DISPATCH2_PROTOCOL instance.
+ @param[in] DispatchHandle Handle of dispatch function to deregister.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ unregistered and the SMI source has been disabled
+ if there are no other registered child dispatch
+ functions for this SMI source.
+ @retval EFI_INVALID_PARAMETER Handle is invalid.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+IoTrapUnRegister (
+ IN CONST EFI_SMM_IO_TRAP_DISPATCH2_PROTOCOL *This,
+ IN EFI_HANDLE DispatchHandle
+ );
+
+/**
+ This I/O Trap SMI handler invokes the ACPI reference code to handle the SMI.
+ It currently assumes it owns all of the IO trap SMI.
+
+ @param[in] DispatchHandle Not used
+
+**/
+VOID
+EFIAPI
+IoTrapCallback (
+ IN EFI_HANDLE DispatchHandle
+ );
+
+/**
+ Pause IoTrap callback function.
+
+ This function disables the SMI enable of IoTrap according to the DispatchHandle,
+ which is returned by IoTrap callback registration. It only supports the DispatchHandle
+ with MergeDisable TRUE and address not zero.
+
+ @param[in] This Pointer to the PCH_SMM_IO_TRAP_CONTROL_PROTOCOL instance.
+ @param[in] DispatchHandle Handle of the child service to change state.
+
+ @retval EFI_SUCCESS This operation is complete.
+ @retval EFI_INVALID_PARAMETER The DispatchHandle is invalid.
+ @retval EFI_ACCESS_DENIED The SMI status is alrady PAUSED.
+**/
+EFI_STATUS
+EFIAPI
+IoTrapControlPause (
+ IN PCH_SMM_IO_TRAP_CONTROL_PROTOCOL * This,
+ IN EFI_HANDLE DispatchHandle
+ );
+
+/**
+ Resume IoTrap callback function.
+
+ This function enables the SMI enable of IoTrap according to the DispatchHandle,
+ which is returned by IoTrap callback registration. It only supports the DispatchHandle
+ with MergeDisable TRUE and address not zero.
+
+ @param[in] This Pointer to the PCH_SMM_IO_TRAP_CONTROL_PROTOCOL instance.
+ @param[in] DispatchHandle Handle of the child service to change state.
+
+ @retval EFI_SUCCESS This operation is complete.
+ @retval EFI_INVALID_PARAMETER The DispatchHandle is invalid.
+ @retval EFI_ACCESS_DENIED The SMI status is alrady RESUMED.
+**/
+EFI_STATUS
+EFIAPI
+IoTrapControlResume (
+ IN PCH_SMM_IO_TRAP_CONTROL_PROTOCOL * This,
+ IN EFI_HANDLE DispatchHandle
+ );
+
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmiDispatch.c b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmiDispatch.c
new file mode 100644
index 0000000000..affbe94eb7
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmiDispatch.c
@@ -0,0 +1,2442 @@
+/** @file
+ This function handle the register/unregister of PCH specific SMI events.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include "PchSmmHelpers.h"
+#include <Library/SmiHandlerProfileLib.h>
+#include <Register/PchRegs.h>
+#include <Register/PchPcrRegs.h>
+#include <Register/PmcRegs.h>
+#include <Register/PchRegsLpc.h>
+#include <Register/SpiRegs.h>
+#include <Register/PchPcieRpRegs.h>
+#include <Register/PchRegsPsth.h>
+#include <Library/PchPciBdfLib.h>
+#include <Library/S3BootScriptLib.h>
+#include <PchBdfAssignment.h>
+#include "PchSmiHelper.h"
+
+/**
+ The internal function used to create and insert a database record
+ for SMI record of Pch Smi types.
+
+ @param[in] SrcDesc The pointer to the SMI source description
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[in] PchSmiType Specific SMI type of PCH SMI
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+**/
+EFI_STATUS
+PchSmiRecordInsert (
+ IN CONST PCH_SMM_SOURCE_DESC *SrcDesc,
+ IN PCH_SMI_CALLBACK_FUNCTIONS DispatchFunction,
+ IN PCH_SMI_TYPES PchSmiType,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+ DATABASE_RECORD Record;
+
+ if (SrcDesc == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ZeroMem (&Record, sizeof (DATABASE_RECORD));
+ //
+ // Gather information about the registration request
+ //
+ Record.Signature = DATABASE_RECORD_SIGNATURE;
+ Record.PchSmiCallback = DispatchFunction;
+ Record.ProtocolType = PchSmiDispatchType;
+ Record.PchSmiType = PchSmiType;
+
+ CopyMem (&Record.SrcDesc, SrcDesc, sizeof (PCH_SMM_SOURCE_DESC));
+ Status = SmmCoreInsertRecord (
+ &Record,
+ DispatchHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
+
+
+//
+// TCO_STS bit that needs to be cleared
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mDescSrcTcoSts = {
+ PCH_SMM_NO_FLAGS,
+ {
+ NULL_BIT_DESC_INITIALIZER,
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_ACPI_IO_SMI_STS}
+ },
+ S_ACPI_IO_SMI_STS,
+ N_ACPI_IO_SMI_STS_TCO
+ }
+ },
+ NULL_BIT_DESC_INITIALIZER
+};
+
+/**
+ Clear the TCO SMI status bit and block after the SMI handling is done
+
+ @param[in] SrcDesc Pointer to the PCH SMI source description table
+
+**/
+VOID
+EFIAPI
+PchTcoSmiClearSourceAndBlock (
+ CONST PCH_SMM_SOURCE_DESC *SrcDesc
+ )
+{
+ PchSmmClearSourceAndBlock (SrcDesc);
+ //
+ // Any TCO-based status bits require special handling.
+ // SMI_STS.TCO_STS must be cleared in addition to the status bit in the TCO registers
+ //
+ PchSmmClearSource (&mDescSrcTcoSts);
+}
+
+/**
+ Clear the TCO SMI status bit after the SMI handling is done
+
+ @param[in] SrcDesc Pointer to the PCH SMI source description table
+
+**/
+VOID
+EFIAPI
+PchTcoSmiClearSource (
+ CONST PCH_SMM_SOURCE_DESC *SrcDesc
+ )
+{
+ PchSmmClearSource (SrcDesc);
+ //
+ // Any TCO-based status bits require special handling.
+ // SMI_STS.TCO_STS must be cleared in addition to the status bit in the TCO registers
+ //
+ PchSmmClearSource (&mDescSrcTcoSts);
+}
+
+/**
+ Initialize Source descriptor structure
+
+ @param[in] SrcDesc Pointer to the PCH SMI source description table
+
+**/
+VOID
+EFIAPI
+NullInitSourceDesc (
+ PCH_SMM_SOURCE_DESC *SrcDesc
+ )
+{
+ ZeroMem (SrcDesc, sizeof (PCH_SMM_SOURCE_DESC));
+ SrcDesc->En[0].Reg.Type = PCH_SMM_ADDR_TYPE_NULL;
+ SrcDesc->En[1].Reg.Type = PCH_SMM_ADDR_TYPE_NULL;
+ SrcDesc->Sts[0].Reg.Type = PCH_SMM_ADDR_TYPE_NULL;
+ SrcDesc->PmcSmiSts.Reg.Type = PCH_SMM_ADDR_TYPE_NULL;
+}
+
+//
+// Mch srcdesc
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescMch = {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_ACPI_IO_SMI_EN}
+ },
+ S_ACPI_IO_SMI_EN,
+ N_ACPI_IO_SMI_EN_TCO
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ TCO_ADDR_TYPE,
+ {R_TCO_IO_TCO1_STS}
+ },
+ S_TCO_IO_TCO1_STS,
+ N_TCO_IO_TCO1_STS_DMISMI
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_ACPI_IO_SMI_STS}
+ },
+ S_ACPI_IO_SMI_STS,
+ N_ACPI_IO_SMI_STS_TCO
+ }
+};
+
+/**
+ The register function used to register SMI handler of MCH event.
+
+ @param[in] This The pointer to the protocol itself
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchTcoSmiMchRegister (
+ IN PCH_TCO_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_TCO_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+ DATABASE_RECORD *Record;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = PchSmiRecordInsert (
+ &mSrcDescMch,
+ (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+ PchTcoSmiMchType,
+ DispatchHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
+ Record->ClearSource = PchTcoSmiClearSource;
+ PchSmmClearSource (&Record->SrcDesc);
+ PchSmmEnableSource (&Record->SrcDesc);
+ SmiHandlerProfileRegisterHandler (&gPchTcoSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
+ }
+ return Status;
+}
+
+//
+// TcoTimeout srcdesc
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescTcoTimeout = {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_ACPI_IO_SMI_EN}
+ },
+ S_ACPI_IO_SMI_EN,
+ N_ACPI_IO_SMI_EN_TCO
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ TCO_ADDR_TYPE,
+ {R_TCO_IO_TCO1_STS}
+ },
+ S_TCO_IO_TCO1_STS,
+ N_TCO_IO_TCO1_STS_TIMEOUT
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_ACPI_IO_SMI_STS}
+ },
+ S_ACPI_IO_SMI_STS,
+ N_ACPI_IO_SMI_STS_TCO
+ }
+};
+
+/**
+ The register function used to register SMI handler of TcoTimeout event.
+
+ @param[in] This The pointer to the protocol itself
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchTcoSmiTcoTimeoutRegister (
+ IN PCH_TCO_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_TCO_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+ DATABASE_RECORD *Record;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = PchSmiRecordInsert (
+ &mSrcDescTcoTimeout,
+ (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+ PchTcoSmiTcoTimeoutType,
+ DispatchHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
+ Record->ClearSource = PchTcoSmiClearSource;
+ PchSmmClearSource (&Record->SrcDesc);
+ PchSmmEnableSource (&Record->SrcDesc);
+ SmiHandlerProfileRegisterHandler (&gPchTcoSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
+ }
+ return Status;
+}
+
+//
+// OsTco srcdesc
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescOsTco = {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_ACPI_IO_SMI_EN}
+ },
+ S_ACPI_IO_SMI_EN,
+ N_ACPI_IO_SMI_EN_TCO
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ TCO_ADDR_TYPE,
+ {R_TCO_IO_TCO1_STS}
+ },
+ S_TCO_IO_TCO1_STS,
+ N_TCO_IO_TCO1_STS_SW_TCO_SMI
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_ACPI_IO_SMI_STS}
+ },
+ S_ACPI_IO_SMI_STS,
+ N_ACPI_IO_SMI_STS_TCO
+ }
+};
+
+/**
+ The register function used to register SMI handler of OS TCO event.
+
+ @param[in] This The pointer to the protocol itself
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchTcoSmiOsTcoRegister (
+ IN PCH_TCO_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_TCO_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+ DATABASE_RECORD *Record;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = PchSmiRecordInsert (
+ &mSrcDescOsTco,
+ (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+ PchTcoSmiOsTcoType,
+ DispatchHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
+ Record->ClearSource = PchTcoSmiClearSource;
+ PchSmmClearSource (&Record->SrcDesc);
+ PchSmmEnableSource (&Record->SrcDesc);
+ SmiHandlerProfileRegisterHandler (&gPchTcoSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
+ }
+ return Status;
+}
+
+//
+// Nmi
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescNmi = {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ TCO_ADDR_TYPE,
+ {R_TCO_IO_TCO1_CNT}
+ },
+ S_TCO_IO_TCO1_CNT,
+ N_TCO_IO_TCO1_CNT_NMI2SMI_EN
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ TCO_ADDR_TYPE,
+ {R_TCO_IO_TCO1_STS}
+ },
+ S_TCO_IO_TCO1_STS,
+ N_TCO_IO_TCO1_STS_NMI2SMI
+ }
+ },
+ //
+ // NOTE: The status of NMI2SMI won't reflect to PMC SMI_STS.
+ // So skip the top level status check and check the TCO1_STS directly.
+ //
+ NULL_BIT_DESC_INITIALIZER
+};
+
+/**
+ The register function used to register SMI handler of NMI event.
+
+ @param[in] This The pointer to the protocol itself
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchTcoSmiNmiRegister (
+ IN PCH_TCO_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_TCO_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+ DATABASE_RECORD *Record;
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = PchSmiRecordInsert (
+ &mSrcDescNmi,
+ (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+ PchTcoSmiNmiType,
+ DispatchHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
+ Record->ClearSource = PchTcoSmiClearSource;
+ PchSmmClearSource (&Record->SrcDesc);
+ PchSmmEnableSource (&Record->SrcDesc);
+ SmiHandlerProfileRegisterHandler (&gPchTcoSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
+ }
+ return Status;
+}
+
+//
+// IntruderDetect srcdesc
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescIntruderDet = {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_ACPI_IO_SMI_EN}
+ },
+ S_ACPI_IO_SMI_EN,
+ N_ACPI_IO_SMI_EN_TCO
+ },
+ {
+ {
+ TCO_ADDR_TYPE,
+ {R_TCO_IO_TCO2_CNT}
+ },
+ S_TCO_IO_TCO2_CNT,
+ N_TCO_IO_TCO2_CNT_INTRD_SEL
+ }
+ },
+ {
+ {
+ {
+ TCO_ADDR_TYPE,
+ {R_TCO_IO_TCO2_STS}
+ },
+ S_TCO_IO_TCO2_STS,
+ N_TCO_IO_TCO2_STS_INTRD_DET
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_ACPI_IO_SMI_STS}
+ },
+ S_ACPI_IO_SMI_STS,
+ N_ACPI_IO_SMI_STS_TCO
+ }
+};
+
+/**
+ The register function used to register SMI handler of Intruder Detect event.
+
+ @param[in] This The pointer to the protocol itself
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchTcoSmiIntruderDetRegister (
+ IN PCH_TCO_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_TCO_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+ DATABASE_RECORD *Record;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = PchSmiRecordInsert (
+ &mSrcDescIntruderDet,
+ (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+ PchTcoSmiIntruderDetectType,
+ DispatchHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
+ Record->ClearSource = PchTcoSmiClearSourceAndBlock;
+ PchSmmClearSource (&Record->SrcDesc);
+ PchSmmEnableSource (&Record->SrcDesc);
+ SmiHandlerProfileRegisterHandler (&gPchTcoSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
+ }
+ return Status;
+}
+
+//
+// SpiBiosWp srcdesc
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescSpiBiosWp = {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_ACPI_IO_SMI_EN}
+ },
+ S_ACPI_IO_SMI_EN,
+ N_ACPI_IO_SMI_EN_TCO
+ },
+ {
+ {
+ PCIE_ADDR_TYPE,
+ { (
+ (DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
+ (PCI_DEVICE_NUMBER_PCH_SPI << 19) |
+ (PCI_FUNCTION_NUMBER_PCH_SPI << 16) |
+ R_SPI_CFG_BC
+ ) }
+ },
+ S_SPI_CFG_BC,
+ N_SPI_CFG_BC_BLE
+ },
+ },
+ {
+ {
+ {
+ PCIE_ADDR_TYPE,
+ { (
+ (DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
+ (PCI_DEVICE_NUMBER_PCH_SPI << 19) |
+ (PCI_FUNCTION_NUMBER_PCH_SPI << 16) |
+ R_SPI_CFG_BC
+ ) }
+ },
+ S_SPI_CFG_BC,
+ N_SPI_CFG_BC_SYNC_SS
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_ACPI_IO_SMI_STS}
+ },
+ S_ACPI_IO_SMI_STS,
+ N_ACPI_IO_SMI_STS_TCO
+ }
+};
+
+/**
+ Special handling for SPI Write Protect
+
+ @param[in] SrcDesc Not used
+**/
+VOID
+EFIAPI
+PchTcoSpiWpClearSource (
+ CONST PCH_SMM_SOURCE_DESC *SrcDesc
+ )
+{
+ UINT64 SpiRegBase;
+ UINT32 BiosControl;
+ UINT32 Timeout;
+
+ SpiRegBase = SpiPciCfgBase ();
+ PciSegmentAndThenOr32 (
+ SpiRegBase + R_SPI_CFG_BC,
+ (UINT32) ~B_SPI_CFG_BC_ASYNC_SS,
+ B_SPI_CFG_BC_SYNC_SS
+ );
+ //
+ // Ensure the SYNC is cleared
+ //
+ Timeout = 1000;
+ do {
+ BiosControl = PciSegmentRead32 (SpiRegBase + R_SPI_CFG_BC);
+ Timeout--;
+ } while ((BiosControl & B_SPI_CFG_BC_SYNC_SS) && (Timeout > 0));
+
+ //
+ // Any TCO-based status bits require special handling.
+ // SMI_STS.TCO_STS must be cleared in addition to the status bit in the TCO registers
+ //
+ PchSmmClearSource (&mDescSrcTcoSts);
+}
+
+/**
+ Set SMI_EN_TCO to enable TCO SMI.
+**/
+STATIC
+VOID
+PchSetSmiEnTco (
+ VOID
+ )
+{
+ IoOr32 (mAcpiBaseAddr + R_ACPI_IO_SMI_EN, B_ACPI_IO_SMI_EN_TCO);
+}
+
+/**
+ The register function used to register SMI handler of BIOS write protect event.
+
+ @param[in] This The pointer to the protocol itself
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchTcoSmiSpiBiosWpRegister (
+ IN PCH_TCO_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_TCO_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+ DATABASE_RECORD *Record;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = PchSmiRecordInsert (
+ &mSrcDescSpiBiosWp,
+ (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+ PchTcoSmiSpiBiosWpType,
+ DispatchHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
+ Record->ClearSource = PchTcoSpiWpClearSource;
+ PchTcoSpiWpClearSource (NULL);
+ //
+ // It doesn't enable the BIOSLOCK here. Enable it by policy in DXE.
+ // Only enable SMI_EN_TCO.
+ //
+ PchSetSmiEnTco ();
+ SmiHandlerProfileRegisterHandler (&gPchTcoSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
+ }
+ return Status;
+}
+
+//
+// LpcBiosWp srcdesc
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescLpcBiosWp = {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_ACPI_IO_SMI_EN}
+ },
+ S_ACPI_IO_SMI_EN,
+ N_ACPI_IO_SMI_EN_TCO
+ },
+ {
+ {
+ PCIE_ADDR_TYPE,
+ { (
+ (DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
+ (PCI_DEVICE_NUMBER_PCH_LPC << 19) |
+ (PCI_FUNCTION_NUMBER_PCH_LPC << 16) |
+ R_LPC_CFG_BC
+ ) }
+ },
+ S_LPC_CFG_BC,
+ N_LPC_CFG_BC_LE
+ }
+ },
+ {
+ {
+ {
+ TCO_ADDR_TYPE,
+ {R_TCO_IO_TCO1_STS}
+ },
+ S_TCO_IO_TCO1_STS,
+ N_TCO_IO_TCO1_STS_BIOSWR
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_ACPI_IO_SMI_STS}
+ },
+ S_ACPI_IO_SMI_STS,
+ N_ACPI_IO_SMI_STS_TCO
+ }
+};
+
+/**
+ The register function used to register SMI handler of LPC BIOS write protect event.
+
+ @param[in] This The pointer to the protocol itself
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchTcoSmiLpcBiosWpRegister (
+ IN PCH_TCO_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_TCO_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+ DATABASE_RECORD *Record;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ if (IsEspiEnabled ()) {
+ //
+ // Status is D31F0's PCBC.BWPDS
+ //
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ Status = PchSmiRecordInsert (
+ &mSrcDescLpcBiosWp,
+ (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+ PchTcoSmiLpcBiosWpType,
+ DispatchHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
+ Record->ClearSource = PchTcoSmiClearSource;
+ PchSmmClearSource (&Record->SrcDesc);
+ //
+ // It doesn't enable the BIOSLOCK here. Enable it by policy in DXE.
+ // Only enable SMI_EN_TCO.
+ //
+ PchSetSmiEnTco ();
+ SmiHandlerProfileRegisterHandler (&gPchTcoSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
+ }
+ return Status;
+}
+
+//
+// NEWCENTURY_STS bit that needs to be cleared
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescNewCentury = {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_ACPI_IO_SMI_EN}
+ },
+ S_ACPI_IO_SMI_EN,
+ N_ACPI_IO_SMI_EN_TCO
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ TCO_ADDR_TYPE,
+ {R_TCO_IO_TCO1_STS}
+ },
+ S_TCO_IO_TCO1_STS,
+ N_TCO_IO_TCO1_STS_NEWCENTURY
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_ACPI_IO_SMI_STS}
+ },
+ S_ACPI_IO_SMI_STS,
+ N_ACPI_IO_SMI_STS_TCO
+ }
+};
+
+/**
+ The register function used to register SMI handler of NEW CENTURY event.
+
+ @param[in] This The pointer to the protocol itself
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchTcoSmiNewCenturyRegister (
+ IN PCH_TCO_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_TCO_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+ DATABASE_RECORD *Record;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = PchSmiRecordInsert (
+ &mSrcDescNewCentury,
+ (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+ PchTcoSmiNewCenturyType,
+ DispatchHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
+ Record->ClearSource = PchTcoSmiClearSourceAndBlock;
+ PchSmmClearSource (&Record->SrcDesc);
+ PchSmmEnableSource (&Record->SrcDesc);
+ SmiHandlerProfileRegisterHandler (&gPchTcoSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
+ }
+ return Status;
+}
+
+/**
+ Unregister a child SMI source dispatch function with a parent SMM driver
+
+ @param[in] This Protocol instance pointer.
+ @param[in] DispatchHandle Handle of dispatch function to deregister.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ unregistered and the SMI source has been disabled
+ if there are no other registered child dispatch
+ functions for this SMI source.
+ @retval EFI_INVALID_PARAMETER Handle is invalid.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchTcoSmiUnRegister (
+ IN PCH_TCO_SMI_DISPATCH_PROTOCOL *This,
+ IN EFI_HANDLE DispatchHandle
+ )
+{
+ DATABASE_RECORD *Record;
+ EFI_STATUS Status;
+
+ Record = DATABASE_RECORD_FROM_LINK (DispatchHandle);
+ if ((Record->SrcDesc.En[1].Reg.Type == ACPI_ADDR_TYPE) &&
+ (Record->SrcDesc.En[1].Reg.Data.pcie.Fields.Dev == SpiDevNumber ()) &&
+ (Record->SrcDesc.En[1].Reg.Data.pcie.Fields.Fnc == SpiFuncNumber ()) &&
+ (Record->SrcDesc.En[1].Reg.Data.pcie.Fields.Reg == R_SPI_CFG_BC) &&
+ (Record->SrcDesc.En[1].Bit == N_SPI_CFG_BC_BLE)) {
+ //
+ // SPI Write Protect cannot be disabled
+ //
+ return EFI_ACCESS_DENIED;
+ } else if ((Record->SrcDesc.En[1].Reg.Type == ACPI_ADDR_TYPE) &&
+ (Record->SrcDesc.En[1].Reg.Data.pcie.Fields.Dev == LpcDevNumber ()) &&
+ (Record->SrcDesc.En[1].Reg.Data.pcie.Fields.Fnc == LpcFuncNumber ()) &&
+ (Record->SrcDesc.En[1].Reg.Data.pcie.Fields.Reg == R_LPC_CFG_BC) &&
+ (Record->SrcDesc.En[1].Bit == N_LPC_CFG_BC_LE)) {
+ //
+ // eSPI/LPC Write Protect cannot be disabled
+ //
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = PchSmmCoreUnRegister (NULL, DispatchHandle);
+ if (!EFI_ERROR (Status)) {
+ SmiHandlerProfileUnregisterHandler (&gPchTcoSmiDispatchProtocolGuid, Record->Callback, NULL, 0);
+ }
+ return Status;
+}
+
+
+//
+// PcieRpHotPlug srcdesc
+//
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_SMM_SOURCE_DESC PchPcieSmiRpHotPlugTemplate = {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ PCIE_ADDR_TYPE,
+ {R_PCH_PCIE_CFG_MPC}
+ },
+ S_PCH_PCIE_CFG_MPC,
+ N_PCH_PCIE_CFG_MPC_HPME
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ PCIE_ADDR_TYPE,
+ {R_PCH_PCIE_CFG_SMSCS}
+ },
+ S_PCH_PCIE_CFG_SMSCS,
+ N_PCH_PCIE_CFG_SMSCS_HPPDM
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_ACPI_IO_SMI_STS}
+ },
+ S_ACPI_IO_SMI_STS,
+ N_ACPI_IO_SMI_STS_PCI_EXP
+ }
+};
+
+/**
+ The register function used to register SMI handler of PCIE RP hotplug event.
+
+ @param[in] This The pointer to the protocol itself
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[in] RpIndex Refer PCIE_COMBINED_RPINDEX for PCH RP index and CPU RP index.
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchPcieSmiHotPlugRegister (
+ IN PCH_PCIE_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_PCIE_SMI_RP_DISPATCH_CALLBACK DispatchFunction,
+ IN UINTN RpIndex,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+ UINTN RpDev;
+ UINTN RpFun;
+ PCH_SMM_PCIE_REGISTER_CONTEXT Context;
+ DATABASE_RECORD *Record;
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+ GetPcieRpDevFun (RpIndex, &RpDev, &RpFun);
+
+ PchPcieSmiRpHotPlugTemplate.En[0].Reg.Data.pcie.Fields.Dev = (UINT8) RpDev;
+ PchPcieSmiRpHotPlugTemplate.En[0].Reg.Data.pcie.Fields.Fnc = (UINT8) RpFun;
+ PchPcieSmiRpHotPlugTemplate.Sts[0].Reg.Data.pcie.Fields.Dev = (UINT8) RpDev;
+ PchPcieSmiRpHotPlugTemplate.Sts[0].Reg.Data.pcie.Fields.Fnc = (UINT8) RpFun;
+
+ Status = PchSmiRecordInsert (
+ &PchPcieSmiRpHotPlugTemplate,
+ (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+ PchPcieSmiRpHotplugType,
+ DispatchHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
+ Record->ChildContext.Pcie.PchSmiType = PchPcieSmiRpHotplugType;
+ Record->ChildContext.Pcie.RpIndex = RpIndex;
+ Record->ContextSize = sizeof (PCH_SMM_PCIE_REGISTER_CONTEXT);
+ SmiHandlerProfileRegisterHandler (
+ &gPchPcieSmiDispatchProtocolGuid,
+ (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction,
+ (UINTN)RETURN_ADDRESS (0),
+ &Context,
+ sizeof (Context)
+ );
+ }
+ PchSmmClearSource (&PchPcieSmiRpHotPlugTemplate);
+ PchSmmEnableSource (&PchPcieSmiRpHotPlugTemplate);
+
+ return Status;
+}
+
+//
+// PcieRpLinkActive srcdesc
+//
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_SMM_SOURCE_DESC PchPcieSmiRpLinkActiveTemplate = {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ PCIE_ADDR_TYPE,
+ {R_PCH_PCIE_CFG_MPC}
+ },
+ S_PCH_PCIE_CFG_MPC,
+ N_PCH_PCIE_CFG_MPC_HPME
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ PCIE_ADDR_TYPE,
+ {R_PCH_PCIE_CFG_SMSCS}
+ },
+ S_PCH_PCIE_CFG_SMSCS,
+ N_PCH_PCIE_CFG_SMSCS_HPLAS
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_ACPI_IO_SMI_STS}
+ },
+ S_ACPI_IO_SMI_STS,
+ N_ACPI_IO_SMI_STS_PCI_EXP
+ }
+};
+
+/**
+ The register function used to register SMI handler of PCIE RP link active event.
+
+ @param[in] This The pointer to the protocol itself
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[in] RpIndex Refer PCIE_COMBINED_RPINDEX for PCH RP index and CPU RP index.
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchPcieSmiLinkActiveRegister (
+ IN PCH_PCIE_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_PCIE_SMI_RP_DISPATCH_CALLBACK DispatchFunction,
+ IN UINTN RpIndex,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+ UINTN RpDev;
+ UINTN RpFun;
+ PCH_SMM_PCIE_REGISTER_CONTEXT Context;
+ DATABASE_RECORD *Record;
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ GetPcieRpDevFun (RpIndex, &RpDev, &RpFun);
+
+
+ PchPcieSmiRpLinkActiveTemplate.En[0].Reg.Data.pcie.Fields.Dev = (UINT8) RpDev;
+ PchPcieSmiRpLinkActiveTemplate.En[0].Reg.Data.pcie.Fields.Fnc = (UINT8) RpFun;
+ PchPcieSmiRpLinkActiveTemplate.Sts[0].Reg.Data.pcie.Fields.Dev = (UINT8) RpDev;
+ PchPcieSmiRpLinkActiveTemplate.Sts[0].Reg.Data.pcie.Fields.Fnc = (UINT8) RpFun;
+
+ Status = PchSmiRecordInsert (
+ &PchPcieSmiRpLinkActiveTemplate,
+ (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+ PchPcieSmiRpLinkActiveType,
+ DispatchHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
+ Record->ChildContext.Pcie.PchSmiType = PchPcieSmiRpLinkActiveType;
+ Record->ChildContext.Pcie.RpIndex = RpIndex;
+ Record->ContextSize = sizeof (PCH_SMM_PCIE_REGISTER_CONTEXT);
+ SmiHandlerProfileRegisterHandler (
+ &gPchPcieSmiDispatchProtocolGuid,
+ (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction,
+ (UINTN)RETURN_ADDRESS (0),
+ &Context,
+ sizeof (Context)
+ );
+ }
+ PchSmmClearSource (&PchPcieSmiRpLinkActiveTemplate);
+ PchSmmEnableSource (&PchPcieSmiRpLinkActiveTemplate);
+
+ return Status;
+}
+
+//
+// PcieRpLinkEq srcdesc
+//
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_SMM_SOURCE_DESC PchPcieSmiRpLinkEqTemplate = {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ PCIE_ADDR_TYPE,
+ {R_PCH_PCIE_CFG_EQCFG1}
+ },
+ S_PCH_PCIE_CFG_EQCFG1,
+ N_PCH_PCIE_CFG_EQCFG1_LERSMIE
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ PCIE_ADDR_TYPE,
+ {R_PCH_PCIE_CFG_SMSCS}
+ },
+ S_PCH_PCIE_CFG_SMSCS,
+ N_PCH_PCIE_CFG_SMSCS_LERSMIS
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_ACPI_IO_SMI_STS}
+ },
+ S_ACPI_IO_SMI_STS,
+ N_ACPI_IO_SMI_STS_PCI_EXP
+ }
+};
+/**
+ The register function used to register SMI handler of PCIE RP Link Equalization Request event.
+
+ @param[in] This The pointer to the protocol itself
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[in] RpIndex Refer PCIE_COMBINED_RPINDEX for PCH RP index and CPU RP index.
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchPcieSmiLinkEqRegister (
+ IN PCH_PCIE_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_PCIE_SMI_RP_DISPATCH_CALLBACK DispatchFunction,
+ IN UINTN RpIndex,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ UINTN RpDev;
+ UINTN RpFun;
+ EFI_STATUS Status;
+ PCH_SMM_PCIE_REGISTER_CONTEXT Context;
+ DATABASE_RECORD *Record;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ GetPcieRpDevFun (RpIndex, &RpDev, &RpFun);
+
+ //
+ // Patch the RP device number and function number of srcdesc.
+ //
+ PchPcieSmiRpLinkEqTemplate.En[0].Reg.Data.pcie.Fields.Dev = (UINT8) RpDev;
+ PchPcieSmiRpLinkEqTemplate.En[0].Reg.Data.pcie.Fields.Fnc = (UINT8) RpFun;
+ PchPcieSmiRpLinkEqTemplate.Sts[0].Reg.Data.pcie.Fields.Dev = (UINT8) RpDev;
+ PchPcieSmiRpLinkEqTemplate.Sts[0].Reg.Data.pcie.Fields.Fnc = (UINT8) RpFun;
+
+ Status = PchSmiRecordInsert (
+ &PchPcieSmiRpLinkEqTemplate,
+ (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+ PchPcieSmiRpLinkEqType,
+ DispatchHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
+ Record->ChildContext.Pcie.PchSmiType = PchPcieSmiRpLinkEqType;
+ Record->ChildContext.Pcie.RpIndex = RpIndex;
+ Record->ContextSize = sizeof (PCH_SMM_PCIE_REGISTER_CONTEXT);
+ SmiHandlerProfileRegisterHandler (
+ &gPchPcieSmiDispatchProtocolGuid,
+ (EFI_SMM_HANDLER_ENTRY_POINT2) DispatchFunction,
+ (UINTN)RETURN_ADDRESS (0),
+ &Context,
+ sizeof (Context)
+ );
+ }
+ return Status;
+}
+
+/**
+ Unregister a child SMI source dispatch function with a parent SMM driver
+
+ @param[in] This Protocol instance pointer.
+ @param[in] DispatchHandle Handle of dispatch function to deregister.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ unregistered and the SMI source has been disabled
+ if there are no other registered child dispatch
+ functions for this SMI source.
+ @retval EFI_INVALID_PARAMETER Handle is invalid.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchPcieSmiUnRegister (
+ IN PCH_PCIE_SMI_DISPATCH_PROTOCOL *This,
+ IN EFI_HANDLE DispatchHandle
+ )
+{
+ DATABASE_RECORD *RecordToDelete;
+ EFI_STATUS Status;
+
+ RecordToDelete = DATABASE_RECORD_FROM_LINK (DispatchHandle);
+ Status = PchSmmCoreUnRegister (NULL, DispatchHandle);
+ if (!EFI_ERROR (Status)) {
+ SmiHandlerProfileUnregisterHandler (
+ &gPchPcieSmiDispatchProtocolGuid,
+ RecordToDelete->Callback,
+ &RecordToDelete->ChildContext,
+ sizeof (RecordToDelete->ContextSize)
+ );
+ }
+ return Status;
+}
+
+//
+// Pme srcdesc
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescPme = {
+ PCH_SMM_SCI_EN_DEPENDENT,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_ACPI_IO_GPE0_EN_127_96}
+ },
+ S_ACPI_IO_GPE0_EN_127_96,
+ N_ACPI_IO_GPE0_EN_127_96_PME
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_ACPI_IO_GPE0_STS_127_96}
+ },
+ S_ACPI_IO_GPE0_STS_127_96,
+ N_ACPI_IO_GPE0_STS_127_96_PME
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_ACPI_IO_SMI_STS}
+ },
+ S_ACPI_IO_SMI_STS,
+ N_ACPI_IO_SMI_STS_GPE0
+ }
+};
+
+/**
+ The register function used to register SMI handler of PME event.
+
+ @param[in] This The pointer to the protocol itself
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchAcpiSmiPmeRegister (
+ IN PCH_ACPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ACPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = PchSmiRecordInsert (
+ &mSrcDescPme,
+ (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+ PchAcpiSmiPmeType,
+ DispatchHandle
+ );
+ PchSmmClearSource (&mSrcDescPme);
+ PchSmmEnableSource (&mSrcDescPme);
+ if (!EFI_ERROR (Status)) {
+ SmiHandlerProfileRegisterHandler (&gPchAcpiSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
+ }
+ return Status;
+}
+
+//
+// PmeB0 srcdesc
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescPmeB0 = {
+ PCH_SMM_SCI_EN_DEPENDENT,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_ACPI_IO_GPE0_EN_127_96}
+ },
+ S_ACPI_IO_GPE0_EN_127_96,
+ N_ACPI_IO_GPE0_EN_127_96_PME_B0
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_ACPI_IO_GPE0_STS_127_96}
+ },
+ S_ACPI_IO_GPE0_STS_127_96,
+ N_ACPI_IO_GPE0_STS_127_96_PME_B0
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_ACPI_IO_SMI_STS}
+ },
+ S_ACPI_IO_SMI_STS,
+ N_ACPI_IO_SMI_STS_GPE0
+ }
+};
+/**
+ The register function used to register SMI handler of PME B0 event.
+
+ @param[in] This The pointer to the protocol itself
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchAcpiSmiPmeB0Register (
+ IN PCH_ACPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ACPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = PchSmiRecordInsert (
+ &mSrcDescPmeB0,
+ (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+ PchAcpiSmiPmeB0Type,
+ DispatchHandle
+ );
+ PchSmmClearSource (&mSrcDescPmeB0);
+ PchSmmEnableSource (&mSrcDescPmeB0);
+ if (!EFI_ERROR (Status)) {
+ SmiHandlerProfileRegisterHandler (&gPchAcpiSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
+ }
+ return Status;
+}
+
+//
+// RtcAlarm srcdesc
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescRtcAlarm = {
+ PCH_SMM_SCI_EN_DEPENDENT,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_ACPI_IO_PM1_EN}
+ },
+ S_ACPI_IO_PM1_EN,
+ N_ACPI_IO_PM1_EN_RTC
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_ACPI_IO_PM1_STS}
+ },
+ S_ACPI_IO_PM1_STS,
+ N_ACPI_IO_PM1_STS_RTC
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_ACPI_IO_SMI_STS}
+ },
+ S_ACPI_IO_SMI_STS,
+ N_ACPI_IO_SMI_STS_PM1_STS_REG
+ }
+};
+
+/**
+ The register function used to register SMI handler of RTC alarm event.
+
+ @param[in] This The pointer to the protocol itself
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchAcpiSmiRtcAlarmRegister (
+ IN PCH_ACPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ACPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = PchSmiRecordInsert (
+ &mSrcDescRtcAlarm,
+ (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+ PchAcpiSmiRtcAlarmType,
+ DispatchHandle
+ );
+
+ PchSmmClearSource (&mSrcDescRtcAlarm);
+ PchSmmEnableSource (&mSrcDescRtcAlarm);
+ if (!EFI_ERROR (Status)) {
+ SmiHandlerProfileRegisterHandler (&gPchAcpiSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
+ }
+ return Status;
+}
+
+//
+// TmrOverflow srcdesc
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescTmrOverflow = {
+ PCH_SMM_SCI_EN_DEPENDENT,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_ACPI_IO_PM1_EN}
+ },
+ S_ACPI_IO_PM1_EN,
+ N_ACPI_IO_PM1_EN_TMROF
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_ACPI_IO_PM1_STS}
+ },
+ S_ACPI_IO_PM1_STS,
+ N_ACPI_IO_PM1_STS_TMROF
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_ACPI_IO_SMI_STS}
+ },
+ S_ACPI_IO_SMI_STS,
+ N_ACPI_IO_SMI_STS_PM1_STS_REG
+ }
+};
+
+/**
+ The register function used to register SMI handler of Timer Overflow event.
+
+ @param[in] This The pointer to the protocol itself
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchAcpiSmiTmrOverflowRegister (
+ IN PCH_ACPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ACPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = PchSmiRecordInsert (
+ &mSrcDescTmrOverflow,
+ (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+ PchAcpiSmiTmrOverflowType,
+ DispatchHandle
+ );
+ PchSmmClearSource (&mSrcDescTmrOverflow);
+ PchSmmEnableSource (&mSrcDescTmrOverflow);
+ if (!EFI_ERROR (Status)) {
+ SmiHandlerProfileRegisterHandler (&gPchAcpiSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
+ }
+
+ return Status;
+}
+
+/**
+ Unregister a child SMI source dispatch function with a parent SMM driver
+
+ @param[in] This Protocol instance pointer.
+ @param[in] DispatchHandle Handle of dispatch function to deregister.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ unregistered and the SMI source has been disabled
+ if there are no other registered child dispatch
+ functions for this SMI source.
+ @retval EFI_INVALID_PARAMETER Handle is invalid.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchAcpiSmiUnRegister (
+ IN PCH_ACPI_SMI_DISPATCH_PROTOCOL *This,
+ IN EFI_HANDLE DispatchHandle
+ )
+{
+ DATABASE_RECORD *RecordToDelete;
+ EFI_STATUS Status;
+
+ RecordToDelete = DATABASE_RECORD_FROM_LINK (DispatchHandle);
+ Status = PchSmmCoreUnRegister (NULL, DispatchHandle);
+ if (!EFI_ERROR (Status)) {
+ SmiHandlerProfileUnregisterHandler (&gPchAcpiSmiDispatchProtocolGuid, RecordToDelete->Callback, NULL, 0);
+ }
+ return Status;
+}
+
+//
+// SerialIrq srcdesc
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescSerialIrq = {
+ PCH_SMM_NO_FLAGS,
+ {
+ NULL_BIT_DESC_INITIALIZER,
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_ACPI_IO_SMI_STS}
+ },
+ S_ACPI_IO_SMI_STS,
+ N_ACPI_IO_SMI_STS_SERIRQ
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_ACPI_IO_SMI_STS}
+ },
+ S_ACPI_IO_SMI_STS,
+ N_ACPI_IO_SMI_STS_SERIRQ
+ }
+};
+
+/**
+ The register function used to register SMI handler of Serial IRQ event.
+
+ @param[in] This The pointer to the protocol itself
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchSmiSerialIrqRegister (
+ IN PCH_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = PchSmiRecordInsert (
+ &mSrcDescSerialIrq,
+ (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+ PchSmiSerialIrqType,
+ DispatchHandle
+ );
+ PchSmmClearSource (&mSrcDescSerialIrq);
+ PchSmmEnableSource (&mSrcDescSerialIrq);
+ if (!EFI_ERROR (Status)) {
+ SmiHandlerProfileRegisterHandler (&gPchSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
+ }
+ return Status;
+}
+
+//
+// McSmi srcdesc
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescMcSmi = {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_ACPI_IO_SMI_EN}
+ },
+ S_ACPI_IO_SMI_EN,
+ N_ACPI_IO_SMI_EN_MCSMI
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_ACPI_IO_SMI_STS}
+ },
+ S_ACPI_IO_SMI_STS,
+ N_ACPI_IO_SMI_STS_MCSMI
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_ACPI_IO_SMI_STS}
+ },
+ S_ACPI_IO_SMI_STS,
+ N_ACPI_IO_SMI_STS_MCSMI
+ }
+};
+
+/**
+ The register function used to register SMI handler of MCSMI event.
+
+ @param[in] This The pointer to the protocol itself
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchSmiMcSmiRegister (
+ IN PCH_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = PchSmiRecordInsert (
+ &mSrcDescMcSmi,
+ (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+ PchSmiMcSmiType,
+ DispatchHandle
+ );
+ PchSmmClearSource (&mSrcDescMcSmi);
+ PchSmmEnableSource (&mSrcDescMcSmi);
+ if (!EFI_ERROR (Status)) {
+ SmiHandlerProfileRegisterHandler (&gPchSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
+ }
+ return Status;
+}
+
+//
+// SmBus srcdesc
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescSmbus = {
+ PCH_SMM_NO_FLAGS,
+ {
+ NULL_BIT_DESC_INITIALIZER,
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_ACPI_IO_SMI_STS}
+ },
+ S_ACPI_IO_SMI_STS,
+ N_ACPI_IO_SMI_STS_SMBUS
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_ACPI_IO_SMI_STS}
+ },
+ S_ACPI_IO_SMI_STS,
+ N_ACPI_IO_SMI_STS_SMBUS
+ }
+};
+
+/**
+ The register function used to register SMI handler of SMBUS event.
+
+ @param[in] This The pointer to the protocol itself
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchSmiSmbusRegister (
+ IN PCH_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = PchSmiRecordInsert (
+ &mSrcDescSmbus,
+ (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+ PchSmiSmBusType,
+ DispatchHandle
+ );
+ PchSmmClearSource (&mSrcDescSmbus);
+ PchSmmEnableSource (&mSrcDescSmbus);
+ if (!EFI_ERROR (Status)) {
+ SmiHandlerProfileRegisterHandler (&gPchSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
+ }
+ return Status;
+}
+
+//
+// SpiAsyncSmi srcdesc
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescSpiAsyncSmi = {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ PCIE_ADDR_TYPE,
+ { (
+ (DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
+ (PCI_DEVICE_NUMBER_PCH_SPI << 19) |
+ (PCI_FUNCTION_NUMBER_PCH_SPI << 16) |
+ R_SPI_CFG_BC
+ ) }
+ },
+ S_SPI_CFG_BC,
+ N_SPI_CFG_BC_ASE_BWP
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ PCIE_ADDR_TYPE,
+ { (
+ (DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
+ (PCI_DEVICE_NUMBER_PCH_SPI << 19) |
+ (PCI_FUNCTION_NUMBER_PCH_SPI << 16) |
+ R_SPI_CFG_BC
+ ) }
+ },
+ S_SPI_CFG_BC,
+ N_SPI_CFG_BC_ASYNC_SS
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_ACPI_IO_SMI_STS}
+ },
+ S_ACPI_IO_SMI_STS,
+ N_ACPI_IO_SMI_STS_SPI
+ }
+};
+
+/**
+ Special handling for SPI Asynchronous SMI.
+ If SPI ASYNC SMI is enabled, De-assert SMI is sent when Flash Cycle Done
+ transitions from 1 to 0 or when the SMI enable becomes false.
+
+ @param[in] SrcDesc Not used
+**/
+VOID
+EFIAPI
+PchSmiSpiAsyncClearSource (
+ CONST PCH_SMM_SOURCE_DESC *SrcDesc
+ )
+{
+ UINT64 SpiRegBase;
+ UINT32 SpiBar0;
+
+ SpiRegBase = SpiPciCfgBase ();
+ SpiBar0 = PciSegmentRead32 (SpiRegBase + R_SPI_CFG_BAR0) & ~(B_SPI_CFG_BAR0_MASK);
+ if (SpiBar0 != PCH_SPI_BASE_ADDRESS) {
+ //
+ // Temporary disable MSE, and override with SPI reserved MMIO address, then enable MSE.
+ //
+ SpiBar0 = PCH_SPI_BASE_ADDRESS;
+ PciSegmentAnd8 (SpiRegBase + PCI_COMMAND_OFFSET, (UINT8) ~EFI_PCI_COMMAND_MEMORY_SPACE);
+ PciSegmentWrite32 (SpiRegBase + R_SPI_CFG_BAR0, SpiBar0);
+ PciSegmentOr8 (SpiRegBase + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_MEMORY_SPACE);
+ }
+
+ MmioOr32 (SpiBar0 + R_SPI_MEM_HSFSC, B_SPI_MEM_HSFSC_FDONE);
+}
+
+/**
+ Special handling to enable SPI Asynchronous SMI
+**/
+VOID
+PchSmiSpiAsyncEnableSource (
+ VOID
+ )
+{
+ UINT64 SpiRegBase;
+ UINT32 Data32And;
+ UINT32 Data32Or;
+
+ SpiRegBase = SpiPciCfgBase ();
+ Data32And = (UINT32) ~B_SPI_CFG_BC_SYNC_SS;
+ Data32Or = B_SPI_CFG_BC_ASE_BWP;
+
+ PciSegmentAndThenOr32 (
+ SpiRegBase + R_SPI_CFG_BC,
+ Data32And,
+ Data32Or
+ );
+ S3BootScriptSavePciCfgReadWrite (
+ S3BootScriptWidthUint32,
+ SpiRegBase + R_SPI_CFG_BC,
+ (VOID*) &Data32Or,
+ (VOID*) &Data32And
+ );
+
+ //
+ // Clear the source
+ //
+ PchSmiSpiAsyncClearSource (NULL);
+}
+
+/**
+ The register function used to register SMI handler of SPI Asynchronous event.
+
+ @param[in] This The pointer to the protocol itself
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchSmiSpiAsyncRegister (
+ IN PCH_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+ DATABASE_RECORD *Record;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = PchSmiRecordInsert (
+ &mSrcDescSpiAsyncSmi,
+ (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+ PchSmiSpiAsyncType,
+ DispatchHandle
+ );
+
+ if (!EFI_ERROR (Status)) {
+ Record = DATABASE_RECORD_FROM_LINK (*DispatchHandle);
+ Record->ClearSource = PchSmiSpiAsyncClearSource;
+ PchSmiSpiAsyncClearSource (NULL);
+ PchSmiSpiAsyncEnableSource ();
+ SmiHandlerProfileRegisterHandler (&gPchSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
+ }
+ return Status;
+}
+
+/**
+ Unregister a child SMI source dispatch function with a parent SMM driver
+
+ @param[in] This Protocol instance pointer.
+ @param[in] DispatchHandle Handle of dispatch function to deregister.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ unregistered and the SMI source has been disabled
+ if there are no other registered child dispatch
+ functions for this SMI source.
+ @retval EFI_INVALID_PARAMETER Handle is invalid.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+ @retval EFI_ACCESS_DENIED Return access denied since SPI aync SMI handler is not able to disabled.
+**/
+EFI_STATUS
+EFIAPI
+PchSmiUnRegister (
+ IN PCH_SMI_DISPATCH_PROTOCOL *This,
+ IN EFI_HANDLE DispatchHandle
+ )
+{
+ DATABASE_RECORD *Record;
+ UINT64 SpiRegBase;
+ EFI_STATUS Status;
+
+ Record = DATABASE_RECORD_FROM_LINK (DispatchHandle);
+ if ((Record->SrcDesc.En[0].Reg.Type == PCIE_ADDR_TYPE) &&
+ (Record->SrcDesc.En[0].Reg.Data.pcie.Fields.Dev == SpiDevNumber ()) &&
+ (Record->SrcDesc.En[0].Reg.Data.pcie.Fields.Fnc == SpiFuncNumber ()) &&
+ (Record->SrcDesc.En[0].Reg.Data.pcie.Fields.Reg == R_SPI_CFG_BC) &&
+ (Record->SrcDesc.En[0].Bit == N_SPI_CFG_BC_ASE_BWP)) {
+ SpiRegBase = SpiPciCfgBase ();
+ if (PciSegmentRead8 (SpiRegBase + R_SPI_CFG_BC) & B_SPI_CFG_BC_BILD) {
+ //
+ // SPI Asynchronous SMI cannot be disabled
+ //
+ return EFI_ACCESS_DENIED;
+ }
+ }
+ Status = PchSmmCoreUnRegister (NULL, DispatchHandle);
+ if (!EFI_ERROR (Status)) {
+ SmiHandlerProfileUnregisterHandler (&gPchSmiDispatchProtocolGuid, Record->Callback, NULL, 0);
+ }
+ return Status;
+}
+
+
+/**
+ Declaration of PCH TCO SMI DISPATCH PROTOCOL instance
+**/
+PCH_TCO_SMI_DISPATCH_PROTOCOL mPchTcoSmiDispatchProtocol = {
+ PCH_TCO_SMI_DISPATCH_REVISION, // Revision
+ PchTcoSmiUnRegister, // Unregister
+ PchTcoSmiMchRegister, // Mch
+ PchTcoSmiTcoTimeoutRegister, // TcoTimeout
+ PchTcoSmiOsTcoRegister, // OsTco
+ PchTcoSmiNmiRegister, // Nmi
+ PchTcoSmiIntruderDetRegister, // IntruderDectect
+ PchTcoSmiSpiBiosWpRegister, // SpiBiosWp
+ PchTcoSmiLpcBiosWpRegister, // LpcBiosWp
+ PchTcoSmiNewCenturyRegister // NewCentury
+};
+
+/**
+ Declaration of PCH PCIE SMI DISPATCH PROTOCOL instance
+**/
+PCH_PCIE_SMI_DISPATCH_PROTOCOL mPchPcieSmiDispatchProtocol = {
+ PCH_PCIE_SMI_DISPATCH_REVISION, // Revision
+ PchPcieSmiUnRegister, // Unregister
+ PchPcieSmiHotPlugRegister, // PcieRpXHotPlug
+ PchPcieSmiLinkActiveRegister, // PcieRpXLinkActive
+ PchPcieSmiLinkEqRegister // PcieRpXLinkEq
+};
+
+/**
+ Declaration of PCH ACPI SMI DISPATCH PROTOCOL instance
+**/
+PCH_ACPI_SMI_DISPATCH_PROTOCOL mPchAcpiSmiDispatchProtocol = {
+ PCH_ACPI_SMI_DISPATCH_REVISION, // Revision
+ PchAcpiSmiUnRegister, // Unregister
+ PchAcpiSmiPmeRegister, // Pme
+ PchAcpiSmiPmeB0Register, // PmeB0
+ PchAcpiSmiRtcAlarmRegister, // RtcAlarm
+ PchAcpiSmiTmrOverflowRegister // TmrOverflow
+};
+
+/**
+ Declaration of MISC PCH SMI DISPATCH PROTOCOL instance
+**/
+PCH_SMI_DISPATCH_PROTOCOL mPchSmiDispatchProtocol = {
+ PCH_SMI_DISPATCH_REVISION, // Revision
+ PchSmiUnRegister, // Unregister
+ PchSmiSerialIrqRegister, // SerialIrq
+ PchSmiMcSmiRegister, // McSmi
+ PchSmiSmbusRegister, // SmBus
+ PchSmiSpiAsyncRegister // SpiAsync
+};
+
+/**
+ Install protocols of PCH specifics SMI types, including
+ PCH TCO SMI types, PCH PCIE SMI types, PCH ACPI SMI types, PCH MISC SMI types.
+
+ @retval the result of protocol installation
+**/
+EFI_STATUS
+InstallPchSmiDispatchProtocols (
+ VOID
+ )
+{
+ EFI_HANDLE Handle;
+ EFI_STATUS Status;
+
+ Handle = NULL;
+ Status = gSmst->SmmInstallProtocolInterface (
+ &Handle,
+ &gPchTcoSmiDispatchProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &mPchTcoSmiDispatchProtocol
+ );
+ Status = gSmst->SmmInstallProtocolInterface (
+ &Handle,
+ &gPchPcieSmiDispatchProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &mPchPcieSmiDispatchProtocol
+ );
+ Status = gSmst->SmmInstallProtocolInterface (
+ &Handle,
+ &gPchAcpiSmiDispatchProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &mPchAcpiSmiDispatchProtocol
+ );
+ Status = gSmst->SmmInstallProtocolInterface (
+ &Handle,
+ &gPchSmiDispatchProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &mPchSmiDispatchProtocol
+ );
+
+ return Status;
+}
+
+/**
+ The function to dispatch all callback function of PCH SMI types.
+
+ @retval EFI_SUCCESS Function successfully completed
+ @retval EFI_UNSUPPORTED no
+**/
+EFI_STATUS
+PchSmiTypeCallbackDispatcher (
+ IN DATABASE_RECORD *Record
+ )
+{
+ EFI_STATUS Status;
+ PCH_SMI_TYPES PchSmiType;
+ UINTN RpIndex;
+ PCH_PCIE_SMI_RP_CONTEXT RpContext;
+
+ PchSmiType = Record->PchSmiType;
+ Status = EFI_SUCCESS;
+
+ switch (PchSmiType) {
+ case PchTcoSmiMchType:
+ case PchTcoSmiTcoTimeoutType:
+ case PchTcoSmiOsTcoType:
+ case PchTcoSmiNmiType:
+ case PchTcoSmiIntruderDetectType:
+ case PchTcoSmiSpiBiosWpType:
+ case PchTcoSmiLpcBiosWpType:
+ case PchTcoSmiNewCenturyType:
+ ((PCH_TCO_SMI_DISPATCH_CALLBACK) (Record->PchSmiCallback)) ((EFI_HANDLE)&Record->Link);
+ break;
+ case PchPcieSmiRpHotplugType:
+ case PchPcieSmiRpLinkActiveType:
+ case PchPcieSmiRpLinkEqType:
+ RpContext.BusNum = DEFAULT_PCI_BUS_NUMBER_PCH;
+ RpContext.DevNum = (UINT8) Record->SrcDesc.En[0].Reg.Data.pcie.Fields.Dev;
+ RpContext.FuncNum = (UINT8) Record->SrcDesc.En[0].Reg.Data.pcie.Fields.Fnc;
+ GetPcieRpNumber (RpContext.DevNum, RpContext.FuncNum, &RpIndex);
+ RpContext.RpIndex = (UINT8) RpIndex;
+ ((PCH_PCIE_SMI_RP_DISPATCH_CALLBACK) (Record->PchSmiCallback)) ((EFI_HANDLE)&Record->Link, &RpContext);
+ break;
+ case PchAcpiSmiPmeType:
+ case PchAcpiSmiPmeB0Type:
+ case PchAcpiSmiRtcAlarmType:
+ case PchAcpiSmiTmrOverflowType:
+ ((PCH_ACPI_SMI_DISPATCH_CALLBACK) (Record->PchSmiCallback)) ((EFI_HANDLE)&Record->Link);
+ break;
+ case PchEspiSmiEspiSlaveType:
+ ((PCH_ESPI_SMI_DISPATCH_CALLBACK) (Record->PchSmiCallback)) ((EFI_HANDLE)&Record->Link);
+ break;
+ case PchSmiSerialIrqType:
+ case PchSmiMcSmiType:
+ case PchSmiSmBusType:
+ case PchSmiSpiAsyncType:
+ case PchIoTrapSmiType: ///< internal type for IoTrap
+ ((PCH_SMI_DISPATCH_CALLBACK) (Record->PchSmiCallback)) ((EFI_HANDLE)&Record->Link);
+ break;
+ default:
+ Status = EFI_UNSUPPORTED;
+ break;
+ }
+
+ return Status;
+}
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescIoTrap[4] = {
+ //
+ // PCH I/O Trap register 0 monitor
+ //
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ PCR_ADDR_TYPE,
+ {PCH_PCR_ADDRESS (PID_PSTH, R_PSTH_PCR_TRPREG0) }
+ },
+ 4,
+ 0
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ PCR_ADDR_TYPE,
+ {PCH_PCR_ADDRESS (PID_PSTH, R_PSTH_PCR_TRPST) }
+ },
+ 1,
+ 0
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_ACPI_IO_SMI_STS}
+ },
+ S_ACPI_IO_SMI_STS,
+ N_ACPI_IO_SMI_STS_MONITOR
+ }
+ },
+ //
+ // PCH I/O Trap register 1 monitor
+ //
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ PCR_ADDR_TYPE,
+ {PCH_PCR_ADDRESS (PID_PSTH, R_PSTH_PCR_TRPREG1) }
+ },
+ 4,
+ 0
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ PCR_ADDR_TYPE,
+ {PCH_PCR_ADDRESS (PID_PSTH, R_PSTH_PCR_TRPST) }
+ },
+ 1,
+ 1
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_ACPI_IO_SMI_STS}
+ },
+ S_ACPI_IO_SMI_STS,
+ N_ACPI_IO_SMI_STS_MONITOR
+ }
+ },
+ //
+ // PCH I/O Trap register 2 monitor
+ //
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ PCR_ADDR_TYPE,
+ {PCH_PCR_ADDRESS (PID_PSTH, R_PSTH_PCR_TRPREG2) }
+ },
+ 4,
+ 0
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ PCR_ADDR_TYPE,
+ {PCH_PCR_ADDRESS (PID_PSTH, R_PSTH_PCR_TRPST) }
+ },
+ 1,
+ 2
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_ACPI_IO_SMI_STS}
+ },
+ S_ACPI_IO_SMI_STS,
+ N_ACPI_IO_SMI_STS_MONITOR
+ }
+ },
+ //
+ // PCH I/O Trap register 3 monitor,
+ //
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ PCR_ADDR_TYPE,
+ {PCH_PCR_ADDRESS (PID_PSTH, R_PSTH_PCR_TRPREG3) }
+ },
+ 4,
+ 0
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ PCR_ADDR_TYPE,
+ {PCH_PCR_ADDRESS (PID_PSTH, R_PSTH_PCR_TRPST) }
+ },
+ 1,
+ 3
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_ACPI_IO_SMI_STS}
+ },
+ S_ACPI_IO_SMI_STS,
+ N_ACPI_IO_SMI_STS_MONITOR
+ }
+ }
+};
+
+/**
+ The register function used to register SMI handler of IoTrap event.
+ This is internal function and only used by Iotrap module.
+
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[in] IoTrapIndex Index number of IOTRAP register
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+**/
+EFI_STATUS
+PchInternalIoTrapSmiRegister (
+ IN PCH_SMI_DISPATCH_CALLBACK DispatchFunction,
+ IN UINTN IoTrapIndex,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+
+ Status = PchSmiRecordInsert (
+ &mSrcDescIoTrap[IoTrapIndex],
+ (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+ PchIoTrapSmiType,
+ DispatchHandle
+ );
+ PchSmmClearSource (&mSrcDescIoTrap[IoTrapIndex]);
+ PchSmmEnableSource (&mSrcDescIoTrap[IoTrapIndex]);
+ return Status;
+}
+
+/**
+ Unregister a child SMI source dispatch function with a parent SMM driver
+
+ @param[in] DispatchHandle Handle of dispatch function to deregister.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ unregistered and the SMI source has been disabled
+ if there are no other registered child dispatch
+ functions for this SMI source.
+ @retval EFI_INVALID_PARAMETER Handle is invalid.
+**/
+EFI_STATUS
+PchInternalIoTrapSmiUnRegister (
+ IN EFI_HANDLE DispatchHandle
+ )
+{
+ return PchSmmCoreUnRegister (NULL, DispatchHandle);
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmiDispatcher.inf b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmiDispatcher.inf
new file mode 100644
index 0000000000..97ad2f457e
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmiDispatcher.inf
@@ -0,0 +1,116 @@
+## @file
+# Component description file for the Pch SMI Dispatch Handlers module
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PchSmiDispatcher
+FILE_GUID = B0D6ED53-B844-43f5-BD2F-61095264E77E
+VERSION_STRING = 1.0
+MODULE_TYPE = DXE_SMM_DRIVER
+PI_SPECIFICATION_VERSION = 1.10
+ENTRY_POINT = InitializePchSmmDispatcher
+
+
+[LibraryClasses]
+UefiBootServicesTableLib
+UefiDriverEntryPoint
+IoLib
+DebugLib
+PcdLib
+BaseLib
+BaseMemoryLib
+HobLib
+DevicePathLib
+PchCycleDecodingLib
+PchPcieRpLib
+PchPcrLib
+SmmServicesTableLib
+ReportStatusCodeLib
+PerformanceLib
+DxeServicesTableLib
+GpioLib
+GpioPrivateLib
+EspiLib
+S3BootScriptLib
+ConfigBlockLib
+PmcPrivateLib
+PmcLib
+SmiHandlerProfileLib
+CpuPcieRpLib
+PchPciBdfLib
+PmcPrivateLibWithS3
+CpuPcieInfoFruLib
+
+[Packages]
+MdePkg/MdePkg.dec
+TigerlakeSiliconPkg/SiPkg.dec
+
+
+[Pcd]
+# Progress Code for S3 Suspend start.
+# PROGRESS_CODE_S3_SUSPEND_START = (EFI_SOFTWARE_SMM_DRIVER | (EFI_OEM_SPECIFIC | 0x00000000)) = 0x03078000
+gSiPkgTokenSpaceGuid.PcdProgressCodeS3SuspendStart
+# Progress Code for S3 Suspend end.
+# PROGRESS_CODE_S3_SUSPEND_END = (EFI_SOFTWARE_SMM_DRIVER | (EFI_OEM_SPECIFIC | 0x00000001)) = 0x03078001
+gSiPkgTokenSpaceGuid.PcdProgressCodeS3SuspendEnd
+gSiPkgTokenSpaceGuid.PcdEfiGcdAllocateType
+
+
+[Sources]
+PchSmm.h
+PchSmmCore.c
+PchSmmHelpers.h
+PchSmmHelpers.c
+PchxSmmHelpers.h
+PchxSmmHelpers.c
+PchSmmUsb.c
+PchSmmGpi.c
+PchSmmPowerButton.c
+PchSmmSw.c
+PchSmmSx.c
+PchSmmPeriodicTimer.c
+IoTrap.c
+PchSmiDispatch.c
+PchSmmEspi.c
+PchSmiHelperClient.c
+
+
+[Protocols]
+gEfiPciRootBridgeIoProtocolGuid ## CONSUMES
+gEfiSmmGpiDispatch2ProtocolGuid ## PRODUCES
+gEfiSmmSxDispatch2ProtocolGuid ## PRODUCES
+gEfiSmmSwDispatch2ProtocolGuid ## PRODUCES
+gEfiSmmUsbDispatch2ProtocolGuid ## PRODUCES
+gEfiSmmPowerButtonDispatch2ProtocolGuid ## PRODUCES
+gEfiSmmPeriodicTimerDispatch2ProtocolGuid ## PRODUCES
+gEfiSmmBase2ProtocolGuid ## CONSUMES
+gEfiSmmCpuProtocolGuid ## CONSUMES
+gEfiSmmReadyToLockProtocolGuid ## CONSUMES
+gEfiSmmIoTrapDispatch2ProtocolGuid ## PRODUCES
+gPchSmmIoTrapControlGuid ## PRODUCES
+gPchTcoSmiDispatchProtocolGuid ## PRODUCES
+gPchPcieSmiDispatchProtocolGuid ## PRODUCES
+gPchAcpiSmiDispatchProtocolGuid ## PRODUCES
+gPchSmiDispatchProtocolGuid ## PRODUCES
+gPchEspiSmiDispatchProtocolGuid ## PRODUCES
+gPchSmmPeriodicTimerControlGuid ## PRODUCES
+gIoTrapExDispatchProtocolGuid ## PRODUCES
+gPchNvsAreaProtocolGuid ## CONSUMES
+
+
+[Guids]
+
+
+[Depex]
+gEfiPciRootBridgeIoProtocolGuid AND
+gEfiPciHostBridgeResourceAllocationProtocolGuid AND ## This is to ensure that PCI MMIO resource has been prepared and available for this driver to allocate.
+gEfiSmmCpuProtocolGuid AND
+gEfiSmmBase2ProtocolGuid AND ## This is for SmmServicesTableLib
+gPchNvsAreaProtocolGuid
+
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmiHelper.h b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmiHelper.h
new file mode 100644
index 0000000000..b224ee650c
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmiHelper.h
@@ -0,0 +1,40 @@
+/** @file
+ PCH SMI Helper Header
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _PCH_SMI_HELPER_H_
+#define _PCH_SMI_HELPER_H_
+#include <Uefi/UefiBaseType.h>
+
+/**
+ Get Root Port physical Number by CPU or PCH 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 physical Root Port index (0-based)
+**/
+VOID
+GetPcieRpNumber (
+ IN UINTN RpDev,
+ IN UINTN RpFun,
+ OUT UINTN *RpNumber
+ );
+
+/**
+ Get CPU or PCH 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.
+**/
+VOID
+GetPcieRpDevFun (
+ IN UINTN RpIndex,
+ OUT UINTN *RpDev,
+ OUT UINTN *RpFun
+ );
+
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmiHelperClient.c b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmiHelperClient.c
new file mode 100644
index 0000000000..7693e76683
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmiHelperClient.c
@@ -0,0 +1,57 @@
+/** @file
+ This file provides function to handle client-server differences.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include "PchSmmHelpers.h"
+#include <Register/PmcRegs.h>
+#include <Register/PchPcieRpRegs.h>
+#include <Register/CpuPcieRegs.h>
+#include <Library/CpuPcieInfoFruLib.h>
+#include <Library/CpuPcieRpLib.h>
+#include <CpuPcieInfo.h>
+#include <Library/PchPcieRpLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/PchPciBdfLib.h>
+
+/**
+ Get Root Port physical Number by CPU or PCH 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 physical Root Port index (0-based)
+**/
+VOID
+GetPcieRpNumber (
+ IN UINTN RpDev,
+ IN UINTN RpFun,
+ OUT UINTN *RpNumber
+ )
+{
+ UINT64 RpBase;
+ RpBase = PCI_SEGMENT_LIB_ADDRESS (SA_SEG_NUM, SA_MC_BUS, RpDev, RpFun, 0);
+ GetPchPcieRpNumber (RpDev, RpFun, RpNumber);
+}
+
+/**
+ Get CPU or PCH 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.
+**/
+VOID
+GetPcieRpDevFun (
+ IN UINTN RpIndex,
+ OUT UINTN *RpDev,
+ OUT UINTN *RpFun
+ )
+{
+ if (RpIndex >= CpuRpIndex0 && RpIndex <= CpuRpIndex3) {
+ GetCpuPcieRpDevFun ((RpIndex - CpuRpIndex0), RpDev, RpFun);
+ } else {
+ *RpDev = PchPcieRpDevNumber (RpIndex);
+ *RpFun = PchPcieRpFuncNumber (RpIndex);
+ }
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmm.h b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmm.h
new file mode 100644
index 0000000000..6a23de2bc9
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmm.h
@@ -0,0 +1,1043 @@
+/** @file
+ Prototypes and defines for the PCH SMM Dispatcher.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PCH_SMM_H_
+#define _PCH_SMM_H_
+
+#include <Uefi.h>
+#include <Protocol/PciRootBridgeIo.h>
+#include <Protocol/LoadedImage.h>
+#include <Protocol/SmmControl2.h>
+#include <Protocol/SmmUsbDispatch2.h>
+#include <Protocol/SmmSxDispatch2.h>
+#include <Protocol/SmmSwDispatch2.h>
+#include <Protocol/SmmGpiDispatch2.h>
+#include <Protocol/SmmPowerButtonDispatch2.h>
+#include <Protocol/SmmPeriodicTimerDispatch2.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/SmmServicesTableLib.h>
+#include <Library/ReportStatusCodeLib.h>
+#include <Library/PerformanceLib.h>
+#include <Protocol/SmmReadyToLock.h>
+#include <IndustryStandard/Pci30.h>
+#include <Library/PchCycleDecodingLib.h>
+#include <Library/PchPcieRpLib.h>
+#include <Library/PchPcrLib.h>
+#include <Library/PciSegmentLib.h>
+#include <Library/GpioLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/EspiLib.h>
+#include <Library/GpioPrivateLib.h>
+#include <Protocol/PchTcoSmiDispatch.h>
+#include <Protocol/PchPcieSmiDispatch.h>
+#include <Protocol/PchAcpiSmiDispatch.h>
+#include <Protocol/PchSmiDispatch.h>
+#include <Protocol/PchEspiSmiDispatch.h>
+#include <Protocol/IoTrapExDispatch.h>
+#include <Library/PmcLib.h>
+#include "IoTrap.h"
+
+#define EFI_BAD_POINTER 0xAFAFAFAFAFAFAFAFULL
+
+extern BOOLEAN mReadyToLock;
+
+///
+/// Define an enumeration for all the supported protocols
+///
+#define PCH_SMM_PROTOCOL_TYPE_MAX 6
+
+typedef enum {
+ UsbType,
+ SxType,
+ SwType,
+ GpiType,
+ PowerButtonType,
+ PeriodicTimerType,
+ PchSmiDispatchType,
+ PchSmmProtocolTypeMax
+} PCH_SMM_PROTOCOL_TYPE;
+
+///
+/// Define all the supported types of PCH SMI
+///
+typedef enum {
+ PchTcoSmiMchType,
+ PchTcoSmiTcoTimeoutType,
+ PchTcoSmiOsTcoType,
+ PchTcoSmiNmiType,
+ PchTcoSmiIntruderDetectType,
+ PchTcoSmiSpiBiosWpType,
+ PchTcoSmiLpcBiosWpType,
+ PchTcoSmiNewCenturyType,
+ PchPcieSmiRpHotplugType,
+ PchPcieSmiRpLinkActiveType,
+ PchPcieSmiRpLinkEqType,
+ PchAcpiSmiPmeType,
+ PchAcpiSmiPmeB0Type,
+ PchAcpiSmiRtcAlarmType,
+ PchAcpiSmiTmrOverflowType,
+ PchEspiSmiEspiSlaveType,
+ PchSmiSerialIrqType,
+ PchSmiMcSmiType,
+ PchSmiSmBusType,
+ PchSmiSpiAsyncType,
+ PchIoTrapSmiType ///< internal SMI type
+} PCH_SMI_TYPES;
+
+///
+/// Generic funciton pointer to cover all Pch SMI function pointer types
+///
+typedef
+VOID
+(EFIAPI *PCH_SMI_CALLBACK_FUNCTIONS) (
+ IN EFI_HANDLE DispatchHandle,
+ ...
+ );
+
+
+///
+/// SPECIFYING A REGISTER
+/// We want a general way of referring to addresses. For this case, we'll only
+/// need addresses in the ACPI table (and the TCO entries within the ACPI table).
+/// However, it's interesting to consider what it would take to support other types
+/// of addresses. To address Will's concern, I think it prudent to accommodate it
+/// early on in the design.
+///
+/// Addresses we need to consider:
+///
+/// Type: Required:
+/// I/O Yes
+/// ACPI (special case of I/O) Only if we want to
+/// TCO (special case of I/O) Only if we want to
+/// GPIO (special case of MMIO) Only if we want to
+/// Memory (or Memory Mapped I/O) Only if we want to
+/// PCIE Yes, for BiosWp
+///
+typedef enum {
+ ///
+ /// IO_ADDR_TYPE, /// unimplemented
+ ///
+ ACPI_ADDR_TYPE,
+ TCO_ADDR_TYPE,
+ ///
+ /// MEMORY_ADDR_TYPE, /// unimplemented
+ ///
+ GPIO_ADDR_TYPE,
+ MEMORY_MAPPED_IO_ADDRESS_TYPE,
+ PCIE_ADDR_TYPE,
+ PCR_ADDR_TYPE,
+ NUM_ADDR_TYPES, ///< count of items in this enum
+ PCH_SMM_ADDR_TYPE_NULL = -1 ///< sentinel to indicate NULL or to signal end of arrays
+} ADDR_TYPE;
+
+//
+// Assumption: 32-bits -- enum's evaluate to integer
+// Assumption: This code will only run on IA-32. Justification: IA-64 doesn't have SMIs.
+// We don't have to worry about 64-bit addresses.
+// Typedef the size of addresses in case the numbers I'm using are wrong or in case
+// this changes. This is a good idea because PCI_ADDR will change, for example, when
+// we add support for PciExpress.
+//
+typedef UINT16 IO_ADDR;
+typedef IO_ADDR ACPI_ADDR; ///< can omit
+typedef IO_ADDR TCO_ADDR; ///< can omit
+typedef UINTN MEM_ADDR;
+typedef MEM_ADDR *MEMORY_MAPPED_IO_ADDRESS;
+typedef MEM_ADDR *GPIO_ADDR;
+typedef union {
+ UINT32 Raw;
+ struct {
+ UINT32 Reg: 16;
+ UINT32 Fnc: 3;
+ UINT32 Dev: 5;
+ UINT32 Bus: 8;
+ } Fields;
+} PCIE_ADDR;
+
+typedef union {
+ UINT32 Raw;
+ struct {
+ UINT16 Offset;
+ UINT8 Pid;
+ UINT8 Base;
+ } Fields;
+} PCR_ADDR;
+
+typedef struct {
+ ADDR_TYPE Type;
+ union {
+ ///
+ /// used to initialize during declaration/definition
+ ///
+ UINT32 raw;
+
+ ///
+ /// used to access useful data
+ ///
+ IO_ADDR io;
+ ACPI_ADDR acpi;
+ TCO_ADDR tco;
+ GPIO_ADDR gpio;
+ MEM_ADDR mem;
+ MEMORY_MAPPED_IO_ADDRESS Mmio;
+ PCIE_ADDR pcie;
+ PCR_ADDR Pcr;
+
+ } Data;
+
+} PCH_SMM_ADDRESS;
+
+///
+/// SPECIFYING BITS WITHIN A REGISTER
+/// Here's a struct that helps us specify a source or enable bit.
+///
+typedef struct {
+ PCH_SMM_ADDRESS Reg;
+ UINT8 SizeInBytes; ///< of the register
+ UINT8 Bit;
+} PCH_SMM_BIT_DESC;
+
+//
+// Sometimes, we'll have bit descriptions that are unused. It'd be great to have a
+// way to easily identify them:
+//
+#define IS_BIT_DESC_NULL(BitDesc) ((BitDesc).Reg.Type == PCH_SMM_ADDR_TYPE_NULL) ///< "returns" true when BitDesc is NULL
+#define NULL_THIS_BIT_DESC(BitDesc) ((BitDesc).Reg.Type = PCH_SMM_ADDR_TYPE_NULL) ///< will "return" an integer w/ value of 0
+#define NULL_BIT_DESC_INITIALIZER \
+ { \
+ { \
+ PCH_SMM_ADDR_TYPE_NULL, \
+ { \
+ 0 \
+ } \
+ }, \
+ 0, 0 \
+ }
+//
+// I'd like a type to specify the callback's Sts & En bits because they'll
+// be commonly used together:
+//
+#define NUM_EN_BITS 2
+#define NUM_STS_BITS 1
+
+//
+// Flags
+//
+typedef UINT8 PCH_SMM_SOURCE_FLAGS;
+
+//
+// Flags required to describe the event source
+//
+#define PCH_SMM_NO_FLAGS 0
+#define PCH_SMM_SCI_EN_DEPENDENT 1
+
+typedef struct {
+ PCH_SMM_SOURCE_FLAGS Flags;
+ PCH_SMM_BIT_DESC En[NUM_EN_BITS]; ///< Describes the enable bit(s) for the SMI event
+ PCH_SMM_BIT_DESC Sts[NUM_STS_BITS]; ///< Describes the secondary status bit for the SMI event. Might be the same as TopLevelSmi
+ PCH_SMM_BIT_DESC PmcSmiSts; ///< Refereing to the top level status bit in PMC SMI_STS, i.e. R_PCH_SMI_STS
+} PCH_SMM_SOURCE_DESC;
+
+///
+/// Used to initialize null source descriptor
+///
+#define NULL_SOURCE_DESC_INITIALIZER \
+ { \
+ PCH_SMM_NO_FLAGS, \
+ { \
+ NULL_BIT_DESC_INITIALIZER, NULL_BIT_DESC_INITIALIZER \
+ }, \
+ { \
+ NULL_BIT_DESC_INITIALIZER \
+ }, \
+ NULL_BIT_DESC_INITIALIZER \
+ }
+
+///
+/// Define a PCIE RP event context for SmiProfileHandlerInfo tool
+///
+typedef struct {
+ PCH_SMI_TYPES PchSmiType;
+ UINTN RpIndex;
+} PCH_SMM_PCIE_REGISTER_CONTEXT;
+
+///
+/// CHILD CONTEXTS
+/// To keep consistent w/ the architecture, we'll need to provide the context
+/// to the child when we call its callback function. After talking with Will,
+/// we agreed that we'll need functions to "dig" the context out of the hardware
+/// in many cases (Sx, Trap, Gpi, etc), and we'll need a function to compare those
+/// contexts to prevent unnecessary dispatches. I'd like a general type for these
+/// "GetContext" functions, so I'll need a union of all the protocol contexts for
+/// our internal use:
+///
+typedef union {
+ //
+ // (in no particular order)
+ //
+ EFI_SMM_SX_REGISTER_CONTEXT Sx;
+ EFI_SMM_PERIODIC_TIMER_REGISTER_CONTEXT PeriodicTimer;
+ EFI_SMM_SW_REGISTER_CONTEXT Sw;
+ EFI_SMM_POWER_BUTTON_REGISTER_CONTEXT PowerButton;
+ EFI_SMM_USB_REGISTER_CONTEXT Usb;
+ EFI_SMM_GPI_REGISTER_CONTEXT Gpi;
+ PCH_SMM_PCIE_REGISTER_CONTEXT Pcie;
+} PCH_SMM_CONTEXT;
+
+///
+/// Misc data for PchDispatcher usage.
+/// For PeriodicTimer, since the ElapsedTime is removed from EFI_SMM_PERIODIC_TIMER_REGISTER_CONTEXT of EDKII,
+/// and PchDispatcher needs it for every record. Thus move it here to support ElapsedTime.
+///
+typedef struct {
+ UINTN ElapsedTime;
+ ///
+ /// A switch to control periodic timer SMI enabling
+ ///
+ BOOLEAN TimerSmiEnabled;
+} PCH_SMM_MISC_DATA;
+
+//
+// Assumption: PeriodicTimer largest at 3x64-bits or 24 bytes
+//
+typedef struct _DATABASE_RECORD DATABASE_RECORD;
+
+///
+/// Assumption: the GET_CONTEXT function will be as small and simple as possible.
+/// Assumption: We don't need to pass in an enumeration for the protocol because each
+/// GET_CONTEXT function is written for only one protocol.
+/// We also need a function to compare contexts to see if the child should be dispatched
+/// In addition, we need a function to acquire CommBuffer and CommBufferSize for
+/// dispatch callback function of EDKII native support.
+///
+typedef
+VOID
+(EFIAPI *GET_CONTEXT) (
+ IN DATABASE_RECORD * Record,
+ OUT PCH_SMM_CONTEXT * Context
+ );
+
+typedef
+BOOLEAN
+(EFIAPI *CMP_CONTEXT) (
+ IN PCH_SMM_CONTEXT * Context1,
+ IN PCH_SMM_CONTEXT * Context2
+ );
+
+typedef
+VOID
+(EFIAPI *GET_COMMBUFFER) (
+ IN DATABASE_RECORD * Record,
+ OUT VOID **CommBuffer,
+ OUT UINTN * CommBufferSize
+ );
+
+///
+/// Finally, every protocol will require a "Get Context" and "Compare Context" call, so
+/// we may as well wrap that up in a table, too.
+///
+typedef struct {
+ GET_CONTEXT GetContext;
+ CMP_CONTEXT CmpContext;
+ GET_COMMBUFFER GetCommBuffer;
+} CONTEXT_FUNCTIONS;
+
+extern CONTEXT_FUNCTIONS ContextFunctions[PCH_SMM_PROTOCOL_TYPE_MAX];
+
+///
+/// MAPPING CONTEXT TO BIT DESCRIPTIONS
+/// I'd like to have a general approach to mapping contexts to bit descriptions.
+/// Sometimes, we'll find that we can use table lookups or constant assignments;
+/// other times, we'll find that we'll need to use a function to perform the mapping.
+/// If we define a macro to mask that process, we'll never have to change the code.
+/// I don't know if this is desirable or not -- if it isn't, then we can get rid
+/// of the macros and just use function calls or variable assignments. Doesn't matter
+/// to me.
+/// Mapping complex contexts requires a function
+///
+
+/**
+ Maps a USB context to a source description.
+
+ @param[in] Context The context we need to map. Type must be USB.
+ @param[out] SrcDesc The source description that corresponds to the given context.
+
+**/
+VOID
+MapUsbToSrcDesc (
+ IN PCH_SMM_CONTEXT *Context,
+ OUT PCH_SMM_SOURCE_DESC *SrcDesc
+ );
+
+/**
+ Figure out which timer the child is requesting and
+ send back the source description
+
+ @param[in] DispatchContext The pointer to the Dispatch Context instances
+ @param[out] SrcDesc The pointer to the source description
+
+**/
+VOID
+MapPeriodicTimerToSrcDesc (
+ IN PCH_SMM_CONTEXT *DispatchContext,
+ OUT PCH_SMM_SOURCE_DESC *SrcDesc
+ );
+
+//
+// Mapping simple contexts can be done by assignment or lookup table
+//
+extern CONST PCH_SMM_SOURCE_DESC mSxSourceDesc;
+extern CONST PCH_SMM_SOURCE_DESC mPowerButtonSourceDesc;
+extern CONST PCH_SMM_SOURCE_DESC mSrcDescNewCentury;
+extern CONST PCH_SMM_SOURCE_DESC mGpiSourceDescTemplate;
+
+///
+/// For PCHx, APMC is UINT8 port, so the MAX SWI Value is 0xFF.
+///
+#define MAXIMUM_SWI_VALUE 0xFF
+///
+/// Open: Need to make sure this kind of type cast will actually work.
+/// May need an intermediate form w/ two VOID* arguments. I'll figure
+/// that out when I start compiling.
+///
+typedef
+VOID
+(EFIAPI *PCH_SMM_CLEAR_SOURCE) (
+ CONST PCH_SMM_SOURCE_DESC * SrcDesc
+ );
+
+///
+/// "DATABASE" RECORD
+/// Linked list data structures
+///
+#define DATABASE_RECORD_SIGNATURE SIGNATURE_32 ('D', 'B', 'R', 'C')
+
+struct _DATABASE_RECORD {
+ UINT32 Signature;
+ LIST_ENTRY Link;
+ BOOLEAN Processed;
+ ///
+ /// Status and Enable bit description
+ ///
+ PCH_SMM_SOURCE_DESC SrcDesc;
+
+ ///
+ /// Callback function
+ ///
+ EFI_SMM_HANDLER_ENTRY_POINT2 Callback;
+ PCH_SMM_CONTEXT ChildContext;
+ UINTN ContextSize;
+
+ ///
+ /// Special handling hooks -- init them to NULL if unused/unneeded
+ ///
+ PCH_SMM_CLEAR_SOURCE ClearSource;
+
+ ///
+ /// Functions required to make callback code general
+ ///
+ CONTEXT_FUNCTIONS ContextFunctions;
+
+ ///
+ /// The protocol that this record dispatches
+ ///
+ PCH_SMM_PROTOCOL_TYPE ProtocolType;
+
+ ///
+ /// Misc data for private usage
+ ///
+ PCH_SMM_MISC_DATA MiscData;
+
+ ///
+ /// PCH SMI callback function
+ ///
+ PCH_SMI_CALLBACK_FUNCTIONS PchSmiCallback;
+ ///
+ /// Indicate the PCH SMI types.
+ ///
+ PCH_SMI_TYPES PchSmiType;
+};
+
+#define DATABASE_RECORD_FROM_LINK(_record) CR (_record, DATABASE_RECORD, Link, DATABASE_RECORD_SIGNATURE)
+#define DATABASE_RECORD_FROM_CHILDCONTEXT(_record) CR (_record, DATABASE_RECORD, ChildContext, DATABASE_RECORD_SIGNATURE)
+
+///
+/// HOOKING INTO THE ARCHITECTURE
+///
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SMM_GENERIC_REGISTER) (
+ IN VOID **This,
+ IN VOID *DispatchFunction,
+ IN VOID *DispatchContext,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+typedef
+EFI_STATUS
+(EFIAPI *PCH_SMM_GENERIC_UNREGISTER) (
+ IN VOID **This,
+ IN EFI_HANDLE DispatchHandle
+ );
+
+///
+/// Define a memory "stamp" equivalent in size and function to most of the protocols
+///
+typedef struct {
+ PCH_SMM_GENERIC_REGISTER Register;
+ PCH_SMM_GENERIC_UNREGISTER Unregister;
+ UINTN Extra1;
+ UINTN Extra2; ///< may not need this one
+} PCH_SMM_GENERIC_PROTOCOL;
+
+/**
+ Register a child SMI dispatch function with a parent SMM driver.
+
+ @param[in] This Pointer to the PCH_SMM_GENERIC_PROTOCOL instance.
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source.
+ @param[in] DispatchContext Pointer to the dispatch function's context.
+ @param[out] DispatchHandle Handle of dispatch function, for when interfacing
+ with the parent SMM driver, will be the address of linked
+ list link in the call back record.
+
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create database record
+ @retval EFI_INVALID_PARAMETER The input parameter is invalid
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ registered and the SMI source has been enabled.
+**/
+EFI_STATUS
+EFIAPI
+PchPiSmmCoreRegister (
+ IN PCH_SMM_GENERIC_PROTOCOL *This,
+ IN EFI_SMM_HANDLER_ENTRY_POINT2 DispatchFunction,
+ IN PCH_SMM_CONTEXT *DispatchContext,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+
+/**
+ Unregister a child SMI source dispatch function with a parent SMM driver
+
+ @param[in] This Protocol instance pointer.
+ @param[in] DispatchHandle Handle of dispatch function to deregister.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ unregistered and the SMI source has been disabled
+ if there are no other registered child dispatch
+ functions for this SMI source.
+ @retval EFI_INVALID_PARAMETER Handle is invalid.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchPiSmmCoreUnRegister (
+ IN PCH_SMM_GENERIC_PROTOCOL *This,
+ IN EFI_HANDLE *DispatchHandle
+ );
+
+
+/**
+ Unregister a child SMI source dispatch function with a parent SMM driver.
+
+ @param[in] This Pointer to the PCH_SMM_GENERIC_PROTOCOL instance.
+ @param[in] DispatchHandle Handle of dispatch function to deregister.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ unregistered and the SMI source has been disabled
+ if there are no other registered child dispatch
+ functions for this SMI source.
+ @retval EFI_INVALID_PARAMETER Handle is invalid.
+**/
+EFI_STATUS
+EFIAPI
+PchSmmCoreUnRegister (
+ IN PCH_SMM_GENERIC_PROTOCOL *This,
+ IN EFI_HANDLE *DispatchHandle
+ );
+
+typedef union {
+ PCH_SMM_GENERIC_PROTOCOL Generic;
+ EFI_SMM_USB_DISPATCH2_PROTOCOL Usb;
+ EFI_SMM_SX_DISPATCH2_PROTOCOL Sx;
+ EFI_SMM_SW_DISPATCH2_PROTOCOL Sw;
+ EFI_SMM_GPI_DISPATCH2_PROTOCOL Gpi;
+ EFI_SMM_POWER_BUTTON_DISPATCH2_PROTOCOL PowerButton;
+ EFI_SMM_PERIODIC_TIMER_DISPATCH2_PROTOCOL PeriodicTimer;
+} PCH_SMM_PROTOCOL;
+
+///
+/// Define a structure to help us identify the generic protocol
+///
+#define PROTOCOL_SIGNATURE SIGNATURE_32 ('P', 'R', 'O', 'T')
+
+typedef struct {
+ UINTN Signature;
+
+ PCH_SMM_PROTOCOL_TYPE Type;
+ EFI_GUID *Guid;
+ PCH_SMM_PROTOCOL Protocols;
+} PCH_SMM_QUALIFIED_PROTOCOL;
+
+#define QUALIFIED_PROTOCOL_FROM_GENERIC(_generic) \
+ CR ( \
+ _generic, \
+ PCH_SMM_QUALIFIED_PROTOCOL, \
+ Protocols, \
+ PROTOCOL_SIGNATURE \
+ )
+
+///
+/// Create private data for the protocols that we'll publish
+///
+typedef struct {
+ LIST_ENTRY CallbackDataBase;
+ EFI_HANDLE SmiHandle;
+ EFI_HANDLE InstallMultProtHandle;
+ PCH_SMM_QUALIFIED_PROTOCOL Protocols[PCH_SMM_PROTOCOL_TYPE_MAX];
+} PRIVATE_DATA;
+
+extern PRIVATE_DATA mPrivateData;
+extern UINT16 mAcpiBaseAddr;
+extern UINT16 mTcoBaseAddr;
+
+/**
+ The internal function used to create and insert a database record
+
+ @param[in] InsertRecord Record to insert to database.
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+**/
+EFI_STATUS
+SmmCoreInsertRecord (
+ IN DATABASE_RECORD *NewRecord,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+
+/**
+ Get the Sleep type
+
+ @param[in] Record No use
+ @param[out] Context The context that includes SLP_TYP bits to be filled
+**/
+VOID
+EFIAPI
+SxGetContext (
+ IN DATABASE_RECORD *Record,
+ OUT PCH_SMM_CONTEXT *Context
+ );
+
+/**
+ Register a child SMI source dispatch function for the specified software SMI.
+
+ This service registers a function (DispatchFunction) which will be called when the software
+ SMI source specified by RegisterContext->SwSmiCpuIndex is detected. On return,
+ DispatchHandle contains a unique handle which may be used later to unregister the function
+ using UnRegister().
+
+ @param[in] This Pointer to the EFI_SMM_SW_DISPATCH2_PROTOCOL instance.
+ @param[in] DispatchFunction Function to register for handler when the specified software
+ SMI is generated.
+ @param[in, out] RegisterContext Pointer to the dispatch function's context.
+ The caller fills this context in before calling
+ the register function to indicate to the register
+ function which Software SMI input value the
+ dispatch function should be invoked for.
+ @param[out] DispatchHandle Handle generated by the dispatcher to track the
+ function instance.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ registered and the SMI source has been enabled.
+ @retval EFI_DEVICE_ERROR The SW driver was unable to enable the SMI source.
+ @retval EFI_INVALID_PARAMETER RegisterContext is invalid. The SW SMI input value
+ is not within a valid range or is already in use.
+ @retval EFI_OUT_OF_RESOURCES There is not enough memory (system or SMM) to manage this
+ child.
+ @retval EFI_OUT_OF_RESOURCES A unique software SMI value could not be assigned
+ for this dispatch.
+**/
+EFI_STATUS
+EFIAPI
+PchSwSmiRegister (
+ IN EFI_SMM_SW_DISPATCH2_PROTOCOL *This,
+ IN EFI_SMM_HANDLER_ENTRY_POINT2 DispatchFunction,
+ IN EFI_SMM_SW_REGISTER_CONTEXT *DispatchContext,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+
+/**
+ Unregister a child SMI source dispatch function for the specified software SMI.
+
+ This service removes the handler associated with DispatchHandle so that it will no longer be
+ called in response to a software SMI.
+
+ @param[in] This Pointer to the EFI_SMM_SW_DISPATCH2_PROTOCOL instance.
+ @param[in] DispatchHandle Handle of dispatch function to deregister.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully unregistered.
+ @retval EFI_INVALID_PARAMETER The DispatchHandle was not valid.
+**/
+EFI_STATUS
+EFIAPI
+PchSwSmiUnRegister (
+ IN CONST EFI_SMM_SW_DISPATCH2_PROTOCOL *This,
+ IN EFI_HANDLE DispatchHandle
+ );
+
+/**
+ Init required protocol for Pch Sw Dispatch protocol.
+**/
+VOID
+PchSwDispatchInit (
+ VOID
+ );
+
+/**
+ Check whether sleep type of two contexts match
+
+ @param[in] Context1 Context 1 that includes sleep type 1
+ @param[in] Context2 Context 2 that includes sleep type 2
+
+ @retval FALSE Sleep types match
+ @retval TRUE Sleep types don't match
+**/
+BOOLEAN
+EFIAPI
+SxCmpContext (
+ IN PCH_SMM_CONTEXT *Context1,
+ IN PCH_SMM_CONTEXT *Context2
+ );
+
+/**
+ Update the elapsed time from the Interval data of DATABASE_RECORD
+
+ @param[in] Record The pointer to the DATABASE_RECORD.
+ @param[out] HwContext The Context to be updated.
+**/
+VOID
+EFIAPI
+PeriodicTimerGetContext (
+ IN DATABASE_RECORD *Record,
+ OUT PCH_SMM_CONTEXT *Context
+ );
+
+/**
+ Check whether Periodic Timer of two contexts match
+
+ @param[in] Context1 Context 1 that includes Periodic Timer 1
+ @param[in] Context2 Context 2 that includes Periodic Timer 2
+
+ @retval FALSE Periodic Timer match
+ @retval TRUE Periodic Timer don't match
+**/
+BOOLEAN
+EFIAPI
+PeriodicTimerCmpContext (
+ IN PCH_SMM_CONTEXT *Context1,
+ IN PCH_SMM_CONTEXT *Context2
+ );
+
+/**
+ Gather the CommBuffer information of SmmPeriodicTimerDispatch2.
+
+ @param[in] Record No use
+ @param[out] CommBuffer Point to the CommBuffer structure
+ @param[out] CommBufferSize Point to the Size of CommBuffer structure
+**/
+VOID
+EFIAPI
+PeriodicTimerGetCommBuffer (
+ IN DATABASE_RECORD *Record,
+ OUT VOID **CommBuffer,
+ OUT UINTN *CommBufferSize
+ );
+
+/**
+ Get the power button status.
+
+ @param[in] Record The pointer to the DATABASE_RECORD.
+ @param[out] Context Calling context from the hardware, will be updated with the current power button status.
+**/
+VOID
+EFIAPI
+PowerButtonGetContext (
+ IN DATABASE_RECORD *Record,
+ OUT PCH_SMM_CONTEXT *Context
+ );
+
+/**
+ Check whether Power Button status of two contexts match
+
+ @param[in] Context1 Context 1 that includes Power Button status 1
+ @param[in] Context2 Context 2 that includes Power Button status 2
+
+ @retval FALSE Power Button status match
+ @retval TRUE Power Button status don't match
+**/
+BOOLEAN
+EFIAPI
+PowerButtonCmpContext (
+ IN PCH_SMM_CONTEXT *Context1,
+ IN PCH_SMM_CONTEXT *Context2
+ );
+
+/**
+ This function is responsible for calculating and enabling any timers that are required
+ to dispatch messages to children. The SrcDesc argument isn't acutally used.
+
+ @param[in] SrcDesc Pointer to the PCH_SMM_SOURCE_DESC instance.
+**/
+VOID
+EFIAPI
+PchSmmPeriodicTimerClearSource (
+ IN CONST PCH_SMM_SOURCE_DESC *SrcDesc
+ );
+
+/**
+ This services returns the next SMI tick period that is supported by the chipset.
+ The order returned is from longest to shortest interval period.
+
+ @param[in] This Pointer to the EFI_SMM_PERIODIC_TIMER_DISPATCH2_PROTOCOL instance.
+ @param[in, out] SmiTickInterval Pointer to pointer of the next shorter SMI interval period that is supported by the child.
+
+ @retval EFI_SUCCESS The service returned successfully.
+ @retval EFI_INVALID_PARAMETER The parameter SmiTickInterval is invalid.
+**/
+EFI_STATUS
+PchSmmPeriodicTimerDispatchGetNextShorterInterval (
+ IN CONST EFI_SMM_PERIODIC_TIMER_DISPATCH2_PROTOCOL *This,
+ IN OUT UINT64 **SmiTickInterval
+ );
+
+/**
+ Install PCH SMM periodic timer control protocol
+
+ @param[in] Handle handle for this driver
+
+ @retval EFI_SUCCESS Driver initialization completed successfully
+**/
+EFI_STATUS
+EFIAPI
+InstallPchSmmPeriodicTimerControlProtocol (
+ IN EFI_HANDLE Handle
+ );
+
+/**
+ When we get an SMI that indicates that we are transitioning to a sleep state,
+ we need to actually transition to that state. We do this by disabling the
+ "SMI on sleep enable" feature, which generates an SMI when the operating system
+ tries to put the system to sleep, and then physically putting the system to sleep.
+**/
+VOID
+PchSmmSxGoToSleep (
+ VOID
+ );
+
+/**
+ Install protocols of PCH specifics SMI types, including
+ PCH TCO SMI types, PCH PCIE SMI types, PCH ACPI SMI types, PCH MISC SMI types.
+
+ @retval the result of protocol installation
+**/
+EFI_STATUS
+InstallPchSmiDispatchProtocols (
+ VOID
+ );
+
+/**
+ The function to dispatch all callback function of PCH SMI types.
+
+ @retval EFI_SUCCESS Function successfully completed
+ @retval EFI_UNSUPPORTED no
+**/
+EFI_STATUS
+PchSmiTypeCallbackDispatcher (
+ IN DATABASE_RECORD *Record
+ );
+
+/**
+ The register function used to register SMI handler of IoTrap event.
+ This is internal function and only used by Iotrap module.
+
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[in] IoTrapIndex Index number of IOTRAP register
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+**/
+EFI_STATUS
+PchInternalIoTrapSmiRegister (
+ IN PCH_SMI_DISPATCH_CALLBACK DispatchFunction,
+ IN UINTN IoTrapIndex,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+
+/**
+ Unregister a child SMI source dispatch function with a parent SMM driver
+
+ @param[in] DispatchHandle Handle of dispatch function to deregister.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ unregistered and the SMI source has been disabled
+ if there are no other registered child dispatch
+ functions for this SMI source.
+ @retval EFI_INVALID_PARAMETER Handle is invalid.
+**/
+EFI_STATUS
+PchInternalIoTrapSmiUnRegister (
+ IN EFI_HANDLE DispatchHandle
+ );
+
+/**
+ Register an eSPI SMI handler based on the type
+
+ @param[in] DispatchFunction Callback in an event of eSPI SMI
+ @param[in] PchSmiTypes The eSPI type published by PchSmiDispatch
+ @param[out] DispatchHandle The callback handle
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS Registration is successful.
+**/
+EFI_STATUS
+PchInternalEspiSmiRegister (
+ IN PCH_SMI_DISPATCH_CALLBACK DispatchFunction,
+ IN PCH_SMI_TYPES PchSmiTypes,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+
+/**
+ Unregister an eSPI SMI handler
+
+ @param[in] DispatchHandle Handle of dispatch function to deregister.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ unregistered and the SMI source has been disabled
+ if there are no other registered child dispatch
+ functions for this SMI source.
+ @retval EFI_INVALID_PARAMETER Handle is invalid.
+**/
+EFI_STATUS
+PchInternalEspiSmiUnRegister (
+ IN EFI_HANDLE DispatchHandle
+ );
+
+/**
+ The internal function used to create and insert a database record
+ for SMI record of Pch Smi types.
+
+ @param[in] SrcDesc The pointer to the SMI source description
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source
+ @param[in] PchSmiType Specific SMI type of PCH SMI
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+**/
+EFI_STATUS
+PchSmiRecordInsert (
+ IN CONST PCH_SMM_SOURCE_DESC *SrcDesc,
+ IN PCH_SMI_CALLBACK_FUNCTIONS DispatchFunction,
+ IN PCH_SMI_TYPES PchSmiType,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+
+extern CONST PCH_SMM_SOURCE_DESC mSrcDescSerialIrq;
+extern CONST PCH_SMM_SOURCE_DESC mSrcDescLpcBiosWp;
+
+/**
+ Clear the TCO SMI status bit and block after the SMI handling is done
+
+ @param[in] SrcDesc Pointer to the PCH SMI source description table
+
+**/
+VOID
+EFIAPI
+PchTcoSmiClearSourceAndBlock (
+ CONST PCH_SMM_SOURCE_DESC *SrcDesc
+ );
+
+/**
+ Clear the TCO SMI status bit after the SMI handling is done
+
+ @param[in] SrcDesc Pointer to the PCH SMI source description table
+
+**/
+VOID
+EFIAPI
+PchTcoSmiClearSource (
+ CONST PCH_SMM_SOURCE_DESC *SrcDesc
+ );
+
+/**
+ Initialize Source descriptor structure
+
+ @param[in] SrcDesc Pointer to the PCH SMI source description table
+**/
+VOID
+EFIAPI
+NullInitSourceDesc (
+ PCH_SMM_SOURCE_DESC *SrcDesc
+ );
+
+/**
+ The register function used to register SMI handler of GPI SMI event.
+
+ @param[in] This Pointer to the EFI_SMM_GPI_DISPATCH2_PROTOCOL instance.
+ @param[in] DispatchFunction Function to register for handler when the specified GPI causes an SMI.
+ @param[in] RegisterContext Pointer to the dispatch function's context.
+ The caller fills this context in before calling
+ the register function to indicate to the register
+ function the GPI(s) for which the dispatch function
+ should be invoked.
+ @param[out] DispatchHandle Handle generated by the dispatcher to track the
+ function instance.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ registered and the SMI source has been enabled.
+ @retval EFI_ACCESS_DENIED Register is not allowed
+ @retval EFI_INVALID_PARAMETER RegisterContext is invalid. The GPI input value
+ is not within valid range.
+ @retval EFI_OUT_OF_RESOURCES There is not enough memory (system or SMM) to manage this child.
+**/
+EFI_STATUS
+EFIAPI
+PchGpiSmiRegister (
+ IN CONST EFI_SMM_GPI_DISPATCH2_PROTOCOL *This,
+ IN EFI_SMM_HANDLER_ENTRY_POINT2 DispatchFunction,
+ IN EFI_SMM_GPI_REGISTER_CONTEXT *RegisterContext,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+
+/**
+ Unregister a GPI SMI source dispatch function with a parent SMM driver
+
+ @param[in] This Pointer to the EFI_SMM_GPI_DISPATCH2_PROTOCOL instance.
+ @param[in] DispatchHandle Handle of dispatch function to deregister.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ unregistered and the SMI source has been disabled
+ if there are no other registered child dispatch
+ functions for this SMI source.
+ @retval EFI_INVALID_PARAMETER Handle is invalid.
+**/
+EFI_STATUS
+EFIAPI
+PchGpiSmiUnRegister (
+ IN CONST EFI_SMM_GPI_DISPATCH2_PROTOCOL *This,
+ IN EFI_HANDLE DispatchHandle
+ );
+
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmCore.c b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmCore.c
new file mode 100644
index 0000000000..b2e76a8b72
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmCore.c
@@ -0,0 +1,926 @@
+/** @file
+ This driver is responsible for the registration of child drivers
+ and the abstraction of the PCH SMI sources.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include "PchSmm.h"
+#include "PchSmmHelpers.h"
+#include "PchSmmEspi.h"
+#include <Library/SmiHandlerProfileLib.h>
+#include <Register/GpioRegs.h>
+#include <Register/PmcRegs.h>
+#include <Register/RtcRegs.h>
+
+#define PROGRESS_CODE_S3_SUSPEND_START PcdGet32 (PcdProgressCodeS3SuspendStart)
+//
+// MODULE / GLOBAL DATA
+//
+// Module variables used by the both the main dispatcher and the source dispatchers
+// Declared in PchSmm.h
+//
+GLOBAL_REMOVE_IF_UNREFERENCED UINT16 mAcpiBaseAddr;
+GLOBAL_REMOVE_IF_UNREFERENCED UINT16 mTcoBaseAddr;
+GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN mReadyToLock;
+GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN mS3SusStart;
+
+GLOBAL_REMOVE_IF_UNREFERENCED PRIVATE_DATA mPrivateData = {
+ {
+ NULL,
+ NULL
+ }, // CallbackDataBase linked list head
+ NULL, // EFI handle returned when calling InstallMultipleProtocolInterfaces
+ NULL, //
+ { // protocol arrays
+ //
+ // elements within the array
+ //
+ {
+ PROTOCOL_SIGNATURE,
+ UsbType,
+ &gEfiSmmUsbDispatch2ProtocolGuid,
+ {{
+ (PCH_SMM_GENERIC_REGISTER) PchPiSmmCoreRegister,
+ (PCH_SMM_GENERIC_UNREGISTER) PchPiSmmCoreUnRegister
+ }}
+ },
+ {
+ PROTOCOL_SIGNATURE,
+ SxType,
+ &gEfiSmmSxDispatch2ProtocolGuid,
+ {{
+ (PCH_SMM_GENERIC_REGISTER) PchPiSmmCoreRegister,
+ (PCH_SMM_GENERIC_UNREGISTER) PchPiSmmCoreUnRegister
+ }}
+ },
+ {
+ PROTOCOL_SIGNATURE,
+ SwType,
+ &gEfiSmmSwDispatch2ProtocolGuid,
+ {{
+ (PCH_SMM_GENERIC_REGISTER) PchSwSmiRegister,
+ (PCH_SMM_GENERIC_UNREGISTER) PchSwSmiUnRegister,
+ (UINTN) MAXIMUM_SWI_VALUE
+ }}
+ },
+ {
+ PROTOCOL_SIGNATURE,
+ GpiType,
+ &gEfiSmmGpiDispatch2ProtocolGuid,
+ {{
+ (PCH_SMM_GENERIC_REGISTER) PchGpiSmiRegister,
+ (PCH_SMM_GENERIC_UNREGISTER) PchGpiSmiUnRegister,
+ (UINTN) PCH_GPIO_NUM_SUPPORTED_GPIS
+ }}
+ },
+ {
+ PROTOCOL_SIGNATURE,
+ PowerButtonType,
+ &gEfiSmmPowerButtonDispatch2ProtocolGuid,
+ {{
+ (PCH_SMM_GENERIC_REGISTER) PchPiSmmCoreRegister,
+ (PCH_SMM_GENERIC_UNREGISTER) PchPiSmmCoreUnRegister
+ }}
+ },
+ {
+ PROTOCOL_SIGNATURE,
+ PeriodicTimerType,
+ &gEfiSmmPeriodicTimerDispatch2ProtocolGuid,
+ {{
+ (PCH_SMM_GENERIC_REGISTER) PchPiSmmCoreRegister,
+ (PCH_SMM_GENERIC_UNREGISTER) PchPiSmmCoreUnRegister,
+ (UINTN) PchSmmPeriodicTimerDispatchGetNextShorterInterval
+ }}
+ },
+ }
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONTEXT_FUNCTIONS mContextFunctions[PCH_SMM_PROTOCOL_TYPE_MAX] = {
+ {
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ SxGetContext,
+ SxCmpContext,
+ NULL
+ },
+ {
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ PowerButtonGetContext,
+ PowerButtonCmpContext,
+ NULL
+ },
+ {
+ PeriodicTimerGetContext,
+ PeriodicTimerCmpContext,
+ PeriodicTimerGetCommBuffer
+ },
+};
+
+//
+// PROTOTYPES
+//
+// Functions use only in this file
+//
+EFI_STATUS
+EFIAPI
+PchSmmCoreDispatcher (
+ IN EFI_HANDLE SmmImageHandle,
+ IN CONST VOID *PchSmmCore, OPTIONAL
+ IN OUT VOID *CommunicationBuffer,
+ IN OUT UINTN *SourceSize
+ );
+
+//
+// FUNCTIONS
+//
+/**
+ SMM ready to lock notification event handler.
+
+ @param Protocol Points to the protocol's unique identifier
+ @param Interface Points to the interface instance
+ @param Handle The handle on which the interface was installed
+
+ @retval EFI_SUCCESS SmmReadyToLockCallback runs successfully
+
+**/
+EFI_STATUS
+EFIAPI
+SmmReadyToLockCallback (
+ IN CONST EFI_GUID *Protocol,
+ IN VOID *Interface,
+ IN EFI_HANDLE Handle
+ )
+{
+ mReadyToLock = TRUE;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ <b>PchSmiDispatcher SMM Module Entry Point</b>\n
+ - <b>Introduction</b>\n
+ The PchSmiDispatcher module is an SMM driver which provides SMI handler registration
+ services for PCH generated SMIs.
+
+ - <b>Details</b>\n
+ This module provides SMI handler registration servicies for PCH SMIs.
+ NOTE: All the register/unregister functions will be locked after SMM ready to boot signal event.
+ Please make sure no handler is installed after that.
+
+ - @pre
+ - EFI_SMM_BASE2_PROTOCOL
+ - Documented in the System Management Mode Core Interface Specification
+ - EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
+ - Documented in the UEFI 2.0 Specification and above
+ - EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
+ - This is to ensure that PCI MMIO and IO resource has been prepared and available for this driver to allocate.
+ - EFI_SMM_CPU_PROTOCOL
+
+ - @result
+ The PchSmiDispatcher driver produces:
+ - EFI_SMM_USB_DISPATCH2_PROTOCOL
+ - EFI_SMM_SX_DISPATCH2_PROTOCOL
+ - EFI_SMM_SW_DISPATCH2_PROTOCOL
+ - EFI_SMM_GPI_DISPATCH2_PROTOCOL
+ - EFI_SMM_IO_TRAP_DISPATCH2_PROTOCOL
+ - EFI_SMM_POWER_BUTTON_DISPATCH2_PROTOCOL
+ - EFI_SMM_PERIODIC_TIMER_DISPATCH2_PROTOCOL
+ - @link _PCH_SMM_IO_TRAP_CONTROL_PROTOCOL PCH_SMM_IO_TRAP_CONTROL_PROTOCOL @endlink
+ - @link _PCH_PCIE_SMI_DISPATCH_PROTOCOL PCH_PCIE_SMI_DISPATCH_PROTOCOL @endlink
+ - @link _PCH_TCO_SMI_DISPATCH_PROTOCOL PCH_TCO_SMI_DISPATCH_PROTOCOL @endlink
+ - @link _PCH_ACPI_SMI_DISPATCH_PROTOCOL PCH_ACPI_SMI_DISPATCH_PROTOCOL @endlink
+ - @link _PCH_SMI_DISPATCH_PROTOCOL PCH_SMI_DISPATCH_PROTOCOL @endlink
+ - @link _PCH_ESPI_SMI_DISPATCH_PROTOCOL PCH_ESPI_SMI_DISPATCH_PROTOCOL @endlink
+
+ @param[in] ImageHandle Pointer to the loaded image protocol for this driver
+ @param[in] SystemTable Pointer to the EFI System Table
+
+ @retval EFI_SUCCESS PchSmmDispatcher Initialization completed.
+**/
+EFI_STATUS
+EFIAPI
+InitializePchSmmDispatcher (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ VOID *SmmReadyToLockRegistration;
+
+ mS3SusStart = FALSE;
+ //
+ // Access ACPI Base Addresses Register
+ //
+
+ mAcpiBaseAddr = PmcGetAcpiBase ();
+ ASSERT (mAcpiBaseAddr != 0);
+
+ //
+ // Access TCO Base Addresses Register
+ //
+ PchTcoBaseGet (&mTcoBaseAddr);
+ ASSERT (mTcoBaseAddr != 0);
+
+ //
+ // Register a callback function to handle subsequent SMIs. This callback
+ // will be called by SmmCoreDispatcher.
+ //
+ Status = gSmst->SmiHandlerRegister (PchSmmCoreDispatcher, NULL, &mPrivateData.SmiHandle);
+ ASSERT_EFI_ERROR (Status);
+ //
+ // Initialize Callback DataBase
+ //
+ InitializeListHead (&mPrivateData.CallbackDataBase);
+
+ //
+ // Enable SMIs on the PCH now that we have a callback
+ //
+ PchSmmInitHardware ();
+
+ //
+ // Install and initialize all the needed protocols
+ //
+ PchSwDispatchInit ();
+ PchSmmPublishDispatchProtocols ();
+ InstallPchSmiDispatchProtocols ();
+ InstallIoTrap (ImageHandle);
+ InstallEspiSmi (ImageHandle);
+ InstallPchSmmPeriodicTimerControlProtocol (mPrivateData.InstallMultProtHandle);
+
+ //
+ // Register EFI_SMM_READY_TO_LOCK_PROTOCOL_GUID notify function.
+ //
+ Status = gSmst->SmmRegisterProtocolNotify (
+ &gEfiSmmReadyToLockProtocolGuid,
+ SmmReadyToLockCallback,
+ &SmmReadyToLockRegistration
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ The internal function used to create and insert a database record
+
+ @param[in] InsertRecord Record to insert to database.
+ @param[out] DispatchHandle Handle of dispatch function to register.
+
+ @retval EFI_INVALID_PARAMETER Error with NULL SMI source description
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate pool for database record
+ @retval EFI_SUCCESS The database record is created successfully.
+**/
+EFI_STATUS
+SmmCoreInsertRecord (
+ IN DATABASE_RECORD *NewRecord,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+ DATABASE_RECORD *Record;
+
+ if ((NewRecord == NULL) ||
+ (NewRecord->Signature != DATABASE_RECORD_SIGNATURE))
+ {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = gSmst->SmmAllocatePool (EfiRuntimeServicesData, sizeof (DATABASE_RECORD), (VOID **) &Record);
+ if (EFI_ERROR (Status)) {
+ ASSERT (FALSE);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ CopyMem (Record, NewRecord, sizeof (DATABASE_RECORD));
+
+ //
+ // After ensuring the source of event is not null, we will insert the record into the database
+ //
+ InsertTailList (&mPrivateData.CallbackDataBase, &Record->Link);
+
+ //
+ // Child's handle will be the address linked list link in the record
+ //
+ *DispatchHandle = (EFI_HANDLE) (&Record->Link);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Unregister a child SMI source dispatch function with a parent SMM driver
+
+ @param[in] This Protocol instance pointer.
+ @param[in] DispatchHandle Handle of dispatch function to deregister.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ unregistered and the SMI source has been disabled
+ if there are no other registered child dispatch
+ functions for this SMI source.
+ @retval EFI_INVALID_PARAMETER Handle is invalid.
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+**/
+EFI_STATUS
+EFIAPI
+PchPiSmmCoreUnRegister (
+ IN PCH_SMM_GENERIC_PROTOCOL *This,
+ IN EFI_HANDLE *DispatchHandle
+ )
+{
+ DATABASE_RECORD *RecordToDelete;
+ EFI_STATUS Status;
+ PCH_SMM_QUALIFIED_PROTOCOL *Qualified;
+
+ Qualified = QUALIFIED_PROTOCOL_FROM_GENERIC (This);
+ RecordToDelete = DATABASE_RECORD_FROM_LINK (DispatchHandle);
+ Status = PchSmmCoreUnRegister (NULL, DispatchHandle);
+ if (!EFI_ERROR (Status)) {
+ SmiHandlerProfileUnregisterHandler (
+ Qualified->Guid,
+ RecordToDelete->Callback,
+ &RecordToDelete->ChildContext,
+ RecordToDelete->ContextSize
+ );
+ }
+ return Status;
+}
+
+/**
+ Register a child SMI dispatch function with a parent SMM driver.
+
+ @param[in] This Pointer to the PCH_SMM_GENERIC_PROTOCOL instance.
+ @param[in] DispatchFunction Pointer to dispatch function to be invoked for this SMI source.
+ @param[in] DispatchContext Pointer to the dispatch function's context.
+ @param[out] DispatchHandle Handle of dispatch function, for when interfacing
+ with the parent SMM driver, will be the address of linked
+ list link in the call back record.
+
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create database record
+ @retval EFI_INVALID_PARAMETER The input parameter is invalid
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ registered and the SMI source has been enabled.
+**/
+EFI_STATUS
+EFIAPI
+PchPiSmmCoreRegister (
+ IN PCH_SMM_GENERIC_PROTOCOL *This,
+ IN EFI_SMM_HANDLER_ENTRY_POINT2 DispatchFunction,
+ IN PCH_SMM_CONTEXT *DispatchContext,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+ DATABASE_RECORD Record;
+ PCH_SMM_QUALIFIED_PROTOCOL *Qualified;
+ PCH_SMM_SOURCE_DESC NullSourceDesc;
+
+ //
+ // Initialize NullSourceDesc
+ //
+ NullInitSourceDesc (&NullSourceDesc);
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the EndOfDxe event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ ZeroMem (&Record, sizeof (DATABASE_RECORD));
+
+ //
+ // Gather information about the registration request
+ //
+ Record.Callback = DispatchFunction;
+
+ Qualified = QUALIFIED_PROTOCOL_FROM_GENERIC (This);
+
+ Record.ProtocolType = Qualified->Type;
+
+ Record.ContextFunctions = mContextFunctions[Qualified->Type];
+ //
+ // Perform linked list housekeeping
+ //
+ Record.Signature = DATABASE_RECORD_SIGNATURE;
+
+ switch (Qualified->Type) {
+ //
+ // By the end of this switch statement, we'll know the
+ // source description the child is registering for
+ //
+ case UsbType:
+ Record.ContextSize = sizeof (EFI_SMM_USB_REGISTER_CONTEXT);
+ CopyMem (&Record.ChildContext, DispatchContext, Record.ContextSize);
+ //
+ // Check the validity of Context Type
+ //
+ if ((Record.ChildContext.Usb.Type < UsbLegacy) || (Record.ChildContext.Usb.Type > UsbWake)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ MapUsbToSrcDesc (DispatchContext, &Record.SrcDesc);
+ Record.ClearSource = NULL;
+ //
+ // use default clear source function
+ //
+ break;
+
+ case SxType:
+ Record.ContextSize = sizeof (EFI_SMM_SX_REGISTER_CONTEXT);
+ CopyMem (&Record.ChildContext, DispatchContext, Record.ContextSize);
+ //
+ // Check the validity of Context Type and Phase
+ //
+ if ((Record.ChildContext.Sx.Type < SxS0) ||
+ (Record.ChildContext.Sx.Type >= EfiMaximumSleepType) ||
+ (Record.ChildContext.Sx.Phase < SxEntry) ||
+ (Record.ChildContext.Sx.Phase >= EfiMaximumPhase)
+ ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CopyMem (&Record.SrcDesc, &mSxSourceDesc, sizeof (PCH_SMM_SOURCE_DESC));
+ Record.ClearSource = NULL;
+ //
+ // use default clear source function
+ //
+ break;
+
+ case PowerButtonType:
+ Record.ContextSize = sizeof (EFI_SMM_POWER_BUTTON_REGISTER_CONTEXT);
+ CopyMem (&Record.ChildContext, DispatchContext, Record.ContextSize);
+ //
+ // Check the validity of Context Phase
+ //
+ if ((Record.ChildContext.PowerButton.Phase < EfiPowerButtonEntry) ||
+ (Record.ChildContext.PowerButton.Phase > EfiPowerButtonExit))
+ {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CopyMem (&Record.SrcDesc, &mPowerButtonSourceDesc, sizeof (PCH_SMM_SOURCE_DESC));
+ Record.ClearSource = NULL;
+ //
+ // use default clear source function
+ //
+ break;
+
+ case PeriodicTimerType:
+ Record.ContextSize = sizeof (EFI_SMM_PERIODIC_TIMER_REGISTER_CONTEXT);
+ CopyMem (&Record.ChildContext, DispatchContext, Record.ContextSize);
+ //
+ // Check the validity of timer value
+ //
+ if (DispatchContext->PeriodicTimer.SmiTickInterval <= 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ MapPeriodicTimerToSrcDesc (DispatchContext, &Record.SrcDesc);
+ Record.MiscData.TimerSmiEnabled = TRUE;
+ Record.ClearSource = PchSmmPeriodicTimerClearSource;
+ break;
+
+ default:
+ return EFI_INVALID_PARAMETER;
+ break;
+ }
+
+ if (CompareSources (&Record.SrcDesc, &NullSourceDesc)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // After ensuring the source of event is not null, we will insert the record into the database
+ // Child's handle will be the address linked list link in the record
+ //
+ Status = SmmCoreInsertRecord (
+ &Record,
+ DispatchHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ if (Record.ClearSource == NULL) {
+ //
+ // Clear the SMI associated w/ the source using the default function
+ //
+ PchSmmClearSource (&Record.SrcDesc);
+ } else {
+ //
+ // This source requires special handling to clear
+ //
+ Record.ClearSource (&Record.SrcDesc);
+ }
+
+ PchSmmEnableSource (&Record.SrcDesc);
+ SmiHandlerProfileRegisterHandler (
+ Qualified->Guid,
+ DispatchFunction,
+ (UINTN)RETURN_ADDRESS (0),
+ DispatchContext,
+ Record.ContextSize
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Unregister a child SMI source dispatch function with a parent SMM driver.
+
+ @param[in] This Pointer to the PCH_SMM_GENERIC_PROTOCOL instance.
+ @param[in] DispatchHandle Handle of dispatch function to deregister.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ unregistered and the SMI source has been disabled
+ if there are no other registered child dispatch
+ functions for this SMI source.
+ @retval EFI_INVALID_PARAMETER Handle is invalid.
+**/
+EFI_STATUS
+EFIAPI
+PchSmmCoreUnRegister (
+ IN PCH_SMM_GENERIC_PROTOCOL *This,
+ IN EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+ BOOLEAN NeedClearEnable;
+ UINTN DescIndex;
+ DATABASE_RECORD *RecordToDelete;
+ DATABASE_RECORD *RecordInDb;
+ LIST_ENTRY *LinkInDb;
+
+ if (DispatchHandle == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "UnRegister is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ RecordToDelete = DATABASE_RECORD_FROM_LINK (DispatchHandle);
+
+ //
+ // Take the entry out of the linked list
+ //
+ if (RecordToDelete->Link.ForwardLink == (LIST_ENTRY *) EFI_BAD_POINTER) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ RemoveEntryList (&RecordToDelete->Link);
+
+ //
+ // Loop through all the souces in record linked list to see if any source enable is equal.
+ // If any source enable is equal, we do not want to disable it.
+ //
+ for (DescIndex = 0; DescIndex < NUM_EN_BITS; ++DescIndex) {
+ if (IS_BIT_DESC_NULL (RecordToDelete->SrcDesc.En[DescIndex])) {
+ continue;
+ }
+ NeedClearEnable = TRUE;
+ LinkInDb = GetFirstNode (&mPrivateData.CallbackDataBase);
+ while (!IsNull (&mPrivateData.CallbackDataBase, LinkInDb)) {
+ RecordInDb = DATABASE_RECORD_FROM_LINK (LinkInDb);
+ if (IsBitEqualToAnySourceEn (&RecordToDelete->SrcDesc.En[DescIndex], &RecordInDb->SrcDesc)) {
+ NeedClearEnable = FALSE;
+ break;
+ }
+ LinkInDb = GetNextNode (&mPrivateData.CallbackDataBase, &RecordInDb->Link);
+ }
+ if (NeedClearEnable == FALSE) {
+ continue;
+ }
+ WriteBitDesc (&RecordToDelete->SrcDesc.En[DescIndex], 0, FALSE);
+ }
+ Status = gSmst->SmmFreePool (RecordToDelete);
+ if (EFI_ERROR (Status)) {
+ ASSERT (FALSE);
+ return Status;
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ This function clears the pending SMI status before set EOS.
+ NOTE: This only clears the pending SMI with known reason.
+ Please do not clear unknown pending SMI status since that will hide potential issues.
+
+ @param[in] SmiStsValue SMI status
+ @param[in] SciEn Sci Enable status
+**/
+STATIC
+VOID
+ClearPendingSmiStatus (
+ UINT32 SmiStsValue,
+ BOOLEAN SciEn
+ )
+{
+ //
+ // Clear NewCentury status if it's not handled.
+ //
+ if (SmiStsValue & B_ACPI_IO_SMI_STS_TCO) {
+ if (IoRead16 (mTcoBaseAddr + R_TCO_IO_TCO1_STS) & B_TCO_IO_TCO1_STS_NEWCENTURY) {
+ PchTcoSmiClearSourceAndBlock (&mSrcDescNewCentury);
+ }
+ }
+ // Clear PWRBTNOR_STS if it's not handled.
+ //
+ if (IoRead16 (mAcpiBaseAddr + R_ACPI_IO_PM1_STS) & B_ACPI_IO_PM1_STS_PRBTNOR) {
+ IoWrite16 (mAcpiBaseAddr + R_ACPI_IO_PM1_STS, B_ACPI_IO_PM1_STS_PRBTNOR);
+ }
+ //
+ // Clear WADT_STS if this is triggered by WADT timer.
+ //
+ if (!SciEn) {
+ if (IoRead32 (mAcpiBaseAddr + R_ACPI_IO_GPE0_STS_127_96) & B_ACPI_IO_GPE0_STS_127_96_WADT) {
+ IoWrite32 (mAcpiBaseAddr + R_ACPI_IO_GPE0_STS_127_96, B_ACPI_IO_GPE0_STS_127_96_WADT);
+ }
+ }
+ //
+ // Clear GPIO_UNLOCK_SMI_STS in case it is set as GPIO Unlock SMI is not supported
+ //
+ if (SmiStsValue & B_ACPI_IO_SMI_STS_GPIO_UNLOCK) {
+ IoWrite32 (mAcpiBaseAddr + R_ACPI_IO_SMI_STS, B_ACPI_IO_SMI_STS_GPIO_UNLOCK);
+ }
+}
+
+/**
+ The callback function to handle subsequent SMIs. This callback will be called by SmmCoreDispatcher.
+
+ @param[in] SmmImageHandle Not used
+ @param[in] PchSmmCore Not used
+ @param[in, out] CommunicationBuffer Not used
+ @param[in, out] SourceSize Not used
+
+ @retval EFI_SUCCESS Function successfully completed
+**/
+EFI_STATUS
+EFIAPI
+PchSmmCoreDispatcher (
+ IN EFI_HANDLE SmmImageHandle,
+ IN CONST VOID *PchSmmCore,
+ IN OUT VOID *CommunicationBuffer,
+ IN OUT UINTN *SourceSize
+ )
+{
+ //
+ // Used to prevent infinite loops
+ //
+ UINTN EscapeCount;
+
+ BOOLEAN ContextsMatch;
+ BOOLEAN EosSet;
+ BOOLEAN SxChildWasDispatched;
+
+ DATABASE_RECORD *RecordInDb;
+ LIST_ENTRY *LinkInDb;
+ DATABASE_RECORD *RecordToExhaust;
+ LIST_ENTRY *LinkToExhaust;
+
+ PCH_SMM_CONTEXT Context;
+ VOID *CommBuffer;
+ UINTN CommBufferSize;
+
+ EFI_STATUS Status;
+ BOOLEAN SciEn;
+ UINT32 SmiEnValue;
+ UINT32 SmiStsValue;
+ UINT8 Port74Save;
+ UINT8 Port76Save;
+
+ PCH_SMM_SOURCE_DESC ActiveSource;
+
+ //
+ // Initialize ActiveSource
+ //
+ NullInitSourceDesc (&ActiveSource);
+
+ EscapeCount = 3;
+ ContextsMatch = FALSE;
+ EosSet = FALSE;
+ SxChildWasDispatched = FALSE;
+ Status = EFI_SUCCESS;
+
+ //
+ // Save IO index registers
+ // @note: Save/Restore port 70h directly might break NMI_EN# setting,
+ // then save/restore 74h/76h instead.
+ // @note: CF8 is not saved. Prefer method is to use MMIO instead of CF8
+ //
+ Port76Save = IoRead8 (R_RTC_IO_EXT_INDEX_ALT);
+ Port74Save = IoRead8 (R_RTC_IO_INDEX_ALT);
+
+ if (!IsListEmpty (&mPrivateData.CallbackDataBase)) {
+ //
+ // We have children registered w/ us -- continue
+ //
+ while ((!EosSet) && (EscapeCount > 0)) {
+ EscapeCount--;
+
+ LinkInDb = GetFirstNode (&mPrivateData.CallbackDataBase);
+
+ //
+ // Cache SciEn, SmiEnValue and SmiStsValue to determine if source is active
+ //
+ SciEn = PchSmmGetSciEn ();
+ SmiEnValue = IoRead32 ((UINTN) (mAcpiBaseAddr + R_ACPI_IO_SMI_EN));
+ SmiStsValue = IoRead32 ((UINTN) (mAcpiBaseAddr + R_ACPI_IO_SMI_STS));
+
+ while (!IsNull (&mPrivateData.CallbackDataBase, LinkInDb)) {
+ RecordInDb = DATABASE_RECORD_FROM_LINK (LinkInDb);
+
+ //
+ // look for the first active source
+ //
+ if (!SourceIsActive (&RecordInDb->SrcDesc, SciEn, SmiEnValue, SmiStsValue)) {
+ //
+ // Didn't find the source yet, keep looking
+ //
+ LinkInDb = GetNextNode (&mPrivateData.CallbackDataBase, &RecordInDb->Link);
+
+ //
+ // if it's the last one, try to clear EOS
+ //
+ if (IsNull (&mPrivateData.CallbackDataBase, LinkInDb)) {
+ //
+ // Clear pending SMI status before EOS
+ //
+ ClearPendingSmiStatus (SmiStsValue, SciEn);
+ EosSet = PchSmmSetAndCheckEos ();
+ }
+ } else {
+ //
+ // We found a source. If this is a sleep type, we have to go to
+ // appropriate sleep state anyway.No matter there is sleep child or not
+ //
+ if (RecordInDb->ProtocolType == SxType) {
+ SxChildWasDispatched = TRUE;
+ }
+ //
+ // "cache" the source description and don't query I/O anymore
+ //
+ CopyMem ((VOID *) &ActiveSource, (VOID *) &(RecordInDb->SrcDesc), sizeof (PCH_SMM_SOURCE_DESC));
+ LinkToExhaust = LinkInDb;
+
+ //
+ // exhaust the rest of the queue looking for the same source
+ //
+ while (!IsNull (&mPrivateData.CallbackDataBase, LinkToExhaust)) {
+ RecordToExhaust = DATABASE_RECORD_FROM_LINK (LinkToExhaust);
+ //
+ // RecordToExhaust->Link might be removed (unregistered) by Callback function, and then the
+ // system will hang in ASSERT() while calling GetNextNode().
+ // To prevent the issue, we need to get next record in DB here (before Callback function).
+ //
+ LinkToExhaust = GetNextNode (&mPrivateData.CallbackDataBase, &RecordToExhaust->Link);
+
+ if (CompareSources (&RecordToExhaust->SrcDesc, &ActiveSource)) {
+ //
+ // These source descriptions are equal, so this callback should be
+ // dispatched.
+ //
+ if (RecordToExhaust->ContextFunctions.GetContext != NULL) {
+ //
+ // This child requires that we get a calling context from
+ // hardware and compare that context to the one supplied
+ // by the child.
+ //
+ ASSERT (RecordToExhaust->ContextFunctions.CmpContext != NULL);
+
+ //
+ // Make sure contexts match before dispatching event to child
+ //
+ RecordToExhaust->ContextFunctions.GetContext (RecordToExhaust, &Context);
+ ContextsMatch = RecordToExhaust->ContextFunctions.CmpContext (&Context, &RecordToExhaust->ChildContext);
+
+ } else {
+ //
+ // This child doesn't require any more calling context beyond what
+ // it supplied in registration. Simply pass back what it gave us.
+ //
+ Context = RecordToExhaust->ChildContext;
+ ContextsMatch = TRUE;
+ }
+
+ if (ContextsMatch) {
+ if (RecordToExhaust->ProtocolType == PchSmiDispatchType) {
+ //
+ // For PCH SMI dispatch protocols
+ //
+ PchSmiTypeCallbackDispatcher (RecordToExhaust);
+ } else {
+ if ((RecordToExhaust->ProtocolType == SxType) && (Context.Sx.Type == SxS3) && (Context.Sx.Phase == SxEntry) && !mS3SusStart) {
+ REPORT_STATUS_CODE (EFI_PROGRESS_CODE, PROGRESS_CODE_S3_SUSPEND_START);
+ mS3SusStart = TRUE;
+ }
+ //
+ // For EFI standard SMI dispatch protocols
+ //
+ if (RecordToExhaust->Callback != NULL) {
+ if (RecordToExhaust->ContextFunctions.GetCommBuffer != NULL) {
+ //
+ // This callback function needs CommBuffer and CommBufferSize.
+ // Get those from child and then pass to callback function.
+ //
+ RecordToExhaust->ContextFunctions.GetCommBuffer (RecordToExhaust, &CommBuffer, &CommBufferSize);
+ } else {
+ //
+ // Child doesn't support the CommBuffer and CommBufferSize.
+ // Just pass NULL value to callback function.
+ //
+ CommBuffer = NULL;
+ CommBufferSize = 0;
+ }
+
+ PERF_START_EX (NULL, "SmmFunction", NULL, AsmReadTsc (), RecordToExhaust->ProtocolType);
+ RecordToExhaust->Callback ((EFI_HANDLE) & RecordToExhaust->Link, &Context, CommBuffer, &CommBufferSize);
+ PERF_END_EX (NULL, "SmmFunction", NULL, AsmReadTsc (), RecordToExhaust->ProtocolType);
+ if (RecordToExhaust->ProtocolType == SxType) {
+ SxChildWasDispatched = TRUE;
+ }
+ } else {
+ ASSERT (FALSE);
+ }
+ }
+ }
+ }
+ }
+
+ if (RecordInDb->ClearSource == NULL) {
+ //
+ // Clear the SMI associated w/ the source using the default function
+ //
+ PchSmmClearSource (&ActiveSource);
+ } else {
+ //
+ // This source requires special handling to clear
+ //
+ RecordInDb->ClearSource (&ActiveSource);
+ }
+ //
+ // Clear pending SMI status before EOS
+ //
+ ClearPendingSmiStatus (SmiStsValue, SciEn);
+ //
+ // Also, try to clear EOS
+ //
+ EosSet = PchSmmSetAndCheckEos ();
+ //
+ // Queue is empty, reset the search
+ //
+ break;
+ }
+ }
+ }
+ }
+ //
+ // If you arrive here, there are two possible reasons:
+ // (1) you've got problems with clearing the SMI status bits in the
+ // ACPI table. If you don't properly clear the SMI bits, then you won't be able to set the
+ // EOS bit. If this happens too many times, the loop exits.
+ // (2) there was a SMM communicate for callback messages that was received prior
+ // to this driver.
+ // If there is an asynchronous SMI that occurs while processing the Callback, let
+ // all of the drivers (including this one) have an opportunity to scan for the SMI
+ // and handle it.
+ // If not, we don't want to exit and have the foreground app. clear EOS without letting
+ // these other sources get serviced.
+ //
+ // This assert is not valid with CSM legacy solution because it generates software SMI
+ // to test for legacy USB support presence.
+ // This may not be illegal, so we cannot assert at this time.
+ //
+ // ASSERT (EscapeCount > 0);
+ //
+ if (SxChildWasDispatched) {
+ //
+ // A child of the SmmSxDispatch protocol was dispatched during this call;
+ // put the system to sleep.
+ //
+ PchSmmSxGoToSleep ();
+ }
+ //
+ // Restore IO index registers
+ // @note: Save/Restore port 70h directly might break NMI_EN# setting,
+ // then save/restore 74h/76h instead.
+ //
+ IoWrite8 (R_RTC_IO_EXT_INDEX_ALT, Port76Save);
+ IoWrite8 (R_RTC_IO_INDEX_ALT, Port74Save);
+
+ return Status;
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmEspi.c b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmEspi.c
new file mode 100644
index 0000000000..9ce4072e37
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmEspi.c
@@ -0,0 +1,1588 @@
+/** @file
+ eSPI SMI implementation
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "PchSmmEspi.h"
+#include <Library/PmcPrivateLib.h>
+#include <Library/EspiLib.h>
+#include <Library/SmiHandlerProfileLib.h>
+#include <Register/PchRegs.h>
+#include <Register/PchPcrRegs.h>
+#include <Register/PchRegsLpc.h>
+#include <Library/PchPciBdfLib.h>
+#include <PchBdfAssignment.h>
+
+GLOBAL_REMOVE_IF_UNREFERENCED ESPI_SMI_INSTANCE mEspiSmiInstance = {
+ //
+ // Signature
+ //
+ ESPI_SMI_INSTANCE_SIGNATURE,
+ //
+ // Handle
+ //
+ NULL,
+ //
+ // PchEspiSmiDispatchProtocol
+ //
+ {
+ PCH_ESPI_SMI_DISPATCH_REVISION,
+ EspiSmiUnRegister,
+ BiosWrProtectRegister,
+ BiosWrReportRegister,
+ PcNonFatalErrRegister,
+ PcFatalErrRegister,
+ VwNonFatalErrRegister,
+ VwFatalErrRegister,
+ FlashNonFatalErrRegister,
+ FlashFatalErrRegister,
+ LnkType1ErrRegister,
+ EspiSlaveSmiRegister
+ },
+ //
+ // PchSmiEspiHandle[EspiTopLevelTypeMax]
+ //
+ {
+ NULL, NULL, NULL
+ },
+ //
+ // CallbackDataBase[EspiSmiTypeMax]
+ //
+ {
+ {NULL, NULL}, {NULL, NULL}, {NULL, NULL}, {NULL, NULL}, {NULL, NULL},
+ {NULL, NULL}, {NULL, NULL}, {NULL, NULL}, {NULL, NULL}, {NULL, NULL}
+ },
+ //
+ // EspiSmiEventCounter[EspiSmiTypeMax]
+ //
+ {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ },
+ //
+ // Barrier[EspiTopLevelTypeMax]
+ //
+ {
+ {
+ BiosWrProtect,
+ BiosWrProtect
+ },
+ {
+ BiosWrReport,
+ LnkType1Err
+ },
+ {
+ EspiSlaveSmi,
+ EspiSlaveSmi
+ }
+ }
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST ESPI_DESCRIPTOR mEspiDescriptor[EspiSmiTypeMax] = {
+ //
+ // BiosWrProtect
+ //
+ {
+ {
+ PCIE_ADDR_TYPE,
+ { (
+ (DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
+ (PCI_DEVICE_NUMBER_PCH_LPC << 19) |
+ (PCI_FUNCTION_NUMBER_PCH_LPC << 16) |
+ R_ESPI_CFG_PCBC
+ ) }
+ },
+ //
+ // SourceIsActiveAndMask and SourceIsActiveValue
+ //
+ B_ESPI_CFG_PCBC_BWPDS | B_ESPI_CFG_PCBC_LE,
+ B_ESPI_CFG_PCBC_BWPDS | B_ESPI_CFG_PCBC_LE,
+ //
+ // ClearStatusAndMask and ClearStatusOrMask
+ //
+ (UINT32) ~B_ESPI_CFG_PCBC_BWRS,
+ B_ESPI_CFG_PCBC_BWPDS
+ },
+ //
+ // BiosWrReport
+ //
+ {
+ {
+ PCIE_ADDR_TYPE,
+ { (
+ (DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
+ (PCI_DEVICE_NUMBER_PCH_LPC << 19) |
+ (PCI_FUNCTION_NUMBER_PCH_LPC << 16) |
+ R_ESPI_CFG_PCBC
+ ) }
+ },
+ B_ESPI_CFG_PCBC_BWRS | B_ESPI_CFG_PCBC_BWRE,
+ B_ESPI_CFG_PCBC_BWRS | B_ESPI_CFG_PCBC_BWRE,
+ (UINT32) ~B_ESPI_CFG_PCBC_BWPDS,
+ B_ESPI_CFG_PCBC_BWRS
+ },
+ //
+ // PcNonFatalErr
+ //
+ {
+ {
+ PCR_ADDR_TYPE,
+ {PCH_PCR_ADDRESS (PID_ESPISPI, R_ESPI_PCR_PCERR_SLV0) }
+ },
+ (B_ESPI_PCR_XERR_XNFES | B_ESPI_PCR_XERR_XNFEE),
+ (B_ESPI_PCR_XERR_XNFES | (V_ESPI_PCR_XERR_XNFEE_SMI << N_ESPI_PCR_XERR_XNFEE)),
+ (UINT32) ~(B_ESPI_PCR_PCERR_SLV0_PCURD | B_ESPI_PCR_XERR_XFES),
+ B_ESPI_PCR_XERR_XNFES
+ },
+ //
+ // PcFatalErr
+ //
+ {
+ {
+ PCR_ADDR_TYPE,
+ {PCH_PCR_ADDRESS (PID_ESPISPI, R_ESPI_PCR_PCERR_SLV0) }
+ },
+ (B_ESPI_PCR_XERR_XFES | B_ESPI_PCR_XERR_XFEE),
+ (B_ESPI_PCR_XERR_XFES | (V_ESPI_PCR_XERR_XFEE_SMI << N_ESPI_PCR_XERR_XFEE)),
+ (UINT32) ~(B_ESPI_PCR_PCERR_SLV0_PCURD | B_ESPI_PCR_XERR_XNFES),
+ B_ESPI_PCR_XERR_XFES
+ },
+ //
+ // VwNonFatalErr
+ //
+ {
+ {
+ PCR_ADDR_TYPE,
+ {PCH_PCR_ADDRESS (PID_ESPISPI, R_ESPI_PCR_VWERR_SLV0) }
+ },
+ (B_ESPI_PCR_XERR_XNFES | B_ESPI_PCR_XERR_XNFEE),
+ (B_ESPI_PCR_XERR_XNFES | (V_ESPI_PCR_XERR_XNFEE_SMI << N_ESPI_PCR_XERR_XNFEE)),
+ (UINT32) ~B_ESPI_PCR_XERR_XFES,
+ B_ESPI_PCR_XERR_XNFES
+ },
+ //
+ // VwFatalErr
+ //
+ {
+ {
+ PCR_ADDR_TYPE,
+ {PCH_PCR_ADDRESS (PID_ESPISPI, R_ESPI_PCR_VWERR_SLV0) }
+ },
+ (B_ESPI_PCR_XERR_XFES | B_ESPI_PCR_XERR_XFEE),
+ (B_ESPI_PCR_XERR_XFES | (V_ESPI_PCR_XERR_XFEE_SMI << N_ESPI_PCR_XERR_XFEE)),
+ (UINT32) ~B_ESPI_PCR_XERR_XNFES,
+ B_ESPI_PCR_XERR_XFES
+ },
+ //
+ // FlashNonFatalErr
+ //
+ {
+ {
+ PCR_ADDR_TYPE,
+ {PCH_PCR_ADDRESS (PID_ESPISPI, R_ESPI_PCR_FCERR_SLV0) }
+ },
+ (B_ESPI_PCR_XERR_XNFES | B_ESPI_PCR_XERR_XNFEE),
+ (B_ESPI_PCR_XERR_XNFES | (V_ESPI_PCR_XERR_XNFEE_SMI << N_ESPI_PCR_XERR_XNFEE)),
+ (UINT32) ~B_ESPI_PCR_XERR_XFES,
+ B_ESPI_PCR_XERR_XNFES
+ },
+ //
+ // FlashFatalErr
+ //
+ {
+ {
+ PCR_ADDR_TYPE,
+ {PCH_PCR_ADDRESS (PID_ESPISPI, R_ESPI_PCR_FCERR_SLV0) }
+ },
+ (B_ESPI_PCR_XERR_XFES | B_ESPI_PCR_XERR_XFEE),
+ (B_ESPI_PCR_XERR_XFES | (V_ESPI_PCR_XERR_XFEE_SMI << N_ESPI_PCR_XERR_XFEE)),
+ (UINT32) ~B_ESPI_PCR_XERR_XNFES,
+ B_ESPI_PCR_XERR_XFES
+ },
+ //
+ // LnkType1Err
+ //
+ {
+ {
+ PCR_ADDR_TYPE,
+ {PCH_PCR_ADDRESS (PID_ESPISPI, R_ESPI_PCR_LNKERR_SLV0) }
+ },
+ B_ESPI_PCR_LNKERR_SLV0_LFET1S | B_ESPI_PCR_LNKERR_SLV0_LFET1E,
+ B_ESPI_PCR_LNKERR_SLV0_LFET1S | (V_ESPI_PCR_LNKERR_SLV0_LFET1E_SMI << N_ESPI_PCR_LNKERR_SLV0_LFET1E),
+ (UINT32) ~B_ESPI_PCR_LNKERR_SLV0_SLCRR,
+ B_ESPI_PCR_LNKERR_SLV0_LFET1S
+ },
+};
+
+/**
+ Enable eSPI SMI source
+
+ @param[in] EspiSmiType Type based on ESPI_SMI_TYPE
+**/
+STATIC
+VOID
+EspiSmiEnableSource (
+ IN CONST ESPI_SMI_TYPE EspiSmiType
+ )
+{
+ UINT64 PciBaseAddress;
+
+ switch (EspiSmiType) {
+ case BiosWrProtect:
+ //
+ // It doesn't enable the BIOSLOCK here. Enable it by policy in DXE.
+ //
+ break;
+ case BiosWrReport:
+ PciBaseAddress = EspiPciCfgBase ();
+ PciSegmentAndThenOr32 (
+ PciBaseAddress + R_ESPI_CFG_PCBC,
+ (UINT32) ~(B_ESPI_CFG_PCBC_BWRS | B_ESPI_CFG_PCBC_BWPDS),
+ B_ESPI_CFG_PCBC_BWRE
+ );
+ break;
+ case PcNonFatalErr:
+ PchPcrAndThenOr32 (
+ PID_ESPISPI,
+ (UINT16) R_ESPI_PCR_PCERR_SLV0,
+ (UINT32) ~(B_ESPI_PCR_PCERR_SLV0_PCURD | B_ESPI_PCR_XERR_XNFES | B_ESPI_PCR_XERR_XFES),
+ B_ESPI_PCR_XERR_XNFEE
+ );
+ break;
+
+ case PcFatalErr:
+ PchPcrAndThenOr32 (
+ PID_ESPISPI,
+ (UINT16) R_ESPI_PCR_PCERR_SLV0,
+ (UINT32) ~(B_ESPI_PCR_PCERR_SLV0_PCURD | B_ESPI_PCR_XERR_XNFES | B_ESPI_PCR_XERR_XFES),
+ B_ESPI_PCR_XERR_XFEE
+ );
+ break;
+
+ case VwNonFatalErr:
+ PchPcrAndThenOr32 (
+ PID_ESPISPI,
+ (UINT16) R_ESPI_PCR_VWERR_SLV0,
+ (UINT32) ~(B_ESPI_PCR_XERR_XNFES | B_ESPI_PCR_XERR_XFES),
+ B_ESPI_PCR_XERR_XNFEE
+ );
+ break;
+
+ case VwFatalErr:
+ PchPcrAndThenOr32 (
+ PID_ESPISPI,
+ (UINT16) R_ESPI_PCR_VWERR_SLV0,
+ (UINT32) ~(B_ESPI_PCR_XERR_XNFES | B_ESPI_PCR_XERR_XFES),
+ B_ESPI_PCR_XERR_XFEE
+ );
+ break;
+
+ case FlashNonFatalErr:
+ PchPcrAndThenOr32 (
+ PID_ESPISPI,
+ (UINT16) R_ESPI_PCR_FCERR_SLV0,
+ (UINT32) ~(B_ESPI_PCR_XERR_XNFES | B_ESPI_PCR_XERR_XFES),
+ B_ESPI_PCR_XERR_XNFEE
+ );
+ break;
+
+ case FlashFatalErr:
+ PchPcrAndThenOr32 (
+ PID_ESPISPI,
+ (UINT16) R_ESPI_PCR_FCERR_SLV0,
+ (UINT32) ~(B_ESPI_PCR_XERR_XNFES | B_ESPI_PCR_XERR_XFES),
+ B_ESPI_PCR_XERR_XFEE
+ );
+ break;
+
+ case LnkType1Err:
+ PchPcrAndThenOr32 (
+ PID_ESPISPI,
+ (UINT16) R_ESPI_PCR_LNKERR_SLV0,
+ (UINT32) ~(B_ESPI_PCR_LNKERR_SLV0_SLCRR | B_ESPI_PCR_LNKERR_SLV0_LFET1S),
+ (UINT32) (V_ESPI_PCR_LNKERR_SLV0_LFET1E_SMI << N_ESPI_PCR_LNKERR_SLV0_LFET1E)
+ );
+
+ if (IsEspiSecondSlaveSupported ()) {
+ PchPcrAndThenOr32 (
+ PID_ESPISPI,
+ (UINT16) R_ESPI_PCR_LNKERR_SLV1,
+ (UINT32) ~(B_ESPI_PCR_LNKERR_SLV0_SLCRR | B_ESPI_PCR_LNKERR_SLV0_LFET1S),
+ (UINT32) (V_ESPI_PCR_LNKERR_SLV0_LFET1E_SMI << N_ESPI_PCR_LNKERR_SLV0_LFET1E)
+ );
+ }
+ break;
+
+ default:
+ DEBUG ((DEBUG_ERROR, "Unsupported EspiSmiType \n"));
+ ASSERT (FALSE);
+ break;
+ }
+}
+
+
+/**
+ Disable eSPI SMI source
+
+ @param[in] EspiSmiType Type based on ESPI_SMI_TYPE
+**/
+STATIC
+VOID
+EspiSmiDisableSource (
+ IN CONST ESPI_SMI_TYPE EspiSmiType
+ )
+{
+
+ switch (EspiSmiType) {
+ case BiosWrProtect:
+ case BiosWrReport:
+ DEBUG ((DEBUG_ERROR, "Bit is write lock, thus BWRE/BWPDS source cannot be disabled \n"));
+ ASSERT (FALSE);
+ break;
+ case PcNonFatalErr:
+ PchPcrAndThenOr32 (
+ PID_ESPISPI,
+ (UINT16) R_ESPI_PCR_PCERR_SLV0,
+ (UINT32) ~(B_ESPI_PCR_PCERR_SLV0_PCURD | B_ESPI_PCR_XERR_XNFES | B_ESPI_PCR_XERR_XFES | B_ESPI_PCR_XERR_XNFEE),
+ 0
+ );
+ break;
+
+ case PcFatalErr:
+ PchPcrAndThenOr32 (
+ PID_ESPISPI,
+ (UINT16) R_ESPI_PCR_PCERR_SLV0,
+ (UINT32) ~(B_ESPI_PCR_PCERR_SLV0_PCURD | B_ESPI_PCR_XERR_XNFES | B_ESPI_PCR_XERR_XFES | B_ESPI_PCR_XERR_XFEE),
+ 0
+ );
+ break;
+
+ case VwNonFatalErr:
+ PchPcrAndThenOr32 (
+ PID_ESPISPI,
+ (UINT16) R_ESPI_PCR_VWERR_SLV0,
+ (UINT32) ~(B_ESPI_PCR_XERR_XNFES | B_ESPI_PCR_XERR_XFES | B_ESPI_PCR_XERR_XNFEE),
+ 0
+ );
+ break;
+
+ case VwFatalErr:
+ PchPcrAndThenOr32 (
+ PID_ESPISPI,
+ (UINT16) R_ESPI_PCR_VWERR_SLV0,
+ (UINT32) ~(B_ESPI_PCR_XERR_XNFES | B_ESPI_PCR_XERR_XFES | B_ESPI_PCR_XERR_XFEE),
+ 0
+ );
+ break;
+
+ case FlashNonFatalErr:
+ PchPcrAndThenOr32 (
+ PID_ESPISPI,
+ (UINT16) R_ESPI_PCR_FCERR_SLV0,
+ (UINT32) ~(B_ESPI_PCR_XERR_XNFES | B_ESPI_PCR_XERR_XFES | B_ESPI_PCR_XERR_XNFEE),
+ 0
+ );
+ break;
+
+ case FlashFatalErr:
+ PchPcrAndThenOr32 (
+ PID_ESPISPI,
+ (UINT16) R_ESPI_PCR_FCERR_SLV0,
+ (UINT32) ~(B_ESPI_PCR_XERR_XNFES | B_ESPI_PCR_XERR_XFES | B_ESPI_PCR_XERR_XFEE),
+ 0
+ );
+ break;
+
+ case LnkType1Err:
+ PchPcrAndThenOr32 (
+ PID_ESPISPI,
+ (UINT16) R_ESPI_PCR_LNKERR_SLV0,
+ (UINT32) ~(B_ESPI_PCR_LNKERR_SLV0_SLCRR | B_ESPI_PCR_LNKERR_SLV0_LFET1S),
+ 0
+ );
+
+ if (IsEspiSecondSlaveSupported ()) {
+ PchPcrAndThenOr32 (
+ PID_ESPISPI,
+ (UINT16) R_ESPI_PCR_LNKERR_SLV1,
+ (UINT32) ~(B_ESPI_PCR_LNKERR_SLV0_SLCRR | B_ESPI_PCR_LNKERR_SLV0_LFET1S),
+ 0
+ );
+ }
+ break;
+
+ default:
+ DEBUG ((DEBUG_ERROR, "Unsupported EspiSmiType \n"));
+ ASSERT (FALSE);
+ break;
+ }
+}
+
+/**
+ Clear a status for the SMI event
+
+ @param[in] EspiSmiType Type based on ESPI_SMI_TYPE
+**/
+STATIC
+VOID
+EspiSmiClearStatus (
+ IN CONST ESPI_SMI_TYPE EspiSmiType
+ )
+{
+ UINT32 PciBus;
+ UINT32 PciDev;
+ UINT32 PciFun;
+ UINT32 PciReg;
+ UINT64 PciBaseAddress;
+ CONST ESPI_DESCRIPTOR *Desc;
+
+ Desc = &mEspiDescriptor[EspiSmiType];
+
+ switch (Desc->Address.Type) {
+ case PCIE_ADDR_TYPE:
+ PciBus = Desc->Address.Data.pcie.Fields.Bus;
+ PciDev = Desc->Address.Data.pcie.Fields.Dev;
+ PciFun = Desc->Address.Data.pcie.Fields.Fnc;
+ PciReg = Desc->Address.Data.pcie.Fields.Reg;
+ PciBaseAddress = PCI_SEGMENT_LIB_ADDRESS (DEFAULT_PCI_SEGMENT_NUMBER_PCH, PciBus, PciDev, PciFun, 0);
+ PciSegmentAndThenOr32 (PciBaseAddress + PciReg, Desc->ClearStatusAndMask, Desc->ClearStatusOrMask);
+ break;
+ case PCR_ADDR_TYPE:
+ PchPcrAndThenOr32 (
+ Desc->Address.Data.Pcr.Fields.Pid,
+ Desc->Address.Data.Pcr.Fields.Offset,
+ Desc->ClearStatusAndMask,
+ Desc->ClearStatusOrMask
+ );
+ break;
+ default:
+ DEBUG ((DEBUG_ERROR, "Address type for eSPI SMI is invalid \n"));
+ ASSERT (FALSE);
+ break;
+ }
+}
+
+/**
+ Checks if a source is active by looking at the enable and status bits
+
+ @param[in] EspiSmiType Type based on ESPI_SMI_TYPE
+**/
+STATIC
+BOOLEAN
+EspiSmiSourceIsActive (
+ IN CONST ESPI_SMI_TYPE EspiSmiType
+ )
+{
+ BOOLEAN Active;
+ UINT32 PciBus;
+ UINT32 PciDev;
+ UINT32 PciFun;
+ UINT32 PciReg;
+ UINT64 PciBaseAddress;
+ UINT32 Data32;
+ CONST ESPI_DESCRIPTOR *Desc;
+
+ Desc = &mEspiDescriptor[EspiSmiType];
+
+ Active = FALSE;
+ switch (Desc->Address.Type) {
+ case PCIE_ADDR_TYPE:
+ PciBus = Desc->Address.Data.pcie.Fields.Bus;
+ PciDev = Desc->Address.Data.pcie.Fields.Dev;
+ PciFun = Desc->Address.Data.pcie.Fields.Fnc;
+ PciReg = Desc->Address.Data.pcie.Fields.Reg;
+ PciBaseAddress = PCI_SEGMENT_LIB_ADDRESS (DEFAULT_PCI_SEGMENT_NUMBER_PCH, PciBus, PciDev, PciFun, 0);
+ Data32 = PciSegmentRead32 (PciBaseAddress + PciReg);
+ break;
+
+ case PCR_ADDR_TYPE:
+ Data32 = PchPcrRead32 (
+ Desc->Address.Data.Pcr.Fields.Pid,
+ Desc->Address.Data.Pcr.Fields.Offset
+ );
+ break;
+
+ default:
+ Data32 = 0;
+ DEBUG ((DEBUG_ERROR, "Address type for eSPI SMI is invalid \n"));
+ ASSERT (FALSE);
+ break;
+ }
+
+ if ((Data32 & Desc->SourceIsActiveAndMask) == Desc->SourceIsActiveValue) {
+ Active = TRUE;
+ }
+
+ return Active;
+}
+
+/**
+ Insert a handler into the corresponding linked list based on EspiSmiType
+
+ @param[in] DispatchFunction The callback to execute
+ @param[in] EspiSmiType Type based on ESPI_SMI_TYPE to determine which linked list to use
+ @param[out] DispatchHandle The link to the record in the database
+
+ @retval EFI_SUCCESS Record was successfully inserted into master database
+ @retval EFI_OUT_OF_RESOURCES Cannot allocate pool to insert record
+**/
+STATIC
+EFI_STATUS
+InsertEspiRecord (
+ IN PCH_ESPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ IN ESPI_SMI_TYPE EspiSmiType,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+ ESPI_SMI_RECORD *Record;
+
+ Status = gSmst->SmmAllocatePool (EfiRuntimeServicesData, sizeof (ESPI_SMI_RECORD), (VOID **) &Record);
+ if (EFI_ERROR (Status)) {
+ ASSERT (FALSE);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ SetMem (Record, sizeof (ESPI_SMI_RECORD), 0);
+
+ Record->Callback = DispatchFunction;
+ Record->Signature = ESPI_SMI_RECORD_SIGNATURE;
+
+ InsertTailList (&mEspiSmiInstance.CallbackDataBase[EspiSmiType], &Record->Link);
+ EspiSmiClearStatus (EspiSmiType);
+ EspiSmiEnableSource (EspiSmiType);
+
+ ++mEspiSmiInstance.EspiSmiEventCounter[EspiSmiType];
+
+ *DispatchHandle = (EFI_HANDLE) (&Record->Link);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This callback is registered to PchSmiDispatch
+
+ @param[in] DispatchHandle Used to determine which source have been triggered
+**/
+VOID
+EspiSmiCallback (
+ IN EFI_HANDLE DispatchHandle
+ )
+{
+ DATABASE_RECORD *PchSmiRecord;
+ ESPI_TOP_LEVEL_TYPE EspiTopLevelType;
+ ESPI_SMI_TYPE EspiSmiType;
+ ESPI_SMI_RECORD *RecordInDb;
+ LIST_ENTRY *LinkInDb;
+
+ PchSmiRecord = DATABASE_RECORD_FROM_LINK (DispatchHandle);
+
+ if (PchSmiRecord->PchSmiType == PchTcoSmiLpcBiosWpType) {
+ EspiTopLevelType = EspiBiosWrProtect;
+ } else if (PchSmiRecord->PchSmiType == PchSmiSerialIrqType) {
+ EspiTopLevelType = EspiSerialIrq;
+ } else {
+ DEBUG ((DEBUG_ERROR, "EspiSmiCallback was dispatched with a wrong DispatchHandle"));
+ ASSERT (FALSE);
+ return;
+ }
+
+ for (EspiSmiType = mEspiSmiInstance.Barrier[EspiTopLevelType].Start; EspiSmiType <= mEspiSmiInstance.Barrier[EspiTopLevelType].End; ++EspiSmiType) {
+ if (!EspiSmiSourceIsActive (EspiSmiType)) {
+ continue;
+ }
+ //
+ // The source is active, so walk the callback database and dispatch
+ //
+ if (!IsListEmpty (&mEspiSmiInstance.CallbackDataBase[EspiSmiType])) {
+ //
+ // We have children registered w/ us -- continue
+ //
+ LinkInDb = GetFirstNode (&mEspiSmiInstance.CallbackDataBase[EspiSmiType]);
+
+ while (!IsNull (&mEspiSmiInstance.CallbackDataBase[EspiSmiType], LinkInDb)) {
+ RecordInDb = ESPI_RECORD_FROM_LINK (LinkInDb);
+
+ //
+ // RecordInDb->Link might be removed (unregistered) by Callback function, and then the
+ // system will hang in ASSERT() while calling GetNextNode().
+ // To prevent the issue, we need to get next record in DB here (before Callback function).
+ //
+ LinkInDb = GetNextNode (&mEspiSmiInstance.CallbackDataBase[EspiSmiType], &RecordInDb->Link);
+
+ //
+ // Callback
+ //
+ if (RecordInDb->Callback != NULL) {
+ RecordInDb->Callback ((EFI_HANDLE) &RecordInDb->Link);
+ } else {
+ ASSERT (FALSE);
+ }
+ }
+ } else if (EspiSmiType == LnkType1Err) {
+ //
+ // If no proper handler registered for Link Type 1 Error
+ // Call default SMI handler recover otherwise
+ //
+ EspiDefaultFatalErrorHandler ();
+ }
+
+ //
+ // Finish walking the linked list for the EspiSmiType, so clear status
+ //
+ EspiSmiClearStatus (EspiSmiType);
+ }
+}
+
+//
+// EspiBiosWp srcdesc
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescEspiBiosWp = {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_ACPI_IO_SMI_EN}
+ },
+ S_ACPI_IO_SMI_EN,
+ N_ACPI_IO_SMI_EN_TCO
+ },
+ {
+ {
+ PCIE_ADDR_TYPE,
+ { (
+ (DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
+ (PCI_DEVICE_NUMBER_PCH_LPC << 19) |
+ (PCI_FUNCTION_NUMBER_PCH_LPC << 16) |
+ R_ESPI_CFG_PCBC
+ ) }
+ },
+ S_ESPI_CFG_PCBC,
+ N_ESPI_CFG_PCBC_LE
+ }
+ },
+ {
+ {
+ {
+ PCIE_ADDR_TYPE,
+ { (
+ (DEFAULT_PCI_BUS_NUMBER_PCH << 24) |
+ (PCI_DEVICE_NUMBER_PCH_LPC << 19) |
+ (PCI_FUNCTION_NUMBER_PCH_LPC << 16) |
+ R_ESPI_CFG_PCBC
+ ) }
+ },
+ S_ESPI_CFG_PCBC,
+ N_ESPI_CFG_PCBC_BWPDS
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_ACPI_IO_SMI_STS}
+ },
+ S_ACPI_IO_SMI_STS,
+ N_ACPI_IO_SMI_STS_TCO
+ }
+};
+
+/**
+ This function will register EspiSmiCallback with mSrcDescEspiBiosWp source decriptor
+ This function make sure there is only one BIOS WP SMI handler is registered.
+ While any ESPI sub BIOS WP SMI type is registered, all the BIOS WP SMI
+ will go to callback function EspiSmiCallback first, and then dispatchs the callbacks
+ recorded in mEspiSmiInstance.
+
+ @retval EFI_SUCCESS Registration succeed
+ @retval others Registration failed
+**/
+STATIC
+EFI_STATUS
+RegisterBiosWrProtectIfNull (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ DATABASE_RECORD *Record;
+
+ if (mEspiSmiInstance.PchSmiEspiHandle[EspiBiosWrProtect] == NULL) {
+ Status = PchSmiRecordInsert (
+ &mSrcDescEspiBiosWp,
+ (PCH_SMI_CALLBACK_FUNCTIONS) EspiSmiCallback,
+ PchTcoSmiLpcBiosWpType,
+ &mEspiSmiInstance.PchSmiEspiHandle[EspiBiosWrProtect]
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Fail to register BIOS WP SMI handler \n"));
+ return Status;
+ }
+ Record = DATABASE_RECORD_FROM_LINK (mEspiSmiInstance.PchSmiEspiHandle[EspiBiosWrProtect]);
+ Record->ClearSource = PchTcoSmiClearSource;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function will register EspiSmiCallback with mSrcDescSerialIrq source decriptor
+ This function make sure there is only one Serial IRQ SMI handler is registered.
+ While any ESPI sub Serial IRQ SMI type is registered, all the Serial IRQ SMI
+ will go to callback function EspiSmiCallback first, and then dispatchs the callbacks
+ recorded in mEspiSmiInstance.
+
+ @retval EFI_SUCCESS Registration succeed
+ @retval others Registration failed
+**/
+STATIC
+EFI_STATUS
+RegisterSerialIrqIfNull (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ if (mEspiSmiInstance.PchSmiEspiHandle[EspiSerialIrq] == NULL) {
+ Status = PchSmiRecordInsert (
+ &mSrcDescSerialIrq,
+ (PCH_SMI_CALLBACK_FUNCTIONS) EspiSmiCallback,
+ PchSmiSerialIrqType,
+ &mEspiSmiInstance.PchSmiEspiHandle[EspiSerialIrq]
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Fail to register Serial IRQ SMI handler \n"));
+ return Status;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Installs and initialize this protocol
+
+ @param[in] ImageHandle Not used
+
+ @retval EFI_SUCCESS Installation succeed
+ @retval others Installation failed
+**/
+EFI_STATUS
+EFIAPI
+InstallEspiSmi (
+ IN EFI_HANDLE ImageHandle
+ )
+{
+ EFI_STATUS Status;
+ ESPI_SMI_TYPE EspiSmiType;
+
+ DEBUG ((DEBUG_INFO, "[InstallEspiSmi] Enter\n"));
+
+ //
+ // InitializeListHead for mEspiSmiInstance.CallBackDataBase[EspiTopLevelTypeMax]
+ //
+ for (EspiSmiType = 0; EspiSmiType < EspiSmiTypeMax; ++EspiSmiType) {
+ InitializeListHead (&mEspiSmiInstance.CallbackDataBase[EspiSmiType]);
+ }
+
+ //
+ // Install EfiEspiSmiDispatchProtocol
+ //
+ Status = gSmst->SmmInstallProtocolInterface (
+ &mEspiSmiInstance.Handle,
+ &gPchEspiSmiDispatchProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &mEspiSmiInstance.PchEspiSmiDispatchProtocol
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed to install eSPI SMI Dispatch Protocol\n"));
+ ASSERT (FALSE);
+ return Status;
+ }
+
+ // Register eSPI SMM callback to enable Fatal Error handling by default handler
+ Status = RegisterSerialIrqIfNull ();
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ // Enable LnkType1Err SMI generation for default handler
+ EspiSmiClearStatus (LnkType1Err);
+ EspiSmiEnableSource (LnkType1Err);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ eSPI SMI Dispatch Protocol instance to register a BIOS Write Protect event
+
+ @param[in] This Not used
+ @param[in] DispatchFunction The callback to execute
+ @param[out] DispatchHandle The handle for this callback registration
+
+ @retval EFI_SUCCESS Registration succeed
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+ @retval others Registration failed
+**/
+EFI_STATUS
+EFIAPI
+BiosWrProtectRegister (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ESPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = RegisterBiosWrProtectIfNull ();
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Insert a record
+ //
+ Status = InsertEspiRecord (DispatchFunction, BiosWrProtect, DispatchHandle);
+ if (!EFI_ERROR (Status)) {
+ SmiHandlerProfileRegisterHandler (&gPchEspiSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
+ }
+ return Status;
+}
+
+/**
+ eSPI SMI Dispatch Protocol instance to register a BIOS Write Report event
+
+ @param[in] This Not used
+ @param[in] DispatchFunction The callback to execute
+ @param[out] DispatchHandle The handle for this callback registration
+
+ @retval EFI_SUCCESS Registration succeed
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+ @retval others Registration failed
+**/
+EFI_STATUS
+EFIAPI
+BiosWrReportRegister (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ESPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = RegisterSerialIrqIfNull ();
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Insert a record
+ //
+ Status = InsertEspiRecord (DispatchFunction, BiosWrReport, DispatchHandle);
+ if (!EFI_ERROR (Status)) {
+ SmiHandlerProfileRegisterHandler (&gPchEspiSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
+ }
+ return Status;
+}
+
+/**
+ eSPI SMI Dispatch Protocol instance to register a Peripheral Channel Non Fatal Error event
+
+ @param[in] This Not used
+ @param[in] DispatchFunction The callback to execute
+ @param[out] DispatchHandle The handle for this callback registration
+
+ @retval EFI_SUCCESS Registration succeed
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+ @retval others Registration failed
+**/
+EFI_STATUS
+EFIAPI
+PcNonFatalErrRegister (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ESPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = RegisterSerialIrqIfNull ();
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Insert a record
+ //
+ Status = InsertEspiRecord (DispatchFunction, PcNonFatalErr, DispatchHandle);
+ if (!EFI_ERROR (Status)) {
+ SmiHandlerProfileRegisterHandler (&gPchEspiSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
+ }
+ return Status;
+}
+
+/**
+ eSPI SMI Dispatch Protocol instance to register a Peripheral Channel Fatal Error event
+
+ @param[in] This Not used
+ @param[in] DispatchFunction The callback to execute
+ @param[out] DispatchHandle The handle for this callback registration
+
+ @retval EFI_SUCCESS Registration succeed
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+ @retval others Registration failed
+**/
+EFI_STATUS
+EFIAPI
+PcFatalErrRegister (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ESPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = RegisterSerialIrqIfNull ();
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Insert a record
+ //
+ Status = InsertEspiRecord (DispatchFunction, PcFatalErr, DispatchHandle);
+ if (!EFI_ERROR (Status)) {
+ SmiHandlerProfileRegisterHandler (&gPchEspiSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
+ }
+ return Status;
+}
+
+/**
+ eSPI SMI Dispatch Protocol instance to register a Virtual Wire Non Fatal Error event
+
+ @param[in] This Not used
+ @param[in] DispatchFunction The callback to execute
+ @param[out] DispatchHandle The handle for this callback registration
+
+ @retval EFI_SUCCESS Registration succeed
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+ @retval others Registration failed
+**/
+EFI_STATUS
+EFIAPI
+VwNonFatalErrRegister (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ESPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = RegisterSerialIrqIfNull ();
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Insert a record
+ //
+ Status = InsertEspiRecord (DispatchFunction, VwNonFatalErr, DispatchHandle);
+ if (!EFI_ERROR (Status)) {
+ SmiHandlerProfileRegisterHandler (&gPchEspiSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
+ }
+ return Status;
+}
+
+/**
+ eSPI SMI Dispatch Protocol instance to register a Virtual Wire Fatal Error event
+
+ @param[in] This Not used
+ @param[in] DispatchFunction The callback to execute
+ @param[out] DispatchHandle The handle for this callback registration
+
+ @retval EFI_SUCCESS Registration succeed
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+ @retval others Registration failed
+**/
+EFI_STATUS
+EFIAPI
+VwFatalErrRegister (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ESPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = RegisterSerialIrqIfNull ();
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Insert a record
+ //
+ Status = InsertEspiRecord (DispatchFunction, VwFatalErr, DispatchHandle);
+ if (!EFI_ERROR (Status)) {
+ SmiHandlerProfileRegisterHandler (&gPchEspiSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
+ }
+ return Status;
+}
+
+/**
+ eSPI SMI Dispatch Protocol instance to register a Flash Channel Non Fatal Error event
+
+ @param[in] This Not used
+ @param[in] DispatchFunction The callback to execute
+ @param[out] DispatchHandle The handle for this callback registration
+
+ @retval EFI_SUCCESS Registration succeed
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+ @retval others Registration failed
+**/
+EFI_STATUS
+EFIAPI
+FlashNonFatalErrRegister (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ESPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = RegisterSerialIrqIfNull ();
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Insert a record
+ //
+ Status = InsertEspiRecord (DispatchFunction, FlashNonFatalErr, DispatchHandle);
+ if (!EFI_ERROR (Status)) {
+ SmiHandlerProfileRegisterHandler (&gPchEspiSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
+ }
+ return Status;
+}
+
+/**
+ eSPI SMI Dispatch Protocol instance to register a Flash Channel Fatal Error event
+
+ @param[in] This Not used
+ @param[in] DispatchFunction The callback to execute
+ @param[out] DispatchHandle The handle for this callback registration
+
+ @retval EFI_SUCCESS Registration succeed
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+ @retval others Registration failed
+**/
+EFI_STATUS
+EFIAPI
+FlashFatalErrRegister (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ESPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = RegisterSerialIrqIfNull ();
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Insert a record
+ //
+ Status = InsertEspiRecord (DispatchFunction, FlashFatalErr, DispatchHandle);
+ if (!EFI_ERROR (Status)) {
+ SmiHandlerProfileRegisterHandler (&gPchEspiSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
+ }
+ return Status;
+}
+
+/**
+ eSPI SMI Dispatch Protocol instance to register a Link Error event
+
+ @param[in] This Not used
+ @param[in] DispatchFunction The callback to execute
+ @param[out] DispatchHandle The handle for this callback registration
+
+ @retval EFI_SUCCESS Registration succeed
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+ @retval others Registration failed
+**/
+EFI_STATUS
+EFIAPI
+LnkType1ErrRegister (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ESPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = RegisterSerialIrqIfNull ();
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Insert a record
+ //
+ Status = InsertEspiRecord (DispatchFunction, LnkType1Err, DispatchHandle);
+ if (!EFI_ERROR (Status)) {
+ SmiHandlerProfileRegisterHandler (&gPchEspiSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
+ }
+ return Status;
+}
+
+//
+// EspiSlave srcdesc
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSrcDescEspiSlave = {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_ACPI_IO_SMI_EN}
+ },
+ S_ACPI_IO_SMI_EN,
+ N_ACPI_IO_SMI_EN_ESPI
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_ACPI_IO_SMI_STS}
+ },
+ S_ACPI_IO_SMI_STS,
+ N_ACPI_IO_SMI_STS_ESPI
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_ACPI_IO_SMI_STS}
+ },
+ S_ACPI_IO_SMI_STS,
+ N_ACPI_IO_SMI_STS_ESPI
+ }
+};
+
+/**
+ eSPI SMI Dispatch Protocol instance to register a eSPI slave SMI
+ This routine will also lock down ESPI_SMI_LOCK bit after registration and prevent
+ this handler from unregistration.
+ On platform that supports more than 1 device through another chip select (SPT-H),
+ the SMI handler itself needs to inspect both the eSPI devices' interrupt status registers
+ (implementation specific for each Slave) in order to identify and service the cause.
+ After servicing it, it has to clear the Slaves' internal SMI# status registers
+
+ @param[in] This Not used
+ @param[in] DispatchFunction The callback to execute
+ @param[out] DispatchHandle The handle for this callback registration
+
+ @retval EFI_SUCCESS Registration succeed
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+ @retval EFI_ACCESS_DENIED The ESPI_SMI_LOCK is set and register is blocked.
+ @retval others Registration failed
+**/
+EFI_STATUS
+EFIAPI
+EspiSlaveSmiRegister (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ESPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ //
+ // If ESPI_SMI_LOCK is set, the register is blocked.
+ //
+ if (PmcIsEspiSmiLockSet ()) {
+ return EFI_ACCESS_DENIED;
+ }
+
+ //
+ // @note: This service doesn't utilize the data base of mEspiSmiInstance.
+ // While SMI is triggered it directly goes to the registing DispatchFunction
+ // instead of EspiSmiCallback.
+ //
+ Status = PchSmiRecordInsert (
+ &mSrcDescEspiSlave,
+ (PCH_SMI_CALLBACK_FUNCTIONS) DispatchFunction,
+ PchEspiSmiEspiSlaveType,
+ DispatchHandle
+ );
+ PchSmmClearSource (&mSrcDescEspiSlave);
+ PchSmmEnableSource (&mSrcDescEspiSlave);
+
+ //
+ // Lock down the ESPI_SMI_LOCK after ESPI SMI is enabled.
+ //
+ PmcLockEspiSmiWithS3BootScript ();
+ //
+ // Keep the DispatchHandle which will be used for unregister function.
+ //
+ mEspiSmiInstance.PchSmiEspiHandle[EspiPmc] = *DispatchHandle;
+
+ if (!EFI_ERROR (Status)) {
+ SmiHandlerProfileRegisterHandler (&gPchEspiSmiDispatchProtocolGuid, (EFI_SMM_HANDLER_ENTRY_POINT2)DispatchFunction, (UINTN)RETURN_ADDRESS (0), NULL, 0);
+ }
+
+ return Status;
+}
+
+/**
+ eSPI SMI Dispatch Protocol instance to unregister a callback based on handle
+
+ @param[in] This Not used
+ @param[in] DispatchHandle Handle acquired during registration
+
+ @retval EFI_SUCCESS Unregister successful
+ @retval EFI_INVALID_PARAMETER DispatchHandle is null
+ @retval EFI_INVALID_PARAMETER DispatchHandle's forward link has bad pointer
+ @retval EFI_INVALID_PARAMETER DispatchHandle does not exist in database
+ @retval EFI_ACCESS_DENIED Unregistration is done after end of DXE
+ @retval EFI_ACCESS_DENIED DispatchHandle is not allowed to unregistered
+**/
+EFI_STATUS
+EFIAPI
+EspiSmiUnRegister (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN EFI_HANDLE DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+ ESPI_TOP_LEVEL_TYPE EspiTopLevelType;
+ ESPI_SMI_TYPE EspiSmiType;
+ BOOLEAN SafeToDisable;
+ LIST_ENTRY *LinkInDb;
+ ESPI_SMI_RECORD *RecordPointer;
+ DATABASE_RECORD *RecordToDelete;
+
+ if (DispatchHandle == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "UnRegister is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ if (((LIST_ENTRY *) DispatchHandle)->ForwardLink == (LIST_ENTRY *) EFI_BAD_POINTER) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // For DispatchHandle belongs to Espi Slave SMI, refuses the request of unregistration.
+ //
+ if (mEspiSmiInstance.PchSmiEspiHandle[EspiPmc] == DispatchHandle) {
+ DEBUG ((DEBUG_ERROR, "UnRegister is not allowed for ESPI Slave SMI handle! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ //
+ // Iterate through all the database to find the record
+ //
+ for (EspiSmiType = 0; EspiSmiType < EspiSmiTypeMax; ++EspiSmiType) {
+ LinkInDb = GetFirstNode (&mEspiSmiInstance.CallbackDataBase[EspiSmiType]);
+
+ while (!IsNull (&mEspiSmiInstance.CallbackDataBase[EspiSmiType], LinkInDb)) {
+ if (LinkInDb != (LIST_ENTRY *) DispatchHandle) {
+ LinkInDb = GetNextNode (&mEspiSmiInstance.CallbackDataBase[EspiSmiType], LinkInDb);
+
+ } else {
+ //
+ // Found the source to be from this list
+ //
+ RemoveEntryList (LinkInDb);
+ RecordPointer = (ESPI_RECORD_FROM_LINK (LinkInDb));
+
+ if (mEspiSmiInstance.EspiSmiEventCounter[EspiSmiType] != 0) {
+ if (--mEspiSmiInstance.EspiSmiEventCounter[EspiSmiType] == 0) {
+ EspiSmiDisableSource (EspiSmiType);
+ }
+ }
+
+ Status = gSmst->SmmFreePool (RecordPointer);
+ if (EFI_ERROR (Status)) {
+ ASSERT (FALSE);
+ }
+
+ goto EspiSmiUnRegisterEnd;
+ }
+ }
+ }
+ //
+ // If the code reach here, the handle passed in cannot be found
+ //
+ DEBUG ((DEBUG_ERROR, "eSPI SMI handle is not in record database \n"));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+
+EspiSmiUnRegisterEnd:
+
+ //
+ // Unregister and clear the handle from PchSmiDispatch
+ //
+ for (EspiTopLevelType = 0; EspiTopLevelType < EspiTopLevelTypeMax; ++EspiTopLevelType) {
+ SafeToDisable = TRUE;
+ //
+ // Checks all the child events that belongs to a top level status in PMC
+ //
+ for (EspiSmiType = mEspiSmiInstance.Barrier[EspiTopLevelType].Start; EspiSmiType <= mEspiSmiInstance.Barrier[EspiTopLevelType].End; ++EspiSmiType) {
+ if (mEspiSmiInstance.EspiSmiEventCounter[EspiSmiType] != 0) {
+ SafeToDisable = FALSE;
+ }
+ }
+ //
+ // Finally, disable the top level event in PMC
+ //
+ if (SafeToDisable) {
+ if (mEspiSmiInstance.PchSmiEspiHandle[EspiTopLevelType] != NULL) {
+ Status = PchSmmCoreUnRegister (NULL, mEspiSmiInstance.PchSmiEspiHandle[EspiTopLevelType]);
+ ASSERT_EFI_ERROR (Status);
+ mEspiSmiInstance.PchSmiEspiHandle[EspiTopLevelType] = NULL;
+ }
+ }
+ }
+ RecordToDelete = DATABASE_RECORD_FROM_LINK (DispatchHandle);
+ if (!EFI_ERROR (Status)) {
+ SmiHandlerProfileUnregisterHandler (&gPchEspiSmiDispatchProtocolGuid, RecordToDelete->Callback, NULL, 0);
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Returns AND maks for clearing eSPI channel registers errors statuses
+ In addition to common status bit we add channel specific erro bits to avoid clearing them
+
+ @param[in] ChannelNumber Channel number (0 for PC, 1 for VW, 2 for OOB, 3 for FA)
+
+ @retval UINT32 AND mask with all the status bit masked to not clear them by mistake
+**/
+UINT32
+GetEspiChannelStatusClearMask (
+ UINT8 ChannelNumber
+ )
+{
+ UINT32 Data32;
+
+ // Common error status bits for all channel registers
+ Data32 = B_ESPI_PCR_XERR_XNFES | B_ESPI_PCR_XERR_XFES;
+
+ // Check channels for channel specific status bits
+ switch(ChannelNumber) {
+ case 0: // Peripheral Channel specific status bits
+ Data32 |= B_ESPI_PCR_PCERR_PCURD;
+ break;
+ case 3: // Flash Access Channel specific status bits
+ Data32 |= B_ESPI_PCR_FCERR_SAFBLK;
+ break;
+ }
+
+ // Return the expected AND mask
+ return (UINT32)~(Data32);
+}
+
+/**
+ Checks if channel error register data has Fatal Error bit set
+ If yes then reset the channel on slave
+
+ @param[in] ChannelBaseAddress Base address
+ @param[in] ChannelNumber Channel number (0 for PC, 1 for VW, 2 for OOB, 3 for FA)
+ @param[in] SlaveId Slave ID of which channel is to be reset
+**/
+VOID
+CheckSlaveChannelErrorAndReset (
+ UINT16 ChannelBaseAddress,
+ UINT8 ChannelNumber,
+ UINT8 SlaveId
+ )
+{
+ UINT32 Data32;
+ UINT16 ChannelAddress;
+ EFI_STATUS Status;
+
+ if (ChannelNumber == 2) {
+ DEBUG ((DEBUG_INFO, "Channel %d is not supported by this function due to lack of error register\n", ChannelNumber));
+ return;
+ }
+
+ if (!IsEspiSlaveChannelSupported (SlaveId, ChannelNumber)) {
+ DEBUG ((DEBUG_WARN, "Channel %d is not supported by slave device\n", ChannelNumber));
+ return;
+ }
+
+ // Calculate channel address based on slave id
+ ChannelAddress = (UINT16) (ChannelBaseAddress + (SlaveId * S_ESPI_PCR_XERR));
+
+ // Reading channel error register data
+ Data32 = PchPcrRead32 (PID_ESPISPI, ChannelAddress);
+
+ DEBUG ((DEBUG_INFO, "eSPI channel error register (0x%4X) has value 0x%8X\n", ChannelAddress, Data32));
+
+ // Check Fatal Error status bit in channel error register data
+ if ((Data32 & B_ESPI_PCR_XERR_XFES) != 0) {
+ Status = PchEspiSlaveChannelReset (SlaveId, ChannelNumber);
+
+ if (EFI_ERROR (Status)) {
+ switch (Status) {
+ case EFI_UNSUPPORTED:
+ DEBUG ((DEBUG_ERROR, "Slave doesn't support channel %d\n", ChannelNumber));
+ break;
+ case EFI_TIMEOUT:
+ DEBUG ((DEBUG_ERROR, "Timeout occured during channel %d reset on slave %d\n", ChannelNumber, SlaveId));
+ break;
+ default:
+ DEBUG ((DEBUG_ERROR, "Error occured during channel %d reset\n", ChannelNumber));
+ break;
+ }
+ } else {
+ DEBUG ((DEBUG_INFO, "eSPI Slave %d channel %d reset ended successfully\n", SlaveId, ChannelNumber));
+ // If channel reset was successfull clear the fatal error flag by writing one
+ // we should be aware not to clear other status bits by mistake and mask them
+ PchPcrAndThenOr32 (
+ PID_ESPISPI,
+ ChannelAddress,
+ GetEspiChannelStatusClearMask (ChannelNumber),
+ B_ESPI_PCR_XERR_XFES
+ );
+ }
+ }
+}
+
+/**
+ eSPI SMI handler for Fatal Error recovery flow
+**/
+VOID
+EspiDefaultFatalErrorHandler (
+ VOID
+ )
+{
+ UINT32 Data32;
+ UINT8 SlaveId;
+ UINT8 MaxSlavesCount;
+
+ DEBUG ((DEBUG_INFO, "[EspiRecoverFromFatalError] Enter\n"));
+
+ MaxSlavesCount = IsEspiSecondSlaveSupported () ? 2 : 1;
+
+ DEBUG ((DEBUG_INFO, "[EspiRecoverFromFatalError] MaxSlavesCount %d\n", MaxSlavesCount));
+
+ for (SlaveId = 0; SlaveId < MaxSlavesCount; ++SlaveId) {
+ //
+ // Check if slave has SLCRR bit set. If it does it means it needs recovery.
+ //
+ Data32 = PchPcrRead32 (PID_ESPISPI, (UINT16) (R_ESPI_PCR_LNKERR_SLV0 + (SlaveId * S_ESPI_PCR_XERR)));
+
+ DEBUG ((DEBUG_INFO, "[EspiRecoverFromFatalError] Slave %d LNKERR reg 0x%8X\n", SlaveId, Data32));
+ //
+ // If SLCRR[31] bit is set we need to recover that slave
+ //
+ if ((Data32 & B_ESPI_PCR_LNKERR_SLV0_SLCRR) != 0) {
+ // 1. Perform in-band reset
+ PchEspiSlaveInBandReset (SlaveId);
+
+ // 2. Channels reset
+ CheckSlaveChannelErrorAndReset (R_ESPI_PCR_PCERR_SLV0, 0, SlaveId); // Peripheral channel reset
+ CheckSlaveChannelErrorAndReset (R_ESPI_PCR_VWERR_SLV0, 1, SlaveId); // Virtual Wire channel reset
+
+ // Flash Access channel is not supported for CS1#
+ if (SlaveId == 0) {
+ CheckSlaveChannelErrorAndReset (R_ESPI_PCR_PCERR_SLV0, 3, SlaveId); // Flash Access channel reset
+ }
+
+ // Clear SLCRR bit of slave after all channels recovery was done
+ PchPcrAndThenOr32 (
+ PID_ESPISPI,
+ (UINT16) (R_ESPI_PCR_LNKERR_SLV0 + (SlaveId * S_ESPI_PCR_XERR)),
+ (UINT32)~(B_ESPI_PCR_LNKERR_SLV0_LFET1S),
+ (UINT32) (B_ESPI_PCR_LNKERR_SLV0_SLCRR)
+ );
+ }
+ }
+
+ DEBUG ((DEBUG_INFO, "[EspiRecoverFromFatalError] Exit\n"));
+}
+
+
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmEspi.h b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmEspi.h
new file mode 100644
index 0000000000..4903464fae
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmEspi.h
@@ -0,0 +1,341 @@
+/** @file
+ eSPI SMI Dispatch header
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _PCH_SMM_ESPI_H_
+#define _PCH_SMM_ESPI_H_
+
+#include "PchSmmHelpers.h"
+
+#define ESPI_SMI_INSTANCE_SIGNATURE SIGNATURE_32 ('E', 'S', 'P', 'I')
+#define ESPI_SMI_RECORD_SIGNATURE SIGNATURE_32 ('E', 'S', 'R', 'C')
+
+#define ESPI_INSTANCE_FROM_THIS(_this) CR (_this, ESPI_SMI_INSTANCE, EfiEspiSmiDispatchProtocol, ESPI_SMI_INSTANCE_SIGNATURE)
+#define ESPI_RECORD_FROM_LINK(_link) CR (_link, ESPI_SMI_RECORD, Link, ESPI_SMI_RECORD_SIGNATURE)
+
+typedef enum {
+ EspiBiosWrProtect, ///< BIOS Write Protect
+ EspiSerialIrq, ///< eSPI Master Asserted SMI
+ EspiPmc, ///< eSPI PMC SMI
+ EspiTopLevelTypeMax
+} ESPI_TOP_LEVEL_TYPE;
+
+typedef enum {
+ BiosWrProtect, ///< BIOS Write Protect
+ BiosWrReport, ///< Peripheral Channel BIOS Write Protect
+ PcNonFatalErr, ///< Peripheral Channel Non Fatal Error
+ PcFatalErr, ///< Peripheral Channel Fatal Error
+ VwNonFatalErr, ///< Virtual Wire Non Fatal Error
+ VwFatalErr, ///< Virtual Wire Fatal Error
+ FlashNonFatalErr, ///< Flash Channel Non Fatal Error
+ FlashFatalErr, ///< Flash Channel Fatal Error
+ LnkType1Err, ///< Link Error
+ EspiSlaveSmi, ///< Espi Slave SMI
+ EspiSmiTypeMax
+} ESPI_SMI_TYPE;
+
+///
+/// This is used to classify ESPI_SMI_TYPE to ESPI_TOP_LEVEL_TYPE.
+/// Used during dispatching and unregistering
+///
+typedef struct {
+ ESPI_SMI_TYPE Start;
+ ESPI_SMI_TYPE End;
+} ESPI_SMI_TYPE_BARRIER;
+
+typedef struct _ESPI_SMI_INSTANCE {
+ ///
+ /// Signature associated with this instance
+ ///
+ UINT32 Signature;
+ ///
+ /// EFI_HANDLE acquired when installing PchEspiSmiDispatchProtocol
+ ///
+ EFI_HANDLE Handle;
+ ///
+ /// The protocol to register or unregister eSPI SMI callbacks
+ ///
+ PCH_ESPI_SMI_DISPATCH_PROTOCOL PchEspiSmiDispatchProtocol;
+ ///
+ /// The handle acquired when registering eSPI SMI callback to PchSmiDispatch
+ ///
+ EFI_HANDLE PchSmiEspiHandle[EspiTopLevelTypeMax];
+ ///
+ /// The linked list for record database.
+ ///
+ LIST_ENTRY CallbackDataBase[EspiSmiTypeMax];
+ ///
+ /// This is an internal counter to track the number of eSPI master events have been registered.
+ /// When unregistering, we can disable the SMI if the counter is zero
+ ///
+ UINTN EspiSmiEventCounter[EspiSmiTypeMax];
+ ///
+ /// Instance of barrier
+ ///
+ CONST ESPI_SMI_TYPE_BARRIER Barrier[EspiTopLevelTypeMax];
+} ESPI_SMI_INSTANCE;
+
+typedef struct _ESPI_DESCRIPTOR {
+ PCH_SMM_ADDRESS Address;
+ UINT32 SourceIsActiveAndMask;
+ UINT32 SourceIsActiveValue;
+ UINT32 ClearStatusAndMask;
+ UINT32 ClearStatusOrMask;
+} ESPI_DESCRIPTOR;
+
+///
+/// A simple record to store the callbacks associated with an eSPI SMI source
+///
+typedef struct _ESPI_SMI_RECORD {
+ UINT32 Signature;
+ LIST_ENTRY Link;
+ PCH_ESPI_SMI_DISPATCH_CALLBACK Callback;
+} ESPI_SMI_RECORD;
+
+/**
+ Installs and initialize this protocol
+
+ @param[in] ImageHandle Not used
+
+ @retval EFI_SUCCESS Installation succeed
+ @retval others Installation failed
+**/
+EFI_STATUS
+EFIAPI
+InstallEspiSmi (
+ IN EFI_HANDLE ImageHandle
+ );
+
+/**
+ eSPI SMI Dispatch Protocol instance to register a BIOS Write Protect event
+
+ @param[in] This Not used
+ @param[in] DispatchFunction The callback to execute
+ @param[out] DispatchHandle The handle for this callback registration
+
+ @retval EFI_SUCCESS Registration succeed
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+ @retval others Registration failed
+**/
+EFI_STATUS
+EFIAPI
+BiosWrProtectRegister (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ESPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+
+/**
+ eSPI SMI Dispatch Protocol instance to register a BIOS Write Report event
+
+ @param[in] This Not used
+ @param[in] DispatchFunction The callback to execute
+ @param[out] DispatchHandle The handle for this callback registration
+
+ @retval EFI_SUCCESS Registration succeed
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+ @retval others Registration failed
+**/
+EFI_STATUS
+EFIAPI
+BiosWrReportRegister (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ESPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+
+/**
+ eSPI SMI Dispatch Protocol instance to register a Peripheral Channel Non Fatal Error event
+
+ @param[in] This Not used
+ @param[in] DispatchFunction The callback to execute
+ @param[out] DispatchHandle The handle for this callback registration
+
+ @retval EFI_SUCCESS Registration succeed
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+ @retval others Registration failed
+**/
+EFI_STATUS
+EFIAPI
+PcNonFatalErrRegister (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ESPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+
+/**
+ eSPI SMI Dispatch Protocol instance to register a Peripheral Channel Fatal Error event
+
+ @param[in] This Not used
+ @param[in] DispatchFunction The callback to execute
+ @param[out] DispatchHandle The handle for this callback registration
+
+ @retval EFI_SUCCESS Registration succeed
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+ @retval others Registration failed
+**/
+EFI_STATUS
+EFIAPI
+PcFatalErrRegister (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ESPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+
+/**
+ eSPI SMI Dispatch Protocol instance to register a Virtual Wire Non Fatal Error event
+
+ @param[in] This Not used
+ @param[in] DispatchFunction The callback to execute
+ @param[out] DispatchHandle The handle for this callback registration
+
+ @retval EFI_SUCCESS Registration succeed
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+ @retval others Registration failed
+**/
+EFI_STATUS
+EFIAPI
+VwNonFatalErrRegister (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ESPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+
+/**
+ eSPI SMI Dispatch Protocol instance to register a Virtual Wire Fatal Error event
+
+ @param[in] This Not used
+ @param[in] DispatchFunction The callback to execute
+ @param[out] DispatchHandle The handle for this callback registration
+
+ @retval EFI_SUCCESS Registration succeed
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+ @retval others Registration failed
+**/
+EFI_STATUS
+EFIAPI
+VwFatalErrRegister (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ESPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+
+/**
+ eSPI SMI Dispatch Protocol instance to register a Flash Channel Non Fatal Error event
+
+ @param[in] This Not used
+ @param[in] DispatchFunction The callback to execute
+ @param[out] DispatchHandle The handle for this callback registration
+
+ @retval EFI_SUCCESS Registration succeed
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+ @retval others Registration failed
+**/
+EFI_STATUS
+EFIAPI
+FlashNonFatalErrRegister (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ESPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+
+/**
+ eSPI SMI Dispatch Protocol instance to register a Flash Channel Fatal Error event
+
+ @param[in] This Not used
+ @param[in] DispatchFunction The callback to execute
+ @param[out] DispatchHandle The handle for this callback registration
+
+ @retval EFI_SUCCESS Registration succeed
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+ @retval others Registration failed
+**/
+EFI_STATUS
+EFIAPI
+FlashFatalErrRegister (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ESPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+
+/**
+ eSPI SMI Dispatch Protocol instance to register a Link Error event
+
+ @param[in] This Not used
+ @param[in] DispatchFunction The callback to execute
+ @param[out] DispatchHandle The handle for this callback registration
+
+ @retval EFI_SUCCESS Registration succeed
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+ @retval others Registration failed
+**/
+EFI_STATUS
+EFIAPI
+LnkType1ErrRegister (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ESPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+
+/**
+ eSPI SMI Dispatch Protocol instance to register a eSPI slave SMI
+ NOTE: The register function is not available when the ESPI_SMI_LOCK bit is set.
+ This runtine will also lock donw ESPI_SMI_LOCK bit after registration and
+ prevent this handler from unregistration.
+ On platform that supports more than 1 device through another chip select (SPT-H),
+ the SMI handler itself needs to inspect both the eSPI devices' interrupt status registers
+ (implementation specific for each Slave) in order to identify and service the cause.
+ After servicing it, it has to clear the Slaves' internal SMI# status registers
+
+ @param[in] This Not used
+ @param[in] DispatchFunction The callback to execute
+ @param[out] DispatchHandle The handle for this callback registration
+
+ @retval EFI_SUCCESS Registration succeed
+ @retval EFI_ACCESS_DENIED Return access denied if the SmmReadyToLock event has been triggered
+ @retval EFI_ACCESS_DENIED The ESPI_SMI_LOCK is set and register is blocked.
+ @retval others Registration failed
+**/
+EFI_STATUS
+EFIAPI
+EspiSlaveSmiRegister (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN PCH_ESPI_SMI_DISPATCH_CALLBACK DispatchFunction,
+ OUT EFI_HANDLE *DispatchHandle
+ );
+
+/**
+ eSPI SMI Dispatch Protocol instance to unregister a callback based on handle
+
+ @param[in] This Not used
+ @param[in] DispatchHandle Handle acquired during registration
+
+ @retval EFI_SUCCESS Unregister successful
+ @retval EFI_INVALID_PARAMETER DispatchHandle is null
+ @retval EFI_INVALID_PARAMETER DispatchHandle's forward link has bad pointer
+ @retval EFI_INVALID_PARAMETER DispatchHandle does not exist in database
+ @retval EFI_ACCESS_DENIED Unregistration is done after end of DXE
+ @retval EFI_ACCESS_DENIED DispatchHandle is not allowed to unregistered
+**/
+EFI_STATUS
+EFIAPI
+EspiSmiUnRegister (
+ IN PCH_ESPI_SMI_DISPATCH_PROTOCOL *This,
+ IN EFI_HANDLE DispatchHandle
+ );
+
+/**
+ eSPI SMI handler for Fatal Error recovery flow
+
+ @param[in] DispatchHandle Handle acquired during registration
+**/
+VOID
+EspiDefaultFatalErrorHandler (
+ VOID
+ );
+
+
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmGpi.c b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmGpi.c
new file mode 100644
index 0000000000..61f925c860
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmGpi.c
@@ -0,0 +1,263 @@
+/** @file
+ File to contain all the hardware specific stuff for the Smm Gpi dispatch protocol.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include "PchSmm.h"
+#include "PchSmmHelpers.h"
+#include <Library/SmiHandlerProfileLib.h>
+#include <Register/GpioRegs.h>
+#include <Register/PmcRegs.h>
+
+//
+// Structure for GPI SMI is a template which needs to have
+// GPI Smi bit offset and Smi Status & Enable registers updated (accordingly
+// to choosen group and pad number) after adding it to SMM Callback database
+//
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mPchGpiSourceDescTemplate = {
+ PCH_SMM_NO_FLAGS,
+ {
+ NULL_BIT_DESC_INITIALIZER,
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ GPIO_ADDR_TYPE, {0x0}
+ },
+ S_GPIO_PCR_GP_SMI_STS, 0x0,
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_ACPI_IO_SMI_STS}
+ },
+ S_ACPI_IO_SMI_STS,
+ N_ACPI_IO_SMI_STS_GPIO_SMI
+ }
+};
+
+/**
+ The register function used to register SMI handler of GPI SMI event.
+
+ @param[in] This Pointer to the EFI_SMM_GPI_DISPATCH2_PROTOCOL instance.
+ @param[in] DispatchFunction Function to register for handler when the specified GPI causes an SMI.
+ @param[in] RegisterContext Pointer to the dispatch function's context.
+ The caller fills this context in before calling
+ the register function to indicate to the register
+ function the GPI(s) for which the dispatch function
+ should be invoked.
+ @param[out] DispatchHandle Handle generated by the dispatcher to track the
+ function instance.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ registered and the SMI source has been enabled.
+ @retval EFI_ACCESS_DENIED Register is not allowed
+ @retval EFI_INVALID_PARAMETER RegisterContext is invalid. The GPI input value
+ is not within valid range.
+ @retval EFI_OUT_OF_RESOURCES There is not enough memory (system or SMM) to manage this child.
+**/
+EFI_STATUS
+EFIAPI
+PchGpiSmiRegister (
+ IN CONST EFI_SMM_GPI_DISPATCH2_PROTOCOL *This,
+ IN EFI_SMM_HANDLER_ENTRY_POINT2 DispatchFunction,
+ IN EFI_SMM_GPI_REGISTER_CONTEXT *RegisterContext,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+ DATABASE_RECORD Record;
+ GPIO_PAD GpioPad;
+ UINT8 GpiSmiBitOffset;
+ UINT32 GpiHostSwOwnRegAddress;
+ UINT32 GpiSmiStsRegAddress;
+ UINT32 Data32Or;
+ UINT32 Data32And;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the EndOfDxe event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = GpioGetPadAndSmiRegs (
+ (UINT32) RegisterContext->GpiNum,
+ &GpioPad,
+ &GpiSmiBitOffset,
+ &GpiHostSwOwnRegAddress,
+ &GpiSmiStsRegAddress
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ ZeroMem (&Record, sizeof (DATABASE_RECORD));
+
+ //
+ // Gather information about the registration request
+ //
+ Record.Callback = DispatchFunction;
+ Record.ChildContext.Gpi = *RegisterContext;
+ Record.ProtocolType = GpiType;
+ Record.Signature = DATABASE_RECORD_SIGNATURE;
+
+ CopyMem (&Record.SrcDesc, &mPchGpiSourceDescTemplate, sizeof (PCH_SMM_SOURCE_DESC) );
+
+ Record.SrcDesc.Sts[0].Reg.Data.raw = GpiSmiStsRegAddress; // GPI SMI Status register
+ Record.SrcDesc.Sts[0].Bit = GpiSmiBitOffset; // Bit position for selected pad
+
+ //
+ // Insert GpiSmi handler to PchSmmCore database
+ //
+ *DispatchHandle = NULL;
+
+ Status = SmmCoreInsertRecord (
+ &Record,
+ DispatchHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ SmiHandlerProfileRegisterHandler (
+ &gEfiSmmGpiDispatch2ProtocolGuid,
+ (EFI_SMM_HANDLER_ENTRY_POINT2) DispatchFunction,
+ (UINTN)RETURN_ADDRESS (0),
+ RegisterContext,
+ sizeof(*RegisterContext)
+ );
+
+ //
+ // Enable GPI SMI
+ // HOSTSW_OWN with respect to generating GPI SMI has negative logic:
+ // - 0 (ACPI mode) - GPIO pad will be capable of generating SMI/NMI/SCI
+ // - 1 (GPIO mode) - GPIO pad will not generate SMI/NMI/SCI
+ //
+ Data32And = (UINT32)~(1u << GpiSmiBitOffset);
+ MmioAnd32 (GpiHostSwOwnRegAddress, Data32And);
+
+ //
+ // Add HOSTSW_OWN programming into S3 boot script
+ //
+ Data32Or = 0;
+ S3BootScriptSaveMemReadWrite (S3BootScriptWidthUint32, GpiHostSwOwnRegAddress, &Data32Or, &Data32And);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Unregister a GPI SMI source dispatch function with a parent SMM driver
+
+ @param[in] This Pointer to the EFI_SMM_GPI_DISPATCH2_PROTOCOL instance.
+ @param[in] DispatchHandle Handle of dispatch function to deregister.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ unregistered and the SMI source has been disabled
+ if there are no other registered child dispatch
+ functions for this SMI source.
+ @retval EFI_INVALID_PARAMETER Handle is invalid.
+**/
+EFI_STATUS
+EFIAPI
+PchGpiSmiUnRegister (
+ IN CONST EFI_SMM_GPI_DISPATCH2_PROTOCOL *This,
+ IN EFI_HANDLE DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+ DATABASE_RECORD *RecordToDelete;
+ DATABASE_RECORD *RecordInDb;
+ LIST_ENTRY *LinkInDb;
+ GPIO_PAD GpioPad;
+ UINT8 GpiSmiBitOffset;
+ UINT32 GpiHostSwOwnRegAddress;
+ UINT32 GpiSmiStsRegAddress;
+ UINT32 Data32Or;
+ UINT32 Data32And;
+ BOOLEAN DisableGpiSmiSource;
+
+
+ if (DispatchHandle == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ RecordToDelete = DATABASE_RECORD_FROM_LINK (DispatchHandle);
+ if ((RecordToDelete->Signature != DATABASE_RECORD_SIGNATURE) ||
+ (RecordToDelete->ProtocolType != GpiType)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "UnRegister is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ DisableGpiSmiSource = TRUE;
+ //
+ // Loop through all sources in record linked list to see if any other GPI SMI
+ // is installed on the same pin. If no then disable GPI SMI capability on this pad
+ //
+ LinkInDb = GetFirstNode (&mPrivateData.CallbackDataBase);
+ while (!IsNull (&mPrivateData.CallbackDataBase, LinkInDb)) {
+ RecordInDb = DATABASE_RECORD_FROM_LINK (LinkInDb);
+ LinkInDb = GetNextNode (&mPrivateData.CallbackDataBase, &RecordInDb->Link);
+ //
+ // If this is the record to delete skip it
+ //
+ if (RecordInDb == RecordToDelete) {
+ continue;
+ }
+ //
+ // Check if record is GPI SMI type
+ //
+ if (RecordInDb->ProtocolType == GpiType) {
+ //
+ // Check if same GPIO pad is the source of this SMI
+ //
+ if (RecordInDb->ChildContext.Gpi.GpiNum == RecordToDelete->ChildContext.Gpi.GpiNum) {
+ DisableGpiSmiSource = FALSE;
+ break;
+ }
+ }
+ }
+
+ if (DisableGpiSmiSource) {
+ GpioGetPadAndSmiRegs (
+ (UINT32) RecordToDelete->ChildContext.Gpi.GpiNum,
+ &GpioPad,
+ &GpiSmiBitOffset,
+ &GpiHostSwOwnRegAddress,
+ &GpiSmiStsRegAddress
+ );
+
+ Data32Or = 1u << GpiSmiBitOffset;
+ Data32And = 0xFFFFFFFF;
+ MmioOr32 (GpiHostSwOwnRegAddress, Data32Or);
+ S3BootScriptSaveMemReadWrite (S3BootScriptWidthUint32, GpiHostSwOwnRegAddress, &Data32Or, &Data32And);
+ }
+
+
+ RemoveEntryList (&RecordToDelete->Link);
+ ZeroMem (RecordToDelete, sizeof (DATABASE_RECORD));
+ Status = gSmst->SmmFreePool (RecordToDelete);
+
+ if (EFI_ERROR (Status)) {
+ ASSERT (FALSE);
+ return Status;
+ }
+ SmiHandlerProfileUnregisterHandler (
+ &gEfiSmmGpiDispatch2ProtocolGuid,
+ RecordToDelete->Callback,
+ &RecordToDelete->ChildContext,
+ RecordToDelete->ContextSize
+ );
+ return EFI_SUCCESS;
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmHelpers.c b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmHelpers.c
new file mode 100644
index 0000000000..6bbf9ea8e8
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmHelpers.c
@@ -0,0 +1,332 @@
+/** @file
+ Helper functions for PCH SMM dispatcher.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include "PchSmmHelpers.h"
+#include <Register/PmcRegs.h>
+
+///
+/// #define BIT_ZERO 0x00000001
+///
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 BIT_ZERO = 0x00000001;
+
+///
+/// SUPPORT / HELPER FUNCTIONS (PCH version-independent)
+///
+
+/**
+ Compare 2 SMM source descriptors' enable settings.
+
+ @param[in] Src1 Pointer to the PCH SMI source description table 1
+ @param[in] Src2 Pointer to the PCH SMI source description table 2
+
+ @retval TRUE The enable settings of the 2 SMM source descriptors are identical.
+ @retval FALSE The enable settings of the 2 SMM source descriptors are not identical.
+**/
+BOOLEAN
+CompareEnables (
+ CONST IN PCH_SMM_SOURCE_DESC *Src1,
+ CONST IN PCH_SMM_SOURCE_DESC *Src2
+ )
+{
+ BOOLEAN IsEqual;
+ UINTN DescIndex;
+
+ IsEqual = TRUE;
+ for (DescIndex = 0; DescIndex < NUM_EN_BITS; DescIndex++) {
+ ///
+ /// It's okay to compare a NULL bit description to a non-NULL bit description.
+ /// They are unequal and these tests will generate the correct result.
+ ///
+ if (Src1->En[DescIndex].Bit != Src2->En[DescIndex].Bit ||
+ Src1->En[DescIndex].Reg.Type != Src2->En[DescIndex].Reg.Type ||
+ Src1->En[DescIndex].Reg.Data.raw != Src2->En[DescIndex].Reg.Data.raw
+ ) {
+ IsEqual = FALSE;
+ break;
+ ///
+ /// out of for loop
+ ///
+ }
+ }
+
+ return IsEqual;
+}
+
+/**
+ Compare a bit descriptor to the enables of source descriptor. Includes null address type.
+
+ @param[in] BitDesc Pointer to the PCH SMI bit descriptor
+ @param[in] Src Pointer to the PCH SMI source description table 2
+
+ @retval TRUE The bit desc is equal to any of the enables in source descriptor
+ @retval FALSE The bid desc is not equal to all of the enables in source descriptor
+**/
+BOOLEAN
+IsBitEqualToAnySourceEn (
+ CONST IN PCH_SMM_BIT_DESC *BitDesc,
+ CONST IN PCH_SMM_SOURCE_DESC *Src
+ )
+{
+ BOOLEAN IsEqual;
+ UINTN DescIndex;
+
+ IsEqual = FALSE;
+
+ for (DescIndex = 0; DescIndex < NUM_EN_BITS; ++DescIndex) {
+ if ((BitDesc->Reg.Type == Src->En[DescIndex].Reg.Type) &&
+ (BitDesc->Reg.Data.raw == Src->En[DescIndex].Reg.Data.raw) &&
+ (BitDesc->Bit == Src->En[DescIndex].Bit)) {
+ IsEqual = TRUE;
+ break;
+ }
+ }
+ return IsEqual;
+}
+
+/**
+ Compare 2 SMM source descriptors' statuses.
+
+ @param[in] Src1 Pointer to the PCH SMI source description table 1
+ @param[in] Src2 Pointer to the PCH SMI source description table 2
+
+ @retval TRUE The statuses of the 2 SMM source descriptors are identical.
+ @retval FALSE The statuses of the 2 SMM source descriptors are not identical.
+**/
+BOOLEAN
+CompareStatuses (
+ CONST IN PCH_SMM_SOURCE_DESC *Src1,
+ CONST IN PCH_SMM_SOURCE_DESC *Src2
+ )
+{
+ BOOLEAN IsEqual;
+ UINTN DescIndex;
+
+ IsEqual = TRUE;
+
+ for (DescIndex = 0; DescIndex < NUM_STS_BITS; DescIndex++) {
+ ///
+ /// It's okay to compare a NULL bit description to a non-NULL bit description.
+ /// They are unequal and these tests will generate the correct result.
+ ///
+ if (Src1->Sts[DescIndex].Bit != Src2->Sts[DescIndex].Bit ||
+ Src1->Sts[DescIndex].Reg.Type != Src2->Sts[DescIndex].Reg.Type ||
+ Src1->Sts[DescIndex].Reg.Data.raw != Src2->Sts[DescIndex].Reg.Data.raw
+ ) {
+ IsEqual = FALSE;
+ break;
+ ///
+ /// out of for loop
+ ///
+ }
+ }
+
+ return IsEqual;
+}
+
+/**
+ Compare 2 SMM source descriptors, based on Enable settings and Status settings of them.
+
+ @param[in] Src1 Pointer to the PCH SMI source description table 1
+ @param[in] Src2 Pointer to the PCH SMI source description table 2
+
+ @retval TRUE The 2 SMM source descriptors are identical.
+ @retval FALSE The 2 SMM source descriptors are not identical.
+**/
+BOOLEAN
+CompareSources (
+ CONST IN PCH_SMM_SOURCE_DESC *Src1,
+ CONST IN PCH_SMM_SOURCE_DESC *Src2
+ )
+{
+ return (BOOLEAN) (CompareEnables (Src1, Src2) && CompareStatuses (Src1, Src2));
+}
+
+/**
+ Check if an SMM source is active.
+
+ @param[in] Src Pointer to the PCH SMI source description table
+ @param[in] SciEn Indicate if SCI is enabled or not
+ @param[in] SmiEnValue Value from R_ACPI_IO_SMI_EN
+ @param[in] SmiStsValue Value from R_ACPI_IO_SMI_STS
+
+ @retval TRUE It is active.
+ @retval FALSE It is inactive.
+**/
+BOOLEAN
+SourceIsActive (
+ CONST IN PCH_SMM_SOURCE_DESC *Src,
+ CONST IN BOOLEAN SciEn,
+ CONST IN UINT32 SmiEnValue,
+ CONST IN UINT32 SmiStsValue
+ )
+{
+ UINTN DescIndex;
+
+ ///
+ /// This source is dependent on SciEn, and SciEn == 1. An ACPI OS is present,
+ /// so we shouldn't do anything w/ this source until SciEn == 0.
+ ///
+ if ((Src->Flags == PCH_SMM_SCI_EN_DEPENDENT) && (SciEn)) {
+ return FALSE;
+ }
+
+ ///
+ /// Checking top level SMI status. If the status is not active, return false immediately
+ ///
+ if (!IS_BIT_DESC_NULL (Src->PmcSmiSts)) {
+ if ((Src->PmcSmiSts.Reg.Type == ACPI_ADDR_TYPE) &&
+ (Src->PmcSmiSts.Reg.Data.acpi == R_ACPI_IO_SMI_STS) &&
+ ((SmiStsValue & (1u << Src->PmcSmiSts.Bit)) == 0)) {
+ return FALSE;
+ }
+ }
+
+ ///
+ /// Read each bit desc from hardware and make sure it's a one
+ ///
+ for (DescIndex = 0; DescIndex < NUM_EN_BITS; DescIndex++) {
+ if (!IS_BIT_DESC_NULL (Src->En[DescIndex])) {
+ if ((Src->En[DescIndex].Reg.Type == ACPI_ADDR_TYPE) &&
+ (Src->En[DescIndex].Reg.Data.acpi == R_ACPI_IO_SMI_EN) &&
+ ((SmiEnValue & (1u << Src->En[DescIndex].Bit)) == 0)) {
+ return FALSE;
+ } else if (ReadBitDesc (&Src->En[DescIndex]) == 0) {
+ return FALSE;
+ }
+ }
+ }
+
+ ///
+ /// Read each bit desc from hardware and make sure it's a one
+ ///
+ for (DescIndex = 0; DescIndex < NUM_STS_BITS; DescIndex++) {
+ if (!IS_BIT_DESC_NULL (Src->Sts[DescIndex])) {
+ if ((Src->Sts[DescIndex].Reg.Type == ACPI_ADDR_TYPE) &&
+ (Src->Sts[DescIndex].Reg.Data.acpi == R_ACPI_IO_SMI_STS) &&
+ ((SmiStsValue & (1u << Src->Sts[DescIndex].Bit)) == 0)) {
+ return FALSE;
+ } else if (ReadBitDesc (&Src->Sts[DescIndex]) == 0) {
+ return FALSE;
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+/**
+ Enable the SMI source event by set the SMI enable bit, this function would also clear SMI
+ status bit to make initial state is correct
+
+ @param[in] SrcDesc Pointer to the PCH SMI source description table
+
+**/
+VOID
+PchSmmEnableSource (
+ CONST PCH_SMM_SOURCE_DESC *SrcDesc
+ )
+{
+ UINTN DescIndex;
+
+ ///
+ /// Set enables to 1 by writing a 1
+ ///
+ for (DescIndex = 0; DescIndex < NUM_EN_BITS; DescIndex++) {
+ if (!IS_BIT_DESC_NULL (SrcDesc->En[DescIndex])) {
+ WriteBitDesc (&SrcDesc->En[DescIndex], 1, FALSE);
+ }
+ }
+ ///
+ /// Clear statuses to 0 by writing a 1
+ ///
+ for (DescIndex = 0; DescIndex < NUM_STS_BITS; DescIndex++) {
+ if (!IS_BIT_DESC_NULL (SrcDesc->Sts[DescIndex])) {
+ WriteBitDesc (&SrcDesc->Sts[DescIndex], 1, TRUE);
+ }
+ }
+}
+
+/**
+ Disable the SMI source event by clear the SMI enable bit
+
+ @param[in] SrcDesc Pointer to the PCH SMI source description table
+
+**/
+VOID
+PchSmmDisableSource (
+ CONST PCH_SMM_SOURCE_DESC *SrcDesc
+ )
+{
+ UINTN DescIndex;
+
+ for (DescIndex = 0; DescIndex < NUM_EN_BITS; DescIndex++) {
+ if (!IS_BIT_DESC_NULL (SrcDesc->En[DescIndex])) {
+ WriteBitDesc (&SrcDesc->En[DescIndex], 0, FALSE);
+ }
+ }
+}
+
+/**
+ Clear the SMI status bit by set the source bit of SMI status register
+
+ @param[in] SrcDesc Pointer to the PCH SMI source description table
+
+**/
+VOID
+PchSmmClearSource (
+ CONST PCH_SMM_SOURCE_DESC *SrcDesc
+ )
+{
+ UINTN DescIndex;
+
+ for (DescIndex = 0; DescIndex < NUM_STS_BITS; DescIndex++) {
+ if (!IS_BIT_DESC_NULL (SrcDesc->Sts[DescIndex])) {
+ WriteBitDesc (&SrcDesc->Sts[DescIndex], 1, TRUE);
+ }
+ }
+}
+
+/**
+ Sets the source to a 1 and then waits for it to clear.
+ Be very careful when calling this function -- it will not
+ ASSERT. An acceptable case to call the function is when
+ waiting for the NEWCENTURY_STS bit to clear (which takes
+ 3 RTCCLKs).
+
+ @param[in] SrcDesc Pointer to the PCH SMI source description table
+
+**/
+VOID
+PchSmmClearSourceAndBlock (
+ CONST PCH_SMM_SOURCE_DESC *SrcDesc
+ )
+{
+ UINTN DescIndex;
+ BOOLEAN IsSet;
+
+ for (DescIndex = 0; DescIndex < NUM_STS_BITS; DescIndex++) {
+
+ if (!IS_BIT_DESC_NULL (SrcDesc->Sts[DescIndex])) {
+ ///
+ /// Write the bit
+ ///
+ WriteBitDesc (&SrcDesc->Sts[DescIndex], 1, TRUE);
+
+ ///
+ /// Don't return until the bit actually clears.
+ ///
+ IsSet = TRUE;
+ while (IsSet) {
+ IsSet = ReadBitDesc (&SrcDesc->Sts[DescIndex]);
+ ///
+ /// IsSet will eventually clear -- or else we'll have
+ /// an infinite loop.
+ ///
+ }
+ }
+ }
+}
+
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmHelpers.h b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmHelpers.h
new file mode 100644
index 0000000000..db7713fa02
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmHelpers.h
@@ -0,0 +1,155 @@
+/** @file
+ Helper functions for PCH SMM
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef PCH_SMM_HELPERS_H
+#define PCH_SMM_HELPERS_H
+
+#include "PchSmm.h"
+#include "PchxSmmHelpers.h"
+//
+// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// SUPPORT / HELPER FUNCTIONS (PCH version-independent)
+//
+
+/**
+ Publish SMI Dispatch protocols.
+
+
+**/
+VOID
+PchSmmPublishDispatchProtocols (
+ VOID
+ );
+
+/**
+ Compare 2 SMM source descriptors' enable settings.
+
+ @param[in] Src1 Pointer to the PCH SMI source description table 1
+ @param[in] Src2 Pointer to the PCH SMI source description table 2
+
+ @retval TRUE The enable settings of the 2 SMM source descriptors are identical.
+ @retval FALSE The enable settings of the 2 SMM source descriptors are not identical.
+**/
+BOOLEAN
+CompareEnables (
+ CONST IN PCH_SMM_SOURCE_DESC *Src1,
+ CONST IN PCH_SMM_SOURCE_DESC *Src2
+ );
+
+/**
+ Compare a bit descriptor to the enables of source descriptor. Includes null address type.
+
+ @param[in] BitDesc Pointer to the PCH SMI bit descriptor
+ @param[in] Src Pointer to the PCH SMI source description table 2
+
+ @retval TRUE The bit desc is equal to any of the enables in source descriptor
+ @retval FALSE The bid desc is not equal to all of the enables in source descriptor
+**/
+BOOLEAN
+IsBitEqualToAnySourceEn (
+ CONST IN PCH_SMM_BIT_DESC *BitDesc,
+ CONST IN PCH_SMM_SOURCE_DESC *Src
+ );
+
+/**
+ Compare 2 SMM source descriptors' statuses.
+
+ @param[in] Src1 Pointer to the PCH SMI source description table 1
+ @param[in] Src2 Pointer to the PCH SMI source description table 2
+
+ @retval TRUE The statuses of the 2 SMM source descriptors are identical.
+ @retval FALSE The statuses of the 2 SMM source descriptors are not identical.
+**/
+BOOLEAN
+CompareStatuses (
+ CONST IN PCH_SMM_SOURCE_DESC *Src1,
+ CONST IN PCH_SMM_SOURCE_DESC *Src2
+ );
+
+/**
+ Compare 2 SMM source descriptors, based on Enable settings and Status settings of them.
+
+ @param[in] Src1 Pointer to the PCH SMI source description table 1
+ @param[in] Src2 Pointer to the PCH SMI source description table 2
+
+ @retval TRUE The 2 SMM source descriptors are identical.
+ @retval FALSE The 2 SMM source descriptors are not identical.
+**/
+BOOLEAN
+CompareSources (
+ CONST IN PCH_SMM_SOURCE_DESC *Src1,
+ CONST IN PCH_SMM_SOURCE_DESC *Src2
+ );
+
+/**
+ Check if an SMM source is active.
+
+ @param[in] Src Pointer to the PCH SMI source description table
+ @param[in] SciEn Indicate if SCI is enabled or not
+ @param[in] SmiEnValue Value from R_PCH_SMI_EN
+ @param[in] SmiStsValue Value from R_PCH_SMI_STS
+
+ @retval TRUE It is active.
+ @retval FALSE It is inactive.
+**/
+BOOLEAN
+SourceIsActive (
+ CONST IN PCH_SMM_SOURCE_DESC *Src,
+ CONST IN BOOLEAN SciEn,
+ CONST IN UINT32 SmiEnValue,
+ CONST IN UINT32 SmiStsValue
+ );
+
+/**
+ Enable the SMI source event by set the SMI enable bit, this function would also clear SMI
+ status bit to make initial state is correct
+
+ @param[in] SrcDesc Pointer to the PCH SMI source description table
+
+**/
+VOID
+PchSmmEnableSource (
+ CONST PCH_SMM_SOURCE_DESC *SrcDesc
+ );
+
+/**
+ Disable the SMI source event by clear the SMI enable bit
+
+ @param[in] SrcDesc Pointer to the PCH SMI source description table
+
+**/
+VOID
+PchSmmDisableSource (
+ CONST PCH_SMM_SOURCE_DESC *SrcDesc
+ );
+
+/**
+ Clear the SMI status bit by set the source bit of SMI status register
+
+ @param[in] SrcDesc Pointer to the PCH SMI source description table
+
+**/
+VOID
+PchSmmClearSource (
+ CONST PCH_SMM_SOURCE_DESC *SrcDesc
+ );
+
+/**
+ Sets the source to a 1 and then waits for it to clear.
+ Be very careful when calling this function -- it will not
+ ASSERT. An acceptable case to call the function is when
+ waiting for the NEWCENTURY_STS bit to clear (which takes
+ 3 RTCCLKs).
+
+ @param[in] SrcDesc Pointer to the PCH SMI source description table
+
+**/
+VOID
+PchSmmClearSourceAndBlock (
+ CONST PCH_SMM_SOURCE_DESC *SrcDesc
+ );
+
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmPeriodicTimer.c b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmPeriodicTimer.c
new file mode 100644
index 0000000000..3c3e638cbf
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmPeriodicTimer.c
@@ -0,0 +1,667 @@
+/** @file
+ File to contain all the hardware specific stuff for the Periodical Timer dispatch protocol.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include "PchSmmHelpers.h"
+#include <Protocol/PchSmmPeriodicTimerControl.h>
+#include <Library/PmcPrivateLib.h>
+
+//
+// There is only one instance for PeriodicTimerCommBuffer.
+// It's safe in SMM since there is no re-entry for the function.
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_SMM_PERIODIC_TIMER_CONTEXT mPchPeriodicTimerCommBuffer;
+
+typedef enum {
+ PERIODIC_TIMER= 0,
+ SWSMI_TIMER,
+ NUM_TIMERS
+} SUPPORTED_TIMER;
+
+typedef struct _TIMER_INTERVAL {
+ UINT64 Interval;
+ UINT8 AssociatedTimer;
+} TIMER_INTERVAL;
+
+#define NUM_INTERVALS 8
+
+//
+// Time constants, in 100 nano-second units
+//
+#define TIME_64s 640000000 ///< 64 s
+#define TIME_32s 320000000 ///< 32 s
+#define TIME_16s 160000000 ///< 16 s
+#define TIME_8s 80000000 ///< 8 s
+#define TIME_64ms 640000 ///< 64 ms
+#define TIME_32ms 320000 ///< 32 ms
+#define TIME_16ms 160000 ///< 16 ms
+#define TIME_1_5ms 15000 ///< 1.5 ms
+
+typedef enum {
+ INDEX_TIME_64s = 0,
+ INDEX_TIME_32s,
+ INDEX_TIME_16s,
+ INDEX_TIME_8s,
+ INDEX_TIME_64ms,
+ INDEX_TIME_32ms,
+ INDEX_TIME_16ms,
+ INDEX_TIME_1_5ms,
+ INDEX_TIME_MAX
+} TIMER_INTERVAL_INDEX;
+
+static TIMER_INTERVAL mSmmPeriodicTimerIntervals[NUM_INTERVALS] = {
+ {
+ TIME_64s,
+ PERIODIC_TIMER
+ },
+ {
+ TIME_32s,
+ PERIODIC_TIMER
+ },
+ {
+ TIME_16s,
+ PERIODIC_TIMER
+ },
+ {
+ TIME_8s,
+ PERIODIC_TIMER
+ },
+ {
+ TIME_64ms,
+ SWSMI_TIMER
+ },
+ {
+ TIME_32ms,
+ SWSMI_TIMER
+ },
+ {
+ TIME_16ms,
+ SWSMI_TIMER
+ },
+ {
+ TIME_1_5ms,
+ SWSMI_TIMER
+ },
+};
+
+typedef struct _TIMER_INFO {
+ UINTN NumChildren; ///< number of children using this timer
+ UINT64 MinReqInterval; ///< minimum interval required by children
+ UINTN CurrentSetting; ///< interval this timer is set at right now (index into interval table)
+} TIMER_INFO;
+
+GLOBAL_REMOVE_IF_UNREFERENCED TIMER_INFO mTimers[NUM_TIMERS];
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mTimerSourceDesc[NUM_TIMERS] = {
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_ACPI_IO_SMI_EN}
+ },
+ S_ACPI_IO_SMI_EN,
+ N_ACPI_IO_SMI_EN_PERIODIC
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_ACPI_IO_SMI_STS}
+ },
+ S_ACPI_IO_SMI_STS,
+ N_ACPI_IO_SMI_STS_PERIODIC
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_ACPI_IO_SMI_STS}
+ },
+ S_ACPI_IO_SMI_STS,
+ N_ACPI_IO_SMI_STS_PERIODIC
+ }
+ },
+ {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_ACPI_IO_SMI_EN}
+ },
+ S_ACPI_IO_SMI_EN,
+ N_ACPI_IO_SMI_EN_SWSMI_TMR
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_ACPI_IO_SMI_STS}
+ },
+ S_ACPI_IO_SMI_STS,
+ N_ACPI_IO_SMI_STS_SWSMI_TMR
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_ACPI_IO_SMI_STS}
+ },
+ S_ACPI_IO_SMI_STS,
+ N_ACPI_IO_SMI_STS_SWSMI_TMR
+ }
+ }
+};
+
+/**
+ Program Smm Periodic Timer
+
+ @param[in] SrcDesc Pointer to the PCH_SMM_SOURCE_DESC instance.
+**/
+VOID
+PchSmmPeriodicTimerProgramTimers (
+ IN CONST PCH_SMM_SOURCE_DESC *SrcDesc
+ );
+
+/**
+ Convert the dispatch context to the timer interval, this function will assert if then either:
+ (1) The context contains an invalid interval
+ (2) The timer interval table is corrupt
+
+ @param[in] DispatchContext The pointer to the Dispatch Context
+
+ @retval TIMER_INTERVAL The timer interval of input dispatch context
+**/
+TIMER_INTERVAL *
+ContextToTimerInterval (
+ IN PCH_SMM_CONTEXT *DispatchContext
+ )
+{
+ UINTN loopvar;
+
+ ///
+ /// Determine which timer this child is using
+ ///
+ for (loopvar = 0; loopvar < NUM_INTERVALS; loopvar++) {
+ if (((DispatchContext->PeriodicTimer.SmiTickInterval == 0) &&
+ (DispatchContext->PeriodicTimer.Period >= mSmmPeriodicTimerIntervals[loopvar].Interval)) ||
+ (DispatchContext->PeriodicTimer.SmiTickInterval == mSmmPeriodicTimerIntervals[loopvar].Interval)) {
+ return &mSmmPeriodicTimerIntervals[loopvar];
+ }
+ }
+ ///
+ /// If this assertion fires, then either:
+ /// (1) the context contains an invalid interval
+ /// (2) the timer interval table is corrupt
+ ///
+ ASSERT (FALSE);
+
+ return NULL;
+}
+
+/**
+ Figure out which timer the child is requesting and
+ send back the source description
+
+ @param[in] DispatchContext The pointer to the Dispatch Context instances
+ @param[out] SrcDesc The pointer to the source description
+
+**/
+VOID
+MapPeriodicTimerToSrcDesc (
+ IN PCH_SMM_CONTEXT *DispatchContext,
+ OUT PCH_SMM_SOURCE_DESC *SrcDesc
+ )
+{
+ TIMER_INTERVAL *TimerInterval;
+
+ ///
+ /// Figure out which timer the child is requesting and
+ /// send back the source description
+ ///
+ TimerInterval = ContextToTimerInterval (DispatchContext);
+ if (TimerInterval == NULL) {
+ return;
+ }
+
+ CopyMem (
+ (VOID *) SrcDesc,
+ (VOID *) (&mTimerSourceDesc[TimerInterval->AssociatedTimer]),
+ sizeof (PCH_SMM_SOURCE_DESC)
+ );
+
+ ///
+ /// Program the value of the interval into hardware
+ ///
+ PchSmmPeriodicTimerProgramTimers (SrcDesc);
+}
+
+/**
+ Update the elapsed time from the Interval data of DATABASE_RECORD
+
+ @param[in] Record The pointer to the DATABASE_RECORD.
+ @param[out] HwContext The Context to be updated.
+
+**/
+VOID
+EFIAPI
+PeriodicTimerGetContext (
+ IN DATABASE_RECORD *Record,
+ OUT PCH_SMM_CONTEXT *HwContext
+ )
+{
+ TIMER_INTERVAL *TimerInterval;
+
+ ASSERT (Record->ProtocolType == PeriodicTimerType);
+
+ TimerInterval = ContextToTimerInterval (&Record->ChildContext);
+ if (TimerInterval == NULL) {
+ return;
+ }
+ ///
+ /// Ignore the hardware context. It's not required for this protocol.
+ /// Instead, just increment the child's context.
+ /// Update the elapsed time w/ the data from our tables
+ ///
+ Record->MiscData.ElapsedTime += mTimers[TimerInterval->AssociatedTimer].MinReqInterval;
+ *HwContext = Record->ChildContext;
+}
+
+/**
+ Check whether Periodic Timer of two contexts match
+
+ @param[in] Context1 Context 1 that includes Periodic Timer 1
+ @param[in] Context2 Context 2 that includes Periodic Timer 2
+
+ @retval FALSE Periodic Timer match
+ @retval TRUE Periodic Timer don't match
+**/
+BOOLEAN
+EFIAPI
+PeriodicTimerCmpContext (
+ IN PCH_SMM_CONTEXT *HwContext,
+ IN PCH_SMM_CONTEXT *ChildContext
+ )
+{
+ DATABASE_RECORD *Record;
+ Record = DATABASE_RECORD_FROM_CHILDCONTEXT (ChildContext);
+
+ if (!Record->MiscData.TimerSmiEnabled) {
+ return FALSE;
+ }
+ if (Record->MiscData.ElapsedTime >= ChildContext->PeriodicTimer.Period) {
+ ///
+ /// For EDKII, the ElapsedTime is reset when PeriodicTimerGetCommBuffer
+ ///
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+/**
+ Gather the CommBuffer information of SmmPeriodicTimerDispatch2.
+
+ @param[in] Record No use
+ @param[out] CommBuffer Point to the CommBuffer structure
+ @param[out] CommBufferSize Point to the Size of CommBuffer structure
+
+**/
+VOID
+EFIAPI
+PeriodicTimerGetCommBuffer (
+ IN DATABASE_RECORD *Record,
+ OUT VOID **CommBuffer,
+ OUT UINTN *CommBufferSize
+ )
+{
+ ASSERT (Record->ProtocolType == PeriodicTimerType);
+
+ mPchPeriodicTimerCommBuffer.ElapsedTime = Record->MiscData.ElapsedTime;
+
+ ///
+ /// For EDKII, the ElapsedTime is reset here
+ ///
+ Record->MiscData.ElapsedTime = 0;
+
+ ///
+ /// Return the CommBuffer
+ ///
+ *CommBuffer = (VOID *) &mPchPeriodicTimerCommBuffer;
+ *CommBufferSize = sizeof (EFI_SMM_PERIODIC_TIMER_CONTEXT);
+}
+
+/**
+ Program Smm Periodic Timer
+
+ @param[in] SrcDesc Pointer to the PCH_SMM_SOURCE_DESC instance.
+**/
+VOID
+PchSmmPeriodicTimerProgramTimers (
+ IN CONST PCH_SMM_SOURCE_DESC *SrcDesc
+ )
+{
+ SUPPORTED_TIMER Timer;
+ DATABASE_RECORD *RecordInDb;
+ LIST_ENTRY *LinkInDb;
+ TIMER_INTERVAL *TimerInterval;
+
+ ///
+ /// Find the minimum required interval for each timer
+ ///
+ for (Timer = 0; Timer < NUM_TIMERS; Timer++) {
+ mTimers[Timer].MinReqInterval = ~ (UINT64) 0x0;
+ mTimers[Timer].NumChildren = 0;
+ }
+
+ LinkInDb = GetFirstNode (&mPrivateData.CallbackDataBase);
+ while (!IsNull (&mPrivateData.CallbackDataBase, LinkInDb)) {
+ RecordInDb = DATABASE_RECORD_FROM_LINK (LinkInDb);
+ if (RecordInDb->ProtocolType == PeriodicTimerType) {
+ if (RecordInDb->MiscData.TimerSmiEnabled) {
+ ///
+ /// This child is registerd with the PeriodicTimer protocol
+ ///
+ TimerInterval = ContextToTimerInterval (&RecordInDb->ChildContext);
+ if (TimerInterval == NULL) {
+ return;
+ }
+
+ Timer = TimerInterval->AssociatedTimer;
+ if (Timer < 0 || Timer >= NUM_TIMERS) {
+ ASSERT (FALSE);
+ CpuDeadLoop ();
+ return;
+ }
+ if (mTimers[Timer].MinReqInterval > RecordInDb->ChildContext.PeriodicTimer.SmiTickInterval) {
+ mTimers[Timer].MinReqInterval = RecordInDb->ChildContext.PeriodicTimer.SmiTickInterval;
+ }
+ mTimers[Timer].NumChildren++;
+ }
+ }
+ LinkInDb = GetNextNode (&mPrivateData.CallbackDataBase, &RecordInDb->Link);
+ }
+ ///
+ /// Program the hardware
+ ///
+ if (mTimers[PERIODIC_TIMER].NumChildren > 0) {
+ switch (mTimers[PERIODIC_TIMER].MinReqInterval) {
+ case TIME_64s:
+ PmcSetPeriodicSmiRate (PmcPeriodicSmiRate64s);
+ mTimers[PERIODIC_TIMER].CurrentSetting = INDEX_TIME_64s;
+ break;
+
+ case TIME_32s:
+ PmcSetPeriodicSmiRate (PmcPeriodicSmiRate32s);
+ mTimers[PERIODIC_TIMER].CurrentSetting = INDEX_TIME_32s;
+ break;
+
+ case TIME_16s:
+ PmcSetPeriodicSmiRate (PmcPeriodicSmiRate16s);
+ mTimers[PERIODIC_TIMER].CurrentSetting = INDEX_TIME_16s;
+ break;
+
+ case TIME_8s:
+ PmcSetPeriodicSmiRate (PmcPeriodicSmiRate8s);
+ mTimers[PERIODIC_TIMER].CurrentSetting = INDEX_TIME_8s;
+ break;
+
+ default:
+ ASSERT (FALSE);
+ break;
+ }
+
+ ///
+ /// Restart the timer here, just need to clear the SMI
+ ///
+ if (SrcDesc->Sts[0].Bit == N_ACPI_IO_SMI_STS_PERIODIC) {
+ PchSmmClearSource (&mTimerSourceDesc[PERIODIC_TIMER]);
+ }
+ } else {
+ PchSmmDisableSource (&mTimerSourceDesc[PERIODIC_TIMER]);
+ }
+
+ if (mTimers[SWSMI_TIMER].NumChildren > 0) {
+ switch (mTimers[SWSMI_TIMER].MinReqInterval) {
+ case TIME_64ms:
+ PmcSetSwSmiRate (PmcSwSmiRate64ms);
+ mTimers[SWSMI_TIMER].CurrentSetting = INDEX_TIME_64ms;
+ break;
+
+ case TIME_32ms:
+ PmcSetSwSmiRate (PmcSwSmiRate32ms);
+ mTimers[SWSMI_TIMER].CurrentSetting = INDEX_TIME_32ms;
+ break;
+
+ case TIME_16ms:
+ PmcSetSwSmiRate (PmcSwSmiRate16ms);
+ mTimers[SWSMI_TIMER].CurrentSetting = INDEX_TIME_16ms;
+ break;
+
+ case TIME_1_5ms:
+ PmcSetSwSmiRate (PmcSwSmiRate1p5ms);
+ mTimers[SWSMI_TIMER].CurrentSetting = INDEX_TIME_1_5ms;
+ break;
+
+ default:
+ ASSERT (FALSE);
+ break;
+ }
+
+ ///
+ /// Restart the timer here, need to disable, clear, then enable to restart this timer
+ ///
+ if (SrcDesc->Sts[0].Bit == N_ACPI_IO_SMI_STS_SWSMI_TMR) {
+ PchSmmDisableSource (&mTimerSourceDesc[SWSMI_TIMER]);
+ PchSmmClearSource (&mTimerSourceDesc[SWSMI_TIMER]);
+ PchSmmEnableSource (&mTimerSourceDesc[SWSMI_TIMER]);
+ }
+ } else {
+ PchSmmDisableSource (&mTimerSourceDesc[SWSMI_TIMER]);
+ }
+}
+
+/**
+ This services returns the next SMI tick period that is supported by the chipset.
+ The order returned is from longest to shortest interval period.
+
+ @param[in] This Pointer to the EFI_SMM_PERIODIC_TIMER_DISPATCH2_PROTOCOL instance.
+ @param[in, out] SmiTickInterval Pointer to pointer of the next shorter SMI interval period that is supported by the child.
+
+ @retval EFI_SUCCESS The service returned successfully.
+ @retval EFI_INVALID_PARAMETER The parameter SmiTickInterval is invalid.
+**/
+EFI_STATUS
+PchSmmPeriodicTimerDispatchGetNextShorterInterval (
+ IN CONST EFI_SMM_PERIODIC_TIMER_DISPATCH2_PROTOCOL *This,
+ IN OUT UINT64 **SmiTickInterval
+ )
+{
+ TIMER_INTERVAL *IntervalPointer;
+
+ ASSERT (SmiTickInterval != NULL);
+
+ IntervalPointer = (TIMER_INTERVAL *) *SmiTickInterval;
+
+ if (IntervalPointer == NULL) {
+ ///
+ /// The first time child requesting an interval
+ ///
+ IntervalPointer = &mSmmPeriodicTimerIntervals[0];
+ } else if (IntervalPointer == &mSmmPeriodicTimerIntervals[NUM_INTERVALS - 1]) {
+ ///
+ /// At end of the list
+ ///
+ IntervalPointer = NULL;
+ } else {
+ if ((IntervalPointer >= &mSmmPeriodicTimerIntervals[0]) &&
+ (IntervalPointer < &mSmmPeriodicTimerIntervals[NUM_INTERVALS - 1])
+ ) {
+ ///
+ /// Get the next interval in the list
+ ///
+ IntervalPointer++;
+ } else {
+ ///
+ /// Input is out of range
+ ///
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ if (IntervalPointer != NULL) {
+ *SmiTickInterval = &IntervalPointer->Interval;
+ } else {
+ *SmiTickInterval = NULL;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function is responsible for calculating and enabling any timers that are required
+ to dispatch messages to children. The SrcDesc argument isn't acutally used.
+
+ @param[in] SrcDesc Pointer to the PCH_SMM_SOURCE_DESC instance.
+
+**/
+VOID
+EFIAPI
+PchSmmPeriodicTimerClearSource (
+ IN CONST PCH_SMM_SOURCE_DESC *SrcDesc
+ )
+{
+ PchSmmPeriodicTimerProgramTimers (SrcDesc);
+}
+
+
+/**
+ Check if the handle is in type of PeriodicTimer
+
+ @retval TRUE The handle is in type of PeriodicTimer.
+ @retval FALSE The handle is not in type of PeriodicTimer.
+**/
+BOOLEAN
+IsSmmPeriodicTimerHandle (
+ IN EFI_HANDLE DispatchHandle
+ )
+{
+ DATABASE_RECORD *RecordInDb;
+ LIST_ENTRY *LinkInDb;
+
+ LinkInDb = GetFirstNode (&mPrivateData.CallbackDataBase);
+ while (!IsNull (&mPrivateData.CallbackDataBase, LinkInDb)) {
+ if (DispatchHandle == (EFI_HANDLE) LinkInDb) {
+ RecordInDb = DATABASE_RECORD_FROM_LINK (LinkInDb);
+ if (RecordInDb->ProtocolType == PeriodicTimerType) {
+ return TRUE;
+ }
+ }
+ LinkInDb = GetNextNode (&mPrivateData.CallbackDataBase, LinkInDb);
+ }
+ return FALSE;
+}
+
+/**
+ Pause SMM periodic timer callback function.
+
+ This function disable the SMI enable of SMI timer according to the DispatchHandle,
+ which is returned by SMM periodic timer callback registration.
+
+ @retval EFI_SUCCESS This operation is complete.
+ @retval EFI_INVALID_PARAMETER The DispatchHandle is invalid.
+**/
+EFI_STATUS
+EFIAPI
+PchSmmPeriodicTimerControlPause (
+ IN PCH_SMM_PERIODIC_TIMER_CONTROL_PROTOCOL *This,
+ IN EFI_HANDLE DispatchHandle
+ )
+{
+ DATABASE_RECORD *RecordInDb;
+
+ if (IsSmmPeriodicTimerHandle (DispatchHandle) == FALSE) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ RecordInDb = DATABASE_RECORD_FROM_LINK (DispatchHandle);
+ RecordInDb->MiscData.TimerSmiEnabled = FALSE;
+ //
+ // reset the timer interval per SMI trigger due to stop a periodic timer SMI
+ //
+ PchSmmPeriodicTimerProgramTimers (&RecordInDb->SrcDesc);
+ return EFI_SUCCESS;
+}
+
+/**
+ Resume SMM periodic timer callback function.
+
+ This function enable the SMI enable of SMI timer according to the DispatchHandle,
+ which is returned by SMM periodic timer callback registration.
+
+ @retval EFI_SUCCESS This operation is complete.
+ @retval EFI_INVALID_PARAMETER The DispatchHandle is invalid.
+**/
+EFI_STATUS
+EFIAPI
+PchSmmPeriodicTimerControlResume (
+ IN PCH_SMM_PERIODIC_TIMER_CONTROL_PROTOCOL *This,
+ IN EFI_HANDLE DispatchHandle
+ )
+{
+ DATABASE_RECORD *RecordInDb;
+
+ if (IsSmmPeriodicTimerHandle (DispatchHandle) == FALSE) {
+ return EFI_INVALID_PARAMETER;
+ }
+ RecordInDb = DATABASE_RECORD_FROM_LINK (DispatchHandle);
+ RecordInDb->MiscData.TimerSmiEnabled = TRUE;
+ //
+ // reset the timer interval per SMI trigger due to resume a periodic timer SMI
+ //
+ PchSmmPeriodicTimerProgramTimers (&RecordInDb->SrcDesc);
+ return EFI_SUCCESS;
+}
+
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_SMM_PERIODIC_TIMER_CONTROL_PROTOCOL mPchSmmPeriodicTimerControlProtocol = {
+ PchSmmPeriodicTimerControlPause,
+ PchSmmPeriodicTimerControlResume
+};
+
+/**
+ Install PCH SMM periodic timer control protocol
+
+ @param[in] Handle handle for this driver
+
+ @retval EFI_SUCCESS Driver initialization completed successfully
+**/
+EFI_STATUS
+EFIAPI
+InstallPchSmmPeriodicTimerControlProtocol (
+ IN EFI_HANDLE Handle
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Install protocol interface
+ //
+ Status = gSmst->SmmInstallProtocolInterface (
+ &Handle,
+ &gPchSmmPeriodicTimerControlGuid,
+ EFI_NATIVE_INTERFACE,
+ &mPchSmmPeriodicTimerControlProtocol
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
+
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmPowerButton.c b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmPowerButton.c
new file mode 100644
index 0000000000..bfed944848
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmPowerButton.c
@@ -0,0 +1,81 @@
+/** @file
+ File to contain all the hardware specific stuff for the Smm Power Button dispatch protocol.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include <PchSmmHelpers.h>
+#include <Library/PmcPrivateLib.h>
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mPowerButtonSourceDesc = {
+ PCH_SMM_SCI_EN_DEPENDENT,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_ACPI_IO_PM1_EN}
+ },
+ S_ACPI_IO_PM1_EN,
+ N_ACPI_IO_PM1_EN_PWRBTN
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_ACPI_IO_PM1_STS}
+ },
+ S_ACPI_IO_PM1_STS,
+ N_ACPI_IO_PM1_STS_PWRBTN
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_ACPI_IO_SMI_STS}
+ },
+ S_ACPI_IO_SMI_STS,
+ N_ACPI_IO_SMI_STS_PM1_STS_REG
+ }
+};
+
+/**
+ Get the power button status.
+
+ @param[in] Record The pointer to the DATABASE_RECORD.
+ @param[out] Context Calling context from the hardware, will be updated with the current power button status.
+
+**/
+VOID
+EFIAPI
+PowerButtonGetContext (
+ IN DATABASE_RECORD *Record,
+ OUT PCH_SMM_CONTEXT *Context
+ )
+{
+ if (PmcGetPwrBtnLevel ()) {
+ Context->PowerButton.Phase = EfiPowerButtonExit;
+ } else {
+ Context->PowerButton.Phase = EfiPowerButtonEntry;
+ }
+}
+
+/**
+ Check whether Power Button status of two contexts match
+
+ @param[in] Context1 Context 1 that includes Power Button status 1
+ @param[in] Context2 Context 2 that includes Power Button status 2
+
+ @retval FALSE Power Button status match
+ @retval TRUE Power Button status don't match
+**/
+BOOLEAN
+EFIAPI
+PowerButtonCmpContext (
+ IN PCH_SMM_CONTEXT *Context1,
+ IN PCH_SMM_CONTEXT *Context2
+ )
+{
+ return (BOOLEAN) (Context1->PowerButton.Phase == Context2->PowerButton.Phase);
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmSw.c b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmSw.c
new file mode 100644
index 0000000000..9b13bf6308
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmSw.c
@@ -0,0 +1,381 @@
+/** @file
+ File to contain all the hardware specific stuff for the Smm Sw dispatch protocol.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include "PchSmmHelpers.h"
+#include <Protocol/SmmCpu.h>
+#include <Register/PchRegsLpc.h>
+#include <Register/PmcRegs.h>
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_SMM_CPU_PROTOCOL *mSmmCpuProtocol;
+
+STATIC LIST_ENTRY mSwSmiCallbackDataBase;
+
+//
+// "SWSMI" RECORD
+// Linked list data structures
+//
+#define SW_SMI_RECORD_SIGNATURE SIGNATURE_32 ('S', 'W', 'S', 'M')
+
+#define SW_SMI_RECORD_FROM_LINK(_record) CR (_record, SW_SMI_RECORD, Link, SW_SMI_RECORD_SIGNATURE)
+
+typedef struct {
+ UINT32 Signature;
+ LIST_ENTRY Link;
+ EFI_SMM_SW_REGISTER_CONTEXT Context;
+ EFI_SMM_HANDLER_ENTRY_POINT2 Callback;
+} SW_SMI_RECORD;
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSwSourceDesc = {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_ACPI_IO_SMI_EN}
+ },
+ S_ACPI_IO_SMI_EN,
+ N_ACPI_IO_SMI_EN_APMC
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_ACPI_IO_SMI_STS}
+ },
+ S_ACPI_IO_SMI_STS,
+ N_ACPI_IO_SMI_STS_APM
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_ACPI_IO_SMI_STS}
+ },
+ S_ACPI_IO_SMI_STS,
+ N_ACPI_IO_SMI_STS_APM
+ }
+};
+
+/**
+ Check the SwSmiInputValue to see if there is a duplicated one in the database
+
+ @param[in] SwSmiInputValue SwSmiInputValue
+
+ @retval EFI_SUCCESS There is no duplicated SwSmiInputValue
+ @retval EFI_INVALID_PARAMETER There is a duplicated SwSmiInputValue
+**/
+EFI_STATUS
+SmiInputValueDuplicateCheck (
+ IN UINTN SwSmiInputValue
+ )
+{
+ SW_SMI_RECORD *SwSmiRecord;
+ LIST_ENTRY *LinkInDb;
+
+ LinkInDb = GetFirstNode (&mSwSmiCallbackDataBase);
+ while (!IsNull (&mSwSmiCallbackDataBase, LinkInDb)) {
+ SwSmiRecord = SW_SMI_RECORD_FROM_LINK (LinkInDb);
+ if (SwSmiRecord->Context.SwSmiInputValue == SwSmiInputValue) {
+ return EFI_INVALID_PARAMETER;
+ }
+ LinkInDb = GetNextNode (&mSwSmiCallbackDataBase, &SwSmiRecord->Link);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Register a child SMI source dispatch function for the specified software SMI.
+
+ This service registers a function (DispatchFunction) which will be called when the software
+ SMI source specified by RegisterContext->SwSmiCpuIndex is detected. On return,
+ DispatchHandle contains a unique handle which may be used later to unregister the function
+ using UnRegister().
+
+ @param[in] This Pointer to the EFI_SMM_SW_DISPATCH2_PROTOCOL instance.
+ @param[in] DispatchFunction Function to register for handler when the specified software
+ SMI is generated.
+ @param[in, out] RegisterContext Pointer to the dispatch function's context.
+ The caller fills this context in before calling
+ the register function to indicate to the register
+ function which Software SMI input value the
+ dispatch function should be invoked for.
+ @param[out] DispatchHandle Handle generated by the dispatcher to track the
+ function instance.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully
+ registered and the SMI source has been enabled.
+ @retval EFI_DEVICE_ERROR The SW driver was unable to enable the SMI source.
+ @retval EFI_INVALID_PARAMETER RegisterContext is invalid. The SW SMI input value
+ is not within a valid range or is already in use.
+ @retval EFI_OUT_OF_RESOURCES There is not enough memory (system or SMM) to manage this
+ child.
+ @retval EFI_OUT_OF_RESOURCES A unique software SMI value could not be assigned
+ for this dispatch.
+**/
+EFI_STATUS
+EFIAPI
+PchSwSmiRegister (
+ IN EFI_SMM_SW_DISPATCH2_PROTOCOL *This,
+ IN EFI_SMM_HANDLER_ENTRY_POINT2 DispatchFunction,
+ IN EFI_SMM_SW_REGISTER_CONTEXT *DispatchContext,
+ OUT EFI_HANDLE *DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+ SW_SMI_RECORD *SwSmiRecord;
+ UINTN Index;
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "Register is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ //
+ // Find available SW SMI value if the input is -1
+ //
+ if (DispatchContext->SwSmiInputValue == (UINTN) -1) {
+ for (Index = 1; Index < MAXIMUM_SWI_VALUE; Index++) {
+ if (!EFI_ERROR (SmiInputValueDuplicateCheck (Index))) {
+ DispatchContext->SwSmiInputValue = Index;
+ break;
+ }
+ }
+ if (DispatchContext->SwSmiInputValue == (UINTN) -1) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ }
+ //
+ // Check if it's a valid SW SMI value.
+ // The value must not bigger than 0xFF.
+ // And the value must not be 0xFF sincie it's used for SmmControll protocol.
+ //
+ if (DispatchContext->SwSmiInputValue >= MAXIMUM_SWI_VALUE) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (EFI_ERROR (SmiInputValueDuplicateCheck (DispatchContext->SwSmiInputValue))) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Create database record and add to database
+ //
+ Status = gSmst->SmmAllocatePool (
+ EfiRuntimeServicesData,
+ sizeof (SW_SMI_RECORD),
+ (VOID **) &SwSmiRecord
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed to allocate memory for SwSmiRecord! \n"));
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Gather information about the registration request
+ //
+ SwSmiRecord->Signature = SW_SMI_RECORD_SIGNATURE;
+ SwSmiRecord->Context.SwSmiInputValue = DispatchContext->SwSmiInputValue;
+ SwSmiRecord->Callback = DispatchFunction;
+ //
+ // Publish the S/W SMI numbers in Serial logs used for Debug build.
+ //
+ DEBUG ((DEBUG_INFO, "SW SMI NUM %x Sw Record at Address 0x%X\n", SwSmiRecord->Context.SwSmiInputValue, SwSmiRecord));
+
+ InsertTailList (&mSwSmiCallbackDataBase, &SwSmiRecord->Link);
+
+ //
+ // Child's handle will be the address linked list link in the record
+ //
+ *DispatchHandle = (EFI_HANDLE) (&SwSmiRecord->Link);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Unregister a child SMI source dispatch function for the specified software SMI.
+
+ This service removes the handler associated with DispatchHandle so that it will no longer be
+ called in response to a software SMI.
+
+ @param[in] This Pointer to the EFI_SMM_SW_DISPATCH2_PROTOCOL instance.
+ @param[in] DispatchHandle Handle of dispatch function to deregister.
+
+ @retval EFI_SUCCESS The dispatch function has been successfully unregistered.
+ @retval EFI_INVALID_PARAMETER The DispatchHandle was not valid.
+**/
+EFI_STATUS
+EFIAPI
+PchSwSmiUnRegister (
+ IN CONST EFI_SMM_SW_DISPATCH2_PROTOCOL *This,
+ IN EFI_HANDLE DispatchHandle
+ )
+{
+ EFI_STATUS Status;
+ SW_SMI_RECORD *RecordToDelete;
+
+ if (DispatchHandle == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Return access denied if the SmmReadyToLock event has been triggered
+ //
+ if (mReadyToLock == TRUE) {
+ DEBUG ((DEBUG_ERROR, "UnRegister is not allowed if the SmmReadyToLock event has been triggered! \n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ RecordToDelete = SW_SMI_RECORD_FROM_LINK (DispatchHandle);
+ //
+ // Take the entry out of the linked list
+ //
+ if (RecordToDelete->Signature != SW_SMI_RECORD_SIGNATURE) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ RemoveEntryList (&RecordToDelete->Link);
+ ZeroMem (RecordToDelete, sizeof (SW_SMI_RECORD));
+ Status = gSmst->SmmFreePool (RecordToDelete);
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Main entry point for an SMM handler dispatch or communicate-based callback.
+
+ @param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
+ @param[in] Context Points to an optional handler context which was specified when the
+ handler was registered.
+ @param[in,out] CommBuffer A pointer to a collection of data in memory that will
+ be conveyed from a non-SMM environment into an SMM environment.
+ @param[in,out] CommBufferSize The size of the CommBuffer.
+
+ @retval EFI_SUCCESS The interrupt was handled and quiesced. No other handlers
+ should still be called.
+ @retval EFI_WARN_INTERRUPT_SOURCE_QUIESCED The interrupt has been quiesced but other handlers should
+ still be called.
+ @retval EFI_WARN_INTERRUPT_SOURCE_PENDING The interrupt is still pending and other handlers should still
+ be called.
+ @retval EFI_INTERRUPT_PENDING The interrupt could not be quiesced.
+**/
+EFI_STATUS
+EFIAPI
+PchSwSmiDispatcher (
+ IN EFI_HANDLE DispatchHandle,
+ IN CONST VOID *Context,
+ IN OUT VOID *CommBuffer,
+ IN OUT UINTN *CommBufferSize
+ )
+{
+ EFI_STATUS Status;
+ EFI_SMM_SAVE_STATE_IO_INFO SmiIoInfo;
+ UINTN CpuIndex;
+ SW_SMI_RECORD *SwSmiRecord;
+ LIST_ENTRY *LinkInDb;
+ EFI_SMM_SW_CONTEXT SwSmiCommBuffer;
+ UINTN SwSmiCommBufferSize;
+
+ SwSmiCommBufferSize = sizeof (EFI_SMM_SW_CONTEXT);
+ //
+ // The value in DataPort might not be accurate in multiple thread environment.
+ // There might be racing condition for R_PCH_IO_APM_STS port.
+ // Therefor, this is just for reference.
+ //
+ SwSmiCommBuffer.DataPort = IoRead8 (R_PCH_IO_APM_STS);
+
+ for (CpuIndex = 0; CpuIndex < gSmst->NumberOfCpus; CpuIndex++) {
+ Status = mSmmCpuProtocol->ReadSaveState (
+ mSmmCpuProtocol,
+ sizeof (EFI_SMM_SAVE_STATE_IO_INFO),
+ EFI_SMM_SAVE_STATE_REGISTER_IO,
+ CpuIndex,
+ &SmiIoInfo
+ );
+ //
+ // If this is not the SMI source, skip it.
+ //
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+ //
+ // If the IO address is not "BYTE" "WRITE" to "R_PCH_IO_APM_CNT (0xB2)", skip it.
+ //
+ if ((SmiIoInfo.IoPort != R_PCH_IO_APM_CNT) ||
+ (SmiIoInfo.IoType != EFI_SMM_SAVE_STATE_IO_TYPE_OUTPUT) ||
+ (SmiIoInfo.IoWidth != EFI_SMM_SAVE_STATE_IO_WIDTH_UINT8))
+ {
+ continue;
+ }
+ //
+ // If the IO data is used for SmmControl protocol, skip it.
+ //
+ if (SmiIoInfo.IoData == 0xFF) {
+ continue;
+ }
+
+ SwSmiCommBuffer.SwSmiCpuIndex = CpuIndex;
+ SwSmiCommBuffer.CommandPort = (UINT8) SmiIoInfo.IoData;
+
+ LinkInDb = GetFirstNode (&mSwSmiCallbackDataBase);
+ while (!IsNull (&mSwSmiCallbackDataBase, LinkInDb)) {
+ SwSmiRecord = SW_SMI_RECORD_FROM_LINK (LinkInDb);
+ if (SwSmiRecord->Context.SwSmiInputValue == SmiIoInfo.IoData) {
+ SwSmiRecord->Callback ((EFI_HANDLE) &SwSmiRecord->Link, &SwSmiRecord->Context, &SwSmiCommBuffer, &SwSmiCommBufferSize);
+ }
+ LinkInDb = GetNextNode (&mSwSmiCallbackDataBase, &SwSmiRecord->Link);
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Init required protocol for Pch Sw Dispatch protocol.
+**/
+VOID
+PchSwDispatchInit (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE DispatchHandle;
+ DATABASE_RECORD Record;
+
+ //
+ // Locate PI SMM CPU protocol
+ //
+ Status = gSmst->SmmLocateProtocol (&gEfiSmmCpuProtocolGuid, NULL, (VOID **)&mSmmCpuProtocol);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Initialize SW SMI Callback DataBase
+ //
+ InitializeListHead (&mSwSmiCallbackDataBase);
+
+ //
+ // Insert SwSmi handler to PchSmmCore database
+ // There will always be one SwType record in PchSmmCore database
+ //
+ ZeroMem (&Record, sizeof (DATABASE_RECORD));
+ Record.Signature = DATABASE_RECORD_SIGNATURE;
+ Record.Callback = PchSwSmiDispatcher;
+ Record.ProtocolType = SwType;
+
+ CopyMem (&Record.SrcDesc, &mSwSourceDesc, sizeof (PCH_SMM_SOURCE_DESC));
+
+ DispatchHandle = NULL;
+ Status = SmmCoreInsertRecord (
+ &Record,
+ &DispatchHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmSx.c b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmSx.c
new file mode 100644
index 0000000000..7d79f21dbd
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmSx.c
@@ -0,0 +1,224 @@
+/** @file
+ File to contain all the hardware specific stuff for the Smm Sx dispatch protocol.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include "PchSmmHelpers.h"
+#include <Register/PmcRegs.h>
+#include <Register/PchPcieRpRegs.h>
+#include <Library/PchPciBdfLib.h>
+#include "PchSmiHelper.h"
+
+extern BOOLEAN mS3SusStart;
+#define PROGRESS_CODE_S3_SUSPEND_END PcdGet32 (PcdProgressCodeS3SuspendEnd)
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mSxSourceDesc = {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_ACPI_IO_SMI_EN}
+ },
+ S_ACPI_IO_SMI_EN,
+ N_ACPI_IO_SMI_EN_ON_SLP_EN
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_ACPI_IO_SMI_STS}
+ },
+ S_ACPI_IO_SMI_STS,
+ N_ACPI_IO_SMI_STS_ON_SLP_EN
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_ACPI_IO_SMI_STS}
+ },
+ S_ACPI_IO_SMI_STS,
+ N_ACPI_IO_SMI_STS_ON_SLP_EN
+ }
+};
+
+/**
+ Get the Sleep type
+
+ @param[in] Record No use
+ @param[out] Context The context that includes SLP_TYP bits to be filled
+
+**/
+VOID
+EFIAPI
+SxGetContext (
+ IN DATABASE_RECORD *Record,
+ OUT PCH_SMM_CONTEXT *Context
+ )
+{
+ UINT32 Pm1Cnt;
+
+ Pm1Cnt = IoRead32 ((UINTN) (mAcpiBaseAddr + R_ACPI_IO_PM1_CNT));
+
+ ///
+ /// By design, the context phase will always be ENTRY
+ ///
+ Context->Sx.Phase = SxEntry;
+
+ ///
+ /// Map the PM1_CNT register's SLP_TYP bits to the context type
+ ///
+ switch (Pm1Cnt & B_ACPI_IO_PM1_CNT_SLP_TYP) {
+ case V_ACPI_IO_PM1_CNT_S0:
+ Context->Sx.Type = SxS0;
+ break;
+
+ case V_ACPI_IO_PM1_CNT_S1:
+ Context->Sx.Type = SxS1;
+ break;
+
+ case V_ACPI_IO_PM1_CNT_S3:
+ Context->Sx.Type = SxS3;
+ break;
+
+ case V_ACPI_IO_PM1_CNT_S4:
+ Context->Sx.Type = SxS4;
+ break;
+
+ case V_ACPI_IO_PM1_CNT_S5:
+ Context->Sx.Type = SxS5;
+ break;
+
+ default:
+ ASSERT (FALSE);
+ break;
+ }
+}
+
+/**
+ Check whether sleep type of two contexts match
+
+ @param[in] Context1 Context 1 that includes sleep type 1
+ @param[in] Context2 Context 2 that includes sleep type 2
+
+ @retval FALSE Sleep types match
+ @retval TRUE Sleep types don't match
+**/
+BOOLEAN
+EFIAPI
+SxCmpContext (
+ IN PCH_SMM_CONTEXT *Context1,
+ IN PCH_SMM_CONTEXT *Context2
+ )
+{
+ return (BOOLEAN) (Context1->Sx.Type == Context2->Sx.Type);
+}
+
+/**
+ For each PCIE RP clear PME SCI status and disable SCI, then PCIEXP_WAKE_STS from PMC.
+ This prevents platform from waking more than one time due to a single PCIE wake event.
+ Normally it's up to OS to clear SCI statuses. But in a scenario where platform wakes
+ and goes to S5 instead of booting to OS, the SCI status would remain set and would trigger another wake.
+**/
+VOID
+ClearPcieSci (
+ VOID
+ )
+{
+ UINT32 MaxPorts;
+ UINT32 RpIndex;
+ UINT64 RpBase;
+
+ MaxPorts = GetPchMaxPciePortNum ();
+ for (RpIndex = 0; RpIndex < MaxPorts; RpIndex++) {
+ RpBase = PchPcieRpPciCfgBase (RpIndex);
+ if (PciSegmentRead16 (RpBase + PCI_VENDOR_ID_OFFSET) != 0xFFFF) {
+ PciSegmentAnd8 ((RpBase + R_PCH_PCIE_CFG_MPC + 3), (UINT8)~((UINT8)(B_PCH_PCIE_CFG_MPC_PMCE >> 24)));
+ PciSegmentWrite32 (RpBase + R_PCH_PCIE_CFG_SMSCS, B_PCH_PCIE_CFG_SMSCS_PMCS);
+ }
+ }
+ IoWrite16 (mAcpiBaseAddr + R_ACPI_IO_PM1_STS, B_ACPI_IO_PM1_STS_PCIEXP_WAKE_STS);
+}
+
+
+/**
+ When we get an SMI that indicates that we are transitioning to a sleep state,
+ we need to actually transition to that state. We do this by disabling the
+ "SMI on sleep enable" feature, which generates an SMI when the operating system
+ tries to put the system to sleep, and then physically putting the system to sleep.
+
+
+**/
+VOID
+PchSmmSxGoToSleep (
+ VOID
+ )
+{
+ UINT32 Pm1Cnt;
+
+ ClearPcieSci ();
+
+ ///
+ /// Disable SMIs
+ ///
+ PchSmmClearSource (&mSxSourceDesc);
+ PchSmmDisableSource (&mSxSourceDesc);
+
+ ///
+ /// Get Power Management 1 Control Register Value
+ ///
+ Pm1Cnt = IoRead32 ((UINTN) (mAcpiBaseAddr + R_ACPI_IO_PM1_CNT));
+
+ ///
+ /// Record S3 suspend performance data
+ ///
+ if ((Pm1Cnt & B_ACPI_IO_PM1_CNT_SLP_TYP) == V_ACPI_IO_PM1_CNT_S3) {
+ ///
+ /// Report status code before goto S3 sleep
+ ///
+ REPORT_STATUS_CODE (EFI_PROGRESS_CODE, PROGRESS_CODE_S3_SUSPEND_END);
+ mS3SusStart = FALSE;
+ ///
+ /// Write back cache into memory and invalidate cache before going to sleep.
+ ///
+ AsmWbinvd ();
+ }
+
+ ///
+ /// Now that SMIs are disabled, write to the SLP_EN bit again to trigger the sleep
+ ///
+ Pm1Cnt |= B_ACPI_IO_PM1_CNT_SLP_EN;
+
+ IoWrite32 ((UINTN) (mAcpiBaseAddr + R_ACPI_IO_PM1_CNT), Pm1Cnt);
+
+ ///
+ /// Should only proceed if wake event is generated.
+ ///
+ if ((Pm1Cnt & B_ACPI_IO_PM1_CNT_SLP_TYP) == V_ACPI_IO_PM1_CNT_S1) {
+ while (((IoRead16 ((UINTN) (mAcpiBaseAddr + R_ACPI_IO_PM1_STS))) & B_ACPI_IO_PM1_STS_WAK) == 0x0);
+ } else {
+ CpuDeadLoop ();
+ }
+ ///
+ /// The system just went to sleep. If the sleep state was S1, then code execution will resume
+ /// here when the system wakes up.
+ ///
+ Pm1Cnt = IoRead32 ((UINTN) (mAcpiBaseAddr + R_ACPI_IO_PM1_CNT));
+
+ if ((Pm1Cnt & B_ACPI_IO_PM1_CNT_SCI_EN) == 0) {
+ ///
+ /// An ACPI OS isn't present, clear the sleep information
+ ///
+ Pm1Cnt &= ~B_ACPI_IO_PM1_CNT_SLP_TYP;
+ Pm1Cnt |= V_ACPI_IO_PM1_CNT_S0;
+
+ IoWrite32 ((UINTN) (mAcpiBaseAddr + R_ACPI_IO_PM1_CNT), Pm1Cnt);
+ }
+
+ PchSmmClearSource (&mSxSourceDesc);
+ PchSmmEnableSource (&mSxSourceDesc);
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmUsb.c b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmUsb.c
new file mode 100644
index 0000000000..a0c67bd959
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchSmmUsb.c
@@ -0,0 +1,230 @@
+/** @file
+ File to contain all the hardware specific stuff for the Smm USB dispatch protocol.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include "PchSmmHelpers.h"
+#include <Register/UsbRegs.h>
+#include <Register/PchRegsLpc.h>
+#include <Register/PmcRegs.h>
+#include <Library/PchPciBdfLib.h>
+#include <PchBdfAssignment.h>
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mUsb1Legacy = {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_ACPI_IO_SMI_EN}
+ },
+ S_ACPI_IO_SMI_EN,
+ N_ACPI_IO_SMI_EN_LEGACY_USB
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_ACPI_IO_SMI_STS}
+ },
+ S_ACPI_IO_SMI_STS,
+ N_ACPI_IO_SMI_STS_LEGACY_USB
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_ACPI_IO_SMI_STS}
+ },
+ S_ACPI_IO_SMI_STS,
+ N_ACPI_IO_SMI_STS_LEGACY_USB
+ }
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC mUsb3Legacy = {
+ PCH_SMM_NO_FLAGS,
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_ACPI_IO_SMI_EN}
+ },
+ S_ACPI_IO_SMI_EN,
+ N_ACPI_IO_SMI_EN_LEGACY_USB3
+ },
+ NULL_BIT_DESC_INITIALIZER
+ },
+ {
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_ACPI_IO_SMI_STS}
+ },
+ S_ACPI_IO_SMI_STS,
+ N_ACPI_IO_SMI_STS_LEGACY_USB3
+ }
+ },
+ {
+ {
+ ACPI_ADDR_TYPE,
+ {R_ACPI_IO_SMI_STS}
+ },
+ S_ACPI_IO_SMI_STS,
+ N_ACPI_IO_SMI_STS_LEGACY_USB3
+ }
+};
+
+typedef enum {
+ PchUsbControllerLpc0 = 0,
+ PchUsbControllerXhci,
+ PchUsbControllerTypeMax
+} PCH_USB_CONTROLLER_TYPE;
+
+typedef struct {
+ UINT8 Function;
+ UINT8 Device;
+ PCH_USB_CONTROLLER_TYPE UsbConType;
+} USB_CONTROLLER;
+
+GLOBAL_REMOVE_IF_UNREFERENCED USB_CONTROLLER mUsbControllersMap[] = {
+ {
+ PCI_FUNCTION_NUMBER_PCH_LPC,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PchUsbControllerLpc0
+ },
+ {
+ PCI_FUNCTION_NUMBER_PCH_XHCI,
+ PCI_DEVICE_NUMBER_PCH_XHCI,
+ PchUsbControllerXhci
+ }
+};
+
+/**
+ Find the handle that best matches the input Device Path and return the USB controller type
+
+ @param[in] DevicePath Pointer to the device Path table
+ @param[out] Controller Returned with the USB controller type of the input device path
+
+ @retval EFI_SUCCESS Find the handle that best matches the input Device Path
+ @exception EFI_UNSUPPORTED Invalid device Path table or can't find any match USB device path
+ PCH_USB_CONTROLLER_TYPE The USB controller type of the input
+ device path
+**/
+EFI_STATUS
+DevicePathToSupportedController (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ OUT PCH_USB_CONTROLLER_TYPE *Controller
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE DeviceHandle;
+ ACPI_HID_DEVICE_PATH *AcpiNode;
+ PCI_DEVICE_PATH *PciNode;
+ EFI_DEVICE_PATH_PROTOCOL *RemaingDevicePath;
+ UINT8 UsbIndex;
+ ///
+ /// Find the handle that best matches the Device Path. If it is only a
+ /// partial match the remaining part of the device path is returned in
+ /// RemainingDevicePath.
+ ///
+ RemaingDevicePath = DevicePath;
+ Status = gBS->LocateDevicePath (
+ &gEfiPciRootBridgeIoProtocolGuid,
+ &DevicePath,
+ &DeviceHandle
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ DevicePath = RemaingDevicePath;
+
+ ///
+ /// Get first node: Acpi Node
+ ///
+ AcpiNode = (ACPI_HID_DEVICE_PATH *) RemaingDevicePath;
+
+ if (AcpiNode->Header.Type != ACPI_DEVICE_PATH ||
+ AcpiNode->Header.SubType != ACPI_DP ||
+ DevicePathNodeLength (&AcpiNode->Header) != sizeof (ACPI_HID_DEVICE_PATH) ||
+ AcpiNode->HID != EISA_PNP_ID (0x0A03) ||
+ AcpiNode->UID != 0
+ ) {
+ return EFI_UNSUPPORTED;
+ } else {
+ ///
+ /// Get the next node: Pci Node
+ ///
+ RemaingDevicePath = NextDevicePathNode (RemaingDevicePath);
+ PciNode = (PCI_DEVICE_PATH *) RemaingDevicePath;
+ if (PciNode->Header.Type != HARDWARE_DEVICE_PATH ||
+ PciNode->Header.SubType != HW_PCI_DP ||
+ DevicePathNodeLength (&PciNode->Header) != sizeof (PCI_DEVICE_PATH)
+ ) {
+ return EFI_UNSUPPORTED;
+ }
+
+ for (UsbIndex = 0; UsbIndex < sizeof (mUsbControllersMap) / sizeof (USB_CONTROLLER); UsbIndex++) {
+ if ((PciNode->Device == mUsbControllersMap[UsbIndex].Device) &&
+ (PciNode->Function == mUsbControllersMap[UsbIndex].Function)) {
+ *Controller = mUsbControllersMap[UsbIndex].UsbConType;
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_UNSUPPORTED;
+ }
+}
+
+/**
+ Maps a USB context to a source description.
+
+ @param[in] Context The context we need to map. Type must be USB.
+ @param[in] SrcDesc The source description that corresponds to the given context.
+
+**/
+VOID
+MapUsbToSrcDesc (
+ IN PCH_SMM_CONTEXT *Context,
+ OUT PCH_SMM_SOURCE_DESC *SrcDesc
+ )
+{
+ PCH_USB_CONTROLLER_TYPE Controller;
+ EFI_STATUS Status;
+
+ Status = DevicePathToSupportedController (Context->Usb.Device, &Controller);
+ ///
+ /// Either the device path passed in by the child is incorrect or
+ /// the ones stored here internally are incorrect.
+ ///
+ ASSERT_EFI_ERROR (Status);
+
+ switch (Context->Usb.Type) {
+ case UsbLegacy:
+ switch (Controller) {
+ case PchUsbControllerLpc0:
+ CopyMem ((VOID *) SrcDesc, (VOID *) (&mUsb1Legacy), sizeof (PCH_SMM_SOURCE_DESC));
+ break;
+
+ case PchUsbControllerXhci:
+ CopyMem ((VOID *) SrcDesc, (VOID *) (&mUsb3Legacy), sizeof (PCH_SMM_SOURCE_DESC));
+ break;
+
+ default:
+ ASSERT (FALSE);
+ break;
+ }
+ break;
+
+ case UsbWake:
+ ASSERT (FALSE);
+ break;
+
+ default:
+ ASSERT (FALSE);
+ break;
+ }
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchxSmmHelpers.c b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchxSmmHelpers.c
new file mode 100644
index 0000000000..a0b7e37d46
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchxSmmHelpers.c
@@ -0,0 +1,778 @@
+/** @file
+ This driver is responsible for the registration of child drivers
+ and the abstraction of the PCH SMI sources.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include "PchSmmHelpers.h"
+#include <Register/PchRegs.h>
+#include <Register/PmcRegs.h>
+
+//
+// Help handle porting bit shifts to IA-64.
+//
+#define BIT_ZERO 0x00000001
+
+/**
+ Publish SMI Dispatch protocols.
+
+
+**/
+VOID
+PchSmmPublishDispatchProtocols (
+ VOID
+ )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+ UINTN Index;
+ //
+ // Install protocol interfaces.
+ //
+ for (Index = 0; Index < PCH_SMM_PROTOCOL_TYPE_MAX; Index++) {
+ Status = gSmst->SmmInstallProtocolInterface (
+ &mPrivateData.InstallMultProtHandle,
+ mPrivateData.Protocols[Index].Guid,
+ EFI_NATIVE_INTERFACE,
+ &mPrivateData.Protocols[Index].Protocols.Generic
+ );
+ }
+ ASSERT_EFI_ERROR (Status);
+}
+
+/**
+ Initialize bits that aren't necessarily related to an SMI source.
+
+
+ @retval EFI_SUCCESS SMI source initialization completed.
+ @retval Asserts Global Smi Bit is not enabled successfully.
+**/
+EFI_STATUS
+PchSmmInitHardware (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Clear all SMIs
+ //
+ PchSmmClearSmi ();
+
+ Status = PchSmmEnableGlobalSmiBit ();
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Be *really* sure to clear all SMIs
+ //
+ PchSmmClearSmi ();
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Enables the PCH to generate SMIs. Note that no SMIs will be generated
+ if no SMI sources are enabled. Conversely, no enabled SMI source will
+ generate SMIs if SMIs are not globally enabled. This is the main
+ switchbox for SMI generation.
+
+
+ @retval EFI_SUCCESS Enable Global Smi Bit completed
+**/
+EFI_STATUS
+PchSmmEnableGlobalSmiBit (
+ VOID
+ )
+{
+ UINT32 SmiEn;
+
+ SmiEn = IoRead32 ((UINTN) (mAcpiBaseAddr + R_ACPI_IO_SMI_EN));
+
+ //
+ // Set the "global smi enable" bit
+ //
+ SmiEn |= B_ACPI_IO_SMI_EN_GBL_SMI;
+
+ IoWrite32 ((UINTN) (mAcpiBaseAddr + R_ACPI_IO_SMI_EN), SmiEn);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Clears the SMI after all SMI source have been processed.
+ Note that this function will not work correctly (as it is
+ written) unless all SMI sources have been processed.
+ A revision of this function could manually clear all SMI
+ status bits to guarantee success.
+
+
+ @retval EFI_SUCCESS Clears the SMIs completed
+ @retval Asserts EOS was not set to a 1
+**/
+EFI_STATUS
+PchSmmClearSmi (
+ VOID
+ )
+{
+ BOOLEAN EosSet;
+ BOOLEAN SciEn;
+ UINT32 Pm1Cnt;
+ UINT16 Pm1Sts;
+ UINT32 Gpe0Sts;
+ UINT32 SmiSts;
+ UINT16 DevActSts;
+ UINT16 Tco1Sts;
+
+ Gpe0Sts = 0;
+ //
+ // Determine whether an ACPI OS is present (via the SCI_EN bit)
+ //
+ Pm1Cnt = IoRead32 ((UINTN) (mAcpiBaseAddr + R_ACPI_IO_PM1_CNT));
+ SciEn = (BOOLEAN) ((Pm1Cnt & B_ACPI_IO_PM1_CNT_SCI_EN) == B_ACPI_IO_PM1_CNT_SCI_EN);
+ if (!SciEn) {
+ //
+ // Clear any SMIs that double as SCIs (when SCI_EN==0)
+ //
+ Pm1Sts = IoRead16 ((UINTN) (mAcpiBaseAddr + R_ACPI_IO_PM1_STS));
+ Gpe0Sts = IoRead32 ((UINTN) (mAcpiBaseAddr + R_ACPI_IO_GPE0_STS_127_96));
+
+ Pm1Sts |=
+ (
+ B_ACPI_IO_PM1_STS_WAK |
+ B_ACPI_IO_PM1_STS_PRBTNOR |
+ B_ACPI_IO_PM1_STS_RTC |
+ B_ACPI_IO_PM1_STS_PWRBTN |
+ B_ACPI_IO_PM1_STS_GBL |
+ B_ACPI_IO_PM1_STS_TMROF
+ );
+
+ Gpe0Sts |=
+ (
+ B_ACPI_IO_GPE0_STS_127_96_WADT |
+ B_ACPI_IO_GPE0_STS_127_96_USB_CON_DSX_STS |
+ B_ACPI_IO_GPE0_STS_127_96_LAN_WAKE |
+ B_ACPI_IO_GPE0_STS_127_96_PME_B0 |
+ B_ACPI_IO_GPE0_STS_127_96_PME |
+ B_ACPI_IO_GPE0_STS_127_96_BATLOW |
+ B_ACPI_IO_GPE0_STS_127_96_RI |
+ B_ACPI_IO_GPE0_STS_127_96_SWGPE
+ );
+
+ IoWrite16 ((UINTN) (mAcpiBaseAddr + R_ACPI_IO_PM1_STS), (UINT16) Pm1Sts);
+ IoWrite32 ((UINTN) (mAcpiBaseAddr + R_ACPI_IO_GPE0_STS_127_96), (UINT32) Gpe0Sts);
+ }
+ //
+ // Clear all SMIs that are unaffected by SCI_EN
+ //
+ SmiSts = IoRead32 ((UINTN) (mAcpiBaseAddr + R_ACPI_IO_SMI_STS));
+ DevActSts = IoRead16 ((UINTN) (mAcpiBaseAddr + R_ACPI_IO_DEVACT_STS));
+ Tco1Sts = IoRead16 ((UINTN) (mTcoBaseAddr + R_TCO_IO_TCO1_STS));
+
+ SmiSts |=
+ (
+ B_ACPI_IO_SMI_STS_SMBUS |
+ B_ACPI_IO_SMI_STS_PERIODIC |
+ B_ACPI_IO_SMI_STS_TCO |
+ B_ACPI_IO_SMI_STS_MCSMI |
+ B_ACPI_IO_SMI_STS_SWSMI_TMR |
+ B_ACPI_IO_SMI_STS_APM |
+ B_ACPI_IO_SMI_STS_ON_SLP_EN |
+ B_ACPI_IO_SMI_STS_BIOS
+ );
+ DevActSts |=
+ (
+ B_ACPI_IO_DEVACT_STS_KBC |
+ B_ACPI_IO_DEVACT_STS_PIRQDH |
+ B_ACPI_IO_DEVACT_STS_PIRQCG |
+ B_ACPI_IO_DEVACT_STS_PIRQBF |
+ B_ACPI_IO_DEVACT_STS_PIRQAE
+ );
+ Tco1Sts |=
+ (
+ B_TCO_IO_TCO1_STS_DMISERR |
+ B_TCO_IO_TCO1_STS_DMISMI |
+ B_TCO_IO_TCO1_STS_DMISCI |
+ B_TCO_IO_TCO1_STS_BIOSWR |
+ B_TCO_IO_TCO1_STS_NEWCENTURY |
+ B_TCO_IO_TCO1_STS_TIMEOUT |
+ B_TCO_IO_TCO1_STS_TCO_INT |
+ B_TCO_IO_TCO1_STS_SW_TCO_SMI
+ );
+
+ GpioClearAllGpiSmiSts ();
+
+ IoWrite16 ((UINTN) (mTcoBaseAddr + R_TCO_IO_TCO1_STS), Tco1Sts);
+
+ //
+ // We do not want to write 1 to clear INTRD_DET bit.
+ //
+ IoWrite16 ((UINTN) (mTcoBaseAddr + R_TCO_IO_TCO2_STS), (UINT16) ~B_TCO_IO_TCO2_STS_INTRD_DET);
+
+ IoWrite32 ((UINTN) (mAcpiBaseAddr + R_ACPI_IO_SMI_STS), SmiSts);
+
+ IoWrite16 ((UINTN) (mAcpiBaseAddr + R_ACPI_IO_DEVACT_STS), DevActSts);
+
+ //
+ // Try to clear the EOS bit. ASSERT on an error
+ //
+ EosSet = PchSmmSetAndCheckEos ();
+ ASSERT (EosSet);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Set the SMI EOS bit after all SMI source have been processed.
+
+
+ @retval FALSE EOS was not set to a 1; this is an error
+ @retval TRUE EOS was correctly set to a 1
+**/
+BOOLEAN
+PchSmmSetAndCheckEos (
+ VOID
+ )
+{
+ UINT32 SmiEn;
+
+ SmiEn = IoRead32 ((UINTN) (mAcpiBaseAddr + R_ACPI_IO_SMI_EN));
+
+ //
+ // Reset the PCH to generate subsequent SMIs
+ //
+ SmiEn |= B_ACPI_IO_SMI_EN_EOS;
+
+ IoWrite32 ((UINTN) (mAcpiBaseAddr + R_ACPI_IO_SMI_EN), SmiEn);
+
+ //
+ // Double check that the assert worked
+ //
+ SmiEn = IoRead32 ((UINTN) (mAcpiBaseAddr + R_ACPI_IO_SMI_EN));
+
+ //
+ // Return TRUE if EOS is set correctly
+ //
+ if ((SmiEn & B_ACPI_IO_SMI_EN_EOS) == 0) {
+ //
+ // EOS was not set to a 1; this is an error
+ //
+ return FALSE;
+ } else {
+ //
+ // EOS was correctly set to a 1
+ //
+ return TRUE;
+ }
+}
+
+/**
+ Determine whether an ACPI OS is present (via the SCI_EN bit)
+
+
+ @retval TRUE ACPI OS is present
+ @retval FALSE ACPI OS is not present
+**/
+BOOLEAN
+PchSmmGetSciEn (
+ VOID
+ )
+{
+ BOOLEAN SciEn;
+ UINT32 Pm1Cnt;
+
+ //
+ // Determine whether an ACPI OS is present (via the SCI_EN bit)
+ //
+ Pm1Cnt = IoRead32 ((UINTN) (mAcpiBaseAddr + R_ACPI_IO_PM1_CNT));
+ SciEn = (BOOLEAN) ((Pm1Cnt & B_ACPI_IO_PM1_CNT_SCI_EN) == B_ACPI_IO_PM1_CNT_SCI_EN);
+
+ return SciEn;
+}
+
+/**
+ Read a specifying bit with the register
+ These may or may not need to change w/ the PCH version; they're highly IA-32 dependent, though.
+
+ @param[in] BitDesc The struct that includes register address, size in byte and bit number
+
+ @retval TRUE The bit is enabled
+ @retval FALSE The bit is disabled
+**/
+BOOLEAN
+ReadBitDesc (
+ CONST PCH_SMM_BIT_DESC *BitDesc
+ )
+{
+ EFI_STATUS Status;
+ UINT64 Register;
+ UINT32 PciBus;
+ UINT32 PciDev;
+ UINT32 PciFun;
+ UINT32 PciReg;
+ UINTN RegSize;
+ BOOLEAN BitWasOne;
+ UINTN ShiftCount;
+ UINTN RegisterOffset;
+ UINT32 BaseAddr;
+ UINT64 PciBaseAddress;
+
+ ASSERT (BitDesc != NULL);
+ ASSERT (!IS_BIT_DESC_NULL (*BitDesc));
+
+ RegSize = 0;
+ Register = 0;
+ ShiftCount = 0;
+ BitWasOne = FALSE;
+
+ switch (BitDesc->Reg.Type) {
+
+ case ACPI_ADDR_TYPE:
+ case TCO_ADDR_TYPE:
+ if (BitDesc->Reg.Type == ACPI_ADDR_TYPE) {
+ RegisterOffset = BitDesc->Reg.Data.acpi;
+ BaseAddr = mAcpiBaseAddr;
+ } else {
+ RegisterOffset = BitDesc->Reg.Data.tco;
+ BaseAddr = mTcoBaseAddr;
+ }
+ switch (BitDesc->SizeInBytes) {
+
+ case 0:
+ //
+ // Chances are that this field didn't get initialized.
+ // Check your assignments to bit descriptions.
+ //
+ ASSERT (FALSE);
+ break;
+
+ case 1:
+ RegSize = SMM_IO_UINT8;
+ break;
+
+ case 2:
+ RegSize = SMM_IO_UINT16;
+ break;
+
+ case 4:
+ RegSize = SMM_IO_UINT32;
+ break;
+
+ case 8:
+ RegSize = SMM_IO_UINT64;
+ break;
+
+ default:
+ //
+ // Unsupported or invalid register size
+ //
+ ASSERT (FALSE);
+ break;
+ }
+ //
+ // Double check that we correctly read in the acpi base address
+ //
+ ASSERT ((BaseAddr != 0x0) && ((BaseAddr & 0x1) != 0x1));
+
+ ShiftCount = BitDesc->Bit;
+ //
+ // As current CPU Smm Io can only support at most
+ // 32-bit read/write,if Operation is 64 bit,
+ // we do a 32 bit operation according to BitDesc->Bit
+ //
+ if (RegSize == SMM_IO_UINT64) {
+ RegSize = SMM_IO_UINT32;
+ //
+ // If the operation is for high 32 bits
+ //
+ if (BitDesc->Bit >= 32) {
+ RegisterOffset += 4;
+ ShiftCount -= 32;
+ }
+ }
+
+ Status = gSmst->SmmIo.Io.Read (
+ &gSmst->SmmIo,
+ RegSize,
+ BaseAddr + RegisterOffset,
+ 1,
+ &Register
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ if ((Register & (LShiftU64 (BIT_ZERO, ShiftCount))) != 0) {
+ BitWasOne = TRUE;
+ } else {
+ BitWasOne = FALSE;
+ }
+ break;
+
+ case GPIO_ADDR_TYPE:
+ case MEMORY_MAPPED_IO_ADDRESS_TYPE:
+ //
+ // Read the register, and it with the bit to read
+ //
+ switch (BitDesc->SizeInBytes) {
+ case 1:
+ Register = (UINT64) MmioRead8 ((UINTN) BitDesc->Reg.Data.Mmio);
+ break;
+
+ case 2:
+ Register = (UINT64) MmioRead16 ((UINTN) BitDesc->Reg.Data.Mmio);
+ break;
+
+ case 4:
+ Register = (UINT64) MmioRead32 ((UINTN) BitDesc->Reg.Data.Mmio);
+ break;
+
+ case 8:
+ Register = (UINT64) MmioRead32 ((UINTN) BitDesc->Reg.Data.Mmio);
+ *((UINT32 *) (&Register) + 1) = MmioRead32 ((UINTN) BitDesc->Reg.Data.Mmio + 4);
+ break;
+
+ default:
+ //
+ // Unsupported or invalid register size
+ //
+ ASSERT (FALSE);
+ break;
+ }
+
+ Register = Register & (LShiftU64 (BIT0, BitDesc->Bit));
+ if (Register) {
+ BitWasOne = TRUE;
+ } else {
+ BitWasOne = FALSE;
+ }
+ break;
+
+ case PCIE_ADDR_TYPE:
+ PciBus = BitDesc->Reg.Data.pcie.Fields.Bus;
+ PciDev = BitDesc->Reg.Data.pcie.Fields.Dev;
+ PciFun = BitDesc->Reg.Data.pcie.Fields.Fnc;
+ PciReg = BitDesc->Reg.Data.pcie.Fields.Reg;
+ PciBaseAddress = PCI_SEGMENT_LIB_ADDRESS (DEFAULT_PCI_SEGMENT_NUMBER_PCH, PciBus, PciDev, PciFun, 0);
+ switch (BitDesc->SizeInBytes) {
+
+ case 0:
+ //
+ // Chances are that this field didn't get initialized.
+ // Check your assignments to bit descriptions.
+ //
+ ASSERT (FALSE);
+ break;
+
+ case 1:
+ Register = (UINT64) PciSegmentRead8 (PciBaseAddress + PciReg);
+ break;
+
+ case 2:
+ Register = (UINT64) PciSegmentRead16 (PciBaseAddress + PciReg);
+ break;
+
+ case 4:
+ Register = (UINT64) PciSegmentRead32 (PciBaseAddress + PciReg);
+ break;
+
+ default:
+ //
+ // Unsupported or invalid register size
+ //
+ ASSERT (FALSE);
+ break;
+ }
+
+ if ((Register & (LShiftU64 (BIT_ZERO, BitDesc->Bit))) != 0) {
+ BitWasOne = TRUE;
+ } else {
+ BitWasOne = FALSE;
+ }
+ break;
+
+ case PCR_ADDR_TYPE:
+ //
+ // Read the register, and it with the bit to read
+ //
+ switch (BitDesc->SizeInBytes) {
+ case 1:
+ Register = PchPcrRead8 (BitDesc->Reg.Data.Pcr.Fields.Pid, BitDesc->Reg.Data.Pcr.Fields.Offset);
+ break;
+
+ case 2:
+ Register = PchPcrRead16 (BitDesc->Reg.Data.Pcr.Fields.Pid, BitDesc->Reg.Data.Pcr.Fields.Offset);
+ break;
+
+ case 4:
+ Register = PchPcrRead32 (BitDesc->Reg.Data.Pcr.Fields.Pid, BitDesc->Reg.Data.Pcr.Fields.Offset);
+ break;
+
+ default:
+ //
+ // Unsupported or invalid register size
+ //
+ ASSERT (FALSE);
+ break;
+ }
+
+ Register = Register & (LShiftU64 (BIT0, BitDesc->Bit));
+ if (Register) {
+ BitWasOne = TRUE;
+ } else {
+ BitWasOne = FALSE;
+ }
+ break;
+
+ default:
+ //
+ // This address type is not yet implemented
+ //
+ ASSERT (FALSE);
+ break;
+ }
+
+ return BitWasOne;
+}
+
+/**
+ Write a specifying bit with the register
+
+ @param[in] BitDesc The struct that includes register address, size in byte and bit number
+ @param[in] ValueToWrite The value to be wrote
+ @param[in] WriteClear If the rest bits of the register is write clear
+
+**/
+VOID
+WriteBitDesc (
+ CONST PCH_SMM_BIT_DESC *BitDesc,
+ CONST BOOLEAN ValueToWrite,
+ CONST BOOLEAN WriteClear
+ )
+{
+ EFI_STATUS Status;
+ UINT64 Register;
+ UINT64 AndVal;
+ UINT64 OrVal;
+ UINT32 RegSize;
+ UINT32 PciBus;
+ UINT32 PciDev;
+ UINT32 PciFun;
+ UINT32 PciReg;
+ UINTN RegisterOffset;
+ UINT32 BaseAddr;
+ UINT64 PciBaseAddress;
+
+ ASSERT (BitDesc != NULL);
+ ASSERT (!IS_BIT_DESC_NULL (*BitDesc));
+
+ RegSize = 0;
+ Register = 0;
+
+ if (WriteClear) {
+ AndVal = LShiftU64 (BIT_ZERO, BitDesc->Bit);
+ } else {
+ AndVal = ~(LShiftU64 (BIT_ZERO, BitDesc->Bit));
+ }
+
+ OrVal = (LShiftU64 ((UINT32) ValueToWrite, BitDesc->Bit));
+
+ switch (BitDesc->Reg.Type) {
+
+ case ACPI_ADDR_TYPE:
+ case TCO_ADDR_TYPE:
+ if (BitDesc->Reg.Type == ACPI_ADDR_TYPE) {
+ RegisterOffset = BitDesc->Reg.Data.acpi;
+ BaseAddr = mAcpiBaseAddr;
+ } else {
+ RegisterOffset = BitDesc->Reg.Data.tco;
+ BaseAddr = mTcoBaseAddr;
+ }
+
+ switch (BitDesc->SizeInBytes) {
+
+ case 0:
+ //
+ // Chances are that this field didn't get initialized.
+ // Check your assignments to bit descriptions.
+ //
+ ASSERT (FALSE);
+ break;
+
+ case 1:
+ RegSize = SMM_IO_UINT8;
+ break;
+
+ case 2:
+ RegSize = SMM_IO_UINT16;
+ break;
+
+ case 4:
+ RegSize = SMM_IO_UINT32;
+ break;
+
+ case 8:
+ RegSize = SMM_IO_UINT64;
+ break;
+
+ default:
+ //
+ // Unsupported or invalid register size
+ //
+ ASSERT (FALSE);
+ break;
+ }
+ //
+ // Double check that we correctly read in the acpi base address
+ //
+ ASSERT ((BaseAddr != 0x0) && ((BaseAddr & 0x1) != 0x1));
+
+ //
+ // As current CPU Smm Io can only support at most
+ // 32-bit read/write,if Operation is 64 bit,
+ // we do a 32 bit operation according to BitDesc->Bit
+ //
+ if (RegSize == SMM_IO_UINT64) {
+ RegSize = SMM_IO_UINT32;
+ //
+ // If the operation is for high 32 bits
+ //
+ if (BitDesc->Bit >= 32) {
+ RegisterOffset += 4;
+
+ if (WriteClear) {
+ AndVal = LShiftU64 (BIT_ZERO, BitDesc->Bit - 32);
+ } else {
+ AndVal = ~(LShiftU64 (BIT_ZERO, BitDesc->Bit - 32));
+ }
+
+ OrVal = LShiftU64 ((UINT32) ValueToWrite, BitDesc->Bit - 32);
+ }
+ }
+
+ Status = gSmst->SmmIo.Io.Read (
+ &gSmst->SmmIo,
+ RegSize,
+ BaseAddr + RegisterOffset,
+ 1,
+ &Register
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Register &= AndVal;
+ Register |= OrVal;
+
+ Status = gSmst->SmmIo.Io.Write (
+ &gSmst->SmmIo,
+ RegSize,
+ BaseAddr + RegisterOffset,
+ 1,
+ &Register
+ );
+ ASSERT_EFI_ERROR (Status);
+ break;
+
+ case GPIO_ADDR_TYPE:
+ case MEMORY_MAPPED_IO_ADDRESS_TYPE:
+ //
+ // Read the register, or it with the bit to set, then write it back.
+ //
+ switch (BitDesc->SizeInBytes) {
+ case 1:
+ MmioAndThenOr8 ((UINTN) BitDesc->Reg.Data.Mmio, (UINT8) AndVal, (UINT8) OrVal);
+ break;
+
+ case 2:
+ MmioAndThenOr16 ((UINTN) BitDesc->Reg.Data.Mmio, (UINT16) AndVal, (UINT16) OrVal);
+ break;
+
+ case 4:
+ MmioAndThenOr32 ((UINTN) BitDesc->Reg.Data.Mmio, (UINT32) AndVal, (UINT32) OrVal);
+ break;
+
+ case 8:
+ Register = (UINT64) MmioRead32 ((UINTN) BitDesc->Reg.Data.Mmio);
+ *((UINT32 *) (&Register) + 1) = MmioRead32 ((UINTN) BitDesc->Reg.Data.Mmio + 4);
+ Register &= AndVal;
+ Register |= OrVal;
+ MmioWrite32 ((UINTN) BitDesc->Reg.Data.Mmio, (UINT32) Register);
+ MmioWrite32 ((UINTN) BitDesc->Reg.Data.Mmio + 4, *((UINT32 *) (&Register) + 1));
+ break;
+
+ default:
+ //
+ // Unsupported or invalid register size
+ //
+ ASSERT (FALSE);
+ break;
+ }
+ break;
+
+ case PCIE_ADDR_TYPE:
+ PciBus = BitDesc->Reg.Data.pcie.Fields.Bus;
+ PciDev = BitDesc->Reg.Data.pcie.Fields.Dev;
+ PciFun = BitDesc->Reg.Data.pcie.Fields.Fnc;
+ PciReg = BitDesc->Reg.Data.pcie.Fields.Reg;
+ PciBaseAddress = PCI_SEGMENT_LIB_ADDRESS (DEFAULT_PCI_SEGMENT_NUMBER_PCH, PciBus, PciDev, PciFun, 0);
+ switch (BitDesc->SizeInBytes) {
+
+ case 0:
+ //
+ // Chances are that this field didn't get initialized -- check your assignments
+ // to bit descriptions.
+ //
+ ASSERT (FALSE);
+ break;
+
+ case 1:
+ PciSegmentAndThenOr8 (PciBaseAddress + PciReg, (UINT8) AndVal, (UINT8) OrVal);
+ break;
+
+ case 2:
+ PciSegmentAndThenOr16 (PciBaseAddress + PciReg, (UINT16) AndVal, (UINT16) OrVal);
+ break;
+
+ case 4:
+ PciSegmentAndThenOr32 (PciBaseAddress + PciReg, (UINT32) AndVal, (UINT32) OrVal);
+ break;
+
+ default:
+ //
+ // Unsupported or invalid register size
+ //
+ ASSERT (FALSE);
+ break;
+ }
+ break;
+
+ case PCR_ADDR_TYPE:
+ //
+ // Read the register, or it with the bit to set, then write it back.
+ //
+ switch (BitDesc->SizeInBytes) {
+ case 1:
+ PchPcrAndThenOr8 ((PCH_SBI_PID) BitDesc->Reg.Data.Pcr.Fields.Pid, (UINT16) BitDesc->Reg.Data.Pcr.Fields.Offset, (UINT8) AndVal, (UINT8) OrVal);
+ break;
+
+ case 2:
+ PchPcrAndThenOr16 ((PCH_SBI_PID) BitDesc->Reg.Data.Pcr.Fields.Pid, (UINT16) BitDesc->Reg.Data.Pcr.Fields.Offset, (UINT16) AndVal, (UINT16) OrVal);
+ break;
+
+ case 4:
+ PchPcrAndThenOr32 ((PCH_SBI_PID) BitDesc->Reg.Data.Pcr.Fields.Pid, (UINT16) BitDesc->Reg.Data.Pcr.Fields.Offset, (UINT32) AndVal, (UINT32) OrVal);
+ break;
+
+ default:
+ //
+ // Unsupported or invalid register size
+ //
+ ASSERT (FALSE);
+ break;
+ }
+ break;
+
+ default:
+ //
+ // This address type is not yet implemented
+ //
+ ASSERT (FALSE);
+ break;
+ }
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchxSmmHelpers.h b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchxSmmHelpers.h
new file mode 100644
index 0000000000..6dd6f2027d
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/PchSmiDispatcher/Smm/PchxSmmHelpers.h
@@ -0,0 +1,107 @@
+/** @file
+ This driver is responsible for the registration of child drivers
+ and the abstraction of the PCH SMI sources.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _PCHX_SMM_HELPERS_H_
+#define _PCHX_SMM_HELPERS_H_
+
+#include "PchSmm.h"
+
+/**
+ Initialize bits that aren't necessarily related to an SMI source.
+
+
+ @retval EFI_SUCCESS SMI source initialization completed.
+ @retval Asserts Global Smi Bit is not enabled successfully.
+**/
+EFI_STATUS
+PchSmmInitHardware (
+ VOID
+ );
+
+/**
+ Enables the PCH to generate SMIs. Note that no SMIs will be generated
+ if no SMI sources are enabled. Conversely, no enabled SMI source will
+ generate SMIs if SMIs are not globally enabled. This is the main
+ switchbox for SMI generation.
+
+
+ @retval EFI_SUCCESS Enable Global Smi Bit completed
+**/
+EFI_STATUS
+PchSmmEnableGlobalSmiBit (
+ VOID
+ );
+
+/**
+ Clears the SMI after all SMI source have been processed.
+ Note that this function will not work correctly (as it is
+ written) unless all SMI sources have been processed.
+ A revision of this function could manually clear all SMI
+ status bits to guarantee success.
+
+
+ @retval EFI_SUCCESS Clears the SMIs completed
+ @retval Asserts EOS was not set to a 1
+**/
+EFI_STATUS
+PchSmmClearSmi (
+ VOID
+ );
+
+/**
+ Set the SMI EOS bit after all SMI source have been processed.
+
+
+ @retval FALSE EOS was not set to a 1; this is an error
+ @retval TRUE EOS was correctly set to a 1
+**/
+BOOLEAN
+PchSmmSetAndCheckEos (
+ VOID
+ );
+
+/**
+ Determine whether an ACPI OS is present (via the SCI_EN bit)
+
+
+ @retval TRUE ACPI OS is present
+ @retval FALSE ACPI OS is not present
+**/
+BOOLEAN
+PchSmmGetSciEn (
+ VOID
+ );
+
+/**
+ Read a specifying bit with the register
+
+ @param[in] BitDesc The struct that includes register address, size in byte and bit number
+
+ @retval TRUE The bit is enabled
+ @retval FALSE The bit is disabled
+**/
+BOOLEAN
+ReadBitDesc (
+ CONST PCH_SMM_BIT_DESC *BitDesc
+ );
+
+/**
+ Write a specifying bit with the register
+
+ @param[in] BitDesc The struct that includes register address, size in byte and bit number
+ @param[in] ValueToWrite The value to be wrote
+ @param[in] WriteClear If the rest bits of the register is write clear
+
+**/
+VOID
+WriteBitDesc (
+ CONST PCH_SMM_BIT_DESC *BitDesc,
+ CONST BOOLEAN ValueToWrite,
+ CONST BOOLEAN WriteClear
+ );
+
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControl.inf b/Silicon/Intel/TigerlakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControl.inf
new file mode 100644
index 0000000000..a142cfa95a
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControl.inf
@@ -0,0 +1,54 @@
+## @file
+# Component description file for SmmControl module
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = SmmControl
+FILE_GUID = A0BAD9F7-AB78-491b-B583-C52B7F84B9E0
+VERSION_STRING = 1.0
+MODULE_TYPE = DXE_RUNTIME_DRIVER
+ENTRY_POINT = SmmControlDriverEntryInit
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+
+
+[LibraryClasses]
+IoLib
+UefiDriverEntryPoint
+DebugLib
+UefiBootServicesTableLib
+UefiRuntimeServicesTableLib
+PmcLib
+GpioLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+TigerlakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+SmmControlDriver.h
+SmmControlDriver.c
+
+
+[Protocols]
+gEfiSmmControl2ProtocolGuid ## PRODUCES
+
+
+[Guids]
+gEfiEventVirtualAddressChangeGuid
+
+
+[Depex]
+TRUE
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControlDriver.c b/Silicon/Intel/TigerlakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControlDriver.c
new file mode 100644
index 0000000000..5822f42165
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControlDriver.c
@@ -0,0 +1,394 @@
+/** @file
+ This is the driver that publishes the SMM Control Protocol.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Guid/EventGroup.h>
+#include <Library/PmcLib.h>
+#include <Library/GpioLib.h>
+#include <IndustryStandard/Pci30.h>
+#include <Register/PchRegsLpc.h>
+#include <Register/SpiRegs.h>
+#include <Register/PmcRegs.h>
+#include "SmmControlDriver.h"
+
+STATIC SMM_CONTROL_PRIVATE_DATA mSmmControl;
+GLOBAL_REMOVE_IF_UNREFERENCED UINT16 mABase;
+
+VOID
+EFIAPI
+DisablePendingSmis (
+ VOID
+ );
+
+/**
+ Fixup internal data pointers so that the services can be called in virtual mode.
+
+ @param[in] Event The event registered.
+ @param[in] Context Event context.
+
+**/
+VOID
+EFIAPI
+SmmControlVirtualAddressChangeEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ gRT->ConvertPointer (0, (VOID *) &(mSmmControl.SmmControl.Trigger));
+ gRT->ConvertPointer (0, (VOID *) &(mSmmControl.SmmControl.Clear));
+}
+
+/**
+ <b>SmmControl DXE RUNTIME Module Entry Point</b>\n
+ - <b>Introduction</b>\n
+ The SmmControl module is a DXE RUNTIME driver that provides a standard way
+ for other drivers to trigger software SMIs.
+
+ - @pre
+ - PCH Power Management I/O space base address has already been programmed.
+ If SmmControl Runtime DXE driver is run before Status Code Runtime Protocol
+ is installed and there is the need to use Status code in the driver, it will
+ be necessary to add EFI_STATUS_CODE_RUNTIME_PROTOCOL_GUID to the dependency file.
+ - EFI_SMM_BASE2_PROTOCOL
+ - Documented in the System Management Mode Core Interface Specification.
+
+ - @result
+ The SmmControl driver produces the EFI_SMM_CONTROL_PROTOCOL documented in
+ System Management Mode Core Interface Specification.
+
+ @param[in] ImageHandle Handle for the image of this driver
+ @param[in] SystemTable Pointer to the EFI System Table
+
+ @retval EFI_STATUS Results of the installation of the SMM Control Protocol
+**/
+EFI_STATUS
+EFIAPI
+SmmControlDriverEntryInit (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_EVENT Event;
+
+ DEBUG ((DEBUG_INFO, "SmmControlDriverEntryInit() Start\n"));
+
+ //
+ // Get the Power Management I/O space base address. We assume that
+ // this base address has already been programmed if this driver is
+ // being run.
+ //
+ mABase = PmcGetAcpiBase ();
+
+ Status = EFI_SUCCESS;
+ if (mABase != 0) {
+ //
+ // Install the instance of the protocol
+ //
+ mSmmControl.Signature = SMM_CONTROL_PRIVATE_DATA_SIGNATURE;
+ mSmmControl.Handle = ImageHandle;
+
+ mSmmControl.SmmControl.Trigger = Activate;
+ mSmmControl.SmmControl.Clear = Deactivate;
+ mSmmControl.SmmControl.MinimumTriggerPeriod = 0;
+
+ //
+ // Install our protocol interfaces on the device's handle
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &mSmmControl.Handle,
+ &gEfiSmmControl2ProtocolGuid,
+ &mSmmControl.SmmControl,
+ NULL
+ );
+ } else {
+ Status = EFI_DEVICE_ERROR;
+ return Status;
+ }
+
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ SmmControlVirtualAddressChangeEvent,
+ NULL,
+ &gEfiEventVirtualAddressChangeGuid,
+ &Event
+ );
+ //
+ // Disable any PCH SMIs that, for whatever reason, are asserted after the boot.
+ //
+ DisablePendingSmis ();
+
+ DEBUG ((DEBUG_INFO, "SmmControlDriverEntryInit() End\n"));
+
+ return Status;
+}
+
+/**
+ Trigger the software SMI
+
+ @param[in] Data The value to be set on the software SMI data port
+
+ @retval EFI_SUCCESS Function completes successfully
+**/
+EFI_STATUS
+EFIAPI
+SmmTrigger (
+ IN UINT8 Data
+ )
+{
+ UINT32 OutputData;
+ UINT32 OutputPort;
+
+ //
+ // Enable the APMC SMI
+ //
+ OutputPort = mABase + R_ACPI_IO_SMI_EN;
+ OutputData = IoRead32 ((UINTN) OutputPort);
+ OutputData |= (B_ACPI_IO_SMI_EN_APMC | B_ACPI_IO_SMI_EN_GBL_SMI);
+ DEBUG (
+ (DEBUG_VERBOSE,
+ "The SMI Control Port at address %x will be written to %x.\n",
+ OutputPort,
+ OutputData)
+ );
+ IoWrite32 (
+ (UINTN) OutputPort,
+ (UINT32) (OutputData)
+ );
+
+ OutputPort = R_PCH_IO_APM_CNT;
+ OutputData = Data;
+
+ //
+ // Generate the APMC SMI
+ //
+ IoWrite8 (
+ (UINTN) OutputPort,
+ (UINT8) (OutputData)
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Clear the SMI status
+
+
+ @retval EFI_SUCCESS The function completes successfully
+ @retval EFI_DEVICE_ERROR Something error occurred
+**/
+EFI_STATUS
+EFIAPI
+SmmClear (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINT32 OutputData;
+ UINT32 OutputPort;
+
+ Status = EFI_SUCCESS;
+
+ //
+ // Clear the Power Button Override Status Bit, it gates EOS from being set.
+ //
+ OutputPort = mABase + R_ACPI_IO_PM1_STS;
+ OutputData = B_ACPI_IO_PM1_STS_PRBTNOR;
+ DEBUG (
+ (DEBUG_VERBOSE,
+ "The PM1 Status Port at address %x will be written to %x.\n",
+ OutputPort,
+ OutputData)
+ );
+ IoWrite16 (
+ (UINTN) OutputPort,
+ (UINT16) (OutputData)
+ );
+
+ //
+ // Clear the APM SMI Status Bit
+ //
+ OutputPort = mABase + R_ACPI_IO_SMI_STS;
+ OutputData = B_ACPI_IO_SMI_STS_APM;
+ DEBUG (
+ (DEBUG_VERBOSE,
+ "The SMI Status Port at address %x will be written to %x.\n",
+ OutputPort,
+ OutputData)
+ );
+ IoWrite32 (
+ (UINTN) OutputPort,
+ (UINT32) (OutputData)
+ );
+
+ //
+ // Set the EOS Bit
+ //
+ OutputPort = mABase + R_ACPI_IO_SMI_EN;
+ OutputData = IoRead32 ((UINTN) OutputPort);
+ OutputData |= B_ACPI_IO_SMI_EN_EOS;
+ DEBUG (
+ (DEBUG_VERBOSE,
+ "The SMI Control Port at address %x will be written to %x.\n",
+ OutputPort,
+ OutputData)
+ );
+ IoWrite32 (
+ (UINTN) OutputPort,
+ (UINT32) (OutputData)
+ );
+
+ //
+ // There is no need to read EOS back and check if it is set.
+ // This can lead to a reading of zero if an SMI occurs right after the SMI_EN port read
+ // but before the data is returned to the CPU.
+ // SMM Dispatcher should make sure that EOS is set after all SMI sources are processed.
+ //
+ return Status;
+}
+
+/**
+ This routine generates an SMI
+
+ @param[in] This The EFI SMM Control protocol instance
+ @param[in, out] CommandPort The buffer contains data to the command port
+ @param[in, out] DataPort The buffer contains data to the data port
+ @param[in] Periodic Periodic or not
+ @param[in] ActivationInterval Interval of periodic SMI
+
+ @retval EFI Status Describing the result of the operation
+ @retval EFI_INVALID_PARAMETER Some parameter value passed is not supported
+**/
+EFI_STATUS
+EFIAPI
+Activate (
+ IN CONST EFI_SMM_CONTROL2_PROTOCOL * This,
+ IN OUT UINT8 *CommandPort OPTIONAL,
+ IN OUT UINT8 *DataPort OPTIONAL,
+ IN BOOLEAN Periodic OPTIONAL,
+ IN UINTN ActivationInterval OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ UINT8 Data;
+
+ if (Periodic) {
+ DEBUG ((DEBUG_WARN, "Invalid parameter\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (CommandPort == NULL) {
+ Data = 0xFF;
+ } else {
+ Data = *CommandPort;
+ }
+ //
+ // Clear any pending the APM SMI
+ //
+ Status = SmmClear ();
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ return SmmTrigger (Data);
+}
+
+/**
+ This routine clears an SMI
+
+ @param[in] This The EFI SMM Control protocol instance
+ @param[in] Periodic Periodic or not
+
+ @retval EFI Status Describing the result of the operation
+ @retval EFI_INVALID_PARAMETER Some parameter value passed is not supported
+**/
+EFI_STATUS
+EFIAPI
+Deactivate (
+ IN CONST EFI_SMM_CONTROL2_PROTOCOL *This,
+ IN BOOLEAN Periodic OPTIONAL
+ )
+{
+ if (Periodic) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return SmmClear ();
+}
+/**
+ Disable all pending SMIs
+
+**/
+VOID
+EFIAPI
+DisablePendingSmis (
+ VOID
+ )
+{
+ UINT32 Data;
+ BOOLEAN SciEn;
+
+ //
+ // Determine whether an ACPI OS is present (via the SCI_EN bit)
+ //
+ Data = IoRead16 ((UINTN) mABase + R_ACPI_IO_PM1_CNT);
+ SciEn = (BOOLEAN) ((Data & B_ACPI_IO_PM1_CNT_SCI_EN) == B_ACPI_IO_PM1_CNT_SCI_EN);
+
+ if (!SciEn) {
+ //
+ // Clear any SMIs that double as SCIs (when SCI_EN==0)
+ //
+ IoWrite16 ((UINTN) mABase + R_ACPI_IO_PM1_STS, 0xFFFF);
+ IoWrite16 ((UINTN) mABase + R_ACPI_IO_PM1_EN, 0);
+ IoWrite16 ((UINTN) mABase + R_ACPI_IO_PM1_CNT, 0);
+ IoWrite32 (
+ (UINTN) mABase + R_ACPI_IO_GPE0_STS_127_96,
+ (UINT32)( B_ACPI_IO_GPE0_STS_127_96_WADT |
+ B_ACPI_IO_GPE0_STS_127_96_USB_CON_DSX_STS |
+ B_ACPI_IO_GPE0_STS_127_96_LAN_WAKE |
+ B_ACPI_IO_GPE0_STS_127_96_PME_B0 |
+ B_ACPI_IO_GPE0_STS_127_96_PME |
+ B_ACPI_IO_GPE0_STS_127_96_BATLOW |
+ B_ACPI_IO_GPE0_STS_127_96_RI |
+ B_ACPI_IO_GPE0_STS_127_96_SWGPE)
+ );
+ IoWrite32 ((UINTN) mABase + R_ACPI_IO_GPE0_EN_127_96, (UINT32) B_ACPI_IO_GPE0_EN_127_96_WADT);
+ }
+ //
+ // Clear and disable all SMIs that are unaffected by SCI_EN
+ //
+ GpioDisableAllGpiSmi ();
+
+ GpioClearAllGpiSmiSts ();
+
+ IoWrite32 ((UINTN) mABase + R_ACPI_IO_DEVACT_STS, 0x0000FFFF);
+
+ IoWrite32 ((UINTN) mABase + R_ACPI_IO_SMI_STS, ~0u);
+
+ //
+ // (Make sure to write this register last -- EOS re-enables SMIs for the PCH)
+ //
+ Data = IoRead32 ((UINTN) mABase + R_ACPI_IO_SMI_EN);
+ //
+ // clear all bits except those tied to SCI_EN
+ //
+ Data &= B_ACPI_IO_SMI_EN_BIOS_RLS;
+ //
+ // enable SMIs and specifically enable writes to APM_CNT.
+ //
+ Data |= B_ACPI_IO_SMI_EN_GBL_SMI | B_ACPI_IO_SMI_EN_APMC;
+ //
+ // NOTE: Default value of EOS is set in PCH, it will be automatically cleared Once the PCH asserts SMI# low,
+ // we don't need to do anything to clear it
+ //
+ IoWrite32 ((UINTN) mABase + R_ACPI_IO_SMI_EN, Data);
+}
+
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControlDriver.h b/Silicon/Intel/TigerlakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControlDriver.h
new file mode 100644
index 0000000000..af368e6945
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControlDriver.h
@@ -0,0 +1,130 @@
+/** @file
+ Header file for SMM Control Driver.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _SMM_CONTROL_DRIVER_H_
+#define _SMM_CONTROL_DRIVER_H_
+
+#include <Protocol/SmmControl2.h>
+
+
+#define SMM_CONTROL_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('i', '4', 's', 'c')
+
+typedef struct {
+ UINTN Signature;
+ EFI_HANDLE Handle;
+ EFI_SMM_CONTROL2_PROTOCOL SmmControl;
+} SMM_CONTROL_PRIVATE_DATA;
+
+#define SMM_CONTROL_PRIVATE_DATA_FROM_THIS(a) CR (a, SMM_CONTROL_PRIVATE_DATA, SmmControl, SMM_CONTROL_DEV_SIGNATURE)
+
+//
+// Prototypes
+//
+
+/**
+ <b>SmmControl DXE RUNTIME Module Entry Point</b>\n
+ - <b>Introduction</b>\n
+ The SmmControl module is a DXE RUNTIME driver that provides a standard way
+ for other drivers to trigger software SMIs.
+
+ - @pre
+ - PCH Power Management I/O space base address has already been programmed.
+ If SmmControl Runtime DXE driver is run before Status Code Runtime Protocol
+ is installed and there is the need to use Status code in the driver, it will
+ be necessary to add EFI_STATUS_CODE_RUNTIME_PROTOCOL_GUID to the dependency file.
+ - EFI_SMM_BASE2_PROTOCOL
+ - Documented in the System Management Mode Core Interface Specification.
+
+ - @result
+ The SmmControl driver produces the EFI_SMM_CONTROL_PROTOCOL documented in
+ System Management Mode Core Interface Specification.
+
+ @param[in] ImageHandle Handle for the image of this driver
+ @param[in] SystemTable Pointer to the EFI System Table
+
+ @retval EFI_STATUS Results of the installation of the SMM Control Protocol
+**/
+EFI_STATUS
+EFIAPI
+SmmControlDriverEntryInit (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Trigger the software SMI
+
+ @param[in] Data The value to be set on the software SMI data port
+
+ @retval EFI_SUCCESS Function completes successfully
+**/
+EFI_STATUS
+EFIAPI
+SmmTrigger (
+ UINT8 Data
+ );
+
+/**
+ Clear the SMI status
+
+
+ @retval EFI_SUCCESS The function completes successfully
+ @retval EFI_DEVICE_ERROR Something error occurred
+**/
+EFI_STATUS
+EFIAPI
+SmmClear (
+ VOID
+ );
+
+/**
+ This routine generates an SMI
+
+ @param[in] This The EFI SMM Control protocol instance
+ @param[in, out] ArgumentBuffer The buffer of argument
+ @param[in, out] ArgumentBufferSize The size of the argument buffer
+ @param[in] Periodic Periodic or not
+ @param[in] ActivationInterval Interval of periodic SMI
+
+ @retval EFI Status Describing the result of the operation
+ @retval EFI_INVALID_PARAMETER Some parameter value passed is not supported
+**/
+EFI_STATUS
+EFIAPI
+Activate (
+ IN CONST EFI_SMM_CONTROL2_PROTOCOL *This,
+ IN OUT UINT8 *ArgumentBuffer OPTIONAL,
+ IN OUT UINT8 *ArgumentBufferSize OPTIONAL,
+ IN BOOLEAN Periodic OPTIONAL,
+ IN UINTN ActivationInterval OPTIONAL
+ );
+
+/**
+ This routine clears an SMI
+
+ @param[in] This The EFI SMM Control protocol instance
+ @param[in] Periodic Periodic or not
+
+ @retval EFI Status Describing the result of the operation
+ @retval EFI_INVALID_PARAMETER Some parameter value passed is not supported
+**/
+EFI_STATUS
+EFIAPI
+Deactivate (
+ IN CONST EFI_SMM_CONTROL2_PROTOCOL *This,
+ IN BOOLEAN Periodic OPTIONAL
+ );
+/**
+ Disable all pending SMIs
+
+**/
+VOID
+EFIAPI
+DisablePendingSmis (
+ VOID
+ );
+
+#endif
--
2.24.0.windows.2
^ permalink raw reply related [flat|nested] 42+ messages in thread
* [Patch V3 37/40] TigerlakeSiliconPkg/SystemAgent: Add SystemAgent modules
2021-02-05 7:40 [Patch V3 01/40] TigerlakeSiliconPkg: Add package and Include/ConfigBlock headers Heng Luo
` (34 preceding siblings ...)
2021-02-05 7:40 ` [Patch V3 36/40] TigerlakeSiliconPkg/Pch: Add Pch modules Heng Luo
@ 2021-02-05 7:40 ` Heng Luo
2021-02-05 7:40 ` [Patch V3 38/40] TigerlakeSiliconPkg/Fru: Add Fru DSC files Heng Luo
` (2 subsequent siblings)
38 siblings, 0 replies; 42+ messages in thread
From: Heng Luo @ 2021-02-05 7:40 UTC (permalink / raw)
To: devel; +Cc: Sai Chaganty, Nate DeSimone
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3171
Adds the following files:
* SystemAgent/SaInit/Dxe
* SystemAgent/SaInit/Smm
Cc: Sai Chaganty <rangasai.v.chaganty@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Signed-off-by: Heng Luo <heng.luo@intel.com>
---
Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaAcpi.c | 431 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInit.c | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInit.h | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInitDxe.c | 181 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInitDxe.h | 136 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInitDxe.inf | 117 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/SaInit/Smm/CpuPcieSmm.c | 454 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/SaInit/Smm/SaLateInitSmm.c | 112 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/SaInit/Smm/SaLateInitSmm.h | 122 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/SaInit/Smm/SaLateInitSmm.inf | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
10 files changed, 1803 insertions(+)
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaAcpi.c b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaAcpi.c
new file mode 100644
index 0000000000..d84a0c1fa4
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaAcpi.c
@@ -0,0 +1,431 @@
+/** @file
+ This is the driver that initializes the Intel System Agent.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include "SaInitDxe.h"
+#include "SaInit.h"
+#include <SaConfigHob.h>
+#include <Protocol/SaNvsArea.h>
+#include <Library/PchInfoLib.h>
+#include <CpuPcieInfo.h>
+#include <Library/DxeCpuPcieRpLib.h>
+#include <SaConfigHob.h>
+#include <CpuPcieHob.h>
+#include <HostBridgeDataHob.h>
+#include <CpuDataStruct.h>
+
+///
+/// Global Variables
+///
+GLOBAL_REMOVE_IF_UNREFERENCED SYSTEM_AGENT_NVS_AREA_PROTOCOL mSaNvsAreaProtocol;
+GLOBAL_REMOVE_IF_UNREFERENCED SA_POLICY_PROTOCOL *mSaPolicy;
+extern SA_CONFIG_HOB *mSaConfigHob;
+
+/**
+ A protocol callback which updates 64bits MMIO Base and Length in SA GNVS area
+**/
+VOID
+UpdateSaGnvsForMmioResourceBaseLength (
+ VOID
+ )
+{
+ EFI_PHYSICAL_ADDRESS PciBaseAddress;
+ UINT32 Tolud;
+ UINT64 Length;
+ UINT64 McD0BaseAddress;
+ UINTN ResMemLimit1;
+ UINT8 EnableAbove4GBMmioBiosAssignemnt;
+ HOST_BRIDGE_DATA_HOB *HostBridgeDataHob;
+
+ PciBaseAddress = 0;
+ Tolud = 0;
+ Length = 0;
+ ResMemLimit1 = 0;
+ EnableAbove4GBMmioBiosAssignemnt = 0;
+ HostBridgeDataHob = NULL;
+ //
+ // Read memory map registers
+ //
+ McD0BaseAddress = PCI_SEGMENT_LIB_ADDRESS (SA_SEG_NUM, SA_MC_BUS, 0, 0, 0);
+ Tolud = PciSegmentRead32 (McD0BaseAddress + R_SA_TOLUD) & B_SA_TOLUD_TOLUD_MASK;
+ PciBaseAddress = Tolud;
+
+ ResMemLimit1 = (UINTN) PcdGet64 (PcdSiPciExpressBaseAddress);
+
+ Length = ResMemLimit1 - PciBaseAddress;
+
+ //
+ // Get HostBridgeData HOB and see if above 4GB MMIO BIOS assignment enabled
+ //
+ HostBridgeDataHob = (HOST_BRIDGE_DATA_HOB *) GetFirstGuidHob (&gHostBridgeDataHobGuid);
+ if ((HostBridgeDataHob != NULL) && (HostBridgeDataHob->EnableAbove4GBMmio == 1)) {
+ EnableAbove4GBMmioBiosAssignemnt = 1;
+ }
+
+ //
+ // Enable Above 4GB MMIO when Aperture Size is 2GB or higher
+ //
+ if ((mSaConfigHob != NULL) && (mSaConfigHob->ApertureSize >= 15)) {
+ EnableAbove4GBMmioBiosAssignemnt = 1;
+ }
+
+ //
+ // Check Enable Above 4GB MMIO or not
+ //
+
+ DEBUG ((DEBUG_INFO, "Update SA GNVS Area.\n"));
+ mSaNvsAreaProtocol.Area->Mmio32Base = (UINT32) PciBaseAddress;
+ mSaNvsAreaProtocol.Area->Mmio32Length = (UINT32) Length;
+ if (EnableAbove4GBMmioBiosAssignemnt == 1) {
+ mSaNvsAreaProtocol.Area->Mmio64Base = BASE_256GB;
+ mSaNvsAreaProtocol.Area->Mmio64Length = SIZE_256GB;
+ }
+ DEBUG ((DEBUG_INFO, "SaNvsAreaProtocol.Area->Mmio64Base = %lx\n", mSaNvsAreaProtocol.Area->Mmio64Base));
+ DEBUG ((DEBUG_INFO, "SaNvsAreaProtocol.Area->Mmio64Length = %lx\n", mSaNvsAreaProtocol.Area->Mmio64Length));
+ DEBUG ((DEBUG_INFO, "SaNvsAreaProtocol.Area->Mmio32Base = %lx\n", mSaNvsAreaProtocol.Area->Mmio32Base));
+ DEBUG ((DEBUG_INFO, "SaNvsAreaProtocol.Area->Mmio32Length = %lx\n", mSaNvsAreaProtocol.Area->Mmio32Length));
+}
+
+/**
+ Install SSDT Table
+
+ @retval EFI_SUCCESS - SSDT Table load successful.
+**/
+EFI_STATUS
+InstallSsdtAcpiTable (
+ IN GUID SsdtTableGuid,
+ IN UINT64 Signature
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE *HandleBuffer;
+ BOOLEAN LoadTable;
+ UINTN NumberOfHandles;
+ UINTN Index;
+ INTN Instance;
+ UINTN Size;
+ UINT32 FvStatus;
+ UINTN TableHandle;
+ EFI_FV_FILETYPE FileType;
+ EFI_FV_FILE_ATTRIBUTES Attributes;
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVol;
+ EFI_ACPI_TABLE_PROTOCOL *AcpiTable;
+ EFI_ACPI_DESCRIPTION_HEADER *TableHeader;
+ EFI_ACPI_COMMON_HEADER *Table;
+
+ FwVol = NULL;
+ Table = NULL;
+
+ DEBUG ((DEBUG_INFO, "Loading SSDT Table GUID: %g\n", SsdtTableGuid));
+
+ ///
+ /// Locate FV protocol.
+ ///
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiFirmwareVolume2ProtocolGuid,
+ NULL,
+ &NumberOfHandles,
+ &HandleBuffer
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Look for FV with ACPI storage file
+ ///
+ for (Index = 0; Index < NumberOfHandles; Index++) {
+ ///
+ /// Get the protocol on this handle
+ /// This should not fail because of LocateHandleBuffer
+ ///
+ Status = gBS->HandleProtocol (
+ HandleBuffer[Index],
+ &gEfiFirmwareVolume2ProtocolGuid,
+ (VOID **) &FwVol
+ );
+ ASSERT_EFI_ERROR (Status);
+ if (FwVol == NULL) {
+ return EFI_NOT_FOUND;
+ }
+ ///
+ /// See if it has the ACPI storage file
+ ///
+ Size = 0;
+ FvStatus = 0;
+ Status = FwVol->ReadFile (
+ FwVol,
+ &SsdtTableGuid,
+ NULL,
+ &Size,
+ &FileType,
+ &Attributes,
+ &FvStatus
+ );
+
+ ///
+ /// If we found it, then we are done
+ ///
+ if (!EFI_ERROR (Status)) {
+ break;
+ }
+ }
+ ///
+ /// Our exit status is determined by the success of the previous operations
+ /// If the protocol was found, Instance already points to it.
+ ///
+ ///
+ /// Free any allocated buffers
+ ///
+ FreePool (HandleBuffer);
+
+ ///
+ /// Sanity check that we found our data file
+ ///
+ ASSERT (FwVol);
+
+ ///
+ /// Locate ACPI tables
+ ///
+ Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTable);
+
+ ///
+ /// Read tables from the storage file.
+ ///
+ if (FwVol == NULL) {
+ ASSERT_EFI_ERROR (EFI_NOT_FOUND);
+ return EFI_NOT_FOUND;
+ }
+ Instance = 0;
+
+ while (Status == EFI_SUCCESS) {
+ ///
+ /// Read the ACPI tables
+ ///
+ Status = FwVol->ReadSection (
+ FwVol,
+ &SsdtTableGuid,
+ EFI_SECTION_RAW,
+ Instance,
+ (VOID **) &Table,
+ &Size,
+ &FvStatus
+ );
+ if (!EFI_ERROR (Status)) {
+ ///
+ /// check and load HybridGraphics SSDT table
+ ///
+ LoadTable = FALSE;
+ TableHeader = (EFI_ACPI_DESCRIPTION_HEADER *) Table;
+
+ if (((EFI_ACPI_DESCRIPTION_HEADER *) TableHeader)->OemTableId == Signature) {
+ ///
+ /// This is the SSDT table that match the Signature
+ ///
+ DEBUG ((DEBUG_INFO, "Found out SSDT Table GUID: %g\n", SsdtTableGuid));
+ LoadTable = TRUE;
+ }
+
+ ///
+ /// Add the table
+ ///
+ if (LoadTable) {
+ TableHandle = 0;
+ Status = AcpiTable->InstallAcpiTable (
+ AcpiTable,
+ TableHeader,
+ TableHeader->Length,
+ &TableHandle
+ );
+ }
+ ///
+ /// Increment the instance
+ ///
+ Instance++;
+ Table = NULL;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function gets registered as a callback to perform Dmar Igd
+
+ @param[in] Event - A pointer to the Event that triggered the callback.
+ @param[in] Context - A pointer to private data registered with the callback function.
+**/
+VOID
+EFIAPI
+SaAcpiEndOfDxeCallback (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+
+ if (PciSegmentRead16 (PCI_SEGMENT_LIB_ADDRESS (SA_SEG_NUM, IGD_BUS_NUM, IGD_DEV_NUM, IGD_FUN_NUM, PCI_VENDOR_ID_OFFSET)) != 0xFFFF) {
+ Status = PostPmInitEndOfDxe ();
+ if (EFI_SUCCESS != Status) {
+ DEBUG ((DEBUG_WARN, "[SA] EndOfDxe GraphicsInit Error, Status = %r \n", Status));
+ ASSERT_EFI_ERROR (Status);
+ }
+ }
+
+ if (PciSegmentRead16 (PCI_SEGMENT_LIB_ADDRESS (SA_SEG_NUM, IGD_BUS_NUM, IGD_DEV_NUM, IGD_FUN_NUM, PCI_VENDOR_ID_OFFSET)) != 0xFFFF) {
+ Status = GetVBiosVbtEndOfDxe ();
+ if (EFI_SUCCESS != Status) {
+ DEBUG ((DEBUG_WARN, "[SA] EndOfDxe Op Region Error, Status = %r \n", Status));
+ }
+
+ Status = UpdateIgdOpRegionEndOfDxe ();
+ if (EFI_SUCCESS != Status) {
+ DEBUG ((DEBUG_WARN, "[SA] EndOfDxe Update Op Region Error, Status = %r \n", Status));
+ }
+ }
+
+ return;
+}
+
+/**
+ SystemAgent Acpi Initialization.
+
+ @param[in] ImageHandle Handle for the image of this driver
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
+**/
+EFI_STATUS
+EFIAPI
+SaAcpiInit (
+ IN EFI_HANDLE ImageHandle
+ )
+{
+ EFI_STATUS Status;
+ EFI_CPUID_REGISTER CpuidRegs;
+ EFI_EVENT EndOfDxeEvent;
+
+ CPU_PCIE_HOB *CpuPcieHob;
+
+ AsmCpuid (1, &CpuidRegs.RegEax, 0, 0, 0);
+ ///
+ /// Get the platform setup policy.
+ ///
+ Status = gBS->LocateProtocol (&gSaPolicyProtocolGuid, NULL, (VOID **) &mSaPolicy);
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Install System Agent Global NVS protocol
+ ///
+ DEBUG ((DEBUG_INFO, "Install SA GNVS protocol\n"));
+ Status = (gBS->AllocatePool) (EfiACPIMemoryNVS, sizeof (SYSTEM_AGENT_NVS_AREA), (VOID **) &mSaNvsAreaProtocol.Area);
+ ASSERT_EFI_ERROR (Status);
+ ZeroMem ((VOID *) mSaNvsAreaProtocol.Area, sizeof (SYSTEM_AGENT_NVS_AREA));
+ mSaNvsAreaProtocol.Area->XPcieCfgBaseAddress = (UINT32) (PcdGet64 (PcdSiPciExpressBaseAddress));
+ mSaNvsAreaProtocol.Area->CpuIdInfo = CpuidRegs.RegEax;
+
+ ///
+ /// Get CpuPcieHob HOB
+ ///
+ CpuPcieHob = NULL;
+ CpuPcieHob = (CPU_PCIE_HOB *) GetFirstGuidHob (&gCpuPcieHobGuid);
+ if (CpuPcieHob == NULL) {
+ DEBUG((DEBUG_ERROR, "CpuPcieHob not found\n"));
+ // @todo: Will add it back once it will get add into NVS library since currently it is failing for JSL
+ //ASSERT(CpuPcieHob != NULL);
+ //return EFI_NOT_FOUND;
+ } else {
+ mSaNvsAreaProtocol.Area->SlotSelection = CpuPcieHob->SlotSelection;
+ DEBUG((DEBUG_INFO, "RpEnabledMask == %x\n", CpuPcieHob->RpEnabledMask));
+ if (CpuPcieHob->RpEnabledMask == 0) {
+ DEBUG ((DEBUG_ERROR, "All CPU PCIe root ports are disabled!!\n"));
+ } else {
+ if (CpuPcieHob->RpEnabledMask & BIT0) {
+ mSaNvsAreaProtocol.Area->CpuPcieRp0Enable = 1;
+ }
+ if (CpuPcieHob->RpEnabledMask & BIT1) {
+ mSaNvsAreaProtocol.Area->CpuPcieRp1Enable = 1;
+ }
+ if (CpuPcieHob->RpEnabledMask & BIT2) {
+ mSaNvsAreaProtocol.Area->CpuPcieRp2Enable = 1;
+ }
+ if (CpuPcieHob->RpEnabledMask & BIT3) {
+ mSaNvsAreaProtocol.Area->CpuPcieRp3Enable = 1;
+ }
+ }
+ mSaNvsAreaProtocol.Area->MaxPegPortNumber = GetMaxCpuPciePortNum ();
+ }
+
+ mSaNvsAreaProtocol.Area->SimicsEnvironment = 0;
+
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &ImageHandle,
+ &gSaNvsAreaProtocolGuid,
+ &mSaNvsAreaProtocol,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// GtPostInit Initialization
+ ///
+ DEBUG ((DEBUG_INFO, "Initializing GT ACPI tables\n"));
+ GraphicsInit (ImageHandle, mSaPolicy);
+
+ ///
+ /// Audio (dHDA) Initialization
+ ///
+ ///
+ /// Vtd Initialization
+ ///
+ DEBUG ((DEBUG_INFO, "Initializing VT-d ACPI tables\n"));
+ VtdInit (mSaPolicy);
+
+ ///
+ /// IgdOpRegion Install Initialization
+ ///
+ DEBUG ((DEBUG_INFO, "Initializing IGD OpRegion\n"));
+ IgdOpRegionInit ();
+
+ ///
+ /// Register an end of DXE event for SA ACPI to do tasks before invoking any UEFI drivers,
+ /// applications, or connecting consoles,...
+ ///
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ SaAcpiEndOfDxeCallback,
+ NULL,
+ &gEfiEndOfDxeEventGroupGuid,
+ &EndOfDxeEvent
+ );
+
+ ///
+ /// Install System Agent Global NVS ACPI table
+ ///
+ Status = InstallSsdtAcpiTable (gSaSsdtAcpiTableStorageGuid, SIGNATURE_64 ('S', 'a', 'S', 's', 'd', 't', ' ', 0));
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Update CPU PCIE RP NVS AREA
+ ///
+ UpdateCpuPcieNVS();
+ ///
+ /// Install Intel Graphics SSDT
+ ///
+ Status = InstallSsdtAcpiTable (gGraphicsAcpiTableStorageGuid, SIGNATURE_64 ('I','g','f','x','S','s','d','t'));
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Install IPU SSDT if IPU is present.
+ ///
+ if (PciSegmentRead16 (PCI_SEGMENT_LIB_ADDRESS (SA_SEG_NUM, IPU_BUS_NUM, IPU_DEV_NUM, IPU_FUN_NUM, 0)) != V_SA_DEVICE_ID_INVALID) {
+ Status = InstallSsdtAcpiTable (gIpuAcpiTableStorageGuid, SIGNATURE_64 ('I','p','u','S','s','d','t',0));
+ ASSERT_EFI_ERROR (Status);
+
+ }
+
+ return EFI_SUCCESS;
+}
+
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInit.c b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInit.c
new file mode 100644
index 0000000000..5c0fea422b
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInit.c
@@ -0,0 +1,120 @@
+/** @file
+ This is the Common driver that initializes the Intel System Agent.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include "SaInit.h"
+#include <Library/PciSegmentLib.h>
+#include <HostBridgeDataHob.h>
+#include <SaConfigHob.h>
+#include <Protocol/PciEnumerationComplete.h>
+
+///
+/// Global Variables
+///
+GLOBAL_REMOVE_IF_UNREFERENCED SA_CONFIG_HOB *mSaConfigHob;
+BOOLEAN mSkipPamLock = FALSE;
+
+/*
+ Intel(R) Core Processor Skylake BWG version 0.4.0
+
+ 18.6 System Agent Configuration Locking
+ For reliable operation and security, System BIOS must set the following bits:
+ 1. For all modern Intel processors, Intel strongly recommends that BIOS should set
+ the D_LCK bit. Set B0:D0:F0.R088h [4] = 1b to lock down SMRAM space.
+ BaseAddr values for mSaSecurityRegisters that uses PciExpressBaseAddress will be initialized at
+ Runtime inside function CpuPcieInitPolicy().
+*/
+GLOBAL_REMOVE_IF_UNREFERENCED BOOT_SCRIPT_REGISTER_SETTING mSaSecurityRegisters[] = {
+ {0, R_SA_SMRAMC, 0xFFFFFFFF, BIT4}
+};
+
+/**
+ SystemAgent Initialization Common Function.
+
+ @retval EFI_SUCCESS - Always.
+**/
+
+VOID
+SaInitEntryPoint (
+ VOID
+ )
+{
+ HOST_BRIDGE_DATA_HOB *HostBridgeDataHob;
+
+ ///
+ /// Get Host Bridge Data HOB
+ ///
+ HostBridgeDataHob = NULL;
+ HostBridgeDataHob = (HOST_BRIDGE_DATA_HOB *) GetFirstGuidHob (&gHostBridgeDataHobGuid);
+ if (HostBridgeDataHob != NULL) {
+ mSkipPamLock = HostBridgeDataHob->SkipPamLock;
+ }
+ return;
+}
+
+/**
+ This function does SA security lock
+**/
+VOID
+SaSecurityLock (
+ VOID
+ )
+{
+ UINT8 Index;
+ UINT64 BaseAddress;
+ UINT32 RegOffset;
+ UINT32 Data32And;
+ UINT32 Data32Or;
+
+ ///
+ /// 17.2 System Agent Security Lock configuration
+ ///
+ DEBUG ((DEBUG_INFO, "DXE SaSecurityLock\n"));
+ for (Index = 0; Index < (sizeof (mSaSecurityRegisters) / sizeof (BOOT_SCRIPT_REGISTER_SETTING)); Index++) {
+ BaseAddress = mSaSecurityRegisters[Index].BaseAddr;
+ RegOffset = mSaSecurityRegisters[Index].Offset;
+ Data32And = mSaSecurityRegisters[Index].AndMask;
+ Data32Or = mSaSecurityRegisters[Index].OrMask;
+
+ if (RegOffset == R_SA_SMRAMC) {
+ ///
+ /// SMRAMC LOCK must use CF8/CFC access
+ ///
+ PciCf8Or8 (PCI_CF8_LIB_ADDRESS (SA_MC_BUS, SA_MC_DEV, SA_MC_FUN, R_SA_SMRAMC), (UINT8) Data32Or);
+ BaseAddress = S3_BOOT_SCRIPT_LIB_PCI_ADDRESS (SA_MC_BUS, SA_MC_DEV, SA_MC_FUN, R_SA_SMRAMC);
+ S3BootScriptSavePciCfgReadWrite (
+ S3BootScriptWidthUint8,
+ (UINTN) BaseAddress,
+ &Data32Or,
+ &Data32And
+ );
+ }
+ }
+
+}
+
+/**
+ This function performs SA Security locking in EndOfDxe callback
+
+ @retval EFI_SUCCESS - Security lock has done
+ @retval EFI_UNSUPPORTED - Security lock not done successfully
+**/
+EFI_STATUS
+SaSecurityInit (
+ VOID
+ )
+{
+
+ UINT8 Index;
+
+ for (Index = 0; Index < (sizeof (mSaSecurityRegisters) / sizeof (BOOT_SCRIPT_REGISTER_SETTING)); Index++) {
+ if (mSaSecurityRegisters[Index].BaseAddr != PcdGet64 (PcdMchBaseAddress)) {
+ mSaSecurityRegisters[Index].BaseAddr = PcdGet64 (PcdSiPciExpressBaseAddress);
+ }
+ }
+ SaSecurityLock ();
+
+ return EFI_SUCCESS;
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInit.h b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInit.h
new file mode 100644
index 0000000000..5c8f7dfd5f
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInit.h
@@ -0,0 +1,58 @@
+/** @file
+ Header file for SA Common Initialization Driver.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _SA_INITIALIZATION_DRIVER_H_
+#define _SA_INITIALIZATION_DRIVER_H_
+
+#include <Uefi.h>
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/Pci.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/UefiLib.h>
+#include <Library/IoLib.h>
+#include <Library/PciCf8Lib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/S3BootScriptLib.h>
+#include <Library/SaPlatformLib.h>
+#include <Guid/EventGroup.h>
+#include <Protocol/SaPolicy.h>
+#include <Register/SaRegsHostBridge.h>
+#include <SaConfigHob.h>
+
+extern SA_POLICY_PROTOCOL *mSaPolicy;
+extern SA_CONFIG_HOB *SaConfigHob;
+
+typedef struct {
+ UINT64 BaseAddr;
+ UINT32 Offset;
+ UINT32 AndMask;
+ UINT32 OrMask;
+} BOOT_SCRIPT_REGISTER_SETTING;
+
+/**
+ SystemAgent Initialization Common Function.
+
+ @retval EFI_SUCCESS - Always.
+**/
+VOID
+SaInitEntryPoint (
+ VOID
+ );
+
+/**
+ This function performs SA Security locking in EndOfDxe callback
+
+ @retval EFI_SUCCESS - Security lock has done
+ @retval EFI_UNSUPPORTED - Security lock not done successfully
+**/
+EFI_STATUS
+SaSecurityInit (
+ VOID
+ );
+
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInitDxe.c b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInitDxe.c
new file mode 100644
index 0000000000..2a0e0accf5
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInitDxe.c
@@ -0,0 +1,181 @@
+/** @file
+ This is the driver that initializes the Intel System Agent.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include "SaInitDxe.h"
+#include "SaInit.h"
+#include <SaConfigHob.h>
+#include <Protocol/PciEnumerationComplete.h>
+#include <MemInfoHob.h>
+#include <Protocol/SaIotrapSmi.h>
+
+GLOBAL_REMOVE_IF_UNREFERENCED UINT16 mPcieIoTrapAddress;
+
+///
+/// Global Variables
+///
+extern SA_CONFIG_HOB *mSaConfigHob;
+
+
+/**
+ SystemAgent Dxe Initialization.
+
+ @param[in] ImageHandle Handle for the image of this driver
+ @param[in] SystemTable Pointer to the EFI System Table
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
+**/
+EFI_STATUS
+EFIAPI
+SaInitEntryPointDxe (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ VOID *Registration;
+ EFI_EVENT ReadyToBoot;
+
+
+ DEBUG ((DEBUG_INFO, "SaInitDxe Start\n"));
+
+ SaInitEntryPoint ();
+
+ Status = SaAcpiInit (ImageHandle);
+ ///
+ /// Create PCI Enumeration Completed callback for CPU PCIe
+ ///
+ EfiCreateProtocolNotifyEvent (
+ &gEfiPciEnumerationCompleteProtocolGuid,
+ TPL_CALLBACK,
+ CpuPciEnumCompleteCallback,
+ NULL,
+ &Registration
+ );
+
+ //
+ // Register a Ready to boot event to config PCIE power management setting after OPROM executed
+ //
+ Status = EfiCreateEventReadyToBootEx (
+ TPL_CALLBACK,
+ SaOnReadyToBoot,
+ NULL,
+ &ReadyToBoot
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ DEBUG ((DEBUG_INFO, "SaInitDxe End\n"));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Do PCIE power management while resume from S3
+**/
+VOID
+ReconfigureCpuPciePowerManagementForS3 (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Data32;
+ SA_IOTRAP_SMI_PROTOCOL *CpuPcieIoTrapProtocol;
+
+ Status = gBS->LocateProtocol (&gCpuPcieIoTrapProtocolGuid, NULL, (VOID **) &CpuPcieIoTrapProtocol);
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+ mPcieIoTrapAddress = CpuPcieIoTrapProtocol->SaIotrapSmiAddress;
+ DEBUG ((DEBUG_INFO, "PcieIoTrapAddress: %0x\n", mPcieIoTrapAddress));
+
+ if (mPcieIoTrapAddress != 0) {
+ //
+ // Save PCH PCIE IoTrap address to re-config PCIE power management setting after resume from S3
+ //
+ Data32 = CpuPciePmTrap;
+ S3BootScriptSaveIoWrite (
+ S3BootScriptWidthUint32,
+ (UINTN) (mPcieIoTrapAddress),
+ 1,
+ &Data32
+ );
+ } else {
+ ASSERT (FALSE);
+ }
+}
+
+
+/**
+ SA initialization before boot to OS
+
+ @param[in] Event A pointer to the Event that triggered the callback.
+ @param[in] Context A pointer to private data registered with the callback function.
+**/
+VOID
+EFIAPI
+SaOnReadyToBoot (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ DEBUG ((DEBUG_INFO, "Uefi SaOnReadyToBoot() Start\n"));
+
+ if (Event != NULL) {
+ gBS->CloseEvent (Event);
+ }
+
+ //
+ // Trigger an Iotrap SMI to config PCIE power management setting after PCI enumrate is done
+ //
+#if FixedPcdGetBool(PcdCpuPcieEnable) == 1
+ if (mPcieIoTrapAddress != 0) {
+ IoWrite32 ((UINTN) mPcieIoTrapAddress, CpuPciePmTrap);
+ } else {
+ ASSERT (FALSE);
+ }
+#endif
+ DEBUG ((DEBUG_INFO, "Uefi SaOnReadyToBoot() End\n"));
+}
+
+
+/**
+ This function gets registered as a callback to perform CPU PCIe initialization before EndOfDxe
+
+ @param[in] Event - A pointer to the Event that triggered the callback.
+ @param[in] Context - A pointer to private data registered with the callback function.
+**/
+VOID
+EFIAPI
+CpuPciEnumCompleteCallback (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ VOID *ProtocolPointer;
+
+ DEBUG ((DEBUG_INFO, "CpuPciEnumCompleteCallback Start\n"));
+ ///
+ /// Check if this is first time called by EfiCreateProtocolNotifyEvent() or not,
+ /// if it is, we will skip it until real event is triggered
+ ///
+ Status = gBS->LocateProtocol (&gEfiPciEnumerationCompleteProtocolGuid, NULL, (VOID **) &ProtocolPointer);
+ if (EFI_SUCCESS != Status) {
+ return;
+ }
+
+ gBS->CloseEvent (Event);
+
+ ReconfigureCpuPciePowerManagementForS3();
+ //
+ // Routine for update DMAR
+ //
+ UpdateDmarEndOfPcieEnum ();
+
+ UpdateSaGnvsForMmioResourceBaseLength ();
+ DEBUG ((DEBUG_INFO, "CpuPciEnumCompleteCallback End\n"));
+ return;
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInitDxe.h b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInitDxe.h
new file mode 100644
index 0000000000..7110d049a8
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInitDxe.h
@@ -0,0 +1,136 @@
+/** @file
+ Header file for SA Initialization Driver.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _SA_INIT_DXE_DRIVER_H_
+#define _SA_INIT_DXE_DRIVER_H_
+
+#include <Library/UefiBootServicesTableLib.h>
+#include <Protocol/AcpiTable.h>
+#include <Library/DxeVtdInitLib.h>
+#include <Library/DxeIgdOpRegionInitLib.h>
+#include <Library/DxeGraphicsInitLib.h>
+#include <Register/SaRegsHostBridge.h>
+
+///
+/// Driver Consumed Protocol Prototypes
+///
+#include <Protocol/SaPolicy.h>
+
+extern EFI_GUID gSaAcpiTableStorageGuid;
+extern EFI_GUID gSaSsdtAcpiTableStorageGuid;
+
+typedef struct {
+ UINT64 Address;
+ EFI_BOOT_SCRIPT_WIDTH Width;
+ UINT32 Value;
+} BOOT_SCRIPT_PCI_REGISTER_SAVE;
+
+///
+/// Function Prototype
+///
+/**
+ This function gets registered as a callback to perform CPU PCIe initialization before ExitPmAuth
+
+ @param[in] Event - A pointer to the Event that triggered the callback.
+ @param[in] Context - A pointer to private data registered with the callback function.
+
+**/
+VOID
+EFIAPI
+CpuPciEnumCompleteCallback (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+/**
+ <b>System Agent Initialization DXE Driver Entry Point</b>
+ - <b>Introduction</b> \n
+ Based on the information/data in SA_POLICY_PROTOCOL, this module performs further SA initialization in DXE phase,
+ e.g. internal devices enable/disable, SSVID/SID programming, graphic power-management, VT-d, IGD OpRegion initialization.
+ From the perspective of a PCI Express hierarchy, the Broadwell System Agent and PCH together appear as a Root Complex with root ports the number of which depends on how the 8 PCH ports and 4 System Agent PCIe ports are configured [4x1, 2x8, 1x16].
+ There is an internal link (DMI or OPI) that connects the System Agent to the PCH component. This driver includes initialization of SA DMI, PCI Express, SA & PCH Root Complex Topology.
+ For iGFX, this module implements the initialization of the Graphics Technology Power Management from the Broadwell System Agent BIOS Specification and the initialization of the IGD OpRegion/Software SCI - BIOS Specification.
+ The ASL files that go along with the driver define the IGD OpRegion mailboxes in ACPI space and implement the software SCI interrupt mechanism.
+ The IGD OpRegion/Software SCI code serves as a communication interface between system BIOS, ASL, and Intel graphics driver including making a block of customizable data (VBT) from the Intel video BIOS available.
+ Reference Code for the SCI service functions "Get BIOS Data" and "System BIOS Callback" can be found in the ASL files, those functions can be platform specific, the sample provided in the reference code are implemented for Intel CRB.
+ This module implements the VT-d functionality described in the Broadwell System Agent BIOS Specification.
+ This module publishes the LegacyRegion protocol to control the read and write accesses to the Legacy BIOS ranges.
+ E000 and F000 segments are the legacy BIOS ranges and contain pointers to the ACPI regions, SMBIOS tables and so on. This is a private protocol used by Intel Framework.
+ This module registers CallBack function that performs SA security registers lockdown at end of post as required from Broadwell Bios Spec.
+ In addition, this module publishes the SaInfo Protocol with information such as current System Agent reference code version#.
+
+ - @pre
+ - EFI_FIRMWARE_VOLUME_PROTOCOL: Documented in Firmware Volume Specification, available at the URL: http://www.intel.com/technology/framework/spec.htm
+ - SA_POLICY_PROTOCOL: A protocol published by a platform DXE module executed earlier; this is documented in this document as well.
+ - EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL: Documented in the Unified Extensible Firmware Interface Specification, version 2.0, available at the URL: http://www.uefi.org/specs/
+ - EFI_BOOT_SCRIPT_SAVE_PROTOCOL: A protocol published by a platform DXE module executed earlier; refer to the Sample Code section of the Framework PCH Reference Code.
+ - EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL: Documented in the Unified Extensible Firmware Interface Specification, version 2.0, available at the URL: http://www.uefi.org/specs/
+ - EFI_ACPI_TABLE_PROTOCOL : Documented in PI Specification 1.2
+ - EFI_CPU_IO_PROTOCOL: Documented in CPU I/O Protocol Specification, available at the URL: http://www.intel.com/technology/framework/spec.htm
+ - EFI_DATA_HUB_PROTOCOL: Documented in EFI Data Hub Infrastructure Specification, available at the URL: http://www.intel.com/technology/framework/spec.htm
+ - EFI_HII_PROTOCOL (or EFI_HII_DATABASE_PROTOCOL for UEFI 2.1): Documented in Human Interface Infrastructure Specification, available at the URL: http://www.intel.com/technology/framework/spec.htm
+ (For EFI_HII_DATABASE_PROTOCOL, refer to UEFI Specification Version 2.1 available at the URL: http://www.uefi.org/)
+
+ - @result
+ IGD power-management functionality is initialized; VT-d is initialized (meanwhile, the DMAR table is updated); IGD OpRegion is initialized - IGD_OPREGION_PROTOCOL installed, IGD OpRegion allocated and mailboxes initialized, chipset initialized and ready to generate Software SCI for Internal graphics events. Publishes the SA_INFO_PROTOCOL with current SA reference code version #. Publishes the EFI_LEGACY_REGION_PROTOCOL documented in the Compatibility Support Module Specification, version 0.9, available at the URL: http://www.intel.com/technology/framework/spec.htm
+
+ - <b>References</b> \n
+ IGD OpRegion/Software SCI for Broadwell
+ Advanced Configuration and Power Interface Specification Revision 4.0a.
+
+ - <b>Porting Recommendations</b> \n
+ No modification of the DXE driver should be typically necessary.
+ This driver should be executed after all related devices (audio, video, ME, etc.) are initialized to ensure correct data in DMAR table and DMA-remapping registers.
+
+ @param[in] ImageHandle Handle for the image of this driver
+ @param[in] SystemTable Pointer to the EFI System Table
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
+**/
+EFI_STATUS
+EFIAPI
+SaInitEntryPointDxe (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ SystemAgent Acpi Initialization.
+
+ @param[in] ImageHandle Handle for the image of this driver
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
+**/
+EFI_STATUS
+EFIAPI
+SaAcpiInit (
+ IN EFI_HANDLE ImageHandle
+ );
+
+/**
+ A protocol callback which updates 64bits MMIO Base and Length in SA GNVS area
+**/
+VOID
+UpdateSaGnvsForMmioResourceBaseLength (
+ VOID
+ );
+
+/**
+ SA initialization before boot to OS
+
+ @param[in] Event A pointer to the Event that triggered the callback.
+ @param[in] Context A pointer to private data registered with the callback function.
+**/
+VOID
+EFIAPI
+SaOnReadyToBoot (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInitDxe.inf b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInitDxe.inf
new file mode 100644
index 0000000000..d23ba0fa3b
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/SaInit/Dxe/SaInitDxe.inf
@@ -0,0 +1,117 @@
+## @file
+# Component description file for SystemAgent Initialization driver
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = SaInitDxe
+FILE_GUID = DE23ACEE-CF55-4fb6-AA77-984AB53DE811
+VERSION_STRING = 1.0
+MODULE_TYPE = DXE_DRIVER
+ENTRY_POINT = SaInitEntryPointDxe
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 EBC
+#
+
+
+
+[LibraryClasses]
+UefiDriverEntryPoint
+UefiLib
+UefiBootServicesTableLib
+DxeServicesTableLib
+DebugLib
+PciCf8Lib
+PciSegmentLib
+BaseMemoryLib
+MemoryAllocationLib
+IoLib
+S3BootScriptLib
+PmcLib
+PchInfoLib
+GpioLib
+ConfigBlockLib
+SaPlatformLib
+PchPcieRpLib
+DxeGraphicsInitLib
+DxeIgdOpRegionInitLib
+DxeVtdInitLib
+PciExpressHelpersLib
+DxeCpuPcieRpLib
+SataLib
+
+[Packages]
+TigerlakeSiliconPkg/SiPkg.dec
+MdePkg/MdePkg.dec
+UefiCpuPkg/UefiCpuPkg.dec
+IntelSiliconPkg/IntelSiliconPkg.dec
+
+[Pcd]
+gSiPkgTokenSpaceGuid.PcdSiPciExpressBaseAddress
+gSiPkgTokenSpaceGuid.PcdMchBaseAddress
+gSiPkgTokenSpaceGuid.PcdSiIoApicBaseAddress
+gSiPkgTokenSpaceGuid.PcdCpuPcieEnable ## CONSUMES
+
+[FixedPcd]
+
+[Sources]
+SaInitDxe.h
+SaInitDxe.c
+SaInit.h
+SaInit.c
+SaAcpi.c
+
+
+[Protocols]
+gEfiAcpiTableProtocolGuid ## CONSUMES
+gSaNvsAreaProtocolGuid ## PRODUCES
+gSaPolicyProtocolGuid ## CONSUMES
+gEfiCpuArchProtocolGuid ## CONSUMES
+gEfiPciEnumerationCompleteProtocolGuid ## CONSUMES
+gEfiPciRootBridgeIoProtocolGuid ## CONSUMES
+gIgdOpRegionProtocolGuid ## PRODUCES
+gEfiFirmwareVolume2ProtocolGuid ## CONSUMES
+gGopComponentName2ProtocolGuid ## CONSUMES
+gSaIotrapSmiProtocolGuid ## CONSUMES
+gCpuPcieIoTrapProtocolGuid ## CONSUMES
+
+[Guids]
+gSaConfigHobGuid
+gHgAcpiTablePchStorageGuid
+gSaAcpiTableStorageGuid
+gHgAcpiTableStorageGuid
+gSaSsdtAcpiTableStorageGuid
+gSegSsdtAcpiTableStorageGuid
+gTcssSsdtAcpiTableStorageGuid
+gGraphicsAcpiTableStorageGuid
+gIpuAcpiTableStorageGuid
+gEfiEndOfDxeEventGroupGuid
+gSiConfigHobGuid ## CONSUMES
+gGraphicsDxeConfigGuid
+gMemoryDxeConfigGuid
+gPcieDxeConfigGuid
+gPchInfoHobGuid
+gTcssHobGuid
+gSaConfigHobGuid
+gSaDataHobGuid
+gCpuPcieHobGuid
+gHostBridgeDataHobGuid
+gVmdInfoHobGuid ## CONSUMES
+
+[FixedPcd]
+
+[Depex]
+gEfiAcpiTableProtocolGuid AND
+gEfiFirmwareVolume2ProtocolGuid AND
+gSaPolicyProtocolGuid AND
+gEfiPciRootBridgeIoProtocolGuid AND
+gEfiPciHostBridgeResourceAllocationProtocolGuid AND # This is to ensure that PCI MMIO resource has been prepared and available for this driver to allocate.
+gEfiHiiDatabaseProtocolGuid
+
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/SaInit/Smm/CpuPcieSmm.c b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/SaInit/Smm/CpuPcieSmm.c
new file mode 100644
index 0000000000..70d47e787f
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/SaInit/Smm/CpuPcieSmm.c
@@ -0,0 +1,454 @@
+/** @file
+ CPU PCIe SMM Driver Entry
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include "SaLateInitSmm.h"
+#include <Library/BaseLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/SmmServicesTableLib.h>
+#include <PcieRegs.h>
+#include <Register/PchRegs.h>
+#include <Register/CpuPcieRegs.h>
+#include <Library/PcieHelperLib.h>
+#include <CpuPcieInfo.h>
+#include <Library/TimerLib.h>
+#include <Library/PciExpressHelpersLib.h>
+#include <Library/CpuPcieInfoFruLib.h>
+#include <CpuPcieConfig.h>
+#include <Library/CpuPcieRpLib.h>
+#include <Protocol/PchPcieSmiDispatch.h>
+#include <Protocol/PchSmiDispatch.h>
+#include <Protocol/SaIotrapSmi.h>
+#include <Library/SmmServicesTableLib.h>
+#include <Library/S3BootScriptLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <CpuPcieHob.h>
+
+GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mSaBusNumber;
+//
+// @note:
+// These temp bus numbers cannot be used in runtime (hot-plug).
+// These can be used only during boot.
+//
+GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mTempRootPortBusNumMin;
+GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mTempRootPortBusNumMax;
+GLOBAL_REMOVE_IF_UNREFERENCED CPU_PCIE_ROOT_PORT_CONFIG mCpuPcieRootPortConfig[CPU_PCIE_MAX_ROOT_PORTS];
+GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN mCpuPciePmTrapExecuted = FALSE;
+GLOBAL_REMOVE_IF_UNREFERENCED PCH_PCIE_DEVICE_OVERRIDE *mDevAspmOverride;
+GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mNumOfDevAspmOverride;
+
+/**
+ An IoTrap callback to config PCIE power management settings
+**/
+VOID
+CpuPciePmIoTrapSmiCallback (
+ VOID
+ )
+{
+ UINT32 PortIndex;
+ UINT64 RpBase;
+ UINT8 MaxPciePortNum;
+ UINTN RpDevice;
+ UINTN RpFunction;
+
+ MaxPciePortNum = GetMaxCpuPciePortNum ();
+
+ for (PortIndex = 0; PortIndex < MaxPciePortNum; PortIndex++) {
+ GetCpuPcieRpDevFun (PortIndex, &RpDevice, &RpFunction);
+ RpBase = PCI_SEGMENT_LIB_ADDRESS (SA_SEG_NUM, SA_MC_BUS, (UINT32) RpDevice, (UINT32) RpFunction, 0);
+
+ if (PciSegmentRead16 (RpBase) != 0xFFFF) {
+ mDevAspmOverride = NULL;
+ mNumOfDevAspmOverride = 0;
+ RootportDownstreamPmConfiguration (
+ SA_SEG_NUM,
+ SA_MC_BUS,
+ (UINT8)RpDevice,
+ (UINT8)RpFunction,
+ mTempRootPortBusNumMin,
+ mTempRootPortBusNumMax,
+ &mCpuPcieRootPortConfig[PortIndex].PcieRpCommonConfig,
+ mNumOfDevAspmOverride,
+ mDevAspmOverride
+ );
+
+ }
+ }
+}
+
+/**
+ Program Common Clock and ASPM of Downstream Devices
+
+ @param[in] PortIndex Pcie Root Port Number
+ @param[in] RpDevice Pcie Root Pci Device Number
+ @param[in] RpFunction Pcie Root Pci Function Number
+
+ @retval EFI_SUCCESS Root port complete successfully
+ @retval EFI_UNSUPPORTED PMC has invalid vendor ID
+**/
+EFI_STATUS
+CpuPcieSmi (
+ IN UINT8 PortIndex,
+ IN UINT8 RpDevice,
+ IN UINT8 RpFunction
+ )
+{
+ UINT8 SecBus;
+ UINT8 SubBus;
+ UINT64 RpBase;
+ UINT64 EpBase;
+ UINT8 EpPcieCapPtr;
+ UINT8 EpMaxSpeed;
+ BOOLEAN DownstreamDevicePresent;
+ UINT32 Timeout;
+ UINT32 MaxLinkSpeed;
+
+ RpBase = PCI_SEGMENT_LIB_ADDRESS (
+ SA_SEG_NUM,
+ SA_MC_BUS,
+ (UINT32) RpDevice,
+ (UINT32) RpFunction,
+ 0
+ );
+
+ if (PciSegmentRead16 (RpBase + PCI_VENDOR_ID_OFFSET) == 0xFFFF) {
+ DEBUG((DEBUG_INFO, "PCIe controller is disabled, return!!\n"));
+ return EFI_SUCCESS;
+ }
+ //
+ // Check presence detect state. Here the endpoint must be detected using PDS rather than
+ // the usual LinkActive check, because PDS changes immediately and LA takes a few milliseconds to stabilize
+ //
+ DownstreamDevicePresent = !!(PciSegmentRead16 (RpBase + R_PCIE_SLSTS) & B_PCIE_SLSTS_PDS);
+
+ if (DownstreamDevicePresent) {
+ ///
+ /// Make sure the link is active before trying to talk to device behind it
+ /// Wait up to 100ms, according to PCIE spec chapter 6.7.3.3
+ ///
+ Timeout = 100 * 1000;
+ while (CpuPcieIsLinkActive(RpBase) == 0) {
+ MicroSecondDelay (10);
+ Timeout-=10;
+ if (Timeout == 0) {
+ DEBUG((DEBUG_INFO, "PDS set but timeout while waiting for LA bit to get set!!!\n"));
+ return EFI_NOT_FOUND;
+ }
+ }
+ SecBus = PciSegmentRead8 (RpBase + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET);
+ SubBus = PciSegmentRead8 (RpBase + PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET);
+ ASSERT (SecBus != 0 && SubBus != 0);
+ if (SecBus == 0) {
+ DEBUG((DEBUG_INFO, "Secondary Bus is 0, return!!!\n"));
+ return EFI_NOT_FOUND;
+ }
+ RootportDownstreamConfiguration (
+ SA_SEG_NUM,
+ SA_MC_BUS,
+ RpDevice,
+ RpFunction,
+ mTempRootPortBusNumMin,
+ mTempRootPortBusNumMax,
+ EnumCpuPcie
+ );
+ RootportDownstreamPmConfiguration (
+ SA_SEG_NUM,
+ SA_MC_BUS,
+ RpDevice,
+ RpFunction,
+ mTempRootPortBusNumMin,
+ mTempRootPortBusNumMax,
+ &mCpuPcieRootPortConfig[PortIndex].PcieRpCommonConfig,
+ mNumOfDevAspmOverride,
+ mDevAspmOverride
+ );
+ //
+ // Perform Equalization
+ //
+ EpBase = PCI_SEGMENT_LIB_ADDRESS (SA_SEG_NUM, SecBus, 0, 0, 0);
+ EpPcieCapPtr = PcieFindCapId (SA_SEG_NUM, SecBus, 0, 0, EFI_PCI_CAPABILITY_ID_PCIEXP);
+ EpMaxSpeed = PciSegmentRead8 (EpBase + EpPcieCapPtr + R_PCIE_LCAP_OFFSET) & B_PCIE_LCAP_MLS;
+ MaxLinkSpeed = CpuPcieGetMaxLinkSpeed (RpBase);
+ if (EpMaxSpeed < MaxLinkSpeed) {
+ MaxLinkSpeed = EpMaxSpeed;
+ }
+ if (EpMaxSpeed >= V_PCIE_LCAP_MLS_GEN3 && EpMaxSpeed <= V_PCIE_LCAP_MLS_GEN4) {
+ PciSegmentAndThenOr16 (RpBase + R_PCIE_LCTL2, (UINT16)~B_PCIE_LCTL2_TLS, (UINT16)MaxLinkSpeed);
+ PciSegmentOr32 (RpBase + R_PCIE_LCTL3, B_PCIE_LCTL3_PE);
+ PciSegmentOr32 (RpBase + R_PCIE_LCTL, B_PCIE_LCTL_RL);
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ PCIE Hotplug SMI call back function for each Root port
+
+ @param[in] DispatchHandle Handle of this dispatch function
+ @param[in] RpContext Rootport context, which contains RootPort Index,
+ and RootPort PCI BDF.
+**/
+VOID
+EFIAPI
+CpuPcieSmiRpHandlerFunction (
+ IN EFI_HANDLE DispatchHandle,
+ IN PCH_PCIE_SMI_RP_CONTEXT *RpContext
+ )
+{
+ CpuPcieSmi (RpContext->RpIndex, RpContext->DevNum, RpContext->FuncNum);
+}
+
+/**
+ PCIE Link Active State Change Hotplug SMI call back function for all Root ports
+
+ @param[in] DispatchHandle Handle of this dispatch function
+ @param[in] RpContext Rootport context, which contains RootPort Index,
+ and RootPort PCI BDF.
+**/
+VOID
+EFIAPI
+CpuPcieLinkActiveStateChange (
+ IN EFI_HANDLE DispatchHandle,
+ IN PCH_PCIE_SMI_RP_CONTEXT *RpContext
+ )
+{
+ return;
+}
+
+/**
+ PCIE Link Equalization Request SMI call back function for all Root ports
+
+ @param[in] DispatchHandle Handle of this dispatch function
+ @param[in] RpContext Rootport context, which contains RootPort Index,
+ and RootPort PCI BDF.
+**/
+VOID
+EFIAPI
+CpuPcieLinkEqHandlerFunction (
+ IN EFI_HANDLE DispatchHandle,
+ IN PCH_PCIE_SMI_RP_CONTEXT *RpContext
+ )
+{
+ ///
+ /// From PCI Express specification, the PCIe device can request for Link Equalization. When the
+ /// Link Equalization is requested by the device, an SMI will be generated by PCIe RP when
+ /// enabled and the SMI subroutine would invoke the Software Preset/Coefficient Search
+ /// software to re-equalize the link.
+ ///
+
+ return;
+
+}
+/**
+ An IoTrap callback to config PCIE power management settings
+
+ @param[in] DispatchHandle - The handle of this callback, obtained when registering
+ @param[in] DispatchContext - Pointer to the EFI_SMM_IO_TRAP_DISPATCH_CALLBACK_CONTEXT
+
+**/
+VOID
+EFIAPI
+CpuPcieIoTrapSmiCallback (
+ IN EFI_HANDLE DispatchHandle,
+ IN EFI_SMM_IO_TRAP_CONTEXT *CallbackContext,
+ IN OUT VOID *CommBuffer,
+ IN OUT UINTN *CommBufferSize
+ )
+{
+ if (CallbackContext->WriteData == CpuPciePmTrap) {
+ if (mCpuPciePmTrapExecuted == FALSE) {
+ CpuPciePmIoTrapSmiCallback ();
+ mCpuPciePmTrapExecuted = TRUE;
+ }
+ } else {
+ ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
+ }
+}
+
+/**
+ This function clear the Io trap executed flag before enter S3
+
+ @param[in] Handle Handle of the callback
+ @param[in] Context The dispatch context
+
+ @retval EFI_SUCCESS SA register saved
+**/
+EFI_STATUS
+EFIAPI
+CpuPcieS3EntryCallBack (
+ IN EFI_HANDLE Handle,
+ IN CONST VOID *Context OPTIONAL,
+ IN OUT VOID *CommBuffer OPTIONAL,
+ IN OUT UINTN *CommBufferSize OPTIONAL
+ )
+{
+ mCpuPciePmTrapExecuted = FALSE;
+ return EFI_SUCCESS;
+}
+
+/**
+ Register PCIE Hotplug SMI dispatch function to handle Hotplug enabling
+
+ @param[in] ImageHandle The image handle of this module
+ @param[in] SystemTable The EFI System Table
+
+ @retval EFI_SUCCESS The function completes successfully
+**/
+EFI_STATUS
+EFIAPI
+InitializeCpuPcieSmm (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ UINT8 PortIndex;
+ UINT8 Data8;
+ UINT32 Data32Or;
+ UINT32 Data32And;
+ UINT64 RpBase;
+ UINTN RpDevice;
+ UINTN RpFunction;
+ EFI_HANDLE PcieHandle;
+ EFI_HANDLE PchIoTrapHandle;
+ PCH_PCIE_SMI_DISPATCH_PROTOCOL *PchPcieSmiDispatchProtocol;
+ EFI_SMM_IO_TRAP_REGISTER_CONTEXT PchIoTrapContext;
+ EFI_SMM_SX_REGISTER_CONTEXT SxDispatchContext;
+ SA_IOTRAP_SMI_PROTOCOL *CpuPcieIoTrapProtocol;
+ EFI_HANDLE SxDispatchHandle;
+ UINT8 MaxPciePortNum;
+ CPU_PCIE_HOB *CpuPcieHob;
+
+ DEBUG ((DEBUG_INFO, "InitializeCpuPcieSmm () Start\n"));
+
+ MaxPciePortNum = GetMaxCpuPciePortNum ();
+
+ //
+ // Locate Pch Pcie Smi Dispatch Protocol
+ //
+ Status = gSmst->SmmLocateProtocol (&gPchPcieSmiDispatchProtocolGuid, NULL, (VOID**) &PchPcieSmiDispatchProtocol);
+ ASSERT_EFI_ERROR (Status);
+
+ mTempRootPortBusNumMin = PcdGet8 (PcdSiliconInitTempPciBusMin);
+ mTempRootPortBusNumMax = PcdGet8 (PcdSiliconInitTempPciBusMax);
+
+ ///
+ /// Locate HOB for CPU PCIe
+ ///
+ CpuPcieHob = GetFirstGuidHob(&gCpuPcieHobGuid);
+ if (CpuPcieHob != NULL) {
+ ASSERT (sizeof mCpuPcieRootPortConfig == sizeof CpuPcieHob->RootPort);
+ CopyMem (
+ mCpuPcieRootPortConfig,
+ &(CpuPcieHob->RootPort),
+ sizeof (mCpuPcieRootPortConfig)
+ );
+ }
+
+ //
+ // Throught all PCIE root port function and register the SMI Handler for enabled ports.
+ //
+ for (PortIndex = 0; PortIndex < MaxPciePortNum; PortIndex++) {
+ GetCpuPcieRpDevFun (PortIndex, &RpDevice, &RpFunction);
+ RpBase = PCI_SEGMENT_LIB_ADDRESS (SA_SEG_NUM, SA_MC_BUS, (UINT32) RpDevice, (UINT32) RpFunction, 0);
+ //
+ // Skip the root port function which is not enabled
+ //
+ if (PciSegmentRead32 (RpBase) == 0xFFFFFFFF) {
+ continue;
+ }
+
+ //
+ // Register SMI Handlers for Hot Plug and Link Active State Change
+ //
+ Data8 = PciSegmentRead8 (RpBase + R_PCIE_SLCAP);
+ if (Data8 & B_PCIE_SLCAP_HPC) {
+ PcieHandle = NULL;
+ Status = PchPcieSmiDispatchProtocol->HotPlugRegister (
+ PchPcieSmiDispatchProtocol,
+ CpuPcieSmiRpHandlerFunction,
+ (PortIndex + CpuRpIndex0),
+ &PcieHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = PchPcieSmiDispatchProtocol->LinkActiveRegister (
+ PchPcieSmiDispatchProtocol,
+ CpuPcieLinkActiveStateChange,
+ (PortIndex + CpuRpIndex0),
+ &PcieHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Data32Or = B_PCIE_MPC_HPME;
+ Data32And = (UINT32) ~B_PCIE_MPC_HPME;
+ S3BootScriptSaveMemReadWrite (
+ S3BootScriptWidthUint32,
+ PcdGet64 (PcdSiPciExpressBaseAddress) + RpBase + R_PCIE_MPC,
+ &Data32Or, /// Data to be ORed
+ &Data32And /// Data to be ANDed
+ );
+ }
+
+ //
+ // Register SMI Handler for Link Equalization Request from Gen 3 Devices.
+ //
+ Data8 = PciSegmentRead8 (RpBase + R_PCIE_LCAP);
+ if ((Data8 & B_PCIE_LCAP_MLS) == V_PCIE_LCAP_MLS_GEN3) {
+ Status = PchPcieSmiDispatchProtocol->LinkEqRegister (
+ PchPcieSmiDispatchProtocol,
+ CpuPcieLinkEqHandlerFunction,
+ (PortIndex + CpuRpIndex0),
+ &PcieHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+ }
+
+ ASSERT_EFI_ERROR (Status);
+ PchIoTrapContext.Type = WriteTrap;
+ PchIoTrapContext.Length = 4;
+ PchIoTrapContext.Address = 0;
+ Status = mPchIoTrap->Register (
+ mPchIoTrap,
+ (EFI_SMM_HANDLER_ENTRY_POINT2) CpuPcieIoTrapSmiCallback,
+ &PchIoTrapContext,
+ &PchIoTrapHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Install the SA Pcie IoTrap protocol
+ //
+ (gBS->AllocatePool) (EfiBootServicesData, sizeof (SA_IOTRAP_SMI_PROTOCOL), (VOID **)&CpuPcieIoTrapProtocol);
+ CpuPcieIoTrapProtocol->SaIotrapSmiAddress = PchIoTrapContext.Address;
+
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &ImageHandle,
+ &gCpuPcieIoTrapProtocolGuid,
+ CpuPcieIoTrapProtocol,
+ NULL
+ );
+
+ //
+ // Register the callback for S3 entry
+ //
+ SxDispatchContext.Type = SxS3;
+ SxDispatchContext.Phase = SxEntry;
+ Status = mSxDispatch->Register (
+ mSxDispatch,
+ CpuPcieS3EntryCallBack,
+ &SxDispatchContext,
+ &SxDispatchHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ DEBUG ((DEBUG_INFO, "InitializeCpuPcieSmm, IoTrap @ %x () End\n", PchIoTrapContext.Address));
+
+ return EFI_SUCCESS;
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/SaInit/Smm/SaLateInitSmm.c b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/SaInit/Smm/SaLateInitSmm.c
new file mode 100644
index 0000000000..0e9ba41f1b
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/SaInit/Smm/SaLateInitSmm.c
@@ -0,0 +1,112 @@
+/** @file
+ This SMM driver will handle SA relevant late initialization
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include <Library/BaseLib.h>
+#include <Base.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/SmmServicesTableLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <Library/IoLib.h>
+#include <Library/HobLib.h>
+#include <Library/SaPlatformLib.h>
+#include <Protocol/SmmIoTrapDispatch2.h>
+#include "SaLateInitSmm.h"
+#include <Library/PciSegmentLib.h>
+#include <CpuDataStruct.h>
+#include <CpuPcieHob.h>
+#include <Protocol/SaIotrapSmi.h>
+#include <PchPcieRpConfig.h>
+#include <SaConfigHob.h>
+#include "CpuPcieInfo.h"
+#include <Register/CpuPcieRegs.h>
+#include <IndustryStandard/Pci30.h>
+#include <Register/IgdRegs.h>
+#include <Register/CommonMsr.h>
+
+typedef enum {
+ EnumSaSmiCallbackForMaxPayLoad,
+ EnumSaSmiCallbackForSaSaveRestore,
+ EnumSaSmiCallbackForLateInit,
+ EnumSaSmiCallbackForS3resume,
+ EnumSaSmiCallbackMax
+} SMI_OPERATION;
+
+GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mSaSmiCallbackPhase = EnumSaSmiCallbackForMaxPayLoad;
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_SMM_IO_TRAP_DISPATCH2_PROTOCOL *mPchIoTrap;
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_SMM_SX_DISPATCH2_PROTOCOL *mSxDispatch;
+
+
+typedef struct {
+ UINT64 BaseAddr;
+ UINT32 Offset;
+ UINT32 AndMask;
+ UINT32 OrMask;
+} BOOT_SCRIPT_REGISTER_SETTING;
+
+/**
+ Initializes the SA SMM handler
+
+ @param[in] ImageHandle - The image handle of Wake On Lan driver
+ @param[in] SystemTable - The standard EFI system table
+
+ @retval EFI_SUCCESS - SA SMM handler was installed or not necessary
+ @retval EFI_NOT_FOUND - Fail to register SMI callback or required protocol/hob missing.
+**/
+EFI_STATUS
+EFIAPI
+SaLateInitSmmEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+#if FixedPcdGetBool(PcdCpuPcieEnable) == 1
+ CPU_PCIE_HOB *CpuPcieHob = NULL;
+ EFI_STATUS Status;
+#endif
+
+ DEBUG ((DEBUG_INFO, "SaLateInitSmmEntryPoint()\n"));
+
+#if FixedPcdGetBool(PcdCpuPcieEnable) == 1
+ CpuPcieHob = (CPU_PCIE_HOB *) GetFirstGuidHob (&gCpuPcieHobGuid);
+ Status = EFI_NOT_FOUND;
+ if (CpuPcieHob == NULL) {
+ DEBUG ((DEBUG_INFO, "CPU PCIE HOB Not found\n"));
+ ASSERT (CpuPcieHob != NULL);
+ return Status;
+ }
+
+ ///
+ /// Locate the PCH Trap dispatch protocol
+ ///
+ Status = gSmst->SmmLocateProtocol (&gEfiSmmIoTrapDispatch2ProtocolGuid, NULL, (VOID **) &mPchIoTrap);
+ ASSERT_EFI_ERROR (Status);
+ Status = gSmst->SmmLocateProtocol (&gEfiSmmSxDispatch2ProtocolGuid, NULL, (VOID**) &mSxDispatch);
+ ASSERT_EFI_ERROR (Status);
+ if (Status == EFI_SUCCESS) {
+ ///
+ /// If ASPM policy is set to "Before OPROM", this SMI callback is not necessary
+ /// Ensure the SMI callback handler will directly return and continue the POST.
+ ///
+ mSaSmiCallbackPhase = EnumSaSmiCallbackMax;
+ Status = EFI_SUCCESS;
+ }
+
+ Status = InitializeCpuPcieSmm (ImageHandle, SystemTable);
+ ASSERT_EFI_ERROR (Status);
+
+ if (Status != EFI_SUCCESS) {
+ DEBUG ((DEBUG_ERROR, "Failed to register SaIotrapSmiCallback!\n"));
+ ///
+ /// System will halt when failing to register required SMI handler
+ ///
+ CpuDeadLoop ();
+ }
+#endif
+ return EFI_SUCCESS;
+}
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/SaInit/Smm/SaLateInitSmm.h b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/SaInit/Smm/SaLateInitSmm.h
new file mode 100644
index 0000000000..c93f92305c
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/SaInit/Smm/SaLateInitSmm.h
@@ -0,0 +1,122 @@
+/** @file
+ Header file for SA SMM Handler
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _SaLateInitSmm_H_
+#define _SaLateInitSmm_H_
+
+///
+/// Driver Consumed Protocol Prototypes
+///
+
+#include <Protocol/SmmBase2.h>
+#include <Protocol/SmmSxDispatch2.h>
+#include <Protocol/SmmIoTrapDispatch2.h>
+#include <Protocol/SaPolicy.h>
+#include <Library/S3BootScriptLib.h>
+#include <CpuPcieConfig.h>
+#include <Library/CpuPcieInfoFruLib.h>
+
+extern EFI_SMM_IO_TRAP_DISPATCH2_PROTOCOL *mPchIoTrap;
+extern EFI_SMM_SX_DISPATCH2_PROTOCOL *mSxDispatch;
+
+///
+/// The value before AutoConfig match the setting of PCI Express Base Specification 1.1, please be careful for adding new feature
+///
+typedef enum {
+ PcieAspmDisabled,
+ PcieAspmL0s,
+ PcieAspmL1,
+ PcieAspmL0sL1,
+ PcieAspmAutoConfig,
+ PcieAspmMax
+} CPU_PCIE_ASPM_CONFIG;
+
+typedef struct {
+ UINT64 Address;
+ S3_BOOT_SCRIPT_LIB_WIDTH Width;
+ UINT32 Value;
+} BOOT_SCRIPT_PCI_REGISTER_SAVE;
+
+
+/**
+ <b>System Agent Initialization SMM Driver Entry Point</b>
+ - <b>Introduction</b> \n
+ This is an optional driver to support PCIe ASPM initialization later than Option ROM initialization.\n
+ In this scenario S3 Save Boot Script table has been closed per security consideration so the ASPM settings will be stored in SMM memory and restored during S3 resume.
+ If platform does not support this scenario this driver can be excluded and SI_SA_POLICY_PPI -> PCIE_CONFIG -> InitPcieAspmAfterOprom must be set to FALSE. \n
+ Note: When InitPcieAspmAfterOprom enabled, the SMI callback handler must be registered successfully, otherwise it will halt the system.
+
+ - @pre
+ - _EFI_SMM_BASE_PROTOCOL (or _EFI_SMM_BASE2_PROTOCOL for EDK2): Provides SMM infrastructure services.
+ - _EFI_SMM_IO_TRAP_DISPATCH_PROTOCOL (or _EFI_SMM_IO_TRAP_DISPATCH2_PROTOCOL for EDK2): Interface structure for the SMM IO trap specific SMI Dispatch Protocol
+ - SA_POLICY_PROTOCOL: A protocol published by a platform DXE module executed earlier; this is documented in this document as well.
+
+ - @result
+ PCIe ASPM has been initialized on all end point devices discovered and same settings will be restored during S3 resume.
+
+ @param[in] ImageHandle - The image handle of Wake On Lan driver
+ @param[in] SystemTable - The standard EFI system table
+
+ @retval EFI_SUCCESS - SA SMM handler was installed or not necessary
+ @retval EFI_NOT_FOUND - Fail to register SMI callback or required protocol/hob missing.
+**/
+EFI_STATUS
+EFIAPI
+SaLateInitSmmEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+An IoTrap callback to config PCIE power management settings
+
+@param[in] DispatchHandle - The handle of this callback, obtained when registering
+@param[in] DispatchContext - Pointer to the EFI_SMM_IO_TRAP_DISPATCH_CALLBACK_CONTEXT
+
+**/
+VOID
+EFIAPI
+CpuPcieIoTrapSmiCallback(
+IN EFI_HANDLE DispatchHandle,
+IN EFI_SMM_IO_TRAP_CONTEXT *CallbackContext,
+IN OUT VOID *CommBuffer,
+IN OUT UINTN *CommBufferSize
+);
+
+/**
+ This function is used to set or clear flags at S3 entry
+ Clear the Io trap executed flag before enter S3
+
+ @param[in] Handle Handle of the callback
+ @param[in] Context The dispatch context
+ @param[in,out] CommBuffer A pointer to a collection of data in memory that will be conveyed from a non-SMM environment into an SMM environment.
+ @param[in,out] CommBufferSize The size of the CommBuffer.
+ @retval EFI_SUCCESS SA register saved
+**/
+EFI_STATUS
+EFIAPI
+CpuPcieS3EntryCallBack (
+ IN EFI_HANDLE Handle,
+ IN CONST VOID *Context OPTIONAL,
+ IN OUT VOID *CommBuffer OPTIONAL,
+ IN OUT UINTN *CommBufferSize OPTIONAL
+ );
+
+/**
+ Register PCIE Hotplug SMI dispatch function to handle Hotplug enabling
+
+ @param[in] ImageHandle The image handle of this module
+ @param[in] SystemTable The EFI System Table
+
+ @retval EFI_SUCCESS The function completes successfully
+**/
+EFI_STATUS
+EFIAPI
+InitializeCpuPcieSmm (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+#endif
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/SaInit/Smm/SaLateInitSmm.inf b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/SaInit/Smm/SaLateInitSmm.inf
new file mode 100644
index 0000000000..ef3486d2a6
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/SystemAgent/SaInit/Smm/SaLateInitSmm.inf
@@ -0,0 +1,72 @@
+## @file
+# Component description file for the SA late initialization SMM module.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = SaLateInitSmm
+FILE_GUID = 2D1E361C-7B3F-4d15-8B1F-66E551FABDC7
+VERSION_STRING = 1.0
+MODULE_TYPE = DXE_SMM_DRIVER
+PI_SPECIFICATION_VERSION = 1.10
+ENTRY_POINT = SaLateInitSmmEntryPoint
+
+[LibraryClasses]
+UefiDriverEntryPoint
+UefiBootServicesTableLib
+DxeServicesTableLib
+DebugLib
+HobLib
+BaseLib
+S3BootScriptLib
+PciSegmentLib
+SaPlatformLib
+TimerLib
+PciExpressHelpersLib
+PcdLib
+S3BootScriptLib
+CpuPcieInfoFruLib
+ConfigBlockLib
+CpuPcieRpLib
+
+[Packages]
+MdePkg/MdePkg.dec
+TigerlakeSiliconPkg/SiPkg.dec
+
+[Pcd]
+gSiPkgTokenSpaceGuid.PcdSiPciExpressBaseAddress
+gSiPkgTokenSpaceGuid.PcdSiliconInitTempPciBusMax
+gSiPkgTokenSpaceGuid.PcdSiliconInitTempPciBusMin
+gSiPkgTokenSpaceGuid.PcdCpuPcieEnable ## CONSUMES
+
+
+[Sources]
+SaLateInitSmm.c
+CpuPcieSmm.c
+SaLateInitSmm.h
+
+[Protocols]
+gSaPolicyProtocolGuid ## CONSUMES
+gEfiSmmIoTrapDispatch2ProtocolGuid ## CONSUMES
+gSaIotrapSmiProtocolGuid ## PRODUCES
+gCpuPcieIoTrapProtocolGuid ## PRODUCES
+gEfiSmmSxDispatch2ProtocolGuid ## CONSUMES
+gPchSmiDispatchProtocolGuid ## CONSUMES
+gPchPcieSmiDispatchProtocolGuid ## CONSUMES
+
+[Guids]
+gSaConfigHobGuid
+gCpuPcieHobGuid
+gPcieDxeConfigGuid
+gSaPegHobGuid
+
+[Depex]
+gEfiSmmBase2ProtocolGuid AND
+gEfiSmmSxDispatch2ProtocolGuid AND
+gEfiSmmIoTrapDispatch2ProtocolGuid AND
+gSaPolicyProtocolGuid
+
--
2.24.0.windows.2
^ permalink raw reply related [flat|nested] 42+ messages in thread
* [Patch V3 38/40] TigerlakeSiliconPkg/Fru: Add Fru DSC files
2021-02-05 7:40 [Patch V3 01/40] TigerlakeSiliconPkg: Add package and Include/ConfigBlock headers Heng Luo
` (35 preceding siblings ...)
2021-02-05 7:40 ` [Patch V3 37/40] TigerlakeSiliconPkg/SystemAgent: Add SystemAgent modules Heng Luo
@ 2021-02-05 7:40 ` Heng Luo
2021-02-05 7:40 ` [Patch V3 39/40] TigerlakeSiliconPkg: Add package " Heng Luo
2021-02-05 7:40 ` [Patch V3 40/40] Maintainers.txt: Add TigerlakeSiliconPkg maintainers Heng Luo
38 siblings, 0 replies; 42+ messages in thread
From: Heng Luo @ 2021-02-05 7:40 UTC (permalink / raw)
To: devel; +Cc: Sai Chaganty, Nate DeSimone
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3171
Adds the following DSC files:
* Fru/TglCpu
* Fru/TglPch
Cc: Sai Chaganty <rangasai.v.chaganty@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Signed-off-by: Heng Luo <heng.luo@intel.com>
---
Silicon/Intel/TigerlakeSiliconPkg/Fru/TglCpu/CommonLib.dsc | 11 +++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Fru/TglCpu/Dxe.dsc | 9 +++++++++
Silicon/Intel/TigerlakeSiliconPkg/Fru/TglCpu/DxeLib.dsc | 20 ++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Fru/TglCpu/Pei.dsc | 8 ++++++++
Silicon/Intel/TigerlakeSiliconPkg/Fru/TglCpu/PeiLib.dsc | 7 +++++++
Silicon/Intel/TigerlakeSiliconPkg/Fru/TglPch/CommonLib.dsc | 30 ++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Fru/TglPch/Dxe.dsc | 9 +++++++++
Silicon/Intel/TigerlakeSiliconPkg/Fru/TglPch/DxeLib.dsc | 13 +++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/Fru/TglPch/Pei.dsc | 8 ++++++++
Silicon/Intel/TigerlakeSiliconPkg/Fru/TglPch/PeiLib.dsc | 10 ++++++++++
10 files changed, 125 insertions(+)
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglCpu/CommonLib.dsc b/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglCpu/CommonLib.dsc
new file mode 100644
index 0000000000..99ee0eccac
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglCpu/CommonLib.dsc
@@ -0,0 +1,11 @@
+## @file
+# Component description file for the TigerLake CPU Common FRU libraries.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+VtdInfoLib|$(PLATFORM_SI_PACKAGE)/IpBlock/Vtd/Library/PeiDxeSmmVtdInfoLib/PeiDxeSmmVtdInfoLib.inf
+CpuPcieRpLib|$(PLATFORM_SI_PACKAGE)/IpBlock/CpuPcieRp/Library/PeiDxeSmmCpuPcieRpLib/PeiDxeSmmCpuPcieRpLib.inf
+CpuPcieInfoFruLib|$(PLATFORM_SI_PACKAGE)/Fru/TglCpu/CpuPcieRp/Library/PeiDxeSmmCpuPcieInfoFruLib/PeiDxeSmmCpuPcieInfoFruLib.inf
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglCpu/Dxe.dsc b/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglCpu/Dxe.dsc
new file mode 100644
index 0000000000..874e4cbaad
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglCpu/Dxe.dsc
@@ -0,0 +1,9 @@
+## @file
+# Component description file for the Tigerlake CPU DXE FRU drivers.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglCpu/DxeLib.dsc b/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglCpu/DxeLib.dsc
new file mode 100644
index 0000000000..5c72c2ac61
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglCpu/DxeLib.dsc
@@ -0,0 +1,20 @@
+## @file
+# Component description file for the Tigerlake CPU DXE FRU libraries.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+DxeGraphicsPolicyLib|$(PLATFORM_SI_PACKAGE)/IpBlock/Graphics/LibraryPrivate/DxeGraphicsPolicyLib/DxeGraphicsPolicyLib.inf
+DxeGraphicsInitLib|$(PLATFORM_SI_PACKAGE)/IpBlock/Graphics/LibraryPrivate/DxeGraphicsInitLib/DxeGraphicsInitLib.inf
+DxeIgdOpRegionInitLib|$(PLATFORM_SI_PACKAGE)/IpBlock/Graphics/LibraryPrivate/DxeIgdOpRegionInitLib/DxeIgdOpRegionInitLib.inf
+DxeVtdInitLib|$(PLATFORM_SI_PACKAGE)/IpBlock/Vtd/LibraryPrivate/DxeVtdInitLib/DxeVtdInitLib.inf
+DxeVtdPolicyLib|$(PLATFORM_SI_PACKAGE)/IpBlock/Vtd/LibraryPrivate/DxeVtdPolicyLib/DxeVtdPolicyLib.inf
+DxeVtdInitFruLib|$(PLATFORM_SI_PACKAGE)/Fru/TglCpu/Vtd/LibraryPrivate/DxeVtdInitLib/DxeVtdInitFruLib.inf
+
+
+#
+# CPU PCIe IpBlock
+#
+DxeCpuPcieRpLib|$(PLATFORM_SI_PACKAGE)/IpBlock/CpuPcieRp/LibraryPrivate/DxeCpuPcieRpLib/DxeCpuPcieRpLib.inf
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglCpu/Pei.dsc b/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglCpu/Pei.dsc
new file mode 100644
index 0000000000..de8288364a
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglCpu/Pei.dsc
@@ -0,0 +1,8 @@
+## @file
+# Component description file for the Tigerlake CPU PEI FRU drivers.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglCpu/PeiLib.dsc b/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglCpu/PeiLib.dsc
new file mode 100644
index 0000000000..5355ecb288
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglCpu/PeiLib.dsc
@@ -0,0 +1,7 @@
+## @file
+# Component description file for the Tigerlake CPU PEI FRU ibraries.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglPch/CommonLib.dsc b/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglPch/CommonLib.dsc
new file mode 100644
index 0000000000..b7ba1f752c
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglPch/CommonLib.dsc
@@ -0,0 +1,30 @@
+## @file
+# Component description file for the Tigerlake PCH Common FRU libraries.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+ PsfLib|$(PLATFORM_SI_PACKAGE)/IpBlock/Psf/LibraryPrivate/PsfLib/PeiDxeSmmPsfLibVer2.inf
+ PchPcrLib|$(PLATFORM_SI_PACKAGE)/IpBlock/P2sb/Library/PeiDxeSmmPchPcrLib/PeiDxeSmmPchPcrLib.inf
+ PchSbiAccessLib|$(PLATFORM_SI_PACKAGE)/IpBlock/P2sb/LibraryPrivate/PeiDxeSmmPchSbiAccessLib/PeiDxeSmmPchSbiAccessLib.inf
+ GbeMdiLib|$(PLATFORM_SI_PACKAGE)/IpBlock/Gbe/LibraryPrivate/PeiDxeSmmGbeMdiLib/PeiDxeSmmGbeMdiLib.inf
+ GbeLib|$(PLATFORM_SI_PACKAGE)/IpBlock/Gbe/Library/PeiDxeSmmGbeLib/PeiDxeSmmGbeLib.inf
+ EspiLib|$(PLATFORM_SI_PACKAGE)/IpBlock/Espi/Library/PeiDxeSmmEspiLib/PeiDxeSmmEspiLib.inf
+ PmcLib|$(PLATFORM_SI_PACKAGE)/IpBlock/Pmc/Library/PeiDxeSmmPmcLib/PeiDxeSmmPmcLib.inf
+ PmcPrivateLib|$(PLATFORM_SI_PACKAGE)/IpBlock/Pmc/LibraryPrivate/PeiDxeSmmPmcPrivateLib/PeiDxeSmmPmcPrivateLibVer2.inf
+ PmcPrivateLibWithS3|$(PLATFORM_SI_PACKAGE)/IpBlock/Pmc/LibraryPrivate/PeiDxeSmmPmcPrivateLib/PeiDxeSmmPmcPrivateLibWithS3.inf
+ SpiCommonLib|$(PLATFORM_SI_PACKAGE)/IpBlock/Spi/LibraryPrivate/BaseSpiCommonLib/BaseSpiCommonLib.inf
+ GpioLib|$(PLATFORM_SI_PACKAGE)/IpBlock/Gpio/Library/PeiDxeSmmGpioLib/PeiDxeSmmGpioLib.inf
+ GpioPrivateLib|$(PLATFORM_SI_PACKAGE)/IpBlock/Gpio/LibraryPrivate/PeiDxeSmmGpioPrivateLib/PeiDxeSmmGpioPrivateLibVer2.inf
+ GpioCheckConflictLib|$(PLATFORM_SI_PACKAGE)/IpBlock/Gpio/Library/BaseGpioCheckConflictLib/BaseGpioCheckConflictLib.inf
+ PchDmiLib|$(PLATFORM_SI_PACKAGE)/IpBlock/PchDmi/LibraryPrivate/PeiDxeSmmPchDmiLib/PeiDxeSmmPchDmiLib.inf
+ PchDmiWithS3Lib|$(PLATFORM_SI_PACKAGE)/IpBlock/PchDmi/LibraryPrivate/PeiDxeSmmPchDmiLib/PeiDxeSmmPchDmiWithS3Lib.inf
+ SataLib|$(PLATFORM_SI_PACKAGE)/IpBlock/Sata/Library/PeiDxeSmmSataLib/PeiDxeSmmSataLibVer2.inf
+ SpiAccessLib|$(PLATFORM_SI_PACKAGE)/IpBlock/Spi/Library/PeiDxeSmmSpiAccessLib/PeiDxeSmmSpiAccessLib.inf
+ SpiAccessPrivateLib|$(PLATFORM_SI_PACKAGE)/IpBlock/Spi/LibraryPrivate/PeiDxeSmmSpiAccessPrivateLib/PeiDxeSmmSpiAccessPrivateLib.inf
+ PchPcieRpLib|$(PLATFORM_SI_PACKAGE)/IpBlock/PcieRp/Library/PeiDxeSmmPchPcieRpLib/PeiDxeSmmPchPcieRpLibVer2.inf
+ PcieRpLib|$(PLATFORM_SI_PACKAGE)/IpBlock/PcieRp/LibraryPrivate/PcieClientRpLib/PcieClientRpLib.inf
+ PciExpressHelpersLib|$(PLATFORM_SI_PACKAGE)/IpBlock/PcieRp/LibraryPrivate/PciExpressHelpersLibrary/PeiDxeSmmPciExpressHelpersLib.inf
+ BasePcieHelperLib|$(PLATFORM_SI_PACKAGE)/IpBlock/PcieRp/Library/BasePcieHelperLib/BasePcieHelperLib.inf
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglPch/Dxe.dsc b/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglPch/Dxe.dsc
new file mode 100644
index 0000000000..9fefc6b4c9
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglPch/Dxe.dsc
@@ -0,0 +1,9 @@
+## @file
+# Component description file for the Tigerlake PCH DXE FRU drivers.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+$(PLATFORM_SI_PACKAGE)/IpBlock/Spi/Smm/SpiSmm.inf
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglPch/DxeLib.dsc b/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglPch/DxeLib.dsc
new file mode 100644
index 0000000000..e9be448baa
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglPch/DxeLib.dsc
@@ -0,0 +1,13 @@
+## @file
+# Component description file for the Tigerlake PCH DXE FRU libraries.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+ DxeHdaNhltLib|$(PLATFORM_SI_PACKAGE)/IpBlock/Hda/Library/DxeHdaNhltLib/DxeHdaNhltLib.inf
+ DxeHdaPolicyLib|$(PLATFORM_SI_PACKAGE)/IpBlock/Hda/LibraryPrivate/DxeHdaPolicyLib/DxeHdaPolicyLib.inf
+ GpioHelpersLib|$(PLATFORM_SI_PACKAGE)/IpBlock/Gpio/LibraryPrivate/BaseGpioHelpersLibNull/BaseGpioHelpersLibNull.inf
+ GpioNameBufferLib|$(PLATFORM_SI_PACKAGE)/IpBlock/Gpio/LibraryPrivate/DxeGpioNameBufferLib/DxeGpioNameBufferLib.inf
+ DxeGpioPolicyLib|$(PLATFORM_SI_PACKAGE)/IpBlock/Gpio/LibraryPrivate/DxeGpioPolicyLib/DxeGpioPolicyLib.inf
+ DxePchPcieRpPolicyLib|$(PLATFORM_SI_PACKAGE)/IpBlock/PcieRp/LibraryPrivate/DxePchPcieRpPolicyLib/DxePchPcieRpPolicyLib.inf
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglPch/Pei.dsc b/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglPch/Pei.dsc
new file mode 100644
index 0000000000..2eacbe905c
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglPch/Pei.dsc
@@ -0,0 +1,8 @@
+## @file
+# Component description file for the Tigerlake PCH PEI FRU drivers.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglPch/PeiLib.dsc b/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglPch/PeiLib.dsc
new file mode 100644
index 0000000000..d8e6313084
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/Fru/TglPch/PeiLib.dsc
@@ -0,0 +1,10 @@
+## @file
+# Component description file for the Tigerlake PCH PEI FRU libraries.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+ GpioHelpersLib|$(PLATFORM_SI_PACKAGE)/IpBlock/Gpio/LibraryPrivate/PeiGpioHelpersLib/PeiGpioHelpersLib.inf
+ GpioNameBufferLib|$(PLATFORM_SI_PACKAGE)/IpBlock/Gpio/LibraryPrivate/PeiGpioNameBufferLib/PeiGpioNameBufferLib.inf
--
2.24.0.windows.2
^ permalink raw reply related [flat|nested] 42+ messages in thread
* [Patch V3 39/40] TigerlakeSiliconPkg: Add package DSC files
2021-02-05 7:40 [Patch V3 01/40] TigerlakeSiliconPkg: Add package and Include/ConfigBlock headers Heng Luo
` (36 preceding siblings ...)
2021-02-05 7:40 ` [Patch V3 38/40] TigerlakeSiliconPkg/Fru: Add Fru DSC files Heng Luo
@ 2021-02-05 7:40 ` Heng Luo
2021-02-05 7:40 ` [Patch V3 40/40] Maintainers.txt: Add TigerlakeSiliconPkg maintainers Heng Luo
38 siblings, 0 replies; 42+ messages in thread
From: Heng Luo @ 2021-02-05 7:40 UTC (permalink / raw)
To: devel; +Cc: Sai Chaganty, Nate DeSimone
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3171
Cc: Sai Chaganty <rangasai.v.chaganty@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Signed-off-by: Heng Luo <heng.luo@intel.com>
---
Silicon/Intel/TigerlakeSiliconPkg/SiPkgBuildOption.dsc | 122 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/SiPkgCommonLib.dsc | 43 +++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/SiPkgDxe.dsc | 47 +++++++++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/SiPkgDxeLib.dsc | 40 ++++++++++++++++++++++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/SiPkgPei.dsc | 20 ++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/SiPkgPeiLib.dsc | 20 ++++++++++++++++++++
Silicon/Intel/TigerlakeSiliconPkg/TigerlakeSiliconPkg.dsc | 229 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
7 files changed, 521 insertions(+)
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/SiPkgBuildOption.dsc b/Silicon/Intel/TigerlakeSiliconPkg/SiPkgBuildOption.dsc
new file mode 100644
index 0000000000..51c40812ea
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/SiPkgBuildOption.dsc
@@ -0,0 +1,122 @@
+## @file
+# Silicon build option configuration file.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[BuildOptions]
+# Define Build Options both for EDK and EDKII drivers.
+
+ DEFINE PCH_BUILD_OPTIONS = -DPCH_TGL
+#
+# SA
+#
+!if gSiPkgTokenSpaceGuid.PcdBdatEnable == TRUE
+ DEFINE BDAT_BUILD_OPTION = -DBDAT_SUPPORT=1
+!else
+ DEFINE BDAT_BUILD_OPTION =
+!endif
+
+ DEFINE SLE_BUILD_OPTIONS =
+!if $(TARGET) == RELEASE
+!if gSiPkgTokenSpaceGuid.PcdSiCatalogDebugEnable == TRUE
+ DEFINE DEBUG_BUILD_OPTIONS =
+!else
+ # MDEPKG_NDEBUG is introduced for the intention
+ # of size reduction when compiler optimization is disabled. If MDEPKG_NDEBUG is
+ # defined, then debug and assert related macros wrapped by it are the NULL implementations.
+ DEFINE DEBUG_BUILD_OPTIONS = -DMDEPKG_NDEBUG
+!endif
+!else
+ DEFINE DEBUG_BUILD_OPTIONS =
+!endif
+
+!if ($(TARGET) == RELEASE) AND (gSiPkgTokenSpaceGuid.PcdSiCatalogDebugEnable == TRUE)
+ DEFINE RELEASE_CATALOG_BUILD_OPTIONS = -DRELEASE_CATALOG
+!else
+ DEFINE RELEASE_CATALOG_BUILD_OPTIONS =
+!endif
+
+!if gSiPkgTokenSpaceGuid.PcdOptimizeCompilerEnable == FALSE
+ DEFINE OPTIMIZE_DISABLE_OPTIONS = -Od -GL-
+!else
+ DEFINE OPTIMIZE_DISABLE_OPTIONS =
+!endif
+
+ DEFINE HSLE_BUILD_OPTIONS =
+
+
+ DEFINE CPU_FLAGS = -DCPU_ICL -DCPU_TGL
+
+
+ DEFINE RESTRICTED_OPTION =
+
+!if gSiPkgTokenSpaceGuid.PcdMrcTraceMessageSupported == FALSE
+ *_*_*_MRC_NDEBUG = -DMDEPKG_NDEBUG
+!endif
+
+DEFINE DSC_SIPKG_FEATURE_BUILD_OPTIONS = $(BDAT_BUILD_OPTION) $(DEBUG_BUILD_OPTIONS)
+DEFINE DSC_SIPKG_FEATURE_BUILD_OPTIONS = $(DSC_SIPKG_FEATURE_BUILD_OPTIONS) $(PCH_BUILD_OPTIONS) $(CPU_FLAGS) $(HSLE_BUILD_OPTIONS)
+
+!if gSiPkgTokenSpaceGuid.PcdSourceDebugEnable == TRUE
+ *_*_X64_GENFW_FLAGS = --keepexceptiontable
+!endif
+
+[BuildOptions.Common.EDKII]
+
+#
+# For IA32 Global Build Flag
+#
+ *_*_IA32_CC_FLAGS = $(DSC_SIPKG_FEATURE_BUILD_OPTIONS) -D PI_SPECIFICATION_VERSION=0x00010015 -DASF_PEI
+ *_*_IA32_VFRPP_FLAGS = $(DSC_SIPKG_FEATURE_BUILD_OPTIONS)
+ *_*_IA32_APP_FLAGS = $(DSC_SIPKG_FEATURE_BUILD_OPTIONS)
+ *_*_IA32_ASLPP_FLAGS = $(DSC_SIPKG_FEATURE_BUILD_OPTIONS)
+ *_*_IA32_ASLCC_FLAGS = $(DSC_SIPKG_FEATURE_BUILD_OPTIONS)
+
+#
+# For IA32 Specific Build Flag
+#
+GCC: *_*_IA32_PP_FLAGS = $(DSC_SIPKG_FEATURE_BUILD_OPTIONS)
+MSFT: *_*_IA32_ASM_FLAGS = $(DSC_SIPKG_FEATURE_BUILD_OPTIONS)
+MSFT: *_*_IA32_CC_FLAGS = $(DSC_SIPKG_FEATURE_BUILD_OPTIONS) $(OPTIMIZE_DISABLE_OPTIONS) -D PI_SPECIFICATION_VERSION=0x00010015 -DASF_PEI /w34668
+MSFT: *_*_IA32_VFRPP_FLAGS = $(DSC_SIPKG_FEATURE_BUILD_OPTIONS) $(OPTIMIZE_DISABLE_OPTIONS)
+MSFT: *_*_IA32_APP_FLAGS = $(DSC_SIPKG_FEATURE_BUILD_OPTIONS) $(OPTIMIZE_DISABLE_OPTIONS)
+MSFT: *_*_IA32_ASLPP_FLAGS = $(DSC_SIPKG_FEATURE_BUILD_OPTIONS) $(OPTIMIZE_DISABLE_OPTIONS)
+MSFT: *_*_IA32_ASLCC_FLAGS = $(DSC_SIPKG_FEATURE_BUILD_OPTIONS) $(OPTIMIZE_DISABLE_OPTIONS)
+
+#
+# For X64 Global Build Flag
+#
+ *_*_X64_CC_FLAGS = $(DSC_SIPKG_FEATURE_BUILD_OPTIONS) -D PI_SPECIFICATION_VERSION=0x00010015
+ *_*_X64_VFRPP_FLAGS = $(DSC_SIPKG_FEATURE_BUILD_OPTIONS)
+ *_*_X64_APP_FLAGS = $(DSC_SIPKG_FEATURE_BUILD_OPTIONS)
+ *_*_X64_ASLPP_FLAGS = $(DSC_SIPKG_FEATURE_BUILD_OPTIONS)
+ *_*_X64_ASLCC_FLAGS = $(DSC_SIPKG_FEATURE_BUILD_OPTIONS)
+
+#
+# For X64 Specific Build Flag
+#
+GCC: *_*_X64_PP_FLAGS = $(DSC_SIPKG_FEATURE_BUILD_OPTIONS)
+MSFT: *_*_X64_ASM_FLAGS = $(DSC_SIPKG_FEATURE_BUILD_OPTIONS)
+MSFT: *_*_X64_CC_FLAGS = $(DSC_SIPKG_FEATURE_BUILD_OPTIONS) $(OPTIMIZE_DISABLE_OPTIONS) -D PI_SPECIFICATION_VERSION=0x00010015 /w34668
+MSFT: *_*_X64_VFRPP_FLAGS = $(DSC_SIPKG_FEATURE_BUILD_OPTIONS) $(OPTIMIZE_DISABLE_OPTIONS)
+MSFT: *_*_X64_APP_FLAGS = $(DSC_SIPKG_FEATURE_BUILD_OPTIONS) $(OPTIMIZE_DISABLE_OPTIONS)
+MSFT: *_*_X64_ASLPP_FLAGS = $(DSC_SIPKG_FEATURE_BUILD_OPTIONS)
+MSFT: *_*_X64_ASLCC_FLAGS = $(DSC_SIPKG_FEATURE_BUILD_OPTIONS)
+
+#
+# For Xcode Specific Build Flag
+#
+# Override assembly code build order
+*_XCODE5_*_*_BUILDRULEORDER = nasm S s
+# Align 47bfbd7f8069e523798ef973c8eb0abd5c6b0746 to fix the usage of VA_START in undefined way
+*_XCODE5_*_CC_FLAGS = -Wno-varargs
+
+# Force PE/COFF sections to be aligned at 4KB boundaries to support page level protection of runtime modules
+[BuildOptions.common.EDKII.DXE_RUNTIME_DRIVER]
+ MSFT: *_*_*_DLINK_FLAGS = /ALIGN:4096
+ GCC: *_GCC*_*_DLINK_FLAGS = -z common-page-size=0x1000
+
+
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/SiPkgCommonLib.dsc b/Silicon/Intel/TigerlakeSiliconPkg/SiPkgCommonLib.dsc
new file mode 100644
index 0000000000..16f148f1e7
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/SiPkgCommonLib.dsc
@@ -0,0 +1,43 @@
+## @file
+# Component description file for the TigerLake silicon package both Pei and Dxe libraries DSC file.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+#
+# FRUs
+#
+!include $(PLATFORM_SI_PACKAGE)/Fru/TglCpu/CommonLib.dsc
+!include $(PLATFORM_SI_PACKAGE)/Fru/TglPch/CommonLib.dsc
+
+#
+# Common
+#
+ MmPciLib|$(PLATFORM_SI_PACKAGE)/Library/PeiDxeSmmMmPciLib/PeiDxeSmmMmPciLib.inf
+ PciSegmentLib|$(PLATFORM_SI_PACKAGE)/Library/BasePciSegmentMultiSegLibPci/BasePciSegmentMultiSegLibPci.inf
+
+#
+# Pch
+#
+ PchCycleDecodingLib|$(PLATFORM_SI_PACKAGE)/Pch/Library/PeiDxeSmmPchCycleDecodingLib/PeiDxeSmmPchCycleDecodingLib.inf
+ PchInfoLib|$(PLATFORM_SI_PACKAGE)/Pch/Library/PeiDxeSmmPchInfoLib/PeiDxeSmmPchInfoLibTgl.inf
+ CpuPcieInitCommonLib|$(PLATFORM_SI_PACKAGE)/IpBlock/CpuPcieRp/Library/PeiDxeSmmCpuPcieInitCommonLib/PeiDxeSmmCpuPcieInitCommonLib.inf
+ CpuPcieRpLib|$(PLATFORM_SI_PACKAGE)/IpBlock/CpuPcieRp/Library/PeiDxeSmmCpuPcieRpLib/PeiDxeSmmCpuPcieRpLib.inf
+
+ SerialIoAccessLib|$(PLATFORM_SI_PACKAGE)/IpBlock/SerialIo/Library/PeiDxeSmmSerialIoAccessLib/PeiDxeSmmSerialIoAccessLib.inf
+ SerialIoPrivateLib|$(PLATFORM_SI_PACKAGE)/IpBlock/SerialIo/LibraryPrivate/PeiDxeSmmSerialIoPrivateLib/PeiDxeSmmSerialIoPrivateLibVer2.inf
+ ResetSystemLib|$(PLATFORM_SI_PACKAGE)/Pch/Library/BaseResetSystemLib/BaseResetSystemLib.inf
+ #private
+ GpioPrivateLib|$(PLATFORM_SI_PACKAGE)/IpBlock/Gpio/LibraryPrivate/PeiDxeSmmGpioPrivateLib/PeiDxeSmmGpioPrivateLibVer2.inf
+
+ SiScheduleResetLib|$(PLATFORM_SI_PACKAGE)/Pch/LibraryPrivate/BaseSiScheduleResetLib/BaseSiScheduleResetLib.inf
+ PchPciBdfLib|$(PLATFORM_SI_PACKAGE)/Pch/Library/BasePchPciBdfLib/BasePchPciBdfLib.inf
+ PcieRpLib|$(PLATFORM_SI_PACKAGE)/IpBlock/PcieRp/LibraryPrivate/PcieClientRpLib/PcieClientRpLib.inf
+
+#
+# SA
+#
+ SaPlatformLib|$(PLATFORM_SI_PACKAGE)/SystemAgent/Library/PeiDxeSmmSaPlatformLib/PeiDxeSmmSaPlatformLib.inf
+ CpuRegbarAccessLib|$(PLATFORM_SI_PACKAGE)/IpBlock/P2sb/Library/PeiDxeSmmCpuRegbarAccessLib/PeiDxeSmmCpuRegbarAccessLib.inf
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/SiPkgDxe.dsc b/Silicon/Intel/TigerlakeSiliconPkg/SiPkgDxe.dsc
new file mode 100644
index 0000000000..1a08fbc24c
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/SiPkgDxe.dsc
@@ -0,0 +1,47 @@
+## @file
+# Component description file for the TigerLake silicon package DXE drivers.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+#
+# FRUs
+#
+!include $(PLATFORM_SI_PACKAGE)/Fru/TglCpu/Dxe.dsc
+!include $(PLATFORM_SI_PACKAGE)/Fru/TglPch/Dxe.dsc
+
+#
+# Common
+#
+
+#
+# Pch
+#
+ $(PLATFORM_SI_PACKAGE)/Pch/PchInit/Dxe/PchInitDxeTgl.inf
+ $(PLATFORM_SI_PACKAGE)/Pch/SmmControl/RuntimeDxe/SmmControl.inf
+
+ $(PLATFORM_SI_PACKAGE)/Pch/PchSmiDispatcher/Smm/PchSmiDispatcher.inf{
+ <LibraryClasses>
+ #SmiHandlerProfileLib|MdeModulePkg/Library/SmmSmiHandlerProfileLib/SmmSmiHandlerProfileLib.inf
+ SmiHandlerProfileLib|MdePkg/Library/SmiHandlerProfileLibNull/SmiHandlerProfileLibNull.inf
+ }
+ $(PLATFORM_SI_PACKAGE)/Pch/PchInit/Smm/PchInitSmm.inf
+
+#
+# SystemAgent
+#
+
+ $(PLATFORM_SI_PACKAGE)/SystemAgent/SaInit/Dxe/SaInitDxe.inf
+
+ $(PLATFORM_SI_PACKAGE)/SystemAgent/SaInit/Smm/SaLateInitSmm.inf {
+ <LibraryClasses>
+ S3BootScriptLib|MdePkg/Library/BaseS3BootScriptLibNull/BaseS3BootScriptLibNull.inf
+ }
+
+!if gSiPkgTokenSpaceGuid.PcdAcpiEnable == TRUE
+ $(PLATFORM_SI_PACKAGE)/SystemAgent/AcpiTables/SaSsdt/SaSsdt.inf
+ $(PLATFORM_SI_PACKAGE)/IpBlock/Graphics/AcpiTables/IgfxSsdt.inf
+!endif
+
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/SiPkgDxeLib.dsc b/Silicon/Intel/TigerlakeSiliconPkg/SiPkgDxeLib.dsc
new file mode 100644
index 0000000000..210fb37332
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/SiPkgDxeLib.dsc
@@ -0,0 +1,40 @@
+## @file
+# Component description file for the TigerLake silicon package DXE libraries.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+#
+# Silicon Init Dxe Library
+#
+
+#
+# FRUs
+#
+!include $(PLATFORM_SI_PACKAGE)/Fru/TglCpu/DxeLib.dsc
+!include $(PLATFORM_SI_PACKAGE)/Fru/TglPch/DxeLib.dsc
+
+#
+# Common
+#
+SiConfigBlockLib|$(PLATFORM_SI_PACKAGE)/Library/BaseSiConfigBlockLib/BaseSiConfigBlockLib.inf
+
+#
+# Pch
+#
+DxePchPolicyLib|$(PLATFORM_SI_PACKAGE)/Pch/Library/DxePchPolicyLib/DxePchPolicyLib.inf
+SmmPchPrivateLib|$(PLATFORM_SI_PACKAGE)/Pch/LibraryPrivate/SmmPchPrivateLib/SmmPchPrivateLib.inf
+
+#
+# SystemAgent
+#
+DxeSaPolicyLib|$(PLATFORM_SI_PACKAGE)/SystemAgent/Library/DxeSaPolicyLib/DxeSaPolicyLib.inf
+DxeVtdPolicyLib|$(PLATFORM_SI_PACKAGE)/IpBlock/Vtd/LibraryPrivate/DxeVtdPolicyLib/DxeVtdPolicyLib.inf
+
+#
+# CPU PCIe IpBlock
+#
+
+DxeCpuPcieRpLib|$(PLATFORM_SI_PACKAGE)/IpBlock/CpuPcieRp/LibraryPrivate/DxeCpuPcieRpLib/DxeCpuPcieRpLib.inf
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/SiPkgPei.dsc b/Silicon/Intel/TigerlakeSiliconPkg/SiPkgPei.dsc
new file mode 100644
index 0000000000..15fc5685a5
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/SiPkgPei.dsc
@@ -0,0 +1,20 @@
+## @file
+# Component description file for the TigerLake silicon package PEI drivers.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+#
+# Common
+#
+
+#
+# SystemAgent
+#
+
+#
+# Cpu
+#
+
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/SiPkgPeiLib.dsc b/Silicon/Intel/TigerlakeSiliconPkg/SiPkgPeiLib.dsc
new file mode 100644
index 0000000000..6f90ff02bb
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/SiPkgPeiLib.dsc
@@ -0,0 +1,20 @@
+## @file
+# Component description file for the TigerLake silicon package PEI libraries.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+#
+# Silicon Init Pei Library
+#
+
+#
+# FRUs
+#
+!include $(PLATFORM_SI_PACKAGE)/Fru/TglCpu/PeiLib.dsc
+
+!include $(PLATFORM_SI_PACKAGE)/Fru/TglPch/PeiLib.dsc
+
+ SiConfigBlockLib|$(PLATFORM_SI_PACKAGE)/Library/BaseSiConfigBlockLib/BaseSiConfigBlockLib.inf
diff --git a/Silicon/Intel/TigerlakeSiliconPkg/TigerlakeSiliconPkg.dsc b/Silicon/Intel/TigerlakeSiliconPkg/TigerlakeSiliconPkg.dsc
new file mode 100644
index 0000000000..73a2594887
--- /dev/null
+++ b/Silicon/Intel/TigerlakeSiliconPkg/TigerlakeSiliconPkg.dsc
@@ -0,0 +1,229 @@
+## @file
+# Component description file for the TigerLake silicon package DSC file.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+[Packages]
+MdePkg/MdePkg.dec
+UefiCpuPkg/UefiCpuPkg.dec
+TigerlakeSiliconPkg/SiPkg.dec
+
+[PcdsFixedAtBuild]
+gSiPkgTokenSpaceGuid.PcdSmmVariableEnable |TRUE
+gSiPkgTokenSpaceGuid.PcdAtaEnable |FALSE
+
+gSiPkgTokenSpaceGuid.PcdAcpiEnable |TRUE
+gSiPkgTokenSpaceGuid.PcdSourceDebugEnable |FALSE
+gSiPkgTokenSpaceGuid.PcdPpmEnable |TRUE
+gSiPkgTokenSpaceGuid.PcdPttEnable |FALSE
+gSiPkgTokenSpaceGuid.PcdJhiEnable |FALSE
+gSiPkgTokenSpaceGuid.PcdSmbiosEnable |TRUE
+gSiPkgTokenSpaceGuid.PcdS3Enable |TRUE
+gSiPkgTokenSpaceGuid.PcdOverclockEnable |FALSE
+gSiPkgTokenSpaceGuid.PcdCpuPowerOnConfigEnable |FALSE
+gSiPkgTokenSpaceGuid.PcdBdatEnable |TRUE
+gSiPkgTokenSpaceGuid.PcdIgdEnable |TRUE
+gSiPkgTokenSpaceGuid.PcdPegEnable |TRUE
+gSiPkgTokenSpaceGuid.PcdSaDmiEnable |TRUE
+gSiPkgTokenSpaceGuid.PcdVtdEnable |TRUE
+gSiPkgTokenSpaceGuid.PcdBiosGuardEnable |FALSE #BiosGuardModule.bin
+gSiPkgTokenSpaceGuid.PcdOptimizeCompilerEnable |TRUE
+gSiPkgTokenSpaceGuid.PcdPeiDisplayEnable |TRUE
+gSiPkgTokenSpaceGuid.PcdSiCatalogDebugEnable |FALSE
+gSiPkgTokenSpaceGuid.PcdMrcTraceMessageSupported |TRUE
+gSiPkgTokenSpaceGuid.PcdOcWdtEnable |TRUE
+gSiPkgTokenSpaceGuid.PcdSerialIoUartEnable |TRUE
+
+gSiPkgTokenSpaceGuid.PcdThcEnable |TRUE
+gSiPkgTokenSpaceGuid.PcdPpamEnable |TRUE
+gSiPkgTokenSpaceGuid.PcdEmbeddedEnable |0x0
+gSiPkgTokenSpaceGuid.PcdCpuPcieEnable |TRUE
+gSiPkgTokenSpaceGuid.PcdHybridStorageSupport |TRUE
+
+!if gSiPkgTokenSpaceGuid.PcdPpamEnable == TRUE
+#
+# PCD for State Save Support on DGR
+# TRUE - SMM State Save region access is protected
+# FALSE - SMM can have Read/Write access to SMM State Save region
+#
+gSiPkgTokenSpaceGuid.PcdSpsStateSaveEnable |FALSE
+#
+# PCD to enable SPA Support on DGR
+# Note: This PCD is mainly used for Debugging purpose. Not recommended to set for End Product.
+#
+gSiPkgTokenSpaceGuid.PcdSpaEnable |FALSE
+!endif
+
+[PcdsFixedAtBuild.common]
+gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress |0xC0000000
+gSiPkgTokenSpaceGuid.PcdSiPciExpressBaseAddress |gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
+gSiPkgTokenSpaceGuid.PcdTemporaryPciExpressRegionLength |0x10000000
+
+[PcdsDynamicDefault.common]
+gSiPkgTokenSpaceGuid.PcdPciExpressRegionLength |0x10000000
+## Specifies the AP wait loop state during POST phase.
+# The value is defined as below.
+# 1: Place AP in the Hlt-Loop state.
+# 2: Place AP in the Mwait-Loop state.
+# 3: Place AP in the Run-Loop state.
+# @Prompt The AP wait loop state.
+gUefiCpuPkgTokenSpaceGuid.PcdCpuApLoopMode|2
+## Specifies the AP target C-state for Mwait during POST phase.
+# The default value 0 means C1 state.
+# The value is defined as below.<BR><BR>
+# @Prompt The specified AP target C-state for Mwait.
+gUefiCpuPkgTokenSpaceGuid.PcdCpuApTargetCstate|0
+
+[Defines]
+ PLATFORM_NAME = TigerlakeSiliconPkg
+ PLATFORM_GUID = CCD38CA7-61D3-4185-9CDA-A9FDF209CB31
+ PLATFORM_VERSION = 0.4
+ DSC_SPECIFICATION = 0x00010005
+ OUTPUT_DIRECTORY = Build/TigerlakeSiliconPkg
+ SUPPORTED_ARCHITECTURES = IA32|X64
+ BUILD_TARGETS = DEBUG|RELEASE
+ SKUID_IDENTIFIER = DEFAULT
+
+ DEFINE PLATFORM_SI_PACKAGE = TigerlakeSiliconPkg
+ #
+ # Definition for Build Flag
+ #
+ !include $(PLATFORM_SI_PACKAGE)/SiPkgBuildOption.dsc
+
+[LibraryClasses.common]
+ #
+ # Entry point
+ #
+ PeiCoreEntryPoint|MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.inf
+ PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf
+ DxeCoreEntryPoint|MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf
+ UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf
+ UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf
+ PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf
+
+ #
+ # Basic
+ #
+ BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
+ BaseMemoryLib|MdePkg/Library/BaseMemoryLibRepStr/BaseMemoryLibRepStr.inf
+ PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
+ CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf
+ IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf
+ PciSegmentLib|$(PLATFORM_SI_PACKAGE)/Library/BasePciSegmentMultiSegLibPci/BasePciSegmentMultiSegLibPci.inf
+ PciLib|MdePkg/Library/BasePciLibPciExpress/BasePciLibPciExpress.inf
+ PciCf8Lib|MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf
+ CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf
+ PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
+ PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
+ PciExpressLib|MdePkg/Library/BasePciExpressLib/BasePciExpressLib.inf
+ PostCodeLib|MdePkg/Library/BasePostCodeLibPort80/BasePostCodeLibPort80.inf
+
+ #
+ # UEFI & PI
+ #
+ UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf
+ UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf
+ UefiRuntimeLib|MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf
+ UefiLib|MdePkg/Library/UefiLib/UefiLib.inf
+ DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
+ PeiServicesTablePointerLib|MdePkg/Library/PeiServicesTablePointerLibIdt/PeiServicesTablePointerLibIdt.inf
+ PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf
+ DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf
+ DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf
+
+ S3BootScriptLib|MdePkg/Library/BaseS3BootScriptLibNull/BaseS3BootScriptLibNull.inf
+ S3IoLib|MdePkg/Library/BaseS3IoLib/BaseS3IoLib.inf
+ S3PciLib|MdePkg/Library/BaseS3PciLib/BaseS3PciLib.inf
+
+ UefiUsbLib|MdePkg/Library/UefiUsbLib/UefiUsbLib.inf
+ UefiScsiLib|MdePkg/Library/UefiScsiLib/UefiScsiLib.inf
+ SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
+
+ DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf
+
+ #
+ # Misc
+ #
+ DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
+ PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf
+ PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
+ TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf
+ ReportStatusCodeLib|MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf
+ MtrrLib|UefiCpuPkg/Library/MtrrLib/MtrrLib.inf
+ RngLib|MdePkg/Library/BaseRngLib/BaseRngLib.inf
+
+#####################################################################################################
+
+#
+# Silicon Init Common Library
+#
+!include $(PLATFORM_SI_PACKAGE)/SiPkgCommonLib.dsc
+ConfigBlockLib|IntelSiliconPkg/Library/BaseConfigBlockLib/BaseConfigBlockLib.inf
+
+[LibraryClasses.IA32]
+#
+# PEI phase common
+#
+ PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
+ HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf
+ MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf
+ ExtractGuidedSectionLib|MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.inf
+ PeiGetVtdPmrAlignmentLib|IntelSiliconPkg/Library/PeiGetVtdPmrAlignmentLib/PeiGetVtdPmrAlignmentLib.inf
+
+#####################################################################################################################################
+
+#
+# Silicon Init Pei Library
+#
+!include $(PLATFORM_SI_PACKAGE)/SiPkgPeiLib.dsc
+
+[LibraryClasses.IA32.SEC]
+ GpioHelpersLib|$(PLATFORM_SI_PACKAGE)/IpBlock/Gpio/LibraryPrivate/BaseGpioHelpersLibNull/BaseGpioHelpersLibNull.inf
+
+[LibraryClasses.X64]
+ #
+ # DXE phase common
+ #
+ HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
+ PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+ MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
+ ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf
+
+#
+# Hsti
+#
+ HstiLib|MdePkg/Library/DxeHstiLib/DxeHstiLib.inf
+
+###################################################################################################
+#
+# Silicon Init Dxe Library
+#
+!include $(PLATFORM_SI_PACKAGE)/SiPkgDxeLib.dsc
+
+[LibraryClasses.X64.PEIM]
+
+[LibraryClasses.X64.DXE_CORE]
+ HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf
+ PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
+
+[LibraryClasses.X64.DXE_SMM_DRIVER]
+ SmmServicesTableLib|MdePkg/Library/SmmServicesTableLib/SmmServicesTableLib.inf
+ MemoryAllocationLib|MdePkg/Library/SmmMemoryAllocationLib/SmmMemoryAllocationLib.inf
+ SmmIoLib|MdePkg/Library/SmmIoLib/SmmIoLib.inf
+ SmmMemLib|MdePkg/Library/SmmMemLib/SmmMemLib.inf
+
+[LibraryClasses.X64.SMM_CORE]
+
+[LibraryClasses.X64.UEFI_DRIVER]
+ PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
+
+[LibraryClasses.X64.UEFI_APPLICATION]
+ PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+
+[Components.IA32]
+!include $(PLATFORM_SI_PACKAGE)/SiPkgPei.dsc
+
+[Components.X64]
+!include $(PLATFORM_SI_PACKAGE)/SiPkgDxe.dsc
--
2.24.0.windows.2
^ permalink raw reply related [flat|nested] 42+ messages in thread
* [Patch V3 40/40] Maintainers.txt: Add TigerlakeSiliconPkg maintainers
2021-02-05 7:40 [Patch V3 01/40] TigerlakeSiliconPkg: Add package and Include/ConfigBlock headers Heng Luo
` (37 preceding siblings ...)
2021-02-05 7:40 ` [Patch V3 39/40] TigerlakeSiliconPkg: Add package " Heng Luo
@ 2021-02-05 7:40 ` Heng Luo
2021-02-05 18:36 ` Nate DeSimone
38 siblings, 1 reply; 42+ messages in thread
From: Heng Luo @ 2021-02-05 7:40 UTC (permalink / raw)
To: devel; +Cc: Sai Chaganty, Nate DeSimone
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3171
Cc: Sai Chaganty <rangasai.v.chaganty@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Signed-off-by: Heng Luo <heng.luo@intel.com>
---
Maintainers.txt | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/Maintainers.txt b/Maintainers.txt
index 56e16fc48c..34f0b58581 100644
--- a/Maintainers.txt
+++ b/Maintainers.txt
@@ -242,6 +242,12 @@ F: Silicon/Intel/KabylakeSiliconPkg/
M: Chasel Chiu <chasel.chiu@intel.com>
M: Sai Chaganty <rangasai.v.chaganty@intel.com>
+Silicon/Intel/TigerlakeSiliconPkg
+F: Silicon/Intel/TigerlakeSiliconPkg/
+M: Sai Chaganty <rangasai.v.chaganty@intel.com>
+M: Nate DeSimone <nathaniel.l.desimone@intel.com>
+R: Heng Luo <heng.luo@intel.com>
+
Silicon/Intel/SimicsX58SktPkg
F: Silicon/Intel/SimicsX58SktPkg/
M: Agyeman Prince <prince.agyeman@intel.com>
--
2.24.0.windows.2
^ permalink raw reply related [flat|nested] 42+ messages in thread
* Re: [Patch V3 40/40] Maintainers.txt: Add TigerlakeSiliconPkg maintainers
2021-02-05 7:40 ` [Patch V3 40/40] Maintainers.txt: Add TigerlakeSiliconPkg maintainers Heng Luo
@ 2021-02-05 18:36 ` Nate DeSimone
2021-02-05 18:57 ` Chaganty, Rangasai V
0 siblings, 1 reply; 42+ messages in thread
From: Nate DeSimone @ 2021-02-05 18:36 UTC (permalink / raw)
To: Luo, Heng, devel@edk2.groups.io; +Cc: Chaganty, Rangasai V
The series has been pushed as d55602c~..ee33d4f
Thanks Again Heng!
> -----Original Message-----
> From: Luo, Heng <heng.luo@intel.com>
> Sent: Thursday, February 4, 2021 11:41 PM
> To: devel@edk2.groups.io
> Cc: Chaganty, Rangasai V <rangasai.v.chaganty@intel.com>; Desimone,
> Nathaniel L <nathaniel.l.desimone@intel.com>
> Subject: [Patch V3 40/40] Maintainers.txt: Add TigerlakeSiliconPkg
> maintainers
>
> REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3171
>
> Cc: Sai Chaganty <rangasai.v.chaganty@intel.com>
> Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
> Signed-off-by: Heng Luo <heng.luo@intel.com>
> ---
> Maintainers.txt | 6 ++++++
> 1 file changed, 6 insertions(+)
>
> diff --git a/Maintainers.txt b/Maintainers.txt index 56e16fc48c..34f0b58581
> 100644
> --- a/Maintainers.txt
> +++ b/Maintainers.txt
> @@ -242,6 +242,12 @@ F: Silicon/Intel/KabylakeSiliconPkg/
> M: Chasel Chiu <chasel.chiu@intel.com> M: Sai Chaganty
> <rangasai.v.chaganty@intel.com> +Silicon/Intel/TigerlakeSiliconPkg+F:
> Silicon/Intel/TigerlakeSiliconPkg/+M: Sai Chaganty
> <rangasai.v.chaganty@intel.com>+M: Nate DeSimone
> <nathaniel.l.desimone@intel.com>+R: Heng Luo <heng.luo@intel.com>+
> Silicon/Intel/SimicsX58SktPkg F: Silicon/Intel/SimicsX58SktPkg/ M: Agyeman
> Prince <prince.agyeman@intel.com>--
> 2.24.0.windows.2
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [Patch V3 40/40] Maintainers.txt: Add TigerlakeSiliconPkg maintainers
2021-02-05 18:36 ` Nate DeSimone
@ 2021-02-05 18:57 ` Chaganty, Rangasai V
0 siblings, 0 replies; 42+ messages in thread
From: Chaganty, Rangasai V @ 2021-02-05 18:57 UTC (permalink / raw)
To: Desimone, Nathaniel L, Luo, Heng, devel@edk2.groups.io
Thanks Heng for all the hard work! And thank you Nate for pushing the series.
-----Original Message-----
From: Desimone, Nathaniel L <nathaniel.l.desimone@intel.com>
Sent: Friday, February 05, 2021 10:37 AM
To: Luo, Heng <heng.luo@intel.com>; devel@edk2.groups.io
Cc: Chaganty, Rangasai V <rangasai.v.chaganty@intel.com>
Subject: RE: [Patch V3 40/40] Maintainers.txt: Add TigerlakeSiliconPkg maintainers
The series has been pushed as d55602c~..ee33d4f
Thanks Again Heng!
> -----Original Message-----
> From: Luo, Heng <heng.luo@intel.com>
> Sent: Thursday, February 4, 2021 11:41 PM
> To: devel@edk2.groups.io
> Cc: Chaganty, Rangasai V <rangasai.v.chaganty@intel.com>; Desimone,
> Nathaniel L <nathaniel.l.desimone@intel.com>
> Subject: [Patch V3 40/40] Maintainers.txt: Add TigerlakeSiliconPkg
> maintainers
>
> REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3171
>
> Cc: Sai Chaganty <rangasai.v.chaganty@intel.com>
> Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
> Signed-off-by: Heng Luo <heng.luo@intel.com>
> ---
> Maintainers.txt | 6 ++++++
> 1 file changed, 6 insertions(+)
>
> diff --git a/Maintainers.txt b/Maintainers.txt index
> 56e16fc48c..34f0b58581
> 100644
> --- a/Maintainers.txt
> +++ b/Maintainers.txt
> @@ -242,6 +242,12 @@ F: Silicon/Intel/KabylakeSiliconPkg/
> M: Chasel Chiu <chasel.chiu@intel.com> M: Sai Chaganty
> <rangasai.v.chaganty@intel.com> +Silicon/Intel/TigerlakeSiliconPkg+F:
> Silicon/Intel/TigerlakeSiliconPkg/+M: Sai Chaganty
> <rangasai.v.chaganty@intel.com>+M: Nate DeSimone
> <nathaniel.l.desimone@intel.com>+R: Heng Luo <heng.luo@intel.com>+
> Silicon/Intel/SimicsX58SktPkg F: Silicon/Intel/SimicsX58SktPkg/ M:
> Agyeman Prince <prince.agyeman@intel.com>--
> 2.24.0.windows.2
^ permalink raw reply [flat|nested] 42+ messages in thread