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