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