summaryrefslogtreecommitdiff
path: root/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmGpioLib/GpioNativeLib.c
diff options
context:
space:
mode:
Diffstat (limited to 'Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmGpioLib/GpioNativeLib.c')
-rw-r--r--Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmGpioLib/GpioNativeLib.c454
1 files changed, 454 insertions, 0 deletions
diff --git a/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmGpioLib/GpioNativeLib.c b/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmGpioLib/GpioNativeLib.c
new file mode 100644
index 0000000000..a86c144679
--- /dev/null
+++ b/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmGpioLib/GpioNativeLib.c
@@ -0,0 +1,454 @@
+/** @file
+
+Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "GpioLibrary.h"
+
+//
+// Chipset specific data
+//
+//SATA
+extern GPIO_PAD_NATIVE_FUNCTION mPchHSataPortResetToGpioMap[PCH_H_AHCI_MAX_PORTS];
+extern GPIO_PAD_NATIVE_FUNCTION mPchHSataDevSlpPinToGpioMap[PCH_H_AHCI_MAX_PORTS];
+
+//
+// SKX specific
+//
+extern GPIO_GROUP_INFO mPchGpioGroupInfo[V_PCH_GPIO_GROUP_MAX];
+
+/**
+ This procedure will set GPIO mode
+
+ @param[in] GpioPad GPIO pad
+ @param[out] PadModeValue GPIO pad mode value
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+SetGpioPadMode (
+ IN GPIO_PAD GpioPad,
+ IN GPIO_PAD_MODE PadModeValue
+ )
+{
+ GPIO_PAD_OWN PadOwnVal;
+ UINT32 PadCfgReg;
+ GPIO_GROUP_INFO *GpioGroupInfo;
+ UINTN GpioGroupInfoLength;
+ UINT32 PadNumber;
+ UINT32 GroupIndex;
+ UINT32 Dw0Reg;
+ UINT32 Dw0RegMask;
+
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+
+ GroupIndex = GpioGetGroupIndexFromGpioPad (GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+
+DEBUG_CODE_BEGIN();
+ if (!GpioIsCorrectPadForThisChipset (GpioPad)) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Incorrect GpioPad define used on this chipset (Group=%d, Pad=%d)!\n", GroupIndex, PadNumber));
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+DEBUG_CODE_END();
+
+ GpioGetPadOwnership (GpioPad, &PadOwnVal);
+
+ if (PadOwnVal != GpioPadOwnHost) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Accessing pad not owned by host (Group=%d, Pad=%d)!\n", GroupIndex, PadNumber));
+ return EFI_UNSUPPORTED;
+ }
+
+ if (GpioIsPadLocked (GroupIndex, PadNumber)) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Pad is locked (Group=%d, Pad=%d)!\n", GroupIndex, PadNumber));
+ return EFI_WRITE_PROTECTED;
+ }
+
+ //
+ // Create Pad Configuration register offset
+ //
+ PadCfgReg = 0x8 * PadNumber + GpioGroupInfo[GroupIndex].PadCfgOffset;
+
+ Dw0RegMask = ((((PadModeValue & GPIO_CONF_PAD_MODE_MASK) >> GPIO_CONF_PAD_MODE_BIT_POS) == GpioHardwareDefault) ? 0x0 : B_PCH_GPIO_PAD_MODE);
+ Dw0Reg = (((PadModeValue & GPIO_CONF_PAD_MODE_MASK) >> (GPIO_CONF_PAD_MODE_BIT_POS + 1)) << N_PCH_GPIO_PAD_MODE);
+
+ MmioAndThenOr32 (
+ (UINTN)PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, PadCfgReg),
+ ~(UINT32)Dw0RegMask,
+ (UINT32)Dw0Reg
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will get GPIO mode
+
+ @param[in] GpioPad GPIO pad
+ @param[out] PadModeValue GPIO pad mode value
+
+ @retval EFI_SUCCESS The function completed successfully
+ @retval EFI_INVALID_PARAMETER Invalid group or pad number
+**/
+EFI_STATUS
+GetGpioPadMode (
+ IN GPIO_PAD GpioPad,
+ OUT GPIO_PAD_MODE *PadModeValue
+ )
+{
+ GPIO_PAD_OWN PadOwnVal;
+ UINT32 PadCfgReg;
+ GPIO_GROUP_INFO *GpioGroupInfo;
+ UINTN GpioGroupInfoLength;
+ UINT32 PadNumber;
+ UINT32 GroupIndex;
+ UINT32 Dw0Reg;
+
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+
+ GroupIndex = GpioGetGroupIndexFromGpioPad (GpioPad);
+ PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
+
+DEBUG_CODE_BEGIN();
+ if (!GpioIsCorrectPadForThisChipset (GpioPad)) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Incorrect GpioPad define used on this chipset (Group=%d, Pad=%d)!\n", GroupIndex, PadNumber));
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+DEBUG_CODE_END();
+
+ GpioGetPadOwnership (GpioPad, &PadOwnVal);
+
+ if (PadOwnVal != GpioPadOwnHost) {
+ DEBUG ((DEBUG_ERROR, "GPIO ERROR: Accessing pad not owned by host (Group=%d, Pad=%d)!\n", GroupIndex, PadNumber));
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Create Pad Configuration register offset
+ //
+ PadCfgReg = 0x8 * PadNumber + GpioGroupInfo[GroupIndex].PadCfgOffset;
+
+ Dw0Reg = MmioRead32 ((UINTN)PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, PadCfgReg));
+
+ *PadModeValue = ((Dw0Reg & B_PCH_GPIO_PAD_MODE) >> (N_PCH_GPIO_PAD_MODE - (GPIO_CONF_PAD_MODE_BIT_POS + 1))) | (0x1 << GPIO_CONF_PAD_MODE_BIT_POS);
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ 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
+
+**/
+GPIO_GROUP_INFO*
+GpioGetGroupInfoTable (
+ OUT UINTN *GpioGroupInfoTableLength
+ )
+{
+ if (GetPchGeneration () == SklPch) {
+ *GpioGroupInfoTableLength = sizeof (mPchGpioGroupInfo) / sizeof (GPIO_GROUP_INFO);
+ return mPchGpioGroupInfo;
+ } else {
+ *GpioGroupInfoTableLength = 0;
+ return NULL;
+ }
+}
+
+
+/**
+ 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
+ )
+{
+DEBUG_CODE_BEGIN();
+ PCH_SERIES PchSeries;
+
+ PchSeries = GetPchSeries ();
+
+ if ((PchSeries == PchH) && (GPIO_GET_CHIPSET_ID(GpioPad) == GPIO_SKL_H_CHIPSET_ID)) {
+ return TRUE;
+ } else if ((PchSeries == PchLp) && (GPIO_GET_CHIPSET_ID(GpioPad) == GPIO_SKL_LP_CHIPSET_ID)) {
+ return TRUE;
+ }
+
+DEBUG_CODE_END();
+ return FALSE;
+}
+
+
+/**
+ 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
+ )
+{
+ GPIO_GROUP_INFO *GpioGroupInfo;
+ UINTN GpioGroupInfoLength;
+ UINT32 GroupIndex;
+ //
+ // Check if group argument exceeds GPIO GROUP INFO array
+ //
+ GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
+ GroupIndex = GpioGetGroupIndexFromGroup (Group);
+
+ if ((UINTN)GroupIndex >= GpioGroupInfoLength) {
+ ASSERT(FALSE);
+ return 0;
+ } else {
+ return GpioGroupInfo[GroupIndex].PadPerGroup;
+ }
+}
+
+/**
+ This procedure will get number of groups
+
+ @param[in] none
+
+ @retval Value Group number
+**/
+UINT8
+GpioGetNumberOfGroups (
+ VOID
+ )
+{
+ return V_PCH_H_GPIO_GROUP_MAX;
+}
+/**
+ This procedure will get lowest group
+
+ @param[in] none
+
+ @retval Value Lowest Group
+**/
+GPIO_GROUP
+GpioGetLowestGroup (
+ VOID
+ )
+{
+ return (UINT32)GPIO_SKL_H_GROUP_GPP_A;
+}
+/**
+ This procedure will get highest group
+
+ @param[in] none
+
+ @retval Value Highest Group
+**/
+GPIO_GROUP
+GpioGetHighestGroup (
+ VOID
+ )
+{
+ return (UINT32)GPIO_SKL_H_GROUP_GPD;
+}
+
+/**
+ 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 pad number (0 based) from Gpio Pad
+
+ @param[in] GpioPad Gpio Pad
+
+ @retval Value Pad Number
+**/
+UINT32
+GpioGetPadNumberFromGpioPad (
+ IN GPIO_PAD GpioPad
+ )
+{
+ return (UINT32)GPIO_GET_PAD_NUMBER (GpioPad);
+}
+/**
+ This procedure will return GpioPad from Group and PadNumber
+
+ @param[in] Group GPIO group
+ @param[in] PadNumber GPIO PadNumber
+
+ @retval GpioPad GpioPad
+**/
+GPIO_PAD
+GpioGetGpioPadFromGroupAndPadNumber (
+ IN GPIO_GROUP Group,
+ IN UINT32 PadNumber
+ )
+{
+ return GPIO_PAD_DEF(Group,PadNumber);
+}
+
+
+
+/**
+ This function checks if GPIO pin for SATA reset port is in GPIO MODE
+
+ @param[in] SataPort SATA port number
+
+ @retval TRUE Pin is in GPIO mode
+ FALSE Pin is in native mode
+**/
+BOOLEAN
+GpioIsSataResetPortInGpioMode (
+ IN UINTN SataPort
+ )
+{
+ EFI_STATUS Status;
+ UINT32 GpioPin;
+ GPIO_PAD_MODE GpioMode;
+
+
+ ASSERT (SataPort < PCH_H_AHCI_MAX_PORTS);
+ GpioPin = mPchHSataPortResetToGpioMap[SataPort].Pad;
+
+ Status = GetGpioPadMode (GpioPin, &GpioMode);
+ if ((EFI_ERROR (Status)) || (GpioMode != GpioPadModeGpio)) {
+ return FALSE;
+ } else {
+ return TRUE;
+ }
+}
+
+
+/**
+ This function checks if GPIO pin is a SataDevSlp pin
+
+ @param[in] GpioPad GPIO pad
+ @param[in] PadMode GPIO pad mode
+
+ @retval TRUE Pin is in GPIO mode
+ FALSE Pin is in native mode
+**/
+BOOLEAN
+GpioIsPadASataDevSlpPin (
+ IN GPIO_PAD GpioPad,
+ IN GPIO_PAD_MODE PadMode
+ )
+{
+ UINT32 SataDevSlpPinMax;
+ UINT32 SataDevSlpPinIndex;
+ GPIO_PAD_OWN PadOwnership;
+ GPIO_PAD_NATIVE_FUNCTION *SataDevSlpPinToGpioMap;
+
+ SataDevSlpPinToGpioMap = mPchHSataDevSlpPinToGpioMap;
+ SataDevSlpPinMax = sizeof(mPchHSataDevSlpPinToGpioMap)/sizeof(GPIO_PAD_NATIVE_FUNCTION);
+
+ for (SataDevSlpPinIndex = 0; SataDevSlpPinIndex < SataDevSlpPinMax; SataDevSlpPinIndex++) {
+ if ((GpioPad == SataDevSlpPinToGpioMap[SataDevSlpPinIndex].Pad) &&
+ (PadMode == SataDevSlpPinToGpioMap[SataDevSlpPinIndex].Mode)) {
+ GpioGetPadOwnership (SataDevSlpPinToGpioMap[SataDevSlpPinIndex].Pad , &PadOwnership);
+ if (PadOwnership == GpioPadOwnHost) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+ }
+ }
+ return FALSE;
+}
+
+/**
+ This function checks if SataDevSlp pin is in native mode
+
+ @param[in] SataPort SATA port
+ @param[out] DevSlpPad DevSlpPad
+
+ @retval TRUE DevSlp is in native mode
+ FALSE DevSlp is not in native mode
+**/
+BOOLEAN
+GpioIsSataDevSlpPinEnabled (
+ IN UINTN SataPort,
+ OUT GPIO_PAD *DevSlpPad
+ )
+{
+ GPIO_PAD_MODE DevSlpPadMode;
+ GPIO_PAD DevSlpGpioPad;
+ GPIO_PAD_MODE GpioMode;
+ EFI_STATUS Status;
+
+ ASSERT (SataPort < PCH_H_AHCI_MAX_PORTS);
+ DevSlpGpioPad = mPchHSataDevSlpPinToGpioMap[SataPort].Pad;
+ DevSlpPadMode = mPchHSataDevSlpPinToGpioMap[SataPort].Mode;
+
+ Status = GetGpioPadMode (DevSlpGpioPad, &GpioMode);
+
+ if (EFI_ERROR (Status) || (GpioMode != DevSlpPadMode)) {
+ *DevSlpPad = 0x0;
+ return FALSE;
+ } else {
+ *DevSlpPad = DevSlpGpioPad;
+ return TRUE;
+ }
+}
+