summaryrefslogtreecommitdiff
path: root/src/soc/intel/apollolake
diff options
context:
space:
mode:
Diffstat (limited to 'src/soc/intel/apollolake')
-rw-r--r--src/soc/intel/apollolake/chip.c79
-rw-r--r--src/soc/intel/apollolake/chip.h3
-rw-r--r--src/soc/intel/apollolake/include/soc/cpu.h14
3 files changed, 79 insertions, 17 deletions
diff --git a/src/soc/intel/apollolake/chip.c b/src/soc/intel/apollolake/chip.c
index eeac6cee5e..181d4d68bc 100644
--- a/src/soc/intel/apollolake/chip.c
+++ b/src/soc/intel/apollolake/chip.c
@@ -193,22 +193,67 @@ static void pcie_override_devicetree_after_silicon_init(void)
pcie_update_device_tree(PCIEB0_DEVFN, 2);
}
-static void rapl_update(void)
+/* Configure package power limits */
+static void set_power_limits(void)
{
- uint32_t *rapl_reg;
- uint32_t val;
- const uint32_t power_mw = 15000;
-
- rapl_reg = (void*)(uintptr_t) (MCH_BASE_ADDR + MCHBAR_RAPL_PPL);
-
- /* Due to an incorrect value set for the power limit PL1 as 6W in RAPL
- * MMIO register from FSP code, the system is not able to leverage full
- * TDP capacity. This RAPL MMIO register is a physically separate
- * instance from RAPL MSR register. Punit algorithm controls to the
- * minimum power limit PL1 mentioned in the RAPL MMIO and MSR registers.
- * Here, setting RAPL PL1 in Bits[14:0] to 15W in RAPL MMIO register. */
- val = (power_mw << (rdmsr(MSR_PKG_POWER_SKU_UNIT).lo & 0xf)) / 1000;
- write32(rapl_reg, (read32(rapl_reg) & ~0x7fff) | val);
+ static struct soc_intel_apollolake_config *cfg;
+ struct device *dev = NB_DEV_ROOT;
+ msr_t rapl_msr_reg, limit;
+ uint32_t power_unit;
+ uint32_t tdp, min_power, max_power;
+ uint32_t *rapl_mmio_reg;
+
+ if (!dev || !dev->chip_info) {
+ printk(BIOS_ERR, "BUG! Could not find SOC devicetree config\n");
+ return;
+ }
+
+ cfg = dev->chip_info;
+
+ /* 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;
+
+ if (min_power > 0 && tdp < min_power)
+ tdp = min_power;
+
+ if (max_power > 0 && tdp > max_power)
+ tdp = max_power;
+
+ /* Set PL1 override value */
+ tdp = (cfg->tdp_pl1_override_mw == 0) ?
+ tdp : (cfg->tdp_pl1_override_mw * power_unit) / 1000;
+
+ /* Set long term power limit to TDP */
+ limit.lo = tdp & PKG_POWER_LIMIT_MASK;
+ /* PL2 is invalid for small core */
+ limit.hi = 0x0;
+
+ /* Set PL1 Pkg Power clamp bit */
+ limit.lo |= PKG_POWER_LIMIT_CLAMP;
+
+ limit.lo |= PKG_POWER_LIMIT_EN;
+ limit.lo |= (MB_POWER_LIMIT1_TIME_DEFAULT &
+ PKG_POWER_LIMIT_TIME_MASK) << PKG_POWER_LIMIT_TIME_SHIFT;
+
+ /* Program package power limits in RAPL MSR */
+ wrmsr(MSR_PKG_POWER_LIMIT, limit);
+ printk(BIOS_INFO, "RAPL PL1 %d.%dW\n", tdp / power_unit,
+ 100 * (tdp % power_unit) / power_unit);
+
+ /* Get the MMIO address */
+ rapl_mmio_reg = (void *)(uintptr_t) (MCH_BASE_ADDR + MCHBAR_RAPL_PPL);
+ /*
+ * Disable RAPL MMIO PL1 Power limits because RAPL uses MSR value.
+ * PL2 (limit.hi) is invalid for small cores
+ */
+ write32(rapl_mmio_reg, limit.lo & ~(PKG_POWER_LIMIT_EN));
}
static void soc_init(void *data)
@@ -241,8 +286,8 @@ static void soc_init(void *data)
/* Allocate ACPI NVS in CBMEM */
gnvs = cbmem_add(CBMEM_ID_ACPI_GNVS, sizeof(*gnvs));
- /* Update RAPL package power limit */
- rapl_update();
+ /* Set RAPL MSR for Package power limits*/
+ set_power_limits();
}
static void soc_final(void *data)
diff --git a/src/soc/intel/apollolake/chip.h b/src/soc/intel/apollolake/chip.h
index 74a6411b50..6c3bcd8cad 100644
--- a/src/soc/intel/apollolake/chip.h
+++ b/src/soc/intel/apollolake/chip.h
@@ -107,6 +107,9 @@ struct soc_intel_apollolake_config {
/* Enable DPTF support */
int dptf_enable;
+ /* PL1 override value in mW for APL */
+ uint16_t tdp_pl1_override_mw;
+
/* Configure Audio clk gate and power gate
* IOSF-SB port ID 92 offset 0x530 [5] and [3]
*/
diff --git a/src/soc/intel/apollolake/include/soc/cpu.h b/src/soc/intel/apollolake/include/soc/cpu.h
index 22412aff2d..bffe4bcd8d 100644
--- a/src/soc/intel/apollolake/include/soc/cpu.h
+++ b/src/soc/intel/apollolake/include/soc/cpu.h
@@ -39,6 +39,20 @@ 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, RAPL default PL1 time window value set to 28 seconds.
+ * RAPL time window calculation defined as follows:
+ * Time Window = (float)((1+X/4)*(2*^Y), X Corresponds to [23:22],
+ * Y to [21:17] in MSR 0x610. 28 sec is equal to 0x6e.
+ */
+#define MB_POWER_LIMIT1_TIME_DEFAULT 0x6e
#define MSR_L2_QOS_MASK(reg) (0xd10 + reg)
#define MSR_IA32_PQR_ASSOC 0xc8f