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 28/* 29 * This file handles the target-independent stages of the U-Boot 30 * start-up where a C runtime environment is needed. Its entry point 31 * is _main and is branched into from the target's start.S file. 32 * 33 * _main execution sequence is: 34 * 35 * 1. Set up initial environment for calling board_init_f(). 36 * This environment only provides a stack and a place to store 37 * the GD ('global data') structure, both located in some readily 38 * available RAM (SRAM, locked cache...). In this context, VARIABLE 39 * global data, initialized or not (BSS), are UNAVAILABLE; only 40 * CONSTANT initialized data are available. 41 * 42 * 2. Call board_init_f(). This function prepares the hardware for 43 * execution from system RAM (DRAM, DDR...) As system RAM may not 44 * be available yet, , board_init_f() must use the current GD to 45 * store any data which must be passed on to later stages. These 46 * data include the relocation destination, the future stack, and 47 * the future GD location. 48 * 49 * (the following applies only to non-SPL builds) 50 * 51 * 3. Set up intermediate environment where the stack and GD are the 52 * ones allocated by board_init_f() in system RAM, but BSS and 53 * initialized non-const data are still not available. 54 * 55 * 4. Call relocate_code(). This function relocates U-Boot from its 56 * current location into the relocation destination computed by 57 * board_init_f(). 58 * 59 * 5. Set up final environment for calling board_init_r(). This 60 * environment has BSS (initialized to 0), initialized non-const 61 * data (initialized to their intended value), and stack in system 62 * RAM. GD has retained values set by board_init_f(). Some CPUs 63 * have some work left to do at this point regarding memory, so 64 * call c_runtime_cpu_setup. 65 * 66 * 6. Branch to either nand_boot() or board_init_r(). 67 */ 68 69/* 70 * declare nand_boot() or board_init_r() to jump to at end of crt0 71 */ 72 73#if defined(CONFIG_NAND_SPL) 74 75.globl nand_boot 76 77#elif ! defined(CONFIG_SPL_BUILD) 78 79.globl board_init_r 80 81#endif 82 83/* 84 * start and end of BSS 85 */ 86 87.globl __bss_start 88.globl __bss_end 89 90/* 91 * entry point of crt0 sequence 92 */ 93 94.global _main 95 96_main: 97 98/* 99 * Set up initial C runtime environment and call board_init_f(0). 100 */ 101 102#if defined(CONFIG_NAND_SPL) 103 /* deprecated, use instead CONFIG_SPL_BUILD */ 104 ldr sp, =(CONFIG_SYS_INIT_SP_ADDR) 105#elif defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK) 106 ldr sp, =(CONFIG_SPL_STACK) 107#else 108 ldr sp, =(CONFIG_SYS_INIT_SP_ADDR) 109#endif 110 bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ 111 sub sp, #GD_SIZE /* allocate one GD above SP */ 112 bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ 113 mov r8, sp /* GD is above SP */ 114 mov r0, #0 115 bl board_init_f 116 117#if ! defined(CONFIG_SPL_BUILD) 118 119/* 120 * Set up intermediate environment (new sp and gd) and call 121 * relocate_code(addr_sp, gd, addr_moni). Trick here is that 122 * we'll return 'here' but relocated. 123 */ 124 125 ldr sp, [r8, #GD_START_ADDR_SP] /* r8 = gd->start_addr_sp */ 126 bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ 127 ldr r8, [r8, #GD_BD] /* r8 = gd->bd */ 128 sub r8, r8, #GD_SIZE /* new GD is below bd */ 129 130 adr lr, here 131 ldr r0, [r8, #GD_RELOC_OFF] /* lr = gd->start_addr_sp */ 132 add lr, lr, r0 133 ldr r0, [r8, #GD_START_ADDR_SP] /* r0 = gd->start_addr_sp */ 134 mov r1, r8 /* r1 = gd */ 135 ldr r2, [r8, #GD_RELOCADDR] /* r2 = gd->relocaddr */ 136 b relocate_code 137here: 138 139/* Set up final (full) environment */ 140 141 bl c_runtime_cpu_setup /* we still call old routine here */ 142 143 ldr r0, =__bss_start /* this is auto-relocated! */ 144 ldr r1, =__bss_end /* this is auto-relocated! */ 145 146 mov r2, #0x00000000 /* prepare zero to clear BSS */ 147 148clbss_l:cmp r0, r1 /* while not at end of BSS */ 149 strlo r2, [r0] /* clear 32-bit BSS word */ 150 addlo r0, r0, #4 /* move to next */ 151 blo clbss_l 152 153 bl coloured_LED_init 154 bl red_led_on 155 156#if defined(CONFIG_NAND_SPL) 157 158 /* call _nand_boot() */ 159 ldr pc, =nand_boot 160 161#else 162 163 /* call board_init_r(gd_t *id, ulong dest_addr) */ 164 mov r0, r8 /* gd_t */ 165 ldr r1, [r8, #GD_RELOCADDR] /* dest_addr */ 166 /* call board_init_r */ 167 ldr pc, =board_init_r /* this is auto-relocated! */ 168 169#endif 170 171 /* we should not return here. */ 172 173#endif 174