Philipp Deppenwiese has submitted this change. ( https://review.coreboot.org/c/coreboot/+/37466 )
Change subject: soc/intel/cannonlake: Add VR config for CFL, CNL and WHL ......................................................................
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 --- M src/soc/intel/cannonlake/include/soc/vr_config.h M src/soc/intel/cannonlake/vr_config.c 2 files changed, 266 insertions(+), 17 deletions(-)
Approvals: build bot (Jenkins): Verified Philipp Deppenwiese: Looks good to me, approved
Objections: Edward O'Callaghan: I would prefer that you didn't submit this
diff --git a/src/soc/intel/cannonlake/include/soc/vr_config.h b/src/soc/intel/cannonlake/include/soc/vr_config.h index 8bcf001..1390b17 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 @@ 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 @@ 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 25270d8..7096b62 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 @@ .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 @@ .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 @@ .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 @@ .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 @@ 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); }