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