blob: 700d40fa7f0a5b0b115af8f50fa3d5d580455628 [file] [log] [blame]
Andrey Petrov465fc132016-02-25 14:16:33 -08001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2015 Intel Corp.
5 * (Written by Andrey Petrov <andrey.petrov@intel.com> for Intel Corp.)
6 * (Written by Alexandru Gagniuc <alexandrux.gagniuc@intel.com> for Intel Corp.)
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 */
13
14#include <arch/io.h>
15#include <arch/cpu.h>
Aaron Durbinb4302502016-07-17 17:04:37 -050016#include <arch/symbols.h>
Aaron Durbin27928682016-07-15 22:32:28 -050017#include <cbmem.h>
Andrey Petrov465fc132016-02-25 14:16:33 -080018#include <console/console.h>
19#include <fsp/api.h>
20#include <fsp/util.h>
21#include <memrange.h>
Aaron Durbinb4302502016-07-17 17:04:37 -050022#include <reset.h>
23#include <romstage_handoff.h>
24#include <soc/intel/common/mrc_cache.h>
Andrey Petrov465fc132016-02-25 14:16:33 -080025#include <string.h>
26#include <timestamp.h>
27
28typedef asmlinkage enum fsp_status (*fsp_memory_init_fn)
29 (void *raminit_upd, void **hob_list);
30
Aaron Durbinb4302502016-07-17 17:04:37 -050031static enum fsp_status do_fsp_post_memory_init(void *hob_list_ptr, bool s3wake)
32{
33 struct range_entry fsp_mem;
34 size_t mrc_data_size;
35 const void *mrc_data;
36 struct romstage_handoff *handoff;
37
38 fsp_find_reserved_memory(&fsp_mem, hob_list_ptr);
39
40 /* initialize cbmem by adding FSP reserved memory first thing */
41 if (!s3wake) {
42 cbmem_initialize_empty_id_size(CBMEM_ID_FSP_RESERVED_MEMORY,
43 range_entry_size(&fsp_mem));
44 } else if (cbmem_initialize_id_size(CBMEM_ID_FSP_RESERVED_MEMORY,
45 range_entry_size(&fsp_mem))) {
46 if (IS_ENABLED(CONFIG_HAVE_ACPI_RESUME)) {
47 printk(BIOS_DEBUG, "Failed to recover CBMEM in S3 resume.\n");
48 /* Failed S3 resume, reset to come up cleanly */
49 hard_reset();
50 }
51 }
52
53 /* make sure FSP memory is reserved in cbmem */
54 if (range_entry_base(&fsp_mem) !=
55 (uintptr_t)cbmem_find(CBMEM_ID_FSP_RESERVED_MEMORY))
56 die("Failed to accommodate FSP reserved memory request");
57
58 /* Now that CBMEM is up, save the list so ramstage can use it */
59 fsp_save_hob_list(hob_list_ptr);
60
61 /* Save MRC Data to CBMEM */
62 if (IS_ENABLED(CONFIG_CACHE_MRC_SETTINGS) && !s3wake) {
63 mrc_data = fsp_find_nv_storage_data(&mrc_data_size);
64 if (mrc_data && mrc_cache_stash_data(mrc_data, mrc_data_size) < 0)
65 printk(BIOS_ERR, "Failed to stash MRC data\n");
66 }
67
68 /* Create romstage handof information */
69 handoff = romstage_handoff_find_or_add();
70 if (handoff != NULL)
71 handoff->s3_resume = s3wake;
72 else
73 printk(BIOS_DEBUG, "Romstage handoff structure not added!\n");
74
75 return FSP_SUCCESS;
76}
77
78static void fsp_fill_common_arch_params(struct FSPM_ARCH_UPD *arch_upd,
79 bool s3wake)
80{
81 const struct mrc_saved_data *mrc_cache;
82
83 /*
84 * FSPM_UPD passed here is populated with default values provided by
85 * the blob itself. We let FSPM use top of CAR region of the size it
86 * requests.
87 * TODO: add checks to avoid overlap/conflict of CAR usage.
88 */
89 arch_upd->StackBase = _car_region_end - arch_upd->StackSize;
90
91 arch_upd->BootMode = FSP_BOOT_WITH_FULL_CONFIGURATION;
92
93 if (IS_ENABLED(CONFIG_CACHE_MRC_SETTINGS)) {
94 if (!mrc_cache_get_current_with_version(&mrc_cache, 0)) {
95 /* MRC cache found */
96 arch_upd->NvsBufferPtr = (void *)mrc_cache->data;
97 arch_upd->BootMode = s3wake ?
98 FSP_BOOT_ON_S3_RESUME:
99 FSP_BOOT_ASSUMING_NO_CONFIGURATION_CHANGES;
100 printk(BIOS_DEBUG, "MRC cache found, size %x bootmode:%d\n",
101 mrc_cache->size, arch_upd->BootMode);
102 } else
103 printk(BIOS_DEBUG, "MRC cache was not found\n");
104 }
105}
106
107static enum fsp_status do_fsp_memory_init(struct fsp_header *hdr, bool s3wake)
Andrey Petrov465fc132016-02-25 14:16:33 -0800108{
109 enum fsp_status status;
110 fsp_memory_init_fn fsp_raminit;
111 struct FSPM_UPD fspm_upd, *upd;
Aaron Durbinb4302502016-07-17 17:04:37 -0500112 void *hob_list_ptr;
Andrey Petrov465fc132016-02-25 14:16:33 -0800113
114 post_code(0x34);
115
116 upd = (struct FSPM_UPD *)(hdr->cfg_region_offset + hdr->image_base);
117
118 if (upd->FspUpdHeader.Signature != FSPM_UPD_SIGNATURE) {
119 printk(BIOS_ERR, "Invalid FSPM signature\n");
120 return FSP_INCOMPATIBLE_VERSION;
121 }
122
123 /* Copy the default values from the UPD area */
124 memcpy(&fspm_upd, upd, sizeof(fspm_upd));
125
Aaron Durbin27928682016-07-15 22:32:28 -0500126 /* Reserve enough memory under TOLUD to save CBMEM header */
127 fspm_upd.FspmArchUpd.BootLoaderTolumSize = cbmem_overhead_size();
128
Aaron Durbinb4302502016-07-17 17:04:37 -0500129 /* Fill common settings on behalf of chipset. */
130 fsp_fill_common_arch_params(&fspm_upd.FspmArchUpd, s3wake);
131
Andrey Petrov465fc132016-02-25 14:16:33 -0800132 /* Give SoC and mainboard a chance to update the UPD */
133 platform_fsp_memory_init_params_cb(&fspm_upd);
134
135 /* Call FspMemoryInit */
136 fsp_raminit = (void *)(hdr->image_base + hdr->memory_init_entry_offset);
137 printk(BIOS_DEBUG, "Calling FspMemoryInit: 0x%p\n", fsp_raminit);
138 printk(BIOS_SPEW, "\t%p: raminit_upd\n", &fspm_upd);
Aaron Durbinb4302502016-07-17 17:04:37 -0500139 printk(BIOS_SPEW, "\t%p: hob_list ptr\n", &hob_list_ptr);
Andrey Petrov465fc132016-02-25 14:16:33 -0800140
Alexandru Gagniucc4ea8f72016-05-23 12:16:58 -0700141 post_code(POST_FSP_MEMORY_INIT);
Andrey Petrov465fc132016-02-25 14:16:33 -0800142 timestamp_add_now(TS_FSP_MEMORY_INIT_START);
Aaron Durbinb4302502016-07-17 17:04:37 -0500143 status = fsp_raminit(&fspm_upd, &hob_list_ptr);
Alexandru Gagniucc4ea8f72016-05-23 12:16:58 -0700144 post_code(POST_FSP_MEMORY_INIT);
Andrey Petrov465fc132016-02-25 14:16:33 -0800145 timestamp_add_now(TS_FSP_MEMORY_INIT_END);
146
147 printk(BIOS_DEBUG, "FspMemoryInit returned 0x%08x\n", status);
148
Aaron Durbinb4302502016-07-17 17:04:37 -0500149 /* TODO: Is this the only thing that can happen? */
150 if (status != FSP_SUCCESS)
151 return status;
152
153 return do_fsp_post_memory_init(hob_list_ptr, s3wake);
Andrey Petrov465fc132016-02-25 14:16:33 -0800154}
155
Aaron Durbinb4302502016-07-17 17:04:37 -0500156enum fsp_status fsp_memory_init(struct range_entry *range, bool s3wake)
Andrey Petrov465fc132016-02-25 14:16:33 -0800157{
158 struct fsp_header hdr;
159
Andrey Petrov9be1a112016-05-14 16:32:39 -0700160 if (fsp_load_binary(&hdr, CONFIG_FSP_M_CBFS, range) != CB_SUCCESS)
Andrey Petrov465fc132016-02-25 14:16:33 -0800161 return FSP_NOT_FOUND;
162
Aaron Durbinb4302502016-07-17 17:04:37 -0500163 return do_fsp_memory_init(&hdr, s3wake);
Andrey Petrov465fc132016-02-25 14:16:33 -0800164}