blob: 3ce04e274bbef0761147e81fb627c3dfa7eec961 [file] [log] [blame]
Aaron Durbin3d0071b2013-01-18 14:32:50 -06001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2012 ChromeOS Authors
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <stdint.h>
21#include <cbmem.h>
22#include <console/console.h>
Aaron Durbina2671612013-02-06 21:41:01 -060023#include <arch/cpu.h>
24#include <cpu/x86/bist.h>
25#include <cpu/x86/msr.h>
Aaron Durbin38d94232013-02-07 00:03:33 -060026#include <cpu/x86/mtrr.h>
27#include <cpu/x86/stack.h>
Aaron Durbina2671612013-02-06 21:41:01 -060028#include <lib.h>
29#include <timestamp.h>
30#include <arch/io.h>
31#include <arch/romcc_io.h>
32#include <device/pci_def.h>
33#include <cpu/x86/lapic.h>
34#include <cbmem.h>
35#if CONFIG_CHROMEOS
36#include <vendorcode/google/chromeos/chromeos.h>
37#endif
38#include "haswell.h"
39#include "northbridge/intel/haswell/haswell.h"
40#include "northbridge/intel/haswell/raminit.h"
41#include "southbridge/intel/lynxpoint/pch.h"
42#include "southbridge/intel/lynxpoint/me.h"
Aaron Durbin3d0071b2013-01-18 14:32:50 -060043
Aaron Durbina2671612013-02-06 21:41:01 -060044
Aaron Durbin38d94232013-02-07 00:03:33 -060045/* The cache-as-ram assembly file calls romstage_main() after setting up
46 * cache-as-ram. romstage_main() will then call the mainboards's
47 * mainboard_romstage_entry() function. That function then calls
48 * romstage_common() below. The reason for the back and forth is to provide
49 * common entry point from cache-as-ram while still allowing for code sharing.
50 * Because we can't use global variables the stack is used for allocations --
51 * thus the need to call back and forth. */
Aaron Durbin3d0071b2013-01-18 14:32:50 -060052
Aaron Durbin38d94232013-02-07 00:03:33 -060053
54static inline u32 *stack_push(u32 *stack, u32 value)
55{
56 stack = &stack[-1];
57 *stack = value;
58 return stack;
59}
60
61/* setup_romstage_stack_after_car() determines the stack to use after
62 * cache-as-ram is torn down as well as the MTRR settings to use. */
63static void *setup_romstage_stack_after_car(void)
64{
65 unsigned long top_of_stack;
66 int num_mtrrs;
67 u32 *slot;
68 u32 mtrr_mask_upper;
69
70 /* Top of stack needs to be aligned to a 4-byte boundary. */
71 top_of_stack = ROMSTAGE_STACK & ~3;
72 slot = (void *)top_of_stack;
73 num_mtrrs = 0;
74
75 /* The upper bits of the MTRR mask need to set according to the number
76 * of physical address bits. */
77 mtrr_mask_upper = (1 << ((cpuid_eax(0x80000008) & 0xff) - 32)) - 1;
78
79 /* The order for each MTTR is value then base with upper 32-bits of
80 * each value coming before the lower 32-bits. The reasoning for
81 * this ordering is to create a stack layout like the following:
82 * +0: Number of MTRRs
83 * +4: MTTR base 0 31:0
84 * +8: MTTR base 0 63:32
85 * +12: MTTR mask 0 31:0
86 * +16: MTTR mask 0 63:32
87 * +20: MTTR base 1 31:0
88 * +24: MTTR base 1 63:32
89 * +28: MTTR mask 1 31:0
90 * +32: MTTR mask 1 63:32
91 */
92
93 /* Cache the ROM as WP just below 4GiB. */
94 slot = stack_push(slot, mtrr_mask_upper); /* upper mask */
95 slot = stack_push(slot, ~(CONFIG_ROM_SIZE - 1) | MTRRphysMaskValid);
96 slot = stack_push(slot, 0); /* upper base */
97 slot = stack_push(slot, ~(CONFIG_ROM_SIZE - 1) | MTRR_TYPE_WRPROT);
98 num_mtrrs++;
99
100 /* Cache RAM as WB from 0 -> CONFIG_RAMTOP. */
101 slot = stack_push(slot, mtrr_mask_upper); /* upper mask */
102 slot = stack_push(slot, ~(CONFIG_RAMTOP - 1) | MTRRphysMaskValid);
103 slot = stack_push(slot, 0); /* upper base */
104 slot = stack_push(slot, 0 | MTRR_TYPE_WRBACK);
105 num_mtrrs++;
106
107 /* Cache 8MiB below the top of ram. On haswell systems the top of
108 * ram under 4GiB is the start of the TSEG region. It is required to
109 * be 8MiB aligned. Set this area as cacheable so it can be used later
110 * for ramstage before setting up the entire RAM as cacheable. */
111 slot = stack_push(slot, mtrr_mask_upper); /* upper mask */
112 slot = stack_push(slot, ~((8 << 20) - 1) | MTRRphysMaskValid);
113 slot = stack_push(slot, 0); /* upper base */
114 slot = stack_push(slot,
115 (get_top_of_ram() - (8 << 20)) | MTRR_TYPE_WRBACK);
116 num_mtrrs++;
117
118 /* Save the number of MTTRs to setup. Return the stack location
119 * pointing to the number of MTRRs. */
120 slot = stack_push(slot, num_mtrrs);
121
122 return slot;
123}
124
125void * __attribute__((regparm(0))) romstage_main(unsigned long bist)
Aaron Durbin3d0071b2013-01-18 14:32:50 -0600126{
127 int i;
Aaron Durbin38d94232013-02-07 00:03:33 -0600128 void *romstage_stack_after_car;
Aaron Durbin3d0071b2013-01-18 14:32:50 -0600129 const int num_guards = 4;
130 const u32 stack_guard = 0xdeadbeef;
131 u32 *stack_base = (void *)(CONFIG_DCACHE_RAM_BASE +
132 CONFIG_DCACHE_RAM_SIZE -
133 CONFIG_DCACHE_RAM_ROMSTAGE_STACK_SIZE);
134
135 printk(BIOS_DEBUG, "Setting up stack guards.\n");
136 for (i = 0; i < num_guards; i++)
137 stack_base[i] = stack_guard;
138
Aaron Durbina2671612013-02-06 21:41:01 -0600139 mainboard_romstage_entry(bist);
Aaron Durbin3d0071b2013-01-18 14:32:50 -0600140
141 /* Check the stack. */
142 for (i = 0; i < num_guards; i++) {
143 if (stack_base[i] == stack_guard)
144 continue;
145 printk(BIOS_DEBUG, "Smashed stack detected in romstage!\n");
146 }
147
Aaron Durbin38d94232013-02-07 00:03:33 -0600148 /* Get the stack to use after cache-as-ram is torn down. */
149 romstage_stack_after_car = setup_romstage_stack_after_car();
150
Aaron Durbin3d0071b2013-01-18 14:32:50 -0600151#if CONFIG_CONSOLE_CBMEM
152 /* Keep this the last thing this function does. */
153 cbmemc_reinit();
154#endif
Aaron Durbin38d94232013-02-07 00:03:33 -0600155
156 return romstage_stack_after_car;
Aaron Durbin3d0071b2013-01-18 14:32:50 -0600157}
Aaron Durbina2671612013-02-06 21:41:01 -0600158
159void romstage_common(const struct romstage_params *params)
160{
161 int boot_mode = 0;
162 int wake_from_s3;
163 int cbmem_was_initted;
164
165#if CONFIG_COLLECT_TIMESTAMPS
166 tsc_t start_romstage_time;
167 tsc_t before_dram_time;
168 tsc_t after_dram_time;
169 tsc_t base_time = {
170 .lo = pci_read_config32(PCI_DEV(0, 0x00, 0), 0xdc),
171 .hi = pci_read_config32(PCI_DEV(0, 0x1f, 2), 0xd0)
172 };
173#endif
174
175#if CONFIG_COLLECT_TIMESTAMPS
176 start_romstage_time = rdtsc();
177#endif
178
179 if (params->bist == 0)
180 enable_lapic();
181
182 wake_from_s3 = early_pch_init(params->gpio_map, params->rcba_config);
183
184 /* Halt if there was a built in self test failure */
185 report_bist_failure(params->bist);
186
187 /* Perform some early chipset initialization required
188 * before RAM initialization can work
189 */
190 haswell_early_initialization(HASWELL_MOBILE);
191 printk(BIOS_DEBUG, "Back from haswell_early_initialization()\n");
192
193 if (wake_from_s3) {
194#if CONFIG_HAVE_ACPI_RESUME
195 printk(BIOS_DEBUG, "Resume from S3 detected.\n");
196 boot_mode = 2;
197#else
198 printk(BIOS_DEBUG, "Resume from S3 detected, but disabled.\n");
199#endif
200 }
201
202 /* Prepare USB controller early in S3 resume */
203 if (boot_mode == 2)
204 enable_usb_bar();
205
206 post_code(0x3a);
207 params->pei_data->boot_mode = boot_mode;
208#if CONFIG_COLLECT_TIMESTAMPS
209 before_dram_time = rdtsc();
210#endif
211
212 report_platform_info();
213
214 sdram_initialize(params->pei_data);
215
216#if CONFIG_COLLECT_TIMESTAMPS
217 after_dram_time = rdtsc();
218#endif
219 post_code(0x3b);
220
221 intel_early_me_status();
222
223 quick_ram_check();
224 post_code(0x3e);
225
226#if CONFIG_EARLY_CBMEM_INIT
227 cbmem_was_initted = !cbmem_initialize();
228#else
229 cbmem_was_initted = cbmem_reinit((uint64_t) (get_top_of_ram()
230 - HIGH_MEMORY_SIZE));
231#endif
232
Aaron Durbin2ad1dba2013-02-07 00:51:18 -0600233 /* Save data returned from MRC on non-S3 resumes. */
234 if (boot_mode != 2)
235 save_mrc_data(params->pei_data);
236
Aaron Durbina2671612013-02-06 21:41:01 -0600237#if CONFIG_HAVE_ACPI_RESUME
238 /* If there is no high memory area, we didn't boot before, so
239 * this is not a resume. In that case we just create the cbmem toc.
240 */
241
242 *(u32 *)CBMEM_BOOT_MODE = 0;
243 *(u32 *)CBMEM_RESUME_BACKUP = 0;
244
245 if ((boot_mode == 2) && cbmem_was_initted) {
246 void *resume_backup_memory = cbmem_find(CBMEM_ID_RESUME);
247 if (resume_backup_memory) {
248 *(u32 *)CBMEM_BOOT_MODE = boot_mode;
249 *(u32 *)CBMEM_RESUME_BACKUP = (u32)resume_backup_memory;
250 }
251 /* Magic for S3 resume */
252 pci_write_config32(PCI_DEV(0, 0x00, 0), SKPAD, 0xcafed00d);
253 } else if (boot_mode == 2) {
254 /* Failed S3 resume, reset to come up cleanly */
255 outb(0x6, 0xcf9);
256 while (1) {
257 hlt();
258 }
259 } else {
260 pci_write_config32(PCI_DEV(0, 0x00, 0), SKPAD, 0xcafebabe);
261 }
262#endif
263 post_code(0x3f);
264#if CONFIG_CHROMEOS
265 init_chromeos(boot_mode);
266#endif
267#if CONFIG_COLLECT_TIMESTAMPS
268 timestamp_init(base_time);
269 timestamp_add(TS_START_ROMSTAGE, start_romstage_time );
270 timestamp_add(TS_BEFORE_INITRAM, before_dram_time );
271 timestamp_add(TS_AFTER_INITRAM, after_dram_time );
272 timestamp_add_now(TS_END_ROMSTAGE);
273#endif
274}