]>
Commit | Line | Data |
---|---|---|
fe8c2806 WD |
1 | /* |
2 | * armboot - Startup Code for ARM720 CPU-core | |
3 | * | |
fa82f871 AA |
4 | * Copyright (c) 2001 Marius Gröger <mag@sysgo.de> |
5 | * Copyright (c) 2002 Alex Züpke <azu@sysgo.de> | |
fe8c2806 WD |
6 | * |
7 | * See file CREDITS for list of people who contributed to this | |
8 | * project. | |
9 | * | |
10 | * This program is free software; you can redistribute it and/or | |
11 | * modify it under the terms of the GNU General Public License as | |
12 | * published by the Free Software Foundation; either version 2 of | |
13 | * the License, or (at your option) any later version. | |
14 | * | |
15 | * This program is distributed in the hope that it will be useful, | |
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
cdc7fea1 | 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
fe8c2806 WD |
18 | * GNU General Public License for more details. |
19 | * | |
20 | * You should have received a copy of the GNU General Public License | |
21 | * along with this program; if not, write to the Free Software | |
22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | |
23 | * MA 02111-1307 USA | |
24 | */ | |
25 | ||
25ddd1fb | 26 | #include <asm-offsets.h> |
fe8c2806 WD |
27 | #include <config.h> |
28 | #include <version.h> | |
39539887 | 29 | #include <asm/hardware.h> |
fe8c2806 WD |
30 | |
31 | /* | |
32 | ************************************************************************* | |
33 | * | |
34 | * Jump vector table as in table 3.1 in [1] | |
35 | * | |
36 | ************************************************************************* | |
37 | */ | |
38 | ||
39 | ||
40 | .globl _start | |
cdc7fea1 | 41 | _start: b reset |
fe8c2806 WD |
42 | ldr pc, _undefined_instruction |
43 | ldr pc, _software_interrupt | |
44 | ldr pc, _prefetch_abort | |
45 | ldr pc, _data_abort | |
6bd2447e GJ |
46 | #ifdef CONFIG_LPC2292 |
47 | .word 0xB4405F76 /* 2's complement of the checksum of the vectors */ | |
48 | #else | |
fe8c2806 | 49 | ldr pc, _not_used |
6bd2447e | 50 | #endif |
fe8c2806 WD |
51 | ldr pc, _irq |
52 | ldr pc, _fiq | |
53 | ||
cdc7fea1 | 54 | _undefined_instruction: .word undefined_instruction |
fe8c2806 WD |
55 | _software_interrupt: .word software_interrupt |
56 | _prefetch_abort: .word prefetch_abort | |
57 | _data_abort: .word data_abort | |
58 | _not_used: .word not_used | |
59 | _irq: .word irq | |
60 | _fiq: .word fiq | |
61 | ||
62 | .balignl 16,0xdeadbeef | |
63 | ||
64 | ||
65 | /* | |
66 | ************************************************************************* | |
67 | * | |
68 | * Startup Code (reset vector) | |
69 | * | |
f6e20fc6 | 70 | * do important init only if we don't start from RAM! |
fe8c2806 WD |
71 | * relocate armboot to ram |
72 | * setup stack | |
73 | * jump to second stage | |
74 | * | |
75 | ************************************************************************* | |
76 | */ | |
77 | ||
abef7b85 | 78 | .globl _TEXT_BASE |
fe8c2806 | 79 | _TEXT_BASE: |
14d0a02a | 80 | .word CONFIG_SYS_TEXT_BASE |
fe8c2806 | 81 | |
fe8c2806 | 82 | /* |
f6e20fc6 | 83 | * These are defined in the board-specific linker script. |
3336ca60 AA |
84 | * Subtracting _start from them lets the linker put their |
85 | * relative position in the executable instead of leaving | |
86 | * them null. | |
fe8c2806 | 87 | */ |
3336ca60 AA |
88 | .globl _bss_start_ofs |
89 | _bss_start_ofs: | |
90 | .word __bss_start - _start | |
f6e20fc6 | 91 | |
3336ca60 AA |
92 | .globl _bss_end_ofs |
93 | _bss_end_ofs: | |
44c6e659 | 94 | .word __bss_end__ - _start |
fe8c2806 | 95 | |
f326cbba PYC |
96 | .globl _end_ofs |
97 | _end_ofs: | |
98 | .word _end - _start | |
99 | ||
fe8c2806 WD |
100 | #ifdef CONFIG_USE_IRQ |
101 | /* IRQ stack memory (calculated at run-time) */ | |
102 | .globl IRQ_STACK_START | |
103 | IRQ_STACK_START: | |
104 | .word 0x0badc0de | |
105 | ||
106 | /* IRQ stack memory (calculated at run-time) */ | |
107 | .globl FIQ_STACK_START | |
108 | FIQ_STACK_START: | |
109 | .word 0x0badc0de | |
110 | #endif | |
111 | ||
abef7b85 HS |
112 | /* IRQ stack memory (calculated at run-time) + 8 bytes */ |
113 | .globl IRQ_STACK_START_IN | |
114 | IRQ_STACK_START_IN: | |
115 | .word 0x0badc0de | |
116 | ||
abef7b85 HS |
117 | /* |
118 | * the actual reset code | |
119 | */ | |
120 | ||
121 | reset: | |
122 | /* | |
123 | * set the cpu to SVC32 mode | |
124 | */ | |
125 | mrs r0,cpsr | |
126 | bic r0,r0,#0x1f | |
127 | orr r0,r0,#0xd3 | |
128 | msr cpsr,r0 | |
129 | ||
130 | /* | |
131 | * we do sys-critical inits only at reboot, | |
132 | * not when booting from ram! | |
133 | */ | |
134 | #ifndef CONFIG_SKIP_LOWLEVEL_INIT | |
135 | bl cpu_init_crit | |
136 | #endif | |
137 | ||
138 | #ifdef CONFIG_LPC2292 | |
139 | bl lowlevel_init | |
140 | #endif | |
141 | ||
142 | /* Set stackpointer in internal RAM to call board_init_f */ | |
143 | call_board_init_f: | |
144 | ldr sp, =(CONFIG_SYS_INIT_SP_ADDR) | |
296cae73 | 145 | bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ |
abef7b85 HS |
146 | ldr r0,=0x00000000 |
147 | bl board_init_f | |
148 | ||
149 | /*------------------------------------------------------------------------------*/ | |
150 | ||
151 | /* | |
152 | * void relocate_code (addr_sp, gd, addr_moni) | |
153 | * | |
154 | * This "function" does not return, instead it continues in RAM | |
155 | * after relocating the monitor code. | |
156 | * | |
157 | */ | |
158 | .globl relocate_code | |
159 | relocate_code: | |
160 | mov r4, r0 /* save addr_sp */ | |
161 | mov r5, r1 /* save addr of gd */ | |
162 | mov r6, r2 /* save addr of destination */ | |
abef7b85 HS |
163 | |
164 | /* Set up the stack */ | |
165 | stack_setup: | |
166 | mov sp, r4 | |
167 | ||
168 | adr r0, _start | |
a1a47d3c AB |
169 | cmp r0, r6 |
170 | beq clear_bss /* skip relocation */ | |
a78fb68f | 171 | mov r1, r6 /* r1 <- scratch for copy_loop */ |
3336ca60 AA |
172 | ldr r3, _bss_start_ofs |
173 | add r2, r0, r3 /* r2 <- source end address */ | |
abef7b85 | 174 | |
abef7b85 HS |
175 | copy_loop: |
176 | ldmia r0!, {r9-r10} /* copy from source address [r0] */ | |
a78fb68f | 177 | stmia r1!, {r9-r10} /* copy to target address [r1] */ |
da90d4ce AA |
178 | cmp r0, r2 /* until source end address [r2] */ |
179 | blo copy_loop | |
abef7b85 | 180 | |
401bb30b | 181 | #ifndef CONFIG_SPL_BUILD |
3336ca60 AA |
182 | /* |
183 | * fix .rel.dyn relocations | |
184 | */ | |
185 | ldr r0, _TEXT_BASE /* r0 <- Text base */ | |
a78fb68f | 186 | sub r9, r6, r0 /* r9 <- relocation offset */ |
3336ca60 AA |
187 | ldr r10, _dynsym_start_ofs /* r10 <- sym table ofs */ |
188 | add r10, r10, r0 /* r10 <- sym table in FLASH */ | |
189 | ldr r2, _rel_dyn_start_ofs /* r2 <- rel dyn start ofs */ | |
190 | add r2, r2, r0 /* r2 <- rel dyn start in FLASH */ | |
191 | ldr r3, _rel_dyn_end_ofs /* r3 <- rel dyn end ofs */ | |
192 | add r3, r3, r0 /* r3 <- rel dyn end in FLASH */ | |
abef7b85 | 193 | fixloop: |
3336ca60 AA |
194 | ldr r0, [r2] /* r0 <- location to fix up, IN FLASH! */ |
195 | add r0, r0, r9 /* r0 <- location to fix up in RAM */ | |
196 | ldr r1, [r2, #4] | |
1f52d89f AB |
197 | and r7, r1, #0xff |
198 | cmp r7, #23 /* relative fixup? */ | |
3336ca60 | 199 | beq fixrel |
1f52d89f | 200 | cmp r7, #2 /* absolute fixup? */ |
3336ca60 AA |
201 | beq fixabs |
202 | /* ignore unknown type of fixup */ | |
203 | b fixnext | |
204 | fixabs: | |
205 | /* absolute fix: set location to (offset) symbol value */ | |
206 | mov r1, r1, LSR #4 /* r1 <- symbol index in .dynsym */ | |
207 | add r1, r10, r1 /* r1 <- address of symbol in table */ | |
208 | ldr r1, [r1, #4] /* r1 <- symbol value */ | |
3600945b | 209 | add r1, r1, r9 /* r1 <- relocated sym addr */ |
3336ca60 AA |
210 | b fixnext |
211 | fixrel: | |
212 | /* relative fix: increase location by offset */ | |
213 | ldr r1, [r0] | |
214 | add r1, r1, r9 | |
215 | fixnext: | |
216 | str r1, [r0] | |
217 | add r2, r2, #8 /* each rel.dyn entry is 8 bytes */ | |
abef7b85 | 218 | cmp r2, r3 |
79e63139 | 219 | blo fixloop |
abef7b85 | 220 | #endif |
abef7b85 HS |
221 | |
222 | clear_bss: | |
401bb30b | 223 | #ifndef CONFIG_SPL_BUILD |
3336ca60 AA |
224 | ldr r0, _bss_start_ofs |
225 | ldr r1, _bss_end_ofs | |
a78fb68f | 226 | mov r4, r6 /* reloc addr */ |
abef7b85 | 227 | add r0, r0, r4 |
abef7b85 HS |
228 | add r1, r1, r4 |
229 | mov r2, #0x00000000 /* clear */ | |
230 | ||
231 | clbss_l:str r2, [r0] /* clear loop... */ | |
232 | add r0, r0, #4 | |
233 | cmp r0, r1 | |
234 | bne clbss_l | |
235 | ||
236 | bl coloured_LED_init | |
237 | bl red_LED_on | |
238 | #endif | |
239 | ||
240 | /* | |
241 | * We are done. Do not return, instead branch to second part of board | |
242 | * initialization, now running from RAM. | |
243 | */ | |
3336ca60 AA |
244 | ldr r0, _board_init_r_ofs |
245 | adr r1, _start | |
246 | add lr, r0, r1 | |
247 | add lr, lr, r9 | |
abef7b85 HS |
248 | /* setup parameters for board_init_r */ |
249 | mov r0, r5 /* gd_t */ | |
a78fb68f | 250 | mov r1, r6 /* dest_addr */ |
abef7b85 | 251 | /* jump to it ... */ |
abef7b85 HS |
252 | mov pc, lr |
253 | ||
3336ca60 AA |
254 | _board_init_r_ofs: |
255 | .word board_init_r - _start | |
256 | ||
257 | _rel_dyn_start_ofs: | |
258 | .word __rel_dyn_start - _start | |
259 | _rel_dyn_end_ofs: | |
260 | .word __rel_dyn_end - _start | |
261 | _dynsym_start_ofs: | |
262 | .word __dynsym_start - _start | |
abef7b85 | 263 | |
fe8c2806 WD |
264 | /* |
265 | ************************************************************************* | |
266 | * | |
267 | * CPU_init_critical registers | |
268 | * | |
269 | * setup important registers | |
270 | * setup memory timing | |
271 | * | |
272 | ************************************************************************* | |
273 | */ | |
274 | ||
c570b2fd | 275 | #if defined(CONFIG_IMPA7) || defined(CONFIG_EP7312) || defined(CONFIG_ARMADILLO) |
fe8c2806 | 276 | |
16263087 | 277 | /* Interrupt-Controller base addresses */ |
fe8c2806 WD |
278 | INTMR1: .word 0x80000280 @ 32 bit size |
279 | INTMR2: .word 0x80001280 @ 16 bit size | |
280 | INTMR3: .word 0x80002280 @ 8 bit size | |
281 | ||
282 | /* SYSCONs */ | |
283 | SYSCON1: .word 0x80000100 | |
284 | SYSCON2: .word 0x80001100 | |
285 | SYSCON3: .word 0x80002200 | |
286 | ||
287 | #define CLKCTL 0x6 /* mask */ | |
288 | #define CLKCTL_18 0x0 /* 18.432 MHz */ | |
289 | #define CLKCTL_36 0x2 /* 36.864 MHz */ | |
290 | #define CLKCTL_49 0x4 /* 49.152 MHz */ | |
291 | #define CLKCTL_73 0x6 /* 73.728 MHz */ | |
292 | ||
6bd2447e GJ |
293 | #elif defined(CONFIG_LPC2292) |
294 | PLLCFG_ADR: .word PLLCFG | |
295 | PLLFEED_ADR: .word PLLFEED | |
296 | PLLCON_ADR: .word PLLCON | |
297 | PLLSTAT_ADR: .word PLLSTAT | |
298 | VPBDIV_ADR: .word VPBDIV | |
299 | MEMMAP_ADR: .word MEMMAP | |
300 | ||
39539887 WD |
301 | #endif |
302 | ||
fe8c2806 | 303 | cpu_init_crit: |
c570b2fd | 304 | #if defined(CONFIG_IMPA7) || defined(CONFIG_EP7312) || defined(CONFIG_ARMADILLO) |
39539887 | 305 | |
fe8c2806 WD |
306 | /* |
307 | * mask all IRQs by clearing all bits in the INTMRs | |
308 | */ | |
309 | mov r1, #0x00 | |
310 | ldr r0, INTMR1 | |
311 | str r1, [r0] | |
312 | ldr r0, INTMR2 | |
313 | str r1, [r0] | |
314 | ldr r0, INTMR3 | |
315 | str r1, [r0] | |
316 | ||
317 | /* | |
318 | * flush v4 I/D caches | |
319 | */ | |
320 | mov r0, #0 | |
321 | mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */ | |
322 | mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */ | |
323 | ||
324 | /* | |
325 | * disable MMU stuff and caches | |
326 | */ | |
327 | mrc p15,0,r0,c1,c0 | |
328 | bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS) | |
329 | bic r0, r0, #0x0000008f @ clear bits 7, 3:0 (B--- WCAM) | |
330 | orr r0, r0, #0x00000002 @ set bit 2 (A) Align | |
331 | mcr p15,0,r0,c1,c0 | |
39539887 | 332 | #elif defined(CONFIG_NETARM) |
2d1a537d WD |
333 | /* |
334 | * prior to software reset : need to set pin PORTC4 to be *HRESET | |
335 | */ | |
336 | ldr r0, =NETARM_GEN_MODULE_BASE | |
337 | ldr r1, =(NETARM_GEN_PORT_MODE(0x10) | \ | |
338 | NETARM_GEN_PORT_DIR(0x10)) | |
339 | str r1, [r0, #+NETARM_GEN_PORTC] | |
340 | /* | |
341 | * software reset : see HW Ref. Guide 8.2.4 : Software Service register | |
cdc7fea1 | 342 | * for an explanation of this process |
2d1a537d WD |
343 | */ |
344 | ldr r0, =NETARM_GEN_MODULE_BASE | |
345 | ldr r1, =NETARM_GEN_SW_SVC_RESETA | |
346 | str r1, [r0, #+NETARM_GEN_SOFTWARE_SERVICE] | |
347 | ldr r1, =NETARM_GEN_SW_SVC_RESETB | |
348 | str r1, [r0, #+NETARM_GEN_SOFTWARE_SERVICE] | |
349 | ldr r1, =NETARM_GEN_SW_SVC_RESETA | |
350 | str r1, [r0, #+NETARM_GEN_SOFTWARE_SERVICE] | |
351 | ldr r1, =NETARM_GEN_SW_SVC_RESETB | |
352 | str r1, [r0, #+NETARM_GEN_SOFTWARE_SERVICE] | |
353 | /* | |
354 | * setup PLL and System Config | |
355 | */ | |
356 | ldr r0, =NETARM_GEN_MODULE_BASE | |
357 | ||
358 | ldr r1, =( NETARM_GEN_SYS_CFG_LENDIAN | \ | |
359 | NETARM_GEN_SYS_CFG_BUSFULL | \ | |
360 | NETARM_GEN_SYS_CFG_USER_EN | \ | |
361 | NETARM_GEN_SYS_CFG_ALIGN_ABORT | \ | |
362 | NETARM_GEN_SYS_CFG_BUSARB_INT | \ | |
363 | NETARM_GEN_SYS_CFG_BUSMON_EN ) | |
364 | ||
365 | str r1, [r0, #+NETARM_GEN_SYSTEM_CONTROL] | |
366 | ||
3df5bea0 | 367 | #ifndef CONFIG_NETARM_PLL_BYPASS |
2d1a537d WD |
368 | ldr r1, =( NETARM_GEN_PLL_CTL_PLLCNT(NETARM_PLL_COUNT_VAL) | \ |
369 | NETARM_GEN_PLL_CTL_POLTST_DEF | \ | |
370 | NETARM_GEN_PLL_CTL_INDIV(1) | \ | |
371 | NETARM_GEN_PLL_CTL_ICP_DEF | \ | |
372 | NETARM_GEN_PLL_CTL_OUTDIV(2) ) | |
373 | str r1, [r0, #+NETARM_GEN_PLL_CONTROL] | |
3df5bea0 WD |
374 | #endif |
375 | ||
2d1a537d WD |
376 | /* |
377 | * mask all IRQs by clearing all bits in the INTMRs | |
378 | */ | |
379 | mov r1, #0 | |
380 | ldr r0, =NETARM_GEN_MODULE_BASE | |
381 | str r1, [r0, #+NETARM_GEN_INTR_ENABLE] | |
39539887 WD |
382 | |
383 | #elif defined(CONFIG_S3C4510B) | |
384 | ||
385 | /* | |
386 | * Mask off all IRQ sources | |
387 | */ | |
388 | ldr r1, =REG_INTMASK | |
389 | ldr r0, =0x3FFFFF | |
390 | str r0, [r1] | |
391 | ||
392 | /* | |
393 | * Disable Cache | |
394 | */ | |
395 | ldr r0, =REG_SYSCFG | |
cdc7fea1 | 396 | ldr r1, =0x83ffffa0 /* cache-disabled */ |
39539887 WD |
397 | str r1, [r0] |
398 | ||
87cb6862 WD |
399 | #elif defined(CONFIG_INTEGRATOR) && defined(CONFIG_ARCH_INTEGRATOR) |
400 | /* No specific initialisation for IntegratorAP/CM720T as yet */ | |
6bd2447e GJ |
401 | #elif defined(CONFIG_LPC2292) |
402 | /* Set-up PLL */ | |
403 | mov r3, #0xAA | |
404 | mov r4, #0x55 | |
f8db84f1 | 405 | /* First disconnect and disable the PLL */ |
6bd2447e GJ |
406 | ldr r0, PLLCON_ADR |
407 | mov r1, #0x00 | |
408 | str r1, [r0] | |
409 | ldr r0, PLLFEED_ADR /* start feed sequence */ | |
410 | str r3, [r0] | |
f8db84f1 | 411 | str r4, [r0] /* feed sequence done */ |
6bd2447e GJ |
412 | /* Set new M and P values */ |
413 | ldr r0, PLLCFG_ADR | |
414 | mov r1, #0x23 /* M=4 and P=2 */ | |
415 | str r1, [r0] | |
416 | ldr r0, PLLFEED_ADR /* start feed sequence */ | |
417 | str r3, [r0] | |
418 | str r4, [r0] /* feed sequence done */ | |
419 | /* Then enable the PLL */ | |
420 | ldr r0, PLLCON_ADR | |
421 | mov r1, #0x01 /* PLL enable bit */ | |
422 | str r1, [r0] | |
423 | ldr r0, PLLFEED_ADR /* start feed sequence */ | |
424 | str r3, [r0] | |
425 | str r4, [r0] /* feed sequence done */ | |
f8db84f1 | 426 | /* Wait for the lock */ |
6bd2447e GJ |
427 | ldr r0, PLLSTAT_ADR |
428 | mov r1, #0x400 /* lock bit */ | |
f8db84f1 | 429 | lock_loop: |
6bd2447e GJ |
430 | ldr r2, [r0] |
431 | and r2, r1, r2 | |
432 | cmp r2, #0 | |
433 | beq lock_loop | |
434 | /* And finally connect the PLL */ | |
435 | ldr r0, PLLCON_ADR | |
436 | mov r1, #0x03 /* PLL enable bit and connect bit */ | |
437 | str r1, [r0] | |
438 | ldr r0, PLLFEED_ADR /* start feed sequence */ | |
439 | str r3, [r0] | |
f8db84f1 | 440 | str r4, [r0] /* feed sequence done */ |
6bd2447e GJ |
441 | /* Set-up VPBDIV register */ |
442 | ldr r0, VPBDIV_ADR | |
443 | mov r1, #0x01 /* VPB clock is same as process clock */ | |
444 | str r1, [r0] | |
39539887 WD |
445 | #else |
446 | #error No cpu_init_crit() defined for current CPU type | |
447 | #endif | |
fe8c2806 WD |
448 | |
449 | #ifdef CONFIG_ARM7_REVD | |
450 | /* set clock speed */ | |
451 | /* !!! we run @ 36 MHz due to a hardware flaw in Rev. D processors */ | |
452 | /* !!! not doing DRAM refresh properly! */ | |
453 | ldr r0, SYSCON3 | |
454 | ldr r1, [r0] | |
455 | bic r1, r1, #CLKCTL | |
456 | orr r1, r1, #CLKCTL_36 | |
457 | str r1, [r0] | |
458 | #endif | |
459 | ||
6bd2447e | 460 | #ifndef CONFIG_LPC2292 |
87cb6862 | 461 | mov ip, lr |
fe8c2806 WD |
462 | /* |
463 | * before relocating, we have to setup RAM timing | |
f6e20fc6 | 464 | * because memory timing is board-dependent, you will |
400558b5 | 465 | * find a lowlevel_init.S in your board directory. |
fe8c2806 | 466 | */ |
400558b5 | 467 | bl lowlevel_init |
fe8c2806 | 468 | mov lr, ip |
6bd2447e | 469 | #endif |
fe8c2806 WD |
470 | |
471 | mov pc, lr | |
472 | ||
473 | ||
fe8c2806 WD |
474 | /* |
475 | ************************************************************************* | |
476 | * | |
477 | * Interrupt handling | |
478 | * | |
479 | ************************************************************************* | |
480 | */ | |
481 | ||
482 | @ | |
483 | @ IRQ stack frame. | |
484 | @ | |
485 | #define S_FRAME_SIZE 72 | |
486 | ||
487 | #define S_OLD_R0 68 | |
488 | #define S_PSR 64 | |
489 | #define S_PC 60 | |
490 | #define S_LR 56 | |
491 | #define S_SP 52 | |
492 | ||
493 | #define S_IP 48 | |
494 | #define S_FP 44 | |
495 | #define S_R10 40 | |
496 | #define S_R9 36 | |
497 | #define S_R8 32 | |
498 | #define S_R7 28 | |
499 | #define S_R6 24 | |
500 | #define S_R5 20 | |
501 | #define S_R4 16 | |
502 | #define S_R3 12 | |
503 | #define S_R2 8 | |
504 | #define S_R1 4 | |
505 | #define S_R0 0 | |
506 | ||
507 | #define MODE_SVC 0x13 | |
508 | #define I_BIT 0x80 | |
509 | ||
510 | /* | |
511 | * use bad_save_user_regs for abort/prefetch/undef/swi ... | |
512 | * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling | |
513 | */ | |
514 | ||
515 | .macro bad_save_user_regs | |
516 | sub sp, sp, #S_FRAME_SIZE | |
517 | stmia sp, {r0 - r12} @ Calling r0-r12 | |
cdc7fea1 | 518 | add r8, sp, #S_PC |
fe8c2806 | 519 | |
abef7b85 | 520 | ldr r2, IRQ_STACK_START_IN |
cdc7fea1 | 521 | ldmia r2, {r2 - r4} @ get pc, cpsr, old_r0 |
fe8c2806 WD |
522 | add r0, sp, #S_FRAME_SIZE @ restore sp_SVC |
523 | ||
524 | add r5, sp, #S_SP | |
525 | mov r1, lr | |
cdc7fea1 | 526 | stmia r5, {r0 - r4} @ save sp_SVC, lr_SVC, pc, cpsr, old_r |
fe8c2806 WD |
527 | mov r0, sp |
528 | .endm | |
529 | ||
530 | .macro irq_save_user_regs | |
531 | sub sp, sp, #S_FRAME_SIZE | |
532 | stmia sp, {r0 - r12} @ Calling r0-r12 | |
cdc7fea1 WD |
533 | add r8, sp, #S_PC |
534 | stmdb r8, {sp, lr}^ @ Calling SP, LR | |
535 | str lr, [r8, #0] @ Save calling PC | |
536 | mrs r6, spsr | |
537 | str r6, [r8, #4] @ Save CPSR | |
538 | str r0, [r8, #8] @ Save OLD_R0 | |
fe8c2806 WD |
539 | mov r0, sp |
540 | .endm | |
541 | ||
542 | .macro irq_restore_user_regs | |
543 | ldmia sp, {r0 - lr}^ @ Calling r0 - lr | |
544 | mov r0, r0 | |
545 | ldr lr, [sp, #S_PC] @ Get PC | |
546 | add sp, sp, #S_FRAME_SIZE | |
547 | subs pc, lr, #4 @ return & move spsr_svc into cpsr | |
548 | .endm | |
549 | ||
550 | .macro get_bad_stack | |
abef7b85 | 551 | ldr r13, IRQ_STACK_START_IN @ setup our mode stack |
fe8c2806 WD |
552 | |
553 | str lr, [r13] @ save caller lr / spsr | |
554 | mrs lr, spsr | |
cdc7fea1 | 555 | str lr, [r13, #4] |
fe8c2806 WD |
556 | |
557 | mov r13, #MODE_SVC @ prepare SVC-Mode | |
558 | msr spsr_c, r13 | |
559 | mov lr, pc | |
560 | movs pc, lr | |
561 | .endm | |
562 | ||
563 | .macro get_irq_stack @ setup IRQ stack | |
564 | ldr sp, IRQ_STACK_START | |
565 | .endm | |
566 | ||
567 | .macro get_fiq_stack @ setup FIQ stack | |
568 | ldr sp, FIQ_STACK_START | |
569 | .endm | |
570 | ||
571 | /* | |
572 | * exception handlers | |
573 | */ | |
cdc7fea1 | 574 | .align 5 |
fe8c2806 WD |
575 | undefined_instruction: |
576 | get_bad_stack | |
577 | bad_save_user_regs | |
cdc7fea1 | 578 | bl do_undefined_instruction |
fe8c2806 WD |
579 | |
580 | .align 5 | |
581 | software_interrupt: | |
582 | get_bad_stack | |
583 | bad_save_user_regs | |
cdc7fea1 | 584 | bl do_software_interrupt |
fe8c2806 WD |
585 | |
586 | .align 5 | |
587 | prefetch_abort: | |
588 | get_bad_stack | |
589 | bad_save_user_regs | |
cdc7fea1 | 590 | bl do_prefetch_abort |
fe8c2806 WD |
591 | |
592 | .align 5 | |
593 | data_abort: | |
594 | get_bad_stack | |
595 | bad_save_user_regs | |
cdc7fea1 | 596 | bl do_data_abort |
fe8c2806 WD |
597 | |
598 | .align 5 | |
599 | not_used: | |
600 | get_bad_stack | |
601 | bad_save_user_regs | |
cdc7fea1 | 602 | bl do_not_used |
fe8c2806 WD |
603 | |
604 | #ifdef CONFIG_USE_IRQ | |
605 | ||
606 | .align 5 | |
607 | irq: | |
608 | get_irq_stack | |
609 | irq_save_user_regs | |
cdc7fea1 | 610 | bl do_irq |
fe8c2806 WD |
611 | irq_restore_user_regs |
612 | ||
613 | .align 5 | |
614 | fiq: | |
615 | get_fiq_stack | |
616 | /* someone ought to write a more effiction fiq_save_user_regs */ | |
617 | irq_save_user_regs | |
cdc7fea1 | 618 | bl do_fiq |
fe8c2806 WD |
619 | irq_restore_user_regs |
620 | ||
621 | #else | |
622 | ||
623 | .align 5 | |
624 | irq: | |
625 | get_bad_stack | |
626 | bad_save_user_regs | |
cdc7fea1 | 627 | bl do_irq |
fe8c2806 WD |
628 | |
629 | .align 5 | |
630 | fiq: | |
631 | get_bad_stack | |
632 | bad_save_user_regs | |
cdc7fea1 | 633 | bl do_fiq |
fe8c2806 WD |
634 | |
635 | #endif | |
636 | ||
c570b2fd | 637 | #if defined(CONFIG_IMPA7) || defined(CONFIG_EP7312) || defined(CONFIG_ARMADILLO) |
fe8c2806 WD |
638 | .align 5 |
639 | .globl reset_cpu | |
640 | reset_cpu: | |
cdc7fea1 WD |
641 | mov ip, #0 |
642 | mcr p15, 0, ip, c7, c7, 0 @ invalidate cache | |
643 | mcr p15, 0, ip, c8, c7, 0 @ flush TLB (v4) | |
644 | mrc p15, 0, ip, c1, c0, 0 @ get ctrl register | |
645 | bic ip, ip, #0x000f @ ............wcam | |
646 | bic ip, ip, #0x2100 @ ..v....s........ | |
647 | mcr p15, 0, ip, c1, c0, 0 @ ctrl register | |
648 | mov pc, r0 | |
39539887 WD |
649 | #elif defined(CONFIG_NETARM) |
650 | .align 5 | |
651 | .globl reset_cpu | |
652 | reset_cpu: | |
2d1a537d WD |
653 | ldr r1, =NETARM_MEM_MODULE_BASE |
654 | ldr r0, [r1, #+NETARM_MEM_CS0_BASE_ADDR] | |
655 | ldr r1, =0xFFFFF000 | |
656 | and r0, r1, r0 | |
14d0a02a | 657 | ldr r1, =(relocate-CONFIG_SYS_TEXT_BASE) |
2d1a537d WD |
658 | add r0, r1, r0 |
659 | ldr r4, =NETARM_GEN_MODULE_BASE | |
660 | ldr r1, =NETARM_GEN_SW_SVC_RESETA | |
661 | str r1, [r4, #+NETARM_GEN_SOFTWARE_SERVICE] | |
662 | ldr r1, =NETARM_GEN_SW_SVC_RESETB | |
663 | str r1, [r4, #+NETARM_GEN_SOFTWARE_SERVICE] | |
664 | ldr r1, =NETARM_GEN_SW_SVC_RESETA | |
665 | str r1, [r4, #+NETARM_GEN_SOFTWARE_SERVICE] | |
666 | ldr r1, =NETARM_GEN_SW_SVC_RESETB | |
667 | str r1, [r4, #+NETARM_GEN_SOFTWARE_SERVICE] | |
668 | mov pc, r0 | |
39539887 WD |
669 | #elif defined(CONFIG_S3C4510B) |
670 | /* Nothing done here as reseting the CPU is board specific, depending | |
671 | * on external peripherals such as watchdog timers, etc. */ | |
87cb6862 WD |
672 | #elif defined(CONFIG_INTEGRATOR) && defined(CONFIG_ARCH_INTEGRATOR) |
673 | /* No specific reset actions for IntegratorAP/CM720T as yet */ | |
6bd2447e GJ |
674 | #elif defined(CONFIG_LPC2292) |
675 | .align 5 | |
676 | .globl reset_cpu | |
677 | reset_cpu: | |
678 | mov pc, r0 | |
39539887 WD |
679 | #else |
680 | #error No reset_cpu() defined for current CPU type | |
2d1a537d | 681 | #endif |