Werner Zeh (werner.zeh@siemens.com) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/15913
-gerrit
commit e94e7281cee9a1b7a52bfe2824b1eaaf0a2d00fe Author: Werner Zeh werner.zeh@siemens.com Date: Wed Jul 27 08:22:50 2016 +0200
fsp_broadwell_de: Add DMAR table to ACPI
Create DMAR table for Broadwell-DE SoC.
TEST=Booted MC BDX1 into lubuntu15, dumped ACPI tables with acpidump and disassembled DMAR table using iasl. The table contents are as expected and the kernel loads DMAR table without errors.
Change-Id: I7933ba4f5f0539a50f2ab9a5571e502c84873ec6 Signed-off-by: Werner Zeh werner.zeh@siemens.com --- src/soc/intel/fsp_broadwell_de/acpi.c | 97 +++++++++++++++++++++++ src/soc/intel/fsp_broadwell_de/include/soc/acpi.h | 3 + src/soc/intel/fsp_broadwell_de/northcluster.c | 18 +++-- 3 files changed, 110 insertions(+), 8 deletions(-)
diff --git a/src/soc/intel/fsp_broadwell_de/acpi.c b/src/soc/intel/fsp_broadwell_de/acpi.c index 1e08868..52a180a 100644 --- a/src/soc/intel/fsp_broadwell_de/acpi.c +++ b/src/soc/intel/fsp_broadwell_de/acpi.c @@ -312,6 +312,103 @@ void acpi_fill_in_fadt(acpi_fadt_t *fadt, acpi_facs_t *facs, void *dsdt) header->checksum = acpi_checksum((void *) fadt, sizeof(acpi_fadt_t)); }
+static unsigned long acpi_fill_dmar(unsigned long current) +{ + uint32_t vtbar = 0, tmp = current; + device_t dev = dev_find_slot(0, PCI_DEVFN(5, 0)); + uint16_t bdf = 0, hpet_bdf[8]; + uint8_t i = 0, j = 0; + + if (!dev) + return current; + + vtbar = pci_read_config32(dev, 0x180) & 0xffffe000; + if (!vtbar) + return current; + + current += acpi_create_dmar_drhd(current, + DRHD_INCLUDE_PCI_ALL, 0, vtbar); + /* The IIO I/O APIC is fixed on PCI 00:05.4 on Broadwell-DE */ + current += acpi_create_dmar_drhd_ds_ioapic(current, + 9, 0, 5, 4); + /* Get the PCI BDF for the PCH I/O APIC */ + dev = dev_find_slot(0, LPC_DEV_FUNC); + bdf = pci_read_config16(dev, 0x6c); + current += acpi_create_dmar_drhd_ds_ioapic(current, + 8, (bdf >> 8), PCI_SLOT(bdf), PCI_FUNC(bdf)); + + /* + * Check if there are different PCI paths for the 8 HPET timers + * and add every different PCI path as a separate HPET entry. + * Although the DMAR specification talks about HPET block for this + * entry, it is possible to assign a unique PCI BDF to every single + * timer within a HPET block which will result in different source + * IDs reported by a generated MSI. + * In default configuration every single timer will have the same + * PCI BDF which will result in a single HPET entry in DMAR table. + * I have checked several different systems and all of them had one + * single entry for HPET in DMAR. + */ + memset(hpet_bdf, 0, sizeof(hpet_bdf)); + /* Get all unique HPET paths. */ + for (i = 0; i < 8; i++) { + bdf = pci_read_config16(dev, 0x70 + (i * 2)); + for (j = 0; j < ARRAY_SIZE(hpet_bdf); j++) { + if (hpet_bdf[j] == bdf) + break; + } + if (j == ARRAY_SIZE(hpet_bdf)) + hpet_bdf[i] = bdf; + } + /* Create one HPET entry in DMAR for every unique HPET PCI path. */ + for (i = 0; i < 8; i++) { + if (hpet_bdf[i]) + current += acpi_create_dmar_drhd_ds_msi_hpet(current, + 0, (hpet_bdf[i] >> 8), PCI_SLOT(hpet_bdf[i]), + PCI_FUNC(hpet_bdf[i])); + } + acpi_dmar_drhd_fixup(tmp, current); + + /* Create root port ATSR capability */ + tmp = current; + current += acpi_create_dmar_atsr(current, 0, 0); + /* Add one entry to ATSR for each PCI root port */ + dev = all_devices; + do { + dev = dev_find_class(PCI_CLASS_BRIDGE_PCI << 8, dev); + if (dev && dev->bus->secondary == 0 && + PCI_SLOT(dev->path.pci.devfn) <= 3) + current += acpi_create_dmar_drhd_ds_pci_br(current, + dev->bus->secondary, + PCI_SLOT(dev->path.pci.devfn), + PCI_FUNC(dev->path.pci.devfn)); + } while (dev); + acpi_dmar_atsr_fixup(tmp, current); + + return current; +} + +unsigned long northcluster_write_acpi_tables(struct device *const dev, + unsigned long current, + struct acpi_rsdp *const rsdp) +{ + acpi_dmar_t *const dmar = (acpi_dmar_t *)current; + device_t vtdev = dev_find_slot(0, PCI_DEVFN(5, 0)); + + /* Create DMAR table only if virtualization is enabled */ + if (!(pci_read_config32(vtdev, 0x180) & 0x01)) + return current; + + printk(BIOS_DEBUG, "ACPI: * DMAR\n"); + acpi_create_dmar(dmar, DMAR_INTR_REMAP, acpi_fill_dmar); + current += dmar->header.length; + current = acpi_align_current(current); + acpi_add_table(rsdp, dmar); + current = acpi_align_current(current); + + return current; +} + static int calculate_power(int tdp, int p1_ratio, int ratio) { u32 m; diff --git a/src/soc/intel/fsp_broadwell_de/include/soc/acpi.h b/src/soc/intel/fsp_broadwell_de/include/soc/acpi.h index f717d15..8693041 100644 --- a/src/soc/intel/fsp_broadwell_de/include/soc/acpi.h +++ b/src/soc/intel/fsp_broadwell_de/include/soc/acpi.h @@ -23,5 +23,8 @@ void acpi_create_intel_hpet(acpi_hpet_t *hpet); void acpi_fill_in_fadt(acpi_fadt_t *fadt, acpi_facs_t *facs, void *dsdt); unsigned long acpi_madt_irq_overrides(unsigned long current); uint16_t get_pmbase(void); +unsigned long northcluster_write_acpi_tables(struct device *const dev, + unsigned long current, + struct acpi_rsdp *const rsdp);
#endif /* _SOC_ACPI_H_ */ diff --git a/src/soc/intel/fsp_broadwell_de/northcluster.c b/src/soc/intel/fsp_broadwell_de/northcluster.c index 307137b..fcaccd1 100644 --- a/src/soc/intel/fsp_broadwell_de/northcluster.c +++ b/src/soc/intel/fsp_broadwell_de/northcluster.c @@ -24,6 +24,7 @@ #include <soc/iomap.h> #include <soc/pci_devs.h> #include <soc/ramstage.h> +#include <soc/acpi.h>
static const int legacy_hole_base_k = 0xa0000 / 1024; static const int legacy_hole_size_k = 384; @@ -133,14 +134,15 @@ static void nc_enable(device_t dev) }
static struct device_operations nc_ops = { - .read_resources = nc_read_resources, + .read_resources = nc_read_resources, .acpi_fill_ssdt_generator = generate_cpu_entries, - .set_resources = pci_dev_set_resources, - .enable_resources = pci_dev_enable_resources, - .init = NULL, - .enable = &nc_enable, - .scan_bus = 0, - .ops_pci = &soc_pci_ops, + .write_acpi_tables = northcluster_write_acpi_tables, + .set_resources = pci_dev_set_resources, + .enable_resources = pci_dev_enable_resources, + .init = NULL, + .enable = &nc_enable, + .scan_bus = 0, + .ops_pci = &soc_pci_ops, };
static const struct pci_driver nc_driver __pci_driver = { @@ -153,4 +155,4 @@ static const struct pci_driver nc_driver_es2 __pci_driver = { .ops = &nc_ops, .vendor = PCI_VENDOR_ID_INTEL, .device = SOC_DEVID_ES2, -}; \ No newline at end of file +};