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