/** @file
|
This file contains routines for PEI GPIO Helpers Lib
|
|
Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
|
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
**/
|
|
#include <Library/HobLib.h>
|
#include <Base.h>
|
#include <Uefi/UefiBaseType.h>
|
#include <Library/IoLib.h>
|
#include <Library/DebugLib.h>
|
#include <Library/BaseMemoryLib.h>
|
#include <Library/GpioNativeLib.h>
|
#include <Pch/Library/PeiDxeSmmGpioLib/GpioLibrary.h>
|
#include <Private/Library/GpioHelpersLib.h>
|
|
extern EFI_GUID gGpioLibUnlockHobGuid;
|
|
//
|
// GPIO Lock HOB
|
// Stores information on GPIO pads that should be left unlocked
|
//
|
typedef struct {
|
//
|
// GPIO PadConfig unlock data
|
//
|
UINT32 PadConfig;
|
//
|
// GPIO Output unlock data
|
//
|
UINT32 OutputState;
|
} GPIO_UNLOCK_HOB_DATA;
|
|
/**
|
This procedure will get index of GPIO Unlock HOB structure for selected GroupIndex and DwNum.
|
|
@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 GpioUnlockHobIndex
|
**/
|
STATIC
|
UINT32
|
GpioUnlockDataIndex (
|
IN UINT32 GroupIndex,
|
IN UINT32 DwNum
|
)
|
{
|
UINT32 GpioUnlockDataIndex;
|
UINT32 Index;
|
|
GpioUnlockDataIndex = 0;
|
|
for (Index = 0; Index < GroupIndex; Index++) {
|
GpioUnlockDataIndex += GPIO_GET_DW_NUM (GpioGetPadPerGroup (GpioGetGroupFromGroupIndex (Index))) + 1;
|
}
|
|
GpioUnlockDataIndex += DwNum;
|
return GpioUnlockDataIndex;
|
}
|
|
/**
|
This procedure will create GPIO HOB for storing unlock data
|
|
@retval Pointer to GPIO Unlock data structure
|
**/
|
STATIC
|
GPIO_UNLOCK_HOB_DATA*
|
GpioCreateUnlockData (
|
VOID
|
)
|
{
|
VOID *HobData;
|
GPIO_GROUP Group;
|
GPIO_GROUP GroupMin;
|
GPIO_GROUP GroupMax;
|
UINT32 GpioUnlockDataRecords;
|
|
GroupMin = GpioGetLowestGroup ();
|
GroupMax = GpioGetHighestGroup ();
|
GpioUnlockDataRecords = 0;
|
|
for (Group = GroupMin; Group <= GroupMax; Group++) {
|
GpioUnlockDataRecords += GPIO_GET_DW_NUM (GpioGetPadPerGroup (Group)) + 1;
|
}
|
|
HobData = BuildGuidHob (&gGpioLibUnlockHobGuid, GpioUnlockDataRecords * sizeof (GPIO_UNLOCK_HOB_DATA));
|
if (HobData == NULL) {
|
return NULL;
|
}
|
|
ZeroMem (HobData, GpioUnlockDataRecords * sizeof (GPIO_UNLOCK_HOB_DATA));
|
|
return (GPIO_UNLOCK_HOB_DATA*)HobData;
|
}
|
|
/**
|
This procedure will Get GPIO Unlock data structure for storing unlock data.
|
If HOB doesn't exist it will be created.
|
|
@param[out] GpioUnlockData pointer to GPIO Unlock data structure
|
|
@retval Length number of GPIO unlock data records
|
**/
|
STATIC
|
UINT32
|
GpioGetUnlockData (
|
GPIO_UNLOCK_HOB_DATA **GpioUnlockData
|
)
|
{
|
VOID *Hob;
|
|
Hob = GetFirstGuidHob (&gGpioLibUnlockHobGuid);
|
if (Hob == NULL) {
|
//
|
// It is the first time this function is used so create the HOB
|
//
|
*GpioUnlockData = GpioCreateUnlockData ();
|
if (*GpioUnlockData == NULL) {
|
return 0;
|
}
|
Hob = GetFirstGuidHob (&gGpioLibUnlockHobGuid);
|
} else {
|
*GpioUnlockData = (GPIO_UNLOCK_HOB_DATA*) GET_GUID_HOB_DATA (Hob);
|
}
|
return GET_GUID_HOB_DATA_SIZE (Hob) / sizeof (GPIO_UNLOCK_HOB_DATA);
|
}
|
|
/**
|
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
|
)
|
{
|
VOID *Hob;
|
|
Hob = GetFirstGuidHob (&gGpioLibUnlockHobGuid);
|
if (Hob == NULL) {
|
*GpioUnlockData = NULL;
|
return 0;
|
}
|
|
*GpioUnlockData = (GPIO_UNLOCK_HOB_DATA*) GET_GUID_HOB_DATA (Hob);
|
return GET_GUID_HOB_DATA_SIZE (Hob) / sizeof (GPIO_UNLOCK_HOB_DATA);
|
}
|
|
/**
|
This procedure stores GPIO pad unlock information
|
|
@param[in] GpioPad GPIO pad
|
@param[in] GpioLockConfig GPIO Lock Configuration
|
|
@retval Status
|
**/
|
EFI_STATUS
|
GpioStoreUnlockData (
|
IN GPIO_PAD GpioPad,
|
IN GPIO_LOCK_CONFIG GpioLockConfig
|
)
|
{
|
GPIO_UNLOCK_HOB_DATA *GpioUnlockData;
|
UINT32 Length;
|
UINT32 GroupIndex;
|
UINT32 PadNumber;
|
UINT32 Index;
|
|
if (GpioLockConfig == GpioLockDefault) {
|
return EFI_SUCCESS;
|
}
|
|
Length = GpioGetUnlockData (&GpioUnlockData);
|
if (Length == 0) {
|
return EFI_NOT_FOUND;
|
}
|
|
GroupIndex = GpioGetGroupIndexFromGpioPad (GpioPad);
|
PadNumber = GpioGetPadNumberFromGpioPad (GpioPad);
|
Index = GpioUnlockDataIndex (GroupIndex, GPIO_GET_DW_NUM (PadNumber));
|
|
if (Index >= Length) {
|
return EFI_INVALID_PARAMETER;
|
}
|
|
if ((GpioLockConfig & B_GPIO_LOCK_CONFIG_PAD_CONF_LOCK_MASK) == GpioPadConfigUnlock) {
|
GpioUnlockData[Index].PadConfig |= 1 << (GpioGetPadNumberFromGpioPad (GpioPad) % 32);
|
}
|
|
if ((GpioLockConfig & B_GPIO_LOCK_CONFIG_OUTPUT_LOCK_MASK) == GpioOutputStateUnlock) {
|
GpioUnlockData[Index].OutputState |= 1 << (GpioGetPadNumberFromGpioPad (GpioPad) % 32);
|
}
|
|
return EFI_SUCCESS;
|
}
|
|
/**
|
This procedure stores GPIO group data about pads which PadConfig needs to be unlocked.
|
|
@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.
|
@param[in] UnlockedPads DWORD bitmask for pads which are going to be left unlocked
|
Bit position - PadNumber
|
Bit value - 0: Skip, 1: Leave unlocked
|
|
@retval Status
|
**/
|
EFI_STATUS
|
GpioStoreGroupDwUnlockPadConfigData (
|
IN UINT32 GroupIndex,
|
IN UINT32 DwNum,
|
IN UINT32 UnlockedPads
|
)
|
{
|
GPIO_UNLOCK_HOB_DATA *GpioUnlockData;
|
UINT32 Length;
|
UINT32 Index;
|
|
if (UnlockedPads == 0) {
|
//
|
// No pads to be left unlocked
|
//
|
return EFI_SUCCESS;
|
}
|
|
Length = GpioGetUnlockData (&GpioUnlockData);
|
if (Length == 0) {
|
return EFI_NOT_FOUND;
|
}
|
|
Index = GpioUnlockDataIndex (GroupIndex, DwNum);
|
if (Index >= Length) {
|
return EFI_INVALID_PARAMETER;
|
}
|
|
GpioUnlockData[Index].PadConfig |= UnlockedPads;
|
return EFI_SUCCESS;
|
}
|
|
/**
|
This procedure stores GPIO group data about pads which Output state needs to be unlocked.
|
|
@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.
|
@param[in] UnlockedPads DWORD bitmask for pads which are going to be left unlocked
|
Bit position - PadNumber
|
Bit value - 0: Skip, 1: Leave unlocked
|
@retval Status
|
**/
|
EFI_STATUS
|
GpioStoreGroupDwUnlockOutputData (
|
IN UINT32 GroupIndex,
|
IN UINT32 DwNum,
|
IN UINT32 UnlockedPads
|
)
|
{
|
GPIO_UNLOCK_HOB_DATA *GpioUnlockData;
|
UINT32 Length;
|
UINT32 Index;
|
|
if (UnlockedPads == 0) {
|
//
|
// No pads to be left unlocked
|
//
|
return EFI_SUCCESS;
|
}
|
|
Length = GpioGetUnlockData (&GpioUnlockData);
|
if (Length == 0) {
|
return EFI_NOT_FOUND;
|
}
|
|
Index = GpioUnlockDataIndex (GroupIndex, DwNum);
|
if (Index >= Length) {
|
return EFI_INVALID_PARAMETER;
|
}
|
|
GpioUnlockData[Index].OutputState |= UnlockedPads;
|
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;
|
}
|