diff options
author | Angel Pons <th3fanbus@gmail.com> | 2020-10-25 00:02:29 +0000 |
---|---|---|
committer | Angel Pons <th3fanbus@gmail.com> | 2020-10-30 00:45:08 +0000 |
commit | 9f6cdbaaf5d1a799e314e0baf9f4fda218abdf75 (patch) | |
tree | 7e389d972b2e4dce00382e6c73e20da623e5b759 /src/soc/intel/broadwell/cpu.c | |
parent | a6f02a8c494a6a8584caf0453a028d76bdd2d972 (diff) |
Revert "broadwell: update processor power limits configuration"
This reverts commit fa42d568a00e5daadd35722790c529539227130e.
Reason for revert: Passes in an incompatible structure and only happens
to boot by chance. Moreover, Broadwell will soon be merged with Haswell
and this requires Broadwell to not depend on any Intel common SoC code.
Tested on out-of-tree Acer Aspire E5-573, PL values are correct again.
Change-Id: I6e8e000dba8ff09fab4e6f174ab703348dcd6a96
Signed-off-by: Angel Pons <th3fanbus@gmail.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/45011
Reviewed-by: Michael Niewöhner <foss@mniewoehner.de>
Reviewed-by: Tim Wawrzynczak <twawrzynczak@chromium.org>
Reviewed-by: Sumeet R Pawnikar <sumeet.r.pawnikar@intel.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Diffstat (limited to 'src/soc/intel/broadwell/cpu.c')
-rw-r--r-- | src/soc/intel/broadwell/cpu.c | 143 |
1 files changed, 142 insertions, 1 deletions
diff --git a/src/soc/intel/broadwell/cpu.c b/src/soc/intel/broadwell/cpu.c index 694c7277a4..72efa3dc81 100644 --- a/src/soc/intel/broadwell/cpu.c +++ b/src/soc/intel/broadwell/cpu.c @@ -15,7 +15,6 @@ #include <cpu/intel/turbo.h> #include <cpu/x86/name.h> #include <delay.h> -#include <intelblocks/cpulib.h> #include <soc/cpu.h> #include <soc/msr.h> #include <soc/pci_devs.h> @@ -25,6 +24,64 @@ #include <soc/intel/broadwell/chip.h> #include <cpu/intel/common/common.h> +/* Convert time in seconds to POWER_LIMIT_1_TIME MSR value */ +static const u8 power_limit_time_sec_to_msr[] = { + [0] = 0x00, + [1] = 0x0a, + [2] = 0x0b, + [3] = 0x4b, + [4] = 0x0c, + [5] = 0x2c, + [6] = 0x4c, + [7] = 0x6c, + [8] = 0x0d, + [10] = 0x2d, + [12] = 0x4d, + [14] = 0x6d, + [16] = 0x0e, + [20] = 0x2e, + [24] = 0x4e, + [28] = 0x6e, + [32] = 0x0f, + [40] = 0x2f, + [48] = 0x4f, + [56] = 0x6f, + [64] = 0x10, + [80] = 0x30, + [96] = 0x50, + [112] = 0x70, + [128] = 0x11, +}; + +/* Convert POWER_LIMIT_1_TIME MSR value to seconds */ +static const u8 power_limit_time_msr_to_sec[] = { + [0x00] = 0, + [0x0a] = 1, + [0x0b] = 2, + [0x4b] = 3, + [0x0c] = 4, + [0x2c] = 5, + [0x4c] = 6, + [0x6c] = 7, + [0x0d] = 8, + [0x2d] = 10, + [0x4d] = 12, + [0x6d] = 14, + [0x0e] = 16, + [0x2e] = 20, + [0x4e] = 24, + [0x6e] = 28, + [0x0f] = 32, + [0x2f] = 40, + [0x4f] = 48, + [0x6f] = 56, + [0x10] = 64, + [0x30] = 80, + [0x50] = 96, + [0x70] = 112, + [0x11] = 128, +}; + /* The core 100MHz BCLK is disabled in deeper c-states. One needs to calibrate * the 100MHz BCLK against the 24MHz BCLK to restore the clocks properly * when a core is woken up. */ @@ -230,6 +287,90 @@ static void configure_pch_power_sharing(void) RCBA32(PMSYNC_CONFIG2) = pmsync2; } +int cpu_config_tdp_levels(void) +{ + msr_t platform_info; + + /* Bits 34:33 indicate how many levels supported */ + platform_info = rdmsr(MSR_PLATFORM_INFO); + return (platform_info.hi >> 1) & 3; +} + +/* + * Configure processor power limits if possible + * This must be done AFTER set of BIOS_RESET_CPL + */ +void set_power_limits(u8 power_limit_1_time) +{ + msr_t msr = rdmsr(MSR_PLATFORM_INFO); + msr_t limit; + unsigned int power_unit; + unsigned int tdp, min_power, max_power, max_time; + u8 power_limit_1_val; + + if (power_limit_1_time >= ARRAY_SIZE(power_limit_time_sec_to_msr)) + power_limit_1_time = ARRAY_SIZE(power_limit_time_sec_to_msr) - 1; + + if (!(msr.lo & PLATFORM_INFO_SET_TDP)) + return; + + /* Get units */ + msr = rdmsr(MSR_PKG_POWER_SKU_UNIT); + power_unit = 2 << ((msr.lo & 0xf) - 1); + + /* Get power defaults for this SKU */ + msr = rdmsr(MSR_PKG_POWER_SKU); + tdp = msr.lo & 0x7fff; + min_power = (msr.lo >> 16) & 0x7fff; + max_power = msr.hi & 0x7fff; + max_time = (msr.hi >> 16) & 0x7f; + + printk(BIOS_DEBUG, "CPU TDP: %u Watts\n", tdp / power_unit); + + if (power_limit_time_msr_to_sec[max_time] > power_limit_1_time) + power_limit_1_time = power_limit_time_msr_to_sec[max_time]; + + if (min_power > 0 && tdp < min_power) + tdp = min_power; + + if (max_power > 0 && tdp > max_power) + tdp = max_power; + + power_limit_1_val = power_limit_time_sec_to_msr[power_limit_1_time]; + + /* Set long term power limit to TDP */ + limit.lo = 0; + limit.lo |= tdp & PKG_POWER_LIMIT_MASK; + limit.lo |= PKG_POWER_LIMIT_EN; + limit.lo |= (power_limit_1_val & PKG_POWER_LIMIT_TIME_MASK) << + PKG_POWER_LIMIT_TIME_SHIFT; + + /* Set short term power limit to 1.25 * TDP */ + limit.hi = 0; + limit.hi |= ((tdp * 125) / 100) & PKG_POWER_LIMIT_MASK; + limit.hi |= PKG_POWER_LIMIT_EN; + /* Power limit 2 time is only programmable on server SKU */ + + wrmsr(MSR_PKG_POWER_LIMIT, limit); + + /* Set power limit values in MCHBAR as well */ + MCHBAR32(MCH_PKG_POWER_LIMIT_LO) = limit.lo; + MCHBAR32(MCH_PKG_POWER_LIMIT_HI) = limit.hi; + + /* Set DDR RAPL power limit by copying from MMIO to MSR */ + msr.lo = MCHBAR32(MCH_DDR_POWER_LIMIT_LO); + msr.hi = MCHBAR32(MCH_DDR_POWER_LIMIT_HI); + wrmsr(MSR_DDR_RAPL_LIMIT, msr); + + /* Use nominal TDP values for CPUs with configurable TDP */ + if (cpu_config_tdp_levels()) { + msr = rdmsr(MSR_CONFIG_TDP_NOMINAL); + limit.hi = 0; + limit.lo = msr.lo & 0xff; + wrmsr(MSR_TURBO_ACTIVATION_RATIO, limit); + } +} + static void configure_c_states(void) { msr_t msr; |