GNU Linux-libre 4.19.286-gnu1
[releases.git] / arch / nds32 / kernel / head.S
1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (C) 2005-2017 Andes Technology Corporation
3
4 #include <linux/linkage.h>
5 #include <linux/init.h>
6 #include <asm/ptrace.h>
7 #include <asm/asm-offsets.h>
8 #include <asm/page.h>
9 #include <asm/pgtable.h>
10 #include <asm/sizes.h>
11 #include <asm/thread_info.h>
12
13 #ifdef CONFIG_CPU_BIG_ENDIAN
14 #define OF_DT_MAGIC 0xd00dfeed
15 #else
16 #define OF_DT_MAGIC 0xedfe0dd0
17 #endif
18
19         .globl  swapper_pg_dir
20         .equ    swapper_pg_dir, TEXTADDR - 0x4000
21
22 /*
23  * Kernel startup entry point.
24  */
25         .section ".head.text", "ax"
26         .type   _stext, %function
27 ENTRY(_stext)
28         setgie.d                            ! Disable interrupt
29         isb
30 /*
31  * Disable I/D-cache and enable it at a proper time
32  */
33         mfsr    $r0, $mr8
34         li      $r1, #~(CACHE_CTL_mskIC_EN|CACHE_CTL_mskDC_EN)
35         and     $r0, $r0, $r1
36         mtsr    $r0, $mr8
37
38 /*
39  * Process device tree blob
40  */
41         andi    $r0,$r2,#0x3
42         li      $r10, 0
43         bne     $r0, $r10, _nodtb
44         lwi     $r0, [$r2]
45         li      $r1, OF_DT_MAGIC
46         bne     $r0, $r1, _nodtb
47         move    $r10, $r2
48 _nodtb:
49
50 /*
51  * Create a temporary mapping area for booting, before start_kernel
52  */
53         sethi   $r4, hi20(swapper_pg_dir)
54         li      $p0, (PAGE_OFFSET - PHYS_OFFSET)
55         sub     $r4, $r4, $p0
56         tlbop   FlushAll            ! invalidate TLB\n"
57         isb
58         mtsr    $r4, $L1_PPTB       ! load page table pointer\n"
59
60 #ifdef CONFIG_CPU_DCACHE_DISABLE
61         #define MMU_CTL_NTCC MMU_CTL_CACHEABLE_NON
62 #else
63         #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
64                 #define MMU_CTL_NTCC MMU_CTL_CACHEABLE_WT
65         #else
66                 #define MMU_CTL_NTCC MMU_CTL_CACHEABLE_WB
67         #endif
68 #endif
69
70 /* set NTC cacheability, mutliple page size in use */
71         mfsr    $r3, $MMU_CTL
72 #if CONFIG_MEMORY_START >= 0xc0000000
73         ori     $r3, $r3, (MMU_CTL_NTCC << MMU_CTL_offNTC3)
74 #elif CONFIG_MEMORY_START >= 0x80000000
75         ori     $r3, $r3, (MMU_CTL_NTCC << MMU_CTL_offNTC2)
76 #elif CONFIG_MEMORY_START >= 0x40000000
77         ori     $r3, $r3, (MMU_CTL_NTCC << MMU_CTL_offNTC1)
78 #else
79         ori     $r3, $r3, (MMU_CTL_NTCC << MMU_CTL_offNTC0)
80 #endif
81
82 #ifdef CONFIG_ANDES_PAGE_SIZE_4KB
83         ori     $r3, $r3, #(MMU_CTL_mskMPZIU)
84 #else
85         ori     $r3, $r3, #(MMU_CTL_mskMPZIU|MMU_CTL_D8KB)
86 #endif
87 #ifdef CONFIG_HW_SUPPORT_UNALIGNMENT_ACCESS
88         li      $r0, #MMU_CTL_UNA
89         or      $r3, $r3, $r0
90 #endif
91         mtsr    $r3, $MMU_CTL
92         isb
93
94 /* set page size and size of kernel image */
95         mfsr    $r0, $MMU_CFG
96         srli    $r3, $r0, MMU_CFG_offfEPSZ
97         zeb     $r3, $r3
98         bnez    $r3, _extra_page_size_support
99 #ifdef CONFIG_ANDES_PAGE_SIZE_4KB
100         li      $r5, #SZ_4K                 ! Use 4KB page size
101 #else
102         li      $r5, #SZ_8K                 ! Use 8KB page size
103         li      $r3, #1
104 #endif
105         mtsr    $r3, $TLB_MISC
106         b       _image_size_check
107
108 _extra_page_size_support:                    ! Use epzs pages size
109         clz     $r6, $r3
110         subri   $r2, $r6, #31
111         li      $r3, #1
112         sll     $r3, $r3, $r2
113         /* MMU_CFG.EPSZ value -> meaning */
114         mul     $r5, $r3, $r3
115         slli    $r5, $r5, #14
116         /* MMU_CFG.EPSZ  -> TLB_MISC.ACC_PSZ */
117         addi    $r3, $r2, #0x2
118         mtsr    $r3, $TLB_MISC
119
120 _image_size_check:
121         /* calculate the image maximum size accepted by TLB config */
122         andi    $r6, $r0, MMU_CFG_mskTBW
123         andi    $r0, $r0, MMU_CFG_mskTBS
124         srli    $r6, $r6, MMU_CFG_offTBW
125         srli    $r0, $r0, MMU_CFG_offTBS
126         /*
127          * we just map the kernel to the maximum way - 1 of tlb
128          * reserver one way for UART VA mapping
129          * it will cause page fault if UART mapping cover the kernel mapping
130          *
131          * direct mapping is not supported now.
132          */
133         li      $r2, 't'
134         beqz    $r6, __error                 ! MMU_CFG.TBW = 0 is direct mappin
135         addi    $r0, $r0, #0x2               ! MMU_CFG.TBS value -> meaning
136         sll     $r0, $r6, $r0                ! entries = k-way * n-set
137         mul     $r6, $r0, $r5                ! max size = entries * page size
138         /* check kernel image size */
139         la      $r3, (_end - PAGE_OFFSET)
140         li      $r2, 's'
141         bgt     $r3, $r6, __error
142
143         li      $r2, #(PHYS_OFFSET + TLB_DATA_kernel_text_attr)
144         li      $r3, PAGE_OFFSET
145         add     $r6, $r6, $r3
146
147 _tlb:
148         mtsr    $r3, $TLB_VPN
149         dsb
150         tlbop   $r2, RWR
151         isb
152         add     $r3, $r3, $r5
153         add     $r2, $r2, $r5
154         bgt     $r6, $r3, _tlb
155         mfsr    $r3, $TLB_MISC      ! setup access page size
156         li      $r2, #~0xf
157         and     $r3, $r3, $r2
158 #ifdef CONFIG_ANDES_PAGE_SIZE_8KB
159         ori    $r3, $r3, #0x1
160 #endif
161         mtsr    $r3, $TLB_MISC
162
163         mfsr    $r0, $MISC_CTL      ! Enable BTB and RTP and shadow sp
164         ori     $r0, $r0, #MISC_init
165         mtsr    $r0, $MISC_CTL
166
167         mfsr    $p1, $PSW
168         li      $r15, #~PSW_clr             ! clear WBNA|DME|IME|DT|IT|POM|INTL|GIE
169         and     $p1, $p1, $r15
170         ori     $p1, $p1, #PSW_init
171         mtsr    $p1, $IPSW                  ! when iret, it will automatically enable MMU
172         la      $lp, __mmap_switched
173         mtsr    $lp, $IPC
174         iret
175         nop
176
177         .type   __switch_data, %object
178 __switch_data:
179         .long   __bss_start                 ! $r6
180         .long   _end                        ! $r7
181         .long   __atags_pointer             ! $atag_pointer
182         .long   init_task                   ! $r9, move to $r25
183         .long   init_thread_union + THREAD_SIZE    ! $sp
184
185
186 /*
187  * The following fragment of code is executed with the MMU on in MMU mode,
188  * and uses absolute addresses; this is not position independent.
189  */
190         .align
191         .type   __mmap_switched, %function
192 __mmap_switched:
193         la  $r3, __switch_data
194         lmw.bim $r6, [$r3], $r9, #0b0001
195         move    $r25, $r9
196         move    $fp, #0             ! Clear  BSS (and zero $fp)
197         beq $r7, $r6, _RRT
198 1:      swi.bi  $fp, [$r6], #4
199         bne $r7, $r6, 1b
200         swi     $r10, [$r8]
201
202 _RRT:
203         b   start_kernel
204
205 __error:
206         b   __error