diff --git a/src/acpi/Kconfig b/src/acpi/Kconfig index cf51969e41..83d18bf62f 100644 --- a/src/acpi/Kconfig +++ b/src/acpi/Kconfig @@ -86,6 +86,12 @@ config ACPI_GTDT help Selected by platforms that implement ARM generic timers +config ACPI_IORT + def_bool n + depends on ARCH_ARM64 && HAVE_ACPI_TABLES + help + Selected by platforms that implement ARM IO Remap table. + config MAX_ACPI_TABLE_SIZE_KB int default 144 diff --git a/src/acpi/acpi.c b/src/acpi/acpi.c index c4d55ab453..f9e9162545 100644 --- a/src/acpi/acpi.c +++ b/src/acpi/acpi.c @@ -14,6 +14,7 @@ */ #include +#include #include #include #include @@ -1194,6 +1195,26 @@ unsigned long acpi_gtdt_add_watchdog(unsigned long current, uint64_t refresh_fra return current + sizeof(struct acpi_gtdt_watchdog); } +static void acpi_create_iort(acpi_header_t *header, void *unused) +{ + if (!CONFIG(ACPI_IORT)) + return; + + acpi_iort_t *iort = (acpi_iort_t *)header; + unsigned long current = (unsigned long)iort + sizeof(acpi_iort_t); + + if (acpi_fill_header(header, "IORT", IORT, sizeof(acpi_iort_t)) != CB_SUCCESS) + return; + + iort->node_count = 0; + iort->node_offset = current - (unsigned long)iort; + + current = acpi_soc_fill_iort(iort, current); + + /* (Re)calculate length */ + header->length = current - (unsigned long)iort; +} + unsigned long acpi_create_lpi_desc_ncst(acpi_lpi_desc_ncst_t *lpi_desc, uint16_t uid) { memset(lpi_desc, 0, sizeof(acpi_lpi_desc_ncst_t)); @@ -1409,6 +1430,7 @@ unsigned long write_acpi_tables(const unsigned long start) { acpi_create_spcr, NULL, sizeof(acpi_spcr_t) }, { acpi_create_gtdt, NULL, sizeof(acpi_gtdt_t) }, { acpi_create_pptt, NULL, sizeof(acpi_pptt_t) }, + { acpi_create_iort, NULL, sizeof(acpi_iort_t) }, }; current = start; @@ -1760,6 +1782,8 @@ int get_acpi_table_revision(enum acpi_tables table) return 3; case PPTT: /* ACPI 6.4 */ return 3; + case IORT: /* IO Remapping Table E.e */ + return 6; default: return -1; } diff --git a/src/include/acpi/acpi.h b/src/include/acpi/acpi.h index a298e39143..b405e20431 100644 --- a/src/include/acpi/acpi.h +++ b/src/include/acpi/acpi.h @@ -105,6 +105,7 @@ enum acpi_tables { XSDT, /* Extended System Description Table */ /* Additional proprietary tables used by coreboot */ CRAT, /* Component Resource Attribute Table */ + IORT, /* Input Output Remapping Table */ NHLT, /* Non HD audio Link Table */ SPMI, /* Server Platform Management Interface table */ VFCT /* VBIOS Fetch Table */ diff --git a/src/include/acpi/acpi_iort.h b/src/include/acpi/acpi_iort.h new file mode 100644 index 0000000000..74a520d6a6 --- /dev/null +++ b/src/include/acpi/acpi_iort.h @@ -0,0 +1,113 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef __ACPI_IORT_H__ +#define __ACPI_IORT_H__ + +#include +#include + +/* IORT - IO Remapping Table revision 6 + * Document number: ARM DEN 0049E.e, Sep 2022 + */ +typedef struct acpi_table_iort { + acpi_header_t header; /* Common ACPI table header */ + u32 node_count; + u32 node_offset; + u32 reserved; +} __packed acpi_iort_t; + +/* + * IORT subtables + */ +typedef struct acpi_iort_node { + u8 type; + u16 length; + u8 revision; + u32 identifier; + u32 mapping_count; + u32 mapping_offset; + char node_data[]; +} __packed acpi_iort_node_t; + +/* Values for subtable Type above */ +enum acpi_iort_node_type { + ACPI_IORT_NODE_ITS_GROUP = 0x00, + ACPI_IORT_NODE_NAMED_COMPONENT = 0x01, + ACPI_IORT_NODE_PCI_ROOT_COMPLEX = 0x02, + ACPI_IORT_NODE_SMMU = 0x03, + ACPI_IORT_NODE_SMMU_V3 = 0x04, + ACPI_IORT_NODE_PMCG = 0x05, + ACPI_IORT_NODE_RMR = 0x06, +}; + +/* ITS Group revision 1 */ +typedef struct acpi_iort_its_group { + u32 its_count; + u32 identifiers[]; /* GIC ITS identifier array */ +} __packed acpi_iort_its_group_t; + +/* SMMUv3 revision 5 */ +typedef struct acpi_iort_smmu_v3 { + u64 base_address; /* SMMUv3 base address */ + u32 flags; + u32 reserved; + u64 vatos_address; + u32 model; + u32 event_gsiv; + u32 pri_gsiv; + u32 gerr_gsiv; + u32 sync_gsiv; + u32 pxm; + u32 id_mapping_index; +} __packed acpi_iort_smmu_v3_t; + +/* Masks for Flags field above */ +#define ACPI_IORT_SMMU_V3_COHACC_OVERRIDE (1) +#define ACPI_IORT_SMMU_V3_HTTU_OVERRIDE (3<<1) +#define ACPI_IORT_SMMU_V3_PXM_VALID (1<<3) +#define ACPI_IORT_SMMU_V3_DEVICEID_VALID (1<<4) + +typedef struct acpi_iort_id_mapping { + u32 input_base; /* Lowest value in input range */ + u32 id_count; /* Number of IDs */ + u32 output_base; /* Lowest value in output range */ + u32 output_reference; /* A reference to the output node */ + u32 flags; +} __packed acpi_iort_id_mapping_t; + +/* Masks for Flags field above for IORT subtable */ +#define ACPI_IORT_ID_SINGLE_MAPPING (1) + +/* Named Component revision 4 */ +typedef struct acpi_iort_named_component { + u32 node_flags; + u64 memory_properties; /* Memory access properties */ + u8 memory_address_limit; /* Memory address size limit */ + char device_name[]; /* Path of namespace object */ +} __packed acpi_iort_named_component_t; + +/* Masks for Flags field above */ +#define ACPI_IORT_NC_STALL_SUPPORTED (1) +#define ACPI_IORT_NC_PASID_BITS (31<<1) + +typedef struct acpi_iort_root_complex { + u64 memory_properties; /* Memory access properties */ + u32 ats_attribute; + u32 pci_segment_number; + u8 memory_address_limit;/* Memory address size limit */ + u16 pasid_capabilities; /* PASID Capabilities */ + u8 reserved; /* Reserved, must be zero */ + u32 flags; /* Flags */ +} __packed acpi_iort_root_complex_t; + +/* Masks for ats_attribute field above */ +#define ACPI_IORT_ATS_SUPPORTED (1) /* The root complex ATS support */ +#define ACPI_IORT_PRI_SUPPORTED (1<<1) /* The root complex PRI support */ +#define ACPI_IORT_PASID_FWD_SUPPORTED (1<<2) /* The root complex PASID forward support */ + +/* Masks for pasid_capabilities field above */ +#define ACPI_IORT_PASID_MAX_WIDTH (0x1F) /* Bits 0-4 */ + +unsigned long acpi_soc_fill_iort(acpi_iort_t *iort, unsigned long current); + +#endif