]> git.ipfire.org Git - people/ms/u-boot.git/blob - cpu/mpc86xx/start.S
Merge with /home/wd/git/u-boot/master
[people/ms/u-boot.git] / cpu / mpc86xx / start.S
1 /*
2 * Copyright 2004 Freescale Semiconductor.
3 * Srikanth Srinivasan <srikanth.srinivaan@freescale.com>
4 *
5 * See file CREDITS for list of people who contributed to this
6 * project.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21 * MA 02111-1307 USA
22 */
23
24 /* U-Boot - Startup Code for 86xx PowerPC based Embedded Boards
25 *
26 *
27 * The processor starts at 0xfff00100 and the code is executed
28 * from flash. The code is organized to be at an other address
29 * in memory, but as long we don't jump around before relocating.
30 * board_init lies at a quite high address and when the cpu has
31 * jumped there, everything is ok.
32 */
33 #include <config.h>
34 #include <mpc86xx.h>
35 #include <version.h>
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 ""
45 #endif
46
47 /* We don't want the MMU yet.
48 */
49 #undef MSR_KERNEL
50 /* Machine Check and Recoverable Interr. */
51 #define MSR_KERNEL ( MSR_ME | MSR_RI )
52
53 /*
54 * Set up GOT: Global Offset Table
55 *
56 * Use r14 to access the GOT
57 */
58 START_GOT
59 GOT_ENTRY(_GOT2_TABLE_)
60 GOT_ENTRY(_FIXUP_TABLE_)
61
62 GOT_ENTRY(_start)
63 GOT_ENTRY(_start_of_vectors)
64 GOT_ENTRY(_end_of_vectors)
65 GOT_ENTRY(transfer_to_handler)
66
67 GOT_ENTRY(__init_end)
68 GOT_ENTRY(_end)
69 GOT_ENTRY(__bss_start)
70 END_GOT
71
72 /*
73 * r3 - 1st arg to board_init(): IMMP pointer
74 * r4 - 2nd arg to board_init(): boot flag
75 */
76 .text
77 .long 0x27051956 /* U-Boot Magic Number */
78 .globl version_string
79 version_string:
80 .ascii U_BOOT_VERSION
81 .ascii " (", __DATE__, " - ", __TIME__, ")"
82 .ascii CONFIG_IDENT_STRING, "\0"
83
84 . = EXC_OFF_SYS_RESET
85 .globl _start
86 _start:
87 li r21, BOOTFLAG_COLD /* Normal Power-On: Boot from FLASH */
88 b boot_cold
89 sync
90
91 . = EXC_OFF_SYS_RESET + 0x10
92
93 .globl _start_warm
94 _start_warm:
95 li r21, BOOTFLAG_WARM /* Software reboot */
96 b boot_warm
97 sync
98
99 /* the boot code is located below the exception table */
100
101 .globl _start_of_vectors
102 _start_of_vectors:
103
104 /* Machine check */
105 STD_EXCEPTION(0x200, MachineCheck, MachineCheckException)
106
107 /* Data Storage exception. */
108 STD_EXCEPTION(0x300, DataStorage, UnknownException)
109
110 /* Instruction Storage exception. */
111 STD_EXCEPTION(0x400, InstStorage, UnknownException)
112
113 /* External Interrupt exception. */
114 STD_EXCEPTION(0x500, ExtInterrupt, external_interrupt)
115
116 /* Alignment exception. */
117 . = 0x600
118 Alignment:
119 EXCEPTION_PROLOG
120 mfspr r4,DAR
121 stw r4,_DAR(r21)
122 mfspr r5,DSISR
123 stw r5,_DSISR(r21)
124 addi r3,r1,STACK_FRAME_OVERHEAD
125 li r20,MSR_KERNEL
126 rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */
127 lwz r6,GOT(transfer_to_handler)
128 mtlr r6
129 blrl
130 .L_Alignment:
131 .long AlignmentException - _start + EXC_OFF_SYS_RESET
132 .long int_return - _start + EXC_OFF_SYS_RESET
133
134 /* Program check exception */
135 . = 0x700
136 ProgramCheck:
137 EXCEPTION_PROLOG
138 addi r3,r1,STACK_FRAME_OVERHEAD
139 li r20,MSR_KERNEL
140 rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */
141 lwz r6,GOT(transfer_to_handler)
142 mtlr r6
143 blrl
144 .L_ProgramCheck:
145 .long ProgramCheckException - _start + EXC_OFF_SYS_RESET
146 .long int_return - _start + EXC_OFF_SYS_RESET
147
148 STD_EXCEPTION(0x800, FPUnavailable, UnknownException)
149
150 /* I guess we could implement decrementer, and may have
151 * to someday for timekeeping.
152 */
153 STD_EXCEPTION(0x900, Decrementer, timer_interrupt)
154 STD_EXCEPTION(0xa00, Trap_0a, UnknownException)
155 STD_EXCEPTION(0xb00, Trap_0b, UnknownException)
156 STD_EXCEPTION(0xc00, SystemCall, UnknownException)
157 STD_EXCEPTION(0xd00, SingleStep, UnknownException)
158 STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
159 STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
160 STD_EXCEPTION(0x1000, SoftEmu, SoftEmuException)
161 STD_EXCEPTION(0x1100, InstructionTLBMiss, UnknownException)
162 STD_EXCEPTION(0x1200, DataTLBMiss, UnknownException)
163 STD_EXCEPTION(0x1300, InstructionTLBError, UnknownException)
164 STD_EXCEPTION(0x1400, DataTLBError, UnknownException)
165 STD_EXCEPTION(0x1500, Reserved5, UnknownException)
166 STD_EXCEPTION(0x1600, Reserved6, UnknownException)
167 STD_EXCEPTION(0x1700, Reserved7, UnknownException)
168 STD_EXCEPTION(0x1800, Reserved8, UnknownException)
169 STD_EXCEPTION(0x1900, Reserved9, UnknownException)
170 STD_EXCEPTION(0x1a00, ReservedA, UnknownException)
171 STD_EXCEPTION(0x1b00, ReservedB, UnknownException)
172 STD_EXCEPTION(0x1c00, DataBreakpoint, UnknownException)
173 STD_EXCEPTION(0x1d00, InstructionBreakpoint, UnknownException)
174 STD_EXCEPTION(0x1e00, PeripheralBreakpoint, UnknownException)
175 STD_EXCEPTION(0x1f00, DevPortBreakpoint, UnknownException)
176
177 .globl _end_of_vectors
178 _end_of_vectors:
179
180 . = 0x2000
181
182 boot_cold:
183 boot_warm:
184
185 /* if this is a multi-core system we need to check which cpu
186 * this is, if it is not cpu 0 send the cpu to the linux reset
187 * vector */
188 #if (CONFIG_NUM_CPUS > 1)
189 mfspr r0, MSSCR0
190 andi. r0, r0, 0x0020
191 rlwinm r0,r0,27,31,31
192 mtspr PIR, r0
193 beq 1f
194
195 bl secondary_cpu_setup
196 #endif
197
198 /* disable everything */
199 1: li r0, 0
200 mtspr HID0, r0
201 sync
202 mtmsr 0
203 bl invalidate_bats
204 sync
205
206 #ifdef CFG_L2
207 /* init the L2 cache */
208 addis r3, r0, L2_INIT@h
209 ori r3, r3, L2_INIT@l
210 mtspr l2cr, r3
211 /* invalidate the L2 cache */
212 bl l2cache_invalidate
213 sync
214 #endif
215
216 /*
217 * Calculate absolute address in FLASH and jump there
218 *------------------------------------------------------*/
219 lis r3, CFG_MONITOR_BASE@h
220 ori r3, r3, CFG_MONITOR_BASE@l
221 addi r3, r3, in_flash - _start + EXC_OFF_SYS_RESET
222 mtlr r3
223 blr
224
225 in_flash:
226 /* let the C-code set up the rest */
227 /* */
228 /* Be careful to keep code relocatable ! */
229 /*------------------------------------------------------*/
230 /* perform low-level init */
231
232 /* enable extended addressing */
233 bl enable_ext_addr
234
235 /* setup the bats */
236 bl setup_bats
237 sync
238
239 #if (CFG_CCSRBAR_DEFAULT != CFG_CCSRBAR)
240 /* setup ccsrbar */
241 bl setup_ccsrbar
242 #endif
243
244 /* Fix for SMP linux - Changing arbitration to round-robin */
245 lis r3, CFG_CCSRBAR@h
246 ori r3, r3, 0x1000
247 xor r4, r4, r4
248 li r4, 0x1000
249 stw r4, 0(r3)
250
251 /* setup the law entries */
252 bl law_entry
253 sync
254
255 /* Don't use this feature due to bug in 8641D PD4 */
256 /* Disable ERD_DIS */
257 lis r3, CFG_CCSRBAR@h
258 ori r3, r3, 0x1008
259 lwz r4, 0(r3)
260 oris r4, r4, 0x4000
261 stw r4, 0(r3)
262 sync
263
264 #if (EMULATOR_RUN == 1)
265 /* On the emulator we want to adjust these ASAP */
266 /* otherwise things are sloooow */
267 /* Setup OR0 (LALE FIX)*/
268 lis r3, CFG_CCSRBAR@h
269 ori r3, r3, 0x5004
270 li r4, 0x0FF3
271 stw r4, 0(r3)
272 sync
273
274 /* Setup LCRR */
275 lis r3, CFG_CCSRBAR@h
276 ori r3, r3, 0x50D4
277 lis r4, 0x8000
278 ori r4, r4, 0x0002
279 stw r4, 0(r3)
280 sync
281 #endif
282 #if 1
283 /* make sure timer enabled in guts register too */
284 lis r3, CFG_CCSRBAR@h
285 oris r3,r3, 0xE
286 ori r3,r3,0x0070
287 lwz r4, 0(r3)
288 lis r5,0xFFFC
289 ori r5,r5,0x5FFF
290 and r4,r4,r5
291 stw r4,0(r3)
292 #endif
293 /*
294 * Cache must be enabled here for stack-in-cache trick.
295 * This means we need to enable the BATS.
296 * Cache should be turned on after BATs, since by default
297 * everything is write-through.
298 */
299
300 /* enable address translation */
301 bl enable_addr_trans
302 sync
303
304 /* enable and invalidate the data cache */
305 /* bl l1dcache_enable */
306 bl dcache_enable
307 sync
308
309 #if 1
310 bl icache_enable
311 #endif
312
313 #ifdef CFG_INIT_RAM_LOCK
314 bl lock_ram_in_cache
315 sync
316 #endif
317
318 /* set up the stack pointer in our newly created
319 * cache-ram (r1) */
320 lis r1, (CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET)@h
321 ori r1, r1, (CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET)@l
322
323 li r0, 0 /* Make room for stack frame header and */
324 stwu r0, -4(r1) /* clear final stack frame so that */
325 stwu r0, -4(r1) /* stack backtraces terminate cleanly */
326
327 GET_GOT /* initialize GOT access */
328
329 /* run low-level CPU init code (from Flash) */
330 bl cpu_init_f
331 sync
332
333 #ifdef RUN_DIAG
334
335 /* Sri: Code to run the diagnostic automatically */
336
337 /* Load PX_AUX register address in r4 */
338 lis r4, 0xf810
339 ori r4, r4, 0x6
340 /* Load contents of PX_AUX in r3 bits 24 to 31*/
341 lbz r3, 0(r4)
342
343 /* Mask and obtain the bit in r3 */
344 rlwinm. r3, r3, 0, 24, 24
345 /* If not zero, jump and continue with u-boot */
346 bne diag_done
347
348 /* Load back contents of PX_AUX in r3 bits 24 to 31 */
349 lbz r3, 0(r4)
350 /* Set the MSB of the register value */
351 ori r3, r3, 0x80
352 /* Write value in r3 back to PX_AUX */
353 stb r3, 0(r4)
354
355 /* Get the address to jump to in r3*/
356 lis r3, CFG_DIAG_ADDR@h
357 ori r3, r3, CFG_DIAG_ADDR@l
358
359 /* Load the LR with the branch address */
360 mtlr r3
361
362 /* Branch to diagnostic */
363 blr
364
365 diag_done:
366 #endif
367
368 /* bl l2cache_enable */
369 mr r3, r21
370
371 /* r3: BOOTFLAG */
372 /* run 1st part of board init code (from Flash) */
373 bl board_init_f
374 sync
375
376 /* NOTREACHED */
377
378 .globl invalidate_bats
379 invalidate_bats:
380
381 /* invalidate BATs */
382 mtspr IBAT0U, r0
383 mtspr IBAT1U, r0
384 mtspr IBAT2U, r0
385 mtspr IBAT3U, r0
386 mtspr IBAT4U, r0
387 mtspr IBAT5U, r0
388 mtspr IBAT6U, r0
389 mtspr IBAT7U, r0
390
391 isync
392 mtspr DBAT0U, r0
393 mtspr DBAT1U, r0
394 mtspr DBAT2U, r0
395 mtspr DBAT3U, r0
396 mtspr DBAT4U, r0
397 mtspr DBAT5U, r0
398 mtspr DBAT6U, r0
399 mtspr DBAT7U, r0
400
401 isync
402 sync
403 blr
404
405
406 /* setup_bats - set them up to some initial state */
407 .globl setup_bats
408 setup_bats:
409
410 addis r0, r0, 0x0000
411
412 /* IBAT 0 */
413 addis r4, r0, CFG_IBAT0L@h
414 ori r4, r4, CFG_IBAT0L@l
415 addis r3, r0, CFG_IBAT0U@h
416 ori r3, r3, CFG_IBAT0U@l
417 mtspr IBAT0L, r4
418 mtspr IBAT0U, r3
419 isync
420
421 /* DBAT 0 */
422 addis r4, r0, CFG_DBAT0L@h
423 ori r4, r4, CFG_DBAT0L@l
424 addis r3, r0, CFG_DBAT0U@h
425 ori r3, r3, CFG_DBAT0U@l
426 mtspr DBAT0L, r4
427 mtspr DBAT0U, r3
428 isync
429
430 /* IBAT 1 */
431 addis r4, r0, CFG_IBAT1L@h
432 ori r4, r4, CFG_IBAT1L@l
433 addis r3, r0, CFG_IBAT1U@h
434 ori r3, r3, CFG_IBAT1U@l
435 mtspr IBAT1L, r4
436 mtspr IBAT1U, r3
437 isync
438
439 /* DBAT 1 */
440 addis r4, r0, CFG_DBAT1L@h
441 ori r4, r4, CFG_DBAT1L@l
442 addis r3, r0, CFG_DBAT1U@h
443 ori r3, r3, CFG_DBAT1U@l
444 mtspr DBAT1L, r4
445 mtspr DBAT1U, r3
446 isync
447
448 /* IBAT 2 */
449 addis r4, r0, CFG_IBAT2L@h
450 ori r4, r4, CFG_IBAT2L@l
451 addis r3, r0, CFG_IBAT2U@h
452 ori r3, r3, CFG_IBAT2U@l
453 mtspr IBAT2L, r4
454 mtspr IBAT2U, r3
455 isync
456
457 /* DBAT 2 */
458 addis r4, r0, CFG_DBAT2L@h
459 ori r4, r4, CFG_DBAT2L@l
460 addis r3, r0, CFG_DBAT2U@h
461 ori r3, r3, CFG_DBAT2U@l
462 mtspr DBAT2L, r4
463 mtspr DBAT2U, r3
464 isync
465
466 /* IBAT 3 */
467 addis r4, r0, CFG_IBAT3L@h
468 ori r4, r4, CFG_IBAT3L@l
469 addis r3, r0, CFG_IBAT3U@h
470 ori r3, r3, CFG_IBAT3U@l
471 mtspr IBAT3L, r4
472 mtspr IBAT3U, r3
473 isync
474
475 /* DBAT 3 */
476 addis r4, r0, CFG_DBAT3L@h
477 ori r4, r4, CFG_DBAT3L@l
478 addis r3, r0, CFG_DBAT3U@h
479 ori r3, r3, CFG_DBAT3U@l
480 mtspr DBAT3L, r4
481 mtspr DBAT3U, r3
482 isync
483
484 /* IBAT 4 */
485 addis r4, r0, CFG_IBAT4L@h
486 ori r4, r4, CFG_IBAT4L@l
487 addis r3, r0, CFG_IBAT4U@h
488 ori r3, r3, CFG_IBAT4U@l
489 mtspr IBAT4L, r4
490 mtspr IBAT4U, r3
491 isync
492
493 /* DBAT 4 */
494 addis r4, r0, CFG_DBAT4L@h
495 ori r4, r4, CFG_DBAT4L@l
496 addis r3, r0, CFG_DBAT4U@h
497 ori r3, r3, CFG_DBAT4U@l
498 mtspr DBAT4L, r4
499 mtspr DBAT4U, r3
500 isync
501
502 /* IBAT 5 */
503 addis r4, r0, CFG_IBAT5L@h
504 ori r4, r4, CFG_IBAT5L@l
505 addis r3, r0, CFG_IBAT5U@h
506 ori r3, r3, CFG_IBAT5U@l
507 mtspr IBAT5L, r4
508 mtspr IBAT5U, r3
509 isync
510
511 /* DBAT 5 */
512 addis r4, r0, CFG_DBAT5L@h
513 ori r4, r4, CFG_DBAT5L@l
514 addis r3, r0, CFG_DBAT5U@h
515 ori r3, r3, CFG_DBAT5U@l
516 mtspr DBAT5L, r4
517 mtspr DBAT5U, r3
518 isync
519
520 /* IBAT 6 */
521 addis r4, r0, CFG_IBAT6L@h
522 ori r4, r4, CFG_IBAT6L@l
523 addis r3, r0, CFG_IBAT6U@h
524 ori r3, r3, CFG_IBAT6U@l
525 mtspr IBAT6L, r4
526 mtspr IBAT6U, r3
527 isync
528
529 /* DBAT 6 */
530 addis r4, r0, CFG_DBAT6L@h
531 ori r4, r4, CFG_DBAT6L@l
532 addis r3, r0, CFG_DBAT6U@h
533 ori r3, r3, CFG_DBAT6U@l
534 mtspr DBAT6L, r4
535 mtspr DBAT6U, r3
536 isync
537
538 /* IBAT 7 */
539 addis r4, r0, CFG_IBAT7L@h
540 ori r4, r4, CFG_IBAT7L@l
541 addis r3, r0, CFG_IBAT7U@h
542 ori r3, r3, CFG_IBAT7U@l
543 mtspr IBAT7L, r4
544 mtspr IBAT7U, r3
545 isync
546
547 /* DBAT 7 */
548 addis r4, r0, CFG_DBAT7L@h
549 ori r4, r4, CFG_DBAT7L@l
550 addis r3, r0, CFG_DBAT7U@h
551 ori r3, r3, CFG_DBAT7U@l
552 mtspr DBAT7L, r4
553 mtspr DBAT7U, r3
554 isync
555
556 1:
557 addis r3, 0, 0x0000
558 addis r5, 0, 0x4 /* upper bound of 0x00040000 for 7400/750 */
559 isync
560
561 tlblp:
562 tlbie r3
563 sync
564 addi r3, r3, 0x1000
565 cmp 0, 0, r3, r5
566 blt tlblp
567
568 blr
569
570 .globl enable_addr_trans
571 enable_addr_trans:
572 /* enable address translation */
573 mfmsr r5
574 ori r5, r5, (MSR_IR | MSR_DR)
575 mtmsr r5
576 isync
577 blr
578
579 .globl disable_addr_trans
580 disable_addr_trans:
581 /* disable address translation */
582 mflr r4
583 mfmsr r3
584 andi. r0, r3, (MSR_IR | MSR_DR)
585 beqlr
586 andc r3, r3, r0
587 mtspr SRR0, r4
588 mtspr SRR1, r3
589 rfi
590
591 /*
592 * This code finishes saving the registers to the exception frame
593 * and jumps to the appropriate handler for the exception.
594 * Register r21 is pointer into trap frame, r1 has new stack pointer.
595 */
596 .globl transfer_to_handler
597 transfer_to_handler:
598 stw r22,_NIP(r21)
599 lis r22,MSR_POW@h
600 andc r23,r23,r22
601 stw r23,_MSR(r21)
602 SAVE_GPR(7, r21)
603 SAVE_4GPRS(8, r21)
604 SAVE_8GPRS(12, r21)
605 SAVE_8GPRS(24, r21)
606 mflr r23
607 andi. r24,r23,0x3f00 /* get vector offset */
608 stw r24,TRAP(r21)
609 li r22,0
610 stw r22,RESULT(r21)
611 mtspr SPRG2,r22 /* r1 is now kernel sp */
612 lwz r24,0(r23) /* virtual address of handler */
613 lwz r23,4(r23) /* where to go when done */
614 mtspr SRR0,r24
615 mtspr SRR1,r20
616 mtlr r23
617 SYNC
618 rfi /* jump to handler, enable MMU */
619
620 int_return:
621 mfmsr r28 /* Disable interrupts */
622 li r4,0
623 ori r4,r4,MSR_EE
624 andc r28,r28,r4
625 SYNC /* Some chip revs need this... */
626 mtmsr r28
627 SYNC
628 lwz r2,_CTR(r1)
629 lwz r0,_LINK(r1)
630 mtctr r2
631 mtlr r0
632 lwz r2,_XER(r1)
633 lwz r0,_CCR(r1)
634 mtspr XER,r2
635 mtcrf 0xFF,r0
636 REST_10GPRS(3, r1)
637 REST_10GPRS(13, r1)
638 REST_8GPRS(23, r1)
639 REST_GPR(31, r1)
640 lwz r2,_NIP(r1) /* Restore environment */
641 lwz r0,_MSR(r1)
642 mtspr SRR0,r2
643 mtspr SRR1,r0
644 lwz r0,GPR0(r1)
645 lwz r2,GPR2(r1)
646 lwz r1,GPR1(r1)
647 SYNC
648 rfi
649
650 .globl dc_read
651 dc_read:
652 blr
653
654 .globl get_pvr
655 get_pvr:
656 mfspr r3, PVR
657 blr
658
659 .globl get_svr
660 get_svr:
661 mfspr r3, SVR
662 blr
663
664
665 /*
666 * Function: in8
667 * Description: Input 8 bits
668 */
669 .globl in8
670 in8:
671 lbz r3,0x0000(r3)
672 blr
673
674 /*
675 * Function: out8
676 * Description: Output 8 bits
677 */
678 .globl out8
679 out8:
680 stb r4,0x0000(r3)
681 blr
682
683 /*
684 * Function: out16
685 * Description: Output 16 bits
686 */
687 .globl out16
688 out16:
689 sth r4,0x0000(r3)
690 blr
691
692 /*
693 * Function: out16r
694 * Description: Byte reverse and output 16 bits
695 */
696 .globl out16r
697 out16r:
698 sthbrx r4,r0,r3
699 blr
700
701 /*
702 * Function: out32
703 * Description: Output 32 bits
704 */
705 .globl out32
706 out32:
707 stw r4,0x0000(r3)
708 blr
709
710 /*
711 * Function: out32r
712 * Description: Byte reverse and output 32 bits
713 */
714 .globl out32r
715 out32r:
716 stwbrx r4,r0,r3
717 blr
718
719 /*
720 * Function: in16
721 * Description: Input 16 bits
722 */
723 .globl in16
724 in16:
725 lhz r3,0x0000(r3)
726 blr
727
728 /*
729 * Function: in16r
730 * Description: Input 16 bits and byte reverse
731 */
732 .globl in16r
733 in16r:
734 lhbrx r3,r0,r3
735 blr
736
737 /*
738 * Function: in32
739 * Description: Input 32 bits
740 */
741 .globl in32
742 in32:
743 lwz 3,0x0000(3)
744 blr
745
746 /*
747 * Function: in32r
748 * Description: Input 32 bits and byte reverse
749 */
750 .globl in32r
751 in32r:
752 lwbrx r3,r0,r3
753 blr
754
755 /*
756 * Function: ppcDcbf
757 * Description: Data Cache block flush
758 * Input: r3 = effective address
759 * Output: none.
760 */
761 .globl ppcDcbf
762 ppcDcbf:
763 dcbf r0,r3
764 blr
765
766 /*
767 * Function: ppcDcbi
768 * Description: Data Cache block Invalidate
769 * Input: r3 = effective address
770 * Output: none.
771 */
772 .globl ppcDcbi
773 ppcDcbi:
774 dcbi r0,r3
775 blr
776
777 /*
778 * Function: ppcDcbz
779 * Description: Data Cache block zero.
780 * Input: r3 = effective address
781 * Output: none.
782 */
783 .globl ppcDcbz
784 ppcDcbz:
785 dcbz r0,r3
786 blr
787
788 /*
789 * Function: ppcSync
790 * Description: Processor Synchronize
791 * Input: none.
792 * Output: none.
793 */
794 .globl ppcSync
795 ppcSync:
796 sync
797 blr
798
799 /*
800 * void relocate_code (addr_sp, gd, addr_moni)
801 *
802 * This "function" does not return, instead it continues in RAM
803 * after relocating the monitor code.
804 *
805 * r3 = dest
806 * r4 = src
807 * r5 = length in bytes
808 * r6 = cachelinesize
809 */
810 .globl relocate_code
811 relocate_code:
812
813 mr r1, r3 /* Set new stack pointer */
814 mr r9, r4 /* Save copy of Global Data pointer */
815 mr r29, r9 /* Save for DECLARE_GLOBAL_DATA_PTR */
816 mr r10, r5 /* Save copy of Destination Address */
817
818 mr r3, r5 /* Destination Address */
819 lis r4, CFG_MONITOR_BASE@h /* Source Address */
820 ori r4, r4, CFG_MONITOR_BASE@l
821 lwz r5, GOT(__init_end)
822 sub r5, r5, r4
823 li r6, CFG_CACHELINE_SIZE /* Cache Line Size */
824
825 /*
826 * Fix GOT pointer:
827 *
828 * New GOT-PTR = (old GOT-PTR - CFG_MONITOR_BASE) + Destination Address
829 *
830 * Offset:
831 */
832 sub r15, r10, r4
833
834 /* First our own GOT */
835 add r14, r14, r15
836 /* then the one used by the C code */
837 add r30, r30, r15
838
839 /*
840 * Now relocate code
841 */
842 #ifdef CONFIG_ECC
843 bl board_relocate_rom
844 sync
845 mr r3, r10 /* Destination Address */
846 lis r4, CFG_MONITOR_BASE@h /* Source Address */
847 ori r4, r4, CFG_MONITOR_BASE@l
848 lwz r5, GOT(__init_end)
849 sub r5, r5, r4
850 li r6, CFG_CACHELINE_SIZE /* Cache Line Size */
851 #else
852 cmplw cr1,r3,r4
853 addi r0,r5,3
854 srwi. r0,r0,2
855 beq cr1,4f /* In place copy is not necessary */
856 beq 7f /* Protect against 0 count */
857 mtctr r0
858 bge cr1,2f
859
860 la r8,-4(r4)
861 la r7,-4(r3)
862 1: lwzu r0,4(r8)
863 stwu r0,4(r7)
864 bdnz 1b
865 b 4f
866
867 2: slwi r0,r0,2
868 add r8,r4,r0
869 add r7,r3,r0
870 3: lwzu r0,-4(r8)
871 stwu r0,-4(r7)
872 bdnz 3b
873 #endif
874 /*
875 * Now flush the cache: note that we must start from a cache aligned
876 * address. Otherwise we might miss one cache line.
877 */
878 4: cmpwi r6,0
879 add r5,r3,r5
880 beq 7f /* Always flush prefetch queue in any case */
881 subi r0,r6,1
882 andc r3,r3,r0
883 mr r4,r3
884 5: dcbst 0,r4
885 add r4,r4,r6
886 cmplw r4,r5
887 blt 5b
888 sync /* Wait for all dcbst to complete on bus */
889 mr r4,r3
890 6: icbi 0,r4
891 add r4,r4,r6
892 cmplw r4,r5
893 blt 6b
894 7: sync /* Wait for all icbi to complete on bus */
895 isync
896
897 /*
898 * We are done. Do not return, instead branch to second part of board
899 * initialization, now running from RAM.
900 */
901 addi r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
902 mtlr r0
903 blr
904
905 in_ram:
906 #ifdef CONFIG_ECC
907 bl board_init_ecc
908 #endif
909 /*
910 * Relocation Function, r14 point to got2+0x8000
911 *
912 * Adjust got2 pointers, no need to check for 0, this code
913 * already puts a few entries in the table.
914 */
915 li r0,__got2_entries@sectoff@l
916 la r3,GOT(_GOT2_TABLE_)
917 lwz r11,GOT(_GOT2_TABLE_)
918 mtctr r0
919 sub r11,r3,r11
920 addi r3,r3,-4
921 1: lwzu r0,4(r3)
922 add r0,r0,r11
923 stw r0,0(r3)
924 bdnz 1b
925
926 /*
927 * Now adjust the fixups and the pointers to the fixups
928 * in case we need to move ourselves again.
929 */
930 2: li r0,__fixup_entries@sectoff@l
931 lwz r3,GOT(_FIXUP_TABLE_)
932 cmpwi r0,0
933 mtctr r0
934 addi r3,r3,-4
935 beq 4f
936 3: lwzu r4,4(r3)
937 lwzux r0,r4,r11
938 add r0,r0,r11
939 stw r10,0(r3)
940 stw r0,0(r4)
941 bdnz 3b
942 4:
943 /* clear_bss: */
944 /*
945 * Now clear BSS segment
946 */
947 lwz r3,GOT(__bss_start)
948 lwz r4,GOT(_end)
949
950 cmplw 0, r3, r4
951 beq 6f
952
953 li r0, 0
954 5:
955 stw r0, 0(r3)
956 addi r3, r3, 4
957 cmplw 0, r3, r4
958 bne 5b
959 6:
960 mr r3, r9 /* Init Date pointer */
961 mr r4, r10 /* Destination Address */
962 bl board_init_r
963
964 /* not reached - end relocate_code */
965 /*-----------------------------------------------------------------------*/
966
967 /*
968 * Copy exception vector code to low memory
969 *
970 * r3: dest_addr
971 * r7: source address, r8: end address, r9: target address
972 */
973 .globl trap_init
974 trap_init:
975 lwz r7, GOT(_start)
976 lwz r8, GOT(_end_of_vectors)
977
978 li r9, 0x100 /* reset vector always at 0x100 */
979
980 cmplw 0, r7, r8
981 bgelr /* return if r7>=r8 - just in case */
982
983 mflr r4 /* save link register */
984 1:
985 lwz r0, 0(r7)
986 stw r0, 0(r9)
987 addi r7, r7, 4
988 addi r9, r9, 4
989 cmplw 0, r7, r8
990 bne 1b
991
992 /*
993 * relocate `hdlr' and `int_return' entries
994 */
995 li r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
996 li r8, Alignment - _start + EXC_OFF_SYS_RESET
997 2:
998 bl trap_reloc
999 addi r7, r7, 0x100 /* next exception vector */
1000 cmplw 0, r7, r8
1001 blt 2b
1002
1003 li r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
1004 bl trap_reloc
1005
1006 li r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
1007 bl trap_reloc
1008
1009 li r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
1010 li r8, SystemCall - _start + EXC_OFF_SYS_RESET
1011 3:
1012 bl trap_reloc
1013 addi r7, r7, 0x100 /* next exception vector */
1014 cmplw 0, r7, r8
1015 blt 3b
1016
1017 li r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
1018 li r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
1019 4:
1020 bl trap_reloc
1021 addi r7, r7, 0x100 /* next exception vector */
1022 cmplw 0, r7, r8
1023 blt 4b
1024
1025 /* enable execptions from RAM vectors */
1026 mfmsr r7
1027 li r8,MSR_IP
1028 andc r7,r7,r8
1029 mtmsr r7
1030
1031 mtlr r4 /* restore link register */
1032 blr
1033
1034 /*
1035 * Function: relocate entries for one exception vector
1036 */
1037 trap_reloc:
1038 lwz r0, 0(r7) /* hdlr ... */
1039 add r0, r0, r3 /* ... += dest_addr */
1040 stw r0, 0(r7)
1041
1042 lwz r0, 4(r7) /* int_return ... */
1043 add r0, r0, r3 /* ... += dest_addr */
1044 stw r0, 4(r7)
1045
1046 sync
1047 isync
1048
1049 blr
1050
1051 .globl enable_ext_addr
1052 enable_ext_addr:
1053 mfspr r0, HID0
1054 lis r0, (HID0_HIGH_BAT_EN | HID0_XBSEN | HID0_XAEN)@h
1055 ori r0, r0, (HID0_HIGH_BAT_EN | HID0_XBSEN | HID0_XAEN)@l
1056 mtspr HID0, r0
1057 sync
1058 isync
1059 blr
1060
1061 #if (CFG_CCSRBAR_DEFAULT != CFG_CCSRBAR)
1062 .globl setup_ccsrbar
1063 setup_ccsrbar:
1064 /* Special sequence needed to update CCSRBAR itself */
1065 lis r4, CFG_CCSRBAR_DEFAULT@h
1066 ori r4, r4, CFG_CCSRBAR_DEFAULT@l
1067
1068 lis r5, CFG_CCSRBAR@h
1069 ori r5, r5, CFG_CCSRBAR@l
1070 srwi r6,r5,12
1071 stw r6, 0(r4)
1072 isync
1073
1074 lis r5, 0xffff
1075 ori r5,r5,0xf000
1076 lwz r5, 0(r5)
1077 isync
1078
1079 lis r3, CFG_CCSRBAR@h
1080 lwz r5, CFG_CCSRBAR@l(r3)
1081 isync
1082
1083 blr
1084 #endif
1085
1086 #ifdef CFG_INIT_RAM_LOCK
1087 lock_ram_in_cache:
1088 /* Allocate Initial RAM in data cache.
1089 */
1090 lis r3, (CFG_INIT_RAM_ADDR & ~31)@h
1091 ori r3, r3, (CFG_INIT_RAM_ADDR & ~31)@l
1092 li r2, ((CFG_INIT_RAM_END & ~31) + \
1093 (CFG_INIT_RAM_ADDR & 31) + 31) / 32
1094 mtctr r2
1095 1:
1096 dcbz r0, r3
1097 addi r3, r3, 32
1098 bdnz 1b
1099 #if 1
1100 /* Lock the data cache */
1101 mfspr r0, HID0
1102 ori r0, r0, 0x1000
1103 sync
1104 mtspr HID0, r0
1105 sync
1106 blr
1107 #endif
1108 #if 0
1109 /* Lock the first way of the data cache */
1110 mfspr r0, LDSTCR
1111 ori r0, r0, 0x0080
1112 #if defined(CONFIG_ALTIVEC)
1113 dssall
1114 #endif
1115 sync
1116 mtspr LDSTCR, r0
1117 sync
1118 isync
1119 blr
1120 #endif
1121
1122 .globl unlock_ram_in_cache
1123 unlock_ram_in_cache:
1124 /* invalidate the INIT_RAM section */
1125 lis r3, (CFG_INIT_RAM_ADDR & ~31)@h
1126 ori r3, r3, (CFG_INIT_RAM_ADDR & ~31)@l
1127 li r2, ((CFG_INIT_RAM_END & ~31) + \
1128 (CFG_INIT_RAM_ADDR & 31) + 31) / 32
1129 mtctr r2
1130 1: icbi r0, r3
1131 addi r3, r3, 32
1132 bdnz 1b
1133 sync /* Wait for all icbi to complete on bus */
1134 isync
1135 #if 1
1136 /* Unlock the data cache and invalidate it */
1137 mfspr r0, HID0
1138 li r3,0x1000
1139 andc r0,r0,r3
1140 li r3,0x0400
1141 or r0,r0,r3
1142 sync
1143 mtspr HID0, r0
1144 sync
1145 blr
1146 #endif
1147 #if 0
1148 /* Unlock the first way of the data cache */
1149 mfspr r0, LDSTCR
1150 li r3,0x0080
1151 andc r0,r0,r3
1152 #ifdef CONFIG_ALTIVEC
1153 dssall
1154 #endif
1155 sync
1156 mtspr LDSTCR, r0
1157 sync
1158 isync
1159 li r3,0x0400
1160 or r0,r0,r3
1161 sync
1162 mtspr HID0, r0
1163 sync
1164 blr
1165 #endif
1166 #endif
1167
1168 /* If this is a multi-cpu system then we need to handle the
1169 * 2nd cpu. The assumption is that the 2nd cpu is being
1170 * held in boot holdoff mode until the 1st cpu unlocks it
1171 * from Linux. We'll do some basic cpu init and then pass
1172 * it to the Linux Reset Vector.
1173 * Sri: Much of this initialization is not required. Linux
1174 * rewrites the bats, and the sprs and also enables the L1 cache.
1175 */
1176 #if (CONFIG_NUM_CPUS > 1)
1177 .globl secondary_cpu_setup
1178 secondary_cpu_setup:
1179 /* Do only core setup on all cores except cpu0 */
1180 bl invalidate_bats
1181 sync
1182 bl enable_ext_addr
1183
1184 #ifdef CFG_L2
1185 /* init the L2 cache */
1186 addis r3, r0, L2_INIT@h
1187 ori r3, r3, L2_INIT@l
1188 sync
1189 mtspr l2cr, r3
1190 #ifdef CONFIG_ALTIVEC
1191 dssall
1192 #endif
1193 /* invalidate the L2 cache */
1194 bl l2cache_invalidate
1195 sync
1196 #endif
1197
1198 /* enable and invalidate the data cache */
1199 bl dcache_enable
1200 sync
1201
1202 /* enable and invalidate the instruction cache*/
1203 bl icache_enable
1204 sync
1205
1206 /* TBEN in HID0 */
1207 mfspr r4, HID0
1208 oris r4, r4, 0x0400
1209 mtspr HID0, r4
1210 sync
1211 isync
1212
1213 /*SYNCBE|ABE in HID1*/
1214 mfspr r4, HID1
1215 ori r4, r4, 0x0C00
1216 mtspr HID1, r4
1217 sync
1218 isync
1219
1220 lis r3, CONFIG_LINUX_RESET_VEC@h
1221 ori r3, r3, CONFIG_LINUX_RESET_VEC@l
1222 mtlr r3
1223 blr
1224
1225 /* Never Returns, Running in Linux Now */
1226 #endif