2 * CRISv32 kernel startup code.
4 * Copyright (C) 2003, Axis Communications AB
8 #define ASSEMBLER_MACROS_ONLY
11 * The macros found in mmu_defs_asm.h uses the ## concatenation operator, so
12 * -traditional must not be used when assembling this file.
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>
20 #define CRAMFS_MAGIC 0x28cd3d45
21 #define RAM_INIT_MAGIC 0x56902387
22 #define COMMAND_LINE_MAGIC 0x87109563
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!
32 .global romfs_in_flash
33 .global swapper_pg_dir
34 .global crisv32_nand_boot
35 .global crisv32_nand_cramfs_offset
37 ;; Dummy section to make it bootable with current VCS simulator
38 #ifdef CONFIG_ETRAXFS_SIM
39 .section ".boot", "ax"
46 ;; This is the entry point of the kernel. The CPU is currently in
49 ;; 0x00000000 if flash.
50 ;; 0x40004000 if DRAM.
54 ;; Start clocks for used blocks.
55 move.d REG_ADDR(config, regi_config, rw_clk_ctrl), $r1
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
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
66 move.d REG_ADDR(bif_core, regi_bif_core, rw_grp2_cfg), $r0
67 move.d CONFIG_ETRAX_MEM_GRP2_CONFIG, $r1
69 move.d REG_ADDR(bif_core, regi_bif_core, rw_grp3_cfg), $r0
70 move.d CONFIG_ETRAX_MEM_GRP3_CONFIG, $r1
72 move.d REG_ADDR(bif_core, regi_bif_core, rw_grp4_cfg), $r0
73 move.d CONFIG_ETRAX_MEM_GRP4_CONFIG, $r1
76 #ifdef CONFIG_ETRAXFS_SIM
77 ;; Set up minimal flash waitstates
79 move.d REG_ADDR(bif_core, regi_bif_core, rw_grp1_cfg), $r11
83 ;; Setup and enable the MMU. Use same configuration for both the data
84 ;; and the instruction MMU.
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
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
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
105 ;; Enable certain page protections and setup linear mapping
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
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
151 ;; Update instruction MMU.
156 move $r0, $s2 ; kbase_hi.
157 move $r1, $s1 ; kbase_lo.
158 move $r2, $s0 ; mm_cfg, virtual memory configuration.
165 move $r0, $s2 ; kbase_hi.
166 move $r1, $s1 ; kbase_lo
167 move $r2, $s0 ; mm_cfg, virtual memory configuration.
169 ;; Enable data and instruction MMU.
171 moveq 0xf, $r0 ; IMMU, DMMU, DCache, Icache on
191 ; A slave waits for cpu_now_booting to be equal to CPU ID.
192 move.d cpu_now_booting, $r1
197 ; Time to boot-up. Get stack location provided by master CPU.
198 move.d smp_init_current_idle_thread, $r1
201 move.d ebp_start, $r0 ; Defined in linker-script.
207 #ifndef CONFIG_ETRAXFS_SIM
208 ;; Check if starting from DRAM or flash.
210 and.d 0x7fffffff, $r0 ; Mask off the non-cache bit.
211 cmp.d 0x10000, $r0 ; Arbitrary, something above this code.
216 jump _inram ; Jump to cached RAM.
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"
231 cmp.d RAM_INIT_MAGIC, $r8 ; Already initialized?
232 beq _dram_initialized
235 #include "../lib/dram_init.S"
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
246 1: move.w [$r0+], $r3
252 ;; Keep CRAMFS in flash.
254 move.d romfs_length, $r1
256 move.d [$r4], $r0 ; cramfs_super.magic
257 cmp.d CRAMFS_MAGIC, $r0
263 move.d romfs_length, $r1
265 add.d 0xf0000000, $r4 ; Add cached flash start in virtual memory.
266 move.d romfs_start, $r1
269 move.d romfs_in_flash, $r1
272 jump _start_it ; Jump to cached code.
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
280 and.d REG_MASK(config, r_bootsel, boot_mode), $r0
281 cmp.d REG_STATE(config, r_bootsel, boot_mode, nand), $r0
284 move.d crisv32_nand_boot, $r1
286 move.d crisv32_nand_cramfs_offset, $r1
289 move.d romfs_in_flash, $r1
295 ;; Move the cramfs after BSS.
297 move.d romfs_length, $r1
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.
310 ba _no_romfs_in_flash
313 move.d [$r9], $r0 ; cramfs_super.magic
314 cmp.d CRAMFS_MAGIC, $r0
315 bne _no_romfs_in_flash
320 move.d romfs_length, $r1
322 add.d 0xf0000000, $r9 ; Add cached flash start in virtual memory.
323 move.d romfs_start, $r1
326 move.d romfs_in_flash, $r1
329 jump _start_it ; Jump to cached code.
334 #ifndef CONFIG_ETRAXFS_SIM
335 move.d __vmlinux_end, $r0
340 cmp.d CRAMFS_MAGIC, $r1
347 move.d romfs_start, $r3
349 move.d romfs_length, $r3
352 #ifndef CONFIG_ETRAXFS_SIM
356 lsrq 1, $r2 ; Size is in bytes, we copy words.
370 move.d romfs_in_flash, $r1
373 jump _start_it ; Jump to cached code.
378 ;; Check if kernel command line is supplied
379 cmp.d COMMAND_LINE_MAGIC, $r10
384 move.d cris_command_line, $r10
385 or.d 0x80000000, $r11 ; Make it virtual
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.
401 move.d etrax_irv, $r1 ; Set the exception base register and pointer.
404 #ifndef CONFIG_ETRAXFS_SIM
405 ;; Clear the BSS region from _bss_start to _end.
406 move.d __bss_start, $r0
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
422 ; Initialize registers to increase determinism
423 move.d __bss_start, $r0
426 jump start_kernel ; Jump to start_kernel() in init/main.c.
440 crisv32_nand_cramfs_offset:
443 swapper_pg_dir = 0xc0002000
445 .section ".init.data", "aw"
447 #include "../lib/hw_settings.S"