CRIS v32: Update kernel/head.S
[linux-2.6.git] / arch / cris / arch-v32 / kernel / head.S
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 <hwregs/reg_rdwr.h>
14 #include <asm/arch/memmap.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 <asm/arch/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
47 tstart:
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 #ifdef CONFIG_SMP
61 secondary_cpu_entry: /* Entry point for secondary CPUs */
62         di
63 #endif
64
65         ;; Setup and enable the MMU. Use same configuration for both the data
66         ;; and the instruction MMU.
67         ;;
68         ;; Note; 3 cycles is needed for a bank-select to take effect. Further;
69         ;; bank 1 is the instruction MMU, bank 2 is the data MMU.
70 #ifndef CONFIG_ETRAX_VCS_SIM
71         move.d  REG_FIELD(mmu, rw_mm_kbase_hi, base_e, 8)       \
72                 | REG_FIELD(mmu, rw_mm_kbase_hi, base_c, 4)     \
73                 | REG_FIELD(mmu, rw_mm_kbase_hi, base_b, 0xb), $r0
74 #else
75         ;; Map the virtual DRAM to the RW eprom area at address 0.
76         ;; Also map 0xa for the hook calls,
77         move.d  REG_FIELD(mmu, rw_mm_kbase_hi, base_e, 8)       \
78                 | REG_FIELD(mmu, rw_mm_kbase_hi, base_c, 4)     \
79                 | REG_FIELD(mmu, rw_mm_kbase_hi, base_b, 0xb)   \
80                 | REG_FIELD(mmu, rw_mm_kbase_hi, base_a, 0xa), $r0
81 #endif
82
83         ;; Temporary map of 0x40 -> 0x40 and 0x00 -> 0x00.
84         move.d  REG_FIELD(mmu, rw_mm_kbase_lo, base_4, 4)  \
85                 | REG_FIELD(mmu, rw_mm_kbase_lo, base_0, 0), $r1
86
87         ;; Enable certain page protections and setup linear mapping
88         ;; for f,e,c,b,4,0.
89 #ifndef CONFIG_ETRAX_VCS_SIM
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, linear)      \
95                 | REG_STATE(mmu, rw_mm_cfg, seg_e, linear)      \
96                 | REG_STATE(mmu, rw_mm_cfg, seg_d, page)        \
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, linear)      \
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 #ifdef CONFIG_SMP
163         ;; Read CPU ID
164         move    0, $srs
165         nop
166         nop
167         nop
168         move    $s12, $r0
169         cmpq    0, $r0
170         beq     master_cpu
171         nop
172 slave_cpu:
173         ; Time to boot-up. Get stack location provided by master CPU.
174         move.d  smp_init_current_idle_thread, $r1
175         move.d  [$r1], $sp
176         add.d   8192, $sp
177         move.d  ebp_start, $r0  ; Defined in linker-script.
178         move    $r0, $ebp
179         jsr     smp_callin
180         nop
181 master_cpu:
182         /* Set up entry point for secondary CPUs. The boot ROM has set up
183          * EBP at start of internal memory. The CPU will get there
184          * later when we issue an IPI to them... */
185         move.d MEM_INTMEM_START + IPI_INTR_VECT * 4, $r0
186         move.d secondary_cpu_entry, $r1
187         move.d $r1, [$r0]
188 #endif
189 #ifndef CONFIG_ETRAX_VCS_SIM
190         ; Check if starting from DRAM (network->RAM boot or unpacked
191         ; compressed kernel), or directly from flash.
192         lapcq   ., $r0
193         and.d   0x7fffffff, $r0 ; Mask off the non-cache bit.
194         cmp.d   0x10000, $r0    ; Arbitrary, something above this code.
195         blo     _inflash0
196         nop
197 #endif
198
199         jump    _inram          ; Jump to cached RAM.
200         nop
201
202         ;; Jumpgate.
203 _inflash0:
204         jump _inflash
205         nop
206
207         ;; Put the following in a section so that storage for it can be
208         ;; reclaimed after init is finished.
209         .section ".init.text", "ax"
210
211 _inflash:
212
213         ;; Initialize DRAM.
214         cmp.d   RAM_INIT_MAGIC, $r8 ; Already initialized?
215         beq     _dram_initialized
216         nop
217
218 #include "../mach/dram_init.S"
219
220 _dram_initialized:
221         ;; Copy the text and data section to DRAM. This depends on that the
222         ;; variables used below are correctly set up by the linker script.
223         ;; The calculated value stored in R4 is used below.
224         ;; Leave the cramfs file system (piggybacked after the kernel) in flash.
225         moveq   0, $r0          ; Source.
226         move.d  text_start, $r1 ; Destination.
227         move.d  __vmlinux_end, $r2
228         move.d  $r2, $r4
229         sub.d   $r1, $r4
230 1:      move.w  [$r0+], $r3
231         move.w  $r3, [$r1+]
232         cmp.d   $r2, $r1
233         blo     1b
234         nop
235
236         ;; Check for cramfs.
237         moveq   0, $r0
238         move.d  romfs_length, $r1
239         move.d  $r0, [$r1]
240         move.d  [$r4], $r0      ; cramfs_super.magic
241         cmp.d   CRAMFS_MAGIC, $r0
242         bne 1f
243         nop
244
245         ;; Set length and start of cramfs, set romfs_in_flash flag
246         addoq   +4, $r4, $acr
247         move.d  [$acr], $r0
248         move.d  romfs_length, $r1
249         move.d  $r0, [$r1]
250         add.d   0xf0000000, $r4 ; Add cached flash start in virtual memory.
251         move.d  romfs_start, $r1
252         move.d  $r4, [$r1]
253 1:      moveq   1, $r0
254         move.d  romfs_in_flash, $r1
255         move.d  $r0, [$r1]
256
257         jump    _start_it       ; Jump to cached code.
258         nop
259
260 _inram:
261         ;; Check if booting from NAND flash; if so, set appropriate flags
262         ;; and move on.
263         cmp.d   NAND_BOOT_MAGIC, $r12
264         bne     move_cramfs     ; not nand, jump
265         moveq   1, $r0
266         move.d  nand_boot, $r1  ; tell axisflashmap we're booting from NAND
267         move.d  $r0, [$r1]
268         moveq   0, $r0          ; tell axisflashmap romfs is not in
269         move.d  romfs_in_flash, $r1 ; (directly accessed) flash
270         move.d  $r0, [$r1]
271         jump    _start_it       ; continue with boot
272         nop
273
274 move_cramfs:
275         ;; kernel is in DRAM.
276         ;; Must figure out if there is a piggybacked rootfs image or not.
277         ;; Set romfs_length to 0 => no rootfs image available by default.
278         moveq   0, $r0
279         move.d  romfs_length, $r1
280         move.d  $r0, [$r1]
281
282 #ifndef CONFIG_ETRAX_VCS_SIM
283         ;; The kernel could have been unpacked to DRAM by the loader, but
284         ;; the cramfs image could still be in the flash immediately
285         ;; following the compressed kernel image. The loader passes the address
286         ;; of the byte succeeding the last compressed byte in the flash in
287         ;; register R9 when starting the kernel.
288         cmp.d   0x0ffffff8, $r9
289         bhs     _no_romfs_in_flash ; R9 points outside the flash area.
290         nop
291 #else
292         ba _no_romfs_in_flash
293         nop
294 #endif
295         ;; cramfs rootfs might to be in flash. Check for it.
296         move.d  [$r9], $r0      ; cramfs_super.magic
297         cmp.d   CRAMFS_MAGIC, $r0
298         bne     _no_romfs_in_flash
299         nop
300
301         ;; found cramfs in flash. set address and size, and romfs_in_flash flag.
302         addoq   +4, $r9, $acr
303         move.d  [$acr], $r0
304         move.d  romfs_length, $r1
305         move.d  $r0, [$r1]
306         add.d   0xf0000000, $r9 ; Add cached flash start in virtual memory.
307         move.d  romfs_start, $r1
308         move.d  $r9, [$r1]
309         moveq   1, $r0
310         move.d  romfs_in_flash, $r1
311         move.d  $r0, [$r1]
312
313         jump    _start_it       ; Jump to cached code.
314         nop
315
316 _no_romfs_in_flash:
317         ;; No romfs in flash, so look for cramfs, or jffs2 with jhead,
318         ;; after kernel in RAM, as is the case with network->RAM boot.
319         ;; For cramfs, partition starts with magic and length.
320         ;; For jffs2, a jhead is prepended which contains with magic and length.
321         ;; The jhead is not part of the jffs2 partition however.
322 #ifndef CONFIG_ETRAXFS_SIM
323         move.d  __vmlinux_end, $r0
324 #else
325         move.d  __end, $r0
326 #endif
327         move.d  [$r0], $r1
328         cmp.d   CRAMFS_MAGIC, $r1 ; cramfs magic?
329         beq     2f                ; yes, jump
330         nop
331         cmp.d   JHEAD_MAGIC, $r1 ; jffs2 (jhead) magic?
332         bne     4f              ; no, skip copy
333         nop
334         addq    4, $r0          ; location of jffs2 size
335         move.d  [$r0+], $r2     ; fetch jffs2 size -> r2
336                                 ; r0 now points to start of jffs2
337         ba      3f
338         nop
339 2:
340         addoq   +4, $r0, $acr   ; location of cramfs size
341         move.d  [$acr], $r2     ; fetch cramfs size -> r2
342                                 ; r0 still points to start of cramfs
343 3:
344         ;; Now, move the root fs to after kernel's BSS
345
346         move.d  _end, $r1       ; start of cramfs -> r1
347         move.d  romfs_start, $r3
348         move.d  $r1, [$r3]      ; store at romfs_start (for axisflashmap)
349         move.d  romfs_length, $r3
350         move.d  $r2, [$r3]      ; store size at romfs_length
351
352 #ifndef CONFIG_ETRAX_VCS_SIM
353         add.d   $r2, $r0        ; copy from end and downwards
354         add.d   $r2, $r1
355
356         lsrq    1, $r2          ; Size is in bytes, we copy words.
357         addq    1, $r2
358 1:
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
368 4:
369         ;; BSS move done.
370         ;; Clear romfs_in_flash flag, as we now know romfs is in DRAM
371         ;; Also clear nand_boot flag; if we got here, we know we've not
372         ;; booted from NAND flash.
373         moveq   0, $r0
374         move.d  romfs_in_flash, $r1
375         move.d  $r0, [$r1]
376         moveq   0, $r0
377         move.d  nand_boot, $r1
378         move.d  $r0, [$r1]
379
380         jump    _start_it       ; Jump to cached code.
381         nop
382
383 _start_it:
384
385         ;; Check if kernel command line is supplied
386         cmp.d   COMMAND_LINE_MAGIC, $r10
387         bne     no_command_line
388         nop
389
390         move.d  256, $r13
391         move.d  cris_command_line, $r10
392         or.d    0x80000000, $r11 ; Make it virtual
393 1:
394         move.b  [$r11+], $r1
395         move.b  $r1, [$r10+]
396         subq    1, $r13
397         bne     1b
398         nop
399
400 no_command_line:
401
402         ;; The kernel stack contains a task structure for each task. This
403         ;; the initial kernel stack is in the same page as the init_task,
404         ;; but starts at the top of the page, i.e. + 8192 bytes.
405         move.d  init_thread_union + 8192, $sp
406         move.d  ebp_start, $r0  ; Defined in linker-script.
407         move    $r0, $ebp
408         move.d  etrax_irv, $r1  ; Set the exception base register and pointer.
409         move.d  $r0, [$r1]
410
411 #ifndef CONFIG_ETRAX_VCS_SIM
412         ;; Clear the BSS region from _bss_start to _end.
413         move.d  __bss_start, $r0
414         move.d  _end, $r1
415 1:      clear.d [$r0+]
416         cmp.d   $r1, $r0
417         blo 1b
418         nop
419 #endif
420
421 #ifdef CONFIG_ETRAX_VCS_SIM
422         /* Set the watchdog timeout to something big. Will be removed when */
423         /* watchdog can be disabled with command line option */
424         move.d  0x7fffffff, $r10
425         jsr     CPU_WATCHDOG_TIMEOUT
426         nop
427 #endif
428
429         ; Initialize registers to increase determinism
430         move.d __bss_start, $r0
431         movem [$r0], $r13
432
433 #ifdef CONFIG_ETRAX_L2CACHE
434         jsr     l2cache_init
435         nop
436 #endif
437
438         jump    start_kernel    ; Jump to start_kernel() in init/main.c.
439         nop
440
441         .data
442 etrax_irv:
443         .dword 0
444
445 ; Variables for communication with the Axis flash map driver (axisflashmap),
446 ; and for setting up memory in arch/cris/kernel/setup.c .
447
448 ; romfs_start is set to the start of the root file system, if it exists
449 ; in directly accessible memory (i.e. NOR Flash when booting from Flash,
450 ; or RAM when booting directly from a network-downloaded RAM image)
451 romfs_start:
452         .dword 0
453
454 ; romfs_length is set to the size of the root file system image, if it exists
455 ; in directly accessible memory (see romfs_start). Otherwise it is set to 0.
456 romfs_length:
457         .dword 0
458
459 ; romfs_in_flash is set to 1 if the root file system resides in directly
460 ; accessible flash memory (i.e. NOR flash). It is set to 0 for RAM boot
461 ; or NAND flash boot.
462 romfs_in_flash:
463         .dword 0
464
465 ; nand_boot is set to 1 when the kernel has been booted from NAND flash
466 nand_boot:
467         .dword 0
468
469 swapper_pg_dir = 0xc0002000
470
471         .section ".init.data", "aw"
472
473 #include "../mach/hw_settings.S"