]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/arm/cpu/arm925t/start.S
Add GPL-2.0+ SPDX-License-Identifier to source files
[karo-tx-uboot.git] / arch / arm / cpu / arm925t / start.S
1 /*
2  *  armboot - Startup Code for ARM925 CPU-core
3  *
4  *  Copyright (c) 2003  Texas Instruments
5  *
6  *  ----- Adapted for OMAP1510 from ARM920 code ------
7  *
8  *  Copyright (c) 2001  Marius Gröger <mag@sysgo.de>
9  *  Copyright (c) 2002  Alex Züpke <azu@sysgo.de>
10  *  Copyright (c) 2002  Gary Jennejohn <garyj@denx.de>
11  *  Copyright (c) 2003  Richard Woodruff <r-woodruff2@ti.com>
12  *  Copyright (c) 2003  Kshitij  <kshitij@ti.com>
13  *
14  * SPDX-License-Identifier:     GPL-2.0+
15  */
16
17 #include <asm-offsets.h>
18 #include <config.h>
19 #include <version.h>
20
21 /*
22  *************************************************************************
23  *
24  * Jump vector table as in table 3.1 in [1]
25  *
26  *************************************************************************
27  */
28
29
30 .globl _start
31 _start: b       reset
32         ldr     pc, _undefined_instruction
33         ldr     pc, _software_interrupt
34         ldr     pc, _prefetch_abort
35         ldr     pc, _data_abort
36         ldr     pc, _not_used
37         ldr     pc, _irq
38         ldr     pc, _fiq
39
40 _undefined_instruction: .word undefined_instruction
41 _software_interrupt:    .word software_interrupt
42 _prefetch_abort:        .word prefetch_abort
43 _data_abort:            .word data_abort
44 _not_used:              .word not_used
45 _irq:                   .word irq
46 _fiq:                   .word fiq
47
48         .balignl 16,0xdeadbeef
49
50
51 /*
52  *************************************************************************
53  *
54  * Startup Code (reset vector)
55  *
56  * do important init only if we don't start from memory!
57  * setup Memory and board specific bits prior to relocation.
58  * relocate armboot to ram
59  * setup stack
60  *
61  *************************************************************************
62  */
63
64 .globl _TEXT_BASE
65 _TEXT_BASE:
66 #if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_TEXT_BASE)
67         .word   CONFIG_SPL_TEXT_BASE
68 #else
69         .word   CONFIG_SYS_TEXT_BASE
70 #endif
71
72 /*
73  * These are defined in the board-specific linker script.
74  * Subtracting _start from them lets the linker put their
75  * relative position in the executable instead of leaving
76  * them null.
77  */
78 .globl _bss_start_ofs
79 _bss_start_ofs:
80         .word __bss_start - _start
81
82 .globl _bss_end_ofs
83 _bss_end_ofs:
84         .word __bss_end - _start
85
86 .globl _end_ofs
87 _end_ofs:
88         .word _end - _start
89
90 #ifdef CONFIG_USE_IRQ
91 /* IRQ stack memory (calculated at run-time) */
92 .globl IRQ_STACK_START
93 IRQ_STACK_START:
94         .word   0x0badc0de
95
96 /* IRQ stack memory (calculated at run-time) */
97 .globl FIQ_STACK_START
98 FIQ_STACK_START:
99         .word 0x0badc0de
100 #endif
101
102 /* IRQ stack memory (calculated at run-time) + 8 bytes */
103 .globl IRQ_STACK_START_IN
104 IRQ_STACK_START_IN:
105         .word   0x0badc0de
106
107 /*
108  * the actual reset code
109  */
110
111 reset:
112         /*
113          * set the cpu to SVC32 mode
114          */
115         mrs     r0,cpsr
116         bic     r0,r0,#0x1f
117         orr     r0,r0,#0xd3
118         msr     cpsr,r0
119
120         /*
121          * Set up 925T mode
122          */
123         mov r1, #0x81               /* Set ARM925T configuration. */
124         mcr p15, 0, r1, c15, c1, 0  /* Write ARM925T configuration register. */
125
126         /*
127          * turn off the watchdog, unlock/diable sequence
128          */
129         mov  r1, #0xF5
130         ldr  r0, =WDTIM_MODE
131         strh r1, [r0]
132         mov  r1, #0xA0
133         strh r1, [r0]
134
135         /*
136          * mask all IRQs by setting all bits in the INTMR - default
137          */
138         mov r1, #0xffffffff
139         ldr r0, =REG_IHL1_MIR
140         str r1, [r0]
141         ldr r0, =REG_IHL2_MIR
142         str r1, [r0]
143
144         /*
145          * wait for dpll to lock
146          */
147         ldr  r0, =CK_DPLL1
148         mov  r1, #0x10
149         strh r1, [r0]
150 poll1:
151         ldrh r1, [r0]
152         ands r1, r1, #0x01
153         beq poll1
154
155         /*
156          * we do sys-critical inits only at reboot,
157          * not when booting from ram!
158          */
159 #ifndef CONFIG_SKIP_LOWLEVEL_INIT
160         bl  cpu_init_crit
161 #endif
162
163         bl      _main
164
165 /*------------------------------------------------------------------------------*/
166
167         .globl  c_runtime_cpu_setup
168 c_runtime_cpu_setup:
169
170         mov     pc, lr
171
172 /*
173  *************************************************************************
174  *
175  * CPU_init_critical registers
176  *
177  * setup important registers
178  * setup memory timing
179  *
180  *************************************************************************
181  */
182
183
184 cpu_init_crit:
185         /*
186          * flush v4 I/D caches
187          */
188         mov     r0, #0
189         mcr     p15, 0, r0, c7, c7, 0   /* flush v3/v4 cache */
190         mcr     p15, 0, r0, c8, c7, 0   /* flush v4 TLB */
191
192         /*
193          * disable MMU stuff and caches
194          */
195         mrc     p15, 0, r0, c1, c0, 0
196         bic     r0, r0, #0x00002300     @ clear bits 13, 9:8 (--V- --RS)
197         bic     r0, r0, #0x00000087     @ clear bits 7, 2:0 (B--- -CAM)
198         orr     r0, r0, #0x00000002     @ set bit 2 (A) Align
199         orr     r0, r0, #0x00001000     @ set bit 12 (I) I-Cache
200         mcr     p15, 0, r0, c1, c0, 0
201
202         /*
203          * Go setup Memory and board specific bits prior to relocation.
204          */
205         mov     ip, lr          /* perserve link reg across call */
206         bl      lowlevel_init   /* go setup pll,mux,memory */
207         mov     lr, ip          /* restore link */
208         mov     pc, lr          /* back to my caller */
209 /*
210  *************************************************************************
211  *
212  * Interrupt handling
213  *
214  *************************************************************************
215  */
216
217 @
218 @ IRQ stack frame.
219 @
220 #define S_FRAME_SIZE    72
221
222 #define S_OLD_R0        68
223 #define S_PSR           64
224 #define S_PC            60
225 #define S_LR            56
226 #define S_SP            52
227
228 #define S_IP            48
229 #define S_FP            44
230 #define S_R10           40
231 #define S_R9            36
232 #define S_R8            32
233 #define S_R7            28
234 #define S_R6            24
235 #define S_R5            20
236 #define S_R4            16
237 #define S_R3            12
238 #define S_R2            8
239 #define S_R1            4
240 #define S_R0            0
241
242 #define MODE_SVC 0x13
243 #define I_BIT    0x80
244
245 /*
246  * use bad_save_user_regs for abort/prefetch/undef/swi ...
247  * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
248  */
249
250         .macro  bad_save_user_regs
251         sub     sp, sp, #S_FRAME_SIZE           @ carve out a frame on current user stack
252         stmia   sp, {r0 - r12}                  @ Save user registers (now in svc mode) r0-r12
253
254         ldr     r2, IRQ_STACK_START_IN
255         ldmia   r2, {r2 - r3}                   @ get values for "aborted" pc and cpsr (into parm regs)
256         add     r0, sp, #S_FRAME_SIZE           @ grab pointer to old stack
257
258         add     r5, sp, #S_SP
259         mov     r1, lr
260         stmia   r5, {r0 - r3}                   @ save sp_SVC, lr_SVC, pc, cpsr
261         mov     r0, sp                          @ save current stack into r0 (param register)
262         .endm
263
264         .macro  irq_save_user_regs
265         sub     sp, sp, #S_FRAME_SIZE
266         stmia   sp, {r0 - r12}                  @ Calling r0-r12
267         add     r8, sp, #S_PC                   @ !!!! R8 NEEDS to be saved !!!! a reserved stack spot would be good.
268         stmdb   r8, {sp, lr}^                   @ Calling SP, LR
269         str     lr, [r8, #0]                    @ Save calling PC
270         mrs     r6, spsr
271         str     r6, [r8, #4]                    @ Save CPSR
272         str     r0, [r8, #8]                    @ Save OLD_R0
273         mov     r0, sp
274         .endm
275
276         .macro  irq_restore_user_regs
277         ldmia   sp, {r0 - lr}^                  @ Calling r0 - lr
278         mov     r0, r0
279         ldr     lr, [sp, #S_PC]                 @ Get PC
280         add     sp, sp, #S_FRAME_SIZE
281         subs    pc, lr, #4                      @ return & move spsr_svc into cpsr
282         .endm
283
284         .macro get_bad_stack
285         ldr     r13, IRQ_STACK_START_IN
286
287         str     lr, [r13]                       @ save caller lr in position 0 of saved stack
288         mrs     lr, spsr                        @ get the spsr
289         str     lr, [r13, #4]                   @ save spsr in position 1 of saved stack
290
291         mov     r13, #MODE_SVC                  @ prepare SVC-Mode
292         @ msr   spsr_c, r13
293         msr     spsr, r13                       @ switch modes, make sure moves will execute
294         mov     lr, pc                          @ capture return pc
295         movs    pc, lr                          @ jump to next instruction & switch modes.
296         .endm
297
298         .macro get_irq_stack                    @ setup IRQ stack
299         ldr     sp, IRQ_STACK_START
300         .endm
301
302         .macro get_fiq_stack                    @ setup FIQ stack
303         ldr     sp, FIQ_STACK_START
304         .endm
305
306 /*
307  * exception handlers
308  */
309         .align  5
310 undefined_instruction:
311         get_bad_stack
312         bad_save_user_regs
313         bl      do_undefined_instruction
314
315         .align  5
316 software_interrupt:
317         get_bad_stack
318         bad_save_user_regs
319         bl      do_software_interrupt
320
321         .align  5
322 prefetch_abort:
323         get_bad_stack
324         bad_save_user_regs
325         bl      do_prefetch_abort
326
327         .align  5
328 data_abort:
329         get_bad_stack
330         bad_save_user_regs
331         bl      do_data_abort
332
333         .align  5
334 not_used:
335         get_bad_stack
336         bad_save_user_regs
337         bl      do_not_used
338
339 #ifdef CONFIG_USE_IRQ
340
341         .align  5
342 irq:
343         get_irq_stack
344         irq_save_user_regs
345         bl      do_irq
346         irq_restore_user_regs
347
348         .align  5
349 fiq:
350         get_fiq_stack
351         /* someone ought to write a more effiction fiq_save_user_regs */
352         irq_save_user_regs
353         bl      do_fiq
354         irq_restore_user_regs
355
356 #else
357
358         .align  5
359 irq:
360         get_bad_stack
361         bad_save_user_regs
362         bl      do_irq
363
364         .align  5
365 fiq:
366         get_bad_stack
367         bad_save_user_regs
368         bl      do_fiq
369
370 #endif
371
372         .align  5
373 .globl reset_cpu
374 reset_cpu:
375         ldr     r1, rstctl1     /* get clkm1 reset ctl */
376         mov     r3, #0x3        /* dsp_en + arm_rst = global reset */
377         strh    r3, [r1]        /* force reset */
378         mov     r0, r0
379 _loop_forever:
380         b       _loop_forever
381 rstctl1:
382         .word   0xfffece10