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> 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 25e05e5de7SAlbert ARIBAUD * CONSTANT initialized data are available. 26e05e5de7SAlbert ARIBAUD * 27e05e5de7SAlbert ARIBAUD * 2. Call board_init_f(). This function prepares the hardware for 28e05e5de7SAlbert ARIBAUD * execution from system RAM (DRAM, DDR...) As system RAM may not 29e05e5de7SAlbert ARIBAUD * be available yet, , board_init_f() must use the current GD to 30e05e5de7SAlbert ARIBAUD * store any data which must be passed on to later stages. These 31e05e5de7SAlbert ARIBAUD * data include the relocation destination, the future stack, and 32e05e5de7SAlbert ARIBAUD * the future GD location. 33e05e5de7SAlbert ARIBAUD * 34e05e5de7SAlbert ARIBAUD * (the following applies only to non-SPL builds) 35e05e5de7SAlbert ARIBAUD * 36e05e5de7SAlbert ARIBAUD * 3. Set up intermediate environment where the stack and GD are the 37e05e5de7SAlbert ARIBAUD * ones allocated by board_init_f() in system RAM, but BSS and 38e05e5de7SAlbert ARIBAUD * initialized non-const data are still not available. 39e05e5de7SAlbert ARIBAUD * 40e05e5de7SAlbert ARIBAUD * 4. Call relocate_code(). This function relocates U-Boot from its 41e05e5de7SAlbert ARIBAUD * current location into the relocation destination computed by 42e05e5de7SAlbert ARIBAUD * board_init_f(). 43e05e5de7SAlbert ARIBAUD * 44e05e5de7SAlbert ARIBAUD * 5. Set up final environment for calling board_init_r(). This 45e05e5de7SAlbert ARIBAUD * environment has BSS (initialized to 0), initialized non-const 46e05e5de7SAlbert ARIBAUD * data (initialized to their intended value), and stack in system 47e05e5de7SAlbert ARIBAUD * RAM. GD has retained values set by board_init_f(). Some CPUs 48e05e5de7SAlbert ARIBAUD * have some work left to do at this point regarding memory, so 49e05e5de7SAlbert ARIBAUD * call c_runtime_cpu_setup. 50e05e5de7SAlbert ARIBAUD * 5166f30bf9SBenoît Thébaudeau * 6. Branch to board_init_r(). 52e05e5de7SAlbert ARIBAUD */ 53e05e5de7SAlbert ARIBAUD 54e05e5de7SAlbert ARIBAUD/* 55e05e5de7SAlbert ARIBAUD * entry point of crt0 sequence 56e05e5de7SAlbert ARIBAUD */ 57e05e5de7SAlbert ARIBAUD 589c5feab7SBenoît ThébaudeauENTRY(_main) 59e05e5de7SAlbert ARIBAUD 60e05e5de7SAlbert ARIBAUD/* 61e05e5de7SAlbert ARIBAUD * Set up initial C runtime environment and call board_init_f(0). 62e05e5de7SAlbert ARIBAUD */ 63e05e5de7SAlbert ARIBAUD 6466f30bf9SBenoît Thébaudeau#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK) 65e05e5de7SAlbert ARIBAUD ldr sp, =(CONFIG_SPL_STACK) 66e05e5de7SAlbert ARIBAUD#else 67e05e5de7SAlbert ARIBAUD ldr sp, =(CONFIG_SYS_INIT_SP_ADDR) 68e05e5de7SAlbert ARIBAUD#endif 69e05e5de7SAlbert ARIBAUD bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ 70aae2aef9SSimon Glass mov r2, sp 716ba2bc8fSAndreas Bießmann sub sp, sp, #GD_SIZE /* allocate one GD above SP */ 72e05e5de7SAlbert ARIBAUD bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ 73fe1378a9SJeroen Hofstee mov r9, sp /* GD is above SP */ 74aae2aef9SSimon Glass mov r1, sp 75e05e5de7SAlbert ARIBAUD mov r0, #0 76aae2aef9SSimon Glassclr_gd: 77aae2aef9SSimon Glass cmp r1, r2 /* while not at end of GD */ 78aae2aef9SSimon Glass strlo r0, [r1] /* clear 32-bit GD word */ 79aae2aef9SSimon Glass addlo r1, r1, #4 /* move to next */ 80aae2aef9SSimon Glass blo clr_gd 81ba19599bSSimon Glass#if defined(CONFIG_SYS_MALLOC_F_LEN) 8276a1e584SSimon Glass sub sp, sp, #CONFIG_SYS_MALLOC_F_LEN 8376a1e584SSimon Glass str sp, [r9, #GD_MALLOC_BASE] 8476a1e584SSimon Glass#endif 85aae2aef9SSimon Glass /* mov r0, #0 not needed due to above code */ 86e05e5de7SAlbert ARIBAUD bl board_init_f 87e05e5de7SAlbert ARIBAUD 88e05e5de7SAlbert ARIBAUD#if ! defined(CONFIG_SPL_BUILD) 89e05e5de7SAlbert ARIBAUD 90e05e5de7SAlbert ARIBAUD/* 91e05e5de7SAlbert ARIBAUD * Set up intermediate environment (new sp and gd) and call 925c6db120SBenoît Thébaudeau * relocate_code(addr_moni). Trick here is that we'll return 935c6db120SBenoît Thébaudeau * 'here' but relocated. 94e05e5de7SAlbert ARIBAUD */ 95e05e5de7SAlbert ARIBAUD 96fe1378a9SJeroen Hofstee ldr sp, [r9, #GD_START_ADDR_SP] /* sp = gd->start_addr_sp */ 97e05e5de7SAlbert ARIBAUD bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ 98fe1378a9SJeroen Hofstee ldr r9, [r9, #GD_BD] /* r9 = gd->bd */ 99fe1378a9SJeroen Hofstee sub r9, r9, #GD_SIZE /* new GD is below bd */ 100e05e5de7SAlbert ARIBAUD 101e05e5de7SAlbert ARIBAUD adr lr, here 102fe1378a9SJeroen Hofstee ldr r0, [r9, #GD_RELOC_OFF] /* r0 = gd->reloc_off */ 103e05e5de7SAlbert ARIBAUD add lr, lr, r0 104fe1378a9SJeroen Hofstee ldr r0, [r9, #GD_RELOCADDR] /* r0 = gd->relocaddr */ 105e05e5de7SAlbert ARIBAUD b relocate_code 106e05e5de7SAlbert ARIBAUDhere: 107db544b96SAlbert ARIBAUD/* 108db544b96SAlbert ARIBAUD * now relocate vectors 109db544b96SAlbert ARIBAUD */ 110db544b96SAlbert ARIBAUD 111db544b96SAlbert ARIBAUD bl relocate_vectors 112e05e5de7SAlbert ARIBAUD 113e05e5de7SAlbert ARIBAUD/* Set up final (full) environment */ 114e05e5de7SAlbert ARIBAUD 115e05e5de7SAlbert ARIBAUD bl c_runtime_cpu_setup /* we still call old routine here */ 116*db910353SSimon Glass#endif 117*db910353SSimon Glass#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_FRAMEWORK) 118*db910353SSimon Glass# ifdef CONFIG_SPL_BUILD 119*db910353SSimon Glass /* Use a DRAM stack for the rest of SPL, if requested */ 120*db910353SSimon Glass bl spl_relocate_stack_gd 121*db910353SSimon Glass cmp r0, #0 122*db910353SSimon Glass movne sp, r0 123*db910353SSimon Glass# endif 124e05e5de7SAlbert ARIBAUD ldr r0, =__bss_start /* this is auto-relocated! */ 1253929fb0aSSimon Glass ldr r1, =__bss_end /* this is auto-relocated! */ 126e05e5de7SAlbert ARIBAUD 127e05e5de7SAlbert ARIBAUD mov r2, #0x00000000 /* prepare zero to clear BSS */ 128e05e5de7SAlbert ARIBAUD 129e05e5de7SAlbert ARIBAUDclbss_l:cmp r0, r1 /* while not at end of BSS */ 130e05e5de7SAlbert ARIBAUD strlo r2, [r0] /* clear 32-bit BSS word */ 131e05e5de7SAlbert ARIBAUD addlo r0, r0, #4 /* move to next */ 132e05e5de7SAlbert ARIBAUD blo clbss_l 133e05e5de7SAlbert ARIBAUD 134*db910353SSimon Glass#if ! defined(CONFIG_SPL_BUILD) 135e05e5de7SAlbert ARIBAUD bl coloured_LED_init 136e05e5de7SAlbert ARIBAUD bl red_led_on 137*db910353SSimon Glass#endif 138e05e5de7SAlbert ARIBAUD /* call board_init_r(gd_t *id, ulong dest_addr) */ 139fe1378a9SJeroen Hofstee mov r0, r9 /* gd_t */ 140fe1378a9SJeroen Hofstee ldr r1, [r9, #GD_RELOCADDR] /* dest_addr */ 141e05e5de7SAlbert ARIBAUD /* call board_init_r */ 142e05e5de7SAlbert ARIBAUD ldr pc, =board_init_r /* this is auto-relocated! */ 143e05e5de7SAlbert ARIBAUD 144e05e5de7SAlbert ARIBAUD /* we should not return here. */ 145e05e5de7SAlbert ARIBAUD#endif 1469c5feab7SBenoît Thébaudeau 1479c5feab7SBenoît ThébaudeauENDPROC(_main) 148