| /* $NoKeywords:$ */ |
| /** |
| * @file |
| * |
| * NB services |
| * |
| * |
| * |
| * @xrefitem bom "File Content Label" "Release Content" |
| * @e project: AGESA |
| * @e sub-project: GNB |
| * @e \$Revision: 64352 $ @e \$Date: 2012-01-19 03:54:04 -0600 (Thu, 19 Jan 2012) $ |
| * |
| */ |
| /* |
| ***************************************************************************** |
| * |
| * Copyright (c) 2008 - 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 "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 "GnbRegistersTN.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 service request |
| * |
| * |
| * @param[in] GnbPciAddress GNB PCI address |
| * @param[in] RequestId Request ID |
| * @param[in] AccessFlags See GNB_ACCESS_FLAGS_* definitions |
| * @param[in] StdHeader Standard configuration header |
| */ |
| |
| VOID |
| GnbSmuServiceRequestV4 ( |
| IN PCI_ADDR GnbPciAddress, |
| IN UINT8 RequestId, |
| IN UINT32 AccessFlags, |
| IN AMD_CONFIG_PARAMS *StdHeader |
| ) |
| { |
| D0F0xBC_xE0003004_STRUCT D0F0xBC_xE0003004; |
| D0F0xBC_xE0003000_STRUCT D0F0xBC_xE0003000; |
| IDS_HDT_CONSOLE (GNB_TRACE, "GnbSmuServiceRequestV4 Enter\n"); |
| IDS_HDT_CONSOLE (NB_MISC, " Service Request %d\n", RequestId); |
| |
| if ((AccessFlags & GNB_REG_ACC_FLAG_S3SAVE) != 0) { |
| SMU_MSG_CONTEXT SmuMsgContext; |
| SmuMsgContext.GnbPciAddress.AddressValue = GnbPciAddress.AddressValue; |
| SmuMsgContext.RequestId = RequestId; |
| S3_SAVE_DISPATCH (StdHeader, GnbSmuServiceRequestV4S3Script_ID, sizeof (SmuMsgContext), &SmuMsgContext); |
| } |
| do { |
| GnbLibPciIndirectRead (GnbPciAddress.AddressValue | D0F0xB8_ADDRESS, D0F0xBC_xE0003004_ADDRESS, AccessWidth32, &D0F0xBC_xE0003004.Value, StdHeader); |
| } while (D0F0xBC_xE0003004.Field.IntDone == 0x0); |
| GnbLibPciIndirectRead (GnbPciAddress.AddressValue | D0F0xB8_ADDRESS, D0F0xBC_xE0003000_ADDRESS, AccessWidth32, &D0F0xBC_xE0003000.Value, StdHeader); |
| D0F0xBC_xE0003000.Field.IntToggle = ~D0F0xBC_xE0003000.Field.IntToggle; |
| D0F0xBC_xE0003000.Field.ServiceIndex = RequestId; |
| GnbLibPciIndirectWrite (GnbPciAddress.AddressValue | D0F0xB8_ADDRESS, D0F0xBC_xE0003000_ADDRESS, AccessWidth32, &D0F0xBC_xE0003000.Value, StdHeader); |
| do { |
| GnbLibPciIndirectRead (GnbPciAddress.AddressValue | D0F0xB8_ADDRESS, D0F0xBC_xE0003004_ADDRESS, AccessWidth32, &D0F0xBC_xE0003004.Value, StdHeader); |
| } while (D0F0xBC_xE0003004.Field.IntAck == 0x0); |
| do { |
| GnbLibPciIndirectRead (GnbPciAddress.AddressValue | D0F0xB8_ADDRESS, D0F0xBC_xE0003004_ADDRESS, AccessWidth32, &D0F0xBC_xE0003004.Value, StdHeader); |
| } while (D0F0xBC_xE0003004.Field.IntDone == 0x0); |
| IDS_HDT_CONSOLE (GNB_TRACE, "GnbSmuServiceRequestV4 Exit\n"); |
| } |
| /*----------------------------------------------------------------------------------------*/ |
| /** |
| * SMU service request for S3 script |
| * |
| * |
| * @param[in] StdHeader Standard configuration header |
| * @param[in] ContextLength Context length |
| * @param[in] Context Pointer to Context |
| */ |
| |
| VOID |
| GnbSmuServiceRequestV4S3Script ( |
| IN AMD_CONFIG_PARAMS *StdHeader, |
| IN UINT16 ContextLength, |
| IN VOID *Context |
| ) |
| { |
| SMU_MSG_CONTEXT *SmuMsgContext; |
| SmuMsgContext = (SMU_MSG_CONTEXT *) Context; |
| GnbSmuServiceRequestV4 (SmuMsgContext->GnbPciAddress, SmuMsgContext->RequestId, 0, StdHeader); |
| } |
| |
| /*----------------------------------------------------------------------------------------*/ |
| /** |
| * SMU firmware download |
| * |
| * |
| * @param[in] GnbPciAddress GNB Pci Address |
| * @param[in] Firmware Pointer tp firmware |
| * @param[in] StdHeader Standard configuration header |
| */ |
| |
| AGESA_STATUS |
| GnbSmuFirmwareLoadV4 ( |
| IN PCI_ADDR GnbPciAddress, |
| IN FIRMWARE_HEADER_V4 *Firmware, |
| IN AMD_CONFIG_PARAMS *StdHeader |
| ) |
| { |
| |
| UINT32 Index; |
| D0F0xBC_xE00030A4_STRUCT D0F0xBC_xE00030A4; |
| D0F0xBC_xE0000004_STRUCT D0F0xBC_xE0000004; |
| D0F0xBC_xE0003088_STRUCT D0F0xBC_xE0003088; |
| ex1005_STRUCT ex1005 ; |
| D0F0xBC_x1F380_STRUCT D0F0xBC_x1F380; |
| IDS_HDT_CONSOLE (GNB_TRACE, "GnbSmuFirmwareLoadV4 Enter\n"); |
| IDS_HDT_CONSOLE (NB_MISC, " Firmware version 0x%x\n", Firmware->Version); |
| // Step 2, 10, make sure Rom firmware sequance is done |
| do { |
| GnbLibPciIndirectRead (GnbPciAddress.AddressValue | D0F0xB8_ADDRESS, D0F0xBC_xE0000004_ADDRESS, AccessWidth32, &D0F0xBC_xE0000004.Value, StdHeader); |
| } while (D0F0xBC_xE0000004.Field.boot_seq_done == 0); |
| // Step 1, check if firmware running in protected mode |
| GnbLibPciIndirectRead (GnbPciAddress.AddressValue | D0F0xB8_ADDRESS, D0F0xBC_xE00030A4_ADDRESS, AccessWidth32, &D0F0xBC_xE00030A4.Value, StdHeader); |
| if (D0F0xBC_xE00030A4.Field.SmuProtectedMode == 0) { |
| // Step3, Clear firmware interrupt flags |
| GnbLibPciIndirectRMW ( |
| GnbPciAddress.AddressValue | D0F0xB8_ADDRESS, |
| D0F0xBC_x1F380_ADDRESS, |
| AccessWidth32, |
| 0x0, |
| 0x0, |
| StdHeader |
| ); |
| } |
| //Step 4, 11, Assert LM32 reset |
| GnbLibPciIndirectRMW ( |
| GnbPciAddress.AddressValue | D0F0xB8_ADDRESS, |
| 0x80000000 , |
| AccessWidth32, |
| (UINT32) ~(0x1 ), |
| 1 << 0 , |
| StdHeader |
| ); |
| // Step5, 12, Load firmware |
| for (Index = 0; Index < (Firmware->FirmwareLength + Firmware->HeaderLength); Index++) { |
| GnbLibPciIndirectWrite (GnbPciAddress.AddressValue | D0F0xB8_ADDRESS, SMC_RAM_START_ADDR + (Index * 4), AccessWidth32, &((UINT32 *) Firmware)[Index], StdHeader); |
| } |
| if (D0F0xBC_xE00030A4.Field.SmuProtectedMode == 0) { |
| //Step 6, Write jmp to RAM firmware |
| GnbLibPciIndirectRMW ( |
| GnbPciAddress.AddressValue | D0F0xB8_ADDRESS, |
| 0x0, |
| AccessWidth32, |
| 0x0, |
| 0xE0000000 + ((SMC_RAM_START_ADDR + Firmware->HeaderLength * 4) >> 2), |
| StdHeader |
| ); |
| } else { |
| //Step 13, Clear autentification done |
| GnbLibPciIndirectRMW ( |
| GnbPciAddress.AddressValue | D0F0xB8_ADDRESS, |
| D0F0xBC_xE0003088_ADDRESS, |
| AccessWidth32, |
| 0x0, |
| 0x0, |
| StdHeader |
| ); |
| } |
| // Step 7, 14 Enable LM32 clock |
| GnbLibPciIndirectRMW ( |
| GnbPciAddress.AddressValue | D0F0xB8_ADDRESS, |
| 0x80000004 , |
| AccessWidth32, |
| (UINT32) ~(0x1 ), |
| 0 << 0 , |
| StdHeader |
| ); |
| |
| //Step 8, 15, Deassert LM32 reset |
| GnbLibPciIndirectRMW ( |
| GnbPciAddress.AddressValue | D0F0xB8_ADDRESS, |
| 0x80000000 , |
| AccessWidth32, |
| (UINT32) ~(0x1 ), |
| 0 << 0 , |
| StdHeader |
| ); |
| |
| if (D0F0xBC_xE00030A4.Field.SmuProtectedMode == 1) { |
| IDS_HDT_CONSOLE (NB_MISC, " Protected mode: poll init autehtication vector\n"); |
| // Step 16, Wait for rom firmware init autehtication vector |
| do { |
| GnbLibPciIndirectRead (GnbPciAddress.AddressValue | D0F0xB8_ADDRESS, 0x80010000 , AccessWidth32, &ex1005.Value, StdHeader); |
| } while (ex1005.Value != 0x400); |
| // Call Authentication service |
| GnbSmuServiceRequestV4 (GnbPciAddress, SMC_MSG_FIRMWARE_AUTH, 0, StdHeader); |
| IDS_HDT_CONSOLE (NB_MISC, " Protected mode: poll init autehtication done\n"); |
| // Wait for autehtication done |
| do { |
| GnbLibPciIndirectRead (GnbPciAddress.AddressValue | D0F0xB8_ADDRESS, D0F0xBC_xE0003088_ADDRESS, AccessWidth32, &D0F0xBC_xE0003088.Value, StdHeader); |
| } while (D0F0xBC_xE0003088.Field.SmuAuthDone == 0x0); |
| //Step 17, Check Authentication results |
| if (D0F0xBC_xE0003088.Field.SmuAuthPass == 0) { |
| IDS_HDT_CONSOLE (NB_MISC, " ERROR!!!Autehtication fail!!!\n"); |
| ASSERT (FALSE); |
| return AGESA_FATAL; |
| } |
| // Step 18, Clear firmware interrupt enable flag |
| GnbLibPciIndirectRMW ( |
| GnbPciAddress.AddressValue | D0F0xB8_ADDRESS, |
| D0F0xBC_x1F380_ADDRESS, |
| AccessWidth32, |
| 0x0, |
| 0x0, |
| StdHeader |
| ); |
| //Step 19, Assert LM32 reset |
| GnbLibPciIndirectRMW ( |
| GnbPciAddress.AddressValue | D0F0xB8_ADDRESS, |
| 0x80000000 , |
| AccessWidth32, |
| (UINT32) ~(0x1 ), |
| 1 << 0 , |
| StdHeader |
| ); |
| //Step 20, Deassert LM32 reset |
| GnbLibPciIndirectRMW ( |
| GnbPciAddress.AddressValue | D0F0xB8_ADDRESS, |
| 0x80000000 , |
| AccessWidth32, |
| (UINT32) ~(0x1 ), |
| 0 << 0 , |
| StdHeader |
| ); |
| } |
| //Step 9, 21 Wait firmware to initialize |
| do { |
| GnbLibPciIndirectRead (GnbPciAddress.AddressValue | D0F0xB8_ADDRESS, D0F0xBC_x1F380_ADDRESS, AccessWidth32, &D0F0xBC_x1F380.Value, StdHeader); |
| } while (D0F0xBC_x1F380.Field.InterruptsEnabled == 0); |
| IDS_HDT_CONSOLE (GNB_TRACE, "GnbSmuFirmwareLoadV4 Exit\n"); |
| return AGESA_SUCCESS; |
| } |
| |
| /*----------------------------------------------------------------------------------------*/ |
| /** |
| * 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 | (1 << D0F0x94_OrbIndWrEn_OFFSET), |
| 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 | (1 << D0F0x94_OrbIndWrEn_OFFSET), |
| 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] 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 %llx 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; |
| } |
| |