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