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