xref: /rk3399_rockchip-uboot/arch/arc/lib/start.S (revision 4d93617d87285f01f450a30584520369ff3585d2)
1*4d93617dSAlexey Brodkin/*
2*4d93617dSAlexey Brodkin * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved.
3*4d93617dSAlexey Brodkin *
4*4d93617dSAlexey Brodkin * SPDX-License-Identifier:	GPL-2.0+
5*4d93617dSAlexey Brodkin */
6*4d93617dSAlexey Brodkin
7*4d93617dSAlexey Brodkin#include <asm-offsets.h>
8*4d93617dSAlexey Brodkin#include <config.h>
9*4d93617dSAlexey Brodkin#include <linux/linkage.h>
10*4d93617dSAlexey Brodkin#include <asm/arcregs.h>
11*4d93617dSAlexey Brodkin
12*4d93617dSAlexey Brodkin/*
13*4d93617dSAlexey Brodkin * Note on the LD/ST addressing modes with address register write-back
14*4d93617dSAlexey Brodkin *
15*4d93617dSAlexey Brodkin * LD.a same as LD.aw
16*4d93617dSAlexey Brodkin *
17*4d93617dSAlexey Brodkin * LD.a    reg1, [reg2, x]  => Pre Incr
18*4d93617dSAlexey Brodkin *      Eff Addr for load = [reg2 + x]
19*4d93617dSAlexey Brodkin *
20*4d93617dSAlexey Brodkin * LD.ab   reg1, [reg2, x]  => Post Incr
21*4d93617dSAlexey Brodkin *      Eff Addr for load = [reg2]
22*4d93617dSAlexey Brodkin */
23*4d93617dSAlexey Brodkin
24*4d93617dSAlexey Brodkin.macro PUSH reg
25*4d93617dSAlexey Brodkin	st.a	\reg, [%sp, -4]
26*4d93617dSAlexey Brodkin.endm
27*4d93617dSAlexey Brodkin
28*4d93617dSAlexey Brodkin.macro PUSHAX aux
29*4d93617dSAlexey Brodkin	lr	%r9, [\aux]
30*4d93617dSAlexey Brodkin	PUSH	%r9
31*4d93617dSAlexey Brodkin.endm
32*4d93617dSAlexey Brodkin
33*4d93617dSAlexey Brodkin.macro  SAVE_R1_TO_R24
34*4d93617dSAlexey Brodkin	PUSH	%r1
35*4d93617dSAlexey Brodkin	PUSH	%r2
36*4d93617dSAlexey Brodkin	PUSH	%r3
37*4d93617dSAlexey Brodkin	PUSH	%r4
38*4d93617dSAlexey Brodkin	PUSH	%r5
39*4d93617dSAlexey Brodkin	PUSH	%r6
40*4d93617dSAlexey Brodkin	PUSH	%r7
41*4d93617dSAlexey Brodkin	PUSH	%r8
42*4d93617dSAlexey Brodkin	PUSH	%r9
43*4d93617dSAlexey Brodkin	PUSH	%r10
44*4d93617dSAlexey Brodkin	PUSH	%r11
45*4d93617dSAlexey Brodkin	PUSH	%r12
46*4d93617dSAlexey Brodkin	PUSH	%r13
47*4d93617dSAlexey Brodkin	PUSH	%r14
48*4d93617dSAlexey Brodkin	PUSH	%r15
49*4d93617dSAlexey Brodkin	PUSH	%r16
50*4d93617dSAlexey Brodkin	PUSH	%r17
51*4d93617dSAlexey Brodkin	PUSH	%r18
52*4d93617dSAlexey Brodkin	PUSH	%r19
53*4d93617dSAlexey Brodkin	PUSH	%r20
54*4d93617dSAlexey Brodkin	PUSH	%r21
55*4d93617dSAlexey Brodkin	PUSH	%r22
56*4d93617dSAlexey Brodkin	PUSH	%r23
57*4d93617dSAlexey Brodkin	PUSH	%r24
58*4d93617dSAlexey Brodkin.endm
59*4d93617dSAlexey Brodkin
60*4d93617dSAlexey Brodkin.macro SAVE_ALL_SYS
61*4d93617dSAlexey Brodkin	/* saving %r0 to reg->r0 in advance since we read %ecr into it */
62*4d93617dSAlexey Brodkin	st	%r0, [%sp, -8]
63*4d93617dSAlexey Brodkin	lr	%r0, [%ecr]	/* all stack addressing is manual so far */
64*4d93617dSAlexey Brodkin	st	%r0, [%sp]
65*4d93617dSAlexey Brodkin	st	%sp, [%sp, -4]
66*4d93617dSAlexey Brodkin	/* now move %sp to reg->r0 position so we can do "push" automatically */
67*4d93617dSAlexey Brodkin	sub	%sp, %sp, 8
68*4d93617dSAlexey Brodkin
69*4d93617dSAlexey Brodkin	SAVE_R1_TO_R24
70*4d93617dSAlexey Brodkin	PUSH	%r25
71*4d93617dSAlexey Brodkin	PUSH	%gp
72*4d93617dSAlexey Brodkin	PUSH	%fp
73*4d93617dSAlexey Brodkin	PUSH	%blink
74*4d93617dSAlexey Brodkin	PUSHAX	%eret
75*4d93617dSAlexey Brodkin	PUSHAX	%erstatus
76*4d93617dSAlexey Brodkin	PUSH	%lp_count
77*4d93617dSAlexey Brodkin	PUSHAX	%lp_end
78*4d93617dSAlexey Brodkin	PUSHAX	%lp_start
79*4d93617dSAlexey Brodkin	PUSHAX	%erbta
80*4d93617dSAlexey Brodkin.endm
81*4d93617dSAlexey Brodkin
82*4d93617dSAlexey Brodkin.macro SAVE_EXCEPTION_SOURCE
83*4d93617dSAlexey Brodkin#ifdef CONFIG_MMU
84*4d93617dSAlexey Brodkin	/* If MMU exists exception faulting address is loaded in EFA reg */
85*4d93617dSAlexey Brodkin	lr	%r0, [%efa]
86*4d93617dSAlexey Brodkin#else
87*4d93617dSAlexey Brodkin	/* Otherwise in ERET (exception return) reg */
88*4d93617dSAlexey Brodkin	lr	%r0, [%eret]
89*4d93617dSAlexey Brodkin#endif
90*4d93617dSAlexey Brodkin.endm
91*4d93617dSAlexey Brodkin
92*4d93617dSAlexey BrodkinENTRY(_start)
93*4d93617dSAlexey Brodkin	/* Setup interrupt vector base that matches "__text_start" */
94*4d93617dSAlexey Brodkin	sr	__ivt_start, [ARC_AUX_INTR_VEC_BASE]
95*4d93617dSAlexey Brodkin
96*4d93617dSAlexey Brodkin	/* Setup stack pointer */
97*4d93617dSAlexey Brodkin	mov	%sp, CONFIG_SYS_INIT_SP_ADDR
98*4d93617dSAlexey Brodkin	mov	%fp, %sp
99*4d93617dSAlexey Brodkin
100*4d93617dSAlexey Brodkin	/* Clear bss */
101*4d93617dSAlexey Brodkin	mov	%r0, __bss_start
102*4d93617dSAlexey Brodkin	mov	%r1, __bss_end
103*4d93617dSAlexey Brodkin
104*4d93617dSAlexey Brodkinclear_bss:
105*4d93617dSAlexey Brodkin	st.ab	0, [%r0, 4]
106*4d93617dSAlexey Brodkin	brlt	%r0, %r1, clear_bss
107*4d93617dSAlexey Brodkin
108*4d93617dSAlexey Brodkin	/* Zero the one and only argument of "board_init_f" */
109*4d93617dSAlexey Brodkin	mov_s	%r0, 0
110*4d93617dSAlexey Brodkin	j	board_init_f
111*4d93617dSAlexey BrodkinENDPROC(_start)
112*4d93617dSAlexey Brodkin
113*4d93617dSAlexey BrodkinENTRY(memory_error)
114*4d93617dSAlexey Brodkin	SAVE_ALL_SYS
115*4d93617dSAlexey Brodkin	SAVE_EXCEPTION_SOURCE
116*4d93617dSAlexey Brodkin	mov	%r1, %sp
117*4d93617dSAlexey Brodkin	j	do_memory_error
118*4d93617dSAlexey BrodkinENDPROC(memory_error)
119*4d93617dSAlexey Brodkin
120*4d93617dSAlexey BrodkinENTRY(instruction_error)
121*4d93617dSAlexey Brodkin	SAVE_ALL_SYS
122*4d93617dSAlexey Brodkin	SAVE_EXCEPTION_SOURCE
123*4d93617dSAlexey Brodkin	mov	%r1, %sp
124*4d93617dSAlexey Brodkin	j	do_instruction_error
125*4d93617dSAlexey BrodkinENDPROC(instruction_error)
126*4d93617dSAlexey Brodkin
127*4d93617dSAlexey BrodkinENTRY(interrupt_handler)
128*4d93617dSAlexey Brodkin	/* Todo - save and restore CPU context when interrupts will be in use */
129*4d93617dSAlexey Brodkin	bl	do_interrupt_handler
130*4d93617dSAlexey Brodkin	rtie
131*4d93617dSAlexey BrodkinENDPROC(interrupt_handler)
132*4d93617dSAlexey Brodkin
133*4d93617dSAlexey BrodkinENTRY(EV_MachineCheck)
134*4d93617dSAlexey Brodkin	SAVE_ALL_SYS
135*4d93617dSAlexey Brodkin	SAVE_EXCEPTION_SOURCE
136*4d93617dSAlexey Brodkin	mov	%r1, %sp
137*4d93617dSAlexey Brodkin	j	do_machine_check_fault
138*4d93617dSAlexey BrodkinENDPROC(EV_MachineCheck)
139*4d93617dSAlexey Brodkin
140*4d93617dSAlexey BrodkinENTRY(EV_TLBMissI)
141*4d93617dSAlexey Brodkin	SAVE_ALL_SYS
142*4d93617dSAlexey Brodkin	mov	%r0, %sp
143*4d93617dSAlexey Brodkin	j	do_itlb_miss
144*4d93617dSAlexey BrodkinENDPROC(EV_TLBMissI)
145*4d93617dSAlexey Brodkin
146*4d93617dSAlexey BrodkinENTRY(EV_TLBMissD)
147*4d93617dSAlexey Brodkin	SAVE_ALL_SYS
148*4d93617dSAlexey Brodkin	mov	%r0, %sp
149*4d93617dSAlexey Brodkin	j	do_dtlb_miss
150*4d93617dSAlexey BrodkinENDPROC(EV_TLBMissD)
151*4d93617dSAlexey Brodkin
152*4d93617dSAlexey BrodkinENTRY(EV_TLBProtV)
153*4d93617dSAlexey Brodkin	SAVE_ALL_SYS
154*4d93617dSAlexey Brodkin	SAVE_EXCEPTION_SOURCE
155*4d93617dSAlexey Brodkin	mov	%r1, %sp
156*4d93617dSAlexey Brodkin	j	do_tlb_prot_violation
157*4d93617dSAlexey BrodkinENDPROC(EV_TLBProtV)
158*4d93617dSAlexey Brodkin
159*4d93617dSAlexey BrodkinENTRY(EV_PrivilegeV)
160*4d93617dSAlexey Brodkin	SAVE_ALL_SYS
161*4d93617dSAlexey Brodkin	mov	%r0, %sp
162*4d93617dSAlexey Brodkin	j	do_privilege_violation
163*4d93617dSAlexey BrodkinENDPROC(EV_PrivilegeV)
164*4d93617dSAlexey Brodkin
165*4d93617dSAlexey BrodkinENTRY(EV_Trap)
166*4d93617dSAlexey Brodkin	SAVE_ALL_SYS
167*4d93617dSAlexey Brodkin	mov	%r0, %sp
168*4d93617dSAlexey Brodkin	j	do_trap
169*4d93617dSAlexey BrodkinENDPROC(EV_Trap)
170*4d93617dSAlexey Brodkin
171*4d93617dSAlexey BrodkinENTRY(EV_Extension)
172*4d93617dSAlexey Brodkin	SAVE_ALL_SYS
173*4d93617dSAlexey Brodkin	mov	%r0, %sp
174*4d93617dSAlexey Brodkin	j	do_extension
175*4d93617dSAlexey BrodkinENDPROC(EV_Extension)
176*4d93617dSAlexey Brodkin
177*4d93617dSAlexey Brodkin/*
178*4d93617dSAlexey Brodkin * void relocate_code (addr_sp, gd, addr_moni)
179*4d93617dSAlexey Brodkin *
180*4d93617dSAlexey Brodkin * This "function" does not return, instead it continues in RAM
181*4d93617dSAlexey Brodkin * after relocating the monitor code.
182*4d93617dSAlexey Brodkin *
183*4d93617dSAlexey Brodkin * r0 = start_addr_sp
184*4d93617dSAlexey Brodkin * r1 = new__gd
185*4d93617dSAlexey Brodkin * r2 = relocaddr
186*4d93617dSAlexey Brodkin */
187*4d93617dSAlexey BrodkinENTRY(relocate_code)
188*4d93617dSAlexey Brodkin	/*
189*4d93617dSAlexey Brodkin	 * r0-r12 might be clobbered by C functions
190*4d93617dSAlexey Brodkin	 * so we use r13-r16 for storage here
191*4d93617dSAlexey Brodkin	 */
192*4d93617dSAlexey Brodkin	mov	%r13, %r0		/* save addr_sp */
193*4d93617dSAlexey Brodkin	mov	%r14, %r1		/* save addr of gd */
194*4d93617dSAlexey Brodkin	mov	%r15, %r2		/* save addr of destination */
195*4d93617dSAlexey Brodkin
196*4d93617dSAlexey Brodkin	mov	%r16, %r2		/* %r9 - relocation offset */
197*4d93617dSAlexey Brodkin	sub	%r16, %r16, __image_copy_start
198*4d93617dSAlexey Brodkin
199*4d93617dSAlexey Brodkin/* Set up the stack */
200*4d93617dSAlexey Brodkinstack_setup:
201*4d93617dSAlexey Brodkin	mov	%sp, %r13
202*4d93617dSAlexey Brodkin	mov	%fp, %sp
203*4d93617dSAlexey Brodkin
204*4d93617dSAlexey Brodkin/* Check if monitor is loaded right in place for relocation */
205*4d93617dSAlexey Brodkin	mov	%r0, __image_copy_start
206*4d93617dSAlexey Brodkin	cmp	%r0, %r15		/* skip relocation if code loaded */
207*4d93617dSAlexey Brodkin	bz	do_board_init_r		/* in target location already */
208*4d93617dSAlexey Brodkin
209*4d93617dSAlexey Brodkin/* Copy data (__image_copy_start - __image_copy_end) to new location */
210*4d93617dSAlexey Brodkin	mov	%r1, %r15
211*4d93617dSAlexey Brodkin	mov	%r2, __image_copy_end
212*4d93617dSAlexey Brodkin	sub	%r2, %r2, %r0		/* r3 <- amount of bytes to copy */
213*4d93617dSAlexey Brodkin	asr	%r2, %r2, 2		/* r3 <- amount of words to copy */
214*4d93617dSAlexey Brodkin	mov	%lp_count, %r2
215*4d93617dSAlexey Brodkin	lp	copy_end
216*4d93617dSAlexey Brodkin	ld.ab	%r2,[%r0,4]
217*4d93617dSAlexey Brodkin	st.ab	%r2,[%r1,4]
218*4d93617dSAlexey Brodkincopy_end:
219*4d93617dSAlexey Brodkin
220*4d93617dSAlexey Brodkin/* Fix relocations related issues */
221*4d93617dSAlexey Brodkin	bl	do_elf_reloc_fixups
222*4d93617dSAlexey Brodkin#ifndef CONFIG_SYS_ICACHE_OFF
223*4d93617dSAlexey Brodkin	bl	invalidate_icache_all
224*4d93617dSAlexey Brodkin#endif
225*4d93617dSAlexey Brodkin#ifndef CONFIG_SYS_DCACHE_OFF
226*4d93617dSAlexey Brodkin	bl	flush_dcache_all
227*4d93617dSAlexey Brodkin#endif
228*4d93617dSAlexey Brodkin
229*4d93617dSAlexey Brodkin/* Update position of intterupt vector table */
230*4d93617dSAlexey Brodkin	lr	%r0, [ARC_AUX_INTR_VEC_BASE]	/* Read current position */
231*4d93617dSAlexey Brodkin	add	%r0, %r0, %r16			/* Update address */
232*4d93617dSAlexey Brodkin	sr	%r0, [ARC_AUX_INTR_VEC_BASE]	/* Write new position */
233*4d93617dSAlexey Brodkin
234*4d93617dSAlexey Brodkindo_board_init_r:
235*4d93617dSAlexey Brodkin/* Prepare for exection of "board_init_r" in relocated monitor */
236*4d93617dSAlexey Brodkin	mov	%r2, board_init_r	/* old address of "board_init_r()" */
237*4d93617dSAlexey Brodkin	add	%r2, %r2, %r16		/* new address of "board_init_r()" */
238*4d93617dSAlexey Brodkin	mov	%r0, %r14		/* 1-st parameter: gd_t */
239*4d93617dSAlexey Brodkin	mov	%r1, %r15		/* 2-nd parameter: dest_addr */
240*4d93617dSAlexey Brodkin	j	[%r2]
241*4d93617dSAlexey BrodkinENDPROC(relocate_code)
242