summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/soc/intel/jasperlake/chip.h53
-rw-r--r--src/soc/intel/jasperlake/fsp_params.c141
2 files changed, 194 insertions, 0 deletions
diff --git a/src/soc/intel/jasperlake/chip.h b/src/soc/intel/jasperlake/chip.h
index e5e10e3c94d6..70fbbc32b977 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 92ac5b8994f8..c45af27ece72 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);
}