[coreboot-gerrit] Patch set updated for coreboot: soc/intel/apollolake: Set package power limits for RAPL registers

Sumeet R Pawnikar (sumeet.r.pawnikar@intel.com) gerrit at coreboot.org
Fri Oct 7 12:37:26 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 a7a3117b9cdbae07a8446c98f82e02fd90c6343b
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=Built, booted and tested these package power limits
    before and after boot and suspend-resume cycle. Before
    suspend and after resume, read RAPL MSR and MMIO register.
    
    Change-Id: I34208048a6d4a127e9b1267d2df043cb2c46cf77
    Signed-off-by: Sumeet Pawnikar <sumeet.r.pawnikar at intel.com>
---
 src/soc/intel/apollolake/chip.c            | 130 +++++++++++++++++++++++++++++
 src/soc/intel/apollolake/include/soc/cpu.h |   9 ++
 2 files changed, 139 insertions(+)

diff --git a/src/soc/intel/apollolake/chip.c b/src/soc/intel/apollolake/chip.c
index eeac6ce..993f010 100644
--- a/src/soc/intel/apollolake/chip.c
+++ b/src/soc/intel/apollolake/chip.c
@@ -38,6 +38,39 @@
 
 #include "chip.h"
 
+#define	MAX_NUM_ENTRY	(sizeof(lookup_table) / sizeof(lookup_table[0]))
+
+static const struct {
+	uint8_t time;
+	uint8_t msr_val;
+} lookup_table[] = {
+	{0, 0},
+	{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}
+};
+
 static void *vbt;
 static struct region_device vbt_rdev;
 
@@ -193,6 +226,100 @@ static void pcie_override_devicetree_after_silicon_init(void)
 	pcie_update_device_tree(PCIEB0_DEVFN, 2);
 }
 
+static uint8_t find_lookup_time(u8 in_msr)
+{
+	uint8_t index = 0;
+
+	while (in_msr != lookup_table[index].msr_val && index < MAX_NUM_ENTRY)
+		index++;
+
+	/*
+	 * If some value is not part of this lookup table,
+	 * assinging the default time value for PL1.
+	 */
+	if (index >= MAX_NUM_ENTRY)
+		return MB_POWER_LIMIT1_TIME_DEFAULT;
+
+	return lookup_table[index].time;
+}
+
+static uint8_t find_lookup_msr(u8 in_time)
+{
+	uint8_t index = 0;
+
+	while (in_time != lookup_table[index].time && index < MAX_NUM_ENTRY)
+		index++;
+
+	/*
+	 * If some value is not part of this lookup table,
+	 * assinging the default time value for PL1.
+	 */
+	if (index >= MAX_NUM_ENTRY)
+		return find_lookup_msr(MB_POWER_LIMIT1_TIME_DEFAULT);
+
+	return lookup_table[index].msr_val;
+}
+
+/* Configure package power limits */
+static void set_power_limits(u8 power_limit_1_time)
+{
+	uint32_t *rapl_mmio_reg;
+	msr_t rapl_msr_reg, limit;
+	unsigned int power_unit;
+	unsigned int tdp, min_power, max_power, max_time;
+	uint8_t power_limit_1_val;
+
+	rapl_mmio_reg = (void *)(uintptr_t) (MCH_BASE_ADDR + MCHBAR_RAPL_PPL);
+
+	if (power_limit_1_time > MAX_NUM_ENTRY)
+		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);
+	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 (find_lookup_time(max_time) > power_limit_1_time)
+		power_limit_1_time = find_lookup_time(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 = find_lookup_msr(power_limit_1_time);
+
+	/* Set long term power limit to TDP */
+	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 = 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 register 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 +368,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(MB_POWER_LIMIT1_TIME_DEFAULT);
+
 	/* 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..0195249 100644
--- a/src/soc/intel/apollolake/include/soc/cpu.h
+++ b/src/soc/intel/apollolake/include/soc/cpu.h
@@ -39,6 +39,15 @@ void apollolake_init_cpus(struct device *dev);
 #define   PREFETCH_L2_DISABLE	(1 << 2)
 
 #define MSR_PKG_POWER_SKU_UNIT	0x606
+#define MSR_PKG_POWER_SKU	0x614
+#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