diff options
author | Werner Zeh <werner.zeh@siemens.com> | 2016-07-27 08:22:50 +0200 |
---|---|---|
committer | Werner Zeh <werner.zeh@siemens.com> | 2016-08-03 12:44:25 +0200 |
commit | 1cfb555e713f57b86d6ae779704e2861e654b25c (patch) | |
tree | a83360152acceb8699cd8c8cc471d66b1eb612b4 | |
parent | 5407310e64ea34b41ca4226ad724642f2b5de8fa (diff) |
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>
Reviewed-on: https://review.coreboot.org/15913
Tested-by: build bot (Jenkins)
Reviewed-by: Nico Huber <nico.h@gmx.de>
-rw-r--r-- | src/soc/intel/fsp_broadwell_de/acpi.c | 99 | ||||
-rw-r--r-- | src/soc/intel/fsp_broadwell_de/include/soc/acpi.h | 4 | ||||
-rw-r--r-- | src/soc/intel/fsp_broadwell_de/include/soc/broadwell_de.h | 3 | ||||
-rw-r--r-- | src/soc/intel/fsp_broadwell_de/include/soc/pci_devs.h | 5 | ||||
-rw-r--r-- | src/soc/intel/fsp_broadwell_de/northcluster.c | 17 |
5 files changed, 121 insertions, 7 deletions
diff --git a/src/soc/intel/fsp_broadwell_de/acpi.c b/src/soc/intel/fsp_broadwell_de/acpi.c index 1e088684c0..1647505820 100644 --- a/src/soc/intel/fsp_broadwell_de/acpi.c +++ b/src/soc/intel/fsp_broadwell_de/acpi.c @@ -4,6 +4,7 @@ * Copyright (C) 2007-2009 coresystems GmbH * Copyright (C) 2013 Google Inc. * Copyright (C) 2015-2016 Intel Corp. + * Copyright (C) 2016 Siemens AG * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -35,6 +36,7 @@ #include <soc/msr.h> #include <soc/pattrs.h> #include <soc/pci_devs.h> +#include <soc/broadwell_de.h> #include <chip.h> uint16_t get_pmbase(void) @@ -312,6 +314,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, tmp = current; + struct device *dev = dev_find_slot(0, VTD_DEV_FUNC); + uint16_t bdf, hpet_bdf[8]; + uint8_t i, j; + + if (!dev) + return current; + + vtbar = pci_read_config32(dev, VTBAR_OFFSET) & VTBAR_MASK; + 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 < ARRAY_SIZE(hpet_bdf); i++) { + bdf = pci_read_config16(dev, 0x70 + (i * 2)); + for (j = 0; j < i; j++) { + if (hpet_bdf[j] == bdf) + break; + } + if (j == i) + hpet_bdf[i] = bdf; + } + /* Create one HPET entry in DMAR for every unique HPET PCI path. */ + for (i = 0; i < ARRAY_SIZE(hpet_bdf); 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 f717d15a3b..da552cc615 100644 --- a/src/soc/intel/fsp_broadwell_de/include/soc/acpi.h +++ b/src/soc/intel/fsp_broadwell_de/include/soc/acpi.h @@ -3,6 +3,7 @@ * * Copyright (C) 2013 Google, Inc. * Copyright (C) 2015-2016 Intel Corp. + * Copyright (C) 2016 Siemens AG * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,5 +24,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/include/soc/broadwell_de.h b/src/soc/intel/fsp_broadwell_de/include/soc/broadwell_de.h index 6828d03dc9..85298a5ccd 100644 --- a/src/soc/intel/fsp_broadwell_de/include/soc/broadwell_de.h +++ b/src/soc/intel/fsp_broadwell_de/include/soc/broadwell_de.h @@ -17,4 +17,7 @@ #ifndef _SOC_BROADWELL_DE_H_ #define _SOC_BROADWELL_DE_H_ +#define VTBAR_OFFSET 0x180 +#define VTBAR_MASK 0xffffe000 + #endif /* _SOC_BROADWELL_DE_H_ */ diff --git a/src/soc/intel/fsp_broadwell_de/include/soc/pci_devs.h b/src/soc/intel/fsp_broadwell_de/include/soc/pci_devs.h index 5f3cfb963a..c5bb77ab75 100644 --- a/src/soc/intel/fsp_broadwell_de/include/soc/pci_devs.h +++ b/src/soc/intel/fsp_broadwell_de/include/soc/pci_devs.h @@ -27,6 +27,11 @@ #define SOC_DEVID_ES2 0x6F00 #define SOC_DEV_FUNC PCI_DEVFN(SOC_DEV, SOC_FUNC) +#define VTD_DEV 5 +#define VTD_FUNC 0 +#define VTD_DEVID 0x6f28 +#define VTD_DEV_FUNC PCI_DEVFN(VTD_DEV, VTD_FUNC) + #define LPC_DEV 31 #define LPC_FUNC 0 #define LPC_DEVID 0x8C42 diff --git a/src/soc/intel/fsp_broadwell_de/northcluster.c b/src/soc/intel/fsp_broadwell_de/northcluster.c index 38872b4435..c15ff5f2fe 100644 --- a/src/soc/intel/fsp_broadwell_de/northcluster.c +++ b/src/soc/intel/fsp_broadwell_de/northcluster.c @@ -3,6 +3,7 @@ * * Copyright (C) 2013 Google Inc. * Copyright (C) 2015-2016 Intel Corp. + * Copyright (C) 2016 Siemens AG * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -24,6 +25,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 +135,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 = { |