531bd0c5fbdbdcc367f8684f4eb27fe1548cadbb
[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         sync
211         mtspr   l2cr, r3        
212 #ifdef CONFIG_ALTIVEC
213         dssall
214 #endif
215         /* invalidate the L2 cache */
216         bl      l2cache_invalidate
217         sync
218 #endif
219         
220         /*
221          * Calculate absolute address in FLASH and jump there
222          *------------------------------------------------------*/
223         lis     r3, CFG_MONITOR_BASE@h
224         ori     r3, r3, CFG_MONITOR_BASE@l
225         addi    r3, r3, in_flash - _start + EXC_OFF_SYS_RESET
226         mtlr    r3
227         blr
228
229 in_flash:
230         /* let the C-code set up the rest                       */
231         /*                                                      */
232         /* Be careful to keep code relocatable !                */
233         /*------------------------------------------------------*/
234         /* perform low-level init */
235
236         /* enable extended addressing */
237         bl      enable_ext_addr
238         
239         /* setup the bats */
240         bl      setup_bats
241         sync
242
243 #if (CFG_CCSRBAR_DEFAULT != CFG_CCSRBAR)
244         /* setup ccsrbar */
245         bl      setup_ccsrbar
246 #endif
247         
248         /* setup the law entries */
249         bl      law_entry
250         sync
251
252         /* Don't use this feature due to bug in 8641D PD4 */
253         /* Disable ERD_DIS */
254         lis     r3, CFG_CCSRBAR@h
255         ori     r3, r3, 0x1008
256         lwz     r4, 0(r3)
257         oris    r4, r4, 0x4000
258         stw     r4, 0(r3)
259         sync
260
261 #if (EMULATOR_RUN == 1)
262         /* On the emulator we want to adjust these ASAP */
263         /* otherwise things are sloooow */
264         /* Setup OR0 (LALE FIX)*/
265         lis     r3, CFG_CCSRBAR@h
266         ori     r3, r3, 0x5004
267         li      r4, 0x0FF3
268         stw     r4, 0(r3)
269         sync
270
271         /* Setup LCRR */
272         lis     r3, CFG_CCSRBAR@h
273         ori     r3, r3, 0x50D4
274         lis     r4, 0x8000
275         ori     r4, r4, 0x0002
276         stw     r4, 0(r3)
277         sync
278 #endif
279 #if 1   
280         /* make sure timer enabled in guts register too */
281         lis     r3, CFG_CCSRBAR@h
282         oris    r3,r3, 0xE
283         ori     r3,r3,0x0070  /*Jason from 3*/
284         lwz     r4, 0(r3)
285         lis     r5,0xFFFC     /*Jason from 0xffff*/
286         ori     r5,r5,0x5FFF
287         and     r4,r4,r5
288         stw     r4,0(r3)
289 #endif  
290         /*
291          * Cache must be enabled here for stack-in-cache trick.
292          * This means we need to enable the BATS.
293          * Cache should be turned on after BATs, since by default
294          * everything is write-through.
295          */
296
297         /* enable address translation */
298         bl      enable_addr_trans
299         sync
300
301         /* enable and invalidate the data cache */
302 /*      bl      l1dcache_enable */
303         bl      dcache_enable 
304         sync
305
306 #if 1
307         bl      icache_enable
308 #endif
309         
310 #ifdef CFG_INIT_RAM_LOCK
311         bl      lock_ram_in_cache
312         sync
313 #endif
314
315         /* set up the stack pointer in our newly created
316          * cache-ram (r1) */
317         lis     r1, (CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET)@h
318         ori     r1, r1, (CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET)@l
319
320         li      r0, 0           /* Make room for stack frame header and */
321         stwu    r0, -4(r1)      /* clear final stack frame so that      */
322         stwu    r0, -4(r1)      /* stack backtraces terminate cleanly   */
323
324         GET_GOT                 /* initialize GOT access        */
325
326         /* run low-level CPU init code     (from Flash) */
327         bl      cpu_init_f
328         sync
329
330 #ifdef  RUN_DIAG        
331
332         /* Sri:  Code to run the diagnostic automatically */
333
334         /* Load PX_AUX register address in r4 */
335         lis     r4, 0xf810
336         ori     r4, r4, 0x6
337         /* Load contents of PX_AUX in r3 bits 24 to 31*/
338         lbz     r3, 0(r4)
339
340         /* Mask and obtain the bit in r3 */
341         rlwinm. r3, r3, 0, 24, 24
342         /* If not zero, jump and continue with u-boot */
343         bne     diag_done
344
345         /* Load back contents of PX_AUX in r3 bits 24 to 31 */
346         lbz     r3, 0(r4)
347         /* Set the MSB of the register value */
348         ori     r3, r3, 0x80
349         /* Write value in r3 back to PX_AUX */
350         stb     r3, 0(r4)
351
352         /* Get the address to jump to in r3*/
353         lis     r3, CFG_DIAG_ADDR@h
354         ori     r3, r3, CFG_DIAG_ADDR@l
355
356         /* Load the LR with the branch address */
357         mtlr    r3
358
359         /* Branch to diagnostic */
360         blr
361         
362 diag_done:      
363 #endif        
364
365   /*      bl      l2cache_enable*/
366         mr      r3, r21
367
368         /* r3: BOOTFLAG */
369         /* run 1st part of board init code (from Flash)   */
370         bl      board_init_f
371         sync
372
373         /* NOTREACHED */
374
375         .globl  invalidate_bats
376 invalidate_bats:
377         
378         /* invalidate BATs */
379         mtspr   IBAT0U, r0
380         mtspr   IBAT1U, r0
381         mtspr   IBAT2U, r0
382         mtspr   IBAT3U, r0
383         mtspr   IBAT4U, r0
384         mtspr   IBAT5U, r0
385         mtspr   IBAT6U, r0
386         mtspr   IBAT7U, r0
387
388         isync
389         mtspr   DBAT0U, r0
390         mtspr   DBAT1U, r0
391         mtspr   DBAT2U, r0
392         mtspr   DBAT3U, r0
393         mtspr   DBAT4U, r0
394         mtspr   DBAT5U, r0
395         mtspr   DBAT6U, r0
396         mtspr   DBAT7U, r0
397
398         isync
399         sync
400         blr
401         
402         
403         /* setup_bats - set them up to some initial state */
404         .globl  setup_bats
405 setup_bats:
406         
407         addis   r0, r0, 0x0000
408
409         /* IBAT 0 */
410         addis   r4, r0, CFG_IBAT0L@h
411         ori     r4, r4, CFG_IBAT0L@l
412         addis   r3, r0, CFG_IBAT0U@h
413         ori     r3, r3, CFG_IBAT0U@l
414         mtspr   IBAT0L, r4
415         mtspr   IBAT0U, r3
416         isync
417
418         /* DBAT 0 */
419         addis   r4, r0, CFG_DBAT0L@h
420         ori     r4, r4, CFG_DBAT0L@l
421         addis   r3, r0, CFG_DBAT0U@h
422         ori     r3, r3, CFG_DBAT0U@l
423         mtspr   DBAT0L, r4
424         mtspr   DBAT0U, r3
425         isync
426
427         /* IBAT 1 */
428         addis   r4, r0, CFG_IBAT1L@h
429         ori     r4, r4, CFG_IBAT1L@l
430         addis   r3, r0, CFG_IBAT1U@h
431         ori     r3, r3, CFG_IBAT1U@l
432         mtspr   IBAT1L, r4
433         mtspr   IBAT1U, r3
434         isync
435
436         /* DBAT 1 */
437         addis   r4, r0, CFG_DBAT1L@h
438         ori     r4, r4, CFG_DBAT1L@l
439         addis   r3, r0, CFG_DBAT1U@h
440         ori     r3, r3, CFG_DBAT1U@l
441         mtspr   DBAT1L, r4
442         mtspr   DBAT1U, r3
443         isync
444
445         /* IBAT 2 */
446         addis   r4, r0, CFG_IBAT2L@h
447         ori     r4, r4, CFG_IBAT2L@l
448         addis   r3, r0, CFG_IBAT2U@h
449         ori     r3, r3, CFG_IBAT2U@l
450         mtspr   IBAT2L, r4
451         mtspr   IBAT2U, r3
452         isync
453
454         /* DBAT 2 */
455         addis   r4, r0, CFG_DBAT2L@h
456         ori     r4, r4, CFG_DBAT2L@l
457         addis   r3, r0, CFG_DBAT2U@h
458         ori     r3, r3, CFG_DBAT2U@l
459         mtspr   DBAT2L, r4
460         mtspr   DBAT2U, r3
461         isync
462
463         /* IBAT 3 */
464         addis   r4, r0, CFG_IBAT3L@h
465         ori     r4, r4, CFG_IBAT3L@l
466         addis   r3, r0, CFG_IBAT3U@h
467         ori     r3, r3, CFG_IBAT3U@l
468         mtspr   IBAT3L, r4
469         mtspr   IBAT3U, r3
470         isync
471
472         /* DBAT 3 */
473         addis   r4, r0, CFG_DBAT3L@h
474         ori     r4, r4, CFG_DBAT3L@l
475         addis   r3, r0, CFG_DBAT3U@h
476         ori     r3, r3, CFG_DBAT3U@l
477         mtspr   DBAT3L, r4
478         mtspr   DBAT3U, r3
479         isync
480
481         /* IBAT 4 */
482         addis   r4, r0, CFG_IBAT4L@h
483         ori     r4, r4, CFG_IBAT4L@l
484         addis   r3, r0, CFG_IBAT4U@h
485         ori     r3, r3, CFG_IBAT4U@l
486         mtspr   IBAT4L, r4
487         mtspr   IBAT4U, r3
488         isync
489
490         /* DBAT 4 */
491         addis   r4, r0, CFG_DBAT4L@h
492         ori     r4, r4, CFG_DBAT4L@l
493         addis   r3, r0, CFG_DBAT4U@h
494         ori     r3, r3, CFG_DBAT4U@l
495         mtspr   DBAT4L, r4
496         mtspr   DBAT4U, r3
497         isync
498
499         /* IBAT 5 */
500         addis   r4, r0, CFG_IBAT5L@h
501         ori     r4, r4, CFG_IBAT5L@l
502         addis   r3, r0, CFG_IBAT5U@h
503         ori     r3, r3, CFG_IBAT5U@l
504         mtspr   IBAT5L, r4
505         mtspr   IBAT5U, r3
506         isync
507
508         /* DBAT 5 */
509         addis   r4, r0, CFG_DBAT5L@h
510         ori     r4, r4, CFG_DBAT5L@l
511         addis   r3, r0, CFG_DBAT5U@h
512         ori     r3, r3, CFG_DBAT5U@l
513         mtspr   DBAT5L, r4
514         mtspr   DBAT5U, r3
515         isync
516
517         /* IBAT 6 */
518         addis   r4, r0, CFG_IBAT6L@h
519         ori     r4, r4, CFG_IBAT6L@l
520         addis   r3, r0, CFG_IBAT6U@h
521         ori     r3, r3, CFG_IBAT6U@l
522         mtspr   IBAT6L, r4
523         mtspr   IBAT6U, r3
524         isync
525
526         /* DBAT 6 */
527         addis   r4, r0, CFG_DBAT6L@h
528         ori     r4, r4, CFG_DBAT6L@l
529         addis   r3, r0, CFG_DBAT6U@h
530         ori     r3, r3, CFG_DBAT6U@l
531         mtspr   DBAT6L, r4
532         mtspr   DBAT6U, r3
533         isync
534
535         /* IBAT 7 */
536         addis   r4, r0, CFG_IBAT7L@h
537         ori     r4, r4, CFG_IBAT7L@l
538         addis   r3, r0, CFG_IBAT7U@h
539         ori     r3, r3, CFG_IBAT7U@l
540         mtspr   IBAT7L, r4
541         mtspr   IBAT7U, r3
542         isync
543
544         /* DBAT 7 */
545         addis   r4, r0, CFG_DBAT7L@h
546         ori     r4, r4, CFG_DBAT7L@l
547         addis   r3, r0, CFG_DBAT7U@h
548         ori     r3, r3, CFG_DBAT7U@l
549         mtspr   DBAT7L, r4
550         mtspr   DBAT7U, r3
551         isync
552
553 1:      
554         addis   r3, 0, 0x0000
555         addis   r5, 0, 0x4    /* upper bound of 0x00040000 for 7400/750 */
556         isync
557
558 tlblp:
559         tlbie   r3
560         sync
561         addi    r3, r3, 0x1000
562         cmp     0, 0, r3, r5
563         blt tlblp
564
565         blr
566
567         .globl enable_addr_trans
568 enable_addr_trans:
569         /* enable address translation */
570         mfmsr   r5
571         ori     r5, r5, (MSR_IR | MSR_DR)
572         mtmsr   r5
573         isync
574         blr
575
576         .globl disable_addr_trans
577 disable_addr_trans:
578         /* disable address translation */
579         mflr    r4
580         mfmsr   r3
581         andi.   r0, r3, (MSR_IR | MSR_DR)
582         beqlr
583         andc    r3, r3, r0
584         mtspr   SRR0, r4
585         mtspr   SRR1, r3
586         rfi
587
588 /*
589  * This code finishes saving the registers to the exception frame
590  * and jumps to the appropriate handler for the exception.
591  * Register r21 is pointer into trap frame, r1 has new stack pointer.
592  */
593         .globl  transfer_to_handler
594 transfer_to_handler:
595         stw     r22,_NIP(r21)
596         lis     r22,MSR_POW@h
597         andc    r23,r23,r22
598         stw     r23,_MSR(r21)
599         SAVE_GPR(7, r21)
600         SAVE_4GPRS(8, r21)
601         SAVE_8GPRS(12, r21)
602         SAVE_8GPRS(24, r21)
603         mflr    r23
604         andi.   r24,r23,0x3f00          /* get vector offset */
605         stw     r24,TRAP(r21)
606         li      r22,0
607         stw     r22,RESULT(r21)
608         mtspr   SPRG2,r22               /* r1 is now kernel sp */
609         lwz     r24,0(r23)              /* virtual address of handler */
610         lwz     r23,4(r23)              /* where to go when done */
611         mtspr   SRR0,r24
612         mtspr   SRR1,r20
613         mtlr    r23
614         SYNC
615         rfi                             /* jump to handler, enable MMU */
616
617 int_return:
618         mfmsr   r28             /* Disable interrupts */
619         li      r4,0
620         ori     r4,r4,MSR_EE
621         andc    r28,r28,r4
622         SYNC                    /* Some chip revs need this... */
623         mtmsr   r28
624         SYNC
625         lwz     r2,_CTR(r1)
626         lwz     r0,_LINK(r1)
627         mtctr   r2
628         mtlr    r0
629         lwz     r2,_XER(r1)
630         lwz     r0,_CCR(r1)
631         mtspr   XER,r2
632         mtcrf   0xFF,r0
633         REST_10GPRS(3, r1)
634         REST_10GPRS(13, r1)
635         REST_8GPRS(23, r1)
636         REST_GPR(31, r1)
637         lwz     r2,_NIP(r1)     /* Restore environment */
638         lwz     r0,_MSR(r1)
639         mtspr   SRR0,r2
640         mtspr   SRR1,r0
641         lwz     r0,GPR0(r1)
642         lwz     r2,GPR2(r1)
643         lwz     r1,GPR1(r1)
644         SYNC
645         rfi
646
647         .globl  dc_read
648 dc_read:
649         blr
650
651         .globl get_pvr
652 get_pvr:
653         mfspr   r3, PVR
654         blr
655
656         .globl get_svr
657 get_svr:
658         mfspr   r3, SVR
659         blr
660
661
662 /*------------------------------------------------------------------------------- */
663 /* Function:     in8 */
664 /* Description:  Input 8 bits */
665 /*------------------------------------------------------------------------------- */
666         .globl  in8
667 in8:
668         lbz     r3,0x0000(r3)
669         blr
670
671 /*------------------------------------------------------------------------------- */
672 /* Function:     out8 */
673 /* Description:  Output 8 bits */
674 /*------------------------------------------------------------------------------- */
675         .globl  out8
676 out8:
677         stb     r4,0x0000(r3)
678         blr
679
680 /*------------------------------------------------------------------------------- */
681 /* Function:     out16 */
682 /* Description:  Output 16 bits */
683 /*------------------------------------------------------------------------------- */
684         .globl  out16
685 out16:
686         sth     r4,0x0000(r3)
687         blr
688
689 /*------------------------------------------------------------------------------- */
690 /* Function:     out16r */
691 /* Description:  Byte reverse and output 16 bits */
692 /*------------------------------------------------------------------------------- */
693         .globl  out16r
694 out16r:
695         sthbrx  r4,r0,r3
696         blr
697
698 /*------------------------------------------------------------------------------- */
699 /* Function:     out32 */
700 /* Description:  Output 32 bits */
701 /*------------------------------------------------------------------------------- */
702         .globl  out32
703 out32:
704         stw     r4,0x0000(r3)
705         blr
706
707 /*------------------------------------------------------------------------------- */
708 /* Function:     out32r */
709 /* Description:  Byte reverse and output 32 bits */
710 /*------------------------------------------------------------------------------- */
711         .globl  out32r
712 out32r:
713         stwbrx  r4,r0,r3
714         blr
715
716 /*------------------------------------------------------------------------------- */
717 /* Function:     in16 */
718 /* Description:  Input 16 bits */
719 /*------------------------------------------------------------------------------- */
720         .globl  in16
721 in16:
722         lhz     r3,0x0000(r3)
723         blr
724
725 /*------------------------------------------------------------------------------- */
726 /* Function:     in16r */
727 /* Description:  Input 16 bits and byte reverse */
728 /*------------------------------------------------------------------------------- */
729         .globl  in16r
730 in16r:
731         lhbrx   r3,r0,r3
732         blr
733
734 /*------------------------------------------------------------------------------- */
735 /* Function:     in32 */
736 /* Description:  Input 32 bits */
737 /*------------------------------------------------------------------------------- */
738         .globl  in32
739 in32:
740         lwz     3,0x0000(3)
741         blr
742
743 /*------------------------------------------------------------------------------- */
744 /* Function:     in32r */
745 /* Description:  Input 32 bits and byte reverse */
746 /*------------------------------------------------------------------------------- */
747         .globl  in32r
748 in32r:
749         lwbrx   r3,r0,r3
750         blr
751
752 /*------------------------------------------------------------------------------- */
753 /* Function:     ppcDcbf */
754 /* Description:  Data Cache block flush */
755 /* Input:        r3 = effective address */
756 /* Output:       none. */
757 /*------------------------------------------------------------------------------- */
758         .globl  ppcDcbf
759 ppcDcbf:
760         dcbf    r0,r3
761         blr
762
763 /*------------------------------------------------------------------------------- */
764 /* Function:     ppcDcbi */
765 /* Description:  Data Cache block Invalidate */
766 /* Input:        r3 = effective address */
767 /* Output:       none. */
768 /*------------------------------------------------------------------------------- */
769         .globl  ppcDcbi
770 ppcDcbi:
771         dcbi    r0,r3
772         blr
773
774 /*--------------------------------------------------------------------------
775  * Function:     ppcDcbz
776  * Description:  Data Cache block zero.
777  * Input:        r3 = effective address
778  * Output:       none.
779  *-------------------------------------------------------------------------- */
780
781         .globl  ppcDcbz
782 ppcDcbz:
783         dcbz    r0,r3
784         blr
785
786 /*------------------------------------------------------------------------------- */
787 /* Function:     ppcSync */
788 /* Description:  Processor Synchronize */
789 /* Input:        none. */
790 /* Output:       none. */
791 /*------------------------------------------------------------------------------- */
792         .globl  ppcSync
793 ppcSync:
794         sync
795         blr
796         
797 /*-----------------------------------------------------------------------*/
798 /*
799  * void relocate_code (addr_sp, gd, addr_moni)
800  *
801  * This "function" does not return, instead it continues in RAM
802  * after relocating the monitor code.
803  *
804  * r3 = dest
805  * r4 = src
806  * r5 = length in bytes
807  * r6 = cachelinesize
808  */
809         .globl  relocate_code
810 relocate_code:
811
812         mr      r1,  r3         /* Set new stack pointer                */
813         mr      r9,  r4         /* Save copy of Global Data pointer     */
814         mr      r10, r5         /* Save copy of Destination Address     */
815         
816         mr      r3,  r5                         /* Destination Address  */
817         lis     r4, CFG_MONITOR_BASE@h          /* Source      Address  */
818         ori     r4, r4, CFG_MONITOR_BASE@l
819         lwz     r5, GOT(__init_end)
820         sub     r5, r5, r4
821         li      r6, CFG_CACHELINE_SIZE          /* Cache Line Size      */
822
823         /*
824          * Fix GOT pointer:
825          *
826          * New GOT-PTR = (old GOT-PTR - CFG_MONITOR_BASE) + Destination Address
827          *
828          * Offset:
829          */
830         sub     r15, r10, r4
831
832         /* First our own GOT */
833         add     r14, r14, r15
834         /* then the one used by the C code */
835         add     r30, r30, r15
836
837         /*
838          * Now relocate code
839          */
840 #ifdef CONFIG_ECC
841         bl      board_relocate_rom
842         sync
843         mr      r3, r10                         /* Destination Address  */
844         lis     r4, CFG_MONITOR_BASE@h          /* Source      Address  */
845         ori     r4, r4, CFG_MONITOR_BASE@l
846         lwz     r5, GOT(__init_end)
847         sub     r5, r5, r4
848         li      r6, CFG_CACHELINE_SIZE          /* Cache Line Size      */
849 #else
850         cmplw   cr1,r3,r4
851         addi    r0,r5,3
852         srwi.   r0,r0,2
853         beq     cr1,4f          /* In place copy is not necessary       */
854         beq     7f              /* Protect against 0 count              */
855         mtctr   r0
856         bge     cr1,2f
857
858         la      r8,-4(r4)
859         la      r7,-4(r3)
860 1:      lwzu    r0,4(r8)
861         stwu    r0,4(r7)
862         bdnz    1b
863         b       4f
864
865 2:      slwi    r0,r0,2
866         add     r8,r4,r0
867         add     r7,r3,r0
868 3:      lwzu    r0,-4(r8)
869         stwu    r0,-4(r7)
870         bdnz    3b
871 #endif
872 /*
873  * Now flush the cache: note that we must start from a cache aligned
874  * address. Otherwise we might miss one cache line.
875  */
876 4:      cmpwi   r6,0
877         add     r5,r3,r5
878         beq     7f              /* Always flush prefetch queue in any case */
879         subi    r0,r6,1
880         andc    r3,r3,r0
881         mr      r4,r3
882 5:      dcbst   0,r4
883         add     r4,r4,r6
884         cmplw   r4,r5
885         blt     5b
886         sync                    /* Wait for all dcbst to complete on bus */
887         mr      r4,r3
888 6:      icbi    0,r4
889         add     r4,r4,r6
890         cmplw   r4,r5
891         blt     6b
892 7:      sync                    /* Wait for all icbi to complete on bus */
893         isync
894
895 /*
896  * We are done. Do not return, instead branch to second part of board
897  * initialization, now running from RAM.
898  */
899         addi    r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
900         mtlr    r0
901         blr
902
903 in_ram:
904 #ifdef CONFIG_ECC
905         bl      board_init_ecc
906 #endif
907         /*
908          * Relocation Function, r14 point to got2+0x8000
909          *
910          * Adjust got2 pointers, no need to check for 0, this code
911          * already puts a few entries in the table.
912          */
913         li      r0,__got2_entries@sectoff@l
914         la      r3,GOT(_GOT2_TABLE_)
915         lwz     r11,GOT(_GOT2_TABLE_)
916         mtctr   r0
917         sub     r11,r3,r11
918         addi    r3,r3,-4
919 1:      lwzu    r0,4(r3)
920         add     r0,r0,r11
921         stw     r0,0(r3)
922         bdnz    1b
923
924         /*
925          * Now adjust the fixups and the pointers to the fixups
926          * in case we need to move ourselves again.
927          */
928 2:      li      r0,__fixup_entries@sectoff@l
929         lwz     r3,GOT(_FIXUP_TABLE_)
930         cmpwi   r0,0
931         mtctr   r0
932         addi    r3,r3,-4
933         beq     4f
934 3:      lwzu    r4,4(r3)
935         lwzux   r0,r4,r11
936         add     r0,r0,r11
937         stw     r10,0(r3)
938         stw     r0,0(r4)
939         bdnz    3b
940 4:
941 /* clear_bss: */
942         /*
943          * Now clear BSS segment
944          */
945         lwz     r3,GOT(__bss_start)
946         lwz     r4,GOT(_end)
947
948         cmplw   0, r3, r4
949         beq     6f
950
951         li      r0, 0
952 5:
953         stw     r0, 0(r3)
954         addi    r3, r3, 4
955         cmplw   0, r3, r4
956         bne     5b
957 6:
958         mr      r3, r10         /* Destination Address          */
959         bl      after_reloc
960
961         /* not reached - end relocate_code */
962 /*-----------------------------------------------------------------------*/
963
964         /*
965          * Copy exception vector code to low memory
966          *
967          * r3: dest_addr
968          * r7: source address, r8: end address, r9: target address
969          */
970         .globl  trap_init
971 trap_init:
972         lwz     r7, GOT(_start)
973         lwz     r8, GOT(_end_of_vectors)
974
975         li      r9, 0x100               /* reset vector always at 0x100 */
976
977         cmplw   0, r7, r8
978         bgelr                           /* return if r7>=r8 - just in case */
979
980         mflr    r4                      /* save link register           */
981 1:
982         lwz     r0, 0(r7)
983         stw     r0, 0(r9)
984         addi    r7, r7, 4
985         addi    r9, r9, 4
986         cmplw   0, r7, r8
987         bne     1b
988
989         /*
990          * relocate `hdlr' and `int_return' entries
991          */
992         li      r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
993         li      r8, Alignment - _start + EXC_OFF_SYS_RESET
994 2:
995         bl      trap_reloc
996         addi    r7, r7, 0x100           /* next exception vector        */
997         cmplw   0, r7, r8
998         blt     2b
999
1000         li      r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
1001         bl      trap_reloc
1002
1003         li      r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
1004         bl      trap_reloc
1005
1006         li      r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
1007         li      r8, SystemCall - _start + EXC_OFF_SYS_RESET
1008 3:
1009         bl      trap_reloc
1010         addi    r7, r7, 0x100           /* next exception vector        */
1011         cmplw   0, r7, r8
1012         blt     3b
1013
1014         li      r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
1015         li      r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
1016 4:
1017         bl      trap_reloc
1018         addi    r7, r7, 0x100           /* next exception vector        */
1019         cmplw   0, r7, r8
1020         blt     4b
1021
1022         /* enable execptions from RAM vectors */
1023         mfmsr   r7
1024         li      r8,MSR_IP
1025         andc    r7,r7,r8
1026         mtmsr   r7
1027
1028         mtlr    r4                      /* restore link register        */
1029         blr
1030
1031         /*
1032          * Function: relocate entries for one exception vector
1033          */
1034 trap_reloc:
1035         lwz     r0, 0(r7)               /* hdlr ...                     */
1036         add     r0, r0, r3              /*  ... += dest_addr            */
1037         stw     r0, 0(r7)
1038
1039         lwz     r0, 4(r7)               /* int_return ...               */
1040         add     r0, r0, r3              /*  ... += dest_addr            */
1041         stw     r0, 4(r7)
1042
1043         sync
1044         isync
1045
1046         blr
1047
1048 .globl enable_ext_addr
1049 enable_ext_addr:
1050         mfspr   r0, HID0
1051         lis     r0, (HID0_HIGH_BAT_EN | HID0_XBSEN | HID0_XAEN)@h
1052         ori     r0, r0, (HID0_HIGH_BAT_EN | HID0_XBSEN | HID0_XAEN)@l
1053         mtspr   HID0, r0
1054         sync
1055         isync
1056         blr
1057
1058 #if (CFG_CCSRBAR_DEFAULT != CFG_CCSRBAR)
1059 .globl setup_ccsrbar
1060 setup_ccsrbar:          
1061         /* Special sequence needed to update CCSRBAR itself */
1062         lis     r4, CFG_CCSRBAR_DEFAULT@h
1063         ori     r4, r4, CFG_CCSRBAR_DEFAULT@l
1064
1065         lis     r5, CFG_CCSRBAR@h
1066         ori     r5, r5, CFG_CCSRBAR@l
1067         srwi    r6,r5,12
1068         stw     r6, 0(r4)
1069         isync
1070
1071         lis     r5, 0xffff
1072         ori     r5,r5,0xf000
1073         lwz     r5, 0(r5)
1074         isync
1075
1076         lis     r3, CFG_CCSRBAR@h
1077         lwz     r5, CFG_CCSRBAR@l(r3)
1078         isync
1079         
1080         blr
1081 #endif
1082                         
1083 #ifdef CFG_INIT_RAM_LOCK
1084 lock_ram_in_cache:
1085         /* Allocate Initial RAM in data cache.
1086          */
1087         lis     r3, (CFG_INIT_RAM_ADDR & ~31)@h
1088         ori     r3, r3, (CFG_INIT_RAM_ADDR & ~31)@l
1089         li      r2, ((CFG_INIT_RAM_END & ~31) + \
1090                      (CFG_INIT_RAM_ADDR & 31) + 31) / 32
1091         mtctr   r2
1092 1:
1093         dcbz    r0, r3
1094         addi    r3, r3, 32
1095         bdnz    1b
1096 #if 1
1097 /* Lock the data cache */
1098         mfspr   r0, HID0
1099         ori     r0, r0, 0x1000
1100         sync
1101         mtspr   HID0, r0
1102         sync
1103         blr
1104 #endif
1105 #if 0
1106         /* Lock the first way of the data cache */
1107         mfspr   r0, LDSTCR
1108         ori     r0, r0, 0x0080
1109 #if defined(CONFIG_ALTIVEC)
1110         dssall
1111 #endif
1112         sync
1113         mtspr   LDSTCR, r0
1114         sync
1115         isync
1116         blr
1117 #endif
1118         
1119 .globl unlock_ram_in_cache
1120 unlock_ram_in_cache:
1121         /* invalidate the INIT_RAM section */
1122         lis     r3, (CFG_INIT_RAM_ADDR & ~31)@h
1123         ori     r3, r3, (CFG_INIT_RAM_ADDR & ~31)@l
1124         li      r2, ((CFG_INIT_RAM_END & ~31) + \
1125                      (CFG_INIT_RAM_ADDR & 31) + 31) / 32
1126         mtctr   r2
1127 1:      icbi    r0, r3
1128         addi    r3, r3, 32
1129         bdnz    1b
1130         sync                    /* Wait for all icbi to complete on bus */
1131         isync
1132 #if 1
1133 /* Unlock the data cache and invalidate it */
1134         mfspr   r0, HID0
1135         li      r3,0x1000
1136         andc    r0,r0,r3
1137         li      r3,0x0400
1138         or      r0,r0,r3
1139         sync
1140         mtspr   HID0, r0
1141         sync
1142         blr
1143 #endif
1144 #if 0   
1145         /* Unlock the first way of the data cache */
1146         mfspr   r0, LDSTCR
1147         li      r3,0x0080
1148         andc    r0,r0,r3
1149 #ifdef CONFIG_ALTIVEC
1150         dssall
1151 #endif
1152         sync
1153         mtspr   LDSTCR, r0
1154         sync
1155         isync
1156         li      r3,0x0400
1157         or      r0,r0,r3
1158         sync
1159         mtspr   HID0, r0
1160         sync
1161         blr
1162 #endif
1163 #endif
1164
1165 /* If this is a multi-cpu system then we need to handle the
1166  * 2nd cpu.  The assumption is that the 2nd cpu is being
1167  * held in boot holdoff mode until the 1st cpu unlocks it
1168  * from Linux.  We'll do some basic cpu init and then pass
1169  * it to the Linux Reset Vector.
1170  * Sri:  Much of this initialization is not required. Linux
1171  * rewrites the bats, and the sprs and also enables the L1 cache.      
1172  */
1173 #if (CONFIG_NUM_CPUS > 1)
1174 .globl secondary_cpu_setup
1175 secondary_cpu_setup:    
1176         /* Do only core setup on all cores except cpu0 */
1177         bl      invalidate_bats
1178         sync
1179         bl      enable_ext_addr
1180         
1181 #ifdef CFG_L2
1182         /* init the L2 cache */
1183         addis   r3, r0, L2_INIT@h
1184         ori     r3, r3, L2_INIT@l
1185         sync
1186         mtspr   l2cr, r3
1187 #ifdef CONFIG_ALTIVEC
1188         dssall
1189 #endif
1190         /* invalidate the L2 cache */
1191         bl      l2cache_invalidate
1192         sync
1193 #endif
1194
1195         /* setup the bats */
1196         bl      setup_bats
1197         sync
1198         /* enable address translation */
1199         bl      enable_addr_trans
1200         sync
1201
1202         /* enable and invalidate the data cache */
1203         bl      dcache_enable
1204         sync
1205
1206         /* enable and invalidate the instruction cache*/
1207         bl      icache_enable
1208         sync
1209         
1210         /* Set up MSR and HID0, HID1*/        
1211         /* Enable interrupts */
1212 /*        mfmsr r28     
1213          li     r4,0
1214         ori     r4,r4,MSR_EE
1215         or      r28,r28,r4
1216         mtmsr   r28
1217   */      
1218
1219         /* TBEN  in HID0 */
1220         mfspr   r4, HID0
1221         oris    r4, r4, 0x0400 
1222         mtspr   HID0, r4
1223         sync
1224         isync
1225         
1226         /*SYNCBE|ABE in HID1*/
1227         mfspr   r4, HID1
1228         ori     r4, r4, 0x0C00 
1229         mtspr   HID1, r4
1230         sync
1231         isync
1232         
1233         lis     r3, CONFIG_LINUX_RESET_VEC@h
1234         ori     r3, r3, CONFIG_LINUX_RESET_VEC@l
1235         mtlr    r3
1236         blr
1237         
1238         /* Never Returns, Running in Linux Now */    
1239 #endif
1240