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