summaryrefslogtreecommitdiff
path: root/src/soc
diff options
context:
space:
mode:
authorPatrick Rudolph <patrick.rudolph@9elements.com>2019-12-04 13:51:00 +0100
committerPhilipp Deppenwiese <zaolin.daisuki@gmail.com>2020-01-06 10:06:37 +0000
commit9b5447b7819ac99ffc3787f2ecb0c4428eea8055 (patch)
tree005e2fe27b223086c470ebaf4e5a1b97864a448f /src/soc
parent26e2eeb2767db4ab7a7e197696c7e3e77a4f27c1 (diff)
downloadcoreboot-9b5447b7819ac99ffc3787f2ecb0c4428eea8055.tar.xz
soc/intel/cannonlake: Add VR config for CFL, CNL and WHL
Add VR config IccMax, DC and AC loadline defaults and voltage regulator maximum for all CFL, CNL and WHL. This supports mainboards with replaceable CPUs and provides sane defaults for boards that are missing the devicetree overwrite. Remove the default IccMax to make use of the introduced lookup-table. Also change some hex values to decimal. I couldn't find CML datasheet, so those are left out for now. Used Doc #337344 and #338023 Section 7. Change-Id: I1d2e174157d468830cc0baf2a2d8295ef61a1a63 Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/37466 Reviewed-by: Philipp Deppenwiese <zaolin.daisuki@gmail.com> Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Diffstat (limited to 'src/soc')
-rw-r--r--src/soc/intel/cannonlake/include/soc/vr_config.h19
-rw-r--r--src/soc/intel/cannonlake/vr_config.c264
2 files changed, 266 insertions, 17 deletions
diff --git a/src/soc/intel/cannonlake/include/soc/vr_config.h b/src/soc/intel/cannonlake/include/soc/vr_config.h
index 8bcf001ea9..1390b174e1 100644
--- a/src/soc/intel/cannonlake/include/soc/vr_config.h
+++ b/src/soc/intel/cannonlake/include/soc/vr_config.h
@@ -55,7 +55,8 @@ struct vr_config {
uint16_t dc_loadline;
};
-#define VR_CFG_AMP(i) ((i) * 4)
+#define VR_CFG_AMP(i) (uint16_t)((i) * 4)
+#define VR_CFG_MOHMS(i) (uint16_t)((i) * 100)
/* VrConfig Settings for 4 domains
* 0 = System Agent, 1 = IA Core,
@@ -68,6 +69,22 @@ enum vr_domain {
NUM_VR_DOMAINS
};
+#define VR_CFG_ALL_DOMAINS_ICC(sa, ia, gt_unsl, gt_sl) \
+ { \
+ [VR_SYSTEM_AGENT] = VR_CFG_AMP(sa), \
+ [VR_IA_CORE] = VR_CFG_AMP(ia), \
+ [VR_GT_UNSLICED] = VR_CFG_AMP(gt_unsl), \
+ [VR_GT_SLICED] = VR_CFG_AMP(gt_sl), \
+ }
+
+#define VR_CFG_ALL_DOMAINS_LOADLINE(sa, ia, gt_unsl, gt_sl) \
+ { \
+ [VR_SYSTEM_AGENT] = VR_CFG_MOHMS(sa), \
+ [VR_IA_CORE] = VR_CFG_MOHMS(ia), \
+ [VR_GT_UNSLICED] = VR_CFG_MOHMS(gt_unsl), \
+ [VR_GT_SLICED] = VR_CFG_MOHMS(gt_sl), \
+ }
+
void fill_vr_domain_config(void *params,
int domain, const struct vr_config *cfg);
diff --git a/src/soc/intel/cannonlake/vr_config.c b/src/soc/intel/cannonlake/vr_config.c
index 25270d8f98..7096b62e4a 100644
--- a/src/soc/intel/cannonlake/vr_config.c
+++ b/src/soc/intel/cannonlake/vr_config.c
@@ -14,9 +14,13 @@
*
*/
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
#include <fsp/api.h>
#include <soc/ramstage.h>
#include <soc/vr_config.h>
+#include <console/console.h>
+#include <intelblocks/cpulib.h>
static const struct vr_config default_configs[NUM_VR_DOMAINS] = {
[VR_SYSTEM_AGENT] = {
@@ -26,9 +30,9 @@ static const struct vr_config default_configs[NUM_VR_DOMAINS] = {
.psi3threshold = VR_CFG_AMP(1),
.psi3enable = 1,
.psi4enable = 1,
- .imon_slope = 0x0,
- .imon_offset = 0x0,
- .icc_max = VR_CFG_AMP(6),
+ .imon_slope = 0,
+ .imon_offset = 0,
+ .icc_max = 0,
.voltage_limit = 1520,
},
[VR_IA_CORE] = {
@@ -38,9 +42,9 @@ static const struct vr_config default_configs[NUM_VR_DOMAINS] = {
.psi3threshold = VR_CFG_AMP(1),
.psi3enable = 1,
.psi4enable = 1,
- .imon_slope = 0x0,
- .imon_offset = 0x0,
- .icc_max = VR_CFG_AMP(70),
+ .imon_slope = 0,
+ .imon_offset = 0,
+ .icc_max = 0,
.voltage_limit = 1520,
},
[VR_GT_UNSLICED] = {
@@ -50,9 +54,9 @@ static const struct vr_config default_configs[NUM_VR_DOMAINS] = {
.psi3threshold = VR_CFG_AMP(1),
.psi3enable = 1,
.psi4enable = 1,
- .imon_slope = 0x0,
- .imon_offset = 0x0,
- .icc_max = VR_CFG_AMP(31),
+ .imon_slope = 0,
+ .imon_offset = 0,
+ .icc_max = 0,
.voltage_limit = 1520,
},
[VR_GT_SLICED] = {
@@ -62,13 +66,224 @@ static const struct vr_config default_configs[NUM_VR_DOMAINS] = {
.psi3threshold = VR_CFG_AMP(1),
.psi3enable = 1,
.psi4enable = 1,
- .imon_slope = 0x0,
- .imon_offset = 0x0,
- .icc_max = VR_CFG_AMP(31),
+ .imon_slope = 0,
+ .imon_offset = 0,
+ .icc_max = 0,
.voltage_limit = 1520,
},
};
+
+static uint16_t get_sku_icc_max(int domain)
+{
+ const uint16_t tdp = cpu_get_power_max();
+
+ static uint16_t mch_id = 0, igd_id = 0;
+ if (!mch_id) {
+ struct device *dev = pcidev_path_on_root(SA_DEVFN_ROOT);
+ mch_id = dev ? pci_read_config16(dev, PCI_DEVICE_ID) : 0xffff;
+ }
+ if (!igd_id) {
+ struct device *dev = pcidev_path_on_root(SA_DEVFN_IGD);
+ igd_id = dev ? pci_read_config16(dev, PCI_DEVICE_ID) : 0xffff;
+ }
+
+ /*
+ * Iccmax table from Doc #337344 Section 7.2 DC Specifications for CFL.
+ * Iccmax table from Doc #338023 Section 7.2 DC Specifications for WHL.
+ *
+ * Platform Segment SA IA GT (GT/GTx)
+ * ---------------------------------------------------------------------
+ * CFL-U (28W) GT3 quad 8.5 64 64
+ * CFL-U (28W) GT3 dual 8.5 64 64
+ *
+ * CFL-H (45W) GT2 hex 11.1 128 0
+ * CFL-H (45W) GT2 quad 11.1 86 0
+ *
+ * CFL-S (95W) GT2 octa 11.1 193 45
+ *
+ * CFL-S (95W) GT2 hex 11.1 138 45
+ * CFL-S (65W) GT2 hex 11.1 133 45
+ * CFL-S (80W) GT2 hex 11.1 133 45
+ * CFL-S (35W) GT2 hex 11.1 104 35
+ *
+ * CFL-S (91W) GT2 quad 11.1 100 45
+ * CFL-S (83W) GT2 quad 11.1 100 45
+ * CFL-S (71W) GT2 quad 11.1 100 45
+ * CFL-S (65W) GT2 quad 11.1 79 45
+ * CFL-S (62W) GT2 quad 11.1 79 45
+ * CFL-S (35W) GT2 quad 11.1 66 35
+ *
+ * CFL-S (58W) GT2 dual 11.1 79 45
+ * CFL-S (54W) GT2 dual 11.1 58 45
+ * CFL-S (35W) GT2 dual 11.1 40 35
+ *
+ * CNL-U (15W) 13 34 0
+ *
+ * WHL-U (15W) GT2 quad 6 70 31
+ * WHL-U (15W) GT2 dual 6 35 31
+ *
+ * GT0 versions are the same as GT2/GT3, but have GT/GTx set to 0.
+ */
+
+ if (igd_id == 0xffff && ((domain == VR_GT_SLICED) || (domain == VR_GT_UNSLICED)))
+ return 0;
+
+ switch (mch_id) {
+ case PCI_DEVICE_ID_INTEL_CNL_ID_U: /* fallthrough */
+ case PCI_DEVICE_ID_INTEL_CNL_ID_Y: {
+ uint16_t icc_max[NUM_VR_DOMAINS] = VR_CFG_ALL_DOMAINS_ICC(13, 34, 0, 0);
+
+ return icc_max[domain];
+ }
+ case PCI_DEVICE_ID_INTEL_WHL_ID_W_4: {
+ uint16_t icc_max[NUM_VR_DOMAINS] = VR_CFG_ALL_DOMAINS_ICC(6, 70, 31, 31);
+
+ return icc_max[domain];
+ }
+ case PCI_DEVICE_ID_INTEL_WHL_ID_W_2: {
+ uint16_t icc_max[NUM_VR_DOMAINS] = VR_CFG_ALL_DOMAINS_ICC(6, 35, 31, 31);
+
+ return icc_max[domain];
+ }
+ case PCI_DEVICE_ID_INTEL_CFL_ID_U: /* fallthrough */
+ case PCI_DEVICE_ID_INTEL_CFL_ID_U_2: {
+ uint16_t icc_max[NUM_VR_DOMAINS] = VR_CFG_ALL_DOMAINS_ICC(8.5, 64, 64, 64);
+
+ return icc_max[domain];
+ }
+ case PCI_DEVICE_ID_INTEL_CFL_ID_H_8: /* fallthrough - undocumented */
+ case PCI_DEVICE_ID_INTEL_CFL_ID_H: { /* 6 core */
+ uint16_t icc_max[NUM_VR_DOMAINS] = VR_CFG_ALL_DOMAINS_ICC(11.1, 128, 0, 0);
+
+ return icc_max[domain];
+ }
+ case PCI_DEVICE_ID_INTEL_CFL_ID_H_4: { /* 4 core */
+ uint16_t icc_max[NUM_VR_DOMAINS] = VR_CFG_ALL_DOMAINS_ICC(11.1, 86, 0, 0);
+
+ return icc_max[domain];
+ }
+ case PCI_DEVICE_ID_INTEL_CFL_ID_S_DT_2: { /* 2 core */
+ uint16_t icc_max[NUM_VR_DOMAINS] = VR_CFG_ALL_DOMAINS_ICC(11.1, 40, 35, 35);
+
+ if (tdp >= 54) {
+ if (tdp >= 58)
+ icc_max[VR_IA_CORE] = VR_CFG_AMP(79);
+ else
+ icc_max[VR_IA_CORE] = VR_CFG_AMP(58);
+
+ icc_max[VR_GT_SLICED] = VR_CFG_AMP(45);
+ icc_max[VR_GT_UNSLICED] = VR_CFG_AMP(45);
+ }
+
+ return icc_max[domain];
+ }
+ case PCI_DEVICE_ID_INTEL_CFL_ID_S_S_8: {
+ uint16_t icc_max[NUM_VR_DOMAINS] = VR_CFG_ALL_DOMAINS_ICC(11.1, 193, 45, 45);
+
+ return icc_max[domain];
+ }
+ case PCI_DEVICE_ID_INTEL_CFL_ID_S: /* fallthrough */
+ case PCI_DEVICE_ID_INTEL_CFL_ID_S_WS_6: /* fallthrough */
+ case PCI_DEVICE_ID_INTEL_CFL_ID_S_S_6: {
+ uint16_t icc_max[NUM_VR_DOMAINS] = VR_CFG_ALL_DOMAINS_ICC(11.1, 104, 35, 35);
+ if (tdp >= 54) {
+ if (tdp >= 95)
+ icc_max[VR_IA_CORE] = VR_CFG_AMP(138);
+ else if (tdp >= 65)
+ icc_max[VR_IA_CORE] = VR_CFG_AMP(133);
+
+ icc_max[VR_GT_SLICED] = VR_CFG_AMP(45);
+ icc_max[VR_GT_UNSLICED] = VR_CFG_AMP(45);
+ }
+
+ return icc_max[domain];
+ }
+ case PCI_DEVICE_ID_INTEL_CFL_ID_S_S_4: /* fallthrough */
+ case PCI_DEVICE_ID_INTEL_CFL_ID_S_WS_4: /* fallthrough */
+ case PCI_DEVICE_ID_INTEL_CFL_ID_S_DT_4: {
+ uint16_t icc_max[NUM_VR_DOMAINS] = VR_CFG_ALL_DOMAINS_ICC(11.1, 66, 35, 35);
+ if (tdp >= 54) {
+ if (tdp >= 71)
+ icc_max[VR_IA_CORE] = VR_CFG_AMP(100);
+ else if (tdp >= 62)
+ icc_max[VR_IA_CORE] = VR_CFG_AMP(79);
+
+ icc_max[VR_GT_SLICED] = VR_CFG_AMP(45);
+ icc_max[VR_GT_UNSLICED] = VR_CFG_AMP(45);
+ }
+
+ return icc_max[domain];
+ }
+ default:
+ printk(BIOS_ERR, "ERROR: Unknown MCH (0x%x) in VR-config\n", mch_id);
+ }
+ return 0;
+}
+
+static uint16_t get_sku_ac_dc_loadline(const int domain)
+{
+ static uint16_t mch_id = 0;
+ if (!mch_id) {
+ struct device *dev = pcidev_path_on_root(SA_DEVFN_ROOT);
+ mch_id = dev ? pci_read_config16(dev, PCI_DEVICE_ID) : 0xffff;
+ }
+
+ switch (mch_id) {
+ case PCI_DEVICE_ID_INTEL_WHL_ID_W_4: /* fallthrough */
+ case PCI_DEVICE_ID_INTEL_CFL_ID_H_8: /* fallthrough */
+ case PCI_DEVICE_ID_INTEL_CFL_ID_H: /* fallthrough */
+ case PCI_DEVICE_ID_INTEL_CFL_ID_H_4: { /* fallthrough */
+ uint16_t loadline[NUM_VR_DOMAINS] =
+ VR_CFG_ALL_DOMAINS_LOADLINE(10.3, 1.8, 2.7, 2.7);
+ if (mch_id == PCI_DEVICE_ID_INTEL_WHL_ID_W_4) {
+ loadline[VR_GT_SLICED] = 0; /* unspecified */
+ loadline[VR_GT_UNSLICED] = 0; /* unspecified */
+ }
+ return loadline[domain];
+ }
+ case PCI_DEVICE_ID_INTEL_WHL_ID_W_2: /* fallthrough */
+ case PCI_DEVICE_ID_INTEL_CFL_ID_U: /* fallthrough */
+ case PCI_DEVICE_ID_INTEL_CFL_ID_U_2: /* fallthrough */
+ case PCI_DEVICE_ID_INTEL_CNL_ID_U: /* fallthrough */
+ case PCI_DEVICE_ID_INTEL_CNL_ID_Y: {
+ uint16_t loadline[NUM_VR_DOMAINS] =
+ VR_CFG_ALL_DOMAINS_LOADLINE(10.3, 2.4, 2.0, 2.0);
+ if (mch_id == PCI_DEVICE_ID_INTEL_WHL_ID_W_2) {
+ loadline[VR_GT_SLICED] = 0; /* unspecified */
+ loadline[VR_GT_UNSLICED] = 0; /* unspecified */
+ }
+ return loadline[domain];
+ }
+ case PCI_DEVICE_ID_INTEL_CFL_ID_S_S_8: {
+ /* FIXME: Loadline isn't specified for S-series, using H-series default */
+ const uint16_t loadline[NUM_VR_DOMAINS] =
+ VR_CFG_ALL_DOMAINS_LOADLINE(10.3, 1.6, 3.1, 3.1);
+ return loadline[domain];
+ }
+ case PCI_DEVICE_ID_INTEL_CFL_ID_S: /* fallthrough */
+ case PCI_DEVICE_ID_INTEL_CFL_ID_S_WS_6: /* fallthrough */
+ case PCI_DEVICE_ID_INTEL_CFL_ID_S_S_6: /* fallthrough */
+ case PCI_DEVICE_ID_INTEL_CFL_ID_S_S_4: /* fallthrough */
+ case PCI_DEVICE_ID_INTEL_CFL_ID_S_WS_4: /* fallthrough */
+ case PCI_DEVICE_ID_INTEL_CFL_ID_S_DT_4: /* fallthrough */
+ case PCI_DEVICE_ID_INTEL_CFL_ID_S_DT_2: {
+ /* FIXME: Loadline isn't specified for S-series, using H-series default */
+ const uint16_t loadline[NUM_VR_DOMAINS] =
+ VR_CFG_ALL_DOMAINS_LOADLINE(10.3, 2.1, 3.1, 3.1);
+ return loadline[domain];
+ }
+ default:
+ printk(BIOS_ERR, "ERROR: Unknown MCH (0x%x) in VR-config\n", mch_id);
+ }
+ return 0;
+}
+
+static uint16_t get_sku_voltagelimit(int domain)
+{
+ return 1520;
+}
+
void fill_vr_domain_config(void *params,
int domain, const struct vr_config *chip_cfg)
{
@@ -92,8 +307,25 @@ void fill_vr_domain_config(void *params,
vr_params->Psi4Enable[domain] = cfg->psi4enable;
vr_params->ImonSlope[domain] = cfg->imon_slope;
vr_params->ImonOffset[domain] = cfg->imon_offset;
- vr_params->IccMax[domain] = cfg->icc_max;
- vr_params->VrVoltageLimit[domain] = cfg->voltage_limit;
- vr_params->AcLoadline[domain] = cfg->ac_loadline;
- vr_params->DcLoadline[domain] = cfg->dc_loadline;
+
+ /* If board provided non-zero value, use it. */
+ if (cfg->voltage_limit)
+ vr_params->VrVoltageLimit[domain] = cfg->voltage_limit;
+ else
+ vr_params->VrVoltageLimit[domain] = get_sku_voltagelimit(domain);
+
+ if (cfg->icc_max)
+ vr_params->IccMax[domain] = cfg->icc_max;
+ else
+ vr_params->IccMax[domain] = get_sku_icc_max(domain);
+
+ if (cfg->ac_loadline)
+ vr_params->AcLoadline[domain] = cfg->ac_loadline;
+ else
+ vr_params->AcLoadline[domain] = get_sku_ac_dc_loadline(domain);
+
+ if (cfg->dc_loadline)
+ vr_params->DcLoadline[domain] = cfg->dc_loadline;
+ else
+ vr_params->DcLoadline[domain] = get_sku_ac_dc_loadline(domain);
}