[PATCH v4 31/59] x86: acpi: Add support for additional Intel tables

Simon Glass sjg at chromium.org
Tue Sep 22 20:45:16 CEST 2020


Apollo Lake needs to generate a few more table types used on Intel SoCs.
Add support for these into the x86 ACPI code.

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

(no changes since v1)

Changes in v1:
- Move this code into an x86-specific file
- Update commit message
- Use OEM_TABLE_ID instead of ACPI_TABLE_CREATOR

 arch/x86/include/asm/acpi_table.h | 115 ++++++++++++++++++++++++++++++
 arch/x86/lib/acpi_table.c         | 111 ++++++++++++++++++++++++++++
 include/acpi/acpi_table.h         |  43 +++++++++++
 3 files changed, 269 insertions(+)

diff --git a/arch/x86/include/asm/acpi_table.h b/arch/x86/include/asm/acpi_table.h
index 3245e447813..faf31730730 100644
--- a/arch/x86/include/asm/acpi_table.h
+++ b/arch/x86/include/asm/acpi_table.h
@@ -98,4 +98,119 @@ int arch_write_sci_irq_select(uint scis);
  */
 int arch_madt_sci_irq_polarity(int sci);
 
+/**
+ * acpi_create_dmar_drhd() - Create a table for DMA remapping with the IOMMU
+ *
+ * See here for the specification
+ * https://software.intel.com/sites/default/files/managed/c5/15/vt-directed-io-spec.pdf
+ *
+ * @ctx: ACPI context pointer
+ * @flags: (DRHD_INCLUDE_...)
+ * @segment: PCI segment asscociated with this unit
+ * @bar: Base address of remapping hardware register-set for this unit
+ */
+void acpi_create_dmar_drhd(struct acpi_ctx *ctx, uint flags, uint segment,
+			   u64 bar);
+
+/**
+ * acpi_create_dmar_rmrr() - Set up an RMRR
+ *
+ * This sets up a Reserved-Memory Region Reporting structure, used to allow
+ * DMA to regions used by devices that the BIOS controls.
+ *
+ * @ctx: ACPI context pointer
+ * @segment: PCI segment asscociated with this unit
+ * @bar: Base address of mapping
+ * @limit: End address of mapping
+ */
+void acpi_create_dmar_rmrr(struct acpi_ctx *ctx, uint segment, u64 bar,
+			   u64 limit);
+
+/**
+ * acpi_dmar_drhd_fixup() - Set the length of an DRHD
+ *
+ * This sets the DRHD length field based on the current ctx->current
+ *
+ * @ctx: ACPI context pointer
+ * @base: Address of the start of the DRHD
+ */
+void acpi_dmar_drhd_fixup(struct acpi_ctx *ctx, void *base);
+
+/**
+ * acpi_dmar_rmrr_fixup() - Set the length of an RMRR
+ *
+ * This sets the RMRR length field based on the current ctx->current
+ *
+ * @ctx: ACPI context pointer
+ * @base: Address of the start of the RMRR
+ */
+void acpi_dmar_rmrr_fixup(struct acpi_ctx *ctx, void *base);
+
+/**
+ * acpi_create_dmar_ds_pci() - Set up a DMAR scope for a PCI device
+ *
+ * @ctx: ACPI context pointer
+ * @bdf: PCI device to add
+ * @return length of mapping in bytes
+ */
+int acpi_create_dmar_ds_pci(struct acpi_ctx *ctx, pci_dev_t bdf);
+
+/**
+ * acpi_create_dmar_ds_pci_br() - Set up a DMAR scope for a PCI bridge
+ *
+ * This is used to provide a mapping for a PCI bridge
+ *
+ * @ctx: ACPI context pointer
+ * @bdf: PCI device to add
+ * @return length of mapping in bytes
+ */
+int acpi_create_dmar_ds_pci_br(struct acpi_ctx *ctx, pci_dev_t bdf);
+
+/**
+ * acpi_create_dmar_ds_ioapic() - Set up a DMAR scope for an IOAPIC device
+ *
+ * @ctx: ACPI context pointer
+ * @enumeration_id: Enumeration ID (typically 2)
+ * @bdf: PCI device to add
+ * @return length of mapping in bytes
+ */
+int acpi_create_dmar_ds_ioapic(struct acpi_ctx *ctx, uint enumeration_id,
+			       pci_dev_t bdf);
+
+/**
+ * acpi_create_dmar_ds_msi_hpet() - Set up a DMAR scope for an HPET
+ *
+ * Sets up a scope for a High-Precision Event Timer that supports
+ * Message-Signalled Interrupts
+ *
+ * @ctx: ACPI context pointer
+ * @enumeration_id: Enumeration ID (typically 0)
+ * @bdf: PCI device to add
+ * @return length of mapping in bytes
+ */
+int acpi_create_dmar_ds_msi_hpet(struct acpi_ctx *ctx, uint enumeration_id,
+				 pci_dev_t bdf);
+
+/**
+ * acpi_fadt_common() - Handle common parts of filling out an FADT
+ *
+ * This sets up the Fixed ACPI Description Table
+ *
+ * @fadt: Pointer to place to put FADT
+ * @facs: Pointer to the FACS
+ * @dsdt: Pointer to the DSDT
+ */
+void acpi_fadt_common(struct acpi_fadt *fadt, struct acpi_facs *facs,
+		      void *dsdt);
+
+/**
+ * intel_acpi_fill_fadt() - Set up the contents of the FADT
+ *
+ * This sets up parts of the Fixed ACPI Description Table that are common to
+ * Intel chips
+ *
+ * @fadt: Pointer to place to put FADT
+ */
+void intel_acpi_fill_fadt(struct acpi_fadt *fadt);
+
 #endif /* __ASM_ACPI_TABLE_H__ */
