summaryrefslogtreecommitdiff
path: root/src/soc/intel/elkhartlake
diff options
context:
space:
mode:
Diffstat (limited to 'src/soc/intel/elkhartlake')
-rw-r--r--src/soc/intel/elkhartlake/Kconfig213
-rw-r--r--src/soc/intel/elkhartlake/Makefile.inc60
-rw-r--r--src/soc/intel/elkhartlake/acpi.c343
-rw-r--r--src/soc/intel/elkhartlake/chip.c180
-rw-r--r--src/soc/intel/elkhartlake/chip.h348
-rw-r--r--src/soc/intel/elkhartlake/cpu.c213
-rw-r--r--src/soc/intel/elkhartlake/elog.c117
-rw-r--r--src/soc/intel/elkhartlake/espi.c192
-rw-r--r--src/soc/intel/elkhartlake/finalize.c76
-rw-r--r--src/soc/intel/elkhartlake/fsp_params.c79
-rw-r--r--src/soc/intel/elkhartlake/gpio.c198
-rw-r--r--src/soc/intel/elkhartlake/gspi.c17
-rw-r--r--src/soc/intel/elkhartlake/i2c.c43
-rw-r--r--src/soc/intel/elkhartlake/include/soc/cpu.h33
-rw-r--r--src/soc/intel/elkhartlake/include/soc/espi.h8
-rw-r--r--src/soc/intel/elkhartlake/include/soc/gpe.h121
-rw-r--r--src/soc/intel/elkhartlake/include/soc/gpio.h15
-rw-r--r--src/soc/intel/elkhartlake/include/soc/gpio_defs.h260
-rw-r--r--src/soc/intel/elkhartlake/include/soc/gpio_soc_defs.h347
-rw-r--r--src/soc/intel/elkhartlake/include/soc/irq.h36
-rw-r--r--src/soc/intel/elkhartlake/include/soc/itss.h13
-rw-r--r--src/soc/intel/elkhartlake/include/soc/me.h123
-rw-r--r--src/soc/intel/elkhartlake/include/soc/meminit.h112
-rw-r--r--src/soc/intel/elkhartlake/include/soc/msr.h11
-rw-r--r--src/soc/intel/elkhartlake/include/soc/nvs.h8
-rw-r--r--src/soc/intel/elkhartlake/include/soc/pmc.h138
-rw-r--r--src/soc/intel/elkhartlake/include/soc/ramstage.h14
-rw-r--r--src/soc/intel/elkhartlake/include/soc/serialio.h36
-rw-r--r--src/soc/intel/elkhartlake/include/soc/usb.h139
-rw-r--r--src/soc/intel/elkhartlake/lockdown.c59
-rw-r--r--src/soc/intel/elkhartlake/me.c69
-rw-r--r--src/soc/intel/elkhartlake/meminit.c114
-rw-r--r--src/soc/intel/elkhartlake/p2sb.c30
-rw-r--r--src/soc/intel/elkhartlake/pmc.c118
-rw-r--r--src/soc/intel/elkhartlake/pmutil.c266
-rw-r--r--src/soc/intel/elkhartlake/reset.c34
-rw-r--r--src/soc/intel/elkhartlake/sd.c24
-rw-r--r--src/soc/intel/elkhartlake/smihandler.c41
-rw-r--r--src/soc/intel/elkhartlake/smmrelocate.c234
-rw-r--r--src/soc/intel/elkhartlake/spi.c19
-rw-r--r--src/soc/intel/elkhartlake/systemagent.c62
-rw-r--r--src/soc/intel/elkhartlake/uart.c57
42 files changed, 4617 insertions, 3 deletions
diff --git a/src/soc/intel/elkhartlake/Kconfig b/src/soc/intel/elkhartlake/Kconfig
new file mode 100644
index 0000000000..166bda01cc
--- /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 0000000000..5c46f86738
--- /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 0000000000..af837aba5d
--- /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 0000000000..e4884efea1
--- /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 0000000000..5037147d74
--- /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 0000000000..382bbf7b01
--- /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 0000000000..c88efc81bc
--- /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 0000000000..71339971fa
--- /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 0000000000..e9b3f21683
--- /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 0000000000..3d740fb74c
--- /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 0000000000..9ba5d8e058
--- /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 0000000000..61ad2608db
--- /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 0000000000..c13a1a6099
--- /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 0000000000..6ee34f234c
--- /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 80b5c1e49e..6c2615816e 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 0000000000..34dfcea763
--- /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 0000000000..6cca742614
--- /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 0000000000..0b8d8a74a9
--- /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 0000000000..278c2c63aa
--- /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 0000000000..ac45424476
--- /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 0000000000..a550f4c922
--- /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 0000000000..d845629e4a
--- /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 0000000000..ea4664a150
--- /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 0000000000..67e09dcf41
--- /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 0000000000..512945898e
--- /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 0000000000..59bee8f4a3
--- /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 0000000000..8188fbdb84
--- /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 0000000000..e42af5f781
--- /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 0000000000..247b0ba554
--- /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 0000000000..b2d4210531
--- /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 0000000000..d00702eef5
--- /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 0000000000..cd777ba3a0
--- /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 0000000000..0ddd007920
--- /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 0000000000..57f26d921c
--- /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 0000000000..4d5c04d02d
--- /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 0000000000..107db5accb
--- /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 0000000000..a4b89c5803
--- /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 0000000000..7d2a15e737
--- /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 0000000000..11b631bb86
--- /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 0000000000..8fd3126dee
--- /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 0000000000..73f7963b3f
--- /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 0000000000..cc0e3a848b
--- /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;
+ }
+}