mirror of
https://github.com/linuxboot/heads.git
synced 2024-12-23 14:52:27 +00:00
155 lines
5.2 KiB
Diff
155 lines
5.2 KiB
Diff
|
From 65b3bf5a7d211f7e1e37d73d0b59ed053dff85a8 Mon Sep 17 00:00:00 2001
|
||
|
From: Nico Huber <nico.h@gmx.de>
|
||
|
Date: Mon, 18 Sep 2017 20:03:46 +0200
|
||
|
Subject: [PATCH 4/9] soc/intel/skylake: Generate ACPI DMAR table
|
||
|
|
||
|
If the SoC is VT-d capable, write an ACPI DMAR table. The entry for the
|
||
|
GFXVTBAR is only generated if the IGD is enabled.
|
||
|
|
||
|
Change-Id: I8176401dd19aee7ad09a8a145b7a3801fe5b2ae1
|
||
|
Signed-off-by: Nico Huber <nico.h@gmx.de>
|
||
|
---
|
||
|
src/soc/intel/skylake/acpi.c | 68 ++++++++++++++++++++++++++++++++
|
||
|
src/soc/intel/skylake/chip_fsp20.c | 3 +-
|
||
|
src/soc/intel/skylake/include/soc/acpi.h | 2 +
|
||
|
src/soc/intel/skylake/include/soc/p2sb.h | 3 ++
|
||
|
4 files changed, 75 insertions(+), 1 deletion(-)
|
||
|
|
||
|
diff --git a/src/soc/intel/skylake/acpi.c b/src/soc/intel/skylake/acpi.c
|
||
|
index 61360dafae..45061aba6f 100644
|
||
|
--- a/src/soc/intel/skylake/acpi.c
|
||
|
+++ b/src/soc/intel/skylake/acpi.c
|
||
|
@@ -34,14 +34,17 @@
|
||
|
#include <intelblocks/lpc_lib.h>
|
||
|
#include <intelblocks/sgx.h>
|
||
|
#include <intelblocks/uart.h>
|
||
|
+#include <intelblocks/systemagent.h>
|
||
|
#include <soc/intel/common/acpi.h>
|
||
|
#include <soc/acpi.h>
|
||
|
#include <soc/cpu.h>
|
||
|
#include <soc/iomap.h>
|
||
|
#include <soc/msr.h>
|
||
|
+#include <soc/p2sb.h>
|
||
|
#include <soc/pci_devs.h>
|
||
|
#include <soc/pm.h>
|
||
|
#include <soc/ramstage.h>
|
||
|
+#include <soc/systemagent.h>
|
||
|
#include <string.h>
|
||
|
#include <types.h>
|
||
|
#include <vendorcode/google/chromeos/gnvs.h>
|
||
|
@@ -539,6 +542,71 @@ void generate_cpu_entries(device_t device)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
+static unsigned long acpi_fill_dmar(unsigned long current)
|
||
|
+{
|
||
|
+ struct device *const igfx_dev = dev_find_slot(0, SA_DEVFN_IGD);
|
||
|
+ const u32 gfx_vtbar = MCHBAR32(GFXVTBAR) & ~0xfff;
|
||
|
+
|
||
|
+ /* iGFX has to be enabled, GFXVTBAR set and in 32-bit space. */
|
||
|
+ if (igfx_dev && igfx_dev->enabled &&
|
||
|
+ gfx_vtbar && !MCHBAR32(GFXVTBAR + 4)) {
|
||
|
+ const unsigned long tmp = current;
|
||
|
+
|
||
|
+ current += acpi_create_dmar_drhd(current, 0, 0, gfx_vtbar);
|
||
|
+ current += acpi_create_dmar_drhd_ds_pci(current, 0, 2, 0);
|
||
|
+
|
||
|
+ acpi_dmar_drhd_fixup(tmp, current);
|
||
|
+ }
|
||
|
+
|
||
|
+ struct device *const p2sb_dev = dev_find_slot(0, PCH_DEVFN_P2SB);
|
||
|
+ const u32 vtvc0bar = MCHBAR32(VTVC0BAR) & ~0xfff;
|
||
|
+
|
||
|
+ /* General VTBAR has to be set and in 32-bit space. */
|
||
|
+ if (p2sb_dev && vtvc0bar && !MCHBAR32(VTVC0BAR + 4)) {
|
||
|
+ const unsigned long tmp = current;
|
||
|
+
|
||
|
+ /* P2SB may already be hidden. There's no clear rule, when. */
|
||
|
+ const u8 p2sb_hidden =
|
||
|
+ pci_read_config8(p2sb_dev, PCH_P2SB_E0 + 1);
|
||
|
+ pci_write_config8(p2sb_dev, PCH_P2SB_E0 + 1, 0);
|
||
|
+
|
||
|
+ const u16 ibdf = pci_read_config16(p2sb_dev, PCH_P2SB_IBDF);
|
||
|
+ const u16 hbdf = pci_read_config16(p2sb_dev, PCH_P2SB_HBDF);
|
||
|
+
|
||
|
+ pci_write_config8(p2sb_dev, PCH_P2SB_E0 + 1, p2sb_hidden);
|
||
|
+
|
||
|
+ current += acpi_create_dmar_drhd(current,
|
||
|
+ DRHD_INCLUDE_PCI_ALL, 0, vtvc0bar);
|
||
|
+ current += acpi_create_dmar_drhd_ds_ioapic(current,
|
||
|
+ 2, ibdf >> 8, PCI_SLOT(ibdf), PCI_FUNC(ibdf));
|
||
|
+ current += acpi_create_dmar_drhd_ds_msi_hpet(current,
|
||
|
+ 0, hbdf >> 8, PCI_SLOT(hbdf), PCI_FUNC(hbdf));
|
||
|
+
|
||
|
+ acpi_dmar_drhd_fixup(tmp, current);
|
||
|
+ }
|
||
|
+
|
||
|
+ return current;
|
||
|
+}
|
||
|
+
|
||
|
+unsigned long northbridge_write_acpi_tables(struct device *const dev,
|
||
|
+ unsigned long current,
|
||
|
+ struct acpi_rsdp *const rsdp)
|
||
|
+{
|
||
|
+ acpi_dmar_t *const dmar = (acpi_dmar_t *)current;
|
||
|
+
|
||
|
+ /* Create DMAR table only if we have VT-d capability. */
|
||
|
+ if (!soc_is_vtd_capable())
|
||
|
+ 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);
|
||
|
+
|
||
|
+ return current;
|
||
|
+}
|
||
|
+
|
||
|
unsigned long acpi_madt_irq_overrides(unsigned long current)
|
||
|
{
|
||
|
int sci = acpi_sci_irq();
|
||
|
diff --git a/src/soc/intel/skylake/chip_fsp20.c b/src/soc/intel/skylake/chip_fsp20.c
|
||
|
index 875542c9c6..9fbc3da8dc 100644
|
||
|
--- a/src/soc/intel/skylake/chip_fsp20.c
|
||
|
+++ b/src/soc/intel/skylake/chip_fsp20.c
|
||
|
@@ -59,7 +59,8 @@ static struct device_operations pci_domain_ops = {
|
||
|
.scan_bus = &pci_domain_scan_bus,
|
||
|
.ops_pci_bus = &pci_bus_default_ops,
|
||
|
#if IS_ENABLED(CONFIG_HAVE_ACPI_TABLES)
|
||
|
- .acpi_name = &soc_acpi_name,
|
||
|
+ .write_acpi_tables = &northbridge_write_acpi_tables,
|
||
|
+ .acpi_name = &soc_acpi_name,
|
||
|
#endif
|
||
|
};
|
||
|
|
||
|
diff --git a/src/soc/intel/skylake/include/soc/acpi.h b/src/soc/intel/skylake/include/soc/acpi.h
|
||
|
index b0d2194612..6d492acd67 100644
|
||
|
--- a/src/soc/intel/skylake/include/soc/acpi.h
|
||
|
+++ b/src/soc/intel/skylake/include/soc/acpi.h
|
||
|
@@ -32,5 +32,7 @@ void acpi_mainboard_gnvs(global_nvs_t *gnvs);
|
||
|
void southbridge_inject_dsdt(device_t device);
|
||
|
unsigned long southbridge_write_acpi_tables(device_t device,
|
||
|
unsigned long current, struct acpi_rsdp *rsdp);
|
||
|
+unsigned long northbridge_write_acpi_tables(struct device *,
|
||
|
+ unsigned long current, struct acpi_rsdp *);
|
||
|
|
||
|
#endif /* _SOC_ACPI_H_ */
|
||
|
diff --git a/src/soc/intel/skylake/include/soc/p2sb.h b/src/soc/intel/skylake/include/soc/p2sb.h
|
||
|
index d846dfc8f5..09e73fc254 100644
|
||
|
--- a/src/soc/intel/skylake/include/soc/p2sb.h
|
||
|
+++ b/src/soc/intel/skylake/include/soc/p2sb.h
|
||
|
@@ -19,6 +19,9 @@
|
||
|
#define HPTC_OFFSET 0x60
|
||
|
#define HPTC_ADDR_ENABLE_BIT (1 << 7)
|
||
|
|
||
|
+#define PCH_P2SB_IBDF 0x6c
|
||
|
+#define PCH_P2SB_HBDF 0x70
|
||
|
+
|
||
|
#define PCH_P2SB_EPMASK0 0xB0
|
||
|
#define PCH_P2SB_EPMASK(mask_number) (PCH_P2SB_EPMASK0 + ((mask_number) * 4))
|
||
|
|
||
|
--
|
||
|
2.14.3
|
||
|
|