Back to home page

LXR

 
 

    


0001 /*
0002  * CRISv32 kernel startup code.
0003  *
0004  * Copyright (C) 2003, Axis Communications AB
0005  */
0006 
0007 #include <linux/init.h>
0008 
0009 #define ASSEMBLER_MACROS_ONLY
0010 
0011 /*
0012  * The macros found in mmu_defs_asm.h uses the ## concatenation operator, so
0013  * -traditional must not be used when assembling this file.
0014  */
0015 #include <arch/memmap.h>
0016 #include <hwregs/reg_rdwr.h>
0017 #include <hwregs/intr_vect.h>
0018 #include <hwregs/asm/mmu_defs_asm.h>
0019 #include <hwregs/asm/reg_map_asm.h>
0020 #include <mach/startup.inc>
0021 
0022 #define CRAMFS_MAGIC 0x28cd3d45
0023 #define JHEAD_MAGIC 0x1FF528A6
0024 #define JHEAD_SIZE 8
0025 #define RAM_INIT_MAGIC 0x56902387
0026 #define COMMAND_LINE_MAGIC 0x87109563
0027 #define NAND_BOOT_MAGIC 0x9a9db001
0028 
0029     ;; NOTE: R8 and R9 carry information from the decompressor (if the
0030     ;; kernel was compressed). They must not be used in the code below
0031     ;; until they are read!
0032 
0033     ;; Exported symbols.
0034     .global etrax_irv
0035     .global romfs_start
0036     .global romfs_length
0037     .global romfs_in_flash
0038     .global nand_boot
0039     .global swapper_pg_dir
0040 
0041     __HEAD
0042 tstart:
0043     ;; This is the entry point of the kernel. The CPU is currently in
0044     ;; supervisor mode.
0045     ;;
0046     ;; 0x00000000 if flash.
0047     ;; 0x40004000 if DRAM.
0048     ;;
0049     di
0050 
0051     START_CLOCKS
0052 
0053     SETUP_WAIT_STATES
0054 
0055     GIO_INIT
0056 
0057     ;; Setup and enable the MMU. Use same configuration for both the data
0058     ;; and the instruction MMU.
0059     ;;
0060     ;; Note; 3 cycles is needed for a bank-select to take effect. Further;
0061     ;; bank 1 is the instruction MMU, bank 2 is the data MMU.
0062 
0063 #ifdef CONFIG_CRIS_MACH_ARTPEC3
0064     move.d  REG_FIELD(mmu, rw_mm_kbase_hi, base_e, 8)   \
0065         | REG_FIELD(mmu, rw_mm_kbase_hi, base_c, 4) \
0066         | REG_FIELD(mmu, rw_mm_kbase_hi, base_d, 5)     \
0067         | REG_FIELD(mmu, rw_mm_kbase_hi, base_b, 0xb), $r0
0068 #else
0069     move.d  REG_FIELD(mmu, rw_mm_kbase_hi, base_e, 8)   \
0070         | REG_FIELD(mmu, rw_mm_kbase_hi, base_c, 4) \
0071         | REG_FIELD(mmu, rw_mm_kbase_hi, base_b, 0xb), $r0
0072 #endif
0073 
0074     ;; Temporary map of 0x40 -> 0x40 and 0x00 -> 0x00.
0075     move.d  REG_FIELD(mmu, rw_mm_kbase_lo, base_4, 4)  \
0076         | REG_FIELD(mmu, rw_mm_kbase_lo, base_0, 0), $r1
0077 
0078     ;; Enable certain page protections and setup linear mapping
0079     ;; for f,e,c,b,4,0.
0080 
0081     ;; ARTPEC-3:
0082     ;; c,d used for linear kernel mapping, up to 512 MB
0083     ;; e used for vmalloc
0084     ;; f unused, but page mapped to get page faults
0085 
0086     ;; ETRAX FS:
0087     ;; c used for linear kernel mapping, up to 256 MB
0088     ;; d used for vmalloc
0089     ;; e,f used for memory-mapped NOR flash
0090 
0091 #ifdef CONFIG_CRIS_MACH_ARTPEC3
0092     move.d  REG_STATE(mmu, rw_mm_cfg, we, on)       \
0093         | REG_STATE(mmu, rw_mm_cfg, acc, on)        \
0094         | REG_STATE(mmu, rw_mm_cfg, ex, on)     \
0095         | REG_STATE(mmu, rw_mm_cfg, inv, on)            \
0096         | REG_STATE(mmu, rw_mm_cfg, seg_f, page)    \
0097         | REG_STATE(mmu, rw_mm_cfg, seg_e, page)    \
0098         | REG_STATE(mmu, rw_mm_cfg, seg_d, linear)      \
0099         | REG_STATE(mmu, rw_mm_cfg, seg_c, linear)  \
0100         | REG_STATE(mmu, rw_mm_cfg, seg_b, linear)  \
0101         | REG_STATE(mmu, rw_mm_cfg, seg_a, page)    \
0102         | REG_STATE(mmu, rw_mm_cfg, seg_9, page)    \
0103         | REG_STATE(mmu, rw_mm_cfg, seg_8, page)    \
0104         | REG_STATE(mmu, rw_mm_cfg, seg_7, page)    \
0105         | REG_STATE(mmu, rw_mm_cfg, seg_6, page)    \
0106         | REG_STATE(mmu, rw_mm_cfg, seg_5, page)    \
0107         | REG_STATE(mmu, rw_mm_cfg, seg_4, linear)  \
0108         | REG_STATE(mmu, rw_mm_cfg, seg_3, page)    \
0109         | REG_STATE(mmu, rw_mm_cfg, seg_2, page)    \
0110         | REG_STATE(mmu, rw_mm_cfg, seg_1, page)    \
0111         | REG_STATE(mmu, rw_mm_cfg, seg_0, linear), $r2
0112 #else
0113     move.d  REG_STATE(mmu, rw_mm_cfg, we, on)       \
0114         | REG_STATE(mmu, rw_mm_cfg, acc, on)        \
0115         | REG_STATE(mmu, rw_mm_cfg, ex, on)     \
0116         | REG_STATE(mmu, rw_mm_cfg, inv, on)        \
0117         | REG_STATE(mmu, rw_mm_cfg, seg_f, linear)  \
0118         | REG_STATE(mmu, rw_mm_cfg, seg_e, linear)  \
0119         | REG_STATE(mmu, rw_mm_cfg, seg_d, page)    \
0120         | REG_STATE(mmu, rw_mm_cfg, seg_c, linear)  \
0121         | REG_STATE(mmu, rw_mm_cfg, seg_b, linear)  \
0122         | REG_STATE(mmu, rw_mm_cfg, seg_a, page)    \
0123         | REG_STATE(mmu, rw_mm_cfg, seg_9, page)    \
0124         | REG_STATE(mmu, rw_mm_cfg, seg_8, page)    \
0125         | REG_STATE(mmu, rw_mm_cfg, seg_7, page)    \
0126         | REG_STATE(mmu, rw_mm_cfg, seg_6, page)    \
0127         | REG_STATE(mmu, rw_mm_cfg, seg_5, page)    \
0128         | REG_STATE(mmu, rw_mm_cfg, seg_4, linear)  \
0129         | REG_STATE(mmu, rw_mm_cfg, seg_3, page)    \
0130         | REG_STATE(mmu, rw_mm_cfg, seg_2, page)    \
0131         | REG_STATE(mmu, rw_mm_cfg, seg_1, page)    \
0132         | REG_STATE(mmu, rw_mm_cfg, seg_0, linear), $r2
0133 #endif
0134 
0135     ;; Update instruction MMU.
0136     move    1, $srs
0137     nop
0138     nop
0139     nop
0140     move    $r0, $s2    ; kbase_hi.
0141     move    $r1, $s1    ; kbase_lo.
0142     move    $r2, $s0    ; mm_cfg, virtual memory configuration.
0143 
0144     ;; Update data MMU.
0145     move    2, $srs
0146     nop
0147     nop
0148     nop
0149     move    $r0, $s2    ; kbase_hi.
0150     move    $r1, $s1    ; kbase_lo
0151     move    $r2, $s0    ; mm_cfg, virtual memory configuration.
0152 
0153     ;; Enable data and instruction MMU.
0154     move    0, $srs
0155     moveq   0xf, $r0    ;  IMMU, DMMU, DCache, Icache on
0156     nop
0157     nop
0158     nop
0159     move    $r0, $s0
0160     nop
0161     nop
0162     nop
0163 
0164     ; Check if starting from DRAM (network->RAM boot or unpacked
0165     ; compressed kernel), or directly from flash.
0166     lapcq   ., $r0
0167     and.d   0x7fffffff, $r0 ; Mask off the non-cache bit.
0168     cmp.d   0x10000, $r0    ; Arbitrary, something above this code.
0169     blo _inflash0
0170     nop
0171 
0172     jump    _inram      ; Jump to cached RAM.
0173     nop
0174 
0175     ;; Jumpgate.
0176 _inflash0:
0177     jump _inflash
0178     nop
0179 
0180     ;; Put the following in a section so that storage for it can be
0181     ;; reclaimed after init is finished.
0182     __INIT
0183 
0184 _inflash:
0185 
0186     ;; Initialize DRAM.
0187     cmp.d   RAM_INIT_MAGIC, $r8 ; Already initialized?
0188     beq _dram_initialized
0189     nop
0190 
0191 #if defined CONFIG_ETRAXFS
0192 #include "../mach-fs/dram_init.S"
0193 #elif defined CONFIG_CRIS_MACH_ARTPEC3
0194 #include "../mach-a3/dram_init.S"
0195 #else
0196 #error Only ETRAXFS and ARTPEC-3 supported!
0197 #endif
0198 
0199 
0200 _dram_initialized:
0201     ;; Copy the text and data section to DRAM. This depends on that the
0202     ;; variables used below are correctly set up by the linker script.
0203     ;; The calculated value stored in R4 is used below.
0204     ;; Leave the cramfs file system (piggybacked after the kernel) in flash.
0205     moveq   0, $r0      ; Source.
0206     move.d  text_start, $r1 ; Destination.
0207     move.d  __vmlinux_end, $r2
0208     move.d  $r2, $r4
0209     sub.d   $r1, $r4
0210 1:  move.w  [$r0+], $r3
0211     move.w  $r3, [$r1+]
0212     cmp.d   $r2, $r1
0213     blo 1b
0214     nop
0215 
0216     ;; Check for cramfs.
0217     moveq   0, $r0
0218     move.d  romfs_length, $r1
0219     move.d  $r0, [$r1]
0220     move.d  [$r4], $r0  ; cramfs_super.magic
0221     cmp.d   CRAMFS_MAGIC, $r0
0222     bne 1f
0223     nop
0224 
0225     ;; Set length and start of cramfs, set romfs_in_flash flag
0226     addoq   +4, $r4, $acr
0227     move.d  [$acr], $r0
0228     move.d  romfs_length, $r1
0229     move.d  $r0, [$r1]
0230     add.d   0xf0000000, $r4 ; Add cached flash start in virtual memory.
0231     move.d  romfs_start, $r1
0232     move.d  $r4, [$r1]
0233 1:  moveq   1, $r0
0234     move.d  romfs_in_flash, $r1
0235     move.d  $r0, [$r1]
0236 
0237     jump    _start_it   ; Jump to cached code.
0238     nop
0239 
0240 _inram:
0241     ;; Check if booting from NAND flash; if so, set appropriate flags
0242     ;; and move on.
0243     cmp.d   NAND_BOOT_MAGIC, $r12
0244     bne move_cramfs ; not nand, jump
0245     moveq   1, $r0
0246     move.d  nand_boot, $r1  ; tell axisflashmap we're booting from NAND
0247     move.d  $r0, [$r1]
0248     moveq   0, $r0      ; tell axisflashmap romfs is not in
0249     move.d  romfs_in_flash, $r1 ; (directly accessed) flash
0250     move.d  $r0, [$r1]
0251     jump    _start_it   ; continue with boot
0252     nop
0253 
0254 move_cramfs:
0255     ;; kernel is in DRAM.
0256     ;; Must figure out if there is a piggybacked rootfs image or not.
0257     ;; Set romfs_length to 0 => no rootfs image available by default.
0258     moveq   0, $r0
0259     move.d  romfs_length, $r1
0260     move.d  $r0, [$r1]
0261 
0262     ;; The kernel could have been unpacked to DRAM by the loader, but
0263     ;; the cramfs image could still be in the flash immediately
0264     ;; following the compressed kernel image. The loader passes the address
0265     ;; of the byte succeeding the last compressed byte in the flash in
0266     ;; register R9 when starting the kernel.
0267     cmp.d   0x0ffffff8, $r9
0268     bhs _no_romfs_in_flash ; R9 points outside the flash area.
0269     nop
0270     ;; cramfs rootfs might to be in flash. Check for it.
0271     move.d  [$r9], $r0  ; cramfs_super.magic
0272     cmp.d   CRAMFS_MAGIC, $r0
0273     bne _no_romfs_in_flash
0274     nop
0275 
0276     ;; found cramfs in flash. set address and size, and romfs_in_flash flag.
0277     addoq   +4, $r9, $acr
0278     move.d  [$acr], $r0
0279     move.d  romfs_length, $r1
0280     move.d  $r0, [$r1]
0281     add.d   0xf0000000, $r9 ; Add cached flash start in virtual memory.
0282     move.d  romfs_start, $r1
0283     move.d  $r9, [$r1]
0284     moveq   1, $r0
0285     move.d  romfs_in_flash, $r1
0286     move.d  $r0, [$r1]
0287 
0288     jump    _start_it   ; Jump to cached code.
0289     nop
0290 
0291 _no_romfs_in_flash:
0292     ;; No romfs in flash, so look for cramfs, or jffs2 with jhead,
0293     ;; after kernel in RAM, as is the case with network->RAM boot.
0294     ;; For cramfs, partition starts with magic and length.
0295     ;; For jffs2, a jhead is prepended which contains with magic and length.
0296     ;; The jhead is not part of the jffs2 partition however.
0297     move.d  __bss_start, $r0
0298     move.d  [$r0], $r1
0299     cmp.d   CRAMFS_MAGIC, $r1 ; cramfs magic?
0300     beq 2f        ; yes, jump
0301     nop
0302     cmp.d   JHEAD_MAGIC, $r1 ; jffs2 (jhead) magic?
0303     bne 4f      ; no, skip copy
0304     nop
0305     addq    4, $r0      ; location of jffs2 size
0306     move.d  [$r0+], $r2 ; fetch jffs2 size -> r2
0307                 ; r0 now points to start of jffs2
0308     ba  3f
0309     nop
0310 2:
0311     addoq   +4, $r0, $acr   ; location of cramfs size
0312     move.d  [$acr], $r2 ; fetch cramfs size -> r2
0313                 ; r0 still points to start of cramfs
0314 3:
0315     ;; Now, move the root fs to after kernel's BSS
0316 
0317     move.d  _end, $r1   ; start of cramfs -> r1
0318     move.d  romfs_start, $r3
0319     move.d  $r1, [$r3]  ; store at romfs_start (for axisflashmap)
0320     move.d  romfs_length, $r3
0321     move.d  $r2, [$r3]  ; store size at romfs_length
0322 
0323     add.d   $r2, $r0    ; copy from end and downwards
0324     add.d   $r2, $r1
0325 
0326     lsrq    1, $r2      ; Size is in bytes, we copy words.
0327     addq    1, $r2
0328 1:
0329     move.w  [$r0], $r3
0330     move.w  $r3, [$r1]
0331     subq    2, $r0
0332     subq    2, $r1
0333     subq    1, $r2
0334     bne 1b
0335     nop
0336 
0337 4:
0338     ;; BSS move done.
0339     ;; Clear romfs_in_flash flag, as we now know romfs is in DRAM
0340     ;; Also clear nand_boot flag; if we got here, we know we've not
0341     ;; booted from NAND flash.
0342     moveq   0, $r0
0343     move.d  romfs_in_flash, $r1
0344     move.d  $r0, [$r1]
0345     moveq   0, $r0
0346     move.d  nand_boot, $r1
0347     move.d  $r0, [$r1]
0348 
0349     jump    _start_it   ; Jump to cached code.
0350     nop
0351 
0352 _start_it:
0353 
0354     ;; Check if kernel command line is supplied
0355     cmp.d   COMMAND_LINE_MAGIC, $r10
0356     bne no_command_line
0357     nop
0358 
0359     move.d  256, $r13
0360     move.d  cris_command_line, $r10
0361     or.d    0x80000000, $r11 ; Make it virtual
0362 1:
0363     move.b  [$r11+], $r1
0364     move.b  $r1, [$r10+]
0365     subq    1, $r13
0366     bne 1b
0367     nop
0368 
0369 no_command_line:
0370 
0371     ;; The kernel stack contains a task structure for each task. This
0372     ;; the initial kernel stack is in the same page as the init_task,
0373     ;; but starts at the top of the page, i.e. + 8192 bytes.
0374     move.d  init_thread_union + 8192, $sp
0375     move.d  ebp_start, $r0  ; Defined in linker-script.
0376     move    $r0, $ebp
0377     move.d  etrax_irv, $r1  ; Set the exception base register and pointer.
0378     move.d  $r0, [$r1]
0379 
0380     ;; Clear the BSS region from _bss_start to _end.
0381     move.d  __bss_start, $r0
0382     move.d  _end, $r1
0383 1:  clear.d [$r0+]
0384     cmp.d   $r1, $r0
0385     blo 1b
0386     nop
0387 
0388     ; Initialize registers to increase determinism
0389     move.d __bss_start, $r0
0390     movem [$r0], $r13
0391 
0392 #ifdef CONFIG_ETRAX_L2CACHE
0393     jsr l2cache_init
0394     nop
0395 #endif
0396 
0397     jump    start_kernel    ; Jump to start_kernel() in init/main.c.
0398     nop
0399 
0400     .data
0401 etrax_irv:
0402     .dword 0
0403 
0404 ; Variables for communication with the Axis flash map driver (axisflashmap),
0405 ; and for setting up memory in arch/cris/kernel/setup.c .
0406 
0407 ; romfs_start is set to the start of the root file system, if it exists
0408 ; in directly accessible memory (i.e. NOR Flash when booting from Flash,
0409 ; or RAM when booting directly from a network-downloaded RAM image)
0410 romfs_start:
0411     .dword 0
0412 
0413 ; romfs_length is set to the size of the root file system image, if it exists
0414 ; in directly accessible memory (see romfs_start). Otherwise it is set to 0.
0415 romfs_length:
0416     .dword 0
0417 
0418 ; romfs_in_flash is set to 1 if the root file system resides in directly
0419 ; accessible flash memory (i.e. NOR flash). It is set to 0 for RAM boot
0420 ; or NAND flash boot.
0421 romfs_in_flash:
0422     .dword 0
0423 
0424 ; nand_boot is set to 1 when the kernel has been booted from NAND flash
0425 nand_boot:
0426     .dword 0
0427 
0428 swapper_pg_dir = 0xc0002000
0429 
0430     .section ".init.data", "aw"
0431 
0432 #if defined CONFIG_ETRAXFS
0433 #include "../mach-fs/hw_settings.S"
0434 #elif defined CONFIG_CRIS_MACH_ARTPEC3
0435 #include "../mach-a3/hw_settings.S"
0436 #else
0437 #error Only ETRAXFS and ARTPEC-3 supported!
0438 #endif