diff options
-rw-r--r-- | src/soc/intel/baytrail/baytrail/pmc.h | 7 | ||||
-rw-r--r-- | src/soc/intel/baytrail/romstage/raminit.c | 27 | ||||
-rw-r--r-- | src/soc/intel/baytrail/romstage/romstage.c | 49 |
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"); |