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