summaryrefslogtreecommitdiffstats
path: root/firmware/target/arm/imx31/crt0.S
blob: 1c1ae557361988b196f8903ecc1f99c6c429e1b7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
/***************************************************************************
 *             __________               __   ___.
 *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
 *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
 *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
 *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
 *                     \/            \/     \/    \/            \/
 * $Id$
 *
 * Copyright (C) 2002 by Linus Nielsen Feltzing
 *
 * 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 software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
 * KIND, either express or implied.
 *
 ****************************************************************************/
#include "config.h"
#include "cpu.h"

    .section .init.text,"ax",%progbits

    .global    start
start:
    /* Exception vectors */
    b       newstart
    b       undef_instr_handler
    b       software_int_handler
    b       prefetch_abort_handler
    b       data_abort_handler
    b       reserved_handler
    /* These vectors are unused */
    subs    pc, lr, #4              @ b       irq_handler
    subs    pc, lr, #4              @ b       fiq_handler
    .balign 0x40, 0x6B

/* Arm bootloader and startup code based on startup.s from the iPodLinux loader
 *
 * Copyright (c) 2003, Daniel Palffy (dpalffy (at) rainstorm.org)
 * Copyright (c) 2005, Bernard Leach <leachbj@bouncycastle.org>
 *
 */

/* Bootloader:
 * Initially this code is running at VA 0x8a000000 (PA 0x82000000).
 * The mapping stub is copied to IRAM (0x1fffc000), sets up the MMU and
 * jumps into the final VA remapping starting at 0x02000000 (32MB).
 *
 * Firmware:
 * This code will be running from VA 0x00000000 (PA 0x80000000) and perform
 * similar steps to the bootloader code.
 */
newstart:
    msr     cpsr_c, #0xd3 /* enter supervisor mode, disable IRQ/FIQ */

    adr     r2, remap_start    /* Load PC-relative labels (relocatable) */
    adr     r3, remap_end
    ldr     r5, =TTB_BASE_ADDR /* TTB pointer */
    ldr     r6, =IRAM_BASE_ADDR
    mov     r1, r6

1:  /* Copy remapping stub to IRAM */
    cmp     r3, r2
    ldrhi   r4, [r2], #4
    strhi   r4, [r1], #4
    bhi     1b

    bx      r6

    /* Remapping stub. No absolute addresses may be used until after the
     * remapping is complete. */
