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