diff --git a/src/mainboard/prodrive/atlas/Kconfig b/src/mainboard/prodrive/atlas/Kconfig index b40e2b796b..cbd625cf4f 100644 --- a/src/mainboard/prodrive/atlas/Kconfig +++ b/src/mainboard/prodrive/atlas/Kconfig @@ -13,6 +13,7 @@ config BOARD_PRODRIVE_ATLAS_BASEBOARD select MEMORY_MAPPED_TPM select PCIEXP_SUPPORT_RESIZABLE_BARS select SOC_INTEL_ALDERLAKE_PCH_P + select DRIVERS_OPTION_CFR_ENABLED config BOARD_PRODRIVE_ATLAS select BOARD_PRODRIVE_ATLAS_BASEBOARD @@ -23,13 +24,6 @@ config ATLAS_ENABLE_SAGV bool "Enable SaGv" default n -config ATLAS_ENABLE_IBECC - bool "Enable IBECC" - help - Enables In Band Error Correction Code. It's only needed for endurance testing - and therefore not always required. - default n - config D3COLD_SUPPORT default n diff --git a/src/mainboard/prodrive/atlas/Makefile.mk b/src/mainboard/prodrive/atlas/Makefile.mk index b31f03a7fc..df7af1c0a1 100644 --- a/src/mainboard/prodrive/atlas/Makefile.mk +++ b/src/mainboard/prodrive/atlas/Makefile.mk @@ -8,6 +8,7 @@ bootblock-y += early_gpio.c romstage-y += romstage_fsp_params.c +ramstage-$(CONFIG_DRIVERS_OPTION_CFR) += cfr.c ramstage-y += gpio.c ramstage-y += mainboard.c ramstage-y += ramstage_fsp_params.c diff --git a/src/mainboard/prodrive/atlas/cfr.c b/src/mainboard/prodrive/atlas/cfr.c new file mode 100644 index 0000000000..f5700e2ba0 --- /dev/null +++ b/src/mainboard/prodrive/atlas/cfr.c @@ -0,0 +1,264 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "vpd.h" + +static void update_rt_perf(const struct sm_object *obj, struct sm_object *new) +{ + const bool rt_perf = get_emi_eeprom_vpd()->profile == ATLAS_PROF_REALTIME_PERFORMANCE; + + if (!rt_perf) + return; + + if (obj->kind == SM_OBJ_BOOL) { + new->sm_bool.flags = CFR_OPTFLAG_SUPPRESS; + new->sm_bool.default_value = false; + } else if (obj->kind == SM_OBJ_ENUM) { + new->sm_enum.flags = CFR_OPTFLAG_SUPPRESS; + new->sm_enum.default_value = 0; + } +} + +static void update_bad_profile(const struct sm_object *obj, struct sm_object *new) +{ + const bool pf_ok = get_emi_eeprom_vpd()->profile != 0; + + if (!pf_ok) + return; + new->sm_comment.flags |= CFR_OPTFLAG_SUPPRESS; +} + +static void update_serial(const struct sm_object *obj, struct sm_object *new) +{ + new->sm_varchar.default_value = get_emi_eeprom_vpd()->serial_number; +} + +static void update_part_number(const struct sm_object *obj, struct sm_object *new) +{ + new->sm_varchar.default_value = get_emi_eeprom_vpd()->part_number; +} + +static void update_profile(const struct sm_object *obj, struct sm_object *new) +{ + new->sm_number.default_value = get_emi_eeprom_vpd()->profile; +} + +/* TODO: Suppress option if carrier board is known to not have a RTC battery */ +static const struct sm_enum_value pwr_after_g3_values[] = { + { "Power off (S5)", MAINBOARD_POWER_STATE_OFF }, + { "Power on (S0)", MAINBOARD_POWER_STATE_ON }, + /* No support for previous/last power state */ + SM_ENUM_VALUE_END, +}; + +static const struct sm_object power_on_after_fail = SM_DECLARE_ENUM({ + .opt_name = "power_on_after_fail", + .ui_name = "Restore AC Power Loss", + .ui_helptext = "Specify what to do when power is re-applied " + "after a power loss. This option has no effect " + "on systems without a RTC battery.", + .default_value = CONFIG_MAINBOARD_POWER_FAILURE_STATE, + .values = pwr_after_g3_values, +}); + +static const struct sm_enum_value primary_display_values[] = { + { "Intel iGPU", 0 }, + { "CPU PEG dGPU", 1 }, + { "PCH PCIe dGPU", 2 }, + { "Auto", 3 }, + SM_ENUM_VALUE_END, +}; + +static const struct sm_object primary_display = SM_DECLARE_ENUM({ + .opt_name = "primary_display", + .ui_name = "Primary display device", + .ui_helptext = "Specify which display device to use as primary.", + .default_value = CONFIG(ONBOARD_VGA_IS_PRIMARY) ? 0 : 3, + .values = primary_display_values, +}); + +static const struct sm_enum_value pkg_c_state_limit_values[] = { + { "C0/C1", 0 }, + { "C2", 1 }, + { "C3", 2 }, + { "C6", 3 }, + { "C7", 4 }, + { "C7S", 5 }, + { "C8", 6 }, + { "C9", 7 }, + { "C10", 8 }, + { "Default", 254 }, + { "Auto", 255 }, + SM_ENUM_VALUE_END, +}; + +static const struct sm_object turbo_mode = SM_DECLARE_BOOL({ + .opt_name = "turbo_mode", + .ui_name = "Turbo Boost", + /* No help text */ + .default_value = true, +}); + +static const struct sm_object vmx = SM_DECLARE_BOOL({ + .opt_name = "vmx", + .ui_name = "Intel Virtualization Technology (VT-x)", + /* No help text */ + .default_value = false, +}); + +static const struct sm_object vtd = SM_DECLARE_BOOL({ + .opt_name = "vtd", + .ui_name = "Intel Virtualization Technology for Directed I/O (VT-d)", + /* No help text */ + .default_value = false, +}); + +static const struct sm_object ibecc = SM_DECLARE_BOOL({ + .opt_name = "ibecc", + .ui_name = "In-Band ECC", + .ui_helptext = "Specify whether In-Band error checking and " + "correction is to be enabled. Enabling this " + "option will reduce the amount of available " + "RAM because some memory is needed to store " + "ECC codes.", + .default_value = false, +}); + +static const struct sm_object serial_number = SM_DECLARE_VARCHAR({ + .flags = CFR_OPTFLAG_READONLY | CFR_OPTFLAG_VOLATILE, + .opt_name = "serial_number", + .ui_name = "Serial Number", +}, WITH_CALLBACK(update_serial)); + +static const struct sm_object part_number = SM_DECLARE_VARCHAR({ + .flags = CFR_OPTFLAG_READONLY | CFR_OPTFLAG_VOLATILE, + .opt_name = "part_number", + .ui_name = "Part Number", +}, WITH_CALLBACK(update_part_number)); + +static const struct sm_object bad_profile = SM_DECLARE_COMMENT({ + .flags = CFR_OPTFLAG_READONLY, + .ui_name = "WARNING: Profile code is invalid", +}, WITH_CALLBACK(update_bad_profile)); + +static const struct sm_object profile = SM_DECLARE_NUMBER({ + .flags = CFR_OPTFLAG_READONLY | CFR_OPTFLAG_VOLATILE, + .opt_name = "profile", + .ui_name = "Profile code", + .ui_helptext = "The profile code obtained from the EEPROM", +}, WITH_CALLBACK(update_profile)); + +static const struct sm_object energy_eff_turbo = SM_DECLARE_BOOL({ + .flags = 0, + .opt_name = "energy_eff_turbo", + .ui_name = "Energy Efficient Turbo", + /* No help text */ + .default_value = false, +}, WITH_CALLBACK(update_rt_perf)); + +static const struct sm_object pkg_c_state_limit = SM_DECLARE_ENUM({ + .flags = 0, + .opt_name = "pkg_c_state_limit", + .ui_name = "Package C-state limit", + .ui_helptext = "", /* TODO: write something */ + .default_value = 255, + .values = pkg_c_state_limit_values, +}, WITH_CALLBACK(update_rt_perf)); + +#define NUM_PCIE_SSC_SETTINGS 21 +static struct sm_enum_value pch_pm_pcie_pll_ssc_values[] = { + [NUM_PCIE_SSC_SETTINGS] = { "Auto", 0xff }, + SM_ENUM_VALUE_END, +}; + +static void update_pll_ssc_values(const struct sm_object *obj, struct sm_object *new) +{ + for (size_t i = 0; i < NUM_PCIE_SSC_SETTINGS; i++) { + char buffer[16]; + snprintf(buffer, sizeof(buffer), "%u.%u%%", i / 10, i % 10); + pch_pm_pcie_pll_ssc_values[i].ui_name = strdup(buffer); + pch_pm_pcie_pll_ssc_values[i].value = i; + } +} + +static const struct sm_object pch_pcie_pll_ssc = SM_DECLARE_ENUM({ + .opt_name = "pch_pcie_pll_ssc", + .ui_name = "PCH PCIe PLL Spread Spectrum Clocking", + /* No help text */ + .default_value = 0xff, + .values = pch_pm_pcie_pll_ssc_values, +}, WITH_CALLBACK(update_pll_ssc_values)); + +static const struct sm_object c_states = SM_DECLARE_BOOL({ + .flags = 0, + .opt_name = "c_states", + .ui_name = "CPU power states (C-states)", + .ui_helptext = "Specify whether C-states are supported.", + .default_value = true, +}, WITH_CALLBACK(update_rt_perf)); + +static const struct sm_object hyper_threading = SM_DECLARE_BOOL({ + .flags = 0, + .opt_name = "hyper_threading", + .ui_name = "Hyper-Threading Technology", + /* No help text */ + .default_value = true, +}, WITH_CALLBACK(update_rt_perf)); + +static struct sm_obj_form cpu = { + .ui_name = "CPU", + .obj_list = (const struct sm_object *[]) { + &c_states, + &hyper_threading, + &turbo_mode, + &energy_eff_turbo, + &vmx, + &vtd, + NULL + }, +}; + +static struct sm_obj_form main = { + .ui_name = "Main", + .obj_list = (const struct sm_object *[]) { + &serial_number, + &part_number, + &bad_profile, + &profile, + &power_on_after_fail, + &primary_display, + &pkg_c_state_limit, + &pch_pcie_pll_ssc, + &ibecc, + NULL + }, +}; + +static struct sm_obj_form *sm_root[] = { + &main, + &cpu, + NULL +}; + +/* + * TODO: Writing this by hand is extremely tedious. Introducing a DSL + * (Domain-Specific Language) to describe options which is translated + * into code at build time may be the way to go. Maybe expand SCONFIG + * so that these can be devicetree options? + */ +void lb_board(struct lb_header *header) +{ + char *current = (char *)lb_new_record(header); + struct lb_cfr *cfr_root = (struct lb_cfr *)current; + + cfr_write_setup_menu(cfr_root, sm_root); +} diff --git a/src/mainboard/prodrive/atlas/devicetree.cb b/src/mainboard/prodrive/atlas/devicetree.cb index 580ca7671d..baca59d576 100644 --- a/src/mainboard/prodrive/atlas/devicetree.cb +++ b/src/mainboard/prodrive/atlas/devicetree.cb @@ -52,9 +52,6 @@ chip soc/intel/alderlake register "usb3_ports[2]" = "USB3_PORT_DEFAULT(OC1)" register "usb3_ports[3]" = "USB3_PORT_DEFAULT(OC1)" - register "ibecc.enable" = "CONFIG(ATLAS_ENABLE_IBECC)" - register "ibecc.mode" = "CONFIG(ATLAS_ENABLE_IBECC) ? IBECC_MODE_ALL : IBECC_MODE_NONE" - register "sata_salp_support" = "1" register "sata_ports_enable" = "{ diff --git a/src/mainboard/prodrive/atlas/ramstage_fsp_params.c b/src/mainboard/prodrive/atlas/ramstage_fsp_params.c index e3c11e9127..786f345862 100644 --- a/src/mainboard/prodrive/atlas/ramstage_fsp_params.c +++ b/src/mainboard/prodrive/atlas/ramstage_fsp_params.c @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ +#include #include #include "vpd.h" @@ -37,5 +38,17 @@ void mainboard_silicon_init_params(FSP_S_CONFIG *params) params->PmcV1p05PhyExtFetControlEn = 0; params->PmcV1p05IsExtFetControlEn = 0; break; + default: + if (get_uint_option("c_states", 1) == 0) { + params->Cx = 0; + params->C1e = 0; + params->C1StateUnDemotion = 0; + params->C1StateAutoDemotion = 0; + } + params->PkgCStateLimit = get_uint_option("pkg_c_state_limit", 255); + params->PchPmPciePllSsc = get_uint_option("pch_pcie_pll_ssc", 255); + params->EnergyEfficientTurbo = get_uint_option("energy_eff_turbo", 0); + params->TurboMode = get_uint_option("turbo_mode", 1); + break; } } diff --git a/src/mainboard/prodrive/atlas/romstage_fsp_params.c b/src/mainboard/prodrive/atlas/romstage_fsp_params.c index 7d3d9b51f3..4a4c48d355 100644 --- a/src/mainboard/prodrive/atlas/romstage_fsp_params.c +++ b/src/mainboard/prodrive/atlas/romstage_fsp_params.c @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ #include +#include #include #include @@ -48,6 +49,13 @@ void mainboard_memory_init_params(FSPM_UPD *memupd) memcfg_init(memupd, mem_config, &dimm_module_spd_info, half_populated); + const unsigned int def_prim_display = CONFIG(ONBOARD_VGA_IS_PRIMARY) ? 0 : 3; + mcfg->PrimaryDisplay = get_uint_option("primary_display", def_prim_display); + mcfg->VmxEnable = get_uint_option("vmx", mcfg->VmxEnable); + mcfg->VtdDisable = !get_uint_option("vtd", !mcfg->VtdDisable); + mcfg->Ibecc = get_uint_option("ibecc", false); + mcfg->IbeccOperationMode = mcfg->Ibecc ? 2 : 0; + /* Apply profile-specific settings */ switch (get_emi_eeprom_vpd()->profile) { case ATLAS_PROF_REALTIME_PERFORMANCE: