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