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