remap_start:
    mrc     p15, 0, r3, c1, c0, 0  /* perform writeback if D cache is enabled */
    tst     r3, #(1 <<  2)         /* dcache? */
    tsteq   r3, #(1 << 12)         /* or icache? */
    mov     r0, #0
    mcrne   p15, 0, r0, c7, c10, 0 /* clean dcache */
    mcrne   p15, 0, r0, c7, c7, 0  /* invalidate I cache and D cache */
    mcr     p15, 0, r0, c8, c7, 0  /* invalidate TLBs */
    mcr     p15, 0, r0, c7, c10, 4 /* Drain the write buffer */

    mcr     p15, 0, r0, c13, c0, 0
    mcr     p15, 0, r0, c13, c0, 1

    /* Also setup the Peripheral Port Remap register inside the core */
    mov     r0, #0x40000000        /* start from AIPS 2GB region */
    add     r0, r0, #0x15
    mcr     p15, 0, r0, c15, c2, 4

    /*** L2 Cache setup/invalidation/disable ***/
    /* Disable L2 cache first */
    mov     r0, #L2CC_BASE_ADDR
    mov     r1, #0
    str     r1, [r0, #L2_CACHE_CTL_REG]

    /* Disble L1 caches and memory manager */
    bic     r3, r3, #(1 << 12)    /* L1 I-cache disabled */
    bic     r3, r3, #((1 << 2) |  /* L1 D-cache disabled */ \
                      (1 << 0))   /* MMU disabled */
    mcr     p15, 0, r3, c1, c0, 0

    /*
     * Configure L2 Cache:
     * - 128k size(16k way)
     * - 8-way associativity
     * - 0 ws TAG/VALID/DIRTY
     * - 4 ws DATA R/W
     */
    mov     r1, #0x00130000
    orr     r1, r1, #0x24
    str     r1, [r0, #L2_CACHE_AUX_CTL_REG]

    /* Invalidate L2 */
    mov     r1, #0x000000FF
    str     r1, [r0, #L2_CACHE_INV_WAY_REG]
1:
    /* Poll Invalidate By Way register */
    ldr     r1, [r0, #L2_CACHE_INV_WAY_REG]
    cmp     r1, #0
    bne     1b

    /*** End of L2 operations ***/

    /* TTB Initialisation */

    /* Set TTB base address */
    mcr     p15, 0, r5, c2, c0, 0

    /* Set all domains to manager status */
    mvn     r0, #0
    mcr     p15, 0, r0, c3, c0, 0

    /* Set page tables */

    /* Map each memory loc to itself
     * not cached, not buffered */
                                   /* Physical address = 0x0 */
    mov     r1,      #(1 << 10)    /* superuser - r/w, user - no access */
    orr     r1, r1, #((0 <<  5)  | /* domain 0th */ \
                      (1 <<  4)  | /* should be "1" */ \
                      (1 <<  1))   /* Section signature */
    mov     r2, r5
    add     r3, r5, #TTB_SIZE   /* End position */
1:
    str     r1, [r2], #4
    add     r1, r1, #(1 << 20)  /* Next MB */
    cmp     r2, r3
    blo     1b

    /* Bits 31:20 of r1 will be 0 due to wraparound in previous loop */

    /* Map PA:0x80000000-0x83ffffff to VA:0x00000000-0x03f00000
     * cached, buffered */
    mov     r2, r5                 /* TTB pointer */
    add     r3, r5, #64*4          /* End position */
    orr     r1, r1, #(0x80000000 | /* Physical address */ \
                      (1 << 3) |   /* cache flag */ \
                      (1 << 2))    /* buffer flag */
1:
    str     r1, [r2], #4
    add     r1, r1, #(1 << 20)
    cmp     r2, r3
    blo     1b

    /* Map TTB, FRAME and QHARRAY section PA:0x83f00000-0x83ffffff to
     * VA:0x04000000-0x040fffff
     * not cache, buffered */
    sub     r1, r1, #0x00100000
    bic     r1, r1, #(1 << 3)     /* clear cache flag */
    str     r1, [r5, #64*4]

    /* Enable MMU */
    mov     r0, #0
    mcr     p15, 0, r0, c8, c7, 0 /* Invalidate TLB */
    mcr     p15, 0, r0, c7, c7, 0 /* Invalidate icache and dcache */

    /* Auxilliary control register */
    mrc     p15, 0, r0, c1, c0, 1
    bic     r0, r0, #((1 << 6) | /* Restrict cache size OFF */ \
                      (1 << 5) | /* Enable block tranfer cache operations */ \
                      (1 << 4) | /* Clean+Invalidate cache operation ON */ \
                      (1 << 3))  /* Round-robin micro TLB replacement */
    orr     r0, r0, #((1 << 2) | /* Static branch prediction ON */ \
                      (1 << 1) | /* Dynamic branch prediction ON */ \
                      (1 << 0))  /* Return stack enabled */
    mcr     p15, 0, r0, c1, c0, 1

    /* Control register */
    mrc     p15, 0, r0, c1, c0, 0
    bic     r0, r0, #((1 << 29) | /* AF by AP disabled */ \
                      (1 << 28) | /* TEX remap disabled */ \
                      (1 << 23))  /* Sub AP bits enabled (compatible) */
    bic     r0, r0, #((1 << 21) | /* All performance features enabled */ \
                      (1 << 15))  /* Loads to PC set T bit */
    bic     r0, r0, #((1 << 13))  /* Low vectors */
    bic     r0, r0, #((1 <<  1))  /* Strict alignment disabled */
    orr     r0, r0, #((1 << 24) | /* Vectored interrupt ON */ \
                      (1 << 22))  /* Unaligned access support enabled */
    orr     r0, r0, #((1 << 14) | /* Round-robin replacement for I/D caches */ \
                      (1 << 12) | /* L1 I-cache enabled */ \
                      (1 << 11) | /* Program flow prediction enabled */ \
                      (1 <<  9) | /* ROM protection enabled */ \
                      (1 <<  8))  /* MMU protection enabled */
    orr     r0, r0, #((1 <<  2) | /* L1 D-cache enabled */ \
                      (1 <<  0))  /* MMU enabled */
    mcr     p15, 0, r0, c1, c0, 0
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    ldr     pc, L_post_remap
L_post_remap:
    .word remap_end
remap_end:

