aboutsummaryrefslogtreecommitdiff
path: root/src/vendorcode/amd/cimx/rd890/nbIommu.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/vendorcode/amd/cimx/rd890/nbIommu.c')
-rw-r--r--src/vendorcode/amd/cimx/rd890/nbIommu.c1737
1 files changed, 0 insertions, 1737 deletions
diff --git a/src/vendorcode/amd/cimx/rd890/nbIommu.c b/src/vendorcode/amd/cimx/rd890/nbIommu.c
deleted file mode 100644
index 705b1a82fd..0000000000
--- a/src/vendorcode/amd/cimx/rd890/nbIommu.c
+++ /dev/null
@@ -1,1737 +0,0 @@
-/**
- * @file
- *
- * Routines for IOMMU.
- *
- * Implement the IOMMU init and ACPI feature.
- *
- * @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"
-
-#define Int32FromChar(a,b,c,d) ((a) << 0 | (b) << 8 | (c) << 16 | (d) << 24)
-
-/*----------------------------------------------------------------------------------------
- * R D 8 9 0 / S D A T A
- *----------------------------------------------------------------------------------------
- */
-
-// IOMMU Initialization
-
-INDIRECT_REG_ENTRY
-CONST
-STATIC
-IommuL1Table[] = {
- // 01. 0x0C [30:28]=7 L1VirtOrderQueues Increase maximum number virtual queues
- // for all devices
- { L1CFG_SEL_WR_EN | L1CFG_SEL_GPP1 | L1REG_0C, 0x8FFFFFFF, 0x70000000 },
- { L1CFG_SEL_WR_EN | L1CFG_SEL_GPP2 | L1REG_0C, 0x8FFFFFFF, 0x70000000 },
- { L1CFG_SEL_WR_EN | L1CFG_SEL_SB | L1REG_0C, 0x8FFFFFFF, 0x70000000 },
- { L1CFG_SEL_WR_EN | L1CFG_SEL_GPP3A | L1REG_0C, 0x8FFFFFFF, 0x70000000 },
- { L1CFG_SEL_WR_EN | L1CFG_SEL_GPP3B | L1REG_0C, 0x8FFFFFFF, 0x70000000 },
- { L1CFG_SEL_WR_EN | L1CFG_SEL_VC1 | L1REG_0C, 0x8FFFFFFF, 0x70000000 },
- // 02. 0x07 [11] L1DEBUG_1 Multiple error logs possible
- { L1CFG_SEL_WR_EN | L1CFG_SEL_GPP1 | L1REG_07, (UINT32)~(BIT8 + BIT9 + BIT10), BIT11 + BIT5 },
- { L1CFG_SEL_WR_EN | L1CFG_SEL_GPP2 | L1REG_07, (UINT32)~(BIT8 + BIT9 + BIT10), BIT11 + BIT5},
- { L1CFG_SEL_WR_EN | L1CFG_SEL_SB | L1REG_07, (UINT32)~(BIT8 + BIT9 + BIT10), BIT11 + BIT5},
- { L1CFG_SEL_WR_EN | L1CFG_SEL_GPP3A | L1REG_07, (UINT32)~(BIT8 + BIT9 + BIT10), BIT11 + BIT5},
- { L1CFG_SEL_WR_EN | L1CFG_SEL_GPP3B | L1REG_07, (UINT32)~(BIT8 + BIT9 + BIT10), BIT11 + BIT5},
- { L1CFG_SEL_WR_EN | L1CFG_SEL_VC1 | L1REG_07, (UINT32)~(BIT8 + BIT9 + BIT10), BIT11 + BIT5},
- // 02. 0x06 [0] L1DEBUG_0 Phantom function disable
- { L1CFG_SEL_WR_EN | L1CFG_SEL_GPP1 | L1REG_06, (UINT32)~BIT0, 0 },
- { L1CFG_SEL_WR_EN | L1CFG_SEL_GPP2 | L1REG_06, (UINT32)~BIT0, 0 },
- { L1CFG_SEL_WR_EN | L1CFG_SEL_SB | L1REG_06, (UINT32)~BIT0, 0 },
- { L1CFG_SEL_WR_EN | L1CFG_SEL_GPP3A | L1REG_06, (UINT32)~BIT0, 0 },
- { L1CFG_SEL_WR_EN | L1CFG_SEL_GPP3B | L1REG_06, (UINT32)~BIT0, 0 },
- { L1CFG_SEL_WR_EN | L1CFG_SEL_VC1 | L1REG_06, (UINT32)~BIT0, 0 }
-};
-
-INDIRECT_REG_ENTRY
-CONST
-STATIC
-IommuL2Table[] = {
- // 01. 0x0C [29]=1 IFifoClientPriority Set attribute to VC1 L1 client high priority
- { L2CFG_SEL_WR_EN | L2REG_0C, 0xD0000000, 0x20000000 },
- // 02. 0x10 [9:8]=2 DTCInvalidationSel DTC cache invalidation sequential precise
- { L2CFG_SEL_WR_EN | L2REG_10, 0xFFFFFC00, 0x00000200 },
- // 03. 0x14 [9:8]=2 ITCInvalidationSel ... cache invalidation sequential precise
- { L2CFG_SEL_WR_EN | L2REG_14, 0xFFFFFC00, 0x00000200 },
- // 04. 0x18 [9:8]=2 IPTCAInvalidationSel ... cache invalidation sequential precise
- { L2CFG_SEL_WR_EN | L2REG_18, 0xFFFFFC00, 0x00000200 },
- // 05. 0x1C [9:8]=2 IPTCBInvalidationSel ... cache invalidation sequential precise
- { L2CFG_SEL_WR_EN | L2REG_1C, 0xFFFFFC00, 0x00000200 },
- // 06. 0x50 [9:8]=2 PDCInvalidationSel ... cache invalidation sequential precise
- { L2CFG_SEL_WR_EN | L2REG_50, 0xFFFFFC00, 0x00000200 },
- // 07. 0x10 [4]=1 DTCParityEn DTC cache parity protection
- { L2CFG_SEL_WR_EN | L2REG_10, (UINT32)~BIT4, BIT4 },
- // 08. 0x14 [4]=1 ITCParityEn ... cache parity protection
- { L2CFG_SEL_WR_EN | L2REG_14, (UINT32)~BIT4, BIT4 },
- // 09. 0x18 [4]=1 PTCAParityEn ... cache parity protection
- { L2CFG_SEL_WR_EN | L2REG_18, (UINT32)~BIT4, BIT4 },
- // 10. 0x1C [4]=1 PTCBParityEn ... cache parity protection
- { L2CFG_SEL_WR_EN | L2REG_1C, (UINT32)~BIT4, BIT4 },
- // 11. 0x50 [4]=1 PDCParityEn ... cache parity protection
- { L2CFG_SEL_WR_EN | L2REG_50, (UINT32)~BIT4, BIT4 },
- // 12. 0x80 [0]=1 ERRRuleLock0 Lock fault detection rule sets
- // 0x30 [0]=1 ERRRuleLock1
- { L2CFG_SEL_WR_EN | L2REG_80, (UINT32)~BIT0, BIT0 },
- { L2CFG_SEL_WR_EN | L2REG_30, (UINT32)~BIT0, BIT0 },
- // 13. 0x56 [2]=0 L2_CP_CONTROL Disable CP flush on invalidation
- // 0x56 [1]=1 L2_CP_CONTROL Enable CP flush on wait
- { L2CFG_SEL_WR_EN | L2REG_56, 0xFFFFFFF9, BIT1 },
- // A21
- { L2CFG_SEL_WR_EN | L2REG_06, 0xFFFFFFFF, BIT6 + BIT7 + BIT5 + BIT8 },
- { L2CFG_SEL_WR_EN | L2REG_47, 0xFFFFFFFF, BIT1 + BIT3 + BIT0 + BIT4 + BIT5 },
- { L2CFG_SEL_WR_EN | L2REG_07, 0xFFFFFFFF, BIT1 + BIT2 + BIT3 + BIT4 + BIT5 + BIT8 + BIT6},
-
-};
-
-// IOMMU ACPI Initialization
-
-IOMMU_IVRS_HEADER
-STATIC
-RD890S_DfltHeader = {
-// 'SRVI',
- Int32FromChar ('S', 'R', 'V', 'I'),
- 48,
- 1,
- 0,
- {'A', 'M', 'D', ' ', ' ', 0},
- {'R', 'D', '8', '9', '0', 'S', 0, 0},
- {'1', ' ', ' ', 0},
- {'A','M','D',' '},
- {'1', ' ', ' ', 0},
- 0,
- 0
-};
-
-IOMMU_EXCLUSIONTABLE
-STATIC
-RD890S_DfltExclusion = {
- sizeof (UINTN) + sizeof (IOMMU_EXCLUSIONRANGE) * 0,
- {{0, 0}}
-};
-
-IOMMU_DEVICELIST
-STATIC
-RD890S_DfltDevices = {
- (sizeof (UINT16) + sizeof (UINT16) * 12),
- {
- DEVICEID_NB, // Type 2 entry, Device 0, Func 0 <-- NB all functions
- DEVICEID_GPP1_0, // Type 2 entry, Device 2, Func 0 <-- GPP1 port 0
- DEVICEID_GPP1_1, // Type 2 entry, Device 3, Func 0 <-- GPP1 port 1
- DEVICEID_GPP3A_0, // Type 2 entry, Device 4, Func 0 <-- GPP3a port 0
- DEVICEID_GPP3A_1, // Type 2 entry, Device 5, Func 0 <-- GPP3a port 1
- DEVICEID_GPP3A_2, // Type 2 entry, Device 6, Func 0 <-- GPP3a port 2
- DEVICEID_GPP3A_3, // Type 2 entry, Device 7, Func 0 <-- GPP3a port 3
- DEVICEID_GPP3A_4, // Type 2 entry, Device 9, Func 0 <-- GPP3a port 4
- DEVICEID_GPP3A_5, // Type 2 entry, Device A, Func 0 <-- GPP3a port 5
- DEVICEID_GPP2_0, // Type 2 entry, Device B, Func 0 <-- GPP2 port 0
- DEVICEID_GPP2_1, // Type 2 entry, Device C, Func 0 <-- GPP2 port 1
- DEVICEID_GPP3B_0, // Type 2 entry, Device D, Func 0 <-- GPP3b port 0
- }
-};
-
-/*----------------------------------------------------------------------------------------
- * 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
- *----------------------------------------------------------------------------------------
-*/
-
-// IOMMU Library
-
-BOOLEAN
-NbIommuEnabled (
- IN OUT AMD_NB_CONFIG_BLOCK *ConfigPtr
- );
-
-BOOLEAN
-IommuCheckEnable (
- IN PCI_ADDR IommuPciAddress,
- IN AMD_NB_CONFIG *pConfig
- );
-
-BOOLEAN
-IommuCheckHp (
- IN UINT16 DeviceId,
- IN AMD_NB_CONFIG *pConfig
- );
-
-BOOLEAN
-IommuCheckPhantom (
- IN UINT16 DeviceId,
- IN AMD_NB_CONFIG *pConfig
- );
-
-UINT32
-IommuGetL1 (
- IN UINT16 DeviceId
- );
-
-UINT8
-IommuGetLog2 (
- IN UINT32 Value
- );
-
-VOID
-IommuRecordBusDevFuncInfo (
- IN OUT IOMMU_PCI_TOPOLOGY *PciPtr,
- IN UINT16 DeviceId,
- IN AMD_NB_CONFIG *pConfig
- );
-
-
-AGESA_STATUS
-IommuInit (
- IN OUT AMD_NB_CONFIG *pConfig
- );
-
-VOID
-IommuInitL2CacheControl (
- IN IOMMU_PCI_TOPOLOGY *PciPtr,
- IN OUT AMD_NB_CONFIG *pConfig
-);
-
-VOID
-IommuPlaceHeader (
- IN OUT VOID *BufferPtr,
- IN OUT AMD_NB_CONFIG *pConfig
- );
-
-VOID
-IommuPlaceIvhdAndScanDevices (
- IN OUT VOID *BufferPtr,
- IN OUT AMD_NB_CONFIG *pConfig
- );
-
-VOID
-IommuPlaceIvmdAndExclusions (
- IN OUT VOID *BufferPtr,
- IN OUT AMD_NB_CONFIG *pConfig
- );
-
-VOID
-IommuIvhdNorthbridgeDevices (
- IN OUT IOMMU_PCI_TOPOLOGY *PciPtr,
- IN OUT IOMMU_IVHD_ENTRY *IvhdPtr,
- IN OUT AMD_NB_CONFIG *pConfig
- );
-
-VOID
-IommuIvhdSouthbridgeDevices (
- IN OUT IOMMU_PCI_TOPOLOGY *PciPtr,
- IN OUT IOMMU_IVHD_ENTRY *IvhdPtr,
- IN OUT AMD_NB_CONFIG *pConfig
- );
-
-VOID
-IommuIvhdApicsAndHpets (
- IN OUT IOMMU_IVHD_ENTRY *IvhdPtr,
- IN OUT AMD_NB_CONFIG *pConfig
- );
-
-VOID
-IommuCreateDeviceEntry (
- IN OUT IOMMU_PCI_TOPOLOGY *PciPtr,
- IN UINT16 DeviceId,
- IN OUT IOMMU_IVHD_ENTRY *IvhdPtr,
- IN AMD_NB_CONFIG *pConfig
- );
-
-VOID
-IommuCreate4ByteEntry (
- IN UINT8 Type,
- IN UINT8 Data,
- IN UINT16 Word1,
- IN OUT IOMMU_IVHD_ENTRY *IvhdPtr
- );
-
-VOID
-IommuCreate8ByteEntry (
- IN UINT8 Type,
- IN UINT8 Data,
- IN UINT16 Word1,
- IN UINT8 Byte4,
- IN UINT16 Word5,
- IN UINT8 Byte7,
- IN OUT IOMMU_IVHD_ENTRY *IvhdPtr
- );
-
-VOID
-IommuFinalizeIvrs (
- IN OUT VOID *BufferPtr,
- IN AMD_NB_CONFIG *pConfig
- );
-
-// IOMMU ACPI Final
-
-UINT64
-IommuGetApicBaseAddress (
- IN VOID *DevicePtr,
- IN AMD_NB_CONFIG *pConfig
- );
-
-UINT8
-IommuGetApicId (
- IN UINT64 BaseAddress,
- IN VOID *MadtPtr,
- IN AMD_NB_CONFIG *pConfig
- );
-
-AGESA_STATUS
-NbIommuHwInit (
- IN OUT AMD_NB_CONFIG_BLOCK *ConfigPtr
- );
-
-AGESA_STATUS
-NbIommuHwTopologyInit (
- IN OUT AMD_NB_CONFIG_BLOCK *ConfigPtr
- );
-
-AGESA_STATUS
-IommuTopologyInit (
- IN OUT AMD_NB_CONFIG *pConfig
- );
-
-/*----------------------------------------------------------------------------------------
- * E X P O R T E D
- *----------------------------------------------------------------------------------------
- */
-
-
-/*----------------------------------------------------------------------------------------*/
-/**
- * Check if IOMMU enable on platform
- *
- * @param[in] ConfigPtr Northbridges configuration block pointer.
- * @retval AGESA_SUCCESS IOMMU initialized and table created
- * @retval AGESA_UNSUPPORTED IOMMU not enabled or not found
- * @retval AGESA_ERROR IOMMU initialization failed.
- *
- */
-BOOLEAN
-NbIommuEnabled (
- IN OUT AMD_NB_CONFIG_BLOCK *ConfigPtr
- )
-{
- UINT8 NorthbridgeId;
- BOOLEAN Result;
- Result = FALSE;
- for (NorthbridgeId = 0; NorthbridgeId <= ConfigPtr->NumberOfNorthbridges; NorthbridgeId++) {
- if (ConfigPtr->Northbridges[NorthbridgeId].pNbConfig->IommuBaseAddress != 0) {
- Result = TRUE;
- break;
- }
- }
- return Result;
-}
-
-/*----------------------------------------------------------------------------------------*/
-/**
- * Northbridge Iommu Initialization for all NB in system.
- *
- * @param[in] ConfigPtr Northbridges configuration block pointer.
- * @retval AGESA_SUCCESS IOMMU initialized and table created
- * @retval AGESA_UNSUPPORTED IOMMU not enabled or not found
- * @retval AGESA_ERROR IOMMU initialization failed.
- *
- */
-AGESA_STATUS
-NbIommuInit (
- IN OUT AMD_NB_CONFIG_BLOCK *ConfigPtr
- )
-{
- AGESA_STATUS Status;
-
- Status = AGESA_SUCCESS;
-
- CIMX_TRACE ((TRACE_DATA (ConfigPtr, CIMX_NB_TRACE), "[NBIOMMU]NbIommuInit Enter\n"));
-
- if (NbIommuEnabled (ConfigPtr)) {
- NbIommuHwInit (ConfigPtr);
- NbIommuAcpiInit (ConfigPtr);
- NbIommuHwTopologyInit (ConfigPtr);
- } else {
- Status = AGESA_UNSUPPORTED;
- }
-
- CIMX_TRACE ((TRACE_DATA (ConfigPtr, CIMX_NB_TRACE), "[NBIOMMU]NbIommuInit Exit [Status = 0x%x]\n", Status));
- return Status;
-}
-
-
-
-
-/*----------------------------------------------------------------------------------------*/
-/**
- * Northbridge Iommu Initialization for all NB in system.
- *
- * @param[in] ConfigPtr Northbridges configuration block pointer.
- * @retval AGESA_SUCCESS IOMMU initialized and table created
- * @retval AGESA_UNSUPPORTED IOMMU not enabled or not found
- * @retval AGESA_ERROR IOMMU initialization failed.
- *
- */
-AGESA_STATUS
-NbIommuInitS3 (
- IN OUT AMD_NB_CONFIG_BLOCK *ConfigPtr
- )
-{
- AGESA_STATUS Status;
-
- Status = AGESA_SUCCESS;
- CIMX_TRACE ((TRACE_DATA (ConfigPtr, CIMX_NB_TRACE), "[NBIOMMU]NbIommuInitS3 Enter\n"));
-
- if (NbIommuEnabled (ConfigPtr)) {
- NbIommuHwInit (ConfigPtr);
- NbIommuHwTopologyInit (ConfigPtr);
- } else {
- Status = AGESA_UNSUPPORTED;
- }
- CIMX_TRACE ((TRACE_DATA (ConfigPtr, CIMX_NB_TRACE), "[NBIOMMU]NbIommuInitS3 Exit [Status = 0x%x]\n", Status));
- return Status;
-}
-
-
-
-
-/*----------------------------------------------------------------------------------------*/
-/**
- * Northbridge Iommu HW Initialization for all NB in system.
- *
- * @param[in] ConfigPtr Northbridges configuration block pointer.
- * @retval AGESA_SUCCESS IOMMU initialized and table created
- * @retval AGESA_ERROR IOMMU initialization failed.
- *
- */
-AGESA_STATUS
-NbIommuHwInit (
- IN OUT AMD_NB_CONFIG_BLOCK *ConfigPtr
- )
-{
- UINT8 NorthbridgeId;
- AMD_NB_CONFIG *pConfig;
-
- for (NorthbridgeId = 0; NorthbridgeId <= ConfigPtr->NumberOfNorthbridges; NorthbridgeId++) {
- pConfig = &ConfigPtr->Northbridges[NorthbridgeId];
- ConfigPtr->CurrentNorthbridge = NorthbridgeId;
- IommuInit (pConfig);
- }
- return AGESA_SUCCESS;
-}
-
-/*----------------------------------------------------------------------------------------*/
-/**
- * Northbridge Iommu HW Initialization for all NB in system.
- *
- * @param[in] ConfigPtr Northbridges configuration block pointer.
- * @retval AGESA_SUCCESS IOMMU initialized and table created
- * @retval AGESA_ERROR IOMMU initialization failed.
- *
- */
-AGESA_STATUS
-NbIommuHwTopologyInit (
- IN OUT AMD_NB_CONFIG_BLOCK *ConfigPtr
- )
-{
- UINT8 NorthbridgeId;
- AMD_NB_CONFIG *pConfig;
-
- for (NorthbridgeId = 0; NorthbridgeId <= ConfigPtr->NumberOfNorthbridges; NorthbridgeId++) {
- pConfig = &ConfigPtr->Northbridges[NorthbridgeId];
- ConfigPtr->CurrentNorthbridge = NorthbridgeId;
- IommuTopologyInit (pConfig);
- }
- return AGESA_SUCCESS;
-}
-
-/*----------------------------------------------------------------------------------------*/
-/**
- * Northbridge Iommu Initialization for all NB in system.
- *
- * @param[in] ConfigPtr Northbridges configuration block pointer.
- * @retval AGESA_SUCCESS IOMMU initialized and table created
- * @retval AGESA_UNSUPPORTED IOMMU not enabled or not found
- * @retval AGESA_ERROR IOMMU initialization failed.
- *
- */
-AGESA_STATUS
-NbIommuAcpiInit (
- IN OUT AMD_NB_CONFIG_BLOCK *ConfigPtr
- )
-{
- UINT8 NorthbridgeId;
- AGESA_STATUS Status;
- AMD_NB_CONFIG *pConfig;
- NB_BUFFER_PARAMS Ivrs;
- UINTN IvrsHandle;
-
- Status = AGESA_SUCCESS;
- Ivrs.BufferLength = 0;
- Ivrs.BufferHandle = IVRS_HANDLE;
- Ivrs.BufferPtr = NULL;
- pConfig = &ConfigPtr->Northbridges[0];
- ConfigPtr->CurrentNorthbridge = 0;
- IvrsHandle = 0;
-
- CIMX_TRACE ((TRACE_DATA (ConfigPtr, CIMX_NB_TRACE), "[NBIOMMU]NbIommuAcpiInit Enter\n"));
-
- // Get a buffer for IVRS
- Ivrs.BufferLength = IVRS_BUFFER_SIZE;
- Status = LibNbCallBack (PHCB_AmdAllocateBuffer, (UINTN)&Ivrs, &ConfigPtr->Northbridges[0]);
- if (Status != AGESA_SUCCESS || Ivrs.BufferPtr == NULL) {
- // Table creation failed
- return AGESA_ERROR;
- }
-
- // Clear buffer before using
- LibAmdMemFill (Ivrs.BufferPtr, 0, Ivrs.BufferLength, (AMD_CONFIG_PARAMS *)&(pConfig->sHeader));
-
- // PLACE OUR ACPI IVRS TABLE
- // 1. Create IVRS header
- // 2. For each northbridge place IVHD
- // 3. For northbridge 0 only, place IVMD exclusion entries
- for (NorthbridgeId = 0; NorthbridgeId <= ConfigPtr->NumberOfNorthbridges; NorthbridgeId++) {
- pConfig = &ConfigPtr->Northbridges[NorthbridgeId];
- ConfigPtr->CurrentNorthbridge = NorthbridgeId;
- if (NorthbridgeId == 0) {
- IommuPlaceHeader (Ivrs.BufferPtr, pConfig);
- }
- IommuPlaceIvhdAndScanDevices (Ivrs.BufferPtr, pConfig);
- IommuPlaceIvmdAndExclusions (Ivrs.BufferPtr, pConfig);
- }
- IommuFinalizeIvrs (Ivrs.BufferPtr, pConfig);
-
- LibAmdSetAcpiTable (Ivrs.BufferPtr, TRUE, &IvrsHandle);
-
- CIMX_TRACE ((TRACE_DATA (ConfigPtr, CIMX_NB_TRACE), "[NBIOMMU]NbIommuAcpiInit [IVRS TableAddress = 0x%x]\n", (UINT32)(Ivrs.BufferPtr)));
- CIMX_TRACE ((TRACE_DATA (ConfigPtr, CIMX_NB_TRACE), "[NBIOMMU]NbIommuAcpiInit Exit [Status = 0x%x]\n", Status));
-
- return AGESA_SUCCESS;
-}
-
-/*----------------------------------------------------------------------------------------*/
-/**
- * Northbridge Iommu IVRS fixup for APICS
- *
- * @param[in] ConfigPtr Northbridges configuration block pointer.
- * @retval AGESA_SUCCESS IOMMU initialized and table patched, or no patching required
- * @retval AGESA_ERROR IOMMU enabled but no previously generated IVRC table found.
- *
- */
-AGESA_STATUS
-NbIommuAcpiFixup (
- IN OUT AMD_NB_CONFIG_BLOCK *ConfigPtr
- )
-{
- AGESA_STATUS Status;
- UINT8 ApicId;
- UINT64 ApicBaseAddress;
- UINT8 NorthbridgeId;
- BOOLEAN IommuFound;
- VOID *DevicePtr;
- VOID *IvhdPtr;
- VOID *IvrsPtr;
- VOID *MadtPtr;
- AMD_NB_CONFIG *pConfig;
- PCI_ADDR IommuPciAddress;
- UINTN IvrsHandle;
-
-
- pConfig = &ConfigPtr->Northbridges[0];
- IommuFound = FALSE;
- ApicId = 0xFF;
- ApicBaseAddress = 0;
-
- CIMX_TRACE ((TRACE_DATA (ConfigPtr, CIMX_NB_TRACE), "[NBIOMMU]NbIommuAcpiFixup Enter\n"));
-
- for (NorthbridgeId = 0; NorthbridgeId <= ConfigPtr->NumberOfNorthbridges; NorthbridgeId++) {
- pConfig = &ConfigPtr->Northbridges[NorthbridgeId];
- ConfigPtr->CurrentNorthbridge = NorthbridgeId;
- IommuPciAddress = pConfig->NbPciAddress;
- IommuPciAddress.Address.Function = NB_IOMMU;
- if (IommuCheckEnable (IommuPciAddress, pConfig)) {
- IommuFound = TRUE;
- }
- }
-
- // Any Iommus enabled? If no, we don't need to patch anything
- if (!IommuFound) {
- return AGESA_SUCCESS;
- }
-
- // Check for an IVRS
- // Check IVRS for a type 10 block (IVHD)
- // Check for an MADT
- // If these conditions fail, abort
-
-// Status = LibAmdGetAcpiTable ('SRVI', &IvrsPtr, &IvrsHandle);
- Status = LibAmdGetAcpiTable (Int32FromChar ('S', 'R', 'V', 'I'), &IvrsPtr, &IvrsHandle);
- if (Status != AGESA_SUCCESS) {
-// REPORT_EVENT (AGESA_ERROR, GENERAL_ERROR_LOCATE_ACPI_TABLE, 'SRVI', 0, 0, 0, pConfig);
- REPORT_EVENT (AGESA_ERROR, GENERAL_ERROR_LOCATE_ACPI_TABLE, Int32FromChar ('S', 'R', 'V', 'I'), 0, 0, 0, pConfig);
- return AGESA_ERROR;
- }
-
-// Status = LibAmdGetAcpiTable ('CIPA', &MadtPtr, NULL);
- Status = LibAmdGetAcpiTable (Int32FromChar ('C', 'I', 'P', 'A'), &MadtPtr, NULL);
- if (Status != AGESA_SUCCESS) {
-// REPORT_EVENT (AGESA_ERROR, GENERAL_ERROR_LOCATE_ACPI_TABLE, 'CIPA', 0, 0, 0, pConfig);
- REPORT_EVENT (AGESA_ERROR, GENERAL_ERROR_LOCATE_ACPI_TABLE, Int32FromChar ('C', 'I', 'P', 'A'), 0, 0, 0, pConfig);
- return AGESA_ERROR;
- }
-
- IvhdPtr = LibAmdGetFirstIvrsBlockEntry (TYPE_IVHD, IvrsPtr);
- if (IvhdPtr == NULL) {
- return AGESA_ERROR;
- }
-
- // An IVRS can contain one or more IVHD entries (one per IOMMU)
- // Each IVHD entry can contain one or more APIC entries
-
- while (IvhdPtr != NULL) {
- DevicePtr = LibAmdGetFirstDeviceEntry (DE_SPECIAL, IvhdPtr);
- do {
- // Be sure to only fix APIC entries
- if (*(UINT8*) ((UINT8*)DevicePtr + DE_SPECIAL_VARIETY) == VARIETY_IOAPIC) {
- ApicBaseAddress = IommuGetApicBaseAddress (DevicePtr, pConfig);
- ApicId = IommuGetApicId (ApicBaseAddress, MadtPtr, pConfig);
- *(UINT8*)((UINT8*)DevicePtr + DE_SPECIAL_ID) = ApicId;
- }
- DevicePtr = LibAmdGetNextDeviceEntry (DE_SPECIAL, DevicePtr, IvhdPtr);
- } while (DevicePtr != NULL);
-
- IvhdPtr = LibAmdGetNextIvrsBlockEntry (TYPE_IVHD, IvhdPtr, IvrsPtr);
- }
-
- LibAmdSetAcpiTable (IvrsPtr, TRUE, &IvrsHandle);
-
- CIMX_TRACE ((TRACE_DATA (ConfigPtr, CIMX_NB_TRACE), "[NBIOMMU]NbIommuAcpiFixup [IVRS TableAddress = 0x%x]\n", (UINT32)IvrsPtr));
- CIMX_TRACE ((TRACE_DATA (ConfigPtr, CIMX_NB_TRACE), "[NBIOMMU]NbIommuAcpiFixup [APIC TableAddress = 0x%x]\n", (UINT32)MadtPtr));
- CIMX_TRACE ((TRACE_DATA (ConfigPtr, CIMX_NB_TRACE), "[NBIOMMU]NbIommuAcpiFixup Exit\n"));
-
- return AGESA_SUCCESS;
-}
-
-/*----------------------------------------------------------------------------------------
- * P R I V A T E
- *----------------------------------------------------------------------------------------
- */
-UINT32 IommuMmioInitTable[] = {
- 0x8, 0x0,
- 0xC, 0x08000000,
- 0x10, 0x0,
- 0x14, 0x08000000,
- 0x2000, 0x0,
- 0x2008, 0x0
-};
-
-/*----------------------------------------------------------------------------------------*/
-/**
- * Nb Iommu Initialization.
- *
- * @param[in] pConfig Northbridge configuration pointer
- * @retval AGESA_SUCCESS IOMMU enable and initialized succesfully.
- * @retval AGESA_UNSUPPORTED IOMMU not initialized.
- */
-AGESA_STATUS
-IommuInit (
- IN OUT AMD_NB_CONFIG *pConfig
- )
-{
- UINT8 CapBase;
- PCI_ADDR IommuPciAddress;
- UINTN i;
-
- IommuPciAddress = pConfig->NbPciAddress;
- IommuPciAddress.Address.Function = NB_IOMMU;
-
- // If the base address = 0, don't enable IOMMU
- if (pConfig->pNbConfig->IommuBaseAddress == 0) {
- return AGESA_UNSUPPORTED;
- }
-
- // NBMISCIND:0x75 IOC_FEATURE_CNTL_10_0[10]=1
- // 0=disable
- // 1=enable
-
- LibNbPciIndexRMW (pConfig->NbPciAddress.AddressValue | NB_MISC_INDEX, NB_MISC_REG75, AccessS3SaveWidth32, (UINT32)~(BIT28), BIT0, pConfig);
-
- // Get Capabilities pointer 32h (points to 40h) - capability ID 0x0F. Not found, we have no IOMMU.
- CapBase = LibNbFindPciCapability (IommuPciAddress.AddressValue, IOMMU_CAPID, pConfig);
- if (CapBase == 0) {
- return AGESA_UNSUPPORTED;
- }
-
- // IOMMU_ADAPTER_ID_W - RW - 32 bits - nbconfigfunc2:0x68
- // SUBSYSTEM_VENDOR_ID_W 15:0 0x0 Sets the subsystem vendor ID register header
- // SUBSYSTEM_ID_W 31:16 0x0 Sets the subsystem ID register in the configuration header
- CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (pConfig), CIMX_NB_TRACE), "[NBIOMMU]Iommu Device Found [PCI Address = 0x%x]\n", IommuPciAddress.AddressValue));
- if (pConfig->pNbConfig->SSID == PCI_INVALID) {
- LibNbPciRead (IommuPciAddress.AddressValue, AccessWidth32, &pConfig->pNbConfig->SSID, pConfig);
- }
- if (pConfig->pNbConfig->SSID) {
- LibNbPciWrite (IommuPciAddress.AddressValue | 0x68, AccessS3SaveWidth32, &pConfig->pNbConfig->SSID, pConfig);
- }
-
- // Get Capabilities pointer 32h (points to 40h) - capability ID 0x0F
- // Set Cap_Offset+04h [31:14] Base Address Low [31:14]
- // Set Cap_Offset+08h [31:0] Base Address High [64:32]
- // Set Cap_Offset+04h [0] Enable
- LibNbPciRMW ((IommuPciAddress.AddressValue | (CapBase + 8)), AccessS3SaveWidth32, 0x0, ((UINT32*)&pConfig->pNbConfig->IommuBaseAddress)[1], pConfig);
- LibNbPciRMW ((IommuPciAddress.AddressValue | (CapBase + 4)), AccessS3SaveWidth32, 0x0, ((UINT32*)&pConfig->pNbConfig->IommuBaseAddress)[0], pConfig);
-
- // Enable zeroing of address for zero-byte reads when IOMMU enabled
- LibNbPciIndexRMW (pConfig->NbPciAddress.AddressValue | NB_MISC_INDEX, NB_MISC_REG01, AccessS3SaveWidth32, (UINT32)~(BIT8 | BIT9), BIT8, pConfig);
-
- // 8.3.1 L1 Initialization
- LibNbIndirectTableInit (IommuPciAddress.AddressValue | L1CFG_INDEX,
- 0,
- (INDIRECT_REG_ENTRY*)FIX_PTR_ADDR(&IommuL1Table[0],NULL),
- (sizeof (IommuL1Table) / sizeof (INDIRECT_REG_ENTRY)),
- pConfig
- );
-
- // 8.3.3.1 L2 Common Initialization
- LibNbIndirectTableInit (IommuPciAddress.AddressValue | L2CFG_INDEX,
- 0,
- (INDIRECT_REG_ENTRY*)FIX_PTR_ADDR(&IommuL2Table[0], NULL),
- (sizeof (IommuL2Table) / sizeof (INDIRECT_REG_ENTRY)),
- pConfig
- );
- //Configure PDC cache to 12-way set associative cache for A21
- if (LibNbGetRevisionInfo (pConfig).Revision > NB_REV_A11) {
- LibNbPciIndexRMW (IommuPciAddress.AddressValue | L2CFG_INDEX, L2CFG_SEL_WR_EN | L2REG_52, AccessS3SaveWidth32, 0x0, 0xF0000002 , pConfig);
- }
- // Start and lock the Iommu settings
- LibNbPciRMW ((IommuPciAddress.AddressValue | (CapBase + 4)), AccessS3SaveWidth32, 0xFFFFFFFF, (UINT32)BIT0, pConfig);
-
- //Reset IOMMU MMIO registers on system reset
- for (i = 0; i < (sizeof (IommuMmioInitTable) / sizeof (UINT32)); i = i + 2) {
- LibNbMemRMW (pConfig->pNbConfig->IommuBaseAddress + IommuMmioInitTable[i], AccessS3SaveWidth32, 0x0, IommuMmioInitTable[i + 1], pConfig);
- }
- return AGESA_SUCCESS;
-}
-
-
-/*----------------------------------------------------------------------------------------*/
-/**
- * Iommu Initialization of topology specific data.
- *
- * @param[in] pConfig Northbridge configuration pointer
- * @retval AGESA_SUCCESS IOMMU enable and initialized succesfully.
- * @retval AGESA_UNSUPPORTED IOMMU not initialized.
- */
-AGESA_STATUS
-IommuTopologyInit (
- IN OUT AMD_NB_CONFIG *pConfig
- )
-{
- // Set L2 Caches Hash Control based on maximum bus, device, function
- IommuInitL2CacheControl ((IOMMU_PCI_TOPOLOGY*) &pConfig->pNbConfig->IommuTpologyInfo, pConfig);
- return AGESA_SUCCESS;
-}
-
-L2_HASH_CONTROL HashControls[] = {
- {
- L2_DTC_CONTROL
- },
- {
- L2_ITC_CONTROL
- },
- {
- L2_PTC_A_CONTROL
- },
- {
- L2_PTC_B_CONTROL
- },
- {
- L2_PDC_CONTROL
- }
-};
-
-/*----------------------------------------------------------------------------------------*/
-/**
- * Set L2 Cache Hash Control based on maximum Bus, Dev, Function found
- *
- * @param[in] PciPtr Array of bus, device, function
- * @param[in] pConfig Northbridge configuration structure pointer.
- */
-VOID
-IommuInitL2CacheControl (
- IN IOMMU_PCI_TOPOLOGY *PciPtr,
- IN OUT AMD_NB_CONFIG *pConfig
- )
-{
- UINT32 Value;
- PCI_ADDR IommuPciAddress;
- UINTN i;
- UINT8 FuncBitsUsed;
- UINT8 DevBitsUsed;
- UINT8 BusBitsUsed;
-
- IommuPciAddress = pConfig->NbPciAddress;
- IommuPciAddress.Address.Function = NB_IOMMU;
-
- CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (pConfig), CIMX_NB_TRACE), " L2Cache Init Max Bus = 0x%x Max Device = 0x%x Mux Func = 0x%x\n", PciPtr->MaxBus, PciPtr->MaxDevice, PciPtr->MaxFunction));
-
- FuncBitsUsed = CIMX_MAX (IommuGetLog2 (PciPtr->MaxFunction + 1), 3);
- DevBitsUsed = IommuGetLog2 (PciPtr->MaxDevice + 1);
- BusBitsUsed = IommuGetLog2 (PciPtr->MaxBus + 1);
-
- for (i = 0; i < (sizeof (HashControls) / sizeof (L2_HASH_CONTROL)); i++) {
- UINT8 NBits;
- UINT8 NFuncBits;
- UINT8 NDevBits;
- UINT8 NBusBits;
- LibNbPciIndexRead (IommuPciAddress.AddressValue | L2CFG_INDEX, L2CFG_SEL_WR_EN | HashControls[i].HashControl, AccessWidth32, &Value, pConfig);
- NBits = (UINT8) (Value >> 28) - IommuGetLog2 ((Value >> 16) & 0xff);
- NFuncBits = CIMX_MIN (NBits, 0x3);
- NBits = NBits - NFuncBits;
- NDevBits = CIMX_MIN ( NBits, DevBitsUsed + FuncBitsUsed - NFuncBits);
- NBusBits = NBits - NDevBits;
- CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (pConfig), CIMX_NB_TRACE), " NBusBits = %d, NDevBits = %d, NFuncBits = %d \n", NBusBits, NDevBits, NFuncBits));
- LibNbPciIndexRMW (
- IommuPciAddress.AddressValue | L2CFG_INDEX,
- L2CFG_SEL_WR_EN | (HashControls[i].HashControl + 1),
- AccessS3SaveWidth32,
- 0xFFFFFE00,
- (NFuncBits | (NDevBits << 2) | (NBusBits << 5)) & 0x1FF,
- pConfig
- );
- }
-}
-
-/*----------------------------------------------------------------------------------------*/
-/**
- * Check to see if current PCI Address is an IOMMU
- *
- * @param[in] IommuPciAddress PCI Address to check
- * @param[in] pConfig Northbridge configuration structure pointer.
- * @retval TRUE if Iommu is enabled and found
- */
-BOOLEAN
-IommuCheckEnable (
- IN PCI_ADDR IommuPciAddress,
- IN AMD_NB_CONFIG *pConfig
- )
-{
- UINT8 CapBase;
-
- if (pConfig->pNbConfig->IommuBaseAddress == 0x0) {
- return FALSE;
- }
- CapBase = LibNbFindPciCapability (IommuPciAddress.AddressValue, IOMMU_CAPID, pConfig);
- if (CapBase == 0) {
- return FALSE;
- } else {
- return TRUE;
- }
-}
-
-/*----------------------------------------------------------------------------------------*/
-/**
- * Check an RD890 PCIE bridge to see if hot plug is enabled
- *
- * @param[in] DeviceId Device Id to check
- * @param[in] pConfig Northbridge configuration structure pointer.
- * @retval TRUE if current device supports hotplug
- */
-BOOLEAN
-IommuCheckHp (
- IN UINT16 DeviceId,
- IN AMD_NB_CONFIG *pConfig
- )
-{
- UINT32 PciData;
- PCI_ADDR PciAddress;
-
- PciAddress.AddressValue = MAKE_SBDFO (0, (DeviceId >> 8) & 0xFF, (DeviceId >> 3) & 0x1F, DeviceId & 0x7, 0);
-
- LibNbPciRead (PciAddress.AddressValue | NB_PCIP_REG6C, AccessWidth32, &PciData, pConfig);
-
- // Check for hot plug by reading PCIE_SLOT_CAP pcieConfigDev[13:2]:0x6C [6] HOTPLUG_CAPABLE
- PciData &= BIT6;
- if (PciData != 0) {
- return TRUE;
- } else {
- return FALSE;
- }
-}
-
-/*----------------------------------------------------------------------------------------*/
-/**
- * Check a PCIE device to see if it supports phantom functions
- *
- * @param[in] DeviceId Device Id to check
- * @param[in] pConfig Northbridge configuration structure pointer.
- * @retval TRUE if current device supports phantom functions
- */
-BOOLEAN
-IommuCheckPhantom (
- IN UINT16 DeviceId,
- IN AMD_NB_CONFIG *pConfig
- )
-{
- UINT32 PciData;
- UINT8 PcieCapBase;
- PCI_ADDR PciAddress;
-
- PciAddress.AddressValue = MAKE_SBDFO (0, (DeviceId >> 8) & 0xFF, (DeviceId >> 3) & 0x1F, DeviceId & 0x7, 0);
-
- // Check for phantom functions by reading PCIE Device Capabilities register (base + 4) [4:3] 0 = not supported
- PcieCapBase = LibNbFindPciCapability (PciAddress.AddressValue, PCIE_CAPID, pConfig);
- if (PcieCapBase != 0) {
- LibNbPciRead (((PciAddress.AddressValue) | (PcieCapBase + 4)), AccessWidth32, &PciData, pConfig);
- PciData &= PCIE_PHANTOMMASK;
- if (PciData != 0) {
- return TRUE;
- }
- }
- return FALSE;
-}
-
-/*----------------------------------------------------------------------------------------*/
-/**
- * Check to see if current PCI Address is a multi-port PCIE core
- *
- * @param[in] DeviceId 16-bit device id to check
- * @retval L1 configuration select
- */
-UINT32
-IommuGetL1 (
- IN UINT16 DeviceId
- )
-{
- // This function translates an RD890 multi-port pci core to the offset of the L1 entry
- // corresponding to it. An unknown device returns as invalid
- switch (DeviceId) {
- case DEVICEID_GPP1_0 :
- return L1CFG_SEL_GPP1;
- case DEVICEID_GPP1_1 :
- return L1CFG_SEL_GPP1;
- case DEVICEID_GPP2_0 :
- return L1CFG_SEL_GPP2;
- case DEVICEID_GPP2_1 :
- return L1CFG_SEL_GPP2;
- case DEVICEID_GPP3A_0 :
- return L1CFG_SEL_GPP3A;
- case DEVICEID_GPP3A_1 :
- return L1CFG_SEL_GPP3A;
- case DEVICEID_GPP3A_2 :
- return L1CFG_SEL_GPP3A;
- case DEVICEID_GPP3A_3 :
- return L1CFG_SEL_GPP3A;
- case DEVICEID_GPP3A_4 :
- return L1CFG_SEL_GPP3A;
- case DEVICEID_GPP3A_5 :
- return L1CFG_SEL_GPP3A;
- case DEVICEID_GPP3B_0 :
- return L1CFG_SEL_GPP3B;
- default:
- return PCI_INVALID;
- }
-}
-
-/*----------------------------------------------------------------------------------------*/
-/**
- * Place IVHD Device Entries
- *
- * @param[in] Value Value to find the logarithm of
- * @retval Logarithm of input Value
- */
-UINT8
-IommuGetLog2 (
- IN UINT32 Value
- )
-{
- UINT8 Result;
-
- Result = 0;
-
- // This code will round a 32bit value to the next highest power of 2
- Value--;
- Value |= Value >> 1;
- Value |= Value >> 2;
- Value |= Value >> 4;
- Value |= Value >> 8;
- Value |= Value >> 16;
- Value++;
-
- // Calculate the logarithm
- while (Value >>= 1) {
- Result++;
- }
-
- return Result;
-}
-
-/*----------------------------------------------------------------------------------------*/
-/**
- * Place IVRS Header for IOMMU ACPI table
- *
- * @param[in, out] BufferPtr Pointer to buffer to return IVRS.
- * @param[in] pConfig Northbridge configuration structure pointer.
- */
-VOID
-IommuPlaceHeader (
- IN OUT VOID *BufferPtr,
- IN OUT AMD_NB_CONFIG *pConfig
- )
-{
- IOMMU_IVRS_HEADER *HeaderPtr;
- HeaderPtr = (IOMMU_IVRS_HEADER *)BufferPtr;
- LibAmdMemCopy (HeaderPtr, &RD890S_DfltHeader, sizeof (IOMMU_IVRS_HEADER), (AMD_CONFIG_PARAMS *)&(pConfig->sHeader));
-}
-
-/*----------------------------------------------------------------------------------------*/
-/**
- * Place IVMD (memory device) Create all IVMD entries for a single exclusion table
- *
- * @param[in, out] BufferPtr Pointer to text buffer to return IVRS
- * @param[in] pConfig Northbridge configuration pointer
- */
-VOID
-IommuPlaceIvmdAndExclusions (
- IN OUT VOID *BufferPtr,
- IN OUT AMD_NB_CONFIG *pConfig
- )
-{
- UINT8 EntryCount;
- UINT8 CurrentExclusion;
- AGESA_STATUS Status;
- IOMMU_EXCLUSIONTABLE *pExclusion;
- IOMMU_IVRS_HEADER *HeaderPtr;
- IOMMU_IVMD_ENTRY *IvmdPtr;
-
- pExclusion = &RD890S_DfltExclusion;
- HeaderPtr = (IOMMU_IVRS_HEADER *)BufferPtr;
- IvmdPtr = (IOMMU_IVMD_ENTRY *)BufferPtr;
-
- Status = LibNbCallBack (PHCB_AmdGetExclusionTable, (UINTN)&pExclusion, pConfig);
- if (Status == AGESA_SUCCESS) {
- EntryCount = (UINT8) ((pExclusion->TableLength - sizeof (UINTN)) / sizeof (IOMMU_EXCLUSIONRANGE));
- for (CurrentExclusion = 0; CurrentExclusion < EntryCount; CurrentExclusion++) {
- IvmdPtr = (IOMMU_IVMD_ENTRY*) ((UINT8*)HeaderPtr + HeaderPtr->Length);
- IvmdPtr->Type = TYPE_IVMD_ALL; // 20h = All peripherals
- IvmdPtr->Flags = 0x7; // Exclusion range
- IvmdPtr->Length = 32; // 32 byte structure
- IvmdPtr->DeviceId = 0; // Reserved for type 20h
- IvmdPtr->AuxData = 0; // Reserved for type 20h
- IvmdPtr->Reserved = 0;
- IvmdPtr->BlockStartAddress = pExclusion->ExclusionRange[CurrentExclusion].Start;
- IvmdPtr->BlockLength = pExclusion->ExclusionRange[CurrentExclusion].Length;
- HeaderPtr->Length += 32; // Update size of IVRS
- }
- }
-}
-
-/*----------------------------------------------------------------------------------------*/
-/**
- * Place IVHD (hardware device) Entry for IOMMU ACPI table
- *
- * @param[in, out] BufferPtr Pointer to text buffer to return IVRS
- * @param[in] pConfig Northbridge configuration pointer
- */
-VOID
-IommuPlaceIvhdAndScanDevices (
- IN OUT VOID *BufferPtr,
- IN OUT AMD_NB_CONFIG *pConfig
- )
-{
- UINT32 Value;
- IOMMU_PCI_TOPOLOGY PciFlags;
- IOMMU_IVRS_HEADER *HeaderPtr;
- IOMMU_IVHD_ENTRY *IvhdPtr;
- PCI_ADDR IommuPciAddress;
-
- HeaderPtr = (IOMMU_IVRS_HEADER *)BufferPtr;
- IvhdPtr = (IOMMU_IVHD_ENTRY *)BufferPtr;
- //PciFlags.PhantomFunction = FALSE;
- PciFlags.MaxBus = 0;
- PciFlags.MaxDevice = 0;
- PciFlags.MaxFunction = 0;
- IommuPciAddress = pConfig->NbPciAddress;
- IommuPciAddress.Address.Function = NB_IOMMU;
-
- IvhdPtr = (IOMMU_IVHD_ENTRY*) ((UINT8*)HeaderPtr + HeaderPtr->Length);
- IvhdPtr->Type = TYPE_IVHD; // Hardware block
- IvhdPtr->Flags = FLAGS_COHERENT | FLAGS_IOTLBSUP | FLAGS_ISOC | FLAGS_RESPASSPW | FLAGS_PASSPW;
- IvhdPtr->Length = 24; // Length = 24 with no devices
- IvhdPtr->DeviceId = (UINT16)((IommuPciAddress.AddressValue >> 12) & 0xFFFF); // Change 32 bit ID into 16 bit
- IvhdPtr->CapabilityOffset = (UINT16) (LibNbFindPciCapability (IommuPciAddress.AddressValue, IOMMU_CAPID, pConfig));
- IvhdPtr->BaseAddress = pConfig->pNbConfig->IommuBaseAddress;
- IvhdPtr->PciSegment = 0;
- LibNbPciRead (IommuPciAddress.AddressValue | (IvhdPtr->CapabilityOffset + 0x10), AccessWidth32, &Value, pConfig);
- IvhdPtr->IommuInfo = (UINT16)(Value & 0x1f); //Set MSInum.
- IvhdPtr->IommuInfo |= ((0x13) << 8); //set UnitID
- IvhdPtr->Reserved = 0;
-
- IommuIvhdNorthbridgeDevices (&PciFlags, IvhdPtr, pConfig);
- if (IommuPciAddress.Address.Bus == 0) {
- IommuIvhdSouthbridgeDevices (&PciFlags, IvhdPtr, pConfig);
- }
- IommuIvhdApicsAndHpets (IvhdPtr, pConfig);
- pConfig->pNbConfig->IommuTpologyInfo = *((UINT32*) &PciFlags);
- HeaderPtr->Length += IvhdPtr->Length;
-}
-
-/*----------------------------------------------------------------------------------------*/
-/**
- * Place IVHD Device Entries
- *
- * @param[in, out] PciPtr Pci topology flags
- * @param[in, out] IvhdPtr Pointer to IVHD where entry is appended
- * @param[in] pConfig NB config block
- */
-VOID
-IommuIvhdNorthbridgeDevices (
- IN OUT IOMMU_PCI_TOPOLOGY *PciPtr,
- IN OUT IOMMU_IVHD_ENTRY *IvhdPtr,
- IN OUT AMD_NB_CONFIG *pConfig
- )
-{
- UINT16 CurrentDevice;
- UINT16 DeviceId;
- UINT8 EntryCount;
- IOMMU_DEVICELIST *pDevices;
- PCI_ADDR NbPciAddress;
- PCI_ADDR IommuPciAddress;
-
- pDevices = &RD890S_DfltDevices;
- NbPciAddress = pConfig->NbPciAddress;
- IommuPciAddress = pConfig->NbPciAddress;
-
- IommuPciAddress.Address.Function = NB_IOMMU;
- EntryCount = (UINT8) ((pDevices->TableLength - sizeof (UINT16)) / sizeof (UINT16));
-
- // Run RD890S device table, fixed for current bus
- for (CurrentDevice = 0; CurrentDevice < EntryCount; CurrentDevice++) {
- DeviceId = (UINT16) (NbPciAddress.Address.Bus << 8) | pDevices->Device[CurrentDevice];
- IommuCreateDeviceEntry (PciPtr, DeviceId, IvhdPtr, pConfig);
-
- // CHECK HOTPLUG OR PHANTOM FUNCTION SUPPORT
- // For each device, reset PhantomEnable, but set it as a one-shot. If any device under the northbridge PCIE bridge
- // device has phantom function support enabled, set the L1. Additionally, check the bridge for hotplug, and set the
- // L1 if so.
-
- //PciPtr->PhantomFunction = FALSE;
- //if (PciPtr->PhantomFunction || IommuCheckHp (DeviceId, pConfig)) {
- // if (IommuGetL1 (DeviceId) != PCI_INVALID && LibNbGetRevisionInfo (pConfig).Revision != NB_REV_A11) {
- // // Determine from deviceID which L1
- // LibNbPciIndexRMW (IommuPciAddress.AddressValue | L1CFG_INDEX, L1CFG_SEL_WR_EN | IommuGetL1 (DeviceId), AccessS3SaveWidth32, (UINT32)~BIT0, BIT0, pConfig);
- // }
- //}
- //PciPtr->PhantomFunction = FALSE;
- }
-}
-
-/*----------------------------------------------------------------------------------------*/
-/**
- * Place IVHD Device Entries
- *
- * @param[in, out] PciPtr PCI topology flags
- * @param[in, out] IvhdPtr Pointer to IVHD where entry is appended
- * @param[in] pConfig NB config structute
- */
-VOID
-IommuIvhdSouthbridgeDevices (
- IN OUT IOMMU_PCI_TOPOLOGY *PciPtr,
- IN OUT IOMMU_IVHD_ENTRY *IvhdPtr,
- IN OUT AMD_NB_CONFIG *pConfig
- )
-{
- UINT16 DeviceId;
- PCI_ADDR IommuPciAddress;
- IommuPciAddress = pConfig->NbPciAddress;
- IommuPciAddress.Address.Function = NB_IOMMU;
-
- // Assume Device 0x10 Function 0 - Device 0x17 Function 7 belong to the SB
- //PciPtr->PhantomFunction = FALSE;
- for (DeviceId = (0x10 << 3); (DeviceId < (0x18 << 3)); DeviceId++) {
- IommuCreateDeviceEntry (PciPtr, DeviceId, IvhdPtr, pConfig);
- //if (PciPtr->PhantomFunction) {
- // // Enable SB phantom enable
- // LibNbPciIndexRMW (IommuPciAddress.AddressValue | L1CFG_INDEX, L1CFG_SEL_WR_EN | L1CFG_SEL_SB, AccessS3SaveWidth32, (UINT32)~BIT0, BIT0, pConfig);
- //}
- //PciPtr->PhantomFunction = FALSE;
- }
-
-#if defined (IVHD_APIC_SUPPORT) || defined (IVHD_HPET_SUPPORT)
- DeviceId = (SB_DEV << 3); // Bus 0 Dev 14 Func 0
-#endif
-
-#ifdef IVHD_APIC_SUPPORT
- // Southbridge IOAPIC
- IommuCreate8ByteEntry (DE_SPECIAL, DATA_ALLINTS, 0, 0xFF, DeviceId, VARIETY_IOAPIC, IvhdPtr);
-#endif
-
-#ifdef IVHD_HPET_SUPPORT
- // Southbridge HPET
- IommuCreate8ByteEntry (DE_SPECIAL, DATA_ALLINTS, 0, 0, DeviceId, VARIETY_HPET, IvhdPtr);
-#endif
-
-}
-
-/*----------------------------------------------------------------------------------------*/
-/**
- * Place IVHD Device Entries
- *
- * @param[in, out] IvhdPtr Pointer to buffer to return IVRS.
- * @param[in] pConfig NB config structute
- */
-VOID
-IommuIvhdApicsAndHpets (
- IN OUT IOMMU_IVHD_ENTRY *IvhdPtr,
- IN OUT AMD_NB_CONFIG *pConfig
- )
-{
-#ifdef IVHD_APIC_SUPPORT
- PCI_ADDR PciAddress;
- UINT16 DeviceId;
- UINT32 PciData;
-
- PciAddress = pConfig->NbPciAddress;
-
- // Northbridge IOAPIC
- DeviceId = (UINT16)((PciAddress.Address.Bus << 8)) | 1; // Bus X Dev 0 Func 0
- LibNbPciRead (PciAddress.AddressValue | 0x4C, AccessWidth32, &PciData, pConfig);
- if (PciData & (UINT32)BIT1) {
- IommuCreate8ByteEntry (DE_SPECIAL, DATA_NOINTS, 0, 0xFF, DeviceId, VARIETY_IOAPIC, IvhdPtr);
- }
-#endif
-}
-
-/*----------------------------------------------------------------------------------------*/
-/**
- * Place IVHD device entry (type 2 for single function or 3/4 for multifunction) at end of IVHD entry
- *
- * @param[in, out] PciPtr Pci topology flags
- * @param[in] DeviceId DeviceID of entry to potentially create
- * @param[in, out] IvhdPtr Pointer to IVHD
- * @param[in] pConfig NB config structute
- */
-VOID
-IommuCreateDeviceEntry (
- IN OUT IOMMU_PCI_TOPOLOGY *PciPtr,
- IN UINT16 DeviceId,
- IN OUT IOMMU_IVHD_ENTRY *IvhdPtr,
- IN AMD_NB_CONFIG *pConfig
- )
-{
- // 8 BYTE DEVICE ENTRY:
- // [0] Type (0x2 = Device, 0x3 = Device Range Start, 0x4 = Device Range End
- // [1] DeviceID LSB (Device/Function)
- // [2] DeviceID MSB (Bus)
- // [3] Data (0 = No legacy interrupts)
-
- // DEVICEID
- // A 16 bit bus/device/function DeviceId consists of:
- // [15:8] Bus
- // [7:3] Device
- // [2:0] Function
-
- PCI_ADDR PciAddress;
- UINT32 PciData;
- UINT8 DeviceCount;
- UINT8 FunctionCount;
- UINT8 PcieCapBase;
- UINT8 PcixCapBase;
-
- BOOLEAN LegacyBridge;
- BOOLEAN MultiFunction;
- BOOLEAN SubFunction;
- BOOLEAN DiscreteEntry;
- UINT8 HighFunction;
- UINT32 ClassCode;
- UINT16 ExtendedCapabilityPtr;
- SB_INFO SbInfo;
- UINT8 SataEnableRegValue;
- BOOLEAN SrIovDevice;
-
- PcieCapBase = 0;
- PcixCapBase = 0;
- LegacyBridge = FALSE;
- MultiFunction = FALSE;
- SubFunction = FALSE;
- DiscreteEntry = FALSE;
- HighFunction = 0;
- SataEnableRegValue = 0;
- SrIovDevice = FALSE;
-
- //For SB700, get combined mode status
- SbInfo = LibAmdSbGetRevisionInfo ((pConfig == NULL)?NULL:GET_BLOCK_CONFIG_PTR (pConfig));
- if (SbInfo.Type == SB_SB700) {
- LibNbPciRead (MAKE_SBDFO (0, 0, 0x14, 0, SATA_ENABLE_REG), AccessWidth8, &SataEnableRegValue , pConfig);
- }
-
-
- // If the device to check does not exist, exit
- PciAddress.AddressValue = MAKE_SBDFO (0, (DeviceId >> 8) & 0xFF, (DeviceId >> 3) & 0x1F, DeviceId & 0x7, 0);
- if (!LibNbIsDevicePresent (PciAddress, pConfig)) {
- return;
- };
- LibNbPciRead (PciAddress.AddressValue | PCI_CLASS, AccessWidth32, &ClassCode, pConfig);
- ClassCode = (ClassCode >> 16) & 0xFFFF; // Keep class code and sub-class only
-
- // THREE STAGES TO THIS FUNCTION
- // 1. Check for multifunction or special devices
- // 2. Place device entry for the current device ID
- // 3. If a bridge, decide if we need to traverse further
-
- // STEP 1 - CHECK FUNCTIONS ON THIS DEVICE
- // To make decisions, we will need several pieces of information about this device not found with current SBDFO
- // 1. Multifunction device - To determine if a device entry, or device range entry is needed - check function 0 only
- // 2. DisableRange - We will create single entries a device containing a PCI or PCIE bridge
- // 3. How many functions on this device?
-
- PciAddress.AddressValue = MAKE_SBDFO (0, (DeviceId >> 8) & 0xFF, (DeviceId >> 3) & 0x1F, 0, 0);
- LibNbPciRead (PciAddress.AddressValue | PCI_HEADER, AccessWidth32, &PciData, pConfig);
- if ((PciData & PCI_MULTIFUNCTION) != 0) {
- MultiFunction = TRUE;
- } else {
- DiscreteEntry = TRUE;
- }
- if ((DeviceId & 0x7) != 0 && MultiFunction) {
- SubFunction = TRUE;
- }
-
- if (MultiFunction) {
- for (FunctionCount = 0; FunctionCount < 8; FunctionCount++) {
- PciAddress.AddressValue = MAKE_SBDFO (0, (DeviceId >> 8) & 0xFF, (DeviceId >> 3) & 0x1F, FunctionCount, 0);
- LibNbPciRead (PciAddress.AddressValue | PCI_HEADER, AccessWidth32, &PciData, pConfig);
- if (PciData != PCI_INVALID) {
- HighFunction = FunctionCount;
- }
- LibNbPciRead (PciAddress.AddressValue | PCI_CLASS, AccessWidth32, &PciData, pConfig);
- if (((PciData >> 16) & 0xFFFF) == PCI_BRIDGE_CLASS) {
- DiscreteEntry = TRUE;
- }
- }
- }
-
- // For SR IOV devices set for all functions to be available
- if (MultiFunction && (!DiscreteEntry) && (!SubFunction)) {
- PciAddress.AddressValue = MAKE_SBDFO (0, (DeviceId >> 8) & 0xFF, (DeviceId >> 3) & 0x1F, 0, 0);
- ExtendedCapabilityPtr = LibNbFindPcieExtendedCapability (PciAddress.AddressValue, 0x10, pConfig);
- if (ExtendedCapabilityPtr != 0) {
- SrIovDevice = TRUE;
- }
- }
- // STEP 2 - PLACE DEVICE ENTRY
- // We have already decided whether we should use discrete type2 entries, or ranged type3/4 entries
- // Place each device entry at the end of the current IVHD
- // In each case, increment the maximum bus/device/function for L2 cache control done after the IVHD is created
-
- CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (pConfig), CIMX_NB_TRACE), "[NBIOMMU]Placing Entry for Device [0x%x]\n", DeviceId));
-
- //if (IommuCheckPhantom (DeviceId, pConfig)) {
- // PciPtr->PhantomFunction = TRUE;
- //}
-
- if (!MultiFunction || DiscreteEntry) {
- //For Device 0x14, function 0, Set DATA_ALLINTS
- if (DeviceId == (SB_DEV << 3)) {
- IommuCreate4ByteEntry (DE_SELECT, DATA_ALLINTS, DeviceId, IvhdPtr);
- } else if (DeviceId == DEVICEID_IDE) {
- // For IDE device 0x14, function 1, first check if in combined mode
- if (SataEnableRegValue & SATA_COMBINED_MODE) {
- // Create Alias entry in combined mode
- IommuCreate8ByteEntry (DE_ALIASSELECT, DATA_NOINTS, DEVICEID_IDE, 0, DEVICEID_SATA, 00, IvhdPtr);
- } else {
- //Create select entry if not in the combined mode
- IommuCreate4ByteEntry (DE_SELECT, 0, DeviceId, IvhdPtr);
- }
- } else {
- // For all other single function devices other than device 0x14, functions 0 or 1, create select entry
- IommuCreate4ByteEntry (DE_SELECT, 0, DeviceId, IvhdPtr);
- }
-
- // Record the largest bus, device, function which will be used as a mask by the Iommu L2 cache
- // Record if phantom device present for current device. Only set it if present, do not clear.
-// if (IommuCheckPhantom (DeviceId, pConfig)) {
-// PciPtr->PhantomFunction = TRUE;
-// }
- IommuRecordBusDevFuncInfo (PciPtr, DeviceId, pConfig);
- }
-
- if (MultiFunction && (!DiscreteEntry) && (!SubFunction)) {
-
- // This is a multifunction device without a bridge, so create a type 3 and 4 device entry
- IommuCreate4ByteEntry (DE_START, 0, DeviceId, IvhdPtr);
- if (SrIovDevice) {
- IommuCreate4ByteEntry (DE_END, 0, (DeviceId | 0x00FF), IvhdPtr);
- } else {
- IommuCreate4ByteEntry (DE_END, 0, DeviceId + HighFunction, IvhdPtr);
- }
-
- // Record the largest bus, device, function which will be used as a mask by the Iommu L2 cache
- // Record if phantom device present for current device. Only set it if present, do not clear.
-// if (IommuCheckPhantom (DeviceId, pConfig)) {
-// PciPtr->PhantomFunction = TRUE;
-// }
- IommuRecordBusDevFuncInfo (PciPtr, DeviceId + HighFunction, pConfig);
- }
-
- if (ClassCode == PCI_BRIDGE_CLASS) {
- UINTN Type;
- UINT32 BusData;
- // STEP 3 - BRIDGE DEVICE
- // These are treated a little differently. We already created the entry for the bridge itself...
- // For a PCIe bridge, continue down the bridge device creating more entries until we find an endpoint
- // For a PCI bridge, define the entire sub-bus range as belonging to this source id
- // For a PCIX bridge, figure out which mode it is operating in
- PciAddress.AddressValue = MAKE_SBDFO (0, (DeviceId >> 8) & 0xFF, (DeviceId >> 3) & 0x1F, DeviceId & 0x7, 0);
- LibNbPciRead (PciAddress.AddressValue | PCI_BUS, AccessWidth32, &BusData, pConfig);
- PcieCapBase = LibNbFindPciCapability (PciAddress.AddressValue, PCIE_CAPID, pConfig);
- PcixCapBase = LibNbFindPciCapability (PciAddress.AddressValue, PCIX_CAPID, pConfig);
-
- Type = 0;
- if (PcieCapBase != 0) {
- Type = 1;
- LibNbPciRead (PciAddress.AddressValue | PcieCapBase, AccessWidth32, &PciData, pConfig);
- PciData = (PciData >> 16) & PCIE_PORTMASK; // [7:4] are Device/Port type, 01
- if (PciData == PCIE_PCIE2PCIX) {
- Type = 2;
- }
- }
- if (PcixCapBase != 0) {
- Type = 2;
- }
-
- //For Hot plug capable devices, create 'Start of range' and 'End of range' IVRS'.
- // This will override Type 1 and Type 2.
- if (IommuCheckHp (DeviceId, pConfig)) {
- Type = 3;
- }
-
- switch (Type) {
- case 0:
- //PCI
- IommuRecordBusDevFuncInfo (PciPtr, DeviceId, pConfig);
- IommuCreate8ByteEntry (DE_ALIASSTART, DATA_NOINTS, (UINT16) (BusData & 0xFF00), 0, DeviceId, 0, IvhdPtr);
- IommuCreate4ByteEntry (DE_END, 0, (UINT16) (((BusData & 0xFF0000) >> 8) + 0xFF), IvhdPtr);
- break;
- case 1:
- //Pcie (non hot plug)
- for (DeviceCount = 0; DeviceCount <= 0x1f; DeviceCount++) {
- for (FunctionCount = 0; FunctionCount <= 0x7; FunctionCount++) {
- IommuCreateDeviceEntry (PciPtr, ((UINT16) (BusData & 0xFF00)) | (DeviceCount << 3) | FunctionCount, IvhdPtr, pConfig);
- }
- }
- break;
- case 2:
- //PCIx
- IommuRecordBusDevFuncInfo (PciPtr, (UINT16) (BusData & 0xFF00), pConfig);
- IommuCreate8ByteEntry (DE_ALIASSTART, DATA_NOINTS, (UINT16) ((BusData & 0xFF00) | ( 1 << 3)), 0, (UINT16) (BusData & 0xFF00), 0, IvhdPtr);
- IommuCreate4ByteEntry (DE_END, 0, (UINT16) (((BusData & 0xFF0000) >> 8) + 0xFF), IvhdPtr);
- break;
- case 3:
- //For Hot plug ports, set all devices and functions behind the secondary bus.
- IommuCreate4ByteEntry (DE_START, 0, (UINT16) (BusData & 0xFF00), IvhdPtr); // Secondary bus, Device 0, Function 0
- IommuCreate4ByteEntry (DE_END, 0, (UINT16) ((BusData & 0xFF00) | (0x1F << 3) | 7), IvhdPtr); // Secondary bus, Device 1f, Function 7
- break;
- default:
- CIMX_ASSERT (FALSE);
- }
- }
-}
-
-/*----------------------------------------------------------------------------------------*/
-/**
- * Place IVHD device entry (type 2 for single function or 3/4 for multifunction) at end of IVHD entry
- *
- * @param[in, out] PciPtr Pci topology flags
- * @param[in] DeviceId DeviceID
- * @param[in] pConfig NB config structute
- */
-VOID
-IommuRecordBusDevFuncInfo (
- IN OUT IOMMU_PCI_TOPOLOGY *PciPtr,
- IN UINT16 DeviceId,
- IN AMD_NB_CONFIG *pConfig
- )
-{
- UINT16 ExtendedCapabilityPtr;
- PCI_ADDR Device;
- Device.AddressValue = MAKE_SBDFO (0, DeviceId >> 8, (DeviceId >> 3) & 0x1f, DeviceId & 0x7, 0);
-#ifdef EXCLUDE_SB_DEVICE_FROM_L2_HASH
- if ((UINT8)Device.Address.Bus == 0) {
- AMD_NB_CONFIG_BLOCK *ConfigPtr = GET_BLOCK_CONFIG_PTR (pConfig);
- if (ConfigPtr->PlatformType == ServerPlatform) {
- return;
- }
- }
-#endif
- Device.AddressValue = MAKE_SBDFO (0, DeviceId >> 8, (DeviceId >> 3) & 0x1f, DeviceId & 0x7, 0);
- CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (pConfig), CIMX_NB_TRACE), " Device Data For L2 Hash Bus = 0x%x Device = 0x%x Func = 0x%x\n", Device.Address.Bus, Device.Address.Device, Device.Address.Function));
- ExtendedCapabilityPtr = LibNbFindPcieExtendedCapability (Device.AddressValue, 0x10, pConfig);
- if (ExtendedCapabilityPtr != 0) {
- UINT16 TotalVF;
- LibNbPciRead (Device.AddressValue | (ExtendedCapabilityPtr + 0xE), AccessWidth16, &TotalVF, pConfig);
- PciPtr->MaxFunction = CIMX_MAX (PciPtr->MaxFunction, TotalVF);
- }
- PciPtr->MaxBus = CIMX_MAX (PciPtr->MaxBus, (UINT8)Device.Address.Bus);
- PciPtr->MaxDevice = CIMX_MAX (PciPtr->MaxDevice, (UINT8)Device.Address.Device);
- PciPtr->MaxFunction = CIMX_MAX (PciPtr->MaxFunction, (UINT16) (UINT8)Device.Address.Function);
-}
-
-
-/*----------------------------------------------------------------------------------------*/
-/**
- * Append data entry to IVRS
- *
- * @param[in] Type IVRC entry type
- * @param[in] Data IVRC entry data
- * @param[in] Word1 IVRC entry data
- * @param[in, out] IvhdPtr Current IVHD pointer
- *
- */
-VOID
-IommuCreate4ByteEntry (
- IN UINT8 Type,
- IN UINT8 Data,
- IN UINT16 Word1,
- IN OUT IOMMU_IVHD_ENTRY *IvhdPtr
- )
-{
- UINT32 Buffer;
- UINT16 AlignedDeviceEntryIndex;
- UINT16 DeviceEntryIndex;
-
- Buffer = Type + (Word1 << 8) + (Data << 24);
- DeviceEntryIndex = (IvhdPtr->Length - 24) / sizeof (UINT32);
- AlignedDeviceEntryIndex = DeviceEntryIndex;
-
-#ifdef IVHD_MIN_8BYTE_ALIGNMENT
- AlignedDeviceEntryIndex = (DeviceEntryIndex + 1) & 0xfffe;
-#endif
-
- IvhdPtr->DeviceEntry[AlignedDeviceEntryIndex] = Buffer;
- IvhdPtr->Length += (4 + (AlignedDeviceEntryIndex - DeviceEntryIndex) * 4);
- CIMX_TRACE ((TRACE_DATA (NULL, CIMX_NB_TRACE), "[NBIOMMU]Added entry - [0x%x]\n", Buffer));
-}
-
-/*----------------------------------------------------------------------------------------*/
-/**
- * Append data entry to IVRS
- *
- * @param[in] Type IVRC entry type
- * @param[in] Data IVRC entry data
- * @param[in] Word1 IVRC entry data
- * @param[in] Byte4 IVRC entry data
- * @param[in] Word5 IVRC entry data
- * @param[in] Byte7 IVRC entry data
- * @param[in, out] IvhdPtr Current IVHD pointer
- *
- */
-VOID
-IommuCreate8ByteEntry (
- IN UINT8 Type,
- IN UINT8 Data,
- IN UINT16 Word1,
- IN UINT8 Byte4,
- IN UINT16 Word5,
- IN UINT8 Byte7,
- IN OUT IOMMU_IVHD_ENTRY *IvhdPtr
- )
-{
- UINT16 AlignedDeviceEntryIndex;
- UINT16 DeviceEntryIndex;
- UINT64 Buffer;
-
- Buffer = Type + (Word1 << 8) + ((UINT32)Data << 24);
- ((UINT32*)&Buffer)[1] = Byte4 + (Word5 << 8) + (Byte7 << 24);
- DeviceEntryIndex = (IvhdPtr->Length - 24) / sizeof (UINT32);
- AlignedDeviceEntryIndex = DeviceEntryIndex;
-
-#if defined (IVHD_MIN_8BYTE_ALIGNMENT) || defined (IVHD_SIZE_ALIGNMENT)
- AlignedDeviceEntryIndex = (DeviceEntryIndex + 1) & 0xfffe;
-#endif
- IvhdPtr->DeviceEntry[AlignedDeviceEntryIndex] = ((UINT32*)&Buffer)[0];
- IvhdPtr->DeviceEntry[AlignedDeviceEntryIndex + 1] = ((UINT32*)&Buffer)[1];
- IvhdPtr->Length += (8 + (AlignedDeviceEntryIndex - DeviceEntryIndex) * 4);
- CIMX_TRACE ((TRACE_DATA (NULL, CIMX_NB_TRACE), "[NBIOMMU]Added entry - [0x%llx]\n", Buffer));
-}
-
-/*----------------------------------------------------------------------------------------*/
-/**
- * Set checksum, IvInfo, finish IVRS table
- *
- * @param[in, out] BufferPtr Pointer to text buffer to return IVRS.
- * @param[in, out] pConfig Northbridge configuration structure pointer.
- *
- */
-VOID
-IommuFinalizeIvrs (
- IN OUT VOID *BufferPtr,
- IN AMD_NB_CONFIG *pConfig
- )
-{
- IOMMU_IVRS_HEADER *HeaderPtr;
- PCI_ADDR IommuPciAddress;
- UINT32 PciData;
-
- HeaderPtr = (IOMMU_IVRS_HEADER *)BufferPtr;
- IommuPciAddress = pConfig->NbPciAddress;
- IommuPciAddress.Address.Function = NB_IOMMU;
-
- // Find common IvInfo (largest shared) 0x50
- // [22] = ATS Translation Reserved
- // [21:15] = VA Size
- // [14:8] = PA Size
-
- LibNbPciRead (IommuPciAddress.AddressValue | RD890S_CAP_MISC, AccessWidth32, &PciData, pConfig);
- PciData &= (IVINFO_ATSMASK | IVINFO_VAMASK | IVINFO_PAMASK);
- HeaderPtr->IvInfo = PciData;
-
- //LibAmdUpdateAcpiTableChecksum (HeaderPtr);
-}
-
-/*----------------------------------------------------------------------------------------*/
-/**
- * Nb Iommu Fixup of IVRS APIC entries
- *
- * @param[in] DevicePtr Pointer to current device entry
- * @param[in] pConfig Northbridge configuration structure pointer.
- *
- */
-UINT64
-IommuGetApicBaseAddress (
- IN VOID *DevicePtr,
- IN AMD_NB_CONFIG *pConfig
- )
-{
- PCI_ADDR PciAddress;
- UINT16 DeviceId;
- UINT32 Data;
-
- // If no pointer provided, return no base address
- if (DevicePtr == NULL) {
- return 0;
- }
-
- // Special entry can be IOAPIC or other(HPET). We only care about the IOAPIC.
- if (*(UINT8*) ((UINT8*)DevicePtr + DE_SPECIAL_VARIETY) != VARIETY_IOAPIC) {
- return 0;
- }
-
- DeviceId = *(UINT16*) ((UINT8*)DevicePtr + DE_DEVICEID);
- PciAddress.AddressValue = MAKE_SBDFO (0, (DeviceId >> 8) & 0xFF, (DeviceId >> 3) & 0x1F, 0, 0);
-
- // An APIC entry will only be created for AMD northbridge or southbridges, so
- // we can assume PCI dev/func = 0, 0 will be a northbridge IOAPIC device
- // and any other will be a southbridge IOAPIC device. If the device was not
- // already enabled and known to be an AMD device, no entry would have been created.
-
- if ((PciAddress.Address.Device == NB_PCI_DEV) && (PciAddress.Address.Function == NB_HOST)) {
-
- // We have an AMD NB, check function 0
- Data = 1;
- PciAddress.Address.Function = 0;
- LibNbPciWrite (PciAddress.AddressValue | 0xF8, AccessS3SaveWidth32, &Data, pConfig);
- LibNbPciRead (PciAddress.AddressValue | 0xFC, AccessWidth32, &Data, pConfig);
- } else {
- SB_INFO SbInfo;
- SbInfo = LibAmdSbGetRevisionInfo ((pConfig == NULL)?NULL:GET_BLOCK_CONFIG_PTR (pConfig));
- if (SbInfo.Type == SB_SB700) {
- PciAddress.Address.Function = 0;
- LibNbPciRead (PciAddress.AddressValue | 0x74, AccessWidth32, &Data, pConfig);
- } else {
- LibAmdSbPmioRead ( 0x34, AccessWidth32, &Data, pConfig);
- }
- }
- return ((UINT64) (Data & 0xFFFFFF00));
-}
-
-/*----------------------------------------------------------------------------------------*/
-/**
- * Nb Iommu Fixup of IVRS APIC entries
- *
- * @param[in] BaseAddress Base address to match
- * @param[in] MadtPtr Pointer to current device entry
- * @param[in] pConfig Northbridge configuration structure pointer.
- *
- */
-UINT8
-IommuGetApicId (
- IN UINT64 BaseAddress,
- IN VOID *MadtPtr,
- IN AMD_NB_CONFIG *pConfig
- )
-{
- VOID *EntryPtr;
-
- EntryPtr = LibAmdGetFirstMadtStructure (MADT_APIC_TYPE, MadtPtr);
-
- do {
- // If our base address for a known device matches this MADT, get the APIC ID
- if (*(UINT32*) ((UINT8*)EntryPtr + MADT_APIC_BASE) == (UINT32)BaseAddress) {
- return *(UINT8*) ((UINT8*)EntryPtr + MADT_APIC_ID);
- }
- EntryPtr = LibAmdGetNextMadtStructure (MADT_APIC_TYPE, EntryPtr, MadtPtr);
- } while (EntryPtr != NULL);
- return 0xFF;
-}
-
-/*----------------------------------------------------------------------------------------*/
-/**
- * Disconnect unused PCIe core from IOMMU block.
- *
- * @param[in] CoreId Pcie Core Id
- * @param[in] pConfig Northbridge configuration structure pointer.
- *
- */
-VOID
-NbIommuDisconnectPcieCore (
- IN CORE CoreId,
- IN AMD_NB_CONFIG *pConfig
- )
-{
- PCI_ADDR IommuPciAddress;
- UINT32 Value;
- IommuPciAddress = pConfig->NbPciAddress;
- IommuPciAddress.Address.Function = NB_IOMMU;
- Value = 1 << ((0x4310 >> (CoreId * 4)) & 0xf);
- LibNbPciIndexRMW (IommuPciAddress.AddressValue | L2CFG_INDEX, L2CFG_SEL_WR_EN | L2REG_46, AccessS3SaveWidth32, 0xFFFFFFFF, Value , pConfig);
-}