/** @file
|
This file contains routines for GPIO
|
|
Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
**/
|
#include "GpioLibrary.h"
|
|
/**
|
This procedure will check if GpioPad is owned by host.
|
|
@param[in] GpioPad GPIO pad
|
|
@retval TRUE GPIO pad is owned by host
|
@retval FALSE GPIO pad is not owned by host and should not be used with GPIO lib API
|
**/
|
BOOLEAN
|
GpioIsPadHostOwned (
|
IN GPIO_PAD GpioPad
|
)
|
{
|
UINT32 GroupIndex;
|
UINT32 PadNumber;
|
GPIO_PAD_OWN PadOwnVal;
|
|
//
|
// Check if selected GPIO Pad is not owned by CSME/ISH
|
// If GPIO is not owned by Host all access to PadCfg will be dropped
|
//
|
GpioGetPadOwnership (GpioPad, &PadOwnVal);
|
if (PadOwnVal != GpioPadOwnHost) {
|
GroupIndex = GpioGetGroupIndexFromGpioPad (GpioPad);
|
PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
|
DEBUG ((DEBUG_ERROR, "GPIO ERROR: Gpio pad not owned by host (Group=%d, Pad=%d)!\n", GroupIndex, PadNumber));
|
return FALSE;
|
}
|
|
return TRUE;
|
}
|
|
/**
|
This procedure will check if GpioPad argument is valid.
|
Function will check below conditions:
|
- GpioPad represents a pad for current PCH
|
- GpioPad belongs to valid GpioGroup
|
- GPIO PadNumber is not greater than number of pads for this group
|
|
@param[in] GpioPad GPIO pad
|
|
@retval TRUE GPIO pad is valid and can be used with GPIO lib API
|
@retval FALSE GPIO pad is invalid and cannot be used with GPIO lib API
|
**/
|
BOOLEAN
|
GpioIsPadValid (
|
IN GPIO_PAD GpioPad
|
)
|
{
|
GPIO_GROUP_INFO *GpioGroupInfo;
|
UINTN GpioGroupInfoLength;
|
UINT32 GroupIndex;
|
UINT32 PadNumber;
|
|
GroupIndex = GpioGetGroupIndexFromGpioPad (GpioPad);
|
PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
|
|
if (!GpioIsCorrectPadForThisChipset (GpioPad)) {
|
DEBUG ((DEBUG_ERROR, "GPIO ERROR: Incorrect GpioPad used on this chipset (Group=%d, Pad=%d)!\n", GroupIndex, PadNumber));
|
return FALSE;
|
}
|
|
GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
|
|
//
|
// Check if group argument exceeds GPIO GROUP INFO array
|
//
|
if ((UINTN) GroupIndex >= GpioGroupInfoLength) {
|
DEBUG ((DEBUG_ERROR, "GPIO ERROR: Group argument (%d) exceeds GPIO group range\n", GroupIndex));
|
return FALSE;
|
}
|
|
if ((GroupIndex < GpioGetGroupIndexFromGroup (GpioGetLowestGroup ())) ||
|
(GroupIndex > GpioGetGroupIndexFromGroup (GpioGetHighestGroup ()))) {
|
DEBUG ((DEBUG_ERROR, "GPIO ERROR: Group argument (%d) is not within range of possible groups for this PCH\n", GroupIndex));
|
return FALSE;
|
}
|
|
//
|
// Check if legal pin number
|
//
|
if (PadNumber >= GpioGroupInfo[GroupIndex].PadPerGroup) {
|
DEBUG ((DEBUG_ERROR, "GPIO ERROR: Pin number (%d) exceeds possible range for this group\n", PadNumber));
|
return FALSE;
|
}
|
|
return TRUE;
|
}
|
|
/**
|
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;
|
GPIO_GROUP_INFO *GpioGroupInfo;
|
UINTN GpioGroupInfoLength;
|
|
GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
|
|
GroupIndex = GpioGetGroupIndexFromGroup (Group);
|
|
//
|
// Check if group argument exceeds GPIO GROUP INFO array
|
//
|
if ((UINTN) GroupIndex >= GpioGroupInfoLength) {
|
DEBUG ((DEBUG_ERROR, "GPIO ERROR: Group argument (%d) exceeds GPIO group range\n", GroupIndex));
|
return FALSE;
|
}
|
|
if ((GroupIndex < GpioGetGroupIndexFromGroup (GpioGetLowestGroup ())) ||
|
(GroupIndex > GpioGetGroupIndexFromGroup (GpioGetHighestGroup ()))) {
|
DEBUG ((DEBUG_ERROR, "GPIO ERROR: Group argument (%d) is not within range of possible groups for this PCH\n", GroupIndex));
|
return FALSE;
|
}
|
|
//
|
// 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)){
|
return FALSE;
|
}
|
|
return TRUE;
|
}
|
|
/**
|
This procedure will write or read GPIO Pad Configuration register
|
|
@param[in] GpioPad GPIO pad
|
@param[in] DwReg Choose PADCFG register: 0:DW0, 1:DW1
|
@param[out] PadCfgRegValue Read data
|
|
@retval none
|
**/
|
VOID
|
GpioReadPadCfgReg (
|
IN GPIO_PAD GpioPad,
|
IN UINT8 DwReg,
|
OUT UINT32 *PadCfgRegValue
|
)
|
{
|
UINT32 PadCfgReg;
|
GPIO_GROUP_INFO *GpioGroupInfo;
|
UINTN GpioGroupInfoLength;
|
UINT32 GroupIndex;
|
UINT32 PadNumber;
|
|
GroupIndex = GpioGetGroupIndexFromGpioPad (GpioPad);
|
PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
|
|
GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
|
|
//
|
// Create Pad Configuration register offset
|
//
|
PadCfgReg = GpioGroupInfo[GroupIndex].PadCfgOffset + PAD_CFG_SIZE * PadNumber + 0x4 * DwReg;
|
|
*PadCfgRegValue = MmioRead32 (PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, PadCfgReg));
|
}
|
|
/**
|
This procedure will write or read GPIO Pad Configuration register
|
|
@param[in] GpioPad GPIO pad
|
@param[in] DwReg Choose PADCFG register: 0:DW0, 1:DW1
|
@param[in] PadCfgAndMask Mask to be AND'ed with PADCFG reg value
|
@param[in] PadCfgOrMask Mask to be OR'ed with PADCFG reg value
|
|
@retval none
|
**/
|
VOID
|
GpioWritePadCfgReg (
|
IN GPIO_PAD GpioPad,
|
IN UINT8 DwReg,
|
IN UINT32 PadCfgAndMask,
|
IN UINT32 PadCfgOrMask
|
)
|
{
|
UINT32 PadCfgReg;
|
GPIO_GROUP_INFO *GpioGroupInfo;
|
UINTN GpioGroupInfoLength;
|
UINT32 GroupIndex;
|
UINT32 PadNumber;
|
|
GroupIndex = GpioGetGroupIndexFromGpioPad (GpioPad);
|
PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
|
|
GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
|
|
//
|
// Create Pad Configuration register offset
|
//
|
PadCfgReg = GpioGroupInfo[GroupIndex].PadCfgOffset + PAD_CFG_SIZE * PadNumber + 0x4 * DwReg;
|
|
MmioAndThenOr32 (
|
PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, PadCfgReg),
|
PadCfgAndMask,
|
PadCfgOrMask
|
);
|
}
|
|
//
|
// 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;
|
GPIO_GROUP_INFO *GpioGroupInfo;
|
UINTN 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:
|
ASSERT (FALSE);
|
break;
|
}
|
|
//
|
// Check if selected register exists
|
//
|
if (RegOffset == NO_REGISTER_FOR_PROPERTY) {
|
return EFI_UNSUPPORTED;
|
}
|
|
//
|
// If there are more then 32 pads per group then certain
|
// group information would be split into more then one DWord register.
|
//
|
if ((RegType == GpioPadConfigLockRegister) || (RegType == GpioPadLockOutputRegister)) {
|
//
|
// PadConfigLock and OutputLock registers when used for group containing more than 32 pads
|
// are not placed in a continuous way, e.g:
|
// 0x0 - PadConfigLock_DW0
|
// 0x4 - OutputLock_DW0
|
// 0x8 - PadConfigLock_DW1
|
// 0xC - OutputLock_DW1
|
//
|
RegOffset += DwNum * 0x8;
|
} else {
|
RegOffset += DwNum * 0x4;
|
}
|
|
*ReadVal = MmioRead32 (PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, RegOffset));
|
|
return EFI_SUCCESS;
|
}
|
|
/**
|
This procedure will write GPIO register
|
|
@param[in] RegType GPIO register type
|
@param[in] Group GPIO group
|
@param[in] DwNum Register number for current group (parameter applicable in accessing whole register).
|
For group which has less then 32 pads per group DwNum must be 0.
|
@param[in] RegAndMask Mask which will be AND'ed with register value
|
@param[in] RegOrMask Mask which will be OR'ed with register value
|
|
@retval EFI_SUCCESS The function completed successfully
|
@retval EFI_UNSUPPORTED Feature is not supported for this group or pad
|
**/
|
STATIC
|
EFI_STATUS
|
GpioWriteReg (
|
IN GPIO_REG RegType,
|
IN GPIO_GROUP Group,
|
IN UINT32 DwNum,
|
IN UINT32 RegAndMask,
|
IN UINT32 RegOrMask
|
)
|
{
|
UINT32 RegOffset;
|
UINT32 GroupIndex;
|
GPIO_GROUP_INFO *GpioGroupInfo;
|
UINTN 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:
|
case GpioPadLockOutputRegister:
|
ASSERT (FALSE);
|
break;
|
default:
|
ASSERT (FALSE);
|
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.
|
//
|
RegOffset += DwNum * 0x4;
|
|
MmioAndThenOr32 (
|
PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, RegOffset),
|
RegAndMask,
|
RegOrMask
|
);
|
|
return EFI_SUCCESS;
|
}
|
|
/**
|
This procedure will write GPIO Lock/LockTx register using SBI.
|
|
@param[in] RegType GPIO register (Lock or LockTx)
|
@param[in] Group GPIO group number
|
@param[in] DwNum Register number for current group.
|
For group which has less then 32 pads per group DwNum must be 0.
|
@param[in] LockRegAndMask Mask which will be AND'ed with Lock register value
|
@param[in] LockRegOrMask Mask which will be Or'ed with Lock register value
|
|
@retval EFI_SUCCESS The function completed successfully
|
@retval EFI_UNSUPPORTED Feature is not supported for this group or pad
|
**/
|
STATIC
|
EFI_STATUS
|
GpioWriteLockReg (
|
IN GPIO_REG RegType,
|
IN GPIO_GROUP Group,
|
IN UINT32 DwNum,
|
IN UINT32 LockRegAndMask,
|
IN UINT32 LockRegOrMask
|
)
|
{
|
UINT8 Response;
|
EFI_STATUS Status;
|
GPIO_GROUP_INFO *GpioGroupInfo;
|
UINTN GpioGroupInfoLength;
|
UINT32 RegOffset;
|
UINT32 OldPadCfgLockRegVal;
|
UINT32 NewPadCfgLockRegVal;
|
UINT32 GroupIndex;
|
|
RegOffset = NO_REGISTER_FOR_PROPERTY;
|
GroupIndex = GpioGetGroupIndexFromGroup (Group);
|
|
GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
|
|
switch (RegType) {
|
case GpioPadConfigLockRegister:
|
RegOffset = GpioGroupInfo[GroupIndex].PadCfgLockOffset;
|
break;
|
case GpioPadLockOutputRegister:
|
RegOffset = GpioGroupInfo[GroupIndex].PadCfgLockTxOffset;
|
break;
|
default:
|
ASSERT (FALSE);
|
break;
|
}
|
|
//
|
// Check if selected register exists
|
//
|
if (RegOffset == NO_REGISTER_FOR_PROPERTY) {
|
return EFI_UNSUPPORTED;
|
}
|
|
//
|
// If there are more then 32 pads per group then certain
|
// group information would be split into more then one DWord register.
|
// PadConfigLock and OutputLock registers when used for group containing more than 32 pads
|
// are not placed in a continuous way, e.g:
|
// 0x0 - PadConfigLock_DW0
|
// 0x4 - OutputLock_DW0
|
// 0x8 - PadConfigLock_DW1
|
// 0xC - OutputLock_DW1
|
//
|
RegOffset += DwNum *0x8;
|
|
GpioGetPadCfgLockForGroupDw (Group, DwNum, &OldPadCfgLockRegVal);
|
|
NewPadCfgLockRegVal = (OldPadCfgLockRegVal & LockRegAndMask) | LockRegOrMask;
|
|
Status = PchSbiExecution (
|
GpioGroupInfo[GroupIndex].Community,
|
RegOffset,
|
GpioLockUnlock,
|
FALSE,
|
&NewPadCfgLockRegVal,
|
&Response
|
);
|
ASSERT_EFI_ERROR (Status);
|
return Status;
|
}
|
|
/**
|
This internal procedure will calculate GPIO_RESET_CONFIG value (new type)
|
based on provided PadRstCfg for a specific GPIO Pad.
|
|
@param[in] GpioPad GPIO Pad
|
@param[in] PadRstCfg GPIO PadRstCfg value
|
|
@retval GpioResetConfig GPIO Reset configuration (new type)
|
**/
|
GPIO_RESET_CONFIG
|
GpioResetConfigFromPadRstCfg (
|
IN GPIO_PAD GpioPad,
|
IN UINT32 PadRstCfg
|
)
|
{
|
GPIO_GROUP Group;
|
|
static GPIO_RESET_CONFIG GppPadRstCfgToGpioResetConfigMap[] = {
|
GpioResumeReset,
|
GpioHostDeepReset,
|
GpioPlatformReset};
|
static GPIO_RESET_CONFIG GpdPadRstCfgToGpioResetConfigMap[] = {
|
GpioDswReset,
|
GpioHostDeepReset,
|
GpioPlatformReset,
|
GpioResumeReset};
|
|
Group = GpioGetGroupFromGpioPad (GpioPad);
|
|
if ((Group == GPIO_SKL_LP_GROUP_GPD) || (Group == GPIO_SKL_H_GROUP_GPD)) {
|
ASSERT (PadRstCfg < 4);
|
if (PadRstCfg >= 4) return GpioResumeReset;
|
return GpdPadRstCfgToGpioResetConfigMap[PadRstCfg];
|
} else {
|
ASSERT (PadRstCfg < 3);
|
if (PadRstCfg >= 3) return GpioResumeReset;
|
return GppPadRstCfgToGpioResetConfigMap[PadRstCfg];
|
}
|
}
|
|
/**
|
This internal procedure will calculate PadRstCfg register value based
|
on provided GPIO Reset configuration for a certain pad.
|
|
@param[in] GpioPad GPIO Pad
|
@param[in] GpioResetConfig GPIO Reset configuration
|
@param[out] PadRstCfg GPIO PadRstCfg value
|
|
@retval EFI_SUCCESS The function completed successfully
|
@retval EFI_INVALID_PARAMETER Invalid configuration
|
**/
|
EFI_STATUS
|
GpioPadRstCfgFromResetConfig (
|
IN GPIO_PAD GpioPad,
|
IN GPIO_RESET_CONFIG GpioResetConfig,
|
OUT UINT32 *PadRstCfg
|
)
|
{
|
GPIO_GROUP Group;
|
|
Group = GpioGetGroupFromGpioPad (GpioPad);
|
|
switch (GpioResetConfig) {
|
case GpioResetDefault:
|
*PadRstCfg = 0x0;
|
break;
|
case GpioResetPwrGood: //old reset type
|
*PadRstCfg = V_PCH_GPIO_RST_CONF_POW_GOOD;
|
break;
|
case GpioResetDeep: //old reset type
|
case GpioHostDeepReset: //new reset type
|
*PadRstCfg = V_PCH_GPIO_RST_CONF_DEEP_RST;
|
break;
|
case GpioResetNormal: //old reset type
|
case GpioPlatformReset: //new reset type
|
*PadRstCfg = V_PCH_GPIO_RST_CONF_GPIO_RST;
|
break;
|
case GpioResetResume: //old reset type
|
if ((Group == GPIO_SKL_LP_GROUP_GPD) || (Group == GPIO_SKL_H_GROUP_GPD)) {
|
*PadRstCfg = V_PCH_GPIO_RST_CONF_RESUME_RST;
|
} else {
|
DEBUG ((DEBUG_ERROR, "GPIO ERROR: Only GPD group pads can use GpioResetResume (Group=%d, Pad=%d)!\n", GpioGetGroupIndexFromGpioPad (GpioPad), GpioGetPadNumberFromGpioPad (GpioPad)));
|
return EFI_INVALID_PARAMETER;
|
}
|
break;
|
case GpioResumeReset: //new reset type
|
if ((Group == GPIO_SKL_LP_GROUP_GPD) || (Group == GPIO_SKL_H_GROUP_GPD)) {
|
*PadRstCfg = V_PCH_GPIO_RST_CONF_RESUME_RST;
|
} else {
|
*PadRstCfg = V_PCH_GPIO_RST_CONF_POW_GOOD;
|
}
|
break;
|
case GpioDswReset: //new reset type
|
if ((Group == GPIO_SKL_LP_GROUP_GPD) || (Group == GPIO_SKL_H_GROUP_GPD)) {
|
*PadRstCfg = V_PCH_GPIO_RST_CONF_POW_GOOD;
|
} else {
|
DEBUG ((DEBUG_ERROR, "GPIO ERROR: Only GPD group pads can use GpioDswReset (Group=%d, Pad=%d)!\n", GpioGetGroupIndexFromGpioPad (GpioPad), GpioGetPadNumberFromGpioPad (GpioPad)));
|
return EFI_INVALID_PARAMETER;
|
}
|
break;
|
default:
|
ASSERT (FALSE);
|
break;
|
}
|
|
return EFI_SUCCESS;
|
}
|
|
/**
|
This internal procedure will get GPIO_CONFIG data from PADCFG registers value
|
|
@param[in] GpioPad GPIO Pad
|
@param[in] PadCfgDwReg PADCFG DWx register values
|
@param[out] GpioData GPIO Configuration data
|
|
@retval Status
|
**/
|
STATIC
|
VOID
|
GpioConfigFromPadCfgRegValue (
|
IN GPIO_PAD GpioPad,
|
IN CONST UINT32 *PadCfgDwReg,
|
OUT GPIO_CONFIG *GpioConfig
|
)
|
{
|
UINT32 PadRstCfg;
|
|
//
|
// Get Reset Type (PadRstCfg)
|
//
|
PadRstCfg = (PadCfgDwReg[0] & B_PCH_GPIO_RST_CONF) >> N_PCH_GPIO_RST_CONF;
|
|
GpioConfig->PowerConfig = GpioResetConfigFromPadRstCfg (
|
GpioPad,
|
PadRstCfg
|
);
|
|
//
|
// Get how interrupt is triggered (RxEvCfg)
|
//
|
GpioConfig->InterruptConfig = ((PadCfgDwReg[0] & B_PCH_GPIO_RX_LVL_EDG) >> (N_PCH_GPIO_RX_LVL_EDG - (N_GPIO_INT_CONFIG_INT_TYPE_BIT_POS + 1))) | (0x1 << N_GPIO_INT_CONFIG_INT_TYPE_BIT_POS);
|
|
//
|
// Get interrupt generation (GPIRoutIOxAPIC/SCI/SMI/NMI)
|
//
|
GpioConfig->InterruptConfig |= ((PadCfgDwReg[0] & (B_PCH_GPIO_RX_NMI_ROUTE | B_PCH_GPIO_RX_SCI_ROUTE | B_PCH_GPIO_RX_SMI_ROUTE | B_PCH_GPIO_RX_APIC_ROUTE)) >> (N_PCH_GPIO_RX_NMI_ROUTE - (N_GPIO_INT_CONFIG_INT_SOURCE_BIT_POS + 1))) | (0x1 << N_GPIO_INT_CONFIG_INT_SOURCE_BIT_POS);
|
|
//
|
// Get GPIO direction (GPIORxDis and GPIOTxDis)
|
//
|
GpioConfig->Direction = ((PadCfgDwReg[0] & (B_PCH_GPIO_RXDIS | B_PCH_GPIO_TXDIS)) >> (N_PCH_GPIO_TXDIS - (N_GPIO_DIRECTION_DIR_BIT_POS + 1))) | (0x1 << N_GPIO_DIRECTION_DIR_BIT_POS);
|
|
//
|
// Get GPIO input inversion (RXINV)
|
// (Only meaningful if input enabled)
|
//
|
if((PadCfgDwReg[0] & B_PCH_GPIO_RXDIS) == 0) {
|
GpioConfig->Direction |= ((PadCfgDwReg[0] & B_PCH_GPIO_RXINV) >> (N_PCH_GPIO_RXINV - (N_GPIO_DIRECTION_INV_BIT_POS + 1))) | (0x1 << N_GPIO_DIRECTION_INV_BIT_POS);
|
}
|
|
//
|
// Get GPIO output state (GPIOTxState)
|
//
|
GpioConfig->OutputState = ((PadCfgDwReg[0] & B_PCH_GPIO_TX_STATE) << (N_PCH_GPIO_TX_STATE + (N_GPIO_OUTPUT_BIT_POS + 1))) | (0x1 << N_GPIO_OUTPUT_BIT_POS);
|
|
//
|
// Configure GPIO RX raw override to '1' (RXRAW1)
|
//
|
GpioConfig->OtherSettings = ((PadCfgDwReg[0] & B_PCH_GPIO_RX_RAW1) >> (N_PCH_GPIO_RX_RAW1 - (N_GPIO_OTHER_CONFIG_RXRAW_BIT_POS + 1))) | (0x1 << N_GPIO_OTHER_CONFIG_RXRAW_BIT_POS);
|
|
//
|
// Get GPIO Pad Mode (PMode)
|
//
|
GpioConfig->PadMode = ((PadCfgDwReg[0] & B_PCH_GPIO_PAD_MODE) >> (N_PCH_GPIO_PAD_MODE - (N_GPIO_PAD_MODE_BIT_POS + 1))) | (0x1 << N_GPIO_PAD_MODE_BIT_POS);
|
|
//
|
// Get GPIO termination (Term)
|
//
|
GpioConfig->ElectricalConfig = ((PadCfgDwReg[1] & B_PCH_GPIO_TERM) >> (N_PCH_GPIO_TERM - (N_GPIO_ELECTRICAL_CONFIG_TERMINATION_BIT_POS + 1))) | (0x1 << N_GPIO_ELECTRICAL_CONFIG_TERMINATION_BIT_POS);
|
|
//
|
// Get GPIO pad tolerance (padtol)
|
//
|
GpioConfig->ElectricalConfig |= ((PadCfgDwReg[1] & B_PCH_GPIO_PADTOL) >> (N_PCH_GPIO_PADTOL - (N_GPIO_ELECTRICAL_CONFIG_1V8_TOLERANCE_BIT_POS + 1))) | (0x1 << N_GPIO_ELECTRICAL_CONFIG_1V8_TOLERANCE_BIT_POS);
|
}
|
|
/**
|
This procedure will read multiple GPIO settings
|
|
@param[in] GpioPad GPIO Pad
|
@param[out] GpioData GPIO data structure
|
|
@retval EFI_SUCCESS The function completed successfully
|
@retval EFI_INVALID_PARAMETER Invalid group or pad number
|
**/
|
EFI_STATUS
|
GpioGetPadConfig (
|
IN GPIO_PAD GpioPad,
|
OUT GPIO_CONFIG *GpioData
|
)
|
{
|
EFI_STATUS Status;
|
UINT32 PadCfgDwReg[2];
|
UINT32 RegVal;
|
GPIO_GROUP Group;
|
UINT32 PadNumber;
|
UINT32 PadBitPosition;
|
|
Group = GpioGetGroupFromGpioPad (GpioPad);
|
PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
|
PadBitPosition = GPIO_GET_PAD_POSITION (PadNumber);
|
|
if (!GpioIsPadValid (GpioPad)) {
|
ASSERT (FALSE);
|
return EFI_UNSUPPORTED;
|
}
|
|
if (!GpioIsPadHostOwned (GpioPad)) {
|
return EFI_UNSUPPORTED;
|
}
|
|
//
|
// Read PADCFG DW0 register
|
//
|
GpioReadPadCfgReg (
|
GpioPad,
|
0,
|
&PadCfgDwReg[0]
|
);
|
|
//
|
// Read PADCFG DW1 register
|
//
|
GpioReadPadCfgReg (
|
GpioPad,
|
1,
|
&PadCfgDwReg[1]
|
);
|
|
GpioConfigFromPadCfgRegValue (
|
GpioPad,
|
PadCfgDwReg,
|
GpioData
|
);
|
|
//
|
// Read HOSTSW_OWN registers
|
//
|
Status = GpioReadReg (
|
GpioHostOwnershipRegister,
|
Group,
|
GPIO_GET_DW_NUM (PadNumber),
|
&RegVal
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
//
|
// Get Host Software Ownership
|
//
|
GpioData->HostSoftPadOwn = (((RegVal >> PadBitPosition) & 0x1) << (N_GPIO_HOSTSW_OWN_BIT_POS + 1)) | (0x1 << N_GPIO_HOSTSW_OWN_BIT_POS);
|
|
//
|
// Read PADCFGLOCK register
|
//
|
Status = GpioReadReg (
|
GpioPadConfigLockRegister,
|
Group,
|
GPIO_GET_DW_NUM (PadNumber),
|
&RegVal
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
//
|
// Get Pad Configuration Lock state
|
//
|
GpioData->LockConfig = (((RegVal >> PadBitPosition) & 0x1) << 1) | 0x1;
|
|
//
|
// Read PADCFGLOCKTX register
|
//
|
Status = GpioReadReg (
|
GpioPadLockOutputRegister,
|
Group,
|
GPIO_GET_DW_NUM (PadNumber),
|
&RegVal
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
//
|
// Get Pad Configuration Lock Tx state
|
//
|
GpioData->LockConfig |= (((RegVal >> PadBitPosition) & 0x1) << 2) | 0x1;
|
|
return Status;
|
}
|
|
/**
|
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
|
)
|
{
|
EFI_STATUS Status;
|
UINT32 PadRstCfg;
|
|
//
|
// Configure Reset Type (PadRstCfg)
|
// Reset configuration depends on group type.
|
// This field requires support for new and deprecated settings.
|
//
|
Status = GpioPadRstCfgFromResetConfig (
|
GpioPad,
|
GpioConfig->PowerConfig,
|
&PadRstCfg
|
);
|
ASSERT_EFI_ERROR (Status);
|
|
PadCfgDwRegMask[0] |= ((((GpioConfig->PowerConfig & B_GPIO_RESET_CONFIG_RESET_MASK) >> N_GPIO_RESET_CONFIG_RESET_BIT_POS) == GpioHardwareDefault) ? 0x0 : B_PCH_GPIO_RST_CONF);
|
PadCfgDwReg[0] |= PadRstCfg << N_PCH_GPIO_RST_CONF;
|
|
//
|
// Configure how interrupt is triggered (RxEvCfg)
|
//
|
PadCfgDwRegMask[0] |= ((((GpioConfig->InterruptConfig & B_GPIO_INT_CONFIG_INT_TYPE_MASK) >> N_GPIO_INT_CONFIG_INT_TYPE_BIT_POS) == GpioHardwareDefault) ? 0x0 : B_PCH_GPIO_RX_LVL_EDG);
|
PadCfgDwReg[0] |= (((GpioConfig->InterruptConfig & B_GPIO_INT_CONFIG_INT_TYPE_MASK) >> (N_GPIO_INT_CONFIG_INT_TYPE_BIT_POS + 1)) << N_PCH_GPIO_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_PCH_GPIO_RX_NMI_ROUTE | B_PCH_GPIO_RX_SCI_ROUTE | B_PCH_GPIO_RX_SMI_ROUTE | B_PCH_GPIO_RX_APIC_ROUTE));
|
PadCfgDwReg[0] |= (((GpioConfig->InterruptConfig & B_GPIO_INT_CONFIG_INT_SOURCE_MASK) >> (N_GPIO_INT_CONFIG_INT_SOURCE_BIT_POS + 1)) << N_PCH_GPIO_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_PCH_GPIO_RXDIS | B_PCH_GPIO_TXDIS));
|
PadCfgDwReg[0] |= (((GpioConfig->Direction & B_GPIO_DIRECTION_DIR_MASK) >> (N_GPIO_DIRECTION_DIR_BIT_POS + 1)) << N_PCH_GPIO_TXDIS);
|
|
//
|
// Configure GPIO input inversion (RXINV)
|
//
|
PadCfgDwRegMask[0] |= ((((GpioConfig->Direction & B_GPIO_DIRECTION_INV_MASK) >> N_GPIO_DIRECTION_INV_BIT_POS) == GpioHardwareDefault) ? 0x0 : B_PCH_GPIO_RXINV);
|
PadCfgDwReg[0] |= (((GpioConfig->Direction & B_GPIO_DIRECTION_INV_MASK) >> (N_GPIO_DIRECTION_INV_BIT_POS + 1)) << N_PCH_GPIO_RXINV);
|
|
//
|
// Configure GPIO output state (GPIOTxState)
|
//
|
PadCfgDwRegMask[0] |= ((((GpioConfig->OutputState & B_GPIO_OUTPUT_MASK) >> N_GPIO_OUTPUT_BIT_POS) == GpioHardwareDefault) ? 0x0 : B_PCH_GPIO_TX_STATE);
|
PadCfgDwReg[0] |= (((GpioConfig->OutputState & B_GPIO_OUTPUT_MASK) >> (N_GPIO_OUTPUT_BIT_POS + 1)) << N_PCH_GPIO_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_PCH_GPIO_RX_RAW1);
|
PadCfgDwReg[0] |= (((GpioConfig->OtherSettings & B_GPIO_OTHER_CONFIG_RXRAW_MASK) >> (N_GPIO_OTHER_CONFIG_RXRAW_BIT_POS + 1)) << N_PCH_GPIO_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_PCH_GPIO_PAD_MODE);
|
PadCfgDwReg[0] |= (((GpioConfig->PadMode & B_GPIO_PAD_MODE_MASK) >> (N_GPIO_PAD_MODE_BIT_POS + 1)) << N_PCH_GPIO_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_PCH_GPIO_TERM);
|
PadCfgDwReg[1] |= (((GpioConfig->ElectricalConfig & B_GPIO_ELECTRICAL_CONFIG_TERMINATION_MASK) >> (N_GPIO_ELECTRICAL_CONFIG_TERMINATION_BIT_POS + 1)) << N_PCH_GPIO_TERM);
|
|
//
|
// Configure GPIO pad tolerance (padtol)
|
//
|
PadCfgDwRegMask[1] |= ((((GpioConfig->ElectricalConfig & B_GPIO_ELECTRICAL_CONFIG_1V8_TOLERANCE_MASK) >> N_GPIO_ELECTRICAL_CONFIG_1V8_TOLERANCE_BIT_POS) == GpioHardwareDefault) ? 0x0 : B_PCH_GPIO_PADTOL);
|
PadCfgDwReg[1] |= (((GpioConfig->ElectricalConfig & B_GPIO_ELECTRICAL_CONFIG_1V8_TOLERANCE_MASK) >> (N_GPIO_ELECTRICAL_CONFIG_1V8_TOLERANCE_BIT_POS + 1)) << N_PCH_GPIO_PADTOL);
|
|
return Status;
|
}
|
|
/**
|
This procedure will configure multiple GPIO settings
|
|
@param[in] GpioPad GPIO Pad
|
@param[in] GpioData GPIO data structure
|
|
@retval EFI_SUCCESS The function completed successfully
|
@retval EFI_INVALID_PARAMETER Invalid group or pad number
|
**/
|
EFI_STATUS
|
GpioSetPadConfig (
|
IN GPIO_PAD GpioPad,
|
IN GPIO_CONFIG *GpioData
|
)
|
{
|
EFI_STATUS Status;
|
UINT32 PadCfgDwReg[2];
|
UINT32 PadCfgDwRegMask[2];
|
UINT32 HostSoftOwnReg;
|
UINT32 HostSoftOwnRegMask;
|
UINT32 GpiGpeEnReg;
|
UINT32 GpiGpeEnRegMask;
|
UINT32 GpiNmiEnReg;
|
UINT32 GpiNmiEnRegMask;
|
GPIO_GROUP Group;
|
UINT32 GroupIndex;
|
UINT32 PadNumber;
|
UINT32 PadBitPosition;
|
UINT32 DwNum;
|
|
ZeroMem (PadCfgDwReg, sizeof (PadCfgDwReg));
|
ZeroMem (PadCfgDwRegMask, sizeof (PadCfgDwRegMask));
|
|
Group = GpioGetGroupFromGpioPad (GpioPad);
|
GroupIndex = GpioGetGroupIndexFromGpioPad (GpioPad);
|
PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
|
PadBitPosition = GPIO_GET_PAD_POSITION (PadNumber);
|
DwNum = GPIO_GET_DW_NUM (PadNumber);
|
|
if (!GpioIsPadValid (GpioPad)) {
|
ASSERT (FALSE);
|
return EFI_UNSUPPORTED;
|
}
|
|
if (!GpioIsPadHostOwned (GpioPad)) {
|
return EFI_UNSUPPORTED;
|
}
|
|
//
|
// Get GPIO PADCFG register value from GPIO config data
|
//
|
GpioPadCfgRegValueFromGpioConfig (
|
GpioPad,
|
GpioData,
|
PadCfgDwReg,
|
PadCfgDwRegMask
|
);
|
|
//
|
// Write PADCFG DW0 register
|
//
|
GpioWritePadCfgReg (
|
GpioPad,
|
0,
|
~PadCfgDwRegMask[0],
|
PadCfgDwReg[0]
|
);
|
|
//
|
// Write PADCFG DW1 register
|
//
|
GpioWritePadCfgReg (
|
GpioPad,
|
1,
|
~PadCfgDwRegMask[1],
|
PadCfgDwReg[1]
|
);
|
|
//
|
// Update value to be programmed in HOSTSW_OWN register
|
//
|
HostSoftOwnRegMask = (GpioData->HostSoftPadOwn & 0x1) << PadBitPosition;
|
HostSoftOwnReg = (GpioData->HostSoftPadOwn >> 0x1) << PadBitPosition;
|
|
//
|
// Write HOSTSW_OWN registers
|
//
|
Status = GpioWriteReg (
|
GpioHostOwnershipRegister,
|
Group,
|
DwNum,
|
~HostSoftOwnRegMask,
|
HostSoftOwnReg
|
);
|
ASSERT_EFI_ERROR (Status);
|
|
//
|
// Update value to be programmed in GPI_GPE_EN register
|
//
|
GpiGpeEnRegMask = (GpioData->InterruptConfig & 0x1) << PadBitPosition;
|
GpiGpeEnReg = ((GpioData->InterruptConfig & GpioIntSci) >> 3) << PadBitPosition;
|
|
//
|
// Write GPI_GPE_EN registers
|
//
|
Status = GpioWriteReg (
|
GpioGpeEnableRegister,
|
Group,
|
DwNum,
|
~GpiGpeEnRegMask,
|
GpiGpeEnReg
|
);
|
ASSERT_EFI_ERROR (Status);
|
|
//
|
// Update value to be programmed in GPI_NMI_EN register
|
//
|
GpiNmiEnRegMask = (GpioData->InterruptConfig & 0x1) << PadBitPosition;
|
GpiNmiEnReg = ((GpioData->InterruptConfig & GpioIntNmi) >> 1) << PadBitPosition;
|
|
Status = GpioWriteReg (
|
GpioNmiEnableRegister,
|
Group,
|
DwNum,
|
~GpiNmiEnRegMask,
|
GpiNmiEnReg
|
);
|
if (Status == EFI_UNSUPPORTED) {
|
if (GpiNmiEnReg == 0) {
|
//
|
// Not all GPIO have NMI capabilities. Since we always try to program this register,
|
// even when not enabling NMI for a pad so do not report such access as an error
|
//
|
Status = EFI_SUCCESS;
|
} else {
|
DEBUG ((DEBUG_ERROR, "GPIO ERROR: Group %d has no pads supporting NMI\n", GroupIndex));
|
ASSERT (FALSE);
|
return Status;
|
}
|
}
|
|
//
|
// Program Pad Configuration Lock
|
//
|
if ((GpioData->LockConfig & GpioPadConfigLock) == GpioPadConfigLock) {
|
GpioWriteLockReg (
|
GpioPadConfigLockRegister,
|
Group,
|
DwNum,
|
~0u,
|
1 << PadBitPosition
|
);
|
}
|
|
//
|
// Program Pad Configuration Lock Tx
|
//
|
if ((GpioData->LockConfig & GpioOutputStateLock) == GpioOutputStateLock) {
|
GpioWriteLockReg (
|
GpioPadLockOutputRegister,
|
Group,
|
DwNum,
|
~0u,
|
1 << PadBitPosition
|
);
|
}
|
return Status;
|
}
|
|
/**
|
This procedure will set GPIO output level
|
|
@param[in] GpioPad GPIO pad
|
@param[in] Value Output value
|
0: OutputLow, 1: OutputHigh
|
|
@retval EFI_SUCCESS The function completed successfully
|
@retval EFI_INVALID_PARAMETER Invalid GpioPad
|
**/
|
EFI_STATUS
|
GpioSetOutputValue (
|
IN GPIO_PAD GpioPad,
|
IN UINT32 Value
|
)
|
{
|
if (Value > 1) {
|
ASSERT (FALSE);
|
return EFI_INVALID_PARAMETER;
|
}
|
|
if (!GpioIsPadValid (GpioPad)) {
|
ASSERT (FALSE);
|
return EFI_INVALID_PARAMETER;
|
}
|
|
if (!GpioIsPadHostOwned (GpioPad)) {
|
return EFI_UNSUPPORTED;
|
}
|
|
GpioWritePadCfgReg (
|
GpioPad,
|
0,
|
(UINT32)~B_PCH_GPIO_TX_STATE,
|
Value << N_PCH_GPIO_TX_STATE
|
);
|
|
return EFI_SUCCESS;
|
}
|
|
/**
|
This procedure will get GPIO output level
|
|
@param[in] GpioPad GPIO pad
|
@param[out] OutputVal GPIO Output value
|
0: OutputLow, 1: OutputHigh
|
|
@retval EFI_SUCCESS The function completed successfully
|
@retval EFI_INVALID_PARAMETER Invalid GpioPad
|
**/
|
EFI_STATUS
|
GpioGetOutputValue (
|
IN GPIO_PAD GpioPad,
|
OUT UINT32 *OutputVal
|
)
|
{
|
UINT32 PadCfgReg;
|
|
if (!GpioIsPadValid (GpioPad)) {
|
ASSERT (FALSE);
|
return EFI_INVALID_PARAMETER;
|
}
|
|
if (!GpioIsPadHostOwned (GpioPad)) {
|
return EFI_UNSUPPORTED;
|
}
|
|
GpioReadPadCfgReg (
|
GpioPad,
|
0,
|
&PadCfgReg
|
);
|
|
*OutputVal = (PadCfgReg & B_PCH_GPIO_TX_STATE) >> N_PCH_GPIO_TX_STATE;
|
|
return EFI_SUCCESS;
|
}
|
|
/**
|
This procedure will get GPIO input level
|
|
@param[in] GpioPad GPIO pad
|
@param[out] InputVal GPIO Input value
|
0: InputLow, 1: InpuHigh
|
|
@retval EFI_SUCCESS The function completed successfully
|
@retval EFI_INVALID_PARAMETER Invalid GpioPad
|
**/
|
EFI_STATUS
|
GpioGetInputValue (
|
IN GPIO_PAD GpioPad,
|
OUT UINT32 *InputVal
|
)
|
{
|
UINT32 PadCfgReg;
|
|
if (!GpioIsPadValid (GpioPad)) {
|
ASSERT (FALSE);
|
return EFI_INVALID_PARAMETER;
|
}
|
|
if (!GpioIsPadHostOwned (GpioPad)) {
|
return EFI_UNSUPPORTED;
|
}
|
|
GpioReadPadCfgReg (
|
GpioPad,
|
0,
|
&PadCfgReg
|
);
|
|
*InputVal = (PadCfgReg & B_PCH_GPIO_RX_STATE) >> N_PCH_GPIO_RX_STATE;
|
|
return EFI_SUCCESS;
|
}
|
|
/**
|
This procedure will get GPIO IOxAPIC interrupt number
|
|
@param[in] GpioPad GPIO pad
|
@param[out] IrqNum IRQ number
|
|
@retval EFI_SUCCESS The function completed successfully
|
@retval EFI_INVALID_PARAMETER Invalid GpioPad
|
**/
|
EFI_STATUS
|
GpioGetPadIoApicIrqNumber (
|
IN GPIO_PAD GpioPad,
|
OUT UINT32 *IrqNum
|
)
|
{
|
UINT32 PadCfgReg;
|
|
if (!GpioIsPadValid (GpioPad)) {
|
ASSERT (FALSE);
|
return EFI_INVALID_PARAMETER;
|
}
|
|
if (!GpioIsPadHostOwned (GpioPad)) {
|
return EFI_UNSUPPORTED;
|
}
|
|
GpioReadPadCfgReg (
|
GpioPad,
|
1,
|
&PadCfgReg
|
);
|
|
*IrqNum = (PadCfgReg & B_PCH_GPIO_INTSEL) >> N_PCH_GPIO_INTSEL;
|
|
return EFI_SUCCESS;
|
}
|
|
/**
|
This procedure will configure GPIO input inversion
|
|
@param[in] GpioPad GPIO pad
|
@param[in] Value Value for GPIO input inversion
|
0: No input inversion, 1: Invert input
|
|
@retval EFI_SUCCESS The function completed successfully
|
@retval EFI_INVALID_PARAMETER Invalid GpioPad
|
**/
|
EFI_STATUS
|
GpioSetInputInversion (
|
IN GPIO_PAD GpioPad,
|
IN UINT32 Value
|
)
|
{
|
if (Value > 1) {
|
ASSERT (FALSE);
|
return EFI_INVALID_PARAMETER;
|
}
|
|
if (!GpioIsPadValid (GpioPad)) {
|
ASSERT (FALSE);
|
return EFI_INVALID_PARAMETER;
|
}
|
|
if (!GpioIsPadHostOwned (GpioPad)) {
|
return EFI_UNSUPPORTED;
|
}
|
|
GpioWritePadCfgReg (
|
GpioPad,
|
0,
|
(UINT32)~B_PCH_GPIO_RXINV,
|
Value << N_PCH_GPIO_RXINV
|
);
|
|
return EFI_SUCCESS;
|
}
|
|
/**
|
This procedure will get GPIO pad input inversion value
|
|
@param[in] GpioPad GPIO pad
|
@param[out] InvertState GPIO inversion state
|
0: No input inversion, 1: Inverted input
|
|
@retval EFI_SUCCESS The function completed successfully
|
@retval EFI_INVALID_PARAMETER Invalid GpioPad
|
**/
|
EFI_STATUS
|
GpioGetInputInversion (
|
IN GPIO_PAD GpioPad,
|
OUT UINT32 *InvertState
|
)
|
{
|
UINT32 PadCfgReg;
|
|
if (!GpioIsPadValid (GpioPad)) {
|
ASSERT (FALSE);
|
return EFI_INVALID_PARAMETER;
|
}
|
|
if (!GpioIsPadHostOwned (GpioPad)) {
|
return EFI_UNSUPPORTED;
|
}
|
|
GpioReadPadCfgReg (
|
GpioPad,
|
0,
|
&PadCfgReg
|
);
|
|
*InvertState = (PadCfgReg & B_PCH_GPIO_RXINV) >> N_PCH_GPIO_RXINV;
|
return EFI_SUCCESS;
|
}
|
|
/**
|
This procedure will set GPIO interrupt settings
|
|
@param[in] GpioPad GPIO pad
|
@param[in] Value Value of Level/Edge
|
use GPIO_INT_CONFIG as argument
|
|
@retval EFI_SUCCESS The function completed successfully
|
@retval EFI_INVALID_PARAMETER Invalid GpioPad
|
**/
|
EFI_STATUS
|
GpioSetPadInterruptConfig (
|
IN GPIO_PAD GpioPad,
|
IN GPIO_INT_CONFIG Value
|
)
|
{
|
EFI_STATUS Status;
|
UINT32 RxLvlEdgeValue;
|
UINT32 IntRouteValue;
|
UINT32 PadNumber;
|
UINT32 GpeEnable;
|
UINT32 NmiEnable;
|
|
if (!GpioIsPadValid (GpioPad)) {
|
ASSERT (FALSE);
|
return EFI_INVALID_PARAMETER;
|
}
|
|
if (!GpioIsPadHostOwned (GpioPad)) {
|
return EFI_UNSUPPORTED;
|
}
|
|
Status = EFI_SUCCESS;
|
|
if (((Value & B_GPIO_INT_CONFIG_INT_TYPE_MASK) >> N_GPIO_INT_CONFIG_INT_TYPE_BIT_POS) != GpioHardwareDefault) {
|
RxLvlEdgeValue = ((Value & B_GPIO_INT_CONFIG_INT_TYPE_MASK) >> (N_GPIO_INT_CONFIG_INT_TYPE_BIT_POS + 1)) << N_PCH_GPIO_RX_LVL_EDG;
|
|
GpioWritePadCfgReg (
|
GpioPad,
|
0,
|
(UINT32)~B_PCH_GPIO_RX_LVL_EDG,
|
RxLvlEdgeValue
|
);
|
}
|
|
if (((Value & B_GPIO_INT_CONFIG_INT_SOURCE_MASK) >> N_GPIO_INT_CONFIG_INT_SOURCE_BIT_POS) != GpioHardwareDefault) {
|
|
IntRouteValue = ((Value & B_GPIO_INT_CONFIG_INT_SOURCE_MASK) >> (N_GPIO_INT_CONFIG_INT_SOURCE_BIT_POS + 1)) << N_PCH_GPIO_RX_NMI_ROUTE;
|
|
GpioWritePadCfgReg (
|
GpioPad,
|
0,
|
(UINT32)~(B_PCH_GPIO_RX_NMI_ROUTE | B_PCH_GPIO_RX_SCI_ROUTE | B_PCH_GPIO_RX_SMI_ROUTE | B_PCH_GPIO_RX_APIC_ROUTE),
|
IntRouteValue
|
);
|
|
if ((Value & GpioIntSci) == GpioIntSci) {
|
GpeEnable = 0x1;
|
} else {
|
GpeEnable = 0x0;
|
}
|
|
PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
|
|
Status = GpioWriteReg (
|
GpioGpeEnableRegister,
|
GpioGetGroupFromGpioPad (GpioPad),
|
GPIO_GET_DW_NUM (PadNumber),
|
~(1 << GPIO_GET_PAD_POSITION (PadNumber)),
|
GpeEnable << GPIO_GET_PAD_POSITION (PadNumber)
|
);
|
ASSERT_EFI_ERROR (Status);
|
|
if ((Value & GpioIntNmi) == GpioIntNmi) {
|
NmiEnable = 0x1;
|
} else {
|
NmiEnable = 0x0;
|
}
|
|
Status = GpioWriteReg (
|
GpioNmiEnableRegister,
|
GpioGetGroupFromGpioPad (GpioPad),
|
GPIO_GET_DW_NUM (PadNumber),
|
~(1 << GPIO_GET_PAD_POSITION (PadNumber)),
|
NmiEnable << GPIO_GET_PAD_POSITION (PadNumber)
|
);
|
if (Status == EFI_UNSUPPORTED) {
|
if (NmiEnable == 0) {
|
//
|
// Not all GPIO have NMI capabilities. Since we always try to program this register,
|
// even when not enabling NMI for a pad so do not report such access as an error
|
//
|
return EFI_SUCCESS;
|
} else {
|
DEBUG ((DEBUG_ERROR, "GPIO ERROR: Group %d has no pads supporting NMI\n", GpioGetGroupIndexFromGpioPad (GpioPad)));
|
}
|
}
|
ASSERT_EFI_ERROR (Status);
|
}
|
|
return Status;
|
}
|
|
/**
|
This procedure will set GPIO electrical settings
|
|
@param[in] GpioPad GPIO pad
|
@param[in] Value Value of termination
|
use GPIO_ELECTRICAL_CONFIG as argument
|
|
@retval EFI_SUCCESS The function completed successfully
|
@retval EFI_INVALID_PARAMETER Invalid GpioPad
|
**/
|
EFI_STATUS
|
GpioSetPadElectricalConfig (
|
IN GPIO_PAD GpioPad,
|
IN GPIO_ELECTRICAL_CONFIG Value
|
)
|
{
|
UINT32 TermValue;
|
UINT32 PadTolValue;
|
|
if (!GpioIsPadValid (GpioPad)) {
|
ASSERT (FALSE);
|
return EFI_INVALID_PARAMETER;
|
}
|
|
if (!GpioIsPadHostOwned (GpioPad)) {
|
return EFI_UNSUPPORTED;
|
}
|
|
if (((Value & B_GPIO_ELECTRICAL_CONFIG_TERMINATION_MASK) >> N_GPIO_ELECTRICAL_CONFIG_TERMINATION_BIT_POS) != GpioHardwareDefault) {
|
TermValue = ((Value & B_GPIO_ELECTRICAL_CONFIG_TERMINATION_MASK) >> (N_GPIO_ELECTRICAL_CONFIG_TERMINATION_BIT_POS + 1)) << N_PCH_GPIO_TERM;
|
|
GpioWritePadCfgReg (
|
GpioPad,
|
1,
|
(UINT32)~B_PCH_GPIO_TERM,
|
TermValue
|
);
|
}
|
|
if (((Value & B_GPIO_ELECTRICAL_CONFIG_1V8_TOLERANCE_MASK) >> N_GPIO_ELECTRICAL_CONFIG_1V8_TOLERANCE_BIT_POS) != GpioHardwareDefault) {
|
PadTolValue = ((Value & B_GPIO_ELECTRICAL_CONFIG_1V8_TOLERANCE_MASK) >> (N_GPIO_ELECTRICAL_CONFIG_1V8_TOLERANCE_BIT_POS + 1)) << N_PCH_GPIO_PADTOL;
|
|
GpioWritePadCfgReg (
|
GpioPad,
|
1,
|
(UINT32)~B_PCH_GPIO_PADTOL,
|
PadTolValue
|
);
|
}
|
return EFI_SUCCESS;
|
}
|
|
/**
|
This procedure will set GPIO Reset settings
|
|
@param[in] GpioPad GPIO pad
|
@param[in] Value Value for Pad Reset Configuration
|
use GPIO_RESET_CONFIG as argument
|
|
@retval EFI_SUCCESS The function completed successfully
|
@retval EFI_INVALID_PARAMETER Invalid GpioPad
|
**/
|
EFI_STATUS
|
GpioSetPadResetConfig (
|
IN GPIO_PAD GpioPad,
|
IN GPIO_RESET_CONFIG Value
|
)
|
{
|
EFI_STATUS Status;
|
UINT32 PadRstCfg;
|
|
Status = EFI_SUCCESS;
|
|
if (!GpioIsPadValid (GpioPad)) {
|
ASSERT (FALSE);
|
return EFI_INVALID_PARAMETER;
|
}
|
|
if (!GpioIsPadHostOwned (GpioPad)) {
|
return EFI_UNSUPPORTED;
|
}
|
|
if (((Value & B_GPIO_RESET_CONFIG_RESET_MASK) >> N_GPIO_RESET_CONFIG_RESET_BIT_POS) != GpioHardwareDefault) {
|
|
//
|
// Reset configuration depends on group type.
|
// This field requires support for new and deprecated settings.
|
//
|
Status = GpioPadRstCfgFromResetConfig (
|
GpioPad,
|
Value,
|
&PadRstCfg
|
);
|
ASSERT_EFI_ERROR (Status);
|
|
GpioWritePadCfgReg (
|
GpioPad,
|
0,
|
(UINT32)~B_PCH_GPIO_RST_CONF,
|
PadRstCfg << N_PCH_GPIO_RST_CONF
|
);
|
}
|
return Status;
|
}
|
|
/**
|
This procedure will get GPIO Reset settings
|
|
@param[in] GpioPad GPIO pad
|
@param[in] Value Value of Pad Reset Configuration
|
based on GPIO_RESET_CONFIG
|
|
@retval EFI_SUCCESS The function completed successfully
|
@retval EFI_INVALID_PARAMETER Invalid GpioPad
|
**/
|
EFI_STATUS
|
GpioGetPadResetConfig (
|
IN GPIO_PAD GpioPad,
|
IN GPIO_RESET_CONFIG *Value
|
)
|
{
|
UINT32 PadRstCfg;
|
UINT32 PadCfgDw0Reg;
|
|
if (!GpioIsPadValid (GpioPad)) {
|
ASSERT (FALSE);
|
return EFI_INVALID_PARAMETER;
|
}
|
|
if (!GpioIsPadHostOwned (GpioPad)) {
|
return EFI_UNSUPPORTED;
|
}
|
|
GpioReadPadCfgReg (
|
GpioPad,
|
0,
|
&PadCfgDw0Reg
|
);
|
|
//
|
// Get Reset Type (PadRstCfg)
|
//
|
PadRstCfg = (PadCfgDw0Reg & B_PCH_GPIO_RST_CONF) >> N_PCH_GPIO_RST_CONF;
|
|
*Value = GpioResetConfigFromPadRstCfg (
|
GpioPad,
|
PadRstCfg
|
);
|
|
return EFI_SUCCESS;
|
}
|
|
/**
|
This procedure will get GPIO Host Software Pad Ownership for certain group
|
|
@param[in] Group GPIO group
|
@param[in] DwNum Host Ownership register number for current group.
|
For group which has less then 32 pads per group DwNum must be 0.
|
@param[out] HostSwRegVal Value of Host Software Pad Ownership register
|
Bit position - PadNumber
|
Bit value - 0: ACPI Mode, 1: GPIO Driver mode
|
|
@retval EFI_SUCCESS The function completed successfully
|
@retval EFI_INVALID_PARAMETER Invalid group or DwNum parameter number
|
**/
|
EFI_STATUS
|
GpioGetHostSwOwnershipForGroupDw (
|
IN GPIO_GROUP Group,
|
IN UINT32 DwNum,
|
OUT UINT32 *HostSwRegVal
|
)
|
{
|
EFI_STATUS Status;
|
|
if (!GpioIsGroupAndDwNumValid (Group, DwNum)) {
|
ASSERT (FALSE);
|
return EFI_INVALID_PARAMETER;
|
}
|
|
Status = GpioReadReg (
|
GpioHostOwnershipRegister,
|
Group,
|
DwNum,
|
HostSwRegVal
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
return Status;
|
}
|
|
/**
|
This procedure will get GPIO Host Software Pad Ownership for certain group
|
|
@param[in] Group GPIO group
|
@param[in] DwNum Host Ownership register number for current group
|
For group which has less then 32 pads per group DwNum must be 0.
|
@param[in] HostSwRegVal Value of Host Software Pad Ownership register
|
Bit position - PadNumber
|
Bit value - 0: ACPI Mode, 1: GPIO Driver mode
|
|
@retval EFI_SUCCESS The function completed successfully
|
@retval EFI_INVALID_PARAMETER Invalid group or DwNum parameter number
|
**/
|
EFI_STATUS
|
GpioSetHostSwOwnershipForGroupDw (
|
IN GPIO_GROUP Group,
|
IN UINT32 DwNum,
|
IN UINT32 HostSwRegVal
|
)
|
{
|
EFI_STATUS Status;
|
|
if (!GpioIsGroupAndDwNumValid (Group, DwNum)) {
|
ASSERT (FALSE);
|
return EFI_INVALID_PARAMETER;
|
}
|
|
Status = GpioWriteReg (
|
GpioHostOwnershipRegister,
|
Group,
|
DwNum,
|
0,
|
HostSwRegVal
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
return Status;
|
}
|
|
/**
|
This procedure will get Gpio Pad Host Software Ownership
|
|
@param[in] GpioPad GPIO pad
|
@param[out] PadHostSwOwn Value of Host Software Pad Owner
|
0: ACPI Mode, 1: GPIO Driver mode
|
|
@retval EFI_SUCCESS The function completed successfully
|
@retval EFI_INVALID_PARAMETER Invalid GpioPad
|
**/
|
EFI_STATUS
|
GpioGetHostSwOwnershipForPad (
|
IN GPIO_PAD GpioPad,
|
OUT UINT32 *PadHostSwOwn
|
)
|
{
|
EFI_STATUS Status;
|
UINT32 PadNumber;
|
UINT32 HostSwRegVal;
|
|
if (!GpioIsPadValid (GpioPad)) {
|
ASSERT (FALSE);
|
return EFI_INVALID_PARAMETER;
|
}
|
|
PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
|
|
Status = GpioReadReg (
|
GpioHostOwnershipRegister,
|
GpioGetGroupFromGpioPad (GpioPad),
|
GPIO_GET_DW_NUM (PadNumber),
|
&HostSwRegVal
|
);
|
ASSERT_EFI_ERROR (Status);
|
|
*PadHostSwOwn = (HostSwRegVal >> GPIO_GET_PAD_POSITION (PadNumber)) & 0x1;
|
|
return Status;
|
}
|
|
/**
|
This procedure will set Gpio Pad Host Software Ownership
|
|
@param[in] GpioPad GPIO pad
|
@param[in] PadHostSwOwn Pad Host Software Owner
|
0: ACPI Mode, 1: GPIO Driver mode
|
|
@retval EFI_SUCCESS The function completed successfully
|
@retval EFI_INVALID_PARAMETER Invalid GpioPad
|
**/
|
EFI_STATUS
|
GpioSetHostSwOwnershipForPad (
|
IN GPIO_PAD GpioPad,
|
IN UINT32 PadHostSwOwn
|
)
|
{
|
EFI_STATUS Status;
|
UINT32 PadNumber;
|
|
if (!GpioIsPadValid (GpioPad)) {
|
ASSERT (FALSE);
|
return EFI_INVALID_PARAMETER;
|
}
|
|
PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
|
|
Status = GpioWriteReg (
|
GpioHostOwnershipRegister,
|
GpioGetGroupFromGpioPad (GpioPad),
|
GPIO_GET_DW_NUM (PadNumber),
|
~0u,
|
1 << GPIO_GET_PAD_POSITION (PadNumber)
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
return Status;
|
}
|
|
/**
|
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;
|
GPIO_GROUP_INFO *GpioGroupInfo;
|
UINTN GpioGroupInfoLength;
|
UINT32 PadOwnRegValue;
|
|
if (!GpioIsPadValid (GpioPad)) {
|
ASSERT (FALSE);
|
return EFI_INVALID_PARAMETER;
|
}
|
|
GroupIndex = GpioGetGroupIndexFromGpioPad (GpioPad);
|
PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
|
|
GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
|
|
//
|
// Calculate RegOffset using Pad Ownership offset and GPIO Pad number.
|
// One DWord register contains information for 8 pads.
|
//
|
RegOffset = GpioGroupInfo[GroupIndex].PadOwnOffset + (PadNumber >> 3) * 0x4;
|
|
//
|
// Calculate pad bit position within DWord register
|
//
|
PadNumber %= 8;
|
Mask = (BIT1 | BIT0) << (PadNumber * 4);
|
|
PadOwnRegValue = MmioRead32 (PCH_PCR_ADDRESS (GpioGroupInfo[GroupIndex].Community, RegOffset));
|
|
*PadOwnVal = (GPIO_PAD_OWN) ((PadOwnRegValue & Mask) >> (PadNumber * 4));
|
|
return EFI_SUCCESS;
|
}
|
|
/**
|
This procedure will check state of Pad Config Lock for pads within one group
|
|
@param[in] Group GPIO group
|
@param[in] DwNum PadCfgLock register number for current group.
|
For group which has less then 32 pads per group DwNum must be 0.
|
@param[out] PadCfgLockRegVal Value of PadCfgLock register
|
Bit position - PadNumber
|
Bit value - 0: NotLocked, 1: Locked
|
|
@retval EFI_SUCCESS The function completed successfully
|
@retval EFI_INVALID_PARAMETER Invalid group or DwNum parameter number
|
**/
|
EFI_STATUS
|
GpioGetPadCfgLockForGroupDw (
|
IN GPIO_GROUP Group,
|
IN UINT32 DwNum,
|
OUT UINT32 *PadCfgLockRegVal
|
)
|
{
|
EFI_STATUS Status;
|
|
if (!GpioIsGroupAndDwNumValid (Group, DwNum)) {
|
ASSERT (FALSE);
|
return EFI_INVALID_PARAMETER;
|
}
|
|
Status = GpioReadReg (
|
GpioPadConfigLockRegister,
|
Group,
|
DwNum,
|
PadCfgLockRegVal
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
return Status;
|
}
|
|
/**
|
This procedure will check state of Pad Config Lock for selected pad
|
|
@param[in] GpioPad GPIO pad
|
@param[out] PadCfgLock PadCfgLock for selected pad
|
0: NotLocked, 1: Locked
|
|
@retval EFI_SUCCESS The function completed successfully
|
@retval EFI_INVALID_PARAMETER Invalid GpioPad
|
**/
|
EFI_STATUS
|
GpioGetPadCfgLock (
|
IN GPIO_PAD GpioPad,
|
OUT UINT32 *PadCfgLock
|
)
|
{
|
EFI_STATUS Status;
|
UINT32 PadNumber;
|
UINT32 PadCfgLockRegVal;
|
|
if (!GpioIsPadValid (GpioPad)) {
|
ASSERT (FALSE);
|
return EFI_INVALID_PARAMETER;
|
}
|
|
PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
|
|
Status = GpioReadReg (
|
GpioPadConfigLockRegister,
|
GpioGetGroupFromGpioPad (GpioPad),
|
GPIO_GET_DW_NUM (PadNumber),
|
&PadCfgLockRegVal
|
);
|
ASSERT_EFI_ERROR (Status);
|
|
*PadCfgLock = (PadCfgLockRegVal >> GPIO_GET_PAD_POSITION (PadNumber)) & 0x1;
|
|
return Status;
|
}
|
|
/**
|
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
|
)
|
{
|
EFI_STATUS Status;
|
|
if (!GpioIsGroupAndDwNumValid (Group, DwNum)) {
|
ASSERT (FALSE);
|
return EFI_INVALID_PARAMETER;
|
}
|
|
Status = GpioReadReg (
|
GpioPadLockOutputRegister,
|
Group,
|
DwNum,
|
PadCfgLockTxRegVal
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
return Status;
|
}
|
|
/**
|
This procedure will check state of Pad Config Tx Lock for selected pad
|
|
@param[in] GpioPad GPIO pad
|
@param[out] PadCfgLock PadCfgLockTx for selected pad
|
0: NotLockedTx, 1: LockedTx
|
|
@retval EFI_SUCCESS The function completed successfully
|
@retval EFI_INVALID_PARAMETER Invalid GpioPad
|
**/
|
EFI_STATUS
|
GpioGetPadCfgLockTx (
|
IN GPIO_PAD GpioPad,
|
OUT UINT32 *PadCfgLockTx
|
)
|
{
|
EFI_STATUS Status;
|
UINT32 PadNumber;
|
UINT32 PadCfgLockTxRegVal;
|
|
if (!GpioIsPadValid (GpioPad)) {
|
ASSERT (FALSE);
|
return EFI_INVALID_PARAMETER;
|
}
|
|
PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
|
|
Status = GpioReadReg (
|
GpioPadLockOutputRegister,
|
GpioGetGroupFromGpioPad (GpioPad),
|
GPIO_GET_DW_NUM (PadNumber),
|
&PadCfgLockTxRegVal
|
);
|
ASSERT_EFI_ERROR (Status);
|
|
*PadCfgLockTx = (PadCfgLockTxRegVal >> GPIO_GET_PAD_POSITION (PadNumber)) & 0x1;
|
|
return Status;
|
}
|
|
/**
|
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
|
)
|
{
|
EFI_STATUS Status;
|
|
if (!GpioIsGroupAndDwNumValid (Group, DwNum)) {
|
ASSERT (FALSE);
|
return EFI_INVALID_PARAMETER;
|
}
|
|
Status = GpioWriteLockReg (
|
GpioPadConfigLockRegister,
|
Group,
|
DwNum,
|
~PadsToUnlock,
|
0
|
);
|
ASSERT_EFI_ERROR (Status);
|
return Status;
|
}
|
|
/**
|
This procedure will clear PadCfgLock for selected pad.
|
This function should be used only inside SMI.
|
|
@param[in] GpioPad GPIO pad
|
|
@retval EFI_SUCCESS The function completed successfully
|
@retval EFI_INVALID_PARAMETER Invalid group or pad number
|
**/
|
EFI_STATUS
|
GpioUnlockPadCfg (
|
IN GPIO_PAD GpioPad
|
)
|
{
|
EFI_STATUS Status;
|
GPIO_GROUP Group;
|
UINT32 PadNumber;
|
|
Group = GpioGetGroupFromGpioPad (GpioPad);
|
PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
|
|
Status = GpioUnlockPadCfgForGroupDw (
|
Group,
|
GPIO_GET_DW_NUM (PadNumber),
|
1 << GPIO_GET_PAD_POSITION (PadNumber)
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
return Status;
|
}
|
|
/**
|
This procedure will set PadCfgLock for selected pads within one group
|
|
@param[in] Group GPIO group
|
@param[in] DwNum PadCfgLock register number for current group.
|
For group which has less then 32 pads per group DwNum must be 0.
|
@param[in] PadsToLock Bitmask for pads which are going to be locked
|
Bit position - PadNumber
|
Bit value - 0: DoNotLock, 1: Lock
|
|
@retval EFI_SUCCESS The function completed successfully
|
@retval EFI_INVALID_PARAMETER Invalid group or DwNum parameter number
|
**/
|
EFI_STATUS
|
GpioLockPadCfgForGroupDw (
|
IN GPIO_GROUP Group,
|
IN UINT32 DwNum,
|
IN UINT32 PadsToLock
|
)
|
{
|
EFI_STATUS Status;
|
|
if (!GpioIsGroupAndDwNumValid (Group, DwNum)) {
|
ASSERT (FALSE);
|
return EFI_INVALID_PARAMETER;
|
}
|
|
Status = GpioWriteLockReg (
|
GpioPadConfigLockRegister,
|
Group,
|
DwNum,
|
~0u,
|
PadsToLock
|
);
|
ASSERT_EFI_ERROR (Status);
|
return Status;
|
}
|
|
/**
|
This procedure will set PadCfgLock for selected pad
|
|
@param[in] GpioPad GPIO pad
|
|
@retval EFI_SUCCESS The function completed successfully
|
@retval EFI_INVALID_PARAMETER Invalid group or pad number
|
**/
|
EFI_STATUS
|
GpioLockPadCfg (
|
IN GPIO_PAD GpioPad
|
)
|
{
|
EFI_STATUS Status;
|
GPIO_GROUP Group;
|
UINT32 PadNumber;
|
|
Group = GpioGetGroupFromGpioPad (GpioPad);
|
PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
|
|
Status = GpioLockPadCfgForGroupDw (
|
Group,
|
GPIO_GET_DW_NUM (PadNumber),
|
1 << GPIO_GET_PAD_POSITION (PadNumber)
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
return Status;
|
}
|
|
/**
|
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
|
)
|
{
|
EFI_STATUS Status;
|
|
if (!GpioIsGroupAndDwNumValid (Group, DwNum)) {
|
ASSERT (FALSE);
|
return EFI_INVALID_PARAMETER;
|
}
|
|
Status = GpioWriteLockReg (
|
GpioPadLockOutputRegister,
|
Group,
|
DwNum,
|
~PadsToUnlockTx,
|
0
|
);
|
ASSERT_EFI_ERROR (Status);
|
return Status;
|
}
|
|
/**
|
This procedure will clear PadCfgLockTx for selected pad.
|
This function should be used only inside SMI.
|
|
@param[in] GpioPad GPIO pad
|
|
@retval EFI_SUCCESS The function completed successfully
|
@retval EFI_INVALID_PARAMETER Invalid group or pad number
|
**/
|
EFI_STATUS
|
GpioUnlockPadCfgTx (
|
IN GPIO_PAD GpioPad
|
)
|
{
|
EFI_STATUS Status;
|
GPIO_GROUP Group;
|
UINT32 PadNumber;
|
|
Group = GpioGetGroupFromGpioPad (GpioPad);
|
PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
|
|
Status = GpioUnlockPadCfgTxForGroupDw (
|
Group,
|
GPIO_GET_DW_NUM (PadNumber),
|
1 << GPIO_GET_PAD_POSITION (PadNumber)
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
return Status;
|
}
|
|
/**
|
This procedure will set PadCfgLockTx for selected pads within one group
|
|
@param[in] Group GPIO group
|
@param[in] DwNum PadCfgLock register number for current group.
|
For group which has less then 32 pads per group DwNum must be 0.
|
@param[in] PadsToLockTx Bitmask for pads which are going to be locked,
|
Bit position - PadNumber
|
Bit value - 0: DoNotLockTx, 1: LockTx
|
|
@retval EFI_SUCCESS The function completed successfully
|
@retval EFI_INVALID_PARAMETER Invalid group or DwNum parameter number
|
**/
|
EFI_STATUS
|
GpioLockPadCfgTxForGroupDw (
|
IN GPIO_GROUP Group,
|
IN UINT32 DwNum,
|
IN UINT32 PadsToLockTx
|
)
|
{
|
EFI_STATUS Status;
|
|
if (!GpioIsGroupAndDwNumValid (Group, DwNum)) {
|
ASSERT (FALSE);
|
return EFI_INVALID_PARAMETER;
|
}
|
|
Status = GpioWriteLockReg (
|
GpioPadLockOutputRegister,
|
Group,
|
DwNum,
|
~0u,
|
PadsToLockTx
|
);
|
ASSERT_EFI_ERROR (Status);
|
return Status;
|
}
|
|
/**
|
This procedure will set PadCfgLockTx for selected pad
|
|
@param[in] GpioPad GPIO pad
|
|
@retval EFI_SUCCESS The function completed successfully
|
@retval EFI_INVALID_PARAMETER Invalid group or pad number
|
**/
|
EFI_STATUS
|
GpioLockPadCfgTx (
|
IN GPIO_PAD GpioPad
|
)
|
{
|
EFI_STATUS Status;
|
GPIO_GROUP Group;
|
UINT32 PadNumber;
|
|
Group = GpioGetGroupFromGpioPad (GpioPad);
|
PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
|
|
Status = GpioLockPadCfgTxForGroupDw (
|
Group,
|
GPIO_GET_DW_NUM (PadNumber),
|
1 << GPIO_GET_PAD_POSITION (PadNumber)
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
return Status;
|
}
|
|
|
/**
|
This procedure will get Group to GPE mapping.
|
|
@param[out] GroupToGpeDw0 GPIO group to be mapped to GPE_DW0
|
@param[out] GroupToGpeDw1 GPIO group to be mapped to GPE_DW1
|
@param[out] GroupToGpeDw2 GPIO group to be mapped to GPE_DW2
|
|
@retval EFI_SUCCESS The function completed successfully
|
@retval EFI_INVALID_PARAMETER Invalid group or pad number
|
**/
|
EFI_STATUS
|
GpioGetGroupToGpeDwX (
|
IN GPIO_GROUP *GroupToGpeDw0,
|
IN GPIO_GROUP *GroupToGpeDw1,
|
IN GPIO_GROUP *GroupToGpeDw2
|
)
|
{
|
UINT32 Data32;
|
UINT32 PchPwrmBase;
|
GPIO_GROUP GpioGroupOffset;
|
|
GpioGroupOffset = GpioGetLowestGroup ();
|
|
PchPwrmBaseGet (&PchPwrmBase);
|
|
Data32 = MmioRead32 ((UINTN) (PchPwrmBase + R_PCH_PWRM_GPIO_CFG));
|
|
*GroupToGpeDw0 = ((Data32 & B_PCH_PWRM_GPIO_CFG_GPE0_DW0) >> N_PCH_PWRM_GPIO_CFG_GPE0_DW0) + GpioGroupOffset;
|
*GroupToGpeDw1 = ((Data32 & B_PCH_PWRM_GPIO_CFG_GPE0_DW1) >> N_PCH_PWRM_GPIO_CFG_GPE0_DW1) + GpioGroupOffset;
|
*GroupToGpeDw2 = ((Data32 & B_PCH_PWRM_GPIO_CFG_GPE0_DW2) >> N_PCH_PWRM_GPIO_CFG_GPE0_DW2) + GpioGroupOffset;
|
|
return EFI_SUCCESS;
|
}
|
|
/**
|
This procedure will set Group to GPE mapping.
|
|
@param[in] GroupToGpeDw0 GPIO group to be mapped to GPE_DW0
|
@param[in] GroupToGpeDw1 GPIO group to be mapped to GPE_DW1
|
@param[in] GroupToGpeDw2 GPIO group to be mapped to GPE_DW2
|
|
@retval EFI_SUCCESS The function completed successfully
|
@retval EFI_INVALID_PARAMETER Invalid group or pad number
|
**/
|
EFI_STATUS
|
GpioSetGroupToGpeDwX (
|
IN GPIO_GROUP GroupToGpeDw0,
|
IN GPIO_GROUP GroupToGpeDw1,
|
IN GPIO_GROUP GroupToGpeDw2
|
)
|
{
|
UINT32 Data32Or;
|
UINT32 Data32And;
|
UINT32 PchPwrmBase;
|
GPIO_GROUP GpioGroupLowest;
|
GPIO_GROUP GpioGroupHighest;
|
|
GpioGroupLowest = GpioGetLowestGroup ();
|
GpioGroupHighest = GpioGetHighestGroup ();
|
|
//
|
// Check if group argument exceeds GPIO group range
|
//
|
if (((UINT32) GroupToGpeDw0 < GpioGroupLowest) || ((UINT32) GroupToGpeDw0 > GpioGroupHighest) ||
|
((UINT32) GroupToGpeDw1 < GpioGroupLowest) || ((UINT32) GroupToGpeDw1 > GpioGroupHighest) ||
|
((UINT32) GroupToGpeDw2 < GpioGroupLowest) || ((UINT32) GroupToGpeDw2 > GpioGroupHighest)) {
|
DEBUG ((DEBUG_ERROR, "GPIO ERROR: Group argument exceeds GPIO group range\n"));
|
return EFI_INVALID_PARAMETER;
|
}
|
|
//
|
// Check if each group number is unique
|
//
|
if ((GroupToGpeDw0 == GroupToGpeDw1) ||
|
(GroupToGpeDw0 == GroupToGpeDw2) ||
|
(GroupToGpeDw1 == GroupToGpeDw2)) {
|
return EFI_INVALID_PARAMETER;
|
}
|
|
//
|
// Values in GPE0_DWx registers are 0 based (GPP_A = 0h)
|
//
|
GroupToGpeDw0 = GpioGetGroupIndexFromGroup (GroupToGpeDw0);
|
GroupToGpeDw1 = GpioGetGroupIndexFromGroup (GroupToGpeDw1);
|
GroupToGpeDw2 = GpioGetGroupIndexFromGroup (GroupToGpeDw2);
|
|
PchPwrmBaseGet (&PchPwrmBase);
|
|
//
|
// Program GPIO_CFG (PMRMBASE + 120h) register
|
//
|
Data32And = (UINT32) ~(B_PCH_PWRM_GPIO_CFG_GPE0_DW2 | B_PCH_PWRM_GPIO_CFG_GPE0_DW1 | B_PCH_PWRM_GPIO_CFG_GPE0_DW0);
|
Data32Or = (UINT32) ((GroupToGpeDw2 << N_PCH_PWRM_GPIO_CFG_GPE0_DW2) |
|
(GroupToGpeDw1 << N_PCH_PWRM_GPIO_CFG_GPE0_DW1) |
|
(GroupToGpeDw0 << N_PCH_PWRM_GPIO_CFG_GPE0_DW0));
|
|
MmioAndThenOr32 (
|
(PchPwrmBase + R_PCH_PWRM_GPIO_CFG),
|
Data32And,
|
Data32Or
|
);
|
|
Data32And = (UINT32) ~(B_PCH_PCR_GPIO_MISCCFG_GPE0_DW2 | B_PCH_PCR_GPIO_MISCCFG_GPE0_DW1 | B_PCH_PCR_GPIO_MISCCFG_GPE0_DW0);
|
Data32Or = (UINT32) ((GroupToGpeDw2 << N_PCH_PCR_GPIO_MISCCFG_GPE0_DW2) |
|
(GroupToGpeDw1 << N_PCH_PCR_GPIO_MISCCFG_GPE0_DW1) |
|
(GroupToGpeDw0 << N_PCH_PCR_GPIO_MISCCFG_GPE0_DW0));
|
//
|
// Program MISCCFG register for Community 0
|
//
|
MmioAndThenOr32 (
|
PCH_PCR_ADDRESS (PID_GPIOCOM0, R_PCH_PCR_GPIO_MISCCFG),
|
Data32And,
|
Data32Or
|
);
|
|
//
|
// Program MISCCFG register for Community 1
|
//
|
MmioAndThenOr32 (
|
PCH_PCR_ADDRESS (PID_GPIOCOM1, R_PCH_PCR_GPIO_MISCCFG),
|
Data32And,
|
Data32Or
|
);
|
|
//
|
// Program MISCCFG register for Community 2
|
//
|
MmioAndThenOr32 (
|
PCH_PCR_ADDRESS (PID_GPIOCOM2, R_PCH_PCR_GPIO_MISCCFG),
|
Data32And,
|
Data32Or
|
);
|
|
//
|
// Program MISCCFG register for Community 3
|
//
|
MmioAndThenOr32 (
|
PCH_PCR_ADDRESS (PID_GPIOCOM3, R_PCH_PCR_GPIO_MISCCFG),
|
Data32And,
|
Data32Or
|
);
|
|
return EFI_SUCCESS;
|
}
|
|
/**
|
This procedure will get GPE number for provided GpioPad.
|
PCH allows to configure mapping between GPIO groups and related GPE (GpioSetGroupToGpeDwX())
|
what results in the fact that certain Pad can cause different General Purpose Event. Only three
|
GPIO groups can be mapped to cause unique GPE (1-tier), all others groups will be under one common
|
event (GPE_111 for 2-tier).
|
|
1-tier:
|
Returned GpeNumber is in range <0,95>. GpioGetGpeNumber() can be used
|
to determine what _LXX ACPI method would be called on event on selected GPIO pad
|
|
2-tier:
|
Returned GpeNumber is 0x6F (111). All GPIO pads which are not mapped to 1-tier GPE
|
will be under one master GPE_111 which is linked to _L6F ACPI method. If it is needed to determine
|
what Pad from 2-tier has caused the event, _L6F method should check GPI_GPE_STS and GPI_GPE_EN
|
registers for all GPIO groups not mapped to 1-tier GPE.
|
|
@param[in] GpioPad GPIO pad
|
@param[out] GpeNumber GPE number
|
|
@retval EFI_SUCCESS The function completed successfully
|
@retval EFI_INVALID_PARAMETER Invalid GpioPad
|
**/
|
EFI_STATUS
|
GpioGetGpeNumber (
|
IN GPIO_PAD GpioPad,
|
OUT UINT32 *GpeNumber
|
)
|
{
|
GPIO_GROUP GroupToGpeDw0;
|
GPIO_GROUP GroupToGpeDw1;
|
GPIO_GROUP GroupToGpeDw2;
|
GPIO_GROUP Group;
|
UINT32 PadNumber;
|
|
Group = GpioGetGroupFromGpioPad (GpioPad);
|
PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
|
|
if (!GpioIsPadValid (GpioPad)) {
|
ASSERT (FALSE);
|
return EFI_INVALID_PARAMETER;
|
}
|
|
//
|
// Get GPIO groups mapping to 1-tier GPE
|
// This mapping is dependent on GPIO IP implementation
|
// and may change between chipset generations
|
//
|
GpioGetGroupToGpeDwX (&GroupToGpeDw0,&GroupToGpeDw1,&GroupToGpeDw2);
|
|
if (Group == GroupToGpeDw0) {
|
*GpeNumber = PadNumber;
|
} else if (Group == GroupToGpeDw1) {
|
*GpeNumber = PadNumber + 32;
|
} else if (Group == GroupToGpeDw2) {
|
*GpeNumber = PadNumber + 64;
|
} else {
|
//
|
// If Group number doesn't match any of above then
|
// it means than certain pad is routed to 2-tier GPE
|
// which all are under GPE_111 (0x6F)
|
//
|
*GpeNumber = PCH_GPIO_2_TIER_MASTER_GPE_NUMBER;
|
}
|
|
return EFI_SUCCESS;
|
}
|
|
/**
|
This procedure is used to clear SMI STS for a specified Pad
|
|
@param[in] GpioPad GPIO pad
|
|
@retval EFI_SUCCESS The function completed successfully
|
@retval EFI_INVALID_PARAMETER Invalid GpioPad
|
**/
|
EFI_STATUS
|
GpioClearGpiSmiSts (
|
IN GPIO_PAD GpioPad
|
)
|
{
|
EFI_STATUS Status;
|
GPIO_GROUP Group;
|
UINT32 PadNumber;
|
UINT32 DwNum;
|
UINT32 PadBitPosition;
|
|
if (!GpioIsPadValid (GpioPad)) {
|
ASSERT (FALSE);
|
return EFI_UNSUPPORTED;
|
}
|
|
Group = GpioGetGroupFromGpioPad (GpioPad);
|
PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
|
DwNum = GPIO_GET_DW_NUM (PadNumber);
|
PadBitPosition = GPIO_GET_PAD_POSITION (PadNumber);
|
|
//
|
// Clear GPI SMI Status bit by writing '1'
|
//
|
Status = GpioWriteReg (
|
GpioSmiStatusRegister,
|
Group,
|
DwNum,
|
0u,
|
(UINT32) (BIT0 << PadBitPosition)
|
);
|
|
return Status;
|
}
|
|
/**
|
This procedure is used by PchSmiDispatcher and will clear
|
all GPI SMI Status bits
|
|
@retval EFI_SUCCESS The function completed successfully
|
@retval EFI_INVALID_PARAMETER Invalid group or pad number
|
**/
|
EFI_STATUS
|
GpioClearAllGpiSmiSts (
|
VOID
|
)
|
{
|
UINT32 DwNum;
|
GPIO_GROUP Group;
|
GPIO_GROUP GroupMin;
|
GPIO_GROUP GroupMax;
|
|
GroupMin = GpioGetLowestGroup ();
|
GroupMax = GpioGetHighestGroup ();
|
|
for (Group = GroupMin; Group <= GroupMax; Group++) {
|
//
|
// Disable all GPI SMI
|
//
|
for (DwNum = 0; DwNum <= GPIO_GET_DW_NUM (GpioGetPadPerGroup (Group)); DwNum++) {
|
GpioWriteReg (
|
GpioSmiStatusRegister,
|
Group,
|
DwNum,
|
0u,
|
0xFFFFFFFF
|
);
|
}
|
}
|
return EFI_SUCCESS;
|
|
}
|
|
/**
|
This procedure is used to disable all GPI SMI
|
|
@retval EFI_SUCCESS The function completed successfully
|
@retval EFI_INVALID_PARAMETER Invalid group or pad number
|
**/
|
EFI_STATUS
|
GpioDisableAllGpiSmi (
|
VOID
|
)
|
{
|
UINT32 DwNum;
|
GPIO_GROUP Group;
|
GPIO_GROUP GroupMin;
|
GPIO_GROUP GroupMax;
|
|
GroupMin = GpioGetLowestGroup ();
|
GroupMax = GpioGetHighestGroup ();
|
|
for (Group = GroupMin; Group <= GroupMax; Group++) {
|
//
|
// Disable all GPI SMI
|
//
|
for (DwNum = 0; DwNum <= GPIO_GET_DW_NUM (GpioGetPadPerGroup (Group)); DwNum++) {
|
GpioWriteReg (
|
GpioSmiEnableRegister,
|
Group,
|
DwNum,
|
0u,
|
0u
|
);
|
}
|
}
|
return EFI_SUCCESS;
|
}
|
|
/**
|
This procedure is used to register GPI SMI dispatch function.
|
|
@param[in] GpioPad GPIO pad
|
@param[out] GpiNum GPI number
|
|
@retval EFI_SUCCESS The function completed successfully
|
@retval EFI_INVALID_PARAMETER Invalid GpioPad
|
**/
|
EFI_STATUS
|
GpioGetGpiSmiNum (
|
IN GPIO_PAD GpioPad,
|
OUT UINTN *GpiNum
|
)
|
{
|
UINT32 GroupIndex;
|
UINT32 Index;
|
UINT32 PadNumber;
|
GPIO_GROUP_INFO *GpioGroupInfo;
|
UINTN GpioGroupInfoLength;
|
|
GroupIndex = GpioGetGroupIndexFromGpioPad (GpioPad);
|
PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
|
|
if (!GpioIsPadValid (GpioPad)) {
|
ASSERT (FALSE);
|
return EFI_UNSUPPORTED;
|
}
|
|
GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
|
|
*GpiNum = 0;
|
|
for (Index = 0; Index < GroupIndex; Index++) {
|
*GpiNum += (UINTN) (GpioGroupInfo[Index].PadPerGroup);
|
}
|
*GpiNum += (UINTN) PadNumber;
|
|
return EFI_SUCCESS;
|
}
|
|
/**
|
This procedure is used to check GPIO inputs belongs to 2 tier or 1 tier architecture
|
|
@param[in] GpioPad GPIO pad
|
|
@retval Data 0 means 1-tier, 1 means 2-tier
|
**/
|
BOOLEAN
|
GpioCheckFor2Tier (
|
IN GPIO_PAD GpioPad
|
)
|
{
|
UINT32 Data32;
|
|
GpioGetGpeNumber (GpioPad, &Data32);
|
if (Data32 == PCH_GPIO_2_TIER_MASTER_GPE_NUMBER) {
|
return TRUE;
|
}
|
|
return FALSE;
|
}
|
|
/**
|
This procedure is used to clear GPE STS for a specified GpioPad
|
|
@param[in] GpioPad GPIO pad
|
|
@retval EFI_SUCCESS The function completed successfully
|
@retval EFI_INVALID_PARAMETER Invalid GpioPad
|
**/
|
EFI_STATUS
|
GpioClearGpiGpeSts (
|
IN GPIO_PAD GpioPad
|
)
|
{
|
EFI_STATUS Status;
|
GPIO_GROUP Group;
|
UINT32 PadNumber;
|
UINT32 DwNum;
|
UINT32 PadBitPosition;
|
|
if (!GpioIsPadValid (GpioPad)) {
|
ASSERT (FALSE);
|
return EFI_UNSUPPORTED;
|
}
|
|
//
|
// Check for 2-tier
|
//
|
if (!(GpioCheckFor2Tier (GpioPad))) {
|
return EFI_INVALID_PARAMETER;
|
}
|
|
Group = GpioGetGroupFromGpioPad (GpioPad);
|
PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
|
DwNum = GPIO_GET_DW_NUM (PadNumber);
|
PadBitPosition = GPIO_GET_PAD_POSITION (PadNumber);
|
|
//
|
// Clear GPI GPE Status bit by writing '1'
|
//
|
Status = GpioWriteReg (
|
GpioGpeStatusRegister,
|
Group,
|
DwNum,
|
0u,
|
(UINT32) (BIT0 << PadBitPosition)
|
);
|
|
return Status;
|
}
|
|
/**
|
This procedure is used to read GPE STS for a specified Pad
|
|
@param[in] GpioPad GPIO pad
|
@param[out] Data GPE STS data
|
|
@retval EFI_SUCCESS The function completed successfully
|
@retval EFI_INVALID_PARAMETER Invalid GpioPad
|
**/
|
EFI_STATUS
|
GpioGetGpiGpeSts (
|
IN GPIO_PAD GpioPad,
|
OUT UINT32 *Data
|
)
|
{
|
EFI_STATUS Status;
|
UINT32 GpeStsRegVal;
|
GPIO_GROUP Group;
|
UINT32 PadNumber;
|
UINT32 DwNum;
|
UINT32 PadBitPosition;
|
|
if (!GpioIsPadValid (GpioPad)) {
|
ASSERT (FALSE);
|
return EFI_UNSUPPORTED;
|
}
|
|
//
|
// Check for 2-tier
|
//
|
if (!(GpioCheckFor2Tier (GpioPad))) {
|
return EFI_INVALID_PARAMETER;
|
}
|
|
Group = GpioGetGroupFromGpioPad (GpioPad);
|
PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
|
DwNum = GPIO_GET_DW_NUM (PadNumber);
|
PadBitPosition = GPIO_GET_PAD_POSITION (PadNumber);
|
|
//
|
// Read GPI GPE Status bits
|
//
|
Status = GpioReadReg (
|
GpioGpeStatusRegister,
|
Group,
|
DwNum,
|
&GpeStsRegVal
|
);
|
if (EFI_ERROR (Status)) {
|
return EFI_INVALID_PARAMETER;
|
}
|
|
*Data = (GpeStsRegVal >> PadBitPosition) & 0x1;
|
|
return Status;
|
}
|