@@ -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)
{
@@ -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
*
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(+)