/** @file
Install Iio Port Bifurcation Init Data.
@copyright
Copyright 2017 - 2021 Intel Corporation.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "PeiCommonBoardInitLib.h"
#include "IioBifurcationSlotTable.h"
#define IIO_D_UBALOG(...) { DEBUG((DEBUG_ERROR, "[IIO](UBA) " __VA_ARGS__)); } // Important log always printed
#define IIO_D_UBADBG(...) { DEBUG((DEBUG_INFO, "[IIO](UBA) " __VA_ARGS__)); } // Debug log, printed with BIOS debug jumper
#define IIO_D_UBAWARN(...) { DEBUG((DEBUG_ERROR, "[IIO](UBA) WARNING: " __VA_ARGS__)); } // Warning log, not necessary error
#define IIO_D_UBAERR(...) { DEBUG((DEBUG_ERROR, "[IIO](UBA) ERROR: " __VA_ARGS__)); } // Errorneous situation, probably bug or hw problem
EFI_PLATFORM_INFO*
GetPlatformInfoFromHob (
VOID
)
{
EFI_HOB_GUID_TYPE *GuidHob;
GuidHob = GetFirstGuidHob (&gEfiPlatformInfoGuid);
if (GuidHob == NULL) {
ASSERT (FALSE);
return NULL;
}
return GET_GUID_HOB_DATA (GuidHob);
}
/**
Check if QAT-UPLINK override is needed
@param[in] Socket Socket index
@param[in] Iou IOU index
@param[out] Bifurcation Buffer for bifurcation needed to support QAT
@return TRUE if custom bifurcation is necessary
*/
BOOLEAN
IsQatUplinkOverrideNeeded (
IN UINT8 Socket,
IN UINT8 Iou,
IN DYNAMIC_SI_LIBARY_PPI *DynamicSiLibraryPpi,
OUT UINT8 *Bifurcation
)
{
EFI_PLATFORM_INFO *PlatformInfo;
UINT32 Gpio;
EFI_STATUS Status;
PlatformInfo = GetPlatformInfoFromHob ();
if (PlatformInfo == NULL) {
return FALSE;
}
switch (PlatformInfo->BoardId) {
case TypeWilsonCityRP:
case TypeWilsonCityModular:
case TypeWilsonCitySMT:
case TypeWilsonCityPPV:
case TypeWilsonPointRP:
case TypeWilsonPointModular:
case TypeCooperCityRP:
if (Socket %2 == 0 && Iou == 3) {
//
// It is possible that special bifurcation for QAT-UPLINK if needed
// It can be recognized by GPIO D8: 0 means that there is no UPLINK
//
Status = DynamicSiLibraryPpi->GpioGetInputValueByPchId (PCH_LEGACY_ID, GPIO_SKL_H_GPP_D8, &Gpio);
if (EFI_ERROR (Status)) {
return FALSE;
}
if (Gpio != 0) {
*Bifurcation = IIO_BIFURCATE_xxx8xxx8;
return TRUE;
} else {
return FALSE;
}
}
break;
}
//
// By default there is no QAT-UPLINK support
//
return FALSE;
}
/**
Check if QAT-CABLE override is needed
@param[in] Socket Socket index
@param[in] Iou IOU index
@param[out] Bifurcation Buffer for bifurcation needed to support QAT
@return TRUE if custom bifurcation is necessary
*/
BOOLEAN
IsQatCableOverrideNeeded (
IN UINT8 Socket,
IN UINT8 Iou,
IN DYNAMIC_SI_LIBARY_PPI *DynamicSiLibraryPpi,
OUT UINT8 *Bifurcation
)
{
EFI_PLATFORM_INFO *PlatformInfo;
UINT32 Gpio;
EFI_STATUS Status;
PlatformInfo = GetPlatformInfoFromHob ();
if (PlatformInfo == NULL) {
return FALSE;
}
switch (PlatformInfo->BoardId) {
case TypeWilsonCityRP:
case TypeWilsonCityModular:
case TypeWilsonCitySMT:
case TypeWilsonCityPPV:
case TypeWilsonPointRP:
case TypeWilsonPointModular:
if (Iou == 4) {
//
// It is possible that special bifurcation for Oculink QAT cable is needed
// Then cable is used to connect oculinks ports with QAT
// To determine it if cable is needed GPIO-B3 needs to be examined
// GPIO-B3 == 0 means that cable is present
//
Status = DynamicSiLibraryPpi->GpioGetInputValueByPchId (PCH_LEGACY_ID, GPIO_SKL_H_GPP_B3, &Gpio);
if (EFI_ERROR (Status)) {
return FALSE;
}
if (Gpio != 0) {
//
// There is no cable
//
return FALSE;
}
//
// Cable is present to check which MEZZ IOU is used GPIO B4 needs to be examined
// GPIO-B4 == 1: MEZZ IOU from Socket0 is used;
// GPIO-B4 == 0: MEZZ IOU from Socket1 is used;
//
Status = DynamicSiLibraryPpi->GpioGetInputValueByPchId (PCH_LEGACY_ID, GPIO_SKL_H_GPP_B4, &Gpio);
if (EFI_ERROR (Status)) {
return FALSE;
}
if ((Socket == 0 && Gpio == 1) || (Socket == 1 && Gpio == 0)) {
*Bifurcation = IIO_BIFURCATE_xxx8x4x4;
return TRUE;
}
}
} //switch: Board-Id
//
// By default there is no QAT-cable support
//
return FALSE;
}
/**
Check if QAT override is needed.
There are two possible QAT variants:
- QAT uplink
- QAT cable
If LBG with QAT is detected (by GPIO read) custom bifurcation should be set.
@param[in] IioGlobalData Pointer to IioGlobalData
*/
VOID
CheckQatBifurcationOverrides (
IN IIO_GLOBALS *IioGlobalData,
IN DYNAMIC_SI_LIBARY_PPI *DynamicSiLibraryPpi
)
{
UINT8 Socket;
UINT8 Iou;
UINT8 Bifurcation;
UINT8 StackIndex;
for (Socket = 0; Socket < MAX_SOCKET; Socket++) {
for (Iou = 0; Iou < MAX_IOU_PER_SOCKET; Iou++) {
StackIndex = Iou+1;
if (!DynamicSiLibraryPpi->IioIsSocketPresent (Socket)) {
//
// Skip sockets which are not present on the platform
//
continue;
}
if (!DynamicSiLibraryPpi->IioIsStackPresent (Socket, StackIndex)) {
//
// Skips stacks which are not present on the platform
//
continue;
}
//
// Override if QAT is enabled
//
if (IsQatUplinkOverrideNeeded (Socket, Iou, DynamicSiLibraryPpi, &Bifurcation)) {
if (IioGlobalData->SetupData.ConfigIOU[Socket][Iou] == IIO_BIFURCATE_AUTO) {
IioGlobalData->SetupData.ConfigIOU[Socket][Iou] = Bifurcation;
IIO_D_UBALOG ("[%d.%d] QAT-uplink detected; bif=%d\n", Socket, StackIndex, Bifurcation);
}
} else if (IsQatCableOverrideNeeded (Socket, Iou, DynamicSiLibraryPpi, &Bifurcation)) {
if (IioGlobalData->SetupData.ConfigIOU[Socket][Iou] == IIO_BIFURCATE_AUTO) {
IioGlobalData->SetupData.ConfigIOU[Socket][Iou] = Bifurcation;
IIO_D_UBALOG ("[%d.%d] QAT-cable detected; bif=%d\n", Socket, StackIndex, Bifurcation);
}
}
} // for each Iou
} // for each Socket
}
/**
Check if MRL sensor is present for given port.
It depends on board architecture.
Sometimes slot doesn't support it in contrast to Ext.Card.
@param[in] TotalPortIndex Index of the port (across all ports on platform)
@param[in] ExtCardPresent TRUE if Ext. card presence was detected
@return TRUE if MRL sensor presence is expected
*/
BOOLEAN
IsMrlSensorPresent (
IN UINT16 TotalPortIndex,
IN BOOLEAN ExtCardPresent
)
{
EFI_HOB_GUID_TYPE *GuidHob;
EFI_PLATFORM_INFO *PlatformInfo;
//
// This data should be read from platform specific config (slot table IIO_BIFURCATION_DATA_ENTRY_EX)
// but for now there is no such information
// Let this be a temp. workaround until the update of UBA slot configs
//
if (ExtCardPresent) {
//
// MRL sensor is always present for Ext. Cards
//
return TRUE;
}
GuidHob = GetFirstGuidHob (&gEfiPlatformInfoGuid);
if (GuidHob == NULL) {
ASSERT (FALSE);
return FALSE;
}
PlatformInfo = GET_GUID_HOB_DATA (GuidHob);
switch (PlatformInfo->BoardId) {
case TypeWilsonCityRP:
//
// This is version for ICX
//
switch (TotalPortIndex) {
case SOCKET_1_INDEX + PORT_1A_INDEX:
case SOCKET_1_INDEX + PORT_1B_INDEX:
case SOCKET_1_INDEX + PORT_1C_INDEX:
case SOCKET_1_INDEX + PORT_1D_INDEX:
//
// only one slot on WilsonCity supports MRL
//
return TRUE;
default:
return FALSE;
}
break;
case TypeCooperCityRP:
//
// Let's assume that MRL is supported by all slots on CooperCity - where HP is enabled!
//
return TRUE;
default:
//
// For the rest of platforms the situation is unknown for now
//
return FALSE;
}
}
/**
Verify if VMD is enabled and override Slot configuration
based on the VMD settings
@param[in] IioGlobalData Pointer to Iio Globals.
@param[in] Slot Slot configuration settings
@param[in] SlotEntries Number of slot entries
@param[in] ExtCardPresent Table with results of Ext. Card detection
**/
#define SLOT_NUM_OFFSET_FOR_EXT_CARD_SLOT 0x50
VOID
ConfigureSlots (
IN OUT IIO_GLOBALS *IioGlobalData,
IN IIO_SLOT_CONFIG_DATA_ENTRY_EX *Slot,
IN UINT8 SlotEntries,
IN DYNAMIC_SI_LIBARY_PPI *DynamicSiLibraryPpi,
IN BOOLEAN ExtCardPresent[MAX_SOCKET][MAX_IOU_PER_SOCKET]
)
{
UINT8 Index;
UINT16 TotalPortIndex;
UINT8 IioIndex = 0;
UINT8 Stack;
UINT8 PortIndex = 0;
UINT8 Iou;
BOOLEAN IsHpSupportedBySlot;
BOOLEAN IsVmdEnabledForSlot = TRUE;
BOOLEAN IsExtCardInSlot = TRUE;
BOOLEAN AreLanesAssignedToPort = TRUE;
for (Index = 0; Index < SlotEntries; Index ++) {
TotalPortIndex = Slot[Index].PortIndex;
if (DynamicSiLibraryPpi->GetMaxPortNumPerSocket() == 0 || DynamicSiLibraryPpi->GetMaxPortNumPerSocket() == 0) {
return;
}
IioIndex = (UINT8) (TotalPortIndex / DynamicSiLibraryPpi->GetMaxPortNumPerSocket ());
PortIndex = (UINT8) (TotalPortIndex - (IioIndex * DynamicSiLibraryPpi->GetMaxPortNumPerSocket ()));
Stack = IioGlobalData->IioVar.IioVData.StackPerPort[IioIndex][PortIndex];
Iou = Stack - 1;
IsHpSupportedBySlot = FALSE;
IsVmdEnabledForSlot = DynamicSiLibraryPpi->IsVMDEnabledForPort (IioIndex, PortIndex);
IsExtCardInSlot = (Slot[Index].ExtensionCardSupport && ExtCardPresent[IioIndex][Iou]);
AreLanesAssignedToPort = DynamicSiLibraryPpi->IioAreLanesAssignedToPort (IioGlobalData, IioIndex, PortIndex);
if (Slot[Index].Hidden || !AreLanesAssignedToPort) {
//
// Hide rootports which are hidden in slots table or don't have any lanes assigned
//
IioGlobalData->SetupData.HidePEXPMenu[TotalPortIndex] = HIDE;
IioGlobalData->SetupData.PEXPHIDE[TotalPortIndex] = HIDE;
} else {
//
// Unhide active rootports (hided by default)
//
IioGlobalData->SetupData.HidePEXPMenu[TotalPortIndex] = NOT_HIDE;
IioGlobalData->SetupData.PEXPHIDE[TotalPortIndex] = NOT_HIDE;
}
if (Slot[Index].SlotPowerLimitScale != PWR_SCL_MAX) {
IioGlobalData->SetupData.SLOTSPLS[TotalPortIndex] = Slot[Index].SlotPowerLimitScale;
IioGlobalData->SetupData.SLOTSPLV[TotalPortIndex] = Slot[Index].SlotPowerLimitValue;
}
if (Slot[Index].SlotNumber != NO_SLT_IMP) {
IioGlobalData->SetupData.SLOTIMP[TotalPortIndex] = SLT_IMP;
IioGlobalData->SetupData.SLOTPSP[TotalPortIndex] = Slot[Index].SlotNumber;
} else if (AreLanesAssignedToPort) {
//
// If slot is not marked as implemented yet, but is exposed in current bifurcation
// assume that there will be a slot
//
IioGlobalData->SetupData.SLOTIMP[TotalPortIndex] = 1;
IioGlobalData->SetupData.SLOTPSP[TotalPortIndex] = SLOT_NUM_OFFSET_FOR_EXT_CARD_SLOT + TotalPortIndex;
}
if (IsVmdEnabledForSlot) {
//
// Disable Electromechanical Interlock presence for VMD
//
IioGlobalData->SetupData.SLOTEIP[TotalPortIndex] = DISABLE;
} else {
IioGlobalData->SetupData.SLOTEIP[TotalPortIndex] = Slot[Index].InterLockPresent;
}
//
// HotPlug related settings:
// - first check the presence of Ext. Card in the slot and apply specific setting
// - next apply common settings for HotPlug
//
if (IsExtCardInSlot && Slot[Index].ExtnCardHotPlugCapable) {
IsHpSupportedBySlot = TRUE;
//
// Apply specific overrides for HP with Ext. Card
//
if (Slot[Index].ExtnCardHPVppPort != VPP_PORT_MAX) {
IioGlobalData->SetupData.VppEnabled[TotalPortIndex] = TRUE;
IioGlobalData->SetupData.VppPort[TotalPortIndex] = Slot[Index].ExtnCardHPVppPort;
IioGlobalData->SetupData.VppAddress[TotalPortIndex] = Slot[Index].ExtnCardHPVppAddress;
}
} else if (Slot[Index].HotPlugCapable) {
//
// HP settings when there is no Ext. Card
//
IsHpSupportedBySlot = TRUE;
if (Slot[Index].VppPort != VPP_PORT_MAX) {
IioGlobalData->SetupData.VppEnabled[TotalPortIndex] = TRUE;
IioGlobalData->SetupData.VppPort[TotalPortIndex] = Slot[Index].VppPort;
IioGlobalData->SetupData.VppAddress[TotalPortIndex] = Slot[Index].VppAddress;
}
}
if (IsHpSupportedBySlot) {
//
// There are common setting for HP
//
IioGlobalData->SetupData.SLOTHPCAP[TotalPortIndex] = ENABLE;
IioGlobalData->SetupData.SLOTAIP[TotalPortIndex] = ENABLE; // Attention Indicator Present
IioGlobalData->SetupData.SLOTPIP[TotalPortIndex] = ENABLE; // Power Indicator Present
if (IsVmdEnabledForSlot) {
IioGlobalData->SetupData.SLOTHPSUP[TotalPortIndex] = ENABLE; // HotPlug Surprise is always enabled for VMD
}
if (!IsVmdEnabledForSlot && IsMrlSensorPresent (TotalPortIndex, IsExtCardInSlot)) {
//
// Let's assume that if MRL sensor is present Attention button and Power Controller is also present
//
IioGlobalData->SetupData.SLOTMRLSP[TotalPortIndex] = ENABLE;
IioGlobalData->SetupData.SLOTABP[TotalPortIndex] = ENABLE;
IioGlobalData->SetupData.SLOTPCP[TotalPortIndex] = ENABLE;
} else {
IioGlobalData->SetupData.SLOTMRLSP[TotalPortIndex] = DISABLE;
IioGlobalData->SetupData.SLOTABP[TotalPortIndex] = DISABLE;
IioGlobalData->SetupData.SLOTPCP[TotalPortIndex] = DISABLE;
}
}
} // for each slot entry
}
/**
Check if lanes are reversed for given IOU - this is important when non-symetrical
bifurcation is requested.
@param[in] BifurcationTable record from bifurcation table
@return TRUE if lanes are in reversed order
*/
BOOLEAN
IsLaneReversed (
IN IIO_BIFURCATION_DATA_ENTRY_EX *BifurcationTable
)
{
EFI_HOB_GUID_TYPE *GuidHob;
EFI_PLATFORM_INFO *PlatformInfo;
//
// This data should be read from platform specific config - but for now we don't have this information there
// Let this be a temp. workaround until the update of biffurcation config.
//
GuidHob = GetFirstGuidHob (&gEfiPlatformInfoGuid);
if (GuidHob == NULL) {
ASSERT (FALSE);
return FALSE;
}
PlatformInfo = GET_GUID_HOB_DATA (GuidHob);
switch (PlatformInfo->BoardId) {
case TypeCooperCityRP:
//
// For CooperCityRP lane reversed are:
// - on even sockets: on IOU4
// - on odd sockets: on IOU1
//
return ((BifurcationTable->Socket&1) == 1 && BifurcationTable->IouNumber == Iio_Iou1);
default:
//
// Let's assume that WilsonCity config is a default one.
//
//
// This is version for ICX (default)
//
return (BifurcationTable->Socket == 1 &&
(BifurcationTable->IouNumber == Iio_Iou0 || BifurcationTable->IouNumber == Iio_Iou4));
}
}
/**
Read the bifurcation info stored at I/O Expander (PCA9554) which BIOS
can get through Smbus.
To communicate with IO Expander first MUX PCA9545 needs to be configured.
The bifurcation encoding is [3:0]:
BW5_BIFURCATE_x4x4x4x4 1 0 0 0
BW5_BIFURCATE_x4x4xxx8 1 0 0 1 Lanes to port ACD on board
BW5_BIFURCATE_xxx8x4x4 1 0 1 0 Lanes to port ABC on board
BW5_BIFURCATE_xxx8xxx8 1 0 1 1 Lanes to port AC on board
No BW5 1 1 x x
@param IioGlobalData - Pointer to IioGlobals
@param BroadwayTablePtr - Pointer to BroadwayTable
@retval IIO_BIFURCATE_xxxxxxxx BW communication failure
@retval IIO_BIFURCATE_x4x4x4x4 Requested bifurcation x4x4x4x4
@retval IIO_BIFURCATE_x4x4xxx8 Requested bifurcation x4x4xxx8
@retval IIO_BIFURCATE_xxx8x4x4 Requested bifurcation xxx8x4x4
@retval IIO_BIFURCATE_xxx8xxx8 Requested bifurcation xxx8xxx8
**/
UINT8
GetBw5Bifurcation (
IN IIO_BIFURCATION_DATA_ENTRY_EX *BifurcationTable,
IN IN DYNAMIC_SI_LIBARY_PPI *DynamicSiLibraryPpi
)
{
EFI_STATUS Status;
EFI_SMBUS_DEVICE_ADDRESS SmbDevAddr;
EFI_PEI_SMBUS2_PPI *SmbPpi = NULL;
UINT16 SmbData = 0;
UINT8 SmbByteData = 0;
UINT8 RetryCount;
UINTN SmbLen = 2;
UINTN SmbByteLen = 1;
if (BifurcationTable->ExtnCardSMBusAddress == SMB_ADDR_MAX ) {
return IIO_BIFURCATE_xxxxxxxx;
}
Status = PeiServicesLocatePpi (&gEfiPeiSmbus2PpiGuid, 0, NULL, (VOID **) &SmbPpi);
// Initialize Bw5Id to not present
if (Status != EFI_SUCCESS || SmbPpi == NULL) {
DEBUG ((DEBUG_ERROR, "[Iio] Get SMBus protocol error %x\n", Status));
return IIO_BIFURCATE_xxxxxxxx;
}
for (RetryCount = 0; RetryCount < NUM_OF_RETRIES; RetryCount++) {
//
// Configure through the smbus MUX PCA9545 to start communicate to GPIO expander
//
SmbDevAddr.SmbusDeviceAddress = BifurcationTable->MuxSMBusAddress >> 1;
SmbByteData = BifurcationTable->MuxSMBusChannel;
Status = SmbPpi->Execute (SmbPpi, SmbDevAddr, 0, EfiSmbusSendByte, FALSE, &SmbByteLen, &SmbByteData);
if (EFI_ERROR (Status)) {
continue;
}
//
// Read the current I/O pins configuration for Port0
//
SmbDevAddr.SmbusDeviceAddress = BifurcationTable->ExtnCardSMBusAddress >> 1;
Status = SmbPpi->Execute (SmbPpi, SmbDevAddr, BW4_CONFIG_OFFSET, EfiSmbusReadWord, FALSE, &SmbLen, &SmbData);
if (!EFI_ERROR (Status)) {
//
// Configure the direction of I/O pins for Port0/Port1 as Input.
//
SmbData = SmbData | BW5_CONFIG_REG_MASK;
Status = SmbPpi->Execute (SmbPpi, SmbDevAddr, BW4_CONFIG_OFFSET, EfiSmbusWriteWord, FALSE, &SmbLen, &SmbData);
if (!EFI_ERROR (Status)) {
//
// Read Input Port0/Port1 register to identify BW5 Id
//
Status = SmbPpi->Execute (SmbPpi, SmbDevAddr, BW4_DATA_OFFSET, EfiSmbusReadWord, FALSE, &SmbLen, &SmbData);
if (!EFI_ERROR (Status)){
//
// Mask the Input Port0/1 register data [15:0] to get BW5 ID [3:0].
//
// The bifurcation encoding is [3:0]:
// BW5_BIFURCATE_x4x4x4x4 1 0 0 0
// BW5_BIFURCATE_x4x4xxx8 1 0 0 1 Lanes to port ACD on board
// BW5_BIFURCATE_xxx8x4x4 1 0 1 0 Lanes to port ABC on board
// BW5_BIFURCATE_xxx8xxx8 1 0 1 1 Lanes to port AC on board
// No BW5 1 1 x x
//
switch (SmbData & 0xF) {
case 0x8:
return IIO_BIFURCATE_x4x4x4x4;
break;
case 0x9:
if (IsLaneReversed (BifurcationTable)) {
return IIO_BIFURCATE_xxx8x4x4;
} else {
return IIO_BIFURCATE_x4x4xxx8;
}
break;
case 0xA:
if (IsLaneReversed (BifurcationTable)) {
return IIO_BIFURCATE_x4x4xxx8;
} else {
return IIO_BIFURCATE_xxx8x4x4;
}
break;
case 0xB:
return IIO_BIFURCATE_xxx8xxx8;
break;
default:
return IIO_BIFURCATE_xxxxxxxx;
break;
}
} // Read Port0
} // Configure Port0
} // Read Port0 Config
//
// Configure through the smbus MUX PCA9545 to end communicate to GPIO expander
//
SmbDevAddr.SmbusDeviceAddress = BifurcationTable->MuxSMBusAddress >> 1;
SmbByteData &= ~BifurcationTable->MuxSMBusChannel;
Status = SmbPpi->Execute (SmbPpi, SmbDevAddr, 0, EfiSmbusSendByte, FALSE, &SmbByteLen, &SmbByteData);
if (EFI_ERROR (Status)) {
continue;
}
} //RetryCount
return IIO_BIFURCATE_xxxxxxxx;
}
/**
Set bifurcation base of default settings and Ext. Card presence
(detected by BW)
@param[in] IioGlobalData Pointer to Iio Globals.
@param[in] BifurcationTable Bifurcation configuration settings
@param[in] BifurcationEntries Number of bif. table entries
@param[in] ExtCardPresent Table with results of Ext. Card detection
**/
VOID
DetectExtCards (
IN IIO_GLOBALS *IioGlobalData,
IN IIO_BIFURCATION_DATA_ENTRY_EX *BifurcationTable,
IN UINT8 BifurcationEntries,
IN DYNAMIC_SI_LIBARY_PPI *DynamicSiLibraryPpi,
OUT BOOLEAN ExtCardPresent[MAX_SOCKET][MAX_IOU_PER_SOCKET]
)
{
UINT8 Index;
UINT8 BwBifurcation;
UINT8 Socket;
UINT8 Iou;
//
// Try to communicate with Ext.Card which can request custom bifurcation on the stack
//
for (Index = 0; Index < BifurcationEntries; Index++){
Socket = BifurcationTable[Index].Socket;
Iou = BifurcationTable[Index].IouNumber;
ExtCardPresent[Socket][Iou] = FALSE; // by default
if (BifurcationTable[Index].ExtnCardSMBusAddress != SMB_ADDR_MAX) {
//
// ExtCard can be supported at this stack - try to detect it
//
BwBifurcation = GetBw5Bifurcation (&BifurcationTable[Index], DynamicSiLibraryPpi);
if (BwBifurcation != IIO_BIFURCATE_xxxxxxxx) {
//
// Ext. Card is detected on this IOU
//
IIO_D_UBALOG ("[%d.%d] Ext. Card detected; bif=%d\n", Socket, Iou+1, BwBifurcation);
ExtCardPresent[Socket][Iou] = TRUE;
}
}
//
// Set custom bifurcation requested by Ext. Card
//
if (IioGlobalData->SetupData.ConfigIOU[Socket][Iou] == IIO_BIFURCATE_AUTO) {
//
// There are no overrides for this IOU
//
if (ExtCardPresent[Socket][Iou]) {
//
// Set bifurcation requested by Ext. Card
//
IioGlobalData->SetupData.ConfigIOU[Socket][Iou] = BwBifurcation;
} else {
//
// Set the default bifurcation for this IOU
//
IioGlobalData->SetupData.ConfigIOU[Socket][Iou] = BifurcationTable[Index].Bifurcation;
}
}
IIO_D_UBADBG ("[%d.%d] final bifurcation = %X\n", Socket, Iou+1, IioGlobalData->SetupData.ConfigIOU[Socket][Iou]);
} // for bifurcation table entry
}
/**
Dump prepared configuration to log.
@param[in] SetupData Pointer to SetupData structure
**/
VOID
DumpConfiguration (
IN IIO_CONFIG *SetupData,
IN DYNAMIC_SI_LIBARY_PPI *DynamicSiLibraryPpi
)
{
UINT8 IioIndex;
UINT8 StackIndex = 0;
UINT8 Iou;
UINT8 PortIndex = 0;
UINT8 PortInStackIndex = 0;
UINT16 TotalPortIndex =0;
for (IioIndex = 0; IioIndex < MAX_SOCKET ; IioIndex++) {
if (!DynamicSiLibraryPpi->IioIsSocketPresent (IioIndex)) {
//
// Skips sockets which are not present on the platform
//
continue;
}
for (StackIndex = 0; StackIndex < DynamicSiLibraryPpi->GetMaxStackNumPerSocket (); StackIndex++) {
if (DynamicSiLibraryPpi->IsDmiStack (StackIndex)) {
//
// Skip DMI stacks in dump
//
continue;
}
if (!DynamicSiLibraryPpi->IioIsStackPresent (IioIndex, StackIndex)) {
//
// Skips stacks which are not present on the platform
//
continue;
}
if (StackIndex >= MAX_IIO_STACK) {
break;
}
Iou = StackIndex - 1;
IIO_D_UBALOG("[%d.%d] Bifurcation = %X\n", IioIndex, StackIndex, SetupData->ConfigIOU[IioIndex][Iou]);
IIO_D_UBALOG (" [ IDX ], PortHide, SlotImpl, SlotNumber, HotPlug, Vpp, Interlock\n");
for (PortInStackIndex = 0; PortInStackIndex < DynamicSiLibraryPpi->GetMaxPortNumPerStack (StackIndex); PortInStackIndex++) {
PortIndex = DynamicSiLibraryPpi->GetPortIndexbyStack (StackIndex, PortInStackIndex);
TotalPortIndex = (IioIndex * DynamicSiLibraryPpi->GetMaxPortNumPerSocket ()) + PortIndex;
IIO_D_UBALOG (" [%d p%02d] %2d | %2d | %3d | %3d | 0x%02x | %2d \n",
IioIndex, PortIndex,
SetupData->PEXPHIDE[TotalPortIndex],
SetupData->SLOTIMP[TotalPortIndex],
SetupData->SLOTPSP[TotalPortIndex],
SetupData->SLOTHPCAP[TotalPortIndex],
SetupData->VppAddress[TotalPortIndex] | SetupData->VppPort[TotalPortIndex],
SetupData->SLOTEIP[TotalPortIndex]);
} // foreach PortInStack
} //foreach StackIndex
} // foreach IioIndex
}
/**
This function prepare the data for silicon initialization based on
bifurcations and slots table
This function is for tables in version PLATFORM_IIO_CONFIG_UPDATE_VERSION = 2
@param[in] IioGlobalData IIO Global data structure
@param[in] IioConfigTable
*/
VOID
IioPortBifurcationInitVer2 (
IN IIO_GLOBALS *IioGlobalData,
IN PLATFORM_IIO_CONFIG_UPDATE_TABLE_EX IioConfigTable,
IN DYNAMIC_SI_LIBARY_PPI *DynamicSiLibraryPpi
)
{
IIO_BIFURCATION_DATA_ENTRY_EX *BifurcationTableEx;
UINT8 BifurcationEntries;
IIO_SLOT_CONFIG_DATA_ENTRY_EX *SlotTableEx;
UINT8 SlotEntries;
BOOLEAN ExtCardDetected[MAX_SOCKET][MAX_IOU_PER_SOCKET];
//
// Init bifurcation and slots tables
//
BifurcationTableEx = IioConfigTable.IioBifurcationTablePtr;
BifurcationEntries = (UINT8) (IioConfigTable.IioBifurcationTableSize / sizeof (IIO_BIFURCATION_DATA_ENTRY_EX));
SlotTableEx = IioConfigTable.IioSlotTablePtr;
SlotEntries = (UINT8) (IioConfigTable.IioSlotTableSize / sizeof (IIO_SLOT_CONFIG_DATA_ENTRY_EX));
//
// Set the bifurcations for each IOU:
// - if any override is set in setup menu - stay bifurcation not changed
// - next check if QAT is detected (this is LBG specific) - QAT requires special bifurcation
// - next try to detect ext. cards with BW bifurcation
// - at the end set default bifurcation if no other options wer applied before
if (DynamicSiLibraryPpi->IsCpuAndRevision (CPU_ICXSP, REV_ALL) ||
DynamicSiLibraryPpi->IsCpuAndRevision (CPU_CPX, REV_ALL) ||
DynamicSiLibraryPpi->IsCpuAndRevision (CPU_SKX, REV_ALL) ||
DynamicSiLibraryPpi->IsCpuAndRevision (CPU_CLX, REV_ALL)
) {
//
// This is important only for programs with LBG PCH
//
CheckQatBifurcationOverrides (IioGlobalData, DynamicSiLibraryPpi);
}
DetectExtCards (IioGlobalData, BifurcationTableEx, BifurcationEntries, DynamicSiLibraryPpi, ExtCardDetected);
//
// Set each rootport settings based on slots table
//
ConfigureSlots (IioGlobalData, SlotTableEx, SlotEntries, DynamicSiLibraryPpi, ExtCardDetected);
//
// Configuration is ready - dump the config to log
//
DumpConfiguration (&IioGlobalData->SetupData, DynamicSiLibraryPpi);
}
/**
Program the IIO_GLOBALS data structure with OEM IIO init values for SLOTs and Bifurcation.
@param mSB - pointer to this protocol
@param IioUds - Pointer to the IIO UDS data structure.
@retval EFI_SUCCESS
**/
VOID
IioPortBifurcationInitCallback (
IN IIO_GLOBALS *IioGlobalData
)
{
EFI_STATUS Status;
UBA_CONFIG_DATABASE_PPI *UbaConfigPpi = NULL;
DYNAMIC_SI_LIBARY_PPI *DynamicSiLibraryPpi = NULL;
PLATFORM_IIO_CONFIG_UPDATE_TABLE_EX IioConfigTable;
UINTN TableSize;
//
// Locate PLATFORM_IIO_CONFIG_UPDATE_TABLE_EX
//
Status = PeiServicesLocatePpi (&gUbaConfigDatabasePpiGuid, 0, NULL, (VOID **) &UbaConfigPpi);
if (EFI_ERROR (Status)) {
ASSERT (FALSE);
return;
}
Status = PeiServicesLocatePpi (&gDynamicSiLibraryPpiGuid, 0, NULL, (VOID **) &DynamicSiLibraryPpi);
if (EFI_ERROR (Status)) {
ASSERT_EFI_ERROR (Status);
return;
}
TableSize = sizeof (IioConfigTable);
Status = UbaConfigPpi->GetData (UbaConfigPpi, &gPlatformIioConfigDataGuid, &IioConfigTable, &TableSize);
if (EFI_ERROR (Status)) {
ASSERT (FALSE);
return;
}
ASSERT (IioConfigTable.Signature == PLATFORM_IIO_CONFIG_UPDATE_SIGNATURE);
//
// Call the right version of bifurcation init procedure
//
switch (IioConfigTable.Version) {
case PLATFORM_IIO_CONFIG_UPDATE_VERSION_2:
IioPortBifurcationInitVer2 (IioGlobalData, IioConfigTable, DynamicSiLibraryPpi);
break;
case PLATFORM_IIO_CONFIG_UPDATE_VERSION:
IioPortBifurcationInitVer1 (IioGlobalData);
break;
default:
ASSERT (FALSE);
break;
}
}
IIO_PORT_BIFURCATION_INIT_TABLE IioPortBifurcationInitTable =
{
IIO_PORT_BIFURCATION_INIT_SIGNATURE,
IIO_PORT_BIFURCATION_INIT_VERSION,
IioPortBifurcationInitCallback
};
EFI_STATUS
InstallIioPortBifurcationInitData (
IN UBA_CONFIG_DATABASE_PPI *UbaConfigPpi
)
{
return UbaConfigPpi->AddData (
UbaConfigPpi,
&gIioPortBifurcationInitDataGuid,
&IioPortBifurcationInitTable,
sizeof (IioPortBifurcationInitTable)
);
}