From 83b36f82761f3d354266300bd4dcfd517ac29b1b Mon Sep 17 00:00:00 2001 From: Sumeet R Pawnikar Date: Thu, 20 Apr 2023 17:26:00 +0530 Subject: [PATCH] soc/intel/common: Support power limits update for variants Add support to update power limit values for variants. Until now, each SoC implements this themselves. To avoid code duplication, add this to common code. BRANCH=None BUG=b:270664854 TEST=Built and verified power limit values as below log message for 15W SKU on Rex board. Overriding power limits PL1 (mW) (10000, 15000) PL2 (mW) (57000, 57000) PL4 (W) (114) Change-Id: I414715f211d816bbfad03a673ca96dd5df94caeb Signed-off-by: Sumeet Pawnikar Reviewed-on: https://review.coreboot.org/c/coreboot/+/74620 Tested-by: build bot (Jenkins) Reviewed-by: Subrata Banik Reviewed-by: Eric Lai --- .../block/include/intelblocks/power_limit.h | 14 +++++ .../intel/common/block/power_limit/Kconfig | 7 +++ .../common/block/power_limit/power_limit.c | 56 +++++++++++++++++++ 3 files changed, 77 insertions(+) diff --git a/src/soc/intel/common/block/include/intelblocks/power_limit.h b/src/soc/intel/common/block/include/intelblocks/power_limit.h index 3f18126e9b..290a3a3659 100644 --- a/src/soc/intel/common/block/include/intelblocks/power_limit.h +++ b/src/soc/intel/common/block/include/intelblocks/power_limit.h @@ -42,4 +42,18 @@ void set_power_limits(u8 power_limit_1_time, u8 get_cpu_tdp(void); +struct cpu_tdp_power_limits { + uint16_t mch_id; + uint8_t cpu_tdp; + unsigned int pl1_min_power; + unsigned int pl1_max_power; + unsigned int pl2_min_power; + unsigned int pl2_max_power; + unsigned int pl4_power; +}; + +/* Modify Power Limit devictree settings during ramstage */ +void variant_update_cpu_power_limits(const struct cpu_tdp_power_limits *limits, + size_t num_entries); + #endif /* _SOC_INTEL_COMMON_BLOCK_POWER_LIMIT_H_ */ diff --git a/src/soc/intel/common/block/power_limit/Kconfig b/src/soc/intel/common/block/power_limit/Kconfig index b6782bc6df..0e57f1c71c 100644 --- a/src/soc/intel/common/block/power_limit/Kconfig +++ b/src/soc/intel/common/block/power_limit/Kconfig @@ -9,3 +9,10 @@ config SOC_INTEL_RAPL_DISABLE_VIA_MCHBAR default n help Select if disabling Running Average Power Limit (RAPL) has to be done via MCHBAR. + +config SOC_INTEL_COMMON_BLOCK_VARIANT_POWER_LIMIT + bool + default n + help + This option allows to configure processor power limit values + for different variants based on CPU TDP and machine id. diff --git a/src/soc/intel/common/block/power_limit/power_limit.c b/src/soc/intel/common/block/power_limit/power_limit.c index d7c9077cb1..adf391fae7 100644 --- a/src/soc/intel/common/block/power_limit/power_limit.c +++ b/src/soc/intel/common/block/power_limit/power_limit.c @@ -2,9 +2,13 @@ #include #include +#include +#include #include #include #include +#include +#include #include /* Convert time in seconds to POWER_LIMIT_1_TIME MSR value */ @@ -227,3 +231,55 @@ u8 get_cpu_tdp(void) return cpu_tdp / power_unit; } + +WEAK_DEV_PTR(dptf_policy); + +#if CONFIG(SOC_INTEL_COMMON_BLOCK_VARIANT_POWER_LIMIT) +void variant_update_cpu_power_limits(const struct cpu_tdp_power_limits *limits, + size_t num_entries) +{ + if (!num_entries) { + printk(BIOS_INFO, "CPU Power limits entry not available\n"); + return; + } + + const struct device *policy_dev = DEV_PTR(dptf_policy); + if (!policy_dev) + return; + + struct drivers_intel_dptf_config *config = policy_dev->chip_info; + if (!config) { + printk(BIOS_INFO, "DPTF is not enabled\n"); + return; + } + + uint16_t mch_id = pci_s_read_config16(PCI_DEV(0, 0, 0), PCI_DEVICE_ID); + if (mch_id == 0xffff) { + printk(BIOS_INFO, "No matching PCI DID present\n"); + return; + } + + uint8_t tdp = get_cpu_tdp(); + + for (size_t index = 0; index < num_entries; index++) { + if (mch_id != limits[index].mch_id || tdp != limits[index].cpu_tdp) { + continue; + } else { + struct dptf_power_limits *settings = &config->controls.power_limits; + config_t *conf = config_of_soc(); + struct soc_power_limits_config *soc_config = conf->power_limits_config; + settings->pl1.min_power = limits[index].pl1_min_power; + settings->pl1.max_power = limits[index].pl1_max_power; + settings->pl2.min_power = limits[index].pl2_min_power; + settings->pl2.max_power = limits[index].pl2_max_power; + soc_config->tdp_pl4 = DIV_ROUND_UP(limits[index].pl4_power, MILLIWATTS_TO_WATTS); + printk(BIOS_INFO, "Overriding power limits PL1 (mW) (%u, %u) PL2 (mW) (%u, %u) PL4 (W) (%u)\n", + settings->pl1.min_power, + settings->pl1.max_power, + settings->pl2.min_power, + settings->pl2.max_power, + soc_config->tdp_pl4); + } + } +} +#endif