Lean Sheng Tan has submitted this change. ( https://review.coreboot.org/c/coreboot/+/74122?usp=email )
Change subject: mb/prodrive/atlas: Add initial support for options ......................................................................
mb/prodrive/atlas: Add initial support for options
The plan is to have a setup menu in edk2 to configure coreboot options without having to describe the options in both coreboot and edk2; that would be a maintenance nightmare. Options are passed to edk2 using CFR structures, edk2 stores the values in the variable store in flash, and coreboot reads the option values using the EFI variable store backend.
Change-Id: I47585a9a6f94ab5005f2ab63a0df267c0caef231 Signed-off-by: Angel Pons th3fanbus@gmail.com Reviewed-on: https://review.coreboot.org/c/coreboot/+/74122 Tested-by: build bot (Jenkins) no-reply@coreboot.org Reviewed-by: Christian Walter christian.walter@9elements.com --- M src/mainboard/prodrive/atlas/Kconfig M src/mainboard/prodrive/atlas/Makefile.mk A src/mainboard/prodrive/atlas/cfr.c M src/mainboard/prodrive/atlas/devicetree.cb M src/mainboard/prodrive/atlas/ramstage_fsp_params.c M src/mainboard/prodrive/atlas/romstage_fsp_params.c 6 files changed, 287 insertions(+), 10 deletions(-)
Approvals: Angel Pons: Looks good to me, approved Christian Walter: Looks good to me, approved build bot (Jenkins): Verified
diff --git a/src/mainboard/prodrive/atlas/Kconfig b/src/mainboard/prodrive/atlas/Kconfig index b40e2b7..cbd625c 100644 --- a/src/mainboard/prodrive/atlas/Kconfig +++ b/src/mainboard/prodrive/atlas/Kconfig @@ -13,6 +13,7 @@ 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 @@ 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 b31f03a..df7af1c 100644 --- a/src/mainboard/prodrive/atlas/Makefile.mk +++ b/src/mainboard/prodrive/atlas/Makefile.mk @@ -8,6 +8,7 @@
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 0000000..f5700e2 --- /dev/null +++ b/src/mainboard/prodrive/atlas/cfr.c @@ -0,0 +1,264 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <boot/coreboot_tables.h> +#include <commonlib/coreboot_tables.h> +#include <drivers/option/cfr_frontend.h> +#include <intelblocks/pmclib.h> +#include <inttypes.h> +#include <soc/pm.h> +#include <stdio.h> +#include <string.h> +#include <types.h> + +#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 580ca76..baca59d 100644 --- a/src/mainboard/prodrive/atlas/devicetree.cb +++ b/src/mainboard/prodrive/atlas/devicetree.cb @@ -52,9 +52,6 @@ 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 e3c11e9..786f345 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 <option.h> #include <soc/ramstage.h>
#include "vpd.h" @@ -37,5 +38,17 @@ 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 7d3d9b5..4a4c48d 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 <fsp/api.h> +#include <option.h> #include <soc/romstage.h> #include <soc/meminit.h>
@@ -48,6 +49,13 @@
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: