/** * @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; }