183d290c5STom Rini/* SPDX-License-Identifier: GPL-2.0+ */ 2e05e5de7SAlbert ARIBAUD/* 3e05e5de7SAlbert ARIBAUD * crt0 - C-runtime startup Code for ARM U-Boot 4e05e5de7SAlbert ARIBAUD * 5e05e5de7SAlbert ARIBAUD * Copyright (c) 2012 Albert ARIBAUD <albert.u.boot@aribaud.net> 6e05e5de7SAlbert ARIBAUD */ 7e05e5de7SAlbert ARIBAUD 8e05e5de7SAlbert ARIBAUD#include <config.h> 9e05e5de7SAlbert ARIBAUD#include <asm-offsets.h> 109c5feab7SBenoît Thébaudeau#include <linux/linkage.h> 11d22336aaSVikas Manocha#include <asm/assembler.h> 12e05e5de7SAlbert ARIBAUD 13e05e5de7SAlbert ARIBAUD/* 14e05e5de7SAlbert ARIBAUD * This file handles the target-independent stages of the U-Boot 15e05e5de7SAlbert ARIBAUD * start-up where a C runtime environment is needed. Its entry point 16e05e5de7SAlbert ARIBAUD * is _main and is branched into from the target's start.S file. 17e05e5de7SAlbert ARIBAUD * 18e05e5de7SAlbert ARIBAUD * _main execution sequence is: 19e05e5de7SAlbert ARIBAUD * 20e05e5de7SAlbert ARIBAUD * 1. Set up initial environment for calling board_init_f(). 21e05e5de7SAlbert ARIBAUD * This environment only provides a stack and a place to store 22e05e5de7SAlbert ARIBAUD * the GD ('global data') structure, both located in some readily 23e05e5de7SAlbert ARIBAUD * available RAM (SRAM, locked cache...). In this context, VARIABLE 24e05e5de7SAlbert ARIBAUD * global data, initialized or not (BSS), are UNAVAILABLE; only 25ed64190fSSimon Glass * CONSTANT initialized data are available. GD should be zeroed 26ed64190fSSimon Glass * before board_init_f() is called. 27e05e5de7SAlbert ARIBAUD * 28e05e5de7SAlbert ARIBAUD * 2. Call board_init_f(). This function prepares the hardware for 29e05e5de7SAlbert ARIBAUD * execution from system RAM (DRAM, DDR...) As system RAM may not 30e05e5de7SAlbert ARIBAUD * be available yet, , board_init_f() must use the current GD to 31e05e5de7SAlbert ARIBAUD * store any data which must be passed on to later stages. These 32e05e5de7SAlbert ARIBAUD * data include the relocation destination, the future stack, and 33e05e5de7SAlbert ARIBAUD * the future GD location. 34e05e5de7SAlbert ARIBAUD * 35e05e5de7SAlbert ARIBAUD * 3. Set up intermediate environment where the stack and GD are the 36e05e5de7SAlbert ARIBAUD * ones allocated by board_init_f() in system RAM, but BSS and 37e05e5de7SAlbert ARIBAUD * initialized non-const data are still not available. 38e05e5de7SAlbert ARIBAUD * 39ed64190fSSimon Glass * 4a.For U-Boot proper (not SPL), call relocate_code(). This function 40ed64190fSSimon Glass * relocates U-Boot from its current location into the relocation 41ed64190fSSimon Glass * destination computed by board_init_f(). 42ed64190fSSimon Glass * 43ed64190fSSimon Glass * 4b.For SPL, board_init_f() just returns (to crt0). There is no 44ed64190fSSimon Glass * code relocation in SPL. 45e05e5de7SAlbert ARIBAUD * 46e05e5de7SAlbert ARIBAUD * 5. Set up final environment for calling board_init_r(). This 47e05e5de7SAlbert ARIBAUD * environment has BSS (initialized to 0), initialized non-const 48e05e5de7SAlbert ARIBAUD * data (initialized to their intended value), and stack in system 49ed64190fSSimon Glass * RAM (for SPL moving the stack and GD into RAM is optional - see 50ed64190fSSimon Glass * CONFIG_SPL_STACK_R). GD has retained values set by board_init_f(). 51e05e5de7SAlbert ARIBAUD * 52ed64190fSSimon Glass * 6. For U-Boot proper (not SPL), some CPUs have some work left to do 53ed64190fSSimon Glass * at this point regarding memory, so call c_runtime_cpu_setup. 54ed64190fSSimon Glass * 55ed64190fSSimon Glass * 7. Branch to board_init_r(). 56ed64190fSSimon Glass * 57ed64190fSSimon Glass * For more information see 'Board Initialisation Flow in README. 58e05e5de7SAlbert ARIBAUD */ 59e05e5de7SAlbert ARIBAUD 60e05e5de7SAlbert ARIBAUD/* 61e05e5de7SAlbert ARIBAUD * entry point of crt0 sequence 62e05e5de7SAlbert ARIBAUD */ 63e05e5de7SAlbert ARIBAUD 649c5feab7SBenoît ThébaudeauENTRY(_main) 65e05e5de7SAlbert ARIBAUD 66e05e5de7SAlbert ARIBAUD/* 67e05e5de7SAlbert ARIBAUD * Set up initial C runtime environment and call board_init_f(0). 68e05e5de7SAlbert ARIBAUD */ 69e05e5de7SAlbert ARIBAUD 7066f30bf9SBenoît Thébaudeau#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK) 71c62c1b3cSVikas Manocha ldr r0, =(CONFIG_SPL_STACK) 72e05e5de7SAlbert ARIBAUD#else 73c62c1b3cSVikas Manocha ldr r0, =(CONFIG_SYS_INIT_SP_ADDR) 74e05e5de7SAlbert ARIBAUD#endif 75c62c1b3cSVikas Manocha bic r0, r0, #7 /* 8-byte alignment for ABI compliance */ 76c62c1b3cSVikas Manocha mov sp, r0 77ecc30663SAlbert ARIBAUD bl board_init_f_alloc_reserve 785ba534d2SSimon Glass mov sp, r0 79adc421e4SAlbert ARIBAUD /* set up gd here, outside any C code */ 80adc421e4SAlbert ARIBAUD mov r9, r0 81ecc30663SAlbert ARIBAUD bl board_init_f_init_reserve 825ba534d2SSimon Glass 83e05e5de7SAlbert ARIBAUD mov r0, #0 84e05e5de7SAlbert ARIBAUD bl board_init_f 85e05e5de7SAlbert ARIBAUD 860d1d4e81SChia-Wei, Wang#if (defined(CONFIG_SPL_BUILD) && !defined(CONFIG_TPL_BUILD) && !defined(CONFIG_SPL_SKIP_RELOCATE)) || \ 870d1d4e81SChia-Wei, Wang !defined(CONFIG_SPL_BUILD) 88e05e5de7SAlbert ARIBAUD/* 89e05e5de7SAlbert ARIBAUD * Set up intermediate environment (new sp and gd) and call 905c6db120SBenoît Thébaudeau * relocate_code(addr_moni). Trick here is that we'll return 915c6db120SBenoît Thébaudeau * 'here' but relocated. 92e05e5de7SAlbert ARIBAUD */ 93e05e5de7SAlbert ARIBAUD 94c62c1b3cSVikas Manocha ldr r0, [r9, #GD_START_ADDR_SP] /* sp = gd->start_addr_sp */ 95c62c1b3cSVikas Manocha bic r0, r0, #7 /* 8-byte alignment for ABI compliance */ 96c62c1b3cSVikas Manocha mov sp, r0 970d1d4e81SChia-Wei, Wang ldr r9, [r9, #GD_NEW_GD] 980d1d4e81SChia-Wei, Wang#if 0 99fe1378a9SJeroen Hofstee ldr r9, [r9, #GD_BD] /* r9 = gd->bd */ 100fe1378a9SJeroen Hofstee sub r9, r9, #GD_SIZE /* new GD is below bd */ 1010d1d4e81SChia-Wei, Wang#endif 102e05e5de7SAlbert ARIBAUD 103e05e5de7SAlbert ARIBAUD adr lr, here 10486c21f0aSChia-Wei, Wang#ifdef CONFIG_POSITION_INDEPENDENT 10586c21f0aSChia-Wei, Wang adr r0, _main 10686c21f0aSChia-Wei, Wang ldr r1, _start_ofs 10786c21f0aSChia-Wei, Wang add r0, r1 1080d1d4e81SChia-Wei, Wang#ifdef CONFIG_SPL_BUILD 1090d1d4e81SChia-Wei, Wang ldr r1, =CONFIG_SPL_TEXT_BASE 1100d1d4e81SChia-Wei, Wang#else 11186c21f0aSChia-Wei, Wang ldr r1, =CONFIG_SYS_TEXT_BASE 1120d1d4e81SChia-Wei, Wang#endif 11386c21f0aSChia-Wei, Wang sub r1, r0 11486c21f0aSChia-Wei, Wang add lr, r1 115*04a213b5SChia-Wei Wang 116*04a213b5SChia-Wei Wang ldr r0, [r9, #GD_ENV_ADDR] /* r0 = gd->env_addr */ 117*04a213b5SChia-Wei Wang add r0, r0, r1 118*04a213b5SChia-Wei Wang str r0, [r9, #GD_ENV_ADDR] 11986c21f0aSChia-Wei, Wang#endif 120fe1378a9SJeroen Hofstee ldr r0, [r9, #GD_RELOC_OFF] /* r0 = gd->reloc_off */ 121e05e5de7SAlbert ARIBAUD add lr, lr, r0 12212d8a729Srev13@wp.pl#if defined(CONFIG_CPU_V7M) 12312d8a729Srev13@wp.pl orr lr, #1 /* As required by Thumb-only */ 12412d8a729Srev13@wp.pl#endif 125fe1378a9SJeroen Hofstee ldr r0, [r9, #GD_RELOCADDR] /* r0 = gd->relocaddr */ 126e05e5de7SAlbert ARIBAUD b relocate_code 127e05e5de7SAlbert ARIBAUDhere: 128db544b96SAlbert ARIBAUD/* 129db544b96SAlbert ARIBAUD * now relocate vectors 130db544b96SAlbert ARIBAUD */ 131db544b96SAlbert ARIBAUD 132db544b96SAlbert ARIBAUD bl relocate_vectors 133e05e5de7SAlbert ARIBAUD 134e05e5de7SAlbert ARIBAUD/* Set up final (full) environment */ 135e05e5de7SAlbert ARIBAUD 136e05e5de7SAlbert ARIBAUD bl c_runtime_cpu_setup /* we still call old routine here */ 137db910353SSimon Glass#endif 138db910353SSimon Glass#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_FRAMEWORK) 139db910353SSimon Glass# ifdef CONFIG_SPL_BUILD 140db910353SSimon Glass /* Use a DRAM stack for the rest of SPL, if requested */ 141db910353SSimon Glass bl spl_relocate_stack_gd 142db910353SSimon Glass cmp r0, #0 143db910353SSimon Glass movne sp, r0 144adc421e4SAlbert ARIBAUD movne r9, r0 145db910353SSimon Glass# endif 146e05e5de7SAlbert ARIBAUD ldr r0, =__bss_start /* this is auto-relocated! */ 147e05e5de7SAlbert ARIBAUD 148114c86d8SPrzemyslaw Marczak#ifdef CONFIG_USE_ARCH_MEMSET 149114c86d8SPrzemyslaw Marczak ldr r3, =__bss_end /* this is auto-relocated! */ 150114c86d8SPrzemyslaw Marczak mov r1, #0x00000000 /* prepare zero to clear BSS */ 151114c86d8SPrzemyslaw Marczak 152114c86d8SPrzemyslaw Marczak subs r2, r3, r0 /* r2 = memset len */ 153114c86d8SPrzemyslaw Marczak bl memset 154114c86d8SPrzemyslaw Marczak#else 155114c86d8SPrzemyslaw Marczak ldr r1, =__bss_end /* this is auto-relocated! */ 156e05e5de7SAlbert ARIBAUD mov r2, #0x00000000 /* prepare zero to clear BSS */ 157e05e5de7SAlbert ARIBAUD 158e05e5de7SAlbert ARIBAUDclbss_l:cmp r0, r1 /* while not at end of BSS */ 159e05e5de7SAlbert ARIBAUD strlo r2, [r0] /* clear 32-bit BSS word */ 160e05e5de7SAlbert ARIBAUD addlo r0, r0, #4 /* move to next */ 161e05e5de7SAlbert ARIBAUD blo clbss_l 162114c86d8SPrzemyslaw Marczak#endif 163e05e5de7SAlbert ARIBAUD 164db910353SSimon Glass#if ! defined(CONFIG_SPL_BUILD) 165e05e5de7SAlbert ARIBAUD bl coloured_LED_init 166e05e5de7SAlbert ARIBAUD bl red_led_on 167db910353SSimon Glass#endif 168e05e5de7SAlbert ARIBAUD /* call board_init_r(gd_t *id, ulong dest_addr) */ 169fe1378a9SJeroen Hofstee mov r0, r9 /* gd_t */ 170fe1378a9SJeroen Hofstee ldr r1, [r9, #GD_RELOCADDR] /* dest_addr */ 171e05e5de7SAlbert ARIBAUD /* call board_init_r */ 1723a649407STom Rini#if CONFIG_IS_ENABLED(SYS_THUMB_BUILD) 17303a3a8aeSDavid Müller (ELSOFT AG) ldr lr, =board_init_r /* this is auto-relocated! */ 17403a3a8aeSDavid Müller (ELSOFT AG) bx lr 17503a3a8aeSDavid Müller (ELSOFT AG)#else 176e05e5de7SAlbert ARIBAUD ldr pc, =board_init_r /* this is auto-relocated! */ 17703a3a8aeSDavid Müller (ELSOFT AG)#endif 178e05e5de7SAlbert ARIBAUD /* we should not return here. */ 179e05e5de7SAlbert ARIBAUD#endif 1809c5feab7SBenoît Thébaudeau 1819c5feab7SBenoît ThébaudeauENDPROC(_main) 18286c21f0aSChia-Wei, Wang 18386c21f0aSChia-Wei, Wang_start_ofs: 18486c21f0aSChia-Wei, Wang .word _start - _main 185