1/* 2 * Copyright (C) 1998 Dan Malek <dmalek@jlc.net> 3 * Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se> 4 * Copyright (C) 2000,2001,2002 Wolfgang Denk <wd@denx.de> 5 * 6 * See file CREDITS for list of people who contributed to this 7 * project. 8 * 9 * This program is free software; you can redistribute it and/or 10 * modify it under the terms of the GNU General Public License as 11 * published by the Free Software Foundation; either version 2 of 12 * the License, or (at your option) any later version. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program; if not, write to the Free Software 21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 22 * MA 02111-1307 USA 23 */ 24 25/* U-Boot - Startup Code for PowerPC based Embedded Boards 26 * 27 * 28 * The processor starts at 0x00000100 and the code is executed 29 * from flash. The code is organized to be at an other address 30 * in memory, but as long we don't jump around before relocating, 31 * board_init lies at a quite high address and when the cpu has 32 * jumped there, everything is ok. 33 * This works because the cpu gives the FLASH (CS0) the whole 34 * address space at startup, and board_init lies as a echo of 35 * the flash somewhere up there in the memory map. 36 * 37 * board_init will change CS0 to be positioned at the correct 38 * address and (s)dram will be positioned at address 0 39 */ 40#include <asm-offsets.h> 41#include <config.h> 42#include <mpc8xx.h> 43#include <timestamp.h> 44#include <version.h> 45 46#define CONFIG_8xx 1 /* needed for Linux kernel header files */ 47#define _LINUX_CONFIG_H 1 /* avoid reading Linux autoconf.h file */ 48 49#include <ppc_asm.tmpl> 50#include <ppc_defs.h> 51 52#include <asm/cache.h> 53#include <asm/mmu.h> 54#include <asm/u-boot.h> 55 56#ifndef CONFIG_IDENT_STRING 57#define CONFIG_IDENT_STRING "" 58#endif 59 60/* We don't want the MMU yet. 61*/ 62#undef MSR_KERNEL 63#define MSR_KERNEL ( MSR_ME | MSR_RI ) /* Machine Check and Recoverable Interr. */ 64 65/* 66 * Set up GOT: Global Offset Table 67 * 68 * Use r12 to access the GOT 69 */ 70 START_GOT 71 GOT_ENTRY(_GOT2_TABLE_) 72 GOT_ENTRY(_FIXUP_TABLE_) 73 74 GOT_ENTRY(_start) 75 GOT_ENTRY(_start_of_vectors) 76 GOT_ENTRY(_end_of_vectors) 77 GOT_ENTRY(transfer_to_handler) 78 79 GOT_ENTRY(__init_end) 80 GOT_ENTRY(__bss_end__) 81 GOT_ENTRY(__bss_start) 82 END_GOT 83 84/* 85 * r3 - 1st arg to board_init(): IMMP pointer 86 * r4 - 2nd arg to board_init(): boot flag 87 */ 88 .text 89 .long 0x27051956 /* U-Boot Magic Number */ 90 .globl version_string 91version_string: 92 .ascii U_BOOT_VERSION 93 .ascii " (", U_BOOT_DATE, " - ", U_BOOT_TIME, ")" 94 .ascii CONFIG_IDENT_STRING, "\0" 95 96 . = EXC_OFF_SYS_RESET 97 .globl _start 98_start: 99 lis r3, CONFIG_SYS_IMMR@h /* position IMMR */ 100 mtspr 638, r3 101 102 /* Initialize machine status; enable machine check interrupt */ 103 /*----------------------------------------------------------------------*/ 104 li r3, MSR_KERNEL /* Set ME, RI flags */ 105 mtmsr r3 106 mtspr SRR1, r3 /* Make SRR1 match MSR */ 107 108 mfspr r3, ICR /* clear Interrupt Cause Register */ 109 110 /* Initialize debug port registers */ 111 /*----------------------------------------------------------------------*/ 112 xor r0, r0, r0 /* Clear R0 */ 113 mtspr LCTRL1, r0 /* Initialize debug port regs */ 114 mtspr LCTRL2, r0 115 mtspr COUNTA, r0 116 mtspr COUNTB, r0 117 118 /* Reset the caches */ 119 /*----------------------------------------------------------------------*/ 120 121 mfspr r3, IC_CST /* Clear error bits */ 122 mfspr r3, DC_CST 123 124 lis r3, IDC_UNALL@h /* Unlock all */ 125 mtspr IC_CST, r3 126 mtspr DC_CST, r3 127 128 lis r3, IDC_INVALL@h /* Invalidate all */ 129 mtspr IC_CST, r3 130 mtspr DC_CST, r3 131 132 lis r3, IDC_DISABLE@h /* Disable data cache */ 133 mtspr DC_CST, r3 134 135#if !defined(CONFIG_SYS_DELAYED_ICACHE) 136 /* On IP860 and PCU E, 137 * we cannot enable IC yet 138 */ 139 lis r3, IDC_ENABLE@h /* Enable instruction cache */ 140#endif 141 mtspr IC_CST, r3 142 143 /* invalidate all tlb's */ 144 /*----------------------------------------------------------------------*/ 145 146 tlbia 147 isync 148 149 /* 150 * Calculate absolute address in FLASH and jump there 151 *----------------------------------------------------------------------*/ 152 153 lis r3, CONFIG_SYS_MONITOR_BASE@h 154 ori r3, r3, CONFIG_SYS_MONITOR_BASE@l 155 addi r3, r3, in_flash - _start + EXC_OFF_SYS_RESET 156 mtlr r3 157 blr 158 159in_flash: 160 161 /* initialize some SPRs that are hard to access from C */ 162 /*----------------------------------------------------------------------*/ 163 164 lis r3, CONFIG_SYS_IMMR@h /* pass IMMR as arg1 to C routine */ 165 ori r1, r3, CONFIG_SYS_INIT_SP_OFFSET /* set up the stack in internal DPRAM */ 166 /* Note: R0 is still 0 here */ 167 stwu r0, -4(r1) /* clear final stack frame so that */ 168 stwu r0, -4(r1) /* stack backtraces terminate cleanly */ 169 170 /* 171 * Disable serialized ifetch and show cycles 172 * (i.e. set processor to normal mode). 173 * This is also a silicon bug workaround, see errata 174 */ 175 176 li r2, 0x0007 177 mtspr ICTRL, r2 178 179 /* Set up debug mode entry */ 180 181 lis r2, CONFIG_SYS_DER@h 182 ori r2, r2, CONFIG_SYS_DER@l 183 mtspr DER, r2 184 185 /* let the C-code set up the rest */ 186 /* */ 187 /* Be careful to keep code relocatable ! */ 188 /*----------------------------------------------------------------------*/ 189 190 GET_GOT /* initialize GOT access */ 191#if defined(__pic__) && __pic__ == 1 192 /* Needed for upcoming -msingle-pic-base */ 193 bl _GLOBAL_OFFSET_TABLE_@local-4 194 mflr r30 195#endif 196 /* r3: IMMR */ 197 bl cpu_init_f /* run low-level CPU init code (from Flash) */ 198 199 bl board_init_f /* run 1st part of board init code (from Flash) */ 200 201 /* NOTREACHED - board_init_f() does not return */ 202 203 204 .globl _start_of_vectors 205_start_of_vectors: 206 207/* Machine check */ 208 STD_EXCEPTION(0x200, MachineCheck, MachineCheckException) 209 210/* Data Storage exception. "Never" generated on the 860. */ 211 STD_EXCEPTION(0x300, DataStorage, UnknownException) 212 213/* Instruction Storage exception. "Never" generated on the 860. */ 214 STD_EXCEPTION(0x400, InstStorage, UnknownException) 215 216/* External Interrupt exception. */ 217 STD_EXCEPTION(0x500, ExtInterrupt, external_interrupt) 218 219/* Alignment exception. */ 220 . = 0x600 221Alignment: 222 EXCEPTION_PROLOG(SRR0, SRR1) 223 mfspr r4,DAR 224 stw r4,_DAR(r21) 225 mfspr r5,DSISR 226 stw r5,_DSISR(r21) 227 addi r3,r1,STACK_FRAME_OVERHEAD 228 EXC_XFER_TEMPLATE(Alignment, AlignmentException, MSR_KERNEL, COPY_EE) 229 230/* Program check exception */ 231 . = 0x700 232ProgramCheck: 233 EXCEPTION_PROLOG(SRR0, SRR1) 234 addi r3,r1,STACK_FRAME_OVERHEAD 235 EXC_XFER_TEMPLATE(ProgramCheck, ProgramCheckException, 236 MSR_KERNEL, COPY_EE) 237 238 /* No FPU on MPC8xx. This exception is not supposed to happen. 239 */ 240 STD_EXCEPTION(0x800, FPUnavailable, UnknownException) 241 242 /* I guess we could implement decrementer, and may have 243 * to someday for timekeeping. 244 */ 245 STD_EXCEPTION(0x900, Decrementer, timer_interrupt) 246 STD_EXCEPTION(0xa00, Trap_0a, UnknownException) 247 STD_EXCEPTION(0xb00, Trap_0b, UnknownException) 248 STD_EXCEPTION(0xc00, SystemCall, UnknownException) 249 STD_EXCEPTION(0xd00, SingleStep, UnknownException) 250 251 STD_EXCEPTION(0xe00, Trap_0e, UnknownException) 252 STD_EXCEPTION(0xf00, Trap_0f, UnknownException) 253 254 /* On the MPC8xx, this is a software emulation interrupt. It occurs 255 * for all unimplemented and illegal instructions. 256 */ 257 STD_EXCEPTION(0x1000, SoftEmu, SoftEmuException) 258 259 STD_EXCEPTION(0x1100, InstructionTLBMiss, UnknownException) 260 STD_EXCEPTION(0x1200, DataTLBMiss, UnknownException) 261 STD_EXCEPTION(0x1300, InstructionTLBError, UnknownException) 262 STD_EXCEPTION(0x1400, DataTLBError, UnknownException) 263 264 STD_EXCEPTION(0x1500, Reserved5, UnknownException) 265 STD_EXCEPTION(0x1600, Reserved6, UnknownException) 266 STD_EXCEPTION(0x1700, Reserved7, UnknownException) 267 STD_EXCEPTION(0x1800, Reserved8, UnknownException) 268 STD_EXCEPTION(0x1900, Reserved9, UnknownException) 269 STD_EXCEPTION(0x1a00, ReservedA, UnknownException) 270 STD_EXCEPTION(0x1b00, ReservedB, UnknownException) 271 272 STD_EXCEPTION(0x1c00, DataBreakpoint, UnknownException) 273 STD_EXCEPTION(0x1d00, InstructionBreakpoint, DebugException) 274 STD_EXCEPTION(0x1e00, PeripheralBreakpoint, UnknownException) 275 STD_EXCEPTION(0x1f00, DevPortBreakpoint, UnknownException) 276 277 278 .globl _end_of_vectors 279_end_of_vectors: 280 281 282 . = 0x2000 283 284/* 285 * This code finishes saving the registers to the exception frame 286 * and jumps to the appropriate handler for the exception. 287 * Register r21 is pointer into trap frame, r1 has new stack pointer. 288 */ 289 .globl transfer_to_handler 290transfer_to_handler: 291 stw r22,_NIP(r21) 292 lis r22,MSR_POW@h 293 andc r23,r23,r22 294 stw r23,_MSR(r21) 295 SAVE_GPR(7, r21) 296 SAVE_4GPRS(8, r21) 297 SAVE_8GPRS(12, r21) 298 SAVE_8GPRS(24, r21) 299 mflr r23 300 andi. r24,r23,0x3f00 /* get vector offset */ 301 stw r24,TRAP(r21) 302 li r22,0 303 stw r22,RESULT(r21) 304 mtspr SPRG2,r22 /* r1 is now kernel sp */ 305 lwz r24,0(r23) /* virtual address of handler */ 306 lwz r23,4(r23) /* where to go when done */ 307 mtspr SRR0,r24 308 mtspr SRR1,r20 309 mtlr r23 310 SYNC 311 rfi /* jump to handler, enable MMU */ 312 313int_return: 314 mfmsr r28 /* Disable interrupts */ 315 li r4,0 316 ori r4,r4,MSR_EE 317 andc r28,r28,r4 318 SYNC /* Some chip revs need this... */ 319 mtmsr r28 320 SYNC 321 lwz r2,_CTR(r1) 322 lwz r0,_LINK(r1) 323 mtctr r2 324 mtlr r0 325 lwz r2,_XER(r1) 326 lwz r0,_CCR(r1) 327 mtspr XER,r2 328 mtcrf 0xFF,r0 329 REST_10GPRS(3, r1) 330 REST_10GPRS(13, r1) 331 REST_8GPRS(23, r1) 332 REST_GPR(31, r1) 333 lwz r2,_NIP(r1) /* Restore environment */ 334 lwz r0,_MSR(r1) 335 mtspr SRR0,r2 336 mtspr SRR1,r0 337 lwz r0,GPR0(r1) 338 lwz r2,GPR2(r1) 339 lwz r1,GPR1(r1) 340 SYNC 341 rfi 342 343/* Cache functions. 344*/ 345 .globl icache_enable 346icache_enable: 347 SYNC 348 lis r3, IDC_INVALL@h 349 mtspr IC_CST, r3 350 lis r3, IDC_ENABLE@h 351 mtspr IC_CST, r3 352 blr 353 354 .globl icache_disable 355icache_disable: 356 SYNC 357 lis r3, IDC_DISABLE@h 358 mtspr IC_CST, r3 359 blr 360 361 .globl icache_status 362icache_status: 363 mfspr r3, IC_CST 364 srwi r3, r3, 31 /* >>31 => select bit 0 */ 365 blr 366 367 .globl dcache_enable 368dcache_enable: 369#if 0 370 SYNC 371#endif 372#if 1 373 lis r3, 0x0400 /* Set cache mode with MMU off */ 374 mtspr MD_CTR, r3 375#endif 376 377 lis r3, IDC_INVALL@h 378 mtspr DC_CST, r3 379#if 0 380 lis r3, DC_SFWT@h 381 mtspr DC_CST, r3 382#endif 383 lis r3, IDC_ENABLE@h 384 mtspr DC_CST, r3 385 blr 386 387 .globl dcache_disable 388dcache_disable: 389 SYNC 390 lis r3, IDC_DISABLE@h 391 mtspr DC_CST, r3 392 lis r3, IDC_INVALL@h 393 mtspr DC_CST, r3 394 blr 395 396 .globl dcache_status 397dcache_status: 398 mfspr r3, DC_CST 399 srwi r3, r3, 31 /* >>31 => select bit 0 */ 400 blr 401 402 .globl dc_read 403dc_read: 404 mtspr DC_ADR, r3 405 mfspr r3, DC_DAT 406 blr 407 408/* 409 * unsigned int get_immr (unsigned int mask) 410 * 411 * return (mask ? (IMMR & mask) : IMMR); 412 */ 413 .globl get_immr 414get_immr: 415 mr r4,r3 /* save mask */ 416 mfspr r3, IMMR /* IMMR */ 417 cmpwi 0,r4,0 /* mask != 0 ? */ 418 beq 4f 419 and r3,r3,r4 /* IMMR & mask */ 4204: 421 blr 422 423 .globl get_pvr 424get_pvr: 425 mfspr r3, PVR 426 blr 427 428 429 .globl wr_ic_cst 430wr_ic_cst: 431 mtspr IC_CST, r3 432 blr 433 434 .globl rd_ic_cst 435rd_ic_cst: 436 mfspr r3, IC_CST 437 blr 438 439 .globl wr_ic_adr 440wr_ic_adr: 441 mtspr IC_ADR, r3 442 blr 443 444 445 .globl wr_dc_cst 446wr_dc_cst: 447 mtspr DC_CST, r3 448 blr 449 450 .globl rd_dc_cst 451rd_dc_cst: 452 mfspr r3, DC_CST 453 blr 454 455 .globl wr_dc_adr 456wr_dc_adr: 457 mtspr DC_ADR, r3 458 blr 459 460/*------------------------------------------------------------------------------*/ 461 462/* 463 * void relocate_code (addr_sp, gd, addr_moni) 464 * 465 * This "function" does not return, instead it continues in RAM 466 * after relocating the monitor code. 467 * 468 * r3 = dest 469 * r4 = src 470 * r5 = length in bytes 471 * r6 = cachelinesize 472 */ 473 .globl relocate_code 474relocate_code: 475 mr r1, r3 /* Set new stack pointer */ 476 mr r9, r4 /* Save copy of Global Data pointer */ 477 mr r10, r5 /* Save copy of Destination Address */ 478 479 GET_GOT 480#if defined(__pic__) && __pic__ == 1 481 /* Needed for upcoming -msingle-pic-base */ 482 bl _GLOBAL_OFFSET_TABLE_@local-4 483 mflr r30 484#endif 485 mr r3, r5 /* Destination Address */ 486 lis r4, CONFIG_SYS_MONITOR_BASE@h /* Source Address */ 487 ori r4, r4, CONFIG_SYS_MONITOR_BASE@l 488 lwz r5, GOT(__init_end) 489 sub r5, r5, r4 490 li r6, CONFIG_SYS_CACHELINE_SIZE /* Cache Line Size */ 491 492 /* 493 * Fix GOT pointer: 494 * 495 * New GOT-PTR = (old GOT-PTR - CONFIG_SYS_MONITOR_BASE) + Destination Address 496 * 497 * Offset: 498 */ 499 sub r15, r10, r4 500 501 /* First our own GOT */ 502 add r12, r12, r15 503 /* then the one used by the C code */ 504 add r30, r30, r15 505 506 /* 507 * Now relocate code 508 */ 509 510 cmplw cr1,r3,r4 511 addi r0,r5,3 512 srwi. r0,r0,2 513 beq cr1,4f /* In place copy is not necessary */ 514 beq 7f /* Protect against 0 count */ 515 mtctr r0 516 bge cr1,2f 517 518 la r8,-4(r4) 519 la r7,-4(r3) 5201: lwzu r0,4(r8) 521 stwu r0,4(r7) 522 bdnz 1b 523 b 4f 524 5252: slwi r0,r0,2 526 add r8,r4,r0 527 add r7,r3,r0 5283: lwzu r0,-4(r8) 529 stwu r0,-4(r7) 530 bdnz 3b 531 532/* 533 * Now flush the cache: note that we must start from a cache aligned 534 * address. Otherwise we might miss one cache line. 535 */ 5364: cmpwi r6,0 537 add r5,r3,r5 538 beq 7f /* Always flush prefetch queue in any case */ 539 subi r0,r6,1 540 andc r3,r3,r0 541 mr r4,r3 5425: dcbst 0,r4 543 add r4,r4,r6 544 cmplw r4,r5 545 blt 5b 546 sync /* Wait for all dcbst to complete on bus */ 547 mr r4,r3 5486: icbi 0,r4 549 add r4,r4,r6 550 cmplw r4,r5 551 blt 6b 5527: sync /* Wait for all icbi to complete on bus */ 553 isync 554 555/* 556 * We are done. Do not return, instead branch to second part of board 557 * initialization, now running from RAM. 558 */ 559 560 addi r0, r10, in_ram - _start + EXC_OFF_SYS_RESET 561 mtlr r0 562 blr 563 564in_ram: 565 566 /* 567 * Relocation Function, r12 point to got2+0x8000 568 * 569 * Adjust got2 pointers, no need to check for 0, this code 570 * already puts a few entries in the table. 571 */ 572 li r0,__got2_entries@sectoff@l 573 la r3,GOT(_GOT2_TABLE_) 574 lwz r11,GOT(_GOT2_TABLE_) 575 mtctr r0 576 sub r11,r3,r11 577 addi r3,r3,-4 5781: lwzu r0,4(r3) 579 cmpwi r0,0 580 beq- 2f 581 add r0,r0,r11 582 stw r0,0(r3) 5832: bdnz 1b 584 585 /* 586 * Now adjust the fixups and the pointers to the fixups 587 * in case we need to move ourselves again. 588 */ 589 li r0,__fixup_entries@sectoff@l 590 lwz r3,GOT(_FIXUP_TABLE_) 591 cmpwi r0,0 592 mtctr r0 593 addi r3,r3,-4 594 beq 4f 5953: lwzu r4,4(r3) 596 lwzux r0,r4,r11 597 cmpwi r0,0 598 add r0,r0,r11 599 stw r4,0(r3) 600 beq- 5f 601 stw r0,0(r4) 6025: bdnz 3b 6034: 604clear_bss: 605 /* 606 * Now clear BSS segment 607 */ 608 lwz r3,GOT(__bss_start) 609 lwz r4,GOT(__bss_end__) 610 611 cmplw 0, r3, r4 612 beq 6f 613 614 li r0, 0 6155: 616 stw r0, 0(r3) 617 addi r3, r3, 4 618 cmplw 0, r3, r4 619 bne 5b 6206: 621 622 mr r3, r9 /* Global Data pointer */ 623 mr r4, r10 /* Destination Address */ 624 bl board_init_r 625 626 /* 627 * Copy exception vector code to low memory 628 * 629 * r3: dest_addr 630 * r7: source address, r8: end address, r9: target address 631 */ 632 .globl trap_init 633trap_init: 634 mflr r4 /* save link register */ 635 GET_GOT 636 lwz r7, GOT(_start) 637 lwz r8, GOT(_end_of_vectors) 638 639 li r9, 0x100 /* reset vector always at 0x100 */ 640 641 cmplw 0, r7, r8 642 bgelr /* return if r7>=r8 - just in case */ 6431: 644 lwz r0, 0(r7) 645 stw r0, 0(r9) 646 addi r7, r7, 4 647 addi r9, r9, 4 648 cmplw 0, r7, r8 649 bne 1b 650 651 /* 652 * relocate `hdlr' and `int_return' entries 653 */ 654 li r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET 655 li r8, Alignment - _start + EXC_OFF_SYS_RESET 6562: 657 bl trap_reloc 658 addi r7, r7, 0x100 /* next exception vector */ 659 cmplw 0, r7, r8 660 blt 2b 661 662 li r7, .L_Alignment - _start + EXC_OFF_SYS_RESET 663 bl trap_reloc 664 665 li r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET 666 bl trap_reloc 667 668 li r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET 669 li r8, SystemCall - _start + EXC_OFF_SYS_RESET 6703: 671 bl trap_reloc 672 addi r7, r7, 0x100 /* next exception vector */ 673 cmplw 0, r7, r8 674 blt 3b 675 676 li r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET 677 li r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET 6784: 679 bl trap_reloc 680 addi r7, r7, 0x100 /* next exception vector */ 681 cmplw 0, r7, r8 682 blt 4b 683 684 mtlr r4 /* restore link register */ 685 blr 686