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