blob: fe08f8e8379df5657872f59f2437ab0217ffced6 [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
180 li r12,0xd00-4*3 /* save LR & SRRx */
181 mflr r0
182 stw r0,0(r12)
183 mfspr r0,SRR0
184 stw r0,4(r12)
185 mfspr r0,SRR1
186 stw r0,8(r12)
187
188 li r12,0xc00+_back-SystemCall
189 mtlr r12
190 mtspr SRR0,r11
191
1921: SYNC
193 rfi
194
195_back:
196
197 mfmsr r11 /* Disable interrupts */
198 li r12,0
199 ori r12,r12,MSR_EE
200 andc r11,r11,r12
201 SYNC /* Some chip revs need this... */
202 mtmsr r11
203 SYNC
204
205 li r12,0xd00-4*3 /* restore regs */
206 lwz r11,0(r12)
207 mtlr r11
208 lwz r11,4(r12)
209 mtspr SRR0,r11
210 lwz r11,8(r12)
211 mtspr SRR1,r11
212
213 SYNC
214 rfi
215
216 STD_EXCEPTION(0xd00, SingleStep, UnknownException)
217
218 STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
219 STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
220
221 /*
222 * On the MPC8xx, this is a software emulation interrupt. It
223 * occurs for all unimplemented and illegal instructions.
224 */
225 STD_EXCEPTION(0x1000, SoftEmu, SoftEmuException)
226
227 STD_EXCEPTION(0x1100, InstructionTLBMiss, UnknownException)
228 STD_EXCEPTION(0x1200, DataTLBMiss, UnknownException)
229 STD_EXCEPTION(0x1300, InstructionTLBError, UnknownException)
230 STD_EXCEPTION(0x1400, DataTLBError, UnknownException)
231
232 STD_EXCEPTION(0x1500, Reserved5, UnknownException)
233 STD_EXCEPTION(0x1600, Reserved6, UnknownException)
234 STD_EXCEPTION(0x1700, Reserved7, UnknownException)
235 STD_EXCEPTION(0x1800, Reserved8, UnknownException)
236 STD_EXCEPTION(0x1900, Reserved9, UnknownException)
237 STD_EXCEPTION(0x1a00, ReservedA, UnknownException)
238 STD_EXCEPTION(0x1b00, ReservedB, UnknownException)
239
240 STD_EXCEPTION(0x1c00, DataBreakpoint, UnknownException)
241 STD_EXCEPTION(0x1d00, InstructionBreakpoint, UnknownException)
242 STD_EXCEPTION(0x1e00, PeripheralBreakpoint, UnknownException)
243 STD_EXCEPTION(0x1f00, DevPortBreakpoint, UnknownException)
244
245 .globl _end_of_vectors
246_end_of_vectors:
247
248 . = 0x2000
249
250boot_cold:
251boot_warm:
252 /* disable everything */
253 li r0, 0
254 mtspr HID0, r0
255 sync
256 mtmsr 0
257 bl invalidate_bats
258 sync
259
260#ifdef CFG_L2
261 /* init the L2 cache */
262 addis r3, r0, L2_INIT@h
263 ori r3, r3, L2_INIT@l
264 sync
265 mtspr l2cr, r3
266#endif
267#if defined(CONFIG_ALTIVEC) && defined(CONFIG_74xx)
268 .long 0x7e00066c
269 /*
270 * dssall instruction, gas doesn't have it yet
271 * ...for altivec, data stream stop all this probably
272 * isn't needed unless we warm (software) reboot U-Boot
273 */
274#endif
275
276#ifdef CFG_L2
277 /* invalidate the L2 cache */
278 bl l2cache_invalidate
279 sync
280#endif
281#ifdef CFG_BOARD_ASM_INIT
282 /* do early init */
283 bl board_asm_init
284#endif
285
286 /*
287 * Calculate absolute address in FLASH and jump there
288 *------------------------------------------------------*/
289 lis r3, CFG_MONITOR_BASE@h
290 ori r3, r3, CFG_MONITOR_BASE@l
291 addi r3, r3, in_flash - _start + EXC_OFF_SYS_RESET
292 mtlr r3
293 blr
294
295in_flash:
296 /* let the C-code set up the rest */
297 /* */
298 /* Be careful to keep code relocatable ! */
299 /*------------------------------------------------------*/
300
301 /* perform low-level init */
302 /* sdram init, galileo init, etc */
303 /* r3: NHR bit from HID0 */
304
305 /* setup the bats */
306 bl setup_bats
307 sync
308
309 /*
310 * Cache must be enabled here for stack-in-cache trick.
311 * This means we need to enable the BATS.
312 * This means:
313 * 1) for the EVB, original gt regs need to be mapped
314 * 2) need to have an IBAT for the 0xf region,
315 * we are running there!
316 * Cache should be turned on after BATs, since by default
317 * everything is write-through.
318 * The init-mem BAT can be reused after reloc. The old
319 * gt-regs BAT can be reused after board_init_f calls
320 * board_pre_init (EVB only).
321 */
322#if !defined(CONFIG_BAB7xx) && !defined(CONFIG_ELPPC)
323 /* enable address translation */
324 bl enable_addr_trans
325 sync
326
327 /* enable and invalidate the data cache */
328 bl l1dcache_enable
329 sync
330#endif
331#ifdef CFG_INIT_RAM_LOCK
332 bl lock_ram_in_cache
333 sync
334#endif
335
336 /* set up the stack pointer in our newly created
337 * cache-ram (r1) */
338 lis r1, (CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET)@h
339 ori r1, r1, (CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET)@l
340
341 li r0, 0 /* Make room for stack frame header and */
342 stwu r0, -4(r1) /* clear final stack frame so that */
343 stwu r0, -4(r1) /* stack backtraces terminate cleanly */
344
345 GET_GOT /* initialize GOT access */
346
347 /* run low-level CPU init code (from Flash) */
348 bl cpu_init_f
349 sync
350
351 mr r3, r21
352
353 /* r3: BOOTFLAG */
354 /* run 1st part of board init code (from Flash) */
355 bl board_init_f
356 sync
357
358 /* NOTREACHED */
359
360 .globl invalidate_bats
361invalidate_bats:
362 /* invalidate BATs */
363 mtspr IBAT0U, r0
364 mtspr IBAT1U, r0
365 mtspr IBAT2U, r0
366 mtspr IBAT3U, r0
367 isync
368 mtspr DBAT0U, r0
369 mtspr DBAT1U, r0
370 mtspr DBAT2U, r0
371 mtspr DBAT3U, r0
372 isync
373 sync
374 blr
375
376 /* setup_bats - set them up to some initial state */
377 .globl setup_bats
378setup_bats:
379 addis r0, r0, 0x0000
380
381 /* IBAT 0 */
382 addis r4, r0, CFG_IBAT0L@h
383 ori r4, r4, CFG_IBAT0L@l
384 addis r3, r0, CFG_IBAT0U@h
385 ori r3, r3, CFG_IBAT0U@l
386 mtspr IBAT0L, r4
387 mtspr IBAT0U, r3
388 isync
389
390 /* DBAT 0 */
391 addis r4, r0, CFG_DBAT0L@h
392 ori r4, r4, CFG_DBAT0L@l
393 addis r3, r0, CFG_DBAT0U@h
394 ori r3, r3, CFG_DBAT0U@l
395 mtspr DBAT0L, r4
396 mtspr DBAT0U, r3
397 isync
398
399 /* IBAT 1 */
400 addis r4, r0, CFG_IBAT1L@h
401 ori r4, r4, CFG_IBAT1L@l
402 addis r3, r0, CFG_IBAT1U@h
403 ori r3, r3, CFG_IBAT1U@l
404 mtspr IBAT1L, r4
405 mtspr IBAT1U, r3
406 isync
407
408 /* DBAT 1 */
409 addis r4, r0, CFG_DBAT1L@h
410 ori r4, r4, CFG_DBAT1L@l
411 addis r3, r0, CFG_DBAT1U@h
412 ori r3, r3, CFG_DBAT1U@l
413 mtspr DBAT1L, r4
414 mtspr DBAT1U, r3
415 isync
416
417 /* IBAT 2 */
418 addis r4, r0, CFG_IBAT2L@h
419 ori r4, r4, CFG_IBAT2L@l
420 addis r3, r0, CFG_IBAT2U@h
421 ori r3, r3, CFG_IBAT2U@l
422 mtspr IBAT2L, r4
423 mtspr IBAT2U, r3
424 isync
425
426 /* DBAT 2 */
427 addis r4, r0, CFG_DBAT2L@h
428 ori r4, r4, CFG_DBAT2L@l
429 addis r3, r0, CFG_DBAT2U@h
430 ori r3, r3, CFG_DBAT2U@l
431 mtspr DBAT2L, r4
432 mtspr DBAT2U, r3
433 isync
434
435 /* IBAT 3 */
436 addis r4, r0, CFG_IBAT3L@h
437 ori r4, r4, CFG_IBAT3L@l
438 addis r3, r0, CFG_IBAT3U@h
439 ori r3, r3, CFG_IBAT3U@l
440 mtspr IBAT3L, r4
441 mtspr IBAT3U, r3
442 isync
443
444 /* DBAT 3 */
445 addis r4, r0, CFG_DBAT3L@h
446 ori r4, r4, CFG_DBAT3L@l
447 addis r3, r0, CFG_DBAT3U@h
448 ori r3, r3, CFG_DBAT3U@l
449 mtspr DBAT3L, r4
450 mtspr DBAT3U, r3
451 isync
452
453 /* bats are done, now invalidate the TLBs */
454
455 addis r3, 0, 0x0000
456 addis r5, 0, 0x4 /* upper bound of 0x00040000 for 7400/750 */
457
458 isync
459
460tlblp:
461 tlbie r3
462 sync
463 addi r3, r3, 0x1000
464 cmp 0, 0, r3, r5
465 blt tlblp
466
467 blr
468
469 .globl enable_addr_trans
470enable_addr_trans:
471 /* enable address translation */
472 mfmsr r5
473 ori r5, r5, (MSR_IR | MSR_DR)
474 mtmsr r5
475 isync
476 blr
477
478 .globl disable_addr_trans
479disable_addr_trans:
480 /* disable address translation */
481 mflr r4
482 mfmsr r3
483 andi. r0, r3, (MSR_IR | MSR_DR)
484 beqlr
485 andc r3, r3, r0
486 mtspr SRR0, r4
487 mtspr SRR1, r3
488 rfi
489
490/*
491 * This code finishes saving the registers to the exception frame
492 * and jumps to the appropriate handler for the exception.
493 * Register r21 is pointer into trap frame, r1 has new stack pointer.
494 */
495 .globl transfer_to_handler
496transfer_to_handler:
497 stw r22,_NIP(r21)
498 lis r22,MSR_POW@h
499 andc r23,r23,r22
500 stw r23,_MSR(r21)
501 SAVE_GPR(7, r21)
502 SAVE_4GPRS(8, r21)
503 SAVE_8GPRS(12, r21)
504 SAVE_8GPRS(24, r21)
505 mflr r23
506 andi. r24,r23,0x3f00 /* get vector offset */
507 stw r24,TRAP(r21)
508 li r22,0
509 stw r22,RESULT(r21)
510 mtspr SPRG2,r22 /* r1 is now kernel sp */
511 lwz r24,0(r23) /* virtual address of handler */
512 lwz r23,4(r23) /* where to go when done */
513 mtspr SRR0,r24
514 mtspr SRR1,r20
515 mtlr r23
516 SYNC
517 rfi /* jump to handler, enable MMU */
518
519int_return:
520 mfmsr r28 /* Disable interrupts */
521 li r4,0
522 ori r4,r4,MSR_EE
523 andc r28,r28,r4
524 SYNC /* Some chip revs need this... */
525 mtmsr r28
526 SYNC
527 lwz r2,_CTR(r1)
528 lwz r0,_LINK(r1)
529 mtctr r2
530 mtlr r0
531 lwz r2,_XER(r1)
532 lwz r0,_CCR(r1)
533 mtspr XER,r2
534 mtcrf 0xFF,r0
535 REST_10GPRS(3, r1)
536 REST_10GPRS(13, r1)
537 REST_8GPRS(23, r1)
538 REST_GPR(31, r1)
539 lwz r2,_NIP(r1) /* Restore environment */
540 lwz r0,_MSR(r1)
541 mtspr SRR0,r2
542 mtspr SRR1,r0
543 lwz r0,GPR0(r1)
544 lwz r2,GPR2(r1)
545 lwz r1,GPR1(r1)
546 SYNC
547 rfi
548
549 .globl dc_read
550dc_read:
551 blr
552
553 .globl get_pvr
554get_pvr:
555 mfspr r3, PVR
556 blr
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 lis r5, CFG_MONITOR_LEN@h /* Length in Bytes */
580 ori r5, r5, CFG_MONITOR_LEN@l
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#ifdef CONFIG_ECC
601 bl board_relocate_rom
602 sync
603 mr r3, r10 /* Destination Address */
604 lis r4, CFG_MONITOR_BASE@h /* Source Address */
605 ori r4, r4, CFG_MONITOR_BASE@l
606 lis r5, CFG_MONITOR_LEN@h /* Length in Bytes */
607 ori r5, r5, CFG_MONITOR_LEN@l
608 li r6, CFG_CACHELINE_SIZE /* Cache Line Size */
609#else
610 cmplw cr1,r3,r4
611 addi r0,r5,3
612 srwi. r0,r0,2
613 beq cr1,4f /* In place copy is not necessary */
614 beq 7f /* Protect against 0 count */
615 mtctr r0
616 bge cr1,2f
617
618 la r8,-4(r4)
619 la r7,-4(r3)
6201: lwzu r0,4(r8)
621 stwu r0,4(r7)
622 bdnz 1b
623 b 4f
624
6252: slwi r0,r0,2
626 add r8,r4,r0
627 add r7,r3,r0
6283: lwzu r0,-4(r8)
629 stwu r0,-4(r7)
630 bdnz 3b
631#endif
632/*
633 * Now flush the cache: note that we must start from a cache aligned
634 * address. Otherwise we might miss one cache line.
635 */
6364: cmpwi r6,0
637 add r5,r3,r5
638 beq 7f /* Always flush prefetch queue in any case */
639 subi r0,r6,1
640 andc r3,r3,r0
641 mr r4,r3
6425: dcbst 0,r4
643 add r4,r4,r6
644 cmplw r4,r5
645 blt 5b
646 sync /* Wait for all dcbst to complete on bus */
647 mr r4,r3
6486: icbi 0,r4
649 add r4,r4,r6
650 cmplw r4,r5
651 blt 6b
6527: sync /* Wait for all icbi to complete on bus */
653 isync
654
655/*
656 * We are done. Do not return, instead branch to second part of board
657 * initialization, now running from RAM.
658 */
659 addi r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
660 mtlr r0
661 blr
662
663in_ram:
664#ifdef CONFIG_ECC
665 bl board_init_ecc
666#endif
667 /*
668 * Relocation Function, r14 point to got2+0x8000
669 *
670 * Adjust got2 pointers, no need to check for 0, this code
671 * already puts a few entries in the table.
672 */
673 li r0,__got2_entries@sectoff@l
674 la r3,GOT(_GOT2_TABLE_)
675 lwz r11,GOT(_GOT2_TABLE_)
676 mtctr r0
677 sub r11,r3,r11
678 addi r3,r3,-4
6791: lwzu r0,4(r3)
680 add r0,r0,r11
681 stw r0,0(r3)
682 bdnz 1b
683
684 /*
685 * Now adjust the fixups and the pointers to the fixups
686 * in case we need to move ourselves again.
687 */
6882: li r0,__fixup_entries@sectoff@l
689 lwz r3,GOT(_FIXUP_TABLE_)
690 cmpwi r0,0
691 mtctr r0
692 addi r3,r3,-4
693 beq 4f
6943: lwzu r4,4(r3)
695 lwzux r0,r4,r11
696 add r0,r0,r11
697 stw r10,0(r3)
698 stw r0,0(r4)
699 bdnz 3b
7004:
701/* clear_bss: */
702 /*
703 * Now clear BSS segment
704 */
705 lwz r3,GOT(.bss)
706 lwz r4,GOT(_end)
707
708 cmplw 0, r3, r4
709 beq 6f
710
711 li r0, 0
7125:
713 stw r0, 0(r3)
714 addi r3, r3, 4
715 cmplw 0, r3, r4
716 bne 5b
7176:
718 mr r3, r10 /* Destination Address */
719 bl after_reloc
720
721 /* not reached - end relocate_code */
722/*-----------------------------------------------------------------------*/
723
724 /* Problems accessing "end" in C, so do it here */
725 .globl get_endaddr
726get_endaddr:
727 lwz r3,GOT(_end)
728 blr
729
730 /*
731 * Copy exception vector code to low memory
732 *
733 * r3: dest_addr
734 * r7: source address, r8: end address, r9: target address
735 */
736 .globl trap_init
737trap_init:
738 lwz r7, GOT(_start)
739 lwz r8, GOT(_end_of_vectors)
740
741 rlwinm r9, r7, 0, 18, 31 /* _start & 0x3FFF */
742
743 cmplw 0, r7, r8
744 bgelr /* return if r7>=r8 - just in case */
745
746 mflr r4 /* save link register */
7471:
748 lwz r0, 0(r7)
749 stw r0, 0(r9)
750 addi r7, r7, 4
751 addi r9, r9, 4
752 cmplw 0, r7, r8
753 bne 1b
754
755 /*
756 * relocate `hdlr' and `int_return' entries
757 */
758 li r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
759 li r8, Alignment - _start + EXC_OFF_SYS_RESET
7602:
761 bl trap_reloc
762 addi r7, r7, 0x100 /* next exception vector */
763 cmplw 0, r7, r8
764 blt 2b
765
766 li r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
767 bl trap_reloc
768
769 li r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
770 bl trap_reloc
771
772 li r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
773 li r8, SystemCall - _start + EXC_OFF_SYS_RESET
7743:
775 bl trap_reloc
776 addi r7, r7, 0x100 /* next exception vector */
777 cmplw 0, r7, r8
778 blt 3b
779
780 li r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
781 li r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
7824:
783 bl trap_reloc
784 addi r7, r7, 0x100 /* next exception vector */
785 cmplw 0, r7, r8
786 blt 4b
787
788 /* enable execptions from RAM vectors */
789 mfmsr r7
790 li r8,MSR_IP
791 andc r7,r7,r8
792 mtmsr r7
793
794 mtlr r4 /* restore link register */
795 blr
796
797 /*
798 * Function: relocate entries for one exception vector
799 */
800trap_reloc:
801 lwz r0, 0(r7) /* hdlr ... */
802 add r0, r0, r3 /* ... += dest_addr */
803 stw r0, 0(r7)
804
805 lwz r0, 4(r7) /* int_return ... */
806 add r0, r0, r3 /* ... += dest_addr */
807 stw r0, 4(r7)
808
809 sync
810 isync
811
812 blr
813
814#ifdef CFG_INIT_RAM_LOCK
815lock_ram_in_cache:
816 /* Allocate Initial RAM in data cache.
817 */
818 lis r3, (CFG_INIT_RAM_ADDR & ~31)@h
819 ori r3, r3, (CFG_INIT_RAM_ADDR & ~31)@l
820 li r2, ((CFG_INIT_RAM_END & ~31) + \
821 (CFG_INIT_RAM_ADDR & 31) + 31) / 32
822 mtctr r2
8231:
824 dcbz r0, r3
825 addi r3, r3, 32
826 bdnz 1b
827
828 /* Lock the data cache */
829 mfspr r0, HID0
830 ori r0, r0, 0x1000
831 sync
832 mtspr HID0, r0
833 sync
834 blr
835
836.globl unlock_ram_in_cache
837unlock_ram_in_cache:
838 /* invalidate the INIT_RAM section */
839 lis r3, (CFG_INIT_RAM_ADDR & ~31)@h
840 ori r3, r3, (CFG_INIT_RAM_ADDR & ~31)@l
841 li r2, ((CFG_INIT_RAM_END & ~31) + \
842 (CFG_INIT_RAM_ADDR & 31) + 31) / 32
843 mtctr r2
8441: icbi r0, r3
845 addi r3, r3, 32
846 bdnz 1b
847 sync /* Wait for all icbi to complete on bus */
848 isync
849
850 /* Unlock the data cache and invalidate it */
851 mfspr r0, HID0
852 li r3,0x1000
853 andc r0,r0,r3
854 li r3,0x0400
855 or r0,r0,r3
856 sync
857 mtspr HID0, r0
858 sync
859 blr
860#endif