xref: /rk3399_rockchip-uboot/arch/arm/lib/crt0.S (revision 034db99592582995a0315dd043493a1c55b5eea3)
1e05e5de7SAlbert ARIBAUD/*
2e05e5de7SAlbert ARIBAUD *  crt0 - C-runtime startup Code for ARM U-Boot
3e05e5de7SAlbert ARIBAUD *
4e05e5de7SAlbert ARIBAUD *  Copyright (c) 2012  Albert ARIBAUD <albert.u.boot@aribaud.net>
5e05e5de7SAlbert ARIBAUD *
61a459660SWolfgang Denk * SPDX-License-Identifier:	GPL-2.0+
7e05e5de7SAlbert ARIBAUD */
8e05e5de7SAlbert ARIBAUD
9e05e5de7SAlbert ARIBAUD#include <config.h>
10e05e5de7SAlbert ARIBAUD#include <asm-offsets.h>
119c5feab7SBenoît Thébaudeau#include <linux/linkage.h>
1212d8a729Srev13@wp.pl#ifdef CONFIG_CPU_V7M
1312d8a729Srev13@wp.pl#include <asm/armv7m.h>
1412d8a729Srev13@wp.pl#endif
15e05e5de7SAlbert ARIBAUD
16e05e5de7SAlbert ARIBAUD/*
17e05e5de7SAlbert ARIBAUD * This file handles the target-independent stages of the U-Boot
18e05e5de7SAlbert ARIBAUD * start-up where a C runtime environment is needed. Its entry point
19e05e5de7SAlbert ARIBAUD * is _main and is branched into from the target's start.S file.
20e05e5de7SAlbert ARIBAUD *
21e05e5de7SAlbert ARIBAUD * _main execution sequence is:
22e05e5de7SAlbert ARIBAUD *
23e05e5de7SAlbert ARIBAUD * 1. Set up initial environment for calling board_init_f().
24e05e5de7SAlbert ARIBAUD *    This environment only provides a stack and a place to store
25e05e5de7SAlbert ARIBAUD *    the GD ('global data') structure, both located in some readily
26e05e5de7SAlbert ARIBAUD *    available RAM (SRAM, locked cache...). In this context, VARIABLE
27e05e5de7SAlbert ARIBAUD *    global data, initialized or not (BSS), are UNAVAILABLE; only
28ed64190fSSimon Glass *    CONSTANT initialized data are available. GD should be zeroed
29ed64190fSSimon Glass *    before board_init_f() is called.
30e05e5de7SAlbert ARIBAUD *
31e05e5de7SAlbert ARIBAUD * 2. Call board_init_f(). This function prepares the hardware for
32e05e5de7SAlbert ARIBAUD *    execution from system RAM (DRAM, DDR...) As system RAM may not
33e05e5de7SAlbert ARIBAUD *    be available yet, , board_init_f() must use the current GD to
34e05e5de7SAlbert ARIBAUD *    store any data which must be passed on to later stages. These
35e05e5de7SAlbert ARIBAUD *    data include the relocation destination, the future stack, and
36e05e5de7SAlbert ARIBAUD *    the future GD location.
37e05e5de7SAlbert ARIBAUD *
38e05e5de7SAlbert ARIBAUD * 3. Set up intermediate environment where the stack and GD are the
39e05e5de7SAlbert ARIBAUD *    ones allocated by board_init_f() in system RAM, but BSS and
40e05e5de7SAlbert ARIBAUD *    initialized non-const data are still not available.
41e05e5de7SAlbert ARIBAUD *
42ed64190fSSimon Glass * 4a.For U-Boot proper (not SPL), call relocate_code(). This function
43ed64190fSSimon Glass *    relocates U-Boot from its current location into the relocation
44ed64190fSSimon Glass *    destination computed by board_init_f().
45ed64190fSSimon Glass *
46ed64190fSSimon Glass * 4b.For SPL, board_init_f() just returns (to crt0). There is no
47ed64190fSSimon Glass *    code relocation in SPL.
48e05e5de7SAlbert ARIBAUD *
49e05e5de7SAlbert ARIBAUD * 5. Set up final environment for calling board_init_r(). This
50e05e5de7SAlbert ARIBAUD *    environment has BSS (initialized to 0), initialized non-const
51e05e5de7SAlbert ARIBAUD *    data (initialized to their intended value), and stack in system
52ed64190fSSimon Glass *    RAM (for SPL moving the stack and GD into RAM is optional - see
53ed64190fSSimon Glass *    CONFIG_SPL_STACK_R). GD has retained values set by board_init_f().
54e05e5de7SAlbert ARIBAUD *
55ed64190fSSimon Glass * 6. For U-Boot proper (not SPL), some CPUs have some work left to do
56ed64190fSSimon Glass *    at this point regarding memory, so call c_runtime_cpu_setup.
57ed64190fSSimon Glass *
58ed64190fSSimon Glass * 7. Branch to board_init_r().
59ed64190fSSimon Glass *
60ed64190fSSimon Glass * For more information see 'Board Initialisation Flow in README.
61e05e5de7SAlbert ARIBAUD */
62e05e5de7SAlbert ARIBAUD
63e05e5de7SAlbert ARIBAUD/*
64e05e5de7SAlbert ARIBAUD * entry point of crt0 sequence
65e05e5de7SAlbert ARIBAUD */
66e05e5de7SAlbert ARIBAUD
679c5feab7SBenoît ThébaudeauENTRY(_main)
68e05e5de7SAlbert ARIBAUD
69e05e5de7SAlbert ARIBAUD/*
70e05e5de7SAlbert ARIBAUD * Set up initial C runtime environment and call board_init_f(0).
71e05e5de7SAlbert ARIBAUD */
72e05e5de7SAlbert ARIBAUD
732ca68684SKever Yang#if defined(CONFIG_TPL_BUILD) && defined(CONFIG_TPL_NEEDS_SEPARATE_STACK)
742ca68684SKever Yang	ldr	r0, =(CONFIG_TPL_STACK)
752ca68684SKever Yang#elif defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK)
76c62c1b3cSVikas Manocha	ldr	r0, =(CONFIG_SPL_STACK)
77e05e5de7SAlbert ARIBAUD#else
78c62c1b3cSVikas Manocha	ldr	r0, =(CONFIG_SYS_INIT_SP_ADDR)
79e05e5de7SAlbert ARIBAUD#endif
80c62c1b3cSVikas Manocha	bic	r0, r0, #7	/* 8-byte alignment for ABI compliance */
81c62c1b3cSVikas Manocha	mov	sp, r0
82ecc30663SAlbert ARIBAUD	bl	board_init_f_alloc_reserve
835ba534d2SSimon Glass	mov	sp, r0
84adc421e4SAlbert ARIBAUD	/* set up gd here, outside any C code */
85adc421e4SAlbert ARIBAUD	mov	r9, r0
86ecc30663SAlbert ARIBAUD	bl	board_init_f_init_reserve
87*034db995SJoseph Chen	bl	board_init_f_boot_flags
885ba534d2SSimon Glass
89e05e5de7SAlbert ARIBAUD	bl	board_init_f
90e05e5de7SAlbert ARIBAUD
91e05e5de7SAlbert ARIBAUD#if ! defined(CONFIG_SPL_BUILD)
92e05e5de7SAlbert ARIBAUD
93e05e5de7SAlbert ARIBAUD/*
94e05e5de7SAlbert ARIBAUD * Set up intermediate environment (new sp and gd) and call
955c6db120SBenoît Thébaudeau * relocate_code(addr_moni). Trick here is that we'll return
965c6db120SBenoît Thébaudeau * 'here' but relocated.
97e05e5de7SAlbert ARIBAUD */
98e05e5de7SAlbert ARIBAUD
99c62c1b3cSVikas Manocha	ldr	r0, [r9, #GD_START_ADDR_SP]	/* sp = gd->start_addr_sp */
100c62c1b3cSVikas Manocha	bic	r0, r0, #7	/* 8-byte alignment for ABI compliance */
101c62c1b3cSVikas Manocha	mov	sp, r0
102fe1378a9SJeroen Hofstee	ldr	r9, [r9, #GD_BD]		/* r9 = gd->bd */
103fe1378a9SJeroen Hofstee	sub	r9, r9, #GD_SIZE		/* new GD is below bd */
104e05e5de7SAlbert ARIBAUD
105645a442dSJoseph Chen#ifndef CONFIG_SKIP_RELOCATE_UBOOT
106e05e5de7SAlbert ARIBAUD	adr	lr, here
107fe1378a9SJeroen Hofstee	ldr	r0, [r9, #GD_RELOC_OFF]		/* r0 = gd->reloc_off */
108e05e5de7SAlbert ARIBAUD	add	lr, lr, r0
10912d8a729Srev13@wp.pl#if defined(CONFIG_CPU_V7M)
11012d8a729Srev13@wp.pl	orr	lr, #1				/* As required by Thumb-only */
11112d8a729Srev13@wp.pl#endif
112fe1378a9SJeroen Hofstee	ldr	r0, [r9, #GD_RELOCADDR]		/* r0 = gd->relocaddr */
113e05e5de7SAlbert ARIBAUD	b	relocate_code
114645a442dSJoseph Chen#endif
115e05e5de7SAlbert ARIBAUDhere:
116f6fe8359SJoseph Chen
117f6fe8359SJoseph Chen/*
118f6fe8359SJoseph Chen * The "relocate_vectors" is in section: .text.relocate_vectors, if we don't
119f6fe8359SJoseph Chen * compile "bl	relocate_vectors", there seems something wrong about sections
120f6fe8359SJoseph Chen * layout(U-Boot code section is quite large, I don't find root cause now),
121f6fe8359SJoseph Chen * so let's just skip it.
122f6fe8359SJoseph Chen */
123f6fe8359SJoseph Chen#ifdef CONFIG_SKIP_RELOCATE_UBOOT
124f6fe8359SJoseph Chen	b	c_runtime
125f6fe8359SJoseph Chen#endif
126f6fe8359SJoseph Chen
127db544b96SAlbert ARIBAUD/*
128db544b96SAlbert ARIBAUD * now relocate vectors
129db544b96SAlbert ARIBAUD */
130db544b96SAlbert ARIBAUD	bl	relocate_vectors
131e05e5de7SAlbert ARIBAUD
132f6fe8359SJoseph Chenc_runtime:
133e05e5de7SAlbert ARIBAUD/* Set up final (full) environment */
134e05e5de7SAlbert ARIBAUD
135e05e5de7SAlbert ARIBAUD	bl	c_runtime_cpu_setup	/* we still call old routine here */
136db910353SSimon Glass#endif
13730129f2fSDavid Wu#if !defined(CONFIG_SPL_BUILD) || (defined(CONFIG_SPL_FRAMEWORK) && !defined(CONFIG_TPL_BUILD))
138db910353SSimon Glass# ifdef CONFIG_SPL_BUILD
139db910353SSimon Glass	/* Use a DRAM stack for the rest of SPL, if requested */
140db910353SSimon Glass	bl	spl_relocate_stack_gd
141db910353SSimon Glass	cmp	r0, #0
142db910353SSimon Glass	movne	sp, r0
143adc421e4SAlbert ARIBAUD	movne	r9, r0
144db910353SSimon Glass# endif
145e05e5de7SAlbert ARIBAUD	ldr	r0, =__bss_start	/* this is auto-relocated! */
146e05e5de7SAlbert ARIBAUD
147114c86d8SPrzemyslaw Marczak#ifdef CONFIG_USE_ARCH_MEMSET
148114c86d8SPrzemyslaw Marczak	ldr	r3, =__bss_end		/* this is auto-relocated! */
149114c86d8SPrzemyslaw Marczak	mov	r1, #0x00000000		/* prepare zero to clear BSS */
150114c86d8SPrzemyslaw Marczak
151114c86d8SPrzemyslaw Marczak	subs	r2, r3, r0		/* r2 = memset len */
152114c86d8SPrzemyslaw Marczak	bl	memset
153114c86d8SPrzemyslaw Marczak#else
154114c86d8SPrzemyslaw Marczak	ldr	r1, =__bss_end		/* this is auto-relocated! */
155e05e5de7SAlbert ARIBAUD	mov	r2, #0x00000000		/* prepare zero to clear BSS */
156e05e5de7SAlbert ARIBAUD
157e05e5de7SAlbert ARIBAUDclbss_l:cmp	r0, r1			/* while not at end of BSS */
15812d8a729Srev13@wp.pl#if defined(CONFIG_CPU_V7M)
15912d8a729Srev13@wp.pl	itt	lo
16012d8a729Srev13@wp.pl#endif
161e05e5de7SAlbert ARIBAUD	strlo	r2, [r0]		/* clear 32-bit BSS word */
162e05e5de7SAlbert ARIBAUD	addlo	r0, r0, #4		/* move to next */
163e05e5de7SAlbert ARIBAUD	blo	clbss_l
164114c86d8SPrzemyslaw Marczak#endif
165e05e5de7SAlbert ARIBAUD
166db910353SSimon Glass#if ! defined(CONFIG_SPL_BUILD)
167e05e5de7SAlbert ARIBAUD	bl coloured_LED_init
168e05e5de7SAlbert ARIBAUD	bl red_led_on
169db910353SSimon Glass#endif
170e05e5de7SAlbert ARIBAUD	/* call board_init_r(gd_t *id, ulong dest_addr) */
171fe1378a9SJeroen Hofstee	mov     r0, r9                  /* gd_t */
172fe1378a9SJeroen Hofstee	ldr	r1, [r9, #GD_RELOCADDR]	/* dest_addr */
173e05e5de7SAlbert ARIBAUD	/* call board_init_r */
1743a649407STom Rini#if CONFIG_IS_ENABLED(SYS_THUMB_BUILD)
17503a3a8aeSDavid Müller (ELSOFT AG)	ldr	lr, =board_init_r	/* this is auto-relocated! */
17603a3a8aeSDavid Müller (ELSOFT AG)	bx	lr
17703a3a8aeSDavid Müller (ELSOFT AG)#else
178e05e5de7SAlbert ARIBAUD	ldr	pc, =board_init_r	/* this is auto-relocated! */
17903a3a8aeSDavid Müller (ELSOFT AG)#endif
180e05e5de7SAlbert ARIBAUD	/* we should not return here. */
181e05e5de7SAlbert ARIBAUD#endif
1829c5feab7SBenoît Thébaudeau
1839c5feab7SBenoît ThébaudeauENDPROC(_main)
184