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