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