summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/soc/intel/baytrail/baytrail/pmc.h7
-rw-r--r--src/soc/intel/baytrail/romstage/raminit.c27
-rw-r--r--src/soc/intel/baytrail/romstage/romstage.c49
3 files changed, 77 insertions, 6 deletions
diff --git a/src/soc/intel/baytrail/baytrail/pmc.h b/src/soc/intel/baytrail/baytrail/pmc.h
index 92edb6ef64..1a7588cc20 100644
--- a/src/soc/intel/baytrail/baytrail/pmc.h
+++ b/src/soc/intel/baytrail/baytrail/pmc.h
@@ -24,9 +24,11 @@
#define IOCOM1 0x3f8
/* Memory mapped IO registers behind PMC_BASE_ADDRESS */
-#define GEN_PMCONF1 0x20
+#define GEN_PMCON1 0x20
# define AFTERG3_EN (1 << 0)
# define UART_EN (1 << 24)
+# define PWR_FLR (1 << 16)
+# define SUS_PWR_FLR (1 << 14)
#define ETR 0x48
# define CF9LOCK (1 << 31)
# define LTR_DEF (1 << 22)
@@ -86,7 +88,8 @@
#define TMROF_EN (1 << 0)
#define PM1_CNT 0x04
#define SLP_EN (1 << 13)
-#define SLP_TYP (7 << 10)
+#define SLP_TYP_SHIFT 10
+#define SLP_TYP (7 << SLP_TYP_SHIFT)
#define SLP_TYP_S0 0
#define SLP_TYP_S1 1
#define SLP_TYP_S3 5
diff --git a/src/soc/intel/baytrail/romstage/raminit.c b/src/soc/intel/baytrail/romstage/raminit.c
index 98d389eb2c..017f37d3ef 100644
--- a/src/soc/intel/baytrail/romstage/raminit.c
+++ b/src/soc/intel/baytrail/romstage/raminit.c
@@ -18,7 +18,9 @@
*/
#include <stddef.h>
+#include <arch/hlt.h>
#include <arch/io.h>
+#include <bootmode.h>
#include <cbfs.h>
#include <cbmem.h>
#include <console/console.h>
@@ -28,8 +30,14 @@
#include <baytrail/iomap.h>
#include <baytrail/iosf.h>
#include <baytrail/pci_devs.h>
+#include <baytrail/reset.h>
#include <baytrail/romstage.h>
+static void reset_system(void)
+{
+ warm_reset();
+ while(1) { hlt(); }
+}
static void enable_smbus(void)
{
@@ -111,9 +119,16 @@ void raminit(struct mrc_params *mp, int prev_sleep_state)
mp->console_out = &send_to_console;
mp->prev_sleep_state = prev_sleep_state;
- if (!mrc_cache_get_current(&cache)) {
+ if (recovery_mode_enabled()) {
+ printk(BIOS_DEBUG, "Recovery mode: not using MRC cache.\n");
+ } else if (!mrc_cache_get_current(&cache)) {
mp->saved_data_size = cache->size;
mp->saved_data = &cache->data[0];
+ } else if (prev_sleep_state == 3) {
+ /* If waking from S3 and no cache then. */
+ printk(BIOS_DEBUG, "No MRC cache found in S3 resume path.\n");
+ post_code(POST_RESUME_FAILURE);
+ reset_system();
} else {
printk(BIOS_DEBUG, "No MRC cache found.\n");
}
@@ -132,7 +147,15 @@ void raminit(struct mrc_params *mp, int prev_sleep_state)
print_dram_info();
- cbmem_initialize_empty();
+ if (prev_sleep_state != 3) {
+ cbmem_initialize_empty();
+ } else if (cbmem_initialize()) {
+ #if CONFIG_HAVE_ACPI_RESUME
+ printk(BIOS_DEBUG, "Failed to recover CBMEM in S3 resume.\n");
+ /* Failed S3 resume, reset to come up cleanly */
+ reset_system();
+ #endif
+ }
printk(BIOS_DEBUG, "MRC Wrapper returned %d\n", ret);
printk(BIOS_DEBUG, "MRC data at %p %d bytes\n", mp->data_to_save,
diff --git a/src/soc/intel/baytrail/romstage/romstage.c b/src/soc/intel/baytrail/romstage/romstage.c
index 5af9bf4566..969e8487f9 100644
--- a/src/soc/intel/baytrail/romstage/romstage.c
+++ b/src/soc/intel/baytrail/romstage/romstage.c
@@ -36,6 +36,7 @@
#include <baytrail/iomap.h>
#include <baytrail/lpc.h>
#include <baytrail/pci_devs.h>
+#include <baytrail/pmc.h>
#include <baytrail/reset.h>
#include <baytrail/romstage.h>
#include <baytrail/smm.h>
@@ -139,10 +140,50 @@ void * asmlinkage romstage_main(unsigned long bist,
return setup_stack_and_mttrs();
}
+/* Return 0, 3, or 5 to indicate the previous sleep state. */
+static int chipset_prev_sleep_state(void)
+{
+ uint16_t pm1_sts;
+ uint32_t pm1_cnt;
+ uint32_t gen_pmcon1;
+ /* Default to S0. */
+ int prev_sleep_state = 0;
+
+ pm1_sts = inw(ACPI_BASE_ADDRESS + PM1_STS);
+ pm1_cnt = inl(ACPI_BASE_ADDRESS + PM1_CNT);
+
+ if (pm1_sts & WAK_STS) {
+ switch ((pm1_cnt & SLP_TYP) >> SLP_TYP_SHIFT) {
+ #if CONFIG_HAVE_ACPI_RESUME
+ case SLP_TYP_S3:
+ prev_sleep_state = 3;
+ break;
+ #endif
+ case SLP_TYP_S5:
+ prev_sleep_state = 5;
+ }
+ /* Clear SLP_TYP. */
+ outl(pm1_cnt & ~(SLP_TYP), ACPI_BASE_ADDRESS + PM1_CNT);
+ }
+
+ gen_pmcon1 = read32(PMC_BASE_ADDRESS + GEN_PMCON1);
+ if (gen_pmcon1 & (PWR_FLR | SUS_PWR_FLR)) {
+ /* Clear power failure bits. */
+ write32(PMC_BASE_ADDRESS + GEN_PMCON1, gen_pmcon1);
+ prev_sleep_state = 5;
+ }
+
+ printk(BIOS_DEBUG, "pm1_sts = %04x pm1_cnt = %08x gen_pmcon1 = %08x\n",
+ pm1_sts, pm1_cnt, gen_pmcon1);
+
+ return prev_sleep_state;
+}
+
/* Entry from the mainboard. */
void romstage_common(struct romstage_params *params)
{
struct romstage_handoff *handoff;
+ int prev_sleep_state;
mark_ts(params, timestamp_get());
@@ -150,14 +191,18 @@ void romstage_common(struct romstage_params *params)
boot_count_increment();
#endif
+ prev_sleep_state = chipset_prev_sleep_state();
+
+ printk(BIOS_DEBUG, "prev_sleep_state = S%d\n", prev_sleep_state);
+
/* Initialize RAM */
- raminit(params->mrc_params, 5);
+ raminit(params->mrc_params, prev_sleep_state);
mark_ts(params, timestamp_get());
handoff = romstage_handoff_find_or_add();
if (handoff != NULL)
- handoff->s3_resume = 0;
+ handoff->s3_resume = (prev_sleep_state == 3);
else
printk(BIOS_DEBUG, "Romstage handoff structure not added!\n");