| /* $NoKeywords:$ */ |
| /** |
| * @file |
| * |
| * NB services |
| * |
| * |
| * |
| * @xrefitem bom "File Content Label" "Release Content" |
| * @e project: AGESA |
| * @e sub-project: GNB |
| * @e \$Revision: 84150 $ @e \$Date: 2012-12-12 15:46:25 -0600 (Wed, 12 Dec 2012) $ |
| * |
| */ |
| /* |
| ***************************************************************************** |
| * |
| * Copyright (c) 2008 - 2013, 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 "AGESA.h" |
| #include "Ids.h" |
| #include "amdlib.h" |
| #include "S3SaveState.h" |
| #include "Gnb.h" |
| #include "GnbPcieConfig.h" |
| #include "GnbCommonLib.h" |
| #include "GnbPcieInitLibV1.h" |
| #include "GnbNbInitLibV4.h" |
| #include "GnbRegistersCommonV2.h" |
| #include "heapManager.h" |
| #include "GnbFamServices.h" |
| #include "Filecode.h" |
| #define FILECODE PROC_GNB_MODULES_GNBNBINITLIBV4_GNBNBINITLIBV4_FILECODE |
| /*---------------------------------------------------------------------------------------- |
| * D E F I N I T I O N S A N D M A C R O S |
| *---------------------------------------------------------------------------------------- |
| */ |
| |
| #define SMC_RAM_START_ADDR 0x10000ul |
| |
| /*---------------------------------------------------------------------------------------- |
| * T Y P E D E F S A N D S T R U C T U R E S |
| *---------------------------------------------------------------------------------------- |
| */ |
| |
| typedef struct { |
| GNB_PCI_SCAN_DATA ScanData; |
| GNB_TOPOLOGY_INFO *TopologyInfo; |
| } GNB_TOPOLOGY_INFO_DATA; |
| |
| /*---------------------------------------------------------------------------------------- |
| * 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 |
| *---------------------------------------------------------------------------------------- |
| */ |
| VOID |
| GnbSmuServiceRequestV4S3Script ( |
| IN AMD_CONFIG_PARAMS *StdHeader, |
| IN UINT16 ContextLength, |
| IN VOID *Context |
| ); |
| |
| /*----------------------------------------------------------------------------------------*/ |
| /** |
| * Check a PCIE device to see if it supports phantom functions |
| * |
| * @param[in] Device Device pci address |
| * @param[in] StdHeader Standard configuration header |
| * @return TRUE Current device supports phantom functions |
| */ |
| STATIC BOOLEAN |
| GnbCheckPhantomFuncSupport ( |
| IN PCI_ADDR Device, |
| IN AMD_CONFIG_PARAMS *StdHeader |
| ) |
| { |
| UINT8 PcieCapPtr; |
| UINT32 Value; |
| Value = 0; |
| |
| PcieCapPtr = GnbLibFindPciCapability (Device.AddressValue, PCIE_CAP_ID, StdHeader); |
| if (PcieCapPtr != 0) { |
| GnbLibPciRead (Device.AddressValue | (PcieCapPtr + 4), AccessWidth32, &Value, StdHeader); |
| } |
| return ((Value & (BIT3 | BIT4)) != 0) ? TRUE : FALSE; |
| } |
| |
| /*----------------------------------------------------------------------------------------*/ |
| /** |
| * Evaluate device |
| * |
| * |
| * |
| * @param[in] Device PCI Address |
| * @param[in,out] ScanData Scan configuration data |
| * @retval Scan Status |
| */ |
| |
| SCAN_STATUS |
| STATIC |
| GnbTopologyInfoScanCallback ( |
| IN PCI_ADDR Device, |
| IN OUT GNB_PCI_SCAN_DATA *ScanData |
| ) |
| { |
| SCAN_STATUS ScanStatus; |
| GNB_TOPOLOGY_INFO_DATA *GnbTopologyInfo; |
| PCIE_DEVICE_TYPE DeviceType; |
| ScanStatus = SCAN_SUCCESS; |
| IDS_HDT_CONSOLE (GNB_TRACE, " GnbIommuInfoScanCallback for Device = %d:%d:%d\n", |
| Device.Address.Bus, |
| Device.Address.Device, |
| Device.Address.Function |
| ); |
| GnbTopologyInfo = (GNB_TOPOLOGY_INFO_DATA *)ScanData; |
| ScanStatus = SCAN_SUCCESS; |
| DeviceType = GnbLibGetPcieDeviceType (Device, ScanData->StdHeader); |
| switch (DeviceType) { |
| case PcieDeviceRootComplex: |
| case PcieDeviceDownstreamPort: |
| GnbLibPciScanSecondaryBus (Device, &GnbTopologyInfo->ScanData); |
| break; |
| case PcieDeviceUpstreamPort: |
| GnbLibPciScanSecondaryBus (Device, &GnbTopologyInfo->ScanData); |
| ScanStatus = SCAN_SKIP_FUNCTIONS | SCAN_SKIP_DEVICES | SCAN_SKIP_BUSES; |
| break; |
| case PcieDevicePcieToPcix: |
| GnbTopologyInfo->TopologyInfo->PcieToPciexBridge = TRUE; |
| ScanStatus = SCAN_SKIP_FUNCTIONS | SCAN_SKIP_DEVICES | SCAN_SKIP_BUSES; |
| break; |
| case PcieDeviceEndPoint: |
| case PcieDeviceLegacyEndPoint: |
| if (GnbCheckPhantomFuncSupport (Device, ScanData->StdHeader)) { |
| GnbTopologyInfo->TopologyInfo->PhantomFunction = TRUE; |
| } |
| ScanStatus = SCAN_SKIP_DEVICES | SCAN_SKIP_BUSES; |
| break; |
| default: |
| break; |
| } |
| return ScanStatus; |
| } |
| |
| /*----------------------------------------------------------------------------------------*/ |
| /** |
| * Get IOMMU topology info |
| * |
| * |
| * |
| * @param[in] StartPciAddress Start PCI address |
| * @param[in] EndPciAddress End PCI address |
| * @param[in] TopologyInfo Topology info structure |
| * @param[in] StdHeader Standard Configuration Header |
| */ |
| |
| AGESA_STATUS |
| GnbGetTopologyInfoV4 ( |
| IN PCI_ADDR StartPciAddress, |
| IN PCI_ADDR EndPciAddress, |
| OUT GNB_TOPOLOGY_INFO *TopologyInfo, |
| IN AMD_CONFIG_PARAMS *StdHeader |
| ) |
| { |
| GNB_TOPOLOGY_INFO_DATA GnbTopologyInfo; |
| IDS_HDT_CONSOLE (GNB_TRACE, "GnbGetTopologyInfoV4 Enter\n"); |
| GnbTopologyInfo.ScanData.GnbScanCallback = GnbTopologyInfoScanCallback; |
| GnbTopologyInfo.ScanData.StdHeader = StdHeader; |
| GnbTopologyInfo.TopologyInfo = TopologyInfo; |
| GnbLibPciScan (StartPciAddress, EndPciAddress, &GnbTopologyInfo.ScanData); |
| IDS_HDT_CONSOLE (GNB_TRACE, "GnbGetTopologyInfoV4 Exit\n"); |
| return AGESA_SUCCESS; |
| } |
| |
| |
| |
| /*----------------------------------------------------------------------------------------*/ |
| /*----------------------------------------------------------------------------------------*/ |
| /** |
| * SMU firmware download |
| * |
| * |
| * @param[in] GnbPciAddress GNB Pci Address |
| * @param[in] Firmware Pointer tp firmware |
| * @param[in] StdHeader Standard configuration header |
| */ |
| |
| |
| /*----------------------------------------------------------------------------------------*/ |
| /** |
| * Get IOMMU PCI address |
| * |
| * |
| * @param[in] GnbHandle GNB handle |
| * @param[in] StdHeader Standard configuration header |
| */ |
| |
| PCI_ADDR |
| GnbGetIommuPciAddressV4 ( |
| IN GNB_HANDLE *GnbHandle, |
| IN AMD_CONFIG_PARAMS *StdHeader |
| ) |
| { |
| PCI_ADDR GnbIommuPciAddress; |
| GnbIommuPciAddress = GnbGetHostPciAddress (GnbHandle); |
| GnbIommuPciAddress.Address.Function = 0x2; |
| return GnbIommuPciAddress; |
| } |
| |
| |
| /*----------------------------------------------------------------------------------------*/ |
| /** |
| * UnitID Clumping |
| * |
| * |
| * @param[in] GnbHandle GNB handle |
| * @param[in] StdHeader Standard configuration header |
| */ |
| |
| VOID |
| GnbClumpUnitIdV4 ( |
| IN GNB_HANDLE *GnbHandle, |
| IN AMD_CONFIG_PARAMS *StdHeader |
| ) |
| { |
| |
| PCIe_ENGINE_CONFIG *EngineList; |
| UINT32 Value; |
| |
| Value = 0; |
| EngineList = (PCIe_ENGINE_CONFIG *) PcieConfigGetChild (DESCRIPTOR_PCIE_ENGINE, &GnbHandle->Header); |
| while (EngineList != NULL) { |
| if (EngineList->Type.Port.NumberOfUnitId != 0) { |
| if (!PcieConfigIsActivePcieEngine (EngineList)) { |
| Value |= (((1 << EngineList->Type.Port.NumberOfUnitId) - 1) << EngineList->Type.Port.UnitId); |
| } else { |
| if (EngineList->Type.Port.NumberOfUnitId > 1) { |
| Value |= (((1 << (EngineList->Type.Port.NumberOfUnitId - 1)) - 1) << (EngineList->Type.Port.UnitId + 1)); |
| } |
| } |
| } |
| EngineList = (PCIe_ENGINE_CONFIG *) PcieConfigGetNextTopologyDescriptor (EngineList, DESCRIPTOR_TERMINATE_GNB); |
| } |
| // Set GNB |
| GnbLibPciIndirectRMW ( |
| GnbHandle->Address.AddressValue | D0F0x94_ADDRESS, |
| D0F0x98_x3A_ADDRESS, |
| AccessS3SaveWidth32, |
| (UINT32) ~Value, |
| Value, |
| StdHeader |
| ); |
| //Set UNB |
| GnbLibPciRMW ( |
| MAKE_SBDFO (0, 0, GnbHandle->NodeId + 0x18, 0, D18F0x110_ADDRESS + GnbHandle->LinkId * 4), |
| AccessS3SaveWidth32, |
| (UINT32) ~Value, |
| Value, |
| StdHeader |
| ); |
| } |
| |
| |
| |
| /*----------------------------------------------------------------------------------------*/ |
| /** |
| * Config GNB to prevent LPC deadlock scenario |
| * |
| * |
| * @param[in] GnbHandle GNB handle |
| * @param[in] StdHeader Standard configuration header |
| */ |
| |
| VOID |
| GnbLpcDmaDeadlockPreventionV4 ( |
| IN GNB_HANDLE *GnbHandle, |
| IN AMD_CONFIG_PARAMS *StdHeader |
| ) |
| { |
| PCIe_PLATFORM_CONFIG *Pcie; |
| PCIe_ENGINE_CONFIG *EngineList; |
| |
| Pcie = (PCIe_PLATFORM_CONFIG *) PcieConfigGetParent (DESCRIPTOR_PLATFORM, &GnbHandle->Header); |
| EngineList = (PCIe_ENGINE_CONFIG *) PcieConfigGetChild (DESCRIPTOR_ALL_ENGINES, &GnbHandle->Header); |
| while (EngineList != NULL) { |
| if (PcieConfigIsPcieEngine (EngineList) && PcieConfigIsSbPcieEngine (EngineList)) { |
| PcieRegisterRMW ( |
| PcieConfigGetParentWrapper (EngineList), |
| CORE_SPACE (EngineList->Type.Port.CoreId, D0F0xE4_CORE_0010_ADDRESS), |
| D0F0xE4_CORE_0010_UmiNpMemWrite_MASK, |
| 1 << D0F0xE4_CORE_0010_UmiNpMemWrite_OFFSET, |
| TRUE, |
| Pcie |
| ); |
| //Enable special NP memory write protocol in ORB |
| GnbLibPciIndirectRMW ( |
| GnbHandle->Address.AddressValue | D0F0x94_ADDRESS, |
| D0F0x98_x06_ADDRESS, |
| AccessS3SaveWidth32, |
| 0xFFFFFFFF, |
| 1 << D0F0x98_x06_UmiNpMemWrEn_OFFSET, |
| StdHeader |
| ); |
| break; |
| } |
| EngineList = (PCIe_ENGINE_CONFIG *) PcieConfigGetNextTopologyDescriptor (EngineList, DESCRIPTOR_TERMINATE_GNB); |
| } |
| } |
| |
| /*----------------------------------------------------------------------------------------*/ |
| /** |
| * Enable IOMMU base address. (MMIO space ) |
| * |
| * |
| * @param[in] GnbHandle GNB handle |
| * @param[in] StdHeader Standard Configuration Header |
| * @retval AGESA_SUCCESS |
| * @retval AGESA_ERROR |
| */ |
| |
| AGESA_STATUS |
| GnbEnableIommuMmioV4 ( |
| IN GNB_HANDLE *GnbHandle, |
| IN AMD_CONFIG_PARAMS *StdHeader |
| ) |
| { |
| AGESA_STATUS Status; |
| UINT16 CapabilityOffset; |
| UINT64 BaseAddress; |
| UINT32 Value; |
| PCI_ADDR GnbIommuPciAddress; |
| |
| Status = AGESA_SUCCESS; |
| IDS_HDT_CONSOLE (GNB_TRACE, "GnbEnableIommuMmio Enter\n"); |
| |
| if (GnbFmCheckIommuPresent (GnbHandle, StdHeader)) { |
| GnbIommuPciAddress = GnbGetIommuPciAddressV4 (GnbHandle, StdHeader); |
| CapabilityOffset = GnbLibFindPciCapability (GnbIommuPciAddress.AddressValue, IOMMU_CAP_ID, StdHeader); |
| |
| GnbLibPciRead (GnbIommuPciAddress.AddressValue | (CapabilityOffset + 0x4), AccessWidth32, &Value, StdHeader); |
| BaseAddress = (UINT64) Value << 32; |
| GnbLibPciRead (GnbIommuPciAddress.AddressValue | (CapabilityOffset + 0x8), AccessWidth32, &Value, StdHeader); |
| BaseAddress |= Value; |
| |
| if ((BaseAddress & 0xfffffffffffffffe) != 0x0) { |
| IDS_HDT_CONSOLE (GNB_TRACE, " Enable IOMMU MMIO at address %x for Socket %d Silicon %d\n", BaseAddress, GnbGetSocketId (GnbHandle) , GnbGetSiliconId (GnbHandle)); |
| GnbLibPciRMW (GnbIommuPciAddress.AddressValue | (CapabilityOffset + 0x8), AccessS3SaveWidth32, 0xFFFFFFFF, 0x0, StdHeader); |
| GnbLibPciRMW (GnbIommuPciAddress.AddressValue | (CapabilityOffset + 0x4), AccessS3SaveWidth32, 0xFFFFFFFE, 0x1, StdHeader); |
| } else { |
| ASSERT (FALSE); |
| Status = AGESA_ERROR; |
| } |
| } |
| |
| IDS_HDT_CONSOLE (GNB_TRACE, "GnbEnableIommuMmio Exit\n"); |
| return Status; |
| } |
| |