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