summaryrefslogtreecommitdiff
path: root/src/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'src/drivers')
-rw-r--r--src/drivers/intel/fsp2_0/include/fsp/api.h12
-rw-r--r--src/drivers/intel/fsp2_0/memory_init.c101
2 files changed, 97 insertions, 16 deletions
diff --git a/src/drivers/intel/fsp2_0/include/fsp/api.h b/src/drivers/intel/fsp2_0/include/fsp/api.h
index aa45d97876..9f8aae7f80 100644
--- a/src/drivers/intel/fsp2_0/include/fsp/api.h
+++ b/src/drivers/intel/fsp2_0/include/fsp/api.h
@@ -58,7 +58,7 @@ enum fsp_notify_phase {
/* Main FSP stages */
-enum fsp_status fsp_memory_init(void **hob_list, struct range_entry *r);
+enum fsp_status fsp_memory_init(struct range_entry *r, bool s3wake);
enum fsp_status fsp_silicon_init(struct range_entry *r);
enum fsp_status fsp_notify(enum fsp_notify_phase phase);
@@ -74,24 +74,18 @@ void platform_fsp_silicon_init_params_cb(struct FSPS_UPD *supd);
* points and map 1:1 to the FSP entry points of the same name.
*
* ### fsp_memory_init():
- * - hob_list: retuns a pointer to the HOB storage area created by FSP
* - r: memory range that the binary is allowed to be loaded into
+ * - s3wake: boolean indicating if the system is waking from resume
*
* This function is responsible for loading and executing the memory
* initialization code from the FSP-M binary. It expects this binary to reside
* in cbfs as FSP_M_FILE.
*
- * The function takes one parameter, which is described below, but does not
+ * The function takes two parameters, which are described above, but does not
* take in memory parameters as an argument. The memory parameters can be filled
* in with platform_fsp_memory_init_params_cb(). This is a callback symbol
* that fsp_memory_init() will call. The platform must provide this symbol.
*
- * FSP returns information about the memory layout in a series of structures
- * called hand-off-blocks (HOB). The "hob_list" output parameter will point to
- * the start of the HOB list. The fsp reserved region will also be described by
- * one of the HOBs. For more information on parsing these structures, see
- * fsp/util.h
- *
*
* ### fsp_silicon_init():
* - r: memory range that the binary is allowed to be loaded into
diff --git a/src/drivers/intel/fsp2_0/memory_init.c b/src/drivers/intel/fsp2_0/memory_init.c
index 5363fdd380..700d40fa7f 100644
--- a/src/drivers/intel/fsp2_0/memory_init.c
+++ b/src/drivers/intel/fsp2_0/memory_init.c
@@ -13,23 +13,103 @@
#include <arch/io.h>
#include <arch/cpu.h>
+#include <arch/symbols.h>
#include <cbmem.h>
#include <console/console.h>
#include <fsp/api.h>
#include <fsp/util.h>
#include <memrange.h>
+#include <reset.h>
+#include <romstage_handoff.h>
+#include <soc/intel/common/mrc_cache.h>
#include <string.h>
#include <timestamp.h>
typedef asmlinkage enum fsp_status (*fsp_memory_init_fn)
(void *raminit_upd, void **hob_list);
-static enum fsp_status do_fsp_memory_init(void **hob_list_ptr,
- struct fsp_header *hdr)
+static enum fsp_status do_fsp_post_memory_init(void *hob_list_ptr, bool s3wake)
+{
+ struct range_entry fsp_mem;
+ size_t mrc_data_size;
+ const void *mrc_data;
+ struct romstage_handoff *handoff;
+
+ fsp_find_reserved_memory(&fsp_mem, hob_list_ptr);
+
+ /* initialize cbmem by adding FSP reserved memory first thing */
+ if (!s3wake) {
+ 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) !=
+ (uintptr_t)cbmem_find(CBMEM_ID_FSP_RESERVED_MEMORY))
+ die("Failed to accommodate FSP reserved memory request");
+
+ /* Now that CBMEM is up, save the list so ramstage can use it */
+ fsp_save_hob_list(hob_list_ptr);
+
+ /* Save MRC Data to CBMEM */
+ if (IS_ENABLED(CONFIG_CACHE_MRC_SETTINGS) && !s3wake) {
+ 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 = s3wake;
+ else
+ printk(BIOS_DEBUG, "Romstage handoff structure not added!\n");
+
+ return FSP_SUCCESS;
+}
+
+static void fsp_fill_common_arch_params(struct FSPM_ARCH_UPD *arch_upd,
+ bool s3wake)
+{
+ const struct mrc_saved_data *mrc_cache;
+
+ /*
+ * FSPM_UPD passed here is populated with default values provided by
+ * the blob itself. We let FSPM use top of CAR region of the size it
+ * requests.
+ * TODO: add checks to avoid overlap/conflict of CAR usage.
+ */
+ arch_upd->StackBase = _car_region_end - arch_upd->StackSize;
+
+ arch_upd->BootMode = FSP_BOOT_WITH_FULL_CONFIGURATION;
+
+ if (IS_ENABLED(CONFIG_CACHE_MRC_SETTINGS)) {
+ if (!mrc_cache_get_current_with_version(&mrc_cache, 0)) {
+ /* MRC cache found */
+ arch_upd->NvsBufferPtr = (void *)mrc_cache->data;
+ arch_upd->BootMode = s3wake ?
+ 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");
+ }
+}
+
+static enum fsp_status do_fsp_memory_init(struct fsp_header *hdr, bool s3wake)
{
enum fsp_status status;
fsp_memory_init_fn fsp_raminit;
struct FSPM_UPD fspm_upd, *upd;
+ void *hob_list_ptr;
post_code(0x34);
@@ -46,6 +126,9 @@ static enum fsp_status do_fsp_memory_init(void **hob_list_ptr,
/* Reserve enough memory under TOLUD to save CBMEM header */
fspm_upd.FspmArchUpd.BootLoaderTolumSize = cbmem_overhead_size();
+ /* Fill common settings on behalf of chipset. */
+ fsp_fill_common_arch_params(&fspm_upd.FspmArchUpd, s3wake);
+
/* Give SoC and mainboard a chance to update the UPD */
platform_fsp_memory_init_params_cb(&fspm_upd);
@@ -53,25 +136,29 @@ static enum fsp_status do_fsp_memory_init(void **hob_list_ptr,
fsp_raminit = (void *)(hdr->image_base + hdr->memory_init_entry_offset);
printk(BIOS_DEBUG, "Calling FspMemoryInit: 0x%p\n", fsp_raminit);
printk(BIOS_SPEW, "\t%p: raminit_upd\n", &fspm_upd);
- printk(BIOS_SPEW, "\t%p: hob_list ptr\n", hob_list_ptr);
+ printk(BIOS_SPEW, "\t%p: hob_list ptr\n", &hob_list_ptr);
post_code(POST_FSP_MEMORY_INIT);
timestamp_add_now(TS_FSP_MEMORY_INIT_START);
- status = fsp_raminit(&fspm_upd, hob_list_ptr);
+ status = fsp_raminit(&fspm_upd, &hob_list_ptr);
post_code(POST_FSP_MEMORY_INIT);
timestamp_add_now(TS_FSP_MEMORY_INIT_END);
printk(BIOS_DEBUG, "FspMemoryInit returned 0x%08x\n", status);
- return status;
+ /* TODO: Is this the only thing that can happen? */
+ if (status != FSP_SUCCESS)
+ return status;
+
+ return do_fsp_post_memory_init(hob_list_ptr, s3wake);
}
-enum fsp_status fsp_memory_init(void **hob_list, struct range_entry *range)
+enum fsp_status fsp_memory_init(struct range_entry *range, bool s3wake)
{
struct fsp_header hdr;
if (fsp_load_binary(&hdr, CONFIG_FSP_M_CBFS, range) != CB_SUCCESS)
return FSP_NOT_FOUND;
- return do_fsp_memory_init(hob_list, &hdr);
+ return do_fsp_memory_init(&hdr, s3wake);
}