d255bdeeb8a9d715b5a5a6bd7e5af49f6ad9d657
[platform/kernel/u-boot.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_SYS_DEFAULT_IMMR)
140         lis     r3, CONFIG_SYS_IMMR@h
141         ori     r3, r3, CONFIG_SYS_IMMR@l
142         lis     r4, CONFIG_SYS_DEFAULT_IMMR@h
143         stw     r3, 0x1A8(r4)
144 #endif /* CONFIG_SYS_DEFAULT_IMMR */
145
146         /* Initialise the MPC8260 processor core                        */
147         /*--------------------------------------------------------------*/
148
149         bl      init_8260_core
150
151 #ifndef CONFIG_SYS_RAMBOOT
152         /* When booting from ROM (Flash or EPROM), clear the            */
153         /* Address Mask in OR0 so ROM appears everywhere                */
154         /*--------------------------------------------------------------*/
155
156         lis     r3, (CONFIG_SYS_IMMR+IM_REGBASE)@h
157         lwz     r4, IM_OR0@l(r3)
158         li      r5, 0x7fff
159         and     r4, r4, r5
160         stw     r4, IM_OR0@l(r3)
161
162         /* Calculate absolute address in FLASH and jump there           */
163         /*--------------------------------------------------------------*/
164
165         lis     r3, CONFIG_SYS_MONITOR_BASE@h
166         ori     r3, r3, CONFIG_SYS_MONITOR_BASE@l
167         addi    r3, r3, in_flash - _start + EXC_OFF_SYS_RESET
168         mtlr    r3
169         blr
170
171 in_flash:
172 #endif  /* CONFIG_SYS_RAMBOOT */
173
174         /* initialize some things that are hard to access from C        */
175         /*--------------------------------------------------------------*/
176
177         lis     r3, CONFIG_SYS_IMMR@h           /* set up stack in internal DPRAM */
178         ori     r1, r3, CONFIG_SYS_INIT_SP_OFFSET
179         li      r0, 0                   /* Make room for stack frame header and */
180         stwu    r0, -4(r1)              /* clear final stack frame so that      */
181         stwu    r0, -4(r1)              /* stack backtraces terminate cleanly   */
182
183         /* let the C-code set up the rest                               */
184         /*                                                              */
185         /* Be careful to keep code relocatable !                        */
186         /*--------------------------------------------------------------*/
187
188         GET_GOT                 /* initialize GOT access                */
189
190         /* r3: IMMR */
191         bl      cpu_init_f      /* run low-level CPU init code (in Flash)*/
192
193 #ifdef DEBUG
194         bl      init_debug      /* set up debugging stuff               */
195 #endif
196
197         bl      board_init_f    /* run 1st part of board init code (in Flash)*/
198
199         /* NOTREACHED - board_init_f() does not return */
200
201 /*
202  * Vector Table
203  */
204
205         .globl  _start_of_vectors
206 _start_of_vectors:
207
208 /* Machine check */
209         STD_EXCEPTION(0x200, MachineCheck, MachineCheckException)
210
211 /* Data Storage exception. */
212         STD_EXCEPTION(0x300, DataStorage, UnknownException)
213
214 /* Instruction Storage exception. */
215         STD_EXCEPTION(0x400, InstStorage, UnknownException)
216
217 /* External Interrupt exception. */
218         STD_EXCEPTION(0x500, ExtInterrupt, external_interrupt)
219
220 /* Alignment exception. */
221         . = 0x600
222 Alignment:
223         EXCEPTION_PROLOG(SRR0, SRR1)
224         mfspr   r4,DAR
225         stw     r4,_DAR(r21)
226         mfspr   r5,DSISR
227         stw     r5,_DSISR(r21)
228         addi    r3,r1,STACK_FRAME_OVERHEAD
229         EXC_XFER_TEMPLATE(Alignment, AlignmentException, MSR_KERNEL, COPY_EE)
230
231 /* Program check exception */
232         . = 0x700
233 ProgramCheck:
234         EXCEPTION_PROLOG(SRR0, SRR1)
235         addi    r3,r1,STACK_FRAME_OVERHEAD
236         EXC_XFER_TEMPLATE(ProgramCheck, ProgramCheckException,
237                 MSR_KERNEL, COPY_EE)
238
239         STD_EXCEPTION(0x800, FPUnavailable, UnknownException)
240
241         /* I guess we could implement decrementer, and may have
242          * to someday for timekeeping.
243          */
244         STD_EXCEPTION(0x900, Decrementer, timer_interrupt)
245
246         STD_EXCEPTION(0xa00, Trap_0a, UnknownException)
247         STD_EXCEPTION(0xb00, Trap_0b, UnknownException)
248         STD_EXCEPTION(0xc00, SystemCall, UnknownException)
249         STD_EXCEPTION(0xd00, SingleStep, UnknownException)
250
251         STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
252         STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
253
254         STD_EXCEPTION(0x1000, InstructionTLBMiss, UnknownException)
255         STD_EXCEPTION(0x1100, DataLoadTLBMiss, UnknownException)
256         STD_EXCEPTION(0x1200, DataStoreTLBMiss, UnknownException)
257 #ifdef DEBUG
258         . = 0x1300
259         /*
260          * This exception occurs when the program counter matches the
261          * Instruction Address Breakpoint Register (IABR).
262          *
263          * I want the cpu to halt if this occurs so I can hunt around
264          * with the debugger and look at things.
265          *
266          * When DEBUG is defined, both machine check enable (in the MSR)
267          * and checkstop reset enable (in the reset mode register) are
268          * turned off and so a checkstop condition will result in the cpu
269          * halting.
270          *
271          * I force the cpu into a checkstop condition by putting an illegal
272          * instruction here (at least this is the theory).
273          *
274          * well - that didnt work, so just do an infinite loop!
275          */
276 1:      b       1b
277 #else
278         STD_EXCEPTION(0x1300, InstructionBreakpoint, DebugException)
279 #endif
280         STD_EXCEPTION(0x1400, SMI, UnknownException)
281
282         STD_EXCEPTION(0x1500, Trap_15, UnknownException)
283         STD_EXCEPTION(0x1600, Trap_16, UnknownException)
284         STD_EXCEPTION(0x1700, Trap_17, UnknownException)
285         STD_EXCEPTION(0x1800, Trap_18, UnknownException)
286         STD_EXCEPTION(0x1900, Trap_19, UnknownException)
287         STD_EXCEPTION(0x1a00, Trap_1a, UnknownException)
288         STD_EXCEPTION(0x1b00, Trap_1b, UnknownException)
289         STD_EXCEPTION(0x1c00, Trap_1c, UnknownException)
290         STD_EXCEPTION(0x1d00, Trap_1d, UnknownException)
291         STD_EXCEPTION(0x1e00, Trap_1e, UnknownException)
292         STD_EXCEPTION(0x1f00, Trap_1f, UnknownException)
293         STD_EXCEPTION(0x2000, Trap_20, UnknownException)
294         STD_EXCEPTION(0x2100, Trap_21, UnknownException)
295         STD_EXCEPTION(0x2200, Trap_22, UnknownException)
296         STD_EXCEPTION(0x2300, Trap_23, UnknownException)
297         STD_EXCEPTION(0x2400, Trap_24, UnknownException)
298         STD_EXCEPTION(0x2500, Trap_25, UnknownException)
299         STD_EXCEPTION(0x2600, Trap_26, UnknownException)
300         STD_EXCEPTION(0x2700, Trap_27, UnknownException)
301         STD_EXCEPTION(0x2800, Trap_28, UnknownException)
302         STD_EXCEPTION(0x2900, Trap_29, UnknownException)
303         STD_EXCEPTION(0x2a00, Trap_2a, UnknownException)
304         STD_EXCEPTION(0x2b00, Trap_2b, UnknownException)
305         STD_EXCEPTION(0x2c00, Trap_2c, UnknownException)
306         STD_EXCEPTION(0x2d00, Trap_2d, UnknownException)
307         STD_EXCEPTION(0x2e00, Trap_2e, UnknownException)
308         STD_EXCEPTION(0x2f00, Trap_2f, UnknownException)
309
310
311         .globl  _end_of_vectors
312 _end_of_vectors:
313
314         . = 0x3000
315
316 /*
317  * This code finishes saving the registers to the exception frame
318  * and jumps to the appropriate handler for the exception.
319  * Register r21 is pointer into trap frame, r1 has new stack pointer.
320  */
321         .globl  transfer_to_handler
322 transfer_to_handler:
323         stw     r22,_NIP(r21)
324         lis     r22,MSR_POW@h
325         andc    r23,r23,r22
326         stw     r23,_MSR(r21)
327         SAVE_GPR(7, r21)
328         SAVE_4GPRS(8, r21)
329         SAVE_8GPRS(12, r21)
330         SAVE_8GPRS(24, r21)
331         mflr    r23
332         andi.   r24,r23,0x3f00          /* get vector offset */
333         stw     r24,TRAP(r21)
334         li      r22,0
335         stw     r22,RESULT(r21)
336         lwz     r24,0(r23)              /* virtual address of handler */
337         lwz     r23,4(r23)              /* where to go when done */
338         mtspr   SRR0,r24
339         mtspr   SRR1,r20
340         mtlr    r23
341         SYNC
342         rfi                             /* jump to handler, enable MMU */
343
344 int_return:
345         mfmsr   r28             /* Disable interrupts */
346         li      r4,0
347         ori     r4,r4,MSR_EE
348         andc    r28,r28,r4
349         SYNC                    /* Some chip revs need this... */
350         mtmsr   r28
351         SYNC
352         lwz     r2,_CTR(r1)
353         lwz     r0,_LINK(r1)
354         mtctr   r2
355         mtlr    r0
356         lwz     r2,_XER(r1)
357         lwz     r0,_CCR(r1)
358         mtspr   XER,r2
359         mtcrf   0xFF,r0
360         REST_10GPRS(3, r1)
361         REST_10GPRS(13, r1)
362         REST_8GPRS(23, r1)
363         REST_GPR(31, r1)
364         lwz     r2,_NIP(r1)     /* Restore environment */
365         lwz     r0,_MSR(r1)
366         mtspr   SRR0,r2
367         mtspr   SRR1,r0
368         lwz     r0,GPR0(r1)
369         lwz     r2,GPR2(r1)
370         lwz     r1,GPR1(r1)
371         SYNC
372         rfi
373
374 /*
375  * This code initialises the MPC8260 processor core
376  * (conforms to PowerPC 603e spec)
377  * Note: expects original MSR contents to be in r5.
378  */
379
380         .globl  init_8260_core
381 init_8260_core:
382
383         /* Initialize machine status; enable machine check interrupt    */
384         /*--------------------------------------------------------------*/
385
386         li      r3, MSR_KERNEL          /* Set ME and RI flags */
387         rlwimi  r3, r5, 0, 25, 25       /* preserve IP bit set by HRCW */
388 #ifdef DEBUG
389         rlwimi  r3, r5, 0, 21, 22       /* debugger might set SE & BE bits */
390 #endif
391         SYNC                            /* Some chip revs need this... */
392         mtmsr   r3
393         SYNC
394         mtspr   SRR1, r3                /* Make SRR1 match MSR */
395
396         /* Initialise the SYPCR early, and reset the watchdog (if req)  */
397         /*--------------------------------------------------------------*/
398
399         lis     r3, (CONFIG_SYS_IMMR+IM_REGBASE)@h
400         lis     r4, CONFIG_SYS_SYPCR@h
401         ori     r4, r4, CONFIG_SYS_SYPCR@l
402         stw     r4, IM_SYPCR@l(r3)
403 #if defined(CONFIG_WATCHDOG)
404         li      r4, 21868               /* = 0x556c */
405         sth     r4, IM_SWSR@l(r3)
406         li      r4, -21959              /* = 0xaa39 */
407         sth     r4, IM_SWSR@l(r3)
408 #endif /* CONFIG_WATCHDOG */
409
410         /* Initialize the Hardware Implementation-dependent Registers   */
411         /* HID0 also contains cache control                             */
412         /*--------------------------------------------------------------*/
413
414         lis     r3, CONFIG_SYS_HID0_INIT@h
415         ori     r3, r3, CONFIG_SYS_HID0_INIT@l
416         SYNC
417         mtspr   HID0, r3
418
419         lis     r3, CONFIG_SYS_HID0_FINAL@h
420         ori     r3, r3, CONFIG_SYS_HID0_FINAL@l
421         SYNC
422         mtspr   HID0, r3
423
424         lis     r3, CONFIG_SYS_HID2@h
425         ori     r3, r3, CONFIG_SYS_HID2@l
426         mtspr   HID2, r3
427
428         /* clear all BAT's                                              */
429         /*--------------------------------------------------------------*/
430
431         li      r0, 0
432         mtspr   DBAT0U, r0
433         mtspr   DBAT0L, r0
434         mtspr   DBAT1U, r0
435         mtspr   DBAT1L, r0
436         mtspr   DBAT2U, r0
437         mtspr   DBAT2L, r0
438         mtspr   DBAT3U, r0
439         mtspr   DBAT3L, r0
440         mtspr   IBAT0U, r0
441         mtspr   IBAT0L, r0
442         mtspr   IBAT1U, r0
443         mtspr   IBAT1L, r0
444         mtspr   IBAT2U, r0
445         mtspr   IBAT2L, r0
446         mtspr   IBAT3U, r0
447         mtspr   IBAT3L, r0
448         SYNC
449
450         /* invalidate all tlb's                                         */
451         /*                                                              */
452         /* From the 603e User Manual: "The 603e provides the ability to */
453         /* invalidate a TLB entry. The TLB Invalidate Entry (tlbie)     */
454         /* instruction invalidates the TLB entry indexed by the EA, and */
455         /* operates on both the instruction and data TLBs simultaneously*/
456         /* invalidating four TLB entries (both sets in each TLB). The   */
457         /* index corresponds to bits 15-19 of the EA. To invalidate all */
458         /* entries within both TLBs, 32 tlbie instructions should be    */
459         /* issued, incrementing this field by one each time."           */
460         /*                                                              */
461         /* "Note that the tlbia instruction is not implemented on the   */
462         /* 603e."                                                       */
463         /*                                                              */
464         /* bits 15-19 correspond to addresses 0x00000000 to 0x0001F000  */
465         /* incrementing by 0x1000 each time. The code below is sort of  */
466         /* based on code in "flush_tlbs" from arch/powerpc/kernel/head.S        */
467         /*                                                              */
468         /*--------------------------------------------------------------*/
469
470         li      r3, 32
471         mtctr   r3
472         li      r3, 0
473 1:      tlbie   r3
474         addi    r3, r3, 0x1000
475         bdnz    1b
476         SYNC
477
478         /* Done!                                                        */
479         /*--------------------------------------------------------------*/
480
481         blr
482
483 #ifdef DEBUG
484
485 /*
486  * initialise things related to debugging.
487  *
488  * must be called after the global offset table (GOT) is initialised
489  * (GET_GOT) and after cpu_init_f() has executed.
490  */
491
492         .globl  init_debug
493 init_debug:
494
495         lis     r3, (CONFIG_SYS_IMMR+IM_REGBASE)@h
496
497         /* Quick and dirty hack to enable the RAM and copy the          */
498         /* vectors so that we can take exceptions.                      */
499         /*--------------------------------------------------------------*/
500         /* write Memory Refresh Prescaler */
501         li      r4, CONFIG_SYS_MPTPR
502         sth     r4, IM_MPTPR@l(r3)
503         /* write 60x Refresh Timer */
504         li      r4, CONFIG_SYS_PSRT
505         stb     r4, IM_PSRT@l(r3)
506         /* init the 60x SDRAM Mode Register */
507         lis     r4, (CONFIG_SYS_PSDMR|PSDMR_OP_NORM)@h
508         ori     r4, r4, (CONFIG_SYS_PSDMR|PSDMR_OP_NORM)@l
509         stw     r4, IM_PSDMR@l(r3)
510         /* write Precharge All Banks command */
511         lis     r4, (CONFIG_SYS_PSDMR|PSDMR_OP_PREA)@h
512         ori     r4, r4, (CONFIG_SYS_PSDMR|PSDMR_OP_PREA)@l
513         stw     r4, IM_PSDMR@l(r3)
514         stb     r0, 0(0)
515         /* write eight CBR Refresh commands */
516         lis     r4, (CONFIG_SYS_PSDMR|PSDMR_OP_CBRR)@h
517         ori     r4, r4, (CONFIG_SYS_PSDMR|PSDMR_OP_CBRR)@l
518         stw     r4, IM_PSDMR@l(r3)
519         stb     r0, 0(0)
520         stb     r0, 0(0)
521         stb     r0, 0(0)
522         stb     r0, 0(0)
523         stb     r0, 0(0)
524         stb     r0, 0(0)
525         stb     r0, 0(0)
526         stb     r0, 0(0)
527         /* write Mode Register Write command */
528         lis     r4, (CONFIG_SYS_PSDMR|PSDMR_OP_MRW)@h
529         ori     r4, r4, (CONFIG_SYS_PSDMR|PSDMR_OP_MRW)@l
530         stw     r4, IM_PSDMR@l(r3)
531         stb     r0, 0(0)
532         /* write Normal Operation command and enable Refresh */
533         lis     r4, (CONFIG_SYS_PSDMR|PSDMR_OP_NORM|PSDMR_RFEN)@h
534         ori     r4, r4, (CONFIG_SYS_PSDMR|PSDMR_OP_NORM|PSDMR_RFEN)@l
535         stw     r4, IM_PSDMR@l(r3)
536         stb     r0, 0(0)
537         /* RAM should now be operational */
538
539 #define VEC_WRD_CNT     ((_end_of_vectors - _start + EXC_OFF_SYS_RESET) / 4)
540         mflr    r3
541         GET_GOT
542         mtlr    r3
543         lwz     r3, GOT(_end_of_vectors)
544         rlwinm  r4, r3, 0, 18, 31       /* _end_of_vectors & 0x3FFF     */
545         lis     r5, VEC_WRD_CNT@h
546         ori     r5, r5, VEC_WRD_CNT@l
547         mtctr   r5
548 1:
549         lwzu    r5, -4(r3)
550         stwu    r5, -4(r4)
551         bdnz    1b
552
553         /* Load the Instruction Address Breakpoint Register (IABR).     */
554         /*                                                              */
555         /* The address to load is stored in the first word of dual port */
556         /* ram and should be preserved while the power is on, so you    */
557         /* can plug addresses into that location then reset the cpu and */
558         /* this code will load that address into the IABR after the     */
559         /* reset.                                                       */
560         /*                                                              */
561         /* When the program counter matches the contents of the IABR,   */
562         /* an exception is generated (before the instruction at that    */
563         /* location completes). The vector for this exception is 0x1300 */
564         /*--------------------------------------------------------------*/
565         lis     r3, CONFIG_SYS_IMMR@h
566         lwz     r3, 0(r3)
567         mtspr   IABR, r3
568
569         /* Set the entire dual port RAM (where the initial stack        */
570         /* resides) to a known value - makes it easier to see where     */
571         /* the stack has been written                                   */
572         /*--------------------------------------------------------------*/
573         lis     r3, (CONFIG_SYS_IMMR + CONFIG_SYS_INIT_SP_OFFSET)@h
574         ori     r3, r3, (CONFIG_SYS_IMMR + CONFIG_SYS_INIT_SP_OFFSET)@l
575         li      r4, ((CONFIG_SYS_INIT_SP_OFFSET - 4) / 4)
576         mtctr   r4
577         lis     r4, 0xdeadbeaf@h
578         ori     r4, r4, 0xdeadbeaf@l
579 1:
580         stwu    r4, -4(r3)
581         bdnz    1b
582
583         /* Done!                                                        */
584         /*--------------------------------------------------------------*/
585
586         blr
587 #endif
588
589 /* Cache functions.
590  *
591  * Note: requires that all cache bits in
592  * HID0 are in the low half word.
593  */
594         .globl  icache_enable
595 icache_enable:
596         mfspr   r3, HID0
597         ori     r3, r3, HID0_ICE
598         lis     r4, 0
599         ori     r4, r4, HID0_ILOCK
600         andc    r3, r3, r4
601         ori     r4, r3, HID0_ICFI
602         isync
603         mtspr   HID0, r4        /* sets enable and invalidate, clears lock */
604         isync
605         mtspr   HID0, r3        /* clears invalidate */
606         blr
607
608         .globl  icache_disable
609 icache_disable:
610         mfspr   r3, HID0
611         lis     r4, 0
612         ori     r4, r4, HID0_ICE|HID0_ILOCK
613         andc    r3, r3, r4
614         ori     r4, r3, HID0_ICFI
615         isync
616         mtspr   HID0, r4        /* sets invalidate, clears enable and lock */
617         isync
618         mtspr   HID0, r3        /* clears invalidate */
619         blr
620
621         .globl  icache_status
622 icache_status:
623         mfspr   r3, HID0
624         rlwinm  r3, r3, HID0_ICE_BITPOS + 1, 31, 31
625         blr
626
627         .globl  dcache_enable
628 dcache_enable:
629         mfspr   r3, HID0
630         ori     r3, r3, HID0_DCE
631         lis     r4, 0
632         ori     r4, r4, HID0_DLOCK
633         andc    r3, r3, r4
634         ori     r4, r3, HID0_DCI
635         sync
636         mtspr   HID0, r4        /* sets enable and invalidate, clears lock */
637         sync
638         mtspr   HID0, r3        /* clears invalidate */
639         blr
640
641         .globl  dcache_disable
642 dcache_disable:
643         mfspr   r3, HID0
644         lis     r4, 0
645         ori     r4, r4, HID0_DCE|HID0_DLOCK
646         andc    r3, r3, r4
647         ori     r4, r3, HID0_DCI
648         sync
649         mtspr   HID0, r4        /* sets invalidate, clears enable and lock */
650         sync
651         mtspr   HID0, r3        /* clears invalidate */
652         blr
653
654         .globl  dcache_status
655 dcache_status:
656         mfspr   r3, HID0
657         rlwinm  r3, r3, HID0_DCE_BITPOS + 1, 31, 31
658         blr
659
660         .globl get_pvr
661 get_pvr:
662         mfspr   r3, PVR
663         blr
664
665 /*------------------------------------------------------------------------------*/
666
667 /*
668  * void relocate_code (addr_sp, gd, addr_moni)
669  *
670  * This "function" does not return, instead it continues in RAM
671  * after relocating the monitor code.
672  *
673  * r3 = dest
674  * r4 = src
675  * r5 = length in bytes
676  * r6 = cachelinesize
677  */
678         .globl  relocate_code
679 relocate_code:
680         mr      r1,  r3         /* Set new stack pointer                */
681         mr      r9,  r4         /* Save copy of Global Data pointer     */
682         mr      r10, r5         /* Save copy of Destination Address     */
683
684         GET_GOT
685         mr      r3,  r5                         /* Destination Address  */
686         lis     r4, CONFIG_SYS_MONITOR_BASE@h           /* Source      Address  */
687         ori     r4, r4, CONFIG_SYS_MONITOR_BASE@l
688         lwz     r5, GOT(__init_end)
689         sub     r5, r5, r4
690         li      r6, CONFIG_SYS_CACHELINE_SIZE           /* Cache Line Size      */
691
692         /*
693          * Fix GOT pointer:
694          *
695          * New GOT-PTR = (old GOT-PTR - CONFIG_SYS_MONITOR_BASE) + Destination Address
696          *
697          * Offset:
698          */
699         sub     r15, r10, r4
700
701         /* First our own GOT */
702         add     r12, r12, r15
703         /* then the one used by the C code */
704         add     r30, r30, r15
705
706         /*
707          * Now relocate code
708          */
709
710         cmplw   cr1,r3,r4
711         addi    r0,r5,3
712         srwi.   r0,r0,2
713         beq     cr1,4f          /* In place copy is not necessary       */
714         beq     7f              /* Protect against 0 count              */
715         mtctr   r0
716         bge     cr1,2f
717
718         la      r8,-4(r4)
719         la      r7,-4(r3)
720 1:      lwzu    r0,4(r8)
721         stwu    r0,4(r7)
722         bdnz    1b
723         b       4f
724
725 2:      slwi    r0,r0,2
726         add     r8,r4,r0
727         add     r7,r3,r0
728 3:      lwzu    r0,-4(r8)
729         stwu    r0,-4(r7)
730         bdnz    3b
731
732 /*
733  * Now flush the cache: note that we must start from a cache aligned
734  * address. Otherwise we might miss one cache line.
735  */
736 4:      cmpwi   r6,0
737         add     r5,r3,r5
738         beq     7f              /* Always flush prefetch queue in any case */
739         subi    r0,r6,1
740         andc    r3,r3,r0
741         mfspr   r7,HID0         /* don't do dcbst if dcache is disabled */
742         rlwinm  r7,r7,HID0_DCE_BITPOS+1,31,31
743         cmpwi   r7,0
744         beq     9f
745         mr      r4,r3
746 5:      dcbst   0,r4
747         add     r4,r4,r6
748         cmplw   r4,r5
749         blt     5b
750         sync                    /* Wait for all dcbst to complete on bus */
751 9:      mfspr   r7,HID0         /* don't do icbi if icache is disabled */
752         rlwinm  r7,r7,HID0_ICE_BITPOS+1,31,31
753         cmpwi   r7,0
754         beq     7f
755         mr      r4,r3
756 6:      icbi    0,r4
757         add     r4,r4,r6
758         cmplw   r4,r5
759         blt     6b
760 7:      sync                    /* Wait for all icbi to complete on bus */
761         isync
762
763 /*
764  * We are done. Do not return, instead branch to second part of board
765  * initialization, now running from RAM.
766  */
767
768         addi    r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
769         mtlr    r0
770         blr
771
772 in_ram:
773
774         /*
775          * Relocation Function, r12 point to got2+0x8000
776          *
777          * Adjust got2 pointers, no need to check for 0, this code
778          * already puts a few entries in the table.
779          */
780         li      r0,__got2_entries@sectoff@l
781         la      r3,GOT(_GOT2_TABLE_)
782         lwz     r11,GOT(_GOT2_TABLE_)
783         mtctr   r0
784         sub     r11,r3,r11
785         addi    r3,r3,-4
786 1:      lwzu    r0,4(r3)
787         cmpwi   r0,0
788         beq-    2f
789         add     r0,r0,r11
790         stw     r0,0(r3)
791 2:      bdnz    1b
792
793         /*
794          * Now adjust the fixups and the pointers to the fixups
795          * in case we need to move ourselves again.
796          */
797         li      r0,__fixup_entries@sectoff@l
798         lwz     r3,GOT(_FIXUP_TABLE_)
799         cmpwi   r0,0
800         mtctr   r0
801         addi    r3,r3,-4
802         beq     4f
803 3:      lwzu    r4,4(r3)
804         lwzux   r0,r4,r11
805         cmpwi   r0,0
806         add     r0,r0,r11
807         stw     r4,0(r3)
808         beq-    5f
809         stw     r0,0(r4)
810 5:      bdnz    3b
811 4:
812 clear_bss:
813         /*
814          * Now clear BSS segment
815          */
816         lwz     r3,GOT(__bss_start)
817         lwz     r4,GOT(__bss_end)
818
819         cmplw   0, r3, r4
820         beq     6f
821
822         li      r0, 0
823 5:
824         stw     r0, 0(r3)
825         addi    r3, r3, 4
826         cmplw   0, r3, r4
827         bne     5b
828 6:
829
830         mr      r3, r9          /* Global Data pointer          */
831         mr      r4, r10         /* Destination Address          */
832         bl      board_init_r
833
834         /*
835          * Copy exception vector code to low memory
836          *
837          * r3: dest_addr
838          * r7: source address, r8: end address, r9: target address
839          */
840         .globl  trap_init
841 trap_init:
842         mflr    r4                      /* save link register           */
843         GET_GOT
844         lwz     r7, GOT(_start)
845         lwz     r8, GOT(_end_of_vectors)
846
847         li      r9, 0x100               /* reset vector always at 0x100 */
848
849         cmplw   0, r7, r8
850         bgelr                           /* return if r7>=r8 - just in case */
851 1:
852         lwz     r0, 0(r7)
853         stw     r0, 0(r9)
854         addi    r7, r7, 4
855         addi    r9, r9, 4
856         cmplw   0, r7, r8
857         bne     1b
858
859         /*
860          * relocate `hdlr' and `int_return' entries
861          */
862         li      r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
863         li      r8, Alignment - _start + EXC_OFF_SYS_RESET
864 2:
865         bl      trap_reloc
866         addi    r7, r7, 0x100           /* next exception vector        */
867         cmplw   0, r7, r8
868         blt     2b
869
870         li      r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
871         bl      trap_reloc
872
873         li      r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
874         bl      trap_reloc
875
876         li      r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
877         li      r8, SystemCall - _start + EXC_OFF_SYS_RESET
878 3:
879         bl      trap_reloc
880         addi    r7, r7, 0x100           /* next exception vector        */
881         cmplw   0, r7, r8
882         blt     3b
883
884         li      r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
885         li      r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
886 4:
887         bl      trap_reloc
888         addi    r7, r7, 0x100           /* next exception vector        */
889         cmplw   0, r7, r8
890         blt     4b
891
892         mfmsr   r3                      /* now that the vectors have    */
893         lis     r7, MSR_IP@h            /* relocated into low memory    */
894         ori     r7, r7, MSR_IP@l        /* MSR[IP] can be turned off    */
895         andc    r3, r3, r7              /* (if it was on)               */
896         SYNC                            /* Some chip revs need this... */
897         mtmsr   r3
898         SYNC
899
900         mtlr    r4                      /* restore link register    */
901         blr