Coding style cleanup
[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         /* not needed and conflicts with some debuggers */
159         /* mtspr        DBCR0,r0 */
160         mtspr   DBCR1,r0
161         mtspr   DBCR2,r0
162         /* not needed and conflicts with some debuggers */
163         /* mtspr        IAC1,r0 */
164         /* mtspr        IAC2,r0 */
165         mtspr   DAC1,r0
166         mtspr   DAC2,r0
167
168         mfspr   r1,DBSR
169         mtspr   DBSR,r1         /* Clear all valid bits */
170
171         mtspr   PID0,r0
172         mtspr   PID1,r0
173         mtspr   PID2,r0
174         mtspr   TCR,r0
175
176         mtspr   BUCSR,r0        /* disable branch prediction */
177         mtspr   MAS4,r0
178         mtspr   MAS6,r0
179 #if defined(CONFIG_ENABLE_36BIT_PHYS)
180         mtspr   MAS7,r0
181 #endif
182         isync
183
184         /* Setup interrupt vectors */
185         lis     r1,TEXT_BASE@h
186         mtspr IVPR, r1
187
188         li      r1,0x0100
189         mtspr   IVOR0,r1        /* 0: Critical input */
190         li      r1,0x0200
191         mtspr   IVOR1,r1        /* 1: Machine check */
192         li      r1,0x0300
193         mtspr   IVOR2,r1        /* 2: Data storage */
194         li      r1,0x0400
195         mtspr   IVOR3,r1        /* 3: Instruction storage */
196         li      r1,0x0500
197         mtspr   IVOR4,r1        /* 4: External interrupt */
198         li      r1,0x0600
199         mtspr   IVOR5,r1        /* 5: Alignment */
200         li      r1,0x0700
201         mtspr   IVOR6,r1        /* 6: Program check */
202         li      r1,0x0800
203         mtspr   IVOR7,r1        /* 7: floating point unavailable */
204         li      r1,0x0900
205         mtspr   IVOR8,r1        /* 8: System call */
206         /* 9: Auxiliary processor unavailable(unsupported) */
207         li      r1,0x0a00
208         mtspr   IVOR10,r1       /* 10: Decrementer */
209         li      r1,0x0b00
210         mtspr   IVOR11,r1       /* 11: Interval timer */
211         li      r1,0x0c00
212         mtspr   IVOR12,r1       /* 12: Watchdog timer */
213         li      r1,0x0d00
214         mtspr   IVOR13,r1       /* 13: Data TLB error */
215         li      r1,0x0e00
216         mtspr   IVOR14,r1       /* 14: Instruction TLB error */
217         li      r1,0x0f00
218         mtspr   IVOR15,r1       /* 15: Debug */
219
220         /*
221          * Invalidate MMU L1/L2
222          *
223          * Note: There is a fixup earlier for Errata CPU4 on
224          * Rev 1 parts that must precede this MMU invalidation.
225          */
226         li      r2, 0x001e
227         mtspr   MMUCSR0, r2
228         isync
229
230         /*
231          * Invalidate all TLB0 entries.
232          */
233         li      r3,4
234         li      r4,0
235         tlbivax r4,r3
236         /*
237          * To avoid REV1 Errata CPU6 issues, make sure
238          * the instruction following tlbivax is not a store.
239          */
240
241         /*
242          * After reset, CCSRBAR is located at CFG_CCSRBAR_DEFAULT, i.e.
243          * 0xff700000-0xff800000. We need add a TLB1 entry for this 1MB
244          * region before we can access any CCSR registers such as L2
245          * registers, Local Access Registers,etc. We will also re-allocate
246          * CFG_CCSRBAR_DEFAULT to CFG_CCSRBAR immediately after TLB1 setup.
247          *
248          * Please refer to board-specif directory for TLB1 entry configuration.
249          * (e.g. board/<yourboard>/init.S)
250          *
251          */
252         bl      tlb1_entry
253         mr      r5,r0
254         lwzu    r4,0(r5)        /* how many TLB1 entries we actually use */
255         mtctr   r4
256
257 0:      lwzu    r0,4(r5)
258         lwzu    r1,4(r5)
259         lwzu    r2,4(r5)
260         lwzu    r3,4(r5)
261         mtspr   MAS0,r0
262         mtspr   MAS1,r1
263         mtspr   MAS2,r2
264         mtspr   MAS3,r3
265         isync
266         msync
267         tlbwe
268         isync
269         bdnz    0b
270
271 1:
272 #if (CFG_CCSRBAR_DEFAULT != CFG_CCSRBAR)
273         /* Special sequence needed to update CCSRBAR itself */
274         lis     r4, CFG_CCSRBAR_DEFAULT@h
275         ori     r4, r4, CFG_CCSRBAR_DEFAULT@l
276
277         lis     r5, CFG_CCSRBAR@h
278         ori     r5, r5, CFG_CCSRBAR@l
279         srwi    r6,r5,12
280         stw     r6, 0(r4)
281         isync
282
283         lis     r5, 0xffff
284         ori     r5,r5,0xf000
285         lwz     r5, 0(r5)
286         isync
287
288         lis     r3, CFG_CCSRBAR@h
289         lwz     r5, CFG_CCSRBAR@l(r3)
290         isync
291 #endif
292
293
294         /* set up local access windows, defined at board/<boardname>/init.S */
295         lis     r7,CFG_CCSRBAR@h
296         ori     r7,r7,CFG_CCSRBAR@l
297
298         bl      law_entry
299         mr      r6,r0
300         lwzu    r5,0(r6)        /* how many windows we actually use */
301         mtctr   r5
302
303         li      r2,0x0c28       /* the first pair is reserved for boot-over-rio-or-pci */
304         li      r1,0x0c30
305
306 0:      lwzu    r4,4(r6)
307         lwzu    r3,4(r6)
308         stwx    r4,r7,r2
309         stwx    r3,r7,r1
310         addi    r2,r2,0x0020
311         addi    r1,r1,0x0020
312         bdnz    0b
313
314         /* Jump out the last 4K page and continue to 'normal' start */
315 1:      bl      3f
316         b       _start
317
318 3:      li      r0,0
319         mtspr   SRR1,r0         /* Keep things disabled for now */
320         mflr    r1
321         mtspr   SRR0,r1
322         rfi
323
324 /*
325  * r3 - 1st arg to board_init(): IMMP pointer
326  * r4 - 2nd arg to board_init(): boot flag
327  */
328         .text
329         .long   0x27051956              /* U-BOOT Magic Number                  */
330         .globl  version_string
331 version_string:
332         .ascii U_BOOT_VERSION
333         .ascii " (", __DATE__, " - ", __TIME__, ")"
334         .ascii CONFIG_IDENT_STRING, "\0"
335
336         . = EXC_OFF_SYS_RESET
337         .globl  _start
338 _start:
339         /* Clear and set up some registers. */
340         li      r0,0x0000
341         lis     r1,0xffff
342         mtspr   DEC,r0                  /* prevent dec exceptions */
343         mttbl   r0                      /* prevent fit & wdt exceptions */
344         mttbu   r0
345         mtspr   TSR,r1                  /* clear all timer exception status */
346         mtspr   TCR,r0                  /* disable all */
347         mtspr   ESR,r0                  /* clear exception syndrome register */
348         mtspr   MCSR,r0                 /* machine check syndrome register */
349         mtxer   r0                      /* clear integer exception register */
350         lis     r1,0x0002               /* set CE bit (Critical Exceptions) */
351         ori     r1,r1,0x1200            /* set ME/DE bit */
352         mtmsr   r1                      /* change MSR */
353         isync
354
355         /* Enable Time Base and Select Time Base Clock */
356         lis     r0,HID0_EMCP@h          /* Enable machine check */
357         ori     r0,r0,0x4000            /* time base is processor clock */
358 #if defined(CONFIG_ENABLE_36BIT_PHYS)
359         ori     r0,r0,0x0080            /* enable MAS7 updates */
360 #endif
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(SRR0, SRR1)
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(SRR0, SRR1)
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         andi.   r3,r3,1
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         andi.   r3,r3,1
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          * Re-point the IVPR at RAM
992          */
993         mtspr   IVPR,r10
994
995 /*
996  * We are done. Do not return, instead branch to second part of board
997  * initialization, now running from RAM.
998  */
999
1000         addi    r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
1001         mtlr    r0
1002         blr                             /* NEVER RETURNS! */
1003
1004 in_ram:
1005
1006         /*
1007          * Relocation Function, r14 point to got2+0x8000
1008          *
1009          * Adjust got2 pointers, no need to check for 0, this code
1010          * already puts a few entries in the table.
1011          */
1012         li      r0,__got2_entries@sectoff@l
1013         la      r3,GOT(_GOT2_TABLE_)
1014         lwz     r11,GOT(_GOT2_TABLE_)
1015         mtctr   r0
1016         sub     r11,r3,r11
1017         addi    r3,r3,-4
1018 1:      lwzu    r0,4(r3)
1019         add     r0,r0,r11
1020         stw     r0,0(r3)
1021         bdnz    1b
1022
1023         /*
1024          * Now adjust the fixups and the pointers to the fixups
1025          * in case we need to move ourselves again.
1026          */
1027 2:      li      r0,__fixup_entries@sectoff@l
1028         lwz     r3,GOT(_FIXUP_TABLE_)
1029         cmpwi   r0,0
1030         mtctr   r0
1031         addi    r3,r3,-4
1032         beq     4f
1033 3:      lwzu    r4,4(r3)
1034         lwzux   r0,r4,r11
1035         add     r0,r0,r11
1036         stw     r10,0(r3)
1037         stw     r0,0(r4)
1038         bdnz    3b
1039 4:
1040 clear_bss:
1041         /*
1042          * Now clear BSS segment
1043          */
1044         lwz     r3,GOT(__bss_start)
1045         lwz     r4,GOT(_end)
1046
1047         cmplw   0, r3, r4
1048         beq     6f
1049
1050         li      r0, 0
1051 5:
1052         stw     r0, 0(r3)
1053         addi    r3, r3, 4
1054         cmplw   0, r3, r4
1055         bne     5b
1056 6:
1057
1058         mr      r3, r9          /* Init Data pointer            */
1059         mr      r4, r10         /* Destination Address          */
1060         bl      board_init_r
1061
1062         /*
1063          * Copy exception vector code to low memory
1064          *
1065          * r3: dest_addr
1066          * r7: source address, r8: end address, r9: target address
1067          */
1068         .globl  trap_init
1069 trap_init:
1070         lwz     r7, GOT(_start)
1071         lwz     r8, GOT(_end_of_vectors)
1072
1073         li      r9, 0x100               /* reset vector always at 0x100 */
1074
1075         cmplw   0, r7, r8
1076         bgelr                           /* return if r7>=r8 - just in case */
1077
1078         mflr    r4                      /* save link register           */
1079 1:
1080         lwz     r0, 0(r7)
1081         stw     r0, 0(r9)
1082         addi    r7, r7, 4
1083         addi    r9, r9, 4
1084         cmplw   0, r7, r8
1085         bne     1b
1086
1087         /*
1088          * relocate `hdlr' and `int_return' entries
1089          */
1090         li      r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
1091         bl      trap_reloc
1092         li      r7, .L_DataStorage - _start + EXC_OFF_SYS_RESET
1093         bl      trap_reloc
1094         li      r7, .L_InstStorage - _start + EXC_OFF_SYS_RESET
1095         bl      trap_reloc
1096         li      r7, .L_ExtInterrupt - _start + EXC_OFF_SYS_RESET
1097         bl      trap_reloc
1098         li      r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
1099         bl      trap_reloc
1100         li      r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
1101         bl      trap_reloc
1102         li      r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
1103         bl      trap_reloc
1104         li      r7, .L_Decrementer - _start + EXC_OFF_SYS_RESET
1105         bl      trap_reloc
1106         li      r7, .L_IntervalTimer - _start + EXC_OFF_SYS_RESET
1107         li      r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
1108 2:
1109         bl      trap_reloc
1110         addi    r7, r7, 0x100           /* next exception vector        */
1111         cmplw   0, r7, r8
1112         blt     2b
1113
1114         lis     r7,0x0
1115         mtspr   IVPR, r7
1116
1117         mtlr    r4                      /* restore link register        */
1118         blr
1119
1120         /*
1121          * Function: relocate entries for one exception vector
1122          */
1123 trap_reloc:
1124         lwz     r0, 0(r7)               /* hdlr ...                     */
1125         add     r0, r0, r3              /*  ... += dest_addr            */
1126         stw     r0, 0(r7)
1127
1128         lwz     r0, 4(r7)               /* int_return ...               */
1129         add     r0, r0, r3              /*  ... += dest_addr            */
1130         stw     r0, 4(r7)
1131
1132         blr
1133
1134 #ifdef CFG_INIT_RAM_LOCK
1135 .globl unlock_ram_in_cache
1136 unlock_ram_in_cache:
1137         /* invalidate the INIT_RAM section */
1138         lis     r3, (CFG_INIT_RAM_ADDR & ~31)@h
1139         ori     r3, r3, (CFG_INIT_RAM_ADDR & ~31)@l
1140         li      r2,512
1141         mtctr   r2
1142 1:      icbi    r0, r3
1143         dcbi    r0, r3
1144         addi    r3, r3, 32
1145         bdnz    1b
1146         sync                    /* Wait for all icbi to complete on bus */
1147         isync
1148         blr
1149 #endif