1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2002 by Linus Nielsen Feltzing
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
24 .section .init.text,"ax",%progbits
28 /* Exception vectors */
31 b software_int_handler
32 b prefetch_abort_handler
35 subs pc, lr, #4 @ b irq_handler
39 /* Arm bootloader and startup code based on startup.s from the iPodLinux loader
41 * Copyright (c) 2003, Daniel Palffy (dpalffy (at) rainstorm.org)
42 * Copyright (c) 2005, Bernard Leach <leachbj@bouncycastle.org>
47 * Initially this code is running at VA 0x8a000000 (PA 0x82000000).
48 * The mapping stub is copied to IRAM (0x1fffc000), sets up the MMU and
49 * jumps into the final VA remapping starting at 0x02000000 (32MB).
52 * This code will be running from VA 0x00000000 (PA 0x80000000) and perform
53 * similar steps to the bootloader code.
56 msr cpsr_c, #0xd3 /* enter supervisor mode, disable IRQ/FIQ */
58 adr r2, remap_start /* Load PC-relative labels (relocatable) */
60 ldr r5, =TTB_BASE_ADDR /* TTB pointer */
61 ldr r6, =IRAM_BASE_ADDR
64 1: /* Copy remapping stub to IRAM */
72 /* Remapping stub. No absolute addresses may be used until after the
73 * remapping is complete. */
75 mrc p15, 0, r3, c1, c0, 0 /* perform writeback if D cache is enabled */
76 tst r3, #(1 << 2) /* dcache? */
77 tsteq r3, #(1 << 12) /* or icache? */
79 mcrne p15, 0, r0, c7, c10, 0 /* clean dcache */
80 mcrne p15, 0, r0, c7, c7, 0 /* invalidate I cache and D cache */
81 mcr p15, 0, r0, c8, c7, 0 /* invalidate TLBs */
82 mcr p15, 0, r0, c7, c10, 4 /* Drain the write buffer */
84 mcr p15, 0, r0, c13, c0, 0
85 mcr p15, 0, r0, c13, c0, 1
87 /* Also setup the Peripheral Port Remap register inside the core */
88 mov r0, #0x40000000 /* start from AIPS 2GB region */
90 mcr p15, 0, r0, c15, c2, 4
92 /*** L2 Cache setup/invalidation/disable ***/
93 /* Disable L2 cache first */
94 mov r0, #L2CC_BASE_ADDR
96 str r1, [r0, #L2_CACHE_CTL_REG]
98 /* Disble L1 caches and memory manager */
99 bic r3, r3, #(1 << 12) /* L1 I-cache disabled */
100 bic r3, r3, #((1 << 2) | /* L1 D-cache disabled */ \
101 (1 << 0)) /* MMU disabled */
102 mcr p15, 0, r3, c1, c0, 0
105 * Configure L2 Cache:
106 * - 128k size(16k way)
107 * - 8-way associativity
108 * - 0 ws TAG/VALID/DIRTY
113 str r1, [r0, #L2_CACHE_AUX_CTL_REG]
117 str r1, [r0, #L2_CACHE_INV_WAY_REG]
119 /* Poll Invalidate By Way register */
120 ldr r1, [r0, #L2_CACHE_INV_WAY_REG]
124 /*** End of L2 operations ***/
126 /* TTB Initialisation */
128 /* Set TTB base address */
129 mcr p15, 0, r5, c2, c0, 0
131 /* Set all domains to manager status */
133 mcr p15, 0, r0, c3, c0, 0
135 /* Set page tables */
137 /* Map each memory loc to itself
138 * not cached, not buffered */
139 /* Physical address = 0x0 */
140 mov r1, #(1 << 10) /* superuser - r/w, user - no access */
141 orr r1, r1, #((0 << 5) | /* domain 0th */ \
142 (1 << 4) | /* should be "1" */ \
143 (1 << 1)) /* Section signature */
145 add r3, r5, #TTB_SIZE /* End position */
148 add r1, r1, #(1 << 20) /* Next MB */
152 /* Bits 31:20 of r1 will be 0 due to wraparound in previous loop */
154 /* Map PA:0x80000000-0x83ffffff to VA:0x00000000-0x03f00000
155 * cached, buffered */
156 mov r2, r5 /* TTB pointer */
157 add r3, r5, #64*4 /* End position */
158 orr r1, r1, #(0x80000000 | /* Physical address */ \
159 (1 << 3) | /* cache flag */ \
160 (1 << 2)) /* buffer flag */
163 add r1, r1, #(1 << 20)
167 /* Map TTB, FRAME and QHARRAY section PA:0x83f00000-0x83ffffff to
168 * VA:0x04000000-0x040fffff
169 * not cache, buffered */
170 sub r1, r1, #0x00100000
171 bic r1, r1, #(1 << 3) /* clear cache flag */
176 mcr p15, 0, r0, c8, c7, 0 /* Invalidate TLB */
177 mcr p15, 0, r0, c7, c7, 0 /* Invalidate icache and dcache */
179 /* Auxilliary control register */
180 mrc p15, 0, r0, c1, c0, 1
181 bic r0, r0, #((1 << 6) | /* Restrict cache size OFF */ \
182 (1 << 5) | /* Enable block tranfer cache operations */ \
183 (1 << 4) | /* Clean+Invalidate cache operation ON */ \
184 (1 << 3)) /* Round-robin micro TLB replacement */
185 orr r0, r0, #((1 << 2) | /* Static branch prediction ON */ \
186 (1 << 1) | /* Dynamic branch prediction ON */ \
187 (1 << 0)) /* Return stack enabled */
188 mcr p15, 0, r0, c1, c0, 1
190 /* Control register */
191 mrc p15, 0, r0, c1, c0, 0
192 bic r0, r0, #((1 << 29) | /* AF by AP disabled */ \
193 (1 << 28) | /* TEX remap disabled */ \
194 (1 << 23)) /* Sub AP bits enabled (compatible) */
195 bic r0, r0, #((1 << 21) | /* All performance features enabled */ \
196 (1 << 15)) /* Loads to PC set T bit */
197 bic r0, r0, #((1 << 13)) /* Low vectors */
198 bic r0, r0, #((1 << 1)) /* Strict alignment disabled */
199 orr r0, r0, #((1 << 24) | /* Vectored interrupt ON */ \
200 (1 << 22)) /* Unaligned access support enabled */
201 orr r0, r0, #((1 << 14) | /* Round-robin replacement for I/D caches */ \
202 (1 << 12) | /* L1 I-cache enabled */ \
203 (1 << 11) | /* Program flow prediction enabled */ \
204 (1 << 9) | /* ROM protection enabled */ \
205 (1 << 8)) /* MMU protection enabled */
206 orr r0, r0, #((1 << 2) | /* L1 D-cache enabled */ \
207 (1 << 0)) /* MMU enabled */
208 mcr p15, 0, r0, c1, c0, 0
223 /* Copy bootloader exception handler code to address 0 */
224 ldr r2, =_vectorsstart
226 ldr r4, =_vectorscopy
232 #endif /* BOOTLOADER */
234 #ifdef HAVE_INIT_ATTR
235 /* copy init data to codec buffer */
236 /* must be done before bss is zeroed */
245 #endif /* HAVE_INIT_ATTR */
247 /* Initialise bss and ncbss sections to zero */
256 /* Set up some stack and munge it with 0xdeadbeef */
265 /* Set up stack for IRQ mode */
269 /* Set up stack for FIQ mode */
273 /* Let abort and undefined modes use IRQ stack */
279 /* Switch back to supervisor mode */
283 /* Enable access to VFP */
284 mrc p15, 0, r3, c1, c0, 2
285 orr r3, r3, #0xf00000
286 mcr p15, 0, r3, c1, c0, 2
289 mrc p10, 7, r3, c8, c0, 0
291 mcr p10, 7, r3, c8, c0, 0
293 /* Disable exceptions, enable default NaN, flush-to-zero, round toward 0 */
294 mrc p10, 7, r3, c1, c0, 0
297 mcr p10, 7, r3, c1, c0, 0
300 /* Make memory coherent for devices */
306 /* Exception vectors with absolute jumps for bootloader */
307 .section .vectors,"aw"
314 subs pc, lr, #4 @ ldr pc, [pc, #24]
317 .word undef_instr_handler
318 .word software_int_handler
319 .word prefetch_abort_handler
320 .word data_abort_handler
321 .word reserved_handler
322 .word 0 @ irq_handler
324 #endif /* BOOTLOADER */
328 /* All illegal exceptions call into UIE with exception address as first
329 * parameter. This is calculated differently depending on which exception
330 * we're in. Second parameter is exception number, used for a string lookup
337 /* We run supervisor mode most of the time, and should never see a software
338 * exception being thrown. Perhaps make it illegal and call UIE? */
339 software_int_handler:
343 prefetch_abort_handler:
353 /* 256 words of IRQ stack */
357 /* 256 words of FIQ stack */