soc/intel/xeon_sp: Add basic Cooperlake-SP support

This adds barebones support.

What works:
* Linux kernel boots fine
* SIRQ and PCH interupts work fine (only in IOAPIC mode)
* PCH devices are usable

What doesn't:
* MP init is not there yet, only 1 CPU is up
* SMM is not supported
* GPIO is not available
* All IIO and extended bus numbers enumeration is not yet available
* Warm reset flow is untested
* MRC cache save/load

TEST=boots into Linux

Signed-off-by: Andrey Petrov <anpetrov@fb.com>
Change-Id: I7c987badc3c53f16ad178369c7e0906d6596e465
Reviewed-on: https://review.coreboot.org/c/coreboot/+/39713
Reviewed-by: Maxim Polyakov <max.senia.poliak@gmail.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
diff --git a/src/soc/intel/xeon_sp/cpx/Kconfig b/src/soc/intel/xeon_sp/cpx/Kconfig
new file mode 100644
index 0000000..70703d0
--- /dev/null
+++ b/src/soc/intel/xeon_sp/cpx/Kconfig
@@ -0,0 +1,78 @@
+##
+## SPDX-License-Identifier: GPL-2.0-only
+## This file is part of the coreboot project.
+##
+
+if SOC_INTEL_COOPERLAKE_SP
+
+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
+	  select FSP_USES_CB_STACK
+
+config FSP_HEADER_PATH
+	  string "Location of FSP headers"
+	  depends on MAINBOARD_USES_FSP2_0
+	  default "src/vendorcode/intel/fsp/fsp2_0/cooperlake_sp"
+
+config MAX_SOCKET
+	int
+	default 2
+
+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.
+
+# currently FSP hardcodes [0fe800000;fe930000] for its heap
+config DCACHE_RAM_BASE
+	hex
+	default 0xfe930000
+
+config DCACHE_RAM_SIZE
+	hex
+	default 0xd0000
+
+config DCACHE_BSP_STACK_SIZE
+	hex
+	default 0x10000
+
+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
+
+config FSP_TEMP_RAM_SIZE
+	hex
+	depends on FSP_USES_CB_STACK
+	default 0x70000
+	help
+	  The amount of anticipated heap usage in CAR by FSP.
+	  Refer to Platform FSP integration guide document to know
+	  the exact FSP requirement for Heap setup.
+
+endif
diff --git a/src/soc/intel/xeon_sp/cpx/Makefile.inc b/src/soc/intel/xeon_sp/cpx/Makefile.inc
new file mode 100644
index 0000000..b909a45
--- /dev/null
+++ b/src/soc/intel/xeon_sp/cpx/Makefile.inc
@@ -0,0 +1,17 @@
+##
+## SPDX-License-Identifier: GPL-2.0-only
+## This file is part of the coreboot project.
+##
+
+ifeq ($(CONFIG_SOC_INTEL_COOPERLAKE_SP),y)
+
+subdirs-y += ../../../../cpu/x86/lapic
+subdirs-y += ../../../../cpu/x86/mtrr
+subdirs-y += ../../../../cpu/x86/tsc
+
+romstage-y += romstage.c
+ramstage-y += chip.c acpi.c
+
+CPPFLAGS_common += -I$(src)/soc/intel/xeon_sp/cpx/include -I$(src)/soc/intel/xeon_sp/cpx
+
+endif ## CONFIG_SOC_INTEL_COOPERLAKE_SP
diff --git a/src/soc/intel/xeon_sp/cpx/acpi.c b/src/soc/intel/xeon_sp/cpx/acpi.c
new file mode 100644
index 0000000..48ad374
--- /dev/null
+++ b/src/soc/intel/xeon_sp/cpx/acpi.c
@@ -0,0 +1,182 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* This file is part of the coreboot project. */
+
+#include <arch/acpigen.h>
+#include <arch/ioapic.h>
+#include <arch/smp/mpspec.h>
+#include <cbmem.h>
+#include <cf9_reset.h>
+#include <console/console.h>
+#include <cpu/x86/smm.h>
+#include <device/pci.h>
+#include <intelblocks/acpi.h>
+#include <soc/iomap.h>
+#include <soc/nvs.h>
+#include <soc/pm.h>
+
+#include "chip.h"
+
+#define SCI_INT_NUM		9
+
+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_fill_mcfg(unsigned long current)
+{
+	current += acpi_create_mcfg_mmconfig((acpi_mcfg_mmconfig_t *)current,
+		CONFIG_MMCONF_BASE_ADDRESS, 0, 0, 255);
+	return current;
+}
+
+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, 0x2000);
+		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();
+	}
+}
+
+void acpi_create_gnvs(struct global_nvs_t *gnvs)
+{
+	config_t *config = config_of_soc();
+	(void) config;
+	/* not implemented yet */
+}
+
+static unsigned long acpi_madt_irq_overrides(unsigned long current)
+{
+	int sci = SCI_INT_NUM;
+	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);
+
+	return current;
+}
+
+unsigned long acpi_fill_madt(unsigned long current)
+{
+	/* Local APICs */
+	current = acpi_create_madt_lapics(current);
+
+	/* IOAPIC */
+	current += acpi_create_madt_ioapic((void *)current, 2, IO_APIC_ADDR, 0);
+
+	return acpi_madt_irq_overrides(current);
+}
+
+int soc_madt_sci_irq_polarity(int sci)
+{
+	if (sci >= 20)
+		return MP_IRQ_POLARITY_LOW;
+	else
+		return MP_IRQ_POLARITY_HIGH;
+}
+
+void acpi_fill_fadt(acpi_fadt_t *fadt)
+{
+
+	const uint16_t pmbase = ACPI_BASE_ADDRESS;
+
+	fadt->header.revision = get_acpi_table_revision(FADT);
+	fadt->sci_int = SCI_INT_NUM;
+
+	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->gpe0_blk = pmbase + GPE0_STS(0);
+
+	fadt->pm1_evt_len = 4;
+	fadt->pm1_cnt_len = 2;
+
+	/* GPE0 STS/EN pairs each 32 bits wide. */
+	fadt->gpe0_blk_len = 2 * GPE0_REG_MAX * sizeof(uint32_t);
+
+	fadt->flush_size = 0x400;	/* twice of cache size */
+	fadt->flush_stride = 0x10;	/* Cache line width  */
+	fadt->duty_offset = 1;
+	fadt->day_alrm = 0xd;
+
+	fadt->flags = ACPI_FADT_WBINVD | ACPI_FADT_C1_SUPPORTED | ACPI_FADT_C2_MP_SUPPORTED |
+			ACPI_FADT_RESET_REGISTER | ACPI_FADT_PLATFORM_CLOCK;
+
+	fadt->reset_reg.space_id = 1;
+	fadt->reset_reg.bit_width = 8;
+	fadt->reset_reg.addrl = RST_CNT;
+	fadt->reset_reg.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
+	fadt->reset_value = RST_CPU | SYS_RST;
+
+	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.addrl = pmbase + PM1_STS;
+
+	fadt->x_pm1b_evt_blk.space_id = 1;
+
+	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.addrl = pmbase + PM1_CNT;
+
+	fadt->x_pm1b_cnt_blk.space_id = 1;
+
+	fadt->x_gpe1_blk.space_id = 1;
+
+	if (CONFIG(HAVE_SMI_HANDLER)) {
+		fadt->smi_cmd = APM_CNT;
+		fadt->acpi_enable = APM_CNT_ACPI_ENABLE;
+		fadt->acpi_disable = APM_CNT_ACPI_DISABLE;
+		fadt->s4bios_req = 0;
+		fadt->pstate_cnt = 0;
+		fadt->cst_cnt = 0;
+	} else {
+		fadt->smi_cmd = 0;
+		fadt->acpi_enable = 0;
+		fadt->acpi_disable = 0;
+		fadt->s4bios_req = 0;
+		fadt->pstate_cnt = 0;
+		fadt->cst_cnt = 0;
+	}
+
+	/*  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 = 0;
+
+	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 = 0;
+	fadt->x_gpe1_blk.addrh = 0;
+}
diff --git a/src/soc/intel/xeon_sp/cpx/acpi/southcluster.asl b/src/soc/intel/xeon_sp/cpx/acpi/southcluster.asl
new file mode 100644
index 0000000..8dfa0a1
--- /dev/null
+++ b/src/soc/intel/xeon_sp/cpx/acpi/southcluster.asl
@@ -0,0 +1,236 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* This file is part of the coreboot project. */
+
+#include <soc/iomap.h>
+
+Name(_HID,EISAID("PNP0A08"))	// PCIe
+Name(_CID,EISAID("PNP0A03"))	// PCI
+
+Name(_BBN, 0)
+
+Name (MCRS, ResourceTemplate() {
+	// Bus Numbers
+	WordBusNumber (ResourceProducer, MinFixed, MaxFixed, PosDecode,
+		0x0000, 0x0000, 0x00fe, 0x0000, 0xff,,, PB00)
+
+	// IO Region 0
+	DWordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
+		0x0000, 0x0000, 0x0cf7, 0x0000, 0x0cf8,,, PI00)
+
+	// PCI Config Space
+	Io (Decode16, 0x0cf8, 0x0cf8, 0x0001, 0x0008)
+
+	// IO Region 1
+	DWordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
+		0x0000, 0x0d00, 0xefff, 0x0000, 0xE300,,, PI01)
+
+	// VGA memory (0xa0000-0xbffff)
+	DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+		Cacheable, ReadWrite,
+		0x00000000, 0x000a0000, 0x000bffff, 0x00000000,
+		0x00020000,,, ASEG)
+
+	// OPROM reserved (0xc0000-0xc3fff)
+	DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+		Cacheable, ReadWrite,
+		0x00000000, 0x000c0000, 0x000c3fff, 0x00000000,
+		0x00004000,,, OPR0)
+
+	// OPROM reserved (0xc4000-0xc7fff)
+	DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+		Cacheable, ReadWrite,
+		0x00000000, 0x000c4000, 0x000c7fff, 0x00000000,
+		0x00004000,,, OPR1)
+
+	// OPROM reserved (0xc8000-0xcbfff)
+	DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+		Cacheable, ReadWrite,
+		0x00000000, 0x000c8000, 0x000cbfff, 0x00000000,
+		0x00004000,,, OPR2)
+
+	// OPROM reserved (0xcc000-0xcffff)
+	DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+		Cacheable, ReadWrite,
+		0x00000000, 0x000cc000, 0x000cffff, 0x00000000,
+		0x00004000,,, OPR3)
+
+	// OPROM reserved (0xd0000-0xd3fff)
+	DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+		Cacheable, ReadWrite,
+		0x00000000, 0x000d0000, 0x000d3fff, 0x00000000,
+		0x00004000,,, OPR4)
+
+	// OPROM reserved (0xd4000-0xd7fff)
+	DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+		Cacheable, ReadWrite,
+		0x00000000, 0x000d4000, 0x000d7fff, 0x00000000,
+		0x00004000,,, OPR5)
+
+	// OPROM reserved (0xd8000-0xdbfff)
+	DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+		Cacheable, ReadWrite,
+		0x00000000, 0x000d8000, 0x000dbfff, 0x00000000,
+		0x00004000,,, OPR6)
+
+	// OPROM reserved (0xdc000-0xdffff)
+	DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+		Cacheable, ReadWrite,
+		0x00000000, 0x000dc000, 0x000dffff, 0x00000000,
+		0x00004000,,, OPR7)
+
+	// BIOS Extension (0xe0000-0xe3fff)
+	DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+		Cacheable, ReadWrite,
+		0x00000000, 0x000e0000, 0x000e3fff, 0x00000000,
+		0x00004000,,, ESG0)
+
+	// BIOS Extension (0xe4000-0xe7fff)
+	DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+		Cacheable, ReadWrite,
+		0x00000000, 0x000e4000, 0x000e7fff, 0x00000000,
+		0x00004000,,, ESG1)
+
+	// BIOS Extension (0xe8000-0xebfff)
+	DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+		Cacheable, ReadWrite,
+		0x00000000, 0x000e8000, 0x000ebfff, 0x00000000,
+		0x00004000,,, ESG2)
+
+	// BIOS Extension (0xec000-0xeffff)
+	DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+		Cacheable, ReadWrite,
+		0x00000000, 0x000ec000, 0x000effff, 0x00000000,
+		0x00004000,,, ESG3)
+
+	// System BIOS (0xf0000-0xfffff)
+	DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+		Cacheable, ReadWrite,
+		0x00000000, 0x000f0000, 0x000fffff, 0x00000000,
+		0x00010000,,, FSEG)
+
+	// PCI Memory Region (Top of memory-0xfeafffff)
+	DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+		Cacheable, ReadWrite,
+		0x00000000, 0x90000000, 0xFEAFFFFF, 0x00000000,
+		0x6EB00000,,, PMEM)
+
+	DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+		Cacheable, ReadWrite,
+		0x00000000, 0xfec00000, 0xfecfffff, 0x00000000,
+		0x00100000,,, APIC)
+
+	DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+		Cacheable, ReadWrite,
+		0x00000000, 0xfed00000, 0xfedfffff, 0x00000000,
+		0x00100000,,, PCHR)
+
+	QWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, NonCacheable, ReadWrite,
+		0x0000000000000000, // Granularity
+		0x0000380000000000, // Range Minimum
+		0x0000383FFFFFFFFF, // Range Maximum
+		0x0000000000000000, // Translation Offset
+		0x0000004000000000, // Length
+		,,, AddressRangeMemory, TypeStatic)
+})
+
+Method (_CRS, 0, Serialized) {
+	Return (MCRS)
+}
+
+Method (_OSC, 4) {
+	/* Check for proper GUID */
+	If (LEqual (Arg0, ToUUID("33DB4D5B-1FF7-401C-9657-7441C03DD766")))
+	{
+		/* Let OS control everything */
+		Return (Arg3)
+	}
+	Else
+	{
+		/* Unrecognized UUID */
+		CreateDWordField (Arg3, 0, CDW1)
+		Or (CDW1, 4, CDW1)
+		Return (Arg3)
+	}
+}
+
+
+Name (AR00, Package() {
+	// [DMI0]: Legacy PCI Express Port 0 on PCI0
+	Package() { 0x0000FFFF, 0, 0, 47 },
+	// [BR1A]: PCI Express Port 1A on PCI0
+	// [BR1B]: PCI Express Port 1B on PCI0
+	Package() { 0x0001FFFF, 0, 0, 47 },
+	// [BR2A]: PCI Express Port 2A on PCI0
+	// [BR2B]: PCI Express Port 2B on PCI0
+	// [BR2C]: PCI Express Port 2C on PCI0
+	// [BR2D]: PCI Express Port 2D on PCI0
+	Package() { 0x0002FFFF, 0, 0, 47 },
+	// [BR3A]: PCI Express Port 3A on PCI0
+	// [BR3B]: PCI Express Port 3B on PCI0
+	// [BR3C]: PCI Express Port 3C on PCI0
+	// [BR3D]: PCI Express Port 3D on PCI0
+	Package() { 0x0003FFFF, 0, 0, 47 },
+	// [CB0A]: CB3DMA on PCI0
+	// [CB0E]: CB3DMA on PCI0
+	Package() { 0x0004FFFF, 0, 0, 31 },
+	// [CB0B]: CB3DMA on PCI0
+	// [CB0F]: CB3DMA on PCI0
+	Package() { 0x0004FFFF, 1, 0, 39 },
+	// [CB0C]: CB3DMA on PCI0
+	// [CB0G]: CB3DMA on PCI0
+	Package() { 0x0004FFFF, 2, 0, 31 },
+	// [CB0D]: CB3DMA on PCI0
+	// [CB0H]: CB3DMA on PCI0
+	Package() { 0x0004FFFF, 3, 0, 39 },
+	// [IIM0]: IIOMISC on PCI0
+	Package() { 0x0005FFFF, 0, 0, 16 },
+	Package() { 0x0005FFFF, 1, 0, 17 },
+	Package() { 0x0005FFFF, 2, 0, 18 },
+	Package() { 0x0005FFFF, 3, 0, 19 },
+	// [IID0]: IIODFX0 on PCI0
+	Package() { 0x0006FFFF, 0, 0, 16 },
+	Package() { 0x0006FFFF, 1, 0, 17 },
+	Package() { 0x0006FFFF, 2, 0, 18 },
+	Package() { 0x0006FFFF, 3, 0, 19 },
+	// [XHCI]: xHCI controller 1 on PCH
+	Package() { 0x0014FFFF, 3, 0, 19 },
+	// [HECI]: ME HECI on PCH
+	// [IDER]: ME IDE redirect on PCH
+	Package() { 0x0016FFFF, 0, 0, 16 },
+	// [HEC2]: ME HECI2 on PCH
+	// [MEKT]: MEKT on PCH
+	Package() { 0x0016FFFF, 1, 0, 17 },
+	// [GBEM]: GbE Controller VPRO
+	Package() { 0x0019FFFF, 0, 0, 20 },
+	// [EHC2]: EHCI controller #2 on PCH
+	Package() { 0x001AFFFF, 2, 0, 18 },
+	// [ALZA]: High definition Audio Controller
+	Package() { 0x001BFFFF, 0, 0, 22 },
+	// [RP01]: Pci Express Port 1 on PCH
+	// [RP05]: Pci Express Port 5 on PCH
+	Package() { 0x001CFFFF, 0, 0, 16 },
+	// [RP02]: Pci Express Port 2 on PCH
+	// [RP06]: Pci Express Port 6 on PCH
+	Package() { 0x001CFFFF, 1, 0, 17 },
+	// [RP03]: Pci Express Port 3 on PCH
+	// [RP07]: Pci Express Port 7 on PCH
+	Package() { 0x001CFFFF, 2, 0, 18 },
+	// [RP04]: Pci Express Port 4 on PCH
+	// [RP08]: Pci Express Port 8 on ICH
+	Package() { 0x001CFFFF, 3, 0, 19 },
+	// [EHC1]: EHCI controller #1 on PCH
+	Package() { 0x001DFFFF, 2, 0, 18 },
+	// [SAT1]: SATA controller 1 on PCH
+	// [SAT2]: SATA Host controller 2 on PCH
+	Package() { 0x001FFFFF, 0, 0, 16 },
+	// [SMBS]: SMBus controller on PCH
+	// [TERM]: Thermal Subsystem on ICH
+	Package() { 0x001FFFFF, 2, 0, 18 },
+	Package() { 0x0017FFFF, 0, 0, 20 },
+	Package() { 0x0011FFFF, 0, 0, 21 },
+})
+
+// Socket 0 Root bridge
+Method (_PRT, 0) {
+	Return (AR00)
+}
diff --git a/src/soc/intel/xeon_sp/cpx/chip.c b/src/soc/intel/xeon_sp/cpx/chip.c
new file mode 100644
index 0000000..dbbf3b3
--- /dev/null
+++ b/src/soc/intel/xeon_sp/cpx/chip.c
@@ -0,0 +1,98 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* This file is part of the coreboot project. */
+
+#include <arch/ioapic.h>
+#include <cbfs.h>
+#include <console/console.h>
+#include <cpu/x86/lapic.h>
+#include <device/pci.h>
+#include <fsp/api.h>
+#include <soc/ramstage.h>
+#include <soc/pm.h>
+
+/* C620 IOAPIC has 120 redirection entries */
+#define C620_IOAPIC_REDIR_ENTRIES		120
+
+static void pci_domain_set_resources(struct device *dev)
+{
+	assign_resources(dev->link_list);
+}
+
+void platform_fsp_silicon_init_params_cb(FSPS_UPD *silupd)
+{
+	/* not implemented yet */
+}
+
+static struct device_operations pci_domain_ops = {
+	.read_resources = &pci_domain_read_resources,
+	.set_resources = &pci_domain_set_resources,
+	.scan_bus = &pci_domain_scan_bus,
+};
+
+static void init_cpus(struct device *dev)
+{
+	/* not implemented yet */
+}
+
+static struct device_operations cpu_bus_ops = {
+	.read_resources = DEVICE_NOOP,
+	.set_resources = DEVICE_NOOP,
+	.enable_resources = DEVICE_NOOP,
+	.init = init_cpus,
+	.scan_bus = NULL,
+};
+
+static void chip_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;
+	} else if (dev->path.type == DEVICE_PATH_CPU_CLUSTER) {
+		dev->ops = &cpu_bus_ops;
+	}
+}
+
+static void pch_enable_ioapic(const struct device *dev)
+{
+	uint32_t reg32;
+
+	set_ioapic_id((void *)IO_APIC_ADDR, 2);
+
+	/* affirm full set of redirection table entries ("write once") */
+	reg32 = io_apic_read((void *)IO_APIC_ADDR, 1);
+
+	reg32 &= ~0x00ff0000;
+	reg32 |= (C620_IOAPIC_REDIR_ENTRIES - 1) << 16;
+
+	io_apic_write((void *)IO_APIC_ADDR, 1, reg32);
+
+	/*
+	 * Select Boot Configuration register (0x03) and
+	 * use Processor System Bus (0x01) to deliver interrupts.
+	 */
+	io_apic_write((void *)IO_APIC_ADDR, 3, 1);
+}
+
+struct pci_operations soc_pci_ops = {
+	.set_subsystem = pci_dev_set_subsystem,
+};
+
+static void chip_final(void *data)
+{
+	/* nothing implemented yet */
+}
+
+static void chip_init(void *data)
+{
+	printk(BIOS_DEBUG, "coreboot: calling fsp_silicon_init\n");
+	fsp_silicon_init(false);
+	pch_enable_ioapic(NULL);
+	setup_lapic();
+}
+
+struct chip_operations soc_intel_xeon_sp_cpx_ops = {
+	CHIP_NAME("Intel Cooperlake-SP")
+	.enable_dev = chip_enable_dev,
+	.init = chip_init,
+	.final = chip_final
+};
diff --git a/src/soc/intel/xeon_sp/cpx/chip.h b/src/soc/intel/xeon_sp/cpx/chip.h
new file mode 100644
index 0000000..d86b8e7
--- /dev/null
+++ b/src/soc/intel/xeon_sp/cpx/chip.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* This file is part of the coreboot project. */
+
+#ifndef _SOC_CHIP_H_
+#define _SOC_CHIP_H_
+
+#include <stdint.h>
+#include <intelblocks/cfg.h>
+
+struct soc_intel_xeon_sp_cpx_config {
+	/* Common struct containing soc config data required by common code */
+	struct soc_intel_common_config common_soc_config;
+
+	/* Generic IO decode ranges */
+	uint32_t gen1_dec;
+	uint32_t gen2_dec;
+	uint32_t gen3_dec;
+	uint32_t gen4_dec;
+};
+
+extern struct chip_operations soc_intel_xeon_sp_cpx_ops;
+
+typedef struct soc_intel_xeon_sp_cpx_config config_t;
+
+#endif
diff --git a/src/soc/intel/xeon_sp/cpx/include/soc/cpu.h b/src/soc/intel/xeon_sp/cpx/include/soc/cpu.h
new file mode 100644
index 0000000..f33df89
--- /dev/null
+++ b/src/soc/intel/xeon_sp/cpx/include/soc/cpu.h
@@ -0,0 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* This file is part of the coreboot project. */
+
+/* nothing here yet */
diff --git a/src/soc/intel/xeon_sp/cpx/include/soc/gpio.h b/src/soc/intel/xeon_sp/cpx/include/soc/gpio.h
new file mode 100644
index 0000000..36e1a70
--- /dev/null
+++ b/src/soc/intel/xeon_sp/cpx/include/soc/gpio.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* This file is part of the coreboot project. */
+
+/* not implemented, adding defaults just to make common code happy */
+
+#ifndef _SOC_GPIO_H_
+#define _SOC_GPIO_H
+
+#define GPIO_NUM_PAD_CFG_REGS		0
+#define NUM_GPI_STATUS_REGS		0
+
+#endif
diff --git a/src/soc/intel/xeon_sp/cpx/include/soc/irq.h b/src/soc/intel/xeon_sp/cpx/include/soc/irq.h
new file mode 100644
index 0000000..14dd852
--- /dev/null
+++ b/src/soc/intel/xeon_sp/cpx/include/soc/irq.h
@@ -0,0 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* This file is part of the coreboot project. */
+
+/* nothing here, please come back later */
diff --git a/src/soc/intel/xeon_sp/cpx/include/soc/nvs.h b/src/soc/intel/xeon_sp/cpx/include/soc/nvs.h
new file mode 100644
index 0000000..352bc27
--- /dev/null
+++ b/src/soc/intel/xeon_sp/cpx/include/soc/nvs.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* This file is part of the coreboot project. */
+
+#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/cpx/include/soc/pci_devs.h b/src/soc/intel/xeon_sp/cpx/include/soc/pci_devs.h
new file mode 100644
index 0000000..1154527
--- /dev/null
+++ b/src/soc/intel/xeon_sp/cpx/include/soc/pci_devs.h
@@ -0,0 +1,64 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* This file is part of the coreboot project. */
+
+#ifndef _SOC_PCI_DEVS_H_
+#define _SOC_PCI_DEVS_H_
+
+#include <device/pci_def.h>
+
+#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 SAD_ALL_DEV			29
+#define SAD_ALL_FUNC			0
+#define SAD_ALL_PAM0123_CSR		0x40
+#define SAD_ALL_PAM456_CSR		0x44
+
+#define UBOX_DECS_BUS			0
+#define UBOX_DECS_DEV			8
+#define UBOX_DECS_FUNC			2
+#define UBOX_DECS_CPUBUSNO_CSR		0xcc
+
+#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 MMAP_VTD_CFG_REG_DEVID		0x2024
+#define VTD_DEV				5
+#define VTD_FUNC			0
+
+
+
+#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/cpx/include/soc/ramstage.h b/src/soc/intel/xeon_sp/cpx/include/soc/ramstage.h
new file mode 100644
index 0000000..28e8d1a
--- /dev/null
+++ b/src/soc/intel/xeon_sp/cpx/include/soc/ramstage.h
@@ -0,0 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* This file is part of the coreboot project. */
+
+#include <device/device.h>
+
+extern struct pci_operations soc_pci_ops;
diff --git a/src/soc/intel/xeon_sp/cpx/romstage.c b/src/soc/intel/xeon_sp/cpx/romstage.c
new file mode 100644
index 0000000..32ada9f
--- /dev/null
+++ b/src/soc/intel/xeon_sp/cpx/romstage.c
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* This file is part of the coreboot project. */
+
+#include <arch/romstage.h>
+#include <fsp/api.h>
+#include "chip.h"
+
+void platform_fsp_memory_init_params_cb(FSPM_UPD *mupd, uint32_t version)
+{
+	FSP_M_CONFIG *m_cfg = &mupd->FspmConfig;
+
+	(void)m_cfg;
+}