[EHL] GpioLock update

Issue seen in Yocto RT kernel that PSE GBE0 Transmission.
Found out that GPPC_A_5.pmode=0 (RGMII0_TXCTL) which expected
to be 0x1.
override become 0x0.
After investigation these PADCFGLOCK_GPP_A_0 and PADCFGLOCKTX_GPP_A_0
registers should be 0xFFFFFF to lock the GPIO GPPC_A_x to prevent
modificaiton to the GPIO.
Implemented GpioLock function in GpioLib.c to fix this issue.

Signed-off-by: Ong Kok Tong <kok.tong.ong@intel.com>
This commit is contained in:
Ong Kok Tong 2021-05-10 14:31:57 +08:00 committed by Maurice Ma
parent 126a2c5f03
commit f94decd222
3 changed files with 297 additions and 0 deletions

View File

@ -751,6 +751,7 @@ BoardInit (
if (GetBootMode() != BOOT_ON_FLASH_UPDATE) {
UpdatePayloadId ();
}
GpioLockPads();
break;
case PostSiliconInit:
// Set TSEG base/size PCD

View File

@ -25,6 +25,8 @@ typedef struct {
//
UINT32 OutputState;
} GPIO_UNLOCK_HOB_DATA;
GLOBAL_REMOVE_IF_UNREFERENCED GPIO_UNLOCK_HOB_DATA *mGpioUnlockData = NULL;
GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mGpioUnlockDataRecords = 0;
/**
This procedure will get index of GPIO Unlock HOB structure for selected GroupIndex and DwNum.
@ -126,6 +128,29 @@ GpioGetUnlockData (
return HobDataLength;
}
/**
This procedure will get pointer to GPIO Unlock data structure.
@param[out] GpioUnlockData pointer to GPIO Unlock data structure
@retval Length number of GPIO unlock data records
**/
STATIC
UINT32
GpioLocateUnlockData (
GPIO_UNLOCK_HOB_DATA **GpioUnlockData
)
{
if (mGpioUnlockData == NULL) {
*GpioUnlockData = NULL;
return 0;
}
*GpioUnlockData = (GPIO_UNLOCK_HOB_DATA *) mGpioUnlockData;
return mGpioUnlockDataRecords;
}
/**
This procedure stores GPIO group data about pads which PadConfig needs to be unlocked.
@ -213,3 +238,102 @@ GpioStoreGroupDwUnlockOutputData (
return EFI_SUCCESS;
}
/**
This procedure will get GPIO group data with pads, which PadConfig is supposed to be left unlock
@param[in] GroupIndex GPIO group index
@param[in] DwNum DWORD index for a group.
For group which has less then 32 pads per group DwNum must be 0.
@retval UnlockedPads DWORD bitmask for pads which are going to be left unlocked
Bit position - PadNumber
Bit value - 0: to be locked, 1: Leave unlocked
**/
UINT32
GpioGetGroupDwUnlockPadConfigMask (
IN UINT32 GroupIndex,
IN UINT32 DwNum
)
{
GPIO_UNLOCK_HOB_DATA *GpioUnlockData;
UINT32 Length;
UINT32 Index;
Length = GpioLocateUnlockData (&GpioUnlockData);
if (Length == 0) {
return 0;
}
Index = GpioUnlockDataIndex (GroupIndex, DwNum);
if (Index >= Length) {
return 0;
}
return GpioUnlockData[Index].PadConfig;
}
/**
This procedure will get GPIO group data with pads, which Output is supposed to be left unlock
@param[in] GroupIndex GPIO group index
@param[in] DwNum DWORD index for a group.
For group which has less then 32 pads per group DwNum must be 0.
@retval UnlockedPads DWORD bitmask for pads which are going to be left unlocked
Bit position - PadNumber
Bit value - 0: to be locked, 1: Leave unlocked
**/
UINT32
GpioGetGroupDwUnlockOutputMask (
IN UINT32 GroupIndex,
IN UINT32 DwNum
)
{
GPIO_UNLOCK_HOB_DATA *GpioUnlockData;
UINT32 Length;
UINT32 Index;
Length = GpioLocateUnlockData (&GpioUnlockData);
if (Length == 0) {
return 0;
}
Index = GpioUnlockDataIndex (GroupIndex, DwNum);
if (Index >= Length) {
return 0;
}
return GpioUnlockData[Index].OutputState;
}
/**
This function is to be used In GpioLockPads() to override a lock request by SOC code.
@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] *UnlockCfgPad DWORD bitmask for pads which are going to be left unlocked
Bit position - PadNumber
Bit value - 0: to be locked, 1: Leave unlocked
@param[out] *UnlockTxPad DWORD bitmask for pads which are going to be left unlocked
Bit position - PadNumber
Bit value - 0: to be locked, 1: Leave unlocked
@retval EFI_SUCCESS The function completed successfully
@retval EFI_INVALID_PARAMETER Invalid input parameter
**/
EFI_STATUS
GpioUnlockOverride (
IN GPIO_GROUP Group,
IN UINT32 DwNum,
OUT UINT32 *UnlockCfgPad,
OUT UINT32 *UnlockTxPad
)
{
if ((UnlockCfgPad == NULL) || (UnlockTxPad == NULL)) {
return EFI_INVALID_PARAMETER;
}
*UnlockCfgPad = 0;
*UnlockTxPad = 0;
return EFI_SUCCESS;
}

View File

@ -531,6 +531,64 @@ GpioUnlockPadCfgForGroupDw (
DwNum,
~PadsToUnlock,
0
);
}
/**
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
)
{
if (!GpioIsGroupAndDwNumValid (Group, DwNum)) {
return EFI_INVALID_PARAMETER;
}
return GpioWriteLockReg (
GpioPadConfigLockRegister,
Group,
DwNum,
~0u,
PadsToLock
);
}
/**
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
)
{
GPIO_GROUP Group;
UINT32 PadNumber;
Group = GpioGetGroupFromGpioPad (GpioPad);
PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
return GpioLockPadCfgForGroupDw (
Group,
GPIO_GET_DW_NUM (PadNumber),
1 << GPIO_GET_PAD_POSITION (PadNumber)
);
}
@ -568,6 +626,64 @@ GpioUnlockPadCfgTxForGroupDw (
);
}
/**
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
)
{
if (!GpioIsGroupAndDwNumValid (Group, DwNum)) {
return EFI_INVALID_PARAMETER;
}
return GpioWriteLockReg (
GpioPadLockOutputRegister,
Group,
DwNum,
~0u,
PadsToLockTx
);
}
/**
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
)
{
GPIO_GROUP Group;
UINT32 PadNumber;
Group = GpioGetGroupFromGpioPad (GpioPad);
PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
return GpioLockPadCfgTxForGroupDw (
Group,
GPIO_GET_DW_NUM (PadNumber),
1 << GPIO_GET_PAD_POSITION (PadNumber)
);
}
/**
This function gets Group to GPE0 configuration
@ -657,3 +773,59 @@ GpioGetGroupDwToGpeDwX (
return EFI_SUCCESS;
}
/**
This procedure is used to lock all GPIO pads except the ones
which were requested during their configuration to be left unlocked.
This function must be called before BIOS_DONE - before POSTBOOT_SAI is enabled.
FSP - call this function from wrapper before transition to FSP-S
UEFI/EDK - call this function before EndOfPei event
@retval EFI_SUCCESS The function completed successfully
@retval EFI_INVALID_PARAMETER Invalid group or pad number
**/
EFI_STATUS
GpioLockPads (
VOID
)
{
UINT32 DwNum;
GPIO_GROUP Group;
GPIO_GROUP GroupMin;
GPIO_GROUP GroupMax;
UINT32 UnlockedPads;
UINT32 OverrideCfgPads;
UINT32 OverrideTxPads;
EFI_STATUS Status;
GroupMin = GpioGetLowestGroup ();
GroupMax = GpioGetHighestGroup ();
for (Group = GroupMin; Group <= GroupMax; Group++) {
for (DwNum = 0; DwNum <= GPIO_GET_DW_NUM (GpioGetPadPerGroup (Group)); DwNum++) {
OverrideCfgPads = 0;
OverrideTxPads = 0;
Status = GpioUnlockOverride (Group, DwNum, &OverrideCfgPads, &OverrideTxPads);
if (EFI_ERROR (Status)) {
ASSERT (FALSE);
return Status;
}
UnlockedPads = GpioGetGroupDwUnlockPadConfigMask (GpioGetGroupIndexFromGroup (Group), DwNum);
Status = GpioLockPadCfgForGroupDw (Group, DwNum, (UINT32)~(UnlockedPads | OverrideCfgPads));
if (EFI_ERROR (Status)) {
ASSERT (FALSE);
return Status;
}
UnlockedPads = GpioGetGroupDwUnlockOutputMask (GpioGetGroupIndexFromGroup (Group), DwNum);
Status = GpioLockPadCfgTxForGroupDw (Group, DwNum, (UINT32)~(UnlockedPads | OverrideTxPads));
if (EFI_ERROR (Status)) {
ASSERT (FALSE);
return Status;
}
}
}
return EFI_SUCCESS;
}