]> git.sur5r.net Git - u-boot/blob - cpu/mpc86xx/start.S
Merge branch 'mpc86xx'
[u-boot] / 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      r10, r5         /* Save copy of Destination Address     */
818         
819         mr      r3,  r5                         /* Destination Address  */
820         lis     r4, CFG_MONITOR_BASE@h          /* Source      Address  */
821         ori     r4, r4, CFG_MONITOR_BASE@l
822         lwz     r5, GOT(__init_end)
823         sub     r5, r5, r4
824         li      r6, CFG_CACHELINE_SIZE          /* Cache Line Size      */
825
826         /*
827          * Fix GOT pointer:
828          *
829          * New GOT-PTR = (old GOT-PTR - CFG_MONITOR_BASE) + Destination Address
830          *
831          * Offset:
832          */
833         sub     r15, r10, r4
834
835         /* First our own GOT */
836         add     r14, r14, r15
837         /* then the one used by the C code */
838         add     r30, r30, r15
839
840         /*
841          * Now relocate code
842          */
843 #ifdef CONFIG_ECC
844         bl      board_relocate_rom
845         sync
846         mr      r3, r10                         /* Destination Address  */
847         lis     r4, CFG_MONITOR_BASE@h          /* Source      Address  */
848         ori     r4, r4, CFG_MONITOR_BASE@l
849         lwz     r5, GOT(__init_end)
850         sub     r5, r5, r4
851         li      r6, CFG_CACHELINE_SIZE          /* Cache Line Size      */
852 #else
853         cmplw   cr1,r3,r4
854         addi    r0,r5,3
855         srwi.   r0,r0,2
856         beq     cr1,4f          /* In place copy is not necessary       */
857         beq     7f              /* Protect against 0 count              */
858         mtctr   r0
859         bge     cr1,2f
860
861         la      r8,-4(r4)
862         la      r7,-4(r3)
863 1:      lwzu    r0,4(r8)
864         stwu    r0,4(r7)
865         bdnz    1b
866         b       4f
867
868 2:      slwi    r0,r0,2
869         add     r8,r4,r0
870         add     r7,r3,r0
871 3:      lwzu    r0,-4(r8)
872         stwu    r0,-4(r7)
873         bdnz    3b
874 #endif
875 /*
876  * Now flush the cache: note that we must start from a cache aligned
877  * address. Otherwise we might miss one cache line.
878  */
879 4:      cmpwi   r6,0
880         add     r5,r3,r5
881         beq     7f              /* Always flush prefetch queue in any case */
882         subi    r0,r6,1
883         andc    r3,r3,r0
884         mr      r4,r3
885 5:      dcbst   0,r4
886         add     r4,r4,r6
887         cmplw   r4,r5
888         blt     5b
889         sync                    /* Wait for all dcbst to complete on bus */
890         mr      r4,r3
891 6:      icbi    0,r4
892         add     r4,r4,r6
893         cmplw   r4,r5
894         blt     6b
895 7:      sync                    /* Wait for all icbi to complete on bus */
896         isync
897
898 /*
899  * We are done. Do not return, instead branch to second part of board
900  * initialization, now running from RAM.
901  */
902         addi    r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
903         mtlr    r0
904         blr
905
906 in_ram:
907 #ifdef CONFIG_ECC
908         bl      board_init_ecc
909 #endif
910         /*
911          * Relocation Function, r14 point to got2+0x8000
912          *
913          * Adjust got2 pointers, no need to check for 0, this code
914          * already puts a few entries in the table.
915          */
916         li      r0,__got2_entries@sectoff@l
917         la      r3,GOT(_GOT2_TABLE_)
918         lwz     r11,GOT(_GOT2_TABLE_)
919         mtctr   r0
920         sub     r11,r3,r11
921         addi    r3,r3,-4
922 1:      lwzu    r0,4(r3)
923         add     r0,r0,r11
924         stw     r0,0(r3)
925         bdnz    1b
926
927         /*
928          * Now adjust the fixups and the pointers to the fixups
929          * in case we need to move ourselves again.
930          */
931 2:      li      r0,__fixup_entries@sectoff@l
932         lwz     r3,GOT(_FIXUP_TABLE_)
933         cmpwi   r0,0
934         mtctr   r0
935         addi    r3,r3,-4
936         beq     4f
937 3:      lwzu    r4,4(r3)
938         lwzux   r0,r4,r11
939         add     r0,r0,r11
940         stw     r10,0(r3)
941         stw     r0,0(r4)
942         bdnz    3b
943 4:
944 /* clear_bss: */
945         /*
946          * Now clear BSS segment
947          */
948         lwz     r3,GOT(__bss_start)
949         lwz     r4,GOT(_end)
950
951         cmplw   0, r3, r4
952         beq     6f
953
954         li      r0, 0
955 5:
956         stw     r0, 0(r3)
957         addi    r3, r3, 4
958         cmplw   0, r3, r4
959         bne     5b
960 6:
961         mr      r3, r9          /* Init Date pointer            */
962         mr      r4, r10         /* Destination Address          */
963         bl      board_init_r
964
965         /* not reached - end relocate_code */
966 /*-----------------------------------------------------------------------*/
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         /* enable execptions from RAM vectors */
1027         mfmsr   r7
1028         li      r8,MSR_IP
1029         andc    r7,r7,r8
1030         mtmsr   r7
1031
1032         mtlr    r4                      /* restore link register        */
1033         blr
1034
1035         /*
1036          * Function: relocate entries for one exception vector
1037          */
1038 trap_reloc:
1039         lwz     r0, 0(r7)               /* hdlr ...                     */
1040         add     r0, r0, r3              /*  ... += dest_addr            */
1041         stw     r0, 0(r7)
1042
1043         lwz     r0, 4(r7)               /* int_return ...               */
1044         add     r0, r0, r3              /*  ... += dest_addr            */
1045         stw     r0, 4(r7)
1046
1047         sync
1048         isync
1049
1050         blr
1051
1052 .globl enable_ext_addr
1053 enable_ext_addr:
1054         mfspr   r0, HID0
1055         lis     r0, (HID0_HIGH_BAT_EN | HID0_XBSEN | HID0_XAEN)@h
1056         ori     r0, r0, (HID0_HIGH_BAT_EN | HID0_XBSEN | HID0_XAEN)@l
1057         mtspr   HID0, r0
1058         sync
1059         isync
1060         blr
1061
1062 #if (CFG_CCSRBAR_DEFAULT != CFG_CCSRBAR)
1063 .globl setup_ccsrbar
1064 setup_ccsrbar:          
1065         /* Special sequence needed to update CCSRBAR itself */
1066         lis     r4, CFG_CCSRBAR_DEFAULT@h
1067         ori     r4, r4, CFG_CCSRBAR_DEFAULT@l
1068
1069         lis     r5, CFG_CCSRBAR@h
1070         ori     r5, r5, CFG_CCSRBAR@l
1071         srwi    r6,r5,12
1072         stw     r6, 0(r4)
1073         isync
1074
1075         lis     r5, 0xffff
1076         ori     r5,r5,0xf000
1077         lwz     r5, 0(r5)
1078         isync
1079
1080         lis     r3, CFG_CCSRBAR@h
1081         lwz     r5, CFG_CCSRBAR@l(r3)
1082         isync
1083         
1084         blr
1085 #endif
1086                         
1087 #ifdef CFG_INIT_RAM_LOCK
1088 lock_ram_in_cache:
1089         /* Allocate Initial RAM in data cache.
1090          */
1091         lis     r3, (CFG_INIT_RAM_ADDR & ~31)@h
1092         ori     r3, r3, (CFG_INIT_RAM_ADDR & ~31)@l
1093         li      r2, ((CFG_INIT_RAM_END & ~31) + \
1094                      (CFG_INIT_RAM_ADDR & 31) + 31) / 32
1095         mtctr   r2
1096 1:
1097         dcbz    r0, r3
1098         addi    r3, r3, 32
1099         bdnz    1b
1100 #if 1
1101 /* Lock the data cache */
1102         mfspr   r0, HID0
1103         ori     r0, r0, 0x1000
1104         sync
1105         mtspr   HID0, r0
1106         sync
1107         blr
1108 #endif
1109 #if 0
1110         /* Lock the first way of the data cache */
1111         mfspr   r0, LDSTCR
1112         ori     r0, r0, 0x0080
1113 #if defined(CONFIG_ALTIVEC)
1114         dssall
1115 #endif
1116         sync
1117         mtspr   LDSTCR, r0
1118         sync
1119         isync
1120         blr
1121 #endif
1122         
1123 .globl unlock_ram_in_cache
1124 unlock_ram_in_cache:
1125         /* invalidate the INIT_RAM section */
1126         lis     r3, (CFG_INIT_RAM_ADDR & ~31)@h
1127         ori     r3, r3, (CFG_INIT_RAM_ADDR & ~31)@l
1128         li      r2, ((CFG_INIT_RAM_END & ~31) + \
1129                      (CFG_INIT_RAM_ADDR & 31) + 31) / 32
1130         mtctr   r2
1131 1:      icbi    r0, r3
1132         addi    r3, r3, 32
1133         bdnz    1b
1134         sync                    /* Wait for all icbi to complete on bus */
1135         isync
1136 #if 1
1137 /* Unlock the data cache and invalidate it */
1138         mfspr   r0, HID0
1139         li      r3,0x1000
1140         andc    r0,r0,r3
1141         li      r3,0x0400
1142         or      r0,r0,r3
1143         sync
1144         mtspr   HID0, r0
1145         sync
1146         blr
1147 #endif
1148 #if 0   
1149         /* Unlock the first way of the data cache */
1150         mfspr   r0, LDSTCR
1151         li      r3,0x0080
1152         andc    r0,r0,r3
1153 #ifdef CONFIG_ALTIVEC
1154         dssall
1155 #endif
1156         sync
1157         mtspr   LDSTCR, r0
1158         sync
1159         isync
1160         li      r3,0x0400
1161         or      r0,r0,r3
1162         sync
1163         mtspr   HID0, r0
1164         sync
1165         blr
1166 #endif
1167 #endif
1168
1169 /* If this is a multi-cpu system then we need to handle the
1170  * 2nd cpu.  The assumption is that the 2nd cpu is being
1171  * held in boot holdoff mode until the 1st cpu unlocks it
1172  * from Linux.  We'll do some basic cpu init and then pass
1173  * it to the Linux Reset Vector.
1174  * Sri:  Much of this initialization is not required. Linux
1175  * rewrites the bats, and the sprs and also enables the L1 cache.      
1176  */
1177 #if (CONFIG_NUM_CPUS > 1)
1178 .globl secondary_cpu_setup
1179 secondary_cpu_setup:    
1180         /* Do only core setup on all cores except cpu0 */
1181         bl      invalidate_bats
1182         sync
1183         bl      enable_ext_addr
1184         
1185 #ifdef CFG_L2
1186         /* init the L2 cache */
1187         addis   r3, r0, L2_INIT@h
1188         ori     r3, r3, L2_INIT@l
1189         sync
1190         mtspr   l2cr, r3
1191 #ifdef CONFIG_ALTIVEC
1192         dssall
1193 #endif
1194         /* invalidate the L2 cache */
1195         bl      l2cache_invalidate
1196         sync
1197 #endif
1198
1199         /* setup the bats */
1200         bl      setup_bats
1201         sync
1202         /* enable address translation */
1203         bl      enable_addr_trans
1204         sync
1205
1206         /* enable and invalidate the data cache */
1207         bl      dcache_enable
1208         sync
1209
1210         /* enable and invalidate the instruction cache*/
1211         bl      icache_enable
1212         sync
1213         
1214         /* Set up MSR and HID0, HID1*/        
1215         /* Enable interrupts */
1216 /*        mfmsr r28     
1217          li     r4,0
1218         ori     r4,r4,MSR_EE
1219         or      r28,r28,r4
1220         mtmsr   r28
1221   */      
1222
1223         /* TBEN  in HID0 */
1224         mfspr   r4, HID0
1225         oris    r4, r4, 0x0400 
1226         mtspr   HID0, r4
1227         sync
1228         isync
1229         
1230         /*SYNCBE|ABE in HID1*/
1231         mfspr   r4, HID1
1232         ori     r4, r4, 0x0C00 
1233         mtspr   HID1, r4
1234         sync
1235         isync
1236         
1237         lis     r3, CONFIG_LINUX_RESET_VEC@h
1238         ori     r3, r3, CONFIG_LINUX_RESET_VEC@l
1239         mtlr    r3
1240         blr
1241         
1242         /* Never Returns, Running in Linux Now */    
1243 #endif
1244