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