Merge with git://www.denx.de/git/u-boot.git
[platform/kernel/u-boot.git] / cpu / mpc85xx / start.S
1 /*
2  * Copyright 2004, 2007 Freescale Semiconductor.
3  * Copyright (C) 2003  Motorola,Inc.
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 Motorola 85xx PowerPC based Embedded Boards
25  *
26  * The processor starts at 0xfffffffc and the code is first executed in the
27  * last 4K page(0xfffff000-0xffffffff) in flash/rom.
28  *
29  */
30
31 #include <config.h>
32 #include <mpc85xx.h>
33 #include <version.h>
34
35 #define _LINUX_CONFIG_H 1       /* avoid reading Linux autoconf.h file  */
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 #undef  MSR_KERNEL
48 #define MSR_KERNEL ( MSR_ME )   /* Machine Check */
49
50 /*
51  * Set up GOT: Global Offset Table
52  *
53  * Use r14 to access the GOT
54  */
55         START_GOT
56         GOT_ENTRY(_GOT2_TABLE_)
57         GOT_ENTRY(_FIXUP_TABLE_)
58
59         GOT_ENTRY(_start)
60         GOT_ENTRY(_start_of_vectors)
61         GOT_ENTRY(_end_of_vectors)
62         GOT_ENTRY(transfer_to_handler)
63
64         GOT_ENTRY(__init_end)
65         GOT_ENTRY(_end)
66         GOT_ENTRY(__bss_start)
67         END_GOT
68
69 /*
70  * e500 Startup -- after reset only the last 4KB of the effective
71  * address space is mapped in the MMU L2 TLB1 Entry0. The .bootpg
72  * section is located at THIS LAST page and basically does three
73  * things: clear some registers, set up exception tables and
74  * add more TLB entries for 'larger spaces'(e.g. the boot rom) to
75  * continue the boot procedure.
76
77  * Once the boot rom is mapped by TLB entries we can proceed
78  * with normal startup.
79  *
80  */
81
82         .section .bootpg,"ax"
83         .globl _start_e500
84
85 _start_e500:
86
87 /* clear registers/arrays not reset by hardware */
88
89         /* L1 */
90         li      r0,2
91         mtspr   L1CSR0,r0       /* invalidate d-cache */
92         mtspr   L1CSR1,r0       /* invalidate i-cache */
93
94         mfspr   r1,DBSR
95         mtspr   DBSR,r1         /* Clear all valid bits */
96
97         /*
98          *      Enable L1 Caches early
99          *
100          */
101
102         lis     r2,L1CSR0_CPE@H /* enable parity */
103         ori     r2,r2,L1CSR0_DCE
104         mtspr   L1CSR0,r2       /* enable L1 Dcache */
105         isync
106         mtspr   L1CSR1,r2       /* enable L1 Icache */
107         isync
108         msync
109
110         /* Setup interrupt vectors */
111         lis     r1,TEXT_BASE@h
112         mtspr   IVPR,r1
113
114         li      r1,0x0100
115         mtspr   IVOR0,r1        /* 0: Critical input */
116         li      r1,0x0200
117         mtspr   IVOR1,r1        /* 1: Machine check */
118         li      r1,0x0300
119         mtspr   IVOR2,r1        /* 2: Data storage */
120         li      r1,0x0400
121         mtspr   IVOR3,r1        /* 3: Instruction storage */
122         li      r1,0x0500
123         mtspr   IVOR4,r1        /* 4: External interrupt */
124         li      r1,0x0600
125         mtspr   IVOR5,r1        /* 5: Alignment */
126         li      r1,0x0700
127         mtspr   IVOR6,r1        /* 6: Program check */
128         li      r1,0x0800
129         mtspr   IVOR7,r1        /* 7: floating point unavailable */
130         li      r1,0x0900
131         mtspr   IVOR8,r1        /* 8: System call */
132         /* 9: Auxiliary processor unavailable(unsupported) */
133         li      r1,0x0a00
134         mtspr   IVOR10,r1       /* 10: Decrementer */
135         li      r1,0x0b00
136         mtspr   IVOR11,r1       /* 11: Interval timer */
137         li      r1,0x0c00
138         mtspr   IVOR12,r1       /* 12: Watchdog timer */
139         li      r1,0x0d00
140         mtspr   IVOR13,r1       /* 13: Data TLB error */
141         li      r1,0x0e00
142         mtspr   IVOR14,r1       /* 14: Instruction TLB error */
143         li      r1,0x0f00
144         mtspr   IVOR15,r1       /* 15: Debug */
145
146
147         /*
148          * After reset, CCSRBAR is located at CFG_CCSRBAR_DEFAULT, i.e.
149          * 0xff700000-0xff800000. We need add a TLB1 entry for this 1MB
150          * region before we can access any CCSR registers such as L2
151          * registers, Local Access Registers,etc. We will also re-allocate
152          * CFG_CCSRBAR_DEFAULT to CFG_CCSRBAR immediately after TLB1 setup.
153          *
154          * Please refer to board-specif directory for TLB1 entry configuration.
155          * (e.g. board/<yourboard>/init.S)
156          *
157          */
158         bl      tlb1_entry
159         mr      r5,r0
160         lwzu    r4,0(r5)        /* how many TLB1 entries we actually use */
161         mtctr   r4
162
163 0:      lwzu    r6,4(r5)
164         lwzu    r7,4(r5)
165         lwzu    r8,4(r5)
166         lwzu    r9,4(r5)
167         mtspr   MAS0,r6
168         mtspr   MAS1,r7
169         mtspr   MAS2,r8
170         mtspr   MAS3,r9
171         isync
172         msync
173         tlbwe
174         isync
175         bdnz    0b
176
177 1:
178 #if (CFG_CCSRBAR_DEFAULT != CFG_CCSRBAR)
179         /* Special sequence needed to update CCSRBAR itself */
180         lis     r4,CFG_CCSRBAR_DEFAULT@h
181         ori     r4,r4,CFG_CCSRBAR_DEFAULT@l
182
183         lis     r5,CFG_CCSRBAR@h
184         ori     r5,r5,CFG_CCSRBAR@l
185         srwi    r6,r5,12
186         stw     r6,0(r4)
187         isync
188
189         lis     r5,0xffff
190         ori     r5,r5,0xf000
191         lwz     r5,0(r5)
192         isync
193
194         lis     r3,CFG_CCSRBAR@h
195         lwz     r5,CFG_CCSRBAR@l(r3)
196         isync
197 #endif
198
199
200         /* set up local access windows, defined at board/<boardname>/init.S */
201         lis     r7,CFG_CCSRBAR@h
202         ori     r7,r7,CFG_CCSRBAR@l
203
204         bl      law_entry
205         mr      r6,r0
206         lwzu    r5,0(r6)        /* how many windows we actually use */
207         mtctr   r5
208
209         li      r2,0x0c28       /* the first pair is reserved for */
210         li      r1,0x0c30       /* boot-over-rio-or-pci */
211
212 0:      lwzu    r4,4(r6)
213         lwzu    r3,4(r6)
214         stwx    r4,r7,r2
215         stwx    r3,r7,r1
216         addi    r2,r2,0x0020
217         addi    r1,r1,0x0020
218         bdnz    0b
219
220         /* Clear and set up some registers. */
221         li      r0,0x0000
222         lis     r1,0xffff
223         mtspr   DEC,r0                  /* prevent dec exceptions */
224         mttbl   r0                      /* prevent fit & wdt exceptions */
225         mttbu   r0
226         mtspr   TSR,r1                  /* clear all timer exception status */
227         mtspr   TCR,r0                  /* disable all */
228         mtspr   ESR,r0                  /* clear exception syndrome register */
229         mtspr   MCSR,r0                 /* machine check syndrome register */
230         mtxer   r0                      /* clear integer exception register */
231         lis     r1,0x0002               /* set CE bit (Critical Exceptions) */
232         ori     r1,r1,0x1200            /* set ME/DE bit */
233         mtmsr   r1                      /* change MSR */
234         isync
235
236         /* Enable Time Base and Select Time Base Clock */
237         lis     r0,HID0_EMCP@h          /* Enable machine check */
238 #if defined(CONFIG_ENABLE_36BIT_PHYS)
239         ori     r0,r0,(HID0_TBEN|HID0_ENMAS7)@l /* Enable Timebase & MAS7 */
240 #else
241         ori     r0,r0,HID0_TBEN@l       /* enable Timebase */
242 #endif
243         mtspr   HID0,r0
244
245         li      r0,(HID1_ASTME|HID1_ABE)@l      /* Addr streaming & broadcast */
246         mtspr   HID1,r0
247
248         /* Enable Branch Prediction */
249 #if defined(CONFIG_BTB)
250         li      r0,0x201                /* BBFI = 1, BPEN = 1 */
251         mtspr   BUCSR,r0
252 #endif
253
254 #if defined(CFG_INIT_DBCR)
255         lis     r1,0xffff
256         ori     r1,r1,0xffff
257         mtspr   DBSR,r1                 /* Clear all status bits */
258         lis     r0,CFG_INIT_DBCR@h      /* DBCR0[IDM] must be set */
259         ori     r0,r0,CFG_INIT_DBCR@l
260         mtspr   DBCR0,r0
261 #endif
262
263 /* L1 DCache is used for initial RAM */
264
265         /* Allocate Initial RAM in data cache.
266          */
267         lis     r3,CFG_INIT_RAM_ADDR@h
268         ori     r3,r3,CFG_INIT_RAM_ADDR@l
269         li      r2,512 /* 512*32=16K */
270         mtctr   r2
271         li      r0,0
272 1:
273         dcbz    r0,r3
274         dcbtls  0,r0,r3
275         addi    r3,r3,32
276         bdnz    1b
277
278         /* Jump out the last 4K page and continue to 'normal' start */
279 #ifdef CFG_RAMBOOT
280         bl      3f
281         b       _start_cont
282 #else
283         /* Calculate absolute address in FLASH and jump there           */
284         /*--------------------------------------------------------------*/
285         lis     r3,CFG_MONITOR_BASE@h
286         ori     r3,r3,CFG_MONITOR_BASE@l
287         addi    r3,r3,_start_cont - _start + _START_OFFSET
288         mtlr    r3
289 #endif
290
291 3:      li      r0,0
292         mtspr   SRR1,r0         /* Keep things disabled for now */
293         mflr    r1
294         mtspr   SRR0,r1
295         rfi
296         isync
297
298         .text
299         .globl  _start
300 _start:
301         .long   0x27051956              /* U-BOOT Magic Number */
302         .globl  version_string
303 version_string:
304         .ascii U_BOOT_VERSION
305         .ascii " (", __DATE__, " - ", __TIME__, ")"
306         .ascii CONFIG_IDENT_STRING, "\0"
307
308         .align  4
309         .globl  _start_cont
310 _start_cont:
311         /* Setup the stack in initial RAM,could be L2-as-SRAM or L1 dcache*/
312         lis     r1,CFG_INIT_RAM_ADDR@h
313         ori     r1,r1,CFG_INIT_SP_OFFSET@l
314
315         li      r0,0
316         stwu    r0,-4(r1)
317         stwu    r0,-4(r1)               /* Terminate call chain */
318
319         stwu    r1,-8(r1)               /* Save back chain and move SP */
320         lis     r0,RESET_VECTOR@h       /* Address of reset vector */
321         ori     r0,r0,RESET_VECTOR@l
322         stwu    r1,-8(r1)               /* Save back chain and move SP */
323         stw     r0,+12(r1)              /* Save return addr (underflow vect) */
324
325         GET_GOT
326         bl      cpu_init_f
327         bl      board_init_f
328         isync
329
330         . = EXC_OFF_SYS_RESET
331         .globl  _start_of_vectors
332 _start_of_vectors:
333
334 /* Critical input. */
335         CRIT_EXCEPTION(0x0100, CriticalInput, CritcalInputException)
336
337 /* Machine check */
338         MCK_EXCEPTION(0x200, MachineCheck, MachineCheckException)
339
340 /* Data Storage exception. */
341         STD_EXCEPTION(0x0300, DataStorage, UnknownException)
342
343 /* Instruction Storage exception. */
344         STD_EXCEPTION(0x0400, InstStorage, UnknownException)
345
346 /* External Interrupt exception. */
347         STD_EXCEPTION(0x0500, ExtInterrupt, ExtIntException)
348
349 /* Alignment exception. */
350         . = 0x0600
351 Alignment:
352         EXCEPTION_PROLOG(SRR0, SRR1)
353         mfspr   r4,DAR
354         stw     r4,_DAR(r21)
355         mfspr   r5,DSISR
356         stw     r5,_DSISR(r21)
357         addi    r3,r1,STACK_FRAME_OVERHEAD
358         li      r20,MSR_KERNEL
359         rlwimi  r20,r23,0,16,16         /* copy EE bit from saved MSR */
360         lwz     r6,GOT(transfer_to_handler)
361         mtlr    r6
362         blrl
363 .L_Alignment:
364         .long   AlignmentException - _start + _START_OFFSET
365         .long   int_return - _start + _START_OFFSET
366
367 /* Program check exception */
368         . = 0x0700
369 ProgramCheck:
370         EXCEPTION_PROLOG(SRR0, SRR1)
371         addi    r3,r1,STACK_FRAME_OVERHEAD
372         li      r20,MSR_KERNEL
373         rlwimi  r20,r23,0,16,16         /* copy EE bit from saved MSR */
374         lwz     r6,GOT(transfer_to_handler)
375         mtlr    r6
376         blrl
377 .L_ProgramCheck:
378         .long   ProgramCheckException - _start + _START_OFFSET
379         .long   int_return - _start + _START_OFFSET
380
381         /* No FPU on MPC85xx.  This exception is not supposed to happen.
382         */
383         STD_EXCEPTION(0x0800, FPUnavailable, UnknownException)
384
385         . = 0x0900
386 /*
387  * r0 - SYSCALL number
388  * r3-... arguments
389  */
390 SystemCall:
391         addis   r11,r0,0        /* get functions table addr */
392         ori     r11,r11,0       /* Note: this code is patched in trap_init */
393         addis   r12,r0,0        /* get number of functions */
394         ori     r12,r12,0
395
396         cmplw   0,r0,r12
397         bge     1f
398
399         rlwinm  r0,r0,2,0,31    /* fn_addr = fn_tbl[r0] */
400         add     r11,r11,r0
401         lwz     r11,0(r11)
402
403         li      r20,0xd00-4     /* Get stack pointer */
404         lwz     r12,0(r20)
405         subi    r12,r12,12      /* Adjust stack pointer */
406         li      r0,0xc00+_end_back-SystemCall
407         cmplw   0,r0,r12        /* Check stack overflow */
408         bgt     1f
409         stw     r12,0(r20)
410
411         mflr    r0
412         stw     r0,0(r12)
413         mfspr   r0,SRR0
414         stw     r0,4(r12)
415         mfspr   r0,SRR1
416         stw     r0,8(r12)
417
418         li      r12,0xc00+_back-SystemCall
419         mtlr    r12
420         mtspr   SRR0,r11
421
422 1:      SYNC
423         rfi
424 _back:
425
426         mfmsr   r11                     /* Disable interrupts */
427         li      r12,0
428         ori     r12,r12,MSR_EE
429         andc    r11,r11,r12
430         SYNC                            /* Some chip revs need this... */
431         mtmsr   r11
432         SYNC
433
434         li      r12,0xd00-4             /* restore regs */
435         lwz     r12,0(r12)
436
437         lwz     r11,0(r12)
438         mtlr    r11
439         lwz     r11,4(r12)
440         mtspr   SRR0,r11
441         lwz     r11,8(r12)
442         mtspr   SRR1,r11
443
444         addi    r12,r12,12              /* Adjust stack pointer */
445         li      r20,0xd00-4
446         stw     r12,0(r20)
447
448         SYNC
449         rfi
450 _end_back:
451
452         STD_EXCEPTION(0x0a00, Decrementer, timer_interrupt)
453         STD_EXCEPTION(0x0b00, IntervalTimer, UnknownException)
454         STD_EXCEPTION(0x0c00, WatchdogTimer, UnknownException)
455
456         STD_EXCEPTION(0x0d00, DataTLBError, UnknownException)
457         STD_EXCEPTION(0x0e00, InstructionTLBError, UnknownException)
458
459         CRIT_EXCEPTION(0x0f00, DebugBreakpoint, DebugException )
460
461         .globl  _end_of_vectors
462 _end_of_vectors:
463
464
465         . = . + (0x100 - ( . & 0xff ))  /* align for debug */
466
467 /*
468  * This code finishes saving the registers to the exception frame
469  * and jumps to the appropriate handler for the exception.
470  * Register r21 is pointer into trap frame, r1 has new stack pointer.
471  */
472         .globl  transfer_to_handler
473 transfer_to_handler:
474         stw     r22,_NIP(r21)
475         lis     r22,MSR_POW@h
476         andc    r23,r23,r22
477         stw     r23,_MSR(r21)
478         SAVE_GPR(7, r21)
479         SAVE_4GPRS(8, r21)
480         SAVE_8GPRS(12, r21)
481         SAVE_8GPRS(24, r21)
482
483         mflr    r23
484         andi.   r24,r23,0x3f00          /* get vector offset */
485         stw     r24,TRAP(r21)
486         li      r22,0
487         stw     r22,RESULT(r21)
488         mtspr   SPRG2,r22               /* r1 is now kernel sp */
489
490         lwz     r24,0(r23)              /* virtual address of handler */
491         lwz     r23,4(r23)              /* where to go when done */
492         mtspr   SRR0,r24
493         mtspr   SRR1,r20
494         mtlr    r23
495         SYNC
496         rfi                             /* jump to handler, enable MMU */
497
498 int_return:
499         mfmsr   r28             /* Disable interrupts */
500         li      r4,0
501         ori     r4,r4,MSR_EE
502         andc    r28,r28,r4
503         SYNC                    /* Some chip revs need this... */
504         mtmsr   r28
505         SYNC
506         lwz     r2,_CTR(r1)
507         lwz     r0,_LINK(r1)
508         mtctr   r2
509         mtlr    r0
510         lwz     r2,_XER(r1)
511         lwz     r0,_CCR(r1)
512         mtspr   XER,r2
513         mtcrf   0xFF,r0
514         REST_10GPRS(3, r1)
515         REST_10GPRS(13, r1)
516         REST_8GPRS(23, r1)
517         REST_GPR(31, r1)
518         lwz     r2,_NIP(r1)     /* Restore environment */
519         lwz     r0,_MSR(r1)
520         mtspr   SRR0,r2
521         mtspr   SRR1,r0
522         lwz     r0,GPR0(r1)
523         lwz     r2,GPR2(r1)
524         lwz     r1,GPR1(r1)
525         SYNC
526         rfi
527
528 crit_return:
529         mfmsr   r28             /* Disable interrupts */
530         li      r4,0
531         ori     r4,r4,MSR_EE
532         andc    r28,r28,r4
533         SYNC                    /* Some chip revs need this... */
534         mtmsr   r28
535         SYNC
536         lwz     r2,_CTR(r1)
537         lwz     r0,_LINK(r1)
538         mtctr   r2
539         mtlr    r0
540         lwz     r2,_XER(r1)
541         lwz     r0,_CCR(r1)
542         mtspr   XER,r2
543         mtcrf   0xFF,r0
544         REST_10GPRS(3, r1)
545         REST_10GPRS(13, r1)
546         REST_8GPRS(23, r1)
547         REST_GPR(31, r1)
548         lwz     r2,_NIP(r1)     /* Restore environment */
549         lwz     r0,_MSR(r1)
550         mtspr   SPRN_CSRR0,r2
551         mtspr   SPRN_CSRR1,r0
552         lwz     r0,GPR0(r1)
553         lwz     r2,GPR2(r1)
554         lwz     r1,GPR1(r1)
555         SYNC
556         rfci
557
558 mck_return:
559         mfmsr   r28             /* Disable interrupts */
560         li      r4,0
561         ori     r4,r4,MSR_EE
562         andc    r28,r28,r4
563         SYNC                    /* Some chip revs need this... */
564         mtmsr   r28
565         SYNC
566         lwz     r2,_CTR(r1)
567         lwz     r0,_LINK(r1)
568         mtctr   r2
569         mtlr    r0
570         lwz     r2,_XER(r1)
571         lwz     r0,_CCR(r1)
572         mtspr   XER,r2
573         mtcrf   0xFF,r0
574         REST_10GPRS(3, r1)
575         REST_10GPRS(13, r1)
576         REST_8GPRS(23, r1)
577         REST_GPR(31, r1)
578         lwz     r2,_NIP(r1)     /* Restore environment */
579         lwz     r0,_MSR(r1)
580         mtspr   SPRN_MCSRR0,r2
581         mtspr   SPRN_MCSRR1,r0
582         lwz     r0,GPR0(r1)
583         lwz     r2,GPR2(r1)
584         lwz     r1,GPR1(r1)
585         SYNC
586         rfmci
587
588 /* Cache functions.
589 */
590 invalidate_icache:
591         mfspr   r0,L1CSR1
592         ori     r0,r0,L1CSR1_ICFI
593         msync
594         isync
595         mtspr   L1CSR1,r0
596         isync
597         blr                             /* entire I cache */
598
599 invalidate_dcache:
600         mfspr   r0,L1CSR0
601         ori     r0,r0,L1CSR0_DCFI
602         msync
603         isync
604         mtspr   L1CSR0,r0
605         isync
606         blr
607
608         .globl  icache_enable
609 icache_enable:
610         mflr    r8
611         bl      invalidate_icache
612         mtlr    r8
613         isync
614         mfspr   r4,L1CSR1
615         ori     r4,r4,0x0001
616         oris    r4,r4,0x0001
617         mtspr   L1CSR1,r4
618         isync
619         blr
620
621         .globl  icache_disable
622 icache_disable:
623         mfspr   r0,L1CSR1
624         lis     r3,0
625         ori     r3,r3,L1CSR1_ICE
626         andc    r0,r0,r3
627         mtspr   L1CSR1,r0
628         isync
629         blr
630
631         .globl  icache_status
632 icache_status:
633         mfspr   r3,L1CSR1
634         andi.   r3,r3,L1CSR1_ICE
635         blr
636
637         .globl  dcache_enable
638 dcache_enable:
639         mflr    r8
640         bl      invalidate_dcache
641         mtlr    r8
642         isync
643         mfspr   r0,L1CSR0
644         ori     r0,r0,0x0001
645         oris    r0,r0,0x0001
646         msync
647         isync
648         mtspr   L1CSR0,r0
649         isync
650         blr
651
652         .globl  dcache_disable
653 dcache_disable:
654         mfspr   r3,L1CSR0
655         lis     r4,0
656         ori     r4,r4,L1CSR0_DCE
657         andc    r3,r3,r4
658         mtspr   L1CSR0,r0
659         isync
660         blr
661
662         .globl  dcache_status
663 dcache_status:
664         mfspr   r3,L1CSR0
665         andi.   r3,r3,L1CSR0_DCE
666         blr
667
668         .globl get_pir
669 get_pir:
670         mfspr   r3,PIR
671         blr
672
673         .globl get_pvr
674 get_pvr:
675         mfspr   r3,PVR
676         blr
677
678         .globl get_svr
679 get_svr:
680         mfspr   r3,SVR
681         blr
682
683         .globl wr_tcr
684 wr_tcr:
685         mtspr   TCR,r3
686         blr
687
688 /*------------------------------------------------------------------------------- */
689 /* Function:     in8 */
690 /* Description:  Input 8 bits */
691 /*------------------------------------------------------------------------------- */
692         .globl  in8
693 in8:
694         lbz     r3,0x0000(r3)
695         blr
696
697 /*------------------------------------------------------------------------------- */
698 /* Function:     out8 */
699 /* Description:  Output 8 bits */
700 /*------------------------------------------------------------------------------- */
701         .globl  out8
702 out8:
703         stb     r4,0x0000(r3)
704         blr
705
706 /*------------------------------------------------------------------------------- */
707 /* Function:     out16 */
708 /* Description:  Output 16 bits */
709 /*------------------------------------------------------------------------------- */
710         .globl  out16
711 out16:
712         sth     r4,0x0000(r3)
713         blr
714
715 /*------------------------------------------------------------------------------- */
716 /* Function:     out16r */
717 /* Description:  Byte reverse and output 16 bits */
718 /*------------------------------------------------------------------------------- */
719         .globl  out16r
720 out16r:
721         sthbrx  r4,r0,r3
722         blr
723
724 /*------------------------------------------------------------------------------- */
725 /* Function:     out32 */
726 /* Description:  Output 32 bits */
727 /*------------------------------------------------------------------------------- */
728         .globl  out32
729 out32:
730         stw     r4,0x0000(r3)
731         blr
732
733 /*------------------------------------------------------------------------------- */
734 /* Function:     out32r */
735 /* Description:  Byte reverse and output 32 bits */
736 /*------------------------------------------------------------------------------- */
737         .globl  out32r
738 out32r:
739         stwbrx  r4,r0,r3
740         blr
741
742 /*------------------------------------------------------------------------------- */
743 /* Function:     in16 */
744 /* Description:  Input 16 bits */
745 /*------------------------------------------------------------------------------- */
746         .globl  in16
747 in16:
748         lhz     r3,0x0000(r3)
749         blr
750
751 /*------------------------------------------------------------------------------- */
752 /* Function:     in16r */
753 /* Description:  Input 16 bits and byte reverse */
754 /*------------------------------------------------------------------------------- */
755         .globl  in16r
756 in16r:
757         lhbrx   r3,r0,r3
758         blr
759
760 /*------------------------------------------------------------------------------- */
761 /* Function:     in32 */
762 /* Description:  Input 32 bits */
763 /*------------------------------------------------------------------------------- */
764         .globl  in32
765 in32:
766         lwz     3,0x0000(3)
767         blr
768
769 /*------------------------------------------------------------------------------- */
770 /* Function:     in32r */
771 /* Description:  Input 32 bits and byte reverse */
772 /*------------------------------------------------------------------------------- */
773         .globl  in32r
774 in32r:
775         lwbrx   r3,r0,r3
776         blr
777
778 /*------------------------------------------------------------------------------- */
779 /* Function:     ppcDcbf */
780 /* Description:  Data Cache block flush */
781 /* Input:        r3 = effective address */
782 /* Output:       none. */
783 /*------------------------------------------------------------------------------- */
784         .globl  ppcDcbf
785 ppcDcbf:
786         dcbf    r0,r3
787         blr
788
789 /*------------------------------------------------------------------------------- */
790 /* Function:     ppcDcbi */
791 /* Description:  Data Cache block Invalidate */
792 /* Input:        r3 = effective address */
793 /* Output:       none. */
794 /*------------------------------------------------------------------------------- */
795         .globl  ppcDcbi
796 ppcDcbi:
797         dcbi    r0,r3
798         blr
799
800 /*--------------------------------------------------------------------------
801  * Function:     ppcDcbz
802  * Description:  Data Cache block zero.
803  * Input:        r3 = effective address
804  * Output:       none.
805  *-------------------------------------------------------------------------- */
806
807         .globl  ppcDcbz
808 ppcDcbz:
809         dcbz    r0,r3
810         blr
811
812 /*------------------------------------------------------------------------------- */
813 /* Function:     ppcSync */
814 /* Description:  Processor Synchronize */
815 /* Input:        none. */
816 /* Output:       none. */
817 /*------------------------------------------------------------------------------- */
818         .globl  ppcSync
819 ppcSync:
820         sync
821         blr
822
823 /*------------------------------------------------------------------------------*/
824
825 /*
826  * void relocate_code (addr_sp, gd, addr_moni)
827  *
828  * This "function" does not return, instead it continues in RAM
829  * after relocating the monitor code.
830  *
831  * r3 = dest
832  * r4 = src
833  * r5 = length in bytes
834  * r6 = cachelinesize
835  */
836         .globl  relocate_code
837 relocate_code:
838         mr      r1,r3           /* Set new stack pointer                */
839         mr      r9,r4           /* Save copy of Init Data pointer       */
840         mr      r10,r5          /* Save copy of Destination Address     */
841
842         mr      r3,r5                           /* Destination Address  */
843         lis     r4,CFG_MONITOR_BASE@h           /* Source      Address  */
844         ori     r4,r4,CFG_MONITOR_BASE@l
845         lwz     r5,GOT(__init_end)
846         sub     r5,r5,r4
847         li      r6,CFG_CACHELINE_SIZE           /* Cache Line Size      */
848
849         /*
850          * Fix GOT pointer:
851          *
852          * New GOT-PTR = (old GOT-PTR - CFG_MONITOR_BASE) + Destination Address
853          *
854          * Offset:
855          */
856         sub     r15,r10,r4
857
858         /* First our own GOT */
859         add     r14,r14,r15
860         /* the the one used by the C code */
861         add     r30,r30,r15
862
863         /*
864          * Now relocate code
865          */
866
867         cmplw   cr1,r3,r4
868         addi    r0,r5,3
869         srwi.   r0,r0,2
870         beq     cr1,4f          /* In place copy is not necessary       */
871         beq     7f              /* Protect against 0 count              */
872         mtctr   r0
873         bge     cr1,2f
874
875         la      r8,-4(r4)
876         la      r7,-4(r3)
877 1:      lwzu    r0,4(r8)
878         stwu    r0,4(r7)
879         bdnz    1b
880         b       4f
881
882 2:      slwi    r0,r0,2
883         add     r8,r4,r0
884         add     r7,r3,r0
885 3:      lwzu    r0,-4(r8)
886         stwu    r0,-4(r7)
887         bdnz    3b
888
889 /*
890  * Now flush the cache: note that we must start from a cache aligned
891  * address. Otherwise we might miss one cache line.
892  */
893 4:      cmpwi   r6,0
894         add     r5,r3,r5
895         beq     7f              /* Always flush prefetch queue in any case */
896         subi    r0,r6,1
897         andc    r3,r3,r0
898         mr      r4,r3
899 5:      dcbst   0,r4
900         add     r4,r4,r6
901         cmplw   r4,r5
902         blt     5b
903         sync                    /* Wait for all dcbst to complete on bus */
904         mr      r4,r3
905 6:      icbi    0,r4
906         add     r4,r4,r6
907         cmplw   r4,r5
908         blt     6b
909 7:      sync                    /* Wait for all icbi to complete on bus */
910         isync
911
912         /*
913          * Re-point the IVPR at RAM
914          */
915         mtspr   IVPR,r10
916
917 /*
918  * We are done. Do not return, instead branch to second part of board
919  * initialization, now running from RAM.
920  */
921
922         addi    r0,r10,in_ram - _start + _START_OFFSET
923         mtlr    r0
924         blr                             /* NEVER RETURNS! */
925         .globl  in_ram
926 in_ram:
927
928         /*
929          * Relocation Function, r14 point to got2+0x8000
930          *
931          * Adjust got2 pointers, no need to check for 0, this code
932          * already puts a few entries in the table.
933          */
934         li      r0,__got2_entries@sectoff@l
935         la      r3,GOT(_GOT2_TABLE_)
936         lwz     r11,GOT(_GOT2_TABLE_)
937         mtctr   r0
938         sub     r11,r3,r11
939         addi    r3,r3,-4
940 1:      lwzu    r0,4(r3)
941         add     r0,r0,r11
942         stw     r0,0(r3)
943         bdnz    1b
944
945         /*
946          * Now adjust the fixups and the pointers to the fixups
947          * in case we need to move ourselves again.
948          */
949 2:      li      r0,__fixup_entries@sectoff@l
950         lwz     r3,GOT(_FIXUP_TABLE_)
951         cmpwi   r0,0
952         mtctr   r0
953         addi    r3,r3,-4
954         beq     4f
955 3:      lwzu    r4,4(r3)
956         lwzux   r0,r4,r11
957         add     r0,r0,r11
958         stw     r10,0(r3)
959         stw     r0,0(r4)
960         bdnz    3b
961 4:
962 clear_bss:
963         /*
964          * Now clear BSS segment
965          */
966         lwz     r3,GOT(__bss_start)
967         lwz     r4,GOT(_end)
968
969         cmplw   0,r3,r4
970         beq     6f
971
972         li      r0,0
973 5:
974         stw     r0,0(r3)
975         addi    r3,r3,4
976         cmplw   0,r3,r4
977         bne     5b
978 6:
979
980         mr      r3,r9           /* Init Data pointer            */
981         mr      r4,r10          /* Destination Address          */
982         bl      board_init_r
983
984         /*
985          * Copy exception vector code to low memory
986          *
987          * r3: dest_addr
988          * r7: source address, r8: end address, r9: target address
989          */
990         .globl  trap_init
991 trap_init:
992         lwz     r7,GOT(_start_of_vectors)
993         lwz     r8,GOT(_end_of_vectors)
994
995         li      r9,0x100                /* reset vector always at 0x100 */
996
997         cmplw   0,r7,r8
998         bgelr                           /* return if r7>=r8 - just in case */
999
1000         mflr    r4                      /* save link register           */
1001 1:
1002         lwz     r0,0(r7)
1003         stw     r0,0(r9)
1004         addi    r7,r7,4
1005         addi    r9,r9,4
1006         cmplw   0,r7,r8
1007         bne     1b
1008
1009         /*
1010          * relocate `hdlr' and `int_return' entries
1011          */
1012         li      r7,.L_CriticalInput - _start + _START_OFFSET
1013         bl      trap_reloc
1014         li      r7,.L_MachineCheck - _start + _START_OFFSET
1015         bl      trap_reloc
1016         li      r7,.L_DataStorage - _start + _START_OFFSET
1017         bl      trap_reloc
1018         li      r7,.L_InstStorage - _start + _START_OFFSET
1019         bl      trap_reloc
1020         li      r7,.L_ExtInterrupt - _start + _START_OFFSET
1021         bl      trap_reloc
1022         li      r7,.L_Alignment - _start + _START_OFFSET
1023         bl      trap_reloc
1024         li      r7,.L_ProgramCheck - _start + _START_OFFSET
1025         bl      trap_reloc
1026         li      r7,.L_FPUnavailable - _start + _START_OFFSET
1027         bl      trap_reloc
1028         li      r7,.L_Decrementer - _start + _START_OFFSET
1029         bl      trap_reloc
1030         li      r7,.L_IntervalTimer - _start + _START_OFFSET
1031         li      r8,_end_of_vectors - _start + _START_OFFSET
1032 2:
1033         bl      trap_reloc
1034         addi    r7,r7,0x100             /* next exception vector        */
1035         cmplw   0,r7,r8
1036         blt     2b
1037
1038         lis     r7,0x0
1039         mtspr   IVPR,r7
1040
1041         mtlr    r4                      /* restore link register        */
1042         blr
1043
1044         /*
1045          * Function: relocate entries for one exception vector
1046          */
1047 trap_reloc:
1048         lwz     r0,0(r7)                /* hdlr ...                     */
1049         add     r0,r0,r3                /*  ... += dest_addr            */
1050         stw     r0,0(r7)
1051
1052         lwz     r0,4(r7)                /* int_return ...               */
1053         add     r0,r0,r3                /*  ... += dest_addr            */
1054         stw     r0,4(r7)
1055
1056         blr
1057
1058 #ifdef CFG_INIT_RAM_LOCK
1059 .globl unlock_ram_in_cache
1060 unlock_ram_in_cache:
1061         /* invalidate the INIT_RAM section */
1062         lis     r3,(CFG_INIT_RAM_ADDR & ~31)@h
1063         ori     r3,r3,(CFG_INIT_RAM_ADDR & ~31)@l
1064         li      r4,512
1065         mtctr   r4
1066 1:      icbi    r0,r3
1067         dcbi    r0,r3
1068         addi    r3,r3,32
1069         bdnz    1b
1070         sync                    /* Wait for all icbi to complete on bus */
1071         isync
1072         blr
1073 #endif