diff options
author | Kerry Sheh <shekairui@gmail.com> | 2012-01-31 20:39:37 +0800 |
---|---|---|
committer | Patrick Georgi <patrick@georgi-clan.de> | 2012-02-02 13:54:36 +0100 |
commit | 9292d89be84d6abf9257ddb872887d4f53b2a00e (patch) | |
tree | 9eaa548f1742745f57fc92a12734649fec8db1cd /src/vendorcode/amd/cimx/rd890/nbPcieLib.c | |
parent | 17670866a0d12839bc2a4c852210ccf11d3cb4b2 (diff) |
RD890 Northbridge: AMD RD890/SR56X0 Northbridge CIMX code
Change-Id: If9908ffeb5b707a660db38dc44f5118347cbcc06
Signed-off-by: Kerry Sheh <kerry.she@amd.com>
Signed-off-by: Kerry Sheh <shekairui@gmail.com>
Reviewed-on: http://review.coreboot.org/557
Tested-by: build bot (Jenkins)
Reviewed-by: Patrick Georgi <patrick@georgi-clan.de>
Diffstat (limited to 'src/vendorcode/amd/cimx/rd890/nbPcieLib.c')
-rw-r--r-- | src/vendorcode/amd/cimx/rd890/nbPcieLib.c | 1604 |
1 files changed, 1604 insertions, 0 deletions
diff --git a/src/vendorcode/amd/cimx/rd890/nbPcieLib.c b/src/vendorcode/amd/cimx/rd890/nbPcieLib.c new file mode 100644 index 0000000000..2e91cb6c1a --- /dev/null +++ b/src/vendorcode/amd/cimx/rd890/nbPcieLib.c @@ -0,0 +1,1604 @@ +/** + * @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; +} |