uboot/arch/powerpc/cpu/mpc8260/start.S
<<
>>
Prefs
   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/*
  26 *  U-Boot - Startup Code for MPC8260 PowerPC based Embedded Boards
  27 */
  28#include <asm-offsets.h>
  29#include <config.h>
  30#include <mpc8260.h>
  31#include <version.h>
  32
  33#define CONFIG_8260 1           /* needed for Linux kernel header files */
  34#define _LINUX_CONFIG_H 1       /* avoid reading Linux autoconf.h file  */
  35
  36#include <ppc_asm.tmpl>
  37#include <ppc_defs.h>
  38
  39#include <asm/cache.h>
  40#include <asm/mmu.h>
  41#include <asm/u-boot.h>
  42
  43/* We don't want the  MMU yet.
  44*/
  45#undef  MSR_KERNEL
  46/* Floating Point enable, Machine Check and Recoverable Interr. */
  47#ifdef DEBUG
  48#define MSR_KERNEL (MSR_FP|MSR_RI)
  49#else
  50#define MSR_KERNEL (MSR_FP|MSR_ME|MSR_RI)
  51#endif
  52
  53/*
  54 * Set up GOT: Global Offset Table
  55 *
  56 * Use r12 to access the GOT
  57 */
  58        START_GOT
  59        GOT_ENTRY(_GOT2_TABLE_)
  60        GOT_ENTRY(_FIXUP_TABLE_)
  61
  62        GOT_ENTRY(_start)
  63        GOT_ENTRY(_start_of_vectors)
  64        GOT_ENTRY(_end_of_vectors)
  65        GOT_ENTRY(transfer_to_handler)
  66
  67        GOT_ENTRY(__init_end)
  68        GOT_ENTRY(__bss_end__)
  69        GOT_ENTRY(__bss_start)
  70#if defined(CONFIG_HYMOD)
  71        GOT_ENTRY(environment)
  72#endif
  73        END_GOT
  74
  75/*
  76 * Version string - must be in data segment because MPC8260 uses the first
  77 * 256 bytes for the Hard Reset Configuration Word table (see below).
  78 * Similarly, can't have the U-Boot Magic Number as the first thing in
  79 * the image - don't know how this will affect the image tools, but I guess
  80 * I'll find out soon
  81 */
  82        .data
  83        .globl  version_string
  84version_string:
  85        .ascii U_BOOT_VERSION_STRING, "\0"
  86
  87/*
  88 *  Hard Reset Configuration Word (HRCW) table
  89 *
  90 *  The Hard Reset Configuration Word (HRCW) sets a number of useful things
  91 *  such as whether there is an external memory controller, whether the
  92 *  PowerPC core is disabled (i.e. only the communications processor is
  93 *  active, accessed by another CPU on the bus), whether using external
  94 *  arbitration, external bus mode, boot port size, core initial prefix,
  95 *  internal space base, boot memory space, etc.
  96 *
  97 *  These things dictate where the processor begins execution, where the
  98 *  boot ROM appears in memory, the memory controller setup when access
  99 *  boot ROM, etc. The HRCW is *extremely* important.
 100 *
 101 *  The HRCW is read from the bus during reset. One CPU on the bus will
 102 *  be a hard reset configuration master, any others will be hard reset
 103 *  configuration slaves. The master reads eight HRCWs from flash during
 104 *  reset - the first it uses for itself, the other 7 it communicates to
 105 *  up to 7 configuration slaves by some complicated mechanism, which is
 106 *  not really important here.
 107 *
 108 *  The configuration master performs 32 successive reads starting at address
 109 *  0 and incrementing by 8 each read (i.e. on 64 bit boundaries) but only 8
 110 *  bits is read, and always from byte lane D[0-7] (so that port size of the
 111 *  boot device does not matter). The first four reads form the 32 bit HRCW
 112 *  for the master itself. The second four reads form the HRCW for the first
 113 *  slave, and so on, up to seven slaves. The 32 bit HRCW is formed by
 114 *  concatenating the four bytes, with the first read placed in byte 0 (the
 115 *  most significant byte), and so on with the fourth read placed in byte 3
 116 *  (the least significant byte).
 117 */
 118#define _HRCW_TABLE_ENTRY(w)            \
 119        .fill   8,1,(((w)>>24)&0xff);   \
 120        .fill   8,1,(((w)>>16)&0xff);   \
 121        .fill   8,1,(((w)>> 8)&0xff);   \
 122        .fill   8,1,(((w)    )&0xff)
 123        .text
 124        .globl  _hrcw_table
 125_hrcw_table:
 126        _HRCW_TABLE_ENTRY(CONFIG_SYS_HRCW_MASTER)
 127        _HRCW_TABLE_ENTRY(CONFIG_SYS_HRCW_SLAVE1)
 128        _HRCW_TABLE_ENTRY(CONFIG_SYS_HRCW_SLAVE2)
 129        _HRCW_TABLE_ENTRY(CONFIG_SYS_HRCW_SLAVE3)
 130        _HRCW_TABLE_ENTRY(CONFIG_SYS_HRCW_SLAVE4)
 131        _HRCW_TABLE_ENTRY(CONFIG_SYS_HRCW_SLAVE5)
 132        _HRCW_TABLE_ENTRY(CONFIG_SYS_HRCW_SLAVE6)
 133        _HRCW_TABLE_ENTRY(CONFIG_SYS_HRCW_SLAVE7)
 134/*
 135 *  After configuration, a system reset exception is executed using the
 136 *  vector at offset 0x100 relative to the base set by MSR[IP]. If MSR[IP]
 137 *  is 0, the base address is 0x00000000. If MSR[IP] is 1, the base address
 138 *  is 0xfff00000. In the case of a Power On Reset or Hard Reset, the value
 139 *  of MSR[IP] is determined by the CIP field in the HRCW.
 140 *
 141 *  Other bits in the HRCW set up the Base Address and Port Size in BR0.
 142 *  This determines the location of the boot ROM (flash or EPROM) in the
 143 *  processor's address space at boot time. As long as the HRCW is set up
 144 *  so that we eventually end up executing the code below when the processor
 145 *  executes the reset exception, the actual values used should not matter.
 146 *
 147 *  Once we have got here, the address mask in OR0 is cleared so that the
 148 *  bottom 32K of the boot ROM is effectively repeated all throughout the
 149 *  processor's address space, after which we can jump to the absolute
 150 *  address at which the boot ROM was linked at compile time, and proceed
 151 *  to initialise the memory controller without worrying if the rug will be
 152 *  pulled out from under us, so to speak (it will be fine as long as we
 153 *  configure BR0 with the same boot ROM link address).
 154 */
 155        . = EXC_OFF_SYS_RESET
 156
 157        .globl  _start
 158_start:
 159#if defined(CONFIG_MPC8260ADS) && defined(CONFIG_SYS_DEFAULT_IMMR)
 160        lis     r3, CONFIG_SYS_DEFAULT_IMMR@h
 161        nop
 162        lwz     r4, 0(r3)
 163        nop
 164        rlwinm  r4, r4, 0, 8, 5
 165        nop
 166        oris    r4, r4, 0x0200
 167        nop
 168        stw     r4, 0(r3)
 169        nop
 170#endif /* CONFIG_MPC8260ADS && CONFIG_SYS_DEFAULT_IMMR */
 171
 172        mfmsr   r5                      /* save msr contents            */
 173
 174#if defined(CONFIG_COGENT)
 175        /* this is what the cogent EPROM does */
 176        li      r0, 0
 177        mtmsr   r0
 178        isync
 179        bl      cogent_init_8260
 180#endif  /* CONFIG_COGENT */
 181
 182#if defined(CONFIG_SYS_DEFAULT_IMMR)
 183        lis     r3, CONFIG_SYS_IMMR@h
 184        ori     r3, r3, CONFIG_SYS_IMMR@l
 185        lis     r4, CONFIG_SYS_DEFAULT_IMMR@h
 186        stw     r3, 0x1A8(r4)
 187#endif /* CONFIG_SYS_DEFAULT_IMMR */
 188
 189        /* Initialise the MPC8260 processor core                        */
 190        /*--------------------------------------------------------------*/
 191
 192        bl      init_8260_core
 193
 194#ifndef CONFIG_SYS_RAMBOOT
 195        /* When booting from ROM (Flash or EPROM), clear the            */
 196        /* Address Mask in OR0 so ROM appears everywhere                */
 197        /*--------------------------------------------------------------*/
 198
 199        lis     r3, (CONFIG_SYS_IMMR+IM_REGBASE)@h
 200        lwz     r4, IM_OR0@l(r3)
 201        li      r5, 0x7fff
 202        and     r4, r4, r5
 203        stw     r4, IM_OR0@l(r3)
 204
 205        /* Calculate absolute address in FLASH and jump there           */
 206        /*--------------------------------------------------------------*/
 207
 208        lis     r3, CONFIG_SYS_MONITOR_BASE@h
 209        ori     r3, r3, CONFIG_SYS_MONITOR_BASE@l
 210        addi    r3, r3, in_flash - _start + EXC_OFF_SYS_RESET
 211        mtlr    r3
 212        blr
 213
 214in_flash:
 215#endif  /* CONFIG_SYS_RAMBOOT */
 216
 217        /* initialize some things that are hard to access from C        */
 218        /*--------------------------------------------------------------*/
 219
 220        lis     r3, CONFIG_SYS_IMMR@h           /* set up stack in internal DPRAM */
 221        ori     r1, r3, CONFIG_SYS_INIT_SP_OFFSET
 222        li      r0, 0                   /* Make room for stack frame header and */
 223        stwu    r0, -4(r1)              /* clear final stack frame so that      */
 224        stwu    r0, -4(r1)              /* stack backtraces terminate cleanly   */
 225
 226        /* let the C-code set up the rest                               */
 227        /*                                                              */
 228        /* Be careful to keep code relocatable !                        */
 229        /*--------------------------------------------------------------*/
 230
 231        GET_GOT                 /* initialize GOT access                */
 232
 233        /* r3: IMMR */
 234        bl      cpu_init_f      /* run low-level CPU init code (in Flash)*/
 235
 236#ifdef DEBUG
 237        bl      init_debug      /* set up debugging stuff               */
 238#endif
 239
 240        bl      board_init_f    /* run 1st part of board init code (in Flash)*/
 241
 242        /* NOTREACHED - board_init_f() does not return */
 243
 244/*
 245 * Vector Table
 246 */
 247
 248        .globl  _start_of_vectors
 249_start_of_vectors:
 250
 251/* Machine check */
 252        STD_EXCEPTION(0x200, MachineCheck, MachineCheckException)
 253
 254/* Data Storage exception. */
 255        STD_EXCEPTION(0x300, DataStorage, UnknownException)
 256
 257/* Instruction Storage exception. */
 258        STD_EXCEPTION(0x400, InstStorage, UnknownException)
 259
 260/* External Interrupt exception. */
 261        STD_EXCEPTION(0x500, ExtInterrupt, external_interrupt)
 262
 263/* Alignment exception. */
 264        . = 0x600
 265Alignment:
 266        EXCEPTION_PROLOG(SRR0, SRR1)
 267        mfspr   r4,DAR
 268        stw     r4,_DAR(r21)
 269        mfspr   r5,DSISR
 270        stw     r5,_DSISR(r21)
 271        addi    r3,r1,STACK_FRAME_OVERHEAD
 272        EXC_XFER_TEMPLATE(Alignment, AlignmentException, MSR_KERNEL, COPY_EE)
 273
 274/* Program check exception */
 275        . = 0x700
 276ProgramCheck:
 277        EXCEPTION_PROLOG(SRR0, SRR1)
 278        addi    r3,r1,STACK_FRAME_OVERHEAD
 279        EXC_XFER_TEMPLATE(ProgramCheck, ProgramCheckException,
 280                MSR_KERNEL, COPY_EE)
 281
 282        STD_EXCEPTION(0x800, FPUnavailable, UnknownException)
 283
 284        /* I guess we could implement decrementer, and may have
 285         * to someday for timekeeping.
 286         */
 287        STD_EXCEPTION(0x900, Decrementer, timer_interrupt)
 288
 289        STD_EXCEPTION(0xa00, Trap_0a, UnknownException)
 290        STD_EXCEPTION(0xb00, Trap_0b, UnknownException)
 291        STD_EXCEPTION(0xc00, SystemCall, UnknownException)
 292        STD_EXCEPTION(0xd00, SingleStep, UnknownException)
 293
 294        STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
 295        STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
 296
 297        STD_EXCEPTION(0x1000, InstructionTLBMiss, UnknownException)
 298        STD_EXCEPTION(0x1100, DataLoadTLBMiss, UnknownException)
 299        STD_EXCEPTION(0x1200, DataStoreTLBMiss, UnknownException)
 300#ifdef DEBUG
 301        . = 0x1300
 302        /*
 303         * This exception occurs when the program counter matches the
 304         * Instruction Address Breakpoint Register (IABR).
 305         *
 306         * I want the cpu to halt if this occurs so I can hunt around
 307         * with the debugger and look at things.
 308         *
 309         * When DEBUG is defined, both machine check enable (in the MSR)
 310         * and checkstop reset enable (in the reset mode register) are
 311         * turned off and so a checkstop condition will result in the cpu
 312         * halting.
 313         *
 314         * I force the cpu into a checkstop condition by putting an illegal
 315         * instruction here (at least this is the theory).
 316         *
 317         * well - that didnt work, so just do an infinite loop!
 318         */
 3191:      b       1b
 320#else
 321        STD_EXCEPTION(0x1300, InstructionBreakpoint, DebugException)
 322#endif
 323        STD_EXCEPTION(0x1400, SMI, UnknownException)
 324
 325        STD_EXCEPTION(0x1500, Trap_15, UnknownException)
 326        STD_EXCEPTION(0x1600, Trap_16, UnknownException)
 327        STD_EXCEPTION(0x1700, Trap_17, UnknownException)
 328        STD_EXCEPTION(0x1800, Trap_18, UnknownException)
 329        STD_EXCEPTION(0x1900, Trap_19, UnknownException)
 330        STD_EXCEPTION(0x1a00, Trap_1a, UnknownException)
 331        STD_EXCEPTION(0x1b00, Trap_1b, UnknownException)
 332        STD_EXCEPTION(0x1c00, Trap_1c, UnknownException)
 333        STD_EXCEPTION(0x1d00, Trap_1d, UnknownException)
 334        STD_EXCEPTION(0x1e00, Trap_1e, UnknownException)
 335        STD_EXCEPTION(0x1f00, Trap_1f, UnknownException)
 336        STD_EXCEPTION(0x2000, Trap_20, UnknownException)
 337        STD_EXCEPTION(0x2100, Trap_21, UnknownException)
 338        STD_EXCEPTION(0x2200, Trap_22, UnknownException)
 339        STD_EXCEPTION(0x2300, Trap_23, UnknownException)
 340        STD_EXCEPTION(0x2400, Trap_24, UnknownException)
 341        STD_EXCEPTION(0x2500, Trap_25, UnknownException)
 342        STD_EXCEPTION(0x2600, Trap_26, UnknownException)
 343        STD_EXCEPTION(0x2700, Trap_27, UnknownException)
 344        STD_EXCEPTION(0x2800, Trap_28, UnknownException)
 345        STD_EXCEPTION(0x2900, Trap_29, UnknownException)
 346        STD_EXCEPTION(0x2a00, Trap_2a, UnknownException)
 347        STD_EXCEPTION(0x2b00, Trap_2b, UnknownException)
 348        STD_EXCEPTION(0x2c00, Trap_2c, UnknownException)
 349        STD_EXCEPTION(0x2d00, Trap_2d, UnknownException)
 350        STD_EXCEPTION(0x2e00, Trap_2e, UnknownException)
 351        STD_EXCEPTION(0x2f00, Trap_2f, UnknownException)
 352
 353
 354        .globl  _end_of_vectors
 355_end_of_vectors:
 356
 357        . = 0x3000
 358
 359/*
 360 * This code finishes saving the registers to the exception frame
 361 * and jumps to the appropriate handler for the exception.
 362 * Register r21 is pointer into trap frame, r1 has new stack pointer.
 363 */
 364        .globl  transfer_to_handler
 365transfer_to_handler:
 366        stw     r22,_NIP(r21)
 367        lis     r22,MSR_POW@h
 368        andc    r23,r23,r22
 369        stw     r23,_MSR(r21)
 370        SAVE_GPR(7, r21)
 371        SAVE_4GPRS(8, r21)
 372        SAVE_8GPRS(12, r21)
 373        SAVE_8GPRS(24, r21)
 374        mflr    r23
 375        andi.   r24,r23,0x3f00          /* get vector offset */
 376        stw     r24,TRAP(r21)
 377        li      r22,0
 378        stw     r22,RESULT(r21)
 379        lwz     r24,0(r23)              /* virtual address of handler */
 380        lwz     r23,4(r23)              /* where to go when done */
 381        mtspr   SRR0,r24
 382        mtspr   SRR1,r20
 383        mtlr    r23
 384        SYNC
 385        rfi                             /* jump to handler, enable MMU */
 386
 387int_return:
 388        mfmsr   r28             /* Disable interrupts */
 389        li      r4,0
 390        ori     r4,r4,MSR_EE
 391        andc    r28,r28,r4
 392        SYNC                    /* Some chip revs need this... */
 393        mtmsr   r28
 394        SYNC
 395        lwz     r2,_CTR(r1)
 396        lwz     r0,_LINK(r1)
 397        mtctr   r2
 398        mtlr    r0
 399        lwz     r2,_XER(r1)
 400        lwz     r0,_CCR(r1)
 401        mtspr   XER,r2
 402        mtcrf   0xFF,r0
 403        REST_10GPRS(3, r1)
 404        REST_10GPRS(13, r1)
 405        REST_8GPRS(23, r1)
 406        REST_GPR(31, r1)
 407        lwz     r2,_NIP(r1)     /* Restore environment */
 408        lwz     r0,_MSR(r1)
 409        mtspr   SRR0,r2
 410        mtspr   SRR1,r0
 411        lwz     r0,GPR0(r1)
 412        lwz     r2,GPR2(r1)
 413        lwz     r1,GPR1(r1)
 414        SYNC
 415        rfi
 416
 417#if defined(CONFIG_COGENT)
 418
 419/*
 420 * This code initialises the MPC8260 processor core
 421 * (conforms to PowerPC 603e spec)
 422 */
 423
 424        .globl  cogent_init_8260
 425cogent_init_8260:
 426
 427        /* Taken from page 14 of CMA282 manual                          */
 428        /*--------------------------------------------------------------*/
 429
 430        lis     r4, (CONFIG_SYS_IMMR+IM_REGBASE)@h
 431        lis     r3, CONFIG_SYS_IMMR@h
 432        stw     r3, IM_IMMR@l(r4)
 433        lwz     r3, IM_IMMR@l(r4)
 434        stw     r3, 0(r0)
 435        lis     r3, CONFIG_SYS_SYPCR@h
 436        ori     r3, r3, CONFIG_SYS_SYPCR@l
 437        stw     r3, IM_SYPCR@l(r4)
 438        lwz     r3, IM_SYPCR@l(r4)
 439        stw     r3, 4(r0)
 440        lis     r3, CONFIG_SYS_SCCR@h
 441        ori     r3, r3, CONFIG_SYS_SCCR@l
 442        stw     r3, IM_SCCR@l(r4)
 443        lwz     r3, IM_SCCR@l(r4)
 444        stw     r3, 8(r0)
 445
 446        /* the rest of this was disassembled from the                   */
 447        /* EPROM code that came with my CMA282 CPU module               */
 448        /*--------------------------------------------------------------*/
 449
 450        lis     r1, 0x1234
 451        ori     r1, r1, 0x5678
 452        stw     r1, 0x20(r0)
 453        lwz     r1, 0x20(r0)
 454        stw     r1, 0x24(r0)
 455        lwz     r1, 0x24(r0)
 456        lis     r3, 0x0e80
 457        ori     r3, r3, 0
 458        stw     r1, 4(r3)
 459        lwz     r1, 4(r3)
 460
 461        /* Done!                                                        */
 462        /*--------------------------------------------------------------*/
 463
 464        blr
 465
 466#endif  /* CONFIG_COGENT */
 467
 468/*
 469 * This code initialises the MPC8260 processor core
 470 * (conforms to PowerPC 603e spec)
 471 * Note: expects original MSR contents to be in r5.
 472 */
 473
 474        .globl  init_8260_core
 475init_8260_core:
 476
 477        /* Initialize machine status; enable machine check interrupt    */
 478        /*--------------------------------------------------------------*/
 479
 480        li      r3, MSR_KERNEL          /* Set ME and RI flags */
 481        rlwimi  r3, r5, 0, 25, 25       /* preserve IP bit set by HRCW */
 482#ifdef DEBUG
 483        rlwimi  r3, r5, 0, 21, 22       /* debugger might set SE & BE bits */
 484#endif
 485        SYNC                            /* Some chip revs need this... */
 486        mtmsr   r3
 487        SYNC
 488        mtspr   SRR1, r3                /* Make SRR1 match MSR */
 489
 490        /* Initialise the SYPCR early, and reset the watchdog (if req)  */
 491        /*--------------------------------------------------------------*/
 492
 493        lis     r3, (CONFIG_SYS_IMMR+IM_REGBASE)@h
 494#if !defined(CONFIG_COGENT)
 495        lis     r4, CONFIG_SYS_SYPCR@h
 496        ori     r4, r4, CONFIG_SYS_SYPCR@l
 497        stw     r4, IM_SYPCR@l(r3)
 498#endif /* !CONFIG_COGENT */
 499#if defined(CONFIG_WATCHDOG)
 500        li      r4, 21868               /* = 0x556c */
 501        sth     r4, IM_SWSR@l(r3)
 502        li      r4, -21959              /* = 0xaa39 */
 503        sth     r4, IM_SWSR@l(r3)
 504#endif /* CONFIG_WATCHDOG */
 505
 506        /* Initialize the Hardware Implementation-dependent Registers   */
 507        /* HID0 also contains cache control                             */
 508        /*--------------------------------------------------------------*/
 509
 510        lis     r3, CONFIG_SYS_HID0_INIT@h
 511        ori     r3, r3, CONFIG_SYS_HID0_INIT@l
 512        SYNC
 513        mtspr   HID0, r3
 514
 515        lis     r3, CONFIG_SYS_HID0_FINAL@h
 516        ori     r3, r3, CONFIG_SYS_HID0_FINAL@l
 517        SYNC
 518        mtspr   HID0, r3
 519
 520        lis     r3, CONFIG_SYS_HID2@h
 521        ori     r3, r3, CONFIG_SYS_HID2@l
 522        mtspr   HID2, r3
 523
 524        /* clear all BAT's                                              */
 525        /*--------------------------------------------------------------*/
 526
 527        li      r0, 0
 528        mtspr   DBAT0U, r0
 529        mtspr   DBAT0L, r0
 530        mtspr   DBAT1U, r0
 531        mtspr   DBAT1L, r0
 532        mtspr   DBAT2U, r0
 533        mtspr   DBAT2L, r0
 534        mtspr   DBAT3U, r0
 535        mtspr   DBAT3L, r0
 536        mtspr   IBAT0U, r0
 537        mtspr   IBAT0L, r0
 538        mtspr   IBAT1U, r0
 539        mtspr   IBAT1L, r0
 540        mtspr   IBAT2U, r0
 541        mtspr   IBAT2L, r0
 542        mtspr   IBAT3U, r0
 543        mtspr   IBAT3L, r0
 544        SYNC
 545
 546        /* invalidate all tlb's                                         */
 547        /*                                                              */
 548        /* From the 603e User Manual: "The 603e provides the ability to */
 549        /* invalidate a TLB entry. The TLB Invalidate Entry (tlbie)     */
 550        /* instruction invalidates the TLB entry indexed by the EA, and */
 551        /* operates on both the instruction and data TLBs simultaneously*/
 552        /* invalidating four TLB entries (both sets in each TLB). The   */
 553        /* index corresponds to bits 15-19 of the EA. To invalidate all */
 554        /* entries within both TLBs, 32 tlbie instructions should be    */
 555        /* issued, incrementing this field by one each time."           */
 556        /*                                                              */
 557        /* "Note that the tlbia instruction is not implemented on the   */
 558        /* 603e."                                                       */
 559        /*                                                              */
 560        /* bits 15-19 correspond to addresses 0x00000000 to 0x0001F000  */
 561        /* incrementing by 0x1000 each time. The code below is sort of  */
 562        /* based on code in "flush_tlbs" from arch/powerpc/kernel/head.S        */
 563        /*                                                              */
 564        /*--------------------------------------------------------------*/
 565
 566        li      r3, 32
 567        mtctr   r3
 568        li      r3, 0
 5691:      tlbie   r3
 570        addi    r3, r3, 0x1000
 571        bdnz    1b
 572        SYNC
 573
 574        /* Done!                                                        */
 575        /*--------------------------------------------------------------*/
 576
 577        blr
 578
 579#ifdef DEBUG
 580
 581/*
 582 * initialise things related to debugging.
 583 *
 584 * must be called after the global offset table (GOT) is initialised
 585 * (GET_GOT) and after cpu_init_f() has executed.
 586 */
 587
 588        .globl  init_debug
 589init_debug:
 590
 591        lis     r3, (CONFIG_SYS_IMMR+IM_REGBASE)@h
 592
 593        /* Quick and dirty hack to enable the RAM and copy the          */
 594        /* vectors so that we can take exceptions.                      */
 595        /*--------------------------------------------------------------*/
 596        /* write Memory Refresh Prescaler */
 597        li      r4, CONFIG_SYS_MPTPR
 598        sth     r4, IM_MPTPR@l(r3)
 599        /* write 60x Refresh Timer */
 600        li      r4, CONFIG_SYS_PSRT
 601        stb     r4, IM_PSRT@l(r3)
 602        /* init the 60x SDRAM Mode Register */
 603        lis     r4, (CONFIG_SYS_PSDMR|PSDMR_OP_NORM)@h
 604        ori     r4, r4, (CONFIG_SYS_PSDMR|PSDMR_OP_NORM)@l
 605        stw     r4, IM_PSDMR@l(r3)
 606        /* write Precharge All Banks command */
 607        lis     r4, (CONFIG_SYS_PSDMR|PSDMR_OP_PREA)@h
 608        ori     r4, r4, (CONFIG_SYS_PSDMR|PSDMR_OP_PREA)@l
 609        stw     r4, IM_PSDMR@l(r3)
 610        stb     r0, 0(0)
 611        /* write eight CBR Refresh commands */
 612        lis     r4, (CONFIG_SYS_PSDMR|PSDMR_OP_CBRR)@h
 613        ori     r4, r4, (CONFIG_SYS_PSDMR|PSDMR_OP_CBRR)@l
 614        stw     r4, IM_PSDMR@l(r3)
 615        stb     r0, 0(0)
 616        stb     r0, 0(0)
 617        stb     r0, 0(0)
 618        stb     r0, 0(0)
 619        stb     r0, 0(0)
 620        stb     r0, 0(0)
 621        stb     r0, 0(0)
 622        stb     r0, 0(0)
 623        /* write Mode Register Write command */
 624        lis     r4, (CONFIG_SYS_PSDMR|PSDMR_OP_MRW)@h
 625        ori     r4, r4, (CONFIG_SYS_PSDMR|PSDMR_OP_MRW)@l
 626        stw     r4, IM_PSDMR@l(r3)
 627        stb     r0, 0(0)
 628        /* write Normal Operation command and enable Refresh */
 629        lis     r4, (CONFIG_SYS_PSDMR|PSDMR_OP_NORM|PSDMR_RFEN)@h
 630        ori     r4, r4, (CONFIG_SYS_PSDMR|PSDMR_OP_NORM|PSDMR_RFEN)@l
 631        stw     r4, IM_PSDMR@l(r3)
 632        stb     r0, 0(0)
 633        /* RAM should now be operational */
 634
 635#define VEC_WRD_CNT     ((_end_of_vectors - _start + EXC_OFF_SYS_RESET) / 4)
 636        mflr    r3
 637        GET_GOT
 638        mtlr    r3
 639        lwz     r3, GOT(_end_of_vectors)
 640        rlwinm  r4, r3, 0, 18, 31       /* _end_of_vectors & 0x3FFF     */
 641        lis     r5, VEC_WRD_CNT@h
 642        ori     r5, r5, VEC_WRD_CNT@l
 643        mtctr   r5
 6441:
 645        lwzu    r5, -4(r3)
 646        stwu    r5, -4(r4)
 647        bdnz    1b
 648
 649        /* Load the Instruction Address Breakpoint Register (IABR).     */
 650        /*                                                              */
 651        /* The address to load is stored in the first word of dual port */
 652        /* ram and should be preserved while the power is on, so you    */
 653        /* can plug addresses into that location then reset the cpu and */
 654        /* this code will load that address into the IABR after the     */
 655        /* reset.                                                       */
 656        /*                                                              */
 657        /* When the program counter matches the contents of the IABR,   */
 658        /* an exception is generated (before the instruction at that    */
 659        /* location completes). The vector for this exception is 0x1300 */
 660        /*--------------------------------------------------------------*/
 661        lis     r3, CONFIG_SYS_IMMR@h
 662        lwz     r3, 0(r3)
 663        mtspr   IABR, r3
 664
 665        /* Set the entire dual port RAM (where the initial stack        */
 666        /* resides) to a known value - makes it easier to see where     */
 667        /* the stack has been written                                   */
 668        /*--------------------------------------------------------------*/
 669        lis     r3, (CONFIG_SYS_IMMR + CONFIG_SYS_INIT_SP_OFFSET)@h
 670        ori     r3, r3, (CONFIG_SYS_IMMR + CONFIG_SYS_INIT_SP_OFFSET)@l
 671        li      r4, ((CONFIG_SYS_INIT_SP_OFFSET - 4) / 4)
 672        mtctr   r4
 673        lis     r4, 0xdeadbeaf@h
 674        ori     r4, r4, 0xdeadbeaf@l
 6751:
 676        stwu    r4, -4(r3)
 677        bdnz    1b
 678
 679        /* Done!                                                        */
 680        /*--------------------------------------------------------------*/
 681
 682        blr
 683#endif
 684
 685/* Cache functions.
 686 *
 687 * Note: requires that all cache bits in
 688 * HID0 are in the low half word.
 689 */
 690        .globl  icache_enable
 691icache_enable:
 692        mfspr   r3, HID0
 693        ori     r3, r3, HID0_ICE
 694        lis     r4, 0
 695        ori     r4, r4, HID0_ILOCK
 696        andc    r3, r3, r4
 697        ori     r4, r3, HID0_ICFI
 698        isync
 699        mtspr   HID0, r4        /* sets enable and invalidate, clears lock */
 700        isync
 701        mtspr   HID0, r3        /* clears invalidate */
 702        blr
 703
 704        .globl  icache_disable
 705icache_disable:
 706        mfspr   r3, HID0
 707        lis     r4, 0
 708        ori     r4, r4, HID0_ICE|HID0_ILOCK
 709        andc    r3, r3, r4
 710        ori     r4, r3, HID0_ICFI
 711        isync
 712        mtspr   HID0, r4        /* sets invalidate, clears enable and lock */
 713        isync
 714        mtspr   HID0, r3        /* clears invalidate */
 715        blr
 716
 717        .globl  icache_status
 718icache_status:
 719        mfspr   r3, HID0
 720        rlwinm  r3, r3, HID0_ICE_BITPOS + 1, 31, 31
 721        blr
 722
 723        .globl  dcache_enable
 724dcache_enable:
 725        mfspr   r3, HID0
 726        ori     r3, r3, HID0_DCE
 727        lis     r4, 0
 728        ori     r4, r4, HID0_DLOCK
 729        andc    r3, r3, r4
 730        ori     r4, r3, HID0_DCI
 731        sync
 732        mtspr   HID0, r4        /* sets enable and invalidate, clears lock */
 733        sync
 734        mtspr   HID0, r3        /* clears invalidate */
 735        blr
 736
 737        .globl  dcache_disable
 738dcache_disable:
 739        mfspr   r3, HID0
 740        lis     r4, 0
 741        ori     r4, r4, HID0_DCE|HID0_DLOCK
 742        andc    r3, r3, r4
 743        ori     r4, r3, HID0_DCI
 744        sync
 745        mtspr   HID0, r4        /* sets invalidate, clears enable and lock */
 746        sync
 747        mtspr   HID0, r3        /* clears invalidate */
 748        blr
 749
 750        .globl  dcache_status
 751dcache_status:
 752        mfspr   r3, HID0
 753        rlwinm  r3, r3, HID0_DCE_BITPOS + 1, 31, 31
 754        blr
 755
 756        .globl get_pvr
 757get_pvr:
 758        mfspr   r3, PVR
 759        blr
 760
 761/*------------------------------------------------------------------------------*/
 762
 763/*
 764 * void relocate_code (addr_sp, gd, addr_moni)
 765 *
 766 * This "function" does not return, instead it continues in RAM
 767 * after relocating the monitor code.
 768 *
 769 * r3 = dest
 770 * r4 = src
 771 * r5 = length in bytes
 772 * r6 = cachelinesize
 773 */
 774        .globl  relocate_code
 775relocate_code:
 776        mr      r1,  r3         /* Set new stack pointer                */
 777        mr      r9,  r4         /* Save copy of Global Data pointer     */
 778        mr      r10, r5         /* Save copy of Destination Address     */
 779
 780        GET_GOT
 781        mr      r3,  r5                         /* Destination Address  */
 782        lis     r4, CONFIG_SYS_MONITOR_BASE@h           /* Source      Address  */
 783        ori     r4, r4, CONFIG_SYS_MONITOR_BASE@l
 784        lwz     r5, GOT(__init_end)
 785        sub     r5, r5, r4
 786        li      r6, CONFIG_SYS_CACHELINE_SIZE           /* Cache Line Size      */
 787
 788        /*
 789         * Fix GOT pointer:
 790         *
 791         * New GOT-PTR = (old GOT-PTR - CONFIG_SYS_MONITOR_BASE) + Destination Address
 792         *
 793         * Offset:
 794         */
 795        sub     r15, r10, r4
 796
 797        /* First our own GOT */
 798        add     r12, r12, r15
 799        /* then the one used by the C code */
 800        add     r30, r30, r15
 801
 802        /*
 803         * Now relocate code
 804         */
 805
 806        cmplw   cr1,r3,r4
 807        addi    r0,r5,3
 808        srwi.   r0,r0,2
 809        beq     cr1,4f          /* In place copy is not necessary       */
 810        beq     7f              /* Protect against 0 count              */
 811        mtctr   r0
 812        bge     cr1,2f
 813
 814        la      r8,-4(r4)
 815        la      r7,-4(r3)
 8161:      lwzu    r0,4(r8)
 817        stwu    r0,4(r7)
 818        bdnz    1b
 819        b       4f
 820
 8212:      slwi    r0,r0,2
 822        add     r8,r4,r0
 823        add     r7,r3,r0
 8243:      lwzu    r0,-4(r8)
 825        stwu    r0,-4(r7)
 826        bdnz    3b
 827
 828/*
 829 * Now flush the cache: note that we must start from a cache aligned
 830 * address. Otherwise we might miss one cache line.
 831 */
 8324:      cmpwi   r6,0
 833        add     r5,r3,r5
 834        beq     7f              /* Always flush prefetch queue in any case */
 835        subi    r0,r6,1
 836        andc    r3,r3,r0
 837        mfspr   r7,HID0         /* don't do dcbst if dcache is disabled */
 838        rlwinm  r7,r7,HID0_DCE_BITPOS+1,31,31
 839        cmpwi   r7,0
 840        beq     9f
 841        mr      r4,r3
 8425:      dcbst   0,r4
 843        add     r4,r4,r6
 844        cmplw   r4,r5
 845        blt     5b
 846        sync                    /* Wait for all dcbst to complete on bus */
 8479:      mfspr   r7,HID0         /* don't do icbi if icache is disabled */
 848        rlwinm  r7,r7,HID0_ICE_BITPOS+1,31,31
 849        cmpwi   r7,0
 850        beq     7f
 851        mr      r4,r3
 8526:      icbi    0,r4
 853        add     r4,r4,r6
 854        cmplw   r4,r5
 855        blt     6b
 8567:      sync                    /* Wait for all icbi to complete on bus */
 857        isync
 858
 859/*
 860 * We are done. Do not return, instead branch to second part of board
 861 * initialization, now running from RAM.
 862 */
 863
 864        addi    r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
 865        mtlr    r0
 866        blr
 867
 868in_ram:
 869
 870        /*
 871         * Relocation Function, r12 point to got2+0x8000
 872         *
 873         * Adjust got2 pointers, no need to check for 0, this code
 874         * already puts a few entries in the table.
 875         */
 876        li      r0,__got2_entries@sectoff@l
 877        la      r3,GOT(_GOT2_TABLE_)
 878        lwz     r11,GOT(_GOT2_TABLE_)
 879        mtctr   r0
 880        sub     r11,r3,r11
 881        addi    r3,r3,-4
 8821:      lwzu    r0,4(r3)
 883        cmpwi   r0,0
 884        beq-    2f
 885        add     r0,r0,r11
 886        stw     r0,0(r3)
 8872:      bdnz    1b
 888
 889        /*
 890         * Now adjust the fixups and the pointers to the fixups
 891         * in case we need to move ourselves again.
 892         */
 893        li      r0,__fixup_entries@sectoff@l
 894        lwz     r3,GOT(_FIXUP_TABLE_)
 895        cmpwi   r0,0
 896        mtctr   r0
 897        addi    r3,r3,-4
 898        beq     4f
 8993:      lwzu    r4,4(r3)
 900        lwzux   r0,r4,r11
 901        cmpwi   r0,0
 902        add     r0,r0,r11
 903        stw     r4,0(r3)
 904        beq-    5f
 905        stw     r0,0(r4)
 9065:      bdnz    3b
 9074:
 908clear_bss:
 909        /*
 910         * Now clear BSS segment
 911         */
 912        lwz     r3,GOT(__bss_start)
 913#if defined(CONFIG_HYMOD)
 914        /*
 915         * For HYMOD - the environment is the very last item in flash.
 916         * The real .bss stops just before environment starts, so only
 917         * clear up to that point.
 918         *
 919         * taken from mods for FADS board
 920         */
 921        lwz     r4,GOT(environment)
 922#else
 923        lwz     r4,GOT(__bss_end__)
 924#endif
 925
 926        cmplw   0, r3, r4
 927        beq     6f
 928
 929        li      r0, 0
 9305:
 931        stw     r0, 0(r3)
 932        addi    r3, r3, 4
 933        cmplw   0, r3, r4
 934        bne     5b
 9356:
 936
 937        mr      r3, r9          /* Global Data pointer          */
 938        mr      r4, r10         /* Destination Address          */
 939        bl      board_init_r
 940
 941        /*
 942         * Copy exception vector code to low memory
 943         *
 944         * r3: dest_addr
 945         * r7: source address, r8: end address, r9: target address
 946         */
 947        .globl  trap_init
 948trap_init:
 949        mflr    r4                      /* save link register           */
 950        GET_GOT
 951        lwz     r7, GOT(_start)
 952        lwz     r8, GOT(_end_of_vectors)
 953
 954        li      r9, 0x100               /* reset vector always at 0x100 */
 955
 956        cmplw   0, r7, r8
 957        bgelr                           /* return if r7>=r8 - just in case */
 9581:
 959        lwz     r0, 0(r7)
 960        stw     r0, 0(r9)
 961        addi    r7, r7, 4
 962        addi    r9, r9, 4
 963        cmplw   0, r7, r8
 964        bne     1b
 965
 966        /*
 967         * relocate `hdlr' and `int_return' entries
 968         */
 969        li      r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
 970        li      r8, Alignment - _start + EXC_OFF_SYS_RESET
 9712:
 972        bl      trap_reloc
 973        addi    r7, r7, 0x100           /* next exception vector        */
 974        cmplw   0, r7, r8
 975        blt     2b
 976
 977        li      r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
 978        bl      trap_reloc
 979
 980        li      r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
 981        bl      trap_reloc
 982
 983        li      r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
 984        li      r8, SystemCall - _start + EXC_OFF_SYS_RESET
 9853:
 986        bl      trap_reloc
 987        addi    r7, r7, 0x100           /* next exception vector        */
 988        cmplw   0, r7, r8
 989        blt     3b
 990
 991        li      r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
 992        li      r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
 9934:
 994        bl      trap_reloc
 995        addi    r7, r7, 0x100           /* next exception vector        */
 996        cmplw   0, r7, r8
 997        blt     4b
 998
 999        mfmsr   r3                      /* now that the vectors have    */
1000        lis     r7, MSR_IP@h            /* relocated into low memory    */
1001        ori     r7, r7, MSR_IP@l        /* MSR[IP] can be turned off    */
1002        andc    r3, r3, r7              /* (if it was on)               */
1003        SYNC                            /* Some chip revs need this... */
1004        mtmsr   r3
1005        SYNC
1006
1007        mtlr    r4                      /* restore link register    */
1008        blr
1009