1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
8 * $Id: crt0.S 18776 2008-10-11 18:32:17Z gevaerts $
10 * Copyright (C) 2008 by Marcoen Hirschberg
11 * Copyright (C) 2008 by Denes Balatoni
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 ****************************************************************************/
25 .section .intvect,"ax",%progbits
28 /* Exception vectors */
30 #if CONFIG_CPU==S5L8701 && defined(BOOTLOADER)
35 ldr pc, =undef_instr_handler
36 ldr pc, =software_int_handler
37 ldr pc, =prefetch_abort_handler
38 ldr pc, =data_abort_handler
39 ldr pc, =reserved_handler
42 #if CONFIG_CPU==S5L8700
43 .word 0x43554644 /* DFUC */
47 ldr pc, =newstart2 // we do not want to execute from 0x0 as iram will be mapped there
48 .section .init.text,"ax",%progbits
50 msr cpsr_c, #0xd3 /* enter supervisor mode, disable IRQ/FIQ */
52 #ifdef ROCKBOX_BIG_ENDIAN
54 mrc 15, 0, r0, c1, c0, 0
56 mcr 15, 0, r0, c1, c0, 0 // set bigendian
59 ldr r1, =0x3c800000 // disable watchdog
65 str r0, [r1,#0x08] // mask all interrupts
66 str r0, [r1,#0x20] // mask all external interrupts
68 str r0, [r1,#0x1c] // clear pending external interrupts
69 str r0, [r1] // irq priority
70 str r0, [r1,#0x10] // clear pending interrupts
72 // ldr r1, =0x3cf00000
82 // str r0, [r1,#0x04] // switch backlight on
84 #if CONFIG_CPU==S5L8701
89 str r2, [r1] // remap iram to address 0x0
92 /* Relocate ourself to IRAM - we have been loaded to DRAM */
93 mov r0, #0x08000000 /* source (DRAM) */
94 mov r1, #0x00000000 /* dest (IRAM) */
102 ldr pc, =start_loc /* jump to the relocated start_loc: */
104 #endif /* BOOTLOADER */
105 #endif /* CONFIG_CPU==S5L8701 */
109 str r0, [r1] // CLKCON
111 str r0, [r1,#0x24] // PLLCON
113 ldr r0, =0x21200 // pdiv=2, mdiv=0x12 sdiv=0
115 ldr r0, =0x1ad200 // pdiv=0x1a, mdiv=0xd2 sdiv=0
117 str r0, [r1,#0x04] // PLL0PMS
119 str r0, [r1,#0x14] // PLL0LCNT
121 str r0, [r1,#0x24] // PLLCON
123 ldr r0, [r1,#0x20] // PLLLOCK
127 str r0, [r1,#0x3c] // CLKCON2
128 ldr r0, =0x20803180 // FCLK_CPU = 200MHz, HCLK = 100MHz, PCLK = 50MHz, other clocks off
129 str r0, [r1] // CLKCON
132 mrc 15, 0, r0, c1, c0, 0
136 mcr 15, 0, r0, c1, c0, 0 // asynchronous clocking mode
142 // ldr r0, =0x10100000
143 // ldr r1, =0x38200034
144 // str r0, [r1] // SRAM0/1 data width 16 bit
145 // ldr r0, =0x00220922
146 // ldr r7, =0x38200038
147 // str r0, [r7] // SRAM0/1 clocks
148 // ldr r0, =0x00220922
149 // ldr r9, =0x3820003c
150 // str r0, [r9] // SRAM2/3 clocks
156 /* The following two sections of code (i.e. Nano2G and Meizus) should
157 be unified at some point. */
162 str r0, [r1,#0x28] // PWRCON
164 str r0, [r1,#0x40] // PWRCONEXT
166 mrc 15, 0, r0, c1, c0, 0
169 mcr 15, 0, r0, c1, c0, 0 // disable caches and protection unit
176 mcr 15, 0, r2, c7, c14, 2 // clean and flush dcache single entry
180 add r1, r1, #0x4000000
186 mcr 15, 0, r0, c7, c10, 4 // clean and flush whole dcache
187 mcr 15, 0, r0, c7, c5, 0 // flush icache
188 mcr 15, 0, r0, c7, c6, 0 // flush dcache
191 mcr 15, 0, r0, c6, c0, 1 // CS0: 4GB at offset 0 - everything
192 mcr 15, 0, r0, c6, c0, 0 // DS0: 4GB at offset 0 - everything
194 mov r0, #0x31 // FIXME: calculate that from MEMORYSIZE
196 mov r0, #0x2f // FIXME: calculate that from MEMORYSIZE
198 mcr 15, 0, r0, c6, c1, 1 // CS1: SRAM/SDRAM mirror
199 mcr 15, 0, r0, c6, c1, 0 // DS1: SRAM/SDRAM mirror
200 add r0, r0, #0x08000000
201 mcr 15, 0, r0, c6, c2, 1 // CS2: SDRAM
202 mcr 15, 0, r0, c6, c2, 0 // DS2: SDRAM
204 mcr 15, 0, r0, c6, c3, 1 // CS3: SRAM
205 mcr 15, 0, r0, c6, c3, 0 // DS3: SRAM
207 mcr 15, 0, r0, c6, c4, 1 // CS4: NOR flash
208 mcr 15, 0, r0, c6, c4, 0 // DS4: NOR flash
210 mcr 15, 0, r0, c6, c5, 1 // CS5: unused
211 mcr 15, 0, r0, c6, c5, 0 // DS5: unused
212 mcr 15, 0, r0, c6, c6, 1 // CS6: unused
213 mcr 15, 0, r0, c6, c6, 0 // DS6: unused
214 mcr 15, 0, r0, c6, c7, 1 // CS7: unused
215 mcr 15, 0, r0, c6, c7, 0 // DS7: unused
217 mcr 15, 0, r0, c2, c0, 1 // CS1-4: cacheable
218 mcr 15, 0, r0, c2, c0, 0 // DS1-4: cacheable
219 mcr 15, 0, r0, c3, c0, 0 // DS1-4: write cacheable
221 mcr 15, 0, r0, c5, c0, 1 // CS0-4: full access
222 mcr 15, 0, r0, c5, c0, 0 // DS0-4: full access
224 mrc 15, 0, r0, c1, c0, 0
227 mcr 15, 0, r0, c1, c0, 0 // re-enable protection unit and caches
233 str r0, [r1, #40] // enable clock for all peripherals
235 str r0, [r1, #44] // do not enter any power saving mode
238 mrc 15, 0, r0, c1, c0, 0
240 mcr 15, 0, r0, c1, c0, 0 // disable protection unit
243 mrc 15, 0, r0, c1, c0, 0
245 mcr 15, 0, r0, c1, c0, 0 // dcache disable
248 mrc 15, 0, r0, c1, c0, 0
250 mcr 15, 0, r0, c1, c0, 0 // icache disable
257 mcr 15, 0, r2, c7, c14, 2 // clean and flush dcache single entry
261 add r1, r1, #0x4000000
267 mcr 15, 0, r0, c7, c10, 4 // clean and flush whole dcache
270 mcr 15, 0, r0, c7, c5, 0 // flush icache
273 mcr 15, 0, r0, c7, c6, 0 // flush dcache
276 mcr 15, 0, r0, c6, c0, 1
278 mcr 15, 0, r0, c6, c1, 1
280 mcr 15, 0, r0, c6, c2, 1
282 mcr 15, 0, r0, c6, c3, 1
284 mcr 15, 0, r0, c6, c4, 1
286 mcr 15, 0, r0, c6, c0, 0
288 mcr 15, 0, r0, c6, c1, 0
290 mcr 15, 0, r0, c6, c2, 0
292 mcr 15, 0, r0, c6, c3, 0
294 mcr 15, 0, r0, c6, c4, 0
296 mcr 15, 0, r0, c2, c0, 1
298 mcr 15, 0, r0, c2, c0, 0
300 mcr 15, 0, r0, c3, c0, 0
302 mcr 15, 0, r0, c5, c0, 1
304 mcr 15, 0, r0, c5, c0, 0 // set up protection and caching
307 mrc 15, 0, r0, c1, c0, 0
309 mcr 15, 0, r0, c1, c0, 0 // dcache enable
312 mrc 15, 0, r0, c1, c0, 0
314 mcr 15, 0, r0, c1, c0, 0 // icache enable
317 mrc 15, 0, r0, c1, c0, 0
319 mcr 15, 0, r0, c1, c0, 0 // enable protection unit
322 #if CONFIG_CPU==S5L8700 || !defined(BOOTLOADER)
323 /* Copy interrupt vectors to iram */
324 ldr r2, =_intvectstart
326 ldr r4, =_intvectcopy
334 /* Initialise bss section to zero */
343 #if CONFIG_CPU==S5L8700 && defined(BOOTLOADER)
344 /* Copy icode and data to ram */
356 /* Copy icode and data to ram */
366 /* Initialise ibss section to zero */
376 /* Set up some stack and munge it with 0xdeadbeef */
385 /* Set up stack for IRQ mode */
387 ldr sp, =_irqstackend
389 /* Set up stack for FIQ mode */
391 ldr sp, =_fiqstackend
393 /* Let abort and undefined modes use IRQ stack */
395 ldr sp, =_irqstackend
397 ldr sp, =_irqstackend
399 /* Switch back to supervisor mode */
402 // if we did not switch remap on, device
403 // would crash when MENU is pressed,
404 // as that button is connected to BOOT_MODE pin
405 #if CONFIG_CPU==S5L8700
412 str r0, [r1] // remap iram to address 0x0
420 /* All illegal exceptions call into UIE with exception address as first
421 * parameter. This is calculated differently depending on which exception
422 * we're in. Second parameter is exception number, used for a string lookup
429 /* We run supervisor mode most of the time, and should never see a software
430 * exception being thrown. Perhaps make it illegal and call UIE? */
431 software_int_handler:
435 prefetch_abort_handler: