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