blob: 0d63144356f01d130da131f362e4f08c767f4929 [file] [log] [blame]
wdenk47d1a6e2002-11-03 00:01:44 +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,2001,2002 Wolfgang Denk <wd@denx.de>
5 * Copyright (C) 2001 Josh Huber <huber@mclx.com>
6 *
7 * See file CREDITS for list of people who contributed to this
8 * project.
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License as
12 * published by the Free Software Foundation; either version 2 of
13 * the License, or (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
23 * MA 02111-1307 USA
24 */
25
26/* U-Boot - Startup Code for PowerPC based Embedded Boards
27 *
28 *
29 * The processor starts at 0xfff00100 and the code is executed
30 * from flash. The code is organized to be at an other address
31 * in memory, but as long we don't jump around before relocating.
32 * board_init lies at a quite high address and when the cpu has
33 * jumped there, everything is ok.
34 */
35#include <config.h>
36#include <74xx_7xx.h>
37#include <version.h>
38
39#include <ppc_asm.tmpl>
40#include <ppc_defs.h>
41
42#include <asm/cache.h>
43#include <asm/mmu.h>
44
45#include <galileo/gt64260R.h>
46
47#ifndef CONFIG_IDENT_STRING
48#define CONFIG_IDENT_STRING ""
49#endif
50
51/* We don't want the MMU yet.
52*/
53#undef MSR_KERNEL
54/* Machine Check and Recoverable Interr. */
55#define MSR_KERNEL ( MSR_ME | MSR_RI )
56
57/*
58 * Set up GOT: Global Offset Table
59 *
60 * Use r14 to access the GOT
61 */
62 START_GOT
63 GOT_ENTRY(_GOT2_TABLE_)
64 GOT_ENTRY(_FIXUP_TABLE_)
65
66 GOT_ENTRY(_start)
67 GOT_ENTRY(_start_of_vectors)
68 GOT_ENTRY(_end_of_vectors)
69 GOT_ENTRY(transfer_to_handler)
70
71 GOT_ENTRY(_end)
72 GOT_ENTRY(.bss)
73 END_GOT
74
75/*
76 * r3 - 1st arg to board_init(): IMMP pointer
77 * r4 - 2nd arg to board_init(): boot flag
78 */
79 .text
80 .long 0x27051956 /* U-Boot Magic Number */
81 .globl version_string
82version_string:
83 .ascii U_BOOT_VERSION
84 .ascii " (", __DATE__, " - ", __TIME__, ")"
85 .ascii CONFIG_IDENT_STRING, "\0"
86
87 . = EXC_OFF_SYS_RESET
88 .globl _start
89_start:
90 li r21, BOOTFLAG_COLD /* Normal Power-On: Boot from FLASH */
91 b boot_cold
92 sync
93
94 . = EXC_OFF_SYS_RESET + 0x10
95
96 .globl _start_warm
97_start_warm:
98 li r21, BOOTFLAG_WARM /* Software reboot */
99 b boot_warm
100 sync
101
102 /* the boot code is located below the exception table */
103
104 .globl _start_of_vectors
105_start_of_vectors:
106
107/* Machine check */
108 STD_EXCEPTION(0x200, MachineCheck, MachineCheckException)
109
110/* Data Storage exception. "Never" generated on the 860. */
111 STD_EXCEPTION(0x300, DataStorage, UnknownException)
112
113/* Instruction Storage exception. "Never" generated on the 860. */
114 STD_EXCEPTION(0x400, InstStorage, UnknownException)
115
116/* External Interrupt exception. */
117 STD_EXCEPTION(0x500, ExtInterrupt, external_interrupt)
118
119/* Alignment exception. */
120 . = 0x600
121Alignment:
122 EXCEPTION_PROLOG
123 mfspr r4,DAR
124 stw r4,_DAR(r21)
125 mfspr r5,DSISR
126 stw r5,_DSISR(r21)
127 addi r3,r1,STACK_FRAME_OVERHEAD
128 li r20,MSR_KERNEL
129 rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */
130 lwz r6,GOT(transfer_to_handler)
131 mtlr r6
132 blrl
133.L_Alignment:
134 .long AlignmentException - _start + EXC_OFF_SYS_RESET
135 .long int_return - _start + EXC_OFF_SYS_RESET
136
137/* Program check exception */
138 . = 0x700
139ProgramCheck:
140 EXCEPTION_PROLOG
141 addi r3,r1,STACK_FRAME_OVERHEAD
142 li r20,MSR_KERNEL
143 rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */
144 lwz r6,GOT(transfer_to_handler)
145 mtlr r6
146 blrl
147.L_ProgramCheck:
148 .long ProgramCheckException - _start + EXC_OFF_SYS_RESET
149 .long int_return - _start + EXC_OFF_SYS_RESET
150
151 /* No FPU on MPC8xx. This exception is not supposed to happen.
152 */
153 STD_EXCEPTION(0x800, FPUnavailable, UnknownException)
154
155 /* I guess we could implement decrementer, and may have
156 * to someday for timekeeping.
157 */
158 STD_EXCEPTION(0x900, Decrementer, timer_interrupt)
159 STD_EXCEPTION(0xa00, Trap_0a, UnknownException)
160 STD_EXCEPTION(0xb00, Trap_0b, UnknownException)
161
162 . = 0xc00
163/*
164 * r0 - SYSCALL number
165 * r3-... arguments
166 */
167SystemCall:
168 addis r11,r0,0 /* get functions table addr */
169 ori r11,r11,0 /* Note: this code is patched in trap_init */
170 addis r12,r0,0 /* get number of functions */
171 ori r12,r12,0
172
173 cmplw 0, r0, r12
174 bge 1f
175
176 rlwinm r0,r0,2,0,31 /* fn_addr = fn_tbl[r0] */
177 add r11,r11,r0
178 lwz r11,0(r11)
179
wdenk7c7a23b2002-12-07 00:20:59 +0000180 li r20,0xd00-4 /* Get stack pointer */
181 lwz r12,0(r20)
182 subi r12,r12,12 /* Adjust stack pointer */
183 li r0,0xc00+_end_back-SystemCall
184 cmplw 0, r0, r12 /* Check stack overflow */
185 bgt 1f
186 stw r12,0(r20)
187
wdenk47d1a6e2002-11-03 00:01:44 +0000188 mflr r0
189 stw r0,0(r12)
190 mfspr r0,SRR0
191 stw r0,4(r12)
192 mfspr r0,SRR1
193 stw r0,8(r12)
194
195 li r12,0xc00+_back-SystemCall
196 mtlr r12
197 mtspr SRR0,r11
198
1991: SYNC
200 rfi
201
202_back:
203
204 mfmsr r11 /* Disable interrupts */
205 li r12,0
206 ori r12,r12,MSR_EE
207 andc r11,r11,r12
208 SYNC /* Some chip revs need this... */
209 mtmsr r11
210 SYNC
211
wdenk7c7a23b2002-12-07 00:20:59 +0000212 li r12,0xd00-4 /* restore regs */
213 lwz r12,0(r12)
214
wdenk47d1a6e2002-11-03 00:01:44 +0000215 lwz r11,0(r12)
216 mtlr r11
217 lwz r11,4(r12)
218 mtspr SRR0,r11
219 lwz r11,8(r12)
220 mtspr SRR1,r11
221
wdenk7c7a23b2002-12-07 00:20:59 +0000222 addi r12,r12,12 /* Adjust stack pointer */
223 li r20,0xd00-4
224 stw r12,0(r20)
225
wdenk47d1a6e2002-11-03 00:01:44 +0000226 SYNC
227 rfi
wdenk7c7a23b2002-12-07 00:20:59 +0000228_end_back:
wdenk47d1a6e2002-11-03 00:01:44 +0000229
230 STD_EXCEPTION(0xd00, SingleStep, UnknownException)
231
232 STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
233 STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
234
235 /*
236 * On the MPC8xx, this is a software emulation interrupt. It
237 * occurs for all unimplemented and illegal instructions.
238 */
239 STD_EXCEPTION(0x1000, SoftEmu, SoftEmuException)
240
241 STD_EXCEPTION(0x1100, InstructionTLBMiss, UnknownException)
242 STD_EXCEPTION(0x1200, DataTLBMiss, UnknownException)
243 STD_EXCEPTION(0x1300, InstructionTLBError, UnknownException)
244 STD_EXCEPTION(0x1400, DataTLBError, UnknownException)
245
246 STD_EXCEPTION(0x1500, Reserved5, UnknownException)
247 STD_EXCEPTION(0x1600, Reserved6, UnknownException)
248 STD_EXCEPTION(0x1700, Reserved7, UnknownException)
249 STD_EXCEPTION(0x1800, Reserved8, UnknownException)
250 STD_EXCEPTION(0x1900, Reserved9, UnknownException)
251 STD_EXCEPTION(0x1a00, ReservedA, UnknownException)
252 STD_EXCEPTION(0x1b00, ReservedB, UnknownException)
253
254 STD_EXCEPTION(0x1c00, DataBreakpoint, UnknownException)
255 STD_EXCEPTION(0x1d00, InstructionBreakpoint, UnknownException)
256 STD_EXCEPTION(0x1e00, PeripheralBreakpoint, UnknownException)
257 STD_EXCEPTION(0x1f00, DevPortBreakpoint, UnknownException)
258
259 .globl _end_of_vectors
260_end_of_vectors:
261
262 . = 0x2000
263
264boot_cold:
265boot_warm:
266 /* disable everything */
267 li r0, 0
268 mtspr HID0, r0
269 sync
270 mtmsr 0
271 bl invalidate_bats
272 sync
273
274#ifdef CFG_L2
275 /* init the L2 cache */
276 addis r3, r0, L2_INIT@h
277 ori r3, r3, L2_INIT@l
278 sync
279 mtspr l2cr, r3
280#endif
281#if defined(CONFIG_ALTIVEC) && defined(CONFIG_74xx)
282 .long 0x7e00066c
283 /*
284 * dssall instruction, gas doesn't have it yet
285 * ...for altivec, data stream stop all this probably
286 * isn't needed unless we warm (software) reboot U-Boot
287 */
288#endif
289
290#ifdef CFG_L2
291 /* invalidate the L2 cache */
292 bl l2cache_invalidate
293 sync
294#endif
295#ifdef CFG_BOARD_ASM_INIT
296 /* do early init */
297 bl board_asm_init
298#endif
299
300 /*
301 * Calculate absolute address in FLASH and jump there
302 *------------------------------------------------------*/
303 lis r3, CFG_MONITOR_BASE@h
304 ori r3, r3, CFG_MONITOR_BASE@l
305 addi r3, r3, in_flash - _start + EXC_OFF_SYS_RESET
306 mtlr r3
307 blr
308
309in_flash:
310 /* let the C-code set up the rest */
311 /* */
312 /* Be careful to keep code relocatable ! */
313 /*------------------------------------------------------*/
314
315 /* perform low-level init */
316 /* sdram init, galileo init, etc */
317 /* r3: NHR bit from HID0 */
318
319 /* setup the bats */
320 bl setup_bats
321 sync
322
323 /*
324 * Cache must be enabled here for stack-in-cache trick.
325 * This means we need to enable the BATS.
326 * This means:
327 * 1) for the EVB, original gt regs need to be mapped
328 * 2) need to have an IBAT for the 0xf region,
329 * we are running there!
330 * Cache should be turned on after BATs, since by default
331 * everything is write-through.
332 * The init-mem BAT can be reused after reloc. The old
333 * gt-regs BAT can be reused after board_init_f calls
334 * board_pre_init (EVB only).
335 */
336#if !defined(CONFIG_BAB7xx) && !defined(CONFIG_ELPPC)
337 /* enable address translation */
338 bl enable_addr_trans
339 sync
340
341 /* enable and invalidate the data cache */
342 bl l1dcache_enable
343 sync
344#endif
345#ifdef CFG_INIT_RAM_LOCK
346 bl lock_ram_in_cache
347 sync
348#endif
349
350 /* set up the stack pointer in our newly created
351 * cache-ram (r1) */
352 lis r1, (CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET)@h
353 ori r1, r1, (CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET)@l
354
355 li r0, 0 /* Make room for stack frame header and */
356 stwu r0, -4(r1) /* clear final stack frame so that */
357 stwu r0, -4(r1) /* stack backtraces terminate cleanly */
358
359 GET_GOT /* initialize GOT access */
360
361 /* run low-level CPU init code (from Flash) */
362 bl cpu_init_f
363 sync
364
365 mr r3, r21
366
367 /* r3: BOOTFLAG */
368 /* run 1st part of board init code (from Flash) */
369 bl board_init_f
370 sync
371
372 /* NOTREACHED */
373
374 .globl invalidate_bats
375invalidate_bats:
376 /* invalidate BATs */
377 mtspr IBAT0U, r0
378 mtspr IBAT1U, r0
379 mtspr IBAT2U, r0
380 mtspr IBAT3U, r0
381 isync
382 mtspr DBAT0U, r0
383 mtspr DBAT1U, r0
384 mtspr DBAT2U, r0
385 mtspr DBAT3U, r0
386 isync
387 sync
388 blr
389
390 /* setup_bats - set them up to some initial state */
391 .globl setup_bats
392setup_bats:
393 addis r0, r0, 0x0000
394
395 /* IBAT 0 */
396 addis r4, r0, CFG_IBAT0L@h
397 ori r4, r4, CFG_IBAT0L@l
398 addis r3, r0, CFG_IBAT0U@h
399 ori r3, r3, CFG_IBAT0U@l
400 mtspr IBAT0L, r4
401 mtspr IBAT0U, r3
402 isync
403
404 /* DBAT 0 */
405 addis r4, r0, CFG_DBAT0L@h
406 ori r4, r4, CFG_DBAT0L@l
407 addis r3, r0, CFG_DBAT0U@h
408 ori r3, r3, CFG_DBAT0U@l
409 mtspr DBAT0L, r4
410 mtspr DBAT0U, r3
411 isync
412
413 /* IBAT 1 */
414 addis r4, r0, CFG_IBAT1L@h
415 ori r4, r4, CFG_IBAT1L@l
416 addis r3, r0, CFG_IBAT1U@h
417 ori r3, r3, CFG_IBAT1U@l
418 mtspr IBAT1L, r4
419 mtspr IBAT1U, r3
420 isync
421
422 /* DBAT 1 */
423 addis r4, r0, CFG_DBAT1L@h
424 ori r4, r4, CFG_DBAT1L@l
425 addis r3, r0, CFG_DBAT1U@h
426 ori r3, r3, CFG_DBAT1U@l
427 mtspr DBAT1L, r4
428 mtspr DBAT1U, r3
429 isync
430
431 /* IBAT 2 */
432 addis r4, r0, CFG_IBAT2L@h
433 ori r4, r4, CFG_IBAT2L@l
434 addis r3, r0, CFG_IBAT2U@h
435 ori r3, r3, CFG_IBAT2U@l
436 mtspr IBAT2L, r4
437 mtspr IBAT2U, r3
438 isync
439
440 /* DBAT 2 */
441 addis r4, r0, CFG_DBAT2L@h
442 ori r4, r4, CFG_DBAT2L@l
443 addis r3, r0, CFG_DBAT2U@h
444 ori r3, r3, CFG_DBAT2U@l
445 mtspr DBAT2L, r4
446 mtspr DBAT2U, r3
447 isync
448
449 /* IBAT 3 */
450 addis r4, r0, CFG_IBAT3L@h
451 ori r4, r4, CFG_IBAT3L@l
452 addis r3, r0, CFG_IBAT3U@h
453 ori r3, r3, CFG_IBAT3U@l
454 mtspr IBAT3L, r4
455 mtspr IBAT3U, r3
456 isync
457
458 /* DBAT 3 */
459 addis r4, r0, CFG_DBAT3L@h
460 ori r4, r4, CFG_DBAT3L@l
461 addis r3, r0, CFG_DBAT3U@h
462 ori r3, r3, CFG_DBAT3U@l
463 mtspr DBAT3L, r4
464 mtspr DBAT3U, r3
465 isync
466
467 /* bats are done, now invalidate the TLBs */
468
469 addis r3, 0, 0x0000
470 addis r5, 0, 0x4 /* upper bound of 0x00040000 for 7400/750 */
471
472 isync
473
474tlblp:
475 tlbie r3
476 sync
477 addi r3, r3, 0x1000
478 cmp 0, 0, r3, r5
479 blt tlblp
480
481 blr
482
483 .globl enable_addr_trans
484enable_addr_trans:
485 /* enable address translation */
486 mfmsr r5
487 ori r5, r5, (MSR_IR | MSR_DR)
488 mtmsr r5
489 isync
490 blr
491
492 .globl disable_addr_trans
493disable_addr_trans:
494 /* disable address translation */
495 mflr r4
496 mfmsr r3
497 andi. r0, r3, (MSR_IR | MSR_DR)
498 beqlr
499 andc r3, r3, r0
500 mtspr SRR0, r4
501 mtspr SRR1, r3
502 rfi
503
504/*
505 * This code finishes saving the registers to the exception frame
506 * and jumps to the appropriate handler for the exception.
507 * Register r21 is pointer into trap frame, r1 has new stack pointer.
508 */
509 .globl transfer_to_handler
510transfer_to_handler:
511 stw r22,_NIP(r21)
512 lis r22,MSR_POW@h
513 andc r23,r23,r22
514 stw r23,_MSR(r21)
515 SAVE_GPR(7, r21)
516 SAVE_4GPRS(8, r21)
517 SAVE_8GPRS(12, r21)
518 SAVE_8GPRS(24, r21)
519 mflr r23
520 andi. r24,r23,0x3f00 /* get vector offset */
521 stw r24,TRAP(r21)
522 li r22,0
523 stw r22,RESULT(r21)
524 mtspr SPRG2,r22 /* r1 is now kernel sp */
525 lwz r24,0(r23) /* virtual address of handler */
526 lwz r23,4(r23) /* where to go when done */
527 mtspr SRR0,r24
528 mtspr SRR1,r20
529 mtlr r23
530 SYNC
531 rfi /* jump to handler, enable MMU */
532
533int_return:
534 mfmsr r28 /* Disable interrupts */
535 li r4,0
536 ori r4,r4,MSR_EE
537 andc r28,r28,r4
538 SYNC /* Some chip revs need this... */
539 mtmsr r28
540 SYNC
541 lwz r2,_CTR(r1)
542 lwz r0,_LINK(r1)
543 mtctr r2
544 mtlr r0
545 lwz r2,_XER(r1)
546 lwz r0,_CCR(r1)
547 mtspr XER,r2
548 mtcrf 0xFF,r0
549 REST_10GPRS(3, r1)
550 REST_10GPRS(13, r1)
551 REST_8GPRS(23, r1)
552 REST_GPR(31, r1)
553 lwz r2,_NIP(r1) /* Restore environment */
554 lwz r0,_MSR(r1)
555 mtspr SRR0,r2
556 mtspr SRR1,r0
557 lwz r0,GPR0(r1)
558 lwz r2,GPR2(r1)
559 lwz r1,GPR1(r1)
560 SYNC
561 rfi
562
563 .globl dc_read
564dc_read:
565 blr
566
567 .globl get_pvr
568get_pvr:
569 mfspr r3, PVR
570 blr
571
572/*-----------------------------------------------------------------------*/
573/*
574 * void relocate_code (addr_sp, gd, addr_moni)
575 *
576 * This "function" does not return, instead it continues in RAM
577 * after relocating the monitor code.
578 *
579 * r3 = dest
580 * r4 = src
581 * r5 = length in bytes
582 * r6 = cachelinesize
583 */
584 .globl relocate_code
585relocate_code:
586 mr r1, r3 /* Set new stack pointer */
587 mr r9, r4 /* Save copy of Global Data pointer */
588 mr r10, r5 /* Save copy of Destination Address */
589
590 mr r3, r5 /* Destination Address */
591 lis r4, CFG_MONITOR_BASE@h /* Source Address */
592 ori r4, r4, CFG_MONITOR_BASE@l
593 lis r5, CFG_MONITOR_LEN@h /* Length in Bytes */
594 ori r5, r5, CFG_MONITOR_LEN@l
595 li r6, CFG_CACHELINE_SIZE /* Cache Line Size */
596
597 /*
598 * Fix GOT pointer:
599 *
600 * New GOT-PTR = (old GOT-PTR - CFG_MONITOR_BASE) + Destination Address
601 *
602 * Offset:
603 */
604 sub r15, r10, r4
605
606 /* First our own GOT */
607 add r14, r14, r15
608 /* then the one used by the C code */
609 add r30, r30, r15
610
611 /*
612 * Now relocate code
613 */
614#ifdef CONFIG_ECC
615 bl board_relocate_rom
616 sync
617 mr r3, r10 /* Destination Address */
618 lis r4, CFG_MONITOR_BASE@h /* Source Address */
619 ori r4, r4, CFG_MONITOR_BASE@l
620 lis r5, CFG_MONITOR_LEN@h /* Length in Bytes */
621 ori r5, r5, CFG_MONITOR_LEN@l
622 li r6, CFG_CACHELINE_SIZE /* Cache Line Size */
623#else
624 cmplw cr1,r3,r4
625 addi r0,r5,3
626 srwi. r0,r0,2
627 beq cr1,4f /* In place copy is not necessary */
628 beq 7f /* Protect against 0 count */
629 mtctr r0
630 bge cr1,2f
631
632 la r8,-4(r4)
633 la r7,-4(r3)
6341: lwzu r0,4(r8)
635 stwu r0,4(r7)
636 bdnz 1b
637 b 4f
638
6392: slwi r0,r0,2
640 add r8,r4,r0
641 add r7,r3,r0
6423: lwzu r0,-4(r8)
643 stwu r0,-4(r7)
644 bdnz 3b
645#endif
646/*
647 * Now flush the cache: note that we must start from a cache aligned
648 * address. Otherwise we might miss one cache line.
649 */
6504: cmpwi r6,0
651 add r5,r3,r5
652 beq 7f /* Always flush prefetch queue in any case */
653 subi r0,r6,1
654 andc r3,r3,r0
655 mr r4,r3
6565: dcbst 0,r4
657 add r4,r4,r6
658 cmplw r4,r5
659 blt 5b
660 sync /* Wait for all dcbst to complete on bus */
661 mr r4,r3
6626: icbi 0,r4
663 add r4,r4,r6
664 cmplw r4,r5
665 blt 6b
6667: sync /* Wait for all icbi to complete on bus */
667 isync
668
669/*
670 * We are done. Do not return, instead branch to second part of board
671 * initialization, now running from RAM.
672 */
673 addi r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
674 mtlr r0
675 blr
676
677in_ram:
678#ifdef CONFIG_ECC
679 bl board_init_ecc
680#endif
681 /*
682 * Relocation Function, r14 point to got2+0x8000
683 *
684 * Adjust got2 pointers, no need to check for 0, this code
685 * already puts a few entries in the table.
686 */
687 li r0,__got2_entries@sectoff@l
688 la r3,GOT(_GOT2_TABLE_)
689 lwz r11,GOT(_GOT2_TABLE_)
690 mtctr r0
691 sub r11,r3,r11
692 addi r3,r3,-4
6931: lwzu r0,4(r3)
694 add r0,r0,r11
695 stw r0,0(r3)
696 bdnz 1b
697
698 /*
699 * Now adjust the fixups and the pointers to the fixups
700 * in case we need to move ourselves again.
701 */
7022: li r0,__fixup_entries@sectoff@l
703 lwz r3,GOT(_FIXUP_TABLE_)
704 cmpwi r0,0
705 mtctr r0
706 addi r3,r3,-4
707 beq 4f
7083: lwzu r4,4(r3)
709 lwzux r0,r4,r11
710 add r0,r0,r11
711 stw r10,0(r3)
712 stw r0,0(r4)
713 bdnz 3b
7144:
715/* clear_bss: */
716 /*
717 * Now clear BSS segment
718 */
719 lwz r3,GOT(.bss)
720 lwz r4,GOT(_end)
721
722 cmplw 0, r3, r4
723 beq 6f
724
725 li r0, 0
7265:
727 stw r0, 0(r3)
728 addi r3, r3, 4
729 cmplw 0, r3, r4
730 bne 5b
7316:
732 mr r3, r10 /* Destination Address */
wdenk7c7a23b2002-12-07 00:20:59 +0000733#ifdef CONFIG_AMIGAONEG3SE
734 mr r4, r9 /* Use RAM copy of the global data */
735#endif
wdenk47d1a6e2002-11-03 00:01:44 +0000736 bl after_reloc
737
738 /* not reached - end relocate_code */
739/*-----------------------------------------------------------------------*/
740
741 /* Problems accessing "end" in C, so do it here */
742 .globl get_endaddr
743get_endaddr:
744 lwz r3,GOT(_end)
745 blr
746
747 /*
748 * Copy exception vector code to low memory
749 *
750 * r3: dest_addr
751 * r7: source address, r8: end address, r9: target address
752 */
753 .globl trap_init
754trap_init:
755 lwz r7, GOT(_start)
756 lwz r8, GOT(_end_of_vectors)
757
758 rlwinm r9, r7, 0, 18, 31 /* _start & 0x3FFF */
759
760 cmplw 0, r7, r8
761 bgelr /* return if r7>=r8 - just in case */
762
763 mflr r4 /* save link register */
7641:
765 lwz r0, 0(r7)
766 stw r0, 0(r9)
767 addi r7, r7, 4
768 addi r9, r9, 4
769 cmplw 0, r7, r8
770 bne 1b
771
772 /*
773 * relocate `hdlr' and `int_return' entries
774 */
775 li r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
776 li r8, Alignment - _start + EXC_OFF_SYS_RESET
7772:
778 bl trap_reloc
779 addi r7, r7, 0x100 /* next exception vector */
780 cmplw 0, r7, r8
781 blt 2b
782
783 li r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
784 bl trap_reloc
785
786 li r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
787 bl trap_reloc
788
789 li r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
790 li r8, SystemCall - _start + EXC_OFF_SYS_RESET
7913:
792 bl trap_reloc
793 addi r7, r7, 0x100 /* next exception vector */
794 cmplw 0, r7, r8
795 blt 3b
796
797 li r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
798 li r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
7994:
800 bl trap_reloc
801 addi r7, r7, 0x100 /* next exception vector */
802 cmplw 0, r7, r8
803 blt 4b
804
805 /* enable execptions from RAM vectors */
806 mfmsr r7
807 li r8,MSR_IP
808 andc r7,r7,r8
809 mtmsr r7
810
811 mtlr r4 /* restore link register */
812 blr
813
814 /*
815 * Function: relocate entries for one exception vector
816 */
817trap_reloc:
818 lwz r0, 0(r7) /* hdlr ... */
819 add r0, r0, r3 /* ... += dest_addr */
820 stw r0, 0(r7)
821
822 lwz r0, 4(r7) /* int_return ... */
823 add r0, r0, r3 /* ... += dest_addr */
824 stw r0, 4(r7)
825
826 sync
827 isync
828
829 blr
830
831#ifdef CFG_INIT_RAM_LOCK
832lock_ram_in_cache:
833 /* Allocate Initial RAM in data cache.
834 */
835 lis r3, (CFG_INIT_RAM_ADDR & ~31)@h
836 ori r3, r3, (CFG_INIT_RAM_ADDR & ~31)@l
837 li r2, ((CFG_INIT_RAM_END & ~31) + \
838 (CFG_INIT_RAM_ADDR & 31) + 31) / 32
839 mtctr r2
8401:
841 dcbz r0, r3
842 addi r3, r3, 32
843 bdnz 1b
844
845 /* Lock the data cache */
846 mfspr r0, HID0
847 ori r0, r0, 0x1000
848 sync
849 mtspr HID0, r0
850 sync
851 blr
852
853.globl unlock_ram_in_cache
854unlock_ram_in_cache:
855 /* invalidate the INIT_RAM section */
856 lis r3, (CFG_INIT_RAM_ADDR & ~31)@h
857 ori r3, r3, (CFG_INIT_RAM_ADDR & ~31)@l
858 li r2, ((CFG_INIT_RAM_END & ~31) + \
859 (CFG_INIT_RAM_ADDR & 31) + 31) / 32
860 mtctr r2
8611: icbi r0, r3
862 addi r3, r3, 32
863 bdnz 1b
864 sync /* Wait for all icbi to complete on bus */
865 isync
866
867 /* Unlock the data cache and invalidate it */
868 mfspr r0, HID0
869 li r3,0x1000
870 andc r0,r0,r3
871 li r3,0x0400
872 or r0,r0,r3
873 sync
874 mtspr HID0, r0
875 sync
876 blr
877#endif