xref: /openbmc/u-boot/common/board_f.c (revision 9450ab2ba8d720bd9f73bccc0af2e2b5a2c2aaf1)
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