]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - cpu/arm720t/start.S
f6ae9d67a4a576e8ca65f682b8dc542aaf74e053
[karo-tx-uboot.git] / cpu / arm720t / start.S
1 /*
2  *  armboot - Startup Code for ARM720 CPU-core
3  *
4  *  Copyright (c) 2001  Marius Gröger <mag@sysgo.de>
5  *  Copyright (c) 2002  Alex Züpke <azu@sysgo.de>
6  *
7  * See file CREDITS for list of people who contributed to this
8  * project.
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License as
12  * published by the Free Software Foundation; either version 2 of
13  * the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
23  * MA 02111-1307 USA
24  */
25
26
27 #include <config.h>
28 #include <version.h>
29 #ifdef CONFIG_NETARM
30 #include <asm/arch/netarm_registers.h>
31 #endif
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 RAM!
69  * relocate armboot to ram
70  * setup stack
71  * jump to second stage
72  *
73  *************************************************************************
74  */
75
76 _TEXT_BASE:
77         .word   TEXT_BASE
78
79 .globl _armboot_start
80 _armboot_start:
81         .word _start
82
83 /*
84  * These are defined in the board-specific linker script.
85  */
86 .globl _bss_start
87 _bss_start:
88         .word __bss_start
89
90 .globl _bss_end
91 _bss_end:
92         .word _end
93
94 #ifdef CONFIG_USE_IRQ
95 /* IRQ stack memory (calculated at run-time) */
96 .globl IRQ_STACK_START
97 IRQ_STACK_START:
98         .word   0x0badc0de
99
100 /* IRQ stack memory (calculated at run-time) */
101 .globl FIQ_STACK_START
102 FIQ_STACK_START:
103         .word 0x0badc0de
104 #endif
105
106
107 /*
108  * the actual reset code
109  */
110
111 reset:
112         /*
113          * set the cpu to SVC32 mode
114          */
115         mrs     r0,cpsr
116         bic     r0,r0,#0x1f
117         orr     r0,r0,#0x13
118         msr     cpsr,r0
119
120         /*
121          * we do sys-critical inits only at reboot,
122          * not when booting from ram!
123          */
124 #ifdef CONFIG_INIT_CRITICAL
125         bl      cpu_init_crit
126 #endif
127
128 relocate:                               /* relocate U-Boot to RAM           */
129         adr     r0, _start              /* r0 <- current position of code   */
130         ldr     r1, _TEXT_BASE          /* test if we run from flash or RAM */
131         cmp     r0, r1                  /* don't reloc during debug         */
132         beq     stack_setup
133
134         ldr     r2, _armboot_start
135         ldr     r3, _bss_start
136         sub     r2, r3, r2              /* r2 <- size of armboot            */
137         add     r2, r0, r2              /* r2 <- source end address         */
138
139 copy_loop:
140         ldmia   r0!, {r3-r10}           /* copy from source address [r0]    */
141         stmia   r1!, {r3-r10}           /* copy to   target address [r1]    */
142         cmp     r0, r2                  /* until source end addreee [r2]    */
143         ble     copy_loop
144
145         /* Set up the stack                                                 */
146 stack_setup:
147         ldr     r0, _TEXT_BASE          /* upper 128 KiB: relocated uboot   */
148         sub     r0, r0, #CFG_MALLOC_LEN /* malloc area                      */
149         sub     r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo                        */
150 #ifdef CONFIG_USE_IRQ
151         sub     r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
152 #endif
153         sub     sp, r0, #12             /* leave 3 words for abort-stack    */
154
155 clear_bss:
156         ldr     r0, _bss_start          /* find start of bss segment        */
157         ldr     r1, _bss_end            /* stop here                        */
158         mov     r2, #0x00000000         /* clear                            */
159
160 clbss_l:str     r2, [r0]                /* clear loop...                    */
161         add     r0, r0, #4
162         cmp     r0, r1
163         bne     clbss_l
164
165         ldr     pc, _start_armboot
166
167 _start_armboot: .word start_armboot
168
169
170 /*
171  *************************************************************************
172  *
173  * CPU_init_critical registers
174  *
175  * setup important registers
176  * setup memory timing
177  *
178  *************************************************************************
179  */
180
181
182 /* Interupt-Controller base addresses */
183 INTMR1:         .word   0x80000280 @ 32 bit size
184 INTMR2:         .word   0x80001280 @ 16 bit size
185 INTMR3:         .word   0x80002280 @  8 bit size
186
187 /* SYSCONs */
188 SYSCON1:        .word   0x80000100
189 SYSCON2:        .word   0x80001100
190 SYSCON3:        .word   0x80002200
191
192 #define CLKCTL         0x6  /* mask */
193 #define CLKCTL_18      0x0  /* 18.432 MHz */
194 #define CLKCTL_36      0x2  /* 36.864 MHz */
195 #define CLKCTL_49      0x4  /* 49.152 MHz */
196 #define CLKCTL_73      0x6  /* 73.728 MHz */
197
198 cpu_init_crit:
199 #ifndef CONFIG_NETARM
200         /*
201          * mask all IRQs by clearing all bits in the INTMRs
202          */
203         mov     r1, #0x00
204         ldr     r0, INTMR1
205         str     r1, [r0]
206         ldr     r0, INTMR2
207         str     r1, [r0]
208         ldr     r0, INTMR3
209         str     r1, [r0]
210
211         /*
212          * flush v4 I/D caches
213          */
214         mov     r0, #0
215         mcr     p15, 0, r0, c7, c7, 0   /* flush v3/v4 cache */
216         mcr     p15, 0, r0, c8, c7, 0   /* flush v4 TLB */
217
218         /*
219          * disable MMU stuff and caches
220          */
221         mrc     p15,0,r0,c1,c0
222         bic     r0, r0, #0x00002300     @ clear bits 13, 9:8 (--V- --RS)
223         bic     r0, r0, #0x0000008f     @ clear bits 7, 3:0 (B--- WCAM)
224         orr     r0, r0, #0x00000002     @ set bit 2 (A) Align
225         mcr     p15,0,r0,c1,c0
226 #else /* CONFIG_NETARM */
227         /*
228          * prior to software reset : need to set pin PORTC4 to be *HRESET
229          */
230         ldr     r0, =NETARM_GEN_MODULE_BASE
231         ldr     r1, =(NETARM_GEN_PORT_MODE(0x10) | \
232                         NETARM_GEN_PORT_DIR(0x10))
233         str     r1, [r0, #+NETARM_GEN_PORTC]
234         /*
235          * software reset : see HW Ref. Guide 8.2.4 : Software Service register
236          *                  for an explanation of this process
237          */
238         ldr     r0, =NETARM_GEN_MODULE_BASE
239         ldr     r1, =NETARM_GEN_SW_SVC_RESETA
240         str     r1, [r0, #+NETARM_GEN_SOFTWARE_SERVICE]
241         ldr     r1, =NETARM_GEN_SW_SVC_RESETB
242         str     r1, [r0, #+NETARM_GEN_SOFTWARE_SERVICE]
243         ldr     r1, =NETARM_GEN_SW_SVC_RESETA
244         str     r1, [r0, #+NETARM_GEN_SOFTWARE_SERVICE]
245         ldr     r1, =NETARM_GEN_SW_SVC_RESETB
246         str     r1, [r0, #+NETARM_GEN_SOFTWARE_SERVICE]
247         /*
248          * setup PLL and System Config
249          */
250         ldr     r0, =NETARM_GEN_MODULE_BASE
251
252         ldr     r1, =(  NETARM_GEN_SYS_CFG_LENDIAN | \
253                         NETARM_GEN_SYS_CFG_BUSFULL | \
254                         NETARM_GEN_SYS_CFG_USER_EN | \
255                         NETARM_GEN_SYS_CFG_ALIGN_ABORT | \
256                         NETARM_GEN_SYS_CFG_BUSARB_INT | \
257                         NETARM_GEN_SYS_CFG_BUSMON_EN )
258
259         str     r1, [r0, #+NETARM_GEN_SYSTEM_CONTROL]
260
261         ldr     r1, =(  NETARM_GEN_PLL_CTL_PLLCNT(NETARM_PLL_COUNT_VAL) | \
262                         NETARM_GEN_PLL_CTL_POLTST_DEF | \
263                         NETARM_GEN_PLL_CTL_INDIV(1) | \
264                         NETARM_GEN_PLL_CTL_ICP_DEF | \
265                         NETARM_GEN_PLL_CTL_OUTDIV(2) )
266         str     r1, [r0, #+NETARM_GEN_PLL_CONTROL]
267         /*
268          * mask all IRQs by clearing all bits in the INTMRs
269          */
270         mov     r1, #0
271         ldr     r0, =NETARM_GEN_MODULE_BASE
272         str     r1, [r0, #+NETARM_GEN_INTR_ENABLE]
273 #endif /* CONFIG_NETARM */
274
275 #ifdef CONFIG_ARM7_REVD
276         /* set clock speed */
277         /* !!! we run @ 36 MHz due to a hardware flaw in Rev. D processors */
278         /* !!! not doing DRAM refresh properly! */
279         ldr     r0, SYSCON3
280         ldr     r1, [r0]
281         bic     r1, r1, #CLKCTL
282         orr     r1, r1, #CLKCTL_36
283         str     r1, [r0]
284 #endif
285
286         /*
287          * before relocating, we have to setup RAM timing
288          * because memory timing is board-dependent, you will
289          * find a memsetup.S in your board directory.
290          */
291         mov     ip, lr
292         bl      memsetup
293         mov     lr, ip
294
295         mov     pc, lr
296
297
298 /*
299  *************************************************************************
300  *
301  * Interrupt handling
302  *
303  *************************************************************************
304  */
305
306 @
307 @ IRQ stack frame.
308 @
309 #define S_FRAME_SIZE    72
310
311 #define S_OLD_R0        68
312 #define S_PSR           64
313 #define S_PC            60
314 #define S_LR            56
315 #define S_SP            52
316
317 #define S_IP            48
318 #define S_FP            44
319 #define S_R10           40
320 #define S_R9            36
321 #define S_R8            32
322 #define S_R7            28
323 #define S_R6            24
324 #define S_R5            20
325 #define S_R4            16
326 #define S_R3            12
327 #define S_R2            8
328 #define S_R1            4
329 #define S_R0            0
330
331 #define MODE_SVC 0x13
332 #define I_BIT    0x80
333
334 /*
335  * use bad_save_user_regs for abort/prefetch/undef/swi ...
336  * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
337  */
338
339         .macro  bad_save_user_regs
340         sub     sp, sp, #S_FRAME_SIZE
341         stmia   sp, {r0 - r12}                  @ Calling r0-r12
342         add     r8, sp, #S_PC
343
344         ldr     r2, _armboot_start
345         sub     r2, r2, #(CONFIG_STACKSIZE+CFG_MALLOC_LEN)
346         sub     r2, r2, #(CFG_GBL_DATA_SIZE+8)  @ set base 2 words into abort stack
347         ldmia   r2, {r2 - r4}                   @ get pc, cpsr, old_r0
348         add     r0, sp, #S_FRAME_SIZE           @ restore sp_SVC
349
350         add     r5, sp, #S_SP
351         mov     r1, lr
352         stmia   r5, {r0 - r4}                   @ save sp_SVC, lr_SVC, pc, cpsr, old_r
353         mov     r0, sp
354         .endm
355
356         .macro  irq_save_user_regs
357         sub     sp, sp, #S_FRAME_SIZE
358         stmia   sp, {r0 - r12}                  @ Calling r0-r12
359         add     r8, sp, #S_PC
360         stmdb   r8, {sp, lr}^                   @ Calling SP, LR
361         str     lr, [r8, #0]                    @ Save calling PC
362         mrs     r6, spsr
363         str     r6, [r8, #4]                    @ Save CPSR
364         str     r0, [r8, #8]                    @ Save OLD_R0
365         mov     r0, sp
366         .endm
367
368         .macro  irq_restore_user_regs
369         ldmia   sp, {r0 - lr}^                  @ Calling r0 - lr
370         mov     r0, r0
371         ldr     lr, [sp, #S_PC]                 @ Get PC
372         add     sp, sp, #S_FRAME_SIZE
373         subs    pc, lr, #4                      @ return & move spsr_svc into cpsr
374         .endm
375
376         .macro get_bad_stack
377         ldr     r13, _armboot_start             @ setup our mode stack
378         sub     r13, r13, #(CONFIG_STACKSIZE+CFG_MALLOC_LEN)
379         sub     r13, r13, #(CFG_GBL_DATA_SIZE+8) @ reserved a couple spots in abort stack
380
381         str     lr, [r13]                       @ save caller lr / spsr
382         mrs     lr, spsr
383         str     lr, [r13, #4]
384
385         mov     r13, #MODE_SVC                  @ prepare SVC-Mode
386         msr     spsr_c, r13
387         mov     lr, pc
388         movs    pc, lr
389         .endm
390
391         .macro get_irq_stack                    @ setup IRQ stack
392         ldr     sp, IRQ_STACK_START
393         .endm
394
395         .macro get_fiq_stack                    @ setup FIQ stack
396         ldr     sp, FIQ_STACK_START
397         .endm
398
399 /*
400  * exception handlers
401  */
402         .align  5
403 undefined_instruction:
404         get_bad_stack
405         bad_save_user_regs
406         bl      do_undefined_instruction
407
408         .align  5
409 software_interrupt:
410         get_bad_stack
411         bad_save_user_regs
412         bl      do_software_interrupt
413
414         .align  5
415 prefetch_abort:
416         get_bad_stack
417         bad_save_user_regs
418         bl      do_prefetch_abort
419
420         .align  5
421 data_abort:
422         get_bad_stack
423         bad_save_user_regs
424         bl      do_data_abort
425
426         .align  5
427 not_used:
428         get_bad_stack
429         bad_save_user_regs
430         bl      do_not_used
431
432 #ifdef CONFIG_USE_IRQ
433
434         .align  5
435 irq:
436         get_irq_stack
437         irq_save_user_regs
438         bl      do_irq
439         irq_restore_user_regs
440
441         .align  5
442 fiq:
443         get_fiq_stack
444         /* someone ought to write a more effiction fiq_save_user_regs */
445         irq_save_user_regs
446         bl      do_fiq
447         irq_restore_user_regs
448
449 #else
450
451         .align  5
452 irq:
453         get_bad_stack
454         bad_save_user_regs
455         bl      do_irq
456
457         .align  5
458 fiq:
459         get_bad_stack
460         bad_save_user_regs
461         bl      do_fiq
462
463 #endif
464
465         .align  5
466 .globl reset_cpu
467 reset_cpu:
468 #ifndef CONFIG_NETARM
469         mov     ip, #0
470         mcr     p15, 0, ip, c7, c7, 0           @ invalidate cache
471         mcr     p15, 0, ip, c8, c7, 0           @ flush TLB (v4)
472         mrc     p15, 0, ip, c1, c0, 0           @ get ctrl register
473         bic     ip, ip, #0x000f                 @ ............wcam
474         bic     ip, ip, #0x2100                 @ ..v....s........
475         mcr     p15, 0, ip, c1, c0, 0           @ ctrl register
476         mov     pc, r0
477 #else
478         ldr     r1, =NETARM_MEM_MODULE_BASE
479         ldr     r0, [r1, #+NETARM_MEM_CS0_BASE_ADDR]
480         ldr     r1, =0xFFFFF000
481         and     r0, r1, r0
482         ldr     r1, =(relocate-TEXT_BASE)
483         add     r0, r1, r0
484         ldr     r4, =NETARM_GEN_MODULE_BASE
485         ldr     r1, =NETARM_GEN_SW_SVC_RESETA
486         str     r1, [r4, #+NETARM_GEN_SOFTWARE_SERVICE]
487         ldr     r1, =NETARM_GEN_SW_SVC_RESETB
488         str     r1, [r4, #+NETARM_GEN_SOFTWARE_SERVICE]
489         ldr     r1, =NETARM_GEN_SW_SVC_RESETA
490         str     r1, [r4, #+NETARM_GEN_SOFTWARE_SERVICE]
491         ldr     r1, =NETARM_GEN_SW_SVC_RESETB
492         str     r1, [r4, #+NETARM_GEN_SOFTWARE_SERVICE]
493         mov     pc, r0
494 #endif