From 7aee5c67a11bed7ae028aac6752ed2f31868b43e Mon Sep 17 00:00:00 2001 From: V Sowmya Date: Fri, 24 Jul 2020 08:58:14 +0530 Subject: soc/intel/jasperlake: Add FSP UPDs for minimum assertion widths Add the FSP UPDs for the chipset minimum assertion widths and Power cycle duration to the chip options which can be configured per mainboard. * PchPmSlpS3MinAssert: SLP_S3 Minimum Assertion Width Policy * PchPmSlpS4MinAssert: SLP_S4 Minimum Assertion Width Policy * PchPmSlpSusMinAssert: SLP_SUS Minimum Assertion Width Policy * PchPmSlpAMinAssert: SLP_A Minimum Assertion Width Policy * PchPmPwrCycDur: PCH PM Reset Power Cycle Duration * Check to avoid violating the PCH EDS recommendation for the PchPmPwrCycDur setting. BUG=b:159104150 Change-Id: I042e8e34b7dfda3bc21e5f2e6727cb7692ffc7f7 Signed-off-by: V Sowmya Reviewed-on: https://review.coreboot.org/c/coreboot/+/43791 Tested-by: build bot (Jenkins) Reviewed-by: Aamir Bohra Reviewed-by: Sridhar Siricilla Reviewed-by: Maulik V Vaghela Reviewed-by: Ronak Kanabar Reviewed-by: Subrata Banik --- src/soc/intel/jasperlake/chip.h | 53 +++++++++++++ src/soc/intel/jasperlake/fsp_params.c | 141 ++++++++++++++++++++++++++++++++++ 2 files changed, 194 insertions(+) (limited to 'src') diff --git a/src/soc/intel/jasperlake/chip.h b/src/soc/intel/jasperlake/chip.h index e5e10e3c94..70fbbc32b9 100644 --- a/src/soc/intel/jasperlake/chip.h +++ b/src/soc/intel/jasperlake/chip.h @@ -291,6 +291,59 @@ struct soc_intel_jasperlake_config { * for the platforms with soldered down SOC. */ uint8_t SkipCpuReplacementCheck; + + /* + * SLP_S3 Minimum Assertion Width Policy + * 1 = 60us + * 2 = 1ms + * 3 = 50ms (default) + * 4 = 2s + */ + uint8_t PchPmSlpS3MinAssert; + + /* + * SLP_S4 Minimum Assertion Width Policy + * 1 = 1s (default) + * 2 = 2s + * 3 = 3s + * 4 = 4s + */ + uint8_t PchPmSlpS4MinAssert; + + /* + * SLP_SUS Minimum Assertion Width Policy + * 1 = 0ms + * 2 = 500ms + * 3 = 1s + * 4 = 4s (default) + */ + uint8_t PchPmSlpSusMinAssert; + + /* + * SLP_A Minimum Assertion Width Policy + * 1 = 0ms + * 2 = 4s + * 3 = 98ms + * 4 = 2s (default) + */ + uint8_t PchPmSlpAMinAssert; + + /* + * PCH PM Reset Power Cycle Duration + * 0 = 4s (default) + * 1 = 1s + * 2 = 2s + * 3 = 3s + * 4 = 4s + * + * NOTE: Duration programmed in the PchPmPwrCycDur should never be smaller than the + * stretch duration programmed in the following registers: + * - GEN_PMCON_A.SLP_S3_MIN_ASST_WDTH (PchPmSlpS3MinAssert) + * - GEN_PMCON_A.S4MAW (PchPmSlpS4MinAssert) + * - PM_CFG.SLP_A_MIN_ASST_WDTH (PchPmSlpAMinAssert) + * - PM_CFG.SLP_LAN_MIN_ASST_WDTH + */ + uint8_t PchPmPwrCycDur; }; typedef struct soc_intel_jasperlake_config config_t; diff --git a/src/soc/intel/jasperlake/fsp_params.c b/src/soc/intel/jasperlake/fsp_params.c index 92ac5b8994..c45af27ece 100644 --- a/src/soc/intel/jasperlake/fsp_params.c +++ b/src/soc/intel/jasperlake/fsp_params.c @@ -42,6 +42,38 @@ static const pci_devfn_t serial_io_dev[] = { PCH_DEVFN_UART2 }; +/* List of Minimum Assertion durations in microseconds */ +enum min_assrt_dur { + MinAssrtDur0s = 0, + MinAssrtDur60us = 60, + MinAssrtDur1ms = 1000, + MinAssrtDur50ms = 50000, + MinAssrtDur98ms = 98000, + MinAssrtDur500ms = 500000, + MinAssrtDur1s = 1000000, + MinAssrtDur2s = 2000000, + MinAssrtDur3s = 3000000, + MinAssrtDur4s = 4000000, +}; + +/* Signal Assertion duration values */ +struct cfg_assrt_dur { + /* Minimum assertion duration of SLP_A signal */ + enum min_assrt_dur slp_a; + + /* Minimum assertion duration of SLP_4 signal */ + enum min_assrt_dur slp_s4; + + /* Minimum assertion duration of SLP_3 signal */ + enum min_assrt_dur slp_s3; + + /* PCH PM Power Cycle duration */ + enum min_assrt_dur pm_pwr_cyc_dur; +}; + +/* Default value of PchPmPwrCycDur */ +#define PCH_PM_PWR_CYC_DUR 0 + static void parse_devicetree(FSP_S_CONFIG *params) { const struct soc_intel_jasperlake_config *config = config_of_soc(); @@ -77,6 +109,99 @@ static void parse_devicetree(FSP_S_CONFIG *params) sizeof(config->SerialIoUartMode)); } +/* This function returns the highest assertion duration of the SLP_Sx assertion widths */ +static enum min_assrt_dur get_high_assrt_width(const struct cfg_assrt_dur *cfg_assrt_dur) +{ + enum min_assrt_dur max_assert_dur = cfg_assrt_dur->slp_s4; + + if (max_assert_dur < cfg_assrt_dur->slp_s3) + max_assert_dur = cfg_assrt_dur->slp_s3; + + if (max_assert_dur < cfg_assrt_dur->slp_a) + max_assert_dur = cfg_assrt_dur->slp_a; + + return max_assert_dur; +} + +/* This function converts assertion durations from register-encoded to microseconds */ +static void get_min_assrt_dur(uint8_t slp_s4_min_assrt, uint8_t slp_s3_min_assrt, + uint8_t slp_a_min_assrt, uint8_t pm_pwr_cyc_dur, + struct cfg_assrt_dur *cfg_assrt_dur) +{ + /* + * Ensure slp_x_dur_list[] elements in the devicetree config are in sync with + * FSP encoded values. + */ + + /* slp_s4_assrt_dur_list : 1s, 1s(default), 2s, 3s, 4s */ + const enum min_assrt_dur slp_s4_assrt_dur_list[] = { + MinAssrtDur1s, MinAssrtDur1s, MinAssrtDur2s, MinAssrtDur3s, MinAssrtDur4s + }; + + /* slp_s3_assrt_dur_list: 50ms, 60us, 1ms, 50ms (Default), 2s */ + const enum min_assrt_dur slp_s3_assrt_dur_list[] = { + MinAssrtDur50ms, MinAssrtDur60us, MinAssrtDur1ms, MinAssrtDur50ms, MinAssrtDur2s + }; + + /* slp_a_assrt_dur_list: 2s, 0s, 4s, 98ms, 2s(Default) */ + const enum min_assrt_dur slp_a_assrt_dur_list[] = { + MinAssrtDur2s, MinAssrtDur0s, MinAssrtDur4s, MinAssrtDur98ms, MinAssrtDur2s + }; + + /* pm_pwr_cyc_dur_list: 4s(Default), 1s, 2s, 3s, 4s */ + const enum min_assrt_dur pm_pwr_cyc_dur_list[] = { + MinAssrtDur4s, MinAssrtDur1s, MinAssrtDur2s, MinAssrtDur3s, MinAssrtDur4s + }; + + /* Get signal assertion width */ + if (slp_s4_min_assrt < ARRAY_SIZE(slp_s4_assrt_dur_list)) + cfg_assrt_dur->slp_s4 = slp_s4_assrt_dur_list[slp_s4_min_assrt]; + + if (slp_s3_min_assrt < ARRAY_SIZE(slp_s3_assrt_dur_list)) + cfg_assrt_dur->slp_s3 = slp_s3_assrt_dur_list[slp_s3_min_assrt]; + + if (slp_a_min_assrt < ARRAY_SIZE(slp_a_assrt_dur_list)) + cfg_assrt_dur->slp_a = slp_a_assrt_dur_list[slp_a_min_assrt]; + + if (pm_pwr_cyc_dur < ARRAY_SIZE(pm_pwr_cyc_dur_list)) + cfg_assrt_dur->pm_pwr_cyc_dur = pm_pwr_cyc_dur_list[pm_pwr_cyc_dur]; +} + +/* This function ensures that the duration programmed in the PchPmPwrCycDur will never be + * smaller than the SLP_Sx assertion widths. + * If the pm_pwr_cyc_dur is less than any of the SLP_Sx assertion widths then it returns the + * default value PCH_PM_PWR_CYC_DUR. + */ +static uint8_t get_pm_pwr_cyc_dur(uint8_t slp_s4_min_assrt, uint8_t slp_s3_min_assrt, + uint8_t slp_a_min_assrt, uint8_t pm_pwr_cyc_dur) +{ + /* Set default values for the minimum assertion duration */ + struct cfg_assrt_dur cfg_assrt_dur = { + .slp_a = MinAssrtDur2s, + .slp_s4 = MinAssrtDur1s, + .slp_s3 = MinAssrtDur50ms, + .pm_pwr_cyc_dur = MinAssrtDur4s + }; + + enum min_assrt_dur high_assrt_width; + + /* Convert assertion durations from register-encoded to microseconds */ + get_min_assrt_dur(slp_s4_min_assrt, slp_s3_min_assrt, slp_a_min_assrt, pm_pwr_cyc_dur, + &cfg_assrt_dur); + + /* Get the highest assertion duration among PCH EDS specified signals for pwr_cyc_dur */ + high_assrt_width = get_high_assrt_width(&cfg_assrt_dur); + + if (cfg_assrt_dur.pm_pwr_cyc_dur >= high_assrt_width) + return pm_pwr_cyc_dur; + + printk(BIOS_DEBUG, + "Set PmPwrCycDur to 4s as configured PmPwrCycDur (%d) violates PCH EDS " + "spec\n", pm_pwr_cyc_dur); + + return PCH_PM_PWR_CYC_DUR; +} + /* UPD parameters to be initialized before SiliconInit */ void platform_fsp_silicon_init_params_cb(FSPS_UPD *supd) { @@ -204,6 +329,22 @@ void platform_fsp_silicon_init_params_cb(FSPS_UPD *supd) /* Provide correct UART number for FSP debug logs */ params->SerialIoDebugUartNumber = CONFIG_UART_FOR_CONSOLE; + /* Apply minimum assertion width settings if non-zero */ + if (config->PchPmSlpS3MinAssert) + params->PchPmSlpS3MinAssert = config->PchPmSlpS3MinAssert; + if (config->PchPmSlpS4MinAssert) + params->PchPmSlpS4MinAssert = config->PchPmSlpS4MinAssert; + if (config->PchPmSlpSusMinAssert) + params->PchPmSlpSusMinAssert = config->PchPmSlpSusMinAssert; + if (config->PchPmSlpAMinAssert) + params->PchPmSlpAMinAssert = config->PchPmSlpAMinAssert; + + /* Set Power Cycle Duration */ + if (config->PchPmPwrCycDur) + params->PchPmPwrCycDur = get_pm_pwr_cyc_dur(config->PchPmSlpS4MinAssert, + config->PchPmSlpS3MinAssert, config->PchPmSlpAMinAssert, + config->PchPmPwrCycDur); + /* Override/Fill FSP Silicon Param for mainboard */ mainboard_silicon_init_params(params); } -- cgit v1.2.3