soc/intel/cannonlake: Add PchPmPwrCycDur to chip options
Add PchPmPwrCycDur to chip options to control the UPD FSPS PchPmPwrCycDur from devicetree. The UPD determines the minimum time a platform will stay in reset during host partition reset with power cycle or global reset. This patch also ensures configured PchPmPwrCycDur value doesn't violate the PCH EDS specification. TEST=Verified on Hatch and Puff boards Signed-off-by: Sridhar Siricilla <sridhar.siricilla@intel.com> Change-Id: I55e836c78fab34e34d57b04428a1498b7dc7174b Reviewed-on: https://review.coreboot.org/c/coreboot/+/42440 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Edward O'Callaghan <quasisec@chromium.org>
This commit is contained in:
parent
d95dba0ce3
commit
e40b9481e6
|
@ -314,6 +314,23 @@ struct soc_intel_cannonlake_config {
|
|||
*/
|
||||
uint8_t PchPmSlpAMinAssert;
|
||||
|
||||
/*
|
||||
* PCH PM Reset Power Cycle Duration
|
||||
* 0 = 4s
|
||||
* 1 = 1s
|
||||
* 2 = 2s
|
||||
* 3 = 3s
|
||||
* 4 = 4s (default)
|
||||
*
|
||||
* 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;
|
||||
|
||||
/*
|
||||
* SerialIO device mode selection:
|
||||
*
|
||||
|
|
|
@ -32,6 +32,39 @@ 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 4
|
||||
|
||||
/*
|
||||
* Given an enum for PCH_SERIAL_IO_MODE, 1 needs to be subtracted to get the FSP
|
||||
* UPD expected value for Serial IO since valid enum index starts from 1.
|
||||
|
@ -57,6 +90,93 @@ static uint8_t get_param_value(const config_t *config, uint32_t dev_offset)
|
|||
}
|
||||
|
||||
#if CONFIG(SOC_INTEL_COMETLAKE)
|
||||
static enum min_assrt_dur get_high_asst_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;
|
||||
}
|
||||
|
||||
static void get_min_assrt_dur(uint8_t slp_s4_min_asst, uint8_t slp_s3_min_asst,
|
||||
uint8_t slp_a_min_asst, uint8_t pm_pwr_cyc_dur,
|
||||
struct cfg_assrt_dur *cfg_assrt_dur)
|
||||
{
|
||||
/*
|
||||
* Ensure slp_x_dur_list[] elements are in sync with devicetree config to FSP encoded
|
||||
* values.
|
||||
* slp_s4_asst_dur_list : 1s, 1s, 2s, 3s, 4s(Default)
|
||||
*/
|
||||
const enum min_assrt_dur slp_s4_asst_dur_list[] = {
|
||||
MinAssrtDur1s, MinAssrtDur1s, MinAssrtDur2s, MinAssrtDur3s, MinAssrtDur4s
|
||||
};
|
||||
|
||||
/* slp_s3_asst_dur_list: 50ms, 60us, 50ms (Default), 2s */
|
||||
const enum min_assrt_dur slp_s3_asst_dur_list[] = {
|
||||
MinAssrtDur50ms, MinAssrtDur60us, MinAssrtDur50ms, MinAssrtDur2s
|
||||
};
|
||||
|
||||
/* slp_a_asst_dur_list: 2s, 0s, 4s, 98ms, 2s(Default) */
|
||||
const enum min_assrt_dur slp_a_asst_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_asst < ARRAY_SIZE(slp_s4_asst_dur_list))
|
||||
cfg_assrt_dur->slp_s4 = slp_s4_asst_dur_list[slp_s4_min_asst];
|
||||
|
||||
if (slp_s3_min_asst < ARRAY_SIZE(slp_s3_asst_dur_list))
|
||||
cfg_assrt_dur->slp_s3 = slp_s3_asst_dur_list[slp_s3_min_asst];
|
||||
|
||||
if (slp_a_min_asst < ARRAY_SIZE(slp_a_asst_dur_list))
|
||||
cfg_assrt_dur->slp_a = slp_a_asst_dur_list[slp_a_min_asst];
|
||||
|
||||
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];
|
||||
}
|
||||
|
||||
|
||||
static uint8_t get_pm_pwr_cyc_dur(uint8_t slp_s4_min_asst, uint8_t slp_s3_min_asst,
|
||||
uint8_t slp_a_min_asst, uint8_t pm_pwr_cyc_dur)
|
||||
{
|
||||
/* Sets default minimum asserton duration values */
|
||||
struct cfg_assrt_dur cfg_assrt_dur = {
|
||||
.slp_a = MinAssrtDur2s,
|
||||
.slp_s4 = MinAssrtDur4s,
|
||||
.slp_s3 = MinAssrtDur50ms,
|
||||
.pm_pwr_cyc_dur = MinAssrtDur4s
|
||||
};
|
||||
|
||||
enum min_assrt_dur high_asst_width;
|
||||
|
||||
/* Convert assertion durations from register-encoded to microseconds */
|
||||
get_min_assrt_dur(slp_s4_min_asst, slp_s3_min_asst, slp_a_min_asst, pm_pwr_cyc_dur,
|
||||
&cfg_assrt_dur);
|
||||
|
||||
/* Get the higher assertion duration among PCH EDS specified signals for pwr_cyc_dur */
|
||||
high_asst_width = get_high_asst_width(&cfg_assrt_dur);
|
||||
|
||||
if (cfg_assrt_dur.pm_pwr_cyc_dur >= high_asst_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;
|
||||
}
|
||||
|
||||
|
||||
static void parse_devicetree_param(const config_t *config, FSP_S_CONFIG *params)
|
||||
{
|
||||
uint32_t dev_offset = 0;
|
||||
|
@ -412,6 +532,13 @@ void platform_fsp_silicon_init_params_cb(FSPS_UPD *supd)
|
|||
if (config->PchPmSlpAMinAssert)
|
||||
params->PchPmSlpAMinAssert = config->PchPmSlpAMinAssert;
|
||||
|
||||
#if CONFIG(SOC_INTEL_COMETLAKE)
|
||||
if (config->PchPmPwrCycDur)
|
||||
params->PchPmPwrCycDur = get_pm_pwr_cyc_dur(config->PchPmSlpS4MinAssert,
|
||||
config->PchPmSlpS3MinAssert, config->PchPmSlpAMinAssert,
|
||||
config->PchPmPwrCycDur);
|
||||
#endif
|
||||
|
||||
/* Set TccActivationOffset */
|
||||
tconfig->TccActivationOffset = config->tcc_offset;
|
||||
|
||||
|
|
Loading…
Reference in New Issue