[092/108] x86: acpi: Add support for additional DMAR tables

Message ID 20200126220508.92.I8aa77aa9037dc3d08929270b114eac2f8fc9daa3@changeid
State New
Headers show
Series
  • RFC: dm: Add programatic generation of ACPI tables
Related show

Commit Message

Simon Glass Jan. 27, 2020, 5:06 a.m.
Apollo Lake needs to generate a few more table types. Add support for
these into the x86 ACPI code.

Signed-off-by: Simon Glass <sjg at chromium.org>
---

 arch/x86/lib/acpi_table.c | 115 ++++++++++++++++++++++++++++++++++++++
 include/acpi_table.h      |  37 ++++++++++++
 2 files changed, 152 insertions(+)

Patch

diff --git a/arch/x86/lib/acpi_table.c b/arch/x86/lib/acpi_table.c
index f12344de50..886960a5fa 100644
--- a/arch/x86/lib/acpi_table.c
+++ b/arch/x86/lib/acpi_table.c
@@ -450,6 +450,121 @@  void acpi_create_ssdt(struct acpi_ctx *ctx, struct acpi_table_header *ssdt,
 	ssdt->checksum = table_compute_checksum((void *)ssdt, ssdt->length);
 }
 
+void acpi_fadt_common(struct acpi_fadt *fadt, struct acpi_facs *facs,
+		      void *dsdt)
+{
+	struct acpi_table_header *header = &fadt->header;
+
+	memset((void *)fadt, '\0', sizeof(struct acpi_fadt));
+
+	acpi_fill_header(header, "FACP");
+	header->length = sizeof(struct acpi_fadt);
+	header->revision = 4;
+	memcpy(header->oem_id, OEM_ID, 6);
+	memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8);
+	memcpy(header->aslc_id, ASLC_ID, 4);
+	header->aslc_revision = 1;
+
+	fadt->firmware_ctrl = (unsigned long)facs;
+	fadt->dsdt = (unsigned long)dsdt;
+
+	fadt->x_firmware_ctl_l = (unsigned long)facs;
+	fadt->x_firmware_ctl_h = 0;
+	fadt->x_dsdt_l = (unsigned long)dsdt;
+	fadt->x_dsdt_h = 0;
+
+	fadt->preferred_pm_profile = ACPI_PM_MOBILE;
+
+	/* Use ACPI 3.0 revision */
+	fadt->header.revision = 4;
+}
+
+int acpi_create_dmar_drhd(struct acpi_ctx *ctx, uint flags, uint segment,
+			  u64 bar)
+{
+	struct dmar_entry *drhd = ctx->current;
+
+	memset(drhd, 0, sizeof(*drhd));
+	drhd->type = DMAR_DRHD;
+	drhd->length = sizeof(*drhd); /* will be fixed up later */
+	drhd->flags = flags;
+	drhd->segment = segment;
+	drhd->bar = bar;
+	acpi_inc(ctx, drhd->length);
+
+	return 0;
+}
+
+int acpi_create_dmar_rmrr(struct acpi_ctx *ctx, uint segment, u64 bar,
+			  u64 limit)
+{
+	struct dmar_rmrr_entry *rmrr = ctx->current;
+
+	memset(rmrr, 0, sizeof(*rmrr));
+	rmrr->type = DMAR_RMRR;
+	rmrr->length = sizeof(*rmrr); /* will be fixed up later */
+	rmrr->segment = segment;
+	rmrr->bar = bar;
+	rmrr->limit = limit;
+	acpi_inc(ctx, rmrr->length);
+
+	return 0;
+}
+
+void acpi_dmar_drhd_fixup(struct acpi_ctx *ctx, void *base)
+{
+	struct dmar_entry *drhd = base;
+
+	drhd->length = ctx->current - base;
+}
+
+void acpi_dmar_rmrr_fixup(struct acpi_ctx *ctx, void *base)
+{
+	struct dmar_rmrr_entry *rmrr = base;
+
+	rmrr->length = ctx->current - base;
+}
+
+static int acpi_create_dmar_ds(struct acpi_ctx *ctx, enum dev_scope_type type,
+			       uint enumeration_id, pci_dev_t bdf)
+{
+	/* we don't support longer paths yet */
+	const size_t dev_scope_length = sizeof(struct dev_scope) + 2;
+	struct dev_scope *ds = ctx->current;
+
+	memset(ds, 0, dev_scope_length);
+	ds->type	= type;
+	ds->length	= dev_scope_length;
+	ds->enumeration	= enumeration_id;
+	ds->start_bus	= PCI_BUS(bdf);
+	ds->path[0].dev	= PCI_DEV(bdf);
+	ds->path[0].fn	= PCI_FUNC(bdf);
+
+	return ds->length;
+}
+
+int acpi_create_dmar_ds_pci_br(struct acpi_ctx *ctx, pci_dev_t bdf)
+{
+	return acpi_create_dmar_ds(ctx, SCOPE_PCI_SUB, 0, bdf);
+}
+
+int acpi_create_dmar_ds_pci(struct acpi_ctx *ctx, pci_dev_t bdf)
+{
+	return acpi_create_dmar_ds(ctx, SCOPE_PCI_ENDPOINT, 0, bdf);
+}
+
+int acpi_create_dmar_ds_ioapic(struct acpi_ctx *ctx, uint enumeration_id,
+			       pci_dev_t bdf)
+{
+	return acpi_create_dmar_ds(ctx, SCOPE_IOAPIC, enumeration_id, bdf);
+}
+
+int acpi_create_dmar_ds_msi_hpet(struct acpi_ctx *ctx, uint enumeration_id,
+				 pci_dev_t bdf)
+{
+	return acpi_create_dmar_ds(ctx, SCOPE_MSI_HPET, enumeration_id, bdf);
+}
+
 /* http://www.intel.com/hardwaredesign/hpetspec_1.pdf */
 int acpi_create_hpet(struct acpi_hpet *hpet)
 {
diff --git a/include/acpi_table.h b/include/acpi_table.h
index 6d91ae85e2..17f2a90af9 100644
--- a/include/acpi_table.h
+++ b/include/acpi_table.h
@@ -418,6 +418,26 @@  enum acpi_upc_type {
 	UPC_TYPE_HUB
 };
 
+enum dev_scope_type {
+	SCOPE_PCI_ENDPOINT = 1,
+	SCOPE_PCI_SUB = 2,
+	SCOPE_IOAPIC = 3,
+	SCOPE_MSI_HPET = 4,
+	SCOPE_ACPI_NAMESPACE_DEVICE = 5
+};
+
+struct __packed dev_scope {
+	u8 type;
+	u8 length;
+	u8 reserved[2];
+	u8 enumeration;
+	u8 start_bus;
+	struct {
+		u8 dev;
+		u8 fn;
+	} __packed path[0];
+};
+
 enum dmar_type {
 	DMAR_DRHD = 0,
 	DMAR_RMRR = 1,
@@ -578,6 +598,13 @@  enum acpi_tables {
  */
 int acpi_get_table_revision(enum acpi_tables table);
 
+int acpi_create_dmar_drhd(struct acpi_ctx *ctx, uint flags, uint segment,
+			  u64 bar);
+int acpi_create_dmar_rmrr(struct acpi_ctx *ctx, uint segment, u64 bar,
+			  u64 limit);
+void acpi_dmar_rmrr_fixup(struct acpi_ctx *ctx, void *base);
+void acpi_dmar_drhd_fixup(struct acpi_ctx *ctx, void *base);
+
 /**
  * acpi_create_dmar() - Create a DMA Remapping Reporting (DMAR) table
  *
@@ -592,6 +619,16 @@  void acpi_create_dbg2(struct acpi_dbg2_header *dbg2,
 		      struct acpi_gen_regaddr *address, uint32_t address_size,
 		      const char *device_path);
 
+int acpi_create_dmar_ds_pci_br(struct acpi_ctx *ctx, pci_dev_t bdf);
+int acpi_create_dmar_ds_pci(struct acpi_ctx *ctx, pci_dev_t bdf);
+int acpi_create_dmar_ds_ioapic(struct acpi_ctx *ctx, uint enumeration_id,
+			       pci_dev_t bdf);
+int acpi_create_dmar_ds_msi_hpet(struct acpi_ctx *ctx, uint enumeration_id,
+				 pci_dev_t bdf);
+void acpi_fadt_common(struct acpi_fadt *fadt, struct acpi_facs *facs,
+		      void *dsdt);
+void intel_acpi_fill_fadt(struct acpi_fadt *fadt);
+
 /**
  * acpi_fill_header() - Set up a new table header
  *