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