drivers/pc80: Add optional spinlock for nvram CBFS access
[coreboot.git] / src / cpu / amd / car / post_cache_as_ram.c
blob435fdcb588f2891a761a9207d35fc3ddc1f14b36
1 /* Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
2 * Copyright (C) 2012 ChromeOS Authors
3 * 2005.6 by yhlu
4 * 2006.3 yhlu add copy data from CAR to ram
5 */
6 #include <string.h>
7 #include <arch/stages.h>
8 #include <arch/early_variables.h>
9 #include <cpu/x86/mtrr.h>
10 #include <cpu/amd/mtrr.h>
11 #include <cpu/amd/car.h>
12 #include <arch/acpi.h>
13 #include <romstage_handoff.h>
14 #include "cbmem.h"
15 #include "cpu/amd/car/disable_cache_as_ram.c"
17 #if CONFIG_RAMTOP <= 0x100000
18 #error "You need to set CONFIG_RAMTOP greater than 1M"
19 #endif
21 #if IS_ENABLED(CONFIG_DEBUG_CAR)
22 #define print_car_debug(format, arg...) printk(BIOS_DEBUG, "%s: " format, __func__, ##arg)
23 #else
24 #define print_car_debug(format, arg...)
25 #endif
27 static size_t backup_size(void)
29 size_t car_size = car_data_size();
30 return ALIGN(car_size + 1024, 1024);
33 static void memcpy_(void *d, const void *s, size_t len)
35 print_car_debug(" Copy [%08x-%08x] to [%08x - %08x] ...",
36 (uint32_t) s, (uint32_t) (s + len - 1), (uint32_t) d, (uint32_t) (d + len - 1));
37 memcpy(d, s, len);
40 static void memset_(void *d, int val, size_t len)
42 print_car_debug(" Fill [%08x-%08x] ...", (uint32_t) d, (uint32_t) (d + len - 1));
43 memset(d, val, len);
46 static int memcmp_(void *d, const void *s, size_t len)
48 print_car_debug(" Compare [%08x-%08x] with [%08x - %08x] ...",
49 (uint32_t) s, (uint32_t) (s + len - 1), (uint32_t) d, (uint32_t) (d + len - 1));
50 return memcmp(d, s, len);
53 static void prepare_romstage_ramstack(void *resume_backup_memory)
55 size_t backup_top = backup_size();
56 print_car_debug("Prepare CAR migration and stack regions...");
58 if (resume_backup_memory) {
59 memcpy_(resume_backup_memory + HIGH_MEMORY_SAVE - backup_top,
60 (void *)(CONFIG_RAMTOP - backup_top), backup_top);
62 memset_((void *)(CONFIG_RAMTOP - backup_top), 0, backup_top);
64 print_car_debug(" Done\n");
67 static void prepare_ramstage_region(void *resume_backup_memory)
69 size_t backup_top = backup_size();
70 print_car_debug("Prepare ramstage memory region...");
72 if (resume_backup_memory) {
73 memcpy_(resume_backup_memory, (void *) CONFIG_RAMBASE, HIGH_MEMORY_SAVE - backup_top);
74 memset_((void*) CONFIG_RAMBASE, 0, HIGH_MEMORY_SAVE - backup_top);
75 } else {
76 memset_((void*)0, 0, CONFIG_RAMTOP - backup_top);
79 #if IS_ENABLED(CONFIG_HAVE_ROMSTAGE_CONSOLE_SPINLOCK)
80 initialize_romstage_console_lock();
81 #endif
82 #if IS_ENABLED(CONFIG_HAVE_ROMSTAGE_NVRAM_CBFS_SPINLOCK)
83 initialize_romstage_nvram_cbfs_lock();
84 #endif
86 print_car_debug(" Done\n");
89 /* Disable Erratum 343 Workaround, see RevGuide for Fam10h, Pub#41322 Rev 3.33
90 * and RevGuide for Fam12h, Pub#44739 Rev 3.10
93 static void vErrata343(void)
95 msr_t msr;
96 unsigned int uiMask = 0xFFFFFFF7;
98 msr = rdmsr(BU_CFG2_MSR);
99 msr.hi &= uiMask; // IcDisSpecTlbWr (bit 35) = 0
100 wrmsr(BU_CFG2_MSR, msr);
103 void post_cache_as_ram(void)
105 void *resume_backup_memory = NULL;
106 uint32_t family = amd_fam1x_cpu_family();
108 /* Verify that the BSP didn't overrun the lower stack
109 * boundary during romstage execution
111 volatile uint32_t *lower_stack_boundary;
112 lower_stack_boundary = (void *)((CONFIG_DCACHE_RAM_BASE + CONFIG_DCACHE_RAM_SIZE) - CONFIG_DCACHE_BSP_STACK_SIZE);
113 if ((*lower_stack_boundary) != 0xdeadbeef)
114 printk(BIOS_WARNING, "BSP overran lower stack boundary. Undefined behaviour may result!\n");
116 struct romstage_handoff *handoff;
117 handoff = romstage_handoff_find_or_add();
118 if (handoff != NULL)
119 handoff->s3_resume = acpi_is_wakeup_s3();
120 else
121 printk(BIOS_DEBUG, "Romstage handoff structure not added!\n");
123 int s3resume = acpi_is_wakeup_s3();
124 if (s3resume) {
125 cbmem_recovery(s3resume);
126 resume_backup_memory = cbmem_find(CBMEM_ID_RESUME);
128 prepare_romstage_ramstack(resume_backup_memory);
130 /* from here don't store more data in CAR */
131 if (family >= 0x1f && family <= 0x3f) {
132 /* Family 10h and 12h, 11h until shown otherwise */
133 vErrata343();
136 size_t car_size = car_data_size();
137 void *migrated_car = (void *)(CONFIG_RAMTOP - car_size);
139 print_car_debug("Copying data from cache to RAM...");
140 memcpy_(migrated_car, &_car_data_start[0], car_size);
141 print_car_debug(" Done\n");
143 print_car_debug("Verifying data integrity in RAM...");
144 if (memcmp_(migrated_car, &_car_data_start[0], car_size) == 0)
145 print_car_debug(" Done\n");
146 else
147 print_car_debug(" FAILED\n");
149 /* New stack grows right below migrated_car. */
150 print_car_debug("Switching to use RAM as stack...");
151 cache_as_ram_switch_stack(migrated_car);
153 /* We do not come back. */
156 void cache_as_ram_new_stack (void)
158 void *resume_backup_memory = NULL;
160 print_car_debug("Top about %08x ... Done\n", (uint32_t) &resume_backup_memory);
161 print_car_debug("Disabling cache as ram now\n");
162 disable_cache_as_ram_bsp();
164 disable_cache();
165 /* Enable cached access to RAM in the range 1M to CONFIG_RAMTOP */
166 set_var_mtrr(0, 0x00000000, CONFIG_RAMTOP, MTRR_TYPE_WRBACK);
167 enable_cache();
169 if (acpi_is_wakeup_s3()) {
170 resume_backup_memory = cbmem_find(CBMEM_ID_RESUME);
171 print_car_debug("Resume backup memory location: %p\n", resume_backup_memory);
173 prepare_ramstage_region(resume_backup_memory);
175 set_sysinfo_in_ram(1); // So other core0 could start to train mem
177 /*copy and execute ramstage */
178 copy_and_run();
179 /* We will not return */
181 print_car_debug("should not be here -\n");