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
   8#define ASSEMBLER_MACROS_ONLY
   9
  10/*
  11 * The macros found in mmu_defs_asm.h uses the ## concatenation operator, so
  12 * -traditional must not be used when assembling this file.
  13 */
  14#include <asm/arch/hwregs/reg_rdwr.h>
  15#include <asm/arch/hwregs/asm/mmu_defs_asm.h>
  16#include <asm/arch/hwregs/asm/reg_map_asm.h>
  17#include <asm/arch/hwregs/asm/config_defs_asm.h>
  18#include <asm/arch/hwregs/asm/bif_core_defs_asm.h>
  19
  20#define CRAMFS_MAGIC 0x28cd3d45
  21#define RAM_INIT_MAGIC 0x56902387
  22#define COMMAND_LINE_MAGIC 0x87109563
  23
  24        ;; NOTE: R8 and R9 carry information from the decompressor (if the
  25        ;; kernel was compressed). They must not be used in the code below
  26        ;; until they are read!
  27
  28        ;; Exported symbols.
  29        .global etrax_irv
  30        .global romfs_start
  31        .global romfs_length
  32        .global romfs_in_flash
  33        .global swapper_pg_dir
  34        .global crisv32_nand_boot
  35        .global crisv32_nand_cramfs_offset
  36
  37        ;; Dummy section to make it bootable with current VCS simulator
  38#ifdef CONFIG_ETRAXFS_SIM
  39        .section ".boot", "ax"
  40        ba tstart
  41        nop
  42#endif
  43
  44        .text
  45tstart:
  46        ;; This is the entry point of the kernel. The CPU is currently in
  47        ;; supervisor mode.
  48        ;;
  49        ;; 0x00000000 if flash.
  50        ;; 0x40004000 if DRAM.
  51        ;;
  52        di
  53
  54        ;; Start clocks for used blocks.
  55        move.d REG_ADDR(config, regi_config, rw_clk_ctrl), $r1
  56        move.d [$r1], $r0
  57        or.d   REG_STATE(config, rw_clk_ctrl, cpu, yes) | \
  58               REG_STATE(config, rw_clk_ctrl, bif, yes) | \
  59               REG_STATE(config, rw_clk_ctrl, fix_io, yes), $r0
  60        move.d $r0, [$r1]
  61
  62        ;; Set up waitstates etc
  63        move.d   REG_ADDR(bif_core, regi_bif_core, rw_grp1_cfg), $r0
  64        move.d   CONFIG_ETRAX_MEM_GRP1_CONFIG, $r1
  65        move.d   $r1, [$r0]
  66        move.d   REG_ADDR(bif_core, regi_bif_core, rw_grp2_cfg), $r0
  67        move.d   CONFIG_ETRAX_MEM_GRP2_CONFIG, $r1
  68        move.d   $r1, [$r0]
  69        move.d   REG_ADDR(bif_core, regi_bif_core, rw_grp3_cfg), $r0
  70        move.d   CONFIG_ETRAX_MEM_GRP3_CONFIG, $r1
  71        move.d   $r1, [$r0]
  72        move.d   REG_ADDR(bif_core, regi_bif_core, rw_grp4_cfg), $r0
  73        move.d   CONFIG_ETRAX_MEM_GRP4_CONFIG, $r1
  74        move.d   $r1, [$r0]
  75
  76#ifdef CONFIG_ETRAXFS_SIM
  77        ;; Set up minimal flash waitstates
  78        move.d 0, $r10
  79        move.d REG_ADDR(bif_core, regi_bif_core, rw_grp1_cfg), $r11
  80        move.d $r10, [$r11]
  81#endif
  82
  83        ;; Setup and enable the MMU. Use same configuration for both the data
  84        ;; and the instruction MMU.
  85        ;;
  86        ;; Note; 3 cycles is needed for a bank-select to take effect. Further;
  87        ;; bank 1 is the instruction MMU, bank 2 is the data MMU.
  88#ifndef CONFIG_ETRAXFS_SIM
  89        move.d  REG_FIELD(mmu, rw_mm_kbase_hi, base_e, 8)       \
  90                | REG_FIELD(mmu, rw_mm_kbase_hi, base_c, 4)     \
  91                | REG_FIELD(mmu, rw_mm_kbase_hi, base_b, 0xb), $r0
  92#else
  93        ;; Map the virtual DRAM to the RW eprom area at address 0.
  94        ;; Also map 0xa for the hook calls,
  95        move.d  REG_FIELD(mmu, rw_mm_kbase_hi, base_e, 8)       \
  96                | REG_FIELD(mmu, rw_mm_kbase_hi, base_c, 0)     \
  97                | REG_FIELD(mmu, rw_mm_kbase_hi, base_b, 0xb)   \
  98                | REG_FIELD(mmu, rw_mm_kbase_hi, base_a, 0xa), $r0
  99#endif
 100
 101        ;; Temporary map of 0x40 -> 0x40 and 0x00 -> 0x00.
 102        move.d  REG_FIELD(mmu, rw_mm_kbase_lo, base_4, 4)  \
 103                | REG_FIELD(mmu, rw_mm_kbase_lo, base_0, 0), $r1
 104
 105        ;; Enable certain page protections and setup linear mapping
 106        ;; for f,e,c,b,4,0.
 107#ifndef CONFIG_ETRAXFS_SIM
 108        move.d  REG_STATE(mmu, rw_mm_cfg, we, on)               \
 109                | REG_STATE(mmu, rw_mm_cfg, acc, on)            \
 110                | REG_STATE(mmu, rw_mm_cfg, ex, on)             \
 111                | REG_STATE(mmu, rw_mm_cfg, inv, on)            \
 112                | REG_STATE(mmu, rw_mm_cfg, seg_f, linear)      \
 113                | REG_STATE(mmu, rw_mm_cfg, seg_e, linear)      \
 114                | REG_STATE(mmu, rw_mm_cfg, seg_d, page)        \
 115                | REG_STATE(mmu, rw_mm_cfg, seg_c, linear)      \
 116                | REG_STATE(mmu, rw_mm_cfg, seg_b, linear)      \
 117                | REG_STATE(mmu, rw_mm_cfg, seg_a, page)        \
 118                | REG_STATE(mmu, rw_mm_cfg, seg_9, page)        \
 119                | REG_STATE(mmu, rw_mm_cfg, seg_8, page)        \
 120                | REG_STATE(mmu, rw_mm_cfg, seg_7, page)        \
 121                | REG_STATE(mmu, rw_mm_cfg, seg_6, page)        \
 122                | REG_STATE(mmu, rw_mm_cfg, seg_5, page)        \
 123                | REG_STATE(mmu, rw_mm_cfg, seg_4, linear)      \
 124                | REG_STATE(mmu, rw_mm_cfg, seg_3, page)        \
 125                | REG_STATE(mmu, rw_mm_cfg, seg_2, page)        \
 126                | REG_STATE(mmu, rw_mm_cfg, seg_1, page)        \
 127                | REG_STATE(mmu, rw_mm_cfg, seg_0, linear), $r2
 128#else
 129        move.d  REG_STATE(mmu, rw_mm_cfg, we, on)               \
 130                | REG_STATE(mmu, rw_mm_cfg, acc, on)            \
 131                | REG_STATE(mmu, rw_mm_cfg, ex, on)             \
 132                | REG_STATE(mmu, rw_mm_cfg, inv, on)            \
 133                | REG_STATE(mmu, rw_mm_cfg, seg_f, linear)      \
 134                | REG_STATE(mmu, rw_mm_cfg, seg_e, linear)      \
 135                | REG_STATE(mmu, rw_mm_cfg, seg_d, page)        \
 136                | REG_STATE(mmu, rw_mm_cfg, seg_c, linear)      \
 137                | REG_STATE(mmu, rw_mm_cfg, seg_b, linear)      \
 138                | REG_STATE(mmu, rw_mm_cfg, seg_a, linear)      \
 139                | REG_STATE(mmu, rw_mm_cfg, seg_9, page)        \
 140                | REG_STATE(mmu, rw_mm_cfg, seg_8, page)        \
 141                | REG_STATE(mmu, rw_mm_cfg, seg_7, page)        \
 142                | REG_STATE(mmu, rw_mm_cfg, seg_6, page)        \
 143                | REG_STATE(mmu, rw_mm_cfg, seg_5, page)        \
 144                | REG_STATE(mmu, rw_mm_cfg, seg_4, linear)      \
 145                | REG_STATE(mmu, rw_mm_cfg, seg_3, page)        \
 146                | REG_STATE(mmu, rw_mm_cfg, seg_2, page)        \
 147                | REG_STATE(mmu, rw_mm_cfg, seg_1, page)        \
 148                | REG_STATE(mmu, rw_mm_cfg, seg_0, linear), $r2
 149#endif
 150
 151        ;; Update instruction MMU.
 152        move    1, $srs
 153        nop
 154        nop
 155        nop
 156        move    $r0, $s2        ; kbase_hi.
 157        move    $r1, $s1        ; kbase_lo.
 158        move    $r2, $s0        ; mm_cfg, virtual memory configuration.
 159
 160        ;; Update data MMU.
 161        move    2, $srs
 162        nop
 163        nop
 164        nop
 165        move    $r0, $s2        ; kbase_hi.
 166        move    $r1, $s1        ; kbase_lo
 167        move    $r2, $s0        ; mm_cfg, virtual memory configuration.
 168
 169        ;; Enable data and instruction MMU.
 170        move    0, $srs
 171        moveq   0xf, $r0        ;  IMMU, DMMU, DCache, Icache on
 172        nop
 173        nop
 174        nop
 175        move    $r0, $s0
 176        nop
 177        nop
 178        nop
 179
 180#ifdef CONFIG_SMP
 181        ;; Read CPU ID
 182        move    0, $srs
 183        nop
 184        nop
 185        nop
 186        move    $s10, $r0
 187        cmpq    0, $r0
 188        beq     master_cpu
 189        nop
 190slave_cpu:
 191        ; A slave waits for cpu_now_booting to be equal to CPU ID.
 192        move.d  cpu_now_booting, $r1
 193slave_wait:
 194        cmp.d   [$r1], $r0
 195        bne     slave_wait
 196        nop
 197        ; Time to boot-up. Get stack location provided by master CPU.
 198        move.d  smp_init_current_idle_thread, $r1
 199        move.d  [$r1], $sp
 200        add.d   8192, $sp
 201        move.d  ebp_start, $r0  ; Defined in linker-script.
 202        move    $r0, $ebp
 203        jsr     smp_callin
 204        nop
 205master_cpu:
 206#endif
 207#ifndef CONFIG_ETRAXFS_SIM
 208        ;; Check if starting from DRAM or flash.
 209        lapcq   ., $r0
 210        and.d   0x7fffffff, $r0 ; Mask off the non-cache bit.
 211        cmp.d   0x10000, $r0    ; Arbitrary, something above this code.
 212        blo     _inflash0
 213        nop
 214#endif
 215
 216        jump    _inram          ; Jump to cached RAM.
 217        nop
 218
 219        ;; Jumpgate.
 220_inflash0:
 221        jump _inflash
 222        nop
 223
 224        ;; Put the following in a section so that storage for it can be
 225        ;; reclaimed after init is finished.
 226        .section ".init.text", "ax"
 227
 228_inflash:
 229
 230        ;; Initialize DRAM.
 231        cmp.d   RAM_INIT_MAGIC, $r8 ; Already initialized?
 232        beq     _dram_initialized
 233        nop
 234
 235#include "../lib/dram_init.S"
 236
 237_dram_initialized:
 238        ;; Copy the text and data section to DRAM. This depends on that the
 239        ;; variables used below are correctly set up by the linker script.
 240        ;; The calculated value stored in R4 is used below.
 241        moveq   0, $r0          ; Source.
 242        move.d  text_start, $r1 ; Destination.
 243        move.d  __vmlinux_end, $r2
 244        move.d  $r2, $r4
 245        sub.d   $r1, $r4
 2461:      move.w  [$r0+], $r3
 247        move.w  $r3, [$r1+]
 248        cmp.d   $r2, $r1
 249        blo     1b
 250        nop
 251
 252        ;; Keep CRAMFS in flash.
 253        moveq   0, $r0
 254        move.d  romfs_length, $r1
 255        move.d  $r0, [$r1]
 256        move.d  [$r4], $r0      ; cramfs_super.magic
 257        cmp.d   CRAMFS_MAGIC, $r0
 258        bne 1f
 259        nop
 260
 261        addoq   +4, $r4, $acr
 262        move.d  [$acr], $r0
 263        move.d  romfs_length, $r1
 264        move.d  $r0, [$r1]
 265        add.d   0xf0000000, $r4 ; Add cached flash start in virtual memory.
 266        move.d  romfs_start, $r1
 267        move.d  $r4, [$r1]
 2681:      moveq   1, $r0
 269        move.d  romfs_in_flash, $r1
 270        move.d  $r0, [$r1]
 271
 272        jump    _start_it       ; Jump to cached code.
 273        nop
 274
 275_inram:
 276        ;; Check if booting from NAND flash (in that case we just remember the offset
 277        ;; into the flash where cramfs should be).
 278        move.d  REG_ADDR(config, regi_config, r_bootsel), $r0
 279        move.d  [$r0], $r0
 280        and.d   REG_MASK(config, r_bootsel, boot_mode), $r0
 281        cmp.d   REG_STATE(config, r_bootsel, boot_mode, nand), $r0
 282        bne     move_cramfs
 283        moveq   1,$r0
 284        move.d  crisv32_nand_boot, $r1
 285        move.d  $r0, [$r1]
 286        move.d  crisv32_nand_cramfs_offset, $r1
 287        move.d  $r9, [$r1]
 288        moveq   1, $r0
 289        move.d  romfs_in_flash, $r1
 290        move.d  $r0, [$r1]
 291        jump    _start_it
 292        nop
 293
 294move_cramfs:
 295        ;; Move the cramfs after BSS.
 296        moveq   0, $r0
 297        move.d  romfs_length, $r1
 298        move.d  $r0, [$r1]
 299
 300#ifndef CONFIG_ETRAXFS_SIM
 301        ;; The kernel could have been unpacked to DRAM by the loader, but
 302        ;; the cramfs image could still be inte the flash immediately
 303        ;; following the compressed kernel image. The loaded passes the address
 304        ;; of the bute succeeding the last compressed byte in the flash in
 305        ;; register R9 when starting the kernel.
 306        cmp.d   0x0ffffff8, $r9
 307        bhs     _no_romfs_in_flash ; R9 points outside the flash area.
 308        nop
 309#else
 310        ba _no_romfs_in_flash
 311        nop
 312#endif
 313        move.d  [$r9], $r0      ; cramfs_super.magic
 314        cmp.d   CRAMFS_MAGIC, $r0
 315        bne     _no_romfs_in_flash
 316        nop
 317
 318        addoq   +4, $r9, $acr
 319        move.d  [$acr], $r0
 320        move.d  romfs_length, $r1
 321        move.d  $r0, [$r1]
 322        add.d   0xf0000000, $r9 ; Add cached flash start in virtual memory.
 323        move.d  romfs_start, $r1
 324        move.d  $r9, [$r1]
 325        moveq   1, $r0
 326        move.d  romfs_in_flash, $r1
 327        move.d  $r0, [$r1]
 328
 329        jump    _start_it       ; Jump to cached code.
 330        nop
 331
 332_no_romfs_in_flash:
 333        ;; Look for cramfs.
 334#ifndef CONFIG_ETRAXFS_SIM
 335        move.d  __vmlinux_end, $r0
 336#else
 337        move.d  __end, $r0
 338#endif
 339        move.d  [$r0], $r1
 340        cmp.d   CRAMFS_MAGIC, $r1
 341        bne     2f
 342        nop
 343
 344        addoq   +4, $r0, $acr
 345        move.d  [$acr], $r2
 346        move.d  _end, $r1
 347        move.d  romfs_start, $r3
 348        move.d  $r1, [$r3]
 349        move.d  romfs_length, $r3
 350        move.d  $r2, [$r3]
 351
 352#ifndef CONFIG_ETRAXFS_SIM
 353        add.d   $r2, $r0
 354        add.d   $r2, $r1
 355
 356        lsrq    1, $r2          ; Size is in bytes, we copy words.
 357        addq    1, $r2
 3581:
 359        move.w  [$r0], $r3
 360        move.w  $r3, [$r1]
 361        subq    2, $r0
 362        subq    2, $r1
 363        subq    1, $r2
 364        bne     1b
 365        nop
 366#endif
 367
 3682:
 369        moveq   0, $r0
 370        move.d  romfs_in_flash, $r1
 371        move.d  $r0, [$r1]
 372
 373        jump    _start_it       ; Jump to cached code.
 374        nop
 375
 376_start_it:
 377
 378        ;; Check if kernel command line is supplied
 379        cmp.d   COMMAND_LINE_MAGIC, $r10
 380        bne     no_command_line
 381        nop
 382
 383        move.d  256, $r13
 384        move.d  cris_command_line, $r10
 385        or.d    0x80000000, $r11 ; Make it virtual
 3861:
 387        move.b  [$r11+], $r12
 388        move.b  $r12, [$r10+]
 389        subq    1, $r13
 390        bne     1b
 391        nop
 392
 393no_command_line:
 394
 395        ;; The kernel stack contains a task structure for each task. This
 396        ;; the initial kernel stack is in the same page as the init_task,
 397        ;; but starts at the top of the page, i.e. + 8192 bytes.
 398        move.d  init_thread_union + 8192, $sp
 399        move.d  ebp_start, $r0  ; Defined in linker-script.
 400        move    $r0, $ebp
 401        move.d  etrax_irv, $r1  ; Set the exception base register and pointer.
 402        move.d  $r0, [$r1]
 403
 404#ifndef CONFIG_ETRAXFS_SIM
 405        ;; Clear the BSS region from _bss_start to _end.
 406        move.d  __bss_start, $r0
 407        move.d  _end, $r1
 4081:      clear.d [$r0+]
 409        cmp.d   $r1, $r0
 410        blo 1b
 411        nop
 412#endif
 413
 414#ifdef CONFIG_ETRAXFS_SIM
 415        /* Set the watchdog timeout to something big. Will be removed when */
 416        /* watchdog can be disabled with command line option */
 417        move.d  0x7fffffff, $r10
 418        jsr     CPU_WATCHDOG_TIMEOUT
 419        nop
 420#endif
 421
 422        ; Initialize registers to increase determinism
 423        move.d __bss_start, $r0
 424        movem [$r0], $r13
 425
 426        jump    start_kernel    ; Jump to start_kernel() in init/main.c.
 427        nop
 428
 429        .data
 430etrax_irv:
 431        .dword 0
 432romfs_start:
 433        .dword 0
 434romfs_length:
 435        .dword 0
 436romfs_in_flash:
 437        .dword 0
 438crisv32_nand_boot:
 439        .dword 0
 440crisv32_nand_cramfs_offset:
 441        .dword 0
 442
 443swapper_pg_dir = 0xc0002000
 444
 445        .section ".init.data", "aw"
 446
 447#include "../lib/hw_settings.S"
 448