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/config.h>
13 #include <linux/threads.h>
14 #include <linux/linkage.h>
15 #include <asm/ptrace.h>
17 #include <asm/spr-regs.h>
18 #include <asm/mb86943a.h>
19 #include <asm/cache.h>
22 ###############################################################################
24 # void _boot(unsigned long magic, char *command_line) __attribute__((noreturn))
26 # - if magic is 0xdead1eaf, then command_line is assumed to point to the kernel
29 ###############################################################################
30 .section .text.head,"ax"
33 .globl _boot, __head_reference
37 sethi.p %hi(LED_ADDR),gr30
38 setlo %lo(LED_ADDR),gr30
42 # calculate reference address for PC-relative stuff
45 addi gr26,#__head_reference-0b,gr26
47 # invalidate and disable both of the caches and turn off the memory access checking
51 sethi.p %hi(~(HSR0_ICE|HSR0_DCE|HSR0_CBM|HSR0_EIMMU|HSR0_EDMMU)),gr4
52 setlo %lo(~(HSR0_ICE|HSR0_DCE|HSR0_CBM|HSR0_EIMMU|HSR0_EDMMU)),gr4
64 # turn the instruction cache back on
65 sethi.p %hi(HSR0_ICE),gr4
66 setlo %lo(HSR0_ICE),gr4
76 # retrieve the parameters (including command line) before we overwrite them
77 sethi.p %hi(0xdead1eaf),gr7
78 setlo %lo(0xdead1eaf),gr7
79 subcc gr7,gr8,gr0,icc0
80 bne icc0,#0,__head_no_parameters
82 sethi.p %hi(redboot_command_line-1),gr6
83 setlo %lo(redboot_command_line-1),gr6
84 sethi.p %hi(__head_reference),gr4
85 setlo %lo(__head_reference),gr4
93 ldubu.p @(gr9,gr5),gr16
94 subicc gr4,#1,gr4,icc0
95 stbu.p gr16,@(gr6,gr5)
96 subicc gr16,#0,gr0,icc1
97 bls icc0,#0,__head_end_cmdline
98 bne icc1,#1,__head_copy_cmdline
101 __head_no_parameters:
103 ###############################################################################
105 # we need to relocate the SDRAM to 0x00000000 (linux) or 0xC0000000 (uClinux)
106 # - note that we're going to have to run entirely out of the icache whilst
107 # fiddling with the SDRAM controller registers
109 ###############################################################################
111 call __head_fr451_describe_sdram
116 subicc gr5,#3,gr0,icc0
117 beq icc0,#0,__head_fr551_sdram
119 call __head_fr401_describe_sdram
123 call __head_fr555_describe_sdram
129 # preload the registers with invalid values in case any DBR/DARS are marked not present
130 sethi.p %hi(0xfe000000),gr17 ; unused SDRAM DBR value
131 setlo %lo(0xfe000000),gr17
137 # consult the SDRAM controller CS address registers
138 cld @(gr14,gr0 ),gr20, cc0,#1 ; DBR0 / DARS0
139 cld @(gr14,gr11),gr21, cc1,#1 ; DBR1 / DARS1
140 cld @(gr14,gr12),gr22, cc2,#1 ; DBR2 / DARS2
141 cld.p @(gr14,gr13),gr23, cc3,#1 ; DBR3 / DARS3
143 sll gr20,gr15,gr20 ; shift values up for FR551
150 # assume the lowest valid CS line to be the SDRAM base and get its address
151 subcc gr20,gr17,gr0,icc0
152 subcc.p gr21,gr17,gr0,icc1
153 subcc gr22,gr17,gr0,icc2
154 subcc.p gr23,gr17,gr0,icc3
155 ckne icc0,cc4 ; T if DBR0 != 0xfe000000
159 cor gr23,gr0,gr24, cc7,#1 ; GR24 = SDRAM base
160 cor gr22,gr0,gr24, cc6,#1
161 cor gr21,gr0,gr24, cc5,#1
162 cor gr20,gr0,gr24, cc4,#1
164 # calculate the displacement required to get the SDRAM into the right place in memory
165 sethi.p %hi(__sdram_base),gr16
166 setlo %lo(__sdram_base),gr16
167 sub gr16,gr24,gr16 ; delta = __sdram_base - DBRx
169 # calculate the new values to go in the controller regs
170 cadd.p gr20,gr16,gr20, cc4,#1 ; DCS#0 (new) = DCS#0 (old) + delta
171 cadd gr21,gr16,gr21, cc5,#1
172 cadd.p gr22,gr16,gr22, cc6,#1
173 cadd gr23,gr16,gr23, cc7,#1
175 srl gr20,gr15,gr20 ; shift values down for FR551
180 # work out the address at which the reg updater resides and lock it into icache
181 # also work out the address the updater will jump to when finished
182 sethi.p %hi(__head_move_sdram-__head_reference),gr18
183 setlo %lo(__head_move_sdram-__head_reference),gr18
184 sethi.p %hi(__head_sdram_moved-__head_reference),gr19
185 setlo %lo(__head_sdram_moved-__head_reference),gr19
188 add.p gr19,gr16,gr19 ; moved = addr + (__sdram_base - DBRx)
189 add gr18,gr5,gr4 ; two cachelines probably required
191 icpl gr18,gr0,#1 ; load and lock the cachelines
198 .balign L1_CACHE_BYTES
200 cst gr20,@(gr14,gr0 ), cc4,#1
201 cst gr21,@(gr14,gr11), cc5,#1
202 cst gr22,@(gr14,gr12), cc6,#1
203 cst gr23,@(gr14,gr13), cc7,#1
204 cld @(gr14,gr0 ),gr20, cc4,#1
205 cld @(gr14,gr11),gr21, cc5,#1
206 cld @(gr14,gr12),gr22, cc4,#1
207 cld @(gr14,gr13),gr23, cc7,#1
212 .balign L1_CACHE_BYTES
222 # recalculate reference address
225 addi gr26,#__head_reference-0b,gr26
228 ###############################################################################
230 # move the kernel image down to the bottom of the SDRAM
232 ###############################################################################
233 sethi.p %hi(__kernel_image_size_no_bss+15),gr4
234 setlo %lo(__kernel_image_size_no_bss+15),gr4
235 srli.p gr4,#4,gr4 ; count
236 or gr26,gr26,gr16 ; source
238 sethi.p %hi(__sdram_base),gr17 ; destination
239 setlo %lo(__sdram_base),gr17
242 sub.p gr16,gr5,gr16 ; adjust src for LDDU
243 sub gr17,gr5,gr17 ; adjust dst for LDDU
245 sethi.p %hi(__head_move_kernel-__head_reference),gr18
246 setlo %lo(__head_move_kernel-__head_reference),gr18
247 sethi.p %hi(__head_kernel_moved-__head_reference+__sdram_base),gr19
248 setlo %lo(__head_kernel_moved-__head_reference+__sdram_base),gr19
255 lddu @(gr16,gr5),gr10
256 lddu @(gr16,gr5),gr12
257 stdu.p gr10,@(gr17,gr5)
258 subicc gr4,#1,gr4,icc0
259 stdu.p gr12,@(gr17,gr5)
260 bhi icc0,#0,__head_move_kernel
271 # recalculate reference address
274 addi gr26,#__head_reference-0b,gr26
277 ###############################################################################
279 # rearrange the iomem map and set the protection registers
281 ###############################################################################
285 call __head_fr451_set_busctl
287 call __head_fr451_survey_sdram
289 call __head_fr451_set_protection
293 srli gr5,#PSR_IMPLE_SHIFT,gr5
294 subicc gr5,#PSR_IMPLE_FR551,gr0,icc0
295 beq icc0,#0,__head_fr555_memmap
296 subicc gr5,#PSR_IMPLE_FR451,gr0,icc0
297 beq icc0,#0,__head_fr451_memmap
300 call __head_fr401_set_busctl
302 call __head_fr401_survey_sdram
304 call __head_fr401_set_protection
305 bra __head_done_memmap
309 call __head_fr401_set_busctl
311 call __head_fr401_survey_sdram
313 call __head_fr451_set_protection
314 bra __head_done_memmap
318 call __head_fr555_set_busctl
320 call __head_fr555_survey_sdram
322 call __head_fr555_set_protection
328 ###############################################################################
330 # turn the data cache and MMU on
331 # - for the FR451 this'll mean that the window through which the kernel is
334 ###############################################################################
337 #define MMUMODE HSR0_EIMMU|HSR0_EDMMU|HSR0_EXMMU|HSR0_EDAT|HSR0_XEDAT
339 #define MMUMODE HSR0_EIMMU|HSR0_EDMMU
344 sethi.p %hi(MMUMODE),gr4
345 setlo %lo(MMUMODE),gr4
348 #if defined(CONFIG_FRV_DEFL_CACHE_WTHRU)
349 sethi.p %hi(HSR0_DCE|HSR0_CBM_WRITE_THRU),gr4
350 setlo %lo(HSR0_DCE|HSR0_CBM_WRITE_THRU),gr4
351 #elif defined(CONFIG_FRV_DEFL_CACHE_WBACK)
352 sethi.p %hi(HSR0_DCE|HSR0_CBM_COPY_BACK),gr4
353 setlo %lo(HSR0_DCE|HSR0_CBM_COPY_BACK),gr4
354 #elif defined(CONFIG_FRV_DEFL_CACHE_WBEHIND)
355 sethi.p %hi(HSR0_DCE|HSR0_CBM_COPY_BACK),gr4
356 setlo %lo(HSR0_DCE|HSR0_CBM_COPY_BACK),gr4
360 cmpi gr6,#0x50,icc0 // FR451
362 cmpi gr6,#0x40,icc0 // FR405
365 # turn off write-allocate
366 sethi.p %hi(HSR0_NWA),gr6
367 setlo %lo(HSR0_NWA),gr6
372 #error No default cache configuration set
381 sethi.p %hi(__head_mmu_enabled),gr19
382 setlo %lo(__head_mmu_enabled),gr19
392 call __head_fr451_finalise_protection
397 ###############################################################################
399 # set up the runtime environment
401 ###############################################################################
404 sethi.p %hi(__bss_start),gr4
405 setlo %lo(__bss_start),gr4
406 sethi.p %hi(_end),gr5
415 stdi.p gr18,@(gr4,#24)
417 subcc gr5,gr4,gr0,icc0
422 # save the SDRAM details
423 sethi.p %hi(__sdram_old_base),gr4
424 setlo %lo(__sdram_old_base),gr4
427 sethi.p %hi(__sdram_base),gr5
428 setlo %lo(__sdram_base),gr5
429 sethi.p %hi(memory_start),gr4
430 setlo %lo(memory_start),gr4
434 sethi.p %hi(memory_end),gr4
435 setlo %lo(memory_end),gr4
438 # point the TBR at the kernel trap table
439 sethi.p %hi(__entry_kerneltrap_table),gr4
440 setlo %lo(__entry_kerneltrap_table),gr4
443 # set up the exception frame for init
444 sethi.p %hi(__kernel_frame0_ptr),gr28
445 setlo %lo(__kernel_frame0_ptr),gr28
446 sethi.p %hi(_gp),gr16
448 sethi.p %hi(__entry_usertrap_table),gr4
449 setlo %lo(__entry_usertrap_table),gr4
451 lddi @(gr28,#0),gr28 ; load __frame & current
452 ldi.p @(gr29,#4),gr15 ; set current_thread
457 sti.p gr4,@(gr28,REG_TBR)
458 setlos #ISR_EDE|ISR_DTT_DIVBYZERO|ISR_EMAM_EXCEPTION,gr5
461 # turn on and off various CPU services
463 sethi.p %hi(#PSR_EM|PSR_EF|PSR_CM|PSR_NEM),gr4
464 setlo %lo(#PSR_EM|PSR_EF|PSR_CM|PSR_NEM),gr4
468 andi gr22,#~(PSR_PIL|PSR_PS|PSR_S),gr22
469 ori gr22,#PSR_ET,gr22
470 sti gr22,@(gr28,REG_PSR)
473 ###############################################################################
475 # set up the registers and jump into the kernel
477 ###############################################################################
481 # initialise the processor and the peripherals
482 #call SYMBOL_NAME(processor_init)
483 #call SYMBOL_NAME(unit_init)
523 # invoke the debugging stub if present
524 # - arch/frv/kernel/debug-stub.c will shift control directly to init/main.c
525 # (it will not return here)
527 .globl __debug_stub_init_break
528 __debug_stub_init_break:
530 # however, if you need to use an ICE, and don't care about using any userspace
531 # debugging tools (such as the ptrace syscall), you can just step over the break
532 # above and get to the kernel this way
533 # look at arch/frv/kernel/debug-stub.c: debug_stub_init() to see what you've missed
540 # provide a point for GDB to place a break
541 .section .text.start,"ax"
548 ###############################################################################
550 # split a tile off of the region defined by GR8-GR9
553 # GR4 - IAMPR value representing tile
554 # GR5 - DAMPR value representing tile
555 # GR6 - IAMLR value representing tile
556 # GR7 - DAMLR value representing tile
557 # GR8 region base pointer [saved]
558 # GR9 region top pointer updated to exclude new tile
559 # GR11 xAMLR mask [saved]
560 # GR25 SDRAM size [saved]
561 # GR30 LED address [saved]
563 # - GR8 and GR9 should be rounded up/down to the nearest megabyte before calling
565 ###############################################################################
566 .globl __head_split_region
567 .type __head_split_region,@function
569 subcc.p gr9,gr8,gr4,icc0
572 beq icc0,#0,__head_region_empty
573 sub.p gr5,gr6,gr6 ; bit number of highest set bit (1MB=>20)
575 sll.p gr4,gr6,gr4 ; size of region (1 << bitno)
576 subi gr6,#17,gr6 ; 1MB => 0x03
577 slli.p gr6,#4,gr6 ; 1MB => 0x30
578 sub gr9,gr4,gr9 ; move uncovered top down
581 ori gr4,#xAMPRx_S_USER|xAMPRx_C_CACHED|xAMPRx_V,gr4
594 .size __head_split_region, .-__head_split_region
596 ###############################################################################
598 # write the 32-bit hex number in GR8 to ttyS0
600 ###############################################################################
602 .globl __head_write_to_ttyS0
603 .type __head_write_to_ttyS0,@function
604 __head_write_to_ttyS0:
605 sethi.p %hi(0xfeff9c00),gr31
606 setlo %lo(0xfeff9c00),gr31
609 0: ldubi @(gr31,#5*8),gr21
611 subicc gr21,#0x60,gr21,icc0
618 subicc gr21,#'9',gr0,icc0
620 addi gr21,#'A'-'0'-10,gr21
622 stbi gr21,@(gr31,#0*8)
623 subicc gr20,#1,gr20,icc0
627 stbi gr21,@(gr31,#0*8)
630 stbi gr21,@(gr31,#0*8)
632 3: ldubi @(gr31,#5*8),gr21
634 subicc gr21,#0x60,gr21,icc0
638 .size __head_write_to_ttyS0, .-__head_write_to_ttyS0