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