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