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