blob: c0981185f6327112c4a1c77842d8f63a2eca1906 [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)
Heiko Schocher296cae72010-11-12 07:53:55 +0100141 bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
Heiko Schocherabef7b82010-09-17 13:10:52 +0200142 ldr r0,=0x00000000
143 bl board_init_f
144
145/*------------------------------------------------------------------------------*/
146
147/*
148 * void relocate_code (addr_sp, gd, addr_moni)
149 *
150 * This "function" does not return, instead it continues in RAM
151 * after relocating the monitor code.
152 *
153 */
154 .globl relocate_code
155relocate_code:
156 mov r4, r0 /* save addr_sp */
157 mov r5, r1 /* save addr of gd */
158 mov r6, r2 /* save addr of destination */
Heiko Schocherabef7b82010-09-17 13:10:52 +0200159
160 /* Set up the stack */
161stack_setup:
162 mov sp, r4
163
164 adr r0, _start
Andreas Bießmanna1a47d32010-12-01 00:58:34 +0100165 cmp r0, r6
166 beq clear_bss /* skip relocation */
Andreas Bießmanna78fb682010-12-01 00:58:33 +0100167 mov r1, r6 /* r1 <- scratch for copy_loop */
Albert Aribaud3336ca62010-11-25 22:45:02 +0100168 ldr r3, _bss_start_ofs
169 add r2, r0, r3 /* r2 <- source end address */
Heiko Schocherabef7b82010-09-17 13:10:52 +0200170
Heiko Schocherabef7b82010-09-17 13:10:52 +0200171copy_loop:
172 ldmia r0!, {r9-r10} /* copy from source address [r0] */
Andreas Bießmanna78fb682010-12-01 00:58:33 +0100173 stmia r1!, {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 */
Andreas Bießmanna78fb682010-12-01 00:58:33 +0100182 sub r9, r6, r0 /* r9 <- relocation offset */
Albert Aribaud3336ca62010-11-25 22:45:02 +0100183 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]
Andreas Bießmann1f52d892010-12-01 00:58:35 +0100193 and r7, r1, #0xff
194 cmp r7, #23 /* relative fixup? */
Albert Aribaud3336ca62010-11-25 22:45:02 +0100195 beq fixrel
Andreas Bießmann1f52d892010-12-01 00:58:35 +0100196 cmp r7, #2 /* absolute fixup? */
Albert Aribaud3336ca62010-11-25 22:45:02 +0100197 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 */
Wolfgang Denk36009452010-12-09 11:26:24 +0100205 add r1, r1, r9 /* r1 <- relocated sym addr */
Albert Aribaud3336ca62010-11-25 22:45:02 +0100206 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
Andreas Bießmanna78fb682010-12-01 00:58:33 +0100222 mov r4, r6 /* reloc addr */
Heiko Schocherabef7b82010-09-17 13:10:52 +0200223 add r0, r0, r4
Heiko Schocherabef7b82010-09-17 13:10:52 +0200224 add r1, r1, r4
225 mov r2, #0x00000000 /* clear */
226
227clbss_l:str r2, [r0] /* clear loop... */
228 add r0, r0, #4
229 cmp r0, r1
230 bne clbss_l
231
232 bl coloured_LED_init
233 bl red_LED_on
234#endif
235
236/*
237 * We are done. Do not return, instead branch to second part of board
238 * initialization, now running from RAM.
239 */
Albert Aribaud3336ca62010-11-25 22:45:02 +0100240 ldr r0, _board_init_r_ofs
241 adr r1, _start
242 add lr, r0, r1
243 add lr, lr, r9
Heiko Schocherabef7b82010-09-17 13:10:52 +0200244 /* setup parameters for board_init_r */
245 mov r0, r5 /* gd_t */
Andreas Bießmanna78fb682010-12-01 00:58:33 +0100246 mov r1, r6 /* dest_addr */
Heiko Schocherabef7b82010-09-17 13:10:52 +0200247 /* jump to it ... */
Heiko Schocherabef7b82010-09-17 13:10:52 +0200248 mov pc, lr
249
Albert Aribaud3336ca62010-11-25 22:45:02 +0100250_board_init_r_ofs:
251 .word board_init_r - _start
252
253_rel_dyn_start_ofs:
254 .word __rel_dyn_start - _start
255_rel_dyn_end_ofs:
256 .word __rel_dyn_end - _start
257_dynsym_start_ofs:
258 .word __dynsym_start - _start
Heiko Schocherabef7b82010-09-17 13:10:52 +0200259
wdenkfe8c2802002-11-03 00:38:21 +0000260/*
261 *************************************************************************
262 *
263 * CPU_init_critical registers
264 *
265 * setup important registers
266 * setup memory timing
267 *
268 *************************************************************************
269 */
270
Wolfgang Denkc570b2f2005-09-26 01:06:33 +0200271#if defined(CONFIG_IMPA7) || defined(CONFIG_EP7312) || defined(CONFIG_ARMADILLO)
wdenkfe8c2802002-11-03 00:38:21 +0000272
273/* Interupt-Controller base addresses */
274INTMR1: .word 0x80000280 @ 32 bit size
275INTMR2: .word 0x80001280 @ 16 bit size
276INTMR3: .word 0x80002280 @ 8 bit size
277
278/* SYSCONs */
279SYSCON1: .word 0x80000100
280SYSCON2: .word 0x80001100
281SYSCON3: .word 0x80002200
282
283#define CLKCTL 0x6 /* mask */
284#define CLKCTL_18 0x0 /* 18.432 MHz */
285#define CLKCTL_36 0x2 /* 36.864 MHz */
286#define CLKCTL_49 0x4 /* 49.152 MHz */
287#define CLKCTL_73 0x6 /* 73.728 MHz */
288
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100289#elif defined(CONFIG_LPC2292)
290PLLCFG_ADR: .word PLLCFG
291PLLFEED_ADR: .word PLLFEED
292PLLCON_ADR: .word PLLCON
293PLLSTAT_ADR: .word PLLSTAT
294VPBDIV_ADR: .word VPBDIV
295MEMMAP_ADR: .word MEMMAP
296
wdenk39539882004-07-01 16:30:44 +0000297#endif
298
wdenkfe8c2802002-11-03 00:38:21 +0000299cpu_init_crit:
Wolfgang Denkc570b2f2005-09-26 01:06:33 +0200300#if defined(CONFIG_IMPA7) || defined(CONFIG_EP7312) || defined(CONFIG_ARMADILLO)
wdenk39539882004-07-01 16:30:44 +0000301
wdenkfe8c2802002-11-03 00:38:21 +0000302 /*
303 * mask all IRQs by clearing all bits in the INTMRs
304 */
305 mov r1, #0x00
306 ldr r0, INTMR1
307 str r1, [r0]
308 ldr r0, INTMR2
309 str r1, [r0]
310 ldr r0, INTMR3
311 str r1, [r0]
312
313 /*
314 * flush v4 I/D caches
315 */
316 mov r0, #0
317 mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */
318 mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */
319
320 /*
321 * disable MMU stuff and caches
322 */
323 mrc p15,0,r0,c1,c0
324 bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS)
325 bic r0, r0, #0x0000008f @ clear bits 7, 3:0 (B--- WCAM)
326 orr r0, r0, #0x00000002 @ set bit 2 (A) Align
327 mcr p15,0,r0,c1,c0
wdenk39539882004-07-01 16:30:44 +0000328#elif defined(CONFIG_NETARM)
wdenk2d1a5372004-02-23 19:30:57 +0000329 /*
330 * prior to software reset : need to set pin PORTC4 to be *HRESET
331 */
332 ldr r0, =NETARM_GEN_MODULE_BASE
333 ldr r1, =(NETARM_GEN_PORT_MODE(0x10) | \
334 NETARM_GEN_PORT_DIR(0x10))
335 str r1, [r0, #+NETARM_GEN_PORTC]
336 /*
337 * software reset : see HW Ref. Guide 8.2.4 : Software Service register
wdenkcdc7fea2004-07-11 22:27:55 +0000338 * for an explanation of this process
wdenk2d1a5372004-02-23 19:30:57 +0000339 */
340 ldr r0, =NETARM_GEN_MODULE_BASE
341 ldr r1, =NETARM_GEN_SW_SVC_RESETA
342 str r1, [r0, #+NETARM_GEN_SOFTWARE_SERVICE]
343 ldr r1, =NETARM_GEN_SW_SVC_RESETB
344 str r1, [r0, #+NETARM_GEN_SOFTWARE_SERVICE]
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 /*
350 * setup PLL and System Config
351 */
352 ldr r0, =NETARM_GEN_MODULE_BASE
353
354 ldr r1, =( NETARM_GEN_SYS_CFG_LENDIAN | \
355 NETARM_GEN_SYS_CFG_BUSFULL | \
356 NETARM_GEN_SYS_CFG_USER_EN | \
357 NETARM_GEN_SYS_CFG_ALIGN_ABORT | \
358 NETARM_GEN_SYS_CFG_BUSARB_INT | \
359 NETARM_GEN_SYS_CFG_BUSMON_EN )
360
361 str r1, [r0, #+NETARM_GEN_SYSTEM_CONTROL]
362
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200363#ifndef CONFIG_NETARM_PLL_BYPASS
wdenk2d1a5372004-02-23 19:30:57 +0000364 ldr r1, =( NETARM_GEN_PLL_CTL_PLLCNT(NETARM_PLL_COUNT_VAL) | \
365 NETARM_GEN_PLL_CTL_POLTST_DEF | \
366 NETARM_GEN_PLL_CTL_INDIV(1) | \
367 NETARM_GEN_PLL_CTL_ICP_DEF | \
368 NETARM_GEN_PLL_CTL_OUTDIV(2) )
369 str r1, [r0, #+NETARM_GEN_PLL_CONTROL]
Wolfgang Denk3df5bea2005-10-09 01:41:48 +0200370#endif
371
wdenk2d1a5372004-02-23 19:30:57 +0000372 /*
373 * mask all IRQs by clearing all bits in the INTMRs
374 */
375 mov r1, #0
376 ldr r0, =NETARM_GEN_MODULE_BASE
377 str r1, [r0, #+NETARM_GEN_INTR_ENABLE]
wdenk39539882004-07-01 16:30:44 +0000378
379#elif defined(CONFIG_S3C4510B)
380
381 /*
382 * Mask off all IRQ sources
383 */
384 ldr r1, =REG_INTMASK
385 ldr r0, =0x3FFFFF
386 str r0, [r1]
387
388 /*
389 * Disable Cache
390 */
391 ldr r0, =REG_SYSCFG
wdenkcdc7fea2004-07-11 22:27:55 +0000392 ldr r1, =0x83ffffa0 /* cache-disabled */
wdenk39539882004-07-01 16:30:44 +0000393 str r1, [r0]
394
Wolfgang Denk87cb6862005-10-06 17:08:18 +0200395#elif defined(CONFIG_INTEGRATOR) && defined(CONFIG_ARCH_INTEGRATOR)
396 /* No specific initialisation for IntegratorAP/CM720T as yet */
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100397#elif defined(CONFIG_LPC2292)
398 /* Set-up PLL */
399 mov r3, #0xAA
400 mov r4, #0x55
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100401 /* First disconnect and disable the PLL */
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100402 ldr r0, PLLCON_ADR
403 mov r1, #0x00
404 str r1, [r0]
405 ldr r0, PLLFEED_ADR /* start feed sequence */
406 str r3, [r0]
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100407 str r4, [r0] /* feed sequence done */
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100408 /* Set new M and P values */
409 ldr r0, PLLCFG_ADR
410 mov r1, #0x23 /* M=4 and P=2 */
411 str r1, [r0]
412 ldr r0, PLLFEED_ADR /* start feed sequence */
413 str r3, [r0]
414 str r4, [r0] /* feed sequence done */
415 /* Then enable the PLL */
416 ldr r0, PLLCON_ADR
417 mov r1, #0x01 /* PLL enable bit */
418 str r1, [r0]
419 ldr r0, PLLFEED_ADR /* start feed sequence */
420 str r3, [r0]
421 str r4, [r0] /* feed sequence done */
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100422 /* Wait for the lock */
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100423 ldr r0, PLLSTAT_ADR
424 mov r1, #0x400 /* lock bit */
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100425lock_loop:
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100426 ldr r2, [r0]
427 and r2, r1, r2
428 cmp r2, #0
429 beq lock_loop
430 /* And finally connect the PLL */
431 ldr r0, PLLCON_ADR
432 mov r1, #0x03 /* PLL enable bit and connect bit */
433 str r1, [r0]
434 ldr r0, PLLFEED_ADR /* start feed sequence */
435 str r3, [r0]
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100436 str r4, [r0] /* feed sequence done */
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100437 /* Set-up VPBDIV register */
438 ldr r0, VPBDIV_ADR
439 mov r1, #0x01 /* VPB clock is same as process clock */
440 str r1, [r0]
wdenk39539882004-07-01 16:30:44 +0000441#else
442#error No cpu_init_crit() defined for current CPU type
443#endif
wdenkfe8c2802002-11-03 00:38:21 +0000444
445#ifdef CONFIG_ARM7_REVD
446 /* set clock speed */
447 /* !!! we run @ 36 MHz due to a hardware flaw in Rev. D processors */
448 /* !!! not doing DRAM refresh properly! */
449 ldr r0, SYSCON3
450 ldr r1, [r0]
451 bic r1, r1, #CLKCTL
452 orr r1, r1, #CLKCTL_36
453 str r1, [r0]
454#endif
455
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100456#ifndef CONFIG_LPC2292
Wolfgang Denk87cb6862005-10-06 17:08:18 +0200457 mov ip, lr
wdenkfe8c2802002-11-03 00:38:21 +0000458 /*
459 * before relocating, we have to setup RAM timing
wdenkf6e20fc2004-02-08 19:38:38 +0000460 * because memory timing is board-dependent, you will
wdenk400558b2005-04-02 23:52:25 +0000461 * find a lowlevel_init.S in your board directory.
wdenkfe8c2802002-11-03 00:38:21 +0000462 */
wdenk400558b2005-04-02 23:52:25 +0000463 bl lowlevel_init
wdenkfe8c2802002-11-03 00:38:21 +0000464 mov lr, ip
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100465#endif
wdenkfe8c2802002-11-03 00:38:21 +0000466
467 mov pc, lr
468
469
wdenkfe8c2802002-11-03 00:38:21 +0000470/*
471 *************************************************************************
472 *
473 * Interrupt handling
474 *
475 *************************************************************************
476 */
477
478@
479@ IRQ stack frame.
480@
481#define S_FRAME_SIZE 72
482
483#define S_OLD_R0 68
484#define S_PSR 64
485#define S_PC 60
486#define S_LR 56
487#define S_SP 52
488
489#define S_IP 48
490#define S_FP 44
491#define S_R10 40
492#define S_R9 36
493#define S_R8 32
494#define S_R7 28
495#define S_R6 24
496#define S_R5 20
497#define S_R4 16
498#define S_R3 12
499#define S_R2 8
500#define S_R1 4
501#define S_R0 0
502
503#define MODE_SVC 0x13
504#define I_BIT 0x80
505
506/*
507 * use bad_save_user_regs for abort/prefetch/undef/swi ...
508 * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
509 */
510
511 .macro bad_save_user_regs
512 sub sp, sp, #S_FRAME_SIZE
513 stmia sp, {r0 - r12} @ Calling r0-r12
wdenkcdc7fea2004-07-11 22:27:55 +0000514 add r8, sp, #S_PC
wdenkfe8c2802002-11-03 00:38:21 +0000515
Heiko Schocherabef7b82010-09-17 13:10:52 +0200516 ldr r2, IRQ_STACK_START_IN
wdenkcdc7fea2004-07-11 22:27:55 +0000517 ldmia r2, {r2 - r4} @ get pc, cpsr, old_r0
wdenkfe8c2802002-11-03 00:38:21 +0000518 add r0, sp, #S_FRAME_SIZE @ restore sp_SVC
519
520 add r5, sp, #S_SP
521 mov r1, lr
wdenkcdc7fea2004-07-11 22:27:55 +0000522 stmia r5, {r0 - r4} @ save sp_SVC, lr_SVC, pc, cpsr, old_r
wdenkfe8c2802002-11-03 00:38:21 +0000523 mov r0, sp
524 .endm
525
526 .macro irq_save_user_regs
527 sub sp, sp, #S_FRAME_SIZE
528 stmia sp, {r0 - r12} @ Calling r0-r12
wdenkcdc7fea2004-07-11 22:27:55 +0000529 add r8, sp, #S_PC
530 stmdb r8, {sp, lr}^ @ Calling SP, LR
531 str lr, [r8, #0] @ Save calling PC
532 mrs r6, spsr
533 str r6, [r8, #4] @ Save CPSR
534 str r0, [r8, #8] @ Save OLD_R0
wdenkfe8c2802002-11-03 00:38:21 +0000535 mov r0, sp
536 .endm
537
538 .macro irq_restore_user_regs
539 ldmia sp, {r0 - lr}^ @ Calling r0 - lr
540 mov r0, r0
541 ldr lr, [sp, #S_PC] @ Get PC
542 add sp, sp, #S_FRAME_SIZE
543 subs pc, lr, #4 @ return & move spsr_svc into cpsr
544 .endm
545
546 .macro get_bad_stack
Heiko Schocherabef7b82010-09-17 13:10:52 +0200547 ldr r13, IRQ_STACK_START_IN @ setup our mode stack
wdenkfe8c2802002-11-03 00:38:21 +0000548
549 str lr, [r13] @ save caller lr / spsr
550 mrs lr, spsr
wdenkcdc7fea2004-07-11 22:27:55 +0000551 str lr, [r13, #4]
wdenkfe8c2802002-11-03 00:38:21 +0000552
553 mov r13, #MODE_SVC @ prepare SVC-Mode
554 msr spsr_c, r13
555 mov lr, pc
556 movs pc, lr
557 .endm
558
559 .macro get_irq_stack @ setup IRQ stack
560 ldr sp, IRQ_STACK_START
561 .endm
562
563 .macro get_fiq_stack @ setup FIQ stack
564 ldr sp, FIQ_STACK_START
565 .endm
566
567/*
568 * exception handlers
569 */
wdenkcdc7fea2004-07-11 22:27:55 +0000570 .align 5
wdenkfe8c2802002-11-03 00:38:21 +0000571undefined_instruction:
572 get_bad_stack
573 bad_save_user_regs
wdenkcdc7fea2004-07-11 22:27:55 +0000574 bl do_undefined_instruction
wdenkfe8c2802002-11-03 00:38:21 +0000575
576 .align 5
577software_interrupt:
578 get_bad_stack
579 bad_save_user_regs
wdenkcdc7fea2004-07-11 22:27:55 +0000580 bl do_software_interrupt
wdenkfe8c2802002-11-03 00:38:21 +0000581
582 .align 5
583prefetch_abort:
584 get_bad_stack
585 bad_save_user_regs
wdenkcdc7fea2004-07-11 22:27:55 +0000586 bl do_prefetch_abort
wdenkfe8c2802002-11-03 00:38:21 +0000587
588 .align 5
589data_abort:
590 get_bad_stack
591 bad_save_user_regs
wdenkcdc7fea2004-07-11 22:27:55 +0000592 bl do_data_abort
wdenkfe8c2802002-11-03 00:38:21 +0000593
594 .align 5
595not_used:
596 get_bad_stack
597 bad_save_user_regs
wdenkcdc7fea2004-07-11 22:27:55 +0000598 bl do_not_used
wdenkfe8c2802002-11-03 00:38:21 +0000599
600#ifdef CONFIG_USE_IRQ
601
602 .align 5
603irq:
604 get_irq_stack
605 irq_save_user_regs
wdenkcdc7fea2004-07-11 22:27:55 +0000606 bl do_irq
wdenkfe8c2802002-11-03 00:38:21 +0000607 irq_restore_user_regs
608
609 .align 5
610fiq:
611 get_fiq_stack
612 /* someone ought to write a more effiction fiq_save_user_regs */
613 irq_save_user_regs
wdenkcdc7fea2004-07-11 22:27:55 +0000614 bl do_fiq
wdenkfe8c2802002-11-03 00:38:21 +0000615 irq_restore_user_regs
616
617#else
618
619 .align 5
620irq:
621 get_bad_stack
622 bad_save_user_regs
wdenkcdc7fea2004-07-11 22:27:55 +0000623 bl do_irq
wdenkfe8c2802002-11-03 00:38:21 +0000624
625 .align 5
626fiq:
627 get_bad_stack
628 bad_save_user_regs
wdenkcdc7fea2004-07-11 22:27:55 +0000629 bl do_fiq
wdenkfe8c2802002-11-03 00:38:21 +0000630
631#endif
632
Wolfgang Denkc570b2f2005-09-26 01:06:33 +0200633#if defined(CONFIG_IMPA7) || defined(CONFIG_EP7312) || defined(CONFIG_ARMADILLO)
wdenkfe8c2802002-11-03 00:38:21 +0000634 .align 5
635.globl reset_cpu
636reset_cpu:
wdenkcdc7fea2004-07-11 22:27:55 +0000637 mov ip, #0
638 mcr p15, 0, ip, c7, c7, 0 @ invalidate cache
639 mcr p15, 0, ip, c8, c7, 0 @ flush TLB (v4)
640 mrc p15, 0, ip, c1, c0, 0 @ get ctrl register
641 bic ip, ip, #0x000f @ ............wcam
642 bic ip, ip, #0x2100 @ ..v....s........
643 mcr p15, 0, ip, c1, c0, 0 @ ctrl register
644 mov pc, r0
wdenk39539882004-07-01 16:30:44 +0000645#elif defined(CONFIG_NETARM)
646 .align 5
647.globl reset_cpu
648reset_cpu:
wdenk2d1a5372004-02-23 19:30:57 +0000649 ldr r1, =NETARM_MEM_MODULE_BASE
650 ldr r0, [r1, #+NETARM_MEM_CS0_BASE_ADDR]
651 ldr r1, =0xFFFFF000
652 and r0, r1, r0
Wolfgang Denk14d0a022010-10-07 21:51:12 +0200653 ldr r1, =(relocate-CONFIG_SYS_TEXT_BASE)
wdenk2d1a5372004-02-23 19:30:57 +0000654 add r0, r1, r0
655 ldr r4, =NETARM_GEN_MODULE_BASE
656 ldr r1, =NETARM_GEN_SW_SVC_RESETA
657 str r1, [r4, #+NETARM_GEN_SOFTWARE_SERVICE]
658 ldr r1, =NETARM_GEN_SW_SVC_RESETB
659 str r1, [r4, #+NETARM_GEN_SOFTWARE_SERVICE]
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 mov pc, r0
wdenk39539882004-07-01 16:30:44 +0000665#elif defined(CONFIG_S3C4510B)
666/* Nothing done here as reseting the CPU is board specific, depending
667 * on external peripherals such as watchdog timers, etc. */
Wolfgang Denk87cb6862005-10-06 17:08:18 +0200668#elif defined(CONFIG_INTEGRATOR) && defined(CONFIG_ARCH_INTEGRATOR)
669 /* No specific reset actions for IntegratorAP/CM720T as yet */
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100670#elif defined(CONFIG_LPC2292)
671 .align 5
672.globl reset_cpu
673reset_cpu:
674 mov pc, r0
wdenk39539882004-07-01 16:30:44 +0000675#else
676#error No reset_cpu() defined for current CPU type
wdenk2d1a5372004-02-23 19:30:57 +0000677#endif