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