]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/arm/cpu/sa1100/start.S
arm: bugfix: replace ble with blo in start.S files
[karo-tx-uboot.git] / arch / arm / cpu / sa1100 / start.S
1 /*
2  *  armboot - Startup Code for SA1100 CPU
3  *
4  *  Copyright (C) 1998  Dan Malek <dmalek@jlc.net>
5  *  Copyright (C) 1999  Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
6  *  Copyright (C) 2000  Wolfgang Denk <wd@denx.de>
7  *  Copyright (c) 2001  Alex Züpke <azu@sysgo.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
28
29 #include <config.h>
30 #include <version.h>
31
32
33 /*
34  *************************************************************************
35  *
36  * Jump vector table as in table 3.1 in [1]
37  *
38  *************************************************************************
39  */
40
41
42 .globl _start
43 _start: b       reset
44         ldr     pc, _undefined_instruction
45         ldr     pc, _software_interrupt
46         ldr     pc, _prefetch_abort
47         ldr     pc, _data_abort
48         ldr     pc, _not_used
49         ldr     pc, _irq
50         ldr     pc, _fiq
51
52 _undefined_instruction: .word undefined_instruction
53 _software_interrupt:    .word software_interrupt
54 _prefetch_abort:        .word prefetch_abort
55 _data_abort:            .word data_abort
56 _not_used:              .word not_used
57 _irq:                   .word irq
58 _fiq:                   .word fiq
59
60         .balignl 16,0xdeadbeef
61
62
63 /*
64  *************************************************************************
65  *
66  * Startup Code (reset vector)
67  *
68  * do important init only if we don't start from memory!
69  * relocate armboot to ram
70  * setup stack
71  * jump to second stage
72  *
73  *************************************************************************
74  */
75
76 .globl _TEXT_BASE
77 _TEXT_BASE:
78         .word   TEXT_BASE
79
80 #if defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
81 .globl _armboot_start
82 _armboot_start:
83         .word _start
84 #endif
85
86 /*
87  * These are defined in the board-specific linker script.
88  */
89 .globl _bss_start
90 _bss_start:
91         .word __bss_start
92
93 .globl _bss_end
94 _bss_end:
95         .word _end
96
97 #ifdef CONFIG_USE_IRQ
98 /* IRQ stack memory (calculated at run-time) */
99 .globl IRQ_STACK_START
100 IRQ_STACK_START:
101         .word   0x0badc0de
102
103 /* IRQ stack memory (calculated at run-time) */
104 .globl FIQ_STACK_START
105 FIQ_STACK_START:
106         .word 0x0badc0de
107 #endif
108
109 #if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
110 /* IRQ stack memory (calculated at run-time) + 8 bytes */
111 .globl IRQ_STACK_START_IN
112 IRQ_STACK_START_IN:
113         .word   0x0badc0de
114
115 .globl _datarel_start
116 _datarel_start:
117         .word __datarel_start
118
119 .globl _datarelrolocal_start
120 _datarelrolocal_start:
121         .word __datarelrolocal_start
122
123 .globl _datarellocal_start
124 _datarellocal_start:
125         .word __datarellocal_start
126
127 .globl _datarelro_start
128 _datarelro_start:
129         .word __datarelro_start
130
131 .globl _got_start
132 _got_start:
133         .word __got_start
134
135 .globl _got_end
136 _got_end:
137         .word __got_end
138
139 /*
140  * the actual reset code
141  */
142
143 reset:
144         /*
145          * set the cpu to SVC32 mode
146          */
147         mrs     r0,cpsr
148         bic     r0,r0,#0x1f
149         orr     r0,r0,#0xd3
150         msr     cpsr,r0
151
152         /*
153          * we do sys-critical inits only at reboot,
154          * not when booting from ram!
155          */
156 #ifndef CONFIG_SKIP_LOWLEVEL_INIT
157         bl      cpu_init_crit
158 #endif
159
160 /* Set stackpointer in internal RAM to call board_init_f */
161 call_board_init_f:
162         ldr     sp, =(CONFIG_SYS_INIT_SP_ADDR)
163         ldr     r0,=0x00000000
164         bl      board_init_f
165
166 /*------------------------------------------------------------------------------*/
167
168 /*
169  * void relocate_code (addr_sp, gd, addr_moni)
170  *
171  * This "function" does not return, instead it continues in RAM
172  * after relocating the monitor code.
173  *
174  */
175         .globl  relocate_code
176 relocate_code:
177         mov     r4, r0  /* save addr_sp */
178         mov     r5, r1  /* save addr of gd */
179         mov     r6, r2  /* save addr of destination */
180         mov     r7, r2  /* save addr of destination */
181
182         /* Set up the stack                                                 */
183 stack_setup:
184         mov     sp, r4
185
186         adr     r0, _start
187         ldr     r2, _TEXT_BASE
188         ldr     r3, _bss_start
189         sub     r2, r3, r2              /* r2 <- size of armboot            */
190         add     r2, r0, r2              /* r2 <- source end address         */
191         cmp     r0, r6
192         beq     clear_bss
193
194 #ifndef CONFIG_SKIP_RELOCATE_UBOOT
195 copy_loop:
196         ldmia   r0!, {r9-r10}           /* copy from source address [r0]    */
197         stmia   r6!, {r9-r10}           /* copy to   target address [r1]    */
198         cmp     r0, r2                  /* until source end address [r2]    */
199         blo     copy_loop
200
201 #ifndef CONFIG_PRELOADER
202         /* fix got entries */
203         ldr     r1, _TEXT_BASE          /* Text base */
204         mov     r0, r7                  /* reloc addr */
205         ldr     r2, _got_start          /* addr in Flash */
206         ldr     r3, _got_end            /* addr in Flash */
207         sub     r3, r3, r1
208         add     r3, r3, r0
209         sub     r2, r2, r1
210         add     r2, r2, r0
211
212 fixloop:
213         ldr     r4, [r2]
214         sub     r4, r4, r1
215         add     r4, r4, r0
216         str     r4, [r2]
217         add     r2, r2, #4
218         cmp     r2, r3
219         bne     fixloop
220 #endif
221 #endif  /* #ifndef CONFIG_SKIP_RELOCATE_UBOOT */
222
223 clear_bss:
224 #ifndef CONFIG_PRELOADER
225         ldr     r0, _bss_start
226         ldr     r1, _bss_end
227         ldr     r3, _TEXT_BASE          /* Text base */
228         mov     r4, r7                  /* reloc addr */
229         sub     r0, r0, r3
230         add     r0, r0, r4
231         sub     r1, r1, r3
232         add     r1, r1, r4
233         mov     r2, #0x00000000         /* clear                            */
234
235 clbss_l:str     r2, [r0]                /* clear loop...                    */
236         add     r0, r0, #4
237         cmp     r0, r1
238         bne     clbss_l
239 #endif
240
241 /*
242  * We are done. Do not return, instead branch to second part of board
243  * initialization, now running from RAM.
244  */
245         ldr     r0, _TEXT_BASE
246         ldr     r2, _board_init_r
247         sub     r2, r2, r0
248         add     r2, r2, r7      /* position from board_init_r in RAM */
249         /* setup parameters for board_init_r */
250         mov     r0, r5          /* gd_t */
251         mov     r1, r7          /* dest_addr */
252         /* jump to it ... */
253         mov     lr, r2
254         mov     pc, lr
255
256 _board_init_r: .word board_init_r
257
258 #else /* #if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC) */
259
260 /*
261  * the actual reset code
262  */
263
264 reset:
265         /*
266          * set the cpu to SVC32 mode
267          */
268         mrs     r0,cpsr
269         bic     r0,r0,#0x1f
270         orr     r0,r0,#0x13
271         msr     cpsr,r0
272
273         /*
274          * we do sys-critical inits only at reboot,
275          * not when booting from ram!
276          */
277 #ifndef CONFIG_SKIP_LOWLEVEL_INIT
278         bl      cpu_init_crit
279 #endif
280
281 #ifndef CONFIG_SKIP_RELOCATE_UBOOT
282 relocate:                               /* relocate U-Boot to RAM           */
283         adr     r0, _start              /* r0 <- current position of code   */
284         ldr     r1, _TEXT_BASE          /* test if we run from flash or RAM */
285         cmp     r0, r1                  /* don't reloc during debug         */
286         beq     stack_setup
287
288         ldr     r2, _armboot_start
289         ldr     r3, _bss_start
290         sub     r2, r3, r2              /* r2 <- size of armboot            */
291         add     r2, r0, r2              /* r2 <- source end address         */
292
293 copy_loop:
294         ldmia   r0!, {r3-r10}           /* copy from source address [r0]    */
295         stmia   r1!, {r3-r10}           /* copy to   target address [r1]    */
296         cmp     r0, r2                  /* until source end address [r2]    */
297         blo     copy_loop
298 #endif  /* CONFIG_SKIP_RELOCATE_UBOOT */
299
300         /* Set up the stack                                                 */
301 stack_setup:
302         ldr     r0, _TEXT_BASE          /* upper 128 KiB: relocated uboot   */
303         sub     r0, r0, #CONFIG_SYS_MALLOC_LEN  /* malloc area                      */
304         sub     r0, r0, #CONFIG_SYS_GBL_DATA_SIZE /* bdinfo                        */
305 #ifdef CONFIG_USE_IRQ
306         sub     r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
307 #endif
308         sub     sp, r0, #12             /* leave 3 words for abort-stack    */
309         bic     sp, sp, #7              /* 8-byte alignment for ABI compliance */
310
311 clear_bss:
312         ldr     r0, _bss_start          /* find start of bss segment        */
313         ldr     r1, _bss_end            /* stop here                        */
314         mov     r2, #0x00000000         /* clear                            */
315
316 clbss_l:str     r2, [r0]                /* clear loop...                    */
317         add     r0, r0, #4
318         cmp     r0, r1
319         blo     clbss_l
320
321         ldr     pc, _start_armboot
322
323 _start_armboot: .word start_armboot
324
325 #endif /* #if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC) */
326
327 /*
328  *************************************************************************
329  *
330  * CPU_init_critical registers
331  *
332  * setup important registers
333  * setup memory timing
334  *
335  *************************************************************************
336  */
337
338
339 /* Interupt-Controller base address */
340 IC_BASE:        .word   0x90050000
341 #define ICMR    0x04
342
343
344 /* Reset-Controller */
345 RST_BASE:               .word   0x90030000
346 #define RSRR    0x00
347 #define RCSR    0x04
348
349
350 /* PWR */
351 PWR_BASE:               .word   0x90020000
352 #define PSPR    0x08
353 #define PPCR    0x14
354 cpuspeed:               .word   CONFIG_SYS_CPUSPEED
355
356
357 cpu_init_crit:
358         /*
359          * mask all IRQs
360          */
361         ldr     r0, IC_BASE
362         mov     r1, #0x00
363         str     r1, [r0, #ICMR]
364
365         /* set clock speed */
366         ldr     r0, PWR_BASE
367         ldr     r1, cpuspeed
368         str     r1, [r0, #PPCR]
369
370         /*
371          * before relocating, we have to setup RAM timing
372          * because memory timing is board-dependend, you will
373          * find a lowlevel_init.S in your board directory.
374          */
375         mov     ip,     lr
376         bl      lowlevel_init
377         mov     lr,     ip
378
379         /*
380          * disable MMU stuff and enable I-cache
381          */
382         mrc     p15,0,r0,c1,c0
383         bic     r0, r0, #0x00002000     @ clear bit 13 (X)
384         bic     r0, r0, #0x0000000f     @ clear bits 3-0 (WCAM)
385         orr     r0, r0, #0x00001000     @ set bit 12 (I) Icache
386         orr     r0, r0, #0x00000002     @ set bit 2 (A) Align
387         mcr     p15,0,r0,c1,c0
388
389         /*
390          * flush v4 I/D caches
391          */
392         mov     r0, #0
393         mcr     p15, 0, r0, c7, c7, 0   /* flush v3/v4 cache */
394         mcr     p15, 0, r0, c8, c7, 0   /* flush v4 TLB */
395
396         mov     pc, lr
397
398
399 /*
400  *************************************************************************
401  *
402  * Interrupt handling
403  *
404  *************************************************************************
405  */
406
407 @
408 @ IRQ stack frame.
409 @
410 #define S_FRAME_SIZE    72
411
412 #define S_OLD_R0        68
413 #define S_PSR           64
414 #define S_PC            60
415 #define S_LR            56
416 #define S_SP            52
417
418 #define S_IP            48
419 #define S_FP            44
420 #define S_R10           40
421 #define S_R9            36
422 #define S_R8            32
423 #define S_R7            28
424 #define S_R6            24
425 #define S_R5            20
426 #define S_R4            16
427 #define S_R3            12
428 #define S_R2            8
429 #define S_R1            4
430 #define S_R0            0
431
432 #define MODE_SVC 0x13
433 #define I_BIT    0x80
434
435 /*
436  * use bad_save_user_regs for abort/prefetch/undef/swi ...
437  * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
438  */
439
440         .macro  bad_save_user_regs
441         sub     sp, sp, #S_FRAME_SIZE
442         stmia   sp, {r0 - r12}                  @ Calling r0-r12
443         add     r8, sp, #S_PC
444
445 #if defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
446         ldr     r2, _armboot_start
447         sub     r2, r2, #(CONFIG_STACKSIZE+CONFIG_SYS_MALLOC_LEN)
448         sub     r2, r2, #(CONFIG_SYS_GBL_DATA_SIZE+8)  @ set base 2 words into abort stack
449 #else
450         ldr     r2, IRQ_STACK_START_IN
451 #endif
452         ldmia   r2, {r2 - r4}                   @ get pc, cpsr, old_r0
453         add     r0, sp, #S_FRAME_SIZE           @ restore sp_SVC
454
455         add     r5, sp, #S_SP
456         mov     r1, lr
457         stmia   r5, {r0 - r4}                   @ save sp_SVC, lr_SVC, pc, cpsr, old_r
458         mov     r0, sp
459         .endm
460
461         .macro  irq_save_user_regs
462         sub     sp, sp, #S_FRAME_SIZE
463         stmia   sp, {r0 - r12}                  @ Calling r0-r12
464         add     r8, sp, #S_PC
465         stmdb   r8, {sp, lr}^                   @ Calling SP, LR
466         str     lr, [r8, #0]                    @ Save calling PC
467         mrs     r6, spsr
468         str     r6, [r8, #4]                    @ Save CPSR
469         str     r0, [r8, #8]                    @ Save OLD_R0
470         mov     r0, sp
471         .endm
472
473         .macro  irq_restore_user_regs
474         ldmia   sp, {r0 - lr}^                  @ Calling r0 - lr
475         mov     r0, r0
476         ldr     lr, [sp, #S_PC]                 @ Get PC
477         add     sp, sp, #S_FRAME_SIZE
478         subs    pc, lr, #4                      @ return & move spsr_svc into cpsr
479         .endm
480
481         .macro get_bad_stack
482 #if defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
483         ldr     r13, _armboot_start             @ setup our mode stack
484         sub     r13, r13, #(CONFIG_STACKSIZE+CONFIG_SYS_MALLOC_LEN)
485         sub     r13, r13, #(CONFIG_SYS_GBL_DATA_SIZE+8) @ reserved a couple spots in abort stack
486 #else
487         ldr     r13, IRQ_STACK_START_IN         @ setup our mode stack
488 #endif
489
490         str     lr, [r13]                       @ save caller lr / spsr
491         mrs     lr, spsr
492         str     lr, [r13, #4]
493
494         mov     r13, #MODE_SVC                  @ prepare SVC-Mode
495         msr     spsr_c, r13
496         mov     lr, pc
497         movs    pc, lr
498         .endm
499
500         .macro get_irq_stack                    @ setup IRQ stack
501         ldr     sp, IRQ_STACK_START
502         .endm
503
504         .macro get_fiq_stack                    @ setup FIQ stack
505         ldr     sp, FIQ_STACK_START
506         .endm
507
508 /*
509  * exception handlers
510  */
511         .align  5
512 undefined_instruction:
513         get_bad_stack
514         bad_save_user_regs
515         bl      do_undefined_instruction
516
517         .align  5
518 software_interrupt:
519         get_bad_stack
520         bad_save_user_regs
521         bl      do_software_interrupt
522
523         .align  5
524 prefetch_abort:
525         get_bad_stack
526         bad_save_user_regs
527         bl      do_prefetch_abort
528
529         .align  5
530 data_abort:
531         get_bad_stack
532         bad_save_user_regs
533         bl      do_data_abort
534
535         .align  5
536 not_used:
537         get_bad_stack
538         bad_save_user_regs
539         bl      do_not_used
540
541 #ifdef CONFIG_USE_IRQ
542
543         .align  5
544 irq:
545         get_irq_stack
546         irq_save_user_regs
547         bl      do_irq
548         irq_restore_user_regs
549
550         .align  5
551 fiq:
552         get_fiq_stack
553         /* someone ought to write a more effiction fiq_save_user_regs */
554         irq_save_user_regs
555         bl      do_fiq
556         irq_restore_user_regs
557
558 #else
559
560         .align  5
561 irq:
562         get_bad_stack
563         bad_save_user_regs
564         bl      do_irq
565
566         .align  5
567 fiq:
568         get_bad_stack
569         bad_save_user_regs
570         bl      do_fiq
571
572 #endif
573
574         .align  5
575 .globl reset_cpu
576 reset_cpu:
577         ldr     r0, RST_BASE
578         mov     r1, #0x0                        @ set bit 3-0 ...
579         str     r1, [r0, #RCSR]                 @ ... to clear in RCSR
580         mov     r1, #0x1
581         str     r1, [r0, #RSRR]                 @ and perform reset
582         b       reset_cpu                       @ silly, but repeat endlessly