summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSean Rhodes <sean@starlabs.systems>2024-04-04 20:02:31 +0100
committerMartin Roth <martin.roth@amd.corp-partner.google.com>2024-08-06 16:53:36 +0000
commita25f310830b34aad29db712ab90b0d2c15ecbb2b (patch)
treefce35b0d188b74c521d47976ab903b35e4a48794 /src
parentc6c75dfbaeff208c17bb47fdede855286e12d857 (diff)
intel/alderlake: Add helper functions for Power Management
Clock Power Management, ASPM and L1 Substates have been configured the same way since Skylake. The main control to enable or disable is Kconfig, and then the level can be overridden in devicetree. Despite the UPDs remaining the same since Skylake, this is not the case for Alder Lake, Raptor Lake and Meteor Lake. Taking `starlabs/starbook` as an example, at the time of this commit it has PCIEXP_CLK_PM, PCIEXP_ASPM and PCIEXP_L1_SUB_STATE enabled. On Comet Lake, this results in the correct configuration, verified with the lspci command: ``` LnkCap: Port #0, Speed 5GT/s, Width x1, ASPM L1, Exit Latency L1 <8us ClockPM+ Surprise- LLActRep- BwNot- ASPMOptComp+ LnkCtl: ASPM L1 Enabled; RCB 64 bytes, Disabled- CommClk+ ExtSynch- ClockPM+ AutWidDis- BWInt- AutBWInt- ``` On Raptor Lake: ``` LnkCap: Port #0, Speed 16GT/s, Width x4, ASPM L1, Exit Latency L1 <64us ClockPM- Surprise- LLActRep- BwNot- ASPMOptComp+ LnkCtl: ASPM Disabled; RCB 64 bytes, Disabled- CommClk+ ``` Clock Power Management, ASPM and L1 Substates are also not configured for CPU root ports. Add helper functions to configure these correctly based on Kconfig, but retain the capability to override the specific levels from devicetree. Change-Id: I9db18859f9a04ad4b7c0c3f7992b09e0f9484a81 Signed-off-by: Sean Rhodes <sean@starlabs.systems> Reviewed-on: https://review.coreboot.org/c/coreboot/+/81638 Reviewed-by: Angel Pons <th3fanbus@gmail.com> Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Nico Huber <nico.h@gmx.de>
Diffstat (limited to 'src')
-rw-r--r--src/soc/intel/alderlake/fsp_params.c123
-rw-r--r--src/soc/intel/common/block/include/intelblocks/pcie_rp.h3
2 files changed, 88 insertions, 38 deletions
diff --git a/src/soc/intel/alderlake/fsp_params.c b/src/soc/intel/alderlake/fsp_params.c
index 2cbf7964b4..dd66f8feb5 100644
--- a/src/soc/intel/alderlake/fsp_params.c
+++ b/src/soc/intel/alderlake/fsp_params.c
@@ -465,44 +465,97 @@ static const SI_PCH_DEVICE_INTERRUPT_CONFIG *pci_irq_to_fsp(size_t *out_count)
}
/*
- * Chip config parameter PcieRpL1Substates uses (UPD value + 1)
- * because UPD value of 0 for PcieRpL1Substates means disabled for FSP.
- * In order to ensure that mainboard setting does not disable L1 substates
- * incorrectly, chip config parameter values are offset by 1 with 0 meaning
- * use FSP UPD default. get_l1_substate_control() ensures that the right UPD
- * value is set in fsp_params.
- * 0: Use FSP UPD default
- * 1: Disable L1 substates
- * 2: Use L1.1
- * 3: Use L1.2 (FSP UPD default)
+ * The PCIe RP ASPM and PCIe L1 Substate UPDs follow the PCI Express Base
+ * Specification 1.1. The UPDs and their default values are consistent
+ * from Skylake through Meteor Lake. However, the default for CPU ports
+ * differs from PCH ports. Use auto and maximum unless overwritten
+ * to make the behaviour consistent.
+ *
+ * +-------------------+--------------------------+-----------+-----------+
+ * | Setting | Option | PCH Ports | CPU Ports |
+ * |-------------------|--------------------------|-----------|-----------|
+ * | PcieRpEnableCpm | Disabled | [Default] | [Default] |
+ * | | Enabled | | |
+ * |-------------------|--------------------------|-----------|-----------|
+ * | PcieRpAspm | PchPcieAspmDisabled | | |
+ * | | PchPcieAspmL0s | | |
+ * | | PchPcieAspmL1 | | |
+ * | | PchPcieAspmL0sL1 | | [Default] |
+ * | | PchPcieAspmAutoConfig | [Default] | |
+ * | | PchPcieAspmMax | | |
+ * |-------------------|--------------------------|-----------|-----------|
+ * | PcieRpL1Substates | Disabled | | |
+ * | | PchPcieL1SubstatesL1_1 | | |
+ * | | PchPcieL1SubstatesL1_1_2 | | [Default] |
+ * | | PchPcieL1SubstatesMax | [Default] | |
+ * +-------------------+--------------------------+-----------+-----------+
*/
-static int get_l1_substate_control(enum L1_substates_control ctl)
+
+static unsigned int adl_aspm_control_to_upd(enum ASPM_control aspm_control)
{
+ /* Disable without Kconfig selected */
+ if (!CONFIG(PCIEXP_ASPM))
+ return UPD_INDEX(ASPM_DISABLE);
+
+ /* Use auto unless overwritten */
+ if (!aspm_control)
+ return UPD_INDEX(ASPM_AUTO);
+
+ return UPD_INDEX(aspm_control);
+}
+
+static unsigned int adl_l1ss_control_to_upd(enum L1_substates_control l1_substates_control)
+{
+ /* Disable without Kconfig selected */
+ if (!CONFIG(PCIEXP_ASPM))
+ return UPD_INDEX(L1_SS_DISABLED);
+
+ /* Don't enable UPD if Kconfig not set */
+ if (!CONFIG(PCIEXP_L1_SUB_STATE))
+ return UPD_INDEX(L1_SS_DISABLED);
+
+ /* L1 Substate should be disabled in compliance mode */
if (CONFIG(SOC_INTEL_COMPLIANCE_TEST_MODE))
- ctl = L1_SS_DISABLED;
- else if ((ctl > L1_SS_L1_2) || (ctl == L1_SS_FSP_DEFAULT))
- ctl = L1_SS_L1_2;
- return ctl - 1;
+ return UPD_INDEX(L1_SS_DISABLED);
+
+ /* Use maximum unless overwritten */
+ if (!l1_substates_control)
+ return UPD_INDEX(L1_SS_L1_2);
+
+ return UPD_INDEX(l1_substates_control);
+}
+
+static void configure_pch_rp_power_management(FSP_S_CONFIG *s_cfg,
+ const struct pcie_rp_config *rp_cfg,
+ unsigned int index)
+{
+ s_cfg->PcieRpEnableCpm[index] = CONFIG(PCIEXP_CLK_PM);
+ s_cfg->PcieRpAspm[index] = adl_aspm_control_to_upd(rp_cfg->pcie_rp_aspm);
+ s_cfg->PcieRpL1Substates[index] = adl_l1ss_control_to_upd(rp_cfg->PcieRpL1Substates);
}
/*
- * Chip config parameter pcie_rp_aspm uses (UPD value + 1) because
- * a UPD value of 0 for pcie_rp_aspm means disabled. In order to ensure
- * that the mainboard setting does not disable ASPM incorrectly, chip
- * config parameter values are offset by 1 with 0 meaning use FSP UPD default.
- * get_aspm_control() ensures that the right UPD value is set in fsp_params.
- * 0: Use FSP UPD default
- * 1: Disable ASPM
- * 2: L0s only
- * 3: L1 only
- * 4: L0s and L1
- * 5: Auto configuration
+ * Starting with Alder Lake, UPDs for Clock Power Management were
+ * introduced for the CPU root ports.
+ *
+ * CpuPcieClockGating:
+ * Disabled
+ * Enabled [Default]
+ *
+ * CpuPciePowerGating
+ * Disabled
+ * Enabled [Default]
+ *
*/
-static unsigned int get_aspm_control(enum ASPM_control ctl)
+static void configure_cpu_rp_power_management(FSP_S_CONFIG *s_cfg,
+ const struct pcie_rp_config *rp_cfg,
+ unsigned int index)
{
- if ((ctl > ASPM_AUTO) || (ctl == ASPM_DEFAULT))
- ctl = ASPM_AUTO;
- return ctl - 1;
+ s_cfg->CpuPcieRpEnableCpm[index] = CONFIG(PCIEXP_CLK_PM);
+ s_cfg->CpuPcieClockGating[index] = CONFIG(PCIEXP_CLK_PM);
+ s_cfg->CpuPciePowerGating[index] = CONFIG(PCIEXP_CLK_PM);
+ s_cfg->CpuPcieRpAspm[index] = adl_aspm_control_to_upd(rp_cfg->pcie_rp_aspm);
+ s_cfg->CpuPcieRpL1Substates[index] = adl_l1ss_control_to_upd(rp_cfg->PcieRpL1Substates);
}
/* This function returns the VccIn Aux Imon IccMax values for ADL and RPL
@@ -912,19 +965,16 @@ static void fill_fsps_pcie_params(FSP_S_CONFIG *s_cfg,
if (!(enable_mask & BIT(i)))
continue;
const struct pcie_rp_config *rp_cfg = &config->pch_pcie_rp[i];
- s_cfg->PcieRpL1Substates[i] =
- get_l1_substate_control(rp_cfg->PcieRpL1Substates);
s_cfg->PcieRpLtrEnable[i] = !!(rp_cfg->flags & PCIE_RP_LTR);
s_cfg->PcieRpAdvancedErrorReporting[i] = !!(rp_cfg->flags & PCIE_RP_AER);
s_cfg->PcieRpHotPlug[i] = !!(rp_cfg->flags & PCIE_RP_HOTPLUG)
|| CONFIG(SOC_INTEL_COMPLIANCE_TEST_MODE);
s_cfg->PcieRpClkReqDetect[i] = !!(rp_cfg->flags & PCIE_RP_CLK_REQ_DETECT);
- if (rp_cfg->pcie_rp_aspm)
- s_cfg->PcieRpAspm[i] = get_aspm_control(rp_cfg->pcie_rp_aspm);
/* PcieRpSlotImplemented default to 1 (slot implemented) in FSP; 0: built-in */
if (!!(rp_cfg->flags & PCIE_RP_BUILT_IN))
s_cfg->PcieRpSlotImplemented[i] = 0;
s_cfg->PcieRpDetectTimeoutMs[i] = rp_cfg->pcie_rp_detect_timeout_ms;
+ configure_pch_rp_power_management(s_cfg, rp_cfg, i);
}
s_cfg->PcieComplianceTestMode = CONFIG(SOC_INTEL_COMPLIANCE_TEST_MODE);
@@ -976,19 +1026,16 @@ static void fill_fsps_cpu_pcie_params(FSP_S_CONFIG *s_cfg,
continue;
const struct pcie_rp_config *rp_cfg = &config->cpu_pcie_rp[i];
- s_cfg->CpuPcieRpL1Substates[i] =
- get_l1_substate_control(rp_cfg->PcieRpL1Substates);
s_cfg->CpuPcieRpLtrEnable[i] = !!(rp_cfg->flags & PCIE_RP_LTR);
s_cfg->CpuPcieRpAdvancedErrorReporting[i] = !!(rp_cfg->flags & PCIE_RP_AER);
s_cfg->CpuPcieRpHotPlug[i] = !!(rp_cfg->flags & PCIE_RP_HOTPLUG)
|| CONFIG(SOC_INTEL_COMPLIANCE_TEST_MODE);
s_cfg->CpuPcieRpDetectTimeoutMs[i] = rp_cfg->pcie_rp_detect_timeout_ms;
s_cfg->PtmEnabled[i] = 0;
- if (rp_cfg->pcie_rp_aspm)
- s_cfg->CpuPcieRpAspm[i] = get_aspm_control(rp_cfg->pcie_rp_aspm);
if (!!(rp_cfg->flags & PCIE_RP_BUILT_IN))
s_cfg->CpuPcieRpSlotImplemented[i] = 0;
+ configure_cpu_rp_power_management(s_cfg, rp_cfg, i);
}
s_cfg->CpuPcieComplianceTestMode = CONFIG(SOC_INTEL_COMPLIANCE_TEST_MODE);
}
diff --git a/src/soc/intel/common/block/include/intelblocks/pcie_rp.h b/src/soc/intel/common/block/include/intelblocks/pcie_rp.h
index dff4d97382..7f7dba6d31 100644
--- a/src/soc/intel/common/block/include/intelblocks/pcie_rp.h
+++ b/src/soc/intel/common/block/include/intelblocks/pcie_rp.h
@@ -37,6 +37,9 @@ enum pcie_clk_src_flags {
PCIE_CLK_LAN = (1 << 1),
};
+/* coreboot enums are off-by-1 to allow for no config in devicetree */
+#define UPD_INDEX(upd) (upd - 1)
+
/* This enum is for passing into an FSP UPD, typically PcieRpL1Substates */
enum L1_substates_control {
L1_SS_FSP_DEFAULT,