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