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