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