/** @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) ); }