]> git.ipfire.org Git - people/ms/u-boot.git/blame - cpu/mpc83xx/start.S
Merge remote branch 'u-boot-at91/for-1.3.4'
[people/ms/u-boot.git] / cpu / mpc83xx / start.S
CommitLineData
f046ccd1
EL
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>
31068b7c 5 * Copyright Freescale Semiconductor, Inc. 2004, 2006. All rights reserved.
f046ccd1
EL
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>
de1d0a69 31#include <mpc83xx.h>
f046ccd1
EL
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/*
f35f3582
JVB
80 * The Hard Reset Configuration Word (HRCW) table is in the first 64
81 * (0x40) bytes of flash. It has 8 bytes, but each byte is repeated 8
82 * times so the processor can fetch it out of flash whether the flash
83 * is 8, 16, 32, or 64 bits wide (hardware trickery).
f046ccd1 84 */
f046ccd1
EL
85 .text
86#define _HRCW_TABLE_ENTRY(w) \
87 .fill 8,1,(((w)>>24)&0xff); \
88 .fill 8,1,(((w)>>16)&0xff); \
89 .fill 8,1,(((w)>> 8)&0xff); \
90 .fill 8,1,(((w) )&0xff)
91
92 _HRCW_TABLE_ENTRY(CFG_HRCW_LOW)
93 _HRCW_TABLE_ENTRY(CFG_HRCW_HIGH)
94
f35f3582
JVB
95/*
96 * Magic number and version string - put it after the HRCW since it
97 * cannot be first in flash like it is in many other processors.
98 */
99 .long 0x27051956 /* U-Boot Magic Number */
100
101 .globl version_string
102version_string:
103 .ascii U_BOOT_VERSION
104 .ascii " (", __DATE__, " - ", __TIME__, ")"
105 .ascii " ", CONFIG_IDENT_STRING, "\0"
106
f046ccd1 107
f046ccd1
EL
108#ifndef CONFIG_DEFAULT_IMMR
109#error CONFIG_DEFAULT_IMMR must be defined
110#endif /* CFG_DEFAULT_IMMR */
d239d74b
TT
111#ifndef CFG_IMMR
112#define CFG_IMMR CONFIG_DEFAULT_IMMR
113#endif /* CFG_IMMR */
f046ccd1
EL
114
115/*
116 * After configuration, a system reset exception is executed using the
117 * vector at offset 0x100 relative to the base set by MSR[IP]. If
118 * MSR[IP] is 0, the base address is 0x00000000. If MSR[IP] is 1, the
119 * base address is 0xfff00000. In the case of a Power On Reset or Hard
120 * Reset, the value of MSR[IP] is determined by the CIP field in the
121 * HRCW.
122 *
123 * Other bits in the HRCW set up the Base Address and Port Size in BR0.
124 * This determines the location of the boot ROM (flash or EPROM) in the
125 * processor's address space at boot time. As long as the HRCW is set up
126 * so that we eventually end up executing the code below when the
127 * processor executes the reset exception, the actual values used should
128 * not matter.
129 *
130 * Once we have got here, the address mask in OR0 is cleared so that the
131 * bottom 32K of the boot ROM is effectively repeated all throughout the
132 * processor's address space, after which we can jump to the absolute
133 * address at which the boot ROM was linked at compile time, and proceed
134 * to initialise the memory controller without worrying if the rug will
135 * be pulled out from under us, so to speak (it will be fine as long as
136 * we configure BR0 with the same boot ROM link address).
137 */
138 . = EXC_OFF_SYS_RESET
139
140 .globl _start
141_start: /* time t 0 */
142 li r21, BOOTFLAG_COLD /* Normal Power-On: Boot from FLASH*/
143 nop
144 b boot_cold
145
146 . = EXC_OFF_SYS_RESET + 0x10
147
148 .globl _start_warm
de1d0a69 149_start_warm:
f046ccd1
EL
150 li r21, BOOTFLAG_WARM /* Software reboot */
151 b boot_warm
152
153
154boot_cold: /* time t 3 */
155 lis r4, CONFIG_DEFAULT_IMMR@h
156 nop
157boot_warm: /* time t 5 */
158 mfmsr r5 /* save msr contents */
d239d74b
TT
159 lis r3, CFG_IMMR@h
160 ori r3, r3, CFG_IMMR@l
f046ccd1 161 stw r3, IMMRBAR(r4)
de1d0a69 162
f046ccd1
EL
163 /* Initialise the E300 processor core */
164 /*------------------------------------------*/
de1d0a69 165
f046ccd1 166 bl init_e300_core
de1d0a69 167
f046ccd1
EL
168#ifndef CFG_RAMBOOT
169
170 /* Inflate flash location so it appears everywhere, calculate */
171 /* the absolute address in final location of the FLASH, jump */
172 /* there and deflate the flash size back to minimal size */
173 /*------------------------------------------------------------*/
174 bl map_flash_by_law1
78e48829
KP
175 lis r4, (CFG_MONITOR_BASE)@h
176 ori r4, r4, (CFG_MONITOR_BASE)@l
f046ccd1
EL
177 addi r5, r4, in_flash - _start + EXC_OFF_SYS_RESET
178 mtlr r5
179 blr
180in_flash:
181#if 1 /* Remapping flash with LAW0. */
182 bl remap_flash_by_law0
183#endif
184#endif /* CFG_RAMBOOT */
185
2688e2f9
KG
186 /* setup the bats */
187 bl setup_bats
188 sync
189
190 /*
191 * Cache must be enabled here for stack-in-cache trick.
192 * This means we need to enable the BATS.
193 * This means:
194 * 1) for the EVB, original gt regs need to be mapped
195 * 2) need to have an IBAT for the 0xf region,
196 * we are running there!
197 * Cache should be turned on after BATs, since by default
198 * everything is write-through.
199 * The init-mem BAT can be reused after reloc. The old
200 * gt-regs BAT can be reused after board_init_f calls
201 * board_early_init_f (EVB only).
202 */
203 /* enable address translation */
204 bl enable_addr_trans
205 sync
206
207 /* enable and invalidate the data cache */
208 bl dcache_enable
209 sync
210#ifdef CFG_INIT_RAM_LOCK
211 bl lock_ram_in_cache
212 sync
213#endif
214
215 /* set up the stack pointer in our newly created
216 * cache-ram (r1) */
217 lis r1, (CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET)@h
218 ori r1, r1, (CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET)@l
219
220 li r0, 0 /* Make room for stack frame header and */
221 stwu r0, -4(r1) /* clear final stack frame so that */
222 stwu r0, -4(r1) /* stack backtraces terminate cleanly */
223
f046ccd1
EL
224
225 /* let the C-code set up the rest */
2688e2f9 226 /* */
f046ccd1
EL
227 /* Be careful to keep code relocatable & stack humble */
228 /*------------------------------------------------------*/
229
230 GET_GOT /* initialize GOT access */
231
232 /* r3: IMMR */
d239d74b 233 lis r3, CFG_IMMR@h
f046ccd1
EL
234 /* run low-level CPU init code (in Flash)*/
235 bl cpu_init_f
236
237 /* r3: BOOTFLAG */
238 mr r3, r21
239 /* run 1st part of board init code (in Flash)*/
240 bl board_init_f
241
242/*
243 * Vector Table
244 */
245
246 .globl _start_of_vectors
247_start_of_vectors:
248
249/* Machine check */
250 STD_EXCEPTION(0x200, MachineCheck, MachineCheckException)
251
252/* Data Storage exception. */
253 STD_EXCEPTION(0x300, DataStorage, UnknownException)
254
255/* Instruction Storage exception. */
256 STD_EXCEPTION(0x400, InstStorage, UnknownException)
257
258/* External Interrupt exception. */
259#ifndef FIXME
260 STD_EXCEPTION(0x500, ExtInterrupt, external_interrupt)
de1d0a69 261#endif
f046ccd1
EL
262
263/* Alignment exception. */
264 . = 0x600
265Alignment:
02032e8f 266 EXCEPTION_PROLOG(SRR0, SRR1)
f046ccd1
EL
267 mfspr r4,DAR
268 stw r4,_DAR(r21)
269 mfspr r5,DSISR
270 stw r5,_DSISR(r21)
271 addi r3,r1,STACK_FRAME_OVERHEAD
272 li r20,MSR_KERNEL
273 rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */
274 rlwimi r20,r23,0,25,25 /* copy IP bit from saved MSR */
275 lwz r6,GOT(transfer_to_handler)
276 mtlr r6
277 blrl
278.L_Alignment:
279 .long AlignmentException - _start + EXC_OFF_SYS_RESET
280 .long int_return - _start + EXC_OFF_SYS_RESET
281
282/* Program check exception */
283 . = 0x700
284ProgramCheck:
02032e8f 285 EXCEPTION_PROLOG(SRR0, SRR1)
f046ccd1
EL
286 addi r3,r1,STACK_FRAME_OVERHEAD
287 li r20,MSR_KERNEL
288 rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */
289 rlwimi r20,r23,0,25,25 /* copy IP bit from saved MSR */
290 lwz r6,GOT(transfer_to_handler)
291 mtlr r6
292 blrl
293.L_ProgramCheck:
294 .long ProgramCheckException - _start + EXC_OFF_SYS_RESET
295 .long int_return - _start + EXC_OFF_SYS_RESET
296
297 STD_EXCEPTION(0x800, FPUnavailable, UnknownException)
298
299 /* I guess we could implement decrementer, and may have
300 * to someday for timekeeping.
301 */
302 STD_EXCEPTION(0x900, Decrementer, timer_interrupt)
303
304 STD_EXCEPTION(0xa00, Trap_0a, UnknownException)
305 STD_EXCEPTION(0xb00, Trap_0b, UnknownException)
306 STD_EXCEPTION(0xc00, SystemCall, UnknownException)
307 STD_EXCEPTION(0xd00, SingleStep, UnknownException)
308
309 STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
310 STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
311
312 STD_EXCEPTION(0x1000, InstructionTLBMiss, UnknownException)
313 STD_EXCEPTION(0x1100, DataLoadTLBMiss, UnknownException)
314 STD_EXCEPTION(0x1200, DataStoreTLBMiss, UnknownException)
315#ifdef DEBUG
316 . = 0x1300
317 /*
318 * This exception occurs when the program counter matches the
319 * Instruction Address Breakpoint Register (IABR).
320 *
321 * I want the cpu to halt if this occurs so I can hunt around
322 * with the debugger and look at things.
323 *
324 * When DEBUG is defined, both machine check enable (in the MSR)
325 * and checkstop reset enable (in the reset mode register) are
326 * turned off and so a checkstop condition will result in the cpu
327 * halting.
328 *
329 * I force the cpu into a checkstop condition by putting an illegal
330 * instruction here (at least this is the theory).
331 *
332 * well - that didnt work, so just do an infinite loop!
333 */
3341: b 1b
335#else
336 STD_EXCEPTION(0x1300, InstructionBreakpoint, DebugException)
337#endif
338 STD_EXCEPTION(0x1400, SMI, UnknownException)
339
340 STD_EXCEPTION(0x1500, Trap_15, UnknownException)
341 STD_EXCEPTION(0x1600, Trap_16, UnknownException)
342 STD_EXCEPTION(0x1700, Trap_17, UnknownException)
343 STD_EXCEPTION(0x1800, Trap_18, UnknownException)
344 STD_EXCEPTION(0x1900, Trap_19, UnknownException)
345 STD_EXCEPTION(0x1a00, Trap_1a, UnknownException)
346 STD_EXCEPTION(0x1b00, Trap_1b, UnknownException)
347 STD_EXCEPTION(0x1c00, Trap_1c, UnknownException)
348 STD_EXCEPTION(0x1d00, Trap_1d, UnknownException)
349 STD_EXCEPTION(0x1e00, Trap_1e, UnknownException)
350 STD_EXCEPTION(0x1f00, Trap_1f, UnknownException)
351 STD_EXCEPTION(0x2000, Trap_20, UnknownException)
352 STD_EXCEPTION(0x2100, Trap_21, UnknownException)
353 STD_EXCEPTION(0x2200, Trap_22, UnknownException)
354 STD_EXCEPTION(0x2300, Trap_23, UnknownException)
355 STD_EXCEPTION(0x2400, Trap_24, UnknownException)
356 STD_EXCEPTION(0x2500, Trap_25, UnknownException)
357 STD_EXCEPTION(0x2600, Trap_26, UnknownException)
358 STD_EXCEPTION(0x2700, Trap_27, UnknownException)
359 STD_EXCEPTION(0x2800, Trap_28, UnknownException)
360 STD_EXCEPTION(0x2900, Trap_29, UnknownException)
361 STD_EXCEPTION(0x2a00, Trap_2a, UnknownException)
362 STD_EXCEPTION(0x2b00, Trap_2b, UnknownException)
363 STD_EXCEPTION(0x2c00, Trap_2c, UnknownException)
364 STD_EXCEPTION(0x2d00, Trap_2d, UnknownException)
365 STD_EXCEPTION(0x2e00, Trap_2e, UnknownException)
366 STD_EXCEPTION(0x2f00, Trap_2f, UnknownException)
367
368
369 .globl _end_of_vectors
370_end_of_vectors:
371
372 . = 0x3000
373
374/*
375 * This code finishes saving the registers to the exception frame
376 * and jumps to the appropriate handler for the exception.
377 * Register r21 is pointer into trap frame, r1 has new stack pointer.
378 */
379 .globl transfer_to_handler
380transfer_to_handler:
381 stw r22,_NIP(r21)
382 lis r22,MSR_POW@h
383 andc r23,r23,r22
384 stw r23,_MSR(r21)
385 SAVE_GPR(7, r21)
386 SAVE_4GPRS(8, r21)
387 SAVE_8GPRS(12, r21)
388 SAVE_8GPRS(24, r21)
389 mflr r23
390 andi. r24,r23,0x3f00 /* get vector offset */
391 stw r24,TRAP(r21)
392 li r22,0
393 stw r22,RESULT(r21)
394 lwz r24,0(r23) /* virtual address of handler */
395 lwz r23,4(r23) /* where to go when done */
396 mtspr SRR0,r24
397 mtspr SRR1,r20
398 mtlr r23
399 SYNC
400 rfi /* jump to handler, enable MMU */
401
402int_return:
403 mfmsr r28 /* Disable interrupts */
404 li r4,0
405 ori r4,r4,MSR_EE
406 andc r28,r28,r4
407 SYNC /* Some chip revs need this... */
408 mtmsr r28
409 SYNC
410 lwz r2,_CTR(r1)
411 lwz r0,_LINK(r1)
412 mtctr r2
413 mtlr r0
414 lwz r2,_XER(r1)
415 lwz r0,_CCR(r1)
416 mtspr XER,r2
417 mtcrf 0xFF,r0
418 REST_10GPRS(3, r1)
419 REST_10GPRS(13, r1)
420 REST_8GPRS(23, r1)
421 REST_GPR(31, r1)
422 lwz r2,_NIP(r1) /* Restore environment */
423 lwz r0,_MSR(r1)
424 mtspr SRR0,r2
425 mtspr SRR1,r0
426 lwz r0,GPR0(r1)
427 lwz r2,GPR2(r1)
428 lwz r1,GPR1(r1)
429 SYNC
430 rfi
431
432/*
433 * This code initialises the E300 processor core
434 * (conforms to PowerPC 603e spec)
435 * Note: expects original MSR contents to be in r5.
436 */
437 .globl init_e300_core
438init_e300_core: /* time t 10 */
439 /* Initialize machine status; enable machine check interrupt */
440 /*-----------------------------------------------------------*/
441
442 li r3, MSR_KERNEL /* Set ME and RI flags */
443 rlwimi r3, r5, 0, 25, 25 /* preserve IP bit set by HRCW */
444#ifdef DEBUG
445 rlwimi r3, r5, 0, 21, 22 /* debugger might set SE & BE bits */
446#endif
447 SYNC /* Some chip revs need this... */
448 mtmsr r3
449 SYNC
450 mtspr SRR1, r3 /* Make SRR1 match MSR */
451
452
d239d74b 453 lis r3, CFG_IMMR@h
f046ccd1
EL
454#if defined(CONFIG_WATCHDOG)
455 /* Initialise the Wathcdog values and reset it (if req) */
456 /*------------------------------------------------------*/
457 lis r4, CFG_WATCHDOG_VALUE
458 ori r4, r4, (SWCRR_SWEN | SWCRR_SWRI | SWCRR_SWPR)
459 stw r4, SWCRR(r3)
de1d0a69 460
f046ccd1 461 /* and reset it */
de1d0a69 462
f046ccd1
EL
463 li r4, 0x556C
464 sth r4, SWSRR@l(r3)
f6db9456 465 li r4, -0x55C7
f046ccd1
EL
466 sth r4, SWSRR@l(r3)
467#else
468 /* Disable Wathcdog */
469 /*-------------------*/
ec00c335
KG
470 lwz r4, SWCRR(r3)
471 /* Check to see if its enabled for disabling
472 once disabled by SW you can't re-enable */
473 andi. r4, r4, 0x4
474 beq 1f
f046ccd1
EL
475 xor r4, r4, r4
476 stw r4, SWCRR(r3)
ec00c335 4771:
f046ccd1
EL
478#endif /* CONFIG_WATCHDOG */
479
480 /* Initialize the Hardware Implementation-dependent Registers */
481 /* HID0 also contains cache control */
482 /*------------------------------------------------------*/
483
484 lis r3, CFG_HID0_INIT@h
485 ori r3, r3, CFG_HID0_INIT@l
486 SYNC
487 mtspr HID0, r3
488
489 lis r3, CFG_HID0_FINAL@h
490 ori r3, r3, CFG_HID0_FINAL@l
491 SYNC
492 mtspr HID0, r3
493
494 lis r3, CFG_HID2@h
495 ori r3, r3, CFG_HID2@l
496 SYNC
497 mtspr HID2, r3
498
499 /* clear all BAT's */
500 /*----------------------------------*/
501
502 xor r0, r0, r0
503 mtspr DBAT0U, r0
504 mtspr DBAT0L, r0
505 mtspr DBAT1U, r0
506 mtspr DBAT1L, r0
507 mtspr DBAT2U, r0
508 mtspr DBAT2L, r0
509 mtspr DBAT3U, r0
510 mtspr DBAT3L, r0
511 mtspr IBAT0U, r0
512 mtspr IBAT0L, r0
513 mtspr IBAT1U, r0
514 mtspr IBAT1L, r0
515 mtspr IBAT2U, r0
516 mtspr IBAT2L, r0
517 mtspr IBAT3U, r0
518 mtspr IBAT3L, r0
519 SYNC
520
521 /* invalidate all tlb's
522 *
523 * From the 603e User Manual: "The 603e provides the ability to
524 * invalidate a TLB entry. The TLB Invalidate Entry (tlbie)
525 * instruction invalidates the TLB entry indexed by the EA, and
526 * operates on both the instruction and data TLBs simultaneously
527 * invalidating four TLB entries (both sets in each TLB). The
528 * index corresponds to bits 15-19 of the EA. To invalidate all
529 * entries within both TLBs, 32 tlbie instructions should be
530 * issued, incrementing this field by one each time."
531 *
532 * "Note that the tlbia instruction is not implemented on the
533 * 603e."
534 *
535 * bits 15-19 correspond to addresses 0x00000000 to 0x0001F000
536 * incrementing by 0x1000 each time. The code below is sort of
537 * based on code in "flush_tlbs" from arch/ppc/kernel/head.S
538 *
539 */
540
541 li r3, 32
542 mtctr r3
543 li r3, 0
5441: tlbie r3
545 addi r3, r3, 0x1000
546 bdnz 1b
547 SYNC
548
549 /* Done! */
550 /*------------------------------*/
de1d0a69 551 blr
f046ccd1 552
2688e2f9
KG
553 .globl invalidate_bats
554invalidate_bats:
555 /* invalidate BATs */
556 mtspr IBAT0U, r0
557 mtspr IBAT1U, r0
558 mtspr IBAT2U, r0
559 mtspr IBAT3U, r0
560#if (CFG_HID2 & HID2_HBE)
561 mtspr IBAT4U, r0
562 mtspr IBAT5U, r0
563 mtspr IBAT6U, r0
564 mtspr IBAT7U, r0
565#endif
566 isync
567 mtspr DBAT0U, r0
568 mtspr DBAT1U, r0
569 mtspr DBAT2U, r0
570 mtspr DBAT3U, r0
571#if (CFG_HID2 & HID2_HBE)
572 mtspr DBAT4U, r0
573 mtspr DBAT5U, r0
574 mtspr DBAT6U, r0
575 mtspr DBAT7U, r0
576#endif
577 isync
578 sync
579 blr
580
581 /* setup_bats - set them up to some initial state */
582 .globl setup_bats
583setup_bats:
584 addis r0, r0, 0x0000
585
586 /* IBAT 0 */
587 addis r4, r0, CFG_IBAT0L@h
588 ori r4, r4, CFG_IBAT0L@l
589 addis r3, r0, CFG_IBAT0U@h
590 ori r3, r3, CFG_IBAT0U@l
591 mtspr IBAT0L, r4
592 mtspr IBAT0U, r3
593 isync
594
595 /* DBAT 0 */
596 addis r4, r0, CFG_DBAT0L@h
597 ori r4, r4, CFG_DBAT0L@l
598 addis r3, r0, CFG_DBAT0U@h
599 ori r3, r3, CFG_DBAT0U@l
600 mtspr DBAT0L, r4
601 mtspr DBAT0U, r3
602 isync
603
604 /* IBAT 1 */
605 addis r4, r0, CFG_IBAT1L@h
606 ori r4, r4, CFG_IBAT1L@l
607 addis r3, r0, CFG_IBAT1U@h
608 ori r3, r3, CFG_IBAT1U@l
609 mtspr IBAT1L, r4
610 mtspr IBAT1U, r3
611 isync
612
613 /* DBAT 1 */
614 addis r4, r0, CFG_DBAT1L@h
615 ori r4, r4, CFG_DBAT1L@l
616 addis r3, r0, CFG_DBAT1U@h
617 ori r3, r3, CFG_DBAT1U@l
618 mtspr DBAT1L, r4
619 mtspr DBAT1U, r3
620 isync
621
622 /* IBAT 2 */
623 addis r4, r0, CFG_IBAT2L@h
624 ori r4, r4, CFG_IBAT2L@l
625 addis r3, r0, CFG_IBAT2U@h
626 ori r3, r3, CFG_IBAT2U@l
627 mtspr IBAT2L, r4
628 mtspr IBAT2U, r3
629 isync
630
631 /* DBAT 2 */
632 addis r4, r0, CFG_DBAT2L@h
633 ori r4, r4, CFG_DBAT2L@l
634 addis r3, r0, CFG_DBAT2U@h
635 ori r3, r3, CFG_DBAT2U@l
636 mtspr DBAT2L, r4
637 mtspr DBAT2U, r3
638 isync
639
640 /* IBAT 3 */
641 addis r4, r0, CFG_IBAT3L@h
642 ori r4, r4, CFG_IBAT3L@l
643 addis r3, r0, CFG_IBAT3U@h
644 ori r3, r3, CFG_IBAT3U@l
645 mtspr IBAT3L, r4
646 mtspr IBAT3U, r3
647 isync
648
649 /* DBAT 3 */
650 addis r4, r0, CFG_DBAT3L@h
651 ori r4, r4, CFG_DBAT3L@l
652 addis r3, r0, CFG_DBAT3U@h
653 ori r3, r3, CFG_DBAT3U@l
654 mtspr DBAT3L, r4
655 mtspr DBAT3U, r3
656 isync
657
658#if (CFG_HID2 & HID2_HBE)
659 /* IBAT 4 */
660 addis r4, r0, CFG_IBAT4L@h
661 ori r4, r4, CFG_IBAT4L@l
662 addis r3, r0, CFG_IBAT4U@h
663 ori r3, r3, CFG_IBAT4U@l
664 mtspr IBAT4L, r4
665 mtspr IBAT4U, r3
666 isync
667
668 /* DBAT 4 */
669 addis r4, r0, CFG_DBAT4L@h
670 ori r4, r4, CFG_DBAT4L@l
671 addis r3, r0, CFG_DBAT4U@h
672 ori r3, r3, CFG_DBAT4U@l
673 mtspr DBAT4L, r4
674 mtspr DBAT4U, r3
675 isync
676
677 /* IBAT 5 */
678 addis r4, r0, CFG_IBAT5L@h
679 ori r4, r4, CFG_IBAT5L@l
680 addis r3, r0, CFG_IBAT5U@h
681 ori r3, r3, CFG_IBAT5U@l
682 mtspr IBAT5L, r4
683 mtspr IBAT5U, r3
684 isync
685
686 /* DBAT 5 */
687 addis r4, r0, CFG_DBAT5L@h
688 ori r4, r4, CFG_DBAT5L@l
689 addis r3, r0, CFG_DBAT5U@h
690 ori r3, r3, CFG_DBAT5U@l
691 mtspr DBAT5L, r4
692 mtspr DBAT5U, r3
693 isync
694
695 /* IBAT 6 */
696 addis r4, r0, CFG_IBAT6L@h
697 ori r4, r4, CFG_IBAT6L@l
698 addis r3, r0, CFG_IBAT6U@h
699 ori r3, r3, CFG_IBAT6U@l
700 mtspr IBAT6L, r4
701 mtspr IBAT6U, r3
702 isync
703
704 /* DBAT 6 */
705 addis r4, r0, CFG_DBAT6L@h
706 ori r4, r4, CFG_DBAT6L@l
707 addis r3, r0, CFG_DBAT6U@h
708 ori r3, r3, CFG_DBAT6U@l
709 mtspr DBAT6L, r4
710 mtspr DBAT6U, r3
711 isync
712
713 /* IBAT 7 */
714 addis r4, r0, CFG_IBAT7L@h
715 ori r4, r4, CFG_IBAT7L@l
716 addis r3, r0, CFG_IBAT7U@h
717 ori r3, r3, CFG_IBAT7U@l
718 mtspr IBAT7L, r4
719 mtspr IBAT7U, r3
720 isync
721
722 /* DBAT 7 */
723 addis r4, r0, CFG_DBAT7L@h
724 ori r4, r4, CFG_DBAT7L@l
725 addis r3, r0, CFG_DBAT7U@h
726 ori r3, r3, CFG_DBAT7U@l
727 mtspr DBAT7L, r4
728 mtspr DBAT7U, r3
729 isync
730#endif
731
732 /* Invalidate TLBs.
733 * -> for (val = 0; val < 0x20000; val+=0x1000)
734 * -> tlbie(val);
735 */
736 lis r3, 0
737 lis r5, 2
738
7391:
740 tlbie r3
741 addi r3, r3, 0x1000
742 cmp 0, 0, r3, r5
743 blt 1b
744
745 blr
746
747 .globl enable_addr_trans
748enable_addr_trans:
749 /* enable address translation */
750 mfmsr r5
751 ori r5, r5, (MSR_IR | MSR_DR)
752 mtmsr r5
753 isync
754 blr
755
756 .globl disable_addr_trans
757disable_addr_trans:
758 /* disable address translation */
759 mflr r4
760 mfmsr r3
761 andi. r0, r3, (MSR_IR | MSR_DR)
762 beqlr
763 andc r3, r3, r0
764 mtspr SRR0, r4
765 mtspr SRR1, r3
766 rfi
767
f046ccd1
EL
768/* Cache functions.
769 *
770 * Note: requires that all cache bits in
771 * HID0 are in the low half word.
772 */
773 .globl icache_enable
774icache_enable:
775 mfspr r3, HID0
776 ori r3, r3, HID0_ICE
777 lis r4, 0
778 ori r4, r4, HID0_ILOCK
779 andc r3, r3, r4
780 ori r4, r3, HID0_ICFI
781 isync
782 mtspr HID0, r4 /* sets enable and invalidate, clears lock */
783 isync
784 mtspr HID0, r3 /* clears invalidate */
785 blr
786
787 .globl icache_disable
788icache_disable:
789 mfspr r3, HID0
790 lis r4, 0
791 ori r4, r4, HID0_ICE|HID0_ILOCK
792 andc r3, r3, r4
793 ori r4, r3, HID0_ICFI
794 isync
795 mtspr HID0, r4 /* sets invalidate, clears enable and lock*/
796 isync
797 mtspr HID0, r3 /* clears invalidate */
798 blr
799
800 .globl icache_status
801icache_status:
802 mfspr r3, HID0
a7c66ad2 803 rlwinm r3, r3, (31 - HID0_ICE_SHIFT + 1), 31, 31
f046ccd1
EL
804 blr
805
806 .globl dcache_enable
807dcache_enable:
808 mfspr r3, HID0
2688e2f9
KG
809 li r5, HID0_DCFI|HID0_DLOCK
810 andc r3, r3, r5
811 mtspr HID0, r3 /* no invalidate, unlock */
812 ori r3, r3, HID0_DCE
813 ori r5, r3, HID0_DCFI
814 mtspr HID0, r5 /* enable + invalidate */
815 mtspr HID0, r3 /* enable */
f046ccd1 816 sync
f046ccd1
EL
817 blr
818
819 .globl dcache_disable
820dcache_disable:
821 mfspr r3, HID0
822 lis r4, 0
2688e2f9 823 ori r4, r4, HID0_DCE|HID0_DLOCK
f046ccd1 824 andc r3, r3, r4
2688e2f9 825 ori r4, r3, HID0_DCI
f046ccd1 826 sync
2688e2f9 827 mtspr HID0, r4 /* sets invalidate, clears enable and lock */
f046ccd1
EL
828 sync
829 mtspr HID0, r3 /* clears invalidate */
830 blr
831
832 .globl dcache_status
833dcache_status:
834 mfspr r3, HID0
a7c66ad2 835 rlwinm r3, r3, (31 - HID0_DCE_SHIFT + 1), 31, 31
f046ccd1
EL
836 blr
837
838 .globl get_pvr
839get_pvr:
840 mfspr r3, PVR
841 blr
842
90f30a71
DL
843 .globl ppcDWstore
844ppcDWstore:
845 lfd 1, 0(r4)
846 stfd 1, 0(r3)
847 blr
848
849 .globl ppcDWload
850ppcDWload:
851 lfd 1, 0(r3)
852 stfd 1, 0(r4)
853 blr
854
f046ccd1
EL
855/*-------------------------------------------------------------------*/
856
857/*
858 * void relocate_code (addr_sp, gd, addr_moni)
859 *
860 * This "function" does not return, instead it continues in RAM
861 * after relocating the monitor code.
862 *
863 * r3 = dest
864 * r4 = src
865 * r5 = length in bytes
866 * r6 = cachelinesize
867 */
868 .globl relocate_code
869relocate_code:
870 mr r1, r3 /* Set new stack pointer */
871 mr r9, r4 /* Save copy of Global Data pointer */
872 mr r10, r5 /* Save copy of Destination Address */
873
874 mr r3, r5 /* Destination Address */
78e48829
KP
875 lis r4, CFG_MONITOR_BASE@h /* Source Address */
876 ori r4, r4, CFG_MONITOR_BASE@l
f046ccd1
EL
877 lwz r5, GOT(__init_end)
878 sub r5, r5, r4
879 li r6, CFG_CACHELINE_SIZE /* Cache Line Size */
880
881 /*
882 * Fix GOT pointer:
883 *
884 * New GOT-PTR = (old GOT-PTR - CFG_MONITOR_BASE)
885 * + Destination Address
886 *
887 * Offset:
888 */
889 sub r15, r10, r4
890
891 /* First our own GOT */
892 add r14, r14, r15
893 /* then the one used by the C code */
894 add r30, r30, r15
895
896 /*
897 * Now relocate code
898 */
899
900 cmplw cr1,r3,r4
901 addi r0,r5,3
902 srwi. r0,r0,2
903 beq cr1,4f /* In place copy is not necessary */
904 beq 7f /* Protect against 0 count */
905 mtctr r0
906 bge cr1,2f
907 la r8,-4(r4)
908 la r7,-4(r3)
909
910 /* copy */
9111: lwzu r0,4(r8)
912 stwu r0,4(r7)
913 bdnz 1b
914
915 addi r0,r5,3
916 srwi. r0,r0,2
917 mtctr r0
918 la r8,-4(r4)
919 la r7,-4(r3)
de1d0a69
JL
920
921 /* and compare */
f046ccd1
EL
92220: lwzu r20,4(r8)
923 lwzu r21,4(r7)
924 xor. r22, r20, r21
925 bne 30f
926 bdnz 20b
927 b 4f
928
929 /* compare failed */
93030: li r3, 0
931 blr
932
9332: slwi r0,r0,2 /* re copy in reverse order ... y do we needed it? */
934 add r8,r4,r0
935 add r7,r3,r0
9363: lwzu r0,-4(r8)
937 stwu r0,-4(r7)
938 bdnz 3b
f046ccd1
EL
939
940/*
941 * Now flush the cache: note that we must start from a cache aligned
942 * address. Otherwise we might miss one cache line.
943 */
2688e2f9 9444: cmpwi r6,0
f046ccd1 945 add r5,r3,r5
2688e2f9 946 beq 7f /* Always flush prefetch queue in any case */
f046ccd1
EL
947 subi r0,r6,1
948 andc r3,r3,r0
f046ccd1
EL
949 mr r4,r3
9505: dcbst 0,r4
951 add r4,r4,r6
952 cmplw r4,r5
953 blt 5b
2688e2f9 954 sync /* Wait for all dcbst to complete on bus */
f046ccd1
EL
955 mr r4,r3
9566: icbi 0,r4
957 add r4,r4,r6
958 cmplw r4,r5
959 blt 6b
2688e2f9 9607: sync /* Wait for all icbi to complete on bus */
f046ccd1
EL
961 isync
962
963/*
964 * We are done. Do not return, instead branch to second part of board
965 * initialization, now running from RAM.
966 */
f046ccd1
EL
967 addi r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
968 mtlr r0
969 blr
970
971in_ram:
972
973 /*
974 * Relocation Function, r14 point to got2+0x8000
975 *
976 * Adjust got2 pointers, no need to check for 0, this code
977 * already puts a few entries in the table.
978 */
979 li r0,__got2_entries@sectoff@l
980 la r3,GOT(_GOT2_TABLE_)
981 lwz r11,GOT(_GOT2_TABLE_)
982 mtctr r0
983 sub r11,r3,r11
984 addi r3,r3,-4
9851: lwzu r0,4(r3)
986 add r0,r0,r11
987 stw r0,0(r3)
988 bdnz 1b
989
990 /*
991 * Now adjust the fixups and the pointers to the fixups
992 * in case we need to move ourselves again.
993 */
9942: li r0,__fixup_entries@sectoff@l
995 lwz r3,GOT(_FIXUP_TABLE_)
996 cmpwi r0,0
997 mtctr r0
998 addi r3,r3,-4
999 beq 4f
10003: lwzu r4,4(r3)
1001 lwzux r0,r4,r11
1002 add r0,r0,r11
1003 stw r10,0(r3)
1004 stw r0,0(r4)
1005 bdnz 3b
10064:
1007clear_bss:
1008 /*
1009 * Now clear BSS segment
1010 */
1011 lwz r3,GOT(__bss_start)
1012#if defined(CONFIG_HYMOD)
1013 /*
1014 * For HYMOD - the environment is the very last item in flash.
1015 * The real .bss stops just before environment starts, so only
1016 * clear up to that point.
1017 *
1018 * taken from mods for FADS board
1019 */
1020 lwz r4,GOT(environment)
1021#else
1022 lwz r4,GOT(_end)
1023#endif
1024
1025 cmplw 0, r3, r4
1026 beq 6f
1027
1028 li r0, 0
10295:
1030 stw r0, 0(r3)
1031 addi r3, r3, 4
1032 cmplw 0, r3, r4
1033 bne 5b
10346:
1035
1036 mr r3, r9 /* Global Data pointer */
1037 mr r4, r10 /* Destination Address */
1038 bl board_init_r
1039
1040 /*
1041 * Copy exception vector code to low memory
1042 *
1043 * r3: dest_addr
1044 * r7: source address, r8: end address, r9: target address
1045 */
1046 .globl trap_init
1047trap_init:
1048 lwz r7, GOT(_start)
1049 lwz r8, GOT(_end_of_vectors)
1050
1051 li r9, 0x100 /* reset vector always at 0x100 */
1052
1053 cmplw 0, r7, r8
1054 bgelr /* return if r7>=r8 - just in case */
1055
1056 mflr r4 /* save link register */
10571:
1058 lwz r0, 0(r7)
1059 stw r0, 0(r9)
1060 addi r7, r7, 4
1061 addi r9, r9, 4
1062 cmplw 0, r7, r8
1063 bne 1b
1064
1065 /*
1066 * relocate `hdlr' and `int_return' entries
1067 */
1068 li r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
1069 li r8, Alignment - _start + EXC_OFF_SYS_RESET
10702:
1071 bl trap_reloc
1072 addi r7, r7, 0x100 /* next exception vector */
1073 cmplw 0, r7, r8
1074 blt 2b
1075
1076 li r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
1077 bl trap_reloc
1078
1079 li r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
1080 bl trap_reloc
1081
1082 li r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
1083 li r8, SystemCall - _start + EXC_OFF_SYS_RESET
10843:
1085 bl trap_reloc
1086 addi r7, r7, 0x100 /* next exception vector */
1087 cmplw 0, r7, r8
1088 blt 3b
1089
1090 li r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
1091 li r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
10924:
1093 bl trap_reloc
1094 addi r7, r7, 0x100 /* next exception vector */
1095 cmplw 0, r7, r8
1096 blt 4b
1097
1098 mfmsr r3 /* now that the vectors have */
1099 lis r7, MSR_IP@h /* relocated into low memory */
1100 ori r7, r7, MSR_IP@l /* MSR[IP] can be turned off */
1101 andc r3, r3, r7 /* (if it was on) */
1102 SYNC /* Some chip revs need this... */
1103 mtmsr r3
1104 SYNC
1105
1106 mtlr r4 /* restore link register */
1107 blr
1108
1109 /*
1110 * Function: relocate entries for one exception vector
1111 */
1112trap_reloc:
1113 lwz r0, 0(r7) /* hdlr ... */
1114 add r0, r0, r3 /* ... += dest_addr */
1115 stw r0, 0(r7)
1116
1117 lwz r0, 4(r7) /* int_return ... */
1118 add r0, r0, r3 /* ... += dest_addr */
1119 stw r0, 4(r7)
1120
1121 blr
1122
1123#ifdef CFG_INIT_RAM_LOCK
2688e2f9
KG
1124lock_ram_in_cache:
1125 /* Allocate Initial RAM in data cache.
1126 */
1127 lis r3, (CFG_INIT_RAM_ADDR & ~31)@h
1128 ori r3, r3, (CFG_INIT_RAM_ADDR & ~31)@l
1129 li r2, ((CFG_INIT_RAM_END & ~31) + \
1130 (CFG_INIT_RAM_ADDR & 31) + 31) / 32
1131 mtctr r2
11321:
1133 dcbz r0, r3
1134 addi r3, r3, 32
1135 bdnz 1b
1136
1137 /* Lock the data cache */
1138 mfspr r0, HID0
1139 ori r0, r0, 0x1000
1140 sync
1141 mtspr HID0, r0
1142 sync
1143 blr
1144
f046ccd1
EL
1145.globl unlock_ram_in_cache
1146unlock_ram_in_cache:
1147 /* invalidate the INIT_RAM section */
1148 lis r3, (CFG_INIT_RAM_ADDR & ~31)@h
1149 ori r3, r3, (CFG_INIT_RAM_ADDR & ~31)@l
1150 li r2,512
1151 mtctr r2
11521: icbi r0, r3
1153 dcbi r0, r3
1154 addi r3, r3, 32
1155 bdnz 1b
1156 sync /* Wait for all icbi to complete on bus */
1157 isync
2688e2f9
KG
1158
1159 /* Unlock the data cache and invalidate it */
1160 mfspr r3, HID0
1161 li r5, HID0_DLOCK|HID0_DCFI
1162 andc r3, r3, r5 /* no invalidate, unlock */
1163 ori r5, r3, HID0_DCFI /* invalidate, unlock */
1164 mtspr HID0, r5 /* invalidate, unlock */
1165 mtspr HID0, r3 /* no invalidate, unlock */
1166 sync
f046ccd1
EL
1167 blr
1168#endif
1169
1170map_flash_by_law1:
1171 /* When booting from ROM (Flash or EPROM), clear the */
1172 /* Address Mask in OR0 so ROM appears everywhere */
1173 /*----------------------------------------------------*/
d239d74b 1174 lis r3, (CFG_IMMR)@h /* r3 <= CFG_IMMR */
de1d0a69 1175 lwz r4, OR0@l(r3)
f046ccd1 1176 li r5, 0x7fff /* r5 <= 0x00007FFFF */
de1d0a69 1177 and r4, r4, r5
f046ccd1
EL
1178 stw r4, OR0@l(r3) /* OR0 <= OR0 & 0x00007FFFF */
1179
1180 /* As MPC8349E User's Manual presented, when RCW[BMS] is set to 0,
1181 * system will boot from 0x0000_0100, and the LBLAWBAR0[BASE_ADDR]
1182 * reset value is 0x00000; when RCW[BMS] is set to 1, system will boot
1183 * from 0xFFF0_0100, and the LBLAWBAR0[BASE_ADDR] reset value is
1184 * 0xFF800. From the hard resetting to here, the processor fetched and
1185 * executed the instructions one by one. There is not absolutely
1186 * jumping happened. Laterly, the u-boot code has to do an absolutely
1187 * jumping to tell the CPU instruction fetching component what the
1188 * u-boot TEXT base address is. Because the TEXT base resides in the
1189 * boot ROM memory space, to garantee the code can run smoothly after
1190 * that jumping, we must map in the entire boot ROM by Local Access
1191 * Window. Sometimes, we desire an non-0x00000 or non-0xFF800 starting
1192 * address for boot ROM, such as 0xFE000000. In this case, the default
1193 * LBIU Local Access Widow 0 will not cover this memory space. So, we
1194 * need another window to map in it.
1195 */
1196 lis r4, (CFG_FLASH_BASE)@h
1197 ori r4, r4, (CFG_FLASH_BASE)@l
1198 stw r4, LBLAWBAR1(r3) /* LBLAWBAR1 <= CFG_FLASH_BASE */
31068b7c
TT
1199
1200 /* Store 0x80000012 + log2(CFG_FLASH_SIZE) into LBLAWAR1 */
1201 lis r4, (0x80000012)@h
1202 ori r4, r4, (0x80000012)@l
1203 li r5, CFG_FLASH_SIZE
12041: srawi. r5, r5, 1 /* r5 = r5 >> 1 */
1205 addi r4, r4, 1
1206 bne 1b
1207
f046ccd1
EL
1208 stw r4, LBLAWAR1(r3) /* LBLAWAR1 <= 8MB Flash Size */
1209 blr
1210
1211 /* Though all the LBIU Local Access Windows and LBC Banks will be
1212 * initialized in the C code, we'd better configure boot ROM's
1213 * window 0 and bank 0 correctly at here.
1214 */
1215remap_flash_by_law0:
1216 /* Initialize the BR0 with the boot ROM starting address. */
1217 lwz r4, BR0(r3)
1218 li r5, 0x7FFF
de1d0a69 1219 and r4, r4, r5
f046ccd1 1220 lis r5, (CFG_FLASH_BASE & 0xFFFF8000)@h
de1d0a69 1221 ori r5, r5, (CFG_FLASH_BASE & 0xFFFF8000)@l
f046ccd1
EL
1222 or r5, r5, r4
1223 stw r5, BR0(r3) /* r5 <= (CFG_FLASH_BASE & 0xFFFF8000) | (BR0 & 0x00007FFF) */
1224
1225 lwz r4, OR0(r3)
31068b7c 1226 lis r5, ~((CFG_FLASH_SIZE << 4) - 1)
f046ccd1 1227 or r4, r4, r5
31068b7c 1228 stw r4, OR0(r3)
f046ccd1
EL
1229
1230 lis r4, (CFG_FLASH_BASE)@h
1231 ori r4, r4, (CFG_FLASH_BASE)@l
1232 stw r4, LBLAWBAR0(r3) /* LBLAWBAR0 <= CFG_FLASH_BASE */
1233
31068b7c
TT
1234 /* Store 0x80000012 + log2(CFG_FLASH_SIZE) into LBLAWAR0 */
1235 lis r4, (0x80000012)@h
1236 ori r4, r4, (0x80000012)@l
1237 li r5, CFG_FLASH_SIZE
12381: srawi. r5, r5, 1 /* r5 = r5 >> 1 */
1239 addi r4, r4, 1
1240 bne 1b
1241 stw r4, LBLAWAR0(r3) /* LBLAWAR0 <= Flash Size */
1242
f046ccd1
EL
1243
1244 xor r4, r4, r4
1245 stw r4, LBLAWBAR1(r3)
1246 stw r4, LBLAWAR1(r3) /* Off LBIU LAW1 */
1247 blr