25687f8bb7538f2df04b45d4de4ab4d473c16b37
[oweals/u-boot.git] / cpu / mpc86xx / start.S
1 /*
2  * Copyright 2004 Freescale Semiconductor.
3  * Srikanth Srinivasan <srikanth.srinivaan@freescale.com>
4  *
5  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  * MA 02111-1307 USA
22  */
23
24 /*  U-Boot - Startup Code for 86xx PowerPC based Embedded Boards
25  *
26  *
27  *  The processor starts at 0xfff00100 and the code is executed
28  *  from flash. The code is organized to be at an other address
29  *  in memory, but as long we don't jump around before relocating.
30  *  board_init lies at a quite high address and when the cpu has
31  *  jumped there, everything is ok.
32  */
33 #include <config.h>
34 #include <mpc86xx.h>
35 #include <version.h>
36
37 #include <ppc_asm.tmpl>
38 #include <ppc_defs.h>
39
40 #include <asm/cache.h>
41 #include <asm/mmu.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 /* Machine Check and Recoverable Interr. */
51 #define MSR_KERNEL ( MSR_ME | MSR_RI )
52
53 /*
54  * Set up GOT: Global Offset Table
55  *
56  * Use r14 to access the GOT
57  */
58         START_GOT
59         GOT_ENTRY(_GOT2_TABLE_)
60         GOT_ENTRY(_FIXUP_TABLE_)
61
62         GOT_ENTRY(_start)
63         GOT_ENTRY(_start_of_vectors)
64         GOT_ENTRY(_end_of_vectors)
65         GOT_ENTRY(transfer_to_handler)
66
67         GOT_ENTRY(__init_end)
68         GOT_ENTRY(_end)
69         GOT_ENTRY(__bss_start)
70         END_GOT
71
72 /*
73  * r3 - 1st arg to board_init(): IMMP pointer
74  * r4 - 2nd arg to board_init(): boot flag
75  */
76         .text
77         .long   0x27051956              /* U-Boot Magic Number          */
78         .globl  version_string
79 version_string:
80         .ascii  U_BOOT_VERSION
81         .ascii  " (", __DATE__, " - ", __TIME__, ")"
82         .ascii  CONFIG_IDENT_STRING, "\0"
83
84         . = EXC_OFF_SYS_RESET
85         .globl  _start
86 _start:
87         li      r21, BOOTFLAG_COLD      /* Normal Power-On: Boot from FLASH */
88         b       boot_cold
89         sync
90
91         . = EXC_OFF_SYS_RESET + 0x10
92
93         .globl  _start_warm
94 _start_warm:
95         li      r21, BOOTFLAG_WARM      /* Software reboot              */
96         b       boot_warm
97         sync
98
99         /* the boot code is located below the exception table */
100
101         .globl  _start_of_vectors
102 _start_of_vectors:
103
104 /* Machine check */
105         STD_EXCEPTION(0x200, MachineCheck, MachineCheckException)
106
107 /* Data Storage exception. */
108         STD_EXCEPTION(0x300, DataStorage, UnknownException)
109
110 /* Instruction Storage exception. */
111         STD_EXCEPTION(0x400, InstStorage, UnknownException)
112
113 /* External Interrupt exception. */
114         STD_EXCEPTION(0x500, ExtInterrupt, external_interrupt)
115
116 /* Alignment exception. */
117         . = 0x600
118 Alignment:
119         EXCEPTION_PROLOG
120         mfspr   r4,DAR
121         stw     r4,_DAR(r21)
122         mfspr   r5,DSISR
123         stw     r5,_DSISR(r21)
124         addi    r3,r1,STACK_FRAME_OVERHEAD
125         li      r20,MSR_KERNEL
126         rlwimi  r20,r23,0,16,16         /* copy EE bit from saved MSR */
127         lwz     r6,GOT(transfer_to_handler)
128         mtlr    r6
129         blrl
130 .L_Alignment:
131         .long   AlignmentException - _start + EXC_OFF_SYS_RESET
132         .long   int_return - _start + EXC_OFF_SYS_RESET
133
134 /* Program check exception */
135         . = 0x700
136 ProgramCheck:
137         EXCEPTION_PROLOG
138         addi    r3,r1,STACK_FRAME_OVERHEAD
139         li      r20,MSR_KERNEL
140         rlwimi  r20,r23,0,16,16         /* copy EE bit from saved MSR */
141         lwz     r6,GOT(transfer_to_handler)
142         mtlr    r6
143         blrl
144 .L_ProgramCheck:
145         .long   ProgramCheckException - _start + EXC_OFF_SYS_RESET
146         .long   int_return - _start + EXC_OFF_SYS_RESET
147
148         STD_EXCEPTION(0x800, FPUnavailable, UnknownException)
149
150         /* I guess we could implement decrementer, and may have
151          * to someday for timekeeping.
152          */
153         STD_EXCEPTION(0x900, Decrementer, timer_interrupt)
154         STD_EXCEPTION(0xa00, Trap_0a, UnknownException)
155         STD_EXCEPTION(0xb00, Trap_0b, UnknownException)
156         STD_EXCEPTION(0xc00, SystemCall, UnknownException)
157         STD_EXCEPTION(0xd00, SingleStep, UnknownException)
158         STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
159         STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
160         STD_EXCEPTION(0x1000, SoftEmu, SoftEmuException)
161         STD_EXCEPTION(0x1100, InstructionTLBMiss, UnknownException)
162         STD_EXCEPTION(0x1200, DataTLBMiss, UnknownException)
163         STD_EXCEPTION(0x1300, InstructionTLBError, UnknownException)
164         STD_EXCEPTION(0x1400, DataTLBError, UnknownException)
165         STD_EXCEPTION(0x1500, Reserved5, UnknownException)
166         STD_EXCEPTION(0x1600, Reserved6, UnknownException)
167         STD_EXCEPTION(0x1700, Reserved7, UnknownException)
168         STD_EXCEPTION(0x1800, Reserved8, UnknownException)
169         STD_EXCEPTION(0x1900, Reserved9, UnknownException)
170         STD_EXCEPTION(0x1a00, ReservedA, UnknownException)
171         STD_EXCEPTION(0x1b00, ReservedB, UnknownException)
172         STD_EXCEPTION(0x1c00, DataBreakpoint, UnknownException)
173         STD_EXCEPTION(0x1d00, InstructionBreakpoint, UnknownException)
174         STD_EXCEPTION(0x1e00, PeripheralBreakpoint, UnknownException)
175         STD_EXCEPTION(0x1f00, DevPortBreakpoint, UnknownException)
176
177         .globl  _end_of_vectors
178 _end_of_vectors:
179
180         . = 0x2000
181
182 boot_cold:
183 boot_warm:
184
185         /* if this is a multi-core system we need to check which cpu
186          * this is, if it is not cpu 0 send the cpu to the linux reset 
187          * vector */
188 #if (CONFIG_NUM_CPUS > 1)
189         mfspr   r0, MSSCR0
190         andi.   r0, r0, 0x0020
191         rlwinm  r0,r0,27,31,31
192         mtspr   PIR, r0
193         beq     1f
194
195         bl      secondary_cpu_setup
196 #endif
197         
198         /* disable everything */
199 1:      li      r0, 0
200         mtspr   HID0, r0
201         sync
202         mtmsr   0
203         bl      invalidate_bats
204         sync
205         
206 #ifdef CFG_L2
207         /* init the L2 cache */
208         addis   r3, r0, L2_INIT@h
209         ori     r3, r3, L2_INIT@l
210         mtspr   l2cr, r3        
211         /* invalidate the L2 cache */
212         bl      l2cache_invalidate
213         sync
214 #endif
215         
216         /*
217          * Calculate absolute address in FLASH and jump there
218          *------------------------------------------------------*/
219         lis     r3, CFG_MONITOR_BASE@h
220         ori     r3, r3, CFG_MONITOR_BASE@l
221         addi    r3, r3, in_flash - _start + EXC_OFF_SYS_RESET
222         mtlr    r3
223         blr
224
225 in_flash:
226         /* let the C-code set up the rest                       */
227         /*                                                      */
228         /* Be careful to keep code relocatable !                */
229         /*------------------------------------------------------*/
230         /* perform low-level init */
231
232         /* enable extended addressing */
233         bl      enable_ext_addr
234         
235         /* setup the bats */
236         bl      setup_bats
237         sync
238
239 #if (CFG_CCSRBAR_DEFAULT != CFG_CCSRBAR)
240         /* setup ccsrbar */
241         bl      setup_ccsrbar
242 #endif
243         
244         /* Fix for SMP linux - Changing arbitration to round-robin */
245         lis     r3, CFG_CCSRBAR@h
246         ori     r3, r3, 0x1000
247         xor     r4, r4, r4
248         li      r4, 0x1000
249         stw     r4, 0(r3)
250
251         /* setup the law entries */
252         bl      law_entry
253         sync
254
255         /* Don't use this feature due to bug in 8641D PD4 */
256         /* Disable ERD_DIS */
257         lis     r3, CFG_CCSRBAR@h
258         ori     r3, r3, 0x1008
259         lwz     r4, 0(r3)
260         oris    r4, r4, 0x4000
261         stw     r4, 0(r3)
262         sync
263
264 #if (EMULATOR_RUN == 1)
265         /* On the emulator we want to adjust these ASAP */
266         /* otherwise things are sloooow */
267         /* Setup OR0 (LALE FIX)*/
268         lis     r3, CFG_CCSRBAR@h
269         ori     r3, r3, 0x5004
270         li      r4, 0x0FF3
271         stw     r4, 0(r3)
272         sync
273
274         /* Setup LCRR */
275         lis     r3, CFG_CCSRBAR@h
276         ori     r3, r3, 0x50D4
277         lis     r4, 0x8000
278         ori     r4, r4, 0x0002
279         stw     r4, 0(r3)
280         sync
281 #endif
282 #if 1   
283         /* make sure timer enabled in guts register too */
284         lis     r3, CFG_CCSRBAR@h
285         oris    r3,r3, 0xE
286         ori     r3,r3,0x0070
287         lwz     r4, 0(r3)
288         lis     r5,0xFFFC
289         ori     r5,r5,0x5FFF
290         and     r4,r4,r5
291         stw     r4,0(r3)
292 #endif  
293         /*
294          * Cache must be enabled here for stack-in-cache trick.
295          * This means we need to enable the BATS.
296          * Cache should be turned on after BATs, since by default
297          * everything is write-through.
298          */
299
300         /* enable address translation */
301         bl      enable_addr_trans
302         sync
303
304         /* enable and invalidate the data cache */
305 /*      bl      l1dcache_enable */
306         bl      dcache_enable 
307         sync
308
309 #if 1
310         bl      icache_enable
311 #endif
312         
313 #ifdef CFG_INIT_RAM_LOCK
314         bl      lock_ram_in_cache
315         sync
316 #endif
317
318         /* set up the stack pointer in our newly created
319          * cache-ram (r1) */
320         lis     r1, (CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET)@h
321         ori     r1, r1, (CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET)@l
322
323         li      r0, 0           /* Make room for stack frame header and */
324         stwu    r0, -4(r1)      /* clear final stack frame so that      */
325         stwu    r0, -4(r1)      /* stack backtraces terminate cleanly   */
326
327         GET_GOT                 /* initialize GOT access        */
328
329         /* run low-level CPU init code     (from Flash) */
330         bl      cpu_init_f
331         sync
332
333 #ifdef  RUN_DIAG        
334
335         /* Sri:  Code to run the diagnostic automatically */
336
337         /* Load PX_AUX register address in r4 */
338         lis     r4, 0xf810
339         ori     r4, r4, 0x6
340         /* Load contents of PX_AUX in r3 bits 24 to 31*/
341         lbz     r3, 0(r4)
342
343         /* Mask and obtain the bit in r3 */
344         rlwinm. r3, r3, 0, 24, 24
345         /* If not zero, jump and continue with u-boot */
346         bne     diag_done
347
348         /* Load back contents of PX_AUX in r3 bits 24 to 31 */
349         lbz     r3, 0(r4)
350         /* Set the MSB of the register value */
351         ori     r3, r3, 0x80
352         /* Write value in r3 back to PX_AUX */
353         stb     r3, 0(r4)
354
355         /* Get the address to jump to in r3*/
356         lis     r3, CFG_DIAG_ADDR@h
357         ori     r3, r3, CFG_DIAG_ADDR@l
358
359         /* Load the LR with the branch address */
360         mtlr    r3
361
362         /* Branch to diagnostic */
363         blr
364         
365 diag_done:      
366 #endif        
367
368   /*      bl      l2cache_enable*/
369         mr      r3, r21
370
371         /* r3: BOOTFLAG */
372         /* run 1st part of board init code (from Flash)   */
373         bl      board_init_f
374         sync
375
376         /* NOTREACHED */
377
378         .globl  invalidate_bats
379 invalidate_bats:
380         
381         /* invalidate BATs */
382         mtspr   IBAT0U, r0
383         mtspr   IBAT1U, r0
384         mtspr   IBAT2U, r0
385         mtspr   IBAT3U, r0
386         mtspr   IBAT4U, r0
387         mtspr   IBAT5U, r0
388         mtspr   IBAT6U, r0
389         mtspr   IBAT7U, r0
390
391         isync
392         mtspr   DBAT0U, r0
393         mtspr   DBAT1U, r0
394         mtspr   DBAT2U, r0
395         mtspr   DBAT3U, r0
396         mtspr   DBAT4U, r0
397         mtspr   DBAT5U, r0
398         mtspr   DBAT6U, r0
399         mtspr   DBAT7U, r0
400
401         isync
402         sync
403         blr
404         
405         
406         /* setup_bats - set them up to some initial state */
407         .globl  setup_bats
408 setup_bats:
409         
410         addis   r0, r0, 0x0000
411
412         /* IBAT 0 */
413         addis   r4, r0, CFG_IBAT0L@h
414         ori     r4, r4, CFG_IBAT0L@l
415         addis   r3, r0, CFG_IBAT0U@h
416         ori     r3, r3, CFG_IBAT0U@l
417         mtspr   IBAT0L, r4
418         mtspr   IBAT0U, r3
419         isync
420
421         /* DBAT 0 */
422         addis   r4, r0, CFG_DBAT0L@h
423         ori     r4, r4, CFG_DBAT0L@l
424         addis   r3, r0, CFG_DBAT0U@h
425         ori     r3, r3, CFG_DBAT0U@l
426         mtspr   DBAT0L, r4
427         mtspr   DBAT0U, r3
428         isync
429
430         /* IBAT 1 */
431         addis   r4, r0, CFG_IBAT1L@h
432         ori     r4, r4, CFG_IBAT1L@l
433         addis   r3, r0, CFG_IBAT1U@h
434         ori     r3, r3, CFG_IBAT1U@l
435         mtspr   IBAT1L, r4
436         mtspr   IBAT1U, r3
437         isync
438
439         /* DBAT 1 */
440         addis   r4, r0, CFG_DBAT1L@h
441         ori     r4, r4, CFG_DBAT1L@l
442         addis   r3, r0, CFG_DBAT1U@h
443         ori     r3, r3, CFG_DBAT1U@l
444         mtspr   DBAT1L, r4
445         mtspr   DBAT1U, r3
446         isync
447
448         /* IBAT 2 */
449         addis   r4, r0, CFG_IBAT2L@h
450         ori     r4, r4, CFG_IBAT2L@l
451         addis   r3, r0, CFG_IBAT2U@h
452         ori     r3, r3, CFG_IBAT2U@l
453         mtspr   IBAT2L, r4
454         mtspr   IBAT2U, r3
455         isync
456
457         /* DBAT 2 */
458         addis   r4, r0, CFG_DBAT2L@h
459         ori     r4, r4, CFG_DBAT2L@l
460         addis   r3, r0, CFG_DBAT2U@h
461         ori     r3, r3, CFG_DBAT2U@l
462         mtspr   DBAT2L, r4
463         mtspr   DBAT2U, r3
464         isync
465
466         /* IBAT 3 */
467         addis   r4, r0, CFG_IBAT3L@h
468         ori     r4, r4, CFG_IBAT3L@l
469         addis   r3, r0, CFG_IBAT3U@h
470         ori     r3, r3, CFG_IBAT3U@l
471         mtspr   IBAT3L, r4
472         mtspr   IBAT3U, r3
473         isync
474
475         /* DBAT 3 */
476         addis   r4, r0, CFG_DBAT3L@h
477         ori     r4, r4, CFG_DBAT3L@l
478         addis   r3, r0, CFG_DBAT3U@h
479         ori     r3, r3, CFG_DBAT3U@l
480         mtspr   DBAT3L, r4
481         mtspr   DBAT3U, r3
482         isync
483
484         /* IBAT 4 */
485         addis   r4, r0, CFG_IBAT4L@h
486         ori     r4, r4, CFG_IBAT4L@l
487         addis   r3, r0, CFG_IBAT4U@h
488         ori     r3, r3, CFG_IBAT4U@l
489         mtspr   IBAT4L, r4
490         mtspr   IBAT4U, r3
491         isync
492
493         /* DBAT 4 */
494         addis   r4, r0, CFG_DBAT4L@h
495         ori     r4, r4, CFG_DBAT4L@l
496         addis   r3, r0, CFG_DBAT4U@h
497         ori     r3, r3, CFG_DBAT4U@l
498         mtspr   DBAT4L, r4
499         mtspr   DBAT4U, r3
500         isync
501
502         /* IBAT 5 */
503         addis   r4, r0, CFG_IBAT5L@h
504         ori     r4, r4, CFG_IBAT5L@l
505         addis   r3, r0, CFG_IBAT5U@h
506         ori     r3, r3, CFG_IBAT5U@l
507         mtspr   IBAT5L, r4
508         mtspr   IBAT5U, r3
509         isync
510
511         /* DBAT 5 */
512         addis   r4, r0, CFG_DBAT5L@h
513         ori     r4, r4, CFG_DBAT5L@l
514         addis   r3, r0, CFG_DBAT5U@h
515         ori     r3, r3, CFG_DBAT5U@l
516         mtspr   DBAT5L, r4
517         mtspr   DBAT5U, r3
518         isync
519
520         /* IBAT 6 */
521         addis   r4, r0, CFG_IBAT6L@h
522         ori     r4, r4, CFG_IBAT6L@l
523         addis   r3, r0, CFG_IBAT6U@h
524         ori     r3, r3, CFG_IBAT6U@l
525         mtspr   IBAT6L, r4
526         mtspr   IBAT6U, r3
527         isync
528
529         /* DBAT 6 */
530         addis   r4, r0, CFG_DBAT6L@h
531         ori     r4, r4, CFG_DBAT6L@l
532         addis   r3, r0, CFG_DBAT6U@h
533         ori     r3, r3, CFG_DBAT6U@l
534         mtspr   DBAT6L, r4
535         mtspr   DBAT6U, r3
536         isync
537
538         /* IBAT 7 */
539         addis   r4, r0, CFG_IBAT7L@h
540         ori     r4, r4, CFG_IBAT7L@l
541         addis   r3, r0, CFG_IBAT7U@h
542         ori     r3, r3, CFG_IBAT7U@l
543         mtspr   IBAT7L, r4
544         mtspr   IBAT7U, r3
545         isync
546
547         /* DBAT 7 */
548         addis   r4, r0, CFG_DBAT7L@h
549         ori     r4, r4, CFG_DBAT7L@l
550         addis   r3, r0, CFG_DBAT7U@h
551         ori     r3, r3, CFG_DBAT7U@l
552         mtspr   DBAT7L, r4
553         mtspr   DBAT7U, r3
554         isync
555
556 1:      
557         addis   r3, 0, 0x0000
558         addis   r5, 0, 0x4    /* upper bound of 0x00040000 for 7400/750 */
559         isync
560
561 tlblp:
562         tlbie   r3
563         sync
564         addi    r3, r3, 0x1000
565         cmp     0, 0, r3, r5
566         blt tlblp
567
568         blr
569
570         .globl enable_addr_trans
571 enable_addr_trans:
572         /* enable address translation */
573         mfmsr   r5
574         ori     r5, r5, (MSR_IR | MSR_DR)
575         mtmsr   r5
576         isync
577         blr
578
579         .globl disable_addr_trans
580 disable_addr_trans:
581         /* disable address translation */
582         mflr    r4
583         mfmsr   r3
584         andi.   r0, r3, (MSR_IR | MSR_DR)
585         beqlr
586         andc    r3, r3, r0
587         mtspr   SRR0, r4
588         mtspr   SRR1, r3
589         rfi
590
591 /*
592  * This code finishes saving the registers to the exception frame
593  * and jumps to the appropriate handler for the exception.
594  * Register r21 is pointer into trap frame, r1 has new stack pointer.
595  */
596         .globl  transfer_to_handler
597 transfer_to_handler:
598         stw     r22,_NIP(r21)
599         lis     r22,MSR_POW@h
600         andc    r23,r23,r22
601         stw     r23,_MSR(r21)
602         SAVE_GPR(7, r21)
603         SAVE_4GPRS(8, r21)
604         SAVE_8GPRS(12, r21)
605         SAVE_8GPRS(24, r21)
606         mflr    r23
607         andi.   r24,r23,0x3f00          /* get vector offset */
608         stw     r24,TRAP(r21)
609         li      r22,0
610         stw     r22,RESULT(r21)
611         mtspr   SPRG2,r22               /* r1 is now kernel sp */
612         lwz     r24,0(r23)              /* virtual address of handler */
613         lwz     r23,4(r23)              /* where to go when done */
614         mtspr   SRR0,r24
615         mtspr   SRR1,r20
616         mtlr    r23
617         SYNC
618         rfi                             /* jump to handler, enable MMU */
619
620 int_return:
621         mfmsr   r28             /* Disable interrupts */
622         li      r4,0
623         ori     r4,r4,MSR_EE
624         andc    r28,r28,r4
625         SYNC                    /* Some chip revs need this... */
626         mtmsr   r28
627         SYNC
628         lwz     r2,_CTR(r1)
629         lwz     r0,_LINK(r1)
630         mtctr   r2
631         mtlr    r0
632         lwz     r2,_XER(r1)
633         lwz     r0,_CCR(r1)
634         mtspr   XER,r2
635         mtcrf   0xFF,r0
636         REST_10GPRS(3, r1)
637         REST_10GPRS(13, r1)
638         REST_8GPRS(23, r1)
639         REST_GPR(31, r1)
640         lwz     r2,_NIP(r1)     /* Restore environment */
641         lwz     r0,_MSR(r1)
642         mtspr   SRR0,r2
643         mtspr   SRR1,r0
644         lwz     r0,GPR0(r1)
645         lwz     r2,GPR2(r1)
646         lwz     r1,GPR1(r1)
647         SYNC
648         rfi
649
650         .globl  dc_read
651 dc_read:
652         blr
653
654         .globl get_pvr
655 get_pvr:
656         mfspr   r3, PVR
657         blr
658
659         .globl get_svr
660 get_svr:
661         mfspr   r3, SVR
662         blr
663
664
665 /*------------------------------------------------------------------------------- */
666 /* Function:     in8 */
667 /* Description:  Input 8 bits */
668 /*------------------------------------------------------------------------------- */
669         .globl  in8
670 in8:
671         lbz     r3,0x0000(r3)
672         blr
673
674 /*------------------------------------------------------------------------------- */
675 /* Function:     out8 */
676 /* Description:  Output 8 bits */
677 /*------------------------------------------------------------------------------- */
678         .globl  out8
679 out8:
680         stb     r4,0x0000(r3)
681         blr
682
683 /*------------------------------------------------------------------------------- */
684 /* Function:     out16 */
685 /* Description:  Output 16 bits */
686 /*------------------------------------------------------------------------------- */
687         .globl  out16
688 out16:
689         sth     r4,0x0000(r3)
690         blr
691
692 /*------------------------------------------------------------------------------- */
693 /* Function:     out16r */
694 /* Description:  Byte reverse and output 16 bits */
695 /*------------------------------------------------------------------------------- */
696         .globl  out16r
697 out16r:
698         sthbrx  r4,r0,r3
699         blr
700
701 /*------------------------------------------------------------------------------- */
702 /* Function:     out32 */
703 /* Description:  Output 32 bits */
704 /*------------------------------------------------------------------------------- */
705         .globl  out32
706 out32:
707         stw     r4,0x0000(r3)
708         blr
709
710 /*------------------------------------------------------------------------------- */
711 /* Function:     out32r */
712 /* Description:  Byte reverse and output 32 bits */
713 /*------------------------------------------------------------------------------- */
714         .globl  out32r
715 out32r:
716         stwbrx  r4,r0,r3
717         blr
718
719 /*------------------------------------------------------------------------------- */
720 /* Function:     in16 */
721 /* Description:  Input 16 bits */
722 /*------------------------------------------------------------------------------- */
723         .globl  in16
724 in16:
725         lhz     r3,0x0000(r3)
726         blr
727
728 /*------------------------------------------------------------------------------- */
729 /* Function:     in16r */
730 /* Description:  Input 16 bits and byte reverse */
731 /*------------------------------------------------------------------------------- */
732         .globl  in16r
733 in16r:
734         lhbrx   r3,r0,r3
735         blr
736
737 /*------------------------------------------------------------------------------- */
738 /* Function:     in32 */
739 /* Description:  Input 32 bits */
740 /*------------------------------------------------------------------------------- */
741         .globl  in32
742 in32:
743         lwz     3,0x0000(3)
744         blr
745
746 /*------------------------------------------------------------------------------- */
747 /* Function:     in32r */
748 /* Description:  Input 32 bits and byte reverse */
749 /*------------------------------------------------------------------------------- */
750         .globl  in32r
751 in32r:
752         lwbrx   r3,r0,r3
753         blr
754
755 /*------------------------------------------------------------------------------- */
756 /* Function:     ppcDcbf */
757 /* Description:  Data Cache block flush */
758 /* Input:        r3 = effective address */
759 /* Output:       none. */
760 /*------------------------------------------------------------------------------- */
761         .globl  ppcDcbf
762 ppcDcbf:
763         dcbf    r0,r3
764         blr
765
766 /*------------------------------------------------------------------------------- */
767 /* Function:     ppcDcbi */
768 /* Description:  Data Cache block Invalidate */
769 /* Input:        r3 = effective address */
770 /* Output:       none. */
771 /*------------------------------------------------------------------------------- */
772         .globl  ppcDcbi
773 ppcDcbi:
774         dcbi    r0,r3
775         blr
776
777 /*--------------------------------------------------------------------------
778  * Function:     ppcDcbz
779  * Description:  Data Cache block zero.
780  * Input:        r3 = effective address
781  * Output:       none.
782  *-------------------------------------------------------------------------- */
783
784         .globl  ppcDcbz
785 ppcDcbz:
786         dcbz    r0,r3
787         blr
788
789 /*-------------------------------------------------------------------------- */
790 /* Function:     ppcSync */
791 /* Description:  Processor Synchronize */
792 /* Input:        none. */
793 /* Output:       none. */
794 /*-------------------------------------------------------------------------- */
795         .globl  ppcSync
796 ppcSync:
797         sync
798         blr
799         
800 /*-----------------------------------------------------------------------*/
801 /*
802  * void relocate_code (addr_sp, gd, addr_moni)
803  *
804  * This "function" does not return, instead it continues in RAM
805  * after relocating the monitor code.
806  *
807  * r3 = dest
808  * r4 = src
809  * r5 = length in bytes
810  * r6 = cachelinesize
811  */
812         .globl  relocate_code
813 relocate_code:
814
815         mr      r1,  r3         /* Set new stack pointer                */
816         mr      r9,  r4         /* Save copy of Global Data pointer     */
817         mr      r29, r9         /* Save for DECLARE_GLOBAL_DATA_PTR     */
818         mr      r10, r5         /* Save copy of Destination Address     */
819
820         mr      r3,  r5                         /* Destination Address  */
821         lis     r4, CFG_MONITOR_BASE@h          /* Source      Address  */
822         ori     r4, r4, CFG_MONITOR_BASE@l
823         lwz     r5, GOT(__init_end)
824         sub     r5, r5, r4
825         li      r6, CFG_CACHELINE_SIZE          /* Cache Line Size      */
826
827         /*
828          * Fix GOT pointer:
829          *
830          * New GOT-PTR = (old GOT-PTR - CFG_MONITOR_BASE) + Destination Address
831          *
832          * Offset:
833          */
834         sub     r15, r10, r4
835
836         /* First our own GOT */
837         add     r14, r14, r15
838         /* then the one used by the C code */
839         add     r30, r30, r15
840
841         /*
842          * Now relocate code
843          */
844 #ifdef CONFIG_ECC
845         bl      board_relocate_rom
846         sync
847         mr      r3, r10                         /* Destination Address  */
848         lis     r4, CFG_MONITOR_BASE@h          /* Source      Address  */
849         ori     r4, r4, CFG_MONITOR_BASE@l
850         lwz     r5, GOT(__init_end)
851         sub     r5, r5, r4
852         li      r6, CFG_CACHELINE_SIZE          /* Cache Line Size      */
853 #else
854         cmplw   cr1,r3,r4
855         addi    r0,r5,3
856         srwi.   r0,r0,2
857         beq     cr1,4f          /* In place copy is not necessary       */
858         beq     7f              /* Protect against 0 count              */
859         mtctr   r0
860         bge     cr1,2f
861
862         la      r8,-4(r4)
863         la      r7,-4(r3)
864 1:      lwzu    r0,4(r8)
865         stwu    r0,4(r7)
866         bdnz    1b
867         b       4f
868
869 2:      slwi    r0,r0,2
870         add     r8,r4,r0
871         add     r7,r3,r0
872 3:      lwzu    r0,-4(r8)
873         stwu    r0,-4(r7)
874         bdnz    3b
875 #endif
876 /*
877  * Now flush the cache: note that we must start from a cache aligned
878  * address. Otherwise we might miss one cache line.
879  */
880 4:      cmpwi   r6,0
881         add     r5,r3,r5
882         beq     7f              /* Always flush prefetch queue in any case */
883         subi    r0,r6,1
884         andc    r3,r3,r0
885         mr      r4,r3
886 5:      dcbst   0,r4
887         add     r4,r4,r6
888         cmplw   r4,r5
889         blt     5b
890         sync                    /* Wait for all dcbst to complete on bus */
891         mr      r4,r3
892 6:      icbi    0,r4
893         add     r4,r4,r6
894         cmplw   r4,r5
895         blt     6b
896 7:      sync                    /* Wait for all icbi to complete on bus */
897         isync
898
899 /*
900  * We are done. Do not return, instead branch to second part of board
901  * initialization, now running from RAM.
902  */
903         addi    r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
904         mtlr    r0
905         blr
906
907 in_ram:
908 #ifdef CONFIG_ECC
909         bl      board_init_ecc
910 #endif
911         /*
912          * Relocation Function, r14 point to got2+0x8000
913          *
914          * Adjust got2 pointers, no need to check for 0, this code
915          * already puts a few entries in the table.
916          */
917         li      r0,__got2_entries@sectoff@l
918         la      r3,GOT(_GOT2_TABLE_)
919         lwz     r11,GOT(_GOT2_TABLE_)
920         mtctr   r0
921         sub     r11,r3,r11
922         addi    r3,r3,-4
923 1:      lwzu    r0,4(r3)
924         add     r0,r0,r11
925         stw     r0,0(r3)
926         bdnz    1b
927
928         /*
929          * Now adjust the fixups and the pointers to the fixups
930          * in case we need to move ourselves again.
931          */
932 2:      li      r0,__fixup_entries@sectoff@l
933         lwz     r3,GOT(_FIXUP_TABLE_)
934         cmpwi   r0,0
935         mtctr   r0
936         addi    r3,r3,-4
937         beq     4f
938 3:      lwzu    r4,4(r3)
939         lwzux   r0,r4,r11
940         add     r0,r0,r11
941         stw     r10,0(r3)
942         stw     r0,0(r4)
943         bdnz    3b
944 4:
945 /* clear_bss: */
946         /*
947          * Now clear BSS segment
948          */
949         lwz     r3,GOT(__bss_start)
950         lwz     r4,GOT(_end)
951
952         cmplw   0, r3, r4
953         beq     6f
954
955         li      r0, 0
956 5:
957         stw     r0, 0(r3)
958         addi    r3, r3, 4
959         cmplw   0, r3, r4
960         bne     5b
961 6:
962         mr      r3, r9          /* Init Date pointer            */
963         mr      r4, r10         /* Destination Address          */
964         bl      board_init_r
965
966         /* not reached - end relocate_code */
967 /*-----------------------------------------------------------------------*/
968
969         /*
970          * Copy exception vector code to low memory
971          *
972          * r3: dest_addr
973          * r7: source address, r8: end address, r9: target address
974          */
975         .globl  trap_init
976 trap_init:
977         lwz     r7, GOT(_start)
978         lwz     r8, GOT(_end_of_vectors)
979
980         li      r9, 0x100               /* reset vector always at 0x100 */
981
982         cmplw   0, r7, r8
983         bgelr                           /* return if r7>=r8 - just in case */
984
985         mflr    r4                      /* save link register           */
986 1:
987         lwz     r0, 0(r7)
988         stw     r0, 0(r9)
989         addi    r7, r7, 4
990         addi    r9, r9, 4
991         cmplw   0, r7, r8
992         bne     1b
993
994         /*
995          * relocate `hdlr' and `int_return' entries
996          */
997         li      r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
998         li      r8, Alignment - _start + EXC_OFF_SYS_RESET
999 2:
1000         bl      trap_reloc
1001         addi    r7, r7, 0x100           /* next exception vector        */
1002         cmplw   0, r7, r8
1003         blt     2b
1004
1005         li      r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
1006         bl      trap_reloc
1007
1008         li      r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
1009         bl      trap_reloc
1010
1011         li      r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
1012         li      r8, SystemCall - _start + EXC_OFF_SYS_RESET
1013 3:
1014         bl      trap_reloc
1015         addi    r7, r7, 0x100           /* next exception vector        */
1016         cmplw   0, r7, r8
1017         blt     3b
1018
1019         li      r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
1020         li      r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
1021 4:
1022         bl      trap_reloc
1023         addi    r7, r7, 0x100           /* next exception vector        */
1024         cmplw   0, r7, r8
1025         blt     4b
1026
1027         /* enable execptions from RAM vectors */
1028         mfmsr   r7
1029         li      r8,MSR_IP
1030         andc    r7,r7,r8
1031         mtmsr   r7
1032
1033         mtlr    r4                      /* restore link register        */
1034         blr
1035
1036         /*
1037          * Function: relocate entries for one exception vector
1038          */
1039 trap_reloc:
1040         lwz     r0, 0(r7)               /* hdlr ...                     */
1041         add     r0, r0, r3              /*  ... += dest_addr            */
1042         stw     r0, 0(r7)
1043
1044         lwz     r0, 4(r7)               /* int_return ...               */
1045         add     r0, r0, r3              /*  ... += dest_addr            */
1046         stw     r0, 4(r7)
1047
1048         sync
1049         isync
1050
1051         blr
1052
1053 .globl enable_ext_addr
1054 enable_ext_addr:
1055         mfspr   r0, HID0
1056         lis     r0, (HID0_HIGH_BAT_EN | HID0_XBSEN | HID0_XAEN)@h
1057         ori     r0, r0, (HID0_HIGH_BAT_EN | HID0_XBSEN | HID0_XAEN)@l
1058         mtspr   HID0, r0
1059         sync
1060         isync
1061         blr
1062
1063 #if (CFG_CCSRBAR_DEFAULT != CFG_CCSRBAR)
1064 .globl setup_ccsrbar
1065 setup_ccsrbar:          
1066         /* Special sequence needed to update CCSRBAR itself */
1067         lis     r4, CFG_CCSRBAR_DEFAULT@h
1068         ori     r4, r4, CFG_CCSRBAR_DEFAULT@l
1069
1070         lis     r5, CFG_CCSRBAR@h
1071         ori     r5, r5, CFG_CCSRBAR@l
1072         srwi    r6,r5,12
1073         stw     r6, 0(r4)
1074         isync
1075
1076         lis     r5, 0xffff
1077         ori     r5,r5,0xf000
1078         lwz     r5, 0(r5)
1079         isync
1080
1081         lis     r3, CFG_CCSRBAR@h
1082         lwz     r5, CFG_CCSRBAR@l(r3)
1083         isync
1084         
1085         blr
1086 #endif
1087                         
1088 #ifdef CFG_INIT_RAM_LOCK
1089 lock_ram_in_cache:
1090         /* Allocate Initial RAM in data cache.
1091          */
1092         lis     r3, (CFG_INIT_RAM_ADDR & ~31)@h
1093         ori     r3, r3, (CFG_INIT_RAM_ADDR & ~31)@l
1094         li      r2, ((CFG_INIT_RAM_END & ~31) + \
1095                      (CFG_INIT_RAM_ADDR & 31) + 31) / 32
1096         mtctr   r2
1097 1:
1098         dcbz    r0, r3
1099         addi    r3, r3, 32
1100         bdnz    1b
1101 #if 1
1102 /* Lock the data cache */
1103         mfspr   r0, HID0
1104         ori     r0, r0, 0x1000
1105         sync
1106         mtspr   HID0, r0
1107         sync
1108         blr
1109 #endif
1110 #if 0
1111         /* Lock the first way of the data cache */
1112         mfspr   r0, LDSTCR
1113         ori     r0, r0, 0x0080
1114 #if defined(CONFIG_ALTIVEC)
1115         dssall
1116 #endif
1117         sync
1118         mtspr   LDSTCR, r0
1119         sync
1120         isync
1121         blr
1122 #endif
1123         
1124 .globl unlock_ram_in_cache
1125 unlock_ram_in_cache:
1126         /* invalidate the INIT_RAM section */
1127         lis     r3, (CFG_INIT_RAM_ADDR & ~31)@h
1128         ori     r3, r3, (CFG_INIT_RAM_ADDR & ~31)@l
1129         li      r2, ((CFG_INIT_RAM_END & ~31) + \
1130                      (CFG_INIT_RAM_ADDR & 31) + 31) / 32
1131         mtctr   r2
1132 1:      icbi    r0, r3
1133         addi    r3, r3, 32
1134         bdnz    1b
1135         sync                    /* Wait for all icbi to complete on bus */
1136         isync
1137 #if 1
1138 /* Unlock the data cache and invalidate it */
1139         mfspr   r0, HID0
1140         li      r3,0x1000
1141         andc    r0,r0,r3
1142         li      r3,0x0400
1143         or      r0,r0,r3
1144         sync
1145         mtspr   HID0, r0
1146         sync
1147         blr
1148 #endif
1149 #if 0   
1150         /* Unlock the first way of the data cache */
1151         mfspr   r0, LDSTCR
1152         li      r3,0x0080
1153         andc    r0,r0,r3
1154 #ifdef CONFIG_ALTIVEC
1155         dssall
1156 #endif
1157         sync
1158         mtspr   LDSTCR, r0
1159         sync
1160         isync
1161         li      r3,0x0400
1162         or      r0,r0,r3
1163         sync
1164         mtspr   HID0, r0
1165         sync
1166         blr
1167 #endif
1168 #endif
1169
1170 /* If this is a multi-cpu system then we need to handle the
1171  * 2nd cpu.  The assumption is that the 2nd cpu is being
1172  * held in boot holdoff mode until the 1st cpu unlocks it
1173  * from Linux.  We'll do some basic cpu init and then pass
1174  * it to the Linux Reset Vector.
1175  * Sri:  Much of this initialization is not required. Linux
1176  * rewrites the bats, and the sprs and also enables the L1 cache.      
1177  */
1178 #if (CONFIG_NUM_CPUS > 1)
1179 .globl secondary_cpu_setup
1180 secondary_cpu_setup:    
1181         /* Do only core setup on all cores except cpu0 */
1182         bl      invalidate_bats
1183         sync
1184         bl      enable_ext_addr
1185         
1186 #ifdef CFG_L2
1187         /* init the L2 cache */
1188         addis   r3, r0, L2_INIT@h
1189         ori     r3, r3, L2_INIT@l
1190         sync
1191         mtspr   l2cr, r3
1192 #ifdef CONFIG_ALTIVEC
1193         dssall
1194 #endif
1195         /* invalidate the L2 cache */
1196         bl      l2cache_invalidate
1197         sync
1198 #endif
1199
1200         /* enable and invalidate the data cache */
1201         bl      dcache_enable
1202         sync
1203
1204         /* enable and invalidate the instruction cache*/
1205         bl      icache_enable
1206         sync
1207         
1208
1209         /* TBEN  in HID0 */
1210         mfspr   r4, HID0
1211         oris    r4, r4, 0x0400 
1212         mtspr   HID0, r4
1213         sync
1214         isync
1215         
1216         /*SYNCBE|ABE in HID1*/
1217         mfspr   r4, HID1
1218         ori     r4, r4, 0x0C00 
1219         mtspr   HID1, r4
1220         sync
1221         isync
1222         
1223         lis     r3, CONFIG_LINUX_RESET_VEC@h
1224         ori     r3, r3, CONFIG_LINUX_RESET_VEC@l
1225         mtlr    r3
1226         blr
1227         
1228         /* Never Returns, Running in Linux Now */    
1229 #endif
1230