206 lines
5.7 KiB
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;
|
|
}
|