[coreboot-gerrit] New patch to review for coreboot: soc/intel/apollolake: Set package power limits for RAPL registers
Sumeet R Pawnikar (sumeet.r.pawnikar@intel.com)
gerrit at coreboot.org
Wed Oct 5 13:37:01 CEST 2016
Sumeet R Pawnikar (sumeet.r.pawnikar at 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 at 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 at 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
More information about the coreboot-gerrit
mailing list