Attention is currently required from: Christian Walter, Johnny Lin, Jonathan Zhang, Shuo Liu, Tim Chu.
Patrick Rudolph has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/85845?usp=email )
Change subject: soc/intel/xeon_sp: Add Xeon ICX-SP support ......................................................................
soc/intel/xeon_sp: Add Xeon ICX-SP support
Add support for the 1st Gen 10nm Xeon-SP CPUs. Supported and tested are dual socket systems with a LBG PCH.
The WhitleyFSP, that is being used here, never has been validated in API mode and has several flaws: - CPU PCIe ports MUST be disabled - QPI links MUST run at degraded speeds
Currently uses the SPR ACPI code.
TEST: Boots to Linux userspace. No errors in coreboot or dmesg visible. TODO: Merge with SPR code base.
Change-Id: I7bb74c0db2c91c87bf623c079f89fd139780160b Signed-off-by: Patrick Rudolph patrick.rudolph@9elements.com --- M src/include/cpu/intel/cpu_ids.h M src/soc/intel/xeon_sp/Makefile.mk A src/soc/intel/xeon_sp/icx/Kconfig A src/soc/intel/xeon_sp/icx/Makefile.mk A src/soc/intel/xeon_sp/icx/chip.c A src/soc/intel/xeon_sp/icx/chip.h A src/soc/intel/xeon_sp/icx/chipset.cb A src/soc/intel/xeon_sp/icx/cpu.c A src/soc/intel/xeon_sp/icx/hob_display.c A src/soc/intel/xeon_sp/icx/include/soc/pci_devs.h A src/soc/intel/xeon_sp/icx/include/soc/soc_msr.h A src/soc/intel/xeon_sp/icx/include/soc/soc_util.h A src/soc/intel/xeon_sp/icx/ramstage.c A src/soc/intel/xeon_sp/icx/reset.c A src/soc/intel/xeon_sp/icx/romstage.c A src/soc/intel/xeon_sp/icx/soc_acpi.c A src/soc/intel/xeon_sp/icx/soc_util.c A src/soc/intel/xeon_sp/icx/upd_display.c 18 files changed, 1,614 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/45/85845/1
diff --git a/src/include/cpu/intel/cpu_ids.h b/src/include/cpu/intel/cpu_ids.h index 9ef74b9..8239294 100644 --- a/src/include/cpu/intel/cpu_ids.h +++ b/src/include/cpu/intel/cpu_ids.h @@ -24,6 +24,13 @@ #define CPUID_CANNONLAKE_B0 0x60661 #define CPUID_CANNONLAKE_C0 0x60662 #define CPUID_CANNONLAKE_D0 0x60663 +#define CPUID_ICELAKE_SP_A 0x606a0 +#define CPUID_ICELAKE_SP_B 0x606a1 +#define CPUID_ICELAKE_SP_C 0x606a2 +#define CPUID_ICELAKE_SP_E0 0x606a3 +#define CPUID_ICELAKE_SP_E1 0x606a4 +#define CPUID_ICELAKE_SP_E2 0x606a5 +#define CPUID_ICELAKE_SP_D 0x606a6 #define CPUID_APOLLOLAKE_A0 0x506c8 #define CPUID_APOLLOLAKE_B0 0x506c9 #define CPUID_APOLLOLAKE_E0 0x506ca diff --git a/src/soc/intel/xeon_sp/Makefile.mk b/src/soc/intel/xeon_sp/Makefile.mk index c66b8ad..3fbeda1 100644 --- a/src/soc/intel/xeon_sp/Makefile.mk +++ b/src/soc/intel/xeon_sp/Makefile.mk @@ -4,6 +4,7 @@
subdirs-$(CONFIG_SOC_INTEL_SKYLAKE_SP) += skx lbg subdirs-$(CONFIG_SOC_INTEL_COOPERLAKE_SP) += cpx lbg +subdirs-$(CONFIG_SOC_INTEL_ICELAKE_SP) += icx lbg subdirs-$(CONFIG_SOC_INTEL_SAPPHIRERAPIDS_SP) += spr ebg subdirs-$(CONFIG_SOC_INTEL_GRANITERAPIDS) += gnr ibl
diff --git a/src/soc/intel/xeon_sp/icx/Kconfig b/src/soc/intel/xeon_sp/icx/Kconfig new file mode 100644 index 0000000..cf9eb3a --- /dev/null +++ b/src/soc/intel/xeon_sp/icx/Kconfig @@ -0,0 +1,162 @@ +## SPDX-License-Identifier: GPL-2.0-only + +config SOC_INTEL_ICELAKE_SP + bool + select FSP_NVS_DATA_POST_SILICON_INIT + select SOC_INTEL_MEM_MAPPED_PM_CONFIGURATION + select DISABLE_ACPI_HIBERNATE + select DEFAULT_X2APIC_RUNTIME + select CACHE_MRC_SETTINGS + select CPU_INTEL_TURBO_NOT_PACKAGE_SCOPED + select FSP_SPEC_VIOLATION_XEON_SP_HEAP_WORKAROUND + select PLATFORM_USES_FSP2_1 + select SOC_INTEL_CSE_SERVER_SKU + select XEON_SP_COMMON_BASE + select HAVE_INTEL_FSP_REPO + select UDK_202005_BINDING + select HAVE_X86_64_SUPPORT + select IDT_IN_EVERY_STAGE + help + Intel Ice Lake-SP support + +if SOC_INTEL_ICELAKE_SP + +config CHIPSET_DEVICETREE + string + default "soc/intel/xeon_sp/icx/chipset.cb" + +config FSP_HEADER_PATH + default "3rdparty/fsp/WhitleyFspBinPkg/Include/" + +config FSP_FD_PATH + string + depends on FSP_USE_REPO + default "3rdparty/fsp/WhitleyFspBinPkg/Fsp.fd" + +config MAX_CPUS + int + default 255 + +config ACPI_CPU_STRING + string + default "C%03X" + +config PCR_BASE_ADDRESS + hex + default 0xfd000000 + help + This option allows you to select MMIO Base Address of sideband bus. + +config DCACHE_RAM_BASE + hex + default 0xfe800000 + +config DCACHE_RAM_SIZE + hex + default 0x1fff00 + help + The size of the cache-as-ram region required during bootblock + and/or romstage. FSP-T reserves the upper 0x100 for + FspReservedBuffer. + +config DCACHE_BSP_STACK_SIZE + hex + default 0x40000 + help + The amount of anticipated stack usage in CAR by bootblock and + other stages. It needs to include FSP-M stack requirement and + CB romstage stack requirement. The integration documentation + says this needs to be 256KiB. + +config FSP_M_RC_HEAP_SIZE + hex + default 0x130000 + help + On xeon_sp/spr FSP-M has two separate heap managers, one regular + whose size and base are controllable via the StackBase and + StackSize UPDs and a 'rc' heap manager that is statically + allocated at 0xfe800000 (the CAR base) and consumes about 0x130000 + bytes of memory. + + +config STACK_SIZE + hex + default 0x4000 + +config FSP_TEMP_RAM_SIZE + hex + depends on FSP_USES_CB_STACK + default 0x50000 + 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. The FSP integration + documentation says this needs to be at least 128KiB, but practice + show this needs to be 256KiB or more. + +config IED_REGION_SIZE + hex + default 0x400000 + +config IFD_CHIPSET + string + default "lbg" + +config SOC_INTEL_COMMON_BLOCK_P2SB + def_bool y + +config SOC_INTEL_HAS_BIOS_DONE_MSR + def_bool y + +config SOC_INTEL_HAS_NCMEM + def_bool y + +config CPU_BCLK_MHZ + int + default 100 + +# SPR-SP has 4 IMCs, 2 channels per IMC, 2 DIMMs per channel +# Default value is set to two sockets, full config. +config MAX_IMC + int + default 4 + +config DIMM_MAX + int + default 32 + +# DDR4 +config DIMM_SPD_SIZE + int + default 1024 + +config MAX_ACPI_TABLE_SIZE_KB + int + default 512 if MAX_SOCKET = 4 + default 224 + +config FIXED_SMBUS_IO_BASE + default 0x780 + +config DISPLAY_UPD_IIO_DATA + def_bool n + depends on DISPLAY_UPD_DATA + +if INTEL_TXT + +config INTEL_TXT_SINIT_SIZE + hex + default 0x50000 + help + According to document number 572782 this needs to be 256KiB + for the SINIT module and 64KiB for SINIT data. + +config INTEL_TXT_HEAP_SIZE + hex + default 0xf0000 + help + This must be 960KiB according to 572782. + +endif # INTEL_TXT + +endif diff --git a/src/soc/intel/xeon_sp/icx/Makefile.mk b/src/soc/intel/xeon_sp/icx/Makefile.mk new file mode 100644 index 0000000..cddfff1 --- /dev/null +++ b/src/soc/intel/xeon_sp/icx/Makefile.mk @@ -0,0 +1,31 @@ +## SPDX-License-Identifier: GPL-2.0-only + +ifeq ($(CONFIG_SOC_INTEL_ICELAKE_SP),y) + +subdirs-y += ../../../../cpu/intel/turbo +subdirs-y += ../../../../cpu/x86/lapic +subdirs-y += ../../../../cpu/x86/mtrr +subdirs-y += ../../../../cpu/x86/tsc +subdirs-y += ../../../../cpu/intel/microcode + +romstage-y += romstage.c soc_util.c +romstage-$(CONFIG_DISPLAY_HOBS) += hob_display.c +romstage-$(CONFIG_DISPLAY_UPD_DATA) += upd_display.c + +ramstage-y += chip.c cpu.c soc_util.c ramstage.c soc_acpi.c reset.c +ramstage-y += ../chip_gen1.c ../lpc_gen1.c +ramstage-$(CONFIG_DISPLAY_HOBS) += hob_display.c +ramstage-$(CONFIG_DISPLAY_UPD_DATA) += upd_display.c +ramstage-y += ../pcu0.c +ramstage-y += ../pcu1.c +ramstage-y += ../pcu2.c +ramstage-y += ../pcu3.c +ramstage-y += ../pcu6.c + +CPPFLAGS_common += -I$(src)/soc/intel/xeon_sp/icx/include -I$(src)/soc/intel/xeon_sp/icx +CPPFLAGS_common += -I$(src)/vendorcode/intel/fsp/fsp2_0/whitley + +cpu_microcode_bins += 3rdparty/intel-microcode/intel-ucode/06-6a-05 +cpu_microcode_bins += 3rdparty/intel-microcode/intel-ucode/06-6a-06 + +endif ## CONFIG_SOC_INTEL_ICELAKE_SP diff --git a/src/soc/intel/xeon_sp/icx/chip.c b/src/soc/intel/xeon_sp/icx/chip.c new file mode 100644 index 0000000..c909d2a --- /dev/null +++ b/src/soc/intel/xeon_sp/icx/chip.c @@ -0,0 +1,92 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#include <acpi/acpigen_pci.h> +#include <arch/ioapic.h> +#include <console/console.h> +#include <console/debug.h> +#include <cpu/x86/lapic.h> +#include <device/pci.h> +#include <device/pci_ids.h> +#include <device/pciexp.h> +#include <intelblocks/acpi.h> +#include <intelblocks/gpio.h> +#include <intelblocks/lpc_lib.h> +#include <intelblocks/p2sb.h> +#include <intelblocks/pcr.h> +#include <intelblocks/tco.h> +#include <soc/acpi.h> +#include <soc/chip_common.h> +#include <soc/numa.h> +#include <soc/p2sb.h> +#include <soc/pch.h> +#include <soc/soc_pch.h> +#include <soc/pci_devs.h> +#include <soc/ramstage.h> +#include <soc/soc_util.h> +#include <soc/util.h> + +__weak void mainboard_silicon_init_params(FSPS_UPD *params) +{ +} + +/* UPD parameters to be initialized before SiliconInit */ +void platform_fsp_silicon_init_params_cb(FSPS_UPD *silupd) +{ + mainboard_silicon_init_params(silupd); +} + +static struct device_operations cpu_bus_ops = { + .read_resources = noop_read_resources, + .set_resources = noop_set_resources, + .init = mp_cpu_bus_init, + .acpi_fill_ssdt = generate_cpu_entries, +}; + +struct pci_operations soc_pci_ops = { + .set_subsystem = pci_dev_set_subsystem, +}; + +static void chip_enable_dev(struct device *dev) +{ + /* Set the operations if it is a special bus type */ + if (dev->path.type == DEVICE_PATH_DOMAIN) { + /* domain ops are assigned at their creation */ + } else if (dev->path.type == DEVICE_PATH_CPU_CLUSTER) { + dev->ops = &cpu_bus_ops; + } else if (dev->path.type == DEVICE_PATH_GPIO) { + block_gpio_enable(dev); + } +} + +static void chip_final(void *data) +{ + /* Lock SBI */ + pci_or_config32(PCH_DEV_P2SB, P2SBC, SBILOCK); + + /* LOCK PAM */ + pci_or_config32(pcidev_path_on_root(PCI_DEVFN(0, 0)), 0x80, 1 << 0); + + tco_lockdown(); + + p2sb_hide(); +} + +static void chip_init(void *data) +{ + printk(BIOS_DEBUG, "coreboot: calling fsp_silicon_init\n"); + fsp_silicon_init(); + + setup_pds(); + attach_iio_stacks(); + + override_hpet_ioapic_bdf(); + pch_enable_ioapic(); + pch_lock_dmictl(); + p2sb_unhide(); +} + +struct chip_operations soc_intel_xeon_sp_icx_ops = { + .name = "Intel Ice Lake-SP", + .enable_dev = chip_enable_dev, + .init = chip_init, + .final = chip_final, +}; diff --git a/src/soc/intel/xeon_sp/icx/chip.h b/src/soc/intel/xeon_sp/icx/chip.h new file mode 100644 index 0000000..3163153 --- /dev/null +++ b/src/soc/intel/xeon_sp/icx/chip.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef _SOC_CHIP_H_ +#define _SOC_CHIP_H_ + +#include <intelblocks/cfg.h> +#include <soc/acpi.h> +#include <soc/irq.h> +#include <stdint.h> + +struct soc_intel_xeon_sp_icx_config { + /* Common struct containing soc config data required by common code */ + struct soc_intel_common_config common_soc_config; + + uint64_t turbo_ratio_limit; + uint64_t turbo_ratio_limit_cores; + + uint32_t pstate_req_ratio; + + uint8_t vtd_support; + + /* Generic IO decode ranges */ + uint32_t gen1_dec; + uint32_t gen2_dec; + uint32_t gen3_dec; + uint32_t gen4_dec; + + /* TCC activation offset */ + uint32_t tcc_offset; + + enum acpi_cstate_mode cstate_states; +}; + +typedef struct soc_intel_xeon_sp_icx_config config_t; + +#endif diff --git a/src/soc/intel/xeon_sp/icx/chipset.cb b/src/soc/intel/xeon_sp/icx/chipset.cb new file mode 100644 index 0000000..ae4553f --- /dev/null +++ b/src/soc/intel/xeon_sp/icx/chipset.cb @@ -0,0 +1,63 @@ +## SPDX-License-Identifier: GPL-2.0-or-later + +chip soc/intel/xeon_sp/icx + # configure PSTATE_REQ_RATIO for MSR_IA32_PERF_CTRL + register "pstate_req_ratio" = "0xa" + + # configure VT-d + register "vtd_support" = "1" + + register "gen2_dec" = "0x000c0ca1" # IPMI KCS + + register "cstate_states" = "CSTATES_C1C6" + device cpu_cluster 0 on end + device domain 0 on + device pci 00.0 on end # Intel device 09a2: Memory Map/Intel VT-d + device pci 00.1 on end # Intel device 09a4: Mesh to IAL + device pci 00.4 on end # Intel device 0b23: IEH + device pci 00.2 on end # Intel device 09a3: RAS + device pci 01.0 on end # Intel device 3c01: Port A PCIe Gen5 + device pci 02.0 on end # Intel device 3c01: Port D PCIe Gen4 + device pci 03.0 on end # Intel device 3c01: Port B PCIe Gen5 + device pci 04.0 on end # Intel device 3c01: Port C PCIe Gen4 + device pci 05.0 on end # Intel device 3c01: Port C PCIe Gen5 + device pci 06.0 on end # Intel device 3c01: Port B PCIe Gen4 + device pci 07.0 on end # Intel device 3c01: Port D PCIe Gen5 + device pci 08.0 on end # Intel device 2020: DMI + device pci 09.0 on end # Intel device 1bb9: PCH PCIe Root Port #1 + device pci 0a.0 on end # Intel device 1bba: PCH PCIe Root Port #2 + device pci 0b.0 on end # Intel device 1bbb: PCH PCIe Root Port #3 + device pci 0c.0 on end # Intel device 1bbc: PCH PCIe Root Port #4 + device pci 0d.0 on end # Intel device 1bbd: PCH PCIe Root Port #5 + device pci 0e.0 on end # Intel device 1bbe: PCH PCIe Root Port #6 + device pci 0f.0 on end # Intel device 1bbf: PCH PCIe Root Port #7 + device pci 10.0 on end # Intel device 1bb0: PCH PCIe Root Port #8 + device pci 11.0 on end # Intel device 1bb1: PCH PCIe Root Port #9 + device pci 12.0 on end # Intel device 1bb2: PCH PCIe Root Port #10 + device pci 13.0 on end # Intel device 1bb3: PCH PCIe Root Port #11 + device pci 14.0 on end # Intel device 1bcd: PCH USB 3.0 XHCI Controller + device pci 14.2 on end # Intel device 1bce: PCH PMC shared RAM + device pci 15.0 on end # Intel device 1bff + device pci 16.0 on end # Intel device 1be0: PCH ME HECI #1 + device pci 16.1 on end # Intel device 1be1: PCH ME HECI #2 + device pci 16.3 on end # Serial controller: Intel Corporation Device 1be3 + device pci 16.4 on end # Intel device 1be4: PCH ME HECI #3 + device pci 16.5 on end # Intel device 1be5: PCH ME HECI #4 + device pci 16.6 on end # Intel device 1be6 + device pci 17.0 on end # Intel device 1ba2: PCH SATA controller 0 (AHCI) + device pci 18.0 on end # Intel device 1bf2: PCH SATA controller 1 (AHCI) + device pci 19.0 on end # Intel device 1bd2: PCH SATA controller 2 (AHCI) + device pci 1a.0 on end # Intel device 1bb4: PCH PCIe Root Port #12 + device pci 1b.0 on end # Intel device 1bb5: PCH PCIe Root Port #13 + device pci 1e.0 on end # Intel device Communication controller: Intel Corporation Device 1bad + device pci 1f.0 on end # Intel device 1b81: PCH eSPI controller + device pci 1f.1 on end # Intel device 1bc6: PCH P2SB + device pci 1f.2 on end # Intel device 1bc7: PCH PMC + device pci 1f.3 on end # Intel device 1bc8: PCH audio + device pci 1f.4 on end # Intel device 1bc9: PCH SMBus + device pci 1f.5 on end # Intel device 1bca: PCH SPI controller + device pci 1f.6 on end # Intel device 1bcb: PCH GbE controller + device pci 1f.7 on end # Intel device 1bcc: PCH TH + + end +end diff --git a/src/soc/intel/xeon_sp/icx/cpu.c b/src/soc/intel/xeon_sp/icx/cpu.c new file mode 100644 index 0000000..a23bba8 --- /dev/null +++ b/src/soc/intel/xeon_sp/icx/cpu.c @@ -0,0 +1,268 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <console/debug.h> +#include <cpu/intel/common/common.h> +#include <cpu/intel/microcode.h> +#include <cpu/intel/smm_reloc.h> +#include <cpu/intel/turbo.h> +#include <cpu/x86/mp.h> +#include <cpu/x86/topology.h> +#include <intelblocks/cpulib.h> +#include <intelblocks/mp_init.h> +#include <intelpch/lockdown.h> +#include <soc/msr.h> +#include <soc/pm.h> +#include <soc/smmrelocate.h> +#include <soc/util.h> + +#include "chip.h" + +static const void *microcode_patch; + +static const config_t *chip_config = NULL; + +bool cpu_soc_is_in_untrusted_mode(void) +{ + return false; +} + +void cpu_soc_bios_done(void) +{ +} + +static void xeon_configure_mca(void) +{ + msr_t msr; + struct cpuid_result cpuid_regs; + + /* + * Check feature flag in CPUID.(EAX=1):EDX[7]==1 MCE + * and CPUID.(EAX=1):EDX[14]==1 MCA + */ + cpuid_regs = cpuid(1); + if ((cpuid_regs.edx & (1 << 7 | 1 << 14)) != (1 << 7 | 1 << 14)) + return; + + msr = rdmsr(IA32_MCG_CAP); + if (msr.lo & IA32_MCG_CAP_CTL_P_MASK) { + /* Enable all error logging */ + msr.lo = msr.hi = 0xffffffff; + wrmsr(IA32_MCG_CTL, msr); + } + + mca_configure(); +} + +/* + * On server platforms the FIT mechanism only updates the microcode on + * the BSP. Loading MCU on AP in parallel seems to fail in 10% of the cases + * so do it serialized. + */ +void get_microcode_info(const void **microcode, int *parallel) +{ + *microcode = intel_microcode_find(); + *parallel = 0; +} + +static void each_cpu_init(struct device *cpu) +{ + msr_t msr; + + printk(BIOS_SPEW, "%s dev: %s, cpu: %lu, apic_id: 0x%x, package_id: 0x%x\n", + __func__, dev_path(cpu), cpu_index(), cpu->path.apic.apic_id, + cpu->path.apic.package_id); + + /* Populate the node ID. It will be used as proximity ID. */ + assert (cpu->path.apic.node_id < CONFIG_MAX_SOCKET); + + /* + * Enable PWR_PERF_PLTFRM_OVR and PROCHOT_LOCK. + * The value set by FSP is 20_005f, we set it to 1a_00a4_005b. + */ + msr = rdmsr(MSR_POWER_CTL); + msr.lo |= (0x16 << RESERVED1_SHIFT) | PWR_PERF_PLTFRM_OVR | PROCHOT_LOCK; + msr.hi = 0x1a; + wrmsr(MSR_POWER_CTL, msr); + + + /* Set static, idle, dynamic load line impedance */ + msr = rdmsr(MSR_VR_MISC_CONFIG); + msr.lo = 0x1a1a1a; + wrmsr(MSR_VR_MISC_CONFIG, msr); +#if 0 + /* Set current limitation */ + msr = rdmsr(MSR_VR_CURRENT_CONFIG); + msr.lo = 0x1130; + msr.lo |= CURRENT_LIMIT_LOCK; + wrmsr(MSR_VR_CURRENT_CONFIG, msr); +#endif + /* Set Turbo Ratio Limits */ + msr.lo = chip_config->turbo_ratio_limit & 0xffffffff; + msr.hi = (chip_config->turbo_ratio_limit >> 32) & 0xffffffff; + wrmsr(MSR_TURBO_RATIO_LIMIT, msr); + + /* Set Turbo Ratio Limit Cores */ + msr.lo = chip_config->turbo_ratio_limit_cores & 0xffffffff; + msr.hi = (chip_config->turbo_ratio_limit_cores >> 32) & 0xffffffff; + wrmsr(MSR_TURBO_RATIO_LIMIT_CORES, msr); + + /* Set energy policy */ + msr = rdmsr(MSR_ENERGY_PERF_BIAS_CONFIG); + msr.lo = 0x178fa038; + wrmsr(MSR_ENERGY_PERF_BIAS_CONFIG, msr); + + msr.hi = 0x158d20; + msr.lo = 0x00158af0; + wrmsr(PACKAGE_RAPL_LIMIT, msr); + + /* + * Set HWP base feature, EPP reg enumeration, lock thermal and msr + * This is package level MSR. Need to check if it updates correctly on + * multi-socket platform. + */ + msr = rdmsr(MSR_MISC_PWR_MGMT); + if (!(msr.lo & LOCK_MISC_PWR_MGMT_MSR)) { /* if already locked skip update */ + msr.lo = (HWP_ENUM_ENABLE | HWP_EPP_ENUM_ENABLE | LOCK_MISC_PWR_MGMT_MSR + | LOCK_THERM_INT); + wrmsr(MSR_MISC_PWR_MGMT, msr); + } + + /* Enable Fast Strings */ + msr = rdmsr(IA32_MISC_ENABLE); + msr.lo |= FAST_STRINGS_ENABLE_BIT; + wrmsr(IA32_MISC_ENABLE, msr); + /* Enable Turbo */ + enable_turbo(); + + /* Enable speed step. */ + if (get_turbo_state() == TURBO_ENABLED) { + msr = rdmsr(IA32_MISC_ENABLE); + msr.lo |= SPEED_STEP_ENABLE_BIT; + wrmsr(IA32_MISC_ENABLE, msr); + } + + /* Lock the supported Cstates */ + msr = rdmsr(MSR_PKG_CST_CONFIG_CONTROL); + if (!(msr.lo & CST_CFG_LOCK_MASK)) { + msr.lo |= CST_CFG_LOCK_MASK; + wrmsr(MSR_PKG_CST_CONFIG_CONTROL, msr); + } + + /* Disable all writes to overclocking limits MSR */ + msr = rdmsr(MSR_FLEX_RATIO); + if (!(msr.lo & MSR_FLEX_RATIO_OC_LOCK)) { + msr.lo |= MSR_FLEX_RATIO_OC_LOCK; + wrmsr(MSR_FLEX_RATIO, msr); + } + + /* Lock Power Plane Limit MSR */ + msr = rdmsr(MSR_DRAM_PLANE_POWER_LIMIT); + if (!(msr.hi & MSR_HI_PP_PWR_LIM_LOCK)) { + msr.hi |= MSR_HI_PP_PWR_LIM_LOCK; + wrmsr(MSR_DRAM_PLANE_POWER_LIMIT, msr); + } + + /* Clear out pending MCEs */ + xeon_configure_mca(); + + /* Enable Vmx */ + set_vmx_and_lock(); + /* only lock. let vmx enable by FSP */ + set_feature_ctrl_lock(); +} + +static struct device_operations cpu_dev_ops = { + .init = each_cpu_init, +}; + +static const struct cpu_device_id cpu_table[] = { + {X86_VENDOR_INTEL, CPUID_ICELAKE_SP_A, CPUID_EXACT_MATCH_MASK}, + {X86_VENDOR_INTEL, CPUID_ICELAKE_SP_B, CPUID_EXACT_MATCH_MASK}, + {X86_VENDOR_INTEL, CPUID_ICELAKE_SP_C, CPUID_EXACT_MATCH_MASK}, + {X86_VENDOR_INTEL, CPUID_ICELAKE_SP_E0, CPUID_EXACT_MATCH_MASK}, + {X86_VENDOR_INTEL, CPUID_ICELAKE_SP_E1, CPUID_EXACT_MATCH_MASK}, + {X86_VENDOR_INTEL, CPUID_ICELAKE_SP_E2, CPUID_EXACT_MATCH_MASK}, + {X86_VENDOR_INTEL, CPUID_ICELAKE_SP_D, CPUID_EXACT_MATCH_MASK}, + CPU_TABLE_END +}; + +static const struct cpu_driver driver __cpu_driver = { + .ops = &cpu_dev_ops, + .id_table = cpu_table, +}; + +static void set_max_turbo_freq(void) +{ + msr_t msr, perf_ctl; + + FUNC_ENTER(); + perf_ctl.hi = 0; + + /* Check for configurable TDP option */ + if (get_turbo_state() == TURBO_ENABLED) { + msr = rdmsr(MSR_TURBO_RATIO_LIMIT); + perf_ctl.lo = (msr.lo & 0xff) << 8; + } else if (cpu_config_tdp_levels()) { + /* Set to nominal TDP ratio */ + msr = rdmsr(MSR_CONFIG_TDP_NOMINAL); + perf_ctl.lo = (msr.lo & 0xff) << 8; + } else { + /* Platform Info bits 15:8 give max ratio */ + msr = rdmsr(MSR_PLATFORM_INFO); + perf_ctl.lo = msr.lo & 0xff00; + } + wrmsr(IA32_PERF_CTL, perf_ctl); + + printk(BIOS_DEBUG, "cpu: frequency set to %d\n", + ((perf_ctl.lo >> 8) & 0xff) * CONFIG_CPU_BCLK_MHZ); + FUNC_EXIT(); +} + +/* + * Do essential initialization tasks before APs can be fired up + */ +static void pre_mp_init(void) +{ + x86_setup_mtrrs_with_detect(); + x86_mtrr_check(); +} + +static void post_mp_init(void) +{ + /* Set Max Ratio */ + set_max_turbo_freq(); + + if (CONFIG(HAVE_SMI_HANDLER)) { + global_smi_enable(); + if (get_lockdown_config() == CHIPSET_LOCKDOWN_COREBOOT) + pmc_lock_smi(); + } +} + +static const struct mp_ops mp_ops = { + .pre_mp_init = pre_mp_init, + .get_cpu_count = get_platform_thread_count, +#if CONFIG(HAVE_SMI_HANDLER) + .get_smm_info = get_smm_info, + .pre_mp_smm_init = smm_southbridge_clear_state, + .relocation_handler = smm_relocation_handler, +#endif + .get_microcode_info = get_microcode_info, + .post_mp_init = post_mp_init, +}; + +void mp_init_cpus(struct bus *bus) +{ + /* + * chip_config is used in cpu device callback. Other than cpu 0, + * rest of the CPU devices do not have chip_info updated. + */ + chip_config = bus->dev->chip_info; + + microcode_patch = intel_microcode_find(); + intel_microcode_load_unlocked(microcode_patch); + + enum cb_err ret = mp_init_with_smm(bus, &mp_ops); + if (ret != CB_SUCCESS) + printk(BIOS_ERR, "MP initialization failure %d.\n", ret); +} diff --git a/src/soc/intel/xeon_sp/icx/hob_display.c b/src/soc/intel/xeon_sp/icx/hob_display.c new file mode 100644 index 0000000..7f1f719 --- /dev/null +++ b/src/soc/intel/xeon_sp/icx/hob_display.c @@ -0,0 +1,226 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <console/console.h> +#include <fsp/util.h> +#include <hob_cxlnode.h> +#include <hob_iiouds.h> +#include <hob_memmap.h> +#include <lib.h> +#include <soc/soc_util.h> + +static const uint8_t fsp_hob_iio_uds_guid[16] = FSP_HOB_IIO_UNIVERSAL_DATA_GUID; +static const uint8_t fsp_hob_memmap_guid[16] = FSP_SYSTEM_MEMORYMAP_HOB_GUID; +static const uint8_t fsp_hob_cxlnode_guid[16] = FSP_HOB_CXLNODE_GUID; + +struct guid_name_map { + const void *guid; + const char *name; +}; + +static const struct guid_name_map guid_names[] = { + {fsp_hob_iio_uds_guid, "FSP_HOB_IIO_UNIVERSAL_DATA_GUID"}, + {fsp_hob_memmap_guid, "FSP_SYSTEM_MEMORYMAP_HOB_GUID"}, + {fsp_hob_cxlnode_guid, "FSP_HOB_CXLNODE_GUID"}, +}; + +const char *soc_get_guid_name(const uint8_t *guid) +{ + size_t index; + + /* Compare the GUID values in this module */ + for (index = 0; index < ARRAY_SIZE(guid_names); index++) + if (fsp_guid_compare(guid, guid_names[index].guid)) + return guid_names[index].name; + + return NULL; +} + +void soc_display_memmap_hob(const struct SystemMemoryMapHob **hob_addr) +{ + struct SystemMemoryMapHob *hob = (struct SystemMemoryMapHob *)*hob_addr; + + printk(BIOS_DEBUG, "================== MEMORY MAP HOB DATA ==================\n"); + printk(BIOS_DEBUG, "hob: %p, structure size: 0x%lx\n", hob, sizeof(*hob)); + + printk(BIOS_DEBUG, + "\tlowMemBase: 0x%x, lowMemSize: 0x%x, highMemBase: 0x%x, " + "highMemSize: 0x%x\n", + hob->lowMemBase, hob->lowMemSize, hob->highMemBase, hob->highMemSize); + printk(BIOS_DEBUG, "\tmemSize: 0x%x, memFreq: 0x%x\n", hob->memSize, hob->memFreq); + + printk(BIOS_DEBUG, "\tNumChPerMC: %d\n", hob->NumChPerMC); + printk(BIOS_DEBUG, "\tSystemMemoryMapElement Entries: %d, entry size: %ld\n", + hob->numberEntries, sizeof(SYSTEM_MEMORY_MAP_ELEMENT)); + + for (int e = 0; e < hob->numberEntries; ++e) { + const struct SystemMemoryMapElement *mem_element = &hob->Element[e]; + printk(BIOS_DEBUG, + "\t\tmemory_map %d, SocketId: 0x%x, BaseAddress: 0x%x, ElementSize: 0x%x, Type: 0x%x\n", + e, mem_element->SocketId, mem_element->BaseAddress, + mem_element->ElementSize, mem_element->Type); + } + + printk(BIOS_DEBUG, + "^^^ MEMMAP_SOCKET: %ld, ChannelDevice: %ld, MEMMAP_DIMM_DEVICE_INFO_STRUCT: %ld\n", + sizeof(MEMMAP_SOCKET), sizeof(struct ChannelDevice), + sizeof(MEMMAP_DIMM_DEVICE_INFO_STRUCT)); + printk(BIOS_DEBUG, "^^^ Element Offset: %ld\n", + offsetof(SYSTEM_MEMORY_MAP_HOB, Element)); + printk(BIOS_DEBUG, "^^^ Socket Offset: %ld\n", + offsetof(SYSTEM_MEMORY_MAP_HOB, Socket)); + printk(BIOS_DEBUG, "^^^ ChannelInfo Offset: %ld\n", + offsetof(MEMMAP_SOCKET, ChannelInfo)); + printk(BIOS_DEBUG, "^^^ DimmInfo Offset: %ld\n", + offsetof(struct ChannelDevice, DimmInfo)); + printk(BIOS_DEBUG, "^^^ DimmSize Offset: %ld\n", + offsetof(struct DimmDevice, DimmSize)); + + for (int s = 0; s < MAX_SOCKET; ++s) { + if (!hob->Socket[s].SocketEnabled) + continue; + for (int ch = 0; ch < MAX_CH; ++ch) { + if (!hob->Socket[s].ChannelInfo[ch].Enabled) + continue; + for (int dimm = 0; dimm < MAX_DIMM; ++dimm) { + if (!hob->Socket[s].ChannelInfo[ch].DimmInfo[dimm].Present) + continue; + printk(BIOS_DEBUG, + "\tsocket: %d, ch: %d, dimm: %d, enabled: %d, DimmSize: 0x%x\n", + s, ch, dimm, + hob->Socket[s].ChannelInfo[ch].DimmInfo[dimm].Enabled, + hob->Socket[s].ChannelInfo[ch].DimmInfo[dimm].DimmSize); + } + } + } + + printk(BIOS_DEBUG, "\tBiosFisVersion: 0x%x\n", hob->BiosFisVersion); + printk(BIOS_DEBUG, "\tMmiohBase: 0x%x\n", hob->MmiohBase); + + hexdump(hob, sizeof(*hob)); +} + +void soc_display_iio_universal_data_hob(const IIO_UDS *hob) +{ + printk(BIOS_DEBUG, "===================== IIO_UDS HOB DATA =====================\n"); + printk(BIOS_DEBUG, "hob: %p, structure size: 0x%lx\n", hob, sizeof(*hob)); + + printk(BIOS_DEBUG, "\t===================== SYSTEM STATUS =====================\n"); + printk(BIOS_DEBUG, "\tnumCpus: 0x%x\n", hob->SystemStatus.numCpus); + printk(BIOS_DEBUG, "\ttolmLimit: 0x%x\n", hob->SystemStatus.tolmLimit); + + printk(BIOS_DEBUG, "\t===================== PLATFORM DATA =====================\n"); + printk(BIOS_DEBUG, "\tPlatGlobalIoBase: 0x%x\n", hob->PlatformData.PlatGlobalIoBase); + printk(BIOS_DEBUG, "\tPlatGlobalIoLimit: 0x%x\n", hob->PlatformData.PlatGlobalIoLimit); + printk(BIOS_DEBUG, "\tPlatGlobalMmio32Base: 0x%x\n", + hob->PlatformData.PlatGlobalMmio32Base); + printk(BIOS_DEBUG, "\tPlatGlobalMmio32Limit: 0x%x\n", + hob->PlatformData.PlatGlobalMmio32Limit); + printk(BIOS_DEBUG, "\tnumofIIO: 0x%x\n", hob->PlatformData.numofIIO); + printk(BIOS_DEBUG, "\tMaxBusNumber: 0x%x\n", hob->PlatformData.MaxBusNumber); + printk(BIOS_DEBUG, "\tIoGranularity: 0x%x\n", hob->PlatformData.IoGranularity); + printk(BIOS_DEBUG, "\tMmiolGranularity: 0x%x\n", hob->PlatformData.MmiolGranularity); + printk(BIOS_DEBUG, "\tMmiohGranularity: 0x%llx\n", + hob->PlatformData.MmiohGranularity); + + for (uint8_t s = 0; s < MAX_SOCKET; ++s) { + printk(BIOS_DEBUG, "\t============ Socket %d Info ================\n", s); + printk(BIOS_DEBUG, "\tValid: 0x%x\n", hob->PlatformData.IIO_resource[s].Valid); + printk(BIOS_DEBUG, "\tSocketID: 0x%x\n", + hob->PlatformData.IIO_resource[s].SocketID); + printk(BIOS_DEBUG, "\tBusBase: 0x%x\n", + hob->PlatformData.IIO_resource[s].BusBase); + printk(BIOS_DEBUG, "\tBusLimit: 0x%x\n", + hob->PlatformData.IIO_resource[s].BusLimit); + printk(BIOS_DEBUG, "\tPciResourceIoBase: 0x%x\n", + hob->PlatformData.IIO_resource[s].PciResourceIoBase); + printk(BIOS_DEBUG, "\tPciResourceIoLimit: 0x%x\n", + hob->PlatformData.IIO_resource[s].PciResourceIoLimit); + printk(BIOS_DEBUG, "\tIoApicBase: 0x%x\n", + hob->PlatformData.IIO_resource[s].IoApicBase); + printk(BIOS_DEBUG, "\tIoApicLimit: 0x%x\n", + hob->PlatformData.IIO_resource[s].IoApicLimit); + printk(BIOS_DEBUG, "\tMmio32Base: 0x%x\n", + hob->PlatformData.IIO_resource[s].Mmio32Base); + printk(BIOS_DEBUG, "\tMmio32Limit: 0x%x\n", + hob->PlatformData.IIO_resource[s].Mmio32Limit); + printk(BIOS_DEBUG, "\tMmio64Base: 0x%llx\n", + hob->PlatformData.IIO_resource[s].Mmio64Base); + printk(BIOS_DEBUG, "\tMmio64Limit: 0x%llx\n", + hob->PlatformData.IIO_resource[s].Mmio64Limit); + + printk(BIOS_DEBUG, "\t============ Stack Info ================\n"); + for (int x = 0; x < MAX_LOGIC_IIO_STACK; ++x) { + const STACK_RES *ri = &hob->PlatformData.IIO_resource[s].StackRes[x]; + printk(BIOS_DEBUG, "\t\t========== Stack %d ===============\n", x); + printk(BIOS_DEBUG, "\t\tPersonality: 0x%x\n", ri->Personality); + printk(BIOS_DEBUG, "\t\tBusBase: 0x%x\n", ri->BusBase); + printk(BIOS_DEBUG, "\t\tBusLimit: 0x%x\n", ri->BusLimit); + printk(BIOS_DEBUG, "\t\tPciResourceIoBase: 0x%x\n", + ri->PciResourceIoBase); + printk(BIOS_DEBUG, "\t\tPciResourceIoLimit: 0x%x\n", + ri->PciResourceIoLimit); + printk(BIOS_DEBUG, "\t\tIoApicBase: 0x%x\n", ri->IoApicBase); + printk(BIOS_DEBUG, "\t\tIoApicLimit: 0x%x\n", ri->IoApicLimit); + printk(BIOS_DEBUG, "\t\tMmio32Base: 0x%x\n", ri->Mmio32Base); + printk(BIOS_DEBUG, "\t\tMmio32Limit: 0x%x\n", ri->Mmio32Limit); + printk(BIOS_DEBUG, "\t\tPciResourceMem32Base: 0x%x\n", + ri->PciResourceMem32Base); + printk(BIOS_DEBUG, "\t\tPciResourceMem32Limit: 0x%x\n", + ri->PciResourceMem32Limit); + printk(BIOS_DEBUG, "\t\tMmio64Base: 0x%llx\n", ri->Mmio64Base); + printk(BIOS_DEBUG, "\t\tMmio64Limit: 0x%llx\n", ri->Mmio64Limit); + printk(BIOS_DEBUG, "\t\tPciResourceMem64Base: 0x%llx\n", + ri->PciResourceMem64Base); + printk(BIOS_DEBUG, "\t\tPciResourceMem64Limit: 0x%llx\n", + ri->PciResourceMem64Limit); + printk(BIOS_DEBUG, "\t\tVtdBarAddress: 0x%x\n", ri->VtdBarAddress); + } + } + + hexdump(hob, sizeof(*hob)); +} + +static void soc_display_cxlnode_hob(const CXL_NODE_SOCKET *hob) +{ + printk(BIOS_DEBUG, "===================== CXLNODE HOB DATA =====================\n"); + printk(BIOS_DEBUG, "hob: %p, structure size: 0x%lx\n", hob, sizeof(*hob) * MAX_SOCKET); + + for (uint8_t skt_id = 0; skt_id < MAX_SOCKET; skt_id++) { + printk(BIOS_DEBUG, "\tSocket:%d, CxlNodeCount: 0x%x\n", skt_id, + hob[skt_id].CxlNodeCount); + for (uint8_t i = 0; i < hob[skt_id].CxlNodeCount; ++i) { + printk(BIOS_DEBUG, "\tCxlNodeInfo[%d]:\n", i); + const CXL_NODE_INFO node = hob[skt_id].CxlNodeInfo[i]; + printk(BIOS_DEBUG, "\t\tSerialNumber: 0x%llx\n", node.SerialNumber); + printk(BIOS_DEBUG, "\t\tVendorId: 0x%x\n", node.VendorId); + printk(BIOS_DEBUG, "\t\tAttr: 0x%x\n", node.Attr); + printk(BIOS_DEBUG, "\t\tAddress: 0x%x\n", node.Address); + printk(BIOS_DEBUG, "\t\tSize: 0x%x\n", node.Size); + printk(BIOS_DEBUG, "\t\tWays: 0x%x\n", node.Ways); + printk(BIOS_DEBUG, "\t\tSocketBitmap: 0x%x\n", node.SocketBitmap); + printk(BIOS_DEBUG, + "\t\tPerfData format: RdLatency(0.1ns), WrLatency(0.1ns), RdBW(100MB/s), WrBW(100MB/s)\n"); + printk(BIOS_DEBUG, + "\t\tEfiMemType and PerfData are invalid for SPR-SP.\n"); + } + } + + hexdump(hob, sizeof(*hob) * MAX_SOCKET); +} + +void soc_display_hob(const struct hob_header *hob) +{ + uint8_t *guid; + + if (hob->type != HOB_TYPE_GUID_EXTENSION) + return; + + guid = (uint8_t *)fsp_hob_header_to_resource(hob); + + if (fsp_guid_compare(guid, fsp_hob_iio_uds_guid)) + soc_display_iio_universal_data_hob((const IIO_UDS *)(guid + 16)); + else if (fsp_guid_compare(guid, fsp_hob_memmap_guid)) + soc_display_memmap_hob((const struct SystemMemoryMapHob **)(guid + 16)); + else if (fsp_guid_compare(guid, fsp_hob_cxlnode_guid)) + soc_display_cxlnode_hob((const CXL_NODE_SOCKET *)(guid + 16)); +} diff --git a/src/soc/intel/xeon_sp/icx/include/soc/pci_devs.h b/src/soc/intel/xeon_sp/icx/include/soc/pci_devs.h new file mode 100644 index 0000000..6ccc5d9 --- /dev/null +++ b/src/soc/intel/xeon_sp/icx/include/soc/pci_devs.h @@ -0,0 +1,89 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef _SOC_PCI_DEVS_H_ +#define _SOC_PCI_DEVS_H_ + +#include <device/pci_def.h> +#include <device/pci_type.h> +#include <soc/pch_pci_devs.h> +#include <types.h> + +/* UBOX Registers [U(1), D:0, F:1] */ +#define SMM_FEATURE_CONTROL 0x8c +#define SMM_CODE_CHK_EN BIT(2) +#define SMM_FEATURE_CONTROL_LOCK BIT(0) +#define UBOX_DFX_DEVID 0x3451 + +/* CHA registers [B:31, D:29, F:0/F:1] + * SAD is the previous xeon_sp register name. Keep defines for shared code. + */ +#define CHA_DEV 29 + +#define SAD_ALL_DEV CHA_DEV +#define SAD_ALL_FUNC 0 +#define SAD_ALL_PAM0123_CSR 0x80 +#define PAM_LOCK BIT(0) +#define SAD_ALL_PAM456_CSR 0x84 +#define SAD_ALL_DEVID 0x344f + +/* PCU [B:31, D:30, F:0] */ +#define PCU_IIO_STACK 1 +#define PCU_CR0_DEVID 0x3458 +/* PCU [B:31, D:30, F:1] */ +#define PCU_CR1_DEVID 0x3459 +/* PCU [B:31, D:30, F:2] */ +#define PCU_CR2_DEVID 0x345a +/* PCU [B:31, D:30, F:3] */ +#define PCU_CR3_DEVID 0x345b +/* PCU [B:31, D:30, F:6] */ +#define PCU_CR6_DEVID 0x345e + +/* Memory Map/VTD Device Functions + * These are available in each IIO stack at B:D.F = B:0.0 + */ + +#define VTD_TOLM_CSR 0xd0 +#define VTD_TSEG_BASE_CSR 0xa8 +#define VTD_TSEG_LIMIT_CSR 0xac +#define VTD_EXT_CAP_LOW 0x10 +#define VTD_MMCFG_BASE_CSR 0x90 +#define VTD_MMCFG_LIMIT_CSR 0x98 +#define VTD_TOHM_CSR 0xc8 +#define VTD_MMIOL_CSR 0xd8 +#define VTD_NCMEM_BASE_CSR 0xe0 +#define VTD_NCMEM_LIMIT_CSR 0xe8 +#define VTD_BAR_CSR 0x180 +#define VTD_LTDPR 0x290 + +#define MMAP_VTD_CFG_REG_DEVID 0x09a2 +#define MMAP_VTD_STACK_CFG_REG_DEVID 0x09a2 +#define VTD_DEV_NUM 0x0 +#define VTD_FUNC_NUM 0x0 + +#if !defined(__SIMPLE_DEVICE__) +#define VTD_DEV(bus) pcidev_path_on_bus((bus), PCI_DEVFN(VTD_DEV_NUM, VTD_FUNC_NUM)) +#else +#define VTD_DEV(bus) PCI_DEV((bus), VTD_DEV_NUM, VTD_FUNC_NUM) +#endif + +/* Root port Registers */ + +#define DMIRCBAR 0x50 +#define DMI3_DEVID 0x3348 +#define PCIE_ROOTCTL 0x5c +#define ERRINJCON 0x198 + +// IIO DFX Global D7F7 registers +#define IIO_DFX_TSWCTL0 0x30c +#define IIO_DFX_LCK_CTL 0x504 + +/* MSM registers */ +#define MSM_BUS 0xF2 +#define MSM_DEV 3 +#define MSM_FUN 0 +#define MSM_FUN_PMON 1 +#define CRASHLOG_CTL 0x1B8 +#define BIOS_CRASHLOG_CTL 0x158 +#define CRASHLOG_CTL_DIS BIT(2) + +#endif /* _SOC_PCI_DEVS_H_ */ diff --git a/src/soc/intel/xeon_sp/icx/include/soc/soc_msr.h b/src/soc/intel/xeon_sp/icx/include/soc/soc_msr.h new file mode 100644 index 0000000..3ebb4d4 --- /dev/null +++ b/src/soc/intel/xeon_sp/icx/include/soc/soc_msr.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#ifndef _SOC_MSR_SPR_H_ +#define _SOC_MSR_SPR_H_ + +/* MSR_PKG_CST_CONFIG_CONTROL */ +#define PKG_CSTATE_NO_LIMIT (0x8 << PKG_CSTATE_LIMIT_SHIFT) + +/* MSR_POWER_CTL */ +#define RESERVED1_SHIFT 2 +#define PWR_PERF_PLTFRM_OVR_SHIFT 18 +#define PWR_PERF_PLTFRM_OVR (1 << PWR_PERF_PLTFRM_OVR_SHIFT) +#define EE_TURBO_DISABLE_SHIFT 19 +#define EE_TURBO_DISABLE (1 << EE_TURBO_DISABLE_SHIFT) +#define RTH_DISABLE_SHIFT 20 +#define RTH_DISABLE (1 << RTH_DISABLE_SHIFT) +#define PROCHOT_OUTPUT_DISABLE_SHIFT 21 +#define PROCHOT_OUTPUT_DISABLE (1 << PROCHOT_OUTPUT_DISABLE_SHIFT) +#define PROCHOT_RESPONSE_SHIFT 22 +#define PROCHOT_RESPONSE (1 << PROCHOT_RESPONSE_SHIFT) +#define PROCHOT_LOCK_SHIFT 23 +#define PROCHOT_LOCK (1 << PROCHOT_LOCK_SHIFT) +#define VR_THERM_ALERT_DISABLE_SHIFT 24 +#define VR_THERM_ALERT_DISABLE (1 << VR_THERM_ALERT_DISABLE_SHIFT) +#define DISABLE_RING_EE_SHIFT 25 +#define DISABLE_RING_EE (1 << DISABLE_RING_EE_SHIFT) +#define RESERVED2_SHIFT 26 +#define DISABLE_AUTONOMOUS_SHIFT 28 +#define DISABLE_AUTONOMOUS (1 << DISABLE_AUTONOMOUS_SHIFT) +#define RESERVED3_SHIFT 29 +#define CSTATE_PREWAKE_DISABLE_SHIFT 30 +#define CSTATE_PREWAKE_DISABLE (1 << CSTATE_PREWAKE_DISABLE_SHIFT) + +#define MSR_BIOS_DONE 0x151 +#define XEON_SP_ENABLE_IA_UNTRUSTED BIT(0) + +#define MSR_FLEX_RATIO 0x194 +#define MSR_FLEX_RATIO_OC_LOCK BIT(20) + +/* B1:D30:F0 offset 0xe8 on previous generations */ +#define PACKAGE_RAPL_LIMIT 0x610 + +#define MSR_DRAM_PLANE_POWER_LIMIT 0x618 +#define MSR_HI_PP_PWR_LIM_LOCK BIT(31) /* used as msr.hi */ + +#endif /* _SOC_MSR_SPR_H_ */ diff --git a/src/soc/intel/xeon_sp/icx/include/soc/soc_util.h b/src/soc/intel/xeon_sp/icx/include/soc/soc_util.h new file mode 100644 index 0000000..6a15871 --- /dev/null +++ b/src/soc/intel/xeon_sp/icx/include/soc/soc_util.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef _SOC_UTIL_H_ +#define _SOC_UTIL_H_ + +#include <hob_iiouds.h> +#include <hob_memmap.h> +#include <hob_cxlnode.h> +#include <hob_enhancedwarningloglib.h> + +#define xSTACK_RES STACK_RES +#define xIIO_RESOURCE_INSTANCE IIO_RESOURCE_INSTANCE + +/* + * Address of the MRC status byte in CMOS. Should be reserved + * in mainboards' cmos.layout and not covered by checksum. + */ +#define CMOS_OFFSET_MRC_STATUS 0x47 + +#if CONFIG(USE_OPTION_TABLE) +#include "option_table.h" +#if CMOS_VSTART_mrc_status != CMOS_OFFSET_MRC_STATUS * 8 +#error "CMOS start for SPR-SP MRC status byte is not correct, check your cmos.layout" +#endif +#if CMOS_VLEN_mrc_status != 8 +#error "CMOS length for SPR-SP MRC status byte is not correct, check your cmos.layout" +#endif +#endif + +/* Equals to MAX_IIO_PORTS_PER_SOCKET - 2 * 8, because IOU5 and IOU6 are not used per socket. */ +#define IIO_PORT_SETTINGS (1 + 5 * 8) + +const struct SystemMemoryMapHob *get_system_memory_map(void); +const struct SystemMemoryMapElement *get_system_memory_map_elment(uint8_t *num); + +void soc_display_iio_universal_data_hob(const IIO_UDS *hob); +void soc_display_memmap_hob(const struct SystemMemoryMapHob **hob_addr); +uint8_t get_cxl_node_count(void); + +const EWL_PRIVATE_DATA *get_ewl_hob(void); + +void soc_set_mrc_cold_boot_flag(bool cold_boot_required); + +#endif /* _SOC_UTIL_H_ */ diff --git a/src/soc/intel/xeon_sp/icx/ramstage.c b/src/soc/intel/xeon_sp/icx/ramstage.c new file mode 100644 index 0000000..e1ede29 --- /dev/null +++ b/src/soc/intel/xeon_sp/icx/ramstage.c @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <cpu/x86/smm.h> +#include <drivers/ocp/include/vpd.h> +#include <soc/ramstage.h> +#include <soc/soc_util.h> +#include <soc/util.h> +#include <soc/msr.h> + +unsigned int smbios_cpu_get_voltage(void) +{ + return 16; /* Per SMBIOS spec, voltage times 10 */ +} + +unsigned int smbios_cpu_get_current_speed_mhz(void) +{ + msr_t msr; + msr = rdmsr(MSR_PLATFORM_INFO); + return ((msr.lo >> 8) & 0xff) * CONFIG_CPU_BCLK_MHZ; +} + +__weak void mainboard_override_fsp_gpio(void) +{ + /* Default weak implementation */ +} diff --git a/src/soc/intel/xeon_sp/icx/reset.c b/src/soc/intel/xeon_sp/icx/reset.c new file mode 100644 index 0000000..bc5815a --- /dev/null +++ b/src/soc/intel/xeon_sp/icx/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/xeon_sp/icx/romstage.c b/src/soc/intel/xeon_sp/icx/romstage.c new file mode 100644 index 0000000..087bacd --- /dev/null +++ b/src/soc/intel/xeon_sp/icx/romstage.c @@ -0,0 +1,160 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#include <arch/breakpoint.h> + +#include <assert.h> +#include <cpu/cpu.h> +#include <cpu/intel/cpu_ids.h> +#include <arch/romstage.h> +#include <console/console.h> +#include <cbmem.h> +#include <drivers/vpd/vpd.h> +#include <drivers/ocp/include/vpd.h> +#include <security/intel/txt/txt.h> +#include <fsp/api.h> +#include <fsp/util.h> +#include <hob_iiouds.h> +#include <hob_memmap.h> +#include <spd.h> +#include <soc/chip_common.h> +#include <soc/romstage.h> +#include <soc/pci_devs.h> +#include <soc/soc_pch.h> +#include <static.h> +#include <string.h> +#include <soc/config.h> +#include <soc/soc_util.h> +#include <soc/util.h> +#include <soc/ddr.h> +#include <IioPcieConfigUpd.h> + +#include "chip.h" + +void __weak mainboard_memory_init_params(FSPM_UPD *mupd) +{ + /* Default weak implementation */ +} + +void platform_fsp_memory_init_params_cb(FSPM_UPD *mupd, uint32_t version) +{ + FSP_M_CONFIG *m_cfg = &mupd->FspmConfig; + const config_t *config = config_of_soc(); + + m_cfg->DebugPrintLevel = 0xF; + + m_cfg->DirectoryModeEn = 0x2; + const u8 KtiFpgaEnable[] = {0x2, 0x2, 0x2, 0x2, 0x1, 0x1, 0x1, 0x1}; + memcpy(m_cfg->KtiFpgaEnable, KtiFpgaEnable, sizeof(m_cfg->KtiFpgaEnable)); + + m_cfg->TscSyncEn = 0x1; + + m_cfg->mmiohBase = 0x2000; + m_cfg->mmiohSize = 0x3; + + /* + * By default FSP will set MMCFG size to 256 buses on 1S and 2S platforms + * and 512 buses on 4S platforms. 512 buses are implemented by using multiple + * PCI segment groups and is likely incompatible with legacy software stacks. + */ + switch (CONFIG_ECAM_MMCONF_BUS_NUMBER) { + case 2048: + m_cfg->mmCfgSize = 5; + break; + case 1024: + m_cfg->mmCfgSize = 4; + break; + case 512: + m_cfg->mmCfgSize = 3; + break; + case 256: + m_cfg->mmCfgSize = 2; + break; + case 128: + m_cfg->mmCfgSize = 1; + break; + case 64: + m_cfg->mmCfgSize = 0; + break; + default: + printk(BIOS_ERR, "%s: Unsupported ECAM_MMCONF_BUS_NUMBER = %d\n", + __func__, CONFIG_ECAM_MMCONF_BUS_NUMBER); + } + + m_cfg->BoardTypeBitmask = 0x11111133; + m_cfg->BoardId = 0xff; /* Unknown */ + + /* + * FSP BUG: Intel never validated FSP in API mode with default settings. + * FSP bails out when KTI runs at full speed. + * WORKAROUND: Downgrade KTI link speed to CPX defaults. + */ + m_cfg->KtiLinkSpeed = 2; + m_cfg->KtiLinkSpeedMode = 0; + m_cfg->KtiLinkL0pEn = 1; + m_cfg->KtiLinkL1En = 1; + + /* + * Let coreboot configure LAPIC based on Kconfig. + * coreboot currently can only switch from XAPIC to X2APIC, + * so always select XAPIC mode here. + */ + m_cfg->X2apic = 0; + m_cfg->MeUmaEnable = 1; + + m_cfg->serialDebugMsgLvl = 0x3; + m_cfg->SerialIoUartDebugEnable = CONFIG(CONSOLE_SERIAL); + m_cfg->SerialIoUartDebugIoBase = CONFIG_TTYS0_BASE; + + m_cfg->VtdSupport = config->vtd_support; + + mainboard_memory_init_params(mupd); + + /* + * FSP BUG: + * Unused PCI root ports must be hidden and usually FSP does it based on bifurcation + * settings. FSP in API doesn't do anything, so unused ports stay visible. + * When the CPU tries to access visible, but non working root ports, it hangs forever. + * WORKAROUND: Disable ALL PCIe ports! + */ + m_cfg->PEXPHIDE = 1; + m_cfg->IIOPcieRootPortEnable = 0; + m_cfg->IioPcieConfigTablePtr = 0; + m_cfg->IioPcieConfigTableNumber = 0; +} + +uint8_t get_error_correction_type(const uint8_t RasModesEnabled) +{ + switch (RasModesEnabled) { + case CH_INDEPENDENT: + return MEMORY_ARRAY_ECC_SINGLE_BIT; + case FULL_MIRROR_1LM: + case PARTIAL_MIRROR_1LM: + case FULL_MIRROR_2LM: + case PARTIAL_MIRROR_2LM: + return MEMORY_ARRAY_ECC_MULTI_BIT; + case RK_SPARE: + return MEMORY_ARRAY_ECC_SINGLE_BIT; + case CH_LOCKSTEP: + return MEMORY_ARRAY_ECC_SINGLE_BIT; + default: + return MEMORY_ARRAY_ECC_MULTI_BIT; + } +} + +uint8_t get_max_dimm_count(void) +{ + return MAX_DIMM; +} + +uint8_t get_dram_type(const struct SystemMemoryMapHob *hob) +{ + if (hob->DramType == SPD_MEMORY_TYPE_DDR5_SDRAM) + return MEMORY_TYPE_DDR5; + + return MEMORY_TYPE_DDR4; +} + +uint32_t get_max_capacity_mib(void) +{ + /* According to EDS doc#611488, it's 4 TB per processor. */ + return 4 * MiB * CONFIG_MAX_SOCKET; +} diff --git a/src/soc/intel/xeon_sp/icx/soc_acpi.c b/src/soc/intel/xeon_sp/icx/soc_acpi.c new file mode 100644 index 0000000..88b1fa4 --- /dev/null +++ b/src/soc/intel/xeon_sp/icx/soc_acpi.c @@ -0,0 +1,196 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <acpi/acpigen.h> +#include <arch/smp/mpspec.h> +#include <arch/vga.h> +#include <cpu/intel/turbo.h> +#include <device/mmio.h> +#include <device/pci.h> +#include <intelblocks/acpi.h> +#include <intelblocks/cpulib.h> +#include <intelblocks/pmclib.h> +#include <soc/acpi.h> +#include <soc/iomap.h> +#include <soc/numa.h> +#include <soc/msr.h> +#include <soc/pci_devs.h> +#include <soc/pm.h> +#include <soc/soc_util.h> +#include <soc/util.h> +#include <hob_iiouds.h> + +int soc_madt_sci_irq_polarity(int sci) +{ + if (sci >= 20) + return MP_IRQ_POLARITY_LOW; + else + return MP_IRQ_POLARITY_HIGH; +} + +uint32_t soc_read_sci_irq_select(void) +{ + /* PMC controller is hidden - hence PWRMBASE can't be accessbile using PCI cfg space */ + uintptr_t pmc_bar = PCH_PWRM_BASE_ADDRESS; + return read32((void *)pmc_bar + PMC_ACPI_CNT); +} + +void soc_fill_fadt(acpi_fadt_t *fadt) +{ + const uint16_t pmbase = ACPI_BASE_ADDRESS; + + fadt->FADT_MinorVersion = 1; + fadt->pm_tmr_blk = pmbase + PM1_TMR; + fadt->pm_tmr_len = 4; + /* Clear flags set by common/block/acpi/acpi.c acpi_fill_fadt() */ + fadt->flags &= ~ACPI_FADT_SEALED_CASE; + + fadt->preferred_pm_profile = PM_ENTERPRISE_SERVER; + fadt->pm2_cnt_blk = pmbase + PM2_CNT; + fadt->pm2_cnt_len = 1; + + /* PM Extended Registers */ + fill_fadt_extended_pm_io(fadt); +} + +/* TODO: See if we can use the common generate_p_state_entries */ +void soc_power_states_generation(int core, int cores_per_package) +{ + int ratio_min, ratio_max, ratio_turbo, ratio_step; + int coord_type, power_max, power_unit, num_entries; + int ratio, power, clock, clock_max; + msr_t msr; + + /* Determine P-state coordination type from MISC_PWR_MGMT[0] */ + msr = rdmsr(MSR_MISC_PWR_MGMT); + if (msr.lo & MISC_PWR_MGMT_EIST_HW_DIS) + coord_type = SW_ANY; + else + coord_type = HW_ALL; + + /* Get bus ratio limits and calculate clock speeds */ + msr = rdmsr(MSR_PLATFORM_INFO); + ratio_min = (msr.hi >> (40 - 32)) & 0xff; /* Max Efficiency Ratio */ + + /* Determine if this CPU has configurable TDP */ + if (cpu_config_tdp_levels()) { + /* Set max ratio to nominal TDP ratio */ + msr = rdmsr(MSR_CONFIG_TDP_NOMINAL); + ratio_max = msr.lo & 0xff; + } else { + /* Max Non-Turbo Ratio */ + ratio_max = (msr.lo >> 8) & 0xff; + } + clock_max = ratio_max * CONFIG_CPU_BCLK_MHZ; + + /* Calculate CPU TDP in mW */ + msr = rdmsr(MSR_PKG_POWER_SKU_UNIT); + power_unit = 2 << ((msr.lo & 0xf) - 1); + msr = rdmsr(MSR_PKG_POWER_SKU); + power_max = ((msr.lo & 0x7fff) / power_unit) * 1000; + + /* Write _PCT indicating use of FFixedHW */ + acpigen_write_empty_PCT(); + + /* Write _PPC with no limit on supported P-state */ + acpigen_write_PPC_NVS(); + + /* Write PSD indicating configured coordination type */ + acpigen_write_PSD_package(core, 1, coord_type); + + /* Add P-state entries in _PSS table */ + acpigen_write_name("_PSS"); + + /* Determine ratio points */ + ratio_step = PSS_RATIO_STEP; + num_entries = ((ratio_max - ratio_min) / ratio_step) + 1; + if (num_entries > PSS_MAX_ENTRIES) { + ratio_step += 1; + num_entries = ((ratio_max - ratio_min) / ratio_step) + 1; + } + + /* P[T] is Turbo state if enabled */ + if (get_turbo_state() == TURBO_ENABLED) { + /* _PSS package count including Turbo */ + acpigen_write_package(num_entries + 2); + + msr = rdmsr(MSR_TURBO_RATIO_LIMIT); + ratio_turbo = msr.lo & 0xff; + + /* Add entry for Turbo ratio */ + acpigen_write_PSS_package(clock_max + 1, /* MHz */ + power_max, /* mW */ + PSS_LATENCY_TRANSITION, /* lat1 */ + PSS_LATENCY_BUSMASTER, /* lat2 */ + ratio_turbo << 8, /* control */ + ratio_turbo << 8); /* status */ + } else { + /* _PSS package count without Turbo */ + acpigen_write_package(num_entries + 1); + } + + /* First regular entry is max non-turbo ratio */ + acpigen_write_PSS_package(clock_max, /* MHz */ + power_max, /* mW */ + PSS_LATENCY_TRANSITION, /* lat1 */ + PSS_LATENCY_BUSMASTER, /* lat2 */ + ratio_max << 8, /* control */ + ratio_max << 8); /* status */ + + /* Generate the remaining entries */ + for (ratio = ratio_min + ((num_entries - 1) * ratio_step); ratio >= ratio_min; + ratio -= ratio_step) { + /* Calculate power at this ratio */ + power = common_calculate_power_ratio(power_max, ratio_max, ratio); + clock = ratio * CONFIG_CPU_BCLK_MHZ; + // clock = 1; + acpigen_write_PSS_package(clock, /* MHz */ + power, /* mW */ + PSS_LATENCY_TRANSITION, /* lat1 */ + PSS_LATENCY_BUSMASTER, /* lat2 */ + ratio << 8, /* control */ + ratio << 8); /* status */ + } + + /* Fix package length */ + acpigen_pop_len(); +} + +unsigned long acpi_fill_cedt(unsigned long current) +{ + const IIO_UDS *hob = get_iio_uds(); + union uid { + uint32_t data; + struct { + uint8_t byte0; + uint8_t byte1; + uint8_t byte2; + uint8_t byte3; + }; + } cxl_uid; + u32 cxl_ver; + u64 base; + + cxl_uid.byte0 = 'C'; + cxl_uid.byte1 = 'X'; + /* Loop through all sockets and stacks, add CHBS for each CXL IIO stack */ + for (uint8_t socket = 0, iio = 0; iio < hob->PlatformData.numofIIO; ++socket) { + if (!soc_cpu_is_enabled(socket)) + continue; + iio++; + for (int x = 0; x < MAX_LOGIC_IIO_STACK; ++x) { + const STACK_RES *ri; + ri = &hob->PlatformData.IIO_resource[socket].StackRes[x]; + if (!is_iio_cxl_stack_res(ri)) + continue; + /* uid needs to match with ACPI CXL device ID, eg. acpi/iiostack.asl */ + cxl_uid.byte2 = socket + '0'; + cxl_uid.byte3 = x + '0'; + cxl_ver = ACPI_CEDT_CHBS_CXL_VER_1_1; + base = ri->Mmio32Base; /* DP RCRB base */ + current += acpi_create_cedt_chbs((acpi_cedt_chbs_t *)current, + cxl_uid.data, cxl_ver, base); + } + } + + return current; +} diff --git a/src/soc/intel/xeon_sp/icx/soc_util.c b/src/soc/intel/xeon_sp/icx/soc_util.c new file mode 100644 index 0000000..518764b --- /dev/null +++ b/src/soc/intel/xeon_sp/icx/soc_util.c @@ -0,0 +1,115 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <assert.h> +#include <device/device.h> +#include <device/pci.h> +#include <hob_cxlnode.h> +#include <intelblocks/cpulib.h> +#include <soc/msr.h> +#include <soc/numa.h> +#include <soc/pci_devs.h> +#include <soc/soc_util.h> +#include <soc/util.h> +#include <pc80/mc146818rtc.h> + +const EWL_PRIVATE_DATA *get_ewl_hob(void) +{ + size_t hob_size; + static const EWL_PRIVATE_DATA *hob; + const uint8_t ewl_id_hob_guid[16] = FSP_HOB_EWLID_GUID; + + if (hob != NULL) + return hob; + + hob = fsp_find_extension_hob_by_guid(ewl_id_hob_guid, &hob_size); + assert(hob != NULL && hob_size != 0); + return hob; +} + +const struct SystemMemoryMapHob *get_system_memory_map(void) +{ + size_t hob_size; + const uint8_t mem_hob_guid[16] = FSP_SYSTEM_MEMORYMAP_HOB_GUID; + const struct SystemMemoryMapHob **memmap_addr; + + memmap_addr = (const struct SystemMemoryMapHob **)fsp_find_extension_hob_by_guid( + mem_hob_guid, &hob_size); + /* hob_size is the size of the 8-byte address not the hob data */ + assert(memmap_addr != NULL && hob_size != 0); + /* assert the pointer to the hob is not NULL */ + assert(*memmap_addr != NULL); + + return *memmap_addr; +} + +const struct SystemMemoryMapElement *get_system_memory_map_elment(uint8_t *num) +{ + const struct SystemMemoryMapHob *hob = get_system_memory_map(); + if (!hob) + return NULL; + + *num = hob->numberEntries; + return hob->Element; +} + +bool is_pcie_iio_stack_res(const STACK_RES *res) +{ + return res->Personality == TYPE_UBOX_IIO; +} + +bool is_ubox_stack_res(const STACK_RES *res) +{ + return res->Personality == TYPE_UBOX; +} + +uint8_t get_cxl_node_count(void) +{ + return 0; +} + +void bios_done_msr(void *unused) +{ + msr_t msr = rdmsr(MSR_BIOS_DONE); + if (!(msr.lo & XEON_SP_ENABLE_IA_UNTRUSTED)) { /* if already locked skip update */ + msr.lo |= XEON_SP_ENABLE_IA_UNTRUSTED; + wrmsr(MSR_BIOS_DONE, msr); + } +} + +void soc_set_mrc_cold_boot_flag(bool cold_boot_required) +{ + uint8_t mrc_status = cmos_read(CMOS_OFFSET_MRC_STATUS); + uint8_t new_mrc_status = (mrc_status & 0xfe) | cold_boot_required; + printk(BIOS_SPEW, "MRC status: 0x%02x want 0x%02x\n", mrc_status, new_mrc_status); + if (new_mrc_status != mrc_status) + cmos_write(new_mrc_status, CMOS_OFFSET_MRC_STATUS); +} + +bool is_memtype_reserved(uint16_t mem_type) +{ + return !!(mem_type & MEM_TYPE_RESERVED); +} + +bool is_memtype_non_volatile(uint16_t mem_type) +{ + return !(mem_type & MEMTYPE_VOLATILE_MASK); +} + +bool is_memtype_processor_attached(uint16_t mem_type) +{ + return true; +} + +unsigned int get_prmrr_count(void) +{ + return 0x7; +} + +bool get_mmio_high_base_size(resource_t *base, resource_t *size) +{ + const IIO_UDS *hob = get_iio_uds(); + *base = hob->PlatformData.PlatGlobalMmio64Base; + *size = hob->PlatformData.PlatGlobalMmio64Limit - (*base) + 1; + + return true; +} diff --git a/src/soc/intel/xeon_sp/icx/upd_display.c b/src/soc/intel/xeon_sp/icx/upd_display.c new file mode 100644 index 0000000..ab23fcb --- /dev/null +++ b/src/soc/intel/xeon_sp/icx/upd_display.c @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <console/console.h> +#include <fsp/util.h> +#include <lib.h> + +#define DUMP_UPD(old, new, field) \ + fsp_display_upd_value(#field, sizeof(old->field), old->field, new->field) + +/* Display the UPD parameters for MemoryInit */ +void soc_display_fspm_upd_params(const FSPM_UPD *fspm_old_upd, const FSPM_UPD *fspm_new_upd) +{ + const FSP_M_CONFIG *new; + const FSP_M_CONFIG *old; + + old = &fspm_old_upd->FspmConfig; + new = &fspm_new_upd->FspmConfig; + + printk(BIOS_DEBUG, "UPD values for MemoryInit:\n"); + DUMP_UPD(old, new, DebugPrintLevel); + + printk(BIOS_DEBUG, " Dump of original MemoryInit UPD:\n"); + hexdump(fspm_old_upd, sizeof(*fspm_old_upd)); + + printk(BIOS_DEBUG, " Dump of updated MemoryInit UPD:\n"); + hexdump(fspm_new_upd, sizeof(*fspm_new_upd)); +} + +/* Display the UPD parameters for SiliconInit */ +void soc_display_fsps_upd_params(const FSPS_UPD *fsps_old_upd, const FSPS_UPD *fsps_new_upd) +{ + printk(BIOS_DEBUG, "Dump of original UPD values for SiliconInit:\n"); + hexdump(fsps_old_upd, sizeof(*fsps_old_upd)); + printk(BIOS_DEBUG, "Dump of updated UPD values for SiliconInit:\n"); + hexdump(fsps_new_upd, sizeof(*fsps_new_upd)); +}