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