soc/intel: Add Intel Xeon Scalable Processor support
This patch adds support for Intel Xeon-SP.
This patch is developed and verified with Skylake Scalable
Processor, which is a processor in Xeon-SP family. The code
is expected to be reusable for future geneations of Xeon-SP
processors, and will be updated with smaller targeted
patches accordingly, to add support for additional Xeon-SP
processors, to add features, and to improve the code base.
The Skylake-SP FSP is based on FSP 2.0. The FSP is a
proof-of-concept build. The binary is not shared in public,
when this patch is upstreamed.
Signed-off-by: Jonathan Zhang <jonzhang@fb.com>
Signed-off-by: Reddy Chagam <anjaneya.chagam@intel.com>
Tested-by: johnny_lin@wiwynn.com
Change-Id: Idc9c3bee17caf8b4841f0bc190cb1aa9d38fc23e
Reviewed-on: https://review.coreboot.org/c/coreboot/+/38548
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: David Hendricks <david.hendricks@gmail.com>
diff --git a/src/soc/intel/Kconfig b/src/soc/intel/Kconfig
index e8935b9..47efc4d 100644
--- a/src/soc/intel/Kconfig
+++ b/src/soc/intel/Kconfig
@@ -9,6 +9,7 @@
source "src/soc/intel/skylake/Kconfig"
source "src/soc/intel/icelake/Kconfig"
source "src/soc/intel/tigerlake/Kconfig"
+source "src/soc/intel/xeon_sp/Kconfig"
# Load common config
source "src/soc/intel/common/Kconfig"
diff --git a/src/soc/intel/xeon_sp/Kconfig b/src/soc/intel/xeon_sp/Kconfig
new file mode 100644
index 0000000..8c355c4
--- /dev/null
+++ b/src/soc/intel/xeon_sp/Kconfig
@@ -0,0 +1,134 @@
+##
+## This file is part of the coreboot project.
+##
+## Copyright (C) 2019 - 2020 Intel Corporation
+## Copyright (C) 2019 - 2020 Facebook Inc
+##
+## 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
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+## GNU General Public License for more details.
+##
+
+config SOC_INTEL_XEON_SP
+ bool
+ help
+ Intel Xeon SP support
+
+if SOC_INTEL_XEON_SP
+
+config CPU_SPECIFIC_OPTIONS
+ def_bool y
+ select ARCH_BOOTBLOCK_X86_32
+ select ARCH_RAMSTAGE_X86_32
+ select ARCH_ROMSTAGE_X86_32
+ select ARCH_VERSTAGE_X86_32
+ select BOOT_DEVICE_SPI_FLASH_RW_NOMMAP_EARLY if BOOT_DEVICE_SPI_FLASH
+ select BOOT_DEVICE_SUPPORTS_WRITES
+ select POSTCAR_CONSOLE
+ select SOC_INTEL_COMMON
+ select SOC_INTEL_COMMON_RESET
+ select PLATFORM_USES_FSP2_0
+ select FSP_PLATFORM_MEMORY_SETTINGS_VERSIONS
+ select FSP_T_XIP
+ select FSP_M_XIP
+ select FSP_USE_REPO
+ select POSTCAR_STAGE
+ select IOAPIC
+ select PARALLEL_MP
+ select SMP
+ select INTEL_DESCRIPTOR_MODE_CAPABLE
+ select COMMON_FADT
+ select SOC_INTEL_COMMON_BLOCK
+ select SOC_INTEL_COMMON_BLOCK_CPU
+ select SOC_INTEL_COMMON_BLOCK_TIMER
+ select SOC_INTEL_COMMON_BLOCK_LPC
+ select SOC_INTEL_COMMON_BLOCK_RTC
+ select SOC_INTEL_COMMON_BLOCK_SPI
+ select SOC_INTEL_COMMON_BLOCK_FAST_SPI
+ select SOC_INTEL_COMMON_BLOCK_PCR
+ select TSC_MONOTONIC_TIMER
+ select UDELAY_TSC
+ select SUPPORT_CPU_UCODE_IN_CBFS
+ select CPU_INTEL_FIRMWARE_INTERFACE_TABLE
+
+config MAINBOARD_USES_FSP2_0
+ bool
+ default y
+
+config USE_FSP2_0_DRIVER
+ def_bool y
+ depends on MAINBOARD_USES_FSP2_0
+ select PLATFORM_USES_FSP2_0
+ select UDK_2015_BINDING
+ select POSTCAR_CONSOLE
+ select POSTCAR_STAGE
+
+# Fake FSP binary is used, as the current FSP binary for SKX-SP
+# is an engineering build. It is not available to the public
+# for now.
+config FSP_FD_PATH
+ string "Location of FSP binary"
+ depends on FSP_USE_REPO
+ default "3rdparty/fsp/KabylakeFspBinPkg/Fsp.fd"
+
+config FSP_HEADER_PATH
+ string "Location of FSP headers"
+ depends on MAINBOARD_USES_FSP2_0
+ default "src/vendorcode/intel/fsp/fsp2_0/skylake_sp"
+
+config MAX_SOCKET
+ int
+ default 2
+
+# For 2S config, the number of cpus could be as high as
+# 2 threads * 20 cores * 2 sockets
+config MAX_CPUS
+ int
+ default 80
+
+config PCR_BASE_ADDRESS
+ hex
+ default 0xfd000000
+ help
+ This option allows you to select MMIO Base Address of sideband bus.
+
+config DCACHE_RAM_BASE
+ hex
+ default 0xfe800000
+
+config DCACHE_RAM_SIZE
+ hex
+ default 0x200000
+
+config DCACHE_BSP_STACK_SIZE
+ hex
+ default 0x10000
+
+config MMCONF_BASE_ADDRESS
+ hex
+ default 0x80000000
+
+config CPU_MICROCODE_CBFS_LOC
+ hex
+ default 0xfff0fdc0
+
+config CPU_MICROCODE_CBFS_LEN
+ hex
+ default 0x7C00
+
+config C_ENV_BOOTBLOCK_SIZE
+ hex
+ default 0xC000
+
+config HEAP_SIZE
+ hex
+ default 0x80000
+
+
+endif ## SOC_INTEL_XEON_SP
diff --git a/src/soc/intel/xeon_sp/Makefile.inc b/src/soc/intel/xeon_sp/Makefile.inc
new file mode 100644
index 0000000..9ad3e77
--- /dev/null
+++ b/src/soc/intel/xeon_sp/Makefile.inc
@@ -0,0 +1,59 @@
+##
+## This file is part of the coreboot project.
+##
+## Copyright (C) 2019 - 2020 Intel Corporation
+## Copyright (C) 2019 - 2020 Facebook Inc
+##
+## 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
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+## GNU General Public License for more details.
+##
+
+ifeq ($(CONFIG_SOC_INTEL_XEON_SP),y)
+
+subdirs-y += ../../../cpu/intel/microcode
+subdirs-y += ../../../cpu/intel/turbo
+subdirs-y += ../../../cpu/x86/lapic
+subdirs-y += ../../../cpu/x86/mtrr
+subdirs-y += ../../../cpu/x86/tsc
+subdirs-y += ../../../cpu/x86/cache
+subdirs-$(CONFIG_HAVE_SMI_HANDLER) += ../../../cpu/x86/smm
+
+bootblock-y += bootblock/bootblock.c
+bootblock-y += spi.c
+
+postcar-y += soc_util.c
+postcar-y += spi.c
+
+romstage-y += soc_util.c
+romstage-y += reset.c
+romstage-y += romstage.c
+romstage-y += soc_util.c
+romstage-y += spi.c
+romstage-y += hob_display.c
+romstage-$(CONFIG_DISPLAY_UPD_DATA) += upd_display.c
+romstage-$(CONFIG_DISPLAY_HOBS) += hob_display.c
+
+ramstage-y += soc_util.c
+ramstage-y += uncore.c
+ramstage-y += reset.c
+ramstage-y += chip.c
+ramstage-y += soc_util.c
+ramstage-y += lpc.c
+ramstage-y += cpu.c
+ramstage-y += spi.c
+ramstage-$(CONFIG_HAVE_ACPI_TABLES) += acpi.c
+ramstage-$(CONFIG_DISPLAY_UPD_DATA) += upd_display.c
+ramstage-$(CONFIG_DISPLAY_HOBS) += hob_display.c
+ramstage-y += hob_display.c
+
+CPPFLAGS_common += -I$(src)/soc/intel/xeon_sp/include
+CPPFLAGS_common += -I$(CONFIG_FSP_HEADER_PATH)
+
+endif ## CONFIG_SOC_INTEL_XEON_SP
diff --git a/src/soc/intel/xeon_sp/acpi.c b/src/soc/intel/xeon_sp/acpi.c
new file mode 100644
index 0000000..37dd420
--- /dev/null
+++ b/src/soc/intel/xeon_sp/acpi.c
@@ -0,0 +1,1017 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2019 - 2020 Intel Corporation
+ * Copyright (C) 2019 - 2020 Facebook Inc
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <assert.h>
+#include <arch/acpigen.h>
+#include <arch/smp/mpspec.h>
+#include <intelblocks/acpi.h>
+#include <device/pci.h>
+#include <cbmem.h>
+#include <soc/acpi.h>
+#include <soc/cpu.h>
+#include <soc/pci_devs.h>
+#include <soc/soc_util.h>
+#include <soc/pm.h>
+#include "chip.h"
+
+static int acpi_sci_irq(void)
+{
+ int sci_irq = 9;
+ int32_t scis;
+
+ scis = soc_read_sci_irq_select();
+ scis &= SCI_IRQ_SEL;
+ scis >>= SCI_IRQ_ADJUST;
+
+ /* Determine how SCI is routed. */
+ switch (scis) {
+ case SCIS_IRQ9:
+ case SCIS_IRQ10:
+ case SCIS_IRQ11:
+ sci_irq = scis - SCIS_IRQ9 + 9;
+ break;
+ case SCIS_IRQ20:
+ case SCIS_IRQ21:
+ case SCIS_IRQ22:
+ case SCIS_IRQ23:
+ sci_irq = scis - SCIS_IRQ20 + 20;
+ break;
+ default:
+ printk(BIOS_DEBUG, "Invalid SCI route! Defaulting to IRQ9.\n");
+ sci_irq = 9;
+ break;
+ }
+
+ printk(BIOS_DEBUG, "SCI is IRQ%d\n", sci_irq);
+ return sci_irq;
+}
+
+void acpi_init_gnvs(global_nvs_t *gnvs)
+{
+ /* CPU core count */
+ gnvs->pcnt = dev_count_cpu();
+ printk(BIOS_DEBUG, "%s gnvs->pcnt: %d\n", __func__, gnvs->pcnt);
+
+ /* Update the mem console pointer. */
+ if (CONFIG(CONSOLE_CBMEM))
+ gnvs->cbmc = (uint32_t)cbmem_find(CBMEM_ID_CONSOLE);
+}
+
+uint32_t soc_read_sci_irq_select(void)
+{
+ struct device *dev = PCH_DEV_PMC;
+
+ if (!dev)
+ return 0;
+
+ return pci_read_config32(dev, PMC_ACPI_CNT);
+}
+
+acpi_cstate_t *soc_get_cstate_map(size_t *entries)
+{
+ *entries = 0;
+ return NULL;
+}
+
+unsigned long acpi_fill_mcfg(unsigned long current)
+{
+ current += acpi_create_mcfg_mmconfig((acpi_mcfg_mmconfig_t *)current,
+ CONFIG_MMCONF_BASE_ADDRESS, 0, 0, 255);
+ return current;
+}
+
+unsigned long acpi_madt_irq_overrides(unsigned long current)
+{
+ int sci = acpi_sci_irq();
+ uint16_t flags = MP_IRQ_TRIGGER_LEVEL;
+
+ /* INT_SRC_OVR */
+ current += acpi_create_madt_irqoverride((void *)current, 0, 0, 2, 0);
+
+ flags |= soc_madt_sci_irq_polarity(sci);
+
+ /* SCI */
+ current += acpi_create_madt_irqoverride((void *)current, 0, sci, sci, flags);
+
+ current +=
+ acpi_create_madt_lapic_nmi((acpi_madt_lapic_nmi_t *) current, 0xff, 0x0d, 1);
+
+ return current;
+}
+
+static unsigned long xeonsp_acpi_create_madt_lapics(unsigned long current)
+{
+ struct device *cpu;
+ int num_cpus = 0;
+
+ for (cpu = all_devices; cpu; cpu = cpu->next) {
+ if ((cpu->path.type != DEVICE_PATH_APIC) ||
+ (cpu->bus->dev->path.type != DEVICE_PATH_CPU_CLUSTER)) {
+ continue;
+ }
+ if (!cpu->enabled)
+ continue;
+ current += acpi_create_madt_lapic((acpi_madt_lapic_t *)current,
+ num_cpus, cpu->path.apic.apic_id);
+ }
+
+ return current;
+}
+
+unsigned long acpi_fill_madt(unsigned long current)
+{
+ size_t hob_size = 0;
+ const uint8_t fsp_hob_iio_universal_data_guid[16] =
+ FSP_HOB_IIO_UNIVERSAL_DATA_GUID;
+ const IIO_UDS *hob;
+ int cur_stack;
+
+ int gsi_bases[] = { 0, 0x18, 0x20, 0x28, 0x30, 0x48, 0x50, 0x58, 0x60 };
+ int ioapic_ids[] = { 0x8, 0x9, 0xa, 0xb, 0xc, 0xf, 0x10, 0x11, 0x12 };
+
+ /* Local APICs */
+ current = xeonsp_acpi_create_madt_lapics(current);
+
+ hob = fsp_find_extension_hob_by_guid(fsp_hob_iio_universal_data_guid, &hob_size);
+ assert(hob != NULL && hob_size != 0);
+
+ cur_stack = 0;
+ for (int socket = 0; socket < hob->PlatformData.numofIIO; ++socket) {
+ for (int stack = 0; stack < MAX_IIO_STACK; ++stack) {
+ const STACK_RES *ri =
+ &hob->PlatformData.IIO_resource[socket].StackRes[stack];
+ // TODO: do we have situation with only bus 0 and one stack?
+ if (ri->BusBase != ri->BusLimit) {
+ assert(cur_stack < ARRAY_SIZE(ioapic_ids));
+ assert(cur_stack < ARRAY_SIZE(gsi_bases));
+ int ioapic_id = ioapic_ids[cur_stack];
+ int gsi_base = gsi_bases[cur_stack];
+ printk(BIOS_DEBUG, "Adding MADT IOAPIC for socket: %d, stack: %d, ioapic_id: 0x%x, "
+ "ioapic_base: 0x%x, gsi_base: 0x%x\n",
+ socket, stack, ioapic_id, ri->IoApicBase, gsi_base);
+ current += acpi_create_madt_ioapic(
+ (acpi_madt_ioapic_t *)current,
+ ioapic_id, ri->IoApicBase, gsi_base);
+ ++cur_stack;
+
+ if (socket == 0 && stack == 0) {
+ assert(cur_stack < ARRAY_SIZE(ioapic_ids));
+ assert(cur_stack < ARRAY_SIZE(gsi_bases));
+ ioapic_id = ioapic_ids[cur_stack];
+ gsi_base = gsi_bases[cur_stack];
+ printk(BIOS_DEBUG, "Adding MADT IOAPIC for socket: %d, stack: %d, ioapic_id: 0x%x, "
+ "ioapic_base: 0x%x, gsi_base: 0x%x\n",
+ socket, stack, ioapic_id,
+ ri->IoApicBase + 0x1000, gsi_base);
+ current += acpi_create_madt_ioapic(
+ (acpi_madt_ioapic_t *)current,
+ ioapic_id, ri->IoApicBase + 0x1000, gsi_base);
+ ++cur_stack;
+ }
+ }
+ }
+ }
+
+ return acpi_madt_irq_overrides(current);
+}
+
+__attribute__ ((weak)) void motherboard_fill_fadt(acpi_fadt_t *fadt)
+{
+}
+
+void generate_t_state_entries(int core, int cores_per_package)
+{
+}
+
+void generate_p_state_entries(int core, int cores_per_package)
+{
+}
+
+void generate_cpu_entries(struct device *device)
+{
+ int core_id, cpu_id, pcontrol_blk = ACPI_BASE_ADDRESS;
+ int plen = 6;
+ int total_threads = dev_count_cpu();
+ int threads_per_package = get_threads_per_package();
+ int numcpus = total_threads / threads_per_package;
+
+ printk(BIOS_DEBUG, "Found %d CPU(s) with %d core(s) each, totalcores: %d.\n",
+ numcpus, threads_per_package, total_threads);
+
+ for (cpu_id = 0; cpu_id < numcpus; cpu_id++) {
+ for (core_id = 0; core_id < threads_per_package; core_id++) {
+ if (core_id > 0) {
+ pcontrol_blk = 0;
+ plen = 0;
+ }
+
+ /* Generate processor \_PR.CPUx */
+ acpigen_write_processor((cpu_id) * threads_per_package +
+ core_id, pcontrol_blk, plen);
+
+ /* NOTE: Intel idle driver doesn't use ACPI C-state tables */
+
+ /* TODO: Soc specific power states generation */
+ acpigen_pop_len();
+ }
+ }
+ /* PPKG is usually used for thermal management
+ of the first and only package. */
+ acpigen_write_processor_package("PPKG", 0, threads_per_package);
+
+ /* Add a method to notify processor nodes */
+ acpigen_write_processor_cnot(threads_per_package);
+}
+
+void soc_fill_fadt(acpi_fadt_t *fadt)
+{
+ uint16_t pmbase = ACPI_BASE_ADDRESS;
+
+ /* System Management */
+ if (!CONFIG(HAVE_SMI_HANDLER)) {
+ fadt->smi_cmd = 0x00;
+ fadt->acpi_enable = 0x00;
+ fadt->acpi_disable = 0x00;
+ }
+
+ /* Power Control */
+ fadt->pm2_cnt_blk = pmbase + PM2_CNT;
+ fadt->pm_tmr_blk = pmbase + PM1_TMR;
+ fadt->gpe1_blk = 0;
+
+ /* Control Registers - Length */
+ fadt->pm2_cnt_len = 1;
+ fadt->pm_tmr_len = 4;
+ /* There are 4 GPE0 STS/EN pairs each 32 bits wide. */
+ fadt->gpe0_blk_len = 2 * GPE0_REG_MAX * sizeof(uint32_t);
+ fadt->gpe1_blk_len = 0;
+ fadt->gpe1_base = 0;
+ fadt->cst_cnt = 0;
+ fadt->p_lvl2_lat = ACPI_FADT_C2_NOT_SUPPORTED;
+ fadt->p_lvl3_lat = ACPI_FADT_C3_NOT_SUPPORTED;
+ fadt->flush_size = 0; /* set to 0 if WBINVD is 1 in flags */
+ fadt->flush_stride = 0; /* set to 0 if WBINVD is 1 in flags */
+ fadt->duty_offset = 1;
+ fadt->duty_width = 0;
+
+ /* RTC Registers */
+ fadt->day_alrm = 0x0D;
+ fadt->mon_alrm = 0x00;
+ fadt->century = 0x00;
+ fadt->iapc_boot_arch = ACPI_FADT_LEGACY_DEVICES | ACPI_FADT_8042;
+
+ fadt->flags = ACPI_FADT_WBINVD | ACPI_FADT_C1_SUPPORTED |
+ ACPI_FADT_C2_MP_SUPPORTED | ACPI_FADT_SLEEP_BUTTON |
+ ACPI_FADT_RESET_REGISTER | ACPI_FADT_SLEEP_TYPE |
+ ACPI_FADT_S4_RTC_WAKE | ACPI_FADT_PLATFORM_CLOCK;
+
+ /* Reset Register */
+ fadt->reset_reg.space_id = ACPI_ADDRESS_SPACE_IO;
+ fadt->reset_reg.bit_width = 8;
+ fadt->reset_reg.bit_offset = 0;
+ fadt->reset_reg.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
+ fadt->reset_reg.addrl = 0xCF9;
+ fadt->reset_reg.addrh = 0x00;
+ fadt->reset_value = 6;
+
+ /* PM1 Status & PM1 Enable */
+ fadt->x_pm1a_evt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
+ fadt->x_pm1a_evt_blk.bit_width = 32;
+ fadt->x_pm1a_evt_blk.bit_offset = 0;
+ fadt->x_pm1a_evt_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
+ fadt->x_pm1a_evt_blk.addrl = fadt->pm1a_evt_blk;
+ fadt->x_pm1a_evt_blk.addrh = 0x00;
+
+ fadt->x_pm1b_evt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
+ fadt->x_pm1b_evt_blk.bit_width = 0;
+ fadt->x_pm1b_evt_blk.bit_offset = 0;
+ fadt->x_pm1b_evt_blk.access_size = 0;
+ fadt->x_pm1b_evt_blk.addrl = fadt->pm1b_evt_blk;
+ fadt->x_pm1b_evt_blk.addrh = 0x00;
+
+ /* PM1 Control Registers */
+ fadt->x_pm1a_cnt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
+ fadt->x_pm1a_cnt_blk.bit_width = 16;
+ fadt->x_pm1a_cnt_blk.bit_offset = 0;
+ fadt->x_pm1a_cnt_blk.access_size = ACPI_ACCESS_SIZE_WORD_ACCESS;
+ fadt->x_pm1a_cnt_blk.addrl = fadt->pm1a_cnt_blk;
+ fadt->x_pm1a_cnt_blk.addrh = 0x00;
+
+ fadt->x_pm1b_cnt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
+ fadt->x_pm1b_cnt_blk.bit_width = 0;
+ fadt->x_pm1b_cnt_blk.bit_offset = 0;
+ fadt->x_pm1b_cnt_blk.access_size = 0;
+ fadt->x_pm1b_cnt_blk.addrl = fadt->pm1b_cnt_blk;
+ fadt->x_pm1b_cnt_blk.addrh = 0x00;
+
+ /* PM2 Control Registers */
+ fadt->x_pm2_cnt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
+ fadt->x_pm2_cnt_blk.bit_width = 8;
+ fadt->x_pm2_cnt_blk.bit_offset = 0;
+ fadt->x_pm2_cnt_blk.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
+ fadt->x_pm2_cnt_blk.addrl = fadt->pm2_cnt_blk;
+ fadt->x_pm2_cnt_blk.addrh = 0x00;
+
+ /* PM1 Timer Register */
+ fadt->x_pm_tmr_blk.space_id = ACPI_ADDRESS_SPACE_IO;
+ fadt->x_pm_tmr_blk.bit_width = 32;
+ fadt->x_pm_tmr_blk.bit_offset = 0;
+ fadt->x_pm_tmr_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
+ fadt->x_pm_tmr_blk.addrl = fadt->pm_tmr_blk;
+ fadt->x_pm_tmr_blk.addrh = 0x00;
+
+ /* General-Purpose Event Registers */
+ fadt->x_gpe0_blk.space_id = ACPI_ADDRESS_SPACE_IO;
+ fadt->x_gpe0_blk.bit_width = 64; /* EventStatus + EventEnable */
+ fadt->x_gpe0_blk.bit_offset = 0;
+ fadt->x_gpe0_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
+ fadt->x_gpe0_blk.addrl = fadt->gpe0_blk;
+ fadt->x_gpe0_blk.addrh = 0x00;
+
+ fadt->x_gpe1_blk.space_id = ACPI_ADDRESS_SPACE_IO;
+ fadt->x_gpe1_blk.bit_width = 0;
+ fadt->x_gpe1_blk.bit_offset = 0;
+ fadt->x_gpe1_blk.access_size = 0;
+ fadt->x_gpe1_blk.addrl = fadt->gpe1_blk;
+ fadt->x_gpe1_blk.addrh = 0x00;
+
+ motherboard_fill_fadt(fadt);
+}
+
+void acpi_fill_fadt(acpi_fadt_t *fadt)
+{
+ const uint16_t pmbase = ACPI_BASE_ADDRESS;
+
+ /* Use ACPI 3.0 revision */
+ fadt->header.revision = get_acpi_table_revision(FADT);
+
+ fadt->sci_int = acpi_sci_irq();
+ /*
+ TODO: enabled SMM mode switch when SMM handlers are set up.
+ fadt->smi_cmd = APM_CNT;
+ fadt->acpi_enable = APM_CNT_ACPI_ENABLE;
+ fadt->acpi_disable = APM_CNT_ACPI_DISABLE;
+ */
+ fadt->smi_cmd = 0x00;
+ fadt->acpi_enable = 0x00;
+ fadt->acpi_disable = 0x00;
+ fadt->s4bios_req = 0x0;
+ fadt->pstate_cnt = 0;
+
+ fadt->pm1a_evt_blk = pmbase + PM1_STS;
+ fadt->pm1b_evt_blk = 0x0;
+ fadt->pm1a_cnt_blk = pmbase + PM1_CNT;
+ fadt->pm1b_cnt_blk = 0x0;
+ fadt->pm2_cnt_blk = pmbase + PM2_CNT;
+ fadt->pm_tmr_blk = pmbase + PM1_TMR;
+ fadt->gpe0_blk = pmbase + GPE0_STS(0);
+ fadt->gpe1_blk = 0;
+
+ fadt->pm1_evt_len = 4;
+ fadt->pm1_cnt_len = 2;
+ fadt->pm2_cnt_len = 1;
+ fadt->pm_tmr_len = 4;
+ /* There are 4 GPE0 STS/EN pairs each 32 bits wide. */
+ fadt->gpe0_blk_len = 2 * GPE0_REG_MAX * sizeof(uint32_t);
+ fadt->gpe1_blk_len = 0;
+ fadt->gpe1_base = 0;
+ fadt->cst_cnt = 0;
+ fadt->p_lvl2_lat = 1;
+ fadt->p_lvl3_lat = 87;
+ fadt->flush_size = 1024;
+ fadt->flush_stride = 16;
+ fadt->duty_offset = 1;
+ fadt->duty_width = 0;
+ fadt->day_alrm = 0xd;
+ fadt->mon_alrm = 0x00;
+ fadt->century = 0x00;
+ fadt->iapc_boot_arch = ACPI_FADT_LEGACY_FREE;
+ if (!CONFIG(NO_FADT_8042))
+ fadt->iapc_boot_arch |= ACPI_FADT_8042;
+
+ fadt->flags = ACPI_FADT_WBINVD | ACPI_FADT_C1_SUPPORTED |
+ ACPI_FADT_C2_MP_SUPPORTED | ACPI_FADT_SLEEP_BUTTON |
+ ACPI_FADT_RESET_REGISTER | ACPI_FADT_SEALED_CASE |
+ ACPI_FADT_S4_RTC_WAKE | ACPI_FADT_PLATFORM_CLOCK;
+
+ fadt->reset_reg.space_id = 1;
+ fadt->reset_reg.bit_width = 8;
+ fadt->reset_reg.bit_offset = 0;
+ fadt->reset_reg.access_size = 0;
+ fadt->reset_reg.addrl = 0xcf9;
+ fadt->reset_reg.addrh = 0;
+ fadt->reset_value = 6;
+
+ fadt->x_pm1a_evt_blk.space_id = 1;
+ fadt->x_pm1a_evt_blk.bit_width = fadt->pm1_evt_len * 8;
+ fadt->x_pm1a_evt_blk.bit_offset = 0;
+ fadt->x_pm1a_evt_blk.access_size = 0;
+ fadt->x_pm1a_evt_blk.addrl = pmbase + PM1_STS;
+ fadt->x_pm1a_evt_blk.addrh = 0x0;
+
+ fadt->x_pm1b_evt_blk.space_id = 1;
+ fadt->x_pm1b_evt_blk.bit_width = 0;
+ fadt->x_pm1b_evt_blk.bit_offset = 0;
+ fadt->x_pm1b_evt_blk.access_size = 0;
+ fadt->x_pm1b_evt_blk.addrl = 0x0;
+ fadt->x_pm1b_evt_blk.addrh = 0x0;
+
+ fadt->x_pm1a_cnt_blk.space_id = 1;
+ fadt->x_pm1a_cnt_blk.bit_width = fadt->pm1_cnt_len * 8;
+ fadt->x_pm1a_cnt_blk.bit_offset = 0;
+ fadt->x_pm1a_cnt_blk.access_size = 0;
+ fadt->x_pm1a_cnt_blk.addrl = pmbase + PM1_CNT;
+ fadt->x_pm1a_cnt_blk.addrh = 0x0;
+
+ fadt->x_pm1b_cnt_blk.space_id = 1;
+ fadt->x_pm1b_cnt_blk.bit_width = 0;
+ fadt->x_pm1b_cnt_blk.bit_offset = 0;
+ fadt->x_pm1b_cnt_blk.access_size = 0;
+ fadt->x_pm1b_cnt_blk.addrl = 0x0;
+ fadt->x_pm1b_cnt_blk.addrh = 0x0;
+
+ fadt->x_pm2_cnt_blk.space_id = 1;
+ fadt->x_pm2_cnt_blk.bit_width = fadt->pm2_cnt_len * 8;
+ fadt->x_pm2_cnt_blk.bit_offset = 0;
+ fadt->x_pm2_cnt_blk.access_size = 0;
+ fadt->x_pm2_cnt_blk.addrl = pmbase + PM2_CNT;
+ fadt->x_pm2_cnt_blk.addrh = 0x0;
+
+ fadt->x_pm_tmr_blk.space_id = 1;
+ fadt->x_pm_tmr_blk.bit_width = fadt->pm_tmr_len * 8;
+ fadt->x_pm_tmr_blk.bit_offset = 0;
+ fadt->x_pm_tmr_blk.access_size = 0;
+ fadt->x_pm_tmr_blk.addrl = pmbase + PM1_TMR;
+ fadt->x_pm_tmr_blk.addrh = 0x0;
+
+ fadt->x_gpe0_blk.space_id = 0;
+ fadt->x_gpe0_blk.bit_width = 0;
+ fadt->x_gpe0_blk.bit_offset = 0;
+ fadt->x_gpe0_blk.access_size = 0;
+ fadt->x_gpe0_blk.addrl = 0;
+ fadt->x_gpe0_blk.addrh = 0;
+
+ fadt->x_gpe1_blk.space_id = 1;
+ fadt->x_gpe1_blk.bit_width = 0;
+ fadt->x_gpe1_blk.bit_offset = 0;
+ fadt->x_gpe1_blk.access_size = 0;
+ fadt->x_gpe1_blk.addrl = 0x0;
+ fadt->x_gpe1_blk.addrh = 0x0;
+
+ soc_fill_fadt(fadt);
+}
+
+static acpi_tstate_t xeon_sp_tss_table[] = {
+ { 100, 1000, 0, 0x00, 0 },
+ { 88, 875, 0, 0x1e, 0 },
+ { 75, 750, 0, 0x1c, 0 },
+ { 63, 625, 0, 0x1a, 0 },
+ { 50, 500, 0, 0x18, 0 },
+ { 38, 375, 0, 0x16, 0 },
+ { 25, 250, 0, 0x14, 0 },
+ { 13, 125, 0, 0x12, 0 },
+};
+
+acpi_tstate_t *soc_get_tss_table(int *entries)
+{
+ *entries = ARRAY_SIZE(xeon_sp_tss_table);
+ return xeon_sp_tss_table;
+}
+
+int soc_madt_sci_irq_polarity(int sci)
+{
+ if (sci >= 20)
+ return MP_IRQ_POLARITY_LOW;
+ else
+ return MP_IRQ_POLARITY_HIGH;
+}
+
+unsigned long southbridge_write_acpi_tables(struct device *device,
+ unsigned long current,
+ struct acpi_rsdp *rsdp)
+{
+ current = acpi_write_hpet(device, current, rsdp);
+ current = (ALIGN(current, 16));
+ printk(BIOS_DEBUG, "current = %lx\n", current);
+ return current;
+}
+
+unsigned long acpi_create_srat_lapics(unsigned long current)
+{
+ struct device *cpu;
+ int cpu_index = 0;
+
+ for (cpu = all_devices; cpu; cpu = cpu->next) {
+ if ((cpu->path.type != DEVICE_PATH_APIC) ||
+ (cpu->bus->dev->path.type != DEVICE_PATH_CPU_CLUSTER)) {
+ continue;
+ }
+ if (!cpu->enabled)
+ continue;
+ printk(BIOS_DEBUG, "SRAT: lapic cpu_index=%02x, node_id=%02x, apic_id=%02x\n",
+ cpu_index, cpu->path.apic.node_id, cpu->path.apic.apic_id);
+ current += acpi_create_srat_lapic((acpi_srat_lapic_t *)current,
+ cpu->path.apic.node_id, cpu->path.apic.apic_id);
+ cpu_index++;
+ }
+ return current;
+}
+
+static unsigned long acpi_fill_srat(unsigned long current)
+{
+ acpi_srat_mem_t srat_mem[MAX_ACPI_MEMORY_AFFINITY_COUNT];
+ unsigned int mem_count;
+
+ /* create all subtables for processors */
+ current = acpi_create_srat_lapics(current);
+
+ mem_count = get_srat_memory_entries(srat_mem);
+ for (int i = 0; i < mem_count; ++i) {
+ printk(BIOS_DEBUG, "adding srat memory %d entry length: %d, addr: 0x%x%x, "
+ "length: 0x%x%x, proximity_domain: %d, flags: %x\n",
+ i, srat_mem[i].length,
+ srat_mem[i].base_address_high, srat_mem[i].base_address_low,
+ srat_mem[i].length_high, srat_mem[i].length_low,
+ srat_mem[i].proximity_domain, srat_mem[i].flags);
+ memcpy((acpi_srat_mem_t *)current, &srat_mem[i], sizeof(srat_mem[i]));
+ current += srat_mem[i].length;
+ }
+
+ return current;
+}
+
+static unsigned long acpi_fill_slit(unsigned long current)
+{
+ int nodes = get_cpu_count();
+
+ uint8_t *p = (uint8_t *)current;
+ memset(p, 0, 8 + nodes * nodes);
+ *p = (uint8_t)nodes;
+ p += 8;
+
+ /* this assumes fully connected socket topology */
+ for (int i = 0; i < nodes; i++) {
+ for (int j = 0; j < nodes; j++) {
+ if (i == j)
+ p[i*nodes+j] = 10;
+ else
+ p[i*nodes+j] = 16;
+ }
+ }
+
+ current += 8+nodes*nodes;
+ return current;
+}
+
+static int get_stack_for_port(int p)
+{
+ if (p == 0)
+ return CSTACK;
+ else if (p >= PORT_1A && p <= PORT_1D)
+ return PSTACK0;
+ else if (p >= PORT_2A && p <= PORT_2D)
+ return PSTACK1;
+ else if (p >= PORT_3A && p <= PORT_3D)
+ return PSTACK2;
+ else if (p >= PORT_4A && p <= PORT_4D)
+ return PSTACK3; // MCP0
+ else
+ return PSTACK4; // MCP1
+}
+
+static unsigned long acpi_create_drhd(unsigned long current, int socket, int stack)
+{
+ int IoApicID[] = {
+ // socket 0
+ PC00_IOAPIC_ID, PC01_IOAPIC_ID, PC02_IOAPIC_ID, PC03_IOAPIC_ID,
+ PC04_IOAPIC_ID, PC05_IOAPIC_ID,
+ // socket 1
+ PC06_IOAPIC_ID, PC07_IOAPIC_ID, PC08_IOAPIC_ID, PC09_IOAPIC_ID,
+ PC10_IOAPIC_ID, PC11_IOAPIC_ID,
+ };
+
+ uint32_t enum_id;
+ unsigned long tmp = current;
+
+ size_t hob_size;
+ const uint8_t fsp_hob_iio_universal_data_guid[16] = FSP_HOB_IIO_UNIVERSAL_DATA_GUID;
+ const IIO_UDS *hob = fsp_find_extension_hob_by_guid(
+ fsp_hob_iio_universal_data_guid, &hob_size);
+ assert(hob != NULL && hob_size != 0);
+
+ uint32_t bus = hob->PlatformData.CpuQpiInfo[socket].StackBus[stack];
+ uint32_t pcie_seg = hob->PlatformData.CpuQpiInfo[socket].PcieSegment;
+ uint32_t reg_base =
+ hob->PlatformData.IIO_resource[socket].StackRes[stack].VtdBarAddress;
+ printk(BIOS_SPEW, "%s socket: %d, stack: %d, bus: 0x%x, pcie_seg: 0x%x, reg_base: 0x%x\n",
+ __func__, socket, stack, bus, pcie_seg, reg_base);
+
+ // Add DRHD Hardware Unit
+ if (socket == 0 && stack == CSTACK) {
+ printk(BIOS_DEBUG, "[Hardware Unit Definition] Flags: 0x%x, PCI Segment Number: 0x%x, "
+ "Register Base Address: 0x%x\n",
+ DRHD_INCLUDE_PCI_ALL, pcie_seg, reg_base);
+ current += acpi_create_dmar_drhd(current, DRHD_INCLUDE_PCI_ALL,
+ pcie_seg, reg_base);
+ } else {
+ printk(BIOS_DEBUG, "[Hardware Unit Definition] Flags: 0x%x, PCI Segment Number: 0x%x, "
+ "Register Base Address: 0x%x\n", 0, pcie_seg, reg_base);
+ current += acpi_create_dmar_drhd(current, 0, pcie_seg, reg_base);
+ }
+
+ // Add PCH IOAPIC
+ if (socket == 0 && stack == CSTACK) {
+ printk(BIOS_DEBUG, " [IOAPIC Device] Enumeration ID: 0x%x, PCI Bus Number: 0x%x, "
+ "PCI Path: 0x%x, 0x%x\n",
+ PCH_IOAPIC_ID, PCH_IOAPIC_BUS_NUMBER,
+ PCH_IOAPIC_DEV_NUM, PCH_IOAPIC_FUNC_NUM);
+ current += acpi_create_dmar_ds_ioapic(current, PCH_IOAPIC_ID,
+ PCH_IOAPIC_BUS_NUMBER, PCH_IOAPIC_DEV_NUM, PCH_IOAPIC_FUNC_NUM);
+ }
+
+ // Add IOAPIC entry
+ enum_id = IoApicID[(socket*MAX_IIO_STACK)+stack];
+ printk(BIOS_DEBUG, " [IOAPIC Device] Enumeration ID: 0x%x, PCI Bus Number: 0x%x, "
+ "PCI Path: 0x%x, 0x%x\n", enum_id, bus, APIC_DEV_NUM, APIC_FUNC_NUM);
+ current += acpi_create_dmar_ds_ioapic(current, enum_id, bus,
+ APIC_DEV_NUM, APIC_FUNC_NUM);
+
+ // Add CBDMA devices for CSTACK
+ if (socket != 0 && stack == CSTACK) {
+ for (int cbdma_func_id = 0; cbdma_func_id < 8; ++cbdma_func_id) {
+ printk(BIOS_DEBUG, " [PCI Endpoint Device] Enumeration ID: 0x%x, "
+ "PCI Bus Number: 0x%x, PCI Path: 0x%x, 0x%x\n",
+ 0, bus, CBDMA_DEV_NUM, cbdma_func_id);
+ current += acpi_create_dmar_ds_pci(current,
+ bus, CBDMA_DEV_NUM, cbdma_func_id);
+ }
+ }
+
+ // Add PCIe Ports
+ if (socket != 0 || stack != CSTACK) {
+ IIO_RESOURCE_INSTANCE iio_resource =
+ hob->PlatformData.IIO_resource[socket];
+ for (int p = 0; p < NUMBER_PORTS_PER_SOCKET; ++p) {
+ if (get_stack_for_port(p) != stack)
+ continue;
+
+ uint32_t dev = iio_resource.PcieInfo.PortInfo[p].Device;
+ uint32_t func = iio_resource.PcieInfo.PortInfo[p].Function;
+
+ uint32_t id = pci_mmio_read_config32(PCI_DEV(bus, dev, func),
+ PCI_VENDOR_ID);
+ if (id == 0xffffffff)
+ continue;
+
+ printk(BIOS_DEBUG, " [PCI Bridge Device] Enumeration ID: 0x%x, "
+ "PCI Bus Number: 0x%x, PCI Path: 0x%x, 0x%x\n",
+ 0, bus, dev, func);
+ current += acpi_create_dmar_ds_pci_br(current,
+ bus, dev, func);
+ }
+
+ // Add VMD
+ if (hob->PlatformData.VMDStackEnable[socket][stack] &&
+ stack >= PSTACK0 && stack <= PSTACK2) {
+ printk(BIOS_DEBUG, " [PCI Endpoint Device] Enumeration ID: 0x%x, "
+ "PCI Bus Number: 0x%x, PCI Path: 0x%x, 0x%x\n",
+ 0, bus, VMD_DEV_NUM, VMD_FUNC_NUM);
+ current += acpi_create_dmar_ds_pci(current,
+ bus, VMD_DEV_NUM, VMD_FUNC_NUM);
+ }
+ }
+
+ // Add HPET
+ if (socket == 0 && stack == CSTACK) {
+ uint16_t hpet_capid = read16((void *)HPET_BASE_ADDRESS);
+ uint16_t num_hpets = (hpet_capid >> 0x08) & 0x1F; // Bits [8:12] has hpet count
+ printk(BIOS_SPEW, "%s hpet_capid: 0x%x, num_hpets: 0x%x\n",
+ __func__, hpet_capid, num_hpets);
+ //BIT 15
+ if (num_hpets && (num_hpets != 0x1f) &&
+ (read32((void *)(HPET_BASE_ADDRESS + 0x100)) & (0x00008000))) {
+ printk(BIOS_DEBUG, " [Message-capable HPET Device] Enumeration ID: 0x%x, "
+ "PCI Bus Number: 0x%x, PCI Path: 0x%x, 0x%x\n",
+ 0, HPET_BUS_NUM, HPET_DEV_NUM, HPET0_FUNC_NUM);
+ current += acpi_create_dmar_ds_msi_hpet(current, 0, HPET_BUS_NUM,
+ HPET_DEV_NUM, HPET0_FUNC_NUM);
+ }
+ }
+
+ acpi_dmar_drhd_fixup(tmp, current);
+
+ return current;
+}
+
+static unsigned long acpi_create_atsr(unsigned long current)
+{
+ size_t hob_size;
+ const uint8_t uds_guid[16] = FSP_HOB_IIO_UNIVERSAL_DATA_GUID;
+ const IIO_UDS *hob = fsp_find_extension_hob_by_guid(uds_guid, &hob_size);
+ assert(hob != NULL && hob_size != 0);
+
+ for (int socket = 0; socket < hob->PlatformData.numofIIO; ++socket) {
+ uint32_t pcie_seg = hob->PlatformData.CpuQpiInfo[socket].PcieSegment;
+ unsigned long tmp = current;
+ bool first = true;
+ IIO_RESOURCE_INSTANCE iio_resource =
+ hob->PlatformData.IIO_resource[socket];
+
+ for (int stack = 0; stack <= PSTACK2; ++stack) {
+ uint32_t bus = hob->PlatformData.CpuQpiInfo[socket].StackBus[stack];
+ uint32_t vtd_base = iio_resource.StackRes[stack].VtdBarAddress;
+ if (!vtd_base)
+ continue;
+ uint64_t vtd_mmio_cap = read64((void *)(vtd_base + VTD_EXT_CAP_LOW));
+ printk(BIOS_SPEW, "%s socket: %d, stack: %d, bus: 0x%x, vtd_base: 0x%x, "
+ "vtd_mmio_cap: 0x%llx\n",
+ __func__, socket, stack, bus, vtd_base, vtd_mmio_cap);
+
+ // ATSR is applicable only for platform supporting device IOTLBs
+ // through the VT-d extended capability register
+ assert(vtd_mmio_cap != 0xffffffffffffffff);
+ if ((vtd_mmio_cap & 0x4) == 0) // BIT 2
+ continue;
+
+ for (int p = 0; p < NUMBER_PORTS_PER_SOCKET; ++p) {
+ if (socket == 0 && p == 0)
+ continue;
+ if (get_stack_for_port(p) != stack)
+ continue;
+
+ uint32_t dev = iio_resource.PcieInfo.PortInfo[p].Device;
+ uint32_t func = iio_resource.PcieInfo.PortInfo[p].Function;
+
+ u32 id = pci_mmio_read_config32(PCI_DEV(bus, dev, func),
+ PCI_VENDOR_ID);
+ if (id == 0xffffffff)
+ continue;
+
+ if (first) {
+ printk(BIOS_DEBUG, "[Root Port ATS Capability] Flags: 0x%x, "
+ "PCI Segment Number: 0x%x\n",
+ 0, pcie_seg);
+ current += acpi_create_dmar_atsr(current, 0, pcie_seg);
+ first = 0;
+ }
+
+ printk(BIOS_DEBUG, " [PCI Bridge Device] Enumeration ID: 0x%x, "
+ "PCI Bus Number: 0x%x, PCI Path: 0x%x, 0x%x\n",
+ 0, bus, dev, func);
+ current += acpi_create_dmar_ds_pci_br(current, bus, dev, func);
+ }
+ }
+ if (tmp != current)
+ acpi_dmar_atsr_fixup(tmp, current);
+ }
+
+ return current;
+}
+
+static unsigned long acpi_create_rmrr(unsigned long current)
+{
+ uint32_t size = ALIGN_UP(MEM_BLK_COUNT * sizeof(MEM_BLK), 0x1000);
+
+ uint32_t *ptr;
+
+ // reserve memory
+ ptr = cbmem_find(CBMEM_ID_STORAGE_DATA);
+ if (!ptr) {
+ ptr = cbmem_add(CBMEM_ID_STORAGE_DATA, size);
+ assert(ptr != NULL);
+ memset(ptr, 0, size);
+ }
+
+ unsigned long tmp = current;
+ printk(BIOS_DEBUG, "[Reserved Memory Region] PCI Segment Number: 0x%x, Base Address: 0x%x, "
+ "End Address (limit): 0x%x\n",
+ 0, (uint32_t) ptr, (uint32_t) ((uint32_t) ptr + size - 1));
+ current += acpi_create_dmar_rmrr(current, 0, (uint32_t) ptr,
+ (uint32_t) ((uint32_t) ptr + size - 1));
+
+ printk(BIOS_DEBUG, " [PCI Endpoint Device] Enumeration ID: 0x%x, PCI Bus Number: 0x%x, "
+ "PCI Path: 0x%x, 0x%x\n",
+ 0, XHCI_BUS_NUMBER, PCH_DEV_SLOT_XHCI, XHCI_FUNC_NUM);
+ current += acpi_create_dmar_ds_pci(current, XHCI_BUS_NUMBER,
+ PCH_DEV_SLOT_XHCI, XHCI_FUNC_NUM);
+
+ acpi_dmar_rmrr_fixup(tmp, current);
+
+ return current;
+}
+
+static unsigned long acpi_create_rhsa(unsigned long current)
+{
+ size_t hob_size;
+ const uint8_t uds_guid[16] = FSP_HOB_IIO_UNIVERSAL_DATA_GUID;
+ const IIO_UDS *hob = fsp_find_extension_hob_by_guid(uds_guid, &hob_size);
+ assert(hob != NULL && hob_size != 0);
+
+ for (int socket = 0; socket < hob->PlatformData.numofIIO; ++socket) {
+ IIO_RESOURCE_INSTANCE iio_resource =
+ hob->PlatformData.IIO_resource[socket];
+ for (int stack = 0; stack <= PSTACK2; ++stack) {
+ uint32_t vtd_base = iio_resource.StackRes[stack].VtdBarAddress;
+ if (!vtd_base)
+ continue;
+
+ printk(BIOS_DEBUG, "[Remapping Hardware Static Affinity] Base Address: 0x%x, "
+ "Proximity Domain: 0x%x\n", vtd_base, socket);
+ current += acpi_create_dmar_rhsa(current, vtd_base, socket);
+ }
+ }
+
+ return current;
+}
+
+static unsigned long acpi_fill_dmar(unsigned long current)
+{
+ size_t hob_size;
+ const uint8_t uds_guid[16] = FSP_HOB_IIO_UNIVERSAL_DATA_GUID;
+ const IIO_UDS *hob = fsp_find_extension_hob_by_guid(uds_guid, &hob_size);
+ assert(hob != NULL && hob_size != 0);
+
+ // DRHD
+ for (int iio = 1; iio <= hob->PlatformData.numofIIO; ++iio) {
+ int socket = iio;
+ if (socket == hob->PlatformData.numofIIO) // socket 0 should be last DRHD entry
+ socket = 0;
+
+ if (socket == 0) {
+ for (int stack = 1; stack <= PSTACK2; ++stack)
+ current = acpi_create_drhd(current, socket, stack);
+ current = acpi_create_drhd(current, socket, CSTACK);
+ } else {
+ for (int stack = 0; stack <= PSTACK2; ++stack)
+ current = acpi_create_drhd(current, socket, stack);
+ }
+ }
+
+ // RMRR
+ current = acpi_create_rmrr(current);
+
+ // ATSR - causes hang
+ current = acpi_create_atsr(current);
+
+ // RHSA
+ current = acpi_create_rhsa(current);
+
+ return current;
+}
+
+unsigned long northbridge_write_acpi_tables(struct device *device,
+ unsigned long current,
+ struct acpi_rsdp *rsdp)
+{
+ acpi_srat_t *srat;
+ acpi_slit_t *slit;
+ acpi_dmar_t *dmar;
+
+ const struct soc_intel_xeon_sp_config *const config = config_of(device);
+
+ /* SRAT */
+ current = ALIGN(current, 8);
+ printk(BIOS_DEBUG, "ACPI: * SRAT at %lx\n", current);
+ srat = (acpi_srat_t *) current;
+ acpi_create_srat(srat, acpi_fill_srat);
+ current += srat->header.length;
+ acpi_add_table(rsdp, srat);
+
+ /* SLIT */
+ current = ALIGN(current, 8);
+ printk(BIOS_DEBUG, "ACPI: * SLIT at %lx\n", current);
+ slit = (acpi_slit_t *) current;
+ acpi_create_slit(slit, acpi_fill_slit);
+ current += slit->header.length;
+ acpi_add_table(rsdp, slit);
+
+ /* DMAR */
+ if (config->vtd_support) {
+ current = ALIGN(current, 8);
+ dmar = (acpi_dmar_t *)current;
+ printk(BIOS_DEBUG, "ACPI: * DMAR\n");
+ printk(BIOS_DEBUG, "[DMA Remapping table] Flags: 0x%x\n",
+ (DMAR_INTR_REMAP | DMAR_X2APIC_OPT_OUT));
+ acpi_create_dmar(dmar, (DMAR_INTR_REMAP | DMAR_X2APIC_OPT_OUT), acpi_fill_dmar);
+ current += dmar->header.length;
+ current = acpi_align_current(current);
+ acpi_add_table(rsdp, dmar);
+ }
+
+ return current;
+}
+
+void uncore_inject_dsdt(void)
+{
+ size_t hob_size;
+ const uint8_t uds_guid[16] = FSP_HOB_IIO_UNIVERSAL_DATA_GUID;
+ const IIO_UDS *hob = fsp_find_extension_hob_by_guid(uds_guid, &hob_size);
+ assert(hob != NULL && hob_size != 0);
+
+ acpigen_write_scope("\\_SB");
+ for (int socket = 0; socket < hob->PlatformData.numofIIO; ++socket) {
+ IIO_RESOURCE_INSTANCE iio_resource =
+ hob->PlatformData.IIO_resource[socket];
+ for (int stack = 0; stack <= PSTACK2; ++stack) {
+ const STACK_RES *ri = &iio_resource.StackRes[stack];
+ char rtname[16];
+ snprintf(rtname, sizeof(rtname), "RT%02x",
+ (socket*MAX_IIO_STACK)+stack);
+
+ acpigen_write_name(rtname);
+ printk(BIOS_DEBUG, "\tCreating ResourceTemplate %s for socket: %d, stack: %d\n",
+ rtname, socket, stack);
+
+ acpigen_write_resourcetemplate_header();
+
+ /* bus resource */
+ acpigen_resource_word(2, 0xc, 0, 0, ri->BusBase, ri->BusLimit,
+ 0x0, (ri->BusLimit - ri->BusBase + 1));
+
+ // additional io resources on socket 0 bus 0
+ if (socket == 0 && stack == 0) {
+ /* ACPI 6.4.2.5 I/O Port Descriptor */
+ acpigen_write_io16(0xCF8, 0xCFF, 0x1, 0x8, 1);
+
+ /* IO decode CF8-CFF */
+ acpigen_resource_word(1, 0xc, 0x3, 0, 0x0000, 0x03AF,
+ 0, 0x03B0);
+ acpigen_resource_word(1, 0xc, 0x3, 0, 0x03E0, 0x0CF7,
+ 0, 0x0918);
+ acpigen_resource_word(1, 0xc, 0x3, 0, 0x03B0, 0x03BB,
+ 0, 0x000C);
+ acpigen_resource_word(1, 0xc, 0x3, 0, 0x03C0, 0x03DF,
+ 0, 0x0020);
+ }
+
+ /* IO resource */
+ acpigen_resource_word(1, 0xc, 0x3, 0, ri->PciResourceIoBase,
+ ri->PciResourceIoLimit, 0x0,
+ (ri->PciResourceIoLimit - ri->PciResourceIoBase + 1));
+
+ // additional mem32 resources on socket 0 bus 0
+ if (socket == 0 && stack == 0) {
+ acpigen_resource_dword(0, 0xc, 3, 0, VGA_BASE_ADDRESS,
+ (VGA_BASE_ADDRESS + VGA_BASE_SIZE - 1), 0x0,
+ VGA_BASE_SIZE);
+ acpigen_resource_dword(0, 0xc, 1, 0, SPI_BASE_ADDRESS,
+ (SPI_BASE_ADDRESS + SPI_BASE_SIZE - 1), 0x0,
+ SPI_BASE_SIZE);
+ }
+
+ /* Mem32 resource */
+ acpigen_resource_dword(0, 0xc, 1, 0, ri->PciResourceMem32Base,
+ ri->PciResourceMem32Limit, 0x0,
+ (ri->PciResourceMem32Limit - ri->PciResourceMem32Base + 1));
+
+ /* Mem64 resource */
+ acpigen_resource_qword(0, 0xc, 1, 0, ri->PciResourceMem64Base,
+ ri->PciResourceMem64Limit, 0x0,
+ (ri->PciResourceMem64Limit - ri->PciResourceMem64Base + 1));
+
+ acpigen_write_resourcetemplate_footer();
+ }
+ }
+ acpigen_pop_len();
+}
+
+void southbridge_inject_dsdt(struct device *device)
+{
+ global_nvs_t *gnvs;
+
+ gnvs = cbmem_find(CBMEM_ID_ACPI_GNVS);
+ if (!gnvs) {
+ gnvs = cbmem_add(CBMEM_ID_ACPI_GNVS, sizeof(*gnvs));
+ if (gnvs)
+ memset(gnvs, 0, sizeof(*gnvs));
+ }
+
+ if (gnvs) {
+ acpi_create_gnvs(gnvs);
+ /* TODO: tell SMI about it, if HAVE_SMI_HANDLER */
+ // smm_setup_structures(gnvs, NULL, NULL);
+
+ /* Add it to DSDT. */
+ printk(BIOS_SPEW, "%s injecting NVSA with 0x%x\n", __FILE__, (uint32_t)gnvs);
+ acpigen_write_scope("\\");
+ acpigen_write_name_dword("NVSA", (uint32_t)gnvs);
+ acpigen_pop_len();
+ }
+
+ // Add IIOStack ACPI Resource Templates
+ uncore_inject_dsdt();
+}
diff --git a/src/soc/intel/xeon_sp/acpi/globalnvs.asl b/src/soc/intel/xeon_sp/acpi/globalnvs.asl
new file mode 100644
index 0000000..c2d5853
--- /dev/null
+++ b/src/soc/intel/xeon_sp/acpi/globalnvs.asl
@@ -0,0 +1,82 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 Google Inc.
+ * Copyright (C) 2014 - 2020 Intel Corporation
+ * Copyright (C) 2019 - 2020 Facebook Inc
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+
+/* Global Variables */
+
+Name(\PICM, 0) // IOAPIC/8259
+
+/*
+ * Global ACPI memory region. This region is used for passing information
+ * between coreboot (aka "the system bios"), ACPI, and the SMI handler.
+ * Since we don't know where this will end up in memory at ACPI compile time,
+ * we have to fix it up in coreboot's ACPI creation phase.
+ */
+
+
+External(NVSA)
+OperationRegion (GNVS, SystemMemory, NVSA, 0x2000)
+Field (GNVS, ByteAcc, NoLock, Preserve)
+{
+ /* Miscellaneous */
+ OSYS, 16, // 0x00 - Operating System
+ SMIF, 8, // 0x02 - SMI function
+ PRM0, 8, // 0x03 - SMI function parameter
+ PRM1, 8, // 0x04 - SMI function parameter
+ SCIF, 8, // 0x05 - SCI function
+ PRM2, 8, // 0x06 - SCI function parameter
+ PRM3, 8, // 0x07 - SCI function parameter
+ LCKF, 8, // 0x08 - Global Lock function for EC
+ PRM4, 8, // 0x09 - Lock function parameter
+ PRM5, 8, // 0x0a - Lock function parameter
+ P80D, 32, // 0x0b - Debug port (IO 0x80) value
+ LIDS, 8, // 0x0f - LID state (open = 1)
+ PWRS, 8, // 0x10 - Power State (AC = 1)
+ PCNT, 8, // 0x11 - Processor count
+ TPMP, 8, // 0x12 - TPM Present and Enabled
+ TLVL, 8, // 0x13 - Throttle Level
+ PPCM, 8, // 0x14 - Maximum P-state usable by OS
+ PM1I, 64, // 0x15 - PM1 wake status bit
+ GPEI, 64, // 0x1D - GPE wake status bit
+ U2WE, 16, // 0x25 - USB2 Wake Enable Bitmap
+ U3WE, 8, // 0x27 - USB3 Wake Enable Bitmap
+
+
+ /* Device Config */
+ Offset (0x30),
+ S5U0, 8, // 0x30 - Enable USB0 in S5
+ S5U1, 8, // 0x31 - Enable USB1 in S5
+ S3U0, 8, // 0x32 - Enable USB0 in S3
+ S3U1, 8, // 0x33 - Enable USB1 in S3
+ TACT, 8, // 0x34 - Thermal Active trip point
+ TPSV, 8, // 0x35 - Thermal Passive trip point
+ TCRT, 8, // 0x36 - Thermal Critical trip point
+ DPTE, 8, // 0x37 - Enable DPTF
+
+ /* Base addresses */
+ Offset (0x50),
+ CMEM, 32, // 0x50 - CBMEM TOC
+ TOLM, 32, // 0x54 - Top of Low Memory
+ CBMC, 32, // 0x58 - coreboot mem console pointer
+ MMOB, 32, // 0x5C - MMIO Base Low Base
+ MMOL, 32, // 0x60 - MMIO Base Low Limit
+ MMHB, 64, // 0x64 - MMIO Base High Base
+ MMHL, 64, // 0x6C - MMIO Base High Limit
+ TSGB, 32, // 0x74 - TSEG Base
+ TSSZ, 32, // 0x78 - TSEG Size
+}
diff --git a/src/soc/intel/xeon_sp/acpi/iiostack.asl b/src/soc/intel/xeon_sp/acpi/iiostack.asl
new file mode 100644
index 0000000..2d1187f
--- /dev/null
+++ b/src/soc/intel/xeon_sp/acpi/iiostack.asl
@@ -0,0 +1,92 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2019 - 2020 Intel Corporation
+ * Copyright (C) 2019 - 2020 Facebook Inc
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#define MAKE_IIO_DEV(id,rt) \
+ Device (PC##id) \
+ { \
+ Name (_HID, EisaId ("PNP0A08") /* PCI Express Bus */) \
+ Name (_CID, EisaId ("PNP0A03") /* PCI Bus */) \
+ Name (_UID, 0x##id) \
+ Method (_PRT, 0, NotSerialized) \
+ { \
+ If (PICM) \
+ { \
+ Return (\_SB_.AR##rt) \
+ } \
+ Return (\_SB_.PR##rt) \
+ } \
+ External(\_SB.RT##id) \
+ Method (_CRS, 0, NotSerialized) \
+ { \
+ Return (\_SB.RT##id) \
+ } \
+ Name (SUPP, 0x00) \
+ Name (CTRL, 0x00) \
+ Name (_PXM, 0x00) /* _PXM: Device Proximity */ \
+ Method (_OSC, 4, NotSerialized) \
+ { \
+ CreateDWordField (Arg3, 0x00, CDW1) \
+ If ((Arg0 == ToUUID ("33db4d5b-1ff7-401c-9657-7441c03dd766") /* PCI Host Bridge Device */)) \
+ { \
+ CreateDWordField (Arg3, 0x04, CDW2) \
+ If ((Arg2 > 0x02)) \
+ { \
+ CreateDWordField (Arg3, 0x08, CDW3) \
+ } \
+ SUPP = CDW2 \
+ CTRL = CDW3 \
+ If ((AHPE || ((SUPP & 0x16) != 0x16))) \
+ { \
+ CTRL &= 0x1E \
+ Sleep (0x03E8) \
+ } \
+ /* Never allow SHPC (no SHPC controller in system) */ \
+ CTRL &= 0x1D \
+ /* Disable Native PCIe AER handling from OS */ \
+ CTRL &= 0x17 \
+ If ((Arg1 != One)) /* unknown revision */ \
+ { \
+ CDW1 |= 0x08 \
+ } \
+ If ((CDW3 != CTRL)) /* capabilities bits were masked */ \
+ { \
+ CDW1 |= 0x10 \
+ } \
+ CDW3 = CTRL \
+ Return (Arg3) \
+ } \
+ Else \
+ { \
+ /* indicate unrecognized UUID */ \
+ CDW1 |= 0x04 \
+ IO80 = 0xEE \
+ Return (Arg3) \
+ } \
+ } \
+ }
+
+MAKE_IIO_DEV(00, 00)
+MAKE_IIO_DEV(01, 10)
+MAKE_IIO_DEV(02, 20)
+MAKE_IIO_DEV(03, 28)
+
+#if MAX_SOCKET > 1
+MAKE_IIO_DEV(06, 40)
+MAKE_IIO_DEV(07, 50)
+MAKE_IIO_DEV(08, 60)
+MAKE_IIO_DEV(09, 68)
+#endif
diff --git a/src/soc/intel/xeon_sp/acpi/pci_irq.asl b/src/soc/intel/xeon_sp/acpi/pci_irq.asl
new file mode 100644
index 0000000..cfa4ad5
--- /dev/null
+++ b/src/soc/intel/xeon_sp/acpi/pci_irq.asl
@@ -0,0 +1,113 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 coresystems GmbH
+ * Copyright (C) 2014 Google Inc.
+ * Copyright (C) 2020 Intel Corporation
+ * Copyright (C) 2019 - 2020 Facebook Inc.
+ *
+ * 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
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/*
+ * Refer to Intel® C620 Series Chipset Platform Controller Hub EDS section 20.11
+ * CONFIG_PCR_BASE_ADDRESS 0xfd000000 0x3100
+ * (0xfd000000 | ((uint8_t)(0xC4) << 16) | (uint16_t)(0x3100) = 0xFDC43100
+ *
+ * PIRQ routing control is in PCR ITSS region.
+ */
+
+OperationRegion (ITSS, SystemMemory,
+ Add (PCR_ITSS_PIRQA_ROUT,
+ Add (CONFIG_PCR_BASE_ADDRESS,
+ ShiftLeft (PID_ITSS, PCR_PORTID_SHIFT))), 8)
+Field (ITSS, ByteAcc, NoLock, Preserve)
+{
+ PIRA, 8, /* PIRQA Routing Control */
+ PIRB, 8, /* PIRQB Routing Control */
+ PIRC, 8, /* PIRQC Routing Control */
+ PIRD, 8, /* PIRQD Routing Control */
+ PIRE, 8, /* PIRQE Routing Control */
+ PIRF, 8, /* PIRQF Routing Control */
+ PIRG, 8, /* PIRQG Routing Control */
+ PIRH, 8, /* PIRQH Routing Control */
+}
+
+Name (IREN, 0x80) /* Interrupt Routing Enable */
+Name (IREM, 0x0f) /* Interrupt Routing Mask */
+
+Name (PRSA, ResourceTemplate ()
+{
+ IRQ (Level, ActiveLow, Shared, )
+ {3,4,5,6,7,10,11,12,14,15}
+})
+Alias (PRSA, PRSB)
+Name (PRSC, ResourceTemplate ()
+{
+ IRQ (Level, ActiveLow, Shared, )
+ {3,4,5,6,10,11,12,14,15}
+})
+Alias (PRSC, PRSD)
+Alias (PRSA, PRSE)
+Alias (PRSA, PRSF)
+Alias (PRSA, PRSG)
+Alias (PRSA, PRSH)
+
+#define MAKE_LINK_DEV(id,uid) \
+ Device (LNK##id) \
+ { \
+ Name (_HID, EISAID ("PNP0C0F")) \
+ Name (_UID, ##uid) \
+ Method (_PRS, 0, NotSerialized) \
+ { \
+ Return (PRS##id) \
+ } \
+ Method (_CRS, 0, Serialized) \
+ { \
+ Name (RTLA, ResourceTemplate () \
+ { \
+ IRQ (Level, ActiveLow, Shared) {} \
+ }) \
+ CreateWordField (RTLA, 1, IRQ0) \
+ Store (Zero, IRQ0) \
+ \
+ /* Set the bit from PIRQ Routing Register */ \
+ ShiftLeft (1, And (^^PIR##id, ^^IREM), IRQ0) \
+ Return (RTLA) \
+ } \
+ Method (_SRS, 1, Serialized) \
+ { \
+ CreateWordField (Arg0, 1, IRQ0) \
+ FindSetRightBit (IRQ0, Local0) \
+ Decrement (Local0) \
+ Store (Local0, ^^PIR##id) \
+ } \
+ Method (_STA, 0, Serialized) \
+ { \
+ If (And (^^PIR##id, ^^IREN)) { \
+ Return (0x9) \
+ } Else { \
+ Return (0xb) \
+ } \
+ } \
+ Method (_DIS, 0, Serialized) \
+ { \
+ Or (^^PIR##id, ^^IREN, ^^PIR##id) \
+ } \
+ }
+
+MAKE_LINK_DEV(A,1)
+MAKE_LINK_DEV(B,2)
+MAKE_LINK_DEV(C,3)
+MAKE_LINK_DEV(D,4)
+MAKE_LINK_DEV(E,5)
+MAKE_LINK_DEV(F,6)
+MAKE_LINK_DEV(G,7)
+MAKE_LINK_DEV(H,8)
diff --git a/src/soc/intel/xeon_sp/acpi/uncore.asl b/src/soc/intel/xeon_sp/acpi/uncore.asl
new file mode 100644
index 0000000..35fbf98
--- /dev/null
+++ b/src/soc/intel/xeon_sp/acpi/uncore.asl
@@ -0,0 +1,48 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2019 - 2020 Intel Corporation
+ * Copyright (C) 2019 - 2020 Facebook Inc.
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+
+#include <intelblocks/itss.h>
+#include <intelblocks/pcr.h>
+#include <soc/iomap.h>
+#include <soc/irq.h>
+#include <soc/pcr_ids.h>
+
+Scope(\)
+{
+ // Private Chipset Register(PCR). Memory Mapped through ILB
+ OperationRegion(PCRR, SystemMemory, P2SB_BAR, 0x01000000)
+ Field(PCRR, DWordAcc, Lock, Preserve)
+ {
+ Offset (0xD03100), // Interrupt Routing Registers
+ PRTA, 8,
+ PRTB, 8,
+ PRTC, 8,
+ PRTD, 8,
+ PRTE, 8,
+ PRTF, 8,
+ PRTG, 8,
+ PRTH, 8,
+ }
+}
+
+Scope (_SB)
+{
+ #include "pci_irq.asl"
+ #include "uncore_irq.asl"
+ #include "iiostack.asl"
+}
diff --git a/src/soc/intel/xeon_sp/acpi/uncore_irq.asl b/src/soc/intel/xeon_sp/acpi/uncore_irq.asl
new file mode 100644
index 0000000..8492725
--- /dev/null
+++ b/src/soc/intel/xeon_sp/acpi/uncore_irq.asl
@@ -0,0 +1,566 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2019 - 2020 Intel Corporation
+ * Copyright (C) 2019 - 2020 Facebook Inc.
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/*
+ * Uncore devices PCI interrupt routing packages.
+ * See ACPI spec 6.2.13 _PRT (PCI routing table) for details.
+ * The mapping fields ae Address, Pin, Source, Source Index.
+ */
+
+#define GEN_PCIE_LEGACY_IRQ() \
+ Package (0x04) { 0x0000FFFF, 0x00, LNKA, 0x00 }, \
+ Package (0x04) { 0x0001FFFF, 0x00, LNKA, 0x00 }, \
+ Package (0x04) { 0x0002FFFF, 0x00, LNKA, 0x00 }, \
+ Package (0x04) { 0x0003FFFF, 0x00, LNKA, 0x00 }
+
+#define GEN_UNCORE_LEGACY_IRQ(dev) \
+ Package (0x04) { ##dev, 0x00, LNKA, 0x00 }, \
+ Package (0x04) { ##dev, 0x01, LNKB, 0x00 }, \
+ Package (0x04) { ##dev, 0x02, LNKC, 0x00 }, \
+ Package (0x04) { ##dev, 0x03, LNKD, 0x00 }
+
+#define GEN_PCIE_IOAPIC_IRQ(irq) \
+ Package (0x04) { 0x0000FFFF, 0x00, 0x00, ##irq }, \
+ Package (0x04) { 0x0001FFFF, 0x00, 0x00, ##irq }, \
+ Package (0x04) { 0x0002FFFF, 0x00, 0x00, ##irq }, \
+ Package (0x04) { 0x0003FFFF, 0x00, 0x00, ##irq }
+
+#define GEN_UNCORE_IOAPIC_IRQ(dev,irq1,irq2,irq3,irq4) \
+ Package (0x04) { ##dev, 0x00, 0x00, ##irq1 }, \
+ Package (0x04) { ##dev, 0x01, 0x00, ##irq2 }, \
+ Package (0x04) { ##dev, 0x02, 0x00, ##irq3 }, \
+ Package (0x04) { ##dev, 0x03, 0x00, ##irq4 }
+
+// Socket 0, IIOStack 0 device legacy interrupt routing
+Name (PR00, Package (0x28)
+{
+ // [DMI0]: Legacy PCI Express Port 0
+ Package (0x04) { 0x0000FFFF, 0x00, LNKA, 0x00 },
+ // [CB0A]: CBDMA
+ // [CB0E]: CBDMA
+ Package (0x04) { 0x0004FFFF, 0x00, LNKA, 0x00 },
+ // [CB0B]: CBDMA
+ // [CB0F]: CBDMA
+ Package (0x04) { 0x0004FFFF, 0x01, LNKB, 0x00 },
+ // [CB0C]: CBDMA
+ // [CB0G]: CBDMA
+ Package (0x04) { 0x0004FFFF, 0x02, LNKC, 0x00 },
+ // [CB0D]: CBDMA
+ // [CB0H]: CBDMA
+ Package (0x04) { 0x0004FFFF, 0x03, LNKD, 0x00 },
+ // Uncore 0 UBOX Device
+ Package (0x04) { 0x0008FFFF, 0x00, LNKA, 0x00 },
+ Package (0x04) { 0x0008FFFF, 0x01, LNKB, 0x00 },
+ Package (0x04) { 0x0008FFFF, 0x02, LNKC, 0x00 },
+ Package (0x04) { 0x0008FFFF, 0x03, LNKD, 0x00 },
+ // [DISP]: Display Controller
+ Package (0x04) { 0x000FFFFF, 0x00, LNKA, 0x00 },
+ // [IHC1]: HECI #1
+ // [IHC3]: HECI #3
+ Package (0x04) { 0x0010FFFF, 0x00, LNKA, 0x00 },
+ // [IHC2]: HECI #2
+ Package (0x04) { 0x0010FFFF, 0x01, LNKB, 0x00 },
+ // [IIDR]: IDE-Redirection (IDE-R)
+ Package (0x04) { 0x0010FFFF, 0x02, LNKC, 0x00 },
+ // [IMKT]: Keyboard and Text (KT) Redirection
+ Package (0x04) { 0x0010FFFF, 0x03, LNKD, 0x00 },
+ // [SAT2]: sSATA Host controller 2 on PCH
+ Package (0x04) { 0x0011FFFF, 0x00, LNKA, 0x00 },
+ // // [XHCI]: xHCI controller 1 on PCH
+ Package (0x04) { 0x0014FFFF, 0x00, LNKA, 0x00 },
+ // [OTG0]: USB Device Controller (OTG) on PCH
+ Package (0x04) { 0x0014FFFF, 0x01, LNKB, 0x00 },
+ // [TERM]: Thermal Subsystem on PCH
+ Package (0x04) { 0x0014FFFF, 0x02, LNKC, 0x00 },
+ // [CAMR]: Camera IO Host Controller on PCH
+ Package (0x04) { 0x0014FFFF, 0x03, LNKD, 0x00 },
+ // [HEC1]: HECI #1 on PCH
+ // [HEC3]: HECI #3 on PCH
+ Package (0x04) { 0x0016FFFF, 0x00, LNKA, 0x00 },
+ // [HEC2]: HECI #2 on PCH
+ Package (0x04) { 0x0016FFFF, 0x01, LNKB, 0x00 },
+ // [IDER]: ME IDE redirect on PCH
+ Package (0x04) { 0x0016FFFF, 0x02, LNKC, 0x00 },
+ // [MEKT]: MEKT on PCH
+ Package (0x04) { 0x0016FFFF, 0x03, LNKD, 0x00 },
+ // [SAT1]: SATA controller 1 on PCH
+ Package (0x04) { 0x0017FFFF, 0x00, LNKA, 0x00 },
+ // [NAN1]: NAND Cycle Router on PCH
+ Package (0x04) { 0x0018FFFF, 0x00, LNKA, 0x00 },
+ // [RP17]: PCIE PCH Root Port #17
+ Package (0x04) { 0x001BFFFF, 0x00, LNKA, 0x00 },
+ // [RP18]: PCIE PCH Root Port #18
+ Package (0x04) { 0x001BFFFF, 0x01, LNKB, 0x00 },
+ // [RP19]: PCIE PCH Root Port #19
+ Package (0x04) { 0x001BFFFF, 0x02, LNKC, 0x00 },
+ // [RP20]: PCIE PCH Root Port #20
+ Package (0x04) { 0x001BFFFF, 0x03, LNKD, 0x00 },
+ // [RP01]: PCIE PCH Root Port #1
+ // [RP05]: PCIE PCH Root Port #5
+ Package (0x04) { 0x001CFFFF, 0x00, LNKA, 0x00 },
+ // [RP02]: PCIE PCH Root Port #2
+ // [RP06]: PCIE PCH Root Port #6
+ Package (0x04) { 0x001CFFFF, 0x01, LNKB, 0x00 },
+ // [RP03]: PCIE PCH Root Port #3
+ // [RP07]: PCIE PCH Root Port #7
+ Package (0x04) { 0x001CFFFF, 0x02, LNKC, 0x00 },
+ // [RP04]: PCIE PCH Root Port #4
+ // [RP08]: PCIE PCH Root Port #8
+ Package (0x04) { 0x001CFFFF, 0x03, LNKD, 0x00 },
+ // [RP09]: PCIE PCH Root Port #9
+ // [RP13]: PCIE PCH Root Port #13
+ Package (0x04) { 0x001DFFFF, 0x00, LNKA, 0x00 },
+ // [RP10]: PCIE PCH Root Port #10
+ // [RP14]: PCIE PCH Root Port #14
+ Package (0x04) { 0x001DFFFF, 0x01, LNKB, 0x00 },
+ // [RP11]: PCIE PCH Root Port #11
+ // [RP15]: PCIE PCH Root Port #15
+ Package (0x04) { 0x001DFFFF, 0x02, LNKC, 0x00 },
+ // [RP12]: PCIE PCH Root Port #12
+ // [RP16]: PCIE PCH Root Port #16
+ Package (0x04) { 0x001DFFFF, 0x03, LNKD, 0x00 },
+ // [UAR0]: UART #0 on PCH
+ Package (0x04) { 0x001EFFFF, 0x02, LNKC, 0x00 },
+ // [UAR1]: UART #1 on PCH
+ Package (0x04) { 0x001EFFFF, 0x03, LNKD, 0x00 },
+ // [CAVS]: HD Audio Subsystem Controller on PCH
+ // [SMBS]: SMBus controller on PCH
+ // [GBE1]: GbE Controller on PCH
+ // [NTPK]: Northpeak Controller on PCH
+ Package (0x04) { 0x001FFFFF, 0x00, LNKA, 0x00 },
+})
+
+// Socket 0, IIOStack 0 device IOAPIC interrupt routing
+Name (AR00, Package (0x28)
+{
+ // [DMI0]: Legacy PCI Express Port 0
+ Package (0x04) { 0x0000FFFF, 0x00, 0x00, 0x1F },
+ // [CB0A]: CB3DMA
+ // [CB0E]: CB3DMA
+ Package (0x04) { 0x0004FFFF, 0x00, 0x00, 0x1A },
+ // [CB0B]: CB3DMA
+ // [CB0F]: CB3DMA
+ Package (0x04) { 0x0004FFFF, 0x01, 0x00, 0x1B },
+ // [CB0C]: CB3DMA
+ // [CB0G]: CB3DMA
+ Package (0x04) { 0x0004FFFF, 0x02, 0x00, 0x1A },
+ // [CB0D]: CB3DMA
+ // [CB0H]: CB3DMA
+ Package (0x04) { 0x0004FFFF, 0x03, 0x00, 0x1B },
+ // [UBX0]: Uncore 0 UBOX Device
+ Package (0x04) { 0x0008FFFF, 0x00, 0x00, 0x18 },
+ Package (0x04) { 0x0008FFFF, 0x01, 0x00, 0x1C },
+ Package (0x04) { 0x0008FFFF, 0x02, 0x00, 0x1D },
+ Package (0x04) { 0x0008FFFF, 0x03, 0x00, 0x1E },
+ // [DISP]: Display Controller
+ Package (0x04) { 0x000FFFFF, 0x00, 0x00, 0x10 },
+ // [IHC1]: HECI #1
+ // [IHC3]: HECI #3
+ Package (0x04) { 0x0010FFFF, 0x00, 0x00, 0x10 },
+ // [IHC2]: HECI #2
+ Package (0x04) { 0x0010FFFF, 0x01, 0x00, 0x11 },
+ // [IIDR]: IDE-Redirection (IDE-R)
+ Package (0x04) { 0x0010FFFF, 0x02, 0x00, 0x12 },
+ // [IMKT]: Keyboard and Text (KT) Redirection
+ Package (0x04) { 0x0010FFFF, 0x03, 0x00, 0x13 },
+ // [SAT2]: sSATA Host controller 2 on PCH
+ Package (0x04) { 0x0011FFFF, 0x00, 0x00, 0x10 },
+ // [XHCI]: xHCI controller 1 on PCH
+ Package (0x04) { 0x0014FFFF, 0x00, 0x00, 0x10 },
+ // [OTG0]: USB Device Controller (OTG) on PCH
+ Package (0x04) { 0x0014FFFF, 0x01, 0x00, 0x11 },
+ // [TERM]: Thermal Subsystem on PCH
+ Package (0x04) { 0x0014FFFF, 0x02, 0x00, 0x12 },
+ // [CAMR]: Camera IO Host Controller on PCH
+ Package (0x04) { 0x0014FFFF, 0x03, 0x00, 0x13 },
+ // [HEC1]: HECI #1 on PCH
+ // [HEC3]: HECI #3 on PCH
+ Package (0x04) { 0x0016FFFF, 0x00, 0x00, 0x10 },
+ // [HEC2]: HECI #2 on PCH
+ Package (0x04) { 0x0016FFFF, 0x01, 0x00, 0x11 },
+ // [IDER]: ME IDE redirect on PCH
+ Package (0x04) { 0x0016FFFF, 0x02, 0x00, 0x12 },
+ // [MEKT]: MEKT on PCH
+ Package (0x04) { 0x0016FFFF, 0x03, 0x00, 0x13 },
+ // [SAT1]: SATA controller 1 on PCH
+ Package (0x04) { 0x0017FFFF, 0x00, 0x00, 0x10 },
+ // [NAN1]: NAND Cycle Router on PCH
+ Package (0x04) { 0x0018FFFF, 0x00, 0x00, 0x10 },
+ // [RP17]: PCIE PCH Root Port #17
+ Package (0x04) { 0x001BFFFF, 0x00, 0x00, 0x10 },
+ // [RP18]: PCIE PCH Root Port #18
+ Package (0x04) { 0x001BFFFF, 0x01, 0x00, 0x11 },
+ // [RP19]: PCIE PCH Root Port #19
+ Package (0x04) { 0x001BFFFF, 0x02, 0x00, 0x12 },
+ // [RP20]: PCIE PCH Root Port #20
+ Package (0x04) { 0x001BFFFF, 0x03, 0x00, 0x13 },
+ // [RP01]: PCIE PCH Root Port #1
+ // [RP05]: PCIE PCH Root Port #5
+ Package (0x04) { 0x001CFFFF, 0x00, 0x00, 0x10 },
+ // [RP02]: PCIE PCH Root Port #2
+ // [RP06]: PCIE PCH Root Port #6
+ Package (0x04) { 0x001CFFFF, 0x01, 0x00, 0x11 },
+ // [RP03]: PCIE PCH Root Port #3
+ // [RP07]: PCIE PCH Root Port #7
+ Package (0x04) { 0x001CFFFF, 0x02, 0x00, 0x12 },
+ // [RP04]: PCIE PCH Root Port #4
+ // [RP08]: PCIE PCH Root Port #8
+ Package (0x04) { 0x001CFFFF, 0x03, 0x00, 0x13 },
+ // [RP09]: PCIE PCH Root Port #9
+ // [RP13]: PCIE PCH Root Port #13
+ Package (0x04) { 0x001DFFFF, 0x00, 0x00, 0x10 },
+ // [RP10]: PCIE PCH Root Port #10
+ // [RP14]: PCIE PCH Root Port #14
+ Package (0x04) { 0x001DFFFF, 0x01, 0x00, 0x11 },
+ // [RP11]: PCIE PCH Root Port #11
+ // [RP15]: PCIE PCH Root Port #15
+ Package (0x04) { 0x001DFFFF, 0x02, 0x00, 0x12 },
+ // [RP12]: PCIE PCH Root Port #12
+ // [RP16]: PCIE PCH Root Port #16
+ Package (0x04) { 0x001DFFFF, 0x03, 0x00, 0x13 },
+ // [UAR0]: UART #0 on PCH
+ Package (0x04) { 0x001EFFFF, 0x02, 0x00, 0x16 },
+ // [UAR1]: UART #1 on PCH
+ Package (0x04) { 0x001EFFFF, 0x03, 0x00, 0x17 },
+ // [CAVS]: HD Audio Subsystem Controller on PCH
+ // [SMBS]: SMBus controller on PCH
+ // [GBE1]: GbE Controller on PCH
+ // [NTPK]: Northpeak Controller on PCH
+ Package (0x04) { 0x001FFFFF, 0x00, 0x00, 0x10 },
+})
+
+// Socket 0, IIOStack 1 device legacy interrupt routing
+Name (PR10, Package (0x40)
+{
+ // PCI Express Port 1A-1D
+ GEN_PCIE_LEGACY_IRQ(),
+
+ // Uncore CHAUTIL Devices
+ GEN_UNCORE_LEGACY_IRQ(0x0008FFFF),
+ GEN_UNCORE_LEGACY_IRQ(0x0009FFFF),
+ GEN_UNCORE_LEGACY_IRQ(0x000AFFFF),
+ GEN_UNCORE_LEGACY_IRQ(0x000BFFFF),
+
+ // Uncore CHASAD Devices
+ GEN_UNCORE_LEGACY_IRQ(0x000EFFFF),
+ GEN_UNCORE_LEGACY_IRQ(0x000FFFFF),
+ GEN_UNCORE_LEGACY_IRQ(0x0010FFFF),
+ GEN_UNCORE_LEGACY_IRQ(0x0011FFFF),
+
+ // Uncore CMSCHA Devices
+ GEN_UNCORE_LEGACY_IRQ(0x0014FFFF),
+ GEN_UNCORE_LEGACY_IRQ(0x0015FFFF),
+ GEN_UNCORE_LEGACY_IRQ(0x0016FFFF),
+ GEN_UNCORE_LEGACY_IRQ(0x0017FFFF),
+
+ // Uncore CHASADALL Device
+ GEN_UNCORE_LEGACY_IRQ(0x001DFFFF),
+
+ // Uncore PCUCR Device
+ GEN_UNCORE_LEGACY_IRQ(0x001EFFFF),
+
+ // Uncore VCUCR Device
+ GEN_UNCORE_LEGACY_IRQ(0x001FFFFF)
+})
+
+// Socket 0, IIOStack 1 device IOAPIC interrupt routing
+Name (AR10, Package (0x40)
+{
+ // PCI Express Port 1A-1D
+ GEN_PCIE_IOAPIC_IRQ(0x27),
+
+ // Uncore CHAUTIL Devices
+ GEN_UNCORE_IOAPIC_IRQ(0x0008FFFF, 0x20, 0x24, 0x25, 0x26),
+ GEN_UNCORE_IOAPIC_IRQ(0x0009FFFF, 0x20, 0x24, 0x25, 0x26),
+ GEN_UNCORE_IOAPIC_IRQ(0x000AFFFF, 0x20, 0x24, 0x25, 0x26),
+ GEN_UNCORE_IOAPIC_IRQ(0x000BFFFF, 0x20, 0x24, 0x25, 0x26),
+
+ // Uncore CHASAD Devices
+ GEN_UNCORE_IOAPIC_IRQ(0x000EFFFF, 0x20, 0x24, 0x25, 0x26),
+ GEN_UNCORE_IOAPIC_IRQ(0x000FFFFF, 0x20, 0x24, 0x25, 0x26),
+ GEN_UNCORE_IOAPIC_IRQ(0x0010FFFF, 0x20, 0x24, 0x25, 0x26),
+ GEN_UNCORE_IOAPIC_IRQ(0x0011FFFF, 0x20, 0x24, 0x25, 0x26),
+
+ // Uncore CMSCHA Devices
+ GEN_UNCORE_IOAPIC_IRQ(0x0014FFFF, 0x20, 0x24, 0x25, 0x26),
+ GEN_UNCORE_IOAPIC_IRQ(0x0015FFFF, 0x20, 0x24, 0x25, 0x26),
+ GEN_UNCORE_IOAPIC_IRQ(0x0016FFFF, 0x20, 0x24, 0x25, 0x26),
+ GEN_UNCORE_IOAPIC_IRQ(0x0017FFFF, 0x20, 0x24, 0x25, 0x26),
+
+ // Uncore CHASADALL Device
+ GEN_UNCORE_IOAPIC_IRQ(0x001DFFFF, 0x20, 0x24, 0x25, 0x26),
+
+ // Uncore PCUCR Device
+ GEN_UNCORE_IOAPIC_IRQ(0x001EFFFF, 0x20, 0x24, 0x25, 0x26),
+
+ // Uncore VCUCR Device
+ GEN_UNCORE_IOAPIC_IRQ(0x001FFFFF, 0x20, 0x24, 0x25, 0x26)
+})
+
+// Socket 0, IIOStack 2 device legacy interrupt routing
+Name (PR20, Package (0x24)
+{
+ // PCI Express Port 2 on PC02
+ GEN_PCIE_LEGACY_IRQ(),
+
+ // Uncore M2MEM Devices
+ GEN_UNCORE_LEGACY_IRQ(0x0008FFFF),
+ GEN_UNCORE_LEGACY_IRQ(0x0009FFFF),
+
+ // Uncore MCMAIN Device
+ GEN_UNCORE_LEGACY_IRQ(0x000AFFFF),
+
+ // Uncore MCDECS2 Device
+ GEN_UNCORE_LEGACY_IRQ(0x000BFFFF),
+
+ // Uncore MCMAIN Device
+ GEN_UNCORE_LEGACY_IRQ(0x000CFFFF),
+
+ // Uncore MCDECS Device
+ GEN_UNCORE_LEGACY_IRQ(0x000DFFFF),
+
+ // Uncore Unicast MC0 DDRIO0 Device
+ GEN_UNCORE_LEGACY_IRQ(0x0016FFFF),
+
+ // Uncore Unicast MC1 DDRIO0 Device
+ GEN_UNCORE_LEGACY_IRQ(0x0017FFFF)
+})
+
+// Socket 0, IIOStack 2 device IOAPIC interrupt routing
+Name (AR20, Package (0x24)
+{
+ // PCI Express Port 2 on PC02
+ GEN_PCIE_IOAPIC_IRQ(0x2F),
+
+ // Uncore M2MEM Devices
+ GEN_UNCORE_IOAPIC_IRQ(0x0008FFFF, 0x28, 0x2C, 0x2D, 0x2E),
+ GEN_UNCORE_IOAPIC_IRQ(0x0009FFFF, 0x28, 0x2C, 0x2D, 0x2E),
+
+ // Uncore MCMAIN Device
+ GEN_UNCORE_IOAPIC_IRQ(0x000AFFFF, 0x28, 0x2C, 0x2D, 0x2E),
+
+ // Uncore MCDECS2 Device
+ GEN_UNCORE_IOAPIC_IRQ(0x000BFFFF, 0x28, 0x2C, 0x2D, 0x2E),
+
+ // Uncore MCMAIN Device
+ GEN_UNCORE_IOAPIC_IRQ(0x000CFFFF, 0x28, 0x2C, 0x2D, 0x2E),
+
+ // Uncore MCDECS Device
+ GEN_UNCORE_IOAPIC_IRQ(0x000DFFFF, 0x28, 0x2C, 0x2D, 0x2E),
+
+ // Uncore Unicast MC0 DDRIO0 Device
+ GEN_UNCORE_IOAPIC_IRQ(0x0016FFFF, 0x28, 0x2C, 0x2D, 0x2E),
+
+ // Uncore Unicast MC1 DDRIO0 Device
+ GEN_UNCORE_IOAPIC_IRQ(0x0017FFFF, 0x28, 0x2C, 0x2D, 0x2E)
+})
+
+// Socket 0, IIOStack 3 device legacy interrupt routing
+Name (PR28, Package (0x20)
+{
+ // PCI Express Port 3 on PC03
+ GEN_PCIE_LEGACY_IRQ(),
+
+ // KTI Devices
+ GEN_UNCORE_LEGACY_IRQ(0x000EFFFF),
+ GEN_UNCORE_LEGACY_IRQ(0x000FFFFF),
+ GEN_UNCORE_LEGACY_IRQ(0x0010FFFF),
+
+ // M3K Device
+ GEN_UNCORE_LEGACY_IRQ(0x0012FFFF),
+
+ // M2U Device
+ GEN_UNCORE_LEGACY_IRQ(0x0015FFFF),
+
+ // M2D Device
+ GEN_UNCORE_LEGACY_IRQ(0x0016FFFF),
+
+ // M20 Device
+ GEN_UNCORE_LEGACY_IRQ(0x0017FFFF)
+})
+
+// Socket 0, IIOStack 3 device IOAPIC interrupt routing
+Name (AR28, Package (0x20)
+{
+ // PCI Express Port 3 on PC03
+ GEN_PCIE_IOAPIC_IRQ(0x37),
+
+ // KTI Devices
+ GEN_UNCORE_IOAPIC_IRQ(0x000EFFFF, 0x30, 0x34, 0x35, 0x36),
+ GEN_UNCORE_IOAPIC_IRQ(0x000FFFFF, 0x30, 0x34, 0x35, 0x36),
+ GEN_UNCORE_IOAPIC_IRQ(0x0010FFFF, 0x30, 0x34, 0x35, 0x36),
+
+ // M3K Device
+ GEN_UNCORE_IOAPIC_IRQ(0x0012FFFF, 0x30, 0x34, 0x35, 0x36),
+
+ // M2U Device
+ GEN_UNCORE_IOAPIC_IRQ(0x0015FFFF, 0x30, 0x34, 0x35, 0x36),
+
+ // M2D Device
+ GEN_UNCORE_IOAPIC_IRQ(0x0016FFFF, 0x30, 0x34, 0x35, 0x36),
+
+ // M20 Device
+ GEN_UNCORE_IOAPIC_IRQ(0x0017FFFF, 0x30, 0x34, 0x35, 0x36)
+})
+
+// Socket 1, IIOStack 0 device legacy interrupt routing
+Name (PR40, Package (0x09)
+{
+ // DMI
+ Package (0x04) { 0x0000FFFF, 0x00, LNKA, 0x00 },
+
+ // CBDMA
+ GEN_UNCORE_LEGACY_IRQ(0x0004FFFF),
+
+ // Ubox
+ GEN_UNCORE_LEGACY_IRQ(0x0008FFFF)
+})
+
+// Socket 1, IIOStack 0 device IOAPIC interrupt routing
+Name (AR40, Package (0x09)
+{
+ // DMI
+ Package (0x04) { 0x0000FFFF, 0x00, 0x00, 0x4F },
+
+ // CBDMA
+ GEN_UNCORE_IOAPIC_IRQ(0x0004FFFF, 0x4A, 0x4B, 0x4A, 0x4B),
+
+ // Ubox
+ GEN_UNCORE_IOAPIC_IRQ(0x0008FFFF, 0x48, 0x4C, 0x4D, 0x4E),
+})
+
+// Socket 1, IIOStack 1 device legacy interrupt routing
+Name (PR50, Package (0x40)
+{
+ // PCI Express Port
+ GEN_PCIE_LEGACY_IRQ(),
+
+ // CHA Devices
+ GEN_UNCORE_LEGACY_IRQ(0x0008FFFF),
+ GEN_UNCORE_LEGACY_IRQ(0x0009FFFF),
+ GEN_UNCORE_LEGACY_IRQ(0x000AFFFF),
+ GEN_UNCORE_LEGACY_IRQ(0x000BFFFF),
+ GEN_UNCORE_LEGACY_IRQ(0x000EFFFF),
+ GEN_UNCORE_LEGACY_IRQ(0x000FFFFF),
+ GEN_UNCORE_LEGACY_IRQ(0x0010FFFF),
+ GEN_UNCORE_LEGACY_IRQ(0x0011FFFF),
+ GEN_UNCORE_LEGACY_IRQ(0x0014FFFF),
+ GEN_UNCORE_LEGACY_IRQ(0x0015FFFF),
+ GEN_UNCORE_LEGACY_IRQ(0x0016FFFF),
+ GEN_UNCORE_LEGACY_IRQ(0x0017FFFF),
+ GEN_UNCORE_LEGACY_IRQ(0x001DFFFF),
+
+ // PCU Devices
+ GEN_UNCORE_LEGACY_IRQ(0x001EFFFF),
+ GEN_UNCORE_LEGACY_IRQ(0x001FFFFF)
+})
+
+// Socket 1, IIOStack 1 device IOAPIC interrupt routing
+Name (AR50, Package (0x40)
+{
+ // PCI Express Port
+ GEN_PCIE_IOAPIC_IRQ(0x57),
+
+ // CHA Devices
+ GEN_UNCORE_IOAPIC_IRQ(0x0008FFFF, 0x50, 0x54, 0x55, 0x56),
+ GEN_UNCORE_IOAPIC_IRQ(0x0009FFFF, 0x50, 0x54, 0x55, 0x56),
+ GEN_UNCORE_IOAPIC_IRQ(0x000AFFFF, 0x50, 0x54, 0x55, 0x56),
+ GEN_UNCORE_IOAPIC_IRQ(0x000BFFFF, 0x50, 0x54, 0x55, 0x56),
+ GEN_UNCORE_IOAPIC_IRQ(0x000EFFFF, 0x50, 0x54, 0x55, 0x56),
+ GEN_UNCORE_IOAPIC_IRQ(0x000FFFFF, 0x50, 0x54, 0x55, 0x56),
+ GEN_UNCORE_IOAPIC_IRQ(0x0010FFFF, 0x50, 0x54, 0x55, 0x56),
+ GEN_UNCORE_IOAPIC_IRQ(0x0011FFFF, 0x50, 0x54, 0x55, 0x56),
+ GEN_UNCORE_IOAPIC_IRQ(0x0014FFFF, 0x50, 0x54, 0x55, 0x56),
+ GEN_UNCORE_IOAPIC_IRQ(0x0015FFFF, 0x50, 0x54, 0x55, 0x56),
+ GEN_UNCORE_IOAPIC_IRQ(0x0016FFFF, 0x50, 0x54, 0x55, 0x56),
+ GEN_UNCORE_IOAPIC_IRQ(0x0017FFFF, 0x50, 0x54, 0x55, 0x56),
+ GEN_UNCORE_IOAPIC_IRQ(0x001DFFFF, 0x50, 0x54, 0x55, 0x56),
+
+ // PCU Devices
+ GEN_UNCORE_IOAPIC_IRQ(0x001EFFFF, 0x50, 0x54, 0x55, 0x56),
+ GEN_UNCORE_IOAPIC_IRQ(0x001FFFFF, 0x50, 0x54, 0x55, 0x56)
+})
+
+// Socket 1, IIOStack 2 device legacy interrupt routing
+Name (PR60, Package (0x24)
+{
+ // PCI Express Port
+ GEN_PCIE_LEGACY_IRQ(),
+
+ // Integrated Memory Controller
+ GEN_UNCORE_LEGACY_IRQ(0x0008FFFF),
+ GEN_UNCORE_LEGACY_IRQ(0x0009FFFF),
+
+ // Uncore Devices
+ GEN_UNCORE_LEGACY_IRQ(0x000AFFFF),
+ GEN_UNCORE_LEGACY_IRQ(0x000BFFFF),
+ GEN_UNCORE_LEGACY_IRQ(0x000CFFFF),
+ GEN_UNCORE_LEGACY_IRQ(0x000DFFFF),
+ GEN_UNCORE_LEGACY_IRQ(0x0016FFFF),
+ GEN_UNCORE_LEGACY_IRQ(0x0017FFFF)
+})
+
+// Socket 1, IIOStack 2 device IOAPIC interrupt routing
+Name (AR60, Package (0x24)
+{
+ // PCI Express Port
+ GEN_PCIE_IOAPIC_IRQ(0x5F),
+
+ // Integrated Memory Controller
+ GEN_UNCORE_IOAPIC_IRQ(0x0008FFFF, 0x58, 0x5C, 0x5D, 0x5E),
+ GEN_UNCORE_IOAPIC_IRQ(0x0009FFFF, 0x58, 0x5C, 0x5D, 0x5E),
+
+ // Uncore Devices
+ GEN_UNCORE_IOAPIC_IRQ(0x000AFFFF, 0x58, 0x5C, 0x5D, 0x5E),
+ GEN_UNCORE_IOAPIC_IRQ(0x000BFFFF, 0x58, 0x5C, 0x5D, 0x5E),
+ GEN_UNCORE_IOAPIC_IRQ(0x000CFFFF, 0x58, 0x5C, 0x5D, 0x5E),
+ GEN_UNCORE_IOAPIC_IRQ(0x000DFFFF, 0x58, 0x5C, 0x5D, 0x5E),
+ GEN_UNCORE_IOAPIC_IRQ(0x0016FFFF, 0x58, 0x5C, 0x5D, 0x5E),
+ GEN_UNCORE_IOAPIC_IRQ(0x0017FFFF, 0x58, 0x5C, 0x5D, 0x5E)
+})
+
+// Socket 1, IIOStack 3 device legacy interrupt routing
+Name (PR68, Package (0x20)
+{
+ // PCI Express Port
+ GEN_PCIE_LEGACY_IRQ(),
+
+ // Uncore Devices
+ GEN_UNCORE_LEGACY_IRQ(0x000EFFFF),
+ GEN_UNCORE_LEGACY_IRQ(0x000FFFFF),
+ GEN_UNCORE_LEGACY_IRQ(0x0010FFFF),
+ GEN_UNCORE_LEGACY_IRQ(0x0012FFFF),
+ GEN_UNCORE_LEGACY_IRQ(0x0015FFFF),
+ GEN_UNCORE_LEGACY_IRQ(0x0016FFFF),
+ GEN_UNCORE_LEGACY_IRQ(0x0017FFFF)
+})
+
+// Socket 1, IIOStack 3 device legacy interrupt routing
+Name (AR68, Package (0x20)
+{
+ // PCI Express Port
+ GEN_PCIE_IOAPIC_IRQ(0x67),
+
+ // Uncore Devices
+ GEN_UNCORE_IOAPIC_IRQ(0x000EFFFF, 0x60, 0x64, 0x65, 0x66),
+ GEN_UNCORE_IOAPIC_IRQ(0x000FFFFF, 0x60, 0x64, 0x65, 0x66),
+ GEN_UNCORE_IOAPIC_IRQ(0x0010FFFF, 0x60, 0x64, 0x65, 0x66),
+ GEN_UNCORE_IOAPIC_IRQ(0x0012FFFF, 0x60, 0x64, 0x65, 0x66),
+ GEN_UNCORE_IOAPIC_IRQ(0x0015FFFF, 0x60, 0x64, 0x65, 0x66),
+ GEN_UNCORE_IOAPIC_IRQ(0x0016FFFF, 0x60, 0x64, 0x65, 0x66),
+ GEN_UNCORE_IOAPIC_IRQ(0x0017FFFF, 0x60, 0x64, 0x65, 0x66)
+})
diff --git a/src/soc/intel/xeon_sp/bootblock/bootblock.c b/src/soc/intel/xeon_sp/bootblock/bootblock.c
new file mode 100644
index 0000000..482f5b5
--- /dev/null
+++ b/src/soc/intel/xeon_sp/bootblock/bootblock.c
@@ -0,0 +1,61 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2019 - 2020 Intel Corporation.
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <bootblock_common.h>
+#include <device/pci.h>
+#include <FsptUpd.h>
+#include <intelblocks/fast_spi.h>
+#include <soc/iomap.h>
+#include <console/console.h>
+
+const FSPT_UPD temp_ram_init_params = {
+ .FspUpdHeader = {
+ .Signature = FSPT_UPD_SIGNATURE,
+ .Revision = 1,
+ .Reserved = {0},
+ },
+ .FsptCoreUpd = {
+ .MicrocodeRegionBase = (UINT32)CONFIG_CPU_MICROCODE_CBFS_LOC,
+ .MicrocodeRegionLength = (UINT32)CONFIG_CPU_MICROCODE_CBFS_LEN,
+ .CodeRegionBase = (uint32_t)(0x100000000ULL - CONFIG_ROM_SIZE),
+ .CodeRegionLength = (UINT32)CONFIG_ROM_SIZE,
+ .Reserved1 = {0},
+ },
+ .FsptConfig = {
+ .PcdFsptPort80RouteDisable = 0,
+ .ReservedTempRamInitUpd = {0},
+ },
+ .UnusedUpdSpace0 = {0},
+ .UpdTerminator = 0x55AA,
+};
+
+asmlinkage void bootblock_c_entry(uint64_t base_timestamp)
+{
+ fast_spi_cache_bios_region();
+
+ bootblock_main_with_basetime(base_timestamp);
+}
+
+void bootblock_soc_early_init(void)
+{
+ fast_spi_early_init(SPI_BASE_ADDRESS);
+}
+
+void bootblock_soc_init(void)
+{
+ if (CONFIG(BOOTBLOCK_CONSOLE))
+ printk(BIOS_DEBUG, "FSP TempRamInit successful...\n");
+}
diff --git a/src/soc/intel/xeon_sp/chip.c b/src/soc/intel/xeon_sp/chip.c
new file mode 100644
index 0000000..832f98e
--- /dev/null
+++ b/src/soc/intel/xeon_sp/chip.c
@@ -0,0 +1,603 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2019 - 2020 Intel Corporation
+ * Copyright (C) 2019 - 2020 Facebook Inc.
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <cbfs.h>
+#include <assert.h>
+#include <device/pci.h>
+#include <soc/acpi.h>
+#include <soc/ramstage.h>
+#include <soc/soc_util.h>
+
+struct pci_resource {
+ struct device *dev;
+ struct resource *res;
+ struct pci_resource *next;
+};
+
+struct stack_dev_resource {
+ uint8_t align;
+ struct pci_resource *children;
+ struct stack_dev_resource *next;
+};
+
+static void assign_stack_resources(struct iiostack_resource *stack_list,
+ struct device *dev, struct resource *bridge);
+
+static void xeonsp_pci_domain_scan_bus(struct device *dev)
+{
+ DEV_FUNC_ENTER(dev);
+ struct bus *link = dev->link_list;
+
+ printk(BIOS_SPEW, "%s:%s scanning buses under device %s\n",
+ __FILE__, __func__, dev_path(dev));
+ while (link != NULL) {
+ if (link->secondary == 0) { // scan only PSTACK buses
+ struct device *d;
+ for (d = link->children; d; d = d->sibling)
+ pci_probe_dev(d, link, d->path.pci.devfn);
+ scan_bridges(link);
+ } else {
+ pci_scan_bus(link, PCI_DEVFN(0, 0), 0xff);
+ }
+ link = link->next;
+ }
+ DEV_FUNC_EXIT(dev);
+}
+
+static void xeonsp_pci_dev_iterator(struct bus *bus,
+ void (*dev_iterator)(struct device *, void *),
+ void (*res_iterator)(struct device *, struct resource *, void *),
+ void *data)
+{
+ struct device *curdev;
+ struct resource *res;
+
+ /* Walk through all devices and find which resources they need. */
+ for (curdev = bus->children; curdev; curdev = curdev->sibling) {
+ struct bus *link;
+
+ if (!curdev->enabled)
+ continue;
+
+ if (!curdev->ops || !curdev->ops->read_resources) {
+ if (curdev->path.type != DEVICE_PATH_APIC)
+ printk(BIOS_ERR, "%s missing read_resources\n",
+ dev_path(curdev));
+ continue;
+ }
+
+ if (dev_iterator)
+ dev_iterator(curdev, data);
+
+ if (res_iterator) {
+ for (res = curdev->resource_list; res; res = res->next)
+ res_iterator(curdev, res, data);
+ }
+
+ /* Read in the resources behind the current device's links. */
+ for (link = curdev->link_list; link; link = link->next)
+ xeonsp_pci_dev_iterator(link, dev_iterator, res_iterator, data);
+ }
+}
+
+static void xeonsp_pci_dev_read_resources(struct device *dev, void *data)
+{
+ post_log_path(dev);
+ dev->ops->read_resources(dev);
+}
+
+static void xeonsp_pci_dev_dummy_func(struct device *dev)
+{
+}
+
+static void xeonsp_reset_pci_op(struct device *dev, void *data)
+{
+ if (dev->ops)
+ dev->ops->read_resources = xeonsp_pci_dev_dummy_func;
+}
+
+static STACK_RES *find_stack_for_bus(struct iiostack_resource *info, uint8_t bus)
+{
+ for (int i = 0; i < info->no_of_stacks; ++i) {
+ if (bus >= info->res[i].BusBase && bus <= info->res[i].BusLimit)
+ return &info->res[i];
+ }
+ return NULL;
+}
+
+static void add_res_to_stack(struct stack_dev_resource **root,
+ struct device *dev, struct resource *res)
+{
+ struct stack_dev_resource *cur = *root;
+ while (cur) {
+ if (cur->align == res->align || cur->next == NULL) /* equal or last record */
+ break;
+ else if (cur->align > res->align) {
+ if (cur->next->align < res->align) /* need to insert new record here */
+ break;
+ cur = cur->next;
+ } else {
+ break;
+ }
+ }
+
+ struct stack_dev_resource *nr;
+ if (!cur || cur->align != res->align) { /* need to add new record */
+ nr = malloc(sizeof(struct stack_dev_resource));
+ if (nr == 0)
+ die("assign_resource_to_stack(): out of memory.\n");
+ memset(nr, 0, sizeof(struct stack_dev_resource));
+ nr->align = res->align;
+ if (!cur) {
+ *root = nr; /* head node */
+ } else if (cur->align > nr->align) {
+ if (cur->next == NULL) {
+ cur->next = nr;
+ } else {
+ nr->next = cur->next;
+ cur->next = nr;
+ }
+ } else { /* insert in the beginning */
+ nr->next = cur;
+ *root = nr;
+ }
+ } else {
+ nr = cur;
+ }
+
+ assert(nr != NULL && nr->align == res->align);
+
+ struct pci_resource *npr = malloc(sizeof(struct pci_resource));
+ if (npr == NULL)
+ die("%s: out of memory.\n", __func__);
+ npr->res = res;
+ npr->dev = dev;
+ npr->next = NULL;
+
+ if (nr->children == NULL) {
+ nr->children = npr;
+ } else {
+ struct pci_resource *pr = nr->children;
+ while (pr->next != NULL)
+ pr = pr->next;
+ pr->next = npr;
+ }
+}
+
+static void reserve_dev_resources(STACK_RES *stack, unsigned long res_type,
+ struct stack_dev_resource *res_root, struct resource *bridge)
+{
+ uint8_t align;
+ uint64_t orig_base, base;
+
+ if (res_type & IORESOURCE_IO)
+ orig_base = stack->PciResourceIoBase;
+ else if ((res_type & IORESOURCE_MEM) && ((res_type & IORESOURCE_PCI64) ||
+ (!res_root && bridge && (bridge->flags & IORESOURCE_PREFETCH))))
+ orig_base = stack->PciResourceMem64Base;
+ else
+ orig_base = stack->PciResourceMem32Base;
+
+ align = 0;
+ base = orig_base;
+ int first = 1;
+ while (res_root) { /* loop through all devices grouped by alignment requirements */
+ struct pci_resource *pr = res_root->children;
+ while (pr) {
+ if (first) {
+ if (bridge) { /* takes highest alignment */
+ if (bridge->align < pr->res->align)
+ bridge->align = pr->res->align;
+ orig_base = ALIGN_UP(orig_base, 1 << bridge->align);
+ } else {
+ orig_base = ALIGN_UP(orig_base, 1 << pr->res->align);
+ }
+ base = orig_base;
+
+ if (bridge)
+ bridge->base = base;
+ pr->res->base = base;
+ first = 0;
+ } else {
+ pr->res->base = ALIGN_UP(base, 1 << pr->res->align);
+ }
+ pr->res->limit = pr->res->base + pr->res->size - 1;
+ base = pr->res->limit + 1;
+ pr->res->flags |= (IORESOURCE_ASSIGNED);
+ pr = pr->next;
+ }
+ res_root = res_root->next;
+ }
+
+ if (bridge) {
+ /* this bridge doesn't have any resources, will set it to default window */
+ if (first) {
+ orig_base = ALIGN_UP(orig_base, 1 << bridge->align);
+ bridge->base = orig_base;
+ base = orig_base + (1ULL << bridge->gran);
+ }
+
+ bridge->size = ALIGN_UP(base, 1 << bridge->align) - bridge->base;
+
+ bridge->limit = bridge->base + bridge->size - 1;
+ bridge->flags |= (IORESOURCE_ASSIGNED);
+ base = bridge->limit + 1;
+ }
+
+ /* update new limits */
+ if (res_type & IORESOURCE_IO)
+ stack->PciResourceIoBase = base;
+ else if ((res_type & IORESOURCE_MEM) && ((res_type & IORESOURCE_PCI64) ||
+ (!res_root && bridge && (bridge->flags & IORESOURCE_PREFETCH))))
+ stack->PciResourceMem64Base = base;
+ else
+ stack->PciResourceMem32Base = base;
+}
+
+static void reclaim_resource_mem(struct stack_dev_resource *res_root)
+{
+ while (res_root) { /* loop through all devices grouped by alignment requirements */
+ /* free pci_resource */
+ struct pci_resource *pr = res_root->children;
+ while (pr) {
+ struct pci_resource *dpr = pr;
+ pr = pr->next;
+ free(dpr);
+ }
+
+ /* free stack_dev_resource */
+ struct stack_dev_resource *ddr = res_root;
+ res_root = res_root->next;
+ free(ddr);
+ }
+}
+
+static void assign_bridge_resources(struct iiostack_resource *stack_list,
+ struct device *dev, struct resource *bridge)
+{
+ struct resource *res;
+ if (!dev->enabled)
+ return;
+
+ for (res = dev->resource_list; res; res = res->next) {
+ if (!(res->flags & IORESOURCE_BRIDGE) ||
+ (bridge && ((bridge->flags & (IORESOURCE_IO | IORESOURCE_MEM |
+ IORESOURCE_PREFETCH | IORESOURCE_PCI64)) !=
+ (res->flags & (IORESOURCE_IO | IORESOURCE_MEM |
+ IORESOURCE_PREFETCH | IORESOURCE_PCI64)))))
+ continue;
+
+ assign_stack_resources(stack_list, dev, res);
+ if (!bridge)
+ continue;
+ /* for 1st time update, overlading IORESOURCE_ASSIGNED */
+ if (!(bridge->flags & IORESOURCE_ASSIGNED)) {
+ bridge->base = res->base;
+ bridge->limit = res->limit;
+ bridge->flags |= (IORESOURCE_ASSIGNED);
+ } else {
+ /* update bridge range from child bridge range */
+ if (res->base < bridge->base)
+ bridge->base = res->base;
+ if (res->limit > bridge->limit)
+ bridge->limit = res->limit;
+ }
+ bridge->size = (bridge->limit - bridge->base + 1);
+ }
+}
+
+static void assign_stack_resources(struct iiostack_resource *stack_list,
+ struct device *dev, struct resource *bridge)
+{
+ struct bus *bus;
+
+ /* Read in the resources behind the current device's links. */
+ for (bus = dev->link_list; bus; bus = bus->next) {
+ struct device *curdev;
+ STACK_RES *stack;
+
+ /* get IIO stack for this bus */
+ stack = find_stack_for_bus(stack_list, bus->secondary);
+ assert(stack != NULL);
+
+ /* Assign resources to bridge */
+ for (curdev = bus->children; curdev; curdev = curdev->sibling)
+ assign_bridge_resources(stack_list, curdev, bridge);
+
+ /* Pick non-bridged resources for resource allocation for each resource type */
+ unsigned long flags[5] = {IORESOURCE_IO, IORESOURCE_MEM,
+ (IORESOURCE_PCI64|IORESOURCE_MEM), (IORESOURCE_MEM|IORESOURCE_PREFETCH),
+ (IORESOURCE_PCI64|IORESOURCE_MEM|IORESOURCE_PREFETCH)};
+ uint8_t no_res_types = 5;
+ if (bridge) {
+ flags[0] = bridge->flags &
+ (IORESOURCE_IO | IORESOURCE_MEM | IORESOURCE_PREFETCH);
+ if ((bridge->flags & IORESOURCE_MEM) &&
+ (bridge->flags & IORESOURCE_PREFETCH))
+ flags[0] |= IORESOURCE_PCI64;
+ no_res_types = 1;
+ }
+
+ /* Process each resource type */
+ for (int rt = 0; rt < no_res_types; ++rt) {
+ struct stack_dev_resource *res_root = NULL;
+
+ for (curdev = bus->children; curdev; curdev = curdev->sibling) {
+ struct resource *res;
+ if (!curdev->enabled)
+ continue;
+
+ for (res = curdev->resource_list; res; res = res->next) {
+ if ((res->flags & IORESOURCE_BRIDGE) || (res->flags &
+ (IORESOURCE_STORED | IORESOURCE_RESERVE |
+ IORESOURCE_FIXED | IORESOURCE_ASSIGNED)
+ ) || ((res->flags & (IORESOURCE_IO |
+ IORESOURCE_MEM | IORESOURCE_PCI64
+ | IORESOURCE_PREFETCH))
+ != flags[rt]) || res->size == 0)
+ continue;
+ else
+ add_res_to_stack(&res_root, curdev, res);
+ }
+ }
+
+ /* Allocate resources and update bridge range */
+ if (res_root || (bridge && !(bridge->flags & IORESOURCE_ASSIGNED))) {
+ reserve_dev_resources(stack, flags[rt], res_root, bridge);
+ reclaim_resource_mem(res_root);
+ }
+ }
+ }
+}
+
+static void xeonsp_constrain_pci_resources(struct device *dev, struct resource *res, void *data)
+{
+ STACK_RES *stack = (STACK_RES *) data;
+ if (!(res->flags & IORESOURCE_FIXED))
+ return;
+
+ uint64_t base, limit;
+ if (res->flags & IORESOURCE_IO) {
+ base = stack->PciResourceIoBase;
+ limit = stack->PciResourceIoLimit;
+ } else if ((res->flags & IORESOURCE_MEM) && (res->flags & IORESOURCE_PCI64)) {
+ base = stack->PciResourceMem64Base;
+ limit = stack->PciResourceMem64Limit;
+ } else {
+ base = stack->PciResourceMem32Base;
+ limit = stack->PciResourceMem32Limit;
+ }
+
+ if (((res->base + res->size - 1) < base) || (res->base > limit)) /* outside window */
+ return;
+
+ if (res->limit > limit) /* resource end is out of limit */
+ limit = res->base - 1;
+ else
+ base = res->base + res->size;
+
+ if (res->flags & IORESOURCE_IO) {
+ stack->PciResourceIoBase = base;
+ stack->PciResourceIoLimit = limit;
+ } else if ((res->flags & IORESOURCE_MEM) && (res->flags & IORESOURCE_PCI64)) {
+ stack->PciResourceMem64Base = base;
+ stack->PciResourceMem64Limit = limit;
+ } else {
+ stack->PciResourceMem32Base = base;
+ stack->PciResourceMem32Limit = limit;
+ }
+}
+
+static void xeonsp_pci_domain_read_resources(struct device *dev)
+{
+ struct bus *link;
+
+ DEV_FUNC_ENTER(dev);
+
+ pci_domain_read_resources(dev);
+
+ /*
+ * Walk through all devices in this domain and read resources.
+ * Since there is no callback when read resource operation is
+ * complete for all devices, domain read resource function initiates
+ * read resources for all devices and swaps read resource operation
+ * with dummy function to avoid warning.
+ */
+ for (link = dev->link_list; link; link = link->next)
+ xeonsp_pci_dev_iterator(link, xeonsp_pci_dev_read_resources, NULL, NULL);
+
+ for (link = dev->link_list; link; link = link->next)
+ xeonsp_pci_dev_iterator(link, xeonsp_reset_pci_op, NULL, NULL);
+
+ /*
+ * 1. group devices, resources for each stack
+ * 2. order resources in descending order of requested resource allocation sizes
+ */
+ struct iiostack_resource stack_info = {0};
+ get_iiostack_info(&stack_info);
+
+ /* constrain stack window */
+ for (link = dev->link_list; link; link = link->next) {
+ STACK_RES *stack = find_stack_for_bus(&stack_info, link->secondary);
+ assert(stack != 0);
+ xeonsp_pci_dev_iterator(link, NULL, xeonsp_constrain_pci_resources, stack);
+ }
+
+ /* assign resources */
+ assign_stack_resources(&stack_info, dev, NULL);
+
+ DEV_FUNC_EXIT(dev);
+}
+
+static void reset_resource_to_unassigned(struct device *dev, struct resource *res, void *data)
+{
+ if ((res->flags & (IORESOURCE_IO | IORESOURCE_MEM)) &&
+ !(res->flags & (IORESOURCE_FIXED | IORESOURCE_RESERVE))) {
+ res->flags &= ~IORESOURCE_ASSIGNED;
+ }
+}
+
+static void xeonsp_pci_domain_set_resources(struct device *dev)
+{
+ DEV_FUNC_ENTER(dev);
+
+ print_resource_tree(dev, BIOS_SPEW, "Before xeonsp pci domain set resource");
+
+ /* reset bus 0 dev resource assignment - need to change them to FSP IIOStack window */
+ xeonsp_pci_dev_iterator(dev->link_list, NULL, reset_resource_to_unassigned, NULL);
+
+ /* update dev resources based on IIOStack IO/Mem32/Mem64 windows */
+ xeonsp_pci_domain_read_resources(dev);
+
+ struct bus *link = dev->link_list;
+ while (link != NULL) {
+ assign_resources(link);
+ link = link->next;
+ }
+
+ print_resource_tree(dev, BIOS_SPEW, "After xeonsp pci domain set resource");
+
+ DEV_FUNC_EXIT(dev);
+}
+
+static struct device_operations pci_domain_ops = {
+ .read_resources = &pci_domain_read_resources,
+ .set_resources = &xeonsp_pci_domain_set_resources,
+ .scan_bus = &xeonsp_pci_domain_scan_bus,
+#if CONFIG(HAVE_ACPI_TABLES)
+ .write_acpi_tables = &northbridge_write_acpi_tables,
+#endif
+};
+
+static struct device_operations cpu_bus_ops = {
+ .read_resources = DEVICE_NOOP,
+ .set_resources = DEVICE_NOOP,
+ .enable_resources = DEVICE_NOOP,
+ .init = xeon_sp_init_cpus,
+ .scan_bus = NULL,
+#if CONFIG(HAVE_ACPI_TABLES)
+ /* defined in src/soc/intel/common/block/acpi/acpi.c */
+ .acpi_fill_ssdt_generator = generate_cpu_entries,
+#endif
+};
+
+/* Attach IIO stack bus numbers with dummy device to PCI DOMAIN 0000 device */
+static void attach_iio_stacks(struct device *dev)
+{
+ struct bus *iiostack_bus;
+ struct device dummy;
+ struct iiostack_resource stack_info = {0};
+
+ DEV_FUNC_ENTER(dev);
+
+ get_iiostack_info(&stack_info);
+ for (int s = 0; s < stack_info.no_of_stacks; ++s) {
+ /* only non zero bus no. needs to be enumerated */
+ if (stack_info.res[s].BusBase == 0)
+ continue;
+
+ iiostack_bus = malloc(sizeof(struct bus));
+ if (iiostack_bus == NULL)
+ die("%s: out of memory.\n", __func__);
+ memset(iiostack_bus, 0, sizeof(*iiostack_bus));
+ memcpy(iiostack_bus, dev->bus, sizeof(*iiostack_bus));
+ iiostack_bus->secondary = stack_info.res[s].BusBase;
+ iiostack_bus->subordinate = stack_info.res[s].BusBase;
+ iiostack_bus->dev = NULL;
+ iiostack_bus->children = NULL;
+ iiostack_bus->next = NULL;
+ iiostack_bus->link_num = 1;
+
+ dummy.bus = iiostack_bus;
+ dummy.path.type = DEVICE_PATH_PCI;
+ dummy.path.pci.devfn = 0;
+ uint32_t id = pci_read_config32(&dummy, PCI_VENDOR_ID);
+ if (id == 0xffffffff)
+ printk(BIOS_WARNING, "IIO Stack device %s not visible\n",
+ dev_path(&dummy));
+
+ if (dev->link_list == NULL) {
+ dev->link_list = iiostack_bus;
+ } else {
+ struct bus *nlink = dev->link_list;
+ while (nlink->next != NULL)
+ nlink = nlink->next;
+ nlink->next = iiostack_bus;
+ }
+ }
+
+ DEV_FUNC_EXIT(dev);
+}
+
+static void soc_enable_dev(struct device *dev)
+{
+ /* Set the operations if it is a special bus type */
+ if (dev->path.type == DEVICE_PATH_DOMAIN) {
+ dev->ops = &pci_domain_ops;
+ attach_iio_stacks(dev);
+ } else if (dev->path.type == DEVICE_PATH_CPU_CLUSTER) {
+ dev->ops = &cpu_bus_ops;
+ }
+}
+
+static void soc_init(void *data)
+{
+ printk(BIOS_DEBUG, "coreboot: calling fsp_silicon_init\n");
+ fsp_silicon_init(false);
+}
+
+static void soc_final(void *data)
+{
+ // Temp Fix - should be done by FSP, in 2S bios completion
+ // is not carried out on socket 2
+ set_bios_init_completion();
+}
+
+static void soc_silicon_init_params(FSPS_UPD *silupd)
+{
+}
+
+void platform_fsp_silicon_init_params_cb(FSPS_UPD *silupd)
+{
+ const struct microcode *microcode_file;
+ size_t microcode_len;
+
+ microcode_file = cbfs_boot_map_with_leak("cpu_microcode_blob.bin",
+ CBFS_TYPE_MICROCODE, µcode_len);
+
+ if ((microcode_file != NULL) && (microcode_len != 0)) {
+ /* Update CPU Microcode patch base address/size */
+ silupd->FspsConfig.PcdCpuMicrocodePatchBase =
+ (uint32_t)microcode_file;
+ silupd->FspsConfig.PcdCpuMicrocodePatchSize =
+ (uint32_t)microcode_len;
+ }
+
+ soc_silicon_init_params(silupd);
+ mainboard_silicon_init_params(silupd);
+}
+
+struct chip_operations soc_intel_xeon_sp_ops = {
+ CHIP_NAME("Intel Xeon-SP SOC")
+ .enable_dev = soc_enable_dev,
+ .init = soc_init,
+ .final = soc_final
+};
+
+struct pci_operations soc_pci_ops = {
+ .set_subsystem = pci_dev_set_subsystem,
+};
diff --git a/src/soc/intel/xeon_sp/chip.h b/src/soc/intel/xeon_sp/chip.h
new file mode 100644
index 0000000..72f2445
--- /dev/null
+++ b/src/soc/intel/xeon_sp/chip.h
@@ -0,0 +1,87 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2019 - 2020 Intel Corporation
+ * Copyright (C) 2019 - 2020 Facebook Inc
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+
+#ifndef _SOC_CHIP_H_
+#define _SOC_CHIP_H_
+
+#include <stdint.h>
+#include <intelblocks/cfg.h>
+#include <soc/irq.h>
+
+struct soc_intel_xeon_sp_config {
+ /* Common struct containing soc config data required by common code */
+ struct soc_intel_common_config common_soc_config;
+
+ /**
+ * Interrupt Routing configuration
+ * If bit7 is 1, the interrupt is disabled.
+ */
+ uint8_t pirqa_routing;
+ uint8_t pirqb_routing;
+ uint8_t pirqc_routing;
+ uint8_t pirqd_routing;
+ uint8_t pirqe_routing;
+ uint8_t pirqf_routing;
+ uint8_t pirqg_routing;
+ uint8_t pirqh_routing;
+
+ /**
+ * Device Interrupt Routing configuration
+ * Interrupt Pin x Route.
+ * 0h = PIRQA#
+ * 1h = PIRQB#
+ * 2h = PIRQC#
+ * 3h = PIRQD#
+ * 4h = PIRQE#
+ * 5h = PIRQF#
+ * 6h = PIRQG#
+ * 7h = PIRQH#
+ */
+ uint16_t ir00_routing;
+ uint16_t ir01_routing;
+ uint16_t ir02_routing;
+ uint16_t ir03_routing;
+ uint16_t ir04_routing;
+
+ /**
+ * Device Interrupt Polarity Control
+ * ipc0 - IRQ-00-31 - 1: Active low to IOAPIC, 0: Active high to IOAPIC
+ * ipc1 - IRQ-32-63 - 1: Active low to IOAPIC, 0: Active high to IOAPIC
+ * ipc2 - IRQ-64-95 - 1: Active low to IOAPIC, 0: Active high to IOAPIC
+ * ipc3 - IRQ-96-119 - 1: Active low to IOAPIC, 0: Active high to IOAPIC
+ */
+ uint32_t ipc0;
+ uint32_t ipc1;
+ uint32_t ipc2;
+ uint32_t ipc3;
+
+ uint64_t turbo_ratio_limit;
+ uint64_t turbo_ratio_limit_cores;
+
+ uint32_t pstate_req_ratio;
+
+ uint32_t vtd_support;
+ uint32_t coherency_support;
+ uint32_t ats_support;
+};
+
+extern struct chip_operations soc_intel_xeon_sp_ops;
+
+typedef struct soc_intel_xeon_sp_config config_t;
+
+#endif
diff --git a/src/soc/intel/xeon_sp/cpu.c b/src/soc/intel/xeon_sp/cpu.c
new file mode 100644
index 0000000..1d5c578
--- /dev/null
+++ b/src/soc/intel/xeon_sp/cpu.c
@@ -0,0 +1,260 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2019 - 2020 Intel Corporation
+ * Copyright (C) 2019 - 2020 Facebook Inc
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <console/console.h>
+#include <intelblocks/cpulib.h>
+#include <cpu/cpu.h>
+#include <cpu/x86/mtrr.h>
+#include <cpu/x86/mp.h>
+#include <cpu/intel/turbo.h>
+#include <soc/msr.h>
+#include <soc/cpu.h>
+#include <soc/soc_util.h>
+#include <assert.h>
+#include "chip.h"
+
+static const config_t *chip_config = NULL;
+
+static void xeon_configure_mca(void)
+{
+ msr_t msr;
+ struct cpuid_result cpuid_regs;
+
+ /* Check feature flag in CPUID.(EAX=1):EDX[7]==1 MCE
+ * and CPUID.(EAX=1):EDX[14]==1 MCA*/
+ cpuid_regs = cpuid(1);
+ if ((cpuid_regs.edx & (1<<7 | 1<<14)) != (1<<7 | 1<<14))
+ return;
+
+ msr = rdmsr(IA32_MCG_CAP);
+ if (msr.lo & IA32_MCG_CAP_CTL_P_MASK) {
+ /* Enable all error logging */
+ msr.lo = msr.hi = 0xffffffff;
+ wrmsr(IA32_MCG_CTL, msr);
+ }
+
+ /* TODO(adurbin): This should only be done on a cold boot. Also, some
+ of these banks are core vs package scope. For now every CPU clears
+ every bank. */
+ mca_configure();
+}
+
+static void xeon_sp_core_init(struct device *cpu)
+{
+ msr_t msr;
+
+ printk(BIOS_INFO, "%s dev: %s, cpu: %d, apic_id: 0x%x\n",
+ __func__, dev_path(cpu), cpu_index(), cpu->path.apic.apic_id);
+ assert(chip_config != NULL);
+
+ /* set MSR_PKG_CST_CONFIG_CONTROL - scope per core*/
+ msr.hi = 0;
+ msr.lo = (PKG_CSTATE_NO_LIMIT | IO_MWAIT_REDIRECTION_ENABLE | CFG_LOCK_ENABLE);
+ wrmsr(MSR_PKG_CST_CONFIG_CONTROL, msr);
+
+ /* set MSR_PMG_IO_CAPTURE_BASE - scope per core */
+ msr.hi = 0;
+ msr.lo = (LVL_2_BASE_ADDRESS | CST_RANGE_MAX_C6);
+ wrmsr(MSR_PMG_IO_CAPTURE_BASE, msr);
+
+ /* Enable Energy Perf Bias Access, Dynamic switching and lock MSR */
+ msr = rdmsr(MSR_POWER_CTL);
+ msr.lo |= (ENERGY_PERF_BIAS_ACCESS_ENABLE | PWR_PERF_TUNING_DYN_SWITCHING_ENABLE
+ | PROCHOT_LOCK_ENABLE);
+ wrmsr(MSR_POWER_CTL, msr);
+
+ /* Set P-State ratio */
+ msr = rdmsr(MSR_IA32_PERF_CTRL);
+ msr.lo &= ~PSTATE_REQ_MASK;
+ msr.lo |= (chip_config->pstate_req_ratio << PSTATE_REQ_SHIFT);
+ wrmsr(MSR_IA32_PERF_CTRL, msr);
+
+ /*
+ * Set HWP base feature, EPP reg enumeration, lock thermal and msr
+ * TODO: Set LOCK_MISC_PWR_MGMT_MSR, Unexpected Exception if you
+ * lock & issue wrmsr on every thread
+ * This is package level MSR. Need to check if it updates correctly on
+ * multi-socket platform.
+ */
+ msr = rdmsr(MSR_MISC_PWR_MGMT);
+ if (!(msr.lo & LOCK_MISC_PWR_MGMT_MSR)) { /* if already locked skip update */
+ msr.lo = (HWP_ENUM_ENABLE | HWP_EPP_ENUM_ENABLE | LOCK_MISC_PWR_MGMT_MSR |
+ LOCK_THERM_INT);
+ wrmsr(MSR_MISC_PWR_MGMT, msr);
+ }
+
+ /* TODO MSR_VR_MISC_CONFIG */
+
+ /* Set current limit lock */
+ msr = rdmsr(MSR_VR_CURRENT_CONFIG);
+ msr.lo |= CURRENT_LIMIT_LOCK;
+ wrmsr(MSR_VR_CURRENT_CONFIG, msr);
+
+ /* Set Turbo Ratio Limits */
+ msr.lo = chip_config->turbo_ratio_limit & 0xffffffff;
+ msr.hi = (chip_config->turbo_ratio_limit >> 32) & 0xffffffff;
+ wrmsr(MSR_TURBO_RATIO_LIMIT, msr);
+
+ /* Set Turbo Ratio Limit Cores */
+ msr.lo = chip_config->turbo_ratio_limit_cores & 0xffffffff;
+ msr.hi = (chip_config->turbo_ratio_limit_cores >> 32) & 0xffffffff;
+ wrmsr(MSR_TURBO_RATIO_LIMIT_CORES, msr);
+
+ /* set Turbo Activation ratio */
+ msr.hi = 0;
+ msr = rdmsr(MSR_TURBO_ACTIVATION_RATIO);
+ msr.lo |= MAX_NON_TURBO_RATIO;
+ wrmsr(MSR_TURBO_ACTIVATION_RATIO, msr);
+
+ /* Enable Fast Strings */
+ msr = rdmsr(IA32_MISC_ENABLE);
+ msr.lo |= FAST_STRINGS_ENABLE_BIT;
+ wrmsr(IA32_MISC_ENABLE, msr);
+
+ /* Set energy policy */
+ msr_t msr1 = rdmsr(MSR_ENERGY_PERF_BIAS_CONFIG);
+ msr.lo = (msr1.lo & EPB_ENERGY_POLICY_MASK) >> EPB_ENERGY_POLICY_SHIFT;
+ msr.hi = 0;
+ wrmsr(MSR_IA32_ENERGY_PERF_BIAS, msr);
+
+ /* Enable Turbo */
+ enable_turbo();
+
+ /* Enable speed step. */
+ if (get_turbo_state() == TURBO_ENABLED) {
+ msr = rdmsr(IA32_MISC_ENABLE);
+ msr.lo |= SPEED_STEP_ENABLE_BIT;
+ wrmsr(IA32_MISC_ENABLE, msr);
+ }
+
+ /* Clear out pending MCEs */
+ xeon_configure_mca();
+}
+
+static struct device_operations cpu_dev_ops = {
+ .init = xeon_sp_core_init,
+};
+
+static const struct cpu_device_id cpu_table[] = {
+ /* Skylake-SP A0/A1 CPUID 0x506f0*/
+ {X86_VENDOR_INTEL, CPUID_SKYLAKE_SP_A0_A1},
+ /* Skylake-SP B0 CPUID 0x506f1*/
+ {X86_VENDOR_INTEL, CPUID_SKYLAKE_SP_B0},
+ /* Skylake-SP 4 CPUID 0x50654*/
+ {X86_VENDOR_INTEL, CPUID_SKYLAKE_SP_4},
+ {0, 0},
+};
+
+static const struct cpu_driver driver __cpu_driver = {
+ .ops = &cpu_dev_ops,
+ .id_table = cpu_table,
+};
+
+static void set_max_turbo_freq(void)
+{
+ msr_t msr, perf_ctl;
+
+ FUNC_ENTER();
+ perf_ctl.hi = 0;
+
+ /* Check for configurable TDP option */
+ if (get_turbo_state() == TURBO_ENABLED) {
+ msr = rdmsr(MSR_TURBO_RATIO_LIMIT);
+ perf_ctl.lo = (msr.lo & 0xff) << 8;
+ } else if (cpu_config_tdp_levels()) {
+ /* Set to nominal TDP ratio */
+ msr = rdmsr(MSR_CONFIG_TDP_NOMINAL);
+ perf_ctl.lo = (msr.lo & 0xff) << 8;
+ } else {
+ /* Platform Info bits 15:8 give max ratio */
+ msr = rdmsr(MSR_PLATFORM_INFO);
+ perf_ctl.lo = msr.lo & 0xff00;
+ }
+ wrmsr(IA32_PERF_CTL, perf_ctl);
+
+ printk(BIOS_DEBUG, "cpu: frequency set to %d\n",
+ ((perf_ctl.lo >> 8) & 0xff) * CPU_BCLK);
+ FUNC_EXIT();
+}
+
+/*
+ * Do essential initialization tasks before APs can be fired up
+ *
+ * Prevent race condition in MTRR solution. Enable MTRRs on the BSP. This
+ * creates the MTRR solution that the APs will use. Otherwise APs will try to
+ * apply the incomplete solution as the BSP is calculating it.
+ */
+static void pre_mp_init(void)
+{
+ printk(BIOS_DEBUG, "%s: entry\n", __func__);
+
+ x86_setup_fixed_mtrrs();
+}
+
+static void post_mp_init(void)
+{
+ /* Set Max Ratio */
+ set_max_turbo_freq();
+
+ /*
+ * TODO: Now that all APs have been relocated as well as the BSP let SMIs
+ * start flowing.
+ */
+}
+
+/*
+ * CPU initialization recipe
+ *
+ * Note that no microcode update is passed to the init function. CSE updates
+ * the microcode on all cores before releasing them from reset. That means that
+ * the BSP and all APs will come up with the same microcode revision.
+ */
+static const struct mp_ops mp_ops = {
+ .pre_mp_init = pre_mp_init,
+ .get_cpu_count = get_platform_thread_count,
+ //.get_smm_info = get_smm_info, /* TODO */
+ .get_smm_info = NULL,
+ //.pre_mp_smm_init = southcluster_smm_clear_state, /* TODO */
+ .pre_mp_smm_init = NULL,
+ //.relocation_handler = relocation_handler, /* TODO */
+ .relocation_handler = NULL,
+ .post_mp_init = post_mp_init,
+};
+
+
+void xeon_sp_init_cpus(struct device *dev)
+{
+ FUNC_ENTER();
+
+ /*
+ * This gets used in cpu device callback. Other than cpu 0,
+ * rest of the CPU devices do not have
+ * chip_info updated. Global chip_config is used as workaround
+ */
+ chip_config = dev->chip_info;
+
+ config_reset_cpl3_csrs();
+
+ /* calls src/cpu/x86/mp_init.c */
+ if (mp_init_with_smm(dev->link_list, &mp_ops) < 0)
+ printk(BIOS_ERR, "MP initialization failure.\n");
+
+ /* update numa domain for all cpu devices */
+ xeonsp_init_cpu_config();
+
+ FUNC_EXIT();
+}
diff --git a/src/soc/intel/xeon_sp/hob_display.c b/src/soc/intel/xeon_sp/hob_display.c
new file mode 100644
index 0000000..1508011
--- /dev/null
+++ b/src/soc/intel/xeon_sp/hob_display.c
@@ -0,0 +1,235 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2019 - 2020 Intel Corporation
+ * Copyright (C) 2019 - 2020 Facebook Inc
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <console/console.h>
+#include <fsp/util.h>
+#include <lib.h>
+#include <assert.h>
+#include <hob_iiouds.h>
+#include <hob_memmap.h>
+
+static const uint8_t fsp_hob_iio_uds_guid[16] = FSP_HOB_IIO_UNIVERSAL_DATA_GUID;
+static const uint8_t fsp_hob_memmap_guid[16] = FSP_SYSTEM_MEMORYMAP_HOB_GUID;
+
+struct guid_name_map {
+ const void *guid;
+ const char *name;
+};
+
+static const struct guid_name_map guid_names[] = {
+ { fsp_hob_iio_uds_guid, "FSP_HOB_IIO_UNIVERSAL_DATA_GUID" },
+ { fsp_hob_memmap_guid, "FSP_SYSTEM_MEMORYMAP_HOB_GUID" },
+};
+
+const char *soc_get_guid_name(const uint8_t *guid)
+{
+ size_t index;
+
+ /* Compare the GUID values in this module */
+ for (index = 0; index < ARRAY_SIZE(guid_names); index++)
+ if (fsp_guid_compare(guid, guid_names[index].guid))
+ return guid_names[index].name;
+
+ return NULL;
+}
+
+void soc_display_hob(const struct hob_header *hob)
+{
+ const struct hob_resource *res;
+
+ res = fsp_hob_header_to_resource(hob);
+ assert(res != NULL);
+ printk(BIOS_DEBUG, "\tResource type: 0x%x, attribute: 0x%x, addr: 0x%08llx, len: 0x%08llx\n",
+ res->type, res->attribute_type, res->addr, res->length);
+ printk(BIOS_DEBUG, "\tOwner GUID: ");
+ fsp_print_guid(res->owner_guid);
+ printk(BIOS_DEBUG, " (%s)\n", fsp_get_guid_name(res->owner_guid));
+
+ if (fsp_guid_compare(res->owner_guid, fsp_hob_iio_uds_guid) == 0)
+ soc_display_iio_universal_data_hob();
+ else if (fsp_guid_compare(res->owner_guid, fsp_hob_memmap_guid) == 0)
+ soc_display_memmap_hob();
+ else
+ hexdump(hob, hob->length);
+}
+
+void soc_display_memmap_hob(void)
+{
+ size_t hob_size = 0;
+ const struct SystemMemoryMapHob *hob =
+ fsp_find_extension_hob_by_guid(fsp_hob_memmap_guid, &hob_size);
+ assert(hob != NULL && hob_size != 0);
+
+ printk(BIOS_DEBUG, "===================== MEMORY MAP HOB DATA =====================\n");
+ printk(BIOS_DEBUG, "hob: %p, hob_size: 0x%lx, SystemMemoryMapHob size: 0x%lx, "
+ "MAX_SOCKET: %d, SAD_RULES: %d\n",
+ hob, hob_size, sizeof(struct SystemMemoryMapHob), MAX_SOCKET, SAD_RULES);
+ printk(BIOS_DEBUG, "\tlowMemBase: 0x%x, lowMemSize: 0x%x, highMemBase: 0x%x, "
+ "highMemSize: 0x%x\n",
+ hob->lowMemBase, hob->lowMemSize, hob->highMemBase, hob->highMemSize);
+ printk(BIOS_DEBUG, "\tasilLoMemBase: 0x%x, asilHiMemBase: 0x%x, asilLoMemSize: 0x%x, "
+ "asilHiMemSize: 0x%x\n",
+ hob->lowMemBase, hob->lowMemSize, hob->highMemBase, hob->highMemSize);
+ printk(BIOS_DEBUG, "\tmemSize: 0x%x, memFreq: 0x%x, memMode: 0x%x, volMemMode: 0x%x, "
+ "DimmType: 0x%x, DramType: 0x%x\n",
+ hob->memSize, hob->memFreq, hob->memMode, hob->volMemMode,
+ hob->DimmType, hob->DramType);
+ printk(BIOS_DEBUG, "\tNumChPerMC: 0x%x, numberEntries: 0x%x, maxIMC: 0x%x, maxCh: 0x%x\n",
+ hob->NumChPerMC, hob->numberEntries, hob->maxIMC, hob->maxCh);
+
+ printk(BIOS_DEBUG, "\tSystemMemoryMapElement Entries: %d\n", hob->numberEntries);
+ for (int e = 0; e < hob->numberEntries; ++e) {
+ const struct SystemMemoryMapElement *mem_element = &hob->Element[e];
+ printk(BIOS_DEBUG, "\t\tmemory_map %d BaseAddress: 0x%x, ElementSize: 0x%x, Type: 0x%x\n",
+ e, mem_element->BaseAddress,
+ mem_element->ElementSize, mem_element->Type);
+ }
+}
+
+void soc_display_iio_universal_data_hob(void)
+{
+ size_t hob_size = 0;
+ const IIO_UDS *hob = fsp_find_extension_hob_by_guid(fsp_hob_iio_uds_guid, &hob_size);
+
+ assert(hob != NULL && hob_size != 0);
+
+ printk(BIOS_DEBUG, "===================== IIO_UDS HOB DATA =====================\n");
+
+ printk(BIOS_DEBUG, "\t===================== SYSTEM STATUS =====================\n");
+ printk(BIOS_DEBUG, "\tcpuType: 0x%x\n", hob->SystemStatus.cpuType);
+ printk(BIOS_DEBUG, "\tcpuSubType: 0x%x\n", hob->SystemStatus.cpuSubType);
+ printk(BIOS_DEBUG, "\tSystemRasType: 0x%x\n", hob->SystemStatus.SystemRasType);
+ printk(BIOS_DEBUG, "\tnumCpus: 0x%x\n", hob->SystemStatus.numCpus);
+ for (int x = 0; x < MAX_SOCKET; ++x) {
+ printk(BIOS_DEBUG, "\tSocket %d FusedCores: 0x%x, ActiveCores: 0x%x, "
+ "MaxCoreToBusRatio: 0x%x, MinCoreToBusRatio: 0x%x\n",
+ x, hob->SystemStatus.FusedCores[x], hob->SystemStatus.ActiveCores[x],
+ hob->SystemStatus.MaxCoreToBusRatio[x],
+ hob->SystemStatus.MinCoreToBusRatio[x]);
+ }
+ printk(BIOS_DEBUG, "\tCurrentCoreToBusRatio: 0x%x\n",
+ hob->SystemStatus.CurrentCoreToBusRatio);
+ printk(BIOS_DEBUG, "\tIntelSpeedSelectCapable: 0x%x\n",
+ hob->SystemStatus.IntelSpeedSelectCapable);
+ printk(BIOS_DEBUG, "\tIssConfigTdpLevelInfo: 0x%x\n",
+ hob->SystemStatus.IssConfigTdpLevelInfo);
+ for (int x = 0; x < TDP_MAX_LEVEL; ++x) {
+ printk(BIOS_DEBUG, "\t\tTDL Level %d IssConfigTdpTdpInfo: 0x%x, "
+ "IssConfigTdpPowerInfo: 0x%x, IssConfigTdpCoreCount: 0x%x\n",
+ x, hob->SystemStatus.IssConfigTdpTdpInfo[x],
+ hob->SystemStatus.IssConfigTdpPowerInfo[x],
+ hob->SystemStatus.IssConfigTdpCoreCount[x]);
+ }
+ printk(BIOS_DEBUG, "\tsocketPresentBitMap: 0x%x\n",
+ hob->SystemStatus.socketPresentBitMap);
+ printk(BIOS_DEBUG, "\ttolmLimit: 0x%x\n", hob->SystemStatus.tolmLimit);
+ printk(BIOS_DEBUG, "\ttohmLimit: 0x%x\n", hob->SystemStatus.tohmLimit);
+ printk(BIOS_DEBUG, "\tmmCfgBase: 0x%x\n", hob->SystemStatus.mmCfgBase);
+ printk(BIOS_DEBUG, "\tnumChPerMC: 0x%x\n", hob->SystemStatus.numChPerMC);
+ printk(BIOS_DEBUG, "\tmaxCh: 0x%x\n", hob->SystemStatus.maxCh);
+ printk(BIOS_DEBUG, "\tmaxIMC: 0x%x\n", hob->SystemStatus.maxIMC);
+
+ printk(BIOS_DEBUG, "\t===================== PLATFORM DATA =====================\n");
+ printk(BIOS_DEBUG, "\tPlatGlobalIoBase: 0x%x\n", hob->PlatformData.PlatGlobalIoBase);
+ printk(BIOS_DEBUG, "\tPlatGlobalIoLimit: 0x%x\n", hob->PlatformData.PlatGlobalIoLimit);
+ printk(BIOS_DEBUG, "\tPlatGlobalMmiolBase: 0x%x\n",
+ hob->PlatformData.PlatGlobalMmiolBase);
+ printk(BIOS_DEBUG, "\tPlatGlobalMmiolLimit: 0x%x\n",
+ hob->PlatformData.PlatGlobalMmiolLimit);
+ printk(BIOS_DEBUG, "\tPlatGlobalMmiohBase: 0x%llx\n",
+ hob->PlatformData.PlatGlobalMmiohBase);
+ printk(BIOS_DEBUG, "\tPlatGlobalMmiohLimit: 0x%llx\n",
+ hob->PlatformData.PlatGlobalMmiohLimit);
+ printk(BIOS_DEBUG, "\tMemTsegSize: 0x%x\n", hob->PlatformData.MemTsegSize);
+ printk(BIOS_DEBUG, "\tMemIedSize: 0x%x\n", hob->PlatformData.MemIedSize);
+ printk(BIOS_DEBUG, "\tPciExpressBase: 0x%llx\n", hob->PlatformData.PciExpressBase);
+ printk(BIOS_DEBUG, "\tPciExpressSize: 0x%x\n", hob->PlatformData.PciExpressSize);
+ printk(BIOS_DEBUG, "\tMemTolm: 0x%x\n", hob->PlatformData.MemTolm);
+ printk(BIOS_DEBUG, "\tnumofIIO: 0x%x\n", hob->PlatformData.numofIIO);
+ printk(BIOS_DEBUG, "\tMaxBusNumber: 0x%x\n", hob->PlatformData.MaxBusNumber);
+ printk(BIOS_DEBUG, "\tIoGranularity: 0x%x\n", hob->PlatformData.IoGranularity);
+ printk(BIOS_DEBUG, "\tMmiolGranularity: 0x%x\n", hob->PlatformData.MmiolGranularity);
+ printk(BIOS_DEBUG, "\tMmiohGranularity: hi: 0x%x, lo:0x%x\n",
+ hob->PlatformData.MmiohGranularity.hi, hob->PlatformData.MmiohGranularity.lo);
+
+ for (int s = 0; s < hob->PlatformData.numofIIO; ++s) {
+ printk(BIOS_DEBUG, "\t============ Socket %d Info ================\n", s);
+ printk(BIOS_DEBUG, "\tSocketID: 0x%x\n",
+ hob->PlatformData.IIO_resource[s].SocketID);
+ printk(BIOS_DEBUG, "\tBusBase: 0x%x\n",
+ hob->PlatformData.IIO_resource[s].BusBase);
+ printk(BIOS_DEBUG, "\tBusLimit: 0x%x\n",
+ hob->PlatformData.IIO_resource[s].BusLimit);
+ printk(BIOS_DEBUG, "\tPciResourceIoBase: 0x%x\n",
+ hob->PlatformData.IIO_resource[s].PciResourceIoBase);
+ printk(BIOS_DEBUG, "\tPciResourceIoLimit: 0x%x\n",
+ hob->PlatformData.IIO_resource[s].PciResourceIoLimit);
+ printk(BIOS_DEBUG, "\tIoApicBase: 0x%x\n",
+ hob->PlatformData.IIO_resource[s].IoApicBase);
+ printk(BIOS_DEBUG, "\tIoApicLimit: 0x%x\n",
+ hob->PlatformData.IIO_resource[s].IoApicLimit);
+ printk(BIOS_DEBUG, "\tPciResourceMem32Base: 0x%x\n",
+ hob->PlatformData.IIO_resource[s].PciResourceMem32Base);
+ printk(BIOS_DEBUG, "\tPciResourceMem32Limit: 0x%x\n",
+ hob->PlatformData.IIO_resource[s].PciResourceMem32Limit);
+ printk(BIOS_DEBUG, "\tPciResourceMem64Base: 0x%llx\n",
+ hob->PlatformData.IIO_resource[s].PciResourceMem64Base);
+ printk(BIOS_DEBUG, "\tPciResourceMem64Limit: 0x%llx\n",
+ hob->PlatformData.IIO_resource[s].PciResourceMem64Limit);
+
+ printk(BIOS_DEBUG, "\t============ Stack Info ================\n");
+ for (int x = 0; x < MAX_IIO_STACK; ++x) {
+ const STACK_RES *ri = &hob->PlatformData.IIO_resource[s].StackRes[x];
+ printk(BIOS_DEBUG, "\t\t========== Stack %d ===============\n", x);
+ printk(BIOS_DEBUG, "\t\tBusBase: 0x%x\n", ri->BusBase);
+ printk(BIOS_DEBUG, "\t\tBusLimit: 0x%x\n", ri->BusLimit);
+ printk(BIOS_DEBUG, "\t\tPciResourceIoBase: 0x%x\n",
+ ri->PciResourceIoBase);
+ printk(BIOS_DEBUG, "\t\tPciResourceIoLimit: 0x%x\n",
+ ri->PciResourceIoLimit);
+ printk(BIOS_DEBUG, "\t\tIoApicBase: 0x%x\n", ri->IoApicBase);
+ printk(BIOS_DEBUG, "\t\tIoApicLimit: 0x%x\n", ri->IoApicLimit);
+ printk(BIOS_DEBUG, "\t\tPciResourceMem32Base: 0x%x\n",
+ ri->PciResourceMem32Base);
+ printk(BIOS_DEBUG, "\t\tPciResourceMem32Limit: 0x%x\n",
+ ri->PciResourceMem32Limit);
+ printk(BIOS_DEBUG, "\t\tPciResourceMem64Base: 0x%llx\n",
+ ri->PciResourceMem64Base);
+ printk(BIOS_DEBUG, "\t\tPciResourceMem64Limit: 0x%llx\n",
+ ri->PciResourceMem64Limit);
+ printk(BIOS_DEBUG, "\t\tVtdBarAddress: 0x%x\n", ri->VtdBarAddress);
+ }
+
+ printk(BIOS_DEBUG, "\t============ PcieInfo ================\n");
+ IIO_RESOURCE_INSTANCE iio_resource =
+ hob->PlatformData.IIO_resource[s];
+ for (int p = 0; p < NUMBER_PORTS_PER_SOCKET; ++p) {
+ printk(BIOS_DEBUG, "\t\tPort: %d, Device: 0x%x, Function: 0x%x\n",
+ p, iio_resource.PcieInfo.PortInfo[p].Device,
+ iio_resource.PcieInfo.PortInfo[p].Function);
+ }
+ }
+
+ printk(BIOS_DEBUG, "\t============ Bus Bases ===============\n");
+ for (int socket = 0; socket < MAX_SOCKET; ++socket) {
+ for (int stack = 0; stack < MAX_IIO_STACK; ++stack) {
+ printk(BIOS_DEBUG, "socket: %d, stack: %d, busno: 0x%x\n",
+ socket, stack,
+ hob->PlatformData.CpuQpiInfo[socket].StackBus[stack]);
+ }
+ }
+}
diff --git a/src/soc/intel/xeon_sp/include/soc/acpi.h b/src/soc/intel/xeon_sp/include/soc/acpi.h
new file mode 100644
index 0000000..641a3c5
--- /dev/null
+++ b/src/soc/intel/xeon_sp/include/soc/acpi.h
@@ -0,0 +1,37 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2019 - 2020 Intel Corporation.
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+
+#ifndef _SOC_ACPI_H_
+#define _SOC_ACPI_H_
+
+#include <arch/acpi.h>
+#include <soc/nvs.h>
+
+#define MEM_BLK_COUNT 0x140
+typedef struct {
+ uint8_t buf[32];
+} MEM_BLK;
+
+void acpi_create_serialio_ssdt(acpi_header_t *ssdt);
+unsigned long acpi_madt_irq_overrides(unsigned long current);
+void acpi_init_gnvs(global_nvs_t *gnvs);
+unsigned long northbridge_write_acpi_tables(struct device *device,
+ unsigned long current, struct acpi_rsdp *rsdp);
+void uncore_inject_dsdt(void);
+void motherboard_fill_fadt(acpi_fadt_t *fadt);
+
+#endif /* _SOC_ACPI_H_ */
diff --git a/src/soc/intel/xeon_sp/include/soc/cpu.h b/src/soc/intel/xeon_sp/include/soc/cpu.h
new file mode 100644
index 0000000..82b893c
--- /dev/null
+++ b/src/soc/intel/xeon_sp/include/soc/cpu.h
@@ -0,0 +1,33 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2019 - 2020 Intel Corporation.
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _SOC_CPU_H_
+#define _SOC_CPU_H_
+
+#include <device/device.h>
+
+/* SKXSP CPUID */
+#define CPUID_SKYLAKE_SP_A0_A1 0x506f0
+#define CPUID_SKYLAKE_SP_B0 0x506f1
+#define CPUID_SKYLAKE_SP_4 0x50654
+
+/* CPU bus clock is fixed at 100MHz */
+#define CPU_BCLK 100
+
+int get_cpu_count(void);
+void xeon_sp_init_cpus(struct device *dev);
+
+#endif
diff --git a/src/soc/intel/xeon_sp/include/soc/gpio_soc_defs.h b/src/soc/intel/xeon_sp/include/soc/gpio_soc_defs.h
new file mode 100644
index 0000000..8cb472d
--- /dev/null
+++ b/src/soc/intel/xeon_sp/include/soc/gpio_soc_defs.h
@@ -0,0 +1,299 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2019 - 2020 Intel Corporation.
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _GPIO_SOC_DEFS_H_
+#define _GPIO_SOC_DEFS_H_
+
+///
+/// Skylake-SP chipset GPIO Groups
+///
+#define GPIO_SKL_H_GROUP_GPP_A 0x0100
+#define GPIO_SKL_H_GROUP_GPP_B 0x0101
+#define GPIO_SKL_H_GROUP_GPP_C 0x0102
+#define GPIO_SKL_H_GROUP_GPP_D 0x0103
+#define GPIO_SKL_H_GROUP_GPP_E 0x0104
+#define GPIO_SKL_H_GROUP_GPP_F 0x0105
+#define GPIO_SKL_H_GROUP_GPP_G 0x0106
+#define GPIO_SKL_H_GROUP_GPP_H 0x0107
+#define GPIO_SKL_H_GROUP_GPP_I 0x0108
+#define GPIO_SKL_H_GROUP_GPP_J 0x0109
+#define GPIO_SKL_H_GROUP_GPP_K 0x010A
+#define GPIO_SKL_H_GROUP_GPP_L 0x010B
+#define GPIO_SKL_H_GROUP_GPD 0x010C
+
+///
+/// SKL H GPIO pins
+///
+#define GPIO_SKL_H_GPP_A0 0x01000000
+#define GPIO_SKL_H_GPP_A1 0x01000001
+#define GPIO_SKL_H_GPP_A2 0x01000002
+#define GPIO_SKL_H_GPP_A3 0x01000003
+#define GPIO_SKL_H_GPP_A4 0x01000004
+#define GPIO_SKL_H_GPP_A5 0x01000005
+#define GPIO_SKL_H_GPP_A6 0x01000006
+#define GPIO_SKL_H_GPP_A7 0x01000007
+#define GPIO_SKL_H_GPP_A8 0x01000008
+#define GPIO_SKL_H_GPP_A9 0x01000009
+#define GPIO_SKL_H_GPP_A10 0x0100000A
+#define GPIO_SKL_H_GPP_A11 0x0100000B
+#define GPIO_SKL_H_GPP_A12 0x0100000C
+#define GPIO_SKL_H_GPP_A13 0x0100000D
+#define GPIO_SKL_H_GPP_A14 0x0100000E
+#define GPIO_SKL_H_GPP_A15 0x0100000F
+#define GPIO_SKL_H_GPP_A16 0x01000010
+#define GPIO_SKL_H_GPP_A17 0x01000011
+#define GPIO_SKL_H_GPP_A18 0x01000012
+#define GPIO_SKL_H_GPP_A19 0x01000013
+#define GPIO_SKL_H_GPP_A20 0x01000014
+#define GPIO_SKL_H_GPP_A21 0x01000015
+#define GPIO_SKL_H_GPP_A22 0x01000016
+#define GPIO_SKL_H_GPP_A23 0x01000017
+#define GPIO_SKL_H_GPP_B0 0x01010000
+#define GPIO_SKL_H_GPP_B1 0x01010001
+#define GPIO_SKL_H_GPP_B2 0x01010002
+#define GPIO_SKL_H_GPP_B3 0x01010003
+#define GPIO_SKL_H_GPP_B4 0x01010004
+#define GPIO_SKL_H_GPP_B5 0x01010005
+#define GPIO_SKL_H_GPP_B6 0x01010006
+#define GPIO_SKL_H_GPP_B7 0x01010007
+#define GPIO_SKL_H_GPP_B8 0x01010008
+#define GPIO_SKL_H_GPP_B9 0x01010009
+#define GPIO_SKL_H_GPP_B10 0x0101000A
+#define GPIO_SKL_H_GPP_B11 0x0101000B
+#define GPIO_SKL_H_GPP_B12 0x0101000C
+#define GPIO_SKL_H_GPP_B13 0x0101000D
+#define GPIO_SKL_H_GPP_B14 0x0101000E
+#define GPIO_SKL_H_GPP_B15 0x0101000F
+#define GPIO_SKL_H_GPP_B16 0x01010010
+#define GPIO_SKL_H_GPP_B17 0x01010011
+#define GPIO_SKL_H_GPP_B18 0x01010012
+#define GPIO_SKL_H_GPP_B19 0x01010013
+#define GPIO_SKL_H_GPP_B20 0x01010014
+#define GPIO_SKL_H_GPP_B21 0x01010015
+#define GPIO_SKL_H_GPP_B22 0x01010016
+#define GPIO_SKL_H_GPP_B23 0x01010017
+#define GPIO_SKL_H_GPP_C0 0x01020000
+#define GPIO_SKL_H_GPP_C1 0x01020001
+#define GPIO_SKL_H_GPP_C2 0x01020002
+#define GPIO_SKL_H_GPP_C3 0x01020003
+#define GPIO_SKL_H_GPP_C4 0x01020004
+#define GPIO_SKL_H_GPP_C5 0x01020005
+#define GPIO_SKL_H_GPP_C6 0x01020006
+#define GPIO_SKL_H_GPP_C7 0x01020007
+#define GPIO_SKL_H_GPP_C8 0x01020008
+#define GPIO_SKL_H_GPP_C9 0x01020009
+#define GPIO_SKL_H_GPP_C10 0x0102000A
+#define GPIO_SKL_H_GPP_C11 0x0102000B
+#define GPIO_SKL_H_GPP_C12 0x0102000C
+#define GPIO_SKL_H_GPP_C13 0x0102000D
+#define GPIO_SKL_H_GPP_C14 0x0102000E
+#define GPIO_SKL_H_GPP_C15 0x0102000F
+#define GPIO_SKL_H_GPP_C16 0x01020010
+#define GPIO_SKL_H_GPP_C17 0x01020011
+#define GPIO_SKL_H_GPP_C18 0x01020012
+#define GPIO_SKL_H_GPP_C19 0x01020013
+#define GPIO_SKL_H_GPP_C20 0x01020014
+#define GPIO_SKL_H_GPP_C21 0x01020015
+#define GPIO_SKL_H_GPP_C22 0x01020016
+#define GPIO_SKL_H_GPP_C23 0x01020017
+#define GPIO_SKL_H_GPP_D0 0x01030000
+#define GPIO_SKL_H_GPP_D1 0x01030001
+#define GPIO_SKL_H_GPP_D2 0x01030002
+#define GPIO_SKL_H_GPP_D3 0x01030003
+#define GPIO_SKL_H_GPP_D4 0x01030004
+#define GPIO_SKL_H_GPP_D5 0x01030005
+#define GPIO_SKL_H_GPP_D6 0x01030006
+#define GPIO_SKL_H_GPP_D7 0x01030007
+#define GPIO_SKL_H_GPP_D8 0x01030008
+#define GPIO_SKL_H_GPP_D9 0x01030009
+#define GPIO_SKL_H_GPP_D10 0x0103000A
+#define GPIO_SKL_H_GPP_D11 0x0103000B
+#define GPIO_SKL_H_GPP_D12 0x0103000C
+#define GPIO_SKL_H_GPP_D13 0x0103000D
+#define GPIO_SKL_H_GPP_D14 0x0103000E
+#define GPIO_SKL_H_GPP_D15 0x0103000F
+#define GPIO_SKL_H_GPP_D16 0x01030010
+#define GPIO_SKL_H_GPP_D17 0x01030011
+#define GPIO_SKL_H_GPP_D18 0x01030012
+#define GPIO_SKL_H_GPP_D19 0x01030013
+#define GPIO_SKL_H_GPP_D20 0x01030014
+#define GPIO_SKL_H_GPP_D21 0x01030015
+#define GPIO_SKL_H_GPP_D22 0x01030016
+#define GPIO_SKL_H_GPP_D23 0x01030017
+#define GPIO_SKL_H_GPP_E0 0x01040000
+#define GPIO_SKL_H_GPP_E1 0x01040001
+#define GPIO_SKL_H_GPP_E2 0x01040002
+#define GPIO_SKL_H_GPP_E3 0x01040003
+#define GPIO_SKL_H_GPP_E4 0x01040004
+#define GPIO_SKL_H_GPP_E5 0x01040005
+#define GPIO_SKL_H_GPP_E6 0x01040006
+#define GPIO_SKL_H_GPP_E7 0x01040007
+#define GPIO_SKL_H_GPP_E8 0x01040008
+#define GPIO_SKL_H_GPP_E9 0x01040009
+#define GPIO_SKL_H_GPP_E10 0x0104000A
+#define GPIO_SKL_H_GPP_E11 0x0104000B
+#define GPIO_SKL_H_GPP_E12 0x0104000C
+#define GPIO_SKL_H_GPP_F0 0x01050000
+#define GPIO_SKL_H_GPP_F1 0x01050001
+#define GPIO_SKL_H_GPP_F2 0x01050002
+#define GPIO_SKL_H_GPP_F3 0x01050003
+#define GPIO_SKL_H_GPP_F4 0x01050004
+#define GPIO_SKL_H_GPP_F5 0x01050005
+#define GPIO_SKL_H_GPP_F6 0x01050006
+#define GPIO_SKL_H_GPP_F7 0x01050007
+#define GPIO_SKL_H_GPP_F8 0x01050008
+#define GPIO_SKL_H_GPP_F9 0x01050009
+#define GPIO_SKL_H_GPP_F10 0x0105000A
+#define GPIO_SKL_H_GPP_F11 0x0105000B
+#define GPIO_SKL_H_GPP_F12 0x0105000C
+#define GPIO_SKL_H_GPP_F13 0x0105000D
+#define GPIO_SKL_H_GPP_F14 0x0105000E
+#define GPIO_SKL_H_GPP_F15 0x0105000F
+#define GPIO_SKL_H_GPP_F16 0x01050010
+#define GPIO_SKL_H_GPP_F17 0x01050011
+#define GPIO_SKL_H_GPP_F18 0x01050012
+#define GPIO_SKL_H_GPP_F19 0x01050013
+#define GPIO_SKL_H_GPP_F20 0x01050014
+#define GPIO_SKL_H_GPP_F21 0x01050015
+#define GPIO_SKL_H_GPP_F22 0x01050016
+#define GPIO_SKL_H_GPP_F23 0x01050017
+#define GPIO_SKL_H_GPP_G0 0x01060000
+#define GPIO_SKL_H_GPP_G1 0x01060001
+#define GPIO_SKL_H_GPP_G2 0x01060002
+#define GPIO_SKL_H_GPP_G3 0x01060003
+#define GPIO_SKL_H_GPP_G4 0x01060004
+#define GPIO_SKL_H_GPP_G5 0x01060005
+#define GPIO_SKL_H_GPP_G6 0x01060006
+#define GPIO_SKL_H_GPP_G7 0x01060007
+#define GPIO_SKL_H_GPP_G8 0x01060008
+#define GPIO_SKL_H_GPP_G9 0x01060009
+#define GPIO_SKL_H_GPP_G10 0x0106000A
+#define GPIO_SKL_H_GPP_G11 0x0106000B
+#define GPIO_SKL_H_GPP_G12 0x0106000C
+#define GPIO_SKL_H_GPP_G13 0x0106000D
+#define GPIO_SKL_H_GPP_G14 0x0106000E
+#define GPIO_SKL_H_GPP_G15 0x0106000F
+#define GPIO_SKL_H_GPP_G16 0x01060010
+#define GPIO_SKL_H_GPP_G17 0x01060011
+#define GPIO_SKL_H_GPP_G18 0x01060012
+#define GPIO_SKL_H_GPP_G19 0x01060013
+#define GPIO_SKL_H_GPP_G20 0x01060014
+#define GPIO_SKL_H_GPP_G21 0x01060015
+#define GPIO_SKL_H_GPP_G22 0x01060016
+#define GPIO_SKL_H_GPP_G23 0x01060017
+#define GPIO_SKL_H_GPP_H0 0x01070000
+#define GPIO_SKL_H_GPP_H1 0x01070001
+#define GPIO_SKL_H_GPP_H2 0x01070002
+#define GPIO_SKL_H_GPP_H3 0x01070003
+#define GPIO_SKL_H_GPP_H4 0x01070004
+#define GPIO_SKL_H_GPP_H5 0x01070005
+#define GPIO_SKL_H_GPP_H6 0x01070006
+#define GPIO_SKL_H_GPP_H7 0x01070007
+#define GPIO_SKL_H_GPP_H8 0x01070008
+#define GPIO_SKL_H_GPP_H9 0x01070009
+#define GPIO_SKL_H_GPP_H10 0x0107000A
+#define GPIO_SKL_H_GPP_H11 0x0107000B
+#define GPIO_SKL_H_GPP_H12 0x0107000C
+#define GPIO_SKL_H_GPP_H13 0x0107000D
+#define GPIO_SKL_H_GPP_H14 0x0107000E
+#define GPIO_SKL_H_GPP_H15 0x0107000F
+#define GPIO_SKL_H_GPP_H16 0x01070010
+#define GPIO_SKL_H_GPP_H17 0x01070011
+#define GPIO_SKL_H_GPP_H18 0x01070012
+#define GPIO_SKL_H_GPP_H19 0x01070013
+#define GPIO_SKL_H_GPP_H20 0x01070014
+#define GPIO_SKL_H_GPP_H21 0x01070015
+#define GPIO_SKL_H_GPP_H22 0x01070016
+#define GPIO_SKL_H_GPP_H23 0x01070017
+#define GPIO_SKL_H_GPP_I0 0x01080000
+#define GPIO_SKL_H_GPP_I1 0x01080001
+#define GPIO_SKL_H_GPP_I2 0x01080002
+#define GPIO_SKL_H_GPP_I3 0x01080003
+#define GPIO_SKL_H_GPP_I4 0x01080004
+#define GPIO_SKL_H_GPP_I5 0x01080005
+#define GPIO_SKL_H_GPP_I6 0x01080006
+#define GPIO_SKL_H_GPP_I7 0x01080007
+#define GPIO_SKL_H_GPP_I8 0x01080008
+#define GPIO_SKL_H_GPP_I9 0x01080009
+#define GPIO_SKL_H_GPP_I10 0x0108000A
+
+#define GPIO_SKL_H_GPP_J0 0x01090000
+#define GPIO_SKL_H_GPP_J1 0x01090001
+#define GPIO_SKL_H_GPP_J2 0x01090002
+#define GPIO_SKL_H_GPP_J3 0x01090003
+#define GPIO_SKL_H_GPP_J4 0x01090004
+#define GPIO_SKL_H_GPP_J5 0x01090005
+#define GPIO_SKL_H_GPP_J6 0x01090006
+#define GPIO_SKL_H_GPP_J7 0x01090007
+#define GPIO_SKL_H_GPP_J8 0x01090008
+#define GPIO_SKL_H_GPP_J9 0x01090009
+#define GPIO_SKL_H_GPP_J10 0x0109000A
+#define GPIO_SKL_H_GPP_J11 0x0109000B
+#define GPIO_SKL_H_GPP_J12 0x0109000C
+#define GPIO_SKL_H_GPP_J13 0x0109000D
+#define GPIO_SKL_H_GPP_J14 0x0109000E
+#define GPIO_SKL_H_GPP_J15 0x0109000F
+#define GPIO_SKL_H_GPP_J16 0x01090010
+#define GPIO_SKL_H_GPP_J17 0x01090011
+#define GPIO_SKL_H_GPP_J18 0x01090012
+#define GPIO_SKL_H_GPP_J19 0x01090013
+#define GPIO_SKL_H_GPP_J20 0x01090014
+#define GPIO_SKL_H_GPP_J21 0x01090015
+#define GPIO_SKL_H_GPP_J22 0x01090016
+#define GPIO_SKL_H_GPP_J23 0x01090017
+#define GPIO_SKL_H_GPP_K0 0x010A0000
+#define GPIO_SKL_H_GPP_K1 0x010A0001
+#define GPIO_SKL_H_GPP_K2 0x010A0002
+#define GPIO_SKL_H_GPP_K3 0x010A0003
+#define GPIO_SKL_H_GPP_K4 0x010A0004
+#define GPIO_SKL_H_GPP_K5 0x010A0005
+#define GPIO_SKL_H_GPP_K6 0x010A0006
+#define GPIO_SKL_H_GPP_K7 0x010A0007
+#define GPIO_SKL_H_GPP_K8 0x010A0008
+#define GPIO_SKL_H_GPP_K9 0x010A0009
+#define GPIO_SKL_H_GPP_K10 0x010A000A
+#define GPIO_SKL_H_GPP_L2 0x010B0002
+#define GPIO_SKL_H_GPP_L3 0x010B0003
+#define GPIO_SKL_H_GPP_L4 0x010B0004
+#define GPIO_SKL_H_GPP_L5 0x010B0005
+#define GPIO_SKL_H_GPP_L6 0x010B0006
+#define GPIO_SKL_H_GPP_L7 0x010B0007
+#define GPIO_SKL_H_GPP_L8 0x010B0008
+#define GPIO_SKL_H_GPP_L9 0x010B0009
+#define GPIO_SKL_H_GPP_L10 0x010B000A
+#define GPIO_SKL_H_GPP_L11 0x010B000B
+#define GPIO_SKL_H_GPP_L12 0x010B000C
+#define GPIO_SKL_H_GPP_L13 0x010B000D
+#define GPIO_SKL_H_GPP_L14 0x010B000E
+#define GPIO_SKL_H_GPP_L15 0x010B000F
+#define GPIO_SKL_H_GPP_L16 0x010B0010
+#define GPIO_SKL_H_GPP_L17 0x010B0011
+#define GPIO_SKL_H_GPP_L18 0x010B0012
+#define GPIO_SKL_H_GPP_L19 0x010B0013
+#define GPIO_SKL_H_GPD0 0x010C0000
+#define GPIO_SKL_H_GPD1 0x010C0001
+#define GPIO_SKL_H_GPD2 0x010C0002
+#define GPIO_SKL_H_GPD3 0x010C0003
+#define GPIO_SKL_H_GPD4 0x010C0004
+#define GPIO_SKL_H_GPD5 0x010C0005
+#define GPIO_SKL_H_GPD6 0x010C0006
+#define GPIO_SKL_H_GPD7 0x010C0007
+#define GPIO_SKL_H_GPD8 0x010C0008
+#define GPIO_SKL_H_GPD9 0x010C0009
+#define GPIO_SKL_H_GPD10 0x010C000A
+#define GPIO_SKL_H_GPD11 0x010C000B
+
+#endif
diff --git a/src/soc/intel/xeon_sp/include/soc/iomap.h b/src/soc/intel/xeon_sp/include/soc/iomap.h
new file mode 100644
index 0000000..7c825a4
--- /dev/null
+++ b/src/soc/intel/xeon_sp/include/soc/iomap.h
@@ -0,0 +1,47 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2019 - 2020 Intel Corporation.
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+
+#ifndef _SOC_IOMAP_H_
+#define _SOC_IOMAP_H_
+
+#define MAP_ENTRY(reg_, is_64_, is_limit_, mask_bits_, desc_) \
+ { \
+ .reg = reg_, .is_64_bit = is_64_, .is_limit = is_limit_, \
+ .mask_bits = mask_bits_, .description = desc_, \
+ }
+
+#define MAP_ENTRY_BASE_64(reg_, desc_) MAP_ENTRY(reg_, 1, 0, 0, desc_)
+#define MAP_ENTRY_LIMIT_64(reg_, mask_bits_, desc_) MAP_ENTRY(reg_, 1, 1, mask_bits_, desc_)
+#define MAP_ENTRY_BASE_32(reg_, desc_) MAP_ENTRY(reg_, 0, 0, 0, desc_)
+#define MAP_ENTRY_LIMIT_32(reg_, mask_bits_, desc_) MAP_ENTRY(reg_, 0, 1, mask_bits_, desc_)
+
+// SPI BAR0 MMIO base address
+#define SPI_BASE_ADDRESS 0xfe010000
+#define SPI_BASE_SIZE 0x1000
+
+#define ACPI_BASE_ADDRESS 0x500
+
+/* Video RAM */
+#define VGA_BASE_ADDRESS 0xa0000
+#define VGA_BASE_SIZE 0x20000
+
+/* High Performance Event Timer */
+#define HPET_BASE_ADDRESS 0xfed00000
+
+#define P2SB_BAR CONFIG_PCR_BASE_ADDRESS
+
+#endif /* _SOC_IOMAP_H_ */
diff --git a/src/soc/intel/xeon_sp/include/soc/irq.h b/src/soc/intel/xeon_sp/include/soc/irq.h
new file mode 100644
index 0000000..06942ae
--- /dev/null
+++ b/src/soc/intel/xeon_sp/include/soc/irq.h
@@ -0,0 +1,23 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2019 - 2020 Intel Corporation.
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _SOC_IRQ_H_
+#define _SOC_IRQ_H_
+
+#define PCH_IRQ10 10
+#define PCH_IRQ11 11
+
+#endif /* _SOC_IRQ_H_ */
diff --git a/src/soc/intel/xeon_sp/include/soc/msr.h b/src/soc/intel/xeon_sp/include/soc/msr.h
new file mode 100644
index 0000000..6004490
--- /dev/null
+++ b/src/soc/intel/xeon_sp/include/soc/msr.h
@@ -0,0 +1,113 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2019 - 2020 Intel Corporation.
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _SOC_MSR_H_
+#define _SOC_MSR_H_
+
+#include <intelblocks/msr.h>
+
+#define IA32_MCG_CAP 0x179
+#define IA32_MCG_CAP_COUNT_MASK 0xff
+#define IA32_MCG_CAP_CTL_P_BIT 8
+#define IA32_MCG_CAP_CTL_P_MASK (1 << IA32_MCG_CAP_CTL_P_BIT)
+
+#define IA32_MCG_CTL 0x17b
+
+/* IA32_MISC_ENABLE bits */
+#define FAST_STRINGS_ENABLE_BIT (1 << 0)
+#define SPEED_STEP_ENABLE_BIT (1 << 16)
+#define MONIOR_ENABLE_BIT (1 << 18)
+
+#define MSR_IA32_ENERGY_PERF_BIAS 0x1b0
+
+/* MSR_PKG_CST_CONFIG_CONTROL bits */
+#define MSR_PKG_CST_CONFIG_CONTROL 0xe2
+#define PKG_CSTATE_LIMIT_SHIFT 0 /* 0:3 */
+/* No package C-state limit. All C-States supported by the processor are available. */
+#define PKG_CSTATE_LIMIT_MASK (0xf << PKG_CSTATE_LIMIT_SHIFT)
+#define PKG_CSTATE_NO_LIMIT (0x7 << PKG_CSTATE_LIMIT_SHIFT)
+#define IO_MWAIT_REDIRECTION_SHIFT 10
+#define IO_MWAIT_REDIRECTION_ENABLE (1 << IO_MWAIT_REDIRECTION_SHIFT)
+#define CFG_LOCK_SHIFT 15
+#define CFG_LOCK_ENABLE (1 << CFG_LOCK_SHIFT)
+
+/* MSR_PMG_IO_CAPTURE_BASE bits */
+#define MSR_PMG_IO_CAPTURE_BASE 0xe4
+#define LVL_2_BASE_ADDRESS_SHIFT 0 /* 15:0 bits */
+#define LVL_2_BASE_ADDRESS (0x0514 << LVL_2_BASE_ADDRESS_SHIFT)
+#define CST_RANGE_SHIFT 16 /* 18:16 bits */
+#define CST_RANGE_MAX_C6 (0x1 << CST_RANGE_SHIFT)
+
+/* MSR_POWER_CTL bits */
+#define MSR_POWER_CTL 0x1fc
+#define BIDIR_PROCHOT_ENABLE_SHIFT 0
+#define BIDIR_PROCHOT_ENABLE (1 << BIDIR_PROCHOT_ENABLE_SHIFT)
+#define FAST_BRK_SNP_ENABLE_SHIFT 3
+#define FAST_BRK_SNP_ENABLE (1 << FAST_BRK_SNP_ENABLE_SHIFT)
+#define FAST_BRK_INT_ENABLE_SHIFT 4
+#define FAST_BRK_INT_ENABLE (1 << FAST_BRK_INT_ENABLE_SHIFT)
+#define PHOLD_CST_PREVENTION_INIT_SHIFT 6
+#define PHOLD_CST_PREVENTION_INIT_VALUE (1 << PHOLD_CST_PREVENTION_INIT_SHIFT)
+#define ENERGY_PERF_BIAS_ACCESS_ENABLE_SHIFT 18
+#define ENERGY_PERF_BIAS_ACCESS_ENABLE (1 << ENERGY_PERF_BIAS_ACCESS_ENABLE_SHIFT)
+#define PROCHOT_OUTPUT_DISABLE_SHIFT 21
+#define PROCHOT_OUTPUT_DISABLE (1 << PROCHOT_OUTPUT_DISABLE_SHIFT)
+#define PWR_PERF_TUNING_DYN_SWITCHING_SHIFT 24
+#define PWR_PERF_TUNING_DYN_SWITCHING_ENABLE (1 << PWR_PERF_TUNING_DYN_SWITCHING_SHIFT)
+#define PROCHOT_LOCK_SHIFT 27
+#define PROCHOT_LOCK_ENABLE (1 << PROCHOT_LOCK_SHIFT)
+#define LTR_IIO_DISABLE_SHIFT 29
+#define LTR_IIO_DISABLE (1 << LTR_IIO_DISABLE_SHIFT)
+
+/* MSR_IA32_PERF_CTRL (0x199) bits */
+#define MSR_IA32_PERF_CTRL 0x199
+#define PSTATE_REQ_SHIFT 8 /* 8:14 bits */
+#define PSTATE_REQ_MASK (0x7f << PSTATE_REQ_SHIFT)
+#define PSTATE_REQ_RATIO (0xa << PSTATE_REQ_SHIFT)
+
+/* MSR_MISC_PWR_MGMT bits */
+#define MSR_MISC_PWR_MGMT 0x1aa
+#define HWP_ENUM_SHIFT 6
+#define HWP_ENUM_ENABLE (1 << HWP_ENUM_SHIFT)
+#define HWP_EPP_SHIFT 12
+#define HWP_EPP_ENUM_ENABLE (1 << HWP_EPP_SHIFT)
+#define LOCK_MISC_PWR_MGMT_MSR_SHIFT 13
+#define LOCK_MISC_PWR_MGMT_MSR (1 << LOCK_MISC_PWR_MGMT_MSR_SHIFT)
+#define LOCK_THERM_INT_SHIFT 22
+#define LOCK_THERM_INT (1 << LOCK_THERM_INT_SHIFT)
+
+/* MSR_TURBO_RATIO_LIMIT bits */
+#define MSR_TURBO_RATIO_LIMIT 0x1ad
+
+/* MSR_TURBO_RATIO_LIMIT_CORES (0x1ae) */
+#define MSR_TURBO_RATIO_LIMIT_CORES 0x1ae
+
+/* MSR_VR_CURRENT_CONFIG bits */
+#define MSR_VR_CURRENT_CONFIG 0x601
+#define CURRENT_LIMIT_LOCK_SHIFT 31
+#define CURRENT_LIMIT_LOCK (0x1 << CURRENT_LIMIT_LOCK_SHIFT)
+
+/* MSR_TURBO_ACTIVATION_RATIO bits */
+#define MSR_TURBO_ACTIVATION_RATIO 0x64c
+#define MAX_NON_TURBO_RATIO_SHIFT 0
+#define MAX_NON_TURBO_RATIO (0xff << MAX_NON_TURBO_RATIO_SHIFT)
+
+/* MSR_ENERGY_PERF_BIAS_CONFIG bits */
+#define MSR_ENERGY_PERF_BIAS_CONFIG 0xa01
+#define EPB_ENERGY_POLICY_SHIFT 3
+#define EPB_ENERGY_POLICY_MASK (0xf << EPB_ENERGY_POLICY_SHIFT)
+
+#endif /* _SOC_MSR_H_ */
diff --git a/src/soc/intel/xeon_sp/include/soc/nvs.h b/src/soc/intel/xeon_sp/include/soc/nvs.h
new file mode 100644
index 0000000..00dded3
--- /dev/null
+++ b/src/soc/intel/xeon_sp/include/soc/nvs.h
@@ -0,0 +1,33 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2008 - 2009 coresystems GmbH
+ * Copyright (C) 2011 Google Inc
+ * Copyright (C) 2014 - 2020 Intel Corporation.
+ *
+ * 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
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _SOC_NVS_H_
+#define _SOC_NVS_H_
+
+#include <stdint.h>
+
+/* TODO - this requires xeon sp, server board support */
+/* NOTE: We do not use intelblocks/nvs.h since it includes
+ mostly client specific attributes */
+typedef struct global_nvs_t {
+ uint8_t pcnt; /* 0x00 - Processor Count */
+ uint32_t cbmc; /* 0x01 - coreboot memconsole */
+ uint8_t rsvd3[251];
+} __packed global_nvs_t;
+
+#endif /* _SOC_NVS_H_ */
diff --git a/src/soc/intel/xeon_sp/include/soc/pci_devs.h b/src/soc/intel/xeon_sp/include/soc/pci_devs.h
new file mode 100644
index 0000000..db78c82
--- /dev/null
+++ b/src/soc/intel/xeon_sp/include/soc/pci_devs.h
@@ -0,0 +1,186 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2019 - 2020 Intel Corporation.
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _SOC_PCI_DEVS_H_
+#define _SOC_PCI_DEVS_H_
+
+#include <device/pci_def.h>
+#include <hob_iiouds.h>
+
+#define dump_csr(fmt, dev, reg) \
+ printk(BIOS_SPEW, "%s%x:%x:%x reg: %s (0x%x), data: 0x%x\n", \
+ fmt, ((uint32_t)dev >> 20) & 0xfff, ((uint32_t)dev >> 15) & 0x1f, \
+ ((uint32_t)dev >> 12) & 0x07, \
+ #reg, reg, pci_mmio_read_config32(dev, reg))
+
+#define dump_csr64(fmt, dev, reg) \
+ printk(BIOS_SPEW, "%s%x:%x:%x reg: %s (0x%x), data: 0x%x%x\n", \
+ fmt, ((uint32_t)dev >> 20) & 0xfff, ((uint32_t)dev >> 15) & 0x1f, \
+ ((uint32_t)dev >> 12) & 0x07, #reg, reg, \
+ pci_mmio_read_config32(dev, reg+4), pci_mmio_read_config32(dev, reg))
+
+#define _SA_DEVFN(slot) PCI_DEVFN(SA_DEV_SLOT_ ## slot, 0)
+#define _PCH_DEVFN(slot, func) PCI_DEVFN(PCH_DEV_SLOT_ ## slot, func)
+
+#if !defined(__SIMPLE_DEVICE__)
+#include <device/device.h>
+#define _SA_DEV(slot) pcidev_path_on_root_debug(_SA_DEVFN(slot), __func__)
+#define _PCH_DEV(slot, func) pcidev_path_on_root_debug(_PCH_DEVFN(slot, func), __func__)
+#else
+#include <arch/io.h>
+#define _SA_DEV(slot) PCI_DEV(0, SA_DEV_SLOT_ ## slot, 0)
+#define _PCH_DEV(slot, func) PCI_DEV(0, PCH_DEV_SLOT_ ## slot, func)
+#endif
+
+#define MMAP_VTD_CFG_REG_DEVID 0x2024
+#define VTD_DEV 5
+#define VTD_FUNC 0
+
+#define VTD_TOLM_CSR 0xd0
+#define VTD_TSEG_BASE_CSR 0xa8
+#define VTD_TSEG_LIMIT_CSR 0xac
+#define VTD_EXT_CAP_LOW 0x10
+#define VTD_MMCFG_BASE_CSR 0x90
+#define VTD_MMCFG_LIMIT_CSR 0x98
+#define VTD_TOHM_CSR 0xd4
+#define VTD_MMIOL_CSR 0xdc
+#define VTD_ME_BASE_CSR 0xf0
+#define VTD_ME_LIMIT_CSR 0xf8
+#define VTD_VERSION 0x00
+#define VTD_CAP 0x08
+#define VTD_CAP_LOW 0x08
+#define VTD_CAP_HIGH 0x0C
+#define VTD_EXT_CAP_HIGH 0x14
+
+#define SAD_ALL_DEV 29
+#define SAD_ALL_FUNC 0
+#define SAD_ALL_PAM0123_CSR 0x40
+#define SAD_ALL_PAM456_CSR 0x44
+
+#define PCU_IIO_STACK 1
+#define PCU_DEV 30
+#define PCU_CR1_FUN 1
+
+#define PCU_CR0_FUN 0
+#define PCU_CR0_PLATFORM_INFO 0xa8
+#define PCU_CR0_P_STATE_LIMITS 0xd8
+#define P_STATE_LIMITS_LOCK_SHIFT 31
+#define P_STATE_LIMITS_LOCK (1 << P_STATE_LIMITS_LOCK_SHIFT)
+#define PCU_CR0_TEMPERATURE_TARGET 0xe4
+#define PCU_CR0_PACKAGE_RAPL_LIMIT 0xe8
+#define PCU_CR0_CURRENT_CONFIG 0xf8
+#define MAX_NON_TURBO_LIM_RATIO_SHIFT 8 /* 8:15 */
+#define MAX_NON_TURBO_LIM_RATIO_MASK (0xff << MAX_NON_TURBO_LIM_RATIO_SHIFT)
+
+#define PCU_CR1_BIOS_RESET_CPL_REG 0x94
+#define RST_CPL1_MASK ((uint32_t)1 << 1)
+#define RST_CPL2_MASK ((uint32_t)1 << 2)
+#define RST_CPL3_MASK ((uint32_t)1 << 3)
+#define RST_CPL4_MASK ((uint32_t)1 << 4)
+#define PCODE_INIT_DONE1_MASK ((uint32_t)1 << 9)
+#define PCODE_INIT_DONE2_MASK ((uint32_t)1 << 10)
+#define PCODE_INIT_DONE3_MASK ((uint32_t)1 << 11)
+#define PCODE_INIT_DONE4_MASK ((uint32_t)1 << 12)
+
+#define PCU_CR1_BIOS_MB_DATA_REG 0x8c
+
+#define PCU_CR1_BIOS_MB_INTERFACE_REG 0x90
+#define BIOS_MB_RUN_BUSY_MASK ((uint32_t)1 << 31)
+#define BIOS_MB_CMD_MASK ((uint32_t)0xff)
+#define BIOS_CMD_READ_PCU_MISC_CFG 0x5
+#define BIOS_CMD_WRITE_PCU_MISC_CFG 0x6
+#define BIOS_ERR_INVALID_CMD 0x01
+
+#define PCU_CR1_DESIRED_CORES_CFG2_REG 0xa0
+#define PCU_CR1_DESIRED_CORES_CFG2_REG_LOCK_MASK ((uint32_t)1 << 31)
+
+#define PCU_CR1_C2C3TT_REG 0xdc
+#define PCU_CR1_PCIE_ILTR_OVRD 0xfc
+#define PCU_CR1_SAPMCTL 0xb0
+#define SAPMCTL_LOCK_SHIFT 31
+#define SAPMCTL_LOCK_MASK (1 << SAPMCTL_LOCK_SHIFT)
+#define PCU_CR1_MC_BIOS_REQ 0x98
+
+#define PCU_CR2_FUN 2
+#define PCU_CR2_PKG_CST_ENTRY_CRITERIA_MASK 0x8c
+#define PCIE_IN_PKGCSTATE_L1_MASK 0xFFFFFF /* 23:0 bits */
+#define PCU_CR2_PKG_CST_ENTRY_CRITERIA_MASK2 0x90
+#define KTI_IN_PKGCSTATE_L1_MASK 0x7 /* 2:0 bits */
+#define PCU_CR2_DYNAMIC_PERF_POWER_CTL 0xdc
+#define UNCORE_PLIMIT_OVERRIDE_BIT 20
+#define UNOCRE_PLIMIT_OVERRIDE_SHIFT (1 << UNCORE_PLIMIT_OVERRIDE_BIT)
+#define PCU_CR2_PROCHOT_RESPONSE_RATIO_REG 0xb0
+#define PROCHOT_RATIO 0xa /* bits 0:7 */
+
+#define UBOX_DECS_BUS 0
+#define UBOX_DECS_DEV 8
+#define UBOX_DECS_FUNC 2
+#define UBOX_DECS_CPUBUSNO_CSR 0xcc
+
+#define CHA_UTIL_ALL_DEV 29
+#define CHA_UTIL_ALL_FUNC 1
+#define CHA_UTIL_ALL_MMCFG_CSR 0xc0
+
+#define CBDMA_DEV_NUM 0x04
+#define IIO_CBDMA_MMIO_SIZE 0x10000 //64kB for one CBDMA function
+#define IIO_CBDMA_MMIO_ALIGNMENT 14 //2^14 - 16kB
+
+#define VMD_DEV_NUM 5
+#define VMD_FUNC_NUM 5
+
+#define APIC_DEV_NUM 5
+#define APIC_FUNC_NUM 0
+
+#define PCH_IOAPIC_BUS_NUMBER 0xF0
+#define PCH_IOAPIC_DEV_NUM 0x1F
+#define PCH_IOAPIC_FUNC_NUM 0x00
+
+// ================================== IOAPIC Definitions for DMAR/ACPI ====================
+#define PCH_IOAPIC_ID 0x08
+#define PC00_IOAPIC_ID 0x09
+#define PC01_IOAPIC_ID 0x0A
+#define PC02_IOAPIC_ID 0x0B
+#define PC03_IOAPIC_ID 0x0C
+#define PC04_IOAPIC_ID 0x0D
+#define PC05_IOAPIC_ID 0x0E
+#define PC06_IOAPIC_ID 0x0F
+#define PC07_IOAPIC_ID 0x10
+#define PC08_IOAPIC_ID 0x11
+#define PC09_IOAPIC_ID 0x12
+#define PC10_IOAPIC_ID 0x13
+#define PC11_IOAPIC_ID 0x14
+
+/* PCH Device info */
+
+#define XHCI_BUS_NUMBER 0x0
+#define PCH_DEV_SLOT_XHCI 0x14
+#define XHCI_FUNC_NUM 0x0
+
+#define HPET_BUS_NUM 0x0
+#define HPET_DEV_NUM PCH_DEV_SLOT_LPC
+#define HPET0_FUNC_NUM 0x00
+
+#define PCH_DEV_SLOT_LPC 0x1f
+#define PCH_DEVFN_LPC _PCH_DEVFN(LPC, 0)
+#define PCH_DEVFN_P2SB _PCH_DEVFN(LPC, 1)
+#define PCH_DEVFN_PMC _PCH_DEVFN(LPC, 2)
+#define PCH_DEVFN_SPI _PCH_DEVFN(LPC, 5)
+#define PCH_DEV_LPC _PCH_DEV(LPC, 0)
+#define PCH_DEV_P2SB _PCH_DEV(LPC, 1)
+#define PCH_DEV_PMC _PCH_DEV(LPC, 2)
+#define PCH_DEV_SPI _PCH_DEV(LPC, 5)
+
+#endif /* _SOC_PCI_DEVS_H_ */
diff --git a/src/soc/intel/xeon_sp/include/soc/pcr_ids.h b/src/soc/intel/xeon_sp/include/soc/pcr_ids.h
new file mode 100644
index 0000000..c679692
--- /dev/null
+++ b/src/soc/intel/xeon_sp/include/soc/pcr_ids.h
@@ -0,0 +1,23 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2019 - 2020 Intel Corporation.
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _PCR_IDS_H_
+#define _PCR_IDS_H_
+
+#define PID_ITSS 0xC4
+#define PID_RTC 0xC3
+
+#endif /* _PCR_IDS_H_ */
diff --git a/src/soc/intel/xeon_sp/include/soc/pm.h b/src/soc/intel/xeon_sp/include/soc/pm.h
new file mode 100644
index 0000000..ea111cde
--- /dev/null
+++ b/src/soc/intel/xeon_sp/include/soc/pm.h
@@ -0,0 +1,32 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2014 Google Inc.
+ * Copyright (C) 2019 - 2020 Intel Corporation.
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _SOC_PM_H_
+#define _SOC_PM_H_
+
+#include <soc/iomap.h>
+#include <soc/pmc.h>
+
+#define PM1_CNT 0x04
+#define PM1_STS 0x00
+#define PM1_TMR 0x08
+#define PM2_CNT 0x50
+
+#define GPE0_REG_MAX 4
+#define GPE0_STS(x) (0x80 + (x * 4))
+
+#endif
diff --git a/src/soc/intel/xeon_sp/include/soc/pmc.h b/src/soc/intel/xeon_sp/include/soc/pmc.h
new file mode 100644
index 0000000..c080749
--- /dev/null
+++ b/src/soc/intel/xeon_sp/include/soc/pmc.h
@@ -0,0 +1,34 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2019 - 2020 Intel Corporation.
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _SOC_PMC_H_
+#define _SOC_PMC_H_
+
+/* PCI Configuration Space (D31:F2): PMC */
+#define PMC_ACPI_CNT 0x44
+
+#define SCI_IRQ_SEL (7 << 0)
+#define SCIS_IRQ9 0
+#define SCIS_IRQ10 1
+#define SCIS_IRQ11 2
+#define SCIS_IRQ20 4
+#define SCIS_IRQ21 5
+#define SCIS_IRQ22 6
+#define SCIS_IRQ23 7
+
+#define SCI_IRQ_ADJUST 0
+
+#endif
diff --git a/src/soc/intel/xeon_sp/include/soc/ramstage.h b/src/soc/intel/xeon_sp/include/soc/ramstage.h
new file mode 100644
index 0000000..c012dd6
--- /dev/null
+++ b/src/soc/intel/xeon_sp/include/soc/ramstage.h
@@ -0,0 +1,30 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2019 - 2020 Intel Corporation.
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _SOC_RAMSTAGE_H_
+#define _SOC_RAMSTAGE_H_
+
+#include <device/device.h>
+#include <fsp/api.h>
+#include <fsp/util.h>
+#include <memory_info.h>
+
+void xeon_sp_init_cpus(struct device *dev);
+void mainboard_silicon_init_params(FSPS_UPD *params);
+
+extern struct pci_operations soc_pci_ops;
+
+#endif
diff --git a/src/soc/intel/xeon_sp/include/soc/romstage.h b/src/soc/intel/xeon_sp/include/soc/romstage.h
new file mode 100644
index 0000000..623306f
--- /dev/null
+++ b/src/soc/intel/xeon_sp/include/soc/romstage.h
@@ -0,0 +1,26 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2019 - 2020 Intel Corporation.
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+
+#ifndef _SOC_ROMSTAGE_H_
+#define _SOC_ROMSTAGE_H_
+
+#include <fsp/api.h>
+
+/* These functions are weak and can be overridden by a mainboard functions. */
+void mainboard_memory_init_params(FSPM_UPD * mupd);
+
+#endif /* _SOC_ROMSTAGE_H_ */
diff --git a/src/soc/intel/xeon_sp/include/soc/soc_util.h b/src/soc/intel/xeon_sp/include/soc/soc_util.h
new file mode 100644
index 0000000..8b5e1a2
--- /dev/null
+++ b/src/soc/intel/xeon_sp/include/soc/soc_util.h
@@ -0,0 +1,80 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2019 - 2020 Intel Corporation.
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+
+#ifndef _SOC_UTIL_H_
+#define _SOC_UTIL_H_
+
+#include <hob_iiouds.h>
+#include <hob_memmap.h>
+#include <arch/acpi.h>
+
+#define LOG_MEM_RESOURCE(type, dev, index, base_kb, size_kb) \
+ printk(BIOS_SPEW, "%s:%d res: %s, dev: %s, index: 0x%x, base: 0x%llx, " \
+ "end: 0x%llx, size_kb: 0x%llx\n", \
+ __func__, __LINE__, type, dev_path(dev), index, (base_kb << 10), \
+ (base_kb << 10) + (size_kb << 10) - 1, size_kb)
+
+#define LOG_IO_RESOURCE(type, dev, index, base, size) \
+ printk(BIOS_SPEW, "%s:%d res: %s, dev: %s, index: 0x%x, base: 0x%llx, " \
+ "end: 0x%llx, size: 0x%llx\n", \
+ __func__, __LINE__, type, dev_path(dev), index, base, base + size - 1, size)
+
+#define DEV_FUNC_ENTER(dev) \
+ printk(BIOS_SPEW, "%s:%s:%d: ENTER (dev: %s)\n", \
+ __FILE__, __func__, __LINE__, dev_path(dev))
+
+#define DEV_FUNC_EXIT(dev) \
+ printk(BIOS_SPEW, "%s:%s:%d: EXIT (dev: %s)\n", __FILE__, \
+ __func__, __LINE__, dev_path(dev))
+
+#define FUNC_ENTER() \
+ printk(BIOS_SPEW, "%s:%s:%d: ENTER\n", __FILE__, __func__, __LINE__)
+
+#define FUNC_EXIT() \
+ printk(BIOS_SPEW, "%s:%s:%d: EXIT\n", __FILE__, __func__, __LINE__)
+
+struct iiostack_resource {
+ uint8_t no_of_stacks;
+ STACK_RES res[CONFIG_MAX_SOCKET * MAX_IIO_STACK];
+};
+
+uintptr_t get_tolm(uint32_t bus);
+void get_tseg_base_lim(uint32_t bus, uint32_t *base, uint32_t *limit);
+uintptr_t get_cha_mmcfg_base(uint32_t bus);
+uint32_t top_of_32bit_ram(void); // Top of 32bit usable memory
+
+uint32_t pci_read_mmio_reg(int bus, uint32_t dev, uint32_t func, int offset);
+
+void get_stack_busnos(uint32_t *bus);
+void get_cpubusnos(uint32_t *bus0, uint32_t *bus1, uint32_t *bus2, uint32_t *bus3);
+uint32_t get_socket_stack_busno(uint32_t socket, uint32_t stack);
+void get_iiostack_info(struct iiostack_resource *info);
+
+int get_threads_per_package(void);
+int get_platform_thread_count(void);
+void get_core_thread_bits(uint32_t *core_bits, uint32_t *thread_bits);
+
+unsigned int get_srat_memory_entries(acpi_srat_mem_t *srat_mem);
+void get_cpu_info_from_apicid(uint32_t apicid, uint32_t core_bits,
+ uint32_t thread_bits, uint8_t *package, uint8_t *core, uint8_t *thread);
+
+void unlock_pam_regions(void);
+void xeonsp_init_cpu_config(void);
+void set_bios_init_completion(void);
+void config_reset_cpl3_csrs(void);
+
+#endif /* _SOC_UTIL_H_ */
diff --git a/src/soc/intel/xeon_sp/lpc.c b/src/soc/intel/xeon_sp/lpc.c
new file mode 100644
index 0000000..b0ba681
--- /dev/null
+++ b/src/soc/intel/xeon_sp/lpc.c
@@ -0,0 +1,45 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2019 - 2020 Intel Corporation
+ * Copyright (C) 2019 - 2020 Facebook Inc
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <console/console.h>
+#include <arch/ioapic.h>
+#include <intelblocks/lpc_lib.h>
+#include <soc/soc_util.h>
+#include <soc/iomap.h>
+
+static const struct lpc_mmio_range xeon_lpc_fixed_mmio_ranges[] = {
+ { 0, 0 }
+};
+
+const struct lpc_mmio_range *soc_get_fixed_mmio_ranges(void)
+{
+ return xeon_lpc_fixed_mmio_ranges;
+}
+
+void lpc_soc_init(struct device *dev)
+{
+ printk(BIOS_SPEW, "pch: lpc_init\n");
+
+ /* FSP configures IOAPIC and PCHInterrupt Config */
+ printk(BIOS_SPEW, "IOAPICID 0x%x, 0x%x\n",
+ io_apic_read((void *)IO_APIC_ADDR, 0x00),
+ ((io_apic_read((void *)IO_APIC_ADDR, 0x00) & 0x0f000000) >> 24));
+}
+
+void pch_lpc_soc_fill_io_resources(struct device *dev)
+{
+}
diff --git a/src/soc/intel/xeon_sp/reset.c b/src/soc/intel/xeon_sp/reset.c
new file mode 100644
index 0000000..80a452b
--- /dev/null
+++ b/src/soc/intel/xeon_sp/reset.c
@@ -0,0 +1,24 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2019 - 2020 Intel Corporation
+ * Copyright (C) 2019 - 2020 Facebook Inc
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <console/console.h>
+#include <fsp/util.h>
+
+void chipset_handle_reset(uint32_t status)
+{
+ die("Reset not implemented!\n");
+}
diff --git a/src/soc/intel/xeon_sp/romstage.c b/src/soc/intel/xeon_sp/romstage.c
new file mode 100644
index 0000000..dc94dc6
--- /dev/null
+++ b/src/soc/intel/xeon_sp/romstage.c
@@ -0,0 +1,83 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2019 - 2020 Intel Corporation
+ * Copyright (C) 2019 - 2020 Facebook Inc
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <arch/romstage.h>
+#include <cbmem.h>
+#include <intelblocks/rtc.h>
+#include <console/console.h>
+#include <cpu/x86/mtrr.h>
+#include <soc/romstage.h>
+#include <soc/soc_util.h>
+#include "chip.h"
+
+asmlinkage void car_stage_entry(void)
+{
+ struct postcar_frame pcf;
+ uintptr_t top_of_ram;
+
+ printk(BIOS_DEBUG, "FSP TempRamInit was successful...\n");
+
+ console_init();
+ rtc_init();
+
+ fsp_memory_init(false);
+ printk(BIOS_DEBUG, "coreboot fsp_memory_init finished...\n");
+
+ unlock_pam_regions();
+
+ if (postcar_frame_init(&pcf, 1 * KiB))
+ die("Unable to initialize postcar frame.\n");
+
+ /*
+ * We need to make sure ramstage will be run cached. At this point exact
+ * location of ramstage in cbmem is not known. Instruct postcar to cache
+ * 16 megs under cbmem top which is a safe bet to cover ramstage.
+ */
+ top_of_ram = (uintptr_t)cbmem_top();
+ printk(BIOS_DEBUG, "top_of_ram: 0x%lx\n", top_of_ram);
+ postcar_frame_add_mtrr(&pcf, top_of_ram - 16 * MiB, 16 * MiB,
+ MTRR_TYPE_WRBACK);
+
+ /* Cache the memory-mapped boot media. */
+ postcar_frame_add_romcache(&pcf, MTRR_TYPE_WRPROT);
+
+ run_postcar_phase(&pcf);
+}
+
+static void soc_memory_init_params(FSP_M_CONFIG *m_cfg)
+{
+}
+
+void platform_fsp_memory_init_params_cb(FSPM_UPD *mupd, uint32_t version)
+{
+ const config_t *config = config_of_soc();
+ FSP_M_CONFIG *m_cfg = &mupd->FspmConfig;
+
+ mupd->FspmUpdVersion = FSP_UPD_VERSION;
+
+ // ErrorLevel - 0 (disable) to 8 (verbose)
+ m_cfg->PcdFspMrcDebugPrintErrorLevel = 0;
+ m_cfg->PcdFspKtiDebugPrintErrorLevel = 0;
+
+ soc_memory_init_params(m_cfg);
+
+ mainboard_memory_init_params(mupd);
+
+ m_cfg->VTdConfig.VTdSupport = config->vtd_support;
+ m_cfg->VTdConfig.CoherencySupport = config->coherency_support;
+ m_cfg->VTdConfig.ATS = config->ats_support;
+}
diff --git a/src/soc/intel/xeon_sp/soc_util.c b/src/soc/intel/xeon_sp/soc_util.c
new file mode 100644
index 0000000..6310bac
--- /dev/null
+++ b/src/soc/intel/xeon_sp/soc_util.c
@@ -0,0 +1,577 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2019 - 2020 Intel Corporation
+ * Copyright (C) 2019 - 2020 Facebook Inc
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <assert.h>
+#include <commonlib/sort.h>
+#include <console/console.h>
+#include <cpu/cpu.h>
+#include <cpu/x86/msr.h>
+#include <delay.h>
+#include <device/pci.h>
+#include <hob_iiouds.h>
+#include <intelblocks/cpulib.h>
+#include <intelblocks/pcr.h>
+#include <soc/iomap.h>
+#include <soc/cpu.h>
+#include <soc/msr.h>
+#include <soc/pci_devs.h>
+#include <soc/pcr_ids.h>
+#include <soc/soc_util.h>
+#include <stdlib.h>
+#include <timer.h>
+
+/*
+ * Get TOLM CSR B0:D5:F0:Offset_d0h
+ */
+uintptr_t get_tolm(uint32_t bus)
+{
+ uint32_t w = pci_io_read_config32(PCI_DEV(bus, VTD_DEV, VTD_FUNC),
+ VTD_TOLM_CSR);
+ uintptr_t addr = w & 0xfc000000;
+ printk(BIOS_DEBUG, "VTD_TOLM_CSR 0x%x, addr: 0x%lx\n", w, addr);
+ return addr;
+}
+
+void get_tseg_base_lim(uint32_t bus, uint32_t *base, uint32_t *limit)
+{
+ uint32_t w1 = pci_io_read_config32(PCI_DEV(bus, VTD_DEV, VTD_FUNC),
+ VTD_TSEG_BASE_CSR);
+ uint32_t wh = pci_io_read_config32(PCI_DEV(bus, VTD_DEV, VTD_FUNC),
+ VTD_TSEG_LIMIT_CSR);
+ *base = w1 & 0xfff00000;
+ *limit = wh & 0xfff00000;
+}
+
+/*
+ * Get MMCFG CSR B1:D29:F1:Offset_C0h
+ */
+uintptr_t get_cha_mmcfg_base(uint32_t bus)
+{
+ uint32_t wl = pci_io_read_config32(PCI_DEV(bus, CHA_UTIL_ALL_DEV,
+ CHA_UTIL_ALL_FUNC), CHA_UTIL_ALL_MMCFG_CSR);
+ uint32_t wh = pci_io_read_config32(PCI_DEV(bus, CHA_UTIL_ALL_DEV,
+ CHA_UTIL_ALL_FUNC), CHA_UTIL_ALL_MMCFG_CSR + 4);
+ uintptr_t addr = ((((wh & 0x3fff) << 6) | ((wl >> 26) & 0x3f)) << 26);
+ printk(BIOS_DEBUG, "CHA_UTIL_ALL_MMCFG_CSR wl: 0x%x, wh: 0x%x, addr: 0x%lx\n",
+ wl, wh, addr);
+ return addr;
+}
+
+/*
+ * Get Socket 0 CPUBUSNO(0), CPUBUSNO(1) PCI bus numbers UBOX (B0:D8:F2:Offset_CCh)
+ * TODO: D0h
+ */
+void get_cpubusnos(uint32_t *bus0, uint32_t *bus1, uint32_t *bus2, uint32_t *bus3)
+{
+ uint32_t bus = pci_io_read_config32(PCI_DEV(UBOX_DECS_BUS, UBOX_DECS_DEV,
+ UBOX_DECS_FUNC), UBOX_DECS_CPUBUSNO_CSR);
+ if (bus0)
+ *bus0 = (bus & 0xff);
+ if (bus1)
+ *bus1 = (bus >> 8) & 0xff;
+ if (bus2)
+ *bus2 = (bus >> 16) & 0xff;
+ if (bus3)
+ *bus3 = (bus >> 24) & 0xff;
+}
+
+uint32_t top_of_32bit_ram(void)
+{
+ uintptr_t mmcfg, tolm;
+ uint32_t bus0 = 0, bus1 = 0;
+ uint32_t base = 0, limit = 0;
+
+ get_cpubusnos(&bus0, &bus1, NULL, NULL);
+
+ mmcfg = get_cha_mmcfg_base(bus1);
+ tolm = get_tolm(bus0);
+ printk(BIOS_DEBUG, "bus0: 0x%x, bus1: 0x%x, mmcfg: 0x%lx, tolm: 0x%lx\n",
+ bus0, bus1, mmcfg, tolm);
+ get_tseg_base_lim(bus0, &base, &limit);
+ printk(BIOS_DEBUG, "tseg base: 0x%x, limit: 0x%x\n", base, limit);
+
+ /* We will use TSEG base as the top of DRAM */
+ return base;
+}
+
+/*
+ * +-------------------------+ TOLM
+ * | System Management Mode |
+ * | code and data |
+ * | (TSEG) |
+ * +-------------------------+ SMM base (aligned)
+ * | |
+ * | Chipset Reserved Memory |
+ * | |
+ * +-------------------------+ top_of_ram (aligned)
+ * | |
+ * | CBMEM Root |
+ * | |
+ * +-------------------------+
+ * | |
+ * | FSP Reserved Memory |
+ * | |
+ * +-------------------------+
+ * | |
+ * | Various CBMEM Entries |
+ * | |
+ * +-------------------------+ top_of_stack (8 byte aligned)
+ * | |
+ * | stack (CBMEM Entry) |
+ * | |
+ * +-------------------------+
+ */
+
+uint32_t pci_read_mmio_reg(int bus, uint32_t dev, uint32_t func, int offset)
+{
+ return pci_mmio_read_config32(PCI_DEV(bus, dev, func), offset);
+}
+
+uint32_t get_socket_stack_busno(uint32_t socket, uint32_t stack)
+{
+ size_t hob_size;
+ const IIO_UDS *hob;
+ const uint8_t fsp_hob_iio_universal_data_guid[16] = FSP_HOB_IIO_UNIVERSAL_DATA_GUID;
+
+ assert(socket < MAX_SOCKET && stack < MAX_IIO_STACK);
+
+ hob = fsp_find_extension_hob_by_guid(fsp_hob_iio_universal_data_guid, &hob_size);
+ assert(hob != NULL && hob_size != 0);
+
+ return hob->PlatformData.CpuQpiInfo[socket].StackBus[stack];
+}
+
+/* bus needs to be of size 6 (MAX_IIO_STACK) */
+void get_stack_busnos(uint32_t *bus)
+{
+ uint32_t reg1, reg2;
+
+ reg1 = pci_mmio_read_config32(PCI_DEV(UBOX_DECS_BUS, UBOX_DECS_DEV, UBOX_DECS_FUNC),
+ 0xcc);
+ reg2 = pci_mmio_read_config32(PCI_DEV(UBOX_DECS_BUS, UBOX_DECS_DEV, UBOX_DECS_FUNC),
+ 0xd0);
+
+ for (int i = 0; i < 4; ++i)
+ bus[i] = ((reg1 >> (i * 8)) & 0xff);
+ for (int i = 0; i < 2; ++i)
+ bus[4+i] = ((reg2 >> (i * 8)) & 0xff);
+}
+
+void unlock_pam_regions(void)
+{
+ uint32_t bus1 = 0;
+ uint32_t pam0123_unlock_dram = 0x33333330;
+ uint32_t pam456_unlock_dram = 0x00333333;
+
+ get_cpubusnos(NULL, &bus1, NULL, NULL);
+ pci_io_write_config32(PCI_DEV(bus1, SAD_ALL_DEV, SAD_ALL_FUNC),
+ SAD_ALL_PAM0123_CSR, pam0123_unlock_dram);
+ pci_io_write_config32(PCI_DEV(bus1, SAD_ALL_DEV, SAD_ALL_FUNC),
+ SAD_ALL_PAM456_CSR, pam456_unlock_dram);
+
+ uint32_t reg1 = pci_io_read_config32(PCI_DEV(bus1, SAD_ALL_DEV,
+ SAD_ALL_FUNC), SAD_ALL_PAM0123_CSR);
+ uint32_t reg2 = pci_io_read_config32(PCI_DEV(bus1, SAD_ALL_DEV,
+ SAD_ALL_FUNC), SAD_ALL_PAM456_CSR);
+ printk(BIOS_DEBUG, "%s:%s pam0123_csr: 0x%x, pam456_csr: 0x%x\n",
+ __FILE__, __func__, reg1, reg2);
+}
+
+/* return 1 if command timed out else 0 */
+static uint32_t wait_for_bios_cmd_cpl(pci_devfn_t dev, uint32_t reg, uint32_t mask,
+ uint32_t target)
+{
+ uint32_t max_delay = 5000; /* 5 seconds max */
+ uint32_t step_delay = 50; /* 50 us */
+ struct stopwatch sw;
+
+ stopwatch_init_msecs_expire(&sw, max_delay);
+ while ((pci_mmio_read_config32(dev, reg) & mask) != target) {
+ udelay(step_delay);
+ if (stopwatch_expired(&sw)) {
+ printk(BIOS_ERR, "%s timed out for dev: 0x%x, reg: 0x%x, "
+ "mask: 0x%x, target: 0x%x\n", __func__, dev, reg, mask, target);
+ return 1; /* timedout */
+ }
+ }
+ return 0; /* successful */
+}
+
+/* return 1 if command timed out else 0 */
+static int set_bios_reset_cpl_for_package(uint32_t socket, uint32_t rst_cpl_mask,
+ uint32_t pcode_init_mask, uint32_t val)
+{
+ uint32_t bus = get_socket_stack_busno(socket, PCU_IIO_STACK);
+ pci_devfn_t dev = PCI_DEV(bus, PCU_DEV, PCU_CR1_FUN);
+
+ uint32_t reg = pci_mmio_read_config32(dev, PCU_CR1_BIOS_RESET_CPL_REG);
+ reg &= (uint32_t) ~rst_cpl_mask;
+ reg |= rst_cpl_mask;
+ reg |= val;
+
+ /* update BIOS RESET completion bit */
+ pci_mmio_write_config32(dev, PCU_CR1_BIOS_RESET_CPL_REG, reg);
+
+ /* wait for PCU ack */
+ return wait_for_bios_cmd_cpl(dev, PCU_CR1_BIOS_RESET_CPL_REG, pcode_init_mask,
+ pcode_init_mask);
+}
+
+/* return 1 if command timed out else 0 */
+static uint32_t write_bios_mailbox_cmd(pci_devfn_t dev, uint32_t command, uint32_t data)
+{
+ /* verify bios is not in busy state */
+ if (wait_for_bios_cmd_cpl(dev, PCU_CR1_BIOS_MB_INTERFACE_REG, BIOS_MB_RUN_BUSY_MASK, 0))
+ return 1; /* timed out */
+
+ /* write data to data register */
+ printk(BIOS_SPEW, "%s - pci_mmio_write_config32 reg: 0x%x, data: 0x%x\n", __func__,
+ PCU_CR1_BIOS_MB_DATA_REG, data);
+ pci_mmio_write_config32(dev, PCU_CR1_BIOS_MB_DATA_REG, data);
+
+ /* write the command */
+ printk(BIOS_SPEW, "%s - pci_mmio_write_config32 reg: 0x%x, data: 0x%x\n", __func__,
+ PCU_CR1_BIOS_MB_INTERFACE_REG,
+ (uint32_t) (command | BIOS_MB_RUN_BUSY_MASK));
+ pci_mmio_write_config32(dev, PCU_CR1_BIOS_MB_INTERFACE_REG,
+ (uint32_t) (command | BIOS_MB_RUN_BUSY_MASK));
+
+ /* wait for completion or time out*/
+ return wait_for_bios_cmd_cpl(dev, PCU_CR1_BIOS_MB_INTERFACE_REG,
+ BIOS_MB_RUN_BUSY_MASK, 0);
+}
+
+void config_reset_cpl3_csrs(void)
+{
+ uint32_t data, plat_info, max_min_turbo_limit_ratio;
+
+ for (uint32_t socket = 0; socket < MAX_SOCKET; ++socket) {
+ uint32_t bus = get_socket_stack_busno(socket, PCU_IIO_STACK);
+
+ /* configure PCU_CR0_FUN csrs */
+ pci_devfn_t cr0_dev = PCI_DEV(bus, PCU_DEV, PCU_CR0_FUN);
+ data = pci_mmio_read_config32(cr0_dev, PCU_CR0_P_STATE_LIMITS);
+ data |= P_STATE_LIMITS_LOCK;
+ pci_mmio_write_config32(cr0_dev, PCU_CR0_P_STATE_LIMITS, data);
+
+ plat_info = pci_mmio_read_config32(cr0_dev, PCU_CR0_PLATFORM_INFO);
+ dump_csr64("", cr0_dev, PCU_CR0_PLATFORM_INFO);
+ max_min_turbo_limit_ratio =
+ (plat_info & MAX_NON_TURBO_LIM_RATIO_MASK) >>
+ MAX_NON_TURBO_LIM_RATIO_SHIFT;
+ printk(BIOS_SPEW, "plat_info: 0x%x, max_min_turbo_limit_ratio: 0x%x\n",
+ plat_info, max_min_turbo_limit_ratio);
+
+ /* configure PCU_CR1_FUN csrs */
+ pci_devfn_t cr1_dev = PCI_DEV(bus, PCU_DEV, PCU_CR1_FUN);
+
+ data = pci_mmio_read_config32(cr1_dev, PCU_CR1_SAPMCTL);
+ /* clear bits 27:31 - FSP sets this with 0x7 which needs to be cleared */
+ data &= 0x0fffffff;
+ data |= SAPMCTL_LOCK_MASK;
+ pci_mmio_write_config32(cr1_dev, PCU_CR1_SAPMCTL, data);
+
+ /* configure PCU_CR1_FUN csrs */
+ pci_devfn_t cr2_dev = PCI_DEV(bus, PCU_DEV, PCU_CR2_FUN);
+
+ data = PCIE_IN_PKGCSTATE_L1_MASK;
+ pci_mmio_write_config32(cr2_dev, PCU_CR2_PKG_CST_ENTRY_CRITERIA_MASK, data);
+
+ data = KTI_IN_PKGCSTATE_L1_MASK;
+ pci_mmio_write_config32(cr2_dev, PCU_CR2_PKG_CST_ENTRY_CRITERIA_MASK2, data);
+
+ data = PROCHOT_RATIO;
+ printk(BIOS_SPEW, "PCU_CR2_PROCHOT_RESPONSE_RATIO_REG data: 0x%x\n", data);
+ pci_mmio_write_config32(cr2_dev, PCU_CR2_PROCHOT_RESPONSE_RATIO_REG, data);
+ dump_csr("", cr2_dev, PCU_CR2_PROCHOT_RESPONSE_RATIO_REG);
+
+ data = pci_mmio_read_config32(cr2_dev, PCU_CR2_DYNAMIC_PERF_POWER_CTL);
+ data |= UNOCRE_PLIMIT_OVERRIDE_SHIFT;
+ pci_mmio_write_config32(cr2_dev, PCU_CR2_DYNAMIC_PERF_POWER_CTL, data);
+ }
+}
+
+static void set_bios_init_completion_for_package(uint32_t socket)
+{
+ uint32_t data;
+ uint32_t timedout;
+ uint32_t bus = get_socket_stack_busno(socket, PCU_IIO_STACK);
+ pci_devfn_t dev = PCI_DEV(bus, PCU_DEV, PCU_CR1_FUN);
+
+ /* read pcu config */
+ timedout = write_bios_mailbox_cmd(dev, BIOS_CMD_READ_PCU_MISC_CFG, 0);
+ if (timedout) {
+ /* 2nd try */
+ timedout = write_bios_mailbox_cmd(dev, BIOS_CMD_READ_PCU_MISC_CFG, 0);
+ if (timedout)
+ die("BIOS PCU Misc Config Read timed out.\n");
+
+ data = pci_mmio_read_config32(dev, PCU_CR1_BIOS_MB_DATA_REG);
+ printk(BIOS_SPEW, "%s - pci_mmio_read_config32 reg: 0x%x, data: 0x%x\n",
+ __func__, PCU_CR1_BIOS_MB_DATA_REG, data);
+
+ /* write PCU config */
+ timedout = write_bios_mailbox_cmd(dev, BIOS_CMD_WRITE_PCU_MISC_CFG, data);
+ if (timedout)
+ die("BIOS PCU Misc Config Write timed out.\n");
+ }
+
+ /* update RST_CPL3, PCODE_INIT_DONE3 */
+ timedout = set_bios_reset_cpl_for_package(socket, RST_CPL3_MASK,
+ PCODE_INIT_DONE3_MASK, RST_CPL3_MASK);
+ if (timedout)
+ die("BIOS RESET CPL3 timed out.\n");
+
+ /* update RST_CPL4, PCODE_INIT_DONE4 */
+ timedout = set_bios_reset_cpl_for_package(socket, RST_CPL4_MASK,
+ PCODE_INIT_DONE4_MASK, RST_CPL4_MASK);
+ if (timedout)
+ die("BIOS RESET CPL4 timed out.\n");
+ /* set CSR_DESIRED_CORES_CFG2 lock bit */
+ data = pci_mmio_read_config32(dev, PCU_CR1_DESIRED_CORES_CFG2_REG);
+ data |= PCU_CR1_DESIRED_CORES_CFG2_REG_LOCK_MASK;
+ printk(BIOS_SPEW, "%s - pci_mmio_write_config32 PCU_CR1_DESIRED_CORES_CFG2_REG 0x%x, data: 0x%x\n",
+ __func__, PCU_CR1_DESIRED_CORES_CFG2_REG, data);
+ pci_mmio_write_config32(dev, PCU_CR1_DESIRED_CORES_CFG2_REG, data);
+}
+
+void set_bios_init_completion(void)
+{
+ uint32_t sbsp_socket_id = 0; /* TODO - this needs to be configurable */
+
+ for (uint32_t socket = 0; socket < MAX_SOCKET; ++socket) {
+ if (socket == sbsp_socket_id)
+ continue;
+ set_bios_init_completion_for_package(socket);
+ }
+ set_bios_init_completion_for_package(sbsp_socket_id);
+}
+
+void get_core_thread_bits(uint32_t *core_bits, uint32_t *thread_bits)
+{
+ register int ecx;
+ struct cpuid_result cpuid_regs;
+
+ /* get max index of CPUID */
+ cpuid_regs = cpuid(0);
+ assert(cpuid_regs.eax >= 0xb); /* cpuid_regs.eax is max input value for cpuid */
+
+ *thread_bits = *core_bits = 0;
+ ecx = 0;
+ while (1) {
+ cpuid_regs = cpuid_ext(0xb, ecx);
+ if (ecx == 0) {
+ *thread_bits = (cpuid_regs.eax & 0x1f);
+ } else {
+ *core_bits = (cpuid_regs.eax & 0x1f) - *thread_bits;
+ break;
+ }
+ ecx++;
+ }
+}
+
+void get_cpu_info_from_apicid(uint32_t apicid, uint32_t core_bits, uint32_t thread_bits,
+ uint8_t *package, uint8_t *core, uint8_t *thread)
+{
+ if (package != NULL)
+ *package = (apicid >> (thread_bits + core_bits));
+ if (core != NULL)
+ *core = (uint32_t)((apicid >> thread_bits) & ~((~0) << core_bits));
+ if (thread != NULL)
+ *thread = (uint32_t)(apicid & ~((~0) << thread_bits));
+}
+
+int get_cpu_count(void)
+{
+ size_t hob_size;
+ const uint8_t fsp_hob_iio_universal_data_guid[16] = FSP_HOB_IIO_UNIVERSAL_DATA_GUID;
+ const IIO_UDS *hob;
+
+ /* these fields are incorrect - need debugging */
+ hob = fsp_find_extension_hob_by_guid(fsp_hob_iio_universal_data_guid, &hob_size);
+ assert(hob != NULL && hob_size != 0);
+ return hob->SystemStatus.numCpus;
+}
+
+int get_threads_per_package(void)
+{
+ unsigned int core_count, thread_count;
+ cpu_read_topology(&core_count, &thread_count);
+ return thread_count;
+}
+
+int get_platform_thread_count(void)
+{
+ return get_cpu_count() * get_threads_per_package();
+}
+
+void get_iiostack_info(struct iiostack_resource *info)
+{
+ size_t hob_size;
+ const uint8_t fsp_hob_iio_universal_data_guid[16] = FSP_HOB_IIO_UNIVERSAL_DATA_GUID;
+ const IIO_UDS *hob;
+
+ hob = fsp_find_extension_hob_by_guid(
+ fsp_hob_iio_universal_data_guid, &hob_size);
+ assert(hob != NULL && hob_size != 0);
+
+ // copy IIO Stack info from FSP HOB
+ info->no_of_stacks = 0;
+ for (int s = 0; s < hob->PlatformData.numofIIO; ++s) {
+ for (int x = 0; x < MAX_IIO_STACK; ++x) {
+ const STACK_RES *ri = &hob->PlatformData.IIO_resource[s].StackRes[x];
+ // TODO: do we have situation with only bux 0 and one stack?
+ if (ri->BusBase >= ri->BusLimit)
+ continue;
+ assert(info->no_of_stacks < (CONFIG_MAX_SOCKET * MAX_IIO_STACK));
+ memcpy(&info->res[info->no_of_stacks++], ri, sizeof(STACK_RES));
+ }
+ }
+}
+
+#if ENV_RAMSTAGE
+
+void xeonsp_init_cpu_config(void)
+{
+ struct device *dev;
+ int apic_ids[CONFIG_MAX_CPUS] = {0}, apic_ids_by_thread[CONFIG_MAX_CPUS] = {0};
+ int num_apics = 0;
+ uint32_t core_bits, thread_bits;
+ unsigned int core_count, thread_count;
+ unsigned int num_cpus;
+
+ /* sort APIC ids in asending order to identify apicid ranges for
+ each numa domain
+ */
+ for (dev = all_devices; dev; dev = dev->next) {
+ if ((dev->path.type != DEVICE_PATH_APIC) ||
+ (dev->bus->dev->path.type != DEVICE_PATH_CPU_CLUSTER)) {
+ continue;
+ }
+ if (!dev->enabled)
+ continue;
+ if (num_apics >= ARRAY_SIZE(apic_ids))
+ break;
+ apic_ids[num_apics++] = dev->path.apic.apic_id;
+ }
+ if (num_apics > 1)
+ bubblesort(apic_ids, num_apics, NUM_ASCENDING);
+
+ num_cpus = get_cpu_count();
+ cpu_read_topology(&core_count, &thread_count);
+ assert(num_apics == (num_cpus * thread_count));
+
+ /* sort them by thread i.e., all cores with thread 0 and then thread 1 */
+ int index = 0;
+ for (int id = 0; id < num_apics; ++id) {
+ int apic_id = apic_ids[id];
+ if (apic_id & 0x1) { /* 2nd thread */
+ apic_ids_by_thread[index + (num_apics/2) - 1] = apic_id;
+ } else { /* 1st thread */
+ apic_ids_by_thread[index++] = apic_id;
+ }
+ }
+
+
+ /* update apic_id, node_id in sorted order */
+ num_apics = 0;
+ get_core_thread_bits(&core_bits, &thread_bits);
+ for (dev = all_devices; dev; dev = dev->next) {
+ uint8_t package;
+
+ if ((dev->path.type != DEVICE_PATH_APIC) ||
+ (dev->bus->dev->path.type != DEVICE_PATH_CPU_CLUSTER)) {
+ continue;
+ }
+ if (!dev->enabled)
+ continue;
+ if (num_apics >= ARRAY_SIZE(apic_ids))
+ break;
+ dev->path.apic.apic_id = apic_ids_by_thread[num_apics];
+ get_cpu_info_from_apicid(dev->path.apic.apic_id, core_bits, thread_bits,
+ &package, NULL, NULL);
+ dev->path.apic.node_id = package;
+ printk(BIOS_DEBUG, "CPU %d apic_id: 0x%x (%d), node_id: 0x%x\n",
+ num_apics, dev->path.apic.apic_id,
+ dev->path.apic.apic_id, dev->path.apic.node_id);
+
+ ++num_apics;
+ }
+}
+
+unsigned int get_srat_memory_entries(acpi_srat_mem_t *srat_mem)
+{
+ const struct SystemMemoryMapHob *memory_map;
+ size_t hob_size;
+ const uint8_t mem_hob_guid[16] = FSP_SYSTEM_MEMORYMAP_HOB_GUID;
+ unsigned int mmap_index;
+
+ memory_map = fsp_find_extension_hob_by_guid(mem_hob_guid, &hob_size);
+ assert(memory_map != NULL && hob_size != 0);
+ printk(BIOS_DEBUG, "FSP_SYSTEM_MEMORYMAP_HOB_GUID hob_size: %ld\n", hob_size);
+
+ mmap_index = 0;
+ for (int e = 0; e < memory_map->numberEntries; ++e) {
+ const struct SystemMemoryMapElement *mem_element = &memory_map->Element[e];
+ uint64_t addr =
+ (uint64_t) ((uint64_t)mem_element->BaseAddress <<
+ MEM_ADDR_64MB_SHIFT_BITS);
+ uint64_t size =
+ (uint64_t) ((uint64_t)mem_element->ElementSize <<
+ MEM_ADDR_64MB_SHIFT_BITS);
+
+ printk(BIOS_DEBUG, "memory_map %d addr: 0x%llx, BaseAddress: 0x%x, size: 0x%llx, "
+ "ElementSize: 0x%x, reserved: %d\n",
+ e, addr, mem_element->BaseAddress, size,
+ mem_element->ElementSize, (mem_element->Type & MEM_TYPE_RESERVED));
+
+ assert(mmap_index < MAX_ACPI_MEMORY_AFFINITY_COUNT);
+
+ /* skip reserved memory region */
+ if (mem_element->Type & MEM_TYPE_RESERVED)
+ continue;
+
+ /* skip if this address is already added */
+ bool skip = false;
+ for (int idx = 0; idx < mmap_index; ++idx) {
+ uint64_t base_addr = ((uint64_t)srat_mem[idx].base_address_high << 32) +
+ srat_mem[idx].base_address_low;
+ if (addr == base_addr) {
+ skip = true;
+ break;
+ }
+ }
+ if (skip)
+ continue;
+
+ srat_mem[mmap_index].type = 1; /* Memory affinity structure */
+ srat_mem[mmap_index].length = sizeof(acpi_srat_mem_t);
+ srat_mem[mmap_index].base_address_low = (uint32_t) (addr & 0xffffffff);
+ srat_mem[mmap_index].base_address_high = (uint32_t) (addr >> 32);
+ srat_mem[mmap_index].length_low = (uint32_t) (size & 0xffffffff);
+ srat_mem[mmap_index].length_high = (uint32_t) (size >> 32);
+ srat_mem[mmap_index].proximity_domain = mem_element->SocketId;
+ srat_mem[mmap_index].flags = SRAT_ACPI_MEMORY_ENABLED;
+ if ((mem_element->Type & MEMTYPE_VOLATILE_MASK) == 0)
+ srat_mem[mmap_index].flags |= SRAT_ACPI_MEMORY_NONVOLATILE;
+ ++mmap_index;
+ }
+
+ return mmap_index;
+}
+
+#endif
diff --git a/src/soc/intel/xeon_sp/spi.c b/src/soc/intel/xeon_sp/spi.c
new file mode 100644
index 0000000..18af5e4
--- /dev/null
+++ b/src/soc/intel/xeon_sp/spi.c
@@ -0,0 +1,28 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2019 - 2020 Intel Corporation
+ * Copyright (C) 2019 - 2020 Facebook Inc
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <intelblocks/spi.h>
+#include <soc/pci_devs.h>
+
+int spi_soc_devfn_to_bus(unsigned int devfn)
+{
+ switch (devfn) {
+ case PCH_DEVFN_SPI:
+ return 0;
+ }
+ return -1;
+}
diff --git a/src/soc/intel/xeon_sp/uncore.c b/src/soc/intel/xeon_sp/uncore.c
new file mode 100644
index 0000000..adf3e3e
--- /dev/null
+++ b/src/soc/intel/xeon_sp/uncore.c
@@ -0,0 +1,305 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2019 - 2020 Intel Corporation
+ * Copyright (C) 2019 - 2020 Facebook Inc
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <cbmem.h>
+#include <console/console.h>
+#include <cpu/x86/lapic.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <soc/iomap.h>
+#include <soc/pci_devs.h>
+#include <soc/ramstage.h>
+#include <soc/soc_util.h>
+
+struct map_entry {
+ uint32_t reg;
+ int is_64_bit;
+ int is_limit;
+ int mask_bits;
+ const char *description;
+};
+
+enum {
+ TOHM_REG,
+ MMIOL_REG,
+ MMCFG_BASE_REG,
+ MMCFG_LIMIT_REG,
+ TOLM_REG,
+ ME_BASE_REG,
+ ME_LIMIT_REG,
+ TSEG_BASE_REG,
+ TSEG_LIMIT_REG,
+ /* Must be last. */
+ NUM_MAP_ENTRIES
+};
+
+static struct map_entry memory_map[NUM_MAP_ENTRIES] = {
+ [TOHM_REG] = MAP_ENTRY_LIMIT_64(VTD_TOHM_CSR, 26, "TOHM"),
+ [MMIOL_REG] = MAP_ENTRY_BASE_32(VTD_MMIOL_CSR, "MMIOL"),
+ [MMCFG_BASE_REG] = MAP_ENTRY_BASE_64(VTD_MMCFG_BASE_CSR, "MMCFG_BASE"),
+ [MMCFG_LIMIT_REG] = MAP_ENTRY_LIMIT_64(VTD_MMCFG_LIMIT_CSR, 26, "MMCFG_LIMIT"),
+ [TOLM_REG] = MAP_ENTRY_LIMIT_32(VTD_TOLM_CSR, 26, "TOLM"),
+ [ME_BASE_REG] = MAP_ENTRY_BASE_64(VTD_ME_BASE_CSR, "ME_BASE"),
+ [ME_LIMIT_REG] = MAP_ENTRY_LIMIT_64(VTD_ME_LIMIT_CSR, 19, "ME_LIMIT"),
+ [TSEG_BASE_REG] = MAP_ENTRY_BASE_32(VTD_TSEG_BASE_CSR, "TSEGMB_BASE"),
+ [TSEG_LIMIT_REG] = MAP_ENTRY_LIMIT_32(VTD_TSEG_LIMIT_CSR, 20, "TSEGMB_LIMIT"),
+};
+
+static void read_map_entry(struct device *dev, struct map_entry *entry,
+ uint64_t *result)
+{
+ uint64_t value;
+ uint64_t mask;
+
+ /* All registers are on a 1MiB granularity. */
+ mask = ((1ULL << entry->mask_bits) - 1);
+ mask = ~mask;
+
+ value = 0;
+
+ if (entry->is_64_bit) {
+ value = pci_read_config32(dev, entry->reg + sizeof(uint32_t));
+ value <<= 32;
+ }
+
+ value |= (uint64_t)pci_read_config32(dev, entry->reg);
+ value &= mask;
+
+ if (entry->is_limit)
+ value |= ~mask;
+
+ *result = value;
+}
+
+static void mc_read_map_entries(struct device *dev, uint64_t *values)
+{
+ int i;
+ for (i = 0; i < NUM_MAP_ENTRIES; i++)
+ read_map_entry(dev, &memory_map[i], &values[i]);
+}
+
+static void mc_report_map_entries(struct device *dev, uint64_t *values)
+{
+ int i;
+ for (i = 0; i < NUM_MAP_ENTRIES; i++) {
+ printk(BIOS_DEBUG, "MC MAP: %s: 0x%llx\n",
+ memory_map[i].description, values[i]);
+ }
+}
+
+/*
+ * Host Memory Map:
+ *
+ * +--------------------------+ TOCM (2 pow 46 - 1)
+ * | Reserved |
+ * +--------------------------+
+ * | MMIOH (relocatable) |
+ * +--------------------------+
+ * | PCISeg |
+ * +--------------------------+ TOHM
+ * | High DRAM Memory |
+ * +--------------------------+ 4GiB (0x100000000)
+ * +--------------------------+ 0xFFFF_FFFF
+ * | Firmware |
+ * +--------------------------+ 0xFF00_0000
+ * | Reserved |
+ * +--------------------------+ 0xFEF0_0000
+ * | Local xAPIC |
+ * +--------------------------+ 0xFEE0_0000
+ * | HPET/LT/TPM/Others |
+ * +--------------------------+ 0xFED0_0000
+ * | I/O xAPIC |
+ * +--------------------------+ 0xFEC0_0000
+ * | Reserved |
+ * +--------------------------+ 0xFEB8_0000
+ * | Reserved |
+ * +--------------------------+ 0xFEB0_0000
+ * | Reserved |
+ * +--------------------------+ 0xFE00_0000
+ * | MMIOL (relocatable) |
+ * | P2SB PCR cfg BAR | (0xfd000000 - 0xfdffffff
+ * | BAR space | [mem 0x90000000-0xfcffffff] available for PCI devices
+ * +--------------------------+ 0x9000_0000
+ * |PCIe MMCFG (relocatable) | CONFIG_MMCONF_BASE_ADDRESS 64 or 256MB
+ * | | (0x80000000 - 0x8fffffff, 0x40000)
+ * +--------------------------+ TOLM
+ * | MEseg (relocatable) | 32, 64, 128 or 256 MB (0x78000000 - 0x7fffffff, 0x20000)
+ * +--------------------------+
+ * | Tseg (relocatable) | N x 8MB (0x70000000 - 0x77ffffff, 0x20000)
+ * +--------------------------+ cbmem_top
+ * | Reserved - CBMEM | (0x6fffe000 - 0x6fffffff, 0x2000)
+ * +--------------------------+
+ * | Reserved - FSP | (0x6fbfe000 - 0x6fffdfff, 0x400000)
+ * +--------------------------+ top_of_ram (0x6fbfdfff)
+ * | Low DRAM Memory |
+ * +--------------------------+ FFFFF (1MB)
+ * | E & F segments |
+ * +--------------------------+ E0000
+ * | C & D segments |
+ * +--------------------------+ C0000
+ * | VGA & SMM Memory |
+ * +--------------------------+ A0000
+ * | Conventional Memory |
+ * | (DOS Range) |
+ * +--------------------------+ 0
+ */
+
+static void mc_add_dram_resources(struct device *dev, int *res_count)
+{
+ struct range_entry fsp_mem;
+ uint64_t base_kb;
+ uint64_t size_kb;
+ uint64_t top_of_ram;
+ uint64_t mc_values[NUM_MAP_ENTRIES];
+ struct resource *resource;
+ int index = *res_count;
+
+ fsp_find_reserved_memory(&fsp_mem);
+
+ /* Read in the MAP registers and report their values. */
+ mc_read_map_entries(dev, &mc_values[0]);
+ mc_report_map_entries(dev, &mc_values[0]);
+
+ top_of_ram = range_entry_base(&fsp_mem) - 1;
+ printk(BIOS_SPEW, "cbmem_top: 0x%lx, fsp range: [0x%llx - 0x%llx], top_of_ram: 0x%llx\n",
+ (uintptr_t) cbmem_top(), range_entry_base(&fsp_mem),
+ range_entry_end(&fsp_mem), top_of_ram);
+
+ /* Conventional Memory (DOS region, 0x0 to 0x9FFFF) */
+ base_kb = 0;
+ size_kb = (0xa0000 >> 10);
+ LOG_MEM_RESOURCE("legacy_ram", dev, index, base_kb, size_kb);
+ ram_resource(dev, index++, base_kb, size_kb);
+
+ /* 1MB -> top_of_ram i.e., fsp_mem_base+1*/
+ base_kb = (0x100000 >> 10);
+ size_kb = (top_of_ram - 0xfffff) >> 10;
+ LOG_MEM_RESOURCE("low_ram", dev, index, base_kb, size_kb);
+ ram_resource(dev, index++, base_kb, size_kb);
+
+ /*
+ * FSP meomoy, CBMem regions are already added as reserved
+ * Add TSEG and MESEG Regions as reserved memory
+ * src/drivers/intel/fsp2_0/memory_init.c sets CBMEM reserved size
+ * arch_upd->BootLoaderTolumSize = cbmem_overhead_size(); == 2 * CBMEM_ROOT_MIN_SIZE
+ * typically 0x2000
+ * Example config:
+ * FSP_RESERVED_MEMORY_RESOURCE_HOB
+ * FspReservedMemoryResource Base : 6FBFE000
+ * FspReservedMemoryResource Size : 400000
+ * FSP_BOOT_LOADER_TOLUM_HOB
+ * FspBootLoaderTolum Base : 6FFFE000
+ * FspBootLoaderTolum Size : 2000
+ */
+
+ /* Mark TSEG/SMM region as reserved */
+ base_kb = (mc_values[TSEG_BASE_REG] >> 10);
+ size_kb = (mc_values[TSEG_LIMIT_REG] - mc_values[TSEG_BASE_REG] + 1) >> 10;
+ LOG_MEM_RESOURCE("mmio_tseg", dev, index, base_kb, size_kb);
+ reserved_ram_resource(dev, index++, base_kb, size_kb);
+
+ /* Mark region between TSEG - TOLM (eg. MESEG) as reserved */
+ if (mc_values[TSEG_LIMIT_REG] < mc_values[TOLM_REG]) {
+ base_kb = ((mc_values[TSEG_LIMIT_REG] + 1) >> 10);
+ size_kb = (mc_values[TOLM_REG] - mc_values[TSEG_LIMIT_REG]) >> 10;
+ LOG_MEM_RESOURCE("mmio_tolm", dev, index, base_kb, size_kb);
+ reserved_ram_resource(dev, index++, base_kb, size_kb);
+ }
+
+ /* 4GiB -> TOHM */
+ if (mc_values[TOHM_REG] > 0x100000000) {
+ base_kb = (0x100000000 >> 10);
+ size_kb = (mc_values[TOHM_REG] - 0x100000000 + 1) >> 10;
+ LOG_MEM_RESOURCE("high_ram", dev, index, base_kb, size_kb);
+ ram_resource(dev, index++, base_kb, size_kb);
+ }
+
+ /* add MMIO CFG resource */
+ resource = new_resource(dev, index++);
+ resource->base = (resource_t) mc_values[MMCFG_BASE_REG];
+ resource->size = (resource_t) (mc_values[MMCFG_LIMIT_REG] -
+ mc_values[MMCFG_BASE_REG] + 1);
+ resource->flags = IORESOURCE_MEM | IORESOURCE_RESERVE |
+ IORESOURCE_FIXED | IORESOURCE_STORED | IORESOURCE_ASSIGNED;
+ LOG_MEM_RESOURCE("mmiocfg_res", dev, index-1, (resource->base >> 10),
+ (resource->size >> 10));
+
+ /* add Local APIC resource */
+ resource = new_resource(dev, index++);
+ resource->base = LAPIC_DEFAULT_BASE;
+ resource->size = 0x00001000;
+ resource->flags = IORESOURCE_MEM | IORESOURCE_RESERVE |
+ IORESOURCE_FIXED | IORESOURCE_STORED | IORESOURCE_ASSIGNED;
+ LOG_MEM_RESOURCE("apic_res", dev, index-1, (resource->base >> 10),
+ (resource->size >> 10));
+
+ /*
+ * Add legacy region as reserved - 0xa000 - 1MB
+ * Reserve everything between A segment and 1MB:
+ *
+ * 0xa0000 - 0xbffff: legacy VGA
+ * 0xc0000 - 0xfffff: RAM
+ */
+ base_kb = VGA_BASE_ADDRESS >> 10;
+ size_kb = VGA_BASE_SIZE >> 10;
+ LOG_MEM_RESOURCE("legacy_mmio", dev, index, base_kb, size_kb);
+ mmio_resource(dev, index++, base_kb, size_kb);
+
+ base_kb = (0xc0000 >> 10);
+ size_kb = (0x100000 - 0xc0000) >> 10;
+ LOG_MEM_RESOURCE("legacy_write_protect", dev, index, base_kb, size_kb);
+ reserved_ram_resource(dev, index++, base_kb, size_kb);
+
+ *res_count = index;
+}
+
+static void mmapvtd_read_resources(struct device *dev)
+{
+ int index = 0;
+
+ /* Read standard PCI resources. */
+ pci_dev_read_resources(dev);
+
+ /* Calculate and add DRAM resources. */
+ mc_add_dram_resources(dev, &index);
+}
+
+static void mmapvtd_init(struct device *dev)
+{
+}
+
+static struct device_operations mmapvtd_ops = {
+ .read_resources = mmapvtd_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = pci_dev_enable_resources,
+ .init = mmapvtd_init,
+ .ops_pci = &soc_pci_ops,
+#if CONFIG(HAVE_ACPI_TABLES)
+ .acpi_inject_dsdt_generator = NULL,
+#endif
+};
+
+static const unsigned short mmapvtd_ids[] = {
+ MMAP_VTD_CFG_REG_DEVID, /* Memory Map/Intel® VT-d Configuration Registers */
+ 0
+};
+
+static const struct pci_driver mmapvtd_driver __pci_driver = {
+ .ops = &mmapvtd_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .devices = mmapvtd_ids
+};
diff --git a/src/soc/intel/xeon_sp/upd_display.c b/src/soc/intel/xeon_sp/upd_display.c
new file mode 100644
index 0000000..2ae34ed
--- /dev/null
+++ b/src/soc/intel/xeon_sp/upd_display.c
@@ -0,0 +1,80 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2019 - 2020 Intel Corporation
+ * Copyright (C) 2019 - 2020 Facebook Inc
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+
+#include <console/console.h>
+#include <fsp/util.h>
+#include <lib.h>
+
+#define DUMP_UPD(old, new, field) \
+ fsp_display_upd_value(#field, sizeof(old->field), old->field, new->field)
+
+/* Display the UPD parameters for MemoryInit */
+void soc_display_fspm_upd_params(
+ const FSPM_UPD *fspm_old_upd,
+ const FSPM_UPD *fspm_new_upd)
+{
+ const FSP_M_CONFIG *new;
+ const FSP_M_CONFIG *old;
+
+ old = &fspm_old_upd->FspmConfig;
+ new = &fspm_new_upd->FspmConfig;
+
+ printk(BIOS_DEBUG, "UPD values for MemoryInit:\n");
+
+ DUMP_UPD(old, new, PcdFspMrcDebugPrintErrorLevel);
+ DUMP_UPD(old, new, PcdFspKtiDebugPrintErrorLevel);
+ DUMP_UPD(old, new, PcdHsuartDevice);
+
+ hexdump(fspm_new_upd, sizeof(*fspm_new_upd));
+}
+
+/* Display the UPD parameters for SiliconInit */
+void soc_display_fsps_upd_params(
+ const FSPS_UPD *fsps_old_upd,
+ const FSPS_UPD *fsps_new_upd)
+{
+ const FSPS_CONFIG *new;
+ const FSPS_CONFIG *old;
+
+ old = &fsps_old_upd->FspsConfig;
+ new = &fsps_new_upd->FspsConfig;
+
+ printk(BIOS_DEBUG, "UPD values for SiliconInit:\n");
+
+ DUMP_UPD(old, new, PcdBifurcationPcie0);
+ DUMP_UPD(old, new, PcdBifurcationPcie1);
+ DUMP_UPD(old, new, PcdActiveCoreCount);
+ DUMP_UPD(old, new, PcdCpuMicrocodePatchBase);
+ DUMP_UPD(old, new, PcdCpuMicrocodePatchSize);
+ DUMP_UPD(old, new, PcdEnablePcie0);
+ DUMP_UPD(old, new, PcdEnablePcie1);
+ DUMP_UPD(old, new, PcdEnableEmmc);
+ DUMP_UPD(old, new, PcdEnableGbE);
+ DUMP_UPD(old, new, PcdFiaMuxConfigRequestPtr);
+ DUMP_UPD(old, new, PcdPcieRootPort0DeEmphasis);
+ DUMP_UPD(old, new, PcdPcieRootPort1DeEmphasis);
+ DUMP_UPD(old, new, PcdPcieRootPort2DeEmphasis);
+ DUMP_UPD(old, new, PcdPcieRootPort3DeEmphasis);
+ DUMP_UPD(old, new, PcdPcieRootPort4DeEmphasis);
+ DUMP_UPD(old, new, PcdPcieRootPort5DeEmphasis);
+ DUMP_UPD(old, new, PcdPcieRootPort6DeEmphasis);
+ DUMP_UPD(old, new, PcdPcieRootPort7DeEmphasis);
+ DUMP_UPD(old, new, PcdEMMCDLLConfigPtr);
+
+ hexdump(fsps_new_upd, sizeof(*fsps_new_upd));
+}