Sumeet R Pawnikar (sumeet.r.pawnikar@intel.com) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/16884
-gerrit
commit db135036699b838eda9ca42a43cee1be23437adb Author: Sumeet Pawnikar sumeet.r.pawnikar@intel.com Date: Tue Sep 27 23:18:35 2016 +0530
soc/intel/apollolake: Set package power limits for RAPL registers
This patch sets the package power limit values in RAPL MSR and MMIO registers after boot and suspend-resume cycle.
BUG=chrome-os-partner:56922 TEST=Build, booted and tested these package power limits before and after boot and suspend-resume cycle.
Change-Id: I34208048a6d4a127e9b1267d2df043cb2c46cf77 Signed-off-by: Sumeet Pawnikar sumeet.r.pawnikar@intel.com --- src/soc/intel/apollolake/chip.c | 123 +++++++++++++++++++++++++++++ src/soc/intel/apollolake/include/soc/cpu.h | 8 ++ 2 files changed, 131 insertions(+)
diff --git a/src/soc/intel/apollolake/chip.c b/src/soc/intel/apollolake/chip.c index eeac6ce..6bbc5e5 100644 --- a/src/soc/intel/apollolake/chip.c +++ b/src/soc/intel/apollolake/chip.c @@ -38,6 +38,64 @@
#include "chip.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, +}; + static void *vbt; static struct region_device vbt_rdev;
@@ -193,6 +251,68 @@ static void pcie_override_devicetree_after_silicon_init(void) pcie_update_device_tree(PCIEB0_DEVFN, 2); }
+/* Configure processor power limits */ +static void set_power_limits(u8 power_limit_1_time) +{ + uint32_t *rapl_mmio_reg; + msr_t rapl_msr_reg, limit; + unsigned power_unit; + unsigned tdp, min_power, max_power, max_time; + u8 power_limit_1_val; + + rapl_mmio_reg = (void*)(uintptr_t) (MCH_BASE_ADDR + MCHBAR_RAPL_PPL); + + if (power_limit_1_time > ARRAY_SIZE(power_limit_time_sec_to_msr)) + power_limit_1_time = MB_POWER_LIMIT1_TIME_DEFAULT; + + /* Get units */ + rapl_msr_reg = rdmsr(MSR_PKG_POWER_SKU_UNIT); + power_unit = 1 << (rapl_msr_reg.lo & 0xf); + + /* Get power defaults for this SKU */ + rapl_msr_reg = rdmsr(MSR_PKG_POWER_SKU_UNIT); + tdp = rapl_msr_reg.lo & PKG_POWER_LIMIT_MASK; + min_power = (rapl_msr_reg.lo >> 16) & PKG_POWER_LIMIT_MASK; + max_power = rapl_msr_reg.hi & PKG_POWER_LIMIT_MASK; + max_time = (rapl_msr_reg.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; + + /* Set PL1 Pkg Power clamp bit */ + limit.lo |= PKG_POWER_LIMIT_CLAMP; + + 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 PL2 to 15W */ + limit.hi = 0; + limit.hi |= 0xf00 & PKG_POWER_LIMIT_MASK; + limit.hi |= PKG_POWER_LIMIT_EN; + + /* Program package power limits in RAPL MSR */ + wrmsr(MSR_PKG_POWER_LIMIT, limit); + + /* Setting RAPL MMIO reister for Power limits */ + write32(rapl_mmio_reg, limit.lo & (~(PKG_POWER_LIMIT_EN))); + write32(rapl_mmio_reg + 1, limit.hi); +} + static void rapl_update(void) { uint32_t *rapl_reg; @@ -241,6 +361,9 @@ static void soc_init(void *data) /* Allocate ACPI NVS in CBMEM */ gnvs = cbmem_add(CBMEM_ID_ACPI_GNVS, sizeof(*gnvs));
+ /* Set RAPL MSR for Package power limits*/ + set_power_limits(28); + /* Update RAPL package power limit */ rapl_update(); } diff --git a/src/soc/intel/apollolake/include/soc/cpu.h b/src/soc/intel/apollolake/include/soc/cpu.h index 22412af..dbe0503 100644 --- a/src/soc/intel/apollolake/include/soc/cpu.h +++ b/src/soc/intel/apollolake/include/soc/cpu.h @@ -39,6 +39,14 @@ void apollolake_init_cpus(struct device *dev); #define PREFETCH_L2_DISABLE (1 << 2)
#define MSR_PKG_POWER_SKU_UNIT 0x606 +#define MSR_PKG_POWER_LIMIT 0x610 +#define PKG_POWER_LIMIT_MASK (0x7fff) +#define PKG_POWER_LIMIT_EN (1 << 15) +#define PKG_POWER_LIMIT_CLAMP (1 << 16) +#define PKG_POWER_LIMIT_TIME_SHIFT 17 +#define PKG_POWER_LIMIT_TIME_MASK (0x7f) +/* For Mobile, default PL1 time window value is 28 seconds */ +#define MB_POWER_LIMIT1_TIME_DEFAULT 28
#define MSR_L2_QOS_MASK(reg) (0xd10 + reg) #define MSR_IA32_PQR_ASSOC 0xc8f