summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRavi Sarawadi <ravishankar.sarawadi@intel.com>2022-04-10 23:36:52 -0700
committerSubrata Banik <subratabanik@google.com>2022-06-29 05:27:52 +0000
commit8069b5d3f242b14421c1b825c1eff22b7945411c (patch)
tree58946ddec1bb02fa1748f24769dddb9748826697 /src
parentb0c68656aa6470ec594d743c99a5366c25f0fb04 (diff)
soc/intel/mtl: Do initial Meteor Lake SoC commit till romstage
List of changes: 1. Add required SoC programming till romstage 2. Include only required headers into include/soc 3. Fill required FSP-M UPD to call FSP-M API BUG=b:224325352 TEST=Build 'util/abuild/abuild -p none -t google/rex -a -c max'. Signed-off-by: Ravi Sarawadi <ravishankar.sarawadi@intel.com> Change-Id: I3d5c6ceb7f97429ff903e7577186e8d8843c1f14 Reviewed-on: https://review.coreboot.org/c/coreboot/+/63363 Reviewed-by: Subrata Banik <subratabanik@google.com> Reviewed-by: Tarun Tuli <taruntuli@google.com> Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Diffstat (limited to 'src')
-rw-r--r--src/soc/intel/meteorlake/Kconfig61
-rw-r--r--src/soc/intel/meteorlake/Makefile.inc10
-rw-r--r--src/soc/intel/meteorlake/chip.h331
-rw-r--r--src/soc/intel/meteorlake/chipset.cb175
-rw-r--r--src/soc/intel/meteorlake/espi.c49
-rw-r--r--src/soc/intel/meteorlake/include/soc/gpe.h8
-rw-r--r--src/soc/intel/meteorlake/include/soc/meminit.h115
-rw-r--r--src/soc/intel/meteorlake/include/soc/msr.h11
-rw-r--r--src/soc/intel/meteorlake/include/soc/pmc.h144
-rw-r--r--src/soc/intel/meteorlake/include/soc/romstage.h22
-rw-r--r--src/soc/intel/meteorlake/include/soc/soc_chip.h8
-rw-r--r--src/soc/intel/meteorlake/include/soc/systemagent.h45
-rw-r--r--src/soc/intel/meteorlake/meminit.c227
-rw-r--r--src/soc/intel/meteorlake/p2sb.c30
-rw-r--r--src/soc/intel/meteorlake/reset.c17
-rw-r--r--src/soc/intel/meteorlake/romstage/Makefile.inc6
-rw-r--r--src/soc/intel/meteorlake/romstage/fsp_params.c297
-rw-r--r--src/soc/intel/meteorlake/romstage/romstage.c139
-rw-r--r--src/soc/intel/meteorlake/romstage/systemagent.c29
19 files changed, 1716 insertions, 8 deletions
diff --git a/src/soc/intel/meteorlake/Kconfig b/src/soc/intel/meteorlake/Kconfig
index a447f2a521..a3692fb7d1 100644
--- a/src/soc/intel/meteorlake/Kconfig
+++ b/src/soc/intel/meteorlake/Kconfig
@@ -8,13 +8,22 @@ config CPU_SPECIFIC_OPTIONS
select ARCH_X86
select BOOT_DEVICE_SUPPORTS_WRITES
select INTEL_DESCRIPTOR_MODE_CAPABLE
+ select CACHE_MRC_SETTINGS
+ select CPU_INTEL_COMMON
+ select FSP_M_XIP
select IDT_IN_EVERY_STAGE
select INTEL_CAR_NEM
+ select INTEL_GMA_ADD_VBT if RUN_FSP_GOP
+ select IOAPIC
select MICROCODE_BLOB_UNDISCLOSED
+ select MRC_SETTINGS_PROTECT
select SOC_INTEL_COMMON
+ select SOC_INTEL_COMMON_BLOCK
select SOC_INTEL_COMMON_BLOCK_CAR
+ select SOC_INTEL_COMMON_BLOCK_CHIP_CONFIG
select SOC_INTEL_COMMON_BLOCK_CPU
select SOC_INTEL_COMMON_BLOCK_GSPI_VERSION_2
+ select SOC_INTEL_COMMON_BLOCK_MEMINIT
select SOC_INTEL_COMMON_BLOCK_SA
select SOC_INTEL_COMMON_PCH_BASE
select SOC_INTEL_COMMON_RESET
@@ -97,14 +106,6 @@ config SOC_INTEL_UART_DEV_MAX
int
default 3
-config SOC_INTEL_USB2_DEV_MAX
- int
- default 10
-
-config SOC_INTEL_USB3_DEV_MAX
- int
- default 2
-
config CONSOLE_UART_BASE_ADDRESS
hex
default 0xfe03e000
@@ -121,6 +122,13 @@ config SOC_INTEL_COMMON_LPSS_UART_CLK_N_VAL
hex
default 0x7fff
+config VBOOT
+ select VBOOT_MUST_REQUEST_DISPLAY
+ select VBOOT_STARTS_IN_BOOTBLOCK
+ select VBOOT_VBNV_CMOS
+ select VBOOT_VBNV_CMOS_BACKUP_TO_FLASH
+ select VBOOT_X86_SHA256_ACCELERATION
+
config CBFS_SIZE
hex
default 0x200000
@@ -129,4 +137,41 @@ config PRERAM_CBMEM_CONSOLE_SIZE
hex
default 0x2000
+config FSP_HEADER_PATH
+ string "Location of FSP headers"
+ default "src/vendorcode/intel/fsp/fsp2_0/meteorlake/"
+
+config FSP_FD_PATH
+ string
+ depends on FSP_USE_REPO
+ default "3rdparty/fsp/MeteorLakeFspBinPkg/Fsp.fd"
+
+config SOC_INTEL_METEORLAKE_DEBUG_CONSENT
+ int "Debug Consent for MTL"
+ # 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 DATA_BUS_WIDTH
+ int
+ default 128
+
+config DIMMS_PER_CHANNEL
+ int
+ default 2
+
+config MRC_CHANNEL_WIDTH
+ int
+ default 16
+
endif
diff --git a/src/soc/intel/meteorlake/Makefile.inc b/src/soc/intel/meteorlake/Makefile.inc
index cc246eb44d..cedb8b4756 100644
--- a/src/soc/intel/meteorlake/Makefile.inc
+++ b/src/soc/intel/meteorlake/Makefile.inc
@@ -1,9 +1,19 @@
ifeq ($(CONFIG_SOC_INTEL_METEORLAKE),y)
+subdirs-y += romstage
+subdirs-y += ../../../cpu/intel/microcode
+subdirs-y += ../../../cpu/intel/turbo
+
bootblock-y += bootblock/bootblock.c
bootblock-y += bootblock/ioe_die.c
bootblock-y += bootblock/report_platform.c
bootblock-y += bootblock/soc_die.c
+bootblock-y += espi.c
+bootblock-y += p2sb.c
+
+romstage-y += espi.c
+romstage-y += meminit.c
+romstage-y += reset.c
CPPFLAGS_common += -I$(src)/soc/intel/meteorlake
CPPFLAGS_common += -I$(src)/soc/intel/meteorlake/include
diff --git a/src/soc/intel/meteorlake/chip.h b/src/soc/intel/meteorlake/chip.h
new file mode 100644
index 0000000000..05d77f3d1c
--- /dev/null
+++ b/src/soc/intel/meteorlake/chip.h
@@ -0,0 +1,331 @@
+/* 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 <intelblocks/pcie_rp.h>
+#include <intelblocks/tcss.h>
+#include <soc/gpe.h>
+#include <soc/pci_devs.h>
+#include <soc/pmc.h>
+#include <soc/serialio.h>
+#include <soc/usb.h>
+#include <stdint.h>
+
+/* Types of different SKUs */
+enum soc_intel_meteorlake_power_limits {
+ MTL_P_POWER_LIMITS_1,
+ MTL_P_POWER_LIMITS_2,
+ MTL_P_POWER_LIMITS_3,
+ MTL_POWER_LIMITS_COUNT
+};
+
+/* Types of display ports */
+enum ddi_ports {
+ DDI_PORT_A,
+ DDI_PORT_B,
+ DDI_PORT_C,
+ DDI_PORT_1,
+ DDI_PORT_2,
+ DDI_PORT_3,
+ DDI_PORT_4,
+ DDI_PORT_COUNT,
+};
+
+enum ddi_port_flags {
+ DDI_ENABLE_DDC = 1 << 0,
+ DDI_ENABLE_HPD = 1 << 1,
+};
+
+/* Bit values for use in LpmStateEnableMask. */
+enum lpm_state_mask {
+ LPM_S0i2_0 = BIT(0),
+ LPM_S0i2_1 = BIT(1),
+ LPM_S0i2_2 = BIT(2),
+ LPM_S0i3_0 = BIT(3),
+ LPM_S0i3_1 = BIT(4),
+ LPM_S0i3_2 = BIT(5),
+ LPM_S0i3_3 = BIT(6),
+ LPM_S0i3_4 = BIT(7),
+ LPM_S0iX_ALL = LPM_S0i2_0 | LPM_S0i2_1 | LPM_S0i2_2
+ | LPM_S0i3_0 | LPM_S0i3_1 | LPM_S0i3_2 | LPM_S0i3_3 | LPM_S0i3_4,
+};
+
+struct soc_intel_meteorlake_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[MTL_POWER_LIMITS_COUNT];
+
+ /* 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;
+ /* Support for TCSS xhci, xdci, TBT PCIe root ports and DMA controllers */
+ uint8_t tcss_d3_hot_disable;
+ /* Support for TBT PCIe root ports and DMA controllers with D3Hot->D3Cold */
+ uint8_t tcss_d3_cold_disable;
+ /* 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[CONFIG_SOC_INTEL_USB2_DEV_MAX];
+ struct usb3_port_config usb3_ports[CONFIG_SOC_INTEL_USB3_DEV_MAX];
+ /* Wake Enable Bitmap for USB2 ports */
+ uint16_t usb2_wake_enable_bitmap;
+ /* Wake Enable Bitmap for USB3 ports */
+ uint16_t usb3_wake_enable_bitmap;
+ /* Program OC pins for TCSS */
+ struct tcss_port_config tcss_ports[MAX_TYPE_C_PORTS];
+ uint8_t tbt_pcie_port_disable[4];
+
+ /* SATA related */
+ uint8_t sata_mode;
+ uint8_t sata_salp_support;
+ uint8_t sata_ports_enable[8];
+ uint8_t sata_ports_dev_slp[8];
+
+ /*
+ * Enable(0)/Disable(1) SATA Power Optimizer on PCH side.
+ * Default 0. Setting this to 1 disables the SATA Power Optimizer.
+ */
+ uint8_t sata_pwr_optimize_disable;
+
+ /*
+ * SATA Port Enable Dito Config.
+ * Enable DEVSLP Idle Timeout settings (DmVal, DitoVal).
+ */
+ uint8_t sata_ports_enable_dito_config[8];
+
+ /* SataPortsDmVal is the DITO multiplier. Default is 15. */
+ uint8_t sata_ports_dm_val[8];
+ /* SataPortsDitoVal is the DEVSLP Idle Timeout, default is 625ms */
+ uint16_t sata_ports_dito_val[8];
+
+ /* Audio related */
+ uint8_t pch_hda_dsp_enable;
+
+ /* iDisp-Link T-Mode 0: 2T, 2: 4T, 3: 8T, 4: 16T */
+ enum {
+ HDA_TMODE_2T = 0,
+ HDA_TMODE_4T = 2,
+ HDA_TMODE_8T = 3,
+ HDA_TMODE_16T = 4,
+ } pch_hda_idisp_link_tmode;
+
+ /* iDisp-Link Freq 4: 96MHz, 3: 48MHz. */
+ enum {
+ HDA_LINKFREQ_48MHZ = 3,
+ HDA_LINKFREQ_96MHZ = 4,
+ } pch_hda_idisp_link_frequency;
+
+ bool pch_hda_idisp_codec_enable;
+
+ struct pcie_rp_config pcie_rp[CONFIG_MAX_ROOT_PORTS];
+ uint8_t pcie_clk_config_flag[CONFIG_MAX_PCIE_CLOCK_SRC];
+
+ /* Gfx related */
+ enum {
+ IGD_SM_0MB = 0x00,
+ IGD_SM_32MB = 0x01,
+ IGD_SM_64MB = 0x02,
+ IGD_SM_96MB = 0x03,
+ IGD_SM_128MB = 0x04,
+ IGD_SM_160MB = 0x05,
+ IGD_SM_4MB = 0xF0,
+ IGD_SM_8MB = 0xF1,
+ IGD_SM_12MB = 0xF2,
+ IGD_SM_16MB = 0xF3,
+ IGD_SM_20MB = 0xF4,
+ IGD_SM_24MB = 0xF5,
+ IGD_SM_28MB = 0xF6,
+ IGD_SM_36MB = 0xF8,
+ IGD_SM_40MB = 0xF9,
+ IGD_SM_44MB = 0xFA,
+ IGD_SM_48MB = 0xFB,
+ IGD_SM_52MB = 0xFC,
+ IGD_SM_56MB = 0xFD,
+ IGD_SM_60MB = 0xFE,
+ } igd_dvmt50_pre_alloc;
+ uint8_t skip_ext_gfx_scan;
+
+ /* Enable/Disable EIST. 1b:Enabled, 0b:Disabled */
+ uint8_t eist_enable;
+
+ uint8_t PmTimerDisabled;
+ /*
+ * SerialIO device mode selection:
+ * PchSerialIoDisabled,
+ * PchSerialIoPci,
+ * PchSerialIoHidden,
+ * PchSerialIoLegacyUart,
+ * PchSerialIoSkipInit
+ */
+ uint8_t serial_io_i2c_mode[CONFIG_SOC_INTEL_I2C_DEV_MAX];
+ uint8_t serial_io_gspi_mode[CONFIG_SOC_INTEL_COMMON_BLOCK_GSPI_MAX];
+ uint8_t serial_io_uart_mode[CONFIG_SOC_INTEL_UART_DEV_MAX];
+ /*
+ * GSPIn Default Chip Select Mode:
+ * 0:Hardware Mode,
+ * 1:Software Mode
+ */
+ uint8_t serial_io_gspi_cs_mode[CONFIG_SOC_INTEL_COMMON_BLOCK_GSPI_MAX];
+ /*
+ * GSPIn Default Chip Select State:
+ * 0: Low,
+ * 1: High
+ */
+ uint8_t serial_io_gspi_cs_state[CONFIG_SOC_INTEL_COMMON_BLOCK_GSPI_MAX];
+
+ /* CNVi BT Core Enable/Disable */
+ bool cnvi_bt_core;
+
+ /* CNVi BT Audio Offload: Enable/Disable BT Audio Offload. */
+ bool cnvi_bt_audio_offload;
+
+ /*
+ * These GPIOs will be programmed by the IOM to handle biasing of the
+ * Type-C aux (SBU) signals when certain alternate modes are used.
+ * `pad_auxn_dc` should be assigned to the GPIO pad providing negative
+ * bias (name usually contains `AUXN_DC` or `AUX_N`); similarly,
+ * `pad_auxp_dc` should be assigned to the GPIO providing positive bias
+ * (name often contains `AUXP_DC` or `_AUX_P`).
+ */
+ struct typec_aux_bias_pads typec_aux_bias_pads[MAX_TYPE_C_PORTS];
+
+ /*
+ * SOC Aux orientation override:
+ * This is a bitfield that corresponds to up to 4 TCSS ports on MTL.
+ * Even numbered bits (0, 2, 4, 6) control the retimer being handled by SOC.
+ * Odd numbered bits (1, 3, 5, 7) control the orientation of the physical aux lines
+ * on the motherboard.
+ */
+ uint16_t tcss_aux_ori;
+
+ /* Connect Topology Command timeout value */
+ uint16_t itbt_connect_topology_timeout_in_ms;
+
+ /*
+ * 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 ddi_port_A_config;
+ uint8_t ddi_port_B_config;
+
+ /* Enable(1)/Disable(0) HPD/DDC */
+ uint8_t ddi_ports_config[DDI_PORT_COUNT];
+
+ /* Hybrid storage mode enable (1) / disable (0)
+ * This mode makes FSP detect Optane and NVME and set PCIe lane mode
+ * accordingly */
+ uint8_t hybrid_storage_mode;
+
+ /*
+ * 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 is 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 if don't want to boot with non-turbo max.
+ */
+ uint8_t cpu_ratio_override;
+
+ /*
+ * Enable(0)/Disable(1) DMI Power Optimizer on PCH side.
+ * Default 0. Setting this to 1 disables the DMI Power Optimizer.
+ */
+ uint8_t dmi_pwr_optimize_disable;
+
+ /*
+ * Enable(1)/Disable(0) CPU Replacement check.
+ * Default 0. Setting this to 1 to check CPU replacement.
+ */
+ uint8_t cpu_replacement_check;
+
+ /* ISA Serial Base selection. */
+ enum {
+ ISA_SERIAL_BASE_ADDR_3F8,
+ ISA_SERIAL_BASE_ADDR_2F8,
+ } isa_serial_uart_base;
+
+ /*
+ * Assign clock source port for GbE. 0: Disable, N-1: port number
+ * Default 0.
+ */
+ uint8_t lan_clk;
+};
+
+typedef struct soc_intel_meteorlake_config config_t;
+
+#endif
diff --git a/src/soc/intel/meteorlake/chipset.cb b/src/soc/intel/meteorlake/chipset.cb
new file mode 100644
index 0000000000..546694048f
--- /dev/null
+++ b/src/soc/intel/meteorlake/chipset.cb
@@ -0,0 +1,175 @@
+chip soc/intel/meteorlake
+
+ device cpu_cluster 0 on end
+
+ #FIXME: update values for MTL and enable override in systemagent.c
+ register "power_limits_config[MTL_P_POWER_LIMITS_2]" = "{
+ .tdp_pl1_override = 15,
+ .tdp_pl2_override = 55,
+ }"
+
+ register "power_limits_config[MTL_P_POWER_LIMITS_1]" = "{
+ .tdp_pl1_override = 45,
+ .tdp_pl2_override = 115,
+ }"
+
+ # NOTE: if any variant wants to override this value, use the same format
+ # as register "common_soc_config.pch_thermal_trip" = "value", instead of
+ # putting it under register "common_soc_config" in overridetree.cb file.
+ #FIXME: update value for MTL
+ register "common_soc_config.pch_thermal_trip" = "100"
+
+ device domain 0 on
+ device pci 00.0 alias system_agent on end
+ device pci 01.0 alias pcie_rp12 off end
+ device pci 02.0 alias igpu off end
+ device pci 04.0 alias dtt off end
+ device pci 05.0 alias ipu off end
+ device pci 06.0 alias pcie_rp9 off end
+ device pci 06.1 alias pcie_rp10 off end
+ device pci 06.2 alias pcie_rp11 off end
+ device pci 07.0 alias tbt_pcie_rp0 off
+ chip soc/intel/common/block/usb4
+ use tcss_dma0 as usb4_port
+ device generic 0 on end
+ end
+ end
+ device pci 07.1 alias tbt_pcie_rp1 off
+ chip soc/intel/common/block/usb4
+ use tcss_dma0 as usb4_port
+ device generic 1 on end
+ end
+ end
+ device pci 07.2 alias tbt_pcie_rp2 off
+ chip soc/intel/common/block/usb4
+ use tcss_dma1 as usb4_port
+ device generic 0 on end
+ end
+ end
+ device pci 07.3 alias tbt_pcie_rp3 off
+ chip soc/intel/common/block/usb4
+ use tcss_dma1 as usb4_port
+ device generic 1 on end
+ end
+ end
+ device pci 08.0 alias gna off end
+ device pci 0a.0 alias crashlog on end
+ device pci 0b.0 alias vpu off end
+ device pci 0d.0 alias tcss_xhci off
+ chip drivers/usb/acpi
+ register "type" = "UPC_TYPE_HUB"
+ device usb 0.0 alias tcss_root_hub off
+ chip drivers/usb/acpi
+ device usb 3.0 alias tcss_usb3_port1 off end
+ end
+ chip drivers/usb/acpi
+ device usb 3.1 alias tcss_usb3_port2 off end
+ end
+ chip drivers/usb/acpi
+ device usb 3.2 alias tcss_usb3_port3 off end
+ end
+ chip drivers/usb/acpi
+ device usb 3.3 alias tcss_usb3_port4 off end
+ end
+ end
+ end
+ end
+ device pci 0d.1 alias tcss_xdci off end
+ device pci 0d.2 alias tcss_dma0 off end
+ device pci 0d.3 alias tcss_dma1 off end
+ device pci 0e.0 alias vmd off end
+ device pci 10.0 alias thc0 off end
+ device pci 10.1 alias thc1 off end
+ device pci 12.0 alias ish off end
+ device pci 12.7 alias ufs off end
+ device pci 13.0 alias ioe_p2sb hidden end
+ device pci 13.1 alias ieh2 off end
+ device pci 13.2 alias pmc2 hidden end
+ device pci 13.3 alias shared_sram2 off end
+ device pci 14.0 alias xhci off
+ chip drivers/usb/acpi
+ register "type" = "UPC_TYPE_HUB"
+ device usb 0.0 alias xhci_root_hub off
+ chip drivers/usb/acpi
+ device usb 2.0 alias usb2_port1 off end
+ end
+ chip drivers/usb/acpi
+ device usb 2.1 alias usb2_port2 off end
+ end
+ chip drivers/usb/acpi
+ device usb 2.2 alias usb2_port3 off end
+ end
+ chip drivers/usb/acpi
+ device usb 2.3 alias usb2_port4 off end
+ end
+ chip drivers/usb/acpi
+ device usb 2.4 alias usb2_port5 off end
+ end
+ chip drivers/usb/acpi
+ device usb 2.5 alias usb2_port6 off end
+ end
+ chip drivers/usb/acpi
+ device usb 2.6 alias usb2_port7 off end
+ end
+ chip drivers/usb/acpi
+ device usb 2.7 alias usb2_port8 off end
+ end
+ chip drivers/usb/acpi
+ device usb 2.8 alias usb2_port9 off end
+ end
+ chip drivers/usb/acpi
+ device usb 2.9 alias usb2_port10 off end
+ end
+ chip drivers/usb/acpi
+ device usb 3.0 alias usb3_port1 off end
+ end
+ chip drivers/usb/acpi
+ device usb 3.1 alias usb3_port2 off end
+ end
+ end
+ end
+ end
+ device pci 14.1 alias usb_otg off end
+ device pci 14.2 alias shared_sram off end
+ device pci 14.3 alias cnvi_wifi off end
+ device pci 14.5 alias ieh off end
+ device pci 15.0 alias i2c0 off end
+ device pci 15.1 alias i2c1 off end
+ device pci 15.2 alias i2c2 off end
+ device pci 15.3 alias i2c3 off end
+ device pci 15.4 alias i3c off end
+ device pci 16.0 alias heci1 on end
+ device pci 16.1 alias heci2 off end
+ device pci 16.4 alias heci3 off end
+ device pci 16.5 alias heci4 off end
+ device pci 17.0 alias sata off end
+ device pci 18.0 alias eheci1 off end
+ device pci 18.1 alias eheci2 off end
+ device pci 18.2 alias eheci3 off end
+ device pci 19.0 alias i2c4 off end
+ device pci 19.1 alias i2c5 off end
+ device pci 19.2 alias uart2 off end
+ device pci 1c.0 alias pcie_rp1 off end
+ device pci 1c.1 alias pcie_rp2 off end
+ device pci 1c.2 alias pcie_rp3 off end
+ device pci 1c.3 alias pcie_rp4 off end
+ device pci 1c.4 alias pcie_rp5 off end
+ device pci 1c.5 alias pcie_rp6 off end
+ device pci 1c.6 alias pcie_rp7 off end
+ device pci 1c.7 alias pcie_rp8 off end
+ device pci 1e.0 alias uart0 off end
+ device pci 1e.1 alias uart1 off end
+ device pci 1e.2 alias gspi0 off end
+ device pci 1e.3 alias gspi1 off end
+ device pci 1e.4 alias tsn_gbe1 off end
+ device pci 1e.5 alias tsn_gbe2 off end
+ device pci 1f.0 alias soc_espi on end
+ device pci 1f.1 alias p2sb off end
+ device pci 1f.2 alias pmc hidden end
+ device pci 1f.3 alias hda off end
+ device pci 1f.4 alias smbus off end
+ device pci 1f.5 alias fast_spi on end
+ device pci 1f.6 alias gbe off end
+ device pci 1f.7 alias npk off end
+ end
+end
diff --git a/src/soc/intel/meteorlake/espi.c b/src/soc/intel/meteorlake/espi.c
new file mode 100644
index 0000000000..4928f1782a
--- /dev/null
+++ b/src/soc/intel/meteorlake/espi.c
@@ -0,0 +1,49 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <device/pci.h>
+#include <pc80/isa-dma.h>
+#include <pc80/i8259.h>
+#include <arch/ioapic.h>
+#include <intelblocks/itss.h>
+#include <intelblocks/lpc_lib.h>
+#include <intelblocks/pcr.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>
+
+void soc_get_gen_io_dec_range(uint32_t gen_io_dec[LPC_NUM_GENERIC_IO_RANGES])
+{
+ const config_t *config = config_of_soc();
+
+ 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;
+}
+
+#if ENV_RAMSTAGE
+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();
+ pch_pirq_init();
+ setup_i8259();
+ i8259_configure_irq_trigger(9, 1);
+}
+#endif
diff --git a/src/soc/intel/meteorlake/include/soc/gpe.h b/src/soc/intel/meteorlake/include/soc/gpe.h
new file mode 100644
index 0000000000..6c08d35588
--- /dev/null
+++ b/src/soc/intel/meteorlake/include/soc/gpe.h
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef _SOC_GPE_H_
+#define _SOC_GPE_H_
+
+#include <intelpch/gpe.h>
+
+#endif /* _SOC_GPE_H_ */
diff --git a/src/soc/intel/meteorlake/include/soc/meminit.h b/src/soc/intel/meteorlake/include/soc/meminit.h
new file mode 100644
index 0000000000..cc5ab18cdc
--- /dev/null
+++ b/src/soc/intel/meteorlake/include/soc/meminit.h
@@ -0,0 +1,115 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef _SOC_METEORLAKE_MEMINIT_H_
+#define _SOC_METEORLAKE_MEMINIT_H_
+
+#include <stddef.h>
+#include <stdint.h>
+#include <types.h>
+#include <fsp/soc_binding.h>
+#include <intelblocks/meminit.h>
+
+enum mem_type {
+ MEM_TYPE_DDR5,
+ MEM_TYPE_LP5X,
+};
+
+struct mem_ddr_config {
+ /* Dqs Pins Interleaved Setting. Enable/Disable Control */
+ bool dq_pins_interleaved;
+};
+
+struct lpx_dq {
+ uint8_t dq0[BITS_PER_BYTE];
+ uint8_t dq1[BITS_PER_BYTE];
+};
+
+struct lpx_dqs {
+ uint8_t dqs0;
+ uint8_t dqs1;
+};
+
+struct lpx_dq_map {
+ struct lpx_dq ddr0;
+ struct lpx_dq ddr1;
+ struct lpx_dq ddr2;
+ struct lpx_dq ddr3;
+ struct lpx_dq ddr4;
+ struct lpx_dq ddr5;
+ struct lpx_dq ddr6;
+ struct lpx_dq ddr7;
+};
+
+struct lpx_dqs_map {
+ struct lpx_dqs ddr0;
+ struct lpx_dqs ddr1;
+ struct lpx_dqs ddr2;
+ struct lpx_dqs ddr3;
+ struct lpx_dqs ddr4;
+ struct lpx_dqs ddr5;
+ struct lpx_dqs ddr6;
+ struct lpx_dqs ddr7;
+};
+
+struct mem_lp5x_config {
+ uint8_t ccc_config;
+};
+
+struct rcomp {
+ /*
+ * Rcomp resistor value. This values represents the resistance in
+ * ohms of the rcomp resistor attached to the DDR_COMP pin on the SoC.
+ *
+ * Note: If mainboard users don't want to override rcomp related settings
+ * then associated rcomp UPDs will have its default value.
+ */
+ uint16_t resistor;
+ /* Rcomp target values. */
+ uint16_t targets[5];
+};
+
+struct mb_cfg {
+ enum mem_type type;
+ struct rcomp rcomp;
+ union {
+ /*
+ * DQ CPU<>DRAM map:
+ * Index of the array represents DQ# on the CPU and the value represents DQ# on
+ * the DRAM part.
+ */
+ uint8_t dq_map[CONFIG_DATA_BUS_WIDTH];
+ struct lpx_dq_map lpx_dq_map;
+ };
+
+ union {
+ /*
+ * DQS CPU<>DRAM map:
+ * Index of the array represents DQS# on the CPU and the value represents DQS#
+ * on the DRAM part.
+ */
+ uint8_t dqs_map[CONFIG_DATA_BUS_WIDTH/BITS_PER_BYTE];
+ struct lpx_dqs_map lpx_dqs_map;
+ };
+
+ union {
+ struct mem_lp5x_config lp5x_config;
+ struct mem_ddr_config ddr_config;
+ };
+
+ /* Early Command Training Enable/Disable Control */
+ bool ect;
+
+ /* Board type */
+ uint8_t UserBd;
+
+ /* Command Mirror */
+ uint8_t CmdMirror;
+
+ /* Enable/Disable TxDqDqs Retraining for Lp4/Lp5/DDR */
+ uint8_t LpDdrDqDqsReTraining;
+};
+
+void memcfg_init(FSPM_UPD *memupd, const struct mb_cfg *mb_cfg,
+ const struct mem_spd *spd_info, bool half_populated);
+
+#endif /* _SOC_METEORLAKE_MEMINIT_H_ */
diff --git a/src/soc/intel/meteorlake/include/soc/msr.h b/src/soc/intel/meteorlake/include/soc/msr.h
new file mode 100644
index 0000000000..e6b8c07850
--- /dev/null
+++ b/src/soc/intel/meteorlake/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_BIOS_DONE 0x151
+#define ENABLE_IA_UNTRUSTED (1 << 0)
+
+#endif
diff --git a/src/soc/intel/meteorlake/include/soc/pmc.h b/src/soc/intel/meteorlake/include/soc/pmc.h
new file mode 100644
index 0000000000..a56c2905be
--- /dev/null
+++ b/src/soc/intel/meteorlake/include/soc/pmc.h
@@ -0,0 +1,144 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef _SOC_METEORLAKE_PMC_H_
+#define _SOC_METEORLAKE_PMC_H_
+#include <device/device.h>
+
+extern struct device_operations pmc_ops;
+
+/* 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 ACPI_TIM_DIS (1 << 1)
+#define GPIO_GPE_CFG 0x1920
+#define GPE0_DWX_MASK 0xf
+#define GPE0_DW_SHIFT(x) (4*(x))
+
+#define PMC_GPP_V 0x0
+#define PMC_GPP_C 0x1
+#define PMC_GPP_A 0x2
+#define PMC_GPP_E 0x3
+#define PMC_GPP_H 0x4
+#define PMC_GPP_F 0x5
+#define PMC_GPP_S 0x6
+#define PMC_GPP_B 0x7
+#define PMC_GPP_D 0x8
+
+#define GBLRST_CAUSE0 0x1924
+#define GBLRST_CAUSE0_THERMTRIP (1 << 5)
+#define GBLRST_CAUSE1 0x1928
+#define HPR_CAUSE0 0x192C
+#define HPR_CAUSE0_MI_HRPD (1 << 10)
+#define HPR_CAUSE0_MI_HRPC (1 << 9)
+#define HPR_CAUSE0_MI_HR (1 << 8)
+
+#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/meteorlake/include/soc/romstage.h b/src/soc/intel/meteorlake/include/soc/romstage.h
new file mode 100644
index 0000000000..b9b3cf8bb6
--- /dev/null
+++ b/src/soc/intel/meteorlake/include/soc/romstage.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef _SOC_ROMSTAGE_H_
+#define _SOC_ROMSTAGE_H_
+
+#include <fsp/api.h>
+#include <stddef.h>
+#include <soc/soc_chip.h>
+
+void mainboard_update_premem_soc_chip_config(struct soc_intel_meteorlake_config *config);
+void mainboard_memory_init_params(FSPM_UPD *memupd);
+void systemagent_early_init(void);
+
+/* Board type */
+enum board_type {
+ BOARD_TYPE_MOBILE = 0,
+ BOARD_TYPE_DESKTOP = 1,
+ BOARD_TYPE_ULT_ULX = 5,
+ BOARD_TYPE_SERVER = 7
+};
+
+#endif /* _SOC_ROMSTAGE_H_ */
diff --git a/src/soc/intel/meteorlake/include/soc/soc_chip.h b/src/soc/intel/meteorlake/include/soc/soc_chip.h
new file mode 100644
index 0000000000..c72c0e9542
--- /dev/null
+++ b/src/soc/intel/meteorlake/include/soc/soc_chip.h
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef _SOC_METEORLAKE_SOC_CHIP_H_
+#define _SOC_METEORLAKE_SOC_CHIP_H_
+
+#include "../../chip.h"
+
+#endif /* _SOC_METEORLAKE_SOC_CHIP_H_ */
diff --git a/src/soc/intel/meteorlake/include/soc/systemagent.h b/src/soc/intel/meteorlake/include/soc/systemagent.h
new file mode 100644
index 0000000000..8d029f3e16
--- /dev/null
+++ b/src/soc/intel/meteorlake/include/soc/systemagent.h
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef SOC_METEORLAKE_SYSTEMAGENT_H
+#define SOC_METEORLAKE_SYSTEMAGENT_H
+
+#include <intelblocks/systemagent.h>
+
+/* Device 0:0.0 PCI configuration space */
+
+#define EPBAR 0x40
+#define DMIBAR 0x68
+#define CAPID0_A 0xe4
+#define VTD_DISABLE (1 << 23)
+
+/* MCHBAR offsets */
+#define EDRAMBAR 0x5408
+#define GFXVTBAR 0x5410
+#define REGBAR 0x5420
+#define MCH_DDR_POWER_LIMIT_LO 0x58e0
+#define MCH_DDR_POWER_LIMIT_HI 0x58e4
+#define MCH_PKG_POWER_LIMIT_LO 0x59a0
+#define MCH_PKG_POWER_LIMIT_HI 0x59a4
+#define BIOS_RESET_CPL 0x5da8
+#define IMRBASE 0x6a40
+#define IMRLIMIT 0x6a48
+#define IPUVTBAR 0x7880
+#define TBTxBAR(x) (0x7888 + (x) * 8)
+
+#define MAX_TBT_PCIE_PORT 4
+
+#define VTBAR_ENABLED 0x01
+#define VTBAR_MASK 0x7ffffff000ull
+
+static const struct sa_mmio_descriptor soc_vtd_resources[] = {
+ { GFXVTBAR, GFXVT_BASE_ADDRESS, GFXVT_BASE_SIZE, "GFXVTBAR" },
+};
+
+#define V_P2SB_CFG_IBDF_BUS 0
+#define V_P2SB_CFG_IBDF_DEV 30
+#define V_P2SB_CFG_IBDF_FUNC 7
+#define V_P2SB_CFG_HBDF_BUS 0
+#define V_P2SB_CFG_HBDF_DEV 30
+#define V_P2SB_CFG_HBDF_FUNC 6
+
+#endif
diff --git a/src/soc/intel/meteorlake/meminit.c b/src/soc/intel/meteorlake/meminit.c
new file mode 100644
index 0000000000..f2b7a090d5
--- /dev/null
+++ b/src/soc/intel/meteorlake/meminit.c
@@ -0,0 +1,227 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include <console/console.h>
+#include <fsp/util.h>
+#include <soc/meminit.h>
+#include <string.h>
+
+#define LPX_PHYSICAL_CH_WIDTH 16
+#define LPX_CHANNELS CHANNEL_COUNT(LPX_PHYSICAL_CH_WIDTH)
+
+#define DDR5_PHYSICAL_CH_WIDTH 32
+#define DDR5_CHANNELS CHANNEL_COUNT(DDR5_PHYSICAL_CH_WIDTH)
+
+static void set_rcomp_config(FSP_M_CONFIG *mem_cfg, const struct mb_cfg *mb_cfg)
+{
+ if (mb_cfg->rcomp.resistor != 0)
+ mem_cfg->RcompResistor = mb_cfg->rcomp.resistor;
+
+ for (size_t i = 0; i < ARRAY_SIZE(mem_cfg->RcompTarget); i++) {
+ if (mb_cfg->rcomp.targets[i] != 0)
+ mem_cfg->RcompTarget[i] = mb_cfg->rcomp.targets[i];
+ }
+}
+
+static void meminit_lp5x(FSP_M_CONFIG *mem_cfg, const struct mem_lp5x_config *lp5x_config)
+{
+ mem_cfg->DqPinsInterleaved = 0;
+}
+
+static void meminit_ddr(FSP_M_CONFIG *mem_cfg, const struct mem_ddr_config *ddr_config)
+{
+ mem_cfg->DqPinsInterleaved = ddr_config->dq_pins_interleaved;
+}
+
+static const struct soc_mem_cfg soc_mem_cfg[] = {
+ [MEM_TYPE_DDR5] = {
+ .num_phys_channels = DDR5_CHANNELS,
+ .phys_to_mrc_map = {
+ [0] = 0,
+ [1] = 1,
+ [2] = 4,
+ [3] = 5,
+ },
+ .md_phy_masks = {
+ /*
+ * Physical channels 0 and 1 are populated in case of
+ * half-populated configurations.
+ */
+ .half_channel = BIT(0) | BIT(1),
+ /* In mixed topologies, channels 2 and 3 are always memory-down. */
+ .mixed_topo = BIT(2) | BIT(3),
+ },
+ },
+ [MEM_TYPE_LP5X] = {
+ .num_phys_channels = LPX_CHANNELS,
+ .phys_to_mrc_map = {
+ [0] = 0,
+ [1] = 1,
+ [2] = 2,
+ [3] = 3,
+ [4] = 4,
+ [5] = 5,
+ [6] = 6,
+ [7] = 7,
+ },
+ .md_phy_masks = {
+ /*
+ * Physical channels 0, 1, 2 and 3 are populated in case of
+ * half-populated configurations.
+ */
+ .half_channel = BIT(0) | BIT(1) | BIT(2) | BIT(3),
+ /* LP5x does not support mixed topologies. */
+ },
+ },
+};
+
+static void mem_init_spd_upds(FSP_M_CONFIG *mem_cfg, const struct mem_channel_data *data)
+{
+ uint32_t *spd_upds[MRC_CHANNELS][CONFIG_DIMMS_PER_CHANNEL] = {
+ [0] = { &mem_cfg->MemorySpdPtr000, &mem_cfg->MemorySpdPtr001, },
+ [1] = { &mem_cfg->MemorySpdPtr010, &mem_cfg->MemorySpdPtr011, },
+ [2] = { &mem_cfg->MemorySpdPtr020, &mem_cfg->MemorySpdPtr021, },
+ [3] = { &mem_cfg->MemorySpdPtr030, &mem_cfg->MemorySpdPtr031, },
+ [4] = { &mem_cfg->MemorySpdPtr100, &mem_cfg->MemorySpdPtr101, },
+ [5] = { &mem_cfg->MemorySpdPtr110, &mem_cfg->MemorySpdPtr111, },
+ [6] = { &mem_cfg->MemorySpdPtr120, &mem_cfg->MemorySpdPtr121, },
+ [7] = { &mem_cfg->MemorySpdPtr130, &mem_cfg->MemorySpdPtr131, },
+ };
+ uint8_t *disable_channel_upds[MRC_CHANNELS] = {
+ &mem_cfg->DisableMc0Ch0,
+ &mem_cfg->DisableMc0Ch1,
+ &mem_cfg->DisableMc0Ch2,
+ &mem_cfg->DisableMc0Ch3,
+ &mem_cfg->DisableMc1Ch0,
+ &mem_cfg->DisableMc1Ch1,
+ &mem_cfg->DisableMc1Ch2,
+ &mem_cfg->DisableMc1Ch3,
+ };
+ size_t ch, dimm;
+
+ mem_cfg->MemorySpdDataLen = data->spd_len;
+
+ for (ch = 0; ch < MRC_CHANNELS; ch++) {
+ uint8_t *disable_channel_ptr = disable_channel_upds[ch];
+ bool enable_channel = 0;
+
+ for (dimm = 0; dimm < CONFIG_DIMMS_PER_CHANNEL; dimm++) {
+ uint32_t *spd_ptr = spd_upds[ch][dimm];
+
+ *spd_ptr = data->spd[ch][dimm];
+ if (*spd_ptr)
+ enable_channel = 1;
+ }
+ *disable_channel_ptr = !enable_channel;
+ }
+}
+
+static void mem_init_dq_dqs_upds(void *upds[MRC_CHANNELS], const void *map, size_t upd_size,
+ const struct mem_channel_data *data, bool auto_detect)
+{
+ size_t i;
+
+ for (i = 0; i < MRC_CHANNELS; i++, map += upd_size) {
+ if (auto_detect ||
+ !channel_is_populated(i, MRC_CHANNELS, data->ch_population_flags))
+ memset(upds[i], 0, upd_size);
+ else
+ memcpy(upds[i], map, upd_size);
+ }
+}
+
+static void mem_init_dq_upds(FSP_M_CONFIG *mem_cfg, const struct mem_channel_data *data,
+ const struct mb_cfg *mb_cfg, bool auto_detect)
+{
+ void *dq_upds[MRC_CHANNELS] = {
+ &mem_cfg->DqMapCpu2DramMc0Ch0,
+ &mem_cfg->DqMapCpu2DramMc0Ch1,
+ &mem_cfg->DqMapCpu2DramMc0Ch2,
+ &mem_cfg->DqMapCpu2DramMc0Ch3,
+ &mem_cfg->DqMapCpu2DramMc1Ch0,
+ &mem_cfg->DqMapCpu2DramMc1Ch1,
+ &mem_cfg->DqMapCpu2DramMc1Ch2,
+ &mem_cfg->DqMapCpu2DramMc1Ch3,
+ };
+
+ const size_t upd_size = sizeof(mem_cfg->DqMapCpu2DramMc0Ch0);
+
+ _Static_assert(sizeof(mem_cfg->DqMapCpu2DramMc0Ch0) == CONFIG_MRC_CHANNEL_WIDTH,
+ "Incorrect DQ UPD size!");
+
+ mem_init_dq_dqs_upds(dq_upds, mb_cfg->dq_map, upd_size, data, auto_detect);
+}
+
+static void mem_init_dqs_upds(FSP_M_CONFIG *mem_cfg, const struct mem_channel_data *data,
+ const struct mb_cfg *mb_cfg, bool auto_detect)
+{
+ void *dqs_upds[MRC_CHANNELS] = {
+ &mem_cfg->DqsMapCpu2DramMc0Ch0,
+ &mem_cfg->DqsMapCpu2DramMc0Ch1,
+ &mem_cfg->DqsMapCpu2DramMc0Ch2,
+ &mem_cfg->DqsMapCpu2DramMc0Ch3,
+ &mem_cfg->DqsMapCpu2DramMc1Ch0,
+ &mem_cfg->DqsMapCpu2DramMc1Ch1,
+ &mem_cfg->DqsMapCpu2DramMc1Ch2,
+ &mem_cfg->DqsMapCpu2DramMc1Ch3,
+ };
+
+ const size_t upd_size = sizeof(mem_cfg->DqsMapCpu2DramMc0Ch0);
+
+ _Static_assert(sizeof(mem_cfg->DqsMapCpu2DramMc0Ch0) == CONFIG_MRC_CHANNEL_WIDTH / 8,
+ "Incorrect DQS UPD size!");
+
+ mem_init_dq_dqs_upds(dqs_upds, mb_cfg->dqs_map, upd_size, data, auto_detect);
+}
+
+#define DDR5_CH_DIMM_OFFSET(ch, dimm) ((ch) * CONFIG_DIMMS_PER_CHANNEL + (dimm))
+
+static void ddr5_fill_dimm_module_info(FSP_M_CONFIG *mem_cfg, const struct mb_cfg *mb_cfg,
+ const struct mem_spd *spd_info)
+{
+ for (size_t ch = 0; ch < soc_mem_cfg[MEM_TYPE_DDR5].num_phys_channels; ch++) {
+ for (size_t dimm = 0; dimm < CONFIG_DIMMS_PER_CHANNEL; dimm++) {
+ size_t mrc_ch = soc_mem_cfg[MEM_TYPE_DDR5].phys_to_mrc_map[ch];
+ mem_cfg->SpdAddressTable[DDR5_CH_DIMM_OFFSET(mrc_ch, dimm)] =
+ spd_info->smbus[ch].addr_dimm[dimm] << 1;
+ }
+ }
+ mem_init_dq_upds(mem_cfg, NULL, mb_cfg, true);
+ mem_init_dqs_upds(mem_cfg, NULL, mb_cfg, true);
+}
+
+void memcfg_init(FSPM_UPD *memupd, const struct mb_cfg *mb_cfg,
+ const struct mem_spd *spd_info, bool half_populated)
+{
+ struct mem_channel_data data;
+ bool dq_dqs_auto_detect = false;
+ FSP_M_CONFIG *mem_cfg = &memupd->FspmConfig;
+
+ mem_cfg->UserBd = mb_cfg->UserBd;
+ set_rcomp_config(mem_cfg, mb_cfg);
+
+ switch (mb_cfg->type) {
+ case MEM_TYPE_DDR5:
+ meminit_ddr(mem_cfg, &mb_cfg->ddr_config);
+ dq_dqs_auto_detect = true;
+ /*
+ * TODO: Drop this workaround once SMBus driver in coreboot is updated to
+ * support DDR5 EEPROM reading.
+ */
+ if (spd_info->topo == MEM_TOPO_DIMM_MODULE) {
+ ddr5_fill_dimm_module_info(mem_cfg, mb_cfg, spd_info);
+ return;
+ }
+ break;
+ case MEM_TYPE_LP5X:
+ meminit_lp5x(mem_cfg, &mb_cfg->lp5x_config);
+ break;
+ default:
+ die("Unsupported memory type(%d)\n", mb_cfg->type);
+ }
+
+ mem_populate_channel_data(memupd, &soc_mem_cfg[mb_cfg->type], spd_info,
+ half_populated, &data);
+ mem_init_spd_upds(mem_cfg, &data);
+ mem_init_dq_upds(mem_cfg, &data, mb_cfg, dq_dqs_auto_detect);
+ mem_init_dqs_upds(mem_cfg, &data, mb_cfg, dq_dqs_auto_detect);
+}
diff --git a/src/soc/intel/meteorlake/p2sb.c b/src/soc/intel/meteorlake/p2sb.c
new file mode 100644
index 0000000000..169cde6147
--- /dev/null
+++ b/src/soc/intel/meteorlake/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/meteorlake/reset.c b/src/soc/intel/meteorlake/reset.c
new file mode 100644
index 0000000000..bc5815ac7a
--- /dev/null
+++ b/src/soc/intel/meteorlake/reset.c
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <cf9_reset.h>
+#include <intelblocks/cse.h>
+#include <intelblocks/pmclib.h>
+#include <soc/intel/common/reset.h>
+
+void do_global_reset(void)
+{
+ /* Ask CSE to do the global reset */
+ if (cse_request_global_reset())
+ return;
+
+ /* global reset if CSE fail to reset */
+ pmc_global_reset_enable(1);
+ do_full_reset();
+}
diff --git a/src/soc/intel/meteorlake/romstage/Makefile.inc b/src/soc/intel/meteorlake/romstage/Makefile.inc
new file mode 100644
index 0000000000..99c1d2ca25
--- /dev/null
+++ b/src/soc/intel/meteorlake/romstage/Makefile.inc
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+romstage-y += fsp_params.c
+romstage-y += ../../../../cpu/intel/car/romstage.c
+romstage-y += romstage.c
+romstage-y += systemagent.c
diff --git a/src/soc/intel/meteorlake/romstage/fsp_params.c b/src/soc/intel/meteorlake/romstage/fsp_params.c
new file mode 100644
index 0000000000..45d9415dfc
--- /dev/null
+++ b/src/soc/intel/meteorlake/romstage/fsp_params.c
@@ -0,0 +1,297 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <assert.h>
+#include <console/console.h>
+#include <cpu/x86/msr.h>
+#include <device/device.h>
+#include <fsp/util.h>
+#include <intelblocks/cpulib.h>
+#include <intelblocks/pcie_rp.h>
+#include <soc/gpio_soc_defs.h>
+#include <soc/iomap.h>
+#include <soc/msr.h>
+#include <soc/pci_devs.h>
+#include <soc/pcie.h>
+#include <soc/romstage.h>
+#include <soc/soc_chip.h>
+#include <soc/soc_info.h>
+#include <string.h>
+
+#define FSP_CLK_NOTUSED 0xFF
+#define FSP_CLK_LAN 0x70
+#define FSP_CLK_FREE_RUNNING 0x80
+
+static void pcie_rp_init(FSP_M_CONFIG *m_cfg, uint32_t en_mask,
+ const struct pcie_rp_config *cfg, size_t cfg_count)
+{
+ size_t i;
+
+ for (i = 0; i < cfg_count; i++) {
+ if (!(en_mask & BIT(i)))
+ continue;
+ if (cfg[i].flags & PCIE_RP_CLK_SRC_UNUSED)
+ continue;
+ /* flags 0 means, RP config is not specify from devicetree */
+ if (cfg[i].flags == 0)
+ continue;
+ if (!(cfg[i].flags & PCIE_RP_CLK_REQ_UNUSED))
+ m_cfg->PcieClkSrcClkReq[cfg[i].clk_src] = cfg[i].clk_req;
+ m_cfg->PcieClkSrcUsage[cfg[i].clk_src] = i;
+ }
+}
+
+static void fill_fspm_pcie_rp_params(FSP_M_CONFIG *m_cfg,
+ const struct soc_intel_meteorlake_config *config)
+{
+ /* Disable all PCIe clock sources by default. And set RP irrelevant clock. */
+ unsigned int i;
+ uint8_t max_clock = get_max_pcie_clock();
+
+ for (i = 0; i < max_clock; i++) {
+ if (config->pcie_clk_config_flag[i] & PCIE_CLK_FREE_RUNNING)
+ m_cfg->PcieClkSrcUsage[i] = FSP_CLK_FREE_RUNNING;
+ else if (config->pcie_clk_config_flag[i] & PCIE_CLK_LAN)
+ m_cfg->PcieClkSrcUsage[i] = FSP_CLK_LAN;
+ else
+ m_cfg->PcieClkSrcUsage[i] = FSP_CLK_NOTUSED;
+ m_cfg->PcieClkSrcClkReq[i] = FSP_CLK_NOTUSED;
+ }
+
+ /* PCIE ports */
+ m_cfg->PcieRpEnableMask = pcie_rp_enable_mask(get_pcie_rp_table());
+ pcie_rp_init(m_cfg, m_cfg->PcieRpEnableMask, config->pcie_rp,
+ get_max_pcie_port());
+}
+
+static void fill_fspm_igd_params(FSP_M_CONFIG *m_cfg,
+ const struct soc_intel_meteorlake_config *config)
+{
+ unsigned int i;
+ const struct ddi_port_upds {
+ uint8_t *ddc;
+ uint8_t *hpd;
+ } ddi_port_upds[] = {
+ [DDI_PORT_A] = {&m_cfg->DdiPortADdc, &m_cfg->DdiPortAHpd},
+ [DDI_PORT_B] = {&m_cfg->DdiPortBDdc, &m_cfg->DdiPortBHpd},
+ [DDI_PORT_C] = {&m_cfg->DdiPortCDdc, &m_cfg->DdiPortCHpd},
+ [DDI_PORT_1] = {&m_cfg->DdiPort1Ddc, &m_cfg->DdiPort1Hpd},
+ [DDI_PORT_2] = {&m_cfg->DdiPort2Ddc, &m_cfg->DdiPort2Hpd},
+ [DDI_PORT_3] = {&m_cfg->DdiPort3Ddc, &m_cfg->DdiPort3Hpd},
+ [DDI_PORT_4] = {&m_cfg->DdiPort4Ddc, &m_cfg->DdiPort4Hpd},
+ };
+ m_cfg->InternalGfx = !CONFIG(SOC_INTEL_DISABLE_IGD) && is_devfn_enabled(PCI_DEVFN_IGD);
+ if (m_cfg->InternalGfx) {
+ /* IGD is enabled, set IGD stolen size to 64MB. */
+ m_cfg->IgdDvmt50PreAlloc = IGD_SM_64MB;
+ /* DP port config */
+ m_cfg->DdiPortAConfig = config->ddi_port_A_config;
+ m_cfg->DdiPortBConfig = config->ddi_port_B_config;
+ for (i = 0; i < ARRAY_SIZE(ddi_port_upds); i++) {
+ *ddi_port_upds[i].ddc = !!(config->ddi_ports_config[i] &
+ DDI_ENABLE_DDC);
+ *ddi_port_upds[i].hpd = !!(config->ddi_ports_config[i] &
+ DDI_ENABLE_HPD);
+ }
+ } else {
+ /* IGD is disabled, skip IGD init in FSP. */
+ m_cfg->IgdDvmt50PreAlloc = 0;
+ /* DP port config */
+ m_cfg->DdiPortAConfig = 0;
+ m_cfg->DdiPortBConfig = 0;
+ for (i = 0; i < ARRAY_SIZE(ddi_port_upds); i++) {
+ *ddi_port_upds[i].ddc = 0;
+ *ddi_port_upds[i].hpd = 0;
+ }
+ }
+}
+
+static void fill_fspm_mrc_params(FSP_M_CONFIG *m_cfg,
+ const struct soc_intel_meteorlake_config *config)
+{
+ m_cfg->SaGv = config->SaGv;
+ m_cfg->RMT = config->RMT;
+}
+
+static void fill_fspm_cpu_params(FSP_M_CONFIG *m_cfg,
+ const struct soc_intel_meteorlake_config *config)
+{
+ m_cfg->TsegSize = CONFIG_SMM_TSEG_SIZE;
+ /* CpuRatio Settings */
+ if (config->cpu_ratio_override)
+ m_cfg->CpuRatio = config->cpu_ratio_override;
+ else
+ /* Set CpuRatio to match existing MSR value */
+ m_cfg->CpuRatio = (rdmsr(MSR_FLEX_RATIO).lo >> 8) & 0xff;
+
+ m_cfg->PrmrrSize = get_valid_prmrr_size();
+ /* Enable Hyper Threading */
+ m_cfg->HyperThreading = 1;
+}
+
+static void fill_fspm_security_params(FSP_M_CONFIG *m_cfg,
+ const struct soc_intel_meteorlake_config *config)
+{
+ /* Disable BIOS Guard */
+ m_cfg->BiosGuard = 0;
+ m_cfg->TmeEnable = CONFIG(INTEL_TME);
+}
+
+static void fill_fspm_uart_params(FSP_M_CONFIG *m_cfg,
+ const struct soc_intel_meteorlake_config *config)
+{
+ if (CONFIG(DRIVERS_UART_8250IO))
+ m_cfg->PcdIsaSerialUartBase = ISA_SERIAL_BASE_ADDR_3F8;
+ m_cfg->SerialIoUartDebugMode = PchSerialIoSkipInit;
+ m_cfg->SerialIoUartDebugControllerNumber = CONFIG_UART_FOR_CONSOLE;
+}
+
+static void fill_fspm_ipu_params(FSP_M_CONFIG *m_cfg,
+ const struct soc_intel_meteorlake_config *config)
+{
+ /* Image clock: disable all clocks for bypassing FSP pin mux */
+ memset(m_cfg->ImguClkOutEn, 0, sizeof(m_cfg->ImguClkOutEn));
+ /* IPU */
+ m_cfg->SaIpuEnable = is_devfn_enabled(PCI_DEVFN_IPU);
+}
+
+static void fill_fspm_smbus_params(FSP_M_CONFIG *m_cfg,
+ const struct soc_intel_meteorlake_config *config)
+{
+ m_cfg->SmbusEnable = is_devfn_enabled(PCI_DEVFN_SMBUS);
+}
+
+static void fill_fspm_misc_params(FSP_M_CONFIG *m_cfg,
+ const struct soc_intel_meteorlake_config *config)
+{
+ /* Disable Lock PCU Thermal Management registers */
+ m_cfg->LockPTMregs = 0;
+
+ /* Skip CPU replacement check */
+ m_cfg->SkipCpuReplacementCheck = !config->cpu_replacement_check;
+
+ /* Skip GPIO configuration from FSP */
+ m_cfg->GpioOverride = 0x1;
+}
+
+static void fill_fspm_audio_params(FSP_M_CONFIG *m_cfg,
+ const struct soc_intel_meteorlake_config *config)
+{
+ /* Audio: HDAUDIO_LINK_MODE I2S/SNDW */
+ m_cfg->PchHdaEnable = is_devfn_enabled(PCI_DEVFN_HDA);
+ m_cfg->PchHdaDspEnable = config->pch_hda_dsp_enable;
+ m_cfg->PchHdaIDispLinkTmode = config->pch_hda_idisp_link_tmode;
+ m_cfg->PchHdaIDispLinkFrequency = config->pch_hda_idisp_link_frequency;
+ m_cfg->PchHdaIDispCodecDisconnect = !config->pch_hda_idisp_codec_enable;
+ /*
+ * All the PchHdaAudioLink{Hda|Dmic|Ssp|Sndw}Enable UPDs are used by FSP only to
+ * configure GPIO pads for audio. Mainboard is expected to perform all GPIO
+ * configuration in coreboot and hence these UPDs are set to 0 to skip FSP GPIO
+ * configuration for audio pads.
+ */
+ m_cfg->PchHdaAudioLinkHdaEnable = 0;
+ memset(m_cfg->PchHdaAudioLinkDmicEnable, 0, sizeof(m_cfg->PchHdaAudioLinkDmicEnable));
+ memset(m_cfg->PchHdaAudioLinkSspEnable, 0, sizeof(m_cfg->PchHdaAudioLinkSspEnable));
+ memset(m_cfg->PchHdaAudioLinkSndwEnable, 0, sizeof(m_cfg->PchHdaAudioLinkSndwEnable));
+}
+
+static void fill_fspm_ish_params(FSP_M_CONFIG *m_cfg,
+ const struct soc_intel_meteorlake_config *config)
+{
+ m_cfg->PchIshEnable = is_devfn_enabled(PCI_DEVFN_ISH);
+}
+
+static void fill_fspm_tcss_params(FSP_M_CONFIG *m_cfg,
+ const struct soc_intel_meteorlake_config *config)
+{
+ int i, max_port;
+
+ /* Tcss USB */
+ m_cfg->TcssXhciEn = is_devfn_enabled(PCI_DEVFN_TCSS_XHCI);
+ m_cfg->TcssXdciEn = is_devfn_enabled(PCI_DEVFN_TCSS_XDCI);
+
+ /* TCSS DMA */
+ m_cfg->TcssDma0En = is_devfn_enabled(PCI_DEVFN_TCSS_DMA0);
+ m_cfg->TcssDma1En = 0;
+
+ /* Enable TCSS port */
+ max_port = get_max_tcss_port();
+ m_cfg->UsbTcPortEnPreMem = 0;
+ for (i = 0; i < max_port; i++)
+ if (config->tcss_ports[i].enable)
+ m_cfg->UsbTcPortEnPreMem |= BIT(i);
+}
+
+static void fill_fspm_usb4_params(FSP_M_CONFIG *m_cfg,
+ const struct soc_intel_meteorlake_config *config)
+{
+ memset(&m_cfg->TcssItbtPcie0En, 0, sizeof(m_cfg->TcssItbtPcie0En)*4);
+
+ m_cfg->TcssItbtPcie0En = !(config->tbt_pcie_port_disable[0]);
+ m_cfg->TcssItbtPcie1En = !(config->tbt_pcie_port_disable[1]);
+}
+
+static void fill_fspm_vtd_params(FSP_M_CONFIG *m_cfg,
+ const struct soc_intel_meteorlake_config *config)
+{
+ m_cfg->VtdDisable = 0;
+ m_cfg->VtdBaseAddress[0] = GFXVT_BASE_ADDRESS;
+ m_cfg->VtdBaseAddress[1] = VTVC0_BASE_ADDRESS;
+
+ /* Change VmxEnable UPD value according to ENABLE_VMX Kconfig */
+ m_cfg->VmxEnable = CONFIG(ENABLE_VMX);
+}
+
+static void fill_fspm_trace_params(FSP_M_CONFIG *m_cfg,
+ const struct soc_intel_meteorlake_config *config)
+{
+ /* Set debug probe type */
+ m_cfg->PlatformDebugConsent = CONFIG_SOC_INTEL_METEORLAKE_DEBUG_CONSENT;
+
+ /* CrashLog config */
+ if (CONFIG(SOC_INTEL_CRASHLOG)) {
+ m_cfg->CpuCrashLogDevice = 1;
+ m_cfg->CpuCrashLogEnable = 1;
+ }
+}
+
+static void soc_memory_init_params(FSP_M_CONFIG *m_cfg,
+ const struct soc_intel_meteorlake_config *config)
+{
+ const void (*const fill_fspm_params[])(FSP_M_CONFIG *m_cfg,
+ const struct soc_intel_meteorlake_config *config) = {
+ fill_fspm_igd_params,
+ fill_fspm_mrc_params,
+ fill_fspm_cpu_params,
+ fill_fspm_security_params,
+ fill_fspm_uart_params,
+ fill_fspm_ipu_params,
+ fill_fspm_smbus_params,
+ fill_fspm_misc_params,
+ fill_fspm_audio_params,
+ fill_fspm_pcie_rp_params,
+ fill_fspm_ish_params,
+ fill_fspm_tcss_params,
+ fill_fspm_usb4_params,
+ fill_fspm_vtd_params,
+ fill_fspm_trace_params,
+ };
+
+ for (size_t i = 0; i < ARRAY_SIZE(fill_fspm_params); i++)
+ fill_fspm_params[i](m_cfg, config);
+}
+
+void platform_fsp_memory_init_params_cb(FSPM_UPD *mupd, uint32_t version)
+{
+ const struct soc_intel_meteorlake_config *config;
+ FSP_M_CONFIG *m_cfg = &mupd->FspmConfig;
+
+ config = config_of_soc();
+
+ soc_memory_init_params(m_cfg, config);
+ mainboard_memory_init_params(mupd);
+}
+
+__weak void mainboard_memory_init_params(FSPM_UPD *memupd)
+{
+ printk(BIOS_DEBUG, "WEAK: %s/%s called\n", __FILE__, __func__);
+}
diff --git a/src/soc/intel/meteorlake/romstage/romstage.c b/src/soc/intel/meteorlake/romstage/romstage.c
new file mode 100644
index 0000000000..95a6e9cd6b
--- /dev/null
+++ b/src/soc/intel/meteorlake/romstage/romstage.c
@@ -0,0 +1,139 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <arch/romstage.h>
+#include <cbmem.h>
+#include <console/console.h>
+#include <fsp/util.h>
+#include <intelblocks/cfg.h>
+#include <intelblocks/cse.h>
+#include <intelblocks/pmclib.h>
+#include <intelblocks/smbus.h>
+#include <memory_info.h>
+#include <soc/intel/common/smbios.h>
+#include <soc/iomap.h>
+#include <soc/pm.h>
+#include <soc/romstage.h>
+#include <soc/soc_chip.h>
+#include <string.h>
+
+#define FSP_SMBIOS_MEMORY_INFO_GUID \
+{ \
+ 0xd4, 0x71, 0x20, 0x9b, 0x54, 0xb0, 0x0c, 0x4e, \
+ 0x8d, 0x09, 0x11, 0xcf, 0x8b, 0x9f, 0x03, 0x23 \
+}
+
+/* Save the DIMM information for SMBIOS table 17 */
+static void save_dimm_info(void)
+{
+ int node, channel, dimm, dimm_max, index;
+ size_t hob_size;
+ const CONTROLLER_INFO *ctrlr_info;
+ const CHANNEL_INFO *channel_info;
+ const DIMM_INFO *src_dimm;
+ struct dimm_info *dest_dimm;
+ struct memory_info *mem_info;
+ const MEMORY_INFO_DATA_HOB *meminfo_hob;
+ const uint8_t smbios_memory_info_guid[sizeof(EFI_GUID)] = FSP_SMBIOS_MEMORY_INFO_GUID;
+ const uint8_t *serial_num;
+ const char *dram_part_num = NULL;
+ size_t dram_part_num_len = 0;
+
+ /* Locate the memory info HOB, presence validated by raminit */
+ meminfo_hob = fsp_find_extension_hob_by_guid(
+ smbios_memory_info_guid,
+ &hob_size);
+ if (meminfo_hob == NULL || hob_size == 0) {
+ printk(BIOS_ERR, "SMBIOS MEMORY_INFO_DATA_HOB not found\n");
+ return;
+ }
+
+ /*
+ * Allocate CBMEM area for DIMM information used to populate SMBIOS
+ * table 17
+ */
+ mem_info = cbmem_add(CBMEM_ID_MEMINFO, sizeof(*mem_info));
+ if (mem_info == NULL) {
+ printk(BIOS_ERR, "CBMEM entry for DIMM info missing\n");
+ return;
+ }
+ memset(mem_info, 0, sizeof(*mem_info));
+
+ /* Allow mainboard to override DRAM part number. */
+ dram_part_num = mainboard_get_dram_part_num();
+ if (dram_part_num)
+ dram_part_num_len = strlen(dram_part_num);
+
+ /* Save available DIMM information */
+ index = 0;
+ dimm_max = ARRAY_SIZE(mem_info->dimm);
+ for (node = 0; node < MAX_NODE; node++) {
+ ctrlr_info = &meminfo_hob->Controller[node];
+ for (channel = 0; channel < MAX_CH && index < dimm_max; channel++) {
+ channel_info = &ctrlr_info->ChannelInfo[channel];
+ if (channel_info->Status != CHANNEL_PRESENT)
+ continue;
+
+ for (dimm = 0; dimm < MAX_DIMM && index < dimm_max; dimm++) {
+ src_dimm = &channel_info->DimmInfo[dimm];
+ dest_dimm = &mem_info->dimm[index];
+ if (src_dimm->Status != DIMM_PRESENT)
+ continue;
+
+ /* If there is no DRAM part number overridden by
+ * mainboard then use original one. */
+ if (!dram_part_num) {
+ dram_part_num_len = sizeof(src_dimm->ModulePartNum);
+ dram_part_num = (const char *)
+ &src_dimm->ModulePartNum[0];
+ }
+
+ uint8_t memProfNum = meminfo_hob->MemoryProfile;
+ serial_num = src_dimm->SpdSave + SPD_SAVE_OFFSET_SERIAL;
+
+ /* Populate the DIMM information */
+ dimm_info_fill(dest_dimm,
+ src_dimm->DimmCapacity,
+ meminfo_hob->MemoryType,
+ meminfo_hob->ConfiguredMemoryClockSpeed,
+ src_dimm->RankInDimm,
+ channel_info->ChannelId,
+ src_dimm->DimmId,
+ dram_part_num,
+ dram_part_num_len,
+ serial_num,
+ meminfo_hob->DataWidth,
+ meminfo_hob->VddVoltage[memProfNum],
+ meminfo_hob->EccSupport,
+ src_dimm->MfgId,
+ src_dimm->SpdModuleType);
+ index++;
+ }
+ }
+ }
+ mem_info->dimm_cnt = index;
+ printk(BIOS_DEBUG, "%d DIMMs found\n", mem_info->dimm_cnt);
+}
+
+void mainboard_romstage_entry(void)
+{
+ bool s3wake;
+ struct chipset_power_state *ps = pmc_get_power_state();
+
+ /* Program MCHBAR, DMIBAR, GDXBAR and EDRAMBAR */
+ systemagent_early_init();
+ /* Program SMBus base address and enable it */
+ smbus_common_init();
+ /* Initialize HECI interface */
+ cse_init(HECI1_BASE_ADDRESS);
+
+ s3wake = pmc_fill_power_state(ps) == ACPI_S3;
+ if (!s3wake) {
+ if (CONFIG(SOC_INTEL_CSE_LITE_SKU))
+ cse_fw_sync();
+ }
+
+ fsp_memory_init(s3wake);
+ pmc_set_disb();
+ if (!s3wake)
+ save_dimm_info();
+}
diff --git a/src/soc/intel/meteorlake/romstage/systemagent.c b/src/soc/intel/meteorlake/romstage/systemagent.c
new file mode 100644
index 0000000000..6e9b9fa486
--- /dev/null
+++ b/src/soc/intel/meteorlake/romstage/systemagent.c
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <intelblocks/systemagent.h>
+#include <soc/iomap.h>
+#include <soc/romstage.h>
+#include <soc/systemagent.h>
+
+void systemagent_early_init(void)
+{
+ static const struct sa_mmio_descriptor soc_fixed_pci_resources[] = {
+ { MCHBAR, MCH_BASE_ADDRESS, MCH_BASE_SIZE, "MCHBAR" },
+ { DMIBAR, DMI_BASE_ADDRESS, DMI_BASE_SIZE, "DMIBAR" },
+ { EPBAR, EP_BASE_ADDRESS, EP_BASE_SIZE, "EPBAR" },
+ };
+
+ static const struct sa_mmio_descriptor soc_fixed_mch_resources[] = {
+ { REGBAR, REG_BASE_ADDRESS, REG_BASE_SIZE, "REGBAR" },
+ { EDRAMBAR, EDRAM_BASE_ADDRESS, EDRAM_BASE_SIZE, "EDRAMBAR" },
+ };
+
+ /* Set Fixed MMIO address into PCI configuration space */
+ sa_set_pci_bar(soc_fixed_pci_resources,
+ ARRAY_SIZE(soc_fixed_pci_resources));
+ /* Set Fixed MMIO address into MCH base address */
+ sa_set_mch_bar(soc_fixed_mch_resources,
+ ARRAY_SIZE(soc_fixed_mch_resources));
+ /* Enable PAM registers */
+ enable_pam_region();
+}