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 /* Meizu M3 SDRAM settings */
27 #define SDR_DSS_SEL_B 1
28 #define SDR_DSS_SEL_O 1
29 #define SDR_DSS_SEL_C 1
30 #define SDR_TIMING 0x6A491D
31 #define SDR_CONFIG 0x900
33 #define SDR_EMRS 0x4000
36 /* Meizu M6SP SDRAM settings */
38 #define SDR_DSS_SEL_B 5
39 #define SDR_DSS_SEL_O 2
40 #define SDR_DSS_SEL_C 2
41 #define SDR_TIMING 0x6A4965
42 #define SDR_CONFIG 0x700
44 #define SDR_EMRS 0x4033
47 .section .intvect,"ax",%progbits
50 /* Exception vectors */
52 #if CONFIG_CPU==S5L8701 && defined(BOOTLOADER)
57 ldr pc, =undef_instr_handler
58 ldr pc, =software_int_handler
59 ldr pc, =prefetch_abort_handler
60 ldr pc, =data_abort_handler
61 ldr pc, =reserved_handler
64 #if CONFIG_CPU==S5L8700
65 .word 0x43554644 /* DFUC */
69 ldr pc, =newstart2 // we do not want to execute from 0x0 as iram will be mapped there
70 .section .init.text,"ax",%progbits
72 msr cpsr_c, #0xd3 /* enter supervisor mode, disable IRQ/FIQ */
74 #ifdef ROCKBOX_BIG_ENDIAN
76 mrc 15, 0, r0, c1, c0, 0
78 mcr 15, 0, r0, c1, c0, 0 // set bigendian
81 ldr r1, =0x3c800000 // disable watchdog
87 str r0, [r1,#0x08] // mask all interrupts
88 str r0, [r1,#0x20] // mask all external interrupts
90 str r0, [r1,#0x1c] // clear pending external interrupts
91 str r0, [r1] // irq priority
92 str r0, [r1,#0x10] // clear pending interrupts
94 // ldr r1, =0x3cf00000
101 // ldr r0, [r1,#0x04]
104 // str r0, [r1,#0x04] // switch backlight on
106 #if CONFIG_CPU==S5L8701
111 str r2, [r1] // remap iram to address 0x0
114 /* Relocate ourself to IRAM - we have been loaded to DRAM */
115 mov r0, #0x08000000 /* source (DRAM) */
116 mov r1, #0x22000000 /* dest (IRAM) */
124 ldr pc, =start_loc /* jump to the relocated start_loc: */
126 #endif /* BOOTLOADER */
127 #endif /* CONFIG_CPU==S5L8701 */
129 #if !(CONFIG_CPU==S5L8701 && defined(BOOTLOADER))
132 str r0, [r1] // CLKCON
134 str r0, [r1,#0x24] // PLLCON
136 ldr r0, =0x21200 // pdiv=2, mdiv=0x12 sdiv=0
138 ldr r0, =0x1ad200 // pdiv=0x1a, mdiv=0xd2 sdiv=0
140 str r0, [r1,#0x04] // PLL0PMS
142 str r0, [r1,#0x14] // PLL0LCNT
144 str r0, [r1,#0x24] // PLLCON
146 ldr r0, [r1,#0x20] // PLLLOCK
150 str r0, [r1,#0x3c] // CLKCON2
151 ldr r0, =0x20803180 // FCLK_CPU = 200MHz, HCLK = 100MHz, PCLK = 50MHz, other clocks off
152 str r0, [r1] // CLKCON
155 mrc 15, 0, r0, c1, c0, 0
159 mcr 15, 0, r0, c1, c0, 0 // asynchronous clocking mode
166 // ldr r0, =0x10100000
167 // ldr r1, =0x38200034
168 // str r0, [r1] // SRAM0/1 data width 16 bit
169 // ldr r0, =0x00220922
170 // ldr r7, =0x38200038
171 // str r0, [r7] // SRAM0/1 clocks
172 // ldr r0, =0x00220922
173 // ldr r9, =0x3820003c
174 // str r0, [r9] // SRAM2/3 clocks
180 /* The following two sections of code (i.e. Nano2G and Meizus) should
181 be unified at some point. */
186 str r0, [r1,#0x28] // PWRCON
188 str r0, [r1,#0x40] // PWRCONEXT
190 mrc 15, 0, r0, c1, c0, 0
193 mcr 15, 0, r0, c1, c0, 0 // disable caches and protection unit
200 mcr 15, 0, r2, c7, c14, 2 // clean and flush dcache single entry
204 add r1, r1, #0x4000000
210 mcr 15, 0, r0, c7, c10, 4 // clean and flush whole dcache
211 mcr 15, 0, r0, c7, c5, 0 // flush icache
212 mcr 15, 0, r0, c7, c6, 0 // flush dcache
215 mcr 15, 0, r0, c6, c0, 1 // CS0: 4GB at offset 0 - everything
216 mcr 15, 0, r0, c6, c0, 0 // DS0: 4GB at offset 0 - everything
218 mov r0, #0x31 // FIXME: calculate that from MEMORYSIZE
220 mov r0, #0x2f // FIXME: calculate that from MEMORYSIZE
222 mcr 15, 0, r0, c6, c1, 1 // CS1: SRAM/SDRAM mirror
223 mcr 15, 0, r0, c6, c1, 0 // DS1: SRAM/SDRAM mirror
224 add r0, r0, #0x08000000
225 mcr 15, 0, r0, c6, c2, 1 // CS2: SDRAM
226 mcr 15, 0, r0, c6, c2, 0 // DS2: SDRAM
228 mcr 15, 0, r0, c6, c3, 1 // CS3: SRAM
229 mcr 15, 0, r0, c6, c3, 0 // DS3: SRAM
231 mcr 15, 0, r0, c6, c4, 1 // CS4: NOR flash
232 mcr 15, 0, r0, c6, c4, 0 // DS4: NOR flash
234 mcr 15, 0, r0, c6, c5, 1 // CS5: unused
235 mcr 15, 0, r0, c6, c5, 0 // DS5: unused
236 mcr 15, 0, r0, c6, c6, 1 // CS6: unused
237 mcr 15, 0, r0, c6, c6, 0 // DS6: unused
238 mcr 15, 0, r0, c6, c7, 1 // CS7: unused
239 mcr 15, 0, r0, c6, c7, 0 // DS7: unused
241 mcr 15, 0, r0, c2, c0, 1 // CS1-4: cacheable
242 mcr 15, 0, r0, c2, c0, 0 // DS1-4: cacheable
243 mcr 15, 0, r0, c3, c0, 0 // DS1-4: write cacheable
245 mcr 15, 0, r0, c5, c0, 1 // CS0-4: full access
246 mcr 15, 0, r0, c5, c0, 0 // DS0-4: full access
248 mrc 15, 0, r0, c1, c0, 0
251 mcr 15, 0, r0, c1, c0, 0 // re-enable protection unit and caches
257 str r0, [r1, #40] // enable clock for all peripherals
259 str r0, [r1, #44] // do not enter any power saving mode
261 #if defined(MEIZU_M6SP) || defined(MEIZU_M3)
262 /* setup SDRAM for Meizu M6SP */
263 ldr r1, =0x38200000
\r
264 // configure SDR drive strength and pad settings
\r
265 mov r0, #SDR_DSS_SEL_B
\r
266 str r0, [r1, #0x4C] // MIU_DSS_SEL_B
\r
267 mov r0, #SDR_DSS_SEL_O
\r
268 str r0, [r1, #0x50] // MIU_DSS_SEL_O
\r
269 mov r0, #SDR_DSS_SEL_C
\r
270 str r0, [r1, #0x54] // MIU_DSS_SEL_C
\r
272 str r0, [r1, #0x60] // SSTL2_PAD_ON
\r
275 mov r2, #0xFFFDFFFF
\r
278 str r0, [r1, #0x40] // MIUORG
\r
279 // set controller configuration
281 str r0, [r1] // MIUCON
282 // set SDRAM timing
\r
283 ldr r0, =SDR_TIMING
\r
284 str r0, [r1, #0x10] // MIUSDPARA
\r
285 // set refresh rate
\r
287 str r0, [r1, #0x08] // MIUAREF
\r
288 // initialise SDRAM
\r
290 str r0, [r1, #0x04] // MIUCOM = nop
\r
292 str r0, [r1, #0x04] // MIUCOM = precharge all banks
\r
297 str r0, [r1, #0x04] // MIUCOM = auto-refresh
\r
302 str r0, [r1, #0x04] // MIUCOM = auto-refresh
\r
307 str r0, [r1, #0x04] // MIUCOM = auto-refresh
\r
312 // set mode register
\r
314 str r0, [r1, #0x0C] // MIUMRS
\r
316 str r0, [r1, #0x04] // MIUCOM = mode register set
\r
318 str r0, [r1, #0x0C] // MIUMRS
\r
320 str r0, [r1, #0x04] // MIUCOM = mode register set
\r
321 #endif /* MEIZU_M6SP */
324 mrc 15, 0, r0, c1, c0, 0
326 mcr 15, 0, r0, c1, c0, 0 // disable protection unit
329 mrc 15, 0, r0, c1, c0, 0
331 mcr 15, 0, r0, c1, c0, 0 // dcache disable
334 mrc 15, 0, r0, c1, c0, 0
336 mcr 15, 0, r0, c1, c0, 0 // icache disable
343 mcr 15, 0, r2, c7, c14, 2 // clean and flush dcache single entry
347 add r1, r1, #0x4000000
353 mcr 15, 0, r0, c7, c10, 4 // clean and flush whole dcache
356 mcr 15, 0, r0, c7, c5, 0 // flush icache
359 mcr 15, 0, r0, c7, c6, 0 // flush dcache
362 mcr 15, 0, r0, c6, c0, 1
364 mcr 15, 0, r0, c6, c1, 1
366 mcr 15, 0, r0, c6, c2, 1
368 mcr 15, 0, r0, c6, c3, 1
370 mcr 15, 0, r0, c6, c4, 1
372 mcr 15, 0, r0, c6, c0, 0
374 mcr 15, 0, r0, c6, c1, 0
376 mcr 15, 0, r0, c6, c2, 0
378 mcr 15, 0, r0, c6, c3, 0
380 mcr 15, 0, r0, c6, c4, 0
382 mcr 15, 0, r0, c2, c0, 1
384 mcr 15, 0, r0, c2, c0, 0
386 mcr 15, 0, r0, c3, c0, 0
388 mcr 15, 0, r0, c5, c0, 1
390 mcr 15, 0, r0, c5, c0, 0 // set up protection and caching
393 mrc 15, 0, r0, c1, c0, 0
395 mcr 15, 0, r0, c1, c0, 0 // dcache enable
398 mrc 15, 0, r0, c1, c0, 0
400 mcr 15, 0, r0, c1, c0, 0 // icache enable
403 mrc 15, 0, r0, c1, c0, 0
405 mcr 15, 0, r0, c1, c0, 0 // enable protection unit
408 #if CONFIG_CPU==S5L8700 || !defined(BOOTLOADER)
409 /* Copy interrupt vectors to iram */
410 ldr r2, =_intvectstart
412 ldr r4, =_intvectcopy
420 /* Initialise bss section to zero */
429 #if CONFIG_CPU==S5L8700 && defined(BOOTLOADER)
430 /* Copy icode and data to ram */
442 /* Copy icode and data to ram */
452 /* Initialise ibss section to zero */
462 /* Set up some stack and munge it with 0xdeadbeef */
471 /* Set up stack for IRQ mode */
473 ldr sp, =_irqstackend
475 /* Set up stack for FIQ mode */
477 ldr sp, =_fiqstackend
479 /* Let abort and undefined modes use IRQ stack */
481 ldr sp, =_irqstackend
483 ldr sp, =_irqstackend
485 /* Switch back to supervisor mode */
488 // if we did not switch remap on, device
489 // would crash when MENU is pressed,
490 // as that button is connected to BOOT_MODE pin
491 #if CONFIG_CPU==S5L8700
498 str r0, [r1] // remap iram to address 0x0
506 /* All illegal exceptions call into UIE with exception address as first
507 * parameter. This is calculated differently depending on which exception
508 * we're in. Second parameter is exception number, used for a string lookup
515 /* We run supervisor mode most of the time, and should never see a software
516 * exception being thrown. Perhaps make it illegal and call UIE? */
517 software_int_handler:
521 prefetch_abort_handler: