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 */ 11 12#include <linux/threads.h> 13#include <linux/linkage.h> 14#include <asm/thread_info.h> 15#include <asm/ptrace.h> 16#include <asm/page.h> 17#include <asm/spr-regs.h> 18#include <asm/mb86943a.h> 19#include <asm/cache.h> 20#include "head.inc" 21 22############################################################################### 23# 24# void _boot(unsigned long magic, char *command_line) __attribute__((noreturn)) 25# 26# - if magic is 0xdead1eaf, then command_line is assumed to point to the kernel 27# command line string 28# 29############################################################################### 30 .section .text.head,"ax" 31 .balign 4 32 33 .globl _boot, __head_reference 34 .type _boot,@function 35_boot: 36__head_reference: 37 sethi.p %hi(LED_ADDR),gr30 38 setlo %lo(LED_ADDR),gr30 39 40 LEDS 0x0000 41 42 # calculate reference address for PC-relative stuff 43 call 0f 440: movsg lr,gr26 45 addi gr26,#__head_reference-0b,gr26 46 47 # invalidate and disable both of the caches and turn off the memory access checking 48 dcef @(gr0,gr0),1 49 bar 50 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 53 movsg hsr0,gr5 54 and gr4,gr5,gr5 55 movgs gr5,hsr0 56 movsg hsr0,gr5 57 58 LEDS 0x0001 59 60 icei @(gr0,gr0),1 61 dcei @(gr0,gr0),1 62 bar 63 64 # turn the instruction cache back on 65 sethi.p %hi(HSR0_ICE),gr4 66 setlo %lo(HSR0_ICE),gr4 67 movsg hsr0,gr5 68 or gr4,gr5,gr5 69 movgs gr5,hsr0 70 movsg hsr0,gr5 71 72 bar 73 74 LEDS 0x0002 75 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 81 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 86 sub gr6,gr4,gr6 87 add.p gr6,gr26,gr6 88 subi gr9,#1,gr9 89 setlos.p #511,gr4 90 setlos #1,gr5 91 92__head_copy_cmdline: 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 99__head_end_cmdline: 100 stbu gr0,@(gr6,gr5) 101__head_no_parameters: 102 103############################################################################### 104# 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 108# 109############################################################################### 110#ifdef CONFIG_MMU 111 call __head_fr451_describe_sdram 112 113#else 114 movsg psr,gr5 115 srli gr5,#28,gr5 116 subicc gr5,#3,gr0,icc0 117 beq icc0,#0,__head_fr551_sdram 118 119 call __head_fr401_describe_sdram 120 bra __head_do_sdram 121 122__head_fr551_sdram: 123 call __head_fr555_describe_sdram 124 LEDS 0x000d 125 126__head_do_sdram: 127#endif 128 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 132 or.p gr17,gr0,gr20 133 or gr17,gr0,gr21 134 or.p gr17,gr0,gr22 135 or gr17,gr0,gr23 136 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 142 143 sll gr20,gr15,gr20 ; shift values up for FR551 144 sll gr21,gr15,gr21 145 sll gr22,gr15,gr22 146 sll gr23,gr15,gr23 147 148 LEDS 0x0003 149 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 156 ckne icc1,cc5 157 ckne icc2,cc6 158 ckne icc3,cc7 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 163 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 168 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 174 175 srl gr20,gr15,gr20 ; shift values down for FR551 176 srl gr21,gr15,gr21 177 srl gr22,gr15,gr22 178 srl gr23,gr15,gr23 179 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 186 add.p gr18,gr26,gr18 187 add gr19,gr26,gr19 188 add.p gr19,gr16,gr19 ; moved = addr + (__sdram_base - DBRx) 189 add gr18,gr5,gr4 ; two cachelines probably required 190 191 icpl gr18,gr0,#1 ; load and lock the cachelines 192 icpl gr4,gr0,#1 193 LEDS 0x0004 194 membar 195 bar 196 jmpl @(gr18,gr0) 197 198 .balign L1_CACHE_BYTES 199__head_move_sdram: 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 208 bar 209 membar 210 jmpl @(gr19,gr0) 211 212 .balign L1_CACHE_BYTES 213__head_sdram_moved: 214 icul gr18 215 add gr18,gr5,gr4 216 icul gr4 217 icei @(gr0,gr0),1 218 dcei @(gr0,gr0),1 219 220 LEDS 0x0005 221 222 # recalculate reference address 223 call 0f 2240: movsg lr,gr26 225 addi gr26,#__head_reference-0b,gr26 226 227 228############################################################################### 229# 230# move the kernel image down to the bottom of the SDRAM 231# 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 237 238 sethi.p %hi(__sdram_base),gr17 ; destination 239 setlo %lo(__sdram_base),gr17 240 241 setlos #8,gr5 242 sub.p gr16,gr5,gr16 ; adjust src for LDDU 243 sub gr17,gr5,gr17 ; adjust dst for LDDU 244 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 249 add gr18,gr26,gr18 250 icpl gr18,gr0,#1 251 jmpl @(gr18,gr0) 252 253 .balign 32 254__head_move_kernel: 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 261 jmpl @(gr19,gr0) 262 263 .balign 32 264__head_kernel_moved: 265 icul gr18 266 icei @(gr0,gr0),1 267 dcei @(gr0,gr0),1 268 269 LEDS 0x0006 270 271 # recalculate reference address 272 call 0f 2730: movsg lr,gr26 274 addi gr26,#__head_reference-0b,gr26 275 276 277############################################################################### 278# 279# rearrange the iomem map and set the protection registers 280# 281############################################################################### 282 283#ifdef CONFIG_MMU 284 LEDS 0x3301 285 call __head_fr451_set_busctl 286 LEDS 0x3303 287 call __head_fr451_survey_sdram 288 LEDS 0x3305 289 call __head_fr451_set_protection 290 291#else 292 movsg psr,gr5 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 298 299 LEDS 0x3101 300 call __head_fr401_set_busctl 301 LEDS 0x3103 302 call __head_fr401_survey_sdram 303 LEDS 0x3105 304 call __head_fr401_set_protection 305 bra __head_done_memmap 306 307__head_fr451_memmap: 308 LEDS 0x3301 309 call __head_fr401_set_busctl 310 LEDS 0x3303 311 call __head_fr401_survey_sdram 312 LEDS 0x3305 313 call __head_fr451_set_protection 314 bra __head_done_memmap 315 316__head_fr555_memmap: 317 LEDS 0x3501 318 call __head_fr555_set_busctl 319 LEDS 0x3503 320 call __head_fr555_survey_sdram 321 LEDS 0x3505 322 call __head_fr555_set_protection 323 324__head_done_memmap: 325#endif 326 LEDS 0x0007 327 328############################################################################### 329# 330# turn the data cache and MMU on 331# - for the FR451 this'll mean that the window through which the kernel is 332# viewed will change 333# 334############################################################################### 335 336#ifdef CONFIG_MMU 337#define MMUMODE HSR0_EIMMU|HSR0_EDMMU|HSR0_EXMMU|HSR0_EDAT|HSR0_XEDAT 338#else 339#define MMUMODE HSR0_EIMMU|HSR0_EDMMU 340#endif 341 342 movsg hsr0,gr5 343 344 sethi.p %hi(MMUMODE),gr4 345 setlo %lo(MMUMODE),gr4 346 or gr4,gr5,gr5 347 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 357 358 movsg psr,gr6 359 srli gr6,#24,gr6 360 cmpi gr6,#0x50,icc0 // FR451 361 beq icc0,#0,0f 362 cmpi gr6,#0x40,icc0 // FR405 363 bne icc0,#0,1f 3640: 365 # turn off write-allocate 366 sethi.p %hi(HSR0_NWA),gr6 367 setlo %lo(HSR0_NWA),gr6 368 or gr4,gr6,gr4 3691: 370 371#else 372#error No default cache configuration set 373#endif 374 375 or gr4,gr5,gr5 376 movgs gr5,hsr0 377 bar 378 379 LEDS 0x0008 380 381 sethi.p %hi(__head_mmu_enabled),gr19 382 setlo %lo(__head_mmu_enabled),gr19 383 jmpl @(gr19,gr0) 384 385__head_mmu_enabled: 386 icei @(gr0,gr0),#1 387 dcei @(gr0,gr0),#1 388 389 LEDS 0x0009 390 391#ifdef CONFIG_MMU 392 call __head_fr451_finalise_protection 393#endif 394 395 LEDS 0x000a 396 397############################################################################### 398# 399# set up the runtime environment 400# 401############################################################################### 402 403 # clear the BSS area 404 sethi.p %hi(__bss_start),gr4 405 setlo %lo(__bss_start),gr4 406 sethi.p %hi(_end),gr5 407 setlo %lo(_end),gr5 408 or.p gr0,gr0,gr18 409 or gr0,gr0,gr19 410 4110: 412 stdi gr18,@(gr4,#0) 413 stdi gr18,@(gr4,#8) 414 stdi gr18,@(gr4,#16) 415 stdi.p gr18,@(gr4,#24) 416 addi gr4,#24,gr4 417 subcc gr5,gr4,gr0,icc0 418 bhi icc0,#2,0b 419 420 LEDS 0x000b 421 422 # save the SDRAM details 423 sethi.p %hi(__sdram_old_base),gr4 424 setlo %lo(__sdram_old_base),gr4 425 st gr24,@(gr4,gr0) 426 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 431 st gr5,@(gr4,gr0) 432 433 add gr25,gr5,gr25 434 sethi.p %hi(memory_end),gr4 435 setlo %lo(memory_end),gr4 436 st gr25,@(gr4,gr0) 437 438 # point the TBR at the kernel trap table 439 sethi.p %hi(__entry_kerneltrap_table),gr4 440 setlo %lo(__entry_kerneltrap_table),gr4 441 movgs gr4,tbr 442 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 447 setlo %lo(_gp),gr16 448 sethi.p %hi(__entry_usertrap_table),gr4 449 setlo %lo(__entry_usertrap_table),gr4 450 451 lddi @(gr28,#0),gr28 ; load __frame & current 452 ldi.p @(gr29,#4),gr15 ; set current_thread 453 454 or gr0,gr0,fp 455 or gr28,gr0,sp 456 457 sti.p gr4,@(gr28,REG_TBR) 458 setlos #ISR_EDE|ISR_DTT_DIVBYZERO|ISR_EMAM_EXCEPTION,gr5 459 movgs gr5,isr 460 461 # turn on and off various CPU services 462 movsg psr,gr22 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 465 or gr22,gr4,gr22 466 movgs gr22,psr 467 468 andi gr22,#~(PSR_PIL|PSR_PS|PSR_S),gr22 469 ori gr22,#PSR_ET,gr22 470 sti gr22,@(gr28,REG_PSR) 471 472 473############################################################################### 474# 475# set up the registers and jump into the kernel 476# 477############################################################################### 478 479 LEDS 0x000c 480 481 # initialise the processor and the peripherals 482 #call SYMBOL_NAME(processor_init) 483 #call SYMBOL_NAME(unit_init) 484 #LEDS 0x0aff 485 486 sethi.p #0xe5e5,gr3 487 setlo #0xe5e5,gr3 488 or.p gr3,gr0,gr4 489 or gr3,gr0,gr5 490 or.p gr3,gr0,gr6 491 or gr3,gr0,gr7 492 or.p gr3,gr0,gr8 493 or gr3,gr0,gr9 494 or.p gr3,gr0,gr10 495 or gr3,gr0,gr11 496 or.p gr3,gr0,gr12 497 or gr3,gr0,gr13 498 or.p gr3,gr0,gr14 499 or gr3,gr0,gr17 500 or.p gr3,gr0,gr18 501 or gr3,gr0,gr19 502 or.p gr3,gr0,gr20 503 or gr3,gr0,gr21 504 or.p gr3,gr0,gr23 505 or gr3,gr0,gr24 506 or.p gr3,gr0,gr25 507 or gr3,gr0,gr26 508 or.p gr3,gr0,gr27 509# or gr3,gr0,gr30 510 or gr3,gr0,gr31 511 movgs gr0,lr 512 movgs gr0,lcr 513 movgs gr0,ccr 514 movgs gr0,cccr 515 516 # initialise the virtual interrupt handling 517 subcc gr0,gr0,gr0,icc2 /* set Z, clear C */ 518 519#ifdef CONFIG_MMU 520 movgs gr3,scr2 521 movgs gr3,scr3 522#endif 523 524 LEDS 0x0fff 525 526 # invoke the debugging stub if present 527 # - arch/frv/kernel/debug-stub.c will shift control directly to init/main.c 528 # (it will not return here) 529 break 530 .globl __debug_stub_init_break 531__debug_stub_init_break: 532 533 # however, if you need to use an ICE, and don't care about using any userspace 534 # debugging tools (such as the ptrace syscall), you can just step over the break 535 # above and get to the kernel this way 536 # look at arch/frv/kernel/debug-stub.c: debug_stub_init() to see what you've missed 537 call start_kernel 538 539 .globl __head_end 540__head_end: 541 .size _boot, .-_boot 542 543 # provide a point for GDB to place a break 544 .section .text.start,"ax" 545 .globl _start 546 .balign 4 547_start: 548 call _boot 549 550 .previous 551############################################################################### 552# 553# split a tile off of the region defined by GR8-GR9 554# 555# ENTRY: EXIT: 556# GR4 - IAMPR value representing tile 557# GR5 - DAMPR value representing tile 558# GR6 - IAMLR value representing tile 559# GR7 - DAMLR value representing tile 560# GR8 region base pointer [saved] 561# GR9 region top pointer updated to exclude new tile 562# GR11 xAMLR mask [saved] 563# GR25 SDRAM size [saved] 564# GR30 LED address [saved] 565# 566# - GR8 and GR9 should be rounded up/down to the nearest megabyte before calling 567# 568############################################################################### 569 .globl __head_split_region 570 .type __head_split_region,@function 571__head_split_region: 572 subcc.p gr9,gr8,gr4,icc0 573 setlos #31,gr5 574 scan.p gr4,gr0,gr6 575 beq icc0,#0,__head_region_empty 576 sub.p gr5,gr6,gr6 ; bit number of highest set bit (1MB=>20) 577 setlos #1,gr4 578 sll.p gr4,gr6,gr4 ; size of region (1 << bitno) 579 subi gr6,#17,gr6 ; 1MB => 0x03 580 slli.p gr6,#4,gr6 ; 1MB => 0x30 581 sub gr9,gr4,gr9 ; move uncovered top down 582 583 or gr9,gr6,gr4 584 ori gr4,#xAMPRx_S_USER|xAMPRx_C_CACHED|xAMPRx_V,gr4 585 or.p gr4,gr0,gr5 586 587 and gr4,gr11,gr6 588 and.p gr5,gr11,gr7 589 bralr 590 591__head_region_empty: 592 or.p gr0,gr0,gr4 593 or gr0,gr0,gr5 594 or.p gr0,gr0,gr6 595 or gr0,gr0,gr7 596 bralr 597 .size __head_split_region, .-__head_split_region 598 599############################################################################### 600# 601# write the 32-bit hex number in GR8 to ttyS0 602# 603############################################################################### 604