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 either nand_boot() or 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_NAND_SPL) 81 /* deprecated, use instead CONFIG_SPL_BUILD */ 82 ldr sp, =(CONFIG_SYS_INIT_SP_ADDR) 83#elif defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK) 84 ldr sp, =(CONFIG_SPL_STACK) 85#else 86 ldr sp, =(CONFIG_SYS_INIT_SP_ADDR) 87#endif 88 bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ 89 sub sp, #GD_SIZE /* allocate one GD above SP */ 90 bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ 91 mov r8, sp /* GD is above SP */ 92 mov r0, #0 93 bl board_init_f 94 95#if ! defined(CONFIG_SPL_BUILD) 96 97/* 98 * Set up intermediate environment (new sp and gd) and call 99 * relocate_code(addr_moni). Trick here is that we'll return 100 * 'here' but relocated. 101 */ 102 103 ldr sp, [r8, #GD_START_ADDR_SP] /* r8 = gd->start_addr_sp */ 104 bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ 105 ldr r8, [r8, #GD_BD] /* r8 = gd->bd */ 106 sub r8, r8, #GD_SIZE /* new GD is below bd */ 107 108 adr lr, here 109 ldr r0, [r8, #GD_RELOC_OFF] /* lr = gd->start_addr_sp */ 110 add lr, lr, r0 111 ldr r0, [r8, #GD_RELOCADDR] /* r0 = gd->relocaddr */ 112 b relocate_code 113here: 114 115/* Set up final (full) environment */ 116 117 bl c_runtime_cpu_setup /* we still call old routine here */ 118 119 ldr r0, =__bss_start /* this is auto-relocated! */ 120 ldr r1, =__bss_end /* this is auto-relocated! */ 121 122 mov r2, #0x00000000 /* prepare zero to clear BSS */ 123 124clbss_l:cmp r0, r1 /* while not at end of BSS */ 125 strlo r2, [r0] /* clear 32-bit BSS word */ 126 addlo r0, r0, #4 /* move to next */ 127 blo clbss_l 128 129 bl coloured_LED_init 130 bl red_led_on 131 132#if defined(CONFIG_NAND_SPL) 133 134 /* call _nand_boot() */ 135 ldr pc, =nand_boot 136 137#else 138 139 /* call board_init_r(gd_t *id, ulong dest_addr) */ 140 mov r0, r8 /* gd_t */ 141 ldr r1, [r8, #GD_RELOCADDR] /* dest_addr */ 142 /* call board_init_r */ 143 ldr pc, =board_init_r /* this is auto-relocated! */ 144 145#endif 146 147 /* we should not return here. */ 148 149#endif 150 151ENDPROC(_main) 152