#ifdef BOOTLOADER
    /* Copy bootloader exception handler code to address 0 */
    ldr     r2, =_vectorsstart
    ldr     r3, =_vectorsend
    ldr     r4, =_vectorscopy
1:
    cmp     r3, r2
    ldrhi   r5, [r4], #4
    strhi   r5, [r2], #4
    bhi     1b
#endif /* BOOTLOADER */

#ifdef HAVE_INIT_ATTR
    /* copy init data to codec buffer */
    /* must be done before bss is zeroed */
    ldr     r4, =_initcopy
    ldr     r3, =_initend
    ldr     r2, =_initstart
1:
    cmp     r3, r2
    ldrhi   r5, [r4], #4
    strhi   r5, [r2], #4
    bhi     1b
#endif /* HAVE_INIT_ATTR */

    /* Initialise bss and ncbss sections to zero */
    ldr     r2, =_edata
    ldr     r3, =_end
    mov     r4, #0
1:
    cmp     r3, r2
    strhi   r4, [r2], #4
    bhi     1b

    /* Set up stack for IRQ mode */
    msr     cpsr_c, #0xd2
    ldr     sp, =irq_stack

    /* FIQ mode is unused, thus sp_FIQ is irrelevant for it */

    /* Set up stack for SVC mode */
    msr     cpsr_c, #0xd3
    ldr     sp, =svc_stack

    /* Let abort and undefined modes use irq stack */
    msr     cpsr_c, #0xd7
    ldr     sp, =irq_stack
    msr     cpsr_c, #0xdb
    ldr     sp, =irq_stack

    /* Switch to sys mode */
    msr     cpsr_c, #0xdf

    /* Set up some stack and munge it with 0xdeadbeef */
    ldr     sp, =stackend
    ldr     r2, =stackbegin
    ldr     r3, =0xdeadbeef
1:
    cmp     sp, r2
    strhi   r3, [r2], #4
    bhi     1b

#ifndef BOOTLOADER
    /* Enable access to VFP */
    mrc     p15, 0, r3, c1, c0, 2
    orr     r3, r3, #0xf00000
    mcr     p15, 0, r3, c1, c0, 2

    /* Enable VFP */
    mrc     p10, 7, r3, c8, c0, 0
    orr     r3, r3, #1<<30
    mcr     p10, 7, r3, c8, c0, 0

    /* Disable exceptions, enable default NaN, flush-to-zero, round toward 0 */
    mrc     p10, 7, r3, c1, c0, 0
    orr     r3, r3, #15<<22
    bic     r3, r3, #31<<8
    mcr     p10, 7, r3, c1, c0, 0
#endif

    /* Make memory coherent for devices */
    bl      commit_discard_idcache

    bl      main

#ifdef BOOTLOADER
    /* Exception vectors with absolute jumps for bootloader */
    .section .vectors,"aw"
    ldr     pc, [pc, #24]
    ldr     pc, [pc, #24]
    ldr     pc, [pc, #24]
    ldr     pc, [pc, #24]
    ldr     pc, [pc, #24]
    ldr     pc, [pc, #24]
    subs    pc, lr, #4          @ ldr     pc, [pc, #24]
    subs    pc, lr, #4          @ ldr     pc, [pc, #24]
    .word   newstart
    .word   undef_instr_handler
    .word   software_int_handler
    .word   prefetch_abort_handler
    .word   data_abort_handler
    .word   reserved_handler
    .word   0                   @ irq_handler
    .word   0                   @ fiq_handler
#endif /* BOOTLOADER */

    .text

/* All illegal exceptions call into UIE with exception address as first
 * parameter. This is calculated differently depending on which exception
 * we're in. Second parameter is exception number, used for a string lookup
 * in UIE. */
undef_instr_handler:
    sub    r0, lr, #4
    mov    r1, #0
    b      UIE

/* We run sys mode most of the time, and should never see a software
 * exception being thrown. Make it illegal and call UIE. */
software_int_handler:
reserved_handler:
    sub    r0, lr, #4
    mov    r1, #4
    b      UIE

prefetch_abort_handler:
    sub    r0, lr, #4
    mov    r1, #1
    b      UIE

data_abort_handler:
    sub    r0, lr, #8
    mov    r1, #2
    b      UIE

/* 256 words of IRQ stack */
    .section .bss
    .balign  32
    .space   256*4
irq_stack:

/* 256 words of SVC stack */
    .section .bss
    .balign  32
    .space   256*4
svc_stack: