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