diff options
Diffstat (limited to 'Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmGpioLib/GpioNativeLib.c')
-rw-r--r-- | Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmGpioLib/GpioNativeLib.c | 454 |
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; + } +} + |