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/nbPcieInitLate.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/nbPcieInitLate.c')
-rw-r--r-- | src/vendorcode/amd/cimx/rd890/nbPcieInitLate.c | 505 |
1 files changed, 505 insertions, 0 deletions
diff --git a/src/vendorcode/amd/cimx/rd890/nbPcieInitLate.c b/src/vendorcode/amd/cimx/rd890/nbPcieInitLate.c new file mode 100644 index 0000000000..17ae4f746b --- /dev/null +++ b/src/vendorcode/amd/cimx/rd890/nbPcieInitLate.c @@ -0,0 +1,505 @@ +/** + * @file + * + * PCIE Late Initialization + * + * + * + * @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 + *---------------------------------------------------------------------------------------- + */ + +/*---------------------------------------------------------------------------------------- + * E X P O R T E D F U N C T I O N S + *---------------------------------------------------------------------------------------- + */ + +/*----------------------------------------------------------------------------------------*/ +/** + * Amd PCIE Late Init for all NB. + * + * + * @param[in] ConfigPtr Northbridges configuration block pointer. + * + */ +AGESA_STATUS +AmdPcieLateInit ( + IN AMD_NB_CONFIG_BLOCK *ConfigPtr + ) +{ + AGESA_STATUS Status; + + Status = LibNbApiCall (PcieLateInit, ConfigPtr); + return Status; +} + +/*----------------------------------------------------------------------------------------*/ +/** + * Amd PCIE Late Init for all NB. + * + * + * @param[in] ConfigPtr Northbridges configuration block pointer. + * + */ +AGESA_STATUS +AmdPcieLateInitWa ( + IN AMD_NB_CONFIG_BLOCK *ConfigPtr + ) +{ + AGESA_STATUS Status; + + Status = LibNbApiCall (PcieLateInitWa, ConfigPtr); + return Status; +} + + +/*----------------------------------------------------------------------------------------*/ +/** + * Amd PCIE Special Init for all NB. + * + * + * @param[in] ConfigPtr Northbridges configuration block pointer. + * + */ +AGESA_STATUS +AmdPcieValidatePortState ( + IN AMD_NB_CONFIG_BLOCK *ConfigPtr + ) +{ + AGESA_STATUS Status; + + Status = LibNbApiCall (PcieValidatePortState, ConfigPtr); + return Status; +} + +/*----------------------------------------------------------------------------------------*/ +/** + * Amd PCIE S3 Init fro all NB. + * + * + * @param[in] ConfigPtr Northbridges configuration block pointer. + * + */ +AGESA_STATUS +AmdPcieS3Init ( + IN AMD_NB_CONFIG_BLOCK *ConfigPtr + ) +{ + AGESA_STATUS Status; + + Status = LibNbApiCall (PcieLateInit, ConfigPtr); + return Status; +} + +/*----------------------------------------------------------------------------------------*/ +/** + * NB PCIE Late Init. + * Extended programming. Enable power management and misc capability. + * Prepare PCIE subsystem to boot to OS. + * + * + * @param[in] NbConfigPtr Northbridge configuration structure pointer. + * + */ +AGESA_STATUS +PcieLateInit ( + IN AMD_NB_CONFIG *NbConfigPtr + ) +{ + AGESA_STATUS Status; + PcieLibUnHidePorts (NbConfigPtr); + Status = PcieLateValidateConfiguration (NbConfigPtr); + if (Status == AGESA_FATAL) { + PcieLibHidePorts (NbConfigPtr); + REPORT_EVENT (AGESA_FATAL, GENERAL_ERROR_BAD_CONFIGURATION, 0, 0, 0, 0, NbConfigPtr); + CIMX_ASSERT (FALSE); + return Status; + } + PcieLibLateInit (NbConfigPtr); + Status = PcieLateInitPorts (NbConfigPtr); + Status = PcieLateInitCores (NbConfigPtr); + PcieLibHidePorts (NbConfigPtr); + return Status; +} + +/*----------------------------------------------------------------------------------------*/ +/** + * NB PCIE Late Init. + * Extended programming. Enable power management and misc capability. + * Prepare PCIE subsystem to boot to OS. + * + * + * @param[in] NbConfigPtr Northbridge configuration structure pointer. + * + */ +AGESA_STATUS +PcieLateInitWa ( + IN AMD_NB_CONFIG *NbConfigPtr + ) +{ + UINT32 Value; + BOOLEAN SmuWa; + LibNbPciIndexRead (NbConfigPtr->NbPciAddress.AddressValue | NB_MISC_INDEX, NB_MISC_REG4A, AccessWidth32, &Value, NbConfigPtr); + SmuWa = ((Value & BIT21) != 0) ? TRUE : FALSE; + if (SmuWa) { + UINT32 SmuWaData; + LibNbMcuControl (AssertReset, NbConfigPtr); + SmuWaData = LibNbReadMcuRam (0xFE74, NbConfigPtr); + SmuWaData &= 0x00ff; + LibNbLoadMcuFirmwareBlock (0xFE74, 0x1, &SmuWaData, NbConfigPtr); + LibNbMcuControl (DeAssertReset, NbConfigPtr); + } + return AGESA_SUCCESS; +} + +/*----------------------------------------------------------------------------------------*/ +/** + * Late init PCIE Ports + * + * + * +* @param[in] NbConfigPtr Northbridge configuration structure pointer. + * + */ +AGESA_STATUS +PcieLateInitPorts ( + IN AMD_NB_CONFIG *NbConfigPtr + ) +{ + AGESA_STATUS Status; + PCIE_CONFIG *pPcieConfig; + PORT PortId; + BOOLEAN IsIommuEnabled; + NB_INFO NbInfo; + CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (NbConfigPtr), CIMX_NBPCIE_TRACE), "[NBPCIE]PcieLateInitPorts Enter\n")); + IsIommuEnabled = LibNbIsIommuEnabled (NbConfigPtr); + NbInfo = LibNbGetRevisionInfo (NbConfigPtr); + pPcieConfig = GET_PCIE_CONFIG_PTR (NbConfigPtr); + Status = AGESA_SUCCESS; + for (PortId = MIN_PORT_ID; PortId <= MAX_PORT_ID; PortId++) { + CORE CoreId; + CoreId = PcieLibGetCoreId (PortId, NbConfigPtr); + if (!PcieLibIsValidCoreId (CoreId, NbConfigPtr)) { + PcieLibPowerOffPortLanes (PortId, PcieLinkWidth_x0, NbConfigPtr); + } else if (PcieLibIsValidPortId (PortId, NbConfigPtr)) { + PCIE_LINK_WIDTH LinkWidth; + PCI_ADDR Port; + LinkWidth = PcieLibGetLinkWidth (PortId, NbConfigPtr); + CoreId = PcieLibGetCoreId (PortId, NbConfigPtr); + Port = PcieLibGetPortPciAddress (PortId, NbConfigPtr); + PcieLateCommonPortInit (PortId, NbConfigPtr); + if (pPcieConfig->PortConfiguration[PortId].PortDetected == ON) { + if (pPcieConfig->PortConfiguration[PortId].PortLinkMode == PcieLinkModeGen2SoftwareInitiated) { + PcieInitiateSoftwareGen2 (PortId, NbConfigPtr); + } + PcieAsmpEnableOnPort (PortId, (UINT8)pPcieConfig->PortConfiguration[PortId].PortAspm, NbConfigPtr); + } + LibNbPciIndexRMW (Port.AddressValue | NB_BIF_INDEX, NB_BIFNBP_REG70 , AccessS3SaveWidth32, (UINT32)~BIT12, 0, NbConfigPtr); //PCIE should not ignore malformed packet error or ATS request + if (pPcieConfig->PortConfiguration[PortId].PortCompliance == OFF && + pPcieConfig->PortConfiguration[PortId].PortHotplug == OFF && + pPcieConfig->CoreSetting[CoreId].PowerOffUnusedLanes == ON) { + PcieLibPowerOffPortLanes (PortId, LinkWidth, NbConfigPtr); + } + } + } + CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (NbConfigPtr), CIMX_NBPCIE_TRACE), "[NBPCIE]PcieLateInitPorts Exit\n")); + return Status; +} + +/*----------------------------------------------------------------------------------------*/ +/** + * Late init PCIE Cores. Core level feature/power management etc. + * + * + * + * @param[in] pConfig Northbridge configuration structure pointer. + * + */ +AGESA_STATUS +PcieLateInitCores ( + IN AMD_NB_CONFIG *pConfig + ) +{ + AGESA_STATUS Status; + PCIE_CONFIG *pPcieConfig; + CORE CoreId; + + CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (pConfig), CIMX_NBPCIE_TRACE), "[NBPCIE]PcieLateInitCores Enter\n")); + Status = AGESA_SUCCESS; + pPcieConfig = GET_PCIE_CONFIG_PTR (pConfig); + for (CoreId = 0; CoreId <= MAX_CORE_ID; CoreId++) { + CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (pConfig), CIMX_NBPCIE_TRACE), " Init CoreId [%d]\n", CoreId)); + if (pPcieConfig->CoreSetting[CoreId].PowerOffPllInL1 == ON) { + PcieLibEnablePllPowerOffInL1 (CoreId, pConfig); + } + if (pPcieConfig->CoreSetting[CoreId].PowerOffPll == ON) { + PcieLibPowerOffPll (CoreId, pConfig); + } + PcieLibMiscLateCoreSetting (CoreId, pConfig); + PcieLibManageTxClock (CoreId, pConfig); + PcieLibManageLclkClock (CoreId, pConfig); + } +#ifndef VC1_SUPPORT_DISABLE + if (NB_SBDFO == 0 && pPcieConfig->PcieConfiguration.NbSbVc1 == ON) { + PcieNbSbSetupVc (pConfig); + } +#endif + CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (pConfig), CIMX_NBPCIE_TRACE), "[NBPCIE]PcieLateInitCores Exit\n")); + return Status; +} + + +/*----------------------------------------------------------------------------------------*/ +/* + * Set up NB-SB virtual channel for audio traffic + * + * + * + * @param[in] pConfig Northbridge configuration structure pointer. + * + */ +VOID +PcieNbSbSetupVc ( + IN AMD_NB_CONFIG *pConfig + ) +{ + UINT32 VCStatus; + PCI_ADDR Port; + + Port = PcieLibGetPortPciAddress (8, pConfig); + if (PcieSbSetupVc (pConfig) == AGESA_SUCCESS) { + LibNbPciRMW (Port.AddressValue | NB_PCIP_REG124, AccessS3SaveWidth8, 0x01, 0, pConfig); + LibNbPciRMW (Port.AddressValue | NB_PCIP_REG130, AccessS3SaveWidth32, (UINT32)~(BIT24 + BIT25 + BIT26), 0xFE + BIT24, pConfig); + LibNbPciRMW (Port.AddressValue | NB_PCIP_REG130, AccessS3SaveWidth32, 0xffffffff, BIT31, pConfig); + do { + STALL (GET_BLOCK_CONFIG_PTR (pConfig), 200, CIMX_S3_SAVE); + LibNbPciRead (Port.AddressValue | NB_PCIP_REG134, AccessWidth32, &VCStatus, pConfig); + } while (VCStatus & BIT17); + PcieSbEnableVc (pConfig); + } +} + + +/*----------------------------------------------------------------------------------------*/ +/* + * Late common Port Init + * + * + * @param[in] PortId Port Id + * @param[in] pConfig Northbridge configuration structure pointer. + * + */ +AGESA_STATUS +PcieLateCommonPortInit ( + IN PORT PortId, + IN AMD_NB_CONFIG *pConfig + ) +{ + AGESA_STATUS Status; + Status = AGESA_SUCCESS; + + return Status; +} + +/*----------------------------------------------------------------------------------------*/ +/* + * Initiate SW Gen2 switch + * + * + * + * @param[in] PortId Port Id. + * @param[in] pConfig Northbridge configuration structure pointer. + * + */ +VOID +PcieInitiateSoftwareGen2 ( + IN PORT PortId, + IN AMD_NB_CONFIG *pConfig + ) +{ + UINT8 LinkSpeedCap; + UINT8 PcieCapPtr; + UINT8 SecondaryBus; + UINT32 Value; + UINT32 Counter; + PCI_ADDR Ep; + PCI_ADDR Port; + + CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (pConfig), CIMX_NBPCIE_TRACE), "[NBPCIE]PcieInitiateSoftwareGen2 PortId[%d] Enter\n", PortId)); + Counter = 5000; + Port = PcieLibGetPortPciAddress (PortId, pConfig); + LibNbPciRead (Port.AddressValue | NB_PCIP_REG19, AccessWidth8, &SecondaryBus, pConfig); + Ep.AddressValue = 0; + Ep.Address.Bus = SecondaryBus; + CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (pConfig), CIMX_NBPCIE_TRACE), "[NBPCIE] SecondaryBus = 0x%x \n", SecondaryBus)); + PcieCapPtr = LibNbFindPciCapability (Ep.AddressValue, PCIE_CAP_ID, pConfig); + LibNbPciRead (Ep.AddressValue | (PcieCapPtr + 0xC), AccessWidth8, &LinkSpeedCap, pConfig); + CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (pConfig), CIMX_NBPCIE_TRACE), "[NBPCIE] PcieCapPtr = 0x%x \n", PcieCapPtr)); + if ((LinkSpeedCap & 0xf) < 2) { + return; + } + PcieLibSetLinkMode (PortId, PcieLinkModeGen2, pConfig); + LibNbPciIndexRMW (Port.AddressValue | NB_BIF_INDEX, NB_BIFNBP_REGA4 , AccessS3SaveWidth32, (UINT32)~(BIT18), BIT18 , pConfig); + do { + STALL (GET_BLOCK_CONFIG_PTR (pConfig), 200, CIMX_S3_SAVE); + LibNbPciIndexRead (Port.AddressValue | NB_PCIP_REGE0, NB_BIFNBP_REGA5, AccessWidth32, &Value, pConfig); + } while ((UINT8)Value != 0x10 && Counter-- != 0); + LibNbPciIndexRead (Port.AddressValue | NB_PCIP_REGE0, NB_BIFNBP_REGA4, AccessWidth32, &Value, pConfig); + if ((Value & BIT24) != 0) { + //Initiate link speed change + LibNbPciIndexRMW (Port.AddressValue | NB_PCIP_REGE0, NB_BIFNBP_REGA4, AccessS3SaveWidth32, ((UINT32)~BIT7), BIT7, pConfig); + } + CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (pConfig), CIMX_NBPCIE_TRACE), "[NBPCIE]PcieInitiateSoftwareGen2 Exit\n")); +} + +/*----------------------------------------------------------------------------------------*/ +/** + * Validate input parameters configuration for PCie Late Init call. + * + * + * + * @param[in] pConfig Northbridge configuration structure pointer. + * + */ +AGESA_STATUS +PcieLateValidateConfiguration ( + IN AMD_NB_CONFIG *pConfig + ) +{ + PCIE_CONFIG *pPcieConfig; + NB_INFO NbInfo; + + CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (pConfig), CIMX_NBPCIE_TRACE), "[NBPCIE]PcieLateValidateConfiguration Enter\n")); + pPcieConfig = GET_PCIE_CONFIG_PTR (pConfig); + NbInfo = LibNbGetRevisionInfo (pConfig); + if (pPcieConfig == NULL) { + REPORT_EVENT (AGESA_FATAL, GENERAL_ERROR_BAD_CONFIGURATION, 0, 0, 0, 0, pConfig); + CIMX_ASSERT (FALSE); + return AGESA_FATAL; + } + if (pPcieConfig->sHeader.InitializerID != INITIALIZED_BY_INITIALIZER) { + PcieLibInitializer (pConfig); + } + CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (pConfig), CIMX_NBPCIE_TRACE), "[NBPCIE]PcieLateValidateConfiguration Exit\n")); + return AGESA_SUCCESS; +} + +/*----------------------------------------------------------------------------------------*/ +/** + * PcieValidatePortState + * Port disable or port visibility control + * + * + * @param[in] NbConfigPtr Northbridge configuration structure pointer. + * + */ +AGESA_STATUS +PcieValidatePortState ( + IN AMD_NB_CONFIG *NbConfigPtr + ) +{ + AGESA_STATUS Status; + + Status = AGESA_SUCCESS; + PcieLibUnHidePorts (NbConfigPtr); + PcieLibValidatePortStateInit (NbConfigPtr); + PcieForcePortsVisibleOrDisable (NbConfigPtr); + PcieLibHidePorts (NbConfigPtr); + return Status; +} + + +/*----------------------------------------------------------------------------------------*/ +/** + * PciePortsVisibleOrDisable + * Set ports always visible or disable based on input parameter + * + * + * +* @param[in] NbConfigPtr Northbridge configuration structure pointer. + * + */ +VOID +PcieForcePortsVisibleOrDisable ( + IN AMD_NB_CONFIG *NbConfigPtr + ) +{ + PCIE_CONFIG *pPcieConfig; + PORT PortId; + PCI_ADDR Port; + + pPcieConfig = GET_PCIE_CONFIG_PTR (NbConfigPtr); + for (PortId = MIN_PORT_ID; PortId <= MAX_PORT_ID; PortId++) { + if (PcieLibIsValidPortId (PortId, NbConfigPtr)) { + Port = PcieLibGetPortPciAddress (PortId, NbConfigPtr); + if (pPcieConfig->PortConfiguration[PortId].ForcePortDisable == ON ) { + pPcieConfig->PortConfiguration[PortId].PortPresent = OFF; + pPcieConfig->PortConfiguration[PortId].PortDetected = OFF; + } + if (pPcieConfig->PortConfiguration[PortId].PortAlwaysVisible == ON) { + LibNbPciIndexRMW (Port.AddressValue | NB_BIF_INDEX, NB_BIFNBP_REG70, AccessWidth32, (UINT32)~BIT19, BIT19, NbConfigPtr); + pPcieConfig->PortConfiguration[PortId].PortPresent = ON; + pPcieConfig->PortConfiguration[PortId].PortDetected = ON; + } + LibNbPciIndexWrite (Port.AddressValue | NB_BIF_INDEX, NB_BIFNBP_REG01, AccessWidth32, (UINT32*)&pPcieConfig->PortConfiguration[PortId], NbConfigPtr); + } + } +} + |