/** @file
|
This file contains functions that configures PCI Express Root Ports function swapping.
|
|
Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
**/
|
#include <Uefi/UefiBaseType.h>
|
#include <Library/DebugLib.h>
|
#include <Library/IoLib.h>
|
#include <Library/MmPciLib.h>
|
#include <Library/PchPcieRpLib.h>
|
#include <Library/PchPcrLib.h>
|
#include <Library/PchInfoLib.h>
|
#include <Library/PchPciExpressHelpersLib.h>
|
#include <Library/PchInitCommonLib.h>
|
#include <Library/PchPsfPrivateLib.h>
|
#include <Library/S3BootScriptLib.h>
|
|
/**
|
Configure root port function number mapping
|
|
@retval EFI_SUCCESS The function completed successfully
|
**/
|
EFI_STATUS
|
PchConfigureRpfnMapping (
|
VOID
|
)
|
{
|
UINT8 PortIndex;
|
UINT8 OriginalFuncZeroRp;
|
UINT8 MaxPciePortNum;
|
UINT32 Data32;
|
UINTN DevNum;
|
UINTN FuncNum;
|
UINTN RpBase;
|
UINT32 ControllerPcd[PCH_MAX_PCIE_CONTROLLERS];
|
PCH_SERIES PchSeries;
|
PCH_GENERATION PchGen;
|
UINT32 PcieControllers;
|
UINT32 ControllerIndex;
|
UINT32 FirstController;
|
PCH_SBI_PID ControllerPid;
|
|
DEBUG ((DEBUG_INFO,"PchConfigureRpfnMapping () Start\n"));
|
|
PchSeries = GetPchSeries ();
|
PchGen = GetPchGeneration ();
|
MaxPciePortNum = GetPchMaxPciePortNum ();
|
|
PcieControllers = GetPchMaxPcieControllerNum ();
|
|
for (ControllerIndex = 0; ControllerIndex < PcieControllers; ++ControllerIndex) {
|
PchPcrRead32 (PchGetPcieControllerSbiPid (ControllerIndex), R_PCH_PCR_SPX_PCD, &ControllerPcd[ControllerIndex]);
|
}
|
|
///
|
/// Configure root port function number mapping
|
///
|
for (PortIndex = 0; PortIndex < MaxPciePortNum; ) {
|
GetPchPcieRpDevFun (PortIndex, &DevNum, &FuncNum);
|
RpBase = MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH, (UINT32) DevNum, (UINT32) FuncNum);
|
//
|
// Search for first enabled function
|
//
|
if (MmioRead16 (RpBase) != 0xFFFF) {
|
if (FuncNum != 0) {
|
//
|
// First enabled root port that is not function zero will be swapped with function zero on the same device
|
// RP PCD register must sync with PSF RP function config register
|
//
|
ControllerIndex = PortIndex / 4;
|
OriginalFuncZeroRp = (PortIndex / 8) * 8;
|
FirstController = OriginalFuncZeroRp / 4;
|
|
//
|
// The enabled root port becomes function zero
|
//
|
ControllerPcd[ControllerIndex] &= (UINT32) ~(B_PCH_PCR_SPX_PCD_RP1FN << ((PortIndex % 4) * S_PCH_PCR_SPX_PCD_RP_FIELD));
|
ControllerPcd[ControllerIndex] |= 0u;
|
//
|
// Origianl function zero on the same device takes the numer of the current port
|
//
|
ControllerPcd[FirstController] &= (UINT32) ~B_PCH_PCR_SPX_PCD_RP1FN;
|
ControllerPcd[FirstController] |= (UINT32) FuncNum;
|
|
//
|
// Program PSF1 RP function config register.
|
//
|
PsfSetPcieFunctionWithS3BootScript (OriginalFuncZeroRp, (UINT32) FuncNum);
|
PsfSetPcieFunctionWithS3BootScript (PortIndex, 0);
|
}
|
//
|
// Once enabled root port was found move to next PCI device
|
//
|
PortIndex = ((PortIndex / 8) + 1) * 8;
|
continue;
|
}
|
//
|
// Continue search for first enabled root port
|
//
|
PortIndex++;
|
}
|
|
//
|
// Write to PCD and lock the register
|
//
|
for (ControllerIndex = 0; ControllerIndex < PcieControllers; ++ControllerIndex) {
|
ControllerPid = PchGetPcieControllerSbiPid (ControllerIndex);
|
Data32 = ControllerPcd[ControllerIndex] | B_PCH_PCR_SPX_PCD_SRL;
|
PchPcrWrite32 (ControllerPid, R_PCH_PCR_SPX_PCD, Data32);
|
PCH_PCR_BOOT_SCRIPT_WRITE (
|
S3BootScriptWidthUint32,
|
ControllerPid, R_PCH_PCR_SPX_PCD,
|
1,
|
&Data32
|
);
|
}
|
return EFI_SUCCESS;
|
}
|
|