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