summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/acpi/Makefile.mk1
-rw-r--r--src/acpi/acpi_iort.c156
-rw-r--r--src/include/acpi/acpi_iort.h22
3 files changed, 179 insertions, 0 deletions
diff --git a/src/acpi/Makefile.mk b/src/acpi/Makefile.mk
index e9d5cb0fda..46801d41e9 100644
--- a/src/acpi/Makefile.mk
+++ b/src/acpi/Makefile.mk
@@ -10,6 +10,7 @@ ramstage-y += acpi_hpet.c
ramstage-y += acpigen_pci_root_resource_producer.c
endif
ramstage-$(CONFIG_ACPI_PPTT) += acpi_pptt.c
+ramstage-$(CONFIG_ACPI_IORT) += acpi_iort.c
ramstage-y += acpigen.c
ramstage-y += acpigen_dptf.c
ramstage-y += acpigen_dsm.c
diff --git a/src/acpi/acpi_iort.c b/src/acpi/acpi_iort.c
new file mode 100644
index 0000000000..5e2263df34
--- /dev/null
+++ b/src/acpi/acpi_iort.c
@@ -0,0 +1,156 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <acpi/acpi.h>
+#include <acpi/acpi_iort.h>
+#include <assert.h>
+
+unsigned long acpi_iort_its_entry(unsigned long current, acpi_iort_t *iort,
+ acpi_iort_node_t **its_out, u32 its_count, u32 *identifiers)
+{
+ acpi_iort_its_group_t *its_node_data;
+ acpi_iort_node_t *its = (acpi_iort_node_t *)current;
+ const unsigned long its_start = current;
+
+ ASSERT(its_out);
+ current += sizeof(*its) + sizeof(*its_node_data);
+ memset(its, 0, current - its_start);
+
+ its->type = ACPI_IORT_NODE_ITS_GROUP;
+ its->revision = 1;
+ its->identifier = iort->node_count++;
+
+ its_node_data = (acpi_iort_its_group_t *)its->node_data;
+ its_node_data->its_count = its_count;
+
+ for (int i = 0; i < its_count; i++)
+ its_node_data->identifiers[i] = identifiers[i];
+
+ current += its_node_data->its_count * sizeof(its_node_data->identifiers[0]);
+ its->length = current - its_start;
+
+ *its_out = its;
+
+ return current;
+}
+
+unsigned long acpi_iort_smmuv3_entry(unsigned long current, acpi_iort_t *iort,
+ acpi_iort_node_t **smmu_v3_out, u64 base, u32 flags)
+{
+ acpi_iort_smmu_v3_t *smmu_v3_node_data;
+ acpi_iort_node_t *smmu_v3 = (acpi_iort_node_t *)current;
+ const unsigned long smmu_v3_start = current;
+
+ ASSERT(smmu_v3_out);
+ current += sizeof(*smmu_v3) + sizeof(*smmu_v3_node_data);
+ memset(smmu_v3, 0, current - smmu_v3_start);
+
+ smmu_v3->type = ACPI_IORT_NODE_SMMU_V3;
+ smmu_v3->revision = 0x5;
+ smmu_v3->identifier = iort->node_count++; // Unique identifier.
+ smmu_v3->mapping_offset = current - smmu_v3_start;
+
+ /* length is further updated by id map entries */
+ smmu_v3->length = smmu_v3->mapping_offset;
+
+ smmu_v3_node_data = (acpi_iort_smmu_v3_t *)smmu_v3->node_data;
+ smmu_v3_node_data->base_address = base;
+ smmu_v3_node_data->flags = flags;
+
+ *smmu_v3_out = smmu_v3;
+
+ return current;
+}
+
+unsigned long acpi_iort_nc_entry(unsigned long current, acpi_iort_t *iort,
+ acpi_iort_node_t **nc_out, u32 node_flags, u64 memory_properties,
+ u32 memory_address_limit, char *device_name)
+{
+ acpi_iort_named_component_t *nc_node_data;
+ acpi_iort_node_t *nc = (acpi_iort_node_t *)current;
+ const unsigned long nc_start = current;
+ const u16 device_name_len = strlen(device_name);
+
+ ASSERT(nc_out);
+ current += sizeof(*nc) + sizeof(*nc_node_data);
+ memset(nc, 0, current - nc_start);
+
+ nc->type = ACPI_IORT_NODE_NAMED_COMPONENT;
+ nc->revision = 0x4;
+ nc->identifier = iort->node_count++; // Unique identifier.
+
+ nc_node_data = (acpi_iort_named_component_t *)nc->node_data;
+ nc_node_data->node_flags = node_flags;
+ nc_node_data->memory_properties = memory_properties;
+ nc_node_data->memory_address_limit = memory_address_limit;
+
+ /* Path of namespace object */
+ memset(nc_node_data->device_name, 0, device_name_len + 5);
+ strncpy(nc_node_data->device_name, device_name, device_name_len + 1);
+
+ current += device_name_len + 2;
+ current = ALIGN_UP(current, 4);
+
+ nc->mapping_offset = current - nc_start;
+
+ /* length is further updated by id map entries */
+ nc->length = nc->mapping_offset;
+
+ *nc_out = nc;
+
+ return current;
+}
+
+unsigned long acpi_iort_rc_entry(unsigned long current, acpi_iort_t *node,
+ acpi_iort_node_t **rc_out, u64 memory_properties,
+ u32 ats_attribute, u32 pci_segment_number,
+ u8 memory_address_limit, u16 pasid_capabilities)
+{
+ acpi_iort_root_complex_t *rc_node_data;
+ acpi_iort_node_t *rc = (acpi_iort_node_t *)current;
+ const unsigned long rc_start = current;
+
+ ASSERT(rc_out);
+ current += sizeof(*rc) + sizeof(*rc_node_data);
+ memset(rc, 0, current - rc_start);
+
+ rc->type = ACPI_IORT_NODE_PCI_ROOT_COMPLEX;
+ rc->revision = 0x4;
+ rc->identifier = node->node_count++; // Unique identifier.
+ rc->mapping_offset = current - rc_start;
+
+ /* length is further updated by id map entries */
+ rc->length = rc->mapping_offset;
+
+ rc_node_data = (acpi_iort_root_complex_t *)rc->node_data;
+ rc_node_data->memory_properties = memory_properties; /* Memory access properties */
+ rc_node_data->ats_attribute = ats_attribute;
+ rc_node_data->pci_segment_number = pci_segment_number;
+ rc_node_data->memory_address_limit = memory_address_limit; /* Memory address size limit */
+ rc_node_data->pasid_capabilities = pasid_capabilities; /* PASID Capabilities */
+
+ *rc_out = rc;
+
+ return current;
+}
+
+unsigned long acpi_iort_id_map_entry(unsigned long current, acpi_iort_node_t *node, u32 input_base,
+ u32 id_count, u32 output_base, u32 output_reference, u32 flags)
+{
+ acpi_iort_id_mapping_t *id_map = (acpi_iort_id_mapping_t *)current;
+
+ ASSERT(node);
+ memset(id_map, 0, sizeof(acpi_iort_id_mapping_t));
+
+ current += sizeof(acpi_iort_id_mapping_t);
+
+ node->mapping_count++;
+ node->length += current - (unsigned long)id_map;
+
+ id_map->input_base = input_base;
+ id_map->id_count = id_count - 1;
+ id_map->output_base = output_base;
+ id_map->output_reference = output_reference;
+ id_map->flags = flags;
+
+ return current;
+}
diff --git a/src/include/acpi/acpi_iort.h b/src/include/acpi/acpi_iort.h
index 74a520d6a6..125b3a1d5d 100644
--- a/src/include/acpi/acpi_iort.h
+++ b/src/include/acpi/acpi_iort.h
@@ -110,4 +110,26 @@ typedef struct acpi_iort_root_complex {
unsigned long acpi_soc_fill_iort(acpi_iort_t *iort, unsigned long current);
+/* ITS Group */
+unsigned long acpi_iort_its_entry(unsigned long current, acpi_iort_t *iort, acpi_iort_node_t **its,
+ u32 its_count, u32 *identifiers);
+
+/* SMMUv3 */
+unsigned long acpi_iort_smmuv3_entry(unsigned long current, acpi_iort_t *iort,
+ acpi_iort_node_t **smmu_v3, u64 base, u32 flags);
+
+/* ID mapping */
+unsigned long acpi_iort_id_map_entry(unsigned long current, acpi_iort_node_t *node, u32 input_base,
+ u32 id_count, u32 output_base, u32 output_reference,
+ u32 flags);
+
+/* Named Component */
+unsigned long acpi_iort_nc_entry(unsigned long current, acpi_iort_t *iort, acpi_iort_node_t **nc,
+ u32 node_flags, u64 memory_properties, u32 memory_address_limit,
+ char *device_name);
+/* Root Complex */
+unsigned long acpi_iort_rc_entry(unsigned long current, acpi_iort_t *node, acpi_iort_node_t **rc,
+ u64 memory_properties, u32 ats_attribute, u32 pci_segment_number,
+ u8 memory_address_limit, u16 pasid_capabilities);
+
#endif