]>
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 | */ | |
22 | #include <config.h> | |
caf83ea8 | 23 | #include <asm/ptrace.h> |
72a087e0 WD |
24 | #include <asm/sysreg.h> |
25 | ||
72a087e0 WD |
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 | ||
caf83ea8 HS |
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 | |
72a087e0 | 40 | .global _start |
caf83ea8 HS |
41 | .global _evba |
42 | .type _start, @function | |
43 | .type _evba, @function | |
72a087e0 | 44 | _start: |
caf83ea8 HS |
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 | |
72a087e0 | 131 | |
caf83ea8 HS |
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: | |
72a087e0 WD |
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 | |
caf83ea8 HS |
170 | 1: .long at32ap_low_level_init |
171 | .size _start, . - _start | |
72a087e0 | 172 | |
caf83ea8 HS |
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 | |
72a087e0 | 180 | |
72a087e0 WD |
181 | /* Initialize the GOT pointer */ |
182 | lddpc r6, got_init | |
183 | 3: rsub r6, pc | |
1f4f2121 HS |
184 | |
185 | /* Let's go */ | |
186 | rjmp board_init_f | |
72a087e0 WD |
187 | |
188 | .align 2 | |
189 | .type sp_init,@object | |
190 | sp_init: | |
6d0f6bcf | 191 | .long CONFIG_SYS_INIT_SP_ADDR |
72a087e0 WD |
192 | got_init: |
193 | .long 3b - _GLOBAL_OFFSET_TABLE_ | |
1f4f2121 HS |
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 | */ | |
caf83ea8 | 201 | .section .text.relocate_code,"ax",@progbits |
1f4f2121 HS |
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_ | |
caf83ea8 HS |
274 | |
275 | .size relocate_code, . - relocate_code |