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