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/threads.h>
13 #include <linux/linkage.h>
14 #include <asm/ptrace.h>
16 #include <asm/spr-regs.h>
17 #include <asm/mb86943a.h>
18 #include <asm/cache.h>
21 ###############################################################################
23 # void _boot(unsigned long magic, char *command_line) __attribute__((noreturn))
25 # - if magic is 0xdead1eaf, then command_line is assumed to point to the kernel
28 ###############################################################################
29 .section .text.head,"ax"
32 .globl _boot, __head_reference
36 sethi.p %hi(LED_ADDR),gr30
37 setlo %lo(LED_ADDR),gr30
41 # calculate reference address for PC-relative stuff
44 addi gr26,#__head_reference-0b,gr26
46 # invalidate and disable both of the caches and turn off the memory access checking
50 sethi.p %hi(~(HSR0_ICE|HSR0_DCE|HSR0_CBM|HSR0_EIMMU|HSR0_EDMMU)),gr4
51 setlo %lo(~(HSR0_ICE|HSR0_DCE|HSR0_CBM|HSR0_EIMMU|HSR0_EDMMU)),gr4
63 # turn the instruction cache back on
64 sethi.p %hi(HSR0_ICE),gr4
65 setlo %lo(HSR0_ICE),gr4
75 # retrieve the parameters (including command line) before we overwrite them
76 sethi.p %hi(0xdead1eaf),gr7
77 setlo %lo(0xdead1eaf),gr7
78 subcc gr7,gr8,gr0,icc0
79 bne icc0,#0,__head_no_parameters
81 sethi.p %hi(redboot_command_line-1),gr6
82 setlo %lo(redboot_command_line-1),gr6
83 sethi.p %hi(__head_reference),gr4
84 setlo %lo(__head_reference),gr4
92 ldubu.p @(gr9,gr5),gr16
93 subicc gr4,#1,gr4,icc0
94 stbu.p gr16,@(gr6,gr5)
95 subicc gr16,#0,gr0,icc1
96 bls icc0,#0,__head_end_cmdline
97 bne icc1,#1,__head_copy_cmdline
100 __head_no_parameters:
102 ###############################################################################
104 # we need to relocate the SDRAM to 0x00000000 (linux) or 0xC0000000 (uClinux)
105 # - note that we're going to have to run entirely out of the icache whilst
106 # fiddling with the SDRAM controller registers
108 ###############################################################################
110 call __head_fr451_describe_sdram
115 subicc gr5,#3,gr0,icc0
116 beq icc0,#0,__head_fr551_sdram
118 call __head_fr401_describe_sdram
122 call __head_fr555_describe_sdram
128 # preload the registers with invalid values in case any DBR/DARS are marked not present
129 sethi.p %hi(0xfe000000),gr17 ; unused SDRAM DBR value
130 setlo %lo(0xfe000000),gr17
136 # consult the SDRAM controller CS address registers
137 cld @(gr14,gr0 ),gr20, cc0,#1 ; DBR0 / DARS0
138 cld @(gr14,gr11),gr21, cc1,#1 ; DBR1 / DARS1
139 cld @(gr14,gr12),gr22, cc2,#1 ; DBR2 / DARS2
140 cld.p @(gr14,gr13),gr23, cc3,#1 ; DBR3 / DARS3
142 sll gr20,gr15,gr20 ; shift values up for FR551
149 # assume the lowest valid CS line to be the SDRAM base and get its address
150 subcc gr20,gr17,gr0,icc0
151 subcc.p gr21,gr17,gr0,icc1
152 subcc gr22,gr17,gr0,icc2
153 subcc.p gr23,gr17,gr0,icc3
154 ckne icc0,cc4 ; T if DBR0 != 0xfe000000
158 cor gr23,gr0,gr24, cc7,#1 ; GR24 = SDRAM base
159 cor gr22,gr0,gr24, cc6,#1
160 cor gr21,gr0,gr24, cc5,#1
161 cor gr20,gr0,gr24, cc4,#1
163 # calculate the displacement required to get the SDRAM into the right place in memory
164 sethi.p %hi(__sdram_base),gr16
165 setlo %lo(__sdram_base),gr16
166 sub gr16,gr24,gr16 ; delta = __sdram_base - DBRx
168 # calculate the new values to go in the controller regs
169 cadd.p gr20,gr16,gr20, cc4,#1 ; DCS#0 (new) = DCS#0 (old) + delta
170 cadd gr21,gr16,gr21, cc5,#1
171 cadd.p gr22,gr16,gr22, cc6,#1
172 cadd gr23,gr16,gr23, cc7,#1
174 srl gr20,gr15,gr20 ; shift values down for FR551
179 # work out the address at which the reg updater resides and lock it into icache
180 # also work out the address the updater will jump to when finished
181 sethi.p %hi(__head_move_sdram-__head_reference),gr18
182 setlo %lo(__head_move_sdram-__head_reference),gr18
183 sethi.p %hi(__head_sdram_moved-__head_reference),gr19
184 setlo %lo(__head_sdram_moved-__head_reference),gr19
187 add.p gr19,gr16,gr19 ; moved = addr + (__sdram_base - DBRx)
188 add gr18,gr5,gr4 ; two cachelines probably required
190 icpl gr18,gr0,#1 ; load and lock the cachelines
197 .balign L1_CACHE_BYTES
199 cst gr20,@(gr14,gr0 ), cc4,#1
200 cst gr21,@(gr14,gr11), cc5,#1
201 cst gr22,@(gr14,gr12), cc6,#1
202 cst gr23,@(gr14,gr13), cc7,#1
203 cld @(gr14,gr0 ),gr20, cc4,#1
204 cld @(gr14,gr11),gr21, cc5,#1
205 cld @(gr14,gr12),gr22, cc4,#1
206 cld @(gr14,gr13),gr23, cc7,#1
211 .balign L1_CACHE_BYTES
221 # recalculate reference address
224 addi gr26,#__head_reference-0b,gr26
227 ###############################################################################
229 # move the kernel image down to the bottom of the SDRAM
231 ###############################################################################
232 sethi.p %hi(__kernel_image_size_no_bss+15),gr4
233 setlo %lo(__kernel_image_size_no_bss+15),gr4
234 srli.p gr4,#4,gr4 ; count
235 or gr26,gr26,gr16 ; source
237 sethi.p %hi(__sdram_base),gr17 ; destination
238 setlo %lo(__sdram_base),gr17
241 sub.p gr16,gr5,gr16 ; adjust src for LDDU
242 sub gr17,gr5,gr17 ; adjust dst for LDDU
244 sethi.p %hi(__head_move_kernel-__head_reference),gr18
245 setlo %lo(__head_move_kernel-__head_reference),gr18
246 sethi.p %hi(__head_kernel_moved-__head_reference+__sdram_base),gr19
247 setlo %lo(__head_kernel_moved-__head_reference+__sdram_base),gr19
254 lddu @(gr16,gr5),gr10
255 lddu @(gr16,gr5),gr12
256 stdu.p gr10,@(gr17,gr5)
257 subicc gr4,#1,gr4,icc0
258 stdu.p gr12,@(gr17,gr5)
259 bhi icc0,#0,__head_move_kernel
270 # recalculate reference address
273 addi gr26,#__head_reference-0b,gr26
276 ###############################################################################
278 # rearrange the iomem map and set the protection registers
280 ###############################################################################
284 call __head_fr451_set_busctl
286 call __head_fr451_survey_sdram
288 call __head_fr451_set_protection
292 srli gr5,#PSR_IMPLE_SHIFT,gr5
293 subicc gr5,#PSR_IMPLE_FR551,gr0,icc0
294 beq icc0,#0,__head_fr555_memmap
295 subicc gr5,#PSR_IMPLE_FR451,gr0,icc0
296 beq icc0,#0,__head_fr451_memmap
299 call __head_fr401_set_busctl
301 call __head_fr401_survey_sdram
303 call __head_fr401_set_protection
304 bra __head_done_memmap
308 call __head_fr401_set_busctl
310 call __head_fr401_survey_sdram
312 call __head_fr451_set_protection
313 bra __head_done_memmap
317 call __head_fr555_set_busctl
319 call __head_fr555_survey_sdram
321 call __head_fr555_set_protection
327 ###############################################################################
329 # turn the data cache and MMU on
330 # - for the FR451 this'll mean that the window through which the kernel is
333 ###############################################################################
336 #define MMUMODE HSR0_EIMMU|HSR0_EDMMU|HSR0_EXMMU|HSR0_EDAT|HSR0_XEDAT
338 #define MMUMODE HSR0_EIMMU|HSR0_EDMMU
343 sethi.p %hi(MMUMODE),gr4
344 setlo %lo(MMUMODE),gr4
347 #if defined(CONFIG_FRV_DEFL_CACHE_WTHRU)
348 sethi.p %hi(HSR0_DCE|HSR0_CBM_WRITE_THRU),gr4
349 setlo %lo(HSR0_DCE|HSR0_CBM_WRITE_THRU),gr4
350 #elif defined(CONFIG_FRV_DEFL_CACHE_WBACK)
351 sethi.p %hi(HSR0_DCE|HSR0_CBM_COPY_BACK),gr4
352 setlo %lo(HSR0_DCE|HSR0_CBM_COPY_BACK),gr4
353 #elif defined(CONFIG_FRV_DEFL_CACHE_WBEHIND)
354 sethi.p %hi(HSR0_DCE|HSR0_CBM_COPY_BACK),gr4
355 setlo %lo(HSR0_DCE|HSR0_CBM_COPY_BACK),gr4
359 cmpi gr6,#0x50,icc0 // FR451
361 cmpi gr6,#0x40,icc0 // FR405
364 # turn off write-allocate
365 sethi.p %hi(HSR0_NWA),gr6
366 setlo %lo(HSR0_NWA),gr6
371 #error No default cache configuration set
380 sethi.p %hi(__head_mmu_enabled),gr19
381 setlo %lo(__head_mmu_enabled),gr19
391 call __head_fr451_finalise_protection
396 ###############################################################################
398 # set up the runtime environment
400 ###############################################################################
403 sethi.p %hi(__bss_start),gr4
404 setlo %lo(__bss_start),gr4
405 sethi.p %hi(_end),gr5
414 stdi.p gr18,@(gr4,#24)
416 subcc gr5,gr4,gr0,icc0
421 # save the SDRAM details
422 sethi.p %hi(__sdram_old_base),gr4
423 setlo %lo(__sdram_old_base),gr4
426 sethi.p %hi(__sdram_base),gr5
427 setlo %lo(__sdram_base),gr5
428 sethi.p %hi(memory_start),gr4
429 setlo %lo(memory_start),gr4
433 sethi.p %hi(memory_end),gr4
434 setlo %lo(memory_end),gr4
437 # point the TBR at the kernel trap table
438 sethi.p %hi(__entry_kerneltrap_table),gr4
439 setlo %lo(__entry_kerneltrap_table),gr4
442 # set up the exception frame for init
443 sethi.p %hi(__kernel_frame0_ptr),gr28
444 setlo %lo(__kernel_frame0_ptr),gr28
445 sethi.p %hi(_gp),gr16
447 sethi.p %hi(__entry_usertrap_table),gr4
448 setlo %lo(__entry_usertrap_table),gr4
450 lddi @(gr28,#0),gr28 ; load __frame & current
451 ldi.p @(gr29,#4),gr15 ; set current_thread
456 sti.p gr4,@(gr28,REG_TBR)
457 setlos #ISR_EDE|ISR_DTT_DIVBYZERO|ISR_EMAM_EXCEPTION,gr5
460 # turn on and off various CPU services
462 sethi.p %hi(#PSR_EM|PSR_EF|PSR_CM|PSR_NEM),gr4
463 setlo %lo(#PSR_EM|PSR_EF|PSR_CM|PSR_NEM),gr4
467 andi gr22,#~(PSR_PIL|PSR_PS|PSR_S),gr22
468 ori gr22,#PSR_ET,gr22
469 sti gr22,@(gr28,REG_PSR)
472 ###############################################################################
474 # set up the registers and jump into the kernel
476 ###############################################################################
480 # initialise the processor and the peripherals
481 #call SYMBOL_NAME(processor_init)
482 #call SYMBOL_NAME(unit_init)
515 # initialise the virtual interrupt handling
516 subcc gr0,gr0,gr0,icc2 /* set Z, clear C */
525 # invoke the debugging stub if present
526 # - arch/frv/kernel/debug-stub.c will shift control directly to init/main.c
527 # (it will not return here)
529 .globl __debug_stub_init_break
530 __debug_stub_init_break:
532 # however, if you need to use an ICE, and don't care about using any userspace
533 # debugging tools (such as the ptrace syscall), you can just step over the break
534 # above and get to the kernel this way
535 # look at arch/frv/kernel/debug-stub.c: debug_stub_init() to see what you've missed
542 # provide a point for GDB to place a break
543 .section .text.start,"ax"
550 ###############################################################################
552 # split a tile off of the region defined by GR8-GR9
555 # GR4 - IAMPR value representing tile
556 # GR5 - DAMPR value representing tile
557 # GR6 - IAMLR value representing tile
558 # GR7 - DAMLR value representing tile
559 # GR8 region base pointer [saved]
560 # GR9 region top pointer updated to exclude new tile
561 # GR11 xAMLR mask [saved]
562 # GR25 SDRAM size [saved]
563 # GR30 LED address [saved]
565 # - GR8 and GR9 should be rounded up/down to the nearest megabyte before calling
567 ###############################################################################
568 .globl __head_split_region
569 .type __head_split_region,@function
571 subcc.p gr9,gr8,gr4,icc0
574 beq icc0,#0,__head_region_empty
575 sub.p gr5,gr6,gr6 ; bit number of highest set bit (1MB=>20)
577 sll.p gr4,gr6,gr4 ; size of region (1 << bitno)
578 subi gr6,#17,gr6 ; 1MB => 0x03
579 slli.p gr6,#4,gr6 ; 1MB => 0x30
580 sub gr9,gr4,gr9 ; move uncovered top down
583 ori gr4,#xAMPRx_S_USER|xAMPRx_C_CACHED|xAMPRx_V,gr4
596 .size __head_split_region, .-__head_split_region
598 ###############################################################################
600 # write the 32-bit hex number in GR8 to ttyS0
602 ###############################################################################
604 .globl __head_write_to_ttyS0
605 .type __head_write_to_ttyS0,@function
606 __head_write_to_ttyS0:
607 sethi.p %hi(0xfeff9c00),gr31
608 setlo %lo(0xfeff9c00),gr31
611 0: ldubi @(gr31,#5*8),gr21
613 subicc gr21,#0x60,gr21,icc0
620 subicc gr21,#'9',gr0,icc0
622 addi gr21,#'A'-'0'-10,gr21
624 stbi gr21,@(gr31,#0*8)
625 subicc gr20,#1,gr20,icc0
629 stbi gr21,@(gr31,#0*8)
632 stbi gr21,@(gr31,#0*8)
634 3: ldubi @(gr31,#5*8),gr21
636 subicc gr21,#0x60,gr21,icc0
640 .size __head_write_to_ttyS0, .-__head_write_to_ttyS0