blob: 7fc2c5c90897e4ee56ca10eaa504677a05ae3a35 [file] [log] [blame]
/**
* @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.
*
*
***************************************************************************/
// Identifying an IOMMU:
// RD890S - IOMMU present
// all other (including RD890) - IOMMU not present
// Class = System Base Peripheral (08h)
// Subclass = IOMMU (06h)
// Programming Interface Code = 0h
// Must reside on top/root complex PCI hierarchy
// There is always a NB device at bus 0 device 0 function 0 (fcn 2 for IOMMU) - device ID 0x5A23
// Inputs:
// From OEM: Get exclusion table
// From OEM: Get text buffer
// Outputs:
// To OEM: Complete IVRS table for linking
#ifndef _NBIOMMU_H_
#define _NBIOMMU_H_
/*----------------------------------------------------------------------------------------
* E X P O R T E D F U N C T I O N S
*----------------------------------------------------------------------------------------
*/
AGESA_STATUS
NbIommuInit (
IN OUT AMD_NB_CONFIG_BLOCK *ConfigPtr
);
AGESA_STATUS
NbIommuInitS3 (
IN OUT AMD_NB_CONFIG_BLOCK *ConfigPtr
);
AGESA_STATUS
NbIommuAcpiInit (
IN OUT AMD_NB_CONFIG_BLOCK *ConfigPtr
);
AGESA_STATUS
NbIommuAcpiFixup (
IN OUT AMD_NB_CONFIG_BLOCK *ConfigPtr
);
VOID
NbIommuDisconnectPcieCore (
IN CORE CoreId,
IN AMD_NB_CONFIG *pConfig
);
/*----------------------------------------------------------------------------------------
* D E F I N I T I O N S A N D M A C R O S
*----------------------------------------------------------------------------------------
*/
// IOMMU Architectural
#define IVRS_BUFFER_SIZE 0x2000 // Default 8KB allocated to table
//#define IVHD_MIN_8BYTE_ALIGNMENT // Align IVHD entries on 8 byte boundary
#define IVHD_SIZE_ALIGNMENT // Align IVHD entries on MOD entry-size boundary
#define IVHD_HPET_SUPPORT // Create HPET entries
#define IVHD_APIC_SUPPORT // Create IOAPIC entries
// IOMMU Northbridge
#define RD890S_CAP_MISC 0x50 // RD890/S Capabilities Misc Info
#define NB_PCI_DEV 0 // PCI NB device number
#define NB_HOST 0 // Function 0 = NB HOST
#define NB_IOMMU 2 // Function 2 = IOMMU
#define SB_DEV 0x14 // PCI SB device number
#define SB_SMBUS 3 // Function 3 = SMBUS
#define SB_SATA 0x11 // SB SATA
#define SATA_ENABLE_REG 0xAD // Dev. 0x14, Func 0, Reg 0xAD for SATA combined mode
#define SATA_COMBINED_MODE BIT3 // Bit 3 of SB_ENABLE_REG., 1 = Combined mode
#define IOMMU_CAP_HEADER_OFFSET 0x00
#define IOMMU_BASE_LOW_OFFSET 0x04
#define IOMMU_BASE_HIGH_OFFSET 0x08
#define IOMMU_RANGE_OFFSET 0x0C
#define IOMMU_MISC_OFFSET 0x10
#define DEVICEID_NB ((0 << 8) + (NB_PCI_DEV << 3) + NB_HOST)
#define DEVICEID_IOMMU ((0 << 8) + (NB_PCI_DEV << 3) + NB_IOMMU)
#define DEVICEID_GPP1_0 ((0 << 8) + (0x2 << 3) + 0)
#define DEVICEID_GPP1_1 ((0 << 8) + (0x3 << 3) + 0)
#define DEVICEID_GPP2_0 ((0 << 8) + (0xB << 3) + 0)
#define DEVICEID_GPP2_1 ((0 << 8) + (0xC << 3) + 0)
#define DEVICEID_GPP3A_0 ((0 << 8) + (0x4 << 3) + 0)
#define DEVICEID_GPP3A_1 ((0 << 8) + (0x5 << 3) + 0)
#define DEVICEID_GPP3A_2 ((0 << 8) + (0x6 << 3) + 0)
#define DEVICEID_GPP3A_3 ((0 << 8) + (0x7 << 3) + 0)
#define DEVICEID_GPP3A_4 ((0 << 8) + (0x9 << 3) + 0)
#define DEVICEID_GPP3A_5 ((0 << 8) + (0xA << 3) + 0)
#define DEVICEID_GPP3B_0 ((0 << 8) + (0xD << 3) + 0)
#define DEVICEID_SATA ((0 << 8) + (0x11 << 3) + 0)
#define DEVICEID_IDE ((0 << 8) + (0x14 << 3) + 1)
#define L1CFG_INDEX 0xF8
// There is an L1 for each device (6), which is selected by [19:16] of L1CFG_INDEX
// e.g. (LibNbPciIndexRead (Address | L1CFGIND, L1_REG_0C | L1_CFG_SEL, AccessWidth32, &Value, pConfig)
#define L1CFG_SEL_WR_EN 0x80000000
#define L1CFG_SEL_GPP1 0x00000000
#define L1CFG_SEL_GPP2 0x00010000
#define L1CFG_SEL_SB 0x00020000
#define L1CFG_SEL_GPP3A 0x00030000
#define L1CFG_SEL_GPP3B 0x00040000
#define L1CFG_SEL_VC1 0x00050000
#define L1REG_06 0x6
#define L1REG_0C 0xC
#define L1REG_0D 0xD
#define L1REG_07 0x7
#define L1CFG_DATA 0xFC
#define L2CFG_INDEX 0xF0
// e.g. (LibNbPciIndexRead (Address | L2CFGIND, L2_REG_0C, AccessWidth16, &Value, pConfig)
#define L2CFG_SEL_WR_EN 0x100
#define L2REG_06 0x6
#define L2REG_07 0x7
#define L2REG_0C 0xC
#define L2REG_10 0x10
#define L2REG_11 0x11
#define L2REG_14 0x14
#define L2REG_15 0x15
#define L2REG_18 0x18
#define L2REG_19 0x19
#define L2REG_1C 0x1C
#define L2REG_1D 0x1D
#define L2REG_46 0x46
#define L2REG_47 0x47
#define L2REG_50 0x50
#define L2REG_51 0x51
#define L2REG_52 0x52
#define L2REG_56 0x56
#define L2REG_30 0x30
#define L2REG_80 0x80
#define L2CFG_DATA 0xF4
// PCI/PCIe Architectural
#define PCIE_CAPID 0x10
#define PCIE_PORTMASK 0xF0 // Device cap reg 2
#define PCIE_PCIE2PCIX 0x70 // Device cap reg 2
#define PCIE_PHANTOMMASK 0x18 // Device cap reg 4
#define PCIX_CAPID 0x07
#define IOMMU_CAPID 0x0F
#define PCI_DVID 0x00
#define PCI_INVALID 0xFFFFFFFF
#define PCI_CLASS 0x08
#define PCI_HEADER 0x0C
#define PCI_MULTIFUNCTION 0x00800000
#define PCI_BUS 0x18
#define PCI_SUBMASK 0xFF0000
#define PCI_SECMASK 0xFF00
#define PCI_PRIMASK 0xFF
#define PCI_BRIDGE_CLASS 0x0604
// IVRS Table Access
#define TYPE_IVHD 0x10
#define IVINFO_ATSMASK 0x00400000 // [22] = ATS
#define IVINFO_VAMASK 0x003F8000 // [21:15] = Virtual Address Size
#define IVINFO_PAMASK 0x00007F00 // [14:8] = Physical Address Size
#define FLAGS_COHERENT BIT5
#define FLAGS_IOTLBSUP BIT4
#define FLAGS_ISOC BIT3
#define FLAGS_RESPASSPW BIT2
#define FLAGS_PASSPW BIT1
#define TYPE_IVMD_ALL 0x20
#define TYPE_IVMD_SELECT 0x21
#define TYPE_IVMD_RANGE 0x22
#define DE_PAD4 1
#define DE_BYTE0 0
#define DE_BYTE1 1
#define DE_BYTE2 2
#define DE_BYTE3 3
#define DE_SELECT 2
#define DATA_NOINTS 0
#define DATA_LINT_EINT_INIT BIT7 + BIT6 + BIT1 + BIT0
#define DATA_ALLINTS 0xD7
#define DE_START 3
#define DE_END 4
#define DE_PAD8 64
#define DE_BYTE4 4
#define DE_BYTE5 5
#define DE_BYTE6 6
#define DE_BYTE7 7
#define DE_ALIASSELECT 66
#define DE_ALIASSTART 67
#define DE_SPECIAL 72
#define VARIETY_IOAPIC 0x1
#define VARIETY_HPET 0x2
#define DE_SPECIAL_VARIETY 7
#define DE_DEVICEID 5
#define DE_SPECIAL_ID 4
// MADT Table Access
#define MADT_APIC_TYPE 0x1
#define MADT_APIC_ID 0x2
#define MADT_APIC_BASE 0x4
/*----------------------------------------------------------------------------------------
* T Y P E D E F S A N D S T R U C T U R E S
*----------------------------------------------------------------------------------------
*/
#pragma pack (push, 1)
/// IVRS header
typedef struct {
UINT32 Signature; ///< see IOMMU specification for details
UINT32 Length; ///< see IOMMU specification for details
UINT8 Revision; ///< see IOMMU specification for details
UINT8 Checksum; ///< see IOMMU specification for details
CHAR8 OemId[6]; ///< see IOMMU specification for details
CHAR8 OemTableId[8]; ///< see IOMMU specification for details
CHAR8 OemRevision[4]; ///< see IOMMU specification for details
CHAR8 CreatorId[4]; ///< see IOMMU specification for details
CHAR8 CreatorRevision[4]; ///< see IOMMU specification for details
UINT32 IvInfo; ///< see IOMMU specification for details
UINT64 Reserved; ///< see IOMMU specification for details
} IOMMU_IVRS_HEADER;
/// DeviceID
typedef struct {
UINT16 TableLength; ///< length of table
UINT16 Device[]; ///< DeviceID
} IOMMU_DEVICELIST;
/// PCI Topology Based Settings
typedef struct {
// BOOLEAN PhantomFunction; ///< phantom functions present
UINT8 MaxBus; ///< max bus accumulator
UINT8 MaxDevice; ///< max device accumulator
UINT16 MaxFunction; ///< max function accumulator
} IOMMU_PCI_TOPOLOGY;
/// IVHD for each hardware definition (i.e. # of northbridges)
typedef struct {
UINT8 Type; ///< see IOMMU specification for details
UINT8 Flags; ///< see IOMMU specification for details
UINT16 Length; ///< see IOMMU specification for details
UINT16 DeviceId; ///< see IOMMU specification for details
UINT16 CapabilityOffset; ///< see IOMMU specification for details
UINT64 BaseAddress; ///< see IOMMU specification for details
UINT16 PciSegment; ///< see IOMMU specification for details
UINT16 IommuInfo; ///< see IOMMU specification for details
UINT32 Reserved; ///< see IOMMU specification for details
UINT32 DeviceEntry[]; ///< see IOMMU specification for details
} IOMMU_IVHD_ENTRY;
/// IVMD for each memory range
typedef struct {
UINT8 Type; ///< see IOMMU specification for details
UINT8 Flags; ///< see IOMMU specification for details
UINT16 Length; ///< see IOMMU specification for details
UINT16 DeviceId; ///< see IOMMU specification for details
UINT16 AuxData; ///< see IOMMU specification for details
UINT64 Reserved; ///< see IOMMU specification for details
UINT64 BlockStartAddress; ///< see IOMMU specification for details
UINT64 BlockLength; ///< see IOMMU specification for details
} IOMMU_IVMD_ENTRY;
//#define IVRS_HANDLE 'SRVI'
#define IVRS_HANDLE Int32FromChar ('S', 'R', 'V', 'I')
#define L2_DTC_CONTROL 0x10
#define L2_ITC_CONTROL 0x14
#define L2_PTC_A_CONTROL 0x18
#define L2_PTC_B_CONTROL 0x1C
#define L2_PDC_CONTROL 0x50
#define EXCLUDE_SB_DEVICE_FROM_L2_HASH
/// L2 cache init
typedef struct {
UINT8 HashControl; ///<Control regsiter block address
} L2_HASH_CONTROL;
#pragma pack (pop)
#endif