diff options
author | Aaron Durbin <adurbin@chromium.org> | 2016-08-25 15:42:04 -0500 |
---|---|---|
committer | Aaron Durbin <adurbin@chromium.org> | 2016-08-30 03:15:32 +0200 |
commit | 41a3fa66a0d8a6b134ceb17b8f34520cad7643a4 (patch) | |
tree | 7e28a0a57b23ec86b10a3ee6d2d8e4699797fffd | |
parent | a1e39248692e659d0cdf397251a8c138d290d334 (diff) | |
download | coreboot-41a3fa66a0d8a6b134ceb17b8f34520cad7643a4.tar.xz |
soc/intel/apollolake: add option for SLP_S3_L assertion width
In order to provide time for the S0 rails to discharge one needs
to be able to set the SLP_S3_L assertion width. The hardware default
is 60 microcseconds which is not slow enough on most boards. Therefore
provide a devicetree option for the mainboard to set accordingly
for its needs. An unset value in devicetree results in a conservative
2 second SLP_S3_L duration.
BUG=chrome-os-partner:56581
Change-Id: I6c6df2f7a181746708ab7897249ae82109c55f50
Signed-off-by: Aaron Durbin <adurbin@chromium.org>
Reviewed-on: https://review.coreboot.org/16326
Tested-by: build bot (Jenkins)
Reviewed-by: Paul Menzel <paulepanter@users.sourceforge.net>
Reviewed-by: Andrey Petrov <andrey.petrov@intel.com>
-rw-r--r-- | src/soc/intel/apollolake/chip.h | 3 | ||||
-rw-r--r-- | src/soc/intel/apollolake/include/soc/pm.h | 6 | ||||
-rw-r--r-- | src/soc/intel/apollolake/pmc.c | 59 |
3 files changed, 68 insertions, 0 deletions
diff --git a/src/soc/intel/apollolake/chip.h b/src/soc/intel/apollolake/chip.h index 16c3aeb76f..22217a4dea 100644 --- a/src/soc/intel/apollolake/chip.h +++ b/src/soc/intel/apollolake/chip.h @@ -106,6 +106,9 @@ struct soc_intel_apollolake_config { /* Enable DPTF support */ int dptf_enable; + + /* SLP S3 minimum assertion width. */ + int slp_s3_assertion_width_usecs; }; #endif /* _SOC_APOLLOLAKE_CHIP_H_ */ diff --git a/src/soc/intel/apollolake/include/soc/pm.h b/src/soc/intel/apollolake/include/soc/pm.h index b3da3aa628..3ee7403b9b 100644 --- a/src/soc/intel/apollolake/include/soc/pm.h +++ b/src/soc/intel/apollolake/include/soc/pm.h @@ -151,6 +151,12 @@ #define RPS (1 << 2) #define GEN_PMCON2 0x1024 #define GEN_PMCON3 0x1028 +# define SLP_S3_ASSERT_WIDTH_SHIFT 10 +# define SLP_S3_ASSERT_MASK (0x3 << SLP_S3_ASSERT_WIDTH_SHIFT) +# define SLP_S3_ASSERT_60_USEC 0x0 +# define SLP_S3_ASSERT_1_MSEC 0x1 +# define SLP_S3_ASSERT_50_MSEC 0x2 +# define SLP_S3_ASSERT_2_SEC 0x3 #define ETR 0x1048 # define CF9_LOCK (1 << 31) # define CF9_GLB_RST (1 << 20) diff --git a/src/soc/intel/apollolake/pmc.c b/src/soc/intel/apollolake/pmc.c index 30b7677a92..c58314494c 100644 --- a/src/soc/intel/apollolake/pmc.c +++ b/src/soc/intel/apollolake/pmc.c @@ -25,6 +25,7 @@ #include <soc/gpio.h> #include <soc/pci_devs.h> #include <soc/pm.h> +#include <timer.h> #include "chip.h" /* @@ -132,12 +133,70 @@ static void pch_set_acpi_mode(void) } } +static int choose_slp_s3_assertion_width(int width_usecs) +{ + int i; + static const struct { + int max_width; + int value; + } slp_s3_settings[] = { + { + .max_width = 60, + .value = SLP_S3_ASSERT_60_USEC, + }, + { + .max_width = 1 * USECS_PER_MSEC, + .value = SLP_S3_ASSERT_1_MSEC, + }, + { + .max_width = 50 * USECS_PER_MSEC, + .value = SLP_S3_ASSERT_50_MSEC, + }, + { + .max_width = 2 * USECS_PER_SEC, + .value = SLP_S3_ASSERT_2_SEC, + }, + }; + + for (i = 0; i < ARRAY_SIZE(slp_s3_settings); i++) { + if (width_usecs <= slp_s3_settings[i].max_width) + break; + } + + /* Provide conservative default if nothing set in devicetree + * or requested assertion width too large. */ + if (width_usecs <= 0 || i == ARRAY_SIZE(slp_s3_settings)) + i = ARRAY_SIZE(slp_s3_settings) - 1; + + printk(BIOS_DEBUG, "SLP S3 assertion width: %d usecs\n", + slp_s3_settings[i].max_width); + + return slp_s3_settings[i].value; +} + +static void set_slp_s3_assertion_width(int width_usecs) +{ + uint32_t reg; + uintptr_t gen_pmcon3 = get_pmc_mmio_bar() + GEN_PMCON3; + int setting = choose_slp_s3_assertion_width(width_usecs); + + reg = read32((void *)gen_pmcon3); + reg &= ~SLP_S3_ASSERT_MASK; + reg |= setting << SLP_S3_ASSERT_WIDTH_SHIFT; + write32((void *)gen_pmcon3, reg); +} + static void pmc_init(struct device *dev) { + const struct soc_intel_apollolake_config *cfg = dev->chip_info; + /* Set up GPE configuration */ pmc_gpe_init(); pch_set_acpi_mode(); + if (cfg != NULL) + set_slp_s3_assertion_width(cfg->slp_s3_assertion_width_usecs); + /* Log power state */ pch_log_state(); } |