diff --git a/arch/x86/lib/acpi_table.c b/arch/x86/lib/acpi_table.c
index e257c789838..86a9a35cb25 100644
--- a/arch/x86/lib/acpi_table.c
+++ b/arch/x86/lib/acpi_table.c
@@ -629,3 +629,114 @@ int acpi_write_dbg2_pci_uart(struct acpi_ctx *ctx, struct udevice *dev,
 
 	return 0;
 }
+
+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, OEM_TABLE_ID, 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;
+}
+
+void 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);
+}
+
+void 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);
+}
+
+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);
+}
diff --git a/include/acpi/acpi_table.h b/include/acpi/acpi_table.h
index c826a797f5b..a2e510cf56e 100644
--- a/include/acpi/acpi_table.h
+++ b/include/acpi/acpi_table.h
@@ -377,6 +377,49 @@ struct acpi_csrt_shared_info {
 	u32 max_block_size;
 };
 
+/* Port types for ACPI _UPC object */
+enum acpi_upc_type {
+	UPC_TYPE_A,
+	UPC_TYPE_MINI_AB,
+	UPC_TYPE_EXPRESSCARD,
+	UPC_TYPE_USB3_A,
+	UPC_TYPE_USB3_B,
+	UPC_TYPE_USB3_MICRO_B,
+	UPC_TYPE_USB3_MICRO_AB,
+	UPC_TYPE_USB3_POWER_B,
+	UPC_TYPE_C_USB2_ONLY,
+	UPC_TYPE_C_USB2_SS_SWITCH,
+	UPC_TYPE_C_USB2_SS,
+	UPC_TYPE_PROPRIETARY = 0xff,
+	/*
+	 * The following types are not directly defined in the ACPI
+	 * spec but are used by coreboot to identify a USB device type.
+	 */
+	UPC_TYPE_INTERNAL = 0xff,
+	UPC_TYPE_UNUSED,
+	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,
-- 
2.28.0.681.g6f77f65b4e-goog



More information about the U-Boot mailing list