|  | /* | 
|  | * Copyright (C) 2005-2008 Atmel Corporation | 
|  | * | 
|  | * See file CREDITS for list of people who contributed to this | 
|  | * project. | 
|  | * | 
|  | * This program is free software; you can redistribute it and/or | 
|  | * modify it under the terms of the GNU General Public License as | 
|  | * published by the Free Software Foundation; either version 2 of | 
|  | * the License, or (at your option) any later version. | 
|  | * | 
|  | * This program is distributed in the hope that it will be useful, | 
|  | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|  | * GNU General Public License for more details. | 
|  | * | 
|  | * You should have received a copy of the GNU General Public License | 
|  | * along with this program; if not, write to the Free Software | 
|  | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | 
|  | * MA 02111-1307 USA | 
|  | */ | 
|  | #include <config.h> | 
|  | #include <asm/ptrace.h> | 
|  | #include <asm/sysreg.h> | 
|  |  | 
|  | #define SYSREG_MMUCR_I_OFFSET	2 | 
|  | #define SYSREG_MMUCR_S_OFFSET	4 | 
|  |  | 
|  | #define SR_INIT (SYSREG_BIT(GM) | SYSREG_BIT(EM) | SYSREG_BIT(M0)) | 
|  | #define CPUCR_INIT (SYSREG_BIT(BI) | SYSREG_BIT(BE)		\ | 
|  | | SYSREG_BIT(FE) | SYSREG_BIT(RE)		\ | 
|  | | SYSREG_BIT(IBE) | SYSREG_BIT(IEE)) | 
|  |  | 
|  | /* | 
|  | * To save some space, we use the same entry point for | 
|  | * exceptions and reset. This avoids lots of alignment padding | 
|  | * since the reset vector is always suitably aligned. | 
|  | */ | 
|  | .section .exception.text, "ax", @progbits | 
|  | .global	_start | 
|  | .global	_evba | 
|  | .type	_start, @function | 
|  | .type	_evba, @function | 
|  | _start: | 
|  | .size	_start, 0 | 
|  | _evba: | 
|  | .org	0x00 | 
|  | rjmp	unknown_exception	/* Unrecoverable exception */ | 
|  | .org	0x04 | 
|  | rjmp	unknown_exception	/* TLB multiple hit */ | 
|  | .org	0x08 | 
|  | rjmp	unknown_exception	/* Bus error data fetch */ | 
|  | .org	0x0c | 
|  | rjmp	unknown_exception	/* Bus error instruction fetch */ | 
|  | .org	0x10 | 
|  | rjmp	unknown_exception	/* NMI */ | 
|  | .org	0x14 | 
|  | rjmp	unknown_exception	/* Instruction address */ | 
|  | .org	0x18 | 
|  | rjmp	unknown_exception	/* ITLB protection */ | 
|  | .org	0x1c | 
|  | rjmp	unknown_exception	/* Breakpoint */ | 
|  | .org	0x20 | 
|  | rjmp	unknown_exception	/* Illegal opcode */ | 
|  | .org	0x24 | 
|  | rjmp	unknown_exception	/* Unimplemented instruction */ | 
|  | .org	0x28 | 
|  | rjmp	unknown_exception	/* Privilege violation */ | 
|  | .org	0x2c | 
|  | rjmp	unknown_exception	/* Floating-point */ | 
|  | .org	0x30 | 
|  | rjmp	unknown_exception	/* Coprocessor absent */ | 
|  | .org	0x34 | 
|  | rjmp	unknown_exception	/* Data Address (read) */ | 
|  | .org	0x38 | 
|  | rjmp	unknown_exception	/* Data Address (write) */ | 
|  | .org	0x3c | 
|  | rjmp	unknown_exception	/* DTLB Protection (read) */ | 
|  | .org	0x40 | 
|  | rjmp	unknown_exception	/* DTLB Protection (write) */ | 
|  | .org	0x44 | 
|  | rjmp	unknown_exception	/* DTLB Modified */ | 
|  |  | 
|  | .org	0x50 | 
|  | rjmp	unknown_exception	/* ITLB Miss */ | 
|  | .org	0x60 | 
|  | rjmp	unknown_exception	/* DTLB Miss (read) */ | 
|  | .org	0x70 | 
|  | rjmp	unknown_exception	/* DTLB Miss (write) */ | 
|  |  | 
|  | .size	_evba, . - _evba | 
|  |  | 
|  | .align	2 | 
|  | .type	unknown_exception, @function | 
|  | unknown_exception: | 
|  | /* Figure out whether we're handling an exception (Exception | 
|  | * mode) or just booting (Supervisor mode). */ | 
|  | csrfcz	SYSREG_M1_OFFSET | 
|  | brcc	at32ap_cpu_bootstrap | 
|  |  | 
|  | /* This is an exception. Complain. */ | 
|  | pushm	r0-r12 | 
|  | sub	r8, sp, REG_R12 - REG_R0 - 4 | 
|  | mov	r9, lr | 
|  | mfsr	r10, SYSREG_RAR_EX | 
|  | mfsr	r11, SYSREG_RSR_EX | 
|  | pushm	r8-r11 | 
|  | mfsr	r12, SYSREG_ECR | 
|  | mov	r11, sp | 
|  | rcall	do_unknown_exception | 
|  | 1:	rjmp	1b | 
|  |  | 
|  | /* The COUNT/COMPARE timer interrupt handler */ | 
|  | .global	timer_interrupt_handler | 
|  | .type	timer_interrupt_handler,@function | 
|  | .align	2 | 
|  | timer_interrupt_handler: | 
|  | /* | 
|  | * Increment timer_overflow and re-write COMPARE with 0xffffffff. | 
|  | * | 
|  | * We're running at interrupt level 3, so we don't need to save | 
|  | * r8-r12 or lr to the stack. | 
|  | */ | 
|  | lda.w	r8, timer_overflow | 
|  | ld.w	r9, r8[0] | 
|  | mov	r10, -1 | 
|  | mtsr	SYSREG_COMPARE, r10 | 
|  | sub	r9, -1 | 
|  | st.w	r8[0], r9 | 
|  | rete | 
|  |  | 
|  | /* | 
|  | * CPU bootstrap after reset is handled here. SoC code may | 
|  | * override this in case they need to initialize oscillators, | 
|  | * etc. | 
|  | */ | 
|  | .section .text.at32ap_cpu_bootstrap, "ax", @progbits | 
|  | .global	at32ap_cpu_bootstrap | 
|  | .weak	at32ap_cpu_bootstrap | 
|  | .type	at32ap_cpu_bootstrap, @function | 
|  | .align	2 | 
|  | at32ap_cpu_bootstrap: | 
|  | /* Reset the Status Register */ | 
|  | mov	r0, lo(SR_INIT) | 
|  | orh	r0, hi(SR_INIT) | 
|  | mtsr	SYSREG_SR, r0 | 
|  |  | 
|  | /* Reset CPUCR and invalidate the BTB */ | 
|  | mov	r2, CPUCR_INIT | 
|  | mtsr	SYSREG_CPUCR, r2 | 
|  |  | 
|  | /* Flush the caches */ | 
|  | mov	r1, 0 | 
|  | cache	r1[4], 8 | 
|  | cache	r1[0], 0 | 
|  | sync	0 | 
|  |  | 
|  | /* Reset the MMU to default settings */ | 
|  | mov	r0, SYSREG_BIT(MMUCR_S) | SYSREG_BIT(MMUCR_I) | 
|  | mtsr	SYSREG_MMUCR, r0 | 
|  |  | 
|  | /* Internal RAM should not need any initialization.  We might | 
|  | have to initialize external RAM here if the part doesn't | 
|  | have internal RAM (or we may use the data cache) */ | 
|  |  | 
|  | /* Jump to cacheable segment */ | 
|  | lddpc	pc, 1f | 
|  |  | 
|  | .align	2 | 
|  | 1:	.long	at32ap_low_level_init | 
|  | .size	_start, . - _start | 
|  |  | 
|  | /* Common CPU bootstrap code after oscillator/cache/etc. init */ | 
|  | .section .text.avr32ap_low_level_init, "ax", @progbits | 
|  | .global	at32ap_low_level_init | 
|  | .type	at32ap_low_level_init, @function | 
|  | .align	2 | 
|  | at32ap_low_level_init: | 
|  | lddpc	sp, sp_init | 
|  |  | 
|  | /* Initialize the GOT pointer */ | 
|  | lddpc	r6, got_init | 
|  | 3:	rsub	r6, pc | 
|  |  | 
|  | /* Let's go */ | 
|  | rjmp	board_init_f | 
|  |  | 
|  | .align	2 | 
|  | .type	sp_init,@object | 
|  | sp_init: | 
|  | .long	CONFIG_SYS_INIT_SP_ADDR | 
|  | got_init: | 
|  | .long	3b - _GLOBAL_OFFSET_TABLE_ | 
|  |  | 
|  | /* | 
|  | * void	relocate_code(new_sp, new_gd, monitor_addr) | 
|  | * | 
|  | * Relocate the u-boot image into RAM and continue from there. | 
|  | * Does not return. | 
|  | */ | 
|  | .section .text.relocate_code,"ax",@progbits | 
|  | .global	relocate_code | 
|  | .type	relocate_code,@function | 
|  | relocate_code: | 
|  | mov	sp, r12		/* use new stack */ | 
|  | mov	r12, r11	/* save new_gd */ | 
|  | mov	r11, r10	/* save destination address */ | 
|  |  | 
|  | /* copy .text section and flush the cache along the way */ | 
|  | lda.w	r8, _text | 
|  | lda.w	r9, _etext | 
|  | sub	lr, r10, r8	/* relocation offset */ | 
|  |  | 
|  | 1:	ldm	r8++, r0-r3 | 
|  | stm	r10, r0-r3 | 
|  | sub	r10, -16 | 
|  | ldm	r8++, r0-r3 | 
|  | stm	r10, r0-r3 | 
|  | sub	r10, -16 | 
|  | cp.w	r8, r9 | 
|  | cache	r10[-4], 0x0d	/* dcache clean/invalidate */ | 
|  | cache	r10[-4], 0x01	/* icache invalidate */ | 
|  | brlt	1b | 
|  |  | 
|  | /* flush write buffer */ | 
|  | sync	0 | 
|  |  | 
|  | /* copy data sections */ | 
|  | lda.w	r9, _edata | 
|  | 1:	ld.d	r0, r8++ | 
|  | st.d	r10++, r0 | 
|  | cp.w	r8, r9 | 
|  | brlt	1b | 
|  |  | 
|  | /* zero out .bss */ | 
|  | mov	r0, 0 | 
|  | mov	r1, 0 | 
|  | lda.w	r9, _end | 
|  | sub	r9, r8 | 
|  | 1:	st.d	r10++, r0 | 
|  | sub	r9, 8 | 
|  | brgt	1b | 
|  |  | 
|  | /* jump to RAM */ | 
|  | sub	r0, pc, . - in_ram | 
|  | add	pc, r0, lr | 
|  |  | 
|  | .align	2 | 
|  | in_ram: | 
|  | /* find the new GOT and relocate it */ | 
|  | lddpc	r6, got_init_reloc | 
|  | 3:	rsub	r6, pc | 
|  | mov	r8, r6 | 
|  | lda.w	r9, _egot | 
|  | lda.w	r10, _got | 
|  | sub	r9, r10 | 
|  | 1:	ld.w	r0, r8[0] | 
|  | add	r0, lr | 
|  | st.w	r8++, r0 | 
|  | sub	r9, 4 | 
|  | brgt	1b | 
|  |  | 
|  | /* Move the exception handlers */ | 
|  | mfsr	r2, SYSREG_EVBA | 
|  | add	r2, lr | 
|  | mtsr	SYSREG_EVBA, r2 | 
|  |  | 
|  | /* Do the rest of the initialization sequence */ | 
|  | call	board_init_r | 
|  |  | 
|  | .align	2 | 
|  | got_init_reloc: | 
|  | .long	3b - _GLOBAL_OFFSET_TABLE_ | 
|  |  | 
|  | .size	relocate_code, . - relocate_code |