1*4882a593Smuzhiyun/* 2*4882a593Smuzhiyun * A lowlevel_init function that sets up the stack to call a C function to 3*4882a593Smuzhiyun * perform further init. 4*4882a593Smuzhiyun * 5*4882a593Smuzhiyun * (C) Copyright 2010 6*4882a593Smuzhiyun * Texas Instruments, <www.ti.com> 7*4882a593Smuzhiyun * 8*4882a593Smuzhiyun * Author : 9*4882a593Smuzhiyun * Aneesh V <aneesh@ti.com> 10*4882a593Smuzhiyun * 11*4882a593Smuzhiyun * SPDX-License-Identifier: GPL-2.0+ 12*4882a593Smuzhiyun */ 13*4882a593Smuzhiyun 14*4882a593Smuzhiyun#include <asm-offsets.h> 15*4882a593Smuzhiyun#include <config.h> 16*4882a593Smuzhiyun#include <linux/linkage.h> 17*4882a593Smuzhiyun 18*4882a593Smuzhiyun.pushsection .text.s_init, "ax" 19*4882a593SmuzhiyunWEAK(s_init) 20*4882a593Smuzhiyun bx lr 21*4882a593SmuzhiyunENDPROC(s_init) 22*4882a593Smuzhiyun.popsection 23*4882a593Smuzhiyun 24*4882a593Smuzhiyun.pushsection .text.lowlevel_init, "ax" 25*4882a593SmuzhiyunWEAK(lowlevel_init) 26*4882a593Smuzhiyun /* 27*4882a593Smuzhiyun * Setup a temporary stack. Global data is not available yet. 28*4882a593Smuzhiyun */ 29*4882a593Smuzhiyun#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK) 30*4882a593Smuzhiyun ldr sp, =CONFIG_SPL_STACK 31*4882a593Smuzhiyun#else 32*4882a593Smuzhiyun ldr sp, =CONFIG_SYS_INIT_SP_ADDR 33*4882a593Smuzhiyun#endif 34*4882a593Smuzhiyun bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ 35*4882a593Smuzhiyun#ifdef CONFIG_SPL_DM 36*4882a593Smuzhiyun mov r9, #0 37*4882a593Smuzhiyun#else 38*4882a593Smuzhiyun /* 39*4882a593Smuzhiyun * Set up global data for boards that still need it. This will be 40*4882a593Smuzhiyun * removed soon. 41*4882a593Smuzhiyun */ 42*4882a593Smuzhiyun#ifdef CONFIG_SPL_BUILD 43*4882a593Smuzhiyun ldr r9, =gdata 44*4882a593Smuzhiyun#else 45*4882a593Smuzhiyun sub sp, sp, #GD_SIZE 46*4882a593Smuzhiyun bic sp, sp, #7 47*4882a593Smuzhiyun mov r9, sp 48*4882a593Smuzhiyun#endif 49*4882a593Smuzhiyun#endif 50*4882a593Smuzhiyun /* 51*4882a593Smuzhiyun * Save the old lr(passed in ip) and the current lr to stack 52*4882a593Smuzhiyun */ 53*4882a593Smuzhiyun push {ip, lr} 54*4882a593Smuzhiyun 55*4882a593Smuzhiyun /* 56*4882a593Smuzhiyun * Call the very early init function. This should do only the 57*4882a593Smuzhiyun * absolute bare minimum to get started. It should not: 58*4882a593Smuzhiyun * 59*4882a593Smuzhiyun * - set up DRAM 60*4882a593Smuzhiyun * - use global_data 61*4882a593Smuzhiyun * - clear BSS 62*4882a593Smuzhiyun * - try to start a console 63*4882a593Smuzhiyun * 64*4882a593Smuzhiyun * For boards with SPL this should be empty since SPL can do all of 65*4882a593Smuzhiyun * this init in the SPL board_init_f() function which is called 66*4882a593Smuzhiyun * immediately after this. 67*4882a593Smuzhiyun */ 68*4882a593Smuzhiyun bl s_init 69*4882a593Smuzhiyun pop {ip, pc} 70*4882a593SmuzhiyunENDPROC(lowlevel_init) 71*4882a593Smuzhiyun.popsection 72