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