]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/arm/cpu/arm1176/start.S
vf610twr: Remove SoC name from U-Boot prompt
[karo-tx-uboot.git] / arch / arm / cpu / arm1176 / start.S
1 /*
2  *  armboot - Startup Code for ARM1176 CPU-core
3  *
4  * Copyright (c) 2007   Samsung Electronics
5  *
6  * Copyright (C) 2008
7  * Guennadi Liakhovetki, DENX Software Engineering, <lg@denx.de>
8  *
9  * See file CREDITS for list of people who contributed to this
10  * project.
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License as
14  * published by the Free Software Foundation; either version 2 of
15  * the License, or (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
25  * MA 02111-1307 USA
26  *
27  * 2007-09-21 - Restructured codes by jsgood (jsgood.yang@samsung.com)
28  * 2007-09-21 - Added MoviNAND and OneNAND boot codes by
29  * jsgood (jsgood.yang@samsung.com)
30  * Base codes by scsuh (sc.suh)
31  */
32
33 #include <asm-offsets.h>
34 #include <config.h>
35 #include <version.h>
36
37 #ifndef CONFIG_SYS_PHY_UBOOT_BASE
38 #define CONFIG_SYS_PHY_UBOOT_BASE       CONFIG_SYS_UBOOT_BASE
39 #endif
40
41 /*
42  *************************************************************************
43  *
44  * Jump vector table as in table 3.1 in [1]
45  *
46  *************************************************************************
47  */
48
49 .globl _start
50 _start: b       reset
51 #ifndef CONFIG_SPL_BUILD
52         ldr     pc, _undefined_instruction
53         ldr     pc, _software_interrupt
54         ldr     pc, _prefetch_abort
55         ldr     pc, _data_abort
56         ldr     pc, _not_used
57         ldr     pc, _irq
58         ldr     pc, _fiq
59
60 _undefined_instruction:
61         .word undefined_instruction
62 _software_interrupt:
63         .word software_interrupt
64 _prefetch_abort:
65         .word prefetch_abort
66 _data_abort:
67         .word data_abort
68 _not_used:
69         .word not_used
70 _irq:
71         .word irq
72 _fiq:
73         .word fiq
74 _pad:
75         .word 0x12345678 /* now 16*4=64 */
76 #else
77         . = _start + 64
78 #endif
79
80 .global _end_vect
81 _end_vect:
82         .balignl 16,0xdeadbeef
83 /*
84  *************************************************************************
85  *
86  * Startup Code (reset vector)
87  *
88  * do important init only if we don't start from memory!
89  * setup Memory and board specific bits prior to relocation.
90  * relocate armboot to ram
91  * setup stack
92  *
93  *************************************************************************
94  */
95
96 .globl _TEXT_BASE
97 _TEXT_BASE:
98 #if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_TEXT_BASE)
99         .word   CONFIG_SPL_TEXT_BASE
100 #else
101         .word   CONFIG_SYS_TEXT_BASE
102 #endif
103
104 /*
105  * These are defined in the board-specific linker script.
106  * Subtracting _start from them lets the linker put their
107  * relative position in the executable instead of leaving
108  * them null.
109  */
110
111 .globl _bss_start_ofs
112 _bss_start_ofs:
113         .word __bss_start - _start
114
115 .globl _image_copy_end_ofs
116 _image_copy_end_ofs:
117         .word __image_copy_end - _start
118
119 .globl _bss_end_ofs
120 _bss_end_ofs:
121         .word __bss_end - _start
122
123 .globl _end_ofs
124 _end_ofs:
125         .word _end - _start
126
127 /* IRQ stack memory (calculated at run-time) + 8 bytes */
128 .globl IRQ_STACK_START_IN
129 IRQ_STACK_START_IN:
130         .word   0x0badc0de
131
132 /*
133  * the actual reset code
134  */
135
136 reset:
137         /*
138          * set the cpu to SVC32 mode
139          */
140         mrs     r0, cpsr
141         bic     r0, r0, #0x3f
142         orr     r0, r0, #0xd3
143         msr     cpsr, r0
144
145 /*
146  *************************************************************************
147  *
148  * CPU_init_critical registers
149  *
150  * setup important registers
151  * setup memory timing
152  *
153  *************************************************************************
154  */
155         /*
156          * we do sys-critical inits only at reboot,
157          * not when booting from ram!
158          */
159 cpu_init_crit:
160         /*
161          * When booting from NAND - it has definitely been a reset, so, no need
162          * to flush caches and disable the MMU
163          */
164 #ifndef CONFIG_SPL_BUILD
165         /*
166          * flush v4 I/D caches
167          */
168         mov     r0, #0
169         mcr     p15, 0, r0, c7, c7, 0   /* flush v3/v4 cache */
170         mcr     p15, 0, r0, c8, c7, 0   /* flush v4 TLB */
171
172         /*
173          * disable MMU stuff and caches
174          */
175         mrc     p15, 0, r0, c1, c0, 0
176         bic     r0, r0, #0x00002300     @ clear bits 13, 9:8 (--V- --RS)
177         bic     r0, r0, #0x00000087     @ clear bits 7, 2:0 (B--- -CAM)
178         orr     r0, r0, #0x00000002     @ set bit 2 (A) Align
179         orr     r0, r0, #0x00001000     @ set bit 12 (I) I-Cache
180
181         /* Prepare to disable the MMU */
182         adr     r2, mmu_disable_phys
183         sub     r2, r2, #(CONFIG_SYS_PHY_UBOOT_BASE - CONFIG_SYS_TEXT_BASE)
184         b       mmu_disable
185
186         .align 5
187         /* Run in a single cache-line */
188 mmu_disable:
189         mcr     p15, 0, r0, c1, c0, 0
190         nop
191         nop
192         mov     pc, r2
193 mmu_disable_phys:
194
195 #ifdef CONFIG_DISABLE_TCM
196         /*
197          * Disable the TCMs
198          */
199         mrc     p15, 0, r0, c0, c0, 2   /* Return TCM details */
200         cmp     r0, #0
201         beq     skip_tcmdisable
202         mov     r1, #0
203         mov     r2, #1
204         tst     r0, r2
205         mcrne   p15, 0, r1, c9, c1, 1   /* Disable Instruction TCM if present*/
206         tst     r0, r2, LSL #16
207         mcrne   p15, 0, r1, c9, c1, 0   /* Disable Data TCM if present*/
208 skip_tcmdisable:
209 #endif
210 #endif
211
212 #ifdef CONFIG_PERIPORT_REMAP
213         /* Peri port setup */
214         ldr     r0, =CONFIG_PERIPORT_BASE
215         orr     r0, r0, #CONFIG_PERIPORT_SIZE
216         mcr     p15,0,r0,c15,c2,4
217 #endif
218
219         /*
220          * Go setup Memory and board specific bits prior to relocation.
221          */
222         bl      lowlevel_init           /* go setup pll,mux,memory */
223
224         bl      _main
225
226 /*------------------------------------------------------------------------------*/
227
228 /*
229  * void relocate_code(addr_moni)
230  *
231  * This function relocates the monitor code.
232  */
233         .globl  relocate_code
234 relocate_code:
235         mov     r6, r0  /* save addr of destination */
236
237         adr     r0, _start
238         subs    r9, r6, r0              /* r9 <- relocation offset */
239         beq     relocate_done           /* skip relocation */
240         mov     r1, r6                  /* r1 <- scratch for copy_loop */
241         ldr     r3, _image_copy_end_ofs
242         add     r2, r0, r3              /* r2 <- source end address         */
243
244 copy_loop:
245         ldmia   r0!, {r10-r11}          /* copy from source address [r0]    */
246         stmia   r1!, {r10-r11}          /* copy to   target address [r1]    */
247         cmp     r0, r2                  /* until source end address [r2]    */
248         blo     copy_loop
249
250 #ifndef CONFIG_SPL_BUILD
251         /*
252          * fix .rel.dyn relocations
253          */
254         ldr     r0, _TEXT_BASE          /* r0 <- Text base */
255         ldr     r10, _dynsym_start_ofs  /* r10 <- sym table ofs */
256         add     r10, r10, r0            /* r10 <- sym table in FLASH */
257         ldr     r2, _rel_dyn_start_ofs  /* r2 <- rel dyn start ofs */
258         add     r2, r2, r0              /* r2 <- rel dyn start in FLASH */
259         ldr     r3, _rel_dyn_end_ofs    /* r3 <- rel dyn end ofs */
260         add     r3, r3, r0              /* r3 <- rel dyn end in FLASH */
261 fixloop:
262         ldr     r0, [r2]                /* r0 <- location to fix up, IN FLASH! */
263         add     r0, r0, r9              /* r0 <- location to fix up in RAM */
264         ldr     r1, [r2, #4]
265         and     r7, r1, #0xff
266         cmp     r7, #23                 /* relative fixup? */
267         beq     fixrel
268         cmp     r7, #2                  /* absolute fixup? */
269         beq     fixabs
270         /* ignore unknown type of fixup */
271         b       fixnext
272 fixabs:
273         /* absolute fix: set location to (offset) symbol value */
274         mov     r1, r1, LSR #4          /* r1 <- symbol index in .dynsym */
275         add     r1, r10, r1             /* r1 <- address of symbol in table */
276         ldr     r1, [r1, #4]            /* r1 <- symbol value */
277         add     r1, r1, r9              /* r1 <- relocated sym addr */
278         b       fixnext
279 fixrel:
280         /* relative fix: increase location by offset */
281         ldr     r1, [r0]
282         add     r1, r1, r9
283 fixnext:
284         str     r1, [r0]
285         add     r2, r2, #8              /* each rel.dyn entry is 8 bytes */
286         cmp     r2, r3
287         blo     fixloop
288 #endif
289
290 relocate_done:
291
292         bx      lr
293
294 _rel_dyn_start_ofs:
295         .word __rel_dyn_start - _start
296 _rel_dyn_end_ofs:
297         .word __rel_dyn_end - _start
298 _dynsym_start_ofs:
299         .word __dynsym_start - _start
300
301         .globl  c_runtime_cpu_setup
302 c_runtime_cpu_setup:
303
304         mov     pc, lr
305
306 #ifndef CONFIG_SPL_BUILD
307 /*
308  *************************************************************************
309  *
310  * Interrupt handling
311  *
312  *************************************************************************
313  */
314 @
315 @ IRQ stack frame.
316 @
317 #define S_FRAME_SIZE    72
318
319 #define S_OLD_R0        68
320 #define S_PSR           64
321 #define S_PC            60
322 #define S_LR            56
323 #define S_SP            52
324
325 #define S_IP            48
326 #define S_FP            44
327 #define S_R10           40
328 #define S_R9            36
329 #define S_R8            32
330 #define S_R7            28
331 #define S_R6            24
332 #define S_R5            20
333 #define S_R4            16
334 #define S_R3            12
335 #define S_R2            8
336 #define S_R1            4
337 #define S_R0            0
338
339 #define MODE_SVC 0x13
340 #define I_BIT    0x80
341
342 /*
343  * use bad_save_user_regs for abort/prefetch/undef/swi ...
344  */
345
346         .macro  bad_save_user_regs
347         /* carve out a frame on current user stack */
348         sub     sp, sp, #S_FRAME_SIZE
349         /* Save user registers (now in svc mode) r0-r12 */
350         stmia   sp, {r0 - r12}
351
352         ldr     r2, IRQ_STACK_START_IN
353         /* get values for "aborted" pc and cpsr (into parm regs) */
354         ldmia   r2, {r2 - r3}
355         /* grab pointer to old stack */
356         add     r0, sp, #S_FRAME_SIZE
357
358         add     r5, sp, #S_SP
359         mov     r1, lr
360         /* save sp_SVC, lr_SVC, pc, cpsr */
361         stmia   r5, {r0 - r3}
362         /* save current stack into r0 (param register) */
363         mov     r0, sp
364         .endm
365
366         .macro get_bad_stack
367         ldr     r13, IRQ_STACK_START_IN         @ setup our mode stack
368
369         /* save caller lr in position 0 of saved stack */
370         str     lr, [r13]
371         /* get the spsr */
372         mrs     lr, spsr
373         /* save spsr in position 1 of saved stack */
374         str     lr, [r13, #4]
375
376         /* prepare SVC-Mode */
377         mov     r13, #MODE_SVC
378         @ msr   spsr_c, r13
379         /* switch modes, make sure moves will execute */
380         msr     spsr, r13
381         /* capture return pc */
382         mov     lr, pc
383         /* jump to next instruction & switch modes. */
384         movs    pc, lr
385         .endm
386
387         .macro get_bad_stack_swi
388         /* space on current stack for scratch reg. */
389         sub     r13, r13, #4
390         /* save R0's value. */
391         str     r0, [r13]
392         ldr     r13, IRQ_STACK_START_IN         @ setup our mode stack
393         /* save caller lr in position 0 of saved stack */
394         str     lr, [r0]
395         /* get the spsr */
396         mrs     lr, spsr
397         /* save spsr in position 1 of saved stack */
398         str     lr, [r0, #4]
399         /* restore lr */
400         ldr     lr, [r0]
401         /* restore r0 */
402         ldr     r0, [r13]
403         /* pop stack entry */
404         add     r13, r13, #4
405         .endm
406
407 /*
408  * exception handlers
409  */
410         .align  5
411 undefined_instruction:
412         get_bad_stack
413         bad_save_user_regs
414         bl      do_undefined_instruction
415
416         .align  5
417 software_interrupt:
418         get_bad_stack_swi
419         bad_save_user_regs
420         bl      do_software_interrupt
421
422         .align  5
423 prefetch_abort:
424         get_bad_stack
425         bad_save_user_regs
426         bl      do_prefetch_abort
427
428         .align  5
429 data_abort:
430         get_bad_stack
431         bad_save_user_regs
432         bl      do_data_abort
433
434         .align  5
435 not_used:
436         get_bad_stack
437         bad_save_user_regs
438         bl      do_not_used
439
440         .align  5
441 irq:
442         get_bad_stack
443         bad_save_user_regs
444         bl      do_irq
445
446         .align  5
447 fiq:
448         get_bad_stack
449         bad_save_user_regs
450         bl      do_fiq
451 #endif /* CONFIG_SPL_BUILD */