From 7d94cf93eec15dfb8eef9cd044fe39319d4ee9bc Mon Sep 17 00:00:00 2001 From: zbao Date: Mon, 2 Jul 2012 14:19:14 +0800 Subject: AGESA F15tn: AMD family15 AGESA code for Trinity AMD AGESA code for trinity. Change-Id: I847a54b15e8ce03ad5dbc17b95ee6771a9da0592 Signed-off-by: Zheng Bao Signed-off-by: zbao Reviewed-on: http://review.coreboot.org/1155 Tested-by: build bot (Jenkins) Reviewed-by: Patrick Georgi --- .../amd/agesa/f15tn/Proc/Fch/Pcie/GppPortInit.c | 760 +++++++++++++++++++++ 1 file changed, 760 insertions(+) create mode 100644 src/vendorcode/amd/agesa/f15tn/Proc/Fch/Pcie/GppPortInit.c (limited to 'src/vendorcode/amd/agesa/f15tn/Proc/Fch/Pcie/GppPortInit.c') diff --git a/src/vendorcode/amd/agesa/f15tn/Proc/Fch/Pcie/GppPortInit.c b/src/vendorcode/amd/agesa/f15tn/Proc/Fch/Pcie/GppPortInit.c new file mode 100644 index 0000000000..e9b8056688 --- /dev/null +++ b/src/vendorcode/amd/agesa/f15tn/Proc/Fch/Pcie/GppPortInit.c @@ -0,0 +1,760 @@ +/* $NoKeywords:$ */ +/** + * @file + * + * Config and Train Fch Gpp Ports + * + * Init Gpp Controller features. + * + * @xrefitem bom "File Content Label" "Release Content" + * @e project: AGESA + * @e sub-project: FCH + * @e \$Revision: 63425 $ @e \$Date: 2011-12-22 11:24:10 -0600 (Thu, 22 Dec 2011) $ + * + */ +/* +***************************************************************************** +* +* Copyright 2008 - 2012 ADVANCED MICRO DEVICES, INC. All Rights Reserved. +* +* AMD is granting you permission to use this software (the Materials) +* pursuant to the terms and conditions of your Software License Agreement +* with AMD. This header does *NOT* give you permission to use the Materials +* or any rights under AMD's intellectual property. Your use of any portion +* of these Materials shall constitute your acceptance of those terms and +* conditions. If you do not agree to the terms and conditions of the Software +* License Agreement, please do not use any portion of these Materials. +* +* CONFIDENTIALITY: The Materials and all other information, identified as +* confidential and provided to you by AMD shall be kept confidential in +* accordance with the terms and conditions of the Software License Agreement. +* +* LIMITATION OF LIABILITY: THE MATERIALS AND ANY OTHER RELATED INFORMATION +* PROVIDED TO YOU BY AMD ARE PROVIDED "AS IS" WITHOUT ANY EXPRESS OR IMPLIED +* WARRANTY OF ANY KIND, INCLUDING BUT NOT LIMITED TO WARRANTIES OF +* MERCHANTABILITY, NONINFRINGEMENT, TITLE, FITNESS FOR ANY PARTICULAR PURPOSE, +* OR WARRANTIES ARISING FROM CONDUCT, COURSE OF DEALING, OR USAGE OF TRADE. +* IN NO EVENT SHALL AMD OR ITS LICENSORS BE LIABLE FOR ANY DAMAGES WHATSOEVER +* (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS +* INTERRUPTION, OR LOSS OF INFORMATION) ARISING OUT OF AMD'S NEGLIGENCE, +* GROSS NEGLIGENCE, THE USE OF OR INABILITY TO USE THE MATERIALS OR ANY OTHER +* RELATED INFORMATION PROVIDED TO YOU BY AMD, EVEN IF AMD HAS BEEN ADVISED OF +* THE POSSIBILITY OF SUCH DAMAGES. BECAUSE SOME JURISDICTIONS PROHIBIT THE +* EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES, +* THE ABOVE LIMITATION MAY NOT APPLY TO YOU. +* +* AMD does not assume any responsibility for any errors which may appear in +* the Materials or any other related information provided to you by AMD, or +* result from use of the Materials or any related information. +* +* You agree that you will not reverse engineer or decompile the Materials. +* +* NO SUPPORT OBLIGATION: AMD is not obligated to furnish, support, or make any +* further information, software, technical information, know-how, or show-how +* available to you. Additionally, AMD retains the right to modify the +* Materials at any time, without notice, and is not obligated to provide such +* modified Materials to you. +* +* U.S. GOVERNMENT RESTRICTED RIGHTS: The Materials are provided with +* "RESTRICTED RIGHTS." Use, duplication, or disclosure by the Government is +* subject to the restrictions as set forth in FAR 52.227-14 and +* DFAR252.227-7013, et seq., or its successor. Use of the Materials by the +* Government constitutes acknowledgement of AMD's proprietary rights in them. +* +* EXPORT ASSURANCE: You agree and certify that neither the Materials, nor any +* direct product thereof will be exported directly or indirectly, into any +* country prohibited by the United States Export Administration Act and the +* regulations thereunder, without the required authorization from the U.S. +* government nor will be used for any purpose prohibited by the same. +**************************************************************************** +*/ +#include "FchPlatform.h" +#include "Ids.h" +#include "Filecode.h" +#define FILECODE PROC_FCH_PCIE_GPPPORTINIT_FILECODE + +// +// Declaration of local functions +// +/** + * GppPortPollingLtssmS3 - Loop polling the LTSSM for each GPP port marked in PortMap (New Algorithm S3) + * + * + * @param[in] FchGpp Pointer to Fch GPP configuration structure + * @param[in] ActivePorts A bitmap of ports which should be polled + * @param[in] IsGen2 TRUE if the polling is in Gen2 mode + * @param[in] StdHeader Pointer to AMD_CONFIG_PARAMS + * + * @retval FailedPorts A bitmap of ports which failed to train + * + */ +STATIC UINT8 +GppPortPollingLtssmS3 ( + IN FCH_GPP *FchGpp, + IN UINT8 ActivePorts, + IN BOOLEAN IsGen2, + IN AMD_CONFIG_PARAMS *StdHeader + ) +{ + UINT8 PortId; + UINT8 FailedPorts; + FCH_GPP_PORT_CONFIG *PortCfg; + UINT32 AbIndex; + UINT32 GppData32; + UINT8 EmptyPorts; + UINT8 RetryCounter; + + FailedPorts = 0; + EmptyPorts = ActivePorts; + RetryCounter = 2; + + while (RetryCounter-- ) { + for (PortId = 0; PortId < MAX_GPP_PORTS; PortId++) { + if (ActivePorts & (1 << PortId)) { + PortCfg = &FchGpp->PortCfg[PortId]; + if ( PortCfg->PortDetected == TRUE ) { + AbIndex = FCH_RCINDXP_REGA5 | (UINT32) (PortId << 24); + GppData32 = ReadAlink (AbIndex, StdHeader) & 0x3F3F3F3F; + + if ((UINT8) (GppData32) > 0x04) { + EmptyPorts &= ~(1 << PortId); + } + + if ((UINT8) (GppData32) == 0x10) { + break; + } + } + } + } + FchStall (180, StdHeader); + } + FailedPorts |= ActivePorts; + return FailedPorts; +} + +/** + * PreInitGppLink - Enable GPP link training. + * + * + * + * @param[in] FchGpp Pointer to Fch GPP configuration structure + * @param[in] StdHeader Pointer to AMD_CONFIG_PARAMS + * + */ +STATIC VOID +PreInitGppLink ( + IN FCH_GPP *FchGpp, + IN AMD_CONFIG_PARAMS *StdHeader + ) +{ + GPP_LINKMODE CfgMode; + UINT8 PortId; + UINT32 GppPortCfg; + UINT16 Tmp16Value; + UINT8 GppS3Data; + UINT8 HotPlugPorts; + + UINT8 PortMask[5] = { + 0x01, + 0x00, + 0x03, + 0x07, + 0x0F + }; + + HotPlugPorts = 0; + // + // PCIE_GPP_ENABLE (abcfg:0xC0): + // + // GPP_LINK_CONFIG ([3:0]) PortA PortB PortC PortD Description + // ---------------------------------------------------------------------------------- + // 0000 0-3 x4 Config + // 0001 N/A + // 0010 0-1 2-3 0 2:2 Config + // 0011 0-1 2 3 2:1:1 Config + // 0100 0 1 2 3 1:1:1:1 Config + // + // For A12 and above: + // ABCFG:0xC0[12] - Port A hold training (default 1) + // ABCFG:0xC0[13] - Port B hold training (default 1) + // ABCFG:0xC0[14] - Port C hold training (default 1) + // ABCFG:0xC0[15] - Port D hold training (default 1) + // + // + // + // Set port enable bit fields based on current GPP link configuration mode + // + CfgMode = FchGpp->GppLinkConfig; + ASSERT (CfgMode == PortA4 || CfgMode == PortA2B2 || CfgMode == PortA2B1C1 || CfgMode == PortA1B1C1D1); + GppPortCfg = (UINT32) PortMask[CfgMode]; + + // + // Mask out non-applicable ports according to the target link configuration mode + // + for ( PortId = 0; PortId < MAX_GPP_PORTS; PortId++ ) { + FchGpp->PortCfg[PortId].PortPresent &= (UINT8 ) (GppPortCfg >> PortId) & BIT0; + if ( FchGpp->PortCfg[PortId].PortHotPlug == TRUE ) { + HotPlugPorts |= ( 1 << PortId); + } + } + + // + // Deassert GPP reset and pull EP out of reset - Clear GPP_RESET (abcfg:0xC0[8] = 0) + // + Tmp16Value = (UINT16) (~GppPortCfg << 12); + GppPortCfg = (UINT32) (Tmp16Value + (GppPortCfg << 4) + CfgMode); + WriteAlink (FCH_ABCFG_REGC0 | (UINT32) (ABCFG << 29), GppPortCfg, StdHeader); + + GppPortCfg = ReadAlink (0xC0 | (UINT32) (RCINDXC << 29), StdHeader); + WriteAlink (0xC0 | (UINT32) (RCINDXC << 29), GppPortCfg | 0x400, StdHeader); /// Set STRAP_F0_MSI_EN + + // + // A-Link L1 Entry Delay Shortening + // AXINDP_Reg 0xA0[7:4] = 0x3 + // KR Does not need this portion of code. + RwAlink (FCH_AX_INDXP_REGA0, 0xFFFFFF0F, 0x30, StdHeader); + RwAlink (FCH_AX_INDXP_REGB1, 0xFFFFFFFF, BIT19, StdHeader); + RwAlink (FCH_AX_INDXP_REGB1, 0xFFFFFFFF, BIT28, StdHeader); + + // + // GPP L1 Entry Delay Shortening + // RCINDP_Reg 0xA0[7:4] = 0x1 Enter L1 sooner after ACK'ing PM request. + // This is done to reduce number of NAK received with L1 enabled. + // + for ( PortId = 0; PortId < MAX_GPP_PORTS; PortId++ ) { + RwAlink (FCH_RCINDXP_REGA0 | PortId << 24, 0xFFFFFF0F, 0x10, StdHeader); + // Hard System Hang running MeatGrinder Test on multiple blocks + // GPP Error Reporting Configuration + RwAlink (FCH_RCINDXP_REG6A | PortId << 24, (UINT32)~(BIT1), 0, StdHeader); + } + + + if (ReadFchSleepType (StdHeader) == ACPI_SLPTYP_S3) { + + ReadMem ( ACPI_MMIO_BASE + CMOS_RAM_BASE + 0x0D, AccessWidth8, &GppS3Data); + for ( PortId = 0; PortId < MAX_GPP_PORTS; PortId++ ) { + if ( GppS3Data & (1 << (PortId + 4))) { + if ( GppS3Data & (1 << PortId)) { + FchGppForceGen1 (FchGpp, (1 << PortId), StdHeader); + } else { + FchGppForceGen2 (FchGpp, (1 << PortId), StdHeader); + } + } + } + } + // + // Obtain original Gen2 strap value (LC_GEN2_EN_STRAP) + // + FchGpp->GppGen2Strap = (UINT8) (ReadAlink (FCH_RCINDXP_REGA4 | 0 << 24, StdHeader) & BIT0); + FchGpp->HotPlugPortsStatus = HotPlugPorts; +} + + +/** + * CheckGppLinkStatus - loop polling the link status for each GPP port + * + * + * Return: ToggleStatus[3:0] = Port bitmap for those need to clear De-emphasis + * + * @param[in] FchGpp Pointer to Fch GPP configuration structure + * @param[in] StdHeader Pointer to AMD_CONFIG_PARAMS + * + */ +STATIC UINT8 +CheckGppLinkStatus ( + IN FCH_GPP *FchGpp, + IN AMD_CONFIG_PARAMS *StdHeader + ) +{ + UINT32 PortId; + UINT8 PortScanMap; + UINT8 GppHwDowngrade; + FCH_GPP_PORT_CONFIG *PortCfg; + UINT8 FailedPorts; + + PortScanMap = 0; + FailedPorts = 0; + + // + // Obtain a list of ports to be checked + // + for ( PortId = 0; PortId < MAX_GPP_PORTS; PortId++ ) { + PortCfg = &FchGpp->PortCfg[PortId]; + if ( PortCfg->PortPresent == TRUE && PortCfg->PortDetected == FALSE ) { + PortScanMap |= 1 << PortId; + } + } + + GppHwDowngrade = (UINT8) FchGpp->GppHardwareDownGrade; + if (GppHwDowngrade != 0) { + // + // Skip polling and always assume this port to be present + // + PortScanMap &= ~(1 << (GppHwDowngrade - 1)); + } + + FchStall (5000, StdHeader); + if (FchGpp->GppGen2 && FchGpp->GppGen2Strap) { + AGESA_TESTPOINT (TpFchGppGen2PortPolling, StdHeader); + FchGppForceGen2 (FchGpp, PortScanMap, StdHeader); + FailedPorts = GppPortPollingLtssm (FchGpp, PortScanMap, TRUE, StdHeader); + + if (FailedPorts) { + AGESA_TESTPOINT (TpFchGppGen1PortPolling, StdHeader); + FchGppForceGen1 (FchGpp, FailedPorts, StdHeader); + FailedPorts = GppPortPollingLtssm (FchGpp, FailedPorts, FALSE, StdHeader); + } + } else { + AGESA_TESTPOINT (TpFchGppGen1PortPolling, StdHeader); + FchGppForceGen1 (FchGpp, PortScanMap, StdHeader); + FailedPorts = GppPortPollingLtssm (FchGpp, PortScanMap, FALSE, StdHeader); + } + return FailedPorts; +} + +STATIC +BOOLEAN +FoundInfiniteCrs ( + IN FCH_GPP *FchGpp, + IN AMD_CONFIG_PARAMS *StdHeader + ) +{ + UINT32 PortId; + UINT32 Value32; + UINT32 RegBusNo; + UINT32 FchTempBus; + FCH_GPP_PORT_CONFIG *PortCfg; + + FchTempBus = GppGetFchTempBus (StdHeader); + for ( PortId = 0; PortId < MAX_GPP_PORTS; PortId++ ) { + PortCfg = &FchGpp->PortCfg[PortId]; + if ( PortCfg->PortDetected == TRUE ) { + RegBusNo = (FchTempBus << 16) + (FchTempBus << 8); + WritePci (PCI_ADDRESS (0, GPP_DEV_NUM, PortId, 0x18), AccessWidth32, &RegBusNo, StdHeader); + ReadPci (PCI_ADDRESS (FchTempBus, 0, 0, 0x08), AccessWidth32, &Value32, StdHeader); + RegBusNo = 0; + WritePci (PCI_ADDRESS (0, GPP_DEV_NUM, PortId, 0x18), AccessWidth32, &RegBusNo, StdHeader); + + if ( Value32 == 0xFFFFFFFF ) { + return TRUE; + } + } + } + return FALSE; +} + + +/** + * AfterGppLinkInit + * - Search for display device behind each GPP port + * - If the port is empty AND not hotplug-capable: + * * Turn off link training + * * (optional) Power down the port + * * Hide the configuration space (Turn off the port) + * + * @param[in] FchGpp Pointer to Fch GPP configuration structure + * @param[in] StdHeader Pointer to AMD_CONFIG_PARAMS + * + */ +STATIC VOID +AfterGppLinkInit ( + IN FCH_GPP *FchGpp, + IN AMD_CONFIG_PARAMS *StdHeader + ) +{ + UINT32 PortId; + FCH_GPP_PORT_CONFIG *PortCfg; + UINT32 RegBusNumber; + UINT32 FchTempBus; + UINT32 AbValue; + UINT32 AbIndex; + UINT8 Value; + + FchGpp->GppFoundGfxDev = 0; + AbValue = ReadAlink (FCH_ABCFG_REGC0 | (UINT32) (ABCFG << 29), StdHeader); + // + // Link Bandwidth Notification Capability Enable + //RCINDC:0xC1[0] = 1 + // + RwAlink (FCH_RCINDXC_REGC1, 0xFFFFFFFF, BIT0, StdHeader); + + for ( PortId = 0; PortId < MAX_GPP_PORTS; PortId++ ) { + // + // Program requester ID for every port + // + AbIndex = FCH_RCINDXP_REG21 | (UINT32) (PortId << 24); + WriteAlink (AbIndex, (FCH_GPP_DEV << 3) + PortId, StdHeader); + // + // Link Bandwidth Notification Capability Enable + //PCIe Cfg 0x68[10] = 0 + //PCIe Cfg 0x68[11] = 0 + // + RwPci (PCI_ADDRESS (0, GPP_DEV_NUM, PortId, 0x68), AccessWidth16, (UINT32)~(BIT10 + BIT11), 0, StdHeader); + + PortCfg = &FchGpp->PortCfg[PortId]; + // + // Check if there is GFX device behind each GPP port + // + FchTempBus = GppGetFchTempBus (StdHeader); + if ( PortCfg->PortDetected == TRUE ) { + RegBusNumber = (FchTempBus << 16) + (FchTempBus << 8); + WritePci (PCI_ADDRESS (0, GPP_DEV_NUM, PortId, 0x18), AccessWidth32, &RegBusNumber, StdHeader); + ReadPci (PCI_ADDRESS (FchTempBus, 0, 0, 0x0B), AccessWidth8, &Value, StdHeader); + if ( Value == 3 ) { + FchGpp->GppFoundGfxDev |= (1 << PortId); + } + + RegBusNumber = 0; + WritePci (PCI_ADDRESS (0, GPP_DEV_NUM, PortId, 0x18), AccessWidth32, &RegBusNumber, StdHeader); + } else if ( PortCfg->PortPresent == FALSE || PortCfg->PortHotPlug == FALSE ) { + // + // Mask off non-applicable ports + // + AbValue &= ~(1 << (PortId + 4)); + } + + if ( PortCfg->PortHotPlug == TRUE ) { + // + // Hot Plug: PCIe Native Support + // RCINDP_Reg 0x10[3] = 0x1 + // PCIe_Cfg 0x5A[8] = 0x1 + // PCIe_Cfg 0x6C[6] = 0x1 + // RCINDP_Reg 0x20[19] = 0x0 + // + RwAlink ((FCH_RCINDXP_REG10 | (UINT32) (PortId << 24)), 0xFFFFFFFF, BIT3, StdHeader); + RwPci (PCI_ADDRESS (0, GPP_DEV_NUM, PortId, 0x5b), AccessWidth8, 0xff, BIT0, StdHeader); + RwPci (PCI_ADDRESS (0, GPP_DEV_NUM, PortId, 0x6c), AccessWidth8, 0xff, BIT6, StdHeader); + RwAlink ((FCH_RCINDXP_REG20 | (UINT32) (PortId << 24)), (UINT32)~BIT19, 0, StdHeader); + } + } + + if ( FchGpp->GppUnhidePorts == FALSE ) { + if ((AbValue & 0xF0) == 0) { + //comment out the following line for BUG284426: GPP_RESET causes S3 resume hard hang on Pumori + //AbValue = BIT8; // if all ports are empty set GPP_RESET + } else if ((AbValue & 0xE0) != 0 && (AbValue & 0x10) == 0) { + AbValue |= BIT4; // PortA should always be visible whenever other ports are exist + } + + // + // Update GPP_Portx_Enable (abcfg:0xC0[7:5]) + // + WriteAlink (FCH_ABCFG_REGC0 | (UINT32) (ABCFG << 29), AbValue, StdHeader); + } + + // + // Common initialization for open GPP ports + // + for ( PortId = 0; PortId < MAX_GPP_PORTS; PortId++ ) { + ReadPci (PCI_ADDRESS (0, GPP_DEV_NUM, PortId, 0x80), AccessWidth8, &Value, StdHeader); + if (Value != 0xff) { + // + // Set pciCfg:PCIE_DEVICE_CNTL2[3:0] = 4'h6 (0x80[3:0]) + // + Value &= 0xf0; + Value |= 0x06; + WritePci (PCI_ADDRESS (0, GPP_DEV_NUM, PortId, 0x80), AccessWidth8, &Value, StdHeader); + + // + // Set PCIEIND_P:PCIE_RX_CNTL[RX_RCB_CPL_TIMEOUT_MODE] (0x70:[19]) = 1 + // + AbIndex = FCH_RCINDXP_REG70 | (UINT32) (PortId << 24); + AbValue = ReadAlink (AbIndex, StdHeader) | BIT19; + WriteAlink (AbIndex, AbValue, StdHeader); + + // + // Set PCIEIND_P:PCIE_TX_CNTL[TX_FLUSH_TLP_DIS] (0x20:[19]) = 0 + // + AbIndex = FCH_RCINDXP_REG20 | (UINT32) (PortId << 24); + AbValue = ReadAlink (AbIndex, StdHeader) & ~BIT19; + WriteAlink (AbIndex, AbValue, StdHeader); + + // + // Set Immediate Ack PM_Active_State_Request_L1 (0xA0:[23]) = 1 + // + AbIndex = FCH_RCINDXP_REGA0 | (UINT32) (PortId << 24); + AbValue = ReadAlink (AbIndex, StdHeader) & ~BIT23; + if ( FchGpp->GppL1ImmediateAck == 0) { + AbValue |= BIT23; + } + WriteAlink (AbIndex, AbValue, StdHeader); + } + } +} + + +/** + * FchGppAerInitialization - Initializing AER + * + * + * @param[in] FchGpp Pointer to Fch GPP configuration structure + * @param[in] StdHeader Pointer to AMD_CONFIG_PARAMS + * + */ +STATIC VOID +FchGppAerInitialization ( + IN FCH_GPP *FchGpp, + IN AMD_CONFIG_PARAMS *StdHeader + ) +{ + if (FchGpp->PcieAer) { + // + // GPP strap configuration + // + RwAlink (0x310 | (UINT32) (ABCFG << 29), (UINT32)~(BIT7 + BIT4), BIT28 + BIT27 + BIT26 + BIT1, StdHeader); + RwAlink (0x314 | (UINT32) (ABCFG << 29), ~(UINT32) (0xfff << 15), 0, StdHeader); + + // + // AB strap configuration + // + RwAlink (FCH_ABCFG_REGF0 | (UINT32) (ABCFG << 29), 0xFFFFFFFF, BIT15 + BIT14, StdHeader); + RwAlink (FCH_ABCFG_REGF4 | (UINT32) (ABCFG << 29), 0xFFFFFFFF, BIT3, StdHeader); + } else { + // + // Hard System Hang running MeatGrinder Test on multiple blocks + // GPP Error Reporting Configuration + RwAlink (FCH_ABCFG_REGF0 | (UINT32) (ABCFG << 29), (UINT32)~(BIT1), 0, StdHeader); + } + +} + +/** + * FchGppRasInitialization - Initializing RAS + * + * + * @param[in] FchGpp Pointer to Fch GPP configuration structure + * @param[in] StdHeader Pointer to AMD_CONFIG_PARAMS + * + */ +STATIC VOID +FchGppRasInitialization ( + IN FCH_GPP *FchGpp, + IN AMD_CONFIG_PARAMS *StdHeader + ) +{ + if (FchGpp->PcieRas) { + RwAlink (FCH_ABCFG_REGF4 | (UINT32) (ABCFG << 29), 0xFFFFFFFF, BIT0, StdHeader); + } +} + + +/** + * FchGppPortInit - GPP port training and initialization + * + * + * @param[in] FchGpp Pointer to Fch GPP configuration structure + * @param[in] StdHeader Pointer to AMD_CONFIG_PARAMS + * + */ +VOID +FchGppPortInit ( + IN FCH_GPP *FchGpp, + IN AMD_CONFIG_PARAMS *StdHeader + ) +{ + // + // GppEarlyInit + // + UINT32 AbValue; + UINT8 ResetCounter; + UINT8 FailPorts; + + AGESA_TESTPOINT (TpFchGppBeforePortTraining, StdHeader); + + // + // Configure NB-FCH link PCIE PHY PLL power down for L1 + // + if ( FchGpp->UmiPhyPllPowerDown == TRUE ) { + // + // Set PCIE_P_CNTL in Alink PCIEIND space + // + WriteAlink (FCH_AX_INDXC_REG30 | (UINT32) (AXINDC << 29), 0x40, StdHeader); + AbValue = ReadAlink (FCH_AX_DATAC_REG34 | (UINT32) (AXINDC << 29), StdHeader); + AbValue |= BIT12 + BIT3 + BIT0; + AbValue &= (UINT32)~(BIT9 + BIT4); + WriteAlink (FCH_AX_DATAC_REG34 | (UINT32) (AXINDC << 29), AbValue, StdHeader); + RwAlink (FCH_AX_INDXC_REG02 | (UINT32) (AXINDC << 29), (UINT32)~(BIT8), (BIT8), StdHeader); + RwAlink (FCH_AX_INDXC_REG02 | (UINT32) (AXINDC << 29), (UINT32)~(BIT3), (BIT3), StdHeader); + } + + // + // AXINDC_Reg 0xA4[18] = 0x1 + // + WriteAlink (FCH_AX_INDXP_REG38 | (UINT32) (AXINDP << 29), 0xA4, StdHeader); + AbValue = ReadAlink (FCH_AX_DATAP_REG3C | (UINT32) (AXINDP << 29), StdHeader); + AbValue |= BIT18; + WriteAlink (FCH_AX_DATAP_REG3C | (UINT32) (AXINDP << 29), AbValue, StdHeader); + + // + // Set ABCFG 0x031C[0] = 1 to enable lane reversal + // + AbValue = ReadAlink (FCH_ABCFG_REG31C | (UINT32) (ABCFG << 29), StdHeader); + if ( FchGpp->GppLaneReversal == TRUE ) { + WriteAlink (FCH_ABCFG_REG31C | (UINT32) (ABCFG << 29), AbValue | BIT0, StdHeader); + } else { + WriteAlink (FCH_ABCFG_REG31C | (UINT32) (ABCFG << 29), AbValue | 0x00, StdHeader); + } + + // + // Set abcfg:0x90[20] = 1 to enable GPP bridge multi-function + // + AbValue = ReadAlink (FCH_ABCFG_REG90 | (UINT32) (ABCFG << 29), StdHeader); + WriteAlink (FCH_ABCFG_REG90 | (UINT32) (ABCFG << 29), AbValue | BIT20, StdHeader); + + // + // Initialize and configure GPP + // + if (FchGpp->GppFunctionEnable) { + if (( FchGpp->NewGppAlgorithm == FALSE ) || ( (ReadFchSleepType (StdHeader) != ACPI_SLPTYP_S3) )) { + ProgramGppTogglePcieReset (FchGpp->GppToggleReset, StdHeader); + } + FchGppAerInitialization (FchGpp, StdHeader); + FchGppRasInitialization (FchGpp, StdHeader); + + // + // PreInit - Enable GPP link training + // + if (( FchGpp->NewGppAlgorithm == FALSE ) || ( (ReadFchSleepType (StdHeader) != ACPI_SLPTYP_S3) )) { + PreInitGppLink (FchGpp, StdHeader); + } + // + // GPP Upstream Memory Write Arbitration Enhancement ABCFG 0x54[26] = 1 + // GPP Memory Write Max Payload Improvement RCINDC_Reg 0x10[12:10] = 0x4 + // + if ( FchGpp->GppMemWrImprove == TRUE ) { + RwAlink (FCH_ABCFG_REG54 | (UINT32) (ABCFG << 29), (UINT32)~BIT26, (BIT26), StdHeader); + RwAlink (FCH_RCINDXC_REG10, (UINT32)~(BIT12 + BIT11 + BIT10), (BIT12), StdHeader); + } + + if ( FchGpp->NewGppAlgorithm == TRUE ) { + if (ReadFchSleepType (StdHeader) == ACPI_SLPTYP_S3) { + if ( FchGpp->HotPlugPortsStatus == 0 ) { + // S3 Procedure + FchStall (5000, StdHeader); + FailPorts = FchGpp->FailPortsStatus; + if ( FchGpp->FailPortsStatus != 0 ) { + AGESA_TESTPOINT (TpFchGppGen1PortPolling, StdHeader); + FchGppForceGen1 (FchGpp, FailPorts, StdHeader); + } + } + } + } else { + ResetCounter = 3; + while (ResetCounter--) { + FailPorts = CheckGppLinkStatus (FchGpp, StdHeader); + if (FoundInfiniteCrs (FchGpp, StdHeader)) { + ProgramGppTogglePcieReset (TRUE, StdHeader); + } else if ((FailPorts != 0) && (ReadFchSleepType (StdHeader) != ACPI_SLPTYP_S3)) { + ProgramGppTogglePcieReset (FchGpp->GppToggleReset, StdHeader); + } else { + break; + } + } + } + + // + // Misc operations after link training + // + if ( FchGpp->NewGppAlgorithm == FALSE ) { + AfterGppLinkInit (FchGpp, StdHeader); + } + } + if ( FchGpp->NewGppAlgorithm == FALSE ) { + FchGppDynamicPowerSaving (FchGpp, StdHeader); + AGESA_TESTPOINT (TpFchGppAfterPortTraining, StdHeader); + } +} + +/** + * FchGppPortInitS3Phase - GPP port training and initialization S3 phase for new algorithm + * + * + * @param[in] FchGpp Pointer to Fch GPP configuration structure + * @param[in] StdHeader Pointer to AMD_CONFIG_PARAMS + * + */ +VOID +FchGppPortInitS3Phase ( + IN FCH_GPP *FchGpp, + IN AMD_CONFIG_PARAMS *StdHeader + ) +{ + UINT8 ResetCounter; + UINT8 FailPorts; + + if (FchGpp->GppFunctionEnable) { + ProgramGppTogglePcieReset (FchGpp->GppToggleReset, StdHeader); + PreInitGppLink (FchGpp, StdHeader); + // For S3 With HotPlug port setting. + if ( FchGpp->HotPlugPortsStatus != 0 ) { + ResetCounter = 3; + while (ResetCounter--) { + FailPorts = CheckGppLinkStatus (FchGpp, StdHeader); + if (FoundInfiniteCrs (FchGpp, StdHeader)) { + ProgramGppTogglePcieReset (TRUE, StdHeader); + } else if (FailPorts != 0) { + ProgramGppTogglePcieReset (FchGpp->GppToggleReset, StdHeader); + } else { + break; + } + } + AfterGppLinkInit (FchGpp, StdHeader); + } + } +} + +/** + * FchGppPortInitPhaseII - GPP port training and initialization phase II for new algorithm + * + * + * @param[in] FchGpp Pointer to Fch GPP configuration structure + * @param[in] StdHeader Pointer to AMD_CONFIG_PARAMS + * + */ +VOID +FchGppPortInitPhaseII ( + IN FCH_GPP *FchGpp, + IN AMD_CONFIG_PARAMS *StdHeader + ) +{ + UINT8 ResetCounter; + UINT8 FailPorts; + UINT8 HotPlugPorts; + + if (FchGpp->GppFunctionEnable) { + // + // Check Link status for the new algorithm + // + HotPlugPorts = 0; + FailPorts = 0; + // + // Read previously HotPlug port status + // + if ( ReadFchSleepType (StdHeader) == ACPI_SLPTYP_S3) { + if ( FchGpp->HotPlugPortsStatus == 0 ) { + FailPorts = FchGpp->FailPortsStatus; + FailPorts = GppPortPollingLtssmS3 (FchGpp, FailPorts, FALSE, StdHeader); + AfterGppLinkInit (FchGpp, StdHeader); + } + } else { + ResetCounter = 3; + while (ResetCounter--) { + FailPorts = CheckGppLinkStatus (FchGpp, StdHeader); + if (FoundInfiniteCrs (FchGpp, StdHeader)) { + ProgramGppTogglePcieReset (TRUE, StdHeader); + } else if ((FailPorts != 0) && (ReadFchSleepType (StdHeader) != ACPI_SLPTYP_S3)) { + // CMOS record need + FchGpp->FailPortsStatus = FailPorts; + ProgramGppTogglePcieReset (FchGpp->GppToggleReset, StdHeader); + } else { + // CMOS clear need + FchGpp->FailPortsStatus = FailPorts; + break; + } + } + AfterGppLinkInit (FchGpp, StdHeader); + } + } + FchGppDynamicPowerSaving (FchGpp, StdHeader); + AGESA_TESTPOINT (TpFchGppAfterPortTraining, StdHeader); +} -- cgit v1.2.3