| /* $NoKeywords:$ */ |
| /** |
| * @file |
| * |
| * GNB function to create/locate PCIe configuration data area |
| * |
| * Contain code that create/locate and rebase configuration data area. |
| * |
| * @xrefitem bom "File Content Label" "Release Content" |
| * @e project: AGESA |
| * @e sub-project: GNB |
| * @e \$Revision: 39898 $ @e \$Date: 2010-10-15 17:08:45 -0400 (Fri, 15 Oct 2010) $ |
| * |
| */ |
| /* |
| ***************************************************************************** |
| * |
| * Copyright (c) 2011, Advanced Micro Devices, Inc. |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are met: |
| * * Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * * Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * * Neither the name of Advanced Micro Devices, Inc. nor the names of |
| * its contributors may be used to endorse or promote products derived |
| * from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
| * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY |
| * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| * |
| * *************************************************************************** |
| * |
| */ |
| |
| /*---------------------------------------------------------------------------------------- |
| * M O D U L E S U S E D |
| *---------------------------------------------------------------------------------------- |
| */ |
| #include "AGESA.h" |
| #include "Ids.h" |
| #include "amdlib.h" |
| #include "heapManager.h" |
| #include "OptionGnb.h" |
| #include "Gnb.h" |
| #include "GnbPcie.h" |
| #include "GnbPcieFamServices.h" |
| #include GNB_MODULE_DEFINITIONS (GnbCommonLib) |
| #include GNB_MODULE_DEFINITIONS (GnbPcieConfig) |
| #include "PcieConfigData.h" |
| #include "PcieMapTopology.h" |
| #include "PcieInputParser.h" |
| #include "Filecode.h" |
| #define FILECODE PROC_GNB_MODULES_GNBPCIECONFIG_PCIECONFIGDATA_FILECODE |
| /*---------------------------------------------------------------------------------------- |
| * D E F I N I T I O N S A N D M A C R O S |
| *---------------------------------------------------------------------------------------- |
| */ |
| |
| |
| #define REBASE_PTR( Ptr, OldBase, NewBase) *(UINTN *)Ptr = (*(UINTN *)Ptr + (UINTN) NewBase - (UINTN) OldBase); |
| |
| extern BUILD_OPT_CFG UserOptions; |
| extern GNB_BUILD_OPTIONS ROMDATA GnbBuildOptions; |
| |
| /*---------------------------------------------------------------------------------------- |
| * T Y P E D E F S A N D S T R U C T U R E S |
| *---------------------------------------------------------------------------------------- |
| */ |
| |
| |
| /*---------------------------------------------------------------------------------------- |
| * P R O T O T Y P E S O F L O C A L F U N C T I O N S |
| *---------------------------------------------------------------------------------------- |
| */ |
| |
| VOID |
| PcieConfigDebugDump ( |
| IN PCIe_PLATFORM_CONFIG *Pcie |
| ); |
| |
| |
| /*----------------------------------------------------------------------------------------*/ |
| /** |
| * Create internal PCIe configuration data |
| * |
| * |
| * |
| * @param[in] StdHeader Standard configuration header |
| * @retval AGESA_SUCCESS Configuration data successfully allocated. |
| * @retval AGESA_FATAL Configuration data allocation failed. |
| */ |
| |
| AGESA_STATUS |
| PcieConfigurationInit ( |
| IN AMD_CONFIG_PARAMS *StdHeader |
| ) |
| { |
| AMD_EARLY_PARAMS *EarlyParamsPtr; |
| PCIe_COMPLEX_DESCRIPTOR *ComplexList; |
| PCIe_PLATFORM_CONFIG *Pcie; |
| AGESA_STATUS AgesaStatus; |
| AGESA_STATUS Status; |
| PCIe_COMPLEX_DESCRIPTOR *ComplexDescriptor; |
| UINTN ComplexesDataLength; |
| UINTN ComplexIndex; |
| UINTN NumberOfComplexes; |
| VOID *Buffer; |
| UINTN Index; |
| UINT32 NumberOfSockets; |
| UINT32 SocketId; |
| |
| IDS_HDT_CONSOLE (GNB_TRACE, "PcieConfigurationInit Enter\n"); |
| EarlyParamsPtr = (AMD_EARLY_PARAMS *) StdHeader; |
| ComplexList = (PCIe_COMPLEX_DESCRIPTOR *)EarlyParamsPtr->GnbConfig.PcieComplexList; |
| AgesaStatus = AGESA_SUCCESS; |
| ComplexesDataLength = 0; |
| NumberOfSockets = GnbGetNumberOfSockets (StdHeader); |
| for (SocketId = 0; SocketId < NumberOfSockets; SocketId++) { |
| if (GnbIsDevicePresentInSocket (SocketId, StdHeader)) { |
| UINTN CurrentComplexesDataLength; |
| Status = PcieFmGetComplexDataLength (SocketId, &CurrentComplexesDataLength); |
| ASSERT (Status == AGESA_SUCCESS); |
| ComplexesDataLength += CurrentComplexesDataLength; |
| } |
| } |
| NumberOfComplexes = PcieInputParserGetNumberOfComplexes (ComplexList); |
| Pcie = GnbAllocateHeapBuffer (AMD_PCIE_COMPLEX_DATA_HANDLE, sizeof (PCIe_PLATFORM_CONFIG) + ComplexesDataLength, StdHeader); |
| if (Pcie == NULL) { |
| IDS_ERROR_TRAP; |
| return AGESA_FATAL; |
| } |
| LibAmdMemFill (Pcie, 0x00, sizeof (PCIe_PLATFORM_CONFIG) + ComplexesDataLength, StdHeader); |
| Pcie->StdHeader = StdHeader; |
| Pcie->This = (UINTN) (Pcie); |
| Buffer = (UINT8 *) (Pcie) + sizeof (PCIe_PLATFORM_CONFIG); |
| ComplexIndex = 0; |
| for (SocketId = 0; SocketId < NumberOfSockets; SocketId++) { |
| if (GnbIsDevicePresentInSocket (SocketId, StdHeader)) { |
| UINTN CurrentComplexesDataLength; |
| if (ComplexIndex > MAX_NUMBER_OF_COMPLEXES) { |
| IDS_ERROR_TRAP; |
| return AGESA_FATAL; |
| } |
| Pcie->ComplexList[ComplexIndex].SiliconList = (PCIe_SILICON_CONFIG *) Buffer; |
| PcieFmBuildComplexConfiguration (Buffer, StdHeader); |
| for (Index = 0; Index < NumberOfComplexes; Index++) { |
| ComplexDescriptor = PcieInputParserGetComplexDescriptor (ComplexList, Index); |
| if (ComplexDescriptor->SocketId == SocketId) { |
| Status = PcieMapTopologyOnComplex (ComplexDescriptor, &Pcie->ComplexList[Index], Pcie); |
| AGESA_STATUS_UPDATE (Status, AgesaStatus); |
| } |
| } |
| PcieFmGetComplexDataLength (SocketId, &CurrentComplexesDataLength); |
| Buffer = (VOID *) ((UINT8 *)Buffer + CurrentComplexesDataLength); |
| ComplexIndex++; |
| } |
| } |
| Pcie->ComplexList[ComplexIndex - 1].Flags |= DESCRIPTOR_TERMINATE_LIST; |
| Pcie->LinkReceiverDetectionPooling = GnbBuildOptions.LinkReceiverDetectionPooling; |
| Pcie->LinkL0Pooling = GnbBuildOptions.LinkL0Pooling; |
| Pcie->LinkGpioResetAssertionTime = GnbBuildOptions.LinkGpioResetAssertionTime; |
| Pcie->LinkResetToTrainingTime = GnbBuildOptions.LinkResetToTrainingTime; |
| Pcie->GfxCardWorkaround = GfxWorkaroundEnable; |
| Pcie->TrainingExitState = LinkStateTrainingCompleted; |
| Pcie->TrainingAlgorithm = GnbBuildOptions.TrainingAlgorithm; |
| if ((UserOptions.CfgAmdPlatformType & AMD_PLATFORM_MOBILE) != 0) { |
| Pcie->GfxCardWorkaround = GfxWorkaroundDisable; |
| } |
| Pcie->PsppPolicy = EarlyParamsPtr->GnbConfig.PsppPolicy; |
| IDS_OPTION_CALLOUT (IDS_CALLOUT_GNB_PCIE_PLATFORM_CONFIG, Pcie, StdHeader); |
| GNB_DEBUG_CODE ( |
| PcieConfigDebugDump (Pcie); |
| ); |
| IDS_HDT_CONSOLE (GNB_TRACE, "PcieConfigurationInit Exit [0x%x]\n", AgesaStatus); |
| return AgesaStatus; |
| } |
| |
| |
| /*----------------------------------------------------------------------------------------*/ |
| /** |
| * Locate global PCIe configuration data |
| * |
| * |
| * |
| * @param[in] StdHeader Standard configuration header |
| * @param[out] Pcie Pointer to global PCIe configuration |
| * @retval AGESA_SUCCESS Configuration data successfully located |
| * @retval AGESA_FATAL Configuration can not be located. |
| */ |
| AGESA_STATUS |
| PcieLocateConfigurationData ( |
| IN AMD_CONFIG_PARAMS *StdHeader, |
| OUT PCIe_PLATFORM_CONFIG **Pcie |
| ) |
| { |
| PCIe_COMPLEX_CONFIG *Complex; |
| *Pcie = GnbLocateHeapBuffer (AMD_PCIE_COMPLEX_DATA_HANDLE, StdHeader); |
| if (*Pcie == NULL) { |
| IDS_ERROR_TRAP; |
| return AGESA_FATAL; |
| } |
| if ((UINTN) (*Pcie) != (UINTN) (*Pcie)->This) { |
| Complex = &(*Pcie)->ComplexList[0]; |
| while (Complex != NULL) { |
| PCIe_SILICON_CONFIG *SiliconList; |
| REBASE_PTR (&Complex->SiliconList, (UINTN) (*Pcie)->This, (UINTN)*Pcie); |
| SiliconList = PcieComplexGetSiliconList (Complex); |
| PcieRebaseConfigurationData (SiliconList, (UINTN) (*Pcie)->This, (UINTN)*Pcie); |
| Complex = PcieLibGetNextDescriptor (Complex); |
| } |
| (*Pcie)->This = (UINTN)(*Pcie); |
| } |
| (*Pcie)->StdHeader = StdHeader; |
| return AGESA_SUCCESS; |
| } |
| |
| /*----------------------------------------------------------------------------------------*/ |
| /** |
| * Rebase all pointers in Complex Configuration Data |
| * |
| * |
| * |
| * @param[in] SiliconList Pointer to first silicon descriptor of the complex |
| * @param[in] OldBase Old base address of the configuration data |
| * @param[in] NewBase New base address of the configuration data |
| */ |
| VOID |
| PcieRebaseConfigurationData ( |
| IN PCIe_SILICON_CONFIG *SiliconList, |
| IN UINTN OldBase, |
| IN UINTN NewBase |
| ) |
| { |
| while (SiliconList != NULL) { |
| PCIe_WRAPPER_CONFIG *WrapperList; |
| REBASE_PTR (&SiliconList->WrapperList, OldBase, NewBase); |
| REBASE_PTR (&SiliconList->FmSilicon, OldBase, NewBase); |
| WrapperList = PcieSiliconGetWrapperList (SiliconList); |
| while (WrapperList != NULL) { |
| PCIe_ENGINE_CONFIG *EngineList; |
| REBASE_PTR (&WrapperList->EngineList, OldBase, NewBase); |
| REBASE_PTR (&WrapperList->FmWrapper, OldBase, NewBase); |
| REBASE_PTR (&WrapperList->Silicon, OldBase, NewBase); |
| EngineList = PcieWrapperGetEngineList (WrapperList); |
| while (EngineList != NULL) { |
| REBASE_PTR (&EngineList->Wrapper, OldBase, NewBase); |
| EngineList = PcieLibGetNextDescriptor (EngineList); |
| } |
| WrapperList = PcieLibGetNextDescriptor (WrapperList); |
| } |
| SiliconList = PcieLibGetNextDescriptor (SiliconList); |
| } |
| } |
| |
| /*----------------------------------------------------------------------------------------*/ |
| /** |
| * Helper function to dump configuration to debug out |
| * |
| * |
| * @param[in] Pcie Pointer to global PCIe configuration |
| */ |
| VOID |
| PcieConfigDebugDump ( |
| IN PCIe_PLATFORM_CONFIG *Pcie |
| ) |
| { |
| PCIe_ENGINE_CONFIG *EngineList; |
| PCIe_SILICON_CONFIG *SiliconList; |
| PCIe_WRAPPER_CONFIG *WrapperList; |
| PCIe_COMPLEX_CONFIG *ComplexList; |
| ComplexList = &Pcie->ComplexList[0]; |
| IDS_HDT_CONSOLE (PCIE_MISC, "<-------------- PCIe Config Start----------------->\n"); |
| IDS_HDT_CONSOLE (PCIE_MISC, " PSPP Policy - %s\n", |
| (Pcie->PsppPolicy == PsppPowerSaving) ? "Power Saving" : |
| (Pcie->PsppPolicy == PsppBalanceHigh) ? "Balance-High" : ( |
| (Pcie->PsppPolicy == PsppBalanceLow) ? "Balance-Low" : ( |
| (Pcie->PsppPolicy == PsppPerformance) ? "Performance" : ( |
| (Pcie->PsppPolicy == PsppDisabled) ? "Disabled" : "Unknown"))) |
| ); |
| IDS_HDT_CONSOLE (PCIE_MISC, " GFX Workaround - %s\n", |
| (Pcie->GfxCardWorkaround == 0) ? "Disabled" : "Enabled" |
| ); |
| IDS_HDT_CONSOLE (PCIE_MISC, " LinkL0Pooling - %dus\n", |
| Pcie->LinkL0Pooling |
| ); |
| IDS_HDT_CONSOLE (PCIE_MISC, " LinkGpioResetAssertionTime - %dus\n", |
| Pcie->LinkGpioResetAssertionTime |
| ); |
| IDS_HDT_CONSOLE (PCIE_MISC, " LinkReceiverDetectionPooling - %dus\n", |
| Pcie->LinkReceiverDetectionPooling |
| ); |
| SiliconList = PcieComplexGetSiliconList (ComplexList); |
| while (SiliconList != NULL) { |
| WrapperList = PcieSiliconGetWrapperList (SiliconList); |
| while (WrapperList != NULL) { |
| IDS_HDT_CONSOLE (PCIE_MISC, " <---------Wrapper - %s Config -------->\n", |
| PcieFmDebugGetWrapperNameString (WrapperList) |
| ); |
| IDS_HDT_CONSOLE (PCIE_MISC, " PowerOffUnusedLanes - %x\n PowerOffUnusedPlls - %x\n ClkGating - %x\n" |
| " LclkGating - %x\n TxclkGatingPllPowerDown - %x\n PllOffInL1 - %x\n", |
| WrapperList->Features.PowerOffUnusedLanes, |
| WrapperList->Features.PowerOffUnusedPlls, |
| WrapperList->Features.ClkGating, |
| WrapperList->Features.LclkGating, |
| WrapperList->Features.TxclkGatingPllPowerDown, |
| WrapperList->Features.PllOffInL1 |
| ); |
| IDS_HDT_CONSOLE (PCIE_MISC, " <---------Wrapper - %s Config End----->\n", |
| PcieFmDebugGetWrapperNameString (WrapperList) |
| ); |
| EngineList = PcieWrapperGetEngineList (WrapperList); |
| while (EngineList != NULL) { |
| if (PcieLibIsEngineAllocated (EngineList)) { |
| IDS_HDT_CONSOLE (PCIE_MISC, " Engine Type - %s\n Start Phy Lane - %d\n End Phy Lane - %d\n", |
| ((EngineList->EngineData.EngineType == PciePortEngine) ? "PCIe Port" : "DDI Link"), |
| EngineList->EngineData.StartLane, |
| EngineList->EngineData.EndLane |
| ); |
| if (PcieLibIsPcieEngine (EngineList)) { |
| IDS_HDT_CONSOLE (PCIE_MISC, " PCIe port configuration:\n"); |
| IDS_HDT_CONSOLE (PCIE_MISC, " Port Training - %s\n", |
| (EngineList->Type.Port.PortData.PortPresent == PortDisabled) ? "Disable" : "Enabled" |
| ); |
| IDS_HDT_CONSOLE (PCIE_MISC, " Start Core Lane - %d\n", EngineList->Type.Port.StartCoreLane); |
| IDS_HDT_CONSOLE (PCIE_MISC, " End Core Lane - %d\n", EngineList->Type.Port.EndCoreLane); |
| IDS_HDT_CONSOLE (PCIE_MISC, " PCI Address - %d:%d:%d\n", |
| EngineList->Type.Port.Address.Address.Bus, |
| EngineList->Type.Port.Address.Address.Device, |
| EngineList->Type.Port.Address.Address.Function |
| ); |
| IDS_HDT_CONSOLE (PCIE_MISC, " Native PCI Dev Number - %d\n", EngineList->Type.Port.NativeDevNumber); |
| IDS_HDT_CONSOLE (PCIE_MISC, " Native PCI Func Number - %d\n", EngineList->Type.Port.NativeFunNumber); |
| IDS_HDT_CONSOLE (PCIE_MISC, " Hotplug - %s\n", |
| (EngineList->Type.Port.PortData.LinkHotplug == 0) ? "Disabled" : ( |
| (EngineList->Type.Port.PortData.LinkHotplug == 1) ? "Basic" : ( |
| (EngineList->Type.Port.PortData.LinkHotplug == 2) ? "Server" : ( |
| (EngineList->Type.Port.PortData.LinkHotplug == 2) ? "Enhanced" : "Unknown"))) |
| ); |
| IDS_HDT_CONSOLE (PCIE_MISC, " ASPM - %s\n", |
| (EngineList->Type.Port.PortData.LinkAspm == 0) ? "Disabled" : ( |
| (EngineList->Type.Port.PortData.LinkAspm == 1) ? "L0s" : ( |
| (EngineList->Type.Port.PortData.LinkAspm == 2) ? "L1" : ( |
| (EngineList->Type.Port.PortData.LinkAspm == 3) ? "L0s & L1" : "Unknown"))) |
| ); |
| IDS_HDT_CONSOLE (PCIE_MISC, " Speed - %d\n", |
| EngineList->Type.Port.PortData.LinkSpeedCapability |
| ); |
| } else { |
| IDS_HDT_CONSOLE (PCIE_MISC, " DDI configuration:\n"); |
| IDS_HDT_CONSOLE (PCIE_MISC, " Connector - %s\n", |
| (EngineList->Type.Ddi.DdiData.ConnectorType == ConnectorTypeDP) ? "DP" : ( |
| (EngineList->Type.Ddi.DdiData.ConnectorType == ConnectorTypeEDP) ? "eDP" : ( |
| (EngineList->Type.Ddi.DdiData.ConnectorType == ConnectorTypeSingleLinkDVI) ? "Single Link DVI" : ( |
| (EngineList->Type.Ddi.DdiData.ConnectorType == ConnectorTypeDualLinkDVI) ? "Dual Link DVI" : ( |
| (EngineList->Type.Ddi.DdiData.ConnectorType == ConnectorTypeHDMI) ? "HDMI" : ( |
| (EngineList->Type.Ddi.DdiData.ConnectorType == ConnectorTypeTravisDpToVga) ? "Travis DP-to-VGA" : ( |
| (EngineList->Type.Ddi.DdiData.ConnectorType == ConnectorTypeTravisDpToLvds) ? "Travis DP-to-LVDS" : ( |
| (EngineList->Type.Ddi.DdiData.ConnectorType == ConnectorTypeLvds) ? "LVDS" : ( |
| (EngineList->Type.Ddi.DdiData.ConnectorType == ConnectorTypeNutmegDpToVga) ? "Hudson-2 Nutmeg DP-to-VGA" : "Unknown")))))))) |
| ); |
| IDS_HDT_CONSOLE (PCIE_MISC, " Aux - Aux%d\n", EngineList->Type.Ddi.DdiData.AuxIndex + 1); |
| IDS_HDT_CONSOLE (PCIE_MISC, " Hdp - Hdp%d\n", EngineList->Type.Ddi.DdiData.HdpIndex + 1); |
| } |
| } |
| EngineList = PcieLibGetNextDescriptor (EngineList); |
| } |
| WrapperList = PcieLibGetNextDescriptor (WrapperList); |
| } |
| SiliconList = PcieLibGetNextDescriptor (SiliconList); |
| } |
| IDS_HDT_CONSOLE (PCIE_MISC, "<-------------- PCIe Config End------------------>\n"); |
| } |