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