[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