[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