acpi: acpi_table: Add IORT support

The SoC can implement acpi_fill_iort to update the IORT table.
Add a helper function to fill out the NAMED_COMPONENT node.

TEST=Run FWTS V24.03.00 on RPi4 and round no problems.

Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Cc: Simon Glass <sjg@chromium.org>
This commit is contained in:
Patrick Rudolph
2024-10-23 15:19:54 +02:00
committed by Tom Rini
parent 7f91bcac1e
commit bf5d37662d
2 changed files with 426 additions and 0 deletions

View File

@@ -832,6 +832,117 @@ struct acpi_pptt_cache {
u16 line_size;
} __packed;
/** IORT - IO Remapping Table revision 6
* Document number: ARM DEN 0049E.e, Sep 2022
*/
struct acpi_table_iort {
struct acpi_table_header header;
u32 node_count;
u32 node_offset;
u32 reserved;
} __packed;
/*
* IORT subtables
*/
struct acpi_iort_node {
u8 type;
u16 length;
u8 revision;
u32 identifier;
u32 mapping_count;
u32 mapping_offset;
char node_data[];
} __packed;
/* 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 */
struct acpi_iort_its_group {
u32 its_count;
u32 identifiers[]; /* GIC ITS identifier array */
} __packed;
/* PCI root complex node revision 2 */
struct acpi_iort_rc {
u64 mem_access_properties;
u32 ats_attributes;
u32 pci_segment_number;
u8 memory_address_size_limit;
u8 reserved[3];
} __packed;
/* SMMUv3 revision 5 */
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;
/* 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)
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;
/* Masks for Flags field above for IORT subtable */
#define ACPI_IORT_ID_SINGLE_MAPPING (1)
/* Named Component revision 4 */
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;
/* Masks for Flags field above */
#define ACPI_IORT_NC_STALL_SUPPORTED (1)
#define ACPI_IORT_NC_PASID_BITS (31 << 1)
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;
/* 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 */
/* Tables defined/reserved by ACPI and generated by U-Boot */
enum acpi_tables {
ACPITAB_BERT,
@@ -1000,6 +1111,108 @@ int acpi_fill_csrt(struct acpi_ctx *ctx);
*/
void acpi_fill_fadt(struct acpi_fadt *fadt);
/**
* acpi_fill_iort() - Fill out the body of the IORT table
*
* Should be implemented in SoC specific code.
*
* @ctx: ACPI context to write to
* @offset: Offset from the start of the IORT
*/
int acpi_fill_iort(struct acpi_ctx *ctx);
/**
* acpi_iort_add_its_group() - Add ITS group node to IORT table
*
* Called by SoC specific code within acpi_fill_iort().
*
* @ctx: ACPI context to write to
* @its_count: Elements in identifiers
* @identifiers: The array of ITS identifiers. These IDs must match the value
* used in the Multiple APIC Description Table (MADT) GIC ITS
* structure for each relevant ITS unit.
* @return Offset of table within parent
*/
int acpi_iort_add_its_group(struct acpi_ctx *ctx,
const u32 its_count,
const u32 *identifiers);
/**
* acpi_iort_add_named_component() - Add named component to IORT table
*
* Called by SoC specific code within acpi_fill_iort().
*
* @ctx: ACPI context to write to
* @node_flags: Node flags
* @memory_properties: Memory properties
* @memory_address_limit: Memory address limit
* @device_name: ACPI device path
* @return Offset of table within parent
*/
int acpi_iort_add_named_component(struct acpi_ctx *ctx,
const u32 node_flags,
const u64 memory_properties,
const u8 memory_address_limit,
const char *device_name);
/**
* acpi_iort_add_rc() - Add PCI root complex node to IORT table
*
* Called by SoC specific code within acpi_fill_iort().
*
* @ctx: ACPI context to write to
* @mem_access_properties: Memory access properties
* @ats_attributes: Support for ATS and its ancillary feature
* @pci_segment_number: The PCI segment number, as in MCFG
* @memory_address_size_limit: The number of address bits, starting from LSB
* @num_mappings: Number of elements in map
* @map: ID mappings for this node
* @return Offset of table within parent
*/
int acpi_iort_add_rc(struct acpi_ctx *ctx,
const u64 mem_access_properties,
const u32 ats_attributes,
const u32 pci_segment_number,
const u8 memory_address_size_limit,
const int num_mappings,
const struct acpi_iort_id_mapping *map);
/**
* acpi_iort_add_smmu_v3() - Add PCI root complex node to IORT table
*
* Called by SoC specific code within acpi_fill_iort().
*
* @ctx: ACPI context to write to
* @base_address: Base address of SMMU
* @flags: SMMUv3 flags
* @vatos_address: Optional, set to zero if not supported
* @model: Model ID
* @event_gsiv: GSIV of the Event interrupt if SPI based
* @pri_gsiv: GSIV of the PRI interrupt if SPI based
* @gerr_gsiv: GSIV of the GERR interrupt if GSIV based
* @sync_gsiv: TGSIV of the Sync interrupt if GSIV based
* @pxm: Proximity Domain
* @id_mapping_index: If all the SMMU control interrupts are GSIV based,
* this field is ignored. Index into the array of ID
* mapping otherwise.
* @num_mappings: Number of elements in map
* @map: ID mappings for this node
* @return Offset of table within parent
*/
int acpi_iort_add_smmu_v3(struct acpi_ctx *ctx,
const u64 base_address,
const u32 flags,
const u64 vatos_address,
const u32 model,
const u32 event_gsiv,
const u32 pri_gsiv,
const u32 gerr_gsiv,
const u32 sync_gsiv,
const u32 pxm,
const u32 id_mapping_index,
const int num_mappings,
const struct acpi_iort_id_mapping *map);
/**
* acpi_fill_madt() - Fill out the body of the MADT
*