/** * @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 "HotplugFirmware.h" /*---------------------------------------------------------------------------------------- * D E F I N I T I O N S A N D M A C R O S *---------------------------------------------------------------------------------------- */ #define MCU_CLEAR_BLOCK_LENGTH 16 /*---------------------------------------------------------------------------------------- * 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 *---------------------------------------------------------------------------------------- */ /*---------------------------------------------------------------------------------------- * E X P O R T E D F U N C T I O N S *---------------------------------------------------------------------------------------- */ INDIRECT_REG_ENTRY STATIC PcieMiscInitTable[] = { { NB_MISC_REG20, (UINT32)~BIT1, 0x0 }, //enable static device remapping by default { NB_MISC_REG22, 0xffffffff, BIT27 | (0x8 << 12) | (0x8 << 16) | (0x8 << 20) }, { NB_MISC_REG2B, 0xffffffff, (0x8 << 12) }, { NB_MISC_REG6C, 0xffffffff, (0x8 << 16) }, { 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 }; /*----------------------------------------------------------------------------------------*/ /** * Misc Initialization prior port training. * * * * @param[in] pConfig Northbridge configuration structure pointer. * */ VOID PcieLibPreTrainingInit ( IN AMD_NB_CONFIG *pConfig ) { UINT32 Value; PCIE_CONFIG *pPcieConfig; UINT32 ServerHotplugMask; BOOLEAN SmuWa; CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (pConfig), CIMX_NBPCIE_TRACE), "[NBPCIE]PcieLibPreTrainingInit Enter\n")); pPcieConfig = GET_PCIE_CONFIG_PTR (pConfig); ServerHotplugMask = 0; //Init Misc registers LibNbIndirectTableInit ( pConfig->NbPciAddress.AddressValue | NB_MISC_INDEX, 0, (INDIRECT_REG_ENTRY*)FIX_PTR_ADDR (&PcieMiscInitTable[0],NULL), (sizeof (PcieMiscInitTable) / sizeof (INDIRECT_REG_ENTRY)), pConfig ); //Setup peer-to-peer if (pPcieConfig->PcieConfiguration.Peer2Peer == ON) { if (pPcieConfig->CoreConfiguration[PcieLibGetCoreId (3, pConfig)] == GFX_CONFIG_AABB) { Value = 0x08080404; } else { Value = 0x08080008; } LibNbPciIndexRMW (pConfig->NbPciAddress.AddressValue | NB_MISC_INDEX, NB_MISC_REG49, AccessWidth32, 0, Value, pConfig); if (pPcieConfig->CoreConfiguration[PcieLibGetCoreId (12, pConfig)] == GFX_CONFIG_AABB) { Value = 0xFFFF0404; } else { Value = 0xFFFF0008; } LibNbPciIndexRMW (pConfig->NbPciAddress.AddressValue | NB_MISC_INDEX, NB_MISC_REG2F, AccessWidth32, 0, Value, pConfig); LibNbPciIndexRMW (pConfig->NbPciAddress.AddressValue | NB_MISC_INDEX, NB_MISC_REG48, AccessWidth32, (UINT32)~(BIT8), 0xffff0000, pConfig); } //Remap device number #ifndef DEVICE_REMAP_DISABLE if (PciePortRemapInit (pConfig) != AGESA_SUCCESS ) { REPORT_EVENT (AGESA_ERROR, PCIE_ERROR_DEVICE_REMAP, 0, 0, 0, 0, pConfig); } #endif #ifndef HOTPLUG_SUPPORT_DISABLED ServerHotplugMask = PcieInitHotplug (pConfig); #endif LibNbPciIndexRead (pConfig->NbPciAddress.AddressValue | NB_MISC_INDEX, NB_MISC_REG4A, AccessWidth32, &Value, pConfig); SmuWa = ((Value & BIT21) != 0) ? TRUE : FALSE; if (SmuWa || ServerHotplugMask != 0) { UINT32 BlockIndex; UINT32 SmuWaData; UINT16 Address; UINT32 Data[MCU_CLEAR_BLOCK_LENGTH]; LibNbMcuControl (AssertReset, pConfig); // clear SMU RAM LibAmdMemFill (&Data[0], 0, sizeof (Data), (AMD_CONFIG_PARAMS *)&(pConfig->sHeader)); for (Address = 0; Address < (16 * 1024); Address = Address + 4 * MCU_CLEAR_BLOCK_LENGTH) { LibNbLoadMcuFirmwareBlock (Address, MCU_CLEAR_BLOCK_LENGTH, &Data[0], pConfig); } //Load SMU firmware for (BlockIndex = 0; BlockIndex < Fm.NumberOfBlock; BlockIndex++) { LibNbLoadMcuFirmwareBlock (Fm.BlockArray[BlockIndex].Address, Fm.BlockArray[BlockIndex].Length, Fm.BlockArray[BlockIndex].Data, pConfig); } if (SmuWa) { SmuWaData = LibHtGetSmuWaData (pConfig); LibNbLoadMcuFirmwareBlock (0xFE70, 0x1, &SmuWaData, pConfig); } SmuWaData = ((SmuWa == TRUE) ? 0x100 : 0x100) | ((ServerHotplugMask != 0) ? 0x1 : 0); LibNbLoadMcuFirmwareBlock (0xFE74, 0x1, &SmuWaData, pConfig); LibNbMcuControl (DeAssertReset, pConfig); } #ifndef HOTPLUG_SUPPORT_DISABLED PcieCheckHotplug (ServerHotplugMask, pConfig); #endif } INDIRECT_REG_ENTRY PcieCoreInitTable[] = { { NB_BIFNB_REG10, (UINT32)~(BIT10 + BIT11 + BIT12), BIT12 }, { NB_BIFNB_REG20, (UINT32)~(BIT8 + BIT9), BIT9 }, { NB_BIFNB_REG02, (UINT32)~(BIT0), BIT0 }, { NB_BIFNB_REG40, (UINT32)~(BIT14 + BIT15), BIT15 }, { NB_BIFNB_REGC2, (UINT32)~(BIT25), BIT25 }, { NB_BIFNB_REGC1, (UINT32)~(BIT0), (BIT0 + BIT1 + BIT2) }, { NB_BIFNB_REG1C, 0x0, (4 << 6) + (4 << 1) + 1 } }; INDIRECT_REG_ENTRY PcieRd790CoreInitTable[] = { { NB_BIFNB_REGC2, (UINT32)~(BIT14), (BIT14) }, { NB_BIFNB_REGC1, (UINT32)~(BIT2), 0x0 }, }; /*----------------------------------------------------------------------------------------*/ /** * Init Core registers * * * * @param[in] CoreId PCI Express Core ID * @param[in] pConfig Northbridge configuration structure pointer. */ VOID PcieLibCommonCoreInit ( IN CORE CoreId, IN AMD_NB_CONFIG *pConfig ) { UINT32 CoreAddress; NB_INFO NbInfo; CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (pConfig), CIMX_NBPCIE_TRACE), "[NBPCIE]PcieLibCommonCoreInit (CoreId = %d) Enter\n", CoreId)); CoreAddress = PcieLibGetCoreAddress (CoreId, pConfig); NbInfo = LibNbGetRevisionInfo (pConfig); LibNbIndirectTableInit ( pConfig->NbPciAddress.AddressValue | NB_BIF_INDEX, CoreAddress, (INDIRECT_REG_ENTRY*)FIX_PTR_ADDR (&PcieCoreInitTable[0],NULL), (sizeof (PcieCoreInitTable) / sizeof (INDIRECT_REG_ENTRY)), pConfig ); if (CoreAddress == SB_CORE) { LibNbPciIndexRMW (pConfig->NbPciAddress.AddressValue | NB_BIF_INDEX, NB_BIFNB_REG10 | CoreAddress, AccessWidth32, (UINT32)~BIT9, BIT9, pConfig); LibNbPciIndexRMW (pConfig->NbPciAddress.AddressValue | NB_HTIU_INDEX, NB_HTIU_REG06, AccessWidth32, (UINT32)~BIT26, BIT26 + BIT1, pConfig); LibNbPciIndexRMW (pConfig->NbPciAddress.AddressValue | NB_BIF_INDEX, NB_BIFNB_REG1C | CoreAddress, AccessWidth32, (UINT32)~BIT0, 0x0, pConfig); } if ( NbInfo.Type < NB_SR5690 ) { LibNbIndirectTableInit ( pConfig->NbPciAddress.AddressValue | NB_BIF_INDEX, CoreAddress, (INDIRECT_REG_ENTRY*)FIX_PTR_ADDR (&PcieRd790CoreInitTable[0], NULL), (sizeof (PcieRd790CoreInitTable) / sizeof (INDIRECT_REG_ENTRY)), pConfig ); } CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (pConfig), CIMX_NBPCIE_TRACE), "[NBPCIE]PcieLibCommonCoreInit Exit\n")); }; /*----------------------------------------------------------------------------------------*/ /** * Init Core after training is completed * * * * @param[in] CoreId PCI Express Core ID * @param[in] pConfig Northbridge configuration structure pointer. * */ VOID PcieLibCoreAfterTrainingInit ( IN CORE CoreId, IN AMD_NB_CONFIG *pConfig ) { UINT32 CoreAddress; PCIE_CONFIG *pPcieConfig; PCI_ADDR ClkPciAddress; pPcieConfig = GET_PCIE_CONFIG_PTR (pConfig); CoreAddress = PcieLibGetCoreAddress (CoreId, pConfig); ClkPciAddress = pConfig->NbPciAddress; ClkPciAddress.Address.Function = 1; LibNbPciIndexRMW (pConfig->NbPciAddress.AddressValue | NB_BIF_INDEX, NB_BIFNB_REG20 | CoreAddress, AccessWidth32, (UINT32)~(BIT9), 0, pConfig); //Save core setting in scratch register LibNbPciIndexWrite ( pConfig->NbPciAddress.AddressValue | NB_BIF_INDEX, NB_BIFNB_REG01 | CoreAddress, AccessWidth32, (UINT32*)&pPcieConfig->CoreSetting[CoreId], pConfig ); //Save general setting in scratch LibNbEnableClkConfig (pConfig); LibNbPciWrite (ClkPciAddress.AddressValue | NB_CLK_REG78, AccessWidth32, &pPcieConfig->PcieConfiguration, pConfig); LibNbDisableClkConfig (pConfig); } INDIRECT_REG_ENTRY PciePortInitTable[] = { { NB_BIFNBP_REG02, (UINT32)~(BIT15), BIT15 }, { NB_BIFNBP_REGA1, (UINT32)~(BIT24 + BIT26), BIT11 }, { NB_BIFNBP_REGB1, 0xffffffff, BIT28 + BIT23 + BIT19 + BIT20 }, { NB_BIFNBP_REGA4, (UINT32)~(BIT0), 0x0 }, { NB_BIFNBP_REGA2, (UINT32)~(BIT13), BIT13 }, { NB_BIFNBP_REGA3, (UINT32)~(BIT9), BIT9 }, { NB_BIFNBP_REGA0, 0xffff000f, 0x6830 }, { NB_BIFNBP_REGC1, 0xfffffff0, 0xC }, { NB_BIFNBP_REG70, (UINT32)~(BIT16 + BIT17 + BIT18), BIT16 + BIT18 } }; /*----------------------------------------------------------------------------------------*/ /** * Init port registers * * * * @param[in] PortId PCI Express Port ID * @param[in] pConfig Northbridge configuration structure pointer. * */ VOID PcieLibCommonPortInit ( IN PORT PortId, IN AMD_NB_CONFIG *pConfig ) { PCI_ADDR Port; PCIE_CONFIG *pPcieConfig; UINT32 PcieSlotCapability; UINT32 CoreAddress; CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (pConfig), CIMX_NBPCIE_TRACE), "[NBPCIE]PcieLibCommonPortInit PortId %d Enter\n", PortId)); Port = PcieLibGetPortPciAddress (PortId, pConfig); CoreAddress = PcieLibGetCoreAddress (PcieLibGetCoreId (PortId, pConfig), pConfig); pPcieConfig = GET_PCIE_CONFIG_PTR (pConfig); LibNbIndirectTableInit ( Port.AddressValue | NB_BIF_INDEX, 0x0, (INDIRECT_REG_ENTRY*)FIX_PTR_ADDR (&PciePortInitTable[0],NULL), (sizeof (PciePortInitTable) / sizeof (INDIRECT_REG_ENTRY)), pConfig ); if (CoreAddress == GPP3a_CORE || CoreAddress == SB_CORE || CoreAddress == GPP3b_CORE) { LibNbPciIndexRMW (Port.AddressValue | NB_BIF_INDEX, NB_BIFNBP_REG70, AccessWidth32, (UINT32)~(BIT16 + BIT17 + BIT18), (BIT17 + BIT18), pConfig); if (CoreAddress == GPP3a_CORE) { LibNbPciIndexRMW (Port.AddressValue | NB_BIF_INDEX, NB_BIFNBP_REGB1, AccessWidth32, (UINT32)~(BIT22), BIT22, pConfig); } } // Set completion timeout LibNbPciRMW (Port.AddressValue | NB_PCIP_REG80, AccessS3SaveWidth8, 0xF0, 0x6, pConfig); //if (CoreAddress != SB_CORE) { // LibNbPciIndexRMW (Port.AddressValue | NB_BIF_INDEX, NB_BIFNBP_REG10, AccessWidth32, (UINT32)~BIT0, 0x0, pConfig); //} //For hotplug ports //if (pPcieConfig->PortConfiguration[PortId].PortHotplug != OFF || // pPcieConfig->PcieConfiguration.DisableHideUnusedPorts == ON || // LibNbGetRevisionInfo (pConfig).Revision == NB_REV_A11) { LibNbPciIndexRMW (Port.AddressValue | NB_BIF_INDEX, NB_BIFNBP_REG20, AccessWidth32, (UINT32)~BIT19, 0x0, pConfig); //} // Enable Immediate ACK if (pPcieConfig->ExtPortConfiguration[PortId].PortL1ImmediateACK == ON) { LibNbPciIndexRMW (Port.AddressValue | NB_BIF_INDEX, NB_BIFNBP_REGA0, AccessWidth32, (UINT32)~BIT23, BIT23, pConfig); } //Set up slot capability PcieSlotCapability = (pPcieConfig->ExtPortConfiguration[PortId].PortPowerLimit << 7) | ((Port.Address.Device | Port.Address.Bus << 5 ) << 19); LibNbPciRMW (Port.AddressValue | NB_PCIP_REG6C, AccessS3SaveWidth32, (UINT32)~((0x3ff << 7) | (0x1fff << 19)), PcieSlotCapability, pConfig); LibNbPciRMW (Port.AddressValue | NB_PCIP_REG5A, AccessS3SaveWidth16, (UINT32)~BIT8, BIT8, pConfig); //Set interrupt pin info LibNbPciRMW (Port.AddressValue | NB_PCIP_REG3D, AccessS3SaveWidth8, 0x0, 0x1, pConfig); CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (pConfig), CIMX_NBPCIE_TRACE), "[NBPCIE]PcieLibCommonPortInit Exit\n")); };