97140e93ebb8fa2917375e5dbd1585f47764d8c7
[platform/kernel/u-boot.git] / arch / avr32 / cpu / start.S
1 /*
2  * Copyright (C) 2005-2008 Atmel Corporation
3  *
4  * See file CREDITS for list of people who contributed to this
5  * project.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License as
9  * published by the Free Software Foundation; either version 2 of
10  * the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
20  * MA 02111-1307 USA
21  */
22 #include <asm-offsets.h>
23 #include <config.h>
24 #include <asm/ptrace.h>
25 #include <asm/sysreg.h>
26
27 #define SYSREG_MMUCR_I_OFFSET   2
28 #define SYSREG_MMUCR_S_OFFSET   4
29
30 #define SR_INIT (SYSREG_BIT(GM) | SYSREG_BIT(EM) | SYSREG_BIT(M0))
31 /* due to errata (unreliable branch folding) clear FE bit explicitly */
32 #define CPUCR_INIT ((SYSREG_BIT(BI) | SYSREG_BIT(BE)    \
33                     | SYSREG_BIT(RE)   |  SYSREG_BIT(IBE)               \
34                     | SYSREG_BIT(IEE)) & ~SYSREG_BIT(FE))
35
36         /*
37          * To save some space, we use the same entry point for
38          * exceptions and reset. This avoids lots of alignment padding
39          * since the reset vector is always suitably aligned.
40          */
41         .section .exception.text, "ax", @progbits
42         .global _start
43         .global _evba
44         .type   _start, @function
45         .type   _evba, @function
46 _start:
47         .size   _start, 0
48 _evba:
49         .org    0x00
50         rjmp    unknown_exception       /* Unrecoverable exception */
51         .org    0x04
52         rjmp    unknown_exception       /* TLB multiple hit */
53         .org    0x08
54         rjmp    unknown_exception       /* Bus error data fetch */
55         .org    0x0c
56         rjmp    unknown_exception       /* Bus error instruction fetch */
57         .org    0x10
58         rjmp    unknown_exception       /* NMI */
59         .org    0x14
60         rjmp    unknown_exception       /* Instruction address */
61         .org    0x18
62         rjmp    unknown_exception       /* ITLB protection */
63         .org    0x1c
64         rjmp    unknown_exception       /* Breakpoint */
65         .org    0x20
66         rjmp    unknown_exception       /* Illegal opcode */
67         .org    0x24
68         rjmp    unknown_exception       /* Unimplemented instruction */
69         .org    0x28
70         rjmp    unknown_exception       /* Privilege violation */
71         .org    0x2c
72         rjmp    unknown_exception       /* Floating-point */
73         .org    0x30
74         rjmp    unknown_exception       /* Coprocessor absent */
75         .org    0x34
76         rjmp    unknown_exception       /* Data Address (read) */
77         .org    0x38
78         rjmp    unknown_exception       /* Data Address (write) */
79         .org    0x3c
80         rjmp    unknown_exception       /* DTLB Protection (read) */
81         .org    0x40
82         rjmp    unknown_exception       /* DTLB Protection (write) */
83         .org    0x44
84         rjmp    unknown_exception       /* DTLB Modified */
85
86         .org    0x50                    /* ITLB Miss */
87         pushm   r8-r12,lr
88         rjmp    1f
89         .org    0x60                    /* DTLB Miss (read) */
90         pushm   r8-r12,lr
91         rjmp    1f
92         .org    0x70                    /* DTLB Miss (write) */
93         pushm   r8-r12,lr
94 1:      mov     r12, sp
95         rcall   mmu_handle_tlb_miss
96         popm    r8-r12,lr
97         brne    unknown_exception
98         rete
99
100         .size   _evba, . - _evba
101
102         .align  2
103         .type   unknown_exception, @function
104 unknown_exception:
105         /* Figure out whether we're handling an exception (Exception
106          * mode) or just booting (Supervisor mode). */
107         csrfcz  SYSREG_M1_OFFSET
108         brcc    at32ap_cpu_bootstrap
109
110         /* This is an exception. Complain. */
111         pushm   r0-r12
112         sub     r8, sp, REG_R12 - REG_R0 - 4
113         mov     r9, lr
114         mfsr    r10, SYSREG_RAR_EX
115         mfsr    r11, SYSREG_RSR_EX
116         pushm   r8-r11
117         mfsr    r12, SYSREG_ECR
118         mov     r11, sp
119         rcall   do_unknown_exception
120 1:      rjmp    1b
121
122         /* The COUNT/COMPARE timer interrupt handler */
123         .global timer_interrupt_handler
124         .type   timer_interrupt_handler,@function
125         .align  2
126 timer_interrupt_handler:
127         /*
128          * Increment timer_overflow and re-write COMPARE with 0xffffffff.
129          *
130          * We're running at interrupt level 3, so we don't need to save
131          * r8-r12 or lr to the stack.
132          */
133         lda.w   r8, timer_overflow
134         ld.w    r9, r8[0]
135         mov     r10, -1
136         mtsr    SYSREG_COMPARE, r10
137         sub     r9, -1
138         st.w    r8[0], r9
139         rete
140
141         /*
142          * CPU bootstrap after reset is handled here. SoC code may
143          * override this in case they need to initialize oscillators,
144          * etc.
145          */
146         .section .text.at32ap_cpu_bootstrap, "ax", @progbits
147         .global at32ap_cpu_bootstrap
148         .weak   at32ap_cpu_bootstrap
149         .type   at32ap_cpu_bootstrap, @function
150         .align  2
151 at32ap_cpu_bootstrap:
152         /* Reset the Status Register */
153         mov     r0, lo(SR_INIT)
154         orh     r0, hi(SR_INIT)
155         mtsr    SYSREG_SR, r0
156
157         /* Reset CPUCR and invalidate the BTB */
158         mov     r2, CPUCR_INIT
159         mtsr    SYSREG_CPUCR, r2
160
161         /* Flush the caches */
162         mov     r1, 0
163         cache   r1[4], 8
164         cache   r1[0], 0
165         sync    0
166
167         /* Reset the MMU to default settings */
168         mov     r0, SYSREG_BIT(MMUCR_S) | SYSREG_BIT(MMUCR_I)
169         mtsr    SYSREG_MMUCR, r0
170
171         /* Internal RAM should not need any initialization.  We might
172            have to initialize external RAM here if the part doesn't
173            have internal RAM (or we may use the data cache) */
174
175         /* Jump to cacheable segment */
176         lddpc   pc, 1f
177
178         .align  2
179 1:      .long   at32ap_low_level_init
180         .size   _start, . - _start
181
182         /* Common CPU bootstrap code after oscillator/cache/etc. init */
183         .section .text.avr32ap_low_level_init, "ax", @progbits
184         .global at32ap_low_level_init
185         .type   at32ap_low_level_init, @function
186         .align  2
187 at32ap_low_level_init:
188         lddpc   sp, sp_init
189
190         /* Initialize the GOT pointer */
191         lddpc   r6, got_init
192 3:      rsub    r6, pc
193
194         /* Let's go */
195         rjmp    board_init_f
196
197         .align  2
198         .type   sp_init,@object
199 sp_init:
200         .long   CONFIG_SYS_INIT_SP_ADDR
201 got_init:
202         .long   3b - _GLOBAL_OFFSET_TABLE_
203
204         /*
205          * void relocate_code(new_sp, new_gd, monitor_addr)
206          *
207          * Relocate the u-boot image into RAM and continue from there.
208          * Does not return.
209          */
210         .section .text.relocate_code,"ax",@progbits
211         .global relocate_code
212         .type   relocate_code,@function
213 relocate_code:
214         mov     sp, r12         /* use new stack */
215         mov     r12, r11        /* save new_gd */
216         mov     r11, r10        /* save destination address */
217
218         /* copy .text section and flush the cache along the way */
219         lda.w   r8, _text
220         lda.w   r9, _etext
221         sub     lr, r10, r8     /* relocation offset */
222
223 1:      ldm     r8++, r0-r3
224         stm     r10, r0-r3
225         sub     r10, -16
226         ldm     r8++, r0-r3
227         stm     r10, r0-r3
228         sub     r10, -16
229         cp.w    r8, r9
230         cache   r10[-4], 0x0d   /* dcache clean/invalidate */
231         cache   r10[-4], 0x01   /* icache invalidate */
232         brlt    1b
233
234         /* flush write buffer */
235         sync    0
236
237         /* copy data sections */
238         lda.w   r9, _edata
239 1:      ld.d    r0, r8++
240         st.d    r10++, r0
241         cp.w    r8, r9
242         brlt    1b
243
244         /* zero out .bss */
245         mov     r0, 0
246         mov     r1, 0
247         lda.w   r9, _end
248         sub     r9, r8
249 1:      st.d    r10++, r0
250         sub     r9, 8
251         brgt    1b
252
253         /* jump to RAM */
254         sub     r0, pc, . - in_ram
255         add     pc, r0, lr
256
257         .align  2
258 in_ram:
259         /* find the new GOT and relocate it */
260         lddpc   r6, got_init_reloc
261 3:      rsub    r6, pc
262         mov     r8, r6
263         lda.w   r9, _egot
264         lda.w   r10, _got
265         sub     r9, r10
266 1:      ld.w    r0, r8[0]
267         add     r0, lr
268         st.w    r8++, r0
269         sub     r9, 4
270         brgt    1b
271
272         /* Move the exception handlers */
273         mfsr    r2, SYSREG_EVBA
274         add     r2, lr
275         mtsr    SYSREG_EVBA, r2
276
277         /* Do the rest of the initialization sequence */
278         call    board_init_r
279
280         .align  2
281 got_init_reloc:
282         .long   3b - _GLOBAL_OFFSET_TABLE_
283
284         .size   relocate_code, . - relocate_code