Linux 2.6.39-rc2
[pohmelfs.git] / arch / frv / kernel / head.S
blobe9a8cc63ac9413a0233f6f55ec0d91693ee3cf57
1 /* head.S: kernel entry point for FR-V kernel
2  *
3  * Copyright (C) 2003, 2004 Red Hat, Inc. All Rights Reserved.
4  * Written by David Howells (dhowells@redhat.com)
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version
9  * 2 of the License, or (at your option) any later version.
10  */
12 #include <linux/init.h>
13 #include <linux/threads.h>
14 #include <linux/linkage.h>
15 #include <asm/thread_info.h>
16 #include <asm/ptrace.h>
17 #include <asm/page.h>
18 #include <asm/spr-regs.h>
19 #include <asm/mb86943a.h>
20 #include <asm/cache.h>
21 #include "head.inc"
23 ###############################################################################
25 # void _boot(unsigned long magic, char *command_line) __attribute__((noreturn))
27 # - if magic is 0xdead1eaf, then command_line is assumed to point to the kernel
28 #   command line string
30 ###############################################################################
31         __HEAD
32         .balign         4
34         .globl          _boot, __head_reference
35         .type           _boot,@function
36 _boot:
37 __head_reference:
38         sethi.p         %hi(LED_ADDR),gr30
39         setlo           %lo(LED_ADDR),gr30
41         LEDS            0x0000
43         # calculate reference address for PC-relative stuff
44         call            0f
45 0:      movsg           lr,gr26
46         addi            gr26,#__head_reference-0b,gr26
48         # invalidate and disable both of the caches and turn off the memory access checking
49         dcef            @(gr0,gr0),1
50         bar
52         sethi.p         %hi(~(HSR0_ICE|HSR0_DCE|HSR0_CBM|HSR0_EIMMU|HSR0_EDMMU)),gr4
53         setlo           %lo(~(HSR0_ICE|HSR0_DCE|HSR0_CBM|HSR0_EIMMU|HSR0_EDMMU)),gr4
54         movsg           hsr0,gr5
55         and             gr4,gr5,gr5
56         movgs           gr5,hsr0
57         movsg           hsr0,gr5
59         LEDS            0x0001
61         icei            @(gr0,gr0),1
62         dcei            @(gr0,gr0),1
63         bar
65         # turn the instruction cache back on
66         sethi.p         %hi(HSR0_ICE),gr4
67         setlo           %lo(HSR0_ICE),gr4
68         movsg           hsr0,gr5
69         or              gr4,gr5,gr5
70         movgs           gr5,hsr0
71         movsg           hsr0,gr5
73         bar
75         LEDS            0x0002
77         # retrieve the parameters (including command line) before we overwrite them
78         sethi.p         %hi(0xdead1eaf),gr7
79         setlo           %lo(0xdead1eaf),gr7
80         subcc           gr7,gr8,gr0,icc0
81         bne             icc0,#0,__head_no_parameters
83         sethi.p         %hi(redboot_command_line-1),gr6
84         setlo           %lo(redboot_command_line-1),gr6
85         sethi.p         %hi(__head_reference),gr4
86         setlo           %lo(__head_reference),gr4
87         sub             gr6,gr4,gr6
88         add.p           gr6,gr26,gr6
89         subi            gr9,#1,gr9
90         setlos.p        #511,gr4
91         setlos          #1,gr5
93 __head_copy_cmdline:
94         ldubu.p         @(gr9,gr5),gr16
95         subicc          gr4,#1,gr4,icc0
96         stbu.p          gr16,@(gr6,gr5)
97         subicc          gr16,#0,gr0,icc1
98         bls             icc0,#0,__head_end_cmdline
99         bne             icc1,#1,__head_copy_cmdline
100 __head_end_cmdline:
101         stbu            gr0,@(gr6,gr5)
102 __head_no_parameters:
104 ###############################################################################
106 # we need to relocate the SDRAM to 0x00000000 (linux) or 0xC0000000 (uClinux)
107 # - note that we're going to have to run entirely out of the icache whilst
108 #   fiddling with the SDRAM controller registers
110 ###############################################################################
111 #ifdef CONFIG_MMU
112         call            __head_fr451_describe_sdram
114 #else
115         movsg           psr,gr5
116         srli            gr5,#28,gr5
117         subicc          gr5,#3,gr0,icc0
118         beq             icc0,#0,__head_fr551_sdram
120         call            __head_fr401_describe_sdram
121         bra             __head_do_sdram
123 __head_fr551_sdram:
124         call            __head_fr555_describe_sdram
125         LEDS            0x000d
127 __head_do_sdram:
128 #endif
130         # preload the registers with invalid values in case any DBR/DARS are marked not present
131         sethi.p         %hi(0xfe000000),gr17            ; unused SDRAM DBR value
132         setlo           %lo(0xfe000000),gr17
133         or.p            gr17,gr0,gr20
134         or              gr17,gr0,gr21
135         or.p            gr17,gr0,gr22
136         or              gr17,gr0,gr23
138         # consult the SDRAM controller CS address registers
139         cld             @(gr14,gr0 ),gr20,      cc0,#1  ; DBR0 / DARS0
140         cld             @(gr14,gr11),gr21,      cc1,#1  ; DBR1 / DARS1
141         cld             @(gr14,gr12),gr22,      cc2,#1  ; DBR2 / DARS2
142         cld.p           @(gr14,gr13),gr23,      cc3,#1  ; DBR3 / DARS3
144         sll             gr20,gr15,gr20                  ; shift values up for FR551
145         sll             gr21,gr15,gr21
146         sll             gr22,gr15,gr22
147         sll             gr23,gr15,gr23
149         LEDS            0x0003
151         # assume the lowest valid CS line to be the SDRAM base and get its address
152         subcc           gr20,gr17,gr0,icc0
153         subcc.p         gr21,gr17,gr0,icc1
154         subcc           gr22,gr17,gr0,icc2
155         subcc.p         gr23,gr17,gr0,icc3
156         ckne            icc0,cc4                        ; T if DBR0 != 0xfe000000
157         ckne            icc1,cc5
158         ckne            icc2,cc6
159         ckne            icc3,cc7
160         cor             gr23,gr0,gr24,          cc7,#1  ; GR24 = SDRAM base
161         cor             gr22,gr0,gr24,          cc6,#1
162         cor             gr21,gr0,gr24,          cc5,#1
163         cor             gr20,gr0,gr24,          cc4,#1
165         # calculate the displacement required to get the SDRAM into the right place in memory
166         sethi.p         %hi(__sdram_base),gr16
167         setlo           %lo(__sdram_base),gr16
168         sub             gr16,gr24,gr16                  ; delta = __sdram_base - DBRx
170         # calculate the new values to go in the controller regs
171         cadd.p          gr20,gr16,gr20,         cc4,#1  ; DCS#0 (new) = DCS#0 (old) + delta
172         cadd            gr21,gr16,gr21,         cc5,#1
173         cadd.p          gr22,gr16,gr22,         cc6,#1
174         cadd            gr23,gr16,gr23,         cc7,#1
176         srl             gr20,gr15,gr20                  ; shift values down for FR551
177         srl             gr21,gr15,gr21
178         srl             gr22,gr15,gr22
179         srl             gr23,gr15,gr23
181         # work out the address at which the reg updater resides and lock it into icache
182         # also work out the address the updater will jump to when finished
183         sethi.p         %hi(__head_move_sdram-__head_reference),gr18
184         setlo           %lo(__head_move_sdram-__head_reference),gr18
185         sethi.p         %hi(__head_sdram_moved-__head_reference),gr19
186         setlo           %lo(__head_sdram_moved-__head_reference),gr19
187         add.p           gr18,gr26,gr18
188         add             gr19,gr26,gr19
189         add.p           gr19,gr16,gr19                  ; moved = addr + (__sdram_base - DBRx)
190         add             gr18,gr5,gr4                    ; two cachelines probably required
192         icpl            gr18,gr0,#1                     ; load and lock the cachelines
193         icpl            gr4,gr0,#1
194         LEDS            0x0004
195         membar
196         bar
197         jmpl            @(gr18,gr0)
199         .balign         L1_CACHE_BYTES
200 __head_move_sdram:
201         cst             gr20,@(gr14,gr0 ),      cc4,#1
202         cst             gr21,@(gr14,gr11),      cc5,#1
203         cst             gr22,@(gr14,gr12),      cc6,#1
204         cst             gr23,@(gr14,gr13),      cc7,#1
205         cld             @(gr14,gr0 ),gr20,      cc4,#1
206         cld             @(gr14,gr11),gr21,      cc5,#1
207         cld             @(gr14,gr12),gr22,      cc4,#1
208         cld             @(gr14,gr13),gr23,      cc7,#1
209         bar
210         membar
211         jmpl            @(gr19,gr0)
213         .balign         L1_CACHE_BYTES
214 __head_sdram_moved:
215         icul            gr18
216         add             gr18,gr5,gr4
217         icul            gr4
218         icei            @(gr0,gr0),1
219         dcei            @(gr0,gr0),1
221         LEDS            0x0005
223         # recalculate reference address
224         call            0f
225 0:      movsg           lr,gr26
226         addi            gr26,#__head_reference-0b,gr26
229 ###############################################################################
231 # move the kernel image down to the bottom of the SDRAM
233 ###############################################################################
234         sethi.p         %hi(__kernel_image_size_no_bss+15),gr4
235         setlo           %lo(__kernel_image_size_no_bss+15),gr4
236         srli.p          gr4,#4,gr4                      ; count
237         or              gr26,gr26,gr16                  ; source
239         sethi.p         %hi(__sdram_base),gr17          ; destination
240         setlo           %lo(__sdram_base),gr17
242         setlos          #8,gr5
243         sub.p           gr16,gr5,gr16                   ; adjust src for LDDU
244         sub             gr17,gr5,gr17                   ; adjust dst for LDDU
246         sethi.p         %hi(__head_move_kernel-__head_reference),gr18
247         setlo           %lo(__head_move_kernel-__head_reference),gr18
248         sethi.p         %hi(__head_kernel_moved-__head_reference+__sdram_base),gr19
249         setlo           %lo(__head_kernel_moved-__head_reference+__sdram_base),gr19
250         add             gr18,gr26,gr18
251         icpl            gr18,gr0,#1
252         jmpl            @(gr18,gr0)
254         .balign         32
255 __head_move_kernel:
256         lddu            @(gr16,gr5),gr10
257         lddu            @(gr16,gr5),gr12
258         stdu.p          gr10,@(gr17,gr5)
259         subicc          gr4,#1,gr4,icc0
260         stdu.p          gr12,@(gr17,gr5)
261         bhi             icc0,#0,__head_move_kernel
262         jmpl            @(gr19,gr0)
264         .balign         32
265 __head_kernel_moved:
266         icul            gr18
267         icei            @(gr0,gr0),1
268         dcei            @(gr0,gr0),1
270         LEDS            0x0006
272         # recalculate reference address
273         call            0f
274 0:      movsg           lr,gr26
275         addi            gr26,#__head_reference-0b,gr26
278 ###############################################################################
280 # rearrange the iomem map and set the protection registers
282 ###############################################################################
284 #ifdef CONFIG_MMU
285         LEDS            0x3301
286         call            __head_fr451_set_busctl
287         LEDS            0x3303
288         call            __head_fr451_survey_sdram
289         LEDS            0x3305
290         call            __head_fr451_set_protection
292 #else
293         movsg           psr,gr5
294         srli            gr5,#PSR_IMPLE_SHIFT,gr5
295         subicc          gr5,#PSR_IMPLE_FR551,gr0,icc0
296         beq             icc0,#0,__head_fr555_memmap
297         subicc          gr5,#PSR_IMPLE_FR451,gr0,icc0
298         beq             icc0,#0,__head_fr451_memmap
300         LEDS            0x3101
301         call            __head_fr401_set_busctl
302         LEDS            0x3103
303         call            __head_fr401_survey_sdram
304         LEDS            0x3105
305         call            __head_fr401_set_protection
306         bra             __head_done_memmap
308 __head_fr451_memmap:
309         LEDS            0x3301
310         call            __head_fr401_set_busctl
311         LEDS            0x3303
312         call            __head_fr401_survey_sdram
313         LEDS            0x3305
314         call            __head_fr451_set_protection
315         bra             __head_done_memmap
317 __head_fr555_memmap:
318         LEDS            0x3501
319         call            __head_fr555_set_busctl
320         LEDS            0x3503
321         call            __head_fr555_survey_sdram
322         LEDS            0x3505
323         call            __head_fr555_set_protection
325 __head_done_memmap:
326 #endif
327         LEDS            0x0007
329 ###############################################################################
331 # turn the data cache and MMU on
332 # - for the FR451 this'll mean that the window through which the kernel is
333 #   viewed will change
335 ###############################################################################
337 #ifdef CONFIG_MMU
338 #define MMUMODE         HSR0_EIMMU|HSR0_EDMMU|HSR0_EXMMU|HSR0_EDAT|HSR0_XEDAT
339 #else
340 #define MMUMODE         HSR0_EIMMU|HSR0_EDMMU
341 #endif
343         movsg           hsr0,gr5
345         sethi.p         %hi(MMUMODE),gr4
346         setlo           %lo(MMUMODE),gr4
347         or              gr4,gr5,gr5
349 #if defined(CONFIG_FRV_DEFL_CACHE_WTHRU)
350         sethi.p         %hi(HSR0_DCE|HSR0_CBM_WRITE_THRU),gr4
351         setlo           %lo(HSR0_DCE|HSR0_CBM_WRITE_THRU),gr4
352 #elif defined(CONFIG_FRV_DEFL_CACHE_WBACK)
353         sethi.p         %hi(HSR0_DCE|HSR0_CBM_COPY_BACK),gr4
354         setlo           %lo(HSR0_DCE|HSR0_CBM_COPY_BACK),gr4
355 #elif defined(CONFIG_FRV_DEFL_CACHE_WBEHIND)
356         sethi.p         %hi(HSR0_DCE|HSR0_CBM_COPY_BACK),gr4
357         setlo           %lo(HSR0_DCE|HSR0_CBM_COPY_BACK),gr4
359         movsg           psr,gr6
360         srli            gr6,#24,gr6
361         cmpi            gr6,#0x50,icc0          // FR451
362         beq             icc0,#0,0f
363         cmpi            gr6,#0x40,icc0          // FR405
364         bne             icc0,#0,1f
366         # turn off write-allocate
367         sethi.p         %hi(HSR0_NWA),gr6
368         setlo           %lo(HSR0_NWA),gr6
369         or              gr4,gr6,gr4
372 #else
373 #error No default cache configuration set
374 #endif
376         or              gr4,gr5,gr5
377         movgs           gr5,hsr0
378         bar
380         LEDS            0x0008
382         sethi.p         %hi(__head_mmu_enabled),gr19
383         setlo           %lo(__head_mmu_enabled),gr19
384         jmpl            @(gr19,gr0)
386 __head_mmu_enabled:
387         icei            @(gr0,gr0),#1
388         dcei            @(gr0,gr0),#1
390         LEDS            0x0009
392 #ifdef CONFIG_MMU
393         call            __head_fr451_finalise_protection
394 #endif
396         LEDS            0x000a
398 ###############################################################################
400 # set up the runtime environment
402 ###############################################################################
404         # clear the BSS area
405         sethi.p         %hi(__bss_start),gr4
406         setlo           %lo(__bss_start),gr4
407         sethi.p         %hi(_end),gr5
408         setlo           %lo(_end),gr5
409         or.p            gr0,gr0,gr18
410         or              gr0,gr0,gr19
413         stdi            gr18,@(gr4,#0)
414         stdi            gr18,@(gr4,#8)
415         stdi            gr18,@(gr4,#16)
416         stdi.p          gr18,@(gr4,#24)
417         addi            gr4,#24,gr4
418         subcc           gr5,gr4,gr0,icc0
419         bhi             icc0,#2,0b
421         LEDS            0x000b
423         # save the SDRAM details
424         sethi.p         %hi(__sdram_old_base),gr4
425         setlo           %lo(__sdram_old_base),gr4
426         st              gr24,@(gr4,gr0)
428         sethi.p         %hi(__sdram_base),gr5
429         setlo           %lo(__sdram_base),gr5
430         sethi.p         %hi(memory_start),gr4
431         setlo           %lo(memory_start),gr4
432         st              gr5,@(gr4,gr0)
434         add             gr25,gr5,gr25
435         sethi.p         %hi(memory_end),gr4
436         setlo           %lo(memory_end),gr4
437         st              gr25,@(gr4,gr0)
439         # point the TBR at the kernel trap table
440         sethi.p         %hi(__entry_kerneltrap_table),gr4
441         setlo           %lo(__entry_kerneltrap_table),gr4
442         movgs           gr4,tbr
444         # set up the exception frame for init
445         sethi.p         %hi(__kernel_frame0_ptr),gr28
446         setlo           %lo(__kernel_frame0_ptr),gr28
447         sethi.p         %hi(_gp),gr16
448         setlo           %lo(_gp),gr16
449         sethi.p         %hi(__entry_usertrap_table),gr4
450         setlo           %lo(__entry_usertrap_table),gr4
452         lddi            @(gr28,#0),gr28         ; load __frame & current
453         ldi.p           @(gr29,#4),gr15         ; set current_thread
455         or              gr0,gr0,fp
456         or              gr28,gr0,sp
458         sti.p           gr4,@(gr28,REG_TBR)
459         setlos          #ISR_EDE|ISR_DTT_DIVBYZERO|ISR_EMAM_EXCEPTION,gr5
460         movgs           gr5,isr
462         # turn on and off various CPU services
463         movsg           psr,gr22
464         sethi.p         %hi(#PSR_EM|PSR_EF|PSR_CM|PSR_NEM),gr4
465         setlo           %lo(#PSR_EM|PSR_EF|PSR_CM|PSR_NEM),gr4
466         or              gr22,gr4,gr22
467         movgs           gr22,psr
469         andi            gr22,#~(PSR_PIL|PSR_PS|PSR_S),gr22
470         ori             gr22,#PSR_ET,gr22
471         sti             gr22,@(gr28,REG_PSR)
474 ###############################################################################
476 # set up the registers and jump into the kernel
478 ###############################################################################
480         LEDS            0x000c
482         # initialise the processor and the peripherals
483         #call           SYMBOL_NAME(processor_init)
484         #call           SYMBOL_NAME(unit_init)
485         #LEDS           0x0aff
487         sethi.p         #0xe5e5,gr3
488         setlo           #0xe5e5,gr3
489         or.p            gr3,gr0,gr4
490         or              gr3,gr0,gr5
491         or.p            gr3,gr0,gr6
492         or              gr3,gr0,gr7
493         or.p            gr3,gr0,gr8
494         or              gr3,gr0,gr9
495         or.p            gr3,gr0,gr10
496         or              gr3,gr0,gr11
497         or.p            gr3,gr0,gr12
498         or              gr3,gr0,gr13
499         or.p            gr3,gr0,gr14
500         or              gr3,gr0,gr17
501         or.p            gr3,gr0,gr18
502         or              gr3,gr0,gr19
503         or.p            gr3,gr0,gr20
504         or              gr3,gr0,gr21
505         or.p            gr3,gr0,gr23
506         or              gr3,gr0,gr24
507         or.p            gr3,gr0,gr25
508         or              gr3,gr0,gr26
509         or.p            gr3,gr0,gr27
510 #       or              gr3,gr0,gr30
511         or              gr3,gr0,gr31
512         movgs           gr0,lr
513         movgs           gr0,lcr
514         movgs           gr0,ccr
515         movgs           gr0,cccr
517         # initialise the virtual interrupt handling
518         subcc           gr0,gr0,gr0,icc2                /* set Z, clear C */
520 #ifdef CONFIG_MMU
521         movgs           gr3,scr2
522         movgs           gr3,scr3
523 #endif
525         LEDS            0x0fff
527         # invoke the debugging stub if present
528         # - arch/frv/kernel/debug-stub.c will shift control directly to init/main.c
529         #   (it will not return here)
530         break
531         .globl          __debug_stub_init_break
532 __debug_stub_init_break:
534         # however, if you need to use an ICE, and don't care about using any userspace
535         # debugging tools (such as the ptrace syscall), you can just step over the break
536         # above and get to the kernel this way
537         # look at arch/frv/kernel/debug-stub.c: debug_stub_init() to see what you've missed
538         call            start_kernel
540         .globl          __head_end
541 __head_end:
542         .size           _boot, .-_boot
544         # provide a point for GDB to place a break
545         .section        .text..start,"ax"
546         .globl          _start
547         .balign         4
548 _start:
549         call            _boot
551         .previous
552 ###############################################################################
554 # split a tile off of the region defined by GR8-GR9
556 #       ENTRY:                  EXIT:
557 # GR4   -                       IAMPR value representing tile
558 # GR5   -                       DAMPR value representing tile
559 # GR6   -                       IAMLR value representing tile
560 # GR7   -                       DAMLR value representing tile
561 # GR8   region base pointer     [saved]
562 # GR9   region top pointer      updated to exclude new tile
563 # GR11  xAMLR mask              [saved]
564 # GR25  SDRAM size              [saved]
565 # GR30  LED address             [saved]
567 # - GR8 and GR9 should be rounded up/down to the nearest megabyte before calling
569 ###############################################################################
570         .globl          __head_split_region
571         .type           __head_split_region,@function
572 __head_split_region:
573         subcc.p         gr9,gr8,gr4,icc0
574         setlos          #31,gr5
575         scan.p          gr4,gr0,gr6
576         beq             icc0,#0,__head_region_empty
577         sub.p           gr5,gr6,gr6                     ; bit number of highest set bit (1MB=>20)
578         setlos          #1,gr4
579         sll.p           gr4,gr6,gr4                     ; size of region (1 << bitno)
580         subi            gr6,#17,gr6                     ; 1MB => 0x03
581         slli.p          gr6,#4,gr6                      ; 1MB => 0x30
582         sub             gr9,gr4,gr9                     ; move uncovered top down
584         or              gr9,gr6,gr4
585         ori             gr4,#xAMPRx_S_USER|xAMPRx_C_CACHED|xAMPRx_V,gr4
586         or.p            gr4,gr0,gr5
588         and             gr4,gr11,gr6
589         and.p           gr5,gr11,gr7
590         bralr
592 __head_region_empty:
593         or.p            gr0,gr0,gr4
594         or              gr0,gr0,gr5
595         or.p            gr0,gr0,gr6
596         or              gr0,gr0,gr7
597         bralr
598         .size           __head_split_region, .-__head_split_region
600 ###############################################################################
602 # write the 32-bit hex number in GR8 to ttyS0
604 ###############################################################################
605 #if 0
606         .globl          __head_write_to_ttyS0
607         .type           __head_write_to_ttyS0,@function
608 __head_write_to_ttyS0:
609         sethi.p         %hi(0xfeff9c00),gr31
610         setlo           %lo(0xfeff9c00),gr31
611         setlos          #8,gr20
613 0:      ldubi           @(gr31,#5*8),gr21
614         andi            gr21,#0x60,gr21
615         subicc          gr21,#0x60,gr21,icc0
616         bne             icc0,#0,0b
618 1:      srli            gr8,#28,gr21
619         slli            gr8,#4,gr8
621         addi            gr21,#'0',gr21
622         subicc          gr21,#'9',gr0,icc0
623         bls             icc0,#2,2f
624         addi            gr21,#'A'-'0'-10,gr21
626         stbi            gr21,@(gr31,#0*8)
627         subicc          gr20,#1,gr20,icc0
628         bhi             icc0,#2,1b
630         setlos          #'\r',gr21
631         stbi            gr21,@(gr31,#0*8)
633         setlos          #'\n',gr21
634         stbi            gr21,@(gr31,#0*8)
636 3:      ldubi           @(gr31,#5*8),gr21
637         andi            gr21,#0x60,gr21
638         subicc          gr21,#0x60,gr21,icc0
639         bne             icc0,#0,3b
640         bralr
642         .size           __head_write_to_ttyS0, .-__head_write_to_ttyS0
643 #endif