diff options
author | Sean Rhodes <sean@starlabs.systems> | 2024-04-04 20:02:31 +0100 |
---|---|---|
committer | Martin Roth <martin.roth@amd.corp-partner.google.com> | 2024-08-06 16:53:36 +0000 |
commit | a25f310830b34aad29db712ab90b0d2c15ecbb2b (patch) | |
tree | fce35b0d188b74c521d47976ab903b35e4a48794 /src/soc/intel | |
parent | c6c75dfbaeff208c17bb47fdede855286e12d857 (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/soc/intel')
-rw-r--r-- | src/soc/intel/alderlake/fsp_params.c | 123 | ||||
-rw-r--r-- | src/soc/intel/common/block/include/intelblocks/pcie_rp.h | 3 |
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, |