blob: e9b8056688379aabe0952e567c32c959a98e3ca1 [file] [log] [blame]
/* $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);
}