soc/intel/elkhartlake: Do initial SoC commit till ramstage

Clone entirely from Jasperlake

List of changes on top off initial jasperlake clone
1. Replace "Jasperlake" with "Elkhartlake"
2. Replace "jsl" with "ehl"
3. Replace "jsp" with "mcc"
4. Rename structure based on Jasperlake with Elkhartlake
5. Clean up upd override in fsp_params.c will be added later
6. Sort #include files alphabetically as per comment
7. Remove doc details from espi.c until it is ready
8. Remove pch_isclk & camera clocks related codes
9. Add new #define NMI_STS_CNT & NMI_EN as per comment

Signed-off-by: Tan, Lean Sheng <lean.sheng.tan@intel.com>
Change-Id: I372b0bb5912e013445ed8df7c58d0a9ee9a7cf35
Reviewed-on: https://review.coreboot.org/c/coreboot/+/44802
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Werner Zeh <werner.zeh@siemens.com>
diff --git a/src/soc/intel/elkhartlake/Kconfig b/src/soc/intel/elkhartlake/Kconfig
new file mode 100644
index 0000000..166bda0
--- /dev/null
+++ b/src/soc/intel/elkhartlake/Kconfig
@@ -0,0 +1,213 @@
+config SOC_INTEL_ELKHARTLAKE
+	bool
+	help
+	  Intel Elkhartlake support
+
+if SOC_INTEL_ELKHARTLAKE
+
+config CPU_SPECIFIC_OPTIONS
+	def_bool y
+	select ACPI_INTEL_HARDWARE_SLEEP_VALUES
+	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 CACHE_MRC_SETTINGS
+	select CPU_INTEL_COMMON
+	select CPU_INTEL_FIRMWARE_INTERFACE_TABLE
+	select FSP_COMPRESS_FSP_S_LZ4
+	select FSP_M_XIP
+	select GENERIC_GPIO_LIB
+	select HAVE_FSP_GOP
+	select INTEL_DESCRIPTOR_MODE_CAPABLE
+	select HAVE_SMI_HANDLER
+	select IDT_IN_EVERY_STAGE
+	select INTEL_CAR_NEM #TODO - Enable INTEL_CAR_NEM_ENHANCED
+	select INTEL_GMA_ACPI
+	select INTEL_GMA_ADD_VBT if RUN_FSP_GOP
+	select IOAPIC
+	select MRC_SETTINGS_PROTECT
+	select PARALLEL_MP
+	select PARALLEL_MP_AP_WORK
+	select MICROCODE_BLOB_UNDISCLOSED
+	select PLATFORM_USES_FSP2_2
+	select FSP_PEIM_TO_PEIM_INTERFACE
+	select REG_SCRIPT
+	select PMC_GLOBAL_RESET_ENABLE_LOCK
+	select CPU_INTEL_COMMON_SMM
+	select SOC_INTEL_COMMON
+	select SOC_INTEL_COMMON_ACPI_WAKE_SOURCE
+	select SOC_INTEL_COMMON_BLOCK
+	select SOC_INTEL_COMMON_BLOCK_ACPI
+	select SOC_INTEL_COMMON_BLOCK_CHIP_CONFIG
+	select SOC_INTEL_COMMON_BLOCK_CPU
+	select SOC_INTEL_COMMON_BLOCK_CPU_MPINIT
+	select SOC_INTEL_COMMON_BLOCK_GPIO_DUAL_ROUTE_SUPPORT
+	select SOC_INTEL_COMMON_BLOCK_GSPI_VERSION_2
+	select SOC_INTEL_COMMON_BLOCK_HDA
+	select SOC_INTEL_COMMON_BLOCK_SA
+	select SOC_INTEL_COMMON_BLOCK_SCS
+	select SOC_INTEL_COMMON_BLOCK_SMM
+	select SOC_INTEL_COMMON_BLOCK_POWER_LIMIT
+	select SOC_INTEL_COMMON_BLOCK_SMM_IO_TRAP
+	select SOC_INTEL_COMMON_PCH_BASE
+	select SOC_INTEL_COMMON_RESET
+	select SOC_INTEL_COMMON_BLOCK_CAR
+	select SSE2
+	select SUPPORT_CPU_UCODE_IN_CBFS
+	select TSC_MONOTONIC_TIMER
+	select UDELAY_TSC
+	select UDK_202005_BINDING
+	select DISPLAY_FSP_VERSION_INFO
+	select HECI_DISABLE_USING_SMM
+
+config DCACHE_RAM_BASE
+	default 0xfef00000
+
+config DCACHE_RAM_SIZE
+	default 0x80000
+	help
+	  The size of the cache-as-ram region required during bootblock
+	  and/or romstage.
+
+config DCACHE_BSP_STACK_SIZE
+	hex
+	default 0x30400
+	help
+	  The amount of anticipated stack usage in CAR by bootblock and
+	  other stages. In the case of FSP_USES_CB_STACK default value
+	  will be sum of FSP-M stack requirement(192 KiB) and CB romstage
+	  stack requirement(~1KiB).
+
+config FSP_TEMP_RAM_SIZE
+	hex
+	default 0x20000
+	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.
+
+config IFD_CHIPSET
+	string
+	default "ehl"
+
+config IED_REGION_SIZE
+	hex
+	default 0x400000
+
+config HEAP_SIZE
+	hex
+	default 0x8000
+
+config MAX_ROOT_PORTS
+	int
+	default 8
+
+config MAX_PCIE_CLOCKS
+	int
+	default 6
+
+config SMM_TSEG_SIZE
+	hex
+	default 0x800000
+
+config SMM_RESERVED_SIZE
+	hex
+	default 0x200000
+
+config PCR_BASE_ADDRESS
+	hex
+	default 0xfd000000
+	help
+	  This option allows you to select MMIO Base Address of sideband bus.
+
+config MMCONF_BASE_ADDRESS
+	hex
+	default 0xc0000000
+
+config CPU_BCLK_MHZ
+	int
+	default 100
+
+config SOC_INTEL_COMMON_BLOCK_GSPI_CLOCK_MHZ
+	int
+	default 120
+
+config DRIVERS_I2C_DESIGNWARE_CLOCK_MHZ
+	int
+	default 133
+
+config SOC_INTEL_COMMON_BLOCK_GSPI_MAX
+	int
+	default 3
+
+config SOC_INTEL_I2C_DEV_MAX
+	int
+	default 6
+
+config SOC_INTEL_UART_DEV_MAX
+	int
+	default 3
+
+config CONSOLE_UART_BASE_ADDRESS
+	hex
+	default 0xfe032000
+	depends on INTEL_LPSS_UART_FOR_CONSOLE
+
+# Clock divider parameters for 115200 baud rate
+# Baudrate = (UART source clcok * M) /(N *16)
+# EHL UART source clock: 100MHz
+config SOC_INTEL_COMMON_LPSS_UART_CLK_M_VAL
+	hex
+	default 0x30
+
+config SOC_INTEL_COMMON_LPSS_UART_CLK_N_VAL
+	hex
+	default 0xc35
+
+config CHROMEOS
+	select CHROMEOS_RAMOOPS_DYNAMIC
+
+config VBOOT
+	select VBOOT_SEPARATE_VERSTAGE
+	select VBOOT_MUST_REQUEST_DISPLAY
+	select VBOOT_STARTS_IN_BOOTBLOCK
+	select VBOOT_VBNV_CMOS
+	select VBOOT_VBNV_CMOS_BACKUP_TO_FLASH
+
+config C_ENV_BOOTBLOCK_SIZE
+	hex
+	default 0xC000
+
+config CBFS_SIZE
+	hex
+	default 0x200000
+
+config FSP_HEADER_PATH
+	default "src/vendorcode/intel/fsp/fsp2_0/elkhartlake/"
+
+config FSP_FD_PATH
+	default "3rdparty/fsp/ElkhartLakeFspBinPkg/Fsp.fd"
+
+config SOC_INTEL_ELKHARTLAKE_DEBUG_CONSENT
+	int "Debug Consent for EHL"
+	# USB DBC is more common for developers so make this default to 3 if
+	# SOC_INTEL_DEBUG_CONSENT=y
+	default 3 if SOC_INTEL_DEBUG_CONSENT
+	default 0
+	help
+	  This is to control debug interface on SOC.
+	  Setting non-zero value will allow to use DBC or DCI to debug SOC.
+	  PlatformDebugConsent in FspmUpd.h has the details.
+
+	  Desired platform debug type are
+	  0:Disabled, 1:Enabled (DCI OOB+[DbC]), 2:Enabled (DCI OOB),
+	  3:Enabled (USB3 DbC), 4:Enabled (XDP/MIPI60), 5:Enabled (USB2 DbC),
+	  6:Enable (2-wire DCI OOB), 7:Manual
+
+config PRERAM_CBMEM_CONSOLE_SIZE
+	hex
+	default 0x1400
+endif
diff --git a/src/soc/intel/elkhartlake/Makefile.inc b/src/soc/intel/elkhartlake/Makefile.inc
new file mode 100644
index 0000000..5c46f86
--- /dev/null
+++ b/src/soc/intel/elkhartlake/Makefile.inc
@@ -0,0 +1,60 @@
+ifeq ($(CONFIG_SOC_INTEL_ELKHARTLAKE),y)
+
+subdirs-y += romstage
+subdirs-y += ../../../cpu/intel/microcode
+subdirs-y += ../../../cpu/intel/turbo
+subdirs-y += ../../../cpu/x86/lapic
+subdirs-y += ../../../cpu/x86/mtrr
+subdirs-y += ../../../cpu/x86/smm
+subdirs-y += ../../../cpu/x86/tsc
+
+# all (bootblock, verstage, romstage, postcar, ramstage)
+all-y += gspi.c
+all-y += i2c.c
+all-y += pmutil.c
+all-y += spi.c
+all-y += uart.c
+
+bootblock-y += bootblock/bootblock.c
+bootblock-y += bootblock/cpu.c
+bootblock-y += bootblock/pch.c
+bootblock-y += bootblock/report_platform.c
+bootblock-y += espi.c
+bootblock-y += gpio.c
+bootblock-y += p2sb.c
+
+romstage-y += espi.c
+romstage-y += gpio.c
+romstage-y += meminit.c
+romstage-y += reset.c
+
+ramstage-y += acpi.c
+ramstage-y += chip.c
+ramstage-y += cpu.c
+ramstage-y += elog.c
+ramstage-y += espi.c
+ramstage-y += finalize.c
+ramstage-y += fsp_params.c
+ramstage-y += gpio.c
+ramstage-y += lockdown.c
+ramstage-y += p2sb.c
+ramstage-y += pmc.c
+ramstage-y += reset.c
+ramstage-y += smmrelocate.c
+ramstage-y += systemagent.c
+ramstage-y += sd.c
+ramstage-y += me.c
+
+smm-y += gpio.c
+smm-y += p2sb.c
+smm-y += pmc.c
+smm-y += pmutil.c
+smm-y += smihandler.c
+smm-y += uart.c
+
+verstage-y += gpio.c
+
+CPPFLAGS_common += -I$(src)/soc/intel/elkhartlake
+CPPFLAGS_common += -I$(src)/soc/intel/elkhartlake/include
+
+endif
diff --git a/src/soc/intel/elkhartlake/acpi.c b/src/soc/intel/elkhartlake/acpi.c
new file mode 100644
index 0000000..af837ab
--- /dev/null
+++ b/src/soc/intel/elkhartlake/acpi.c
@@ -0,0 +1,343 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <acpi/acpi.h>
+#include <acpi/acpi_gnvs.h>
+#include <acpi/acpigen.h>
+#include <arch/smp/mpspec.h>
+#include <cbmem.h>
+#include <console/console.h>
+#include <device/device.h>
+#include <device/mmio.h>
+#include <device/pci_ops.h>
+#include <ec/google/chromeec/ec.h>
+#include <intelblocks/acpi.h>
+#include <intelblocks/cpulib.h>
+#include <intelblocks/pmclib.h>
+#include <soc/cpu.h>
+#include <soc/iomap.h>
+#include <soc/nvs.h>
+#include <soc/pci_devs.h>
+#include <soc/pm.h>
+#include <soc/soc_chip.h>
+#include <soc/systemagent.h>
+#include <string.h>
+#include <wrdd.h>
+
+/*
+ * List of supported C-states in this processor.
+ */
+enum {
+	C_STATE_C0,		/* 0 */
+	C_STATE_C1,		/* 1 */
+	C_STATE_C1E,		/* 2 */
+	C_STATE_C6_SHORT_LAT,	/* 3 */
+	C_STATE_C6_LONG_LAT,	/* 4 */
+	C_STATE_C7_SHORT_LAT,	/* 5 */
+	C_STATE_C7_LONG_LAT,	/* 6 */
+	C_STATE_C7S_SHORT_LAT,	/* 7 */
+	C_STATE_C7S_LONG_LAT,	/* 8 */
+	C_STATE_C8,		/* 9 */
+	C_STATE_C9,		/* 10 */
+	C_STATE_C10,		/* 11 */
+	NUM_C_STATES
+};
+
+#define MWAIT_RES(state, sub_state)				\
+	{							\
+		.addrl = (((state) << 4) | (sub_state)),	\
+		.space_id = ACPI_ADDRESS_SPACE_FIXED,		\
+		.bit_width = ACPI_FFIXEDHW_VENDOR_INTEL,	\
+		.bit_offset = ACPI_FFIXEDHW_CLASS_MWAIT,	\
+		.access_size = ACPI_FFIXEDHW_FLAG_HW_COORD,	\
+	}
+
+static const acpi_cstate_t cstate_map[NUM_C_STATES] = {
+	[C_STATE_C0] = {},
+	[C_STATE_C1] = {
+		.latency = C1_LATENCY,
+		.power = C1_POWER,
+		.resource = MWAIT_RES(0, 0),
+	},
+	[C_STATE_C1E] = {
+		.latency = C1_LATENCY,
+		.power = C1_POWER,
+		.resource = MWAIT_RES(0, 1),
+	},
+	[C_STATE_C6_SHORT_LAT] = {
+		.latency = C6_LATENCY,
+		.power = C6_POWER,
+		.resource = MWAIT_RES(2, 0),
+	},
+	[C_STATE_C6_LONG_LAT] = {
+		.latency = C6_LATENCY,
+		.power = C6_POWER,
+		.resource = MWAIT_RES(2, 1),
+	},
+	[C_STATE_C7_SHORT_LAT] = {
+		.latency = C7_LATENCY,
+		.power = C7_POWER,
+		.resource = MWAIT_RES(3, 0),
+	},
+	[C_STATE_C7_LONG_LAT] = {
+		.latency = C7_LATENCY,
+		.power = C7_POWER,
+		.resource = MWAIT_RES(3, 1),
+	},
+	[C_STATE_C7S_SHORT_LAT] = {
+		.latency = C7_LATENCY,
+		.power = C7_POWER,
+		.resource = MWAIT_RES(3, 2),
+	},
+	[C_STATE_C7S_LONG_LAT] = {
+		.latency = C7_LATENCY,
+		.power = C7_POWER,
+		.resource = MWAIT_RES(3, 3),
+	},
+	[C_STATE_C8] = {
+		.latency = C8_LATENCY,
+		.power = C8_POWER,
+		.resource = MWAIT_RES(4, 0),
+	},
+	[C_STATE_C9] = {
+		.latency = C9_LATENCY,
+		.power = C9_POWER,
+		.resource = MWAIT_RES(5, 0),
+	},
+	[C_STATE_C10] = {
+		.latency = C10_LATENCY,
+		.power = C10_POWER,
+		.resource = MWAIT_RES(6, 0),
+	},
+};
+
+static int cstate_set_non_s0ix[] = {
+	C_STATE_C1,
+	C_STATE_C6_LONG_LAT,
+	C_STATE_C7S_LONG_LAT
+};
+
+static int cstate_set_s0ix[] = {
+	C_STATE_C1,
+	C_STATE_C7S_LONG_LAT,
+	C_STATE_C10
+};
+
+acpi_cstate_t *soc_get_cstate_map(size_t *entries)
+{
+	static acpi_cstate_t map[MAX(ARRAY_SIZE(cstate_set_s0ix),
+				ARRAY_SIZE(cstate_set_non_s0ix))];
+	int *set;
+	int i;
+
+	config_t *config = config_of_soc();
+
+	int is_s0ix_enable = config->s0ix_enable;
+
+	if (is_s0ix_enable) {
+		*entries = ARRAY_SIZE(cstate_set_s0ix);
+		set = cstate_set_s0ix;
+	} else {
+		*entries = ARRAY_SIZE(cstate_set_non_s0ix);
+		set = cstate_set_non_s0ix;
+	}
+
+	for (i = 0; i < *entries; i++) {
+		memcpy(&map[i], &cstate_map[set[i]], sizeof(acpi_cstate_t));
+		map[i].ctype = i + 1;
+	}
+	return map;
+}
+
+void soc_power_states_generation(int core_id, int cores_per_package)
+{
+	config_t *config = config_of_soc();
+
+	if (config->eist_enable)
+		/* Generate P-state tables */
+		generate_p_state_entries(core_id, cores_per_package);
+}
+
+void soc_fill_fadt(acpi_fadt_t *fadt)
+{
+	const uint16_t pmbase = ACPI_BASE_ADDRESS;
+
+	config_t *config = config_of_soc();
+
+	fadt->pm_tmr_blk = pmbase + PM1_TMR;
+	fadt->pm_tmr_len = 4;
+	fadt->x_pm_tmr_blk.space_id = ACPI_ADDRESS_SPACE_IO;
+	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 = ACPI_ACCESS_SIZE_UNDEFINED;
+	fadt->x_pm_tmr_blk.addrl = pmbase + PM1_TMR;
+	fadt->x_pm_tmr_blk.addrh = 0x0;
+
+	if (config->s0ix_enable)
+		fadt->flags |= ACPI_FADT_LOW_PWR_IDLE_S0;
+}
+
+uint32_t soc_read_sci_irq_select(void)
+{
+	uintptr_t pmc_bar = soc_read_pmc_base();
+	return read32((void *)pmc_bar + IRQ_REG);
+}
+
+static unsigned long soc_fill_dmar(unsigned long current)
+{
+	const struct device *const igfx_dev = pcidev_path_on_root(SA_DEVFN_IGD);
+	uint64_t gfxvtbar = MCHBAR64(GFXVTBAR) & VTBAR_MASK;
+	bool gfxvten = MCHBAR32(GFXVTBAR) & VTBAR_ENABLED;
+
+	if (is_dev_enabled(igfx_dev) && gfxvtbar && gfxvten) {
+		unsigned long tmp = current;
+
+		current += acpi_create_dmar_drhd(current, 0, 0, gfxvtbar);
+		current += acpi_create_dmar_ds_pci(current, 0, 2, 0);
+
+		acpi_dmar_drhd_fixup(tmp, current);
+	}
+
+	uint64_t vtvc0bar = MCHBAR64(VTVC0BAR) & VTBAR_MASK;
+	bool vtvc0en = MCHBAR32(VTVC0BAR) & VTBAR_ENABLED;
+
+	if (vtvc0bar && vtvc0en) {
+		const unsigned long tmp = current;
+
+		current += acpi_create_dmar_drhd(current,
+				DRHD_INCLUDE_PCI_ALL, 0, vtvc0bar);
+		current += acpi_create_dmar_ds_ioapic(current,
+				2, V_P2SB_CFG_IBDF_BUS, V_P2SB_CFG_IBDF_DEV,
+				V_P2SB_CFG_IBDF_FUNC);
+		current += acpi_create_dmar_ds_msi_hpet(current,
+				0, V_P2SB_CFG_HBDF_BUS, V_P2SB_CFG_HBDF_DEV,
+				V_P2SB_CFG_HBDF_FUNC);
+
+		acpi_dmar_drhd_fixup(tmp, current);
+	}
+
+	/* Add RMRR entry */
+	const unsigned long tmp = current;
+	current += acpi_create_dmar_rmrr(current, 0,
+		sa_get_gsm_base(), sa_get_tolud_base() - 1);
+	current += acpi_create_dmar_ds_pci(current, 0, 2, 0);
+	acpi_dmar_rmrr_fixup(tmp, current);
+
+	return current;
+}
+
+unsigned long sa_write_acpi_tables(const struct device *dev, unsigned long current,
+				   struct acpi_rsdp *rsdp)
+{
+	acpi_dmar_t *const dmar = (acpi_dmar_t *)current;
+
+	/*
+	 * Create DMAR table only if we have VT-d capability and FSP does not override its
+	 * feature.
+	 */
+	if ((pci_read_config32(dev, CAPID0_A) & VTD_DISABLE) ||
+	    !(MCHBAR32(VTVC0BAR) & VTBAR_ENABLED))
+		return current;
+
+	printk(BIOS_DEBUG, "ACPI:    * DMAR\n");
+	acpi_create_dmar(dmar, DMAR_INTR_REMAP | DMA_CTRL_PLATFORM_OPT_IN_FLAG, soc_fill_dmar);
+	current += dmar->header.length;
+	current = acpi_align_current(current);
+	acpi_add_table(rsdp, dmar);
+
+	return current;
+}
+
+void acpi_create_gnvs(struct global_nvs *gnvs)
+{
+	config_t *config = config_of_soc();
+
+	/* Set unknown wake source */
+	gnvs->pm1i = -1;
+
+	/* CPU core count */
+	gnvs->pcnt = dev_count_cpu();
+
+	if (CONFIG(CONSOLE_CBMEM))
+		/* Update the mem console pointer. */
+		gnvs->cbmc = (uintptr_t)cbmem_find(CBMEM_ID_CONSOLE);
+
+	if (CONFIG(CHROMEOS)) {
+		/* Initialize Verified Boot data */
+		chromeos_init_chromeos_acpi(&(gnvs->chromeos));
+		if (CONFIG(EC_GOOGLE_CHROMEEC)) {
+			gnvs->chromeos.vbt2 = google_ec_running_ro() ?
+				ACTIVE_ECFW_RO : ACTIVE_ECFW_RW;
+		} else
+			gnvs->chromeos.vbt2 = ACTIVE_ECFW_RO;
+	}
+
+	/* Enable DPTF based on mainboard configuration */
+	gnvs->dpte = config->dptf_enable;
+
+	/* Fill in the Wifi Region id */
+	gnvs->cid1 = wifi_regulatory_domain();
+
+	/* Set USB2/USB3 wake enable bitmaps. */
+	gnvs->u2we = config->usb2_wake_enable_bitmap;
+	gnvs->u3we = config->usb3_wake_enable_bitmap;
+
+	/* Fill in Above 4GB MMIO resource */
+	sa_fill_gnvs(gnvs);
+}
+
+uint32_t acpi_fill_soc_wake(uint32_t generic_pm1_en,
+			    const struct chipset_power_state *ps)
+{
+	/*
+	 * WAK_STS bit is set when the system is in one of the sleep states
+	 * (via the SLP_EN bit) and an enabled wake event occurs. Upon setting
+	 * this bit, the PMC will transition the system to the ON state and
+	 * can only be set by hardware and can only be cleared by writing a one
+	 * to this bit position.
+	 */
+
+	generic_pm1_en |= WAK_STS | RTC_EN | PWRBTN_EN;
+	return generic_pm1_en;
+}
+
+int soc_madt_sci_irq_polarity(int sci)
+{
+	return MP_IRQ_POLARITY_HIGH;
+}
+
+static int acpigen_soc_gpio_op(const char *op, unsigned int gpio_num)
+{
+	/* op (gpio_num) */
+	acpigen_emit_namestring(op);
+	acpigen_write_integer(gpio_num);
+	return 0;
+}
+
+static int acpigen_soc_get_gpio_state(const char *op, unsigned int gpio_num)
+{
+	/* Store (op (gpio_num), Local0) */
+	acpigen_write_store();
+	acpigen_soc_gpio_op(op, gpio_num);
+	acpigen_emit_byte(LOCAL0_OP);
+	return 0;
+}
+
+int acpigen_soc_read_rx_gpio(unsigned int gpio_num)
+{
+	return acpigen_soc_get_gpio_state("\\_SB.PCI0.GRXS", gpio_num);
+}
+
+int acpigen_soc_get_tx_gpio(unsigned int gpio_num)
+{
+	return acpigen_soc_get_gpio_state("\\_SB.PCI0.GTXS", gpio_num);
+}
+
+int acpigen_soc_set_tx_gpio(unsigned int gpio_num)
+{
+	return acpigen_soc_gpio_op("\\_SB.PCI0.STXS", gpio_num);
+}
+
+int acpigen_soc_clear_tx_gpio(unsigned int gpio_num)
+{
+	return acpigen_soc_gpio_op("\\_SB.PCI0.CTXS", gpio_num);
+}
diff --git a/src/soc/intel/elkhartlake/chip.c b/src/soc/intel/elkhartlake/chip.c
new file mode 100644
index 0000000..e4884ef
--- /dev/null
+++ b/src/soc/intel/elkhartlake/chip.c
@@ -0,0 +1,180 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <device/device.h>
+#include <device/pci.h>
+#include <fsp/api.h>
+#include <fsp/util.h>
+#include <intelblocks/acpi.h>
+#include <intelblocks/cfg.h>
+#include <intelblocks/itss.h>
+#include <intelblocks/pcie_rp.h>
+#include <intelblocks/xdci.h>
+#include <romstage_handoff.h>
+#include <soc/intel/common/vbt.h>
+#include <soc/itss.h>
+#include <soc/pci_devs.h>
+#include <soc/ramstage.h>
+#include <soc/soc_chip.h>
+
+static const struct pcie_rp_group pch_rp_groups[] = {
+	{ .slot = PCH_DEV_SLOT_PCIE,    .count = 8 },
+	{ 0 }
+};
+
+#if CONFIG(HAVE_ACPI_TABLES)
+const char *soc_acpi_name(const struct device *dev)
+{
+	if (dev->path.type == DEVICE_PATH_DOMAIN)
+		return "PCI0";
+
+	if (dev->path.type == DEVICE_PATH_USB) {
+		switch (dev->path.usb.port_type) {
+		case 0:
+			/* Root Hub */
+			return "RHUB";
+		case 2:
+			/* USB2 ports */
+			switch (dev->path.usb.port_id) {
+			case 0: return "HS01";
+			case 1: return "HS02";
+			case 2: return "HS03";
+			case 3: return "HS04";
+			case 4: return "HS05";
+			case 5: return "HS06";
+			case 6: return "HS07";
+			case 7: return "HS08";
+			case 8: return "HS09";
+			case 9: return "HS10";
+			}
+			break;
+		case 3:
+			/* USB3 ports */
+			switch (dev->path.usb.port_id) {
+			case 0: return "SS01";
+			case 1: return "SS02";
+			case 2: return "SS03";
+			case 3: return "SS04";
+			}
+			break;
+		}
+		return NULL;
+	}
+	if (dev->path.type != DEVICE_PATH_PCI)
+		return NULL;
+
+	switch (dev->path.pci.devfn) {
+	case SA_DEVFN_ROOT:	return "MCHC";
+	case SA_DEVFN_IPU:	return "IPU0";
+	case PCH_DEVFN_ISH:	return "ISHB";
+	case PCH_DEVFN_XHCI:	return "XHCI";
+	case PCH_DEVFN_I2C0:	return "I2C0";
+	case PCH_DEVFN_I2C1:	return "I2C1";
+	case PCH_DEVFN_I2C2:	return "I2C2";
+	case PCH_DEVFN_I2C3:	return "I2C3";
+	case PCH_DEVFN_I2C4:	return "I2C4";
+	case PCH_DEVFN_I2C5:	return "I2C5";
+	case PCH_DEVFN_SATA:	return "SATA";
+	case PCH_DEVFN_PCIE1:	return "RP01";
+	case PCH_DEVFN_PCIE2:	return "RP02";
+	case PCH_DEVFN_PCIE3:	return "RP03";
+	case PCH_DEVFN_PCIE4:	return "RP04";
+	case PCH_DEVFN_PCIE5:	return "RP05";
+	case PCH_DEVFN_PCIE6:	return "RP06";
+	case PCH_DEVFN_PCIE7:	return "RP07";
+	case PCH_DEVFN_PCIE8:	return "RP08";
+	case PCH_DEVFN_PCIE9:	return "RP09";
+	case PCH_DEVFN_PCIE10:	return "RP10";
+	case PCH_DEVFN_PCIE11:	return "RP11";
+	case PCH_DEVFN_PCIE12:	return "RP12";
+	case PCH_DEVFN_UART0:	return "UAR0";
+	case PCH_DEVFN_UART1:	return "UAR1";
+	case PCH_DEVFN_UART2:	return "UAR2";
+	case PCH_DEVFN_GSPI0:	return "SPI0";
+	case PCH_DEVFN_GSPI1:	return "SPI1";
+	case PCH_DEVFN_GSPI2:	return "SPI2";
+	case PCH_DEVFN_GSPI3:   return "SPI3";
+	case PCH_DEVFN_EMMC:	return "EMMC";
+	case PCH_DEVFN_SDCARD:	return "SDXC";
+	/* Keeping ACPI device name coherent with ec.asl */
+	case PCH_DEVFN_ESPI:	return "LPCB";
+	case PCH_DEVFN_HDA:	return "HDAS";
+	case PCH_DEVFN_SMBUS:	return "SBUS";
+	case PCH_DEVFN_GBE:	return "GLAN";
+	}
+
+	return NULL;
+}
+#endif
+
+/* SoC rotine to fill GPIO PM mask and value for GPIO_MISCCFG register */
+static void soc_fill_gpio_pm_configuration(void)
+{
+	uint8_t value[TOTAL_GPIO_COMM];
+	const config_t *config = config_of_soc();
+
+	if (config->gpio_override_pm)
+		memcpy(value, config->gpio_pm, sizeof(uint8_t) *
+			TOTAL_GPIO_COMM);
+	else
+		memset(value, MISCCFG_ENABLE_GPIO_PM_CONFIG, sizeof(uint8_t) *
+			TOTAL_GPIO_COMM);
+
+	gpio_pm_configure(value, TOTAL_GPIO_COMM);
+}
+
+void soc_init_pre_device(void *chip_info)
+{
+	/* Snapshot the current GPIO IRQ polarities. FSP is setting a
+	 * default policy that doesn't honor boards' requirements. */
+	itss_snapshot_irq_polarities(GPIO_IRQ_START, GPIO_IRQ_END);
+
+	/* Perform silicon specific init. */
+	fsp_silicon_init(romstage_handoff_is_resume());
+
+	 /* Display FIRMWARE_VERSION_INFO_HOB */
+	fsp_display_fvi_version_hob();
+
+	/* Restore GPIO IRQ polarities back to previous settings. */
+	itss_restore_irq_polarities(GPIO_IRQ_START, GPIO_IRQ_END);
+
+	soc_fill_gpio_pm_configuration();
+
+	/* swap enabled PCI ports in device tree if needed */
+	pcie_rp_update_devicetree(pch_rp_groups);
+}
+
+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,
+#if CONFIG(HAVE_ACPI_TABLES)
+	.acpi_name        = &soc_acpi_name,
+#endif
+};
+
+static struct device_operations cpu_bus_ops = {
+	.read_resources   = noop_read_resources,
+	.set_resources    = noop_set_resources,
+#if CONFIG(HAVE_ACPI_TABLES)
+	.acpi_fill_ssdt   = generate_cpu_entries,
+#endif
+};
+
+extern struct device_operations pmc_ops;
+static void soc_enable(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;
+	else if (dev->path.type == DEVICE_PATH_PCI &&
+		 dev->path.pci.devfn == PCH_DEVFN_PMC)
+		dev->ops = &pmc_ops;
+}
+
+struct chip_operations soc_intel_elkhartlake_ops = {
+	CHIP_NAME("Intel Elkhartlake")
+	.enable_dev	= &soc_enable,
+	.init		= &soc_init_pre_device,
+};
diff --git a/src/soc/intel/elkhartlake/chip.h b/src/soc/intel/elkhartlake/chip.h
new file mode 100644
index 0000000..5037147
--- /dev/null
+++ b/src/soc/intel/elkhartlake/chip.h
@@ -0,0 +1,348 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef _SOC_CHIP_H_
+#define _SOC_CHIP_H_
+
+#include <drivers/i2c/designware/dw_i2c.h>
+#include <intelblocks/cfg.h>
+#include <intelblocks/gpio.h>
+#include <intelblocks/gspi.h>
+#include <intelblocks/power_limit.h>
+#include <soc/gpe.h>
+#include <soc/gpio.h>
+#include <soc/gpio_defs.h>
+#include <soc/pch.h>
+#include <soc/pci_devs.h>
+#include <soc/pmc.h>
+#include <soc/serialio.h>
+#include <soc/usb.h>
+#include <stdint.h>
+
+#define MAX_HD_AUDIO_DMIC_LINKS 2
+#define MAX_HD_AUDIO_SNDW_LINKS 4
+#define MAX_HD_AUDIO_SSP_LINKS  6
+
+struct soc_intel_elkhartlake_config {
+
+	/* Common struct containing soc config data required by common code */
+	struct soc_intel_common_config common_soc_config;
+
+	/* Common struct containing power limits configuration information */
+	struct soc_power_limits_config power_limits_config;
+
+	/* Gpio group routed to each dword of the GPE0 block. Values are
+	 * of the form PMC_GPP_[A:U] or GPD. */
+	uint8_t pmc_gpe0_dw0; /* GPE0_31_0 STS/EN */
+	uint8_t pmc_gpe0_dw1; /* GPE0_63_32 STS/EN */
+	uint8_t pmc_gpe0_dw2; /* GPE0_95_64 STS/EN */
+
+	/* Generic IO decode ranges */
+	uint32_t gen1_dec;
+	uint32_t gen2_dec;
+	uint32_t gen3_dec;
+	uint32_t gen4_dec;
+
+	/* Enable S0iX support */
+	int s0ix_enable;
+	/* Enable DPTF support */
+	int dptf_enable;
+
+	/* Deep SX enable for both AC and DC */
+	int deep_s3_enable_ac;
+	int deep_s3_enable_dc;
+	int deep_s5_enable_ac;
+	int deep_s5_enable_dc;
+
+	/* Deep Sx Configuration
+	 *  DSX_EN_WAKE_PIN       - Enable WAKE# pin
+	 *  DSX_EN_LAN_WAKE_PIN   - Enable LAN_WAKE# pin
+	 *  DSX_DIS_AC_PRESENT_PD - Disable pull-down on AC_PRESENT pin */
+	uint32_t deep_sx_config;
+
+	/* TCC activation offset */
+	uint32_t tcc_offset;
+
+	/* System Agent dynamic frequency support. Only effects ULX/ULT CPUs.
+	 * When enabled memory will be training at two different frequencies.
+	 * 0:Disabled, 1:FixedPoint0, 2:FixedPoint1, 3:FixedPoint2,
+	 * 4:FixedPoint3, 5:Enabled */
+	enum {
+		SaGv_Disabled,
+		SaGv_FixedPoint0,
+		SaGv_FixedPoint1,
+		SaGv_FixedPoint2,
+		SaGv_FixedPoint3,
+		SaGv_Enabled,
+	} SaGv;
+
+	/* Rank Margin Tool. 1:Enable, 0:Disable */
+	uint8_t RMT;
+
+	/* USB related */
+	struct usb2_port_config usb2_ports[16];
+	struct usb3_port_config usb3_ports[10];
+	/* Wake Enable Bitmap for USB2 ports */
+	uint16_t usb2_wake_enable_bitmap;
+	/* Wake Enable Bitmap for USB3 ports */
+	uint16_t usb3_wake_enable_bitmap;
+
+	/* SATA related */
+	uint8_t SataMode;
+	uint8_t SataSalpSupport;
+	uint8_t SataPortsEnable[8];
+	uint8_t SataPortsDevSlp[8];
+
+	/* Audio related */
+	uint8_t PchHdaDspEnable;
+	uint8_t PchHdaAudioLinkHdaEnable;
+	uint8_t PchHdaAudioLinkDmicEnable[MAX_HD_AUDIO_DMIC_LINKS];
+	uint8_t PchHdaAudioLinkSspEnable[MAX_HD_AUDIO_SSP_LINKS];
+	uint8_t PchHdaAudioLinkSndwEnable[MAX_HD_AUDIO_SNDW_LINKS];
+	uint8_t PchHdaIDispLinkTmode;
+	uint8_t PchHdaIDispLinkFrequency;
+	uint8_t PchHdaIDispCodecDisconnect;
+
+	/* PCIe Root Ports */
+	uint8_t PcieRpEnable[CONFIG_MAX_ROOT_PORTS];
+	/* PCIe output clocks type to PCIe devices.
+	 * 0-23: PCH rootport, 0x70: LAN, 0x80: unspecified but in use,
+	 * 0xFF: not used */
+	uint8_t PcieClkSrcUsage[CONFIG_MAX_PCIE_CLOCKS];
+	/* PCIe ClkReq-to-ClkSrc mapping, number of clkreq signal assigned to
+	 * clksrc. */
+	uint8_t PcieClkSrcClkReq[CONFIG_MAX_PCIE_CLOCKS];
+
+	/* Probe CLKREQ# signal before enabling CLKREQ# based power management.*/
+	uint8_t PcieRpClkReqDetect[CONFIG_MAX_ROOT_PORTS];
+
+	/* PCIe RP L1 substate */
+	enum L1_substates_control {
+		L1_SS_FSP_DEFAULT,
+		L1_SS_DISABLED,
+		L1_SS_L1_1,
+		L1_SS_L1_2,
+	} PcieRpL1Substates[CONFIG_MAX_ROOT_PORTS];
+
+	/* SMBus */
+	uint8_t SmbusEnable;
+
+	/* eMMC and SD */
+	uint8_t ScsEmmcHs400Enabled;
+
+	/* Enable if SD Card Power Enable Signal is Active High */
+	uint8_t SdCardPowerEnableActiveHigh;
+
+	/* Integrated Sensor */
+	uint8_t PchIshEnable;
+
+	/* Heci related */
+	uint8_t Heci3Enabled;
+
+	/* Gfx related */
+	uint8_t IgdDvmt50PreAlloc;
+	uint8_t InternalGfx;
+	uint8_t SkipExtGfxScan;
+
+	uint32_t GraphicsConfigPtr;
+	uint8_t Device4Enable;
+
+	/* HeciEnabled decides the state of Heci1 at end of boot
+	 * Setting to 0 (default) disables Heci1 and hides the device from OS */
+	uint8_t HeciEnabled;
+	/* Intel Speed Shift Technology */
+	uint8_t speed_shift_enable;
+
+	/* Enable/Disable EIST. 1b:Enabled, 0b:Disabled */
+	uint8_t eist_enable;
+
+	/* Enable C6 DRAM */
+	uint8_t enable_c6dram;
+	/*
+	 * PRMRR size setting with below options
+	 * Disable: 0x0
+	 * 32MB: 0x2000000
+	 * 64MB: 0x4000000
+	 * 128 MB: 0x8000000
+	 * 256 MB: 0x10000000
+	 * 512 MB: 0x20000000
+	 */
+	uint32_t PrmrrSize;
+	uint8_t PmTimerDisabled;
+	/*
+	 * SerialIO device mode selection:
+	 * PchSerialIoDisabled,
+	 * PchSerialIoPci,
+	 * PchSerialIoHidden,
+	 * PchSerialIoLegacyUart,
+	 * PchSerialIoSkipInit
+	 */
+	uint8_t SerialIoI2cMode[CONFIG_SOC_INTEL_I2C_DEV_MAX];
+	uint8_t SerialIoGSpiMode[CONFIG_SOC_INTEL_COMMON_BLOCK_GSPI_MAX];
+	uint8_t SerialIoUartMode[CONFIG_SOC_INTEL_UART_DEV_MAX];
+	/*
+	 * GSPIn Default Chip Select Mode:
+	 * 0:Hardware Mode,
+	 * 1:Software Mode
+	 */
+	uint8_t SerialIoGSpiCsMode[CONFIG_SOC_INTEL_COMMON_BLOCK_GSPI_MAX];
+	/*
+	 * GSPIn Default Chip Select State:
+	 * 0: Low,
+	 * 1: High
+	 */
+	uint8_t SerialIoGSpiCsState[CONFIG_SOC_INTEL_COMMON_BLOCK_GSPI_MAX];
+
+	/*
+	 * TraceHubMode config
+	 * 0: Disable, 1: Target Debugger Mode, 2: Host Debugger Mode
+	 */
+	uint8_t TraceHubMode;
+
+	/* Debug interface selection */
+	enum {
+		DEBUG_INTERFACE_RAM = (1 << 0),
+		DEBUG_INTERFACE_UART_8250IO = (1 << 1),
+		DEBUG_INTERFACE_USB3 = (1 << 3),
+		DEBUG_INTERFACE_LPSS_SERIAL_IO = (1 << 4),
+		DEBUG_INTERFACE_TRACEHUB = (1 << 5),
+	} debug_interface_flag;
+
+	/* GPIO SD card detect pin */
+	unsigned int sdcard_cd_gpio;
+
+	/* CNVi BT Audio Offload: Enable/Disable BT Audio Offload. */
+	enum {
+		FORCE_DISABLE,
+		FORCE_ENABLE,
+	} CnviBtAudioOffload;
+
+	/* Tcss */
+	uint8_t TcssXhciEn;
+	uint8_t TcssXdciEn;
+
+	/*
+	 * Override GPIO PM configuration:
+	 * 0: Use FSP default GPIO PM program,
+	 * 1: coreboot to override GPIO PM program
+	 */
+	uint8_t gpio_override_pm;
+
+	/*
+	 * GPIO PM configuration: 0 to disable, 1 to enable power gating
+	 * Bit 6-7: Reserved
+	 * Bit 5: MISCCFG_GPSIDEDPCGEN
+	 * Bit 4: MISCCFG_GPRCOMPCDLCGEN
+	 * Bit 3: MISCCFG_GPRTCDLCGEN
+	 * Bit 2: MISCCFG_GSXLCGEN
+	 * Bit 1: MISCCFG_GPDPCGEN
+	 * Bit 0: MISCCFG_GPDLCGEN
+	 */
+	uint8_t gpio_pm[TOTAL_GPIO_COMM];
+
+	/* DP config */
+	/*
+	 * Port config
+	 * 0:Disabled, 1:eDP, 2:MIPI DSI
+	 */
+	uint8_t DdiPortAConfig;
+	uint8_t DdiPortBConfig;
+
+	/* Enable(1)/Disable(0) HPD */
+	uint8_t DdiPortAHpd;
+	uint8_t DdiPortBHpd;
+	uint8_t DdiPortCHpd;
+	uint8_t DdiPort1Hpd;
+	uint8_t DdiPort2Hpd;
+	uint8_t DdiPort3Hpd;
+	uint8_t DdiPort4Hpd;
+
+	/* Enable(1)/Disable(0) DDC */
+	uint8_t DdiPortADdc;
+	uint8_t DdiPortBDdc;
+	uint8_t DdiPortCDdc;
+	uint8_t DdiPort1Ddc;
+	uint8_t DdiPort2Ddc;
+	uint8_t DdiPort3Ddc;
+	uint8_t DdiPort4Ddc;
+
+	/* Hybrid storage mode enable (1) / disable (0)
+	 * This mode makes FSP detect Optane and NVME and set PCIe lane mode
+	 * accordingly */
+	uint8_t HybridStorageMode;
+
+	/*
+	 * Override CPU flex ratio value:
+	 * CPU ratio value controls the maximum processor non-turbo ratio.
+	 * Valid Range 0 to 63.
+	 * In general descriptor provides option to set default cpu flex ratio.
+	 * Default cpu flex ratio 0 ensures booting with non-turbo max frequency.
+	 * That's the reason FSP skips cpu_ratio override if cpu_ratio is 0.
+	 * Only override CPU flex ratio to not boot with non-turbo max.
+	 */
+	uint8_t cpu_ratio_override;
+
+	/* Skip CPU replacement check
+	 * 0: disable
+	 * 1: enable
+	 * Setting this option to skip CPU replacement check to avoid the forced MRC training
+	 * for the platforms with soldered down SOC.
+	 */
+	uint8_t SkipCpuReplacementCheck;
+
+	/*
+	 * SLP_S3 Minimum Assertion Width Policy
+	 *  1 = 60us
+	 *  2 = 1ms
+	 *  3 = 50ms (default)
+	 *  4 = 2s
+	 */
+	uint8_t PchPmSlpS3MinAssert;
+
+	/*
+	 * SLP_S4 Minimum Assertion Width Policy
+	 *  1 = 1s (default)
+	 *  2 = 2s
+	 *  3 = 3s
+	 *  4 = 4s
+	 */
+	uint8_t PchPmSlpS4MinAssert;
+
+	/*
+	 * SLP_SUS Minimum Assertion Width Policy
+	 *  1 = 0ms
+	 *  2 = 500ms
+	 *  3 = 1s
+	 *  4 = 4s (default)
+	 */
+	uint8_t PchPmSlpSusMinAssert;
+
+	/*
+	 * SLP_A Minimum Assertion Width Policy
+	 *  1 = 0ms
+	 *  2 = 4s
+	 *  3 = 98ms
+	 *  4 = 2s (default)
+	 */
+	uint8_t PchPmSlpAMinAssert;
+
+	/*
+	 * PCH PM Reset Power Cycle Duration
+	 *  0 = 4s (default)
+	 *  1 = 1s
+	 *  2 = 2s
+	 *  3 = 3s
+	 *  4 = 4s
+	 *
+	 * NOTE: Duration programmed in the PchPmPwrCycDur should never be smaller than the
+	 * stretch duration programmed in the following registers:
+	 *  - GEN_PMCON_A.SLP_S3_MIN_ASST_WDTH (PchPmSlpS3MinAssert)
+	 *  - GEN_PMCON_A.S4MAW (PchPmSlpS4MinAssert)
+	 *  - PM_CFG.SLP_A_MIN_ASST_WDTH (PchPmSlpAMinAssert)
+	 *  - PM_CFG.SLP_LAN_MIN_ASST_WDTH
+	 */
+	uint8_t PchPmPwrCycDur;
+};
+
+typedef struct soc_intel_elkhartlake_config config_t;
+
+#endif
diff --git a/src/soc/intel/elkhartlake/cpu.c b/src/soc/intel/elkhartlake/cpu.c
new file mode 100644
index 0000000..382bbf7
--- /dev/null
+++ b/src/soc/intel/elkhartlake/cpu.c
@@ -0,0 +1,213 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <arch/cpu.h>
+#include <console/console.h>
+#include <cpu/intel/smm_reloc.h>
+#include <cpu/intel/turbo.h>
+#include <cpu/x86/lapic.h>
+#include <cpu/x86/mp.h>
+#include <cpu/x86/msr.h>
+#include <device/pci.h>
+#include <fsp/api.h>
+#include <intelblocks/cpulib.h>
+#include <intelblocks/mp_init.h>
+#include <intelblocks/msr.h>
+#include <romstage_handoff.h>
+#include <soc/cpu.h>
+#include <soc/msr.h>
+#include <soc/pci_devs.h>
+#include <soc/pm.h>
+#include <soc/soc_chip.h>
+
+static void soc_fsp_load(void)
+{
+	fsps_load(romstage_handoff_is_resume());
+}
+
+static void configure_isst(void)
+{
+	config_t *conf = config_of_soc();
+	msr_t msr;
+
+	if (conf->speed_shift_enable) {
+		/*
+		 * Kernel driver checks CPUID.06h:EAX[Bit 7] to determine if HWP
+		 * is supported or not. coreboot needs to configure MSR 0x1AA
+		 * which is then reflected in the CPUID register.
+		 */
+		msr = rdmsr(MSR_MISC_PWR_MGMT);
+		msr.lo |= MISC_PWR_MGMT_ISST_EN; /* Enable Speed Shift */
+		msr.lo |= MISC_PWR_MGMT_ISST_EN_INT; /* Enable Interrupt */
+		msr.lo |= MISC_PWR_MGMT_ISST_EN_EPP; /* Enable EPP */
+		wrmsr(MSR_MISC_PWR_MGMT, msr);
+	} else {
+		msr = rdmsr(MSR_MISC_PWR_MGMT);
+		msr.lo &= ~MISC_PWR_MGMT_ISST_EN; /* Disable Speed Shift */
+		msr.lo &= ~MISC_PWR_MGMT_ISST_EN_INT; /* Disable Interrupt */
+		msr.lo &= ~MISC_PWR_MGMT_ISST_EN_EPP; /* Disable EPP */
+		wrmsr(MSR_MISC_PWR_MGMT, msr);
+	}
+}
+
+static void configure_misc(void)
+{
+	msr_t msr;
+
+	config_t *conf = config_of_soc();
+
+	msr = rdmsr(IA32_MISC_ENABLE);
+	msr.lo |= (1 << 0);	/* Fast String enable */
+	msr.lo |= (1 << 3);	/* TM1/TM2/EMTTM enable */
+	wrmsr(IA32_MISC_ENABLE, msr);
+
+	/* Set EIST status */
+	cpu_set_eist(conf->eist_enable);
+
+	/* Disable Thermal interrupts */
+	msr.lo = 0;
+	msr.hi = 0;
+	wrmsr(IA32_THERM_INTERRUPT, msr);
+
+	/* Enable package critical interrupt only */
+	msr.lo = 1 << 4;
+	msr.hi = 0;
+	wrmsr(IA32_PACKAGE_THERM_INTERRUPT, msr);
+
+	/* Enable PROCHOT */
+	msr = rdmsr(MSR_POWER_CTL);
+	msr.lo |= (1 << 0);	/* Enable Bi-directional PROCHOT as an input*/
+	msr.lo |= (1 << 23);	/* Lock it */
+	wrmsr(MSR_POWER_CTL, msr);
+}
+
+static void enable_lapic_tpr(void)
+{
+	msr_t msr;
+
+	msr = rdmsr(MSR_PIC_MSG_CONTROL);
+	msr.lo &= ~(1 << 10);	/* Enable APIC TPR updates */
+	wrmsr(MSR_PIC_MSG_CONTROL, msr);
+}
+
+static void configure_dca_cap(void)
+{
+	uint32_t feature_flag;
+	msr_t msr;
+
+	/* Check feature flag in CPUID.(EAX=1):ECX[18]==1 */
+	feature_flag = cpu_get_feature_flags_ecx();
+	if (feature_flag & CPUID_DCA) {
+		msr = rdmsr(IA32_PLATFORM_DCA_CAP);
+		msr.lo |= 1;
+		wrmsr(IA32_PLATFORM_DCA_CAP, msr);
+	}
+}
+
+static void enable_pm_timer_emulation(void)
+{
+	/* ACPI PM timer emulation */
+	msr_t msr;
+	/*
+	 * The derived frequency is calculated as follows:
+	 * (CTC_FREQ * msr[63:32]) >> 32 = target frequency.
+	 * Back solve the multiplier so the 3.579545MHz ACPI timer
+	 * frequency is used.
+	 */
+	msr.hi = (3579545ULL << 32) / CTC_FREQ;
+	/* Set PM1 timer IO port and enable */
+	msr.lo = (EMULATE_DELAY_VALUE << EMULATE_DELAY_OFFSET_VALUE) |
+			EMULATE_PM_TMR_EN | (ACPI_BASE_ADDRESS + PM1_TMR);
+	wrmsr(MSR_EMULATE_PM_TIMER, msr);
+}
+
+static void set_energy_perf_bias(u8 policy)
+{
+	msr_t msr;
+	int ecx;
+
+	/* Determine if energy efficient policy is supported. */
+	ecx = cpuid_ecx(0x6);
+	if (!(ecx & (1 << 3)))
+		return;
+
+	/* Energy Policy is bits 3:0 */
+	msr = rdmsr(IA32_ENERGY_PERF_BIAS);
+	msr.lo &= ~0xf;
+	msr.lo |= policy & 0xf;
+	wrmsr(IA32_ENERGY_PERF_BIAS, msr);
+}
+
+/* All CPUs including BSP will run the following function. */
+void soc_core_init(struct device *cpu)
+{
+	/* Clear out pending MCEs */
+	/* 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();
+
+	/* Enable the local CPU apics */
+	enable_lapic_tpr();
+	setup_lapic();
+
+	/* Configure Enhanced SpeedStep and Thermal Sensors */
+	configure_misc();
+
+	/* Configure Intel Speed Shift */
+	configure_isst();
+
+	/* Enable PM timer emulation */
+	enable_pm_timer_emulation();
+
+	/* Enable Direct Cache Access */
+	configure_dca_cap();
+
+	/* Set energy policy */
+	set_energy_perf_bias(ENERGY_POLICY_NORMAL);
+
+	/* Enable Turbo */
+	enable_turbo();
+}
+
+static void per_cpu_smm_trigger(void)
+{
+	/* Relocate the SMM handler. */
+	smm_relocate();
+}
+
+static void post_mp_init(void)
+{
+	/* Set Max Ratio */
+	cpu_set_max_ratio();
+
+	/*
+	 * Now that all APs have been relocated as well as the BSP let SMIs
+	 * start flowing.
+	 */
+	global_smi_enable();
+}
+
+static const struct mp_ops mp_ops = {
+	/*
+	 * Skip Pre MP init MTRR programming as MTRRs are mirrored from BSP,
+	 * that are set prior to ramstage.
+	 * Real MTRRs programming are being done after resource allocation.
+	 */
+	.pre_mp_init = soc_fsp_load,
+	.get_cpu_count = get_cpu_count,
+	.get_smm_info = smm_info,
+	.get_microcode_info = get_microcode_info,
+	.pre_mp_smm_init = smm_initialize,
+	.per_cpu_smm_trigger = per_cpu_smm_trigger,
+	.relocation_handler = smm_relocation_handler,
+	.post_mp_init = post_mp_init,
+};
+
+void soc_init_cpus(struct bus *cpu_bus)
+{
+	if (mp_init_with_smm(cpu_bus, &mp_ops))
+		printk(BIOS_ERR, "MP initialization failure.\n");
+
+	/* Thermal throttle activation offset */
+	configure_tcc_thermal_target();
+}
diff --git a/src/soc/intel/elkhartlake/elog.c b/src/soc/intel/elkhartlake/elog.c
new file mode 100644
index 0000000..c88efc8
--- /dev/null
+++ b/src/soc/intel/elkhartlake/elog.c
@@ -0,0 +1,117 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <bootstate.h>
+#include <console/console.h>
+#include <elog.h>
+#include <intelblocks/pmclib.h>
+#include <soc/pci_devs.h>
+#include <soc/pm.h>
+#include <stdint.h>
+
+static void pch_log_gpio_gpe(u32 gpe0_sts, u32 gpe0_en, int start)
+{
+	int i;
+
+	gpe0_sts &= gpe0_en;
+
+	for (i = 0; i <= 31; i++) {
+		if (gpe0_sts & (1 << i))
+			elog_add_event_wake(ELOG_WAKE_SOURCE_GPE, i + start);
+	}
+}
+
+static void pch_log_wake_source(struct chipset_power_state *ps)
+{
+	/* Power Button */
+	if (ps->pm1_sts & PWRBTN_STS)
+		elog_add_event_wake(ELOG_WAKE_SOURCE_PWRBTN, 0);
+
+	/* RTC */
+	if (ps->pm1_sts & RTC_STS)
+		elog_add_event_wake(ELOG_WAKE_SOURCE_RTC, 0);
+
+	/* PCI Express (TODO: determine wake device) */
+	if (ps->pm1_sts & PCIEXPWAK_STS)
+		elog_add_event_wake(ELOG_WAKE_SOURCE_PCIE, 0);
+
+	/* PME (TODO: determine wake device) */
+	if (ps->gpe0_sts[GPE_STD] & PME_STS)
+		elog_add_event_wake(ELOG_WAKE_SOURCE_PME, 0);
+
+	/* Internal PME (TODO: determine wake device) */
+	if (ps->gpe0_sts[GPE_STD] & PME_B0_STS)
+		elog_add_event_wake(ELOG_WAKE_SOURCE_PME_INTERNAL, 0);
+
+	/* SMBUS Wake */
+	if (ps->gpe0_sts[GPE_STD] & SMB_WAK_STS)
+		elog_add_event_wake(ELOG_WAKE_SOURCE_SMBUS, 0);
+
+	/* Log GPIO events in set 1-3 */
+	pch_log_gpio_gpe(ps->gpe0_sts[GPE_31_0], ps->gpe0_en[GPE_31_0], 0);
+	pch_log_gpio_gpe(ps->gpe0_sts[GPE_63_32], ps->gpe0_en[GPE_63_32], 32);
+	pch_log_gpio_gpe(ps->gpe0_sts[GPE_95_64], ps->gpe0_en[GPE_95_64], 64);
+	/* Treat the STD as an extension of GPIO to obtain visibility. */
+	pch_log_gpio_gpe(ps->gpe0_sts[GPE_STD], ps->gpe0_en[GPE_STD], 96);
+}
+
+static void pch_log_power_and_resets(struct chipset_power_state *ps)
+{
+	/* Thermal Trip */
+	if (ps->gblrst_cause[0] & GBLRST_CAUSE0_THERMTRIP)
+		elog_add_event(ELOG_TYPE_THERM_TRIP);
+
+	/* PWR_FLR Power Failure */
+	if (ps->gen_pmcon_a & PWR_FLR)
+		elog_add_event(ELOG_TYPE_POWER_FAIL);
+
+	/* SUS Well Power Failure */
+	if (ps->gen_pmcon_a & SUS_PWR_FLR)
+		elog_add_event(ELOG_TYPE_SUS_POWER_FAIL);
+
+	/* TCO Timeout */
+	if (ps->prev_sleep_state != ACPI_S3 &&
+	    ps->tco2_sts & TCO_STS_SECOND_TO)
+		elog_add_event(ELOG_TYPE_TCO_RESET);
+
+	/* Power Button Override */
+	if (ps->pm1_sts & PRBTNOR_STS)
+		elog_add_event(ELOG_TYPE_POWER_BUTTON_OVERRIDE);
+
+	/* RTC reset */
+	if (ps->gen_pmcon_b & RTC_BATTERY_DEAD)
+		elog_add_event(ELOG_TYPE_RTC_RESET);
+
+	/* Host Reset Status */
+	if (ps->gen_pmcon_a & HOST_RST_STS)
+		elog_add_event(ELOG_TYPE_SYSTEM_RESET);
+
+	/* ACPI Wake Event */
+	if (ps->prev_sleep_state != ACPI_S0)
+		elog_add_event_byte(ELOG_TYPE_ACPI_WAKE, ps->prev_sleep_state);
+}
+
+static void pch_log_state(void *unused)
+{
+	struct chipset_power_state *ps = pmc_get_power_state();
+
+	if (!ps) {
+		printk(BIOS_ERR, "chipset_power_state not found!\n");
+		return;
+	}
+
+	/* Power and Reset */
+	pch_log_power_and_resets(ps);
+
+	/* Wake Sources */
+	if (ps->prev_sleep_state > ACPI_S0)
+		pch_log_wake_source(ps);
+}
+
+BOOT_STATE_INIT_ENTRY(BS_DEV_INIT, BS_ON_EXIT, pch_log_state, NULL);
+
+void elog_gsmi_cb_platform_log_wake_source(void)
+{
+	struct chipset_power_state ps;
+	pmc_fill_pm_reg_info(&ps);
+	pch_log_wake_source(&ps);
+}
diff --git a/src/soc/intel/elkhartlake/espi.c b/src/soc/intel/elkhartlake/espi.c
new file mode 100644
index 0000000..7133997
--- /dev/null
+++ b/src/soc/intel/elkhartlake/espi.c
@@ -0,0 +1,192 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <arch/io.h>
+#include <arch/ioapic.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ops.h>
+#include <intelblocks/itss.h>
+#include <intelblocks/lpc_lib.h>
+#include <intelblocks/pcr.h>
+#include <pc80/isa-dma.h>
+#include <pc80/i8259.h>
+#include <soc/espi.h>
+#include <soc/iomap.h>
+#include <soc/irq.h>
+#include <soc/pci_devs.h>
+#include <soc/pcr_ids.h>
+#include <soc/soc_chip.h>
+
+/*
+* To reserve certain memory range as reserved range for BIOS usage.
+* For this SOC, the range will be from 0FC800000h till FE7FFFFFh"
+*/
+static const struct lpc_mmio_range ehl_lpc_fixed_mmio_ranges[] = {
+	{ PCH_PRESERVED_BASE_ADDRESS, PCH_PRESERVED_BASE_SIZE },
+	{ 0, 0 }
+};
+
+const struct lpc_mmio_range *soc_get_fixed_mmio_ranges()
+{
+	return ehl_lpc_fixed_mmio_ranges;
+}
+
+void soc_get_gen_io_dec_range(const struct device *dev, uint32_t *gen_io_dec)
+{
+	const config_t *config = config_of(dev);
+
+	gen_io_dec[0] = config->gen1_dec;
+	gen_io_dec[1] = config->gen2_dec;
+	gen_io_dec[2] = config->gen3_dec;
+	gen_io_dec[3] = config->gen4_dec;
+}
+
+void soc_setup_dmi_pcr_io_dec(uint32_t *gen_io_dec)
+{
+	/* Mirror these same settings in DMI PCR */
+	pcr_write32(PID_DMI, PCR_DMI_LPCLGIR1, gen_io_dec[0]);
+	pcr_write32(PID_DMI, PCR_DMI_LPCLGIR2, gen_io_dec[1]);
+	pcr_write32(PID_DMI, PCR_DMI_LPCLGIR3, gen_io_dec[2]);
+	pcr_write32(PID_DMI, PCR_DMI_LPCLGIR4, gen_io_dec[3]);
+}
+
+#if ENV_RAMSTAGE
+static void soc_mirror_dmi_pcr_io_dec(void)
+{
+	struct device *dev = pcidev_on_root(PCH_DEV_SLOT_ESPI, 0);
+	uint32_t io_dec_arr[] = {
+		pci_read_config32(dev, ESPI_GEN1_DEC),
+		pci_read_config32(dev, ESPI_GEN2_DEC),
+		pci_read_config32(dev, ESPI_GEN3_DEC),
+		pci_read_config32(dev, ESPI_GEN4_DEC),
+	};
+	/* Mirror these same settings in DMI PCR */
+	soc_setup_dmi_pcr_io_dec(&io_dec_arr[0]);
+}
+
+static void pch_enable_ioapic(const struct device *dev)
+{
+	uint32_t reg32;
+	/* PCH-LP has 120 redirection entries */
+	const int redir_entries = 120;
+
+	set_ioapic_id((void *)IO_APIC_ADDR, 0x02);
+
+	/* affirm full set of redirection table entries ("write once") */
+	reg32 = io_apic_read((void *)IO_APIC_ADDR, 0x01);
+
+	reg32 &= ~0x00ff0000;
+	reg32 |= (redir_entries - 1) << 16;
+
+	io_apic_write((void *)IO_APIC_ADDR, 0x01, reg32);
+
+	/*
+	 * Select Boot Configuration register (0x03) and
+	 * use Processor System Bus (0x01) to deliver interrupts.
+	 */
+	io_apic_write((void *)IO_APIC_ADDR, 0x03, 0x01);
+}
+/*
+ * PIRQ[n]_ROUT[3:0] - PIRQ Routing Control
+ * 0x00 - 0000 = Reserved
+ * 0x01 - 0001 = Reserved
+ * 0x02 - 0010 = Reserved
+ * 0x03 - 0011 = IRQ3
+ * 0x04 - 0100 = IRQ4
+ * 0x05 - 0101 = IRQ5
+ * 0x06 - 0110 = IRQ6
+ * 0x07 - 0111 = IRQ7
+ * 0x08 - 1000 = Reserved
+ * 0x09 - 1001 = IRQ9
+ * 0x0A - 1010 = IRQ10
+ * 0x0B - 1011 = IRQ11
+ * 0x0C - 1100 = IRQ12
+ * 0x0D - 1101 = Reserved
+ * 0x0E - 1110 = IRQ14
+ * 0x0F - 1111 = IRQ15
+ * PIRQ[n]_ROUT[7] - PIRQ Routing Control
+ * 0x80 - The PIRQ is not routed.
+ */
+
+void soc_pch_pirq_init(const struct device *dev)
+{
+	struct device *irq_dev;
+	uint8_t pch_interrupt_routing[MAX_PXRC_CONFIG];
+
+	pch_interrupt_routing[0] = PCH_IRQ11;
+	pch_interrupt_routing[1] = PCH_IRQ10;
+	pch_interrupt_routing[2] = PCH_IRQ11;
+	pch_interrupt_routing[3] = PCH_IRQ11;
+	pch_interrupt_routing[4] = PCH_IRQ11;
+	pch_interrupt_routing[5] = PCH_IRQ11;
+	pch_interrupt_routing[6] = PCH_IRQ11;
+	pch_interrupt_routing[7] = PCH_IRQ11;
+
+	itss_irq_init(pch_interrupt_routing);
+
+	for (irq_dev = all_devices; irq_dev; irq_dev = irq_dev->next) {
+		uint8_t int_pin = 0, int_line = 0;
+
+		if (!irq_dev->enabled || irq_dev->path.type != DEVICE_PATH_PCI)
+			continue;
+
+		int_pin = pci_read_config8(irq_dev, PCI_INTERRUPT_PIN);
+
+		switch (int_pin) {
+		case 1: /* INTA# */
+			int_line = PCH_IRQ11;
+			break;
+		case 2: /* INTB# */
+			int_line = PCH_IRQ10;
+			break;
+		case 3: /* INTC# */
+			int_line = PCH_IRQ11;
+			break;
+		case 4: /* INTD# */
+			int_line = PCH_IRQ11;
+			break;
+		}
+
+		if (!int_line)
+			continue;
+
+		pci_write_config8(irq_dev, PCI_INTERRUPT_LINE, int_line);
+	}
+}
+
+static void pch_misc_init(void)
+{
+	uint8_t reg8;
+
+	/* Setup NMI on errors, disable SERR */
+	reg8 = (inb(NMI_STS_CNT) & 0xf0);
+	outb((reg8 | (1 << 2)), NMI_STS_CNT);
+
+	/* Disable NMI sources */
+	outb((1 << 7), NMI_EN);
+};
+
+void lpc_soc_init(struct device *dev)
+{
+	/* Legacy initialization */
+	isa_dma_init();
+	pch_misc_init();
+
+	/* Enable CLKRUN_EN for power gating ESPI */
+	lpc_enable_pci_clk_cntl();
+
+	/* Set ESPI Serial IRQ mode */
+	if (CONFIG(SERIRQ_CONTINUOUS_MODE))
+		lpc_set_serirq_mode(SERIRQ_CONTINUOUS);
+	else
+		lpc_set_serirq_mode(SERIRQ_QUIET);
+
+	/* Interrupt configuration */
+	pch_enable_ioapic(dev);
+	soc_pch_pirq_init(dev);
+	setup_i8259();
+	i8259_configure_irq_trigger(9, 1);
+	soc_mirror_dmi_pcr_io_dec();
+}
+
+#endif
diff --git a/src/soc/intel/elkhartlake/finalize.c b/src/soc/intel/elkhartlake/finalize.c
new file mode 100644
index 0000000..e9b3f21
--- /dev/null
+++ b/src/soc/intel/elkhartlake/finalize.c
@@ -0,0 +1,76 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <arch/io.h>
+#include <bootstate.h>
+#include <console/console.h>
+#include <console/post_codes.h>
+#include <cpu/x86/smm.h>
+#include <device/mmio.h>
+#include <device/pci.h>
+#include <intelblocks/lpc_lib.h>
+#include <intelblocks/pcr.h>
+#include <intelblocks/tco.h>
+#include <intelblocks/thermal.h>
+#include <soc/p2sb.h>
+#include <soc/pci_devs.h>
+#include <soc/pcr_ids.h>
+#include <soc/pm.h>
+#include <soc/smbus.h>
+#include <soc/soc_chip.h>
+#include <soc/systemagent.h>
+#include <spi-generic.h>
+
+static void pch_finalize(void)
+{
+	uint32_t reg32;
+	uint8_t *pmcbase;
+	config_t *config;
+	uint8_t reg8;
+
+	/* TCO Lock down */
+	tco_lockdown();
+
+	/* TODO: Add Thermal Configuration */
+
+	/*
+	 * Disable ACPI PM timer based on dt policy
+	 *
+	 * Disabling ACPI PM timer is necessary for XTAL OSC shutdown.
+	 * Disabling ACPI PM timer also switches off TCO
+	 *
+	 * SA_DEV_ROOT device is used here instead of PCH_DEV_PMC since it is
+	 * just required to get to chip config. PCH_DEV_PMC is hidden by this
+	 * point and hence removed from the root bus. pcidev_path_on_root thus
+	 * returns NULL for PCH_DEV_PMC device.
+	 */
+	config = config_of_soc();
+	pmcbase = pmc_mmio_regs();
+	if (config->PmTimerDisabled) {
+		reg8 = read8(pmcbase + PCH_PWRM_ACPI_TMR_CTL);
+		reg8 |= (1 << 1);
+		write8(pmcbase + PCH_PWRM_ACPI_TMR_CTL, reg8);
+	}
+
+	/* Disable XTAL shutdown qualification for low power idle. */
+	if (config->s0ix_enable) {
+		reg32 = read32(pmcbase + CPPMVRIC);
+		reg32 |= XTALSDQDIS;
+		write32(pmcbase + CPPMVRIC, reg32);
+	}
+
+	pmc_clear_pmcon_sts();
+}
+
+static void soc_finalize(void *unused)
+{
+	printk(BIOS_DEBUG, "Finalizing chipset.\n");
+
+	pch_finalize();
+	apm_control(APM_CNT_FINALIZE);
+
+	/* Indicate finalize step with post code */
+	post_code(POST_OS_BOOT);
+}
+
+BOOT_STATE_INIT_ENTRY(BS_OS_RESUME, BS_ON_ENTRY, soc_finalize, NULL);
+BOOT_STATE_INIT_ENTRY(BS_PAYLOAD_LOAD, BS_ON_EXIT, soc_finalize, NULL);
diff --git a/src/soc/intel/elkhartlake/fsp_params.c b/src/soc/intel/elkhartlake/fsp_params.c
new file mode 100644
index 0000000..3d740fb
--- /dev/null
+++ b/src/soc/intel/elkhartlake/fsp_params.c
@@ -0,0 +1,79 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#include <assert.h>
+#include <console/console.h>
+#include <device/device.h>
+#include <fsp/api.h>
+#include <fsp/ppi/mp_service_ppi.h>
+#include <fsp/util.h>
+#include <intelblocks/lpss.h>
+#include <intelblocks/mp_init.h>
+#include <intelblocks/xdci.h>
+#include <intelpch/lockdown.h>
+#include <soc/intel/common/vbt.h>
+#include <soc/pci_devs.h>
+#include <soc/ramstage.h>
+#include <soc/soc_chip.h>
+#include <string.h>
+
+/*
+ * ME End of Post configuration
+ * 0 - Disable EOP.
+ * 1 - Send in PEI (Applicable for FSP in API mode)
+ * 2 - Send in DXE (Not applicable for FSP in API mode)
+ */
+enum {
+	EOP_DISABLE,
+	EOP_PEI,
+	EOP_DXE,
+} EndOfPost;
+
+static const pci_devfn_t serial_io_dev[] = {
+	PCH_DEVFN_I2C0,
+	PCH_DEVFN_I2C1,
+	PCH_DEVFN_I2C2,
+	PCH_DEVFN_I2C3,
+	PCH_DEVFN_I2C4,
+	PCH_DEVFN_I2C5,
+	PCH_DEVFN_GSPI0,
+	PCH_DEVFN_GSPI1,
+	PCH_DEVFN_GSPI2,
+	PCH_DEVFN_UART0,
+	PCH_DEVFN_UART1,
+	PCH_DEVFN_UART2
+};
+
+static void parse_devicetree(FSP_S_CONFIG *params)
+{
+	const struct soc_intel_elkhartlake_config *config = config_of_soc();
+	/* TODO: Update with UPD override as FSP matures */
+}
+
+/* UPD parameters to be initialized before SiliconInit */
+void platform_fsp_silicon_init_params_cb(FSPS_UPD *supd)
+{
+	unsigned int i;
+	struct device *dev;
+	FSP_S_CONFIG *params = &supd->FspsConfig;
+	struct soc_intel_elkhartlake_config *config = config_of_soc();
+
+	/* Parse device tree and fill in FSP UPDs */
+	parse_devicetree(params);
+
+	/* TODO: Update with UPD override as FSP matures */
+
+	/* Override/Fill FSP Silicon Param for mainboard */
+	mainboard_silicon_init_params(params);
+}
+
+/* Mainboard GPIO Configuration */
+__weak void mainboard_silicon_init_params(FSP_S_CONFIG *params)
+{
+	printk(BIOS_DEBUG, "WEAK: %s/%s called\n", __FILE__, __func__);
+}
+
+/* Return list of SOC LPSS controllers */
+const pci_devfn_t *soc_lpss_controllers_list(size_t *size)
+{
+	*size = ARRAY_SIZE(serial_io_dev);
+	return serial_io_dev;
+}
diff --git a/src/soc/intel/elkhartlake/gpio.c b/src/soc/intel/elkhartlake/gpio.c
new file mode 100644
index 0000000..9ba5d8e
--- /dev/null
+++ b/src/soc/intel/elkhartlake/gpio.c
@@ -0,0 +1,198 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include <intelblocks/gpio.h>
+#include <intelblocks/pcr.h>
+#include <soc/pcr_ids.h>
+#include <soc/pmc.h>
+
+static const struct reset_mapping rst_map[] = {
+	{ .logical = PAD_CFG0_LOGICAL_RESET_RSMRST, .chipset = 0U << 30 },
+	{ .logical = PAD_CFG0_LOGICAL_RESET_DEEP, .chipset = 1U << 30 },
+	{ .logical = PAD_CFG0_LOGICAL_RESET_PLTRST, .chipset = 2U << 30 },
+};
+
+static const struct reset_mapping rst_map_com0[] = {
+	{ .logical = PAD_CFG0_LOGICAL_RESET_PWROK, .chipset = 0U << 30 },
+	{ .logical = PAD_CFG0_LOGICAL_RESET_DEEP, .chipset = 1U << 30 },
+	{ .logical = PAD_CFG0_LOGICAL_RESET_PLTRST, .chipset = 2U << 30 },
+	{ .logical = PAD_CFG0_LOGICAL_RESET_RSMRST, .chipset = 3U << 30 },
+};
+
+/*
+ * The GPIO driver for Elkhartlake on Windows/Linux expects 32 GPIOs per pad
+ * group, regardless of whether or not there is a physical pad for each
+ * exposed GPIO number.
+ *
+ * This results in the OS having a sparse GPIO map, and devices that need
+ * to export an ACPI GPIO must use the OS expected number.
+ *
+ * Not all pins are usable as GPIO and those groups do not have a pad base.
+ *
+ * This layout matches the Linux kernel pinctrl map for MCC at:
+ * linux/drivers/pinctrl/intel/pinctrl-elkhartlake.c
+ */
+static const struct pad_group ehl_community0_groups[] = {
+
+	INTEL_GPP_BASE(GPP_F0, GPP_F0, GPP_F19, 0),	/* GPP_F */
+	INTEL_GPP(GPP_F0, GPIO_RSVD_0, GPIO_RSVD_8),
+	INTEL_GPP_BASE(GPP_F0, GPP_B0, GPP_B23, 32),	/* GPP_B */
+	INTEL_GPP(GPP_F0, GPIO_RSVD_9, GPIO_RSVD_10),
+	INTEL_GPP_BASE(GPP_F0, GPP_A0, GPIO_RSVD_11, 64),	/* GPP_A */
+	INTEL_GPP_BASE(GPP_F0, GPP_S0, GPP_S7, 96),	/* GPP_S */
+	INTEL_GPP_BASE(GPP_F0, GPP_R0, GPP_R7, 128),	/* GPP_R */
+};
+
+static const struct pad_group ehl_community1_groups[] = {
+	INTEL_GPP_BASE(GPP_H0, GPP_H0, GPP_H23, 160),		/* GPP_H */
+	INTEL_GPP_BASE(GPP_H0, GPP_D0, GPP_D23, 192),	/* GPP_D */
+	INTEL_GPP(GPP_H0, GPIO_RSVD_12, GPIO_RSVD_13),
+	INTEL_GPP_BASE(GPP_H0, VGPIO_0, VGPIO_39, 224),		/* VGPIO */
+	INTEL_GPP_BASE(GPP_H0, GPP_C0, GPP_C23, 256),		/* GPP_C */
+};
+
+/* This community is not visible to the OS */
+static const struct pad_group ehl_community2_groups[] = {
+	INTEL_GPP(GPD0, GPD0, GPD10),				/* GPD */
+	INTEL_GPP(GPD0, GPIO_RSVD_14, GPIO_RSVD_17),
+};
+
+
+static const struct pad_group ehl_community4_groups[] = {
+	INTEL_GPP(GPIO_RSVD_18, GPIO_RSVD_18, GPIO_RSVD_23),
+	INTEL_GPP_BASE(GPIO_RSVD_18, GPP_E0, GPP_E23, 288),		/* GPP_E */
+	INTEL_GPP(GPIO_RSVD_18, GPIO_RSVD_24, GPIO_RSVD_36),
+};
+
+
+static const struct pad_group ehl_community5_groups[] = {
+	INTEL_GPP_BASE(GPP_G0, GPP_G0, GPP_G7, 320),		/* GPP_G */
+};
+
+static const struct pad_community ehl_communities[TOTAL_GPIO_COMM] = {
+	/* GPP F, B, A, S, R */
+	[COMM_0] = {
+		.port = PID_GPIOCOM0,
+		.first_pad = GPP_F0,
+		.last_pad = GPP_R7,
+		.num_gpi_regs = NUM_GPIO_COM0_GPI_REGS,
+		.pad_cfg_base = PAD_CFG_BASE,
+		.host_own_reg_0 = HOSTSW_OWN_REG_0,
+		.gpi_int_sts_reg_0 = GPI_INT_STS_0,
+		.gpi_int_en_reg_0 = GPI_INT_EN_0,
+		.gpi_smi_sts_reg_0 = GPI_SMI_STS_0,
+		.gpi_smi_en_reg_0 = GPI_SMI_EN_0,
+		.max_pads_per_group = GPIO_MAX_NUM_PER_GROUP,
+		.name = "GPP_FBASR",
+		.acpi_path = "\\_SB.PCI0.GPIO",
+		.reset_map = rst_map_com0,
+		.num_reset_vals = ARRAY_SIZE(rst_map_com0),
+		.groups = ehl_community0_groups,
+		.num_groups = ARRAY_SIZE(ehl_community0_groups),
+	},
+	/* GPP H, D, VGPIO, C */
+	[COMM_1] = {
+		.port = PID_GPIOCOM1,
+		.first_pad = GPP_H0,
+		.last_pad = GPP_C23,
+		.num_gpi_regs = NUM_GPIO_COM1_GPI_REGS,
+		.pad_cfg_base = PAD_CFG_BASE,
+		.host_own_reg_0 = HOSTSW_OWN_REG_0,
+		.gpi_int_sts_reg_0 = GPI_INT_STS_0,
+		.gpi_int_en_reg_0 = GPI_INT_EN_0,
+		.gpi_smi_sts_reg_0 = GPI_SMI_STS_0,
+		.gpi_smi_en_reg_0 = GPI_SMI_EN_0,
+		.max_pads_per_group = GPIO_MAX_NUM_PER_GROUP,
+		.name = "GPP_HDC",
+		.acpi_path = "\\_SB.PCI0.GPIO",
+		.reset_map = rst_map,
+		.num_reset_vals = ARRAY_SIZE(rst_map),
+		.groups = ehl_community1_groups,
+		.num_groups = ARRAY_SIZE(ehl_community1_groups),
+	},
+	/* GPD */
+	[COMM_2] = {
+		.port = PID_GPIOCOM2,
+		.first_pad = GPD0,
+		.last_pad = GPIO_RSVD_17,
+		.num_gpi_regs = NUM_GPIO_COM2_GPI_REGS,
+		.pad_cfg_base = PAD_CFG_BASE,
+		.host_own_reg_0 = HOSTSW_OWN_REG_0,
+		.gpi_int_sts_reg_0 = GPI_INT_STS_0,
+		.gpi_int_en_reg_0 = GPI_INT_EN_0,
+		.gpi_smi_sts_reg_0 = GPI_SMI_STS_0,
+		.gpi_smi_en_reg_0 = GPI_SMI_EN_0,
+		.max_pads_per_group = GPIO_MAX_NUM_PER_GROUP,
+		.name = "GPD",
+		.acpi_path = "\\_SB.PCI0.GPIO",
+		.reset_map = rst_map,
+		.num_reset_vals = ARRAY_SIZE(rst_map),
+		.groups = ehl_community2_groups,
+		.num_groups = ARRAY_SIZE(ehl_community2_groups),
+	},
+	/* GPP E */
+	[COMM_4] = {
+		.port = PID_GPIOCOM4,
+		.first_pad = GPIO_RSVD_18,
+		.last_pad = GPIO_RSVD_36,
+		.num_gpi_regs = NUM_GPIO_COM4_GPI_REGS,
+		.pad_cfg_base = PAD_CFG_BASE,
+		.host_own_reg_0 = HOSTSW_OWN_REG_0,
+		.gpi_int_sts_reg_0 = GPI_INT_STS_0,
+		.gpi_int_en_reg_0 = GPI_INT_EN_0,
+		.gpi_smi_sts_reg_0 = GPI_SMI_STS_0,
+		.gpi_smi_en_reg_0 = GPI_SMI_EN_0,
+		.max_pads_per_group = GPIO_MAX_NUM_PER_GROUP,
+		.name = "GPP_E",
+		.acpi_path = "\\_SB.PCI0.GPIO",
+		.reset_map = rst_map,
+		.num_reset_vals = ARRAY_SIZE(rst_map),
+		.groups = ehl_community4_groups,
+		.num_groups = ARRAY_SIZE(ehl_community4_groups),
+	},
+	/* GPP G */
+	[COMM_5] = {
+		.port = PID_GPIOCOM5,
+		.first_pad = GPP_G0,
+		.last_pad = GPP_G7,
+		.num_gpi_regs = NUM_GPIO_COM5_GPI_REGS,
+		.pad_cfg_base = PAD_CFG_BASE,
+		.host_own_reg_0 = HOSTSW_OWN_REG_0,
+		.gpi_int_sts_reg_0 = GPI_INT_STS_0,
+		.gpi_int_en_reg_0 = GPI_INT_EN_0,
+		.gpi_smi_sts_reg_0 = GPI_SMI_STS_0,
+		.gpi_smi_en_reg_0 = GPI_SMI_EN_0,
+		.max_pads_per_group = GPIO_MAX_NUM_PER_GROUP,
+		.name = "GPP_G",
+		.acpi_path = "\\_SB.PCI0.GPIO",
+		.reset_map = rst_map,
+		.num_reset_vals = ARRAY_SIZE(rst_map),
+		.groups = ehl_community5_groups,
+		.num_groups = ARRAY_SIZE(ehl_community5_groups),
+	}
+};
+
+const struct pad_community *soc_gpio_get_community(size_t *num_communities)
+{
+	*num_communities = ARRAY_SIZE(ehl_communities);
+	return ehl_communities;
+}
+
+const struct pmc_to_gpio_route *soc_pmc_gpio_routes(size_t *num)
+{
+	static const struct pmc_to_gpio_route routes[] = {
+		{ PMC_GPP_A, GPP_A },
+		{ PMC_GPP_B, GPP_B },
+		{ PMC_GPP_G, GPP_G },
+		{ PMC_GPP_C, GPP_C },
+		{ PMC_GPP_R, GPP_R },
+		{ PMC_GPP_D, GPP_D },
+		{ PMC_GPP_S, GPP_S },
+		{ PMC_GPP_H, GPP_H },
+		{ PMC_GPP_F, GPP_F },
+		{ PMC_GPD,   GPP_GPD },
+		{ PMC_GPP_E, GPP_E }
+	};
+
+	*num = ARRAY_SIZE(routes);
+	return routes;
+}
diff --git a/src/soc/intel/elkhartlake/gspi.c b/src/soc/intel/elkhartlake/gspi.c
new file mode 100644
index 0000000..61ad260
--- /dev/null
+++ b/src/soc/intel/elkhartlake/gspi.c
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include <intelblocks/gspi.h>
+#include <soc/pci_devs.h>
+
+int gspi_soc_bus_to_devfn(unsigned int gspi_bus)
+{
+	switch (gspi_bus) {
+	case 0:
+		return PCH_DEVFN_GSPI0;
+	case 1:
+		return PCH_DEVFN_GSPI1;
+	case 2:
+		return PCH_DEVFN_GSPI2;
+	}
+	return -1;
+}
diff --git a/src/soc/intel/elkhartlake/i2c.c b/src/soc/intel/elkhartlake/i2c.c
new file mode 100644
index 0000000..c13a1a6
--- /dev/null
+++ b/src/soc/intel/elkhartlake/i2c.c
@@ -0,0 +1,43 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <device/device.h>
+#include <drivers/i2c/designware/dw_i2c.h>
+#include <soc/pci_devs.h>
+
+int dw_i2c_soc_devfn_to_bus(unsigned int devfn)
+{
+	switch (devfn) {
+	case PCH_DEVFN_I2C0:
+		return 0;
+	case PCH_DEVFN_I2C1:
+		return 1;
+	case PCH_DEVFN_I2C2:
+		return 2;
+	case PCH_DEVFN_I2C3:
+		return 3;
+	case PCH_DEVFN_I2C4:
+		return 4;
+	case PCH_DEVFN_I2C5:
+		return 5;
+	}
+	return -1;
+}
+
+int dw_i2c_soc_bus_to_devfn(unsigned int bus)
+{
+	switch (bus) {
+	case 0:
+		return PCH_DEVFN_I2C0;
+	case 1:
+		return PCH_DEVFN_I2C1;
+	case 2:
+		return PCH_DEVFN_I2C2;
+	case 3:
+		return PCH_DEVFN_I2C3;
+	case 4:
+		return PCH_DEVFN_I2C4;
+	case 5:
+		return PCH_DEVFN_I2C5;
+	}
+	return -1;
+}
diff --git a/src/soc/intel/elkhartlake/include/soc/cpu.h b/src/soc/intel/elkhartlake/include/soc/cpu.h
new file mode 100644
index 0000000..6ee34f2
--- /dev/null
+++ b/src/soc/intel/elkhartlake/include/soc/cpu.h
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef _SOC_ELKHARTLAKE_CPU_H_
+#define _SOC_ELKHARTLAKE_CPU_H_
+
+#include <intelblocks/msr.h>
+
+/* Latency times in us */
+#define C1_LATENCY	1
+#define C6_LATENCY	127
+#define C7_LATENCY	253
+#define C8_LATENCY	260
+#define C9_LATENCY	487
+#define C10_LATENCY	1048
+
+/* Power in units of mW */
+#define C1_POWER	0x3e8
+#define C6_POWER	0x15e
+#define C7_POWER	0xc8
+#define C8_POWER	0xc8
+#define C9_POWER	0xc8
+#define C10_POWER	0xc8
+
+/* Common Timer Copy (CTC) frequency - 38.4MHz. */
+#define CTC_FREQ	38400000
+
+#define C_STATE_LATENCY_MICRO_SECONDS(limit, base) \
+	(((1 << ((base)*5)) * (limit)) / 1000)
+#define C_STATE_LATENCY_FROM_LAT_REG(reg) \
+	C_STATE_LATENCY_MICRO_SECONDS(C_STATE_LATENCY_CONTROL_ ##reg## _LIMIT, \
+				      (IRTL_1024_NS >> 10))
+
+#endif
diff --git a/src/soc/intel/elkhartlake/include/soc/espi.h b/src/soc/intel/elkhartlake/include/soc/espi.h
index 80b5c1e..6c26158 100644
--- a/src/soc/intel/elkhartlake/include/soc/espi.h
+++ b/src/soc/intel/elkhartlake/include/soc/espi.h
@@ -15,14 +15,16 @@
 #define SCIS_IRQ23		7
 #define SERIRQ_CNTL		0x64
 #define ESPI_IO_DEC		0x80 /* IO Decode Ranges Register */
