1*4882a593Smuzhiyun/* 2*4882a593Smuzhiyun * crt0 - C-runtime startup Code for AArch64 U-Boot 3*4882a593Smuzhiyun * 4*4882a593Smuzhiyun * (C) Copyright 2013 5*4882a593Smuzhiyun * David Feng <fenghua@phytium.com.cn> 6*4882a593Smuzhiyun * 7*4882a593Smuzhiyun * (C) Copyright 2012 8*4882a593Smuzhiyun * Albert ARIBAUD <albert.u.boot@aribaud.net> 9*4882a593Smuzhiyun * 10*4882a593Smuzhiyun * SPDX-License-Identifier: GPL-2.0+ 11*4882a593Smuzhiyun */ 12*4882a593Smuzhiyun 13*4882a593Smuzhiyun#include <config.h> 14*4882a593Smuzhiyun#include <asm-offsets.h> 15*4882a593Smuzhiyun#include <asm/macro.h> 16*4882a593Smuzhiyun#include <asm/system.h> 17*4882a593Smuzhiyun#include <linux/linkage.h> 18*4882a593Smuzhiyun 19*4882a593Smuzhiyun/* 20*4882a593Smuzhiyun * This file handles the target-independent stages of the U-Boot 21*4882a593Smuzhiyun * start-up where a C runtime environment is needed. Its entry point 22*4882a593Smuzhiyun * is _main and is branched into from the target's start.S file. 23*4882a593Smuzhiyun * 24*4882a593Smuzhiyun * _main execution sequence is: 25*4882a593Smuzhiyun * 26*4882a593Smuzhiyun * 1. Set up initial environment for calling board_init_f(). 27*4882a593Smuzhiyun * This environment only provides a stack and a place to store 28*4882a593Smuzhiyun * the GD ('global data') structure, both located in some readily 29*4882a593Smuzhiyun * available RAM (SRAM, locked cache...). In this context, VARIABLE 30*4882a593Smuzhiyun * global data, initialized or not (BSS), are UNAVAILABLE; only 31*4882a593Smuzhiyun * CONSTANT initialized data are available. GD should be zeroed 32*4882a593Smuzhiyun * before board_init_f() is called. 33*4882a593Smuzhiyun * 34*4882a593Smuzhiyun * 2. Call board_init_f(). This function prepares the hardware for 35*4882a593Smuzhiyun * execution from system RAM (DRAM, DDR...) As system RAM may not 36*4882a593Smuzhiyun * be available yet, , board_init_f() must use the current GD to 37*4882a593Smuzhiyun * store any data which must be passed on to later stages. These 38*4882a593Smuzhiyun * data include the relocation destination, the future stack, and 39*4882a593Smuzhiyun * the future GD location. 40*4882a593Smuzhiyun * 41*4882a593Smuzhiyun * 3. Set up intermediate environment where the stack and GD are the 42*4882a593Smuzhiyun * ones allocated by board_init_f() in system RAM, but BSS and 43*4882a593Smuzhiyun * initialized non-const data are still not available. 44*4882a593Smuzhiyun * 45*4882a593Smuzhiyun * 4a.For U-Boot proper (not SPL), call relocate_code(). This function 46*4882a593Smuzhiyun * relocates U-Boot from its current location into the relocation 47*4882a593Smuzhiyun * destination computed by board_init_f(). 48*4882a593Smuzhiyun * 49*4882a593Smuzhiyun * 4b.For SPL, board_init_f() just returns (to crt0). There is no 50*4882a593Smuzhiyun * code relocation in SPL. 51*4882a593Smuzhiyun * 52*4882a593Smuzhiyun * 5. Set up final environment for calling board_init_r(). This 53*4882a593Smuzhiyun * environment has BSS (initialized to 0), initialized non-const 54*4882a593Smuzhiyun * data (initialized to their intended value), and stack in system 55*4882a593Smuzhiyun * RAM (for SPL moving the stack and GD into RAM is optional - see 56*4882a593Smuzhiyun * CONFIG_SPL_STACK_R). GD has retained values set by board_init_f(). 57*4882a593Smuzhiyun * 58*4882a593Smuzhiyun * TODO: For SPL, implement stack relocation on AArch64. 59*4882a593Smuzhiyun * 60*4882a593Smuzhiyun * 6. For U-Boot proper (not SPL), some CPUs have some work left to do 61*4882a593Smuzhiyun * at this point regarding memory, so call c_runtime_cpu_setup. 62*4882a593Smuzhiyun * 63*4882a593Smuzhiyun * 7. Branch to board_init_r(). 64*4882a593Smuzhiyun * 65*4882a593Smuzhiyun * For more information see 'Board Initialisation Flow in README. 66*4882a593Smuzhiyun */ 67*4882a593Smuzhiyun 68*4882a593SmuzhiyunENTRY(_main) 69*4882a593Smuzhiyun 70*4882a593Smuzhiyun/* 71*4882a593Smuzhiyun * Set up initial C runtime environment and call board_init_f(0). 72*4882a593Smuzhiyun */ 73*4882a593Smuzhiyun#if defined(CONFIG_TPL_BUILD) && defined(CONFIG_TPL_NEEDS_SEPARATE_STACK) 74*4882a593Smuzhiyun ldr x0, =(CONFIG_TPL_STACK) 75*4882a593Smuzhiyun#elif defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK) 76*4882a593Smuzhiyun ldr x0, =(CONFIG_SPL_STACK) 77*4882a593Smuzhiyun#else 78*4882a593Smuzhiyun ldr x0, =(CONFIG_SYS_INIT_SP_ADDR) 79*4882a593Smuzhiyun#endif 80*4882a593Smuzhiyun bic sp, x0, #0xf /* 16-byte alignment for ABI compliance */ 81*4882a593Smuzhiyun mov x0, sp 82*4882a593Smuzhiyun bl board_init_f_alloc_reserve 83*4882a593Smuzhiyun mov sp, x0 84*4882a593Smuzhiyun /* set up gd here, outside any C code */ 85*4882a593Smuzhiyun mov x18, x0 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) && !defined(CONFIG_TPL_BUILD) && !defined(CONFIG_SPL_SKIP_RELOCATE)) || \ 92*4882a593Smuzhiyun !defined(CONFIG_SPL_BUILD) 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 ldr x0, [x18, #GD_START_ADDR_SP] /* x0 <- gd->start_addr_sp */ 99*4882a593Smuzhiyun bic sp, x0, #0xf /* 16-byte alignment for ABI compliance */ 100*4882a593Smuzhiyun ldr x18, [x18, #GD_NEW_GD] /* x18 <- gd->new_gd */ 101*4882a593Smuzhiyun 102*4882a593Smuzhiyun#ifndef CONFIG_SKIP_RELOCATE_UBOOT 103*4882a593Smuzhiyun adr lr, relocation_return 104*4882a593Smuzhiyun#if CONFIG_POSITION_INDEPENDENT 105*4882a593Smuzhiyun /* Add in link-vs-runtime offset */ 106*4882a593Smuzhiyun adr x0, _start /* x0 <- Runtime value of _start */ 107*4882a593Smuzhiyun ldr x9, _TEXT_BASE /* x9 <- Linked value of _start */ 108*4882a593Smuzhiyun sub x9, x9, x0 /* x9 <- Run-vs-link offset */ 109*4882a593Smuzhiyun add lr, lr, x9 110*4882a593Smuzhiyun#endif 111*4882a593Smuzhiyun /* Add in link-vs-relocation offset */ 112*4882a593Smuzhiyun ldr x9, [x18, #GD_RELOC_OFF] /* x9 <- gd->reloc_off */ 113*4882a593Smuzhiyun add lr, lr, x9 /* new return address after relocation */ 114*4882a593Smuzhiyun ldr x0, [x18, #GD_RELOCADDR] /* x0 <- gd->relocaddr */ 115*4882a593Smuzhiyun b relocate_code 116*4882a593Smuzhiyun#endif 117*4882a593Smuzhiyun 118*4882a593Smuzhiyunrelocation_return: 119*4882a593Smuzhiyun 120*4882a593Smuzhiyun/* 121*4882a593Smuzhiyun * Set up final (full) environment 122*4882a593Smuzhiyun */ 123*4882a593Smuzhiyun bl c_runtime_cpu_setup /* still call old routine */ 124*4882a593Smuzhiyun#endif /* !CONFIG_SPL_BUILD */ 125*4882a593Smuzhiyun#if defined(CONFIG_SPL_BUILD) 126*4882a593Smuzhiyun bl spl_relocate_stack_gd /* may return NULL */ 127*4882a593Smuzhiyun /* set up gd here, outside any C code, if new stack is returned */ 128*4882a593Smuzhiyun cmp x0, #0 129*4882a593Smuzhiyun csel x18, x0, x18, ne 130*4882a593Smuzhiyun /* 131*4882a593Smuzhiyun * Perform 'sp = (x0 != NULL) ? x0 : sp' while working 132*4882a593Smuzhiyun * around the constraint that conditional moves can not 133*4882a593Smuzhiyun * have 'sp' as an operand 134*4882a593Smuzhiyun */ 135*4882a593Smuzhiyun mov x1, sp 136*4882a593Smuzhiyun cmp x0, #0 137*4882a593Smuzhiyun csel x0, x0, x1, ne 138*4882a593Smuzhiyun mov sp, x0 139*4882a593Smuzhiyun#endif 140*4882a593Smuzhiyun 141*4882a593Smuzhiyun/* 142*4882a593Smuzhiyun * Clear BSS section 143*4882a593Smuzhiyun */ 144*4882a593Smuzhiyun ldr x0, =__bss_start /* this is auto-relocated! */ 145*4882a593Smuzhiyun ldr x1, =__bss_end /* this is auto-relocated! */ 146*4882a593Smuzhiyunclear_loop: 147*4882a593Smuzhiyun str xzr, [x0], #8 148*4882a593Smuzhiyun cmp x0, x1 149*4882a593Smuzhiyun b.lo clear_loop 150*4882a593Smuzhiyun 151*4882a593Smuzhiyun /* call board_init_r(gd_t *id, ulong dest_addr) */ 152*4882a593Smuzhiyun mov x0, x18 /* gd_t */ 153*4882a593Smuzhiyun ldr x1, [x18, #GD_RELOCADDR] /* dest_addr */ 154*4882a593Smuzhiyun b board_init_r /* PC relative jump */ 155*4882a593Smuzhiyun 156*4882a593Smuzhiyun /* NOTREACHED - board_init_r() does not return */ 157*4882a593Smuzhiyun 158*4882a593SmuzhiyunENDPROC(_main) 159