alder_lake_bios/Intel/AlderLake/AlderLakeChipsetPkg/Library/BaseInsydeChipsetGpioLib/BaseInsydeChipsetGpioLib.c

206 lines
5.7 KiB
C

/** @file
;******************************************************************************
;* Copyright (c) 2015 - 2016, Insyde Software Corp. All Rights Reserved.
;*
;* You may not reproduce, distribute, publish, display, perform, modify, adapt,
;* transmit, broadcast, present, recite, release, license or otherwise exploit
;* any part of this publication in any form, by any means, without the prior
;* written permission of Insyde Software Corporation.
;*
;******************************************************************************
*/
#include <Library/BaseInsydeChipsetGpioLib.h>
/**
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;
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 is used to read SMI 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 group or pad number
**/
EFI_STATUS
GpioGetGpiSmiSts (
IN GPIO_PAD GpioPad,
OUT UINT32* Data
)
{
UINT32 Data32;
UINT32 Mask;
UINT32 GroupIndex;
UINT32 PadNumber;
CONST GPIO_GROUP_INFO *GpioGroupInfo;
UINT32 GpioGroupInfoLength;
*Data = 0xFFFFFFFF;
GpioGroupInfo = GpioGetGroupInfoTable (&GpioGroupInfoLength);
GroupIndex = GpioGetGroupIndexFromGpioPad (GpioPad);
PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
//
// 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));
ASSERT (FALSE);
return EFI_INVALID_PARAMETER;
}
//
// Check if legal pad number
//
if (PadNumber >= GpioGroupInfo[GroupIndex].PadPerGroup) {
DEBUG ((DEBUG_ERROR, "GPIO ERROR: Pin number (%d) exceeds possible range for this group\n", PadNumber));
ASSERT (FALSE);
return EFI_INVALID_PARAMETER;
}
//
// Check if group has GPI GPE register
//
if (GpioGroupInfo[GroupIndex].SmiStsOffset == NO_REGISTER_FOR_PROPERTY) {
return EFI_INVALID_PARAMETER;
}
//
// Read GPI GPE Status bits
//
Data32 = MmioRead32(
PCH_PCR_ADDRESS(GpioGroupInfo[GroupIndex].Community, GpioGroupInfo[GroupIndex].SmiStsOffset)
);
Mask = (UINT32)(BIT0 << PadNumber);
Data32 = (Data32 & Mask) >> PadNumber;
*Data = Data32;
return EFI_SUCCESS;
}
EFI_STATUS
GpioEnableGpiSmi (
IN GPIO_PAD GpioPad,
IN BOOLEAN Enable
)
{
GPIO_CONFIG GpioPadConfig;
EFI_STATUS Status;
UINT32 Data32;
UINT32 PadNumber;
GpioGetPadConfig (GpioPad, &GpioPadConfig);
//
// Set GPI_SMI_EN
//
Data32 = Enable ? 1 : 0;
PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
Status = GpioWriteReg (
GpioSmiEnableRegister,
GpioGetGroupFromGpioPad (GpioPad),
GPIO_GET_DW_NUM (PadNumber),
~(1 << GPIO_GET_PAD_POSITION (PadNumber)),
Data32 << GPIO_GET_PAD_POSITION (PadNumber)
);
ASSERT_EFI_ERROR (Status);
//
// Set GPIROUTSMI
//
Data32 = Enable ? B_GPIO_PCR_RX_SMI_ROUTE : 0;
GpioWritePadCfgReg (
GpioPad,
0,
(UINT32)~B_GPIO_PCR_RX_SMI_ROUTE,
Data32
);
return EFI_SUCCESS;
}