From 646b243c0e3ef49b98071ca2c3fec15299b4d72f Mon Sep 17 00:00:00 2001 From: Jiewen Yao Date: Mon, 19 Jun 2017 10:55:06 +0800 Subject: Add KabylakeSiliconPkg reviewed-by: Jiewen Yao reviewed-by: Michael A Kubacki reviewed-by: Amy Chan reviewed-by: Rangasai V Chaganty reviewed-by: Chasel Chiu Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Jiewen Yao Signed-off-by: Chasel Chiu --- .../Library/PeiDxeSmmPchPcieRpLib/PchPcieRpLib.c | 268 +++++++++++++++++++++ 1 file changed, 268 insertions(+) create mode 100644 Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcieRpLib/PchPcieRpLib.c (limited to 'Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcieRpLib/PchPcieRpLib.c') diff --git a/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcieRpLib/PchPcieRpLib.c b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcieRpLib/PchPcieRpLib.c new file mode 100644 index 0000000000..6b8a51d8d2 --- /dev/null +++ b/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcieRpLib/PchPcieRpLib.c @@ -0,0 +1,268 @@ +/** @file + PCH PCIE root port library. + All function in this library is available for PEI, DXE, and SMM, + But do not support UEFI RUNTIME environment call. + +Copyright (c) 2017, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// +// For SKL PCH-LP, it supports three express port controllers: +// Controller 1: +// Port 1-4, Device 28, function 0-3 +// Controller 2: +// Port 5-8, Device 28, function 4-7 +// Controller 3: +// port 9-12, Device 29, function 0-3 +// For SKL PCH-H, it supports five express port controllers: +// Controller 1: +// Port 1-4, Device 28, function 0-3 +// Controller 2: +// Port 5-8, Device 28, function 4-7 +// Controller 3: +// port 9-12, Device 29, function 0-3 +// Controller 4: +// Port 13-16, Device 29, function 4-7 +// Controller 5: +// port 17-20, Device 27, function 0-3 +// +GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_PCIE_CONTROLLER_INFO mPchPcieControllerInfo[] = { + { PCI_DEVICE_NUMBER_PCH_PCIE_DEVICE_1, PID_SPA, 0 }, + { PCI_DEVICE_NUMBER_PCH_PCIE_DEVICE_1, PID_SPB, 4 }, + { PCI_DEVICE_NUMBER_PCH_PCIE_DEVICE_2, PID_SPC, 8 }, + { PCI_DEVICE_NUMBER_PCH_PCIE_DEVICE_2, PID_SPD, 12 }, // SKL-H and KBL-H only + { PCI_DEVICE_NUMBER_PCH_PCIE_DEVICE_3, PID_SPE, 16 }, // SKL-H and KBL-H only + { PCI_DEVICE_NUMBER_PCH_PCIE_DEVICE_3, PID_SPF, 20 } // KBL-H only +}; +GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 mPchPcieControllerInfoSize = sizeof (mPchPcieControllerInfo) / sizeof (mPchPcieControllerInfo[0]); + +GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mPchLpRstPcieStorageSupportedPort[] = { + RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, // RP1..RP4 + RST_PCIE_STORAGE_CR_2, RST_PCIE_STORAGE_CR_2, RST_PCIE_STORAGE_CR_2, RST_PCIE_STORAGE_CR_2, // RP5..RP8 + RST_PCIE_STORAGE_CR_3, RST_PCIE_STORAGE_CR_3, RST_PCIE_STORAGE_CR_3, RST_PCIE_STORAGE_CR_3 // RP9..RP12 +}; + +GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mSklPchHRstPcieStorageSupportedPort[] = { + RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, // RP1..RP4 + RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, // RP5..RP8 + RST_PCIE_STORAGE_CR_1, RST_PCIE_STORAGE_CR_1, RST_PCIE_STORAGE_CR_1, RST_PCIE_STORAGE_CR_1, // RP9..RP12 + RST_PCIE_STORAGE_CR_2, RST_PCIE_STORAGE_CR_2, RST_PCIE_STORAGE_CR_2, RST_PCIE_STORAGE_CR_2, // RP13..RP16 + RST_PCIE_STORAGE_CR_3, RST_PCIE_STORAGE_CR_3, RST_PCIE_STORAGE_CR_3, RST_PCIE_STORAGE_CR_3 // RP17..RP20 +}; + +GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mKblPchHRstPcieStorageSupportedPort[] = { + RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, // RP1..RP4 + RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, // RP5..RP8 + RST_PCIE_STORAGE_CR_1, RST_PCIE_STORAGE_CR_1, RST_PCIE_STORAGE_CR_1, RST_PCIE_STORAGE_CR_1, // RP9..RP12 + RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, RST_PCIE_STORAGE_CR_INVALID, // RP13..RP16 + RST_PCIE_STORAGE_CR_3, RST_PCIE_STORAGE_CR_3, RST_PCIE_STORAGE_CR_3, RST_PCIE_STORAGE_CR_3, // RP17..RP20 + RST_PCIE_STORAGE_CR_2, RST_PCIE_STORAGE_CR_2, RST_PCIE_STORAGE_CR_2, RST_PCIE_STORAGE_CR_2 // RP21..RP24 +}; + +/** + Get Pch Pcie Root Port Device and Function Number by Root Port physical Number + + @param[in] RpNumber Root port physical number. (0-based) + @param[out] RpDev Return corresponding root port device number. + @param[out] RpFun Return corresponding root port function number. + + @retval EFI_SUCCESS Root port device and function is retrieved + @retval EFI_INVALID_PARAMETER RpNumber is invalid +**/ +EFI_STATUS +EFIAPI +GetPchPcieRpDevFun ( + IN UINTN RpNumber, + OUT UINTN *RpDev, + OUT UINTN *RpFun + ) +{ + UINTN Index; + UINTN FuncIndex; + UINT32 PciePcd; + + // + // if SKL PCH-LP, RpNumber must be < 12. + // if SKL PCH-H , RpNumber must be < 20. + // if KBL PCH-H , RpNumber must be < 24. + // + if (RpNumber >= GetPchMaxPciePortNum ()) { + DEBUG ((DEBUG_ERROR, "GetPchPcieRpDevFun invalid RpNumber %x", RpNumber)); + ASSERT (FALSE); + return EFI_INVALID_PARAMETER; + } + + Index = RpNumber / PCH_PCIE_CONTROLLER_PORTS; + FuncIndex = RpNumber - mPchPcieControllerInfo[Index].RpNumBase; + *RpDev = mPchPcieControllerInfo[Index].DevNum; + PchPcrRead32 (mPchPcieControllerInfo[Index].Pid, R_PCH_PCR_SPX_PCD, &PciePcd); + *RpFun = (PciePcd >> (FuncIndex * S_PCH_PCR_SPX_PCD_RP_FIELD)) & B_PCH_PCR_SPX_PCD_RP1FN; + + return EFI_SUCCESS; +} + +/** + Get Root Port physical Number by Pch Pcie Root Port Device and Function Number + + @param[in] RpDev Root port device number. + @param[in] RpFun Root port function number. + @param[out] RpNumber Return corresponding physical Root Port index (0-based) + + @retval EFI_SUCCESS Physical root port is retrieved + @retval EFI_INVALID_PARAMETER RpDev and/or RpFun are invalid + @retval EFI_UNSUPPORTED Root port device and function is not assigned to any physical root port +**/ +EFI_STATUS +EFIAPI +GetPchPcieRpNumber ( + IN UINTN RpDev, + IN UINTN RpFun, + OUT UINTN *RpNumber + ) +{ + UINTN Index; + UINTN FuncIndex; + UINT32 PciePcd; + UINT8 MaxPorts; + + MaxPorts = GetPchMaxPciePortNum (); + if ( !((RpDev == PCI_DEVICE_NUMBER_PCH_PCIE_DEVICE_1) && (RpFun < 8) && (RpFun < MaxPorts)) && + !((RpDev == PCI_DEVICE_NUMBER_PCH_PCIE_DEVICE_2) && (RpFun < 8) && (RpFun + 8 < MaxPorts)) && + !((RpDev == PCI_DEVICE_NUMBER_PCH_PCIE_DEVICE_3) && (RpFun < 8) && (RpFun + 16 < MaxPorts)) ) { + DEBUG ((DEBUG_ERROR, "GetPchPcieRpNumber invalid RpDev %x RpFun %x", RpDev, RpFun)); + ASSERT (FALSE); + return EFI_INVALID_PARAMETER; + } + + for (Index = 0; Index < mPchPcieControllerInfoSize; Index++) { + if (mPchPcieControllerInfo[Index].DevNum == RpDev) { + PchPcrRead32 (mPchPcieControllerInfo[Index].Pid, R_PCH_PCR_SPX_PCD, &PciePcd); + for (FuncIndex = 0; FuncIndex < 4; FuncIndex ++) { + if (RpFun == ((PciePcd >> (FuncIndex * S_PCH_PCR_SPX_PCD_RP_FIELD)) & B_PCH_PCR_SPX_PCD_RP1FN)) { + break; + } + } + if (FuncIndex < 4) { + *RpNumber = mPchPcieControllerInfo[Index].RpNumBase + FuncIndex; + break; + } + } + } + if (Index >= mPchPcieControllerInfoSize) { + return EFI_UNSUPPORTED; + } + + return EFI_SUCCESS; +} + +/** + Gets base address of PCIe root port. + + @param RpIndex Root Port Index (0 based) + @return PCIe port base address. +**/ +UINTN +PchPcieBase ( + IN UINT32 RpIndex + ) +{ + UINTN RpDevice; + UINTN RpFunction; + GetPchPcieRpDevFun (RpIndex, &RpDevice, &RpFunction); + return MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH, (UINT32) RpDevice, (UINT32) RpFunction); +} + +/** + Determines whether L0s is supported on current stepping. + + @return TRUE if L0s is supported, FALSE otherwise +**/ +BOOLEAN +PchIsPcieL0sSupported ( + VOID + ) +{ + if (GetPchGeneration () == SklPch) { + if (GetPchSeries () == PchLp) { + if (PchStepping () < PchLpC0) { + return FALSE; + } + } else { + if (PchStepping () < PchHD0) { + return FALSE; + } + } + } + + return TRUE; +} + +/** + Some early SKL PCH steppings require Native ASPM to be disabled due to hardware issues: + - RxL0s exit causes recovery + - Disabling PCIe L0s capability disables L1 + Use this function to determine affected steppings. + + @return TRUE if Native ASPM is supported, FALSE otherwise +**/ +BOOLEAN +PchIsPcieNativeAspmSupported ( + VOID + ) +{ + return PchIsPcieL0sSupported (); +} + +/** + Check the RST PCIe Storage Cycle Router number according to the root port number and PCH type + + @param[in] RootPortNum Root Port Number + + @retval UINT32 The RST PCIe Storage Cycle Router Number +**/ +UINT32 +RstGetCycleRouterNumber ( + IN UINT32 RootPortNum + ) +{ + PCH_SERIES PchSeries; + + PchSeries = GetPchSeries (); + + if (PchSeries == PchLp) { + if (RootPortNum < PCH_LP_PCIE_MAX_ROOT_PORTS) { + return mPchLpRstPcieStorageSupportedPort[RootPortNum]; + } + } else { + if (GetPchGeneration () == KblPch) { + if (RootPortNum < KBL_PCH_H_PCIE_MAX_ROOT_PORTS) { + return mKblPchHRstPcieStorageSupportedPort[RootPortNum]; + } + } else { + if (RootPortNum < SKL_PCH_H_PCIE_MAX_ROOT_PORTS) { + return mSklPchHRstPcieStorageSupportedPort[RootPortNum]; + } + } + } + return RST_PCIE_STORAGE_CR_INVALID; +} + -- cgit v1.2.3