[edk2-devel] [PATCH 17/40] TigerlakeSiliconPkg/IpBlock: Add Gpio component

Heng Luo heng.luo at intel.com
Mon Feb 1 01:36:34 UTC 2021


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 at intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone at intel.com>
Signed-off-by: Heng Luo <heng.luo at 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
+
+ at 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



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#70967): https://edk2.groups.io/g/devel/message/70967
Mute This Topic: https://groups.io/mt/80274130/1813853
Group Owner: devel+owner at edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [edk2-devel-archive at redhat.com]
-=-=-=-=-=-=-=-=-=-=-=-






More information about the edk2-devel-archive mailing list