]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - cpu/arm920t/start.S
Initial revision
[karo-tx-uboot.git] / cpu / arm920t / start.S
1 /*
2  *  armboot - Startup Code for ARM920 CPU-core
3  *
4  *  Copyright (c) 2001  Marius Gröger <mag@sysgo.de>
5  *  Copyright (c) 2002  Alex Züpke <azu@sysgo.de>
6  *  Copyright (c) 2002  Gary Jennejohn <gj@denx.de>
7  *
8  * See file CREDITS for list of people who contributed to this
9  * project.
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License as
13  * published by the Free Software Foundation; either version 2 of
14  * the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
24  * MA 02111-1307 USA
25  */
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 /*
77  * CFG_MEM_END is in the board dependent config-file (configs/config_BOARD.h)
78  */
79 _TEXT_BASE:
80         .word   TEXT_BASE
81
82 .globl _armboot_start
83 _armboot_start:
84         .word _start
85
86 /*
87  * Note: _armboot_end_data and _armboot_end are defined
88  * by the (board-dependent) linker script.
89  * _armboot_end_data is the first usable FLASH address after armboot
90  */
91 .globl _armboot_end_data
92 _armboot_end_data:
93         .word armboot_end_data
94 .globl _armboot_end
95 _armboot_end:
96         .word armboot_end
97
98 /*
99  * _armboot_real_end is the first usable RAM address behind armboot
100  * and the various stacks
101  */
102 .globl _armboot_real_end
103 _armboot_real_end:
104         .word 0x0badc0de
105
106 #ifdef CONFIG_USE_IRQ
107 /* IRQ stack memory (calculated at run-time) */
108 .globl IRQ_STACK_START
109 IRQ_STACK_START:
110         .word   0x0badc0de
111
112 /* IRQ stack memory (calculated at run-time) */
113 .globl FIQ_STACK_START
114 FIQ_STACK_START:
115         .word 0x0badc0de
116 #endif
117
118
119 /*
120  * the actual reset code
121  */
122
123 reset:
124         /*
125          * set the cpu to SVC32 mode
126          */
127         mrs     r0,cpsr
128         bic     r0,r0,#0x1f
129         orr     r0,r0,#0xd3
130         msr     cpsr,r0
131
132 /* turn off the watchdog */
133 #if defined(CONFIG_S3C2400)
134 #define pWTCON          0x15300000
135 /* Interupt-Controller base addresses */
136 #define INTMSK          0x14400008
137 /* clock divisor register */
138 #define CLKDIVN         0x14800014
139 #elif defined(CONFIG_S3C2410)
140 #define pWTCON          0x53000000
141 /* Interupt-Controller base addresses */
142 #define INTMSK          0x4A000008
143 #define INTSUBMSK       0x4A00001C
144 /* clock divisor register */
145 #define CLKDIVN         0x4C000014
146 #endif
147
148         ldr     r0, =pWTCON
149         mov     r1, #0x0
150         str     r1, [r0]
151
152         /*
153          * mask all IRQs by setting all bits in the INTMR - default
154          */
155         mov     r1, #0xffffffff
156         ldr     r0, =INTMSK
157         str     r1, [r0]
158 #if defined(CONFIG_S3C2410)
159         ldr     r1, =0x3ff
160         ldr     r0, =INTSUBMSK
161         str     r1, [r0]
162 #endif
163
164         /* FCLK:HCLK:PCLK = 1:2:4 */
165         /* default FCLK is 120 MHz ! */
166         ldr     r0, =CLKDIVN
167         mov     r1, #3
168         str     r1, [r0]
169
170         /*
171          * we do sys-critical inits only at reboot,
172          * not when booting from ram!
173          */
174 #ifdef CONFIG_INIT_CRITICAL
175         bl      cpu_init_crit
176 #endif
177
178 relocate:
179         /*
180          * relocate armboot to RAM
181          */
182         adr     r0, _start              /* r0 <- current position of code */
183         ldr     r2, _armboot_start
184         ldr     r3, _armboot_end
185         sub     r2, r3, r2              /* r2 <- size of armboot */
186         ldr     r1, _TEXT_BASE          /* r1 <- destination address */
187         add     r2, r0, r2              /* r2 <- source end address */
188
189         /*
190          * r0 = source address
191          * r1 = target address
192          * r2 = source end address
193          */
194 copy_loop:
195         ldmia   r0!, {r3-r10}
196         stmia   r1!, {r3-r10}
197         cmp     r0, r2
198         ble     copy_loop
199
200 #if 0
201         /* try doing this stuff after the relocation */
202         ldr     r0, =pWTCON
203         mov     r1, #0x0
204         str     r1, [r0]
205
206         /*
207          * mask all IRQs by setting all bits in the INTMR - default
208          */
209         mov     r1, #0xffffffff
210         ldr     r0, =INTMR
211         str     r1, [r0]
212
213         /* FCLK:HCLK:PCLK = 1:2:4 */
214         /* default FCLK is 120 MHz ! */
215         ldr     r0, =CLKDIVN
216         mov     r1, #3
217         str     r1, [r0]
218         /* END stuff after relocation */
219 #endif
220
221         /* set up the stack */
222         ldr     r0, _armboot_end
223         add     r0, r0, #CONFIG_STACKSIZE
224         sub     sp, r0, #12             /* leave 3 words for abort-stack */
225
226         ldr     pc, _start_armboot
227
228 _start_armboot: .word start_armboot
229
230
231 /*
232  *************************************************************************
233  *
234  * CPU_init_critical registers
235  *
236  * setup important registers
237  * setup memory timing
238  *
239  *************************************************************************
240  */
241
242
243 cpu_init_crit:
244         /*
245          * flush v4 I/D caches
246          */
247         mov     r0, #0
248         mcr     p15, 0, r0, c7, c7, 0   /* flush v3/v4 cache */
249         mcr     p15, 0, r0, c8, c7, 0   /* flush v4 TLB */
250
251         /*
252          * disable MMU stuff and caches
253          */
254         mrc     p15, 0, r0, c1, c0, 0
255         bic     r0, r0, #0x00002300     @ clear bits 13, 9:8 (--V- --RS)
256         bic     r0, r0, #0x00000087     @ clear bits 7, 2:0 (B--- -CAM)
257         orr     r0, r0, #0x00000002     @ set bit 2 (A) Align
258         orr     r0, r0, #0x00001000     @ set bit 12 (I) I-Cache
259         mcr     p15, 0, r0, c1, c0, 0
260
261
262         /*
263          * before relocating, we have to setup RAM timing
264          * because memory timing is board-dependend, you will
265          * find a memsetup.S in your board directory.
266          */
267         mov     ip, lr
268         bl      memsetup
269         mov     lr, ip
270
271         mov     pc, lr
272
273
274
275
276 /*
277  *************************************************************************
278  *
279  * Interrupt handling
280  *
281  *************************************************************************
282  */
283
284 @
285 @ IRQ stack frame.
286 @
287 #define S_FRAME_SIZE    72
288
289 #define S_OLD_R0        68
290 #define S_PSR           64
291 #define S_PC            60
292 #define S_LR            56
293 #define S_SP            52
294
295 #define S_IP            48
296 #define S_FP            44
297 #define S_R10           40
298 #define S_R9            36
299 #define S_R8            32
300 #define S_R7            28
301 #define S_R6            24
302 #define S_R5            20
303 #define S_R4            16
304 #define S_R3            12
305 #define S_R2            8
306 #define S_R1            4
307 #define S_R0            0
308
309 #define MODE_SVC 0x13
310 #define I_BIT    0x80
311
312 /*
313  * use bad_save_user_regs for abort/prefetch/undef/swi ...
314  * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
315  */
316
317         .macro  bad_save_user_regs
318         sub     sp, sp, #S_FRAME_SIZE
319         stmia   sp, {r0 - r12}                  @ Calling r0-r12
320         add     r8, sp, #S_PC
321
322         ldr     r2, _armboot_end
323         add     r2, r2, #CONFIG_STACKSIZE
324         sub     r2, r2, #8
325         ldmia   r2, {r2 - r4}                   @ get pc, cpsr, old_r0
326         add     r0, sp, #S_FRAME_SIZE           @ restore sp_SVC
327
328         add     r5, sp, #S_SP
329         mov     r1, lr
330         stmia   r5, {r0 - r4}                   @ save sp_SVC, lr_SVC, pc, cpsr, old_r
331         mov     r0, sp
332         .endm
333
334         .macro  irq_save_user_regs
335         sub     sp, sp, #S_FRAME_SIZE
336         stmia   sp, {r0 - r12}                  @ Calling r0-r12
337         add     r8, sp, #S_PC
338         stmdb   r8, {sp, lr}^                   @ Calling SP, LR
339         str     lr, [r8, #0]                    @ Save calling PC
340         mrs     r6, spsr
341         str     r6, [r8, #4]                    @ Save CPSR
342         str     r0, [r8, #8]                    @ Save OLD_R0
343         mov     r0, sp
344         .endm
345
346         .macro  irq_restore_user_regs
347         ldmia   sp, {r0 - lr}^                  @ Calling r0 - lr
348         mov     r0, r0
349         ldr     lr, [sp, #S_PC]                 @ Get PC
350         add     sp, sp, #S_FRAME_SIZE
351         subs    pc, lr, #4                      @ return & move spsr_svc into cpsr
352         .endm
353
354         .macro get_bad_stack
355         ldr     r13, _armboot_end               @ setup our mode stack
356         add     r13, r13, #CONFIG_STACKSIZE     @ resides at top of normal stack
357         sub     r13, r13, #8
358
359         str     lr, [r13]                       @ save caller lr / spsr
360         mrs     lr, spsr
361         str     lr, [r13, #4]
362
363         mov     r13, #MODE_SVC                  @ prepare SVC-Mode
364         @ msr   spsr_c, r13
365         msr     spsr, r13
366         mov     lr, pc
367         movs    pc, lr
368         .endm
369
370         .macro get_irq_stack                    @ setup IRQ stack
371         ldr     sp, IRQ_STACK_START
372         .endm
373
374         .macro get_fiq_stack                    @ setup FIQ stack
375         ldr     sp, FIQ_STACK_START
376         .endm
377
378 /*
379  * exception handlers
380  */
381         .align  5
382 undefined_instruction:
383         get_bad_stack
384         bad_save_user_regs
385         bl      do_undefined_instruction
386
387         .align  5
388 software_interrupt:
389         get_bad_stack
390         bad_save_user_regs
391         bl      do_software_interrupt
392
393         .align  5
394 prefetch_abort:
395         get_bad_stack
396         bad_save_user_regs
397         bl      do_prefetch_abort
398
399         .align  5
400 data_abort:
401         get_bad_stack
402         bad_save_user_regs
403         bl      do_data_abort
404
405         .align  5
406 not_used:
407         get_bad_stack
408         bad_save_user_regs
409         bl      do_not_used
410
411 #ifdef CONFIG_USE_IRQ
412
413         .align  5
414 irq:
415         get_irq_stack
416         irq_save_user_regs
417         bl      do_irq
418         irq_restore_user_regs
419
420         .align  5
421 fiq:
422         get_fiq_stack
423         /* someone ought to write a more effiction fiq_save_user_regs */
424         irq_save_user_regs
425         bl      do_fiq
426         irq_restore_user_regs
427
428 #else
429
430         .align  5
431 irq:
432         get_bad_stack
433         bad_save_user_regs
434         bl      do_irq
435
436         .align  5
437 fiq:
438         get_bad_stack
439         bad_save_user_regs
440         bl      do_fiq
441
442 #endif
443
444         .align  5
445 .globl reset_cpu
446 reset_cpu:
447 #ifdef CONFIG_S3C2400
448         bl      disable_interrupts
449         ldr     r1, _rWTCON
450         ldr     r2, _rWTCNT
451         /* Disable watchdog */
452         mov     r3, #0x0000
453         str     r3, [r1]
454         /* Initialize watchdog timer count register */
455         mov     r3, #0x0001
456         str     r3, [r2]
457         /* Enable watchdog timer; assert reset at timer timeout */
458         mov     r3, #0x0021
459         str     r3, [r1]
460 _loop_forever:
461         b       _loop_forever
462 _rWTCON:
463         .word   0x15300000
464 _rWTCNT:
465         .word   0x15300008
466 #else /* ! CONFIG_S3C2400 */
467         mov     ip, #0
468         mcr     p15, 0, ip, c7, c7, 0           @ invalidate cache
469         mcr     p15, 0, ip, c8, c7, 0           @ flush TLB (v4)
470         mrc     p15, 0, ip, c1, c0, 0           @ get ctrl register
471         bic     ip, ip, #0x000f                 @ ............wcam
472         bic     ip, ip, #0x2100                 @ ..v....s........
473         mcr     p15, 0, ip, c1, c0, 0           @ ctrl register
474         mov     pc, r0
475 #endif /* CONFIG_S3C2400 */