Merge branch 'master' of git://git.denx.de/u-boot-blackfin
[platform/kernel/u-boot.git] / arch / arm / cpu / arm720t / start.S
1 /*
2  *  armboot - Startup Code for ARM720 CPU-core
3  *
4  *  Copyright (c) 2001  Marius Gröger <mag@sysgo.de>
5  *  Copyright (c) 2002  Alex Züpke <azu@sysgo.de>
6  *
7  * See file CREDITS for list of people who contributed to this
8  * project.
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License as
12  * published by the Free Software Foundation; either version 2 of
13  * the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
23  * MA 02111-1307 USA
24  */
25
26 #include <asm-offsets.h>
27 #include <config.h>
28 #include <version.h>
29 #include <asm/hardware.h>
30
31 /*
32  *************************************************************************
33  *
34  * Jump vector table as in table 3.1 in [1]
35  *
36  *************************************************************************
37  */
38
39
40 .globl _start
41 _start: b       reset
42         ldr     pc, _undefined_instruction
43         ldr     pc, _software_interrupt
44         ldr     pc, _prefetch_abort
45         ldr     pc, _data_abort
46 #ifdef CONFIG_LPC2292
47         .word   0xB4405F76 /* 2's complement of the checksum of the vectors */
48 #else
49         ldr     pc, _not_used
50 #endif
51         ldr     pc, _irq
52         ldr     pc, _fiq
53
54 _undefined_instruction: .word undefined_instruction
55 _software_interrupt:    .word software_interrupt
56 _prefetch_abort:        .word prefetch_abort
57 _data_abort:            .word data_abort
58 _not_used:              .word not_used
59 _irq:                   .word irq
60 _fiq:                   .word fiq
61
62         .balignl 16,0xdeadbeef
63
64
65 /*
66  *************************************************************************
67  *
68  * Startup Code (reset vector)
69  *
70  * do important init only if we don't start from RAM!
71  * relocate armboot to ram
72  * setup stack
73  * jump to second stage
74  *
75  *************************************************************************
76  */
77
78 .globl _TEXT_BASE
79 _TEXT_BASE:
80         .word   CONFIG_SYS_TEXT_BASE
81
82 /*
83  * These are defined in the board-specific linker script.
84  */
85 .globl _bss_start
86 _bss_start:
87         .word __bss_start
88
89 .globl _bss_end
90 _bss_end:
91         .word _end
92
93 #ifdef CONFIG_USE_IRQ
94 /* IRQ stack memory (calculated at run-time) */
95 .globl IRQ_STACK_START
96 IRQ_STACK_START:
97         .word   0x0badc0de
98
99 /* IRQ stack memory (calculated at run-time) */
100 .globl FIQ_STACK_START
101 FIQ_STACK_START:
102         .word 0x0badc0de
103 #endif
104
105 /* IRQ stack memory (calculated at run-time) + 8 bytes */
106 .globl IRQ_STACK_START_IN
107 IRQ_STACK_START_IN:
108         .word   0x0badc0de
109
110 .globl _datarel_start
111 _datarel_start:
112         .word __datarel_start
113
114 .globl _datarelrolocal_start
115 _datarelrolocal_start:
116         .word __datarelrolocal_start
117
118 .globl _datarellocal_start
119 _datarellocal_start:
120         .word __datarellocal_start
121
122 .globl _datarelro_start
123 _datarelro_start:
124         .word __datarelro_start
125
126 .globl _got_start
127 _got_start:
128         .word __got_start
129
130 .globl _got_end
131 _got_end:
132         .word __got_end
133
134 /*
135  * the actual reset code
136  */
137
138 reset:
139         /*
140          * set the cpu to SVC32 mode
141          */
142         mrs     r0,cpsr
143         bic     r0,r0,#0x1f
144         orr     r0,r0,#0xd3
145         msr     cpsr,r0
146
147         /*
148          * we do sys-critical inits only at reboot,
149          * not when booting from ram!
150          */
151 #ifndef CONFIG_SKIP_LOWLEVEL_INIT
152         bl      cpu_init_crit
153 #endif
154
155 #ifdef CONFIG_LPC2292
156         bl      lowlevel_init
157 #endif
158
159 /* Set stackpointer in internal RAM to call board_init_f */
160 call_board_init_f:
161         ldr     sp, =(CONFIG_SYS_INIT_SP_ADDR)
162         ldr     r0,=0x00000000
163         bl      board_init_f
164
165 /*------------------------------------------------------------------------------*/
166
167 /*
168  * void relocate_code (addr_sp, gd, addr_moni)
169  *
170  * This "function" does not return, instead it continues in RAM
171  * after relocating the monitor code.
172  *
173  */
174         .globl  relocate_code
175 relocate_code:
176         mov     r4, r0  /* save addr_sp */
177         mov     r5, r1  /* save addr of gd */
178         mov     r6, r2  /* save addr of destination */
179         mov     r7, r2  /* save addr of destination */
180
181         /* Set up the stack                                                 */
182 stack_setup:
183         mov     sp, r4
184
185         adr     r0, _start
186         ldr     r2, _TEXT_BASE
187         ldr     r3, _bss_start
188         sub     r2, r3, r2              /* r2 <- size of armboot            */
189         add     r2, r0, r2              /* r2 <- source end address         */
190         cmp     r0, r6
191         beq     clear_bss
192
193 copy_loop:
194         ldmia   r0!, {r9-r10}           /* copy from source address [r0]    */
195         stmia   r6!, {r9-r10}           /* copy to   target address [r1]    */
196         cmp     r0, r2                  /* until source end address [r2]    */
197         blo     copy_loop
198
199 #ifndef CONFIG_PRELOADER
200         /* fix got entries */
201         ldr     r1, _TEXT_BASE          /* Text base */
202         mov     r0, r7                  /* reloc addr */
203         ldr     r2, _got_start          /* addr in Flash */
204         ldr     r3, _got_end            /* addr in Flash */
205         sub     r3, r3, r1
206         add     r3, r3, r0
207         sub     r2, r2, r1
208         add     r2, r2, r0
209
210 fixloop:
211         ldr     r4, [r2]
212         sub     r4, r4, r1
213         add     r4, r4, r0
214         str     r4, [r2]
215         add     r2, r2, #4
216         cmp     r2, r3
217         blo     fixloop
218 #endif
219
220 clear_bss:
221 #ifndef CONFIG_PRELOADER
222         ldr     r0, _bss_start
223         ldr     r1, _bss_end
224         ldr     r3, _TEXT_BASE          /* Text base */
225         mov     r4, r7                  /* reloc addr */
226         sub     r0, r0, r3
227         add     r0, r0, r4
228         sub     r1, r1, r3
229         add     r1, r1, r4
230         mov     r2, #0x00000000         /* clear                            */
231
232 clbss_l:str     r2, [r0]                /* clear loop...                    */
233         add     r0, r0, #4
234         cmp     r0, r1
235         bne     clbss_l
236
237         bl coloured_LED_init
238         bl red_LED_on
239 #endif
240
241 /*
242  * We are done. Do not return, instead branch to second part of board
243  * initialization, now running from RAM.
244  */
245         ldr     r0, _TEXT_BASE
246         ldr     r2, _board_init_r
247         sub     r2, r2, r0
248         add     r2, r2, r7      /* position from board_init_r in RAM */
249         /* setup parameters for board_init_r */
250         mov     r0, r5          /* gd_t */
251         mov     r1, r7          /* dest_addr */
252         /* jump to it ... */
253         mov     lr, r2
254         mov     pc, lr
255
256 _board_init_r: .word board_init_r
257
258 /*
259  *************************************************************************
260  *
261  * CPU_init_critical registers
262  *
263  * setup important registers
264  * setup memory timing
265  *
266  *************************************************************************
267  */
268
269 #if defined(CONFIG_IMPA7) || defined(CONFIG_EP7312) || defined(CONFIG_ARMADILLO)
270
271 /* Interupt-Controller base addresses */
272 INTMR1:         .word   0x80000280 @ 32 bit size
273 INTMR2:         .word   0x80001280 @ 16 bit size
274 INTMR3:         .word   0x80002280 @  8 bit size
275
276 /* SYSCONs */
277 SYSCON1:        .word   0x80000100
278 SYSCON2:        .word   0x80001100
279 SYSCON3:        .word   0x80002200
280
281 #define CLKCTL         0x6  /* mask */
282 #define CLKCTL_18      0x0  /* 18.432 MHz */
283 #define CLKCTL_36      0x2  /* 36.864 MHz */
284 #define CLKCTL_49      0x4  /* 49.152 MHz */
285 #define CLKCTL_73      0x6  /* 73.728 MHz */
286
287 #elif defined(CONFIG_LPC2292)
288 PLLCFG_ADR:     .word   PLLCFG
289 PLLFEED_ADR:    .word   PLLFEED
290 PLLCON_ADR:     .word   PLLCON
291 PLLSTAT_ADR:    .word   PLLSTAT
292 VPBDIV_ADR:     .word   VPBDIV
293 MEMMAP_ADR:     .word   MEMMAP
294
295 #endif
296
297 cpu_init_crit:
298 #if defined(CONFIG_IMPA7) || defined(CONFIG_EP7312) || defined(CONFIG_ARMADILLO)
299
300         /*
301          * mask all IRQs by clearing all bits in the INTMRs
302          */
303         mov     r1, #0x00
304         ldr     r0, INTMR1
305         str     r1, [r0]
306         ldr     r0, INTMR2
307         str     r1, [r0]
308         ldr     r0, INTMR3
309         str     r1, [r0]
310
311         /*
312          * flush v4 I/D caches
313          */
314         mov     r0, #0
315         mcr     p15, 0, r0, c7, c7, 0   /* flush v3/v4 cache */
316         mcr     p15, 0, r0, c8, c7, 0   /* flush v4 TLB */
317
318         /*
319          * disable MMU stuff and caches
320          */
321         mrc     p15,0,r0,c1,c0
322         bic     r0, r0, #0x00002300     @ clear bits 13, 9:8 (--V- --RS)
323         bic     r0, r0, #0x0000008f     @ clear bits 7, 3:0 (B--- WCAM)
324         orr     r0, r0, #0x00000002     @ set bit 2 (A) Align
325         mcr     p15,0,r0,c1,c0
326 #elif defined(CONFIG_NETARM)
327         /*
328          * prior to software reset : need to set pin PORTC4 to be *HRESET
329          */
330         ldr     r0, =NETARM_GEN_MODULE_BASE
331         ldr     r1, =(NETARM_GEN_PORT_MODE(0x10) | \
332                         NETARM_GEN_PORT_DIR(0x10))
333         str     r1, [r0, #+NETARM_GEN_PORTC]
334         /*
335          * software reset : see HW Ref. Guide 8.2.4 : Software Service register
336          *                  for an explanation of this process
337          */
338         ldr     r0, =NETARM_GEN_MODULE_BASE
339         ldr     r1, =NETARM_GEN_SW_SVC_RESETA
340         str     r1, [r0, #+NETARM_GEN_SOFTWARE_SERVICE]
341         ldr     r1, =NETARM_GEN_SW_SVC_RESETB
342         str     r1, [r0, #+NETARM_GEN_SOFTWARE_SERVICE]
343         ldr     r1, =NETARM_GEN_SW_SVC_RESETA
344         str     r1, [r0, #+NETARM_GEN_SOFTWARE_SERVICE]
345         ldr     r1, =NETARM_GEN_SW_SVC_RESETB
346         str     r1, [r0, #+NETARM_GEN_SOFTWARE_SERVICE]
347         /*
348          * setup PLL and System Config
349          */
350         ldr     r0, =NETARM_GEN_MODULE_BASE
351
352         ldr     r1, =(  NETARM_GEN_SYS_CFG_LENDIAN | \
353                         NETARM_GEN_SYS_CFG_BUSFULL | \
354                         NETARM_GEN_SYS_CFG_USER_EN | \
355                         NETARM_GEN_SYS_CFG_ALIGN_ABORT | \
356                         NETARM_GEN_SYS_CFG_BUSARB_INT | \
357                         NETARM_GEN_SYS_CFG_BUSMON_EN )
358
359         str     r1, [r0, #+NETARM_GEN_SYSTEM_CONTROL]
360
361 #ifndef CONFIG_NETARM_PLL_BYPASS
362         ldr     r1, =(  NETARM_GEN_PLL_CTL_PLLCNT(NETARM_PLL_COUNT_VAL) | \
363                         NETARM_GEN_PLL_CTL_POLTST_DEF | \
364                         NETARM_GEN_PLL_CTL_INDIV(1) | \
365                         NETARM_GEN_PLL_CTL_ICP_DEF | \
366                         NETARM_GEN_PLL_CTL_OUTDIV(2) )
367         str     r1, [r0, #+NETARM_GEN_PLL_CONTROL]
368 #endif
369
370         /*
371          * mask all IRQs by clearing all bits in the INTMRs
372          */
373         mov     r1, #0
374         ldr     r0, =NETARM_GEN_MODULE_BASE
375         str     r1, [r0, #+NETARM_GEN_INTR_ENABLE]
376
377 #elif defined(CONFIG_S3C4510B)
378
379         /*
380          * Mask off all IRQ sources
381          */
382         ldr     r1, =REG_INTMASK
383         ldr     r0, =0x3FFFFF
384         str     r0, [r1]
385
386         /*
387          * Disable Cache
388          */
389         ldr r0, =REG_SYSCFG
390         ldr r1, =0x83ffffa0     /* cache-disabled  */
391         str r1, [r0]
392
393 #elif defined(CONFIG_INTEGRATOR) && defined(CONFIG_ARCH_INTEGRATOR)
394         /* No specific initialisation for IntegratorAP/CM720T as yet */
395 #elif defined(CONFIG_LPC2292)
396         /* Set-up PLL */
397         mov     r3, #0xAA
398         mov     r4, #0x55
399         /* First disconnect and disable the PLL */
400         ldr     r0, PLLCON_ADR
401         mov     r1, #0x00
402         str     r1, [r0]
403         ldr     r0, PLLFEED_ADR /* start feed sequence */
404         str     r3, [r0]
405         str     r4, [r0]        /* feed sequence done */
406         /* Set new M and P values */
407         ldr     r0, PLLCFG_ADR
408         mov     r1, #0x23       /* M=4 and P=2 */
409         str     r1, [r0]
410         ldr     r0, PLLFEED_ADR /* start feed sequence */
411         str     r3, [r0]
412         str     r4, [r0]        /* feed sequence done */
413         /* Then enable the PLL */
414         ldr     r0, PLLCON_ADR
415         mov     r1, #0x01       /* PLL enable bit */
416         str     r1, [r0]
417         ldr     r0, PLLFEED_ADR /* start feed sequence */
418         str     r3, [r0]
419         str     r4, [r0]        /* feed sequence done */
420         /* Wait for the lock */
421         ldr     r0, PLLSTAT_ADR
422         mov     r1, #0x400      /* lock bit */
423 lock_loop:
424         ldr     r2, [r0]
425         and     r2, r1, r2
426         cmp     r2, #0
427         beq     lock_loop
428         /* And finally connect the PLL */
429         ldr     r0, PLLCON_ADR
430         mov     r1, #0x03       /* PLL enable bit and connect bit */
431         str     r1, [r0]
432         ldr     r0, PLLFEED_ADR /* start feed sequence */
433         str     r3, [r0]
434         str     r4, [r0]        /* feed sequence done */
435         /* Set-up VPBDIV register */
436         ldr     r0, VPBDIV_ADR
437         mov     r1, #0x01       /* VPB clock is same as process clock */
438         str     r1, [r0]
439 #else
440 #error No cpu_init_crit() defined for current CPU type
441 #endif
442
443 #ifdef CONFIG_ARM7_REVD
444         /* set clock speed */
445         /* !!! we run @ 36 MHz due to a hardware flaw in Rev. D processors */
446         /* !!! not doing DRAM refresh properly! */
447         ldr     r0, SYSCON3
448         ldr     r1, [r0]
449         bic     r1, r1, #CLKCTL
450         orr     r1, r1, #CLKCTL_36
451         str     r1, [r0]
452 #endif
453
454 #ifndef CONFIG_LPC2292
455         mov     ip, lr
456         /*
457          * before relocating, we have to setup RAM timing
458          * because memory timing is board-dependent, you will
459          * find a lowlevel_init.S in your board directory.
460          */
461         bl      lowlevel_init
462         mov     lr, ip
463 #endif
464
465         mov     pc, lr
466
467
468 /*
469  *************************************************************************
470  *
471  * Interrupt handling
472  *
473  *************************************************************************
474  */
475
476 @
477 @ IRQ stack frame.
478 @
479 #define S_FRAME_SIZE    72
480
481 #define S_OLD_R0        68
482 #define S_PSR           64
483 #define S_PC            60
484 #define S_LR            56
485 #define S_SP            52
486
487 #define S_IP            48
488 #define S_FP            44
489 #define S_R10           40
490 #define S_R9            36
491 #define S_R8            32
492 #define S_R7            28
493 #define S_R6            24
494 #define S_R5            20
495 #define S_R4            16
496 #define S_R3            12
497 #define S_R2            8
498 #define S_R1            4
499 #define S_R0            0
500
501 #define MODE_SVC 0x13
502 #define I_BIT    0x80
503
504 /*
505  * use bad_save_user_regs for abort/prefetch/undef/swi ...
506  * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
507  */
508
509         .macro  bad_save_user_regs
510         sub     sp, sp, #S_FRAME_SIZE
511         stmia   sp, {r0 - r12}                  @ Calling r0-r12
512         add     r8, sp, #S_PC
513
514         ldr     r2, IRQ_STACK_START_IN
515         ldmia   r2, {r2 - r4}                   @ get pc, cpsr, old_r0
516         add     r0, sp, #S_FRAME_SIZE           @ restore sp_SVC
517
518         add     r5, sp, #S_SP
519         mov     r1, lr
520         stmia   r5, {r0 - r4}                   @ save sp_SVC, lr_SVC, pc, cpsr, old_r
521         mov     r0, sp
522         .endm
523
524         .macro  irq_save_user_regs
525         sub     sp, sp, #S_FRAME_SIZE
526         stmia   sp, {r0 - r12}                  @ Calling r0-r12
527         add     r8, sp, #S_PC
528         stmdb   r8, {sp, lr}^                   @ Calling SP, LR
529         str     lr, [r8, #0]                    @ Save calling PC
530         mrs     r6, spsr
531         str     r6, [r8, #4]                    @ Save CPSR
532         str     r0, [r8, #8]                    @ Save OLD_R0
533         mov     r0, sp
534         .endm
535
536         .macro  irq_restore_user_regs
537         ldmia   sp, {r0 - lr}^                  @ Calling r0 - lr
538         mov     r0, r0
539         ldr     lr, [sp, #S_PC]                 @ Get PC
540         add     sp, sp, #S_FRAME_SIZE
541         subs    pc, lr, #4                      @ return & move spsr_svc into cpsr
542         .endm
543
544         .macro get_bad_stack
545         ldr     r13, IRQ_STACK_START_IN         @ setup our mode stack
546
547         str     lr, [r13]                       @ save caller lr / spsr
548         mrs     lr, spsr
549         str     lr, [r13, #4]
550
551         mov     r13, #MODE_SVC                  @ prepare SVC-Mode
552         msr     spsr_c, r13
553         mov     lr, pc
554         movs    pc, lr
555         .endm
556
557         .macro get_irq_stack                    @ setup IRQ stack
558         ldr     sp, IRQ_STACK_START
559         .endm
560
561         .macro get_fiq_stack                    @ setup FIQ stack
562         ldr     sp, FIQ_STACK_START
563         .endm
564
565 /*
566  * exception handlers
567  */
568         .align  5
569 undefined_instruction:
570         get_bad_stack
571         bad_save_user_regs
572         bl      do_undefined_instruction
573
574         .align  5
575 software_interrupt:
576         get_bad_stack
577         bad_save_user_regs
578         bl      do_software_interrupt
579
580         .align  5
581 prefetch_abort:
582         get_bad_stack
583         bad_save_user_regs
584         bl      do_prefetch_abort
585
586         .align  5
587 data_abort:
588         get_bad_stack
589         bad_save_user_regs
590         bl      do_data_abort
591
592         .align  5
593 not_used:
594         get_bad_stack
595         bad_save_user_regs
596         bl      do_not_used
597
598 #ifdef CONFIG_USE_IRQ
599
600         .align  5
601 irq:
602         get_irq_stack
603         irq_save_user_regs
604         bl      do_irq
605         irq_restore_user_regs
606
607         .align  5
608 fiq:
609         get_fiq_stack
610         /* someone ought to write a more effiction fiq_save_user_regs */
611         irq_save_user_regs
612         bl      do_fiq
613         irq_restore_user_regs
614
615 #else
616
617         .align  5
618 irq:
619         get_bad_stack
620         bad_save_user_regs
621         bl      do_irq
622
623         .align  5
624 fiq:
625         get_bad_stack
626         bad_save_user_regs
627         bl      do_fiq
628
629 #endif
630
631 #if defined(CONFIG_IMPA7) || defined(CONFIG_EP7312) || defined(CONFIG_ARMADILLO)
632         .align  5
633 .globl reset_cpu
634 reset_cpu:
635         mov     ip, #0
636         mcr     p15, 0, ip, c7, c7, 0           @ invalidate cache
637         mcr     p15, 0, ip, c8, c7, 0           @ flush TLB (v4)
638         mrc     p15, 0, ip, c1, c0, 0           @ get ctrl register
639         bic     ip, ip, #0x000f                 @ ............wcam
640         bic     ip, ip, #0x2100                 @ ..v....s........
641         mcr     p15, 0, ip, c1, c0, 0           @ ctrl register
642         mov     pc, r0
643 #elif defined(CONFIG_NETARM)
644         .align  5
645 .globl reset_cpu
646 reset_cpu:
647         ldr     r1, =NETARM_MEM_MODULE_BASE
648         ldr     r0, [r1, #+NETARM_MEM_CS0_BASE_ADDR]
649         ldr     r1, =0xFFFFF000
650         and     r0, r1, r0
651         ldr     r1, =(relocate-CONFIG_SYS_TEXT_BASE)
652         add     r0, r1, r0
653         ldr     r4, =NETARM_GEN_MODULE_BASE
654         ldr     r1, =NETARM_GEN_SW_SVC_RESETA
655         str     r1, [r4, #+NETARM_GEN_SOFTWARE_SERVICE]
656         ldr     r1, =NETARM_GEN_SW_SVC_RESETB
657         str     r1, [r4, #+NETARM_GEN_SOFTWARE_SERVICE]
658         ldr     r1, =NETARM_GEN_SW_SVC_RESETA
659         str     r1, [r4, #+NETARM_GEN_SOFTWARE_SERVICE]
660         ldr     r1, =NETARM_GEN_SW_SVC_RESETB
661         str     r1, [r4, #+NETARM_GEN_SOFTWARE_SERVICE]
662         mov     pc, r0
663 #elif defined(CONFIG_S3C4510B)
664 /* Nothing done here as reseting the CPU is board specific, depending
665  * on external peripherals such as watchdog timers, etc. */
666 #elif defined(CONFIG_INTEGRATOR) && defined(CONFIG_ARCH_INTEGRATOR)
667         /* No specific reset actions for IntegratorAP/CM720T as yet */
668 #elif defined(CONFIG_LPC2292)
669         .align  5
670 .globl reset_cpu
671 reset_cpu:
672         mov     pc, r0
673 #else
674 #error No reset_cpu() defined for current CPU type
675 #endif