2 * CRISv32 kernel startup code.
4 * Copyright (C) 2003, Axis Communications AB
7 #include <linux/config.h>
9 #define ASSEMBLER_MACROS_ONLY
12 * The macros found in mmu_defs_asm.h uses the ## concatenation operator, so
13 * -traditional must not be used when assembling this file.
15 #include <asm/arch/hwregs/reg_rdwr.h>
16 #include <asm/arch/hwregs/asm/mmu_defs_asm.h>
17 #include <asm/arch/hwregs/asm/reg_map_asm.h>
18 #include <asm/arch/hwregs/asm/config_defs_asm.h>
19 #include <asm/arch/hwregs/asm/bif_core_defs_asm.h>
21 #define CRAMFS_MAGIC 0x28cd3d45
22 #define RAM_INIT_MAGIC 0x56902387
23 #define COMMAND_LINE_MAGIC 0x87109563
25 ;; NOTE: R8 and R9 carry information from the decompressor (if the
26 ;; kernel was compressed). They must not be used in the code below
27 ;; until they are read!
33 .global romfs_in_flash
34 .global swapper_pg_dir
35 .global crisv32_nand_boot
36 .global crisv32_nand_cramfs_offset
38 ;; Dummy section to make it bootable with current VCS simulator
39 #ifdef CONFIG_ETRAXFS_SIM
40 .section ".boot", "ax"
47 ;; This is the entry point of the kernel. The CPU is currently in
50 ;; 0x00000000 if flash.
51 ;; 0x40004000 if DRAM.
55 ;; Start clocks for used blocks.
56 move.d REG_ADDR(config, regi_config, rw_clk_ctrl), $r1
58 or.d REG_STATE(config, rw_clk_ctrl, cpu, yes) | \
59 REG_STATE(config, rw_clk_ctrl, bif, yes) | \
60 REG_STATE(config, rw_clk_ctrl, fix_io, yes), $r0
63 ;; Set up waitstates etc
64 move.d REG_ADDR(bif_core, regi_bif_core, rw_grp1_cfg), $r0
65 move.d CONFIG_ETRAX_MEM_GRP1_CONFIG, $r1
67 move.d REG_ADDR(bif_core, regi_bif_core, rw_grp2_cfg), $r0
68 move.d CONFIG_ETRAX_MEM_GRP2_CONFIG, $r1
70 move.d REG_ADDR(bif_core, regi_bif_core, rw_grp3_cfg), $r0
71 move.d CONFIG_ETRAX_MEM_GRP3_CONFIG, $r1
73 move.d REG_ADDR(bif_core, regi_bif_core, rw_grp4_cfg), $r0
74 move.d CONFIG_ETRAX_MEM_GRP4_CONFIG, $r1
77 #ifdef CONFIG_ETRAXFS_SIM
78 ;; Set up minimal flash waitstates
80 move.d REG_ADDR(bif_core, regi_bif_core, rw_grp1_cfg), $r11
84 ;; Setup and enable the MMU. Use same configuration for both the data
85 ;; and the instruction MMU.
87 ;; Note; 3 cycles is needed for a bank-select to take effect. Further;
88 ;; bank 1 is the instruction MMU, bank 2 is the data MMU.
89 #ifndef CONFIG_ETRAXFS_SIM
90 move.d REG_FIELD(mmu, rw_mm_kbase_hi, base_e, 8) \
91 | REG_FIELD(mmu, rw_mm_kbase_hi, base_c, 4) \
92 | REG_FIELD(mmu, rw_mm_kbase_hi, base_b, 0xb), $r0
94 ;; Map the virtual DRAM to the RW eprom area at address 0.
95 ;; Also map 0xa for the hook calls,
96 move.d REG_FIELD(mmu, rw_mm_kbase_hi, base_e, 8) \
97 | REG_FIELD(mmu, rw_mm_kbase_hi, base_c, 0) \
98 | REG_FIELD(mmu, rw_mm_kbase_hi, base_b, 0xb) \
99 | REG_FIELD(mmu, rw_mm_kbase_hi, base_a, 0xa), $r0
102 ;; Temporary map of 0x40 -> 0x40 and 0x00 -> 0x00.
103 move.d REG_FIELD(mmu, rw_mm_kbase_lo, base_4, 4) \
104 | REG_FIELD(mmu, rw_mm_kbase_lo, base_0, 0), $r1
106 ;; Enable certain page protections and setup linear mapping
108 #ifndef CONFIG_ETRAXFS_SIM
109 move.d REG_STATE(mmu, rw_mm_cfg, we, on) \
110 | REG_STATE(mmu, rw_mm_cfg, acc, on) \
111 | REG_STATE(mmu, rw_mm_cfg, ex, on) \
112 | REG_STATE(mmu, rw_mm_cfg, inv, on) \
113 | REG_STATE(mmu, rw_mm_cfg, seg_f, linear) \
114 | REG_STATE(mmu, rw_mm_cfg, seg_e, linear) \
115 | REG_STATE(mmu, rw_mm_cfg, seg_d, page) \
116 | REG_STATE(mmu, rw_mm_cfg, seg_c, linear) \
117 | REG_STATE(mmu, rw_mm_cfg, seg_b, linear) \
118 | REG_STATE(mmu, rw_mm_cfg, seg_a, page) \
119 | REG_STATE(mmu, rw_mm_cfg, seg_9, page) \
120 | REG_STATE(mmu, rw_mm_cfg, seg_8, page) \
121 | REG_STATE(mmu, rw_mm_cfg, seg_7, page) \
122 | REG_STATE(mmu, rw_mm_cfg, seg_6, page) \
123 | REG_STATE(mmu, rw_mm_cfg, seg_5, page) \
124 | REG_STATE(mmu, rw_mm_cfg, seg_4, linear) \
125 | REG_STATE(mmu, rw_mm_cfg, seg_3, page) \
126 | REG_STATE(mmu, rw_mm_cfg, seg_2, page) \
127 | REG_STATE(mmu, rw_mm_cfg, seg_1, page) \
128 | REG_STATE(mmu, rw_mm_cfg, seg_0, linear), $r2
130 move.d REG_STATE(mmu, rw_mm_cfg, we, on) \
131 | REG_STATE(mmu, rw_mm_cfg, acc, on) \
132 | REG_STATE(mmu, rw_mm_cfg, ex, on) \
133 | REG_STATE(mmu, rw_mm_cfg, inv, on) \
134 | REG_STATE(mmu, rw_mm_cfg, seg_f, linear) \
135 | REG_STATE(mmu, rw_mm_cfg, seg_e, linear) \
136 | REG_STATE(mmu, rw_mm_cfg, seg_d, page) \
137 | REG_STATE(mmu, rw_mm_cfg, seg_c, linear) \
138 | REG_STATE(mmu, rw_mm_cfg, seg_b, linear) \
139 | REG_STATE(mmu, rw_mm_cfg, seg_a, linear) \
140 | REG_STATE(mmu, rw_mm_cfg, seg_9, page) \
141 | REG_STATE(mmu, rw_mm_cfg, seg_8, page) \
142 | REG_STATE(mmu, rw_mm_cfg, seg_7, page) \
143 | REG_STATE(mmu, rw_mm_cfg, seg_6, page) \
144 | REG_STATE(mmu, rw_mm_cfg, seg_5, page) \
145 | REG_STATE(mmu, rw_mm_cfg, seg_4, linear) \
146 | REG_STATE(mmu, rw_mm_cfg, seg_3, page) \
147 | REG_STATE(mmu, rw_mm_cfg, seg_2, page) \
148 | REG_STATE(mmu, rw_mm_cfg, seg_1, page) \
149 | REG_STATE(mmu, rw_mm_cfg, seg_0, linear), $r2
152 ;; Update instruction MMU.
157 move $r0, $s2 ; kbase_hi.
158 move $r1, $s1 ; kbase_lo.
159 move $r2, $s0 ; mm_cfg, virtual memory configuration.
166 move $r0, $s2 ; kbase_hi.
167 move $r1, $s1 ; kbase_lo
168 move $r2, $s0 ; mm_cfg, virtual memory configuration.
170 ;; Enable data and instruction MMU.
172 moveq 0xf, $r0 ; IMMU, DMMU, DCache, Icache on
192 ; A slave waits for cpu_now_booting to be equal to CPU ID.
193 move.d cpu_now_booting, $r1
198 ; Time to boot-up. Get stack location provided by master CPU.
199 move.d smp_init_current_idle_thread, $r1
202 move.d ebp_start, $r0 ; Defined in linker-script.
208 #ifndef CONFIG_ETRAXFS_SIM
209 ;; Check if starting from DRAM or flash.
211 and.d 0x7fffffff, $r0 ; Mask off the non-cache bit.
212 cmp.d 0x10000, $r0 ; Arbitrary, something above this code.
217 jump _inram ; Jump to cached RAM.
225 ;; Put the following in a section so that storage for it can be
226 ;; reclaimed after init is finished.
227 .section ".init.text", "ax"
232 cmp.d RAM_INIT_MAGIC, $r8 ; Already initialized?
233 beq _dram_initialized
236 #include "../lib/dram_init.S"
239 ;; Copy the text and data section to DRAM. This depends on that the
240 ;; variables used below are correctly set up by the linker script.
241 ;; The calculated value stored in R4 is used below.
242 moveq 0, $r0 ; Source.
243 move.d text_start, $r1 ; Destination.
244 move.d __vmlinux_end, $r2
247 1: move.w [$r0+], $r3
253 ;; Keep CRAMFS in flash.
255 move.d romfs_length, $r1
257 move.d [$r4], $r0 ; cramfs_super.magic
258 cmp.d CRAMFS_MAGIC, $r0
264 move.d romfs_length, $r1
266 add.d 0xf0000000, $r4 ; Add cached flash start in virtual memory.
267 move.d romfs_start, $r1
270 move.d romfs_in_flash, $r1
273 jump _start_it ; Jump to cached code.
277 ;; Check if booting from NAND flash (in that case we just remember the offset
278 ;; into the flash where cramfs should be).
279 move.d REG_ADDR(config, regi_config, r_bootsel), $r0
281 and.d REG_MASK(config, r_bootsel, boot_mode), $r0
282 cmp.d REG_STATE(config, r_bootsel, boot_mode, nand), $r0
285 move.d crisv32_nand_boot, $r1
287 move.d crisv32_nand_cramfs_offset, $r1
290 move.d romfs_in_flash, $r1
296 ;; Move the cramfs after BSS.
298 move.d romfs_length, $r1
301 #ifndef CONFIG_ETRAXFS_SIM
302 ;; The kernel could have been unpacked to DRAM by the loader, but
303 ;; the cramfs image could still be inte the flash immediately
304 ;; following the compressed kernel image. The loaded passes the address
305 ;; of the bute succeeding the last compressed byte in the flash in
306 ;; register R9 when starting the kernel.
307 cmp.d 0x0ffffff8, $r9
308 bhs _no_romfs_in_flash ; R9 points outside the flash area.
311 ba _no_romfs_in_flash
314 move.d [$r9], $r0 ; cramfs_super.magic
315 cmp.d CRAMFS_MAGIC, $r0
316 bne _no_romfs_in_flash
321 move.d romfs_length, $r1
323 add.d 0xf0000000, $r9 ; Add cached flash start in virtual memory.
324 move.d romfs_start, $r1
327 move.d romfs_in_flash, $r1
330 jump _start_it ; Jump to cached code.
335 #ifndef CONFIG_ETRAXFS_SIM
336 move.d __vmlinux_end, $r0
341 cmp.d CRAMFS_MAGIC, $r1
348 move.d romfs_start, $r3
350 move.d romfs_length, $r3
353 #ifndef CONFIG_ETRAXFS_SIM
357 lsrq 1, $r2 ; Size is in bytes, we copy words.
371 move.d romfs_in_flash, $r1
374 jump _start_it ; Jump to cached code.
379 ;; Check if kernel command line is supplied
380 cmp.d COMMAND_LINE_MAGIC, $r10
385 move.d cris_command_line, $r10
386 or.d 0x80000000, $r11 ; Make it virtual
396 ;; The kernel stack contains a task structure for each task. This
397 ;; the initial kernel stack is in the same page as the init_task,
398 ;; but starts at the top of the page, i.e. + 8192 bytes.
399 move.d init_thread_union + 8192, $sp
400 move.d ebp_start, $r0 ; Defined in linker-script.
402 move.d etrax_irv, $r1 ; Set the exception base register and pointer.
405 #ifndef CONFIG_ETRAXFS_SIM
406 ;; Clear the BSS region from _bss_start to _end.
407 move.d __bss_start, $r0
415 #ifdef CONFIG_ETRAXFS_SIM
416 /* Set the watchdog timeout to something big. Will be removed when */
417 /* watchdog can be disabled with command line option */
418 move.d 0x7fffffff, $r10
419 jsr CPU_WATCHDOG_TIMEOUT
423 ; Initialize registers to increase determinism
424 move.d __bss_start, $r0
427 jump start_kernel ; Jump to start_kernel() in init/main.c.
441 crisv32_nand_cramfs_offset:
444 swapper_pg_dir = 0xc0002000
446 .section ".init.data", "aw"
448 #include "../lib/hw_settings.S"