-#define   COMA_RANGE		0x0 /* 0x3F8 - 0x3FF COM1*/
-#define   COMB_RANGE		0x1 /* 0x2F8 - 0x2FF COM2*/
+#define COMA_RANGE		0x0 /* 0x3F8 - 0x3FF COM1*/
+#define COMB_RANGE		0x1 /* 0x2F8 - 0x2FF COM2*/
 #define ESPI_GEN1_DEC		0x84 /* ESPI IF Generic Decode Range 1 */
 #define ESPI_GEN2_DEC		0x88 /* ESPI IF Generic Decode Range 2 */
 #define ESPI_GEN3_DEC		0x8c /* ESPI IF Generic Decode Range 3 */
 #define ESPI_GEN4_DEC		0x90 /* ESPI IF Generic Decode Range 4 */
 #define LGMR			0x98 /* ESPI Generic Memory Range */
+#define NMI_EN			0x70
+#define NMI_STS_CNT		0x61
 #define PCCTL			0xE0 /* PCI Clock Control */
-#define   CLKRUN_EN		(1 << 0)
+#define CLKRUN_EN		(1 << 0)
 
 #endif
diff --git a/src/soc/intel/elkhartlake/include/soc/gpe.h b/src/soc/intel/elkhartlake/include/soc/gpe.h
new file mode 100644
index 0000000..34dfcea
--- /dev/null
+++ b/src/soc/intel/elkhartlake/include/soc/gpe.h
@@ -0,0 +1,121 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef _SOC_GPE_H_
+#define _SOC_GPE_H_
+
+/* GPE_31_0 */
+#define GPE0_DW0_00		0
+#define GPE0_DW0_01		1
+#define GPE0_DW0_02		2
+#define GPE0_DW0_03		3
+#define GPE0_DW0_04		4
+#define GPE0_DW0_05		5
+#define GPE0_DW0_06		6
+#define GPE0_DW0_07		7
+#define GPE0_DW0_08		8
+#define GPE0_DW0_09		9
+#define GPE0_DW0_10		10
+#define GPE0_DW0_11		11
+#define GPE0_DW0_12		12
+#define GPE0_DW0_13		13
+#define GPE0_DW0_14		14
+#define GPE0_DW0_15		15
+#define GPE0_DW0_16		16
+#define GPE0_DW0_17		17
+#define GPE0_DW0_18		18
+#define GPE0_DW0_19		19
+#define GPE0_DW0_20		20
+#define GPE0_DW0_21		21
+#define GPE0_DW0_22		22
+#define GPE0_DW0_23		23
+#define GPE0_DW0_24		24
+#define GPE0_DW0_25		25
+#define GPE0_DW0_26		26
+#define GPE0_DW0_27		27
+#define GPE0_DW0_28		28
+#define GPE0_DW0_29		29
+#define GPE0_DW0_30		30
+#define GPE0_DW0_31		31
+/* GPE_63_32 */
+#define GPE0_DW1_00		32
+#define GPE0_DW1_01		33
+#define GPE0_DW1_02		34
+#define GPE0_DW1_03		36
+#define GPE0_DW1_04		36
+#define GPE0_DW1_05		37
+#define GPE0_DW1_06		38
+#define GPE0_DW1_07		39
+#define GPE0_DW1_08		40
+#define GPE0_DW1_09		41
+#define GPE0_DW1_10		42
+#define GPE0_DW1_11		43
+#define GPE0_DW1_12		44
+#define GPE0_DW1_13		45
+#define GPE0_DW1_14		46
+#define GPE0_DW1_15		47
+#define GPE0_DW1_16		48
+#define GPE0_DW1_17		49
+#define GPE0_DW1_18		50
+#define GPE0_DW1_19		51
+#define GPE0_DW1_20		52
+#define GPE0_DW1_21		53
+#define GPE0_DW1_22		54
+#define GPE0_DW1_23		55
+#define GPE0_DW1_24		56
+#define GPE0_DW1_25		57
+#define GPE0_DW1_26		58
+#define GPE0_DW1_27		59
+#define GPE0_DW1_28		60
+#define GPE0_DW1_29		61
+#define GPE0_DW1_30		62
+#define GPE0_DW1_31		63
+/* GPE_95_64 */
+#define GPE0_DW2_00		64
+#define GPE0_DW2_01		65
+#define GPE0_DW2_02		66
+#define GPE0_DW2_03		67
+#define GPE0_DW2_04		68
+#define GPE0_DW2_05		69
+#define GPE0_DW2_06		70
+#define GPE0_DW2_07		71
+#define GPE0_DW2_08		72
+#define GPE0_DW2_09		73
+#define GPE0_DW2_10		74
+#define GPE0_DW2_11		75
+#define GPE0_DW2_12		76
+#define GPE0_DW2_13		77
+#define GPE0_DW2_14		78
+#define GPE0_DW2_15		79
+#define GPE0_DW2_16		80
+#define GPE0_DW2_17		81
+#define GPE0_DW2_18		82
+#define GPE0_DW2_19		83
+#define GPE0_DW2_20		84
+#define GPE0_DW2_21		85
+#define GPE0_DW2_22		86
+#define GPE0_DW2_23		87
+#define GPE0_DW2_24		88
+#define GPE0_DW2_25		89
+#define GPE0_DW2_26		90
+#define GPE0_DW2_27		91
+#define GPE0_DW2_28		92
+#define GPE0_DW2_29		93
+#define GPE0_DW2_30		94
+#define GPE0_DW2_31		95
+/* GPE_STD */
+#define GPE0_HOT_PLUG		97
+#define GPE0_SWGPE		98
+#define GPE0_TCOSCI		102
+#define GPE0_SMB_WAK		103
+#define GPE0_PCI_EXP		105
+#define GPE0_BATLOW		106
+#define GPE0_PME		107
+#define GPE0_ME_SCI		108
+#define GPE0_PME_B0		109
+#define GPE0_ESPI		110
+#define GPE0_GPIO_T2		111
+#define GPE0_LAN_WAK		112
+#define GPE0_WADT		114
+
+#define GPE_MAX			GPE0_WADT
+#endif /* _SOC_GPE_H_ */
diff --git a/src/soc/intel/elkhartlake/include/soc/gpio.h b/src/soc/intel/elkhartlake/include/soc/gpio.h
new file mode 100644
index 0000000..6cca742
--- /dev/null
+++ b/src/soc/intel/elkhartlake/include/soc/gpio.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef _SOC_ELKHARTLAKE_GPIO_H_
+#define _SOC_ELKHARTLAKE_GPIO_H_
+
+#include <intelblocks/gpio.h>
+#include <soc/gpio_defs.h>
+
+#define CROS_GPIO_NAME		"INT34C8"
+#define CROS_GPIO_COMM0_NAME    "INT34C8:00"
+#define CROS_GPIO_COMM1_NAME    "INT34C8:01"
+#define CROS_GPIO_COMM4_NAME    "INT34C8:02"
+#define CROS_GPIO_COMM5_NAME    "INT34C8:03"
+
+#endif
diff --git a/src/soc/intel/elkhartlake/include/soc/gpio_defs.h b/src/soc/intel/elkhartlake/include/soc/gpio_defs.h
new file mode 100644
index 0000000..0b8d8a7
--- /dev/null
+++ b/src/soc/intel/elkhartlake/include/soc/gpio_defs.h
@@ -0,0 +1,260 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef _SOC_ELKHARTLAKE_GPIO_DEFS_H_
+#define _SOC_ELKHARTLAKE_GPIO_DEFS_H_
+
+#ifndef __ACPI__
+#include <stddef.h>
+#endif
+#include <soc/gpio_soc_defs.h>
+
+
+#define GPIO_NUM_PAD_CFG_REGS   4 /* DW0, DW1, DW2, DW3 */
+
+#define NUM_GPIO_COMx_GPI_REGS(n)	\
+		(ALIGN_UP((n), GPIO_MAX_NUM_PER_GROUP) / GPIO_MAX_NUM_PER_GROUP)
+
+#define NUM_GPIO_COM0_GPI_REGS NUM_GPIO_COMx_GPI_REGS(NUM_GPIO_COM0_PADS)
+#define NUM_GPIO_COM1_GPI_REGS NUM_GPIO_COMx_GPI_REGS(NUM_GPIO_COM1_PADS)
+#define NUM_GPIO_COM2_GPI_REGS NUM_GPIO_COMx_GPI_REGS(NUM_GPIO_COM2_PADS)
+#define NUM_GPIO_COM4_GPI_REGS NUM_GPIO_COMx_GPI_REGS(NUM_GPIO_COM4_PADS)
+#define NUM_GPIO_COM5_GPI_REGS NUM_GPIO_COMx_GPI_REGS(NUM_GPIO_COM5_PADS)
+
+#define NUM_GPI_STATUS_REGS	\
+		((NUM_GPIO_COM0_GPI_REGS) +\
+		(NUM_GPIO_COM1_GPI_REGS) +\
+		(NUM_GPIO_COM2_GPI_REGS) +\
+		(NUM_GPIO_COM4_GPI_REGS) +\
+		(NUM_GPIO_COM5_GPI_REGS))
+/*
+ * IOxAPIC IRQs for the GPIOs
+ */
+
+/* Group F */
+#define GPP_F0_IRQ				0x40
+#define GPP_F1_IRQ				0x41
+#define GPP_F2_IRQ				0x42
+#define GPP_F3_IRQ				0x43
+#define GPP_F4_IRQ				0x44
+#define GPP_F5_IRQ				0x45
+#define GPP_F6_IRQ				0x46
+#define GPP_F7_IRQ				0x47
+#define GPP_F8_IRQ				0x48
+#define GPP_F9_IRQ				0x49
+#define GPP_F10_IRQ				0x4a
+#define GPP_F11_IRQ				0x4b
+#define GPP_F12_IRQ				0x4c
+#define GPP_F13_IRQ				0x4d
+#define GPP_F14_IRQ				0x4e
+#define GPP_F15_IRQ				0x4f
+#define GPP_F16_IRQ				0x50
+#define GPP_F17_IRQ				0x51
+#define GPP_F18_IRQ				0x52
+#define GPP_F19_IRQ				0x53
+
+/* Group G */
+#define GPP_G0_IRQ				0x18
+#define GPP_G1_IRQ				0x19
+#define GPP_G2_IRQ				0x1a
+#define GPP_G3_IRQ				0x1b
+#define GPP_G4_IRQ				0x1c
+#define GPP_G5_IRQ				0x1d
+#define GPP_G6_IRQ				0x1e
+#define GPP_G7_IRQ				0x1f
+
+/* Group B */
+#define GPP_B0_IRQ				0x20
+#define GPP_B1_IRQ				0x21
+#define GPP_B2_IRQ				0x22
+#define GPP_B3_IRQ				0x23
+#define GPP_B4_IRQ				0x24
+#define GPP_B5_IRQ				0x25
+#define GPP_B6_IRQ				0x26
+#define GPP_B7_IRQ				0x27
+#define GPP_B8_IRQ				0x28
+#define GPP_B9_IRQ				0x29
+#define GPP_B10_IRQ				0x2a
+#define GPP_B11_IRQ				0x2b
+#define GPP_B12_IRQ				0x2c
+#define GPP_B13_IRQ				0x2d
+#define GPP_B14_IRQ				0x2e
+#define GPP_B15_IRQ				0x2f
+#define GPP_B16_IRQ				0x30
+#define GPP_B17_IRQ				0x31
+#define GPP_B18_IRQ				0x32
+#define GPP_B19_IRQ				0x33
+#define GPP_B20_IRQ				0x34
+#define GPP_B21_IRQ				0x35
+#define GPP_B22_IRQ				0x36
+#define GPP_B23_IRQ				0x37
+
+/* Group A */
+#define GPP_A0_IRQ				0x38
+#define GPP_A1_IRQ				0x39
+#define GPP_A2_IRQ				0x3a
+#define GPP_A3_IRQ				0x3b
+#define GPP_A4_IRQ				0x3c
+#define GPP_A5_IRQ				0x3d
+#define GPP_A6_IRQ				0x3e
+#define GPP_A7_IRQ				0x3f
+#define GPP_A8_IRQ				0x40
+#define GPP_A9_IRQ				0x41
+#define GPP_A10_IRQ				0x42
+#define GPP_A11_IRQ				0x43
+#define GPP_A12_IRQ				0x44
+#define GPP_A13_IRQ				0x45
+#define GPP_A14_IRQ				0x46
+#define GPP_A15_IRQ				0x47
+#define GPP_A16_IRQ				0x48
+#define GPP_A17_IRQ				0x49
+#define GPP_A18_IRQ				0x4a
+#define GPP_A19_IRQ				0x4b
+
+/* Group H */
+#define GPP_H0_IRQ				0x70
+#define GPP_H1_IRQ				0x71
+#define GPP_H2_IRQ				0x72
+#define GPP_H3_IRQ				0x73
+#define GPP_H4_IRQ				0x74
+#define GPP_H5_IRQ				0x75
+#define GPP_H6_IRQ				0x76
+#define GPP_H7_IRQ				0x77
+#define GPP_H8_IRQ				0x18
+#define GPP_H9_IRQ				0x19
+#define GPP_H10_IRQ				0x1a
+#define GPP_H11_IRQ				0x1b
+#define GPP_H12_IRQ				0x1c
+#define GPP_H13_IRQ				0x1d
+#define GPP_H14_IRQ				0x1e
+#define GPP_H15_IRQ				0x1f
+#define GPP_H16_IRQ				0x20
+#define GPP_H17_IRQ				0x21
+#define GPP_H18_IRQ				0x22
+#define GPP_H19_IRQ				0x23
+#define GPP_H20_IRQ				0x24
+#define GPP_H21_IRQ				0x25
+#define GPP_H22_IRQ				0x26
+#define GPP_H23_IRQ				0x27
+
+/* Group D */
+#define GPP_D0_IRQ				0x28
+#define GPP_D1_IRQ				0x29
+#define GPP_D2_IRQ				0x2a
+#define GPP_D3_IRQ				0x2b
+#define GPP_D4_IRQ				0x2c
+#define GPP_D5_IRQ				0x2d
+#define GPP_D6_IRQ				0x2e
+#define GPP_D7_IRQ				0x2f
+#define GPP_D8_IRQ				0x30
+#define GPP_D9_IRQ				0x31
+#define GPP_D10_IRQ				0x32
+#define GPP_D11_IRQ				0x33
+#define GPP_D12_IRQ				0x34
+#define GPP_D13_IRQ				0x35
+#define GPP_D14_IRQ				0x36
+#define GPP_D15_IRQ				0x37
+#define GPP_D16_IRQ				0x38
+#define GPP_D17_IRQ				0x39
+#define GPP_D18_IRQ				0x3a
+#define GPP_D19_IRQ				0x3b
+#define GPP_D20_IRQ				0x3c
+#define GPP_D21_IRQ				0x3d
+#define GPP_D22_IRQ				0x3e
+#define GPP_D23_IRQ				0x3f
+
+/* Group GPD */
+#define GPD0_IRQ				0x64
+#define GPD1_IRQ				0x65
+#define GPD2_IRQ				0x66
+#define GPD3_IRQ				0x67
+#define GPD4_IRQ				0x68
+#define GPD5_IRQ				0x69
+#define GPD6_IRQ				0x6a
+#define GPD7_IRQ				0x6b
+#define GPD8_IRQ				0x6c
+#define GPD9_IRQ				0x6d
+#define GPD10_IRQ				0x6e
+
+/* Group C */
+#define GPP_C0_IRQ				0x5a
+#define GPP_C1_IRQ				0x5b
+#define GPP_C2_IRQ				0x5c
+#define GPP_C3_IRQ				0x5d
+#define GPP_C4_IRQ				0x5e
+#define GPP_C5_IRQ				0x5f
+#define GPP_C6_IRQ				0x60
+#define GPP_C7_IRQ				0x61
+#define GPP_C8_IRQ				0x62
+#define GPP_C9_IRQ				0x63
+#define GPP_C10_IRQ				0x64
+#define GPP_C11_IRQ				0x65
+#define GPP_C12_IRQ				0x66
+#define GPP_C13_IRQ				0x67
+#define GPP_C14_IRQ				0x68
+#define GPP_C15_IRQ				0x69
+#define GPP_C16_IRQ				0x6a
+#define GPP_C17_IRQ				0x6b
+#define GPP_C18_IRQ				0x6c
+#define GPP_C19_IRQ				0x6d
+#define GPP_C20_IRQ				0x6e
+#define GPP_C21_IRQ				0x6f
+#define GPP_C22_IRQ				0x70
+#define GPP_C23_IRQ				0x71
+/* Group E */
+#define GPP_E0_IRQ				0x72
+#define GPP_E1_IRQ				0x73
+#define GPP_E2_IRQ				0x74
+#define GPP_E3_IRQ				0x75
+#define GPP_E4_IRQ				0x76
+#define GPP_E5_IRQ				0x77
+#define GPP_E6_IRQ				0x18
+#define GPP_E7_IRQ				0x19
+#define GPP_E8_IRQ				0x1a
+#define GPP_E9_IRQ				0x1b
+#define GPP_E10_IRQ				0x1c
+#define GPP_E11_IRQ				0x1d
+#define GPP_E12_IRQ				0x1e
+#define GPP_E13_IRQ				0x1f
+#define GPP_E14_IRQ				0x20
+#define GPP_E15_IRQ				0x21
+#define GPP_E16_IRQ				0x22
+#define GPP_E17_IRQ				0x23
+#define GPP_E18_IRQ				0x24
+#define GPP_E19_IRQ				0x25
+#define GPP_E20_IRQ				0x26
+#define GPP_E21_IRQ				0x27
+#define GPP_E22_IRQ				0x28
+#define GPP_E23_IRQ				0x29
+
+/* Group R*/
+#define GPP_R0_IRQ				0x50
+#define GPP_R1_IRQ				0x51
+#define GPP_R2_IRQ				0x52
+#define GPP_R3_IRQ				0x53
+#define GPP_R4_IRQ				0x54
+#define GPP_R5_IRQ				0x55
+#define GPP_R6_IRQ				0x56
+#define GPP_R7_IRQ				0x57
+
+/* Group S */
+#define GPP_S0_IRQ				0x5c
+#define GPP_S1_IRQ				0x5d
+#define GPP_S2_IRQ				0x5e
+#define GPP_S3_IRQ				0x5f
+#define GPP_S4_IRQ				0x60
+#define GPP_S5_IRQ				0x61
+#define GPP_S6_IRQ				0x62
+#define GPP_S7_IRQ				0x63
+
+/* Register defines. */
+#define GPIO_MISCCFG				0x10
+#define GPE_DW_SHIFT				8
+#define GPE_DW_MASK				0xfff00
+#define HOSTSW_OWN_REG_0			0xc0
+#define GPI_INT_STS_0				0x100
+#define GPI_INT_EN_0				0x120
+#define GPI_SMI_STS_0				0x180
+#define GPI_SMI_EN_0				0x1a0
+#define PAD_CFG_BASE				0x600
+
+#endif
diff --git a/src/soc/intel/elkhartlake/include/soc/gpio_soc_defs.h b/src/soc/intel/elkhartlake/include/soc/gpio_soc_defs.h
new file mode 100644
index 0000000..278c2c6
--- /dev/null
+++ b/src/soc/intel/elkhartlake/include/soc/gpio_soc_defs.h
@@ -0,0 +1,347 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef _SOC_ELKHARTLAKE_GPIO_SOC_DEFS_H_
+#define _SOC_ELKHARTLAKE_GPIO_SOC_DEFS_H_
+
+/*
+ * Most of the fixed numbers and macros are based on the GPP groups.
+ * The GPIO groups are accessed through register blocks called
+ * communities.
+ */
+
+#define GPP_A			0x0
+#define GPP_B			0x1
+#define GPP_G			0x2
+#define GPP_C			0x3
+#define GPP_R			0x4
+#define GPP_D			0x5
+#define GPP_S			0x6
+#define GPP_H			0x7
+#define GPP_VGPIO		0x8
+#define GPP_F			0x9
+#define GPP_GPD			0xA
+#define GPP_E			0xD
+
+#define GPIO_NUM_GROUPS		12
+#define GPIO_MAX_NUM_PER_GROUP	24
+#define SD_PWR_EN_PIN		GPP_H1
+
+/*
+ * GPIOs are ordered monotonically increasing to match ACPI/OS driver.
+ */
+
+/* Group F */
+#define GPP_F0		0
+#define GPP_F1		1
+#define GPP_F2		2
+#define GPP_F3		3
+#define GPP_F4		4
+#define GPP_F5		5
+#define GPP_F6		6
+#define GPP_F7		7
+#define GPP_F8		8
+#define GPP_F9		9
+#define GPP_F10		10
+#define GPP_F11		11
+#define GPP_F12		12
+#define GPP_F13		13
+#define GPP_F14		14
+#define GPP_F15		15
+#define GPP_F16		16
+#define GPP_F17		17
+#define GPP_F18		18
+#define GPP_F19		19
+
+/* Group B */
+#define GPIO_RSVD_0	20
+#define GPIO_RSVD_1	21
+#define GPIO_RSVD_2	22
+#define GPIO_RSVD_3	23
+#define GPIO_RSVD_4	24
+#define GPIO_RSVD_5	25
+#define GPIO_RSVD_6	26
+#define GPIO_RSVD_7	27
+#define GPIO_RSVD_8	28
+#define GPP_B0		29
+#define GPP_B1		30
+#define GPP_B2		31
+#define GPP_B3		32
+#define GPP_B4		33
+#define GPP_B5		34
+#define GPP_B6		35
+#define GPP_B7		36
+#define GPP_B8		37
+#define GPP_B9		38
+#define GPP_B10		39
+#define GPP_B11		40
+#define GPP_B12		41
+#define GPP_B13		42
+#define GPP_B14		43
+#define GPP_B15		44
+#define GPP_B16		45
+#define GPP_B17		46
+#define GPP_B18		47
+#define GPP_B19		48
+#define GPP_B20		49
+#define GPP_B21		50
+#define GPP_B22		51
+#define GPP_B23		52
+#define GPIO_RSVD_9	53
+#define GPIO_RSVD_10	54
+
+/* Group A */
+#define GPP_A0		55
+#define GPP_A1		56
+#define GPP_A2		57
+#define GPP_A3		58
+#define GPP_A4		59
+#define GPP_A5		60
+#define GPP_A6		61
+#define GPP_A7		62
+#define GPP_A8		63
+#define GPP_A9		64
+#define GPP_A10		65
+#define GPP_A11		66
+#define GPP_A12		67
+#define GPP_A13		68
+#define GPP_A14		69
+#define GPP_A15		70
+#define GPP_A16		71
+#define GPP_A17		72
+#define GPP_A18		73
+#define GPP_A19		74
+#define GPIO_RSVD_11	75
+
+/* Group S */
+#define GPP_S0		76
+#define GPP_S1		77
+#define GPP_S2		78
+#define GPP_S3		79
+#define GPP_S4		80
+#define GPP_S5		81
+#define GPP_S6		82
+#define GPP_S7		83
+
+/* Group R */
+#define GPP_R0		84
+#define GPP_R1		85
+#define GPP_R2		86
+#define GPP_R3		87
+#define GPP_R4		88
+#define GPP_R5		89
+#define GPP_R6		90
+#define GPP_R7		91
+
+#define GPIO_COM0_START		GPP_F0
+#define GPIO_COM0_END		GPP_R7
+#define NUM_GPIO_COM0_PADS	(GPIO_COM0_END - GPIO_COM0_START + 1)
+
+/* Group H */
+#define GPP_H0		92
+#define GPP_H1		93
+#define GPP_H2		94
+#define GPP_H3		95
+#define GPP_H4		96
+#define GPP_H5		97
+#define GPP_H6		98
+#define GPP_H7		99
+#define GPP_H8		100
+#define GPP_H9		101
+#define GPP_H10		102
+#define GPP_H11		103
+#define GPP_H12		104
+#define GPP_H13		105
+#define GPP_H14		106
+#define GPP_H15		107
+#define GPP_H16		108
+#define GPP_H17		109
+#define GPP_H18		110
+#define GPP_H19		111
+#define GPP_H20		112
+#define GPP_H21		113
+#define GPP_H22		114
+#define GPP_H23		115
+
+/* Group D */
+#define GPP_D0		116
+#define GPP_D1		117
+#define GPP_D2		118
+#define GPP_D3		119
+#define GPP_D4		120
+#define GPP_D5		121
+#define GPP_D6		122
+#define GPP_D7		123
+#define GPP_D8		124
+#define GPP_D9		125
+#define GPP_D10		126
+#define GPP_D11		127
+#define GPP_D12		128
+#define GPP_D13		129
+#define GPP_D14		130
+#define GPP_D15		131
+#define GPP_D16		132
+#define GPP_D17		133
+#define GPP_D18		134
+#define GPP_D19		135
+#define GPP_D20		136
+#define GPP_D21		137
+#define GPP_D22		138
+#define GPP_D23		139
+#define GPIO_RSVD_12	140
+#define GPIO_RSVD_13	141
+
+/* Group VGPIO */
+#define VGPIO_0		142
+#define VGPIO_3		143
+#define VGPIO_4		144
+#define VGPIO_5		145
+#define VGPIO_6		146
+#define VGPIO_7		147
+#define VGPIO_8		148
+#define VGPIO_9		149
+#define VGPIO_10	150
+#define VGPIO_11	151
+#define VGPIO_12	152
+#define VGPIO_13	153
+#define VGPIO_18	154
+#define VGPIO_19	155
+#define VGPIO_20	156
+#define VGPIO_21	157
+#define VGPIO_22	158
+#define VGPIO_23	159
+#define VGPIO_24	160
+#define VGPIO_25	161
+#define VGPIO_30	162
+#define VGPIO_31	163
+#define VGPIO_32	164
+#define VGPIO_33	165
+#define VGPIO_34	166
+#define VGPIO_35	167
+#define VGPIO_36	168
+#define VGPIO_37	169
+#define VGPIO_39	170
+
+/* Group C */
+#define GPP_C0		171
+#define GPP_C1		172
+#define GPP_C2		173
+#define GPP_C3		174
+#define GPP_C4		175
+#define GPP_C5		176
+#define GPP_C6		177
+#define GPP_C7		178
+#define GPP_C8		179
+#define GPP_C9		180
+#define GPP_C10		181
+#define GPP_C11		182
+#define GPP_C12		183
+#define GPP_C13		184
+#define GPP_C14		185
+#define GPP_C15		186
+#define GPP_C16		187
+#define GPP_C17		188
+#define GPP_C18		189
+#define GPP_C19		190
+#define GPP_C20		191
+#define GPP_C21		192
+#define GPP_C22		193
+#define GPP_C23		194
+
+#define GPIO_COM1_START		GPP_H0
+#define GPIO_COM1_END		GPP_C23
+#define NUM_GPIO_COM1_PADS	(GPIO_COM1_END - GPIO_COM1_START + 1)
+
+/* Group GPD */
+#define GPD0		195
+#define GPD1		196
+#define GPD2		197
+#define GPD3		198
+#define GPD4		199
+#define GPD5		200
+#define GPD6		201
+#define GPD7		202
+#define GPD8		203
+#define GPD9		204
+#define GPD10		205
+#define GPIO_RSVD_14	206
+#define GPIO_RSVD_15	207
+#define GPIO_RSVD_16	208
+#define GPIO_RSVD_17	209
+
+#define GPIO_COM2_START		GPD0
+#define GPIO_COM2_END		GPIO_RSVD_17
+#define NUM_GPIO_COM2_PADS	(GPIO_COM2_END - GPIO_COM2_START + 1)
+
+/* Group E */
+#define GPIO_RSVD_18	210
+#define GPIO_RSVD_19	211
+#define GPIO_RSVD_20	212
+#define GPIO_RSVD_21	213
+#define GPIO_RSVD_22	214
+#define GPIO_RSVD_23	215
+#define GPP_E0		216
+#define GPP_E1		217
+#define GPP_E2		218
+#define GPP_E3		219
+#define GPP_E4		220
+#define GPP_E5		221
+#define GPP_E6		222
+#define GPP_E7		223
+#define GPP_E8		224
+#define GPP_E9		225
+#define GPP_E10		226
+#define GPP_E11		227
+#define GPP_E12		228
+#define GPP_E13		229
+#define GPP_E14		230
+#define GPP_E15		231
+#define GPP_E16		232
+#define GPP_E17		233
+#define GPP_E18		234
+#define GPP_E19		235
+#define GPP_E20		236
+#define GPP_E21		237
+#define GPP_E22		238
+#define GPP_E23		239
+#define GPIO_RSVD_24	240
+#define GPIO_RSVD_25	241
+#define GPIO_RSVD_26	242
+#define GPIO_RSVD_27	243
+#define GPIO_RSVD_28	244
+#define GPIO_RSVD_29	245
+#define GPIO_RSVD_30	246
+#define GPIO_RSVD_31	247
+#define GPIO_RSVD_32	248
+#define GPIO_RSVD_33	249
+#define GPIO_RSVD_34	250
+#define GPIO_RSVD_35	251
+#define GPIO_RSVD_36	252
+
+#define GPIO_COM4_START		GPIO_RSVD_18
+#define GPIO_COM4_END		GPIO_RSVD_36
+#define NUM_GPIO_COM4_PADS	(GPIO_COM4_END - GPIO_COM4_START + 1)
+
+/* Group G */
+#define GPP_G0		253
+#define GPP_G1		254
+#define GPP_G2		255
+#define GPP_G3		256
+#define GPP_G4		257
+#define GPP_G5		258
+#define GPP_G6		259
+#define GPP_G7		260
+
+#define GPIO_COM5_START		GPP_G0
+#define GPIO_COM5_END		GPP_G7
+#define NUM_GPIO_COM5_PADS	(GPIO_COM5_END - GPIO_COM5_START + 1)
+
+#define TOTAL_PADS	261
+
+#define COMM_0		0
+#define COMM_1		1
+#define COMM_2		2
+#define COMM_4		3
+#define COMM_5		4
+#define TOTAL_GPIO_COMM	5
+
+#endif
diff --git a/src/soc/intel/elkhartlake/include/soc/irq.h b/src/soc/intel/elkhartlake/include/soc/irq.h
new file mode 100644
index 0000000..ac45424
--- /dev/null
+++ b/src/soc/intel/elkhartlake/include/soc/irq.h
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef _SOC_EHL_IRQ_H_
+#define _SOC_EHL_IRQ_H_
+
+#define GPIO_IRQ14 14
+#define GPIO_IRQ15 15
+
+#define PCH_IRQ10 10
+#define PCH_IRQ11 11
+
+/* LPSS Device IRQs */
+#define LPSS_I2C0_IRQ 16
+#define LPSS_I2C1_IRQ 17
+#define LPSS_I2C2_IRQ 18
+#define LPSS_I2C3_IRQ 19
+#define LPSS_I2C4_IRQ 32
+#define LPSS_I2C5_IRQ 33
+#define LPSS_SPI0_IRQ 22
+#define LPSS_SPI1_IRQ 23
+#define LPSS_SPI2_IRQ 24
+#define LPSS_UART0_IRQ 20
+#define LPSS_UART1_IRQ 21
+#define LPSS_UART2_IRQ 34
+
+/* PCI shared IRQs */
+#define PCH_IRQ_16 16
+#define PCH_IRQ_17 17
+#define PCH_IRQ_18 18
+#define PCH_IRQ_19 19
+#define PCH_IRQ_20 20
+#define PCH_IRQ_21 21
+#define PCH_IRQ_22 22
+#define PCH_IRQ_23 23
+
+#endif /* _EHL_IRQ_H_ */
diff --git a/src/soc/intel/elkhartlake/include/soc/itss.h b/src/soc/intel/elkhartlake/include/soc/itss.h
new file mode 100644
index 0000000..a550f4c
--- /dev/null
+++ b/src/soc/intel/elkhartlake/include/soc/itss.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef SOC_INTEL_EHL_ITSS_H
+#define SOC_INTEL_EHL_ITSS_H
+
+#define GPIO_IRQ_START	50
+#define GPIO_IRQ_END	ITSS_MAX_IRQ
+
+#define ITSS_MAX_IRQ	119
+#define IRQS_PER_IPC	32
+#define NUM_IPC_REGS	((ITSS_MAX_IRQ + IRQS_PER_IPC - 1)/IRQS_PER_IPC)
+
+#endif	/* SOC_INTEL_EHL_ITSS_H */
diff --git a/src/soc/intel/elkhartlake/include/soc/me.h b/src/soc/intel/elkhartlake/include/soc/me.h
new file mode 100644
index 0000000..d845629
--- /dev/null
+++ b/src/soc/intel/elkhartlake/include/soc/me.h
@@ -0,0 +1,123 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef _ELKHARTLAKE_ME_H_
+#define _ELKHARTLAKE_ME_H_
+
+/* ME Host Firmware Status register 1 */
+union me_hfsts1 {
+	uint32_t data;
+	struct {
+		uint32_t working_state: 4;
+		uint32_t mfg_mode: 1;
+		uint32_t fpt_bad: 1;
+		uint32_t operation_state: 3;
+		uint32_t fw_init_complete: 1;
+		uint32_t ft_bup_ld_flr: 1;
+		uint32_t update_in_progress: 1;
+		uint32_t error_code: 4;
+		uint32_t operation_mode: 4;
+		uint32_t reset_count: 4;
+		uint32_t boot_options_present: 1;
+		uint32_t reserved1: 1;
+		uint32_t bist_test_state: 1;
+		uint32_t bist_reset_request: 1;
+		uint32_t current_power_source: 2;
+		uint32_t reserved: 1;
+		uint32_t d0i3_support_valid: 1;
+	} __packed fields;
+};
+
+/* Host Firmware Status Register 2 */
+union me_hfsts2 {
+	uint32_t data;
+	struct {
+		uint32_t nftp_load_failure	: 1;
+		uint32_t icc_prog_status	: 2;
+		uint32_t invoke_mebx		: 1;
+		uint32_t cpu_replaced		: 1;
+		uint32_t rsvd0			: 1;
+		uint32_t mfs_failure		: 1;
+		uint32_t warm_reset_rqst	: 1;
+		uint32_t cpu_replaced_valid	: 1;
+		uint32_t low_power_state	: 1;
+		uint32_t me_power_gate		: 1;
+		uint32_t ipu_needed		: 1;
+		uint32_t forced_safe_boot	: 1;
+		uint32_t rsvd1			: 2;
+		uint32_t listener_change	: 1;
+		uint32_t status_data		: 8;
+		uint32_t current_pmevent	: 4;
+		uint32_t phase			: 4;
+	} __packed fields;
+};
+
+/* ME Host Firmware Status Register 3 */
+union me_hfsts3 {
+	uint32_t data;
+	struct {
+		uint32_t reserved_0: 4;
+		uint32_t fw_sku: 3;
+		uint32_t reserved: 25;
+	} __packed fields;
+};
+
+/* Host Firmware Status Register 4 */
+union me_hfsts4 {
+	uint32_t data;
+	struct {
+		uint32_t rsvd0			: 9;
+		uint32_t enforcement_flow	: 1;
+		uint32_t sx_resume_type		: 1;
+		uint32_t rsvd1			: 1;
+		uint32_t tpms_disconnected	: 1;
+		uint32_t rvsd2			: 1;
+		uint32_t fwsts_valid		: 1;
+		uint32_t boot_guard_self_test	: 1;
+		uint32_t rsvd3			: 16;
+	} __packed fields;
+};
+
+/* Host Firmware Status Register 5 */
+union me_hfsts5 {
+	uint32_t data;
+	struct {
+		uint32_t acm_active		: 1;
+		uint32_t valid			: 1;
+		uint32_t result_code_source	: 1;
+		uint32_t error_status_code	: 5;
+		uint32_t acm_done_sts		: 1;
+		uint32_t timeout_count		: 7;
+		uint32_t scrtm_indicator	: 1;
+		uint32_t inc_boot_guard_acm	: 4;
+		uint32_t inc_key_manifest	: 4;
+		uint32_t inc_boot_policy	: 4;
+		uint32_t rsvd0			: 2;
+		uint32_t start_enforcement	: 1;
+	} __packed fields;
+};
+
+/* Host Firmware Status Register 6 */
+union me_hfsts6 {
+	uint32_t data;
+	struct {
+		uint32_t force_boot_guard_acm	: 1;
+		uint32_t cpu_debug_disable	: 1;
+		uint32_t bsp_init_disable	: 1;
+		uint32_t protect_bios_env	: 1;
+		uint32_t rsvd0			: 2;
+		uint32_t error_enforce_policy	: 2;
+		uint32_t measured_boot		: 1;
+		uint32_t verified_boot		: 1;
+		uint32_t boot_guard_acmsvn	: 4;
+		uint32_t kmsvn			: 4;
+		uint32_t bpmsvn			: 4;
+		uint32_t key_manifest_id	: 4;
+		uint32_t boot_policy_status	: 1;
+		uint32_t error			: 1;
+		uint32_t boot_guard_disable	: 1;
+		uint32_t fpf_disable		: 1;
+		uint32_t fpf_soc_lock		: 1;
+		uint32_t txt_support		: 1;
+	} __packed fields;
+};
+#endif /* _ELKHARTLAKE_ME_H_ */
diff --git a/src/soc/intel/elkhartlake/include/soc/meminit.h b/src/soc/intel/elkhartlake/include/soc/meminit.h
new file mode 100644
index 0000000..ea4664a
--- /dev/null
+++ b/src/soc/intel/elkhartlake/include/soc/meminit.h
@@ -0,0 +1,112 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef _SOC_ELKHARTLAKE_MEMINIT_H_
+#define _SOC_ELKHARTLAKE_MEMINIT_H_
+
+#include <fsp/soc_binding.h>
+#include <types.h>
+
+/* Number of dq bits controlled per dqs */
+#define DQ_BITS_PER_DQS 8
+
+/* Number of memory packages, where a "package" represents a 64-bit solution */
+#define DDR_NUM_PACKAGES 2
+
+/* Number of DQ byte mappings */
+#define DDR_NUM_BYTE_MAPPINGS 6
+
+/* Number of memory DIMM slots available on Elkhart Lake */
+#define NUM_DIMM_SLOT 4
+
+/* 64-bit Channel identification */
+enum {
+	DDR_CH0,
+	DDR_CH1,
+	DDR_NUM_CHANNELS
+};
+
+struct spd_by_pointer {
+	size_t spd_data_len;
+	uintptr_t spd_data_ptr;
+};
+
+enum mem_info_read_type {
+	READ_SPD_CBFS,	/* Find SPD file in CBFS. */
+	READ_SMBUS,	/* Read on-module SPD by SMBUS. */
+	READ_SPD_MEMPTR	/* Find SPD data from pointer. */
+};
+
+struct spd_info {
+	enum mem_info_read_type read_type;
+	union spd_data_by {
+		/* To read on-module SPD when read_type is READ_SMBUS. */
+		uint8_t spd_smbus_address[NUM_DIMM_SLOT];
+
+		/* To identify SPD file when read_type is READ_SPD_CBFS. */
+		int spd_index;
+
+		/* To find SPD data when read_type is READ_SPD_MEMPTR. */
+		struct spd_by_pointer spd_data_ptr_info;
+	} spd_spec;
+};
+
+/* Board-specific memory dq mapping information */
+struct mb_cfg {
+
+	/*
+	 * For each channel, there are 6 sets of DQ byte mappings,
+	 * where each set has a package 0 and a package 1 value (package 0
+	 * represents the first 64-bit lpddr4 chip combination, and package 1
+	 * represents the second 64-bit lpddr4 chip combination).
+	 * The first three sets are for CLK, CMD, and CTL.
+	 * The fsp package actually expects 6 sets, even though the last 3 sets
+	 * are not used in EHL.
+	 * We let the meminit_dq_dqs_map routine take care of clearing the
+	 * unused fields for the caller.
+	 * Note that dq_map is only used by LPDDR; it does not need to be
+	 * initialized for designs using DDR4.
+	 */
+	uint8_t dq_map[DDR_NUM_CHANNELS][DDR_NUM_BYTE_MAPPINGS][DDR_NUM_PACKAGES];
+
+	/*
+	 * DQS CPU<>DRAM map Ch0 and Ch1.  Each array entry represents a
+	 * mapping of a dq bit on the CPU to the bit it's connected to on
+	 * the memory part.  The array index represents the dqs bit number
+	 * on the memory part, and the values in the array represent which
+	 * pin on the CPU that DRAM pin connects to.
+	 * dqs_map is only used by LPDDR; same comments apply as for dq_map
+	 * above.
+	 */
+	uint8_t dqs_map[DDR_NUM_CHANNELS][DQ_BITS_PER_DQS];
+
+	/*
+	 * Rcomp resistor values.  These values represent the resistance in
+	 * ohms of the three rcomp resistors attached to the DDR_COMP_0,
+	 * DDR_COMP_1, and DDR_COMP_2 pins on the DRAM.
+	 */
+	uint16_t rcomp_resistor[3];
+
+	/*
+	 * Rcomp target values.  These will typically be the following
+	 * values for Elkhart Lake : { 80, 40, 40, 40, 30 }
+	 */
+	uint16_t rcomp_targets[5];
+
+	/*
+	 * Early Command Training Enable/Disable Control
+	 * 1 = enable, 0 = disable
+	 */
+	uint8_t ect;
+
+	/* Board type */
+	uint8_t UserBd;
+};
+
+/*
+ * Initialize default memory configurations for Elkhart Lake.
+ */
+
+void memcfg_init(FSP_M_CONFIG *mem_cfg, const struct mb_cfg *board_cfg,
+			const struct spd_info *spd_info, bool half_populated);
+
+#endif /* _SOC_ELKHARTLAKE_MEMINIT_H_ */
diff --git a/src/soc/intel/elkhartlake/include/soc/msr.h b/src/soc/intel/elkhartlake/include/soc/msr.h
new file mode 100644
index 0000000..67e09dc
--- /dev/null
+++ b/src/soc/intel/elkhartlake/include/soc/msr.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef _SOC_MSR_H_
+#define _SOC_MSR_H_
+
+#include <intelblocks/msr.h>
+
+#define MSR_PIC_MSG_CONTROL		0x2e
+#define MSR_VR_MISC_CONFIG2		0x636
+
+#endif
diff --git a/src/soc/intel/elkhartlake/include/soc/nvs.h b/src/soc/intel/elkhartlake/include/soc/nvs.h
new file mode 100644
index 0000000..5129458
--- /dev/null
+++ b/src/soc/intel/elkhartlake/include/soc/nvs.h
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef _SOC_NVS_H_
+#define _SOC_NVS_H_
+
+#include <intelblocks/nvs.h>
+
+#endif
diff --git a/src/soc/intel/elkhartlake/include/soc/pmc.h b/src/soc/intel/elkhartlake/include/soc/pmc.h
new file mode 100644
index 0000000..59bee8f
--- /dev/null
+++ b/src/soc/intel/elkhartlake/include/soc/pmc.h
@@ -0,0 +1,138 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef _SOC_ELKHARTLAKE_PMC_H_
+#define _SOC_ELKHARTLAKE_PMC_H_
+
+/* PCI Configuration Space (D31:F2): PMC */
+#define  PWRMBASE		0x10
+#define  ABASE			0x20
+
+/* Memory mapped IO registers in PMC */
+#define GEN_PMCON_A			0x1020
+#define   DC_PP_DIS			(1 << 30)
+#define   DSX_PP_DIS			(1 << 29)
+#define   AG3_PP_EN			(1 << 28)
+#define   SX_PP_EN			(1 << 27)
+#define   ALLOW_ICLK_PLL_SD_INC0	(1 << 26)
+#define   GBL_RST_STS			(1 << 24)
+#define   DISB				(1 << 23)
+#define   ALLOW_OPI_PLL_SD_INC0		(1 << 22)
+#define   MEM_SR			(1 << 21)
+#define   ALLOW_SPXB_CG_INC0		(1 << 20)
+#define   ALLOW_L1LOW_C0		(1 << 19)
+#define   MS4V				(1 << 18)
+#define   ALLOW_L1LOW_OPI_ON		(1 << 17)
+#define   SUS_PWR_FLR			(1 << 16)
+#define   PME_B0_S5_DIS			(1 << 15)
+#define   PWR_FLR			(1 << 14)
+#define   ALLOW_L1LOW_BCLKREQ_ON	(1 << 13)
+#define   DIS_SLP_X_STRCH_SUS_UP	(1 << 12)
+#define   SLP_S3_MIN_ASST_WDTH_MASK	(3 << 10)
+#define     SLP_S3_MIN_ASST_WDTH_60USEC	(0 << 10)
+#define     SLP_S3_MIN_ASST_WDTH_1MS	(1 << 10)
+#define     SLP_S3_MIN_ASST_WDTH_50MS	(2 << 10)
+#define     SLP_S3_MIN_ASST_WDTH_2S	(3 << 10)
+#define   HOST_RST_STS			(1 << 9)
+#define   ESPI_SMI_LOCK			(1 << 8)
+#define   S4MAW_MASK			(3 << 4)
+#define     S4MAW_1S			(1 << 4)
+#define     S4MAW_2S			(2 << 4)
+#define     S4MAW_3S			(3 << 4)
+#define     S4MAW_4S			(0 << 4)
+#define     S4ASE			(1 << 3)
+#define   PER_SMI_SEL_MASK		(3 << 1)
+#define     SMI_RATE_64S		(0 << 1)
+#define     SMI_RATE_32S		(1 << 1)
+#define     SMI_RATE_16S		(2 << 1)
+#define     SMI_RATE_8S			(3 << 1)
+#define   SLEEP_AFTER_POWER_FAIL	(1 << 0)
+
+#define GEN_PMCON_B			0x1024
+#define   SLP_STR_POL_LOCK		(1 << 18)
+#define   ACPI_BASE_LOCK		(1 << 17)
+#define   PM_DATA_BAR_DIS		(1 << 16)
+#define   WOL_EN_OVRD			(1 << 13)
+#define   BIOS_PCI_EXP_EN		(1 << 10)
+#define   PWRBTN_LVL			(1 << 9)
+#define   SMI_LOCK			(1 << 4)
+#define   RTC_BATTERY_DEAD		(1 << 2)
+
+#define ETR				0x1048
+#define   CF9_LOCK			(1 << 31)
+#define   CF9_GLB_RST			(1 << 20)
+
+#define SSML				0x104C
+#define    SSML_SSL_DS			(0 << 0)
+#define    SSML_SSL_EN			(1 << 0)
+
+#define SSMC				0x1050
+#define    SSMC_SSMS			(1 << 0)
+
+#define SSMD				0x1054
+#define    SSMD_SSD_MASK		(0xffff << 0)
+
+#define PRSTS				0x1810
+
+#define S3_PWRGATE_POL			0x1828
+#define    S3DC_GATE_SUS		(1 << 1)
+#define    S3AC_GATE_SUS		(1 << 0)
+
+#define S4_PWRGATE_POL			0x182c
+#define    S4DC_GATE_SUS		(1 << 1)
+#define    S4AC_GATE_SUS		(1 << 0)
+
+#define S5_PWRGATE_POL			0x1830
+#define    S5DC_GATE_SUS		(1 << 15)
+#define    S5AC_GATE_SUS		(1 << 14)
+
+#define DSX_CFG				0x1834
+#define   REQ_CNV_NOWAKE_DSX		(1 << 4)
+#define    REQ_BATLOW_DSX		(1 << 3)
+#define   DSX_EN_WAKE_PIN		(1 << 2)
+#define   DSX_DIS_AC_PRESENT_PD	(1 << 1)
+#define   DSX_EN_LAN_WAKE_PIN		(1 << 0)
+#define DSX_CFG_MASK			(0x1f << 0)
+
+#define PMSYNC_TPR_CFG			0x18C4
+#define   PCH2CPU_TPR_CFG_LOCK		(1 << 31)
+#define   PCH2CPU_TT_EN			(1 << 26)
+
+#define PCH_PWRM_ACPI_TMR_CTL		0x18FC
+#define GPIO_GPE_CFG			0x1920
+#define  GPE0_DWX_MASK			0xf
+#define  GPE0_DW_SHIFT(x)		(4*(x))
+
+#define  PMC_GPP_G			0x0
+#define  PMC_GPP_B			0x1
+#define  PMC_GPP_A			0x2
+#define  PMC_GPP_R			0x3
+#define  PMC_GPP_S			0x4
+#define  PMC_GPD			0x5
+#define  PMC_GPP_H			0x6
+#define  PMC_GPP_D			0x7
+#define  PMC_GPP_F			0x8
+#define  PMC_GPP_C			0xA
+#define  PMC_GPP_E			0xB
+
+#define GBLRST_CAUSE0			0x1924
+#define   GBLRST_CAUSE0_THERMTRIP	(1 << 5)
+#define GBLRST_CAUSE1			0x1928
+
+#define CPPMVRIC			0x1B1C
+#define   XTALSDQDIS			(1 << 22)
+
+#define IRQ_REG				ACTL
+#define SCI_IRQ_ADJUST			0
+#define ACTL				0x1BD8
+#define   PWRM_EN			(1 << 8)
+#define   ACPI_EN			(1 << 7)
+#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
+#endif
diff --git a/src/soc/intel/elkhartlake/include/soc/ramstage.h b/src/soc/intel/elkhartlake/include/soc/ramstage.h
new file mode 100644
index 0000000..8188fbd
--- /dev/null
+++ b/src/soc/intel/elkhartlake/include/soc/ramstage.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef _SOC_RAMSTAGE_H_
+#define _SOC_RAMSTAGE_H_
+
+#include <device/device.h>
+#include <fsp/api.h>
+#include <fsp/util.h>
+#include <soc/soc_chip.h>
+
+void mainboard_silicon_init_params(FSP_S_CONFIG *params);
+void soc_init_pre_device(void *chip_info);
+
+#endif
diff --git a/src/soc/intel/elkhartlake/include/soc/serialio.h b/src/soc/intel/elkhartlake/include/soc/serialio.h
new file mode 100644
index 0000000..e42af5f
--- /dev/null
+++ b/src/soc/intel/elkhartlake/include/soc/serialio.h
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef _SERIALIO_H_
+#define _SERIALIO_H_
+
+enum {
+	PchSerialIoDisabled,
+	PchSerialIoPci,
+	PchSerialIoHidden,
+	PchSerialIoLegacyUart,
+	PchSerialIoSkipInit
+};
+
+enum {
+	PchSerialIoIndexI2C0,
+	PchSerialIoIndexI2C1,
+	PchSerialIoIndexI2C2,
+	PchSerialIoIndexI2C3,
+	PchSerialIoIndexI2C4,
+	PchSerialIoIndexI2C5,
+};
+
+enum {
+	PchSerialIoIndexGSPI0,
+	PchSerialIoIndexGSPI1,
+	PchSerialIoIndexGSPI2,
+	PchSerialIoIndexGSPI3,
+};
+
+enum {
+	PchSerialIoIndexUART0,
+	PchSerialIoIndexUART1,
+	PchSerialIoIndexUART2,
+};
+
+#endif
diff --git a/src/soc/intel/elkhartlake/include/soc/usb.h b/src/soc/intel/elkhartlake/include/soc/usb.h
new file mode 100644
index 0000000..247b0ba
--- /dev/null
+++ b/src/soc/intel/elkhartlake/include/soc/usb.h
@@ -0,0 +1,139 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+
+#ifndef _SOC_USB_H_
+#define _SOC_USB_H_
+
+#include <stdint.h>
+
+/* Per Port HS Transmitter Emphasis */
+#define USB2_EMP_OFF			0
+#define USB2_DE_EMP_ON			1
+#define USB2_PRE_EMP_ON			2
+#define USB2_DE_EMP_ON_PRE_EMP_ON	3
+
+/* Per Port Half Bit Pre-emphasis */
+#define USB2_FULL_BIT_PRE_EMP	0
+#define USB2_HALF_BIT_PRE_EMP	1
+
+/* Per Port HS Preemphasis Bias */
+#define USB2_BIAS_0MV		0
+#define USB2_BIAS_11P25MV	1
+#define USB2_BIAS_16P9MV	2
+#define USB2_BIAS_28P15MV	3
+#define USB2_BIAS_39P35MV	5
+#define USB2_BIAS_45MV		6
+#define USB2_BIAS_56P3MV	7
+
+struct usb2_port_config {
+	uint8_t enable;
+	uint8_t ocpin;
+	uint8_t tx_bias;
+	uint8_t tx_emp_enable;
+	uint8_t pre_emp_bias;
+	uint8_t pre_emp_bit;
+};
+
+/* USB Overcurrent pins definition */
+enum {
+	OC0 = 0,
+	OC1,
+	OC2,
+	OC3,
+	OC4,
+	OC5,
+	OC6,
+	OC7,
+	OCMAX,
+	OC_SKIP = 0xff, /* Skip OC programming */
+};
+
+/* Standard USB Port based on length:
+ * - External
+ * - Back Panel
+ * - OTG
+ * - M.2
+ * - Internal device down */
+
+#define USB2_PORT_EMPTY { \
+	.enable        = 0, \
+	.ocpin         = OC_SKIP, \
+	.tx_bias       = USB2_BIAS_0MV, \
+	.tx_emp_enable = USB2_EMP_OFF, \
+	.pre_emp_bias  = USB2_BIAS_0MV, \
+	.pre_emp_bit   = USB2_HALF_BIT_PRE_EMP, \
+}
+
+/* Length = 11.5"-12" */
+#define USB2_PORT_LONG(pin) { \
+	.enable        = 1, \
+	.ocpin         = (pin), \
+	.tx_bias       = USB2_BIAS_39P35MV, \
+	.tx_emp_enable = USB2_PRE_EMP_ON, \
+	.pre_emp_bias  = USB2_BIAS_56P3MV, \
+	.pre_emp_bit   = USB2_HALF_BIT_PRE_EMP, \
+}
+
+/* Length  = 6"-11.49" */
+#define USB2_PORT_MID(pin) { \
+	.enable        = 1, \
+	.ocpin         = (pin), \
+	.tx_bias       = USB2_BIAS_0MV, \
+	.tx_emp_enable = USB2_PRE_EMP_ON, \
+	.pre_emp_bias  = USB2_BIAS_56P3MV, \
+	.pre_emp_bit   = USB2_HALF_BIT_PRE_EMP, \
+}
+
+/* Length = 3"-5.99" */
+#define USB2_PORT_SHORT(pin) { \
+	.enable        = 1, \
+	.ocpin         = (pin), \
+	.tx_bias       = USB2_BIAS_39P35MV, \
+	.tx_emp_enable = USB2_PRE_EMP_ON | USB2_DE_EMP_ON, \
+	.pre_emp_bias  = USB2_BIAS_39P35MV, \
+	.pre_emp_bit   = USB2_FULL_BIT_PRE_EMP, \
+}
+
+/* Max TX and Pre-emp settings */
+#define USB2_PORT_MAX(pin) { \
+	.enable        = 1, \
+	.ocpin         = (pin), \
+	.tx_bias       = USB2_BIAS_56P3MV, \
+	.tx_emp_enable = USB2_PRE_EMP_ON, \
+	.pre_emp_bias  = USB2_BIAS_56P3MV, \
+	.pre_emp_bit   = USB2_HALF_BIT_PRE_EMP, \
+}
+
+/* Type-C Port, no BC1.2 charge detect module / MUX
+ * Length  = 3.0" - 9.00" */
+#define USB2_PORT_TYPE_C(pin) { \
+	.enable        = 1, \
+	.ocpin         = (pin), \
+	.tx_bias       = USB2_BIAS_0MV, \
+	.tx_emp_enable = USB2_PRE_EMP_ON, \
+	.pre_emp_bias  = USB2_BIAS_56P3MV, \
+	.pre_emp_bit   = USB2_HALF_BIT_PRE_EMP, \
+}
+
+struct usb3_port_config {
+	uint8_t enable;
+	uint8_t ocpin;
+	uint8_t tx_de_emp;
+	uint8_t tx_downscale_amp;
+};
+
+#define USB3_PORT_EMPTY { \
+	.enable           = 0, \
+	.ocpin            = OC_SKIP, \
+	.tx_de_emp        = 0x00, \
+	.tx_downscale_amp = 0x00, \
+}
+
+#define USB3_PORT_DEFAULT(pin) { \
+	.enable           = 1, \
+	.ocpin            = (pin), \
+	.tx_de_emp        = 0x0, \
+	.tx_downscale_amp = 0x00, \
+}
+
+#endif
diff --git a/src/soc/intel/elkhartlake/lockdown.c b/src/soc/intel/elkhartlake/lockdown.c
new file mode 100644
index 0000000..b2d4210
--- /dev/null
+++ b/src/soc/intel/elkhartlake/lockdown.c
@@ -0,0 +1,59 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <device/mmio.h>
+#include <intelblocks/cfg.h>
+#include <intelpch/lockdown.h>
+#include <soc/pm.h>
+
+static void pmc_lock_pmsync(void)
+{
+	uint8_t *pmcbase;
+	uint32_t pmsyncreg;
+
+	pmcbase = pmc_mmio_regs();
+
+	pmsyncreg = read32(pmcbase + PMSYNC_TPR_CFG);
+	pmsyncreg |= PCH2CPU_TPR_CFG_LOCK;
+	write32(pmcbase + PMSYNC_TPR_CFG, pmsyncreg);
+}
+
+static void pmc_lock_abase(void)
+{
+	uint8_t *pmcbase;
+	uint32_t reg32;
+
+	pmcbase = pmc_mmio_regs();
+
+	reg32 = read32(pmcbase + GEN_PMCON_B);
+	reg32 |= (SLP_STR_POL_LOCK | ACPI_BASE_LOCK);
+	write32(pmcbase + GEN_PMCON_B, reg32);
+}
+
+static void pmc_lock_smi(void)
+{
+	uint8_t *pmcbase;
+	uint8_t reg8;
+
+	pmcbase = pmc_mmio_regs();
+
+	reg8 = read8(pmcbase + GEN_PMCON_B);
+	reg8 |= SMI_LOCK;
+	write8(pmcbase + GEN_PMCON_B, reg8);
+}
+
+static void pmc_lockdown_cfg(int chipset_lockdown)
+{
+	/* PMSYNC */
+	pmc_lock_pmsync();
+	/* Lock down ABASE and sleep stretching policy */
+	pmc_lock_abase();
+
+	if (chipset_lockdown == CHIPSET_LOCKDOWN_COREBOOT)
+		pmc_lock_smi();
+}
+
+void soc_lockdown_config(int chipset_lockdown)
+{
+	/* PMC lock down configuration */
+	pmc_lockdown_cfg(chipset_lockdown);
+}
diff --git a/src/soc/intel/elkhartlake/me.c b/src/soc/intel/elkhartlake/me.c
new file mode 100644
index 0000000..d00702e
--- /dev/null
+++ b/src/soc/intel/elkhartlake/me.c
@@ -0,0 +1,69 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <bootstate.h>
+#include <console/console.h>
+#include <intelblocks/cse.h>
+#include <soc/me.h>
+
+static void dump_me_status(void *unused)
+{
+	union me_hfsts1 hfsts1;
+	union me_hfsts2 hfsts2;
+	union me_hfsts3 hfsts3;
+	union me_hfsts4 hfsts4;
+	union me_hfsts5 hfsts5;
+	union me_hfsts6 hfsts6;
+
+	if (!is_cse_enabled())
+		return;
+
+	hfsts1.data = me_read_config32(PCI_ME_HFSTS1);
+	hfsts2.data = me_read_config32(PCI_ME_HFSTS2);
+	hfsts3.data = me_read_config32(PCI_ME_HFSTS3);
+	hfsts4.data = me_read_config32(PCI_ME_HFSTS4);
+	hfsts5.data = me_read_config32(PCI_ME_HFSTS5);
+	hfsts6.data = me_read_config32(PCI_ME_HFSTS6);
+
+	printk(BIOS_DEBUG, "ME: HFSTS1                  : 0x%08X\n", hfsts1.data);
+	printk(BIOS_DEBUG, "ME: HFSTS2                  : 0x%08X\n", hfsts2.data);
+	printk(BIOS_DEBUG, "ME: HFSTS3                  : 0x%08X\n", hfsts3.data);
+	printk(BIOS_DEBUG, "ME: HFSTS4                  : 0x%08X\n", hfsts4.data);
+	printk(BIOS_DEBUG, "ME: HFSTS5                  : 0x%08X\n", hfsts5.data);
+	printk(BIOS_DEBUG, "ME: HFSTS6                  : 0x%08X\n", hfsts6.data);
+
+	printk(BIOS_DEBUG, "ME: Manufacturing Mode      : %s\n",
+		hfsts1.fields.mfg_mode ? "YES" : "NO");
+	printk(BIOS_DEBUG, "ME: FW Partition Table      : %s\n",
+		hfsts1.fields.fpt_bad ? "BAD" : "OK");
+	printk(BIOS_DEBUG, "ME: Bringup Loader Failure  : %s\n",
+		hfsts1.fields.ft_bup_ld_flr ? "YES" : "NO");
+	printk(BIOS_DEBUG, "ME: Firmware Init Complete  : %s\n",
+		hfsts1.fields.fw_init_complete ? "YES" : "NO");
+	printk(BIOS_DEBUG, "ME: Boot Options Present    : %s\n",
+		hfsts1.fields.boot_options_present ? "YES" : "NO");
+	printk(BIOS_DEBUG, "ME: Update In Progress      : %s\n",
+		hfsts1.fields.update_in_progress ? "YES" : "NO");
+	printk(BIOS_DEBUG, "ME: D0i3 Support            : %s\n",
+		hfsts1.fields.d0i3_support_valid ? "YES" : "NO");
+	printk(BIOS_DEBUG, "ME: Low Power State Enabled : %s\n",
+		hfsts2.fields.low_power_state ? "YES" : "NO");
+	printk(BIOS_DEBUG, "ME: CPU Replaced            : %s\n",
+		hfsts2.fields.cpu_replaced  ? "YES" : "NO");
+	printk(BIOS_DEBUG, "ME: CPU Replacement Valid   : %s\n",
+		hfsts2.fields.cpu_replaced_valid ? "YES" : "NO");
+	printk(BIOS_DEBUG, "ME: Current Working State   : %u\n",
+		hfsts1.fields.working_state);
+	printk(BIOS_DEBUG, "ME: Current Operation State : %u\n",
+		hfsts1.fields.operation_state);
+	printk(BIOS_DEBUG, "ME: Current Operation Mode  : %u\n",
+		hfsts1.fields.operation_mode);
+	printk(BIOS_DEBUG, "ME: Error Code              : %u\n",
+		hfsts1.fields.error_code);
+	printk(BIOS_DEBUG, "ME: CPU Debug Disabled      : %s\n",
+		hfsts6.fields.cpu_debug_disable ? "YES" : "NO");
+	printk(BIOS_DEBUG, "ME: TXT Support             : %s\n",
+		hfsts6.fields.txt_support ? "YES" : "NO");
+}
+
+BOOT_STATE_INIT_ENTRY(BS_DEV_ENABLE, BS_ON_EXIT, print_me_fw_version, NULL);
+BOOT_STATE_INIT_ENTRY(BS_OS_RESUME_CHECK, BS_ON_EXIT, dump_me_status, NULL);
diff --git a/src/soc/intel/elkhartlake/meminit.c b/src/soc/intel/elkhartlake/meminit.c
new file mode 100644
index 0000000..cd777ba
--- /dev/null
+++ b/src/soc/intel/elkhartlake/meminit.c
@@ -0,0 +1,114 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <assert.h>
+#include <console/console.h>
+#include <fsp/util.h>
+#include <soc/meminit.h>
+#include <spd_bin.h>
+#include <string.h>
+
+static void spd_read_from_cbfs(const struct spd_info *spd_info, uintptr_t *spd_data_ptr,
+				size_t *spd_data_len)
+{
+	struct region_device spd_rdev;
+	size_t spd_index = spd_info->spd_spec.spd_index;
+
+	printk(BIOS_DEBUG, "SPD INDEX = %lu\n", spd_index);
+	if (get_spd_cbfs_rdev(&spd_rdev, spd_index) < 0)
+		die("spd.bin not found or incorrect index\n");
+
+	*spd_data_len = region_device_sz(&spd_rdev);
+
+	/* Memory leak is ok since we have memory mapped boot media */
+	assert(CONFIG(BOOT_DEVICE_MEMORY_MAPPED));
+
+	*spd_data_ptr = (uintptr_t)rdev_mmap_full(&spd_rdev);
+}
+
+static void get_spd_data(const struct spd_info *spd_info, uintptr_t *spd_data_ptr,
+				size_t *spd_data_len)
+{
+	if (spd_info->read_type == READ_SPD_MEMPTR) {
+		*spd_data_ptr = spd_info->spd_spec.spd_data_ptr_info.spd_data_ptr;
+		*spd_data_len = spd_info->spd_spec.spd_data_ptr_info.spd_data_len;
+		return;
+	}
+
+	if (spd_info->read_type == READ_SPD_CBFS) {
+		spd_read_from_cbfs(spd_info, spd_data_ptr, spd_data_len);
+		return;
+	}
+
+	die("no valid way to read SPD info");
+}
+
+static void meminit_dq_dqs_map(FSP_M_CONFIG *mem_cfg, const struct mb_cfg *board_cfg,
+				bool half_populated)
+{
+	memcpy(&mem_cfg->RcompResistor, &board_cfg->rcomp_resistor,
+		sizeof(mem_cfg->RcompResistor));
+
+	memcpy(&mem_cfg->RcompTarget, &board_cfg->rcomp_targets,
+		sizeof(mem_cfg->RcompTarget));
+
+	memcpy(&mem_cfg->DqByteMapCh0, &board_cfg->dq_map[DDR_CH0],
+		sizeof(board_cfg->dq_map[DDR_CH0]));
+
+	memcpy(&mem_cfg->DqsMapCpu2DramCh0, &board_cfg->dqs_map[DDR_CH0],
+		sizeof(board_cfg->dqs_map[DDR_CH0]));
+
+	if (half_populated)
+		return;
+
+	memcpy(&mem_cfg->DqByteMapCh1, &board_cfg->dq_map[DDR_CH1],
+		sizeof(board_cfg->dq_map[DDR_CH1]));
+
+	memcpy(&mem_cfg->DqsMapCpu2DramCh1, &board_cfg->dqs_map[DDR_CH1],
+		sizeof(board_cfg->dqs_map[DDR_CH1]));
+}
+
+static void meminit_channels(FSP_M_CONFIG *mem_cfg, const struct mb_cfg *board_cfg,
+				uintptr_t spd_data_ptr, bool half_populated)
+{
+	/* Channel 0 */
+	mem_cfg->MemorySpdPtr00 = spd_data_ptr;
+	mem_cfg->MemorySpdPtr01 = 0;
+
+	if (half_populated) {
+		printk(BIOS_INFO, "%s: DRAM half-populated\n", __func__);
+		spd_data_ptr = 0;
+	}
+
+	/* Channel 1 */
+	mem_cfg->MemorySpdPtr10 = spd_data_ptr;
+	mem_cfg->MemorySpdPtr11 = 0;
+
+	meminit_dq_dqs_map(mem_cfg, board_cfg, half_populated);
+}
+
+/* Initialize onboard memory configurations for lpddr4x */
+void memcfg_init(FSP_M_CONFIG *mem_cfg, const struct mb_cfg *board_cfg,
+			const struct spd_info *spd_info, bool half_populated)
+{
+
+	if (spd_info->read_type == READ_SMBUS) {
+		for (int i = 0; i < NUM_DIMM_SLOT; i++)
+			mem_cfg->SpdAddressTable[i] = spd_info->spd_spec.spd_smbus_address[i];
+
+		meminit_dq_dqs_map(mem_cfg, board_cfg, half_populated);
+	} else {
+		uintptr_t spd_data_ptr = 0;
+		size_t spd_data_len = 0;
+		memset(&mem_cfg->SpdAddressTable, 0, sizeof(mem_cfg->SpdAddressTable));
+		get_spd_data(spd_info, &spd_data_ptr, &spd_data_len);
+		print_spd_info((unsigned char *)spd_data_ptr);
+
+		mem_cfg->MemorySpdDataLen = spd_data_len;
+		meminit_channels(mem_cfg, board_cfg, spd_data_ptr, half_populated);
+	}
+
+	/* Early Command Training Enabled */
+	mem_cfg->ECT = board_cfg->ect;
+
+	mem_cfg->UserBd = board_cfg->UserBd;
+}
diff --git a/src/soc/intel/elkhartlake/p2sb.c b/src/soc/intel/elkhartlake/p2sb.c
new file mode 100644
index 0000000..0ddd007
--- /dev/null
+++ b/src/soc/intel/elkhartlake/p2sb.c
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <console/console.h>
+#include <intelblocks/p2sb.h>
+
+void p2sb_soc_get_sb_mask(uint32_t *ep_mask, size_t count)
+{
+	uint32_t mask;
+
+	if (count != P2SB_EP_MASK_MAX_REG) {
+		printk(BIOS_ERR, "Unable to program EPMASK registers\n");
+		return;
+	}
+
+	/* Remove the host accessing right to PSF register range.
+	 * Set p2sb PCI offset EPMASK5 [29, 28, 27, 26] to disable sideband
+	 * access for PCI Root Bridge.
+	 */
+	mask = (1 << 29) | (1 << 28) | (1 << 27)  | (1 << 26);
+
+	ep_mask[P2SB_EP_MASK_5_REG] = mask;
+
+	/*
+	 * Set p2sb PCI offset EPMASK7 [31, 30] to disable Sideband
+	 * access for Broadcast and Multicast.
+	 */
+	mask = (1 << 31) | (1 << 30);
+
+	ep_mask[P2SB_EP_MASK_7_REG] = mask;
+}
diff --git a/src/soc/intel/elkhartlake/pmc.c b/src/soc/intel/elkhartlake/pmc.c
new file mode 100644
index 0000000..57f26d9
--- /dev/null
+++ b/src/soc/intel/elkhartlake/pmc.c
@@ -0,0 +1,118 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <bootstate.h>
+#include <console/console.h>
+#include <device/device.h>
+#include <device/mmio.h>
+#include <intelblocks/pmc.h>
+#include <intelblocks/pmclib.h>
+#include <intelblocks/rtc.h>
+#include <soc/pci_devs.h>
+#include <soc/pm.h>
+#include <soc/soc_chip.h>
+
+/*
+ * Set which power state system will be after reapplying
+ * the power (from G3 State)
+ */
+void pmc_soc_set_afterg3_en(const bool on)
+{
+	uint8_t reg8;
+	uint8_t *const pmcbase = pmc_mmio_regs();
+
+	reg8 = read8(pmcbase + GEN_PMCON_A);
+	if (on)
+		reg8 &= ~SLEEP_AFTER_POWER_FAIL;
+	else
+		reg8 |= SLEEP_AFTER_POWER_FAIL;
+	write8(pmcbase + GEN_PMCON_A, reg8);
+}
+
+static void config_deep_sX(uint32_t offset, uint32_t mask, int sx, int enable)
+{
+	uint32_t reg;
+	uint8_t *pmcbase = pmc_mmio_regs();
+
+	printk(BIOS_DEBUG, "%sabling Deep S%c\n",
+		enable ? "En" : "Dis", sx + '0');
+	reg = read32(pmcbase + offset);
+	if (enable)
+		reg |= mask;
+	else
+		reg &= ~mask;
+	write32(pmcbase + offset, reg);
+}
+
+static void config_deep_s5(int on_ac, int on_dc)
+{
+	/* Treat S4 the same as S5. */
+	config_deep_sX(S4_PWRGATE_POL, S4AC_GATE_SUS, 4, on_ac);
+	config_deep_sX(S4_PWRGATE_POL, S4DC_GATE_SUS, 4, on_dc);
+	config_deep_sX(S5_PWRGATE_POL, S5AC_GATE_SUS, 5, on_ac);
+	config_deep_sX(S5_PWRGATE_POL, S5DC_GATE_SUS, 5, on_dc);
+}
+
+static void config_deep_s3(int on_ac, int on_dc)
+{
+	config_deep_sX(S3_PWRGATE_POL, S3AC_GATE_SUS, 3, on_ac);
+	config_deep_sX(S3_PWRGATE_POL, S3DC_GATE_SUS, 3, on_dc);
+}
+
+static void config_deep_sx(uint32_t deepsx_config)
+{
+	uint32_t reg;
+	uint8_t *pmcbase = pmc_mmio_regs();
+
+	reg = read32(pmcbase + DSX_CFG);
+	reg &= ~DSX_CFG_MASK;
+	reg |= deepsx_config;
+	write32(pmcbase + DSX_CFG, reg);
+}
+
+static void pmc_init(struct device *dev)
+{
+	const config_t *config = config_of_soc();
+
+	rtc_init();
+
+	pmc_set_power_failure_state(true);
+	pmc_gpe_init();
+
+	config_deep_s3(config->deep_s3_enable_ac, config->deep_s3_enable_dc);
+	config_deep_s5(config->deep_s5_enable_ac, config->deep_s5_enable_dc);
+	config_deep_sx(config->deep_sx_config);
+}
+
+static void soc_pmc_read_resources(struct device *dev)
+{
+	struct resource *res;
+
+	mmio_resource(dev, 0, PCH_PWRM_BASE_ADDRESS / KiB, PCH_PWRM_BASE_SIZE / KiB);
+
+	res = new_resource(dev, 1);
+	res->base = (resource_t)ACPI_BASE_ADDRESS;
+	res->size = (resource_t)ACPI_BASE_SIZE;
+	res->limit = res->base + res->size + 1;
+	res->flags = IORESOURCE_IO | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
+}
+
+static void soc_acpi_mode_init(struct device *dev)
+{
+	/*
+	 * pmc_set_acpi_mode() should be delayed until BS_DEV_INIT in order
+	 * to ensure the ordering does not break the assumptions that other
+	 * drivers make about ACPI mode (e.g. Chrome EC). Since it disables
+	 * ACPI mode, other drivers may take different actions based on this
+	 * (e.g. Chrome EC will flush any pending hostevent bits). Because
+	 * EHL has its PMC device available for device_operations, it can be
+	 * done from the "ops->init" callback.
+	 */
+	pmc_set_acpi_mode();
+}
+
+struct device_operations pmc_ops = {
+	.read_resources		= soc_pmc_read_resources,
+	.set_resources		= noop_set_resources,
+	.init			= soc_acpi_mode_init,
+	.enable			= pmc_init,
+};
diff --git a/src/soc/intel/elkhartlake/pmutil.c b/src/soc/intel/elkhartlake/pmutil.c
new file mode 100644
index 0000000..4d5c04d
--- /dev/null
+++ b/src/soc/intel/elkhartlake/pmutil.c
@@ -0,0 +1,266 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+/*
+ * Helper functions for dealing with power management registers
+ * and the differences between PCH variants.
+ */
+
+#define __SIMPLE_DEVICE__
+
+#include <cbmem.h>
+#include <console/console.h>
+#include <device/device.h>
+#include <device/mmio.h>
+#include <device/pci.h>
+#include <device/pci_def.h>
+#include <intelblocks/pmclib.h>
+#include <intelblocks/rtc.h>
+#include <intelblocks/tco.h>
+#include <security/vboot/vbnv.h>
+#include <soc/espi.h>
+#include <soc/gpe.h>
+#include <soc/gpio.h>
+#include <soc/iomap.h>
+#include <soc/pci_devs.h>
+#include <soc/pm.h>
+#include <soc/smbus.h>
+#include <soc/soc_chip.h>
+
+/*
+ * SMI
+ */
+
+const char *const *soc_smi_sts_array(size_t *a)
+{
+	static const char *const smi_sts_bits[] = {
+		[BIOS_STS_BIT] = "BIOS",
+		[LEGACY_USB_STS_BIT] = "LEGACY_USB",
+		[SMI_ON_SLP_EN_STS_BIT] = "SLP_SMI",
+		[APM_STS_BIT] = "APM",
+		[SWSMI_TMR_STS_BIT] = "SWSMI_TMR",
+		[PM1_STS_BIT] = "PM1",
+		[GPE0_STS_BIT] = "GPE0",
+		[GPIO_STS_BIT] = "GPI",
+		[MCSMI_STS_BIT] = "MCSMI",
+		[DEVMON_STS_BIT] = "DEVMON",
+		[TCO_STS_BIT] = "TCO",
+		[PERIODIC_STS_BIT] = "PERIODIC",
+		[SERIRQ_SMI_STS_BIT] = "SERIRQ_SMI",
+		[SMBUS_SMI_STS_BIT] = "SMBUS_SMI",
+		[PCI_EXP_SMI_STS_BIT] = "PCI_EXP_SMI",
+		[MONITOR_STS_BIT] = "MONITOR",
+		[SPI_SMI_STS_BIT] = "SPI",
+		[GPIO_UNLOCK_SMI_STS_BIT] = "GPIO_UNLOCK",
+		[ESPI_SMI_STS_BIT] = "ESPI_SMI",
+	};
+
+	*a = ARRAY_SIZE(smi_sts_bits);
+	return smi_sts_bits;
+}
+
+/*
+ * TCO
+ */
+
+const char *const *soc_tco_sts_array(size_t *a)
+{
+	static const char *const tco_sts_bits[] = {
+		[0] = "NMI2SMI",
+		[1] = "SW_TCO",
+		[2] = "TCO_INT",
+		[3] = "TIMEOUT",
+		[7] = "NEWCENTURY",
+		[8] = "BIOSWR",
+		[9] = "DMISCI",
+		[10] = "DMISMI",
+		[12] = "DMISERR",
+		[13] = "SLVSEL",
+		[16] = "INTRD_DET",
+		[17] = "SECOND_TO",
+		[18] = "BOOT",
+		[20] = "SMLINK_SLV"
+	};
+
+	*a = ARRAY_SIZE(tco_sts_bits);
+	return tco_sts_bits;
+}
+
+/*
+ * GPE0
+ */
+
+const char *const *soc_std_gpe_sts_array(size_t *a)
+{
+	static const char *const gpe_sts_bits[] = {
+		[1] = "HOTPLUG",
+		[2] = "SWGPE",
+		[6] = "TCO_SCI",
+		[7] = "SMB_WAK",
+		[9] = "PCI_EXP",
+		[10] = "BATLOW",
+		[11] = "PME",
+		[12] = "ME",
+		[13] = "PME_B0",
+		[14] = "eSPI",
+		[15] = "GPIO Tier-2",
+		[16] = "LAN_WAKE",
+		[18] = "WADT"
+	};
+
+	*a = ARRAY_SIZE(gpe_sts_bits);
+	return gpe_sts_bits;
+}
+
+void pmc_set_disb(void)
+{
+	/* Set the DISB after DRAM init */
+	uint8_t disb_val;
+	/* Only care about bits [23:16] of register GEN_PMCON_A */
+	uint8_t *addr = (uint8_t *)(pmc_mmio_regs() + GEN_PMCON_A + 2);
+
+	disb_val = read8(addr);
+	disb_val |= (DISB >> 16);
+
+	/* Don't clear bits that are write-1-to-clear */
+	disb_val &= ~((MS4V | SUS_PWR_FLR) >> 16);
+	write8(addr, disb_val);
+}
+
+void pmc_clear_pmcon_sts(void)
+{
+	uint32_t reg_val;
+	uint8_t *addr;
+	addr = pmc_mmio_regs();
+
+	reg_val = read32(addr + GEN_PMCON_A);
+	/* Clear SUS_PWR_FLR, GBL_RST_STS, HOST_RST_STS, PWR_FLR bits
+	 * while retaining MS4V write-1-to-clear bit */
+	reg_val &= ~(MS4V);
+
+	write32((addr + GEN_PMCON_A), reg_val);
+}
+
+/*
+ * PMC controller gets hidden from PCI bus
+ * during FSP-Silicon init call. Hence PWRMBASE
+ * can't be accessible using PCI configuration space
+ * read/write.
+ */
+uint8_t *pmc_mmio_regs(void)
+{
+	return (void *)(uintptr_t)PCH_PWRM_BASE_ADDRESS;
+}
+
+uintptr_t soc_read_pmc_base(void)
+{
+	return (uintptr_t)pmc_mmio_regs();
+}
+
+uint32_t *soc_pmc_etr_addr(void)
+{
+	return (uint32_t *)(soc_read_pmc_base() + ETR);
+}
+
+void soc_get_gpi_gpe_configs(uint8_t *dw0, uint8_t *dw1, uint8_t *dw2)
+{
+	DEVTREE_CONST struct soc_intel_elkhartlake_config *config;
+
+	config = config_of_soc();
+
+	/* Assign to out variable */
+	*dw0 = config->pmc_gpe0_dw0;
+	*dw1 = config->pmc_gpe0_dw1;
+	*dw2 = config->pmc_gpe0_dw2;
+}
+
+static int rtc_failed(uint32_t gen_pmcon_b)
+{
+	return !!(gen_pmcon_b & RTC_BATTERY_DEAD);
+}
+
+int soc_get_rtc_failed(void)
+{
+	const struct chipset_power_state *ps = cbmem_find(CBMEM_ID_POWER_STATE);
+
+	if (!ps) {
+		printk(BIOS_ERR, "Could not find power state in cbmem, RTC init aborted\n");
+		return 1;
+	}
+
+	return rtc_failed(ps->gen_pmcon_b);
+}
+
+int vbnv_cmos_failed(void)
+{
+	return rtc_failed(read32(pmc_mmio_regs() + GEN_PMCON_B));
+}
+
+static inline int deep_s3_enabled(void)
+{
+	uint32_t deep_s3_pol;
+
+	deep_s3_pol = read32(pmc_mmio_regs() + S3_PWRGATE_POL);
+	return !!(deep_s3_pol & (S3DC_GATE_SUS | S3AC_GATE_SUS));
+}
+
+/* Return 0, 3, or 5 to indicate the previous sleep state. */
+int soc_prev_sleep_state(const struct chipset_power_state *ps,
+	int prev_sleep_state)
+{
+
+	/*
+	 * Check for any power failure to determine if this a wake from
+	* S5 because the PCH does not set the WAK_STS bit when waking
+	* from a true G3 state.
+	*/
+	if (ps->gen_pmcon_a & (PWR_FLR | SUS_PWR_FLR))
+		prev_sleep_state = ACPI_S5;
+
+	/*
+	 * If waking from S3 determine if deep S3 is enabled. If not,
+	 * need to check both deep sleep well and normal suspend well.
+	 * Otherwise just check deep sleep well.
+	 */
+	if (prev_sleep_state == ACPI_S3) {
+		/* PWR_FLR represents deep sleep power well loss. */
+		uint32_t mask = PWR_FLR;
+
+		/* If deep s3 isn't enabled check the suspend well too. */
+		if (!deep_s3_enabled())
+			mask |= SUS_PWR_FLR;
+
+		if (ps->gen_pmcon_a & mask)
+			prev_sleep_state = ACPI_S5;
+	}
+
+	return prev_sleep_state;
+}
+
+void soc_fill_power_state(struct chipset_power_state *ps)
+{
+	uint8_t *pmc;
+
+	ps->tco1_sts = tco_read_reg(TCO1_STS);
+	ps->tco2_sts = tco_read_reg(TCO2_STS);
+
+	printk(BIOS_DEBUG, "TCO_STS:   %04x %04x\n",
+	ps->tco1_sts, ps->tco2_sts);
+
+	pmc = pmc_mmio_regs();
+	ps->gen_pmcon_a = read32(pmc + GEN_PMCON_A);
+	ps->gen_pmcon_b = read32(pmc + GEN_PMCON_B);
+	ps->gblrst_cause[0] = read32(pmc + GBLRST_CAUSE0);
+	ps->gblrst_cause[1] = read32(pmc + GBLRST_CAUSE1);
+
+	printk(BIOS_DEBUG, "GEN_PMCON: %08x %08x\n",
+		ps->gen_pmcon_a, ps->gen_pmcon_b);
+
+	printk(BIOS_DEBUG, "GBLRST_CAUSE: %08x %08x\n",
+		ps->gblrst_cause[0], ps->gblrst_cause[1]);
+}
+
+/* STM Support */
+uint16_t get_pmbase(void)
+{
+	return (uint16_t) ACPI_BASE_ADDRESS;
+}
diff --git a/src/soc/intel/elkhartlake/reset.c b/src/soc/intel/elkhartlake/reset.c
new file mode 100644
index 0000000..107db5a
--- /dev/null
+++ b/src/soc/intel/elkhartlake/reset.c
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <cf9_reset.h>
+#include <console/console.h>
+#include <fsp/util.h>
+#include <intelblocks/cse.h>
+#include <intelblocks/pmclib.h>
+#include <soc/intel/common/reset.h>
+#include <soc/pci_devs.h>
+
+void do_global_reset(void)
+{
+	/* Ask CSE to do the global reset */
+	if (cse_request_global_reset(GLOBAL_RESET))
+		return;
+
+	/* global reset if CSE fail to reset */
+	pmc_global_reset_enable(1);
+	do_full_reset();
+}
+
+void chipset_handle_reset(uint32_t status)
+{
+	switch (status) {
+	case FSP_STATUS_RESET_REQUIRED_3: /* Global Reset */
+		printk(BIOS_DEBUG, "GLOBAL RESET!!\n");
+		global_reset();
+		break;
+	default:
+		printk(BIOS_ERR, "unhandled reset type %x\n", status);
+		die("unknown reset type");
+		break;
+	}
+}
diff --git a/src/soc/intel/elkhartlake/sd.c b/src/soc/intel/elkhartlake/sd.c
new file mode 100644
index 0000000..a4b89c5
--- /dev/null
+++ b/src/soc/intel/elkhartlake/sd.c
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <intelblocks/sd.h>
+#include <soc/soc_chip.h>
+
+int sd_fill_soc_gpio_info(struct acpi_gpio *gpio, const struct device *dev)
+{
+	config_t *config = config_of(dev);
+
+	if (!config->sdcard_cd_gpio)
+		return -1;
+
+	gpio->type = ACPI_GPIO_TYPE_INTERRUPT;
+	gpio->pull = ACPI_GPIO_PULL_NONE;
+	gpio->irq.mode = ACPI_IRQ_EDGE_TRIGGERED;
+	gpio->irq.polarity = ACPI_IRQ_ACTIVE_BOTH;
+	gpio->irq.shared = ACPI_IRQ_SHARED;
+	gpio->irq.wake = ACPI_IRQ_WAKE;
+	gpio->interrupt_debounce_timeout = 10000; /* 100ms */
+	gpio->pin_count = 1;
+	gpio->pins[0] = config->sdcard_cd_gpio;
+
+	return 0;
+}
diff --git a/src/soc/intel/elkhartlake/smihandler.c b/src/soc/intel/elkhartlake/smihandler.c
new file mode 100644
index 0000000..7d2a15e
--- /dev/null
+++ b/src/soc/intel/elkhartlake/smihandler.c
@@ -0,0 +1,41 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <console/console.h>
+#include <device/pci_def.h>
+#include <intelblocks/cse.h>
+#include <intelblocks/smihandler.h>
+#include <soc/soc_chip.h>
+#include <soc/pci_devs.h>
+#include <soc/pm.h>
+
+/*
+ * Specific SOC SMI handler during ramstage finalize phase
+ *
+ * BIOS can't make CSME function disable as is due to POSTBOOT_SAI
+ * restriction in place from MCC chipset. Hence create SMI Handler to
+ * perform CSME function disabling logic during SMM mode.
+ */
+void smihandler_soc_at_finalize(void)
+{
+	const struct soc_intel_elkhartlake_config *config;
+
+	config = config_of_soc();
+
+	if (!config->HeciEnabled && CONFIG(HECI_DISABLE_USING_SMM))
+		heci_disable();
+}
+
+const smi_handler_t southbridge_smi[SMI_STS_BITS] = {
+	[SMI_ON_SLP_EN_STS_BIT] = smihandler_southbridge_sleep,
+	[APM_STS_BIT] = smihandler_southbridge_apmc,
+	[PM1_STS_BIT] = smihandler_southbridge_pm1,
+	[GPE0_STS_BIT] = smihandler_southbridge_gpe0,
+	[GPIO_STS_BIT] = smihandler_southbridge_gpi,
+	[ESPI_SMI_STS_BIT] = smihandler_southbridge_espi,
+	[MCSMI_STS_BIT] = smihandler_southbridge_mc,
+#if CONFIG(SOC_INTEL_COMMON_BLOCK_SMM_TCO_ENABLE)
+	[TCO_STS_BIT] = smihandler_southbridge_tco,
+#endif
+	[PERIODIC_STS_BIT] = smihandler_southbridge_periodic,
+	[MONITOR_STS_BIT] = smihandler_southbridge_monitor,
+};
diff --git a/src/soc/intel/elkhartlake/smmrelocate.c b/src/soc/intel/elkhartlake/smmrelocate.c
new file mode 100644
index 0000000..11b631b
--- /dev/null
+++ b/src/soc/intel/elkhartlake/smmrelocate.c
@@ -0,0 +1,234 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <console/console.h>
+#include <cpu/intel/em64t101_save_state.h>
+#include <cpu/intel/smm_reloc.h>
+#include <cpu/x86/mp.h>
+#include <cpu/x86/msr.h>
+#include <cpu/x86/mtrr.h>
+#include <cpu/x86/smm.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ops.h>
+#include <smp/node.h>
+#include <soc/cpu.h>
+#include <soc/msr.h>
+#include <soc/pci_devs.h>
+#include <soc/soc_chip.h>
+#include <string.h>
+#include <types.h>
+
+static void update_save_state(int cpu, uintptr_t curr_smbase,
+				uintptr_t staggered_smbase,
+				struct smm_relocation_params *relo_params)
+{
+	u32 smbase;
+	u32 iedbase;
+
+	/*
+	 * The relocated handler runs with all CPUs concurrently. Therefore
+	 * stagger the entry points adjusting SMBASE downwards by save state
+	 * size * CPU num.
+	 */
+	smbase = staggered_smbase;
+	iedbase = relo_params->ied_base;
+
+	printk(BIOS_DEBUG, "New SMBASE=0x%08x IEDBASE=0x%08x\n",
+	       smbase, iedbase);
+
+	/*
+	 * All threads need to set IEDBASE and SMBASE to the relocated
+	 * handler region. However, the save state location depends on the
+	 * smm_save_state_in_msrs field in the relocation parameters. If
+	 * smm_save_state_in_msrs is non-zero then the CPUs are relocating
+	 * the SMM handler in parallel, and each CPUs save state area is
+	 * located in their respective MSR space. If smm_save_state_in_msrs
+	 * is zero then the SMM relocation is happening serially so the
+	 * save state is at the same default location for all CPUs.
+	 */
+	if (relo_params->smm_save_state_in_msrs) {
+		msr_t smbase_msr;
+		msr_t iedbase_msr;
+
+		smbase_msr.lo = smbase;
+		smbase_msr.hi = 0;
+
+		/*
+		 * According the BWG the IEDBASE MSR is in bits 63:32. It's
+		 * not clear why it differs from the SMBASE MSR.
+		 */
+		iedbase_msr.lo = 0;
+		iedbase_msr.hi = iedbase;
+
+		wrmsr(SMBASE_MSR, smbase_msr);
+		wrmsr(IEDBASE_MSR, iedbase_msr);
+	} else {
+		em64t101_smm_state_save_area_t *save_state;
+
+		save_state = (void *)(curr_smbase + SMM_DEFAULT_SIZE -
+				      sizeof(*save_state));
+
+		save_state->smbase = smbase;
+		save_state->iedbase = iedbase;
+	}
+}
+
+/* Returns 1 if SMM MSR save state was set. */
+static int bsp_setup_msr_save_state(struct smm_relocation_params *relo_params)
+{
+	msr_t smm_mca_cap;
+
+	smm_mca_cap = rdmsr(SMM_MCA_CAP_MSR);
+	if (smm_mca_cap.hi & SMM_CPU_SVRSTR_MASK) {
+		msr_t smm_feature_control;
+
+		smm_feature_control = rdmsr(SMM_FEATURE_CONTROL_MSR);
+		smm_feature_control.hi = 0;
+		smm_feature_control.lo |= SMM_CPU_SAVE_EN;
+		wrmsr(SMM_FEATURE_CONTROL_MSR, smm_feature_control);
+		relo_params->smm_save_state_in_msrs = 1;
+	}
+	return relo_params->smm_save_state_in_msrs;
+}
+
+/*
+ * The relocation work is actually performed in SMM context, but the code
+ * resides in the ramstage module. This occurs by trampolining from the default
+ * SMRAM entry point to here.
+ */
+void smm_relocation_handler(int cpu, uintptr_t curr_smbase,
+				uintptr_t staggered_smbase)
+{
+	msr_t mtrr_cap;
+	struct smm_relocation_params *relo_params = &smm_reloc_params;
+
+	printk(BIOS_DEBUG, "In relocation handler: CPU %d\n", cpu);
+
+	/*
+	 * Determine if the processor supports saving state in MSRs. If so,
+	 * enable it before the non-BSPs run so that SMM relocation can occur
+	 * in parallel in the non-BSP CPUs.
+	 */
+	if (cpu == 0) {
+		/*
+		 * If smm_save_state_in_msrs is 1 then that means this is the
+		 * 2nd time through the relocation handler for the BSP.
+		 * Parallel SMM handler relocation is taking place. However,
+		 * it is desired to access other CPUs save state in the real
+		 * SMM handler. Therefore, disable the SMM save state in MSRs
+		 * feature.
+		 */
+		if (relo_params->smm_save_state_in_msrs) {
+			msr_t smm_feature_control;
+
+			smm_feature_control = rdmsr(SMM_FEATURE_CONTROL_MSR);
+			smm_feature_control.lo &= ~SMM_CPU_SAVE_EN;
+			wrmsr(SMM_FEATURE_CONTROL_MSR, smm_feature_control);
+		} else if (bsp_setup_msr_save_state(relo_params))
+			/*
+			 * Just return from relocation handler if MSR save
+			 * state is enabled. In that case the BSP will come
+			 * back into the relocation handler to setup the new
+			 * SMBASE as well disabling SMM save state in MSRs.
+			 */
+			return;
+	}
+
+	/* Make appropriate changes to the save state map. */
+	update_save_state(cpu, curr_smbase, staggered_smbase, relo_params);
+
+	/* Write SMRR MSRs based on indicated support. */
+	mtrr_cap = rdmsr(MTRR_CAP_MSR);
+	if (mtrr_cap.lo & SMRR_SUPPORTED)
+		write_smrr(relo_params);
+}
+
+static void fill_in_relocation_params(struct smm_relocation_params *params)
+{
+	uintptr_t tseg_base;
+	size_t tseg_size;
+	/* All range registers are aligned to 4KiB */
+	const u32 rmask = ~(4 * KiB - 1);
+
+	smm_region(&tseg_base, &tseg_size);
+
+	if (!IS_ALIGNED(tseg_base, tseg_size)) {
+		printk(BIOS_WARNING,
+		     "TSEG base not aligned with TSEG SIZE! Not setting SMRR\n");
+		return;
+	}
+
+	smm_subregion(SMM_SUBREGION_CHIPSET, &params->ied_base, &params->ied_size);
+
+	/* SMRR has 32-bits of valid address aligned to 4KiB. */
+	params->smrr_base.lo = (tseg_base & rmask) | MTRR_TYPE_WRBACK;
+	params->smrr_base.hi = 0;
+	params->smrr_mask.lo = (~(tseg_size - 1) & rmask) | MTRR_PHYS_MASK_VALID;
+	params->smrr_mask.hi = 0;
+}
+
+static void setup_ied_area(struct smm_relocation_params *params)
+{
+	char *ied_base;
+
+	struct ied_header ied = {
+		.signature = "INTEL RSVD",
+		.size = params->ied_size,
+		.reserved = {0},
+	};
+
+	ied_base = (void *)params->ied_base;
+
+	printk(BIOS_DEBUG, "IED base = 0x%08x\n", (u32)params->ied_base);
+	printk(BIOS_DEBUG, "IED size = 0x%08x\n", (u32)params->ied_size);
+
+	/* Place IED header at IEDBASE. */
+	memcpy(ied_base, &ied, sizeof(ied));
+
+	/* Zero out 32KiB at IEDBASE + 1MiB */
+	memset(ied_base + 1 * MiB, 0, 32 * KiB);
+}
+
+void smm_info(uintptr_t *perm_smbase, size_t *perm_smsize,
+				size_t *smm_save_state_size)
+{
+	printk(BIOS_DEBUG, "Setting up SMI for CPU\n");
+
+	fill_in_relocation_params(&smm_reloc_params);
+
+	smm_subregion(SMM_SUBREGION_HANDLER, perm_smbase, perm_smsize);
+
+	if (smm_reloc_params.ied_size)
+		setup_ied_area(&smm_reloc_params);
+
+	*smm_save_state_size = sizeof(em64t101_smm_state_save_area_t);
+}
+
+void smm_initialize(void)
+{
+	/* Clear the SMM state in the southbridge. */
+	smm_southbridge_clear_state();
+
+	/*
+	 * Run the relocation handler for on the BSP to check and set up
+	 * parallel SMM relocation.
+	 */
+	smm_initiate_relocation();
+
+	if (smm_reloc_params.smm_save_state_in_msrs)
+		printk(BIOS_DEBUG, "Doing parallel SMM relocation.\n");
+}
+
+void smm_relocate(void)
+{
+	/*
+	 * If smm_save_state_in_msrs is non-zero then parallel SMM relocation
+	 * shall take place. Run the relocation handler a second time on the
+	 * BSP to do * the final move. For APs, a relocation handler always
+	 * needs to be run.
+	 */
+	if (smm_reloc_params.smm_save_state_in_msrs)
+		smm_initiate_relocation_parallel();
+	else if (!boot_cpu())
+		smm_initiate_relocation();
+}
diff --git a/src/soc/intel/elkhartlake/spi.c b/src/soc/intel/elkhartlake/spi.c
new file mode 100644
index 0000000..8fd3126
--- /dev/null
+++ b/src/soc/intel/elkhartlake/spi.c
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#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;
+	case PCH_DEVFN_GSPI0:
+		return 1;
+	case PCH_DEVFN_GSPI1:
+		return 2;
+	case PCH_DEVFN_GSPI2:
+		return 3;
+	}
+	return -1;
+}
diff --git a/src/soc/intel/elkhartlake/systemagent.c b/src/soc/intel/elkhartlake/systemagent.c
new file mode 100644
index 0000000..73f7963
--- /dev/null
+++ b/src/soc/intel/elkhartlake/systemagent.c
@@ -0,0 +1,62 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <delay.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ops.h>
+#include <intelblocks/power_limit.h>
+#include <intelblocks/systemagent.h>
+#include <soc/iomap.h>
+#include <soc/soc_chip.h>
+#include <soc/systemagent.h>
+
+/*
+ * SoC implementation
+ *
+ * Add all known fixed memory ranges for Host Controller/Memory
+ * controller.
+ */
+void soc_add_fixed_mmio_resources(struct device *dev, int *index)
+{
+	static const struct sa_mmio_descriptor soc_fixed_resources[] = {
+		{ PCIEXBAR, CONFIG_MMCONF_BASE_ADDRESS, CONFIG_SA_PCIEX_LENGTH,
+				"PCIEXBAR" },
+		{ MCHBAR, MCH_BASE_ADDRESS, MCH_BASE_SIZE, "MCHBAR" },
+		{ DMIBAR, DMI_BASE_ADDRESS, DMI_BASE_SIZE, "DMIBAR" },
+		{ EPBAR, EP_BASE_ADDRESS, EP_BASE_SIZE, "EPBAR" },
+		{ REGBAR, REG_BASE_ADDRESS, REG_BASE_SIZE, "REGBAR" },
+		{ EDRAMBAR, EDRAM_BASE_ADDRESS, EDRAM_BASE_SIZE, "EDRAMBAR" },
+	};
+
+	sa_add_fixed_mmio_resources(dev, index, soc_fixed_resources,
+			ARRAY_SIZE(soc_fixed_resources));
+
+	/* Add Vt-d resources if VT-d is enabled */
+	if ((pci_read_config32(dev, CAPID0_A) & VTD_DISABLE))
+		return;
+
+	sa_add_fixed_mmio_resources(dev, index, soc_vtd_resources,
+			ARRAY_SIZE(soc_vtd_resources));
+}
+
+/*
+ * SoC implementation
+ *
+ * Perform System Agent Initialization during Ramstage phase.
+ */
+void soc_systemagent_init(struct device *dev)
+{
+	struct soc_power_limits_config *soc_config;
+	config_t *config;
+
+	/* Enable Power Aware Interrupt Routing */
+	enable_power_aware_intr();
+
+	/* Enable BIOS Reset CPL */
+	enable_bios_reset_cpl();
+
+	mdelay(1);
+	config = config_of_soc();
+	soc_config = &config->power_limits_config;
+	set_power_limits(MOBILE_SKU_PL1_TIME_SEC, soc_config);
+}
diff --git a/src/soc/intel/elkhartlake/uart.c b/src/soc/intel/elkhartlake/uart.c
new file mode 100644
index 0000000..cc0e3a8
--- /dev/null
+++ b/src/soc/intel/elkhartlake/uart.c
@@ -0,0 +1,57 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <console/console.h>
+#include <device/pci_def.h>
+#include <intelblocks/gpio.h>
+#include <intelblocks/lpss.h>
+#include <intelblocks/pcr.h>
+#include <intelblocks/uart.h>
+#include <soc/iomap.h>
+#include <soc/pch.h>
+#include <soc/pci_devs.h>
+#include <soc/pcr_ids.h>
+
+const struct uart_gpio_pad_config uart_gpio_pads[] = {
+	{
+		.console_index = 0,
+		.gpios = {
+			PAD_CFG_NF(GPP_C8, NONE, DEEP, NF1), /* UART0 RX */
+			PAD_CFG_NF(GPP_C9, NONE, DEEP, NF1), /* UART0 TX */
+		},
+	},
+	{
+		.console_index = 1,
+		.gpios = {
+			PAD_CFG_NF(GPP_C12, NONE, DEEP, NF1), /* UART1 RX */
+			PAD_CFG_NF(GPP_C13, NONE, DEEP, NF1), /* UART1 TX */
+		},
+	},
+	{
+		.console_index = 2,
+		.gpios = {
+			PAD_CFG_NF(GPP_C20, NONE, DEEP, NF1), /* UART2 RX */
+			PAD_CFG_NF(GPP_C21, NONE, DEEP, NF1), /* UART2 TX */
+		},
+	}
+};
+
+const int uart_max_index = ARRAY_SIZE(uart_gpio_pads);
+
+DEVTREE_CONST struct device *soc_uart_console_to_device(int uart_console)
+{
+	/*
+	 * if index is valid, this function will return corresponding structure
+	 * for uart console else will return NULL.
+	 */
+	switch (uart_console) {
+	case 0:
+		return pcidev_path_on_root(PCH_DEVFN_UART0);
+	case 1:
+		return pcidev_path_on_root(PCH_DEVFN_UART1);
+	case 2:
+		return pcidev_path_on_root(PCH_DEVFN_UART2);
+	default:
+		printk(BIOS_ERR, "Invalid UART console index\n");
+		return NULL;
+	}
+}