blob: 97140e93ebb8fa2917375e5dbd1585f47764d8c7 [file] [log] [blame]
Wolfgang Denk72a087e2006-10-24 14:27:35 +02001/*
Haavard Skinnemoencaf83ea2008-05-02 15:32:57 +02002 * Copyright (C) 2005-2008 Atmel Corporation
Wolfgang Denk72a087e2006-10-24 14:27:35 +02003 *
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 */
Wolfgang Denk25ddd1f2010-10-26 14:34:52 +020022#include <asm-offsets.h>
Wolfgang Denk72a087e2006-10-24 14:27:35 +020023#include <config.h>
Haavard Skinnemoencaf83ea2008-05-02 15:32:57 +020024#include <asm/ptrace.h>
Wolfgang Denk72a087e2006-10-24 14:27:35 +020025#include <asm/sysreg.h>
26
Wolfgang Denk72a087e2006-10-24 14:27:35 +020027#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))
Andreas Bießmanneb70d052010-06-09 14:13:45 +020031/* 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))
Wolfgang Denk72a087e2006-10-24 14:27:35 +020035
Haavard Skinnemoencaf83ea2008-05-02 15:32:57 +020036 /*
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
Wolfgang Denk72a087e2006-10-24 14:27:35 +020042 .global _start
Haavard Skinnemoencaf83ea2008-05-02 15:32:57 +020043 .global _evba
44 .type _start, @function
45 .type _evba, @function
Wolfgang Denk72a087e2006-10-24 14:27:35 +020046_start:
Haavard Skinnemoencaf83ea2008-05-02 15:32:57 +020047 .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 */
Wolfgang Denk72a087e2006-10-24 14:27:35 +020085
Haavard Skinnemoen1f36f732010-08-12 13:52:54 +070086 .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
941: mov r12, sp
95 rcall mmu_handle_tlb_miss
96 popm r8-r12,lr
97 brne unknown_exception
98 rete
Haavard Skinnemoencaf83ea2008-05-02 15:32:57 +020099
100 .size _evba, . - _evba
101
102 .align 2
103 .type unknown_exception, @function
104unknown_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
1201: rjmp 1b
121
122 /* The COUNT/COMPARE timer interrupt handler */
123 .global timer_interrupt_handler
124 .type timer_interrupt_handler,@function
125 .align 2
126timer_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
151at32ap_cpu_bootstrap:
Wolfgang Denk72a087e2006-10-24 14:27:35 +0200152 /* 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
Haavard Skinnemoencaf83ea2008-05-02 15:32:57 +02001791: .long at32ap_low_level_init
180 .size _start, . - _start
Wolfgang Denk72a087e2006-10-24 14:27:35 +0200181
Haavard Skinnemoencaf83ea2008-05-02 15:32:57 +0200182 /* 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
187at32ap_low_level_init:
188 lddpc sp, sp_init
Wolfgang Denk72a087e2006-10-24 14:27:35 +0200189
Wolfgang Denk72a087e2006-10-24 14:27:35 +0200190 /* Initialize the GOT pointer */
191 lddpc r6, got_init
1923: rsub r6, pc
Haavard Skinnemoen1f4f2122006-11-20 15:53:10 +0100193
194 /* Let's go */
195 rjmp board_init_f
Wolfgang Denk72a087e2006-10-24 14:27:35 +0200196
197 .align 2
198 .type sp_init,@object
199sp_init:
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200200 .long CONFIG_SYS_INIT_SP_ADDR
Wolfgang Denk72a087e2006-10-24 14:27:35 +0200201got_init:
202 .long 3b - _GLOBAL_OFFSET_TABLE_
Haavard Skinnemoen1f4f2122006-11-20 15:53:10 +0100203
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 */
Haavard Skinnemoencaf83ea2008-05-02 15:32:57 +0200210 .section .text.relocate_code,"ax",@progbits
Haavard Skinnemoen1f4f2122006-11-20 15:53:10 +0100211 .global relocate_code
212 .type relocate_code,@function
213relocate_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
2231: 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
2391: 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
2491: 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
258in_ram:
259 /* find the new GOT and relocate it */
260 lddpc r6, got_init_reloc
2613: rsub r6, pc
262 mov r8, r6
263 lda.w r9, _egot
264 lda.w r10, _got
265 sub r9, r10
2661: 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
281got_init_reloc:
282 .long 3b - _GLOBAL_OFFSET_TABLE_
Haavard Skinnemoencaf83ea2008-05-02 15:32:57 +0200283
284 .size relocate_code, . - relocate_code