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