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