summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSumeet R Pawnikar <sumeet.r.pawnikar@intel.com>2023-04-20 17:26:00 +0530
committerFelix Held <felix-coreboot@felixheld.de>2023-05-26 18:04:30 +0000
commit83b36f82761f3d354266300bd4dcfd517ac29b1b (patch)
tree8622f53378980eeefa1a6b8bfcb40762e334be8a
parente9efd3248550e01a5043860f25239a799d5b19bc (diff)
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 <sumeet.r.pawnikar@intel.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/74620 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Subrata Banik <subratabanik@google.com> Reviewed-by: Eric Lai <eric_lai@quanta.corp-partner.google.com>
-rw-r--r--src/soc/intel/common/block/include/intelblocks/power_limit.h14
-rw-r--r--src/soc/intel/common/block/power_limit/Kconfig7
-rw-r--r--src/soc/intel/common/block/power_limit/power_limit.c56
3 files changed, 77 insertions, 0 deletions
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 <console/console.h>
#include <cpu/x86/msr.h>
+#include <device/pci_ops.h>
+#include <drivers/intel/dptf/chip.h>
#include <intelblocks/cpulib.h>
#include <intelblocks/power_limit.h>
#include <soc/msr.h>
+#include <soc/pci_devs.h>
+#include <soc/soc_chip.h>
#include <soc/systemagent.h>
/* 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