]>
Commit | Line | Data |
---|---|---|
bcae7211 A |
1 | /* |
2 | * (C) Copyright 2010 | |
3 | * Texas Instruments, <www.ti.com> | |
4 | * | |
5 | * Aneesh V <aneesh@ti.com> | |
6 | * | |
1a459660 | 7 | * SPDX-License-Identifier: GPL-2.0+ |
bcae7211 A |
8 | */ |
9 | #include <common.h> | |
11516518 | 10 | #include <dm.h> |
47f7bcae | 11 | #include <spl.h> |
bcae7211 | 12 | #include <asm/u-boot.h> |
bb085b87 | 13 | #include <nand.h> |
8cf686e1 | 14 | #include <fat.h> |
efb2172e | 15 | #include <version.h> |
8cf686e1 | 16 | #include <image.h> |
2d01dd95 | 17 | #include <malloc.h> |
11516518 | 18 | #include <dm/root.h> |
761ca31e | 19 | #include <linux/compiler.h> |
bcae7211 A |
20 | |
21 | DECLARE_GLOBAL_DATA_PTR; | |
22 | ||
3c6f8a0d SR |
23 | #ifndef CONFIG_SYS_UBOOT_START |
24 | #define CONFIG_SYS_UBOOT_START CONFIG_SYS_TEXT_BASE | |
25 | #endif | |
ae83d882 | 26 | #ifndef CONFIG_SYS_MONITOR_LEN |
e76caa62 | 27 | /* Unknown U-Boot size, let's assume it will not be more than 200 KB */ |
ae83d882 SB |
28 | #define CONFIG_SYS_MONITOR_LEN (200 * 1024) |
29 | #endif | |
30 | ||
47f7bcae | 31 | u32 *boot_params_ptr = NULL; |
9ea5c6ef | 32 | |
6507f133 | 33 | /* Define board data structure */ |
bcae7211 A |
34 | static bd_t bdata __attribute__ ((section(".data"))); |
35 | ||
496c5483 HS |
36 | /* |
37 | * Board-specific Platform code can reimplement show_boot_progress () if needed | |
38 | */ | |
39 | __weak void show_boot_progress(int val) {} | |
40 | ||
379c19ab SS |
41 | /* |
42 | * Default function to determine if u-boot or the OS should | |
43 | * be started. This implementation always returns 1. | |
44 | * | |
45 | * Please implement your own board specific funcion to do this. | |
46 | * | |
47 | * RETURN | |
48 | * 0 to not start u-boot | |
49 | * positive if u-boot should start | |
50 | */ | |
51 | #ifdef CONFIG_SPL_OS_BOOT | |
52 | __weak int spl_start_uboot(void) | |
53 | { | |
026b2fe3 TR |
54 | puts("SPL: Please implement spl_start_uboot() for your board\n"); |
55 | puts("SPL: Direct Linux boot not active!\n"); | |
379c19ab SS |
56 | return 1; |
57 | } | |
431889d6 LM |
58 | |
59 | /* | |
60 | * Weak default function for arch specific zImage check. Return zero | |
61 | * and fill start and end address if image is recognized. | |
62 | */ | |
63 | int __weak bootz_setup(ulong image, ulong *start, ulong *end) | |
64 | { | |
65 | return 1; | |
66 | } | |
379c19ab SS |
67 | #endif |
68 | ||
ea8256f0 SR |
69 | /* |
70 | * Weak default function for board specific cleanup/preparation before | |
71 | * Linux boot. Some boards/platforms might not need it, so just provide | |
72 | * an empty stub here. | |
73 | */ | |
74 | __weak void spl_board_prepare_for_linux(void) | |
75 | { | |
76 | /* Nothing to do! */ | |
77 | } | |
78 | ||
3a3b9147 MS |
79 | __weak void spl_board_prepare_for_boot(void) |
80 | { | |
81 | /* Nothing to do! */ | |
82 | } | |
83 | ||
d95ceb97 | 84 | void spl_set_header_raw_uboot(struct spl_image_info *spl_image) |
0c3117b1 | 85 | { |
d95ceb97 SG |
86 | spl_image->size = CONFIG_SYS_MONITOR_LEN; |
87 | spl_image->entry_point = CONFIG_SYS_UBOOT_START; | |
88 | spl_image->load_addr = CONFIG_SYS_TEXT_BASE; | |
89 | spl_image->os = IH_OS_U_BOOT; | |
90 | spl_image->name = "U-Boot"; | |
0c3117b1 HS |
91 | } |
92 | ||
71316c1d SG |
93 | int spl_parse_image_header(struct spl_image_info *spl_image, |
94 | const struct image_header *header) | |
8cf686e1 A |
95 | { |
96 | u32 header_size = sizeof(struct image_header); | |
97 | ||
77552b06 | 98 | if (image_get_magic(header) == IH_MAGIC) { |
71316c1d | 99 | if (spl_image->flags & SPL_COPY_PAYLOAD_ONLY) { |
022b4975 SR |
100 | /* |
101 | * On some system (e.g. powerpc), the load-address and | |
102 | * entry-point is located at address 0. We can't load | |
103 | * to 0-0x40. So skip header in this case. | |
104 | */ | |
71316c1d SG |
105 | spl_image->load_addr = image_get_load(header); |
106 | spl_image->entry_point = image_get_ep(header); | |
107 | spl_image->size = image_get_data_size(header); | |
022b4975 | 108 | } else { |
71316c1d | 109 | spl_image->entry_point = image_get_load(header); |
022b4975 | 110 | /* Load including the header */ |
71316c1d | 111 | spl_image->load_addr = spl_image->entry_point - |
022b4975 | 112 | header_size; |
71316c1d | 113 | spl_image->size = image_get_data_size(header) + |
022b4975 SR |
114 | header_size; |
115 | } | |
71316c1d SG |
116 | spl_image->os = image_get_os(header); |
117 | spl_image->name = image_get_name(header); | |
62cf11c0 | 118 | debug("spl: payload image: %.*s load addr: 0x%x size: %d\n", |
71316c1d SG |
119 | (int)sizeof(spl_image->name), spl_image->name, |
120 | spl_image->load_addr, spl_image->size); | |
8cf686e1 | 121 | } else { |
8c80eb3b AA |
122 | #ifdef CONFIG_SPL_PANIC_ON_RAW_IMAGE |
123 | /* | |
124 | * CONFIG_SPL_PANIC_ON_RAW_IMAGE is defined when the | |
125 | * code which loads images in SPL cannot guarantee that | |
126 | * absolutely all read errors will be reported. | |
127 | * An example is the LPC32XX MLC NAND driver, which | |
128 | * will consider that a completely unreadable NAND block | |
129 | * is bad, and thus should be skipped silently. | |
130 | */ | |
131 | panic("** no mkimage signature but raw image not supported"); | |
85a37729 PK |
132 | #endif |
133 | ||
431889d6 LM |
134 | #ifdef CONFIG_SPL_OS_BOOT |
135 | ulong start, end; | |
136 | ||
137 | if (!bootz_setup((ulong)header, &start, &end)) { | |
71316c1d SG |
138 | spl_image->name = "Linux"; |
139 | spl_image->os = IH_OS_LINUX; | |
140 | spl_image->load_addr = CONFIG_SYS_LOAD_ADDR; | |
141 | spl_image->entry_point = CONFIG_SYS_LOAD_ADDR; | |
142 | spl_image->size = end - start; | |
431889d6 | 143 | debug("spl: payload zImage, load addr: 0x%x size: %d\n", |
71316c1d | 144 | spl_image->load_addr, spl_image->size); |
431889d6 LM |
145 | return 0; |
146 | } | |
147 | #endif | |
85a37729 PK |
148 | |
149 | #ifdef CONFIG_SPL_ABORT_ON_RAW_IMAGE | |
150 | /* Signature not found, proceed to other boot methods. */ | |
151 | return -EINVAL; | |
152 | #else | |
8cf686e1 | 153 | /* Signature not found - assume u-boot.bin */ |
026b2fe3 | 154 | debug("mkimage signature not found - ih_magic = %x\n", |
8cf686e1 | 155 | header->ih_magic); |
71316c1d | 156 | spl_set_header_raw_uboot(spl_image); |
8c80eb3b | 157 | #endif |
8cf686e1 | 158 | } |
7e0f2267 | 159 | return 0; |
8cf686e1 A |
160 | } |
161 | ||
a759f1e0 | 162 | __weak void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image) |
8cf686e1 | 163 | { |
4a0eb757 S |
164 | typedef void __noreturn (*image_entry_noargs_t)(void); |
165 | ||
8cf686e1 | 166 | image_entry_noargs_t image_entry = |
b2d5ac59 | 167 | (image_entry_noargs_t)(unsigned long)spl_image->entry_point; |
8cf686e1 | 168 | |
a759f1e0 | 169 | debug("image entry point: 0x%X\n", spl_image->entry_point); |
4a0eb757 | 170 | image_entry(); |
8cf686e1 A |
171 | } |
172 | ||
8d16e1d5 MS |
173 | #ifndef CONFIG_SPL_LOAD_FIT_ADDRESS |
174 | # define CONFIG_SPL_LOAD_FIT_ADDRESS 0 | |
175 | #endif | |
176 | ||
6f8387f1 | 177 | #if defined(CONFIG_SPL_RAM_DEVICE) || defined(CONFIG_SPL_DFU_SUPPORT) |
8d16e1d5 MS |
178 | static ulong spl_ram_load_read(struct spl_load_info *load, ulong sector, |
179 | ulong count, void *buf) | |
180 | { | |
181 | debug("%s: sector %lx, count %lx, buf %lx\n", | |
182 | __func__, sector, count, (ulong)buf); | |
183 | memcpy(buf, (void *)(CONFIG_SPL_LOAD_FIT_ADDRESS + sector), count); | |
184 | return count; | |
185 | } | |
186 | ||
2a2ee2ac SG |
187 | static int spl_ram_load_image(struct spl_image_info *spl_image, |
188 | struct spl_boot_device *bootdev) | |
c57b953d | 189 | { |
8d16e1d5 MS |
190 | struct image_header *header; |
191 | ||
192 | header = (struct image_header *)CONFIG_SPL_LOAD_FIT_ADDRESS; | |
c57b953d | 193 | |
98136b2f SG |
194 | #if defined(CONFIG_SPL_DFU_SUPPORT) |
195 | if (bootdev->boot_device == BOOT_DEVICE_DFU) | |
196 | spl_dfu_cmd(0, "dfu_alt_info_ram", "ram", "0"); | |
197 | #endif | |
198 | ||
8d16e1d5 MS |
199 | if (IS_ENABLED(CONFIG_SPL_LOAD_FIT) && |
200 | image_get_magic(header) == FDT_MAGIC) { | |
201 | struct spl_load_info load; | |
c57b953d | 202 | |
8d16e1d5 MS |
203 | debug("Found FIT\n"); |
204 | load.bl_len = 1; | |
205 | load.read = spl_ram_load_read; | |
f4d7d859 | 206 | spl_load_simple_fit(spl_image, &load, 0, header); |
8d16e1d5 MS |
207 | } else { |
208 | debug("Legacy image\n"); | |
209 | /* | |
210 | * Get the header. It will point to an address defined by | |
211 | * handoff which will tell where the image located inside | |
212 | * the flash. For now, it will temporary fixed to address | |
213 | * pointed by U-Boot. | |
214 | */ | |
215 | header = (struct image_header *) | |
216 | (CONFIG_SYS_TEXT_BASE - sizeof(struct image_header)); | |
217 | ||
2a2ee2ac | 218 | spl_parse_image_header(spl_image, header); |
8d16e1d5 | 219 | } |
36afd451 NK |
220 | |
221 | return 0; | |
c57b953d | 222 | } |
34ee947a | 223 | #if defined(CONFIG_SPL_RAM_DEVICE) |
ebc4ef61 | 224 | SPL_LOAD_IMAGE_METHOD("RAM", 0, BOOT_DEVICE_RAM, spl_ram_load_image); |
34ee947a | 225 | #endif |
98136b2f | 226 | #if defined(CONFIG_SPL_DFU_SUPPORT) |
ebc4ef61 | 227 | SPL_LOAD_IMAGE_METHOD("USB DFU", 0, BOOT_DEVICE_DFU, spl_ram_load_image); |
98136b2f | 228 | #endif |
c57b953d PM |
229 | #endif |
230 | ||
070d00b8 | 231 | int spl_init(void) |
bcae7211 | 232 | { |
f3d46bd6 SG |
233 | int ret; |
234 | ||
070d00b8 SG |
235 | debug("spl_init()\n"); |
236 | #if defined(CONFIG_SYS_MALLOC_F_LEN) | |
94b9e22e MV |
237 | #ifdef CONFIG_MALLOC_F_ADDR |
238 | gd->malloc_base = CONFIG_MALLOC_F_ADDR; | |
239 | #endif | |
293f16b1 | 240 | gd->malloc_limit = CONFIG_SYS_MALLOC_F_LEN; |
fb4f5e7c | 241 | gd->malloc_ptr = 0; |
24dafad5 | 242 | #endif |
d223e0a8 | 243 | if (CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)) { |
f3d46bd6 SG |
244 | ret = fdtdec_setup(); |
245 | if (ret) { | |
246 | debug("fdtdec_setup() returned error %d\n", ret); | |
070d00b8 | 247 | return ret; |
f3d46bd6 SG |
248 | } |
249 | } | |
250 | if (IS_ENABLED(CONFIG_SPL_DM)) { | |
7d23b9cf SG |
251 | /* With CONFIG_OF_PLATDATA, bring in all devices */ |
252 | ret = dm_init_and_scan(!CONFIG_IS_ENABLED(OF_PLATDATA)); | |
f3d46bd6 SG |
253 | if (ret) { |
254 | debug("dm_init_and_scan() returned error %d\n", ret); | |
070d00b8 | 255 | return ret; |
f3d46bd6 SG |
256 | } |
257 | } | |
070d00b8 | 258 | gd->flags |= GD_FLG_SPL_INIT; |
2d01dd95 | 259 | |
070d00b8 SG |
260 | return 0; |
261 | } | |
262 | ||
f101e4bd NK |
263 | #ifndef BOOT_DEVICE_NONE |
264 | #define BOOT_DEVICE_NONE 0xdeadbeef | |
265 | #endif | |
266 | ||
f101e4bd NK |
267 | __weak void board_boot_order(u32 *spl_boot_list) |
268 | { | |
269 | spl_boot_list[0] = spl_boot_device(); | |
270 | } | |
271 | ||
310c8466 NK |
272 | #ifdef CONFIG_SPL_BOARD_LOAD_IMAGE |
273 | __weak void spl_board_announce_boot_device(void) { } | |
274 | #endif | |
275 | ||
276 | #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT | |
277 | struct boot_device_name { | |
278 | u32 boot_dev; | |
279 | const char *name; | |
280 | }; | |
281 | ||
282 | struct boot_device_name boot_name_table[] = { | |
283 | #ifdef CONFIG_SPL_RAM_DEVICE | |
284 | { BOOT_DEVICE_RAM, "RAM" }, | |
285 | #endif | |
286 | #ifdef CONFIG_SPL_MMC_SUPPORT | |
8f10b5c6 HG |
287 | { BOOT_DEVICE_MMC1, "MMC1" }, |
288 | { BOOT_DEVICE_MMC2, "MMC2" }, | |
289 | { BOOT_DEVICE_MMC2_2, "MMC2_2" }, | |
310c8466 NK |
290 | #endif |
291 | #ifdef CONFIG_SPL_NAND_SUPPORT | |
292 | { BOOT_DEVICE_NAND, "NAND" }, | |
293 | #endif | |
294 | #ifdef CONFIG_SPL_ONENAND_SUPPORT | |
295 | { BOOT_DEVICE_ONENAND, "OneNAND" }, | |
296 | #endif | |
297 | #ifdef CONFIG_SPL_NOR_SUPPORT | |
298 | { BOOT_DEVICE_NOR, "NOR" }, | |
299 | #endif | |
300 | #ifdef CONFIG_SPL_YMODEM_SUPPORT | |
301 | { BOOT_DEVICE_UART, "UART" }, | |
302 | #endif | |
19e99fb4 | 303 | #if defined(CONFIG_SPL_SPI_SUPPORT) || defined(CONFIG_SPL_SPI_FLASH_SUPPORT) |
310c8466 NK |
304 | { BOOT_DEVICE_SPI, "SPI" }, |
305 | #endif | |
306 | #ifdef CONFIG_SPL_ETH_SUPPORT | |
307 | #ifdef CONFIG_SPL_ETH_DEVICE | |
308 | { BOOT_DEVICE_CPGMAC, "eth device" }, | |
309 | #else | |
310 | { BOOT_DEVICE_CPGMAC, "net" }, | |
311 | #endif | |
312 | #endif | |
313 | #ifdef CONFIG_SPL_USBETH_SUPPORT | |
314 | { BOOT_DEVICE_USBETH, "USB eth" }, | |
315 | #endif | |
316 | #ifdef CONFIG_SPL_USB_SUPPORT | |
317 | { BOOT_DEVICE_USB, "USB" }, | |
318 | #endif | |
6f8387f1 R |
319 | #ifdef CONFIG_SPL_DFU_SUPPORT |
320 | { BOOT_DEVICE_DFU, "USB DFU" }, | |
321 | #endif | |
310c8466 NK |
322 | #ifdef CONFIG_SPL_SATA_SUPPORT |
323 | { BOOT_DEVICE_SATA, "SATA" }, | |
324 | #endif | |
325 | /* Keep this entry last */ | |
326 | { BOOT_DEVICE_NONE, "unknown boot device" }, | |
327 | }; | |
328 | ||
329 | static void announce_boot_device(u32 boot_device) | |
330 | { | |
331 | int i; | |
332 | ||
333 | puts("Trying to boot from "); | |
334 | ||
335 | #ifdef CONFIG_SPL_BOARD_LOAD_IMAGE | |
336 | if (boot_device == BOOT_DEVICE_BOARD) { | |
337 | spl_board_announce_boot_device(); | |
338 | puts("\n"); | |
339 | return; | |
340 | } | |
341 | #endif | |
342 | for (i = 0; i < ARRAY_SIZE(boot_name_table) - 1; i++) { | |
343 | if (boot_name_table[i].boot_dev == boot_device) | |
344 | break; | |
345 | } | |
346 | ||
347 | printf("%s\n", boot_name_table[i].name); | |
348 | } | |
349 | #else | |
350 | static inline void announce_boot_device(u32 boot_device) { } | |
351 | #endif | |
352 | ||
a0a80290 SG |
353 | static struct spl_image_loader *spl_ll_find_loader(uint boot_device) |
354 | { | |
355 | struct spl_image_loader *drv = | |
356 | ll_entry_start(struct spl_image_loader, spl_image_loader); | |
357 | const int n_ents = | |
358 | ll_entry_count(struct spl_image_loader, spl_image_loader); | |
359 | struct spl_image_loader *entry; | |
360 | ||
361 | for (entry = drv; entry != drv + n_ents; entry++) { | |
362 | if (boot_device == entry->boot_device) | |
363 | return entry; | |
364 | } | |
365 | ||
366 | /* Not found */ | |
367 | return NULL; | |
368 | } | |
369 | ||
d32b2d1c | 370 | static int spl_load_image(struct spl_image_info *spl_image, u32 boot_device) |
070d00b8 | 371 | { |
ecdfd69a | 372 | struct spl_boot_device bootdev; |
a0a80290 | 373 | struct spl_image_loader *loader = spl_ll_find_loader(boot_device); |
ecdfd69a SG |
374 | |
375 | bootdev.boot_device = boot_device; | |
376 | bootdev.boot_device_name = NULL; | |
a0a80290 | 377 | if (loader) |
d32b2d1c | 378 | return loader->load_image(spl_image, &bootdev); |
ecdfd69a | 379 | |
18f26fdb | 380 | #if defined(CONFIG_SPL_SERIAL_SUPPORT) && defined(CONFIG_SPL_LIBCOMMON_SUPPORT) |
97d9df0a | 381 | puts("SPL: Unsupported Boot Device!\n"); |
18f26fdb | 382 | #endif |
97d9df0a | 383 | return -ENODEV; |
5211b87e NK |
384 | } |
385 | ||
386 | void board_init_r(gd_t *dummy1, ulong dummy2) | |
387 | { | |
d32b2d1c SG |
388 | u32 spl_boot_list[] = { |
389 | BOOT_DEVICE_NONE, | |
390 | BOOT_DEVICE_NONE, | |
391 | BOOT_DEVICE_NONE, | |
392 | BOOT_DEVICE_NONE, | |
393 | BOOT_DEVICE_NONE, | |
394 | }; | |
395 | struct spl_image_info spl_image; | |
f101e4bd | 396 | int i; |
5211b87e NK |
397 | |
398 | debug(">>spl:board_init_r()\n"); | |
399 | ||
400 | #if defined(CONFIG_SYS_SPL_MALLOC_START) | |
401 | mem_malloc_init(CONFIG_SYS_SPL_MALLOC_START, | |
402 | CONFIG_SYS_SPL_MALLOC_SIZE); | |
403 | gd->flags |= GD_FLG_FULL_MALLOC_INIT; | |
404 | #endif | |
405 | if (!(gd->flags & GD_FLG_SPL_INIT)) { | |
406 | if (spl_init()) | |
407 | hang(); | |
408 | } | |
409 | #ifndef CONFIG_PPC | |
410 | /* | |
411 | * timer_init() does not exist on PPC systems. The timer is initialized | |
412 | * and enabled (decrementer) in interrupt_init() here. | |
413 | */ | |
414 | timer_init(); | |
415 | #endif | |
416 | ||
417 | #ifdef CONFIG_SPL_BOARD_INIT | |
418 | spl_board_init(); | |
419 | #endif | |
420 | ||
d32b2d1c | 421 | memset(&spl_image, '\0', sizeof(spl_image)); |
f101e4bd NK |
422 | board_boot_order(spl_boot_list); |
423 | for (i = 0; i < ARRAY_SIZE(spl_boot_list) && | |
424 | spl_boot_list[i] != BOOT_DEVICE_NONE; i++) { | |
310c8466 | 425 | announce_boot_device(spl_boot_list[i]); |
d32b2d1c | 426 | if (!spl_load_image(&spl_image, spl_boot_list[i])) |
f101e4bd NK |
427 | break; |
428 | } | |
429 | ||
430 | if (i == ARRAY_SIZE(spl_boot_list) || | |
431 | spl_boot_list[i] == BOOT_DEVICE_NONE) { | |
432 | puts("SPL: failed to boot from all boot devices\n"); | |
5211b87e | 433 | hang(); |
f101e4bd | 434 | } |
5211b87e | 435 | |
9ea5c6ef | 436 | switch (spl_image.os) { |
8cf686e1 A |
437 | case IH_OS_U_BOOT: |
438 | debug("Jumping to U-Boot\n"); | |
8cf686e1 | 439 | break; |
379c19ab SS |
440 | #ifdef CONFIG_SPL_OS_BOOT |
441 | case IH_OS_LINUX: | |
442 | debug("Jumping to Linux\n"); | |
443 | spl_board_prepare_for_linux(); | |
ca12e65c SG |
444 | jump_to_image_linux(&spl_image, |
445 | (void *)CONFIG_SYS_SPL_ARGS_ADDR); | |
379c19ab | 446 | #endif |
8cf686e1 | 447 | default: |
42120981 | 448 | debug("Unsupported OS image.. Jumping nevertheless..\n"); |
8cf686e1 | 449 | } |
fb4f5e7c SG |
450 | #if defined(CONFIG_SYS_MALLOC_F_LEN) && !defined(CONFIG_SYS_SPL_MALLOC_SIZE) |
451 | debug("SPL malloc() used %#lx bytes (%ld KB)\n", gd->malloc_ptr, | |
452 | gd->malloc_ptr / 1024); | |
453 | #endif | |
454 | ||
aea3d40d | 455 | debug("loaded - jumping to U-Boot..."); |
3a3b9147 | 456 | spl_board_prepare_for_boot(); |
a759f1e0 | 457 | jump_to_image_no_args(&spl_image); |
bcae7211 A |
458 | } |
459 | ||
6507f133 TR |
460 | /* |
461 | * This requires UART clocks to be enabled. In order for this to work the | |
462 | * caller must ensure that the gd pointer is valid. | |
463 | */ | |
bcae7211 A |
464 | void preloader_console_init(void) |
465 | { | |
bcae7211 | 466 | gd->bd = &bdata; |
bcae7211 A |
467 | gd->baudrate = CONFIG_BAUDRATE; |
468 | ||
bcae7211 A |
469 | serial_init(); /* serial communications setup */ |
470 | ||
b88befa5 IY |
471 | gd->have_console = 1; |
472 | ||
026b2fe3 TR |
473 | puts("\nU-Boot SPL " PLAIN_VERSION " (" U_BOOT_DATE " - " \ |
474 | U_BOOT_TIME ")\n"); | |
861a86f4 TR |
475 | #ifdef CONFIG_SPL_DISPLAY_PRINT |
476 | spl_display_print(); | |
477 | #endif | |
cc3f7058 | 478 | } |
db910353 SG |
479 | |
480 | /** | |
481 | * spl_relocate_stack_gd() - Relocate stack ready for board_init_r() execution | |
482 | * | |
483 | * Sometimes board_init_f() runs with a stack in SRAM but we want to use SDRAM | |
484 | * for the main board_init_r() execution. This is typically because we need | |
485 | * more stack space for things like the MMC sub-system. | |
486 | * | |
487 | * This function calculates the stack position, copies the global_data into | |
adc421e4 AA |
488 | * place, sets the new gd (except for ARM, for which setting GD within a C |
489 | * function may not always work) and returns the new stack position. The | |
490 | * caller is responsible for setting up the sp register and, in the case | |
491 | * of ARM, setting up gd. | |
492 | * | |
493 | * All of this is done using the same layout and alignments as done in | |
494 | * board_init_f_init_reserve() / board_init_f_alloc_reserve(). | |
db910353 SG |
495 | * |
496 | * @return new stack location, or 0 to use the same stack | |
497 | */ | |
498 | ulong spl_relocate_stack_gd(void) | |
499 | { | |
500 | #ifdef CONFIG_SPL_STACK_R | |
501 | gd_t *new_gd; | |
adc421e4 | 502 | ulong ptr = CONFIG_SPL_STACK_R_ADDR; |
db910353 | 503 | |
dcfcb8d4 HG |
504 | #ifdef CONFIG_SPL_SYS_MALLOC_SIMPLE |
505 | if (CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN) { | |
dcfcb8d4 HG |
506 | ptr -= CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN; |
507 | gd->malloc_base = ptr; | |
508 | gd->malloc_limit = CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN; | |
509 | gd->malloc_ptr = 0; | |
510 | } | |
511 | #endif | |
adc421e4 AA |
512 | /* Get stack position: use 8-byte alignment for ABI compliance */ |
513 | ptr = CONFIG_SPL_STACK_R_ADDR - roundup(sizeof(gd_t),16); | |
514 | new_gd = (gd_t *)ptr; | |
515 | memcpy(new_gd, (void *)gd, sizeof(gd_t)); | |
2f11cd91 SG |
516 | #if CONFIG_IS_ENABLED(DM) |
517 | dm_fixup_for_gd_move(new_gd); | |
518 | #endif | |
adc421e4 AA |
519 | #if !defined(CONFIG_ARM) |
520 | gd = new_gd; | |
521 | #endif | |
db910353 SG |
522 | return ptr; |
523 | #else | |
524 | return 0; | |
525 | #endif | |
526 | } |