1*84ad6884SPeter Tyser/* 2*84ad6884SPeter Tyser * armboot - Startup Code for XScale 3*84ad6884SPeter Tyser * 4*84ad6884SPeter Tyser * Copyright (C) 1998 Dan Malek <dmalek@jlc.net> 5*84ad6884SPeter Tyser * Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se> 6*84ad6884SPeter Tyser * Copyright (C) 2000 Wolfgang Denk <wd@denx.de> 7*84ad6884SPeter Tyser * Copyright (C) 2001 Alex Zuepke <azu@sysgo.de> 8*84ad6884SPeter Tyser * Copyright (C) 2002 Kyle Harris <kharris@nexus-tech.net> 9*84ad6884SPeter Tyser * Copyright (C) 2003 Robert Schwebel <r.schwebel@pengutronix.de> 10*84ad6884SPeter Tyser * Copyright (C) 2003 Kai-Uwe Bloem <kai-uwe.bloem@auerswald.de> 11*84ad6884SPeter Tyser * 12*84ad6884SPeter Tyser * See file CREDITS for list of people who contributed to this 13*84ad6884SPeter Tyser * project. 14*84ad6884SPeter Tyser * 15*84ad6884SPeter Tyser * This program is free software; you can redistribute it and/or 16*84ad6884SPeter Tyser * modify it under the terms of the GNU General Public License as 17*84ad6884SPeter Tyser * published by the Free Software Foundation; either version 2 of 18*84ad6884SPeter Tyser * the License, or (at your option) any later version. 19*84ad6884SPeter Tyser * 20*84ad6884SPeter Tyser * This program is distributed in the hope that it will be useful, 21*84ad6884SPeter Tyser * but WITHOUT ANY WARRANTY; without even the implied warranty of 22*84ad6884SPeter Tyser * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23*84ad6884SPeter Tyser * GNU General Public License for more details. 24*84ad6884SPeter Tyser * 25*84ad6884SPeter Tyser * You should have received a copy of the GNU General Public License 26*84ad6884SPeter Tyser * along with this program; if not, write to the Free Software 27*84ad6884SPeter Tyser * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 28*84ad6884SPeter Tyser * MA 02111-1307 USA 29*84ad6884SPeter Tyser */ 30*84ad6884SPeter Tyser 31*84ad6884SPeter Tyser#include <config.h> 32*84ad6884SPeter Tyser#include <version.h> 33*84ad6884SPeter Tyser#include <asm/arch/pxa-regs.h> 34*84ad6884SPeter Tyser 35*84ad6884SPeter Tyser.globl _start 36*84ad6884SPeter Tyser_start: b reset 37*84ad6884SPeter Tyser ldr pc, _undefined_instruction 38*84ad6884SPeter Tyser ldr pc, _software_interrupt 39*84ad6884SPeter Tyser ldr pc, _prefetch_abort 40*84ad6884SPeter Tyser ldr pc, _data_abort 41*84ad6884SPeter Tyser ldr pc, _not_used 42*84ad6884SPeter Tyser ldr pc, _irq 43*84ad6884SPeter Tyser ldr pc, _fiq 44*84ad6884SPeter Tyser 45*84ad6884SPeter Tyser_undefined_instruction: .word undefined_instruction 46*84ad6884SPeter Tyser_software_interrupt: .word software_interrupt 47*84ad6884SPeter Tyser_prefetch_abort: .word prefetch_abort 48*84ad6884SPeter Tyser_data_abort: .word data_abort 49*84ad6884SPeter Tyser_not_used: .word not_used 50*84ad6884SPeter Tyser_irq: .word irq 51*84ad6884SPeter Tyser_fiq: .word fiq 52*84ad6884SPeter Tyser 53*84ad6884SPeter Tyser .balignl 16,0xdeadbeef 54*84ad6884SPeter Tyser 55*84ad6884SPeter Tyser 56*84ad6884SPeter Tyser/* 57*84ad6884SPeter Tyser * Startup Code (reset vector) 58*84ad6884SPeter Tyser * 59*84ad6884SPeter Tyser * do important init only if we don't start from RAM! 60*84ad6884SPeter Tyser * - relocate armboot to RAM 61*84ad6884SPeter Tyser * - setup stack 62*84ad6884SPeter Tyser * - jump to second stage 63*84ad6884SPeter Tyser */ 64*84ad6884SPeter Tyser 65*84ad6884SPeter Tyser_TEXT_BASE: 66*84ad6884SPeter Tyser .word TEXT_BASE 67*84ad6884SPeter Tyser 68*84ad6884SPeter Tyser.globl _armboot_start 69*84ad6884SPeter Tyser_armboot_start: 70*84ad6884SPeter Tyser .word _start 71*84ad6884SPeter Tyser 72*84ad6884SPeter Tyser/* 73*84ad6884SPeter Tyser * These are defined in the board-specific linker script. 74*84ad6884SPeter Tyser */ 75*84ad6884SPeter Tyser.globl _bss_start 76*84ad6884SPeter Tyser_bss_start: 77*84ad6884SPeter Tyser .word __bss_start 78*84ad6884SPeter Tyser 79*84ad6884SPeter Tyser.globl _bss_end 80*84ad6884SPeter Tyser_bss_end: 81*84ad6884SPeter Tyser .word _end 82*84ad6884SPeter Tyser 83*84ad6884SPeter Tyser#ifdef CONFIG_USE_IRQ 84*84ad6884SPeter Tyser/* IRQ stack memory (calculated at run-time) */ 85*84ad6884SPeter Tyser.globl IRQ_STACK_START 86*84ad6884SPeter TyserIRQ_STACK_START: 87*84ad6884SPeter Tyser .word 0x0badc0de 88*84ad6884SPeter Tyser 89*84ad6884SPeter Tyser/* IRQ stack memory (calculated at run-time) */ 90*84ad6884SPeter Tyser.globl FIQ_STACK_START 91*84ad6884SPeter TyserFIQ_STACK_START: 92*84ad6884SPeter Tyser .word 0x0badc0de 93*84ad6884SPeter Tyser#endif /* CONFIG_USE_IRQ */ 94*84ad6884SPeter Tyser 95*84ad6884SPeter Tyser 96*84ad6884SPeter Tyser/****************************************************************************/ 97*84ad6884SPeter Tyser/* */ 98*84ad6884SPeter Tyser/* the actual reset code */ 99*84ad6884SPeter Tyser/* */ 100*84ad6884SPeter Tyser/****************************************************************************/ 101*84ad6884SPeter Tyser 102*84ad6884SPeter Tyserreset: 103*84ad6884SPeter Tyser mrs r0,cpsr /* set the CPU to SVC32 mode */ 104*84ad6884SPeter Tyser bic r0,r0,#0x1f /* (superviser mode, M=10011) */ 105*84ad6884SPeter Tyser orr r0,r0,#0x13 106*84ad6884SPeter Tyser msr cpsr,r0 107*84ad6884SPeter Tyser 108*84ad6884SPeter Tyser /* 109*84ad6884SPeter Tyser * we do sys-critical inits only at reboot, 110*84ad6884SPeter Tyser * not when booting from RAM! 111*84ad6884SPeter Tyser */ 112*84ad6884SPeter Tyser#ifndef CONFIG_SKIP_LOWLEVEL_INIT 113*84ad6884SPeter Tyser bl cpu_init_crit /* we do sys-critical inits */ 114*84ad6884SPeter Tyser#endif /* !CONFIG_SKIP_LOWLEVEL_INIT */ 115*84ad6884SPeter Tyser 116*84ad6884SPeter Tyser#ifndef CONFIG_SKIP_RELOCATE_UBOOT 117*84ad6884SPeter Tyserrelocate: /* relocate U-Boot to RAM */ 118*84ad6884SPeter Tyser adr r0, _start /* r0 <- current position of code */ 119*84ad6884SPeter Tyser ldr r1, _TEXT_BASE /* test if we run from flash or RAM */ 120*84ad6884SPeter Tyser cmp r0, r1 /* don't reloc during debug */ 121*84ad6884SPeter Tyser beq stack_setup 122*84ad6884SPeter Tyser 123*84ad6884SPeter Tyser ldr r2, _armboot_start 124*84ad6884SPeter Tyser ldr r3, _bss_start 125*84ad6884SPeter Tyser sub r2, r3, r2 /* r2 <- size of armboot */ 126*84ad6884SPeter Tyser add r2, r0, r2 /* r2 <- source end address */ 127*84ad6884SPeter Tyser 128*84ad6884SPeter Tysercopy_loop: 129*84ad6884SPeter Tyser ldmia r0!, {r3-r10} /* copy from source address [r0] */ 130*84ad6884SPeter Tyser stmia r1!, {r3-r10} /* copy to target address [r1] */ 131*84ad6884SPeter Tyser cmp r0, r2 /* until source end address [r2] */ 132*84ad6884SPeter Tyser ble copy_loop 133*84ad6884SPeter Tyser#endif /* !CONFIG_SKIP_RELOCATE_UBOOT */ 134*84ad6884SPeter Tyser 135*84ad6884SPeter Tyser /* Set up the stack */ 136*84ad6884SPeter Tyserstack_setup: 137*84ad6884SPeter Tyser ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */ 138*84ad6884SPeter Tyser sub r0, r0, #CONFIG_SYS_MALLOC_LEN /* malloc area */ 139*84ad6884SPeter Tyser sub r0, r0, #CONFIG_SYS_GBL_DATA_SIZE /* bdinfo */ 140*84ad6884SPeter Tyser#ifdef CONFIG_USE_IRQ 141*84ad6884SPeter Tyser sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ) 142*84ad6884SPeter Tyser#endif /* CONFIG_USE_IRQ */ 143*84ad6884SPeter Tyser sub sp, r0, #12 /* leave 3 words for abort-stack */ 144*84ad6884SPeter Tyser 145*84ad6884SPeter Tyserclear_bss: 146*84ad6884SPeter Tyser ldr r0, _bss_start /* find start of bss segment */ 147*84ad6884SPeter Tyser ldr r1, _bss_end /* stop here */ 148*84ad6884SPeter Tyser mov r2, #0x00000000 /* clear */ 149*84ad6884SPeter Tyser 150*84ad6884SPeter Tyserclbss_l:str r2, [r0] /* clear loop... */ 151*84ad6884SPeter Tyser add r0, r0, #4 152*84ad6884SPeter Tyser cmp r0, r1 153*84ad6884SPeter Tyser ble clbss_l 154*84ad6884SPeter Tyser 155*84ad6884SPeter Tyser ldr pc, _start_armboot 156*84ad6884SPeter Tyser 157*84ad6884SPeter Tyser_start_armboot: .word start_armboot 158*84ad6884SPeter Tyser 159*84ad6884SPeter Tyser 160*84ad6884SPeter Tyser/****************************************************************************/ 161*84ad6884SPeter Tyser/* */ 162*84ad6884SPeter Tyser/* CPU_init_critical registers */ 163*84ad6884SPeter Tyser/* */ 164*84ad6884SPeter Tyser/* - setup important registers */ 165*84ad6884SPeter Tyser/* - setup memory timing */ 166*84ad6884SPeter Tyser/* */ 167*84ad6884SPeter Tyser/****************************************************************************/ 168*84ad6884SPeter Tyser/* mk@tbd: Fix this! */ 169*84ad6884SPeter Tyser#undef RCSR 170*84ad6884SPeter Tyser#undef ICMR 171*84ad6884SPeter Tyser#undef OSMR3 172*84ad6884SPeter Tyser#undef OSCR 173*84ad6884SPeter Tyser#undef OWER 174*84ad6884SPeter Tyser#undef OIER 175*84ad6884SPeter Tyser#undef CCCR 176*84ad6884SPeter Tyser 177*84ad6884SPeter Tyser/* Interrupt-Controller base address */ 178*84ad6884SPeter TyserIC_BASE: .word 0x40d00000 179*84ad6884SPeter Tyser#define ICMR 0x04 180*84ad6884SPeter Tyser 181*84ad6884SPeter Tyser/* Reset-Controller */ 182*84ad6884SPeter TyserRST_BASE: .word 0x40f00030 183*84ad6884SPeter Tyser#define RCSR 0x00 184*84ad6884SPeter Tyser 185*84ad6884SPeter Tyser/* Operating System Timer */ 186*84ad6884SPeter TyserOSTIMER_BASE: .word 0x40a00000 187*84ad6884SPeter Tyser#define OSMR3 0x0C 188*84ad6884SPeter Tyser#define OSCR 0x10 189*84ad6884SPeter Tyser#define OWER 0x18 190*84ad6884SPeter Tyser#define OIER 0x1C 191*84ad6884SPeter Tyser 192*84ad6884SPeter Tyser/* Clock Manager Registers */ 193*84ad6884SPeter Tyser#ifdef CONFIG_CPU_MONAHANS 194*84ad6884SPeter Tyser# ifndef CONFIG_SYS_MONAHANS_RUN_MODE_OSC_RATIO 195*84ad6884SPeter Tyser# error "You have to define CONFIG_SYS_MONAHANS_RUN_MODE_OSC_RATIO!!" 196*84ad6884SPeter Tyser# endif /* !CONFIG_SYS_MONAHANS_RUN_MODE_OSC_RATIO */ 197*84ad6884SPeter Tyser# ifndef CONFIG_SYS_MONAHANS_TURBO_RUN_MODE_RATIO 198*84ad6884SPeter Tyser# define CONFIG_SYS_MONAHANS_TURBO_RUN_MODE_RATIO 0x1 199*84ad6884SPeter Tyser# endif /* !CONFIG_SYS_MONAHANS_TURBO_RUN_MODE_RATIO */ 200*84ad6884SPeter Tyser#else /* !CONFIG_CPU_MONAHANS */ 201*84ad6884SPeter Tyser#ifdef CONFIG_SYS_CPUSPEED 202*84ad6884SPeter TyserCC_BASE: .word 0x41300000 203*84ad6884SPeter Tyser#define CCCR 0x00 204*84ad6884SPeter Tysercpuspeed: .word CONFIG_SYS_CPUSPEED 205*84ad6884SPeter Tyser#else /* !CONFIG_SYS_CPUSPEED */ 206*84ad6884SPeter Tyser#error "You have to define CONFIG_SYS_CPUSPEED!!" 207*84ad6884SPeter Tyser#endif /* CONFIG_SYS_CPUSPEED */ 208*84ad6884SPeter Tyser#endif /* CONFIG_CPU_MONAHANS */ 209*84ad6884SPeter Tyser 210*84ad6884SPeter Tyser /* takes care the CP15 update has taken place */ 211*84ad6884SPeter Tyser .macro CPWAIT reg 212*84ad6884SPeter Tyser mrc p15,0,\reg,c2,c0,0 213*84ad6884SPeter Tyser mov \reg,\reg 214*84ad6884SPeter Tyser sub pc,pc,#4 215*84ad6884SPeter Tyser .endm 216*84ad6884SPeter Tyser 217*84ad6884SPeter Tysercpu_init_crit: 218*84ad6884SPeter Tyser 219*84ad6884SPeter Tyser /* mask all IRQs */ 220*84ad6884SPeter Tyser#ifndef CONFIG_CPU_MONAHANS 221*84ad6884SPeter Tyser ldr r0, IC_BASE 222*84ad6884SPeter Tyser mov r1, #0x00 223*84ad6884SPeter Tyser str r1, [r0, #ICMR] 224*84ad6884SPeter Tyser#else /* CONFIG_CPU_MONAHANS */ 225*84ad6884SPeter Tyser /* Step 1 - Enable CP6 permission */ 226*84ad6884SPeter Tyser mrc p15, 0, r1, c15, c1, 0 @ read CPAR 227*84ad6884SPeter Tyser orr r1, r1, #0x40 228*84ad6884SPeter Tyser mcr p15, 0, r1, c15, c1, 0 229*84ad6884SPeter Tyser CPWAIT r1 230*84ad6884SPeter Tyser 231*84ad6884SPeter Tyser /* Step 2 - Mask ICMR & ICMR2 */ 232*84ad6884SPeter Tyser mov r1, #0 233*84ad6884SPeter Tyser mcr p6, 0, r1, c1, c0, 0 @ ICMR 234*84ad6884SPeter Tyser mcr p6, 0, r1, c7, c0, 0 @ ICMR2 235*84ad6884SPeter Tyser 236*84ad6884SPeter Tyser /* turn off all clocks but the ones we will definitly require */ 237*84ad6884SPeter Tyser ldr r1, =CKENA 238*84ad6884SPeter Tyser ldr r2, =(CKENA_22_FFUART | CKENA_10_SRAM | CKENA_9_SMC | CKENA_8_DMC) 239*84ad6884SPeter Tyser str r2, [r1] 240*84ad6884SPeter Tyser ldr r1, =CKENB 241*84ad6884SPeter Tyser ldr r2, =(CKENB_6_IRQ) 242*84ad6884SPeter Tyser str r2, [r1] 243*84ad6884SPeter Tyser#endif /* !CONFIG_CPU_MONAHANS */ 244*84ad6884SPeter Tyser 245*84ad6884SPeter Tyser /* set clock speed */ 246*84ad6884SPeter Tyser#ifdef CONFIG_CPU_MONAHANS 247*84ad6884SPeter Tyser ldr r0, =ACCR 248*84ad6884SPeter Tyser ldr r1, =(((CONFIG_SYS_MONAHANS_TURBO_RUN_MODE_RATIO<<8) & ACCR_XN_MASK) | (CONFIG_SYS_MONAHANS_RUN_MODE_OSC_RATIO & ACCR_XL_MASK)) 249*84ad6884SPeter Tyser str r1, [r0] 250*84ad6884SPeter Tyser#else /* !CONFIG_CPU_MONAHANS */ 251*84ad6884SPeter Tyser#ifdef CONFIG_SYS_CPUSPEED 252*84ad6884SPeter Tyser ldr r0, CC_BASE 253*84ad6884SPeter Tyser ldr r1, cpuspeed 254*84ad6884SPeter Tyser str r1, [r0, #CCCR] 255*84ad6884SPeter Tyser mov r0, #2 256*84ad6884SPeter Tyser mcr p14, 0, r0, c6, c0, 0 257*84ad6884SPeter Tyser 258*84ad6884SPeter Tysersetspeed_done: 259*84ad6884SPeter Tyser 260*84ad6884SPeter Tyser#endif /* CONFIG_SYS_CPUSPEED */ 261*84ad6884SPeter Tyser#endif /* CONFIG_CPU_MONAHANS */ 262*84ad6884SPeter Tyser 263*84ad6884SPeter Tyser /* 264*84ad6884SPeter Tyser * before relocating, we have to setup RAM timing 265*84ad6884SPeter Tyser * because memory timing is board-dependend, you will 266*84ad6884SPeter Tyser * find a lowlevel_init.S in your board directory. 267*84ad6884SPeter Tyser */ 268*84ad6884SPeter Tyser mov ip, lr 269*84ad6884SPeter Tyser bl lowlevel_init 270*84ad6884SPeter Tyser mov lr, ip 271*84ad6884SPeter Tyser 272*84ad6884SPeter Tyser /* Memory interfaces are working. Disable MMU and enable I-cache. */ 273*84ad6884SPeter Tyser /* mk: hmm, this is not in the monahans docs, leave it now but 274*84ad6884SPeter Tyser * check here if it doesn't work :-) */ 275*84ad6884SPeter Tyser 276*84ad6884SPeter Tyser ldr r0, =0x2001 /* enable access to all coproc. */ 277*84ad6884SPeter Tyser mcr p15, 0, r0, c15, c1, 0 278*84ad6884SPeter Tyser CPWAIT r0 279*84ad6884SPeter Tyser 280*84ad6884SPeter Tyser mcr p15, 0, r0, c7, c10, 4 /* drain the write & fill buffers */ 281*84ad6884SPeter Tyser CPWAIT r0 282*84ad6884SPeter Tyser 283*84ad6884SPeter Tyser mcr p15, 0, r0, c7, c7, 0 /* flush Icache, Dcache and BTB */ 284*84ad6884SPeter Tyser CPWAIT r0 285*84ad6884SPeter Tyser 286*84ad6884SPeter Tyser mcr p15, 0, r0, c8, c7, 0 /* flush instuction and data TLBs */ 287*84ad6884SPeter Tyser CPWAIT r0 288*84ad6884SPeter Tyser 289*84ad6884SPeter Tyser /* Enable the Icache */ 290*84ad6884SPeter Tyser/* 291*84ad6884SPeter Tyser mrc p15, 0, r0, c1, c0, 0 292*84ad6884SPeter Tyser orr r0, r0, #0x1800 293*84ad6884SPeter Tyser mcr p15, 0, r0, c1, c0, 0 294*84ad6884SPeter Tyser CPWAIT 295*84ad6884SPeter Tyser*/ 296*84ad6884SPeter Tyser mov pc, lr 297*84ad6884SPeter Tyser 298*84ad6884SPeter Tyser 299*84ad6884SPeter Tyser/****************************************************************************/ 300*84ad6884SPeter Tyser/* */ 301*84ad6884SPeter Tyser/* Interrupt handling */ 302*84ad6884SPeter Tyser/* */ 303*84ad6884SPeter Tyser/****************************************************************************/ 304*84ad6884SPeter Tyser 305*84ad6884SPeter Tyser/* IRQ stack frame */ 306*84ad6884SPeter Tyser 307*84ad6884SPeter Tyser#define S_FRAME_SIZE 72 308*84ad6884SPeter Tyser 309*84ad6884SPeter Tyser#define S_OLD_R0 68 310*84ad6884SPeter Tyser#define S_PSR 64 311*84ad6884SPeter Tyser#define S_PC 60 312*84ad6884SPeter Tyser#define S_LR 56 313*84ad6884SPeter Tyser#define S_SP 52 314*84ad6884SPeter Tyser 315*84ad6884SPeter Tyser#define S_IP 48 316*84ad6884SPeter Tyser#define S_FP 44 317*84ad6884SPeter Tyser#define S_R10 40 318*84ad6884SPeter Tyser#define S_R9 36 319*84ad6884SPeter Tyser#define S_R8 32 320*84ad6884SPeter Tyser#define S_R7 28 321*84ad6884SPeter Tyser#define S_R6 24 322*84ad6884SPeter Tyser#define S_R5 20 323*84ad6884SPeter Tyser#define S_R4 16 324*84ad6884SPeter Tyser#define S_R3 12 325*84ad6884SPeter Tyser#define S_R2 8 326*84ad6884SPeter Tyser#define S_R1 4 327*84ad6884SPeter Tyser#define S_R0 0 328*84ad6884SPeter Tyser 329*84ad6884SPeter Tyser#define MODE_SVC 0x13 330*84ad6884SPeter Tyser 331*84ad6884SPeter Tyser /* use bad_save_user_regs for abort/prefetch/undef/swi ... */ 332*84ad6884SPeter Tyser 333*84ad6884SPeter Tyser .macro bad_save_user_regs 334*84ad6884SPeter Tyser sub sp, sp, #S_FRAME_SIZE 335*84ad6884SPeter Tyser stmia sp, {r0 - r12} /* Calling r0-r12 */ 336*84ad6884SPeter Tyser add r8, sp, #S_PC 337*84ad6884SPeter Tyser 338*84ad6884SPeter Tyser ldr r2, _armboot_start 339*84ad6884SPeter Tyser sub r2, r2, #(CONFIG_STACKSIZE+CONFIG_SYS_MALLOC_LEN) 340*84ad6884SPeter Tyser sub r2, r2, #(CONFIG_SYS_GBL_DATA_SIZE+8) @ set base 2 words into abort stack 341*84ad6884SPeter Tyser ldmia r2, {r2 - r4} /* get pc, cpsr, old_r0 */ 342*84ad6884SPeter Tyser add r0, sp, #S_FRAME_SIZE /* restore sp_SVC */ 343*84ad6884SPeter Tyser 344*84ad6884SPeter Tyser add r5, sp, #S_SP 345*84ad6884SPeter Tyser mov r1, lr 346*84ad6884SPeter Tyser stmia r5, {r0 - r4} /* save sp_SVC, lr_SVC, pc, cpsr, old_r */ 347*84ad6884SPeter Tyser mov r0, sp 348*84ad6884SPeter Tyser .endm 349*84ad6884SPeter Tyser 350*84ad6884SPeter Tyser 351*84ad6884SPeter Tyser /* use irq_save_user_regs / irq_restore_user_regs for */ 352*84ad6884SPeter Tyser /* IRQ/FIQ handling */ 353*84ad6884SPeter Tyser 354*84ad6884SPeter Tyser .macro irq_save_user_regs 355*84ad6884SPeter Tyser sub sp, sp, #S_FRAME_SIZE 356*84ad6884SPeter Tyser stmia sp, {r0 - r12} /* Calling r0-r12 */ 357*84ad6884SPeter Tyser add r8, sp, #S_PC 358*84ad6884SPeter Tyser stmdb r8, {sp, lr}^ /* Calling SP, LR */ 359*84ad6884SPeter Tyser str lr, [r8, #0] /* Save calling PC */ 360*84ad6884SPeter Tyser mrs r6, spsr 361*84ad6884SPeter Tyser str r6, [r8, #4] /* Save CPSR */ 362*84ad6884SPeter Tyser str r0, [r8, #8] /* Save OLD_R0 */ 363*84ad6884SPeter Tyser mov r0, sp 364*84ad6884SPeter Tyser .endm 365*84ad6884SPeter Tyser 366*84ad6884SPeter Tyser .macro irq_restore_user_regs 367*84ad6884SPeter Tyser ldmia sp, {r0 - lr}^ @ Calling r0 - lr 368*84ad6884SPeter Tyser mov r0, r0 369*84ad6884SPeter Tyser ldr lr, [sp, #S_PC] @ Get PC 370*84ad6884SPeter Tyser add sp, sp, #S_FRAME_SIZE 371*84ad6884SPeter Tyser subs pc, lr, #4 @ return & move spsr_svc into cpsr 372*84ad6884SPeter Tyser .endm 373*84ad6884SPeter Tyser 374*84ad6884SPeter Tyser .macro get_bad_stack 375*84ad6884SPeter Tyser ldr r13, _armboot_start @ setup our mode stack 376*84ad6884SPeter Tyser sub r13, r13, #(CONFIG_STACKSIZE+CONFIG_SYS_MALLOC_LEN) 377*84ad6884SPeter Tyser sub r13, r13, #(CONFIG_SYS_GBL_DATA_SIZE+8) @ reserved a couple spots in abort stack 378*84ad6884SPeter Tyser 379*84ad6884SPeter Tyser str lr, [r13] @ save caller lr / spsr 380*84ad6884SPeter Tyser mrs lr, spsr 381*84ad6884SPeter Tyser str lr, [r13, #4] 382*84ad6884SPeter Tyser 383*84ad6884SPeter Tyser mov r13, #MODE_SVC @ prepare SVC-Mode 384*84ad6884SPeter Tyser msr spsr_c, r13 385*84ad6884SPeter Tyser mov lr, pc 386*84ad6884SPeter Tyser movs pc, lr 387*84ad6884SPeter Tyser .endm 388*84ad6884SPeter Tyser 389*84ad6884SPeter Tyser .macro get_irq_stack @ setup IRQ stack 390*84ad6884SPeter Tyser ldr sp, IRQ_STACK_START 391*84ad6884SPeter Tyser .endm 392*84ad6884SPeter Tyser 393*84ad6884SPeter Tyser .macro get_fiq_stack @ setup FIQ stack 394*84ad6884SPeter Tyser ldr sp, FIQ_STACK_START 395*84ad6884SPeter Tyser .endm 396*84ad6884SPeter Tyser 397*84ad6884SPeter Tyser 398*84ad6884SPeter Tyser/****************************************************************************/ 399*84ad6884SPeter Tyser/* */ 400*84ad6884SPeter Tyser/* exception handlers */ 401*84ad6884SPeter Tyser/* */ 402*84ad6884SPeter Tyser/****************************************************************************/ 403*84ad6884SPeter Tyser 404*84ad6884SPeter Tyser .align 5 405*84ad6884SPeter Tyserundefined_instruction: 406*84ad6884SPeter Tyser get_bad_stack 407*84ad6884SPeter Tyser bad_save_user_regs 408*84ad6884SPeter Tyser bl do_undefined_instruction 409*84ad6884SPeter Tyser 410*84ad6884SPeter Tyser .align 5 411*84ad6884SPeter Tysersoftware_interrupt: 412*84ad6884SPeter Tyser get_bad_stack 413*84ad6884SPeter Tyser bad_save_user_regs 414*84ad6884SPeter Tyser bl do_software_interrupt 415*84ad6884SPeter Tyser 416*84ad6884SPeter Tyser .align 5 417*84ad6884SPeter Tyserprefetch_abort: 418*84ad6884SPeter Tyser get_bad_stack 419*84ad6884SPeter Tyser bad_save_user_regs 420*84ad6884SPeter Tyser bl do_prefetch_abort 421*84ad6884SPeter Tyser 422*84ad6884SPeter Tyser .align 5 423*84ad6884SPeter Tyserdata_abort: 424*84ad6884SPeter Tyser get_bad_stack 425*84ad6884SPeter Tyser bad_save_user_regs 426*84ad6884SPeter Tyser bl do_data_abort 427*84ad6884SPeter Tyser 428*84ad6884SPeter Tyser .align 5 429*84ad6884SPeter Tysernot_used: 430*84ad6884SPeter Tyser get_bad_stack 431*84ad6884SPeter Tyser bad_save_user_regs 432*84ad6884SPeter Tyser bl do_not_used 433*84ad6884SPeter Tyser 434*84ad6884SPeter Tyser#ifdef CONFIG_USE_IRQ 435*84ad6884SPeter Tyser 436*84ad6884SPeter Tyser .align 5 437*84ad6884SPeter Tyserirq: 438*84ad6884SPeter Tyser get_irq_stack 439*84ad6884SPeter Tyser irq_save_user_regs 440*84ad6884SPeter Tyser bl do_irq 441*84ad6884SPeter Tyser irq_restore_user_regs 442*84ad6884SPeter Tyser 443*84ad6884SPeter Tyser .align 5 444*84ad6884SPeter Tyserfiq: 445*84ad6884SPeter Tyser get_fiq_stack 446*84ad6884SPeter Tyser irq_save_user_regs /* someone ought to write a more */ 447*84ad6884SPeter Tyser bl do_fiq /* effiction fiq_save_user_regs */ 448*84ad6884SPeter Tyser irq_restore_user_regs 449*84ad6884SPeter Tyser 450*84ad6884SPeter Tyser#else /* !CONFIG_USE_IRQ */ 451*84ad6884SPeter Tyser 452*84ad6884SPeter Tyser .align 5 453*84ad6884SPeter Tyserirq: 454*84ad6884SPeter Tyser get_bad_stack 455*84ad6884SPeter Tyser bad_save_user_regs 456*84ad6884SPeter Tyser bl do_irq 457*84ad6884SPeter Tyser 458*84ad6884SPeter Tyser .align 5 459*84ad6884SPeter Tyserfiq: 460*84ad6884SPeter Tyser get_bad_stack 461*84ad6884SPeter Tyser bad_save_user_regs 462*84ad6884SPeter Tyser bl do_fiq 463*84ad6884SPeter Tyser 464*84ad6884SPeter Tyser#endif /* CONFIG_USE_IRQ */ 465*84ad6884SPeter Tyser 466*84ad6884SPeter Tyser/****************************************************************************/ 467*84ad6884SPeter Tyser/* */ 468*84ad6884SPeter Tyser/* Reset function: the PXA250 doesn't have a reset function, so we have to */ 469*84ad6884SPeter Tyser/* perform a watchdog timeout for a soft reset. */ 470*84ad6884SPeter Tyser/* */ 471*84ad6884SPeter Tyser/****************************************************************************/ 472*84ad6884SPeter Tyser 473*84ad6884SPeter Tyser .align 5 474*84ad6884SPeter Tyser.globl reset_cpu 475*84ad6884SPeter Tyser 476*84ad6884SPeter Tyser /* FIXME: this code is PXA250 specific. How is this handled on */ 477*84ad6884SPeter Tyser /* other XScale processors? */ 478*84ad6884SPeter Tyser 479*84ad6884SPeter Tyserreset_cpu: 480*84ad6884SPeter Tyser 481*84ad6884SPeter Tyser /* We set OWE:WME (watchdog enable) and wait until timeout happens */ 482*84ad6884SPeter Tyser 483*84ad6884SPeter Tyser ldr r0, OSTIMER_BASE 484*84ad6884SPeter Tyser ldr r1, [r0, #OWER] 485*84ad6884SPeter Tyser orr r1, r1, #0x0001 /* bit0: WME */ 486*84ad6884SPeter Tyser str r1, [r0, #OWER] 487*84ad6884SPeter Tyser 488*84ad6884SPeter Tyser /* OS timer does only wrap every 1165 seconds, so we have to set */ 489*84ad6884SPeter Tyser /* the match register as well. */ 490*84ad6884SPeter Tyser 491*84ad6884SPeter Tyser ldr r1, [r0, #OSCR] /* read OS timer */ 492*84ad6884SPeter Tyser add r1, r1, #0x800 /* let OSMR3 match after */ 493*84ad6884SPeter Tyser add r1, r1, #0x800 /* 4096*(1/3.6864MHz)=1ms */ 494*84ad6884SPeter Tyser str r1, [r0, #OSMR3] 495*84ad6884SPeter Tyser 496*84ad6884SPeter Tyserreset_endless: 497*84ad6884SPeter Tyser 498*84ad6884SPeter Tyser b reset_endless 499