From: "Heng Luo" <heng.luo@intel.com>
To: devel@edk2.groups.io
Cc: Sai Chaganty <rangasai.v.chaganty@intel.com>,
Nate DeSimone <nathaniel.l.desimone@intel.com>
Subject: [Patch V3 17/40] TigerlakeSiliconPkg/IpBlock: Add Gpio component
Date: Fri, 5 Feb 2021 15:40:22 +0800 [thread overview]
Message-ID: <20210205074045.3916-17-heng.luo@intel.com> (raw)
In-Reply-To: <20210205074045.3916-1-heng.luo@intel.com>
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
next prev parent reply other threads:[~2021-02-05 7:41 UTC|newest]
Thread overview: 42+ messages / expand[flat|nested] mbox.gz Atom feed top
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 ` [Patch V3 04/40] TigerlakeSiliconPkg/Cpu: Add Include headers Heng Luo
2021-02-05 7:40 ` [Patch V3 05/40] TigerlakeSiliconPkg/Pch: Add include headers Heng Luo
2021-02-05 7:40 ` [Patch V3 06/40] TigerlakeSiliconPkg/Pch: Add IncludePrivate headers Heng Luo
2021-02-05 7:40 ` [Patch V3 07/40] TigerlakeSiliconPkg/SystemAgent: Add include headers Heng Luo
2021-02-05 7:40 ` [Patch V3 08/40] TigerlakeSiliconPkg/SystemAgent: Add IncludePrivate headers Heng Luo
2021-02-05 7:40 ` [Patch V3 09/40] TigerlakeSiliconPkg/Fru: Add TglCpu/Include headers Heng Luo
2021-02-05 7:40 ` [Patch V3 10/40] TigerlakeSiliconPkg/Fru: Add TglCpu/IncludePrivate headers Heng Luo
2021-02-05 7:40 ` [Patch V3 11/40] TigerlakeSiliconPkg/Fru: Add TglPch/Include headers Heng Luo
2021-02-05 7:40 ` [Patch V3 12/40] TigerlakeSiliconPkg/Fru: Add TglPch/IncludePrivate headers Heng Luo
2021-02-05 7:40 ` [Patch V3 13/40] TigerlakeSiliconPkg/IpBlock: Add Cnvi component Heng Luo
2021-02-05 7:40 ` [Patch V3 14/40] TigerlakeSiliconPkg/IpBlock: Add CpuPcieRp component Heng Luo
2021-02-05 7:40 ` [Patch V3 15/40] TigerlakeSiliconPkg/IpBlock: Add Espi component Heng Luo
2021-02-05 7:40 ` [Patch V3 16/40] TigerlakeSiliconPkg/IpBlock: Add Gbe component Heng Luo
2021-02-05 7:40 ` Heng Luo [this message]
2021-02-05 7:40 ` [Patch V3 18/40] TigerlakeSiliconPkg/IpBlock: Add Graphics component Heng Luo
2021-02-05 7:40 ` [Patch V3 19/40] TigerlakeSiliconPkg/IpBlock: Add Hda component Heng Luo
2021-02-05 7:40 ` [Patch V3 20/40] TigerlakeSiliconPkg/IpBlock: Add HostBridge component Heng Luo
2021-02-05 7:40 ` [Patch V3 21/40] TigerlakeSiliconPkg/IpBlock: Add P2sb component Heng Luo
2021-02-05 7:40 ` [Patch V3 22/40] TigerlakeSiliconPkg/IpBlock: Add PchDmi component Heng Luo
2021-02-05 7:40 ` [Patch V3 23/40] TigerlakeSiliconPkg/IpBlock: Add PcieRp component Heng Luo
2021-02-05 7:40 ` [Patch V3 24/40] TigerlakeSiliconPkg/IpBlock: Add Pmc component Heng Luo
2021-02-05 7:40 ` [Patch V3 25/40] TigerlakeSiliconPkg/IpBlock: Add Psf component Heng Luo
2021-02-05 7:40 ` [Patch V3 26/40] TigerlakeSiliconPkg/IpBlock: Add Sata component Heng Luo
2021-02-05 7:40 ` [Patch V3 27/40] TigerlakeSiliconPkg/IpBlock: Add SerialIo component Heng Luo
2021-02-05 7:40 ` [Patch V3 28/40] TigerlakeSiliconPkg/IpBlock: Add Smbus component Heng Luo
2021-02-05 7:40 ` [Patch V3 29/40] TigerlakeSiliconPkg/IpBlock: Add Spi component Heng Luo
2021-02-05 7:40 ` [Patch V3 30/40] TigerlakeSiliconPkg/IpBlock: Add Vtd component Heng Luo
2021-02-05 7:40 ` [Patch V3 31/40] TigerlakeSiliconPkg/Library: Add package common library instances Heng Luo
2021-02-05 7:40 ` [Patch V3 32/40] TigerlakeSiliconPkg/Pch: Add Pch " Heng Luo
2021-02-05 7:40 ` [Patch V3 33/40] TigerlakeSiliconPkg/Pch: Add Pch private " Heng Luo
2021-02-05 7:40 ` [Patch V3 34/40] TigerlakeSiliconPkg/SystemAgent: Add Acpi Tables and " Heng Luo
2021-02-05 7:40 ` [Patch V3 35/40] TigerlakeSiliconPkg/Fru/TglCpu: Add CpuPcieRp and Vtd " Heng Luo
2021-02-05 7:40 ` [Patch V3 36/40] TigerlakeSiliconPkg/Pch: Add Pch modules Heng Luo
2021-02-05 7:40 ` [Patch V3 37/40] TigerlakeSiliconPkg/SystemAgent: Add SystemAgent modules Heng Luo
2021-02-05 7:40 ` [Patch V3 38/40] TigerlakeSiliconPkg/Fru: Add Fru DSC files 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
2021-02-05 18:36 ` Nate DeSimone
2021-02-05 18:57 ` Chaganty, Rangasai V
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20210205074045.3916-17-heng.luo@intel.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox