/** @file This file contains functions that configures PCI Express Root Ports function swapping. Copyright (c) 2017, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include #include #include #include #include #include #include #include #include #include #include /** 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; }