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