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, &microcode_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));
+}