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