blob: e12eee9d1d913808a29a2bdc5109c43748e3cbca [file] [log] [blame]
wdenk21136db2003-07-16 21:53:01 +00001/*
2 * Copyright (C) 1998 Dan Malek <dmalek@jlc.net>
3 * Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
4 * Copyright (C) 2000 - 2003 Wolfgang Denk <wd@denx.de>
5 *
6 * See file CREDITS for list of people who contributed to this
7 * project.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation; either version 2 of
12 * the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
22 * MA 02111-1307 USA
23 */
24
25/*
26 * U-Boot - Startup Code for MPC5xxx CPUs
27 */
28#include <config.h>
29#include <mpc5xxx.h>
30#include <version.h>
31
wdenkbe9c1cb2004-02-24 02:00:03 +000032#define CONFIG_MPC5xxx 1 /* needed for Linux kernel header files */
wdenk21136db2003-07-16 21:53:01 +000033#define _LINUX_CONFIG_H 1 /* avoid reading Linux autoconf.h file */
34
35#include <ppc_asm.tmpl>
36#include <ppc_defs.h>
37
38#include <asm/cache.h>
39#include <asm/mmu.h>
40
41#ifndef CONFIG_IDENT_STRING
42#define CONFIG_IDENT_STRING ""
43#endif
44
45/* We don't want the MMU yet.
46*/
47#undef MSR_KERNEL
48/* Floating Point enable, Machine Check and Recoverable Interr. */
49#ifdef DEBUG
50#define MSR_KERNEL (MSR_FP|MSR_RI)
51#else
52#define MSR_KERNEL (MSR_FP|MSR_ME|MSR_RI)
53#endif
54
55/*
56 * Set up GOT: Global Offset Table
57 *
58 * Use r14 to access the GOT
59 */
60 START_GOT
61 GOT_ENTRY(_GOT2_TABLE_)
62 GOT_ENTRY(_FIXUP_TABLE_)
63
64 GOT_ENTRY(_start)
65 GOT_ENTRY(_start_of_vectors)
66 GOT_ENTRY(_end_of_vectors)
67 GOT_ENTRY(transfer_to_handler)
68
69 GOT_ENTRY(__init_end)
70 GOT_ENTRY(_end)
71 GOT_ENTRY(__bss_start)
72 END_GOT
73
74/*
75 * Version string
76 */
77 .data
78 .globl version_string
79version_string:
80 .ascii U_BOOT_VERSION
81 .ascii " (", __DATE__, " - ", __TIME__, ")"
82 .ascii CONFIG_IDENT_STRING, "\0"
83
84/*
85 * Exception vectors
86 */
87 .text
88 . = EXC_OFF_SYS_RESET
89 .globl _start
90_start:
91 li r21, BOOTFLAG_COLD /* Normal Power-On */
92 nop
93 b boot_cold
94
95 . = EXC_OFF_SYS_RESET + 0x10
96
97 .globl _start_warm
98_start_warm:
99 li r21, BOOTFLAG_WARM /* Software reboot */
100 b boot_warm
101
102boot_cold:
103boot_warm:
104 mfmsr r5 /* save msr contents */
105
wdenke44b9112004-04-18 23:32:11 +0000106 /* Move CSBoot and adjust instruction pointer */
107 /*--------------------------------------------------------------*/
108
wdenk4b16c2e2003-11-07 13:42:26 +0000109#if defined(CFG_LOWBOOT)
wdenkca262162004-02-09 20:51:26 +0000110#if defined(CFG_RAMBOOT)
111#error CFG_LOWBOOT is incompatible with CFG_RAMBOOT
112#endif /* CFG_RAMBOOT */
wdenk4b16c2e2003-11-07 13:42:26 +0000113 lis r4, CFG_DEFAULT_MBAR@h
wdenk0a12b752004-03-11 22:46:36 +0000114 lis r3, START_REG(CFG_BOOTCS_START)@h
115 ori r3, r3, START_REG(CFG_BOOTCS_START)@l
116 stw r3, 0x4(r4) /* CS0 start */
117 lis r3, STOP_REG(CFG_BOOTCS_START, CFG_BOOTCS_SIZE)@h
118 ori r3, r3, STOP_REG(CFG_BOOTCS_START, CFG_BOOTCS_SIZE)@l
wdenk0a12b752004-03-11 22:46:36 +0000119 stw r3, 0x8(r4) /* CS0 stop */
wdenk4b16c2e2003-11-07 13:42:26 +0000120 lis r3, 0x02010000@h
121 ori r3, r3, 0x02010000@l
wdenke44b9112004-04-18 23:32:11 +0000122 stw r3, 0x54(r4) /* CS0 and Boot enable */
wdenk4b16c2e2003-11-07 13:42:26 +0000123
wdenke44b9112004-04-18 23:32:11 +0000124 lis r3, lowboot_reentry@h /* jump from bootlow address space (0x0000xxxx) */
125 ori r3, r3, lowboot_reentry@l /* to the address space the linker used */
wdenk4b16c2e2003-11-07 13:42:26 +0000126 mtlr r3
wdenke44b9112004-04-18 23:32:11 +0000127 blr
wdenk1ebf41e2004-01-02 14:00:00 +0000128
129lowboot_reentry:
wdenk0a12b752004-03-11 22:46:36 +0000130 lis r3, START_REG(CFG_BOOTCS_START)@h
131 ori r3, r3, START_REG(CFG_BOOTCS_START)@l
132 stw r3, 0x4c(r4) /* Boot start */
133 lis r3, STOP_REG(CFG_BOOTCS_START, CFG_BOOTCS_SIZE)@h
134 ori r3, r3, STOP_REG(CFG_BOOTCS_START, CFG_BOOTCS_SIZE)@l
135 stw r3, 0x50(r4) /* Boot stop */
wdenk4b16c2e2003-11-07 13:42:26 +0000136 lis r3, 0x02000001@h
137 ori r3, r3, 0x02000001@l
wdenke44b9112004-04-18 23:32:11 +0000138 stw r3, 0x54(r4) /* Boot enable, CS0 disable */
wdenk4b16c2e2003-11-07 13:42:26 +0000139#endif /* CFG_LOWBOOT */
wdenk1ebf41e2004-01-02 14:00:00 +0000140
wdenk5d841732003-08-17 18:55:18 +0000141#if defined(CFG_DEFAULT_MBAR) && !defined(CFG_RAMBOOT)
wdenk21136db2003-07-16 21:53:01 +0000142 lis r3, CFG_MBAR@h
143 ori r3, r3, CFG_MBAR@l
144#if defined(CONFIG_MPC5200)
wdenk56ed43e2004-02-22 23:46:08 +0000145 /* MBAR is mirrored into the MBAR SPR */
146 mtspr MBAR,r3
wdenk21136db2003-07-16 21:53:01 +0000147 rlwinm r3, r3, 16, 16, 31
148#endif
149#if defined(CONFIG_MGT5100)
150 rlwinm r3, r3, 17, 15, 31
151#endif
152 lis r4, CFG_DEFAULT_MBAR@h
153 stw r3, 0(r4)
154#endif /* CFG_DEFAULT_MBAR */
155
156 /* Initialise the MPC5xxx processor core */
157 /*--------------------------------------------------------------*/
158
159 bl init_5xxx_core
160
161 /* initialize some things that are hard to access from C */
162 /*--------------------------------------------------------------*/
163
164 /* set up stack in on-chip SRAM */
165 lis r3, CFG_INIT_RAM_ADDR@h
166 ori r3, r3, CFG_INIT_RAM_ADDR@l
167 ori r1, r3, CFG_INIT_SP_OFFSET
168 li r0, 0 /* Make room for stack frame header and */
169 stwu r0, -4(r1) /* clear final stack frame so that */
170 stwu r0, -4(r1) /* stack backtraces terminate cleanly */
171
172 /* let the C-code set up the rest */
173 /* */
174 /* Be careful to keep code relocatable ! */
175 /*--------------------------------------------------------------*/
176
177 GET_GOT /* initialize GOT access */
178
179 /* r3: IMMR */
180 bl cpu_init_f /* run low-level CPU init code (in Flash)*/
181
182 mr r3, r21
183 /* r3: BOOTFLAG */
184 bl board_init_f /* run 1st part of board init code (in Flash)*/
185
186/*
187 * Vector Table
188 */
189
190 .globl _start_of_vectors
191_start_of_vectors:
192
193/* Machine check */
194 STD_EXCEPTION(0x200, MachineCheck, MachineCheckException)
195
196/* Data Storage exception. */
197 STD_EXCEPTION(0x300, DataStorage, UnknownException)
198
199/* Instruction Storage exception. */
200 STD_EXCEPTION(0x400, InstStorage, UnknownException)
201
202/* External Interrupt exception. */
203 STD_EXCEPTION(0x500, ExtInterrupt, external_interrupt)
204
205/* Alignment exception. */
206 . = 0x600
207Alignment:
208 EXCEPTION_PROLOG
209 mfspr r4,DAR
210 stw r4,_DAR(r21)
211 mfspr r5,DSISR
212 stw r5,_DSISR(r21)
213 addi r3,r1,STACK_FRAME_OVERHEAD
214 li r20,MSR_KERNEL
215 rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */
216 rlwimi r20,r23,0,25,25 /* copy IP bit from saved MSR */
217 lwz r6,GOT(transfer_to_handler)
218 mtlr r6
219 blrl
220.L_Alignment:
221 .long AlignmentException - _start + EXC_OFF_SYS_RESET
222 .long int_return - _start + EXC_OFF_SYS_RESET
223
224/* Program check exception */
225 . = 0x700
226ProgramCheck:
227 EXCEPTION_PROLOG
228 addi r3,r1,STACK_FRAME_OVERHEAD
229 li r20,MSR_KERNEL
230 rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */
231 rlwimi r20,r23,0,25,25 /* copy IP bit from saved MSR */
232 lwz r6,GOT(transfer_to_handler)
233 mtlr r6
234 blrl
235.L_ProgramCheck:
236 .long ProgramCheckException - _start + EXC_OFF_SYS_RESET
237 .long int_return - _start + EXC_OFF_SYS_RESET
238
239 STD_EXCEPTION(0x800, FPUnavailable, UnknownException)
240
241 /* I guess we could implement decrementer, and may have
242 * to someday for timekeeping.
243 */
244 STD_EXCEPTION(0x900, Decrementer, timer_interrupt)
245
246 STD_EXCEPTION(0xa00, Trap_0a, UnknownException)
247 STD_EXCEPTION(0xb00, Trap_0b, UnknownException)
wdenk874ac262003-07-24 23:38:38 +0000248 STD_EXCEPTION(0xc00, SystemCall, UnknownException)
wdenk21136db2003-07-16 21:53:01 +0000249 STD_EXCEPTION(0xd00, SingleStep, UnknownException)
250
251 STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
252 STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
253
254 STD_EXCEPTION(0x1000, InstructionTLBMiss, UnknownException)
255 STD_EXCEPTION(0x1100, DataLoadTLBMiss, UnknownException)
256 STD_EXCEPTION(0x1200, DataStoreTLBMiss, UnknownException)
257#ifdef DEBUG
258 . = 0x1300
259 /*
260 * This exception occurs when the program counter matches the
261 * Instruction Address Breakpoint Register (IABR).
262 *
263 * I want the cpu to halt if this occurs so I can hunt around
264 * with the debugger and look at things.
265 *
266 * When DEBUG is defined, both machine check enable (in the MSR)
267 * and checkstop reset enable (in the reset mode register) are
268 * turned off and so a checkstop condition will result in the cpu
269 * halting.
270 *
271 * I force the cpu into a checkstop condition by putting an illegal
272 * instruction here (at least this is the theory).
273 *
274 * well - that didnt work, so just do an infinite loop!
275 */
2761: b 1b
277#else
278 STD_EXCEPTION(0x1300, InstructionBreakpoint, DebugException)
279#endif
280 STD_EXCEPTION(0x1400, SMI, UnknownException)
281
282 STD_EXCEPTION(0x1500, Trap_15, UnknownException)
283 STD_EXCEPTION(0x1600, Trap_16, UnknownException)
284 STD_EXCEPTION(0x1700, Trap_17, UnknownException)
285 STD_EXCEPTION(0x1800, Trap_18, UnknownException)
286 STD_EXCEPTION(0x1900, Trap_19, UnknownException)
287 STD_EXCEPTION(0x1a00, Trap_1a, UnknownException)
288 STD_EXCEPTION(0x1b00, Trap_1b, UnknownException)
289 STD_EXCEPTION(0x1c00, Trap_1c, UnknownException)
290 STD_EXCEPTION(0x1d00, Trap_1d, UnknownException)
291 STD_EXCEPTION(0x1e00, Trap_1e, UnknownException)
292 STD_EXCEPTION(0x1f00, Trap_1f, UnknownException)
293 STD_EXCEPTION(0x2000, Trap_20, UnknownException)
294 STD_EXCEPTION(0x2100, Trap_21, UnknownException)
295 STD_EXCEPTION(0x2200, Trap_22, UnknownException)
296 STD_EXCEPTION(0x2300, Trap_23, UnknownException)
297 STD_EXCEPTION(0x2400, Trap_24, UnknownException)
298 STD_EXCEPTION(0x2500, Trap_25, UnknownException)
299 STD_EXCEPTION(0x2600, Trap_26, UnknownException)
300 STD_EXCEPTION(0x2700, Trap_27, UnknownException)
301 STD_EXCEPTION(0x2800, Trap_28, UnknownException)
302 STD_EXCEPTION(0x2900, Trap_29, UnknownException)
303 STD_EXCEPTION(0x2a00, Trap_2a, UnknownException)
304 STD_EXCEPTION(0x2b00, Trap_2b, UnknownException)
305 STD_EXCEPTION(0x2c00, Trap_2c, UnknownException)
306 STD_EXCEPTION(0x2d00, Trap_2d, UnknownException)
307 STD_EXCEPTION(0x2e00, Trap_2e, UnknownException)
308 STD_EXCEPTION(0x2f00, Trap_2f, UnknownException)
309
310
311 .globl _end_of_vectors
312_end_of_vectors:
313
314 . = 0x3000
315
316/*
317 * This code finishes saving the registers to the exception frame
318 * and jumps to the appropriate handler for the exception.
319 * Register r21 is pointer into trap frame, r1 has new stack pointer.
320 */
321 .globl transfer_to_handler
322transfer_to_handler:
323 stw r22,_NIP(r21)
324 lis r22,MSR_POW@h
325 andc r23,r23,r22
326 stw r23,_MSR(r21)
327 SAVE_GPR(7, r21)
328 SAVE_4GPRS(8, r21)
329 SAVE_8GPRS(12, r21)
330 SAVE_8GPRS(24, r21)
331 mflr r23
332 andi. r24,r23,0x3f00 /* get vector offset */
333 stw r24,TRAP(r21)
334 li r22,0
335 stw r22,RESULT(r21)
336 lwz r24,0(r23) /* virtual address of handler */
337 lwz r23,4(r23) /* where to go when done */
338 mtspr SRR0,r24
339 mtspr SRR1,r20
340 mtlr r23
341 SYNC
342 rfi /* jump to handler, enable MMU */
343
344int_return:
345 mfmsr r28 /* Disable interrupts */
346 li r4,0
347 ori r4,r4,MSR_EE
348 andc r28,r28,r4
349 SYNC /* Some chip revs need this... */
350 mtmsr r28
351 SYNC
352 lwz r2,_CTR(r1)
353 lwz r0,_LINK(r1)
354 mtctr r2
355 mtlr r0
356 lwz r2,_XER(r1)
357 lwz r0,_CCR(r1)
358 mtspr XER,r2
359 mtcrf 0xFF,r0
360 REST_10GPRS(3, r1)
361 REST_10GPRS(13, r1)
362 REST_8GPRS(23, r1)
363 REST_GPR(31, r1)
364 lwz r2,_NIP(r1) /* Restore environment */
365 lwz r0,_MSR(r1)
366 mtspr SRR0,r2
367 mtspr SRR1,r0
368 lwz r0,GPR0(r1)
369 lwz r2,GPR2(r1)
370 lwz r1,GPR1(r1)
371 SYNC
372 rfi
373
374/*
375 * This code initialises the MPC5xxx processor core
376 * (conforms to PowerPC 603e spec)
377 * Note: expects original MSR contents to be in r5.
378 */
379
380 .globl init_5xx_core
381init_5xxx_core:
382
383 /* Initialize machine status; enable machine check interrupt */
384 /*--------------------------------------------------------------*/
385
386 li r3, MSR_KERNEL /* Set ME and RI flags */
387 rlwimi r3, r5, 0, 25, 25 /* preserve IP bit set by HRCW */
388#ifdef DEBUG
389 rlwimi r3, r5, 0, 21, 22 /* debugger might set SE & BE bits */
390#endif
391 SYNC /* Some chip revs need this... */
392 mtmsr r3
393 SYNC
394 mtspr SRR1, r3 /* Make SRR1 match MSR */
395
396 /* Initialize the Hardware Implementation-dependent Registers */
397 /* HID0 also contains cache control */
398 /*--------------------------------------------------------------*/
399
400 lis r3, CFG_HID0_INIT@h
401 ori r3, r3, CFG_HID0_INIT@l
402 SYNC
403 mtspr HID0, r3
404
405 lis r3, CFG_HID0_FINAL@h
406 ori r3, r3, CFG_HID0_FINAL@l
407 SYNC
408 mtspr HID0, r3
409
410 /* clear all BAT's */
411 /*--------------------------------------------------------------*/
412
413 li r0, 0
414 mtspr DBAT0U, r0
415 mtspr DBAT0L, r0
416 mtspr DBAT1U, r0
417 mtspr DBAT1L, r0
418 mtspr DBAT2U, r0
419 mtspr DBAT2L, r0
420 mtspr DBAT3U, r0
421 mtspr DBAT3L, r0
wdenkfc314ce2003-09-14 19:08:39 +0000422 mtspr DBAT4U, r0
423 mtspr DBAT4L, r0
424 mtspr DBAT5U, r0
425 mtspr DBAT5L, r0
426 mtspr DBAT6U, r0
427 mtspr DBAT6L, r0
428 mtspr DBAT7U, r0
429 mtspr DBAT7L, r0
wdenk21136db2003-07-16 21:53:01 +0000430 mtspr IBAT0U, r0
431 mtspr IBAT0L, r0
432 mtspr IBAT1U, r0
433 mtspr IBAT1L, r0
434 mtspr IBAT2U, r0
435 mtspr IBAT2L, r0
436 mtspr IBAT3U, r0
437 mtspr IBAT3L, r0
wdenkfc314ce2003-09-14 19:08:39 +0000438 mtspr IBAT4U, r0
439 mtspr IBAT4L, r0
440 mtspr IBAT5U, r0
441 mtspr IBAT5L, r0
442 mtspr IBAT6U, r0
443 mtspr IBAT6L, r0
444 mtspr IBAT7U, r0
445 mtspr IBAT7L, r0
wdenk21136db2003-07-16 21:53:01 +0000446 SYNC
447
448 /* invalidate all tlb's */
449 /* */
450 /* From the 603e User Manual: "The 603e provides the ability to */
451 /* invalidate a TLB entry. The TLB Invalidate Entry (tlbie) */
452 /* instruction invalidates the TLB entry indexed by the EA, and */
453 /* operates on both the instruction and data TLBs simultaneously*/
454 /* invalidating four TLB entries (both sets in each TLB). The */
455 /* index corresponds to bits 15-19 of the EA. To invalidate all */
456 /* entries within both TLBs, 32 tlbie instructions should be */
457 /* issued, incrementing this field by one each time." */
458 /* */
459 /* "Note that the tlbia instruction is not implemented on the */
460 /* 603e." */
461 /* */
462 /* bits 15-19 correspond to addresses 0x00000000 to 0x0001F000 */
463 /* incrementing by 0x1000 each time. The code below is sort of */
464 /* based on code in "flush_tlbs" from arch/ppc/kernel/head.S */
465 /* */
466 /*--------------------------------------------------------------*/
467
468 li r3, 32
469 mtctr r3
470 li r3, 0
4711: tlbie r3
472 addi r3, r3, 0x1000
473 bdnz 1b
474 SYNC
475
476 /* Done! */
477 /*--------------------------------------------------------------*/
478
479 blr
480
481/* Cache functions.
482 *
483 * Note: requires that all cache bits in
484 * HID0 are in the low half word.
485 */
486 .globl icache_enable
487icache_enable:
488 mfspr r3, HID0
489 ori r3, r3, HID0_ICE
490 lis r4, 0
491 ori r4, r4, HID0_ILOCK
492 andc r3, r3, r4
493 ori r4, r3, HID0_ICFI
494 isync
495 mtspr HID0, r4 /* sets enable and invalidate, clears lock */
496 isync
497 mtspr HID0, r3 /* clears invalidate */
498 blr
499
500 .globl icache_disable
501icache_disable:
502 mfspr r3, HID0
503 lis r4, 0
504 ori r4, r4, HID0_ICE|HID0_ILOCK
505 andc r3, r3, r4
506 ori r4, r3, HID0_ICFI
507 isync
508 mtspr HID0, r4 /* sets invalidate, clears enable and lock */
509 isync
510 mtspr HID0, r3 /* clears invalidate */
511 blr
512
513 .globl icache_status
514icache_status:
515 mfspr r3, HID0
516 rlwinm r3, r3, HID0_ICE_BITPOS + 1, 31, 31
517 blr
518
519 .globl dcache_enable
520dcache_enable:
521 mfspr r3, HID0
522 ori r3, r3, HID0_DCE
523 lis r4, 0
524 ori r4, r4, HID0_DLOCK
525 andc r3, r3, r4
526 ori r4, r3, HID0_DCI
527 sync
528 mtspr HID0, r4 /* sets enable and invalidate, clears lock */
529 sync
530 mtspr HID0, r3 /* clears invalidate */
531 blr
532
533 .globl dcache_disable
534dcache_disable:
535 mfspr r3, HID0
536 lis r4, 0
537 ori r4, r4, HID0_DCE|HID0_DLOCK
538 andc r3, r3, r4
539 ori r4, r3, HID0_DCI
540 sync
541 mtspr HID0, r4 /* sets invalidate, clears enable and lock */
542 sync
543 mtspr HID0, r3 /* clears invalidate */
544 blr
545
546 .globl dcache_status
547dcache_status:
548 mfspr r3, HID0
549 rlwinm r3, r3, HID0_DCE_BITPOS + 1, 31, 31
550 blr
551
552 .globl get_pvr
553get_pvr:
554 mfspr r3, PVR
555 blr
556
557/*------------------------------------------------------------------------------*/
558
559/*
560 * void relocate_code (addr_sp, gd, addr_moni)
561 *
562 * This "function" does not return, instead it continues in RAM
563 * after relocating the monitor code.
564 *
565 * r3 = dest
566 * r4 = src
567 * r5 = length in bytes
568 * r6 = cachelinesize
569 */
570 .globl relocate_code
571relocate_code:
572 mr r1, r3 /* Set new stack pointer */
573 mr r9, r4 /* Save copy of Global Data pointer */
574 mr r10, r5 /* Save copy of Destination Address */
575
576 mr r3, r5 /* Destination Address */
577 lis r4, CFG_MONITOR_BASE@h /* Source Address */
578 ori r4, r4, CFG_MONITOR_BASE@l
579 lwz r5, GOT(__init_end)
580 sub r5, r5, r4
581 li r6, CFG_CACHELINE_SIZE /* Cache Line Size */
582
583 /*
584 * Fix GOT pointer:
585 *
586 * New GOT-PTR = (old GOT-PTR - CFG_MONITOR_BASE) + Destination Address
587 *
588 * Offset:
589 */
590 sub r15, r10, r4
591
592 /* First our own GOT */
593 add r14, r14, r15
594 /* then the one used by the C code */
595 add r30, r30, r15
596
597 /*
598 * Now relocate code
599 */
600
601 cmplw cr1,r3,r4
602 addi r0,r5,3
603 srwi. r0,r0,2
604 beq cr1,4f /* In place copy is not necessary */
605 beq 7f /* Protect against 0 count */
606 mtctr r0
607 bge cr1,2f
608
609 la r8,-4(r4)
610 la r7,-4(r3)
6111: lwzu r0,4(r8)
612 stwu r0,4(r7)
613 bdnz 1b
614 b 4f
615
6162: slwi r0,r0,2
617 add r8,r4,r0
618 add r7,r3,r0
6193: lwzu r0,-4(r8)
620 stwu r0,-4(r7)
621 bdnz 3b
622
623/*
624 * Now flush the cache: note that we must start from a cache aligned
625 * address. Otherwise we might miss one cache line.
626 */
6274: cmpwi r6,0
628 add r5,r3,r5
629 beq 7f /* Always flush prefetch queue in any case */
630 subi r0,r6,1
631 andc r3,r3,r0
632 mfspr r7,HID0 /* don't do dcbst if dcache is disabled */
633 rlwinm r7,r7,HID0_DCE_BITPOS+1,31,31
634 cmpwi r7,0
635 beq 9f
636 mr r4,r3
6375: dcbst 0,r4
638 add r4,r4,r6
639 cmplw r4,r5
640 blt 5b
641 sync /* Wait for all dcbst to complete on bus */
6429: mfspr r7,HID0 /* don't do icbi if icache is disabled */
643 rlwinm r7,r7,HID0_ICE_BITPOS+1,31,31
644 cmpwi r7,0
645 beq 7f
646 mr r4,r3
6476: icbi 0,r4
648 add r4,r4,r6
649 cmplw r4,r5
650 blt 6b
6517: sync /* Wait for all icbi to complete on bus */
652 isync
653
654/*
655 * We are done. Do not return, instead branch to second part of board
656 * initialization, now running from RAM.
657 */
658
659 addi r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
660 mtlr r0
661 blr
662
663in_ram:
664
665 /*
666 * Relocation Function, r14 point to got2+0x8000
667 *
668 * Adjust got2 pointers, no need to check for 0, this code
669 * already puts a few entries in the table.
670 */
671 li r0,__got2_entries@sectoff@l
672 la r3,GOT(_GOT2_TABLE_)
673 lwz r11,GOT(_GOT2_TABLE_)
674 mtctr r0
675 sub r11,r3,r11
676 addi r3,r3,-4
6771: lwzu r0,4(r3)
678 add r0,r0,r11
679 stw r0,0(r3)
680 bdnz 1b
681
682 /*
683 * Now adjust the fixups and the pointers to the fixups
684 * in case we need to move ourselves again.
685 */
6862: li r0,__fixup_entries@sectoff@l
687 lwz r3,GOT(_FIXUP_TABLE_)
688 cmpwi r0,0
689 mtctr r0
690 addi r3,r3,-4
691 beq 4f
6923: lwzu r4,4(r3)
693 lwzux r0,r4,r11
694 add r0,r0,r11
695 stw r10,0(r3)
696 stw r0,0(r4)
697 bdnz 3b
6984:
699clear_bss:
700 /*
701 * Now clear BSS segment
702 */
703 lwz r3,GOT(__bss_start)
704 lwz r4,GOT(_end)
705
706 cmplw 0, r3, r4
707 beq 6f
708
709 li r0, 0
7105:
711 stw r0, 0(r3)
712 addi r3, r3, 4
713 cmplw 0, r3, r4
714 bne 5b
7156:
716
717 mr r3, r9 /* Global Data pointer */
718 mr r4, r10 /* Destination Address */
719 bl board_init_r
720
721 /*
722 * Copy exception vector code to low memory
723 *
724 * r3: dest_addr
725 * r7: source address, r8: end address, r9: target address
726 */
727 .globl trap_init
728trap_init:
729 lwz r7, GOT(_start)
730 lwz r8, GOT(_end_of_vectors)
731
732 li r9, 0x100 /* reset vector always at 0x100 */
733
734 cmplw 0, r7, r8
735 bgelr /* return if r7>=r8 - just in case */
736
737 mflr r4 /* save link register */
7381:
739 lwz r0, 0(r7)
740 stw r0, 0(r9)
741 addi r7, r7, 4
742 addi r9, r9, 4
743 cmplw 0, r7, r8
744 bne 1b
745
746 /*
747 * relocate `hdlr' and `int_return' entries
748 */
749 li r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
750 li r8, Alignment - _start + EXC_OFF_SYS_RESET
7512:
752 bl trap_reloc
753 addi r7, r7, 0x100 /* next exception vector */
754 cmplw 0, r7, r8
755 blt 2b
756
757 li r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
758 bl trap_reloc
759
760 li r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
761 bl trap_reloc
762
763 li r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
764 li r8, SystemCall - _start + EXC_OFF_SYS_RESET
7653:
766 bl trap_reloc
767 addi r7, r7, 0x100 /* next exception vector */
768 cmplw 0, r7, r8
769 blt 3b
770
771 li r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
772 li r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
7734:
774 bl trap_reloc
775 addi r7, r7, 0x100 /* next exception vector */
776 cmplw 0, r7, r8
777 blt 4b
778
779 mfmsr r3 /* now that the vectors have */
780 lis r7, MSR_IP@h /* relocated into low memory */
781 ori r7, r7, MSR_IP@l /* MSR[IP] can be turned off */
782 andc r3, r3, r7 /* (if it was on) */
783 SYNC /* Some chip revs need this... */
784 mtmsr r3
785 SYNC
786
787 mtlr r4 /* restore link register */
788 blr
789
790 /*
791 * Function: relocate entries for one exception vector
792 */
793trap_reloc:
794 lwz r0, 0(r7) /* hdlr ... */
795 add r0, r0, r3 /* ... += dest_addr */
796 stw r0, 0(r7)
797
798 lwz r0, 4(r7) /* int_return ... */
799 add r0, r0, r3 /* ... += dest_addr */
800 stw r0, 4(r7)
801
802 blr