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