1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (c) 2016 Google, Inc
4 */
5
6 #define LOG_CATEGORY LOGC_BOOT
7
8 #include <cpu_func.h>
9 #include <debug_uart.h>
10 #include <dm.h>
11 #include <hang.h>
12 #include <image.h>
13 #include <init.h>
14 #include <irq_func.h>
15 #include <log.h>
16 #include <malloc.h>
17 #include <spl.h>
18 #include <syscon.h>
19 #include <vesa.h>
20 #include <asm/cpu.h>
21 #include <asm/cpu_common.h>
22 #include <asm/fsp2/fsp_api.h>
23 #include <asm/global_data.h>
24 #include <asm/mp.h>
25 #include <asm/mrccache.h>
26 #include <asm/mtrr.h>
27 #include <asm/pci.h>
28 #include <asm/processor.h>
29 #include <asm/qemu.h>
30 #include <asm/spl.h>
31 #include <asm/u-boot-x86.h>
32 #include <asm-generic/sections.h>
33
34 DECLARE_GLOBAL_DATA_PTR;
35
fsp_setup_pinctrl(void * ctx,struct event * event)36 __weak int fsp_setup_pinctrl(void *ctx, struct event *event)
37 {
38 return 0;
39 }
40
41 #ifdef CONFIG_TPL
42
set_max_freq(void)43 static int set_max_freq(void)
44 {
45 if (cpu_get_burst_mode_state() == BURST_MODE_UNAVAILABLE) {
46 /*
47 * Burst Mode has been factory-configured as disabled and is not
48 * available in this physical processor package
49 */
50 debug("Burst Mode is factory-disabled\n");
51 return -ENOENT;
52 }
53
54 /* Enable burst mode */
55 cpu_set_burst_mode(true);
56
57 /* Enable speed step */
58 cpu_set_eist(true);
59
60 /* Set P-State ratio */
61 cpu_set_p_state_to_turbo_ratio();
62
63 return 0;
64 }
65 #endif
66
x86_spl_init(void)67 static int x86_spl_init(void)
68 {
69 struct udevice *dev;
70
71 #ifndef CONFIG_TPL
72 /*
73 * TODO(sjg@chromium.org): We use this area of RAM for the stack
74 * and global_data in SPL. Once U-Boot starts up and releocates it
75 * is not needed. We could make this a CONFIG option or perhaps
76 * place it immediately below CONFIG_TEXT_BASE.
77 */
78 __maybe_unused char *ptr = (char *)0x110000;
79 #else
80 struct udevice *punit;
81 #endif
82 int ret;
83
84 log_debug("x86 spl starting\n");
85 if (IS_ENABLED(CONFIG_TPL))
86 ret = x86_cpu_reinit_f();
87 ret = spl_init();
88 if (ret) {
89 log_debug("spl_init() failed (err=%d)\n", ret);
90 return ret;
91 }
92 ret = arch_cpu_init();
93 if (ret) {
94 log_debug("arch_cpu_init() failed (err=%d)\n", ret);
95 return ret;
96 }
97 #ifndef CONFIG_TPL
98 ret = fsp_setup_pinctrl(NULL, NULL);
99 if (ret) {
100 log_debug("fsp_setup_pinctrl() failed (err=%d)\n", ret);
101 return ret;
102 }
103 #endif
104 /*
105 * spl_board_init() below sets up the console if enabled. If it isn't,
106 * do it here. We cannot call this twice since it results in a double
107 * banner and CI tests fail.
108 */
109 if (!IS_ENABLED(CONFIG_SPL_BOARD_INIT))
110 preloader_console_init();
111 #if !defined(CONFIG_TPL) && !CONFIG_IS_ENABLED(CPU)
112 ret = print_cpuinfo();
113 if (ret) {
114 log_debug("print_cpuinfo() failed (err=%d)\n", ret);
115 return ret;
116 }
117 #endif
118 /* probe the LPC so we get the GPIO_BASE set up correctly */
119 ret = uclass_first_device_err(UCLASS_LPC, &dev);
120 if (ret && ret != -ENODEV) {
121 log_debug("lpc probe failed\n");
122 return ret;
123 }
124
125 ret = dram_init();
126 if (ret) {
127 log_debug("dram_init() failed (err=%d)\n", ret);
128 return ret;
129 }
130 log_debug("mrc\n");
131 if (IS_ENABLED(CONFIG_ENABLE_MRC_CACHE)) {
132 ret = mrccache_spl_save();
133 if (ret)
134 log_debug("Failed to write to mrccache (err=%d)\n",
135 ret);
136 }
137
138 #ifndef CONFIG_SYS_COREBOOT
139 debug("BSS clear from %lx to %lx len %lx\n", (ulong)__bss_start,
140 (ulong)__bss_end, (ulong)__bss_end - (ulong)__bss_start);
141 memset(__bss_start, 0, (ulong)__bss_end - (ulong)__bss_start);
142 # ifndef CONFIG_TPL
143
144 /* TODO(sjg@chromium.org): Consider calling cpu_init_r() here */
145 ret = interrupt_init();
146 if (ret) {
147 debug("%s: interrupt_init() failed\n", __func__);
148 return ret;
149 }
150
151 /*
152 * The stack grows down from ptr. Put the global data at ptr. This
153 * will only be used for SPL. Once SPL loads U-Boot proper it will
154 * set up its own stack.
155 */
156 gd->new_gd = (struct global_data *)ptr;
157 memcpy(gd->new_gd, gd, sizeof(*gd));
158
159 log_debug("logging\n");
160 /*
161 * Make sure logging is disabled when we switch, since the log system
162 * list head will move
163 */
164 gd->new_gd->flags &= ~GD_FLG_LOG_READY;
165 arch_setup_gd(gd->new_gd);
166 gd->start_addr_sp = (ulong)ptr;
167
168 /* start up logging again, with the new list-head location */
169 ret = log_init();
170 if (ret) {
171 log_debug("Log setup failed (err=%d)\n", ret);
172 return ret;
173 }
174
175 if (_LOG_DEBUG) {
176 ret = mtrr_list(mtrr_get_var_count(), MP_SELECT_BSP);
177 if (ret)
178 printf("mtrr_list failed\n");
179 }
180
181 /* Cache the SPI flash. Otherwise copying the code to RAM takes ages */
182 ret = mtrr_add_request(MTRR_TYPE_WRBACK,
183 (1ULL << 32) - CONFIG_XIP_ROM_SIZE,
184 CONFIG_XIP_ROM_SIZE);
185 if (ret) {
186 debug("%s: SPI cache setup failed (err=%d)\n", __func__, ret);
187 return ret;
188 }
189 # else
190 ret = syscon_get_by_driver_data(X86_SYSCON_PUNIT, &punit);
191 if (ret)
192 debug("Could not find PUNIT (err=%d)\n", ret);
193
194 ret = set_max_freq();
195 if (ret)
196 debug("Failed to set CPU frequency (err=%d)\n", ret);
197 # endif
198 #endif
199 log_debug("done\n");
200
201 return 0;
202 }
203
board_init_f(ulong flags)204 void board_init_f(ulong flags)
205 {
206 int ret;
207
208 ret = x86_spl_init();
209 if (ret) {
210 printf("x86_spl_init: error %d\n", ret);
211 hang();
212 }
213 #if IS_ENABLED(CONFIG_TPL) || IS_ENABLED(CONFIG_SYS_COREBOOT)
214 gd->bd = malloc(sizeof(*gd->bd));
215 if (!gd->bd) {
216 printf("Out of memory for bd_info size %x\n", sizeof(*gd->bd));
217 hang();
218 }
219 board_init_r(gd, 0);
220 #else
221 /* Uninit CAR and jump to board_init_f_r() */
222 board_init_f_r_trampoline(gd->start_addr_sp);
223 #endif
224 }
225
board_init_f_r(void)226 void board_init_f_r(void)
227 {
228 mtrr_commit(false);
229 init_cache();
230 gd->flags &= ~GD_FLG_SERIAL_READY;
231
232 /* make sure driver model is not accessed from now on */
233 gd->flags |= GD_FLG_DM_DEAD;
234 debug("cache status %d\n", dcache_status());
235 board_init_r(gd, 0);
236 }
237
spl_boot_device(void)238 u32 spl_boot_device(void)
239 {
240 return BOOT_DEVICE_SPI_MMAP;
241 }
242
spl_start_uboot(void)243 int spl_start_uboot(void)
244 {
245 return 0;
246 }
247
spl_board_announce_boot_device(void)248 void spl_board_announce_boot_device(void)
249 {
250 printf("SPI flash");
251 }
252
spl_board_load_image(struct spl_image_info * spl_image,struct spl_boot_device * bootdev)253 static int spl_board_load_image(struct spl_image_info *spl_image,
254 struct spl_boot_device *bootdev)
255 {
256 spl_image->size = CONFIG_SYS_MONITOR_LEN;
257 spl_image->entry_point = CONFIG_TEXT_BASE;
258 spl_image->load_addr = CONFIG_TEXT_BASE;
259 spl_image->os = IH_OS_U_BOOT;
260 spl_image->name = "U-Boot";
261
262 if (spl_image->load_addr != spl_get_image_pos()) {
263 /* Copy U-Boot from ROM */
264 memcpy((void *)spl_image->load_addr,
265 (void *)spl_get_image_pos(), spl_get_image_size());
266 }
267
268 debug("Loading to %lx\n", spl_image->load_addr);
269
270 return 0;
271 }
272 SPL_LOAD_IMAGE_METHOD("SPI", 5, BOOT_DEVICE_SPI_MMAP, spl_board_load_image);
273
spl_spi_load_image(void)274 int spl_spi_load_image(void)
275 {
276 return -EPERM;
277 }
278
279 #ifdef CONFIG_X86_RUN_64BIT
jump_to_image(struct spl_image_info * spl_image)280 void __noreturn jump_to_image(struct spl_image_info *spl_image)
281 {
282 int ret;
283
284 log_debug("Jumping to 64-bit U-Boot\n");
285 ret = cpu_jump_to_64bit_uboot(spl_image->entry_point);
286 debug("ret=%d\n", ret);
287 hang();
288 }
289 #endif
290
spl_board_init(void)291 void spl_board_init(void)
292 {
293 #ifndef CONFIG_TPL
294 preloader_console_init();
295 #endif
296 if (IS_ENABLED(CONFIG_QEMU))
297 qemu_chipset_init();
298
299 if (CONFIG_IS_ENABLED(UPL_OUT))
300 gd->flags |= GD_FLG_UPL;
301
302 if (CONFIG_IS_ENABLED(VIDEO)) {
303 struct udevice *dev;
304 int ret;
305
306 /* Set up PCI video in SPL if required */
307 ret = uclass_first_device_err(UCLASS_PCI, &dev);
308 if (ret)
309 panic("Failed to set up PCI");
310 ret = uclass_first_device_err(UCLASS_VIDEO, &dev);
311 if (ret)
312 panic("Failed to set up video");
313 }
314 }
315