xref: /rk3399_rockchip-uboot/arch/arm/lib/crt0.S (revision 03a3a8aec85780f034c9c8fca4a12abfeb9b4da7)
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
7366f30bf9SBenoît Thébaudeau#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK)
74e05e5de7SAlbert ARIBAUD	ldr	sp, =(CONFIG_SPL_STACK)
75e05e5de7SAlbert ARIBAUD#else
76e05e5de7SAlbert ARIBAUD	ldr	sp, =(CONFIG_SYS_INIT_SP_ADDR)
77e05e5de7SAlbert ARIBAUD#endif
7812d8a729Srev13@wp.pl#if defined(CONFIG_CPU_V7M)	/* v7M forbids using SP as BIC destination */
7912d8a729Srev13@wp.pl	mov	r3, sp
8012d8a729Srev13@wp.pl	bic	r3, r3, #7
8112d8a729Srev13@wp.pl	mov	sp, r3
8212d8a729Srev13@wp.pl#else
83e05e5de7SAlbert ARIBAUD	bic	sp, sp, #7	/* 8-byte alignment for ABI compliance */
8412d8a729Srev13@wp.pl#endif
855ba534d2SSimon Glass	mov	r0, sp
86ecc30663SAlbert ARIBAUD	bl	board_init_f_alloc_reserve
875ba534d2SSimon Glass	mov	sp, r0
88adc421e4SAlbert ARIBAUD	/* set up gd here, outside any C code */
89adc421e4SAlbert ARIBAUD	mov	r9, r0
90ecc30663SAlbert ARIBAUD	bl	board_init_f_init_reserve
915ba534d2SSimon Glass
92e05e5de7SAlbert ARIBAUD	mov	r0, #0
93e05e5de7SAlbert ARIBAUD	bl	board_init_f
94e05e5de7SAlbert ARIBAUD
95e05e5de7SAlbert ARIBAUD#if ! defined(CONFIG_SPL_BUILD)
96e05e5de7SAlbert ARIBAUD
97e05e5de7SAlbert ARIBAUD/*
98e05e5de7SAlbert ARIBAUD * Set up intermediate environment (new sp and gd) and call
995c6db120SBenoît Thébaudeau * relocate_code(addr_moni). Trick here is that we'll return
1005c6db120SBenoît Thébaudeau * 'here' but relocated.
101e05e5de7SAlbert ARIBAUD */
102e05e5de7SAlbert ARIBAUD
103fe1378a9SJeroen Hofstee	ldr	sp, [r9, #GD_START_ADDR_SP]	/* sp = gd->start_addr_sp */
10412d8a729Srev13@wp.pl#if defined(CONFIG_CPU_V7M)	/* v7M forbids using SP as BIC destination */
10512d8a729Srev13@wp.pl	mov	r3, sp
10612d8a729Srev13@wp.pl	bic	r3, r3, #7
10712d8a729Srev13@wp.pl	mov	sp, r3
10812d8a729Srev13@wp.pl#else
109e05e5de7SAlbert ARIBAUD	bic	sp, sp, #7	/* 8-byte alignment for ABI compliance */
11012d8a729Srev13@wp.pl#endif
111fe1378a9SJeroen Hofstee	ldr	r9, [r9, #GD_BD]		/* r9 = gd->bd */
112fe1378a9SJeroen Hofstee	sub	r9, r9, #GD_SIZE		/* new GD is below bd */
113e05e5de7SAlbert ARIBAUD
114e05e5de7SAlbert ARIBAUD	adr	lr, here
115fe1378a9SJeroen Hofstee	ldr	r0, [r9, #GD_RELOC_OFF]		/* r0 = gd->reloc_off */
116e05e5de7SAlbert ARIBAUD	add	lr, lr, r0
11712d8a729Srev13@wp.pl#if defined(CONFIG_CPU_V7M)
11812d8a729Srev13@wp.pl	orr	lr, #1				/* As required by Thumb-only */
11912d8a729Srev13@wp.pl#endif
120fe1378a9SJeroen Hofstee	ldr	r0, [r9, #GD_RELOCADDR]		/* r0 = gd->relocaddr */
121e05e5de7SAlbert ARIBAUD	b	relocate_code
122e05e5de7SAlbert ARIBAUDhere:
123db544b96SAlbert ARIBAUD/*
124db544b96SAlbert ARIBAUD * now relocate vectors
125db544b96SAlbert ARIBAUD */
126db544b96SAlbert ARIBAUD
127db544b96SAlbert ARIBAUD	bl	relocate_vectors
128e05e5de7SAlbert ARIBAUD
129e05e5de7SAlbert ARIBAUD/* Set up final (full) environment */
130e05e5de7SAlbert ARIBAUD
131e05e5de7SAlbert ARIBAUD	bl	c_runtime_cpu_setup	/* we still call old routine here */
132db910353SSimon Glass#endif
133db910353SSimon Glass#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_FRAMEWORK)
134db910353SSimon Glass# ifdef CONFIG_SPL_BUILD
135db910353SSimon Glass	/* Use a DRAM stack for the rest of SPL, if requested */
136db910353SSimon Glass	bl	spl_relocate_stack_gd
137db910353SSimon Glass	cmp	r0, #0
138db910353SSimon Glass	movne	sp, r0
139adc421e4SAlbert ARIBAUD	movne	r9, r0
140db910353SSimon Glass# endif
141e05e5de7SAlbert ARIBAUD	ldr	r0, =__bss_start	/* this is auto-relocated! */
142e05e5de7SAlbert ARIBAUD
143114c86d8SPrzemyslaw Marczak#ifdef CONFIG_USE_ARCH_MEMSET
144114c86d8SPrzemyslaw Marczak	ldr	r3, =__bss_end		/* this is auto-relocated! */
145114c86d8SPrzemyslaw Marczak	mov	r1, #0x00000000		/* prepare zero to clear BSS */
146114c86d8SPrzemyslaw Marczak
147114c86d8SPrzemyslaw Marczak	subs	r2, r3, r0		/* r2 = memset len */
148114c86d8SPrzemyslaw Marczak	bl	memset
149114c86d8SPrzemyslaw Marczak#else
150114c86d8SPrzemyslaw Marczak	ldr	r1, =__bss_end		/* this is auto-relocated! */
151e05e5de7SAlbert ARIBAUD	mov	r2, #0x00000000		/* prepare zero to clear BSS */
152e05e5de7SAlbert ARIBAUD
153e05e5de7SAlbert ARIBAUDclbss_l:cmp	r0, r1			/* while not at end of BSS */
15412d8a729Srev13@wp.pl#if defined(CONFIG_CPU_V7M)
15512d8a729Srev13@wp.pl	itt	lo
15612d8a729Srev13@wp.pl#endif
157e05e5de7SAlbert ARIBAUD	strlo	r2, [r0]		/* clear 32-bit BSS word */
158e05e5de7SAlbert ARIBAUD	addlo	r0, r0, #4		/* move to next */
159e05e5de7SAlbert ARIBAUD	blo	clbss_l
160114c86d8SPrzemyslaw Marczak#endif
161e05e5de7SAlbert ARIBAUD
162db910353SSimon Glass#if ! defined(CONFIG_SPL_BUILD)
163e05e5de7SAlbert ARIBAUD	bl coloured_LED_init
164e05e5de7SAlbert ARIBAUD	bl red_led_on
165db910353SSimon Glass#endif
166e05e5de7SAlbert ARIBAUD	/* call board_init_r(gd_t *id, ulong dest_addr) */
167fe1378a9SJeroen Hofstee	mov     r0, r9                  /* gd_t */
168fe1378a9SJeroen Hofstee	ldr	r1, [r9, #GD_RELOCADDR]	/* dest_addr */
169e05e5de7SAlbert ARIBAUD	/* call board_init_r */
170*03a3a8aeSDavid Müller (ELSOFT AG)#if defined(CONFIG_SYS_THUMB_BUILD)
171*03a3a8aeSDavid Müller (ELSOFT AG)	ldr	lr, =board_init_r	/* this is auto-relocated! */
172*03a3a8aeSDavid Müller (ELSOFT AG)	bx	lr
173*03a3a8aeSDavid Müller (ELSOFT AG)#else
174e05e5de7SAlbert ARIBAUD	ldr	pc, =board_init_r	/* this is auto-relocated! */
175*03a3a8aeSDavid Müller (ELSOFT AG)#endif
176e05e5de7SAlbert ARIBAUD	/* we should not return here. */
177e05e5de7SAlbert ARIBAUD#endif
1789c5feab7SBenoît Thébaudeau
1799c5feab7SBenoît ThébaudeauENDPROC(_main)
180