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