diff options
Diffstat (limited to 'src/vendorcode/amd/agesa/f16kb/Proc/GNB/Modules/GnbPcieTrainingV2/PcieTrainingV2.c')
-rw-r--r-- | src/vendorcode/amd/agesa/f16kb/Proc/GNB/Modules/GnbPcieTrainingV2/PcieTrainingV2.c | 801 |
1 files changed, 801 insertions, 0 deletions
diff --git a/src/vendorcode/amd/agesa/f16kb/Proc/GNB/Modules/GnbPcieTrainingV2/PcieTrainingV2.c b/src/vendorcode/amd/agesa/f16kb/Proc/GNB/Modules/GnbPcieTrainingV2/PcieTrainingV2.c new file mode 100644 index 0000000000..36044ac885 --- /dev/null +++ b/src/vendorcode/amd/agesa/f16kb/Proc/GNB/Modules/GnbPcieTrainingV2/PcieTrainingV2.c @@ -0,0 +1,801 @@ +/* $NoKeywords:$ */ +/** + * @file + * + * PCIe link training + * + * + * + * @xrefitem bom "File Content Label" "Release Content" + * @e project: AGESA + * @e sub-project: GNB + * @e \$Revision: 85361 $ @e \$Date: 2013-01-07 11:15:28 -0600 (Mon, 07 Jan 2013) $ + * + */ +/* +***************************************************************************** +* + * Copyright (c) 2008 - 2013, 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 "GeneralServices.h" +#include "Gnb.h" +#include "GnbPcie.h" +#include "GnbCommonLib.h" +#include "GnbPcieConfig.h" +#include "GnbPcieInitLibV1.h" +#include "GnbPcieInitLibV5.h" +#include "GnbPcieTrainingV2.h" +#include "GnbRegistersCommonV2.h" +#include "Filecode.h" +#define FILECODE PROC_GNB_MODULES_GNBPCIETRAININGV2_PCIETRAININGV2_FILECODE +/*---------------------------------------------------------------------------------------- + * D E F I N I T I O N S A N D M A C R O S + *---------------------------------------------------------------------------------------- + */ + + +/*---------------------------------------------------------------------------------------- + * 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 + *---------------------------------------------------------------------------------------- + */ + +/*----------------------------------------------------------------------------------------*/ +/** + * Set link State + * + * + * @param[in] CurrentEngine Pointer to engine config descriptor + * @param[in] State State to set + * @param[in] UpdateTimeStamp Update time stamp + * @param[in] Pcie Pointer to global PCIe configuration + * + */ +VOID +PcieTrainingSetPortState ( + IN PCIe_ENGINE_CONFIG *CurrentEngine, + IN PCIE_LINK_TRAINING_STATE State, + IN BOOLEAN UpdateTimeStamp, + IN PCIe_PLATFORM_CONFIG *Pcie + ) +{ + UINT32 TimeStamp; + CurrentEngine->Type.Port.State = (UINT8) State; + if (UpdateTimeStamp) { + TimeStamp = PcieTimerGetTimeStamp (Pcie); + CurrentEngine->Type.Port.TimeStamp = TimeStamp; + } +} + + +/*----------------------------------------------------------------------------------------*/ +/** + * Set state for all engines connected to same reset ID + * + * + * + * @param[in] Engine Pointer to engine config descriptor + * @param[in, out] Buffer Pointer to Reset Id + * @param[in] Pcie Pointer to global PCIe configuration + * + */ +STATIC VOID +PcieSetResetStateOnEngines ( + IN PCIe_ENGINE_CONFIG *Engine, + IN OUT VOID *Buffer, + IN PCIe_PLATFORM_CONFIG *Pcie + ) +{ + UINT8 ResetId; + ResetId = *(UINT8 *)Buffer; + if (Engine->Type.Port.PortData.ResetId == ResetId && !PcieConfigIsSbPcieEngine (Engine)) { + PcieTrainingSetPortState (Engine, LinkStateResetDuration, TRUE, Pcie); + GnbLibPciRMW ( + Engine->Type.Port.Address.AddressValue | DxFxx68_ADDRESS, + AccessWidth32, + (UINT32) ~DxFxx68_LinkDis_MASK, + 1 << DxFxx68_LinkDis_OFFSET, + GnbLibGetHeader (Pcie) + ); + } +} + + +/*----------------------------------------------------------------------------------------*/ +/** + * Assert GPIO port reset. + * + * Transition to LinkStateResetDuration state + * + * @param[in] CurrentEngine Pointer to engine config descriptor + * @param[in] Pcie Pointer to global PCIe configuration + * + */ +VOID +STATIC +PcieTrainingAssertReset ( + IN PCIe_ENGINE_CONFIG *CurrentEngine, + IN PCIe_PLATFORM_CONFIG *Pcie + ) +{ + PCIe_SLOT_RESET_INFO ResetInfo; + ResetInfo.ResetControl = AssertSlotReset; + ResetInfo.ResetId = CurrentEngine->Type.Port.PortData.ResetId; + LibAmdMemCopy (&ResetInfo.StdHeader, GnbLibGetHeader (Pcie), sizeof (AMD_CONFIG_PARAMS), GnbLibGetHeader (Pcie)); + PcieConfigRunProcForAllEngines ( + DESCRIPTOR_ALLOCATED | DESCRIPTOR_PCIE_ENGINE, + PcieSetResetStateOnEngines, + (VOID *)&CurrentEngine->Type.Port.PortData.ResetId, + Pcie + ); + AgesaPcieSlotResetControl (0, &ResetInfo); +} + + +/*----------------------------------------------------------------------------------------*/ +/** + * Check for reset duration + * + * Transition to LinkStateResetDuration state + * + * @param[in] CurrentEngine Pointer to engine config descriptor + * @param[in] Pcie Pointer to global PCIe configuration + * + */ +STATIC VOID +PcieTrainingCheckResetDuration ( + IN PCIe_ENGINE_CONFIG *CurrentEngine, + IN PCIe_PLATFORM_CONFIG *Pcie + ) +{ + UINT32 TimeStamp; + TimeStamp = PcieTimerGetTimeStamp (Pcie); + if (TIMESTAMPS_DELTA (TimeStamp, CurrentEngine->Type.Port.TimeStamp) >= Pcie->LinkGpioResetAssertionTime) { + PcieTrainingSetPortState (CurrentEngine, LinkStateResetExit, FALSE, Pcie); + } +} + +/*----------------------------------------------------------------------------------------*/ +/** + * Deassert GPIO port reset. + * + * Transition to LinkStateResetDuration state + * + * @param[in] CurrentEngine Pointer to engine config descriptor + * @param[in] Pcie Platform configuration + * + */ +STATIC VOID +PcieTrainingDeassertReset ( + IN PCIe_ENGINE_CONFIG *CurrentEngine, + IN PCIe_PLATFORM_CONFIG *Pcie + ) +{ + PCIe_SLOT_RESET_INFO ResetInfo; + ResetInfo.ResetControl = DeassertSlotReset; + ResetInfo.ResetId = CurrentEngine->Type.Port.PortData.ResetId; + LibAmdMemCopy (&ResetInfo.StdHeader, GnbLibGetHeader (Pcie), sizeof (AMD_CONFIG_PARAMS), GnbLibGetHeader (Pcie)); + AgesaPcieSlotResetControl (0, &ResetInfo); + GnbLibPciRMW ( + CurrentEngine->Type.Port.Address.AddressValue | DxFxx68_ADDRESS, + AccessWidth32, + (UINT32) ~DxFxx68_LinkDis_MASK, + 0 << DxFxx68_LinkDis_OFFSET, + GnbLibGetHeader (Pcie) + ); + PcieTrainingSetPortState (CurrentEngine, LinkTrainingResetTimeout, TRUE, Pcie); +} + +/*----------------------------------------------------------------------------------------*/ +/** + * Check for after reset deassertion timeout + * + * + * @param[in] CurrentEngine Pointer to engine config descriptor + * @param[in] Pcie Pointer to global PCIe configuration + * + */ +VOID +STATIC +PcieTrainingCheckResetTimeout ( + IN PCIe_ENGINE_CONFIG *CurrentEngine, + IN PCIe_PLATFORM_CONFIG *Pcie + ) +{ + UINT32 TimeStamp; + TimeStamp = PcieTimerGetTimeStamp (Pcie); + if (TIMESTAMPS_DELTA (TimeStamp, CurrentEngine->Type.Port.TimeStamp) >= Pcie->LinkResetToTrainingTime) { + PcieTrainingSetPortState (CurrentEngine, LinkStateReleaseTraining, FALSE, Pcie); + } +} + + +/*----------------------------------------------------------------------------------------*/ +/** + * Release training + * + * + * @param[in] CurrentEngine Pointer to engine config descriptor + * @param[in] Pcie Pointer to global PCIe configuration + * + */ +VOID +STATIC +PcieTrainingRelease ( + IN PCIe_ENGINE_CONFIG *CurrentEngine, + IN PCIe_PLATFORM_CONFIG *Pcie + ) +{ + UINT8 LinkTrainingState; + PcieRegisterWriteField ( + PcieConfigGetParentWrapper (CurrentEngine), + WRAP_SPACE (PcieConfigGetParentWrapper (CurrentEngine)->WrapId, D0F0xE4_WRAP_0800_ADDRESS + 0x100 * CurrentEngine->Type.Port.PortId), + D0F0xE4_WRAP_0800_HoldTraining_OFFSET, + D0F0xE4_WRAP_0800_HoldTraining_WIDTH, + 0, + FALSE, + Pcie + ); + if (CurrentEngine->Type.Port.PortData.MiscControls.LinkComplianceMode == 0x1) { + LinkTrainingState = LinkStateCompliance; + } else { + LinkTrainingState = LinkStateDetectPresence; + } + PcieTrainingSetPortState (CurrentEngine, LinkTrainingState, TRUE, Pcie); +} + +/*----------------------------------------------------------------------------------------*/ +/** + * Detect presence of any EP on the link + * + * + * @param[in] CurrentEngine Pointer to engine config descriptor + * @param[in] Pcie Pointer to global PCIe configuration + * + */ + +VOID +STATIC +PcieTrainingDetectPresence ( + IN PCIe_ENGINE_CONFIG *CurrentEngine, + IN PCIe_PLATFORM_CONFIG *Pcie + ) +{ + UINT8 LinkHwStateHistory[4]; + UINT32 TimeStamp; + PcieUtilGetLinkHwStateHistory (CurrentEngine, &LinkHwStateHistory[0], 4, Pcie); + if (LinkHwStateHistory[0] > 4) { + PcieTrainingSetPortState (CurrentEngine, LinkStateDetecting, TRUE, Pcie); + return; + } + TimeStamp = PcieTimerGetTimeStamp (Pcie); + if (TIMESTAMPS_DELTA (TimeStamp, CurrentEngine->Type.Port.TimeStamp) >= Pcie->LinkReceiverDetectionPooling) { + PcieTrainingSetPortState (CurrentEngine, LinkStateDeviceNotPresent, FALSE, Pcie); + } +} + +UINT8 FailPattern1 [] = {0x2a, 0x6}; +UINT8 FailPattern2 [] = {0x2a, 0x9}; +UINT8 FailPattern3 [] = {0x2a, 0xb}; + +/*----------------------------------------------------------------------------------------*/ +/** + * Detect Link State + * + * + * @param[in] CurrentEngine Pointer to engine config descriptor + * @param[in] Pcie Pointer to global PCIe configuration + * + */ + +VOID +STATIC +PcieTrainingDetectLinkState ( + IN PCIe_ENGINE_CONFIG *CurrentEngine, + IN PCIe_PLATFORM_CONFIG *Pcie + ) +{ + UINT8 LinkHwStateHistory[16]; + UINT32 TimeStamp; + UINT8 LinkTrainingState; + PcieUtilGetLinkHwStateHistory (CurrentEngine, &LinkHwStateHistory[0], 4, Pcie); + if (LinkHwStateHistory[0] == 0x10) { + PcieTrainingSetPortState (CurrentEngine, LinkStateL0, FALSE, Pcie); + return; + }; + TimeStamp = PcieTimerGetTimeStamp (Pcie); + if (TIMESTAMPS_DELTA (TimeStamp, CurrentEngine->Type.Port.TimeStamp) >= Pcie->LinkL0Pooling) { + LinkTrainingState = LinkStateTrainingFail; + PcieUtilGetLinkHwStateHistory (CurrentEngine, &LinkHwStateHistory[0], 16, Pcie); + if (LinkHwStateHistory[0] == 0x7) { + LinkTrainingState = LinkStateCompliance; + } else if (PcieUtilSearchArray (LinkHwStateHistory, sizeof (LinkHwStateHistory), FailPattern1, sizeof (FailPattern1))) { + LinkTrainingState = LinkStateBrokenLane; + } else if (PcieUtilSearchArray (LinkHwStateHistory, sizeof (LinkHwStateHistory), FailPattern2, sizeof (FailPattern2))) { + LinkTrainingState = LinkStateGen2Fail; + } else if (PcieUtilSearchArray (LinkHwStateHistory, sizeof (LinkHwStateHistory), FailPattern3, sizeof (FailPattern3))) { + LinkTrainingState = LinkStateGen2Fail; + } + PcieTrainingSetPortState (CurrentEngine, LinkTrainingState, FALSE, Pcie); + } +} + +/*----------------------------------------------------------------------------------------*/ +/** + * Broken Lane + * + * + * @param[in] CurrentEngine Pointer to engine config descriptor + * @param[in] Pcie Pointer to global PCIe configuration + * + */ + +STATIC VOID +PcieTrainingBrokenLineV2 ( + IN PCIe_ENGINE_CONFIG *CurrentEngine, + IN PCIe_PLATFORM_CONFIG *Pcie + ) +{ + UINT8 CurrentLinkWidth; + UINT8 LinkTrainingState; + CurrentLinkWidth = PcieUtilGetLinkWidth (CurrentEngine, Pcie); + if (CurrentLinkWidth < PcieConfigGetNumberOfPhyLane (CurrentEngine) && CurrentLinkWidth > 0) { + CurrentEngine->InitStatus |= INIT_STATUS_PCIE_PORT_BROKEN_LANE_RECOVERY; + PcieTopologyReduceLinkWidthV5 (CurrentLinkWidth, CurrentEngine, Pcie); + LinkTrainingState = LinkStateResetAssert; + PutEventLog ( + AGESA_WARNING, + GNB_EVENT_BROKEN_LANE_RECOVERY, + CurrentEngine->Type.Port.Address.AddressValue, + 0, + 0, + 0, + GnbLibGetHeader (Pcie) + ); + } else { + LinkTrainingState = LinkStateGen2Fail; + } + PcieTrainingSetPortState (CurrentEngine, LinkTrainingState, FALSE, Pcie); +} + +/*----------------------------------------------------------------------------------------*/ +/** + * Check if link fail because device does not support Gen2 + * + * + * @param[in] CurrentEngine Pointer to engine config descriptor + * @param[in] Pcie Pointer to global PCIe configuration + * + */ +STATIC VOID +PcieTrainingGen2Fail ( + IN PCIe_ENGINE_CONFIG *CurrentEngine, + IN PCIe_PLATFORM_CONFIG *Pcie + ) +{ + UINT8 LinkTrainingState; + if (CurrentEngine->Type.Port.PortData.MiscControls.LinkSafeMode != PcieGen1) { + PcieConfigUpdatePortStatus (CurrentEngine, INIT_STATUS_PCIE_PORT_GEN2_RECOVERY, 0); + CurrentEngine->Type.Port.PortData.MiscControls.LinkSafeMode = PcieGen1; + PcieLinkSafeMode (CurrentEngine, Pcie); + LinkTrainingState = LinkStateResetAssert; + PutEventLog ( + AGESA_WARNING, + GNB_EVENT_BROKEN_LANE_RECOVERY, + CurrentEngine->Type.Port.Address.AddressValue, + 0, + 0, + 0, + GnbLibGetHeader (Pcie) + ); + } else { + LinkTrainingState = LinkStateTrainingFail; + } + PcieTrainingSetPortState (CurrentEngine, LinkTrainingState, FALSE, Pcie); +} + +/*----------------------------------------------------------------------------------------*/ +/** + * Link in L0 + * + * + * @param[in] CurrentEngine Pointer to engine config descriptor + * @param[in] Pcie Pointer to global PCIe configuration + * + */ +VOID +STATIC +PcieCheckLinkL0 ( + IN PCIe_ENGINE_CONFIG *CurrentEngine, + IN PCIe_PLATFORM_CONFIG *Pcie + ) +{ + PcieTrainingSetPortState (CurrentEngine, LinkStateVcoNegotiation, TRUE, Pcie); +} +/*----------------------------------------------------------------------------------------*/ +/** + * Check if link fail because device does not support Gen X + * + * + * @param[in] CurrentEngine Pointer to engine config descriptor + * @param[in] Pcie Pointer to global PCIe configuration + * + */ +VOID +STATIC +PcieTrainingCheckVcoNegotiation ( + IN PCIe_ENGINE_CONFIG *CurrentEngine, + IN PCIe_PLATFORM_CONFIG *Pcie + ) +{ + UINT32 TimeStamp; + DxFxx128_STRUCT DxFxx128; + TimeStamp = PcieTimerGetTimeStamp (Pcie); + GnbLibPciRead (CurrentEngine->Type.Port.Address.AddressValue | DxFxx128_ADDRESS, AccessWidth32, &DxFxx128, GnbLibGetHeader (Pcie)); + if (DxFxx128.Field.VcNegotiationPending == 0) { + UINT16 NumberOfPhyLane; + NumberOfPhyLane = PcieConfigGetNumberOfPhyLane (CurrentEngine); + if (Pcie->GfxCardWorkaround == GfxWorkaroundEnable && NumberOfPhyLane >= 8) { + // Limit exposure of workaround to x8 and x16 port. + PcieTrainingSetPortState (CurrentEngine, LinkStateGfxWorkaround, TRUE, Pcie); + } else { + PcieTrainingSetPortState (CurrentEngine, LinkStateTrainingSuccess, FALSE, Pcie); + } + return; + } + if (TIMESTAMPS_DELTA (TimeStamp, CurrentEngine->Type.Port.TimeStamp) >= 1000 * 1000) { + PcieTrainingSetPortState (CurrentEngine, LinkStateRetrain, FALSE, Pcie); + } +} + +/*----------------------------------------------------------------------------------------*/ +/** + * Check if for GFX workaround condition + * + * + * @param[in] CurrentEngine Pointer to engine config descriptor + * @param[in] Pcie Pointer to global PCIe configuration + * + */ +VOID +STATIC +PcieTrainingGfxWorkaround ( + IN PCIe_ENGINE_CONFIG *CurrentEngine, + IN PCIe_PLATFORM_CONFIG *Pcie + ) +{ + UINT32 TimeStamp; + GFX_WORKAROUND_STATUS GfxWorkaroundStatus; + TimeStamp = PcieTimerGetTimeStamp (Pcie); + + GfxWorkaroundStatus = PcieGfxCardWorkaroundV2 (CurrentEngine->Type.Port.Address, GnbLibGetHeader (Pcie)); + switch (GfxWorkaroundStatus) { + case GFX_WORKAROUND_DEVICE_NOT_READY: + if (TIMESTAMPS_DELTA (TimeStamp, CurrentEngine->Type.Port.TimeStamp) >= (3 * 1000000)) { + PcieTrainingSetPortState (CurrentEngine, LinkStateTrainingFail, TRUE, Pcie); + } + break; + case GFX_WORKAROUND_SUCCESS: + PcieTrainingSetPortState (CurrentEngine, LinkStateTrainingSuccess, FALSE, Pcie); + break; + case GFX_WORKAROUND_RESET_DEVICE: + if (CurrentEngine->Type.Port.GfxWrkRetryCount < 5) { + CurrentEngine->Type.Port.GfxWrkRetryCount++; + PcieTrainingSetPortState (CurrentEngine, LinkStateResetAssert, TRUE, Pcie); + } else { + PcieTrainingSetPortState (CurrentEngine, LinkStateTrainingFail, TRUE, Pcie); + } + break; + default: + ASSERT (FALSE); + } +} + +/*----------------------------------------------------------------------------------------*/ +/** + * Retrain link + * + * + * @param[in] CurrentEngine Pointer to engine config descriptor + * @param[in] Pcie Pointer to global PCIe configuration + * + */ +VOID +STATIC +PcieTrainingRetrainLink ( + IN PCIe_ENGINE_CONFIG *CurrentEngine, + IN PCIe_PLATFORM_CONFIG *Pcie + ) +{ + GnbLibPciRMW ( + CurrentEngine->Type.Port.Address.AddressValue | DxFxx68_ADDRESS, + AccessWidth32, + (UINT32) ~DxFxx68_RetrainLink_MASK, + 1 << DxFxx68_RetrainLink_OFFSET, + GnbLibGetHeader (Pcie) + ); + PcieTrainingSetPortState (CurrentEngine, LinkStateDetecting, TRUE, Pcie); +} + +/*----------------------------------------------------------------------------------------*/ +/** + * Training fail on this port + * + * + * @param[in] CurrentEngine Pointer to engine config descriptor + * @param[in] Pcie Pointer to global PCIe configuration + * + */ +VOID +STATIC +PcieTrainingFail ( + IN PCIe_ENGINE_CONFIG *CurrentEngine, + IN PCIe_PLATFORM_CONFIG *Pcie + ) +{ + PcieConfigUpdatePortStatus (CurrentEngine, INIT_STATUS_PCIE_PORT_TRAINING_FAIL, 0); + PcieTrainingSetPortState (CurrentEngine, LinkStateDeviceNotPresent, FALSE, Pcie); +} + +/*----------------------------------------------------------------------------------------*/ +/** + * Links training success + * + * + * @param[in] CurrentEngine Pointer to engine config descriptor + * @param[in] Pcie Pointer to global PCIe configuration + * + */ + +VOID +STATIC +PcieTrainingSuccess ( + IN PCIe_ENGINE_CONFIG *CurrentEngine, + IN PCIe_PLATFORM_CONFIG *Pcie + ) +{ + PcieConfigUpdatePortStatus (CurrentEngine, INIT_STATUS_PCIE_TRAINING_SUCCESS, 0); + PcieTrainingSetPortState (CurrentEngine, LinkStateTrainingCompleted, FALSE, Pcie); + GnbLibPciRMW ( + CurrentEngine->Type.Port.Address.AddressValue | DxFxx68_ADDRESS, + AccessWidth32, + (UINT32) ~DxFxx68_LinkBWManagementStatus_MASK, + 1 << DxFxx68_LinkBWManagementStatus_OFFSET, + GnbLibGetHeader (Pcie) + ); +} + +/*----------------------------------------------------------------------------------------*/ +/** + * Links in compliance + * + * + * @param[in] CurrentEngine Pointer to engine config descriptor + * @param[in] Pcie Pointer to global PCIe configuration + * + */ +VOID +STATIC +PcieTrainingCompliance ( + IN PCIe_ENGINE_CONFIG *CurrentEngine, + IN PCIe_PLATFORM_CONFIG *Pcie + ) +{ + PcieConfigUpdatePortStatus (CurrentEngine, INIT_STATUS_PCIE_PORT_IN_COMPLIANCE, 0); + PcieTrainingSetPortState (CurrentEngine, LinkStateTrainingCompleted, FALSE, Pcie); +} + +/*----------------------------------------------------------------------------------------*/ +/** + * PCie EP not present + * + * + * @param[in] CurrentEngine Pointer to engine config descriptor + * @param[in] Pcie Pointer to global PCIe configuration + * + */ +VOID +STATIC +PcieTrainingNotPresent ( + IN PCIe_ENGINE_CONFIG *CurrentEngine, + IN PCIe_PLATFORM_CONFIG *Pcie + ) +{ + if ((CurrentEngine->Type.Port.PortData.LinkHotplug == HotplugEnhanced) || (CurrentEngine->Type.Port.PortData.LinkHotplug == HotplugServer)) { + } else { + PcieRegisterWriteField ( + PcieConfigGetParentWrapper (CurrentEngine), + WRAP_SPACE (PcieConfigGetParentWrapper (CurrentEngine)->WrapId, D0F0xE4_WRAP_0800_ADDRESS + 0x100 * CurrentEngine->Type.Port.PortId), + D0F0xE4_WRAP_0800_HoldTraining_OFFSET, + D0F0xE4_WRAP_0800_HoldTraining_WIDTH, + 1, + FALSE, + Pcie + ); + } + PcieTrainingSetPortState (CurrentEngine, LinkStateTrainingCompleted, FALSE, Pcie); +} + +/*----------------------------------------------------------------------------------------*/ +/** + * Final state. Port training completed. + * + * Initialization status recorded in PCIe_ENGINE_CONFIG.InitStatus + * + * @param[in] CurrentEngine Pointer to engine config descriptor + * @param[in] Pcie Pointer to global PCIe configuration + * + */ +VOID +STATIC +PcieTrainingCompleted ( + IN PCIe_ENGINE_CONFIG *CurrentEngine, + IN PCIe_PLATFORM_CONFIG *Pcie + ) +{ +} + +/*----------------------------------------------------------------------------------------*/ +/** + * Training state handling + * + * + * + * @param[in] Engine Pointer to engine config descriptor + * @param[in, out] Buffer Indicate if engine in non final state + * @param[in] Pcie Pointer to global PCIe configuration + * + */ + +VOID +STATIC +PcieTrainingPortCallback ( + IN PCIe_ENGINE_CONFIG *Engine, + IN OUT VOID *Buffer, + IN PCIe_PLATFORM_CONFIG *Pcie + ) +{ + BOOLEAN *TrainingComplete; + TrainingComplete = (BOOLEAN *) Buffer; + if (Engine->Type.Port.State < Pcie->TrainingExitState) { + *TrainingComplete = FALSE; + } else { + return; + } + switch (Engine->Type.Port.State) { + case LinkStateResetAssert: + PcieTrainingAssertReset (Engine, Pcie); + break; + case LinkStateResetDuration: + PcieTrainingCheckResetDuration (Engine, Pcie); + break; + case LinkStateResetExit: + PcieTrainingDeassertReset (Engine, Pcie); + break; + case LinkTrainingResetTimeout: + PcieTrainingCheckResetTimeout (Engine, Pcie); + break; + case LinkStateReleaseTraining: + PcieTrainingRelease (Engine, Pcie); + break; + case LinkStateDetectPresence: + PcieTrainingDetectPresence (Engine, Pcie); + break; + case LinkStateDetecting: + PcieTrainingDetectLinkState (Engine, Pcie); + break; + case LinkStateBrokenLane: + PcieTrainingBrokenLineV2 (Engine, Pcie); + break; + case LinkStateGen2Fail: + PcieTrainingGen2Fail (Engine, Pcie); + break; + case LinkStateL0: + PcieCheckLinkL0 (Engine, Pcie); + break; + case LinkStateVcoNegotiation: + PcieTrainingCheckVcoNegotiation (Engine, Pcie); + break; + case LinkStateRetrain: + PcieTrainingRetrainLink (Engine, Pcie); + break; + case LinkStateTrainingFail: + PcieTrainingFail (Engine, Pcie); + break; + case LinkStateGfxWorkaround: + PcieTrainingGfxWorkaround (Engine, Pcie); + break; + case LinkStateTrainingSuccess: + PcieTrainingSuccess (Engine, Pcie); + break; + case LinkStateCompliance: + PcieTrainingCompliance (Engine, Pcie); + break; + case LinkStateDeviceNotPresent: + PcieTrainingNotPresent (Engine, Pcie); + break; + case LinkStateTrainingCompleted: + PcieTrainingCompleted (Engine, Pcie); + break; + default: + break; + } + +} + + +/*----------------------------------------------------------------------------------------*/ +/** + * Main link training procedure + * + * Port end up in three possible state LinkStateTrainingNotPresent/LinkStateCompliance/ + * LinkStateTrainingSuccess + * + * @param[in] Pcie Pointer to global PCIe configuration + * @retval AGESA_STATUS + * + */ + +AGESA_STATUS +PcieTraining ( + IN PCIe_PLATFORM_CONFIG *Pcie + ) +{ + AGESA_STATUS Status; + BOOLEAN TrainingComplete; + + IDS_PERF_TIMESTAMP (TP_BEGINGNBPCIETRAINING, GnbLibGetHeader (Pcie)); + Status = AGESA_SUCCESS; + IDS_HDT_CONSOLE (GNB_TRACE, "PcieTraining Enter\n"); + do { + TrainingComplete = TRUE; + PcieConfigRunProcForAllEngines ( + DESCRIPTOR_ALLOCATED | DESCRIPTOR_PCIE_ENGINE, + PcieTrainingPortCallback, + &TrainingComplete, + Pcie + ); + } while (!TrainingComplete); + IDS_HDT_CONSOLE (GNB_TRACE, "PcieTraining Exit [%x]\n", Status); + IDS_PERF_TIMESTAMP (TP_ENDGNBPCIETRAINING, GnbLibGetHeader (Pcie)); + return Status; +} + |