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>
diff --git a/include/acpi/acpi_table.h b/include/acpi/acpi_table.h
index 7ee3248..5a30465 100644
--- a/include/acpi/acpi_table.h
+++ b/include/acpi/acpi_table.h
@@ -832,6 +832,117 @@
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,
@@ -1001,6 +1112,108 @@
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
*
* Must be implemented in SoC specific code.