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