]> git.sur5r.net Git - u-boot/blob - arch/nds32/cpu/n1213/start.S
SPDX: Convert all of our single license tags to Linux Kernel style
[u-boot] / 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 (!defined(CONFIG_SYS_ICACHE_OFF) || !defined(CONFIG_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 #ifndef CONFIG_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 !defined(CONFIG_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 !defined(CONFIG_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  * Do CPU critical regs init only at reboot,
205  * not when booting from ram
206  */
207 #ifdef CONFIG_INIT_CRITICAL
208         jal     cpu_init_crit           ! Do CPU critical regs init
209 #endif
210
211 /*
212  * Set stackpointer in internal RAM to call board_init_f
213  * $sp must be 8-byte alignment for ABI compliance.
214  */
215 call_board_init_f:
216         li              $sp, CONFIG_SYS_INIT_SP_ADDR
217         move    $r0, $sp
218         bal     board_init_f_alloc_reserve
219         move    $sp, $r0
220         bal     board_init_f_init_reserve
221 #ifdef CONFIG_DEBUG_UART
222         bal     debug_uart_init
223 #endif
224         li              $r0, 0x00000000
225 #ifdef __PIC__
226 #ifdef __NDS32_N1213_43U1H__
227 /* __NDS32_N1213_43U1H__ implies NDS32 V0 ISA */
228         la      $r15, board_init_f      ! store function address into $r15
229 #endif
230 #endif
231         j       board_init_f            ! jump to board_init_f() in lib/board.c
232
233 /*
234  * void relocate_code (addr_sp, gd, addr_moni)
235  *
236  * This "function" does not return, instead it continues in RAM
237  * after relocating the monitor code.
238  *
239  */
240
241 /*
242  *  gp = ~RAM_SIZE - TEXT_SIZE for burn/load mode
243  */
244
245 .globl  relocate_code
246 relocate_code:
247         move    $r4, $r0                /* save addr_sp */
248         move    $r5, $r1                /* save addr of gd */
249         move    $r6, $r2                /* save addr of destination */
250
251 /* Set up the stack */
252 stack_setup:
253         move    $sp, $r4
254
255         la      $r0, _start@GOTOFF
256         beq     $r0, $r6, clear_bss     /* skip relocation */
257
258         la       $r1, _end@GOTOFF
259         move $r2, $r6                   /* r2 <- scratch for copy_loop */
260 copy_loop:
261         lmw.bim $r11, [$r0], $r18
262         smw.bim $r11, [$r2], $r18
263         blt     $r0, $r1, copy_loop
264 /*
265  * fix relocations related issues
266  */
267 fix_relocations:
268         l.w     $r0, _TEXT_BASE@GOTOFF  /* r0 <- Text base */
269         sub     $r9, $r6, $r0                   /* r9 <- relocation offset */
270
271         la  $r7, __rel_dyn_start@GOTOFF
272         add     $r7, $r7, $r9           /* r2 <- rel __got_start in RAM */
273         la  $r8, __rel_dyn_end@GOTOFF
274         add     $r8, $r8, $r9           /* r2 <- rel __got_start in RAM */
275         li  $r3, #0x2a /* R_NDS32_RELATIVE */
276 1:
277         lmw.bim $r0, [$r7], $r2 /* r0,r1,r2 <- adr,type,addend */
278         bne $r1, $r3, 2f
279
280         add $r0, $r0, $r9
281         add $r2, $r2, $r9
282         sw  $r2, [$r0]
283 2:
284         blt $r7, $r8, 1b
285
286 clear_bss:
287         la      $r0, __bss_start@GOTOFF /* r0 <- rel __bss_start in FLASH */
288         add     $r0, $r0, $r9           /* r0 <- rel __bss_start in FLASH */
289         la      $r1, __bss_end@GOTOFF           /* r1 <- rel __bss_end in RAM */
290         add     $r1, $r1, $r9           /* r0 <- rel __bss_end in RAM */
291         li      $r2, 0x00000000         /* clear */
292
293 clbss_l:
294         sw      $r2, [$r0]              /* clear loop... */
295         addi    $r0, $r0, #4
296         bne     $r0, $r1, clbss_l
297
298 /*
299  * We are done. Do not return, instead branch to second part of board
300  * initialization, now running from RAM.
301  */
302 call_board_init_r:
303         bal invalidate_icache_all
304         bal flush_dcache_all
305         la      $r0, board_init_r@GOTOFF
306         move    $lp, $r0                /* offset of board_init_r() */
307         add     $lp, $lp, $r9           /* real address of board_init_r() */
308         /* setup parameters for board_init_r */
309         move    $r0, $r5                /* gd_t */
310         move    $r1, $r6                /* dest_addr */
311
312 #ifdef __PIC__
313 #ifdef __NDS32_N1213_43U1H__            /* NDS32 V0 ISA */
314         move    $r15, $lp               /* store function address into $r15 */
315 #endif
316 #endif
317
318         /* jump to it ... */
319         jr      $lp                     /* jump to board_init_r() */
320
321 /*
322  * Initialize CPU critical registers
323  *
324  *      1.      Setup control registers
325  *              1.1 Mask all IRQs
326  *              1.2 Flush cache and TLB
327  *              1.3 Disable MMU and cache
328  *      2.      Setup memory timing
329  */
330
331 cpu_init_crit:
332
333         move    $r0, $lp                /* push ra */
334
335         /* Disable Interrupts by clear GIE in $PSW reg */
336         setgie.d
337
338         /* Flush caches and TLB */
339         /* Invalidate caches */
340         jal     invalidate_icac
341         jal     invalidate_dcac
342
343         /* Flush TLB */
344         mfsr    $p0, $MMU_CFG
345         andi    $p0, $p0, 0x3                   ! MMPS
346         li      $p1, 0x2                        ! TLB MMU
347         bne     $p0, $p1, 1f
348         tlbop   flushall                        ! Flush TLB
349
350 1:
351         ! Disable MMU, Dcache
352         ! Whitiger is MMU disabled when reset
353         ! Disable the D$
354         mfsr    $p0, MR_CAC_CTL                 ! Get the $CACHE_CTL reg
355         li      $p1, DIS_DCAC
356         and     $p0, $p0, $p1                   ! Set DC_EN bit
357         mtsr    $p0, MR_CAC_CTL                 ! write back the $CACHE_CTL reg
358         isb
359
360         move    $lp, $r0
361 2:
362         ret
363
364 /*
365  * Invalidate I$
366  */
367 invalidate_icac:
368         ! read $cr1(I CAC/MEM cfg. reg.) configuration
369         mfsr    $t0, CR_ICAC_MEM
370
371         ! Get the ISZ field
372         andi    $p0, $t0, ICAC_MEM_KBF_ISZ
373
374         ! if $p0=0, then no I CAC existed
375         beqz    $p0, end_flush_icache
376
377         ! get $p0 the index of I$ block
378         srli    $p0, $p0, 6
379
380         ! $t1= bit width of I cache line size(ISZ)
381         addi    $t1, $p0, 2
382
383         li      $t4, 1
384         sll     $t5, $t4, $t1                   ! get $t5 cache line size
385         andi    $p1, $t0, ICAC_MEM_KBF_ISET     ! get the ISET field
386         addi    $t2, $p1, 6                     ! $t2= bit width of ISET
387         andi    $p1, $t0, ICAC_MEM_KBF_IWAY     ! get bitfield of Iway
388         srli    $p1, $p1, 3
389         addi    $p1, $p1, 1                     ! then $p1 is I way number
390         add     $t3, $t2, $t1                   ! SHIFT
391         sll     $p1, $p1, $t3                   ! GET the total cache size
392 ICAC_LOOP:
393         sub     $p1, $p1, $t5
394         cctl    $p1, L1I_IX_INVAL
395         bnez    $p1, ICAC_LOOP
396 end_flush_icache:
397         ret
398
399 /*
400  * Invalidate D$
401  */
402 invalidate_dcac:
403         ! read $cr2(D CAC/MEM cfg. reg.) configuration
404         mfsr    $t0, CR_DCAC_MEM
405
406         ! Get the DSZ field
407         andi    $p0, $t0, DCAC_MEM_KBF_DSZ
408
409         ! if $p0=0, then no D CAC existed
410         beqz    $p0, end_flush_dcache
411
412         ! get $p0 the index of D$ block
413         srli    $p0, $p0, 6
414
415         ! $t1= bit width of D cache line size(DSZ)
416         addi    $t1, $p0, 2
417
418         li      $t4, 1
419         sll     $t5, $t4, $t1                   ! get $t5 cache line size
420         andi    $p1, $t0, DCAC_MEM_KBF_DSET     ! get the DSET field
421         addi    $t2, $p1, 6                     ! $t2= bit width of DSET
422         andi    $p1, $t0, DCAC_MEM_KBF_DWAY     ! get bitfield of D way
423         srli    $p1, $p1, 3
424         addi    $p1, $p1, 1                     ! then $p1 is D way number
425         add     $t3, $t2, $t1                   ! SHIFT
426         sll     $p1, $p1, $t3                   ! GET the total cache size
427 DCAC_LOOP:
428         sub     $p1, $p1, $t5
429         cctl    $p1, L1D_IX_INVAL
430         bnez    $p1, DCAC_LOOP
431 end_flush_dcache:
432         ret
433
434 /*
435  * Interrupt handling
436  */
437
438 /*
439  * exception handlers
440  */
441         .align  5
442
443 .macro  SAVE_ALL
444         ! FIXME: Other way to get PC?
445         ! FIXME: Update according to the newest spec!!
446 1:
447         li       $r28, 1
448         push $r28
449         mfsr $r28, PSW                  ! $PSW
450         push $r28
451         mfsr $r28, EIT_EVA              ! $ir1 $EVA
452         push $r28
453         mfsr $r28, EIT_ITYPE            ! $ir2 $ITYPE
454         push $r28
455         mfsr $r28, EIT_MACH_ERR         ! $ir3 Mach Error
456         push $r28
457         mfsr $r28, EIT_INTR_PSW         ! $ir5 $IPSW
458         push $r28
459         mfsr $r28, EIT_PREV_IPSW        ! $ir6 prev $IPSW
460         push $r28
461         mfsr $r28, EIT_PREV_EVA         ! $ir7 prev $EVA
462         push $r28
463         mfsr $r28, EIT_PREV_ITYPE       ! $ir8 prev $ITYPE
464         push $r28
465         mfsr $r28, EIT_INTR_PC          ! $ir9 Interruption PC
466         push $r28
467         mfsr $r28, EIT_PREV_IPC         ! $ir10 prev INTR_PC
468         push $r28
469         mfsr $r28, EIT_OVL_INTR_PC      ! $ir11 Overflowed INTR_PC
470         push $r28
471         mfusr $r28, $d1.lo
472         push $r28
473         mfusr $r28, $d1.hi
474         push $r28
475         mfusr $r28, $d0.lo
476         push $r28
477         mfusr $r28, $d0.hi
478         push $r28
479         pushm $r0, $r30         ! store $sp-$r31, ra-$r30, $gp-$r29, $r28-$fp
480         addi    $sp, $sp, -4    ! make room for implicit pt_regs parameters
481 .endm
482
483         .align  5
484 tlb_fill:
485         SAVE_ALL
486         move    $r0, $sp                        ! To get the kernel stack
487         li      $r1, 1                          ! Determine interruption type
488         bal     do_interruption
489
490         .align  5
491 tlb_not_present:
492         SAVE_ALL
493         move    $r0, $sp                        ! To get the kernel stack
494         li      $r1, 2                          ! Determine interruption type
495         bal     do_interruption
496
497         .align  5
498 tlb_misc:
499         SAVE_ALL
500         move    $r0, $sp                        ! To get the kernel stack
501         li      $r1, 3                          ! Determine interruption type
502         bal     do_interruption
503
504         .align  5
505 tlb_vlpt_miss:
506         SAVE_ALL
507         move    $r0, $sp                        ! To get the kernel stack
508         li      $r1, 4                          ! Determine interruption type
509         bal     do_interruption
510
511         .align  5
512 machine_error:
513         SAVE_ALL
514         move    $r0, $sp                        ! To get the kernel stack
515         li      $r1, 5                          ! Determine interruption type
516         bal     do_interruption
517
518         .align  5
519 debug:
520         SAVE_ALL
521         move    $r0, $sp                        ! To get the kernel stack
522         li      $r1, 6                          ! Determine interruption type
523         bal     do_interruption
524
525         .align  5
526 general_exception:
527         SAVE_ALL
528         move    $r0, $sp                        ! To get the kernel stack
529         li      $r1, 7                          ! Determine interruption type
530         bal     do_interruption
531
532         .align  5
533 syscall:
534         SAVE_ALL
535         move    $r0, $sp                        ! To get the kernel stack
536         li      $r1, 8                          ! Determine interruption type
537         bal     do_interruption
538
539         .align  5
540 internal_interrupt:
541         SAVE_ALL
542         move    $r0, $sp                        ! To get the kernel stack
543         li      $r1, 9                          ! Determine interruption type
544         bal     do_interruption
545
546         .align  5
547 software_interrupt:
548         SAVE_ALL
549         move    $r0, $sp                        ! To get the kernel stack
550         li      $r1, 10                         ! Determine interruption type
551         bal     do_interruption
552
553         .align  5
554
555 /*
556  * void reset_cpu(ulong addr);
557  * $r0: input address to jump to
558  */
559 .globl reset_cpu
560 reset_cpu:
561 /* No need to disable MMU because we never enable it */
562
563         bal     invalidate_icac
564         bal     invalidate_dcac
565         mfsr    $p0, $MMU_CFG
566         andi    $p0, $p0, 0x3                   ! MMPS
567         li      $p1, 0x2                        ! TLB MMU
568         bne     $p0, $p1, 1f
569         tlbop   flushall                        ! Flush TLB
570 1:
571         mfsr    $p0, MR_CAC_CTL                 ! Get the $CACHE_CTL reg
572         li      $p1, DIS_DCAC
573         and     $p0, $p0, $p1                   ! Clear the DC_EN bit
574         mtsr    $p0, MR_CAC_CTL                 ! Write back the $CACHE_CTL reg
575         br      $r0                             ! Jump to the input address