summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/soc/intel/skylake/include/soc/pm.h11
-rw-r--r--src/soc/intel/skylake/romstage/power_state.c18
2 files changed, 27 insertions, 2 deletions
diff --git a/src/soc/intel/skylake/include/soc/pm.h b/src/soc/intel/skylake/include/soc/pm.h
index 4d9abcb20d..2e722bf206 100644
--- a/src/soc/intel/skylake/include/soc/pm.h
+++ b/src/soc/intel/skylake/include/soc/pm.h
@@ -21,6 +21,9 @@
#ifndef _SOC_PM_H_
#define _SOC_PM_H_
+#include <arch/io.h>
+#include <soc/pmc.h>
+
/* ACPI_BASE_ADDRESS / PMBASE */
#define PM1_STS 0x00
@@ -169,4 +172,12 @@ uint8_t *pmc_mmio_regs(void);
/* Get base address of TCO I/O registers. */
uint16_t pmc_tco_regs(void);
+static inline int deep_s3_enabled(void)
+{
+ uint32_t deep_s3_pol;
+
+ deep_s3_pol = read32(pmc_mmio_regs() + S3_PWRGATE_POL);
+ return !!(deep_s3_pol & (S3DC_GATE_SUS | S3AC_GATE_SUS));
+}
+
#endif
diff --git a/src/soc/intel/skylake/romstage/power_state.c b/src/soc/intel/skylake/romstage/power_state.c
index 4ffa381b11..5c94e89fd7 100644
--- a/src/soc/intel/skylake/romstage/power_state.c
+++ b/src/soc/intel/skylake/romstage/power_state.c
@@ -74,8 +74,22 @@ static int prev_sleep_state(struct chipset_power_state *ps)
outl(ps->pm1_cnt & ~(SLP_TYP), ACPI_BASE_ADDRESS + PM1_CNT);
}
- if (ps->gen_pmcon_b & (PWR_FLR | SUS_PWR_FLR))
- prev_sleep_state = SLEEP_STATE_S5;
+ /*
+ * If waking from S3 determine if deep S3 is enabled. If not,
+ * need to check both deep sleep well and normal suspend well.
+ * Otherwise just check deep sleep well.
+ */
+ if (prev_sleep_state == SLEEP_STATE_S3) {
+ /* PWR_FLR represents deep sleep power well loss. */
+ uint32_t mask = PWR_FLR;
+
+ /* If deep s3 isn't enabled check the suspend well too. */
+ if (!deep_s3_enabled())
+ mask |= SUS_PWR_FLR;
+
+ if (ps->gen_pmcon_b & mask)
+ prev_sleep_state = SLEEP_STATE_S5;
+ }
return prev_sleep_state;
}