xref: /openbmc/u-boot/arch/powerpc/cpu/mpc86xx/start.S (revision f77d4410)
1/* SPDX-License-Identifier: GPL-2.0+ */
2/*
3 * Copyright 2004, 2007, 2011 Freescale Semiconductor.
4 * Srikanth Srinivasan <srikanth.srinivaan@freescale.com>
5 */
6
7/*  U-Boot - Startup Code for 86xx PowerPC based Embedded Boards
8 *
9 *
10 *  The processor starts at 0xfff00100 and the code is executed
11 *  from flash. The code is organized to be at an other address
12 *  in memory, but as long we don't jump around before relocating.
13 *  board_init lies at a quite high address and when the cpu has
14 *  jumped there, everything is ok.
15 */
16#include <asm-offsets.h>
17#include <config.h>
18#include <mpc86xx.h>
19#include <version.h>
20
21#include <ppc_asm.tmpl>
22#include <ppc_defs.h>
23
24#include <asm/cache.h>
25#include <asm/mmu.h>
26#include <asm/u-boot.h>
27
28/*
29 * Need MSR_DR | MSR_IR enabled to access I/O (printf) in exceptions
30 */
31
32/*
33 * Set up GOT: Global Offset Table
34 *
35 * Use r12 to access the GOT
36 */
37	START_GOT
38	GOT_ENTRY(_GOT2_TABLE_)
39	GOT_ENTRY(_FIXUP_TABLE_)
40
41	GOT_ENTRY(_start)
42	GOT_ENTRY(_start_of_vectors)
43	GOT_ENTRY(_end_of_vectors)
44	GOT_ENTRY(transfer_to_handler)
45
46	GOT_ENTRY(__init_end)
47	GOT_ENTRY(__bss_end)
48	GOT_ENTRY(__bss_start)
49	END_GOT
50
51/*
52 * r3 - 1st arg to board_init(): IMMP pointer
53 * r4 - 2nd arg to board_init(): boot flag
54 */
55	.text
56	.long	0x27051956		/* U-Boot Magic Number */
57	.globl	version_string
58version_string:
59	.ascii U_BOOT_VERSION_STRING, "\0"
60
61	. = EXC_OFF_SYS_RESET
62	.globl	_start
63_start:
64	b	boot_cold
65
66	/* the boot code is located below the exception table */
67
68	.globl	_start_of_vectors
69_start_of_vectors:
70
71/* Machine check */
72	STD_EXCEPTION(0x200, MachineCheck, MachineCheckException)
73
74/* Data Storage exception. */
75	STD_EXCEPTION(0x300, DataStorage, UnknownException)
76
77/* Instruction Storage exception. */
78	STD_EXCEPTION(0x400, InstStorage, UnknownException)
79
80/* External Interrupt exception. */
81	STD_EXCEPTION(0x500, ExtInterrupt, external_interrupt)
82
83/* Alignment exception. */
84	. = 0x600
85Alignment:
86	EXCEPTION_PROLOG(SRR0, SRR1)
87	mfspr	r4,DAR
88	stw	r4,_DAR(r21)
89	mfspr	r5,DSISR
90	stw	r5,_DSISR(r21)
91	addi	r3,r1,STACK_FRAME_OVERHEAD
92	EXC_XFER_TEMPLATE(Alignment, AlignmentException, MSR_KERNEL, COPY_EE)
93
94/* Program check exception */
95	. = 0x700
96ProgramCheck:
97	EXCEPTION_PROLOG(SRR0, SRR1)
98	addi	r3,r1,STACK_FRAME_OVERHEAD
99	EXC_XFER_TEMPLATE(ProgramCheck, ProgramCheckException,
100		MSR_KERNEL, COPY_EE)
101
102	STD_EXCEPTION(0x800, FPUnavailable, UnknownException)
103
104	/* I guess we could implement decrementer, and may have
105	 * to someday for timekeeping.
106	 */
107	STD_EXCEPTION(0x900, Decrementer, timer_interrupt)
108	STD_EXCEPTION(0xa00, Trap_0a, UnknownException)
109	STD_EXCEPTION(0xb00, Trap_0b, UnknownException)
110	STD_EXCEPTION(0xc00, SystemCall, UnknownException)
111	STD_EXCEPTION(0xd00, SingleStep, UnknownException)
112	STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
113	STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
114	STD_EXCEPTION(0x1000, SoftEmu, SoftEmuException)
115	STD_EXCEPTION(0x1100, InstructionTLBMiss, UnknownException)
116	STD_EXCEPTION(0x1200, DataTLBMiss, UnknownException)
117	STD_EXCEPTION(0x1300, InstructionTLBError, UnknownException)
118	STD_EXCEPTION(0x1400, DataTLBError, UnknownException)
119	STD_EXCEPTION(0x1500, Reserved5, UnknownException)
120	STD_EXCEPTION(0x1600, Reserved6, UnknownException)
121	STD_EXCEPTION(0x1700, Reserved7, UnknownException)
122	STD_EXCEPTION(0x1800, Reserved8, UnknownException)
123	STD_EXCEPTION(0x1900, Reserved9, UnknownException)
124	STD_EXCEPTION(0x1a00, ReservedA, UnknownException)
125	STD_EXCEPTION(0x1b00, ReservedB, UnknownException)
126	STD_EXCEPTION(0x1c00, DataBreakpoint, UnknownException)
127	STD_EXCEPTION(0x1d00, InstructionBreakpoint, UnknownException)
128	STD_EXCEPTION(0x1e00, PeripheralBreakpoint, UnknownException)
129	STD_EXCEPTION(0x1f00, DevPortBreakpoint, UnknownException)
130
131	.globl	_end_of_vectors
132_end_of_vectors:
133
134	. = 0x2000
135
136boot_cold:
137	/*
138	 * NOTE: Only Cpu 0 will ever come here.  Other cores go to an
139	 * address specified by the BPTR
140	 */
1411:
142#ifdef CONFIG_SYS_RAMBOOT
143	/* disable everything */
144	li	r0, 0
145	mtspr	HID0, r0
146	sync
147	mtmsr	0
148#endif
149
150	/* Invalidate BATs */
151	bl	invalidate_bats
152	sync
153	/* Invalidate all of TLB before MMU turn on */
154	bl      clear_tlbs
155	sync
156
157#ifdef CONFIG_SYS_L2
158	/* init the L2 cache */
159	lis	r3, L2_INIT@h
160	ori	r3, r3, L2_INIT@l
161	mtspr	l2cr, r3
162	/* invalidate the L2 cache */
163	bl	l2cache_invalidate
164	sync
165#endif
166
167	/*
168	 * Calculate absolute address in FLASH and jump there
169	 *------------------------------------------------------*/
170	lis	r3, CONFIG_SYS_MONITOR_BASE_EARLY@h
171	ori	r3, r3, CONFIG_SYS_MONITOR_BASE_EARLY@l
172	addi	r3, r3, in_flash - _start + EXC_OFF_SYS_RESET
173	mtlr	r3
174	blr
175
176in_flash:
177	/* let the C-code set up the rest			*/
178	/*							*/
179	/* Be careful to keep code relocatable !		*/
180	/*------------------------------------------------------*/
181	/* perform low-level init */
182
183	/* enable extended addressing */
184	bl	enable_ext_addr
185
186	/* setup the bats */
187	bl	early_bats
188
189	/*
190	 * Cache must be enabled here for stack-in-cache trick.
191	 * This means we need to enable the BATS.
192	 * Cache should be turned on after BATs, since by default
193	 * everything is write-through.
194	 */
195
196	/* enable address translation */
197	mfmsr	r5
198	ori	r5, r5, (MSR_IR | MSR_DR)
199	lis	r3,addr_trans_enabled@h
200	ori	r3, r3, addr_trans_enabled@l
201	mtspr	SPRN_SRR0,r3
202	mtspr	SPRN_SRR1,r5
203	rfi
204
205addr_trans_enabled:
206	/* enable and invalidate the data cache */
207/*	bl	l1dcache_enable */
208	bl	dcache_enable
209	sync
210
211#if 1
212	bl	icache_enable
213#endif
214
215#ifdef CONFIG_SYS_INIT_RAM_LOCK
216	bl	lock_ram_in_cache
217	sync
218#endif
219
220#if (CONFIG_SYS_CCSRBAR_DEFAULT != CONFIG_SYS_CCSRBAR)
221	bl      setup_ccsrbar
222#endif
223
224	/* set up the stack pointer in our newly created
225	 * cache-ram (r1) */
226	lis	r1, (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET)@h
227	ori	r1, r1, (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET)@l
228
229	li	r0, 0		/* Make room for stack frame header and */
230	stwu	r0, -4(r1)	/* clear final stack frame so that	*/
231	stwu	r0, -4(r1)	/* stack backtraces terminate cleanly	*/
232
233	GET_GOT			/* initialize GOT access	*/
234
235	/* run low-level CPU init code	   (from Flash) */
236	bl	cpu_init_f
237	sync
238
239#ifdef	RUN_DIAG
240
241	/* Load PX_AUX register address in r4 */
242	lis	r4, PIXIS_BASE@h
243	ori	r4, r4, 0x6
244	/* Load contents of PX_AUX in r3 bits 24 to 31*/
245	lbz	r3, 0(r4)
246
247	/* Mask and obtain the bit in r3 */
248	rlwinm. r3, r3, 0, 24, 24
249	/* If not zero, jump and continue with u-boot */
250	bne	diag_done
251
252	/* Load back contents of PX_AUX in r3 bits 24 to 31 */
253	lbz	r3, 0(r4)
254	/* Set the MSB of the register value */
255	ori	r3, r3, 0x80
256	/* Write value in r3 back to PX_AUX */
257	stb	r3, 0(r4)
258
259	/* Get the address to jump to in r3*/
260	lis	r3, CONFIG_SYS_DIAG_ADDR@h
261	ori	r3, r3, CONFIG_SYS_DIAG_ADDR@l
262
263	/* Load the LR with the branch address */
264	mtlr	r3
265
266	/* Branch to diagnostic */
267	blr
268
269diag_done:
270#endif
271
272/*	bl	l2cache_enable */
273
274	/* run 1st part of board init code (from Flash)	  */
275	li	r3, 0		/* clear boot_flag for calling board_init_f */
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
548/*
549 * Function:	in8
550 * Description:	Input 8 bits
551 */
552	.globl	in8
553in8:
554	lbz	r3,0x0000(r3)
555	blr
556
557/*
558 * Function:	out8
559 * Description:	Output 8 bits
560 */
561	.globl	out8
562out8:
563	stb	r4,0x0000(r3)
564	blr
565
566/*
567 * Function:	out16
568 * Description:	Output 16 bits
569 */
570	.globl	out16
571out16:
572	sth	r4,0x0000(r3)
573	blr
574
575/*
576 * Function:	out16r
577 * Description:	Byte reverse and output 16 bits
578 */
579	.globl	out16r
580out16r:
581	sthbrx	r4,r0,r3
582	blr
583
584/*
585 * Function:	out32
586 * Description:	Output 32 bits
587 */
588	.globl	out32
589out32:
590	stw	r4,0x0000(r3)
591	blr
592
593/*
594 * Function:	out32r
595 * Description:	Byte reverse and output 32 bits
596 */
597	.globl	out32r
598out32r:
599	stwbrx	r4,r0,r3
600	blr
601
602/*
603 * Function:	in16
604 * Description:	Input 16 bits
605 */
606	.globl	in16
607in16:
608	lhz	r3,0x0000(r3)
609	blr
610
611/*
612 * Function:	in16r
613 * Description:	Input 16 bits and byte reverse
614 */
615	.globl	in16r
616in16r:
617	lhbrx	r3,r0,r3
618	blr
619
620/*
621 * Function:	in32
622 * Description:	Input 32 bits
623 */
624	.globl	in32
625in32:
626	lwz	3,0x0000(3)
627	blr
628
629/*
630 * Function:	in32r
631 * Description:	Input 32 bits and byte reverse
632 */
633	.globl	in32r
634in32r:
635	lwbrx	r3,r0,r3
636	blr
637
638/*
639 * void relocate_code (addr_sp, gd, addr_moni)
640 *
641 * This "function" does not return, instead it continues in RAM
642 * after relocating the monitor code.
643 *
644 * r3 = dest
645 * r4 = src
646 * r5 = length in bytes
647 * r6 = cachelinesize
648 */
649	.globl	relocate_code
650relocate_code:
651
652	mr	r1,  r3		/* Set new stack pointer		*/
653	mr	r9,  r4		/* Save copy of Global Data pointer	*/
654	mr	r10, r5		/* Save copy of Destination Address	*/
655
656	GET_GOT
657	mr	r3,  r5				/* Destination Address	*/
658	lis	r4, CONFIG_SYS_MONITOR_BASE@h		/* Source      Address	*/
659	ori	r4, r4, CONFIG_SYS_MONITOR_BASE@l
660	lwz	r5, GOT(__init_end)
661	sub	r5, r5, r4
662	li	r6, CONFIG_SYS_CACHELINE_SIZE		/* Cache Line Size	*/
663
664	/*
665	 * Fix GOT pointer:
666	 *
667	 * New GOT-PTR = (old GOT-PTR - CONFIG_SYS_MONITOR_BASE) + Destination Address
668	 *
669	 * Offset:
670	 */
671	sub	r15, r10, r4
672
673	/* First our own GOT */
674	add	r12, r12, r15
675	/* then the one used by the C code */
676	add	r30, r30, r15
677
678	/*
679	 * Now relocate code
680	 */
681	cmplw	cr1,r3,r4
682	addi	r0,r5,3
683	srwi.	r0,r0,2
684	beq	cr1,4f		/* In place copy is not necessary	*/
685	beq	7f		/* Protect against 0 count		*/
686	mtctr	r0
687	bge	cr1,2f
688
689	la	r8,-4(r4)
690	la	r7,-4(r3)
6911:	lwzu	r0,4(r8)
692	stwu	r0,4(r7)
693	bdnz	1b
694	b	4f
695
6962:	slwi	r0,r0,2
697	add	r8,r4,r0
698	add	r7,r3,r0
6993:	lwzu	r0,-4(r8)
700	stwu	r0,-4(r7)
701	bdnz	3b
702/*
703 * Now flush the cache: note that we must start from a cache aligned
704 * address. Otherwise we might miss one cache line.
705 */
7064:	cmpwi	r6,0
707	add	r5,r3,r5
708	beq	7f		/* Always flush prefetch queue in any case */
709	subi	r0,r6,1
710	andc	r3,r3,r0
711	mr	r4,r3
7125:	dcbst	0,r4
713	add	r4,r4,r6
714	cmplw	r4,r5
715	blt	5b
716	sync			/* Wait for all dcbst to complete on bus */
717	mr	r4,r3
7186:	icbi	0,r4
719	add	r4,r4,r6
720	cmplw	r4,r5
721	blt	6b
7227:	sync			/* Wait for all icbi to complete on bus */
723	isync
724
725/*
726 * We are done. Do not return, instead branch to second part of board
727 * initialization, now running from RAM.
728 */
729	addi	r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
730	mtlr	r0
731	blr
732
733in_ram:
734	/*
735	 * Relocation Function, r12 point to got2+0x8000
736	 *
737	 * Adjust got2 pointers, no need to check for 0, this code
738	 * already puts a few entries in the table.
739	 */
740	li	r0,__got2_entries@sectoff@l
741	la	r3,GOT(_GOT2_TABLE_)
742	lwz	r11,GOT(_GOT2_TABLE_)
743	mtctr	r0
744	sub	r11,r3,r11
745	addi	r3,r3,-4
7461:	lwzu	r0,4(r3)
747	cmpwi	r0,0
748	beq-	2f
749	add	r0,r0,r11
750	stw	r0,0(r3)
7512:	bdnz	1b
752
753	/*
754	 * Now adjust the fixups and the pointers to the fixups
755	 * in case we need to move ourselves again.
756	 */
757	li	r0,__fixup_entries@sectoff@l
758	lwz	r3,GOT(_FIXUP_TABLE_)
759	cmpwi	r0,0
760	mtctr	r0
761	addi	r3,r3,-4
762	beq	4f
7633:	lwzu	r4,4(r3)
764	lwzux	r0,r4,r11
765	cmpwi	r0,0
766	add	r0,r0,r11
767	stw	r4,0(r3)
768	beq-	5f
769	stw	r0,0(r4)
7705:	bdnz	3b
7714:
772/* clear_bss: */
773	/*
774	 * Now clear BSS segment
775	 */
776	lwz	r3,GOT(__bss_start)
777	lwz	r4,GOT(__bss_end)
778
779	cmplw	0, r3, r4
780	beq	6f
781
782	li	r0, 0
7835:
784	stw	r0, 0(r3)
785	addi	r3, r3, 4
786	cmplw	0, r3, r4
787	bne	5b
7886:
789	mr	r3, r9		/* Init Date pointer		*/
790	mr	r4, r10		/* Destination Address		*/
791	bl	board_init_r
792
793	/* not reached - end relocate_code */
794/*-----------------------------------------------------------------------*/
795
796	/*
797	 * Copy exception vector code to low memory
798	 *
799	 * r3: dest_addr
800	 * r7: source address, r8: end address, r9: target address
801	 */
802	.globl	trap_init
803trap_init:
804	mflr	r4			/* save link register		*/
805	GET_GOT
806	lwz	r7, GOT(_start)
807	lwz	r8, GOT(_end_of_vectors)
808
809	li	r9, 0x100		/* reset vector always at 0x100 */
810
811	cmplw	0, r7, r8
812	bgelr				/* return if r7>=r8 - just in case */
8131:
814	lwz	r0, 0(r7)
815	stw	r0, 0(r9)
816	addi	r7, r7, 4
817	addi	r9, r9, 4
818	cmplw	0, r7, r8
819	bne	1b
820
821	/*
822	 * relocate `hdlr' and `int_return' entries
823	 */
824	li	r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
825	li	r8, Alignment - _start + EXC_OFF_SYS_RESET
8262:
827	bl	trap_reloc
828	addi	r7, r7, 0x100		/* next exception vector	*/
829	cmplw	0, r7, r8
830	blt	2b
831
832	li	r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
833	bl	trap_reloc
834
835	li	r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
836	bl	trap_reloc
837
838	li	r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
839	li	r8, SystemCall - _start + EXC_OFF_SYS_RESET
8403:
841	bl	trap_reloc
842	addi	r7, r7, 0x100		/* next exception vector	*/
843	cmplw	0, r7, r8
844	blt	3b
845
846	li	r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
847	li	r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
8484:
849	bl	trap_reloc
850	addi	r7, r7, 0x100		/* next exception vector	*/
851	cmplw	0, r7, r8
852	blt	4b
853
854	/* enable execptions from RAM vectors */
855	mfmsr	r7
856	li	r8,MSR_IP
857	andc	r7,r7,r8
858	ori	r7,r7,MSR_ME		/* Enable Machine Check */
859	mtmsr	r7
860
861	mtlr	r4			/* restore link register	*/
862	blr
863
864.globl enable_ext_addr
865enable_ext_addr:
866	mfspr	r0, HID0
867	lis	r0, (HID0_HIGH_BAT_EN | HID0_XBSEN | HID0_XAEN)@h
868	ori	r0, r0, (HID0_HIGH_BAT_EN | HID0_XBSEN | HID0_XAEN)@l
869	mtspr	HID0, r0
870	sync
871	isync
872	blr
873
874#if (CONFIG_SYS_CCSRBAR_DEFAULT != CONFIG_SYS_CCSRBAR)
875.globl setup_ccsrbar
876setup_ccsrbar:
877	/* Special sequence needed to update CCSRBAR itself */
878	lis	r4, CONFIG_SYS_CCSRBAR_DEFAULT@h
879	ori	r4, r4, CONFIG_SYS_CCSRBAR_DEFAULT@l
880
881	lis	r5, CONFIG_SYS_CCSRBAR_PHYS_LOW@h
882	ori	r5, r5, CONFIG_SYS_CCSRBAR_PHYS_LOW@l
883	srwi	r5,r5,12
884	li	r6, CONFIG_SYS_CCSRBAR_PHYS_HIGH@l
885	rlwimi	r5,r6,20,8,11
886	stw	r5, 0(r4) /* Store physical value of CCSR */
887	isync
888
889	lis	r5, CONFIG_SYS_TEXT_BASE@h
890	ori	r5,r5,CONFIG_SYS_TEXT_BASE@l
891	lwz	r5, 0(r5)
892	isync
893
894	/* Use VA of CCSR to do read */
895	lis	r3, CONFIG_SYS_CCSRBAR@h
896	lwz	r5, CONFIG_SYS_CCSRBAR@l(r3)
897	isync
898
899	blr
900#endif
901
902#ifdef CONFIG_SYS_INIT_RAM_LOCK
903lock_ram_in_cache:
904	/* Allocate Initial RAM in data cache.
905	 */
906	lis	r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@h
907	ori	r3, r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@l
908	li	r4, ((CONFIG_SYS_INIT_RAM_SIZE & ~31) + \
909		     (CONFIG_SYS_INIT_RAM_ADDR & 31) + 31) / 32
910	mtctr	r4
9111:
912	dcbz	r0, r3
913	addi	r3, r3, 32
914	bdnz	1b
915#if 1
916/* Lock the data cache */
917	mfspr	r0, HID0
918	ori	r0, r0, 0x1000
919	sync
920	mtspr	HID0, r0
921	sync
922	blr
923#endif
924#if 0
925	/* Lock the first way of the data cache */
926	mfspr	r0, LDSTCR
927	ori	r0, r0, 0x0080
928#if defined(CONFIG_ALTIVEC)
929	dssall
930#endif
931	sync
932	mtspr	LDSTCR, r0
933	sync
934	isync
935	blr
936#endif
937
938.globl unlock_ram_in_cache
939unlock_ram_in_cache:
940	/* invalidate the INIT_RAM section */
941	lis	r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@h
942	ori	r3, r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@l
943	li	r4, ((CONFIG_SYS_INIT_RAM_SIZE & ~31) + \
944		     (CONFIG_SYS_INIT_RAM_ADDR & 31) + 31) / 32
945	mtctr	r4
9461:	icbi	r0, r3
947	addi	r3, r3, 32
948	bdnz	1b
949	sync			/* Wait for all icbi to complete on bus */
950	isync
951#if 1
952/* Unlock the data cache and invalidate it */
953	mfspr	r0, HID0
954	li	r3,0x1000
955	andc	r0,r0,r3
956	li	r3,0x0400
957	or	r0,r0,r3
958	sync
959	mtspr	HID0, r0
960	sync
961	blr
962#endif
963#if 0
964	/* Unlock the first way of the data cache */
965	mfspr	r0, LDSTCR
966	li	r3,0x0080
967	andc	r0,r0,r3
968#ifdef CONFIG_ALTIVEC
969	dssall
970#endif
971	sync
972	mtspr	LDSTCR, r0
973	sync
974	isync
975	li	r3,0x0400
976	or	r0,r0,r3
977	sync
978	mtspr	HID0, r0
979	sync
980	blr
981#endif
982#endif
983