From 540f0bae9bd0e19d00d11796a62a08f94d895189 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 22 Sep 2020 12:45:16 -0600 Subject: [PATCH] x86: acpi: Add support for additional Intel tables 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 --- 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 3245e44..faf3173 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 e257c78..86a9a35 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 c826a79..a2e510c 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.7.4