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