1 /* head.S: kernel entry point for FR-V kernel
3 * Copyright (C) 2003, 2004 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
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.
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>
18 #include <asm/spr-regs.h>
19 #include <asm/mb86943a.h>
20 #include <asm/cache.h>
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
30 ###############################################################################
34 .globl _boot, __head_reference
38 sethi.p %hi(LED_ADDR),gr30
39 setlo %lo(LED_ADDR),gr30
43 # calculate reference address for PC-relative stuff
46 addi gr26,#__head_reference-0b,gr26
48 # invalidate and disable both of the caches and turn off the memory access checking
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
65 # turn the instruction cache back on
66 sethi.p %hi(HSR0_ICE),gr4
67 setlo %lo(HSR0_ICE),gr4
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
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
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 ###############################################################################
112 call __head_fr451_describe_sdram
117 subicc gr5,#3,gr0,icc0
118 beq icc0,#0,__head_fr551_sdram
120 call __head_fr401_describe_sdram
124 call __head_fr555_describe_sdram
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
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
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
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
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
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
199 .balign L1_CACHE_BYTES
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
213 .balign L1_CACHE_BYTES
223 # recalculate reference address
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
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
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
272 # recalculate reference address
275 addi gr26,#__head_reference-0b,gr26
278 ###############################################################################
280 # rearrange the iomem map and set the protection registers
282 ###############################################################################
286 call __head_fr451_set_busctl
288 call __head_fr451_survey_sdram
290 call __head_fr451_set_protection
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
301 call __head_fr401_set_busctl
303 call __head_fr401_survey_sdram
305 call __head_fr401_set_protection
306 bra __head_done_memmap
310 call __head_fr401_set_busctl
312 call __head_fr401_survey_sdram
314 call __head_fr451_set_protection
315 bra __head_done_memmap
319 call __head_fr555_set_busctl
321 call __head_fr555_survey_sdram
323 call __head_fr555_set_protection
329 ###############################################################################
331 # turn the data cache and MMU on
332 # - for the FR451 this'll mean that the window through which the kernel is
335 ###############################################################################
338 #define MMUMODE HSR0_EIMMU|HSR0_EDMMU|HSR0_EXMMU|HSR0_EDAT|HSR0_XEDAT
340 #define MMUMODE HSR0_EIMMU|HSR0_EDMMU
345 sethi.p %hi(MMUMODE),gr4
346 setlo %lo(MMUMODE),gr4
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
361 cmpi gr6,#0x50,icc0 // FR451
363 cmpi gr6,#0x40,icc0 // FR405
366 # turn off write-allocate
367 sethi.p %hi(HSR0_NWA),gr6
368 setlo %lo(HSR0_NWA),gr6
373 #error No default cache configuration set
382 sethi.p %hi(__head_mmu_enabled),gr19
383 setlo %lo(__head_mmu_enabled),gr19
393 call __head_fr451_finalise_protection
398 ###############################################################################
400 # set up the runtime environment
402 ###############################################################################
405 sethi.p %hi(__bss_start),gr4
406 setlo %lo(__bss_start),gr4
407 sethi.p %hi(_end),gr5
416 stdi.p gr18,@(gr4,#24)
418 subcc gr5,gr4,gr0,icc0
423 # save the SDRAM details
424 sethi.p %hi(__sdram_old_base),gr4
425 setlo %lo(__sdram_old_base),gr4
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
435 sethi.p %hi(memory_end),gr4
436 setlo %lo(memory_end),gr4
439 # point the TBR at the kernel trap table
440 sethi.p %hi(__entry_kerneltrap_table),gr4
441 setlo %lo(__entry_kerneltrap_table),gr4
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
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
458 sti.p gr4,@(gr28,REG_TBR)
459 setlos #ISR_EDE|ISR_DTT_DIVBYZERO|ISR_EMAM_EXCEPTION,gr5
462 # turn on and off various CPU services
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
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 ###############################################################################
512 # initialise the virtual interrupt handling
513 subcc gr0,gr0,gr0,icc2 /* set Z, clear C */
522 # invoke the debugging stub if present
523 # - arch/frv/kernel/debug-stub.c will shift control directly to init/main.c
524 # (it will not return here)
526 .globl __debug_stub_init_break
527 __debug_stub_init_break:
529 # however, if you need to use an ICE, and don't care about using any userspace
530 # debugging tools (such as the ptrace syscall), you can just step over the break
531 # above and get to the kernel this way
532 # look at arch/frv/kernel/debug-stub.c: debug_stub_init() to see what you've missed
539 # provide a point for GDB to place a break
540 .section .text..start,"ax"
547 ###############################################################################
549 # split a tile off of the region defined by GR8-GR9
552 # GR4 - IAMPR value representing tile
553 # GR5 - DAMPR value representing tile
554 # GR6 - IAMLR value representing tile
555 # GR7 - DAMLR value representing tile
556 # GR8 region base pointer [saved]
557 # GR9 region top pointer updated to exclude new tile
558 # GR11 xAMLR mask [saved]
559 # GR25 SDRAM size [saved]
560 # GR30 LED address [saved]
562 # - GR8 and GR9 should be rounded up/down to the nearest megabyte before calling
564 ###############################################################################
565 .globl __head_split_region
566 .type __head_split_region,@function
568 subcc.p gr9,gr8,gr4,icc0
571 beq icc0,#0,__head_region_empty
572 sub.p gr5,gr6,gr6 ; bit number of highest set bit (1MB=>20)
574 sll.p gr4,gr6,gr4 ; size of region (1 << bitno)
575 subi gr6,#17,gr6 ; 1MB => 0x03
576 slli.p gr6,#4,gr6 ; 1MB => 0x30
577 sub gr9,gr4,gr9 ; move uncovered top down
580 ori gr4,#xAMPRx_S_USER|xAMPRx_C_CACHED|xAMPRx_V,gr4
593 .size __head_split_region, .-__head_split_region
595 ###############################################################################
597 # write the 32-bit hex number in GR8 to ttyS0
599 ###############################################################################
601 .globl __head_write_to_ttyS0
602 .type __head_write_to_ttyS0,@function
603 __head_write_to_ttyS0:
604 sethi.p %hi(0xfeff9c00),gr31
605 setlo %lo(0xfeff9c00),gr31
608 0: ldubi @(gr31,#5*8),gr21
610 subicc gr21,#0x60,gr21,icc0
617 subicc gr21,#'9',gr0,icc0
619 addi gr21,#'A'-'0'-10,gr21
621 stbi gr21,@(gr31,#0*8)
622 subicc gr20,#1,gr20,icc0
626 stbi gr21,@(gr31,#0*8)
629 stbi gr21,@(gr31,#0*8)
631 3: ldubi @(gr31,#5*8),gr21
633 subicc gr21,#0x60,gr21,icc0
637 .size __head_write_to_ttyS0, .-__head_write_to_ttyS0