Meizu M3: configure and use SDRAM
[kugel-rb.git] / firmware / target / arm / s5l8700 / crt0.S
blob67bcc5a796afbed7b8a99cdf7d395593bad38091
1 /***************************************************************************
2  *             __________               __   ___.
3  *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
4  *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
5  *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
6  *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
7  *                     \/            \/     \/    \/            \/
8  * $Id: crt0.S 18776 2008-10-11 18:32:17Z gevaerts $
9  *
10  * Copyright (C) 2008 by Marcoen Hirschberg
11  * Copyright (C) 2008 by Denes Balatoni
12  *
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.
17  *
18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19  * KIND, either express or implied.
20  *
21  ****************************************************************************/
22 #include "config.h"
23 #include "cpu.h"
25 /* Meizu M3 SDRAM settings */
26 #ifdef MEIZU_M3
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
32 #define SDR_MRS         0x37
33 #define SDR_EMRS        0x4000
34 #endif
36 /* Meizu M6SP SDRAM settings */
37 #ifdef MEIZU_M6SP
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
43 #define SDR_MRS         0x33
44 #define SDR_EMRS        0x4033
45 #endif
47     .section .intvect,"ax",%progbits
48     .global    start
49     .global    _newstart
50     /* Exception vectors */
51 start:
52 #if CONFIG_CPU==S5L8701 && defined(BOOTLOADER)
53     b newstart2
54 #else
55     b _newstart
56 #endif
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
62     ldr pc, =irq_handler
63     ldr pc, =fiq_handler
64 #if CONFIG_CPU==S5L8700
65     .word 0x43554644 /* DFUC */
66 #endif
67     .ltorg
68 _newstart:
69     ldr pc, =newstart2 // we do not want to execute from 0x0 as iram will be mapped there
70     .section .init.text,"ax",%progbits
71 newstart2:
72     msr     cpsr_c, #0xd3 /* enter supervisor mode, disable IRQ/FIQ */
74 #ifdef ROCKBOX_BIG_ENDIAN
75     mov r1, #0x80
76     mrc 15, 0, r0, c1, c0, 0
77     orr r0, r0, r1
78     mcr 15, 0, r0, c1, c0, 0 // set bigendian
79 #endif
80              
81     ldr r1, =0x3c800000 // disable watchdog
82     mov r0, #0xa5
83     str r0, [r1]
85     mov r0, #0
86     mov r1, #0x39c00000
87     str r0, [r1,#0x08] // mask all interrupts
88     str r0, [r1,#0x20] // mask all external interrupts
89     mvn r0, #0
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
95 //    ldr r0, [r1]
96 //    mvn r2, #0x30
97 //    and r0, r0, r2
98 //    mov r2, #0x10
99 //    orr r0, r0, r2
100 //    str r0, [r1]
101 //    ldr r0, [r1,#0x04]
102 //    mov r2, #4
103 //    orr r0, r0, r2
104 //    str r0, [r1,#0x04] // switch backlight on
106 #if CONFIG_CPU==S5L8701
107     ldr r1, =0x38200000
108     ldr r2, [r1]
109     orr r2, r2, #1
110     bic r2, r2, #0x10000
111     str r2, [r1] // remap iram to address 0x0
113 #ifdef BOOTLOADER
114     /* Relocate ourself to IRAM - we have been loaded to DRAM */
115     mov    r0, #0x08000000   /* source (DRAM) */
116     mov    r1, #0x22000000   /* dest (IRAM) */
117     ldr    r2, =_dataend
119     cmp    r2, r1
120     ldrhi  r3, [r0], #4
121     strhi  r3, [r1], #4
122     bhi    1b
124     ldr    pc, =start_loc    /* jump to the relocated start_loc:  */
125 start_loc:
126 #endif /* BOOTLOADER */
127 #endif /* CONFIG_CPU==S5L8701 */
129 #if !(CONFIG_CPU==S5L8701 && defined(BOOTLOADER))
130     ldr r1, =0x3c500000 
131     ldr r0, =0x00800080
132     str r0, [r1]        // CLKCON
133     mov r0, #0
134     str r0, [r1,#0x24]  // PLLCON
135 #ifdef IPOD_NANO2G
136     ldr r0, =0x21200    // pdiv=2, mdiv=0x12 sdiv=0
137 #else
138     ldr r0, =0x1ad200   // pdiv=0x1a, mdiv=0xd2 sdiv=0
139 #endif
140     str r0, [r1,#0x04]  // PLL0PMS
141     ldr r0, =8100
142     str r0, [r1,#0x14]  // PLL0LCNT
143     mov r0, #1
144     str r0, [r1,#0x24]  // PLLCON
146     ldr r0, [r1,#0x20]  // PLLLOCK
147     tst r0, #1
148     beq 1b
149     mov r0, #0x280
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
154     ldr r2, =0xc0000078
155     mrc 15, 0, r0, c1, c0, 0
156     mvn r1, #0xc0000000
157     and r0, r0, r1
158     orr r0, r0, r2
159     mcr 15, 0, r0, c1, c0, 0 // asynchronous clocking mode
160     nop
161     nop                         
162     nop
163     nop
164 #endif
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
175 //    nop
176 //    nop
177 //    nop
178 //    nop
180 /* The following two sections of code (i.e. Nano2G and Meizus) should
181    be unified at some point. */
182 #ifdef IPOD_NANO2G
184     ldr r1, =0x3c500000 
185     ldr r0, =0xffdff7ff
186     str r0, [r1,#0x28]  // PWRCON
187     ldr r0, =0xffffef7e
188     str r0, [r1,#0x40]  // PWRCONEXT
190     mrc 15, 0, r0, c1, c0, 0
191     bic r0, r0, #0x1000
192     bic r0, r0, #0x5
193     mcr 15, 0, r0, c1, c0, 0 // disable caches and protection unit
195     mov r1, #0
197     mov r0, #0
199     orr r2, r1, r0
200     mcr 15, 0, r2, c7, c14, 2 // clean and flush dcache single entry
201     add r0, r0, #0x10
202     cmp r0, #0x40
203     bne 2b
204     add r1, r1, #0x4000000
205     cmp r1, #0x0
206     bne 1b
207     nop
208     nop
209     mov r0, #0
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
214     mov r0, #0x3f
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
217 #ifdef IPOD_NANO2G
218     mov r0, #0x31 // FIXME: calculate that from MEMORYSIZE
219 #else
220     mov r0, #0x2f // FIXME: calculate that from MEMORYSIZE
221 #endif
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
227     ldr r0, =0x22000023
228     mcr 15, 0, r0, c6, c3, 1 // CS3: SRAM
229     mcr 15, 0, r0, c6, c3, 0 // DS3: SRAM
230     ldr r0, =0x24000027
231     mcr 15, 0, r0, c6, c4, 1 // CS4: NOR flash
232     mcr 15, 0, r0, c6, c4, 0 // DS4: NOR flash
233     mov r0, #0
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
240     mov r0, #0x1e
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
244     ldr r0, =0x000003ff
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
249     orr r0, r0, #0x5
250     orr r0, r0, #0x1000
251     mcr 15, 0, r0, c1, c0, 0 // re-enable protection unit and caches
253 #else
255     ldr r1, =0x3c500000
256     mov r0, #0  // 0x0
257     str r0, [r1, #40] // enable clock for all peripherals
258     mov r0, #0  // 0x0
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
271     mov r0, #2\r
272     str r0, [r1, #0x60] // SSTL2_PAD_ON\r
273     // select SDR mode\r
274     ldr r0, [r1, #0x40]
275     mov r2, #0xFFFDFFFF\r
276     and r0, r0, r2\r
277     orr r0, r0, #1\r
278     str r0, [r1, #0x40] // MIUORG\r
279     // set controller configuration
280     mov r0, #SDR_CONFIG
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
286     mov r0, #0x1080\r
287     str r0, [r1, #0x08] // MIUAREF\r
288     // initialise SDRAM \r
289     mov r0, #0x003\r
290     str r0, [r1, #0x04] // MIUCOM = nop\r
291     ldr r0, =0x203\r
292     str r0, [r1, #0x04] // MIUCOM = precharge all banks\r
293     nop\r
294     nop\r
295     nop\r
296     ldr r0, =0x303\r
297     str r0, [r1, #0x04] // MIUCOM = auto-refresh\r
298     nop\r
299     nop\r
300     nop\r
301     nop\r
302     str r0, [r1, #0x04] // MIUCOM = auto-refresh\r
303     nop\r
304     nop\r
305     nop\r
306     nop\r
307     str r0, [r1, #0x04] // MIUCOM = auto-refresh\r
308     nop\r
309     nop\r
310     nop\r
311     nop\r
312     // set mode register\r
313     mov r0, #SDR_MRS\r
314     str r0, [r1, #0x0C] // MIUMRS\r
315     ldr r0, =0x103\r
316     str r0, [r1, #0x04] // MIUCOM = mode register set\r
317     ldr r0, =SDR_EMRS\r
318     str r0, [r1, #0x0C] // MIUMRS\r
319     ldr r0, =0x103\r
320     str r0, [r1, #0x04] // MIUCOM = mode register set\r
321 #endif /* MEIZU_M6SP */
323     mov r1, #0x1
324     mrc 15, 0, r0, c1, c0, 0
325     bic r0, r0, r1
326     mcr 15, 0, r0, c1, c0, 0 // disable protection unit
328     mov r1, #0x4
329     mrc 15, 0, r0, c1, c0, 0
330     bic r0, r0, r1
331     mcr 15, 0, r0, c1, c0, 0 // dcache disable
333     mov r1, #0x1000
334     mrc 15, 0, r0, c1, c0, 0
335     bic r0, r0, r1
336     mcr 15, 0, r0, c1, c0, 0 // icache disable
338     mov r1, #0
340     mov r0, #0
342     orr r2, r1, r0
343     mcr 15, 0, r2, c7, c14, 2 // clean and flush dcache single entry
344     add r0, r0, #0x10
345     cmp r0, #0x40
346     bne 2b
347     add r1, r1, #0x4000000
348     cmp r1, #0x0
349     bne 1b
350     nop
351     nop
352     mov r0, #0
353     mcr 15, 0, r0, c7, c10, 4 // clean and flush whole dcache
355     mov r0, #0
356     mcr 15, 0, r0, c7, c5, 0 // flush icache
357     
358     mov r0, #0
359     mcr 15, 0, r0, c7, c6, 0 // flush dcache
361     mov r0, #0x3f
362     mcr 15, 0, r0, c6, c0, 1
363     mov r0, #0x2f
364     mcr 15, 0, r0, c6, c1, 1
365     ldr r0, =0x08000031
366     mcr 15, 0, r0, c6, c2, 1
367     ldr r0, =0x22000023
368     mcr 15, 0, r0, c6, c3, 1
369     ldr r0, =0x24000027
370     mcr 15, 0, r0, c6, c4, 1
371     mov r0, #0x3f
372     mcr 15, 0, r0, c6, c0, 0
373     mov r0, #0x2f
374     mcr 15, 0, r0, c6, c1, 0
375     ldr r0, =0x08000031
376     mcr 15, 0, r0, c6, c2, 0
377     ldr r0, =0x22000023
378     mcr 15, 0, r0, c6, c3, 0
379     ldr r0, =0x24000029
380     mcr 15, 0, r0, c6, c4, 0
381     mov r0, #0x1e
382     mcr 15, 0, r0, c2, c0, 1
383     mov r0, #0x1e
384     mcr 15, 0, r0, c2, c0, 0
385     mov r0, #0x1e
386     mcr 15, 0, r0, c3, c0, 0
387     ldr r0, =0x0000ffff
388     mcr 15, 0, r0, c5, c0, 1
389     ldr r0, =0x0000ffff
390     mcr 15, 0, r0, c5, c0, 0 // set up protection and caching
392     mov r1, #0x4
393     mrc 15, 0, r0, c1, c0, 0
394     orr r0, r0, r1
395     mcr 15, 0, r0, c1, c0, 0 // dcache enable
397     mov r1, #0x1000
398     mrc 15, 0, r0, c1, c0, 0
399     orr r0, r0, r1
400     mcr 15, 0, r0, c1, c0, 0 // icache enable
402     mov r1, #0x1
403     mrc 15, 0, r0, c1, c0, 0
404     orr r0, r0, r1
405     mcr 15, 0, r0, c1, c0, 0 // enable protection unit
406 #endif
408 #if CONFIG_CPU==S5L8700 || !defined(BOOTLOADER)
409     /* Copy interrupt vectors to iram */
410     ldr     r2, =_intvectstart
411     ldr     r3, =_intvectend
412     ldr     r4, =_intvectcopy
414     cmp     r3, r2
415     ldrhi   r1, [r4], #4
416     strhi   r1, [r2], #4
417     bhi     1b
418 #endif
420     /* Initialise bss section to zero */
421     ldr     r2, =_edata
422     ldr     r3, =_end
423     mov     r4, #0
425     cmp     r3, r2
426     strhi   r4, [r2], #4
427     bhi     1b
429 #if CONFIG_CPU==S5L8700 && defined(BOOTLOADER)
430     /* Copy icode and data to ram */
431     ldr     r2, =_datastart
432     ldr     r3, =_dataend
433     ldr     r4, =_datacopy
435     cmp     r3, r2
436     ldrhi   r1, [r4], #4
437     strhi   r1, [r2], #4
438     bhi     1b
439 #endif
441 #ifndef BOOTLOADER
442     /* Copy icode and data to ram */
443     ldr     r2, =_iramstart
444     ldr     r3, =_iramend
445     ldr     r4, =_iramcopy
447     cmp     r3, r2
448     ldrhi   r1, [r4], #4
449     strhi   r1, [r2], #4
450     bhi     1b
451     
452     /* Initialise ibss section to zero */
453     ldr     r2, =_iedata
454     ldr     r3, =_iend
455     mov     r4, #0
457     cmp     r3, r2
458     strhi   r4, [r2], #4
459     bhi     1b
460 #endif
462     /* Set up some stack and munge it with 0xdeadbeef */
463     ldr     sp, =stackend
464     ldr     r2, =stackbegin
465     ldr     r3, =0xdeadbeef
467     cmp     sp, r2
468     strhi   r3, [r2], #4
469     bhi     1b
471     /* Set up stack for IRQ mode */ 
472     msr     cpsr_c, #0xd2
473     ldr     sp, =_irqstackend
475     /* Set up stack for FIQ mode */ 
476     msr     cpsr_c, #0xd1
477     ldr     sp, =_fiqstackend
479     /* Let abort and undefined modes use IRQ stack */
480     msr     cpsr_c, #0xd7
481     ldr     sp, =_irqstackend
482     msr     cpsr_c, #0xdb
483     ldr     sp, =_irqstackend
485     /* Switch back to supervisor mode */
486     msr     cpsr_c, #0xd3
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
492     ldr r1, =0x38200000
493     ldr r0, [r1]
494     mvn r2, #0x10000
495     and r0, r0, r2
496     mov r2, #0x1
497     orr r0, r0, r2
498     str r0, [r1] // remap iram to address 0x0
499 #endif
501     bl      main
503     .text
504 /*    .global UIE*/
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
509  * in UIE. */
510 undef_instr_handler:
511     mov    r0, lr
512     mov    r1, #0
513     b      UIE
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:
518 reserved_handler:
519     movs   pc, lr
521 prefetch_abort_handler:
522     sub    r0, lr, #4
523     mov    r1, #1
524     b      UIE
526 data_abort_handler:
527     sub    r0, lr, #8 
528     mov    r1, #2
529     b      UIE