]> git.ipfire.org Git - people/ms/u-boot.git/blob - cpu/mpc83xx/start.S
* Patch by Eran Liberty
[people/ms/u-boot.git] / cpu / mpc83xx / start.S
1 /*
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 2004 Freescale Semiconductor, Inc.
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 /*
27 * U-Boot - Startup Code for MPC83xx PowerPC based Embedded Boards
28 */
29
30 #include <config.h>
31 #include <mpc83xx.h>
32 #include <version.h>
33
34 #define CONFIG_83XX 1 /* needed for Linux kernel header files*/
35 #define _LINUX_CONFIG_H 1 /* avoid reading Linux autoconf.h file */
36
37 #include <ppc_asm.tmpl>
38 #include <ppc_defs.h>
39
40 #include <asm/cache.h>
41 #include <asm/mmu.h>
42
43 #ifndef CONFIG_IDENT_STRING
44 #define CONFIG_IDENT_STRING "MPC83XX"
45 #endif
46
47 /* We don't want the MMU yet.
48 */
49 #undef MSR_KERNEL
50
51 /*
52 * Floating Point enable, Machine Check and Recoverable Interr.
53 */
54 #ifdef DEBUG
55 #define MSR_KERNEL (MSR_FP|MSR_RI)
56 #else
57 #define MSR_KERNEL (MSR_FP|MSR_ME|MSR_RI)
58 #endif
59
60 /*
61 * Set up GOT: Global Offset Table
62 *
63 * Use r14 to access the GOT
64 */
65 START_GOT
66 GOT_ENTRY(_GOT2_TABLE_)
67 GOT_ENTRY(_FIXUP_TABLE_)
68
69 GOT_ENTRY(_start)
70 GOT_ENTRY(_start_of_vectors)
71 GOT_ENTRY(_end_of_vectors)
72 GOT_ENTRY(transfer_to_handler)
73
74 GOT_ENTRY(__init_end)
75 GOT_ENTRY(_end)
76 GOT_ENTRY(__bss_start)
77 END_GOT
78
79 /*
80 * Version string - must be in data segment because MPC83xx uses the
81 * first 256 bytes for the Hard Reset Configuration Word table (see
82 * below). Similarly, can't have the U-Boot Magic Number as the first
83 * thing in the image - don't know how this will affect the image tools,
84 * but I guess I'll find out soon.
85 */
86 .data
87 .globl version_string
88 version_string:
89 .ascii U_BOOT_VERSION
90 .ascii " (", __DATE__, " - ", __TIME__, ")"
91 .ascii " ", CONFIG_IDENT_STRING, "\0"
92
93 .text
94 #define _HRCW_TABLE_ENTRY(w) \
95 .fill 8,1,(((w)>>24)&0xff); \
96 .fill 8,1,(((w)>>16)&0xff); \
97 .fill 8,1,(((w)>> 8)&0xff); \
98 .fill 8,1,(((w) )&0xff)
99
100 _HRCW_TABLE_ENTRY(CFG_HRCW_LOW)
101 _HRCW_TABLE_ENTRY(CFG_HRCW_HIGH)
102
103
104
105 #ifndef CONFIG_DEFAULT_IMMR
106 #error CONFIG_DEFAULT_IMMR must be defined
107 #endif /* CFG_DEFAULT_IMMR */
108 #ifndef CFG_IMMRBAR
109 #define CFG_IMMRBAR CONFIG_DEFAULT_IMMR
110 #endif /* CFG_IMMRBAR */
111
112 /*
113 * After configuration, a system reset exception is executed using the
114 * vector at offset 0x100 relative to the base set by MSR[IP]. If
115 * MSR[IP] is 0, the base address is 0x00000000. If MSR[IP] is 1, the
116 * base address is 0xfff00000. In the case of a Power On Reset or Hard
117 * Reset, the value of MSR[IP] is determined by the CIP field in the
118 * HRCW.
119 *
120 * Other bits in the HRCW set up the Base Address and Port Size in BR0.
121 * This determines the location of the boot ROM (flash or EPROM) in the
122 * processor's address space at boot time. As long as the HRCW is set up
123 * so that we eventually end up executing the code below when the
124 * processor executes the reset exception, the actual values used should
125 * not matter.
126 *
127 * Once we have got here, the address mask in OR0 is cleared so that the
128 * bottom 32K of the boot ROM is effectively repeated all throughout the
129 * processor's address space, after which we can jump to the absolute
130 * address at which the boot ROM was linked at compile time, and proceed
131 * to initialise the memory controller without worrying if the rug will
132 * be pulled out from under us, so to speak (it will be fine as long as
133 * we configure BR0 with the same boot ROM link address).
134 */
135 . = EXC_OFF_SYS_RESET
136
137 .globl _start
138 _start: /* time t 0 */
139 li r21, BOOTFLAG_COLD /* Normal Power-On: Boot from FLASH*/
140 nop
141 b boot_cold
142
143 . = EXC_OFF_SYS_RESET + 0x10
144
145 .globl _start_warm
146 _start_warm:
147 li r21, BOOTFLAG_WARM /* Software reboot */
148 b boot_warm
149
150
151 boot_cold: /* time t 3 */
152 lis r4, CONFIG_DEFAULT_IMMR@h
153 nop
154 boot_warm: /* time t 5 */
155 mfmsr r5 /* save msr contents */
156 lis r3, CFG_IMMRBAR@h
157 ori r3, r3, CFG_IMMRBAR@l
158 stw r3, IMMRBAR(r4)
159
160 /* Initialise the E300 processor core */
161 /*------------------------------------------*/
162
163 bl init_e300_core
164
165 #ifndef CFG_RAMBOOT
166
167 /* Inflate flash location so it appears everywhere, calculate */
168 /* the absolute address in final location of the FLASH, jump */
169 /* there and deflate the flash size back to minimal size */
170 /*------------------------------------------------------------*/
171 bl map_flash_by_law1
172 lis r4, (CFG_MONITOR_BASE)@h
173 ori r4, r4, (CFG_MONITOR_BASE)@l
174 addi r5, r4, in_flash - _start + EXC_OFF_SYS_RESET
175 mtlr r5
176 blr
177 in_flash:
178 #if 1 /* Remapping flash with LAW0. */
179 bl remap_flash_by_law0
180 #endif
181 #endif /* CFG_RAMBOOT */
182
183 bl setup_stack_in_data_cache_on_r1
184
185 /* let the C-code set up the rest */
186 /* */
187 /* Be careful to keep code relocatable & stack humble */
188 /*------------------------------------------------------*/
189
190 GET_GOT /* initialize GOT access */
191
192 /* r3: IMMR */
193 lis r3, CFG_IMMRBAR@h
194 /* run low-level CPU init code (in Flash)*/
195 bl cpu_init_f
196
197 /* r3: BOOTFLAG */
198 mr r3, r21
199 /* run 1st part of board init code (in Flash)*/
200 bl board_init_f
201
202 /*
203 * Vector Table
204 */
205
206 .globl _start_of_vectors
207 _start_of_vectors:
208
209 /* Machine check */
210 STD_EXCEPTION(0x200, MachineCheck, MachineCheckException)
211
212 /* Data Storage exception. */
213 STD_EXCEPTION(0x300, DataStorage, UnknownException)
214
215 /* Instruction Storage exception. */
216 STD_EXCEPTION(0x400, InstStorage, UnknownException)
217
218 /* External Interrupt exception. */
219 #ifndef FIXME
220 STD_EXCEPTION(0x500, ExtInterrupt, external_interrupt)
221 #endif
222
223 /* Alignment exception. */
224 . = 0x600
225 Alignment:
226 EXCEPTION_PROLOG
227 mfspr r4,DAR
228 stw r4,_DAR(r21)
229 mfspr r5,DSISR
230 stw r5,_DSISR(r21)
231 addi r3,r1,STACK_FRAME_OVERHEAD
232 li r20,MSR_KERNEL
233 rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */
234 rlwimi r20,r23,0,25,25 /* copy IP bit from saved MSR */
235 lwz r6,GOT(transfer_to_handler)
236 mtlr r6
237 blrl
238 .L_Alignment:
239 .long AlignmentException - _start + EXC_OFF_SYS_RESET
240 .long int_return - _start + EXC_OFF_SYS_RESET
241
242 /* Program check exception */
243 . = 0x700
244 ProgramCheck:
245 EXCEPTION_PROLOG
246 addi r3,r1,STACK_FRAME_OVERHEAD
247 li r20,MSR_KERNEL
248 rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */
249 rlwimi r20,r23,0,25,25 /* copy IP bit from saved MSR */
250 lwz r6,GOT(transfer_to_handler)
251 mtlr r6
252 blrl
253 .L_ProgramCheck:
254 .long ProgramCheckException - _start + EXC_OFF_SYS_RESET
255 .long int_return - _start + EXC_OFF_SYS_RESET
256
257 STD_EXCEPTION(0x800, FPUnavailable, UnknownException)
258
259 /* I guess we could implement decrementer, and may have
260 * to someday for timekeeping.
261 */
262 STD_EXCEPTION(0x900, Decrementer, timer_interrupt)
263
264 STD_EXCEPTION(0xa00, Trap_0a, UnknownException)
265 STD_EXCEPTION(0xb00, Trap_0b, UnknownException)
266 STD_EXCEPTION(0xc00, SystemCall, UnknownException)
267 STD_EXCEPTION(0xd00, SingleStep, UnknownException)
268
269 STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
270 STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
271
272 STD_EXCEPTION(0x1000, InstructionTLBMiss, UnknownException)
273 STD_EXCEPTION(0x1100, DataLoadTLBMiss, UnknownException)
274 STD_EXCEPTION(0x1200, DataStoreTLBMiss, UnknownException)
275 #ifdef DEBUG
276 . = 0x1300
277 /*
278 * This exception occurs when the program counter matches the
279 * Instruction Address Breakpoint Register (IABR).
280 *
281 * I want the cpu to halt if this occurs so I can hunt around
282 * with the debugger and look at things.
283 *
284 * When DEBUG is defined, both machine check enable (in the MSR)
285 * and checkstop reset enable (in the reset mode register) are
286 * turned off and so a checkstop condition will result in the cpu
287 * halting.
288 *
289 * I force the cpu into a checkstop condition by putting an illegal
290 * instruction here (at least this is the theory).
291 *
292 * well - that didnt work, so just do an infinite loop!
293 */
294 1: b 1b
295 #else
296 STD_EXCEPTION(0x1300, InstructionBreakpoint, DebugException)
297 #endif
298 STD_EXCEPTION(0x1400, SMI, UnknownException)
299
300 STD_EXCEPTION(0x1500, Trap_15, UnknownException)
301 STD_EXCEPTION(0x1600, Trap_16, UnknownException)
302 STD_EXCEPTION(0x1700, Trap_17, UnknownException)
303 STD_EXCEPTION(0x1800, Trap_18, UnknownException)
304 STD_EXCEPTION(0x1900, Trap_19, UnknownException)
305 STD_EXCEPTION(0x1a00, Trap_1a, UnknownException)
306 STD_EXCEPTION(0x1b00, Trap_1b, UnknownException)
307 STD_EXCEPTION(0x1c00, Trap_1c, UnknownException)
308 STD_EXCEPTION(0x1d00, Trap_1d, UnknownException)
309 STD_EXCEPTION(0x1e00, Trap_1e, UnknownException)
310 STD_EXCEPTION(0x1f00, Trap_1f, UnknownException)
311 STD_EXCEPTION(0x2000, Trap_20, UnknownException)
312 STD_EXCEPTION(0x2100, Trap_21, UnknownException)
313 STD_EXCEPTION(0x2200, Trap_22, UnknownException)
314 STD_EXCEPTION(0x2300, Trap_23, UnknownException)
315 STD_EXCEPTION(0x2400, Trap_24, UnknownException)
316 STD_EXCEPTION(0x2500, Trap_25, UnknownException)
317 STD_EXCEPTION(0x2600, Trap_26, UnknownException)
318 STD_EXCEPTION(0x2700, Trap_27, UnknownException)
319 STD_EXCEPTION(0x2800, Trap_28, UnknownException)
320 STD_EXCEPTION(0x2900, Trap_29, UnknownException)
321 STD_EXCEPTION(0x2a00, Trap_2a, UnknownException)
322 STD_EXCEPTION(0x2b00, Trap_2b, UnknownException)
323 STD_EXCEPTION(0x2c00, Trap_2c, UnknownException)
324 STD_EXCEPTION(0x2d00, Trap_2d, UnknownException)
325 STD_EXCEPTION(0x2e00, Trap_2e, UnknownException)
326 STD_EXCEPTION(0x2f00, Trap_2f, UnknownException)
327
328
329 .globl _end_of_vectors
330 _end_of_vectors:
331
332 . = 0x3000
333
334 /*
335 * This code finishes saving the registers to the exception frame
336 * and jumps to the appropriate handler for the exception.
337 * Register r21 is pointer into trap frame, r1 has new stack pointer.
338 */
339 .globl transfer_to_handler
340 transfer_to_handler:
341 stw r22,_NIP(r21)
342 lis r22,MSR_POW@h
343 andc r23,r23,r22
344 stw r23,_MSR(r21)
345 SAVE_GPR(7, r21)
346 SAVE_4GPRS(8, r21)
347 SAVE_8GPRS(12, r21)
348 SAVE_8GPRS(24, r21)
349 mflr r23
350 andi. r24,r23,0x3f00 /* get vector offset */
351 stw r24,TRAP(r21)
352 li r22,0
353 stw r22,RESULT(r21)
354 lwz r24,0(r23) /* virtual address of handler */
355 lwz r23,4(r23) /* where to go when done */
356 mtspr SRR0,r24
357 mtspr SRR1,r20
358 mtlr r23
359 SYNC
360 rfi /* jump to handler, enable MMU */
361
362 int_return:
363 mfmsr r28 /* Disable interrupts */
364 li r4,0
365 ori r4,r4,MSR_EE
366 andc r28,r28,r4
367 SYNC /* Some chip revs need this... */
368 mtmsr r28
369 SYNC
370 lwz r2,_CTR(r1)
371 lwz r0,_LINK(r1)
372 mtctr r2
373 mtlr r0
374 lwz r2,_XER(r1)
375 lwz r0,_CCR(r1)
376 mtspr XER,r2
377 mtcrf 0xFF,r0
378 REST_10GPRS(3, r1)
379 REST_10GPRS(13, r1)
380 REST_8GPRS(23, r1)
381 REST_GPR(31, r1)
382 lwz r2,_NIP(r1) /* Restore environment */
383 lwz r0,_MSR(r1)
384 mtspr SRR0,r2
385 mtspr SRR1,r0
386 lwz r0,GPR0(r1)
387 lwz r2,GPR2(r1)
388 lwz r1,GPR1(r1)
389 SYNC
390 rfi
391
392 /*
393 * This code initialises the E300 processor core
394 * (conforms to PowerPC 603e spec)
395 * Note: expects original MSR contents to be in r5.
396 */
397 .globl init_e300_core
398 init_e300_core: /* time t 10 */
399 /* Initialize machine status; enable machine check interrupt */
400 /*-----------------------------------------------------------*/
401
402 li r3, MSR_KERNEL /* Set ME and RI flags */
403 rlwimi r3, r5, 0, 25, 25 /* preserve IP bit set by HRCW */
404 #ifdef DEBUG
405 rlwimi r3, r5, 0, 21, 22 /* debugger might set SE & BE bits */
406 #endif
407 SYNC /* Some chip revs need this... */
408 mtmsr r3
409 SYNC
410 mtspr SRR1, r3 /* Make SRR1 match MSR */
411
412
413 lis r3, CFG_IMMRBAR@h
414 #if defined(CONFIG_WATCHDOG)
415 /* Initialise the Wathcdog values and reset it (if req) */
416 /*------------------------------------------------------*/
417 lis r4, CFG_WATCHDOG_VALUE
418 ori r4, r4, (SWCRR_SWEN | SWCRR_SWRI | SWCRR_SWPR)
419 stw r4, SWCRR(r3)
420
421 /* and reset it */
422
423 li r4, 0x556C
424 sth r4, SWSRR@l(r3)
425 li r4, 0xAA39
426 sth r4, SWSRR@l(r3)
427 #else
428 /* Disable Wathcdog */
429 /*-------------------*/
430 xor r4, r4, r4
431 stw r4, SWCRR(r3)
432 #endif /* CONFIG_WATCHDOG */
433
434 /* Initialize the Hardware Implementation-dependent Registers */
435 /* HID0 also contains cache control */
436 /*------------------------------------------------------*/
437
438 lis r3, CFG_HID0_INIT@h
439 ori r3, r3, CFG_HID0_INIT@l
440 SYNC
441 mtspr HID0, r3
442
443 lis r3, CFG_HID0_FINAL@h
444 ori r3, r3, CFG_HID0_FINAL@l
445 SYNC
446 mtspr HID0, r3
447
448 lis r3, CFG_HID2@h
449 ori r3, r3, CFG_HID2@l
450 SYNC
451 mtspr HID2, r3
452
453 /* clear all BAT's */
454 /*----------------------------------*/
455
456 xor r0, r0, r0
457 mtspr DBAT0U, r0
458 mtspr DBAT0L, r0
459 mtspr DBAT1U, r0
460 mtspr DBAT1L, r0
461 mtspr DBAT2U, r0
462 mtspr DBAT2L, r0
463 mtspr DBAT3U, r0
464 mtspr DBAT3L, r0
465 mtspr IBAT0U, r0
466 mtspr IBAT0L, r0
467 mtspr IBAT1U, r0
468 mtspr IBAT1L, r0
469 mtspr IBAT2U, r0
470 mtspr IBAT2L, r0
471 mtspr IBAT3U, r0
472 mtspr IBAT3L, r0
473 SYNC
474
475 /* invalidate all tlb's
476 *
477 * From the 603e User Manual: "The 603e provides the ability to
478 * invalidate a TLB entry. The TLB Invalidate Entry (tlbie)
479 * instruction invalidates the TLB entry indexed by the EA, and
480 * operates on both the instruction and data TLBs simultaneously
481 * invalidating four TLB entries (both sets in each TLB). The
482 * index corresponds to bits 15-19 of the EA. To invalidate all
483 * entries within both TLBs, 32 tlbie instructions should be
484 * issued, incrementing this field by one each time."
485 *
486 * "Note that the tlbia instruction is not implemented on the
487 * 603e."
488 *
489 * bits 15-19 correspond to addresses 0x00000000 to 0x0001F000
490 * incrementing by 0x1000 each time. The code below is sort of
491 * based on code in "flush_tlbs" from arch/ppc/kernel/head.S
492 *
493 */
494
495 li r3, 32
496 mtctr r3
497 li r3, 0
498 1: tlbie r3
499 addi r3, r3, 0x1000
500 bdnz 1b
501 SYNC
502
503 /* Done! */
504 /*------------------------------*/
505 blr
506
507 /* Cache functions.
508 *
509 * Note: requires that all cache bits in
510 * HID0 are in the low half word.
511 */
512 .globl icache_enable
513 icache_enable:
514 mfspr r3, HID0
515 ori r3, r3, HID0_ICE
516 lis r4, 0
517 ori r4, r4, HID0_ILOCK
518 andc r3, r3, r4
519 ori r4, r3, HID0_ICFI
520 isync
521 mtspr HID0, r4 /* sets enable and invalidate, clears lock */
522 isync
523 mtspr HID0, r3 /* clears invalidate */
524 blr
525
526 .globl icache_disable
527 icache_disable:
528 mfspr r3, HID0
529 lis r4, 0
530 ori r4, r4, HID0_ICE|HID0_ILOCK
531 andc r3, r3, r4
532 ori r4, r3, HID0_ICFI
533 isync
534 mtspr HID0, r4 /* sets invalidate, clears enable and lock*/
535 isync
536 mtspr HID0, r3 /* clears invalidate */
537 blr
538
539 .globl icache_status
540 icache_status:
541 mfspr r3, HID0
542 rlwinm r3, r3, HID0_ICE_SHIFT, 31, 31
543 blr
544
545 .globl dcache_enable
546 dcache_enable:
547 mfspr r3, HID0
548 ori r3, r3, HID0_ENABLE_DATA_CACHE
549 lis r4, 0
550 ori r4, r4, HID0_LOCK_DATA_CACHE
551 andc r3, r3, r4
552 ori r4, r3, HID0_LOCK_INSTRUCTION_CACHE
553 sync
554 mtspr HID0, r4 /* sets enable and invalidate, clears lock */
555 sync
556 mtspr HID0, r3 /* clears invalidate */
557 blr
558
559 .globl dcache_disable
560 dcache_disable:
561 mfspr r3, HID0
562 lis r4, 0
563 ori r4, r4, HID0_ENABLE_DATA_CACHE|HID0_LOCK_DATA_CACHE
564 andc r3, r3, r4
565 ori r4, r3, HID0_INVALIDATE_DATA_CACHE
566 sync
567 mtspr HID0, r4 /* sets invalidate, clears enable and lock */
568 sync
569 mtspr HID0, r3 /* clears invalidate */
570 blr
571
572 .globl dcache_status
573 dcache_status:
574 mfspr r3, HID0
575 rlwinm r3, r3, HID0_DCE_SHIFT, 31, 31
576 blr
577
578 .globl get_pvr
579 get_pvr:
580 mfspr r3, PVR
581 blr
582
583 /*-------------------------------------------------------------------*/
584
585 /*
586 * void relocate_code (addr_sp, gd, addr_moni)
587 *
588 * This "function" does not return, instead it continues in RAM
589 * after relocating the monitor code.
590 *
591 * r3 = dest
592 * r4 = src
593 * r5 = length in bytes
594 * r6 = cachelinesize
595 */
596 .globl relocate_code
597 relocate_code:
598 mr r1, r3 /* Set new stack pointer */
599 mr r9, r4 /* Save copy of Global Data pointer */
600 mr r10, r5 /* Save copy of Destination Address */
601
602 mr r3, r5 /* Destination Address */
603 lis r4, CFG_MONITOR_BASE@h /* Source Address */
604 ori r4, r4, CFG_MONITOR_BASE@l
605 lwz r5, GOT(__init_end)
606 sub r5, r5, r4
607 li r6, CFG_CACHELINE_SIZE /* Cache Line Size */
608
609 /*
610 * Fix GOT pointer:
611 *
612 * New GOT-PTR = (old GOT-PTR - CFG_MONITOR_BASE)
613 * + Destination Address
614 *
615 * Offset:
616 */
617 sub r15, r10, r4
618
619 /* First our own GOT */
620 add r14, r14, r15
621 /* then the one used by the C code */
622 add r30, r30, r15
623
624 /*
625 * Now relocate code
626 */
627
628 cmplw cr1,r3,r4
629 addi r0,r5,3
630 srwi. r0,r0,2
631 beq cr1,4f /* In place copy is not necessary */
632 beq 7f /* Protect against 0 count */
633 mtctr r0
634 bge cr1,2f
635 la r8,-4(r4)
636 la r7,-4(r3)
637
638 /* copy */
639 1: lwzu r0,4(r8)
640 stwu r0,4(r7)
641 bdnz 1b
642
643 addi r0,r5,3
644 srwi. r0,r0,2
645 mtctr r0
646 la r8,-4(r4)
647 la r7,-4(r3)
648
649 /* and compare */
650 20: lwzu r20,4(r8)
651 lwzu r21,4(r7)
652 xor. r22, r20, r21
653 bne 30f
654 bdnz 20b
655 b 4f
656
657 /* compare failed */
658 30: li r3, 0
659 blr
660
661 2: slwi r0,r0,2 /* re copy in reverse order ... y do we needed it? */
662 add r8,r4,r0
663 add r7,r3,r0
664 3: lwzu r0,-4(r8)
665 stwu r0,-4(r7)
666 bdnz 3b
667
668
669
670 /*
671 * Now flush the cache: note that we must start from a cache aligned
672 * address. Otherwise we might miss one cache line.
673 */
674 4:
675 bl un_setup_stack_in_data_cache
676 mr r7, r3
677 mr r8, r4
678 bl dcache_disable
679 mr r3, r7
680 mr r4, r8
681
682 cmpwi r6,0
683 add r5,r3,r5
684 beq 7f /* Always flush prefetch queue in any case */
685 subi r0,r6,1
686 andc r3,r3,r0
687 mfspr r7,HID0 /* don't do dcbst if dcache is disabled*/
688 rlwinm r7,r7,HID0_DCE_SHIFT,31,31
689 cmpwi r7,0
690 beq 9f
691 mr r4,r3
692 5: dcbst 0,r4
693 add r4,r4,r6
694 cmplw r4,r5
695 blt 5b
696 sync /* Wait for all dcbst to complete on bus */
697 9: mfspr r7,HID0 /* don't do icbi if icache is disabled */
698 rlwinm r7,r7,HID0_DCE_SHIFT,31,31
699 cmpwi r7,0
700 beq 7f
701 mr r4,r3
702 6: icbi 0,r4
703 add r4,r4,r6
704 cmplw r4,r5
705 blt 6b
706 7: sync /* Wait for all icbi to complete on bus */
707 isync
708
709 /*
710 * We are done. Do not return, instead branch to second part of board
711 * initialization, now running from RAM.
712 */
713
714 addi r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
715 mtlr r0
716 blr
717
718 in_ram:
719
720 /*
721 * Relocation Function, r14 point to got2+0x8000
722 *
723 * Adjust got2 pointers, no need to check for 0, this code
724 * already puts a few entries in the table.
725 */
726 li r0,__got2_entries@sectoff@l
727 la r3,GOT(_GOT2_TABLE_)
728 lwz r11,GOT(_GOT2_TABLE_)
729 mtctr r0
730 sub r11,r3,r11
731 addi r3,r3,-4
732 1: lwzu r0,4(r3)
733 add r0,r0,r11
734 stw r0,0(r3)
735 bdnz 1b
736
737 /*
738 * Now adjust the fixups and the pointers to the fixups
739 * in case we need to move ourselves again.
740 */
741 2: li r0,__fixup_entries@sectoff@l
742 lwz r3,GOT(_FIXUP_TABLE_)
743 cmpwi r0,0
744 mtctr r0
745 addi r3,r3,-4
746 beq 4f
747 3: lwzu r4,4(r3)
748 lwzux r0,r4,r11
749 add r0,r0,r11
750 stw r10,0(r3)
751 stw r0,0(r4)
752 bdnz 3b
753 4:
754 clear_bss:
755 /*
756 * Now clear BSS segment
757 */
758 lwz r3,GOT(__bss_start)
759 #if defined(CONFIG_HYMOD)
760 /*
761 * For HYMOD - the environment is the very last item in flash.
762 * The real .bss stops just before environment starts, so only
763 * clear up to that point.
764 *
765 * taken from mods for FADS board
766 */
767 lwz r4,GOT(environment)
768 #else
769 lwz r4,GOT(_end)
770 #endif
771
772 cmplw 0, r3, r4
773 beq 6f
774
775 li r0, 0
776 5:
777 stw r0, 0(r3)
778 addi r3, r3, 4
779 cmplw 0, r3, r4
780 bne 5b
781 6:
782
783 mr r3, r9 /* Global Data pointer */
784 mr r4, r10 /* Destination Address */
785 bl board_init_r
786
787 /*
788 * Copy exception vector code to low memory
789 *
790 * r3: dest_addr
791 * r7: source address, r8: end address, r9: target address
792 */
793 .globl trap_init
794 trap_init:
795 lwz r7, GOT(_start)
796 lwz r8, GOT(_end_of_vectors)
797
798 li r9, 0x100 /* reset vector always at 0x100 */
799
800 cmplw 0, r7, r8
801 bgelr /* return if r7>=r8 - just in case */
802
803 mflr r4 /* save link register */
804 1:
805 lwz r0, 0(r7)
806 stw r0, 0(r9)
807 addi r7, r7, 4
808 addi r9, r9, 4
809 cmplw 0, r7, r8
810 bne 1b
811
812 /*
813 * relocate `hdlr' and `int_return' entries
814 */
815 li r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
816 li r8, Alignment - _start + EXC_OFF_SYS_RESET
817 2:
818 bl trap_reloc
819 addi r7, r7, 0x100 /* next exception vector */
820 cmplw 0, r7, r8
821 blt 2b
822
823 li r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
824 bl trap_reloc
825
826 li r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
827 bl trap_reloc
828
829 li r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
830 li r8, SystemCall - _start + EXC_OFF_SYS_RESET
831 3:
832 bl trap_reloc
833 addi r7, r7, 0x100 /* next exception vector */
834 cmplw 0, r7, r8
835 blt 3b
836
837 li r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
838 li r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
839 4:
840 bl trap_reloc
841 addi r7, r7, 0x100 /* next exception vector */
842 cmplw 0, r7, r8
843 blt 4b
844
845 mfmsr r3 /* now that the vectors have */
846 lis r7, MSR_IP@h /* relocated into low memory */
847 ori r7, r7, MSR_IP@l /* MSR[IP] can be turned off */
848 andc r3, r3, r7 /* (if it was on) */
849 SYNC /* Some chip revs need this... */
850 mtmsr r3
851 SYNC
852
853 mtlr r4 /* restore link register */
854 blr
855
856 /*
857 * Function: relocate entries for one exception vector
858 */
859 trap_reloc:
860 lwz r0, 0(r7) /* hdlr ... */
861 add r0, r0, r3 /* ... += dest_addr */
862 stw r0, 0(r7)
863
864 lwz r0, 4(r7) /* int_return ... */
865 add r0, r0, r3 /* ... += dest_addr */
866 stw r0, 4(r7)
867
868 blr
869
870 #ifdef CFG_INIT_RAM_LOCK
871 .globl unlock_ram_in_cache
872 unlock_ram_in_cache:
873 /* invalidate the INIT_RAM section */
874 lis r3, (CFG_INIT_RAM_ADDR & ~31)@h
875 ori r3, r3, (CFG_INIT_RAM_ADDR & ~31)@l
876 li r2,512
877 mtctr r2
878 1: icbi r0, r3
879 dcbi r0, r3
880 addi r3, r3, 32
881 bdnz 1b
882 sync /* Wait for all icbi to complete on bus */
883 isync
884 blr
885 #endif
886
887 map_flash_by_law1:
888 /* When booting from ROM (Flash or EPROM), clear the */
889 /* Address Mask in OR0 so ROM appears everywhere */
890 /*----------------------------------------------------*/
891 lis r3, (CFG_IMMRBAR)@h /* r3 <= CFG_IMMRBAR */
892 lwz r4, OR0@l(r3)
893 li r5, 0x7fff /* r5 <= 0x00007FFFF */
894 and r4, r4, r5
895 stw r4, OR0@l(r3) /* OR0 <= OR0 & 0x00007FFFF */
896
897 /* As MPC8349E User's Manual presented, when RCW[BMS] is set to 0,
898 * system will boot from 0x0000_0100, and the LBLAWBAR0[BASE_ADDR]
899 * reset value is 0x00000; when RCW[BMS] is set to 1, system will boot
900 * from 0xFFF0_0100, and the LBLAWBAR0[BASE_ADDR] reset value is
901 * 0xFF800. From the hard resetting to here, the processor fetched and
902 * executed the instructions one by one. There is not absolutely
903 * jumping happened. Laterly, the u-boot code has to do an absolutely
904 * jumping to tell the CPU instruction fetching component what the
905 * u-boot TEXT base address is. Because the TEXT base resides in the
906 * boot ROM memory space, to garantee the code can run smoothly after
907 * that jumping, we must map in the entire boot ROM by Local Access
908 * Window. Sometimes, we desire an non-0x00000 or non-0xFF800 starting
909 * address for boot ROM, such as 0xFE000000. In this case, the default
910 * LBIU Local Access Widow 0 will not cover this memory space. So, we
911 * need another window to map in it.
912 */
913 lis r4, (CFG_FLASH_BASE)@h
914 ori r4, r4, (CFG_FLASH_BASE)@l
915 stw r4, LBLAWBAR1(r3) /* LBLAWBAR1 <= CFG_FLASH_BASE */
916 lis r4, (0x80000016)@h
917 ori r4, r4, (0x80000016)@l
918 stw r4, LBLAWAR1(r3) /* LBLAWAR1 <= 8MB Flash Size */
919 blr
920
921 /* Though all the LBIU Local Access Windows and LBC Banks will be
922 * initialized in the C code, we'd better configure boot ROM's
923 * window 0 and bank 0 correctly at here.
924 */
925 remap_flash_by_law0:
926 /* Initialize the BR0 with the boot ROM starting address. */
927 lwz r4, BR0(r3)
928 li r5, 0x7FFF
929 and r4, r4, r5
930 lis r5, (CFG_FLASH_BASE & 0xFFFF8000)@h
931 ori r5, r5, (CFG_FLASH_BASE & 0xFFFF8000)@l
932 or r5, r5, r4
933 stw r5, BR0(r3) /* r5 <= (CFG_FLASH_BASE & 0xFFFF8000) | (BR0 & 0x00007FFF) */
934
935 lwz r4, OR0(r3)
936 lis r5, 0xFF80 /* 8M */
937 or r4, r4, r5
938 stw r4, OR0(r3) /* OR0 <= OR0 | 0xFF800000 */
939
940 lis r4, (CFG_FLASH_BASE)@h
941 ori r4, r4, (CFG_FLASH_BASE)@l
942 stw r4, LBLAWBAR0(r3) /* LBLAWBAR0 <= CFG_FLASH_BASE */
943
944 lis r4, (0x80000016)@h
945 ori r4, r4, (0x80000016)@l
946 stw r4, LBLAWAR0(r3) /* LBLAWAR0 <= 8MB Flash Size */
947
948 xor r4, r4, r4
949 stw r4, LBLAWBAR1(r3)
950 stw r4, LBLAWAR1(r3) /* Off LBIU LAW1 */
951 blr
952
953 setup_stack_in_data_cache_on_r1:
954 lis r3, (CFG_IMMRBAR)@h
955
956 /* setup D-BAT for the D-Cache (with out real memory backup) */
957
958 lis r4, (CFG_INIT_RAM_ADDR & 0xFFFE0000)@h
959 mtspr DBAT0U, r4
960 ori r4, r4, 0x0002
961 mtspr DBAT0L, r4
962 isync
963
964 #if 0
965 /* Enable MMU */
966 mfmsr r4
967 ori r4, r4, (MSR_DR | MSR_IR)@l
968 mtmsr r4
969 #endif
970
971 /* Enable and invalidate data cache. */
972 mfspr r4, HID0
973 mr r5, r4
974 ori r4, r4, HID0_DCE | HID0_DCI
975 ori r5, r5, HID0_DCE
976 sync
977 mtspr HID0, r4
978 mtspr HID0, r5
979 sync
980
981 /* Allocate Initial RAM in data cache.*/
982 li r0, 0
983 lis r4, (CFG_INIT_RAM_ADDR)@h
984 ori r4, r4, (CFG_INIT_RAM_ADDR)@l
985 li r5, 128*8 /* 128*8*32=32Kb */
986 mtctr r5
987 1:
988 dcbz r0, r4
989 addi r4, r4, 32
990 bdnz 1b
991 isync
992
993 /* Lock all the D-cache, basically leaving the reset of the program without dcache */
994 mfspr r4, HID0
995 ori r4, r4, (HID0_DLOCK)@l
996 sync
997 mtspr HID0 , r4
998
999 /* setup the stack pointer in r1 */
1000 lis r1, (CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET)@h
1001 ori r1, r1, (CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET)@l
1002 li r0, 0 /* Make room for stack frame header and */
1003
1004 stwu r0, -4(r1) /* clear final stack frame so that */
1005 stwu r0, -4(r1) /* stack backtraces terminate cleanly */
1006
1007 blr
1008
1009 un_setup_stack_in_data_cache:
1010 blr
1011 mr r14, r4
1012 mr r15, r5
1013
1014
1015 lis r4, (CFG_INIT_RAM_ADDR & 0xFFFE0000)@h
1016 mtspr DBAT0U, r4
1017 ori r4, r4, 0x0002
1018 mtspr DBAT0L, r4
1019 isync
1020
1021 /* un lock all the D-cache */
1022 mfspr r4, HID0
1023 lis r5, (~(HID0_DLOCK))@h
1024 ori r5, r5, (~(HID0_DLOCK))@l
1025 and r4, r4, r5
1026 sync
1027 mtspr HID0 , r4
1028
1029 /* Re - Allocate Initial RAM in data cache.*/
1030 li r0, 0
1031 lis r4, (CFG_INIT_RAM_ADDR)@h
1032 ori r4, r4, (CFG_INIT_RAM_ADDR)@l
1033 li r5, 128*8 /* 128*8*32=32Kb */
1034 mtctr r5
1035 1:
1036 dcbz r0, r4
1037 addi r4, r4, 32
1038 bdnz 1b
1039 isync
1040
1041 mflr r16
1042 bl dcache_disable
1043 mtlr r16
1044
1045 blr
1046
1047 #if 0
1048 #define GREEN_LIGHT 0x2B0D4046
1049 #define RED_LIGHT 0x250D4046
1050 #define LIB_CNT 0x4FFF
1051
1052 /*
1053 * Lib Light
1054 */
1055
1056 .globl liblight
1057 liblight:
1058 lis r3, CFG_IMMRBAR@h
1059 ori r3, r3, CFG_IMMRBAR@l
1060 li r4, 0x3002
1061 mtmsr r4
1062 xor r4, r4, r4
1063 mtspr HID0, r4
1064 mtspr HID2, r4
1065 lis r4, 0xF8000000@h
1066 ori r4, r4, 0xF8000000@l
1067 stw r4, LBLAWBAR1(r3)
1068 lis r4, 0x8000000E@h
1069 ori r4, r4, 0x8000000E@l
1070 stw r4, LBLAWAR1(r3)
1071 lis r4, 0xF8000801@h
1072 ori r4, r4, 0xF8000801@l
1073 stw r4, BR1(r3)
1074 lis r4, 0xFFFFE8f0@h
1075 ori r4, r4, 0xFFFFE8f0@l
1076 stw r4, OR1(r3)
1077
1078 lis r4, 0xF8000000@h
1079 ori r4, r4, 0xF8000000@l
1080 lis r5, GREEN_LIGHT@h
1081 ori r5, r5, GREEN_LIGHT@l
1082 lis r6, RED_LIGHT@h
1083 ori r6, r6, RED_LIGHT@l
1084 lis r7, LIB_CNT@h
1085 ori r7, r7, LIB_CNT@l
1086
1087 1:
1088 stw r5, 0(r4)
1089 mtctr r7
1090 2: bdnz 2b
1091 stw r6, 0(r4)
1092 mtctr r7
1093 3: bdnz 3b
1094 b 1b
1095
1096 #endif