1/* 2 * CRISv32 kernel startup code. 3 * 4 * Copyright (C) 2003, Axis Communications AB 5 */ 6 7#define ASSEMBLER_MACROS_ONLY 8 9/* 10 * The macros found in mmu_defs_asm.h uses the ## concatenation operator, so 11 * -traditional must not be used when assembling this file. 12 */ 13#include <arch/memmap.h> 14#include <hwregs/reg_rdwr.h> 15#include <hwregs/intr_vect.h> 16#include <hwregs/asm/mmu_defs_asm.h> 17#include <hwregs/asm/reg_map_asm.h> 18#include <mach/startup.inc> 19 20#define CRAMFS_MAGIC 0x28cd3d45 21#define JHEAD_MAGIC 0x1FF528A6 22#define JHEAD_SIZE 8 23#define RAM_INIT_MAGIC 0x56902387 24#define COMMAND_LINE_MAGIC 0x87109563 25#define NAND_BOOT_MAGIC 0x9a9db001 26 27 ;; NOTE: R8 and R9 carry information from the decompressor (if the 28 ;; kernel was compressed). They must not be used in the code below 29 ;; until they are read! 30 31 ;; Exported symbols. 32 .global etrax_irv 33 .global romfs_start 34 .global romfs_length 35 .global romfs_in_flash 36 .global nand_boot 37 .global swapper_pg_dir 38 39 .text 40tstart: 41 ;; This is the entry point of the kernel. The CPU is currently in 42 ;; supervisor mode. 43 ;; 44 ;; 0x00000000 if flash. 45 ;; 0x40004000 if DRAM. 46 ;; 47 di 48 49 START_CLOCKS 50 51 SETUP_WAIT_STATES 52 53 GIO_INIT 54 55 ;; Setup and enable the MMU. Use same configuration for both the data 56 ;; and the instruction MMU. 57 ;; 58 ;; Note; 3 cycles is needed for a bank-select to take effect. Further; 59 ;; bank 1 is the instruction MMU, bank 2 is the data MMU. 60 61#ifdef CONFIG_CRIS_MACH_ARTPEC3 62 move.d REG_FIELD(mmu, rw_mm_kbase_hi, base_e, 8) \ 63 | REG_FIELD(mmu, rw_mm_kbase_hi, base_c, 4) \ 64 | REG_FIELD(mmu, rw_mm_kbase_hi, base_d, 5) \ 65 | REG_FIELD(mmu, rw_mm_kbase_hi, base_b, 0xb), $r0 66#else 67 move.d REG_FIELD(mmu, rw_mm_kbase_hi, base_e, 8) \ 68 | REG_FIELD(mmu, rw_mm_kbase_hi, base_c, 4) \ 69 | REG_FIELD(mmu, rw_mm_kbase_hi, base_b, 0xb), $r0 70#endif 71 72 ;; Temporary map of 0x40 -> 0x40 and 0x00 -> 0x00. 73 move.d REG_FIELD(mmu, rw_mm_kbase_lo, base_4, 4) \ 74 | REG_FIELD(mmu, rw_mm_kbase_lo, base_0, 0), $r1 75 76 ;; Enable certain page protections and setup linear mapping 77 ;; for f,e,c,b,4,0. 78 79 ;; ARTPEC-3: 80 ;; c,d used for linear kernel mapping, up to 512 MB 81 ;; e used for vmalloc 82 ;; f unused, but page mapped to get page faults 83 84 ;; ETRAX FS: 85 ;; c used for linear kernel mapping, up to 256 MB 86 ;; d used for vmalloc 87 ;; e,f used for memory-mapped NOR flash 88 89#ifdef CONFIG_CRIS_MACH_ARTPEC3 90 move.d REG_STATE(mmu, rw_mm_cfg, we, on) \ 91 | REG_STATE(mmu, rw_mm_cfg, acc, on) \ 92 | REG_STATE(mmu, rw_mm_cfg, ex, on) \ 93 | REG_STATE(mmu, rw_mm_cfg, inv, on) \ 94 | REG_STATE(mmu, rw_mm_cfg, seg_f, page) \ 95 | REG_STATE(mmu, rw_mm_cfg, seg_e, page) \ 96 | REG_STATE(mmu, rw_mm_cfg, seg_d, linear) \ 97 | REG_STATE(mmu, rw_mm_cfg, seg_c, linear) \ 98 | REG_STATE(mmu, rw_mm_cfg, seg_b, linear) \ 99 | REG_STATE(mmu, rw_mm_cfg, seg_a, page) \ 100 | REG_STATE(mmu, rw_mm_cfg, seg_9, page) \ 101 | REG_STATE(mmu, rw_mm_cfg, seg_8, page) \ 102 | REG_STATE(mmu, rw_mm_cfg, seg_7, page) \ 103 | REG_STATE(mmu, rw_mm_cfg, seg_6, page) \ 104 | REG_STATE(mmu, rw_mm_cfg, seg_5, page) \ 105 | REG_STATE(mmu, rw_mm_cfg, seg_4, linear) \ 106 | REG_STATE(mmu, rw_mm_cfg, seg_3, page) \ 107 | REG_STATE(mmu, rw_mm_cfg, seg_2, page) \ 108 | REG_STATE(mmu, rw_mm_cfg, seg_1, page) \ 109 | REG_STATE(mmu, rw_mm_cfg, seg_0, linear), $r2 110#else 111 move.d REG_STATE(mmu, rw_mm_cfg, we, on) \ 112 | REG_STATE(mmu, rw_mm_cfg, acc, on) \ 113 | REG_STATE(mmu, rw_mm_cfg, ex, on) \ 114 | REG_STATE(mmu, rw_mm_cfg, inv, on) \ 115 | REG_STATE(mmu, rw_mm_cfg, seg_f, linear) \ 116 | REG_STATE(mmu, rw_mm_cfg, seg_e, linear) \ 117 | REG_STATE(mmu, rw_mm_cfg, seg_d, page) \ 118 | REG_STATE(mmu, rw_mm_cfg, seg_c, linear) \ 119 | REG_STATE(mmu, rw_mm_cfg, seg_b, linear) \ 120 | REG_STATE(mmu, rw_mm_cfg, seg_a, page) \ 121 | REG_STATE(mmu, rw_mm_cfg, seg_9, page) \ 122 | REG_STATE(mmu, rw_mm_cfg, seg_8, page) \ 123 | REG_STATE(mmu, rw_mm_cfg, seg_7, page) \ 124 | REG_STATE(mmu, rw_mm_cfg, seg_6, page) \ 125 | REG_STATE(mmu, rw_mm_cfg, seg_5, page) \ 126 | REG_STATE(mmu, rw_mm_cfg, seg_4, linear) \ 127 | REG_STATE(mmu, rw_mm_cfg, seg_3, page) \ 128 | REG_STATE(mmu, rw_mm_cfg, seg_2, page) \ 129 | REG_STATE(mmu, rw_mm_cfg, seg_1, page) \ 130 | REG_STATE(mmu, rw_mm_cfg, seg_0, linear), $r2 131#endif 132 133 ;; Update instruction MMU. 134 move 1, $srs 135 nop 136 nop 137 nop 138 move $r0, $s2 ; kbase_hi. 139 move $r1, $s1 ; kbase_lo. 140 move $r2, $s0 ; mm_cfg, virtual memory configuration. 141 142 ;; Update data MMU. 143 move 2, $srs 144 nop 145 nop 146 nop 147 move $r0, $s2 ; kbase_hi. 148 move $r1, $s1 ; kbase_lo 149 move $r2, $s0 ; mm_cfg, virtual memory configuration. 150 151 ;; Enable data and instruction MMU. 152 move 0, $srs 153 moveq 0xf, $r0 ; IMMU, DMMU, DCache, Icache on 154 nop 155 nop 156 nop 157 move $r0, $s0 158 nop 159 nop 160 nop 161 162 ; Check if starting from DRAM (network->RAM boot or unpacked 163 ; compressed kernel), or directly from flash. 164 lapcq ., $r0 165 and.d 0x7fffffff, $r0 ; Mask off the non-cache bit. 166 cmp.d 0x10000, $r0 ; Arbitrary, something above this code. 167 blo _inflash0 168 nop 169 170 jump _inram ; Jump to cached RAM. 171 nop 172 173 ;; Jumpgate. 174_inflash0: 175 jump _inflash 176 nop 177 178 ;; Put the following in a section so that storage for it can be 179 ;; reclaimed after init is finished. 180 .section ".init.text", "ax" 181 182_inflash: 183 184 ;; Initialize DRAM. 185 cmp.d RAM_INIT_MAGIC, $r8 ; Already initialized? 186 beq _dram_initialized 187 nop 188 189#if defined CONFIG_ETRAXFS 190#include "../mach-fs/dram_init.S" 191#elif defined CONFIG_CRIS_MACH_ARTPEC3 192#include "../mach-a3/dram_init.S" 193#else 194#error Only ETRAXFS and ARTPEC-3 supported! 195#endif 196 197 198_dram_initialized: 199 ;; Copy the text and data section to DRAM. This depends on that the 200 ;; variables used below are correctly set up by the linker script. 201 ;; The calculated value stored in R4 is used below. 202 ;; Leave the cramfs file system (piggybacked after the kernel) in flash. 203 moveq 0, $r0 ; Source. 204 move.d text_start, $r1 ; Destination. 205 move.d __vmlinux_end, $r2 206 move.d $r2, $r4 207 sub.d $r1, $r4 2081: move.w [$r0+], $r3 209 move.w $r3, [$r1+] 210 cmp.d $r2, $r1 211 blo 1b 212 nop 213 214 ;; Check for cramfs. 215 moveq 0, $r0 216 move.d romfs_length, $r1 217 move.d $r0, [$r1] 218 move.d [$r4], $r0 ; cramfs_super.magic 219 cmp.d CRAMFS_MAGIC, $r0 220 bne 1f 221 nop 222 223 ;; Set length and start of cramfs, set romfs_in_flash flag 224 addoq +4, $r4, $acr 225 move.d [$acr], $r0 226 move.d romfs_length, $r1 227 move.d $r0, [$r1] 228 add.d 0xf0000000, $r4 ; Add cached flash start in virtual memory. 229 move.d romfs_start, $r1 230 move.d $r4, [$r1] 2311: moveq 1, $r0 232 move.d romfs_in_flash, $r1 233 move.d $r0, [$r1] 234 235 jump _start_it ; Jump to cached code. 236 nop 237 238_inram: 239 ;; Check if booting from NAND flash; if so, set appropriate flags 240 ;; and move on. 241 cmp.d NAND_BOOT_MAGIC, $r12 242 bne move_cramfs ; not nand, jump 243 moveq 1, $r0 244 move.d nand_boot, $r1 ; tell axisflashmap we're booting from NAND 245 move.d $r0, [$r1] 246 moveq 0, $r0 ; tell axisflashmap romfs is not in 247 move.d romfs_in_flash, $r1 ; (directly accessed) flash 248 move.d $r0, [$r1] 249 jump _start_it ; continue with boot 250 nop 251 252move_cramfs: 253 ;; kernel is in DRAM. 254 ;; Must figure out if there is a piggybacked rootfs image or not. 255 ;; Set romfs_length to 0 => no rootfs image available by default. 256 moveq 0, $r0 257 move.d romfs_length, $r1 258 move.d $r0, [$r1] 259 260 ;; The kernel could have been unpacked to DRAM by the loader, but 261 ;; the cramfs image could still be in the flash immediately 262 ;; following the compressed kernel image. The loader passes the address 263 ;; of the byte succeeding the last compressed byte in the flash in 264 ;; register R9 when starting the kernel. 265 cmp.d 0x0ffffff8, $r9 266 bhs _no_romfs_in_flash ; R9 points outside the flash area. 267 nop 268 ;; cramfs rootfs might to be in flash. Check for it. 269 move.d [$r9], $r0 ; cramfs_super.magic 270 cmp.d CRAMFS_MAGIC, $r0 271 bne _no_romfs_in_flash 272 nop 273 274 ;; found cramfs in flash. set address and size, and romfs_in_flash flag. 275 addoq +4, $r9, $acr 276 move.d [$acr], $r0 277 move.d romfs_length, $r1 278 move.d $r0, [$r1] 279 add.d 0xf0000000, $r9 ; Add cached flash start in virtual memory. 280 move.d romfs_start, $r1 281 move.d $r9, [$r1] 282 moveq 1, $r0 283 move.d romfs_in_flash, $r1 284 move.d $r0, [$r1] 285 286 jump _start_it ; Jump to cached code. 287 nop 288 289_no_romfs_in_flash: 290 ;; No romfs in flash, so look for cramfs, or jffs2 with jhead, 291 ;; after kernel in RAM, as is the case with network->RAM boot. 292 ;; For cramfs, partition starts with magic and length. 293 ;; For jffs2, a jhead is prepended which contains with magic and length. 294 ;; The jhead is not part of the jffs2 partition however. 295 move.d __bss_start, $r0 296 move.d [$r0], $r1 297 cmp.d CRAMFS_MAGIC, $r1 ; cramfs magic? 298 beq 2f ; yes, jump 299 nop 300 cmp.d JHEAD_MAGIC, $r1 ; jffs2 (jhead) magic? 301 bne 4f ; no, skip copy 302 nop 303 addq 4, $r0 ; location of jffs2 size 304 move.d [$r0+], $r2 ; fetch jffs2 size -> r2 305 ; r0 now points to start of jffs2 306 ba 3f 307 nop 3082: 309 addoq +4, $r0, $acr ; location of cramfs size 310 move.d [$acr], $r2 ; fetch cramfs size -> r2 311 ; r0 still points to start of cramfs 3123: 313 ;; Now, move the root fs to after kernel's BSS 314 315 move.d _end, $r1 ; start of cramfs -> r1 316 move.d romfs_start, $r3 317 move.d $r1, [$r3] ; store at romfs_start (for axisflashmap) 318 move.d romfs_length, $r3 319 move.d $r2, [$r3] ; store size at romfs_length 320 321 add.d $r2, $r0 ; copy from end and downwards 322 add.d $r2, $r1 323 324 lsrq 1, $r2 ; Size is in bytes, we copy words. 325 addq 1, $r2 3261: 327 move.w [$r0], $r3 328 move.w $r3, [$r1] 329 subq 2, $r0 330 subq 2, $r1 331 subq 1, $r2 332 bne 1b 333 nop 334 3354: 336 ;; BSS move done. 337 ;; Clear romfs_in_flash flag, as we now know romfs is in DRAM 338 ;; Also clear nand_boot flag; if we got here, we know we've not 339 ;; booted from NAND flash. 340 moveq 0, $r0 341 move.d romfs_in_flash, $r1 342 move.d $r0, [$r1] 343 moveq 0, $r0 344 move.d nand_boot, $r1 345 move.d $r0, [$r1] 346 347 jump _start_it ; Jump to cached code. 348 nop 349 350_start_it: 351 352 ;; Check if kernel command line is supplied 353 cmp.d COMMAND_LINE_MAGIC, $r10 354 bne no_command_line 355 nop 356 357 move.d 256, $r13 358 move.d cris_command_line, $r10 359 or.d 0x80000000, $r11 ; Make it virtual 3601: 361 move.b [$r11+], $r1 362 move.b $r1, [$r10+] 363 subq 1, $r13 364 bne 1b 365 nop 366 367no_command_line: 368 369 ;; The kernel stack contains a task structure for each task. This 370 ;; the initial kernel stack is in the same page as the init_task, 371 ;; but starts at the top of the page, i.e. + 8192 bytes. 372 move.d init_thread_union + 8192, $sp 373 move.d ebp_start, $r0 ; Defined in linker-script. 374 move $r0, $ebp 375 move.d etrax_irv, $r1 ; Set the exception base register and pointer. 376 move.d $r0, [$r1] 377 378 ;; Clear the BSS region from _bss_start to _end. 379 move.d __bss_start, $r0 380 move.d _end, $r1 3811: clear.d [$r0+] 382 cmp.d $r1, $r0 383 blo 1b 384 nop 385 386 ; Initialize registers to increase determinism 387 move.d __bss_start, $r0 388 movem [$r0], $r13 389 390#ifdef CONFIG_ETRAX_L2CACHE 391 jsr l2cache_init 392 nop 393#endif 394 395 jump start_kernel ; Jump to start_kernel() in init/main.c. 396 nop 397 398 .data 399etrax_irv: 400 .dword 0 401 402; Variables for communication with the Axis flash map driver (axisflashmap), 403; and for setting up memory in arch/cris/kernel/setup.c . 404 405; romfs_start is set to the start of the root file system, if it exists 406; in directly accessible memory (i.e. NOR Flash when booting from Flash, 407; or RAM when booting directly from a network-downloaded RAM image) 408romfs_start: 409 .dword 0 410 411; romfs_length is set to the size of the root file system image, if it exists 412; in directly accessible memory (see romfs_start). Otherwise it is set to 0. 413romfs_length: 414 .dword 0 415 416; romfs_in_flash is set to 1 if the root file system resides in directly 417; accessible flash memory (i.e. NOR flash). It is set to 0 for RAM boot 418; or NAND flash boot. 419romfs_in_flash: 420 .dword 0 421 422; nand_boot is set to 1 when the kernel has been booted from NAND flash 423nand_boot: 424 .dword 0 425 426swapper_pg_dir = 0xc0002000 427 428 .section ".init.data", "aw" 429 430#if defined CONFIG_ETRAXFS 431#include "../mach-fs/hw_settings.S" 432#elif defined CONFIG_CRIS_MACH_ARTPEC3 433#include "../mach-a3/hw_settings.S" 434#else 435#error Only ETRAXFS and ARTPEC-3 supported! 436#endif 437