]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/nds32/cpu/n1213/start.S
Merge branch 'u-boot-imx/master' into 'u-boot-arm/master'
[karo-tx-uboot.git] / arch / nds32 / cpu / n1213 / start.S
1 /*
2  *      Andesboot - Startup Code for Whitiger core
3  *
4  *      Copyright (C) 2006      Andes Technology Corporation
5  *      Copyright (C) 2006      Shawn Lin <nobuhiro@andestech.com>
6  *      Copyright (C) 2011      Macpaul Lin <macpaul@andestech.com>
7  *                              Greentime Hu <greentime@andestech.com>
8  *
9  * See file CREDITS for list of people who contributed to this
10  * project.
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License as
14  * published by the Free Software Foundation; either version 2 of
15  * the License, or (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
25  * MA 02111-1307 USA
26  */
27
28 #include <asm-offsets.h>
29 #include <config.h>
30 #include <common.h>
31 #include <asm/macro.h>
32 #include <version.h>
33
34 /*
35  * Jump vector table for EVIC mode
36  */
37 #define ENA_DCAC                2UL
38 #define DIS_DCAC                ~ENA_DCAC
39 #define ICAC_MEM_KBF_ISET       (0x07)          ! I Cache sets per way
40 #define ICAC_MEM_KBF_IWAY       (0x07<<3)       ! I cache ways
41 #define ICAC_MEM_KBF_ISZ        (0x07<<6)       ! I cache line size
42 #define DCAC_MEM_KBF_DSET       (0x07)          ! D Cache sets per way
43 #define DCAC_MEM_KBF_DWAY       (0x07<<3)       ! D cache ways
44 #define DCAC_MEM_KBF_DSZ        (0x07<<6)       ! D cache line size
45
46 #define PSW                     $ir0
47 #define EIT_INTR_PSW            $ir1            ! interruption $PSW
48 #define EIT_PREV_IPSW           $ir2            ! previous $IPSW
49 #define EIT_IVB                 $ir3            ! intr vector base address
50 #define EIT_EVA                 $ir4            ! MMU related Exception VA reg
51 #define EIT_PREV_EVA            $ir5            ! previous $eva
52 #define EIT_ITYPE               $ir6            ! interruption type
53 #define EIT_PREV_ITYPE          $ir7            ! prev intr type
54 #define EIT_MACH_ERR            $ir8            ! machine error log
55 #define EIT_INTR_PC             $ir9            ! Interruption PC
56 #define EIT_PREV_IPC            $ir10           ! previous $IPC
57 #define EIT_OVL_INTR_PC         $ir11           ! overflow interruption PC
58 #define EIT_PREV_P0             $ir12           ! prev $P0
59 #define EIT_PREV_P1             $ir13           ! prev $p1
60 #define CR_ICAC_MEM             $cr1            ! I-cache/memory config reg
61 #define CR_DCAC_MEM             $cr2            ! D-cache/memory config reg
62 #define MR_CAC_CTL              $mr8
63
64 .globl _start
65
66 _start: j       reset
67         j       tlb_fill
68         j       tlb_not_present
69         j       tlb_misc
70         j       tlb_vlpt_miss
71         j       machine_error
72         j       debug
73         j       general_exception
74         j       syscall
75         j       internal_interrupt              ! H0I
76         j       internal_interrupt              ! H1I
77         j       internal_interrupt              ! H2I
78         j       internal_interrupt              ! H3I
79         j       internal_interrupt              ! H4I
80         j       internal_interrupt              ! H5I
81         j       software_interrupt              ! S0I
82
83         .balign 16
84
85 /*
86  * Andesboot Startup Code (reset vector)
87  *
88  *      1.      bootstrap
89  *              1.1 reset - start of u-boot
90  *              1.2 to superuser mode - as is when reset
91  *              1.4 Do lowlevel_init
92  *                      - (this will jump out to lowlevel_init.S in SoC)
93  *                      - (lowlevel_init)
94  *              1.3 Turn off watchdog timer
95  *                      - (this will jump out to watchdog.S in SoC)
96  *                      - (turnoff_watchdog)
97  *      2.      Do critical init when reboot (not from mem)
98  *      3.      Relocate andesboot to ram
99  *      4.      Setup stack
100  *      5.      Jump to second stage (board_init_r)
101  */
102
103 /* Note: TEXT_BASE is defined by the (board-dependent) linker script */
104 .globl _TEXT_BASE
105 _TEXT_BASE:
106         .word   CONFIG_SYS_TEXT_BASE
107
108 /*
109  * These are defined in the board-specific linker script.
110  * Subtracting _start from them lets the linker put their
111  * relative position in the executable instead of leaving
112  * them null.
113  */
114 #ifdef CONFIG_USE_IRQ
115 /* IRQ stack memory (calculated at run-time) */
116 .globl IRQ_STACK_START
117 IRQ_STACK_START:
118         .word 0x0badc0de
119
120 /* IRQ stack memory (calculated at run-time) */
121 .globl FIQ_STACK_START
122 FIQ_STACK_START:
123         .word 0x0badc0de
124 #endif
125
126 /* IRQ stack memory (calculated at run-time) + 8 bytes */
127 .globl IRQ_STACK_START_IN
128 IRQ_STACK_START_IN:
129         .word 0x0badc0de
130
131 /*
132  * The bootstrap code of nds32 core
133  */
134
135 reset:
136 set_ivb:
137         li      $r0, 0x0
138
139         /* turn on BTB */
140         mtsr    $r0, $misc_ctl
141         /* set IVIC, vector size: 4 bytes, base: 0x0 */
142         mtsr    $r0, $ivb
143
144 load_lli:
145 #ifndef CONFIG_SKIP_LOWLEVEL_INIT
146         jal     load_lowlevel_init
147         jral    $p0
148 #endif
149
150 /*
151  * Set the N1213 (Whitiger) core to superuser mode
152  * According to spec, it is already when reset
153  */
154 turnoff_wtdog:
155 #ifndef CONFIG_SKIP_TRUNOFF_WATCHDOG
156         jal     load_turnoff_watchdog
157         jral    $p0
158 #endif
159
160 /*
161  * Do CPU critical regs init only at reboot,
162  * not when booting from ram
163  */
164 #ifdef CONFIG_INIT_CRITICAL
165         bal     cpu_init_crit           ! Do CPU critical regs init
166 #endif
167
168 /*
169  * Set stackpointer in internal RAM to call board_init_f
170  * $sp must be 8-byte alignment for ABI compliance.
171  */
172 call_board_init_f:
173         li      $sp, CONFIG_SYS_INIT_SP_ADDR
174         li      $r0, 0x00000000
175
176 #ifdef __PIC__
177 #ifdef __NDS32_N1213_43U1H__
178 /* __NDS32_N1213_43U1H__ implies NDS32 V0 ISA */
179         la      $r15, board_init_f      ! store function address into $r15
180 #endif
181 #endif
182         j       board_init_f            ! jump to board_init_f() in lib/board.c
183
184 /*
185  * void relocate_code (addr_sp, gd, addr_moni)
186  *
187  * This "function" does not return, instead it continues in RAM
188  * after relocating the monitor code.
189  *
190  */
191 .globl  relocate_code
192 relocate_code:
193         move    $r4, $r0                /* save addr_sp */
194         move    $r5, $r1                /* save addr of gd */
195         move    $r6, $r2                /* save addr of destination */
196
197 /* Set up the stack */
198 stack_setup:
199         move    $sp, $r4
200
201         la      $r0, _start
202
203         beq     $r0, $r6, clear_bss     /* skip relocation */
204
205         move    $r1, $r6                /* r1 <- scratch for copy_loop */
206         la      $r3, __bss_start
207         sub     $r3, $r3, $r0           /* r3 <- __bss_start_ofs */
208         add     $r2, $r0, $r3           /* r2 <- source end address */
209
210 copy_loop:
211         lwi.p   $r7, [$r0], #4
212         swi.p   $r7, [$r1], #4
213         blt     $r0, $r2, copy_loop
214
215 /*
216  * fix relocations related issues
217  */
218 fix_relocations:
219         l.w     $r0, _TEXT_BASE         /* r0 <- Text base */
220         sub     $r9, $r6, $r0           /* r9 <- relocation offset */
221
222 fix_got:
223 /*
224  * Now we want to update GOT.
225  *
226  * GOT[0] is reserved. GOT[1] is also reserved for the dynamic object
227  * generated by GNU ld. Skip these reserved entries from relocation.
228  */
229         la      $r2, __got_start        /* r2 <- rel __got_start in FLASH */
230         add     $r2, $r2, $r9           /* r2 <- rel __got_start in RAM */
231         la      $r3, __got_end          /* r3 <- rel __got_end in FLASH */
232         add     $r3, $r3, $r9           /* r3 <- rel __got_end in RAM */
233         addi    $r2, $r2, #8            /* skipping first two entries */
234 fix_got_loop:
235         lwi     $r0, [$r2]              /* r0 <- location in FLASH to fix up */
236         add     $r0, $r0, $r9           /* r0 <- location fix up to RAM */
237         swi.p   $r0, [$r2], #4          /* r0 <- store fix into .got in RAM */
238         blt     $r2, $r3, fix_got_loop
239
240 clear_bss:
241         la      $r0, __bss_start        /* r0 <- rel __bss_start in FLASH */
242         add     $r0, $r0, $r9           /* r0 <- rel __bss_start in FLASH */
243         la      $r1, __bss_end          /* r1 <- rel __bss_end in RAM */
244         add     $r1, $r1, $r9           /* r0 <- rel __bss_end in RAM */
245         li      $r2, 0x00000000         /* clear */
246
247 clbss_l:
248         sw      $r2, [$r0]              /* clear loop... */
249         addi    $r0, $r0, #4
250         bne     $r0, $r1, clbss_l
251
252 /*
253  * We are done. Do not return, instead branch to second part of board
254  * initialization, now running from RAM.
255  */
256 call_board_init_r:
257         la      $r0, board_init_r
258         move    $lp, $r0                /* offset of board_init_r() */
259         add     $lp, $lp, $r9           /* real address of board_init_r() */
260         /* setup parameters for board_init_r */
261         move    $r0, $r5                /* gd_t */
262         move    $r1, $r6                /* dest_addr */
263
264 #ifdef __PIC__
265 #ifdef __NDS32_N1213_43U1H__            /* NDS32 V0 ISA */
266         move    $r15, $lp               /* store function address into $r15 */
267 #endif
268 #endif
269
270         /* jump to it ... */
271         jr      $lp                     /* jump to board_init_r() */
272
273 /*
274  * Initialize CPU critical registers
275  *
276  *      1.      Setup control registers
277  *              1.1 Mask all IRQs
278  *              1.2 Flush cache and TLB
279  *              1.3 Disable MMU and cache
280  *      2.      Setup memory timing
281  */
282
283 cpu_init_crit:
284
285         move    $r0, $lp                /* push ra */
286
287         /* Disable Interrupts by clear GIE in $PSW reg */
288         setgie.d
289
290         /* Flush caches and TLB */
291         /* Invalidate caches */
292         bal     invalidate_icac
293         bal     invalidate_dcac
294
295         /* Flush TLB */
296         mfsr    $p0, $MMU_CFG
297         andi    $p0, $p0, 0x3                   ! MMPS
298         li      $p1, 0x2                        ! TLB MMU
299         bne     $p0, $p1, 1f
300         tlbop   flushall                        ! Flush TLB
301
302 1:
303         ! Disable MMU, Dcache
304         ! Whitiger is MMU disabled when reset
305         ! Disable the D$
306         mfsr    $p0, MR_CAC_CTL                 ! Get the $CACHE_CTL reg
307         li      $p1, DIS_DCAC
308         and     $p0, $p0, $p1                   ! Set DC_EN bit
309         mtsr    $p0, MR_CAC_CTL                 ! write back the $CACHE_CTL reg
310         isb
311
312         move    $lp, $r0
313 2:
314         ret
315
316 #ifndef CONFIG_SKIP_LOWLEVEL_INIT
317 load_lowlevel_init:
318         la  $r6, lowlevel_init
319         la  $r7, load_lli + 4
320         sub $p0, $r6, $r7
321         add $p0, $p0, $lp
322 ret
323 #endif
324
325 #ifndef CONFIG_SKIP_TRUNOFF_WATCHDOG
326 load_turnoff_watchdog:
327         la  $r6, turnoff_watchdog
328         la  $r7, turnoff_wtdog + 4
329         sub $p0, $r6, $r7
330         add $p0, $p0, $lp
331 ret
332 #endif
333
334 /*
335  * Invalidate I$
336  */
337 invalidate_icac:
338         ! read $cr1(I CAC/MEM cfg. reg.) configuration
339         mfsr    $t0, CR_ICAC_MEM
340
341         ! Get the ISZ field
342         andi    $p0, $t0, ICAC_MEM_KBF_ISZ
343
344         ! if $p0=0, then no I CAC existed
345         beqz    $p0, end_flush_icache
346
347         ! get $p0 the index of I$ block
348         srli    $p0, $p0, 6
349
350         ! $t1= bit width of I cache line size(ISZ)
351         addi    $t1, $p0, 2
352
353         li      $t4, 1
354         sll     $t5, $t4, $t1                   ! get $t5 cache line size
355         andi    $p1, $t0, ICAC_MEM_KBF_ISET     ! get the ISET field
356         addi    $t2, $p1, 6                     ! $t2= bit width of ISET
357         andi    $p1, $t0, ICAC_MEM_KBF_IWAY     ! get bitfield of Iway
358         srli    $p1, $p1, 3
359         addi    $p1, $p1, 1                     ! then $p1 is I way number
360         add     $t3, $t2, $t1                   ! SHIFT
361         sll     $p1, $p1, $t3                   ! GET the total cache size
362 ICAC_LOOP:
363         sub     $p1, $p1, $t5
364         cctl    $p1, L1I_IX_INVAL
365         bnez    $p1, ICAC_LOOP
366 end_flush_icache:
367         ret
368
369 /*
370  * Invalidate D$
371  */
372 invalidate_dcac:
373         ! read $cr2(D CAC/MEM cfg. reg.) configuration
374         mfsr    $t0, CR_DCAC_MEM
375
376         ! Get the DSZ field
377         andi    $p0, $t0, DCAC_MEM_KBF_DSZ
378
379         ! if $p0=0, then no D CAC existed
380         beqz    $p0, end_flush_dcache
381
382         ! get $p0 the index of D$ block
383         srli    $p0, $p0, 6
384
385         ! $t1= bit width of D cache line size(DSZ)
386         addi    $t1, $p0, 2
387
388         li      $t4, 1
389         sll     $t5, $t4, $t1                   ! get $t5 cache line size
390         andi    $p1, $t0, DCAC_MEM_KBF_DSET     ! get the DSET field
391         addi    $t2, $p1, 6                     ! $t2= bit width of DSET
392         andi    $p1, $t0, DCAC_MEM_KBF_DWAY     ! get bitfield of D way
393         srli    $p1, $p1, 3
394         addi    $p1, $p1, 1                     ! then $p1 is D way number
395         add     $t3, $t2, $t1                   ! SHIFT
396         sll     $p1, $p1, $t3                   ! GET the total cache size
397 DCAC_LOOP:
398         sub     $p1, $p1, $t5
399         cctl    $p1, L1D_IX_INVAL
400         bnez    $p1, DCAC_LOOP
401 end_flush_dcache:
402         ret
403
404 /*
405  * Interrupt handling
406  */
407
408 /*
409  * exception handlers
410  */
411         .align  5
412
413 .macro  SAVE_ALL
414         ! FIXME: Other way to get PC?
415         ! FIXME: Update according to the newest spec!!
416 1:
417         la       $r28, 1
418         push $r28
419         mfsr $r28, PSW                  ! $PSW
420         push $r28
421         mfsr $r28, EIT_EVA              ! $ir1 $EVA
422         push $r28
423         mfsr $r28, EIT_ITYPE            ! $ir2 $ITYPE
424         push $r28
425         mfsr $r28, EIT_MACH_ERR         ! $ir3 Mach Error
426         push $r28
427         mfsr $r28, EIT_INTR_PSW         ! $ir5 $IPSW
428         push $r28
429         mfsr $r28, EIT_PREV_IPSW        ! $ir6 prev $IPSW
430         push $r28
431         mfsr $r28, EIT_PREV_EVA         ! $ir7 prev $EVA
432         push $r28
433         mfsr $r28, EIT_PREV_ITYPE       ! $ir8 prev $ITYPE
434         push $r28
435         mfsr $r28, EIT_INTR_PC          ! $ir9 Interruption PC
436         push $r28
437         mfsr $r28, EIT_PREV_IPC         ! $ir10 prev INTR_PC
438         push $r28
439         mfsr $r28, EIT_OVL_INTR_PC      ! $ir11 Overflowed INTR_PC
440         push $r28
441         mfusr $r28, $d1.lo
442         push $r28
443         mfusr $r28, $d1.hi
444         push $r28
445         mfusr $r28, $d0.lo
446         push $r28
447         mfusr $r28, $d0.hi
448         push $r28
449         pushm $r0, $r30         ! store $sp-$r31, ra-$r30, $gp-$r29, $r28-$fp
450         addi    $sp, $sp, -4    ! make room for implicit pt_regs parameters
451 .endm
452
453         .align  5
454 tlb_fill:
455         SAVE_ALL
456         move    $r0, $sp                        ! To get the kernel stack
457         li      $r1, 1                          ! Determine interruption type
458         bal     do_interruption
459
460         .align  5
461 tlb_not_present:
462         SAVE_ALL
463         move    $r0, $sp                        ! To get the kernel stack
464         li      $r1, 2                          ! Determine interruption type
465         bal     do_interruption
466
467         .align  5
468 tlb_misc:
469         SAVE_ALL
470         move    $r0, $sp                        ! To get the kernel stack
471         li      $r1, 3                          ! Determine interruption type
472         bal     do_interruption
473
474         .align  5
475 tlb_vlpt_miss:
476         SAVE_ALL
477         move    $r0, $sp                        ! To get the kernel stack
478         li      $r1, 4                          ! Determine interruption type
479         bal     do_interruption
480
481         .align  5
482 machine_error:
483         SAVE_ALL
484         move    $r0, $sp                        ! To get the kernel stack
485         li      $r1, 5                          ! Determine interruption type
486         bal     do_interruption
487
488         .align  5
489 debug:
490         SAVE_ALL
491         move    $r0, $sp                        ! To get the kernel stack
492         li      $r1, 6                          ! Determine interruption type
493         bal     do_interruption
494
495         .align  5
496 general_exception:
497         SAVE_ALL
498         move    $r0, $sp                        ! To get the kernel stack
499         li      $r1, 7                          ! Determine interruption type
500         bal     do_interruption
501
502         .align  5
503 syscall:
504         SAVE_ALL
505         move    $r0, $sp                        ! To get the kernel stack
506         li      $r1, 8                          ! Determine interruption type
507         bal     do_interruption
508
509         .align  5
510 internal_interrupt:
511         SAVE_ALL
512         move    $r0, $sp                        ! To get the kernel stack
513         li      $r1, 9                          ! Determine interruption type
514         bal     do_interruption
515
516         .align  5
517 software_interrupt:
518         SAVE_ALL
519         move    $r0, $sp                        ! To get the kernel stack
520         li      $r1, 10                         ! Determine interruption type
521         bal     do_interruption
522
523         .align  5
524
525 /*
526  * void reset_cpu(ulong addr);
527  * $r0: input address to jump to
528  */
529 .globl reset_cpu
530 reset_cpu:
531 /* No need to disable MMU because we never enable it */
532
533         bal     invalidate_icac
534         bal     invalidate_dcac
535         mfsr    $p0, $MMU_CFG
536         andi    $p0, $p0, 0x3                   ! MMPS
537         li      $p1, 0x2                        ! TLB MMU
538         bne     $p0, $p1, 1f
539         tlbop   flushall                        ! Flush TLB
540 1:
541         mfsr    $p0, MR_CAC_CTL                 ! Get the $CACHE_CTL reg
542         li      $p1, DIS_DCAC
543         and     $p0, $p0, $p1                   ! Clear the DC_EN bit
544         mtsr    $p0, MR_CAC_CTL                 ! Write back the $CACHE_CTL reg
545         br      $r0                             ! Jump to the input address