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