Browse Source

Ampere: PCIe: Add support for Ampere Altra Max

This updates the platform specific PCIe modules to
add support for Ampere Altra Max processor which
features 128 PCIe Gen4 lanes (distributed across
eight x16 RCAs) using 32 controllers.

Signed-off-by: Nhi Pham <nhi@os.amperecomputing.com>
Reviewed-by: Leif Lindholm <quic_llindhol@quicinc.com>
Vu Nguyen 1 year ago
parent
commit
0c0b039e02

+ 68 - 7
Platform/Ampere/JadePkg/Library/BoardPcieLib/BoardPcieLib.c

@@ -38,6 +38,54 @@ BoardPcieReleaseAllPerst (
   MicroSecondDelay (PCIE_PERST_DELAY);
 }
 
+EFI_STATUS
+GetGpioGroup (
+  IN  UINT8 RootComplexId,
+  IN  UINT8 PcieIndex,
+  OUT UINT32 *GpioGroupVal
+  )
+{
+  /* Ampere Altra Max RootComplex->ID: 4:7 */
+  if (PcieIndex < 2) {
+    switch (RootComplexId) {
+      case 4:
+        *GpioGroupVal = 34 - (PcieIndex * 2);
+        break;
+      case 5:
+        *GpioGroupVal = 38 - (PcieIndex * 2);
+        break;
+      case 6:
+        *GpioGroupVal = 30 - (PcieIndex * 2);
+        break;
+      case 7:
+        *GpioGroupVal = 26 - (PcieIndex * 2);
+        break;
+      default:
+        return EFI_INVALID_PARAMETER;
+    }
+  } else {
+    /* Ampere Altra Max RootComplex->ID: 4:7 */
+    switch (RootComplexId) {
+      case 4:
+        *GpioGroupVal = 46 - ((PcieIndex - 2) * 2);
+        break;
+      case 5:
+        *GpioGroupVal = 42 - ((PcieIndex - 2) * 2);
+        break;
+      case 6:
+        *GpioGroupVal = 18 - ((PcieIndex - 2) * 2);
+        break;
+      case 7:
+        *GpioGroupVal = 22 - ((PcieIndex - 2) * 2);
+        break;
+      default:
+        return EFI_INVALID_PARAMETER;
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
 /**
   Assert PERST of PCIe controller
 
@@ -56,15 +104,28 @@ BoardPcieAssertPerst (
   IN BOOLEAN           IsPullToHigh
   )
 {
-  UINT32 GpioGroupVal, Val, GpioIndex, GpioPin;
+  UINT32     GpioGroupVal;
+  UINT32     Val;
+  UINT32     GpioIndex;
+  UINT32     GpioPin;
+  EFI_STATUS Status;
 
   if (!IsPullToHigh) {
     if (RootComplex->Type == RootComplexTypeA) {
-      //
-      // RootComplexTypeA: RootComplex->ID: 0->3 ; PcieIndex: 0->3
-      //
-      GpioGroupVal = RCA_MAX_PERST_GROUPVAL - PcieIndex
-                     - RootComplex->ID * MaxPcieControllerOfRootComplexA;
+      if (RootComplex->ID < MaxPcieControllerOfRootComplexA) {
+        /* Ampere Altra: 4 */
+        //
+        // RootComplexTypeA: RootComplex->ID: 0->3 ; PcieIndex: 0->3
+        //
+        GpioGroupVal = RCA_MAX_PERST_GROUPVAL - PcieIndex
+                       - RootComplex->ID * MaxPcieControllerOfRootComplexA;
+      } else {
+        Status = GetGpioGroup (RootComplex->ID, PcieIndex, &GpioGroupVal);
+        if (EFI_ERROR (Status)) {
+          DEBUG ((DEBUG_ERROR, "Invalid Root Complex ID %d\n", RootComplex->ID));
+          return Status;
+        }
+      }
     } else {
       //
       // RootComplexTypeB: RootComplex->ID: 4->7 ; PcieIndex: 0->7
@@ -117,5 +178,5 @@ BoardPcieGetSegmentNumber (
     return Ac01BoardSegment[RootComplex->Socket][RootComplex->ID];
   }
 
-  return DEFAULT_SEGMENT_NUMBER;
+  return (RootComplex->ID - 2);
 }

+ 78 - 49
Silicon/Ampere/AmpereAltraPkg/Drivers/PcieInitPei/PcieInitPei.c

@@ -40,61 +40,33 @@ STATIC UINT64                   mMmio32Size1P[AC01_PCIE_MAX_ROOT_COMPLEX]    = {
 STATIC UINT64                   mMmioBase[AC01_PCIE_MAX_ROOT_COMPLEX]        = { AC01_PCIE_MMIO_BASE_LIST };
 STATIC UINT64                   mMmioSize[AC01_PCIE_MAX_ROOT_COMPLEX]        = { AC01_PCIE_MMIO_SIZE_LIST };
 
-VOID
-BuildRootComplexData (
-  VOID
+AC01_ROOT_COMPLEX_TYPE
+GetRootComplexType (
+  UINT8 RootComplexId
   )
 {
-  AC01_ROOT_COMPLEX                    *RootComplex;
-  BOOLEAN                              ConfigFound;
-  EFI_PEI_READ_ONLY_VARIABLE2_PPI      *VariablePpi;
-  EFI_STATUS                           Status;
-  ROOT_COMPLEX_CONFIG_VARSTORE_DATA    RootComplexConfig;
-  UINT8                                RCIndex;
-  UINT8                                PcieIndex;
-  UINTN                                DataSize;
-
-  ConfigFound = FALSE;
-
-  //
-  // Get the Root Complex config from NVRAM
-  //
-  Status = PeiServicesLocatePpi (
-             &gEfiPeiReadOnlyVariable2PpiGuid,
-             0,
-             NULL,
-             (VOID **)&VariablePpi
-             );
-  if (!EFI_ERROR (Status)) {
-    DataSize = sizeof (RootComplexConfig);
-    Status = VariablePpi->GetVariable (
-                            VariablePpi,
-                            ROOT_COMPLEX_CONFIG_VARSTORE_NAME,
-                            &gRootComplexConfigFormSetGuid,
-                            NULL,
-                            &DataSize,
-                            &RootComplexConfig
-                            );
-    if (!EFI_ERROR (Status)) {
-      ConfigFound = TRUE;
-    }
+  if (IsAc01Processor ()) {
+    return (RootComplexId < MaxRootComplexA) ? RootComplexTypeA : RootComplexTypeB;
   }
 
-  ZeroMem (&mRootComplexList, sizeof (AC01_ROOT_COMPLEX) * AC01_PCIE_MAX_ROOT_COMPLEX);
+  return RootComplexTypeA;
+}
 
-  //
-  // Adjust Root Complex MMIO32 base address in 1P or 2P configuration
-  //
-  if (!IsSlaveSocketAvailable ()) {
-    CopyMem ((VOID *)&mMmio32Base, (VOID *)&mMmio32Base1P, sizeof (mMmio32Base1P));
-    CopyMem ((VOID *)&mMmio32Size, (VOID *)&mMmio32Size1P, sizeof (mMmio32Size1P));
-  }
+VOID
+ConfigureRootComplex (
+  BOOLEAN                           IsConfigFound,
+  ROOT_COMPLEX_CONFIG_VARSTORE_DATA RootComplexConfig
+  )
+{
+  UINT8             RCIndex;
+  UINT8             PcieIndex;
+  AC01_ROOT_COMPLEX *RootComplex;
 
   for (RCIndex = 0; RCIndex < AC01_PCIE_MAX_ROOT_COMPLEX; RCIndex++) {
     RootComplex = &mRootComplexList[RCIndex];
-    RootComplex->Active = ConfigFound ? RootComplexConfig.RCStatus[RCIndex] : TRUE;
-    RootComplex->DevMapLow = ConfigFound ? RootComplexConfig.RCBifurcationLow[RCIndex] : 0;
-    RootComplex->DevMapHigh = ConfigFound ? RootComplexConfig.RCBifurcationHigh[RCIndex] : 0;
+    RootComplex->Active = IsConfigFound ? RootComplexConfig.RCStatus[RCIndex] : TRUE;
+    RootComplex->DevMapLow = IsConfigFound ? RootComplexConfig.RCBifurcationLow[RCIndex] : 0;
+    RootComplex->DevMapHigh = IsConfigFound ? RootComplexConfig.RCBifurcationHigh[RCIndex] : 0;
     RootComplex->Socket = RCIndex / AC01_PCIE_MAX_RCS_PER_SOCKET;
     RootComplex->ID = RCIndex % AC01_PCIE_MAX_RCS_PER_SOCKET;
     RootComplex->CsrBase = mCsrBase[RCIndex];
@@ -106,7 +78,7 @@ BuildRootComplexData (
     RootComplex->MmioSize = mMmioSize[RCIndex];
     RootComplex->Mmio32Base = mMmio32Base[RCIndex];
     RootComplex->Mmio32Size = mMmio32Size[RCIndex];
-    RootComplex->Type = (RootComplex->ID < MaxRootComplexA) ? RootComplexTypeA : RootComplexTypeB;
+    RootComplex->Type = GetRootComplexType (RootComplex->ID);
     RootComplex->MaxPcieController = (RootComplex->Type == RootComplexTypeB)
                                      ? MaxPcieControllerOfRootComplexB : MaxPcieControllerOfRootComplexA;
     RootComplex->Logical = BoardPcieGetSegmentNumber (RootComplex);
@@ -146,6 +118,60 @@ BuildRootComplexData (
   }
 }
 
+VOID
+BuildRootComplexData (
+  VOID
+  )
+{
+  BOOLEAN                              IsConfigFound;
+  EFI_PEI_READ_ONLY_VARIABLE2_PPI      *VariablePpi;
+  EFI_STATUS                           Status;
+  ROOT_COMPLEX_CONFIG_VARSTORE_DATA    RootComplexConfig;
+  UINTN                                DataSize;
+
+  IsConfigFound = FALSE;
+  ZeroMem ((VOID *)&RootComplexConfig, sizeof (ROOT_COMPLEX_CONFIG_VARSTORE_DATA));
+
+  //
+  // Get the Root Complex config from NVRAM
+  //
+  Status = PeiServicesLocatePpi (
+             &gEfiPeiReadOnlyVariable2PpiGuid,
+             0,
+             NULL,
+             (VOID **)&VariablePpi
+             );
+  if (!EFI_ERROR (Status)) {
+    DataSize = sizeof (RootComplexConfig);
+    Status = VariablePpi->GetVariable (
+                            VariablePpi,
+                            ROOT_COMPLEX_CONFIG_VARSTORE_NAME,
+                            &gRootComplexConfigFormSetGuid,
+                            NULL,
+                            &DataSize,
+                            &RootComplexConfig
+                            );
+    if (!EFI_ERROR (Status)) {
+      IsConfigFound = TRUE;
+    }
+  }
+
+  ZeroMem (&mRootComplexList, sizeof (AC01_ROOT_COMPLEX) * AC01_PCIE_MAX_ROOT_COMPLEX);
+
+  //
+  // Adjust Root Complex MMIO32 base address in 1P or 2P configuration
+  //
+  if (!IsSlaveSocketAvailable ()) {
+    CopyMem ((VOID *)&mMmio32Base, (VOID *)&mMmio32Base1P, sizeof (mMmio32Base1P));
+    CopyMem ((VOID *)&mMmio32Size, (VOID *)&mMmio32Size1P, sizeof (mMmio32Size1P));
+  }
+
+  //
+  // All necessary information is available, config Root complex accordingly
+  //
+  ConfigureRootComplex (IsConfigFound, RootComplexConfig);
+}
+
 EFI_STATUS
 EFIAPI
 PcieInitEntry (
@@ -168,11 +194,14 @@ PcieInitEntry (
       continue;
     }
 
+    DEBUG ((DEBUG_INIT, "Initializing S%d-RC%d...", RootComplex->Socket, RootComplex->ID));
     Status = Ac01PcieCoreSetupRC (RootComplex, FALSE, 0);
     if (EFI_ERROR (Status)) {
-      DEBUG ((DEBUG_ERROR, "RootComplex[%d]: Init Failed\n", Index));
+      DEBUG ((DEBUG_ERROR, "Failed\n"));
       RootComplex->Active = FALSE;
       continue;
+    } else {
+      DEBUG ((DEBUG_INIT, "Done + DevMapLow/High: %d/%d\n", RootComplex->DevMapLow, RootComplex->DevMapHigh));
     }
   }
 

+ 216 - 128
Silicon/Ampere/AmpereAltraPkg/Drivers/PcieInitPei/RootComplexNVParam.c

@@ -37,7 +37,7 @@
   |  Y   |  Y   |  Y   |  Y   | 3        |
   ----------------------------------------
 
-  Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+  Copyright (c) 2020 - 2023, Ampere Computing LLC. All rights reserved.<BR>
 
   SPDX-License-Identifier: BSD-2-Clause-Patent
 
@@ -55,6 +55,12 @@
 
 #include "RootComplexNVParam.h"
 
+typedef enum {
+  Gen3Preset = 0,
+  Gen4Preset,
+  GenPresetMax
+} NVPARAM_PCIE_PRESET_TYPE;
+
 STATIC
 BOOLEAN
 IsEmptyRC (
@@ -144,85 +150,233 @@ SetRootComplexBifurcation (
   }
 }
 
-VOID
+DEV_MAP_MODE
 GetDefaultDevMap (
-  AC01_ROOT_COMPLEX *RootComplex
+  IN AC01_ROOT_COMPLEX *RootComplex,
+  IN BOOLEAN           IsGetDevMapLow
   )
 {
-  if (RootComplex->Pcie[PcieController0].Active
-      && RootComplex->Pcie[PcieController1].Active
-      && RootComplex->Pcie[PcieController2].Active
-      && RootComplex->Pcie[PcieController3].Active) {
-    RootComplex->DefaultDevMapLow = DevMapMode4;
-  } else if (RootComplex->Pcie[PcieController0].Active
-             && RootComplex->Pcie[PcieController2].Active
-             && RootComplex->Pcie[PcieController3].Active) {
-    RootComplex->DefaultDevMapLow = DevMapMode3;
-  } else if (RootComplex->Pcie[PcieController0].Active
-             && RootComplex->Pcie[PcieController2].Active) {
-    RootComplex->DefaultDevMapLow = DevMapMode2;
-  } else {
-    RootComplex->DefaultDevMapLow = DevMapMode1;
-  }
+  UINT8        StartIndex;
+  DEV_MAP_MODE DevMapMode;
+
+  DevMapMode = MaxDevMapMode;
+  StartIndex = IsGetDevMapLow ? PcieController0 : PcieController4;
+
+  while (DevMapMode >= DevMapMode1)
+  {
+    switch (DevMapMode) {
+    case DevMapMode4:
+      if (RootComplex->Pcie[StartIndex].Active
+          && RootComplex->Pcie[StartIndex + 1].Active
+          && RootComplex->Pcie[StartIndex + 2].Active
+          && RootComplex->Pcie[StartIndex + 3].Active) {
+            return DevMapMode4;
+          }
+      break;
+    case DevMapMode3:
+      if (RootComplex->Pcie[StartIndex].Active
+          && RootComplex->Pcie[StartIndex + 2].Active
+          && RootComplex->Pcie[StartIndex + 3].Active) {
+            return DevMapMode3;
+          }
+      break;
+    case DevMapMode2:
+      if (RootComplex->Pcie[StartIndex].Active
+          && RootComplex->Pcie[StartIndex + 2].Active) {
+            return DevMapMode2;
+          }
+      break;
+    default:
+      return DevMapMode1;
+    }
 
-  if (RootComplex->Pcie[PcieController4].Active
-      && RootComplex->Pcie[PcieController5].Active
-      && RootComplex->Pcie[PcieController6].Active
-      && RootComplex->Pcie[PcieController7].Active) {
-    RootComplex->DefaultDevMapHigh = DevMapMode4;
-  } else if (RootComplex->Pcie[PcieController4].Active
-             && RootComplex->Pcie[PcieController6].Active
-             && RootComplex->Pcie[PcieController7].Active) {
-    RootComplex->DefaultDevMapHigh = DevMapMode3;
-  } else if (RootComplex->Pcie[PcieController4].Active
-             && RootComplex->Pcie[PcieController6].Active) {
-    RootComplex->DefaultDevMapHigh = DevMapMode2;
-  } else {
-    RootComplex->DefaultDevMapHigh = DevMapMode1;
+    DevMapMode--;
   }
 
+  return DevMapMode1;
+}
+
+VOID
+GetDevMap (
+  IN OUT AC01_ROOT_COMPLEX *RootComplex
+  )
+{
+  //
+  // Get default Devmap low and configure Devmap low accordingly.
+  //
+  RootComplex->DefaultDevMapLow = GetDefaultDevMap (RootComplex, TRUE);
   if (RootComplex->DevMapLow == 0) {
     RootComplex->DevMapLow = RootComplex->DefaultDevMapLow;
   }
 
+  //
+  // Get default Devmap high and configure Devmap high accordingly.
+  //
+  RootComplex->DefaultDevMapHigh = IsAc01Processor () ? GetDefaultDevMap (RootComplex, FALSE) : DevMapMode1;
   if (RootComplex->Type == RootComplexTypeB && RootComplex->DevMapHigh == 0) {
     RootComplex->DevMapHigh = RootComplex->DefaultDevMapHigh;
   }
 
+  //
+  // Set bifurcation bases on Devmap high and Devmap low.
+  //
   SetRootComplexBifurcation (RootComplex, PcieController0, RootComplex->DevMapLow);
   if (RootComplex->Type == RootComplexTypeB) {
     SetRootComplexBifurcation (RootComplex, PcieController4, RootComplex->DevMapHigh);
   }
 }
 
+UINT8
+GetMaxController (
+  IN AC01_ROOT_COMPLEX *RootComplex
+  )
+{
+  if (IsAc01Processor ()) {
+    return MaxPcieControllerOfRootComplexA;
+  }
+
+  return RootComplex->MaxPcieController;
+}
+
+NVPARAM
+CalculateNvParamOffset (
+  IN AC01_ROOT_COMPLEX *RootComplex,
+  IN UINT8             PaddingOrder,
+  IN UINT8             StartIndex,
+  IN UINT64            StartOffset
+  )
+{
+  UINT8   NeededPadding;
+  INT8    PositionFromStartIndex;
+  NVPARAM NvParamOffset;
+
+
+  NeededPadding = RootComplex->ID - PaddingOrder;
+  PositionFromStartIndex = (RootComplex->ID - StartIndex) + NeededPadding;
+  NvParamOffset = StartOffset + PositionFromStartIndex * NV_PARAM_ENTRYSIZE;
+
+  return NvParamOffset;
+}
+
+EFI_STATUS_CODE_TYPE
+GetNvParamOffsetLane (
+  IN  AC01_ROOT_COMPLEX *RootComplex,
+  OUT NVPARAM           *NvParamOffset
+  )
+{
+  BOOLEAN IsAc01;
+  BOOLEAN IsRootComplexTypeA;
+  BOOLEAN IsSocket0;
+  UINT8   StartIndex;
+  UINT64  StartOffset;
+  UINT8   PaddingOrder;
+
+  IsSocket0 = RootComplex->Socket == 0 ? TRUE : FALSE;
+  IsAc01 = IsAc01Processor ();
+  IsRootComplexTypeA = RootComplex->Type == RootComplexTypeA ? TRUE : FALSE;
+
+  if (!IsAc01 && (RootComplex->ID >= MaxPcieControllerOfRootComplexA)) {
+    // Because from NV_SI_RO_BOARD_S0_RCA4_CFG to NV_SI_RO_BOARD_S0_RCA7_CFG for supporting
+    // Altra Max are not sequential arrangement with NV_SI_RO_BOARD_S0_RCA0_CFG
+    // so the start index will be the first Root Complex ID which using these NVParams
+    // (NV_SI_RO_BOARD_S0_RCA4_CFG to NV_SI_RO_BOARD_S0_RCA7_CFG) to support Altra Max processor.
+    StartIndex = 4;
+    StartOffset = IsSocket0 ? NV_SI_RO_BOARD_S0_RCA4_CFG : NV_SI_RO_BOARD_S1_RCA4_CFG;
+    PaddingOrder = RootComplex->ID;
+  } else {
+    StartIndex = 0;
+    StartOffset = IsSocket0 ? NV_SI_RO_BOARD_S0_RCA0_CFG : NV_SI_RO_BOARD_S1_RCA0_CFG;
+    PaddingOrder = IsRootComplexTypeA ? RootComplex->ID : MaxRootComplexA;
+  }
+
+  *NvParamOffset = CalculateNvParamOffset (RootComplex, PaddingOrder, StartIndex, StartOffset);
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+GetNvParamOffsetPreset (
+  IN  AC01_ROOT_COMPLEX        *RootComplex,
+  IN  NVPARAM_PCIE_PRESET_TYPE PresetType,
+  OUT NVPARAM                  *NvParamOffset
+  )
+{
+  BOOLEAN IsAc01;
+  BOOLEAN IsRootComplexTypeA;
+  BOOLEAN IsSocket0;
+  UINT8   StartIndex;
+  UINT64  StartOffset;
+  UINT8   PaddingOrder;
+
+  IsSocket0 = RootComplex->Socket == 0 ? TRUE : FALSE;
+  IsAc01 = IsAc01Processor ();
+  IsRootComplexTypeA = RootComplex->Type == RootComplexTypeA ? TRUE : FALSE;
+
+  switch (PresetType) {
+  case Gen3Preset:
+    if (IsAc01) {
+      StartOffset = IsSocket0 ? NV_SI_RO_BOARD_S0_RCA0_TXRX_G3PRESET :
+                                NV_SI_RO_BOARD_S1_RCA2_TXRX_G3PRESET;
+    } else {
+      StartOffset = IsSocket0 ? NV_SI_RO_BOARD_MQ_S0_RCA0_TXRX_G3PRESET :
+                                NV_SI_RO_BOARD_MQ_S1_RCA2_TXRX_G3PRESET;
+    }
+    break;
+
+  case Gen4Preset:
+    if (IsAc01) {
+      StartOffset = IsSocket0 ? NV_SI_RO_BOARD_S0_RCA0_TXRX_G4PRESET :
+                                NV_SI_RO_BOARD_S1_RCA2_TXRX_G4PRESET;
+    } else {
+      StartOffset = IsSocket0 ? NV_SI_RO_BOARD_MQ_S0_RCA0_TXRX_G4PRESET :
+                                NV_SI_RO_BOARD_MQ_S1_RCA2_TXRX_G4PRESET;
+    }
+    break;
+
+  default:
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // For Socket 0, NVParams for all Root Complexes are supported so starting from RCA0.
+  // For Socket 1, NVParams for RCA0 and RCA1 are not supported so starting from RCA2.
+  //
+  StartIndex = IsSocket0 ? 0 : 2;
+  //
+  // There're two NVParam entries per RootComplexTypeB
+  // so padding need to be start from MaxRootComplexA to
+  // get the first NVParam entry of RootComplexTypeB
+  //
+  PaddingOrder = IsRootComplexTypeA ? RootComplex->ID : MaxRootComplexA;
+
+  *NvParamOffset = CalculateNvParamOffset (RootComplex, PaddingOrder, StartIndex, StartOffset);
+
+  return EFI_SUCCESS;
+}
+
 VOID
 GetLaneAllocation (
-  AC01_ROOT_COMPLEX *RootComplex
+  IN OUT AC01_ROOT_COMPLEX *RootComplex
   )
 {
   EFI_STATUS Status;
   INTN       RPIndex;
   NVPARAM    NvParamOffset;
-  UINT32     Value, Width;
+  UINT32     Value;
+  UINT32     Width;
+  UINT32     MaxController;
 
-  // Retrieve lane allocation and capabilities for each controller
-  if (RootComplex->Type == RootComplexTypeA) {
-    NvParamOffset = (RootComplex->Socket == 0) ? NV_SI_RO_BOARD_S0_RCA0_CFG : NV_SI_RO_BOARD_S1_RCA0_CFG;
-    NvParamOffset += RootComplex->ID * NV_PARAM_ENTRYSIZE;
+  Status = GetNvParamOffsetLane (RootComplex, &NvParamOffset);
+  if (!EFI_ERROR (Status)) {
+    Status = NVParamGet (NvParamOffset, NV_PERM_ALL, &Value);
+    if (EFI_ERROR (Status)) {
+      Value = 0;
+    }
   } else {
-    //
-    // There're two NVParam entries per RootComplexTypeB
-    //
-    NvParamOffset = (RootComplex->Socket == 0) ? NV_SI_RO_BOARD_S0_RCB0_LO_CFG : NV_SI_RO_BOARD_S1_RCB0_LO_CFG;
-    NvParamOffset += (RootComplex->ID - MaxRootComplexA) * (NV_PARAM_ENTRYSIZE * 2);
-  }
-
-  Status = NVParamGet (NvParamOffset, NV_PERM_ALL, &Value);
-  if (EFI_ERROR (Status)) {
     Value = 0;
   }
 
-  for (RPIndex = 0; RPIndex < MaxPcieControllerOfRootComplexA; RPIndex++) {
+  MaxController = GetMaxController (RootComplex);
+  for (RPIndex = PcieController0; RPIndex < MaxController; RPIndex++) {
     Width = (Value >> (RPIndex * BITS_PER_BYTE)) & BYTE_MASK;
     switch (Width) {
     case 1:
@@ -278,78 +432,6 @@ GetLaneAllocation (
   }
 }
 
-NVPARAM
-GetGen3PresetNvParamOffset (
-  AC01_ROOT_COMPLEX *RootComplex
-  )
-{
-  NVPARAM NvParamOffset;
-
-  if (RootComplex->Socket == 0) {
-    if (RootComplex->Type == RootComplexTypeA) {
-      if (RootComplex->ID < MaxRootComplexA) {
-        NvParamOffset = NV_SI_RO_BOARD_S0_RCA0_TXRX_G3PRESET + RootComplex->ID * NV_PARAM_ENTRYSIZE;
-      } else {
-        NvParamOffset = NV_SI_RO_BOARD_S0_RCA4_TXRX_G3PRESET + (RootComplex->ID - MaxRootComplexA) * NV_PARAM_ENTRYSIZE;
-      }
-    } else {
-      //
-      // There're two NVParam entries per RootComplexTypeB
-      //
-      NvParamOffset = NV_SI_RO_BOARD_S0_RCB0A_TXRX_G3PRESET + (RootComplex->ID - MaxRootComplexA) * (NV_PARAM_ENTRYSIZE * 2);
-    }
-  } else if (RootComplex->Type == RootComplexTypeA) {
-    if (RootComplex->ID < MaxRootComplexA) {
-      NvParamOffset = NV_SI_RO_BOARD_S1_RCA2_TXRX_G3PRESET + (RootComplex->ID - 2) * NV_PARAM_ENTRYSIZE;
-    } else {
-      NvParamOffset = NV_SI_RO_BOARD_S1_RCA4_TXRX_G3PRESET + (RootComplex->ID - MaxRootComplexA) * NV_PARAM_ENTRYSIZE;
-    }
-  } else {
-    //
-    // There're two NVParam entries per RootComplexTypeB
-    //
-    NvParamOffset = NV_SI_RO_BOARD_S1_RCB0A_TXRX_G3PRESET + (RootComplex->ID - MaxRootComplexA) * (NV_PARAM_ENTRYSIZE * 2);
-  }
-
-  return NvParamOffset;
-}
-
-NVPARAM
-GetGen4PresetNvParamOffset (
-  AC01_ROOT_COMPLEX *RootComplex
-  )
-{
-  NVPARAM NvParamOffset;
-
-  if (RootComplex->Socket == 0) {
-    if (RootComplex->Type == RootComplexTypeA) {
-      if (RootComplex->ID < MaxRootComplexA) {
-        NvParamOffset = NV_SI_RO_BOARD_S0_RCA0_TXRX_G4PRESET + RootComplex->ID * NV_PARAM_ENTRYSIZE;
-      } else {
-        NvParamOffset = NV_SI_RO_BOARD_S0_RCA4_TXRX_G4PRESET + (RootComplex->ID - MaxRootComplexA) * NV_PARAM_ENTRYSIZE;
-      }
-    } else {
-      //
-      // There're two NVParam entries per RootComplexTypeB
-      //
-      NvParamOffset = NV_SI_RO_BOARD_S0_RCB0A_TXRX_G4PRESET + (RootComplex->ID - MaxRootComplexA) * (NV_PARAM_ENTRYSIZE * 2);
-    }
-  } else if (RootComplex->Type == RootComplexTypeA) {
-    if (RootComplex->ID < MaxRootComplexA) {
-      NvParamOffset = NV_SI_RO_BOARD_S1_RCA2_TXRX_G4PRESET + (RootComplex->ID - 2) * NV_PARAM_ENTRYSIZE;
-    } else {
-      NvParamOffset = NV_SI_RO_BOARD_S1_RCA4_TXRX_G4PRESET + (RootComplex->ID - MaxRootComplexA) * NV_PARAM_ENTRYSIZE;
-    }
-  } else {
-    //
-    // There're two NVParam entries per RootComplexTypeB
-    //
-    NvParamOffset = NV_SI_RO_BOARD_S1_RCB0A_TXRX_G4PRESET + (RootComplex->ID - MaxRootComplexA) * (NV_PARAM_ENTRYSIZE * 2);
-  }
-
-  return NvParamOffset;
-}
-
 VOID
 GetPresetSetting (
   AC01_ROOT_COMPLEX *RootComplex
@@ -366,9 +448,11 @@ GetPresetSetting (
     RootComplex->PresetGen4[Index] = PRESET_INVALID;
   }
 
-  NvParamOffset = GetGen3PresetNvParamOffset (RootComplex);
-
-  Status = NVParamGet (NvParamOffset, NV_PERM_ALL, &Value);
+  // Get NVParam offset of Gen3 preset
+  Status = GetNvParamOffsetPreset (RootComplex, Gen3Preset, &NvParamOffset);
+  if (!EFI_ERROR (Status)) {
+    Status = NVParamGet (NvParamOffset, NV_PERM_ALL, &Value);
+  }
   if (!EFI_ERROR (Status)) {
     for (Index = 0; Index < MaxPcieControllerOfRootComplexA; Index++) {
       RootComplex->PresetGen3[Index] = (Value >> (Index * BITS_PER_BYTE)) & BYTE_MASK;
@@ -385,9 +469,11 @@ GetPresetSetting (
     }
   }
 
-  NvParamOffset = GetGen4PresetNvParamOffset (RootComplex);
-
-  Status = NVParamGet (NvParamOffset, NV_PERM_ALL, &Value);
+  // Get NVParam offset of Gen4 preset.
+  Status = GetNvParamOffsetPreset (RootComplex, Gen4Preset, &NvParamOffset);
+  if (!EFI_ERROR (Status)) {
+    Status = NVParamGet (NvParamOffset, NV_PERM_ALL, &Value);
+  }
   if (!EFI_ERROR (Status)) {
     for (Index = 0; Index < MaxPcieControllerOfRootComplexA; Index++) {
       RootComplex->PresetGen4[Index] = (Value >> (Index * BITS_PER_BYTE)) & BYTE_MASK;
@@ -415,6 +501,7 @@ GetMaxSpeedGen (
   UINT8 ErrataSpeedDevMap4[MaxPcieControllerOfRootComplexA] = { LINK_SPEED_GEN1, LINK_SPEED_GEN1, LINK_SPEED_GEN1, LINK_SPEED_GEN1 };  // Bifurcation 3: x4 x4 x4 x4 (PCIE_ERRATA_SPEED1)
   UINT8 ErrataSpeedRcb[MaxPcieControllerOfRootComplexA] = { LINK_SPEED_GEN1, LINK_SPEED_GEN1, LINK_SPEED_GEN1, LINK_SPEED_GEN1 };      // RootComplexTypeB PCIE_ERRATA_SPEED1
   UINT8 Idx;
+  UINT8 MaxController;
   UINT8 *MaxGen;
 
   ASSERT (MaxPcieControllerOfRootComplexA == 4);
@@ -452,7 +539,8 @@ GetMaxSpeedGen (
     }
   }
 
-  for (Idx = 0; Idx < MaxPcieControllerOfRootComplexA; Idx++) {
+  MaxController = GetMaxController (RootComplex);
+  for (Idx = 0; Idx < MaxController; Idx++) {
     RootComplex->Pcie[Idx].MaxGen = RootComplex->Pcie[Idx].Active ? MaxGen[Idx] : LINK_SPEED_NONE;
   }
 
@@ -509,6 +597,6 @@ ParseRootComplexNVParamData (
 
   GetPresetSetting (RootComplex);
   GetLaneAllocation (RootComplex);
-  GetDefaultDevMap (RootComplex);
+  GetDevMap (RootComplex);
   GetMaxSpeedGen (RootComplex);
 }