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