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