blob: 2fed93de5b6760ada6e48753ceea5c6c167305f4 [file] [log] [blame]
Angel Pons9fdd5572022-05-06 21:12:14 +02001/* SPDX-License-Identifier: GPL-2.0-or-later */
2
Angel Pons1c9a8d82022-05-07 00:26:10 +02003#include <arch/cpu.h>
4#include <assert.h>
5#include <cbmem.h>
6#include <cf9_reset.h>
Angel Pons9fdd5572022-05-06 21:12:14 +02007#include <console/console.h>
Angel Pons1c9a8d82022-05-07 00:26:10 +02008#include <cpu/x86/msr.h>
Angel Pons1c9a8d82022-05-07 00:26:10 +02009#include <device/pci_ops.h>
10#include <mrc_cache.h>
Angel Pons567ece42022-05-06 21:56:48 +020011#include <northbridge/intel/haswell/haswell.h>
Angel Pons9fdd5572022-05-06 21:12:14 +020012#include <northbridge/intel/haswell/raminit.h>
Angel Pons322b1c32022-05-06 22:18:21 +020013#include <southbridge/intel/lynxpoint/me.h>
Angel Pons70c61852022-05-06 23:17:39 +020014#include <southbridge/intel/lynxpoint/pch.h>
Angel Pons567ece42022-05-06 21:56:48 +020015#include <types.h>
16
Angel Pons1c9a8d82022-05-07 00:26:10 +020017#include "raminit_native.h"
18
19static void wait_txt_clear(void)
20{
21 const struct cpuid_result cpuid = cpuid_ext(1, 0);
22
23 /* Check if TXT is supported */
24 if (!(cpuid.ecx & BIT(6)))
25 return;
26
27 /* Some TXT public bit */
28 if (!(read32p(0xfed30010) & 1))
29 return;
30
31 /* Wait for TXT clear */
32 do {} while (!(read8p(0xfed40000) & (1 << 7)));
33}
34
35static enum raminit_boot_mode get_boot_mode(void)
36{
37 const uint16_t pmcon_2 = pci_read_config16(PCH_LPC_DEV, GEN_PMCON_2);
38 const uint16_t bitmask = GEN_PMCON_2_DISB | GEN_PMCON_2_MEM_SR;
39 return (pmcon_2 & bitmask) == bitmask ? BOOTMODE_WARM : BOOTMODE_COLD;
40}
41
Angel Ponsba7ab732022-06-26 10:32:12 +020042static bool early_init_native(enum raminit_boot_mode bootmode)
Angel Pons567ece42022-05-06 21:56:48 +020043{
44 printk(BIOS_DEBUG, "Starting native platform initialisation\n");
45
Angel Pons322b1c32022-05-06 22:18:21 +020046 intel_early_me_init();
Angel Ponsba7ab732022-06-26 10:32:12 +020047 bool cpu_replaced = bootmode == BOOTMODE_COLD && intel_early_me_cpu_replacement_check();
Angel Pons322b1c32022-05-06 22:18:21 +020048
Angel Ponsba7ab732022-06-26 10:32:12 +020049 early_pch_init_native(bootmode == BOOTMODE_S3);
Angel Pons70c61852022-05-06 23:17:39 +020050
Angel Pons567ece42022-05-06 21:56:48 +020051 if (!CONFIG(INTEL_LYNXPOINT_LP))
52 dmi_early_init();
53
Angel Pons322b1c32022-05-06 22:18:21 +020054 return cpu_replaced;
Angel Pons567ece42022-05-06 21:56:48 +020055}
Angel Pons9fdd5572022-05-06 21:12:14 +020056
Angel Pons1c9a8d82022-05-07 00:26:10 +020057#define MRC_CACHE_VERSION 1
58
59struct mrc_data {
60 const void *buffer;
61 size_t buffer_len;
62};
63
64static void save_mrc_data(struct mrc_data *md)
65{
66 mrc_cache_stash_data(MRC_TRAINING_DATA, MRC_CACHE_VERSION, md->buffer, md->buffer_len);
67}
68
69static struct mrc_data prepare_mrc_cache(void)
70{
71 struct mrc_data md = {0};
72 md.buffer = mrc_cache_current_mmap_leak(MRC_TRAINING_DATA,
73 MRC_CACHE_VERSION,
74 &md.buffer_len);
75 return md;
76}
77
78static const char *const bm_names[] = {
79 "BOOTMODE_COLD",
80 "BOOTMODE_WARM",
81 "BOOTMODE_S3",
82 "BOOTMODE_FAST",
83};
84
85static void clear_disb(void)
86{
87 pci_and_config16(PCH_LPC_DEV, GEN_PMCON_2, ~GEN_PMCON_2_DISB);
88}
89
90static void raminit_reset(void)
91{
92 clear_disb();
93 system_reset();
94}
95
96static enum raminit_boot_mode do_actual_raminit(
97 struct mrc_data *md,
98 const bool s3resume,
99 const bool cpu_replaced,
100 const enum raminit_boot_mode orig_bootmode)
101{
102 enum raminit_boot_mode bootmode = orig_bootmode;
103
104 bool save_data_valid = md->buffer && md->buffer_len == USHRT_MAX; /** TODO: sizeof() **/
105
106 if (s3resume) {
107 if (bootmode == BOOTMODE_COLD) {
108 printk(BIOS_EMERG, "Memory may not be in self-refresh for S3 resume\n");
109 printk(BIOS_EMERG, "S3 resume and cold boot are mutually exclusive\n");
110 raminit_reset();
111 }
112 /* Only a true mad hatter would replace a CPU in S3 */
113 if (cpu_replaced) {
114 printk(BIOS_EMERG, "Oh no, CPU was replaced during S3\n");
115 /*
116 * No reason to continue, memory consistency is most likely lost
117 * and ME will probably request a reset through DID response too.
118 */
119 /** TODO: Figure out why past self commented this out **/
120 //raminit_reset();
121 }
122 bootmode = BOOTMODE_S3;
123 if (!save_data_valid) {
124 printk(BIOS_EMERG, "No training data, S3 resume is impossible\n");
125 /* Failed S3 resume, reset to come up cleanly */
126 raminit_reset();
127 }
128 }
129 if (!s3resume && cpu_replaced) {
130 printk(BIOS_NOTICE, "CPU was replaced, forcing a cold boot\n");
131 /*
132 * Looks like the ME will get angry if raminit takes too long.
133 * It will report that the CPU has been replaced on next boot.
134 * Try to continue anyway. This should not happen in most cases.
135 */
136 /** TODO: Figure out why past self commented this out **/
137 //save_data_valid = false;
138 }
139 if (bootmode == BOOTMODE_COLD) {
140 /* If possible, promote to a fast boot */
141 if (save_data_valid)
142 bootmode = BOOTMODE_FAST;
143
144 clear_disb();
145 } else if (bootmode == BOOTMODE_WARM) {
146 /* If a warm reset happened before raminit is done, force a cold boot */
147 if (mchbar_read32(SSKPD) == 0 && mchbar_read32(SSKPD + 4) == 0) {
148 printk(BIOS_NOTICE, "Warm reset occurred early in cold boot\n");
149 save_data_valid = false;
150 }
151 if (!save_data_valid)
152 bootmode = BOOTMODE_COLD;
153 }
154 assert(save_data_valid != (bootmode == BOOTMODE_COLD));
155 if (save_data_valid) {
156 printk(BIOS_INFO, "Using cached memory parameters\n");
157 die("RAMINIT: Fast boot is not yet implemented\n");
158 }
159 printk(RAM_DEBUG, "Initial bootmode: %s\n", bm_names[orig_bootmode]);
160 printk(RAM_DEBUG, "Current bootmode: %s\n", bm_names[bootmode]);
161
162 /*
163 * And now, the actual memory initialization thing.
164 */
165 printk(RAM_DEBUG, "\nStarting native raminit\n");
166 raminit_main(bootmode);
167
168 return bootmode;
169}
170
Angel Pons9fdd5572022-05-06 21:12:14 +0200171void perform_raminit(const int s3resume)
172{
173 /*
174 * See, this function's name is a lie. There are more things to
175 * do that memory initialisation, but they are relatively easy.
176 */
Angel Ponsba7ab732022-06-26 10:32:12 +0200177 const enum raminit_boot_mode orig_bootmode = get_boot_mode();
178
179 const bool cpu_replaced = early_init_native(s3resume ? BOOTMODE_S3 : orig_bootmode);
Angel Pons567ece42022-05-06 21:56:48 +0200180
Angel Pons1c9a8d82022-05-07 00:26:10 +0200181 wait_txt_clear();
182 wrmsr(0x2e6, (msr_t) {.lo = 0, .hi = 0});
Angel Pons9fdd5572022-05-06 21:12:14 +0200183
Angel Pons1c9a8d82022-05-07 00:26:10 +0200184 struct mrc_data md = prepare_mrc_cache();
185
186 const enum raminit_boot_mode bootmode =
187 do_actual_raminit(&md, s3resume, cpu_replaced, orig_bootmode);
188
189 /** TODO: report_memory_config **/
190
Angel Pons322b1c32022-05-06 22:18:21 +0200191 if (intel_early_me_uma_size() > 0) {
Angel Pons1c9a8d82022-05-07 00:26:10 +0200192 /*
193 * The 'other' success value is to report loss of memory
194 * consistency to ME if warm boot was downgraded to cold.
195 */
196 uint8_t me_status;
197 if (BOOTMODE_WARM == orig_bootmode && BOOTMODE_COLD == bootmode)
198 me_status = ME_INIT_STATUS_SUCCESS_OTHER;
199 else
200 me_status = ME_INIT_STATUS_SUCCESS;
201
202 /** TODO: Remove this once raminit is implemented **/
203 me_status = ME_INIT_STATUS_ERROR;
Angel Pons322b1c32022-05-06 22:18:21 +0200204 intel_early_me_init_done(me_status);
205 }
206
207 intel_early_me_status();
208
Angel Pons1c9a8d82022-05-07 00:26:10 +0200209 const bool cbmem_was_initted = !cbmem_recovery(s3resume);
210 if (s3resume && !cbmem_was_initted) {
211 /* Failed S3 resume, reset to come up cleanly */
212 printk(BIOS_CRIT, "Failed to recover CBMEM in S3 resume.\n");
213 system_reset();
214 }
215
216 /* Save training data on non-S3 resumes */
217 if (!s3resume)
218 save_mrc_data(&md);
219
220 /** TODO: setup_sdram_meminfo **/
Angel Pons9fdd5572022-05-06 21:12:14 +0200221}