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