blob: b67d3c5394e50a1e685f69efb4b3653d81052366 [file] [log] [blame]
/* $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;
}