1
2
3
4
5
6
7
8#define ASSEMBLER_MACROS_ONLY
9
10
11
12
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
416
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