]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/powerpc/cpu/mpc85xx/start.S
mtd/nand: docg4: fix compiler warnings
[karo-tx-uboot.git] / arch / powerpc / cpu / mpc85xx / start.S
1 /*
2  * Copyright 2004, 2007-2012 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 <asm-offsets.h>
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 #undef  MSR_KERNEL
45 #define MSR_KERNEL ( MSR_ME )   /* Machine Check */
46
47 #if defined(CONFIG_NAND_SPL) || \
48         (defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_INIT_MINIMAL))
49 #define MINIMAL_SPL
50 #endif
51
52 #if !defined(CONFIG_SPL) && !defined(CONFIG_SYS_RAMBOOT) && !defined(CONFIG_SECURE_BOOT)
53 #define NOR_BOOT
54 #endif
55
56 /*
57  * Set up GOT: Global Offset Table
58  *
59  * Use r12 to access the GOT
60  */
61         START_GOT
62         GOT_ENTRY(_GOT2_TABLE_)
63         GOT_ENTRY(_FIXUP_TABLE_)
64
65 #ifndef MINIMAL_SPL
66         GOT_ENTRY(_start)
67         GOT_ENTRY(_start_of_vectors)
68         GOT_ENTRY(_end_of_vectors)
69         GOT_ENTRY(transfer_to_handler)
70 #endif
71
72         GOT_ENTRY(__init_end)
73         GOT_ENTRY(__bss_end)
74         GOT_ENTRY(__bss_start)
75         END_GOT
76
77 /*
78  * e500 Startup -- after reset only the last 4KB of the effective
79  * address space is mapped in the MMU L2 TLB1 Entry0. The .bootpg
80  * section is located at THIS LAST page and basically does three
81  * things: clear some registers, set up exception tables and
82  * add more TLB entries for 'larger spaces'(e.g. the boot rom) to
83  * continue the boot procedure.
84
85  * Once the boot rom is mapped by TLB entries we can proceed
86  * with normal startup.
87  *
88  */
89
90         .section .bootpg,"ax"
91         .globl _start_e500
92
93 _start_e500:
94 /* Enable debug exception */
95         li      r1,MSR_DE
96         mtmsr   r1
97
98 #ifdef CONFIG_SYS_FSL_ERRATUM_A004510
99         mfspr   r3,SPRN_SVR
100         rlwinm  r3,r3,0,0xff
101         li      r4,CONFIG_SYS_FSL_ERRATUM_A004510_SVR_REV
102         cmpw    r3,r4
103         beq     1f
104
105 #ifdef CONFIG_SYS_FSL_ERRATUM_A004510_SVR_REV2
106         li      r4,CONFIG_SYS_FSL_ERRATUM_A004510_SVR_REV2
107         cmpw    r3,r4
108         beq     1f
109 #endif
110
111         /* Not a supported revision affected by erratum */
112         li      r27,0
113         b       2f
114
115 1:      li      r27,1   /* Remember for later that we have the erratum */
116         /* Erratum says set bits 55:60 to 001001 */
117         msync
118         isync
119         mfspr   r3,SPRN_HDBCR0
120         li      r4,0x48
121         rlwimi  r3,r4,0,0x1f8
122         mtspr   SPRN_HDBCR0,r3
123         isync
124 2:
125 #endif
126
127 #if defined(CONFIG_SECURE_BOOT) && defined(CONFIG_E500MC)
128         /* ISBC uses L2 as stack.
129          * Disable L2 cache here so that u-boot can enable it later
130          * as part of it's normal flow
131         */
132
133         /* Check if L2 is enabled */
134         mfspr   r3, SPRN_L2CSR0
135         lis     r2, L2CSR0_L2E@h
136         ori     r2, r2, L2CSR0_L2E@l
137         and.    r4, r3, r2
138         beq     l2_disabled
139
140         mfspr r3, SPRN_L2CSR0
141         /* Flush L2 cache */
142         lis     r2,(L2CSR0_L2FL)@h
143         ori     r2, r2, (L2CSR0_L2FL)@l
144         or      r3, r2, r3
145         sync
146         isync
147         mtspr   SPRN_L2CSR0,r3
148         isync
149 1:
150         mfspr r3, SPRN_L2CSR0
151         and. r1, r3, r2
152         bne 1b
153
154         mfspr r3, SPRN_L2CSR0
155         lis r2, L2CSR0_L2E@h
156         ori r2, r2, L2CSR0_L2E@l
157         andc r4, r3, r2
158         sync
159         isync
160         mtspr SPRN_L2CSR0,r4
161         isync
162
163 l2_disabled:
164 #endif
165
166 /* clear registers/arrays not reset by hardware */
167
168         /* L1 */
169         li      r0,2
170         mtspr   L1CSR0,r0       /* invalidate d-cache */
171         mtspr   L1CSR1,r0       /* invalidate i-cache */
172
173         mfspr   r1,DBSR
174         mtspr   DBSR,r1         /* Clear all valid bits */
175
176
177         .macro  create_tlb1_entry esel ts tsize epn wimg rpn perm phy_high scratch
178         lis     \scratch, FSL_BOOKE_MAS0(1, \esel, 0)@h
179         ori     \scratch, \scratch, FSL_BOOKE_MAS0(1, \esel, 0)@l
180         mtspr   MAS0, \scratch
181         lis     \scratch, FSL_BOOKE_MAS1(1, 1, 0, \ts, \tsize)@h
182         ori     \scratch, \scratch, FSL_BOOKE_MAS1(1, 1, 0, \ts, \tsize)@l
183         mtspr   MAS1, \scratch
184         lis     \scratch, FSL_BOOKE_MAS2(\epn, \wimg)@h
185         ori     \scratch, \scratch, FSL_BOOKE_MAS2(\epn, \wimg)@l
186         mtspr   MAS2, \scratch
187         lis     \scratch, FSL_BOOKE_MAS3(\rpn, 0, \perm)@h
188         ori     \scratch, \scratch, FSL_BOOKE_MAS3(\rpn, 0, \perm)@l
189         mtspr   MAS3, \scratch
190         lis     \scratch, \phy_high@h
191         ori     \scratch, \scratch, \phy_high@l
192         mtspr   MAS7, \scratch
193         isync
194         msync
195         tlbwe
196         isync
197         .endm
198
199         .macro  create_tlb0_entry esel ts tsize epn wimg rpn perm phy_high scratch
200         lis     \scratch, FSL_BOOKE_MAS0(0, \esel, 0)@h
201         ori     \scratch, \scratch, FSL_BOOKE_MAS0(0, \esel, 0)@l
202         mtspr   MAS0, \scratch
203         lis     \scratch, FSL_BOOKE_MAS1(1, 0, 0, \ts, \tsize)@h
204         ori     \scratch, \scratch, FSL_BOOKE_MAS1(1, 0, 0, \ts, \tsize)@l
205         mtspr   MAS1, \scratch
206         lis     \scratch, FSL_BOOKE_MAS2(\epn, \wimg)@h
207         ori     \scratch, \scratch, FSL_BOOKE_MAS2(\epn, \wimg)@l
208         mtspr   MAS2, \scratch
209         lis     \scratch, FSL_BOOKE_MAS3(\rpn, 0, \perm)@h
210         ori     \scratch, \scratch, FSL_BOOKE_MAS3(\rpn, 0, \perm)@l
211         mtspr   MAS3, \scratch
212         lis     \scratch, \phy_high@h
213         ori     \scratch, \scratch, \phy_high@l
214         mtspr   MAS7, \scratch
215         isync
216         msync
217         tlbwe
218         isync
219         .endm
220
221         .macro  delete_tlb1_entry esel scratch
222         lis     \scratch, FSL_BOOKE_MAS0(1, \esel, 0)@h
223         ori     \scratch, \scratch, FSL_BOOKE_MAS0(1, \esel, 0)@l
224         mtspr   MAS0, \scratch
225         li      \scratch, 0
226         mtspr   MAS1, \scratch
227         isync
228         msync
229         tlbwe
230         isync
231         .endm
232
233         .macro  delete_tlb0_entry esel epn wimg scratch
234         lis     \scratch, FSL_BOOKE_MAS0(0, \esel, 0)@h
235         ori     \scratch, \scratch, FSL_BOOKE_MAS0(0, \esel, 0)@l
236         mtspr   MAS0, \scratch
237         li      \scratch, 0
238         mtspr   MAS1, \scratch
239         lis     \scratch, FSL_BOOKE_MAS2(\epn, \wimg)@h
240         ori     \scratch, \scratch, FSL_BOOKE_MAS2(\epn, \wimg)@l
241         mtspr   MAS2, \scratch
242         isync
243         msync
244         tlbwe
245         isync
246         .endm
247
248 /* Interrupt vectors do not fit in minimal SPL. */
249 #if !defined(MINIMAL_SPL)
250         /* Setup interrupt vectors */
251         lis     r1,CONFIG_SYS_MONITOR_BASE@h
252         mtspr   IVPR,r1
253
254         lis     r3,(CONFIG_SYS_MONITOR_BASE & 0xffff)@h
255         ori     r3,r3,(CONFIG_SYS_MONITOR_BASE & 0xffff)@l
256
257         addi    r4,r3,CriticalInput - _start + _START_OFFSET
258         mtspr   IVOR0,r4        /* 0: Critical input */
259         addi    r4,r3,MachineCheck - _start + _START_OFFSET
260         mtspr   IVOR1,r4        /* 1: Machine check */
261         addi    r4,r3,DataStorage - _start + _START_OFFSET
262         mtspr   IVOR2,r4        /* 2: Data storage */
263         addi    r4,r3,InstStorage - _start + _START_OFFSET
264         mtspr   IVOR3,r4        /* 3: Instruction storage */
265         addi    r4,r3,ExtInterrupt - _start + _START_OFFSET
266         mtspr   IVOR4,r4        /* 4: External interrupt */
267         addi    r4,r3,Alignment - _start + _START_OFFSET
268         mtspr   IVOR5,r4        /* 5: Alignment */
269         addi    r4,r3,ProgramCheck - _start + _START_OFFSET
270         mtspr   IVOR6,r4        /* 6: Program check */
271         addi    r4,r3,FPUnavailable - _start + _START_OFFSET
272         mtspr   IVOR7,r4        /* 7: floating point unavailable */
273         addi    r4,r3,SystemCall - _start + _START_OFFSET
274         mtspr   IVOR8,r4        /* 8: System call */
275         /* 9: Auxiliary processor unavailable(unsupported) */
276         addi    r4,r3,Decrementer - _start + _START_OFFSET
277         mtspr   IVOR10,r4       /* 10: Decrementer */
278         addi    r4,r3,IntervalTimer - _start + _START_OFFSET
279         mtspr   IVOR11,r4       /* 11: Interval timer */
280         addi    r4,r3,WatchdogTimer - _start + _START_OFFSET
281         mtspr   IVOR12,r4       /* 12: Watchdog timer */
282         addi    r4,r3,DataTLBError - _start + _START_OFFSET
283         mtspr   IVOR13,r4       /* 13: Data TLB error */
284         addi    r4,r3,InstructionTLBError - _start + _START_OFFSET
285         mtspr   IVOR14,r4       /* 14: Instruction TLB error */
286         addi    r4,r3,DebugBreakpoint - _start + _START_OFFSET
287         mtspr   IVOR15,r4       /* 15: Debug */
288 #endif
289
290         /* Clear and set up some registers. */
291         li      r0,0x0000
292         lis     r1,0xffff
293         mtspr   DEC,r0                  /* prevent dec exceptions */
294         mttbl   r0                      /* prevent fit & wdt exceptions */
295         mttbu   r0
296         mtspr   TSR,r1                  /* clear all timer exception status */
297         mtspr   TCR,r0                  /* disable all */
298         mtspr   ESR,r0                  /* clear exception syndrome register */
299         mtspr   MCSR,r0                 /* machine check syndrome register */
300         mtxer   r0                      /* clear integer exception register */
301
302 #ifdef CONFIG_SYS_BOOK3E_HV
303         mtspr   MAS8,r0                 /* make sure MAS8 is clear */
304 #endif
305
306         /* Enable Time Base and Select Time Base Clock */
307         lis     r0,HID0_EMCP@h          /* Enable machine check */
308 #if defined(CONFIG_ENABLE_36BIT_PHYS)
309         ori     r0,r0,HID0_ENMAS7@l     /* Enable MAS7 */
310 #endif
311 #ifndef CONFIG_E500MC
312         ori     r0,r0,HID0_TBEN@l       /* Enable Timebase */
313 #endif
314         mtspr   HID0,r0
315
316 #ifndef CONFIG_E500MC
317         li      r0,(HID1_ASTME|HID1_ABE)@l      /* Addr streaming & broadcast */
318         mfspr   r3,PVR
319         andi.   r3,r3, 0xff
320         cmpwi   r3,0x50@l       /* if we are rev 5.0 or greater set MBDD */
321         blt 1f
322         /* Set MBDD bit also */
323         ori r0, r0, HID1_MBDD@l
324 1:
325         mtspr   HID1,r0
326 #endif
327
328 #ifdef CONFIG_SYS_FSL_ERRATUM_CPU_A003999
329         mfspr   r3,SPRN_HDBCR1
330         oris    r3,r3,0x0100
331         mtspr   SPRN_HDBCR1,r3
332 #endif
333
334         /* Enable Branch Prediction */
335 #if defined(CONFIG_BTB)
336         lis     r0,BUCSR_ENABLE@h
337         ori     r0,r0,BUCSR_ENABLE@l
338         mtspr   SPRN_BUCSR,r0
339 #endif
340
341 #if defined(CONFIG_SYS_INIT_DBCR)
342         lis     r1,0xffff
343         ori     r1,r1,0xffff
344         mtspr   DBSR,r1                 /* Clear all status bits */
345         lis     r0,CONFIG_SYS_INIT_DBCR@h       /* DBCR0[IDM] must be set */
346         ori     r0,r0,CONFIG_SYS_INIT_DBCR@l
347         mtspr   DBCR0,r0
348 #endif
349
350 #ifdef CONFIG_MPC8569
351 #define CONFIG_SYS_LBC_ADDR (CONFIG_SYS_CCSRBAR_DEFAULT + 0x5000)
352 #define CONFIG_SYS_LBCR_ADDR (CONFIG_SYS_LBC_ADDR + 0xd0)
353
354         /* MPC8569 Rev.0 silcon needs to set bit 13 of LBCR to allow elBC to
355          * use address space which is more than 12bits, and it must be done in
356          * the 4K boot page. So we set this bit here.
357          */
358
359         /* create a temp mapping TLB0[0] for LBCR  */
360         create_tlb0_entry 0, \
361                 0, BOOKE_PAGESZ_4K, \
362                 CONFIG_SYS_LBC_ADDR, MAS2_I|MAS2_G, \
363                 CONFIG_SYS_LBC_ADDR, MAS3_SW|MAS3_SR, \
364                 0, r6
365
366         /* Set LBCR register */
367         lis     r4,CONFIG_SYS_LBCR_ADDR@h
368         ori     r4,r4,CONFIG_SYS_LBCR_ADDR@l
369
370         lis     r5,CONFIG_SYS_LBC_LBCR@h
371         ori     r5,r5,CONFIG_SYS_LBC_LBCR@l
372         stw     r5,0(r4)
373         isync
374
375         /* invalidate this temp TLB */
376         lis     r4,CONFIG_SYS_LBC_ADDR@h
377         ori     r4,r4,CONFIG_SYS_LBC_ADDR@l
378         tlbivax 0,r4
379         isync
380
381 #endif /* CONFIG_MPC8569 */
382
383 /*
384  * Search for the TLB that covers the code we're executing, and shrink it
385  * so that it covers only this 4K page.  That will ensure that any other
386  * TLB we create won't interfere with it.  We assume that the TLB exists,
387  * which is why we don't check the Valid bit of MAS1.  We also assume
388  * it is in TLB1.
389  *
390  * This is necessary, for example, when booting from the on-chip ROM,
391  * which (oddly) creates a single 4GB TLB that covers CCSR and DDR.
392  */
393         bl      nexti           /* Find our address */
394 nexti:  mflr    r1              /* R1 = our PC */
395         li      r2, 0
396         mtspr   MAS6, r2        /* Assume the current PID and AS are 0 */
397         isync
398         msync
399         tlbsx   0, r1           /* This must succeed */
400
401         mfspr   r14, MAS0       /* Save ESEL for later */
402         rlwinm  r14, r14, 16, 0xfff
403
404         /* Set the size of the TLB to 4KB */
405         mfspr   r3, MAS1
406         li      r2, 0xF80
407         andc    r3, r3, r2      /* Clear the TSIZE bits */
408         ori     r3, r3, MAS1_TSIZE(BOOKE_PAGESZ_4K)@l
409         oris    r3, r3, MAS1_IPROT@h
410         mtspr   MAS1, r3
411
412         /*
413          * Set the base address of the TLB to our PC.  We assume that
414          * virtual == physical.  We also assume that MAS2_EPN == MAS3_RPN.
415          */
416         lis     r3, MAS2_EPN@h
417         ori     r3, r3, MAS2_EPN@l      /* R3 = MAS2_EPN */
418
419         and     r1, r1, r3      /* Our PC, rounded down to the nearest page */
420
421         mfspr   r2, MAS2
422         andc    r2, r2, r3
423         or      r2, r2, r1
424 #ifdef CONFIG_SYS_FSL_ERRATUM_A004510
425         cmpwi   r27,0
426         beq     1f
427         andi.   r15, r2, MAS2_I|MAS2_G /* save the old I/G for later */
428         rlwinm  r2, r2, 0, ~MAS2_I
429         ori     r2, r2, MAS2_G
430 1:
431 #endif
432         mtspr   MAS2, r2        /* Set the EPN to our PC base address */
433
434         mfspr   r2, MAS3
435         andc    r2, r2, r3
436         or      r2, r2, r1
437         mtspr   MAS3, r2        /* Set the RPN to our PC base address */
438
439         isync
440         msync
441         tlbwe
442
443 /*
444  * Clear out any other TLB entries that may exist, to avoid conflicts.
445  * Our TLB entry is in r14.
446  */
447         li      r0, TLBIVAX_ALL | TLBIVAX_TLB0
448         tlbivax 0, r0
449         tlbsync
450
451         mfspr   r4, SPRN_TLB1CFG
452         rlwinm  r4, r4, 0, TLBnCFG_NENTRY_MASK
453
454         li      r3, 0
455         mtspr   MAS1, r3
456 1:      cmpw    r3, r14
457         rlwinm  r5, r3, 16, MAS0_ESEL_MSK
458         addi    r3, r3, 1
459         beq     2f              /* skip the entry we're executing from */
460
461         oris    r5, r5, MAS0_TLBSEL(1)@h
462         mtspr   MAS0, r5
463
464         isync
465         tlbwe
466         isync
467         msync
468
469 2:      cmpw    r3, r4
470         blt     1b
471
472 #if defined(CONFIG_SYS_PPC_E500_DEBUG_TLB) && !defined(MINIMAL_SPL)
473 /*
474  * TLB entry for debuggging in AS1
475  * Create temporary TLB entry in AS0 to handle debug exception
476  * As on debug exception MSR is cleared i.e. Address space is changed
477  * to 0. A TLB entry (in AS0) is required to handle debug exception generated
478  * in AS1.
479  */
480
481 #ifdef NOR_BOOT
482 /*
483  * TLB entry is created for IVPR + IVOR15 to map on valid OP code address
484  * bacause flash's virtual address maps to 0xff800000 - 0xffffffff.
485  * and this window is outside of 4K boot window.
486  */
487         create_tlb1_entry CONFIG_SYS_PPC_E500_DEBUG_TLB, \
488                 0, BOOKE_PAGESZ_4M, \
489                 CONFIG_SYS_MONITOR_BASE & 0xffc00000,  MAS2_I|MAS2_G, \
490                 0xffc00000, MAS3_SX|MAS3_SW|MAS3_SR, \
491                 0, r6
492
493 #elif !defined(CONFIG_SYS_RAMBOOT) && defined(CONFIG_SECURE_BOOT)
494         create_tlb1_entry CONFIG_SYS_PPC_E500_DEBUG_TLB, \
495                 0, BOOKE_PAGESZ_1M, \
496                 CONFIG_SYS_MONITOR_BASE, MAS2_I|MAS2_G, \
497                 CONFIG_SYS_PBI_FLASH_WINDOW, MAS3_SX|MAS3_SW|MAS3_SR, \
498                 0, r6
499 #else
500 /*
501  * TLB entry is created for IVPR + IVOR15 to map on valid OP code address
502  * because "nexti" will resize TLB to 4K
503  */
504         create_tlb1_entry CONFIG_SYS_PPC_E500_DEBUG_TLB, \
505                 0, BOOKE_PAGESZ_256K, \
506                 CONFIG_SYS_MONITOR_BASE & 0xfffc0000, MAS2_I, \
507                 CONFIG_SYS_MONITOR_BASE & 0xfffc0000, MAS3_SX|MAS3_SW|MAS3_SR, \
508                 0, r6
509 #endif
510 #endif
511
512 /*
513  * Relocate CCSR, if necessary.  We relocate CCSR if (obviously) the default
514  * location is not where we want it.  This typically happens on a 36-bit
515  * system, where we want to move CCSR to near the top of 36-bit address space.
516  *
517  * To move CCSR, we create two temporary TLBs, one for the old location, and
518  * another for the new location.  On CoreNet systems, we also need to create
519  * a special, temporary LAW.
520  *
521  * As a general rule, TLB0 is used for short-term TLBs, and TLB1 is used for
522  * long-term TLBs, so we use TLB0 here.
523  */
524 #if (CONFIG_SYS_CCSRBAR_DEFAULT != CONFIG_SYS_CCSRBAR_PHYS)
525
526 #if !defined(CONFIG_SYS_CCSRBAR_PHYS_HIGH) || !defined(CONFIG_SYS_CCSRBAR_PHYS_LOW)
527 #error "CONFIG_SYS_CCSRBAR_PHYS_HIGH and CONFIG_SYS_CCSRBAR_PHYS_LOW) must be defined."
528 #endif
529
530 create_ccsr_new_tlb:
531         /*
532          * Create a TLB for the new location of CCSR.  Register R8 is reserved
533          * for the virtual address of this TLB (CONFIG_SYS_CCSRBAR).
534          */
535         lis     r8, CONFIG_SYS_CCSRBAR@h
536         ori     r8, r8, CONFIG_SYS_CCSRBAR@l
537         lis     r9, (CONFIG_SYS_CCSRBAR + 0x1000)@h
538         ori     r9, r9, (CONFIG_SYS_CCSRBAR + 0x1000)@l
539         create_tlb0_entry 0, \
540                 0, BOOKE_PAGESZ_4K, \
541                 CONFIG_SYS_CCSRBAR, MAS2_I|MAS2_G, \
542                 CONFIG_SYS_CCSRBAR_PHYS_LOW, MAS3_SW|MAS3_SR, \
543                 CONFIG_SYS_CCSRBAR_PHYS_HIGH, r3
544         /*
545          * Create a TLB for the current location of CCSR.  Register R9 is reserved
546          * for the virtual address of this TLB (CONFIG_SYS_CCSRBAR + 0x1000).
547          */
548 create_ccsr_old_tlb:
549         create_tlb0_entry 1, \
550                 0, BOOKE_PAGESZ_4K, \
551                 CONFIG_SYS_CCSRBAR + 0x1000, MAS2_I|MAS2_G, \
552                 CONFIG_SYS_CCSRBAR_DEFAULT, MAS3_SW|MAS3_SR, \
553                 0, r3 /* The default CCSR address is always a 32-bit number */
554
555
556         /*
557          * We have a TLB for what we think is the current (old) CCSR.  Let's
558          * verify that, otherwise we won't be able to move it.
559          * CONFIG_SYS_CCSRBAR_DEFAULT is always a 32-bit number, so we only
560          * need to compare the lower 32 bits of CCSRBAR on CoreNet systems.
561          */
562 verify_old_ccsr:
563         lis     r0, CONFIG_SYS_CCSRBAR_DEFAULT@h
564         ori     r0, r0, CONFIG_SYS_CCSRBAR_DEFAULT@l
565 #ifdef CONFIG_FSL_CORENET
566         lwz     r1, 4(r9)               /* CCSRBARL */
567 #else
568         lwz     r1, 0(r9)               /* CCSRBAR, shifted right by 12 */
569         slwi    r1, r1, 12
570 #endif
571
572         cmpl    0, r0, r1
573
574         /*
575          * If the value we read from CCSRBARL is not what we expect, then
576          * enter an infinite loop.  This will at least allow a debugger to
577          * halt execution and examine TLBs, etc.  There's no point in going
578          * on.
579          */
580 infinite_debug_loop:
581         bne     infinite_debug_loop
582
583 #ifdef CONFIG_FSL_CORENET
584
585 #define CCSR_LAWBARH0   (CONFIG_SYS_CCSRBAR + 0x1000)
586 #define LAW_EN          0x80000000
587 #define LAW_SIZE_4K     0xb
588 #define CCSRBAR_LAWAR   (LAW_EN | (0x1e << 20) | LAW_SIZE_4K)
589 #define CCSRAR_C        0x80000000      /* Commit */
590
591 create_temp_law:
592         /*
593          * On CoreNet systems, we create the temporary LAW using a special LAW
594          * target ID of 0x1e.  LAWBARH is at offset 0xc00 in CCSR.
595          */
596         lis     r0, CONFIG_SYS_CCSRBAR_PHYS_HIGH@h
597         ori     r0, r0, CONFIG_SYS_CCSRBAR_PHYS_HIGH@l
598         lis     r1, CONFIG_SYS_CCSRBAR_PHYS_LOW@h
599         ori     r1, r1, CONFIG_SYS_CCSRBAR_PHYS_LOW@l
600         lis     r2, CCSRBAR_LAWAR@h
601         ori     r2, r2, CCSRBAR_LAWAR@l
602
603         stw     r0, 0xc00(r9)   /* LAWBARH0 */
604         stw     r1, 0xc04(r9)   /* LAWBARL0 */
605         sync
606         stw     r2, 0xc08(r9)   /* LAWAR0 */
607
608         /*
609          * Read back from LAWAR to ensure the update is complete.  e500mc
610          * cores also require an isync.
611          */
612         lwz     r0, 0xc08(r9)   /* LAWAR0 */
613         isync
614
615         /*
616          * Read the current CCSRBARH and CCSRBARL using load word instructions.
617          * Follow this with an isync instruction. This forces any outstanding
618          * accesses to configuration space to completion.
619          */
620 read_old_ccsrbar:
621         lwz     r0, 0(r9)       /* CCSRBARH */
622         lwz     r0, 4(r9)       /* CCSRBARL */
623         isync
624
625         /*
626          * Write the new values for CCSRBARH and CCSRBARL to their old
627          * locations.  The CCSRBARH has a shadow register. When the CCSRBARH
628          * has a new value written it loads a CCSRBARH shadow register. When
629          * the CCSRBARL is written, the CCSRBARH shadow register contents
630          * along with the CCSRBARL value are loaded into the CCSRBARH and
631          * CCSRBARL registers, respectively.  Follow this with a sync
632          * instruction.
633          */
634 write_new_ccsrbar:
635         lis     r0, CONFIG_SYS_CCSRBAR_PHYS_HIGH@h
636         ori     r0, r0, CONFIG_SYS_CCSRBAR_PHYS_HIGH@l
637         lis     r1, CONFIG_SYS_CCSRBAR_PHYS_LOW@h
638         ori     r1, r1, CONFIG_SYS_CCSRBAR_PHYS_LOW@l
639         lis     r2, CCSRAR_C@h
640         ori     r2, r2, CCSRAR_C@l
641
642         stw     r0, 0(r9)       /* Write to CCSRBARH */
643         sync                    /* Make sure we write to CCSRBARH first */
644         stw     r1, 4(r9)       /* Write to CCSRBARL */
645         sync
646
647         /*
648          * Write a 1 to the commit bit (C) of CCSRAR at the old location.
649          * Follow this with a sync instruction.
650          */
651         stw     r2, 8(r9)
652         sync
653
654         /* Delete the temporary LAW */
655 delete_temp_law:
656         li      r1, 0
657         stw     r1, 0xc08(r8)
658         sync
659         stw     r1, 0xc00(r8)
660         stw     r1, 0xc04(r8)
661         sync
662
663 #else /* #ifdef CONFIG_FSL_CORENET */
664
665 write_new_ccsrbar:
666         /*
667          * Read the current value of CCSRBAR using a load word instruction
668          * followed by an isync. This forces all accesses to configuration
669          * space to complete.
670          */
671         sync
672         lwz     r0, 0(r9)
673         isync
674
675 /* CONFIG_SYS_CCSRBAR_PHYS right shifted by 12 */
676 #define CCSRBAR_PHYS_RS12 ((CONFIG_SYS_CCSRBAR_PHYS_HIGH << 20) | \
677                            (CONFIG_SYS_CCSRBAR_PHYS_LOW >> 12))
678
679         /* Write the new value to CCSRBAR. */
680         lis     r0, CCSRBAR_PHYS_RS12@h
681         ori     r0, r0, CCSRBAR_PHYS_RS12@l
682         stw     r0, 0(r9)
683         sync
684
685         /*
686          * The manual says to perform a load of an address that does not
687          * access configuration space or the on-chip SRAM using an existing TLB,
688          * but that doesn't appear to be necessary.  We will do the isync,
689          * though.
690          */
691         isync
692
693         /*
694          * Read the contents of CCSRBAR from its new location, followed by
695          * another isync.
696          */
697         lwz     r0, 0(r8)
698         isync
699
700 #endif  /* #ifdef CONFIG_FSL_CORENET */
701
702         /* Delete the temporary TLBs */
703 delete_temp_tlbs:
704         delete_tlb0_entry 0, CONFIG_SYS_CCSRBAR, MAS2_I|MAS2_G, r3
705         delete_tlb0_entry 1, CONFIG_SYS_CCSRBAR + 0x1000, MAS2_I|MAS2_G, r3
706
707 #endif /* #if (CONFIG_SYS_CCSRBAR_DEFAULT != CONFIG_SYS_CCSRBAR_PHYS) */
708
709 #ifdef CONFIG_SYS_FSL_QORIQ_CHASSIS2
710 create_ccsr_l2_tlb:
711         /*
712          * Create a TLB for the MMR location of CCSR
713          * to access L2CSR0 register
714          */
715         create_tlb0_entry 0, \
716                 0, BOOKE_PAGESZ_4K, \
717                 CONFIG_SYS_CCSRBAR + 0xC20000, MAS2_I|MAS2_G, \
718                 CONFIG_SYS_CCSRBAR_PHYS_LOW + 0xC20000, MAS3_SW|MAS3_SR, \
719                 CONFIG_SYS_CCSRBAR_PHYS_HIGH, r3
720
721 enable_l2_cluster_l2:
722         /* enable L2 cache */
723         lis     r3, (CONFIG_SYS_CCSRBAR + 0xC20000)@h
724         ori     r3, r3, (CONFIG_SYS_CCSRBAR + 0xC20000)@l
725         li      r4, 33  /* stash id */
726         stw     r4, 4(r3)
727         lis     r4, (L2CSR0_L2FI|L2CSR0_L2LFC)@h
728         ori     r4, r4, (L2CSR0_L2FI|L2CSR0_L2LFC)@l
729         sync
730         stw     r4, 0(r3)       /* invalidate L2 */
731 1:      sync
732         lwz     r0, 0(r3)
733         twi     0, r0, 0
734         isync
735         and.    r1, r0, r4
736         bne     1b
737         lis     r4, (L2CSR0_L2E|L2CSR0_L2PE)@h
738         ori     r4, r4, (L2CSR0_L2REP_MODE)@l
739         sync
740         stw     r4, 0(r3)       /* enable L2 */
741 delete_ccsr_l2_tlb:
742         delete_tlb0_entry 0, CONFIG_SYS_CCSRBAR + 0xC20000, MAS2_I|MAS2_G, r3
743 #endif
744
745         /*
746          * Enable the L1. On e6500, this has to be done
747          * after the L2 is up.
748          */
749
750 #ifdef CONFIG_SYS_CACHE_STASHING
751         /* set stash id to (coreID) * 2 + 32 + L1 CT (0) */
752         li      r2,(32 + 0)
753         mtspr   L1CSR2,r2
754 #endif
755
756         /* Enable/invalidate the I-Cache */
757         lis     r2,(L1CSR1_ICFI|L1CSR1_ICLFR)@h
758         ori     r2,r2,(L1CSR1_ICFI|L1CSR1_ICLFR)@l
759         mtspr   SPRN_L1CSR1,r2
760 1:
761         mfspr   r3,SPRN_L1CSR1
762         and.    r1,r3,r2
763         bne     1b
764
765         lis     r3,(L1CSR1_CPE|L1CSR1_ICE)@h
766         ori     r3,r3,(L1CSR1_CPE|L1CSR1_ICE)@l
767         mtspr   SPRN_L1CSR1,r3
768         isync
769 2:
770         mfspr   r3,SPRN_L1CSR1
771         andi.   r1,r3,L1CSR1_ICE@l
772         beq     2b
773
774         /* Enable/invalidate the D-Cache */
775         lis     r2,(L1CSR0_DCFI|L1CSR0_DCLFR)@h
776         ori     r2,r2,(L1CSR0_DCFI|L1CSR0_DCLFR)@l
777         mtspr   SPRN_L1CSR0,r2
778 1:
779         mfspr   r3,SPRN_L1CSR0
780         and.    r1,r3,r2
781         bne     1b
782
783         lis     r3,(L1CSR0_CPE|L1CSR0_DCE)@h
784         ori     r3,r3,(L1CSR0_CPE|L1CSR0_DCE)@l
785         mtspr   SPRN_L1CSR0,r3
786         isync
787 2:
788         mfspr   r3,SPRN_L1CSR0
789         andi.   r1,r3,L1CSR0_DCE@l
790         beq     2b
791 #ifdef CONFIG_SYS_FSL_ERRATUM_A004510
792 #define DCSR_LAWBARH0   (CONFIG_SYS_CCSRBAR + 0x1000)
793 #define LAW_SIZE_1M     0x13
794 #define DCSRBAR_LAWAR   (LAW_EN | (0x1d << 20) | LAW_SIZE_1M)
795
796         cmpwi   r27,0
797         beq     9f
798
799         /*
800          * Create a TLB entry for CCSR
801          *
802          * We're executing out of TLB1 entry in r14, and that's the only
803          * TLB entry that exists.  To allocate some TLB entries for our
804          * own use, flip a bit high enough that we won't flip it again
805          * via incrementing.
806          */
807
808         xori    r8, r14, 32
809         lis     r0, MAS0_TLBSEL(1)@h
810         rlwimi  r0, r8, 16, MAS0_ESEL_MSK
811         lis     r1, FSL_BOOKE_MAS1(1, 1, 0, 0, BOOKE_PAGESZ_16M)@h
812         ori     r1, r1, FSL_BOOKE_MAS1(1, 1, 0, 0, BOOKE_PAGESZ_16M)@l
813         lis     r7, CONFIG_SYS_CCSRBAR@h
814         ori     r7, r7, CONFIG_SYS_CCSRBAR@l
815         ori     r2, r7, MAS2_I|MAS2_G
816         lis     r3, FSL_BOOKE_MAS3(CONFIG_SYS_CCSRBAR_PHYS_LOW, 0, (MAS3_SW|MAS3_SR))@h
817         ori     r3, r3, FSL_BOOKE_MAS3(CONFIG_SYS_CCSRBAR_PHYS_LOW, 0, (MAS3_SW|MAS3_SR))@l
818         lis     r4, CONFIG_SYS_CCSRBAR_PHYS_HIGH@h
819         ori     r4, r4, CONFIG_SYS_CCSRBAR_PHYS_HIGH@l
820         mtspr   MAS0, r0
821         mtspr   MAS1, r1
822         mtspr   MAS2, r2
823         mtspr   MAS3, r3
824         mtspr   MAS7, r4
825         isync
826         tlbwe
827         isync
828         msync
829
830         /* Map DCSR temporarily to physical address zero */
831         li      r0, 0
832         lis     r3, DCSRBAR_LAWAR@h
833         ori     r3, r3, DCSRBAR_LAWAR@l
834
835         stw     r0, 0xc00(r7)   /* LAWBARH0 */
836         stw     r0, 0xc04(r7)   /* LAWBARL0 */
837         sync
838         stw     r3, 0xc08(r7)   /* LAWAR0 */
839
840         /* Read back from LAWAR to ensure the update is complete. */
841         lwz     r3, 0xc08(r7)   /* LAWAR0 */
842         isync
843
844         /* Create a TLB entry for DCSR at zero */
845
846         addi    r9, r8, 1
847         lis     r0, MAS0_TLBSEL(1)@h
848         rlwimi  r0, r9, 16, MAS0_ESEL_MSK
849         lis     r1, FSL_BOOKE_MAS1(1, 1, 0, 0, BOOKE_PAGESZ_1M)@h
850         ori     r1, r1, FSL_BOOKE_MAS1(1, 1, 0, 0, BOOKE_PAGESZ_1M)@l
851         li      r6, 0   /* DCSR effective address */
852         ori     r2, r6, MAS2_I|MAS2_G
853         li      r3, MAS3_SW|MAS3_SR
854         li      r4, 0
855         mtspr   MAS0, r0
856         mtspr   MAS1, r1
857         mtspr   MAS2, r2
858         mtspr   MAS3, r3
859         mtspr   MAS7, r4
860         isync
861         tlbwe
862         isync
863         msync
864
865         /* enable the timebase */
866 #define CTBENR  0xe2084
867         li      r3, 1
868         addis   r4, r7, CTBENR@ha
869         stw     r3, CTBENR@l(r4)
870         lwz     r3, CTBENR@l(r4)
871         twi     0,r3,0
872         isync
873
874         .macro  erratum_set_ccsr offset value
875         addis   r3, r7, \offset@ha
876         lis     r4, \value@h
877         addi    r3, r3, \offset@l
878         ori     r4, r4, \value@l
879         bl      erratum_set_value
880         .endm
881
882         .macro  erratum_set_dcsr offset value
883         addis   r3, r6, \offset@ha
884         lis     r4, \value@h
885         addi    r3, r3, \offset@l
886         ori     r4, r4, \value@l
887         bl      erratum_set_value
888         .endm
889
890         erratum_set_dcsr 0xb0e08 0xe0201800
891         erratum_set_dcsr 0xb0e18 0xe0201800
892         erratum_set_dcsr 0xb0e38 0xe0400000
893         erratum_set_dcsr 0xb0008 0x00900000
894         erratum_set_dcsr 0xb0e40 0xe00a0000
895         erratum_set_ccsr 0x18600 CONFIG_SYS_FSL_CORENET_SNOOPVEC_COREONLY
896         erratum_set_ccsr 0x10f00 0x415e5000
897         erratum_set_ccsr 0x11f00 0x415e5000
898
899         /* Make temp mapping uncacheable again, if it was initially */
900         bl      2f
901 2:      mflr    r3
902         tlbsx   0, r3
903         mfspr   r4, MAS2
904         rlwimi  r4, r15, 0, MAS2_I
905         rlwimi  r4, r15, 0, MAS2_G
906         mtspr   MAS2, r4
907         isync
908         tlbwe
909         isync
910         msync
911
912         /* Clear the cache */
913         lis     r3,(L1CSR1_ICFI|L1CSR1_ICLFR)@h
914         ori     r3,r3,(L1CSR1_ICFI|L1CSR1_ICLFR)@l
915         sync
916         isync
917         mtspr   SPRN_L1CSR1,r3
918         isync
919 2:      sync
920         mfspr   r4,SPRN_L1CSR1
921         and.    r4,r4,r3
922         bne     2b
923
924         lis     r3,(L1CSR1_CPE|L1CSR1_ICE)@h
925         ori     r3,r3,(L1CSR1_CPE|L1CSR1_ICE)@l
926         sync
927         isync
928         mtspr   SPRN_L1CSR1,r3
929         isync
930 2:      sync
931         mfspr   r4,SPRN_L1CSR1
932         and.    r4,r4,r3
933         beq     2b
934
935         /* Remove temporary mappings */
936         lis     r0, MAS0_TLBSEL(1)@h
937         rlwimi  r0, r9, 16, MAS0_ESEL_MSK
938         li      r3, 0
939         mtspr   MAS0, r0
940         mtspr   MAS1, r3
941         isync
942         tlbwe
943         isync
944         msync
945
946         li      r3, 0
947         stw     r3, 0xc08(r7)   /* LAWAR0 */
948         lwz     r3, 0xc08(r7)
949         isync
950
951         lis     r0, MAS0_TLBSEL(1)@h
952         rlwimi  r0, r8, 16, MAS0_ESEL_MSK
953         li      r3, 0
954         mtspr   MAS0, r0
955         mtspr   MAS1, r3
956         isync
957         tlbwe
958         isync
959         msync
960
961         b       9f
962
963         /* r3 = addr, r4 = value, clobbers r5, r11, r12 */
964 erratum_set_value:
965         /* Lock two cache lines into I-Cache */
966         sync
967         mfspr   r11, SPRN_L1CSR1
968         rlwinm  r11, r11, 0, ~L1CSR1_ICUL
969         sync
970         isync
971         mtspr   SPRN_L1CSR1, r11
972         isync
973
974         mflr    r12
975         bl      5f
976 5:      mflr    r5
977         addi    r5, r5, 2f - 5b
978         icbtls  0, 0, r5
979         addi    r5, r5, 64
980
981         sync
982         mfspr   r11, SPRN_L1CSR1
983 3:      andi.   r11, r11, L1CSR1_ICUL
984         bne     3b
985
986         icbtls  0, 0, r5
987         addi    r5, r5, 64
988
989         sync
990         mfspr   r11, SPRN_L1CSR1
991 3:      andi.   r11, r11, L1CSR1_ICUL
992         bne     3b
993
994         b       2f
995         .align  6
996         /* Inside a locked cacheline, wait a while, write, then wait a while */
997 2:      sync
998
999         mfspr   r5, SPRN_TBRL
1000         addis   r11, r5, 0x10000@h /* wait 65536 timebase ticks */
1001 4:      mfspr   r5, SPRN_TBRL
1002         subf.   r5, r5, r11
1003         bgt     4b
1004
1005         stw     r4, 0(r3)
1006
1007         mfspr   r5, SPRN_TBRL
1008         addis   r11, r5, 0x10000@h /* wait 65536 timebase ticks */
1009 4:      mfspr   r5, SPRN_TBRL
1010         subf.   r5, r5, r11
1011         bgt     4b
1012
1013         sync
1014
1015         /*
1016          * Fill out the rest of this cache line and the next with nops,
1017          * to ensure that nothing outside the locked area will be
1018          * fetched due to a branch.
1019          */
1020         .rept 19
1021         nop
1022         .endr
1023
1024         sync
1025         mfspr   r11, SPRN_L1CSR1
1026         rlwinm  r11, r11, 0, ~L1CSR1_ICUL
1027         sync
1028         isync
1029         mtspr   SPRN_L1CSR1, r11
1030         isync
1031
1032         mtlr    r12
1033         blr
1034
1035 9:
1036 #endif
1037
1038 create_init_ram_area:
1039         lis     r6,FSL_BOOKE_MAS0(1, 15, 0)@h
1040         ori     r6,r6,FSL_BOOKE_MAS0(1, 15, 0)@l
1041
1042 #ifdef NOR_BOOT
1043         /* create a temp mapping in AS=1 to the 4M boot window */
1044         create_tlb1_entry 15, \
1045                 1, BOOKE_PAGESZ_4M, \
1046                 CONFIG_SYS_MONITOR_BASE & 0xffc00000, MAS2_I|MAS2_G, \
1047                 0xffc00000, MAS3_SX|MAS3_SW|MAS3_SR, \
1048                 0, r6
1049
1050 #elif !defined(CONFIG_SYS_RAMBOOT) && defined(CONFIG_SECURE_BOOT)
1051         /* create a temp mapping in AS = 1 for Flash mapping
1052          * created by PBL for ISBC code
1053         */
1054         create_tlb1_entry 15, \
1055                 1, BOOKE_PAGESZ_1M, \
1056                 CONFIG_SYS_MONITOR_BASE & 0xfff00000, MAS2_I|MAS2_G, \
1057                 CONFIG_SYS_PBI_FLASH_WINDOW & 0xfff00000, MAS3_SX|MAS3_SW|MAS3_SR, \
1058                 0, r6
1059 #else
1060         /*
1061          * create a temp mapping in AS=1 to the 1M CONFIG_SYS_MONITOR_BASE space, the main
1062          * image has been relocated to CONFIG_SYS_MONITOR_BASE on the second stage.
1063          */
1064         create_tlb1_entry 15, \
1065                 1, BOOKE_PAGESZ_1M, \
1066                 CONFIG_SYS_MONITOR_BASE & 0xfff00000, MAS2_I|MAS2_G, \
1067                 CONFIG_SYS_MONITOR_BASE & 0xfff00000, MAS3_SX|MAS3_SW|MAS3_SR, \
1068                 0, r6
1069 #endif
1070
1071         /* create a temp mapping in AS=1 to the stack */
1072 #if defined(CONFIG_SYS_INIT_RAM_ADDR_PHYS_LOW) && \
1073     defined(CONFIG_SYS_INIT_RAM_ADDR_PHYS_HIGH)
1074         create_tlb1_entry 14, \
1075                 1, BOOKE_PAGESZ_16K, \
1076                 CONFIG_SYS_INIT_RAM_ADDR, 0, \
1077                 CONFIG_SYS_INIT_RAM_ADDR_PHYS_LOW, MAS3_SX|MAS3_SW|MAS3_SR, \
1078                 CONFIG_SYS_INIT_RAM_ADDR_PHYS_HIGH, r6
1079
1080 #else
1081         create_tlb1_entry 14, \
1082                 1, BOOKE_PAGESZ_16K, \
1083                 CONFIG_SYS_INIT_RAM_ADDR, 0, \
1084                 CONFIG_SYS_INIT_RAM_ADDR, MAS3_SX|MAS3_SW|MAS3_SR, \
1085                 0, r6
1086 #endif
1087
1088         lis     r6,MSR_IS|MSR_DS|MSR_DE@h
1089         ori     r6,r6,MSR_IS|MSR_DS|MSR_DE@l
1090         lis     r7,switch_as@h
1091         ori     r7,r7,switch_as@l
1092
1093         mtspr   SPRN_SRR0,r7
1094         mtspr   SPRN_SRR1,r6
1095         rfi
1096
1097 switch_as:
1098 /* L1 DCache is used for initial RAM */
1099
1100         /* Allocate Initial RAM in data cache.
1101          */
1102         lis     r3,CONFIG_SYS_INIT_RAM_ADDR@h
1103         ori     r3,r3,CONFIG_SYS_INIT_RAM_ADDR@l
1104         mfspr   r2, L1CFG0
1105         andi.   r2, r2, 0x1ff
1106         /* cache size * 1024 / (2 * L1 line size) */
1107         slwi    r2, r2, (10 - 1 - L1_CACHE_SHIFT)
1108         mtctr   r2
1109         li      r0,0
1110 1:
1111         dcbz    r0,r3
1112         dcbtls  0,r0,r3
1113         addi    r3,r3,CONFIG_SYS_CACHELINE_SIZE
1114         bdnz    1b
1115
1116         /* Jump out the last 4K page and continue to 'normal' start */
1117 #if defined(CONFIG_SYS_RAMBOOT) || defined(CONFIG_SPL)
1118         /* We assume that we're already running at the address we're linked at */
1119         b       _start_cont
1120 #else
1121         /* Calculate absolute address in FLASH and jump there           */
1122         /*--------------------------------------------------------------*/
1123         lis     r3,CONFIG_SYS_MONITOR_BASE@h
1124         ori     r3,r3,CONFIG_SYS_MONITOR_BASE@l
1125         addi    r3,r3,_start_cont - _start + _START_OFFSET
1126         mtlr    r3
1127         blr
1128 #endif
1129
1130         .text
1131         .globl  _start
1132 _start:
1133         .long   0x27051956              /* U-BOOT Magic Number */
1134         .globl  version_string
1135 version_string:
1136         .ascii U_BOOT_VERSION_STRING, "\0"
1137
1138         .align  4
1139         .globl  _start_cont
1140 _start_cont:
1141         /* Setup the stack in initial RAM,could be L2-as-SRAM or L1 dcache*/
1142         lis     r3,(CONFIG_SYS_INIT_RAM_ADDR)@h
1143         ori     r3,r3,((CONFIG_SYS_INIT_SP_OFFSET-16)&~0xf)@l /* Align to 16 */
1144         li      r0,0
1145         stw     r0,0(r3)        /* Terminate Back Chain */
1146         stw     r0,+4(r3)       /* NULL return address. */
1147         mr      r1,r3           /* Transfer to SP(r1) */
1148
1149         GET_GOT
1150         bl      cpu_init_early_f
1151
1152         /* switch back to AS = 0 */
1153         lis     r3,(MSR_CE|MSR_ME|MSR_DE)@h
1154         ori     r3,r3,(MSR_CE|MSR_ME|MSR_DE)@l
1155         mtmsr   r3
1156         isync
1157
1158         bl      cpu_init_f
1159         bl      board_init_f
1160         isync
1161
1162         /* NOTREACHED - board_init_f() does not return */
1163
1164 #ifndef MINIMAL_SPL
1165         . = EXC_OFF_SYS_RESET
1166         .globl  _start_of_vectors
1167 _start_of_vectors:
1168
1169 /* Critical input. */
1170         CRIT_EXCEPTION(0x0100, CriticalInput, CritcalInputException)
1171
1172 /* Machine check */
1173         MCK_EXCEPTION(0x200, MachineCheck, MachineCheckException)
1174
1175 /* Data Storage exception. */
1176         STD_EXCEPTION(0x0300, DataStorage, UnknownException)
1177
1178 /* Instruction Storage exception. */
1179         STD_EXCEPTION(0x0400, InstStorage, UnknownException)
1180
1181 /* External Interrupt exception. */
1182         STD_EXCEPTION(0x0500, ExtInterrupt, ExtIntException)
1183
1184 /* Alignment exception. */
1185         . = 0x0600
1186 Alignment:
1187         EXCEPTION_PROLOG(SRR0, SRR1)
1188         mfspr   r4,DAR
1189         stw     r4,_DAR(r21)
1190         mfspr   r5,DSISR
1191         stw     r5,_DSISR(r21)
1192         addi    r3,r1,STACK_FRAME_OVERHEAD
1193         EXC_XFER_TEMPLATE(Alignment, AlignmentException, MSR_KERNEL, COPY_EE)
1194
1195 /* Program check exception */
1196         . = 0x0700
1197 ProgramCheck:
1198         EXCEPTION_PROLOG(SRR0, SRR1)
1199         addi    r3,r1,STACK_FRAME_OVERHEAD
1200         EXC_XFER_TEMPLATE(ProgramCheck, ProgramCheckException,
1201                 MSR_KERNEL, COPY_EE)
1202
1203         /* No FPU on MPC85xx.  This exception is not supposed to happen.
1204         */
1205         STD_EXCEPTION(0x0800, FPUnavailable, UnknownException)
1206
1207         . = 0x0900
1208 /*
1209  * r0 - SYSCALL number
1210  * r3-... arguments
1211  */
1212 SystemCall:
1213         addis   r11,r0,0        /* get functions table addr */
1214         ori     r11,r11,0       /* Note: this code is patched in trap_init */
1215         addis   r12,r0,0        /* get number of functions */
1216         ori     r12,r12,0
1217
1218         cmplw   0,r0,r12
1219         bge     1f
1220
1221         rlwinm  r0,r0,2,0,31    /* fn_addr = fn_tbl[r0] */
1222         add     r11,r11,r0
1223         lwz     r11,0(r11)
1224
1225         li      r20,0xd00-4     /* Get stack pointer */
1226         lwz     r12,0(r20)
1227         subi    r12,r12,12      /* Adjust stack pointer */
1228         li      r0,0xc00+_end_back-SystemCall
1229         cmplw   0,r0,r12        /* Check stack overflow */
1230         bgt     1f
1231         stw     r12,0(r20)
1232
1233         mflr    r0
1234         stw     r0,0(r12)
1235         mfspr   r0,SRR0
1236         stw     r0,4(r12)
1237         mfspr   r0,SRR1
1238         stw     r0,8(r12)
1239
1240         li      r12,0xc00+_back-SystemCall
1241         mtlr    r12
1242         mtspr   SRR0,r11
1243
1244 1:      SYNC
1245         rfi
1246 _back:
1247
1248         mfmsr   r11                     /* Disable interrupts */
1249         li      r12,0
1250         ori     r12,r12,MSR_EE
1251         andc    r11,r11,r12
1252         SYNC                            /* Some chip revs need this... */
1253         mtmsr   r11
1254         SYNC
1255
1256         li      r12,0xd00-4             /* restore regs */
1257         lwz     r12,0(r12)
1258
1259         lwz     r11,0(r12)
1260         mtlr    r11
1261         lwz     r11,4(r12)
1262         mtspr   SRR0,r11
1263         lwz     r11,8(r12)
1264         mtspr   SRR1,r11
1265
1266         addi    r12,r12,12              /* Adjust stack pointer */
1267         li      r20,0xd00-4
1268         stw     r12,0(r20)
1269
1270         SYNC
1271         rfi
1272 _end_back:
1273
1274         STD_EXCEPTION(0x0a00, Decrementer, timer_interrupt)
1275         STD_EXCEPTION(0x0b00, IntervalTimer, UnknownException)
1276         STD_EXCEPTION(0x0c00, WatchdogTimer, UnknownException)
1277
1278         STD_EXCEPTION(0x0d00, DataTLBError, UnknownException)
1279         STD_EXCEPTION(0x0e00, InstructionTLBError, UnknownException)
1280
1281         CRIT_EXCEPTION(0x0f00, DebugBreakpoint, DebugException )
1282
1283         .globl  _end_of_vectors
1284 _end_of_vectors:
1285
1286
1287         . = . + (0x100 - ( . & 0xff ))  /* align for debug */
1288
1289 /*
1290  * This code finishes saving the registers to the exception frame
1291  * and jumps to the appropriate handler for the exception.
1292  * Register r21 is pointer into trap frame, r1 has new stack pointer.
1293  */
1294         .globl  transfer_to_handler
1295 transfer_to_handler:
1296         stw     r22,_NIP(r21)
1297         lis     r22,MSR_POW@h
1298         andc    r23,r23,r22
1299         stw     r23,_MSR(r21)
1300         SAVE_GPR(7, r21)
1301         SAVE_4GPRS(8, r21)
1302         SAVE_8GPRS(12, r21)
1303         SAVE_8GPRS(24, r21)
1304
1305         mflr    r23
1306         andi.   r24,r23,0x3f00          /* get vector offset */
1307         stw     r24,TRAP(r21)
1308         li      r22,0
1309         stw     r22,RESULT(r21)
1310         mtspr   SPRG2,r22               /* r1 is now kernel sp */
1311
1312         lwz     r24,0(r23)              /* virtual address of handler */
1313         lwz     r23,4(r23)              /* where to go when done */
1314         mtspr   SRR0,r24
1315         mtspr   SRR1,r20
1316         mtlr    r23
1317         SYNC
1318         rfi                             /* jump to handler, enable MMU */
1319
1320 int_return:
1321         mfmsr   r28             /* Disable interrupts */
1322         li      r4,0
1323         ori     r4,r4,MSR_EE
1324         andc    r28,r28,r4
1325         SYNC                    /* Some chip revs need this... */
1326         mtmsr   r28
1327         SYNC
1328         lwz     r2,_CTR(r1)
1329         lwz     r0,_LINK(r1)
1330         mtctr   r2
1331         mtlr    r0
1332         lwz     r2,_XER(r1)
1333         lwz     r0,_CCR(r1)
1334         mtspr   XER,r2
1335         mtcrf   0xFF,r0
1336         REST_10GPRS(3, r1)
1337         REST_10GPRS(13, r1)
1338         REST_8GPRS(23, r1)
1339         REST_GPR(31, r1)
1340         lwz     r2,_NIP(r1)     /* Restore environment */
1341         lwz     r0,_MSR(r1)
1342         mtspr   SRR0,r2
1343         mtspr   SRR1,r0
1344         lwz     r0,GPR0(r1)
1345         lwz     r2,GPR2(r1)
1346         lwz     r1,GPR1(r1)
1347         SYNC
1348         rfi
1349
1350 crit_return:
1351         mfmsr   r28             /* Disable interrupts */
1352         li      r4,0
1353         ori     r4,r4,MSR_EE
1354         andc    r28,r28,r4
1355         SYNC                    /* Some chip revs need this... */
1356         mtmsr   r28
1357         SYNC
1358         lwz     r2,_CTR(r1)
1359         lwz     r0,_LINK(r1)
1360         mtctr   r2
1361         mtlr    r0
1362         lwz     r2,_XER(r1)
1363         lwz     r0,_CCR(r1)
1364         mtspr   XER,r2
1365         mtcrf   0xFF,r0
1366         REST_10GPRS(3, r1)
1367         REST_10GPRS(13, r1)
1368         REST_8GPRS(23, r1)
1369         REST_GPR(31, r1)
1370         lwz     r2,_NIP(r1)     /* Restore environment */
1371         lwz     r0,_MSR(r1)
1372         mtspr   SPRN_CSRR0,r2
1373         mtspr   SPRN_CSRR1,r0
1374         lwz     r0,GPR0(r1)
1375         lwz     r2,GPR2(r1)
1376         lwz     r1,GPR1(r1)
1377         SYNC
1378         rfci
1379
1380 mck_return:
1381         mfmsr   r28             /* Disable interrupts */
1382         li      r4,0
1383         ori     r4,r4,MSR_EE
1384         andc    r28,r28,r4
1385         SYNC                    /* Some chip revs need this... */
1386         mtmsr   r28
1387         SYNC
1388         lwz     r2,_CTR(r1)
1389         lwz     r0,_LINK(r1)
1390         mtctr   r2
1391         mtlr    r0
1392         lwz     r2,_XER(r1)
1393         lwz     r0,_CCR(r1)
1394         mtspr   XER,r2
1395         mtcrf   0xFF,r0
1396         REST_10GPRS(3, r1)
1397         REST_10GPRS(13, r1)
1398         REST_8GPRS(23, r1)
1399         REST_GPR(31, r1)
1400         lwz     r2,_NIP(r1)     /* Restore environment */
1401         lwz     r0,_MSR(r1)
1402         mtspr   SPRN_MCSRR0,r2
1403         mtspr   SPRN_MCSRR1,r0
1404         lwz     r0,GPR0(r1)
1405         lwz     r2,GPR2(r1)
1406         lwz     r1,GPR1(r1)
1407         SYNC
1408         rfmci
1409
1410 /* Cache functions.
1411 */
1412 .globl flush_icache
1413 flush_icache:
1414 .globl invalidate_icache
1415 invalidate_icache:
1416         mfspr   r0,L1CSR1
1417         ori     r0,r0,L1CSR1_ICFI
1418         msync
1419         isync
1420         mtspr   L1CSR1,r0
1421         isync
1422         blr                             /* entire I cache */
1423
1424 .globl invalidate_dcache
1425 invalidate_dcache:
1426         mfspr   r0,L1CSR0
1427         ori     r0,r0,L1CSR0_DCFI
1428         msync
1429         isync
1430         mtspr   L1CSR0,r0
1431         isync
1432         blr
1433
1434         .globl  icache_enable
1435 icache_enable:
1436         mflr    r8
1437         bl      invalidate_icache
1438         mtlr    r8
1439         isync
1440         mfspr   r4,L1CSR1
1441         ori     r4,r4,0x0001
1442         oris    r4,r4,0x0001
1443         mtspr   L1CSR1,r4
1444         isync
1445         blr
1446
1447         .globl  icache_disable
1448 icache_disable:
1449         mfspr   r0,L1CSR1
1450         lis     r3,0
1451         ori     r3,r3,L1CSR1_ICE
1452         andc    r0,r0,r3
1453         mtspr   L1CSR1,r0
1454         isync
1455         blr
1456
1457         .globl  icache_status
1458 icache_status:
1459         mfspr   r3,L1CSR1
1460         andi.   r3,r3,L1CSR1_ICE
1461         blr
1462
1463         .globl  dcache_enable
1464 dcache_enable:
1465         mflr    r8
1466         bl      invalidate_dcache
1467         mtlr    r8
1468         isync
1469         mfspr   r0,L1CSR0
1470         ori     r0,r0,0x0001
1471         oris    r0,r0,0x0001
1472         msync
1473         isync
1474         mtspr   L1CSR0,r0
1475         isync
1476         blr
1477
1478         .globl  dcache_disable
1479 dcache_disable:
1480         mfspr   r3,L1CSR0
1481         lis     r4,0
1482         ori     r4,r4,L1CSR0_DCE
1483         andc    r3,r3,r4
1484         mtspr   L1CSR0,r3
1485         isync
1486         blr
1487
1488         .globl  dcache_status
1489 dcache_status:
1490         mfspr   r3,L1CSR0
1491         andi.   r3,r3,L1CSR0_DCE
1492         blr
1493
1494         .globl get_pir
1495 get_pir:
1496         mfspr   r3,PIR
1497         blr
1498
1499         .globl get_pvr
1500 get_pvr:
1501         mfspr   r3,PVR
1502         blr
1503
1504         .globl get_svr
1505 get_svr:
1506         mfspr   r3,SVR
1507         blr
1508
1509         .globl wr_tcr
1510 wr_tcr:
1511         mtspr   TCR,r3
1512         blr
1513
1514 /*------------------------------------------------------------------------------- */
1515 /* Function:     in8 */
1516 /* Description:  Input 8 bits */
1517 /*------------------------------------------------------------------------------- */
1518         .globl  in8
1519 in8:
1520         lbz     r3,0x0000(r3)
1521         blr
1522
1523 /*------------------------------------------------------------------------------- */
1524 /* Function:     out8 */
1525 /* Description:  Output 8 bits */
1526 /*------------------------------------------------------------------------------- */
1527         .globl  out8
1528 out8:
1529         stb     r4,0x0000(r3)
1530         sync
1531         blr
1532
1533 /*------------------------------------------------------------------------------- */
1534 /* Function:     out16 */
1535 /* Description:  Output 16 bits */
1536 /*------------------------------------------------------------------------------- */
1537         .globl  out16
1538 out16:
1539         sth     r4,0x0000(r3)
1540         sync
1541         blr
1542
1543 /*------------------------------------------------------------------------------- */
1544 /* Function:     out16r */
1545 /* Description:  Byte reverse and output 16 bits */
1546 /*------------------------------------------------------------------------------- */
1547         .globl  out16r
1548 out16r:
1549         sthbrx  r4,r0,r3
1550         sync
1551         blr
1552
1553 /*------------------------------------------------------------------------------- */
1554 /* Function:     out32 */
1555 /* Description:  Output 32 bits */
1556 /*------------------------------------------------------------------------------- */
1557         .globl  out32
1558 out32:
1559         stw     r4,0x0000(r3)
1560         sync
1561         blr
1562
1563 /*------------------------------------------------------------------------------- */
1564 /* Function:     out32r */
1565 /* Description:  Byte reverse and output 32 bits */
1566 /*------------------------------------------------------------------------------- */
1567         .globl  out32r
1568 out32r:
1569         stwbrx  r4,r0,r3
1570         sync
1571         blr
1572
1573 /*------------------------------------------------------------------------------- */
1574 /* Function:     in16 */
1575 /* Description:  Input 16 bits */
1576 /*------------------------------------------------------------------------------- */
1577         .globl  in16
1578 in16:
1579         lhz     r3,0x0000(r3)
1580         blr
1581
1582 /*------------------------------------------------------------------------------- */
1583 /* Function:     in16r */
1584 /* Description:  Input 16 bits and byte reverse */
1585 /*------------------------------------------------------------------------------- */
1586         .globl  in16r
1587 in16r:
1588         lhbrx   r3,r0,r3
1589         blr
1590
1591 /*------------------------------------------------------------------------------- */
1592 /* Function:     in32 */
1593 /* Description:  Input 32 bits */
1594 /*------------------------------------------------------------------------------- */
1595         .globl  in32
1596 in32:
1597         lwz     3,0x0000(3)
1598         blr
1599
1600 /*------------------------------------------------------------------------------- */
1601 /* Function:     in32r */
1602 /* Description:  Input 32 bits and byte reverse */
1603 /*------------------------------------------------------------------------------- */
1604         .globl  in32r
1605 in32r:
1606         lwbrx   r3,r0,r3
1607         blr
1608 #endif  /* !MINIMAL_SPL */
1609
1610 /*------------------------------------------------------------------------------*/
1611
1612 /*
1613  * void write_tlb(mas0, mas1, mas2, mas3, mas7)
1614  */
1615         .globl  write_tlb
1616 write_tlb:
1617         mtspr   MAS0,r3
1618         mtspr   MAS1,r4
1619         mtspr   MAS2,r5
1620         mtspr   MAS3,r6
1621 #ifdef CONFIG_ENABLE_36BIT_PHYS
1622         mtspr   MAS7,r7
1623 #endif
1624         li      r3,0
1625 #ifdef CONFIG_SYS_BOOK3E_HV
1626         mtspr   MAS8,r3
1627 #endif
1628         isync
1629         tlbwe
1630         msync
1631         isync
1632         blr
1633
1634 /*
1635  * void relocate_code (addr_sp, gd, addr_moni)
1636  *
1637  * This "function" does not return, instead it continues in RAM
1638  * after relocating the monitor code.
1639  *
1640  * r3 = dest
1641  * r4 = src
1642  * r5 = length in bytes
1643  * r6 = cachelinesize
1644  */
1645         .globl  relocate_code
1646 relocate_code:
1647         mr      r1,r3           /* Set new stack pointer                */
1648         mr      r9,r4           /* Save copy of Init Data pointer       */
1649         mr      r10,r5          /* Save copy of Destination Address     */
1650
1651         GET_GOT
1652         mr      r3,r5                           /* Destination Address  */
1653         lis     r4,CONFIG_SYS_MONITOR_BASE@h            /* Source      Address  */
1654         ori     r4,r4,CONFIG_SYS_MONITOR_BASE@l
1655         lwz     r5,GOT(__init_end)
1656         sub     r5,r5,r4
1657         li      r6,CONFIG_SYS_CACHELINE_SIZE            /* Cache Line Size      */
1658
1659         /*
1660          * Fix GOT pointer:
1661          *
1662          * New GOT-PTR = (old GOT-PTR - CONFIG_SYS_MONITOR_BASE) + Destination Address
1663          *
1664          * Offset:
1665          */
1666         sub     r15,r10,r4
1667
1668         /* First our own GOT */
1669         add     r12,r12,r15
1670         /* the the one used by the C code */
1671         add     r30,r30,r15
1672
1673         /*
1674          * Now relocate code
1675          */
1676
1677         cmplw   cr1,r3,r4
1678         addi    r0,r5,3
1679         srwi.   r0,r0,2
1680         beq     cr1,4f          /* In place copy is not necessary       */
1681         beq     7f              /* Protect against 0 count              */
1682         mtctr   r0
1683         bge     cr1,2f
1684
1685         la      r8,-4(r4)
1686         la      r7,-4(r3)
1687 1:      lwzu    r0,4(r8)
1688         stwu    r0,4(r7)
1689         bdnz    1b
1690         b       4f
1691
1692 2:      slwi    r0,r0,2
1693         add     r8,r4,r0
1694         add     r7,r3,r0
1695 3:      lwzu    r0,-4(r8)
1696         stwu    r0,-4(r7)
1697         bdnz    3b
1698
1699 /*
1700  * Now flush the cache: note that we must start from a cache aligned
1701  * address. Otherwise we might miss one cache line.
1702  */
1703 4:      cmpwi   r6,0
1704         add     r5,r3,r5
1705         beq     7f              /* Always flush prefetch queue in any case */
1706         subi    r0,r6,1
1707         andc    r3,r3,r0
1708         mr      r4,r3
1709 5:      dcbst   0,r4
1710         add     r4,r4,r6
1711         cmplw   r4,r5
1712         blt     5b
1713         sync                    /* Wait for all dcbst to complete on bus */
1714         mr      r4,r3
1715 6:      icbi    0,r4
1716         add     r4,r4,r6
1717         cmplw   r4,r5
1718         blt     6b
1719 7:      sync                    /* Wait for all icbi to complete on bus */
1720         isync
1721
1722 /*
1723  * We are done. Do not return, instead branch to second part of board
1724  * initialization, now running from RAM.
1725  */
1726
1727         addi    r0,r10,in_ram - _start + _START_OFFSET
1728
1729         /*
1730          * As IVPR is going to point RAM address,
1731          * Make sure IVOR15 has valid opcode to support debugger
1732          */
1733         mtspr   IVOR15,r0
1734
1735         /*
1736          * Re-point the IVPR at RAM
1737          */
1738         mtspr   IVPR,r10
1739
1740         mtlr    r0
1741         blr                             /* NEVER RETURNS! */
1742         .globl  in_ram
1743 in_ram:
1744
1745         /*
1746          * Relocation Function, r12 point to got2+0x8000
1747          *
1748          * Adjust got2 pointers, no need to check for 0, this code
1749          * already puts a few entries in the table.
1750          */
1751         li      r0,__got2_entries@sectoff@l
1752         la      r3,GOT(_GOT2_TABLE_)
1753         lwz     r11,GOT(_GOT2_TABLE_)
1754         mtctr   r0
1755         sub     r11,r3,r11
1756         addi    r3,r3,-4
1757 1:      lwzu    r0,4(r3)
1758         cmpwi   r0,0
1759         beq-    2f
1760         add     r0,r0,r11
1761         stw     r0,0(r3)
1762 2:      bdnz    1b
1763
1764         /*
1765          * Now adjust the fixups and the pointers to the fixups
1766          * in case we need to move ourselves again.
1767          */
1768         li      r0,__fixup_entries@sectoff@l
1769         lwz     r3,GOT(_FIXUP_TABLE_)
1770         cmpwi   r0,0
1771         mtctr   r0
1772         addi    r3,r3,-4
1773         beq     4f
1774 3:      lwzu    r4,4(r3)
1775         lwzux   r0,r4,r11
1776         cmpwi   r0,0
1777         add     r0,r0,r11
1778         stw     r4,0(r3)
1779         beq-    5f
1780         stw     r0,0(r4)
1781 5:      bdnz    3b
1782 4:
1783 clear_bss:
1784         /*
1785          * Now clear BSS segment
1786          */
1787         lwz     r3,GOT(__bss_start)
1788         lwz     r4,GOT(__bss_end)
1789
1790         cmplw   0,r3,r4
1791         beq     6f
1792
1793         li      r0,0
1794 5:
1795         stw     r0,0(r3)
1796         addi    r3,r3,4
1797         cmplw   0,r3,r4
1798         bne     5b
1799 6:
1800
1801         mr      r3,r9           /* Init Data pointer            */
1802         mr      r4,r10          /* Destination Address          */
1803         bl      board_init_r
1804
1805 #ifndef MINIMAL_SPL
1806         /*
1807          * Copy exception vector code to low memory
1808          *
1809          * r3: dest_addr
1810          * r7: source address, r8: end address, r9: target address
1811          */
1812         .globl  trap_init
1813 trap_init:
1814         mflr    r4                      /* save link register           */
1815         GET_GOT
1816         lwz     r7,GOT(_start_of_vectors)
1817         lwz     r8,GOT(_end_of_vectors)
1818
1819         li      r9,0x100                /* reset vector always at 0x100 */
1820
1821         cmplw   0,r7,r8
1822         bgelr                           /* return if r7>=r8 - just in case */
1823 1:
1824         lwz     r0,0(r7)
1825         stw     r0,0(r9)
1826         addi    r7,r7,4
1827         addi    r9,r9,4
1828         cmplw   0,r7,r8
1829         bne     1b
1830
1831         /*
1832          * relocate `hdlr' and `int_return' entries
1833          */
1834         li      r7,.L_CriticalInput - _start + _START_OFFSET
1835         bl      trap_reloc
1836         li      r7,.L_MachineCheck - _start + _START_OFFSET
1837         bl      trap_reloc
1838         li      r7,.L_DataStorage - _start + _START_OFFSET
1839         bl      trap_reloc
1840         li      r7,.L_InstStorage - _start + _START_OFFSET
1841         bl      trap_reloc
1842         li      r7,.L_ExtInterrupt - _start + _START_OFFSET
1843         bl      trap_reloc
1844         li      r7,.L_Alignment - _start + _START_OFFSET
1845         bl      trap_reloc
1846         li      r7,.L_ProgramCheck - _start + _START_OFFSET
1847         bl      trap_reloc
1848         li      r7,.L_FPUnavailable - _start + _START_OFFSET
1849         bl      trap_reloc
1850         li      r7,.L_Decrementer - _start + _START_OFFSET
1851         bl      trap_reloc
1852         li      r7,.L_IntervalTimer - _start + _START_OFFSET
1853         li      r8,_end_of_vectors - _start + _START_OFFSET
1854 2:
1855         bl      trap_reloc
1856         addi    r7,r7,0x100             /* next exception vector        */
1857         cmplw   0,r7,r8
1858         blt     2b
1859
1860         /* Update IVORs as per relocated vector table address */
1861         li      r7,0x0100
1862         mtspr   IVOR0,r7        /* 0: Critical input */
1863         li      r7,0x0200
1864         mtspr   IVOR1,r7        /* 1: Machine check */
1865         li      r7,0x0300
1866         mtspr   IVOR2,r7        /* 2: Data storage */
1867         li      r7,0x0400
1868         mtspr   IVOR3,r7        /* 3: Instruction storage */
1869         li      r7,0x0500
1870         mtspr   IVOR4,r7        /* 4: External interrupt */
1871         li      r7,0x0600
1872         mtspr   IVOR5,r7        /* 5: Alignment */
1873         li      r7,0x0700
1874         mtspr   IVOR6,r7        /* 6: Program check */
1875         li      r7,0x0800
1876         mtspr   IVOR7,r7        /* 7: floating point unavailable */
1877         li      r7,0x0900
1878         mtspr   IVOR8,r7        /* 8: System call */
1879         /* 9: Auxiliary processor unavailable(unsupported) */
1880         li      r7,0x0a00
1881         mtspr   IVOR10,r7       /* 10: Decrementer */
1882         li      r7,0x0b00
1883         mtspr   IVOR11,r7       /* 11: Interval timer */
1884         li      r7,0x0c00
1885         mtspr   IVOR12,r7       /* 12: Watchdog timer */
1886         li      r7,0x0d00
1887         mtspr   IVOR13,r7       /* 13: Data TLB error */
1888         li      r7,0x0e00
1889         mtspr   IVOR14,r7       /* 14: Instruction TLB error */
1890         li      r7,0x0f00
1891         mtspr   IVOR15,r7       /* 15: Debug */
1892
1893         lis     r7,0x0
1894         mtspr   IVPR,r7
1895
1896         mtlr    r4                      /* restore link register        */
1897         blr
1898
1899 .globl unlock_ram_in_cache
1900 unlock_ram_in_cache:
1901         /* invalidate the INIT_RAM section */
1902         lis     r3,(CONFIG_SYS_INIT_RAM_ADDR & ~(CONFIG_SYS_CACHELINE_SIZE-1))@h
1903         ori     r3,r3,(CONFIG_SYS_INIT_RAM_ADDR & ~(CONFIG_SYS_CACHELINE_SIZE-1))@l
1904         mfspr   r4,L1CFG0
1905         andi.   r4,r4,0x1ff
1906         slwi    r4,r4,(10 - 1 - L1_CACHE_SHIFT)
1907         mtctr   r4
1908 1:      dcbi    r0,r3
1909         dcblc   r0,r3
1910         addi    r3,r3,CONFIG_SYS_CACHELINE_SIZE
1911         bdnz    1b
1912         sync
1913
1914         /* Invalidate the TLB entries for the cache */
1915         lis     r3,CONFIG_SYS_INIT_RAM_ADDR@h
1916         ori     r3,r3,CONFIG_SYS_INIT_RAM_ADDR@l
1917         tlbivax 0,r3
1918         addi    r3,r3,0x1000
1919         tlbivax 0,r3
1920         addi    r3,r3,0x1000
1921         tlbivax 0,r3
1922         addi    r3,r3,0x1000
1923         tlbivax 0,r3
1924         isync
1925         blr
1926
1927 .globl flush_dcache
1928 flush_dcache:
1929         mfspr   r3,SPRN_L1CFG0
1930
1931         rlwinm  r5,r3,9,3       /* Extract cache block size */
1932         twlgti  r5,1            /* Only 32 and 64 byte cache blocks
1933                                  * are currently defined.
1934                                  */
1935         li      r4,32
1936         subfic  r6,r5,2         /* r6 = log2(1KiB / cache block size) -
1937                                  *      log2(number of ways)
1938                                  */
1939         slw     r5,r4,r5        /* r5 = cache block size */
1940
1941         rlwinm  r7,r3,0,0xff    /* Extract number of KiB in the cache */
1942         mulli   r7,r7,13        /* An 8-way cache will require 13
1943                                  * loads per set.
1944                                  */
1945         slw     r7,r7,r6
1946
1947         /* save off HID0 and set DCFA */
1948         mfspr   r8,SPRN_HID0
1949         ori     r9,r8,HID0_DCFA@l
1950         mtspr   SPRN_HID0,r9
1951         isync
1952
1953         lis     r4,0
1954         mtctr   r7
1955
1956 1:      lwz     r3,0(r4)        /* Load... */
1957         add     r4,r4,r5
1958         bdnz    1b
1959
1960         msync
1961         lis     r4,0
1962         mtctr   r7
1963
1964 1:      dcbf    0,r4            /* ...and flush. */
1965         add     r4,r4,r5
1966         bdnz    1b
1967
1968         /* restore HID0 */
1969         mtspr   SPRN_HID0,r8
1970         isync
1971
1972         blr
1973
1974 .globl setup_ivors
1975 setup_ivors:
1976
1977 #include "fixed_ivor.S"
1978         blr
1979 #endif /* !MINIMAL_SPL */