xref: /openbmc/u-boot/arch/powerpc/cpu/mpc86xx/start.S (revision 3765b3e7)
1/*
2 * Copyright 2004, 2007, 2011 Freescale Semiconductor.
3 * Srikanth Srinivasan <srikanth.srinivaan@freescale.com>
4 *
5 * SPDX-License-Identifier:	GPL-2.0+
6 */
7
8/*  U-Boot - Startup Code for 86xx PowerPC based Embedded Boards
9 *
10 *
11 *  The processor starts at 0xfff00100 and the code is executed
12 *  from flash. The code is organized to be at an other address
13 *  in memory, but as long we don't jump around before relocating.
14 *  board_init lies at a quite high address and when the cpu has
15 *  jumped there, everything is ok.
16 */
17#include <asm-offsets.h>
18#include <config.h>
19#include <mpc86xx.h>
20#include <version.h>
21
22#include <ppc_asm.tmpl>
23#include <ppc_defs.h>
24
25#include <asm/cache.h>
26#include <asm/mmu.h>
27#include <asm/u-boot.h>
28
29/*
30 * Need MSR_DR | MSR_IR enabled to access I/O (printf) in exceptions
31 */
32
33/*
34 * Set up GOT: Global Offset Table
35 *
36 * Use r12 to access the GOT
37 */
38	START_GOT
39	GOT_ENTRY(_GOT2_TABLE_)
40	GOT_ENTRY(_FIXUP_TABLE_)
41
42	GOT_ENTRY(_start)
43	GOT_ENTRY(_start_of_vectors)
44	GOT_ENTRY(_end_of_vectors)
45	GOT_ENTRY(transfer_to_handler)
46
47	GOT_ENTRY(__init_end)
48	GOT_ENTRY(__bss_end)
49	GOT_ENTRY(__bss_start)
50	END_GOT
51
52/*
53 * r3 - 1st arg to board_init(): IMMP pointer
54 * r4 - 2nd arg to board_init(): boot flag
55 */
56	.text
57	.long	0x27051956		/* U-Boot Magic Number */
58	.globl	version_string
59version_string:
60	.ascii U_BOOT_VERSION_STRING, "\0"
61
62	. = EXC_OFF_SYS_RESET
63	.globl	_start
64_start:
65	b	boot_cold
66
67	/* the boot code is located below the exception table */
68
69	.globl	_start_of_vectors
70_start_of_vectors:
71
72/* Machine check */
73	STD_EXCEPTION(0x200, MachineCheck, MachineCheckException)
74
75/* Data Storage exception. */
76	STD_EXCEPTION(0x300, DataStorage, UnknownException)
77
78/* Instruction Storage exception. */
79	STD_EXCEPTION(0x400, InstStorage, UnknownException)
80
81/* External Interrupt exception. */
82	STD_EXCEPTION(0x500, ExtInterrupt, external_interrupt)
83
84/* Alignment exception. */
85	. = 0x600
86Alignment:
87	EXCEPTION_PROLOG(SRR0, SRR1)
88	mfspr	r4,DAR
89	stw	r4,_DAR(r21)
90	mfspr	r5,DSISR
91	stw	r5,_DSISR(r21)
92	addi	r3,r1,STACK_FRAME_OVERHEAD
93	EXC_XFER_TEMPLATE(Alignment, AlignmentException, MSR_KERNEL, COPY_EE)
94
95/* Program check exception */
96	. = 0x700
97ProgramCheck:
98	EXCEPTION_PROLOG(SRR0, SRR1)
99	addi	r3,r1,STACK_FRAME_OVERHEAD
100	EXC_XFER_TEMPLATE(ProgramCheck, ProgramCheckException,
101		MSR_KERNEL, COPY_EE)
102
103	STD_EXCEPTION(0x800, FPUnavailable, UnknownException)
104
105	/* I guess we could implement decrementer, and may have
106	 * to someday for timekeeping.
107	 */
108	STD_EXCEPTION(0x900, Decrementer, timer_interrupt)
109	STD_EXCEPTION(0xa00, Trap_0a, UnknownException)
110	STD_EXCEPTION(0xb00, Trap_0b, UnknownException)
111	STD_EXCEPTION(0xc00, SystemCall, UnknownException)
112	STD_EXCEPTION(0xd00, SingleStep, UnknownException)
113	STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
114	STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
115	STD_EXCEPTION(0x1000, SoftEmu, SoftEmuException)
116	STD_EXCEPTION(0x1100, InstructionTLBMiss, UnknownException)
117	STD_EXCEPTION(0x1200, DataTLBMiss, UnknownException)
118	STD_EXCEPTION(0x1300, InstructionTLBError, UnknownException)
119	STD_EXCEPTION(0x1400, DataTLBError, UnknownException)
120	STD_EXCEPTION(0x1500, Reserved5, UnknownException)
121	STD_EXCEPTION(0x1600, Reserved6, UnknownException)
122	STD_EXCEPTION(0x1700, Reserved7, UnknownException)
123	STD_EXCEPTION(0x1800, Reserved8, UnknownException)
124	STD_EXCEPTION(0x1900, Reserved9, UnknownException)
125	STD_EXCEPTION(0x1a00, ReservedA, UnknownException)
126	STD_EXCEPTION(0x1b00, ReservedB, UnknownException)
127	STD_EXCEPTION(0x1c00, DataBreakpoint, UnknownException)
128	STD_EXCEPTION(0x1d00, InstructionBreakpoint, UnknownException)
129	STD_EXCEPTION(0x1e00, PeripheralBreakpoint, UnknownException)
130	STD_EXCEPTION(0x1f00, DevPortBreakpoint, UnknownException)
131
132	.globl	_end_of_vectors
133_end_of_vectors:
134
135	. = 0x2000
136
137boot_cold:
138	/*
139	 * NOTE: Only Cpu 0 will ever come here.  Other cores go to an
140	 * address specified by the BPTR
141	 */
1421:
143#ifdef CONFIG_SYS_RAMBOOT
144	/* disable everything */
145	li	r0, 0
146	mtspr	HID0, r0
147	sync
148	mtmsr	0
149#endif
150
151	/* Invalidate BATs */
152	bl	invalidate_bats
153	sync
154	/* Invalidate all of TLB before MMU turn on */
155	bl      clear_tlbs
156	sync
157
158#ifdef CONFIG_SYS_L2
159	/* init the L2 cache */
160	lis	r3, L2_INIT@h
161	ori	r3, r3, L2_INIT@l
162	mtspr	l2cr, r3
163	/* invalidate the L2 cache */
164	bl	l2cache_invalidate
165	sync
166#endif
167
168	/*
169	 * Calculate absolute address in FLASH and jump there
170	 *------------------------------------------------------*/
171	lis	r3, CONFIG_SYS_MONITOR_BASE_EARLY@h
172	ori	r3, r3, CONFIG_SYS_MONITOR_BASE_EARLY@l
173	addi	r3, r3, in_flash - _start + EXC_OFF_SYS_RESET
174	mtlr	r3
175	blr
176
177in_flash:
178	/* let the C-code set up the rest			*/
179	/*							*/
180	/* Be careful to keep code relocatable !		*/
181	/*------------------------------------------------------*/
182	/* perform low-level init */
183
184	/* enable extended addressing */
185	bl	enable_ext_addr
186
187	/* setup the bats */
188	bl	early_bats
189
190	/*
191	 * Cache must be enabled here for stack-in-cache trick.
192	 * This means we need to enable the BATS.
193	 * Cache should be turned on after BATs, since by default
194	 * everything is write-through.
195	 */
196
197	/* enable address translation */
198	mfmsr	r5
199	ori	r5, r5, (MSR_IR | MSR_DR)
200	lis	r3,addr_trans_enabled@h
201	ori	r3, r3, addr_trans_enabled@l
202	mtspr	SPRN_SRR0,r3
203	mtspr	SPRN_SRR1,r5
204	rfi
205
206addr_trans_enabled:
207	/* enable and invalidate the data cache */
208/*	bl	l1dcache_enable */
209	bl	dcache_enable
210	sync
211
212#if 1
213	bl	icache_enable
214#endif
215
216#ifdef CONFIG_SYS_INIT_RAM_LOCK
217	bl	lock_ram_in_cache
218	sync
219#endif
220
221#if (CONFIG_SYS_CCSRBAR_DEFAULT != CONFIG_SYS_CCSRBAR)
222	bl      setup_ccsrbar
223#endif
224
225	/* set up the stack pointer in our newly created
226	 * cache-ram (r1) */
227	lis	r1, (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET)@h
228	ori	r1, r1, (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET)@l
229
230	li	r0, 0		/* Make room for stack frame header and */
231	stwu	r0, -4(r1)	/* clear final stack frame so that	*/
232	stwu	r0, -4(r1)	/* stack backtraces terminate cleanly	*/
233
234	GET_GOT			/* initialize GOT access	*/
235
236	/* run low-level CPU init code	   (from Flash) */
237	bl	cpu_init_f
238	sync
239
240#ifdef	RUN_DIAG
241
242	/* Load PX_AUX register address in r4 */
243	lis	r4, PIXIS_BASE@h
244	ori	r4, r4, 0x6
245	/* Load contents of PX_AUX in r3 bits 24 to 31*/
246	lbz	r3, 0(r4)
247
248	/* Mask and obtain the bit in r3 */
249	rlwinm. r3, r3, 0, 24, 24
250	/* If not zero, jump and continue with u-boot */
251	bne	diag_done
252
253	/* Load back contents of PX_AUX in r3 bits 24 to 31 */
254	lbz	r3, 0(r4)
255	/* Set the MSB of the register value */
256	ori	r3, r3, 0x80
257	/* Write value in r3 back to PX_AUX */
258	stb	r3, 0(r4)
259
260	/* Get the address to jump to in r3*/
261	lis	r3, CONFIG_SYS_DIAG_ADDR@h
262	ori	r3, r3, CONFIG_SYS_DIAG_ADDR@l
263
264	/* Load the LR with the branch address */
265	mtlr	r3
266
267	/* Branch to diagnostic */
268	blr
269
270diag_done:
271#endif
272
273/*	bl	l2cache_enable */
274
275	/* run 1st part of board init code (from Flash)	  */
276	bl	board_init_f
277	sync
278
279	/* NOTREACHED - board_init_f() does not return */
280
281	.globl	invalidate_bats
282invalidate_bats:
283
284	li	r0, 0
285	/* invalidate BATs */
286	mtspr	IBAT0U, r0
287	mtspr	IBAT1U, r0
288	mtspr	IBAT2U, r0
289	mtspr	IBAT3U, r0
290	mtspr	IBAT4U, r0
291	mtspr	IBAT5U, r0
292	mtspr	IBAT6U, r0
293	mtspr	IBAT7U, r0
294
295	isync
296	mtspr	DBAT0U, r0
297	mtspr	DBAT1U, r0
298	mtspr	DBAT2U, r0
299	mtspr	DBAT3U, r0
300	mtspr	DBAT4U, r0
301	mtspr	DBAT5U, r0
302	mtspr	DBAT6U, r0
303	mtspr	DBAT7U, r0
304
305	isync
306	sync
307	blr
308
309#define CONFIG_BAT_PAIR(n) \
310	lis	r4, CONFIG_SYS_IBAT##n##L@h; 		\
311	ori	r4, r4, CONFIG_SYS_IBAT##n##L@l; 	\
312	lis	r3, CONFIG_SYS_IBAT##n##U@h; 		\
313	ori	r3, r3, CONFIG_SYS_IBAT##n##U@l; 	\
314	mtspr	IBAT##n##L, r4; 			\
315	mtspr	IBAT##n##U, r3; 			\
316	lis	r4, CONFIG_SYS_DBAT##n##L@h; 		\
317	ori	r4, r4, CONFIG_SYS_DBAT##n##L@l; 	\
318	lis	r3, CONFIG_SYS_DBAT##n##U@h; 		\
319	ori	r3, r3, CONFIG_SYS_DBAT##n##U@l; 	\
320	mtspr	DBAT##n##L, r4;				\
321	mtspr	DBAT##n##U, r3;
322
323/*
324 * setup_bats:
325 *
326 * Set up the final BAT registers now that setup is done.
327 *
328 * Assumes that:
329 *	1) Address translation is enabled upon entry
330 *	2) The boot rom is still accessible via 1:1 translation
331 */
332	.globl setup_bats
333setup_bats:
334	mflr	r5
335	sync
336
337	/*
338	 * When we disable address translation, we will get 1:1 (VA==PA)
339	 * translation.  The only place we know for sure is safe for that is
340	 * the bootrom where we originally started out.  Pop back into there.
341	 */
342	lis	r4, CONFIG_SYS_MONITOR_BASE_EARLY@h
343	ori	r4, r4, CONFIG_SYS_MONITOR_BASE_EARLY@l
344	addi	r4, r4, trans_disabled - _start + EXC_OFF_SYS_RESET
345
346	/* disable address translation */
347	mfmsr	r3
348	rlwinm	r3, r3, 0, 28, 25
349	mtspr	SRR0, r4
350	mtspr	SRR1, r3
351	rfi
352
353trans_disabled:
354#if defined(CONFIG_SYS_DBAT0U) && defined(CONFIG_SYS_DBAT0L) \
355	&& defined(CONFIG_SYS_IBAT0U) && defined(CONFIG_SYS_IBAT0L)
356	CONFIG_BAT_PAIR(0)
357#endif
358	CONFIG_BAT_PAIR(1)
359	CONFIG_BAT_PAIR(2)
360	CONFIG_BAT_PAIR(3)
361	CONFIG_BAT_PAIR(4)
362	CONFIG_BAT_PAIR(5)
363	CONFIG_BAT_PAIR(6)
364	CONFIG_BAT_PAIR(7)
365
366	sync
367	isync
368
369	/* Turn translation back on and return */
370	mfmsr	r3
371	ori	r3, r3, (MSR_IR | MSR_DR)
372	mtspr	SPRN_SRR0,r5
373	mtspr	SPRN_SRR1,r3
374	rfi
375
376/*
377 * early_bats:
378 *
379 * Set up bats needed early on - this is usually the BAT for the
380 * stack-in-cache, the Flash, and CCSR space
381 */
382	.globl  early_bats
383early_bats:
384	/* IBAT 3 */
385	lis	r4, CONFIG_SYS_IBAT3L@h
386	ori     r4, r4, CONFIG_SYS_IBAT3L@l
387	lis	r3, CONFIG_SYS_IBAT3U@h
388	ori     r3, r3, CONFIG_SYS_IBAT3U@l
389	mtspr   IBAT3L, r4
390	mtspr   IBAT3U, r3
391	isync
392
393	/* DBAT 3 */
394	lis	r4, CONFIG_SYS_DBAT3L@h
395	ori     r4, r4, CONFIG_SYS_DBAT3L@l
396	lis	r3, CONFIG_SYS_DBAT3U@h
397	ori     r3, r3, CONFIG_SYS_DBAT3U@l
398	mtspr   DBAT3L, r4
399	mtspr   DBAT3U, r3
400	isync
401
402	/* IBAT 5 */
403	lis	r4, CONFIG_SYS_IBAT5L@h
404	ori     r4, r4, CONFIG_SYS_IBAT5L@l
405	lis	r3, CONFIG_SYS_IBAT5U@h
406	ori     r3, r3, CONFIG_SYS_IBAT5U@l
407	mtspr   IBAT5L, r4
408	mtspr   IBAT5U, r3
409	isync
410
411	/* DBAT 5 */
412	lis	r4, CONFIG_SYS_DBAT5L@h
413	ori     r4, r4, CONFIG_SYS_DBAT5L@l
414	lis	r3, CONFIG_SYS_DBAT5U@h
415	ori     r3, r3, CONFIG_SYS_DBAT5U@l
416	mtspr   DBAT5L, r4
417	mtspr   DBAT5U, r3
418	isync
419
420	/* IBAT 6 */
421	lis	r4, CONFIG_SYS_IBAT6L_EARLY@h
422	ori     r4, r4, CONFIG_SYS_IBAT6L_EARLY@l
423	lis	r3, CONFIG_SYS_IBAT6U_EARLY@h
424	ori     r3, r3, CONFIG_SYS_IBAT6U_EARLY@l
425	mtspr   IBAT6L, r4
426	mtspr   IBAT6U, r3
427	isync
428
429	/* DBAT 6 */
430	lis	r4, CONFIG_SYS_DBAT6L_EARLY@h
431	ori     r4, r4, CONFIG_SYS_DBAT6L_EARLY@l
432	lis	r3, CONFIG_SYS_DBAT6U_EARLY@h
433	ori     r3, r3, CONFIG_SYS_DBAT6U_EARLY@l
434	mtspr   DBAT6L, r4
435	mtspr   DBAT6U, r3
436	isync
437
438#if(CONFIG_SYS_CCSRBAR_DEFAULT != CONFIG_SYS_CCSRBAR)
439	/* IBAT 7 */
440	lis	r4, CONFIG_SYS_CCSR_DEFAULT_IBATL@h
441	ori     r4, r4, CONFIG_SYS_CCSR_DEFAULT_IBATL@l
442	lis	r3, CONFIG_SYS_CCSR_DEFAULT_IBATU@h
443	ori     r3, r3, CONFIG_SYS_CCSR_DEFAULT_IBATU@l
444	mtspr   IBAT7L, r4
445	mtspr   IBAT7U, r3
446	isync
447
448	/* DBAT 7 */
449	lis	r4, CONFIG_SYS_CCSR_DEFAULT_DBATL@h
450	ori     r4, r4, CONFIG_SYS_CCSR_DEFAULT_DBATL@l
451	lis	r3, CONFIG_SYS_CCSR_DEFAULT_DBATU@h
452	ori     r3, r3, CONFIG_SYS_CCSR_DEFAULT_DBATU@l
453	mtspr   DBAT7L, r4
454	mtspr   DBAT7U, r3
455	isync
456#endif
457	blr
458
459	.globl clear_tlbs
460clear_tlbs:
461	addis   r3, 0, 0x0000
462	addis   r5, 0, 0x4
463	isync
464tlblp:
465	tlbie   r3
466	sync
467	addi    r3, r3, 0x1000
468	cmp     0, 0, r3, r5
469	blt tlblp
470	blr
471
472	.globl disable_addr_trans
473disable_addr_trans:
474	/* disable address translation */
475	mflr	r4
476	mfmsr	r3
477	andi.	r0, r3, (MSR_IR | MSR_DR)
478	beqlr
479	andc	r3, r3, r0
480	mtspr	SRR0, r4
481	mtspr	SRR1, r3
482	rfi
483
484/*
485 * This code finishes saving the registers to the exception frame
486 * and jumps to the appropriate handler for the exception.
487 * Register r21 is pointer into trap frame, r1 has new stack pointer.
488 */
489	.globl	transfer_to_handler
490transfer_to_handler:
491	stw	r22,_NIP(r21)
492	lis	r22,MSR_POW@h
493	andc	r23,r23,r22
494	stw	r23,_MSR(r21)
495	SAVE_GPR(7, r21)
496	SAVE_4GPRS(8, r21)
497	SAVE_8GPRS(12, r21)
498	SAVE_8GPRS(24, r21)
499	mflr	r23
500	andi.	r24,r23,0x3f00		/* get vector offset */
501	stw	r24,TRAP(r21)
502	li	r22,0
503	stw	r22,RESULT(r21)
504	mtspr	SPRG2,r22		/* r1 is now kernel sp */
505	lwz	r24,0(r23)		/* virtual address of handler */
506	lwz	r23,4(r23)		/* where to go when done */
507	mtspr	SRR0,r24
508	mtspr	SRR1,r20
509	mtlr	r23
510	SYNC
511	rfi				/* jump to handler, enable MMU */
512
513int_return:
514	mfmsr	r28		/* Disable interrupts */
515	li	r4,0
516	ori	r4,r4,MSR_EE
517	andc	r28,r28,r4
518	SYNC			/* Some chip revs need this... */
519	mtmsr	r28
520	SYNC
521	lwz	r2,_CTR(r1)
522	lwz	r0,_LINK(r1)
523	mtctr	r2
524	mtlr	r0
525	lwz	r2,_XER(r1)
526	lwz	r0,_CCR(r1)
527	mtspr	XER,r2
528	mtcrf	0xFF,r0
529	REST_10GPRS(3, r1)
530	REST_10GPRS(13, r1)
531	REST_8GPRS(23, r1)
532	REST_GPR(31, r1)
533	lwz	r2,_NIP(r1)	/* Restore environment */
534	lwz	r0,_MSR(r1)
535	mtspr	SRR0,r2
536	mtspr	SRR1,r0
537	lwz	r0,GPR0(r1)
538	lwz	r2,GPR2(r1)
539	lwz	r1,GPR1(r1)
540	SYNC
541	rfi
542
543	.globl	dc_read
544dc_read:
545	blr
546
547	.globl get_pvr
548get_pvr:
549	mfspr	r3, PVR
550	blr
551
552	.globl get_svr
553get_svr:
554	mfspr	r3, SVR
555	blr
556
557
558/*
559 * Function:	in8
560 * Description:	Input 8 bits
561 */
562	.globl	in8
563in8:
564	lbz	r3,0x0000(r3)
565	blr
566
567/*
568 * Function:	out8
569 * Description:	Output 8 bits
570 */
571	.globl	out8
572out8:
573	stb	r4,0x0000(r3)
574	blr
575
576/*
577 * Function:	out16
578 * Description:	Output 16 bits
579 */
580	.globl	out16
581out16:
582	sth	r4,0x0000(r3)
583	blr
584
585/*
586 * Function:	out16r
587 * Description:	Byte reverse and output 16 bits
588 */
589	.globl	out16r
590out16r:
591	sthbrx	r4,r0,r3
592	blr
593
594/*
595 * Function:	out32
596 * Description:	Output 32 bits
597 */
598	.globl	out32
599out32:
600	stw	r4,0x0000(r3)
601	blr
602
603/*
604 * Function:	out32r
605 * Description:	Byte reverse and output 32 bits
606 */
607	.globl	out32r
608out32r:
609	stwbrx	r4,r0,r3
610	blr
611
612/*
613 * Function:	in16
614 * Description:	Input 16 bits
615 */
616	.globl	in16
617in16:
618	lhz	r3,0x0000(r3)
619	blr
620
621/*
622 * Function:	in16r
623 * Description:	Input 16 bits and byte reverse
624 */
625	.globl	in16r
626in16r:
627	lhbrx	r3,r0,r3
628	blr
629
630/*
631 * Function:	in32
632 * Description:	Input 32 bits
633 */
634	.globl	in32
635in32:
636	lwz	3,0x0000(3)
637	blr
638
639/*
640 * Function:	in32r
641 * Description:	Input 32 bits and byte reverse
642 */
643	.globl	in32r
644in32r:
645	lwbrx	r3,r0,r3
646	blr
647
648/*
649 * void relocate_code (addr_sp, gd, addr_moni)
650 *
651 * This "function" does not return, instead it continues in RAM
652 * after relocating the monitor code.
653 *
654 * r3 = dest
655 * r4 = src
656 * r5 = length in bytes
657 * r6 = cachelinesize
658 */
659	.globl	relocate_code
660relocate_code:
661
662	mr	r1,  r3		/* Set new stack pointer		*/
663	mr	r9,  r4		/* Save copy of Global Data pointer	*/
664	mr	r10, r5		/* Save copy of Destination Address	*/
665
666	GET_GOT
667	mr	r3,  r5				/* Destination Address	*/
668	lis	r4, CONFIG_SYS_MONITOR_BASE@h		/* Source      Address	*/
669	ori	r4, r4, CONFIG_SYS_MONITOR_BASE@l
670	lwz	r5, GOT(__init_end)
671	sub	r5, r5, r4
672	li	r6, CONFIG_SYS_CACHELINE_SIZE		/* Cache Line Size	*/
673
674	/*
675	 * Fix GOT pointer:
676	 *
677	 * New GOT-PTR = (old GOT-PTR - CONFIG_SYS_MONITOR_BASE) + Destination Address
678	 *
679	 * Offset:
680	 */
681	sub	r15, r10, r4
682
683	/* First our own GOT */
684	add	r12, r12, r15
685	/* then the one used by the C code */
686	add	r30, r30, r15
687
688	/*
689	 * Now relocate code
690	 */
691	cmplw	cr1,r3,r4
692	addi	r0,r5,3
693	srwi.	r0,r0,2
694	beq	cr1,4f		/* In place copy is not necessary	*/
695	beq	7f		/* Protect against 0 count		*/
696	mtctr	r0
697	bge	cr1,2f
698
699	la	r8,-4(r4)
700	la	r7,-4(r3)
7011:	lwzu	r0,4(r8)
702	stwu	r0,4(r7)
703	bdnz	1b
704	b	4f
705
7062:	slwi	r0,r0,2
707	add	r8,r4,r0
708	add	r7,r3,r0
7093:	lwzu	r0,-4(r8)
710	stwu	r0,-4(r7)
711	bdnz	3b
712/*
713 * Now flush the cache: note that we must start from a cache aligned
714 * address. Otherwise we might miss one cache line.
715 */
7164:	cmpwi	r6,0
717	add	r5,r3,r5
718	beq	7f		/* Always flush prefetch queue in any case */
719	subi	r0,r6,1
720	andc	r3,r3,r0
721	mr	r4,r3
7225:	dcbst	0,r4
723	add	r4,r4,r6
724	cmplw	r4,r5
725	blt	5b
726	sync			/* Wait for all dcbst to complete on bus */
727	mr	r4,r3
7286:	icbi	0,r4
729	add	r4,r4,r6
730	cmplw	r4,r5
731	blt	6b
7327:	sync			/* Wait for all icbi to complete on bus */
733	isync
734
735/*
736 * We are done. Do not return, instead branch to second part of board
737 * initialization, now running from RAM.
738 */
739	addi	r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
740	mtlr	r0
741	blr
742
743in_ram:
744	/*
745	 * Relocation Function, r12 point to got2+0x8000
746	 *
747	 * Adjust got2 pointers, no need to check for 0, this code
748	 * already puts a few entries in the table.
749	 */
750	li	r0,__got2_entries@sectoff@l
751	la	r3,GOT(_GOT2_TABLE_)
752	lwz	r11,GOT(_GOT2_TABLE_)
753	mtctr	r0
754	sub	r11,r3,r11
755	addi	r3,r3,-4
7561:	lwzu	r0,4(r3)
757	cmpwi	r0,0
758	beq-	2f
759	add	r0,r0,r11
760	stw	r0,0(r3)
7612:	bdnz	1b
762
763	/*
764	 * Now adjust the fixups and the pointers to the fixups
765	 * in case we need to move ourselves again.
766	 */
767	li	r0,__fixup_entries@sectoff@l
768	lwz	r3,GOT(_FIXUP_TABLE_)
769	cmpwi	r0,0
770	mtctr	r0
771	addi	r3,r3,-4
772	beq	4f
7733:	lwzu	r4,4(r3)
774	lwzux	r0,r4,r11
775	cmpwi	r0,0
776	add	r0,r0,r11
777	stw	r4,0(r3)
778	beq-	5f
779	stw	r0,0(r4)
7805:	bdnz	3b
7814:
782/* clear_bss: */
783	/*
784	 * Now clear BSS segment
785	 */
786	lwz	r3,GOT(__bss_start)
787	lwz	r4,GOT(__bss_end)
788
789	cmplw	0, r3, r4
790	beq	6f
791
792	li	r0, 0
7935:
794	stw	r0, 0(r3)
795	addi	r3, r3, 4
796	cmplw	0, r3, r4
797	bne	5b
7986:
799	mr	r3, r9		/* Init Date pointer		*/
800	mr	r4, r10		/* Destination Address		*/
801	bl	board_init_r
802
803	/* not reached - end relocate_code */
804/*-----------------------------------------------------------------------*/
805
806	/*
807	 * Copy exception vector code to low memory
808	 *
809	 * r3: dest_addr
810	 * r7: source address, r8: end address, r9: target address
811	 */
812	.globl	trap_init
813trap_init:
814	mflr	r4			/* save link register		*/
815	GET_GOT
816	lwz	r7, GOT(_start)
817	lwz	r8, GOT(_end_of_vectors)
818
819	li	r9, 0x100		/* reset vector always at 0x100 */
820
821	cmplw	0, r7, r8
822	bgelr				/* return if r7>=r8 - just in case */
8231:
824	lwz	r0, 0(r7)
825	stw	r0, 0(r9)
826	addi	r7, r7, 4
827	addi	r9, r9, 4
828	cmplw	0, r7, r8
829	bne	1b
830
831	/*
832	 * relocate `hdlr' and `int_return' entries
833	 */
834	li	r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
835	li	r8, Alignment - _start + EXC_OFF_SYS_RESET
8362:
837	bl	trap_reloc
838	addi	r7, r7, 0x100		/* next exception vector	*/
839	cmplw	0, r7, r8
840	blt	2b
841
842	li	r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
843	bl	trap_reloc
844
845	li	r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
846	bl	trap_reloc
847
848	li	r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
849	li	r8, SystemCall - _start + EXC_OFF_SYS_RESET
8503:
851	bl	trap_reloc
852	addi	r7, r7, 0x100		/* next exception vector	*/
853	cmplw	0, r7, r8
854	blt	3b
855
856	li	r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
857	li	r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
8584:
859	bl	trap_reloc
860	addi	r7, r7, 0x100		/* next exception vector	*/
861	cmplw	0, r7, r8
862	blt	4b
863
864	/* enable execptions from RAM vectors */
865	mfmsr	r7
866	li	r8,MSR_IP
867	andc	r7,r7,r8
868	ori	r7,r7,MSR_ME		/* Enable Machine Check */
869	mtmsr	r7
870
871	mtlr	r4			/* restore link register	*/
872	blr
873
874.globl enable_ext_addr
875enable_ext_addr:
876	mfspr	r0, HID0
877	lis	r0, (HID0_HIGH_BAT_EN | HID0_XBSEN | HID0_XAEN)@h
878	ori	r0, r0, (HID0_HIGH_BAT_EN | HID0_XBSEN | HID0_XAEN)@l
879	mtspr	HID0, r0
880	sync
881	isync
882	blr
883
884#if (CONFIG_SYS_CCSRBAR_DEFAULT != CONFIG_SYS_CCSRBAR)
885.globl setup_ccsrbar
886setup_ccsrbar:
887	/* Special sequence needed to update CCSRBAR itself */
888	lis	r4, CONFIG_SYS_CCSRBAR_DEFAULT@h
889	ori	r4, r4, CONFIG_SYS_CCSRBAR_DEFAULT@l
890
891	lis	r5, CONFIG_SYS_CCSRBAR_PHYS_LOW@h
892	ori	r5, r5, CONFIG_SYS_CCSRBAR_PHYS_LOW@l
893	srwi	r5,r5,12
894	li	r6, CONFIG_SYS_CCSRBAR_PHYS_HIGH@l
895	rlwimi	r5,r6,20,8,11
896	stw	r5, 0(r4) /* Store physical value of CCSR */
897	isync
898
899	lis	r5, CONFIG_SYS_TEXT_BASE@h
900	ori	r5,r5,CONFIG_SYS_TEXT_BASE@l
901	lwz	r5, 0(r5)
902	isync
903
904	/* Use VA of CCSR to do read */
905	lis	r3, CONFIG_SYS_CCSRBAR@h
906	lwz	r5, CONFIG_SYS_CCSRBAR@l(r3)
907	isync
908
909	blr
910#endif
911
912#ifdef CONFIG_SYS_INIT_RAM_LOCK
913lock_ram_in_cache:
914	/* Allocate Initial RAM in data cache.
915	 */
916	lis	r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@h
917	ori	r3, r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@l
918	li	r4, ((CONFIG_SYS_INIT_RAM_SIZE & ~31) + \
919		     (CONFIG_SYS_INIT_RAM_ADDR & 31) + 31) / 32
920	mtctr	r4
9211:
922	dcbz	r0, r3
923	addi	r3, r3, 32
924	bdnz	1b
925#if 1
926/* Lock the data cache */
927	mfspr	r0, HID0
928	ori	r0, r0, 0x1000
929	sync
930	mtspr	HID0, r0
931	sync
932	blr
933#endif
934#if 0
935	/* Lock the first way of the data cache */
936	mfspr	r0, LDSTCR
937	ori	r0, r0, 0x0080
938#if defined(CONFIG_ALTIVEC)
939	dssall
940#endif
941	sync
942	mtspr	LDSTCR, r0
943	sync
944	isync
945	blr
946#endif
947
948.globl unlock_ram_in_cache
949unlock_ram_in_cache:
950	/* invalidate the INIT_RAM section */
951	lis	r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@h
952	ori	r3, r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@l
953	li	r4, ((CONFIG_SYS_INIT_RAM_SIZE & ~31) + \
954		     (CONFIG_SYS_INIT_RAM_ADDR & 31) + 31) / 32
955	mtctr	r4
9561:	icbi	r0, r3
957	addi	r3, r3, 32
958	bdnz	1b
959	sync			/* Wait for all icbi to complete on bus */
960	isync
961#if 1
962/* Unlock the data cache and invalidate it */
963	mfspr	r0, HID0
964	li	r3,0x1000
965	andc	r0,r0,r3
966	li	r3,0x0400
967	or	r0,r0,r3
968	sync
969	mtspr	HID0, r0
970	sync
971	blr
972#endif
973#if 0
974	/* Unlock the first way of the data cache */
975	mfspr	r0, LDSTCR
976	li	r3,0x0080
977	andc	r0,r0,r3
978#ifdef CONFIG_ALTIVEC
979	dssall
980#endif
981	sync
982	mtspr	LDSTCR, r0
983	sync
984	isync
985	li	r3,0x0400
986	or	r0,r0,r3
987	sync
988	mtspr	HID0, r0
989	sync
990	blr
991#endif
992#endif
993