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