]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - cpu/arm_cortexa8/start.S
imported Freescale specific U-Boot additions for i.MX28,... release L2.6.31_10.08.01
[karo-tx-uboot.git] / cpu / arm_cortexa8 / start.S
1 /*
2  * armboot - Startup Code for OMAP3530/ARM Cortex CPU-core
3  *
4  * Copyright (c) 2004   Texas Instruments <r-woodruff2@ti.com>
5  *
6  * Copyright (c) 2001   Marius Gröger <mag@sysgo.de>
7  * Copyright (c) 2002   Alex Züpke <azu@sysgo.de>
8  * Copyright (c) 2002   Gary Jennejohn <garyj@denx.de>
9  * Copyright (c) 2003   Richard Woodruff <r-woodruff2@ti.com>
10  * Copyright (c) 2003   Kshitij <kshitij@ti.com>
11  * Copyright (c) 2006-2008 Syed Mohammed Khasim <x0khasim@ti.com>
12  * Copyright (c) 2009 Freescale Semiconductor, Inc.
13  *
14  * See file CREDITS for list of people who contributed to this
15  * project.
16  *
17  * This program is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU General Public License as
19  * published by the Free Software Foundation; either version 2 of
20  * the License, or (at your option) any later version.
21  *
22  * This program is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25  * GNU General Public License for more details.
26  *
27  * You should have received a copy of the GNU General Public License
28  * along with this program; if not, write to the Free Software
29  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
30  * MA 02111-1307 USA
31  */
32
33 #include <config.h>
34 #include <version.h>
35
36 .globl _start
37 _start: b       reset
38         ldr     pc, _undefined_instruction
39         ldr     pc, _software_interrupt
40         ldr     pc, _prefetch_abort
41         ldr     pc, _data_abort
42         ldr     pc, _not_used
43         ldr     pc, _irq
44         ldr     pc, _fiq
45
46 _undefined_instruction: .word undefined_instruction
47 _software_interrupt:    .word software_interrupt
48 _prefetch_abort:        .word prefetch_abort
49 _data_abort:            .word data_abort
50 _not_used:              .word not_used
51 _irq:                   .word irq
52 _fiq:                   .word fiq
53 _pad:                   .word 0x12345678 /* now 16*4=64 */
54 .global _end_vect
55 _end_vect:
56
57         .balignl 16,0xdeadbeef
58 /*************************************************************************
59  *
60  * Startup Code (reset vector)
61  *
62  * do important init only if we don't start from memory!
63  * setup Memory and board specific bits prior to relocation.
64  * relocate armboot to ram
65  * setup stack
66  *
67  *************************************************************************/
68
69 _TEXT_BASE:
70         .word   TEXT_BASE
71
72 .globl _armboot_start
73 _armboot_start:
74         .word _start
75
76 /*
77  * These are defined in the board-specific linker script.
78  */
79 .globl _bss_start
80 _bss_start:
81         .word __bss_start
82
83 .globl _bss_end
84 _bss_end:
85         .word _end
86
87 #ifdef CONFIG_USE_IRQ
88 /* IRQ stack memory (calculated at run-time) */
89 .globl IRQ_STACK_START
90 IRQ_STACK_START:
91         .word   0x0badc0de
92
93 /* IRQ stack memory (calculated at run-time) */
94 .globl FIQ_STACK_START
95 FIQ_STACK_START:
96         .word 0x0badc0de
97 #endif
98
99 /*
100  * the actual reset code
101  */
102
103 reset:
104         /*
105          * set the cpu to SVC32 mode
106          */
107         mrs     r0, cpsr
108         bic     r0, r0, #0x1f
109         orr     r0, r0, #0xd3
110         msr     cpsr,r0
111
112 #if (CONFIG_OMAP34XX)
113         /* Copy vectors to mask ROM indirect addr */
114         adr     r0, _start              @ r0 <- current position of code
115         add     r0, r0, #4              @ skip reset vector
116         mov     r2, #64                 @ r2 <- size to copy
117         add     r2, r0, r2              @ r2 <- source end address
118         mov     r1, #SRAM_OFFSET0       @ build vect addr
119         mov     r3, #SRAM_OFFSET1
120         add     r1, r1, r3
121         mov     r3, #SRAM_OFFSET2
122         add     r1, r1, r3
123 next:
124         ldmia   r0!, {r3 - r10}         @ copy from source address [r0]
125         stmia   r1!, {r3 - r10}         @ copy to   target address [r1]
126         cmp     r0, r2                  @ until source end address [r2]
127         bne     next                    @ loop until equal */
128 #if !defined(CONFIG_SYS_NAND_BOOT) && !defined(CONFIG_SYS_ONENAND_BOOT)
129         /* No need to copy/exec the clock code - DPLL adjust already done
130          * in NAND/oneNAND Boot.
131          */
132         bl      cpy_clk_code            @ put dpll adjust code behind vectors
133 #endif /* NAND Boot */
134 #endif
135         /* the mask ROM code should have PLL and others stable */
136 #ifndef CONFIG_SKIP_LOWLEVEL_INIT
137         bl      cpu_init_crit
138 #endif
139
140 #ifndef CONFIG_SKIP_RELOCATE_UBOOT
141 relocate:                               @ relocate U-Boot to RAM
142         adr     r0, _start              @ r0 <- current position of code
143         ldr     r1, _TEXT_BASE          @ test if we run from flash or RAM
144         cmp     r0, r1                  @ don't reloc during debug
145         beq     stack_setup
146
147         ldr     r2, _armboot_start
148         ldr     r3, _bss_start
149         sub     r2, r3, r2              @ r2 <- size of armboot
150         add     r2, r0, r2              @ r2 <- source end address
151
152 copy_loop:                              @ copy 32 bytes at a time
153         ldmia   r0!, {r3 - r10}         @ copy from source address [r0]
154         stmia   r1!, {r3 - r10}         @ copy to   target address [r1]
155         cmp     r0, r2                  @ until source end addreee [r2]
156         ble     copy_loop
157 #endif  /* CONFIG_SKIP_RELOCATE_UBOOT */
158
159         /* Set up the stack */
160 stack_setup:
161         ldr     r0, _TEXT_BASE          @ upper 128 KiB: relocated uboot
162         sub     r0, r0, #CONFIG_SYS_MALLOC_LEN @ malloc area
163         sub     r0, r0, #CONFIG_SYS_GBL_DATA_SIZE @ bdinfo
164 #ifdef CONFIG_USE_IRQ
165         sub     r0, r0, #(CONFIG_STACKSIZE_IRQ + CONFIG_STACKSIZE_FIQ)
166 #endif
167         sub     sp, r0, #12             @ leave 3 words for abort-stack
168         and     sp, sp, #~7             @ 8 byte alinged for (ldr/str)d
169
170         /* Clear BSS (if any). Is below tx (watch load addr - need space) */
171 clear_bss:
172         ldr     r0, _bss_start          @ find start of bss segment
173         ldr     r1, _bss_end            @ stop here
174         mov     r2, #0x00000000         @ clear value
175 clbss_l:
176         str     r2, [r0]                @ clear BSS location
177         cmp     r0, r1                  @ are we at the end yet
178         add     r0, r0, #4              @ increment clear index pointer
179         bne     clbss_l                 @ keep clearing till at end
180
181 #ifdef CONFIG_ARCH_MMU
182         bl board_mmu_init
183 #endif
184         ldr     pc, _start_armboot      @ jump to C code
185
186 _start_armboot: .word start_armboot
187
188
189 /*************************************************************************
190  *
191  * CPU_init_critical registers
192  *
193  * setup important registers
194  * setup memory timing
195  *
196  *************************************************************************/
197 cpu_init_crit:
198         /*
199          * Invalidate L1 I/D
200          */
201         mov     r0, #0                  @ set up for MCR
202         mcr     p15, 0, r0, c8, c7, 0   @ invalidate TLBs
203         mcr     p15, 0, r0, c7, c5, 0   @ invalidate icache
204
205         /*
206          * disable MMU stuff and caches
207          */
208         mrc     p15, 0, r0, c1, c0, 0
209         bic     r0, r0, #0x00002000     @ clear bits 13 (--V-)
210         bic     r0, r0, #0x00000007     @ clear bits 2:0 (-CAM)
211         orr     r0, r0, #0x00000002     @ set bit 1 (--A-) Align
212         orr     r0, r0, #0x00000800     @ set bit 12 (Z---) BTB
213         mcr     p15, 0, r0, c1, c0, 0
214
215         /*
216          * Jump to board specific initialization...
217          * The Mask ROM will have already initialized
218          * basic memory. Go here to bump up clock rate and handle
219          * wake up conditions.
220          */
221         mov     ip, lr                  @ persevere link reg across call
222         bl      lowlevel_init           @ go setup pll,mux,memory
223         mov     lr, ip                  @ restore link
224         mov     pc, lr                  @ back to my caller
225 /*
226  *************************************************************************
227  *
228  * Interrupt handling
229  *
230  *************************************************************************
231  */
232 @
233 @ IRQ stack frame.
234 @
235 #define S_FRAME_SIZE    72
236
237 #define S_OLD_R0        68
238 #define S_PSR           64
239 #define S_PC            60
240 #define S_LR            56
241 #define S_SP            52
242
243 #define S_IP            48
244 #define S_FP            44
245 #define S_R10           40
246 #define S_R9            36
247 #define S_R8            32
248 #define S_R7            28
249 #define S_R6            24
250 #define S_R5            20
251 #define S_R4            16
252 #define S_R3            12
253 #define S_R2            8
254 #define S_R1            4
255 #define S_R0            0
256
257 #define MODE_SVC 0x13
258 #define I_BIT    0x80
259
260 /*
261  * use bad_save_user_regs for abort/prefetch/undef/swi ...
262  * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
263  */
264
265         .macro  bad_save_user_regs
266         sub     sp, sp, #S_FRAME_SIZE           @ carve out a frame on current
267                                                 @ user stack
268         stmia   sp, {r0 - r12}                  @ Save user registers (now in
269                                                 @ svc mode) r0-r12
270
271         ldr     r2, _armboot_start
272         sub     r2, r2, #(CONFIG_SYS_MALLOC_LEN)
273         sub     r2, r2, #(CONFIG_SYS_GBL_DATA_SIZE + 8) @ set base 2 words into abort
274                                                 @ stack
275         ldmia   r2, {r2 - r3}                   @ get values for "aborted" pc
276                                                 @ and cpsr (into parm regs)
277         add     r0, sp, #S_FRAME_SIZE           @ grab pointer to old stack
278
279         add     r5, sp, #S_SP
280         mov     r1, lr
281         stmia   r5, {r0 - r3}                   @ save sp_SVC, lr_SVC, pc, cpsr
282         mov     r0, sp                          @ save current stack into r0
283                                                 @ (param register)
284         .endm
285
286         .macro  irq_save_user_regs
287         sub     sp, sp, #S_FRAME_SIZE
288         stmia   sp, {r0 - r12}                  @ Calling r0-r12
289         add     r8, sp, #S_PC                   @ !! R8 NEEDS to be saved !!
290                                                 @ a reserved stack spot would
291                                                 @ be good.
292         stmdb   r8, {sp, lr}^                   @ Calling SP, LR
293         str     lr, [r8, #0]                    @ Save calling PC
294         mrs     r6, spsr
295         str     r6, [r8, #4]                    @ Save CPSR
296         str     r0, [r8, #8]                    @ Save OLD_R0
297         mov     r0, sp
298         .endm
299
300         .macro  irq_restore_user_regs
301         ldmia   sp, {r0 - lr}^                  @ Calling r0 - lr
302         mov     r0, r0
303         ldr     lr, [sp, #S_PC]                 @ Get PC
304         add     sp, sp, #S_FRAME_SIZE
305         subs    pc, lr, #4                      @ return & move spsr_svc into
306                                                 @ cpsr
307         .endm
308
309         .macro get_bad_stack
310         ldr     r13, _armboot_start             @ setup our mode stack (enter
311                                                 @ in banked mode)
312         sub     r13, r13, #(CONFIG_SYS_MALLOC_LEN)      @ move past malloc pool
313         sub     r13, r13, #(CONFIG_SYS_GBL_DATA_SIZE + 8) @ move to reserved a couple
314                                                 @ spots for abort stack
315
316         str     lr, [r13]                       @ save caller lr in position 0
317                                                 @ of saved stack
318         mrs     lr, spsr                        @ get the spsr
319         str     lr, [r13, #4]                   @ save spsr in position 1 of
320                                                 @ saved stack
321
322         mov     r13, #MODE_SVC                  @ prepare SVC-Mode
323         @ msr   spsr_c, r13
324         msr     spsr, r13                       @ switch modes, make sure
325                                                 @ moves will execute
326         mov     lr, pc                          @ capture return pc
327         movs    pc, lr                          @ jump to next instruction &
328                                                 @ switch modes.
329         .endm
330
331         .macro get_bad_stack_swi
332         sub     r13, r13, #4                    @ space on current stack for
333                                                 @ scratch reg.
334         str     r0, [r13]                       @ save R0's value.
335         ldr     r0, _armboot_start              @ get data regions start
336         sub     r0, r0, #(CONFIG_SYS_MALLOC_LEN)        @ move past malloc pool
337         sub     r0, r0, #(CONFIG_SYS_GBL_DATA_SIZE + 8) @ move past gbl and a couple
338                                                 @ spots for abort stack
339         str     lr, [r0]                        @ save caller lr in position 0
340                                                 @ of saved stack
341         mrs     r0, spsr                        @ get the spsr
342         str     lr, [r0, #4]                    @ save spsr in position 1 of
343                                                 @ saved stack
344         ldr     r0, [r13]                       @ restore r0
345         add     r13, r13, #4                    @ pop stack entry
346         .endm
347
348         .macro get_irq_stack                    @ setup IRQ stack
349         ldr     sp, IRQ_STACK_START
350         .endm
351
352         .macro get_fiq_stack                    @ setup FIQ stack
353         ldr     sp, FIQ_STACK_START
354         .endm
355
356 /*
357  * exception handlers
358  */
359         .align  5
360 undefined_instruction:
361         get_bad_stack
362         bad_save_user_regs
363         bl      do_undefined_instruction
364
365         .align  5
366 software_interrupt:
367         get_bad_stack_swi
368         bad_save_user_regs
369         bl      do_software_interrupt
370
371         .align  5
372 prefetch_abort:
373         get_bad_stack
374         bad_save_user_regs
375         bl      do_prefetch_abort
376
377         .align  5
378 data_abort:
379         get_bad_stack
380         bad_save_user_regs
381         bl      do_data_abort
382
383         .align  5
384 not_used:
385         get_bad_stack
386         bad_save_user_regs
387         bl      do_not_used
388
389 #ifdef CONFIG_USE_IRQ
390
391         .align  5
392 irq:
393         get_irq_stack
394         irq_save_user_regs
395         bl      do_irq
396         irq_restore_user_regs
397
398         .align  5
399 fiq:
400         get_fiq_stack
401         /* someone ought to write a more effective fiq_save_user_regs */
402         irq_save_user_regs
403         bl      do_fiq
404         irq_restore_user_regs
405
406 #else
407
408         .align  5
409 irq:
410         get_bad_stack
411         bad_save_user_regs
412         bl      do_irq
413
414         .align  5
415 fiq:
416         get_bad_stack
417         bad_save_user_regs
418         bl      do_fiq
419
420 #endif
421
422 /*
423  *      v7_flush_dcache_all()
424  *
425  *      Flush the whole D-cache.
426  *
427  *      Corrupted registers: r0-r5, r7, r9-r11
428  *
429  *      - mm    - mm_struct describing address space
430  */
431         .align 5
432 .global v7_flush_dcache_all
433 v7_flush_dcache_all:
434         stmfd   r13!, {r0 - r5, r7, r9 - r12, r14}
435
436         mov     r7, r0                          @ take a backup of device type
437         cmp     r0, #0x3                        @ check if the device type is
438                                                 @ GP
439         moveq r12, #0x1                         @ set up to invalide L2
440 smi:    .word 0x01600070                        @ Call SMI monitor (smieq)
441         cmp     r7, #0x3                        @ compare again in case its
442                                                 @ lost
443         beq     finished_inval                  @ if GP device, inval done
444                                                 @ above
445
446         mrc     p15, 1, r0, c0, c0, 1           @ read clidr
447         ands    r3, r0, #0x7000000              @ extract loc from clidr
448         mov     r3, r3, lsr #23                 @ left align loc bit field
449         beq     finished_inval                  @ if loc is 0, then no need to
450                                                 @ clean
451         mov     r10, #0                         @ start clean at cache level 0
452 inval_loop1:
453         add     r2, r10, r10, lsr #1            @ work out 3x current cache
454                                                 @ level
455         mov     r1, r0, lsr r2                  @ extract cache type bits from
456                                                 @ clidr
457         and     r1, r1, #7                      @ mask of the bits for current
458                                                 @ cache only
459         cmp     r1, #2                          @ see what cache we have at
460                                                 @ this level
461         blt     skip_inval                      @ skip if no cache, or just
462                                                 @ i-cache
463         mcr     p15, 2, r10, c0, c0, 0          @ select current cache level
464                                                 @ in cssr
465         mov     r2, #0                          @ operand for mcr SBZ
466         mcr     p15, 0, r2, c7, c5, 4           @ flush prefetch buffer to
467                                                 @ sych the new cssr&csidr,
468                                                 @ with armv7 this is 'isb',
469                                                 @ but we compile with armv5
470         mrc     p15, 1, r1, c0, c0, 0           @ read the new csidr
471         and     r2, r1, #7                      @ extract the length of the
472                                                 @ cache lines
473         add     r2, r2, #4                      @ add 4 (line length offset)
474         ldr     r4, =0x3ff
475         ands    r4, r4, r1, lsr #3              @ find maximum number on the
476                                                 @ way size
477         clz     r5, r4                          @ find bit position of way
478                                                 @ size increment
479         ldr     r7, =0x7fff
480         ands    r7, r7, r1, lsr #13             @ extract max number of the
481                                                 @ index size
482 inval_loop2:
483         mov     r9, r4                          @ create working copy of max
484                                                 @ way size
485 inval_loop3:
486         orr     r11, r10, r9, lsl r5            @ factor way and cache number
487                                                 @ into r11
488         orr     r11, r11, r7, lsl r2            @ factor index number into r11
489         mcr     p15, 0, r11, c7, c6, 2          @ invalidate by set/way
490         subs    r9, r9, #1                      @ decrement the way
491         bge     inval_loop3
492         subs    r7, r7, #1                      @ decrement the index
493         bge     inval_loop2
494 skip_inval:
495         add     r10, r10, #2                    @ increment cache number
496         cmp     r3, r10
497         bgt     inval_loop1
498 finished_inval:
499         mov     r10, #0                         @ swith back to cache level 0
500         mcr     p15, 2, r10, c0, c0, 0          @ select current cache level
501                                                 @ in cssr
502         mcr     p15, 0, r10, c7, c5, 4          @ flush prefetch buffer,
503                                                 @ with armv7 this is 'isb',
504                                                 @ but we compile with armv5
505
506         ldmfd   r13!, {r0 - r5, r7, r9 - r12, pc}