1/* 2 * crt0 - C-runtime startup Code for ARM U-Boot 3 * 4 * Copyright (c) 2012 Albert ARIBAUD <albert.u.boot@aribaud.net> 5 * 6 * See file CREDITS for list of people who contributed to this 7 * project. 8 * 9 * This program is free software; you can redistribute it and/or 10 * modify it under the terms of the GNU General Public License as 11 * published by the Free Software Foundation; either version 2 of 12 * the License, or (at your option) any later version. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program; if not, write to the Free Software 21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 22 * MA 02111-1307 USA 23 */ 24 25#include <config.h> 26#include <asm-offsets.h> 27#include <linux/linkage.h> 28 29/* 30 * This file handles the target-independent stages of the U-Boot 31 * start-up where a C runtime environment is needed. Its entry point 32 * is _main and is branched into from the target's start.S file. 33 * 34 * _main execution sequence is: 35 * 36 * 1. Set up initial environment for calling board_init_f(). 37 * This environment only provides a stack and a place to store 38 * the GD ('global data') structure, both located in some readily 39 * available RAM (SRAM, locked cache...). In this context, VARIABLE 40 * global data, initialized or not (BSS), are UNAVAILABLE; only 41 * CONSTANT initialized data are available. 42 * 43 * 2. Call board_init_f(). This function prepares the hardware for 44 * execution from system RAM (DRAM, DDR...) As system RAM may not 45 * be available yet, , board_init_f() must use the current GD to 46 * store any data which must be passed on to later stages. These 47 * data include the relocation destination, the future stack, and 48 * the future GD location. 49 * 50 * (the following applies only to non-SPL builds) 51 * 52 * 3. Set up intermediate environment where the stack and GD are the 53 * ones allocated by board_init_f() in system RAM, but BSS and 54 * initialized non-const data are still not available. 55 * 56 * 4. Call relocate_code(). This function relocates U-Boot from its 57 * current location into the relocation destination computed by 58 * board_init_f(). 59 * 60 * 5. Set up final environment for calling board_init_r(). This 61 * environment has BSS (initialized to 0), initialized non-const 62 * data (initialized to their intended value), and stack in system 63 * RAM. GD has retained values set by board_init_f(). Some CPUs 64 * have some work left to do at this point regarding memory, so 65 * call c_runtime_cpu_setup. 66 * 67 * 6. Branch to board_init_r(). 68 */ 69 70/* 71 * entry point of crt0 sequence 72 */ 73 74ENTRY(_main) 75 76/* 77 * Set up initial C runtime environment and call board_init_f(0). 78 */ 79 80#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK) 81 ldr sp, =(CONFIG_SPL_STACK) 82#else 83 ldr sp, =(CONFIG_SYS_INIT_SP_ADDR) 84#endif 85 bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ 86 sub sp, #GD_SIZE /* allocate one GD above SP */ 87 bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ 88 mov r8, sp /* GD is above SP */ 89 mov r0, #0 90 bl board_init_f 91 92#if ! defined(CONFIG_SPL_BUILD) 93 94/* 95 * Set up intermediate environment (new sp and gd) and call 96 * relocate_code(addr_moni). Trick here is that we'll return 97 * 'here' but relocated. 98 */ 99 100 ldr sp, [r8, #GD_START_ADDR_SP] /* r8 = gd->start_addr_sp */ 101 bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ 102 ldr r8, [r8, #GD_BD] /* r8 = gd->bd */ 103 sub r8, r8, #GD_SIZE /* new GD is below bd */ 104 105 adr lr, here 106 ldr r0, [r8, #GD_RELOC_OFF] /* lr = gd->start_addr_sp */ 107 add lr, lr, r0 108 ldr r0, [r8, #GD_RELOCADDR] /* r0 = gd->relocaddr */ 109 b relocate_code 110here: 111 112/* Set up final (full) environment */ 113 114 bl c_runtime_cpu_setup /* we still call old routine here */ 115 116 ldr r0, =__bss_start /* this is auto-relocated! */ 117 ldr r1, =__bss_end /* this is auto-relocated! */ 118 119 mov r2, #0x00000000 /* prepare zero to clear BSS */ 120 121clbss_l:cmp r0, r1 /* while not at end of BSS */ 122 strlo r2, [r0] /* clear 32-bit BSS word */ 123 addlo r0, r0, #4 /* move to next */ 124 blo clbss_l 125 126 bl coloured_LED_init 127 bl red_led_on 128 129 /* call board_init_r(gd_t *id, ulong dest_addr) */ 130 mov r0, r8 /* gd_t */ 131 ldr r1, [r8, #GD_RELOCADDR] /* dest_addr */ 132 /* call board_init_r */ 133 ldr pc, =board_init_r /* this is auto-relocated! */ 134 135 /* we should not return here. */ 136 137#endif 138 139ENDPROC(_main) 140