From: "Chuang, Rosen" <rosen.chuang@intel.com>
To: "Chaganty, Rangasai V" <rangasai.v.chaganty@intel.com>,
"Kasbekar, Saloni" <saloni.kasbekar@intel.com>,
"devel@edk2.groups.io" <devel@edk2.groups.io>
Cc: "Desimone, Nathaniel L" <nathaniel.l.desimone@intel.com>
Subject: Re: [edk2-devel] [PATCH 01/10] AlderlakeSiliconPkg/IpBlock: Add CpuPcieRp, Espi, Gpio components
Date: Fri, 15 Sep 2023 02:59:25 +0000 [thread overview]
Message-ID: <DM8PR11MB5624071E539CF09008F0FFCC92F6A@DM8PR11MB5624.namprd11.prod.outlook.com> (raw)
In-Reply-To: <MW4PR11MB5776117EBE79C2341046C528B6F7A@MW4PR11MB5776.namprd11.prod.outlook.com>
Reviewed-by: Rosen Chuang <rosen.chuang@intel.com>
-----Original Message-----
From: Chaganty, Rangasai V <rangasai.v.chaganty@intel.com>
Sent: Friday, September 15, 2023 12:02 AM
To: Kasbekar, Saloni <saloni.kasbekar@intel.com>; devel@edk2.groups.io
Cc: Desimone, Nathaniel L <nathaniel.l.desimone@intel.com>; Chuang, Rosen <rosen.chuang@intel.com>
Subject: RE: [PATCH 01/10] AlderlakeSiliconPkg/IpBlock: Add CpuPcieRp, Espi, Gpio components
Reviewed-by: Sai Chaganty <rangasai.v.chaganty@intel.com>
-----Original Message-----
From: Kasbekar, Saloni <saloni.kasbekar@intel.com>
Sent: Wednesday, September 13, 2023 3:14 PM
To: devel@edk2.groups.io
Cc: Kasbekar, Saloni <saloni.kasbekar@intel.com>; Chaganty, Rangasai V <rangasai.v.chaganty@intel.com>; Desimone, Nathaniel L <nathaniel.l.desimone@intel.com>; Chuang, Rosen <rosen.chuang@intel.com>
Subject: [PATCH 01/10] AlderlakeSiliconPkg/IpBlock: Add CpuPcieRp, Espi, Gpio components
Adds the following modules:
- IpBlock/CpuPcieRp/Include
- IpBlock/Espi/Library
- IpBlock/Gpio/IncludePrivate
- IpBlock/Gpio/Library
- IpBlock/Gpio/LibraryPrivate
Cc: Sai Chaganty <rangasai.v.chaganty@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Cc: Rosen Chuang <rosen.chuang@intel.com>
Signed-off-by: Saloni Kasbekar <saloni.kasbekar@intel.com>
---
.../IpBlock/CpuPcieRp/Include/CpuPcieInfo.h | 25 +
.../Espi/Library/PeiDxeSmmEspiLib/EspiLib.c | 58 ++
.../PeiDxeSmmEspiLib/PeiDxeSmmEspiLib.inf | 38 ++
.../IncludePrivate/Library/GpioHelpersLib.h | 50 ++
.../IncludePrivate/Library/GpioNativePads.h | 245 ++++++++
.../IncludePrivate/Library/GpioPrivateLib.h | 350 +++++++++++
.../Gpio/Library/PeiDxeSmmGpioLib/GpioInit.c | 546 ++++++++++++++++++
.../Gpio/Library/PeiDxeSmmGpioLib/GpioLib.c | 522 +++++++++++++++++
.../Library/PeiDxeSmmGpioLib/GpioLibrary.h | 29 +
.../Library/PeiDxeSmmGpioLib/GpioNativeLib.c | 177 ++++++
.../PeiDxeSmmGpioLib/PeiDxeSmmGpioLib.inf | 44 ++
.../BaseGpioHelpersLibNull.c | 51 ++
.../BaseGpioHelpersLibNull.inf | 25 +
.../GpioNativePrivateLibInternal.h | 48 ++
.../PeiDxeSmmGpioPrivateLib/GpioPrivateLib.c | 267 +++++++++
.../GpioPrivateLibPch.c | 172 ++++++
.../GpioPrivateLibVer2.c | 81 +++
.../PeiDxeSmmGpioPrivateLibVer2.inf | 40 ++
.../PeiGpioHelpersLib/PeiGpioHelpersLib.c | 218 +++++++
.../PeiGpioHelpersLib/PeiGpioHelpersLib.inf | 46 ++
20 files changed, 3032 insertions(+)
create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/IpBlock/CpuPcieRp/Include/CpuPcieInfo.h
create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Espi/Library/PeiDxeSmmEspiLib/EspiLib.c
create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Espi/Library/PeiDxeSmmEspiLib/PeiDxeSmmEspiLib.inf
create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Gpio/IncludePrivate/Library/GpioHelpersLib.h
create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Gpio/IncludePrivate/Library/GpioNativePads.h
create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Gpio/IncludePrivate/Library/GpioPrivateLib.h
create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Gpio/Library/PeiDxeSmmGpioLib/GpioInit.c
create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Gpio/Library/PeiDxeSmmGpioLib/GpioLib.c
create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Gpio/Library/PeiDxeSmmGpioLib/GpioLibrary.h
create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Gpio/Library/PeiDxeSmmGpioLib/GpioNativeLib.c
create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Gpio/Library/PeiDxeSmmGpioLib/PeiDxeSmmGpioLib.inf
create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/BaseGpioHelpersLibNull/BaseGpioHelpersLibNull.c
create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/BaseGpioHelpersLibNull/BaseGpioHelpersLibNull.inf
create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/PeiDxeSmmGpioPrivateLib/GpioNativePrivateLibInternal.h
create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/PeiDxeSmmGpioPrivateLib/GpioPrivateLib.c
create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/PeiDxeSmmGpioPrivateLib/GpioPrivateLibPch.c
create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/PeiDxeSmmGpioPrivateLib/GpioPrivateLibVer2.c
create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/PeiDxeSmmGpioPrivateLib/PeiDxeSmmGpioPrivateLibVer2.inf
create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/PeiGpioHelpersLib/PeiGpioHelpersLib.c
create mode 100644 Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/PeiGpioHelpersLib/PeiGpioHelpersLib.inf
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/CpuPcieRp/Include/CpuPcieInfo.h b/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/CpuPcieRp/Include/CpuPcieInfo.h
new file mode 100644
index 0000000000..a6f8b16d10
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/CpuPcieRp/Include/CpuPcieInfo.h
@@ -0,0 +1,25 @@
+/** @file
+ This file contains definitions of PCIe controller information
+
+ Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _CPU_PCIE_INFO_H_
+#define _CPU_PCIE_INFO_H_
+
+#define PCIE_HWEQ_COEFFS_MAX 5
+
+
+//
+// SA PCI Express* Port configuration
+//
+
+#define CPU_PCIE_MAX_ROOT_PORTS 4
+#define CPU_PCIE_MAX_CONTROLLERS 3
+
+#define SA_PEG_MAX_FUN 0x04
+#define SA_PEG_MAX_LANE 0x14
+
+
+
+#endif
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Espi/Library/PeiDxeSmmEspiLib/EspiLib.c b/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Espi/Library/PeiDxeSmmEspiLib/EspiLib.c
new file mode 100644
index 0000000000..2e4d1375ca
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Espi/Library/PeiDxeSmmEspiLib/EspiLib.c
@@ -0,0 +1,58 @@
+/** @file
+ This file contains routines for eSPI
+
+ Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/EspiLib.h>
+#include <Library/PchPcrLib.h>
+#include <Library/PchInfoLib.h>
+#include <Library/TimerLib.h>
+#include <PchLimits.h>
+#include <Register/PchPcrRegs.h>
+#include <Register/PchRegsLpc.h>
+
+
+/**
+ Checks if second device capability is enabled
+
+ @retval TRUE There's second device
+ @retval FALSE There's no second device
+**/
+BOOLEAN
+IsEspiSecondSlaveSupported (
+ VOID
+ )
+{
+ return ((PchPcrRead32 (PID_ESPISPI, R_ESPI_PCR_SOFTSTRAPS) & B_ESPI_PCR_SOFTSTRAPS_CS1_EN) != 0);
+}
+
+
+/**
+ Is eSPI enabled in strap.
+
+ @retval TRUE Espi is enabled in strap
+ @retval FALSE Espi is disabled in strap
+**/
+BOOLEAN
+IsEspiEnabled (
+ VOID
+ )
+{
+ return (PchPcrRead32 (PID_ESPISPI, R_ESPI_PCR_CFG_VAL) & B_ESPI_PCR_CFG_VAL_ESPI_EN) != 0;
+}
+
+typedef enum {
+ EspiSlaveOperationConfigRead,
+ EspiSlaveOperationConfigWrite,
+ EspiSlaveOperationStatusRead,
+ EspiSlaveOperationInBandReset
+} ESPI_SLAVE_OPERATION;
+
+
+
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Espi/Library/PeiDxeSmmEspiLib/PeiDxeSmmEspiLib.inf b/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Espi/Library/PeiDxeSmmEspiLib/PeiDxeSmmEspiLib.inf
new file mode 100644
index 0000000000..e8db1e4e8d
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Espi/Library/PeiDxeSmmEspiLib/PeiDxeSmmEspiLib.inf
@@ -0,0 +1,38 @@
+## @file
+# Component description file for the PeiDxeSmmPchEspiLib
+#
+# Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+
+[Defines]
+INF_VERSION = 0x00010017
+BASE_NAME = PeiDxeSmmEspiLib
+FILE_GUID = 7F25F990-7989-4413-B414-1EDE557E9389
+VERSION_STRING = 1.0
+MODULE_TYPE = BASE
+LIBRARY_CLASS = EspiLib
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+
+
+[LibraryClasses]
+BaseLib
+IoLib
+DebugLib
+PchPcrLib
+TimerLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+AlderlakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+EspiLib.c
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Gpio/IncludePrivate/Library/GpioHelpersLib.h b/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Gpio/IncludePrivate/Library/GpioHelpersLib.h
new file mode 100644
index 0000000000..cf67c81ed0
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Gpio/IncludePrivate/Library/GpioHelpersLib.h
@@ -0,0 +1,50 @@
+/** @file
+ Header file for GPIO Helpers Lib implementation.
+
+ Copyright (c) 2022, 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 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
+ );
+
+#endif // _GPIO_HELPERS_LIB_H_
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Gpio/IncludePrivate/Library/GpioNativePads.h b/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Gpio/IncludePrivate/Library/GpioNativePads.h
new file mode 100644
index 0000000000..dbd13963fa
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Gpio/IncludePrivate/Library/GpioNativePads.h
@@ -0,0 +1,245 @@
+/** @file
+ Header file for GPIO Native pads support
+
+ Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _GPIO_NATIVE_PADS_H_
+#define _GPIO_NATIVE_PADS_H_
+
+//
+// GpioPad can contain additional information used to provide data on
+// native functions. Please refer to description of GPIO_NATIVE_PAD
+//
+// FFFF CCCC TTTG GGGG TTTT TTTP PPPP PPPP
+//
+// F - 2^4 = 16, native function number
+// C - 2^4 = 16, chipset ID
+// T - 2^10 = 1024 , abstract type representing native mode of a pad (e.g. SERIALIO_UART2_TX)
+// G - 2^5 = 32, group
+// P - 2^9 = 512, pad number
+//
+// F & T contain additional optional settings used for native pads
+//
+#define GPIO_NATIVE_PAD_DEF(GpioNativePad, NativeMode, NativeFunction) \
+ (GpioNativePad | (NativeMode << 28) | ((NativeFunction & 0x7F) << 9) | ((NativeFunction & 0x380) << 14))
+
+#define GPIO_NATIVE_GET_FUNCTION(GpioNativePad) ((((GpioNativePad) & 0xFE00) >> 9) | (((GpioNativePad) & 0xE00000) >> 14))
+#define GPIO_NATIVE_GET_PAD_FN(GpioNativePad) (((GpioNativePad) >> 28) & 0xF)
+#define GPIO_NATIVE_GET_PAD_MODE(GpioNativePad) ((GPIO_NATIVE_GET_PAD_FN(GpioNativePad) << 1) | 1)
+#define GPIO_NATIVE_TO_GPIO_PAD(GpioNativePad) (GpioNativePad & 0xF1F01FF)
+
+//
+// Below defines and macros are used to build abstract type
+// to help encode native pin information in GPIO_PAD
+//
+
+//
+// Macro used to define GPIO native function.
+// <Min,Max> defines range that can be used to encode given native signal.
+// Numbering must be unique and cannot overlap.
+// If there are many instances of similar signal (e.g. per controller) the lower
+// word will store value for a given instance in the form: Min + Instance
+// Upper word (Max) is left untouched and later used for verification
+//
+#define GPIO_NATIVE_FUNCTION_DEF(Min, Max) (((Max) << 16) + (Min))
+#define GPIO_NATIVE_FUNCTION_GET_MAX(NativeFunction) (((NativeFunction) >> 16) & 0xFFFF)
+#define GPIO_NATIVE_FUNCTION_GET_VALUE(NativeFunction) ((NativeFunction) & 0xFFFF)
+
+//
+// Macro GPIO_NATIVE_FUNCTION_GET_SIGNAL is created as synonym to macro GPIO_NATIVE_FUNCTION_GET_MAX
+// GPIO_NATIVE_FUNCTION_GET_SIGNAL used with below defines is more descriptive and easier to read
+// ex.
+// - GPIO_NATIVE_FUNCTION_GET_SIGNAL(GPIO_SERIAL_IO_UART_RX)
+// - GPIO_NATIVE_FUNCTION_GET_SIGNAL(GPIO_ISH_GP)
+// - ...
+//
+#define GPIO_NATIVE_FUNCTION_GET_SIGNAL(NativeFunction) (GPIO_NATIVE_FUNCTION_GET_MAX(NativeFunction))
+
+//
+// GPIO native modes
+// Those defines are internal to this header.
+// GPIO_FUNCTION_<IP>_<signal>(index) defines should be used by other modules instead.
+//
+#define GPIO_SERIAL_IO_UART_RX GPIO_NATIVE_FUNCTION_DEF(1,8)
+#define GPIO_SERIAL_IO_UART_TX GPIO_NATIVE_FUNCTION_DEF(9,16)
+#define GPIO_SERIAL_IO_UART_RTS GPIO_NATIVE_FUNCTION_DEF(17,24)
+#define GPIO_SERIAL_IO_UART_CTS GPIO_NATIVE_FUNCTION_DEF(25,31)
+#define GPIO_SERIAL_IO_SPI_MOSI GPIO_NATIVE_FUNCTION_DEF(32,39)
+#define GPIO_SERIAL_IO_SPI_MISO GPIO_NATIVE_FUNCTION_DEF(40,47)
+#define GPIO_SERIAL_IO_SPI_CLK GPIO_NATIVE_FUNCTION_DEF(48,55)
+#define GPIO_SERIAL_IO_SPI_CS GPIO_NATIVE_FUNCTION_DEF(56,71)
+#define GPIO_ISH_GP GPIO_NATIVE_FUNCTION_DEF(80,143)
+#define GPIO_ISH_UART_RX GPIO_NATIVE_FUNCTION_DEF(144,151)
+#define GPIO_ISH_UART_TX GPIO_NATIVE_FUNCTION_DEF(152,159)
+#define GPIO_ISH_UART_RTS GPIO_NATIVE_FUNCTION_DEF(160,167)
+#define GPIO_ISH_UART_CTS GPIO_NATIVE_FUNCTION_DEF(168,175)
+#define GPIO_ISH_SPI_MOSI GPIO_NATIVE_FUNCTION_DEF(184,191)
+#define GPIO_ISH_SPI_MISO GPIO_NATIVE_FUNCTION_DEF(192,199)
+#define GPIO_ISH_SPI_CLK GPIO_NATIVE_FUNCTION_DEF(200,207)
+#define GPIO_ISH_SPI_CS GPIO_NATIVE_FUNCTION_DEF(208,223)
+#define GPIO_ISH_I2C_SCL GPIO_NATIVE_FUNCTION_DEF(232,239)
+#define GPIO_ISH_I2C_SDA GPIO_NATIVE_FUNCTION_DEF(240,247)
+#define GPIO_THC_SPI_INT GPIO_NATIVE_FUNCTION_DEF(248,251)
+#define GPIO_DMIC_DATA GPIO_NATIVE_FUNCTION_DEF(258,261)
+#define GPIO_DMIC_CLKA GPIO_NATIVE_FUNCTION_DEF(262,265)
+#define GPIO_DMIC_CLKB GPIO_NATIVE_FUNCTION_DEF(266,269)
+#define GPIO_DDSP_HPD0 GPIO_NATIVE_FUNCTION_DEF(270,285)
+#define GPIO_PANEL_AVDD_EN GPIO_NATIVE_FUNCTION_DEF(286,289)
+#define GPIO_PANEL_BKLTEN GPIO_NATIVE_FUNCTION_DEF(290,293)
+#define GPIO_PANEL_BKLTCTL GPIO_NATIVE_FUNCTION_DEF(294,297)
+#define GPIO_PANEL_RESET GPIO_NATIVE_FUNCTION_DEF(298,301)
+#define GPIO_PANEL_AVEE_EN GPIO_NATIVE_FUNCTION_DEF(302,305)
+#define GPIO_PANEL_VIO_EN GPIO_NATIVE_FUNCTION_DEF(306,309)
+#define GPIO_PANEL_HPD GPIO_NATIVE_FUNCTION_DEF(310,313)
+#define GPIO_PANEL_TE_EN GPIO_NATIVE_FUNCTION_DEF(314,317)
+#define GPIO_HDMI_GMBUS_SCL GPIO_NATIVE_FUNCTION_DEF(318,325)
+#define GPIO_HDMI_GMBUS_SDA GPIO_NATIVE_FUNCTION_DEF(326,333)
+#define GPIO_SERIAL_IO_I2C_SCL GPIO_NATIVE_FUNCTION_DEF(338,353)
+#define GPIO_SERIAL_IO_I2C_SDA GPIO_NATIVE_FUNCTION_DEF(354,369)
+#define GPIO_SD_DATA GPIO_NATIVE_FUNCTION_DEF(374,377)
+#define GPIO_EMMC_DATA GPIO_NATIVE_FUNCTION_DEF(384,391)
+#define GPIO_THC_CLK_LOOPBACK GPIO_NATIVE_FUNCTION_DEF(395,396)
+#define GPIO_MIPI_PANEL_RESET GPIO_NATIVE_FUNCTION_DEF(401,404)
+#define GPIO_MIPI_SEC_POW_EN_AVEE GPIO_NATIVE_FUNCTION_DEF(405,408)
+#define GPIO_MIPI_SEC_POW_EN_AVDD GPIO_NATIVE_FUNCTION_DEF(409,412)
+#define GPIO_THC_WOT GPIO_NATIVE_FUNCTION_DEF(413,414)
+#define GPIO_SATA_DEVSLP GPIO_NATIVE_FUNCTION_DEF(415,446)
+#define GPIO_PCIE_CLKREQ GPIO_NATIVE_FUNCTION_DEF(447,478)
+
+//
+// Serial IO UART
+//
+
+#define GPIO_FUNCTION_SERIAL_IO_UART_RX(UartDev) (GPIO_SERIAL_IO_UART_RX + ((UINT32)UartDev))
+#define GPIO_FUNCTION_SERIAL_IO_UART_TX(UartDev) (GPIO_SERIAL_IO_UART_TX + ((UINT32)UartDev))
+#define GPIO_FUNCTION_SERIAL_IO_UART_RTS(UartDev) (GPIO_SERIAL_IO_UART_RTS + ((UINT32)UartDev))
+#define GPIO_FUNCTION_SERIAL_IO_UART_CTS(UartDev) (GPIO_SERIAL_IO_UART_CTS + ((UINT32)UartDev))
+
+//
+// Serial IO SPI
+//
+#define GPIO_SERIAL_IO_SPI_RANGE 8 // Number of SerialIo SPIx controllers supported in GPIO_NATIVE_PAD encoding
+
+#define GPIO_FUNCTION_SERIAL_IO_SPI_MOSI(SpiDev) (GPIO_SERIAL_IO_SPI_MOSI + ((UINT32)SpiDev))
+#define GPIO_FUNCTION_SERIAL_IO_SPI_MISO(SpiDev) (GPIO_SERIAL_IO_SPI_MISO + ((UINT32)SpiDev))
+#define GPIO_FUNCTION_SERIAL_IO_SPI_CLK(SpiDev) (GPIO_SERIAL_IO_SPI_CLK + ((UINT32)SpiDev))
+#define GPIO_FUNCTION_SERIAL_IO_SPI_CS(SpiDev, CsNum) (GPIO_SERIAL_IO_SPI_CS + ((UINT32)SpiDev) + ((UINT32)CsNum) * GPIO_SERIAL_IO_SPI_RANGE)
+
+//
+// Serial IO I2C
+//
+
+#define GPIO_FUNCTION_SERIAL_IO_I2C_SCL(I2cDev) (GPIO_SERIAL_IO_I2C_SCL + ((UINT32)I2cDev))
+#define GPIO_FUNCTION_SERIAL_IO_I2C_SDA(I2cDev) (GPIO_SERIAL_IO_I2C_SDA + ((UINT32)I2cDev))
+
+//
+// ISH GP
+//
+
+#define GPIO_FUNCTION_ISH_GP(GpNum) (GPIO_ISH_GP + ((UINT32)GpNum))
+
+//
+// ISH UART
+//
+
+#define GPIO_FUNCTION_ISH_UART_RX(UartDev) (GPIO_ISH_UART_RX + ((UINT32)UartDev))
+#define GPIO_FUNCTION_ISH_UART_TX(UartDev) (GPIO_ISH_UART_TX + ((UINT32)UartDev))
+#define GPIO_FUNCTION_ISH_UART_RTS(UartDev) (GPIO_ISH_UART_RTS + ((UINT32)UartDev))
+#define GPIO_FUNCTION_ISH_UART_CTS(UartDev) (GPIO_ISH_UART_CTS + ((UINT32)UartDev))
+
+//
+// ISH SPI
+//
+#define GPIO_ISH_SPI_RANGE 8 // Number of ISH SPI controllers supported in GPIO_NATIVE_PAD encoding
+
+#define GPIO_FUNCTION_ISH_SPI_MOSI(SpiDev) (GPIO_ISH_SPI_MOSI + ((UINT32)SpiDev))
+#define GPIO_FUNCTION_ISH_SPI_MISO(SpiDev) (GPIO_ISH_SPI_MISO + ((UINT32)SpiDev))
+#define GPIO_FUNCTION_ISH_SPI_CLK(SpiDev) (GPIO_ISH_SPI_CLK + ((UINT32)SpiDev))
+#define GPIO_FUNCTION_ISH_SPI_CS(SpiDev, CsNum) (GPIO_ISH_SPI_CS + ((UINT32)SpiDev) + ((UINT32)CsNum) * GPIO_ISH_SPI_RANGE)
+
+//
+// ISH I2C
+//
+
+#define GPIO_FUNCTION_ISH_I2C_SCL(I2cDev) (GPIO_ISH_I2C_SCL + ((UINT32)I2cDev))
+#define GPIO_FUNCTION_ISH_I2C_SDA(I2cDev) (GPIO_ISH_I2C_SDA + ((UINT32)I2cDev))
+
+//
+// SD Card
+//
+#define GPIO_FUNCTION_SD_DATA(Index) (GPIO_SD_DATA + ((UINT32)Index))
+
+//
+// EMMC
+//
+#define GPIO_FUNCTION_EMMC_DATA(Index) (GPIO_EMMC_DATA + ((UINT32)Index))
+
+//
+// THC SPI
+//
+
+#define GPIO_FUNCTION_THC_SPI_INT(SpiDev) (GPIO_THC_SPI_INT + ((UINT32)SpiDev))
+#define GPIO_FUNCTION_THC_CLK_LOOPBACK(SpiDev) (GPIO_THC_CLK_LOOPBACK + ((UINT32)SpiDev))
+#define GPIO_FUNCTION_THC_WOT(SpiDev) (GPIO_THC_WOT + ((UINT32)SpiDev))
+
+
+//
+// DMIC
+//
+
+#define GPIO_FUNCTION_DMIC_DATA(DmicDev) (GPIO_DMIC_DATA + ((UINT32)DmicDev))
+#define GPIO_FUNCTION_DMIC_CLKA(DmicDev) (GPIO_DMIC_CLKA + ((UINT32)DmicDev))
+#define GPIO_FUNCTION_DMIC_CLKB(DmicDev) (GPIO_DMIC_CLKB + ((UINT32)DmicDev))
+#define GPIO_FUNCTION_DMIC_CLK(DmicDev) (GPIO_DMIC_CLKA + ((UINT32)DmicDev)) // If there is no split between channel A/B use A range for such Clocks
+
+
+//
+// DDSP HPD
+//
+
+#define GPIO_FUNCTION_DDSP_HPD(HpdIndex) \
+ (HpdIndex > 7) ? GPIO_DDSP_HPD0 + 8 + (HpdIndex) - 'A' : GPIO_DDSP_HPD0 + HpdIndex
+
+//
+// HDMI_GMBUS
+//
+
+#define GPIO_FUNCTION_HDMI_SCL(DdiPort) (GPIO_HDMI_GMBUS_SCL + ((UINT32)DdiPort))
+#define GPIO_FUNCTION_HDMI_SDA(DdiPort) (GPIO_HDMI_GMBUS_SDA + ((UINT32)DdiPort))
+
+//
+// Panel
+//
+
+#define GPIO_FUNCTION_PANEL_AVDD_EN(PanelDev) (GPIO_PANEL_AVDD_EN + ((UINT32)PanelDev))
+#define GPIO_FUNCTION_PANEL_BKLTEN(PanelDev) (GPIO_PANEL_BKLTEN + ((UINT32)PanelDev))
+#define GPIO_FUNCTION_PANEL_BKLTCTL(PanelDev) (GPIO_PANEL_BKLTCTL + ((UINT32)PanelDev))
+#define GPIO_FUNCTION_PANEL_RESET(PanelDev) (GPIO_PANEL_RESET + ((UINT32)PanelDev))
+#define GPIO_FUNCTION_PANEL_AVEE_EN(PanelDev) (GPIO_PANEL_AVEE_EN + ((UINT32)PanelDev))
+#define GPIO_FUNCTION_PANEL_VIO_EN(PanelDev) (GPIO_PANEL_VIO_EN + ((UINT32)PanelDev))
+#define GPIO_FUNCTION_PANEL_HPD(PanelDev) (GPIO_PANEL_HPD + ((UINT32)PanelDev))
+#define GPIO_FUNCTION_PANEL_TE_EN(PanelDev) (GPIO_PANEL_TE_EN + ((UINT32)PanelDev))
+
+//
+// MIPI
+//
+#define GPIO_FUNCTION_MIPI_PANEL_RESET(PanelDev) (GPIO_MIPI_PANEL_RESET + ((UINT32)PanelDev))
+#define GPIO_FUNCTION_MIPI_SEC_POW_EN_AVEE(PanelDev) (GPIO_MIPI_SEC_POW_EN_AVEE + ((UINT32)PanelDev))
+#define GPIO_FUNCTION_MIPI_SEC_POW_EN_AVDD(PanelDev) (GPIO_MIPI_SEC_POW_EN_AVDD + ((UINT32)PanelDev))
+
+
+//
+// SATA DevSlp
+//
+#define GPIO_SATA_DEVSLP_RANGE 32 // Number of SATA DevSlp instances per controller supported in GPIO_NATIVE_PAD encoding
+
+#define GPIO_FUNCTION_SATA_DEVSLP(CsNum, SataDevSlpIndex) (GPIO_SATA_DEVSLP + ((UINT32)SataDevSlpIndex) + ((UINT32)CsNum) * GPIO_SATA_DEVSLP_RANGE)
+
+//
+// SRC CLKREQ
+//
+
+#define GPIO_FUNCTION_PCIE_CLKREQ(ClkReqIndex) (GPIO_PCIE_CLKREQ + ((UINT32)ClkReqIndex))
+
+#endif // _GPIO_NATIVE_PADS_H_
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Gpio/IncludePrivate/Library/GpioPrivateLib.h b/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Gpio/IncludePrivate/Library/GpioPrivateLib.h
new file mode 100644
index 0000000000..a757a4b057
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Gpio/IncludePrivate/Library/GpioPrivateLib.h
@@ -0,0 +1,350 @@
+/** @file
+ Header file for GpioPrivateLib.
+ All function in this library is available for PEI, DXE, and SMM,
+
+ Copyright (c) 2022, 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>
+
+/**
+ 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_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 N_GPIO_ELECTRICAL_CONFIG_TERMINATION_BIT_POS 0
+#define N_GPIO_OTHER_CONFIG_RXRAW_BIT_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}
+
+/**
+ 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
+ );
+
+
+/**
+ 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 calculates Pad Configuration Register DW offset
+
+ @param[in] GpioPad GPIO pad
+ @param[in] DwReg Index of the configuration register
+
+ @retval DW Register offset
+**/
+UINT32
+GpioGetGpioPadCfgAddressFromGpioPad (
+ IN GPIO_PAD GpioPad,
+ IN UINT32 DwReg
+ );
+
+
+/**
+ 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
+ );
+
+/**
+ 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
+ );
+
+/**
+ Gpio Minimum Set
+
+ Set of Gpio Minimum function to use in Pre Mem phase.
+ To optimise execution and reduce memory footprint thse minimum version
+ of 'full' functions are stripped from:
+ - GpioPad PCH validation
+ - GpioPad Group belonging validation
+ - GpioPad Host ownership validation
+ - IoStandbyState configuration
+ The use of below functions has to be careful and with full
+ understanding of all pros and cons. Please refer to GpioPrivateLib.c
+ to familiarize with details of implementation.
+**/
+
+/**
+ This procedure reads GPIO register
+
+ @param[in] GpioGroupInfo Pointer to GPIO group table info
+ @param[in] Register Register offset
+
+ @retval Register value or "F"s in case of errors
+**/
+UINT32
+GpioRegisterAccessRead32 (
+ IN CONST GPIO_GROUP_INFO *GpioGroupInfo,
+ IN UINT32 Register
+ );
+
+/**
+ This procedure writes GPIO register
+
+ @param[in] GpioGroupInfo Pointer to GPIO group table info
+ @param[in] Register Register offset
+ @param[in] AndValue And value
+ @param[in] OrValue Or value
+
+ @retval EFI_DEVICE_ERROR vGPIO BAR not programmed
+ EFI_SUCCESS Operation completed successfully
+**/
+EFI_STATUS
+GpioRegisterAccessAndThenOr32 (
+ IN CONST GPIO_GROUP_INFO *GpioGroupInfo,
+ IN UINT32 Register,
+ IN UINT32 AndValue,
+ IN UINT32 OrValue
+ );
+
+/**
+ This procedure will calculate PADCFG register value based on GpioConfig data
+ The procedure can be various depending on chipset generation.
+ Available configuration options and corresponding registers fields
+ can distributed in different way in configuration registers.
+
+ @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
+ );
+
+/**
+ This procedure will write GPIO Lock/LockTx register
+ - For PCH SBI message is used.
+ - For IBL MMIO access is used.
+
+ @param[in] RegValue GPIO register (Lock or LockTx) value
+ @param[in] RegOffset GPIO register (Lock or LockTx) base offset
+ @param[in] DwNum Register number for current group.
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[in] GpioGroupInfo Pointer to GPIO group table info
+ @param[in] GroupIndex GPIO group index in the GpioGroupInfo table
+
+ @retval EFI_SUCCESS The function completed successfully
+ EFI_UNSUPPORTED Feature is not supported for this group or pad
+**/
+EFI_STATUS
+GpioInternalWriteLockRegister (
+ IN UINT32 RegValue,
+ IN UINT32 RegOffset,
+ IN UINT32 DwNum,
+ IN CONST GPIO_GROUP_INFO *GpioGroupInfo,
+ IN UINT32 GroupIndex
+ );
+
+#endif // _GPIO_PRIVATE_LIB_H_
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Gpio/Library/PeiDxeSmmGpioLib/GpioInit.c b/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Gpio/Library/PeiDxeSmmGpioLib/GpioInit.c
new file mode 100644
index 0000000000..cf6f92a50d
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Gpio/Library/PeiDxeSmmGpioLib/GpioInit.c
@@ -0,0 +1,546 @@
+/** @file
+ This file contains routines for GPIO initialization
+
+ Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include "GpioLibrary.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.
+//
+// For Cannonlake only vGPIO group has >32 pads but those pads
+// will not be accessed by this function so GPIO_GROUP_DW_NUMBER can be 1
+//
+#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 - 1); 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;
+ UINT32 DwRegIndex;
+
+ PadOwnVal = GpioPadOwnHost;
+
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+
+ Index = 0;
+ while (Index < NumberOfItems) {
+
+ GpioData = &GpioInitTableAddress[Index];
+ GroupIndex = GpioGetGroupIndexFromGpioPad (GpioData->GpioPad);
+
+ 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
+ goto move_to_next_index;
+ }
+
+ //
+ // 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: GPIO used for SCI is not unlocked!\n"));
+ 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
+ );
+
+ //
+ // Write PADCFG DW0, DW1, DW2 registers
+ //
+ for (DwRegIndex = 0; DwRegIndex <= 2; DwRegIndex++) {
+ PadCfgReg = GpioGetGpioPadCfgAddressFromGpioPad (GpioData->GpioPad, DwRegIndex);
+ if (PadCfgReg != 0) {
+ GpioRegisterAccessAndThenOr32 (&GpioGroupInfo[GroupIndex], PadCfgReg, ~PadCfgDwRegMask[DwRegIndex], PadCfgDwReg[DwRegIndex]);
+ }
+ }
+
+ //
+ // Get GPIO DW register values from GPIO config data
+ //
+ GpioDwRegValueFromGpioConfig (
+ PadNumber,
+ &GpioData->GpioConfig,
+ GroupDwData
+ );
+
+ move_to_next_index:
+ //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) {
+ GpioRegisterAccessAndThenOr32 (
+ &GpioGroupInfo[GroupIndex],
+ GpioGroupInfo[GroupIndex].HostOwnOffset + DwNum * 0x4,
+ ~GroupDwData[DwNum].HostSoftOwnRegMask,
+ GroupDwData[DwNum].HostSoftOwnReg
+ );
+ }
+
+ //
+ // Write GPI_GPE_EN registers
+ //
+ if (GpioGroupInfo[GroupIndex].GpiGpeEnOffset != NO_REGISTER_FOR_PROPERTY) {
+ GpioRegisterAccessAndThenOr32 (
+ &GpioGroupInfo[GroupIndex],
+ GpioGroupInfo[GroupIndex].GpiGpeEnOffset + DwNum * 0x4,
+ ~GroupDwData[DwNum].GpiGpeEnRegMask,
+ GroupDwData[DwNum].GpiGpeEnReg
+ );
+ }
+
+ //
+ // Write GPI_NMI_EN registers
+ //
+ if (GpioGroupInfo[GroupIndex].NmiEnOffset != NO_REGISTER_FOR_PROPERTY) {
+ GpioRegisterAccessAndThenOr32 (
+ &GpioGroupInfo[GroupIndex],
+ 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) {
+ GpioRegisterAccessAndThenOr32 (
+ &GpioGroupInfo[GroupIndex],
+ 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++) {
+ GpioRegisterAccessAndThenOr32 (
+ &GpioGroupInfo[GroupIndex],
+ GpioGroupInfo[GroupIndex].GpiIsOffset + DwNum * 0x4,
+ ~(UINT32)0,
+ 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++) {
+ GpioRegisterAccessAndThenOr32 (
+ &GpioGroupInfo[GroupIndex],
+ GpioGroupInfo[GroupIndex].GpiGpeStsOffset + DwNum * 0x4,
+ ~(UINT32)0,
+ 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++) {
+ GpioRegisterAccessAndThenOr32 (
+ &GpioGroupInfo[GroupIndex],
+ GpioGroupInfo[GroupIndex].SmiStsOffset + DwNum * 4,
+ ~(UINT32)0,
+ 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++) {
+ GpioRegisterAccessAndThenOr32 (
+ &GpioGroupInfo[GroupIndex],
+ GpioGroupInfo[GroupIndex].NmiStsOffset + DwNum * 4,
+ ~(UINT32)0,
+ 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);
+
+ GpioClearAllGpioInterrupts ();
+ return Status;
+}
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Gpio/Library/PeiDxeSmmGpioLib/GpioLib.c b/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Gpio/Library/PeiDxeSmmGpioLib/GpioLib.c
new file mode 100644
index 0000000000..19daed97c0
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Gpio/Library/PeiDxeSmmGpioLib/GpioLib.c
@@ -0,0 +1,522 @@
+/** @file
+ This file contains routines for GPIO
+
+ Copyright (c) 2022, 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 = GpioRegisterAccessRead32 (&GpioGroupInfo[GroupIndex], 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;
+
+ GpioRegisterAccessAndThenOr32 (&GpioGroupInfo[GroupIndex], 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
+ )
+{
+ CONST GPIO_GROUP_INFO *GpioGroupInfo;
+ UINT32 GpioGroupInfoLength;
+ UINT32 RegOffset;
+ UINT32 OldLockVal;
+ UINT32 NewLockVal;
+ UINT32 GroupIndex;
+
+ 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;
+ }
+
+ NewLockVal = (OldLockVal & LockRegAndMask) | LockRegOrMask;
+
+ return GpioInternalWriteLockRegister (NewLockVal, RegOffset, DwNum, GpioGroupInfo, GroupIndex);
+}
+
+/**
+ 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);
+
+ //
+ // Check if selected register exists
+ //
+ if (GpioGroupInfo[GroupIndex].PadOwnOffset == NO_REGISTER_FOR_PROPERTY) {
+ *PadOwnVal = GpioPadOwnHost;
+ return EFI_UNSUPPORTED;
+ }
+ //
+ // 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 = GpioRegisterAccessRead32 (&GpioGroupInfo[GroupIndex], 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 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 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 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
+ );
+}
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Gpio/Library/PeiDxeSmmGpioLib/GpioLibrary.h b/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Gpio/Library/PeiDxeSmmGpioLib/GpioLibrary.h
new file mode 100644
index 0000000000..2c2b4ee75c
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Gpio/Library/PeiDxeSmmGpioLib/GpioLibrary.h
@@ -0,0 +1,29 @@
+/** @file
+ Header file for GPIO Lib implementation.
+
+ Copyright (c) 2022, 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/PchCycleDecodingLib.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
+
+#endif // _GPIO_LIBRARY_H_
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Gpio/Library/PeiDxeSmmGpioLib/GpioNativeLib.c b/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Gpio/Library/PeiDxeSmmGpioLib/GpioNativeLib.c
new file mode 100644
index 0000000000..4e4c53e588
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Gpio/Library/PeiDxeSmmGpioLib/GpioNativeLib.c
@@ -0,0 +1,177 @@
+/** @file
+ This file contains routines for GPIO native and chipset specific usage
+
+ Copyright (c) 2022, 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
+ )
+{
+ if (IsPchLp ()) {
+ return GPIO_PAD_DEF (Group,PadNumber);
+ } else {
+ return GPIO_PAD_DEF (Group,PadNumber);
+ }
+}
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Gpio/Library/PeiDxeSmmGpioLib/PeiDxeSmmGpioLib.inf b/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Gpio/Library/PeiDxeSmmGpioLib/PeiDxeSmmGpioLib.inf
new file mode 100644
index 0000000000..21fb4417c1
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Gpio/Library/PeiDxeSmmGpioLib/PeiDxeSmmGpioLib.inf
@@ -0,0 +1,44 @@
+## @file
+# Component description file for the PeiDxeSmmGpioLib
+#
+# Copyright (c) 2022, 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
+GpioHelpersLib
+
+[Packages]
+MdePkg/MdePkg.dec
+AlderlakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+GpioLib.c
+GpioNativeLib.c
+GpioInit.c
+GpioLibrary.h
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/BaseGpioHelpersLibNull/BaseGpioHelpersLibNull.c b/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/BaseGpioHelpersLibNull/BaseGpioHelpersLibNull.c
new file mode 100644
index 0000000000..b4b6c14329
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/BaseGpioHelpersLibNull/BaseGpioHelpersLibNull.c
@@ -0,0 +1,51 @@
+/** @file
+ This file contains NULL implementation for GPIO Helpers Lib
+
+ Copyright (c) 2022, 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 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;
+}
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/BaseGpioHelpersLibNull/BaseGpioHelpersLibNull.inf b/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/BaseGpioHelpersLibNull/BaseGpioHelpersLibNull.inf
new file mode 100644
index 0000000000..91d81af4b9
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/BaseGpioHelpersLibNull/BaseGpioHelpersLibNull.inf
@@ -0,0 +1,25 @@
+## @file
+# Component description file for the NULL GpioHelpersLib
+#
+# Copyright (c) 2022, 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
+AlderlakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+BaseGpioHelpersLibNull.c
+
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/PeiDxeSmmGpioPrivateLib/GpioNativePrivateLibInternal.h b/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/PeiDxeSmmGpioPrivateLib/GpioNativePrivateLibInternal.h
new file mode 100644
index 0000000000..480990cb62
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/PeiDxeSmmGpioPrivateLib/GpioNativePrivateLibInternal.h
@@ -0,0 +1,48 @@
+/** @file
+ Header file for GPIO Private Lib Internal functions.
+
+ Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _GPIO_NATIVE_PRIVATE_LIB_INTERNAL_H_
+#define _GPIO_NATIVE_PRIVATE_LIB_INTERNAL_H_
+
+#include <Library/GpioPrivateLib.h>
+
+
+/**
+ This function provides recommended GPIO IO Standby configuration for a given native function
+
+ @param[in] PadFunction PadFunction for a specific native signal. Please refer to GpioNativePads.h
+ @param[out] StandbyState IO Standby State for specified native function
+ @param[out] StandbyTerm IO Standby Termination for specified native function
+
+ @retval Status
+**/
+EFI_STATUS
+GpioGetFunctionIoStandbyConfig (
+ IN UINT32 PadFunction,
+ OUT GPIO_IOSTANDBY_STATE *StandbyState,
+ OUT GPIO_IOSTANDBY_TERM *StandbyTerm
+ );
+
+/**
+ This procedure will calculate PADCFG register value based on GpioConfig data
+ For physical/local/hard (not virtual) GPIO pads
+
+ @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
+GpioPadCfgRegValueFromGpioConfigHardGpio (
+ IN GPIO_PAD GpioPad,
+ IN CONST GPIO_CONFIG *GpioConfig,
+ OUT UINT32 *PadCfgDwReg,
+ OUT UINT32 *PadCfgDwRegMask
+ );
+
+#endif // _GPIO_NATIVE_PRIVATE_LIB_INTERNAL_H_
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/PeiDxeSmmGpioPrivateLib/GpioPrivateLib.c b/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/PeiDxeSmmGpioPrivateLib/GpioPrivateLib.c
new file mode 100644
index 0000000000..7d5fa9fafd
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/PeiDxeSmmGpioPrivateLib/GpioPrivateLib.c
@@ -0,0 +1,267 @@
+/** @file
+ This file contains GPIO routines for RC usage
+
+ Copyright (c) 2022, 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/GpioNativePads.h>
+#include <Register/GpioRegs.h>
+#include "GpioNativePrivateLibInternal.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: GPIO not owned by host!\n"));
+ 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 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 group (max: %d)\n",
+ PadNumber,
+ 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;
+
+ GroupIndex = GpioGetGroupIndexFromGpioPad (GpioPad);
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+
+ //
+ // Create Pad Configuration register offset
+ //
+ PadCfgReg = GpioGetGpioPadCfgAddressFromGpioPad (GpioPad, DwReg);
+ return GpioRegisterAccessRead32 (&GpioGroupInfo[GroupIndex], PadCfgReg);
+}
+
+
+/**
+ This procedure will calculate PADCFG register value based on GpioConfig data
+ For physical/local/hard (not virtual) GPIO pads
+
+ @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
+GpioPadCfgRegValueFromGpioConfigHardGpio (
+ IN GPIO_PAD GpioPad,
+ IN CONST GPIO_CONFIG *GpioConfig,
+ OUT UINT32 *PadCfgDwReg,
+ OUT UINT32 *PadCfgDwRegMask
+ )
+{
+ //
+ // 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;
+}
+
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/PeiDxeSmmGpioPrivateLib/GpioPrivateLibPch.c b/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/PeiDxeSmmGpioPrivateLib/GpioPrivateLibPch.c
new file mode 100644
index 0000000000..3d16fd2acd
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/PeiDxeSmmGpioPrivateLib/GpioPrivateLibPch.c
@@ -0,0 +1,172 @@
+/** @file
+ This file contains hard/physical/local (not virtual) GPIO information
+
+ Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include <Uefi/UefiBaseType.h>
+#include <Library/GpioLib.h>
+#include <Library/GpioPrivateLib.h>
+#include <Library/GpioNativeLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/PchSbiAccessLib.h>
+#include <Register/GpioRegs.h>
+#include "GpioNativePrivateLibInternal.h"
+
+/**
+ This procedure calculates Pad Configuration Register DW offset
+
+ @param[in] GpioPad GPIO pad
+ @param[in] DwReg Index of the configuration register
+
+ @retval DW Register offset
+**/
+UINT32
+GpioGetGpioPadCfgAddressFromGpioPad (
+ IN GPIO_PAD GpioPad,
+ IN UINT32 DwReg
+ )
+{
+ UINT32 PadCfgRegAddress;
+ 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
+ //
+ PadCfgRegAddress = GpioGroupInfo[GroupIndex].PadCfgOffset + DwReg * 4 + S_GPIO_PCR_PADCFG * PadNumber;
+
+ return PadCfgRegAddress;
+}
+
+/**
+ This procedure reads GPIO register
+
+ @param[in] GpioGroupInfo Pointer to GPIO group table info
+ @param[in] Register Register offset
+
+ @retval Register value or "F"s in case of errors
+**/
+UINT32
+GpioRegisterAccessRead32 (
+ IN CONST GPIO_GROUP_INFO *GpioGroupInfo,
+ IN UINT32 Register
+ )
+{
+ return MmioRead32 (PCH_PCR_ADDRESS (GpioGroupInfo->Community, Register));
+}
+
+/**
+ This procedure writes GPIO register
+
+ @param[in] GpioGroupInfo Pointer to GPIO group table info
+ @param[in] Register Register offset
+ @param[in] AndValue And value
+ @param[in] OrValue Or value
+
+ @retval EFI_SUCCESS Operation completed successfully
+**/
+EFI_STATUS
+GpioRegisterAccessAndThenOr32 (
+ IN CONST GPIO_GROUP_INFO *GpioGroupInfo,
+ IN UINT32 Register,
+ IN UINT32 AndValue,
+ IN UINT32 OrValue
+ )
+{
+ MmioAndThenOr32 (
+ PCH_PCR_ADDRESS (GpioGroupInfo->Community, Register),
+ AndValue,
+ OrValue
+ );
+ 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
+ )
+{
+ return GpioPadCfgRegValueFromGpioConfigHardGpio (GpioPad, GpioConfig, PadCfgDwReg, PadCfgDwRegMask);
+}
+
+/**
+ This procedure will write GPIO Lock/LockTx register
+ - For PCH SBI message is used.
+
+ @param[in] RegValue GPIO register (Lock or LockTx) value
+ @param[in] RegOffset GPIO register (Lock or LockTx) base offset
+ @param[in] DwNum Register number for current group.
+ For group which has less then 32 pads per group DwNum must be 0.
+ @param[in] GpioGroupInfo Pointer to GPIO group table info
+ @param[in] GroupIndex GPIO group index in the GpioGroupInfo table
+
+ @retval EFI_SUCCESS The function completed successfully
+ EFI_UNSUPPORTED Feature is not supported for this group or pad
+**/
+EFI_STATUS
+GpioInternalWriteLockRegister (
+ IN UINT32 RegValue,
+ IN UINT32 RegOffset,
+ IN UINT32 DwNum,
+ IN CONST GPIO_GROUP_INFO *GpioGroupInfo,
+ IN UINT32 GroupIndex
+ )
+{
+ EFI_STATUS Status;
+ PCH_SBI_OPCODE Opcode;
+ UINT8 Response;
+
+ //
+ // 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;
+
+ if (IsGpioLockOpcodeSupported ()) {
+ Opcode = GpioLockUnlock;
+ } else {
+ Opcode = PrivateControlWrite;
+ }
+
+ Status = PchSbiExecutionEx (
+ GpioGroupInfo[GroupIndex].Community,
+ RegOffset,
+ Opcode,
+ FALSE,
+ 0x000F,
+ 0x0000,
+ 0x0000,
+ &RegValue,
+ &Response
+ );
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/PeiDxeSmmGpioPrivateLib/GpioPrivateLibVer2.c b/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/PeiDxeSmmGpioPrivateLib/GpioPrivateLibVer2.c
new file mode 100644
index 0000000000..1348643553
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/PeiDxeSmmGpioPrivateLib/GpioPrivateLibVer2.c
@@ -0,0 +1,81 @@
+/** @file
+ This file contains VER2 specific GPIO information
+
+ Copyright (c) 2022, 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/GpioNativePads.h>
+#include <Library/GpioPrivateLib.h>
+#include <Library/GpioHelpersLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/IoLib.h>
+#include <Register/GpioRegsVer2.h>
+#include <Register/PchPcrRegs.h>
+#include <Register/GpioRegs.h>
+#include <Pins/GpioPinsVer2Lp.h>
+#include <GpioNativePrivateLibInternal.h>
+#include <Library/PcdLib.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
+};
+
+/**
+ 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;
+}
+
+/**
+ 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/AlderlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/PeiDxeSmmGpioPrivateLib/PeiDxeSmmGpioPrivateLibVer2.inf b/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/PeiDxeSmmGpioPrivateLib/PeiDxeSmmGpioPrivateLibVer2.inf
new file mode 100644
index 0000000000..2e9a6b7336
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/PeiDxeSmmGpioPrivateLib/PeiDxeSmmGpioPrivateLibVer2.inf
@@ -0,0 +1,40 @@
+## @file
+# Component description file for the PeiDxeSmmGpioPrivateLib
+#
+# Copyright (c) 2022, 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
+ GpioHelpersLib
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ AlderlakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+ GpioPrivateLib.c
+ GpioPrivateLibVer2.c
+ GpioPrivateLibPch.c
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/PeiGpioHelpersLib/PeiGpioHelpersLib.c b/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/PeiGpioHelpersLib/PeiGpioHelpersLib.c
new file mode 100644
index 0000000000..9d47e6bfd5
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/PeiGpioHelpersLib/PeiGpioHelpersLib.c
@@ -0,0 +1,218 @@
+/** @file
+ This file contains routines for PEI GPIO Helpers Lib
+
+ Copyright (c) 2022, 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 <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 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;
+}
diff --git a/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/PeiGpioHelpersLib/PeiGpioHelpersLib.inf b/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/PeiGpioHelpersLib/PeiGpioHelpersLib.inf
new file mode 100644
index 0000000000..c1886b22f9
--- /dev/null
+++ b/Silicon/Intel/AlderlakeSiliconPkg/IpBlock/Gpio/LibraryPrivate/PeiGpioHelpersLib/PeiGpioHelpersLib.inf
@@ -0,0 +1,46 @@
+## @file
+# Component description file for the PeiGpioHelpersLib
+#
+# Copyright (c) 2022, 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
+ConfigBlockLib
+PeiServicesLib
+
+
+[Packages]
+MdePkg/MdePkg.dec
+AlderlakeSiliconPkg/SiPkg.dec
+
+
+[Sources]
+PeiGpioHelpersLib.c
+
+
+[Guids]
+gGpioLibUnlockHobGuid
+
+[Ppis]
+gSiPreMemPolicyPpiGuid
--
2.36.1.windows.1
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#108663): https://edk2.groups.io/g/devel/message/108663
Mute This Topic: https://groups.io/mt/101347727/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-
prev parent reply other threads:[~2023-09-15 2:59 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-09-13 22:13 [edk2-devel] [PATCH 01/10] AlderlakeSiliconPkg/IpBlock: Add CpuPcieRp, Espi, Gpio components Saloni Kasbekar
2023-09-13 22:13 ` [edk2-devel] [PATCH 02/10] AlderlakeSiliconPkg/IpBlock: Add Graphics, HostBridge, PcieRp components Saloni Kasbekar
2023-09-14 17:23 ` Chaganty, Rangasai V
2023-09-15 3:02 ` Chuang, Rosen
2023-09-13 22:13 ` [edk2-devel] [PATCH 03/10] AlderlakeSiliconPkg/IpBlock: Add P2sb, PchDmi components Saloni Kasbekar
2023-09-14 17:41 ` Chaganty, Rangasai V
2023-09-15 3:02 ` Chuang, Rosen
2023-09-13 22:13 ` [edk2-devel] [PATCH 04/10] AlderlakeSiliconPkg/IpBlock: Add Pmc, Spi components Saloni Kasbekar
2023-09-14 21:40 ` Chaganty, Rangasai V
2023-09-15 3:04 ` Chuang, Rosen
2023-09-13 22:13 ` [edk2-devel] [PATCH 05/10] AlderlakeSiliconPkg/Include: Add ConfigBlock headers Saloni Kasbekar
2023-09-14 21:45 ` Chaganty, Rangasai V
2023-09-15 3:05 ` Chuang, Rosen
2023-09-13 22:13 ` [edk2-devel] [PATCH 06/10] AlderlakeSiliconPkg/Include: Add Library, Pins, Ppi Includes Saloni Kasbekar
2023-09-14 22:01 ` Chaganty, Rangasai V
2023-09-15 3:06 ` Chuang, Rosen
2023-09-13 22:13 ` [edk2-devel] [PATCH 07/10] AlderlakeSiliconPkg/Include: Add Protocol, Register, Other Includes Saloni Kasbekar
2023-09-14 22:02 ` Chaganty, Rangasai V
2023-09-15 3:06 ` Chuang, Rosen
2023-09-13 22:13 ` [edk2-devel] [PATCH 08/10] AlderlakeSiliconPkg/Fru: Add AdlCpu Fru Saloni Kasbekar
2023-09-15 3:07 ` Chuang, Rosen
2023-09-13 22:14 ` [edk2-devel] [PATCH 09/10] AlderlakeSiliconPkg: Add AdlPch Fru and IncludePrivate modules Saloni Kasbekar
2023-09-14 22:20 ` Chaganty, Rangasai V
2023-09-15 3:08 ` Chuang, Rosen
2023-09-13 22:14 ` [edk2-devel] [PATCH 10/10] AlderlakeSiliconPkg: Add Alderlake Product and SiPkg.dec Saloni Kasbekar
2023-09-14 22:23 ` Chaganty, Rangasai V
2023-09-15 3:10 ` Chuang, Rosen
2023-09-14 16:02 ` [edk2-devel] [PATCH 01/10] AlderlakeSiliconPkg/IpBlock: Add CpuPcieRp, Espi, Gpio components Chaganty, Rangasai V
2023-09-15 2:59 ` Chuang, Rosen [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=DM8PR11MB5624071E539CF09008F0FFCC92F6A@DM8PR11MB5624.namprd11.prod.outlook.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox