]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/powerpc/cpu/mpc85xx/start.S
Merge branch 'master' of git://git.denx.de/u-boot-arm
[karo-tx-uboot.git] / arch / powerpc / cpu / mpc85xx / start.S
1 /*
2  * Copyright 2004, 2007-2010 Freescale Semiconductor, Inc.
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 <timestamp.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 r12 to access the GOT
55  */
56         START_GOT
57         GOT_ENTRY(_GOT2_TABLE_)
58         GOT_ENTRY(_FIXUP_TABLE_)
59
60 #ifndef CONFIG_NAND_SPL
61         GOT_ENTRY(_start)
62         GOT_ENTRY(_start_of_vectors)
63         GOT_ENTRY(_end_of_vectors)
64         GOT_ENTRY(transfer_to_handler)
65 #endif
66
67         GOT_ENTRY(__init_end)
68         GOT_ENTRY(_end)
69         GOT_ENTRY(__bss_start)
70         END_GOT
71
72 /*
73  * e500 Startup -- after reset only the last 4KB of the effective
74  * address space is mapped in the MMU L2 TLB1 Entry0. The .bootpg
75  * section is located at THIS LAST page and basically does three
76  * things: clear some registers, set up exception tables and
77  * add more TLB entries for 'larger spaces'(e.g. the boot rom) to
78  * continue the boot procedure.
79
80  * Once the boot rom is mapped by TLB entries we can proceed
81  * with normal startup.
82  *
83  */
84
85         .section .bootpg,"ax"
86         .globl _start_e500
87
88 _start_e500:
89
90 /* clear registers/arrays not reset by hardware */
91
92         /* L1 */
93         li      r0,2
94         mtspr   L1CSR0,r0       /* invalidate d-cache */
95         mtspr   L1CSR1,r0       /* invalidate i-cache */
96
97         mfspr   r1,DBSR
98         mtspr   DBSR,r1         /* Clear all valid bits */
99
100         /*
101          *      Enable L1 Caches early
102          *
103          */
104
105 #if defined(CONFIG_E500MC) && defined(CONFIG_SYS_CACHE_STASHING)
106         /* set stash id to (coreID) * 2 + 32 + L1 CT (0) */
107         li      r2,(32 + 0)
108         mtspr   L1CSR2,r2
109 #endif
110
111         /* Enable/invalidate the I-Cache */
112         lis     r2,(L1CSR1_ICFI|L1CSR1_ICLFR)@h
113         ori     r2,r2,(L1CSR1_ICFI|L1CSR1_ICLFR)@l
114         mtspr   SPRN_L1CSR1,r2
115 1:
116         mfspr   r3,SPRN_L1CSR1
117         and.    r1,r3,r2
118         bne     1b
119
120         lis     r3,(L1CSR1_CPE|L1CSR1_ICE)@h
121         ori     r3,r3,(L1CSR1_CPE|L1CSR1_ICE)@l
122         mtspr   SPRN_L1CSR1,r3
123         isync
124 2:
125         mfspr   r3,SPRN_L1CSR1
126         andi.   r1,r3,L1CSR1_ICE@l
127         beq     2b
128
129         /* Enable/invalidate the D-Cache */
130         lis     r2,(L1CSR0_DCFI|L1CSR0_DCLFR)@h
131         ori     r2,r2,(L1CSR0_DCFI|L1CSR0_DCLFR)@l
132         mtspr   SPRN_L1CSR0,r2
133 1:
134         mfspr   r3,SPRN_L1CSR0
135         and.    r1,r3,r2
136         bne     1b
137
138         lis     r3,(L1CSR0_CPE|L1CSR0_DCE)@h
139         ori     r3,r3,(L1CSR0_CPE|L1CSR0_DCE)@l
140         mtspr   SPRN_L1CSR0,r3
141         isync
142 2:
143         mfspr   r3,SPRN_L1CSR0
144         andi.   r1,r3,L1CSR0_DCE@l
145         beq     2b
146
147         /* Setup interrupt vectors */
148         lis     r1,TEXT_BASE@h
149         mtspr   IVPR,r1
150
151         li      r1,0x0100
152         mtspr   IVOR0,r1        /* 0: Critical input */
153         li      r1,0x0200
154         mtspr   IVOR1,r1        /* 1: Machine check */
155         li      r1,0x0300
156         mtspr   IVOR2,r1        /* 2: Data storage */
157         li      r1,0x0400
158         mtspr   IVOR3,r1        /* 3: Instruction storage */
159         li      r1,0x0500
160         mtspr   IVOR4,r1        /* 4: External interrupt */
161         li      r1,0x0600
162         mtspr   IVOR5,r1        /* 5: Alignment */
163         li      r1,0x0700
164         mtspr   IVOR6,r1        /* 6: Program check */
165         li      r1,0x0800
166         mtspr   IVOR7,r1        /* 7: floating point unavailable */
167         li      r1,0x0900
168         mtspr   IVOR8,r1        /* 8: System call */
169         /* 9: Auxiliary processor unavailable(unsupported) */
170         li      r1,0x0a00
171         mtspr   IVOR10,r1       /* 10: Decrementer */
172         li      r1,0x0b00
173         mtspr   IVOR11,r1       /* 11: Interval timer */
174         li      r1,0x0c00
175         mtspr   IVOR12,r1       /* 12: Watchdog timer */
176         li      r1,0x0d00
177         mtspr   IVOR13,r1       /* 13: Data TLB error */
178         li      r1,0x0e00
179         mtspr   IVOR14,r1       /* 14: Instruction TLB error */
180         li      r1,0x0f00
181         mtspr   IVOR15,r1       /* 15: Debug */
182
183         /* Clear and set up some registers. */
184         li      r0,0x0000
185         lis     r1,0xffff
186         mtspr   DEC,r0                  /* prevent dec exceptions */
187         mttbl   r0                      /* prevent fit & wdt exceptions */
188         mttbu   r0
189         mtspr   TSR,r1                  /* clear all timer exception status */
190         mtspr   TCR,r0                  /* disable all */
191         mtspr   ESR,r0                  /* clear exception syndrome register */
192         mtspr   MCSR,r0                 /* machine check syndrome register */
193         mtxer   r0                      /* clear integer exception register */
194
195 #ifdef CONFIG_SYS_BOOK3E_HV
196         mtspr   MAS8,r0                 /* make sure MAS8 is clear */
197 #endif
198
199         /* Enable Time Base and Select Time Base Clock */
200         lis     r0,HID0_EMCP@h          /* Enable machine check */
201 #if defined(CONFIG_ENABLE_36BIT_PHYS)
202         ori     r0,r0,HID0_ENMAS7@l     /* Enable MAS7 */
203 #endif
204 #ifndef CONFIG_E500MC
205         ori     r0,r0,HID0_TBEN@l       /* Enable Timebase */
206 #endif
207         mtspr   HID0,r0
208
209 #ifndef CONFIG_E500MC
210         li      r0,(HID1_ASTME|HID1_ABE)@l      /* Addr streaming & broadcast */
211         mfspr   r3,PVR
212         andi.   r3,r3, 0xff
213         cmpwi   r3,0x50@l       /* if we are rev 5.0 or greater set MBDD */
214         blt 1f
215         /* Set MBDD bit also */
216         ori r0, r0, HID1_MBDD@l
217 1:
218         mtspr   HID1,r0
219 #endif
220
221         /* Enable Branch Prediction */
222 #if defined(CONFIG_BTB)
223         lis     r0,BUCSR_ENABLE@h
224         ori     r0,r0,BUCSR_ENABLE@l
225         mtspr   SPRN_BUCSR,r0
226 #endif
227
228 #if defined(CONFIG_SYS_INIT_DBCR)
229         lis     r1,0xffff
230         ori     r1,r1,0xffff
231         mtspr   DBSR,r1                 /* Clear all status bits */
232         lis     r0,CONFIG_SYS_INIT_DBCR@h       /* DBCR0[IDM] must be set */
233         ori     r0,r0,CONFIG_SYS_INIT_DBCR@l
234         mtspr   DBCR0,r0
235 #endif
236
237 #ifdef CONFIG_MPC8569
238 #define CONFIG_SYS_LBC_ADDR (CONFIG_SYS_CCSRBAR_DEFAULT + 0x5000)
239 #define CONFIG_SYS_LBCR_ADDR (CONFIG_SYS_LBC_ADDR + 0xd0)
240
241         /* MPC8569 Rev.0 silcon needs to set bit 13 of LBCR to allow elBC to
242          * use address space which is more than 12bits, and it must be done in
243          * the 4K boot page. So we set this bit here.
244          */
245
246         /* create a temp mapping TLB0[0] for LBCR  */
247         lis     r6,FSL_BOOKE_MAS0(0, 0, 0)@h
248         ori     r6,r6,FSL_BOOKE_MAS0(0, 0, 0)@l
249
250         lis     r7,FSL_BOOKE_MAS1(1, 0, 0, 0, BOOKE_PAGESZ_4K)@h
251         ori     r7,r7,FSL_BOOKE_MAS1(1, 0, 0, 0, BOOKE_PAGESZ_4K)@l
252
253         lis     r8,FSL_BOOKE_MAS2(CONFIG_SYS_LBC_ADDR, MAS2_I|MAS2_G)@h
254         ori     r8,r8,FSL_BOOKE_MAS2(CONFIG_SYS_LBC_ADDR, MAS2_I|MAS2_G)@l
255
256         lis     r9,FSL_BOOKE_MAS3(CONFIG_SYS_LBC_ADDR, 0,
257                                                 (MAS3_SX|MAS3_SW|MAS3_SR))@h
258         ori     r9,r9,FSL_BOOKE_MAS3(CONFIG_SYS_LBC_ADDR, 0,
259                                                 (MAS3_SX|MAS3_SW|MAS3_SR))@l
260
261         mtspr   MAS0,r6
262         mtspr   MAS1,r7
263         mtspr   MAS2,r8
264         mtspr   MAS3,r9
265         isync
266         msync
267         tlbwe
268
269         /* Set LBCR register */
270         lis     r4,CONFIG_SYS_LBCR_ADDR@h
271         ori     r4,r4,CONFIG_SYS_LBCR_ADDR@l
272
273         lis     r5,CONFIG_SYS_LBC_LBCR@h
274         ori     r5,r5,CONFIG_SYS_LBC_LBCR@l
275         stw     r5,0(r4)
276         isync
277
278         /* invalidate this temp TLB */
279         lis     r4,CONFIG_SYS_LBC_ADDR@h
280         ori     r4,r4,CONFIG_SYS_LBC_ADDR@l
281         tlbivax 0,r4
282         isync
283
284 #endif /* CONFIG_MPC8569 */
285
286         lis     r6,FSL_BOOKE_MAS0(1, 15, 0)@h
287         ori     r6,r6,FSL_BOOKE_MAS0(1, 15, 0)@l
288
289 #ifndef CONFIG_SYS_RAMBOOT
290         /* create a temp mapping in AS=1 to the 4M boot window */
291         lis     r7,FSL_BOOKE_MAS1(1, 1, 0, 1, BOOKE_PAGESZ_4M)@h
292         ori     r7,r7,FSL_BOOKE_MAS1(1, 1, 0, 1, BOOKE_PAGESZ_4M)@l
293
294         lis     r8,FSL_BOOKE_MAS2(TEXT_BASE & 0xffc00000, (MAS2_I|MAS2_G))@h
295         ori     r8,r8,FSL_BOOKE_MAS2(TEXT_BASE & 0xffc00000, (MAS2_I|MAS2_G))@l
296
297         /* The 85xx has the default boot window 0xff800000 - 0xffffffff */
298         lis     r9,FSL_BOOKE_MAS3(0xffc00000, 0, (MAS3_SX|MAS3_SW|MAS3_SR))@h
299         ori     r9,r9,FSL_BOOKE_MAS3(0xffc00000, 0, (MAS3_SX|MAS3_SW|MAS3_SR))@l
300 #else
301         /*
302          * create a temp mapping in AS=1 to the 1M TEXT_BASE space, the main
303          * image has been relocated to TEXT_BASE on the second stage.
304          */
305         lis     r7,FSL_BOOKE_MAS1(1, 1, 0, 1, BOOKE_PAGESZ_1M)@h
306         ori     r7,r7,FSL_BOOKE_MAS1(1, 1, 0, 1, BOOKE_PAGESZ_1M)@l
307
308         lis     r8,FSL_BOOKE_MAS2(TEXT_BASE, (MAS2_I|MAS2_G))@h
309         ori     r8,r8,FSL_BOOKE_MAS2(TEXT_BASE, (MAS2_I|MAS2_G))@l
310
311         lis     r9,FSL_BOOKE_MAS3(TEXT_BASE, 0, (MAS3_SX|MAS3_SW|MAS3_SR))@h
312         ori     r9,r9,FSL_BOOKE_MAS3(TEXT_BASE, 0, (MAS3_SX|MAS3_SW|MAS3_SR))@l
313 #endif
314
315         mtspr   MAS0,r6
316         mtspr   MAS1,r7
317         mtspr   MAS2,r8
318         mtspr   MAS3,r9
319         isync
320         msync
321         tlbwe
322
323         /* create a temp mapping in AS=1 to the stack */
324         lis     r6,FSL_BOOKE_MAS0(1, 14, 0)@h
325         ori     r6,r6,FSL_BOOKE_MAS0(1, 14, 0)@l
326
327         lis     r7,FSL_BOOKE_MAS1(1, 1, 0, 1, BOOKE_PAGESZ_16K)@h
328         ori     r7,r7,FSL_BOOKE_MAS1(1, 1, 0, 1, BOOKE_PAGESZ_16K)@l
329
330         lis     r8,FSL_BOOKE_MAS2(CONFIG_SYS_INIT_RAM_ADDR, 0)@h
331         ori     r8,r8,FSL_BOOKE_MAS2(CONFIG_SYS_INIT_RAM_ADDR, 0)@l
332
333         lis     r9,FSL_BOOKE_MAS3(CONFIG_SYS_INIT_RAM_ADDR, 0, (MAS3_SX|MAS3_SW|MAS3_SR))@h
334         ori     r9,r9,FSL_BOOKE_MAS3(CONFIG_SYS_INIT_RAM_ADDR, 0, (MAS3_SX|MAS3_SW|MAS3_SR))@l
335
336         mtspr   MAS0,r6
337         mtspr   MAS1,r7
338         mtspr   MAS2,r8
339         mtspr   MAS3,r9
340         isync
341         msync
342         tlbwe
343
344         lis     r6,MSR_IS|MSR_DS@h
345         ori     r6,r6,MSR_IS|MSR_DS@l
346         lis     r7,switch_as@h
347         ori     r7,r7,switch_as@l
348
349         mtspr   SPRN_SRR0,r7
350         mtspr   SPRN_SRR1,r6
351         rfi
352
353 switch_as:
354 /* L1 DCache is used for initial RAM */
355
356         /* Allocate Initial RAM in data cache.
357          */
358         lis     r3,CONFIG_SYS_INIT_RAM_ADDR@h
359         ori     r3,r3,CONFIG_SYS_INIT_RAM_ADDR@l
360         mfspr   r2, L1CFG0
361         andi.   r2, r2, 0x1ff
362         /* cache size * 1024 / (2 * L1 line size) */
363         slwi    r2, r2, (10 - 1 - L1_CACHE_SHIFT)
364         mtctr   r2
365         li      r0,0
366 1:
367         dcbz    r0,r3
368         dcbtls  0,r0,r3
369         addi    r3,r3,CONFIG_SYS_CACHELINE_SIZE
370         bdnz    1b
371
372         /* Jump out the last 4K page and continue to 'normal' start */
373 #ifdef CONFIG_SYS_RAMBOOT
374         b       _start_cont
375 #else
376         /* Calculate absolute address in FLASH and jump there           */
377         /*--------------------------------------------------------------*/
378         lis     r3,CONFIG_SYS_MONITOR_BASE@h
379         ori     r3,r3,CONFIG_SYS_MONITOR_BASE@l
380         addi    r3,r3,_start_cont - _start + _START_OFFSET
381         mtlr    r3
382         blr
383 #endif
384
385         .text
386         .globl  _start
387 _start:
388         .long   0x27051956              /* U-BOOT Magic Number */
389         .globl  version_string
390 version_string:
391         .ascii U_BOOT_VERSION
392         .ascii " (", U_BOOT_DATE, " - ", U_BOOT_TIME, ")"
393         .ascii CONFIG_IDENT_STRING, "\0"
394
395         .align  4
396         .globl  _start_cont
397 _start_cont:
398         /* Setup the stack in initial RAM,could be L2-as-SRAM or L1 dcache*/
399         lis     r1,CONFIG_SYS_INIT_RAM_ADDR@h
400         ori     r1,r1,CONFIG_SYS_INIT_SP_OFFSET@l
401
402         li      r0,0
403         stwu    r0,-4(r1)
404         stwu    r0,-4(r1)               /* Terminate call chain */
405
406         stwu    r1,-8(r1)               /* Save back chain and move SP */
407         lis     r0,RESET_VECTOR@h       /* Address of reset vector */
408         ori     r0,r0,RESET_VECTOR@l
409         stwu    r1,-8(r1)               /* Save back chain and move SP */
410         stw     r0,+12(r1)              /* Save return addr (underflow vect) */
411
412         GET_GOT
413         bl      cpu_init_early_f
414
415         /* switch back to AS = 0 */
416         lis     r3,(MSR_CE|MSR_ME|MSR_DE)@h
417         ori     r3,r3,(MSR_CE|MSR_ME|MSR_DE)@l
418         mtmsr   r3
419         isync
420
421         bl      cpu_init_f
422         bl      board_init_f
423         isync
424
425 #ifndef CONFIG_NAND_SPL
426         . = EXC_OFF_SYS_RESET
427         .globl  _start_of_vectors
428 _start_of_vectors:
429
430 /* Critical input. */
431         CRIT_EXCEPTION(0x0100, CriticalInput, CritcalInputException)
432
433 /* Machine check */
434         MCK_EXCEPTION(0x200, MachineCheck, MachineCheckException)
435
436 /* Data Storage exception. */
437         STD_EXCEPTION(0x0300, DataStorage, UnknownException)
438
439 /* Instruction Storage exception. */
440         STD_EXCEPTION(0x0400, InstStorage, UnknownException)
441
442 /* External Interrupt exception. */
443         STD_EXCEPTION(0x0500, ExtInterrupt, ExtIntException)
444
445 /* Alignment exception. */
446         . = 0x0600
447 Alignment:
448         EXCEPTION_PROLOG(SRR0, SRR1)
449         mfspr   r4,DAR
450         stw     r4,_DAR(r21)
451         mfspr   r5,DSISR
452         stw     r5,_DSISR(r21)
453         addi    r3,r1,STACK_FRAME_OVERHEAD
454         EXC_XFER_TEMPLATE(Alignment, AlignmentException, MSR_KERNEL, COPY_EE)
455
456 /* Program check exception */
457         . = 0x0700
458 ProgramCheck:
459         EXCEPTION_PROLOG(SRR0, SRR1)
460         addi    r3,r1,STACK_FRAME_OVERHEAD
461         EXC_XFER_TEMPLATE(ProgramCheck, ProgramCheckException,
462                 MSR_KERNEL, COPY_EE)
463
464         /* No FPU on MPC85xx.  This exception is not supposed to happen.
465         */
466         STD_EXCEPTION(0x0800, FPUnavailable, UnknownException)
467
468         . = 0x0900
469 /*
470  * r0 - SYSCALL number
471  * r3-... arguments
472  */
473 SystemCall:
474         addis   r11,r0,0        /* get functions table addr */
475         ori     r11,r11,0       /* Note: this code is patched in trap_init */
476         addis   r12,r0,0        /* get number of functions */
477         ori     r12,r12,0
478
479         cmplw   0,r0,r12
480         bge     1f
481
482         rlwinm  r0,r0,2,0,31    /* fn_addr = fn_tbl[r0] */
483         add     r11,r11,r0
484         lwz     r11,0(r11)
485
486         li      r20,0xd00-4     /* Get stack pointer */
487         lwz     r12,0(r20)
488         subi    r12,r12,12      /* Adjust stack pointer */
489         li      r0,0xc00+_end_back-SystemCall
490         cmplw   0,r0,r12        /* Check stack overflow */
491         bgt     1f
492         stw     r12,0(r20)
493
494         mflr    r0
495         stw     r0,0(r12)
496         mfspr   r0,SRR0
497         stw     r0,4(r12)
498         mfspr   r0,SRR1
499         stw     r0,8(r12)
500
501         li      r12,0xc00+_back-SystemCall
502         mtlr    r12
503         mtspr   SRR0,r11
504
505 1:      SYNC
506         rfi
507 _back:
508
509         mfmsr   r11                     /* Disable interrupts */
510         li      r12,0
511         ori     r12,r12,MSR_EE
512         andc    r11,r11,r12
513         SYNC                            /* Some chip revs need this... */
514         mtmsr   r11
515         SYNC
516
517         li      r12,0xd00-4             /* restore regs */
518         lwz     r12,0(r12)
519
520         lwz     r11,0(r12)
521         mtlr    r11
522         lwz     r11,4(r12)
523         mtspr   SRR0,r11
524         lwz     r11,8(r12)
525         mtspr   SRR1,r11
526
527         addi    r12,r12,12              /* Adjust stack pointer */
528         li      r20,0xd00-4
529         stw     r12,0(r20)
530
531         SYNC
532         rfi
533 _end_back:
534
535         STD_EXCEPTION(0x0a00, Decrementer, timer_interrupt)
536         STD_EXCEPTION(0x0b00, IntervalTimer, UnknownException)
537         STD_EXCEPTION(0x0c00, WatchdogTimer, UnknownException)
538
539         STD_EXCEPTION(0x0d00, DataTLBError, UnknownException)
540         STD_EXCEPTION(0x0e00, InstructionTLBError, UnknownException)
541
542         CRIT_EXCEPTION(0x0f00, DebugBreakpoint, DebugException )
543
544         .globl  _end_of_vectors
545 _end_of_vectors:
546
547
548         . = . + (0x100 - ( . & 0xff ))  /* align for debug */
549
550 /*
551  * This code finishes saving the registers to the exception frame
552  * and jumps to the appropriate handler for the exception.
553  * Register r21 is pointer into trap frame, r1 has new stack pointer.
554  */
555         .globl  transfer_to_handler
556 transfer_to_handler:
557         stw     r22,_NIP(r21)
558         lis     r22,MSR_POW@h
559         andc    r23,r23,r22
560         stw     r23,_MSR(r21)
561         SAVE_GPR(7, r21)
562         SAVE_4GPRS(8, r21)
563         SAVE_8GPRS(12, r21)
564         SAVE_8GPRS(24, r21)
565
566         mflr    r23
567         andi.   r24,r23,0x3f00          /* get vector offset */
568         stw     r24,TRAP(r21)
569         li      r22,0
570         stw     r22,RESULT(r21)
571         mtspr   SPRG2,r22               /* r1 is now kernel sp */
572
573         lwz     r24,0(r23)              /* virtual address of handler */
574         lwz     r23,4(r23)              /* where to go when done */
575         mtspr   SRR0,r24
576         mtspr   SRR1,r20
577         mtlr    r23
578         SYNC
579         rfi                             /* jump to handler, enable MMU */
580
581 int_return:
582         mfmsr   r28             /* Disable interrupts */
583         li      r4,0
584         ori     r4,r4,MSR_EE
585         andc    r28,r28,r4
586         SYNC                    /* Some chip revs need this... */
587         mtmsr   r28
588         SYNC
589         lwz     r2,_CTR(r1)
590         lwz     r0,_LINK(r1)
591         mtctr   r2
592         mtlr    r0
593         lwz     r2,_XER(r1)
594         lwz     r0,_CCR(r1)
595         mtspr   XER,r2
596         mtcrf   0xFF,r0
597         REST_10GPRS(3, r1)
598         REST_10GPRS(13, r1)
599         REST_8GPRS(23, r1)
600         REST_GPR(31, r1)
601         lwz     r2,_NIP(r1)     /* Restore environment */
602         lwz     r0,_MSR(r1)
603         mtspr   SRR0,r2
604         mtspr   SRR1,r0
605         lwz     r0,GPR0(r1)
606         lwz     r2,GPR2(r1)
607         lwz     r1,GPR1(r1)
608         SYNC
609         rfi
610
611 crit_return:
612         mfmsr   r28             /* Disable interrupts */
613         li      r4,0
614         ori     r4,r4,MSR_EE
615         andc    r28,r28,r4
616         SYNC                    /* Some chip revs need this... */
617         mtmsr   r28
618         SYNC
619         lwz     r2,_CTR(r1)
620         lwz     r0,_LINK(r1)
621         mtctr   r2
622         mtlr    r0
623         lwz     r2,_XER(r1)
624         lwz     r0,_CCR(r1)
625         mtspr   XER,r2
626         mtcrf   0xFF,r0
627         REST_10GPRS(3, r1)
628         REST_10GPRS(13, r1)
629         REST_8GPRS(23, r1)
630         REST_GPR(31, r1)
631         lwz     r2,_NIP(r1)     /* Restore environment */
632         lwz     r0,_MSR(r1)
633         mtspr   SPRN_CSRR0,r2
634         mtspr   SPRN_CSRR1,r0
635         lwz     r0,GPR0(r1)
636         lwz     r2,GPR2(r1)
637         lwz     r1,GPR1(r1)
638         SYNC
639         rfci
640
641 mck_return:
642         mfmsr   r28             /* Disable interrupts */
643         li      r4,0
644         ori     r4,r4,MSR_EE
645         andc    r28,r28,r4
646         SYNC                    /* Some chip revs need this... */
647         mtmsr   r28
648         SYNC
649         lwz     r2,_CTR(r1)
650         lwz     r0,_LINK(r1)
651         mtctr   r2
652         mtlr    r0
653         lwz     r2,_XER(r1)
654         lwz     r0,_CCR(r1)
655         mtspr   XER,r2
656         mtcrf   0xFF,r0
657         REST_10GPRS(3, r1)
658         REST_10GPRS(13, r1)
659         REST_8GPRS(23, r1)
660         REST_GPR(31, r1)
661         lwz     r2,_NIP(r1)     /* Restore environment */
662         lwz     r0,_MSR(r1)
663         mtspr   SPRN_MCSRR0,r2
664         mtspr   SPRN_MCSRR1,r0
665         lwz     r0,GPR0(r1)
666         lwz     r2,GPR2(r1)
667         lwz     r1,GPR1(r1)
668         SYNC
669         rfmci
670
671 /* Cache functions.
672 */
673 .globl invalidate_icache
674 invalidate_icache:
675         mfspr   r0,L1CSR1
676         ori     r0,r0,L1CSR1_ICFI
677         msync
678         isync
679         mtspr   L1CSR1,r0
680         isync
681         blr                             /* entire I cache */
682
683 .globl invalidate_dcache
684 invalidate_dcache:
685         mfspr   r0,L1CSR0
686         ori     r0,r0,L1CSR0_DCFI
687         msync
688         isync
689         mtspr   L1CSR0,r0
690         isync
691         blr
692
693         .globl  icache_enable
694 icache_enable:
695         mflr    r8
696         bl      invalidate_icache
697         mtlr    r8
698         isync
699         mfspr   r4,L1CSR1
700         ori     r4,r4,0x0001
701         oris    r4,r4,0x0001
702         mtspr   L1CSR1,r4
703         isync
704         blr
705
706         .globl  icache_disable
707 icache_disable:
708         mfspr   r0,L1CSR1
709         lis     r3,0
710         ori     r3,r3,L1CSR1_ICE
711         andc    r0,r0,r3
712         mtspr   L1CSR1,r0
713         isync
714         blr
715
716         .globl  icache_status
717 icache_status:
718         mfspr   r3,L1CSR1
719         andi.   r3,r3,L1CSR1_ICE
720         blr
721
722         .globl  dcache_enable
723 dcache_enable:
724         mflr    r8
725         bl      invalidate_dcache
726         mtlr    r8
727         isync
728         mfspr   r0,L1CSR0
729         ori     r0,r0,0x0001
730         oris    r0,r0,0x0001
731         msync
732         isync
733         mtspr   L1CSR0,r0
734         isync
735         blr
736
737         .globl  dcache_disable
738 dcache_disable:
739         mfspr   r3,L1CSR0
740         lis     r4,0
741         ori     r4,r4,L1CSR0_DCE
742         andc    r3,r3,r4
743         mtspr   L1CSR0,r0
744         isync
745         blr
746
747         .globl  dcache_status
748 dcache_status:
749         mfspr   r3,L1CSR0
750         andi.   r3,r3,L1CSR0_DCE
751         blr
752
753         .globl get_pir
754 get_pir:
755         mfspr   r3,PIR
756         blr
757
758         .globl get_pvr
759 get_pvr:
760         mfspr   r3,PVR
761         blr
762
763         .globl get_svr
764 get_svr:
765         mfspr   r3,SVR
766         blr
767
768         .globl wr_tcr
769 wr_tcr:
770         mtspr   TCR,r3
771         blr
772
773 /*------------------------------------------------------------------------------- */
774 /* Function:     in8 */
775 /* Description:  Input 8 bits */
776 /*------------------------------------------------------------------------------- */
777         .globl  in8
778 in8:
779         lbz     r3,0x0000(r3)
780         blr
781
782 /*------------------------------------------------------------------------------- */
783 /* Function:     out8 */
784 /* Description:  Output 8 bits */
785 /*------------------------------------------------------------------------------- */
786         .globl  out8
787 out8:
788         stb     r4,0x0000(r3)
789         sync
790         blr
791
792 /*------------------------------------------------------------------------------- */
793 /* Function:     out16 */
794 /* Description:  Output 16 bits */
795 /*------------------------------------------------------------------------------- */
796         .globl  out16
797 out16:
798         sth     r4,0x0000(r3)
799         sync
800         blr
801
802 /*------------------------------------------------------------------------------- */
803 /* Function:     out16r */
804 /* Description:  Byte reverse and output 16 bits */
805 /*------------------------------------------------------------------------------- */
806         .globl  out16r
807 out16r:
808         sthbrx  r4,r0,r3
809         sync
810         blr
811
812 /*------------------------------------------------------------------------------- */
813 /* Function:     out32 */
814 /* Description:  Output 32 bits */
815 /*------------------------------------------------------------------------------- */
816         .globl  out32
817 out32:
818         stw     r4,0x0000(r3)
819         sync
820         blr
821
822 /*------------------------------------------------------------------------------- */
823 /* Function:     out32r */
824 /* Description:  Byte reverse and output 32 bits */
825 /*------------------------------------------------------------------------------- */
826         .globl  out32r
827 out32r:
828         stwbrx  r4,r0,r3
829         sync
830         blr
831
832 /*------------------------------------------------------------------------------- */
833 /* Function:     in16 */
834 /* Description:  Input 16 bits */
835 /*------------------------------------------------------------------------------- */
836         .globl  in16
837 in16:
838         lhz     r3,0x0000(r3)
839         blr
840
841 /*------------------------------------------------------------------------------- */
842 /* Function:     in16r */
843 /* Description:  Input 16 bits and byte reverse */
844 /*------------------------------------------------------------------------------- */
845         .globl  in16r
846 in16r:
847         lhbrx   r3,r0,r3
848         blr
849
850 /*------------------------------------------------------------------------------- */
851 /* Function:     in32 */
852 /* Description:  Input 32 bits */
853 /*------------------------------------------------------------------------------- */
854         .globl  in32
855 in32:
856         lwz     3,0x0000(3)
857         blr
858
859 /*------------------------------------------------------------------------------- */
860 /* Function:     in32r */
861 /* Description:  Input 32 bits and byte reverse */
862 /*------------------------------------------------------------------------------- */
863         .globl  in32r
864 in32r:
865         lwbrx   r3,r0,r3
866         blr
867 #endif  /* !CONFIG_NAND_SPL */
868
869 /*------------------------------------------------------------------------------*/
870
871 /*
872  * void write_tlb(mas0, mas1, mas2, mas3, mas7)
873  */
874         .globl  write_tlb
875 write_tlb:
876         mtspr   MAS0,r3
877         mtspr   MAS1,r4
878         mtspr   MAS2,r5
879         mtspr   MAS3,r6
880 #ifdef CONFIG_ENABLE_36BIT_PHYS
881         mtspr   MAS7,r7
882 #endif
883         li      r3,0
884 #ifdef CONFIG_SYS_BOOK3E_HV
885         mtspr   MAS8,r3
886 #endif
887         isync
888         tlbwe
889         msync
890         isync
891         blr
892
893 /*
894  * void relocate_code (addr_sp, gd, addr_moni)
895  *
896  * This "function" does not return, instead it continues in RAM
897  * after relocating the monitor code.
898  *
899  * r3 = dest
900  * r4 = src
901  * r5 = length in bytes
902  * r6 = cachelinesize
903  */
904         .globl  relocate_code
905 relocate_code:
906         mr      r1,r3           /* Set new stack pointer                */
907         mr      r9,r4           /* Save copy of Init Data pointer       */
908         mr      r10,r5          /* Save copy of Destination Address     */
909
910         GET_GOT
911         mr      r3,r5                           /* Destination Address  */
912         lis     r4,CONFIG_SYS_MONITOR_BASE@h            /* Source      Address  */
913         ori     r4,r4,CONFIG_SYS_MONITOR_BASE@l
914         lwz     r5,GOT(__init_end)
915         sub     r5,r5,r4
916         li      r6,CONFIG_SYS_CACHELINE_SIZE            /* Cache Line Size      */
917
918         /*
919          * Fix GOT pointer:
920          *
921          * New GOT-PTR = (old GOT-PTR - CONFIG_SYS_MONITOR_BASE) + Destination Address
922          *
923          * Offset:
924          */
925         sub     r15,r10,r4
926
927         /* First our own GOT */
928         add     r12,r12,r15
929         /* the the one used by the C code */
930         add     r30,r30,r15
931
932         /*
933          * Now relocate code
934          */
935
936         cmplw   cr1,r3,r4
937         addi    r0,r5,3
938         srwi.   r0,r0,2
939         beq     cr1,4f          /* In place copy is not necessary       */
940         beq     7f              /* Protect against 0 count              */
941         mtctr   r0
942         bge     cr1,2f
943
944         la      r8,-4(r4)
945         la      r7,-4(r3)
946 1:      lwzu    r0,4(r8)
947         stwu    r0,4(r7)
948         bdnz    1b
949         b       4f
950
951 2:      slwi    r0,r0,2
952         add     r8,r4,r0
953         add     r7,r3,r0
954 3:      lwzu    r0,-4(r8)
955         stwu    r0,-4(r7)
956         bdnz    3b
957
958 /*
959  * Now flush the cache: note that we must start from a cache aligned
960  * address. Otherwise we might miss one cache line.
961  */
962 4:      cmpwi   r6,0
963         add     r5,r3,r5
964         beq     7f              /* Always flush prefetch queue in any case */
965         subi    r0,r6,1
966         andc    r3,r3,r0
967         mr      r4,r3
968 5:      dcbst   0,r4
969         add     r4,r4,r6
970         cmplw   r4,r5
971         blt     5b
972         sync                    /* Wait for all dcbst to complete on bus */
973         mr      r4,r3
974 6:      icbi    0,r4
975         add     r4,r4,r6
976         cmplw   r4,r5
977         blt     6b
978 7:      sync                    /* Wait for all icbi to complete on bus */
979         isync
980
981         /*
982          * Re-point the IVPR at RAM
983          */
984         mtspr   IVPR,r10
985
986 /*
987  * We are done. Do not return, instead branch to second part of board
988  * initialization, now running from RAM.
989  */
990
991         addi    r0,r10,in_ram - _start + _START_OFFSET
992         mtlr    r0
993         blr                             /* NEVER RETURNS! */
994         .globl  in_ram
995 in_ram:
996
997         /*
998          * Relocation Function, r12 point to got2+0x8000
999          *
1000          * Adjust got2 pointers, no need to check for 0, this code
1001          * already puts a few entries in the table.
1002          */
1003         li      r0,__got2_entries@sectoff@l
1004         la      r3,GOT(_GOT2_TABLE_)
1005         lwz     r11,GOT(_GOT2_TABLE_)
1006         mtctr   r0
1007         sub     r11,r3,r11
1008         addi    r3,r3,-4
1009 1:      lwzu    r0,4(r3)
1010         cmpwi   r0,0
1011         beq-    2f
1012         add     r0,r0,r11
1013         stw     r0,0(r3)
1014 2:      bdnz    1b
1015
1016         /*
1017          * Now adjust the fixups and the pointers to the fixups
1018          * in case we need to move ourselves again.
1019          */
1020         li      r0,__fixup_entries@sectoff@l
1021         lwz     r3,GOT(_FIXUP_TABLE_)
1022         cmpwi   r0,0
1023         mtctr   r0
1024         addi    r3,r3,-4
1025         beq     4f
1026 3:      lwzu    r4,4(r3)
1027         lwzux   r0,r4,r11
1028         add     r0,r0,r11
1029         stw     r10,0(r3)
1030         stw     r0,0(r4)
1031         bdnz    3b
1032 4:
1033 clear_bss:
1034         /*
1035          * Now clear BSS segment
1036          */
1037         lwz     r3,GOT(__bss_start)
1038         lwz     r4,GOT(_end)
1039
1040         cmplw   0,r3,r4
1041         beq     6f
1042
1043         li      r0,0
1044 5:
1045         stw     r0,0(r3)
1046         addi    r3,r3,4
1047         cmplw   0,r3,r4
1048         bne     5b
1049 6:
1050
1051         mr      r3,r9           /* Init Data pointer            */
1052         mr      r4,r10          /* Destination Address          */
1053         bl      board_init_r
1054
1055 #ifndef CONFIG_NAND_SPL
1056         /*
1057          * Copy exception vector code to low memory
1058          *
1059          * r3: dest_addr
1060          * r7: source address, r8: end address, r9: target address
1061          */
1062         .globl  trap_init
1063 trap_init:
1064         mflr    r4                      /* save link register           */
1065         GET_GOT
1066         lwz     r7,GOT(_start_of_vectors)
1067         lwz     r8,GOT(_end_of_vectors)
1068
1069         li      r9,0x100                /* reset vector always at 0x100 */
1070
1071         cmplw   0,r7,r8
1072         bgelr                           /* return if r7>=r8 - just in case */
1073 1:
1074         lwz     r0,0(r7)
1075         stw     r0,0(r9)
1076         addi    r7,r7,4
1077         addi    r9,r9,4
1078         cmplw   0,r7,r8
1079         bne     1b
1080
1081         /*
1082          * relocate `hdlr' and `int_return' entries
1083          */
1084         li      r7,.L_CriticalInput - _start + _START_OFFSET
1085         bl      trap_reloc
1086         li      r7,.L_MachineCheck - _start + _START_OFFSET
1087         bl      trap_reloc
1088         li      r7,.L_DataStorage - _start + _START_OFFSET
1089         bl      trap_reloc
1090         li      r7,.L_InstStorage - _start + _START_OFFSET
1091         bl      trap_reloc
1092         li      r7,.L_ExtInterrupt - _start + _START_OFFSET
1093         bl      trap_reloc
1094         li      r7,.L_Alignment - _start + _START_OFFSET
1095         bl      trap_reloc
1096         li      r7,.L_ProgramCheck - _start + _START_OFFSET
1097         bl      trap_reloc
1098         li      r7,.L_FPUnavailable - _start + _START_OFFSET
1099         bl      trap_reloc
1100         li      r7,.L_Decrementer - _start + _START_OFFSET
1101         bl      trap_reloc
1102         li      r7,.L_IntervalTimer - _start + _START_OFFSET
1103         li      r8,_end_of_vectors - _start + _START_OFFSET
1104 2:
1105         bl      trap_reloc
1106         addi    r7,r7,0x100             /* next exception vector        */
1107         cmplw   0,r7,r8
1108         blt     2b
1109
1110         lis     r7,0x0
1111         mtspr   IVPR,r7
1112
1113         mtlr    r4                      /* restore link register        */
1114         blr
1115
1116 .globl unlock_ram_in_cache
1117 unlock_ram_in_cache:
1118         /* invalidate the INIT_RAM section */
1119         lis     r3,(CONFIG_SYS_INIT_RAM_ADDR & ~(CONFIG_SYS_CACHELINE_SIZE-1))@h
1120         ori     r3,r3,(CONFIG_SYS_INIT_RAM_ADDR & ~(CONFIG_SYS_CACHELINE_SIZE-1))@l
1121         mfspr   r4,L1CFG0
1122         andi.   r4,r4,0x1ff
1123         slwi    r4,r4,(10 - 1 - L1_CACHE_SHIFT)
1124         mtctr   r4
1125 1:      dcbi    r0,r3
1126         addi    r3,r3,CONFIG_SYS_CACHELINE_SIZE
1127         bdnz    1b
1128         sync
1129
1130         /* Invalidate the TLB entries for the cache */
1131         lis     r3,CONFIG_SYS_INIT_RAM_ADDR@h
1132         ori     r3,r3,CONFIG_SYS_INIT_RAM_ADDR@l
1133         tlbivax 0,r3
1134         addi    r3,r3,0x1000
1135         tlbivax 0,r3
1136         addi    r3,r3,0x1000
1137         tlbivax 0,r3
1138         addi    r3,r3,0x1000
1139         tlbivax 0,r3
1140         isync
1141         blr
1142
1143 .globl flush_dcache
1144 flush_dcache:
1145         mfspr   r3,SPRN_L1CFG0
1146
1147         rlwinm  r5,r3,9,3       /* Extract cache block size */
1148         twlgti  r5,1            /* Only 32 and 64 byte cache blocks
1149                                  * are currently defined.
1150                                  */
1151         li      r4,32
1152         subfic  r6,r5,2         /* r6 = log2(1KiB / cache block size) -
1153                                  *      log2(number of ways)
1154                                  */
1155         slw     r5,r4,r5        /* r5 = cache block size */
1156
1157         rlwinm  r7,r3,0,0xff    /* Extract number of KiB in the cache */
1158         mulli   r7,r7,13        /* An 8-way cache will require 13
1159                                  * loads per set.
1160                                  */
1161         slw     r7,r7,r6
1162
1163         /* save off HID0 and set DCFA */
1164         mfspr   r8,SPRN_HID0
1165         ori     r9,r8,HID0_DCFA@l
1166         mtspr   SPRN_HID0,r9
1167         isync
1168
1169         lis     r4,0
1170         mtctr   r7
1171
1172 1:      lwz     r3,0(r4)        /* Load... */
1173         add     r4,r4,r5
1174         bdnz    1b
1175
1176         msync
1177         lis     r4,0
1178         mtctr   r7
1179
1180 1:      dcbf    0,r4            /* ...and flush. */
1181         add     r4,r4,r5
1182         bdnz    1b
1183
1184         /* restore HID0 */
1185         mtspr   SPRN_HID0,r8
1186         isync
1187
1188         blr
1189
1190 .globl setup_ivors
1191 setup_ivors:
1192
1193 #include "fixed_ivor.S"
1194         blr
1195 #endif /* !CONFIG_NAND_SPL */