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