summaryrefslogtreecommitdiff
path: root/Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcieRpLib/PchPcieRpLib.c
diff options
context:
space:
mode:
authorJiewen Yao <jiewen.yao@intel.com>2017-06-19 10:55:06 +0800
committerJiewen Yao <jiewen.yao@intel.com>2017-06-20 15:12:29 +0800
commit646b243c0e3ef49b98071ca2c3fec15299b4d72f (patch)
tree00d62812fcedd3d1bf49692b863bb48a826f3ab0 /Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcieRpLib/PchPcieRpLib.c
parentf98787b719524d7ba9f2cefac0e8c8b8698cb02c (diff)
downloadedk2-platforms-646b243c0e3ef49b98071ca2c3fec15299b4d72f.tar.xz
Add KabylakeSiliconPkg
reviewed-by: Jiewen Yao <jiewen.yao@intel.com> reviewed-by: Michael A Kubacki <michael.a.kubacki@intel.com> reviewed-by: Amy Chan <amy.chan@intel.com> reviewed-by: Rangasai V Chaganty <rangasai.v.chaganty@intel.com> reviewed-by: Chasel Chiu <chasel.chiu@intel.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Jiewen Yao <jiewen.yao@intel.com> Signed-off-by: Chasel Chiu <chasel.chiu@intel.com>
Diffstat (limited to 'Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcieRpLib/PchPcieRpLib.c')
-rw-r--r--Silicon/Intel/KabylakeSiliconPkg/Pch/Library/PeiDxeSmmPchPcieRpLib/PchPcieRpLib.c268
1 files changed, 268 insertions, 0 deletions
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.<BR>
+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 <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/MmPciLib.h>
+#include <PchAccess.h>
+#include <Library/PchInfoLib.h>
+#include <Library/PchPcrLib.h>
+#include <Library/PchPcieRpLib.h>
+
+//
+// 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;
+}
+