xref: /openbmc/u-boot/arch/powerpc/cpu/mpc86xx/start.S (revision 5541543f)
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	li	r3, 0		/* clear boot_flag for calling board_init_f */
277	bl	board_init_f
278	sync
279
280	/* NOTREACHED - board_init_f() does not return */
281
282	.globl	invalidate_bats
283invalidate_bats:
284
285	li	r0, 0
286	/* invalidate BATs */
287	mtspr	IBAT0U, r0
288	mtspr	IBAT1U, r0
289	mtspr	IBAT2U, r0
290	mtspr	IBAT3U, r0
291	mtspr	IBAT4U, r0
292	mtspr	IBAT5U, r0
293	mtspr	IBAT6U, r0
294	mtspr	IBAT7U, r0
295
296	isync
297	mtspr	DBAT0U, r0
298	mtspr	DBAT1U, r0
299	mtspr	DBAT2U, r0
300	mtspr	DBAT3U, r0
301	mtspr	DBAT4U, r0
302	mtspr	DBAT5U, r0
303	mtspr	DBAT6U, r0
304	mtspr	DBAT7U, r0
305
306	isync
307	sync
308	blr
309
310#define CONFIG_BAT_PAIR(n) \
311	lis	r4, CONFIG_SYS_IBAT##n##L@h; 		\
312	ori	r4, r4, CONFIG_SYS_IBAT##n##L@l; 	\
313	lis	r3, CONFIG_SYS_IBAT##n##U@h; 		\
314	ori	r3, r3, CONFIG_SYS_IBAT##n##U@l; 	\
315	mtspr	IBAT##n##L, r4; 			\
316	mtspr	IBAT##n##U, r3; 			\
317	lis	r4, CONFIG_SYS_DBAT##n##L@h; 		\
318	ori	r4, r4, CONFIG_SYS_DBAT##n##L@l; 	\
319	lis	r3, CONFIG_SYS_DBAT##n##U@h; 		\
320	ori	r3, r3, CONFIG_SYS_DBAT##n##U@l; 	\
321	mtspr	DBAT##n##L, r4;				\
322	mtspr	DBAT##n##U, r3;
323
324/*
325 * setup_bats:
326 *
327 * Set up the final BAT registers now that setup is done.
328 *
329 * Assumes that:
330 *	1) Address translation is enabled upon entry
331 *	2) The boot rom is still accessible via 1:1 translation
332 */
333	.globl setup_bats
334setup_bats:
335	mflr	r5
336	sync
337
338	/*
339	 * When we disable address translation, we will get 1:1 (VA==PA)
340	 * translation.  The only place we know for sure is safe for that is
341	 * the bootrom where we originally started out.  Pop back into there.
342	 */
343	lis	r4, CONFIG_SYS_MONITOR_BASE_EARLY@h
344	ori	r4, r4, CONFIG_SYS_MONITOR_BASE_EARLY@l
345	addi	r4, r4, trans_disabled - _start + EXC_OFF_SYS_RESET
346
347	/* disable address translation */
348	mfmsr	r3
349	rlwinm	r3, r3, 0, 28, 25
350	mtspr	SRR0, r4
351	mtspr	SRR1, r3
352	rfi
353
354trans_disabled:
355#if defined(CONFIG_SYS_DBAT0U) && defined(CONFIG_SYS_DBAT0L) \
356	&& defined(CONFIG_SYS_IBAT0U) && defined(CONFIG_SYS_IBAT0L)
357	CONFIG_BAT_PAIR(0)
358#endif
359	CONFIG_BAT_PAIR(1)
360	CONFIG_BAT_PAIR(2)
361	CONFIG_BAT_PAIR(3)
362	CONFIG_BAT_PAIR(4)
363	CONFIG_BAT_PAIR(5)
364	CONFIG_BAT_PAIR(6)
365	CONFIG_BAT_PAIR(7)
366
367	sync
368	isync
369
370	/* Turn translation back on and return */
371	mfmsr	r3
372	ori	r3, r3, (MSR_IR | MSR_DR)
373	mtspr	SPRN_SRR0,r5
374	mtspr	SPRN_SRR1,r3
375	rfi
376
377/*
378 * early_bats:
379 *
380 * Set up bats needed early on - this is usually the BAT for the
381 * stack-in-cache, the Flash, and CCSR space
382 */
383	.globl  early_bats
384early_bats:
385	/* IBAT 3 */
386	lis	r4, CONFIG_SYS_IBAT3L@h
387	ori     r4, r4, CONFIG_SYS_IBAT3L@l
388	lis	r3, CONFIG_SYS_IBAT3U@h
389	ori     r3, r3, CONFIG_SYS_IBAT3U@l
390	mtspr   IBAT3L, r4
391	mtspr   IBAT3U, r3
392	isync
393
394	/* DBAT 3 */
395	lis	r4, CONFIG_SYS_DBAT3L@h
396	ori     r4, r4, CONFIG_SYS_DBAT3L@l
397	lis	r3, CONFIG_SYS_DBAT3U@h
398	ori     r3, r3, CONFIG_SYS_DBAT3U@l
399	mtspr   DBAT3L, r4
400	mtspr   DBAT3U, r3
401	isync
402
403	/* IBAT 5 */
404	lis	r4, CONFIG_SYS_IBAT5L@h
405	ori     r4, r4, CONFIG_SYS_IBAT5L@l
406	lis	r3, CONFIG_SYS_IBAT5U@h
407	ori     r3, r3, CONFIG_SYS_IBAT5U@l
408	mtspr   IBAT5L, r4
409	mtspr   IBAT5U, r3
410	isync
411
412	/* DBAT 5 */
413	lis	r4, CONFIG_SYS_DBAT5L@h
414	ori     r4, r4, CONFIG_SYS_DBAT5L@l
415	lis	r3, CONFIG_SYS_DBAT5U@h
416	ori     r3, r3, CONFIG_SYS_DBAT5U@l
417	mtspr   DBAT5L, r4
418	mtspr   DBAT5U, r3
419	isync
420
421	/* IBAT 6 */
422	lis	r4, CONFIG_SYS_IBAT6L_EARLY@h
423	ori     r4, r4, CONFIG_SYS_IBAT6L_EARLY@l
424	lis	r3, CONFIG_SYS_IBAT6U_EARLY@h
425	ori     r3, r3, CONFIG_SYS_IBAT6U_EARLY@l
426	mtspr   IBAT6L, r4
427	mtspr   IBAT6U, r3
428	isync
429
430	/* DBAT 6 */
431	lis	r4, CONFIG_SYS_DBAT6L_EARLY@h
432	ori     r4, r4, CONFIG_SYS_DBAT6L_EARLY@l
433	lis	r3, CONFIG_SYS_DBAT6U_EARLY@h
434	ori     r3, r3, CONFIG_SYS_DBAT6U_EARLY@l
435	mtspr   DBAT6L, r4
436	mtspr   DBAT6U, r3
437	isync
438
439#if(CONFIG_SYS_CCSRBAR_DEFAULT != CONFIG_SYS_CCSRBAR)
440	/* IBAT 7 */
441	lis	r4, CONFIG_SYS_CCSR_DEFAULT_IBATL@h
442	ori     r4, r4, CONFIG_SYS_CCSR_DEFAULT_IBATL@l
443	lis	r3, CONFIG_SYS_CCSR_DEFAULT_IBATU@h
444	ori     r3, r3, CONFIG_SYS_CCSR_DEFAULT_IBATU@l
445	mtspr   IBAT7L, r4
446	mtspr   IBAT7U, r3
447	isync
448
449	/* DBAT 7 */
450	lis	r4, CONFIG_SYS_CCSR_DEFAULT_DBATL@h
451	ori     r4, r4, CONFIG_SYS_CCSR_DEFAULT_DBATL@l
452	lis	r3, CONFIG_SYS_CCSR_DEFAULT_DBATU@h
453	ori     r3, r3, CONFIG_SYS_CCSR_DEFAULT_DBATU@l
454	mtspr   DBAT7L, r4
455	mtspr   DBAT7U, r3
456	isync
457#endif
458	blr
459
460	.globl clear_tlbs
461clear_tlbs:
462	addis   r3, 0, 0x0000
463	addis   r5, 0, 0x4
464	isync
465tlblp:
466	tlbie   r3
467	sync
468	addi    r3, r3, 0x1000
469	cmp     0, 0, r3, r5
470	blt tlblp
471	blr
472
473	.globl disable_addr_trans
474disable_addr_trans:
475	/* disable address translation */
476	mflr	r4
477	mfmsr	r3
478	andi.	r0, r3, (MSR_IR | MSR_DR)
479	beqlr
480	andc	r3, r3, r0
481	mtspr	SRR0, r4
482	mtspr	SRR1, r3
483	rfi
484
485/*
486 * This code finishes saving the registers to the exception frame
487 * and jumps to the appropriate handler for the exception.
488 * Register r21 is pointer into trap frame, r1 has new stack pointer.
489 */
490	.globl	transfer_to_handler
491transfer_to_handler:
492	stw	r22,_NIP(r21)
493	lis	r22,MSR_POW@h
494	andc	r23,r23,r22
495	stw	r23,_MSR(r21)
496	SAVE_GPR(7, r21)
497	SAVE_4GPRS(8, r21)
498	SAVE_8GPRS(12, r21)
499	SAVE_8GPRS(24, r21)
500	mflr	r23
501	andi.	r24,r23,0x3f00		/* get vector offset */
502	stw	r24,TRAP(r21)
503	li	r22,0
504	stw	r22,RESULT(r21)
505	mtspr	SPRG2,r22		/* r1 is now kernel sp */
506	lwz	r24,0(r23)		/* virtual address of handler */
507	lwz	r23,4(r23)		/* where to go when done */
508	mtspr	SRR0,r24
509	mtspr	SRR1,r20
510	mtlr	r23
511	SYNC
512	rfi				/* jump to handler, enable MMU */
513
514int_return:
515	mfmsr	r28		/* Disable interrupts */
516	li	r4,0
517	ori	r4,r4,MSR_EE
518	andc	r28,r28,r4
519	SYNC			/* Some chip revs need this... */
520	mtmsr	r28
521	SYNC
522	lwz	r2,_CTR(r1)
523	lwz	r0,_LINK(r1)
524	mtctr	r2
525	mtlr	r0
526	lwz	r2,_XER(r1)
527	lwz	r0,_CCR(r1)
528	mtspr	XER,r2
529	mtcrf	0xFF,r0
530	REST_10GPRS(3, r1)
531	REST_10GPRS(13, r1)
532	REST_8GPRS(23, r1)
533	REST_GPR(31, r1)
534	lwz	r2,_NIP(r1)	/* Restore environment */
535	lwz	r0,_MSR(r1)
536	mtspr	SRR0,r2
537	mtspr	SRR1,r0
538	lwz	r0,GPR0(r1)
539	lwz	r2,GPR2(r1)
540	lwz	r1,GPR1(r1)
541	SYNC
542	rfi
543
544	.globl	dc_read
545dc_read:
546	blr
547
548
549/*
550 * Function:	in8
551 * Description:	Input 8 bits
552 */
553	.globl	in8
554in8:
555	lbz	r3,0x0000(r3)
556	blr
557
558/*
559 * Function:	out8
560 * Description:	Output 8 bits
561 */
562	.globl	out8
563out8:
564	stb	r4,0x0000(r3)
565	blr
566
567/*
568 * Function:	out16
569 * Description:	Output 16 bits
570 */
571	.globl	out16
572out16:
573	sth	r4,0x0000(r3)
574	blr
575
576/*
577 * Function:	out16r
578 * Description:	Byte reverse and output 16 bits
579 */
580	.globl	out16r
581out16r:
582	sthbrx	r4,r0,r3
583	blr
584
585/*
586 * Function:	out32
587 * Description:	Output 32 bits
588 */
589	.globl	out32
590out32:
591	stw	r4,0x0000(r3)
592	blr
593
594/*
595 * Function:	out32r
596 * Description:	Byte reverse and output 32 bits
597 */
598	.globl	out32r
599out32r:
600	stwbrx	r4,r0,r3
601	blr
602
603/*
604 * Function:	in16
605 * Description:	Input 16 bits
606 */
607	.globl	in16
608in16:
609	lhz	r3,0x0000(r3)
610	blr
611
612/*
613 * Function:	in16r
614 * Description:	Input 16 bits and byte reverse
615 */
616	.globl	in16r
617in16r:
618	lhbrx	r3,r0,r3
619	blr
620
621/*
622 * Function:	in32
623 * Description:	Input 32 bits
624 */
625	.globl	in32
626in32:
627	lwz	3,0x0000(3)
628	blr
629
630/*
631 * Function:	in32r
632 * Description:	Input 32 bits and byte reverse
633 */
634	.globl	in32r
635in32r:
636	lwbrx	r3,r0,r3
637	blr
638
639/*
640 * void relocate_code (addr_sp, gd, addr_moni)
641 *
642 * This "function" does not return, instead it continues in RAM
643 * after relocating the monitor code.
644 *
645 * r3 = dest
646 * r4 = src
647 * r5 = length in bytes
648 * r6 = cachelinesize
649 */
650	.globl	relocate_code
651relocate_code:
652
653	mr	r1,  r3		/* Set new stack pointer		*/
654	mr	r9,  r4		/* Save copy of Global Data pointer	*/
655	mr	r10, r5		/* Save copy of Destination Address	*/
656
657	GET_GOT
658	mr	r3,  r5				/* Destination Address	*/
659	lis	r4, CONFIG_SYS_MONITOR_BASE@h		/* Source      Address	*/
660	ori	r4, r4, CONFIG_SYS_MONITOR_BASE@l
661	lwz	r5, GOT(__init_end)
662	sub	r5, r5, r4
663	li	r6, CONFIG_SYS_CACHELINE_SIZE		/* Cache Line Size	*/
664
665	/*
666	 * Fix GOT pointer:
667	 *
668	 * New GOT-PTR = (old GOT-PTR - CONFIG_SYS_MONITOR_BASE) + Destination Address
669	 *
670	 * Offset:
671	 */
672	sub	r15, r10, r4
673
674	/* First our own GOT */
675	add	r12, r12, r15
676	/* then the one used by the C code */
677	add	r30, r30, r15
678
679	/*
680	 * Now relocate code
681	 */
682	cmplw	cr1,r3,r4
683	addi	r0,r5,3
684	srwi.	r0,r0,2
685	beq	cr1,4f		/* In place copy is not necessary	*/
686	beq	7f		/* Protect against 0 count		*/
687	mtctr	r0
688	bge	cr1,2f
689
690	la	r8,-4(r4)
691	la	r7,-4(r3)
6921:	lwzu	r0,4(r8)
693	stwu	r0,4(r7)
694	bdnz	1b
695	b	4f
696
6972:	slwi	r0,r0,2
698	add	r8,r4,r0
699	add	r7,r3,r0
7003:	lwzu	r0,-4(r8)
701	stwu	r0,-4(r7)
702	bdnz	3b
703/*
704 * Now flush the cache: note that we must start from a cache aligned
705 * address. Otherwise we might miss one cache line.
706 */
7074:	cmpwi	r6,0
708	add	r5,r3,r5
709	beq	7f		/* Always flush prefetch queue in any case */
710	subi	r0,r6,1
711	andc	r3,r3,r0
712	mr	r4,r3
7135:	dcbst	0,r4
714	add	r4,r4,r6
715	cmplw	r4,r5
716	blt	5b
717	sync			/* Wait for all dcbst to complete on bus */
718	mr	r4,r3
7196:	icbi	0,r4
720	add	r4,r4,r6
721	cmplw	r4,r5
722	blt	6b
7237:	sync			/* Wait for all icbi to complete on bus */
724	isync
725
726/*
727 * We are done. Do not return, instead branch to second part of board
728 * initialization, now running from RAM.
729 */
730	addi	r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
731	mtlr	r0
732	blr
733
734in_ram:
735	/*
736	 * Relocation Function, r12 point to got2+0x8000
737	 *
738	 * Adjust got2 pointers, no need to check for 0, this code
739	 * already puts a few entries in the table.
740	 */
741	li	r0,__got2_entries@sectoff@l
742	la	r3,GOT(_GOT2_TABLE_)
743	lwz	r11,GOT(_GOT2_TABLE_)
744	mtctr	r0
745	sub	r11,r3,r11
746	addi	r3,r3,-4
7471:	lwzu	r0,4(r3)
748	cmpwi	r0,0
749	beq-	2f
750	add	r0,r0,r11
751	stw	r0,0(r3)
7522:	bdnz	1b
753
754	/*
755	 * Now adjust the fixups and the pointers to the fixups
756	 * in case we need to move ourselves again.
757	 */
758	li	r0,__fixup_entries@sectoff@l
759	lwz	r3,GOT(_FIXUP_TABLE_)
760	cmpwi	r0,0
761	mtctr	r0
762	addi	r3,r3,-4
763	beq	4f
7643:	lwzu	r4,4(r3)
765	lwzux	r0,r4,r11
766	cmpwi	r0,0
767	add	r0,r0,r11
768	stw	r4,0(r3)
769	beq-	5f
770	stw	r0,0(r4)
7715:	bdnz	3b
7724:
773/* clear_bss: */
774	/*
775	 * Now clear BSS segment
776	 */
777	lwz	r3,GOT(__bss_start)
778	lwz	r4,GOT(__bss_end)
779
780	cmplw	0, r3, r4
781	beq	6f
782
783	li	r0, 0
7845:
785	stw	r0, 0(r3)
786	addi	r3, r3, 4
787	cmplw	0, r3, r4
788	bne	5b
7896:
790	mr	r3, r9		/* Init Date pointer		*/
791	mr	r4, r10		/* Destination Address		*/
792	bl	board_init_r
793
794	/* not reached - end relocate_code */
795/*-----------------------------------------------------------------------*/
796
797	/*
798	 * Copy exception vector code to low memory
799	 *
800	 * r3: dest_addr
801	 * r7: source address, r8: end address, r9: target address
802	 */
803	.globl	trap_init
804trap_init:
805	mflr	r4			/* save link register		*/
806	GET_GOT
807	lwz	r7, GOT(_start)
808	lwz	r8, GOT(_end_of_vectors)
809
810	li	r9, 0x100		/* reset vector always at 0x100 */
811
812	cmplw	0, r7, r8
813	bgelr				/* return if r7>=r8 - just in case */
8141:
815	lwz	r0, 0(r7)
816	stw	r0, 0(r9)
817	addi	r7, r7, 4
818	addi	r9, r9, 4
819	cmplw	0, r7, r8
820	bne	1b
821
822	/*
823	 * relocate `hdlr' and `int_return' entries
824	 */
825	li	r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
826	li	r8, Alignment - _start + EXC_OFF_SYS_RESET
8272:
828	bl	trap_reloc
829	addi	r7, r7, 0x100		/* next exception vector	*/
830	cmplw	0, r7, r8
831	blt	2b
832
833	li	r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
834	bl	trap_reloc
835
836	li	r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
837	bl	trap_reloc
838
839	li	r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
840	li	r8, SystemCall - _start + EXC_OFF_SYS_RESET
8413:
842	bl	trap_reloc
843	addi	r7, r7, 0x100		/* next exception vector	*/
844	cmplw	0, r7, r8
845	blt	3b
846
847	li	r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
848	li	r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
8494:
850	bl	trap_reloc
851	addi	r7, r7, 0x100		/* next exception vector	*/
852	cmplw	0, r7, r8
853	blt	4b
854
855	/* enable execptions from RAM vectors */
856	mfmsr	r7
857	li	r8,MSR_IP
858	andc	r7,r7,r8
859	ori	r7,r7,MSR_ME		/* Enable Machine Check */
860	mtmsr	r7
861
862	mtlr	r4			/* restore link register	*/
863	blr
864
865.globl enable_ext_addr
866enable_ext_addr:
867	mfspr	r0, HID0
868	lis	r0, (HID0_HIGH_BAT_EN | HID0_XBSEN | HID0_XAEN)@h
869	ori	r0, r0, (HID0_HIGH_BAT_EN | HID0_XBSEN | HID0_XAEN)@l
870	mtspr	HID0, r0
871	sync
872	isync
873	blr
874
875#if (CONFIG_SYS_CCSRBAR_DEFAULT != CONFIG_SYS_CCSRBAR)
876.globl setup_ccsrbar
877setup_ccsrbar:
878	/* Special sequence needed to update CCSRBAR itself */
879	lis	r4, CONFIG_SYS_CCSRBAR_DEFAULT@h
880	ori	r4, r4, CONFIG_SYS_CCSRBAR_DEFAULT@l
881
882	lis	r5, CONFIG_SYS_CCSRBAR_PHYS_LOW@h
883	ori	r5, r5, CONFIG_SYS_CCSRBAR_PHYS_LOW@l
884	srwi	r5,r5,12
885	li	r6, CONFIG_SYS_CCSRBAR_PHYS_HIGH@l
886	rlwimi	r5,r6,20,8,11
887	stw	r5, 0(r4) /* Store physical value of CCSR */
888	isync
889
890	lis	r5, CONFIG_SYS_TEXT_BASE@h
891	ori	r5,r5,CONFIG_SYS_TEXT_BASE@l
892	lwz	r5, 0(r5)
893	isync
894
895	/* Use VA of CCSR to do read */
896	lis	r3, CONFIG_SYS_CCSRBAR@h
897	lwz	r5, CONFIG_SYS_CCSRBAR@l(r3)
898	isync
899
900	blr
901#endif
902
903#ifdef CONFIG_SYS_INIT_RAM_LOCK
904lock_ram_in_cache:
905	/* Allocate Initial RAM in data cache.
906	 */
907	lis	r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@h
908	ori	r3, r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@l
909	li	r4, ((CONFIG_SYS_INIT_RAM_SIZE & ~31) + \
910		     (CONFIG_SYS_INIT_RAM_ADDR & 31) + 31) / 32
911	mtctr	r4
9121:
913	dcbz	r0, r3
914	addi	r3, r3, 32
915	bdnz	1b
916#if 1
917/* Lock the data cache */
918	mfspr	r0, HID0
919	ori	r0, r0, 0x1000
920	sync
921	mtspr	HID0, r0
922	sync
923	blr
924#endif
925#if 0
926	/* Lock the first way of the data cache */
927	mfspr	r0, LDSTCR
928	ori	r0, r0, 0x0080
929#if defined(CONFIG_ALTIVEC)
930	dssall
931#endif
932	sync
933	mtspr	LDSTCR, r0
934	sync
935	isync
936	blr
937#endif
938
939.globl unlock_ram_in_cache
940unlock_ram_in_cache:
941	/* invalidate the INIT_RAM section */
942	lis	r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@h
943	ori	r3, r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@l
944	li	r4, ((CONFIG_SYS_INIT_RAM_SIZE & ~31) + \
945		     (CONFIG_SYS_INIT_RAM_ADDR & 31) + 31) / 32
946	mtctr	r4
9471:	icbi	r0, r3
948	addi	r3, r3, 32
949	bdnz	1b
950	sync			/* Wait for all icbi to complete on bus */
951	isync
952#if 1
953/* Unlock the data cache and invalidate it */
954	mfspr	r0, HID0
955	li	r3,0x1000
956	andc	r0,r0,r3
957	li	r3,0x0400
958	or	r0,r0,r3
959	sync
960	mtspr	HID0, r0
961	sync
962	blr
963#endif
964#if 0
965	/* Unlock the first way of the data cache */
966	mfspr	r0, LDSTCR
967	li	r3,0x0080
968	andc	r0,r0,r3
969#ifdef CONFIG_ALTIVEC
970	dssall
971#endif
972	sync
973	mtspr	LDSTCR, r0
974	sync
975	isync
976	li	r3,0x0400
977	or	r0,r0,r3
978	sync
979	mtspr	HID0, r0
980	sync
981	blr
982#endif
983#endif
984