• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6/arch/cris/arch-v32/kernel/
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	;; Dummy section to make it bootable with current VCS simulator
40#ifdef CONFIG_ETRAX_VCS_SIM
41	.section ".boot", "ax"
42	ba tstart
43	nop
44#endif
45
46	.text
47tstart:
48	;; This is the entry point of the kernel. The CPU is currently in
49	;; supervisor mode.
50	;;
51	;; 0x00000000 if flash.
52	;; 0x40004000 if DRAM.
53	;;
54	di
55
56	START_CLOCKS
57
58	SETUP_WAIT_STATES
59
60	GIO_INIT
61
62#ifdef CONFIG_SMP
63secondary_cpu_entry: /* Entry point for secondary CPUs */
64	di
65#endif
66
67	;; Setup and enable the MMU. Use same configuration for both the data
68	;; and the instruction MMU.
69	;;
70	;; Note; 3 cycles is needed for a bank-select to take effect. Further;
71	;; bank 1 is the instruction MMU, bank 2 is the data MMU.
72
73#ifdef CONFIG_CRIS_MACH_ARTPEC3
74	move.d	REG_FIELD(mmu, rw_mm_kbase_hi, base_e, 8)	\
75		| REG_FIELD(mmu, rw_mm_kbase_hi, base_c, 4)	\
76		| REG_FIELD(mmu, rw_mm_kbase_hi, base_d, 5)     \
77		| REG_FIELD(mmu, rw_mm_kbase_hi, base_b, 0xb), $r0
78#elif !defined(CONFIG_ETRAX_VCS_SIM)
79	move.d	REG_FIELD(mmu, rw_mm_kbase_hi, base_e, 8)	\
80		| REG_FIELD(mmu, rw_mm_kbase_hi, base_c, 4)	\
81		| REG_FIELD(mmu, rw_mm_kbase_hi, base_b, 0xb), $r0
82#else
83	;; Map the virtual DRAM to the RW eprom area at address 0.
84	;; Also map 0xa for the hook calls,
85	move.d	REG_FIELD(mmu, rw_mm_kbase_hi, base_e, 8)	\
86		| REG_FIELD(mmu, rw_mm_kbase_hi, base_c, 4)	\
87		| REG_FIELD(mmu, rw_mm_kbase_hi, base_b, 0xb)   \
88		| REG_FIELD(mmu, rw_mm_kbase_hi, base_a, 0xa), $r0
89#endif
90
91	;; Temporary map of 0x40 -> 0x40 and 0x00 -> 0x00.
92	move.d	REG_FIELD(mmu, rw_mm_kbase_lo, base_4, 4)  \
93		| REG_FIELD(mmu, rw_mm_kbase_lo, base_0, 0), $r1
94
95	;; Enable certain page protections and setup linear mapping
96	;; for f,e,c,b,4,0.
97
98	;; ARTPEC-3:
99	;; c,d used for linear kernel mapping, up to 512 MB
100	;; e used for vmalloc
101	;; f unused, but page mapped to get page faults
102
103	;; ETRAX FS:
104	;; c used for linear kernel mapping, up to 256 MB
105	;; d used for vmalloc
106	;; e,f used for memory-mapped NOR flash
107
108#ifdef CONFIG_CRIS_MACH_ARTPEC3
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, page)	\
114		| REG_STATE(mmu, rw_mm_cfg, seg_e, page)	\
115		| REG_STATE(mmu, rw_mm_cfg, seg_d, linear)      \
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
129#elif !defined(CONFIG_ETRAX_VCS_SIM)
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, page)	\
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
150#else
151	move.d	REG_STATE(mmu, rw_mm_cfg, we, on)		\
152		| REG_STATE(mmu, rw_mm_cfg, acc, on)		\
153		| REG_STATE(mmu, rw_mm_cfg, ex, on)		\
154		| REG_STATE(mmu, rw_mm_cfg, inv, on)		\
155		| REG_STATE(mmu, rw_mm_cfg, seg_f, linear)	\
156		| REG_STATE(mmu, rw_mm_cfg, seg_e, linear)	\
157		| REG_STATE(mmu, rw_mm_cfg, seg_d, page)	\
158		| REG_STATE(mmu, rw_mm_cfg, seg_c, linear)	\
159		| REG_STATE(mmu, rw_mm_cfg, seg_b, linear)	\
160		| REG_STATE(mmu, rw_mm_cfg, seg_a, linear)	\
161		| REG_STATE(mmu, rw_mm_cfg, seg_9, page)	\
162		| REG_STATE(mmu, rw_mm_cfg, seg_8, page)	\
163		| REG_STATE(mmu, rw_mm_cfg, seg_7, page)	\
164		| REG_STATE(mmu, rw_mm_cfg, seg_6, page)	\
165		| REG_STATE(mmu, rw_mm_cfg, seg_5, page)	\
166		| REG_STATE(mmu, rw_mm_cfg, seg_4, linear)	\
167		| REG_STATE(mmu, rw_mm_cfg, seg_3, page)	\
168		| REG_STATE(mmu, rw_mm_cfg, seg_2, page)	\
169		| REG_STATE(mmu, rw_mm_cfg, seg_1, page)	\
170		| REG_STATE(mmu, rw_mm_cfg, seg_0, linear), $r2
171#endif
172
173	;; Update instruction MMU.
174	move	1, $srs
175	nop
176	nop
177	nop
178	move	$r0, $s2	; kbase_hi.
179	move	$r1, $s1	; kbase_lo.
180	move	$r2, $s0	; mm_cfg, virtual memory configuration.
181
182	;; Update data MMU.
183	move	2, $srs
184	nop
185	nop
186	nop
187	move	$r0, $s2	; kbase_hi.
188	move	$r1, $s1	; kbase_lo
189	move	$r2, $s0	; mm_cfg, virtual memory configuration.
190
191	;; Enable data and instruction MMU.
192	move	0, $srs
193	moveq	0xf, $r0	;  IMMU, DMMU, DCache, Icache on
194	nop
195	nop
196	nop
197	move	$r0, $s0
198	nop
199	nop
200	nop
201
202#ifdef CONFIG_SMP
203	;; Read CPU ID
204	move    0, $srs
205	nop
206	nop
207	nop
208	move    $s12, $r0
209	cmpq    0, $r0
210	beq	master_cpu
211	nop
212slave_cpu:
213	; Time to boot-up. Get stack location provided by master CPU.
214	move.d  smp_init_current_idle_thread, $r1
215	move.d  [$r1], $sp
216	add.d	8192, $sp
217	move.d	ebp_start, $r0	; Defined in linker-script.
218	move	$r0, $ebp
219	jsr	smp_callin
220	nop
221master_cpu:
222	/* Set up entry point for secondary CPUs. The boot ROM has set up
223	 * EBP at start of internal memory. The CPU will get there
224	 * later when we issue an IPI to them... */
225	move.d MEM_INTMEM_START + IPI_INTR_VECT * 4, $r0
226	move.d secondary_cpu_entry, $r1
227	move.d $r1, [$r0]
228#endif
229#ifndef CONFIG_ETRAX_VCS_SIM
230	; Check if starting from DRAM (network->RAM boot or unpacked
231	; compressed kernel), or directly from flash.
232	lapcq	., $r0
233	and.d	0x7fffffff, $r0 ; Mask off the non-cache bit.
234	cmp.d	0x10000, $r0	; Arbitrary, something above this code.
235	blo	_inflash0
236	nop
237#endif
238
239	jump	_inram		; Jump to cached RAM.
240	nop
241
242	;; Jumpgate.
243_inflash0:
244	jump _inflash
245	nop
246
247	;; Put the following in a section so that storage for it can be
248	;; reclaimed after init is finished.
249	.section ".init.text", "ax"
250
251_inflash:
252
253	;; Initialize DRAM.
254	cmp.d	RAM_INIT_MAGIC, $r8 ; Already initialized?
255	beq	_dram_initialized
256	nop
257
258#if defined CONFIG_ETRAXFS
259#include "../mach-fs/dram_init.S"
260#elif defined CONFIG_CRIS_MACH_ARTPEC3
261#include "../mach-a3/dram_init.S"
262#else
263#error Only ETRAXFS and ARTPEC-3 supported!
264#endif
265
266
267_dram_initialized:
268	;; Copy the text and data section to DRAM. This depends on that the
269	;; variables used below are correctly set up by the linker script.
270	;; The calculated value stored in R4 is used below.
271	;; Leave the cramfs file system (piggybacked after the kernel) in flash.
272	moveq	0, $r0		; Source.
273	move.d	text_start, $r1	; Destination.
274	move.d	__vmlinux_end, $r2
275	move.d	$r2, $r4
276	sub.d	$r1, $r4
2771:	move.w	[$r0+], $r3
278	move.w	$r3, [$r1+]
279	cmp.d	$r2, $r1
280	blo	1b
281	nop
282
283	;; Check for cramfs.
284	moveq	0, $r0
285	move.d	romfs_length, $r1
286	move.d	$r0, [$r1]
287	move.d	[$r4], $r0	; cramfs_super.magic
288	cmp.d	CRAMFS_MAGIC, $r0
289	bne 1f
290	nop
291
292	;; Set length and start of cramfs, set romfs_in_flash flag
293	addoq	+4, $r4, $acr
294	move.d	[$acr], $r0
295	move.d	romfs_length, $r1
296	move.d	$r0, [$r1]
297	add.d	0xf0000000, $r4	; Add cached flash start in virtual memory.
298	move.d	romfs_start, $r1
299	move.d	$r4, [$r1]
3001:	moveq	1, $r0
301	move.d	romfs_in_flash, $r1
302	move.d	$r0, [$r1]
303
304	jump	_start_it	; Jump to cached code.
305	nop
306
307_inram:
308	;; Check if booting from NAND flash; if so, set appropriate flags
309	;; and move on.
310	cmp.d	NAND_BOOT_MAGIC, $r12
311	bne	move_cramfs	; not nand, jump
312	moveq	1, $r0
313	move.d	nand_boot, $r1	; tell axisflashmap we're booting from NAND
314	move.d	$r0, [$r1]
315	moveq	0, $r0		; tell axisflashmap romfs is not in
316	move.d	romfs_in_flash, $r1 ; (directly accessed) flash
317	move.d	$r0, [$r1]
318	jump	_start_it	; continue with boot
319	nop
320
321move_cramfs:
322	;; kernel is in DRAM.
323	;; Must figure out if there is a piggybacked rootfs image or not.
324	;; Set romfs_length to 0 => no rootfs image available by default.
325	moveq	0, $r0
326	move.d	romfs_length, $r1
327	move.d	$r0, [$r1]
328
329#ifndef CONFIG_ETRAX_VCS_SIM
330	;; The kernel could have been unpacked to DRAM by the loader, but
331	;; the cramfs image could still be in the flash immediately
332	;; following the compressed kernel image. The loader passes the address
333	;; of the byte succeeding the last compressed byte in the flash in
334	;; register R9 when starting the kernel.
335	cmp.d	0x0ffffff8, $r9
336	bhs	_no_romfs_in_flash ; R9 points outside the flash area.
337	nop
338#else
339	ba _no_romfs_in_flash
340	nop
341#endif
342	;; cramfs rootfs might to be in flash. Check for it.
343	move.d	[$r9], $r0	; cramfs_super.magic
344	cmp.d	CRAMFS_MAGIC, $r0
345	bne	_no_romfs_in_flash
346	nop
347
348	;; found cramfs in flash. set address and size, and romfs_in_flash flag.
349	addoq	+4, $r9, $acr
350	move.d	[$acr], $r0
351	move.d	romfs_length, $r1
352	move.d	$r0, [$r1]
353	add.d	0xf0000000, $r9	; Add cached flash start in virtual memory.
354	move.d	romfs_start, $r1
355	move.d	$r9, [$r1]
356	moveq	1, $r0
357	move.d	romfs_in_flash, $r1
358	move.d	$r0, [$r1]
359
360	jump	_start_it	; Jump to cached code.
361	nop
362
363_no_romfs_in_flash:
364	;; No romfs in flash, so look for cramfs, or jffs2 with jhead,
365	;; after kernel in RAM, as is the case with network->RAM boot.
366	;; For cramfs, partition starts with magic and length.
367	;; For jffs2, a jhead is prepended which contains with magic and length.
368	;; The jhead is not part of the jffs2 partition however.
369#ifndef CONFIG_ETRAXFS_SIM
370	move.d	__bss_start, $r0
371#else
372	move.d	__end, $r0
373#endif
374	move.d	[$r0], $r1
375	cmp.d	CRAMFS_MAGIC, $r1 ; cramfs magic?
376	beq	2f		  ; yes, jump
377	nop
378	cmp.d	JHEAD_MAGIC, $r1 ; jffs2 (jhead) magic?
379	bne	4f		; no, skip copy
380	nop
381	addq	4, $r0		; location of jffs2 size
382	move.d	[$r0+], $r2	; fetch jffs2 size -> r2
383				; r0 now points to start of jffs2
384	ba	3f
385	nop
3862:
387	addoq	+4, $r0, $acr	; location of cramfs size
388	move.d	[$acr], $r2	; fetch cramfs size -> r2
389				; r0 still points to start of cramfs
3903:
391	;; Now, move the root fs to after kernel's BSS
392
393	move.d	_end, $r1	; start of cramfs -> r1
394	move.d	romfs_start, $r3
395	move.d	$r1, [$r3]	; store at romfs_start (for axisflashmap)
396	move.d	romfs_length, $r3
397	move.d	$r2, [$r3]	; store size at romfs_length
398
399#ifndef CONFIG_ETRAX_VCS_SIM
400	add.d	$r2, $r0	; copy from end and downwards
401	add.d	$r2, $r1
402
403	lsrq	1, $r2		; Size is in bytes, we copy words.
404	addq    1, $r2
4051:
406	move.w	[$r0], $r3
407	move.w	$r3, [$r1]
408	subq	2, $r0
409	subq	2, $r1
410	subq	1, $r2
411	bne	1b
412	nop
413#endif
414
4154:
416	;; BSS move done.
417	;; Clear romfs_in_flash flag, as we now know romfs is in DRAM
418	;; Also clear nand_boot flag; if we got here, we know we've not
419	;; booted from NAND flash.
420	moveq	0, $r0
421	move.d	romfs_in_flash, $r1
422	move.d	$r0, [$r1]
423	moveq	0, $r0
424	move.d	nand_boot, $r1
425	move.d	$r0, [$r1]
426
427	jump	_start_it	; Jump to cached code.
428	nop
429
430_start_it:
431
432	;; Check if kernel command line is supplied
433	cmp.d	COMMAND_LINE_MAGIC, $r10
434	bne	no_command_line
435	nop
436
437	move.d	256, $r13
438	move.d  cris_command_line, $r10
439	or.d	0x80000000, $r11 ; Make it virtual
4401:
441	move.b  [$r11+], $r1
442	move.b  $r1, [$r10+]
443	subq	1, $r13
444	bne	1b
445	nop
446
447no_command_line:
448
449	;; The kernel stack contains a task structure for each task. This
450	;; the initial kernel stack is in the same page as the init_task,
451	;; but starts at the top of the page, i.e. + 8192 bytes.
452	move.d	init_thread_union + 8192, $sp
453	move.d	ebp_start, $r0	; Defined in linker-script.
454	move	$r0, $ebp
455	move.d	etrax_irv, $r1	; Set the exception base register and pointer.
456	move.d	$r0, [$r1]
457
458#ifndef CONFIG_ETRAX_VCS_SIM
459	;; Clear the BSS region from _bss_start to _end.
460	move.d	__bss_start, $r0
461	move.d	_end, $r1
4621:	clear.d	[$r0+]
463	cmp.d	$r1, $r0
464	blo 1b
465	nop
466#endif
467
468#ifdef CONFIG_ETRAX_VCS_SIM
469	/* Set the watchdog timeout to something big. Will be removed when */
470	/* watchdog can be disabled with command line option */
471	move.d  0x7fffffff, $r10
472	jsr     CPU_WATCHDOG_TIMEOUT
473	nop
474#endif
475
476	; Initialize registers to increase determinism
477	move.d __bss_start, $r0
478	movem [$r0], $r13
479
480#ifdef CONFIG_ETRAX_L2CACHE
481	jsr	l2cache_init
482	nop
483#endif
484
485	jump	start_kernel	; Jump to start_kernel() in init/main.c.
486	nop
487
488	.data
489etrax_irv:
490	.dword 0
491
492; Variables for communication with the Axis flash map driver (axisflashmap),
493; and for setting up memory in arch/cris/kernel/setup.c .
494
495; romfs_start is set to the start of the root file system, if it exists
496; in directly accessible memory (i.e. NOR Flash when booting from Flash,
497; or RAM when booting directly from a network-downloaded RAM image)
498romfs_start:
499	.dword 0
500
501; romfs_length is set to the size of the root file system image, if it exists
502; in directly accessible memory (see romfs_start). Otherwise it is set to 0.
503romfs_length:
504	.dword 0
505
506; romfs_in_flash is set to 1 if the root file system resides in directly
507; accessible flash memory (i.e. NOR flash). It is set to 0 for RAM boot
508; or NAND flash boot.
509romfs_in_flash:
510	.dword 0
511
512; nand_boot is set to 1 when the kernel has been booted from NAND flash
513nand_boot:
514	.dword 0
515
516swapper_pg_dir = 0xc0002000
517
518	.section ".init.data", "aw"
519
520#if defined CONFIG_ETRAXFS
521#include "../mach-fs/hw_settings.S"
522#elif defined CONFIG_CRIS_MACH_ARTPEC3
523#include "../mach-a3/hw_settings.S"
524#else
525#error Only ETRAXFS and ARTPEC-3 supported!
526#endif
527