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