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