blob: 2e91cb6c1a26c77e86d12316e4ad3b89864dc68d [file] [log] [blame]
/**
* @file
*
* PCIe silicon specific functions library.
*
*
*
* @xrefitem bom "File Content Label" "Release Content"
* @e project: CIMx-NB
* @e sub-project:
* @e \$Revision:$ @e \$Date:$
*
*/
/*****************************************************************************
*
* Copyright (C) 2012 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 "NbPlatform.h"
#include "amdDebugOutLib.h"
#include "amdSbLib.h"
/*----------------------------------------------------------------------------------------
* 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
*----------------------------------------------------------------------------------------
*/
UINT32
PcieLibGetCoreConfiguration (
IN CORE CoreId,
IN AMD_NB_CONFIG *pConfig
);
AGESA_STATUS
PcieLibValidateGfxConfig (
IN PORT PortId,
IN OUT AMD_NB_CONFIG *pConfig
);
/*----------------------------------------------------------------------------------------
* E X P O R T E D F U N C T I O N S
*----------------------------------------------------------------------------------------
*/
CORE_INFO CoreInfoTable[] = {
{ // GPP1_CORE_ID = 0 It is GFX Core (GPP1 Core)
GPP1_CORE, // Core Selector
(BIT2 | BIT3), // Port ID Mask. Defines what ports belongs
NB_MISC_REG08,
NB_MISC_REG28, // De-emphasis register
NB_MISC_REG26, // Strap control register
28, // Strap bit offset
NB_CLK_REGF0,
NB_MISC_REG35, 26, // TX drive strength and offset
NB_MISC_REG35, 18, // TX half swing
NB_MISC_REG36, 24, // TX zero deemphasis
0,
28,
23
},
{ // GPP2_CORE_ID = 1 It is GFX2 Core (GPP2 Core)
GPP2_CORE, // Core Selector
(BIT11 | BIT12), // Port ID Mask. Defines what ports belongs
NB_MISC_REG08,
NB_MISC_REG27, // De-emphasis register
NB_MISC_REG26, // Strap control register
29, // Strap bit offset
NB_CLK_REGF0,
NB_MISC_REG35, 28, // TX drive strength and offset
NB_MISC_REG35, 19, // TX half swing
NB_MISC_REG36, 26, // TX zero deemphasis
1,
29,
24
},
{ // GPP3a_CORE_ID = 2 It is GPP Core (GPP3a Core)
GPP3a_CORE, // Core Selector
(BIT4 | BIT5 | BIT6 | BIT7 | BIT9 | BIT10), // Port ID Mask. Defines what ports belongs
NB_MISC_REG08,
NB_MISC_REG28, // De-emphasis register
NB_MISC_REG26, // Strap control register
30, // Strap bit offset
NB_CLK_REGF4,
NB_MISC_REG35, 30, // TX drive strength and offset
NB_MISC_REG35, 20, // TX half swing
NB_MISC_REG36, 28, // TX zero deemphasis
2,
30,
25
},
{ // GPP3b_CORE_ID = 3 It is GPP2 Core (GPP3b Core)
GPP3b_CORE, // Core Selector
(BIT13), // Port ID Mask. Defines what ports belongs
NB_MISC_REG2A,
NB_MISC_REG2D, // De-emphasis register
NB_MISC_REG2D, // Strap control register
21, // Strap bit offset
NB_CLK_REGF4,
NB_MISC_REG2C, 4, // TX drive strength and offset
NB_MISC_REG2C, 2, // TX half swing
NB_MISC_REG2B, 10, // TX zero deemphasis
3,
31,
26
},
{ // SB_CORE_ID = 4 It is SB Core
SB_CORE, // Core Selector
(BIT8), // Port ID Mask. Defines what ports belongs
NB_MISC_REG08,
NB_MISC_REG6F, // De-emphasis register
0x0,
0x0,
0x0,
NB_MISC_REG68, 8, // TX drive strength and offset
NB_MISC_REG67, 27, // TX half swing
NB_MISC_REG68, 20, // TX zero deemphasis
0xff,
0xff,
0xff
}
};
PORT_INFO pGfxPortFullA = {
PcieLinkWidth_x16, 0, 0
};
PORT_INFO pGfxPortA = {
PcieLinkWidth_x8, 0, 96
};
PORT_INFO pGfxPortB = {
PcieLinkWidth_x8, 8, 96
};
PORT_INFO pGpp420000[] = {
{PcieLinkWidth_x4, 0, 56},
{PcieLinkWidth_x2, 4, 28}
};
PORT_INFO pGpp411000[] = {
{PcieLinkWidth_x4, 0, 56},
{PcieLinkWidth_x1, 4, 14},
{PcieLinkWidth_x1, 5, 14}
};
PORT_INFO pGpp222000[] = {
{PcieLinkWidth_x2, 0, 28},
{PcieLinkWidth_x2, 2, 28},
{PcieLinkWidth_x2, 4, 28}
};
PORT_INFO pGpp221100[] = {
{PcieLinkWidth_x2, 0, 28},
{PcieLinkWidth_x2, 2, 28},
{PcieLinkWidth_x1, 4, 14},
{PcieLinkWidth_x1, 5, 14}
};
PORT_INFO pGpp211110[] = {
{PcieLinkWidth_x2, 0, 28},
{PcieLinkWidth_x1, 2, 14},
{PcieLinkWidth_x1, 3, 14},
{PcieLinkWidth_x1, 4, 14},
{PcieLinkWidth_x4, 0, 0 }, //Dummy entry
{PcieLinkWidth_x1, 5, 14}
};
PORT_INFO pGpp111111[] = {
{PcieLinkWidth_x1, 0, 14},
{PcieLinkWidth_x1, 1, 14},
{PcieLinkWidth_x1, 2, 14},
{PcieLinkWidth_x1, 3, 14},
{PcieLinkWidth_x4, 0, 0 }, //Dummy entry
{PcieLinkWidth_x1, 4, 14},
{PcieLinkWidth_x1, 5, 14}
};
GPP_CFG_INFO GppCfgInfoTable[] = {
{pGpp420000, 0xff50fff4},
{pGpp411000, 0xf650fff4},
{pGpp222000, 0xff60f5f4},
{pGpp221100, 0xf760f5f4},
{pGpp211110, 0xf97065f4},
{pGpp111111, 0xfA907654}
};
CONST PORT_STATIC_INFO PortInfoTable[] = {
//Training Reversal Deemp Mapping Hotplug Offset
{4 , 3, 0 , 4 , 0 }, //2
{5 , 4, 1 , 8 , 8 }, //3
{21, 7, 2 , 12 , 0 }, //4
{22, 8, 3 , 16 , 8 }, //5
{23, 9, 4 , 20 , 16 }, //6
{24, 10, 5 , 24 , 0xFF }, //7
{20, 0, 1 , 0xFF , 0xFF }, //8
{25, 11, 6 , 28 , 0xFF }, //9
{26, 12, 7 , 0 , 0xFF }, //10
{6 , 5, 30, 4 , 16 }, //11
{7 , 6, 31, 8 , 24 }, //12
{4 , 25, 5 , 12 , 24 } //13
};
/*----------------------------------------------------------------------------------------*/
/**
* Port Training Control
*
*
*
* @param[in] PortId PCI Express Port ID
* @param[in] Operation Release or Hold training
* @param[in] pConfig Northbridge configuration structure pointer.
*/
VOID
PcieLibPortTrainingControl (
IN PORT PortId,
IN PCIE_LINK_TRAINING Operation,
IN AMD_NB_CONFIG *pConfig
)
{
CORE CoreId;
CORE_INFO *pCoreInfo;
PORT_STATIC_INFO *pStaticPortInfo;
CoreId = PcieLibGetCoreId (PortId, pConfig);
pStaticPortInfo = PcieLibGetStaticPortInfo (PcieLibNativePortId (PortId, pConfig), pConfig);
pCoreInfo = PcieLibGetCoreInfo (CoreId, pConfig);
LibNbPciIndexRMW (
pConfig->NbPciAddress.AddressValue | NB_MISC_INDEX,
pCoreInfo->TrainingRegister,
AccessWidth32,
~(1 << pStaticPortInfo->TrainingAddress),
(Operation == PcieLinkTrainingHold)?(1 << pStaticPortInfo->TrainingAddress):0,
pConfig
);
}
/*----------------------------------------------------------------------------------------*/
/**
* Get PCI address of Port.
* Function return pcie Address based on port mapping and core configuration.
*
*
* @param[in] PortId PCI Express Port ID
* @param[in] pConfig Northbridge configuration structure pointer.
*/
PCI_ADDR
PcieLibGetPortPciAddress (
IN PORT PortId,
IN AMD_NB_CONFIG *pConfig
)
{
PCI_ADDR Port;
UINT32 RemapEnable;
UINT32 RemapValue;
PORT_STATIC_INFO *pPortStaticInfo;
RemapEnable = 0;
RemapValue = 0;
pPortStaticInfo = PcieLibGetStaticPortInfo (PcieLibNativePortId (PortId, pConfig), pConfig);
Port.AddressValue = pConfig->NbPciAddress.AddressValue;
LibNbPciIndexRead (
pConfig->NbPciAddress.AddressValue | NB_MISC_INDEX,
NB_MISC_REG20,
AccessWidth32,
&RemapEnable,
pConfig
);
if (pPortStaticInfo->MappingAddress != 0xff && RemapEnable & BIT0) {
LibNbPciIndexRead (
pConfig->NbPciAddress.AddressValue | NB_MISC_INDEX,
(PortId > 9)? NB_MISC_REG21:NB_MISC_REG20,
AccessWidth32,
&RemapValue,
pConfig
);
RemapValue = (RemapValue >> pPortStaticInfo->MappingAddress) & 0xf;
}
if (RemapValue == 0) {
RemapValue = PortId;
}
Port.Address.Device = RemapValue;
return Port;
}
/*----------------------------------------------------------------------------------------*/
/**
* Get Core register selector.
* Function return selector to access BIFNB register space for selected core
*
*
* @param[in] CoreId PCI Express Core ID
* @param[in] pConfig Northbridge configuration structure pointer.
*
*/
UINT32
PcieLibGetCoreAddress (
IN CORE CoreId,
IN AMD_NB_CONFIG *pConfig
)
{
return PcieLibGetCoreInfo (CoreId, pConfig)->CoreSelector;
}
/*----------------------------------------------------------------------------------------*/
/**
* Get Core Id
* Function return PCIE core ID base on Port ID
*
*
* @param[in] PortId PCI Express Port ID
* @param[in] pConfig Northbridge configuration structure pointer.
* @retval Core ID.
*/
CORE
PcieLibGetCoreId (
IN PORT PortId,
IN AMD_NB_CONFIG *pConfig
)
{
CORE_INFO *pCoreInfoTable = (CORE_INFO*)FIX_PTR_ADDR (&CoreInfoTable[0], NULL);
CORE CoreId;
for (CoreId = 0; CoreId <= MAX_CORE_ID; CoreId++) {
if (pCoreInfoTable[CoreId].PortIdBitMap & (1 << PortId)) {
break;
}
}
return CoreId;
}
/*
INDIRECT_REG_ENTRY
STATIC
PcieMiscInitTable[] = {
{
NB_MISC_REG20,
(UINT32)~BIT1,
0x0
}, //enable static device remapping by default
{
NB_MISC_REG22,
0xffffffff,
BIT27
}, //[10]CMGOOD_OVERRIDE for all 5 pcie cores.
{
NB_MISC_REG6B,
0xffffffff,
(UINT32) (0x1f << 27)
}, //[13][12]Turn Off Offset Cancellation
{
NB_MISC_REG37,
(UINT32)~(BIT11 + BIT12 + BIT13),
0x0
}, //[14][13]Disables Rx Clock gating in CDR
{
NB_MISC_REG67,
(UINT32)~(BIT26 + BIT10 + BIT11),
BIT11
}, //[13]Disables Rx Clock gating in CDR
//[16]Sets Electrical Idle Threshold
{
NB_MISC_REG2C,
(UINT32)~(BIT10),
0x0
}, //[13]Disables Rx Clock gating in CDR
{
NB_MISC_REG2A,
(UINT32)~(BIT17 + BIT16),
BIT17
}, //[16]Sets Electrical l Idle Threshold
{
NB_MISC_REG32,
(UINT32)~(0x3F << 20),
(UINT32) (0x2A << 20)
} //[17][16]Sets Electrical Idle Threshold
};
*/
UINT8 GppConfigTable[] = {
0x0, 0x1, 0x2, 0xC, 0xA, 0x4, 0xB
};
/*----------------------------------------------------------------------------------------*/
/**
* Set Core Configuration.
*
*
*
* @param[in] CoreId PCI Express Core ID
* @param[in] pConfig Northbridge configuration structure pointer.
*/
VOID
PcieLibSetCoreConfiguration (
IN CORE CoreId,
IN AMD_NB_CONFIG *pConfig
)
{
UINT32 LaneReversalValue;
PORT PortId;
PCIE_CONFIG *pPcieConfig;
CORE_INFO *pCoreInfo;
CORE CoreAddress;
pPcieConfig = GET_PCIE_CONFIG_PTR (pConfig);
CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (pConfig), CIMX_NBPCIE_TRACE), "[NBPCIE]PcieLibSetCoreConfiguration CoreId = %d Configuration = 0x%x Enter\n", CoreId, pPcieConfig->CoreConfiguration[CoreId]));
pCoreInfo = PcieLibGetCoreInfo (CoreId, pConfig);
CoreAddress = PcieLibGetCoreAddress (CoreId, pConfig);
LaneReversalValue = 0;
PcieLibCoreReset (CoreId, PcieCoreResetAllAssert, pConfig);
PcieLibStrapModeControl (CoreId, PcieCoreStrapConfigStart, pConfig);
//Setup GFX/GFX2 core configuration
if (CoreAddress == GPP1_CORE || CoreAddress == GPP2_CORE) {
if (pPcieConfig->CoreConfiguration[CoreId] == GFX_CONFIG_AABB) {
LibNbPciIndexRMW (pConfig->NbPciAddress.AddressValue | NB_MISC_INDEX, NB_MISC_REG08, AccessWidth32, 0xffffffff, (CoreAddress == GPP1_CORE)?BIT8:BIT9, pConfig);
STALL (GET_BLOCK_CONFIG_PTR (pConfig), 2000, 0);
}
if (pPcieConfig->CoreSetting[CoreId].RefClockInput == ON) {
LibNbPciIndexRMW (pConfig->NbPciAddress.AddressValue | NB_MISC_INDEX, NB_MISC_REG6C, AccessWidth32, 0xffffffff, (CoreAddress == GPP1_CORE)?BIT9:BIT31, pConfig);
}
}
//Setup GPP core configuration
if (CoreAddress == GPP3a_CORE) {
UINT32 Mux;
UINT8 *pGppConfigTable;
Mux = 0;
pGppConfigTable = (UINT8*)FIX_PTR_ADDR (&GppConfigTable[0], NULL);
LibNbPciIndexRMW (
pConfig->NbPciAddress.AddressValue | NB_MISC_INDEX,
NB_MISC_REG67, AccessWidth32,
0xfffffff0,
(UINT32)pGppConfigTable[pPcieConfig->CoreConfiguration[CoreId]],
pConfig
);
switch (pPcieConfig->CoreConfiguration[CoreId]) {
case GPP_CONFIG_GPP420000:
Mux = (pPcieConfig->PortConfiguration[6].PortReversed == ON)?0xF05BA00:0x055B000;
break;
case GPP_CONFIG_GPP411000:
Mux = 0x215B400;
break;
case GPP_CONFIG_GPP222000:
case GPP_CONFIG_GPP211110:
Mux = (pPcieConfig->PortConfiguration[4].PortReversed == ON)?0xFFF0AAA:0xFF0BAA0;
break;
case GPP_CONFIG_GPP221100:
Mux = 0x215B400;
break;
case GPP_CONFIG_GPP111111:
Mux = 0x2AA3554;
break;
default:
CIMX_ASSERT (FALSE);
}
LibNbPciIndexRMW (pConfig->NbPciAddress.AddressValue | NB_MISC_INDEX, NB_MISC_REG26, AccessWidth32, 0xf0000000, Mux, pConfig);
}
PcieLibStrapModeControl (CoreId, PcieCoreStrapConfigStop, pConfig);
PcieLibCoreReset (CoreId, PcieCoreResetAllDeassert, pConfig);
//Setup lane reversal
for (PortId = MIN_PORT_ID; PortId <= MAX_PORT_ID; PortId++) {
if (PcieLibIsValidPortId (PortId, pConfig)) {
if (pPcieConfig->PortConfiguration[PortId].PortPresent == ON &&
pPcieConfig->PortConfiguration[PortId].PortReversed == ON &&
(pCoreInfo->PortIdBitMap & (1 << PortId)) != 0) {
PORT_STATIC_INFO *pStaticPortInfo = PcieLibGetStaticPortInfo (PcieLibNativePortId (PortId, pConfig), pConfig);
LaneReversalValue |= (1 << (pStaticPortInfo->ReversalAddress));
CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (pConfig), CIMX_NBPCIE_TRACE), " Port reversed Port Id %d Native Id %d, Reversal Address %d \n", PortId, PcieLibNativePortId (PortId, pConfig), pStaticPortInfo->ReversalAddress));
}
}
}
LibNbPciIndexRMW (
pConfig->NbPciAddress.AddressValue | NB_MISC_INDEX,
(CoreAddress == GPP3b_CORE) ? NB_MISC_REG2D : NB_MISC_REG27,
AccessWidth32, 0xffffffff,
LaneReversalValue,
pConfig
);
//Setup performance mode
if (pPcieConfig->CoreSetting[CoreId].PerformanceMode == ON) {
UINT32 RegisterAddress;
switch (CoreAddress) {
case GPP1_CORE:
RegisterAddress = NB_MISC_REG33;
break;
case GPP2_CORE:
RegisterAddress = NB_MISC_REG22;
break;
default:
RegisterAddress = 0;
break;
}
if (RegisterAddress != 0) {
LibNbPciIndexRMW (pConfig->NbPciAddress.AddressValue | NB_MISC_INDEX, RegisterAddress , AccessWidth32, 0xfffffC00, 0xB5, pConfig);
}
}
//Setup Tx Drive Strength
LibNbPciIndexRMW (
pConfig->NbPciAddress.AddressValue | NB_MISC_INDEX,
pCoreInfo->TxDriveStrengthRegister ,
AccessWidth32,
~(0x3 << pCoreInfo->TxDriveStrengthOffset),
pPcieConfig->CoreSetting[CoreId].TxDriveStrength << pCoreInfo->TxDriveStrengthOffset,
pConfig
);
//Setup Tx half swing
if (pPcieConfig->CoreSetting[CoreId].TxHalfSwingMode == ON) {
LibNbPciIndexRMW (
pConfig->NbPciAddress.AddressValue | NB_MISC_INDEX,
pCoreInfo->TxHalfSwingRegister,
AccessWidth32,
~(0x1 << pCoreInfo->TxHalfSwingOffset),
0x0,
pConfig
);
// Setup half swing deemphasis
LibNbPciIndexRMW (
pConfig->NbPciAddress.AddressValue | NB_MISC_INDEX,
pCoreInfo->TxHalfSwingDeepmhasisRegister ,
AccessWidth32,
~(0x3 << pCoreInfo->TxHalfSwingDeepmhasisOffset),
0x0,
pConfig
);
}
//Finalize straps for this core
PcieLibStrapModeControl (CoreId, PcieCoreStrapConfigStart, pConfig);
PcieLibStrapModeControl (CoreId, PcieCoreStrapConfigStop, pConfig);
CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (pConfig), CIMX_NBPCIE_TRACE), "[NBPCIE]PcieLibSetCoreConfiguration Exit\n"));
}
/*----------------------------------------------------------------------------------------*/
/**
* Get Core Configuration
* Function return GPPSB/GFX/GFX2 core configuration.
*
*
*
* @param[in] CoreId PCI Express Core ID
* @param[in] pConfig Northbridge configuration structure pointer.
*/
UINT32
PcieLibGetCoreConfiguration (
IN CORE CoreId,
IN AMD_NB_CONFIG *pConfig
)
{
UINT32 CoreConfiguration;
UINT32 Value;
CORE CoreAddress;
CoreConfiguration = 0,
CoreAddress = PcieLibGetCoreAddress (CoreId, pConfig);
// CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (pConfig), CIMX_NBPCIE_TRACE), "[NBPCIE]PcieLibGetCoreConfiguration (Core = 0x%x) Enter\n", CoreAddress));
if (CoreAddress == GPP1_CORE || CoreAddress == GPP2_CORE) {
LibNbPciIndexRead (pConfig->NbPciAddress.AddressValue | NB_MISC_INDEX, NB_MISC_REG08, AccessWidth32, &Value, pConfig);
CoreConfiguration = (Value & ((CoreAddress == GPP1_CORE) ? BIT8:BIT9))? GFX_CONFIG_AABB:GFX_CONFIG_AAAA;
} else {
if (CoreAddress == GPP3a_CORE) {
UINT8 *pGppConfigTable;
pGppConfigTable = (UINT8*)FIX_PTR_ADDR (&GppConfigTable[0], NULL);
LibNbPciIndexRead (pConfig->NbPciAddress.AddressValue | NB_MISC_INDEX, NB_MISC_REG67, AccessWidth32, &Value, pConfig);
while (pGppConfigTable[CoreConfiguration] != (Value & 0xf)) {
CoreConfiguration++;
}
}
}
// CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (pConfig), CIMX_NBPCIE_TRACE), "[NBPCIE]PcieLibGetCoreConfiguration (CoreConfiguration = 0x%x) Exit\n", CoreConfiguration));
return CoreConfiguration;
}
/*----------------------------------------------------------------------------------------*/
/**
* Return link misc information (max link width, current link width, lane 0 map)
*
*
*
*
* @param[in] PortId PCI Express Port ID
* @param[in] pConfig Northbridge configuration structure pointer.
*/
LINK_INFO
PcieLibGetPortLinkInfo (
IN PORT PortId,
IN AMD_NB_CONFIG *pConfig
)
{
UINT32 Value;
PCI_ADDR Port;
PORT_INFO *pPortInfo;
LINK_INFO LinkInfo = {0, 0, 0};
Port = PcieLibGetPortPciAddress (PortId, pConfig);
pPortInfo = PcieLibGetPortInfo (PortId, pConfig);
//Read current link width
LibNbPciIndexRead (Port.AddressValue | NB_BIF_INDEX, NB_BIFNBP_REGA2, AccessWidth32, &Value, pConfig);
Value = (Value >> 4) & 0xf;
LinkInfo.LinkWidth = (UINT8)Value;
LinkInfo.MaxLinkWidth = pPortInfo->MaxLinkWidth;
LinkInfo.Line0Offset = pPortInfo->Line0Offset;
// CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (pConfig), CIMX_NBPCIE_TRACE), " PortId %d LinkWidth 0x%x MaxLinkWidth 0x%x Line0Offset %d\n", PortId, LinkInfo.LinkWidth, LinkInfo.MaxLinkWidth,LinkInfo.Line0Offset));
return LinkInfo;
}
/*----------------------------------------------------------------------------------------*/
/**
* Check if port in lane reversed configuration.
*
*
*
* @param[in] PortId PCI Express Port ID
* @param[in] pConfig Northbridge configuration structure pointer.
*/
BOOLEAN
PcieLibIsPortReversed (
IN PORT PortId,
IN AMD_NB_CONFIG *pConfig
)
{
BOOLEAN Result;
UINT32 Value;
PCIE_CONFIG *pPcieConfig;
PCI_ADDR Port;
pPcieConfig = GET_PCIE_CONFIG_PTR (pConfig);
Port = PcieLibGetPortPciAddress (PortId, pConfig);
LibNbPciIndexRead (Port.AddressValue | NB_BIF_INDEX, NB_BIFNBP_REG50, AccessWidth32, &Value, pConfig);
if (pPcieConfig->PortConfiguration[PortId].PortReversed == ON || (Value & BIT0) != 0) {
Result = TRUE;
} else {
Result = FALSE;
}
return Result;
}
/*----------------------------------------------------------------------------------------*/
/**
* Check if core id valid for current silicon
*
*
*
* @param[in] CoreId PCI Express Core ID
* @param[in] pConfig Northbridge configuration structure pointer.
*/
BOOLEAN
PcieLibIsValidCoreId (
IN CORE CoreId,
IN AMD_NB_CONFIG *pConfig
)
{
UINT32 CoreAddress;
NB_INFO NbInfo;
CoreAddress = PcieLibGetCoreAddress (CoreId, pConfig);
NbInfo = LibNbGetRevisionInfo (pConfig);
if (CoreAddress == GPP3b_CORE) {
if (NbInfo.Type == NB_RD890 || NbInfo.Type == NB_SR5690) {
return TRUE;
} else {
return FALSE;
}
}
if (CoreAddress == GPP2_CORE && (NbInfo.Type == NB_RD780 || NbInfo.Type == NB_RX780 || NbInfo.Type == NB_SR5650 || NbInfo.Type == NB_990X || NbInfo.Type == NB_970)) {
return FALSE;
}
return TRUE;
}
/*----------------------------------------------------------------------------------------*/
/**
* Check if port Id valid for current core configuration
*
*
*
* @param[in] PortId PCI Express Port ID
* @param[in] pConfig Northbridge configuration structure pointer.
*/
BOOLEAN
PcieLibIsValidPortId (
IN PORT PortId,
IN AMD_NB_CONFIG *pConfig
)
{
CORE CoreId;
NB_INFO NbInfo;
CoreId = PcieLibGetCoreId (PortId, pConfig);
NbInfo = LibNbGetRevisionInfo (pConfig);
if (!PcieLibIsValidCoreId (CoreId, pConfig)) {
return FALSE;
}
if ((PortId == 3 || PortId == 12) && PcieLibGetCoreConfiguration (CoreId, pConfig) != GFX_CONFIG_AABB) {
return FALSE;
}
if (PortId == 3 && NbInfo.Type == NB_970) {
return FALSE;
}
if (PortId == 12 && NbInfo.Type == NB_SR5670) {
return FALSE;
}
if (PortId == 13 || PortId == 8) {
return TRUE;
} else {
return (PcieLibNativePortId (PortId, pConfig) == 0xf)?FALSE:TRUE;
}
}
/*----------------------------------------------------------------------------------------*/
/**
* Set Link mode. Gen1/Gen2/Gen2-Advertize
*
*
*
*
* @param[in] PortId PCI Express Port ID
* @param[in] Operation Link Mode
* @param[in] pConfig Northbridge configuration structure pointer.
*/
VOID
PcieLibSetLinkMode (
IN PORT PortId,
IN PCIE_LINK_MODE Operation,
IN AMD_NB_CONFIG *pConfig
)
{
PCI_ADDR Port;
UINT8 LinkSpeed;
UINT32 LinkDeemphasisMask;
UINT32 LinkDeemphasisValue;
UINT32 RegA4Value;
UINT32 RegA2Value;
UINT32 RegC0Value;
CORE_INFO *pCoreInfo;
PORT_STATIC_INFO *pStaticPortInfo;
PCIE_CONFIG *pPcieConfig;
pPcieConfig = GET_PCIE_CONFIG_PTR (pConfig);
CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (pConfig), CIMX_NBPCIE_TRACE), "[NBPCIE]PcieLibSetLinkMode PortId %d Operation %d Enter\n", PortId, Operation));
LinkSpeed = 2;
RegA4Value = BIT29 + BIT0;
RegA2Value = 0;
RegC0Value = 0;
Port = PcieLibGetPortPciAddress (PortId, pConfig);
pStaticPortInfo = PcieLibGetStaticPortInfo (PcieLibNativePortId (PortId, pConfig), pConfig);
pCoreInfo = PcieLibGetCoreInfo (PcieLibGetCoreId (PortId, pConfig), pConfig);
LinkDeemphasisValue = pPcieConfig->ExtPortConfiguration[PortId].PortDeemphasis << pStaticPortInfo->DeemphasisAddress;
LinkDeemphasisMask = ~(1 << pStaticPortInfo->DeemphasisAddress);
if (Operation == PcieLinkModeGen1 || Operation == PcieLinkModeGen2AdvertizeOnly) {
RegC0Value = BIT15;
RegA2Value = BIT13;
if (Operation == PcieLinkModeGen1) {
RegA4Value = 0;
LinkSpeed = 1;
LinkDeemphasisValue = 0;
}
}
CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (pConfig), CIMX_NBPCIE_TRACE), " pCoreInfo->DeemphasisRegister %x pStaticPortInfo->DeemphasisAddress %x LinkDeemphasisMask %x, LinkDeemphasisValue %x\n", pCoreInfo->DeemphasisRegister, pStaticPortInfo->DeemphasisAddress, LinkDeemphasisMask, LinkDeemphasisValue));
LibNbPciIndexRMW (Port.AddressValue | NB_BIF_INDEX, NB_BIFNBP_REGA4 , AccessWidth32, (UINT32)~(BIT0 + BIT29), RegA4Value , pConfig);
LibNbPciIndexRMW (pConfig->NbPciAddress.AddressValue | NB_MISC_INDEX, pCoreInfo->DeemphasisRegister, AccessWidth32, LinkDeemphasisMask, LinkDeemphasisValue , pConfig);
LibNbPciRMW (Port.AddressValue | NB_PCIP_REG88, AccessWidth8, 0xF0, LinkSpeed, pConfig);
LibNbPciIndexRMW (Port.AddressValue | NB_BIF_INDEX, NB_BIFNBP_REGC0 , AccessWidth32, (UINT32)~(BIT15), RegC0Value , pConfig);
LibNbPciIndexRMW (Port.AddressValue | NB_BIF_INDEX, NB_BIFNBP_REGA2 , AccessWidth32, (UINT32)~(BIT13), RegA2Value , pConfig);
}
/*----------------------------------------------------------------------------------------*/
/**
* Request PCIE reset to be executed
*
*
*
* @param[in] pConfig Northbridge configuration structure pointer.
*
*/
AGESA_STATUS
PcieLibRequestPciReset (
IN AMD_NB_CONFIG *pConfig
)
{
AGESA_STATUS Status;
SCRATCH_1 Scratch;
Status = AGESA_UNSUPPORTED;
LibNbPciIndexRead (pConfig->NbPciAddress.AddressValue | NB_HTIU_INDEX, NB_HTIU_REG15, AccessS3SaveWidth32, (UINT32*)&Scratch, pConfig);
if (Scratch.ResetCount == 0xf) {
Scratch.ResetCount = 0;
}
if (Scratch.ResetCount < 5) {
++Scratch.ResetCount;
LibNbPciIndexWrite (pConfig->NbPciAddress.AddressValue | NB_HTIU_INDEX, NB_HTIU_REG15, AccessS3SaveWidth32, (UINT32*)&Scratch, pConfig);
if (LibNbCallBack (PHCB_AmdGeneratePciReset, WARM_RESET , pConfig) != AGESA_SUCCESS) {
LibNbIoRMW (0xCF9, AccessWidth8, 0, 0x6, pConfig);
}
}
return Status;
}
/*----------------------------------------------------------------------------------------*/
/**
* Control Core Reset
*
*
*
* @param[in] CoreId PCI Express Core ID
* @param[in] Operation Assert/Deassert/Check core reset
* @param[in] pConfig Northbridge configuration structure pointer.
*/
PCI_CORE_RESET
PcieLibCoreReset (
IN CORE CoreId,
IN PCI_CORE_RESET Operation,
IN AMD_NB_CONFIG *pConfig
)
{
UINT32 Value;
UINT32 CalibrationReset;
UINT32 GlobalReset;
UINT32 RegisterAddress;
UINT32 CoreAddress;
RegisterAddress = NB_MISC_REG08;
CoreAddress = PcieLibGetCoreAddress (CoreId, pConfig);
switch (CoreAddress) {
case GPP3b_CORE:
RegisterAddress = NB_MISC_REG2A; // break missing and it is not an error.
case GPP1_CORE:
CalibrationReset = BIT14;
GlobalReset = BIT15;
break;
case GPP2_CORE:
CalibrationReset = BIT12;
GlobalReset = BIT13;
break;
case GPP3a_CORE:
CalibrationReset = BIT30;
GlobalReset = BIT31;
break;
default:
return PcieCoreResetAllDeassert;
}
switch (Operation) {
case PcieCoreResetAllDeassert:
LibNbPciIndexRMW (pConfig->NbPciAddress.AddressValue | NB_MISC_INDEX, RegisterAddress, AccessS3SaveWidth32, ~CalibrationReset, 0x0, pConfig);
STALL (GET_BLOCK_CONFIG_PTR (pConfig), 200, 0);
LibNbPciIndexRMW (pConfig->NbPciAddress.AddressValue | NB_MISC_INDEX, RegisterAddress, AccessS3SaveWidth32, ~GlobalReset, 0x0, pConfig);
STALL (GET_BLOCK_CONFIG_PTR (pConfig), 2000, 0);
break;
case PcieCoreResetAllAssert:
LibNbPciIndexRMW (pConfig->NbPciAddress.AddressValue | NB_MISC_INDEX, RegisterAddress, AccessS3SaveWidth32, 0xffffffff, CalibrationReset | GlobalReset, pConfig);
break;
case PcieCoreResetAllCheck:
LibNbPciIndexRead (pConfig->NbPciAddress.AddressValue | NB_MISC_INDEX, RegisterAddress, AccessS3SaveWidth32, &Value, pConfig);
Operation = (Value & (CalibrationReset | GlobalReset))?PcieCoreResetAllAssert:PcieCoreResetAllDeassert;
break;
default:
CIMX_ASSERT (FALSE);
}
return Operation;
}
UINT8 GfxLineMapTable[] = {
0x00, 0x01, 0x01, 0x03, 0x0f, 0x00, 0xFF
};
UINT8 GppLineMapTable[] = {
0x00, 0x01, 0x03, 0x0F
};
/*----------------------------------------------------------------------------------------*/
/**
* Power off port lanes.
*
*
*
* @param[in] PortId PCI Express Port ID
* @param[in] Width Port Link Width.
* @param[in] pConfig Northbridge configuration structure pointer.
*/
VOID
PcieLibPowerOffPortLanes (
IN PORT PortId,
IN PCIE_LINK_WIDTH Width,
IN AMD_NB_CONFIG *pConfig
)
{
CORE CoreId;
LINK_INFO LinkInfo;
UINT32 PowerOffPads;
UINT32 CoreAddress;
UINT8* pLineMapTable;
UINT16 MaxLaneBitMap;
UINT16 LaneBitMap;
CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (pConfig), CIMX_NBPCIE_TRACE), "[NBPCIE]PcieLibPowerOffPortLanes (PortId = %d, Width = %d) Enter\n", PortId, Width));
CoreId = PcieLibGetCoreId (PortId, pConfig);
LinkInfo = PcieLibGetPortLinkInfo (PortId, pConfig);
CoreAddress = PcieLibGetCoreAddress (CoreId, pConfig);
if (CoreAddress == GPP1_CORE || CoreAddress == GPP2_CORE) {
pLineMapTable = &GfxLineMapTable[0];
LinkInfo.Line0Offset /= 2;
} else {
pLineMapTable = &GppLineMapTable[0];
}
pLineMapTable = (UINT8*)FIX_PTR_ADDR (pLineMapTable, NULL);
LaneBitMap = pLineMapTable[Width];
MaxLaneBitMap = pLineMapTable[LinkInfo.MaxLinkWidth];
if (PcieLibIsPortReversed (PortId, pConfig)) {
LaneBitMap = (UINT16)LibNbBitReverse ((UINT32)LaneBitMap, LibAmdBitScanForward (MaxLaneBitMap), LibAmdBitScanReverse (MaxLaneBitMap));
}
PowerOffPads = (MaxLaneBitMap ^ LaneBitMap) << LinkInfo.Line0Offset;
CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (pConfig), CIMX_NBPCIE_TRACE), " Pads %x Exit\n", PowerOffPads));
LibNbPciIndexRMW (pConfig->NbPciAddress.AddressValue | NB_BIF_INDEX, NB_BIFNB_REG65 | CoreAddress, AccessWidth32, 0xffffffff, PowerOffPads | (PowerOffPads << 8), pConfig);
CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (pConfig), CIMX_NBPCIE_TRACE), "[NBPCIE]PcieLibPowerOffPortLanes Exit\n"));
}
/*----------------------------------------------------------------------------------------*/
/**
* Hide Unused Ports
*
*
*
* @param[in] pConfig Northbridge configuration structure pointer.
*
*/
VOID
PcieLibHidePorts (
IN AMD_NB_CONFIG *pConfig
)
{
UINT32 PresentPortMask;
UINT32 DetectedPortMask;
UINT32 HotplugPortMask;
UINT32 Value;
PORT PortId;
PCIE_CONFIG *pPcieConfig;
CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (pConfig), CIMX_NBPCIE_TRACE), "[NBPCIE]PcieLibHidePorts Enter\n"));
pPcieConfig = GET_PCIE_CONFIG_PTR (pConfig);
PresentPortMask = 0;
DetectedPortMask = 0;
HotplugPortMask = 0;
// Hide SB Port
LibNbPciIndexRMW (pConfig->NbPciAddress.AddressValue | NB_MISC_INDEX, NB_MISC_REG00, AccessS3SaveWidth32, (UINT32)~BIT6, 0, pConfig);
for (PortId = MIN_PORT_ID; PortId <= MAX_PORT_ID; PortId++) {
if (pPcieConfig->PortConfiguration[PortId].PortPresent == ON && PcieLibIsValidPortId (PortId, pConfig)) {
PCI_ADDR Port;
Port = PcieLibGetPortPciAddress (PortId, pConfig);
if (pPcieConfig->PortConfiguration[PortId].PortDetected == ON ) {
DetectedPortMask |= 1 << Port.Address.Device;
}
if (pPcieConfig->PortConfiguration[PortId].PortHotplug != OFF) {
HotplugPortMask |= 1 << Port.Address.Device;
}
PresentPortMask |= 1 << Port.Address.Device;
}
}
if (pPcieConfig->PcieConfiguration.DisableHideUnusedPorts == ON) {
Value = PresentPortMask;
} else {
Value = DetectedPortMask | HotplugPortMask;
}
//CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (pConfig), CIMX_NBPCIE_TRACE), " Present Port 0x%x Visible Ports 0x%xExit\n",PresentPortMask,VisiblePortMask));
Value = (~((Value & (0xFC)) + ((Value & 0x3E00) << 7))) & 0x1F00FC;
// Hide GFX/GFX2/GPP/GPP2 Ports
LibNbPciIndexRMW (pConfig->NbPciAddress.AddressValue | NB_MISC_INDEX, NB_MISC_REG0C, AccessS3SaveWidth32, 0xffffffff, Value, pConfig);
CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (pConfig), CIMX_NBPCIE_TRACE), "[NBPCIE]PcieLibHidePorts Exit\n"));
}
/*----------------------------------------------------------------------------------------*/
/**
* UnHide all PCIE Ports
*
*
*
* @param[in] pConfig Northbridge configuration structure pointer.
*/
VOID
PcieLibUnHidePorts (
IN AMD_NB_CONFIG *pConfig
)
{
LibNbPciIndexRMW (pConfig->NbPciAddress.AddressValue | NB_MISC_INDEX, NB_MISC_REG0C, AccessS3SaveWidth32, (UINT32)~0x1F00FCul, 0, pConfig);
LibNbPciIndexRMW (pConfig->NbPciAddress.AddressValue | NB_MISC_INDEX, NB_MISC_REG00, AccessS3SaveWidth32, (UINT32)~BIT6, BIT6, pConfig);
}
PCIE_DEFAULT_CONFIG PcieDefaultConfig = {
{0, 1, 0, 0},
{
{0, 1, 1, 1, 1, 1, 1, 0, PcieTxDriveStrangth22mA, 0, 0, PcieMediumChannel, 1, 1, 1}, //GPP1
{0, 1, 1, 1, 1, 1, 1, 0, PcieTxDriveStrangth22mA, 0, 0, PcieMediumChannel, 1, 1, 1}, //GPP2
{0, 1, 1, 1, 1, 1, 1, 0, PcieTxDriveStrangth22mA, 0, 0, PcieMediumChannel, 1, 1, 1}, //GPP3a
{0, 1, 1, 1, 1, 1, 0, 0, PcieTxDriveStrangth22mA, 0, 0, PcieMediumChannel, 1, 1, 1}, //GPP3b
{0, 1, 0, 1, 1, 1, 0, 0, PcieTxDriveStrangth22mA, 0, 0, PcieMediumChannel, 0, 0, 0} //SB
},
(BIT2 + BIT4 + BIT5 + BIT6 + BIT7 + BIT8 + BIT9 + BIT10 + BIT11 + BIT13) | (BIT3 + BIT12),
0,
2,
0,
60,
};
/*----------------------------------------------------------------------------------------*/
/**
* AMD structures initializer for all NB.
*
*
*
* @param[in] ConfigPtr Northbridges configuration block pointer.
*
*/
AGESA_STATUS
AmdPcieInitializer (
IN OUT AMD_NB_CONFIG_BLOCK *ConfigPtr
)
{
AGESA_STATUS Status;
Status = LibNbApiCall (PcieLibInitializer, ConfigPtr);
return Status;
}
/*----------------------------------------------------------------------------------------*/
/**
* Initialize default PCIE_CONFIG setting
*
*
*
* @param[in] pConfig Northbridge configuration structure pointer.
*
*/
AGESA_STATUS
PcieLibInitializer (
IN OUT AMD_NB_CONFIG *pConfig
)
{
CORE CoreId;
PCIE_CONFIG *pPcieConfig;
PCIE_DEFAULT_CONFIG *pPcieDefaultConfig;
AMD_NB_CONFIG_BLOCK *ConfigPtr;
PORT PortId;
CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (pConfig), CIMX_NBPCIE_TRACE), "[NBPCIE]PcieLibInitializer Enter\n"));
pPcieConfig = GET_PCIE_CONFIG_PTR (pConfig);
if (pPcieConfig == NULL) {
return AGESA_WARNING;
}
if (pPcieConfig->sHeader.InitializerID == INITIALIZED_BY_INITIALIZER) {
return AGESA_SUCCESS;
}
ConfigPtr = GET_BLOCK_CONFIG_PTR (pConfig);
LibAmdMemFill (pPcieConfig, 0, sizeof (PCIE_CONFIG), (AMD_CONFIG_PARAMS *)&(pPcieConfig->sHeader));
pPcieConfig->sHeader.InitializerID = INITIALIZED_BY_INITIALIZER;
pPcieDefaultConfig = (PCIE_DEFAULT_CONFIG*)FIX_PTR_ADDR (&PcieDefaultConfig, NULL);
for (CoreId = 0; CoreId <= MAX_CORE_ID; CoreId++) {
pPcieConfig->CoreSetting[CoreId] = pPcieDefaultConfig->CoreSetting[CoreId];
}
pPcieConfig->PcieConfiguration = pPcieDefaultConfig->PcieConfiguration;
if (ConfigPtr->PlatformType == DesktopPlatform) {
pPcieConfig->PcieConfiguration.NbSbVc1 = ON;
}
for (PortId = MIN_PORT_ID; PortId <= MAX_PORT_ID; PortId++) {
pPcieConfig->ExtPortConfiguration[PortId].PortDeemphasis = PcieTxDeemphasis3p5dB;
}
pPcieConfig->CoreConfiguration[2] = PcieLibGetCoreConfiguration (2, pConfig);
pPcieConfig->ReceiverDetectionPooling = pPcieDefaultConfig->ReceiverDetectionPooling;
pPcieConfig->ResetToTrainingDelay = pPcieDefaultConfig->ResetToTrainingDelay;
pPcieConfig->ExtPortConfiguration[8].PortL1ImmediateACK = ON;
pPcieConfig->TrainingToLinkTestDelay = pPcieDefaultConfig->TrainingToLinkTestDelay;
pPcieConfig->DeviceInitMaskS1 = pPcieDefaultConfig->DeviceInitMaskS1;
pPcieConfig->DeviceInitMaskS2 = pPcieDefaultConfig->DeviceInitMaskS2;
CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (pConfig), CIMX_NBPCIE_TRACE), "[NBPCIE]PcieLibInitializer Exit\n"));
return AGESA_SUCCESS;
}
/*----------------------------------------------------------------------------------------*/
/*
* Validate Gfx Core Configuration
*
*
*
*
*
*/
AGESA_STATUS
PcieLibValidateGfxConfig (
IN PORT PortId,
IN OUT AMD_NB_CONFIG *pConfig
)
{
CORE CoreId;
PCIE_CONFIG *pPcieConfig;
CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (pConfig), CIMX_NBPCIE_TRACE), "[NBPCIE]PcieLibValidateGfxConfig Enter\n"));
CoreId = PcieLibGetCoreId (PortId, pConfig);
pPcieConfig = GET_PCIE_CONFIG_PTR (pConfig);
CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (pConfig), CIMX_NBPCIE_TRACE), " CoreConfiguration[%d] = \n", CoreId));
if (pPcieConfig->CoreConfiguration[CoreId] == 0x0) {
pPcieConfig->CoreConfiguration[CoreId] = (pPcieConfig->PortConfiguration[PortId].PortPresent == ON)?GFX_CONFIG_AABB:GFX_CONFIG_AAAA;
} else {
if (pPcieConfig->CoreConfiguration[CoreId] != GFX_CONFIG_AABB &&
pPcieConfig->CoreConfiguration[CoreId] != GFX_CONFIG_AAAA) {
//We have received request for unknown configuration.
//pPcieConfig->CoreSetting[CoreId].CoreDisabled = ON;
pPcieConfig->PortConfiguration[PortId].PortPresent = 0;
pPcieConfig->PortConfiguration[PortId - 1].PortPresent = 0;
return AGESA_WARNING;
}
}
CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (pConfig), CIMX_NBPCIE_TRACE), " CoreConfiguration[%d] = %x\n", CoreId, pPcieConfig->CoreConfiguration[CoreId]));
return AGESA_SUCCESS;
}
/*----------------------------------------------------------------------------------------*/
/**
* Validate input parameters for early PCIE init.
*
*
*
* @param[in] pConfig Northbridge configuration structure pointer.
*
*/
AGESA_STATUS
PcieLibInitValidateInput (
IN OUT AMD_NB_CONFIG *pConfig
)
{
AGESA_STATUS Status;
PCIE_CONFIG *pPcieConfig;
NB_INFO NbInfo;
CORE CoreId;
PORT PortId;
NbInfo = LibNbGetRevisionInfo (pConfig);
pPcieConfig = GET_PCIE_CONFIG_PTR (pConfig);
if (NbInfo.Type == NB_UNKNOWN || pPcieConfig == NULL) {
return AGESA_FATAL;
}
Status = AGESA_SUCCESS;
//Validate GFX configuration
if (PcieLibValidateGfxConfig (3, pConfig) != AGESA_SUCCESS) {
REPORT_EVENT (AGESA_WARNING, PCIE_ERROR_CORE_CONFIGURATION, GPP1_CORE , 0, 0, 0, pConfig);
Status = AGESA_WARNING;
}
if (PcieLibValidateGfxConfig (12, pConfig) != AGESA_SUCCESS) {
REPORT_EVENT (AGESA_WARNING, PCIE_ERROR_CORE_CONFIGURATION, GPP2_CORE , 0, 0, 0, pConfig);
Status = AGESA_WARNING;
}
//Enable SB port on NB - SB chain and disable otherwise
pPcieConfig->PortConfiguration[8].PortPresent = (pConfig->NbPciAddress.AddressValue == 0)?ON:OFF;
for (CoreId = 0; CoreId <= MAX_CORE_ID; CoreId++) {
if (pPcieConfig->PcieConfiguration.DisableHideUnusedPorts == ON) {
//pPcieConfig->CoreSetting[CoreId].PowerOffUnusedLanes = OFF;
pPcieConfig->CoreSetting[CoreId].TxClockOff = OFF;
pPcieConfig->CoreSetting[CoreId].LclkClockOff = OFF;
pPcieConfig->CoreSetting[CoreId].PowerOffPll = OFF;
}
if (pPcieConfig->CoreSetting[CoreId].ChannelType != 0) {
//Set Trasmitter drive strength based on cahnnel type
if (pPcieConfig->CoreSetting[CoreId].ChannelType == PcieLongChannel) {
pPcieConfig->CoreSetting[CoreId].TxDriveStrength = (NbInfo.Revision == NB_REV_A11)? PcieTxDriveStrangth24mA : PcieTxDriveStrangth26mA;
} else {
pPcieConfig->CoreSetting[CoreId].TxDriveStrength = PcieTxDriveStrangth22mA;
}
// Enable half swing mode
if (pPcieConfig->CoreSetting[CoreId].ChannelType == PcieShortChannel) {
pPcieConfig->CoreSetting[CoreId].TxHalfSwingMode = ON;
} else {
pPcieConfig->CoreSetting[CoreId].TxHalfSwingMode = OFF;
}
}
}
for (PortId = MIN_PORT_ID; PortId <= MAX_PORT_ID; PortId++) {
CoreId = PcieLibGetCoreId (PortId, pConfig);
if (pPcieConfig->ExtPortConfiguration[PortId].PortPowerLimit == 0) {
pPcieConfig->ExtPortConfiguration[PortId].PortPowerLimit = 75; //Set 75W by default
}
if (pPcieConfig->CoreSetting[CoreId].ChannelType != 0) {
if (pPcieConfig->CoreSetting[CoreId].ChannelType == PcieLongChannel) {
pPcieConfig->ExtPortConfiguration[PortId].PortDeemphasis = PcieTxDeemphasis6dB;
} else {
pPcieConfig->ExtPortConfiguration[PortId].PortDeemphasis = PcieTxDeemphasis3p5dB;
}
}
}
return Status;
}
/*----------------------------------------------------------------------------------------*/
/**
* Enable PCIE Extended configuration MMIO.
*
*
*
* @param[in] PcieMmioBase MMIO Base Address in 1MB unit.
* @param[in] PcieMmioSize MMIO Size in 1MB unit
* @param[in] pConfig Northbridge configuration structure pointer.
*
*/
VOID
PcieLibSetPcieMmioBase (
IN UINT16 PcieMmioBase,
IN UINT16 PcieMmioSize,
IN AMD_NB_CONFIG *pConfig
)
{
UINT8 BAR3BusRange;
BAR3BusRange = LibAmdBitScanReverse ((UINT32)PcieMmioSize);
LibNbPciIndexRMW (pConfig->NbPciAddress.AddressValue | NB_MISC_INDEX, NB_MISC_REG00, AccessWidth32, (UINT32)~BIT3, 0x0, pConfig);
LibNbPciRMW (pConfig->NbPciAddress.AddressValue | NB_PCI_REG7F, AccessWidth8, (UINT32)~BIT6, BIT6, pConfig);
LibNbPciRMW (pConfig->NbPciAddress.AddressValue | (NB_PCI_REG84 + 2), AccessWidth8, (UINT32)~(0x7), (BAR3BusRange > 8)?0:BAR3BusRange, pConfig);
LibNbPciRMW (pConfig->NbPciAddress.AddressValue | NB_PCI_REG1C, AccessWidth32, 0, (UINT32) (PcieMmioBase << 20), pConfig);
LibNbPciRMW (pConfig->NbPciAddress.AddressValue | NB_PCI_REG7F, AccessWidth8, (UINT32)~BIT6, 0, pConfig);
LibNbPciIndexRMW (pConfig->NbPciAddress.AddressValue | NB_HTIU_INDEX, NB_HTIU_REG32, AccessWidth32, 0xffffffff, BIT28, pConfig);
LibNbPciIndexRMW (pConfig->NbPciAddress.AddressValue | NB_MISC_INDEX, NB_MISC_REG00, AccessWidth32, 0xffffffff, BIT3, pConfig);
LibNbPciRMW (pConfig->NbPciAddress.AddressValue | NB_PCI_REG04, AccessWidth8, (UINT32)~BIT1, BIT1, pConfig);
}
/*----------------------------------------------------------------------------------------*/
/**
* Assert/Deassert Strap valid enables programming for misc strap features.
*
*
*
* @param[in] CoreId PCI Express Core ID
* @param[in] Operation Assert or deassert strap valid.
* @param[in] pConfig Northbridge configuration structure pointer.
*
*/
VOID
PcieLibStrapModeControl (
IN CORE CoreId,
IN PCIE_STRAP_MODE Operation,
IN OUT AMD_NB_CONFIG *pConfig
)
{
CORE_INFO *pCoreInfo;
pCoreInfo = PcieLibGetCoreInfo (CoreId, pConfig);
LibNbPciIndexRMW (
pConfig->NbPciAddress.AddressValue | NB_MISC_INDEX,
pCoreInfo->StrapRegister,
AccessS3SaveWidth32,
~(1 << pCoreInfo->StrapAddress),
(Operation == PcieCoreStrapConfigStart)?(1 << pCoreInfo->StrapAddress):0,
pConfig
);
}
/*----------------------------------------------------------------------------------------*/
/**
* Get Pcie Port Info.
*
*
*
* @param[in] PortId PCI Express Port ID
* @param[in] pConfig Northbridge configuration structure pointer.
*
*/
PORT_INFO*
PcieLibGetPortInfo (
IN PORT PortId,
IN OUT AMD_NB_CONFIG *pConfig
)
{
CORE CoreId;
UINT32 CoreConfig;
PORT_INFO *pPortInfo;
PORT NativePortId;
GPP_CFG_INFO *pGppCfgInfoTable;
CoreId = PcieLibGetCoreId (PortId, pConfig);
CoreConfig = PcieLibGetCoreConfiguration (CoreId, pConfig);
switch (PcieLibGetCoreAddress (CoreId, pConfig)) {
case GPP1_CORE:
case GPP2_CORE:
pPortInfo = &pGfxPortFullA;
if (CoreConfig == GFX_CONFIG_AABB) {
if (PortId == 3 || PortId == 12) {
pPortInfo = &pGfxPortB;
} else {
pPortInfo = &pGfxPortA;
}
}
break;
case SB_CORE:
case GPP3b_CORE:
pPortInfo = &pGpp420000[0];
break;
case GPP3a_CORE:
pGppCfgInfoTable = (GPP_CFG_INFO*)FIX_PTR_ADDR (&GppCfgInfoTable[CoreConfig - 1], NULL);
NativePortId = PcieLibNativePortId (PortId, pConfig);
if (NativePortId == 0xf) {
return NULL;
}
pPortInfo = &pGppCfgInfoTable->PortInfoPtr[NativePortId - 4];
break;
default:
return NULL;
}
return (PORT_INFO*)FIX_PTR_ADDR (pPortInfo, NULL);
}
/*----------------------------------------------------------------------------------------*/
/**
* Get Pointer to static port info
*
*
*
* @param[in] PortId PCI Express Port ID
* @param[in] pConfig Northbridge configuration structure pointer.
*/
PORT_STATIC_INFO*
PcieLibGetStaticPortInfo (
IN PORT PortId,
IN OUT AMD_NB_CONFIG *pConfig
)
{
PORT_STATIC_INFO *pPortStaticInfo;
pPortStaticInfo = (PORT_STATIC_INFO*)FIX_PTR_ADDR (&PortInfoTable[PortId - MIN_PORT_ID], NULL);
return pPortStaticInfo ;
}
/*----------------------------------------------------------------------------------------*/
/**
* Get Native Port Id.
* Native Port Id can be different from Port ID only on GPPSB core ports.
*
*
* @param[in] PortId PCI Express Port ID
* @param[in] pConfig Northbridge configuration structure pointer.
*/
PORT
PcieLibNativePortId (
IN PORT PortId,
IN OUT AMD_NB_CONFIG *pConfig
)
{
CORE CoreId;
GPP_CFG_INFO *pGppCfgInfoTable;
CoreId = PcieLibGetCoreId (PortId, pConfig);
if (PcieLibGetCoreAddress (CoreId, pConfig) == GPP3a_CORE) {
UINT32 CoreConfig;
CoreConfig = PcieLibGetCoreConfiguration (CoreId, pConfig);
pGppCfgInfoTable = (GPP_CFG_INFO*)FIX_PTR_ADDR (&GppCfgInfoTable[CoreConfig - 1], NULL);
return (pGppCfgInfoTable->PortIdMap >> ((PortId - 4) * 4)) & 0xF;
} else {
return PortId;
}
}
/*----------------------------------------------------------------------------------------*/
/**
* Get pointer to Core info structure.
*
*
*
* @param[in] CoreId PCI Express Core ID
* @param[in] pConfig Northbridge configuration structure pointer.
*/
CORE_INFO*
PcieLibGetCoreInfo (
IN CORE CoreId,
IN AMD_NB_CONFIG *pConfig
)
{
return (CORE_INFO*)FIX_PTR_ADDR (&CoreInfoTable[CoreId], NULL);
}
/*----------------------------------------------------------------------------------------*/
/**
* Reset Device in slot.
* Check if slot has controlled by GPI reset. If support toggle reset for 10us.
*
*
* @param[in] PortId PCI Express Port ID
* @param[in] pConfig Northbridge configuration structure pointer.
*/
AGESA_STATUS
PcieLibResetSlot (
IN PORT PortId,
IN AMD_NB_CONFIG *pConfig
)
{
AGESA_STATUS Status;
Status = LibNbCallBack (PHCB_AmdPortResetSupported, (UINTN) (1 << PortId), pConfig);
if (Status == AGESA_SUCCESS) {
LibNbCallBack (PHCB_AmdPortResetAssert, (UINTN) (1 << PortId), pConfig);
STALL (GET_BLOCK_CONFIG_PTR (pConfig), 10, 0);
LibNbCallBack (PHCB_AmdPortResetDeassert, (UINTN) (1 << PortId), pConfig);
}
return Status;
}
/*----------------------------------------------------------------------------------------*/
/*
* Secondary level interface to check if Gen2 disabled.
*
*
*
* @param[in] PortId PCI Express Port ID
* @param[in] pConfig Northbridge configuration structure pointer.
*/
BOOLEAN
PcieLibCheckGen2Disabled (
IN PORT PortId,
IN OUT AMD_NB_CONFIG *pConfig
)
{
SCRATCH_1 Scratch;
LibNbPciIndexRead (pConfig->NbPciAddress.AddressValue | NB_HTIU_INDEX, NB_HTIU_REG15, AccessS3SaveWidth32, (UINT32*)&Scratch, pConfig);
if ((Scratch.PortGen2Disable & (1 << (PortId - 2))) != 0) {
return FALSE;
} else {
CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (pConfig), CIMX_NBPCIE_TRACE), " Force Gen2 Disable\n"));
return TRUE;
}
}
/*----------------------------------------------------------------------------------------*/
/*
* Request Gen 2 disabled on next boot.
*
*
*
* @param[in] PortId PCI Express Port ID
* @param[in] pConfig Northbridge configuration structure pointer.
*/
VOID
PcieLibSetGen2Disabled (
IN PORT PortId,
IN OUT AMD_NB_CONFIG *pConfig
)
{
SCRATCH_1 Scratch;
LibNbPciIndexRead (pConfig->NbPciAddress.AddressValue | NB_HTIU_INDEX, NB_HTIU_REG15, AccessS3SaveWidth32, (UINT32*)&Scratch, pConfig);
Scratch.PortGen2Disable &= (~(1 << (PortId - 2)));
LibNbPciIndexWrite (pConfig->NbPciAddress.AddressValue | NB_HTIU_INDEX, NB_HTIU_REG15, AccessS3SaveWidth32, (UINT32*)&Scratch, pConfig);
}
/*----------------------------------------------------------------------------------------*/
/*
* Force link to compliance mode
*
*
*
* @param[in] PortId PCI Express Port ID
* @param[in] pConfig Northbridge configuration structure pointer.
*/
VOID
PcieLibSetLinkCompliance (
IN PORT PortId,
IN AMD_NB_CONFIG *pConfig
)
{
PCI_ADDR Port;
PCIE_CONFIG *pPcieConfig;
Port = PcieLibGetPortPciAddress (PortId, pConfig);
pPcieConfig = GET_PCIE_CONFIG_PTR (pConfig);
if (pPcieConfig->PortConfiguration[PortId].PortLinkMode == PcieLinkModeGen1) {
LibNbPciIndexRMW (Port.AddressValue | NB_BIF_INDEX, NB_BIFNBP_REGC0, AccessWidth32, (UINT32)~BIT13, BIT13, pConfig);
} else {
LibNbPciRMW (Port.AddressValue | NB_PCIP_REG88, AccessWidth8, (UINT32)~BIT4, BIT4, pConfig);
}
}
/*----------------------------------------------------------------------------------------*/
/**
* Get PCIe device type
*
*
*
* @param[in] Device PCI address of device.
* @param[in] pConfig Northbridge configuration structure pointer.
*
* @retval PCIe device type (see PCIE_DEVICE_TYPE)
*/
/*----------------------------------------------------------------------------------------*/
PCIE_DEVICE_TYPE
PcieGetDeviceType (
IN PCI_ADDR Device,
IN AMD_NB_CONFIG *pConfig
)
{
UINT8 PcieCapPtr;
UINT8 Value;
PcieCapPtr = LibNbFindPciCapability (Device.AddressValue, PCIE_CAP_ID, pConfig);
if (PcieCapPtr != 0) {
LibNbPciRead (Device.AddressValue | (PcieCapPtr + 0x2) , AccessWidth8, &Value, pConfig);
return Value >> 4;
}
return PcieNotPcieDevice;
}
/*----------------------------------------------------------------------------------------*/
/**
* Get bitmap of cores that have active or potentially active ports
*
*
*
* @param[in] pConfig Northbridge configuration structure pointer.
*
* @retval Bitmap of cores
*/
/*----------------------------------------------------------------------------------------*/
UINT8
PcieLibGetActiveCoreMap (
IN AMD_NB_CONFIG *pConfig
)
{
PORT PortId;
CORE CoreId;
UINT8 ActiveCoreMap;
PCIE_CONFIG *pPcieConfig;
pPcieConfig = GET_PCIE_CONFIG_PTR (pConfig);
ActiveCoreMap = 0;
//Check through Ports
for (PortId = MIN_PORT_ID; PortId <= MAX_PORT_ID; PortId++) {
if (pPcieConfig->PortConfiguration[PortId].PortPresent == ON && PcieLibIsValidPortId (PortId, pConfig)) {
if (pPcieConfig->PortConfiguration[PortId].PortCompliance == ON ||
pPcieConfig->PortConfiguration[PortId].PortDetected == ON ||
pPcieConfig->PortConfiguration[PortId].PortHotplug != OFF) {
CoreId = PcieLibGetCoreId (PortId, pConfig);
ActiveCoreMap |= (1 << CoreId);
}
}
}
CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (pConfig), CIMX_NBPCIE_TRACE), " Active Core Map = %x\n", ActiveCoreMap));
return ActiveCoreMap;
}