183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
21938f4a5SSimon Glass /*
31938f4a5SSimon Glass * Copyright (c) 2011 The Chromium OS Authors.
41938f4a5SSimon Glass * (C) Copyright 2002-2006
51938f4a5SSimon Glass * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
61938f4a5SSimon Glass *
71938f4a5SSimon Glass * (C) Copyright 2002
81938f4a5SSimon Glass * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
91938f4a5SSimon Glass * Marius Groeger <mgroeger@sysgo.de>
101938f4a5SSimon Glass */
111938f4a5SSimon Glass
121938f4a5SSimon Glass #include <common.h>
13f0293d33SSimon Glass #include <bloblist.h>
1424b852a7SSimon Glass #include <console.h>
155d6c61acSMario Six #include <cpu.h>
16ab7cd627SSimon Glass #include <dm.h>
17138181a5SMario Six #include <environment.h>
181938f4a5SSimon Glass #include <fdtdec.h>
19f828bf25SSimon Glass #include <fs.h>
20e4fef6cfSSimon Glass #include <i2c.h>
211938f4a5SSimon Glass #include <initcall.h>
22fb5cf7f1SSimon Glass #include <malloc.h>
230eb25b61SJoe Hershberger #include <mapmem.h>
24a733b06bSSimon Glass #include <os.h>
251938f4a5SSimon Glass #include <post.h>
26e47b2d67SSimon Glass #include <relocate.h>
27*b0edea3cSSimon Glass #ifdef CONFIG_SPL
28*b0edea3cSSimon Glass #include <spl.h>
29*b0edea3cSSimon Glass #endif
30c5d4001aSJeroen Hofstee #include <status_led.h>
3123471aedSMario Six #include <sysreset.h>
321057e6cfSSimon Glass #include <timer.h>
3371c52dbaSSimon Glass #include <trace.h>
345a541945SSimon Glass #include <video.h>
35e4fef6cfSSimon Glass #include <watchdog.h>
36b885d02eSSimon Glass #ifdef CONFIG_MACH_TYPE
37b885d02eSSimon Glass #include <asm/mach-types.h>
38b885d02eSSimon Glass #endif
391fbf97dcSSimon Glass #if defined(CONFIG_MP) && defined(CONFIG_PPC)
401fbf97dcSSimon Glass #include <asm/mp.h>
411fbf97dcSSimon Glass #endif
421938f4a5SSimon Glass #include <asm/io.h>
431938f4a5SSimon Glass #include <asm/sections.h>
44ab7cd627SSimon Glass #include <dm/root.h>
45056285fdSSimon Glass #include <linux/errno.h>
461938f4a5SSimon Glass
471938f4a5SSimon Glass /*
481938f4a5SSimon Glass * Pointer to initial global data area
491938f4a5SSimon Glass *
501938f4a5SSimon Glass * Here we initialize it if needed.
511938f4a5SSimon Glass */
521938f4a5SSimon Glass #ifdef XTRN_DECLARE_GLOBAL_DATA_PTR
531938f4a5SSimon Glass #undef XTRN_DECLARE_GLOBAL_DATA_PTR
541938f4a5SSimon Glass #define XTRN_DECLARE_GLOBAL_DATA_PTR /* empty = allocate here */
551938f4a5SSimon Glass DECLARE_GLOBAL_DATA_PTR = (gd_t *)(CONFIG_SYS_INIT_GD_ADDR);
561938f4a5SSimon Glass #else
571938f4a5SSimon Glass DECLARE_GLOBAL_DATA_PTR;
581938f4a5SSimon Glass #endif
591938f4a5SSimon Glass
601938f4a5SSimon Glass /*
614c509343SSimon Glass * TODO(sjg@chromium.org): IMO this code should be
621938f4a5SSimon Glass * refactored to a single function, something like:
631938f4a5SSimon Glass *
641938f4a5SSimon Glass * void led_set_state(enum led_colour_t colour, int on);
651938f4a5SSimon Glass */
661938f4a5SSimon Glass /************************************************************************
671938f4a5SSimon Glass * Coloured LED functionality
681938f4a5SSimon Glass ************************************************************************
691938f4a5SSimon Glass * May be supplied by boards if desired
701938f4a5SSimon Glass */
coloured_LED_init(void)71c5d4001aSJeroen Hofstee __weak void coloured_LED_init(void) {}
red_led_on(void)72c5d4001aSJeroen Hofstee __weak void red_led_on(void) {}
red_led_off(void)73c5d4001aSJeroen Hofstee __weak void red_led_off(void) {}
green_led_on(void)74c5d4001aSJeroen Hofstee __weak void green_led_on(void) {}
green_led_off(void)75c5d4001aSJeroen Hofstee __weak void green_led_off(void) {}
yellow_led_on(void)76c5d4001aSJeroen Hofstee __weak void yellow_led_on(void) {}
yellow_led_off(void)77c5d4001aSJeroen Hofstee __weak void yellow_led_off(void) {}
blue_led_on(void)78c5d4001aSJeroen Hofstee __weak void blue_led_on(void) {}
blue_led_off(void)79c5d4001aSJeroen Hofstee __weak void blue_led_off(void) {}
801938f4a5SSimon Glass
811938f4a5SSimon Glass /*
821938f4a5SSimon Glass * Why is gd allocated a register? Prior to reloc it might be better to
831938f4a5SSimon Glass * just pass it around to each function in this file?
841938f4a5SSimon Glass *
851938f4a5SSimon Glass * After reloc one could argue that it is hardly used and doesn't need
861938f4a5SSimon Glass * to be in a register. Or if it is it should perhaps hold pointers to all
871938f4a5SSimon Glass * global data for all modules, so that post-reloc we can avoid the massive
881938f4a5SSimon Glass * literal pool we get on ARM. Or perhaps just encourage each module to use
891938f4a5SSimon Glass * a structure...
901938f4a5SSimon Glass */
911938f4a5SSimon Glass
92d54d7eb9SSonic Zhang #if defined(CONFIG_WATCHDOG) || defined(CONFIG_HW_WATCHDOG)
init_func_watchdog_init(void)93e4fef6cfSSimon Glass static int init_func_watchdog_init(void)
94e4fef6cfSSimon Glass {
95ea3310e8STom Rini # if defined(CONFIG_HW_WATCHDOG) && \
96ea3310e8STom Rini (defined(CONFIG_M68K) || defined(CONFIG_MICROBLAZE) || \
971473f6acSPrasanthi Chellakumar defined(CONFIG_SH) || \
9846d7a3b3SAnatolij Gustschin defined(CONFIG_DESIGNWARE_WATCHDOG) || \
9914a380a8SStefan Roese defined(CONFIG_IMX_WATCHDOG))
100d54d7eb9SSonic Zhang hw_watchdog_init();
101e4fef6cfSSimon Glass puts(" Watchdog enabled\n");
102ba169d98SAnatolij Gustschin # endif
103e4fef6cfSSimon Glass WATCHDOG_RESET();
104e4fef6cfSSimon Glass
105e4fef6cfSSimon Glass return 0;
106e4fef6cfSSimon Glass }
107e4fef6cfSSimon Glass
init_func_watchdog_reset(void)108e4fef6cfSSimon Glass int init_func_watchdog_reset(void)
109e4fef6cfSSimon Glass {
110e4fef6cfSSimon Glass WATCHDOG_RESET();
111e4fef6cfSSimon Glass
112e4fef6cfSSimon Glass return 0;
113e4fef6cfSSimon Glass }
114e4fef6cfSSimon Glass #endif /* CONFIG_WATCHDOG */
115e4fef6cfSSimon Glass
board_add_ram_info(int use_default)116dd2a6cd0SJeroen Hofstee __weak void board_add_ram_info(int use_default)
117e4fef6cfSSimon Glass {
118e4fef6cfSSimon Glass /* please define platform specific board_add_ram_info() */
119e4fef6cfSSimon Glass }
120e4fef6cfSSimon Glass
init_baud_rate(void)1211938f4a5SSimon Glass static int init_baud_rate(void)
1221938f4a5SSimon Glass {
123bfebc8c9SSimon Glass gd->baudrate = env_get_ulong("baudrate", 10, CONFIG_BAUDRATE);
1241938f4a5SSimon Glass return 0;
1251938f4a5SSimon Glass }
1261938f4a5SSimon Glass
display_text_info(void)1271938f4a5SSimon Glass static int display_text_info(void)
1281938f4a5SSimon Glass {
1299b217498SBen Stoltz #if !defined(CONFIG_SANDBOX) && !defined(CONFIG_EFI_APP)
1309fdee7d7SDaniel Schwierzeck ulong bss_start, bss_end, text_base;
1311938f4a5SSimon Glass
132632efa74SSimon Glass bss_start = (ulong)&__bss_start;
133632efa74SSimon Glass bss_end = (ulong)&__bss_end;
134b60eff31SAlbert ARIBAUD
135d54d7eb9SSonic Zhang #ifdef CONFIG_SYS_TEXT_BASE
1369fdee7d7SDaniel Schwierzeck text_base = CONFIG_SYS_TEXT_BASE;
137d54d7eb9SSonic Zhang #else
1389fdee7d7SDaniel Schwierzeck text_base = CONFIG_SYS_MONITOR_BASE;
139d54d7eb9SSonic Zhang #endif
1409fdee7d7SDaniel Schwierzeck
1419fdee7d7SDaniel Schwierzeck debug("U-Boot code: %08lX -> %08lX BSS: -> %08lX\n",
1429fdee7d7SDaniel Schwierzeck text_base, bss_start, bss_end);
143a733b06bSSimon Glass #endif
1441938f4a5SSimon Glass
1451938f4a5SSimon Glass return 0;
1461938f4a5SSimon Glass }
1471938f4a5SSimon Glass
14823471aedSMario Six #ifdef CONFIG_SYSRESET
print_resetinfo(void)14923471aedSMario Six static int print_resetinfo(void)
15023471aedSMario Six {
15123471aedSMario Six struct udevice *dev;
15223471aedSMario Six char status[256];
15323471aedSMario Six int ret;
15423471aedSMario Six
15523471aedSMario Six ret = uclass_first_device_err(UCLASS_SYSRESET, &dev);
15623471aedSMario Six if (ret) {
15723471aedSMario Six debug("%s: No sysreset device found (error: %d)\n",
15823471aedSMario Six __func__, ret);
15923471aedSMario Six /* Not all boards have sysreset drivers available during early
16023471aedSMario Six * boot, so don't fail if one can't be found.
16123471aedSMario Six */
16223471aedSMario Six return 0;
16323471aedSMario Six }
16423471aedSMario Six
16523471aedSMario Six if (!sysreset_get_status(dev, status, sizeof(status)))
16623471aedSMario Six printf("%s", status);
16723471aedSMario Six
16823471aedSMario Six return 0;
16923471aedSMario Six }
17023471aedSMario Six #endif
17123471aedSMario Six
1725d6c61acSMario Six #if defined(CONFIG_DISPLAY_CPUINFO) && CONFIG_IS_ENABLED(CPU)
print_cpuinfo(void)1735d6c61acSMario Six static int print_cpuinfo(void)
1745d6c61acSMario Six {
1755d6c61acSMario Six struct udevice *dev;
1765d6c61acSMario Six char desc[512];
1775d6c61acSMario Six int ret;
1785d6c61acSMario Six
1795d6c61acSMario Six ret = uclass_first_device_err(UCLASS_CPU, &dev);
1805d6c61acSMario Six if (ret) {
1815d6c61acSMario Six debug("%s: Could not get CPU device (err = %d)\n",
1825d6c61acSMario Six __func__, ret);
1835d6c61acSMario Six return ret;
1845d6c61acSMario Six }
1855d6c61acSMario Six
1865d6c61acSMario Six ret = cpu_get_desc(dev, desc, sizeof(desc));
1875d6c61acSMario Six if (ret) {
1885d6c61acSMario Six debug("%s: Could not get CPU description (err = %d)\n",
1895d6c61acSMario Six dev->name, ret);
1905d6c61acSMario Six return ret;
1915d6c61acSMario Six }
1925d6c61acSMario Six
193ecfe6633SBin Meng printf("CPU: %s\n", desc);
1945d6c61acSMario Six
1955d6c61acSMario Six return 0;
1965d6c61acSMario Six }
1975d6c61acSMario Six #endif
1985d6c61acSMario Six
announce_dram_init(void)1991938f4a5SSimon Glass static int announce_dram_init(void)
2001938f4a5SSimon Glass {
2011938f4a5SSimon Glass puts("DRAM: ");
2021938f4a5SSimon Glass return 0;
2031938f4a5SSimon Glass }
2041938f4a5SSimon Glass
show_dram_config(void)2051938f4a5SSimon Glass static int show_dram_config(void)
2061938f4a5SSimon Glass {
207fa39ffe5SYork Sun unsigned long long size;
2081938f4a5SSimon Glass
2091938f4a5SSimon Glass #ifdef CONFIG_NR_DRAM_BANKS
2101938f4a5SSimon Glass int i;
2111938f4a5SSimon Glass
2121938f4a5SSimon Glass debug("\nRAM Configuration:\n");
2131938f4a5SSimon Glass for (i = size = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
2141938f4a5SSimon Glass size += gd->bd->bi_dram[i].size;
215715f599fSBin Meng debug("Bank #%d: %llx ", i,
216715f599fSBin Meng (unsigned long long)(gd->bd->bi_dram[i].start));
2171938f4a5SSimon Glass #ifdef DEBUG
2181938f4a5SSimon Glass print_size(gd->bd->bi_dram[i].size, "\n");
2191938f4a5SSimon Glass #endif
2201938f4a5SSimon Glass }
2211938f4a5SSimon Glass debug("\nDRAM: ");
2221938f4a5SSimon Glass #else
2231938f4a5SSimon Glass size = gd->ram_size;
2241938f4a5SSimon Glass #endif
2251938f4a5SSimon Glass
226e4fef6cfSSimon Glass print_size(size, "");
227e4fef6cfSSimon Glass board_add_ram_info(0);
228e4fef6cfSSimon Glass putc('\n');
2291938f4a5SSimon Glass
2301938f4a5SSimon Glass return 0;
2311938f4a5SSimon Glass }
2321938f4a5SSimon Glass
dram_init_banksize(void)23376b00acaSSimon Glass __weak int dram_init_banksize(void)
2341938f4a5SSimon Glass {
2351938f4a5SSimon Glass #if defined(CONFIG_NR_DRAM_BANKS) && defined(CONFIG_SYS_SDRAM_BASE)
2361938f4a5SSimon Glass gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE;
2371938f4a5SSimon Glass gd->bd->bi_dram[0].size = get_effective_memsize();
2381938f4a5SSimon Glass #endif
23976b00acaSSimon Glass
24076b00acaSSimon Glass return 0;
2411938f4a5SSimon Glass }
2421938f4a5SSimon Glass
24369153988SSimon Glass #if defined(CONFIG_SYS_I2C)
init_func_i2c(void)244e4fef6cfSSimon Glass static int init_func_i2c(void)
245e4fef6cfSSimon Glass {
246e4fef6cfSSimon Glass puts("I2C: ");
247815a76f2Strem #ifdef CONFIG_SYS_I2C
248815a76f2Strem i2c_init_all();
249815a76f2Strem #else
250e4fef6cfSSimon Glass i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
251815a76f2Strem #endif
252e4fef6cfSSimon Glass puts("ready\n");
253e4fef6cfSSimon Glass return 0;
254e4fef6cfSSimon Glass }
255e4fef6cfSSimon Glass #endif
256e4fef6cfSSimon Glass
2571fab98fbSRajesh Bhagat #if defined(CONFIG_VID)
init_func_vid(void)2581fab98fbSRajesh Bhagat __weak int init_func_vid(void)
2591fab98fbSRajesh Bhagat {
2601fab98fbSRajesh Bhagat return 0;
2611fab98fbSRajesh Bhagat }
2621fab98fbSRajesh Bhagat #endif
2631fab98fbSRajesh Bhagat
setup_mon_len(void)2641938f4a5SSimon Glass static int setup_mon_len(void)
2651938f4a5SSimon Glass {
266e945f6dcSMichal Simek #if defined(__ARM__) || defined(__MICROBLAZE__)
267b60eff31SAlbert ARIBAUD gd->mon_len = (ulong)&__bss_end - (ulong)_start;
2689b217498SBen Stoltz #elif defined(CONFIG_SANDBOX) || defined(CONFIG_EFI_APP)
269a733b06bSSimon Glass gd->mon_len = (ulong)&_end - (ulong)_init;
270ea3310e8STom Rini #elif defined(CONFIG_NIOS2) || defined(CONFIG_XTENSA)
271d54d7eb9SSonic Zhang gd->mon_len = CONFIG_SYS_MONITOR_LEN;
272068feb9bSRick Chen #elif defined(CONFIG_NDS32) || defined(CONFIG_SH) || defined(CONFIG_RISCV)
2732e88bb28SKun-Hua Huang gd->mon_len = (ulong)(&__bss_end) - (ulong)(&_start);
274b0b35953SSimon Glass #elif defined(CONFIG_SYS_MONITOR_BASE)
275e4fef6cfSSimon Glass /* TODO: use (ulong)&__bss_end - (ulong)&__text_start; ? */
276e4fef6cfSSimon Glass gd->mon_len = (ulong)&__bss_end - CONFIG_SYS_MONITOR_BASE;
277632efa74SSimon Glass #endif
2781938f4a5SSimon Glass return 0;
2791938f4a5SSimon Glass }
2801938f4a5SSimon Glass
setup_spl_handoff(void)281*b0edea3cSSimon Glass static int setup_spl_handoff(void)
282*b0edea3cSSimon Glass {
283*b0edea3cSSimon Glass #if CONFIG_IS_ENABLED(HANDOFF)
284*b0edea3cSSimon Glass gd->spl_handoff = bloblist_find(BLOBLISTT_SPL_HANDOFF,
285*b0edea3cSSimon Glass sizeof(struct spl_handoff));
286*b0edea3cSSimon Glass debug("Found SPL hand-off info %p\n", gd->spl_handoff);
287*b0edea3cSSimon Glass #endif
288*b0edea3cSSimon Glass
289*b0edea3cSSimon Glass return 0;
290*b0edea3cSSimon Glass }
291*b0edea3cSSimon Glass
arch_cpu_init(void)2921938f4a5SSimon Glass __weak int arch_cpu_init(void)
2931938f4a5SSimon Glass {
2941938f4a5SSimon Glass return 0;
2951938f4a5SSimon Glass }
2961938f4a5SSimon Glass
mach_cpu_init(void)2978ebf5069SPaul Burton __weak int mach_cpu_init(void)
2988ebf5069SPaul Burton {
2998ebf5069SPaul Burton return 0;
3008ebf5069SPaul Burton }
3018ebf5069SPaul Burton
3021938f4a5SSimon Glass /* Get the top of usable RAM */
board_get_usable_ram_top(ulong total_size)3031938f4a5SSimon Glass __weak ulong board_get_usable_ram_top(ulong total_size)
3041938f4a5SSimon Glass {
3051e4d11a5SStephen Warren #ifdef CONFIG_SYS_SDRAM_BASE
3061e4d11a5SStephen Warren /*
3074c509343SSimon Glass * Detect whether we have so much RAM that it goes past the end of our
3081e4d11a5SStephen Warren * 32-bit address space. If so, clip the usable RAM so it doesn't.
3091e4d11a5SStephen Warren */
3101e4d11a5SStephen Warren if (gd->ram_top < CONFIG_SYS_SDRAM_BASE)
3111e4d11a5SStephen Warren /*
3121e4d11a5SStephen Warren * Will wrap back to top of 32-bit space when reservations
3131e4d11a5SStephen Warren * are made.
3141e4d11a5SStephen Warren */
3151e4d11a5SStephen Warren return 0;
3161e4d11a5SStephen Warren #endif
3171938f4a5SSimon Glass return gd->ram_top;
3181938f4a5SSimon Glass }
3191938f4a5SSimon Glass
setup_dest_addr(void)3201938f4a5SSimon Glass static int setup_dest_addr(void)
3211938f4a5SSimon Glass {
3221938f4a5SSimon Glass debug("Monitor len: %08lX\n", gd->mon_len);
3231938f4a5SSimon Glass /*
3241938f4a5SSimon Glass * Ram is setup, size stored in gd !!
3251938f4a5SSimon Glass */
3261938f4a5SSimon Glass debug("Ram size: %08lX\n", (ulong)gd->ram_size);
32736cc0de0SYork Sun #if defined(CONFIG_SYS_MEM_TOP_HIDE)
3281938f4a5SSimon Glass /*
3291938f4a5SSimon Glass * Subtract specified amount of memory to hide so that it won't
3301938f4a5SSimon Glass * get "touched" at all by U-Boot. By fixing up gd->ram_size
3311938f4a5SSimon Glass * the Linux kernel should now get passed the now "corrected"
33236cc0de0SYork Sun * memory size and won't touch it either. This should work
33336cc0de0SYork Sun * for arch/ppc and arch/powerpc. Only Linux board ports in
33436cc0de0SYork Sun * arch/powerpc with bootwrapper support, that recalculate the
33536cc0de0SYork Sun * memory size from the SDRAM controller setup will have to
33636cc0de0SYork Sun * get fixed.
3371938f4a5SSimon Glass */
33836cc0de0SYork Sun gd->ram_size -= CONFIG_SYS_MEM_TOP_HIDE;
33936cc0de0SYork Sun #endif
3401938f4a5SSimon Glass #ifdef CONFIG_SYS_SDRAM_BASE
3411473b12aSSiva Durga Prasad Paladugu gd->ram_base = CONFIG_SYS_SDRAM_BASE;
3421938f4a5SSimon Glass #endif
3431473b12aSSiva Durga Prasad Paladugu gd->ram_top = gd->ram_base + get_effective_memsize();
3441938f4a5SSimon Glass gd->ram_top = board_get_usable_ram_top(gd->mon_len);
345a0ba279aSMasahiro Yamada gd->relocaddr = gd->ram_top;
3461938f4a5SSimon Glass debug("Ram top: %08lX\n", (ulong)gd->ram_top);
347ec3b4820SGabriel Huau #if defined(CONFIG_MP) && (defined(CONFIG_MPC86xx) || defined(CONFIG_E500))
348e4fef6cfSSimon Glass /*
349e4fef6cfSSimon Glass * We need to make sure the location we intend to put secondary core
350e4fef6cfSSimon Glass * boot code is reserved and not used by any part of u-boot
351e4fef6cfSSimon Glass */
352a0ba279aSMasahiro Yamada if (gd->relocaddr > determine_mp_bootpg(NULL)) {
353a0ba279aSMasahiro Yamada gd->relocaddr = determine_mp_bootpg(NULL);
354a0ba279aSMasahiro Yamada debug("Reserving MP boot page to %08lx\n", gd->relocaddr);
355e4fef6cfSSimon Glass }
356e4fef6cfSSimon Glass #endif
3571938f4a5SSimon Glass return 0;
3581938f4a5SSimon Glass }
3591938f4a5SSimon Glass
3601938f4a5SSimon Glass #ifdef CONFIG_PRAM
3611938f4a5SSimon Glass /* reserve protected RAM */
reserve_pram(void)3621938f4a5SSimon Glass static int reserve_pram(void)
3631938f4a5SSimon Glass {
3641938f4a5SSimon Glass ulong reg;
3651938f4a5SSimon Glass
366bfebc8c9SSimon Glass reg = env_get_ulong("pram", 10, CONFIG_PRAM);
367a0ba279aSMasahiro Yamada gd->relocaddr -= (reg << 10); /* size is in kB */
3681938f4a5SSimon Glass debug("Reserving %ldk for protected RAM at %08lx\n", reg,
369a0ba279aSMasahiro Yamada gd->relocaddr);
3701938f4a5SSimon Glass return 0;
3711938f4a5SSimon Glass }
3721938f4a5SSimon Glass #endif /* CONFIG_PRAM */
3731938f4a5SSimon Glass
3741938f4a5SSimon Glass /* Round memory pointer down to next 4 kB limit */
reserve_round_4k(void)3751938f4a5SSimon Glass static int reserve_round_4k(void)
3761938f4a5SSimon Glass {
377a0ba279aSMasahiro Yamada gd->relocaddr &= ~(4096 - 1);
3781938f4a5SSimon Glass return 0;
3791938f4a5SSimon Glass }
3801938f4a5SSimon Glass
38180d4bcd3SSimon Glass #ifdef CONFIG_ARM
reserve_mmu(void)38260873f73SSiva Durga Prasad Paladugu __weak int reserve_mmu(void)
3831938f4a5SSimon Glass {
38480d4bcd3SSimon Glass #if !(defined(CONFIG_SYS_ICACHE_OFF) && defined(CONFIG_SYS_DCACHE_OFF))
3851938f4a5SSimon Glass /* reserve TLB table */
386cce6be7fSDavid Feng gd->arch.tlb_size = PGTABLE_SIZE;
387a0ba279aSMasahiro Yamada gd->relocaddr -= gd->arch.tlb_size;
3881938f4a5SSimon Glass
3891938f4a5SSimon Glass /* round down to next 64 kB limit */
390a0ba279aSMasahiro Yamada gd->relocaddr &= ~(0x10000 - 1);
3911938f4a5SSimon Glass
392a0ba279aSMasahiro Yamada gd->arch.tlb_addr = gd->relocaddr;
3931938f4a5SSimon Glass debug("TLB table from %08lx to %08lx\n", gd->arch.tlb_addr,
3941938f4a5SSimon Glass gd->arch.tlb_addr + gd->arch.tlb_size);
39550e93b95SYork Sun
39650e93b95SYork Sun #ifdef CONFIG_SYS_MEM_RESERVE_SECURE
39750e93b95SYork Sun /*
39850e93b95SYork Sun * Record allocated tlb_addr in case gd->tlb_addr to be overwritten
39950e93b95SYork Sun * with location within secure ram.
40050e93b95SYork Sun */
40150e93b95SYork Sun gd->arch.tlb_allocated = gd->arch.tlb_addr;
40250e93b95SYork Sun #endif
40380d4bcd3SSimon Glass #endif
40450e93b95SYork Sun
4051938f4a5SSimon Glass return 0;
4061938f4a5SSimon Glass }
4071938f4a5SSimon Glass #endif
4081938f4a5SSimon Glass
reserve_video(void)4095a541945SSimon Glass static int reserve_video(void)
4105a541945SSimon Glass {
4110f079eb5SSimon Glass #ifdef CONFIG_DM_VIDEO
4125a541945SSimon Glass ulong addr;
4135a541945SSimon Glass int ret;
4145a541945SSimon Glass
4155a541945SSimon Glass addr = gd->relocaddr;
4165a541945SSimon Glass ret = video_reserve(&addr);
4175a541945SSimon Glass if (ret)
4185a541945SSimon Glass return ret;
4195a541945SSimon Glass gd->relocaddr = addr;
4200f079eb5SSimon Glass #elif defined(CONFIG_LCD)
4211938f4a5SSimon Glass # ifdef CONFIG_FB_ADDR
4221938f4a5SSimon Glass gd->fb_base = CONFIG_FB_ADDR;
4231938f4a5SSimon Glass # else
4241938f4a5SSimon Glass /* reserve memory for LCD display (always full pages) */
425a0ba279aSMasahiro Yamada gd->relocaddr = lcd_setmem(gd->relocaddr);
426a0ba279aSMasahiro Yamada gd->fb_base = gd->relocaddr;
4271938f4a5SSimon Glass # endif /* CONFIG_FB_ADDR */
4280f079eb5SSimon Glass #elif defined(CONFIG_VIDEO) && \
4295b8e76c3SHeiko Schocher (!defined(CONFIG_PPC)) && \
4308703ef3fSSimon Glass !defined(CONFIG_ARM) && !defined(CONFIG_X86) && \
431ea3310e8STom Rini !defined(CONFIG_M68K)
4328703ef3fSSimon Glass /* reserve memory for video display (always full pages) */
4338703ef3fSSimon Glass gd->relocaddr = video_setmem(gd->relocaddr);
4348703ef3fSSimon Glass gd->fb_base = gd->relocaddr;
4350f079eb5SSimon Glass #endif
4368703ef3fSSimon Glass
4378703ef3fSSimon Glass return 0;
4388703ef3fSSimon Glass }
4398703ef3fSSimon Glass
reserve_trace(void)44071c52dbaSSimon Glass static int reserve_trace(void)
44171c52dbaSSimon Glass {
44271c52dbaSSimon Glass #ifdef CONFIG_TRACE
44371c52dbaSSimon Glass gd->relocaddr -= CONFIG_TRACE_BUFFER_SIZE;
44471c52dbaSSimon Glass gd->trace_buff = map_sysmem(gd->relocaddr, CONFIG_TRACE_BUFFER_SIZE);
44571c52dbaSSimon Glass debug("Reserving %dk for trace data at: %08lx\n",
44671c52dbaSSimon Glass CONFIG_TRACE_BUFFER_SIZE >> 10, gd->relocaddr);
44771c52dbaSSimon Glass #endif
44871c52dbaSSimon Glass
44971c52dbaSSimon Glass return 0;
45071c52dbaSSimon Glass }
45171c52dbaSSimon Glass
reserve_uboot(void)4521938f4a5SSimon Glass static int reserve_uboot(void)
4531938f4a5SSimon Glass {
454ff2b2ba8SAlexey Brodkin if (!(gd->flags & GD_FLG_SKIP_RELOC)) {
4551938f4a5SSimon Glass /*
4561938f4a5SSimon Glass * reserve memory for U-Boot code, data & bss
4571938f4a5SSimon Glass * round down to next 4 kB limit
4581938f4a5SSimon Glass */
459a0ba279aSMasahiro Yamada gd->relocaddr -= gd->mon_len;
460a0ba279aSMasahiro Yamada gd->relocaddr &= ~(4096 - 1);
461703ec9ddSPaul Burton #if defined(CONFIG_E500) || defined(CONFIG_MIPS)
462e4fef6cfSSimon Glass /* round down to next 64 kB limit so that IVPR stays aligned */
463a0ba279aSMasahiro Yamada gd->relocaddr &= ~(65536 - 1);
464e4fef6cfSSimon Glass #endif
4651938f4a5SSimon Glass
466ff2b2ba8SAlexey Brodkin debug("Reserving %ldk for U-Boot at: %08lx\n",
467ff2b2ba8SAlexey Brodkin gd->mon_len >> 10, gd->relocaddr);
468ff2b2ba8SAlexey Brodkin }
469a0ba279aSMasahiro Yamada
470a0ba279aSMasahiro Yamada gd->start_addr_sp = gd->relocaddr;
471a0ba279aSMasahiro Yamada
4721938f4a5SSimon Glass return 0;
4731938f4a5SSimon Glass }
4741938f4a5SSimon Glass
4751938f4a5SSimon Glass /* reserve memory for malloc() area */
reserve_malloc(void)4761938f4a5SSimon Glass static int reserve_malloc(void)
4771938f4a5SSimon Glass {
478a0ba279aSMasahiro Yamada gd->start_addr_sp = gd->start_addr_sp - TOTAL_MALLOC_LEN;
4791938f4a5SSimon Glass debug("Reserving %dk for malloc() at: %08lx\n",
480a0ba279aSMasahiro Yamada TOTAL_MALLOC_LEN >> 10, gd->start_addr_sp);
4811938f4a5SSimon Glass return 0;
4821938f4a5SSimon Glass }
4831938f4a5SSimon Glass
4841938f4a5SSimon Glass /* (permanently) allocate a Board Info struct */
reserve_board(void)4851938f4a5SSimon Glass static int reserve_board(void)
4861938f4a5SSimon Glass {
487d54d7eb9SSonic Zhang if (!gd->bd) {
488a0ba279aSMasahiro Yamada gd->start_addr_sp -= sizeof(bd_t);
489a0ba279aSMasahiro Yamada gd->bd = (bd_t *)map_sysmem(gd->start_addr_sp, sizeof(bd_t));
4901938f4a5SSimon Glass memset(gd->bd, '\0', sizeof(bd_t));
4911938f4a5SSimon Glass debug("Reserving %zu Bytes for Board Info at: %08lx\n",
492a0ba279aSMasahiro Yamada sizeof(bd_t), gd->start_addr_sp);
493d54d7eb9SSonic Zhang }
4941938f4a5SSimon Glass return 0;
4951938f4a5SSimon Glass }
4961938f4a5SSimon Glass
setup_machine(void)4971938f4a5SSimon Glass static int setup_machine(void)
4981938f4a5SSimon Glass {
4991938f4a5SSimon Glass #ifdef CONFIG_MACH_TYPE
5001938f4a5SSimon Glass gd->bd->bi_arch_number = CONFIG_MACH_TYPE; /* board id for Linux */
5011938f4a5SSimon Glass #endif
5021938f4a5SSimon Glass return 0;
5031938f4a5SSimon Glass }
5041938f4a5SSimon Glass
reserve_global_data(void)5051938f4a5SSimon Glass static int reserve_global_data(void)
5061938f4a5SSimon Glass {
507a0ba279aSMasahiro Yamada gd->start_addr_sp -= sizeof(gd_t);
508a0ba279aSMasahiro Yamada gd->new_gd = (gd_t *)map_sysmem(gd->start_addr_sp, sizeof(gd_t));
5091938f4a5SSimon Glass debug("Reserving %zu Bytes for Global Data at: %08lx\n",
510a0ba279aSMasahiro Yamada sizeof(gd_t), gd->start_addr_sp);
5111938f4a5SSimon Glass return 0;
5121938f4a5SSimon Glass }
5131938f4a5SSimon Glass
reserve_fdt(void)5141938f4a5SSimon Glass static int reserve_fdt(void)
5151938f4a5SSimon Glass {
516e9acb9eaSSiva Durga Prasad Paladugu #ifndef CONFIG_OF_EMBED
5171938f4a5SSimon Glass /*
5184c509343SSimon Glass * If the device tree is sitting immediately above our image then we
5191938f4a5SSimon Glass * must relocate it. If it is embedded in the data section, then it
5201938f4a5SSimon Glass * will be relocated with other data.
5211938f4a5SSimon Glass */
5221938f4a5SSimon Glass if (gd->fdt_blob) {
5231938f4a5SSimon Glass gd->fdt_size = ALIGN(fdt_totalsize(gd->fdt_blob) + 0x1000, 32);
5241938f4a5SSimon Glass
525a0ba279aSMasahiro Yamada gd->start_addr_sp -= gd->fdt_size;
526a0ba279aSMasahiro Yamada gd->new_fdt = map_sysmem(gd->start_addr_sp, gd->fdt_size);
527a733b06bSSimon Glass debug("Reserving %lu Bytes for FDT at: %08lx\n",
528a0ba279aSMasahiro Yamada gd->fdt_size, gd->start_addr_sp);
5291938f4a5SSimon Glass }
530e9acb9eaSSiva Durga Prasad Paladugu #endif
5311938f4a5SSimon Glass
5321938f4a5SSimon Glass return 0;
5331938f4a5SSimon Glass }
5341938f4a5SSimon Glass
reserve_bootstage(void)53525e7dc6aSSimon Glass static int reserve_bootstage(void)
53625e7dc6aSSimon Glass {
53725e7dc6aSSimon Glass #ifdef CONFIG_BOOTSTAGE
53825e7dc6aSSimon Glass int size = bootstage_get_size();
53925e7dc6aSSimon Glass
54025e7dc6aSSimon Glass gd->start_addr_sp -= size;
54125e7dc6aSSimon Glass gd->new_bootstage = map_sysmem(gd->start_addr_sp, size);
54225e7dc6aSSimon Glass debug("Reserving %#x Bytes for bootstage at: %08lx\n", size,
54325e7dc6aSSimon Glass gd->start_addr_sp);
54425e7dc6aSSimon Glass #endif
54525e7dc6aSSimon Glass
54625e7dc6aSSimon Glass return 0;
54725e7dc6aSSimon Glass }
54825e7dc6aSSimon Glass
arch_reserve_stacks(void)549d6f87712SPatrick Delaunay __weak int arch_reserve_stacks(void)
55068145d4cSAndreas Bießmann {
55168145d4cSAndreas Bießmann return 0;
55268145d4cSAndreas Bießmann }
55368145d4cSAndreas Bießmann
reserve_stacks(void)5541938f4a5SSimon Glass static int reserve_stacks(void)
5551938f4a5SSimon Glass {
55668145d4cSAndreas Bießmann /* make stack pointer 16-byte aligned */
557a0ba279aSMasahiro Yamada gd->start_addr_sp -= 16;
558a0ba279aSMasahiro Yamada gd->start_addr_sp &= ~0xf;
5591938f4a5SSimon Glass
5601938f4a5SSimon Glass /*
5614c509343SSimon Glass * let the architecture-specific code tailor gd->start_addr_sp and
56268145d4cSAndreas Bießmann * gd->irq_sp
5631938f4a5SSimon Glass */
56468145d4cSAndreas Bießmann return arch_reserve_stacks();
5651938f4a5SSimon Glass }
5661938f4a5SSimon Glass
reserve_bloblist(void)567f0293d33SSimon Glass static int reserve_bloblist(void)
568f0293d33SSimon Glass {
569f0293d33SSimon Glass #ifdef CONFIG_BLOBLIST
570f0293d33SSimon Glass gd->start_addr_sp -= CONFIG_BLOBLIST_SIZE;
571f0293d33SSimon Glass gd->new_bloblist = map_sysmem(gd->start_addr_sp, CONFIG_BLOBLIST_SIZE);
572f0293d33SSimon Glass #endif
573f0293d33SSimon Glass
574f0293d33SSimon Glass return 0;
575f0293d33SSimon Glass }
576f0293d33SSimon Glass
display_new_sp(void)5771938f4a5SSimon Glass static int display_new_sp(void)
5781938f4a5SSimon Glass {
579a0ba279aSMasahiro Yamada debug("New Stack Pointer is: %08lx\n", gd->start_addr_sp);
5801938f4a5SSimon Glass
5811938f4a5SSimon Glass return 0;
5821938f4a5SSimon Glass }
5831938f4a5SSimon Glass
584e2099d78SVladimir Zapolskiy #if defined(CONFIG_M68K) || defined(CONFIG_MIPS) || defined(CONFIG_PPC) || \
585e2099d78SVladimir Zapolskiy defined(CONFIG_SH)
setup_board_part1(void)586e4fef6cfSSimon Glass static int setup_board_part1(void)
587e4fef6cfSSimon Glass {
588e4fef6cfSSimon Glass bd_t *bd = gd->bd;
589e4fef6cfSSimon Glass
590e4fef6cfSSimon Glass /*
591e4fef6cfSSimon Glass * Save local variables to board info struct
592e4fef6cfSSimon Glass */
593e4fef6cfSSimon Glass bd->bi_memstart = CONFIG_SYS_SDRAM_BASE; /* start of memory */
594e4fef6cfSSimon Glass bd->bi_memsize = gd->ram_size; /* size in bytes */
595e4fef6cfSSimon Glass
596e4fef6cfSSimon Glass #ifdef CONFIG_SYS_SRAM_BASE
597e4fef6cfSSimon Glass bd->bi_sramstart = CONFIG_SYS_SRAM_BASE; /* start of SRAM */
598e4fef6cfSSimon Glass bd->bi_sramsize = CONFIG_SYS_SRAM_SIZE; /* size of SRAM */
599e4fef6cfSSimon Glass #endif
600e4fef6cfSSimon Glass
60150258977SHeiko Schocher #if defined(CONFIG_E500) || defined(CONFIG_MPC86xx)
602e4fef6cfSSimon Glass bd->bi_immr_base = CONFIG_SYS_IMMR; /* base of IMMR register */
603e4fef6cfSSimon Glass #endif
604064b55cfSHeiko Schocher #if defined(CONFIG_M68K)
605e4fef6cfSSimon Glass bd->bi_mbar_base = CONFIG_SYS_MBAR; /* base of internal registers */
606e4fef6cfSSimon Glass #endif
607e4fef6cfSSimon Glass #if defined(CONFIG_MPC83xx)
608e4fef6cfSSimon Glass bd->bi_immrbar = CONFIG_SYS_IMMR;
609e4fef6cfSSimon Glass #endif
610e4fef6cfSSimon Glass
611e4fef6cfSSimon Glass return 0;
612e4fef6cfSSimon Glass }
613fb3db635SDaniel Schwierzeck #endif
614e4fef6cfSSimon Glass
615fb3db635SDaniel Schwierzeck #if defined(CONFIG_PPC) || defined(CONFIG_M68K)
setup_board_part2(void)616e4fef6cfSSimon Glass static int setup_board_part2(void)
617e4fef6cfSSimon Glass {
618e4fef6cfSSimon Glass bd_t *bd = gd->bd;
619e4fef6cfSSimon Glass
620e4fef6cfSSimon Glass bd->bi_intfreq = gd->cpu_clk; /* Internal Freq, in Hz */
621e4fef6cfSSimon Glass bd->bi_busfreq = gd->bus_clk; /* Bus Freq, in Hz */
622e4fef6cfSSimon Glass #if defined(CONFIG_CPM2)
623e4fef6cfSSimon Glass bd->bi_cpmfreq = gd->arch.cpm_clk;
624e4fef6cfSSimon Glass bd->bi_brgfreq = gd->arch.brg_clk;
625e4fef6cfSSimon Glass bd->bi_sccfreq = gd->arch.scc_clk;
626e4fef6cfSSimon Glass bd->bi_vco = gd->arch.vco_out;
627e4fef6cfSSimon Glass #endif /* CONFIG_CPM2 */
6281313db48SAlison Wang #if defined(CONFIG_M68K) && defined(CONFIG_PCI)
6291313db48SAlison Wang bd->bi_pcifreq = gd->pci_clk;
6301313db48SAlison Wang #endif
6311313db48SAlison Wang #if defined(CONFIG_EXTRA_CLOCK)
6321313db48SAlison Wang bd->bi_inpfreq = gd->arch.inp_clk; /* input Freq in Hz */
6331313db48SAlison Wang bd->bi_vcofreq = gd->arch.vco_clk; /* vco Freq in Hz */
6341313db48SAlison Wang bd->bi_flbfreq = gd->arch.flb_clk; /* flexbus Freq in Hz */
6351313db48SAlison Wang #endif
636e4fef6cfSSimon Glass
637e4fef6cfSSimon Glass return 0;
638e4fef6cfSSimon Glass }
639e4fef6cfSSimon Glass #endif
640e4fef6cfSSimon Glass
6411938f4a5SSimon Glass #ifdef CONFIG_POST
init_post(void)6421938f4a5SSimon Glass static int init_post(void)
6431938f4a5SSimon Glass {
6441938f4a5SSimon Glass post_bootmode_init();
6451938f4a5SSimon Glass post_run(NULL, POST_ROM | post_bootmode_get(0));
6461938f4a5SSimon Glass
6471938f4a5SSimon Glass return 0;
6481938f4a5SSimon Glass }
6491938f4a5SSimon Glass #endif
6501938f4a5SSimon Glass
reloc_fdt(void)6511938f4a5SSimon Glass static int reloc_fdt(void)
6521938f4a5SSimon Glass {
653e9acb9eaSSiva Durga Prasad Paladugu #ifndef CONFIG_OF_EMBED
654f05ad9baSSimon Glass if (gd->flags & GD_FLG_SKIP_RELOC)
655f05ad9baSSimon Glass return 0;
6561938f4a5SSimon Glass if (gd->new_fdt) {
6571938f4a5SSimon Glass memcpy(gd->new_fdt, gd->fdt_blob, gd->fdt_size);
6581938f4a5SSimon Glass gd->fdt_blob = gd->new_fdt;
6591938f4a5SSimon Glass }
660e9acb9eaSSiva Durga Prasad Paladugu #endif
6611938f4a5SSimon Glass
6621938f4a5SSimon Glass return 0;
6631938f4a5SSimon Glass }
6641938f4a5SSimon Glass
reloc_bootstage(void)66525e7dc6aSSimon Glass static int reloc_bootstage(void)
66625e7dc6aSSimon Glass {
66725e7dc6aSSimon Glass #ifdef CONFIG_BOOTSTAGE
66825e7dc6aSSimon Glass if (gd->flags & GD_FLG_SKIP_RELOC)
66925e7dc6aSSimon Glass return 0;
67025e7dc6aSSimon Glass if (gd->new_bootstage) {
67125e7dc6aSSimon Glass int size = bootstage_get_size();
67225e7dc6aSSimon Glass
67325e7dc6aSSimon Glass debug("Copying bootstage from %p to %p, size %x\n",
67425e7dc6aSSimon Glass gd->bootstage, gd->new_bootstage, size);
67525e7dc6aSSimon Glass memcpy(gd->new_bootstage, gd->bootstage, size);
67625e7dc6aSSimon Glass gd->bootstage = gd->new_bootstage;
67725e7dc6aSSimon Glass }
67825e7dc6aSSimon Glass #endif
67925e7dc6aSSimon Glass
68025e7dc6aSSimon Glass return 0;
68125e7dc6aSSimon Glass }
68225e7dc6aSSimon Glass
reloc_bloblist(void)683f0293d33SSimon Glass static int reloc_bloblist(void)
684f0293d33SSimon Glass {
685f0293d33SSimon Glass #ifdef CONFIG_BLOBLIST
686f0293d33SSimon Glass if (gd->flags & GD_FLG_SKIP_RELOC)
687f0293d33SSimon Glass return 0;
688f0293d33SSimon Glass if (gd->new_bloblist) {
689f0293d33SSimon Glass int size = CONFIG_BLOBLIST_SIZE;
690f0293d33SSimon Glass
691f0293d33SSimon Glass debug("Copying bloblist from %p to %p, size %x\n",
692f0293d33SSimon Glass gd->bloblist, gd->new_bloblist, size);
693f0293d33SSimon Glass memcpy(gd->new_bloblist, gd->bloblist, size);
694f0293d33SSimon Glass gd->bloblist = gd->new_bloblist;
695f0293d33SSimon Glass }
696f0293d33SSimon Glass #endif
697f0293d33SSimon Glass
698f0293d33SSimon Glass return 0;
699f0293d33SSimon Glass }
700f0293d33SSimon Glass
setup_reloc(void)7011938f4a5SSimon Glass static int setup_reloc(void)
7021938f4a5SSimon Glass {
703f05ad9baSSimon Glass if (gd->flags & GD_FLG_SKIP_RELOC) {
704f05ad9baSSimon Glass debug("Skipping relocation due to flag\n");
705f05ad9baSSimon Glass return 0;
706f05ad9baSSimon Glass }
707f05ad9baSSimon Glass
708d54d7eb9SSonic Zhang #ifdef CONFIG_SYS_TEXT_BASE
70953207bfdSLothar Waßmann #ifdef ARM
71053207bfdSLothar Waßmann gd->reloc_off = gd->relocaddr - (unsigned long)__image_copy_start;
71153207bfdSLothar Waßmann #elif defined(CONFIG_M68K)
712e310b93eSangelo@sysam.it /*
713e310b93eSangelo@sysam.it * On all ColdFire arch cpu, monitor code starts always
714e310b93eSangelo@sysam.it * just after the default vector table location, so at 0x400
715e310b93eSangelo@sysam.it */
716e310b93eSangelo@sysam.it gd->reloc_off = gd->relocaddr - (CONFIG_SYS_TEXT_BASE + 0x400);
71753207bfdSLothar Waßmann #else
71853207bfdSLothar Waßmann gd->reloc_off = gd->relocaddr - CONFIG_SYS_TEXT_BASE;
719e310b93eSangelo@sysam.it #endif
720d54d7eb9SSonic Zhang #endif
7211938f4a5SSimon Glass memcpy(gd->new_gd, (char *)gd, sizeof(gd_t));
7221938f4a5SSimon Glass
7231938f4a5SSimon Glass debug("Relocation Offset is: %08lx\n", gd->reloc_off);
724a733b06bSSimon Glass debug("Relocating to %08lx, new gd at %08lx, sp at %08lx\n",
725a0ba279aSMasahiro Yamada gd->relocaddr, (ulong)map_to_sysmem(gd->new_gd),
726a0ba279aSMasahiro Yamada gd->start_addr_sp);
7271938f4a5SSimon Glass
7281938f4a5SSimon Glass return 0;
7291938f4a5SSimon Glass }
7301938f4a5SSimon Glass
7312a792753Smario.six@gdsys.cc #ifdef CONFIG_OF_BOARD_FIXUP
fix_fdt(void)7322a792753Smario.six@gdsys.cc static int fix_fdt(void)
7332a792753Smario.six@gdsys.cc {
7342a792753Smario.six@gdsys.cc return board_fix_fdt((void *)gd->fdt_blob);
7352a792753Smario.six@gdsys.cc }
7362a792753Smario.six@gdsys.cc #endif
7372a792753Smario.six@gdsys.cc
7381938f4a5SSimon Glass /* ARM calls relocate_code from its crt0.S */
739530f27eaSSimon Glass #if !defined(CONFIG_ARM) && !defined(CONFIG_SANDBOX) && \
740530f27eaSSimon Glass !CONFIG_IS_ENABLED(X86_64)
7411938f4a5SSimon Glass
jump_to_copy(void)7421938f4a5SSimon Glass static int jump_to_copy(void)
7431938f4a5SSimon Glass {
744f05ad9baSSimon Glass if (gd->flags & GD_FLG_SKIP_RELOC)
745f05ad9baSSimon Glass return 0;
74648a33806SSimon Glass /*
74748a33806SSimon Glass * x86 is special, but in a nice way. It uses a trampoline which
74848a33806SSimon Glass * enables the dcache if possible.
74948a33806SSimon Glass *
75048a33806SSimon Glass * For now, other archs use relocate_code(), which is implemented
75148a33806SSimon Glass * similarly for all archs. When we do generic relocation, hopefully
75248a33806SSimon Glass * we can make all archs enable the dcache prior to relocation.
75348a33806SSimon Glass */
7543fb80163SAlexey Brodkin #if defined(CONFIG_X86) || defined(CONFIG_ARC)
75548a33806SSimon Glass /*
75648a33806SSimon Glass * SDRAM and console are now initialised. The final stack can now
75748a33806SSimon Glass * be setup in SDRAM. Code execution will continue in Flash, but
75848a33806SSimon Glass * with the stack in SDRAM and Global Data in temporary memory
75948a33806SSimon Glass * (CPU cache)
76048a33806SSimon Glass */
761f0c7d9c7SSimon Glass arch_setup_gd(gd->new_gd);
76248a33806SSimon Glass board_init_f_r_trampoline(gd->start_addr_sp);
76348a33806SSimon Glass #else
764a0ba279aSMasahiro Yamada relocate_code(gd->start_addr_sp, gd->new_gd, gd->relocaddr);
76548a33806SSimon Glass #endif
7661938f4a5SSimon Glass
7671938f4a5SSimon Glass return 0;
7681938f4a5SSimon Glass }
7691938f4a5SSimon Glass #endif
7701938f4a5SSimon Glass
7711938f4a5SSimon Glass /* Record the board_init_f() bootstage (after arch_cpu_init()) */
initf_bootstage(void)772b383d6c0SSimon Glass static int initf_bootstage(void)
7731938f4a5SSimon Glass {
774baa7d345SSimon Glass bool from_spl = IS_ENABLED(CONFIG_SPL_BOOTSTAGE) &&
775baa7d345SSimon Glass IS_ENABLED(CONFIG_BOOTSTAGE_STASH);
776b383d6c0SSimon Glass int ret;
777b383d6c0SSimon Glass
778824bb1b4SSimon Glass ret = bootstage_init(!from_spl);
779b383d6c0SSimon Glass if (ret)
780b383d6c0SSimon Glass return ret;
781824bb1b4SSimon Glass if (from_spl) {
782824bb1b4SSimon Glass const void *stash = map_sysmem(CONFIG_BOOTSTAGE_STASH_ADDR,
783824bb1b4SSimon Glass CONFIG_BOOTSTAGE_STASH_SIZE);
784824bb1b4SSimon Glass
785824bb1b4SSimon Glass ret = bootstage_unstash(stash, CONFIG_BOOTSTAGE_STASH_SIZE);
786824bb1b4SSimon Glass if (ret && ret != -ENOENT) {
787824bb1b4SSimon Glass debug("Failed to unstash bootstage: err=%d\n", ret);
788824bb1b4SSimon Glass return ret;
789824bb1b4SSimon Glass }
790824bb1b4SSimon Glass }
791b383d6c0SSimon Glass
7921938f4a5SSimon Glass bootstage_mark_name(BOOTSTAGE_ID_START_UBOOT_F, "board_init_f");
7931938f4a5SSimon Glass
7941938f4a5SSimon Glass return 0;
7951938f4a5SSimon Glass }
7961938f4a5SSimon Glass
initf_console_record(void)7979854a874SSimon Glass static int initf_console_record(void)
7989854a874SSimon Glass {
799f1896c45SAndy Yan #if defined(CONFIG_CONSOLE_RECORD) && CONFIG_VAL(SYS_MALLOC_F_LEN)
8009854a874SSimon Glass return console_record_init();
8019854a874SSimon Glass #else
8029854a874SSimon Glass return 0;
8039854a874SSimon Glass #endif
8049854a874SSimon Glass }
8059854a874SSimon Glass
initf_dm(void)806ab7cd627SSimon Glass static int initf_dm(void)
807ab7cd627SSimon Glass {
808f1896c45SAndy Yan #if defined(CONFIG_DM) && CONFIG_VAL(SYS_MALLOC_F_LEN)
809ab7cd627SSimon Glass int ret;
810ab7cd627SSimon Glass
81163c5bf48SSimon Glass bootstage_start(BOOTSTATE_ID_ACCUM_DM_F, "dm_f");
812ab7cd627SSimon Glass ret = dm_init_and_scan(true);
81363c5bf48SSimon Glass bootstage_accum(BOOTSTATE_ID_ACCUM_DM_F);
814ab7cd627SSimon Glass if (ret)
815ab7cd627SSimon Glass return ret;
816ab7cd627SSimon Glass #endif
8171057e6cfSSimon Glass #ifdef CONFIG_TIMER_EARLY
8181057e6cfSSimon Glass ret = dm_timer_init();
8191057e6cfSSimon Glass if (ret)
8201057e6cfSSimon Glass return ret;
8211057e6cfSSimon Glass #endif
822ab7cd627SSimon Glass
823ab7cd627SSimon Glass return 0;
824ab7cd627SSimon Glass }
825ab7cd627SSimon Glass
826146251f8SSimon Glass /* Architecture-specific memory reservation */
reserve_arch(void)827146251f8SSimon Glass __weak int reserve_arch(void)
828146251f8SSimon Glass {
829146251f8SSimon Glass return 0;
830146251f8SSimon Glass }
831146251f8SSimon Glass
arch_cpu_init_dm(void)832d4c671ccSSimon Glass __weak int arch_cpu_init_dm(void)
833d4c671ccSSimon Glass {
834d4c671ccSSimon Glass return 0;
835d4c671ccSSimon Glass }
836d4c671ccSSimon Glass
8374acff452SSimon Glass static const init_fnc_t init_sequence_f[] = {
8381938f4a5SSimon Glass setup_mon_len,
839b45122fdSSimon Glass #ifdef CONFIG_OF_CONTROL
8400879361fSSimon Glass fdtdec_setup,
841b45122fdSSimon Glass #endif
842d210718dSKevin Hilman #ifdef CONFIG_TRACE
84371c52dbaSSimon Glass trace_early_init,
844d210718dSKevin Hilman #endif
845768e0f52SSimon Glass initf_malloc,
846af1bc0cfSSimon Glass log_init,
8475ac44a55SSimon Glass initf_bootstage, /* uses its own timer, so does not need DM */
848f0293d33SSimon Glass #ifdef CONFIG_BLOBLIST
849f0293d33SSimon Glass bloblist_init,
850f0293d33SSimon Glass #endif
851*b0edea3cSSimon Glass setup_spl_handoff,
8529854a874SSimon Glass initf_console_record,
853671549e5SSimon Glass #if defined(CONFIG_HAVE_FSP)
854671549e5SSimon Glass arch_fsp_init,
855a52a068eSBin Meng #endif
8561938f4a5SSimon Glass arch_cpu_init, /* basic arch cpu dependent setup */
8578ebf5069SPaul Burton mach_cpu_init, /* SoC/machine dependent CPU setup */
8583ea0953dSSimon Glass initf_dm,
859d4c671ccSSimon Glass arch_cpu_init_dm,
8601938f4a5SSimon Glass #if defined(CONFIG_BOARD_EARLY_INIT_F)
8611938f4a5SSimon Glass board_early_init_f,
8621938f4a5SSimon Glass #endif
863727e94a4SSimon Glass #if defined(CONFIG_PPC) || defined(CONFIG_SYS_FSL_CLK) || defined(CONFIG_M68K)
864c252c068SSimon Glass /* get CPU and bus clocks according to the environment variable */
865e4fef6cfSSimon Glass get_clocks, /* get CPU and bus clocks (etc.) */
8661793e782SSimon Glass #endif
8670ce45287SAngelo Dureghello #if !defined(CONFIG_M68K)
8681938f4a5SSimon Glass timer_init, /* initialize timer */
8690ce45287SAngelo Dureghello #endif
870e4fef6cfSSimon Glass #if defined(CONFIG_BOARD_POSTCLK_INIT)
871e4fef6cfSSimon Glass board_postclk_init,
872e4fef6cfSSimon Glass #endif
8731938f4a5SSimon Glass env_init, /* initialize environment */
8741938f4a5SSimon Glass init_baud_rate, /* initialze baudrate settings */
8751938f4a5SSimon Glass serial_init, /* serial communications setup */
8761938f4a5SSimon Glass console_init_f, /* stage 1 init of console */
8771938f4a5SSimon Glass display_options, /* say that we are here */
8781938f4a5SSimon Glass display_text_info, /* show debugging info if required */
879b9153fe3SAngelo Dureghello #if defined(CONFIG_PPC) || defined(CONFIG_SH) || defined(CONFIG_X86)
880e4fef6cfSSimon Glass checkcpu,
881e4fef6cfSSimon Glass #endif
88223471aedSMario Six #if defined(CONFIG_SYSRESET)
88323471aedSMario Six print_resetinfo,
88423471aedSMario Six #endif
885cc664000SSimon Glass #if defined(CONFIG_DISPLAY_CPUINFO)
8861938f4a5SSimon Glass print_cpuinfo, /* display cpu info (and speed) */
887cc664000SSimon Glass #endif
888af9e6ad4SCooper Jr., Franklin #if defined(CONFIG_DTB_RESELECT)
889af9e6ad4SCooper Jr., Franklin embedded_dtb_select,
890af9e6ad4SCooper Jr., Franklin #endif
8911938f4a5SSimon Glass #if defined(CONFIG_DISPLAY_BOARDINFO)
8920365ffccSMasahiro Yamada show_board_info,
8931938f4a5SSimon Glass #endif
894e4fef6cfSSimon Glass INIT_FUNC_WATCHDOG_INIT
895e4fef6cfSSimon Glass #if defined(CONFIG_MISC_INIT_F)
896e4fef6cfSSimon Glass misc_init_f,
897e4fef6cfSSimon Glass #endif
898e4fef6cfSSimon Glass INIT_FUNC_WATCHDOG_RESET
89969153988SSimon Glass #if defined(CONFIG_SYS_I2C)
900e4fef6cfSSimon Glass init_func_i2c,
901e4fef6cfSSimon Glass #endif
9021fab98fbSRajesh Bhagat #if defined(CONFIG_VID) && !defined(CONFIG_SPL)
9031fab98fbSRajesh Bhagat init_func_vid,
9041fab98fbSRajesh Bhagat #endif
9051938f4a5SSimon Glass announce_dram_init,
9061938f4a5SSimon Glass dram_init, /* configure available RAM banks */
907e4fef6cfSSimon Glass #ifdef CONFIG_POST
908e4fef6cfSSimon Glass post_init_f,
909e4fef6cfSSimon Glass #endif
910e4fef6cfSSimon Glass INIT_FUNC_WATCHDOG_RESET
911e4fef6cfSSimon Glass #if defined(CONFIG_SYS_DRAM_TEST)
912e4fef6cfSSimon Glass testdram,
913e4fef6cfSSimon Glass #endif /* CONFIG_SYS_DRAM_TEST */
914e4fef6cfSSimon Glass INIT_FUNC_WATCHDOG_RESET
915e4fef6cfSSimon Glass
9161938f4a5SSimon Glass #ifdef CONFIG_POST
9171938f4a5SSimon Glass init_post,
9181938f4a5SSimon Glass #endif
919e4fef6cfSSimon Glass INIT_FUNC_WATCHDOG_RESET
9201938f4a5SSimon Glass /*
9211938f4a5SSimon Glass * Now that we have DRAM mapped and working, we can
9221938f4a5SSimon Glass * relocate the code and continue running from DRAM.
9231938f4a5SSimon Glass *
9241938f4a5SSimon Glass * Reserve memory at end of RAM for (top down in that order):
9251938f4a5SSimon Glass * - area that won't get touched by U-Boot and Linux (optional)
9261938f4a5SSimon Glass * - kernel log buffer
9271938f4a5SSimon Glass * - protected RAM
9281938f4a5SSimon Glass * - LCD framebuffer
9291938f4a5SSimon Glass * - monitor code
9301938f4a5SSimon Glass * - board info struct
9311938f4a5SSimon Glass */
9321938f4a5SSimon Glass setup_dest_addr,
9331938f4a5SSimon Glass #ifdef CONFIG_PRAM
9341938f4a5SSimon Glass reserve_pram,
9351938f4a5SSimon Glass #endif
9361938f4a5SSimon Glass reserve_round_4k,
93780d4bcd3SSimon Glass #ifdef CONFIG_ARM
9381938f4a5SSimon Glass reserve_mmu,
9391938f4a5SSimon Glass #endif
9405a541945SSimon Glass reserve_video,
9418703ef3fSSimon Glass reserve_trace,
9421938f4a5SSimon Glass reserve_uboot,
9431938f4a5SSimon Glass reserve_malloc,
9441938f4a5SSimon Glass reserve_board,
9451938f4a5SSimon Glass setup_machine,
9461938f4a5SSimon Glass reserve_global_data,
9471938f4a5SSimon Glass reserve_fdt,
94825e7dc6aSSimon Glass reserve_bootstage,
949f0293d33SSimon Glass reserve_bloblist,
950146251f8SSimon Glass reserve_arch,
9511938f4a5SSimon Glass reserve_stacks,
95276b00acaSSimon Glass dram_init_banksize,
9531938f4a5SSimon Glass show_dram_config,
954e2099d78SVladimir Zapolskiy #if defined(CONFIG_M68K) || defined(CONFIG_MIPS) || defined(CONFIG_PPC) || \
955e2099d78SVladimir Zapolskiy defined(CONFIG_SH)
956e4fef6cfSSimon Glass setup_board_part1,
957fb3db635SDaniel Schwierzeck #endif
958fb3db635SDaniel Schwierzeck #if defined(CONFIG_PPC) || defined(CONFIG_M68K)
959e4fef6cfSSimon Glass INIT_FUNC_WATCHDOG_RESET
960e4fef6cfSSimon Glass setup_board_part2,
961e4fef6cfSSimon Glass #endif
9621938f4a5SSimon Glass display_new_sp,
9632a792753Smario.six@gdsys.cc #ifdef CONFIG_OF_BOARD_FIXUP
9642a792753Smario.six@gdsys.cc fix_fdt,
9652a792753Smario.six@gdsys.cc #endif
966e4fef6cfSSimon Glass INIT_FUNC_WATCHDOG_RESET
9671938f4a5SSimon Glass reloc_fdt,
96825e7dc6aSSimon Glass reloc_bootstage,
969f0293d33SSimon Glass reloc_bloblist,
9701938f4a5SSimon Glass setup_reloc,
9713fb80163SAlexey Brodkin #if defined(CONFIG_X86) || defined(CONFIG_ARC)
972313aef37SSimon Glass copy_uboot_to_ram,
973313aef37SSimon Glass do_elf_reloc_fixups,
9746bda55a3SSimon Glass clear_bss,
975313aef37SSimon Glass #endif
976de5e5ceaSChris Zankel #if defined(CONFIG_XTENSA)
977de5e5ceaSChris Zankel clear_bss,
978de5e5ceaSChris Zankel #endif
979530f27eaSSimon Glass #if !defined(CONFIG_ARM) && !defined(CONFIG_SANDBOX) && \
980530f27eaSSimon Glass !CONFIG_IS_ENABLED(X86_64)
9811938f4a5SSimon Glass jump_to_copy,
9821938f4a5SSimon Glass #endif
9831938f4a5SSimon Glass NULL,
9841938f4a5SSimon Glass };
9851938f4a5SSimon Glass
board_init_f(ulong boot_flags)9861938f4a5SSimon Glass void board_init_f(ulong boot_flags)
9871938f4a5SSimon Glass {
9881938f4a5SSimon Glass gd->flags = boot_flags;
9899aed5a27SAlexey Brodkin gd->have_console = 0;
9901938f4a5SSimon Glass
9911938f4a5SSimon Glass if (initcall_run_list(init_sequence_f))
9921938f4a5SSimon Glass hang();
9931938f4a5SSimon Glass
9949b217498SBen Stoltz #if !defined(CONFIG_ARM) && !defined(CONFIG_SANDBOX) && \
995264d298fSAlexey Brodkin !defined(CONFIG_EFI_APP) && !CONFIG_IS_ENABLED(X86_64) && \
996264d298fSAlexey Brodkin !defined(CONFIG_ARC)
9971938f4a5SSimon Glass /* NOTREACHED - jump_to_copy() does not return */
9981938f4a5SSimon Glass hang();
9991938f4a5SSimon Glass #endif
10001938f4a5SSimon Glass }
10011938f4a5SSimon Glass
10023fb80163SAlexey Brodkin #if defined(CONFIG_X86) || defined(CONFIG_ARC)
100348a33806SSimon Glass /*
100448a33806SSimon Glass * For now this code is only used on x86.
100548a33806SSimon Glass *
100648a33806SSimon Glass * init_sequence_f_r is the list of init functions which are run when
100748a33806SSimon Glass * U-Boot is executing from Flash with a semi-limited 'C' environment.
100848a33806SSimon Glass * The following limitations must be considered when implementing an
100948a33806SSimon Glass * '_f_r' function:
101048a33806SSimon Glass * - 'static' variables are read-only
101148a33806SSimon Glass * - Global Data (gd->xxx) is read/write
101248a33806SSimon Glass *
101348a33806SSimon Glass * The '_f_r' sequence must, as a minimum, copy U-Boot to RAM (if
101448a33806SSimon Glass * supported). It _should_, if possible, copy global data to RAM and
101548a33806SSimon Glass * initialise the CPU caches (to speed up the relocation process)
101648a33806SSimon Glass *
101748a33806SSimon Glass * NOTE: At present only x86 uses this route, but it is intended that
101848a33806SSimon Glass * all archs will move to this when generic relocation is implemented.
101948a33806SSimon Glass */
10204acff452SSimon Glass static const init_fnc_t init_sequence_f_r[] = {
1021530f27eaSSimon Glass #if !CONFIG_IS_ENABLED(X86_64)
102248a33806SSimon Glass init_cache_f_r,
1023530f27eaSSimon Glass #endif
102448a33806SSimon Glass
102548a33806SSimon Glass NULL,
102648a33806SSimon Glass };
102748a33806SSimon Glass
board_init_f_r(void)102848a33806SSimon Glass void board_init_f_r(void)
102948a33806SSimon Glass {
103048a33806SSimon Glass if (initcall_run_list(init_sequence_f_r))
103148a33806SSimon Glass hang();
103248a33806SSimon Glass
103348a33806SSimon Glass /*
1034e4d6ab0cSSimon Glass * The pre-relocation drivers may be using memory that has now gone
1035e4d6ab0cSSimon Glass * away. Mark serial as unavailable - this will fall back to the debug
1036e4d6ab0cSSimon Glass * UART if available.
1037af1bc0cfSSimon Glass *
1038af1bc0cfSSimon Glass * Do the same with log drivers since the memory may not be available.
1039e4d6ab0cSSimon Glass */
1040af1bc0cfSSimon Glass gd->flags &= ~(GD_FLG_SERIAL_READY | GD_FLG_LOG_READY);
10415ee94b4fSSimon Glass #ifdef CONFIG_TIMER
10425ee94b4fSSimon Glass gd->timer = NULL;
10435ee94b4fSSimon Glass #endif
1044e4d6ab0cSSimon Glass
1045e4d6ab0cSSimon Glass /*
104648a33806SSimon Glass * U-Boot has been copied into SDRAM, the BSS has been cleared etc.
104748a33806SSimon Glass * Transfer execution from Flash to RAM by calculating the address
104848a33806SSimon Glass * of the in-RAM copy of board_init_r() and calling it
104948a33806SSimon Glass */
10507bf9f20dSAlexey Brodkin (board_init_r + gd->reloc_off)((gd_t *)gd, gd->relocaddr);
105148a33806SSimon Glass
105248a33806SSimon Glass /* NOTREACHED - board_init_r() does not return */
105348a33806SSimon Glass hang();
105448a33806SSimon Glass }
10555bcd19aaSAlexey Brodkin #endif /* CONFIG_X86 */
1056