From 2da008afa622e5469a34cd9d9712d498e84e4ea8 Mon Sep 17 00:00:00 2001 From: Ravi Sarawadi Date: Wed, 27 Apr 2016 15:20:14 -0700 Subject: soc/apollolake: Set BootMode based on previous sleep state - fill_power_state makes a copy of the current snapshot of power management registers in CAR variable "power_state" for use in ramstage - migrate_power_state adds CAR variable "power_state" to CBMEM (CBMEM_ID_POWER_STATE) - s3_resume state is updated in romstage_handoff block Change-Id: I842b85c5e562893b58cd3b3f6432695fbd4430bf Signed-off-by: Hannah Williams Signed-off-by: Ravi Sarawadi Reviewed-on: https://review.coreboot.org/14550 Tested-by: build bot (Jenkins) Reviewed-by: Aaron Durbin --- src/soc/intel/apollolake/romstage.c | 70 +++++++++++++++++++++++++++++++------ 1 file changed, 60 insertions(+), 10 deletions(-) (limited to 'src/soc/intel/apollolake/romstage.c') diff --git a/src/soc/intel/apollolake/romstage.c b/src/soc/intel/apollolake/romstage.c index 42af6c08f8..6b49bbd961 100644 --- a/src/soc/intel/apollolake/romstage.c +++ b/src/soc/intel/apollolake/romstage.c @@ -16,28 +16,34 @@ * GNU General Public License for more details. */ -#include #include +#include #include #include +#include #include #include #include #include #include +#include #include #include -#include -#include -#include +#include +#include #include -#include +#include #include +#include +#include #include #include +#include #define FIT_POINTER (0x100000000ULL - 0x40) +static struct chipset_power_state power_state CAR_GLOBAL; + /* * Enables several BARs and devices which are needed for memory init * - MCH_BASE_ADDR is needed in order to talk to the memory controller @@ -77,6 +83,22 @@ static void disable_watchdog(void) outl(reg, ACPI_PMIO_BASE + 0x68); } +static void migrate_power_state(int is_recovery) +{ + struct chipset_power_state *ps_cbmem; + struct chipset_power_state *ps_car; + + ps_car = car_get_var_ptr(&power_state); + ps_cbmem = cbmem_add(CBMEM_ID_POWER_STATE, sizeof(*ps_cbmem)); + + if (ps_cbmem == NULL) { + printk(BIOS_DEBUG, "Unable to add power state to cbmem!\n"); + return; + } + memcpy(ps_cbmem, ps_car, sizeof(*ps_cbmem)); +} +ROMSTAGE_CBMEM_INIT_HOOK(migrate_power_state); + asmlinkage void car_stage_entry(void) { void *hob_list_ptr; @@ -85,6 +107,9 @@ asmlinkage void car_stage_entry(void) struct postcar_frame pcf; size_t mrc_data_size; uintptr_t top_of_ram; + int prev_sleep_state; + struct romstage_handoff *handoff; + struct chipset_power_state *ps = car_get_var_ptr(&power_state); printk(BIOS_DEBUG, "Starting romstage...\n"); @@ -92,6 +117,8 @@ asmlinkage void car_stage_entry(void) disable_watchdog(); + prev_sleep_state = fill_power_state(ps); + /* Make sure the blob does not override our data in CAR */ range_entry_init(®_car, (uintptr_t)_car_relocatable_data_end, (uintptr_t)_car_region_end, 0); @@ -103,8 +130,17 @@ asmlinkage void car_stage_entry(void) fsp_find_reserved_memory(&fsp_mem, hob_list_ptr); /* initialize cbmem by adding FSP reserved memory first thing */ - cbmem_initialize_empty_id_size(CBMEM_ID_FSP_RESERVED_MEMORY, - range_entry_size(&fsp_mem)); + if (prev_sleep_state != SLEEP_STATE_S3) { + cbmem_initialize_empty_id_size(CBMEM_ID_FSP_RESERVED_MEMORY, + range_entry_size(&fsp_mem)); + } else if (cbmem_initialize_id_size(CBMEM_ID_FSP_RESERVED_MEMORY, + range_entry_size(&fsp_mem))) { + if (IS_ENABLED(CONFIG_HAVE_ACPI_RESUME)) { + printk(BIOS_DEBUG, "Failed to recover CBMEM in S3 resume.\n"); + /* Failed S3 resume, reset to come up cleanly */ + hard_reset(); + } + } /* make sure FSP memory is reserved in cbmem */ if (range_entry_base(&fsp_mem) != @@ -115,13 +151,21 @@ asmlinkage void car_stage_entry(void) fsp_save_hob_list(hob_list_ptr); /* Save MRC Data to CBMEM */ - if (IS_ENABLED(CONFIG_CACHE_MRC_SETTINGS)) + if (IS_ENABLED(CONFIG_CACHE_MRC_SETTINGS) && + (prev_sleep_state != SLEEP_STATE_S3)) { mrc_data = fsp_find_nv_storage_data(&mrc_data_size); if (mrc_data && mrc_cache_stash_data(mrc_data, mrc_data_size) < 0) printk(BIOS_ERR, "Failed to stash MRC data\n"); } + /* Create romstage handof information */ + handoff = romstage_handoff_find_or_add(); + if (handoff != NULL) + handoff->s3_resume = (prev_sleep_state == SLEEP_STATE_S3); + else + printk(BIOS_DEBUG, "Romstage handoff structure not added!\n"); + if (postcar_frame_init(&pcf, 1*KiB)) die("Unable to initialize postcar frame.\n"); @@ -157,6 +201,8 @@ void platform_fsp_memory_init_params_cb(struct FSPM_UPD *mupd) { const struct mrc_saved_data *mrc_cache; struct FSP_M_ARCH_UPD *arch_upd = &mupd->FspmArchUpd; + struct chipset_power_state *ps = car_get_var_ptr(&power_state); + int prev_sleep_state = chipset_prev_sleep_state(ps); fill_console_params(mupd); mainboard_memory_init_params(mupd); @@ -185,8 +231,12 @@ void platform_fsp_memory_init_params_cb(struct FSPM_UPD *mupd) if (!mrc_cache_get_current_with_version(&mrc_cache, 0)) { /* MRC cache found */ arch_upd->NvsBufferPtr = (void *)mrc_cache->data; - arch_upd->Bootmode = FSP_BOOT_ASSUMING_NO_CONFIGURATION_CHANGES; - printk(BIOS_DEBUG, "MRC cache found, size %x\n", mrc_cache->size); + arch_upd->Bootmode = + prev_sleep_state == SLEEP_STATE_S3 ? + FSP_BOOT_ON_S3_RESUME: + FSP_BOOT_ASSUMING_NO_CONFIGURATION_CHANGES; + printk(BIOS_DEBUG, "MRC cache found, size %x bootmode:%d\n", + mrc_cache->size, arch_upd->Bootmode); } else printk(BIOS_DEBUG, "MRC cache was not found\n"); } -- cgit v1.2.3