• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * CRISv32 kernel startup code.
3 *
4 * Copyright (C) 2003, Axis Communications AB
5 */
6
7#define ASSEMBLER_MACROS_ONLY
8
9/*
10 * The macros found in mmu_defs_asm.h uses the ## concatenation operator, so
11 * -traditional must not be used when assembling this file.
12 */
13#include <arch/memmap.h>
14#include <hwregs/reg_rdwr.h>
15#include <hwregs/intr_vect.h>
16#include <hwregs/asm/mmu_defs_asm.h>
17#include <hwregs/asm/reg_map_asm.h>
18#include <mach/startup.inc>
19
20#define CRAMFS_MAGIC 0x28cd3d45
21#define JHEAD_MAGIC 0x1FF528A6
22#define JHEAD_SIZE 8
23#define RAM_INIT_MAGIC 0x56902387
24#define COMMAND_LINE_MAGIC 0x87109563
25#define NAND_BOOT_MAGIC 0x9a9db001
26
27	;; NOTE: R8 and R9 carry information from the decompressor (if the
28	;; kernel was compressed). They must not be used in the code below
29	;; until they are read!
30
31	;; Exported symbols.
32	.global etrax_irv
33	.global romfs_start
34	.global romfs_length
35	.global romfs_in_flash
36	.global nand_boot
37	.global swapper_pg_dir
38
39	.text
40tstart:
41	;; This is the entry point of the kernel. The CPU is currently in
42	;; supervisor mode.
43	;;
44	;; 0x00000000 if flash.
45	;; 0x40004000 if DRAM.
46	;;
47	di
48
49	START_CLOCKS
50
51	SETUP_WAIT_STATES
52
53	GIO_INIT
54
55	;; Setup and enable the MMU. Use same configuration for both the data
56	;; and the instruction MMU.
57	;;
58	;; Note; 3 cycles is needed for a bank-select to take effect. Further;
59	;; bank 1 is the instruction MMU, bank 2 is the data MMU.
60
61#ifdef CONFIG_CRIS_MACH_ARTPEC3
62	move.d	REG_FIELD(mmu, rw_mm_kbase_hi, base_e, 8)	\
63		| REG_FIELD(mmu, rw_mm_kbase_hi, base_c, 4)	\
64		| REG_FIELD(mmu, rw_mm_kbase_hi, base_d, 5)     \
65		| REG_FIELD(mmu, rw_mm_kbase_hi, base_b, 0xb), $r0
66#else
67	move.d	REG_FIELD(mmu, rw_mm_kbase_hi, base_e, 8)	\
68		| REG_FIELD(mmu, rw_mm_kbase_hi, base_c, 4)	\
69		| REG_FIELD(mmu, rw_mm_kbase_hi, base_b, 0xb), $r0
70#endif
71
72	;; Temporary map of 0x40 -> 0x40 and 0x00 -> 0x00.
73	move.d	REG_FIELD(mmu, rw_mm_kbase_lo, base_4, 4)  \
74		| REG_FIELD(mmu, rw_mm_kbase_lo, base_0, 0), $r1
75
76	;; Enable certain page protections and setup linear mapping
77	;; for f,e,c,b,4,0.
78
79	;; ARTPEC-3:
80	;; c,d used for linear kernel mapping, up to 512 MB
81	;; e used for vmalloc
82	;; f unused, but page mapped to get page faults
83
84	;; ETRAX FS:
85	;; c used for linear kernel mapping, up to 256 MB
86	;; d used for vmalloc
87	;; e,f used for memory-mapped NOR flash
88
89#ifdef CONFIG_CRIS_MACH_ARTPEC3
90	move.d	REG_STATE(mmu, rw_mm_cfg, we, on)		\
91		| REG_STATE(mmu, rw_mm_cfg, acc, on)		\
92		| REG_STATE(mmu, rw_mm_cfg, ex, on)		\
93		| REG_STATE(mmu, rw_mm_cfg, inv, on)            \
94		| REG_STATE(mmu, rw_mm_cfg, seg_f, page)	\
95		| REG_STATE(mmu, rw_mm_cfg, seg_e, page)	\
96		| REG_STATE(mmu, rw_mm_cfg, seg_d, linear)      \
97		| REG_STATE(mmu, rw_mm_cfg, seg_c, linear)	\
98		| REG_STATE(mmu, rw_mm_cfg, seg_b, linear)	\
99		| REG_STATE(mmu, rw_mm_cfg, seg_a, page)	\
100		| REG_STATE(mmu, rw_mm_cfg, seg_9, page)	\
101		| REG_STATE(mmu, rw_mm_cfg, seg_8, page)	\
102		| REG_STATE(mmu, rw_mm_cfg, seg_7, page)	\
103		| REG_STATE(mmu, rw_mm_cfg, seg_6, page)	\
104		| REG_STATE(mmu, rw_mm_cfg, seg_5, page)	\
105		| REG_STATE(mmu, rw_mm_cfg, seg_4, linear)	\
106		| REG_STATE(mmu, rw_mm_cfg, seg_3, page)	\
107		| REG_STATE(mmu, rw_mm_cfg, seg_2, page)	\
108		| REG_STATE(mmu, rw_mm_cfg, seg_1, page)	\
109		| REG_STATE(mmu, rw_mm_cfg, seg_0, linear), $r2
110#else
111	move.d	REG_STATE(mmu, rw_mm_cfg, we, on)		\
112		| REG_STATE(mmu, rw_mm_cfg, acc, on)		\
113		| REG_STATE(mmu, rw_mm_cfg, ex, on)		\
114		| REG_STATE(mmu, rw_mm_cfg, inv, on)		\
115		| REG_STATE(mmu, rw_mm_cfg, seg_f, linear)	\
116		| REG_STATE(mmu, rw_mm_cfg, seg_e, linear)	\
117		| REG_STATE(mmu, rw_mm_cfg, seg_d, page)	\
118		| REG_STATE(mmu, rw_mm_cfg, seg_c, linear)	\
119		| REG_STATE(mmu, rw_mm_cfg, seg_b, linear)	\
120		| REG_STATE(mmu, rw_mm_cfg, seg_a, page)	\
121		| REG_STATE(mmu, rw_mm_cfg, seg_9, page)	\
122		| REG_STATE(mmu, rw_mm_cfg, seg_8, page)	\
123		| REG_STATE(mmu, rw_mm_cfg, seg_7, page)	\
124		| REG_STATE(mmu, rw_mm_cfg, seg_6, page)	\
125		| REG_STATE(mmu, rw_mm_cfg, seg_5, page)	\
126		| REG_STATE(mmu, rw_mm_cfg, seg_4, linear)	\
127		| REG_STATE(mmu, rw_mm_cfg, seg_3, page)	\
128		| REG_STATE(mmu, rw_mm_cfg, seg_2, page)	\
129		| REG_STATE(mmu, rw_mm_cfg, seg_1, page)	\
130		| REG_STATE(mmu, rw_mm_cfg, seg_0, linear), $r2
131#endif
132
133	;; Update instruction MMU.
134	move	1, $srs
135	nop
136	nop
137	nop
138	move	$r0, $s2	; kbase_hi.
139	move	$r1, $s1	; kbase_lo.
140	move	$r2, $s0	; mm_cfg, virtual memory configuration.
141
142	;; Update data MMU.
143	move	2, $srs
144	nop
145	nop
146	nop
147	move	$r0, $s2	; kbase_hi.
148	move	$r1, $s1	; kbase_lo
149	move	$r2, $s0	; mm_cfg, virtual memory configuration.
150
151	;; Enable data and instruction MMU.
152	move	0, $srs
153	moveq	0xf, $r0	;  IMMU, DMMU, DCache, Icache on
154	nop
155	nop
156	nop
157	move	$r0, $s0
158	nop
159	nop
160	nop
161
162	; Check if starting from DRAM (network->RAM boot or unpacked
163	; compressed kernel), or directly from flash.
164	lapcq	., $r0
165	and.d	0x7fffffff, $r0 ; Mask off the non-cache bit.
166	cmp.d	0x10000, $r0	; Arbitrary, something above this code.
167	blo	_inflash0
168	nop
169
170	jump	_inram		; Jump to cached RAM.
171	nop
172
173	;; Jumpgate.
174_inflash0:
175	jump _inflash
176	nop
177
178	;; Put the following in a section so that storage for it can be
179	;; reclaimed after init is finished.
180	.section ".init.text", "ax"
181
182_inflash:
183
184	;; Initialize DRAM.
185	cmp.d	RAM_INIT_MAGIC, $r8 ; Already initialized?
186	beq	_dram_initialized
187	nop
188
189#if defined CONFIG_ETRAXFS
190#include "../mach-fs/dram_init.S"
191#elif defined CONFIG_CRIS_MACH_ARTPEC3
192#include "../mach-a3/dram_init.S"
193#else
194#error Only ETRAXFS and ARTPEC-3 supported!
195#endif
196
197
198_dram_initialized:
199	;; Copy the text and data section to DRAM. This depends on that the
200	;; variables used below are correctly set up by the linker script.
201	;; The calculated value stored in R4 is used below.
202	;; Leave the cramfs file system (piggybacked after the kernel) in flash.
203	moveq	0, $r0		; Source.
204	move.d	text_start, $r1	; Destination.
205	move.d	__vmlinux_end, $r2
206	move.d	$r2, $r4
207	sub.d	$r1, $r4
2081:	move.w	[$r0+], $r3
209	move.w	$r3, [$r1+]
210	cmp.d	$r2, $r1
211	blo	1b
212	nop
213
214	;; Check for cramfs.
215	moveq	0, $r0
216	move.d	romfs_length, $r1
217	move.d	$r0, [$r1]
218	move.d	[$r4], $r0	; cramfs_super.magic
219	cmp.d	CRAMFS_MAGIC, $r0
220	bne 1f
221	nop
222
223	;; Set length and start of cramfs, set romfs_in_flash flag
224	addoq	+4, $r4, $acr
225	move.d	[$acr], $r0
226	move.d	romfs_length, $r1
227	move.d	$r0, [$r1]
228	add.d	0xf0000000, $r4	; Add cached flash start in virtual memory.
229	move.d	romfs_start, $r1
230	move.d	$r4, [$r1]
2311:	moveq	1, $r0
232	move.d	romfs_in_flash, $r1
233	move.d	$r0, [$r1]
234
235	jump	_start_it	; Jump to cached code.
236	nop
237
238_inram:
239	;; Check if booting from NAND flash; if so, set appropriate flags
240	;; and move on.
241	cmp.d	NAND_BOOT_MAGIC, $r12
242	bne	move_cramfs	; not nand, jump
243	moveq	1, $r0
244	move.d	nand_boot, $r1	; tell axisflashmap we're booting from NAND
245	move.d	$r0, [$r1]
246	moveq	0, $r0		; tell axisflashmap romfs is not in
247	move.d	romfs_in_flash, $r1 ; (directly accessed) flash
248	move.d	$r0, [$r1]
249	jump	_start_it	; continue with boot
250	nop
251
252move_cramfs:
253	;; kernel is in DRAM.
254	;; Must figure out if there is a piggybacked rootfs image or not.
255	;; Set romfs_length to 0 => no rootfs image available by default.
256	moveq	0, $r0
257	move.d	romfs_length, $r1
258	move.d	$r0, [$r1]
259
260	;; The kernel could have been unpacked to DRAM by the loader, but
261	;; the cramfs image could still be in the flash immediately
262	;; following the compressed kernel image. The loader passes the address
263	;; of the byte succeeding the last compressed byte in the flash in
264	;; register R9 when starting the kernel.
265	cmp.d	0x0ffffff8, $r9
266	bhs	_no_romfs_in_flash ; R9 points outside the flash area.
267	nop
268	;; cramfs rootfs might to be in flash. Check for it.
269	move.d	[$r9], $r0	; cramfs_super.magic
270	cmp.d	CRAMFS_MAGIC, $r0
271	bne	_no_romfs_in_flash
272	nop
273
274	;; found cramfs in flash. set address and size, and romfs_in_flash flag.
275	addoq	+4, $r9, $acr
276	move.d	[$acr], $r0
277	move.d	romfs_length, $r1
278	move.d	$r0, [$r1]
279	add.d	0xf0000000, $r9	; Add cached flash start in virtual memory.
280	move.d	romfs_start, $r1
281	move.d	$r9, [$r1]
282	moveq	1, $r0
283	move.d	romfs_in_flash, $r1
284	move.d	$r0, [$r1]
285
286	jump	_start_it	; Jump to cached code.
287	nop
288
289_no_romfs_in_flash:
290	;; No romfs in flash, so look for cramfs, or jffs2 with jhead,
291	;; after kernel in RAM, as is the case with network->RAM boot.
292	;; For cramfs, partition starts with magic and length.
293	;; For jffs2, a jhead is prepended which contains with magic and length.
294	;; The jhead is not part of the jffs2 partition however.
295	move.d	__bss_start, $r0
296	move.d	[$r0], $r1
297	cmp.d	CRAMFS_MAGIC, $r1 ; cramfs magic?
298	beq	2f		  ; yes, jump
299	nop
300	cmp.d	JHEAD_MAGIC, $r1 ; jffs2 (jhead) magic?
301	bne	4f		; no, skip copy
302	nop
303	addq	4, $r0		; location of jffs2 size
304	move.d	[$r0+], $r2	; fetch jffs2 size -> r2
305				; r0 now points to start of jffs2
306	ba	3f
307	nop
3082:
309	addoq	+4, $r0, $acr	; location of cramfs size
310	move.d	[$acr], $r2	; fetch cramfs size -> r2
311				; r0 still points to start of cramfs
3123:
313	;; Now, move the root fs to after kernel's BSS
314
315	move.d	_end, $r1	; start of cramfs -> r1
316	move.d	romfs_start, $r3
317	move.d	$r1, [$r3]	; store at romfs_start (for axisflashmap)
318	move.d	romfs_length, $r3
319	move.d	$r2, [$r3]	; store size at romfs_length
320
321	add.d	$r2, $r0	; copy from end and downwards
322	add.d	$r2, $r1
323
324	lsrq	1, $r2		; Size is in bytes, we copy words.
325	addq    1, $r2
3261:
327	move.w	[$r0], $r3
328	move.w	$r3, [$r1]
329	subq	2, $r0
330	subq	2, $r1
331	subq	1, $r2
332	bne	1b
333	nop
334
3354:
336	;; BSS move done.
337	;; Clear romfs_in_flash flag, as we now know romfs is in DRAM
338	;; Also clear nand_boot flag; if we got here, we know we've not
339	;; booted from NAND flash.
340	moveq	0, $r0
341	move.d	romfs_in_flash, $r1
342	move.d	$r0, [$r1]
343	moveq	0, $r0
344	move.d	nand_boot, $r1
345	move.d	$r0, [$r1]
346
347	jump	_start_it	; Jump to cached code.
348	nop
349
350_start_it:
351
352	;; Check if kernel command line is supplied
353	cmp.d	COMMAND_LINE_MAGIC, $r10
354	bne	no_command_line
355	nop
356
357	move.d	256, $r13
358	move.d  cris_command_line, $r10
359	or.d	0x80000000, $r11 ; Make it virtual
3601:
361	move.b  [$r11+], $r1
362	move.b  $r1, [$r10+]
363	subq	1, $r13
364	bne	1b
365	nop
366
367no_command_line:
368
369	;; The kernel stack contains a task structure for each task. This
370	;; the initial kernel stack is in the same page as the init_task,
371	;; but starts at the top of the page, i.e. + 8192 bytes.
372	move.d	init_thread_union + 8192, $sp
373	move.d	ebp_start, $r0	; Defined in linker-script.
374	move	$r0, $ebp
375	move.d	etrax_irv, $r1	; Set the exception base register and pointer.
376	move.d	$r0, [$r1]
377
378	;; Clear the BSS region from _bss_start to _end.
379	move.d	__bss_start, $r0
380	move.d	_end, $r1
3811:	clear.d	[$r0+]
382	cmp.d	$r1, $r0
383	blo 1b
384	nop
385
386	; Initialize registers to increase determinism
387	move.d __bss_start, $r0
388	movem [$r0], $r13
389
390#ifdef CONFIG_ETRAX_L2CACHE
391	jsr	l2cache_init
392	nop
393#endif
394
395	jump	start_kernel	; Jump to start_kernel() in init/main.c.
396	nop
397
398	.data
399etrax_irv:
400	.dword 0
401
402; Variables for communication with the Axis flash map driver (axisflashmap),
403; and for setting up memory in arch/cris/kernel/setup.c .
404
405; romfs_start is set to the start of the root file system, if it exists
406; in directly accessible memory (i.e. NOR Flash when booting from Flash,
407; or RAM when booting directly from a network-downloaded RAM image)
408romfs_start:
409	.dword 0
410
411; romfs_length is set to the size of the root file system image, if it exists
412; in directly accessible memory (see romfs_start). Otherwise it is set to 0.
413romfs_length:
414	.dword 0
415
416; romfs_in_flash is set to 1 if the root file system resides in directly
417; accessible flash memory (i.e. NOR flash). It is set to 0 for RAM boot
418; or NAND flash boot.
419romfs_in_flash:
420	.dword 0
421
422; nand_boot is set to 1 when the kernel has been booted from NAND flash
423nand_boot:
424	.dword 0
425
426swapper_pg_dir = 0xc0002000
427
428	.section ".init.data", "aw"
429
430#if defined CONFIG_ETRAXFS
431#include "../mach-fs/hw_settings.S"
432#elif defined CONFIG_CRIS_MACH_ARTPEC3
433#include "../mach-a3/hw_settings.S"
434#else
435#error Only ETRAXFS and ARTPEC-3 supported!
436#endif
437