diff options
Diffstat (limited to 'src/vendorcode/amd/cimx/rd890/nbPcieLateHwLib.c')
-rw-r--r-- | src/vendorcode/amd/cimx/rd890/nbPcieLateHwLib.c | 486 |
1 files changed, 486 insertions, 0 deletions
diff --git a/src/vendorcode/amd/cimx/rd890/nbPcieLateHwLib.c b/src/vendorcode/amd/cimx/rd890/nbPcieLateHwLib.c new file mode 100644 index 0000000000..8b1782e7bb --- /dev/null +++ b/src/vendorcode/amd/cimx/rd890/nbPcieLateHwLib.c @@ -0,0 +1,486 @@ +/** + * @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" + +/*---------------------------------------------------------------------------------------- + * 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 + *---------------------------------------------------------------------------------------- + */ + + + +/*----------------------------------------------------------------------------------------*/ +/** + * Misc Initialization in late init + * + * + * + * @param[in] pConfig Northbridge configuration structure pointer. + * + */ + +VOID +PcieLibLateInit ( + IN AMD_NB_CONFIG *pConfig + ) +{ + CORE CoreId; + PORT PortId; + PCIE_CONFIG *pPcieConfig; + PCI_ADDR ClkPciAddress; + + pPcieConfig = GET_PCIE_CONFIG_PTR (pConfig); + ClkPciAddress = pConfig->NbPciAddress; + ClkPciAddress.Address.Function = 1; + //Restore general setting in scratch + LibNbEnableClkConfig (pConfig); + LibNbPciRead (ClkPciAddress.AddressValue | NB_CLK_REG78, AccessWidth32, &pPcieConfig->PcieConfiguration, pConfig); + LibNbDisableClkConfig (pConfig); + // Restore Core setting from scratch + for (CoreId = 0; CoreId <= MAX_CORE_ID; CoreId++) { +// if (PcieLibIsCoreAccessible (CoreId, pConfig) && pPcieConfig->CoreSetting[CoreId].CoreDisabled != ON ) { + UINT32 CoreAddress; + CoreAddress = PcieLibGetCoreAddress (CoreId, pConfig); + LibNbPciIndexRead ( + pConfig->NbPciAddress.AddressValue | NB_BIF_INDEX, + NB_BIFNB_REG01 | CoreAddress, + AccessWidth32, + (UINT32*)&pPcieConfig->CoreSetting[CoreId], + pConfig + ); +// } else { +// pPcieConfig->CoreSetting[CoreId].CoreDisabled = ON; +// } +// CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (pConfig), CIMX_NBPCIE_TRACE), " Recover Core Setting CoreId %d Setting %x Enter\n", CoreId, (UINT32)(pPcieConfig->CoreSetting[CoreId]))); + } + // Restore port Setting from scratch + for (PortId = MIN_PORT_ID; PortId <= MAX_PORT_ID; PortId++) { + if (PcieLibIsValidPortId (PortId, pConfig)) { + PCI_ADDR Port; + Port = PcieLibGetPortPciAddress (PortId, pConfig); + //Reload port configuration from scratch register + LibNbPciIndexRead ( + Port.AddressValue | NB_BIF_INDEX, + NB_BIFNBP_REG01, + AccessWidth32, + (UINT32*)&pPcieConfig->PortConfiguration[PortId], + pConfig + ); + LibNbPciRead (Port.AddressValue | NB_PCIP_REG108, AccessWidth32, (UINT32*)&pPcieConfig->ExtPortConfiguration[PortId], pConfig); +// CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (pConfig), CIMX_NBPCIE_TRACE), " Recover Port setting PortId %d Setting %x Enter\n", PortId, (UINT32)(pPcieConfig->PortConfiguration[PortId]))); + } else { + *((UINT32*)&pPcieConfig->ExtPortConfiguration[PortId]) = 0; + *((UINT32*)&pPcieConfig->PortConfiguration[PortId]) = 0; + } + } +} + +/*----------------------------------------------------------------------------------------*/ +/** + * Misc Initialization in validate port state + * + * + * + * @param[in] pConfig Northbridge configuration structure pointer. + * + */ + +VOID +PcieLibValidatePortStateInit ( + IN AMD_NB_CONFIG *pConfig + ) +{ + CORE CoreId; + PORT PortId; + UINT32 PortAlwaysVisible; + UINT32 ForcePortDisable; + PCIE_CONFIG *pPcieConfig; + PCI_ADDR ClkPciAddress; + + pPcieConfig = GET_PCIE_CONFIG_PTR (pConfig); + ClkPciAddress = pConfig->NbPciAddress; + ClkPciAddress.Address.Function = 1; + //Restore general setting in scratch + LibNbEnableClkConfig (pConfig); + LibNbPciRead (ClkPciAddress.AddressValue | NB_CLK_REG78, AccessWidth32, &pPcieConfig->PcieConfiguration, pConfig); + LibNbDisableClkConfig (pConfig); + // Restore Core setting from scratch + for (CoreId = 0; CoreId <= MAX_CORE_ID; CoreId++) { +// if (PcieLibIsCoreAccessible (CoreId, pConfig) && pPcieConfig->CoreSetting[CoreId].CoreDisabled != ON ) { + UINT32 CoreAddress; + CoreAddress = PcieLibGetCoreAddress (CoreId, pConfig); + LibNbPciIndexRead ( + pConfig->NbPciAddress.AddressValue | NB_BIF_INDEX, + NB_BIFNB_REG01 | CoreAddress, + AccessWidth32, + (UINT32*)&pPcieConfig->CoreSetting[CoreId], + pConfig + ); +// } else { +// pPcieConfig->CoreSetting[CoreId].CoreDisabled = ON; +// } +// CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (pConfig), CIMX_NBPCIE_TRACE), " Recover Core Setting CoreId %d Setting %x Enter\n", CoreId, (UINT32)(pPcieConfig->CoreSetting[CoreId]))); + } + // Restore port Setting from scratch + for (PortId = MIN_PORT_ID; PortId <= MAX_PORT_ID; PortId++) { + if (PcieLibIsValidPortId (PortId, pConfig)) { + PCI_ADDR Port; + Port = PcieLibGetPortPciAddress (PortId, pConfig); + PortAlwaysVisible = pPcieConfig->PortConfiguration[PortId].PortAlwaysVisible; + ForcePortDisable = pPcieConfig->PortConfiguration[PortId].ForcePortDisable; + //Reload port configuration from scratch register + LibNbPciIndexRead ( + Port.AddressValue | NB_BIF_INDEX, + NB_BIFNBP_REG01, + AccessWidth32, + (UINT32*)&pPcieConfig->PortConfiguration[PortId], + pConfig + ); + pPcieConfig->PortConfiguration[PortId].PortAlwaysVisible = PortAlwaysVisible; + pPcieConfig->PortConfiguration[PortId].ForcePortDisable = ForcePortDisable; + LibNbPciRead (Port.AddressValue | NB_PCIP_REG108, AccessWidth32, (UINT32*)&pPcieConfig->ExtPortConfiguration[PortId], pConfig); +// CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (pConfig), CIMX_NBPCIE_TRACE), " Recover Port setting PortId %d Setting %x Enter\n", PortId, (UINT32)(pPcieConfig->PortConfiguration[PortId]))); + } else { + *((UINT32*)&pPcieConfig->ExtPortConfiguration[PortId]) = 0; + *((UINT32*)&pPcieConfig->PortConfiguration[PortId]) = 0; + } + } +} + +/*----------------------------------------------------------------------------------------*/ +/** + * Enable LCLK clock gating or shutdown LCLK clock banch if possible + * + * + * + * @param[in] CoreId PCI Express Core ID + * @param[in] pConfig Northbridge configuration structure pointer. + * + */ +VOID +PcieLibManageLclkClock ( + IN CORE CoreId, + IN AMD_NB_CONFIG *pConfig + ) +{ + UINT32 Value; + UINT32 Mask; + PCI_ADDR ClkPciAddress; + UINT32 CoreAddress; + PCIE_CONFIG *pPcieConfig; + + CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (pConfig), CIMX_NBPCIE_TRACE), "[NBPCIE]PcieLibManageLclkClock [CoreId %d] Enter \n", CoreId)); + pPcieConfig = GET_PCIE_CONFIG_PTR (pConfig); + CoreAddress = PcieLibGetCoreAddress (CoreId, pConfig); + ClkPciAddress = pConfig->NbPciAddress; + ClkPciAddress.Address.Function = 1; + LibNbEnableClkConfig (pConfig); + + if (pPcieConfig->CoreSetting[CoreId].LclkClockGating == ON) { + ClkPciAddress.Address.Register = NB_CLK_REGE8; + Value = 0; + Mask = 0; + switch (CoreAddress) { + case GPP1_CORE: + ClkPciAddress.Address.Register = NB_CLK_REG94; + Mask = BIT16; + break; + case GPP2_CORE: + Value = BIT28; + break; + case GPP3a_CORE: + Value = BIT31; + break; + case GPP3b_CORE: + Value = BIT25; + break; + case SB_CORE: + ClkPciAddress.Address.Register = NB_CLK_REG94; + Mask = BIT24; + break; + default: + CIMX_ASSERT (FALSE); + } + LibNbPciRMW (ClkPciAddress.AddressValue, AccessS3SaveWidth32, ~Mask, Value, pConfig); + } + if (pPcieConfig->CoreSetting[CoreId].LclkClockOff == ON) { + UINT8 ActiveCoreMap; + ActiveCoreMap = PcieLibGetActiveCoreMap (pConfig); + if ((ActiveCoreMap & (1 << CoreId)) == 0) { + //Core not active we can shutdown LCLK permanantly + CORE_INFO *pCoreInfo; + CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (pConfig), CIMX_NBPCIE_TRACE), " Shutdown LCKL clock\n")); + pCoreInfo = PcieLibGetCoreInfo (CoreId, pConfig); + ClkPciAddress.Address.Register = NB_CLK_REGE0; + pPcieConfig->CoreSetting[CoreId].CoreDisableStatus = ON; + // We have to setup Index for BIFNB to point out to SB core. After this point core registers no longer accesasable + LibNbPciIndexRMW (pConfig->NbPciAddress.AddressValue | NB_BIF_INDEX, 0x00 | SB_CORE, AccessS3SaveWidth32, 0xffffffff, 0x00, pConfig); + LibNbPciRMW (ClkPciAddress.AddressValue, AccessS3SaveWidth32, 0xffffffff, 1 << pCoreInfo->LclkOffOffset, pConfig); + + Value = 0; + if (CoreAddress == GPP1_CORE) { + if ((ActiveCoreMap & 0xb) == 0 && !LibNbIsIommuEnabled (pConfig)) { + // Can shutdown master core + Value = 1 << pCoreInfo->LclkPermOffOffset; + } + } else { + Value = 1 << pCoreInfo->LclkPermOffOffset; + } + if (Value != 0) { + NbIommuDisconnectPcieCore (CoreId, pConfig); + LibNbPciIndexRMW (pConfig->NbPciAddress.AddressValue | NB_MISC_INDEX, NB_MISC_REG27, AccessS3SaveWidth32, 0xffffffff, Value, pConfig); + + } + } + } + LibNbDisableClkConfig (pConfig); +} + +/*----------------------------------------------------------------------------------------*/ +/** + * Power Off Pll for unused lanes. + * + * + * + * @param[in] CoreId PCI Express Core ID + * @param[in] pConfig Northbridge configuration structure pointer. + */ +VOID +PcieLibPowerOffPll ( + IN CORE CoreId, + IN AMD_NB_CONFIG *pConfig + ) +{ + PCIE_CONFIG *pPcieConfig; + UINT32 CoreAddress; + UINT32 PowerOfPllValue; + UINT32 PadsMap; + //UINT32 TxClockOffValue; + UINT32 PowerOfPllRegister; + + pPcieConfig = GET_PCIE_CONFIG_PTR (pConfig); + CoreAddress = PcieLibGetCoreAddress (CoreId, pConfig); + PowerOfPllValue = 0; + PadsMap = 0; + //TxClockOffValue = 0; + PowerOfPllRegister = NB_MISC_REG23; + + LibNbPciIndexRead (pConfig->NbPciAddress.AddressValue | NB_BIF_INDEX, NB_BIFNB_REG65 | CoreAddress, AccessS3SaveWidth32, &PadsMap, pConfig); + if (CoreAddress == GPP1_CORE || CoreAddress == GPP2_CORE) { + if ((PadsMap & 0xf0) == 0xf0) { + //Power Off PLL1 + PowerOfPllValue |= (BIT1 | BIT3); + if ((PadsMap & 0x0f) == 0x0f && pPcieConfig->CoreConfiguration[CoreId] != GFX_CONFIG_AABB) { + //Power Off PLL0 + PowerOfPllValue |= (BIT0 | BIT2); + } + } + if (CoreAddress == GPP2_CORE) { + PowerOfPllValue <<= 8; + //TxClockOffValue = BIT1; + } else { + //TxClockOffValue = BIT0; + } + if ((UINT16)PadsMap != 0xffff) { + //TxClockOffValue = 0; //Do not disable TX clock in case any line is ON + } + } + if (CoreAddress == GPP3a_CORE ) { + if ((UINT16)PadsMap == 0x3F3F) { + PowerOfPllValue = BIT18 | BIT16; + //TxClockOffValue = BIT2; + } + } + if (CoreAddress == GPP3b_CORE ) { + PowerOfPllRegister = NB_MISC_REG2E; + if ((UINT16)PadsMap == 0x0F0F) { + PowerOfPllValue = BIT8 | BIT6; + //TxClockOffValue = BIT3; + } + } + //Power Off Pll + LibNbPciIndexRMW (pConfig->NbPciAddress.AddressValue | NB_MISC_INDEX, PowerOfPllRegister , AccessS3SaveWidth32, 0xffffffff, PowerOfPllValue, pConfig); + CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (pConfig), CIMX_NBPCIE_TRACE), " Power off PLL CoreId %d, Value 0x%x\n", CoreId, PowerOfPllValue)); + //Turn off TXCLK + //LibNbPciIndexRMW (pConfig->NbPciAddress.AddressValue | NB_MISC_INDEX, NB_MISC_REG07, AccessS3SaveWidth32, 0xffffffff, TxClockOffValue, pConfig); +} + + +/*----------------------------------------------------------------------------------------*/ +/** + * Enable TX clock gating or shutdown TX clock if possible + * + * + * + * @param[in] CoreId PCI Express Core ID + * @param[in] pConfig Northbridge configuration structure pointer. * + */ +VOID +PcieLibManageTxClock ( + IN CORE CoreId, + IN AMD_NB_CONFIG *pConfig + ) +{ + PCIE_CONFIG *pPcieConfig; + UINT32 CoreAddress; + UINT32 Value; + pPcieConfig = GET_PCIE_CONFIG_PTR (pConfig); + CoreAddress = PcieLibGetCoreAddress (CoreId, pConfig); + if (pPcieConfig->CoreSetting[CoreId].TxClockGating == ON) { + switch (CoreAddress) { + case GPP1_CORE: + Value = BIT4; + break; + case GPP2_CORE: + Value = BIT5; + break; + case GPP3a_CORE: + Value = BIT6; + break; + case GPP3b_CORE: + Value = BIT24; + break; + case SB_CORE: + Value = BIT7; + break; + default: + Value = 0; + CIMX_ASSERT (FALSE); + } + LibNbPciIndexRMW (pConfig->NbPciAddress.AddressValue | NB_MISC_INDEX, NB_MISC_REG07, AccessS3SaveWidth32, 0xffffffff, Value, pConfig); + LibNbPciIndexRMW (pConfig->NbPciAddress.AddressValue | NB_BIF_INDEX, NB_BIFNB_REG40 | CoreAddress, AccessS3SaveWidth32, (UINT32)~BIT6, BIT6, pConfig); + LibNbPciIndexRMW (pConfig->NbPciAddress.AddressValue | NB_BIF_INDEX, NB_BIFNB_REG11 | CoreAddress, AccessS3SaveWidth32, 0xfffffff0, 0x0C, pConfig); + } + if (pPcieConfig->CoreSetting[CoreId].TxClockOff == ON) { + UINT8 ActiveCoreMap; + ActiveCoreMap = PcieLibGetActiveCoreMap (pConfig); + if ((ActiveCoreMap & (1 << CoreId)) == 0) { + //Core not active we can shutdown TX clk permanantly + CORE_INFO *pCoreInfo; + CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (pConfig), CIMX_NBPCIE_TRACE), " Shutdown TX clock\n")); + pPcieConfig->CoreSetting[CoreId].CoreDisableStatus = ON; + pCoreInfo = PcieLibGetCoreInfo (CoreId, pConfig); + LibNbPciIndexRMW (pConfig->NbPciAddress.AddressValue | NB_MISC_INDEX, NB_MISC_REG07, AccessS3SaveWidth32, 0xffffffff, 1 << pCoreInfo->TxOffOffset, pConfig); + } + } +} + +/*----------------------------------------------------------------------------------------*/ +/** + * Enable Pll Power Down in L1. + * + * + * + * @param[in] CoreId PCI Express Core ID + * @param[in] pConfig Northbridge configuration structure pointer. * + */ +VOID +PcieLibEnablePllPowerOffInL1 ( + IN CORE CoreId, + IN AMD_NB_CONFIG *pConfig + ) +{ + PCIE_CONFIG *pPcieConfig; + UINT32 Value; + UINT32 CoreAddress; + PORT PortId; + pPcieConfig = GET_PCIE_CONFIG_PTR (pConfig); + if (pPcieConfig->CoreSetting[CoreId].DetectPowerOffPllInL1 == ON && !PciePllOffComatibilityTest (CoreId, pConfig)) { + return; + } + for (PortId = MIN_PORT_ID; PortId <= MAX_PORT_ID; PortId++) { + if (PcieLibIsValidPortId (PortId, pConfig) && PcieLibGetCoreId (PortId, pConfig) == CoreId) { + if (pPcieConfig->PortConfiguration[PortId].PortHotplug != OFF) { + // set up max exit latency requirment for hotplug ports + PCI_ADDR Port; + Port = PcieLibGetPortPciAddress (PortId, pConfig); + LibNbPciIndexRMW (Port.AddressValue | NB_BIF_INDEX, NB_BIFNBP_REGC1 , AccessS3SaveWidth32, 0xffffffff, 0xf, pConfig); + } + } + } + CoreAddress = PcieLibGetCoreAddress (CoreId, pConfig); + Value = BIT8; + LibNbPciIndexRMW (pConfig->NbPciAddress.AddressValue | NB_BIF_INDEX, NB_BIFNB_REG40 | CoreAddress, AccessS3SaveWidth32, (UINT32)~(BIT9 + BIT4), BIT3 + BIT0 + BIT12, pConfig); + if (CoreAddress == GPP3b_CORE || CoreAddress == GPP3a_CORE || CoreAddress == SB_CORE) { + Value |= BIT3; + } + LibNbPciIndexRMW (pConfig->NbPciAddress.AddressValue | NB_BIF_INDEX, NB_BIFNB_REG02 | CoreAddress, AccessS3SaveWidth32, 0xffffffff, Value, pConfig); +} + +/*----------------------------------------------------------------------------------------*/ +/** + * Misc. core setting. + * + * + * + * @param[in] CoreId PCI Express- Core ID + * @param[in] pConfig Northbridge configuration structure pointer. + */ +VOID +PcieLibMiscLateCoreSetting ( + IN CORE CoreId, + IN AMD_NB_CONFIG *pConfig + ) +{ +//Lock + LibNbPciIndexRMW ( + pConfig->NbPciAddress.AddressValue | NB_BIF_INDEX, + NB_BIFNB_REG10 | PcieLibGetCoreAddress (CoreId, pConfig), + AccessS3SaveWidth32, + 0xffffffff, + BIT0, + pConfig + ); +} |