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