xref: /rk3399_rockchip-uboot/arch/powerpc/cpu/mpc86xx/start.S (revision d98b0523cfaaedeecb263b15c121c0727b0d80b9)
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	add	r0,r0,r11
731	stw	r10,0(r3)
732	stw	r0,0(r4)
733	bdnz	3b
7344:
735/* clear_bss: */
736	/*
737	 * Now clear BSS segment
738	 */
739	lwz	r3,GOT(__bss_start)
740	lwz	r4,GOT(_end)
741
742	cmplw	0, r3, r4
743	beq	6f
744
745	li	r0, 0
7465:
747	stw	r0, 0(r3)
748	addi	r3, r3, 4
749	cmplw	0, r3, r4
750	bne	5b
7516:
752	mr	r3, r9		/* Init Date pointer		*/
753	mr	r4, r10		/* Destination Address		*/
754	bl	board_init_r
755
756	/* not reached - end relocate_code */
757/*-----------------------------------------------------------------------*/
758
759	/*
760	 * Copy exception vector code to low memory
761	 *
762	 * r3: dest_addr
763	 * r7: source address, r8: end address, r9: target address
764	 */
765	.globl	trap_init
766trap_init:
767	mflr	r4			/* save link register		*/
768	GET_GOT
769	lwz	r7, GOT(_start)
770	lwz	r8, GOT(_end_of_vectors)
771
772	li	r9, 0x100		/* reset vector always at 0x100 */
773
774	cmplw	0, r7, r8
775	bgelr				/* return if r7>=r8 - just in case */
7761:
777	lwz	r0, 0(r7)
778	stw	r0, 0(r9)
779	addi	r7, r7, 4
780	addi	r9, r9, 4
781	cmplw	0, r7, r8
782	bne	1b
783
784	/*
785	 * relocate `hdlr' and `int_return' entries
786	 */
787	li	r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
788	li	r8, Alignment - _start + EXC_OFF_SYS_RESET
7892:
790	bl	trap_reloc
791	addi	r7, r7, 0x100		/* next exception vector	*/
792	cmplw	0, r7, r8
793	blt	2b
794
795	li	r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
796	bl	trap_reloc
797
798	li	r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
799	bl	trap_reloc
800
801	li	r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
802	li	r8, SystemCall - _start + EXC_OFF_SYS_RESET
8033:
804	bl	trap_reloc
805	addi	r7, r7, 0x100		/* next exception vector	*/
806	cmplw	0, r7, r8
807	blt	3b
808
809	li	r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
810	li	r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
8114:
812	bl	trap_reloc
813	addi	r7, r7, 0x100		/* next exception vector	*/
814	cmplw	0, r7, r8
815	blt	4b
816
817	/* enable execptions from RAM vectors */
818	mfmsr	r7
819	li	r8,MSR_IP
820	andc	r7,r7,r8
821	ori	r7,r7,MSR_ME		/* Enable Machine Check */
822	mtmsr	r7
823
824	mtlr	r4			/* restore link register	*/
825	blr
826
827.globl enable_ext_addr
828enable_ext_addr:
829	mfspr	r0, HID0
830	lis	r0, (HID0_HIGH_BAT_EN | HID0_XBSEN | HID0_XAEN)@h
831	ori	r0, r0, (HID0_HIGH_BAT_EN | HID0_XBSEN | HID0_XAEN)@l
832	mtspr	HID0, r0
833	sync
834	isync
835	blr
836
837#if (CONFIG_SYS_CCSRBAR_DEFAULT != CONFIG_SYS_CCSRBAR)
838.globl setup_ccsrbar
839setup_ccsrbar:
840	/* Special sequence needed to update CCSRBAR itself */
841	lis	r4, CONFIG_SYS_CCSRBAR_DEFAULT@h
842	ori	r4, r4, CONFIG_SYS_CCSRBAR_DEFAULT@l
843
844	lis	r5, CONFIG_SYS_CCSRBAR_PHYS_LOW@h
845	ori	r5, r5, CONFIG_SYS_CCSRBAR_PHYS_LOW@l
846	srwi	r5,r5,12
847	li	r6, CONFIG_SYS_CCSRBAR_PHYS_HIGH@l
848	rlwimi	r5,r6,20,8,11
849	stw	r5, 0(r4) /* Store physical value of CCSR */
850	isync
851
852	lis	r5, CONFIG_SYS_TEXT_BASE@h
853	ori	r5,r5,CONFIG_SYS_TEXT_BASE@l
854	lwz	r5, 0(r5)
855	isync
856
857	/* Use VA of CCSR to do read */
858	lis	r3, CONFIG_SYS_CCSRBAR@h
859	lwz	r5, CONFIG_SYS_CCSRBAR@l(r3)
860	isync
861
862	blr
863#endif
864
865#ifdef CONFIG_SYS_INIT_RAM_LOCK
866lock_ram_in_cache:
867	/* Allocate Initial RAM in data cache.
868	 */
869	lis	r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@h
870	ori	r3, r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@l
871	li	r4, ((CONFIG_SYS_INIT_RAM_END & ~31) + \
872		     (CONFIG_SYS_INIT_RAM_ADDR & 31) + 31) / 32
873	mtctr	r4
8741:
875	dcbz	r0, r3
876	addi	r3, r3, 32
877	bdnz	1b
878#if 1
879/* Lock the data cache */
880	mfspr	r0, HID0
881	ori	r0, r0, 0x1000
882	sync
883	mtspr	HID0, r0
884	sync
885	blr
886#endif
887#if 0
888	/* Lock the first way of the data cache */
889	mfspr	r0, LDSTCR
890	ori	r0, r0, 0x0080
891#if defined(CONFIG_ALTIVEC)
892	dssall
893#endif
894	sync
895	mtspr	LDSTCR, r0
896	sync
897	isync
898	blr
899#endif
900
901.globl unlock_ram_in_cache
902unlock_ram_in_cache:
903	/* invalidate the INIT_RAM section */
904	lis	r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@h
905	ori	r3, r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@l
906	li	r4, ((CONFIG_SYS_INIT_RAM_END & ~31) + \
907		     (CONFIG_SYS_INIT_RAM_ADDR & 31) + 31) / 32
908	mtctr	r4
9091:	icbi	r0, r3
910	addi	r3, r3, 32
911	bdnz	1b
912	sync			/* Wait for all icbi to complete on bus */
913	isync
914#if 1
915/* Unlock the data cache and invalidate it */
916	mfspr	r0, HID0
917	li	r3,0x1000
918	andc	r0,r0,r3
919	li	r3,0x0400
920	or	r0,r0,r3
921	sync
922	mtspr	HID0, r0
923	sync
924	blr
925#endif
926#if 0
927	/* Unlock the first way of the data cache */
928	mfspr	r0, LDSTCR
929	li	r3,0x0080
930	andc	r0,r0,r3
931#ifdef CONFIG_ALTIVEC
932	dssall
933#endif
934	sync
935	mtspr	LDSTCR, r0
936	sync
937	isync
938	li	r3,0x0400
939	or	r0,r0,r3
940	sync
941	mtspr	HID0, r0
942	sync
943	blr
944#endif
945#endif
946