blob: 46050dab6e9bca9f4b2435274b81725afdabb568 [file] [log] [blame]
wdenkfe8c2802002-11-03 00:38:21 +00001/*
2 * armboot - Startup Code for ARM720 CPU-core
3 *
4 * Copyright (c) 2001 Marius Gröger <mag@sysgo.de>
5 * Copyright (c) 2002 Alex Züpke <azu@sysgo.de>
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
wdenkcdc7fea2004-07-11 22:27:55 +000017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
wdenkfe8c2802002-11-03 00:38:21 +000018 * 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
Wolfgang Denk25ddd1f2010-10-26 14:34:52 +020026#include <asm-offsets.h>
wdenkfe8c2802002-11-03 00:38:21 +000027#include <config.h>
28#include <version.h>
wdenk39539882004-07-01 16:30:44 +000029#include <asm/hardware.h>
wdenkfe8c2802002-11-03 00:38:21 +000030
31/*
32 *************************************************************************
33 *
34 * Jump vector table as in table 3.1 in [1]
35 *
36 *************************************************************************
37 */
38
39
40.globl _start
wdenkcdc7fea2004-07-11 22:27:55 +000041_start: b reset
wdenkfe8c2802002-11-03 00:38:21 +000042 ldr pc, _undefined_instruction
43 ldr pc, _software_interrupt
44 ldr pc, _prefetch_abort
45 ldr pc, _data_abort
Gary Jennejohn6bd24472007-01-24 12:16:56 +010046#ifdef CONFIG_LPC2292
47 .word 0xB4405F76 /* 2's complement of the checksum of the vectors */
48#else
wdenkfe8c2802002-11-03 00:38:21 +000049 ldr pc, _not_used
Gary Jennejohn6bd24472007-01-24 12:16:56 +010050#endif
wdenkfe8c2802002-11-03 00:38:21 +000051 ldr pc, _irq
52 ldr pc, _fiq
53
wdenkcdc7fea2004-07-11 22:27:55 +000054_undefined_instruction: .word undefined_instruction
wdenkfe8c2802002-11-03 00:38:21 +000055_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 *
wdenkf6e20fc2004-02-08 19:38:38 +000070 * do important init only if we don't start from RAM!
wdenkfe8c2802002-11-03 00:38:21 +000071 * relocate armboot to ram
72 * setup stack
73 * jump to second stage
74 *
75 *************************************************************************
76 */
77
Heiko Schocherabef7b82010-09-17 13:10:52 +020078.globl _TEXT_BASE
wdenkfe8c2802002-11-03 00:38:21 +000079_TEXT_BASE:
Wolfgang Denk14d0a022010-10-07 21:51:12 +020080 .word CONFIG_SYS_TEXT_BASE
wdenkfe8c2802002-11-03 00:38:21 +000081
wdenkfe8c2802002-11-03 00:38:21 +000082/*
wdenkf6e20fc2004-02-08 19:38:38 +000083 * These are defined in the board-specific linker script.
Albert Aribaud3336ca62010-11-25 22:45:02 +010084 * Subtracting _start from them lets the linker put their
85 * relative position in the executable instead of leaving
86 * them null.
wdenkfe8c2802002-11-03 00:38:21 +000087 */
Albert Aribaud3336ca62010-11-25 22:45:02 +010088.globl _bss_start_ofs
89_bss_start_ofs:
90 .word __bss_start - _start
wdenkf6e20fc2004-02-08 19:38:38 +000091
Albert Aribaud3336ca62010-11-25 22:45:02 +010092.globl _bss_end_ofs
93_bss_end_ofs:
94 .word _end - _start
wdenkfe8c2802002-11-03 00:38:21 +000095
wdenkfe8c2802002-11-03 00:38:21 +000096#ifdef CONFIG_USE_IRQ
97/* IRQ stack memory (calculated at run-time) */
98.globl IRQ_STACK_START
99IRQ_STACK_START:
100 .word 0x0badc0de
101
102/* IRQ stack memory (calculated at run-time) */
103.globl FIQ_STACK_START
104FIQ_STACK_START:
105 .word 0x0badc0de
106#endif
107
Heiko Schocherabef7b82010-09-17 13:10:52 +0200108/* IRQ stack memory (calculated at run-time) + 8 bytes */
109.globl IRQ_STACK_START_IN
110IRQ_STACK_START_IN:
111 .word 0x0badc0de
112
Heiko Schocherabef7b82010-09-17 13:10:52 +0200113/*
114 * the actual reset code
115 */
116
117reset:
118 /*
119 * set the cpu to SVC32 mode
120 */
121 mrs r0,cpsr
122 bic r0,r0,#0x1f
123 orr r0,r0,#0xd3
124 msr cpsr,r0
125
126 /*
127 * we do sys-critical inits only at reboot,
128 * not when booting from ram!
129 */
130#ifndef CONFIG_SKIP_LOWLEVEL_INIT
131 bl cpu_init_crit
132#endif
133
134#ifdef CONFIG_LPC2292
135 bl lowlevel_init
136#endif
137
138/* Set stackpointer in internal RAM to call board_init_f */
139call_board_init_f:
140 ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)
141 ldr r0,=0x00000000
142 bl board_init_f
143
144/*------------------------------------------------------------------------------*/
145
146/*
147 * void relocate_code (addr_sp, gd, addr_moni)
148 *
149 * This "function" does not return, instead it continues in RAM
150 * after relocating the monitor code.
151 *
152 */
153 .globl relocate_code
154relocate_code:
155 mov r4, r0 /* save addr_sp */
156 mov r5, r1 /* save addr of gd */
157 mov r6, r2 /* save addr of destination */
158 mov r7, r2 /* save addr of destination */
159
160 /* Set up the stack */
161stack_setup:
162 mov sp, r4
163
164 adr r0, _start
165 ldr r2, _TEXT_BASE
Albert Aribaud3336ca62010-11-25 22:45:02 +0100166 ldr r3, _bss_start_ofs
167 add r2, r0, r3 /* r2 <- source end address */
Heiko Schocherabef7b82010-09-17 13:10:52 +0200168 cmp r0, r6
169 beq clear_bss
170
Heiko Schocherabef7b82010-09-17 13:10:52 +0200171copy_loop:
172 ldmia r0!, {r9-r10} /* copy from source address [r0] */
173 stmia r6!, {r9-r10} /* copy to target address [r1] */
Albert Aribaudda90d4c2010-10-05 16:06:39 +0200174 cmp r0, r2 /* until source end address [r2] */
175 blo copy_loop
Heiko Schocherabef7b82010-09-17 13:10:52 +0200176
177#ifndef CONFIG_PRELOADER
Albert Aribaud3336ca62010-11-25 22:45:02 +0100178 /*
179 * fix .rel.dyn relocations
180 */
181 ldr r0, _TEXT_BASE /* r0 <- Text base */
182 sub r9, r7, r0 /* r9 <- relocation offset */
183 ldr r10, _dynsym_start_ofs /* r10 <- sym table ofs */
184 add r10, r10, r0 /* r10 <- sym table in FLASH */
185 ldr r2, _rel_dyn_start_ofs /* r2 <- rel dyn start ofs */
186 add r2, r2, r0 /* r2 <- rel dyn start in FLASH */
187 ldr r3, _rel_dyn_end_ofs /* r3 <- rel dyn end ofs */
188 add r3, r3, r0 /* r3 <- rel dyn end in FLASH */
Heiko Schocherabef7b82010-09-17 13:10:52 +0200189fixloop:
Albert Aribaud3336ca62010-11-25 22:45:02 +0100190 ldr r0, [r2] /* r0 <- location to fix up, IN FLASH! */
191 add r0, r0, r9 /* r0 <- location to fix up in RAM */
192 ldr r1, [r2, #4]
193 and r8, r1, #0xff
194 cmp r8, #23 /* relative fixup? */
195 beq fixrel
196 cmp r8, #2 /* absolute fixup? */
197 beq fixabs
198 /* ignore unknown type of fixup */
199 b fixnext
200fixabs:
201 /* absolute fix: set location to (offset) symbol value */
202 mov r1, r1, LSR #4 /* r1 <- symbol index in .dynsym */
203 add r1, r10, r1 /* r1 <- address of symbol in table */
204 ldr r1, [r1, #4] /* r1 <- symbol value */
205 add r1, r9 /* r1 <- relocated sym addr */
206 b fixnext
207fixrel:
208 /* relative fix: increase location by offset */
209 ldr r1, [r0]
210 add r1, r1, r9
211fixnext:
212 str r1, [r0]
213 add r2, r2, #8 /* each rel.dyn entry is 8 bytes */
Heiko Schocherabef7b82010-09-17 13:10:52 +0200214 cmp r2, r3
Wolfgang Denk79e63132010-10-23 23:22:38 +0200215 blo fixloop
Heiko Schocherabef7b82010-09-17 13:10:52 +0200216#endif
Heiko Schocherabef7b82010-09-17 13:10:52 +0200217
218clear_bss:
219#ifndef CONFIG_PRELOADER
Albert Aribaud3336ca62010-11-25 22:45:02 +0100220 ldr r0, _bss_start_ofs
221 ldr r1, _bss_end_ofs
Heiko Schocherabef7b82010-09-17 13:10:52 +0200222 ldr r3, _TEXT_BASE /* Text base */
223 mov r4, r7 /* reloc addr */
Heiko Schocherabef7b82010-09-17 13:10:52 +0200224 add r0, r0, r4
Heiko Schocherabef7b82010-09-17 13:10:52 +0200225 add r1, r1, r4
226 mov r2, #0x00000000 /* clear */
227
228clbss_l:str r2, [r0] /* clear loop... */
229 add r0, r0, #4
230 cmp r0, r1
231 bne clbss_l
232
233 bl coloured_LED_init
234 bl red_LED_on
235#endif
236
237/*
238 * We are done. Do not return, instead branch to second part of board
239 * initialization, now running from RAM.
240 */
Albert Aribaud3336ca62010-11-25 22:45:02 +0100241 ldr r0, _board_init_r_ofs
242 adr r1, _start
243 add lr, r0, r1
244 add lr, lr, r9
Heiko Schocherabef7b82010-09-17 13:10:52 +0200245 /* setup parameters for board_init_r */
246 mov r0, r5 /* gd_t */
247 mov r1, r7 /* dest_addr */
248 /* jump to it ... */
Heiko Schocherabef7b82010-09-17 13:10:52 +0200249 mov pc, lr
250
Albert Aribaud3336ca62010-11-25 22:45:02 +0100251_board_init_r_ofs:
252 .word board_init_r - _start
253
254_rel_dyn_start_ofs:
255 .word __rel_dyn_start - _start
256_rel_dyn_end_ofs:
257 .word __rel_dyn_end - _start
258_dynsym_start_ofs:
259 .word __dynsym_start - _start
Heiko Schocherabef7b82010-09-17 13:10:52 +0200260
wdenkfe8c2802002-11-03 00:38:21 +0000261/*
262 *************************************************************************
263 *
264 * CPU_init_critical registers
265 *
266 * setup important registers
267 * setup memory timing
268 *
269 *************************************************************************
270 */
271
Wolfgang Denkc570b2f2005-09-26 01:06:33 +0200272#if defined(CONFIG_IMPA7) || defined(CONFIG_EP7312) || defined(CONFIG_ARMADILLO)
wdenkfe8c2802002-11-03 00:38:21 +0000273
274/* Interupt-Controller base addresses */
275INTMR1: .word 0x80000280 @ 32 bit size
276INTMR2: .word 0x80001280 @ 16 bit size
277INTMR3: .word 0x80002280 @ 8 bit size
278
279/* SYSCONs */
280SYSCON1: .word 0x80000100
281SYSCON2: .word 0x80001100
282SYSCON3: .word 0x80002200
283
284#define CLKCTL 0x6 /* mask */
285#define CLKCTL_18 0x0 /* 18.432 MHz */
286#define CLKCTL_36 0x2 /* 36.864 MHz */
287#define CLKCTL_49 0x4 /* 49.152 MHz */
288#define CLKCTL_73 0x6 /* 73.728 MHz */
289
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100290#elif defined(CONFIG_LPC2292)
291PLLCFG_ADR: .word PLLCFG
292PLLFEED_ADR: .word PLLFEED
293PLLCON_ADR: .word PLLCON
294PLLSTAT_ADR: .word PLLSTAT
295VPBDIV_ADR: .word VPBDIV
296MEMMAP_ADR: .word MEMMAP
297
wdenk39539882004-07-01 16:30:44 +0000298#endif
299
wdenkfe8c2802002-11-03 00:38:21 +0000300cpu_init_crit:
Wolfgang Denkc570b2f2005-09-26 01:06:33 +0200301#if defined(CONFIG_IMPA7) || defined(CONFIG_EP7312) || defined(CONFIG_ARMADILLO)
wdenk39539882004-07-01 16:30:44 +0000302
wdenkfe8c2802002-11-03 00:38:21 +0000303 /*
304 * mask all IRQs by clearing all bits in the INTMRs
305 */
306 mov r1, #0x00
307 ldr r0, INTMR1
308 str r1, [r0]
309 ldr r0, INTMR2
310 str r1, [r0]
311 ldr r0, INTMR3
312 str r1, [r0]
313
314 /*
315 * flush v4 I/D caches
316 */
317 mov r0, #0
318 mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */
319 mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */
320
321 /*
322 * disable MMU stuff and caches
323 */
324 mrc p15,0,r0,c1,c0
325 bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS)
326 bic r0, r0, #0x0000008f @ clear bits 7, 3:0 (B--- WCAM)
327 orr r0, r0, #0x00000002 @ set bit 2 (A) Align
328 mcr p15,0,r0,c1,c0
wdenk39539882004-07-01 16:30:44 +0000329#elif defined(CONFIG_NETARM)
wdenk2d1a5372004-02-23 19:30:57 +0000330 /*
331 * prior to software reset : need to set pin PORTC4 to be *HRESET
332 */
333 ldr r0, =NETARM_GEN_MODULE_BASE
334 ldr r1, =(NETARM_GEN_PORT_MODE(0x10) | \
335 NETARM_GEN_PORT_DIR(0x10))
336 str r1, [r0, #+NETARM_GEN_PORTC]
337 /*
338 * software reset : see HW Ref. Guide 8.2.4 : Software Service register
wdenkcdc7fea2004-07-11 22:27:55 +0000339 * for an explanation of this process
wdenk2d1a5372004-02-23 19:30:57 +0000340 */
341 ldr r0, =NETARM_GEN_MODULE_BASE
342 ldr r1, =NETARM_GEN_SW_SVC_RESETA
343 str r1, [r0, #+NETARM_GEN_SOFTWARE_SERVICE]
344 ldr r1, =NETARM_GEN_SW_SVC_RESETB
345 str r1, [r0, #+NETARM_GEN_SOFTWARE_SERVICE]
346 ldr r1, =NETARM_GEN_SW_SVC_RESETA
347 str r1, [r0, #+NETARM_GEN_SOFTWARE_SERVICE]
348 ldr r1, =NETARM_GEN_SW_SVC_RESETB
349 str r1, [r0, #+NETARM_GEN_SOFTWARE_SERVICE]
350 /*
351 * setup PLL and System Config
352 */
353 ldr r0, =NETARM_GEN_MODULE_BASE
354
355 ldr r1, =( NETARM_GEN_SYS_CFG_LENDIAN | \
356 NETARM_GEN_SYS_CFG_BUSFULL | \
357 NETARM_GEN_SYS_CFG_USER_EN | \
358 NETARM_GEN_SYS_CFG_ALIGN_ABORT | \
359 NETARM_GEN_SYS_CFG_BUSARB_INT | \
360 NETARM_GEN_SYS_CFG_BUSMON_EN )
361
362 str r1, [r0, #+NETARM_GEN_SYSTEM_CONTROL]
363
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200364#ifndef CONFIG_NETARM_PLL_BYPASS
wdenk2d1a5372004-02-23 19:30:57 +0000365 ldr r1, =( NETARM_GEN_PLL_CTL_PLLCNT(NETARM_PLL_COUNT_VAL) | \
366 NETARM_GEN_PLL_CTL_POLTST_DEF | \
367 NETARM_GEN_PLL_CTL_INDIV(1) | \
368 NETARM_GEN_PLL_CTL_ICP_DEF | \
369 NETARM_GEN_PLL_CTL_OUTDIV(2) )
370 str r1, [r0, #+NETARM_GEN_PLL_CONTROL]
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200371#endif
372
wdenk2d1a5372004-02-23 19:30:57 +0000373 /*
374 * mask all IRQs by clearing all bits in the INTMRs
375 */
376 mov r1, #0
377 ldr r0, =NETARM_GEN_MODULE_BASE
378 str r1, [r0, #+NETARM_GEN_INTR_ENABLE]
wdenk39539882004-07-01 16:30:44 +0000379
380#elif defined(CONFIG_S3C4510B)
381
382 /*
383 * Mask off all IRQ sources
384 */
385 ldr r1, =REG_INTMASK
386 ldr r0, =0x3FFFFF
387 str r0, [r1]
388
389 /*
390 * Disable Cache
391 */
392 ldr r0, =REG_SYSCFG
wdenkcdc7fea2004-07-11 22:27:55 +0000393 ldr r1, =0x83ffffa0 /* cache-disabled */
wdenk39539882004-07-01 16:30:44 +0000394 str r1, [r0]
395
Wolfgang Denk87cb6862005-10-06 17:08:18 +0200396#elif defined(CONFIG_INTEGRATOR) && defined(CONFIG_ARCH_INTEGRATOR)
397 /* No specific initialisation for IntegratorAP/CM720T as yet */
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100398#elif defined(CONFIG_LPC2292)
399 /* Set-up PLL */
400 mov r3, #0xAA
401 mov r4, #0x55
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100402 /* First disconnect and disable the PLL */
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100403 ldr r0, PLLCON_ADR
404 mov r1, #0x00
405 str r1, [r0]
406 ldr r0, PLLFEED_ADR /* start feed sequence */
407 str r3, [r0]
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100408 str r4, [r0] /* feed sequence done */
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100409 /* Set new M and P values */
410 ldr r0, PLLCFG_ADR
411 mov r1, #0x23 /* M=4 and P=2 */
412 str r1, [r0]
413 ldr r0, PLLFEED_ADR /* start feed sequence */
414 str r3, [r0]
415 str r4, [r0] /* feed sequence done */
416 /* Then enable the PLL */
417 ldr r0, PLLCON_ADR
418 mov r1, #0x01 /* PLL enable bit */
419 str r1, [r0]
420 ldr r0, PLLFEED_ADR /* start feed sequence */
421 str r3, [r0]
422 str r4, [r0] /* feed sequence done */
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100423 /* Wait for the lock */
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100424 ldr r0, PLLSTAT_ADR
425 mov r1, #0x400 /* lock bit */
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100426lock_loop:
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100427 ldr r2, [r0]
428 and r2, r1, r2
429 cmp r2, #0
430 beq lock_loop
431 /* And finally connect the PLL */
432 ldr r0, PLLCON_ADR
433 mov r1, #0x03 /* PLL enable bit and connect bit */
434 str r1, [r0]
435 ldr r0, PLLFEED_ADR /* start feed sequence */
436 str r3, [r0]
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100437 str r4, [r0] /* feed sequence done */
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100438 /* Set-up VPBDIV register */
439 ldr r0, VPBDIV_ADR
440 mov r1, #0x01 /* VPB clock is same as process clock */
441 str r1, [r0]
wdenk39539882004-07-01 16:30:44 +0000442#else
443#error No cpu_init_crit() defined for current CPU type
444#endif
wdenkfe8c2802002-11-03 00:38:21 +0000445
446#ifdef CONFIG_ARM7_REVD
447 /* set clock speed */
448 /* !!! we run @ 36 MHz due to a hardware flaw in Rev. D processors */
449 /* !!! not doing DRAM refresh properly! */
450 ldr r0, SYSCON3
451 ldr r1, [r0]
452 bic r1, r1, #CLKCTL
453 orr r1, r1, #CLKCTL_36
454 str r1, [r0]
455#endif
456
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100457#ifndef CONFIG_LPC2292
Wolfgang Denk87cb6862005-10-06 17:08:18 +0200458 mov ip, lr
wdenkfe8c2802002-11-03 00:38:21 +0000459 /*
460 * before relocating, we have to setup RAM timing
wdenkf6e20fc2004-02-08 19:38:38 +0000461 * because memory timing is board-dependent, you will
wdenk400558b2005-04-02 23:52:25 +0000462 * find a lowlevel_init.S in your board directory.
wdenkfe8c2802002-11-03 00:38:21 +0000463 */
wdenk400558b2005-04-02 23:52:25 +0000464 bl lowlevel_init
wdenkfe8c2802002-11-03 00:38:21 +0000465 mov lr, ip
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100466#endif
wdenkfe8c2802002-11-03 00:38:21 +0000467
468 mov pc, lr
469
470
wdenkfe8c2802002-11-03 00:38:21 +0000471/*
472 *************************************************************************
473 *
474 * Interrupt handling
475 *
476 *************************************************************************
477 */
478
479@
480@ IRQ stack frame.
481@
482#define S_FRAME_SIZE 72
483
484#define S_OLD_R0 68
485#define S_PSR 64
486#define S_PC 60
487#define S_LR 56
488#define S_SP 52
489
490#define S_IP 48
491#define S_FP 44
492#define S_R10 40
493#define S_R9 36
494#define S_R8 32
495#define S_R7 28
496#define S_R6 24
497#define S_R5 20
498#define S_R4 16
499#define S_R3 12
500#define S_R2 8
501#define S_R1 4
502#define S_R0 0
503
504#define MODE_SVC 0x13
505#define I_BIT 0x80
506
507/*
508 * use bad_save_user_regs for abort/prefetch/undef/swi ...
509 * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
510 */
511
512 .macro bad_save_user_regs
513 sub sp, sp, #S_FRAME_SIZE
514 stmia sp, {r0 - r12} @ Calling r0-r12
wdenkcdc7fea2004-07-11 22:27:55 +0000515 add r8, sp, #S_PC
wdenkfe8c2802002-11-03 00:38:21 +0000516
Heiko Schocherabef7b82010-09-17 13:10:52 +0200517 ldr r2, IRQ_STACK_START_IN
wdenkcdc7fea2004-07-11 22:27:55 +0000518 ldmia r2, {r2 - r4} @ get pc, cpsr, old_r0
wdenkfe8c2802002-11-03 00:38:21 +0000519 add r0, sp, #S_FRAME_SIZE @ restore sp_SVC
520
521 add r5, sp, #S_SP
522 mov r1, lr
wdenkcdc7fea2004-07-11 22:27:55 +0000523 stmia r5, {r0 - r4} @ save sp_SVC, lr_SVC, pc, cpsr, old_r
wdenkfe8c2802002-11-03 00:38:21 +0000524 mov r0, sp
525 .endm
526
527 .macro irq_save_user_regs
528 sub sp, sp, #S_FRAME_SIZE
529 stmia sp, {r0 - r12} @ Calling r0-r12
wdenkcdc7fea2004-07-11 22:27:55 +0000530 add r8, sp, #S_PC
531 stmdb r8, {sp, lr}^ @ Calling SP, LR
532 str lr, [r8, #0] @ Save calling PC
533 mrs r6, spsr
534 str r6, [r8, #4] @ Save CPSR
535 str r0, [r8, #8] @ Save OLD_R0
wdenkfe8c2802002-11-03 00:38:21 +0000536 mov r0, sp
537 .endm
538
539 .macro irq_restore_user_regs
540 ldmia sp, {r0 - lr}^ @ Calling r0 - lr
541 mov r0, r0
542 ldr lr, [sp, #S_PC] @ Get PC
543 add sp, sp, #S_FRAME_SIZE
544 subs pc, lr, #4 @ return & move spsr_svc into cpsr
545 .endm
546
547 .macro get_bad_stack
Heiko Schocherabef7b82010-09-17 13:10:52 +0200548 ldr r13, IRQ_STACK_START_IN @ setup our mode stack
wdenkfe8c2802002-11-03 00:38:21 +0000549
550 str lr, [r13] @ save caller lr / spsr
551 mrs lr, spsr
wdenkcdc7fea2004-07-11 22:27:55 +0000552 str lr, [r13, #4]
wdenkfe8c2802002-11-03 00:38:21 +0000553
554 mov r13, #MODE_SVC @ prepare SVC-Mode
555 msr spsr_c, r13
556 mov lr, pc
557 movs pc, lr
558 .endm
559
560 .macro get_irq_stack @ setup IRQ stack
561 ldr sp, IRQ_STACK_START
562 .endm
563
564 .macro get_fiq_stack @ setup FIQ stack
565 ldr sp, FIQ_STACK_START
566 .endm
567
568/*
569 * exception handlers
570 */
wdenkcdc7fea2004-07-11 22:27:55 +0000571 .align 5
wdenkfe8c2802002-11-03 00:38:21 +0000572undefined_instruction:
573 get_bad_stack
574 bad_save_user_regs
wdenkcdc7fea2004-07-11 22:27:55 +0000575 bl do_undefined_instruction
wdenkfe8c2802002-11-03 00:38:21 +0000576
577 .align 5
578software_interrupt:
579 get_bad_stack
580 bad_save_user_regs
wdenkcdc7fea2004-07-11 22:27:55 +0000581 bl do_software_interrupt
wdenkfe8c2802002-11-03 00:38:21 +0000582
583 .align 5
584prefetch_abort:
585 get_bad_stack
586 bad_save_user_regs
wdenkcdc7fea2004-07-11 22:27:55 +0000587 bl do_prefetch_abort
wdenkfe8c2802002-11-03 00:38:21 +0000588
589 .align 5
590data_abort:
591 get_bad_stack
592 bad_save_user_regs
wdenkcdc7fea2004-07-11 22:27:55 +0000593 bl do_data_abort
wdenkfe8c2802002-11-03 00:38:21 +0000594
595 .align 5
596not_used:
597 get_bad_stack
598 bad_save_user_regs
wdenkcdc7fea2004-07-11 22:27:55 +0000599 bl do_not_used
wdenkfe8c2802002-11-03 00:38:21 +0000600
601#ifdef CONFIG_USE_IRQ
602
603 .align 5
604irq:
605 get_irq_stack
606 irq_save_user_regs
wdenkcdc7fea2004-07-11 22:27:55 +0000607 bl do_irq
wdenkfe8c2802002-11-03 00:38:21 +0000608 irq_restore_user_regs
609
610 .align 5
611fiq:
612 get_fiq_stack
613 /* someone ought to write a more effiction fiq_save_user_regs */
614 irq_save_user_regs
wdenkcdc7fea2004-07-11 22:27:55 +0000615 bl do_fiq
wdenkfe8c2802002-11-03 00:38:21 +0000616 irq_restore_user_regs
617
618#else
619
620 .align 5
621irq:
622 get_bad_stack
623 bad_save_user_regs
wdenkcdc7fea2004-07-11 22:27:55 +0000624 bl do_irq
wdenkfe8c2802002-11-03 00:38:21 +0000625
626 .align 5
627fiq:
628 get_bad_stack
629 bad_save_user_regs
wdenkcdc7fea2004-07-11 22:27:55 +0000630 bl do_fiq
wdenkfe8c2802002-11-03 00:38:21 +0000631
632#endif
633
Wolfgang Denkc570b2f2005-09-26 01:06:33 +0200634#if defined(CONFIG_IMPA7) || defined(CONFIG_EP7312) || defined(CONFIG_ARMADILLO)
wdenkfe8c2802002-11-03 00:38:21 +0000635 .align 5
636.globl reset_cpu
637reset_cpu:
wdenkcdc7fea2004-07-11 22:27:55 +0000638 mov ip, #0
639 mcr p15, 0, ip, c7, c7, 0 @ invalidate cache
640 mcr p15, 0, ip, c8, c7, 0 @ flush TLB (v4)
641 mrc p15, 0, ip, c1, c0, 0 @ get ctrl register
642 bic ip, ip, #0x000f @ ............wcam
643 bic ip, ip, #0x2100 @ ..v....s........
644 mcr p15, 0, ip, c1, c0, 0 @ ctrl register
645 mov pc, r0
wdenk39539882004-07-01 16:30:44 +0000646#elif defined(CONFIG_NETARM)
647 .align 5
648.globl reset_cpu
649reset_cpu:
wdenk2d1a5372004-02-23 19:30:57 +0000650 ldr r1, =NETARM_MEM_MODULE_BASE
651 ldr r0, [r1, #+NETARM_MEM_CS0_BASE_ADDR]
652 ldr r1, =0xFFFFF000
653 and r0, r1, r0
Wolfgang Denk14d0a022010-10-07 21:51:12 +0200654 ldr r1, =(relocate-CONFIG_SYS_TEXT_BASE)
wdenk2d1a5372004-02-23 19:30:57 +0000655 add r0, r1, r0
656 ldr r4, =NETARM_GEN_MODULE_BASE
657 ldr r1, =NETARM_GEN_SW_SVC_RESETA
658 str r1, [r4, #+NETARM_GEN_SOFTWARE_SERVICE]
659 ldr r1, =NETARM_GEN_SW_SVC_RESETB
660 str r1, [r4, #+NETARM_GEN_SOFTWARE_SERVICE]
661 ldr r1, =NETARM_GEN_SW_SVC_RESETA
662 str r1, [r4, #+NETARM_GEN_SOFTWARE_SERVICE]
663 ldr r1, =NETARM_GEN_SW_SVC_RESETB
664 str r1, [r4, #+NETARM_GEN_SOFTWARE_SERVICE]
665 mov pc, r0
wdenk39539882004-07-01 16:30:44 +0000666#elif defined(CONFIG_S3C4510B)
667/* Nothing done here as reseting the CPU is board specific, depending
668 * on external peripherals such as watchdog timers, etc. */
Wolfgang Denk87cb6862005-10-06 17:08:18 +0200669#elif defined(CONFIG_INTEGRATOR) && defined(CONFIG_ARCH_INTEGRATOR)
670 /* No specific reset actions for IntegratorAP/CM720T as yet */
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100671#elif defined(CONFIG_LPC2292)
672 .align 5
673.globl reset_cpu
674reset_cpu:
675 mov pc, r0
wdenk39539882004-07-01 16:30:44 +0000676#else
677#error No reset_cpu() defined for current CPU type
wdenk2d1a5372004-02-23 19:30:57 +0000678#endif