]>
Commit | Line | Data |
---|---|---|
72a087e0 | 1 | /* |
caf83ea8 | 2 | * Copyright (C) 2005-2008 Atmel Corporation |
72a087e0 WD |
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 | */ | |
25ddd1fb | 22 | #include <asm-offsets.h> |
72a087e0 | 23 | #include <config.h> |
caf83ea8 | 24 | #include <asm/ptrace.h> |
72a087e0 WD |
25 | #include <asm/sysreg.h> |
26 | ||
72a087e0 WD |
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)) | |
eb70d05d AB |
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)) | |
72a087e0 | 35 | |
caf83ea8 HS |
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 | |
72a087e0 | 42 | .global _start |
caf83ea8 HS |
43 | .global _evba |
44 | .type _start, @function | |
45 | .type _evba, @function | |
72a087e0 | 46 | _start: |
caf83ea8 HS |
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 | ||
1f36f73f HS |
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 | |
caf83ea8 HS |
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 | |
72a087e0 | 140 | |
caf83ea8 HS |
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: | |
72a087e0 WD |
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 | |
caf83ea8 HS |
179 | 1: .long at32ap_low_level_init |
180 | .size _start, . - _start | |
72a087e0 | 181 | |
caf83ea8 HS |
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 | |
72a087e0 | 189 | |
72a087e0 WD |
190 | /* Initialize the GOT pointer */ |
191 | lddpc r6, got_init | |
192 | 3: rsub r6, pc | |
1f4f2121 HS |
193 | |
194 | /* Let's go */ | |
195 | rjmp board_init_f | |
72a087e0 WD |
196 | |
197 | .align 2 | |
198 | .type sp_init,@object | |
199 | sp_init: | |
6d0f6bcf | 200 | .long CONFIG_SYS_INIT_SP_ADDR |
72a087e0 WD |
201 | got_init: |
202 | .long 3b - _GLOBAL_OFFSET_TABLE_ | |
1f4f2121 HS |
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 | */ | |
caf83ea8 | 210 | .section .text.relocate_code,"ax",@progbits |
1f4f2121 HS |
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 | |
3929fb0a | 247 | lda.w r9, __bss_end |
1f4f2121 HS |
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_ | |
caf83ea8 HS |
283 | |
284 | .size relocate_code, . - relocate_code |